00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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 | 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
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;
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
00158
00159 void ht_treeview::getdata(ht_object_stream *s)
00160 {
00161 s->putIntHex((int)selected, 4, NULL);
00162 }
00163
00164
00165
00166
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
00198
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
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
00307
00308 void ht_treeview::setdata(ht_object_stream *s)
00309 {
00310 }
00311
00312
00313
00314
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
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
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