1 #include "bcdragwindow.h"
3 #include "bclistboxitem.h"
5 #include "bcresources.h"
18 // ====================================================== scrollbars
21 BC_ListBoxYScroll::BC_ListBoxYScroll(BC_ListBox *listbox,
25 : BC_ScrollBar(listbox->get_yscroll_x(),
26 listbox->get_yscroll_y(),
28 listbox->get_yscroll_height(),
33 this->listbox = listbox;
36 BC_ListBoxYScroll::~BC_ListBoxYScroll()
40 int BC_ListBoxYScroll::handle_event()
42 listbox->set_yposition(get_value());
52 BC_ListBoxXScroll::BC_ListBoxXScroll(BC_ListBox *listbox,
56 : BC_ScrollBar(listbox->get_xscroll_x(),
57 listbox->get_xscroll_y(),
59 listbox->get_xscroll_width(),
64 this->listbox = listbox;
67 BC_ListBoxXScroll::~BC_ListBoxXScroll()
71 int BC_ListBoxXScroll::handle_event()
73 listbox->set_xposition(get_value());
84 BC_ListBoxToggle::BC_ListBoxToggle(BC_ListBox *listbox,
89 this->listbox = listbox;
93 this->value = item->get_expand();
95 state = BC_Toggle::TOGGLE_CHECKED;
97 state = BC_Toggle::TOGGLE_UP;
100 void BC_ListBoxToggle::update(BC_ListBoxItem *item,
105 this->value = item->get_expand();
115 state = TOGGLE_CHECKED;
120 state = TOGGLE_CHECKEDHI;
131 case TOGGLE_CHECKEDHI:
136 case TOGGLE_DOWN_EXIT:
144 int BC_ListBoxToggle::cursor_motion_event(int *redraw_toggles)
146 int w = listbox->toggle_images[0]->get_w();
147 int h = listbox->toggle_images[0]->get_h();
148 int cursor_inside = listbox->get_cursor_x() >= x &&
149 listbox->get_cursor_x() < x + w &&
150 listbox->get_cursor_y() >= y &&
151 listbox->get_cursor_y() < y + h;
156 case BC_ListBoxToggle::TOGGLE_UPHI:
159 state = BC_ListBoxToggle::TOGGLE_UP;
164 case BC_ListBoxToggle::TOGGLE_CHECKEDHI:
167 state = BC_ListBoxToggle::TOGGLE_CHECKED;
172 case BC_ListBoxToggle::TOGGLE_DOWN:
175 state = BC_ListBoxToggle::TOGGLE_DOWN_EXIT;
181 case BC_ListBoxToggle::TOGGLE_DOWN_EXIT:
184 state = BC_ListBoxToggle::TOGGLE_DOWN;
194 state = BC_ListBoxToggle::TOGGLE_CHECKEDHI;
196 state = BC_ListBoxToggle::TOGGLE_UPHI;
204 int BC_ListBoxToggle::cursor_leave_event(int *redraw_toggles)
207 state = BC_ListBoxToggle::TOGGLE_CHECKED;
209 state = BC_ListBoxToggle::TOGGLE_UP;
212 int BC_ListBoxToggle::button_press_event()
214 int w = listbox->toggle_images[0]->get_w();
215 int h = listbox->toggle_images[0]->get_h();
217 if(listbox->gui->get_cursor_x() >= x &&
218 listbox->gui->get_cursor_x() < x + w &&
219 listbox->gui->get_cursor_y() >= y &&
220 listbox->gui->get_cursor_y() < y + h)
222 state = BC_ListBoxToggle::TOGGLE_DOWN;
228 int BC_ListBoxToggle::button_release_event(int *redraw_toggles)
233 case BC_ListBoxToggle::TOGGLE_DOWN:
236 state = BC_ListBoxToggle::TOGGLE_CHECKEDHI;
238 state = BC_ListBoxToggle::TOGGLE_UPHI;
239 listbox->expand_item(item, value);
243 case BC_ListBoxToggle::TOGGLE_DOWN_EXIT:
245 state = BC_ListBoxToggle::TOGGLE_CHECKED;
247 state = BC_ListBoxToggle::TOGGLE_UP;
255 void BC_ListBoxToggle::draw(int flash)
259 int image_number = 0;
260 int w = listbox->toggle_images[0]->get_w();
261 int h = listbox->toggle_images[0]->get_h();
265 case BC_ListBoxToggle::TOGGLE_UP: image_number = 0; break;
266 case BC_ListBoxToggle::TOGGLE_UPHI: image_number = 1; break;
267 case BC_ListBoxToggle::TOGGLE_CHECKED: image_number = 2; break;
268 case BC_ListBoxToggle::TOGGLE_DOWN: image_number = 3; break;
269 case BC_ListBoxToggle::TOGGLE_CHECKEDHI: image_number = 4; break;
270 case BC_ListBoxToggle::TOGGLE_DOWN_EXIT:
278 //printf("BC_ListBoxToggle::draw 1 %d\n", state);
279 listbox->gui->draw_pixmap(listbox->toggle_images[image_number],
286 listbox->gui->flash(x, y, w, h);
287 listbox->gui->flush();
305 // ====================================================== box
307 BC_ListBox::BC_ListBox(int x,
312 ArrayList<BC_ListBoxItem*> *data,
313 char **column_titles,
321 : BC_SubWindow(x, y, w, h, -1)
323 justify = LISTBOX_RIGHT;
325 highlighted_item = -1;
326 highlighted_title = -1;
327 highlighted_division = -1;
331 current_cursor = ARROW_CURSOR;
342 selection_number1 = -1;
343 selection_number2 = -1;
347 current_operation = NO_OPERATION;
348 button_highlighted = 0;
352 list_highlighted = 0;
354 allow_drag_scroll = 1;
360 allow_drag_column = 0;
367 for(int i = 0; i < 3; i++)
370 for(int i = 0; i < 4; i++)
371 button_images[i] = 0;
373 for(int i = 0; i < 5; i++)
374 toggle_images[i] = 0;
379 //printf("BC_ListBox::BC_ListBox 1\n");
381 this->columns = columns;
382 this->yposition = yposition;
383 this->is_popup = is_popup;
384 this->display_format = display_format;
385 this->selection_mode = selection_mode;
386 this->icon_position = icon_position;
387 this->allow_drag = allow_drag;
388 this->column_titles = 0;
389 this->column_width = 0;
390 //printf("BC_ListBox::BC_ListBox 1\n");
392 if((!column_titles && column_width) ||
393 (column_titles && !column_width))
395 printf("BC_ListBox::BC_ListBox either column_titles or column_widths == NULL but not both.\n");
397 //printf("BC_ListBox::BC_ListBox 2 %p %p\n", column_titles, column_width);
398 set_columns(column_titles,
402 //printf("BC_ListBox::BC_ListBox 3\n");
404 drag_icon_vframe = 0;
405 drag_column_icon_vframe = 0;
409 // reset the search engine
410 //printf("BC_ListBox::BC_ListBox 4\n");
412 //printf("BC_ListBox::BC_ListBox 5\n");
415 BC_ListBox::~BC_ListBox()
417 expanders.remove_all_objects();
418 if(bg_surface) delete bg_surface;
419 if(bg_pixmap) delete bg_pixmap;
420 if(xscrollbar) delete xscrollbar;
421 if(yscrollbar) delete yscrollbar;
422 for(int i = 0; i < 3; i++)
423 if(column_bg[i]) delete column_bg[i];
424 for(int i = 0; i < 4; i++)
425 if(button_images[i]) delete button_images[i];
426 for(int i = 0; i < 5; i++)
427 if(toggle_images[i]) delete toggle_images[i];
428 if(column_sort_up) delete column_sort_up;
429 if(column_sort_dn) delete column_sort_dn;
432 if(drag_popup) delete drag_popup;
435 int BC_ListBox::enable()
442 int BC_ListBox::disable()
449 void BC_ListBox::reset_query()
451 query[0] = 0; // reset query
454 int BC_ListBox::evaluate_query(int list_item, char *string)
456 return(strcmp(string, data[search_column].values[list_item]->text) <= 0 &&
457 data[search_column].values[list_item]->searchable);
460 int BC_ListBox::query_list()
462 if(query[0] == 0) return 0;
466 int selection_changed = 0;
467 int prev_selection = -1;
468 for(int i = 0; !done && i < data[0].total; i++)
470 if(evaluate_query(i, query))
480 for(int i = 0; i < data[0].total; i++)
482 for(int j = 0; j < columns; j++)
484 if(data[j].values[i]->selected) prev_selection = i;
485 data[j].values[i]->selected = 0;
490 if(prev_selection != result)
491 selection_changed = 1;
492 for(int j = 0; j < columns; j++)
494 data[j].values[result]->selected = 1;
496 center_selection(result);
499 return selection_changed;
502 void BC_ListBox::init_column_width()
504 if(!column_width && data)
507 for(int i = 0; i < data[0].total; i++)
509 w = get_text_width(MEDIUMFONT, data[0].values[i]->get_text()) + 2 * LISTBOX_MARGIN;
510 if(w > widest) widest = w;
512 default_column_width[0] = widest;
516 int BC_ListBox::initialize()
520 for(int i = 0; i < 4; i++)
522 button_images[i] = new BC_Pixmap(parent_window,
523 BC_WindowBase::get_resources()->listbox_button[i],
526 w = button_images[0]->get_w();
527 h = button_images[0]->get_h();
530 current_operation = NO_OPERATION;
535 current_operation = NO_OPERATION;
538 for(int i = 0; i < 3; i++)
540 column_bg[i] = new BC_Pixmap(parent_window,
541 get_resources()->listbox_column[i],
544 for(int i = 0; i < 5; i++)
546 toggle_images[i] = new BC_Pixmap(parent_window,
547 get_resources()->listbox_expand[i],
551 column_sort_up = new BC_Pixmap(parent_window,
552 BC_WindowBase::get_resources()->listbox_up,
554 column_sort_dn = new BC_Pixmap(parent_window,
555 BC_WindowBase::get_resources()->listbox_dn,
558 //printf("BC_ListBox::initialize 10\n");
559 drag_icon_vframe = get_resources()->type_to_icon[ICON_UNKNOWN];
560 drag_column_icon_vframe = get_resources()->type_to_icon[ICON_COLUMN];
561 // = new BC_Pixmap(parent_window,
562 // get_resources()->type_to_icon[ICON_UNKNOWN],
564 // drag_column_icon = new BC_Pixmap(parent_window,
565 // get_resources()->type_to_icon[ICON_COLUMN],
567 BC_SubWindow::initialize();
571 if(top_level->get_resources()->listbox_bg)
572 bg_pixmap = new BC_Pixmap(this,
573 get_resources()->listbox_bg,
581 void BC_ListBox::deactivate_selection()
583 current_operation = NO_OPERATION;
586 int BC_ListBox::draw_button()
588 // Draw the button for a popup listbox
591 int image_number = 0;
593 draw_top_background(parent_window, 0, 0, w, h);
595 if(button_highlighted)
597 if(current_operation == BUTTON_DN)
603 pixmap->draw_pixmap(button_images[image_number],
615 int BC_ListBox::calculate_item_coords()
623 // Change the display_format to get the right item dimensions for both
625 int display_format_temp = display_format;
628 // Scan the first column for lowest y coord of all text
629 // and lowest right x and y coord for all icons which aren't auto placable
630 calculate_last_coords_recursive(data,
637 // Reset last column width. It's recalculated based on text width.
639 calculate_item_coords_recursive(data,
648 display_format = display_format_temp;
653 void BC_ListBox::calculate_last_coords_recursive(
654 ArrayList<BC_ListBoxItem*> *data,
661 for(int i = 0; i < data[0].total; i++)
663 int current_text_y = 0;
664 int current_icon_x = 0;
665 int current_icon_y = 0;
666 BC_ListBoxItem *item = data[0].values[i];
669 if(!item->autoplace_text)
671 // Lowest text coordinate
672 display_format = LISTBOX_TEXT;
673 current_text_y = item->text_y +
674 get_text_height(MEDIUMFONT);
675 if(current_text_y > *next_text_y)
676 *next_text_y = current_text_y;
678 // Add sublist depth if it is expanded
679 if(item->get_sublist() &&
680 item->get_columns() &&
683 calculate_last_coords_recursive(item->get_sublist(),
692 // Get next_icon coordinate
695 BC_ListBoxItem *item = data[master_column].values[i];
696 if(!item->autoplace_icon)
698 display_format = LISTBOX_ICONS;
699 // Lowest right icon coordinate.
700 current_icon_x = item->icon_x;
701 if(current_icon_x > *icon_x) *icon_x = current_icon_x;
702 if(current_icon_x + get_item_w(item) > *next_icon_x)
703 *next_icon_x = current_icon_x + get_item_w(item);
705 current_icon_y = item->icon_y + get_item_h(item);
706 if(current_icon_y > *next_icon_y)
707 *next_icon_y = current_icon_y;
714 void BC_ListBox::calculate_item_coords_recursive(
715 ArrayList<BC_ListBoxItem*> *data,
725 // Set up items which need autoplacement.
726 // Should fill icons down and then across
727 for(int i = 0; i < data[0].total; i++)
729 // Don't increase y unless the row requires autoplacing.
730 int total_autoplaced_columns = 0;
732 // Set up icons in first column
735 BC_ListBoxItem *item = data[master_column].values[i];
736 if(item->autoplace_icon)
738 // 1 column only if icons are used
739 display_format = LISTBOX_ICONS;
742 if(*next_icon_y + get_item_h(item) >= get_h() &&
745 *icon_x = *next_icon_x;
749 if(*icon_x + get_item_w(item) > *next_icon_x)
750 *next_icon_x = *icon_x + get_item_w(item);
753 item->set_icon_x(*icon_x);
754 item->set_icon_y(*next_icon_y);
756 *next_icon_y += get_item_h(item);
764 for(int j = 0; j < columns; j++)
766 BC_ListBoxItem *item = data[j].values[i];
767 if(item->autoplace_text)
769 display_format = LISTBOX_TEXT;
770 item->set_text_x(next_text_x);
771 item->set_text_y(*next_text_y);
773 // printf("BC_ListBox::calculate_item_coords_recursive %p %d %d %d %d %s \n",
774 // item->get_sublist(),
775 // item->get_columns(),
776 // item->get_expand(),
779 // item->get_text());
780 // Increment position of next column
782 next_text_x += (column_width ?
784 default_column_width[j]);
786 // Set last column width based on text width
788 int new_w = get_item_w(item);
790 int *previous_w = (column_width ?
792 &default_column_width[j]);
793 if(new_w > *previous_w)
795 //printf("BC_ListBox::calculate_item_coords_recursive 1 %d\n", new_w);
797 total_autoplaced_columns++;
801 // Increase the text vertical position
802 if(total_autoplaced_columns)
804 display_format = LISTBOX_TEXT;
805 *next_text_y += get_text_height(MEDIUMFONT);
809 BC_ListBoxItem *item = data[master_column].values[i];
810 if(item->get_sublist() &&
811 item->get_columns() &&
814 calculate_item_coords_recursive(
825 void BC_ListBox::set_justify(int value)
827 this->justify = value;
830 void BC_ListBox::set_allow_drag_column(int value)
832 this->allow_drag_column = value;
835 void BC_ListBox::set_process_drag(int value)
837 this->process_drag = value;
840 void BC_ListBox::set_master_column(int value, int redraw)
842 this->master_column = value;
849 void BC_ListBox::set_search_column(int value)
851 this->search_column = value;
854 int BC_ListBox::get_sort_column()
859 void BC_ListBox::set_sort_column(int value, int redraw)
868 int BC_ListBox::get_sort_order()
873 void BC_ListBox::set_sort_order(int value, int redraw)
886 int BC_ListBox::get_display_mode()
888 return display_format;
891 int BC_ListBox::get_yposition()
896 int BC_ListBox::get_xposition()
901 int BC_ListBox::get_highlighted_item()
903 return highlighted_item;
907 int BC_ListBox::get_item_x(BC_ListBoxItem *item)
909 if(display_format == LISTBOX_TEXT)
910 return item->text_x - xposition + 2;
912 return item->icon_x - xposition + 2;
915 int BC_ListBox::get_item_y(BC_ListBoxItem *item)
918 if(display_format == LISTBOX_TEXT)
919 result = item->text_y - yposition + title_h + 2;
921 result = item->icon_y - yposition + title_h + 2;
925 int BC_ListBox::get_item_w(BC_ListBoxItem *item)
927 if(display_format == LISTBOX_ICONS)
930 get_icon_mask(item, x, y, w, h);
932 get_text_mask(item, x, y, w, h);
935 if(icon_position == ICON_LEFT)
936 return icon_w + text_w;
938 return (icon_w > text_w) ? icon_w : text_w;
942 return get_text_width(MEDIUMFONT, item->text) + 2 * LISTBOX_MARGIN;
946 int BC_ListBox::get_item_h(BC_ListBoxItem *item)
948 if(display_format == LISTBOX_ICONS)
951 get_icon_mask(item, x, y, w, h);
953 get_text_mask(item, x, y, w, h);
956 if(icon_position == ICON_LEFT)
957 return (icon_h > text_h) ? icon_h : text_h;
959 return icon_h + text_h;
963 return get_text_height(MEDIUMFONT);
969 int BC_ListBox::get_icon_w(BC_ListBoxItem *item)
971 BC_Pixmap *icon = item->icon;
972 if(icon) return icon->get_w();
976 int BC_ListBox::get_icon_h(BC_ListBoxItem *item)
978 BC_Pixmap *icon = item->icon;
979 if(icon) return icon->get_h();
983 int BC_ListBox::get_items_width()
987 if(display_format == LISTBOX_ICONS)
989 for(int i = 0; i < columns; i++)
991 for(int j = 0; j < data[i].total; j++)
994 BC_ListBoxItem *item = data[i].values[j];
997 get_icon_mask(item, x, y, w, h);
998 if(x1 + w > widest) widest = x1 + w;
1000 if(display_format == LISTBOX_ICONS && icon_position == ICON_LEFT)
1003 get_text_mask(item, x, y, w, h);
1004 if(x1 + w > widest) widest = x1 + w;
1009 if(display_format == LISTBOX_TEXT)
1011 return get_column_offset(columns);
1016 int BC_ListBox::get_items_height(ArrayList<BC_ListBoxItem*> *data,
1033 for(int j = 0; j < (data ? data[master_column].total : 0); j++)
1036 BC_ListBoxItem *item = data[master_column].values[j];
1038 if(display_format == LISTBOX_ICONS)
1040 get_icon_mask(item, x, y, w, h);
1041 if(y + h + yposition > highest) highest = y + h + yposition;
1043 get_text_mask(item, x, y, w, h);
1044 if(y + h + yposition > highest) highest = y + h + yposition;
1048 get_text_mask(item, x, y, w, h);
1052 // Descend into sublist
1053 if(item->get_sublist() &&
1056 get_items_height(item->get_sublist(),
1057 item->get_columns(),
1062 if(display_format == LISTBOX_TEXT && top_level)
1064 highest = LISTBOX_MARGIN + *result;
1071 int BC_ListBox::set_yposition(int position, int draw_items)
1073 this->yposition = position;
1076 this->draw_items(1);
1081 int BC_ListBox::set_xposition(int position)
1083 this->xposition = position;
1088 void BC_ListBox::expand_item(BC_ListBoxItem *item, int expand)
1092 item->expand = expand;
1093 // Collapse sublists if this is collapsed to make it easier to calculate
1095 if(item->get_sublist())
1096 collapse_recursive(item->get_sublist(), master_column);
1099 // Set everything for autoplacement
1101 set_autoplacement(data, 0, 1);
1107 void BC_ListBox::collapse_recursive(ArrayList<BC_ListBoxItem*> *data,
1110 for(int i = 0; i < data[master_column].total; i++)
1112 BC_ListBoxItem *item = data[master_column].values[i];
1113 if(item->get_sublist() && item->expand)
1116 collapse_recursive(item->get_sublist(), master_column);
1121 void BC_ListBox::set_autoplacement(ArrayList<BC_ListBoxItem*> *data,
1125 for(int i = 0; i < data[0].total; i++)
1127 for(int j = 0; j < columns; j++)
1129 if(do_icons) data[j].values[i]->autoplace_icon = 1;
1130 if(do_text) data[j].values[i]->autoplace_text = 1;
1133 BC_ListBoxItem *item = data[master_column].values[i];
1134 if(item->get_sublist())
1136 set_autoplacement(item->get_sublist(), do_icons, do_text);
1143 int BC_ListBox::get_w()
1146 return BCPOPUPLISTBOX_W;
1151 int BC_ListBox::get_h()
1154 return BCPOPUPLISTBOX_H;
1159 int BC_ListBox::get_yscroll_x()
1162 return popup_w - get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w();
1166 get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w();
1169 int BC_ListBox::get_yscroll_y()
1177 int BC_ListBox::get_yscroll_height()
1179 return popup_h - (need_xscroll ?
1180 get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h() :
1184 int BC_ListBox::get_xscroll_x()
1192 int BC_ListBox::get_xscroll_y()
1196 get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h();
1200 get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h();
1203 int BC_ListBox::get_xscroll_width()
1205 return popup_w - (need_yscroll ?
1206 get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w() :
1210 int BC_ListBox::get_column_offset(int column)
1216 column_width[--column] :
1217 default_column_width[--column];
1222 void BC_ListBox::column_width_boundaries()
1226 for(int i = 0; i < columns; i++)
1228 if(column_width[i] < MIN_COLUMN_WIDTH) column_width[i] = MIN_COLUMN_WIDTH;
1233 for(int i = 0; i < columns; i++)
1235 if(default_column_width[i] < MIN_COLUMN_WIDTH) default_column_width[i] = MIN_COLUMN_WIDTH;
1240 int BC_ListBox::get_column_width(int column, int clamp_right)
1242 if(column < columns - 1 || !clamp_right)
1243 return column_width ?
1244 column_width[column] :
1245 default_column_width[column];
1249 get_column_offset(column);
1252 int BC_ListBox::get_icon_mask(BC_ListBoxItem *item,
1258 if(display_format == LISTBOX_ICONS)
1260 x = get_item_x(item);
1261 y = get_item_y(item);
1262 w = get_icon_w(item) + ICON_MARGIN * 2;
1263 h = get_icon_h(item) + ICON_MARGIN * 2;
1266 if(display_format == LISTBOX_TEXT)
1273 int BC_ListBox::get_text_mask(BC_ListBoxItem *item,
1279 x = get_item_x(item);
1280 y = get_item_y(item);
1282 if(display_format == LISTBOX_ICONS)
1284 if(icon_position == ICON_LEFT)
1286 x += get_icon_w(item) + ICON_MARGIN * 2;
1287 y += get_icon_h(item) - get_text_height(MEDIUMFONT);
1291 y += get_icon_h(item) + ICON_MARGIN;
1294 w = get_text_width(MEDIUMFONT, item->text) + ICON_MARGIN * 2;
1295 h = get_text_height(MEDIUMFONT) + ICON_MARGIN * 2;
1298 if(display_format == LISTBOX_TEXT)
1300 w = get_text_width(MEDIUMFONT, item->text) + LISTBOX_MARGIN * 2;
1301 h = get_text_height(MEDIUMFONT);
1306 int BC_ListBox::get_item_highlight(ArrayList<BC_ListBoxItem*> *data,
1310 BC_Resources *resources = get_resources();
1311 if(data[column].values[item]->selected)
1312 return resources->listbox_selected;
1314 if(highlighted_item >= 0 &&
1315 highlighted_ptr == data[master_column].values[item])
1316 return resources->listbox_highlighted;
1318 return resources->listbox_inactive;
1321 int BC_ListBox::get_item_color(ArrayList<BC_ListBoxItem*> *data,
1325 int color = data[column].values[item]->color;
1326 if(color == -1) color = get_resources()->listbox_text;
1327 if(get_item_highlight(data, column, item) == color)
1333 int BC_ListBox::get_from_column()
1335 return dragged_title;
1338 int BC_ListBox::get_to_column()
1340 return highlighted_title;
1344 BC_ListBoxItem* BC_ListBox::get_selection(int column,
1345 int selection_number)
1347 return get_selection_recursive(data,
1352 BC_ListBoxItem* BC_ListBox::get_selection_recursive(
1353 ArrayList<BC_ListBoxItem*> *data,
1355 int selection_number)
1359 for(int i = 0; i < data[master_column].total; i++)
1361 BC_ListBoxItem *item = data[master_column].values[i];
1365 if(selection_number < 0)
1368 return data[column].values[i];
1372 if(item->get_sublist())
1374 BC_ListBoxItem *result = get_selection_recursive(item->get_sublist(),
1377 if(result) return result;
1384 int BC_ListBox::get_selection_number(int column,
1385 int selection_number)
1387 return get_selection_number_recursive(data,
1392 int BC_ListBox::get_selection_number_recursive(
1393 ArrayList<BC_ListBoxItem*> *data,
1395 int selection_number,
1400 if(!counter) counter = &temp;
1402 for(int i = 0; i < data[master_column].total; i++)
1405 BC_ListBoxItem *item = data[master_column].values[i];
1409 if(selection_number < 0)
1414 if(item->get_sublist())
1416 int result = get_selection_number_recursive(
1417 item->get_sublist(),
1421 if(result >= 0) return result;
1428 int BC_ListBox::set_selection_mode(int mode)
1430 this->selection_mode = mode;
1434 void BC_ListBox::delete_columns()
1438 for(int i = 0; i < columns; i++)
1440 delete [] column_titles[i];
1442 delete [] column_titles;
1445 if(column_width) delete [] column_width;
1451 // Need to copy titles so EDL can change
1452 void BC_ListBox::set_columns(char **column_titles,
1456 if((!column_titles && column_width) ||
1457 (column_titles && !column_width))
1459 printf("BC_ListBox::set_columns either column_titles or column_width == NULL but not both.\n");
1468 this->column_titles = new char*[columns];
1469 for(int i = 0; i < columns; i++)
1471 this->column_titles[i] = new char[strlen(column_titles[i]) + 1];
1472 strcpy(this->column_titles[i], column_titles[i]);
1478 this->column_width = new int[columns];
1479 for(int i = 0; i < columns; i++)
1481 this->column_width[i] = column_width[i];
1485 this->columns = columns;
1490 int BC_ListBox::update(ArrayList<BC_ListBoxItem*> *data,
1491 char **column_titles,
1496 int highlighted_number,
1497 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;
2751 // Pressed in button
2752 if(is_popup && top_level->event_win == win)
2754 current_operation = BUTTON_DN;
2758 if(!active && !disabled)
2760 top_level->deactivate();
2767 // Pressed in scrollbar
2768 if((xscrollbar && top_level->event_win == xscrollbar->win) ||
2769 (yscrollbar && top_level->event_win == yscrollbar->win))
2775 if(gui && top_level->event_win == gui->win)
2777 // Activate list items
2780 top_level->deactivate();
2784 // Wheel mouse pressed
2785 if(get_buttonpress() == 4)
2787 if(current_operation == NO_OPERATION)
2789 current_operation = WHEEL;
2792 set_yposition(yposition - gui->get_h() / 10, 0);
2794 update_scrollbars();
2795 highlighted_ptr = 0;
2796 highlighted_item = get_cursor_item(data,
2797 top_level->cursor_x,
2798 top_level->cursor_y,
2806 if(get_buttonpress() == 5)
2808 if(current_operation == NO_OPERATION)
2810 current_operation = WHEEL;
2813 set_yposition(yposition + gui->get_h() / 10, 0);
2815 update_scrollbars();
2816 highlighted_ptr = 0;
2817 highlighted_item = get_cursor_item(data,
2818 top_level->cursor_x,
2819 top_level->cursor_y,
2827 // Pressed over column title division
2828 if(test_column_divisions(gui->get_cursor_x(),
2829 gui->get_cursor_y(),
2832 current_operation = DRAG_DIVISION;
2836 // Pressed in column title
2837 if(test_column_titles(gui->get_cursor_x(), gui->get_cursor_y()))
2839 current_operation = COLUMN_DN;
2840 button_highlighted = 0;
2841 list_highlighted = 1;
2846 // Pressed in expander
2847 if(test_expanders())
2849 current_operation = EXPAND_DN;
2850 // Need to redraw items because of alpha
2855 // Pressed over item
2856 if((selection_number = get_cursor_item(data,
2857 gui->get_cursor_x(),
2858 gui->get_cursor_y(),
2859 ¤t_item)) >= 0)
2861 // Get item button was pressed over
2862 selection_number2 = selection_number1;
2863 selection_number1 = selection_number;
2865 selection_start = -1;
2869 // Multiple item selection is possible
2870 if(selection_mode == LISTBOX_MULTIPLE &&
2871 (ctrl_down() || shift_down()))
2873 // Expand text selection.
2874 // Fill items between selected region and current item.
2875 if(shift_down() && display_format == LISTBOX_TEXT)
2877 // Get first item selected
2878 selection_start = get_first_selection(data);
2879 // Get last item selected
2880 selection_end = get_last_selection(data);
2881 // Get center of selected region
2882 if(selection_end > selection_start)
2884 selection_center = (selection_end + selection_start) >> 1;
2888 selection_center = selection_number;
2892 // Deselect everything.
2893 set_all_selected(data, 0);
2894 // Select just the items
2895 expand_selection(1, selection_number);
2899 // Toggle a single item on or off
2901 toggle_item_selection(data, selection_number);
2902 new_value = current_item->selected;
2906 // Select single item
2908 if(!current_item->selected)
2910 set_all_selected(data, 0);
2919 current_operation = SELECT;
2920 highlighted_item = selection_number;
2921 highlighted_ptr = current_item;
2922 button_highlighted = 0;
2923 list_highlighted = 1;
2926 do_selection_change = 1;
2931 // Pressed over nothing. Start rectangle selection.
2933 if(get_buttonpress() == 1 &&
2934 selection_mode == LISTBOX_MULTIPLE)
2938 // Deselect all and redraw if anything was selected
2939 if(get_selection_number(0, 0) >= 0)
2941 set_all_selected(data, 0);
2943 do_selection_change = 1;
2949 // Promote selections to protect from a rectangle selection
2950 promote_selections(data, 1, 2);
2953 // Start rectangle selection
2954 current_operation = SELECT_RECT;
2955 rect_x1 = rect_x2 = get_cursor_x();
2956 rect_y1 = rect_y2 = get_cursor_y();
2964 if(is_popup && active)
2971 if(do_selection_change) selection_changed();
2976 int BC_ListBox::button_release_event()
2979 int cursor_x, cursor_y;
2983 //printf("BC_ListBox::button_release_event 1 %d\n", current_operation);
2984 switch(current_operation)
2987 current_operation = NO_OPERATION;
2992 current_operation = NO_OPERATION;
2996 // Release item selection
2997 case BUTTON_DOWN_SELECT:
2999 //printf("BC_ListBox::button_release_event 10\n");
3000 unset_repeat(get_resources()->scroll_repeat);
3001 current_operation = NO_OPERATION;
3002 translate_coordinates(top_level->event_win,
3004 gui->get_cursor_x(),
3005 gui->get_cursor_y(),
3011 get_cursor_item(data, cursor_x, cursor_y);
3012 //printf("BC_ListBox::button_release_event %d %d\n", selection_number2, selection_number1);
3017 if(selection_number >= 0)
3023 // Second button release outside button
3024 if(button_releases > 1)
3031 if(top_level->get_double_click() &&
3032 selection_number2 == selection_number1 &&
3033 selection_number2 >= 0 &&
3034 selection_number1 >= 0)
3044 unset_repeat(get_resources()->scroll_repeat);
3047 // Demote selections from rectangle selection
3048 promote_selections(data, 2, 1);
3051 // Hide rectangle overlay
3053 current_operation = NO_OPERATION;
3057 // Release popup button
3060 current_operation = NO_OPERATION;
3064 // Second button release inside button
3065 if(button_releases > 1)
3073 current_operation = NO_OPERATION;
3074 // Update the sort column and the sort order for the user only if the existing
3075 // sort column is valid.
3076 if(sort_column >= 0)
3078 // Invert order only if column is the same
3079 if(highlighted_title == sort_column)
3081 (sort_order == SORT_ASCENDING) ?
3084 // Set the new sort column
3085 sort_column = highlighted_title;
3086 if(!sort_order_event())
3092 // Sorting not enabled. Redraw the title state.
3101 int redraw_toggles = 0;
3102 for(int i = 0; i < expanders.total && !result; i++)
3104 if(expanders.values[i]->button_release_event(&redraw_toggles))
3109 // Need to redraw items because of alpha
3110 if(redraw_toggles) draw_items(1);
3111 current_operation = NO_OPERATION;
3116 // Can't default to NO_OPERATION because it may be used in a drag event.
3121 if(do_event) handle_event();
3126 int BC_ListBox::get_title_h()
3128 if(display_format == LISTBOX_TEXT)
3129 return column_titles ? column_bg[0]->get_h() : 0;
3134 void BC_ListBox::reset_cursor(int new_cursor)
3138 if(gui->get_cursor() != new_cursor)
3140 gui->set_cursor(new_cursor);
3144 if(get_cursor() != new_cursor)
3146 set_cursor(new_cursor);
3150 int BC_ListBox::test_column_divisions(int cursor_x, int cursor_y, int &new_cursor)
3155 cursor_y < get_title_h() &&
3157 cursor_x < gui->get_w())
3159 for(int i = 1; i < columns; i++)
3161 if(cursor_x >= -xposition + get_column_offset(i) - 5 &&
3162 cursor_x < -xposition + get_column_offset(i) +
3163 get_resources()->listbox_title_hotspot)
3165 highlighted_item = -1;
3166 highlighted_ptr = 0;
3167 highlighted_division = i;
3168 highlighted_title = -1;
3169 list_highlighted = 1;
3170 new_cursor = HSEPARATE_CURSOR;
3175 highlighted_division = -1;
3179 int BC_ListBox::test_column_titles(int cursor_x, int cursor_y)
3184 cursor_y < get_title_h() &&
3186 cursor_x < gui->get_w())
3188 for(int i = 0; i < columns; i++)
3190 if(cursor_x >= -xposition + get_column_offset(i) &&
3191 (cursor_x < -xposition + get_column_offset(i + 1) ||
3194 highlighted_item = -1;
3195 highlighted_ptr = 0;
3196 highlighted_division = -1;
3197 highlighted_title = i;
3198 list_highlighted = 1;
3203 highlighted_title = -1;
3207 int BC_ListBox::test_expanders()
3209 for(int i = 0; i < expanders.total; i++)
3211 if(expanders.values[i]->button_press_event())
3213 current_operation = EXPAND_DN;
3221 int BC_ListBox::cursor_motion_event()
3223 int redraw = 0, result = 0;
3224 int new_cursor = ARROW_CURSOR;
3226 selection_number = -1;
3229 switch(current_operation)
3232 // Button pressed and slid off button
3233 if(!cursor_inside())
3235 current_operation = BUTTON_DOWN_SELECT;
3243 int new_w = get_cursor_x() +
3245 get_column_offset(highlighted_division - 1);
3246 new_cursor = HSEPARATE_CURSOR;
3250 column_width[highlighted_division - 1] = new_w;
3254 default_column_width[highlighted_division - 1] = new_w;
3257 column_width_boundaries();
3259 // Force update of coords
3260 set_autoplacement(data, 0, 1);
3261 column_resize_event();
3265 update_scrollbars();
3272 if(test_drag_scroll(get_cursor_x(), get_cursor_y()))
3274 set_repeat(get_resources()->scroll_repeat);
3277 int old_x1 = MIN(rect_x1, rect_x2);
3278 int old_x2 = MAX(rect_x1, rect_x2);
3279 int old_y1 = MIN(rect_y1, rect_y2);
3280 int old_y2 = MAX(rect_y1, rect_y2);
3282 int new_rect_x2 = get_cursor_x();
3283 int new_rect_y2 = get_cursor_y();
3285 int x1 = MIN(rect_x1, new_rect_x2);
3286 int x2 = MAX(rect_x1, new_rect_x2);
3287 int y1 = MIN(rect_y1, new_rect_y2);
3288 int y2 = MAX(rect_y1, new_rect_y2);
3290 // Adjust rectangle coverage
3298 redraw = select_rectangle(data,
3310 rect_x2 = get_cursor_x();
3311 rect_y2 = get_cursor_y();
3316 update_scrollbars();
3317 selection_changed();
3329 int old_highlighted_item = highlighted_item;
3330 int old_highlighted_title = highlighted_title;
3331 BC_ListBoxItem *old_highlighted_ptr = highlighted_ptr;
3333 if(test_drag_scroll(get_cursor_x(),
3336 set_repeat(get_resources()->scroll_repeat);
3340 highlighted_item = selection_number = get_cursor_item(data,
3346 // Deselect all items and select just the one we're over
3347 if(selection_number >= 0 &&
3351 selection_mode == LISTBOX_SINGLE))
3353 redraw = update_selection(data, selection_number);
3356 if(selection_mode == LISTBOX_MULTIPLE &&
3357 (shift_down() || ctrl_down()))
3358 // Expand multiple selection
3360 // Expand selected region in text mode centered around initial range
3361 if(display_format == LISTBOX_TEXT && shift_down())
3363 // Deselect everything.
3364 set_all_selected(data, 0);
3366 // Select just the items
3367 redraw = expand_selection(0, selection_number);
3370 // Set the one item we're over to the selection value determined in
3371 // button_press_event.
3379 if(highlighted_item != old_highlighted_item)
3383 update_scrollbars();
3384 //printf("BC_ListBox::cursor_motion_event %d %d\n", highlighted_item, old_highlighted_item);
3385 selection_changed();
3390 case BUTTON_DOWN_SELECT:
3391 // Went back into button area
3394 current_operation = BUTTON_DN;
3399 // Went into item area
3402 int cursor_x = 0, cursor_y = 0;
3403 translate_coordinates(top_level->event_win,
3405 top_level->cursor_x,
3406 top_level->cursor_y,
3409 int old_highlighted_item = highlighted_item;
3410 highlighted_item = selection_number = get_cursor_item(data,
3415 if(highlighted_item != old_highlighted_item)
3417 update_selection(data, selection_number);
3419 selection_changed();
3426 int redraw_toggles = 0;
3427 for(int i = 0; i < expanders.total && !result; i++)
3429 result = expanders.values[i]->cursor_motion_event(
3434 // Need to redraw items because of the alpha
3442 int cursor_x = get_cursor_x(), cursor_y = get_cursor_y();
3443 if(gui && top_level->event_win == gui->win)
3445 int old_highlighted_title = highlighted_title;
3446 int old_list_highlighted = list_highlighted;
3447 int old_highlighted_division = highlighted_division;
3448 int old_highlighted_item = highlighted_item;
3449 int redraw_titles = 0;
3450 int redraw_border = 0;
3451 int redraw_items = 0;
3452 int redraw_toggles = 0;
3456 // Test if cursor moved over a title division
3457 test_column_divisions(cursor_x, cursor_y, new_cursor);
3459 // Test if cursor moved over a title
3460 if(highlighted_division < 0)
3462 test_column_titles(cursor_x, cursor_y);
3465 // Test if cursor moved over expander
3466 if(highlighted_division < 0 &&
3467 highlighted_title < 0 &&
3468 display_format == LISTBOX_TEXT)
3470 for(int i = 0; i < expanders.total; i++)
3472 expanders.values[i]->cursor_motion_event(
3475 //printf("BC_ListBox::cursor_motion_event %d\n", redraw_toggles);
3478 // Test if cursor moved over an item
3479 if(highlighted_division < 0 &&
3480 highlighted_title < 0)
3482 highlighted_item = get_cursor_item(data,
3489 // Clear title highlighting if moved over division
3490 if(old_highlighted_title != highlighted_title)
3495 // Highlight list border
3496 if(old_list_highlighted != list_highlighted)
3501 // Moved out of item area
3502 if(old_highlighted_item != highlighted_item)
3507 //printf("BC_ListBox::cursor_motion_event 1 %d\n", highlighted_item);
3509 // Change cursor to title division adjustment
3510 reset_cursor(new_cursor);
3537 if(!result && list_highlighted)
3539 list_highlighted = 0;
3540 highlighted_item = -1;
3541 highlighted_ptr = 0;
3542 highlighted_title = -1;
3543 highlighted_division = -1;
3555 int BC_ListBox::drag_start_event()
3557 switch(current_operation)
3561 gui->is_event_win() &&
3564 BC_ListBoxItem *item_return = 0;
3565 selection_number = get_cursor_item(data,
3566 top_level->cursor_x,
3567 top_level->cursor_y,
3570 if(selection_number >= 0)
3573 if (item_return->icon_vframe)
3575 drag_popup = new BC_DragWindow(this,
3576 item_return->icon_vframe,
3577 get_abs_cursor_x(0) - item_return->icon_vframe->get_w() / 2,
3578 get_abs_cursor_y(0) - item_return->icon_vframe->get_h() / 2);
3581 // this probably works not!
3582 if (item_return->icon)
3583 drag_popup = new BC_DragWindow(this,
3585 get_abs_cursor_x(0) - item_return->icon->get_w() / 2,
3586 get_abs_cursor_y(0) - item_return->icon->get_h() / 2);
3588 drag_popup = new BC_DragWindow(this,
3590 get_abs_cursor_x(0) - drag_icon_vframe->get_w() / 2,
3591 get_abs_cursor_y(0) - drag_icon_vframe->get_h() / 2);
3592 current_operation = DRAG_ITEM;
3599 if(gui && gui->is_event_win() && allow_drag_column)
3601 drag_popup = new BC_DragWindow(this,
3602 drag_column_icon_vframe,
3603 get_abs_cursor_x(0) - drag_column_icon_vframe->get_w() / 2,
3604 get_abs_cursor_y(0) - drag_column_icon_vframe->get_h() / 2);
3605 dragged_title = highlighted_title;
3606 current_operation = COLUMN_DRAG;
3616 int BC_ListBox::drag_motion_event()
3618 //printf("BC_ListBox::drag_motion_event 1 %d\n", current_operation);
3619 switch(current_operation)
3625 int new_highlighted_item = -1;
3626 BC_ListBoxItem *new_highlighted_ptr = 0;
3627 int new_highlight = new_highlighted_item = get_cursor_item(data,
3628 top_level->cursor_x,
3629 top_level->cursor_y,
3630 &new_highlighted_ptr);
3632 if(new_highlighted_item != highlighted_item)
3637 // Always update highlighted value for drag_stop
3638 highlighted_item = new_highlighted_item;
3639 highlighted_ptr = new_highlighted_ptr;
3640 //printf("BC_ListBox::drag_motion_event 1 %p\n", highlighted_ptr);
3645 update_scrollbars();
3648 return drag_popup->cursor_motion_event();
3654 int old_highlighted_title = highlighted_title;
3655 test_column_titles(get_cursor_x(), get_cursor_y());
3656 if(old_highlighted_title != highlighted_title)
3660 return drag_popup->cursor_motion_event();
3667 int BC_ListBox::drag_stop_event()
3669 switch(current_operation)
3672 // Inside window boundary
3673 if(top_level->cursor_x > 0 &&
3674 top_level->cursor_x < gui->get_w() - drag_popup->get_w() / 2 &&
3675 top_level->cursor_y > 0 &&
3676 top_level->cursor_y < gui->get_h() - drag_popup->get_h() / 2)
3681 if(display_format == LISTBOX_ICONS)
3683 reposition_item(data,
3685 top_level->cursor_x +
3686 drag_popup->get_offset_x() -
3690 top_level->cursor_y +
3691 drag_popup->get_offset_y() -
3701 int destination = highlighted_item = item_to_index(data,
3703 //printf("BC_ListBox::drag_stop_event 1 %p %d\n", highlighted_ptr, destination);
3705 // Move selected items from data to temporary
3706 ArrayList<BC_ListBoxItem*> *src_items =
3707 new ArrayList<BC_ListBoxItem*>[columns];
3709 move_selection(src_items, data);
3711 // Insert items from temporary to data
3717 delete [] src_items;
3718 set_autoplacement(data, 0, 1);
3725 drag_popup->drag_failure_event();
3729 current_operation = NO_OPERATION;
3735 if(dragged_title != highlighted_title)
3737 if(highlighted_title >= 0)
3739 if(!move_column_event()) draw_titles(1);
3742 drag_popup->drag_failure_event();
3744 current_operation = NO_OPERATION;
3753 BC_DragWindow* BC_ListBox::get_drag_popup()
3758 int BC_ListBox::translation_event()
3762 int new_x = gui->get_x() +
3763 (top_level->last_translate_x -
3765 top_level->get_resources()->get_left_border());
3766 int new_y = gui->get_y() +
3767 (top_level->last_translate_y -
3769 top_level->get_resources()->get_top_border());
3771 gui->reposition_window(new_x, new_y);
3777 int BC_ListBox::reposition_window(int x, int y, int w, int h)
3781 if(w != -1) popup_w = w;
3782 if(h != -1) popup_h = h;
3783 //printf("BC_ListBox::reposition_window %d %d\n", popup_w, popup_h);
3787 if(w != -1) popup_w = w;
3788 if(h != -1) popup_h = h;
3790 xscrollbar->reposition_window(get_xscroll_x(),
3792 get_xscroll_width());
3794 yscrollbar->reposition_window(get_yscroll_x(),
3796 get_yscroll_height());
3801 BC_WindowBase::reposition_window(x, y, w, h);
3807 int BC_ListBox::deactivate()
3818 highlighted_item = -1;
3819 highlighted_ptr = 0;
3821 top_level->active_subwindow = 0;
3826 int BC_ListBox::activate()
3830 top_level->active_subwindow = this;
3832 button_releases = 0;
3839 y = get_y() + get_h();
3840 if(justify == LISTBOX_RIGHT)
3842 x = get_x() - popup_w + get_w();
3850 XTranslateCoordinates(top_level->display,
3859 if(new_x < 0) new_x = 0;
3860 if(new_y + popup_h > top_level->get_root_h(0))
3861 new_y -= get_h() + popup_h;
3863 //printf("BC_ListBox::activate %d %d\n", popup_w, popup_h);
3864 add_subwindow(gui = new BC_Popup(this,
3878 int BC_ListBox::keypress_event()
3880 if(!active) return 0;
3882 int result = 0, redraw = 0, done, view_items = view_h / get_text_height(MEDIUMFONT);
3883 int new_item = -1, new_selection = 0;
3885 switch(top_level->get_keypress())
3889 top_level->deactivate();
3894 new_selection = new_item = select_previous(0);
3896 //printf("BC_ListBox::keypress_event 1 %d\n", new_item);
3899 center_selection(new_item);
3906 new_selection = new_item = select_next(0);
3910 center_selection(new_item);
3917 new_selection = new_item = select_previous(view_items - 1);
3921 center_selection(new_item);
3928 new_selection = new_item = select_next(view_items - 1);
3932 center_selection(new_item);
3953 if(top_level->get_keypress() > 30 &&
3954 top_level->get_keypress() < 127)
3956 int query_len = strlen(query);
3957 query[query_len++] = top_level->get_keypress();
3958 query[query_len] = 0;
3959 new_selection = query_list();
3962 if(top_level->get_keypress() == BACKSPACE)
3964 int query_len = strlen(query);
3965 if(query_len > 0) query[--query_len] = 0;
3966 new_selection = query_list();
3979 update_scrollbars();
3982 if(new_selection >= 0)
3984 selection_changed();
3991 BC_Pixmap* BC_ListBox::get_bg_surface()
3997 void BC_ListBox::draw_background()
3999 // White background pixmap
4000 set_color(top_level->get_resources()->listbox_inactive);
4001 draw_box(0, 0, bg_surface->get_w(), bg_surface->get_h(), bg_surface);
4003 // Optional heroine pixmap
4005 bg_surface->draw_pixmap(bg_pixmap,
4006 bg_surface->get_w() - top_level->get_resources()->listbox_bg->get_w(),
4010 void BC_ListBox::clear_listbox(int x, int y, int w, int h)
4012 gui->draw_pixmap(bg_surface,
4021 void BC_ListBox::update_format(int display_format, int redraw)
4023 this->display_format = display_format;
4026 if(gui) draw_items(1);
4030 int BC_ListBox::get_format()
4032 return display_format;
4037 int BC_ListBox::draw_items(int flash)
4041 BC_Resources *resources = get_resources();
4043 //dump(data, columns);
4045 // Calculate items width
4046 calculate_item_coords();
4049 // Create and destroy scrollbars as needed
4054 // draw_background();
4057 if(display_format == LISTBOX_ICONS)
4059 clear_listbox(2, 2 + title_h, view_w, view_h);
4061 set_font(MEDIUMFONT);
4062 for(int i = 0; i < data[master_column].total; i++)
4064 BC_ListBoxItem *item = data[master_column].values[i];
4065 if(get_item_x(item) >= -get_item_w(item) &&
4066 get_item_x(item) < view_w &&
4067 get_item_y(item) >= -get_item_h(item) + title_h &&
4068 get_item_y(item) < view_h + title_h)
4070 int item_color = get_item_highlight(data, 0, i);
4071 int icon_x, icon_y, icon_w, icon_h;
4072 int text_x, text_y, text_w, text_h;
4075 get_icon_mask(item, icon_x, icon_y, icon_w, icon_h);
4076 get_text_mask(item, text_x, text_y, text_w, text_h);
4079 if(item_color != resources->listbox_inactive)
4081 gui->set_color(BLACK);
4082 gui->draw_rectangle(icon_x, icon_y, icon_w, icon_h);
4083 gui->set_color(item_color);
4084 gui->draw_box(icon_x + 1, icon_y + 1, icon_w - 2, icon_h - 2);
4085 gui->set_color(BLACK);
4086 gui->draw_rectangle(text_x, text_y, text_w, text_h);
4087 gui->set_color(item_color);
4088 gui->draw_box(text_x + 1, text_y + 1, text_w - 2, text_h - 2);
4090 if(icon_position == ICON_LEFT)
4091 gui->draw_box(text_x - 1, text_y + 1, 2, text_h - 2);
4093 if(icon_position == ICON_TOP)
4094 gui->draw_line(text_x + 1, text_y, text_x + icon_w - 2, text_y);
4095 if(text_x + text_w < icon_x + icon_w)
4097 gui->set_color(BLACK);
4098 gui->draw_line(text_x + text_w,
4106 gui->set_color(get_item_color(data, 0, i));
4108 gui->pixmap->draw_pixmap(item->icon,
4109 icon_x + ICON_MARGIN,
4110 icon_y + ICON_MARGIN);
4111 gui->draw_text(text_x + ICON_MARGIN,
4112 text_y + ICON_MARGIN + get_text_ascent(MEDIUMFONT),
4119 if(display_format == LISTBOX_TEXT)
4121 // Draw one column at a time so text overruns don't go into the next column
4122 // clear column backgrounds
4123 int current_toggle = 0;
4124 for(int j = 0; j < columns; j++)
4126 clear_listbox(LISTBOX_BORDER + get_column_offset(j) - xposition,
4127 LISTBOX_BORDER + title_h,
4128 get_column_width(j, 1),
4131 // Draw rows in the column recursively
4132 draw_text_recursive(data, j, 0, ¤t_toggle);
4135 // Delete excess expanders
4136 while(expanders.total > current_toggle)
4138 expanders.remove_object();
4142 // Draw titles on top of rows for superposition effect
4145 // Clear garbage from bottom right corner
4146 if(xscrollbar && yscrollbar && is_popup)
4148 gui->draw_top_background(parent_window,
4149 popup_w - get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w(),
4150 popup_h - get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h(),
4151 get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w(),
4152 get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h());
4159 if(current_operation == SELECT_RECT)
4173 void BC_ListBox::draw_text_recursive(ArrayList<BC_ListBoxItem*> *data,
4176 int *current_toggle)
4181 BC_Resources *resources = get_resources();
4183 set_font(MEDIUMFONT);
4186 // Search for a branch and make room for toggle if there is one
4189 for(int i = 0; i < data[column].total; i++)
4191 if(data[column].values[i]->get_sublist())
4193 subindent = BC_WindowBase::get_resources()->listbox_expand[0]->get_w();
4199 for(int i = 0; i < data[column].total; i++)
4202 BC_ListBoxItem *item = data[column].values[i];
4203 BC_ListBoxItem *first_item = data[master_column].values[i];
4205 if(get_item_y(item) >= -get_item_h(item) + title_h &&
4206 get_item_y(item) < view_h + title_h)
4208 int row_color = get_item_highlight(data, 0, i);
4209 int x, y, w, h, column_width;
4211 get_text_mask(item, x, y, w, h);
4212 column_width = get_column_width(column, 1);
4213 if(x + column_width > view_w + LISTBOX_BORDER * 2)
4214 column_width = view_w + LISTBOX_BORDER * 2 - x;
4216 if(row_color != resources->listbox_inactive)
4218 gui->set_color(row_color);
4223 gui->set_color(BLACK);
4226 x + column_width - 1,
4229 y + get_text_height(MEDIUMFONT),
4230 x + column_width - 1,
4231 y + get_text_height(MEDIUMFONT));
4234 gui->set_color(get_item_color(data, column, i));
4237 // Indent only applies to first column
4242 (column == 0 ? indent + subindent : 0),
4243 y + get_text_ascent(MEDIUMFONT),
4249 item->get_sublist() &&
4250 item->get_columns())
4252 // Create new expander
4253 if(*current_toggle >= expanders.total)
4255 BC_ListBoxToggle *toggle =
4256 new BC_ListBoxToggle(this,
4258 x + LISTBOX_BORDER + LISTBOX_MARGIN + indent,
4261 expanders.append(toggle);
4264 // Reposition existing expander
4266 BC_ListBoxToggle *toggle = expanders.values[*current_toggle];
4267 //printf("BC_ListBox::draw_text_recursive 1 %d\n", *current_toggle);
4268 toggle->update(item,
4269 x + LISTBOX_BORDER + LISTBOX_MARGIN + indent,
4273 (*current_toggle)++;
4280 // Descend into sublist
4281 if(first_item->get_expand())
4283 draw_text_recursive(first_item->get_sublist(),
4285 indent + LISTBOX_INDENT,
4295 int BC_ListBox::draw_border(int flash)
4297 BC_Resources *resources = top_level->get_resources();
4298 gui->draw_3d_border(0,
4300 view_w + LISTBOX_BORDER * 2,
4301 view_h + title_h + LISTBOX_BORDER * 2,
4302 resources->listbox_border1,
4304 resources->listbox_border2_hi :
4305 resources->listbox_border2,
4307 resources->listbox_border3_hi :
4308 resources->listbox_border3,
4309 resources->listbox_border4);
4319 int BC_ListBox::draw_titles(int flash)
4321 if(column_titles && display_format == LISTBOX_TEXT)
4323 //printf("BC_ListBox::draw_titles 1 %d\n", highlighted_title);
4324 for(int i = 0; i < columns; i++)
4328 // Column title background
4329 int image_number = 0;
4330 if(i == highlighted_title)
4333 if(current_operation == COLUMN_DN)
4337 int column_offset = get_column_offset(i) - xposition + LISTBOX_BORDER;
4338 int column_width = get_column_width(i, 1);
4339 gui->draw_3segmenth(get_column_offset(i) - xposition + LISTBOX_BORDER,
4341 get_column_width(i, 1),
4342 column_bg[image_number]);
4344 // Column title sort order
4345 if(i == sort_column)
4348 if(sort_order == SORT_ASCENDING)
4349 src = column_sort_dn;
4351 src = column_sort_up;
4353 int x = column_offset +
4356 if(x > items_w) x = items_w;
4357 x -= 5 + src->get_w();
4358 gui->draw_pixmap(src,
4360 title_h / 2 - src->get_h() / 2 + LISTBOX_BORDER);
4364 int x = -xposition +
4365 get_column_offset(i) +
4368 x += get_resources()->listbox_title_margin;
4370 gui->set_color(get_resources()->listbox_title_color);
4372 LISTBOX_MARGIN + LISTBOX_BORDER + get_text_ascent(MEDIUMFONT),
4373 _(column_titles[i]));
4385 void BC_ListBox::draw_toggles(int flash)
4387 for(int i = 0; i < expanders.total; i++)
4388 expanders.values[i]->draw(0);
4390 //printf("BC_ListBox::draw_toggles 1 %d\n", flash);
4391 if(flash && expanders.total)
4398 int BC_ListBox::draw_rectangle(int flash)
4400 int x1 = MIN(rect_x1, rect_x2);
4401 int x2 = MAX(rect_x1, rect_x2);
4402 int y1 = MIN(rect_y1, rect_y2);
4403 int y2 = MAX(rect_y1, rect_y2);
4405 if(x1 == x2 || y1 == y2) return 0;
4408 gui->set_color(WHITE);
4409 gui->draw_rectangle(x1, y1, x2 - x1, y2 - y1);
4421 void BC_ListBox::dump(ArrayList<BC_ListBoxItem*> *data,
4428 printf("BC_ListBox::dump 1\n");
4431 for(int i = 0; i < data[master_column].total; i++)
4433 for(int k = 0; k < indent; k++)
4435 for(int j = 0; j < columns; j++)
4437 BC_ListBoxItem *item = data[j].values[i];
4438 printf("%d,%d,%d=%s ",
4441 item->autoplace_text,
4446 if(data[master_column].values[i]->get_sublist())
4448 dump(data[master_column].values[i]->get_sublist(),
4449 data[master_column].values[i]->get_columns(),