|
NCBI Home IEB Home C Toolkit docs C++ Toolkit source browser C Toolkit source browser (2) |
NCBI C Toolkit Cross ReferenceC/vibrant/treeview.c |
source navigation diff markup identifier search freetext search file search |
1 /* treeview.c
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * File Name: treeview.c
27 *
28 * Author: Vladimir Soussov
29 *
30 * File Description: treeview functions
31 *
32 *
33 * $Log: treeview.c,v $
34 * Revision 1.14 2008/04/29 13:43:50 kans
35 * fixes for warnings caught by mingw cross-compiler
36 *
37 * Revision 1.13 2001/03/28 14:05:47 beloslyu
38 * fix the comments to C style
39 *
40 * Revision 1.12 2001/03/28 01:37:40 juran
41 * *** empty log message ***
42 *
43 * Revision 1.11 2000/11/06 21:51:15 soussov
44 * adds code to prevent infinite loop in getNodeCoordinates
45 *
46 * Revision 1.10 1999/08/12 18:31:10 soussov
47 * fixed bug in allocNewSegm
48 *
49 * Revision 1.9 1999/08/11 14:19:42 soussov
50 * fixed bug with Int4 -> Int2 conversion
51 *
52 * Revision 1.8 1998/07/02 18:24:33 vakatov
53 * Cleaned the code & made it pass through the C++ compilation
54 *
55 * Revision 1.7 1998/04/08 16:51:49 soussov
56 * typo in function name fixed
57 *
58 * Revision 1.6 1998/04/02 23:03:51 vakatov
59 * PC-specific fixes
60 *
61 * Revision 1.5 1998/04/01 21:52:47 soussov
62 * Prototype fixed
63 *
64 * Revision 1.4 1998/04/01 20:14:41 soussov
65 * vibincld.h added
66 *
67 * Revision 1.3 1998/04/01 20:09:22 soussov
68 * Some prototypes added
69 *
70 * Revision 1.2 1998/04/01 17:43:59 soussov
71 * changed tp include <>
72 *
73 * Revision 1.1 1998/03/31 21:22:27 sirotkin
74 * With Vladimir - moved from distrib/internal/taxonomy/tree
75 *
76 * Revision 6.1 1998/01/13 19:18:51 soussov
77 * qsort for large sibling list added
78 *
79 * Revision 6.0 1997/08/25 18:29:53 madden
80 * Revision changed to 6.0
81 *
82 * Revision 1.1 1997/05/30 16:16:21 soussov
83 * Set of files for ncbitree library
84 *
85 * Revision 1.1 1997/05/29 20:44:31 soussov
86 * Initial version of tree library
87 *
88 *
89 */
90
91 #include <treemgr.h>
92 #include <treeview.h>
93
94 #define TREE_X0 10
95 #define TREE_Y0 10
96
97 #define getTree4Cursor tree_getUserData
98
99 #define port_MoveTo(p, a, b) sMoveTo((a) + (p)->panel_origin_X, (b) + (p)->panel_origin_Y)
100 #define port_LineTo(p, a, b) sLineTo((a) + (p)->panel_origin_X, (b) + (p)->panel_origin_Y)
101
102 static void closeAllSubtrees(TreeCursorPtr cursor);
103 extern void Nlm_GetRect PROTO((Nlm_GraphiC a, Nlm_RectPtr r));
104
105 static _tnSegmPtr getNewSegmBuff(void)
106 {
107 _tnSegmPtr ts= (_tnSegmPtr)MemNew(4096*sizeof(_tnSegm));
108
109 if(ts) {
110 memset(ts, 0, 4096*sizeof(_tnSegm));
111 ts[4095].flags= LINK_TO_NEXT_BUFF;
112 }
113 return ts;
114 }
115
116 static void sMoveTo(Int4 x, Int4 y)
117 {
118 if(x > 32000) x= 32000;
119 else if(x < -32000) x= -32000;
120 if(y > 32000) y= 32000;
121 else if(y < -32000) y= -32000;
122
123 MoveTo((Int2)x, (Int2)y);
124 }
125
126 static void sLineTo(Int4 x, Int4 y)
127 {
128 if(x > 32000) x= 32000;
129 else if(x < -32000) x= -32000;
130 if(y > 32000) y= 32000;
131 else if(y < -32000) y= -32000;
132
133 LineTo((Int2)x, (Int2)y);
134 }
135
136 static void port_PaintRect(_drawContextPtr port, RectPtr r)
137 {
138 r->left+= port->panel_origin_X;
139 r->right+= port->panel_origin_X;
140 r->top+= port->panel_origin_Y;
141 r->bottom+= port->panel_origin_Y;
142
143 PaintRect(r);
144 }
145
146 static void Rect2Box(_drawContextPtr p, RectPtr r, _boxPtr b)
147 {
148 b->xl= (r->left - p->panel_origin_X) + p->port_origin.x;
149 b->xr= (r->right - p->panel_origin_X) + p->port_origin.x;
150 b->yt= (r->top - p->panel_origin_Y) + p->port_origin.y;
151 b->yb= (r->bottom - p->panel_origin_Y) + p->port_origin.y;
152 }
153
154 static void Box2Rect(_drawContextPtr p, _boxPtr b, RectPtr r)
155 {
156 r->left= p->panel_origin_X + (b->xl - p->port_origin.x);
157 r->right= p->panel_origin_X + (b->xr - p->port_origin.x);
158 r->top= p->panel_origin_Y + (b->yt - p->port_origin.y);
159 r->bottom= p->panel_origin_Y + (b->yb - p->port_origin.y);
160 }
161
162 static CharPtr getNodeLabel(TreeCursorPtr cursor)
163 {
164 Uint2 size;
165 CharPtr label;
166
167 label= (CharPtr) tree_getNode(cursor, TREE_NODE_FMT_LABEL, &size);
168 if(label != NULL) label[size]= '\0';
169 return label;
170 }
171
172 static Int4 getNodeLength(TreeCursorPtr cursor)
173 {
174 Uint2 size;
175 Int4 length;
176
177 length= (Int4)tree_getNode(cursor, TREE_NODE_FMT_DISTANCE, &size);
178 return (length <= 0)? 1 : length;
179 }
180
181 static Int2 getIconId(TreeCursorPtr cursor)
182 {
183 Uint2 size;
184 Int4 a;
185 Int2 id;
186
187 a= (Int4) tree_getNode(cursor, TREE_NODE_FMT_ICON, &size);
188 id= (Int2)a;
189
190 return id;
191 }
192
193 #ifdef XXX_UNUSED_STATIC_FUNC
194 static void addBox2Region(_boxPtr region, _boxPtr box)
195 {
196 if(box->xl < region->xl) region->xl= box->xl;
197 if(box->xr > region->xr) region->xr= box->xr;
198 if(box->yt < region->yt) region->yt= box->yt;
199 if(box->yb > region->yb) region->yb= box->yb;
200 }
201 #endif /* XXX_UNUSED_STATIC_FUNC */
202
203 static Boolean BoxXRegion(_boxPtr region, _boxPtr box, _boxPtr res)
204 {
205 if((box->yt >= region->yb) || (box->yb <= region->yt)) return FALSE;
206 if((box->xl >= region->xr) || (box->xr <= region->xl)) return FALSE;
207
208 if(res != NULL) {
209 res->xl= (box->xl > region->xl)? box->xl : region->xl;
210 res->xr= (box->xr < region->xr)? box->xr : region->xr;
211 res->yt= (box->yt > region->yt)? box->yt : region->yt;
212 res->yb= (box->yb < region->yb)? box->yb : region->yb;
213 }
214
215 return TRUE;
216 }
217
218 #ifdef XXX_UNUSED_STATIC_FUNC
219 static void moveBox(_boxPtr box, Int4 dx, Int4 dy)
220 {
221
222 if(dx != 0) {
223 box->xl+= dx;
224 box->xr+= dx;
225 }
226 if(dy != 0) {
227 box->yt+= dy;
228 box->yb+= dy;
229 }
230 }
231 #endif /* XXX_UNUSED_STATIC_FUNC */
232
233 #ifdef XXX_UNUSED_STATIC_FUNC
234 static void zoomBox(_boxPtr box, Int4 dx, Int4 dy)
235 {
236 if(dx != 0) {
237 box->xl-= dx;
238 box->xr+= dx;
239 }
240
241 if(dy != 0) {
242 box->yt-= dy;
243 box->yb+= dy;
244 }
245 }
246 #endif /* XXX_UNUSED_STATIC_FUNC */
247
248 static Boolean ptInBox(_boxPtr box, Int4 x, Int4 y)
249 {
250 return ((y >= box->yt) && (y <= box->yb) && (x >= box->xl) && (x <= box->xr));
251 }
252
253 static void freeNodeSegm(TreeCursorPtr cursor)
254 {
255 _tnSegmPtr ts1;
256 _tnSegmPtr ts2;
257 TreeViewPtr tv;
258
259 tv= (TreeViewPtr) getTree4Cursor(cursor);
260 ts1= (_tnSegmPtr)(cursor->node->sys_data);
261
262 if(ts1 == NULL) return;
263
264 if(ts1->viewer_id == tv->my_spy_id) {
265 cursor->node->sys_data= ts1->next;
266 ts2= ts1;
267 }
268 else {
269 for(ts2= ts1->next; ts2 != NULL; ts2= ts2->next) {
270 if(ts2->viewer_id == tv->my_spy_id) {
271 ts1->next= ts2->next;
272 break;
273 }
274 else {
275 ts1= ts2;
276 }
277 }
278 }
279
280 if(ts2 != NULL) {
281 ts2->flags= 0;
282 }
283 }
284
285 static _tnSegmPtr allocNewSegm(TreeCursorPtr cursor)
286 {
287 _tnSegmPtr ts;
288 _tnSegmPtr tsn;
289 TreeViewPtr tv;
290 /* Int4 i, j; */
291
292 /*find free room */
293 tv= (TreeViewPtr) getTree4Cursor(cursor);
294 ts= tv->segm_buff;
295
296 while(ts) {
297 if(ts->flags == 0) {
298 ts->flags= RESERVED_SEGM;
299 ts->next= (_tnSegmPtr)cursor->node->sys_data;
300 cursor->node->sys_data= ts;
301 ts->viewer_id= tv->my_spy_id;
302 return ts;
303 }
304 if((ts->flags & LINK_TO_NEXT_BUFF) != 0) {
305 if(ts->next) {
306 ts= ts->next;
307 continue;
308 }
309 else break;
310 }
311 ++ts;
312 }
313
314 if(ts == NULL) return NULL;
315 /* try to allocate more memory */
316 if((tsn= getNewSegmBuff()) == NULL) {
317 return NULL;
318 }
319
320 tsn->flags= RESERVED_SEGM;
321 tsn->viewer_id= tv->my_spy_id;
322 ts->next= tsn;
323 cursor->node->sys_data= tsn;
324
325 return tsn;
326 }
327
328
329
330 static Int4 getIconWidth(_ImageListPtr ilp, Uint2 i_id)
331 {
332 Uint2 w= 0, h;
333
334 if(ilp != NULL) {
335 ilst_size(ilp, i_id, &w, &h);
336 }
337 return (Int4)w;
338 }
339
340
341 static Int4 calcNodeWidth(TreeViewPtr tv, Int2 icon_id, Int4 length, CharPtr label)
342 {
343 return ((tv->length_scale >= 0)? (tv->length_scale * length) : (length/(-tv->length_scale))) +
344 (((tv->i_list != NULL) && (icon_id >= 0))? getIconWidth(tv->i_list, icon_id) : 0) +
345 (((label != NULL) && (*label != '\0'))? (StringWidth(label) + 4) : 0);
346 }
347
348 static _tnSegmPtr getNodeViewerData(_tnSegmPtr tn, Uint1 v_id)
349 {
350 while(tn != NULL) {
351 if(tn->viewer_id == v_id) return tn;
352 tn= tn->next;
353 }
354 return NULL;
355 }
356
357 static Boolean getBox4Cursor(TreeCursorPtr cursor, _boxPtr box)
358 {
359 _tnSegmPtr node_data;
360 TreeViewPtr tv;
361
362 tv= (TreeViewPtr) getTree4Cursor(cursor);
363 if((node_data= getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id)) != NULL) {
364 box->xr+= node_data->w;
365 box->yb+= node_data->h;
366 return TRUE;
367 }
368
369 return FALSE;
370 }
371
372 static TreeNodeId getNextSibling(TreeCursorPtr cursor, TreeNodeId nxt_id)
373 {
374 Boolean r;
375 _tnSegmPtr node_data;
376 TreeViewPtr tv;
377
378 tv= (TreeViewPtr)getTree4Cursor(cursor);
379
380 if(nxt_id.idi == cursor->node_id.idi) {
381 nxt_id.idi= 0;
382 return nxt_id;
383 }
384
385 if(nxt_id.idi != 0) {
386 tree_toNode(cursor, nxt_id);
387 if((node_data= getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id)) != NULL) {
388 return node_data->work;
389 }
390 else {
391 nxt_id.idi= 0;
392 return nxt_id;
393 }
394 }
395
396 /* find the first one */
397
398 if(tree_parent(cursor)) {
399
400 for(r= tree_child(cursor); r; r= tree_sibling(cursor)) {
401 if((node_data= getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id)) != NULL) {
402 if((node_data->flags & TREE_FIRST_NODE) != 0) return node_data->work;
403 }
404 }
405 }
406
407 nxt_id.idi= 0;
408 return nxt_id;
409 }
410
411 static void draw_line(_drawContextPtr port, Int4 x1, Int4 y1, Int4 x2, Int4 y2)
412 {
413 if(y1 == y2) {
414 /* horisontal line */
415 if(((y1 + port->pen_w) <= port->clip_box.yt) ||
416 ((y1 - port->pen_w) >= port->clip_box.yb)) return;
417
418 if(x1 > x2) {
419 y2= x1;
420 x1= x2;
421 x2= y2;
422 y2= y1;
423 }
424
425 if(((x2 + port->pen_w) <= port->clip_box.xl) ||
426 ((x1 - port->pen_w) >= port->clip_box.xr)) return;
427 }
428 else if(x1 == x2) {
429 /* vertical line */
430 if(((x1 + port->pen_w) <= port->clip_box.xl) ||
431 ((x1 - port->pen_w) >= port->clip_box.xr)) return;
432
433 if(y1 > y2) {
434 x2= y1;
435 y1= y2;
436 y2= x2;
437 x2= x1;
438 }
439
440 if(((y1 - port->pen_w) >= port->clip_box.yb) ||
441 ((y2 + port->pen_w) <= port->clip_box.yt)) return;
442 }
443
444 /* adjust coordinates */
445 x1-= port->port_origin.x;
446 x2-= port->port_origin.x;
447 y1-= port->port_origin.y;
448 y2-= port->port_origin.y;
449
450 port_MoveTo(port, x1, y1);
451 /* TODO add here the pen settings */
452 SetColor(port->line_color);
453 port_LineTo(port, x2, y2);
454 }
455
456 #if 0
457 static void erase_line(_drawContextPtr port, Int4 x1, Int4 y1, Int4 x2, Int4 y2)
458 {
459 if(y1 == y2) {
460 /* horisontal line */
461 if(((y1 + port->pen_w) <= port->clip_box.yt) ||
462 ((y1 - port->pen_w) >= port->clip_box.yb)) return;
463
464 if(x1 > x2) {
465 y2= x1;
466 x1= x2;
467 x2= y2;
468 y2= y1;
469 }
470
471 if(((x2 + port->pen_w) <= port->clip_box.xl) ||
472 ((x1 - port->pen_w) >= port->clip_box.xr)) return;
473 }
474 else if(x1 == x2) {
475 /* vertical line */
476 if(((x1 + port->pen_w) <= port->clip_box.xl) ||
477 ((x1 - port->pen_w) >= port->clip_box.xr)) return;
478
479 if(y1 > y2) {
480 x2= y1;
481 y1= y2;
482 y2= x2;
483 x2= x1;
484 }
485
486 if(((y1 - port->pen_w) >= port->clip_box.yb) ||
487 ((y2 + port->pen_w) <= port->clip_box.yt)) return;
488 }
489
490 /* adjust coordinates */
491 x1-= port->port_origin.x;
492 x2-= port->port_origin.x;
493 y1-= port->port_origin.y;
494 y2-= port->port_origin.y;
495
496 port_MoveTo(port, x1, y1);
497 /* TODO add here the pen settings */
498 Black();
499 EraseMode();
500 port_LineTo(port, x2, y2);
501 CopyMode();
502 }
503 #endif
504
505 static void draw_plus(_drawContextPtr port, Int4 x, Int4 y)
506 {
507 RecT rect;
508 Int2 radius;
509
510 radius= port->pen_w + 3;
511
512 if(((y + radius) < port->clip_box.yt) ||
513 ((y - radius) > port->clip_box.yb) ||
514 ((x - radius) > port->clip_box.xr) ||
515 ((x + radius) < port->clip_box.xl)) return;
516
517 x-= port->port_origin.x;
518 y-= port->port_origin.y;
519
520 rect.right= (Int2)(x + radius);
521 rect.left= (Int2)(x - radius);
522 rect.top= (Int2)(y - radius);
523 rect.bottom= (Int2)(y + radius);
524
525 SetColor(port->plus_color);
526 Solid();
527 port_PaintRect(port, &rect);
528 SetColor(port->bg_color);
529 port_MoveTo(port, x, y - radius + 1);
530 port_LineTo(port, x, y + radius - 1);
531 port_MoveTo(port, x - radius + 1, y);
532 port_LineTo(port, x + radius - 1, y);
533 }
534
535 static void draw_minus(_drawContextPtr port, Int4 x, Int4 y)
536 {
537 RecT rect;
538 Int2 radius;
539
540 radius= port->pen_w + 3;
541
542 if(((y + radius) < port->clip_box.yt) ||
543 ((y - radius) > port->clip_box.yb) ||
544 ((x - radius) > port->clip_box.xr) ||
545 ((x + radius) < port->clip_box.xl)) return;
546
547 x-= port->port_origin.x;
548 y-= port->port_origin.y;
549
550 rect.right= (Int2)(x + radius);
551 rect.left= (Int2)(x - radius);
552 rect.top= (Int2)(y - radius);
553 rect.bottom= (Int2)(y + radius);
554
555 SetColor(port->plus_color);
556 Solid();
557 port_PaintRect(port, &rect);
558 SetColor(port->bg_color);
559 port_MoveTo(port, x - radius + 1, y);
560 port_LineTo(port, x + radius - 1, y);
561 }
562
563 static void draw_label(_drawContextPtr port, CharPtr label, Int4 x, Int4 y)
564 {
565
566 if(x >= port->clip_box.xr) return;
567
568 /* TODO insert here pen and font settings */
569 SetColor(port->text_color);
570
571 y+= FontHeight()/2 - Descent();
572 x-= port->port_origin.x;
573 y-= port->port_origin.y;
574 port_MoveTo(port, x, y);
575 PaintChar(' ');
576 PaintString(label);
577 }
578
579 static void draw_icon(_drawContextPtr port, _ImageListPtr il, Uint2 i_ind, Int4 x, Int4 y)
580 {
581 Uint2 w, h;
582
583 if(!ilst_size(il, i_ind, &w, &h)) {
584 w= h= 0;
585 }
586
587 x-= w/2 + 1;
588 y-= h/2 + 1;
589
590 if((y > port->clip_box.yb) ||
591 ((y + h) < port->clip_box.yt) ||
592 (x > port->clip_box.xr) ||
593 ((x + w) < port->clip_box.xl)) return;
594
595 x-= port->port_origin.x;
596 y-= port->port_origin.y;
597 ilst_draw(il, i_ind, x + port->panel_origin_X, y + port->panel_origin_Y);
598 }
599
600 static void highLightBox(_drawContextPtr port, _boxPtr node_box, CharPtr label)
601 {
602 RecT r;
603 Int4 x, y;
604
605 r.left= node_box->xl - port->port_origin.x;
606 r.right= node_box->xr - port->port_origin.x;
607 r.top= node_box->yt - port->port_origin.y;
608 r.bottom= node_box->yb - port->port_origin.y;
609
610 InsetRect(&r, 1, 1);
611 r.right+= 1;
612 SetColor(port->sbg_color);
613 port_PaintRect(port, &r);
614 SetColor(port->sfg_color);
615
616 x= node_box->xl;
617 y= ((node_box->yt + node_box->yb)/2) + FontHeight()/2 - Descent();
618 x-= port->port_origin.x;
619 y-= port->port_origin.y;
620 port_MoveTo(port, x, y);
621 PaintChar(' ');
622 if(label != NULL) PaintString(label);
623 /*InvertRect(&r);*/
624 }
625
626 static void unHighLightBox(_drawContextPtr port, _boxPtr node_box, CharPtr label)
627 {
628 RecT r;
629 Int4 x, y;
630
631 r.left= node_box->xl - port->port_origin.x;
632 r.right= node_box->xr - port->port_origin.x;
633 r.top= node_box->yt - port->port_origin.y;
634 r.bottom= node_box->yb - port->port_origin.y;
635
636 InsetRect(&r, 1, 1);
637 r.right+= 1;
638 SetColor(port->bg_color);
639 port_PaintRect(port, &r);
640 SetColor(port->text_color);
641
642 x= node_box->xl;
643 y= ((node_box->yt + node_box->yb)/2) + FontHeight()/2 - Descent();
644 x-= port->port_origin.x;
645 y-= port->port_origin.y;
646 port_MoveTo(port, x, y);
647 PaintChar(' ');
648 if(label != NULL) PaintString(label);
649 /*InvertRect(&r);*/
650 }
651
652 /*******************************************
653 * set clip box on whole panel
654 */
655 static void setPort2Panel(_drawContextPtr my_port)
656 {
657 RecT r;
658
659 ObjectRect(my_port->tree_panel, &r);
660
661 /* convert it to panel coordinates */
662 Rect2Box(my_port, &r, &my_port->clip_box);
663 }
664
665 static void drawVertical(TreeCursorPtr cursor, Int4 x0, Int4 y0)
666 {
667 if(tree_child(cursor)) {
668 TreeViewPtr tv= (TreeViewPtr) getTree4Cursor(cursor);
669 Int4 y1= y0;
670 Int4 dy= tv->row_height;
671 _tnSegmPtr tns;
672
673 if(tv->cmpSiblings == NULL) {
674 /* we don't want to sort siblings */
675 do {
676 y1+= dy;
677 if((tns= getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id)) != NULL) {
678 dy= tns->h;
679 }
680 else dy= 0;
681 }
682 while (tree_sibling(cursor));
683 }
684 else {/* siblings have to be sorted */
685 TreeNodeId id;
686
687 for(id.idi= 0; (id= getNextSibling(cursor, id)).idi != 0;) {
688 y1+= dy;
689 if((tns= getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id)) != NULL) {
690 dy= tns->h;
691 }
692 else dy= 0;
693 }
694 }
695
696 tree_parent(cursor);
697 draw_line(&tv->draw_port, x0, y0, x0, y1);
698 }
699 }
700
701
702 static Int4 draw_node(TreeCursorPtr cursor, Int4 x0, Int4 y0)
703 {
704 TreeViewPtr tv;
705 _box my_box;
706 _box node_box;
707 Int4 ym, xm, xt, yd;
708 Int2 icon_id;
709 Int4 length;
710 CharPtr label;
711 Boolean need_select= FALSE;
712
713 my_box.xl= my_box.xr= x0;
714 my_box.yt= my_box.yb= y0;
715 if(!getBox4Cursor(cursor, &my_box)) return x0;
716 tv= (TreeViewPtr) getTree4Cursor(cursor);
717 icon_id= (tv->i_list == NULL)? -1 : getIconId(cursor);
718 length= getNodeLength(cursor);
719 label= getNodeLabel(cursor);
720
721
722 node_box.xl= x0;
723 node_box.yt= y0;
724 node_box.yb= y0 + tv->row_height;
725 node_box.xr= x0 + calcNodeWidth(tv, icon_id, length, label);
726
727 /* calculate the mediane */
728 ym= y0 + tv->row_height/2;
729
730 xm= x0 +
731 ((tv->length_scale >= 0)?
732 (tv->length_scale * length) : (length/(-tv->length_scale)));
733
734 yd= my_box.yb - tv->row_height/2;
735
736 if(BoxXRegion(&tv->draw_port.clip_box, &node_box, NULL)) {
737 /* we have visible part */
738
739 /* check for selected node */
740 if(cursor->node_id.idi == tv->cr2->node_id.idi) {
741 need_select= TRUE;
742 tv->sel_x= x0;
743 tv->sel_y= y0;
744 }
745
746 /* draw horisontal line */
747 draw_line(&tv->draw_port, x0, ym, xm, ym);
748
749 /* draw vertical line */
750 if((yd - ym) > tv->row_height/2) {
751 drawVertical(cursor, xm, ym);
752 draw_minus(&tv->draw_port, x0, ym);
753 }
754 else if(tree_child(cursor)) {
755 draw_plus(&tv->draw_port, x0, ym);
756 tree_parent(cursor);
757 }
758
759 if(icon_id >= 0) {
760 /* draw icon */
761 xt= xm + getIconWidth(tv->i_list, icon_id)/2;
762 draw_icon(&tv->draw_port, tv->i_list, icon_id, xm, ym);
763 }
764 else xt= xm;
765
766 if(label != NULL) {
767 /* draw label */
768 if(need_select) {
769 node_box.xl= xt;
770 highLightBox(&tv->draw_port, &node_box, label);
771 }
772 else draw_label(&tv->draw_port, label, xt, ym);
773 }
774 }
775 else {
776 /* node itself invisible, but we can see it's children */
777
778 /* draw vertical line */
779 drawVertical(cursor, xm, ym);
780 /*
781 if((yd - ym) > tv->row_height/2) {
782 draw_line(&tv->draw_port, xm, ym, xm, yd);
783 }
784 */
785 }
786 return xm;
787 }
788
789
790 static Boolean drawTree(TreeCursorPtr cursor, Int4 x0, Int4 y0)
791 {
792 _box my_box;
793 TreeViewPtr tv;
794
795 my_box.xl= my_box.xr= x0;
796 my_box.yt= my_box.yb= y0;
797
798 if(!getBox4Cursor(cursor, &my_box)) return FALSE; /* this node is invisible */
799 tv= (TreeViewPtr) getTree4Cursor(cursor);
800
801 if(BoxXRegion(&tv->draw_port.clip_box, &my_box, NULL)) {
802 /* we have visible part */
803 x0= draw_node(cursor, x0, y0);
804 y0+= tv->row_height;
805 if(tree_child(cursor)) {
806
807 if(tv->cmpSiblings == NULL) {
808 /* we don't want to sort siblings */
809 do {
810 if(drawTree(cursor, x0, y0)) {
811 my_box.xl= my_box.xr= x0;
812 my_box.yt= my_box.yb= y0;
813 getBox4Cursor(cursor, &my_box);
814 y0= my_box.yb;
815 if(y0 > tv->draw_port.clip_box.yb) break;
816 }
817 }
818 while (tree_sibling(cursor));
819 }
820 else {/* siblings have to be sorted */
821 TreeNodeId id;
822
823 for(id.idi= 0; (id= getNextSibling(cursor, id)).idi != 0;) {
824 if(drawTree(cursor, x0, y0)) {
825 my_box.xl= my_box.xr= x0;
826 my_box.yt= my_box.yb= y0;
827 getBox4Cursor(cursor, &my_box);
828 y0= my_box.yb;
829 if(y0 > tv->draw_port.clip_box.yb) break;
830 }
831 }
832 }
833
834 tree_parent(cursor);
835 }
836 }
837 return TRUE;
838 }
839
840 /*------------------------------------------------------
841 * Redraw tree fragment in current port
842 */
843
844 static void redrawInPort(TreeViewPtr tv)
845 {
846 RecT r;
847
848 Box2Rect(&tv->draw_port, &tv->draw_port.clip_box, &r);
849
850 InsetRect(&r, 1, 1);
851 InvalRect(&r);
852 /*FrameRect(&r);*/
853 Update();
854 }
855
856 static Boolean makeNodeVisible(TreeCursorPtr cursor)
857 {
858 TreeViewPtr tv;
859 _box my_box;
860 _tnSegmPtr tsp;
861
862 tv= (TreeViewPtr)getTree4Cursor(cursor);
863 if(getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id) != NULL) return TRUE;
864
865 /* we need to open node */
866 tsp= allocNewSegm(cursor);
867 if(tsp == NULL) {
868 return FALSE;
869 }
870 else {
871 Int2 icon_id;
872 Int4 length, xm, ym;
873 CharPtr label;
874
875 icon_id= (tv->i_list == NULL)? -1 : getIconId(cursor);
876 length= getNodeLength(cursor);
877 label= getNodeLabel(cursor);
878
879 tsp->h= tv->row_height;
880
881 tsp->w= calcNodeWidth(tv, icon_id, length, label);
882
883
884
885 if(tree_child(cursor)) {
886
887 /* adjust with children's boxes if visable */
888 xm= ((tv->length_scale >= 0)?
889 (tv->length_scale * length) : (length/(-tv->length_scale)));
890
891 ym= tv->row_height;
892 /* we don't need to sort siblings here */
893 do {
894 my_box.xl= my_box.xr= xm;
895 my_box.yt= my_box.yb= ym;
896
897 if(getBox4Cursor(cursor, &my_box)) {
898 ym= my_box.yb;
899 if(tsp->w < my_box.xr) tsp->w= my_box.xr;
900 }
901 }
902 while (tree_sibling(cursor));
903
904 tsp->h= ym;
905 tree_parent(cursor);
906 }
907 }
908 return TRUE;
909 }
910
911 static void adjust_parentSize(TreeCursorPtr cursor)
912 {
913 TreeViewPtr tv;
914 _box my_box;
915 _tnSegmPtr tsp;
916 TreeNodeId nid= tree_getId(cursor);
917
918 if(tree_parent(cursor)) {
919 tv= (TreeViewPtr) getTree4Cursor(cursor);
920 if((tsp= getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id)) != NULL) {
921 Int2 icon_id;
922 Int4 length, xm, ym;
923 CharPtr label;
924
925 icon_id= (tv->i_list == NULL)? -1 : getIconId(cursor);
926 length= getNodeLength(cursor);
927 label= getNodeLabel(cursor);
928
929 tsp->h= tv->row_height;
930
931 tsp->w= calcNodeWidth(tv, icon_id, length, label);
932
933
934
935 if(tree_child(cursor)) {
936
937 /* adjust with children's boxes if visable */
938 xm= ((tv->length_scale >= 0)?
939 (tv->length_scale * length) : (length/(-tv->length_scale)));
940
941 ym= tv->row_height;
942 /* we don't need to sort siblings here */
943 do {
944 my_box.xl= my_box.xr= xm;
945 my_box.yt= my_box.yb= ym;
946
947 if(getBox4Cursor(cursor, &my_box)) {
948 ym= my_box.yb;
949 if(tsp->w < my_box.xr) tsp->w= my_box.xr;
950 }
951 }
952 while (tree_sibling(cursor));
953
954 tsp->h= ym;
955 tree_parent(cursor);
956 }
957 adjust_parentSize(cursor);
958 }
959 tree_toNode(cursor, nid);
960 }
961 }
962
963 static TreeCursorPtr sortCursor;
964
965 typedef int (*QsortCmpFunc)(const void *, const void *);
966
967 static int my_cmpSibl(TreeNodeId* a, TreeNodeId* b)
968 {
969 TreeViewPtr tv= (TreeViewPtr) getTree4Cursor(sortCursor);
970
971 tree_toNode(sortCursor, *b);
972 tree_toNode(tv->cr3, *a);
973 return (*(tv->cmpSiblings))(tv->cr3, sortCursor);
974 }
975
976 /* sort siblings */
977 static void sortSiblings(TreeCursorPtr cursor, Int2 n)
978 {
979 TreeViewPtr tv= (TreeViewPtr)getTree4Cursor(cursor);
980 _tnSegmPtr tns;
981 int i;
982 TreeNodeId nid, save_id= cursor->node_id;
983 TreeNodeId* aref;
984
985 if(!tree_child(cursor)) return;
986
987 /* create the array of pointers to viewer structure */
988 if(n < 2) {
989 /* we have just one child - nothing to sort */
990 if((tns= getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id)) != NULL) {
991 tns->work= cursor->node_id;
992 tns->flags|= TREE_FIRST_NODE;
993 }
994 tree_parent(cursor);
995 return;
996 }
997
998 for(i= 0; i < n;) {
999 if((tns= getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id)) != NULL) {
1000 tns->work.idi= 0;
1001 tns->flags&= ~TREE_FIRST_NODE;
1002 }
1003 if(!tree_sibling(cursor)) break;
1004 }
1005
1006 tree_parent(cursor);
1007 tree_child(cursor);
1008 if(tv->cr3 == NULL) {
1009 tv->cr3= tree_openCursor(tv->tree, tv, NULL);
1010 }
1011
1012 /* sort it */
1013 #if 1
1014 if((n > 132) && ((aref= (TreeNodeId*)malloc(sizeof(TreeNodeId)*n)) != NULL)) {
1015
1016 sortCursor= cursor;
1017
1018 i= 0;
1019 do {
1020 if(i < n) aref[i++]= tree_getId(cursor);
1021 }
1022 while(tree_sibling(cursor));
1023 qsort((void*)aref, i, sizeof(TreeNodeId), (QsortCmpFunc)my_cmpSibl);
1024
1025 tree_toNode(cursor, aref[0]);
1026 if((tns= getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id)) != NULL) {
1027 tns->flags|= TREE_FIRST_NODE;
1028 }
1029
1030 for(n= 1; n < i; n++) {
1031 tree_toNode(cursor, aref[n-1]);
1032 if((tns= getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id)) != NULL) {
1033 tns->work= aref[n];
1034 }
1035 }
1036
1037 tree_toNode(cursor, aref[i-1]);
1038 if((tns= getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id)) != NULL) {
1039 tns->work= aref[i-1];
1040 }
1041
1042 free(aref);
1043 tree_toNode(cursor, save_id);
1044 return;
1045 }
1046
1047 #endif
1048 nid.idi= 0;
1049 for(i= 0; i < n; i++) {
1050 /* find the minimum */
1051 do {
1052 if(((tns= getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id)) != NULL) &&
1053 (tns->work.idi == 0)) break;
1054 }
1055 while(tree_sibling(cursor));
1056
1057 tree_toNode(tv->cr3, tree_getId(cursor));
1058 while(tree_sibling(tv->cr3)) {
1059 if(((tns= getNodeViewerData((_tnSegmPtr)tv->cr3->node->sys_data, tv->my_spy_id)) != NULL) &&
1060 (tns->work.idi == 0) && ((*(tv->cmpSiblings))(tv->cr3, cursor) < 0)) {
1061
1062 tree_toNode(cursor, tree_getId(tv->cr3));
1063 }
1064 }
1065
1066
1067 if(((tns= getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id)) != NULL) &&
1068 (tns->work.idi == 0)) {
1069
1070 tns->work= tree_getId(cursor);
1071 if(nid.idi == 0) {
1072 tns->flags|= TREE_FIRST_NODE;
1073 }
1074 else {
1075 tree_toNode(tv->cr3, nid);
1076 tns= getNodeViewerData((_tnSegmPtr)tv->cr3->node->sys_data, tv->my_spy_id);
1077 tns->work= tree_getId(cursor);
1078 }
1079 nid= tree_getId(cursor);
1080 }
1081
1082 tree_parent(cursor);
1083 tree_child(cursor);
1084 }
1085 tree_toNode(cursor, save_id);
1086 }
1087
1088 /* open subtree */
1089 static Boolean openSubtree(TreeCursorPtr cursor, Boolean do_callBack)
1090 {
1091 TreeViewPtr tv;
1092 _tnSegmPtr node_data;
1093 _box node_box;
1094 Int4 length, xm, ym;
1095 Int2 n= 0;
1096 TreeNodeId save_id= cursor->node_id;
1097
1098
1099 tv= (TreeViewPtr)getTree4Cursor(cursor);
1100 if((node_data= getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id)) == NULL) {
1101 return FALSE;
1102 }
1103
1104 if(do_callBack && (tv->evntFunc != NULL)) {
1105 (*(tv->evntFunc))(cursor, TVIEW_ON_OPEN);
1106 Select(tv->draw_port.tree_panel);
1107 tree_toNode(cursor, save_id);
1108 }
1109
1110 length= getNodeLength(cursor);
1111
1112 node_data->h= tv->row_height;
1113
1114 node_data->w= calcNodeWidth(tv, (tv->i_list == NULL)? -1 : getIconId(cursor),
1115 length, getNodeLabel(cursor));
1116
1117 xm= ((tv->length_scale >= 0)?
1118 (tv->length_scale * length) : (length/(-tv->length_scale)));
1119
1120 ym= tv->row_height;
1121
1122 if(!tree_child(cursor)) return FALSE;
1123
1124 /* we don't need to sort siblings */
1125 do {
1126 if(makeNodeVisible(cursor)) {
1127 node_box.xl= node_box.xr= xm;
1128 node_box.yt= node_box.yb= ym;
1129 if(getBox4Cursor(cursor, &node_box)) {
1130 ym= node_box.yb;
1131 if(node_data->w < node_box.xr) node_data->w= node_box.xr;
1132 }
1133 ++n;
1134 }
1135 }
1136 while (tree_sibling(cursor));
1137
1138
1139 node_data->h= ym;
1140
1141 tree_parent(cursor);
1142
1143 if(tv->cmpSiblings != NULL) {
1144 if(n > 100) WatchCursor();
1145 sortSiblings(cursor, n);
1146 if(n > 100) ArrowCursor();
1147 }
1148
1149 adjust_parentSize(cursor);
1150
1151 return TRUE;
1152 }
1153
1154 static Boolean closeSubtree(TreeCursorPtr cursor, Boolean do_callBack)
1155 {
1156 TreeViewPtr tv;
1157 _tnSegmPtr tsp;
1158 Int2 icon_id;
1159 Int4 length;
1160 CharPtr label;
1161 TreeNodeId nid= cursor->node_id;
1162
1163
1164 tv= (TreeViewPtr) getTree4Cursor(cursor);
1165 if((tsp= getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id)) == NULL) {
1166 return FALSE;
1167 }
1168
1169 if(do_callBack && (tv->evntFunc != NULL)) {
1170 (*(tv->evntFunc))(cursor, TVIEW_ON_CLOSE);
1171 Select(tv->draw_port.tree_panel);
1172 tree_toNode(cursor, nid);
1173 }
1174
1175 /* check if selected node belongs to subtree to close */
1176 if(cursor->node_id.idi != tv->cr2->node_id.idi) {
1177 if(tree_isDescendant(cursor, tv->cr2)) {
1178 /* it is, so move select to cursor */
1179 tree_toNode(tv->cr2, cursor->node_id);
1180 tv->sel_y= -1024;
1181 }
1182 }
1183
1184 icon_id= (tv->i_list == NULL)? -1 : getIconId(cursor);
1185 length= getNodeLength(cursor);
1186 label= getNodeLabel(cursor);
1187
1188 tsp->h= tv->row_height;
1189
1190 tsp->w= calcNodeWidth(tv, icon_id, length, label);
1191
1192 if(tree_child(cursor)) {
1193 do {
1194 freeNodeSegm(cursor);
1195 }
1196 while (tree_sibling(cursor));
1197 tree_parent(cursor);
1198 }
1199
1200 adjust_parentSize(cursor);
1201
1202
1203 return TRUE;
1204 }
1205
1206 /*****************************************************************************
1207 *
1208 * TreeVScrollProc (sb, viewer, newval, oldval)
1209 *
1210 *****************************************************************************/
1211
1212 static void TreeVScrollProc (BaR sb, SlatE viewer, Int2 newval, Int2 oldval)
1213
1214 {
1215 TreeViewPtr tv;
1216 Int2 height;
1217 Int4 offsetY;
1218 Int2 pixels;
1219 RecT r;
1220 Int2 visLines;
1221
1222 if (viewer != NULL && oldval != newval) {
1223 if (Visible(viewer) && AllParentsVisible (viewer)) {
1224 GetPanelExtra((PaneL) viewer, &tv);
1225 ObjectRect(viewer, &r);
1226 InsetRect (&r, 1, 1);
1227 height = r.bottom - r.top;
1228
1229 visLines = (height) / tv->row_height;
1230
1231 Select (viewer);
1232 if((newval > oldval && newval - visLines + 1 <= oldval) ||
1233 (newval < oldval && newval + visLines - 1 >= oldval)) {
1234 pixels = (newval - oldval) * tv->row_height;
1235 if (ABS(pixels) < height) {
1236 ScrollRect (&r, 0, -pixels);
1237 if (pixels > 0) {
1238 r.top = r.bottom - pixels;
1239 }
1240 else {
1241 r.bottom = r.top - pixels;
1242 }
1243 InsetRect (&r, -1, -1);
1244 InvalRect (&r);
1245 }
1246 else {
1247 InsetRect (&r, -1, -1);
1248 InvalRect (&r);
1249 }
1250 }
1251 else {
1252 InsetRect (&r, -1, -1);
1253 InvalRect (&r);
1254 }
1255
1256 offsetY= tv->row_height * (Int4) (newval - oldval);
1257 tv->draw_port.port_origin.y+= offsetY;
1258
1259 /* calculate clip box for given rect */
1260 Rect2Box(&tv->draw_port, &r, &tv->draw_port.clip_box);
1261
1262 Update ();
1263
1264 setPort2Panel(&tv->draw_port); /* resize clip box to whole panel */
1265 }
1266 }
1267 }
1268
1269 /*****************************************************************************
1270 *
1271 * TreeHScrollProc (sb, viewer, newval, oldval)
1272 *
1273 *****************************************************************************/
1274
1275 static void TreeHScrollProc (BaR sb, SlatE viewer, Int2 newval, Int2 oldval)
1276
1277 {
1278 TreeViewPtr tv;
1279 Int4 lineWidth;
1280 Int4 offsetX;
1281 Int2 pixels;
1282 RecT r;
1283 Int2 visLines;
1284 Int2 width;
1285
1286 if(viewer != NULL && oldval != newval) {
1287 if(Visible (viewer) && AllParentsVisible (viewer)) {
1288 GetPanelExtra ((PaneL)viewer, &tv);
1289 ObjectRect (viewer, &r);
1290 InsetRect (&r, 1, 1);
1291 width = r.right - r.left;
1292 lineWidth= tv->row_width;
1293 visLines = (width) / lineWidth;
1294
1295 Select (viewer);
1296 if((newval > oldval && newval - visLines + 1 <= oldval) ||
1297 (newval < oldval && newval + visLines - 1 >= oldval)) {
1298 pixels= (newval - oldval) * lineWidth;
1299 if (ABS (pixels) < width) {
1300 ScrollRect (&r, -pixels, 0);
1301 if (pixels > 0) {
1302 r.left = r.right - pixels;
1303 }
1304 else {
1305 r.right = r.left - pixels;
1306 }
1307 InsetRect (&r, -1, -1);
1308 InvalRect (&r);
1309 }
1310 else {
1311 InsetRect (&r, -1, -1);
1312 InvalRect (&r);
1313 }
1314 }
1315 else {
1316 InsetRect (&r, -1, -1);
1317 InvalRect (&r);
1318 }
1319
1320 offsetX = lineWidth * (Int4) (newval - oldval);
1321 tv->draw_port.port_origin.x+= offsetX;
1322
1323 /* calculate clip box for given rect */
1324 Rect2Box(&tv->draw_port, &r, &tv->draw_port.clip_box);
1325
1326 Update ();
1327
1328 setPort2Panel(&tv->draw_port); /* resize clip box to whole panel */
1329
1330 }
1331 }
1332 }
1333
1334 static void CorrectScrollbar(BaR sb, Int4 unitSize, Int4 tree_size, Int4 port_min, Int4 port_max)
1335 {
1336
1337 if (sb != NULL) {
1338 Int4 numUnits= ((tree_size < port_max)? port_max : tree_size)/unitSize;
1339 Int4 visUnits= (port_max - port_min + 1)/unitSize;
1340 Int2 max_val= (Int2)MAX((numUnits - visUnits), 0);
1341 Int2 val = (Int2) (port_min / unitSize);
1342
1343 CorrectBarMax (sb, max_val);
1344 CorrectBarValue(sb, val);
1345 CorrectBarPage (sb, (Int2)(visUnits - 1), (Int2)(visUnits - 1));
1346 }
1347 }
1348
1349 static void DrawTreeProc(PaneL tree_panel)
1350 {
1351 TreeViewPtr tv;
1352
1353 if(tree_panel != NULL) {
1354 GetPanelExtra (tree_panel, &tv);
1355 if(tv->draw_port.bg_color_set == 0) {
1356 Uint4 def_col= GetColor();
1357 RecT r;
1358
1359 GetPosition(tree_panel, &r);
1360 tv->draw_port.panel_origin_X= r.left;
1361 tv->draw_port.panel_origin_Y= r.top;
1362 if(tv->draw_port.line_color_set == 0) tv->draw_port.line_color= def_col;
1363 if(tv->draw_port.text_color_set == 0) tv->draw_port.text_color= def_col;
1364 if(tv->draw_port.plus_color_set == 0) tv->draw_port.plus_color= tv->draw_port.line_color;
1365 if(tv->draw_port.sbg_color_set == 0) tv->draw_port.sbg_color= def_col;
1366
1367 InvertColors();
1368 def_col= GetColor();
1369 tv->draw_port.bg_color_set= 1;
1370 tv->draw_port.bg_color= def_col;
1371 if(tv->draw_port.sfg_color_set == 0) tv->draw_port.sfg_color= def_col;
1372 InvertColors();
1373
1374 if(tv->draw_port.line_color == tv->draw_port.bg_color) {
1375 Black();
1376 tv->draw_port.line_color= tv->draw_port.text_color= tv->draw_port.sbg_color= GetColor();
1377 White();
1378 tv->draw_port.bg_color= tv->draw_port.sfg_color= GetColor();
1379 }
1380 }
1381 tree_toNode(tv->cr1, tv->my_root); /*tree_root(tv->cr1);*/
1382 drawTree(tv->cr1, TREE_X0, TREE_Y0);
1383 }
1384 }
1385
1386 /*----------------------------------------------------------
1387 * find node with coordinate x, y
1388 */
1389 static Int2 find_node4xy(TreeCursorPtr cursor, Int4 my_x, Int4 my_y, Int4Ptr px, Int4Ptr py)
1390 {
1391 _box my_box;
1392 Int4 length;
1393 TreeViewPtr tv;
1394 Int2 res;
1395
1396 my_box.xl= my_box.xr= my_x;
1397 my_box.yt= my_box.yb= my_y;
1398
1399 if(!getBox4Cursor(cursor, &my_box)) return 0;
1400
1401 my_box.xl-= 4;
1402 my_box.xr+= 4;
1403
1404 if(!ptInBox(&my_box, *px, *py)) return 0;
1405
1406 tv= (TreeViewPtr) getTree4Cursor(cursor);
1407
1408 length= getNodeLength(cursor);
1409 my_x+= ((tv->length_scale >= 0)?
1410 (tv->length_scale * length) : (length/(-tv->length_scale)));
1411
1412 if(*py <= (my_y+= tv->row_height)) {
1413 /* we are on node itself */
1414 Int2 res= (*px < my_x)? 1 : 2;
1415 *px= my_box.xl + 4;
1416 *py= my_box.yt;
1417 return res;
1418 }
1419
1420 if(*px < (my_x - 4)) return 0;
1421
1422 /* we are on nodes children */
1423 if(tree_child(cursor)) {
1424
1425 if(tv->cmpSiblings == NULL) {
1426 /* we don't want to sort siblings */
1427 do {
1428 if((res= find_node4xy(cursor, my_x, my_y, px, py)) != 0) {
1429 return res;
1430 }
1431 my_box.xl= my_box.xr= my_x;
1432 my_box.yt= my_box.yb= my_y;
1433 getBox4Cursor(cursor, &my_box);
1434 my_y= my_box.yb;
1435 }
1436 while (tree_sibling(cursor));
1437 }
1438 else {/* siblings have to be sorted */
1439 TreeNodeId id;
1440
1441 for(id.idi= 0; (id= getNextSibling(cursor, id)).idi != 0;) {
1442 if((res= find_node4xy(cursor, my_x, my_y, px, py)) != 0) {
1443 return res;
1444 }
1445 my_box.xl= my_box.xr= my_x;
1446 my_box.yt= my_box.yb= my_y;
1447 getBox4Cursor(cursor, &my_box);
1448 my_y= my_box.yb;
1449 }
1450 }
1451
1452 tree_parent(cursor);
1453 }
1454
1455 return 0;
1456 }
1457
1458
1459 /*----------------------------------------------------------
1460 * this function set cursor (cr1) on selected node and return
1461 * the type of element selected
1462 */
1463 static Int2 find_Node4Point(TreeViewPtr tv, Int4Ptr x, Int4Ptr y)
1464 {
1465 tree_toNode(tv->cr1, tv->my_root); /*tree_root(tv->cr1);*/
1466 return find_node4xy(tv->cr1, TREE_X0, TREE_Y0, x, y);
1467 }
1468
1469 static void node_open_close(TreeCursorPtr cursor, Int4 x, Int4 y)
1470 {
1471 TreeViewPtr tv= (TreeViewPtr) getTree4Cursor(cursor);
1472 _tnSegmPtr tns;
1473 Boolean need_resize;
1474
1475 tns= getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id);
1476 if(tns == NULL) return;
1477
1478 need_resize= (tns->h > tv->row_height)? closeSubtree(tv->cr1, TRUE) : openSubtree(tv->cr1, TRUE);
1479
1480 if(need_resize) {
1481 tree_toNode(cursor, tv->my_root); /*tree_root(cursor);*/
1482 tns= getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id);
1483
1484 setPort2Panel(&tv->draw_port);
1485
1486 CorrectScrollbar(GetSlateHScrollBar((SlatE)(tv->draw_port.tree_panel)),
1487 tv->row_width, tns->w + 16, tv->draw_port.clip_box.xl, tv->draw_port.clip_box.xr);
1488
1489 CorrectScrollbar(GetSlateVScrollBar((SlatE)(tv->draw_port.tree_panel)),
1490 tv->row_height, tns->h + 24, tv->draw_port.clip_box.yt, tv->draw_port.clip_box.yb);
1491
1492 if(tv->sel_y > y) {
1493 /* selected node has been moved */
1494 tv->sel_y= -1024;
1495 }
1496
1497 /* redraw all below y */
1498 tv->draw_port.clip_box.yt= y;
1499 redrawInPort(tv);
1500 setPort2Panel(&tv->draw_port);
1501 }
1502 }
1503
1504 static CharPtr calcBox4Select(TreeCursorPtr cursor, Int4 x0, Int4 y0, _boxPtr sel_box)
1505 {
1506 TreeViewPtr tv= (TreeViewPtr) getTree4Cursor(cursor);
1507 Int4 length= getNodeLength(cursor);
1508 Int2 icon_id= getIconId(cursor);
1509 CharPtr label= getNodeLabel(cursor);
1510
1511 sel_box->xl= x0 +
1512 ((tv->length_scale >= 0)? (tv->length_scale * length) : (length/(-tv->length_scale))) +
1513 (((tv->i_list != NULL) && (icon_id >= 0))? (getIconWidth(tv->i_list, icon_id)/2) : 0);
1514 sel_box->xr= x0 + calcNodeWidth(tv, icon_id, length, label);
1515 sel_box->yt= y0;
1516 sel_box->yb= y0 + tv->row_height;
1517 return label;
1518 }
1519
1520 static void select_treeNode(TreeCursorPtr cursor, Int4 x, Int4 y)
1521 {
1522 TreeViewPtr tv= (TreeViewPtr) getTree4Cursor(cursor);
1523 _box my_box;
1524 CharPtr label;
1525
1526 setPort2Panel(&tv->draw_port);
1527 Select(tv->draw_port.tree_panel);
1528
1529 #if 0
1530 if(tv->evntFunc != NULL) {
1531 (*(tv->evntFunc))(cursor, TVIEW_ON_SELECT);
1532 Select(tv->draw_port.tree_panel);
1533 }
1534 #endif
1535
1536
1537 if(tv->sel_y >= 0) {
1538 /* we have selected node */
1539
1540 /* check if selected node is in window */
1541 if((tv->sel_y < tv->draw_port.clip_box.yb) &&
1542 ((tv->sel_y + tv->row_height) > tv->draw_port.clip_box.yt)) {
1543 /* yes it is, we have to unselect it */
1544 label= calcBox4Select(tv->cr2, tv->sel_x, tv->sel_y, &my_box);
1545 unHighLightBox(&tv->draw_port, &my_box, label);
1546 }
1547 }
1548
1549 /* select the new one */
1550 label= calcBox4Select(cursor, x, y, &my_box);
1551 highLightBox(&tv->draw_port, &my_box, label);
1552 tv->sel_x= x;
1553 tv->sel_y= y;
1554 tree_toNode(tv->cr2, tree_getId(cursor));
1555 }
1556
1557 /*****************************************************************************
1558 *
1559 * ViewerClickProc (viewer, pt)
1560 *
1561 *****************************************************************************/
1562
1563 static void ViewerClickProc (PaneL viewer, PoinT pt)
1564
1565 {
1566 TreeViewPtr tv;
1567 Int4 x, y;
1568 TreeNodeId id;
1569
1570 GetPanelExtra (viewer, &tv);
1571
1572 x= (pt.x - tv->draw_port.panel_origin_X) + tv->draw_port.port_origin.x;
1573 y= (pt.y - tv->draw_port.panel_origin_Y) + tv->draw_port.port_origin.y;
1574
1575 switch (find_Node4Point(tv, &x, &y)) {
1576 case 0: /* nothing selected */
1577 id.idi= 0;
1578 if(dblClick && (tv->dblClickFunc != NULL)) (*tv->dblClickFunc)(tv, id, FALSE);
1579 else if(shftKey && (tv->shiftClickFunc != NULL))
1580 (*tv->shiftClickFunc)(tv, id, FALSE);
1581 else if(ctrlKey && (tv->ctrlClickFunc != NULL))
1582 (*tv->ctrlClickFunc)(tv, id, FALSE);
1583 return;
1584 case 1:
1585 /* open/close subtree for this node */
1586 if(dblClick && (tv->dblClickFunc != NULL)) (*tv->dblClickFunc)(tv, tv->cr1->node_id, FALSE);
1587 else if(shftKey && (tv->shiftClickFunc != NULL))
1588 (*tv->shiftClickFunc)(tv, tv->cr1->node_id, FALSE);
1589 else if(ctrlKey && (tv->ctrlClickFunc != NULL))
1590 (*tv->ctrlClickFunc)(tv, tv->cr1->node_id, FALSE);
1591 else node_open_close(tv->cr1, x, y);
1592 return;
1593
1594 case 2:
1595 /* select new node */
1596 if(dblClick && (tv->dblClickFunc != NULL)) (*tv->dblClickFunc)(tv, tv->cr1->node_id, TRUE);
1597 else if(shftKey && (tv->shiftClickFunc != NULL))
1598 (*tv->shiftClickFunc)(tv, tv->cr1->node_id, TRUE);
1599 else if(ctrlKey && (tv->ctrlClickFunc != NULL))
1600 (*tv->ctrlClickFunc)(tv, tv->cr1->node_id, TRUE);
1601 else select_treeNode(tv->cr1, x, y);
1602 return;
1603 }
1604 }
1605
1606 #if 0
1607 static void ViewerHoldProc (PaneL viewer, PoinT pt)
1608
1609 {
1610 TreeViewPtr tv;
1611 Int4 x, y;
1612
1613
1614 GetPanelExtra (viewer, &tv);
1615
1616 if(tv->holdFunc == NULL) return;
1617
1618 x= (pt.x - tv->draw_port.panel_origin_X) + tv->draw_port.port_origin.x;
1619 y= (pt.y - tv->draw_port.panel_origin_Y) + tv->draw_port.port_origin.y;
1620
1621 switch (find_Node4Point(tv, &x, &y)) {
1622 case 0: /* nothing selected */
1623 (*tv->holdFunc)(tv, tv->cr2->node_id, FALSE);
1624 return;
1625 case 1:
1626 /* open/close subtree for this node */
1627 (*tv->holdFunc)(tv, tv->cr1->node_id, FALSE);
1628 return;
1629
1630 case 2:
1631 /* select new node */
1632 (*tv->holdFunc)(tv, tv->cr1->node_id, TRUE);
1633 return;
1634 }
1635 }
1636 #endif
1637
1638 /*
1639 typedef enum {
1640 TREE_CURSOR_MOVED = 0,
1641 TREE_NODE_UPDATE,
1642 TREE_NODE_UPD_DONE,
1643 TREE_NODEDATA_UPDATE,
1644 TREE_NODEDATA_UPD_DONE,
1645 TREE_NODE_DELETE,
1646 TREE_NODE_DEL_DONE,
1647 TREE_NODE_MOVE,
1648 TREE_NODE_MV_DONE,
1649 TREE_NODE_MERGE,
1650 TREE_NODE_MERGE_DONE,
1651 TREE_CHILDREN_MOVE,
1652 TREE_CHILDREN_MV_DONE,
1653 TREE_NODE_ADDED,
1654 TREE_SUBTREE_DELETE,
1655 TREE_SUBTREE_DEL_DONE
1656 } TreeEvent;
1657 */
1658 static void spy_proc(TreePtr tree, Int2 spy_id, TreeEvent event,
1659 TreeNodeId id1, TreeNodeId id2, VoidPtr node_data,
1660 Int2 node_data_size)
1661 {
1662 static int tran_level= 0;
1663 static TreeEvent tran_stack[8];
1664 TreeViewPtr tv= (TreeViewPtr) tree_getSpyData(tree, spy_id);
1665 _tnSegmPtr tns;
1666 Boolean need_redraw= FALSE;
1667
1668 switch(event) {
1669 case TREE_NODE_UPDATE: /* node will be updated */
1670 tree_toNode(tv->cr4, id1);
1671 if(getNodeViewerData((_tnSegmPtr)tv->cr4->node->sys_data, tv->my_spy_id) != NULL) {
1672 freeNodeSegm(tv->cr4);
1673 tran_stack[tran_level++]= TREE_NODE_UPDATE;
1674 }
1675 else {
1676 tran_stack[tran_level++]= TREE_CURSOR_MOVED;
1677 }
1678 break;
1679 case TREE_NODE_UPD_DONE: /* node was updated */
1680 case TREE_NODEDATA_UPD_DONE:
1681 if(tran_stack[--tran_level] == TREE_NODE_UPDATE) {
1682 if(tree_parent(tv->cr4)) {
1683 openSubtree(tv->cr4, FALSE);
1684 }
1685 else {
1686 makeNodeVisible(tv->cr4);
1687 }
1688 need_redraw= TRUE;
1689 }
1690 break;
1691
1692 case TREE_NODEDATA_UPDATE: /* node will be updated */
1693 if(tran_stack[tran_level - 1] == TREE_NODE_UPDATE) {
1694 tran_stack[tran_level++]= TREE_CURSOR_MOVED;
1695 }
1696 else {
1697 tree_toNode(tv->cr4, id1);
1698 if(getNodeViewerData((_tnSegmPtr)tv->cr4->node->sys_data, tv->my_spy_id) != NULL) {
1699 freeNodeSegm(tv->cr4);
1700 tran_stack[tran_level++]= TREE_NODE_UPDATE;
1701 }
1702 else {
1703 tran_stack[tran_level++]= TREE_CURSOR_MOVED;
1704 }
1705 }
1706 break;
1707
1708 case TREE_NODE_DELETE: /* node will be deleted */
1709 tree_toNode(tv->cr4, id1);
1710 if(getNodeViewerData((_tnSegmPtr)tv->cr4->node->sys_data, tv->my_spy_id) != NULL) {
1711 freeNodeSegm(tv->cr4);
1712 tran_stack[tran_level++]= TREE_NODE_DELETE;
1713 tree_toNode(tv->cr4, id2);
1714 closeSubtree(tv->cr4, FALSE);
1715 }
1716 else {
1717 tran_stack[tran_level++]= TREE_CURSOR_MOVED;
1718 }
1719 tree_parent(tv->cr4);
1720 break;
1721
1722 case TREE_SUBTREE_DEL_DONE:
1723 case TREE_NODE_DEL_DONE: /* node was deleted */
1724 tree_toNode(tv->cr4, id1);
1725 if(tran_stack[--tran_level] == TREE_NODE_DELETE) {
1726 openSubtree(tv->cr4, FALSE);
1727 need_redraw= TRUE;
1728 }
1729 break;
1730
1731 case TREE_NODE_MOVE: /* node will be moved */
1732 tree_toNode(tv->cr4, id2);
1733 if(getNodeViewerData((_tnSegmPtr)tv->cr4->node->sys_data, tv->my_spy_id) != NULL) {
1734 /* node is visible */
1735 tree_parent(tv->cr4);
1736 }
1737 else {
1738 tree_toNode(tv->cr4, id1);
1739 }
1740 break;
1741
1742 case TREE_NODE_MV_DONE: /* node has been moved */
1743 if(tv->cr4->node_id.idi != id1.idi) {
1744 need_redraw= openSubtree(tv->cr4, FALSE);
1745 tree_toNode(tv->cr4, id1);
1746 }
1747 need_redraw|= openSubtree(tv->cr4, FALSE);
1748 break;
1749
1750 case TREE_CHILDREN_MOVE: /* children will be moved */
1751 tree_toNode(tv->cr4, id2);
1752 if(((tns= getNodeViewerData((_tnSegmPtr)tv->cr4->node->sys_data, tv->my_spy_id)) != NULL) &&
1753 (tns->h > tv->row_height)) {
1754 need_redraw= closeSubtree(tv->cr4, TRUE);
1755 }
1756 break;
1757
1758 case TREE_CHILDREN_MV_DONE: /* children have been moved */
1759 tree_toNode(tv->cr4, id1);
1760 if((tns= getNodeViewerData((_tnSegmPtr)tv->cr4->node->sys_data, tv->my_spy_id)) == NULL) {
1761 /* this node is invisible */
1762 for(need_redraw= tree_child(tv->cr4); need_redraw; need_redraw= tree_sibling(tv->cr4)) {
1763 if(getNodeViewerData((_tnSegmPtr)tv->cr4->node->sys_data, tv->my_spy_id) != NULL) {
1764 freeNodeSegm(tv->cr4);
1765 }
1766 }
1767 }
1768 else {
1769 closeSubtree(tv->cr4, FALSE);
1770 need_redraw= openSubtree(tv->cr4, TRUE);
1771 }
1772 break;
1773
1774 case TREE_SUBTREE_DELETE: /* subtree will be deleted */
1775 tree_toNode(tv->cr4, id1);
1776 if(getNodeViewerData((_tnSegmPtr)tv->cr4->node->sys_data, tv->my_spy_id) != NULL) {
1777 /* this node is visible */
1778
1779 tran_stack[tran_level++]= TREE_NODE_DELETE;
1780 }
1781 else {
1782 tran_stack[tran_level++]= TREE_CURSOR_MOVED;
1783 }
1784 closeAllSubtrees(tv->cr4);
1785 tree_parent(tv->cr4);
1786 break;
1787
1788 case TREE_NODE_MERGE: /* nodes will be merged */
1789 tree_toNode(tv->cr4, id2);
1790 if(getNodeViewerData((_tnSegmPtr)tv->cr4->node->sys_data, tv->my_spy_id) != NULL) {
1791 /* this node is visible */
1792 freeNodeSegm(tv->cr4);
1793 }
1794 break;
1795
1796 case TREE_NODE_MERGE_DONE: /* nodes was merged */
1797 tree_toNode(tv->cr4, id2);
1798 openSubtree(tv->cr4, TRUE);
1799 tree_toNode(tv->cr4, id1);
1800 openSubtree(tv->cr4, TRUE);
1801 need_redraw= TRUE;
1802 break;
1803
1804 case TREE_NODE_ADDED: /* new node was added */
1805 tree_toNode(tv->cr4, id1);
1806 need_redraw= openSubtree(tv->cr4, TRUE);
1807 break;
1808
1809 case TREE_CURSOR_MOVED:
1810 break; /* do nothing */
1811
1812 case TREE_SHUTDOWN:
1813 break;
1814 }
1815
1816
1817
1818 if(need_redraw) {
1819 tree_toNode(tv->cr4, tv->my_root); /*tree_root(tv->cr4);*/
1820 tns= getNodeViewerData((_tnSegmPtr)tv->cr4->node->sys_data, tv->my_spy_id);
1821
1822 setPort2Panel(&tv->draw_port);
1823
1824 CorrectScrollbar(GetSlateHScrollBar((SlatE)(tv->draw_port.tree_panel)),
1825 tv->row_width, tns->w + 16, tv->draw_port.clip_box.xl, tv->draw_port.clip_box.xr);
1826
1827 CorrectScrollbar(GetSlateVScrollBar((SlatE)(tv->draw_port.tree_panel)),
1828 tv->row_height, tns->h + 24, tv->draw_port.clip_box.yt, tv->draw_port.clip_box.yb);
1829 tv->sel_y= -1024;
1830 tview_redraw(tv);
1831 }
1832 }
1833
1834 static void close_proc(WindoW w)
1835 {
1836 TreeViewPtr tv= (TreeViewPtr) GetWindowExtra(w);
1837
1838 tview_delete(tv, 0);
1839 }
1840
1841 static void resize_proc(WindoW w)
1842 {
1843 TreeViewPtr tv= (TreeViewPtr) GetWindowExtra(w);
1844 RecT r;
1845 _tnSegmPtr tns;
1846
1847 setPort2Panel(&tv->draw_port);
1848 Nlm_GetRect((GraphiC)w, &r);
1849 r.right-= r.left + 10;
1850 r.left= 10;
1851 r.bottom-= r.top + 10;
1852 r.top= 10;
1853 SetPosition(tv->draw_port.tree_panel, &r);
1854
1855 tv->draw_port.panel_origin_X= r.left;
1856 tv->draw_port.panel_origin_Y= r.top;
1857
1858 InsetRect(&r, 1, 1);
1859 tv->draw_port.clip_box.xr= tv->draw_port.clip_box.xl + (r.right - r.left - Nlm_vScrollBarWidth);
1860 tv->draw_port.clip_box.yb= tv->draw_port.clip_box.yt + (r.bottom - r.top - Nlm_hScrollBarHeight);
1861
1862 /* we need to correct scroll bars here */
1863 tree_toNode(tv->cr1, tv->my_root); /*tree_root(tv->cr1);*/
1864 tns= getNodeViewerData((_tnSegmPtr)tv->cr1->node->sys_data, tv->my_spy_id);
1865
1866 CorrectScrollbar(GetSlateHScrollBar((SlatE)(tv->draw_port.tree_panel)),
1867 tv->row_width, tns->w + 16, tv->draw_port.clip_box.xl, tv->draw_port.clip_box.xr);
1868
1869 CorrectScrollbar(GetSlateVScrollBar((SlatE)(tv->draw_port.tree_panel)),
1870 tv->row_height, tns->h + 24, tv->draw_port.clip_box.yt, tv->draw_port.clip_box.yb);
1871
1872 Select(tv->draw_port.tree_panel);
1873 InvalRect (&r);
1874 /* Black();
1875 FrameRect(&r);*/
1876 Update();
1877 }
1878
1879 void tview_resize(TreeViewPtr tv, RectPtr r)
1880 {
1881 _tnSegmPtr tns;
1882
1883 SetPosition(tv->draw_port.tree_panel, r);
1884
1885 tv->draw_port.panel_origin_X= r->left;
1886 tv->draw_port.panel_origin_Y= r->top;
1887
1888 InsetRect(r, 1, 1);
1889 tv->draw_port.clip_box.xr= tv->draw_port.clip_box.xl + (r->right - r->left - Nlm_vScrollBarWidth);
1890 tv->draw_port.clip_box.yb= tv->draw_port.clip_box.yt + (r->bottom - r->top - Nlm_hScrollBarHeight);
1891
1892 /* we need to correct scroll bars here */
1893 tree_toNode(tv->cr1, tv->my_root); /*tree_root(tv->cr1);*/
1894 tns= getNodeViewerData((_tnSegmPtr)tv->cr1->node->sys_data, tv->my_spy_id);
1895
1896 CorrectScrollbar(GetSlateHScrollBar((SlatE)(tv->draw_port.tree_panel)),
1897 tv->row_width, tns->w + 16, tv->draw_port.clip_box.xl, tv->draw_port.clip_box.xr);
1898
1899 CorrectScrollbar(GetSlateVScrollBar((SlatE)(tv->draw_port.tree_panel)),
1900 tv->row_height, tns->h + 24, tv->draw_port.clip_box.yt, tv->draw_port.clip_box.yb);
1901 Select(tv->draw_port.tree_panel);
1902 InvalRect (r);
1903 Update();
1904 }
1905
1906 static void tv_cr2_callback(TreeCursorPtr cursor, TreeEvent event, TreeNodeId id)
1907 {
1908 if(event == TREE_CURSOR_MOVED) {
1909 TreeViewPtr tv= (TreeViewPtr) getTree4Cursor(cursor);
1910
1911 if(tv->evntFunc != NULL) {
1912 (*(tv->evntFunc))(cursor, TVIEW_ON_SELECT);
1913 Select(tv->draw_port.tree_panel);
1914 }
1915 }
1916 }
1917
1918 static void tv_cr5_callback(TreeCursorPtr cursor, TreeEvent event, TreeNodeId id)
1919 {
1920 if(event == TREE_CURSOR_MOVED) {
1921 TreeViewPtr tv= (TreeViewPtr) getTree4Cursor(cursor);
1922
1923 tv->my_root= id;
1924 if(getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id) == NULL) {
1925 tree_parent(cursor);
1926 }
1927 }
1928 }
1929
1930
1931 TreeViewPtr tview_create(GrouP parent, Int2 width, Int2 height,
1932 TreePtr tree, _ImageListPtr il, Int2 l_scale,
1933 TreeNodeCmpFunc NodeCmp)
1934 {
1935 TreeViewPtr tv;
1936 /* int i; */
1937 _tnSegmPtr tns;
1938
1939 if((tv= (TreeViewPtr) MemNew(sizeof(TreeView))) == NULL) return NULL;
1940
1941 if((tv->segm_buff= getNewSegmBuff()) == NULL) {
1942 MemFree(tv);
1943 return NULL;
1944 }
1945
1946
1947 if(parent == NULL) {
1948 /* we need to create window for tree view */
1949 tv->draw_port.tree_window= DocumentWindow(-50, -33, -10, -10, "Tree View", close_proc, resize_proc);
1950 parent= tv->draw_port.tree_window;
1951 SetWindowExtra(tv->draw_port.tree_window, tv, NULL);
1952 }
1953 else tv->draw_port.tree_window= NULL;
1954
1955 /* create panel */
1956 tv->draw_port.tree_panel= AutonomousPanel(parent, width, height, DrawTreeProc,
1957 TreeVScrollProc, TreeHScrollProc,
1958 sizeof(TreeViewPtr), NULL, NULL);
1959
1960 if(tv->draw_port.tree_panel == NULL) {
1961 MemFree(tv->segm_buff);
1962 MemFree(tv);
1963 return NULL;
1964 }
1965
1966 SetPanelClick (tv->draw_port.tree_panel, ViewerClickProc, NULL, NULL, NULL);
1967
1968 SetPanelExtra(tv->draw_port.tree_panel, &tv);
1969
1970 tv->i_list= il;
1971
1972 /* populate tv structure */
1973 tv->tree= tree;
1974
1975 tv->cr1= tree_openCursor(tree, tv, NULL);
1976 tv->cr2= tree_openCursor(tree, tv, tv_cr2_callback);
1977 tv->cr3= NULL;
1978 tv->cr4= tree_openCursor(tree, tv, NULL);
1979
1980 tv->my_spy_id= tree_addSpy(tree, spy_proc, tv);
1981
1982 /* draw port setup */
1983 tv->draw_port.panel_origin_X= tv->draw_port.panel_origin_Y= 0;
1984 tv->draw_port.port_origin.x= 0;
1985 tv->draw_port.port_origin.y= 0;
1986
1987 /*Black();*/
1988 tv->draw_port.clip_box.xl= 0;
1989 tv->draw_port.clip_box.yt= 0;
1990 tv->draw_port.clip_box.xr= width;
1991 tv->draw_port.clip_box.yb= height;
1992 tv->draw_port.line_color= tv->draw_port.text_color= tv->draw_port.sbg_color= 0;
1993 tv->draw_port.line_color_set= tv->draw_port.text_color_set= tv->draw_port.sbg_color_set= 0;
1994 /* InvertColors(); */
1995 tv->draw_port.bg_color= tv->draw_port.sfg_color= 0;
1996 tv->draw_port.bg_color_set= tv->draw_port.sfg_color_set= 0;
1997 tv->draw_port.plus_color= 0;
1998 tv->draw_port.plus_color_set= 0;
1999 /*InvertColors();*/
2000
2001 tv->draw_port.pen_w= 1;
2002
2003 tv->row_height= FontHeight() + 2;
2004 /*tv->row_height+= tv->row_height/4;*/
2005 tv->row_width= CharWidth('w');
2006 if(tv->row_width < 4) tv->row_width= 4;
2007
2008 tv->length_scale= (l_scale == 0)? 1 : l_scale;
2009
2010 tv->sel_y= -1024;
2011
2012 /* prepare root node for drawing */
2013 tns= allocNewSegm(tv->cr1);
2014 tns->w= calcNodeWidth(tv, getIconId(tv->cr1), getNodeLength(tv->cr1), getNodeLabel(tv->cr1));
2015 tns->h= tv->row_height;
2016
2017 tv->cmpSiblings= NodeCmp;
2018 tv->dblClickFunc= NULL;
2019 tv->shiftClickFunc= NULL;
2020 tv->ctrlClickFunc= NULL;
2021
2022 tv->cr5= tree_openCursor(tree, tv, tv_cr5_callback);
2023
2024 tv->my_root= tv->cr5->node_id;
2025
2026 openSubtree(tv->cr1, TRUE);
2027
2028 if(tv->draw_port.tree_window != NULL) {
2029 RealizeWindow(tv->draw_port.tree_window);
2030 Show(tv->draw_port.tree_window);
2031 }
2032 return tv;
2033 }
2034
2035
2036 TreeViewPtr tview_createCustom(Int2 left, Int2 top, Int2 width, Int2 height,
2037 CharPtr title, void (*menuCrtFunc)(WindoW),
2038 TreePtr tree, _ImageListPtr il, Int2 l_scale,
2039 TreeNodeCmpFunc NodeCmp)
2040 {
2041 TreeViewPtr tv;
2042 /* int i; */
2043 _tnSegmPtr tns;
2044
2045 if((tv= (TreeViewPtr) MemNew(sizeof(TreeView))) == NULL) return NULL;
2046
2047 if((tv->segm_buff= getNewSegmBuff()) == NULL) {
2048 MemFree(tv);
2049 return NULL;
2050 }
2051
2052
2053 /* we need to create window for tree view */
2054 tv->draw_port.tree_window= DocumentWindow(left, top, -10, -10, title, close_proc, resize_proc);
2055 SetWindowExtra(tv->draw_port.tree_window, tv, NULL);
2056
2057 if(menuCrtFunc != NULL) (*menuCrtFunc)(tv->draw_port.tree_window);
2058
2059 /* create panel */
2060 tv->draw_port.tree_panel= AutonomousPanel(tv->draw_port.tree_window, width, height, DrawTreeProc,
2061 TreeVScrollProc, TreeHScrollProc,
2062 sizeof(TreeViewPtr), NULL, NULL);
2063
2064 if(tv->draw_port.tree_panel == NULL) {
2065 MemFree(tv->segm_buff);
2066 MemFree(tv);
2067 return NULL;
2068 }
2069
2070 SetPanelClick (tv->draw_port.tree_panel, ViewerClickProc, NULL, NULL, NULL);
2071
2072 SetPanelExtra(tv->draw_port.tree_panel, &tv);
2073
2074 tv->i_list= il;
2075
2076 /* populate tv structure */
2077 tv->tree= tree;
2078
2079 tv->cr1= tree_openCursor(tree, tv, NULL);
2080 tv->cr2= tree_openCursor(tree, tv, tv_cr2_callback);
2081 tv->cr3= NULL;
2082 tv->cr4= tree_openCursor(tree, tv, NULL);
2083
2084 tv->my_spy_id= tree_addSpy(tree, spy_proc, tv);
2085
2086 /* draw port setup */
2087 tv->draw_port.panel_origin_X= tv->draw_port.panel_origin_Y= 0;
2088 tv->draw_port.port_origin.x= 0;
2089 tv->draw_port.port_origin.y= 0;
2090
2091 /*Black();*/
2092 tv->draw_port.clip_box.xl= 0;
2093 tv->draw_port.clip_box.yt= 0;
2094 tv->draw_port.clip_box.xr= width;
2095 tv->draw_port.clip_box.yb= height;
2096 tv->draw_port.line_color= tv->draw_port.text_color= tv->draw_port.sbg_color= 0;
2097 tv->draw_port.line_color_set= tv->draw_port.text_color_set= tv->draw_port.sbg_color_set= 0;
2098 /* InvertColors(); */
2099 tv->draw_port.bg_color= tv->draw_port.sfg_color= 0;
2100 tv->draw_port.bg_color_set= tv->draw_port.sfg_color_set= 0;
2101 tv->draw_port.plus_color= 0;
2102 tv->draw_port.plus_color_set= 0;
2103 /*InvertColors();*/
2104
2105 tv->draw_port.pen_w= 1;
2106
2107 tv->row_height= FontHeight() + 2;
2108 /*tv->row_height+= tv->row_height/4;*/
2109 tv->row_width= CharWidth('w');
2110 if(tv->row_width < 4) tv->row_width= 4;
2111
2112 tv->length_scale= (l_scale == 0)? 1 : l_scale;
2113
2114 tv->sel_y= -1024;
2115
2116 /* prepare root node for drawing */
2117 tns= allocNewSegm(tv->cr1);
2118 tns->w= calcNodeWidth(tv, getIconId(tv->cr1), getNodeLength(tv->cr1), getNodeLabel(tv->cr1));
2119 tns->h= tv->row_height;
2120
2121 tv->cmpSiblings= NodeCmp;
2122 tv->dblClickFunc= NULL;
2123 tv->shiftClickFunc= NULL;
2124 tv->ctrlClickFunc= NULL;
2125
2126 tv->cr5= tree_openCursor(tree, tv, tv_cr5_callback);
2127
2128 tv->my_root= tv->cr5->node_id;
2129
2130 openSubtree(tv->cr1, TRUE);
2131
2132 if(tv->draw_port.tree_window != NULL) {
2133 RealizeWindow(tv->draw_port.tree_window);
2134 Show(tv->draw_port.tree_window);
2135 }
2136 return tv;
2137 }
2138
2139 Boolean tview_setTextColor(TreeViewPtr tv, Uint4 color)
2140 {
2141 if((color != tv->draw_port.bg_color) || (tv->draw_port.bg_color_set == 0)){
2142 tv->draw_port.text_color= color;
2143 tv->draw_port.text_color_set= 1;
2144 return TRUE;
2145 }
2146
2147 return FALSE;
2148 }
2149
2150 Boolean tview_setLineColor(TreeViewPtr tv, Uint4 color)
2151 {
2152 if((color != tv->draw_port.bg_color) || (tv->draw_port.bg_color_set == 0)) {
2153 tv->draw_port.line_color= color;
2154 tv->draw_port.line_color_set= 1;
2155 return TRUE;
2156 }
2157
2158 return FALSE;
2159 }
2160
2161 Boolean tview_setPlusColor(TreeViewPtr tv, Uint4 color)
2162 {
2163 if((color != tv->draw_port.bg_color) || (tv->draw_port.bg_color_set == 0)) {
2164 tv->draw_port.plus_color= color;
2165 tv->draw_port.plus_color_set= 1;
2166 return TRUE;
2167 }
2168
2169 return FALSE;
2170 }
2171
2172 Boolean tview_setSelBGColor(TreeViewPtr tv, Uint4 color)
2173 {
2174 tv->draw_port.sbg_color= color;
2175 tv->draw_port.sbg_color_set= 1;
2176 return TRUE;
2177 }
2178
2179 Boolean tview_setSelFGColor(TreeViewPtr tv, Uint4 color)
2180 {
2181 tv->draw_port.sfg_color= color;
2182 tv->draw_port.sfg_color_set= 1;
2183 return TRUE;
2184 }
2185
2186 Int2 tview_labelCmp(TreeCursorPtr c1, TreeCursorPtr c2)
2187 {
2188 static char l1[256], l2[256];
2189 Int2 res;
2190
2191 StringNCpy(l1, getNodeLabel(c1), 255);
2192 StringNCpy(l2, getNodeLabel(c2), 255);
2193 res= StringCmp(l1, l2);
2194 return res;
2195 }
2196
2197 Int2 tview_distanceCmp(TreeCursorPtr c1, TreeCursorPtr c2)
2198 {
2199 return (Int2)(getNodeLength(c1) - getNodeLength(c2));
2200 }
2201
2202 static void resortNodes(TreeCursorPtr cursor)
2203 {
2204 TreeViewPtr tv= (TreeViewPtr) getTree4Cursor(cursor);
2205 _tnSegmPtr tns= getNodeViewerData((_tnSegmPtr)cursor->node->sys_data, tv->my_spy_id);
2206 TreeNodeId nid= tree_getId(cursor);
2207 Boolean res;
2208
2209 if((tns == NULL) || (tns->h <= tv->row_height)) return;
2210
2211 closeSubtree(cursor, FALSE);
2212
2213 tree_toNode(cursor, nid);
2214
2215 openSubtree(cursor, FALSE);
2216
2217 tree_toNode(cursor, nid);
2218
2219 for(res= tree_child(cursor); res; res= tree_sibling(cursor)) {
2220 resortNodes(cursor);
2221 }
2222
2223 tree_toNode(cursor, nid);
2224 }
2225
2226 TreeNodeCmpFunc tview_setNodeCmpFunc(TreeViewPtr tv, TreeNodeCmpFunc NodeCmp)
2227 {
2228 TreeNodeCmpFunc old;
2229
2230 old= tv->cmpSiblings;
2231 tv->cmpSiblings= NodeCmp;
2232
2233 if(NodeCmp != NULL) {
2234 TreeNodeId sid= tv->cr2->node_id;
2235
2236 WatchCursor();
2237 tree_toNode(tv->cr1, tv->my_root); /*tree_root(tv->cr1);*/
2238 resortNodes(tv->cr1);
2239 tree_toNode(tv->cr2, sid);
2240 tview_showSelected(tv);
2241 ArrowCursor();
2242 }
2243
2244 return old;
2245 }
2246
2247 TreeViewEventFunc tview_setEventHandler(TreeViewPtr tv, TreeViewEventFunc HandlerFunc)
2248 {
2249 TreeViewEventFunc old;
2250
2251 old= tv->evntFunc;
2252 tv->evntFunc= HandlerFunc;
2253
2254 return old;
2255 }
2256
2257
2258 TreeViewClickFunc tview_setDblClickFunc(TreeViewPtr tv, TreeViewClickFunc dblClickProc)
2259 {
2260 TreeViewClickFunc old;
2261
2262 old= tv->dblClickFunc;
2263 tv->dblClickFunc= dblClickProc;
2264
2265 return old;
2266 }
2267
2268 TreeViewClickFunc tview_setShiftClickFunc(TreeViewPtr tv, TreeViewClickFunc shiftClickProc)
2269 {
2270 TreeViewClickFunc old;
2271
2272 old= tv->shiftClickFunc;
2273 tv->shiftClickFunc= shiftClickProc;
2274
2275 return old;
2276 }
2277
2278 TreeViewClickFunc tview_setCtrlClickFunc(TreeViewPtr tv, TreeViewClickFunc ctrlClickProc)
2279 {
2280 TreeViewClickFunc old;
2281
2282 old= tv->ctrlClickFunc;
2283 tv->ctrlClickFunc= ctrlClickProc;
2284
2285 return old;
2286 }
2287
2288 void tview_redraw(TreeViewPtr tv)
2289 {
2290
2291 PaneL viewer= tv->draw_port.tree_panel;
2292 RecT r;
2293 _tnSegmPtr tns;
2294
2295 if (Visible(viewer) && AllParentsVisible (viewer)) {
2296
2297 Select(viewer);
2298 ObjectRect(viewer, &r);
2299 /*InsetRect(&r, 1, 1);*/
2300 setPort2Panel(&tv->draw_port);
2301
2302 tree_toNode(tv->cr1, tv->my_root); /*tree_root(cursor);*/
2303 tns= getNodeViewerData((_tnSegmPtr)tv->cr1->node->sys_data, tv->my_spy_id);
2304
2305 setPort2Panel(&tv->draw_port);
2306
2307 CorrectScrollbar(GetSlateHScrollBar((SlatE)(tv->draw_port.tree_panel)),
2308 tv->row_width, tns->w + 16, tv->draw_port.clip_box.xl, tv->draw_port.clip_box.xr);
2309
2310 CorrectScrollbar(GetSlateVScrollBar((SlatE)(tv->draw_port.tree_panel)),
2311 tv->row_height, tns->h + 24, tv->draw_port.clip_box.yt, tv->draw_port.clip_box.yb);
2312 Select(viewer);
2313 InvalRect(&r);
2314 Update();
2315 }
2316 }
2317
2318 static Boolean ancestor(TreeCursorPtr cursor, TreeNodeId nid)
2319 {
2320 TreeNodeId pid= cursor->node_id;
2321 TreeNodeId gpid= cursor->node->parent;
2322
2323 tree_toNode(cursor, nid);
2324 while(cursor->node_id.idi != gpid.idi) {
2325 if(cursor->node_id.idi == pid.idi) return TRUE;
2326 if(!tree_parent(cursor)) break;
2327 }
2328
2329 tree_toNode(cursor, pid);
2330 return FALSE;
2331 }
2332
2333 /*-------------------------------------------
2334 * function makes node tv->cr1 visible
2335 */
2336 static void getNodeCoordinates(TreeViewPtr tv, Int4Ptr node_x, Int4Ptr node_y)
2337 {
2338 _tnSegmPtr tns;
2339 Int4 x, y;
2340 _box my_box;
2341 /*Boolean need_cont;*/
2342 TreeNodeId nid= tv->cr1->node_id;
2343 TreeNodeId id;
2344 Int4 length;
2345
2346 /* make node visible */
2347 tree_toNode(tv->cr1, tv->my_root); /*tree_root(tv->cr1);*/
2348 x= TREE_X0;
2349 y= TREE_Y0;
2350
2351 if(tv->cr3 == NULL) {
2352 tv->cr3= tree_openCursor(tv->tree, tv, NULL);
2353 }
2354
2355 while(tv->cr1->node_id.idi != nid.idi) {
2356
2357 tns= getNodeViewerData((_tnSegmPtr)tv->cr1->node->sys_data, tv->my_spy_id);
2358 if(tns == NULL) break;
2359 if(tns->h <= tv->row_height) {
2360 openSubtree(tv->cr1, TRUE);
2361 }
2362 y+= tv->row_height;
2363 length= getNodeLength(tv->cr1);
2364 x+= ((tv->length_scale >= 0)?
2365 (tv->length_scale * length) : (length/(-tv->length_scale)));
2366
2367 if(tree_child(tv->cr1)) {
2368
2369 if(tv->cmpSiblings == NULL) {
2370 /* we don't want to sort siblings */
2371 do {
2372 if(ancestor(tv->cr1, nid)) break;
2373
2374 my_box.xl= my_box.xr= x;
2375 my_box.yt= my_box.yb= y;
2376 getBox4Cursor(tv->cr1, &my_box);
2377 y= my_box.yb;
2378 }
2379 while (tree_sibling(tv->cr1));
2380 }
2381 else {/* siblings have to be sorted */
2382
2383 for(id.idi= 0; (id= getNextSibling(tv->cr1, id)).idi != 0;) {
2384
2385 if(ancestor(tv->cr1, nid)) break;
2386
2387 my_box.xl= my_box.xr= x;
2388 my_box.yt= my_box.yb= y;
2389 getBox4Cursor(tv->cr1, &my_box);
2390 y= my_box.yb;
2391 }
2392 }
2393 }
2394 else {
2395 break;
2396 }
2397 }
2398
2399 *node_x= x;
2400 *node_y= y;
2401 tree_toNode(tv->cr1, nid);
2402 }
2403
2404
2405 /*-------------------------------------------
2406 * Adjust scrolling to show selected node
2407 * SetBarValue(Nlm_BaR b, Nlm_Int4 val)
2408 * extern Nlm_Int4 Nlm_GetBarMax (Nlm_BaR b)
2409 */
2410 void tview_showSelected(TreeViewPtr tv)
2411 {
2412 Int4 bar_val= -1, s;
2413 BaR b;
2414 _box my_box;
2415
2416
2417 if(tv->draw_port.tree_window != NULL) Select(tv->draw_port.tree_window);
2418
2419 setPort2Panel(&tv->draw_port);
2420 if(tv->sel_y < 0) {
2421
2422 /* we have to calculate coordinates for selected node */
2423 tree_toNode(tv->cr1, tree_getId(tv->cr2));
2424 getNodeCoordinates(tv, &tv->sel_x, &tv->sel_y);
2425 }
2426
2427 /* adjust vertical bar */
2428
2429 b= GetSlateVScrollBar((SlatE)(tv->draw_port.tree_panel));
2430
2431 if(tv->sel_y < tv->draw_port.clip_box.yt) {
2432 /* the node is above the screen */
2433 if(tv->sel_y == 0) {
2434 /* this is a root */
2435 bar_val= 0;
2436 }
2437 else {
2438 bar_val= tv->sel_y/tv->row_height - 1;
2439 }
2440 }
2441 else if(tv->sel_y >= tv->draw_port.clip_box.yb) {
2442 /* the node is below the screen */
2443 s= (tv->draw_port.clip_box.yb - tv->draw_port.clip_box.yt)/tv->row_height;
2444 bar_val= tv->sel_y/tv->row_height - s + 2;
2445 if(bar_val < 0) bar_val= 1;
2446 s= GetBarMax(b);
2447 if(bar_val > s) bar_val= s;
2448 }
2449
2450 if(bar_val >= 0) {
2451 SetBarValue(b, bar_val);
2452 }
2453
2454 /* adjust horisontal bar */
2455
2456 b= GetSlateHScrollBar((SlatE)(tv->draw_port.tree_panel));
2457 bar_val= -1;
2458 s= GetBarMax(b);
2459
2460 if(s == 0) return;
2461 calcBox4Select(tv->cr2, tv->sel_x, tv->sel_y, &my_box);
2462 if((my_box.xl >= tv->draw_port.clip_box.xl) && (my_box.xr < tv->draw_port.clip_box.xr)) {
2463 /* perfectly visible */
2464 return;
2465 }
2466
2467 bar_val= tv->sel_x/tv->row_width - 1;
2468 if(bar_val < 0) bar_val= 0;
2469 if(bar_val > s) bar_val= s;
2470
2471 if(bar_val >= 0) {
2472 SetBarValue(b, bar_val);
2473 }
2474
2475 }
2476
2477 Boolean tview_selectNode(TreeViewPtr tv, TreeNodeId id)
2478 {
2479 if(tree_toNode(tv->cr1, id)) {
2480 Int4 x, y;
2481
2482 if(!tree_isDescendant(tv->cr5, tv->cr1)) {
2483 tview_moveRoot(tv, tree_getAncestor(tv->cr5, tv->cr1));
2484 tree_toNode(tv->cr1, id);
2485 }
2486 getNodeCoordinates(tv, &x, &y);
2487 select_treeNode(tv->cr1, x, y);
2488 tview_showSelected(tv);
2489 return TRUE;
2490 }
2491 return FALSE;
2492 }
2493
2494 Boolean tview_openSubtree(TreeViewPtr tv, TreeNodeId id)
2495 {
2496 if(tree_toNode(tv->cr1, id)) {
2497 Int4 x, y;
2498
2499 getNodeCoordinates(tv, &x, &y);
2500 openSubtree(tv->cr1, TRUE);
2501 return TRUE;
2502 }
2503 return FALSE;
2504 }
2505
2506 Boolean tview_closeSubtree(TreeViewPtr tv, TreeNodeId id)
2507 {
2508 if(tree_toNode(tv->cr1, id)) {
2509
2510 closeSubtree(tv->cr1, TRUE);
2511 return TRUE;
2512 }
2513 return FALSE;
2514 }
2515
2516 void tview_hide(TreeViewPtr tv)
2517 {
2518 if(tv->draw_port.tree_window != NULL) Hide(tv->draw_port.tree_window);
2519 else Hide(tv->draw_port.tree_panel);
2520 }
2521
2522 void tview_show(TreeViewPtr tv)
2523 {
2524 if(tv->draw_port.tree_window != NULL) Show(tv->draw_port.tree_window);
2525 else Show(tv->draw_port.tree_panel);
2526 }
2527
2528
2529 void tview_disable(TreeViewPtr tv)
2530 {
2531 Disable(tv->draw_port.tree_panel);
2532 }
2533
2534 void tview_enable(TreeViewPtr tv)
2535 {
2536 Enable(tv->draw_port.tree_panel);
2537 }
2538
2539 static void closeAllSubtrees(TreeCursorPtr cursor)
2540 {
2541 freeNodeSegm(cursor);
2542 if(tree_child(cursor)) {
2543 do {
2544 closeAllSubtrees(cursor);
2545 }
2546 while(tree_sibling(cursor));
2547 tree_parent(cursor);
2548 }
2549 }
2550
2551
2552 void tview_delete(TreeViewPtr tv, Boolean do_hide)
2553 {
2554 _tnSegmPtr ts;
2555 _tnSegmPtr tsn;
2556 /* close all subtrees */
2557 tree_root(tv->cr1);
2558 closeAllSubtrees(tv->cr1);
2559
2560 tree_closeCursor(tv->cr1);
2561 tree_closeCursor(tv->cr2);
2562 tree_closeCursor(tv->cr3);
2563 tree_closeCursor(tv->cr4);
2564 tree_closeCursor(tv->cr5);
2565 tree_delSpy(tv->tree, tv->my_spy_id);
2566 if(tv->draw_port.tree_panel != NULL) {
2567 if(do_hide) Hide(tv->draw_port.tree_panel);
2568 Remove(tv->draw_port.tree_panel);
2569 }
2570 if(tv->draw_port.tree_window != NULL) {
2571 if(do_hide) Hide(tv->draw_port.tree_window);
2572 Remove(tv->draw_port.tree_window);
2573 }
2574
2575 for(ts= tv->segm_buff; ts != NULL; ts= tsn) {
2576 tsn= ts[4095].next;
2577 MemFree(ts);
2578 }
2579 MemFree(tv);
2580 }
2581
2582 Boolean tview_moveRoot(TreeViewPtr tv, TreeNodeId id)
2583 {
2584 _tnSegmPtr tns;
2585 BaR b;
2586
2587 if(tree_toNode(tv->cr1, id)) {
2588 tns= getNodeViewerData((_tnSegmPtr)tv->cr1->node->sys_data, tv->my_spy_id);
2589 if(tns == NULL) {
2590
2591 tns= allocNewSegm(tv->cr1);
2592 tns->w= calcNodeWidth(tv, getIconId(tv->cr1), getNodeLength(tv->cr1), getNodeLabel(tv->cr1));
2593 tns->h= tv->row_height;
2594 }
2595 tree_toNode(tv->cr5, id);
2596 if((tv->cr2->node_id.idi != id.idi) && (!tree_isDescendant(tv->cr5, tv->cr2))) {
2597 tree_toNode(tv->cr2, id);
2598 }
2599 openSubtree(tv->cr1, TRUE);
2600
2601 tns= getNodeViewerData((_tnSegmPtr)tv->cr5->node->sys_data, tv->my_spy_id);
2602
2603 setPort2Panel(&tv->draw_port);
2604
2605 CorrectScrollbar(GetSlateHScrollBar((SlatE)(tv->draw_port.tree_panel)),
2606 tv->row_width, tns->w + 16, tv->draw_port.clip_box.xl, tv->draw_port.clip_box.xr);
2607
2608 CorrectScrollbar(GetSlateVScrollBar((SlatE)(tv->draw_port.tree_panel)),
2609 tv->row_height, tns->h + 24, tv->draw_port.clip_box.yt, tv->draw_port.clip_box.yb);
2610
2611 b= GetSlateVScrollBar((SlatE)(tv->draw_port.tree_panel));
2612 SetBarValue(b, 0);
2613
2614 b= GetSlateHScrollBar((SlatE)(tv->draw_port.tree_panel));
2615 SetBarValue(b, 0);
2616
2617 tv->sel_y= -1024;
2618
2619 tview_redraw(tv);
2620 return TRUE;
2621 }
2622 return FALSE;
2623 }
2624
2625 TreeNodeId tview_getSelected(TreeViewPtr tv)
2626 {
2627 return tv->cr2->node_id;
2628 }
2629
2630 TreePtr tview_getTreePtr(TreeViewPtr tv)
2631 {
2632 return tv->tree;
2633 }
2634
2635
2636
2637
2638 |
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more information. |