/* $TOG: Container.c /main/7 1997/05/02 10:09:20 dbl $ */ /* * @OPENGROUP_COPYRIGHT@ * COPYRIGHT NOTICE * Copyright (c) 1990, 1991, 1992, 1993 Open Software Foundation, Inc. * Copyright (c) 1996, 1997, 1998, 1999, 2000 The Open Group * ALL RIGHTS RESERVED (MOTIF). See the file named COPYRIGHT.MOTIF for * the full copyright text. * * This software is subject to an open license. It may only be * used on, with or for operating systems which are themselves open * source systems. You must contact The Open Group for a license * allowing distribution and sublicensing of this software on, with, * or for operating systems which are not Open Source programs. * * See http://www.opengroup.org/openmotif/license for full * details of the license agreement. Any use, reproduction, or * distribution of the program constitutes recipient's acceptance of * this agreement. * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS * PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY * WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY * OR FITNESS FOR A PARTICULAR PURPOSE * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT * NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE * EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * */ /* * HISTORY */ /********************************* WARNING ********************************** * * This widget is for educational purposes only. * Commercial applications should NOT instantiate this widget. * OSF makes no guarantees on the stability of this widget. * ********************************* WARNING *********************************/ /****************************************************************************** * * Container.c - ExmContainer widget. * ******************************************************************************/ /* Include appropriate files. */ #include /* header file for gadget management functions */ #include /* header file for trait functions */ #include /* container trait */ #include /* container item trait */ #include #include #include #include /* This one should be somewhere common */ /* The Max macro returns the higher of two input arguments. */ #define Max(x, y) (((x) > (y)) ? (x) : (y)) /* Declare static functions. */ static void ButtonHandler(Widget wid, XtPointer data, XEvent * event, Boolean *cont); static void GetFirstColumnWidth( Widget wid, int offset, XtArgVal *value); static void GetDetailTabList( Widget wid, int offset, XtArgVal *value); static void SelectColorDefault( Widget widget, int offset, XrmValue *value ); static void ClassPartInitialize( WidgetClass widgetClass); static void Initialize( Widget rw, Widget nw, ArgList args, Cardinal *num_args); static void Destroy( Widget wid); static void Layout ( Widget wid, Widget instigator); static void CalcSize ( Widget wid, Widget instigator, Dimension *gridWidth, Dimension *gridHeight); static Boolean NeedRelayout ( Widget old_w, Widget new_w); static XmTabList GetDefaultTabList( ExmContainerWidget cw, Cardinal detail_order_count); static XmTabList GetDumbTabList( Dimension tab_size, Cardinal asked_num_tab); static void ContainerGetValues(Widget w, XmContainerData containerData); static Dimension GetDefaultFirstColumnWidth( ExmContainerWidget cw, Dimension fcw_init); static Cardinal GetDefaultDetailCount( ExmContainerWidget cw, Cardinal detail_count); /* No translations and no actions. */ static XtResource resources[] = { { ExmNfirstColumnWidth, ExmCFirstColumnWidth, XmRDimension, sizeof (Dimension), XtOffsetOf(ExmContainerRec, container.first_column_width), XmRImmediate, (XtPointer) 0 }, { ExmNdetailOrder, ExmCDetailOrder, XmRCardinalList, sizeof (Cardinal *), XtOffsetOf(ExmContainerRec, container.detail_order), XmRImmediate, (XtPointer) NULL }, { ExmNdetailOrderCount, ExmCDetailOrderCount, XmRCardinal, sizeof (Cardinal), XtOffsetOf(ExmContainerRec, container.detail_order_count), XmRImmediate, (XtPointer) 0 }, { ExmNdetailTabList, ExmCDetailTabList, XmRTabList, sizeof (XmTabList), XtOffsetOf(ExmContainerRec, container.detail_tablist), XmRImmediate, (XtPointer) NULL }, { ExmNdetailHeader, ExmCDetailHeader, XmRXmStringTable, sizeof (XmStringTable), XtOffsetOf(ExmContainerRec, container.detail_header), XmRImmediate, (XtPointer) NULL }, { ExmNdetailHeaderCount, ExmCDetailHeaderCount, XmRCardinal, sizeof (Cardinal), XtOffsetOf(ExmContainerRec, container.detail_header_count), XmRImmediate, (XtPointer) 0 }, { ExmNselectColor, ExmCSelectColor, XmRPixel, sizeof (Pixel), XtOffsetOf(ExmContainerRec, container.select_color), XmRImmediate, (XtPointer) SelectColorDefault }, { ExmNlayoutType, ExmCLayoutType, XmRLayoutType, sizeof (unsigned char), XtOffsetOf(ExmContainerRec, container.layout_type), XmRImmediate, (XtPointer) XmDETAIL }, }; static XmSyntheticResource syn_resources[] = { { ExmNfirstColumnWidth, sizeof (Dimension), XtOffsetOf( ExmContainerRec, container.first_column_width), GetFirstColumnWidth, NULL }, { ExmNdetailTabList, sizeof (XmTabList), XtOffsetOf( ExmContainerRec, container.detail_tablist), GetDetailTabList, NULL }, }; /* Define the widget class record. See Chapter 4 of the "OSF/Motif Widget Writer's Guide" for details. */ externaldef(exmcontainerclassrec) ExmContainerClassRec exmContainerClassRec = { { /* core_class */ /* superclass */ (WidgetClass) &exmGridClassRec, /* class_name */ "ExmContainer", /* widget_size */ sizeof(ExmContainerRec), /* class_initialize */ NULL, /* class_part_initialize */ ClassPartInitialize, /* class_inited */ FALSE, /* initialize */ Initialize, /* initialize_hook */ NULL, /* realize */ XtInheritRealize, /* actions */ NULL, /* num_actions */ 0, /* resources */ resources, /* num_resources */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ TRUE, /* compress_exposure */ XtExposeCompressMaximal, /* compress_enterleave */ TRUE, /* visible_interest */ FALSE, /* destroy */ Destroy, /* resize */ XtInheritResize, /* expose */ XtInheritExpose, /* set_values */ NULL, /* 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 */ XtInheritQueryGeometry, /* display_accelerator */ NULL, /* extension */ NULL, }, { /* composite_class */ /* geometry_manager */ XtInheritGeometryManager, /* change_managed */ XtInheritChangeManaged, /* insert_child */ XtInheritInsertChild, /* delete_child */ XtInheritDeleteChild, /* extension */ NULL, }, { /* constraint_class */ /* constraint_resources */ NULL, /* constraint_num_resources */ 0, /* constraint_size */ sizeof(ExmGridConstraintRec), /* constraint_initialize */ NULL, /* constraint_destroy */ NULL, /* constraint_set_values */ NULL, /* extension */ NULL, }, { /* manager class */ /* translations */ XtInheritTranslations, /* syn_resources */ syn_resources, /* num_syn_resources */ XtNumber(syn_resources), /* syn_constraint_resources */ NULL, /* num_syn_constraint_resources */ 0, /* parent_process */ XmInheritParentProcess, /* extension */ NULL, }, { /* grid class */ /* layout */ Layout, /* calc_size */ CalcSize, /* need_relayout */ NeedRelayout, /* extension */ NULL, }, { /* container class */ /* extension */ NULL, } }; /* Establish the widget class name as an externally accessible symbol. Use the "externaldef" macro rather than the "extern" keyword. */ externaldef(exmcontainerwidgetclass) WidgetClass exmContainerWidgetClass = (WidgetClass) &exmContainerClassRec; /* Container Trait record for Grid */ static XmContainerTraitRec containerCT = { 0, /* version */ ContainerGetValues, }; /************************************************************************ * GetFirstColumnWidth ************************************************************************/ /*ARGSUSED*/ static void GetFirstColumnWidth( Widget wid, int offset, /* unused */ XtArgVal *value) { ExmContainerWidget cw = (ExmContainerWidget) wid ; Dimension fcw = cw->container.first_column_width ; if (!fcw) { /* get the max of icon_width + their indentation */ fcw = GetDefaultFirstColumnWidth(cw, 0); } *value = (XtArgVal)fcw; } /************************************************************************ * GetDetailTabList ************************************************************************/ /*ARGSUSED*/ static void GetDetailTabList( Widget wid, int offset, /* unused */ XtArgVal *value) { ExmContainerWidget cw = (ExmContainerWidget) wid ; XmTabList tab_list = cw->container.detail_tablist ; if (!tab_list) { /* get the default one */ Cardinal detail_order_count ; if (cw->container.detail_order_count != 0) { detail_order_count = cw->container.detail_order_count ; } else { detail_order_count = GetDefaultDetailCount(cw, 0) ; } tab_list = GetDefaultTabList(cw, detail_order_count); /* callers should not free this memory */ } *value = (XtArgVal)tab_list; } /**************************************************************************** * * SelectColorDefault. * ****************************************************************************/ static void SelectColorDefault( Widget widget, int offset, XrmValue *value ) { XmeGetDefaultPixel (widget, XmSELECT, offset, value); } /**************************************************************************** * * ClassPartInitialize: * Called when this widget or a subclass of this widget is instantiated. * ****************************************************************************/ static void ClassPartInitialize ( WidgetClass widgetClass ) { /* Install the XmQTcontainer trait on ExmContainer and all its subclasses. */ XmeTraitSet(widgetClass, XmQTcontainer, (XtPointer) &containerCT); } /************************************************************************ * Initialize ************************************************************************/ /*ARGSUSED*/ static void Initialize( Widget rw, Widget nw, ArgList args, /* unused */ Cardinal *num_args) /* unused */ { ExmContainerWidget cw = (ExmContainerWidget)nw; ExmContainerWidget rcw = (ExmContainerWidget)rw; Arg sargs[10] ; Cardinal n = 0, i ; Widget header_parent = nw ; unsigned char scrollp = XmAPPLICATION_DEFINED ; XmScrollFrameTrait scrollFrameTrait; cw->container.icon_header = NULL ; if (cw->container.detail_header && cw->container.detail_header_count) { /**** first make a copy of the detail header table */ cw->container.detail_header = (XmStringTable) XtMalloc(cw->container.detail_header_count * sizeof(XmString)); for (i=0; icontainer.detail_header_count; i++) cw->container.detail_header[i] = XmStringCopy(rcw->container.detail_header[i]); /**** deal with the IconHeader creation */ scrollFrameTrait = (XmScrollFrameTrait) XmeTraitGet((XtPointer) XtClass(XtParent(nw)), XmQTscrollFrame); /* check that the parent is a scrollframe already initialize, which also means an automatic scrolledwindow in Motif */ if (scrollFrameTrait && scrollFrameTrait -> getInfo (XtParent(nw), NULL, NULL, NULL)) { scrollp = XmAUTOMATIC ; /* use an intermediate DA so that we can have margins */ n = 0 ; XtSetArg(sargs[n], XmNmarginHeight, cw->grid.margin_height); n++ ; XtSetArg(sargs[n], XmNmarginWidth, cw->grid.margin_width); n++ ; XtSetArg(sargs[n], XmNscrolledWindowChildType, XmSCROLL_HOR); n++; XtSetArg(sargs[n], XmNbackground, nw->core.background_pixel); n++; XtSetArg(sargs[n], XmNbackgroundPixmap, nw->core.background_pixmap); n++; XtSetArg(sargs[n], XmNborderWidth, nw->core.border_width); n++; XtSetArg(sargs[n], XmNforeground, cw->manager.foreground); n++; header_parent = XmCreateDrawingArea(XtParent(nw), "HeaderDA", sargs, n); XtManageChild(header_parent); } n = 0 ; /* this is required */ XtSetArg(sargs[n], XmNcontainerID, nw); n++ ; /* this is optional */ XtSetArg(sargs[n], XmNshadowThickness, 0); n++ ; XtSetArg(sargs[n], XmNtraversalOn, False); n++ ; XtSetArg(sargs[n], XmNlabelString, cw->container.detail_header[0]); n++ ; if (cw->container.detail_header_count > 1) { XtSetArg(sargs[n], XmNdetail, &(cw->container.detail_header[1])); n++ ; } XtSetArg(sargs[n], XmNdetailCount, cw->container.detail_header_count - 1); n++ ; cw->container.icon_header = XmCreateIconHeader(header_parent, "Header", sargs, n); XtManageChild(cw->container.icon_header); /**** Now we have to position the Container properly in the scrolling window if there is one */ if (scrollp == XmAUTOMATIC) { cw->core.y = cw->container.icon_header->core.height ; /* also resize the DA to remove the bottom margin */ XmeConfigureObject(header_parent, header_parent->core.x, header_parent->core.y, cw->container.icon_header->core.width + 2*cw->grid.margin_height, cw->container.icon_header->core.height + cw->grid.margin_height, header_parent->core.border_width); } else { /* if not scrolling, no need to keep it, it will be dealt with as a regular kid */ cw->container.icon_header = NULL ; } } /**** copy the tablist */ if (cw->container.detail_tablist) { cw->container.detail_tablist = XmTabListCopy(cw->container.detail_tablist, 0, 0); } /* add an event handler to play with selection */ XtAddEventHandler(nw, ButtonPressMask, False, ButtonHandler, NULL); } static void ButtonHandler(Widget wid, XtPointer data, XEvent * event, Boolean *cont) { Widget item ; XmContainerItemDataRec cItemData; XmContainerItemTrait cItemTrait; item = XmObjectAtPoint(wid, event->xbutton.x, event->xbutton.y); if (item) { if ((cItemTrait = (XmContainerItemTrait) XmeTraitGet((XtPointer)XtClass(item), XmQTcontainerItem))) { cItemData.valueMask = ContItemVisualEmphasis; cItemTrait->getValues(item, &cItemData); if (cItemData.visual_emphasis == XmSELECTED) cItemData.visual_emphasis = XmNOT_SELECTED ; else cItemData.visual_emphasis = XmSELECTED ; cItemTrait->setValues(item, &cItemData); } } } /************************************************************************ * Destroy ************************************************************************/ static void Destroy( Widget wid) { ExmContainerWidget cw = (ExmContainerWidget)wid; Cardinal i ; if (cw->container.icon_header) { /* that will destroy the icon header child as well */ XtDestroyWidget(XtParent(cw->container.icon_header)); } if (cw->container.detail_header && cw->container.detail_header_count) { for (i=0; icontainer.detail_header_count; i++) XmStringFree(cw->container.detail_header[i]); XtFree((char*)cw->container.detail_header); } if (cw->container.detail_tablist) { XmTabListFree(cw->container.detail_tablist); } } /***************************************************************************** * * NeedRelayout: * need to tell if any of the resource values change should cause * a relayout. Must envelop the superclass method because it is * only called once by the superclass defining the method. * ****************************************************************************/ static Boolean NeedRelayout ( Widget old_w, Widget new_w ) { ExmContainerWidget cw = (ExmContainerWidget)old_w; ExmContainerWidget nw = (ExmContainerWidget)new_w; Boolean need_relayout ; /* envelop the superclass method */ need_relayout = ((* ((ExmGridClassRec *) exmContainerClassRec.core_class.superclass) ->grid_class.need_relayout) (old_w, new_w) || (nw->container.first_column_width != cw->container.first_column_width || nw->container.detail_order != cw->container.detail_order || nw->container.detail_order_count != cw->container.detail_order_count || nw->container.detail_tablist != cw->container.detail_tablist)); return (need_relayout); } /*************************************************************************** * * Layout: * Does all the placement of children. * Instigator tells whether or not to resize all children. * *************************************************************************/ static void Layout ( Widget wid, Widget instigator ) { ExmContainerWidget cw = (ExmContainerWidget) wid ; Cardinal i, num_managed = 0; int line_count ; Dimension width, height, baseline_first = 0, interspace_max = 0, pref_height, interspace; int height_under_prec = 0 ; Dimension * baselines ; Position x, y ; /**** a first pass to compute the interspace */ for (i = 0; i < cw->composite.num_children; i++) { Widget ic = cw->composite.children[i]; XtWidgetGeometry reply; if (!XtIsManaged(ic)) continue ; num_managed ++ ; /* ask for preferred height and baseline to the kid */ XmWidgetGetBaselines(ic, &baselines, &line_count); if (!line_count) continue ; /* store the first baseline and height under */ if (!baseline_first) { baseline_first = baselines[0]; /* negative so that it gives 0 below, so that it doesn't count in the max */ height_under_prec = -baseline_first ; } interspace = height_under_prec + baselines[0] ; interspace_max = Max(interspace_max, interspace); /* Get child's preferred height. */ XtQueryGeometry (ic, NULL, &reply); pref_height = (reply.request_mode & CWHeight) ? reply.height : ic->core.height; height_under_prec = pref_height - baselines[0] ; XtFree((char*) baselines); } /* now layout */ /**** a second pass to actually do the layout */ /* first deal with the icon header outside the container */ if (cw->container.icon_header && XtIsManaged(cw->container.icon_header)) { Widget header_parent ; XmeConfigureObject (cw->container.icon_header, cw->grid.margin_width, cw->grid.margin_height, cw->core.width - 2*cw->grid.margin_width, cw->container.icon_header->core.height, cw->container.icon_header->core.border_width); /* also reconfigure the parent DA */ header_parent = XtParent(cw->container.icon_header) ; XmeConfigureObject(header_parent, header_parent->core.x, header_parent->core.y, cw->core.width, cw->container.icon_header->core.height + cw->grid.margin_height, header_parent->core.border_width); } y = cw->grid.margin_height ; for (i = 0; i < cw->composite.num_children; i++) { Widget ic = cw->composite.children[i]; ExmGridConstraint glc = ExmGridCPart (ic); if (LayoutIsRtoLM(cw)) x = cw->grid.margin_width ; else x = cw->grid.margin_width + glc->grid_margin_width_within_cell ; width = cw->core.width - 2*cw->grid.margin_width - glc->grid_margin_width_within_cell; height = ic->core.height ; if (ic != instigator) { XtConfigureWidget (ic, x, y, width, height, ic->core.border_width); } else { ic->core.x = x; ic->core.y = y; ic->core.width = width; ic->core.height = height; } XmWidgetGetBaselines(ic, &baselines, &line_count); if (line_count) y += baselines[0] + interspace_max ; if (i != cw->composite.num_children - 1) { XmWidgetGetBaselines(cw->composite.children[i+1], &baselines, &line_count); if (line_count) y -= baselines[0] ; } } } /**************************************************************************** * * CalcSize: * Calculate the ideal size of the ExmGrid widget. * Only affect the returned size if it is 0 * ***************************************************************************/ static void CalcSize ( Widget wid, Widget instigator, Dimension *width_ret, Dimension *height_ret) { /* The Width of the Container is the sum of the first_column_width and the detail width. If the first_column_width is not set, we must compute it as the max of all the icon_width at their position (we set the fcw temporarily so that it is not recomputed when the detailwidth are calculated. The detail width is the position of the last tab if there is one for the last detail_order, otherwise it's the max width of all icon detail width. The Height of the container is n-1 time the max of height_under baseline of i-1 + baseline of i , + baseline 0 + h_under n-1 */ ExmContainerWidget cw = (ExmContainerWidget) wid ; Boolean fcw_set = False ; Cardinal i, num_managed = 0 ; int line_count ; Dimension height, baseline_first = 0, interspace_max = 0, pref_height, pref_width, interspace, detail_width; int height_under_prec = 0 ; Dimension * baselines ; Cardinal tab_count = 0 ; /**** first get the first column width */ if (!cw->container.first_column_width) { cw->container.first_column_width = GetDefaultFirstColumnWidth(cw, 0); /* we don't want to keep this calculated first_column_width in cw, so set a flag to reset it to 0 at the end */ fcw_set = True ; } /**** now get the details part */ if (cw->container.layout_type != XmDETAIL) detail_width = 0 ; else { if (cw->container.detail_tablist) tab_count = XmTabListTabCount(cw->container.detail_tablist) ; if (cw->container.detail_order_count && tab_count >= cw->container.detail_order_count) { detail_width = XmTabListGetPosition(XtScreen((Widget)cw), cw->container.detail_tablist, tab_count-1); } else { XtWidgetGeometry reply; /* get the max width of all details */ if (cw->container.icon_header && XtIsManaged(cw->container.icon_header)) { Dimension header_width ; /* start with header's preferred width. */ XtQueryGeometry (cw->container.icon_header, NULL, &reply); header_width = (reply.request_mode & CWWidth) ? reply.width : cw->container.icon_header->core.width; detail_width = header_width - /* remove the horiz indent */ (cw->container.first_column_width - cw->container.icon_header->core.x); } else detail_width = 0 ; for (i = 0; i < cw->composite.num_children; i++) { Widget ic = cw->composite.children[i]; /* Get child's preferred width. */ if (ic != instigator) { XtQueryGeometry (ic, NULL, &reply); pref_width = (reply.request_mode & CWWidth) ? reply.width : ic->core.width; } else { pref_width = ic->core.width ; } detail_width = Max(detail_width, pref_width - /* remove the horiz indent */ (cw->container.first_column_width - ic->core.x)); } } } /**** compute the ideal height */ for (i = 0; i < cw->composite.num_children; i++) { Widget ic = cw->composite.children[i]; XtWidgetGeometry reply; if (!XtIsManaged(ic)) continue ; num_managed ++ ; /* ask for preferred height and baseline to the kid */ XmWidgetGetBaselines(ic, &baselines, &line_count); if (!line_count) continue ; /* store the first baseline and height under */ if (!baseline_first) { baseline_first = baselines[0]; /* negative so that it gives 0 below, so that it doesn't count in the max */ height_under_prec = -baseline_first ; } interspace = height_under_prec + baselines[0] ; interspace_max = Max(interspace_max, interspace); /* Get child's preferred height. */ XtQueryGeometry (ic, NULL, &reply); pref_height = (reply.request_mode & CWHeight) ? reply.height : ic->core.height; height_under_prec = pref_height - baselines[0] ; XtFree((char*) baselines); } /* now sum up everything */ height = baseline_first + interspace_max * (num_managed-1) + height_under_prec ; /*** do not set non null dimensions */ if (*width_ret == 0) *width_ret = cw->container.first_column_width + detail_width + cw->grid.margin_width ; if (*height_ret == 0) *height_ret = height + 2*cw->grid.margin_height; /*** set it back to 0, a getvalueshook will provide the real information */ if (fcw_set) cw->container.first_column_width = 0 ; } /************************************************************************ * GetDefaultFirstColumnWidth ************************************************************************/ /*ARGSUSED*/ static Dimension GetDefaultFirstColumnWidth( ExmContainerWidget cw, Dimension first_column_width) { Dimension width ; Cardinal i ; XmContainerItemDataRec cont_item_data ; XmContainerItemTrait cont_item_trait ; /* Get the max icon width + indent of all managed kids */ /* deal with icon_header outside container first */ if (cw->container.icon_header && XtIsManaged(cw->container.icon_header)) { /* start with header's icon width. */ cont_item_trait = (XmContainerItemTrait) XmeTraitGet((XtPointer) XtClass(cw->container.icon_header), XmQTcontainerItem) ; cont_item_data.valueMask = ContItemIconWidth ; cont_item_trait->getValues(cw->container.icon_header, &cont_item_data); first_column_width = Max(first_column_width, cw->grid.margin_width + cont_item_data.icon_width) ; } for (i = 0; i < cw->composite.num_children; i++) { Widget ic = cw->composite.children[i]; ExmGridConstraint glc = ExmGridCPart (ic); if (!XtIsManaged(ic)) continue ; /* if the child has the ContItem trait, use its icon_width, othersize, use it's width */ cont_item_trait = (XmContainerItemTrait) XmeTraitGet((XtPointer) XtClass(ic), XmQTcontainerItem) ; if (cont_item_trait) { cont_item_data.valueMask = ContItemIconWidth ; cont_item_trait->getValues(ic, &cont_item_data); width = cont_item_data.icon_width ; } else { width = ic->core.width ; } /* the inner cell margin width plays the outline indentation role in this example widget */ first_column_width = Max (first_column_width, cw->grid.margin_width + width + glc->grid_margin_width_within_cell); } return first_column_width ; } /************************************************************************ * GetDefaultDetailCount ************************************************************************/ /*ARGSUSED*/ static Cardinal GetDefaultDetailCount( ExmContainerWidget cw, Cardinal detail_count) { Cardinal i ; XmContainerItemDataRec cont_item_data ; XmContainerItemTrait cont_item_trait ; /* Get the max detail_count of all managed kids */ /* deal with icon_header outside container first */ if (cw->container.icon_header && XtIsManaged(cw->container.icon_header)) { /* start with header's detail_count */ cont_item_trait = (XmContainerItemTrait) XmeTraitGet((XtPointer) XtClass(cw->container.icon_header), XmQTcontainerItem) ; /* icon headert always has the trait */ cont_item_data.valueMask = ContItemDetailCount ; cont_item_trait->getValues(cw->container.icon_header, &cont_item_data); detail_count = Max(detail_count, cont_item_data.detail_count) ; } for (i = 0; i < cw->composite.num_children; i++) { Widget ic = cw->composite.children[i]; if (!XtIsManaged(ic)) continue ; /* if the child has the ContItem trait, use its detail_count */ cont_item_trait = (XmContainerItemTrait) XmeTraitGet((XtPointer) XtClass(ic), XmQTcontainerItem) ; if (cont_item_trait) { cont_item_data.valueMask = ContItemDetailCount ; cont_item_trait->getValues(ic, &cont_item_data); detail_count = Max (detail_count, cont_item_data.detail_count); } } return detail_count ; } /**************************************************************************** * * GetDefaultTabList * (XmNwidth-2*XmNmarginWidth-XmNfirstColumnWidth)/XmNdetailOrderCount * ***************************************************************************/ static XmTabList GetDefaultTabList( ExmContainerWidget cw, Cardinal detail_order_count) { XmTabList default_tablist = NULL ; /* if the Container has a valid size, a default tablist of size detail_order_count shall be returned in detail_tablist. The tabs in this tablist shall be equal to: (XmNwidth-2*XmNmarginWidth-XmNfirstColumnWidth) /XmNdetailOrderCount If XmNwidth is not yet valid, a NULL detail_tablist is returned, so that the icon can concat all its details and get a reasonable size. */ if (cw->core.width) { Dimension tab_size = 0 ; if ((cw->core.width > (2*cw->grid.margin_width + cw->container.first_column_width)) && detail_order_count) { tab_size = (cw->core.width - 2*cw->grid.margin_width - cw->container.first_column_width) / detail_order_count ; default_tablist = GetDumbTabList(tab_size, detail_order_count); } /* else return NULL as well */ } return default_tablist ; } /**************************************************************************** * * GetDumbTabList * fixed space - lazy allocation .do not deallocate the returned value * ***************************************************************************/ static XmTabList GetDumbTabList( Dimension tab_size, Cardinal asked_num_tab) { static int Num_tab = 0 ; static XmTab * Tab_pool = NULL ; static XmTabList Tab_list = NULL ; Cardinal i, prev_num_tab = Num_tab ; if (Num_tab < asked_num_tab) { Num_tab = asked_num_tab ; Tab_pool = (XmTab*) XtRealloc((char*)Tab_pool, Num_tab*sizeof(XmTab)); } /* create more tabs */ for (i=prev_num_tab; icontainer.layout_type == XmDETAIL) { if (cw->container.detail_order_count != 0) { containerData->detail_order_count = cw->container.detail_order_count ; containerData->detail_order = cw->container.detail_order ; } else { /* take the max detail count and return NULL for the detail_order, so that the icon takes a default order */ if (containerData->valueMask & ContDetailOrder) { containerData->detail_order_count = GetDefaultDetailCount(cw, 0); containerData->detail_order = NULL ; } } } else { containerData->detail_order_count = 0 ; containerData->detail_order = NULL ; } /**** if the resource firstColumnWidth is set, use it, otherwise, default it */ if (cw->container.layout_type == XmDETAIL) { if (cw->container.first_column_width) containerData->first_column_width = cw->container.first_column_width ; else /* don't bother computing it if not asked */ if (containerData->valueMask & ContFirstColumnWidth) { /* set the container resource temporarily */ cw->container.first_column_width = containerData->first_column_width = GetDefaultFirstColumnWidth(cw, containerData->first_column_width) ; fcw_set = True ; } } else if (cw->container.layout_type == XmSPATIAL) containerData->first_column_width = 0; /**** if detail_tablist has been set, use it, else compute a default */ if (cw->container.detail_tablist) containerData->detail_tablist = cw->container.detail_tablist ; else /* go find a default only if needed */ if (containerData->valueMask & ContDetailTabList) { containerData->detail_tablist = GetDefaultTabList(cw, containerData->detail_order_count); } /**** get a value for this one - kinda random, just to test */ if (cw->manager.navigation_type == XmTAB_GROUP) containerData->selection_mode = XmNORMAL_MODE ; else containerData->selection_mode = XmADD_MODE ; /**** just to try out the trait protocol */ if (cw->container.select_color == WhitePixelOfScreen(XtScreen(w))) containerData->valueMask &= ~ContSelectColor ; else containerData->select_color = cw->container.select_color ; /*** set first_column_width back to 0, a getvalueshook will provided the real information */ if (fcw_set) cw->container.first_column_width = 0 ; } /***************************************************************************** * * ExmCreateContainer: * Called by an application. * ****************************************************************************/ Widget ExmCreateContainer ( Widget parent, char *name, ArgList arglist, Cardinal argcount ) { /* This is a convenience function to instantiate an ExmContainer widget. */ return (XtCreateWidget (name, exmContainerWidgetClass, parent, arglist, argcount)); }