Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

httree.cc

Go to the documentation of this file.
00001 /* 
00002  *      HT Editor
00003  *      httree.cc
00004  *
00005  *      Copyright (C) 1999-2002 Sebastian Biallas (sb@web-productions.de)
00006  *
00007  *      This program is free software; you can redistribute it and/or modify
00008  *      it under the terms of the GNU General Public License version 2 as
00009  *      published by the Free Software Foundation.
00010  *
00011  *      This program is distributed in the hope that it will be useful,
00012  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *      GNU General Public License for more details.
00015  *
00016  *      You should have received a copy of the GNU General Public License
00017  *      along with this program; if not, write to the Free Software
00018  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019  */
00020 
00021 #include <stdlib.h>
00022 
00023 #include "string.h"
00024 
00025 #include "htdialog.h"
00026 #include "htpal.h"
00027 #include "htkeyb.h"
00028 #include "htstring.h"
00029 #include "httree.h"
00030 #include "stream.h"
00031 
00032 void ht_treeview::init(bounds *b, char *d)
00033 {
00034         ht_view::init(b, VO_SELECTABLE | VO_BROWSABLE/* <- FIXME */ | VO_RESIZE, d);
00035         VIEW_DEBUG_NAME("ht_treeview");
00036 
00037         growmode = MK_GM(GMH_FIT, GMV_FIT);
00038 
00039         foc = 0;
00040         delta_x = delta_y = 0;
00041         maxsize_y = 5;
00042         selected = NULL;
00043 }
00044 
00045 void ht_treeview::done()
00046 {
00047         ht_view::done();
00048 }
00049 
00050 void ht_treeview::adjust_focus(int Focus)
00051 {
00052         if (Focus < 0) Focus = 0; else if (Focus >= maxsize_y) Focus = maxsize_y - 1;
00053         if (foc != Focus) has_focused(Focus);
00054         if (Focus < delta_y) scroll_to(delta_x, Focus);
00055                 else if ((Focus - size.h) >= delta_y) scroll_to(delta_x, Focus - size.h + 1);
00056 }
00057 
00058 int  ht_treeview::create_graph(int *s, void *node, int level, int lines, int width, int endwidth, int *Chars)
00059 {
00060 // Chars: space, vbar, T, last L,hbar,+,-,[,]
00061         for (int i=0; i<(level); i++) {
00062                 s[i*width] = (lines&(1<<i)) ? Chars[1] : Chars[0];
00063                 for (int j=1; j<(width); j++) s[i*width+j] = Chars[0];
00064         }
00065         int p = level*width;
00066         s[p] = (get_next_node(node)) ? Chars[2]: Chars[3];
00067         if (has_children(node)) {
00068                 s[p+1] = Chars[7];
00069                 s[p+2] = (is_expanded(node)) ? Chars[6]: Chars[5];
00070                 s[p+3] = Chars[8];
00071         } else {
00072                 s[p+1] = Chars[4];
00073                 s[p+2] = Chars[4];
00074                 s[p+3] = Chars[4];
00075         }
00076         s[p+4] = 32;
00077         p += 5;
00078         char *text=get_text(node);
00079         while (*text) s[p++] = *(text++);
00080         s[p] = 0;
00081         return p;
00082 }
00083 
00084 int     ht_treeview::count_children(void *node)
00085 {
00086         int i = 0;
00087         if (!is_expanded(node)) return 0;
00088         void *p = get_child(node, 1);
00089         while (p) {
00090                 i+=count_children(p);
00091                 p = get_next_node(p);
00092                 i++;
00093         }
00094         return i;
00095 }
00096 
00097 void ht_treeview::collapse_all(void *node)
00098 {
00099         if (has_children(node)) {
00100                 adjust(node, false);
00101                 void *tmp = get_child(node, 1);
00102                 while (tmp) {
00103                         collapse_all(tmp);
00104                         tmp = get_next_node(tmp);
00105                 }
00106         }
00107 }
00108 
00109 void ht_treeview::draw_r(void *node, int level, int *pos, dword lines)
00110 {
00111         int normal_color, sel_color, foc_color, color;
00112         normal_color = getcolor(palidx_generic_list_unfocused_unselected);
00113         foc_color = getcolor(palidx_generic_list_focused_selected);
00114         sel_color = getcolor(palidx_generic_list_unfocused_selected);
00115         int s[1024];
00116 
00117         while (node) {
00118                 if (*pos >= delta_y) {
00119                         if (*pos >= (delta_y+size.h)) break;
00120                         if (is_selected(*pos)) {
00121                                 selected = node; // only for getdata()
00122                                 if (focused) color=foc_color; else color=sel_color;
00123                                 fill(0, *pos-delta_y, size.w, 1, color, ' ');
00124                         } else color = normal_color;
00125                         if (get_graph(s, node, level, lines) > delta_x)
00126                                 buf_lprintw(0, *pos-delta_y, color, size.w, &s[delta_x]);
00127                 }
00128                 (*pos)++;
00129                 if (has_children(node) && is_expanded(node)) {
00130                         draw_r(get_child(node, 1), level+1, pos, (get_next_node(node)) ? lines|(1<<level) : lines);
00131                 }
00132                 node = get_next_node(node);
00133         }
00134 }
00135 
00136 void ht_treeview::draw()
00137 {
00138         clear(getcolor(palidx_generic_list_unfocused_unselected));
00139 
00140         int p = 0;
00141         draw_r(get_root(), 0, &p, 0);
00142 }
00143 
00144 void ht_treeview::expand_all(void *node)
00145 {
00146         if (has_children(node)) {
00147                 adjust(node, true);
00148                 void *tmp = get_child(node, 1);
00149                 while (tmp) {
00150                         expand_all(tmp);
00151                         tmp = get_next_node(tmp);
00152                 }
00153         }
00154 }
00155 
00156 /*
00157  *      stub
00158  */
00159 void ht_treeview::getdata(ht_object_stream *s)
00160 {
00161         s->putIntHex((int)selected, 4, NULL);
00162 }
00163 
00164 /*
00165  *      void *ht_treeview::get_child(void *node, int i)
00166  *      get i. child of node
00167  */
00168 
00169 int  ht_treeview::get_graph(int *s, void *node, int level, int lines)
00170 {
00171     int graph[10];
00172     graph[0]=' ';
00173     graph[1]=CHAR_LINEV;
00174     graph[2]=CHAR_BORDERTL;
00175     graph[3]=CHAR_CORNERLL;
00176     graph[4]=CHAR_LINEH;
00177     graph[5]='+';
00178     graph[6]='-';
00179     graph[7]='[';
00180     graph[8]=']';
00181     return create_graph(s, node, level, lines, 5, 5, graph);
00182 }
00183 
00184 void *ht_treeview::get_node_r(void *node, int *i)
00185 {
00186         while ((node) && (--(*i))) {
00187                 if (has_children(node) && is_expanded(node)) {
00188                         void *tmp = get_node_r(get_child(node, 1), i);
00189                         if (!(*i)) return tmp;
00190                 }
00191                 node = get_next_node(node);
00192         }
00193         return node;
00194 }
00195 
00196 /*
00197  *   get i. node
00198  *      i==1 => 1. node
00199  */
00200 void *ht_treeview::get_node(int i)
00201 {
00202         if (i<=0) return 0;
00203         void *Node = get_root();
00204         return get_node_r(Node, &i);
00205 }
00206 
00207 void    ht_treeview::handlemsg(htmsg *msg)
00208 {
00209         ht_view::handlemsg(msg);
00210         if (msg->msg==msg_keypressed) {
00211                 int Foc = foc;
00212                 switch (msg->data1.integer) {
00213                         case K_Up:
00214                                 Foc--;
00215                                 break;
00216                         case K_Down:
00217                                 Foc++;
00218                                 break;
00219                         case K_Control_Right:
00220                                 if (delta_x < maxsize_x-1) delta_x++;
00221                                 break;
00222                         case K_Control_Left:
00223                                 if (delta_x > 0) delta_x--;
00224                                 break;
00225                         case K_PageUp:
00226                                 Foc -= size.h-1;
00227                                 break;
00228                         case K_PageDown:
00229                                 Foc += size.h-1;
00230                                 break;
00231                         case K_Control_PageUp:
00232                                 Foc = 0;
00233                                 break;
00234                         case K_Control_PageDown:
00235                                 Foc = maxsize_y - 1;
00236                                 break;
00237                         case '+':
00238                         case K_Right: {
00239                                 void *p = get_node(Foc+1);
00240                                 if (has_children(p)) adjust(p, true);
00241                                 break;
00242                         }
00243                         case '-':
00244                                 adjust(get_node(Foc+1), false);
00245                                 break;
00246                         case K_Left: {
00247                                 void *n = get_node(Foc+1);
00248                                 if (is_expanded(n)) {
00249                                         adjust(n, false);
00250                                 } else {
00251                                         if (Foc) {
00252                                                 do {
00253                                                         Foc-=count_children(n)+1;
00254                                                         n = get_prev_node(n);
00255                                                 } while (n);
00256                                                 adjust(get_node(Foc+1), false);
00257                                         }
00258                                 }
00259                                 break;
00260                         }
00261                         case '*':
00262                                 expand_all(get_node(Foc+1));
00263                                 break;
00264                         case '/':
00265                                 collapse_all(get_node(Foc+1));
00266                                 break;
00267                         case K_Return: {
00268                                 void *n = get_node(Foc+1);
00269                                 if (has_children(n)) {
00270                                         adjust(n, !is_expanded(n));
00271                                 } else {
00272                                         select_node(n);
00273                                 }
00274                                 break;
00275                         }
00276                         default:
00277                                 return;
00278                 }
00279                 update();
00280                 adjust_focus(Foc);
00281                 dirtyview();
00282                 clearmsg(msg);
00283         }
00284 }
00285 
00286 void    ht_treeview::has_focused(int i)
00287 {
00288         foc = i;
00289 }
00290 
00291 /*
00292  *      can be overwritten to handle mutiple selections
00293  */
00294 bool    ht_treeview::is_selected(int i)
00295 {
00296         return (foc == i);
00297 }
00298 
00299 void    ht_treeview::scroll_to(int x, int y)
00300 {
00301         delta_x = x;
00302         delta_y = y;
00303 }
00304 
00305 /*
00306  *      stub
00307  */
00308 void ht_treeview::setdata(ht_object_stream *s)
00309 {
00310 }
00311 
00312 /*
00313  *      called whenever a node is being selected
00314  *      can be overwritten
00315  */
00316 void    ht_treeview::select_node(void *node)
00317 {
00318 }
00319 
00320 void    ht_treeview::set_limit(int x, int y)
00321 {
00322         maxsize_x = x;
00323         maxsize_y = y;
00324 }
00325 
00326 void    ht_treeview::update_r(void *node, int level, int *pos, int *x)
00327 {
00328         int *s = (int *)malloc(2048);
00329 
00330         while (node) {
00331                 int l = get_graph(s, node, level, 0);
00332                 if (l > *x) *x = l;
00333                 (*pos)++;
00334                 if (has_children(node) && is_expanded(node)) {
00335                         update_r(get_child(node, 1), level+1, pos, x);
00336                 }
00337                 node = get_next_node(node);
00338         }
00339         free(s);
00340 
00341 }
00342 
00343 /*
00344  *   must be called whenever the data of the tree has changed
00345  */
00346 void    ht_treeview::update()
00347 {
00348         int count = 0, maxx = 0;
00349         update_r(get_root(), 0, &count, &maxx);
00350         set_limit(maxx, count);
00351         adjust_focus(foc);
00352 }
00353 
00354 /****************************************************************************/
00355 
00356 void ht_static_treeview::init(bounds *b, char *desc)
00357 {
00358         ht_treeview::init(b, desc);
00359         VIEW_DEBUG_NAME("ht_static_treeview");
00360         root=0;
00361 }
00362 
00363 void ht_static_treeviewdone_r(static_node *node)
00364 {
00365         while (node) {
00366                 ht_static_treeviewdone_r(node->child);
00367                 if (node->text) free(node->text);
00368                 if (node->data) {
00369                         node->data->done();
00370                         delete node->data;
00371                 }
00372                 static_node *temp = node->next;
00373                 free(node);
00374                 node = temp;
00375         }
00376 }
00377 
00378 void ht_static_treeview::done()
00379 {
00380         ht_static_treeviewdone_r(root);
00381         ht_treeview::done();
00382 }
00383 
00384 void *ht_static_treeview::add_child(void *node, char *text, Object *Data)
00385 {
00386         if (node) {
00387                 return add_node(&((static_node *)node)->child, text, Data);
00388         } else {
00389                 if (root) {
00390                         return add_node(&root, text, Data);
00391                 } else {
00392                         root=create_node(text, NULL, Data);
00393                         return root;
00394                 }
00395         }
00396 }
00397 
00398 void    *ht_static_treeview::add_node(static_node **node, char *text, Object *Data)
00399 {
00400         static_node **p = node;
00401         static_node *prev = NULL;
00402         if (*p) {
00403                 while (*p) {
00404                         prev = *p;
00405                         p = &(*p)->next;
00406                 }
00407         }
00408         *p=create_node(text, prev, Data);
00409         return *p;
00410 }
00411 
00412 void    ht_static_treeview::adjust(void *node, bool expand)
00413 {
00414         ((static_node *)node)->expanded = expand;
00415 }
00416 
00417 static_node *ht_static_treeview::create_node(char *text, static_node *prev, Object *Data)
00418 {
00419         static_node *node = (static_node *)malloc(sizeof(static_node));
00420         node->text = ht_strdup(text);
00421         node->next = NULL;
00422         node->prev = prev;
00423         node->child = NULL;
00424         node->expanded = false;
00425         node->data = Data;
00426         return node;
00427 }
00428 
00429 void *ht_static_treeview::get_child(void *node, int i)
00430 {
00431         static_node *p;
00432         if (node) {
00433                 p = ((static_node *)node)->child;
00434         } else {
00435                 p = root;
00436         }
00437         while (p && (--i)) p = p->next;
00438         return p;
00439 }
00440 
00441 void    *ht_static_treeview::get_next_node(void *node)
00442 {
00443         return ((static_node *)node)->next;
00444 }
00445 
00446 void    *ht_static_treeview::get_prev_node(void *node)
00447 {
00448         return ((static_node *)node)->prev;
00449 }
00450 
00451 void    *ht_static_treeview::get_root()
00452 {
00453         return root;
00454 }
00455 
00456 char    *ht_static_treeview::get_text(void *node)
00457 {
00458         return ((static_node *)node)->text;
00459 }
00460 
00461 void    *ht_static_treeview::get_cursor_node()
00462 {
00463 // FIXME: said to be the wrong thing, works however
00464         return selected;
00465 }
00466 
00467 void    ht_static_treeview::goto_node(void *node)
00468 {
00469 }
00470 
00471 bool    ht_static_treeview::has_children(void *node)
00472 {
00473         return (((static_node *)node)->child);
00474 }
00475 
00476 bool    ht_static_treeview::is_expanded(void *node)
00477 {
00478         return (((static_node *)node)->expanded);
00479 }
00480 
00481 void    ht_static_treeview::select_node(void *node)
00482 {
00483 }
00484 

Generated on Fri May 7 21:15:37 2004 by doxygen 1.3.5