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