XFontStruct --> Tk_Font
[dyninst.git] / paradyn / src / UIthread / shg.h
1 /*
2  * Copyright (c) 1996 Barton P. Miller
3  * 
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.
10  * 
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.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
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.
29  * 
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.
40  */
41
42 // shg.h
43 // new search history graph user interface, along the lines
44 // of the new where axis user interface
45 // Ariel Tamches
46
47 /* $Log: shg.h,v $
48 /* Revision 1.18  1997/09/24 19:21:16  tamches
49 /* XFontStruct --> Tk_Font
50 /*
51  * Revision 1.17  1997/01/15 00:13:41  tamches
52  * removed some warnings
53  *
54  * Revision 1.16  1996/08/16 21:07:11  tamches
55  * updated copyright for release 1.1
56  *
57  * Revision 1.15  1996/05/01 20:55:08  tamches
58  * added inactivateAll
59  * change interface to configNode a bit
60  *
61  * Revision 1.14  1996/05/01 14:07:59  naim
62  * Multiples changes in UI to make call to requestNodeInfoCallback async.
63  * (UI<->PC) - naim
64  *
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.
68  *
69  * Revision 1.12  1996/04/13 04:39:49  karavan
70  * better implementation of batching for edge requests
71  *
72  * Revision 1.11  1996/04/09 19:25:13  karavan
73  * added batch mode to cut down on shg redraw time.
74  *
75  * Revision 1.10  1996/03/10 23:20:51  hollings
76  * Mad sure all assert statements were in { } blocks.  odd compiler problem
77  * for AIX or UMD.
78  *
79  * Revision 1.9  1996/03/08  00:21:20  tamches
80  * added support for hidden nodes
81  *
82  * Revision 1.8  1996/02/15 23:10:01  tamches
83  * added proper support for why vs. where axis refinement
84  *
85  */
86
87 #ifndef _SHG_H_
88 #define _SHG_H_
89
90 #ifndef PARADYN
91 #include "DictionaryLite.h"
92 #else
93 #include "util/h/DictionaryLite.h"
94 #endif
95
96 #ifdef PARADYN
97 #include "performanceConsultant.thread.h" // for struct shg_node_info
98    // shg test program doesn't touch this stuff
99 #endif
100
101 #include "where4tree.h"
102 #include "graphicalPath.h"
103
104 #include "shgConsts.h"
105 #include "shgRootNode.h" // contrast with rootNode.h, the where axis root node class
106
107 class shg {
108  private:
109    // These are needed by shgRootNode:
110    static Tk_Font theRootItemFontStruct, theRootItemShadowFontStruct;
111    static Tk_Font theListboxItemFontStruct, theListboxItemShadowFontStruct;
112
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;
124
125    // this appears to be the WRONG class for the following vrbles:
126    static int listboxBorderPix; // 3
127    static int listboxScrollBarWidth; // 16
128
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)!
138
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
150
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
159
160    where4TreeConstants consts; // yuck
161    shgConsts theShgConsts;
162    int thePhaseId; // new
163
164    Tcl_Interp *interp;
165
166    string horizSBName; // tk window name
167    string vertSBName; // tk window name
168
169    int nominal_centerx; // actual centerx = nominal_centerx + horizScrollBarOffset
170    int horizScrollBarOffset; // always <= 0
171    int vertScrollBarOffset; // always <= 0
172
173    string currItemLabelName; // tk window name
174    whereNodeGraphicalPath<shgRootNode> lastItemUnderMousePath;
175    int lastItemUnderMouseX, lastItemUnderMouseY;
176
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;
181
182    void resizeScrollbars();
183
184    bool set_scrollbars(int absolute_x, int relative_x,
185                        int absolute_y, int relative_y,
186                        bool warpPointer);
187       // returns true iff any sb changes were made.
188       // moves cursor if warpPointer is true
189
190    whereNodeGraphicalPath<shgRootNode> point2path(int x, int y) const;
191
192    void processNonSliderButtonPress(whereNodeGraphicalPath<shgRootNode> &);
193    static void nonSliderButtonRelease(ClientData cd, XEvent *);
194    static void nonSliderButtonAutoRepeatCallback(ClientData cd);
195
196    static void sliderMouseMotion(ClientData cd, XEvent *eventPtr);
197    static void sliderButtonRelease(ClientData cd, XEvent *eventPtr);
198  
199    void rethink_entire_layout(bool isCurrShg) {
200       // slow...
201       assert(rootPtr);
202       rootPtr->recursiveDoneAddingChildren(consts, false); // false --> don't resort
203       rethink_nominal_centerx();
204
205       if (isCurrShg) {
206          resizeScrollbars();
207          adjustHorizSBOffset();
208          adjustVertSBOffset();
209       }
210    }
211
212    bool state2hidden(shgRootNode::evaluationState, bool active,
213                      bool shadow) const;
214
215    bool recursiveUpdateHiddenNodes(where4tree<shgRootNode> *ptr);
216    bool changeHiddenNodesBase(bool isCurrShg);
217       // called by changeHiddenNodes.
218
219  protected:
220    void rethink_nominal_centerx();
221    
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();
226    }
227    static unsigned hashFuncShadow(const unsigned &id) {return id;}
228
229  public:
230
231    // These routines are needed by shgRootNode:
232    static Tk_Font getRootItemFontStruct(bool shadow) {
233       if (shadow)
234          return theRootItemShadowFontStruct;
235       else
236          return theRootItemFontStruct;
237    }
238    static Tk_Font getListboxItemFontStruct(bool shadow) {
239       if (shadow)
240          return theListboxItemShadowFontStruct;
241       else
242          return theListboxItemFontStruct;
243    }
244    static Tk_3DBorder getRootItemTk3DBorder(shgRootNode::evaluationState theEvalStyle) {
245       unsigned styleIndex = theEvalStyle;
246       return rootItemTk3DBordersByStyle[styleIndex];
247    }
248    static GC getRootItemTextGC(bool active, bool shadow) {
249       if (active)
250          if (shadow)
251             return rootItemActiveShadowTextGC;
252          else
253             return rootItemActiveTextGC;
254       else if (shadow)
255          return rootItemInactiveShadowTextGC;
256       else
257          return rootItemInactiveTextGC;
258    }
259    static GC getListboxItemGC(bool active, bool shadow) {
260       if (active)
261          if (shadow)
262             return listboxActiveShadowItemGC;
263          else
264             return listboxActiveItemGC;
265       else if (shadow)
266          return listboxInactiveShadowItemGC;
267       else
268          return listboxInactiveItemGC;
269    }
270    static Tk_3DBorder getListboxItemTk3DBorder(shgRootNode::evaluationState theStyle) {
271       unsigned styleIndex = theStyle;
272       return listboxItemTk3DBordersByStyle[styleIndex];
273    }
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;
281
282       assert("unknown refinement" && false); abort();
283    }
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;
291
292       assert("unknown refinement" && false); abort();
293    }
294
295    shg(int phaseId,
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;}
302
303    int getPhaseId() const {return thePhaseId;}
304    Tk_Window getTkWindow() {
305       // a little hack needed for XWarpPointer
306       return consts.theTkWindow;
307    }
308
309    void initializeStaticsIfNeeded();
310
311    // the return values of the next 2 routines will be <= 0
312    int getVertSBOffset()  const {return vertScrollBarOffset;}
313    int getHorizSBOffset() const {return horizScrollBarOffset;}
314
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
319
320    bool adjustVertSBOffset(float newFirstFrac);
321    bool adjustVertSBOffsetFromDeltaPix(int deltapix);
322    bool adjustVertSBOffset(); // obtains first pix from actual tk sb
323
324    int getTotalVertPixUsed()  const {return rootPtr->entire_height(consts);}
325    int getTotalHorizPixUsed() const {return rootPtr->entire_width(consts);}
326
327    int getVisibleVertPix()  const {return Tk_Height(consts.theTkWindow);}
328    int getVisibleHorizPix() const {return Tk_Width(consts.theTkWindow);}
329
330    void draw(bool doubleBuffer, bool isXsynchOn) const;
331    void resize(bool rethinkScrollbars); // pass true iff we are currently displayed shg
332
333    bool softScrollToEndOfPath(const whereNodePosRawPath &thePath);
334       // Like the above routine, but always scrolls to the last item in the path.
335
336    void recursiveRethinkLayout() {
337       rootPtr->recursiveDoneAddingChildren(consts, false); // don't resort
338    }
339  
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);
346
347    enum changeType{ct_true, ct_false, ct_unknown, ct_never, ct_active, ct_inactive,
348                    ct_shadow};
349    bool changeHiddenNodes(bool newHideTrue, bool newHideFalse, bool newHideUnknown,
350                           bool newHideNeverSeen, bool newHideActive,
351                           bool newHideInactive, bool newHideShadow,
352                           bool isCurrShg);
353       // Returns true iff any changes.
354    bool changeHiddenNodes(changeType, bool hide, bool isCurrShg);
355       // Like above routine but just changes 1 trait
356
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
365       // of the "graph".
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
374       // of a node.
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.
380
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
384                 bool isCurrShg, 
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
388
389 #ifdef PARADYN 
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
393 #endif
394 };
395
396 #endif