/* * Motif * * Copyright (c) 1987-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 librararies and programs; if not, write * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth * Floor, Boston, MA 02110-1301 USA * */ /************************************************************ * INCLUDE FILES *************************************************************/ #include #include "XmI.h" #include #include /************************************************************ * TYPEDEFS AND DEFINES *************************************************************/ #define SUPERCLASS ((WidgetClass) &xmManagerClassRec) /************************************************************ * MACROS *************************************************************/ #define GetIconInfo(w) ((IconInfo*) \ &(((XmIconBoxConstraintsRec*)((char*)((w)->core.constraints)))->icon)) /************************************************************ * GLOBAL DECLARATIONS *************************************************************/ /************************************************************ * STATIC FUNCTION DECLARATIONS *************************************************************/ static void ClassInitialize(); static void ClassPartInitialize(WidgetClass w_class); static void Realize(Widget, Mask *, XSetWindowAttributes *); static void Resize(Widget), ChangeManaged(Widget), InsertChild(Widget); static void Initialize(Widget, Widget, ArgList, Cardinal *); static void ConstraintInitialize(Widget, Widget, ArgList, Cardinal *); static Boolean ConstraintSetValues(Widget, Widget, Widget, ArgList, Cardinal*); static Boolean SetValues(Widget, Widget, Widget, ArgList, Cardinal *); static XtGeometryResult GeometryManager(Widget, XtWidgetGeometry *, XtWidgetGeometry *); static XtGeometryResult QueryGeometry(Widget, XtWidgetGeometry *, XtWidgetGeometry *); /************************ * Actions and callbacks. ************************/ /********************* * Internal Routines. *********************/ static void FindNearestCellLocation(Widget, Position *, Position *); static void GetMinCells(Widget, Cardinal *, Cardinal *); static void PlaceChildren(Widget, Widget); static void GetMaxCellSize(Widget, Widget, Dimension *, Dimension *); static void GetCellFromXY(Widget, Position, Position, Position *, Position *); static void GetXYFromCell(Widget, IconInfo *, Position *, Position *); static void CalcCellSizes(Widget, Widget, Boolean, Boolean, Dimension *, Dimension *); static Boolean SetToEmptyCell(Widget); /************************************************************ * STATIC DECLARATIONS *************************************************************/ static XtResource resources[] = { { XmNminimumVerticalCells, XmCDefaultCells, XmRDimension, sizeof(Dimension), XtOffsetOf(XmIconBoxRec, box.min_v_cells), XmRImmediate, (XtPointer) 2 }, { XmNminimumHorizontalCells, XmCDefaultCells, XmRHorizontalDimension, sizeof(Dimension), XtOffsetOf(XmIconBoxRec, box.min_h_cells), XmRImmediate, (XtPointer) 2 }, { XmNminimumCellWidth, XmCMinimumCellSize, XmRHorizontalDimension, sizeof(Dimension), XtOffsetOf(XmIconBoxRec, box.min_cell_width), XmRImmediate, (XtPointer) 20 }, { XmNminimumCellHeight, XmCMinimumCellSize, XmRDimension, sizeof(Dimension), XtOffsetOf(XmIconBoxRec, box.min_cell_height), XmRImmediate, (XtPointer) 10 }, { XmNverticalMargin, XmCMargin, XmRVerticalDimension, sizeof(Dimension), XtOffsetOf(XmIconBoxRec, box.v_margin), XmRImmediate, (XtPointer) 4 }, { XmNhorizontalMargin, XmCMargin, XmRHorizontalDimension, sizeof(Dimension), XtOffsetOf(XmIconBoxRec, box.h_margin), XmRImmediate, (XtPointer) 4 } }; static XmSyntheticResource get_resources[] = { { XmNhorizontalMargin, sizeof(Dimension), XtOffsetOf(XmIconBoxRec, box.h_margin), XmeFromHorizontalPixels, (XmImportProc) XmeToHorizontalPixels }, { XmNverticalMargin, sizeof(Dimension), XtOffsetOf(XmIconBoxRec, box.v_margin), XmeFromVerticalPixels, (XmImportProc) XmeToVerticalPixels }, { XmNminimumCellWidth, sizeof(Dimension), XtOffsetOf(XmIconBoxRec, box.min_cell_width), XmeFromHorizontalPixels, (XmImportProc) XmeToHorizontalPixels }, { XmNminimumCellHeight, sizeof(Dimension), XtOffsetOf(XmIconBoxRec, box.min_cell_height), XmeFromVerticalPixels, (XmImportProc) XmeToVerticalPixels } }; static short G_any_cell = XmIconBoxAnyCell; static XtResource constraints[] = { { XmNcellX, XmCCellX, XmRShort, sizeof(short), XtOffsetOf(XmIconBoxConstraintsRec, icon.cell_x), XmRShort, (XtPointer) &G_any_cell }, { XmNcellY, XmCCellY, XmRShort, sizeof(short), XtOffsetOf(XmIconBoxConstraintsRec, icon.cell_y), XmRShort, (XtPointer) &G_any_cell } }; XmIconBoxClassRec xmIconBoxClassRec = { { /* core fields */ /* superclass */ SUPERCLASS, /* class_name */ "XmIconBox", /* widget_size */ sizeof(XmIconBoxRec), /* class_initialize */ ClassInitialize, /* class_part_initialize */ ClassPartInitialize, /* class_inited */ FALSE, /* initialize */ Initialize, /* initialize_hook */ NULL, /* realize */ Realize, /* actions */ NULL, /* num_actions */ 0, /* resources */ (XtResource*)resources, /* num_resources */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ TRUE, /* compress_exposure */ TRUE, /* compress_enterleave */ TRUE, /* visible_interest */ FALSE, /* destroy */ NULL, /* resize */ Resize, /* expose */ NULL, /* set_values */ SetValues, /* set_values_hook */ NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ NULL, /* accept_focus */ NULL, /* version */ XtVersion, /* callback_private */ NULL, /* tm_table */ XtInheritTranslations, /* query_geometry */ (XtGeometryHandler) QueryGeometry, /* display_accelerator */ XtInheritDisplayAccelerator, /* extension */ NULL }, { /* composite_class fields */ /* geometry_manager */ GeometryManager, /* change_managed */ ChangeManaged, /* insert_child */ InsertChild, /* delete_child */ XtInheritDeleteChild, /* extension */ NULL, }, { /* constraint_class fields */ /* resource list */ (XtResource*)constraints, /* num resources */ XtNumber(constraints), /* constraint size */ sizeof(XmIconBoxConstraintsRec), /* init proc */ ConstraintInitialize, /* destroy proc */ NULL, /* set values proc */ ConstraintSetValues, /* extension */ NULL, }, { /* manager_class fields */ /* default translations */ XtInheritTranslations, /* syn_resources */ get_resources, /* num_syn_resources */ XtNumber(get_resources), /* syn_cont_resources */ NULL, /* num_syn_cont_resources */ 0, /* parent_process */ XmInheritParentProcess, /* extension */ NULL, }, { /* Icon Box fields */ NULL /* extension */ } }; WidgetClass xmIconBoxWidgetClass = (WidgetClass)&xmIconBoxClassRec; /************************************************************ * STATIC CODE *************************************************************/ /* Function Name: Initialize * Description: Called to initialize information specific * to this widget. * Arguments: req - what was originally requested. * set - what will be created (our superclassed have * already mucked with this) * args, num_args - The arguments passed to * the creation call. * Returns: none. */ static void ClassInitialize() { /* do nothing */ } /*ARGSUSED*/ static void Initialize(Widget req, Widget set, ArgList args, Cardinal * num_args) { XmIconBoxWidget ibw = (XmIconBoxWidget) set; /* * This is needed so that the right thing happens if an icon box is * created w/o any children. */ CalcCellSizes(set, NULL, FALSE, FALSE, &(XmIconBox_cell_width(ibw)), &(XmIconBox_cell_height(ibw))); } /* Function Name: Realize * Description: Called to realize this widget. * Arguments: w - Widget to realize. * valueMask, attributes - attributes to use when creating * this widget's window. * Returns: none. * * This overrides the Manager's frobbing with various values. */ static void Realize(Widget w, Mask *valueMask, XSetWindowAttributes *attributes) { XtCreateWindow (w, InputOutput, CopyFromParent, *valueMask, attributes); } /* Function Name: Resize * Description: Called when this widget has been resized. * Arguments: w - the widget to resize. * Returns: none. */ static void Resize(Widget w) { XmIconBoxWidget ibw = (XmIconBoxWidget) w; CalcCellSizes(w, NULL, TRUE, FALSE, &(XmIconBox_cell_width(ibw)), &(XmIconBox_cell_height(ibw))); PlaceChildren(w, NULL); } /* Function Name: SetValues * Description: Called when some widget data needs to be modified on- * the-fly. * Arguments: current - the current (old) widget values. * request - before superclassed have changed things. * set - what will acutally be the set values. * args, num_args - the arguments in the list. * Returns: none */ /*ARGSUSED*/ static Boolean SetValues(Widget current, Widget request, Widget set, ArgList args, Cardinal * num_args) { XmIconBoxWidget old_ibw = (XmIconBoxWidget) current; XmIconBoxWidget set_ibw = (XmIconBoxWidget) set; if ((XmIconBox_min_v_cells(old_ibw) != XmIconBox_min_v_cells(set_ibw)) || (XmIconBox_min_h_cells(old_ibw) != XmIconBox_min_h_cells(set_ibw)) || (XmIconBox_min_cell_width(old_ibw) != XmIconBox_min_cell_width(set_ibw)) || (XmIconBox_min_cell_height(old_ibw) != XmIconBox_min_cell_height(set_ibw)) || (XmIconBox_v_margin(old_ibw) != XmIconBox_v_margin(set_ibw)) || (XmIconBox_h_margin(old_ibw) != XmIconBox_h_margin(set_ibw)) ) { CalcCellSizes(set, NULL, FALSE, FALSE, &(XmIconBox_cell_width(set_ibw)), &(XmIconBox_cell_height(set_ibw))); PlaceChildren(set, NULL); } return(FALSE); } /* Function Name: QueryGeometry * Description: Called when my parent wants to know what size * I would like to be. * Arguments: w - the widget to check. * indended - constriants imposed by the parent. * preferred - what I would like. * Returns: See Xt Manual. */ static XtGeometryResult QueryGeometry(Widget w,XtWidgetGeometry *intended, XtWidgetGeometry *preferred) { XmIconBoxWidget ibw = (XmIconBoxWidget) w; Cardinal min_x, min_y; Dimension max_w, max_h; GetMinCells(w, &min_x, &min_y); GetMaxCellSize(w, NULL, &max_w, &max_h); min_x++; min_y++; preferred->width = XmIconBox_h_margin(ibw) + min_x * (max_w + XmIconBox_h_margin(ibw)); preferred->height= XmIconBox_v_margin(ibw) + min_y * (max_h + XmIconBox_v_margin(ibw)); return(_XmHWQuery(w, intended, preferred)); } /************************************************************ * * Composite and Constraint Information. * ************************************************************/ /* Function Name: GeometryManager * Description: handles requests from children for a size change. * Arguments: child - the child to change. * request - the geometry that the child wants. * return - what we will allow if this is an almost. * Returns: status. */ /*ARGSUSED*/ static XtGeometryResult GeometryManager(Widget w, XtWidgetGeometry * request, XtWidgetGeometry * result) { Dimension cwidth, cheight; XmIconBoxWidget ibw = (XmIconBoxWidget) XtParent(w); IconInfo * info = GetIconInfo(w); Boolean w_req = (request->request_mode & CWWidth); Boolean h_req = (request->request_mode & CWHeight); Boolean x_req = (request->request_mode & CWX); Boolean y_req = (request->request_mode & CWY); if (!(request->request_mode & (CWWidth | CWHeight | CWX | CWY))) return(XtGeometryNo); result->request_mode = 0; if (w_req || h_req) { CalcCellSizes((Widget) ibw, w, FALSE, TRUE, &cwidth, &cheight); if(w_req) ASSIGN_MAX(cwidth, request->width); else ASSIGN_MAX(cwidth, w->core.width); if(h_req) ASSIGN_MAX(cheight, request->height); else ASSIGN_MAX(cheight, w->core.height); /* * Do not allow an x, y width and height request at the same time. * since it is unclear what this would mean. I want to place the * widget in the cell the center of it is over. With a multiple * request like this is it tough to find out which cell to use * since there are two reasonable values for height and width. */ result->x = w->core.x; result->y = w->core.y; result->width = cwidth; result->height = cheight; result->request_mode |= CWX | CWY | CWHeight | CWWidth; } else if ( x_req || y_req ) { Position x, y; short cell_x, cell_y; if (x_req) x = request->x; else x = w->core.x; if (y_req) y = request->y; else y = w->core.y; FindNearestCellLocation((Widget) ibw, &x, &y); GetCellFromXY((Widget) ibw, x, y, &cell_x, &cell_y); if (XmIconBoxIsCellEmpty((Widget) ibw, cell_x, cell_y, w)) { result->x = x; result->y = y; result->request_mode |= CWX | CWY; } else /* Cell is full, return NO. */ return(XtGeometryNo); } if (((request->x == result->x) || !x_req) && ((request->y == result->y) || !y_req) && ((request->width == result->width) || !w_req) && ((request->height == result->height) || !h_req)) { if (request->request_mode & (CWBorderWidth | CWStackMode | CWSibling)) { return(XtGeometryAlmost); } if (request->request_mode & XtCWQueryOnly) return(XtGeometryYes); if (w_req || h_req) { if (w_req) info->pref_width = w->core.width = request->width; if (h_req) info->pref_height = w->core.height = request->height; } else { /* * NOTE: We are assuming here that the cell height/width * did not change. This is valid because this code is * only executed if w_req and h_req are false. */ GetCellFromXY((Widget) ibw, result->x, result->y, &(info->cell_x), &(info->cell_y)); } CalcCellSizes((Widget) ibw, NULL, FALSE, FALSE, &(XmIconBox_cell_width(ibw)), &(XmIconBox_cell_height(ibw))); PlaceChildren((Widget) ibw, w); return(XtGeometryYes); } info->pref_width = info->pref_height = 0; /* invalidate cache. */ if (((request->x == result->x) || !x_req) || ((request->y == result->y) || !y_req) || ((request->width == result->width) || !w_req) || ((request->height == result->height) || !h_req)) { return(XtGeometryAlmost); } else return(XtGeometryNo); } /* Function Name: InsertChild * Description: called when a new child is to be added. * Arguments: w - the new child. * Returns: none. * * This routine simply makes sure that no gadgets are added. */ static void InsertChild(Widget w) { if (_XmGadgetWarning(w)) return; { XtWidgetProc insert_child; _XmProcessLock(); insert_child = ( (CompositeWidgetClass) SUPERCLASS)->composite_class.insert_child; _XmProcessUnlock(); (*insert_child)(w); } } /* Function Name: ChangeManaged * Description: When a management change has occured... * Arguments: w - the icon box widget. * Returns: none. */ static void ChangeManaged(Widget w) { XmIconBoxWidget ibw = (XmIconBoxWidget) w; Widget * childp; CalcCellSizes(w, NULL, FALSE, TRUE, &(XmIconBox_cell_width(ibw)), &(XmIconBox_cell_height(ibw))); ForAllChildren(ibw, childp) { IconInfo * info = GetIconInfo(*childp); if ((info->cell_x != XmIconBoxAnyCell) && (info->cell_y != XmIconBoxAnyCell) && !XmIconBoxIsCellEmpty((Widget) ibw, info->cell_x, info->cell_y, *childp)) { static String params[1]; Cardinal num = 1; char buf[BUFSIZ]; params[0] = buf; snprintf(buf, BUFSIZ, "(%d, %d)", info->cell_x, info->cell_y); _XmWarningMsg(w, XmNcellNotEmpty, XmNcellNotEmptyMsg, params, num); /* * tell it to reset this to an empty cell. */ info->cell_y = XmIconBoxAnyCell; } if ((info->cell_x == XmIconBoxAnyCell) || (info->cell_y == XmIconBoxAnyCell)) { Position x = (*childp)->core.x; Position y = (*childp)->core.y; Position cell_x, cell_y; /* * If the cell location is not specified try to find the * cell nearest the X and Y coords specified. */ FindNearestCellLocation((Widget) ibw, &x, &y); GetCellFromXY((Widget) ibw, x, y, &cell_x, &cell_y); if (XmIconBoxIsCellEmpty((Widget) ibw, cell_x, cell_y, w)) { info->cell_x = cell_x; info->cell_y = cell_y; } /* * If this cell is full the just find any empty cell. */ else if (!SetToEmptyCell(*childp)) { XmeWarning(w, XmNnoEmptyCellsMsg); } } } CalcCellSizes(w, NULL, FALSE, FALSE, &(XmIconBox_cell_width(ibw)), &(XmIconBox_cell_height(ibw))); PlaceChildren(w, NULL); XmeNavigChangeManaged(w); /* For Motif navigation */ } /* * ClassPartInitialize sets up the fast subclassing for the widget. */ static void #ifdef _NO_PROTO ClassPartInitialize(w_class) WidgetClass w_class ; #else ClassPartInitialize(WidgetClass w_class) #endif /* _NO_PROTO */ { _XmFastSubclassInit (w_class, XmICONBOX_BIT); } /* Function Name: ConstraintInitialize * Description: Called when a childs constriaints need initializing. * Arguments: req - the widget being requested. * set - what this will become. * args, num_args - the argument list. * Returns: none. */ /*ARGSUSED*/ static void ConstraintInitialize(Widget req, Widget set, ArgList args, Cardinal * num_args) { IconInfo * info = GetIconInfo(set); info->pref_width = req->core.width; info->pref_height = req->core.height; } /* Function Name: ConstraintSetValues * Description: Called when some constraint data needs to be modified * on-the-fly. * Arguments: current - the current (old) widget values. * request - before superclassed have changed things. * set - what will acutally be the new values. * args, num_args - the arguments in the list. * Returns: none */ /*ARGSUSED*/ static Boolean ConstraintSetValues(Widget current, Widget request, Widget set, ArgList args, Cardinal * num_args) { IconInfo * set_info = GetIconInfo(set); IconInfo * old_info = GetIconInfo(current); if (set->core.width != set_info->pref_width) set_info->pref_width = 0; if (set->core.height != set_info->pref_height) set_info->pref_height = 0; if ((set_info->cell_x != old_info->cell_x) || (set_info->cell_y != old_info->cell_y)) { if ( XmIconBoxIsCellEmpty(XtParent(set), set_info->cell_x, set_info->cell_y, set)) { GetXYFromCell(XtParent(set), set_info, &(set->core.x), &(set->core.y)); } else { static String params[1]; Cardinal num = 1; char buf[BUFSIZ]; params[0] = buf; snprintf(buf, BUFSIZ, "(%d, %d)", set_info->cell_x, set_info->cell_y); _XmWarningMsg(set, XmNcellNotEmpty, XmNcellNotEmptyMsg, params, num); set_info->cell_x = old_info->cell_x; set_info->cell_y = old_info->cell_y; } } return(False); } /************************************************************ * * Actions and Callbacks. * ************************************************************/ /************************************************************ * * Internal routines. * ************************************************************/ /* Function Name: GetCellFromXY * Description: Gets the cell located at this location. * Arguments: w - the icon box. * x, y - the coordinates in X space. * RETURNED cell_x, cell_y - the corrdinates in cell space. * Returns: none. */ static void GetCellFromXY(Widget w, Position x, Position y, Position * cell_x, Position * cell_y) { XmIconBoxWidget ibw = (XmIconBoxWidget) w; *cell_x = (int)x / (int)(XmIconBox_cell_width(ibw) + XmIconBox_h_margin(ibw)); *cell_y = (int)y / (int)(XmIconBox_cell_height(ibw) + XmIconBox_v_margin(ibw)); } /* Function Name: Find Nearest Cell Location * Description: Finds the nearest cell * Arguments: ibw - the icon box widget. * IN/OUT x, y - Used as an input for the current location * is output with the new location. * Returns: none */ static void FindNearestCellLocation(Widget w, Position *x, Position *y) { IconInfo temp; Dimension width, height; XmIconBoxWidget ibw = (XmIconBoxWidget) w; width = XmIconBox_cell_width(ibw); height = XmIconBox_cell_height(ibw); GetCellFromXY(w, *x + width/2, *y + height/2, &(temp.cell_x), &(temp.cell_y)); GetXYFromCell(w, &temp, x, y); } /* Function Name: GetXYFromCell * Description: Gets the X and Y position for this cell. * Arguments: info - the cell info. * RETURNED x, y - the coordinates in X space. * Returns: none. */ static void GetXYFromCell(Widget w, IconInfo * info, Position * x, Position * y) { XmIconBoxWidget ibw = (XmIconBoxWidget) w; Position x_temp = (info->cell_x < 0) ? 0 : info->cell_x; Position y_temp = (info->cell_y < 0) ? 0 : info->cell_y; *x = XmIconBox_h_margin(ibw) + x_temp * (XmIconBox_cell_width(ibw) + XmIconBox_h_margin(ibw)); *y = XmIconBox_v_margin(ibw) + y_temp * (XmIconBox_cell_height(ibw) + XmIconBox_v_margin(ibw)); } /* Function Name: PlaceChildren * Description: Places all managed children correctly. * Arguments: w - the icon box widget. * child - set attributes rather than configure this child. * Returns: none. */ static void PlaceChildren(Widget w, Widget child) { Widget * childp; Position x, y; XmIconBoxWidget ibw = (XmIconBoxWidget) w; ForAllChildren(ibw, childp) { if (!XtIsManaged(*childp)) continue; GetXYFromCell(w, GetIconInfo(*childp), &x, &y); if (*childp == child) { child->core.x = x; child->core.y = y; child->core.width = XmIconBox_cell_width(ibw); child->core.height = XmIconBox_cell_height(ibw); } else { _XmConfigureWidget(*childp, x, y, XmIconBox_cell_width(ibw), XmIconBox_cell_height(ibw), (*childp)->core.border_width); } } } /* Function Name: CalcCellSizes * Description: Calculates the height and width of each cell. * Arguments: w - the icon box widget. * ignore - ignore this child when calculating cell sizes. * noresize - If true then never attempt a resize. * query_only - only ask, don't change anything. * cell_width, cell_height - new size of each cell. * Returns: none. */ static void CalcCellSizes(Widget w, Widget ignore, Boolean noresize, Boolean query_only, Dimension * cell_width, Dimension * cell_height) { XmIconBoxWidget ibw = (XmIconBoxWidget) w; Cardinal min_x, min_y; Dimension max_w, max_h, d_width, d_height, width, height; GetMinCells(w, &min_x, &min_y); GetMaxCellSize(w, ignore, &max_w, &max_h); min_x++; min_y++; d_width = XmIconBox_h_margin(ibw) + min_x * (max_w + XmIconBox_h_margin(ibw)); d_height = XmIconBox_v_margin(ibw) + min_y * (max_h + XmIconBox_v_margin(ibw)); if (noresize || (_XmRequestNewSize(w, query_only, d_width, d_height, &width, &height) != XtGeometryYes)) { if (noresize) { width = w->core.width; height = w->core.height; } /* * We may need to adjust the cell size. */ if (width < d_width) max_w = (width - XmIconBox_h_margin(ibw))/ min_x - XmIconBox_h_margin(ibw); if (height < d_height) max_h = (height - XmIconBox_v_margin(ibw))/ min_y - XmIconBox_v_margin(ibw); } *cell_width = max_w; *cell_height = max_h; } /* Function Name: GetMinCells * Description: Returns the minimum number of cells that should * be displayed in each direction. * Arguments: w - the Icon Box widget. * RETURN min_x, min_y - minimum number of cells needed * in each direction. * * Returns: */ static void GetMinCells(Widget w, Cardinal * min_x, Cardinal * min_y) { Widget * childp; XmIconBoxWidget ibw = (XmIconBoxWidget) w; *min_x = XmIconBox_min_h_cells(ibw) - 1; *min_y = XmIconBox_min_v_cells(ibw) - 1; ForAllChildren(ibw, childp) { Position x, y; IconInfo * info; if (!XtIsManaged(*childp)) continue; info = GetIconInfo(*childp); x = (info->cell_x < 0) ? 0 : info->cell_x; y = (info->cell_y < 0) ? 0 : info->cell_y; if (x > *min_x) *min_x = x; if (y > *min_y) *min_y = y; } } /* Function Name: GetMaxCellSize * Description: Gets the maximum size of each cell. * Arguments: w - the Icon Box widget. * ignore - ignore this child. * max_w, max_h - the maximum size of each cell. * Returns: none. */ static void GetMaxCellSize(Widget w, Widget ignore, Dimension * max_w, Dimension * max_h) { Widget * childp; XmIconBoxWidget ibw = (XmIconBoxWidget) w; XtWidgetGeometry preferred; register Dimension temp; *max_w = XmIconBox_min_cell_width(ibw); *max_h = XmIconBox_min_cell_height(ibw); ForAllChildren(ibw, childp) { IconInfo * info = GetIconInfo(*childp); if (!XtIsManaged(*childp) || (*childp == ignore)) continue; if ((info->pref_width != 0) && (info->pref_height != 0)) { preferred.width = info->pref_width; preferred.height = info->pref_height; preferred.border_width = (*childp)->core.border_width; } else { (void) XtQueryGeometry(*childp, NULL, &preferred); info->pref_width = preferred.width; info->pref_height = preferred.height; } temp = preferred.width + 2 * preferred.border_width; ASSIGN_MAX(*max_w, temp); temp = preferred.height + 2 * preferred.border_width; ASSIGN_MAX(*max_h, temp); } } /* Function Name: SetToEmptyCell * Description: Puts the widget passed into an empty node as * close to 0, 0 as possible. * Arguments: child - the child. * Returns: True if an empty cell was found. */ static Boolean SetToEmptyCell(Widget child) { XmIconBoxWidget ibw = (XmIconBoxWidget) XtParent(child); register Position x, y, cur_x, cur_y; register unsigned long square, cur_square; Cardinal max_x, max_y; GetMinCells((Widget) ibw, &max_x, &max_y); cur_x = cur_y = XmIconBoxAnyCell; cur_square = max_x * max_x + max_y * max_y; for (y = 0; y <= max_y; y++) for (x = 0; x <= max_x; x++) { square = x * x + y * y; if (square <= cur_square && XmIconBoxIsCellEmpty(XtParent(child), x, y, NULL)) { cur_square = square; cur_x = x; cur_y = y; break; } else if (square >= cur_square) continue; } if (cur_x == XmIconBoxAnyCell) { IconInfo * info = GetIconInfo(child); info->cell_x = 0; info->cell_y = max_y + 1; } else { IconInfo * info = GetIconInfo(child); info->cell_x = cur_x; info->cell_y = cur_y; } return(TRUE); } /************************************************************ * * Public Functions. * ************************************************************/ /* Function Name: XmIconBoxIsCellEmpty * Description: Returns true if this cell is unused. * Arguments: w - the icon box. * x, y - cell to check. * ignore - ignore this widget when checking. * Returns: Returns true if this cell is unused. */ Boolean XmIconBoxIsCellEmpty(Widget w, Position x, Position y, Widget ignore) { XmIconBoxWidget ibw = (XmIconBoxWidget) w; Widget * childp; _XmWidgetToAppContext(w); _XmAppLock(app); ForAllChildren(ibw, childp) { IconInfo * info; if (!XtIsManaged(*childp) || (*childp == ignore) || (*childp)->core.being_destroyed) { continue; } info = GetIconInfo(*childp); if ((x == info->cell_x) && (y == info->cell_y)) { _XmAppUnlock(app); return(False); } } _XmAppUnlock(app); return(True); } /* Function Name: XmCreateIconBox * Description: Creation Routine for UIL and ADA. * Arguments: parent - the parent widget. * name - the name of the widget. * args, num_args - the number and list of args. * Returns: The created widget. */ Widget XmCreateIconBox(Widget parent, String name, ArgList args, Cardinal num_args) { return(XtCreateWidget(name, xmIconBoxWidgetClass, parent, args, num_args)); }