/* * CDE - Common Desktop Environment * * Copyright (c) 1993-2012, The Open Group. All rights reserved. * * These libraries and programs are free software; you can * redistribute them and/or modify them under the terms of the GNU * Lesser General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * These libraries and programs are distributed in the hope that * they will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public * License along with these libraries and programs; if not, write * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth * Floor, Boston, MA 02110-1301 USA */ /* * $XConsortium: abobj_select.c /main/3 1995/11/06 17:17:19 rswiston $ * * @(#)abobj_select.c 1.37 15 Feb 1994 cde_app_builder/src/ab * * RESTRICTED CONFIDENTIAL INFORMATION: * * The information in this document is subject to special * restrictions in a confidential disclosure agreement between * HP, IBM, Sun, USL, SCO and Univel. Do not distribute this * document outside HP, IBM, Sun, USL, SCO, or Univel without * Sun's specific written approval. This document and all copies * and derivative works thereof must be returned or destroyed at * Sun's request. * * Copyright 1993 Sun Microsystems, Inc. All rights reserved. * */ /* *********************************************************************** * ab_select.c - Implements "select" behavior of a UI object * * *********************************************************************** */ #include #include #include #include #include #include #include #include #include #include #include #include #include "abobjP.h" const int AB_selected_rect_size = 7; /************************************************************************* ** ** ** Private Function Declarations ** ** ** **************************************************************************/ static void select_feedback( ABObj selObj, BOOL on ); static void select_footer( ABObj obj, BOOL on ); static void turnon_select_feedback( ABObj selObj, BOOL resizable ); static void turnoff_select_feedback( ABObj selObj, BOOL resizable ); static void draw_select_feedback( ABObj selObj, BOOL resizable ); /* * Event Handlers */ static void monitor_cursor( Widget w, XtPointer clientdata, XEvent *event, Boolean *cont_dispatch ); static void select_feedback_redraw( Widget w, XtPointer clientdata, XEvent *event, Boolean *cont_dispatch ); /************************************************************************* ** ** ** Private Data ** ** ** **************************************************************************/ static GC AB_grab_handle_gc; static XRectangle rb_rect; static Widget rb_widget; static BOOL first_time = TRUE; /************************************************************************* ** ** ** Function Definitions ** ** ** **************************************************************************/ /* * cause the object to appear "selected" */ void abobj_select( ABObj obj ) { AB_CONTAINER_TYPE cont_type; ABObj rootObj = obj_get_root(obj); ABObj selObj; /* Make sure the window is on screen */ if (obj_is_window(rootObj)) ui_win_front(objxm_get_widget(rootObj)); proj_set_cur_module(obj_get_module(obj)); if (obj_is_selected(rootObj)) return; obj_set_is_selected(rootObj, TRUE); if (obj_is_module(rootObj)) return; if (obj_is_item(obj)) { rootObj = obj_get_root(obj_get_parent(obj)); obj_set_is_selected(rootObj, TRUE); } selObj = objxm_comp_get_subobj(rootObj, AB_CFG_SELECT_OBJ); if (selObj == NULL) { if (util_get_verbosity() > 0) fprintf(stderr, "abobj_select: %s :no selection object\n", obj_get_name(rootObj)); return; } if (obj_is_window(rootObj)) select_footer(selObj, True); else turnon_select_feedback(selObj, abobj_is_directly_resizable(rootObj)); } /* * remove "select" feedback from object */ void abobj_deselect( ABObj obj ) { AB_CONTAINER_TYPE cont_type; ABObj rootObj = obj_get_root(obj); ABObj selObj; if (!obj_is_selected(rootObj)) return; obj_set_is_selected(rootObj, FALSE); if (obj_is_module(obj)) return; if (obj_is_item(obj)) { rootObj = obj_get_root(obj_get_parent(obj)); obj_set_is_selected(rootObj, FALSE); } selObj = objxm_comp_get_subobj(rootObj, AB_CFG_SELECT_OBJ); if (selObj == NULL) { if (util_get_verbosity() > 0) fprintf(stderr, "abobj_deselect: %s :no selection object\n", obj_get_name(rootObj)); return; } if (obj_is_window(rootObj)) select_footer(selObj, False); else turnoff_select_feedback(selObj, abobj_is_directly_resizable(rootObj)); } void abobj_deselect_all( ABObj root ) { ABObj obj = root; AB_TRAVERSAL trav; if (obj == NULL) return; for (trav_open(&trav, obj, AB_TRAV_UI); (obj = trav_next(&trav)) != NULL; ) { if (obj_is_selected(obj)) abobj_deselect(obj); } trav_close(&trav); /* * The browser displays the module as well, * so we must deselect it when abobj_deselect_all() is * called */ if (obj_is_project(root)) { for (trav_open(&trav, root, AB_TRAV_MODULES); (obj = trav_next(&trav)) != NULL; ) { if (obj_is_selected(obj)) abobj_deselect(obj); } trav_close(&trav); } else { ABObj module = obj_get_module(root); if (obj_is_selected(module)) abobj_deselect(module); } } /* * abobj_get_selected- Return an array containing ptrs to * all selected ABObjs in a given */ int abobj_get_selected( ABObj root, BOOL include_root, BOOL include_items, ABSelectedRec *sel ) { ABObj obj = root; AB_TRAVERSAL trav; sel->count = 0; sel->list = NULL; if (obj == NULL) return -1; /* First count up all selected objs */ for (trav_open(&trav, obj, AB_TRAV_SALIENT_UI); (obj = trav_next(&trav)) != NULL; ) { if (obj_is_selected(obj) && !(obj_is_item(obj) && !include_items) && !(obj == root && !include_root)) (sel->count)++; } trav_close(&trav); /* Now alloc & fill array with selected objs */ obj = root; if (sel->count > 0) { int i = 0; sel->list = (ABObj*)XtMalloc(sel->count * sizeof(ABObj)); for (trav_open(&trav, obj, AB_TRAV_SALIENT_UI); (obj = trav_next(&trav)) != NULL; ) { if (obj_is_selected(obj) && !(obj_is_item(obj) && !include_items) && !(obj == root && !include_root)) sel->list[i++] = obj; } } return 0; } /* * Sort list of selected objects */ void abobj_sort_sel_list( ABObj *sel_list, int sel_count, int sort ) { int i, j; int x1, y1, x2, y2; ABObj tmp_obj; /* * Sort the list of objects based on x and y values */ for (i = 0; i < sel_count; i++) { for (j = i; j < sel_count; j++) { x1 = obj_get_x(sel_list[i]); y1 = obj_get_y(sel_list[i]); x2 = obj_get_x(sel_list[j]); y2 = obj_get_y(sel_list[j]); if (sort == XSORT) { if (x2 < x1 || (x2 == x1 && y2 < y1)) { tmp_obj = sel_list[i]; sel_list[i] = sel_list[j]; sel_list[j] = tmp_obj; } } else { if (y2 < y1 || (y2 == y1 && x2 < x1)) { tmp_obj = sel_list[i]; sel_list[i] = sel_list[j]; sel_list[j] = tmp_obj; } } } } } /* * render select feedback for objects which do not have grab handles */ static void select_feedback( ABObj selObj, BOOL on ) { Widget selWidget; Pixel contrast; selWidget = (Widget)selObj->ui_handle; if (selWidget == NULL) { if (util_get_verbosity() > 0) fprintf(stderr, "select_feedback: %s :no selection widget\n", obj_get_name(selObj)); return; } if (on) { contrast = x_contrast_color(selWidget); XtVaSetValues(selWidget, XmNborderWidth, (XtArgVal)2, XmNborderColor, contrast, NULL); } else XtVaSetValues(selWidget, XmNborderWidth, (XtArgVal)0, NULL); } static void select_footer( ABObj selObj, BOOL on ) { Widget selWidget; Pixel contrast; XmString xmstr; if (!(selWidget = (Widget)selObj->ui_handle)) return; if (on) { contrast = x_contrast_color(selWidget); xmstr = XmStringCreateLocalized("Window SELECTED "); XtVaSetValues(selWidget, XmNlabelString, xmstr, XmNforeground, contrast, NULL); XmStringFree(xmstr); } else /* off */ { xmstr = XmStringCreateLocalized(" "); XtVaSetValues(selWidget, XmNlabelString, xmstr, NULL); XmStringFree(xmstr); } } /* * set event handlers to draw the grab handles on * the object's selection widget */ static void turnon_select_feedback( ABObj selObj, BOOL resizable ) { Widget selWidget; selWidget = (Widget)selObj->ui_handle; if (selWidget == NULL) return; draw_select_feedback(selObj, resizable); XtAddEventHandler(selWidget, StructureNotifyMask | ExposureMask, FALSE, select_feedback_redraw, (XtPointer)(uintptr_t) resizable); XtAddEventHandler(selWidget, PointerMotionMask, FALSE, monitor_cursor, (XtPointer)selObj); } /* * remove the expose event handlers and clear the * grab handles off the widget */ static void turnoff_select_feedback( ABObj selObj, BOOL resizable ) { XRectangle w_rect; Widget selWidget; selWidget = (Widget)selObj->ui_handle; if (selWidget == NULL) return; x_get_widget_rect(selWidget, &w_rect); XtRemoveEventHandler(selWidget, StructureNotifyMask | ExposureMask, FALSE, select_feedback_redraw, (XtPointer)(uintptr_t) resizable); XtRemoveEventHandler(selWidget, PointerMotionMask, FALSE, monitor_cursor, (XtPointer)selObj); /* Make sure cursor is reset to normal */ monitor_cursor(selWidget, selObj, NULL, NULL); ui_refresh_widget_tree(selWidget); } /* * Draw the grabhandles on the selection-widget for the object */ static void draw_select_feedback( ABObj selObj, BOOL resizable ) { ABObj obj; Widget selWidget; Dimension width = 0; Dimension height = 0; int x0,y0,x1,y1; int border_w; Display *display; Drawable drawable; XGCValues gc_val; unsigned long bg, color_contrast; int grabbox_size; obj = obj_get_root(selObj); selWidget = (Widget)selObj->ui_handle; if ( (obj_is_drawing_area(obj) || obj_is_text_pane(obj)) && (obj_has_hscrollbar(obj) || obj_has_vscrollbar(obj)) ) { ABObj swobj = objxm_comp_get_subobj(obj, AB_CFG_SIZE_OBJ); Widget cwidget; XtVaGetValues((Widget)swobj->ui_handle, XmNclipWindow, &cwidget, NULL); if (cwidget) { XtVaGetValues(cwidget, XtNwidth, &width, XtNheight, &height, NULL); XtVaGetValues(selWidget, XtNbackground, &bg, NULL); } } if (height == 0 || width == 0) XtVaGetValues(selWidget, XtNwidth, &width, XtNheight, &height, XtNbackground,&bg, NULL); /* if (obj_is_control(obj)) grabbox_size = (AB_selected_rect_size / 2) + 1; else */ grabbox_size = AB_selected_rect_size; if (obj_is_control(obj)) border_w = 1; else border_w = 2; x0 = y0 = border_w - 1; x1 = width - grabbox_size; y1 = height - grabbox_size; color_contrast = x_contrast_color(selWidget); display = (Display *) XtDisplay(selWidget); drawable = (Drawable) XtWindow(selWidget); if (!AB_grab_handle_gc) { gc_val.foreground = color_contrast; gc_val.line_width = border_w; gc_val.function = GXcopy; gc_val.subwindow_mode = IncludeInferiors; AB_grab_handle_gc = XCreateGC(display, drawable, (GCFunction | GCForeground | GCLineWidth | GCSubwindowMode), &gc_val); } else { XSetForeground(display, AB_grab_handle_gc, color_contrast); XSetLineAttributes(display, AB_grab_handle_gc, border_w, LineSolid, CapButt, JoinMiter); } /* Draw Select Rectangle */ XDrawRectangle(display, drawable, AB_grab_handle_gc, x0, y0, width-border_w, height-border_w); /* If Obj is Resizable, Draw Resize handles */ if (resizable) { /* North-West */ XFillRectangle(display, drawable, AB_grab_handle_gc, x0, y0, grabbox_size, grabbox_size); /* South-West */ XFillRectangle(display, drawable, AB_grab_handle_gc, x0, y1, grabbox_size, grabbox_size); /* North-East */ XFillRectangle(display, drawable, AB_grab_handle_gc, x1, y0, grabbox_size, grabbox_size); /* South-East */ XFillRectangle(display, drawable, AB_grab_handle_gc, x1, y1, grabbox_size, grabbox_size); /* North */ XFillRectangle(display, drawable, AB_grab_handle_gc, (x0+x1)/2, y0, grabbox_size, grabbox_size); /* South */ XFillRectangle(display, drawable, AB_grab_handle_gc, (x0+x1)/2, y1, grabbox_size, grabbox_size); /* West */ XFillRectangle(display, drawable, AB_grab_handle_gc, x0, (y0+y1)/2, grabbox_size, grabbox_size); /* East */ XFillRectangle(display, drawable, AB_grab_handle_gc, x1, (y0+y1)/2, grabbox_size, grabbox_size); } XFlush(display); } /* * EventHandler: detect when cursor moves over grab handles */ static void monitor_cursor( Widget selWidget, XtPointer clientdata, XEvent *event, Boolean *cont_dispatch ) { ABObj selObj = (ABObj)clientdata; XMotionEvent *mevent; Cursor resize_cursor; RESIZE_DIR dir; static Boolean cursor_changed = FALSE; Window win; Display *dpy; if (event != NULL) { if (event->type != MotionNotify) return; else mevent = (XMotionEvent*)event; dir = abobjP_find_resize_direction(selObj, selWidget, event); } else dir = NONE; dpy = XtDisplay(selWidget); win = XtWindow(selWidget); if (dir == NONE) { if (cursor_changed) { XUndefineCursor(dpy, win); cursor_changed = FALSE; } } else { if ((resize_cursor = abobjP_get_resize_cursor(selWidget, dir)) != 0) { XDefineCursor(dpy, win, resize_cursor); cursor_changed = TRUE; } } } /* * EventHandler: render grab handles on widget for Expose events */ static void select_feedback_redraw( Widget selWidget, XtPointer clientdata, XEvent *event, Boolean *cont_dispatch ) { ABObj selObj = NULL; BOOL resizable = (BOOL)((uintptr_t) clientdata); Boolean redraw = FALSE; selObj = objxm_get_obj_from_widget(selWidget); if (event->type == ConfigureNotify) { XRectangle w_rect; x_get_widget_rect(selWidget, &w_rect); /* ClearArea is roundtrip, should use XOR..*/ ui_refresh_widget_tree(selWidget); redraw = TRUE; } else if (event->type == Expose) redraw = TRUE; if (redraw) draw_select_feedback(selObj, resizable); }