📄 xmcombo.c
字号:
Parent = XtWindow((Widget) w); /* Suche nach dem Dekorationsfenster des Window-Managers */ do { AWindow = Parent; XQueryTree(XtDisplay((Widget) w), AWindow, &Root, &Parent, &Children, &NumChildren); XFree((char *) Children); } while ( Parent != Root ); return AWindow;} /* GetDecorationWindow *//* -------------------------------------------------------------------- * Eine Combo-Box aus dem Wege raeumen... * Momentan muessen wir hier nur den Cursor wieder los werden sowie * eventuell reservierte Pixmaps. * Ups -- natuerlich muss auch wieder der Callback entfernt werden, * der noch an der Shell haengt. */static void Destroy(XmComboBoxWidget w){/* fprintf(stderr, "Destroy: %08X\n", w->core.window);*/ if ( w->combobox.ConvertBitmapToPixmap ) XFreePixmap(XtDisplay((Widget) w), w->combobox.LabelPixmap); if ( w->combobox.ConvertBitmapToPixmapInsensitive ) XFreePixmap(XtDisplay((Widget) w), w->combobox.LabelInsensitivePixmap); if ( w->combobox.PendingFocusOut ) XtRemoveWorkProc(w->combobox.WorkProcID); XtRemoveEventHandler(w->combobox.MyNextShell, StructureNotifyMask | FocusChangeMask, True, (XtEventHandler) ShellCallback, (XtPointer) w);} /* Destroy *//* --------------------------------------------------------------------------- * Ueberpruefe, ob fuer die Ressource "DropDownOffset" ein gueltiger Wert vom * Benutzer angegeben wurde. Diese Ressource gibt an, wie weit die Drop-Down- * Liste nach rechts gegenueber dem Eingabefeld eingerueckt sein soll. Wenn * hierfuer ein negativer Wert angegeben ist, so berechne statt dessen einen * Standardwert: dieser entspricht der Breite der Pfeilschaltflaeche, was * optisch ganz gut wirkt (jedenfall nach meinem Dafuerhalten). */static void CheckDropDownOffset(XmComboBoxWidget w){ if ( w->combobox.DropDownOffset < 0 ) { XtWidgetGeometry ArrowGeom; XtQueryGeometry(w->combobox.ArrowCtrl, NULL, &ArrowGeom); w->combobox.DropDownOffset = ArrowGeom.width; }} /* CheckDropDownOffset *//* -------------------------------------------------------------------- * Berechne die voreinzustellende Groesse, die diese Combo-Box be- * sitzen muss, um ausreichenden Raum fuer das Eingabefeld und den * Pfeil rechts daneben zur Verfuegung zu stellen. Bei einer * editierbaren Combo-Box ist zwischen dem Eingabefeld und dem Pfeil * noch ein Angst-Rasen von der halben Breite eines Pfeiles vorhanden. * Wird das Listenfeld staendig dargestellt, so entfallen sowohl Pfeil * als auch der Angstrasen, dafuer muss aber die Hoehe des Listenfelds * beruecksichtigt werden. */static void DefaultGeometry(XmComboBoxWidget w, Dimension *TotalWidth, Dimension *TotalHeight, Dimension *EditCtrlWidth, Dimension *LabelCtrlWidth){ XtWidgetGeometry EditGeom, ArrowGeom, LabelGeom, ListGeom; XtQueryGeometry(w->combobox.EditCtrl, NULL, &EditGeom); XtQueryGeometry(w->combobox.ArrowCtrl, NULL, &ArrowGeom); XtQueryGeometry(w->combobox.LabelCtrl, NULL, &LabelGeom); /* * Soll die Pfeilschaltflaeche quadratisch, praktisch, gut sein? */ if ( w->combobox.SquareArrow ) ArrowGeom.width = ArrowGeom.height; else ArrowGeom.width = (ArrowGeom.height * 4) / 5; /* * Zuerst einmal ein paar einfache Werte ermitteln und zurueckgeben... */ *TotalHeight = EditGeom.height; *EditCtrlWidth = EditGeom.width; *LabelCtrlWidth = LabelGeom.width; /* * Ermittele nun die Breite, welche die Combobox benoetigt. Je nach- * dem, ob das Eingabefeld oder die Liste breiter sind, wird der * entsprechende Wert genommen. Diese Auswahl zwischen der Breite von * Eingabefeld und Liste findet aber nur statt, wenn die Liste auch * wirklich staendig sichtbar ist. Waehrend der Initialisierung hat * allerdings XmNcolumns, so dass in diesem Moment die List nicht * mehr die Breite kontrollieren kann! */ if ( w->combobox.StaticList ) { /* * Beachte: Frage nicht die Listbox, sondern das ScrolledWindow, * in welchem die Liste eingebettet ist. */ CheckDropDownOffset(w); XtQueryGeometry(XtParent(w->combobox.ListCtrl), NULL, &ListGeom); if ( w->combobox.InInit ) { *TotalWidth = EditGeom.width; } else { if ( EditGeom.width < (Dimension) (ListGeom.width + w->combobox.DropDownOffset) ) *TotalWidth = ListGeom.width + w->combobox.DropDownOffset; else *TotalWidth = EditGeom.width; } *TotalHeight += ListGeom.height; } else { /* * Das Listenfeld interessiert uns hier nicht. Degegen sollte noch * die Breite fuer den Pfeil und ein evtl. Angstrasen beachtet * werden. */ *TotalWidth = EditGeom.width + ArrowGeom.width; if ( w->combobox.Editable && w->combobox.ArrowSpacingOn ) *TotalWidth += ArrowGeom.width/2; } /* * Vergiss nicht, auch noch ein evtl. sichtbares Schriftfeld zu berueck- * sichtigen! */ if ( w->combobox.ShowLabel ) *TotalWidth += LabelGeom.width; } /* DefaultGeometry *//* -------------------------------------------------------------------- * Anhand eines Widgets ermittele darueber die Screennummer desjenigen * Screens, auf dem das Widget erscheint. * Parameter: * w betroffenes Widget. * Ergebnis: * Nummer desjenigen Screens, auf dem das Widget angezeigt wird. */static int WidgetToScreen(Widget w){ Screen *screen; Display *display; int NumScreens, i; screen = XtScreen(w); NumScreens = ScreenCount(XtDisplay(w)); display = DisplayOfScreen(screen); for ( i = 0; i < NumScreens; ++i ) if ( ScreenOfDisplay(display, i) == screen ) return i; XtError("WidgetToScreen: data structures are destroyed."); return 0; /* to avoid a compiler warning */} /* WidgetToScreen *//* -------------------------------------------------------------------- * Positioniere die DropDown-Liste (soweit sie natuerlich auch momentan * sichtbar ist) so auf dem Bildschirm, dass sie sich unterhalb des * Eingabefeldes anschliesst. */static void DoDropDownLayout(XmComboBoxWidget w){ Position abs_x, abs_y; Dimension ArrowWidth, ListWidth, ListHeight; Dimension ScreenHeight, LabelWidth; XWindowChanges WindowChanges; /* * etwa nicht sichtbar ?!! Oder etwa immer sichtbar ?!! * Dann sind wir jetzt sofort fertig. */ if ( !w->combobox.ListVisible || w->combobox.StaticList ) return; /* * Finde zuerst einmal heraus, wo wir uns denn auf dem Bildschirm be- * finden sollen... Beachte dabei auch, dass eventuell die Liste zu schmal * werden koennte und gib' ihr dann ggf. eine Mindestbreite, damit es * keinen core-Dump gibt. */ XtVaGetValues(w->combobox.ArrowCtrl, XmNwidth, &ArrowWidth, NULL); XtTranslateCoords((Widget) w, 0, w->core.height, &abs_x, &abs_y); CheckDropDownOffset(w); ListWidth = w->core.width - w->combobox.DropDownOffset - 2; abs_x += w->combobox.DropDownOffset; if ( w->combobox.ShowLabel ) { XtVaGetValues(w->combobox.LabelCtrl, XmNwidth, &LabelWidth, NULL); ListWidth -= LabelWidth; abs_x += LabelWidth; } if ( ListWidth < 20 ) ListWidth = 20; XtVaGetValues(XtParent(w->combobox.ListCtrl), XmNheight, &ListHeight, NULL); /* * Hier ueberpruefen wir noch, ob die Liste unten aus dem Bildschirm * herausfallen wuerde. In dem Fall klappen wir die Liste oberhalb des * Eingabefeldes auf. */ ScreenHeight = DisplayHeight(XtDisplay((Widget) w), WidgetToScreen((Widget) w)); if ( abs_y + ListHeight + 2 > ScreenHeight ) { int y; y = ((int) abs_y) - ListHeight - w->core.height - 1; if ( y < 0 ) y = 0; abs_y = (Position) y; } XtConfigureWidget(w->combobox.PopupShell, abs_x, abs_y, ListWidth, ListHeight, 1); /* * So...das hier dient der Kosmetik: hier sorgen wir dafuer, dass die * Liste auch wirklich immer direkt ueber der ComboBox innerhalb des * Fensterstapels schwebt. Siehe dazu auch die Erlaeuterungen und An- * merkungen in GetDecorationWindow(). */ if ( XtIsRealized((Widget) w) ) { WindowChanges.sibling = GetDecorationWindow(w); WindowChanges.stack_mode = Above; XReconfigureWMWindow(XtDisplay((Widget) w), XtWindow(w->combobox.PopupShell), WidgetToScreen(w->combobox.PopupShell), CWSibling | CWStackMode, &WindowChanges); }} /* DoDropDownLayout *//* -------------------------------------------------------------------- * Naja... diese Routine scheint ja bereits zu einer Institution beim * Schreiben von Composite-Widgets geworden zu sein. * * Hier beim ComboBox-Widget ist die Aufgabe ziemlich einfach: es * genuegt, die Eingabezeile und den Pfeil-Button entsprechend inner- * halb des ComboBox-Widgets zu plazieren. Seit allerdings noch das * Textlabel hinzukommt, wird's langsam aufwendiger. Nun ja - da sich * das Listenfeld wahlweise auch statisch einblenden laesst, ist nun * noch mehr zu beruecksichtigen, wenn die Kinder-Widgets an ihre * Plaetze geschoben werden. */static void DoLayout(XmComboBoxWidget w){ Dimension EditCtrlWidth, ArrowCtrlWidth, LabelCtrlWidth; Dimension ComboBoxHeight; Dimension BorderWidth; Dimension HighlightThickness; Position EditX; XtVaGetValues(w->combobox.ArrowCtrl, XmNheight, &ArrowCtrlWidth, NULL); if ( !w->combobox.SquareArrow ) ArrowCtrlWidth = (ArrowCtrlWidth * 4) / 5; XtVaGetValues(w->combobox.LabelCtrl, XmNwidth, &LabelCtrlWidth, NULL); /* * In Abhaengigkeit davon, ob die ComboBox editierbar ist und ob das * Listenfeld staendig sichtbar sein soll, hier die Breite einzelner * Widgets bestimmen. */ if ( w->combobox.StaticList ) { ComboBoxHeight = w->combobox.EditCtrl->core.height; EditCtrlWidth = w->core.width; } else { ComboBoxHeight = w->core.height; EditCtrlWidth = w->core.width - ArrowCtrlWidth; if ( w->combobox.Editable && w->combobox.ArrowSpacingOn ) EditCtrlWidth -= ArrowCtrlWidth/2; } /* Beruecksichtige noch ein evtl. ebenfalls anzuzeigendes Schriftfeld * neben dem Eingabefeld. */ if ( w->combobox.ShowLabel ) { EditX = LabelCtrlWidth; EditCtrlWidth -= LabelCtrlWidth; } else EditX = 0; if ( EditCtrlWidth < 20 ) EditCtrlWidth = 20;/* Plaziere nun das Eingabefeld... */ XtVaGetValues(w->combobox.EditCtrl, XmNborderWidth, &BorderWidth, XmNhighlightThickness, &HighlightThickness, NULL); XtConfigureWidget(w->combobox.EditCtrl, EditX, 0, EditCtrlWidth, ComboBoxHeight, BorderWidth);/* ...und nun den Pfeil... */ XtVaGetValues(w->combobox.ArrowCtrl, XtNborderWidth, &BorderWidth, NULL); XtConfigureWidget(w->combobox.ArrowCtrl, w->core.width-ArrowCtrlWidth, HighlightThickness, ArrowCtrlWidth, ComboBoxHeight - 2 * HighlightThickness, BorderWidth);/* ...und ggf. das Textlabel. */ if ( w->combobox.ShowLabel ) { XtVaGetValues(w->combobox.LabelCtrl, XmNborderWidth, &BorderWidth, NULL); XtConfigureWidget(w->combobox.LabelCtrl, 0, 0, LabelCtrlWidth, ComboBoxHeight, BorderWidth); }/* Falls da noch die Liste herumgurkt... */ if ( w->combobox.StaticList ) { Dimension Width, Height; if ( w->core.height > ComboBoxHeight ) Height = w->core.height - ComboBoxHeight; else Height = 10; if ( w->core.width > (Dimension)(ArrowCtrlWidth + EditX) ) Width = w->core.width - ArrowCtrlWidth - EditX; else Width = 10; XtConfigureWidget(XtParent(w->combobox.ListCtrl), EditX + ArrowCtrlWidth, ComboBoxHeight, Width, Height, 0); } else if ( w->combobox.ListVisible ) DoDropDownLayout(w); } /* DoLayout *//* -------------------------------------------------------------------- * Pappi fragt nach, wie gross wir denn sein wollen. * Die hier benutzte Vorgehensweise zur Ermittlung der Groesse: * Sobald der Vater uns eine Breite (oder aber Hoehe) vorschlaegt, * die fuer uns eigentlich zu klein ist, meckern wir und schlagen
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -