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 #include <Xm/Xm.h>
13 #include <Xm/ScrolledW.h>
14 #include <X11/cursorfont.h>
15 
16 #ifdef DXD_WIN
17 #include "../widgets/XmDX.h"
18 #else
19 #include "XmDX.h"
20 #endif
21 #include "WorkSpace.h"
22 #include "WorkSpaceInfo.h"
23 #include "Application.h"
24 #include "List.h"
25 #include "ListIterator.h"
26 #include <../widgets/WorkspaceW.h>
27 
28 
29 String WorkSpace::DefaultResources[] =
30 {
31      ".traversalOn:		True",
32      ".marginWidth:		0",
33      ".marginHeight:		0",
34      ".allowResize:		True",
35      ".sensitive:		True",
36      ".allowMovement:		True",
37      ".allowOverlap:		False",
38      ".button1PressMode:    	False",
39      ".resizePolicy:        	RESIZE_GROW",
40      ".accentPolicy:        	ACCENT_BACKGROUND",
41      ".horizontalDrawGrid:  	DRAW_HASH",
42      ".verticalDrawGrid:    	DRAW_HASH",
43      ".horizontalAlignment: 	ALIGNMENT_CENTER",
44      ".verticalAlignment:   	ALIGNMENT_CENTER",
45      ".inclusionPolicy:     	INCLUDE_ALL",
46      ".outlineType:         	OUTLINE_EACH",
47      ".selectionPolicy:     	EXTENDED_SELECT",
48      ".sortPolicy:          	ALIGNMENT_BEGINNING",
49      NUL(char*)
50 
51 };
52 
WorkSpace(const char * name,Widget parent,WorkSpaceInfo * wsinfo)53 WorkSpace::WorkSpace( const char* name, Widget parent, WorkSpaceInfo *wsinfo) :
54 			UIComponent(name)
55 {
56     this->info = wsinfo;
57     this->parent = parent;
58     this->info->associateWorkSpace(this);
59     this->activeManyPlacements = 0;
60 }
61 
~WorkSpace()62 WorkSpace::~WorkSpace()
63 {
64     if (this->isRoot())
65 	XtRemoveEventHandler(this->parent, StructureNotifyMask, False,
66 	    (XtEventHandler)WorkSpace_ResizeHandlerEH, (XtPointer)this);
67     if (this->info)
68 	this->info->associateWorkSpace(NULL);
69 }
70 
manage()71 void WorkSpace::manage()
72 {
73      if (!this->getRootWidget())
74 	this->initializeRootWidget(FALSE);
75 
76      this->UIComponent::manage();
77 }
78 
initializeRootWidget(boolean fromFirstIntanceOfADerivedClass)79 void WorkSpace::initializeRootWidget(boolean fromFirstIntanceOfADerivedClass)
80 {
81     int              w, h, n;
82     Arg              warg[20];
83     boolean	     prevent_overlap;
84 
85     if (fromFirstIntanceOfADerivedClass) {
86         ASSERT(theApplication);
87         this->setDefaultResources(theApplication->getRootWidget(),
88                                   WorkSpace::DefaultResources);
89     }
90     n = 0;
91     XtSetArg(warg[n],XmNwidth, this->info->getWidth()); n++;
92     XtSetArg(warg[n],XmNheight, this->info->getHeight()); n++;
93 
94     //
95     // Info from grid spec
96     //
97     WorkSpaceInfo *info = this->info;
98     info->getGridSpacing(w,h);
99     prevent_overlap = info->getPreventOverlap();
100     XtSetArg(warg[n],XmNgridWidth, w); n++;
101     XtSetArg(warg[n],XmNgridHeight, h); n++;
102     XtSetArg(warg[n],XmNsnapToGrid,
103 			(info->isGridActive() ? True : False)); n++;
104     XtSetArg(warg[n],XmNverticalAlignment,   info->getGridYAlignment()); n++;
105     XtSetArg(warg[n],XmNhorizontalAlignment, info->getGridXAlignment()); n++;
106 
107     XtSetArg(warg[n],XmNhorizontalDrawGrid,
108 	(info->getGridXAlignment() == XmALIGNMENT_NONE) &&
109 	(info->getGridYAlignment() == XmALIGNMENT_CENTER) ?
110 		XmDRAW_NONE : XmDRAW_HASH); n++;
111     XtSetArg(warg[n],XmNverticalDrawGrid,
112 	(info->getGridYAlignment() == XmALIGNMENT_NONE) &&
113 	(info->getGridXAlignment() == XmALIGNMENT_CENTER) ?
114 		XmDRAW_NONE : XmDRAW_HASH); n++;
115     XtSetArg(warg[n], XmNpreventOverlap, prevent_overlap); n++;
116 
117 
118     this->setRootWidget(
119         XtCreateWidget
120             (name,
121              xmWorkspaceWidgetClass,
122              this->parent,
123 	     warg,
124 	     n));
125 
126     this->display = XtDisplay(this->getRootWidget());
127 
128     XtAddCallback(this->getRootWidget(),
129                       XmNdefaultActionCallback,
130                       (XtCallbackProc)WorkSpace_DefaultActionCB,
131                       (XtPointer)this);
132 
133     XtAddCallback(this->getRootWidget(),
134                   XmNbackgroundCallback,
135                   (XtCallbackProc)WorkSpace_BackgroundCB,
136                   (XtPointer)this);
137 
138     XtAddCallback(this->getRootWidget(),
139                   XmNselectionCallback,
140                   (XtCallbackProc)WorkSpace_SelectionCB,
141                   (XtPointer)this);
142 
143     XtAddCallback(this->getRootWidget(),
144                   XmNpositionChangeCallback,
145                   (XtCallbackProc)WorkSpace_PosChangeCB,
146                   (XtPointer)this);
147 
148     //
149     // Record initial lineDrawing, overlap, and manhattan values so that
150     // they can be toggle later, on behalf of pages.
151     //
152     this->saveWorkSpaceParams(NUL(WorkSpace*));
153 
154     if (this->isRoot())
155 	XtAddEventHandler(this->parent, StructureNotifyMask, False,
156 	    (XtEventHandler)WorkSpace_ResizeHandlerEH, (XtPointer)this);
157 }
158 
WorkSpace_PosChangeCB(Widget widget,XtPointer clientData,XtPointer callData)159 extern "C" void WorkSpace_PosChangeCB(Widget widget,
160                 XtPointer clientData,
161                 XtPointer callData)
162 {
163     WorkSpace *ws = (WorkSpace*) clientData;
164     ws->doPosChangeAction(widget, callData);
165 }
166 
WorkSpace_DefaultActionCB(Widget widget,XtPointer clientData,XtPointer callData)167 extern "C" void WorkSpace_DefaultActionCB(Widget widget,
168                 XtPointer clientData,
169                 XtPointer callData)
170 {
171     WorkSpace *ws = (WorkSpace*) clientData;
172     ws->doDefaultAction(widget, callData);
173 }
174 
WorkSpace_BackgroundCB(Widget widget,XtPointer clientData,XtPointer calldata)175 extern "C" void WorkSpace_BackgroundCB(Widget widget,
176                 XtPointer clientData,
177                 XtPointer calldata)
178 {
179     WorkSpace *ws = (WorkSpace*) clientData;
180 
181     ws->doBackgroundAction(widget,calldata);
182 }
183 
WorkSpace_SelectionCB(Widget widget,XtPointer clientData,XtPointer calldata)184 extern "C" void WorkSpace_SelectionCB(Widget widget,
185                 XtPointer clientData,
186                 XtPointer calldata)
187 {
188     WorkSpace *ws = (WorkSpace*) clientData;
189 
190     ws->doSelectionAction(widget,calldata);
191 }
192 
193 
setCursor(int cursorType)194 void WorkSpace::setCursor(int cursorType)
195 {
196     Widget widget;
197     int    n;
198     Arg    arg[5];
199 
200 
201        static int _type[] =
202     {
203         XC_ul_angle,
204         XC_fleur,
205         XC_watch,
206         XC_left_ptr
207     };
208 
209     static Cursor _cursor[4] =
210     {
211         NUL(Cursor),
212         NUL(Cursor),
213         NUL(Cursor),
214         NUL(Cursor)
215     };
216 
217     widget = this->getRootWidget();
218     ASSERT(widget);
219 
220     n = 0;
221     XtSetArg(arg[n], XmNbutton1PressMode, True); n++;
222     XtSetValues(widget, arg, n);
223 
224     if (!XtIsRealized(widget))
225 	return;
226 
227     ASSERT(cursorType >= 0 AND cursorType < 4);
228 
229     if (_cursor[cursorType] == NUL(Cursor))
230     {
231         _cursor[cursorType] =
232             XCreateFontCursor(XtDisplay(widget), _type[cursorType]);
233     }
234 
235     XDefineCursor(XtDisplay(widget), XtWindow(widget), _cursor[cursorType]);
236 
237     XFlush(XtDisplay(widget));
238 }
239 
240 //
241 // reset the WorkSpace cursor to the default.
242 //
resetCursor()243 void WorkSpace::resetCursor()
244 {
245     Widget widget;
246     int n;
247     Arg arg[2];
248 
249     widget = this->getRootWidget();
250     ASSERT(widget);
251 
252     n = 0;
253     XtSetArg(arg[n], XmNbutton1PressMode, False); n++;
254     XtSetValues(widget, arg, n);
255 
256     if (!XtIsRealized(widget))
257 	return;
258 
259     XUndefineCursor(XtDisplay(widget), XtWindow(widget));
260 
261     XFlush(XtDisplay(widget));
262 }
263 
264 //
265 // Set the Height and Width of the work space.
266 //
setWidth(int val)267 void WorkSpace::setWidth(int val)
268 {
269     this->info->setWidth(val);
270     if (!this->getRootWidget())
271 	return;
272     XtVaSetValues(this->getRootWidget(),XmNwidth, val, NULL);
273 }
setHeight(int val)274 void WorkSpace::setHeight(int val )
275 {
276     this->info->setHeight(val);
277     if (!this->getRootWidget())
278 	return;
279     XtVaSetValues(this->getRootWidget(),XmNheight, val, NULL);
280 }
setWidthHeight(int width,int height)281 void WorkSpace::setWidthHeight(int width, int height )
282 {
283     this->info->setWidth(width);
284     this->info->setHeight(height);
285     if (!this->getRootWidget())
286 	return;
287     XtVaSetValues(this->getRootWidget(),
288 		  XmNwidth, width,
289 		  XmNheight, height,
290 		  NULL);
291 }
getMaxWidthHeight(int * w,int * h)292 void WorkSpace::getMaxWidthHeight(int *w, int *h)
293 {
294     XmWorkspaceGetMaxWidthHeight(this->getRootWidget(), w, h);
295 }
WorkSpace_ResizeHandlerEH(Widget widget,XtPointer clientdata,XEvent *,Boolean *)296 extern "C" void WorkSpace_ResizeHandlerEH(Widget widget,
297                               XtPointer clientdata,
298                               XEvent*,
299 			      Boolean*)
300 
301 {
302     WorkSpace * ws = (WorkSpace*) clientdata;
303 
304     ws->resize();
305 }
306 
307 //
308 // Install the new grid in the WorkSpace
309 //
installInfo(WorkSpaceInfo * new_info)310 void WorkSpace::installInfo(WorkSpaceInfo *new_info)
311 {
312     int n, w,h;
313     Arg warg[20];
314     boolean prevent_overlap;
315 
316     if (new_info) {
317 	this->info->disassociateWorkSpace();
318         this->info = new_info;
319 	this->info->associateWorkSpace(this);
320     }
321 
322     prevent_overlap = this->info->getPreventOverlap();
323 
324     //
325     // Install the grid info in the work space.
326     //
327     n = 0;
328     this->info->getGridSpacing(w,h);
329     XtSetArg(warg[n],XmNgridWidth, w); n++;
330     XtSetArg(warg[n],XmNgridHeight, h); n++;
331     XtSetArg(warg[n],XmNsnapToGrid,
332 			(this->info->isGridActive() ? True : False)); n++;
333     XtSetArg(warg[n],XmNverticalAlignment,   this->info->getGridYAlignment()); n++;
334     XtSetArg(warg[n],XmNhorizontalAlignment, this->info->getGridXAlignment()); n++;
335 
336     XtSetArg(warg[n],XmNhorizontalDrawGrid,
337 	(this->info->getGridXAlignment() == XmALIGNMENT_NONE) &&
338 	(this->info->getGridYAlignment() == XmALIGNMENT_CENTER) ?
339 		XmDRAW_NONE : XmDRAW_HASH); n++;
340     XtSetArg(warg[n],XmNverticalDrawGrid,
341 	(this->info->getGridYAlignment() == XmALIGNMENT_NONE) &&
342 	(this->info->getGridXAlignment() == XmALIGNMENT_CENTER) ?
343 		XmDRAW_NONE : XmDRAW_HASH); n++;
344 
345     this->info->getXYSize(&w,&h);
346     XtSetArg(warg[n],XmNwidth, w); n++;
347     XtSetArg(warg[n],XmNheight, h); n++;
348     XtSetArg(warg[n],XmNpreventOverlap, prevent_overlap); n++;
349     XtSetValues(this->getRootWidget(), warg, n);
350 }
351 //
352 // Optimized the work space for a bunch of placements
353 //
beginManyPlacements()354 void WorkSpace::beginManyPlacements()
355 {
356    ASSERT(this->getRootWidget());
357 
358    this->activeManyPlacements++;
359    if (this->activeManyPlacements == 1) {
360 	XtVaSetValues(this->getRootWidget(),
361 		XmNlineDrawingEnabled, False,
362 		XmNallowOverlap, True,
363 		NULL);
364     }
365 }
endManyPlacements()366 void WorkSpace::endManyPlacements()
367 {
368     ASSERT(this->getRootWidget());
369     this->activeManyPlacements--;
370     if (this->activeManyPlacements == 0) {
371 	Boolean overlap = this->wasAllowOverlap;
372 	Boolean drawing = this->wasLineDrawingEnabled;
373 	if (this->getRootWidget())
374 	    XtVaSetValues(this->getRootWidget(),
375 		XmNlineDrawingEnabled, drawing,
376 		XmNallowOverlap, overlap,
377 	    NULL);
378     }
379 }
380 
setPlacementCount(int count)381 void WorkSpace::setPlacementCount(int count)
382 {
383     boolean active = (count==0);
384     boolean was_active = (this->activeManyPlacements==0);
385     if (active != was_active) {
386 	Boolean overlap = (active?this->wasAllowOverlap:True);
387 	Boolean drawing = (active?this->wasLineDrawingEnabled:False);
388 	if (this->getRootWidget())
389 	    XtVaSetValues(this->getRootWidget(),
390 		XmNlineDrawingEnabled, drawing,
391 		XmNallowOverlap, overlap,
392 	    NULL);
393     }
394     this->activeManyPlacements = count;
395 }
396 
397 
398 //
399 // This logic is supplied by WorkSpaceRoot with the addition of workspace pages.
400 // This version of resize() is in use only for ControlPanelWorkSpace which isn't
401 // paged as of 12/96.  As soon as ControlPanelWorkSpace is converted to use
402 // WorkSpaceRoot and WorkSpacePage, WorkSpace::resize should become pure virtual.
403 //
resize()404 void WorkSpace::resize()
405 {
406     Dimension width, height;
407     Dimension sw_width, sw_height;
408     Dimension vsb_width, hsb_height;
409     int max_w, max_h;
410     Widget wid, vsb, hsb;
411     Widget widget = XtParent(XtParent(this->getRootWidget()));
412 
413     XmWorkspaceGetMaxWidthHeight(this->getRootWidget(), &max_w, &max_h);
414 
415     vsb_width = 0;
416     hsb_height = 0;
417     if(XmIsScrolledWindow(widget))
418     {
419 	Position x, y;
420 
421 	XtVaGetValues(widget,
422 		      XmNhorizontalScrollBar, &hsb,
423 		      XmNverticalScrollBar, &vsb,
424 		      NULL);
425 	XtVaGetValues(widget, XmNwidth, &sw_width, XmNheight, &sw_height, NULL);
426 
427 	//
428 	// Vertical ScrollBar
429 	//
430 	XtVaGetValues(vsb, XmNx, &x, XmNy, &y, NULL);
431 	if((x < sw_width) && (y < sw_height))
432 	    XtVaGetValues(vsb, XmNwidth, &vsb_width, NULL);
433 
434 	//
435 	// Horizontal ScrollBar
436 	//
437 	XtVaGetValues(hsb, XmNx, &x, XmNy, &y, NULL);
438 	if((x < sw_width) && (y < sw_height))
439 	    XtVaGetValues(hsb, XmNheight, &hsb_height, NULL);
440 
441     }
442 
443     if(XmIsScrolledWindow(widget))
444 	XtVaGetValues(widget, XmNclipWindow, &wid, NULL);
445     else
446 	wid = widget;
447 
448     XtVaGetValues(wid,
449 		  XmNwidth, &width,
450 		  XmNheight,&height,
451 		  NULL);
452 
453     width += vsb_width;
454     height += hsb_height;
455     this->setWidthHeight(MAX(width, max_w), MAX(height, max_h));
456 }
457 
458 //
459 // This will probably be supplied in a virtual version in a subclass unless
460 // there is some reason to have pages with different values.  The reason this
461 // routine is required is to make it convenient to have all WorkSpaces use the
462 // same values even though we can't make all WorkSpaces recognize the same
463 // Xdefault setting.  So we want to be able to install a parent's values into
464 // a page if that's what the subclass wants.
465 //
saveWorkSpaceParams(WorkSpace * ws)466 void WorkSpace::saveWorkSpaceParams(WorkSpace *ws)
467 {
468     Boolean overlap, drawing, manhattan;
469 
470     if (ws) {
471 	this->wasAllowOverlap = ws->wasAllowOverlap;
472 	this->wasLineDrawingEnabled = ws->wasLineDrawingEnabled;
473 	this->wasManhattanEnabled = ws->wasManhattanEnabled;
474 
475 	//
476 	// Deal with manhattanRoute in a special way.  We never toggle its value.
477 	// We normally turn on/off lineDrawing.  So if manhattanRoute wants to be
478 	// off, unset it now and don't ever touch it again.
479 	//
480 	if (!this->wasManhattanEnabled)
481 	    XtVaSetValues (this->getRootWidget(), XmNmanhattanRoute, False, NULL);
482     } else {
483 	XtVaGetValues(this->getRootWidget(),
484 	    XmNlineDrawingEnabled, &drawing,
485 	    XmNallowOverlap, &overlap,
486 	    XmNmanhattanRoute, &manhattan,
487 	NULL);
488 	this->wasAllowOverlap = overlap;
489 	this->wasLineDrawingEnabled = drawing;
490 	this->wasManhattanEnabled = manhattan;
491     }
492 }
493 
isEmpty(int x,int y,int width,int height)494 boolean WorkSpace::isEmpty (int x, int y, int width, int height)
495 {
496     return XmWorkspaceRectangleEmpty (this->getRootWidget(), x,y,width,height);
497 }
498