2 * Copyright (c) 1996 Barton P. Miller
4 * We provide the Paradyn Parallel Performance Tools (below
5 * described as Paradyn") on an AS IS basis, and do not warrant its
6 * validity or performance. We reserve the right to update, modify,
7 * or discontinue this software at any time. We shall have no
8 * obligation to supply such updates or modifications or any other
9 * form of support to you.
11 * This license is for research uses. For such uses, there is no
12 * charge. We define "research use" to mean you may freely use it
13 * inside your organization for whatever purposes you see fit. But you
14 * may not re-distribute Paradyn or parts of Paradyn, in any form
15 * source or binary (including derivatives), electronic or otherwise,
16 * to any other organization or entity without our permission.
18 * (for other uses, please contact us at paradyn@cs.wisc.edu)
20 * All warranties, including without limitation, any warranty of
21 * merchantability or fitness for a particular purpose, are hereby
24 * By your use of Paradyn, you understand and agree that we (or any
25 * other person or entity with proprietary rights in Paradyn) are
26 * under no obligation to provide either maintenance services,
27 * update services, notices of latent defects, or correction of
28 * defects for Paradyn.
30 * Even if advised of the possibility of such damages, under no
31 * circumstances shall we (or any other person or entity with
32 * proprietary rights in the software licensed hereunder) be liable
33 * to you or any third party for direct, indirect, or consequential
34 * damages of any character regardless of type of action, including,
35 * without limitation, loss of profits, loss of use, loss of good
36 * will, or computer failure or malfunction. You agree to indemnify
37 * us (and any other person or entity with proprietary rights in the
38 * software licensed hereunder) for any and all liability it may
39 * incur to third parties resulting from your use of Paradyn.
43 // new search history graph user interface, along the lines
44 // of the new where axis user interface
48 /* Revision 1.18 1997/09/24 19:21:16 tamches
49 /* XFontStruct --> Tk_Font
51 * Revision 1.17 1997/01/15 00:13:41 tamches
52 * removed some warnings
54 * Revision 1.16 1996/08/16 21:07:11 tamches
55 * updated copyright for release 1.1
57 * Revision 1.15 1996/05/01 20:55:08 tamches
59 * change interface to configNode a bit
61 * Revision 1.14 1996/05/01 14:07:59 naim
62 * Multiples changes in UI to make call to requestNodeInfoCallback async.
65 * Revision 1.13 1996/04/16 18:37:33 karavan
66 * fine-tunification of UI-PC batching code, plus addification of some
67 * Ari-like verbification commentification.
69 * Revision 1.12 1996/04/13 04:39:49 karavan
70 * better implementation of batching for edge requests
72 * Revision 1.11 1996/04/09 19:25:13 karavan
73 * added batch mode to cut down on shg redraw time.
75 * Revision 1.10 1996/03/10 23:20:51 hollings
76 * Mad sure all assert statements were in { } blocks. odd compiler problem
79 * Revision 1.9 1996/03/08 00:21:20 tamches
80 * added support for hidden nodes
82 * Revision 1.8 1996/02/15 23:10:01 tamches
83 * added proper support for why vs. where axis refinement
91 #include "DictionaryLite.h"
93 #include "util/h/DictionaryLite.h"
97 #include "performanceConsultant.thread.h" // for struct shg_node_info
98 // shg test program doesn't touch this stuff
101 #include "where4tree.h"
102 #include "graphicalPath.h"
104 #include "shgConsts.h"
105 #include "shgRootNode.h" // contrast with rootNode.h, the where axis root node class
109 // These are needed by shgRootNode:
110 static Tk_Font theRootItemFontStruct, theRootItemShadowFontStruct;
111 static Tk_Font theListboxItemFontStruct, theListboxItemShadowFontStruct;
113 static vector<Tk_3DBorder> rootItemTk3DBordersByStyle;
114 // array[shgRootNode::evaluationState]
115 static vector<Tk_3DBorder> listboxItemTk3DBordersByStyle;
116 // array[shgRootNode::evaluationState]
117 static GC rootItemInactiveTextGC, rootItemActiveTextGC,
118 rootItemInactiveShadowTextGC, rootItemActiveShadowTextGC;
119 static GC listboxInactiveItemGC, listboxActiveItemGC,
120 listboxInactiveShadowItemGC, listboxActiveShadowItemGC;
121 static GC whyRefinementRayGC;
122 static GC whereRefinementRayGC;
123 static GC listboxRayGC;
125 // this appears to be the WRONG class for the following vrbles:
126 static int listboxBorderPix; // 3
127 static int listboxScrollBarWidth; // 16
129 // These ugly variables keep track of a button press (and possible hold-down)
130 // in scrollbar-up/down or pageup/pagedown region. They are not used for
131 // press (and possible hold-down) on the scrollbar slider
132 bool nonSliderButtonCurrentlyPressed; // init to false
133 whereNodeGraphicalPath<shgRootNode>::pathEndsIn nonSliderButtonPressRegion;
134 Tk_TimerToken buttonAutoRepeatToken;
135 where4tree<shgRootNode> *nonSliderCurrentSubtree;
136 int nonSliderSubtreeCenter; // WARNING: what if an expansion takes place during a drag (can happen with shg, tho not where axis)!
137 int nonSliderSubtreeTop; // WARNING: what if an expansion takes place during a drag (can happen with shg, tho not where axis)!
139 // Analagous to above; used only for scrollbar slider
140 simpSeq<unsigned> slider_scrollbar_path;
141 // why don't we keep track of left/top, etc.? Because in the SHG, things
142 // can expand at any time --- even when one is sliding a scrollbar. Hence,
143 // screen locations can change. Hence it is safest to go with this slower approach.
144 int slider_initial_yclick;
145 int slider_initial_scrollbar_slider_top;
146 // WARNING: what if an expansion takes place during a drag (can happen
147 // with shg, tho not where axis)!
148 where4tree<shgRootNode> *slider_currently_dragging_subtree;
149 // rechecked at each use
151 where4tree<shgRootNode> *rootPtr;
152 dictionary_lite<unsigned, where4tree<shgRootNode> *> hash;
153 // associative array: shg-node-id --> its corresponding data node
154 dictionary_lite<where4tree<shgRootNode> *, where4tree<shgRootNode> *> hash2;
155 // associative array: shg-node --> its parent
156 dictionary_lite<unsigned, vector< where4tree<shgRootNode>* > > shadowNodeHash;
157 // associative array: shg-node-id --> list of shadow nodes
158 // An entry exists in this dictionary _only_ if shadow node(s) exist
160 where4TreeConstants consts; // yuck
161 shgConsts theShgConsts;
162 int thePhaseId; // new
166 string horizSBName; // tk window name
167 string vertSBName; // tk window name
169 int nominal_centerx; // actual centerx = nominal_centerx + horizScrollBarOffset
170 int horizScrollBarOffset; // always <= 0
171 int vertScrollBarOffset; // always <= 0
173 string currItemLabelName; // tk window name
174 whereNodeGraphicalPath<shgRootNode> lastItemUnderMousePath;
175 int lastItemUnderMouseX, lastItemUnderMouseY;
177 // values of "tunable constants" saying which node types should be hidden:
178 bool hideTrueNodes, hideFalseNodes, hideUnknownNodes, hideNeverSeenNodes;
179 bool hideActiveNodes, hideInactiveNodes;
180 bool hideShadowNodes;
182 void resizeScrollbars();
184 bool set_scrollbars(int absolute_x, int relative_x,
185 int absolute_y, int relative_y,
187 // returns true iff any sb changes were made.
188 // moves cursor if warpPointer is true
190 whereNodeGraphicalPath<shgRootNode> point2path(int x, int y) const;
192 void processNonSliderButtonPress(whereNodeGraphicalPath<shgRootNode> &);
193 static void nonSliderButtonRelease(ClientData cd, XEvent *);
194 static void nonSliderButtonAutoRepeatCallback(ClientData cd);
196 static void sliderMouseMotion(ClientData cd, XEvent *eventPtr);
197 static void sliderButtonRelease(ClientData cd, XEvent *eventPtr);
199 void rethink_entire_layout(bool isCurrShg) {
202 rootPtr->recursiveDoneAddingChildren(consts, false); // false --> don't resort
203 rethink_nominal_centerx();
207 adjustHorizSBOffset();
208 adjustVertSBOffset();
212 bool state2hidden(shgRootNode::evaluationState, bool active,
215 bool recursiveUpdateHiddenNodes(where4tree<shgRootNode> *ptr);
216 bool changeHiddenNodesBase(bool isCurrShg);
217 // called by changeHiddenNodes.
220 void rethink_nominal_centerx();
222 static unsigned hashFunc(const unsigned &id) {return id;}
223 // needed by the hash table class
224 static unsigned hashFunc2(where4tree<shgRootNode>* const &id) {
225 return id->getNodeData().getId();
227 static unsigned hashFuncShadow(const unsigned &id) {return id;}
231 // These routines are needed by shgRootNode:
232 static Tk_Font getRootItemFontStruct(bool shadow) {
234 return theRootItemShadowFontStruct;
236 return theRootItemFontStruct;
238 static Tk_Font getListboxItemFontStruct(bool shadow) {
240 return theListboxItemShadowFontStruct;
242 return theListboxItemFontStruct;
244 static Tk_3DBorder getRootItemTk3DBorder(shgRootNode::evaluationState theEvalStyle) {
245 unsigned styleIndex = theEvalStyle;
246 return rootItemTk3DBordersByStyle[styleIndex];
248 static GC getRootItemTextGC(bool active, bool shadow) {
251 return rootItemActiveShadowTextGC;
253 return rootItemActiveTextGC;
255 return rootItemInactiveShadowTextGC;
257 return rootItemInactiveTextGC;
259 static GC getListboxItemGC(bool active, bool shadow) {
262 return listboxActiveShadowItemGC;
264 return listboxActiveItemGC;
266 return listboxInactiveShadowItemGC;
268 return listboxInactiveItemGC;
270 static Tk_3DBorder getListboxItemTk3DBorder(shgRootNode::evaluationState theStyle) {
271 unsigned styleIndex = theStyle;
272 return listboxItemTk3DBordersByStyle[styleIndex];
274 static GC getGCforListboxRay(shgRootNode::refinement theRefinement) {
275 if (theRefinement == shgRootNode::ref_undefined) {
276 assert("undefined refinement" && false);
277 } else if (theRefinement == shgRootNode::ref_why)
278 return whyRefinementRayGC;
279 else if (theRefinement == shgRootNode::ref_where)
280 return whereRefinementRayGC;
282 assert("unknown refinement" && false); abort();
284 static GC getGCforNonListboxRay(shgRootNode::refinement theRefinement) {
285 if (theRefinement == shgRootNode::ref_undefined) {
286 assert("undefined refinement" && false);
287 } else if (theRefinement == shgRootNode::ref_why)
288 return whyRefinementRayGC;
289 else if (theRefinement == shgRootNode::ref_where)
290 return whereRefinementRayGC;
292 assert("unknown refinement" && false); abort();
296 Tcl_Interp *interp, Tk_Window theTkWindow,
297 const string &iHorizSBName, const string &iVertSBName,
298 const string &iCurrItemLabelName,
299 bool iHideTrue, bool iHideFalse, bool iHideUnknown, bool iHideNever,
300 bool iHaveActive, bool iHideInactive, bool iHideShadow);
301 ~shg() {delete rootPtr;}
303 int getPhaseId() const {return thePhaseId;}
304 Tk_Window getTkWindow() {
305 // a little hack needed for XWarpPointer
306 return consts.theTkWindow;
309 void initializeStaticsIfNeeded();
311 // the return values of the next 2 routines will be <= 0
312 int getVertSBOffset() const {return vertScrollBarOffset;}
313 int getHorizSBOffset() const {return horizScrollBarOffset;}
315 // These routines return true iff a change was made; they don't redraw:
316 bool adjustHorizSBOffset(float newFirstFrac);
317 bool adjustHorizSBOffsetFromDeltaPix(int deltapix);
318 bool adjustHorizSBOffset(); // obtains first pix from actual tk sb
320 bool adjustVertSBOffset(float newFirstFrac);
321 bool adjustVertSBOffsetFromDeltaPix(int deltapix);
322 bool adjustVertSBOffset(); // obtains first pix from actual tk sb
324 int getTotalVertPixUsed() const {return rootPtr->entire_height(consts);}
325 int getTotalHorizPixUsed() const {return rootPtr->entire_width(consts);}
327 int getVisibleVertPix() const {return Tk_Height(consts.theTkWindow);}
328 int getVisibleHorizPix() const {return Tk_Width(consts.theTkWindow);}
330 void draw(bool doubleBuffer, bool isXsynchOn) const;
331 void resize(bool rethinkScrollbars); // pass true iff we are currently displayed shg
333 bool softScrollToEndOfPath(const whereNodePosRawPath &thePath);
334 // Like the above routine, but always scrolls to the last item in the path.
336 void recursiveRethinkLayout() {
337 rootPtr->recursiveDoneAddingChildren(consts, false); // don't resort
340 void processSingleClick(int x, int y);
341 void processMiddleClick(int x, int y);
342 bool processDoubleClick(int x, int y);
343 // // returns true iff a complete redraw is needed
344 // void processShiftDoubleClick(int x, int y);
345 // void processCtrlDoubleClick(int x, int y);
347 enum changeType{ct_true, ct_false, ct_unknown, ct_never, ct_active, ct_inactive,
349 bool changeHiddenNodes(bool newHideTrue, bool newHideFalse, bool newHideUnknown,
350 bool newHideNeverSeen, bool newHideActive,
351 bool newHideInactive, bool newHideShadow,
353 // Returns true iff any changes.
354 bool changeHiddenNodes(changeType, bool hide, bool isCurrShg);
355 // Like above routine but just changes 1 trait
357 // The following are very high-level routines; they tend to correspond
358 // with shg-related igen calls in UI.I:
359 void addNode(unsigned id, bool iActive, shgRootNode::evaluationState iEvalStyle,
360 const string &label, const string &fullInfo,
361 bool rootNodeFlag, bool isCurrShg);
362 // unless we are adding the root node, this routine generally doesn't
363 // require a redraw, because the new node won't (and shouldn't) show up
364 // until a corresponding addEdge() call connects this new node to the rest
366 enum configNodeResult {noChanges, benignChanges, changesInvolvingJustExpandedness,
367 changesInvolvingHideness};
368 configNodeResult configNode(unsigned id, bool active, shgRootNode::evaluationState,
369 bool isCurrShg, bool rethinkIfNecessary);
370 // Does not redraw, but may rethink layout and/or hide-ness.
371 // Note: a change from "tentatively-true" to
372 // (anything else) will un-expand the node, leading to a massive layout
373 // rethinkification. Other changes are more simple -- simply changing the color
375 bool inactivateAll(bool isCurrShg);
376 // returns true iff any changes were made. Note that in the "usual" case,
377 // the only thing that will happen is the fg color of nodes will change.
378 // _However_, if some tunable like "hideInactiveNodes" is set, then massive
379 // rethinkifications are a possibility.
381 void addEdge(unsigned fromId, unsigned toId,
382 shgRootNode::refinement, // why vs. where refinement.
383 const char *label, // only used for shadow nodes; else NULL
385 bool rethinkFlag); // if false, avoids rethinkification
386 // The evaluationState param decides whether to explicitly expand
387 // the "to" node. Rethinks the entire layout of the shg
390 void nodeInformation(unsigned nodeId, const shg_node_info &theNodeInfo);
391 // In response to a middle-mouse-click...
392 // the shg test program doesn't implement this stuff