1 #include "bcdragwindow.h"
3 #include "bclistboxitem.h"
5 #include "bcresources.h"
16 // ====================================================== scrollbars
19 BC_ListBoxYScroll::BC_ListBoxYScroll(BC_ListBox *listbox,
23 : BC_ScrollBar(listbox->get_yscroll_x(),
24 listbox->get_yscroll_y(),
26 listbox->get_yscroll_height(),
31 this->listbox = listbox;
34 BC_ListBoxYScroll::~BC_ListBoxYScroll()
38 int BC_ListBoxYScroll::handle_event()
40 listbox->set_yposition(get_value());
50 BC_ListBoxXScroll::BC_ListBoxXScroll(BC_ListBox *listbox,
54 : BC_ScrollBar(listbox->get_xscroll_x(),
55 listbox->get_xscroll_y(),
57 listbox->get_xscroll_width(),
62 this->listbox = listbox;
65 BC_ListBoxXScroll::~BC_ListBoxXScroll()
69 int BC_ListBoxXScroll::handle_event()
71 listbox->set_xposition(get_value());
82 BC_ListBoxToggle::BC_ListBoxToggle(BC_ListBox *listbox,
87 this->listbox = listbox;
91 this->value = item->get_expand();
93 state = BC_Toggle::TOGGLE_CHECKED;
95 state = BC_Toggle::TOGGLE_UP;
98 void BC_ListBoxToggle::update(BC_ListBoxItem *item,
103 this->value = item->get_expand();
113 state = TOGGLE_CHECKED;
118 state = TOGGLE_CHECKEDHI;
129 case TOGGLE_CHECKEDHI:
134 case TOGGLE_DOWN_EXIT:
142 int BC_ListBoxToggle::cursor_motion_event(int *redraw_toggles)
144 int w = listbox->toggle_images[0]->get_w();
145 int h = listbox->toggle_images[0]->get_h();
146 int cursor_inside = listbox->get_cursor_x() >= x &&
147 listbox->get_cursor_x() < x + w &&
148 listbox->get_cursor_y() >= y &&
149 listbox->get_cursor_y() < y + h;
154 case BC_ListBoxToggle::TOGGLE_UPHI:
157 state = BC_ListBoxToggle::TOGGLE_UP;
162 case BC_ListBoxToggle::TOGGLE_CHECKEDHI:
165 state = BC_ListBoxToggle::TOGGLE_CHECKED;
170 case BC_ListBoxToggle::TOGGLE_DOWN:
173 state = BC_ListBoxToggle::TOGGLE_DOWN_EXIT;
179 case BC_ListBoxToggle::TOGGLE_DOWN_EXIT:
182 state = BC_ListBoxToggle::TOGGLE_DOWN;
192 state = BC_ListBoxToggle::TOGGLE_CHECKEDHI;
194 state = BC_ListBoxToggle::TOGGLE_UPHI;
202 int BC_ListBoxToggle::cursor_leave_event(int *redraw_toggles)
205 state = BC_ListBoxToggle::TOGGLE_CHECKED;
207 state = BC_ListBoxToggle::TOGGLE_UP;
210 int BC_ListBoxToggle::button_press_event()
212 int w = listbox->toggle_images[0]->get_w();
213 int h = listbox->toggle_images[0]->get_h();
215 if(listbox->gui->get_cursor_x() >= x &&
216 listbox->gui->get_cursor_x() < x + w &&
217 listbox->gui->get_cursor_y() >= y &&
218 listbox->gui->get_cursor_y() < y + h)
220 state = BC_ListBoxToggle::TOGGLE_DOWN;
226 int BC_ListBoxToggle::button_release_event(int *redraw_toggles)
231 case BC_ListBoxToggle::TOGGLE_DOWN:
234 state = BC_ListBoxToggle::TOGGLE_CHECKEDHI;
236 state = BC_ListBoxToggle::TOGGLE_UPHI;
237 listbox->expand_item(item, value);
241 case BC_ListBoxToggle::TOGGLE_DOWN_EXIT:
243 state = BC_ListBoxToggle::TOGGLE_CHECKED;
245 state = BC_ListBoxToggle::TOGGLE_UP;
253 void BC_ListBoxToggle::draw(int flash)
257 int image_number = 0;
258 int w = listbox->toggle_images[0]->get_w();
259 int h = listbox->toggle_images[0]->get_h();
263 case BC_ListBoxToggle::TOGGLE_UP: image_number = 0; break;
264 case BC_ListBoxToggle::TOGGLE_UPHI: image_number = 1; break;
265 case BC_ListBoxToggle::TOGGLE_CHECKED: image_number = 2; break;
266 case BC_ListBoxToggle::TOGGLE_DOWN: image_number = 3; break;
267 case BC_ListBoxToggle::TOGGLE_CHECKEDHI: image_number = 4; break;
268 case BC_ListBoxToggle::TOGGLE_DOWN_EXIT:
276 //printf("BC_ListBoxToggle::draw 1 %d\n", state);
277 listbox->gui->draw_pixmap(listbox->toggle_images[image_number],
284 listbox->gui->flash(x, y, w, h);
285 listbox->gui->flush();
303 // ====================================================== box
305 BC_ListBox::BC_ListBox(int x,
310 ArrayList<BC_ListBoxItem*> *data,
311 char **column_titles,
319 : BC_SubWindow(x, y, w, h, -1)
323 highlighted_item = -1;
324 highlighted_title = -1;
325 highlighted_division = -1;
329 current_cursor = ARROW_CURSOR;
340 selection_number1 = -1;
341 selection_number2 = -1;
345 current_operation = NO_OPERATION;
346 button_highlighted = 0;
347 list_highlighted = 0;
349 allow_drag_scroll = 1;
355 allow_drag_column = 0;
362 for(int i = 0; i < 3; i++)
364 button_images[i] = 0;
367 for(int i = 0; i < 5; i++)
368 toggle_images[i] = 0;
373 //printf("BC_ListBox::BC_ListBox 1\n");
375 this->columns = columns;
376 this->yposition = yposition;
377 this->is_popup = is_popup;
378 this->display_format = display_format;
379 this->selection_mode = selection_mode;
380 this->icon_position = icon_position;
381 this->allow_drag = allow_drag;
382 this->column_titles = 0;
383 this->column_width = 0;
384 //printf("BC_ListBox::BC_ListBox 1\n");
386 if((!column_titles && column_width) ||
387 (column_titles && !column_width))
389 printf("BC_ListBox::BC_ListBox either column_titles or column_widths == NULL but not both.\n");
391 //printf("BC_ListBox::BC_ListBox 2 %p %p\n", column_titles, column_width);
392 set_columns(column_titles,
396 //printf("BC_ListBox::BC_ListBox 3\n");
398 drag_icon_vframe = 0;
399 drag_column_icon_vframe = 0;
403 // reset the search engine
404 //printf("BC_ListBox::BC_ListBox 4\n");
406 //printf("BC_ListBox::BC_ListBox 5\n");
409 BC_ListBox::~BC_ListBox()
411 expanders.remove_all_objects();
412 if(bg_surface) delete bg_surface;
413 if(bg_pixmap) delete bg_pixmap;
414 if(xscrollbar) delete xscrollbar;
415 if(yscrollbar) delete yscrollbar;
416 for(int i = 0; i < 3; i++)
418 if(button_images[i]) delete button_images[i];
419 if(column_bg[i]) delete column_bg[i];
421 for(int i = 0; i < 5; i++)
422 if(toggle_images[i]) delete toggle_images[i];
423 if(column_sort_up) delete column_sort_up;
424 if(column_sort_dn) delete column_sort_dn;
427 if(drag_popup) delete drag_popup;
430 void BC_ListBox::reset_query()
432 query[0] = 0; // reset query
435 int BC_ListBox::evaluate_query(int list_item, char *string)
437 return(strcmp(string, data[search_column].values[list_item]->text) <= 0 &&
438 data[search_column].values[list_item]->searchable);
441 int BC_ListBox::query_list()
443 if(query[0] == 0) return 0;
447 int selection_changed = 0;
448 int prev_selection = -1;
449 for(int i = 0; !done && i < data[0].total; i++)
451 if(evaluate_query(i, query))
461 for(int i = 0; i < data[0].total; i++)
463 for(int j = 0; j < columns; j++)
465 if(data[j].values[i]->selected) prev_selection = i;
466 data[j].values[i]->selected = 0;
471 if(prev_selection != result)
472 selection_changed = 1;
473 for(int j = 0; j < columns; j++)
475 data[j].values[result]->selected = 1;
477 center_selection(result);
480 return selection_changed;
483 void BC_ListBox::init_column_width()
485 if(!column_width && data)
488 for(int i = 0; i < data[0].total; i++)
490 w = get_text_width(MEDIUMFONT, data[0].values[i]->get_text()) + 2 * LISTBOX_MARGIN;
491 if(w > widest) widest = w;
493 default_column_width[0] = widest;
497 int BC_ListBox::initialize()
501 for(int i = 0; i < 3; i++)
503 button_images[i] = new BC_Pixmap(parent_window,
504 BC_WindowBase::get_resources()->listbox_button[i],
507 w = button_images[0]->get_w();
508 h = button_images[0]->get_h();
511 current_operation = NO_OPERATION;
516 current_operation = NO_OPERATION;
519 for(int i = 0; i < 3; i++)
521 column_bg[i] = new BC_Pixmap(parent_window,
522 get_resources()->listbox_column[i],
525 for(int i = 0; i < 5; i++)
527 toggle_images[i] = new BC_Pixmap(parent_window,
528 get_resources()->listbox_expand[i],
532 column_sort_up = new BC_Pixmap(parent_window,
533 BC_WindowBase::get_resources()->listbox_up,
535 column_sort_dn = new BC_Pixmap(parent_window,
536 BC_WindowBase::get_resources()->listbox_dn,
539 //printf("BC_ListBox::initialize 10\n");
540 drag_icon_vframe = get_resources()->type_to_icon[ICON_UNKNOWN];
541 drag_column_icon_vframe = get_resources()->type_to_icon[ICON_COLUMN];
542 // = new BC_Pixmap(parent_window,
543 // get_resources()->type_to_icon[ICON_UNKNOWN],
545 // drag_column_icon = new BC_Pixmap(parent_window,
546 // get_resources()->type_to_icon[ICON_COLUMN],
548 BC_SubWindow::initialize();
552 if(top_level->get_resources()->listbox_bg)
553 bg_pixmap = new BC_Pixmap(this,
554 get_resources()->listbox_bg,
562 void BC_ListBox::deactivate_selection()
564 current_operation = NO_OPERATION;
567 int BC_ListBox::draw_button()
569 // Draw the button for a popup listbox
572 int image_number = 0;
574 draw_top_background(parent_window, 0, 0, w, h);
576 if(button_highlighted)
578 if(current_operation == BUTTON_DN)
582 button_images[image_number]->write_drawable(pixmap,
594 int BC_ListBox::calculate_item_coords()
602 // Change the display_format to get the right item dimensions for both
604 int display_format_temp = display_format;
607 // Scan the first column for lowest y coord of all text
608 // and lowest right x and y coord for all icons which aren't auto placable
609 calculate_last_coords_recursive(data,
616 // Reset last column width. It's recalculated based on text width.
618 calculate_item_coords_recursive(data,
627 display_format = display_format_temp;
632 void BC_ListBox::calculate_last_coords_recursive(
633 ArrayList<BC_ListBoxItem*> *data,
640 for(int i = 0; i < data[0].total; i++)
642 int current_text_y = 0;
643 int current_icon_x = 0;
644 int current_icon_y = 0;
645 BC_ListBoxItem *item = data[0].values[i];
648 if(!item->autoplace_text)
650 // Lowest text coordinate
651 display_format = LISTBOX_TEXT;
652 current_text_y = item->text_y +
653 get_text_height(MEDIUMFONT);
654 if(current_text_y > *next_text_y)
655 *next_text_y = current_text_y;
657 // Add sublist depth if it is expanded
658 if(item->get_sublist() &&
659 item->get_columns() &&
662 calculate_last_coords_recursive(item->get_sublist(),
671 // Get next_icon coordinate
674 BC_ListBoxItem *item = data[master_column].values[i];
675 if(!item->autoplace_icon)
677 display_format = LISTBOX_ICONS;
678 // Lowest right icon coordinate.
679 current_icon_x = item->icon_x;
680 if(current_icon_x > *icon_x) *icon_x = current_icon_x;
681 if(current_icon_x + get_item_w(item) > *next_icon_x)
682 *next_icon_x = current_icon_x + get_item_w(item);
684 current_icon_y = item->icon_y + get_item_h(item);
685 if(current_icon_y > *next_icon_y)
686 *next_icon_y = current_icon_y;
693 void BC_ListBox::calculate_item_coords_recursive(
694 ArrayList<BC_ListBoxItem*> *data,
704 // Set up items which need autoplacement.
705 // Should fill icons down and then across
706 for(int i = 0; i < data[0].total; i++)
708 // Don't increase y unless the row requires autoplacing.
709 int total_autoplaced_columns = 0;
711 // Set up icons in first column
714 BC_ListBoxItem *item = data[master_column].values[i];
715 if(item->autoplace_icon)
717 // 1 column only if icons are used
718 display_format = LISTBOX_ICONS;
721 if(*next_icon_y + get_item_h(item) >= get_h() &&
724 *icon_x = *next_icon_x;
728 if(*icon_x + get_item_w(item) > *next_icon_x)
729 *next_icon_x = *icon_x + get_item_w(item);
732 item->set_icon_x(*icon_x);
733 item->set_icon_y(*next_icon_y);
735 *next_icon_y += get_item_h(item);
743 for(int j = 0; j < columns; j++)
745 BC_ListBoxItem *item = data[j].values[i];
746 if(item->autoplace_text)
748 display_format = LISTBOX_TEXT;
749 item->set_text_x(next_text_x);
750 item->set_text_y(*next_text_y);
752 // printf("BC_ListBox::calculate_item_coords_recursive %p %d %d %d %d %s \n",
753 // item->get_sublist(),
754 // item->get_columns(),
755 // item->get_expand(),
758 // item->get_text());
759 // Increment position of next column
761 next_text_x += (column_width ?
763 default_column_width[j]);
765 // Set last column width based on text width
767 int new_w = get_item_w(item);
769 int *previous_w = (column_width ?
771 &default_column_width[j]);
772 if(new_w > *previous_w)
774 //printf("BC_ListBox::calculate_item_coords_recursive 1 %d\n", new_w);
776 total_autoplaced_columns++;
780 // Increase the text vertical position
781 if(total_autoplaced_columns)
783 display_format = LISTBOX_TEXT;
784 *next_text_y += get_text_height(MEDIUMFONT);
788 BC_ListBoxItem *item = data[master_column].values[i];
789 if(item->get_sublist() &&
790 item->get_columns() &&
793 calculate_item_coords_recursive(
806 void BC_ListBox::set_allow_drag_column(int value)
808 this->allow_drag_column = value;
811 void BC_ListBox::set_process_drag(int value)
813 this->process_drag = value;
816 void BC_ListBox::set_master_column(int value, int redraw)
818 this->master_column = value;
825 void BC_ListBox::set_search_column(int value)
827 this->search_column = value;
830 int BC_ListBox::get_sort_column()
835 void BC_ListBox::set_sort_column(int value, int redraw)
844 int BC_ListBox::get_sort_order()
849 void BC_ListBox::set_sort_order(int value, int redraw)
862 int BC_ListBox::get_display_mode()
864 return display_format;
867 int BC_ListBox::get_yposition()
872 int BC_ListBox::get_xposition()
877 int BC_ListBox::get_highlighted_item()
879 return highlighted_item;
883 int BC_ListBox::get_item_x(BC_ListBoxItem *item)
885 if(display_format == LISTBOX_TEXT)
886 return item->text_x - xposition + 2;
888 return item->icon_x - xposition + 2;
891 int BC_ListBox::get_item_y(BC_ListBoxItem *item)
894 if(display_format == LISTBOX_TEXT)
895 result = item->text_y - yposition + title_h + 2;
897 result = item->icon_y - yposition + title_h + 2;
901 int BC_ListBox::get_item_w(BC_ListBoxItem *item)
903 if(display_format == LISTBOX_ICONS)
906 get_icon_mask(item, x, y, w, h);
908 get_text_mask(item, x, y, w, h);
911 if(icon_position == ICON_LEFT)
912 return icon_w + text_w;
914 return (icon_w > text_w) ? icon_w : text_w;
918 return get_text_width(MEDIUMFONT, item->text) + 2 * LISTBOX_MARGIN;
922 int BC_ListBox::get_item_h(BC_ListBoxItem *item)
924 if(display_format == LISTBOX_ICONS)
927 get_icon_mask(item, x, y, w, h);
929 get_text_mask(item, x, y, w, h);
932 if(icon_position == ICON_LEFT)
933 return (icon_h > text_h) ? icon_h : text_h;
935 return icon_h + text_h;
939 return get_text_height(MEDIUMFONT);
945 int BC_ListBox::get_icon_w(BC_ListBoxItem *item)
947 BC_Pixmap *icon = item->icon;
948 if(icon) return icon->get_w();
952 int BC_ListBox::get_icon_h(BC_ListBoxItem *item)
954 BC_Pixmap *icon = item->icon;
955 if(icon) return icon->get_h();
959 int BC_ListBox::get_items_width()
963 if(display_format == LISTBOX_ICONS)
965 for(int i = 0; i < columns; i++)
967 for(int j = 0; j < data[i].total; j++)
970 BC_ListBoxItem *item = data[i].values[j];
973 get_icon_mask(item, x, y, w, h);
974 if(x1 + w > widest) widest = x1 + w;
976 if(display_format == LISTBOX_ICONS && icon_position == ICON_LEFT)
979 get_text_mask(item, x, y, w, h);
980 if(x1 + w > widest) widest = x1 + w;
985 if(display_format == LISTBOX_TEXT)
987 return get_column_offset(columns);
992 int BC_ListBox::get_items_height(ArrayList<BC_ListBoxItem*> *data,
1009 for(int j = 0; j < (data ? data[master_column].total : 0); j++)
1012 BC_ListBoxItem *item = data[master_column].values[j];
1014 if(display_format == LISTBOX_ICONS)
1016 get_icon_mask(item, x, y, w, h);
1017 if(y + h + yposition > highest) highest = y + h + yposition;
1019 get_text_mask(item, x, y, w, h);
1020 if(y + h + yposition > highest) highest = y + h + yposition;
1024 get_text_mask(item, x, y, w, h);
1028 // Descend into sublist
1029 if(item->get_sublist() &&
1032 get_items_height(item->get_sublist(),
1033 item->get_columns(),
1038 if(display_format == LISTBOX_TEXT && top_level)
1040 highest = LISTBOX_MARGIN + *result;
1047 int BC_ListBox::set_yposition(int position, int draw_items)
1049 this->yposition = position;
1052 this->draw_items(1);
1057 int BC_ListBox::set_xposition(int position)
1059 this->xposition = position;
1064 void BC_ListBox::expand_item(BC_ListBoxItem *item, int expand)
1068 item->expand = expand;
1069 // Collapse sublists if this is collapsed to make it easier to calculate
1071 if(item->get_sublist())
1072 collapse_recursive(item->get_sublist(), master_column);
1075 // Set everything for autoplacement
1077 set_autoplacement(data, 0, 1);
1083 void BC_ListBox::collapse_recursive(ArrayList<BC_ListBoxItem*> *data,
1086 for(int i = 0; i < data[master_column].total; i++)
1088 BC_ListBoxItem *item = data[master_column].values[i];
1089 if(item->get_sublist() && item->expand)
1092 collapse_recursive(item->get_sublist(), master_column);
1097 void BC_ListBox::set_autoplacement(ArrayList<BC_ListBoxItem*> *data,
1101 for(int i = 0; i < data[0].total; i++)
1103 for(int j = 0; j < columns; j++)
1105 if(do_icons) data[j].values[i]->autoplace_icon = 1;
1106 if(do_text) data[j].values[i]->autoplace_text = 1;
1109 BC_ListBoxItem *item = data[master_column].values[i];
1110 if(item->get_sublist())
1112 set_autoplacement(item->get_sublist(), do_icons, do_text);
1119 int BC_ListBox::get_w()
1122 return BCPOPUPLISTBOX_W;
1127 int BC_ListBox::get_h()
1130 return BCPOPUPLISTBOX_H;
1135 int BC_ListBox::get_yscroll_x()
1138 return popup_w - get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w();
1142 get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w();
1145 int BC_ListBox::get_yscroll_y()
1153 int BC_ListBox::get_yscroll_height()
1155 return popup_h - (need_xscroll ?
1156 get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h() :
1160 int BC_ListBox::get_xscroll_x()
1168 int BC_ListBox::get_xscroll_y()
1172 get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h();
1176 get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h();
1179 int BC_ListBox::get_xscroll_width()
1181 return popup_w - (need_yscroll ?
1182 get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w() :
1186 int BC_ListBox::get_column_offset(int column)
1192 column_width[--column] :
1193 default_column_width[--column];
1198 void BC_ListBox::column_width_boundaries()
1202 for(int i = 0; i < columns; i++)
1204 if(column_width[i] < MIN_COLUMN_WIDTH) column_width[i] = MIN_COLUMN_WIDTH;
1209 for(int i = 0; i < columns; i++)
1211 if(default_column_width[i] < MIN_COLUMN_WIDTH) default_column_width[i] = MIN_COLUMN_WIDTH;
1216 int BC_ListBox::get_column_width(int column, int clamp_right)
1218 if(column < columns - 1 || !clamp_right)
1219 return column_width ?
1220 column_width[column] :
1221 default_column_width[column];
1225 get_column_offset(column);
1228 int BC_ListBox::get_icon_mask(BC_ListBoxItem *item,
1234 if(display_format == LISTBOX_ICONS)
1236 x = get_item_x(item);
1237 y = get_item_y(item);
1238 w = get_icon_w(item) + ICON_MARGIN * 2;
1239 h = get_icon_h(item) + ICON_MARGIN * 2;
1242 if(display_format == LISTBOX_TEXT)
1249 int BC_ListBox::get_text_mask(BC_ListBoxItem *item,
1255 x = get_item_x(item);
1256 y = get_item_y(item);
1258 if(display_format == LISTBOX_ICONS)
1260 if(icon_position == ICON_LEFT)
1262 x += get_icon_w(item) + ICON_MARGIN * 2;
1263 y += get_icon_h(item) - get_text_height(MEDIUMFONT);
1267 y += get_icon_h(item) + ICON_MARGIN;
1270 w = get_text_width(MEDIUMFONT, item->text) + ICON_MARGIN * 2;
1271 h = get_text_height(MEDIUMFONT) + ICON_MARGIN * 2;
1274 if(display_format == LISTBOX_TEXT)
1276 w = get_text_width(MEDIUMFONT, item->text) + LISTBOX_MARGIN * 2;
1277 h = get_text_height(MEDIUMFONT);
1282 int BC_ListBox::get_item_highlight(ArrayList<BC_ListBoxItem*> *data,
1286 if(data[column].values[item]->selected)
1289 if(highlighted_item >= 0 &&
1290 highlighted_ptr == data[master_column].values[item])
1296 int BC_ListBox::get_item_color(ArrayList<BC_ListBoxItem*> *data,
1300 int color = data[column].values[item]->color;
1301 if(get_item_highlight(data, column, item) == color)
1307 int BC_ListBox::get_from_column()
1309 return dragged_title;
1312 int BC_ListBox::get_to_column()
1314 return highlighted_title;
1318 BC_ListBoxItem* BC_ListBox::get_selection(int column,
1319 int selection_number)
1321 return get_selection_recursive(data,
1326 BC_ListBoxItem* BC_ListBox::get_selection_recursive(
1327 ArrayList<BC_ListBoxItem*> *data,
1329 int selection_number)
1333 for(int i = 0; i < data[master_column].total; i++)
1335 BC_ListBoxItem *item = data[master_column].values[i];
1339 if(selection_number < 0)
1342 return data[column].values[i];
1346 if(item->get_sublist())
1348 BC_ListBoxItem *result = get_selection_recursive(item->get_sublist(),
1351 if(result) return result;
1358 int BC_ListBox::get_selection_number(int column,
1359 int selection_number)
1361 return get_selection_number_recursive(data,
1366 int BC_ListBox::get_selection_number_recursive(
1367 ArrayList<BC_ListBoxItem*> *data,
1369 int selection_number,
1374 if(!counter) counter = &temp;
1376 for(int i = 0; i < data[master_column].total; i++)
1379 BC_ListBoxItem *item = data[master_column].values[i];
1383 if(selection_number < 0)
1388 if(item->get_sublist())
1390 int result = get_selection_number_recursive(
1391 item->get_sublist(),
1395 if(result >= 0) return result;
1402 int BC_ListBox::set_selection_mode(int mode)
1404 this->selection_mode = mode;
1408 void BC_ListBox::delete_columns()
1412 for(int i = 0; i < columns; i++)
1414 delete [] column_titles[i];
1416 delete [] column_titles;
1419 if(column_width) delete [] column_width;
1425 // Need to copy titles so EDL can change
1426 void BC_ListBox::set_columns(char **column_titles,
1430 if((!column_titles && column_width) ||
1431 (column_titles && !column_width))
1433 printf("BC_ListBox::set_columns either column_titles or column_width == NULL but not both.\n");
1442 this->column_titles = new char*[columns];
1443 for(int i = 0; i < columns; i++)
1445 this->column_titles[i] = new char[strlen(column_titles[i]) + 1];
1446 strcpy(this->column_titles[i], column_titles[i]);
1452 this->column_width = new int[columns];
1453 for(int i = 0; i < columns; i++)
1455 this->column_width[i] = column_width[i];
1459 this->columns = columns;
1464 int BC_ListBox::update(ArrayList<BC_ListBoxItem*> *data,
1465 char **column_titles,
1470 int highlighted_number,
1471 int recalc_positions,
1475 set_columns(column_titles,
1481 this->yposition = yposition;
1482 this->xposition = xposition;
1483 this->highlighted_item = highlighted_number;
1484 this->highlighted_ptr = index_to_item(data, highlighted_number, 0);
1486 if(recalc_positions)
1487 set_autoplacement(data, 1, 1);
1489 init_column_width();
1495 update_scrollbars();
1501 void BC_ListBox::center_selection()
1503 int selection = get_selection_number(0, 0);
1505 calculate_item_coords();
1506 center_selection(selection);
1513 update_scrollbars();
1517 void BC_ListBox::move_vertical(int pixels)
1521 void BC_ListBox::move_horizontal(int pixels)
1525 int BC_ListBox::select_previous(int skip,
1526 BC_ListBoxItem *selected_item,
1528 ArrayList<BC_ListBoxItem*> *data,
1534 selected_item = get_selection(0, 0);
1546 got_second = &temp3;
1551 // Scan backwards to item pointer. Then count visible items to get
1552 // destination. Repeat to get wraparound.
1555 for(int i = data[master_column].total - 1; i >= 0; i--)
1557 BC_ListBoxItem *current_item = data[master_column].values[i];
1558 if(current_item->get_sublist() &&
1559 current_item->get_expand())
1561 int result = select_previous(skip,
1564 current_item->get_sublist(),
1576 if((*counter) >= skip)
1578 for(int j = 0; j < columns; j++)
1579 data[j].values[i]->selected = 1;
1581 return item_to_index(this->data, current_item);
1586 if(current_item->selected)
1588 for(int j = 0; j < columns; j++)
1589 data[j].values[i]->selected = 0;
1596 // Hit bottom of top level without finding a selected item.
1597 if(top_level && !(*got_first)) (*got_first) = 1;
1598 }while(top_level && data[master_column].total);
1602 int BC_ListBox::select_next(int skip,
1603 BC_ListBoxItem *selected_item,
1605 ArrayList<BC_ListBoxItem*> *data,
1611 selected_item = get_selection(0, 0);
1623 got_second = &temp3;
1628 // Scan backwards to item pointer. Then count visible items to get
1629 // destination. Repeat to get wraparound.
1632 for(int i = 0; i < data[master_column].total; i++)
1634 BC_ListBoxItem *current_item = data[master_column].values[i];
1638 if((*counter) >= skip)
1640 for(int j = 0; j < columns; j++)
1641 data[j].values[i]->selected = 1;
1643 return item_to_index(this->data, current_item);
1648 if(current_item->selected)
1650 for(int j = 0; j < columns; j++)
1651 data[j].values[i]->selected = 0;
1657 if(current_item->get_sublist() &&
1658 current_item->get_expand())
1660 int result = select_next(skip,
1663 current_item->get_sublist(),
1673 // Hit bottom of top level without finding a selected item.
1674 if(top_level && !(*got_first)) (*got_first) = 1;
1675 }while(top_level && data[master_column].total);
1680 void BC_ListBox::clamp_positions()
1682 items_w = get_items_width();
1683 items_h = get_items_height(data, columns);
1685 if(yposition < 0) yposition = 0;
1687 if(yposition > items_h - view_h)
1688 yposition = items_h - view_h;
1690 if(yposition < 0) yposition = 0;
1692 if(xposition < 0) xposition = 0;
1694 if(xposition >= items_w - view_w)
1695 xposition = items_w - view_w;
1697 if(xposition < 0) xposition = 0;
1700 int BC_ListBox::center_selection(int selection,
1701 ArrayList<BC_ListBoxItem*> *data,
1705 if(!data) data = this->data;
1706 if(!counter) counter = &temp;
1708 for(int i = 0; i < data[master_column].total; i++)
1713 BC_ListBoxItem *item = data[master_column].values[i];
1714 if((*counter) == selection)
1716 BC_ListBoxItem *top_item = this->data[master_column].values[0];
1719 if(display_format == LISTBOX_ICONS)
1721 // Icon is out of window
1722 if(item->icon_y - yposition >
1723 view_h - get_text_height(MEDIUMFONT) ||
1724 item->icon_y - yposition < 0)
1726 yposition = item->icon_y - view_h / 2;
1729 if(data[master_column].values[selection]->icon_x - xposition > view_w ||
1730 data[master_column].values[selection]->icon_x - xposition < 0)
1732 xposition = item->icon_x - view_w / 2;
1736 if(display_format == LISTBOX_TEXT)
1738 // Text coordinate is out of window
1739 if(item->text_y - yposition >
1740 view_h - get_text_height(MEDIUMFONT) ||
1741 item->text_y - yposition < 0)
1743 yposition = item->text_y -
1752 if(item->get_sublist())
1754 int result = center_selection(selection,
1755 item->get_sublist(),
1757 if(result) return result;
1763 void BC_ListBox::update_scrollbars()
1765 int h_needed = items_h = get_items_height(data, columns);
1766 int w_needed = items_w = get_items_width();
1768 // if(columns > 0 && column_width)
1769 // printf("BC_ListBox::update_scrollbars 1 %d %d\n", column_width[columns - 1], w_needed);
1773 if(xposition != xscrollbar->get_value())
1774 xscrollbar->update_value(xposition);
1776 if(w_needed != xscrollbar->get_length() ||
1777 view_w != xscrollbar->get_handlelength())
1778 xscrollbar->update_length(w_needed, xposition, view_w);
1783 if(yposition != yscrollbar->get_value())
1784 yscrollbar->update_value(yposition);
1786 if(h_needed != yscrollbar->get_length() || view_h != yscrollbar->get_handlelength())
1787 yscrollbar->update_length(h_needed, yposition, view_h);
1791 int BC_ListBox::get_scrollbars()
1793 int h_needed = items_h = get_items_height(data, columns);
1794 int w_needed = items_w = get_items_width();
1798 title_h = get_title_h();
1800 view_h = popup_h - title_h - 4;
1801 view_w = popup_w - 4;
1803 // Create scrollbars as needed
1804 for(int i = 0; i < 2; i++)
1806 if(w_needed > view_w)
1811 get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h() -
1819 if(h_needed > view_h)
1823 get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w() -
1832 // Update subwindow size
1833 int new_w = popup_w;
1834 int new_h = popup_h;
1835 if(need_xscroll) new_h -= get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h();
1836 if(need_yscroll) new_w -= get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w();
1839 if(new_w != BC_WindowBase::get_w() || new_h != BC_WindowBase::get_h())
1840 gui->resize_window(new_w, new_h);
1842 BC_WindowBase *destination = (is_popup ? gui : parent_window);
1847 destination->add_subwindow(xscrollbar =
1848 new BC_ListBoxXScroll(this,
1852 xscrollbar->bound_to = this;
1856 xscrollbar->update_length(w_needed, xposition, view_w);
1857 xscrollbar->reposition_window(get_xscroll_x(),
1859 get_xscroll_width());
1864 if(xscrollbar) delete xscrollbar;
1873 destination->add_subwindow(yscrollbar =
1874 new BC_ListBoxYScroll(this,
1878 yscrollbar->bound_to = this;
1882 yscrollbar->update_length(h_needed, yposition, view_h);
1883 yscrollbar->reposition_window(get_yscroll_x(),
1885 get_yscroll_height());
1890 if(yscrollbar) delete yscrollbar;
1896 view_w + 4 != bg_surface->get_w() ||
1897 view_h + 4 != bg_surface->get_h())
1899 if(bg_surface) delete bg_surface;
1900 bg_surface = new BC_Pixmap(gui, view_w + 4, view_h + 4);
1909 void BC_ListBox::set_drag_scroll(int value)
1911 allow_drag_scroll = value;
1915 // Test for scrolling by dragging
1917 int BC_ListBox::test_drag_scroll(int cursor_x, int cursor_y)
1920 if(allow_drag_scroll ||
1921 current_operation == SELECT_RECT)
1924 int top_boundary = get_title_h();
1926 if(cursor_y < top_boundary ||
1927 cursor_y >= view_h + title_h + LISTBOX_BORDER * 2 ||
1928 cursor_x < LISTBOX_BORDER ||
1929 cursor_x >= view_w + LISTBOX_BORDER)
1937 int BC_ListBox::drag_scroll_event()
1939 int top_boundary = get_title_h();
1942 if(get_cursor_y() < top_boundary)
1944 yposition -= top_boundary - get_cursor_y();
1948 if(get_cursor_y() >= view_h + title_h + 4)
1950 yposition += get_cursor_y() - (view_h + title_h + 4);
1954 if(get_cursor_x() < 2)
1956 xposition -= 2 - get_cursor_x();
1960 if(get_cursor_x() >= view_w + 2)
1962 xposition += get_cursor_x() - (view_w + 2);
1965 if(result) clamp_positions();
1969 int BC_ListBox::rectangle_scroll_event()
1971 int old_xposition = xposition;
1972 int old_yposition = yposition;
1973 int result = drag_scroll_event();
1977 rect_x1 += old_xposition - xposition;
1978 rect_y1 += old_yposition - yposition;
1979 rect_x2 = get_cursor_x();
1980 rect_y2 = get_cursor_y();
1982 int x1 = MIN(rect_x1, rect_x2);
1983 int x2 = MAX(rect_x1, rect_x2);
1984 int y1 = MIN(rect_y1, rect_y2);
1985 int y2 = MAX(rect_y1, rect_y2);
1987 if(select_rectangle(data,
1993 selection_changed();
1998 update_scrollbars();
2003 int BC_ListBox::select_scroll_event()
2005 int result = drag_scroll_event();
2009 highlighted_item = selection_number = get_cursor_item(data,
2015 update_scrollbars();
2016 selection_changed();
2021 int BC_ListBox::select_rectangle(ArrayList<BC_ListBoxItem*> *data,
2028 for(int i = 0; i < data[master_column].total; i++)
2030 for(int j = 0; j < columns; j++)
2032 BC_ListBoxItem *item = data[j].values[i];
2033 if(display_format == LISTBOX_ICONS)
2035 int icon_x, icon_y, icon_w, icon_h;
2036 int text_x, text_y, text_w, text_h;
2037 get_icon_mask(item, icon_x, icon_y, icon_w, icon_h);
2038 get_text_mask(item, text_x, text_y, text_w, text_h);
2040 if((x2 >= icon_x && x1 < icon_x + icon_w &&
2041 y2 >= icon_y && y1 < icon_y + icon_h) ||
2042 (x2 >= text_x && x1 < text_x + text_w &&
2043 y2 >= text_y && y1 < text_y + text_h))
2064 gui->get_w() - get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w() :
2067 y1 < gui->get_h() &&
2068 y2 >= get_item_y(item) &&
2069 y1 < get_item_y(item) + get_item_h(item))
2088 BC_ListBoxItem *item = data[master_column].values[i];
2089 if(item->get_sublist() &&
2091 result |= select_rectangle(item->get_sublist(),
2100 int BC_ListBox::reposition_item(ArrayList<BC_ListBoxItem*> *data,
2101 int selection_number,
2107 if(!counter) counter = &temp;
2110 for(int i = 0; i < data[master_column].total; i++)
2112 BC_ListBoxItem *item = data[master_column].values[i];
2114 if((*counter) == selection_number)
2120 // Not recursive because it's only used for icons
2125 void BC_ListBox::move_selection(ArrayList<BC_ListBoxItem*> *dst,
2126 ArrayList<BC_ListBoxItem*> *src)
2128 for(int i = 0; i < src[master_column].total; i++)
2130 BC_ListBoxItem *item = src[master_column].values[i];
2135 for(int j = 0; j < columns; j++)
2137 dst[j].append(src[j].values[i]);
2138 src[j].remove_number(i);
2142 // Descend into sublist
2143 if(item->get_sublist())
2146 item->get_sublist());
2151 int BC_ListBox::put_selection(ArrayList<BC_ListBoxItem*> *data,
2152 ArrayList<BC_ListBoxItem*> *src,
2157 if(!counter) counter = &temp;
2161 for(int j = 0; j < columns; j++)
2163 for(int i = 0; i < src[j].total; i++)
2165 data[j].append(src[j].values[i]);
2171 for(int i = 0; i < data[master_column].total; i++)
2174 if((*counter) == destination)
2176 for(int j = 0; j < columns; j++)
2178 for(int k = 0; k < src[j].total; k++)
2180 data[j].insert(src[j].values[k], destination + k);
2186 BC_ListBoxItem *item = data[master_column].values[i];
2187 if(item->get_sublist())
2189 if(put_selection(item->get_sublist(),
2201 int BC_ListBox::item_to_index(ArrayList<BC_ListBoxItem*> *data,
2202 BC_ListBoxItem *item,
2206 if(!counter) counter = &temp;
2208 for(int i = 0; i < data[master_column].total; i++)
2211 for(int j = 0; j < columns; j++)
2213 BC_ListBoxItem *new_item = data[j].values[i];
2214 //printf("BC_ListBox::item_to_index 1 %d %d %p\n", j, i, new_item);
2215 if(new_item == item)
2221 BC_ListBoxItem *new_item = data[master_column].values[i];
2222 if(new_item->get_sublist())
2224 if(item_to_index(new_item->get_sublist(),
2234 BC_ListBoxItem* BC_ListBox::index_to_item(ArrayList<BC_ListBoxItem*> *data,
2240 if(!counter) counter = &temp;
2241 for(int i = 0; i < data[master_column].total; i++)
2244 if((*counter) == number)
2246 return data[column].values[i];
2248 BC_ListBoxItem *item = data[master_column].values[i];
2249 if(item->get_sublist())
2251 BC_ListBoxItem *result = index_to_item(item->get_sublist(),
2255 if(result) return result;
2261 int BC_ListBox::get_cursor_item(ArrayList<BC_ListBoxItem*> *data,
2264 BC_ListBoxItem **item_return,
2269 if(!data) return -1;
2270 if(!counter) counter = &temp;
2272 // Icons are not treed
2273 if(display_format == LISTBOX_ICONS)
2275 for(int j = data[master_column].total - 1; j >= 0; j--)
2277 int icon_x, icon_y, icon_w, icon_h;
2278 int text_x, text_y, text_w, text_h;
2279 BC_ListBoxItem *item = data[master_column].values[j];
2280 get_icon_mask(item, icon_x, icon_y, icon_w, icon_h);
2281 get_text_mask(item, text_x, text_y, text_w, text_h);
2283 if((cursor_x >= icon_x && cursor_x < icon_x + icon_w &&
2284 cursor_y >= icon_y && cursor_y < icon_y + icon_h) ||
2285 (cursor_x >= text_x && cursor_x < text_x + text_w &&
2286 cursor_y >= text_y && cursor_y < text_y + text_h))
2288 if(item_return) (*item_return) = item;
2295 if(display_format == LISTBOX_TEXT)
2297 // Cursor is inside items rectangle
2299 cursor_x < (yscrollbar ?
2300 gui->get_w() - get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w() :
2302 // Only clamp y if we're not in a SELECT operation.
2303 (current_operation == BC_ListBox::SELECT ||
2304 (cursor_y > get_title_h() + LISTBOX_BORDER &&
2305 cursor_y < gui->get_h())))
2307 // Search table for cursor obstruction
2308 for(int i = 0; i < data[master_column].total; i++)
2310 BC_ListBoxItem *item = data[master_column].values[i];
2313 // Cursor is inside item on current level
2316 cursor_y >= get_item_y(item) &&
2317 cursor_y < get_item_y(item) + get_item_h(item))
2319 //printf("BC_ListBox::get_cursor_item %d %d %p\n", master_column, i, item);
2320 if(item_return) (*item_return) = item;
2324 // Descend into sublist
2325 if(item->get_sublist())
2327 if(get_cursor_item(item->get_sublist(),
2332 item->get_expand()) >= 0)
2341 int BC_ListBox::repeat_event(int64_t duration)
2343 switch(current_operation)
2345 // Repeat out of bounds selection
2347 if(duration == get_resources()->scroll_repeat)
2348 return rectangle_scroll_event();
2352 if(duration == get_resources()->scroll_repeat)
2353 return select_scroll_event();
2358 if(button_highlighted &&
2359 duration == get_resources()->tooltip_delay &&
2360 tooltip_text[0] != 0 &&
2374 int BC_ListBox::cursor_enter_event()
2378 switch(current_operation)
2380 // Cursor moved over button, pressed, and exited.
2381 case BUTTON_DOWN_SELECT:
2382 if(top_level->event_win == win)
2384 current_operation = BUTTON_DN;
2386 button_highlighted = 1;
2392 // Cursor entered button
2393 if(is_popup && top_level->event_win == win)
2395 button_highlighted = 1;
2400 // TODO: Need to get the highlighted column title or item
2401 if(gui && top_level->event_win == gui->win)
2403 list_highlighted = 1;
2413 int BC_ListBox::cursor_leave_event()
2415 int redraw_button = 0;
2416 int redraw_border = 0;
2417 int redraw_titles = 0;
2418 int redraw_items = 0;
2420 if(current_operation == COLUMN_DRAG) return 0;
2423 if(button_highlighted)
2425 button_highlighted = 0;
2430 if(list_highlighted)
2432 list_highlighted = 0;
2433 highlighted_item = -1;
2434 highlighted_ptr = 0;
2435 highlighted_title = -1;
2436 int redraw_toggles = 0;
2437 for(int i = 0; i < expanders.total; i++)
2438 expanders.values[i]->cursor_leave_event(&redraw_toggles);
2446 int BC_ListBox::get_first_selection(ArrayList<BC_ListBoxItem*> *data, int *result)
2449 if(!result) result = &temp;
2451 for(int i = 0; i < data[master_column].total; i++)
2453 BC_ListBoxItem *item = data[master_column].values[i];
2455 if(item->selected) return (*result);
2456 if(item->get_sublist())
2458 if(get_first_selection(item->get_sublist(), result) >= 0)
2465 int BC_ListBox::get_total_items(ArrayList<BC_ListBoxItem*> *data,
2470 if(!result) result = &temp;
2472 for(int i = 0; i < data[master_column].total; i++)
2475 if(data[master_column].values[i]->get_sublist())
2476 get_total_items(data[master_column].values[i]->get_sublist(),
2485 int BC_ListBox::get_last_selection(ArrayList<BC_ListBoxItem*> *data,
2496 for(int i = data[master_column].total - 1; i >= 0; i--)
2498 BC_ListBoxItem *item = data[master_column].values[i];
2503 return get_total_items(data, 0, master_column) - (*result) /* - 1 */;
2508 if(item->get_sublist())
2510 if(get_last_selection(item->get_sublist(), result) >= 0)
2513 return get_total_items(data, 0, master_column) - (*result) /* - 1 */;
2522 void BC_ListBox::select_range(ArrayList<BC_ListBoxItem*> *data,
2528 if(!current) current = &temp;
2530 for(int i = 0; i < data[master_column].total; i++)
2533 if((*current) >= start && (*current) < end)
2535 for(int j = 0; j < columns; j++)
2536 data[j].values[i]->selected = 1;
2538 BC_ListBoxItem *item = data[master_column].values[i];
2539 if(item->get_sublist())
2540 select_range(item->get_sublist(),
2548 // Fill items between current selection and new selection
2549 int BC_ListBox::expand_selection(int button_press, int selection_number)
2551 int old_selection_start = selection_start;
2552 int old_selection_end = selection_end;
2554 // printf("BC_ListBox::expand_selection %d %d\n",
2555 // selection_center,
2556 // selection_number);
2558 // Calculate the range to select based on selection_center and selection_number
2559 if(selection_number < selection_center)
2561 selection_start = selection_number;
2565 selection_end = selection_number + 1;
2568 //printf("BC_ListBox::expand_selection %d %d %d %d\n", old_selection_start, old_selection_end, selection_start, selection_end);
2569 // Recurse through all the items and select the desired range
2570 select_range(data, selection_start, selection_end);
2573 return (old_selection_start != selection_start ||
2574 old_selection_end != selection_end);
2577 int BC_ListBox::toggle_item_selection(ArrayList<BC_ListBoxItem*> *data,
2578 int selection_number,
2582 if(!counter) counter = &temp;
2584 for(int i = 0; i < data[master_column].total; i++)
2586 BC_ListBoxItem *item = data[master_column].values[i];
2588 if((*counter) == selection_number)
2590 // Get new value for selection
2591 int selected = !item->selected;
2593 for(int j = 0; j < columns; j++)
2594 data[j].values[i]->selected = selected;
2598 // Descend into sublist
2599 if(item->get_sublist())
2601 if(toggle_item_selection(item->get_sublist(),
2612 void BC_ListBox::set_all_selected(ArrayList<BC_ListBoxItem*> *data, int value)
2614 for(int i = 0; i < data[master_column].total; i++)
2616 for(int j = 0; j < columns; j++)
2618 BC_ListBoxItem *item = data[j].values[i];
2619 item->selected = value;
2621 BC_ListBoxItem *item = data[master_column].values[i];
2622 if(item->get_sublist())
2624 set_all_selected(item->get_sublist(), value);
2629 void BC_ListBox::set_selected(ArrayList<BC_ListBoxItem*> *data,
2635 if(!counter) counter = &temp;
2636 for(int i = 0; i < data[master_column].total && (*counter) != item_number; i++)
2639 if((*counter) == item_number)
2641 for(int j = 0; j < columns; j++)
2643 BC_ListBoxItem *item = data[j].values[i];
2644 item->selected = value;
2649 BC_ListBoxItem *item = data[master_column].values[i];
2650 if(item->get_sublist())
2652 set_selected(item->get_sublist(),
2660 int BC_ListBox::update_selection(ArrayList<BC_ListBoxItem*> *data,
2661 int selection_number,
2666 if(!counter) counter = &temp;
2668 for(int i = 0; i < data[master_column].total; i++)
2670 BC_ListBoxItem *item = data[master_column].values[i];
2672 if((*counter) == selection_number && !item->selected)
2675 for(int j = 0; j < columns; j++)
2676 data[j].values[i]->selected = 1;
2679 if((*counter) != selection_number && item->selected)
2682 for(int j = 0; j < columns; j++)
2683 data[j].values[i]->selected = 0;
2685 if(item->get_sublist())
2686 result |= update_selection(item->get_sublist(),
2693 void BC_ListBox::promote_selections(ArrayList<BC_ListBoxItem*> *data,
2697 for(int i = 0; i < data[master_column].total; i++)
2699 for(int j = 0; j < columns; j++)
2701 BC_ListBoxItem *item = data[j].values[i];
2702 if(item->selected == old_value) item->selected = new_value;
2704 BC_ListBoxItem *item = data[master_column].values[i];
2705 if(item->get_sublist())
2706 promote_selections(item->get_sublist(), old_value, new_value);
2710 int BC_ListBox::focus_out_event()
2716 int BC_ListBox::button_press_event()
2719 BC_ListBoxItem *current_item = 0;
2721 int do_selection_change = 0;
2727 // Pressed in button
2728 if(is_popup && top_level->event_win == win)
2730 current_operation = BUTTON_DN;
2736 top_level->deactivate();
2743 // Pressed in scrollbar
2744 if((xscrollbar && top_level->event_win == xscrollbar->win) ||
2745 (yscrollbar && top_level->event_win == yscrollbar->win))
2751 if(gui && top_level->event_win == gui->win)
2753 // Activate list items
2756 top_level->deactivate();
2760 // Wheel mouse pressed
2761 if(get_buttonpress() == 4)
2763 current_operation = WHEEL;
2766 set_yposition(yposition - gui->get_h() / 10, 0);
2768 update_scrollbars();
2769 highlighted_ptr = 0;
2770 highlighted_item = get_cursor_item(data,
2771 top_level->cursor_x,
2772 top_level->cursor_y,
2779 if(get_buttonpress() == 5)
2781 current_operation = WHEEL;
2784 set_yposition(yposition + gui->get_h() / 10, 0);
2786 update_scrollbars();
2787 highlighted_ptr = 0;
2788 highlighted_item = get_cursor_item(data,
2789 top_level->cursor_x,
2790 top_level->cursor_y,
2797 // Pressed over column title division
2798 if(test_column_divisions(gui->get_cursor_x(),
2799 gui->get_cursor_y(),
2802 current_operation = DRAG_DIVISION;
2806 // Pressed in column title
2807 if(test_column_titles(gui->get_cursor_x(), gui->get_cursor_y()))
2809 current_operation = COLUMN_DN;
2810 button_highlighted = 0;
2811 list_highlighted = 1;
2816 // Pressed in expander
2817 if(test_expanders())
2819 current_operation = EXPAND_DN;
2820 // Need to redraw items because of alpha
2825 // Pressed over item
2826 if((selection_number = get_cursor_item(data,
2827 gui->get_cursor_x(),
2828 gui->get_cursor_y(),
2829 ¤t_item)) >= 0)
2831 // Get item button was pressed over
2832 selection_number2 = selection_number1;
2833 selection_number1 = selection_number;
2835 selection_start = -1;
2839 // Multiple item selection is possible
2840 if(selection_mode == LISTBOX_MULTIPLE &&
2841 (ctrl_down() || shift_down()))
2843 // Expand text selection.
2844 // Fill items between selected region and current item.
2845 if(shift_down() && display_format == LISTBOX_TEXT)
2847 // Get first item selected
2848 selection_start = get_first_selection(data);
2849 // Get last item selected
2850 selection_end = get_last_selection(data);
2851 // Get center of selected region
2852 if(selection_end > selection_start)
2854 selection_center = (selection_end + selection_start) >> 1;
2858 selection_center = selection_number;
2862 // Deselect everything.
2863 set_all_selected(data, 0);
2864 // Select just the items
2865 expand_selection(1, selection_number);
2869 // Toggle a single item on or off
2871 toggle_item_selection(data, selection_number);
2872 new_value = current_item->selected;
2876 // Select single item
2878 if(!current_item->selected)
2880 set_all_selected(data, 0);
2889 current_operation = SELECT;
2890 highlighted_item = selection_number;
2891 highlighted_ptr = current_item;
2892 button_highlighted = 0;
2893 list_highlighted = 1;
2896 do_selection_change = 1;
2901 // Pressed over nothing. Start rectangle selection.
2903 if(get_buttonpress() == 1 &&
2904 selection_mode == LISTBOX_MULTIPLE)
2908 // Deselect all and redraw if anything was selected
2909 if(get_selection_number(0, 0) >= 0)
2911 set_all_selected(data, 0);
2913 do_selection_change = 1;
2919 // Promote selections to protect from a rectangle selection
2920 promote_selections(data, 1, 2);
2923 // Start rectangle selection
2924 current_operation = SELECT_RECT;
2925 rect_x1 = rect_x2 = get_cursor_x();
2926 rect_y1 = rect_y2 = get_cursor_y();
2934 if(is_popup && active)
2941 if(do_selection_change) selection_changed();
2946 int BC_ListBox::button_release_event()
2949 int cursor_x, cursor_y;
2953 //printf("BC_ListBox::button_release_event 1 %d\n", current_operation);
2954 switch(current_operation)
2957 current_operation = NO_OPERATION;
2962 current_operation = NO_OPERATION;
2966 // Release item selection
2967 case BUTTON_DOWN_SELECT:
2969 //printf("BC_ListBox::button_release_event 10\n");
2970 unset_repeat(get_resources()->scroll_repeat);
2971 current_operation = NO_OPERATION;
2972 translate_coordinates(top_level->event_win,
2974 gui->get_cursor_x(),
2975 gui->get_cursor_y(),
2981 get_cursor_item(data, cursor_x, cursor_y);
2982 //printf("BC_ListBox::button_release_event %d %d\n", selection_number2, selection_number1);
2987 if(selection_number >= 0)
2993 // Second button release outside button
2994 if(button_releases > 1)
3001 if(top_level->get_double_click() &&
3002 selection_number2 == selection_number1 &&
3003 selection_number2 >= 0 &&
3004 selection_number1 >= 0)
3014 unset_repeat(get_resources()->scroll_repeat);
3017 // Demote selections from rectangle selection
3018 promote_selections(data, 2, 1);
3021 // Hide rectangle overlay
3023 current_operation = NO_OPERATION;
3027 // Release popup button
3030 current_operation = NO_OPERATION;
3034 // Second button release inside button
3035 if(button_releases > 1)
3043 current_operation = NO_OPERATION;
3044 // Update the sort column and the sort order for the user only if the existing
3045 // sort column is valid.
3046 if(sort_column >= 0)
3048 // Invert order only if column is the same
3049 if(highlighted_title == sort_column)
3051 (sort_order == SORT_ASCENDING) ?
3054 // Set the new sort column
3055 sort_column = highlighted_title;
3056 if(!sort_order_event())
3062 // Sorting not enabled. Redraw the title state.
3071 int redraw_toggles = 0;
3072 for(int i = 0; i < expanders.total && !result; i++)
3074 if(expanders.values[i]->button_release_event(&redraw_toggles))
3079 // Need to redraw items because of alpha
3080 if(redraw_toggles) draw_items(1);
3081 current_operation = NO_OPERATION;
3086 // Can't default to NO_OPERATION because it may be used in a drag event.
3091 if(do_event) handle_event();
3096 int BC_ListBox::get_title_h()
3098 if(display_format == LISTBOX_TEXT)
3099 return column_titles ? column_bg[0]->get_h() : 0;
3104 void BC_ListBox::reset_cursor(int new_cursor)
3108 if(gui->get_cursor() != new_cursor)
3110 gui->set_cursor(new_cursor);
3114 if(get_cursor() != new_cursor)
3116 set_cursor(new_cursor);
3120 int BC_ListBox::test_column_divisions(int cursor_x, int cursor_y, int &new_cursor)
3125 cursor_y < get_title_h() &&
3127 cursor_x < gui->get_w())
3129 for(int i = 1; i < columns; i++)
3131 if(cursor_x >= -xposition + get_column_offset(i) - 5 &&
3132 cursor_x < -xposition + get_column_offset(i) + 5)
3134 highlighted_item = -1;
3135 highlighted_ptr = 0;
3136 highlighted_division = i;
3137 highlighted_title = -1;
3138 list_highlighted = 1;
3139 new_cursor = HSEPARATE_CURSOR;
3144 highlighted_division = -1;
3148 int BC_ListBox::test_column_titles(int cursor_x, int cursor_y)
3153 cursor_y < get_title_h() &&
3155 cursor_x < gui->get_w())
3157 for(int i = 0; i < columns; i++)
3159 if(cursor_x >= -xposition + get_column_offset(i) &&
3160 (cursor_x < -xposition + get_column_offset(i + 1) ||
3163 highlighted_item = -1;
3164 highlighted_ptr = 0;
3165 highlighted_division = -1;
3166 highlighted_title = i;
3167 list_highlighted = 1;
3172 highlighted_title = -1;
3176 int BC_ListBox::test_expanders()
3178 for(int i = 0; i < expanders.total; i++)
3180 if(expanders.values[i]->button_press_event())
3182 current_operation = EXPAND_DN;
3190 int BC_ListBox::cursor_motion_event()
3192 int redraw = 0, result = 0;
3193 int new_cursor = ARROW_CURSOR;
3195 selection_number = -1;
3198 switch(current_operation)
3201 // Button pressed and slid off button
3202 if(!cursor_inside())
3204 current_operation = BUTTON_DOWN_SELECT;
3212 int new_w = get_cursor_x() +
3214 get_column_offset(highlighted_division - 1);
3215 new_cursor = HSEPARATE_CURSOR;
3219 column_width[highlighted_division - 1] = new_w;
3223 default_column_width[highlighted_division - 1] = new_w;
3226 column_width_boundaries();
3228 // Force update of coords
3229 set_autoplacement(data, 0, 1);
3230 column_resize_event();
3234 update_scrollbars();
3241 if(test_drag_scroll(get_cursor_x(), get_cursor_y()))
3243 set_repeat(get_resources()->scroll_repeat);
3246 int old_x1 = MIN(rect_x1, rect_x2);
3247 int old_x2 = MAX(rect_x1, rect_x2);
3248 int old_y1 = MIN(rect_y1, rect_y2);
3249 int old_y2 = MAX(rect_y1, rect_y2);
3251 int new_rect_x2 = get_cursor_x();
3252 int new_rect_y2 = get_cursor_y();
3254 int x1 = MIN(rect_x1, new_rect_x2);
3255 int x2 = MAX(rect_x1, new_rect_x2);
3256 int y1 = MIN(rect_y1, new_rect_y2);
3257 int y2 = MAX(rect_y1, new_rect_y2);
3259 // Adjust rectangle coverage
3267 redraw = select_rectangle(data,
3279 rect_x2 = get_cursor_x();
3280 rect_y2 = get_cursor_y();
3285 update_scrollbars();
3286 selection_changed();
3298 int old_highlighted_item = highlighted_item;
3299 int old_highlighted_title = highlighted_title;
3300 BC_ListBoxItem *old_highlighted_ptr = highlighted_ptr;
3302 if(test_drag_scroll(get_cursor_x(),
3305 set_repeat(get_resources()->scroll_repeat);
3309 highlighted_item = selection_number = get_cursor_item(data,
3315 // Deselect all items and select just the one we're over
3316 if(selection_number >= 0 &&
3320 selection_mode == LISTBOX_SINGLE))
3322 redraw = update_selection(data, selection_number);
3325 if(selection_mode == LISTBOX_MULTIPLE &&
3326 (shift_down() || ctrl_down()))
3327 // Expand multiple selection
3329 // Expand selected region in text mode centered around initial range
3330 if(display_format == LISTBOX_TEXT && shift_down())
3332 // Deselect everything.
3333 set_all_selected(data, 0);
3335 // Select just the items
3336 redraw = expand_selection(0, selection_number);
3339 // Set the one item we're over to the selection value determined in
3340 // button_press_event.
3348 if(highlighted_item != old_highlighted_item)
3352 update_scrollbars();
3353 //printf("BC_ListBox::cursor_motion_event %d %d\n", highlighted_item, old_highlighted_item);
3354 selection_changed();
3359 case BUTTON_DOWN_SELECT:
3360 // Went back into button area
3363 current_operation = BUTTON_DN;
3368 // Went into item area
3371 int cursor_x = 0, cursor_y = 0;
3372 translate_coordinates(top_level->event_win,
3374 top_level->cursor_x,
3375 top_level->cursor_y,
3378 int old_highlighted_item = highlighted_item;
3379 highlighted_item = selection_number = get_cursor_item(data,
3384 if(highlighted_item != old_highlighted_item)
3386 update_selection(data, selection_number);
3388 selection_changed();
3395 int redraw_toggles = 0;
3396 for(int i = 0; i < expanders.total && !result; i++)
3398 result = expanders.values[i]->cursor_motion_event(
3403 // Need to redraw items because of the alpha
3411 int cursor_x = get_cursor_x(), cursor_y = get_cursor_y();
3412 if(gui && top_level->event_win == gui->win)
3414 int old_highlighted_title = highlighted_title;
3415 int old_list_highlighted = list_highlighted;
3416 int old_highlighted_division = highlighted_division;
3417 int old_highlighted_item = highlighted_item;
3418 int redraw_titles = 0;
3419 int redraw_border = 0;
3420 int redraw_items = 0;
3421 int redraw_toggles = 0;
3425 // Test if cursor moved over a title division
3426 test_column_divisions(cursor_x, cursor_y, new_cursor);
3428 // Test if cursor moved over a title
3429 if(highlighted_division < 0)
3431 test_column_titles(cursor_x, cursor_y);
3434 // Test if cursor moved over expander
3435 if(highlighted_division < 0 &&
3436 highlighted_title < 0 &&
3437 display_format == LISTBOX_TEXT)
3439 for(int i = 0; i < expanders.total; i++)
3441 expanders.values[i]->cursor_motion_event(
3444 //printf("BC_ListBox::cursor_motion_event %d\n", redraw_toggles);
3447 // Test if cursor moved over an item
3448 if(highlighted_division < 0 &&
3449 highlighted_title < 0)
3451 highlighted_item = get_cursor_item(data,
3458 // Clear title highlighting if moved over division
3459 if(old_highlighted_title != highlighted_title)
3464 // Highlight list border
3465 if(old_list_highlighted != list_highlighted)
3470 // Moved out of item area
3471 if(old_highlighted_item != highlighted_item)
3476 //printf("BC_ListBox::cursor_motion_event 1 %d\n", highlighted_item);
3478 // Change cursor to title division adjustment
3479 reset_cursor(new_cursor);
3506 if(!result && list_highlighted)
3508 list_highlighted = 0;
3509 highlighted_item = -1;
3510 highlighted_ptr = 0;
3511 highlighted_title = -1;
3512 highlighted_division = -1;
3524 int BC_ListBox::drag_start_event()
3526 switch(current_operation)
3530 gui->is_event_win() &&
3533 BC_ListBoxItem *item_return = 0;
3534 selection_number = get_cursor_item(data,
3535 top_level->cursor_x,
3536 top_level->cursor_y,
3539 if(selection_number >= 0)
3542 if (item_return->icon_vframe)
3544 drag_popup = new BC_DragWindow(this,
3545 item_return->icon_vframe,
3546 get_abs_cursor_x(0) - item_return->icon_vframe->get_w() / 2,
3547 get_abs_cursor_y(0) - item_return->icon_vframe->get_h() / 2);
3550 // this probably works not!
3551 if (item_return->icon)
3552 drag_popup = new BC_DragWindow(this,
3554 get_abs_cursor_x(0) - item_return->icon->get_w() / 2,
3555 get_abs_cursor_y(0) - item_return->icon->get_h() / 2);
3557 drag_popup = new BC_DragWindow(this,
3559 get_abs_cursor_x(0) - drag_icon_vframe->get_w() / 2,
3560 get_abs_cursor_y(0) - drag_icon_vframe->get_h() / 2);
3561 current_operation = DRAG_ITEM;
3568 if(gui && gui->is_event_win() && allow_drag_column)
3570 drag_popup = new BC_DragWindow(this,
3571 drag_column_icon_vframe,
3572 get_abs_cursor_x(0) - drag_column_icon_vframe->get_w() / 2,
3573 get_abs_cursor_y(0) - drag_column_icon_vframe->get_h() / 2);
3574 dragged_title = highlighted_title;
3575 current_operation = COLUMN_DRAG;
3585 int BC_ListBox::drag_motion_event()
3587 //printf("BC_ListBox::drag_motion_event 1 %d\n", current_operation);
3588 switch(current_operation)
3594 int new_highlighted_item = -1;
3595 BC_ListBoxItem *new_highlighted_ptr = 0;
3596 int new_highlight = new_highlighted_item = get_cursor_item(data,
3597 top_level->cursor_x,
3598 top_level->cursor_y,
3599 &new_highlighted_ptr);
3601 if(new_highlighted_item != highlighted_item)
3606 // Always update highlighted value for drag_stop
3607 highlighted_item = new_highlighted_item;
3608 highlighted_ptr = new_highlighted_ptr;
3609 //printf("BC_ListBox::drag_motion_event 1 %p\n", highlighted_ptr);
3614 update_scrollbars();
3617 return drag_popup->cursor_motion_event();
3623 int old_highlighted_title = highlighted_title;
3624 test_column_titles(get_cursor_x(), get_cursor_y());
3625 if(old_highlighted_title != highlighted_title)
3629 return drag_popup->cursor_motion_event();
3636 int BC_ListBox::drag_stop_event()
3638 switch(current_operation)
3641 // Inside window boundary
3642 if(top_level->cursor_x > 0 &&
3643 top_level->cursor_x < gui->get_w() - drag_popup->get_w() / 2 &&
3644 top_level->cursor_y > 0 &&
3645 top_level->cursor_y < gui->get_h() - drag_popup->get_h() / 2)
3650 if(display_format == LISTBOX_ICONS)
3652 reposition_item(data,
3654 top_level->cursor_x +
3655 drag_popup->get_offset_x() -
3659 top_level->cursor_y +
3660 drag_popup->get_offset_y() -
3670 int destination = highlighted_item = item_to_index(data,
3672 //printf("BC_ListBox::drag_stop_event 1 %p %d\n", highlighted_ptr, destination);
3674 // Move selected items from data to temporary
3675 ArrayList<BC_ListBoxItem*> *src_items =
3676 new ArrayList<BC_ListBoxItem*>[columns];
3678 move_selection(src_items, data);
3680 // Insert items from temporary to data
3686 delete [] src_items;
3687 set_autoplacement(data, 0, 1);
3694 drag_popup->drag_failure_event();
3698 current_operation = NO_OPERATION;
3704 if(dragged_title != highlighted_title)
3706 if(highlighted_title >= 0)
3708 if(!move_column_event()) draw_titles(1);
3711 drag_popup->drag_failure_event();
3713 current_operation = NO_OPERATION;
3722 BC_DragWindow* BC_ListBox::get_drag_popup()
3727 int BC_ListBox::translation_event()
3731 int new_x = gui->get_x() +
3732 (top_level->last_translate_x -
3734 top_level->get_resources()->get_left_border());
3735 int new_y = gui->get_y() +
3736 (top_level->last_translate_y -
3738 top_level->get_resources()->get_top_border());
3740 gui->reposition_window(new_x, new_y);
3746 int BC_ListBox::reposition_window(int x, int y, int w, int h)
3750 if(w != -1) popup_w = w;
3751 if(h != -1) popup_h = h;
3752 //printf("BC_ListBox::reposition_window %d %d\n", popup_w, popup_h);
3756 if(w != -1) popup_w = w;
3757 if(h != -1) popup_h = h;
3759 xscrollbar->reposition_window(get_xscroll_x(),
3761 get_xscroll_width());
3763 yscrollbar->reposition_window(get_yscroll_x(),
3765 get_yscroll_height());
3770 BC_WindowBase::reposition_window(x, y, w, h);
3776 int BC_ListBox::deactivate()
3787 highlighted_item = -1;
3788 highlighted_ptr = 0;
3790 top_level->active_subwindow = 0;
3795 int BC_ListBox::activate()
3799 top_level->active_subwindow = this;
3801 button_releases = 0;
3807 XTranslateCoordinates(top_level->display,
3810 get_x() - popup_w + get_w(),
3816 if(new_x < 0) new_x = 0;
3817 if(new_y + popup_h > top_level->get_root_h(0))
3818 new_y -= get_h() + popup_h;
3820 //printf("BC_ListBox::activate %d %d\n", popup_w, popup_h);
3821 add_subwindow(gui = new BC_Popup(this,
3835 int BC_ListBox::keypress_event()
3837 if(!active) return 0;
3839 int result = 0, redraw = 0, done, view_items = view_h / get_text_height(MEDIUMFONT);
3840 int new_item = -1, new_selection = 0;
3842 switch(top_level->get_keypress())
3846 top_level->deactivate();
3851 new_selection = new_item = select_previous(0);
3853 //printf("BC_ListBox::keypress_event 1 %d\n", new_item);
3856 center_selection(new_item);
3863 new_selection = new_item = select_next(0);
3867 center_selection(new_item);
3874 new_selection = new_item = select_previous(view_items - 1);
3878 center_selection(new_item);
3885 new_selection = new_item = select_next(view_items - 1);
3889 center_selection(new_item);
3910 if(top_level->get_keypress() > 30 &&
3911 top_level->get_keypress() < 127)
3913 int query_len = strlen(query);
3914 query[query_len++] = top_level->get_keypress();
3915 query[query_len] = 0;
3916 new_selection = query_list();
3919 if(top_level->get_keypress() == BACKSPACE)
3921 int query_len = strlen(query);
3922 if(query_len > 0) query[--query_len] = 0;
3923 new_selection = query_list();
3936 update_scrollbars();
3939 if(new_selection >= 0)
3941 selection_changed();
3948 BC_Pixmap* BC_ListBox::get_bg_surface()
3954 void BC_ListBox::draw_background()
3956 // White background pixmap
3958 draw_box(0, 0, bg_surface->get_w(), bg_surface->get_h(), bg_surface);
3960 // Optional heroine pixmap
3962 bg_surface->draw_pixmap(bg_pixmap,
3963 bg_surface->get_w() - top_level->get_resources()->listbox_bg->get_w(),
3967 void BC_ListBox::clear_listbox(int x, int y, int w, int h)
3969 gui->draw_pixmap(bg_surface,
3978 void BC_ListBox::update_format(int display_format, int redraw)
3980 this->display_format = display_format;
3983 if(gui) draw_items(1);
3987 int BC_ListBox::get_format()
3989 return display_format;
3994 int BC_ListBox::draw_items(int flash)
3998 //dump(data, columns);
4000 // Calculate items width
4001 calculate_item_coords();
4004 // Create and destroy scrollbars as needed
4009 // draw_background();
4012 if(display_format == LISTBOX_ICONS)
4014 clear_listbox(2, 2 + title_h, view_w, view_h);
4016 set_font(MEDIUMFONT);
4017 for(int i = 0; i < data[master_column].total; i++)
4019 BC_ListBoxItem *item = data[master_column].values[i];
4020 if(get_item_x(item) >= -get_item_w(item) &&
4021 get_item_x(item) < view_w &&
4022 get_item_y(item) >= -get_item_h(item) + title_h &&
4023 get_item_y(item) < view_h + title_h)
4025 int item_color = get_item_highlight(data, 0, i);
4026 int icon_x, icon_y, icon_w, icon_h;
4027 int text_x, text_y, text_w, text_h;
4030 get_icon_mask(item, icon_x, icon_y, icon_w, icon_h);
4031 get_text_mask(item, text_x, text_y, text_w, text_h);
4033 if(item_color != WHITE)
4035 gui->set_color(BLACK);
4036 gui->draw_rectangle(icon_x, icon_y, icon_w, icon_h);
4037 gui->set_color(item_color);
4038 gui->draw_box(icon_x + 1, icon_y + 1, icon_w - 2, icon_h - 2);
4039 gui->set_color(BLACK);
4040 gui->draw_rectangle(text_x, text_y, text_w, text_h);
4041 gui->set_color(item_color);
4042 gui->draw_box(text_x + 1, text_y + 1, text_w - 2, text_h - 2);
4044 if(icon_position == ICON_LEFT)
4045 gui->draw_box(text_x - 1, text_y + 1, 2, text_h - 2);
4047 if(icon_position == ICON_TOP)
4048 gui->draw_line(text_x + 1, text_y, text_x + icon_w - 2, text_y);
4052 gui->set_color(get_item_color(data, 0, i));
4054 item->icon->write_drawable(gui->pixmap,
4055 icon_x + ICON_MARGIN,
4056 icon_y + ICON_MARGIN);
4057 gui->draw_text(text_x + ICON_MARGIN,
4058 text_y + ICON_MARGIN + get_text_ascent(MEDIUMFONT),
4065 if(display_format == LISTBOX_TEXT)
4067 // Draw one column at a time so text overruns don't go into the next column
4068 // clear column backgrounds
4069 int current_toggle = 0;
4070 for(int j = 0; j < columns; j++)
4072 clear_listbox(LISTBOX_BORDER + get_column_offset(j) - xposition,
4073 LISTBOX_BORDER + title_h,
4074 get_column_width(j, 1),
4077 // Draw rows in the column recursively
4078 draw_text_recursive(data, j, 0, ¤t_toggle);
4081 // Delete excess expanders
4082 while(expanders.total > current_toggle)
4084 expanders.remove_object();
4088 // Draw titles on top of rows for superposition effect
4091 // Clear garbage from bottom right corner
4092 if(xscrollbar && yscrollbar && is_popup)
4094 gui->draw_top_background(parent_window,
4095 popup_w - get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w(),
4096 popup_h - get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h(),
4097 get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w(),
4098 get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h());
4105 if(current_operation == SELECT_RECT)
4119 void BC_ListBox::draw_text_recursive(ArrayList<BC_ListBoxItem*> *data,
4122 int *current_toggle)
4126 set_font(MEDIUMFONT);
4129 // Search for a branch and make room for toggle if there is one
4132 for(int i = 0; i < data[column].total; i++)
4134 if(data[column].values[i]->get_sublist())
4136 subindent = BC_WindowBase::get_resources()->listbox_expand[0]->get_w();
4142 for(int i = 0; i < data[column].total; i++)
4145 BC_ListBoxItem *item = data[column].values[i];
4146 BC_ListBoxItem *first_item = data[master_column].values[i];
4148 if(get_item_y(item) >= -get_item_h(item) + title_h &&
4149 get_item_y(item) < view_h + title_h)
4151 int row_color = get_item_highlight(data, 0, i);
4152 int x, y, w, h, column_width;
4154 get_text_mask(item, x, y, w, h);
4155 column_width = get_column_width(column, 1);
4156 if(x + column_width > view_w + LISTBOX_BORDER * 2)
4157 column_width = view_w + LISTBOX_BORDER * 2 - x;
4159 if(row_color != WHITE)
4161 gui->set_color(row_color);
4166 gui->set_color(BLACK);
4169 x + column_width - 1,
4172 y + get_text_height(MEDIUMFONT),
4173 x + column_width - 1,
4174 y + get_text_height(MEDIUMFONT));
4177 gui->set_color(get_item_color(data, column, i));
4180 // Indent only applies to first column
4185 (column == 0 ? indent + subindent : 0),
4186 y + get_text_ascent(MEDIUMFONT),
4192 item->get_sublist() &&
4193 item->get_columns())
4195 // Create new expander
4196 if(*current_toggle >= expanders.total)
4198 BC_ListBoxToggle *toggle =
4199 new BC_ListBoxToggle(this,
4201 x + LISTBOX_BORDER + LISTBOX_MARGIN + indent,
4204 expanders.append(toggle);
4207 // Reposition existing expander
4209 BC_ListBoxToggle *toggle = expanders.values[*current_toggle];
4210 //printf("BC_ListBox::draw_text_recursive 1 %d\n", *current_toggle);
4211 toggle->update(item,
4212 x + LISTBOX_BORDER + LISTBOX_MARGIN + indent,
4216 (*current_toggle)++;
4223 // Descend into sublist
4224 if(first_item->get_expand())
4226 draw_text_recursive(first_item->get_sublist(),
4228 indent + LISTBOX_INDENT,
4238 int BC_ListBox::draw_border(int flash)
4240 gui->draw_3d_border(0,
4242 view_w + LISTBOX_BORDER * 2,
4243 view_h + title_h + LISTBOX_BORDER * 2,
4244 top_level->get_resources()->button_shadow,
4245 list_highlighted ? RED : BLACK,
4246 list_highlighted ? RED : top_level->get_resources()->button_up,
4247 top_level->get_resources()->button_light);
4257 int BC_ListBox::draw_titles(int flash)
4259 if(column_titles && display_format == LISTBOX_TEXT)
4261 //printf("BC_ListBox::draw_titles 1 %d\n", highlighted_title);
4262 for(int i = 0; i < columns; i++)
4266 // Column title background
4267 int image_number = 0;
4268 if(i == highlighted_title)
4271 if(current_operation == COLUMN_DN)
4275 int column_offset = get_column_offset(i) - xposition + LISTBOX_BORDER;
4276 int column_width = get_column_width(i, 1);
4277 gui->draw_3segmenth(get_column_offset(i) - xposition + LISTBOX_BORDER,
4279 get_column_width(i, 1),
4280 column_bg[image_number]);
4282 // Column title sort order
4283 if(i == sort_column)
4286 if(sort_order == SORT_ASCENDING)
4287 src = column_sort_dn;
4289 src = column_sort_up;
4291 int x = column_offset + column_width - LISTBOX_BORDER;
4292 if(x > items_w) x = items_w;
4293 x -= 5 + src->get_w();
4295 //printf("BC_ListBox::draw_titles 1 %d\n", x);
4296 gui->draw_pixmap(src,
4298 title_h / 2 - src->get_h() / 2 + LISTBOX_BORDER);
4302 gui->set_color(BLACK);
4303 gui->draw_text(-xposition + get_column_offset(i) + LISTBOX_MARGIN + LISTBOX_BORDER,
4304 LISTBOX_MARGIN + LISTBOX_BORDER + get_text_ascent(MEDIUMFONT),
4317 void BC_ListBox::draw_toggles(int flash)
4319 for(int i = 0; i < expanders.total; i++)
4320 expanders.values[i]->draw(0);
4322 //printf("BC_ListBox::draw_toggles 1 %d\n", flash);
4323 if(flash && expanders.total)
4330 int BC_ListBox::draw_rectangle(int flash)
4332 int x1 = MIN(rect_x1, rect_x2);
4333 int x2 = MAX(rect_x1, rect_x2);
4334 int y1 = MIN(rect_y1, rect_y2);
4335 int y2 = MAX(rect_y1, rect_y2);
4337 if(x1 == x2 || y1 == y2) return 0;
4340 gui->set_color(WHITE);
4341 gui->draw_rectangle(x1, y1, x2 - x1, y2 - y1);
4353 void BC_ListBox::dump(ArrayList<BC_ListBoxItem*> *data,
4360 printf("BC_ListBox::dump 1\n");
4363 for(int i = 0; i < data[master_column].total; i++)
4365 for(int k = 0; k < indent; k++)
4367 for(int j = 0; j < columns; j++)
4369 BC_ListBoxItem *item = data[j].values[i];
4370 printf("%d,%d,%d=%s ",
4373 item->autoplace_text,
4378 if(data[master_column].values[i]->get_sublist())
4380 dump(data[master_column].values[i]->get_sublist(),
4381 data[master_column].values[i]->get_columns(),