3 * Copyright (C) 2010-2014 Adam Williams <broadcast at earthling dot net>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "bcdisplayinfo.h"
22 #include "bcdragwindow.h"
23 #include "bclistbox.h"
24 #include "bclistboxitem.h"
26 #include "bcresources.h"
27 #include "bcsignals.h"
39 // ====================================================== scrollbars
41 BC_ListBoxYScroll::BC_ListBoxYScroll(BC_ListBox *listbox)
42 : BC_ScrollBar(listbox->get_yscroll_x(), listbox->get_yscroll_y(),
43 listbox->yscroll_orientation, listbox->get_yscroll_height(),
44 listbox->items_h, listbox->yposition, listbox->view_h)
46 this->listbox = listbox;
49 BC_ListBoxYScroll::~BC_ListBoxYScroll()
53 int BC_ListBoxYScroll::handle_event()
55 listbox->set_yposition(get_value());
59 BC_ListBoxXScroll::BC_ListBoxXScroll(BC_ListBox *listbox)
60 : BC_ScrollBar(listbox->get_xscroll_x(), listbox->get_xscroll_y(),
61 listbox->xscroll_orientation, listbox->get_xscroll_width(),
62 listbox->items_w, listbox->xposition, listbox->view_w)
64 this->listbox = listbox;
67 BC_ListBoxXScroll::~BC_ListBoxXScroll()
71 int BC_ListBoxXScroll::handle_event()
73 listbox->set_xposition(get_value());
78 BC_ListBoxToggle::BC_ListBoxToggle(BC_ListBox *listbox,
83 this->listbox = listbox;
87 this->value = item->get_expand();
89 state = BC_Toggle::TOGGLE_CHECKED;
91 state = BC_Toggle::TOGGLE_UP;
94 void BC_ListBoxToggle::update(BC_ListBoxItem *item,
99 this->value = item->get_expand();
108 state = TOGGLE_CHECKED;
113 state = TOGGLE_CHECKEDHI;
124 case TOGGLE_CHECKEDHI:
129 case TOGGLE_DOWN_EXIT:
137 int BC_ListBoxToggle::cursor_motion_event(int *redraw_toggles)
139 int w = listbox->toggle_images[0]->get_w();
140 int h = listbox->toggle_images[0]->get_h();
141 int cursor_inside = listbox->get_cursor_x() >= x &&
142 listbox->get_cursor_x() < x + w &&
143 listbox->get_cursor_y() >= y &&
144 listbox->get_cursor_y() < y + h;
148 case BC_ListBoxToggle::TOGGLE_UPHI:
149 if( !cursor_inside ) {
150 state = BC_ListBoxToggle::TOGGLE_UP;
155 case BC_ListBoxToggle::TOGGLE_CHECKEDHI:
156 if( !cursor_inside ) {
157 state = BC_ListBoxToggle::TOGGLE_CHECKED;
162 case BC_ListBoxToggle::TOGGLE_DOWN:
163 if( !cursor_inside ) {
164 state = BC_ListBoxToggle::TOGGLE_DOWN_EXIT;
170 case BC_ListBoxToggle::TOGGLE_DOWN_EXIT:
171 if( cursor_inside ) {
172 state = BC_ListBoxToggle::TOGGLE_DOWN;
179 if( cursor_inside ) {
181 state = BC_ListBoxToggle::TOGGLE_CHECKEDHI;
183 state = BC_ListBoxToggle::TOGGLE_UPHI;
191 int BC_ListBoxToggle::cursor_leave_event(int *redraw_toggles)
194 state = BC_ListBoxToggle::TOGGLE_CHECKED;
196 state = BC_ListBoxToggle::TOGGLE_UP;
200 int BC_ListBoxToggle::button_press_event()
202 int w = listbox->toggle_images[0]->get_w();
203 int h = listbox->toggle_images[0]->get_h();
205 if( listbox->gui->get_cursor_x() >= x &&
206 listbox->gui->get_cursor_x() < x + w &&
207 listbox->gui->get_cursor_y() >= y &&
208 listbox->gui->get_cursor_y() < y + h ) {
209 state = BC_ListBoxToggle::TOGGLE_DOWN;
215 int BC_ListBoxToggle::button_release_event(int *redraw_toggles)
220 case BC_ListBoxToggle::TOGGLE_DOWN:
223 state = BC_ListBoxToggle::TOGGLE_CHECKEDHI;
225 state = BC_ListBoxToggle::TOGGLE_UPHI;
226 listbox->expand_item(item, value);
230 case BC_ListBoxToggle::TOGGLE_DOWN_EXIT:
232 state = BC_ListBoxToggle::TOGGLE_CHECKED;
234 state = BC_ListBoxToggle::TOGGLE_UP;
242 void BC_ListBoxToggle::draw(int flash)
245 int image_number = 0;
246 int w = listbox->toggle_images[0]->get_w();
247 int h = listbox->toggle_images[0]->get_h();
250 case BC_ListBoxToggle::TOGGLE_UP: image_number = 0; break;
251 case BC_ListBoxToggle::TOGGLE_UPHI: image_number = 1; break;
252 case BC_ListBoxToggle::TOGGLE_CHECKED: image_number = 2; break;
253 case BC_ListBoxToggle::TOGGLE_DOWN: image_number = 3; break;
254 case BC_ListBoxToggle::TOGGLE_CHECKEDHI: image_number = 4; break;
255 case BC_ListBoxToggle::TOGGLE_DOWN_EXIT:
256 image_number = value ? 2 : 0;
260 //printf("BC_ListBoxToggle::draw 1 %d\n", state);
261 listbox->gui->draw_pixmap(listbox->toggle_images[image_number], x, y);
264 listbox->gui->flash(x, y, w, h);
265 listbox->gui->flush();
271 // ====================================================== box
273 BC_ListBox::BC_ListBox(int x, int y, int w, int h,
274 int display_format, ArrayList<BC_ListBoxItem*> *data,
275 const char **column_titles, int *column_width, int columns,
276 int yposition, int is_popup, int selection_mode,
277 int icon_position, int allow_drag)
278 : BC_SubWindow(x, y, w, h, -1)
280 justify = LISTBOX_RIGHT;
282 highlighted_item = -1;
283 highlighted_title = -1;
284 highlighted_division = -1;
288 current_cursor = ARROW_CURSOR;
290 view_w = items_w = 0;
291 view_h = items_h = 0;
298 xscroll_orientation = SCROLL_HORIZ;
299 yscroll_orientation = SCROLL_VERT;
304 selection_number1 = -1;
305 selection_number2 = -1;
308 row_height = row_ascent = row_descent = 0;
310 selection_center = 0;
312 selection_number = -1;
313 current_operation = NO_OPERATION;
314 button_highlighted = 0;
316 list_highlighted = 0;
320 allow_drag_scroll = 1;
322 for( int i=0; i<32; ++i ) default_column_width[i] = 0;
327 allow_drag_column = 0;
334 for( int i=0; i<3; ++i ) column_bg[i] = 0;
335 for( int i=0; i<4; ++i ) button_images[i] = 0;
336 for( int i=0; i<5; ++i ) toggle_images[i] = 0;
341 //printf("BC_ListBox::BC_ListBox 1\n");
343 this->columns = columns;
344 this->yposition = yposition;
345 this->is_popup = is_popup;
346 this->use_button = 1;
347 this->display_format = display_format;
348 this->selection_mode = selection_mode;
349 this->icon_position = icon_position;
350 this->allow_drag = allow_drag;
351 this->column_titles = 0;
352 this->column_width = 0;
353 this->first_in_view = -1;
354 this->last_in_view = 0;
355 //printf("BC_ListBox::BC_ListBox 1\n");
357 if( (!column_titles && column_width) ||
358 (column_titles && !column_width) ) {
359 printf("BC_ListBox::BC_ListBox either column_titles or column_widths == NULL but not both.\n");
361 //printf("BC_ListBox::BC_ListBox 2 %p %p\n", column_titles, column_width);
363 set_columns(column_titles, column_width, columns);
365 //printf("BC_ListBox::BC_ListBox 3\n");
367 drag_icon_vframe = 0;
368 drag_column_icon_vframe = 0;
371 temp_display_format = display_format;
372 packed_icons = display_format == LISTBOX_ICONS_PACKED ? 1 : 0;
373 rect_x1 = rect_x2 = 0;
374 rect_y1 = rect_y2 = 0;
376 // reset the search engine
377 //printf("BC_ListBox::BC_ListBox 4\n");
380 //printf("BC_ListBox::BC_ListBox 5\n");
383 BC_ListBox::~BC_ListBox()
385 expanders.remove_all_objects();
386 if( bg_surface ) delete bg_surface;
387 if( bg_pixmap ) delete bg_pixmap;
388 if( xscrollbar ) delete xscrollbar;
389 if( yscrollbar ) delete yscrollbar;
390 for( int i=0; i<3; ++i ) delete column_bg[i];
391 for( int i=0; i<4; ++i ) delete button_images[i];
392 for( int i=0; i<5; ++i ) delete toggle_images[i];
393 if( column_sort_up ) delete column_sort_up;
394 if( column_sort_dn ) delete column_sort_dn;
397 if( drag_popup ) delete drag_popup;
400 int BC_ListBox::enable()
407 int BC_ListBox::disable()
414 void BC_ListBox::reset_query()
416 query[0] = 0; // reset query
419 int BC_ListBox::evaluate_query(char *string)
421 for( int i=0; i<data[search_column].size(); ++i ) {
422 if( strcmp(string, data[search_column].get(i)->text) <= 0 &&
423 data[search_column].get(i)->searchable ) {
431 int BC_ListBox::query_list()
433 if( query[0] == 0 ) return 0;
437 int selection_changed = 0;
438 int prev_selection = -1;
439 result = evaluate_query(query);
440 if( result >= 0 ) done = 1;
444 for( int i=0; i<data[0].total; ++i ) {
445 for( int j=0; j<columns; ++j ) {
446 if( data[j].values[i]->selected ) prev_selection = i;
447 data[j].values[i]->selected = 0;
452 if( prev_selection != result )
453 selection_changed = 1;
454 for( int j=0; j<columns; ++j ) {
455 data[j].values[result]->selected = 1;
457 center_selection(result);
460 return selection_changed;
463 void BC_ListBox::init_column_width()
465 if( !column_width && data ) {
467 for( int i=0; i<data[0].total; ++i ) {
468 wd = get_text_w(data[0].values[i]);
469 if( wd > widest ) widest = wd;
471 default_column_width[0] = widest + 2 * LISTBOX_MARGIN;
475 int BC_ListBox::initialize()
479 for( int i=0; i<4; ++i ) {
480 button_images[i] = new BC_Pixmap(parent_window,
481 BC_WindowBase::get_resources()->listbox_button[i],
484 w = button_images[0]->get_w();
485 h = button_images[0]->get_h();
489 current_operation = NO_OPERATION;
494 current_operation = NO_OPERATION;
497 for( int i=0; i<3; ++i ) {
498 column_bg[i] = new BC_Pixmap(parent_window,
499 get_resources()->listbox_column[i],
502 for( int i=0; i<5; ++i ) {
503 toggle_images[i] = new BC_Pixmap(parent_window,
504 get_resources()->listbox_expand[i],
508 column_sort_up = new BC_Pixmap(parent_window,
509 BC_WindowBase::get_resources()->listbox_up,
511 column_sort_dn = new BC_Pixmap(parent_window,
512 BC_WindowBase::get_resources()->listbox_dn,
515 //printf("BC_ListBox::initialize 10\n");
516 drag_icon_vframe = get_resources()->type_to_icon[ICON_UNKNOWN];
517 drag_column_icon_vframe = get_resources()->type_to_icon[ICON_COLUMN];
518 // = new BC_Pixmap(parent_window,
519 // get_resources()->type_to_icon[ICON_UNKNOWN],
521 // drag_column_icon = new BC_Pixmap(parent_window,
522 // get_resources()->type_to_icon[ICON_COLUMN],
524 BC_SubWindow::initialize();
528 if( top_level->get_resources()->listbox_bg )
529 bg_pixmap = new BC_Pixmap(this,
530 get_resources()->listbox_bg,
536 if( !use_button && is_popup ) {
544 void BC_ListBox::deactivate_selection()
546 current_operation = NO_OPERATION;
549 int BC_ListBox::draw_button(int flush)
551 // Draw the button for a popup listbox
552 if( use_button && is_popup ) {
553 int image_number = 0;
554 if( button_highlighted )
556 if( current_operation == BUTTON_DN )
561 int iw = button_images[image_number]->get_w();
562 int ih = button_images[image_number]->get_h();
563 pixmap->draw_pixmap(button_images[image_number],0,0,iw,ih);
569 int BC_ListBox::calculate_item_coords()
571 if( !data ) return 0;
577 // Change the display_format to get the right item dimensions for both
579 temp_display_format = display_format;
582 // Scan the first column for lowest y coord of all text
583 // and lowest right x and y coord for all icons which aren't auto placable
584 calculate_last_coords_recursive(data,
585 &icon_x, &next_icon_x, &next_icon_y, &next_text_y, 1);
587 // Reset last column width. It's recalculated based on text width.
588 calculate_item_coords_recursive(data,
589 &icon_x, &next_icon_x, &next_icon_y, &next_text_y, 1);
591 display_format = temp_display_format;
596 void BC_ListBox::calculate_last_coords_recursive(
597 ArrayList<BC_ListBoxItem*> *data,
604 for( int i=0; i<data[0].size(); ++i ) {
605 int current_text_y = 0;
606 int current_icon_x = 0;
607 int current_icon_y = 0;
608 BC_ListBoxItem *item = data[0].get(i);
611 if( !item->autoplace_text ) {
612 // Lowest text coordinate
613 display_format = LISTBOX_TEXT;
614 current_text_y = item->text_y + get_text_h(item);
615 if( current_text_y > *next_text_y )
616 *next_text_y = current_text_y;
618 // Add sublist depth if it is expanded
619 if( item->sublist_active() && item->get_columns() ) {
620 calculate_last_coords_recursive(item->get_sublist(),
621 icon_x, next_icon_x, next_icon_y, next_text_y, 0);
625 // Get next_icon coordinate
627 BC_ListBoxItem *item = data[master_column].get(i);
628 if( !item->autoplace_icon ) {
629 display_format = LISTBOX_ICONS;
630 // Lowest right icon coordinate.
631 current_icon_x = item->icon_x;
632 if( current_icon_x > *icon_x ) *icon_x = current_icon_x;
633 if( current_icon_x + get_item_w(item) > *next_icon_x ) {
634 *next_icon_x = current_icon_x + get_item_w(item);
637 current_icon_y = item->icon_y + get_item_h(item);
638 if( current_icon_y > *next_icon_y )
639 *next_icon_y = current_icon_y;
646 void BC_ListBox::calculate_item_coords_recursive(
647 ArrayList<BC_ListBoxItem*> *data,
648 int *icon_x, int *next_icon_x, int *next_icon_y, int *next_text_y,
651 // get maximum height of an icon
652 row_height = get_text_height(MEDIUMFONT);
653 if( temp_display_format == LISTBOX_ICON_LIST ) {
654 for( int i=0; i<data[0].size(); ++i ) {
655 if( data[0].get(i)->icon ) {
656 int icon_h = data[0].get(i)->icon->get_h() + 2*ICON_MARGIN;
657 if( row_height < icon_h ) row_height = icon_h;
663 // Set up items which need autoplacement.
664 // Should fill icons down and then across
665 for( int i=0; i<data[0].size(); ++i ) {
666 // Don't increase y unless the row requires autoplacing.
667 int total_autoplaced_columns = 0;
669 // Set up icons in first column
671 BC_ListBoxItem *item = data[master_column].get(i);
672 if( item->autoplace_icon ) {
673 // 1 column only if icons are used
674 display_format = LISTBOX_ICONS;
677 if( *next_icon_y + get_item_h(item) >= get_h() &&
679 *icon_x = *next_icon_x;
683 if( *icon_x + get_item_w(item) > *next_icon_x )
684 *next_icon_x = *icon_x + get_item_w(item);
687 item->set_icon_x(*icon_x);
688 item->set_icon_y(*next_icon_y);
690 *next_icon_y += get_item_h(item);
696 row_ascent = row_descent = 0;
697 // row_height still holds icon max height
698 for( int j=0; j<columns; ++j ) {
699 BC_ListBoxItem *item = data[j].get(i);
700 if( item->autoplace_text ) {
701 display_format = LISTBOX_TEXT;
702 item->set_text_x(next_text_x);
703 item->set_text_y(*next_text_y);
704 int ht = get_text_h(item);
705 if( ht > row_height ) row_height = ht;
706 int bl = get_baseline(item);
707 if( bl > row_ascent ) row_ascent = bl;
709 if( dt > row_descent ) row_descent = dt;
711 // printf("BC_ListBox::calculate_item_coords_recursive %p %d %d %d %d %s \n",
712 // item->sublist, item->get_columns(), item->get_expand(),
713 // next_text_x, *next_text_y, item->get_text());
714 // Increment position of next column
715 if( j < columns - 1 ) {
716 next_text_x += (column_width ?
718 default_column_width[j]);
720 // Set last column width based on text width
722 int new_w = get_item_w(item);
724 int *previous_w = (column_width ?
726 &default_column_width[j]);
727 if( new_w > *previous_w )
729 //printf("BC_ListBox::calculate_item_coords_recursive 1 %d\n", new_w);
731 total_autoplaced_columns++;
735 // Increase the text vertical position
736 if( total_autoplaced_columns ) {
737 display_format = LISTBOX_TEXT;
738 *next_text_y += row_height;
742 BC_ListBoxItem *item = data[master_column].values[i];
743 if( item->sublist_active() && item->get_columns() ) {
744 calculate_item_coords_recursive( item->get_sublist(),
745 icon_x, next_icon_x, next_icon_y, next_text_y, 0);
750 void BC_ListBox::set_is_suggestions(int value)
752 this->is_suggestions = value;
754 void BC_ListBox::set_scroll_repeat()
756 if( scroll_repeat ) return;
758 set_repeat(get_resources()->scroll_repeat);
761 void BC_ListBox::unset_scroll_repeat()
763 if( !scroll_repeat ) return;
765 unset_repeat(get_resources()->scroll_repeat);
768 void BC_ListBox::set_use_button(int value)
770 this->use_button = value;
773 void BC_ListBox::set_justify(int value)
775 this->justify = value;
778 void BC_ListBox::set_allow_drag_column(int value)
780 this->allow_drag_column = value;
783 void BC_ListBox::set_process_drag(int value)
785 this->process_drag = value;
788 void BC_ListBox::set_master_column(int value, int redraw)
790 this->master_column = value;
796 void BC_ListBox::set_search_column(int value)
798 this->search_column = value;
801 int BC_ListBox::get_sort_column()
806 void BC_ListBox::set_sort_column(int value, int redraw)
814 int BC_ListBox::get_sort_order()
819 void BC_ListBox::set_sort_order(int value, int redraw)
828 int BC_ListBox::get_display_mode()
830 return display_format;
833 int BC_ListBox::get_yposition()
838 int BC_ListBox::get_xposition()
843 int BC_ListBox::get_highlighted_item()
845 return highlighted_item;
849 int BC_ListBox::get_item_x(BC_ListBoxItem *item)
851 switch( display_format ) {
853 case LISTBOX_ICON_LIST:
854 return item->text_x - xposition + 2;
856 case LISTBOX_ICONS_PACKED:
857 return item->icon_x - xposition + 2;
862 int BC_ListBox::get_item_y(BC_ListBoxItem *item)
864 switch( display_format ) {
866 case LISTBOX_ICON_LIST:
867 return item->text_y - yposition + title_h + 2;
869 case LISTBOX_ICONS_PACKED:
870 return item->icon_y - yposition + 2;
875 int BC_ListBox::get_item_w(BC_ListBoxItem *item)
877 switch( display_format ) {
879 case LISTBOX_ICON_LIST: {
880 return get_text_w(item) + 2 * LISTBOX_MARGIN; }
882 case LISTBOX_ICONS_PACKED: {
884 get_icon_mask(item, x, y, w, h);
886 get_text_mask(item, x, y, w, h);
889 return icon_position == ICON_LEFT ? icon_w + text_w :
890 icon_w > text_w ? icon_w : text_w;
896 int BC_ListBox::get_item_h(BC_ListBoxItem *item)
898 switch( display_format ) {
900 case LISTBOX_ICON_LIST:
901 return get_text_h(item);
903 case LISTBOX_ICONS_PACKED: {
905 get_icon_mask(item, x, y, w, h);
907 get_text_mask(item, x, y, w, h);
910 return icon_position != ICON_LEFT ? icon_h + text_h :
911 icon_h > text_h ? icon_h : text_h; }
917 int BC_ListBox::get_icon_x(BC_ListBoxItem *item)
919 return get_item_x(item) + ICON_MARGIN;
922 int BC_ListBox::get_icon_y(BC_ListBoxItem *item)
924 return get_item_y(item) + ICON_MARGIN;
927 int BC_ListBox::get_icon_w(BC_ListBoxItem *item)
929 return item->get_icon_w() + 2*ICON_MARGIN;
932 int BC_ListBox::get_icon_h(BC_ListBoxItem *item)
934 return item->get_icon_h() + 2*ICON_MARGIN;
937 int BC_ListBox::get_text_w(BC_ListBoxItem *item)
939 int w = item->get_text_w();
940 if( w < 0 ) item->set_text_w(w = get_text_width(MEDIUMFONT, item->get_text()));
944 int BC_ListBox::get_text_h(BC_ListBoxItem *item)
946 int h = item->get_text_h();
947 if( h < 0 ) item->set_text_h(h = get_text_height(MEDIUMFONT, item->get_text()));
951 int BC_ListBox::get_baseline(BC_ListBoxItem *item)
953 int b = item->get_baseline();
954 if( b < 0 ) item->set_baseline(b = get_text_ascent(MEDIUMFONT));
958 int BC_ListBox::get_items_width()
960 switch( display_format ) {
962 return get_column_offset(columns);
964 case LISTBOX_ICONS_PACKED: {
966 for( int i=0; i<columns; ++i ) {
967 for( int j=0; j<data[i].total; ++j ) {
969 BC_ListBoxItem *item = data[i].values[j];
972 get_icon_mask(item, x, y, w, h);
973 if( x1 + w > widest ) widest = x1 + w;
975 if( icon_position == ICON_LEFT )
978 get_text_mask(item, x, y, w, h);
979 if( x1 + w > widest ) widest = x1 + w;
983 case LISTBOX_ICON_LIST:
984 return get_column_offset(columns);
989 int BC_ListBox::get_items_height(ArrayList<BC_ListBoxItem*> *data, int columns,
1000 for( int j=0; j<(data?data[master_column].total:0); ++j ) {
1002 BC_ListBoxItem *item = data[master_column].values[j];
1004 switch( display_format ) {
1006 get_text_mask(item, x, y, w, h);
1008 // Descend into sublist
1009 if( item->sublist_active() )
1010 get_items_height(item->get_sublist(), item->get_columns(), result);
1013 case LISTBOX_ICONS_PACKED:
1014 case LISTBOX_ICON_LIST:
1015 get_icon_mask(item, x, y, w, h);
1016 if( y + h + yposition > highest ) highest = y + h + yposition;
1018 get_text_mask(item, x, y, w, h);
1019 if( y + h + yposition > highest ) highest = y + h + yposition;
1024 if( display_format == LISTBOX_TEXT && top_level ) {
1025 highest = LISTBOX_MARGIN + *result;
1031 int BC_ListBox::set_yposition(int position, int draw_items)
1033 this->yposition = position;
1035 this->draw_items(1);
1040 int BC_ListBox::set_xposition(int position)
1042 this->xposition = position;
1047 int BC_ListBox::is_highlighted()
1049 return list_highlighted;
1052 void BC_ListBox::expand_item(BC_ListBoxItem *item, int expand)
1055 item->expand = expand;
1056 // Collapse sublists if this is collapsed to make it easier to calculate
1058 if( item->get_sublist() )
1059 collapse_recursive(item->get_sublist(), master_column);
1061 // Set everything for autoplacement
1062 set_autoplacement(data, 0, 1);
1067 void BC_ListBox::collapse_recursive(ArrayList<BC_ListBoxItem*> *data,
1070 for( int i=0; i<data[master_column].total; ++i ) {
1071 BC_ListBoxItem *item = data[master_column].values[i];
1072 if( item->sublist_active() ) {
1074 collapse_recursive(item->get_sublist(), master_column);
1079 void BC_ListBox::set_autoplacement(ArrayList<BC_ListBoxItem*> *data,
1083 for( int i=0; i<data[0].total; ++i ) {
1084 for( int j=0; j<columns; ++j ) {
1085 if( do_icons ) data[j].values[i]->autoplace_icon = 1;
1086 if( do_text ) data[j].values[i]->autoplace_text = 1;
1089 BC_ListBoxItem *item = data[master_column].values[i];
1090 if( item->sublist_active() ) {
1091 set_autoplacement(item->get_sublist(), do_icons, do_text);
1097 void BC_ListBox::set_scroll_stretch(int xv, int yv)
1099 if( xv >= 0 ) xscroll_orientation =
1100 !xv ? SCROLL_HORIZ : SCROLL_HORIZ + SCROLL_STRETCH;
1101 if( yv >= 0 ) yscroll_orientation =
1102 !yv ? SCROLL_VERT : SCROLL_VERT + SCROLL_STRETCH;
1105 int BC_ListBox::get_yscroll_x()
1108 return popup_w - get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w();
1110 return get_x() + popup_w -
1111 get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w();
1114 int BC_ListBox::get_yscroll_y()
1116 return is_popup ? 0 : get_y();
1119 int BC_ListBox::get_yscroll_height()
1121 return popup_h - (need_xscroll ?
1122 get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h() :
1126 int BC_ListBox::get_xscroll_x()
1128 return is_popup ? 0 : get_x();
1131 int BC_ListBox::get_xscroll_y()
1133 return (is_popup ? popup_h : get_y() + popup_h) -
1134 get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h();
1137 int BC_ListBox::get_xscroll_width()
1139 return popup_w - (need_yscroll ?
1140 get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w() : 0);
1143 int BC_ListBox::get_column_offset(int column)
1146 while( column > 0 ) {
1148 column_width[--column] :
1149 default_column_width[--column];
1154 void BC_ListBox::column_width_boundaries()
1156 if( column_width ) {
1157 for( int i=0; i<columns; ++i ) {
1158 if( column_width[i] < MIN_COLUMN_WIDTH )
1159 column_width[i] = MIN_COLUMN_WIDTH;
1163 for( int i=0; i<columns; ++i ) {
1164 if( default_column_width[i] < MIN_COLUMN_WIDTH )
1165 default_column_width[i] = MIN_COLUMN_WIDTH;
1170 int BC_ListBox::get_column_width(int column, int clamp_right)
1172 if( column < columns - 1 || !clamp_right )
1173 return column_width ? column_width[column] : default_column_width[column];
1174 return popup_w + xposition - get_column_offset(column);
1177 int BC_ListBox::get_icon_mask(BC_ListBoxItem *item,
1178 int &x, int &y, int &w, int &h)
1180 switch( display_format ) {
1182 case LISTBOX_ICONS_PACKED:
1183 case LISTBOX_ICON_LIST: {
1184 x = get_icon_x(item);
1185 y = get_icon_y(item);
1186 w = get_icon_w(item);
1187 h = get_icon_h(item);
1197 int BC_ListBox::get_text_mask(BC_ListBoxItem *item,
1198 int &x, int &y, int &w, int &h)
1200 x = get_item_x(item);
1201 y = get_item_y(item);
1203 switch( display_format ) {
1204 case LISTBOX_TEXT: {
1205 w = get_text_w(item) + LISTBOX_MARGIN * 2;
1206 h = get_text_h(item);
1209 case LISTBOX_ICONS_PACKED: {
1210 if( icon_position == ICON_LEFT ) {
1211 x += get_icon_w(item);
1212 y += get_icon_h(item) - get_text_h(item);
1215 y += get_icon_h(item);
1219 get_icon_w(item) + ICON_MARGIN * 2 :
1220 get_text_w(item) + ICON_MARGIN * 2 ;
1221 h = get_text_h(item) + ICON_MARGIN * 2;
1223 case LISTBOX_ICON_LIST: {
1224 w = column_width ? column_width[0] : default_column_width[0];
1233 int BC_ListBox::get_item_highlight(ArrayList<BC_ListBoxItem*> *data,
1234 int column, int item)
1236 BC_Resources *resources = get_resources();
1237 if( data[column].values[item]->selected )
1238 return resources->listbox_selected;
1239 if( highlighted_item >= 0 &&
1240 highlighted_ptr == data[master_column].values[item] )
1241 return resources->listbox_highlighted;
1242 return resources->listbox_inactive;
1245 int BC_ListBox::get_item_color(ArrayList<BC_ListBoxItem*> *data,
1246 int column, int item)
1248 int color = data[column].values[item]->color;
1249 if( color == -1 ) color = get_resources()->listbox_text;
1250 if( get_item_highlight(data, column, item) == color )
1255 int BC_ListBox::get_from_column()
1257 return dragged_title;
1260 int BC_ListBox::get_to_column()
1262 return highlighted_title;
1266 BC_ListBoxItem* BC_ListBox::get_selection(int column, int selection_number)
1268 return get_selection_recursive(data,
1273 BC_ListBoxItem* BC_ListBox::get_selection_recursive(ArrayList<BC_ListBoxItem*> *data,
1274 int column, int selection_number)
1276 if( !data ) return 0;
1278 for( int i=0; i<data[master_column].total; ++i ) {
1279 BC_ListBoxItem *item = data[master_column].values[i];
1280 if( item->selected ) {
1281 //printf("BC_ListBox::get_selection_recursive %d\n", __LINE__);
1283 if( selection_number < 0 ) {
1285 return data[column].values[i];
1289 if( item->sublist_active() ) {
1290 BC_ListBoxItem *result = get_selection_recursive(item->get_sublist(),
1293 if( result ) return result;
1301 int BC_ListBox::get_selection_number(int column, int selection_number)
1303 return get_selection_number_recursive(data, column, selection_number);
1306 int BC_ListBox::get_selection_number_recursive(ArrayList<BC_ListBoxItem*> *data,
1307 int column, int selection_number, int *counter)
1310 if( !data ) return 0;
1311 if( !counter ) counter = &temp;
1313 for( int i=0; i<data[master_column].total; ++i ) {
1315 BC_ListBoxItem *item = data[master_column].values[i];
1316 if( item->selected ) {
1318 if( selection_number < 0 ) {
1322 if( item->sublist_active() ) {
1323 int result = get_selection_number_recursive(item->get_sublist(),
1324 column, selection_number, counter);
1325 if( result >= 0 ) return result;
1332 int BC_ListBox::set_selection_mode(int mode)
1334 this->selection_mode = mode;
1338 void BC_ListBox::delete_columns()
1340 if( column_titles ) {
1341 for( int i=0; i<columns; ++i ) {
1342 delete [] column_titles[i];
1344 delete [] column_titles;
1347 if( column_width ) delete [] column_width;
1353 // Need to copy titles so EDL can change
1354 void BC_ListBox::set_columns(const char **column_titles, int *column_width, int columns)
1356 if( (!column_titles && column_width) ||
1357 (column_titles && !column_width) ) {
1358 printf("BC_ListBox::set_columns either column_titles or column_width == NULL but not both.\n");
1363 if( column_titles ) {
1364 this->column_titles = new char*[columns];
1365 for( int i=0; i<columns; ++i ) {
1366 this->column_titles[i] = new char[strlen(column_titles[i]) + 1];
1367 strcpy(this->column_titles[i], column_titles[i]);
1370 if( column_width ) {
1371 this->column_width = new int[columns];
1372 for( int i=0; i<columns; ++i ) {
1373 this->column_width[i] = column_width[i];
1377 this->columns = columns;
1382 int BC_ListBox::update(ArrayList<BC_ListBoxItem*> *data,
1383 const char **column_titles, int *column_widths, int columns,
1384 int xposition, int yposition, int highlighted_number,
1385 int recalc_positions, int draw)
1387 set_columns(column_titles, column_widths, columns);
1389 this->yposition = yposition;
1390 this->xposition = xposition;
1391 this->highlighted_item = highlighted_number;
1392 this->highlighted_ptr = index_to_item(data, highlighted_number, 0);
1394 if( recalc_positions )
1395 set_autoplacement(data, 1, 1);
1397 init_column_width();
1401 update_scrollbars(1);
1407 void BC_ListBox::center_selection()
1409 int selection = get_selection_number(0, 0);
1410 calculate_item_coords();
1411 center_selection(selection);
1415 update_scrollbars(0);
1416 gui->show_window(1);
1420 void BC_ListBox::move_vertical(int pixels)
1424 void BC_ListBox::move_horizontal(int pixels)
1428 int BC_ListBox::select_previous(int skip, BC_ListBoxItem *selected_item, int *counter,
1429 ArrayList<BC_ListBoxItem*> *data, int *got_first, int *got_second)
1432 if( !selected_item )
1433 selected_item = get_selection(0, 0);
1444 got_second = &temp3;
1448 // Scan backwards to item pointer. Then count visible items to get
1449 // destination. No wraparound.
1451 for( int i=data[master_column].total-1; i>=0; --i ) {
1452 BC_ListBoxItem *current_item = data[master_column].values[i];
1453 if( current_item->sublist_active() ) {
1454 int result = select_previous(skip, selected_item, counter,
1455 current_item->get_sublist(), got_first, got_second);
1462 if( (*counter) >= skip ) {
1463 for( int j=0; j<columns; ++j )
1464 data[j].values[i]->selected = 1;
1466 return item_to_index(this->data, current_item);
1470 if( current_item->selected ) {
1471 for( int j=0; j<columns; ++j )
1472 data[j].values[i]->selected = 0;
1479 // Hit top of top level without finding a selected item.
1481 // Select first item in top level and quit
1482 BC_ListBoxItem *current_item;
1484 current_item = data[master_column].values[0];
1486 for( int j=0; j<columns; ++j )
1487 data[j].values[0]->selected = 1;
1489 return item_to_index(this->data, current_item);
1491 } while( top_level && data[master_column].total );
1496 int BC_ListBox::select_next(int skip, BC_ListBoxItem *selected_item, int *counter,
1497 ArrayList<BC_ListBoxItem*> *data, int *got_first, int *got_second)
1500 if( !selected_item )
1501 selected_item = get_selection(0, 0);
1512 got_second = &temp3;
1516 // Scan forwards to currently selected item pointer.
1517 // Then count visible items to get destination. No wraparound.
1519 for( int i=0; i<data[master_column].total; ++i ) {
1520 BC_ListBoxItem *current_item = data[master_column].values[i];
1522 // Select next item once the number items after the currently selected item
1523 // have been passed.
1526 if( (*counter) >= skip ) {
1527 for( int j=0; j<columns; ++j )
1528 data[j].values[i]->selected = 1;
1530 return item_to_index(this->data, current_item);
1534 // Got currently selected item. Deselect it.
1535 if( current_item->selected ) {
1536 for( int j=0; j<columns; ++j )
1537 data[j].values[i]->selected = 0;
1543 // Descend into expanded level
1544 if( current_item->sublist_active() ) {
1545 int result = select_next(skip, selected_item, counter,
1546 current_item->get_sublist(), got_first, got_second);
1553 // Hit bottom of top level without finding the next item.
1555 BC_ListBoxItem *current_item;
1556 // Select first item in top level and quit
1557 if( !(*got_first) ) {
1559 current_item = data[master_column].values[0];
1561 for( int j=0; j<columns; ++j )
1562 data[j].values[0]->selected = 1;
1566 // Select last item in top level and quit
1568 int current_row = data[master_column].total - 1;
1569 current_item = data[master_column].values[current_row];
1571 for( int j=0; j<columns; ++j )
1572 data[j].values[current_row]->selected = 1;
1576 return item_to_index(this->data, current_item);
1578 } while( top_level && data[master_column].total );
1584 void BC_ListBox::clamp_positions()
1586 items_w = get_items_width();
1587 if( xscroll_orientation & SCROLL_STRETCH )
1588 items_w += view_w / 4;
1589 items_h = get_items_height(data, columns);
1590 if( yscroll_orientation & SCROLL_STRETCH )
1591 items_h += view_h / 4;
1593 if( yposition < 0 ) yposition = 0;
1595 if( yposition > items_h - view_h )
1596 yposition = items_h - view_h;
1598 if( yposition < 0 ) yposition = 0;
1600 if( xposition < 0 ) xposition = 0;
1602 if( xposition >= items_w - view_w )
1603 xposition = items_w - view_w;
1605 if( xposition < 0 ) xposition = 0;
1608 int BC_ListBox::center_selection(int selection,
1609 ArrayList<BC_ListBoxItem*> *data, int *counter)
1612 if( !data ) data = this->data;
1613 if( !counter ) counter = &temp;
1615 for( int i=0; i<data[master_column].total; ++i ) {
1619 BC_ListBoxItem *item = data[master_column].values[i];
1620 if( (*counter) == selection ) {
1621 BC_ListBoxItem *top_item = this->data[master_column].values[0];
1622 switch( display_format ) {
1624 case LISTBOX_ICONS_PACKED: {
1625 // Icon is out of window
1626 if( item->icon_y-yposition > view_h-get_text_h(item) ||
1627 item->icon_y-yposition < 0 ) {
1628 yposition = item->icon_y - view_h / 2;
1631 if( data[master_column].values[selection]->icon_x - xposition > view_w ||
1632 data[master_column].values[selection]->icon_x - xposition < 0 ) {
1633 xposition = item->icon_x - view_w / 2;
1637 case LISTBOX_ICON_LIST:
1638 // Text coordinate is out of window
1639 if( item->text_y-yposition > view_h-get_text_h(item) ||
1640 item->text_y-yposition < 0 ) {
1641 yposition = item->text_y - top_item->text_y - view_h / 2;
1644 if( yposition < 0 ) yposition = 0;
1649 if( item->sublist_active() ) {
1650 int result = center_selection(selection, item->get_sublist(), counter);
1651 if( result ) return result;
1657 void BC_ListBox::update_scrollbars(int flush)
1659 int h_needed = items_h = get_items_height(data, columns);
1660 int w_needed = items_w = get_items_width();
1662 // if( columns > 0 && column_width )
1663 // printf("BC_ListBox::update_scrollbars 1 %d %d\n", column_width[columns - 1], w_needed);
1666 if( xposition != xscrollbar->get_value() )
1667 xscrollbar->update_value(xposition);
1669 if( w_needed != xscrollbar->get_length() ||
1670 view_w != xscrollbar->get_handlelength() )
1671 xscrollbar->update_length(w_needed, xposition, view_w, 0);
1675 if( yposition != yscrollbar->get_value() )
1676 yscrollbar->update_value(yposition);
1678 if( h_needed != yscrollbar->get_length() || view_h != yscrollbar->get_handlelength() )
1679 yscrollbar->update_length(h_needed, yposition, view_h, 0);
1682 if( flush ) this->flush();
1685 int BC_ListBox::get_scrollbars()
1687 int h_needed = items_h = get_items_height(data, columns);
1688 int w_needed = items_w = get_items_width();
1691 title_h = get_title_h();
1692 view_h = popup_h - title_h - yS(4);
1693 view_w = popup_w - xS(4);
1695 // Create scrollbars as needed
1696 for( int i=0; i<2; ++i ) {
1697 if( w_needed > view_w ) {
1699 view_h = popup_h - title_h -
1700 get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h() -
1707 if( h_needed > view_h ) {
1710 get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w() -
1718 // Update subwindow size
1719 int new_w = popup_w;
1720 int new_h = popup_h;
1721 if( need_xscroll ) new_h -= get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h();
1722 if( need_yscroll ) new_w -= get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w();
1725 if( new_w != BC_WindowBase::get_w() || new_h != BC_WindowBase::get_h() )
1726 gui->resize_window(new_w, new_h);
1728 BC_WindowBase *destination = (is_popup ? gui : parent_window);
1729 if( need_xscroll ) {
1731 xscrollbar = new BC_ListBoxXScroll(this);
1732 destination->add_subwindow(xscrollbar);
1733 xscrollbar->show_window(0);
1734 xscrollbar->bound_to = this;
1737 xscrollbar->update_length(w_needed, xposition, view_w, flush);
1738 xscrollbar->reposition_window(get_xscroll_x(),
1740 get_xscroll_width());
1744 if( xscrollbar ) delete xscrollbar;
1749 if( need_yscroll ) {
1751 yscrollbar = new BC_ListBoxYScroll(this);
1752 destination->add_subwindow(yscrollbar);
1753 yscrollbar->show_window(0);
1754 yscrollbar->bound_to = this;
1757 yscrollbar->update_length(h_needed, yposition, view_h, flush);
1758 yscrollbar->reposition_window(get_yscroll_x(),
1760 get_yscroll_height());
1764 if( yscrollbar ) delete yscrollbar;
1770 view_w + xS(4) != bg_surface->get_w() ||
1771 view_h + yS(4) != bg_surface->get_h() ) {
1772 if( bg_surface ) delete bg_surface;
1773 bg_surface = new BC_Pixmap(gui, view_w + xS(4), view_h + yS(4));
1781 int BC_ListBox::get_w()
1783 return is_popup ? button_images[0]->get_w() + xS(1) : popup_w;
1785 int BC_ListBox::get_h()
1787 return is_popup ? button_images[0]->get_h() + yS(1) : popup_h;
1789 int BC_ListBox::gui_tooltip(const char *text)
1791 return is_popup && gui ? gui->show_tooltip(text, gui->get_w(),0, -1,-1) : -1;
1794 void BC_ListBox::set_drag_scroll(int value)
1796 allow_drag_scroll = value;
1799 // Test for scrolling by dragging
1801 int BC_ListBox::test_drag_scroll(int cursor_x, int cursor_y)
1804 if( allow_drag_scroll ||
1805 current_operation == SELECT_RECT ) {
1807 int top_boundary = get_title_h();
1809 if( cursor_y < top_boundary ||
1810 cursor_y >= view_h + title_h + LISTBOX_BORDER * 2 ||
1811 cursor_x < LISTBOX_BORDER ||
1812 cursor_x >= view_w + LISTBOX_BORDER ) {
1819 int BC_ListBox::drag_scroll_event()
1821 int top_boundary = get_title_h();
1824 if( get_cursor_y() < top_boundary ) {
1825 yposition -= top_boundary - get_cursor_y();
1829 if( get_cursor_y() >= view_h + title_h + yS(4) ) {
1830 yposition += get_cursor_y() - (view_h + title_h + yS(4));
1834 if( get_cursor_x() < xS(2) ) {
1835 xposition -= xS(2) - get_cursor_x();
1839 if( get_cursor_x() >= view_w + xS(2) ) {
1840 xposition += get_cursor_x() - (view_w + xS(2));
1850 int BC_ListBox::rectangle_scroll_event()
1852 int old_xposition = xposition;
1853 int old_yposition = yposition;
1854 int result = drag_scroll_event();
1857 rect_x1 += old_xposition - xposition;
1858 rect_y1 += old_yposition - yposition;
1859 rect_x2 = get_cursor_x();
1860 rect_y2 = get_cursor_y();
1862 int x1 = MIN(rect_x1, rect_x2);
1863 int x2 = MAX(rect_x1, rect_x2);
1864 int y1 = MIN(rect_y1, rect_y2);
1865 int y2 = MAX(rect_y1, rect_y2);
1867 if( select_rectangle(data, x1, y1, x2, y2) ) {
1868 selection_changed();
1873 update_scrollbars(1);
1878 int BC_ListBox::select_scroll_event()
1880 int result = drag_scroll_event();
1882 highlighted_item = selection_number = get_cursor_item(data,
1883 get_cursor_x(), get_cursor_y(), &highlighted_ptr);
1886 update_scrollbars(1);
1887 selection_changed();
1892 int BC_ListBox::select_rectangle(ArrayList<BC_ListBoxItem*> *data,
1893 int x1, int y1, int x2, int y2)
1896 for( int i=0; i<data[master_column].total; ++i ) {
1897 for( int j=0; j<columns; ++j ) {
1898 BC_ListBoxItem *item = data[j].values[i];
1899 switch( display_format ) {
1901 case LISTBOX_ICONS_PACKED: {
1902 int icon_x, icon_y, icon_w, icon_h;
1903 int text_x, text_y, text_w, text_h;
1904 get_icon_mask(item, icon_x, icon_y, icon_w, icon_h);
1905 get_text_mask(item, text_x, text_y, text_w, text_h);
1907 if( (x2 >= icon_x && x1 < icon_x + icon_w &&
1908 y2 >= icon_y && y1 < icon_y + icon_h) ||
1909 (x2 >= text_x && x1 < text_x + text_w &&
1910 y2 >= text_y && y1 < text_y + text_h) ) {
1911 if( !item->selected ) {
1917 if( item->selected ) {
1924 case LISTBOX_ICON_LIST: {
1927 gui->get_w() - get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w() :
1928 gui->get_w()) && y2 > 0 &&
1929 y1 < gui->get_h() && y2 >= get_item_y(item) &&
1930 y1 < get_item_y(item) + get_item_h(item) ) {
1931 if( !item->selected ) {
1937 if( item->selected ) {
1946 BC_ListBoxItem *item = data[master_column].values[i];
1947 if( item->sublist_active() ) {
1948 result |= select_rectangle(item->get_sublist(),
1955 int BC_ListBox::reposition_item(ArrayList<BC_ListBoxItem*> *data,
1956 int selection_number, int x, int y, int *counter)
1959 if( !counter ) counter = &temp;
1961 for( int i=0; i<data[master_column].total; ++i ) {
1962 BC_ListBoxItem *item = data[master_column].values[i];
1964 if( (*counter) == selection_number ) {
1969 // Not recursive because it's only used for icons
1974 void BC_ListBox::move_selection(ArrayList<BC_ListBoxItem*> *dst,
1975 ArrayList<BC_ListBoxItem*> *src)
1977 for( int i=0; i<src[master_column].total; ) {
1978 BC_ListBoxItem *item = src[master_column].values[i];
1981 if( item->selected ) {
1982 for( int j=0; j<columns; ++j ) {
1983 dst[j].append(src[j].values[i]);
1984 src[j].remove_number(i);
1988 // Descend into sublist
1989 if( item->sublist_active() ) {
1990 move_selection(dst, item->get_sublist());
1996 int BC_ListBox::put_selection(ArrayList<BC_ListBoxItem*> *data,
1997 ArrayList<BC_ListBoxItem*> *src, int destination, int *counter)
2000 if( !counter ) counter = &temp;
2002 if( destination < 0 || destination >= data[master_column].total ) {
2003 for( int j=0; j<columns; ++j ) {
2004 for( int i=0; i<src[j].total; ++i ) {
2005 data[j].append(src[j].values[i]);
2011 for( int i=0; i<data[master_column].total; ++i ) {
2013 if( (*counter) == destination ) {
2014 for( int j=0; j<columns; ++j ) {
2015 for( int k=0; k<src[j].total; ++k ) {
2016 data[j].insert(src[j].values[k], destination + k);
2022 BC_ListBoxItem *item = data[master_column].values[i];
2023 if( item->sublist_active() ) {
2024 if( put_selection(item->get_sublist(), src, destination, counter) )
2033 int BC_ListBox::item_to_index(ArrayList<BC_ListBoxItem*> *data,
2034 BC_ListBoxItem *item, int *counter)
2037 if( !counter ) counter = &temp;
2039 for( int i=0; i<data[master_column].total; ++i ) {
2041 for( int j=0; j<columns; ++j ) {
2042 BC_ListBoxItem *new_item = data[j].values[i];
2043 //printf("BC_ListBox::item_to_index 1 %d %d %p\n", j, i, new_item);
2044 if( new_item == item ) {
2049 BC_ListBoxItem *new_item = data[master_column].values[i];
2050 if( new_item->sublist_active() ) {
2051 if( item_to_index(new_item->get_sublist(), item, counter) >= 0 )
2059 BC_ListBoxItem* BC_ListBox::index_to_item(ArrayList<BC_ListBoxItem*> *data,
2060 int number, int column, int *counter)
2063 if( !counter ) counter = &temp;
2064 for( int i=0; i<data[master_column].total; ++i ) {
2066 if( (*counter) == number ) {
2067 return data[column].values[i];
2069 BC_ListBoxItem *item = data[master_column].values[i];
2070 if( item->sublist_active() ) {
2071 BC_ListBoxItem *result = index_to_item(item->get_sublist(),
2072 number, column, counter);
2073 if( result ) return result;
2079 int BC_ListBox::get_cursor_item(ArrayList<BC_ListBoxItem*> *data, int cursor_x, int cursor_y,
2080 BC_ListBoxItem **item_return, int *counter, int expanded)
2083 if( !data ) return -1;
2084 if( !counter ) counter = &temp;
2086 // Icons are not treed
2087 switch( display_format ) {
2089 case LISTBOX_ICONS_PACKED:
2090 case LISTBOX_ICON_LIST: {
2091 for( int j=data[master_column].total; --j>=0; ) {
2092 int icon_x, icon_y, icon_w, icon_h;
2093 int text_x, text_y, text_w, text_h;
2094 BC_ListBoxItem *item = data[master_column].values[j];
2095 get_icon_mask(item, icon_x, icon_y, icon_w, icon_h);
2096 get_text_mask(item, text_x, text_y, text_w, text_h);
2098 if( (cursor_x >= icon_x && cursor_x < icon_x + icon_w &&
2099 cursor_y >= icon_y && cursor_y < icon_y + icon_h) ||
2100 (cursor_x >= text_x && cursor_x < text_x + text_w &&
2101 cursor_y >= text_y && cursor_y < text_y + text_h) ) {
2102 if( item_return ) (*item_return) = item;
2110 // Cursor is inside items rectangle
2111 if( cursor_x >= 0 &&
2112 cursor_x < (yscrollbar ?
2113 gui->get_w() - get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w() :
2115 // Only clamp y if we're not in a SELECT operation.
2116 (current_operation == BC_ListBox::SELECT ||
2117 (cursor_y > get_title_h() + LISTBOX_BORDER &&
2118 cursor_y < gui->get_h())) ) {
2119 // Search table for cursor obstruction
2120 for( int i=0; i<data[master_column].total; ++i ) {
2121 BC_ListBoxItem *item = data[master_column].values[i];
2124 // Cursor is inside item on current level
2125 if( expanded && item->selectable &&
2126 cursor_y >= get_item_y(item) &&
2127 cursor_y < get_item_y(item) + get_item_h(item) ) {
2128 //printf("BC_ListBox::get_cursor_item %d %d %p\n", master_column, i, item);
2129 if( item_return ) (*item_return) = item;
2130 if( expanded < 0 ) (*counter) = i;
2134 // Descend into sublist
2135 if( item->sublist_active() ) {
2136 if( get_cursor_item(item->get_sublist(),
2137 cursor_x, cursor_y, item_return, counter,
2138 item->get_expand()) >= 0 ) {
2139 if( expanded < 0 ) (*counter) = i;
2152 int BC_ListBox::get_cursor_item_no()
2155 gui->get_relative_cursor(rx, ry);
2156 return get_cursor_item(data, rx, ry, 0, 0);
2159 int BC_ListBox::get_cursor_data_item_no(BC_ListBoxItem **item_return)
2162 gui->get_relative_cursor(rx, ry);
2163 return get_cursor_item(data, rx, ry, item_return, 0, -1);
2166 int BC_ListBox::repeat_event(int64_t duration)
2168 switch( current_operation ) {
2169 // Repeat out of bounds selection
2171 if( duration != get_resources()->scroll_repeat ) break;
2172 return rectangle_scroll_event();
2175 if( duration != get_resources()->scroll_repeat ) break;
2176 if( !drag_scroll_event() ) break;
2179 update_scrollbars(1);
2183 if( duration != get_resources()->scroll_repeat ) break;
2184 return select_scroll_event();
2188 if( duration != get_resources()->tooltip_delay ) break;
2189 if( !button_highlighted || !is_popup ) break;
2190 if( !tooltip_text || !tooltip_text[0] ) break;
2198 int BC_ListBox::cursor_enter_event()
2202 switch( current_operation ) {
2203 // Cursor moved over button, pressed, and exited.
2204 case BUTTON_DOWN_SELECT:
2205 if( top_level->event_win == win ) {
2206 current_operation = BUTTON_DN;
2208 button_highlighted = 1;
2214 // Cursor entered button
2215 if( is_popup && top_level->event_win == win ) {
2216 button_highlighted = 1;
2221 // TODO: Need to get the highlighted column title or item
2222 if( gui && top_level->event_win == gui->win ) {
2223 list_highlighted = 1;
2233 int BC_ListBox::cursor_leave_event()
2235 if( current_operation == COLUMN_DRAG ) return 0;
2238 if( button_highlighted ) {
2239 button_highlighted = 0;
2244 if( list_highlighted ) {
2245 list_highlighted = 0;
2246 highlighted_item = -1;
2247 highlighted_ptr = 0;
2248 highlighted_title = -1;
2249 int redraw_toggles = 0;
2250 for( int i=0; i<expanders.total; ++i )
2251 expanders.values[i]->cursor_leave_event(&redraw_toggles);
2259 int BC_ListBox::get_first_selection(ArrayList<BC_ListBoxItem*> *data, int *result)
2262 if( !result ) result = &temp;
2264 for( int i=0; i<data[master_column].total; ++i ) {
2265 BC_ListBoxItem *item = data[master_column].values[i];
2267 if( item->selected ) return (*result);
2268 if( item->sublist_active() ) {
2269 if( get_first_selection(item->get_sublist(), result) >= 0 )
2276 int BC_ListBox::get_total_items(ArrayList<BC_ListBoxItem*> *data,
2281 if( !result ) result = &temp;
2283 for( int i=0; i<data[master_column].total; ++i ) {
2285 if( data[master_column].values[i]->sublist_active() )
2286 get_total_items(data[master_column].values[i]->get_sublist(),
2295 int BC_ListBox::get_last_selection(ArrayList<BC_ListBoxItem*> *data,
2305 for( int i=data[master_column].total-1; i>=0; --i ) {
2306 BC_ListBoxItem *item = data[master_column].values[i];
2308 if( item->selected ) {
2310 return get_total_items(data, 0, master_column) - (*result) /* - 1 */;
2315 if( item->sublist_active() ) {
2316 if( get_last_selection(item->get_sublist(), result) >= 0 ) {
2318 return get_total_items(data, 0, master_column) - (*result) /* - 1 */;
2327 void BC_ListBox::select_range(ArrayList<BC_ListBoxItem*> *data,
2328 int start, int end, int *current)
2331 if( !current ) current = &temp;
2333 for( int i=0; i<data[master_column].total; ++i ) {
2335 if( (*current) >= start && (*current) < end ) {
2336 for( int j=0; j<columns; ++j )
2337 data[j].values[i]->selected = 1;
2339 BC_ListBoxItem *item = data[master_column].values[i];
2340 if( item->sublist_active() )
2341 select_range(item->get_sublist(), start, end, current);
2346 // Fill items between current selection and new selection
2347 int BC_ListBox::expand_selection(int button_press, int selection_number)
2349 int old_selection_start = selection_start;
2350 int old_selection_end = selection_end;
2352 // printf("BC_ListBox::expand_selection %d %d\n",
2353 // selection_center,
2354 // selection_number);
2356 // Calculate the range to select based on selection_center and selection_number
2357 if( selection_number < selection_center ) {
2358 selection_start = selection_number;
2361 selection_end = selection_number + 1;
2364 //printf("BC_ListBox::expand_selection %d %d %d %d\n", old_selection_start, old_selection_end, selection_start, selection_end);
2365 // Recurse through all the items and select the desired range
2366 select_range(data, selection_start, selection_end);
2369 return (old_selection_start != selection_start ||
2370 old_selection_end != selection_end);
2373 int BC_ListBox::toggle_item_selection(ArrayList<BC_ListBoxItem*> *data,
2374 int selection_number, int *counter)
2377 if( !counter ) counter = &temp;
2379 for( int i=0; i<data[master_column].total; ++i ) {
2380 BC_ListBoxItem *item = data[master_column].values[i];
2382 if( (*counter) == selection_number ) {
2383 // Get new value for selection
2384 int selected = !item->selected;
2386 for( int j=0; j<columns; ++j )
2387 data[j].values[i]->selected = selected;
2391 // Descend into sublist
2392 if( item->sublist_active() ) {
2393 if( toggle_item_selection(item->get_sublist(),
2394 selection_number, counter) )
2403 void BC_ListBox::set_all_selected(ArrayList<BC_ListBoxItem*> *data, int value)
2405 for( int i=0; i<data[master_column].total; ++i ) {
2406 for( int j=0; j<columns; ++j ) {
2407 BC_ListBoxItem *item = data[j].values[i];
2408 item->selected = value;
2410 BC_ListBoxItem *item = data[master_column].values[i];
2411 if( item->get_sublist() ) {
2412 set_all_selected(item->get_sublist(), value);
2417 void BC_ListBox::set_selected(ArrayList<BC_ListBoxItem*> *data,
2418 int item_number, int value, int *counter)
2421 if( !counter ) counter = &temp;
2422 for( int i=0; i<data[master_column].total&&(*counter)!=item_number; ++i ) {
2424 if( (*counter) == item_number ) {
2425 for( int j=0; j<columns; ++j ) {
2426 BC_ListBoxItem *item = data[j].values[i];
2427 item->selected = value;
2432 BC_ListBoxItem *item = data[master_column].values[i];
2433 if( item->sublist_active() ) {
2434 set_selected(item->get_sublist(), item_number, value, counter);
2439 int BC_ListBox::update_selection(ArrayList<BC_ListBoxItem*> *data,
2440 int selection_number, int *counter)
2444 if( !counter ) counter = &temp;
2446 for( int i=0; i<data[master_column].total; ++i ) {
2447 BC_ListBoxItem *item = data[master_column].values[i];
2449 if( (*counter) == selection_number && !item->selected ) {
2451 for( int j=0; j<columns; ++j )
2452 data[j].values[i]->selected = 1;
2455 if( (*counter) != selection_number && item->selected ) {
2457 for( int j=0; j<columns; ++j )
2458 data[j].values[i]->selected = 0;
2460 if( item->sublist_active() )
2461 result |= update_selection(item->get_sublist(),
2468 void BC_ListBox::promote_selections(ArrayList<BC_ListBoxItem*> *data,
2469 int old_value, int new_value)
2471 for( int i=0; i<data[master_column].total; ++i ) {
2472 for( int j=0; j<columns; ++j ) {
2473 BC_ListBoxItem *item = data[j].values[i];
2474 if( item->selected == old_value ) item->selected = new_value;
2476 BC_ListBoxItem *item = data[master_column].values[i];
2477 if( item->sublist_active() )
2478 promote_selections(item->get_sublist(), old_value, new_value);
2482 int BC_ListBox::focus_out_event()
2488 int BC_ListBox::button_press_event()
2491 BC_ListBoxItem *current_item = 0;
2493 int do_selection_change = 0;
2494 const int debug = 0;
2497 if( debug ) printf("BC_ListBox::button_press_event %d this=%p event_win=%p %p %p %p\n",
2498 __LINE__, this, (void*)top_level->event_win,
2499 (void*)(gui ? gui->win : 0), (void*)win, (void*)parent_window->win);
2501 // Pressed in button
2502 if( is_popup && top_level->event_win == win ) {
2503 if( debug ) printf("BC_ListBox::button_press_event %d\n", __LINE__);
2504 current_operation = BUTTON_DN;
2508 if( !active && !disabled ) {
2509 top_level->deactivate();
2516 // Pressed in scrollbar
2517 if( (xscrollbar && top_level->event_win == xscrollbar->win) ||
2518 (yscrollbar && top_level->event_win == yscrollbar->win) ) {
2519 if( debug ) printf("BC_ListBox::button_press_event %d\n", __LINE__);
2524 if( gui && top_level->event_win == gui->win ) {
2525 if( debug ) printf("BC_ListBox::button_press_event %d\n", __LINE__);
2527 // Activate list items
2528 // If it is a suggestion popup, it is visible without being active
2530 if( debug ) printf("BC_ListBox::button_press_event %d\n", __LINE__);
2531 if( !is_suggestions ) top_level->deactivate();
2532 if( debug ) printf("BC_ListBox::button_press_event %d\n", __LINE__);
2534 if( debug ) printf("BC_ListBox::button_press_event %d\n", __LINE__);
2537 if( current_operation != NO_OPERATION ) {
2538 switch( current_operation ) {
2541 return drag_stop_event();
2545 // Wheel mouse pressed
2546 if( get_buttonpress() == 4 ) {
2547 if( current_operation == NO_OPERATION ) {
2548 current_operation = WHEEL;
2550 set_yposition(yposition - gui->get_h() / 10, 0);
2552 update_scrollbars(0);
2553 highlighted_ptr = 0;
2554 highlighted_item = get_cursor_item(data,
2555 top_level->cursor_x, top_level->cursor_y,
2563 if( get_buttonpress() == 5 ) {
2564 if( current_operation == NO_OPERATION ) {
2565 current_operation = WHEEL;
2567 set_yposition(yposition + gui->get_h() / 10, 0);
2569 update_scrollbars(0);
2570 highlighted_ptr = 0;
2571 highlighted_item = get_cursor_item(data,
2572 top_level->cursor_x, top_level->cursor_y,
2580 // Pressed over column title division
2581 if( test_column_divisions(gui->get_cursor_x(),
2582 gui->get_cursor_y(),
2584 drag_cursor_x = gui->get_cursor_x() + xposition;
2586 drag_column_w = column_width[highlighted_division - 1];
2588 drag_column_w = default_column_width[highlighted_division - 1];
2590 current_operation = DRAG_DIVISION;
2594 // Pressed in column title
2595 if( test_column_titles(gui->get_cursor_x(), gui->get_cursor_y()) ) {
2596 current_operation = COLUMN_DN;
2597 button_highlighted = 0;
2598 list_highlighted = 1;
2603 // Pressed in expander
2604 if( test_expanders() ) {
2605 current_operation = EXPAND_DN;
2606 // Need to redraw items because of alpha
2611 // Pressed over item
2612 if( (selection_number = get_cursor_item(data,
2613 gui->get_cursor_x(), gui->get_cursor_y(),
2614 ¤t_item)) >= 0 ) {
2615 if( debug ) printf("BC_ListBox::button_press_event %d\n", __LINE__);
2617 // Get item button was pressed over
2618 selection_number2 = selection_number1;
2619 selection_number1 = selection_number;
2621 selection_start = -1;
2625 // Multiple item selection is possible
2626 if( selection_mode == LISTBOX_MULTIPLE &&
2627 (ctrl_down() || shift_down() || current_item->selected) ) {
2628 // Expand text selection.
2629 // Fill items between selected region and current item.
2631 (display_format == LISTBOX_TEXT ||
2632 display_format == LISTBOX_ICON_LIST) ) {
2633 // Get first item selected
2634 selection_start = get_first_selection(data);
2635 // Get last item selected
2636 selection_end = get_last_selection(data);
2637 // Get center of selected region
2638 if( selection_end > selection_start ) {
2639 selection_center = (selection_end + selection_start) >> 1;
2642 selection_center = selection_number;
2644 // Deselect everything.
2645 set_all_selected(data, 0);
2646 // Select just the items
2647 expand_selection(1, selection_number);
2650 // Toggle a single item on or off
2651 else if( ctrl_down() ) {
2652 toggle_item_selection(data, selection_number);
2653 new_value = current_item->selected;
2656 // Select single item
2658 if( !current_item->selected || (get_buttonpress() == 1 && !new_value) ) {
2659 set_all_selected(data, 0);
2660 set_selected(data, selection_number, 1);
2666 current_operation = SELECT;
2667 highlighted_item = selection_number;
2668 highlighted_ptr = current_item;
2669 button_highlighted = 0;
2670 list_highlighted = 1;
2673 do_selection_change = 1;
2677 // Pressed over nothing. Start rectangle selection.
2679 if( get_buttonpress() == 1 &&
2680 selection_mode == LISTBOX_MULTIPLE ) {
2681 if( !shift_down() ) {
2682 // Deselect all and redraw if anything was selected
2683 if( get_selection_number(0, 0) >= 0 ) {
2684 set_all_selected(data, 0);
2686 do_selection_change = 1;
2691 // Promote selections to protect from a rectangle selection
2692 promote_selections(data, 1, 2);
2695 // Start rectangle selection
2696 current_operation = SELECT_RECT;
2697 rect_x1 = rect_x2 = get_cursor_x();
2698 rect_y1 = rect_y2 = get_cursor_y();
2706 // Suggestion box is not active but visible, so lie to get it to deactivate
2707 if( is_popup && (active || (is_suggestions && gui)) ) {
2709 if( debug ) printf("BC_ListBox::button_press_event %d\n", __LINE__);
2715 if( do_selection_change ) selection_changed();
2716 if( debug ) printf("BC_ListBox::button_press_event %d %d\n", __LINE__, result);
2721 int BC_ListBox::button_release_event()
2726 unset_scroll_repeat();
2728 //printf("BC_ListBox::button_release_event 1 %d\n", current_operation);
2729 switch( current_operation ) {
2731 current_operation = NO_OPERATION;
2736 current_operation = NO_OPERATION;
2740 // Release item selection
2741 case BUTTON_DOWN_SELECT:
2743 //printf("BC_ListBox::button_release_event 10\n");
2744 current_operation = NO_OPERATION;
2746 selection_number1 = selection_number = get_cursor_item_no();
2747 //printf("BC_ListBox::button_release_event %d %d\n", selection_number2, selection_number1);
2752 if( selection_number >= 0 ) {
2757 // Second button release outside button
2758 if( button_releases > 1 ) {
2763 if( top_level->get_double_click() &&
2764 selection_number2 == selection_number1 &&
2765 selection_number2 >= 0 && selection_number1 >= 0 ) {
2775 // Demote selections from rectangle selection
2776 promote_selections(data, 2, 1);
2779 // Hide rectangle overlay
2781 current_operation = NO_OPERATION;
2785 // Release popup button
2788 current_operation = NO_OPERATION;
2792 // Second button release inside button
2793 if( button_releases > 1 ) {
2800 current_operation = NO_OPERATION;
2801 // Update the sort column and the sort order for the user only if the existing
2802 // sort column is valid.
2803 if( sort_column >= 0 ) {
2804 // Invert order only if column is the same
2805 if( highlighted_title == sort_column )
2806 sort_order = sort_order == SORT_ASCENDING ?
2807 SORT_DESCENDING : SORT_ASCENDING;
2808 // Set the new sort column
2809 sort_column = highlighted_title;
2810 if( !sort_order_event() ) {
2815 // Sorting not enabled. Redraw the title state.
2823 int redraw_toggles = 0;
2824 for( int i=0; i<expanders.total&&!result; ++i ) {
2825 if( expanders.values[i]->button_release_event(&redraw_toggles) ) {
2829 // Need to redraw items because of alpha
2830 if( redraw_toggles ) draw_items(1);
2831 current_operation = NO_OPERATION;
2835 // Can't default to NO_OPERATION because it may be used in a drag event.
2840 if( do_event ) handle_event();
2842 //printf("BC_ListBox::button_release_event %d %d\n", __LINE__, get_window_lock());
2846 int BC_ListBox::get_title_h()
2848 if( display_format == LISTBOX_TEXT ||
2849 display_format == LISTBOX_ICON_LIST )
2850 return column_titles ? column_bg[0]->get_h() : 0;
2854 void BC_ListBox::reset_cursor(int new_cursor)
2857 if( gui->get_cursor() != new_cursor ) {
2858 gui->set_cursor(new_cursor, 0, 0);
2862 if( get_cursor() != new_cursor ) {
2863 set_cursor(new_cursor, 0, 0);
2867 int BC_ListBox::test_column_divisions(int cursor_x, int cursor_y, int &new_cursor)
2869 if( gui && column_titles &&
2870 cursor_y >= 0 && cursor_y < get_title_h() &&
2871 cursor_x >= 0 && cursor_x < gui->get_w() ) {
2872 for( int i=1; i<columns; ++i ) {
2873 if( cursor_x >= -xposition + get_column_offset(i) - 5 &&
2874 cursor_x < -xposition + get_column_offset(i) +
2875 get_resources()->listbox_title_hotspot ) {
2876 highlighted_item = -1;
2877 highlighted_ptr = 0;
2878 highlighted_division = i;
2879 highlighted_title = -1;
2880 list_highlighted = 1;
2881 new_cursor = HSEPARATE_CURSOR;
2886 highlighted_division = -1;
2890 int BC_ListBox::test_column_titles(int cursor_x, int cursor_y)
2892 if( gui && column_titles &&
2893 cursor_y >= 0 && cursor_y < get_title_h() &&
2894 cursor_x >= 0 && cursor_x < gui->get_w() ) {
2895 for( int i=0; i<columns; ++i ) {
2896 if( cursor_x >= -xposition + get_column_offset(i) &&
2897 (cursor_x < -xposition + get_column_offset(i + 1) ||
2898 i == columns - 1) ) {
2899 highlighted_item = -1;
2900 highlighted_ptr = 0;
2901 highlighted_division = -1;
2902 highlighted_title = i;
2903 list_highlighted = 1;
2908 highlighted_title = -1;
2912 int BC_ListBox::test_expanders()
2914 for( int i=0; i<expanders.total; ++i ) {
2915 if( expanders.values[i]->button_press_event() ) {
2916 current_operation = EXPAND_DN;
2924 int BC_ListBox::cursor_motion_event()
2926 int redraw = 0, result = 0;
2927 int new_cursor = ARROW_CURSOR;
2929 selection_number = -1;
2932 switch( current_operation ) {
2934 // Button pressed and slid off button
2935 if( !cursor_inside() ) {
2936 current_operation = BUTTON_DOWN_SELECT;
2942 case DRAG_DIVISION: {
2943 // int new_w = get_cursor_x() +
2945 // get_column_offset(highlighted_division - 1);
2946 int difference = get_cursor_x() + xposition - drag_cursor_x;
2947 int new_w = drag_column_w + difference;
2949 new_cursor = HSEPARATE_CURSOR;
2951 if( column_width ) {
2952 column_width[highlighted_division - 1] = new_w;
2955 default_column_width[highlighted_division - 1] = new_w;
2958 column_width_boundaries();
2960 // Force update of coords
2961 set_autoplacement(data, 0, 1);
2962 column_resize_event();
2966 update_scrollbars(1);
2971 if( test_drag_scroll(get_cursor_x(), get_cursor_y()) )
2972 set_scroll_repeat();
2974 int old_x1 = MIN(rect_x1, rect_x2);
2975 int old_x2 = MAX(rect_x1, rect_x2);
2976 int old_y1 = MIN(rect_y1, rect_y2);
2977 int old_y2 = MAX(rect_y1, rect_y2);
2979 int new_rect_x2 = get_cursor_x();
2980 int new_rect_y2 = get_cursor_y();
2982 int x1 = MIN(rect_x1, new_rect_x2);
2983 int x2 = MAX(rect_x1, new_rect_x2);
2984 int y1 = MIN(rect_y1, new_rect_y2);
2985 int y2 = MAX(rect_y1, new_rect_y2);
2987 // Adjust rectangle coverage
2988 if( old_x1 != x1 || old_x2 != x2 ||
2989 old_y1 != y1 || old_y2 != y2 ) {
2991 redraw = select_rectangle(data, x1, y1, x2, y2);
2996 //printf("BC_ListBox::cursor_motion_event %d\n", __LINE__);
3001 rect_x2 = get_cursor_x();
3002 rect_y2 = get_cursor_y();
3006 update_scrollbars(1);
3007 selection_changed();
3008 //printf("BC_ListBox::cursor_motion_event %d\n", __LINE__);
3011 if( old_x1 != x1 || old_x2 != x2 ||
3012 old_y1 != y1 || old_y2 != y2 ) {
3013 //printf("BC_ListBox::cursor_motion_event %d\n", __LINE__);
3021 int old_highlighted_item = highlighted_item;
3023 if( test_drag_scroll(get_cursor_x(), get_cursor_y()) )
3024 set_scroll_repeat();
3026 highlighted_item = selection_number = get_cursor_item(data,
3027 get_cursor_x(), get_cursor_y(), &highlighted_ptr);
3030 // Deselect all items and select just the one we're over
3031 if( selection_number >= 0 && !allow_drag &&
3032 ((!shift_down() && !ctrl_down()) ||
3033 selection_mode == LISTBOX_SINGLE) ) {
3034 redraw = update_selection(data, selection_number);
3037 // Expand multiple selection
3038 if( selection_mode == LISTBOX_MULTIPLE &&
3039 (shift_down() || ctrl_down()) ) {
3040 // Expand selected region in text mode centered around initial range
3041 if( (display_format == LISTBOX_TEXT ||
3042 display_format == LISTBOX_ICON_LIST) &&
3044 // Select just the items
3045 redraw = expand_selection(0, selection_number);
3047 // Set the one item we're over to the selection value determined in
3048 // button_press_event.
3050 set_selected(data, selection_number, new_value);
3054 if( highlighted_item != old_highlighted_item ) {
3057 update_scrollbars(1);
3058 //printf("BC_ListBox::cursor_motion_event %d %d\n", highlighted_item, old_highlighted_item);
3059 selection_changed();
3063 case BUTTON_DOWN_SELECT:
3064 // Went back into button area
3065 if( cursor_inside() ) {
3066 current_operation = BUTTON_DN;
3071 // Went into item area
3073 int cursor_x = 0, cursor_y = 0;
3074 translate_coordinates(top_level->event_win, gui->win,
3075 top_level->cursor_x, top_level->cursor_y,
3076 &cursor_x, &cursor_y);
3077 int old_highlighted_item = highlighted_item;
3078 highlighted_item = selection_number = get_cursor_item(data,
3083 if( highlighted_item != old_highlighted_item ) {
3084 update_selection(data, selection_number);
3086 selection_changed();
3092 int redraw_toggles = 0;
3093 for( int i=0; i<expanders.total&&!result; ++i ) {
3094 result = expanders.values[i]->cursor_motion_event(
3097 if( redraw_toggles ) {
3098 // Need to redraw items because of the alpha
3103 case NO_OPERATION: {
3104 int cursor_x = get_cursor_x(), cursor_y = get_cursor_y();
3105 if( gui && top_level->event_win == gui->win ) {
3106 int old_highlighted_title = highlighted_title;
3107 int old_list_highlighted = list_highlighted;
3108 int old_highlighted_item = highlighted_item;
3109 int redraw_titles = 0;
3110 int redraw_border = 0;
3111 int redraw_items = 0;
3112 int redraw_toggles = 0;
3115 // Test if cursor moved over a title division
3116 test_column_divisions(cursor_x, cursor_y, new_cursor);
3118 // Test if cursor moved over a title
3119 if( highlighted_division < 0 ) {
3120 test_column_titles(cursor_x, cursor_y);
3123 // Test if cursor moved over expander
3124 if( highlighted_division < 0 && highlighted_title < 0 &&
3125 (display_format == LISTBOX_TEXT ||
3126 display_format == LISTBOX_ICON_LIST) ) {
3127 for( int i=0; i<expanders.total; ++i ) {
3128 expanders.values[i]->cursor_motion_event(
3131 //printf("BC_ListBox::cursor_motion_event %d\n", redraw_toggles);
3134 // Test if cursor moved over an item
3135 if( highlighted_division < 0 && highlighted_title < 0 ) {
3136 highlighted_item = get_cursor_item(data,
3143 // Clear title highlighting if moved over division
3144 if( old_highlighted_title != highlighted_title ) {
3148 // Highlight list border
3149 if( old_list_highlighted != list_highlighted ) {
3153 // Moved out of item area
3154 if( old_highlighted_item != highlighted_item ) {
3155 if( !mouse_over_event(highlighted_item) )
3159 //printf("BC_ListBox::cursor_motion_event 1 %d\n", highlighted_item);
3161 // Change cursor to title division adjustment
3162 reset_cursor(new_cursor);
3164 if( redraw_items ) {
3172 if( redraw_toggles )
3176 if( redraw_items || redraw_titles ||
3177 redraw_border || redraw_toggles ) {
3184 if( !result && list_highlighted ) {
3185 list_highlighted = 0;
3186 highlighted_item = -1;
3187 highlighted_ptr = 0;
3188 highlighted_title = -1;
3189 highlighted_division = -1;
3199 int BC_ListBox::drag_start_event()
3201 switch( current_operation ) {
3203 if( expander_active() ) break;
3204 if( gui && gui->is_event_win() && allow_drag ) {
3205 BC_ListBoxItem *item_return = 0;
3206 selection_number = get_cursor_item(data,
3207 top_level->cursor_x,
3208 top_level->cursor_y,
3211 if( selection_number >= 0 ) {
3213 get_abs_cursor(cx, cy);
3214 if( item_return->icon_vframe ) {
3215 drag_popup = new BC_DragWindow(this,
3216 item_return->icon_vframe, cx, cy);
3219 if( item_return->icon ) {
3220 drag_popup = new BC_DragWindow(this,
3221 item_return->icon, cx, cy);
3224 drag_popup = new BC_DragWindow(this,
3225 drag_icon_vframe, cx, cy);
3227 current_operation = DRAG_ITEM;
3228 // require shift down for scrolling
3229 if( allow_drag < 0 && shift_down() )
3230 set_scroll_repeat();
3237 if( gui && gui->is_event_win() && allow_drag_column ) {
3239 get_abs_cursor(cx, cy);
3240 cx -= drag_column_icon_vframe->get_w() / 2,
3241 cy -= drag_column_icon_vframe->get_h() / 2;
3242 drag_popup = new BC_DragWindow(this,
3243 drag_column_icon_vframe, cx, cy);
3244 dragged_title = highlighted_title;
3245 current_operation = COLUMN_DRAG;
3255 int BC_ListBox::drag_motion_event()
3257 //printf("BC_ListBox::drag_motion_event 1 %d\n", current_operation);
3258 switch( current_operation ) {
3261 int new_highlighted_item = -1;
3262 BC_ListBoxItem *new_highlighted_ptr = 0;
3263 new_highlighted_item = get_cursor_item(data,
3264 top_level->cursor_x, top_level->cursor_y,
3265 &new_highlighted_ptr);
3267 if( new_highlighted_item != highlighted_item ) {
3271 // Always update highlighted value for drag_stop
3272 highlighted_item = new_highlighted_item;
3273 highlighted_ptr = new_highlighted_ptr;
3274 //printf("BC_ListBox::drag_motion_event 1 %p\n", highlighted_ptr);
3278 update_scrollbars(1);
3281 return drag_popup->cursor_motion_event(); }
3284 int old_highlighted_title = highlighted_title;
3285 test_column_titles(get_cursor_x(), get_cursor_y());
3286 if( old_highlighted_title != highlighted_title ) {
3289 return drag_popup->cursor_motion_event(); }
3295 int BC_ListBox::drag_stop_event()
3298 unset_scroll_repeat();
3299 switch( current_operation ) {
3301 // Inside window boundary
3302 if( top_level->cursor_x > 0 &&
3303 top_level->cursor_x < gui->get_w() - drag_popup->get_w() / 2 &&
3304 top_level->cursor_y > 0 &&
3305 top_level->cursor_y < gui->get_h() - drag_popup->get_h() / 2 ) {
3309 if( display_format == LISTBOX_ICONS ||
3310 display_format == LISTBOX_ICONS_PACKED ) {
3311 reposition_item(data,
3313 top_level->cursor_x - drag_popup->get_w() / 2 -
3314 LISTBOX_MARGIN - xS(2) + xposition,
3315 top_level->cursor_y - drag_popup->get_h() / 2 -
3316 LISTBOX_MARGIN - yS(2) + yposition);
3320 if( process_drag ) {
3321 // Move selected items from data to temporary
3322 ArrayList<BC_ListBoxItem*> *src_items =
3323 new ArrayList<BC_ListBoxItem*>[columns];
3324 move_selection(src_items, data);
3326 int destination = highlighted_item = item_to_index(data,
3328 // Insert items from temporary to data
3329 put_selection(data, src_items, destination);
3331 delete [] src_items;
3332 set_autoplacement(data, 0, 1);
3338 drag_popup->drag_failure_event();
3343 if( dragged_title != highlighted_title ) {
3344 if( highlighted_title >= 0 ) {
3345 if( !move_column_event() ) draw_titles(1);
3348 drag_popup->drag_failure_event();
3354 current_operation = NO_OPERATION;
3364 BC_DragWindow* BC_ListBox::get_drag_popup()
3369 int BC_ListBox::translation_event()
3371 if( is_popup && gui ) {
3372 int new_x = gui->get_x() +
3373 (top_level->last_translate_x - top_level->prev_x -
3374 BC_DisplayInfo::get_left_border());
3375 int new_y = gui->get_y() +
3376 (top_level->last_translate_y - top_level->prev_y -
3377 BC_DisplayInfo::get_top_border());
3379 gui->reposition_window(new_x, new_y);
3385 int BC_ListBox::reposition_window(int x, int y, int w, int h, int flush)
3389 if( h != -1 ) popup_h = h;
3390 //printf("BC_ListBox::reposition_window %d %d\n", popup_w, popup_h);
3394 xscrollbar->reposition_window(get_xscroll_x(),
3396 get_xscroll_width());
3398 yscrollbar->reposition_window(get_yscroll_x(),
3400 get_yscroll_height());
3404 BC_WindowBase::reposition_window(x, y, w, h);
3410 int BC_ListBox::deactivate()
3413 // printf("BC_ListBox::deactivate %d this=%p gui=%p active=%d\n",
3414 // __LINE__, this, gui, active);
3417 //printf("BC_ListBox::deactivate %d this=%p gui=%p\n", __LINE__, this, gui);
3419 delete gui; gui = 0;
3424 highlighted_item = -1;
3425 highlighted_ptr = 0;
3428 //printf("BC_ListBox::deactivate %d this=%p\n", __LINE__, this);
3430 top_level->active_subwindow = 0;
3436 int BC_ListBox::activate(int take_focus)
3438 if( active ) return 0;
3441 set_active_subwindow(this);
3442 button_releases = 0;
3443 if( !is_popup || gui ) return 0;
3444 int wx = get_x(), wy = get_y() + get_h();
3445 if( justify == LISTBOX_RIGHT ) wx += get_w() - popup_w;
3448 XTranslateCoordinates(top_level->display,
3449 parent_window->win, top_level->rootwin,
3450 wx, wy, &abs_x, &abs_y, &xwin);
3451 if( x <= 0 ) x = xS(2);
3452 if( y <= 0 ) y = yS(2);
3453 return activate(abs_x, abs_y);
3456 int BC_ListBox::activate(int x, int y, int w, int h)
3458 if( !is_popup || gui ) return 0;
3460 if( w != -1 ) popup_w = w;
3461 if( h != -1 ) popup_h = h;
3463 if( y + popup_h > top_level->get_root_h(0) )
3464 y -= get_h() + popup_h;
3465 add_subwindow(gui = new BC_Popup(this,
3466 x, y, popup_w, popup_h, -1, 0, 0));
3468 gui->show_window(1);
3472 int BC_ListBox::is_active()
3477 int BC_ListBox::expander_active()
3479 for( int i=0; i<expanders.total; ++i ) {
3480 if( expanders.values[i]->value ) return 1;
3485 int BC_ListBox::keypress_event()
3487 if( !active ) return 0;
3489 //printf("BC_ListBox::keypress_event %d\n", __LINE__);
3491 int result = 0, redraw = 0;
3492 int view_items = last_in_view - first_in_view + 1;
3493 if( view_items <= 0 ) view_items = view_h / get_text_height(MEDIUMFONT);
3494 int new_item = -1, new_selection = -1;
3496 switch( top_level->get_keypress() ) {
3499 top_level->deactivate();
3501 // If user is manipulating popup with keyboard, don't pass on event.
3503 //printf("BC_ListBox::keypress_event %d %p\n", __LINE__, get_selection(0, 0));
3504 if( top_level->get_keypress() == RETURN )
3506 //printf("BC_ListBox::keypress_event %d %p\n", __LINE__, get_selection(0, 0));
3514 new_selection = new_item = select_previous(0);
3516 //printf("BC_ListBox::keypress_event 1 %d\n", new_item);
3517 if( new_item >= 0 ) {
3518 center_selection(new_item);
3526 new_selection = new_item = select_next(0);
3528 if( new_item >= 0 ) {
3529 center_selection(new_item);
3537 new_selection = new_item = select_previous(view_items - 1);
3539 if( new_item >= 0 ) {
3540 center_selection(new_item);
3548 new_selection = new_item = select_next(view_items - 1);
3550 if( new_item >= 0 ) {
3551 center_selection(new_item);
3559 xposition -= xS(10);
3565 xposition += xS(10);
3577 if( show_query && !ctrl_down() ) {
3578 int query_len = strlen(query);
3579 if( query_len < (int)sizeof(query)-1 &&
3580 top_level->get_keypress() > 30 &&
3581 top_level->get_keypress() < 127 ) {
3582 query[query_len++] = top_level->get_keypress();
3583 query[query_len] = 0;
3584 new_selection = query_list();
3587 if( top_level->get_keypress() == BACKSPACE ) {
3588 if( query_len > 0 ) query[--query_len] = 0;
3589 new_selection = query_list();
3592 show_tooltip(query);
3604 update_scrollbars(1);
3607 //printf("BC_ListBox::keypress_event %d new_selection=%d\n", __LINE__, new_selection);
3608 if( new_selection >= 0 && !is_suggestions ) {
3609 //printf("BC_ListBox::keypress_event %d\n", __LINE__);
3610 selection_changed();
3611 //printf("BC_ListBox::keypress_event %d\n", __LINE__);
3618 BC_Pixmap* BC_ListBox::get_bg_surface()
3624 void BC_ListBox::draw_background()
3626 if( !bg_draw ) return;
3628 // White background pixmap
3629 set_color(top_level->get_resources()->listbox_inactive);
3630 draw_box(0, 0, bg_surface->get_w(), bg_surface->get_h(), bg_surface);
3632 // Optional heroine pixmap
3634 bg_surface->draw_pixmap(bg_pixmap,
3635 bg_surface->get_w() - top_level->get_resources()->listbox_bg->get_w(),
3639 void BC_ListBox::clear_listbox(int x, int y, int w, int h)
3641 gui->draw_pixmap(bg_surface, x, y, w, h, x, y - title_h);
3644 void BC_ListBox::update_format(int display_format, int redraw)
3646 this->display_format = display_format;
3647 packed_icons = display_format == LISTBOX_ICONS_PACKED ? 1 : 0;
3648 xposition = 0; yposition = 0;
3649 if( redraw && gui ) draw_items(1, 1);
3652 int BC_ListBox::get_format()
3654 return display_format;
3659 int BC_ListBox::draw_items(int flush, int draw_bg)
3662 BC_Resources *resources = get_resources();
3664 //dump(data, columns);
3666 // Calculate items width
3667 calculate_item_coords();
3668 // Create and destroy scrollbars as needed
3671 if( bg_draw ) this->bg_draw = 1;
3677 if( display_format == LISTBOX_ICONS ||
3678 display_format == LISTBOX_ICONS_PACKED ) {
3679 clear_listbox(2, 2 + title_h, view_w, view_h);
3681 set_font(MEDIUMFONT);
3682 for( int i=0; i<data[master_column].size(); ++i ) {
3683 BC_ListBoxItem *item = data[master_column].get(i);
3684 if( get_item_x(item) >= -get_item_w(item) &&
3685 get_item_x(item) < view_w &&
3686 get_item_y(item) >= -get_item_h(item) + title_h &&
3687 get_item_y(item) < view_h + title_h ) {
3688 item->set_in_view(1);
3689 if( first_in_view < 0 ) first_in_view = i;
3691 int item_color = get_item_highlight(data, 0, i);
3692 int icon_x, icon_y, icon_w, icon_h;
3693 int text_x, text_y, text_w, text_h;
3696 get_icon_mask(item, icon_x, icon_y, icon_w, icon_h);
3697 get_text_mask(item, text_x, text_y, text_w, text_h);
3699 if( item_color != resources->listbox_inactive ) {
3700 gui->set_color(BLACK);
3701 gui->draw_rectangle(icon_x, icon_y, icon_w, icon_h);
3702 gui->set_color(item_color);
3703 gui->draw_box(icon_x + 1, icon_y + 1, icon_w - 2, icon_h - 2);
3704 gui->set_color(BLACK);
3705 gui->draw_rectangle(text_x, text_y, text_w, text_h);
3706 gui->set_color(item_color);
3707 gui->draw_box(text_x + 1, text_y + 1, text_w - 2, text_h - 2);
3709 if( icon_position == ICON_LEFT )
3710 gui->draw_box(text_x - 1, text_y + 1, 2, text_h - 2);
3712 if( icon_position == ICON_TOP )
3713 gui->draw_line(text_x + 1, text_y, text_x + icon_w - 2, text_y);
3714 if( text_x + text_w < icon_x + icon_w ) {
3715 gui->set_color(BLACK);
3716 gui->draw_line(text_x + text_w, icon_y + icon_h,
3717 icon_x + icon_w, icon_y + icon_h);
3721 gui->set_color(get_item_color(data, 0, i));
3722 VFrame *vicon = item->get_vicon_frame();
3724 gui->pixmap->draw_vframe(vicon, icon_x, icon_y);
3725 else if( item->icon )
3726 gui->pixmap->draw_pixmap(item->icon, icon_x, icon_y);
3727 char item_text[BCTEXTLEN];
3728 if( display_format == LISTBOX_ICONS_PACKED )
3729 gui->truncate_text(item_text, item->text, text_w);
3731 strcpy(item_text, item->text);
3732 gui->draw_text(text_x, text_y + get_baseline(item), item_text);
3735 item->set_in_view(0);
3740 // Draw one column at a time so text overruns don't go into the next column
3741 // clear column backgrounds
3742 int current_toggle = 0;
3743 for( int j=0; j<columns; ++j ) {
3744 clear_listbox(LISTBOX_BORDER + get_column_offset(j) - xposition,
3745 LISTBOX_BORDER + title_h,
3746 get_column_width(j, 1),
3748 // Draw rows in the column recursively
3749 draw_text_recursive(data, j, 0, ¤t_toggle);
3752 // Delete excess expanders
3753 while( expanders.total > current_toggle ) {
3754 expanders.remove_object();
3758 // draw user images if available
3760 // Draw titles on top of rows for superposition effect
3763 // Clear garbage from bottom right corner
3764 if( xscrollbar && yscrollbar && is_popup ) {
3765 gui->draw_top_background(parent_window,
3766 popup_w - get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w(),
3767 popup_h - get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h(),
3768 get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w(),
3769 get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h());
3776 if( current_operation == SELECT_RECT )
3786 void BC_ListBox::draw_text_recursive(ArrayList<BC_ListBoxItem*> *data,
3787 int column, int indent, int *current_toggle)
3790 BC_Resources *resources = get_resources();
3792 set_font(MEDIUMFONT);
3795 // Search for a branch and make room for toggle if there is one
3797 for( int i=0; i<data[column].size(); ++i ) {
3798 if( data[column].get(i)->get_sublist() ) {
3799 subindent = BC_WindowBase::get_resources()->listbox_expand[0]->get_w();
3805 row_height = row_ascent = row_descent = 0;
3806 for( int i=0; i<data[column].total; ++i ) {
3807 BC_ListBoxItem *item = data[column].values[i];
3808 int ht = get_text_h(item);
3809 if( ht > row_height ) row_height = ht;
3810 int bl = get_baseline(item);
3811 if( bl > row_ascent ) row_ascent = bl;
3813 if( dt > row_descent ) row_descent = dt;
3816 for( int i=0; i<data[column].size(); ++i ) {
3818 BC_ListBoxItem *item = data[column].values[i];
3819 BC_ListBoxItem *first_item = data[master_column].values[i];
3821 if( get_item_y(item) >= -get_item_h(item) + title_h &&
3822 get_item_y(item) < view_h + title_h ) {
3823 int row_color = get_item_highlight(data, 0, i);
3824 int x, y, w, h, column_width;
3826 get_text_mask(item, x, y, w, h);
3827 column_width = get_column_width(column, 1);
3828 if( x + column_width > view_w + LISTBOX_BORDER * 2 )
3829 column_width = view_w + LISTBOX_BORDER * 2 - x;
3831 if( row_color != resources->listbox_inactive ) {
3832 gui->set_color(row_color);
3833 gui->draw_box(x, y, column_width, h);
3834 gui->set_color(BLACK);
3835 int xx = x + column_width-1;
3836 gui->draw_line(x, y, xx, y);
3838 if( display_format == LISTBOX_ICON_LIST ) {
3839 int ih = get_icon_h(item);
3840 if( ih > hh ) hh = ih;
3843 gui->draw_line(x, yy, xx, yy);
3846 gui->set_color(get_item_color(data, column, i));
3849 if( column == 0 && display_format == LISTBOX_ICON_LIST ) {
3850 int ix = get_icon_x(item), iy = get_icon_y(item);
3851 VFrame *vicon = item->get_vicon_frame();
3853 gui->pixmap->draw_vframe(vicon, ix, iy);
3854 x += vicon->get_w() + ICON_MARGIN;
3856 else if( item->icon ) {
3857 gui->pixmap->draw_pixmap(item->icon, ix, iy);
3858 x += item->icon->get_w() + ICON_MARGIN;
3863 // Indent only applies to first column
3865 x + LISTBOX_BORDER + LISTBOX_MARGIN +
3866 (column == 0 ? indent + subindent : 0),
3867 y + get_baseline(item), item->text);
3868 item->set_in_view(1);
3870 if( first_in_view < 0 ) first_in_view = i;
3875 if( column == 0 && item->get_sublist() && item->get_columns() ) {
3876 // Create new expander
3877 if( *current_toggle >= expanders.total ) {
3878 BC_ListBoxToggle *toggle =
3879 new BC_ListBoxToggle(this, item,
3880 x + LISTBOX_BORDER + LISTBOX_MARGIN + indent, y);
3882 expanders.append(toggle);
3884 // Reposition existing expander
3886 BC_ListBoxToggle *toggle = expanders.values[*current_toggle];
3887 //printf("BC_ListBox::draw_text_recursive 1 %d\n", *current_toggle);
3888 toggle->update(item,
3889 x + LISTBOX_BORDER + LISTBOX_MARGIN + indent, y, 0);
3891 (*current_toggle)++;
3898 item->set_in_view(0);
3900 // Descend into sublist
3901 if( first_item->sublist_active() ) {
3902 draw_text_recursive(first_item->get_sublist(),
3904 indent + LISTBOX_INDENT,
3910 int BC_ListBox::draw_border(int flash)
3912 BC_Resources *resources = top_level->get_resources();
3913 gui->draw_3d_border(0, 0,
3914 view_w + LISTBOX_BORDER * 2, view_h + title_h + LISTBOX_BORDER * 2,
3915 resources->listbox_border1,
3917 resources->listbox_border2_hi : resources->listbox_border2,
3919 resources->listbox_border3_hi : resources->listbox_border3,
3920 resources->listbox_border4);
3929 void BC_ListBox::draw_title(int number)
3931 // Column title background
3932 int image_number = 0;
3933 if( number == highlighted_title ) {
3935 if( current_operation == COLUMN_DN )
3939 gui->draw_3segmenth(get_column_offset(number) - xposition + LISTBOX_BORDER,
3941 get_column_width(number, 1) + get_resources()->listbox_title_overlap,
3942 column_bg[image_number]);
3944 int title_x = -xposition + get_column_offset(number) +
3945 LISTBOX_MARGIN + LISTBOX_BORDER;
3946 title_x += get_resources()->listbox_title_margin;
3948 gui->set_color(get_resources()->listbox_title_color);
3949 gui->draw_text(title_x,
3950 LISTBOX_MARGIN + LISTBOX_BORDER + get_text_ascent(MEDIUMFONT),
3951 column_titles[number]);
3953 // Column sort order
3954 if( number == sort_column ) {
3955 BC_Pixmap *src = sort_order == SORT_ASCENDING ?
3956 column_sort_dn : column_sort_up;
3958 // int column_offset = get_column_offset(number) - xposition + LISTBOX_BORDER;
3959 // int column_width = get_column_width(number, 1);
3960 // int toggle_x = column_offset + column_width - LISTBOX_BORDER;
3961 // if( toggle_x > items_w ) toggle_x = items_w;
3962 // toggle_x -= 5 + src->get_w();
3965 get_text_width(MEDIUMFONT, column_titles[number]) +
3968 gui->draw_pixmap(src,
3970 title_h / 2 - src->get_h() / 2 + LISTBOX_BORDER);
3974 int BC_ListBox::draw_titles(int flash)
3976 if( column_titles &&
3977 (display_format == LISTBOX_TEXT ||
3978 display_format == LISTBOX_ICON_LIST) ) {
3979 //printf("BC_ListBox::draw_titles 1 %d\n", highlighted_title);
3980 for( int i=0; i<columns; ++i ) {
3981 if( i != highlighted_title )
3985 if( highlighted_title >= 0 ) draw_title(highlighted_title);
3995 void BC_ListBox::draw_toggles(int flash)
3997 for( int i=0; i<expanders.total; ++i )
3998 expanders.values[i]->draw(0);
4000 //printf("BC_ListBox::draw_toggles 1 %d\n", flash);
4001 if( flash && expanders.total ) {
4006 int BC_ListBox::draw_rectangle(int flash)
4008 int x1 = MIN(rect_x1, rect_x2);
4009 int x2 = MAX(rect_x1, rect_x2);
4010 int y1 = MIN(rect_y1, rect_y2);
4011 int y2 = MAX(rect_y1, rect_y2);
4013 if( x1 == x2 || y1 == y2 ) return 0;
4016 gui->set_color(WHITE);
4017 gui->draw_rectangle(x1, y1, x2 - x1, y2 - y1);
4027 void BC_ListBox::dump(ArrayList<BC_ListBoxItem*> *data, int columns,
4028 int indent, int master_column)
4031 printf("BC_ListBox::dump 1\n");
4034 for( int i=0; i<data[master_column].total; ++i ) {
4035 for( int k=0; k<indent; ++k )
4037 for( int j=0; j<columns; ++j ) {
4038 BC_ListBoxItem *item = data[j].values[i];
4039 printf("%d,%d,%d=%s ",
4040 item->get_text_x(), item->get_text_y(),
4041 item->autoplace_text, item->get_text());
4045 if( data[master_column].values[i]->get_sublist() ) {
4046 dump(data[master_column].values[i]->get_sublist(),
4047 data[master_column].values[i]->get_columns(),