1 /***********************************************************************/
2 /* Open Visualization Data Explorer                                    */
3 /* (C) Copyright IBM Corp. 1989,1999                                   */
4 /* ALL RIGHTS RESERVED                                                 */
5 /* This code licensed under the                                        */
6 /*    "IBM PUBLIC LICENSE - Open Visualization Data Explorer"          */
7 /***********************************************************************/
8 
9 #include <dxconfig.h>
10 #include "../base/defines.h"
11 
12 
13 
14 
15 #include <Xm/Xm.h>
16 #include <Xm/BulletinB.h>
17 #include <Xm/Form.h>
18 #include <Xm/DrawingA.h>
19 #include <Xm/Label.h>
20 #include <Xm/DragDrop.h>
21 #include <X11/Xatom.h>
22 
23 
24 #include "XmUtility.h"
25 #include "Interactor.h"
26 #include "InteractorInstance.h"
27 #include "../widgets/WorkspaceW.h"
28 #include "../widgets/XmDX.h"
29 #include "ControlPanel.h"
30 #include "ControlPanelWorkSpace.h"
31 #include "Network.h"
32 #include "DXStrings.h"
33 #include "DXApplication.h"
34 
35 #include "ntractor.bm"
36 #include "ntractormask.bm"
37 
38 boolean Interactor::InteractorClassInitialized = FALSE;
39 Widget  Interactor::DragIcon;
40 
41 #if defined(aviion) || defined(alphax)
42 // This constant exists in ToggleInteractor.C also, so if you make a change
43 // then dupe it there.
44 #define XMSTRING_COMPARE_IS_BROKEN
45 #endif
46 
47 #define DXXOFFSET "DX_XOFFSET"
48 #define DXYOFFSET "DX_YOFFSET"
49 
50 //
51 // This is the value that specifies the default thickness of the white
52 // border around the interactor (not the decorators).
53 // Use the constant as a default value for HiLites.
54 //
55 // If you change HiLites either thru a change to OFFSET or a change to
56 // dxui.interactorHighlight, you also affect the size of the interactor.
57 #define OFFSET 2
58 static int HiLites = OFFSET + 1;
59 
60 String Interactor::DefaultResources[] =
61 {
62     "*borderWidth:			0",
63     ".shadowType:			SHADOW_OUT",
64     ".resizePolicy:			XmRESIZE_ANY",
65     "*interactive_form.resizePolicy:	XmRESIZE_ANY",
66     ".shadowThickness:			1",
67     ".marginWidth: 			1",
68     ".marginHeight: 			1",
69     ".interactor_label.marginWidth:	1",
70     ".interactor_label.marginHeight:	0",
71     ".interactor_label.marginLeft:	1",
72     ".interactor_label.marginBottom:	1",
73     ".interactor_label.marginTop:	1",
74     ".interactor_label.marginRight:	1",
75      NUL(char*)
76 };
77 
78 Dictionary* Interactor::DragTypeDictionary = new Dictionary;
79 
Interactor(const char * name,InteractorInstance * ii)80 Interactor::Interactor(const char * name, InteractorInstance *ii) :
81    WorkSpaceComponent(name, FALSE),
82    DXDragSource(PrintCPBuffer)
83 {
84     this->interactorInstance = ii;
85     this->label = this->customPart = NUL(Widget);
86     this->currentLayout = ii->isVerticalLayout()?WorkSpaceComponent::VerticalUnset:
87 	WorkSpaceComponent::HorizontalUnset;
88     this->drag_drop_wpid = 0;
89 }
90 
~Interactor()91 Interactor::~Interactor()
92 {
93     if (this->drag_drop_wpid) XtRemoveWorkProc(this->drag_drop_wpid);
94 }
95 
96 //
97 // Change any global attributes and then ask the derived class to
98 // change the attributes of the interactive part.
99 //
handleInteractorStateChange(InteractorInstance * src_ii,boolean major_change)100 void Interactor::handleInteractorStateChange(
101 			InteractorInstance *src_ii, boolean major_change)
102 {
103 int userw, userh, curw, curh;
104 
105     this->handleInteractivePartStateChange(src_ii, FALSE);
106 
107 #if 0
108    //
109    // If the current label is different from the new one, then set it.
110    // Otherwise don't since it may cause the Interactor 'flash' on the
111    // control panel.
112    // FIXME: should do the same filtering that this->setLabel() does.
113    //
114    XmString xms;
115    char *curr_label;
116    const char *new_label = this->interactorInstance->getInteractorLabel();
117    XtVaGetValues(this->label, XmNlabelString, &xms, NULL);
118    // The charset must match what was used when the XmString was created.
119    XmStringGetLtoR(xms, "bold", &curr_label);
120    if (!EqualString(curr_label,new_label))
121        this->setLabel(new_label, FALSE);
122    delete curr_label;
123    XmStringFree(xms);
124 #else
125    // setLabel does nothing if oldlabel == newlabel
126    const char *new_label = this->interactorInstance->getInteractorLabel();
127    this->setLabel(new_label, FALSE);
128 #endif
129 
130    //
131    // Remanage the interactor if the subclass'
132    // handleInteractivePartStateChange() method unmanaged it.
133    //
134    if (!this->isManaged())
135 	this->manage();
136 
137    //
138    // Growing and shrinking is a good thing, but don't get smaller than
139    // the most recent user specified dimensions.
140    //
141    if (this->isUserSizeSet()) {
142 	this->getUserDimensions (&userw, &userh);
143 	this->GetDimensions (this->getRootWidget(), &curh, &curw);
144 	if ((curh!=userh) || (curw!=userw)) {
145 	    Boolean avr = True, ahr = True;
146 	    curw = MAX(curw, userw); curh = MAX(curh, userh);
147 	    XtVaGetValues (this->getRootWidget(), XmNallowVerticalResizing, &avr,
148 		XmNallowHorizontalResizing, &ahr, NULL);
149 	    if (avr) this->setXYSize (UIComponent::UnspecifiedDimension, curh);
150 	    if (ahr) this->setXYSize (curw, UIComponent::UnspecifiedDimension);
151 	}
152    }
153 }
154 
155 
initialize()156 void Interactor::initialize()
157 {
158     //
159     // Initialize default resources (once only).
160     //
161     if (NOT Interactor::InteractorClassInitialized)
162     {
163         Interactor::InteractorClassInitialized = TRUE;
164 	Interactor::DragIcon =
165                 this->createDragIcon(ntractor_width, ntractor_height,
166                                      (char *)ntractor_bits,
167                                      (char *)ntractormask_bits);
168 
169 	HiLites = OFFSET + 1;
170 #if GOING_OVERBOARD
171 	Display *d = theApplication->getDisplay();
172 	char *cp = XGetDefault (d, "dxui", "interactorHighlight");
173 	// don't modify cp
174 	if ((cp) && (cp[0])) {
175 	    sscanf (cp, "%d", &HiLites);
176 	}
177 #endif
178 
179 	if ((theDXApplication->appAllowsRWConfig())&&
180 	    (theDXApplication->appAllowsSavingNetFile()) &&
181 	    (theDXApplication->appAllowsSavingCfgFile()) &&
182 	    (theDXApplication->appAllowsPanelEdit())) {
183 	    this->addSupportedType (Interactor::Modules, DXINTERACTORS, TRUE);
184 	}
185 	if (theDXApplication->appAllowsPanelEdit())
186 	    this->addSupportedType (Interactor::Trash, DXTRASH, FALSE);
187     }
188 }
189 
190 
setSelected(boolean state)191 void Interactor::setSelected (boolean state)
192 {
193 InteractorInstance *ii = this->interactorInstance;
194 
195     if (state) ii->setSelected();
196     else ii->clrSelected();
197     this->WorkSpaceComponent::setSelected(state);
198 }
199 
200 //
201 // Set the displayed label of the interactor
202 //
setLabel(const char * labelString,boolean)203 void Interactor::setLabel(const char *labelString, boolean )
204 {
205 XmStringContext cxt;
206 char *text, *tag;
207 XmStringDirection dir;
208 Boolean sep;
209 unsigned char rp;
210 int i, linesNew, linesOld;
211 XmString oldXmStr = NULL;
212 
213     if(NOT this->label)
214 	return;
215 
216     linesNew = linesOld = 1;
217     XtVaGetValues (this->label, XmNlabelString, &oldXmStr, NULL);
218     ASSERT(oldXmStr);
219 
220     char *filtered = WorkSpaceComponent::FilterLabelString (labelString);
221     for (i=0; filtered[i]!='\0'; i++) if (filtered[i]=='\n') linesNew++;
222 
223 #if !defined(XMSTRING_COMPARE_IS_BROKEN)
224     // For efficiency only
225     XmString tmpXmStr = XmStringCreateLtoR (filtered, "canvas");
226     if (XmStringCompare (tmpXmStr, oldXmStr)) {
227 	XmStringFree (tmpXmStr);
228 	if (filtered) delete filtered;
229 	XmStringFree(oldXmStr);
230 	return ;
231     }
232     XmStringFree (tmpXmStr);
233 #endif
234 
235     if (XmStringInitContext (&cxt, oldXmStr)) {
236 	while (XmStringGetNextSegment (cxt, &text, &tag, &dir, &sep)) {
237 	    if (sep) linesOld++;
238 	    XtFree(text);
239 	    if (tag) XtFree(tag);
240 	}
241 	XmStringFreeContext(cxt);
242     }
243     XmStringFree(oldXmStr);
244 
245     // toggle XmNresizePolicy so that the interactor doesn't snap back
246     // to a reasonable size.  If the old string is taller/shorter than the new string
247     // then let it change.
248 
249     if (linesNew == linesOld) {
250 	XtVaGetValues (this->getRootWidget(), XmNresizePolicy, &rp, NULL);
251 	XtVaSetValues (this->getRootWidget(), XmNresizePolicy, XmRESIZE_GROW, NULL);
252     } else {
253 	this->resetUserDimensions();
254     }
255 
256     if ((!filtered)||(!filtered[0])||(!strlen(filtered))) {
257         this->setBlankLabelLayout(TRUE);
258     } else {
259         this->setBlankLabelLayout(FALSE);
260 	this->WorkSpaceComponent::SetLabelResource(this->label, labelString);
261     }
262     delete filtered;
263 
264     if (linesNew == linesOld)
265 	XtVaSetValues (this->getRootWidget(), XmNresizePolicy, rp, NULL);
266 }
267 
268 void
openDefaultWindow()269 Interactor::openDefaultWindow() {this->interactorInstance->openSetAttrDialog();}
270 
271 //
272 // Build an interactor widget tree.
273 //
createInteractor()274 void Interactor::createInteractor()
275 {
276     int	                 n,x,y;
277     Arg	                 wargs[30];
278     const char		 *labelString;
279     Widget		 parent;
280     InteractorInstance   *ii = this->interactorInstance;
281 
282     if (NOT Interactor::InteractorClassInitialized) this->Interactor::initialize();
283 
284     this->workSpace = ii->getControlPanel()->getWorkSpace();
285     parent = this->workSpace->getRootWidget();
286     ASSERT(parent);
287 
288     //
289     // Create the outermost frame.
290     //
291     ii->getXYPosition(&x,&y);
292 
293     n = 0;
294     XtSetArg(wargs[n], XmNx, x); n++;
295     XtSetArg(wargs[n], XmNy, y); n++;
296     XtSetArg(wargs[n], XmNuserData, (XtPointer)ii); n++;
297     Widget standInRoot = XmCreateForm(parent, this->name, wargs, n);
298     this->setRootWidget(standInRoot);
299     this->setDragWidget(standInRoot);
300     this->setDragIcon(Interactor::DragIcon);
301     this->developerStyle = this->getControlPanel()->isDeveloperStyle();
302 
303 
304     //
305     // Restore width,height.  By checking allow{Vertical,Horizontal}Resizing
306     // we're ignoring dimensions which aren't user configurable.  That way
307     // we can read in .cfg files from other versions of dx without making
308     // crazy looking interactors.  We always get the space we need.
309     //
310     int	width = 0;
311     int height = 0;
312     ii->getXYSize(&width,&height);
313     Boolean avr = True, ahr = True;
314     XtVaGetValues (this->getRootWidget(),
315 	XmNallowVerticalResizing, &avr,
316 	XmNallowHorizontalResizing, &ahr,
317     NULL);
318     if ((!avr)||(!height)) height = UIComponent::UnspecifiedDimension;
319     if ((!ahr)||(!width)) width = UIComponent::UnspecifiedDimension;
320     if ((avr) || (ahr))
321 	this->setXYSize (width, height);
322 
323     n = 0;
324     if (this->currentLayout & WorkSpaceComponent::Vertical) {
325 	XtSetArg (wargs[n], XmNrightAttachment, XmATTACH_FORM); n++;
326 	XtSetArg (wargs[n], XmNrightOffset, HiLites); n++;
327 	XtSetArg (wargs[n], XmNbottomAttachment, XmATTACH_NONE); n++;
328     } else {
329 	XtSetArg (wargs[n], XmNrightAttachment, XmATTACH_NONE); n++;
330 	XtSetArg (wargs[n], XmNbottomAttachment, XmATTACH_FORM); n++;
331 	XtSetArg (wargs[n], XmNbottomOffset, HiLites); n++;
332     }
333     XtSetArg(wargs[n], XmNtopOffset, HiLites); n++;
334     XtSetArg(wargs[n], XmNtopAttachment, XmATTACH_FORM); n++;
335     XtSetArg(wargs[n], XmNleftOffset, HiLites); n++;
336     XtSetArg(wargs[n], XmNleftAttachment, XmATTACH_FORM); n++;
337     XtSetArg(wargs[n], XmNalignment, XmALIGNMENT_CENTER); n++;
338     XtSetArg(wargs[n], XmNuserData, this); n++;
339     this->label = XmCreateLabel(standInRoot, "interactor_label", wargs, n);
340     XtManageChild (this->label);
341     this->passEvents (this->label, TRUE);
342 
343     const char *new_label = this->interactorInstance->getInteractorLabel();
344     if ((new_label) && (new_label[0]))
345 	this->WorkSpaceComponent::SetLabelResource(this->label, new_label);
346 
347     if (this->currentLayout & WorkSpaceComponent::Vertical) {
348 	XtSetArg (wargs[n], XmNtopAttachment, XmATTACH_FORM); n++;
349 	XtSetArg (wargs[n], XmNleftAttachment, XmATTACH_FORM); n++;
350 	XtSetArg (wargs[n], XmNtopWidget, this->label); n++;
351 	XtSetArg (wargs[n], XmNleftOffset, HiLites); n++;
352     } else {
353 	XtSetArg (wargs[n], XmNtopOffset, HiLites); n++;
354 	XtSetArg (wargs[n], XmNtopAttachment, XmATTACH_FORM); n++;
355 	XtSetArg (wargs[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
356 	XtSetArg (wargs[n], XmNleftWidget, this->label); n++;
357     }
358     XtSetArg (wargs[n], XmNbottomAttachment, XmATTACH_FORM); n++;
359     XtSetArg (wargs[n], XmNbottomOffset, HiLites); n++;
360     XtSetArg (wargs[n], XmNrightAttachment, XmATTACH_FORM); n++;
361     XtSetArg (wargs[n], XmNrightOffset, HiLites); n++;
362     XtSetArg (wargs[n], XmNuserData, this); n++;
363     this->customPart = XmCreateForm(standInRoot, "interactive_form", wargs, n);
364     XtManageChild(this->customPart);
365     this->createInteractivePart(this->customPart);
366 
367     this->passEvents (this->customPart, FALSE);
368 
369     //
370     // Set the label after creating the interactive part in case the
371     // sub-class wants to override setLabel().
372     //
373     labelString = ii->getInteractorLabel();
374     ASSERT(labelString);
375     this->setLabel(labelString, FALSE);
376 
377     // Set to ! because must be sure the function does something.
378     this->currentLayout|= WorkSpaceComponent::NotSet;
379     this->layoutInteractor();
380 
381     //
382     // Register selection callback.
383     //
384     XmWorkspaceAddCallback (this->getRootWidget(), XmNselectionCallback,
385 	 (XtCallbackProc)Component_SelectWorkSpaceComponentCB, (void *)this);
386 
387     //
388     // Make sure the interactive part contains the correct initial value.
389     //
390     this->updateDisplayedInteractorValue();
391 
392     this->setAppearance (this->developerStyle);
393 
394     this->installResizeHandler();
395 
396     //
397     // Perform any actions that need to be done after the parent is managed.
398     //
399     this->completeInteractivePart();
400 
401     if ((avr)||(ahr))
402 	this->setUserDimensions (width, height);
403 }
404 
405 //
406 // Pass button and motion events through to the parent of w.
407 //
passEvents(Widget w,boolean dnd)408 void Interactor::passEvents(Widget w, boolean dnd)
409 {
410     this->WorkSpaceComponent::passEvents (w, dnd);
411     if (dnd) this->setDragWidget(w);
412 }
413 
414 
415 //
416 // O R I E N T A T I O N   O R I E N T A T I O N   O R I E N T A T I O N
417 // O R I E N T A T I O N   O R I E N T A T I O N   O R I E N T A T I O N
418 // O R I E N T A T I O N   O R I E N T A T I O N   O R I E N T A T I O N
419 // O R I E N T A T I O N   O R I E N T A T I O N   O R I E N T A T I O N
420 //
421 // It's no longer necessary to do arithmetic inside the Interactor.
422 // The original XmBulletinBoard implementation is replaced with an XmForm.
423 // So things lay themselves out and stay laid out.  The only quirky part is
424 // is the XmLabel widget which must be forced to the proper size the first
425 // time it appears on the screen.  When changing the layout simply change
426 // form attachments.
427 //
setBlankLabelLayout(boolean blank_label)428 void Interactor::setBlankLabelLayout(boolean blank_label)
429 {
430     if ((this->currentLayout & WorkSpaceComponent::NotSet) == 0) {
431 	if ((blank_label)&&
432 	    ((this->currentLayout & WorkSpaceComponent::BlankLabel)!=0)) return ;
433 	if ((!blank_label)&&
434 	    ((this->currentLayout & WorkSpaceComponent::BlankLabel)==0)) return ;
435     } else {
436 	if (blank_label) this->currentLayout|= WorkSpaceComponent::BlankLabel;
437 	else this->currentLayout&= ~WorkSpaceComponent::BlankLabel;
438 	return ;
439     }
440 
441     InteractorInstance *ii = this->interactorInstance;
442     if (blank_label) {
443 	ii->setVerticalLayout(TRUE);
444 	this->currentLayout|= WorkSpaceComponent::BlankLabel;
445 	this->layoutInteractor();
446     } else {
447 	this->currentLayout&= ~WorkSpaceComponent::BlankLabel;
448 	this->currentLayout|= WorkSpaceComponent::NotSet;
449 	this->layoutInteractor();
450     }
451 }
setVerticalLayout(boolean vertical)452 void Interactor::setVerticalLayout(boolean vertical)
453 {
454     if ((this->currentLayout & WorkSpaceComponent::NotSet) == 0) {
455 	if ((vertical)&&(this->currentLayout & WorkSpaceComponent::Vertical)) return ;
456 	if ((!vertical)&&(this->currentLayout & WorkSpaceComponent::Horizontal)) return ;
457     }
458 
459     this->WorkSpaceComponent::setVerticalLayout(vertical);
460     this->layoutInteractor();
461 }
462 
layoutInteractor()463 void Interactor::layoutInteractor()
464 {
465     this->resetUserDimensions();
466 
467     if (this->currentLayout & WorkSpaceComponent::BlankLabel)
468         this->layoutInteractorWithNoLabel();
469     else if (this->currentLayout & WorkSpaceComponent::Vertical)
470         this->layoutInteractorVertically();
471     else if (this->currentLayout & WorkSpaceComponent::Horizontal)
472         this->layoutInteractorHorizontally();
473     else
474 	ASSERT(0);
475     this->currentLayout&= ~WorkSpaceComponent::NotSet;
476 }
477 
478 
479 //
480 // WRT layoutInteractorHorizontally() and Vertically()...
481 // the order in which you make calls to set form constraints is important.
482 // If you change the order to can wind up with either error message to stderr,
483 // or a mess inside an interactor.  Be especially careful with margins.
484 //
485 
layoutInteractorHorizontally()486 void Interactor::layoutInteractorHorizontally()
487 {
488 boolean label_managed = XtIsManaged(this->label);
489 
490     if (!label_managed)  XtManageChild (this->label);
491 
492     //
493     // disconnect
494     //
495     XtVaSetValues (this->customPart,
496 	XmNtopAttachment, XmATTACH_NONE,
497     NULL);
498     XtVaSetValues (this->label,
499 	XmNrightAttachment, XmATTACH_NONE,
500     NULL);
501 
502     //
503     // reconnect
504     //
505     XtVaSetValues (this->customPart,
506 	XmNtopAttachment, XmATTACH_FORM,
507 	XmNleftAttachment, XmATTACH_WIDGET,
508 	XmNleftWidget, this->label,
509 	XmNtopOffset, HiLites,
510 	XmNleftOffset, 0,
511     NULL);
512     XtVaSetValues (this->label,
513 	XmNbottomAttachment, XmATTACH_FORM,
514 	XmNbottomOffset, HiLites,
515 	XmNleftOffset, HiLites,
516 	XmNtopOffset, HiLites,
517     NULL);
518 }
519 
layoutInteractorVertically()520 void Interactor::layoutInteractorVertically()
521 {
522 boolean label_managed = XtIsManaged(this->label);
523 
524     if (!label_managed)  {
525 	XtManageChild (this->label);
526     }
527 
528     //
529     // disconnect
530     //
531     XtVaSetValues (this->label,
532 	XmNbottomAttachment, XmATTACH_NONE,
533 	XmNbottomOffset, 0,
534     NULL);
535     XtVaSetValues (this->customPart,
536 	XmNleftAttachment, XmATTACH_NONE,
537 	XmNleftOffset, HiLites,
538 	XmNtopAttachment, XmATTACH_NONE,
539     NULL);
540 
541     //
542     // reconnect
543     //
544     XtVaSetValues (this->label,
545 	XmNrightAttachment, XmATTACH_FORM,
546 	XmNrightOffset, HiLites,
547     NULL);
548     XtVaSetValues (this->customPart,
549 	XmNtopAttachment, XmATTACH_WIDGET,
550 	XmNtopWidget, this->label,
551 	XmNtopOffset, 0,
552 	XmNleftAttachment, XmATTACH_FORM,
553     NULL);
554 }
555 
layoutInteractorWithNoLabel()556 void Interactor::layoutInteractorWithNoLabel()
557 {
558     //
559     // disconnect
560     //
561     XtVaSetValues (this->customPart,
562 	XmNtopAttachment, XmATTACH_NONE,
563     NULL);
564     if (XtIsManaged(this->label)) {
565 	XtUnmanageChild (this->label);
566 	XtVaSetValues (this->getRootWidget(), XmNheight, 0, NULL);
567     }
568 
569     //
570     // reconnect
571     //
572     XtVaSetValues (this->customPart,
573 	XmNleftAttachment, XmATTACH_FORM, XmNleftOffset, HiLites,
574 	XmNtopAttachment, XmATTACH_FORM, XmNtopOffset, HiLites,
575     NULL);
576 }
577 
578 // D R A G - N - D R O P --- R E L A T E D   S T U F F --- D R A G - N - D R O P
579 // D R A G - N - D R O P --- R E L A T E D   S T U F F --- D R A G - N - D R O P
580 // D R A G - N - D R O P --- R E L A T E D   S T U F F --- D R A G - N - D R O P
581 // D R A G - N - D R O P --- R E L A T E D   S T U F F --- D R A G - N - D R O P
582 //
583 // ...requires only that it be selected
584 //
decideToDrag(XEvent * xev)585 int Interactor::decideToDrag(XEvent *xev)
586 {
587     InteractorInstance *ii = this->interactorInstance;
588     if (!this->developerStyle) return DragSource::Abort;
589     if (!ii->selected) return DragSource::Inactive;
590 
591     Display *d = XtDisplay(this->getRootWidget());
592     Atom xoff = XInternAtom (d, DXXOFFSET, False);
593     Atom yoff = XInternAtom (d, DXYOFFSET, False);
594     Screen *screen = XtScreen(this->getRootWidget());
595     Window root = RootWindowOfScreen(screen);
596     int x = 0;
597     int y = 0;
598     ii->getXYPosition (&x, &y);
599     int minx = x;
600     int miny = y;
601     int junk;
602 
603     this->workSpace->getSelectedBoundingBox (&minx, &miny, &junk, &junk);
604 
605     int xoffset = x - minx;
606     int yoffset = y - miny;
607 
608     if (xev->type == ButtonPress) {
609 	xoffset+= xev->xbutton.x;
610 	yoffset+= xev->xbutton.y;
611     }
612 
613     XChangeProperty (d, root, xoff, XA_INTEGER, 32, PropModeReplace,
614 	(unsigned char*)&xoffset, 1);
615     XChangeProperty (d, root, yoff, XA_INTEGER, 32, PropModeReplace,
616 	(unsigned char*)&yoffset, 1);
617 
618     return DragSource::Proceed;
619 }
620 
621 //
622 // The header (which will not end up being part of the files) says
623 // "hostname:pid, net length = %d, cfg length = %d\n"
624 //
createNetFiles(Network * netw,FILE * netf,char * cfgfile)625 boolean Interactor::createNetFiles(Network *netw, FILE *netf, char *cfgfile)
626 {
627    netw->setCPSelectionOwner(this->getControlPanel());
628    return (boolean)this->DXDragSource::createNetFiles (netw, netf, cfgfile);
629 }
630 
631 //
632 // if the operation was a move and not a copy, then delete
633 // the original interactors.
634 //
dropFinish(long operation,int tag,unsigned char status)635 void Interactor::dropFinish (long operation, int tag, unsigned char status)
636 {
637     //
638     // Delete the atoms set up when starting the drag
639     //
640     Display *d = XtDisplay(this->getRootWidget());
641     Atom xoff_atom = XInternAtom (d, DXXOFFSET, True);
642     Atom yoff_atom = XInternAtom (d, DXYOFFSET, True);
643     Screen *screen = XtScreen(this->getRootWidget());
644     Window root = RootWindowOfScreen(screen);
645     if (xoff_atom != None)
646 	XDeleteProperty (d, root, xoff_atom);
647     if (yoff_atom != None)
648 	XDeleteProperty (d, root, yoff_atom);
649 
650 
651     // If the operation was a copy and the type was Trash,
652     // then treat it would be better to treat it like a move
653     // so that the user isn't required to use the Shift key.
654 
655     if (status) {
656 	if ((operation == XmDROP_MOVE) || (tag == Interactor::Trash)) {
657 	    //this->getControlPanel()->deleteSelectedInteractors();
658 	    XtAppContext apcxt = theApplication->getApplicationContext();
659 	    this->drag_drop_wpid = XtAppAddWorkProc (apcxt, Interactor_DragDropWP,
660 		    (XtPointer)this);
661 	}
662     }
663 }
664 
decodeDragType(int tag,char * a,XtPointer * value,unsigned long * length,long operation)665 boolean Interactor::decodeDragType (int tag,
666 	char * a, XtPointer *value, unsigned long *length, long operation)
667 {
668 boolean retVal;
669 
670     switch (tag) {
671 	case Interactor::Modules:
672 	    // this-convert() comes from DXDragSource and can't be overridden.
673 	    retVal = this->convert (this->getNetwork(), a, value, length, operation);
674 	    break;
675 
676 	// Don't do anything...  Just say OK.  this->dropFinish does the delete
677 	case Interactor::Trash:
678 	    retVal = TRUE;
679 
680 	    // dummy pointer
681 	    *value = (XtPointer)malloc(4);
682 	    *length = 4;
683 	    break;
684 
685 	default:
686 	    retVal = FALSE;
687 	    break;
688     }
689     return retVal;
690 }
691 
692 
693 // U T I L S   U T I L S   U T I L S   U T I L S   U T I L S   U T I L S
694 // U T I L S   U T I L S   U T I L S   U T I L S   U T I L S   U T I L S
695 // U T I L S   U T I L S   U T I L S   U T I L S   U T I L S   U T I L S
696 // U T I L S   U T I L S   U T I L S   U T I L S   U T I L S   U T I L S
697 // U T I L S   U T I L S   U T I L S   U T I L S   U T I L S   U T I L S
698 // U T I L S   U T I L S   U T I L S   U T I L S   U T I L S   U T I L S
isA(Symbol classname)699 boolean Interactor::isA(Symbol classname)
700 {
701     Symbol s = theSymbolManager->registerSymbol(ClassInteractor);
702     if (s == classname) return TRUE;
703     return this->WorkSpaceComponent::isA(classname);
704 }
705 
706 //
707 // Indicate that the interactor is selected.
708 //
indicateSelect(boolean selected)709 void Interactor::indicateSelect(boolean selected)
710 {
711     if (this->getRootWidget()) {
712 	XtVaSetValues(this->getRootWidget(),
713         	XmNselected, (selected ? True : False),
714 		NULL);
715     }
716 }
717 
getComponentHelpTopic()718 const char *Interactor::getComponentHelpTopic()
719 {
720     static char topic[100];
721     sprintf(topic, "%sInteractor",
722 		this->getNode()->getNameString());
723     return topic;
724 }
725 
GetUserData(Widget widget)726 void *GetUserData(Widget widget)
727 {
728     XtPointer data;
729     ASSERT(widget);
730     XtVaGetValues(widget, XmNuserData, &data, NULL);
731     return (data);
732 }
733 
getNetwork()734 Network *Interactor::getNetwork()
735 {
736     ASSERT(this->interactorInstance);
737     return this->interactorInstance->getNetwork();
738 }
getNode()739 Node *Interactor::getNode()
740 {
741     ASSERT(this->interactorInstance);
742     return this->interactorInstance->getNode();
743 }
getControlPanel()744 ControlPanel *Interactor::getControlPanel()
745 {
746     ASSERT(this->interactorInstance);
747     return this->interactorInstance->getControlPanel();
748 }
749 
Interactor_DragDropWP(XtPointer clientData)750 extern "C" Boolean Interactor_DragDropWP(XtPointer clientData)
751 {
752     Interactor* ntr = (Interactor*)clientData;
753     ntr->drag_drop_wpid = 0;
754     ntr->getControlPanel()->deleteSelectedInteractors();
755     return TRUE;
756 }
757