1 #include "bcdragwindow.h"
3 #include "bclistboxitem.h"
5 #include "bcresources.h"
17 // ====================================================== scrollbars
20 BC_ListBoxYScroll::BC_ListBoxYScroll(BC_ListBox *listbox,
24 : BC_ScrollBar(listbox->get_yscroll_x(),
25 listbox->get_yscroll_y(),
27 listbox->get_yscroll_height(),
32 this->listbox = listbox;
35 BC_ListBoxYScroll::~BC_ListBoxYScroll()
39 int BC_ListBoxYScroll::handle_event()
41 listbox->set_yposition(get_value());
51 BC_ListBoxXScroll::BC_ListBoxXScroll(BC_ListBox *listbox,
55 : BC_ScrollBar(listbox->get_xscroll_x(),
56 listbox->get_xscroll_y(),
58 listbox->get_xscroll_width(),
63 this->listbox = listbox;
66 BC_ListBoxXScroll::~BC_ListBoxXScroll()
70 int BC_ListBoxXScroll::handle_event()
72 listbox->set_xposition(get_value());
83 BC_ListBoxToggle::BC_ListBoxToggle(BC_ListBox *listbox,
88 this->listbox = listbox;
92 this->value = item->get_expand();
94 state = BC_Toggle::TOGGLE_CHECKED;
96 state = BC_Toggle::TOGGLE_UP;
99 void BC_ListBoxToggle::update(BC_ListBoxItem *item,
104 this->value = item->get_expand();
114 state = TOGGLE_CHECKED;
119 state = TOGGLE_CHECKEDHI;
130 case TOGGLE_CHECKEDHI:
135 case TOGGLE_DOWN_EXIT:
143 int BC_ListBoxToggle::cursor_motion_event(int *redraw_toggles)
145 int w = listbox->toggle_images[0]->get_w();
146 int h = listbox->toggle_images[0]->get_h();
147 int cursor_inside = listbox->get_cursor_x() >= x &&
148 listbox->get_cursor_x() < x + w &&
149 listbox->get_cursor_y() >= y &&
150 listbox->get_cursor_y() < y + h;
155 case BC_ListBoxToggle::TOGGLE_UPHI:
158 state = BC_ListBoxToggle::TOGGLE_UP;
163 case BC_ListBoxToggle::TOGGLE_CHECKEDHI:
166 state = BC_ListBoxToggle::TOGGLE_CHECKED;
171 case BC_ListBoxToggle::TOGGLE_DOWN:
174 state = BC_ListBoxToggle::TOGGLE_DOWN_EXIT;
180 case BC_ListBoxToggle::TOGGLE_DOWN_EXIT:
183 state = BC_ListBoxToggle::TOGGLE_DOWN;
193 state = BC_ListBoxToggle::TOGGLE_CHECKEDHI;
195 state = BC_ListBoxToggle::TOGGLE_UPHI;
203 int BC_ListBoxToggle::cursor_leave_event(int *redraw_toggles)
206 state = BC_ListBoxToggle::TOGGLE_CHECKED;
208 state = BC_ListBoxToggle::TOGGLE_UP;
211 int BC_ListBoxToggle::button_press_event()
213 int w = listbox->toggle_images[0]->get_w();
214 int h = listbox->toggle_images[0]->get_h();
216 if(listbox->gui->get_cursor_x() >= x &&
217 listbox->gui->get_cursor_x() < x + w &&
218 listbox->gui->get_cursor_y() >= y &&
219 listbox->gui->get_cursor_y() < y + h)
221 state = BC_ListBoxToggle::TOGGLE_DOWN;
227 int BC_ListBoxToggle::button_release_event(int *redraw_toggles)
232 case BC_ListBoxToggle::TOGGLE_DOWN:
235 state = BC_ListBoxToggle::TOGGLE_CHECKEDHI;
237 state = BC_ListBoxToggle::TOGGLE_UPHI;
238 listbox->expand_item(item, value);
242 case BC_ListBoxToggle::TOGGLE_DOWN_EXIT:
244 state = BC_ListBoxToggle::TOGGLE_CHECKED;
246 state = BC_ListBoxToggle::TOGGLE_UP;
254 void BC_ListBoxToggle::draw(int flash)
258 int image_number = 0;
259 int w = listbox->toggle_images[0]->get_w();
260 int h = listbox->toggle_images[0]->get_h();
264 case BC_ListBoxToggle::TOGGLE_UP: image_number = 0; break;
265 case BC_ListBoxToggle::TOGGLE_UPHI: image_number = 1; break;
266 case BC_ListBoxToggle::TOGGLE_CHECKED: image_number = 2; break;
267 case BC_ListBoxToggle::TOGGLE_DOWN: image_number = 3; break;
268 case BC_ListBoxToggle::TOGGLE_CHECKEDHI: image_number = 4; break;
269 case BC_ListBoxToggle::TOGGLE_DOWN_EXIT:
277 //printf("BC_ListBoxToggle::draw 1 %d\n", state);
278 listbox->gui->draw_pixmap(listbox->toggle_images[image_number],
285 listbox->gui->flash(x, y, w, h);
286 listbox->gui->flush();
304 // ====================================================== box
306 BC_ListBox::BC_ListBox(int x,
311 ArrayList<BC_ListBoxItem*> *data,
312 char **column_titles,
320 : BC_SubWindow(x, y, w, h, -1)
322 justify = LISTBOX_RIGHT;
324 highlighted_item = -1;
325 highlighted_title = -1;
326 highlighted_division = -1;
330 current_cursor = ARROW_CURSOR;
341 selection_number1 = -1;
342 selection_number2 = -1;
346 current_operation = NO_OPERATION;
347 button_highlighted = 0;
351 list_highlighted = 0;
353 allow_drag_scroll = 1;
359 allow_drag_column = 0;
366 for(int i = 0; i < 3; i++)
369 for(int i = 0; i < 4; i++)
370 button_images[i] = 0;
372 for(int i = 0; i < 5; i++)
373 toggle_images[i] = 0;
378 //printf("BC_ListBox::BC_ListBox 1\n");
380 this->columns = columns;
381 this->yposition = yposition;
382 this->is_popup = is_popup;
383 this->display_format = display_format;
384 this->selection_mode = selection_mode;
385 this->icon_position = icon_position;
386 this->allow_drag = allow_drag;
387 this->column_titles = 0;
388 this->column_width = 0;
389 //printf("BC_ListBox::BC_ListBox 1\n");
391 if((!column_titles && column_width) ||
392 (column_titles && !column_width))
394 printf("BC_ListBox::BC_ListBox either column_titles or column_widths == NULL but not both.\n");
396 //printf("BC_ListBox::BC_ListBox 2 %p %p\n", column_titles, column_width);
397 set_columns(column_titles,
401 //printf("BC_ListBox::BC_ListBox 3\n");
403 drag_icon_vframe = 0;
404 drag_column_icon_vframe = 0;
408 // reset the search engine
409 //printf("BC_ListBox::BC_ListBox 4\n");
411 //printf("BC_ListBox::BC_ListBox 5\n");
414 BC_ListBox::~BC_ListBox()
416 expanders.remove_all_objects();
417 if(bg_surface) delete bg_surface;
418 if(bg_pixmap) delete bg_pixmap;
419 if(xscrollbar) delete xscrollbar;
420 if(yscrollbar) delete yscrollbar;
421 for(int i = 0; i < 3; i++)
422 if(column_bg[i]) delete column_bg[i];
423 for(int i = 0; i < 4; i++)
424 if(button_images[i]) delete button_images[i];
425 for(int i = 0; i < 5; i++)
426 if(toggle_images[i]) delete toggle_images[i];
427 if(column_sort_up) delete column_sort_up;
428 if(column_sort_dn) delete column_sort_dn;
431 if(drag_popup) delete drag_popup;
434 int BC_ListBox::enable()
441 int BC_ListBox::disable()
448 void BC_ListBox::reset_query()
450 query[0] = 0; // reset query
453 int BC_ListBox::evaluate_query(int list_item, char *string)
455 return(strcmp(string, data[search_column].values[list_item]->text) <= 0 &&
456 data[search_column].values[list_item]->searchable);
459 int BC_ListBox::query_list()
461 if(query[0] == 0) return 0;
465 int selection_changed = 0;
466 int prev_selection = -1;
467 for(int i = 0; !done && i < data[0].total; i++)
469 if(evaluate_query(i, query))
479 for(int i = 0; i < data[0].total; i++)
481 for(int j = 0; j < columns; j++)
483 if(data[j].values[i]->selected) prev_selection = i;
484 data[j].values[i]->selected = 0;
489 if(prev_selection != result)
490 selection_changed = 1;
491 for(int j = 0; j < columns; j++)
493 data[j].values[result]->selected = 1;
495 center_selection(result);
498 return selection_changed;
501 void BC_ListBox::init_column_width()
503 if(!column_width && data)
506 for(int i = 0; i < data[0].total; i++)
508 w = get_text_width(MEDIUMFONT, data[0].values[i]->get_text()) + 2 * LISTBOX_MARGIN;
509 if(w > widest) widest = w;
511 default_column_width[0] = widest;
515 int BC_ListBox::initialize()
519 for(int i = 0; i < 4; i++)
521 button_images[i] = new BC_Pixmap(parent_window,
522 BC_WindowBase::get_resources()->listbox_button[i],
525 w = button_images[0]->get_w();
526 h = button_images[0]->get_h();
529 current_operation = NO_OPERATION;
534 current_operation = NO_OPERATION;
537 for(int i = 0; i < 3; i++)
539 column_bg[i] = new BC_Pixmap(parent_window,
540 get_resources()->listbox_column[i],
543 for(int i = 0; i < 5; i++)
545 toggle_images[i] = new BC_Pixmap(parent_window,
546 get_resources()->listbox_expand[i],
550 column_sort_up = new BC_Pixmap(parent_window,
551 BC_WindowBase::get_resources()->listbox_up,
553 column_sort_dn = new BC_Pixmap(parent_window,
554 BC_WindowBase::get_resources()->listbox_dn,
557 //printf("BC_ListBox::initialize 10\n");
558 drag_icon_vframe = get_resources()->type_to_icon[ICON_UNKNOWN];
559 drag_column_icon_vframe = get_resources()->type_to_icon[ICON_COLUMN];
560 // = new BC_Pixmap(parent_window,
561 // get_resources()->type_to_icon[ICON_UNKNOWN],
563 // drag_column_icon = new BC_Pixmap(parent_window,
564 // get_resources()->type_to_icon[ICON_COLUMN],
566 BC_SubWindow::initialize();
570 if(top_level->get_resources()->listbox_bg)
571 bg_pixmap = new BC_Pixmap(this,
572 get_resources()->listbox_bg,
580 void BC_ListBox::deactivate_selection()
582 current_operation = NO_OPERATION;
585 int BC_ListBox::draw_button()
587 // Draw the button for a popup listbox
590 int image_number = 0;
592 draw_top_background(parent_window, 0, 0, w, h);
594 if(button_highlighted)
596 if(current_operation == BUTTON_DN)
602 button_images[image_number]->write_drawable(pixmap,
614 int BC_ListBox::calculate_item_coords()
622 // Change the display_format to get the right item dimensions for both
624 int display_format_temp = display_format;
627 // Scan the first column for lowest y coord of all text
628 // and lowest right x and y coord for all icons which aren't auto placable
629 calculate_last_coords_recursive(data,
636 // Reset last column width. It's recalculated based on text width.
638 calculate_item_coords_recursive(data,
647 display_format = display_format_temp;
652 void BC_ListBox::calculate_last_coords_recursive(
653 ArrayList<BC_ListBoxItem*> *data,
660 for(int i = 0; i < data[0].total; i++)
662 int current_text_y = 0;
663 int current_icon_x = 0;
664 int current_icon_y = 0;
665 BC_ListBoxItem *item = data[0].values[i];
668 if(!item->autoplace_text)
670 // Lowest text coordinate
671 display_format = LISTBOX_TEXT;
672 current_text_y = item->text_y +
673 get_text_height(MEDIUMFONT);
674 if(current_text_y > *next_text_y)
675 *next_text_y = current_text_y;
677 // Add sublist depth if it is expanded
678 if(item->get_sublist() &&
679 item->get_columns() &&
682 calculate_last_coords_recursive(item->get_sublist(),
691 // Get next_icon coordinate
694 BC_ListBoxItem *item = data[master_column].values[i];
695 if(!item->autoplace_icon)
697 display_format = LISTBOX_ICONS;
698 // Lowest right icon coordinate.
699 current_icon_x = item->icon_x;
700 if(current_icon_x > *icon_x) *icon_x = current_icon_x;
701 if(current_icon_x + get_item_w(item) > *next_icon_x)
702 *next_icon_x = current_icon_x + get_item_w(item);
704 current_icon_y = item->icon_y + get_item_h(item);
705 if(current_icon_y > *next_icon_y)
706 *next_icon_y = current_icon_y;
713 void BC_ListBox::calculate_item_coords_recursive(
714 ArrayList<BC_ListBoxItem*> *data,
724 // Set up items which need autoplacement.
725 // Should fill icons down and then across
726 for(int i = 0; i < data[0].total; i++)
728 // Don't increase y unless the row requires autoplacing.
729 int total_autoplaced_columns = 0;
731 // Set up icons in first column
734 BC_ListBoxItem *item = data[master_column].values[i];
735 if(item->autoplace_icon)
737 // 1 column only if icons are used
738 display_format = LISTBOX_ICONS;
741 if(*next_icon_y + get_item_h(item) >= get_h() &&
744 *icon_x = *next_icon_x;
748 if(*icon_x + get_item_w(item) > *next_icon_x)
749 *next_icon_x = *icon_x + get_item_w(item);
752 item->set_icon_x(*icon_x);
753 item->set_icon_y(*next_icon_y);
755 *next_icon_y += get_item_h(item);
763 for(int j = 0; j < columns; j++)
765 BC_ListBoxItem *item = data[j].values[i];
766 if(item->autoplace_text)
768 display_format = LISTBOX_TEXT;
769 item->set_text_x(next_text_x);
770 item->set_text_y(*next_text_y);
772 // printf("BC_ListBox::calculate_item_coords_recursive %p %d %d %d %d %s \n",
773 // item->get_sublist(),
774 // item->get_columns(),
775 // item->get_expand(),
778 // item->get_text());
779 // Increment position of next column
781 next_text_x += (column_width ?
783 default_column_width[j]);
785 // Set last column width based on text width
787 int new_w = get_item_w(item);
789 int *previous_w = (column_width ?
791 &default_column_width[j]);
792 if(new_w > *previous_w)
794 //printf("BC_ListBox::calculate_item_coords_recursive 1 %d\n", new_w);
796 total_autoplaced_columns++;
800 // Increase the text vertical position
801 if(total_autoplaced_columns)
803 display_format = LISTBOX_TEXT;
804 *next_text_y += get_text_height(MEDIUMFONT);
808 BC_ListBoxItem *item = data[master_column].values[i];
809 if(item->get_sublist() &&
810 item->get_columns() &&
813 calculate_item_coords_recursive(
824 void BC_ListBox::set_justify(int value)
826 this->justify = value;
829 void BC_ListBox::set_allow_drag_column(int value)
831 this->allow_drag_column = value;
834 void BC_ListBox::set_process_drag(int value)
836 this->process_drag = value;
839 void BC_ListBox::set_master_column(int value, int redraw)
841 this->master_column = value;
848 void BC_ListBox::set_search_column(int value)
850 this->search_column = value;
853 int BC_ListBox::get_sort_column()
858 void BC_ListBox::set_sort_column(int value, int redraw)
867 int BC_ListBox::get_sort_order()
872 void BC_ListBox::set_sort_order(int value, int redraw)
885 int BC_ListBox::get_display_mode()
887 return display_format;
890 int BC_ListBox::get_yposition()
895 int BC_ListBox::get_xposition()
900 int BC_ListBox::get_highlighted_item()
902 return highlighted_item;
906 int BC_ListBox::get_item_x(BC_ListBoxItem *item)
908 if(display_format == LISTBOX_TEXT)
909 return item->text_x - xposition + 2;
911 return item->icon_x - xposition + 2;
914 int BC_ListBox::get_item_y(BC_ListBoxItem *item)
917 if(display_format == LISTBOX_TEXT)
918 result = item->text_y - yposition + title_h + 2;
920 result = item->icon_y - yposition + title_h + 2;
924 int BC_ListBox::get_item_w(BC_ListBoxItem *item)
926 if(display_format == LISTBOX_ICONS)
929 get_icon_mask(item, x, y, w, h);
931 get_text_mask(item, x, y, w, h);
934 if(icon_position == ICON_LEFT)
935 return icon_w + text_w;
937 return (icon_w > text_w) ? icon_w : text_w;
941 return get_text_width(MEDIUMFONT, item->text) + 2 * LISTBOX_MARGIN;
945 int BC_ListBox::get_item_h(BC_ListBoxItem *item)
947 if(display_format == LISTBOX_ICONS)
950 get_icon_mask(item, x, y, w, h);
952 get_text_mask(item, x, y, w, h);
955 if(icon_position == ICON_LEFT)
956 return (icon_h > text_h) ? icon_h : text_h;
958 return icon_h + text_h;
962 return get_text_height(MEDIUMFONT);
968 int BC_ListBox::get_icon_w(BC_ListBoxItem *item)
970 BC_Pixmap *icon = item->icon;
971 if(icon) return icon->get_w();
975 int BC_ListBox::get_icon_h(BC_ListBoxItem *item)
977 BC_Pixmap *icon = item->icon;
978 if(icon) return icon->get_h();
982 int BC_ListBox::get_items_width()
986 if(display_format == LISTBOX_ICONS)
988 for(int i = 0; i < columns; i++)
990 for(int j = 0; j < data[i].total; j++)
993 BC_ListBoxItem *item = data[i].values[j];
996 get_icon_mask(item, x, y, w, h);
997 if(x1 + w > widest) widest = x1 + w;
999 if(display_format == LISTBOX_ICONS && icon_position == ICON_LEFT)
1002 get_text_mask(item, x, y, w, h);
1003 if(x1 + w > widest) widest = x1 + w;
1008 if(display_format == LISTBOX_TEXT)
1010 return get_column_offset(columns);
1015 int BC_ListBox::get_items_height(ArrayList<BC_ListBoxItem*> *data,
1032 for(int j = 0; j < (data ? data[master_column].total : 0); j++)
1035 BC_ListBoxItem *item = data[master_column].values[j];
1037 if(display_format == LISTBOX_ICONS)
1039 get_icon_mask(item, x, y, w, h);
1040 if(y + h + yposition > highest) highest = y + h + yposition;
1042 get_text_mask(item, x, y, w, h);
1043 if(y + h + yposition > highest) highest = y + h + yposition;
1047 get_text_mask(item, x, y, w, h);
1051 // Descend into sublist
1052 if(item->get_sublist() &&
1055 get_items_height(item->get_sublist(),
1056 item->get_columns(),
1061 if(display_format == LISTBOX_TEXT && top_level)
1063 highest = LISTBOX_MARGIN + *result;
1070 int BC_ListBox::set_yposition(int position, int draw_items)
1072 this->yposition = position;
1075 this->draw_items(1);
1080 int BC_ListBox::set_xposition(int position)
1082 this->xposition = position;
1087 void BC_ListBox::expand_item(BC_ListBoxItem *item, int expand)
1091 item->expand = expand;
1092 // Collapse sublists if this is collapsed to make it easier to calculate
1094 if(item->get_sublist())
1095 collapse_recursive(item->get_sublist(), master_column);
1098 // Set everything for autoplacement
1100 set_autoplacement(data, 0, 1);
1106 void BC_ListBox::collapse_recursive(ArrayList<BC_ListBoxItem*> *data,
1109 for(int i = 0; i < data[master_column].total; i++)
1111 BC_ListBoxItem *item = data[master_column].values[i];
1112 if(item->get_sublist() && item->expand)
1115 collapse_recursive(item->get_sublist(), master_column);
1120 void BC_ListBox::set_autoplacement(ArrayList<BC_ListBoxItem*> *data,
1124 for(int i = 0; i < data[0].total; i++)
1126 for(int j = 0; j < columns; j++)
1128 if(do_icons) data[j].values[i]->autoplace_icon = 1;
1129 if(do_text) data[j].values[i]->autoplace_text = 1;
1132 BC_ListBoxItem *item = data[master_column].values[i];
1133 if(item->get_sublist())
1135 set_autoplacement(item->get_sublist(), do_icons, do_text);
1142 int BC_ListBox::get_w()
1145 return BCPOPUPLISTBOX_W;
1150 int BC_ListBox::get_h()
1153 return BCPOPUPLISTBOX_H;
1158 int BC_ListBox::get_yscroll_x()
1161 return popup_w - get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w();
1165 get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w();
1168 int BC_ListBox::get_yscroll_y()
1176 int BC_ListBox::get_yscroll_height()
1178 return popup_h - (need_xscroll ?
1179 get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h() :
1183 int BC_ListBox::get_xscroll_x()
1191 int BC_ListBox::get_xscroll_y()
1195 get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h();
1199 get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h();
1202 int BC_ListBox::get_xscroll_width()
1204 return popup_w - (need_yscroll ?
1205 get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w() :
1209 int BC_ListBox::get_column_offset(int column)
1215 column_width[--column] :
1216 default_column_width[--column];
1221 void BC_ListBox::column_width_boundaries()
1225 for(int i = 0; i < columns; i++)
1227 if(column_width[i] < MIN_COLUMN_WIDTH) column_width[i] = MIN_COLUMN_WIDTH;
1232 for(int i = 0; i < columns; i++)
1234 if(default_column_width[i] < MIN_COLUMN_WIDTH) default_column_width[i] = MIN_COLUMN_WIDTH;
1239 int BC_ListBox::get_column_width(int column, int clamp_right)
1241 if(column < columns - 1 || !clamp_right)
1242 return column_width ?
1243 column_width[column] :
1244 default_column_width[column];
1248 get_column_offset(column);
1251 int BC_ListBox::get_icon_mask(BC_ListBoxItem *item,
1257 if(display_format == LISTBOX_ICONS)
1259 x = get_item_x(item);
1260 y = get_item_y(item);
1261 w = get_icon_w(item) + ICON_MARGIN * 2;
1262 h = get_icon_h(item) + ICON_MARGIN * 2;
1265 if(display_format == LISTBOX_TEXT)
1272 int BC_ListBox::get_text_mask(BC_ListBoxItem *item,
1278 x = get_item_x(item);
1279 y = get_item_y(item);
1281 if(display_format == LISTBOX_ICONS)
1283 if(icon_position == ICON_LEFT)
1285 x += get_icon_w(item) + ICON_MARGIN * 2;
1286 y += get_icon_h(item) - get_text_height(MEDIUMFONT);
1290 y += get_icon_h(item) + ICON_MARGIN;
1293 w = get_text_width(MEDIUMFONT, item->text) + ICON_MARGIN * 2;
1294 h = get_text_height(MEDIUMFONT) + ICON_MARGIN * 2;
1297 if(display_format == LISTBOX_TEXT)
1299 w = get_text_width(MEDIUMFONT, item->text) + LISTBOX_MARGIN * 2;
1300 h = get_text_height(MEDIUMFONT);
1305 int BC_ListBox::get_item_highlight(ArrayList<BC_ListBoxItem*> *data,
1309 BC_Resources *resources = get_resources();
1310 if(data[column].values[item]->selected)
1311 return resources->listbox_selected;
1313 if(highlighted_item >= 0 &&
1314 highlighted_ptr == data[master_column].values[item])
1315 return resources->listbox_highlighted;
1317 return resources->listbox_inactive;
1320 int BC_ListBox::get_item_color(ArrayList<BC_ListBoxItem*> *data,
1324 int color = data[column].values[item]->color;
1325 if(color == -1) color = get_resources()->listbox_text;
1326 if(get_item_highlight(data, column, item) == color)
1332 int BC_ListBox::get_from_column()
1334 return dragged_title;
1337 int BC_ListBox::get_to_column()
1339 return highlighted_title;
1343 BC_ListBoxItem* BC_ListBox::get_selection(int column,
1344 int selection_number)
1346 return get_selection_recursive(data,
1351 BC_ListBoxItem* BC_ListBox::get_selection_recursive(
1352 ArrayList<BC_ListBoxItem*> *data,
1354 int selection_number)
1358 for(int i = 0; i < data[master_column].total; i++)
1360 BC_ListBoxItem *item = data[master_column].values[i];
1364 if(selection_number < 0)
1367 return data[column].values[i];
1371 if(item->get_sublist())
1373 BC_ListBoxItem *result = get_selection_recursive(item->get_sublist(),
1376 if(result) return result;
1383 int BC_ListBox::get_selection_number(int column,
1384 int selection_number)
1386 return get_selection_number_recursive(data,
1391 int BC_ListBox::get_selection_number_recursive(
1392 ArrayList<BC_ListBoxItem*> *data,
1394 int selection_number,
1399 if(!counter) counter = &temp;
1401 for(int i = 0; i < data[master_column].total; i++)
1404 BC_ListBoxItem *item = data[master_column].values[i];
1408 if(selection_number < 0)
1413 if(item->get_sublist())
1415 int result = get_selection_number_recursive(
1416 item->get_sublist(),
1420 if(result >= 0) return result;
1427 int BC_ListBox::set_selection_mode(int mode)
1429 this->selection_mode = mode;
1433 void BC_ListBox::delete_columns()
1437 for(int i = 0; i < columns; i++)
1439 delete [] column_titles[i];
1441 delete [] column_titles;
1444 if(column_width) delete [] column_width;
1450 // Need to copy titles so EDL can change
1451 void BC_ListBox::set_columns(char **column_titles,
1455 if((!column_titles && column_width) ||
1456 (column_titles && !column_width))
1458 printf("BC_ListBox::set_columns either column_titles or column_width == NULL but not both.\n");
1467 this->column_titles = new char*[columns];
1468 for(int i = 0; i < columns; i++)
1470 this->column_titles[i] = new char[strlen(column_titles[i]) + 1];
1471 strcpy(this->column_titles[i], column_titles[i]);
1477 this->column_width = new int[columns];
1478 for(int i = 0; i < columns; i++)
1480 this->column_width[i] = column_width[i];
1484 this->columns = columns;
1489 int BC_ListBox::update(ArrayList<BC_ListBoxItem*> *data,
1490 char **column_titles,
1495 int highlighted_number,
1496 int recalc_positions,
1500 set_columns(column_titles,
1506 this->yposition = yposition;
1507 this->xposition = xposition;
1508 this->highlighted_item = highlighted_number;
1509 this->highlighted_ptr = index_to_item(data, highlighted_number, 0);
1511 if(recalc_positions)
1512 set_autoplacement(data, 1, 1);
1514 init_column_width();
1520 update_scrollbars();
1526 void BC_ListBox::center_selection()
1528 int selection = get_selection_number(0, 0);
1530 calculate_item_coords();
1531 center_selection(selection);
1538 update_scrollbars();
1542 void BC_ListBox::move_vertical(int pixels)
1546 void BC_ListBox::move_horizontal(int pixels)
1550 int BC_ListBox::select_previous(int skip,
1551 BC_ListBoxItem *selected_item,
1553 ArrayList<BC_ListBoxItem*> *data,
1559 selected_item = get_selection(0, 0);
1571 got_second = &temp3;
1576 // Scan backwards to item pointer. Then count visible items to get
1577 // destination. Repeat to get wraparound.
1580 for(int i = data[master_column].total - 1; i >= 0; i--)
1582 BC_ListBoxItem *current_item = data[master_column].values[i];
1583 if(current_item->get_sublist() &&
1584 current_item->get_expand())
1586 int result = select_previous(skip,
1589 current_item->get_sublist(),
1601 if((*counter) >= skip)
1603 for(int j = 0; j < columns; j++)
1604 data[j].values[i]->selected = 1;
1606 return item_to_index(this->data, current_item);
1611 if(current_item->selected)
1613 for(int j = 0; j < columns; j++)
1614 data[j].values[i]->selected = 0;
1621 // Hit bottom of top level without finding a selected item.
1622 if(top_level && !(*got_first)) (*got_first) = 1;
1623 }while(top_level && data[master_column].total);
1627 int BC_ListBox::select_next(int skip,
1628 BC_ListBoxItem *selected_item,
1630 ArrayList<BC_ListBoxItem*> *data,
1636 selected_item = get_selection(0, 0);
1648 got_second = &temp3;
1653 // Scan backwards to item pointer. Then count visible items to get
1654 // destination. Repeat to get wraparound.
1657 for(int i = 0; i < data[master_column].total; i++)
1659 BC_ListBoxItem *current_item = data[master_column].values[i];
1663 if((*counter) >= skip)
1665 for(int j = 0; j < columns; j++)
1666 data[j].values[i]->selected = 1;
1668 return item_to_index(this->data, current_item);
1673 if(current_item->selected)
1675 for(int j = 0; j < columns; j++)
1676 data[j].values[i]->selected = 0;
1682 if(current_item->get_sublist() &&
1683 current_item->get_expand())
1685 int result = select_next(skip,
1688 current_item->get_sublist(),
1698 // Hit bottom of top level without finding a selected item.
1699 if(top_level && !(*got_first)) (*got_first) = 1;
1700 }while(top_level && data[master_column].total);
1705 void BC_ListBox::clamp_positions()
1707 items_w = get_items_width();
1708 items_h = get_items_height(data, columns);
1710 if(yposition < 0) yposition = 0;
1712 if(yposition > items_h - view_h)
1713 yposition = items_h - view_h;
1715 if(yposition < 0) yposition = 0;
1717 if(xposition < 0) xposition = 0;
1719 if(xposition >= items_w - view_w)
1720 xposition = items_w - view_w;
1722 if(xposition < 0) xposition = 0;
1725 int BC_ListBox::center_selection(int selection,
1726 ArrayList<BC_ListBoxItem*> *data,
1730 if(!data) data = this->data;
1731 if(!counter) counter = &temp;
1733 for(int i = 0; i < data[master_column].total; i++)
1738 BC_ListBoxItem *item = data[master_column].values[i];
1739 if((*counter) == selection)
1741 BC_ListBoxItem *top_item = this->data[master_column].values[0];
1744 if(display_format == LISTBOX_ICONS)
1746 // Icon is out of window
1747 if(item->icon_y - yposition >
1748 view_h - get_text_height(MEDIUMFONT) ||
1749 item->icon_y - yposition < 0)
1751 yposition = item->icon_y - view_h / 2;
1754 if(data[master_column].values[selection]->icon_x - xposition > view_w ||
1755 data[master_column].values[selection]->icon_x - xposition < 0)
1757 xposition = item->icon_x - view_w / 2;
1761 if(display_format == LISTBOX_TEXT)
1763 // Text coordinate is out of window
1764 if(item->text_y - yposition >
1765 view_h - get_text_height(MEDIUMFONT) ||
1766 item->text_y - yposition < 0)
1768 yposition = item->text_y -
1777 if(item->get_sublist())
1779 int result = center_selection(selection,
1780 item->get_sublist(),
1782 if(result) return result;
1788 void BC_ListBox::update_scrollbars()
1790 int h_needed = items_h = get_items_height(data, columns);
1791 int w_needed = items_w = get_items_width();
1793 // if(columns > 0 && column_width)
1794 // printf("BC_ListBox::update_scrollbars 1 %d %d\n", column_width[columns - 1], w_needed);
1798 if(xposition != xscrollbar->get_value())
1799 xscrollbar->update_value(xposition);
1801 if(w_needed != xscrollbar->get_length() ||
1802 view_w != xscrollbar->get_handlelength())
1803 xscrollbar->update_length(w_needed, xposition, view_w);
1808 if(yposition != yscrollbar->get_value())
1809 yscrollbar->update_value(yposition);
1811 if(h_needed != yscrollbar->get_length() || view_h != yscrollbar->get_handlelength())
1812 yscrollbar->update_length(h_needed, yposition, view_h);
1816 int BC_ListBox::get_scrollbars()
1818 int h_needed = items_h = get_items_height(data, columns);
1819 int w_needed = items_w = get_items_width();
1823 title_h = get_title_h();
1825 view_h = popup_h - title_h - 4;
1826 view_w = popup_w - 4;
1828 // Create scrollbars as needed
1829 for(int i = 0; i < 2; i++)
1831 if(w_needed > view_w)
1836 get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h() -
1844 if(h_needed > view_h)
1848 get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w() -
1857 // Update subwindow size
1858 int new_w = popup_w;
1859 int new_h = popup_h;
1860 if(need_xscroll) new_h -= get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h();
1861 if(need_yscroll) new_w -= get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w();
1864 if(new_w != BC_WindowBase::get_w() || new_h != BC_WindowBase::get_h())
1865 gui->resize_window(new_w, new_h);
1867 BC_WindowBase *destination = (is_popup ? gui : parent_window);
1872 destination->add_subwindow(xscrollbar =
1873 new BC_ListBoxXScroll(this,
1877 xscrollbar->bound_to = this;
1881 xscrollbar->update_length(w_needed, xposition, view_w);
1882 xscrollbar->reposition_window(get_xscroll_x(),
1884 get_xscroll_width());
1889 if(xscrollbar) delete xscrollbar;
1898 destination->add_subwindow(yscrollbar =
1899 new BC_ListBoxYScroll(this,
1903 yscrollbar->bound_to = this;
1907 yscrollbar->update_length(h_needed, yposition, view_h);
1908 yscrollbar->reposition_window(get_yscroll_x(),
1910 get_yscroll_height());
1915 if(yscrollbar) delete yscrollbar;
1921 view_w + 4 != bg_surface->get_w() ||
1922 view_h + 4 != bg_surface->get_h())
1924 if(bg_surface) delete bg_surface;
1925 bg_surface = new BC_Pixmap(gui, view_w + 4, view_h + 4);
1934 void BC_ListBox::set_drag_scroll(int value)
1936 allow_drag_scroll = value;
1940 // Test for scrolling by dragging
1942 int BC_ListBox::test_drag_scroll(int cursor_x, int cursor_y)
1945 if(allow_drag_scroll ||
1946 current_operation == SELECT_RECT)
1949 int top_boundary = get_title_h();
1951 if(cursor_y < top_boundary ||
1952 cursor_y >= view_h + title_h + LISTBOX_BORDER * 2 ||
1953 cursor_x < LISTBOX_BORDER ||
1954 cursor_x >= view_w + LISTBOX_BORDER)
1962 int BC_ListBox::drag_scroll_event()
1964 int top_boundary = get_title_h();
1967 if(get_cursor_y() < top_boundary)
1969 yposition -= top_boundary - get_cursor_y();
1973 if(get_cursor_y() >= view_h + title_h + 4)
1975 yposition += get_cursor_y() - (view_h + title_h + 4);
1979 if(get_cursor_x() < 2)
1981 xposition -= 2 - get_cursor_x();
1985 if(get_cursor_x() >= view_w + 2)
1987 xposition += get_cursor_x() - (view_w + 2);
1990 if(result) clamp_positions();
1994 int BC_ListBox::rectangle_scroll_event()
1996 int old_xposition = xposition;
1997 int old_yposition = yposition;
1998 int result = drag_scroll_event();
2002 rect_x1 += old_xposition - xposition;
2003 rect_y1 += old_yposition - yposition;
2004 rect_x2 = get_cursor_x();
2005 rect_y2 = get_cursor_y();
2007 int x1 = MIN(rect_x1, rect_x2);
2008 int x2 = MAX(rect_x1, rect_x2);
2009 int y1 = MIN(rect_y1, rect_y2);
2010 int y2 = MAX(rect_y1, rect_y2);
2012 if(select_rectangle(data,
2018 selection_changed();
2023 update_scrollbars();
2028 int BC_ListBox::select_scroll_event()
2030 int result = drag_scroll_event();
2034 highlighted_item = selection_number = get_cursor_item(data,
2040 update_scrollbars();
2041 selection_changed();
2046 int BC_ListBox::select_rectangle(ArrayList<BC_ListBoxItem*> *data,
2053 for(int i = 0; i < data[master_column].total; i++)
2055 for(int j = 0; j < columns; j++)
2057 BC_ListBoxItem *item = data[j].values[i];
2058 if(display_format == LISTBOX_ICONS)
2060 int icon_x, icon_y, icon_w, icon_h;
2061 int text_x, text_y, text_w, text_h;
2062 get_icon_mask(item, icon_x, icon_y, icon_w, icon_h);
2063 get_text_mask(item, text_x, text_y, text_w, text_h);
2065 if((x2 >= icon_x && x1 < icon_x + icon_w &&
2066 y2 >= icon_y && y1 < icon_y + icon_h) ||
2067 (x2 >= text_x && x1 < text_x + text_w &&
2068 y2 >= text_y && y1 < text_y + text_h))
2089 gui->get_w() - get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w() :
2092 y1 < gui->get_h() &&
2093 y2 >= get_item_y(item) &&
2094 y1 < get_item_y(item) + get_item_h(item))
2113 BC_ListBoxItem *item = data[master_column].values[i];
2114 if(item->get_sublist() &&
2116 result |= select_rectangle(item->get_sublist(),
2125 int BC_ListBox::reposition_item(ArrayList<BC_ListBoxItem*> *data,
2126 int selection_number,
2132 if(!counter) counter = &temp;
2135 for(int i = 0; i < data[master_column].total; i++)
2137 BC_ListBoxItem *item = data[master_column].values[i];
2139 if((*counter) == selection_number)
2145 // Not recursive because it's only used for icons
2150 void BC_ListBox::move_selection(ArrayList<BC_ListBoxItem*> *dst,
2151 ArrayList<BC_ListBoxItem*> *src)
2153 for(int i = 0; i < src[master_column].total; i++)
2155 BC_ListBoxItem *item = src[master_column].values[i];
2160 for(int j = 0; j < columns; j++)
2162 dst[j].append(src[j].values[i]);
2163 src[j].remove_number(i);
2167 // Descend into sublist
2168 if(item->get_sublist())
2171 item->get_sublist());
2176 int BC_ListBox::put_selection(ArrayList<BC_ListBoxItem*> *data,
2177 ArrayList<BC_ListBoxItem*> *src,
2182 if(!counter) counter = &temp;
2186 for(int j = 0; j < columns; j++)
2188 for(int i = 0; i < src[j].total; i++)
2190 data[j].append(src[j].values[i]);
2196 for(int i = 0; i < data[master_column].total; i++)
2199 if((*counter) == destination)
2201 for(int j = 0; j < columns; j++)
2203 for(int k = 0; k < src[j].total; k++)
2205 data[j].insert(src[j].values[k], destination + k);
2211 BC_ListBoxItem *item = data[master_column].values[i];
2212 if(item->get_sublist())
2214 if(put_selection(item->get_sublist(),
2226 int BC_ListBox::item_to_index(ArrayList<BC_ListBoxItem*> *data,
2227 BC_ListBoxItem *item,
2231 if(!counter) counter = &temp;
2233 for(int i = 0; i < data[master_column].total; i++)
2236 for(int j = 0; j < columns; j++)
2238 BC_ListBoxItem *new_item = data[j].values[i];
2239 //printf("BC_ListBox::item_to_index 1 %d %d %p\n", j, i, new_item);
2240 if(new_item == item)
2246 BC_ListBoxItem *new_item = data[master_column].values[i];
2247 if(new_item->get_sublist())
2249 if(item_to_index(new_item->get_sublist(),
2259 BC_ListBoxItem* BC_ListBox::index_to_item(ArrayList<BC_ListBoxItem*> *data,
2265 if(!counter) counter = &temp;
2266 for(int i = 0; i < data[master_column].total; i++)
2269 if((*counter) == number)
2271 return data[column].values[i];
2273 BC_ListBoxItem *item = data[master_column].values[i];
2274 if(item->get_sublist())
2276 BC_ListBoxItem *result = index_to_item(item->get_sublist(),
2280 if(result) return result;
2286 int BC_ListBox::get_cursor_item(ArrayList<BC_ListBoxItem*> *data,
2289 BC_ListBoxItem **item_return,
2294 if(!data) return -1;
2295 if(!counter) counter = &temp;
2297 // Icons are not treed
2298 if(display_format == LISTBOX_ICONS)
2300 for(int j = data[master_column].total - 1; j >= 0; j--)
2302 int icon_x, icon_y, icon_w, icon_h;
2303 int text_x, text_y, text_w, text_h;
2304 BC_ListBoxItem *item = data[master_column].values[j];
2305 get_icon_mask(item, icon_x, icon_y, icon_w, icon_h);
2306 get_text_mask(item, text_x, text_y, text_w, text_h);
2308 if((cursor_x >= icon_x && cursor_x < icon_x + icon_w &&
2309 cursor_y >= icon_y && cursor_y < icon_y + icon_h) ||
2310 (cursor_x >= text_x && cursor_x < text_x + text_w &&
2311 cursor_y >= text_y && cursor_y < text_y + text_h))
2313 if(item_return) (*item_return) = item;
2320 if(display_format == LISTBOX_TEXT)
2322 // Cursor is inside items rectangle
2324 cursor_x < (yscrollbar ?
2325 gui->get_w() - get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w() :
2327 // Only clamp y if we're not in a SELECT operation.
2328 (current_operation == BC_ListBox::SELECT ||
2329 (cursor_y > get_title_h() + LISTBOX_BORDER &&
2330 cursor_y < gui->get_h())))
2332 // Search table for cursor obstruction
2333 for(int i = 0; i < data[master_column].total; i++)
2335 BC_ListBoxItem *item = data[master_column].values[i];
2338 // Cursor is inside item on current level
2341 cursor_y >= get_item_y(item) &&
2342 cursor_y < get_item_y(item) + get_item_h(item))
2344 //printf("BC_ListBox::get_cursor_item %d %d %p\n", master_column, i, item);
2345 if(item_return) (*item_return) = item;
2349 // Descend into sublist
2350 if(item->get_sublist())
2352 if(get_cursor_item(item->get_sublist(),
2357 item->get_expand()) >= 0)
2366 int BC_ListBox::repeat_event(int64_t duration)
2368 switch(current_operation)
2370 // Repeat out of bounds selection
2372 if(duration == get_resources()->scroll_repeat)
2373 return rectangle_scroll_event();
2377 if(duration == get_resources()->scroll_repeat)
2378 return select_scroll_event();
2383 if(button_highlighted &&
2384 duration == get_resources()->tooltip_delay &&
2385 tooltip_text[0] != 0 &&
2399 int BC_ListBox::cursor_enter_event()
2403 switch(current_operation)
2405 // Cursor moved over button, pressed, and exited.
2406 case BUTTON_DOWN_SELECT:
2407 if(top_level->event_win == win)
2409 current_operation = BUTTON_DN;
2411 button_highlighted = 1;
2417 // Cursor entered button
2418 if(is_popup && top_level->event_win == win)
2420 button_highlighted = 1;
2425 // TODO: Need to get the highlighted column title or item
2426 if(gui && top_level->event_win == gui->win)
2428 list_highlighted = 1;
2438 int BC_ListBox::cursor_leave_event()
2440 int redraw_button = 0;
2441 int redraw_border = 0;
2442 int redraw_titles = 0;
2443 int redraw_items = 0;
2445 if(current_operation == COLUMN_DRAG) return 0;
2448 if(button_highlighted)
2450 button_highlighted = 0;
2455 if(list_highlighted)
2457 list_highlighted = 0;
2458 highlighted_item = -1;
2459 highlighted_ptr = 0;
2460 highlighted_title = -1;
2461 int redraw_toggles = 0;
2462 for(int i = 0; i < expanders.total; i++)
2463 expanders.values[i]->cursor_leave_event(&redraw_toggles);
2471 int BC_ListBox::get_first_selection(ArrayList<BC_ListBoxItem*> *data, int *result)
2474 if(!result) result = &temp;
2476 for(int i = 0; i < data[master_column].total; i++)
2478 BC_ListBoxItem *item = data[master_column].values[i];
2480 if(item->selected) return (*result);
2481 if(item->get_sublist())
2483 if(get_first_selection(item->get_sublist(), result) >= 0)
2490 int BC_ListBox::get_total_items(ArrayList<BC_ListBoxItem*> *data,
2495 if(!result) result = &temp;
2497 for(int i = 0; i < data[master_column].total; i++)
2500 if(data[master_column].values[i]->get_sublist())
2501 get_total_items(data[master_column].values[i]->get_sublist(),
2510 int BC_ListBox::get_last_selection(ArrayList<BC_ListBoxItem*> *data,
2521 for(int i = data[master_column].total - 1; i >= 0; i--)
2523 BC_ListBoxItem *item = data[master_column].values[i];
2528 return get_total_items(data, 0, master_column) - (*result) /* - 1 */;
2533 if(item->get_sublist())
2535 if(get_last_selection(item->get_sublist(), result) >= 0)
2538 return get_total_items(data, 0, master_column) - (*result) /* - 1 */;
2547 void BC_ListBox::select_range(ArrayList<BC_ListBoxItem*> *data,
2553 if(!current) current = &temp;
2555 for(int i = 0; i < data[master_column].total; i++)
2558 if((*current) >= start && (*current) < end)
2560 for(int j = 0; j < columns; j++)
2561 data[j].values[i]->selected = 1;
2563 BC_ListBoxItem *item = data[master_column].values[i];
2564 if(item->get_sublist())
2565 select_range(item->get_sublist(),
2573 // Fill items between current selection and new selection
2574 int BC_ListBox::expand_selection(int button_press, int selection_number)
2576 int old_selection_start = selection_start;
2577 int old_selection_end = selection_end;
2579 // printf("BC_ListBox::expand_selection %d %d\n",
2580 // selection_center,
2581 // selection_number);
2583 // Calculate the range to select based on selection_center and selection_number
2584 if(selection_number < selection_center)
2586 selection_start = selection_number;
2590 selection_end = selection_number + 1;
2593 //printf("BC_ListBox::expand_selection %d %d %d %d\n", old_selection_start, old_selection_end, selection_start, selection_end);
2594 // Recurse through all the items and select the desired range
2595 select_range(data, selection_start, selection_end);
2598 return (old_selection_start != selection_start ||
2599 old_selection_end != selection_end);
2602 int BC_ListBox::toggle_item_selection(ArrayList<BC_ListBoxItem*> *data,
2603 int selection_number,
2607 if(!counter) counter = &temp;
2609 for(int i = 0; i < data[master_column].total; i++)
2611 BC_ListBoxItem *item = data[master_column].values[i];
2613 if((*counter) == selection_number)
2615 // Get new value for selection
2616 int selected = !item->selected;
2618 for(int j = 0; j < columns; j++)
2619 data[j].values[i]->selected = selected;
2623 // Descend into sublist
2624 if(item->get_sublist())
2626 if(toggle_item_selection(item->get_sublist(),
2637 void BC_ListBox::set_all_selected(ArrayList<BC_ListBoxItem*> *data, int value)
2639 for(int i = 0; i < data[master_column].total; i++)
2641 for(int j = 0; j < columns; j++)
2643 BC_ListBoxItem *item = data[j].values[i];
2644 item->selected = value;
2646 BC_ListBoxItem *item = data[master_column].values[i];
2647 if(item->get_sublist())
2649 set_all_selected(item->get_sublist(), value);
2654 void BC_ListBox::set_selected(ArrayList<BC_ListBoxItem*> *data,
2660 if(!counter) counter = &temp;
2661 for(int i = 0; i < data[master_column].total && (*counter) != item_number; i++)
2664 if((*counter) == item_number)
2666 for(int j = 0; j < columns; j++)
2668 BC_ListBoxItem *item = data[j].values[i];
2669 item->selected = value;
2674 BC_ListBoxItem *item = data[master_column].values[i];
2675 if(item->get_sublist())
2677 set_selected(item->get_sublist(),
2685 int BC_ListBox::update_selection(ArrayList<BC_ListBoxItem*> *data,
2686 int selection_number,
2691 if(!counter) counter = &temp;
2693 for(int i = 0; i < data[master_column].total; i++)
2695 BC_ListBoxItem *item = data[master_column].values[i];
2697 if((*counter) == selection_number && !item->selected)
2700 for(int j = 0; j < columns; j++)
2701 data[j].values[i]->selected = 1;
2704 if((*counter) != selection_number && item->selected)
2707 for(int j = 0; j < columns; j++)
2708 data[j].values[i]->selected = 0;
2710 if(item->get_sublist())
2711 result |= update_selection(item->get_sublist(),
2718 void BC_ListBox::promote_selections(ArrayList<BC_ListBoxItem*> *data,
2722 for(int i = 0; i < data[master_column].total; i++)
2724 for(int j = 0; j < columns; j++)
2726 BC_ListBoxItem *item = data[j].values[i];
2727 if(item->selected == old_value) item->selected = new_value;
2729 BC_ListBoxItem *item = data[master_column].values[i];
2730 if(item->get_sublist())
2731 promote_selections(item->get_sublist(), old_value, new_value);
2735 int BC_ListBox::focus_out_event()
2741 int BC_ListBox::button_press_event()
2744 BC_ListBoxItem *current_item = 0;
2746 int do_selection_change = 0;
2752 // Pressed in button
2753 if(is_popup && top_level->event_win == win)
2755 current_operation = BUTTON_DN;
2759 if(!active && !disabled)
2761 top_level->deactivate();
2768 // Pressed in scrollbar
2769 if((xscrollbar && top_level->event_win == xscrollbar->win) ||
2770 (yscrollbar && top_level->event_win == yscrollbar->win))
2776 if(gui && top_level->event_win == gui->win)
2778 // Activate list items
2781 top_level->deactivate();
2785 // Wheel mouse pressed
2786 if(get_buttonpress() == 4 && current_operation == NO_OPERATION)
2788 current_operation = WHEEL;
2791 set_yposition(yposition - gui->get_h() / 10, 0);
2793 update_scrollbars();
2794 highlighted_ptr = 0;
2795 highlighted_item = get_cursor_item(data,
2796 top_level->cursor_x,
2797 top_level->cursor_y,
2804 if(get_buttonpress() == 5 && current_operation == NO_OPERATION)
2806 current_operation = WHEEL;
2809 set_yposition(yposition + gui->get_h() / 10, 0);
2811 update_scrollbars();
2812 highlighted_ptr = 0;
2813 highlighted_item = get_cursor_item(data,
2814 top_level->cursor_x,
2815 top_level->cursor_y,
2822 // Pressed over column title division
2823 if(test_column_divisions(gui->get_cursor_x(),
2824 gui->get_cursor_y(),
2827 current_operation = DRAG_DIVISION;
2831 // Pressed in column title
2832 if(test_column_titles(gui->get_cursor_x(), gui->get_cursor_y()))
2834 current_operation = COLUMN_DN;
2835 button_highlighted = 0;
2836 list_highlighted = 1;
2841 // Pressed in expander
2842 if(test_expanders())
2844 current_operation = EXPAND_DN;
2845 // Need to redraw items because of alpha
2850 // Pressed over item
2851 if((selection_number = get_cursor_item(data,
2852 gui->get_cursor_x(),
2853 gui->get_cursor_y(),
2854 ¤t_item)) >= 0)
2856 // Get item button was pressed over
2857 selection_number2 = selection_number1;
2858 selection_number1 = selection_number;
2860 selection_start = -1;
2864 // Multiple item selection is possible
2865 if(selection_mode == LISTBOX_MULTIPLE &&
2866 (ctrl_down() || shift_down()))
2868 // Expand text selection.
2869 // Fill items between selected region and current item.
2870 if(shift_down() && display_format == LISTBOX_TEXT)
2872 // Get first item selected
2873 selection_start = get_first_selection(data);
2874 // Get last item selected
2875 selection_end = get_last_selection(data);
2876 // Get center of selected region
2877 if(selection_end > selection_start)
2879 selection_center = (selection_end + selection_start) >> 1;
2883 selection_center = selection_number;
2887 // Deselect everything.
2888 set_all_selected(data, 0);
2889 // Select just the items
2890 expand_selection(1, selection_number);
2894 // Toggle a single item on or off
2896 toggle_item_selection(data, selection_number);
2897 new_value = current_item->selected;
2901 // Select single item
2903 if(!current_item->selected)
2905 set_all_selected(data, 0);
2914 current_operation = SELECT;
2915 highlighted_item = selection_number;
2916 highlighted_ptr = current_item;
2917 button_highlighted = 0;
2918 list_highlighted = 1;
2921 do_selection_change = 1;
2926 // Pressed over nothing. Start rectangle selection.
2928 if(get_buttonpress() == 1 &&
2929 selection_mode == LISTBOX_MULTIPLE)
2933 // Deselect all and redraw if anything was selected
2934 if(get_selection_number(0, 0) >= 0)
2936 set_all_selected(data, 0);
2938 do_selection_change = 1;
2944 // Promote selections to protect from a rectangle selection
2945 promote_selections(data, 1, 2);
2948 // Start rectangle selection
2949 current_operation = SELECT_RECT;
2950 rect_x1 = rect_x2 = get_cursor_x();
2951 rect_y1 = rect_y2 = get_cursor_y();
2959 if(is_popup && active)
2966 if(do_selection_change) selection_changed();
2971 int BC_ListBox::button_release_event()
2974 int cursor_x, cursor_y;
2978 //printf("BC_ListBox::button_release_event 1 %d\n", current_operation);
2979 switch(current_operation)
2982 current_operation = NO_OPERATION;
2987 current_operation = NO_OPERATION;
2991 // Release item selection
2992 case BUTTON_DOWN_SELECT:
2994 //printf("BC_ListBox::button_release_event 10\n");
2995 unset_repeat(get_resources()->scroll_repeat);
2996 current_operation = NO_OPERATION;
2997 translate_coordinates(top_level->event_win,
2999 gui->get_cursor_x(),
3000 gui->get_cursor_y(),
3006 get_cursor_item(data, cursor_x, cursor_y);
3007 //printf("BC_ListBox::button_release_event %d %d\n", selection_number2, selection_number1);
3012 if(selection_number >= 0)
3018 // Second button release outside button
3019 if(button_releases > 1)
3026 if(top_level->get_double_click() &&
3027 selection_number2 == selection_number1 &&
3028 selection_number2 >= 0 &&
3029 selection_number1 >= 0)
3039 unset_repeat(get_resources()->scroll_repeat);
3042 // Demote selections from rectangle selection
3043 promote_selections(data, 2, 1);
3046 // Hide rectangle overlay
3048 current_operation = NO_OPERATION;
3052 // Release popup button
3055 current_operation = NO_OPERATION;
3059 // Second button release inside button
3060 if(button_releases > 1)
3068 current_operation = NO_OPERATION;
3069 // Update the sort column and the sort order for the user only if the existing
3070 // sort column is valid.
3071 if(sort_column >= 0)
3073 // Invert order only if column is the same
3074 if(highlighted_title == sort_column)
3076 (sort_order == SORT_ASCENDING) ?
3079 // Set the new sort column
3080 sort_column = highlighted_title;
3081 if(!sort_order_event())
3087 // Sorting not enabled. Redraw the title state.
3096 int redraw_toggles = 0;
3097 for(int i = 0; i < expanders.total && !result; i++)
3099 if(expanders.values[i]->button_release_event(&redraw_toggles))
3104 // Need to redraw items because of alpha
3105 if(redraw_toggles) draw_items(1);
3106 current_operation = NO_OPERATION;
3111 // Can't default to NO_OPERATION because it may be used in a drag event.
3116 if(do_event) handle_event();
3121 int BC_ListBox::get_title_h()
3123 if(display_format == LISTBOX_TEXT)
3124 return column_titles ? column_bg[0]->get_h() : 0;
3129 void BC_ListBox::reset_cursor(int new_cursor)
3133 if(gui->get_cursor() != new_cursor)
3135 gui->set_cursor(new_cursor);
3139 if(get_cursor() != new_cursor)
3141 set_cursor(new_cursor);
3145 int BC_ListBox::test_column_divisions(int cursor_x, int cursor_y, int &new_cursor)
3150 cursor_y < get_title_h() &&
3152 cursor_x < gui->get_w())
3154 for(int i = 1; i < columns; i++)
3156 if(cursor_x >= -xposition + get_column_offset(i) - 5 &&
3157 cursor_x < -xposition + get_column_offset(i) +
3158 get_resources()->listbox_title_hotspot)
3160 highlighted_item = -1;
3161 highlighted_ptr = 0;
3162 highlighted_division = i;
3163 highlighted_title = -1;
3164 list_highlighted = 1;
3165 new_cursor = HSEPARATE_CURSOR;
3170 highlighted_division = -1;
3174 int BC_ListBox::test_column_titles(int cursor_x, int cursor_y)
3179 cursor_y < get_title_h() &&
3181 cursor_x < gui->get_w())
3183 for(int i = 0; i < columns; i++)
3185 if(cursor_x >= -xposition + get_column_offset(i) &&
3186 (cursor_x < -xposition + get_column_offset(i + 1) ||
3189 highlighted_item = -1;
3190 highlighted_ptr = 0;
3191 highlighted_division = -1;
3192 highlighted_title = i;
3193 list_highlighted = 1;
3198 highlighted_title = -1;
3202 int BC_ListBox::test_expanders()
3204 for(int i = 0; i < expanders.total; i++)
3206 if(expanders.values[i]->button_press_event())
3208 current_operation = EXPAND_DN;
3216 int BC_ListBox::cursor_motion_event()
3218 int redraw = 0, result = 0;
3219 int new_cursor = ARROW_CURSOR;
3221 selection_number = -1;
3224 switch(current_operation)
3227 // Button pressed and slid off button
3228 if(!cursor_inside())
3230 current_operation = BUTTON_DOWN_SELECT;
3238 int new_w = get_cursor_x() +
3240 get_column_offset(highlighted_division - 1);
3241 new_cursor = HSEPARATE_CURSOR;
3245 column_width[highlighted_division - 1] = new_w;
3249 default_column_width[highlighted_division - 1] = new_w;
3252 column_width_boundaries();
3254 // Force update of coords
3255 set_autoplacement(data, 0, 1);
3256 column_resize_event();
3260 update_scrollbars();
3267 if(test_drag_scroll(get_cursor_x(), get_cursor_y()))
3269 set_repeat(get_resources()->scroll_repeat);
3272 int old_x1 = MIN(rect_x1, rect_x2);
3273 int old_x2 = MAX(rect_x1, rect_x2);
3274 int old_y1 = MIN(rect_y1, rect_y2);
3275 int old_y2 = MAX(rect_y1, rect_y2);
3277 int new_rect_x2 = get_cursor_x();
3278 int new_rect_y2 = get_cursor_y();
3280 int x1 = MIN(rect_x1, new_rect_x2);
3281 int x2 = MAX(rect_x1, new_rect_x2);
3282 int y1 = MIN(rect_y1, new_rect_y2);
3283 int y2 = MAX(rect_y1, new_rect_y2);
3285 // Adjust rectangle coverage
3293 redraw = select_rectangle(data,
3305 rect_x2 = get_cursor_x();
3306 rect_y2 = get_cursor_y();
3311 update_scrollbars();
3312 selection_changed();
3324 int old_highlighted_item = highlighted_item;
3325 int old_highlighted_title = highlighted_title;
3326 BC_ListBoxItem *old_highlighted_ptr = highlighted_ptr;
3328 if(test_drag_scroll(get_cursor_x(),
3331 set_repeat(get_resources()->scroll_repeat);
3335 highlighted_item = selection_number = get_cursor_item(data,
3341 // Deselect all items and select just the one we're over
3342 if(selection_number >= 0 &&
3346 selection_mode == LISTBOX_SINGLE))
3348 redraw = update_selection(data, selection_number);
3351 if(selection_mode == LISTBOX_MULTIPLE &&
3352 (shift_down() || ctrl_down()))
3353 // Expand multiple selection
3355 // Expand selected region in text mode centered around initial range
3356 if(display_format == LISTBOX_TEXT && shift_down())
3358 // Deselect everything.
3359 set_all_selected(data, 0);
3361 // Select just the items
3362 redraw = expand_selection(0, selection_number);
3365 // Set the one item we're over to the selection value determined in
3366 // button_press_event.
3374 if(highlighted_item != old_highlighted_item)
3378 update_scrollbars();
3379 //printf("BC_ListBox::cursor_motion_event %d %d\n", highlighted_item, old_highlighted_item);
3380 selection_changed();
3385 case BUTTON_DOWN_SELECT:
3386 // Went back into button area
3389 current_operation = BUTTON_DN;
3394 // Went into item area
3397 int cursor_x = 0, cursor_y = 0;
3398 translate_coordinates(top_level->event_win,
3400 top_level->cursor_x,
3401 top_level->cursor_y,
3404 int old_highlighted_item = highlighted_item;
3405 highlighted_item = selection_number = get_cursor_item(data,
3410 if(highlighted_item != old_highlighted_item)
3412 update_selection(data, selection_number);
3414 selection_changed();
3421 int redraw_toggles = 0;
3422 for(int i = 0; i < expanders.total && !result; i++)
3424 result = expanders.values[i]->cursor_motion_event(
3429 // Need to redraw items because of the alpha
3437 int cursor_x = get_cursor_x(), cursor_y = get_cursor_y();
3438 if(gui && top_level->event_win == gui->win)
3440 int old_highlighted_title = highlighted_title;
3441 int old_list_highlighted = list_highlighted;
3442 int old_highlighted_division = highlighted_division;
3443 int old_highlighted_item = highlighted_item;
3444 int redraw_titles = 0;
3445 int redraw_border = 0;
3446 int redraw_items = 0;
3447 int redraw_toggles = 0;
3451 // Test if cursor moved over a title division
3452 test_column_divisions(cursor_x, cursor_y, new_cursor);
3454 // Test if cursor moved over a title
3455 if(highlighted_division < 0)
3457 test_column_titles(cursor_x, cursor_y);
3460 // Test if cursor moved over expander
3461 if(highlighted_division < 0 &&
3462 highlighted_title < 0 &&
3463 display_format == LISTBOX_TEXT)
3465 for(int i = 0; i < expanders.total; i++)
3467 expanders.values[i]->cursor_motion_event(
3470 //printf("BC_ListBox::cursor_motion_event %d\n", redraw_toggles);
3473 // Test if cursor moved over an item
3474 if(highlighted_division < 0 &&
3475 highlighted_title < 0)
3477 highlighted_item = get_cursor_item(data,
3484 // Clear title highlighting if moved over division
3485 if(old_highlighted_title != highlighted_title)
3490 // Highlight list border
3491 if(old_list_highlighted != list_highlighted)
3496 // Moved out of item area
3497 if(old_highlighted_item != highlighted_item)
3502 //printf("BC_ListBox::cursor_motion_event 1 %d\n", highlighted_item);
3504 // Change cursor to title division adjustment
3505 reset_cursor(new_cursor);
3532 if(!result && list_highlighted)
3534 list_highlighted = 0;
3535 highlighted_item = -1;
3536 highlighted_ptr = 0;
3537 highlighted_title = -1;
3538 highlighted_division = -1;
3550 int BC_ListBox::drag_start_event()
3552 switch(current_operation)
3556 gui->is_event_win() &&
3559 BC_ListBoxItem *item_return = 0;
3560 selection_number = get_cursor_item(data,
3561 top_level->cursor_x,
3562 top_level->cursor_y,
3565 if(selection_number >= 0)
3568 if (item_return->icon_vframe)
3570 drag_popup = new BC_DragWindow(this,
3571 item_return->icon_vframe,
3572 get_abs_cursor_x(0) - item_return->icon_vframe->get_w() / 2,
3573 get_abs_cursor_y(0) - item_return->icon_vframe->get_h() / 2);
3576 // this probably works not!
3577 if (item_return->icon)
3578 drag_popup = new BC_DragWindow(this,
3580 get_abs_cursor_x(0) - item_return->icon->get_w() / 2,
3581 get_abs_cursor_y(0) - item_return->icon->get_h() / 2);
3583 drag_popup = new BC_DragWindow(this,
3585 get_abs_cursor_x(0) - drag_icon_vframe->get_w() / 2,
3586 get_abs_cursor_y(0) - drag_icon_vframe->get_h() / 2);
3587 current_operation = DRAG_ITEM;
3594 if(gui && gui->is_event_win() && allow_drag_column)
3596 drag_popup = new BC_DragWindow(this,
3597 drag_column_icon_vframe,
3598 get_abs_cursor_x(0) - drag_column_icon_vframe->get_w() / 2,
3599 get_abs_cursor_y(0) - drag_column_icon_vframe->get_h() / 2);
3600 dragged_title = highlighted_title;
3601 current_operation = COLUMN_DRAG;
3611 int BC_ListBox::drag_motion_event()
3613 //printf("BC_ListBox::drag_motion_event 1 %d\n", current_operation);
3614 switch(current_operation)
3620 int new_highlighted_item = -1;
3621 BC_ListBoxItem *new_highlighted_ptr = 0;
3622 int new_highlight = new_highlighted_item = get_cursor_item(data,
3623 top_level->cursor_x,
3624 top_level->cursor_y,
3625 &new_highlighted_ptr);
3627 if(new_highlighted_item != highlighted_item)
3632 // Always update highlighted value for drag_stop
3633 highlighted_item = new_highlighted_item;
3634 highlighted_ptr = new_highlighted_ptr;
3635 //printf("BC_ListBox::drag_motion_event 1 %p\n", highlighted_ptr);
3640 update_scrollbars();
3643 return drag_popup->cursor_motion_event();
3649 int old_highlighted_title = highlighted_title;
3650 test_column_titles(get_cursor_x(), get_cursor_y());
3651 if(old_highlighted_title != highlighted_title)
3655 return drag_popup->cursor_motion_event();
3662 int BC_ListBox::drag_stop_event()
3664 switch(current_operation)
3667 // Inside window boundary
3668 if(top_level->cursor_x > 0 &&
3669 top_level->cursor_x < gui->get_w() - drag_popup->get_w() / 2 &&
3670 top_level->cursor_y > 0 &&
3671 top_level->cursor_y < gui->get_h() - drag_popup->get_h() / 2)
3676 if(display_format == LISTBOX_ICONS)
3678 reposition_item(data,
3680 top_level->cursor_x +
3681 drag_popup->get_offset_x() -
3685 top_level->cursor_y +
3686 drag_popup->get_offset_y() -
3696 int destination = highlighted_item = item_to_index(data,
3698 //printf("BC_ListBox::drag_stop_event 1 %p %d\n", highlighted_ptr, destination);
3700 // Move selected items from data to temporary
3701 ArrayList<BC_ListBoxItem*> *src_items =
3702 new ArrayList<BC_ListBoxItem*>[columns];
3704 move_selection(src_items, data);
3706 // Insert items from temporary to data
3712 delete [] src_items;
3713 set_autoplacement(data, 0, 1);
3720 drag_popup->drag_failure_event();
3724 current_operation = NO_OPERATION;
3730 if(dragged_title != highlighted_title)
3732 if(highlighted_title >= 0)
3734 if(!move_column_event()) draw_titles(1);
3737 drag_popup->drag_failure_event();
3739 current_operation = NO_OPERATION;
3748 BC_DragWindow* BC_ListBox::get_drag_popup()
3753 int BC_ListBox::translation_event()
3757 int new_x = gui->get_x() +
3758 (top_level->last_translate_x -
3760 top_level->get_resources()->get_left_border());
3761 int new_y = gui->get_y() +
3762 (top_level->last_translate_y -
3764 top_level->get_resources()->get_top_border());
3766 gui->reposition_window(new_x, new_y);
3772 int BC_ListBox::reposition_window(int x, int y, int w, int h)
3776 if(w != -1) popup_w = w;
3777 if(h != -1) popup_h = h;
3778 //printf("BC_ListBox::reposition_window %d %d\n", popup_w, popup_h);
3782 if(w != -1) popup_w = w;
3783 if(h != -1) popup_h = h;
3785 xscrollbar->reposition_window(get_xscroll_x(),
3787 get_xscroll_width());
3789 yscrollbar->reposition_window(get_yscroll_x(),
3791 get_yscroll_height());
3796 BC_WindowBase::reposition_window(x, y, w, h);
3802 int BC_ListBox::deactivate()
3813 highlighted_item = -1;
3814 highlighted_ptr = 0;
3816 top_level->active_subwindow = 0;
3821 int BC_ListBox::activate()
3825 top_level->active_subwindow = this;
3827 button_releases = 0;
3834 y = get_y() + get_h();
3835 if(justify == LISTBOX_RIGHT)
3837 x = get_x() - popup_w + get_w();
3845 XTranslateCoordinates(top_level->display,
3854 if(new_x < 0) new_x = 0;
3855 if(new_y + popup_h > top_level->get_root_h(0))
3856 new_y -= get_h() + popup_h;
3858 //printf("BC_ListBox::activate %d %d\n", popup_w, popup_h);
3859 add_subwindow(gui = new BC_Popup(this,
3873 int BC_ListBox::keypress_event()
3875 if(!active) return 0;
3877 int result = 0, redraw = 0, done, view_items = view_h / get_text_height(MEDIUMFONT);
3878 int new_item = -1, new_selection = 0;
3880 switch(top_level->get_keypress())
3884 top_level->deactivate();
3889 new_selection = new_item = select_previous(0);
3891 //printf("BC_ListBox::keypress_event 1 %d\n", new_item);
3894 center_selection(new_item);
3901 new_selection = new_item = select_next(0);
3905 center_selection(new_item);
3912 new_selection = new_item = select_previous(view_items - 1);
3916 center_selection(new_item);
3923 new_selection = new_item = select_next(view_items - 1);
3927 center_selection(new_item);
3948 if(top_level->get_keypress() > 30 &&
3949 top_level->get_keypress() < 127)
3951 int query_len = strlen(query);
3952 query[query_len++] = top_level->get_keypress();
3953 query[query_len] = 0;
3954 new_selection = query_list();
3957 if(top_level->get_keypress() == BACKSPACE)
3959 int query_len = strlen(query);
3960 if(query_len > 0) query[--query_len] = 0;
3961 new_selection = query_list();
3974 update_scrollbars();
3977 if(new_selection >= 0)
3979 selection_changed();
3986 BC_Pixmap* BC_ListBox::get_bg_surface()
3992 void BC_ListBox::draw_background()
3994 // White background pixmap
3995 set_color(top_level->get_resources()->listbox_inactive);
3996 draw_box(0, 0, bg_surface->get_w(), bg_surface->get_h(), bg_surface);
3998 // Optional heroine pixmap
4000 bg_surface->draw_pixmap(bg_pixmap,
4001 bg_surface->get_w() - top_level->get_resources()->listbox_bg->get_w(),
4005 void BC_ListBox::clear_listbox(int x, int y, int w, int h)
4007 gui->draw_pixmap(bg_surface,
4016 void BC_ListBox::update_format(int display_format, int redraw)
4018 this->display_format = display_format;
4021 if(gui) draw_items(1);
4025 int BC_ListBox::get_format()
4027 return display_format;
4032 int BC_ListBox::draw_items(int flash)
4036 BC_Resources *resources = get_resources();
4038 //dump(data, columns);
4040 // Calculate items width
4041 calculate_item_coords();
4044 // Create and destroy scrollbars as needed
4049 // draw_background();
4052 if(display_format == LISTBOX_ICONS)
4054 clear_listbox(2, 2 + title_h, view_w, view_h);
4056 set_font(MEDIUMFONT);
4057 for(int i = 0; i < data[master_column].total; i++)
4059 BC_ListBoxItem *item = data[master_column].values[i];
4060 if(get_item_x(item) >= -get_item_w(item) &&
4061 get_item_x(item) < view_w &&
4062 get_item_y(item) >= -get_item_h(item) + title_h &&
4063 get_item_y(item) < view_h + title_h)
4065 int item_color = get_item_highlight(data, 0, i);
4066 int icon_x, icon_y, icon_w, icon_h;
4067 int text_x, text_y, text_w, text_h;
4070 get_icon_mask(item, icon_x, icon_y, icon_w, icon_h);
4071 get_text_mask(item, text_x, text_y, text_w, text_h);
4074 if(item_color != resources->listbox_inactive)
4076 gui->set_color(BLACK);
4077 gui->draw_rectangle(icon_x, icon_y, icon_w, icon_h);
4078 gui->set_color(item_color);
4079 gui->draw_box(icon_x + 1, icon_y + 1, icon_w - 2, icon_h - 2);
4080 gui->set_color(BLACK);
4081 gui->draw_rectangle(text_x, text_y, text_w, text_h);
4082 gui->set_color(item_color);
4083 gui->draw_box(text_x + 1, text_y + 1, text_w - 2, text_h - 2);
4085 if(icon_position == ICON_LEFT)
4086 gui->draw_box(text_x - 1, text_y + 1, 2, text_h - 2);
4088 if(icon_position == ICON_TOP)
4089 gui->draw_line(text_x + 1, text_y, text_x + icon_w - 2, text_y);
4090 if(text_x + text_w < icon_x + icon_w)
4092 gui->set_color(BLACK);
4093 gui->draw_line(text_x + text_w,
4101 gui->set_color(get_item_color(data, 0, i));
4103 item->icon->write_drawable(gui->pixmap,
4104 icon_x + ICON_MARGIN,
4105 icon_y + ICON_MARGIN);
4106 gui->draw_text(text_x + ICON_MARGIN,
4107 text_y + ICON_MARGIN + get_text_ascent(MEDIUMFONT),
4114 if(display_format == LISTBOX_TEXT)
4116 // Draw one column at a time so text overruns don't go into the next column
4117 // clear column backgrounds
4118 int current_toggle = 0;
4119 for(int j = 0; j < columns; j++)
4121 clear_listbox(LISTBOX_BORDER + get_column_offset(j) - xposition,
4122 LISTBOX_BORDER + title_h,
4123 get_column_width(j, 1),
4126 // Draw rows in the column recursively
4127 draw_text_recursive(data, j, 0, ¤t_toggle);
4130 // Delete excess expanders
4131 while(expanders.total > current_toggle)
4133 expanders.remove_object();
4137 // Draw titles on top of rows for superposition effect
4140 // Clear garbage from bottom right corner
4141 if(xscrollbar && yscrollbar && is_popup)
4143 gui->draw_top_background(parent_window,
4144 popup_w - get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w(),
4145 popup_h - get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h(),
4146 get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w(),
4147 get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h());
4154 if(current_operation == SELECT_RECT)
4168 void BC_ListBox::draw_text_recursive(ArrayList<BC_ListBoxItem*> *data,
4171 int *current_toggle)
4176 BC_Resources *resources = get_resources();
4178 set_font(MEDIUMFONT);
4181 // Search for a branch and make room for toggle if there is one
4184 for(int i = 0; i < data[column].total; i++)
4186 if(data[column].values[i]->get_sublist())
4188 subindent = BC_WindowBase::get_resources()->listbox_expand[0]->get_w();
4194 for(int i = 0; i < data[column].total; i++)
4197 BC_ListBoxItem *item = data[column].values[i];
4198 BC_ListBoxItem *first_item = data[master_column].values[i];
4200 if(get_item_y(item) >= -get_item_h(item) + title_h &&
4201 get_item_y(item) < view_h + title_h)
4203 int row_color = get_item_highlight(data, 0, i);
4204 int x, y, w, h, column_width;
4206 get_text_mask(item, x, y, w, h);
4207 column_width = get_column_width(column, 1);
4208 if(x + column_width > view_w + LISTBOX_BORDER * 2)
4209 column_width = view_w + LISTBOX_BORDER * 2 - x;
4211 if(row_color != resources->listbox_inactive)
4213 gui->set_color(row_color);
4218 gui->set_color(BLACK);
4221 x + column_width - 1,
4224 y + get_text_height(MEDIUMFONT),
4225 x + column_width - 1,
4226 y + get_text_height(MEDIUMFONT));
4229 gui->set_color(get_item_color(data, column, i));
4232 // Indent only applies to first column
4237 (column == 0 ? indent + subindent : 0),
4238 y + get_text_ascent(MEDIUMFONT),
4244 item->get_sublist() &&
4245 item->get_columns())
4247 // Create new expander
4248 if(*current_toggle >= expanders.total)
4250 BC_ListBoxToggle *toggle =
4251 new BC_ListBoxToggle(this,
4253 x + LISTBOX_BORDER + LISTBOX_MARGIN + indent,
4256 expanders.append(toggle);
4259 // Reposition existing expander
4261 BC_ListBoxToggle *toggle = expanders.values[*current_toggle];
4262 //printf("BC_ListBox::draw_text_recursive 1 %d\n", *current_toggle);
4263 toggle->update(item,
4264 x + LISTBOX_BORDER + LISTBOX_MARGIN + indent,
4268 (*current_toggle)++;
4275 // Descend into sublist
4276 if(first_item->get_expand())
4278 draw_text_recursive(first_item->get_sublist(),
4280 indent + LISTBOX_INDENT,
4290 int BC_ListBox::draw_border(int flash)
4292 BC_Resources *resources = top_level->get_resources();
4293 gui->draw_3d_border(0,
4295 view_w + LISTBOX_BORDER * 2,
4296 view_h + title_h + LISTBOX_BORDER * 2,
4297 resources->listbox_border1,
4299 resources->listbox_border2_hi :
4300 resources->listbox_border2,
4302 resources->listbox_border3_hi :
4303 resources->listbox_border3,
4304 resources->listbox_border4);
4314 int BC_ListBox::draw_titles(int flash)
4316 if(column_titles && display_format == LISTBOX_TEXT)
4318 //printf("BC_ListBox::draw_titles 1 %d\n", highlighted_title);
4319 for(int i = 0; i < columns; i++)
4323 // Column title background
4324 int image_number = 0;
4325 if(i == highlighted_title)
4328 if(current_operation == COLUMN_DN)
4332 int column_offset = get_column_offset(i) - xposition + LISTBOX_BORDER;
4333 int column_width = get_column_width(i, 1);
4334 gui->draw_3segmenth(get_column_offset(i) - xposition + LISTBOX_BORDER,
4336 get_column_width(i, 1),
4337 column_bg[image_number]);
4339 // Column title sort order
4340 if(i == sort_column)
4343 if(sort_order == SORT_ASCENDING)
4344 src = column_sort_dn;
4346 src = column_sort_up;
4348 int x = column_offset +
4351 if(x > items_w) x = items_w;
4352 x -= 5 + src->get_w();
4353 gui->draw_pixmap(src,
4355 title_h / 2 - src->get_h() / 2 + LISTBOX_BORDER);
4359 int x = -xposition +
4360 get_column_offset(i) +
4363 x += get_resources()->listbox_title_margin;
4365 gui->set_color(get_resources()->listbox_title_color);
4367 LISTBOX_MARGIN + LISTBOX_BORDER + get_text_ascent(MEDIUMFONT),
4368 _(column_titles[i]));
4380 void BC_ListBox::draw_toggles(int flash)
4382 for(int i = 0; i < expanders.total; i++)
4383 expanders.values[i]->draw(0);
4385 //printf("BC_ListBox::draw_toggles 1 %d\n", flash);
4386 if(flash && expanders.total)
4393 int BC_ListBox::draw_rectangle(int flash)
4395 int x1 = MIN(rect_x1, rect_x2);
4396 int x2 = MAX(rect_x1, rect_x2);
4397 int y1 = MIN(rect_y1, rect_y2);
4398 int y2 = MAX(rect_y1, rect_y2);
4400 if(x1 == x2 || y1 == y2) return 0;
4403 gui->set_color(WHITE);
4404 gui->draw_rectangle(x1, y1, x2 - x1, y2 - y1);
4416 void BC_ListBox::dump(ArrayList<BC_ListBoxItem*> *data,
4423 printf("BC_ListBox::dump 1\n");
4426 for(int i = 0; i < data[master_column].total; i++)
4428 for(int k = 0; k < indent; k++)
4430 for(int j = 0; j < columns; j++)
4432 BC_ListBoxItem *item = data[j].values[i];
4433 printf("%d,%d,%d=%s ",
4436 item->autoplace_text,
4441 if(data[master_column].values[i]->get_sublist())
4443 dump(data[master_column].values[i]->get_sublist(),
4444 data[master_column].values[i]->get_columns(),