/***********************************************************************/ /* 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 #include #include "defines.h" #include "Application.h" #include "ToggleInteractor.h" #include "InteractorInstance.h" #include "InteractorStyle.h" #if defined(aviion) || defined(alphax) #define XMSTRING_COMPARE_IS_BROKEN #endif String ToggleInteractor::DefaultResources[] = { "*recomputeSize: True", "*toggleButton.shadowThickness: 0", "*toggleButton.selectColor: White", "*toggleButton.topAttachment: XmATTACH_FORM", "*toggleButton.leftAttachment: XmATTACH_FORM", "*toggleButton.rightAttachment: XmATTACH_FORM", "*toggleButton.bottomAttachment: XmATTACH_FORM", "*toggleButton.topOffset: 2", "*toggleButton.leftOffset: 2", "*toggleButton.rightOffset: 0", "*toggleButton.bottomOffset: 2", "*allowHorizontalResizing: True", NUL(char*) }; // // Splain: // Normally WorkSpaceComponent takes care of this stuff, but ToggleInteractors // are different because they get rid of the interactor label which means there // is no place left to click. The following translations connect the various // button clicks on workspace widget children including drag-n-drop. // I would rather put this stuff into DefaultResources but I could never find // the proper combination of line termination symbols. // String ToggleInteractor::WWTable = "\ Shift: select_w()\n\ Ctrl: select_w()\n\ ,: Arm() Select() Disarm()\n\ ,: select_w()\n\ (2+): select_w() release_w() select_w() release_w()\n\ : Arm()\n\ : Select() Disarm() release_w()\n\ : move_w()\n\ ~Shift: select_w() DragSource_StartDrag()\n\ Shift: DragSource_StartDrag()\n\ : release_w()\n\ "; XtTranslations ToggleInteractor::WWTranslations = 0; ToggleInteractor::ToggleInteractor(const char *name, InteractorInstance *ii) : Interactor(name,ii) { this->toggleButton = NULL; } // // Accepts value changes and reflects them into other interactors, cdbs // and off course the interactor node output. // extern "C" void ToggleInteractor_ToggleCB(Widget widget, XtPointer clientData, XtPointer callData) { ToggleInteractor *ti = (ToggleInteractor*)clientData; ASSERT(widget); ASSERT(ti); Boolean setting; XtVaGetValues(widget, XmNset, &setting, NULL); ti->toggleCallback(widget, setting, callData); } // // Build the toggle button and install the valueChange callback for it. // Widget ToggleInteractor::createInteractivePart(Widget form) { Arg wargs[20]; int n; n = 0; this->toggleButton = XtCreateManagedWidget("toggleButton", xmToggleButtonWidgetClass, form, wargs, n); XtAddCallback(this->toggleButton, XmNvalueChangedCallback, (XtCallbackProc)ToggleInteractor_ToggleCB, (XtPointer)this); XtManageChild(this->toggleButton); return this->toggleButton; } void ToggleInteractor::completeInteractivePart() { InteractorInstance *ii = this->interactorInstance; this->setLabel (ii->getInteractorLabel(), True); this->Interactor::setLabel("",FALSE); // // ::passEvents is not applied to the widget(s) in the interactor // which do the actual work i.e. the pushbuttons or togglebuttons. // The problem here is that there is no place on a toggle button to // click to do defaultAction because the border is so thin and there // is no label showing expect that which belongs to the toggle button. // So apply a translation to the togglebutton which sends double clicks // on the the parent. // if (!ToggleInteractor::WWTranslations) { ToggleInteractor::WWTranslations = XtParseTranslationTable(WWTable); } this->setDragWidget (this->toggleButton); ASSERT(ToggleInteractor::WWTranslations); XtOverrideTranslations (this->toggleButton, ToggleInteractor::WWTranslations); } void ToggleInteractor::handleInteractivePartStateChange(InteractorInstance *ii, boolean major_change) { this->updateDisplayedInteractorValue(); } // // Set the displayed label of the interactor and do a layout if // indicated to handle a significant change in label width. // We override the default to always set the toggle label instead // and set the interactor label to "". // void ToggleInteractor::setLabel( const char *labelString, boolean re_layout) { XmStringContext cxt; char *text, *tag; static char buf[1024]; XmStringDirection dir; Boolean sep; unsigned char rp; int i, linesNew, linesOld; XmString oldXmStr = NULL; if(NOT this->toggleButton) return; linesNew = linesOld = 1; XtVaGetValues (this->toggleButton, XmNlabelString, &oldXmStr, NULL); ASSERT(oldXmStr); char *filtered = WorkSpaceComponent::FilterLabelString (labelString); for (i=0; filtered[i]!='\0'; i++) if (filtered[i]=='\n') linesNew++; #if 0 // // FIXME // This piece of code should work, but it doesn't. The XmStringCompare always // returns false. The same code does work in Interactor::setLabel so I guess // something happens to an XmNlabelString setting inside a toggle button. // Way to go OSF. // #if !defined(XMSTRING_COMPARE_IS_BROKEN) // For efficiency only XmString tmpXmStr = XmStringCreateLtoR (filtered, "bold"); if (XmStringCompare (tmpXmStr, oldXmStr)) return ; XmStringFree (tmpXmStr); #endif #endif if (XmStringInitContext (&cxt, oldXmStr)) { while (XmStringGetNextSegment (cxt, &text, &tag, &dir, &sep)) { if (sep) linesOld++; XtFree(text); if (tag) XtFree(tag); } XmStringFreeContext(cxt); } XmStringFree(oldXmStr); // toggle XmNresizePolicy so that the interactor doesn't snap back // to a reasonable size. If the old string is taller/shorter than the new string // then let it change. XtVaGetValues (this->getRootWidget(), XmNresizePolicy, &rp, NULL); if (linesNew == linesOld) XtVaSetValues (this->getRootWidget(), XmNresizePolicy, XmRESIZE_GROW, NULL); else XtVaSetValues (this->getRootWidget(), XmNresizePolicy, XmRESIZE_ANY, NULL); //this->WorkSpaceComponent::setLabelResource(this->toggleButton, labelString); XmString xmstr = XmStringCreateLtoR (filtered, XmSTRING_DEFAULT_CHARSET); XtVaSetValues (this->toggleButton, XmNlabelString, xmstr, NULL); XmStringFree(xmstr); delete filtered; // // Re-layout the interactor in case the width has changed significantly // if (re_layout) this->layoutInteractor(); XtVaSetValues (this->getRootWidget(), XmNresizePolicy, rp, NULL); } // Don't do the normal things because there is no way // to change the layout of a toggle button. void ToggleInteractor::layoutInteractorVertically() { this->Interactor::layoutInteractorVertically(); } void ToggleInteractor::layoutInteractorHorizontally() { this->Interactor::layoutInteractorVertically(); }