/***********************************************************************/ /* Open Visualization Data Explorer */ /* (C) Copyright IBM Corp. 1989,1999 */ /* ALL RIGHTS RESERVED */ /* This code licensed under the */ /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */ /***********************************************************************/ #include #include "UIConfig.h" /* System includes go after UIConfig.h */ #include #include #include #include #include #include "defines.h" #include "Application.h" #include "TextPopup.h" boolean TextPopup::ClassInitialized = FALSE; String TextPopup::DefaultResources[] = { ".popupButton.labelString: ...", ".popupButton.recomputeSize: True", NULL }; void TextPopup::initInstanceData() { this->popupMenu = NULL; this->popupButton = NULL; this->textField = NULL; this->setTextCallback = NULL; this->changeTextCallback = NULL; this->callbackData = NULL; this->callbacksEnabled = FALSE; } TextPopup::TextPopup() : UIComponent("textPopup") { this->initInstanceData(); } TextPopup::TextPopup(const char *name) : UIComponent(name) { this->initInstanceData(); } TextPopup::~TextPopup() { } void TextPopup::initialize() { if (!TextPopup::ClassInitialized) { TextPopup::ClassInitialized = TRUE; this->setDefaultResources(theApplication->getRootWidget(), TextPopup::DefaultResources); } } // // The event handler needs to work with a timer proc so that the pane // can be either spring loaded or sticky. It's only sticky if its popped up // from a ButtonRelease event. But you must be able to popup from a ButtonPress // event so that the person isn't required to click extra times. // extern "C" void TextPopup_ButtonEH(Widget w, XtPointer client, XEvent *e, Boolean *ctd) { TextPopup *dialog = (TextPopup *)client; XmMenuPosition(dialog->popupMenu , (XButtonPressedEvent *)e); if (e->type == ButtonRelease) XtManageChild(dialog->popupMenu); else XtAppAddTimeOut (theApplication->getApplicationContext(), 100, (XtTimerCallbackProc)XtManageChild, (XtPointer)dialog->popupMenu); } extern "C" void TextPopup_ItemSelectCB(Widget widget, XtPointer clientData, XtPointer callData) { ASSERT(clientData); TextPopup *dialog = (TextPopup*) clientData; dialog->itemSelectCallback(XtName(widget)); } extern "C" void TextPopup_ActivateTextCB(Widget widget, XtPointer clientData, XtPointer callData) { ASSERT(clientData); TextPopup *dialog = (TextPopup*) clientData; ASSERT(dialog->callbacksEnabled); char *v = XmTextGetString(widget); dialog->activateTextCallback(v, dialog->callbackData); XtFree(v); } extern "C" void TextPopup_ValueChangedTextCB(Widget widget, XtPointer clientData, XtPointer callData) { ASSERT(clientData); TextPopup *dialog = (TextPopup*) clientData; ASSERT(dialog->callbacksEnabled); char *v = XmTextGetString(widget); dialog->valueChangedTextCallback(v, dialog->callbackData); XtFree(v); } Widget TextPopup::createTextPopup(Widget parent, const char **items, int nitems, SetTextCallback stc, ChangeTextCallback ctc, void *callData) { ASSERT(!this->getRootWidget()); this->initialize(); this->setTextCallback = stc; this->changeTextCallback = ctc; this->callbackData = callData; Widget form = XtVaCreateWidget(this->name,xmFormWidgetClass, parent, NULL); this->setRootWidget(form); this->textField = XtVaCreateManagedWidget("textField", xmTextWidgetClass,form, XmNleftAttachment, XmATTACH_FORM, XmNleftOffset, 0, XmNtopAttachment, XmATTACH_FORM, XmNtopOffset, 0, NULL); Widget button = XtVaCreateManagedWidget("popupButton", xmPushButtonWidgetClass,form, #if 00 XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, this->textField, XmNleftOffset, 10, #else XmNrightAttachment, XmATTACH_FORM, XmNrightOffset, 0, #endif XmNtopAttachment, XmATTACH_FORM, XmNtopOffset, 3, // Center on text widget NULL); this->popupButton = button; XtUninstallTranslations(button); #if 11 XtVaSetValues(this->textField, XmNrightAttachment, XmATTACH_WIDGET, XmNrightWidget, button, XmNrightOffset, 10, NULL); #endif // // Get rid of any existing tranlstions on the label // if (nitems > 0) { // // Disable motif's attempts to pop the menu pane up for us because // if we disable the button later on, them motif will do a grab and // not pop up the pane, which hoses your session. Perhaps there is // a better way to do this disabling? // Arg args[2]; XtSetArg (args[0], XmNmenuPost, "Shift"); this->popupMenu = XmCreatePopupMenu(form, "popupMenu", args, 1); int i; for(i = 0; i < nitems; i++) { XmString xmstring = XmStringCreateSimple((char*)items[i]); Widget wid = XtVaCreateManagedWidget (items[i], xmPushButtonWidgetClass,this->popupMenu, XmNrecomputeSize, True, XmNlabelString, xmstring, NULL); XmStringFree(xmstring); XtAddCallback(wid, XmNactivateCallback, (XtCallbackProc)TextPopup_ItemSelectCB, (XtPointer)this); } XtAddEventHandler(button, ButtonPressMask|ButtonReleaseMask, False, (XtEventHandler)TextPopup_ButtonEH, (XtPointer)this); } else { XtSetSensitive(button,False); } this->enableCallbacks(); this->manage(); return this->getRootWidget(); } // // De/Install callbacks for the text widget. // boolean TextPopup::enableCallbacks(boolean enable) { if (this->callbacksEnabled == enable) return this->callbacksEnabled; this->callbacksEnabled = enable; ASSERT(this->getRootWidget() && this->textField); if (!enable) { XtRemoveCallback(this->textField, XmNactivateCallback, (XtCallbackProc)TextPopup_ActivateTextCB, (XtPointer)this); XtRemoveCallback(this->textField, XmNvalueChangedCallback, (XtCallbackProc)TextPopup_ValueChangedTextCB, (XtPointer)this); } else { XtAddCallback(this->textField, XmNactivateCallback, (XtCallbackProc)TextPopup_ActivateTextCB, (XtPointer)this); XtAddCallback(this->textField, XmNvalueChangedCallback, (XtCallbackProc)TextPopup_ValueChangedTextCB, (XtPointer)this); } return !enable; } char *TextPopup::getText() { return XmTextGetString(this->textField); } void TextPopup::setText(const char *value, boolean doActivate) { XmTextSetString(this->textField, (char*)value); if (doActivate) XtCallCallbacks(this->textField,XmNactivateCallback, this); } void TextPopup::itemSelectCallback(const char *value) { this->setText(value, TRUE); } void TextPopup::activateTextCallback(const char *value, void *callData) { if (this->setTextCallback) this->setTextCallback(this, value, callData); } void TextPopup::valueChangedTextCallback(const char *value, void *callData) { if (this->changeTextCallback) this->changeTextCallback(this, value, callData); }