00001 #include "bcdragwindow.h"
00002 #include "bclistbox.h"
00003 #include "bclistboxitem.h"
00004 #include "bcpixmap.h"
00005 #include "bcresources.h"
00006 #include "bcsignals.h"
00007 #include "clip.h"
00008 #include "cursors.h"
00009 #include "fonts.h"
00010 #include "keys.h"
00011 #include "language.h"
00012 #include "bctimer.h"
00013 #include "vframe.h"
00014
00015 #include <string.h>
00016 #include <unistd.h>
00017
00018
00019
00020
00021 BC_ListBoxYScroll::BC_ListBoxYScroll(BC_ListBox *listbox,
00022 int total_height,
00023 int view_height,
00024 int position)
00025 : BC_ScrollBar(listbox->get_yscroll_x(),
00026 listbox->get_yscroll_y(),
00027 SCROLL_VERT,
00028 listbox->get_yscroll_height(),
00029 total_height,
00030 position,
00031 view_height)
00032 {
00033 this->listbox = listbox;
00034 }
00035
00036 BC_ListBoxYScroll::~BC_ListBoxYScroll()
00037 {
00038 }
00039
00040 int BC_ListBoxYScroll::handle_event()
00041 {
00042 listbox->set_yposition(get_value());
00043 return 1;
00044 }
00045
00046
00047
00048
00049
00050
00051
00052 BC_ListBoxXScroll::BC_ListBoxXScroll(BC_ListBox *listbox,
00053 int total_width,
00054 int view_width,
00055 int position)
00056 : BC_ScrollBar(listbox->get_xscroll_x(),
00057 listbox->get_xscroll_y(),
00058 SCROLL_HORIZ,
00059 listbox->get_xscroll_width(),
00060 total_width,
00061 position,
00062 view_width)
00063 {
00064 this->listbox = listbox;
00065 }
00066
00067 BC_ListBoxXScroll::~BC_ListBoxXScroll()
00068 {
00069 }
00070
00071 int BC_ListBoxXScroll::handle_event()
00072 {
00073 listbox->set_xposition(get_value());
00074 return 1;
00075 }
00076
00077
00078
00079
00080
00081
00082
00083
00084 BC_ListBoxToggle::BC_ListBoxToggle(BC_ListBox *listbox,
00085 BC_ListBoxItem *item,
00086 int x,
00087 int y)
00088 {
00089 this->listbox = listbox;
00090 this->item = item;
00091 this->x = x;
00092 this->y = y;
00093 this->value = item->get_expand();
00094 if(this->value)
00095 state = BC_Toggle::TOGGLE_CHECKED;
00096 else
00097 state = BC_Toggle::TOGGLE_UP;
00098 }
00099
00100 void BC_ListBoxToggle::update(BC_ListBoxItem *item,
00101 int x,
00102 int y,
00103 int flash)
00104 {
00105 this->value = item->get_expand();
00106 this->item = item;
00107 this->x = x;
00108 this->y = y;
00109
00110
00111 switch(state)
00112 {
00113 case TOGGLE_UP:
00114 if(value)
00115 state = TOGGLE_CHECKED;
00116 break;
00117
00118 case TOGGLE_UPHI:
00119 if(value)
00120 state = TOGGLE_CHECKEDHI;
00121 break;
00122
00123 case TOGGLE_CHECKED:
00124 if(!value)
00125 state = TOGGLE_UP;
00126 break;
00127
00128 case TOGGLE_DOWN:
00129 break;
00130
00131 case TOGGLE_CHECKEDHI:
00132 if(!value)
00133 state = TOGGLE_UPHI;
00134 break;
00135
00136 case TOGGLE_DOWN_EXIT:
00137 break;
00138 }
00139
00140
00141 draw(flash);
00142 }
00143
00144 int BC_ListBoxToggle::cursor_motion_event(int *redraw_toggles)
00145 {
00146 int w = listbox->toggle_images[0]->get_w();
00147 int h = listbox->toggle_images[0]->get_h();
00148 int cursor_inside = listbox->get_cursor_x() >= x &&
00149 listbox->get_cursor_x() < x + w &&
00150 listbox->get_cursor_y() >= y &&
00151 listbox->get_cursor_y() < y + h;
00152 int result = 0;
00153
00154 switch(state)
00155 {
00156 case BC_ListBoxToggle::TOGGLE_UPHI:
00157 if(!cursor_inside)
00158 {
00159 state = BC_ListBoxToggle::TOGGLE_UP;
00160 *redraw_toggles = 1;
00161 }
00162 break;
00163
00164 case BC_ListBoxToggle::TOGGLE_CHECKEDHI:
00165 if(!cursor_inside)
00166 {
00167 state = BC_ListBoxToggle::TOGGLE_CHECKED;
00168 *redraw_toggles = 1;
00169 }
00170 break;
00171
00172 case BC_ListBoxToggle::TOGGLE_DOWN:
00173 if(!cursor_inside)
00174 {
00175 state = BC_ListBoxToggle::TOGGLE_DOWN_EXIT;
00176 *redraw_toggles = 1;
00177 }
00178 result = 1;
00179 break;
00180
00181 case BC_ListBoxToggle::TOGGLE_DOWN_EXIT:
00182 if(cursor_inside)
00183 {
00184 state = BC_ListBoxToggle::TOGGLE_DOWN;
00185 *redraw_toggles = 1;
00186 }
00187 result = 1;
00188 break;
00189
00190 default:
00191 if(cursor_inside)
00192 {
00193 if(value)
00194 state = BC_ListBoxToggle::TOGGLE_CHECKEDHI;
00195 else
00196 state = BC_ListBoxToggle::TOGGLE_UPHI;
00197 *redraw_toggles = 1;
00198 }
00199 break;
00200 }
00201 return result;
00202 }
00203
00204 int BC_ListBoxToggle::cursor_leave_event(int *redraw_toggles)
00205 {
00206 if(value)
00207 state = BC_ListBoxToggle::TOGGLE_CHECKED;
00208 else
00209 state = BC_ListBoxToggle::TOGGLE_UP;
00210 }
00211
00212 int BC_ListBoxToggle::button_press_event()
00213 {
00214 int w = listbox->toggle_images[0]->get_w();
00215 int h = listbox->toggle_images[0]->get_h();
00216
00217 if(listbox->gui->get_cursor_x() >= x &&
00218 listbox->gui->get_cursor_x() < x + w &&
00219 listbox->gui->get_cursor_y() >= y &&
00220 listbox->gui->get_cursor_y() < y + h)
00221 {
00222 state = BC_ListBoxToggle::TOGGLE_DOWN;
00223 return 1;
00224 }
00225 return 0;
00226 }
00227
00228 int BC_ListBoxToggle::button_release_event(int *redraw_toggles)
00229 {
00230 int result = 0;
00231 switch(state)
00232 {
00233 case BC_ListBoxToggle::TOGGLE_DOWN:
00234 value = !value;
00235 if(value)
00236 state = BC_ListBoxToggle::TOGGLE_CHECKEDHI;
00237 else
00238 state = BC_ListBoxToggle::TOGGLE_UPHI;
00239 listbox->expand_item(item, value);
00240 result = 1;
00241 break;
00242
00243 case BC_ListBoxToggle::TOGGLE_DOWN_EXIT:
00244 if(value)
00245 state = BC_ListBoxToggle::TOGGLE_CHECKED;
00246 else
00247 state = BC_ListBoxToggle::TOGGLE_UP;
00248 *redraw_toggles = 1;
00249 result = 1;
00250 break;
00251 }
00252 return result;
00253 }
00254
00255 void BC_ListBoxToggle::draw(int flash)
00256 {
00257 if(listbox->gui)
00258 {
00259 int image_number = 0;
00260 int w = listbox->toggle_images[0]->get_w();
00261 int h = listbox->toggle_images[0]->get_h();
00262
00263 switch(state)
00264 {
00265 case BC_ListBoxToggle::TOGGLE_UP: image_number = 0; break;
00266 case BC_ListBoxToggle::TOGGLE_UPHI: image_number = 1; break;
00267 case BC_ListBoxToggle::TOGGLE_CHECKED: image_number = 2; break;
00268 case BC_ListBoxToggle::TOGGLE_DOWN: image_number = 3; break;
00269 case BC_ListBoxToggle::TOGGLE_CHECKEDHI: image_number = 4; break;
00270 case BC_ListBoxToggle::TOGGLE_DOWN_EXIT:
00271 if(value)
00272 image_number = 2;
00273 else
00274 image_number = 0;
00275 break;
00276 }
00277
00278
00279 listbox->gui->draw_pixmap(listbox->toggle_images[image_number],
00280 x,
00281 y);
00282
00283
00284 if(flash)
00285 {
00286 listbox->gui->flash(x, y, w, h);
00287 listbox->gui->flush();
00288 }
00289 }
00290 }
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307 BC_ListBox::BC_ListBox(int x,
00308 int y,
00309 int w,
00310 int h,
00311 int display_format,
00312 ArrayList<BC_ListBoxItem*> *data,
00313 char **column_titles,
00314 int *column_width,
00315 int columns,
00316 int yposition,
00317 int is_popup,
00318 int selection_mode,
00319 int icon_position,
00320 int allow_drag)
00321 : BC_SubWindow(x, y, w, h, -1)
00322 {
00323 justify = LISTBOX_RIGHT;
00324 xposition = 0;
00325 highlighted_item = -1;
00326 highlighted_title = -1;
00327 highlighted_division = -1;
00328 highlighted_ptr = 0;
00329 xscrollbar = 0;
00330 yscrollbar = 0;
00331 current_cursor = ARROW_CURSOR;
00332 gui = 0;
00333 view_h = 0;
00334 view_w = 0;
00335 title_h = 0;
00336 active = 0;
00337 new_value = 0;
00338 need_xscroll = 0;
00339 need_yscroll = 0;
00340 bg_tile = 0;
00341 drag_popup = 0;
00342 selection_number1 = -1;
00343 selection_number2 = -1;
00344 bg_surface = 0;
00345 bg_pixmap = 0;
00346
00347 current_operation = NO_OPERATION;
00348 button_highlighted = 0;
00349
00350 disabled = 0;
00351
00352 list_highlighted = 0;
00353
00354 allow_drag_scroll = 1;
00355 process_drag = 1;
00356
00357 sort_column = -1;
00358 sort_order = 0;
00359
00360 allow_drag_column = 0;
00361 master_column = 0;
00362 search_column = 0;
00363
00364 popup_w = w;
00365 popup_h = h;
00366
00367 for(int i = 0; i < 3; i++)
00368 column_bg[i] = 0;
00369
00370 for(int i = 0; i < 4; i++)
00371 button_images[i] = 0;
00372
00373 for(int i = 0; i < 5; i++)
00374 toggle_images[i] = 0;
00375
00376 column_sort_up = 0;
00377 column_sort_dn = 0;
00378
00379
00380 this->data = data;
00381 this->columns = columns;
00382 this->yposition = yposition;
00383 this->is_popup = is_popup;
00384 this->display_format = display_format;
00385 this->selection_mode = selection_mode;
00386 this->icon_position = icon_position;
00387 this->allow_drag = allow_drag;
00388 this->column_titles = 0;
00389 this->column_width = 0;
00390
00391
00392 if((!column_titles && column_width) ||
00393 (column_titles && !column_width))
00394 {
00395 printf("BC_ListBox::BC_ListBox either column_titles or column_widths == NULL but not both.\n");
00396 }
00397
00398 set_columns(column_titles,
00399 column_width,
00400 columns);
00401
00402
00403
00404 drag_icon_vframe = 0;
00405 drag_column_icon_vframe = 0;
00406
00407
00408
00409
00410
00411 reset_query();
00412
00413 }
00414
00415 BC_ListBox::~BC_ListBox()
00416 {
00417 expanders.remove_all_objects();
00418 if(bg_surface) delete bg_surface;
00419 if(bg_pixmap) delete bg_pixmap;
00420 if(xscrollbar) delete xscrollbar;
00421 if(yscrollbar) delete yscrollbar;
00422 for(int i = 0; i < 3; i++)
00423 if(column_bg[i]) delete column_bg[i];
00424 for(int i = 0; i < 4; i++)
00425 if(button_images[i]) delete button_images[i];
00426 for(int i = 0; i < 5; i++)
00427 if(toggle_images[i]) delete toggle_images[i];
00428 if(column_sort_up) delete column_sort_up;
00429 if(column_sort_dn) delete column_sort_dn;
00430
00431 delete_columns();
00432 if(drag_popup) delete drag_popup;
00433 }
00434
00435 int BC_ListBox::enable()
00436 {
00437 disabled = 0;
00438 draw_button();
00439 return 1;
00440 }
00441
00442 int BC_ListBox::disable()
00443 {
00444 disabled = 1;
00445 draw_button();
00446 return 1;
00447 }
00448
00449 void BC_ListBox::reset_query()
00450 {
00451 query[0] = 0;
00452 }
00453
00454 int BC_ListBox::evaluate_query(int list_item, char *string)
00455 {
00456 return(strcmp(string, data[search_column].values[list_item]->text) <= 0 &&
00457 data[search_column].values[list_item]->searchable);
00458 }
00459
00460 int BC_ListBox::query_list()
00461 {
00462 if(query[0] == 0) return 0;
00463
00464 int done = 0;
00465 int result;
00466 int selection_changed = 0;
00467 int prev_selection = -1;
00468 for(int i = 0; !done && i < data[0].total; i++)
00469 {
00470 if(evaluate_query(i, query))
00471 {
00472 result = i;
00473 done = 1;
00474 }
00475 }
00476
00477 if(done)
00478 {
00479
00480 for(int i = 0; i < data[0].total; i++)
00481 {
00482 for(int j = 0; j < columns; j++)
00483 {
00484 if(data[j].values[i]->selected) prev_selection = i;
00485 data[j].values[i]->selected = 0;
00486 }
00487 }
00488
00489
00490 if(prev_selection != result)
00491 selection_changed = 1;
00492 for(int j = 0; j < columns; j++)
00493 {
00494 data[j].values[result]->selected = 1;
00495 }
00496 center_selection(result);
00497 }
00498
00499 return selection_changed;
00500 }
00501
00502 void BC_ListBox::init_column_width()
00503 {
00504 if(!column_width && data)
00505 {
00506 int widest = 5, w;
00507 for(int i = 0; i < data[0].total; i++)
00508 {
00509 w = get_text_width(MEDIUMFONT, data[0].values[i]->get_text()) + 2 * LISTBOX_MARGIN;
00510 if(w > widest) widest = w;
00511 }
00512 default_column_width[0] = widest;
00513 }
00514 }
00515
00516 int BC_ListBox::initialize()
00517 {
00518 if(is_popup)
00519 {
00520 for(int i = 0; i < 4; i++)
00521 {
00522 button_images[i] = new BC_Pixmap(parent_window,
00523 BC_WindowBase::get_resources()->listbox_button[i],
00524 PIXMAP_ALPHA);
00525 }
00526 w = button_images[0]->get_w();
00527 h = button_images[0]->get_h();
00528
00529 gui = 0;
00530 current_operation = NO_OPERATION;
00531 }
00532 else
00533 {
00534 gui = this;
00535 current_operation = NO_OPERATION;
00536 }
00537
00538 for(int i = 0; i < 3; i++)
00539 {
00540 column_bg[i] = new BC_Pixmap(parent_window,
00541 get_resources()->listbox_column[i],
00542 PIXMAP_ALPHA);
00543 }
00544 for(int i = 0; i < 5; i++)
00545 {
00546 toggle_images[i] = new BC_Pixmap(parent_window,
00547 get_resources()->listbox_expand[i],
00548 PIXMAP_ALPHA);
00549 }
00550
00551 column_sort_up = new BC_Pixmap(parent_window,
00552 BC_WindowBase::get_resources()->listbox_up,
00553 PIXMAP_ALPHA);
00554 column_sort_dn = new BC_Pixmap(parent_window,
00555 BC_WindowBase::get_resources()->listbox_dn,
00556 PIXMAP_ALPHA);
00557
00558
00559 drag_icon_vframe = get_resources()->type_to_icon[ICON_UNKNOWN];
00560 drag_column_icon_vframe = get_resources()->type_to_icon[ICON_COLUMN];
00561
00562
00563
00564
00565
00566
00567 BC_SubWindow::initialize();
00568
00569 init_column_width();
00570
00571 if(top_level->get_resources()->listbox_bg)
00572 bg_pixmap = new BC_Pixmap(this,
00573 get_resources()->listbox_bg,
00574 PIXMAP_OPAQUE);
00575
00576 draw_button();
00577 draw_items(1);
00578 return 0;
00579 }
00580
00581 void BC_ListBox::deactivate_selection()
00582 {
00583 current_operation = NO_OPERATION;
00584 }
00585
00586 int BC_ListBox::draw_button()
00587 {
00588
00589 if(is_popup)
00590 {
00591 int image_number = 0;
00592
00593 draw_top_background(parent_window, 0, 0, w, h);
00594
00595 if(button_highlighted)
00596 image_number = 1;
00597 if(current_operation == BUTTON_DN)
00598 image_number = 2;
00599 if(disabled)
00600 image_number = 3;
00601
00602
00603 pixmap->draw_pixmap(button_images[image_number],
00604 0,
00605 0,
00606 w,
00607 h,
00608 0,
00609 0);
00610 flash();
00611 }
00612 return 0;
00613 }
00614
00615 int BC_ListBox::calculate_item_coords()
00616 {
00617 if(!data) return 0;
00618
00619 int icon_x = 0;
00620 int next_icon_x = 0;
00621 int next_icon_y = 0;
00622 int next_text_y = 0;
00623
00624
00625 int display_format_temp = display_format;
00626
00627
00628
00629
00630 calculate_last_coords_recursive(data,
00631 &icon_x,
00632 &next_icon_x,
00633 &next_icon_y,
00634 &next_text_y,
00635 1);
00636
00637
00638
00639 calculate_item_coords_recursive(data,
00640 &icon_x,
00641 &next_icon_x,
00642 &next_icon_y,
00643 &next_text_y,
00644 1);
00645
00646
00647
00648 display_format = display_format_temp;
00649
00650 return 0;
00651 }
00652
00653 void BC_ListBox::calculate_last_coords_recursive(
00654 ArrayList<BC_ListBoxItem*> *data,
00655 int *icon_x,
00656 int *next_icon_x,
00657 int *next_icon_y,
00658 int *next_text_y,
00659 int top_level)
00660 {
00661 for(int i = 0; i < data[0].total; i++)
00662 {
00663 int current_text_y = 0;
00664 int current_icon_x = 0;
00665 int current_icon_y = 0;
00666 BC_ListBoxItem *item = data[0].values[i];
00667
00668
00669 if(!item->autoplace_text)
00670 {
00671
00672 display_format = LISTBOX_TEXT;
00673 current_text_y = item->text_y +
00674 get_text_height(MEDIUMFONT);
00675 if(current_text_y > *next_text_y)
00676 *next_text_y = current_text_y;
00677
00678
00679 if(item->get_sublist() &&
00680 item->get_columns() &&
00681 item->get_expand())
00682 {
00683 calculate_last_coords_recursive(item->get_sublist(),
00684 icon_x,
00685 next_icon_x,
00686 next_icon_y,
00687 next_text_y,
00688 0);
00689 }
00690 }
00691
00692
00693 if(top_level)
00694 {
00695 BC_ListBoxItem *item = data[master_column].values[i];
00696 if(!item->autoplace_icon)
00697 {
00698 display_format = LISTBOX_ICONS;
00699
00700 current_icon_x = item->icon_x;
00701 if(current_icon_x > *icon_x) *icon_x = current_icon_x;
00702 if(current_icon_x + get_item_w(item) > *next_icon_x)
00703 *next_icon_x = current_icon_x + get_item_w(item);
00704
00705 current_icon_y = item->icon_y + get_item_h(item);
00706 if(current_icon_y > *next_icon_y)
00707 *next_icon_y = current_icon_y;
00708 }
00709 }
00710 }
00711 }
00712
00713
00714 void BC_ListBox::calculate_item_coords_recursive(
00715 ArrayList<BC_ListBoxItem*> *data,
00716 int *icon_x,
00717 int *next_icon_x,
00718 int *next_icon_y,
00719 int *next_text_y,
00720 int top_level)
00721 {
00722
00723
00724
00725
00726
00727 for(int i = 0; i < data[0].total; i++)
00728 {
00729
00730 int total_autoplaced_columns = 0;
00731
00732
00733 if(top_level)
00734 {
00735 BC_ListBoxItem *item = data[master_column].values[i];
00736 if(item->autoplace_icon)
00737 {
00738
00739 display_format = LISTBOX_ICONS;
00740
00741
00742 if(*next_icon_y + get_item_h(item) >= get_h() &&
00743 *next_icon_y > 0)
00744 {
00745 *icon_x = *next_icon_x;
00746 *next_icon_y = 0;
00747 }
00748
00749 if(*icon_x + get_item_w(item) > *next_icon_x)
00750 *next_icon_x = *icon_x + get_item_w(item);
00751
00752
00753 item->set_icon_x(*icon_x);
00754 item->set_icon_y(*next_icon_y);
00755
00756 *next_icon_y += get_item_h(item);
00757 }
00758 }
00759
00760
00761
00762
00763 int next_text_x = 0;
00764 for(int j = 0; j < columns; j++)
00765 {
00766 BC_ListBoxItem *item = data[j].values[i];
00767 if(item->autoplace_text)
00768 {
00769 display_format = LISTBOX_TEXT;
00770 item->set_text_x(next_text_x);
00771 item->set_text_y(*next_text_y);
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781 if(j < columns - 1)
00782 next_text_x += (column_width ?
00783 column_width[j] :
00784 default_column_width[j]);
00785 else
00786
00787 {
00788 int new_w = get_item_w(item);
00789
00790 int *previous_w = (column_width ?
00791 &column_width[j] :
00792 &default_column_width[j]);
00793 if(new_w > *previous_w)
00794 *previous_w = new_w;
00795
00796 }
00797 total_autoplaced_columns++;
00798 }
00799 }
00800
00801
00802 if(total_autoplaced_columns)
00803 {
00804 display_format = LISTBOX_TEXT;
00805 *next_text_y += get_text_height(MEDIUMFONT);
00806 }
00807
00808
00809 BC_ListBoxItem *item = data[master_column].values[i];
00810 if(item->get_sublist() &&
00811 item->get_columns() &&
00812 item->get_expand())
00813 {
00814 calculate_item_coords_recursive(
00815 item->get_sublist(),
00816 icon_x,
00817 next_icon_x,
00818 next_icon_y,
00819 next_text_y,
00820 0);
00821 }
00822 }
00823 }
00824
00825 void BC_ListBox::set_justify(int value)
00826 {
00827 this->justify = value;
00828 }
00829
00830 void BC_ListBox::set_allow_drag_column(int value)
00831 {
00832 this->allow_drag_column = value;
00833 }
00834
00835 void BC_ListBox::set_process_drag(int value)
00836 {
00837 this->process_drag = value;
00838 }
00839
00840 void BC_ListBox::set_master_column(int value, int redraw)
00841 {
00842 this->master_column = value;
00843 if(redraw)
00844 {
00845 draw_items(1);
00846 }
00847 }
00848
00849 void BC_ListBox::set_search_column(int value)
00850 {
00851 this->search_column = value;
00852 }
00853
00854 int BC_ListBox::get_sort_column()
00855 {
00856 return sort_column;
00857 }
00858
00859 void BC_ListBox::set_sort_column(int value, int redraw)
00860 {
00861 sort_column = value;
00862 if(redraw)
00863 {
00864 draw_titles(1);
00865 }
00866 }
00867
00868 int BC_ListBox::get_sort_order()
00869 {
00870 return sort_order;
00871 }
00872
00873 void BC_ListBox::set_sort_order(int value, int redraw)
00874 {
00875 sort_order = value;
00876 if(redraw)
00877 {
00878 draw_titles(1);
00879 }
00880 }
00881
00882
00883
00884
00885
00886 int BC_ListBox::get_display_mode()
00887 {
00888 return display_format;
00889 }
00890
00891 int BC_ListBox::get_yposition()
00892 {
00893 return yposition;
00894 }
00895
00896 int BC_ListBox::get_xposition()
00897 {
00898 return xposition;
00899 }
00900
00901 int BC_ListBox::get_highlighted_item()
00902 {
00903 return highlighted_item;
00904 }
00905
00906
00907 int BC_ListBox::get_item_x(BC_ListBoxItem *item)
00908 {
00909 if(display_format == LISTBOX_TEXT)
00910 return item->text_x - xposition + 2;
00911 else
00912 return item->icon_x - xposition + 2;
00913 }
00914
00915 int BC_ListBox::get_item_y(BC_ListBoxItem *item)
00916 {
00917 int result;
00918 if(display_format == LISTBOX_TEXT)
00919 result = item->text_y - yposition + title_h + 2;
00920 else
00921 result = item->icon_y - yposition + title_h + 2;
00922 return result;
00923 }
00924
00925 int BC_ListBox::get_item_w(BC_ListBoxItem *item)
00926 {
00927 if(display_format == LISTBOX_ICONS)
00928 {
00929 int x, y, w, h;
00930 get_icon_mask(item, x, y, w, h);
00931 int icon_w = w;
00932 get_text_mask(item, x, y, w, h);
00933 int text_w = w;
00934
00935 if(icon_position == ICON_LEFT)
00936 return icon_w + text_w;
00937 else
00938 return (icon_w > text_w) ? icon_w : text_w;
00939 }
00940 else
00941 {
00942 return get_text_width(MEDIUMFONT, item->text) + 2 * LISTBOX_MARGIN;
00943 }
00944 }
00945
00946 int BC_ListBox::get_item_h(BC_ListBoxItem *item)
00947 {
00948 if(display_format == LISTBOX_ICONS)
00949 {
00950 int x, y, w, h;
00951 get_icon_mask(item, x, y, w, h);
00952 int icon_h = h;
00953 get_text_mask(item, x, y, w, h);
00954 int text_h = h;
00955
00956 if(icon_position == ICON_LEFT)
00957 return (icon_h > text_h) ? icon_h : text_h;
00958 else
00959 return icon_h + text_h;
00960 }
00961 else
00962 {
00963 return get_text_height(MEDIUMFONT);
00964 }
00965 return 0;
00966 }
00967
00968
00969 int BC_ListBox::get_icon_w(BC_ListBoxItem *item)
00970 {
00971 BC_Pixmap *icon = item->icon;
00972 if(icon) return icon->get_w();
00973 return 0;
00974 }
00975
00976 int BC_ListBox::get_icon_h(BC_ListBoxItem *item)
00977 {
00978 BC_Pixmap *icon = item->icon;
00979 if(icon) return icon->get_h();
00980 return 0;
00981 }
00982
00983 int BC_ListBox::get_items_width()
00984 {
00985 int widest = 0;
00986
00987 if(display_format == LISTBOX_ICONS)
00988 {
00989 for(int i = 0; i < columns; i++)
00990 {
00991 for(int j = 0; j < data[i].total; j++)
00992 {
00993 int x1, x, y, w, h;
00994 BC_ListBoxItem *item = data[i].values[j];
00995 x1 = item->icon_x;
00996
00997 get_icon_mask(item, x, y, w, h);
00998 if(x1 + w > widest) widest = x1 + w;
00999
01000 if(display_format == LISTBOX_ICONS && icon_position == ICON_LEFT)
01001 x1 += w;
01002
01003 get_text_mask(item, x, y, w, h);
01004 if(x1 + w > widest) widest = x1 + w;
01005 }
01006 }
01007 }
01008 else
01009 if(display_format == LISTBOX_TEXT)
01010 {
01011 return get_column_offset(columns);
01012 }
01013 return widest;
01014 }
01015
01016 int BC_ListBox::get_items_height(ArrayList<BC_ListBoxItem*> *data,
01017 int columns,
01018 int *result)
01019 {
01020 int temp = 0;
01021 int top_level = 0;
01022 int highest = 0;
01023 if(!result)
01024 {
01025 result = &temp;
01026 top_level = 1;
01027 }
01028
01029
01030
01031
01032
01033 for(int j = 0; j < (data ? data[master_column].total : 0); j++)
01034 {
01035 int y1, x, y, w, h;
01036 BC_ListBoxItem *item = data[master_column].values[j];
01037
01038 if(display_format == LISTBOX_ICONS)
01039 {
01040 get_icon_mask(item, x, y, w, h);
01041 if(y + h + yposition > highest) highest = y + h + yposition;
01042
01043 get_text_mask(item, x, y, w, h);
01044 if(y + h + yposition > highest) highest = y + h + yposition;
01045 }
01046 else
01047 {
01048 get_text_mask(item, x, y, w, h);
01049 *result += h;
01050
01051
01052
01053 if(item->get_sublist() &&
01054 item->get_expand())
01055 {
01056 get_items_height(item->get_sublist(),
01057 item->get_columns(),
01058 result);
01059 }
01060 }
01061 }
01062 if(display_format == LISTBOX_TEXT && top_level)
01063 {
01064 highest = LISTBOX_MARGIN + *result;
01065 }
01066
01067
01068 return highest;
01069 }
01070
01071 int BC_ListBox::set_yposition(int position, int draw_items)
01072 {
01073 this->yposition = position;
01074 if(draw_items)
01075 {
01076 this->draw_items(1);
01077 }
01078 return 0;
01079 }
01080
01081 int BC_ListBox::set_xposition(int position)
01082 {
01083 this->xposition = position;
01084 draw_items(1);
01085 return 0;
01086 }
01087
01088 void BC_ListBox::expand_item(BC_ListBoxItem *item, int expand)
01089 {
01090 if(item)
01091 {
01092 item->expand = expand;
01093
01094
01095 if(item->get_sublist())
01096 collapse_recursive(item->get_sublist(), master_column);
01097
01098
01099
01100
01101 set_autoplacement(data, 0, 1);
01102
01103 draw_items(1);
01104 }
01105 }
01106
01107 void BC_ListBox::collapse_recursive(ArrayList<BC_ListBoxItem*> *data,
01108 int master_column)
01109 {
01110 for(int i = 0; i < data[master_column].total; i++)
01111 {
01112 BC_ListBoxItem *item = data[master_column].values[i];
01113 if(item->get_sublist() && item->expand)
01114 {
01115 item->expand = 0;
01116 collapse_recursive(item->get_sublist(), master_column);
01117 }
01118 }
01119 }
01120
01121 void BC_ListBox::set_autoplacement(ArrayList<BC_ListBoxItem*> *data,
01122 int do_icons,
01123 int do_text)
01124 {
01125 for(int i = 0; i < data[0].total; i++)
01126 {
01127 for(int j = 0; j < columns; j++)
01128 {
01129 if(do_icons) data[j].values[i]->autoplace_icon = 1;
01130 if(do_text) data[j].values[i]->autoplace_text = 1;
01131 }
01132
01133 BC_ListBoxItem *item = data[master_column].values[i];
01134 if(item->get_sublist())
01135 {
01136 set_autoplacement(item->get_sublist(), do_icons, do_text);
01137 }
01138 }
01139 }
01140
01141
01142
01143 int BC_ListBox::get_w()
01144 {
01145 if(is_popup)
01146 return BCPOPUPLISTBOX_W;
01147 else
01148 return popup_w;
01149 }
01150
01151 int BC_ListBox::get_h()
01152 {
01153 if(is_popup)
01154 return BCPOPUPLISTBOX_H;
01155 else
01156 return popup_h;
01157 }
01158
01159 int BC_ListBox::get_yscroll_x()
01160 {
01161 if(is_popup)
01162 return popup_w - get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w();
01163 else
01164 return get_x() +
01165 popup_w -
01166 get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w();
01167 }
01168
01169 int BC_ListBox::get_yscroll_y()
01170 {
01171 if(is_popup)
01172 return 0;
01173 else
01174 return get_y();
01175 }
01176
01177 int BC_ListBox::get_yscroll_height()
01178 {
01179 return popup_h - (need_xscroll ?
01180 get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h() :
01181 0);
01182 }
01183
01184 int BC_ListBox::get_xscroll_x()
01185 {
01186 if(is_popup)
01187 return 0;
01188 else
01189 return get_x();
01190 }
01191
01192 int BC_ListBox::get_xscroll_y()
01193 {
01194 if(is_popup)
01195 return popup_h -
01196 get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h();
01197 else
01198 return get_y() +
01199 popup_h -
01200 get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h();
01201 }
01202
01203 int BC_ListBox::get_xscroll_width()
01204 {
01205 return popup_w - (need_yscroll ?
01206 get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w() :
01207 0);
01208 }
01209
01210 int BC_ListBox::get_column_offset(int column)
01211 {
01212 int x = 0;
01213 while(column > 0)
01214 {
01215 x += column_width ?
01216 column_width[--column] :
01217 default_column_width[--column];
01218 }
01219 return x;
01220 }
01221
01222 void BC_ListBox::column_width_boundaries()
01223 {
01224 if(column_width)
01225 {
01226 for(int i = 0; i < columns; i++)
01227 {
01228 if(column_width[i] < MIN_COLUMN_WIDTH) column_width[i] = MIN_COLUMN_WIDTH;
01229 }
01230 }
01231 else
01232 {
01233 for(int i = 0; i < columns; i++)
01234 {
01235 if(default_column_width[i] < MIN_COLUMN_WIDTH) default_column_width[i] = MIN_COLUMN_WIDTH;
01236 }
01237 }
01238 }
01239
01240 int BC_ListBox::get_column_width(int column, int clamp_right)
01241 {
01242 if(column < columns - 1 || !clamp_right)
01243 return column_width ?
01244 column_width[column] :
01245 default_column_width[column];
01246 else
01247 return popup_w +
01248 xposition -
01249 get_column_offset(column);
01250 }
01251
01252 int BC_ListBox::get_icon_mask(BC_ListBoxItem *item,
01253 int &x,
01254 int &y,
01255 int &w,
01256 int &h)
01257 {
01258 if(display_format == LISTBOX_ICONS)
01259 {
01260 x = get_item_x(item);
01261 y = get_item_y(item);
01262 w = get_icon_w(item) + ICON_MARGIN * 2;
01263 h = get_icon_h(item) + ICON_MARGIN * 2;
01264 }
01265 else
01266 if(display_format == LISTBOX_TEXT)
01267 {
01268 x = y = w = h = 0;
01269 }
01270 return 0;
01271 }
01272
01273 int BC_ListBox::get_text_mask(BC_ListBoxItem *item,
01274 int &x,
01275 int &y,
01276 int &w,
01277 int &h)
01278 {
01279 x = get_item_x(item);
01280 y = get_item_y(item);
01281
01282 if(display_format == LISTBOX_ICONS)
01283 {
01284 if(icon_position == ICON_LEFT)
01285 {
01286 x += get_icon_w(item) + ICON_MARGIN * 2;
01287 y += get_icon_h(item) - get_text_height(MEDIUMFONT);
01288 }
01289 else
01290 {
01291 y += get_icon_h(item) + ICON_MARGIN;
01292 }
01293
01294 w = get_text_width(MEDIUMFONT, item->text) + ICON_MARGIN * 2;
01295 h = get_text_height(MEDIUMFONT) + ICON_MARGIN * 2;
01296 }
01297 else
01298 if(display_format == LISTBOX_TEXT)
01299 {
01300 w = get_text_width(MEDIUMFONT, item->text) + LISTBOX_MARGIN * 2;
01301 h = get_text_height(MEDIUMFONT);
01302 }
01303 return 0;
01304 }
01305
01306 int BC_ListBox::get_item_highlight(ArrayList<BC_ListBoxItem*> *data,
01307 int column,
01308 int item)
01309 {
01310 BC_Resources *resources = get_resources();
01311 if(data[column].values[item]->selected)
01312 return resources->listbox_selected;
01313 else
01314 if(highlighted_item >= 0 &&
01315 highlighted_ptr == data[master_column].values[item])
01316 return resources->listbox_highlighted;
01317 else
01318 return resources->listbox_inactive;
01319 }
01320
01321 int BC_ListBox::get_item_color(ArrayList<BC_ListBoxItem*> *data,
01322 int column,
01323 int item)
01324 {
01325 int color = data[column].values[item]->color;
01326 if(color == -1) color = get_resources()->listbox_text;
01327 if(get_item_highlight(data, column, item) == color)
01328 return BLACK;
01329 else
01330 return color;
01331 }
01332
01333 int BC_ListBox::get_from_column()
01334 {
01335 return dragged_title;
01336 }
01337
01338 int BC_ListBox::get_to_column()
01339 {
01340 return highlighted_title;
01341 }
01342
01343
01344 BC_ListBoxItem* BC_ListBox::get_selection(int column,
01345 int selection_number)
01346 {
01347 return get_selection_recursive(data,
01348 column,
01349 selection_number);
01350 }
01351
01352 BC_ListBoxItem* BC_ListBox::get_selection_recursive(
01353 ArrayList<BC_ListBoxItem*> *data,
01354 int column,
01355 int selection_number)
01356 {
01357 if(!data) return 0;
01358
01359 for(int i = 0; i < data[master_column].total; i++)
01360 {
01361 BC_ListBoxItem *item = data[master_column].values[i];
01362 if(item->selected)
01363 {
01364 selection_number--;
01365 if(selection_number < 0)
01366 {
01367
01368 return data[column].values[i];
01369 }
01370 }
01371
01372 if(item->get_sublist())
01373 {
01374 BC_ListBoxItem *result = get_selection_recursive(item->get_sublist(),
01375 column,
01376 selection_number);
01377 if(result) return result;
01378 }
01379 }
01380 return 0;
01381 }
01382
01383
01384 int BC_ListBox::get_selection_number(int column,
01385 int selection_number)
01386 {
01387 return get_selection_number_recursive(data,
01388 column,
01389 selection_number);
01390 }
01391
01392 int BC_ListBox::get_selection_number_recursive(
01393 ArrayList<BC_ListBoxItem*> *data,
01394 int column,
01395 int selection_number,
01396 int *counter)
01397 {
01398 int temp = -1;
01399 if(!data) return 0;
01400 if(!counter) counter = &temp;
01401
01402 for(int i = 0; i < data[master_column].total; i++)
01403 {
01404 (*counter)++;
01405 BC_ListBoxItem *item = data[master_column].values[i];
01406 if(item->selected)
01407 {
01408 selection_number--;
01409 if(selection_number < 0)
01410 {
01411 return (*counter);
01412 }
01413 }
01414 if(item->get_sublist())
01415 {
01416 int result = get_selection_number_recursive(
01417 item->get_sublist(),
01418 column,
01419 selection_number,
01420 counter);
01421 if(result >= 0) return result;
01422 }
01423 }
01424 return -1;
01425 }
01426
01427
01428 int BC_ListBox::set_selection_mode(int mode)
01429 {
01430 this->selection_mode = mode;
01431 return 0;
01432 }
01433
01434 void BC_ListBox::delete_columns()
01435 {
01436 if(column_titles)
01437 {
01438 for(int i = 0; i < columns; i++)
01439 {
01440 delete [] column_titles[i];
01441 }
01442 delete [] column_titles;
01443 }
01444
01445 if(column_width) delete [] column_width;
01446
01447 column_titles = 0;
01448 column_width = 0;
01449 }
01450
01451
01452 void BC_ListBox::set_columns(char **column_titles,
01453 int *column_width,
01454 int columns)
01455 {
01456 if((!column_titles && column_width) ||
01457 (column_titles && !column_width))
01458 {
01459 printf("BC_ListBox::set_columns either column_titles or column_width == NULL but not both.\n");
01460 return;
01461 }
01462
01463
01464 delete_columns();
01465
01466 if(column_titles)
01467 {
01468 this->column_titles = new char*[columns];
01469 for(int i = 0; i < columns; i++)
01470 {
01471 this->column_titles[i] = new char[strlen(column_titles[i]) + 1];
01472 strcpy(this->column_titles[i], column_titles[i]);
01473 }
01474 }
01475
01476 if(column_width)
01477 {
01478 this->column_width = new int[columns];
01479 for(int i = 0; i < columns; i++)
01480 {
01481 this->column_width[i] = column_width[i];
01482 }
01483 }
01484
01485 this->columns = columns;
01486
01487 }
01488
01489
01490 int BC_ListBox::update(ArrayList<BC_ListBoxItem*> *data,
01491 char **column_titles,
01492 int *column_widths,
01493 int columns,
01494 int xposition,
01495 int yposition,
01496 int highlighted_number,
01497 int recalc_positions,
01498 int draw)
01499 {
01500 set_columns(column_titles,
01501 column_widths,
01502 columns);
01503
01504 this->data = data;
01505
01506 this->yposition = yposition;
01507 this->xposition = xposition;
01508 this->highlighted_item = highlighted_number;
01509 this->highlighted_ptr = index_to_item(data, highlighted_number, 0);
01510
01511 if(recalc_positions)
01512 set_autoplacement(data, 1, 1);
01513
01514 init_column_width();
01515
01516 if(gui && draw)
01517 {
01518 draw_background();
01519 draw_items(1);
01520 update_scrollbars();
01521 }
01522
01523 return 0;
01524 }
01525
01526 void BC_ListBox::center_selection()
01527 {
01528 int selection = get_selection_number(0, 0);
01529
01530 calculate_item_coords();
01531 center_selection(selection);
01532
01533
01534 if(gui)
01535 {
01536 draw_background();
01537 draw_items(1);
01538 update_scrollbars();
01539 }
01540 }
01541
01542 void BC_ListBox::move_vertical(int pixels)
01543 {
01544 }
01545
01546 void BC_ListBox::move_horizontal(int pixels)
01547 {
01548 }
01549
01550 int BC_ListBox::select_previous(int skip,
01551 BC_ListBoxItem *selected_item,
01552 int *counter,
01553 ArrayList<BC_ListBoxItem*> *data,
01554 int *got_first,
01555 int *got_second)
01556 {
01557 int top_level = 0;
01558 if(!selected_item)
01559 selected_item = get_selection(0, 0);
01560 int temp = -1;
01561 if(!counter)
01562 counter = &temp;
01563 int temp2 = 0;
01564 if(!got_first)
01565 {
01566 got_first = &temp2;
01567 top_level = 1;
01568 }
01569 int temp3 = 0;
01570 if(!got_second)
01571 got_second = &temp3;
01572 if(!data)
01573 data = this->data;
01574 int done = 0;
01575
01576
01577
01578 do
01579 {
01580 for(int i = data[master_column].total - 1; i >= 0; i--)
01581 {
01582 BC_ListBoxItem *current_item = data[master_column].values[i];
01583 if(current_item->get_sublist() &&
01584 current_item->get_expand())
01585 {
01586 int result = select_previous(skip,
01587 selected_item,
01588 counter,
01589 current_item->get_sublist(),
01590 got_first,
01591 got_second);
01592 if(*got_second)
01593 {
01594 return result;
01595 }
01596 }
01597
01598 if(*got_first)
01599 {
01600 (*counter)++;
01601 if((*counter) >= skip)
01602 {
01603 for(int j = 0; j < columns; j++)
01604 data[j].values[i]->selected = 1;
01605 (*got_second) = 1;
01606 return item_to_index(this->data, current_item);
01607 }
01608 }
01609 else
01610 {
01611 if(current_item->selected)
01612 {
01613 for(int j = 0; j < columns; j++)
01614 data[j].values[i]->selected = 0;
01615 (*got_first) = 1;
01616 (*counter)++;
01617 }
01618 }
01619 }
01620
01621
01622 if(top_level && !(*got_first)) (*got_first) = 1;
01623 }while(top_level && data[master_column].total);
01624 return -1;
01625 }
01626
01627 int BC_ListBox::select_next(int skip,
01628 BC_ListBoxItem *selected_item,
01629 int *counter,
01630 ArrayList<BC_ListBoxItem*> *data,
01631 int *got_first,
01632 int *got_second)
01633 {
01634 int top_level = 0;
01635 if(!selected_item)
01636 selected_item = get_selection(0, 0);
01637 int temp = -1;
01638 if(!counter)
01639 counter = &temp;
01640 int temp2 = 0;
01641 if(!got_first)
01642 {
01643 got_first = &temp2;
01644 top_level = 1;
01645 }
01646 int temp3 = 0;
01647 if(!got_second)
01648 got_second = &temp3;
01649 if(!data)
01650 data = this->data;
01651 int done = 0;
01652
01653
01654
01655 do
01656 {
01657 for(int i = 0; i < data[master_column].total; i++)
01658 {
01659 BC_ListBoxItem *current_item = data[master_column].values[i];
01660 if(*got_first)
01661 {
01662 (*counter)++;
01663 if((*counter) >= skip)
01664 {
01665 for(int j = 0; j < columns; j++)
01666 data[j].values[i]->selected = 1;
01667 (*got_second) = 1;
01668 return item_to_index(this->data, current_item);
01669 }
01670 }
01671 else
01672 {
01673 if(current_item->selected)
01674 {
01675 for(int j = 0; j < columns; j++)
01676 data[j].values[i]->selected = 0;
01677 (*got_first) = 1;
01678 (*counter)++;
01679 }
01680 }
01681
01682 if(current_item->get_sublist() &&
01683 current_item->get_expand())
01684 {
01685 int result = select_next(skip,
01686 selected_item,
01687 counter,
01688 current_item->get_sublist(),
01689 got_first,
01690 got_second);
01691 if(*got_second)
01692 {
01693 return result;
01694 }
01695 }
01696 }
01697
01698
01699 if(top_level && !(*got_first)) (*got_first) = 1;
01700 }while(top_level && data[master_column].total);
01701 return -1;
01702 }
01703
01704
01705 void BC_ListBox::clamp_positions()
01706 {
01707 items_w = get_items_width();
01708 items_h = get_items_height(data, columns);
01709
01710 if(yposition < 0) yposition = 0;
01711 else
01712 if(yposition > items_h - view_h)
01713 yposition = items_h - view_h;
01714
01715 if(yposition < 0) yposition = 0;
01716
01717 if(xposition < 0) xposition = 0;
01718 else
01719 if(xposition >= items_w - view_w)
01720 xposition = items_w - view_w;
01721
01722 if(xposition < 0) xposition = 0;
01723 }
01724
01725 int BC_ListBox::center_selection(int selection,
01726 ArrayList<BC_ListBoxItem*> *data,
01727 int *counter)
01728 {
01729 int temp = -1;
01730 if(!data) data = this->data;
01731 if(!counter) counter = &temp;
01732
01733 for(int i = 0; i < data[master_column].total; i++)
01734 {
01735 (*counter)++;
01736
01737
01738 BC_ListBoxItem *item = data[master_column].values[i];
01739 if((*counter) == selection)
01740 {
01741 BC_ListBoxItem *top_item = this->data[master_column].values[0];
01742
01743
01744 if(display_format == LISTBOX_ICONS)
01745 {
01746
01747 if(item->icon_y - yposition >
01748 view_h - get_text_height(MEDIUMFONT) ||
01749 item->icon_y - yposition < 0)
01750 {
01751 yposition = item->icon_y - view_h / 2;
01752 }
01753
01754 if(data[master_column].values[selection]->icon_x - xposition > view_w ||
01755 data[master_column].values[selection]->icon_x - xposition < 0)
01756 {
01757 xposition = item->icon_x - view_w / 2;
01758 }
01759 }
01760 else
01761 if(display_format == LISTBOX_TEXT)
01762 {
01763
01764 if(item->text_y - yposition >
01765 view_h - get_text_height(MEDIUMFONT) ||
01766 item->text_y - yposition < 0)
01767 {
01768 yposition = item->text_y -
01769 top_item->text_y -
01770 view_h / 2;
01771 }
01772 }
01773 return 1;
01774 }
01775
01776
01777 if(item->get_sublist())
01778 {
01779 int result = center_selection(selection,
01780 item->get_sublist(),
01781 counter);
01782 if(result) return result;
01783 }
01784 }
01785 return 0;
01786 }
01787
01788 void BC_ListBox::update_scrollbars()
01789 {
01790 int h_needed = items_h = get_items_height(data, columns);
01791 int w_needed = items_w = get_items_width();
01792
01793
01794
01795
01796 if(xscrollbar)
01797 {
01798 if(xposition != xscrollbar->get_value())
01799 xscrollbar->update_value(xposition);
01800
01801 if(w_needed != xscrollbar->get_length() ||
01802 view_w != xscrollbar->get_handlelength())
01803 xscrollbar->update_length(w_needed, xposition, view_w);
01804 }
01805
01806 if(yscrollbar)
01807 {
01808 if(yposition != yscrollbar->get_value())
01809 yscrollbar->update_value(yposition);
01810
01811 if(h_needed != yscrollbar->get_length() || view_h != yscrollbar->get_handlelength())
01812 yscrollbar->update_length(h_needed, yposition, view_h);
01813 }
01814 }
01815
01816 int BC_ListBox::get_scrollbars()
01817 {
01818 int h_needed = items_h = get_items_height(data, columns);
01819 int w_needed = items_w = get_items_width();
01820
01821
01822
01823 title_h = get_title_h();
01824
01825 view_h = popup_h - title_h - 4;
01826 view_w = popup_w - 4;
01827
01828
01829 for(int i = 0; i < 2; i++)
01830 {
01831 if(w_needed > view_w)
01832 {
01833 need_xscroll = 1;
01834 view_h = popup_h -
01835 title_h -
01836 get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h() -
01837 4;
01838 }
01839 else
01840 {
01841 need_xscroll = 0;
01842 }
01843
01844 if(h_needed > view_h)
01845 {
01846 need_yscroll = 1;
01847 view_w = popup_w -
01848 get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w() -
01849 4;
01850 }
01851 else
01852 {
01853 need_yscroll = 0;
01854 }
01855 }
01856
01857
01858 int new_w = popup_w;
01859 int new_h = popup_h;
01860 if(need_xscroll) new_h -= get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h();
01861 if(need_yscroll) new_w -= get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w();
01862
01863 if(!is_popup)
01864 if(new_w != BC_WindowBase::get_w() || new_h != BC_WindowBase::get_h())
01865 gui->resize_window(new_w, new_h);
01866
01867 BC_WindowBase *destination = (is_popup ? gui : parent_window);
01868 if(need_xscroll)
01869 {
01870 if(!xscrollbar)
01871 {
01872 destination->add_subwindow(xscrollbar =
01873 new BC_ListBoxXScroll(this,
01874 w_needed,
01875 view_w,
01876 xposition));
01877 xscrollbar->bound_to = this;
01878 }
01879 else
01880 {
01881 xscrollbar->update_length(w_needed, xposition, view_w);
01882 xscrollbar->reposition_window(get_xscroll_x(),
01883 get_xscroll_y(),
01884 get_xscroll_width());
01885 }
01886 }
01887 else
01888 {
01889 if(xscrollbar) delete xscrollbar;
01890 xscrollbar = 0;
01891 xposition = 0;
01892 }
01893
01894 if(need_yscroll)
01895 {
01896 if(!yscrollbar)
01897 {
01898 destination->add_subwindow(yscrollbar =
01899 new BC_ListBoxYScroll(this,
01900 h_needed,
01901 view_h,
01902 yposition));
01903 yscrollbar->bound_to = this;
01904 }
01905 else
01906 {
01907 yscrollbar->update_length(h_needed, yposition, view_h);
01908 yscrollbar->reposition_window(get_yscroll_x(),
01909 get_yscroll_y(),
01910 get_yscroll_height());
01911 }
01912 }
01913 else
01914 {
01915 if(yscrollbar) delete yscrollbar;
01916 yscrollbar = 0;
01917 yposition = 0;
01918 }
01919
01920 if(!bg_surface ||
01921 view_w + 4 != bg_surface->get_w() ||
01922 view_h + 4 != bg_surface->get_h())
01923 {
01924 if(bg_surface) delete bg_surface;
01925 bg_surface = new BC_Pixmap(gui, view_w + 4, view_h + 4);
01926 draw_background();
01927 }
01928
01929 return 0;
01930 }
01931
01932
01933
01934 void BC_ListBox::set_drag_scroll(int value)
01935 {
01936 allow_drag_scroll = value;
01937 }
01938
01939
01940
01941
01942 int BC_ListBox::test_drag_scroll(int cursor_x, int cursor_y)
01943 {
01944 int result = 0;
01945 if(allow_drag_scroll ||
01946 current_operation == SELECT_RECT)
01947 {
01948
01949 int top_boundary = get_title_h();
01950
01951 if(cursor_y < top_boundary ||
01952 cursor_y >= view_h + title_h + LISTBOX_BORDER * 2 ||
01953 cursor_x < LISTBOX_BORDER ||
01954 cursor_x >= view_w + LISTBOX_BORDER)
01955 {
01956 result = 1;
01957 }
01958 }
01959 return result;
01960 }
01961
01962 int BC_ListBox::drag_scroll_event()
01963 {
01964 int top_boundary = get_title_h();
01965 int result = 0;
01966
01967 if(get_cursor_y() < top_boundary)
01968 {
01969 yposition -= top_boundary - get_cursor_y();
01970 result = 1;
01971 }
01972 else
01973 if(get_cursor_y() >= view_h + title_h + 4)
01974 {
01975 yposition += get_cursor_y() - (view_h + title_h + 4);
01976 result = 1;
01977 }
01978
01979 if(get_cursor_x() < 2)
01980 {
01981 xposition -= 2 - get_cursor_x();
01982 result = 1;
01983 }
01984 else
01985 if(get_cursor_x() >= view_w + 2)
01986 {
01987 xposition += get_cursor_x() - (view_w + 2);
01988 result = 1;
01989 }
01990 if(result) clamp_positions();
01991 return result;
01992 }
01993
01994 int BC_ListBox::rectangle_scroll_event()
01995 {
01996 int old_xposition = xposition;
01997 int old_yposition = yposition;
01998 int result = drag_scroll_event();
01999
02000 if(result)
02001 {
02002 rect_x1 += old_xposition - xposition;
02003 rect_y1 += old_yposition - yposition;
02004 rect_x2 = get_cursor_x();
02005 rect_y2 = get_cursor_y();
02006
02007 int x1 = MIN(rect_x1, rect_x2);
02008 int x2 = MAX(rect_x1, rect_x2);
02009 int y1 = MIN(rect_y1, rect_y2);
02010 int y2 = MAX(rect_y1, rect_y2);
02011
02012 if(select_rectangle(data,
02013 x1,
02014 y1,
02015 x2,
02016 y2))
02017 {
02018 selection_changed();
02019 }
02020
02021 clamp_positions();
02022 draw_items(1);
02023 update_scrollbars();
02024 }
02025 return result;
02026 }
02027
02028 int BC_ListBox::select_scroll_event()
02029 {
02030 int result = drag_scroll_event();
02031
02032 if(result)
02033 {
02034 highlighted_item = selection_number = get_cursor_item(data,
02035 get_cursor_x(),
02036 get_cursor_y(),
02037 &highlighted_ptr);
02038 clamp_positions();
02039 draw_items(1);
02040 update_scrollbars();
02041 selection_changed();
02042 }
02043 return result;
02044 }
02045
02046 int BC_ListBox::select_rectangle(ArrayList<BC_ListBoxItem*> *data,
02047 int x1,
02048 int y1,
02049 int x2,
02050 int y2)
02051 {
02052 int result = 0;
02053 for(int i = 0; i < data[master_column].total; i++)
02054 {
02055 for(int j = 0; j < columns; j++)
02056 {
02057 BC_ListBoxItem *item = data[j].values[i];
02058 if(display_format == LISTBOX_ICONS)
02059 {
02060 int icon_x, icon_y, icon_w, icon_h;
02061 int text_x, text_y, text_w, text_h;
02062 get_icon_mask(item, icon_x, icon_y, icon_w, icon_h);
02063 get_text_mask(item, text_x, text_y, text_w, text_h);
02064
02065 if((x2 >= icon_x && x1 < icon_x + icon_w &&
02066 y2 >= icon_y && y1 < icon_y + icon_h) ||
02067 (x2 >= text_x && x1 < text_x + text_w &&
02068 y2 >= text_y && y1 < text_y + text_h))
02069 {
02070 if(!item->selected)
02071 {
02072 item->selected = 1;
02073 result = 1;
02074 }
02075 }
02076 else
02077 {
02078 if(item->selected)
02079 {
02080 item->selected = 0;
02081 result = 1;
02082 }
02083 }
02084 }
02085 else
02086 {
02087 if(x2 >= 0 &&
02088 x1 < (yscrollbar ?
02089 gui->get_w() - get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w() :
02090 gui->get_w()) &&
02091 y2 > 0 &&
02092 y1 < gui->get_h() &&
02093 y2 >= get_item_y(item) &&
02094 y1 < get_item_y(item) + get_item_h(item))
02095 {
02096 if(!item->selected)
02097 {
02098 item->selected = 1;
02099 result = 1;
02100 }
02101 }
02102 else
02103 {
02104 if(item->selected)
02105 {
02106 item->selected = 0;
02107 result = 1;
02108 }
02109 }
02110 }
02111 }
02112
02113 BC_ListBoxItem *item = data[master_column].values[i];
02114 if(item->get_sublist() &&
02115 item->get_expand())
02116 result |= select_rectangle(item->get_sublist(),
02117 x1,
02118 y1,
02119 x2,
02120 y2);
02121 }
02122 return result;
02123 }
02124
02125 int BC_ListBox::reposition_item(ArrayList<BC_ListBoxItem*> *data,
02126 int selection_number,
02127 int x,
02128 int y,
02129 int *counter)
02130 {
02131 int temp = -1;
02132 if(!counter) counter = &temp;
02133
02134
02135 for(int i = 0; i < data[master_column].total; i++)
02136 {
02137 BC_ListBoxItem *item = data[master_column].values[i];
02138 (*counter)++;
02139 if((*counter) == selection_number)
02140 {
02141 item->icon_x = x;
02142 item->icon_y = y;
02143 return 1;
02144 }
02145
02146 }
02147 return 0;
02148 }
02149
02150 void BC_ListBox::move_selection(ArrayList<BC_ListBoxItem*> *dst,
02151 ArrayList<BC_ListBoxItem*> *src)
02152 {
02153 for(int i = 0; i < src[master_column].total; i++)
02154 {
02155 BC_ListBoxItem *item = src[master_column].values[i];
02156
02157
02158 if(item->selected)
02159 {
02160 for(int j = 0; j < columns; j++)
02161 {
02162 dst[j].append(src[j].values[i]);
02163 src[j].remove_number(i);
02164 }
02165 }
02166 else
02167
02168 if(item->get_sublist())
02169 {
02170 move_selection(dst,
02171 item->get_sublist());
02172 }
02173 }
02174 }
02175
02176 int BC_ListBox::put_selection(ArrayList<BC_ListBoxItem*> *data,
02177 ArrayList<BC_ListBoxItem*> *src,
02178 int destination,
02179 int *counter)
02180 {
02181 int temp = -1;
02182 if(!counter) counter = &temp;
02183
02184 if(destination < 0)
02185 {
02186 for(int j = 0; j < columns; j++)
02187 {
02188 for(int i = 0; i < src[j].total; i++)
02189 {
02190 data[j].append(src[j].values[i]);
02191 }
02192 }
02193 return 1;
02194 }
02195 else
02196 for(int i = 0; i < data[master_column].total; i++)
02197 {
02198 (*counter)++;
02199 if((*counter) == destination)
02200 {
02201 for(int j = 0; j < columns; j++)
02202 {
02203 for(int k = 0; k < src[j].total; k++)
02204 {
02205 data[j].insert(src[j].values[k], destination + k);
02206 }
02207 }
02208 return 1;
02209 }
02210
02211 BC_ListBoxItem *item = data[master_column].values[i];
02212 if(item->get_sublist())
02213 {
02214 if(put_selection(item->get_sublist(),
02215 src,
02216 destination,
02217 counter))
02218 return 1;
02219 }
02220 }
02221 return 0;
02222 }
02223
02224
02225
02226 int BC_ListBox::item_to_index(ArrayList<BC_ListBoxItem*> *data,
02227 BC_ListBoxItem *item,
02228 int *counter)
02229 {
02230 int temp = -1;
02231 if(!counter) counter = &temp;
02232
02233 for(int i = 0; i < data[master_column].total; i++)
02234 {
02235 (*counter)++;
02236 for(int j = 0; j < columns; j++)
02237 {
02238 BC_ListBoxItem *new_item = data[j].values[i];
02239
02240 if(new_item == item)
02241 {
02242 return (*counter);
02243 }
02244 }
02245
02246 BC_ListBoxItem *new_item = data[master_column].values[i];
02247 if(new_item->get_sublist())
02248 {
02249 if(item_to_index(new_item->get_sublist(),
02250 item,
02251 counter) >= 0)
02252 return (*counter);
02253 }
02254 }
02255
02256 return -1;
02257 }
02258
02259 BC_ListBoxItem* BC_ListBox::index_to_item(ArrayList<BC_ListBoxItem*> *data,
02260 int number,
02261 int column,
02262 int *counter)
02263 {
02264 int temp = -1;
02265 if(!counter) counter = &temp;
02266 for(int i = 0; i < data[master_column].total; i++)
02267 {
02268 (*counter)++;
02269 if((*counter) == number)
02270 {
02271 return data[column].values[i];
02272 }
02273 BC_ListBoxItem *item = data[master_column].values[i];
02274 if(item->get_sublist())
02275 {
02276 BC_ListBoxItem *result = index_to_item(item->get_sublist(),
02277 number,
02278 column,
02279 counter);
02280 if(result) return result;
02281 }
02282 }
02283 return 0;
02284 }
02285
02286 int BC_ListBox::get_cursor_item(ArrayList<BC_ListBoxItem*> *data,
02287 int cursor_x,
02288 int cursor_y,
02289 BC_ListBoxItem **item_return,
02290 int *counter,
02291 int expanded)
02292 {
02293 int temp = -1;
02294 if(!data) return -1;
02295 if(!counter) counter = &temp;
02296
02297
02298 if(display_format == LISTBOX_ICONS)
02299 {
02300 for(int j = data[master_column].total - 1; j >= 0; j--)
02301 {
02302 int icon_x, icon_y, icon_w, icon_h;
02303 int text_x, text_y, text_w, text_h;
02304 BC_ListBoxItem *item = data[master_column].values[j];
02305 get_icon_mask(item, icon_x, icon_y, icon_w, icon_h);
02306 get_text_mask(item, text_x, text_y, text_w, text_h);
02307
02308 if((cursor_x >= icon_x && cursor_x < icon_x + icon_w &&
02309 cursor_y >= icon_y && cursor_y < icon_y + icon_h) ||
02310 (cursor_x >= text_x && cursor_x < text_x + text_w &&
02311 cursor_y >= text_y && cursor_y < text_y + text_h))
02312 {
02313 if(item_return) (*item_return) = item;
02314 return j;
02315 }
02316 }
02317 }
02318 else
02319
02320 if(display_format == LISTBOX_TEXT)
02321 {
02322
02323 if(cursor_x >= 0 &&
02324 cursor_x < (yscrollbar ?
02325 gui->get_w() - get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w() :
02326 gui->get_w()) &&
02327
02328 (current_operation == BC_ListBox::SELECT ||
02329 (cursor_y > get_title_h() + LISTBOX_BORDER &&
02330 cursor_y < gui->get_h())))
02331 {
02332
02333 for(int i = 0; i < data[master_column].total; i++)
02334 {
02335 BC_ListBoxItem *item = data[master_column].values[i];
02336 (*counter)++;
02337
02338
02339 if(expanded &&
02340 item->selectable &&
02341 cursor_y >= get_item_y(item) &&
02342 cursor_y < get_item_y(item) + get_item_h(item))
02343 {
02344
02345 if(item_return) (*item_return) = item;
02346 return (*counter);
02347 }
02348
02349
02350 if(item->get_sublist())
02351 {
02352 if(get_cursor_item(item->get_sublist(),
02353 cursor_x,
02354 cursor_y,
02355 item_return,
02356 counter,
02357 item->get_expand()) >= 0)
02358 return (*counter);
02359 }
02360 }
02361 }
02362 }
02363 return -1;
02364 }
02365
02366 int BC_ListBox::repeat_event(int64_t duration)
02367 {
02368 switch(current_operation)
02369 {
02370
02371 case SELECT_RECT:
02372 if(duration == get_resources()->scroll_repeat)
02373 return rectangle_scroll_event();
02374 break;
02375
02376 case SELECT:
02377 if(duration == get_resources()->scroll_repeat)
02378 return select_scroll_event();
02379 break;
02380
02381 case NO_OPERATION:
02382
02383 if(button_highlighted &&
02384 duration == get_resources()->tooltip_delay &&
02385 tooltip_text[0] != 0 &&
02386 is_popup &&
02387 !tooltip_done)
02388 {
02389 show_tooltip();
02390 tooltip_done = 1;
02391 return 1;
02392 }
02393 break;
02394 }
02395 return 0;
02396 }
02397
02398
02399 int BC_ListBox::cursor_enter_event()
02400 {
02401 int result = 0;
02402
02403 switch(current_operation)
02404 {
02405
02406 case BUTTON_DOWN_SELECT:
02407 if(top_level->event_win == win)
02408 {
02409 current_operation = BUTTON_DN;
02410 result = 1;
02411 button_highlighted = 1;
02412 draw_button();
02413 }
02414 break;
02415
02416 case NO_OPERATION:
02417
02418 if(is_popup && top_level->event_win == win)
02419 {
02420 button_highlighted = 1;
02421 result = 1;
02422 draw_button();
02423 }
02424 else
02425
02426 if(gui && top_level->event_win == gui->win)
02427 {
02428 list_highlighted = 1;
02429 draw_border(1);
02430 result = 1;
02431 }
02432 break;
02433 }
02434
02435 return result;
02436 }
02437
02438 int BC_ListBox::cursor_leave_event()
02439 {
02440 int redraw_button = 0;
02441 int redraw_border = 0;
02442 int redraw_titles = 0;
02443 int redraw_items = 0;
02444
02445 if(current_operation == COLUMN_DRAG) return 0;
02446
02447
02448 if(button_highlighted)
02449 {
02450 button_highlighted = 0;
02451 hide_tooltip();
02452 draw_button();
02453 }
02454
02455 if(list_highlighted)
02456 {
02457 list_highlighted = 0;
02458 highlighted_item = -1;
02459 highlighted_ptr = 0;
02460 highlighted_title = -1;
02461 int redraw_toggles = 0;
02462 for(int i = 0; i < expanders.total; i++)
02463 expanders.values[i]->cursor_leave_event(&redraw_toggles);
02464
02465 draw_items(1);
02466 }
02467
02468 return 0;
02469 }
02470
02471 int BC_ListBox::get_first_selection(ArrayList<BC_ListBoxItem*> *data, int *result)
02472 {
02473 int temp = -1;
02474 if(!result) result = &temp;
02475
02476 for(int i = 0; i < data[master_column].total; i++)
02477 {
02478 BC_ListBoxItem *item = data[master_column].values[i];
02479 (*result)++;
02480 if(item->selected) return (*result);
02481 if(item->get_sublist())
02482 {
02483 if(get_first_selection(item->get_sublist(), result) >= 0)
02484 return (*result);
02485 }
02486 }
02487 return -1;
02488 }
02489
02490 int BC_ListBox::get_total_items(ArrayList<BC_ListBoxItem*> *data,
02491 int *result,
02492 int master_column)
02493 {
02494 int temp = 0;
02495 if(!result) result = &temp;
02496
02497 for(int i = 0; i < data[master_column].total; i++)
02498 {
02499 (*result)++;
02500 if(data[master_column].values[i]->get_sublist())
02501 get_total_items(data[master_column].values[i]->get_sublist(),
02502 result,
02503 master_column);
02504 }
02505
02506 return (*result);
02507 }
02508
02509
02510 int BC_ListBox::get_last_selection(ArrayList<BC_ListBoxItem*> *data,
02511 int *result)
02512 {
02513 int temp = -1;
02514 int top_level = 0;
02515 if(!result)
02516 {
02517 result = &temp;
02518 top_level = 1;
02519 }
02520
02521 for(int i = data[master_column].total - 1; i >= 0; i--)
02522 {
02523 BC_ListBoxItem *item = data[master_column].values[i];
02524 (*result)++;
02525 if(item->selected)
02526 {
02527 if(top_level)
02528 return get_total_items(data, 0, master_column) - (*result) ;
02529 else
02530 return (*result);
02531 }
02532
02533 if(item->get_sublist())
02534 {
02535 if(get_last_selection(item->get_sublist(), result) >= 0)
02536 {
02537 if(top_level)
02538 return get_total_items(data, 0, master_column) - (*result) ;
02539 else
02540 return (*result);
02541 }
02542 }
02543 }
02544 return -1;
02545 }
02546
02547 void BC_ListBox::select_range(ArrayList<BC_ListBoxItem*> *data,
02548 int start,
02549 int end,
02550 int *current)
02551 {
02552 int temp = -1;
02553 if(!current) current = &temp;
02554
02555 for(int i = 0; i < data[master_column].total; i++)
02556 {
02557 (*current)++;
02558 if((*current) >= start && (*current) < end)
02559 {
02560 for(int j = 0; j < columns; j++)
02561 data[j].values[i]->selected = 1;
02562 }
02563 BC_ListBoxItem *item = data[master_column].values[i];
02564 if(item->get_sublist())
02565 select_range(item->get_sublist(),
02566 start,
02567 end,
02568 current);
02569 }
02570 }
02571
02572
02573
02574 int BC_ListBox::expand_selection(int button_press, int selection_number)
02575 {
02576 int old_selection_start = selection_start;
02577 int old_selection_end = selection_end;
02578
02579
02580
02581
02582
02583
02584 if(selection_number < selection_center)
02585 {
02586 selection_start = selection_number;
02587 }
02588 else
02589 {
02590 selection_end = selection_number + 1;
02591 }
02592
02593
02594
02595 select_range(data, selection_start, selection_end);
02596
02597
02598 return (old_selection_start != selection_start ||
02599 old_selection_end != selection_end);
02600 }
02601
02602 int BC_ListBox::toggle_item_selection(ArrayList<BC_ListBoxItem*> *data,
02603 int selection_number,
02604 int *counter)
02605 {
02606 int temp = -1;
02607 if(!counter) counter = &temp;
02608
02609 for(int i = 0; i < data[master_column].total; i++)
02610 {
02611 BC_ListBoxItem *item = data[master_column].values[i];
02612 (*counter)++;
02613 if((*counter) == selection_number)
02614 {
02615
02616 int selected = !item->selected;
02617
02618 for(int j = 0; j < columns; j++)
02619 data[j].values[i]->selected = selected;
02620 return 1;
02621 }
02622
02623
02624 if(item->get_sublist())
02625 {
02626 if(toggle_item_selection(item->get_sublist(),
02627 selection_number,
02628 counter))
02629 return 1;
02630 }
02631 }
02632
02633 return 0;
02634 }
02635
02636
02637 void BC_ListBox::set_all_selected(ArrayList<BC_ListBoxItem*> *data, int value)
02638 {
02639 for(int i = 0; i < data[master_column].total; i++)
02640 {
02641 for(int j = 0; j < columns; j++)
02642 {
02643 BC_ListBoxItem *item = data[j].values[i];
02644 item->selected = value;
02645 }
02646 BC_ListBoxItem *item = data[master_column].values[i];
02647 if(item->get_sublist())
02648 {
02649 set_all_selected(item->get_sublist(), value);
02650 }
02651 }
02652 }
02653
02654 void BC_ListBox::set_selected(ArrayList<BC_ListBoxItem*> *data,
02655 int item_number,
02656 int value,
02657 int *counter)
02658 {
02659 int temp = -1;
02660 if(!counter) counter = &temp;
02661 for(int i = 0; i < data[master_column].total && (*counter) != item_number; i++)
02662 {
02663 (*counter)++;
02664 if((*counter) == item_number)
02665 {
02666 for(int j = 0; j < columns; j++)
02667 {
02668 BC_ListBoxItem *item = data[j].values[i];
02669 item->selected = value;
02670 }
02671 return;
02672 }
02673
02674 BC_ListBoxItem *item = data[master_column].values[i];
02675 if(item->get_sublist())
02676 {
02677 set_selected(item->get_sublist(),
02678 item_number,
02679 value,
02680 counter);
02681 }
02682 }
02683 }
02684
02685 int BC_ListBox::update_selection(ArrayList<BC_ListBoxItem*> *data,
02686 int selection_number,
02687 int *counter)
02688 {
02689 int temp = -1;
02690 int result = 0;
02691 if(!counter) counter = &temp;
02692
02693 for(int i = 0; i < data[master_column].total; i++)
02694 {
02695 BC_ListBoxItem *item = data[master_column].values[i];
02696 (*counter)++;
02697 if((*counter) == selection_number && !item->selected)
02698 {
02699 result = 1;
02700 for(int j = 0; j < columns; j++)
02701 data[j].values[i]->selected = 1;
02702 }
02703 else
02704 if((*counter) != selection_number && item->selected)
02705 {
02706 result = 1;
02707 for(int j = 0; j < columns; j++)
02708 data[j].values[i]->selected = 0;
02709 }
02710 if(item->get_sublist())
02711 result |= update_selection(item->get_sublist(),
02712 selection_number,
02713 counter);
02714 }
02715 return result;
02716 }
02717
02718 void BC_ListBox::promote_selections(ArrayList<BC_ListBoxItem*> *data,
02719 int old_value,
02720 int new_value)
02721 {
02722 for(int i = 0; i < data[master_column].total; i++)
02723 {
02724 for(int j = 0; j < columns; j++)
02725 {
02726 BC_ListBoxItem *item = data[j].values[i];
02727 if(item->selected == old_value) item->selected = new_value;
02728 }
02729 BC_ListBoxItem *item = data[master_column].values[i];
02730 if(item->get_sublist())
02731 promote_selections(item->get_sublist(), old_value, new_value);
02732 }
02733 }
02734
02735 int BC_ListBox::focus_out_event()
02736 {
02737 deactivate();
02738 return 0;
02739 }
02740
02741 int BC_ListBox::button_press_event()
02742 {
02743 int result = 0;
02744 BC_ListBoxItem *current_item = 0;
02745 int new_cursor;
02746 int do_selection_change = 0;
02747
02748 hide_tooltip();
02749
02750
02751
02752 if(is_popup && top_level->event_win == win)
02753 {
02754 current_operation = BUTTON_DN;
02755 draw_button();
02756
02757
02758 if(!active && !disabled)
02759 {
02760 top_level->deactivate();
02761 activate();
02762 }
02763
02764 result = 1;
02765 }
02766 else
02767
02768 if((xscrollbar && top_level->event_win == xscrollbar->win) ||
02769 (yscrollbar && top_level->event_win == yscrollbar->win))
02770 {
02771 result = 0;
02772 }
02773 else
02774
02775 if(gui && top_level->event_win == gui->win)
02776 {
02777
02778 if(!active)
02779 {
02780 top_level->deactivate();
02781 activate();
02782 }
02783
02784
02785 if(get_buttonpress() == 4)
02786 {
02787 if(current_operation == NO_OPERATION)
02788 {
02789 current_operation = WHEEL;
02790 if(yscrollbar)
02791 {
02792 set_yposition(yposition - gui->get_h() / 10, 0);
02793 clamp_positions();
02794 update_scrollbars();
02795 highlighted_ptr = 0;
02796 highlighted_item = get_cursor_item(data,
02797 top_level->cursor_x,
02798 top_level->cursor_y,
02799 &highlighted_ptr);
02800 draw_items(1);
02801 result = 1;
02802 }
02803 }
02804 }
02805 else
02806 if(get_buttonpress() == 5)
02807 {
02808 if(current_operation == NO_OPERATION)
02809 {
02810 current_operation = WHEEL;
02811 if(yscrollbar)
02812 {
02813 set_yposition(yposition + gui->get_h() / 10, 0);
02814 clamp_positions();
02815 update_scrollbars();
02816 highlighted_ptr = 0;
02817 highlighted_item = get_cursor_item(data,
02818 top_level->cursor_x,
02819 top_level->cursor_y,
02820 &highlighted_ptr);
02821 draw_items(1);
02822 result = 1;
02823 }
02824 }
02825 }
02826 else
02827
02828 if(test_column_divisions(gui->get_cursor_x(),
02829 gui->get_cursor_y(),
02830 new_cursor))
02831 {
02832 current_operation = DRAG_DIVISION;
02833 reset_query();
02834 }
02835 else
02836
02837 if(test_column_titles(gui->get_cursor_x(), gui->get_cursor_y()))
02838 {
02839 current_operation = COLUMN_DN;
02840 button_highlighted = 0;
02841 list_highlighted = 1;
02842 draw_items(1);
02843 result = 1;
02844 }
02845 else
02846
02847 if(test_expanders())
02848 {
02849 current_operation = EXPAND_DN;
02850
02851 draw_items(1);
02852 result = 1;
02853 }
02854 else
02855
02856 if((selection_number = get_cursor_item(data,
02857 gui->get_cursor_x(),
02858 gui->get_cursor_y(),
02859 ¤t_item)) >= 0)
02860 {
02861
02862 selection_number2 = selection_number1;
02863 selection_number1 = selection_number;
02864
02865 selection_start = -1;
02866 selection_end = -1;
02867
02868
02869
02870 if(selection_mode == LISTBOX_MULTIPLE &&
02871 (ctrl_down() || shift_down()))
02872 {
02873
02874
02875 if(shift_down() && display_format == LISTBOX_TEXT)
02876 {
02877
02878 selection_start = get_first_selection(data);
02879
02880 selection_end = get_last_selection(data);
02881
02882 if(selection_end > selection_start)
02883 {
02884 selection_center = (selection_end + selection_start) >> 1;
02885 }
02886 else
02887 {
02888 selection_center = selection_number;
02889 }
02890
02891
02892
02893 set_all_selected(data, 0);
02894
02895 expand_selection(1, selection_number);
02896 new_value = 1;
02897 }
02898 else
02899
02900 {
02901 toggle_item_selection(data, selection_number);
02902 new_value = current_item->selected;
02903 }
02904 }
02905 else
02906
02907 {
02908 if(!current_item->selected)
02909 {
02910 set_all_selected(data, 0);
02911 set_selected(data,
02912 selection_number,
02913 1);
02914 }
02915 new_value = 1;
02916 }
02917
02918
02919 current_operation = SELECT;
02920 highlighted_item = selection_number;
02921 highlighted_ptr = current_item;
02922 button_highlighted = 0;
02923 list_highlighted = 1;
02924 reset_query();
02925 draw_items(1);
02926 do_selection_change = 1;
02927 result = 1;
02928 }
02929 else
02930 if(data)
02931
02932 {
02933 if(get_buttonpress() == 1 &&
02934 selection_mode == LISTBOX_MULTIPLE)
02935 {
02936 if(!shift_down())
02937 {
02938
02939 if(get_selection_number(0, 0) >= 0)
02940 {
02941 set_all_selected(data, 0);
02942 draw_items(1);
02943 do_selection_change = 1;
02944 result = 1;
02945 }
02946 }
02947 else
02948 {
02949
02950 promote_selections(data, 1, 2);
02951 }
02952
02953
02954 current_operation = SELECT_RECT;
02955 rect_x1 = rect_x2 = get_cursor_x();
02956 rect_y1 = rect_y2 = get_cursor_y();
02957 }
02958 }
02959
02960
02961 reset_query();
02962 }
02963 else
02964 if(is_popup && active)
02965 {
02966 deactivate();
02967 result = 1;
02968 }
02969
02970
02971 if(do_selection_change) selection_changed();
02972
02973 return result;
02974 }
02975
02976 int BC_ListBox::button_release_event()
02977 {
02978 int result = 0;
02979 int cursor_x, cursor_y;
02980 int do_event = 0;
02981 new_value = 0;
02982
02983
02984 switch(current_operation)
02985 {
02986 case DRAG_DIVISION:
02987 current_operation = NO_OPERATION;
02988 result = 1;
02989 break;
02990
02991 case WHEEL:
02992 current_operation = NO_OPERATION;
02993 result = 1;
02994 break;
02995
02996
02997 case BUTTON_DOWN_SELECT:
02998 case SELECT:
02999
03000 unset_repeat(get_resources()->scroll_repeat);
03001 current_operation = NO_OPERATION;
03002 translate_coordinates(top_level->event_win,
03003 gui->win,
03004 gui->get_cursor_x(),
03005 gui->get_cursor_y(),
03006 &cursor_x,
03007 &cursor_y);
03008
03009 selection_number1 =
03010 selection_number =
03011 get_cursor_item(data, cursor_x, cursor_y);
03012
03013
03014 if(is_popup)
03015 {
03016 button_releases++;
03017 if(selection_number >= 0)
03018 {
03019 deactivate();
03020 do_event = 1;
03021 }
03022 else
03023
03024 if(button_releases > 1)
03025 {
03026 deactivate();
03027 }
03028 }
03029 else
03030 {
03031 if(top_level->get_double_click() &&
03032 selection_number2 == selection_number1 &&
03033 selection_number2 >= 0 &&
03034 selection_number1 >= 0)
03035 {
03036 do_event = 1;
03037 }
03038 result = 1;
03039 }
03040 break;
03041
03042
03043 case SELECT_RECT:
03044 unset_repeat(get_resources()->scroll_repeat);
03045 if(data)
03046 {
03047
03048 promote_selections(data, 2, 1);
03049 }
03050
03051
03052 draw_rectangle(1);
03053 current_operation = NO_OPERATION;
03054 result = 1;
03055 break;
03056
03057
03058 case BUTTON_DN:
03059 hide_tooltip();
03060 current_operation = NO_OPERATION;
03061 button_releases++;
03062 draw_button();
03063
03064
03065 if(button_releases > 1)
03066 {
03067 deactivate();
03068 }
03069 result = 1;
03070 break;
03071
03072 case COLUMN_DN:
03073 current_operation = NO_OPERATION;
03074
03075
03076 if(sort_column >= 0)
03077 {
03078
03079 if(highlighted_title == sort_column)
03080 sort_order =
03081 (sort_order == SORT_ASCENDING) ?
03082 SORT_DESCENDING :
03083 SORT_ASCENDING;
03084
03085 sort_column = highlighted_title;
03086 if(!sort_order_event())
03087 {
03088 draw_titles(1);
03089 }
03090 }
03091 else
03092
03093 {
03094 draw_titles(1);
03095 }
03096 result = 1;
03097 break;
03098
03099 case EXPAND_DN:
03100 {
03101 int redraw_toggles = 0;
03102 for(int i = 0; i < expanders.total && !result; i++)
03103 {
03104 if(expanders.values[i]->button_release_event(&redraw_toggles))
03105 {
03106 result = 1;
03107 }
03108 }
03109
03110 if(redraw_toggles) draw_items(1);
03111 current_operation = NO_OPERATION;
03112 break;
03113 }
03114
03115 default:
03116
03117 break;
03118 }
03119
03120
03121 if(do_event) handle_event();
03122
03123 return result;
03124 }
03125
03126 int BC_ListBox::get_title_h()
03127 {
03128 if(display_format == LISTBOX_TEXT)
03129 return column_titles ? column_bg[0]->get_h() : 0;
03130 else
03131 return 0;
03132 }
03133
03134 void BC_ListBox::reset_cursor(int new_cursor)
03135 {
03136 if(is_popup)
03137 {
03138 if(gui->get_cursor() != new_cursor)
03139 {
03140 gui->set_cursor(new_cursor);
03141 }
03142 }
03143 else
03144 if(get_cursor() != new_cursor)
03145 {
03146 set_cursor(new_cursor);
03147 }
03148 }
03149
03150 int BC_ListBox::test_column_divisions(int cursor_x, int cursor_y, int &new_cursor)
03151 {
03152 if(gui &&
03153 column_titles &&
03154 cursor_y >= 0 &&
03155 cursor_y < get_title_h() &&
03156 cursor_x >= 0 &&
03157 cursor_x < gui->get_w())
03158 {
03159 for(int i = 1; i < columns; i++)
03160 {
03161 if(cursor_x >= -xposition + get_column_offset(i) - 5 &&
03162 cursor_x < -xposition + get_column_offset(i) +
03163 get_resources()->listbox_title_hotspot)
03164 {
03165 highlighted_item = -1;
03166 highlighted_ptr = 0;
03167 highlighted_division = i;
03168 highlighted_title = -1;
03169 list_highlighted = 1;
03170 new_cursor = HSEPARATE_CURSOR;
03171 return 1;
03172 }
03173 }
03174 }
03175 highlighted_division = -1;
03176 return 0;
03177 }
03178
03179 int BC_ListBox::test_column_titles(int cursor_x, int cursor_y)
03180 {
03181 if(gui &&
03182 column_titles &&
03183 cursor_y >= 0 &&
03184 cursor_y < get_title_h() &&
03185 cursor_x >= 0 &&
03186 cursor_x < gui->get_w())
03187 {
03188 for(int i = 0; i < columns; i++)
03189 {
03190 if(cursor_x >= -xposition + get_column_offset(i) &&
03191 (cursor_x < -xposition + get_column_offset(i + 1) ||
03192 i == columns - 1))
03193 {
03194 highlighted_item = -1;
03195 highlighted_ptr = 0;
03196 highlighted_division = -1;
03197 highlighted_title = i;
03198 list_highlighted = 1;
03199 return 1;
03200 }
03201 }
03202 }
03203 highlighted_title = -1;
03204 return 0;
03205 }
03206
03207 int BC_ListBox::test_expanders()
03208 {
03209 for(int i = 0; i < expanders.total; i++)
03210 {
03211 if(expanders.values[i]->button_press_event())
03212 {
03213 current_operation = EXPAND_DN;
03214 draw_toggles(1);
03215 return 1;
03216 }
03217 }
03218 return 0 ;
03219 }
03220
03221 int BC_ListBox::cursor_motion_event()
03222 {
03223 int redraw = 0, result = 0;
03224 int new_cursor = ARROW_CURSOR;
03225
03226 selection_number = -1;
03227
03228
03229 switch(current_operation)
03230 {
03231 case BUTTON_DN:
03232
03233 if(!cursor_inside())
03234 {
03235 current_operation = BUTTON_DOWN_SELECT;
03236 draw_button();
03237 result = 1;
03238 }
03239 break;
03240
03241 case DRAG_DIVISION:
03242 {
03243 int new_w = get_cursor_x() +
03244 xposition -
03245 get_column_offset(highlighted_division - 1);
03246 new_cursor = HSEPARATE_CURSOR;
03247
03248 if(column_width)
03249 {
03250 column_width[highlighted_division - 1] = new_w;
03251 }
03252 else
03253 {
03254 default_column_width[highlighted_division - 1] = new_w;
03255 }
03256
03257 column_width_boundaries();
03258
03259
03260 set_autoplacement(data, 0, 1);
03261 column_resize_event();
03262
03263 clamp_positions();
03264 draw_items(1);
03265 update_scrollbars();
03266 result = 1;
03267 break;
03268 }
03269
03270 case SELECT_RECT:
03271 {
03272 if(test_drag_scroll(get_cursor_x(), get_cursor_y()))
03273 {
03274 set_repeat(get_resources()->scroll_repeat);
03275 }
03276
03277 int old_x1 = MIN(rect_x1, rect_x2);
03278 int old_x2 = MAX(rect_x1, rect_x2);
03279 int old_y1 = MIN(rect_y1, rect_y2);
03280 int old_y2 = MAX(rect_y1, rect_y2);
03281
03282 int new_rect_x2 = get_cursor_x();
03283 int new_rect_y2 = get_cursor_y();
03284
03285 int x1 = MIN(rect_x1, new_rect_x2);
03286 int x2 = MAX(rect_x1, new_rect_x2);
03287 int y1 = MIN(rect_y1, new_rect_y2);
03288 int y2 = MAX(rect_y1, new_rect_y2);
03289
03290
03291 if(old_x1 != x1 ||
03292 old_x2 != x2 ||
03293 old_y1 != y1 ||
03294 old_y2 != y2)
03295 {
03296 if(data)
03297 {
03298 redraw = select_rectangle(data,
03299 x1,
03300 y1,
03301 x2,
03302 y2);
03303 }
03304
03305
03306 if(!redraw)
03307 draw_rectangle(0);
03308 }
03309
03310 rect_x2 = get_cursor_x();
03311 rect_y2 = get_cursor_y();
03312 if(redraw)
03313 {
03314 clamp_positions();
03315 draw_items(1);
03316 update_scrollbars();
03317 selection_changed();
03318 }
03319 else
03320 {
03321 draw_rectangle(1);
03322 }
03323 result = 1;
03324 break;
03325 }
03326
03327 case SELECT:
03328 {
03329 int old_highlighted_item = highlighted_item;
03330 int old_highlighted_title = highlighted_title;
03331 BC_ListBoxItem *old_highlighted_ptr = highlighted_ptr;
03332
03333 if(test_drag_scroll(get_cursor_x(),
03334 get_cursor_y()))
03335 {
03336 set_repeat(get_resources()->scroll_repeat);
03337 }
03338
03339
03340 highlighted_item = selection_number = get_cursor_item(data,
03341 get_cursor_x(),
03342 get_cursor_y(),
03343 &highlighted_ptr);
03344 result = 1;
03345
03346
03347 if(selection_number >= 0 &&
03348 !allow_drag &&
03349 ((!shift_down() &&
03350 !ctrl_down()) ||
03351 selection_mode == LISTBOX_SINGLE))
03352 {
03353 redraw = update_selection(data, selection_number);
03354 }
03355 else
03356 if(selection_mode == LISTBOX_MULTIPLE &&
03357 (shift_down() || ctrl_down()))
03358
03359 {
03360
03361 if(display_format == LISTBOX_TEXT && shift_down())
03362 {
03363
03364 set_all_selected(data, 0);
03365
03366
03367 redraw = expand_selection(0, selection_number);
03368 }
03369 else
03370
03371
03372 {
03373 set_selected(data,
03374 selection_number,
03375 new_value);
03376 }
03377 }
03378
03379 if(highlighted_item != old_highlighted_item)
03380 {
03381 clamp_positions();
03382 draw_items(1);
03383 update_scrollbars();
03384
03385 selection_changed();
03386 }
03387 break;
03388 }
03389
03390 case BUTTON_DOWN_SELECT:
03391
03392 if(cursor_inside())
03393 {
03394 current_operation = BUTTON_DN;
03395 draw_button();
03396 result = 1;
03397 }
03398 else
03399
03400 if(gui)
03401 {
03402 int cursor_x = 0, cursor_y = 0;
03403 translate_coordinates(top_level->event_win,
03404 gui->win,
03405 top_level->cursor_x,
03406 top_level->cursor_y,
03407 &cursor_x,
03408 &cursor_y);
03409 int old_highlighted_item = highlighted_item;
03410 highlighted_item = selection_number = get_cursor_item(data,
03411 cursor_x,
03412 cursor_y,
03413 &highlighted_ptr);
03414
03415 if(highlighted_item != old_highlighted_item)
03416 {
03417 update_selection(data, selection_number);
03418 draw_items(1);
03419 selection_changed();
03420 }
03421 }
03422 break;
03423
03424 case EXPAND_DN:
03425 {
03426 int redraw_toggles = 0;
03427 for(int i = 0; i < expanders.total && !result; i++)
03428 {
03429 result = expanders.values[i]->cursor_motion_event(
03430 &redraw_toggles);
03431 }
03432 if(redraw_toggles)
03433 {
03434
03435 draw_items(1);
03436 }
03437 break;
03438 }
03439
03440 case NO_OPERATION:
03441 {
03442 int cursor_x = get_cursor_x(), cursor_y = get_cursor_y();
03443 if(gui && top_level->event_win == gui->win)
03444 {
03445 int old_highlighted_title = highlighted_title;
03446 int old_list_highlighted = list_highlighted;
03447 int old_highlighted_division = highlighted_division;
03448 int old_highlighted_item = highlighted_item;
03449 int redraw_titles = 0;
03450 int redraw_border = 0;
03451 int redraw_items = 0;
03452 int redraw_toggles = 0;
03453 result = 1;
03454
03455
03456
03457 test_column_divisions(cursor_x, cursor_y, new_cursor);
03458
03459
03460 if(highlighted_division < 0)
03461 {
03462 test_column_titles(cursor_x, cursor_y);
03463 }
03464
03465
03466 if(highlighted_division < 0 &&
03467 highlighted_title < 0 &&
03468 display_format == LISTBOX_TEXT)
03469 {
03470 for(int i = 0; i < expanders.total; i++)
03471 {
03472 expanders.values[i]->cursor_motion_event(
03473 &redraw_toggles);
03474 }
03475
03476 }
03477
03478
03479 if(highlighted_division < 0 &&
03480 highlighted_title < 0)
03481 {
03482 highlighted_item = get_cursor_item(data,
03483 cursor_x,
03484 cursor_y,
03485 &highlighted_ptr);
03486 }
03487
03488
03489
03490 if(old_highlighted_title != highlighted_title)
03491 {
03492 redraw_titles = 1;
03493 }
03494
03495
03496 if(old_list_highlighted != list_highlighted)
03497 {
03498 redraw_border = 1;
03499 }
03500
03501
03502 if(old_highlighted_item != highlighted_item)
03503 {
03504 redraw_items = 1;
03505 }
03506
03507
03508
03509
03510 reset_cursor(new_cursor);
03511
03512 if(redraw_items)
03513 {
03514 draw_items(0);
03515 }
03516 else
03517 {
03518 if(redraw_titles)
03519 draw_titles(0);
03520 if(redraw_border)
03521 draw_border(0);
03522 if(redraw_toggles)
03523 draw_toggles(0);
03524 }
03525
03526 if(redraw_items ||
03527 redraw_titles ||
03528 redraw_border ||
03529 redraw_toggles)
03530 {
03531 gui->flash();
03532 gui->flush();
03533 }
03534 }
03535
03536
03537 if(!result && list_highlighted)
03538 {
03539 list_highlighted = 0;
03540 highlighted_item = -1;
03541 highlighted_ptr = 0;
03542 highlighted_title = -1;
03543 highlighted_division = -1;
03544 draw_items(1);
03545 result = 0;
03546 }
03547 break;
03548 }
03549 }
03550
03551
03552 return result;
03553 }
03554
03555 int BC_ListBox::drag_start_event()
03556 {
03557 switch(current_operation)
03558 {
03559 case SELECT:
03560 if(gui &&
03561 gui->is_event_win() &&
03562 allow_drag)
03563 {
03564 BC_ListBoxItem *item_return = 0;
03565 selection_number = get_cursor_item(data,
03566 top_level->cursor_x,
03567 top_level->cursor_y,
03568 &item_return);
03569
03570 if(selection_number >= 0)
03571 {
03572
03573 if (item_return->icon_vframe)
03574 {
03575 drag_popup = new BC_DragWindow(this,
03576 item_return->icon_vframe,
03577 get_abs_cursor_x(0) - item_return->icon_vframe->get_w() / 2,
03578 get_abs_cursor_y(0) - item_return->icon_vframe->get_h() / 2);
03579 }
03580 else
03581
03582 if (item_return->icon)
03583 drag_popup = new BC_DragWindow(this,
03584 item_return->icon,
03585 get_abs_cursor_x(0) - item_return->icon->get_w() / 2,
03586 get_abs_cursor_y(0) - item_return->icon->get_h() / 2);
03587 else
03588 drag_popup = new BC_DragWindow(this,
03589 drag_icon_vframe,
03590 get_abs_cursor_x(0) - drag_icon_vframe->get_w() / 2,
03591 get_abs_cursor_y(0) - drag_icon_vframe->get_h() / 2);
03592 current_operation = DRAG_ITEM;
03593 return 1;
03594 }
03595 }
03596 break;
03597
03598 case COLUMN_DN:
03599 if(gui && gui->is_event_win() && allow_drag_column)
03600 {
03601 drag_popup = new BC_DragWindow(this,
03602 drag_column_icon_vframe,
03603 get_abs_cursor_x(0) - drag_column_icon_vframe->get_w() / 2,
03604 get_abs_cursor_y(0) - drag_column_icon_vframe->get_h() / 2);
03605 dragged_title = highlighted_title;
03606 current_operation = COLUMN_DRAG;
03607 draw_titles(1);
03608 return 1;
03609 }
03610 break;
03611 }
03612
03613 return 0;
03614 }
03615
03616 int BC_ListBox::drag_motion_event()
03617 {
03618
03619 switch(current_operation)
03620 {
03621 case DRAG_ITEM:
03622 {
03623 int redraw = 0;
03624
03625 int new_highlighted_item = -1;
03626 BC_ListBoxItem *new_highlighted_ptr = 0;
03627 int new_highlight = new_highlighted_item = get_cursor_item(data,
03628 top_level->cursor_x,
03629 top_level->cursor_y,
03630 &new_highlighted_ptr);
03631
03632 if(new_highlighted_item != highlighted_item)
03633 {
03634 redraw = 1;
03635 }
03636
03637
03638 highlighted_item = new_highlighted_item;
03639 highlighted_ptr = new_highlighted_ptr;
03640
03641 if(redraw)
03642 {
03643 clamp_positions();
03644 draw_items(1);
03645 update_scrollbars();
03646 }
03647
03648 return drag_popup->cursor_motion_event();
03649 break;
03650 }
03651
03652 case COLUMN_DRAG:
03653 {
03654 int old_highlighted_title = highlighted_title;
03655 test_column_titles(get_cursor_x(), get_cursor_y());
03656 if(old_highlighted_title != highlighted_title)
03657 {
03658 draw_titles(1);
03659 }
03660 return drag_popup->cursor_motion_event();
03661 break;
03662 }
03663 }
03664 return 0;
03665 }
03666
03667 int BC_ListBox::drag_stop_event()
03668 {
03669 switch(current_operation)
03670 {
03671 case DRAG_ITEM:
03672
03673 if(top_level->cursor_x > 0 &&
03674 top_level->cursor_x < gui->get_w() - drag_popup->get_w() / 2 &&
03675 top_level->cursor_y > 0 &&
03676 top_level->cursor_y < gui->get_h() - drag_popup->get_h() / 2)
03677 {
03678
03679
03680
03681 if(display_format == LISTBOX_ICONS)
03682 {
03683 reposition_item(data,
03684 selection_number,
03685 top_level->cursor_x +
03686 drag_popup->get_offset_x() -
03687 LISTBOX_MARGIN -
03688 2 +
03689 xposition,
03690 top_level->cursor_y +
03691 drag_popup->get_offset_y() -
03692 LISTBOX_MARGIN -
03693 2 +
03694 yposition);
03695 }
03696 else
03697
03698 if(process_drag)
03699 {
03700
03701 int destination = highlighted_item = item_to_index(data,
03702 highlighted_ptr);
03703
03704
03705
03706 ArrayList<BC_ListBoxItem*> *src_items =
03707 new ArrayList<BC_ListBoxItem*>[columns];
03708
03709 move_selection(src_items, data);
03710
03711
03712 put_selection(data,
03713 src_items,
03714 destination);
03715
03716
03717 delete [] src_items;
03718 set_autoplacement(data, 0, 1);
03719 }
03720
03721
03722 draw_items(1);
03723 }
03724 else
03725 drag_popup->drag_failure_event();
03726
03727 delete drag_popup;
03728 drag_popup = 0;
03729 current_operation = NO_OPERATION;
03730 new_value = 0;
03731 return 1;
03732 break;
03733
03734 case COLUMN_DRAG:
03735 if(dragged_title != highlighted_title)
03736 {
03737 if(highlighted_title >= 0)
03738 {
03739 if(!move_column_event()) draw_titles(1);
03740 }
03741 else
03742 drag_popup->drag_failure_event();
03743 }
03744 current_operation = NO_OPERATION;
03745 delete drag_popup;
03746 drag_popup = 0;
03747 return 1;
03748 break;
03749 }
03750 return 0;
03751 }
03752
03753 BC_DragWindow* BC_ListBox::get_drag_popup()
03754 {
03755 return drag_popup;
03756 }
03757
03758 int BC_ListBox::translation_event()
03759 {
03760 if(is_popup && gui)
03761 {
03762 int new_x = gui->get_x() +
03763 (top_level->last_translate_x -
03764 top_level->prev_x -
03765 top_level->get_resources()->get_left_border());
03766 int new_y = gui->get_y() +
03767 (top_level->last_translate_y -
03768 top_level->prev_y -
03769 top_level->get_resources()->get_top_border());
03770
03771 gui->reposition_window(new_x, new_y);
03772
03773 }
03774 return 0;
03775 }
03776
03777 int BC_ListBox::reposition_window(int x, int y, int w, int h)
03778 {
03779 if(w != -1)
03780 {
03781 if(w != -1) popup_w = w;
03782 if(h != -1) popup_h = h;
03783
03784
03785 if(!is_popup)
03786 {
03787 if(w != -1) popup_w = w;
03788 if(h != -1) popup_h = h;
03789 if(xscrollbar)
03790 xscrollbar->reposition_window(get_xscroll_x(),
03791 get_xscroll_y(),
03792 get_xscroll_width());
03793 if(yscrollbar)
03794 yscrollbar->reposition_window(get_yscroll_x(),
03795 get_yscroll_y(),
03796 get_yscroll_height());
03797 }
03798 }
03799
03800
03801 BC_WindowBase::reposition_window(x, y, w, h);
03802 draw_button();
03803 draw_items(1);
03804 return 0;
03805 }
03806
03807 int BC_ListBox::deactivate()
03808 {
03809 if(active)
03810 {
03811 active = 0;
03812 if(is_popup)
03813 {
03814 if(gui) delete gui;
03815 xscrollbar = 0;
03816 yscrollbar = 0;
03817 gui = 0;
03818 highlighted_item = -1;
03819 highlighted_ptr = 0;
03820 }
03821 top_level->active_subwindow = 0;
03822 }
03823 return 0;
03824 }
03825
03826 int BC_ListBox::activate()
03827 {
03828 if(!active)
03829 {
03830 top_level->active_subwindow = this;
03831 active = 1;
03832 button_releases = 0;
03833
03834 if(is_popup)
03835 {
03836 Window tempwin;
03837 int x, y;
03838 int new_x, new_y;
03839 y = get_y() + get_h();
03840 if(justify == LISTBOX_RIGHT)
03841 {
03842 x = get_x() - popup_w + get_w();
03843 }
03844 else
03845 {
03846 x = get_x();
03847 }
03848
03849
03850 XTranslateCoordinates(top_level->display,
03851 parent_window->win,
03852 top_level->rootwin,
03853 x,
03854 y,
03855 &new_x,
03856 &new_y,
03857 &tempwin);
03858
03859 if(new_x < 0) new_x = 0;
03860 if(new_y + popup_h > top_level->get_root_h(0))
03861 new_y -= get_h() + popup_h;
03862
03863
03864 add_subwindow(gui = new BC_Popup(this,
03865 new_x,
03866 new_y,
03867 popup_w,
03868 popup_h,
03869 -1,
03870 0,
03871 0));
03872 draw_items(1);
03873 }
03874 }
03875 return 0;
03876 }
03877
03878 int BC_ListBox::keypress_event()
03879 {
03880 if(!active) return 0;
03881
03882 int result = 0, redraw = 0, done, view_items = view_h / get_text_height(MEDIUMFONT);
03883 int new_item = -1, new_selection = 0;
03884
03885 switch(top_level->get_keypress())
03886 {
03887 case ESC:
03888 case RETURN:
03889 top_level->deactivate();
03890 result = 0;
03891 break;
03892
03893 case UP:
03894 new_selection = new_item = select_previous(0);
03895
03896
03897 if(new_item >= 0)
03898 {
03899 center_selection(new_item);
03900 redraw = 1;
03901 }
03902 result = 1;
03903 break;
03904
03905 case DOWN:
03906 new_selection = new_item = select_next(0);
03907
03908 if(new_item >= 0)
03909 {
03910 center_selection(new_item);
03911 redraw = 1;
03912 }
03913 result = 1;
03914 break;
03915
03916 case PGUP:
03917 new_selection = new_item = select_previous(view_items - 1);
03918
03919 if(new_item >= 0)
03920 {
03921 center_selection(new_item);
03922 redraw = 1;
03923 }
03924 result = 1;
03925 break;
03926
03927 case PGDN:
03928 new_selection = new_item = select_next(view_items - 1);
03929
03930 if(new_item >= 0)
03931 {
03932 center_selection(new_item);
03933 redraw = 1;
03934 }
03935 result = 1;
03936 break;
03937
03938 case LEFT:
03939 xposition -= 10;
03940 redraw = 1;
03941 result = 1;
03942 break;
03943
03944 case RIGHT:
03945 xposition += 10;
03946 redraw = 1;
03947 result = 1;
03948 break;
03949
03950 default:
03951 if(!ctrl_down())
03952 {
03953 if(top_level->get_keypress() > 30 &&
03954 top_level->get_keypress() < 127)
03955 {
03956 int query_len = strlen(query);
03957 query[query_len++] = top_level->get_keypress();
03958 query[query_len] = 0;
03959 new_selection = query_list();
03960 }
03961 else
03962 if(top_level->get_keypress() == BACKSPACE)
03963 {
03964 int query_len = strlen(query);
03965 if(query_len > 0) query[--query_len] = 0;
03966 new_selection = query_list();
03967 }
03968
03969 redraw = 1;
03970 result = 1;
03971 }
03972 break;
03973 }
03974
03975 if(redraw)
03976 {
03977 clamp_positions();
03978 draw_items(1);
03979 update_scrollbars();
03980 }
03981
03982 if(new_selection >= 0)
03983 {
03984 selection_changed();
03985 }
03986
03987 return result;
03988 }
03989
03990
03991 BC_Pixmap* BC_ListBox::get_bg_surface()
03992 {
03993 return bg_surface;
03994 }
03995
03996
03997 void BC_ListBox::draw_background()
03998 {
03999
04000 set_color(top_level->get_resources()->listbox_inactive);
04001 draw_box(0, 0, bg_surface->get_w(), bg_surface->get_h(), bg_surface);
04002
04003
04004 if(bg_pixmap)
04005 bg_surface->draw_pixmap(bg_pixmap,
04006 bg_surface->get_w() - top_level->get_resources()->listbox_bg->get_w(),
04007 0);
04008 }
04009
04010 void BC_ListBox::clear_listbox(int x, int y, int w, int h)
04011 {
04012 gui->draw_pixmap(bg_surface,
04013 x,
04014 y,
04015 w,
04016 h,
04017 x,
04018 y - title_h);
04019 }
04020
04021 void BC_ListBox::update_format(int display_format, int redraw)
04022 {
04023 this->display_format = display_format;
04024 if(redraw)
04025 {
04026 if(gui) draw_items(1);
04027 }
04028 }
04029
04030 int BC_ListBox::get_format()
04031 {
04032 return display_format;
04033 }
04034
04035
04036
04037 int BC_ListBox::draw_items(int flash)
04038 {
04039 if(gui)
04040 {
04041 BC_Resources *resources = get_resources();
04042
04043
04044
04045
04046 calculate_item_coords();
04047
04048
04049
04050 get_scrollbars();
04051
04052
04053
04054
04055
04056
04057 if(display_format == LISTBOX_ICONS)
04058 {
04059 clear_listbox(2, 2 + title_h, view_w, view_h);
04060
04061 set_font(MEDIUMFONT);
04062 for(int i = 0; i < data[master_column].total; i++)
04063 {
04064 BC_ListBoxItem *item = data[master_column].values[i];
04065 if(get_item_x(item) >= -get_item_w(item) &&
04066 get_item_x(item) < view_w &&
04067 get_item_y(item) >= -get_item_h(item) + title_h &&
04068 get_item_y(item) < view_h + title_h)
04069 {
04070 int item_color = get_item_highlight(data, 0, i);
04071 int icon_x, icon_y, icon_w, icon_h;
04072 int text_x, text_y, text_w, text_h;
04073
04074
04075 get_icon_mask(item, icon_x, icon_y, icon_w, icon_h);
04076 get_text_mask(item, text_x, text_y, text_w, text_h);
04077
04078
04079 if(item_color != resources->listbox_inactive)
04080 {
04081 gui->set_color(BLACK);
04082 gui->draw_rectangle(icon_x, icon_y, icon_w, icon_h);
04083 gui->set_color(item_color);
04084 gui->draw_box(icon_x + 1, icon_y + 1, icon_w - 2, icon_h - 2);
04085 gui->set_color(BLACK);
04086 gui->draw_rectangle(text_x, text_y, text_w, text_h);
04087 gui->set_color(item_color);
04088 gui->draw_box(text_x + 1, text_y + 1, text_w - 2, text_h - 2);
04089
04090 if(icon_position == ICON_LEFT)
04091 gui->draw_box(text_x - 1, text_y + 1, 2, text_h - 2);
04092 else
04093 if(icon_position == ICON_TOP)
04094 gui->draw_line(text_x + 1, text_y, text_x + icon_w - 2, text_y);
04095 if(text_x + text_w < icon_x + icon_w)
04096 {
04097 gui->set_color(BLACK);
04098 gui->draw_line(text_x + text_w,
04099 icon_y + icon_h,
04100 icon_x + icon_w,
04101 icon_y + icon_h);
04102 }
04103 }
04104
04105
04106 gui->set_color(get_item_color(data, 0, i));
04107 if(item->icon)
04108 gui->pixmap->draw_pixmap(item->icon,
04109 icon_x + ICON_MARGIN,
04110 icon_y + ICON_MARGIN);
04111 gui->draw_text(text_x + ICON_MARGIN,
04112 text_y + ICON_MARGIN + get_text_ascent(MEDIUMFONT),
04113 item->text);
04114 }
04115 }
04116 }
04117 else
04118
04119 if(display_format == LISTBOX_TEXT)
04120 {
04121
04122
04123 int current_toggle = 0;
04124 for(int j = 0; j < columns; j++)
04125 {
04126 clear_listbox(LISTBOX_BORDER + get_column_offset(j) - xposition,
04127 LISTBOX_BORDER + title_h,
04128 get_column_width(j, 1),
04129 view_h);
04130
04131
04132 draw_text_recursive(data, j, 0, ¤t_toggle);
04133 }
04134
04135
04136 while(expanders.total > current_toggle)
04137 {
04138 expanders.remove_object();
04139 }
04140 }
04141
04142
04143 draw_titles(0);
04144
04145
04146 if(xscrollbar && yscrollbar && is_popup)
04147 {
04148 gui->draw_top_background(parent_window,
04149 popup_w - get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w(),
04150 popup_h - get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h(),
04151 get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w(),
04152 get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h());
04153 }
04154
04155
04156 draw_border(0);
04157
04158
04159 if(current_operation == SELECT_RECT)
04160 draw_rectangle(0);
04161
04162 if(flash)
04163 {
04164 gui->flash();
04165 gui->flush();
04166 }
04167 }
04168
04169 return 0;
04170 }
04171
04172
04173 void BC_ListBox::draw_text_recursive(ArrayList<BC_ListBoxItem*> *data,
04174 int column,
04175 int indent,
04176 int *current_toggle)
04177 {
04178 if(!data) return;
04179
04180
04181 BC_Resources *resources = get_resources();
04182
04183 set_font(MEDIUMFONT);
04184 int subindent = 0;
04185
04186
04187 if(column == 0)
04188 {
04189 for(int i = 0; i < data[column].total; i++)
04190 {
04191 if(data[column].values[i]->get_sublist())
04192 {
04193 subindent = BC_WindowBase::get_resources()->listbox_expand[0]->get_w();
04194 break;
04195 }
04196 }
04197 }
04198
04199 for(int i = 0; i < data[column].total; i++)
04200 {
04201
04202 BC_ListBoxItem *item = data[column].values[i];
04203 BC_ListBoxItem *first_item = data[master_column].values[i];
04204
04205 if(get_item_y(item) >= -get_item_h(item) + title_h &&
04206 get_item_y(item) < view_h + title_h)
04207 {
04208 int row_color = get_item_highlight(data, 0, i);
04209 int x, y, w, h, column_width;
04210
04211 get_text_mask(item, x, y, w, h);
04212 column_width = get_column_width(column, 1);
04213 if(x + column_width > view_w + LISTBOX_BORDER * 2)
04214 column_width = view_w + LISTBOX_BORDER * 2 - x;
04215
04216 if(row_color != resources->listbox_inactive)
04217 {
04218 gui->set_color(row_color);
04219 gui->draw_box(x,
04220 y,
04221 column_width,
04222 h);
04223 gui->set_color(BLACK);
04224 gui->draw_line(x,
04225 y,
04226 x + column_width - 1,
04227 y);
04228 gui->draw_line(x,
04229 y + get_text_height(MEDIUMFONT),
04230 x + column_width - 1,
04231 y + get_text_height(MEDIUMFONT));
04232 }
04233
04234 gui->set_color(get_item_color(data, column, i));
04235
04236
04237
04238 gui->draw_text(
04239 x +
04240 LISTBOX_BORDER +
04241 LISTBOX_MARGIN +
04242 (column == 0 ? indent + subindent : 0),
04243 y + get_text_ascent(MEDIUMFONT),
04244 item->text);
04245
04246
04247
04248 if(column == 0 &&
04249 item->get_sublist() &&
04250 item->get_columns())
04251 {
04252
04253 if(*current_toggle >= expanders.total)
04254 {
04255 BC_ListBoxToggle *toggle =
04256 new BC_ListBoxToggle(this,
04257 item,
04258 x + LISTBOX_BORDER + LISTBOX_MARGIN + indent,
04259 y);
04260 toggle->draw(0);
04261 expanders.append(toggle);
04262 }
04263 else
04264
04265 {
04266 BC_ListBoxToggle *toggle = expanders.values[*current_toggle];
04267
04268 toggle->update(item,
04269 x + LISTBOX_BORDER + LISTBOX_MARGIN + indent,
04270 y,
04271 0);
04272 }
04273 (*current_toggle)++;
04274 }
04275
04276
04277
04278 }
04279
04280
04281 if(first_item->get_expand())
04282 {
04283 draw_text_recursive(first_item->get_sublist(),
04284 column,
04285 indent + LISTBOX_INDENT,
04286 current_toggle);
04287 }
04288 }
04289 }
04290
04291
04292
04293
04294
04295 int BC_ListBox::draw_border(int flash)
04296 {
04297 BC_Resources *resources = top_level->get_resources();
04298 gui->draw_3d_border(0,
04299 0,
04300 view_w + LISTBOX_BORDER * 2,
04301 view_h + title_h + LISTBOX_BORDER * 2,
04302 resources->listbox_border1,
04303 list_highlighted ?
04304 resources->listbox_border2_hi :
04305 resources->listbox_border2,
04306 list_highlighted ?
04307 resources->listbox_border3_hi :
04308 resources->listbox_border3,
04309 resources->listbox_border4);
04310
04311 if(flash)
04312 {
04313 gui->flash();
04314 gui->flush();
04315 }
04316 return 0;
04317 }
04318
04319 int BC_ListBox::draw_titles(int flash)
04320 {
04321 if(column_titles && display_format == LISTBOX_TEXT)
04322 {
04323
04324 for(int i = 0; i < columns; i++)
04325 {
04326
04327
04328
04329 int image_number = 0;
04330 if(i == highlighted_title)
04331 {
04332 image_number = 1;
04333 if(current_operation == COLUMN_DN)
04334 image_number = 2;
04335 }
04336
04337 int column_offset = get_column_offset(i) - xposition + LISTBOX_BORDER;
04338 int column_width = get_column_width(i, 1);
04339 gui->draw_3segmenth(get_column_offset(i) - xposition + LISTBOX_BORDER,
04340 LISTBOX_BORDER,
04341 get_column_width(i, 1),
04342 column_bg[image_number]);
04343
04344
04345 if(i == sort_column)
04346 {
04347 BC_Pixmap *src;
04348 if(sort_order == SORT_ASCENDING)
04349 src = column_sort_dn;
04350 else
04351 src = column_sort_up;
04352
04353 int x = column_offset +
04354 column_width -
04355 LISTBOX_BORDER;
04356 if(x > items_w) x = items_w;
04357 x -= 5 + src->get_w();
04358 gui->draw_pixmap(src,
04359 x,
04360 title_h / 2 - src->get_h() / 2 + LISTBOX_BORDER);
04361 }
04362
04363
04364 int x = -xposition +
04365 get_column_offset(i) +
04366 LISTBOX_MARGIN +
04367 LISTBOX_BORDER;
04368 x += get_resources()->listbox_title_margin;
04369
04370 gui->set_color(get_resources()->listbox_title_color);
04371 gui->draw_text(x,
04372 LISTBOX_MARGIN + LISTBOX_BORDER + get_text_ascent(MEDIUMFONT),
04373 _(column_titles[i]));
04374 }
04375 draw_border(0);
04376 }
04377
04378 if(flash)
04379 {
04380 gui->flash();
04381 gui->flush();
04382 }
04383 }
04384
04385 void BC_ListBox::draw_toggles(int flash)
04386 {
04387 for(int i = 0; i < expanders.total; i++)
04388 expanders.values[i]->draw(0);
04389
04390
04391 if(flash && expanders.total)
04392 {
04393 gui->flash();
04394 gui->flush();
04395 }
04396 }
04397
04398 int BC_ListBox::draw_rectangle(int flash)
04399 {
04400 int x1 = MIN(rect_x1, rect_x2);
04401 int x2 = MAX(rect_x1, rect_x2);
04402 int y1 = MIN(rect_y1, rect_y2);
04403 int y2 = MAX(rect_y1, rect_y2);
04404
04405 if(x1 == x2 || y1 == y2) return 0;
04406
04407 gui->set_inverse();
04408 gui->set_color(WHITE);
04409 gui->draw_rectangle(x1, y1, x2 - x1, y2 - y1);
04410 gui->set_opaque();
04411
04412
04413 if(flash)
04414 {
04415 gui->flash();
04416 gui->flush();
04417 }
04418 return 0;
04419 }
04420
04421 void BC_ListBox::dump(ArrayList<BC_ListBoxItem*> *data,
04422 int columns,
04423 int indent,
04424 int master_column)
04425 {
04426 if(!indent)
04427 {
04428 printf("BC_ListBox::dump 1\n");
04429 }
04430
04431 for(int i = 0; i < data[master_column].total; i++)
04432 {
04433 for(int k = 0; k < indent; k++)
04434 printf(" ");
04435 for(int j = 0; j < columns; j++)
04436 {
04437 BC_ListBoxItem *item = data[j].values[i];
04438 printf("%d,%d,%d=%s ",
04439 item->get_text_x(),
04440 item->get_text_y(),
04441 item->autoplace_text,
04442 item->get_text());
04443 }
04444 printf("\n");
04445
04446 if(data[master_column].values[i]->get_sublist())
04447 {
04448 dump(data[master_column].values[i]->get_sublist(),
04449 data[master_column].values[i]->get_columns(),
04450 indent + 4,
04451 master_column);
04452 }
04453 }
04454
04455
04456 }
04457
04458
04459
04460