Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

bclistbox.C

Go to the documentation of this file.
00001 #include "bcdragwindow.h"
00002 #include "bclistbox.h"
00003 #include "bclistboxitem.h"
00004 #include "bcpixmap.h"
00005 #include "bcresources.h"
00006 #include "clip.h"
00007 #include "cursors.h"
00008 #include "fonts.h"
00009 #include "keys.h"
00010 #include "language.h"
00011 #include "bctimer.h"
00012 #include "vframe.h"
00013 
00014 #include <string.h>
00015 #include <unistd.h>
00016 
00017 // ====================================================== scrollbars
00018 
00019 
00020 BC_ListBoxYScroll::BC_ListBoxYScroll(BC_ListBox *listbox, 
00021                           int total_height, 
00022                                           int view_height, 
00023                           int position)
00024  : BC_ScrollBar(listbox->get_yscroll_x(), 
00025         listbox->get_yscroll_y(), 
00026         SCROLL_VERT, 
00027         listbox->get_yscroll_height(), 
00028         total_height, 
00029         position, 
00030         view_height)
00031 {
00032         this->listbox = listbox;
00033 }
00034 
00035 BC_ListBoxYScroll::~BC_ListBoxYScroll()
00036 {
00037 }
00038 
00039 int BC_ListBoxYScroll::handle_event()
00040 {
00041         listbox->set_yposition(get_value());
00042         return 1;
00043 }
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 BC_ListBoxXScroll::BC_ListBoxXScroll(BC_ListBox *listbox, 
00052                           int total_width, 
00053                                           int view_width,
00054                           int position)
00055  : BC_ScrollBar(listbox->get_xscroll_x(), 
00056         listbox->get_xscroll_y(), 
00057         SCROLL_HORIZ, 
00058         listbox->get_xscroll_width(), 
00059         total_width, 
00060         position, 
00061         view_width)
00062 {
00063         this->listbox = listbox;
00064 }
00065 
00066 BC_ListBoxXScroll::~BC_ListBoxXScroll()
00067 {
00068 }
00069 
00070 int BC_ListBoxXScroll::handle_event()
00071 {
00072         listbox->set_xposition(get_value());
00073         return 1;
00074 }
00075 
00076 
00077 
00078 
00079 
00080 
00081 
00082 
00083 BC_ListBoxToggle::BC_ListBoxToggle(BC_ListBox *listbox, 
00084         BC_ListBoxItem *item, 
00085         int x, 
00086         int y)
00087 {
00088         this->listbox = listbox;
00089         this->item = item;
00090         this->x = x;
00091         this->y = y;
00092         this->value = item->get_expand();
00093         if(this->value) 
00094                 state = BC_Toggle::TOGGLE_CHECKED;
00095         else
00096                 state = BC_Toggle::TOGGLE_UP;
00097 }
00098 
00099 void BC_ListBoxToggle::update(BC_ListBoxItem *item, 
00100         int x, 
00101         int y,
00102         int flash)
00103 {
00104         this->value = item->get_expand();
00105         this->item = item;
00106         this->x = x;
00107         this->y = y;
00108 
00109 // update state
00110         switch(state)
00111         {
00112                 case TOGGLE_UP:
00113                         if(value)
00114                                 state = TOGGLE_CHECKED;
00115                         break;
00116 
00117                 case TOGGLE_UPHI:
00118                         if(value)
00119                                 state = TOGGLE_CHECKEDHI;
00120                         break;
00121 
00122                 case TOGGLE_CHECKED:
00123                         if(!value)
00124                                 state = TOGGLE_UP;
00125                         break;
00126 
00127                 case TOGGLE_DOWN:
00128                         break;
00129 
00130                 case TOGGLE_CHECKEDHI:
00131                         if(!value)
00132                                 state = TOGGLE_UPHI;
00133                         break;
00134 
00135                 case TOGGLE_DOWN_EXIT:
00136                         break;
00137         }
00138 
00139 
00140         draw(flash);
00141 }
00142 
00143 int BC_ListBoxToggle::cursor_motion_event(int *redraw_toggles)
00144 {
00145         int w = listbox->toggle_images[0]->get_w();
00146         int h = listbox->toggle_images[0]->get_h();
00147         int cursor_inside = listbox->get_cursor_x() >= x && 
00148                 listbox->get_cursor_x() < x + w &&
00149                 listbox->get_cursor_y() >= y && 
00150                 listbox->get_cursor_y() < y + h;
00151         int result = 0;
00152 
00153         switch(state)
00154         {
00155                 case BC_ListBoxToggle::TOGGLE_UPHI:
00156                         if(!cursor_inside)
00157                         {
00158                                 state = BC_ListBoxToggle::TOGGLE_UP;
00159                                 *redraw_toggles = 1;
00160                         }
00161                         break;
00162 
00163                 case BC_ListBoxToggle::TOGGLE_CHECKEDHI:
00164                         if(!cursor_inside)
00165                         {
00166                                 state = BC_ListBoxToggle::TOGGLE_CHECKED;
00167                                 *redraw_toggles = 1;
00168                         }
00169                         break;
00170 
00171                 case BC_ListBoxToggle::TOGGLE_DOWN:
00172                         if(!cursor_inside)
00173                         {
00174                                 state = BC_ListBoxToggle::TOGGLE_DOWN_EXIT;
00175                                 *redraw_toggles = 1;
00176                         }
00177                         result = 1;
00178                         break;
00179 
00180                 case BC_ListBoxToggle::TOGGLE_DOWN_EXIT:
00181                         if(cursor_inside)
00182                         {
00183                                 state = BC_ListBoxToggle::TOGGLE_DOWN;
00184                                 *redraw_toggles = 1;
00185                         }
00186                         result = 1;
00187                         break;
00188 
00189                 default:
00190                         if(cursor_inside)
00191                         {
00192                                 if(value)
00193                                         state = BC_ListBoxToggle::TOGGLE_CHECKEDHI;
00194                                 else
00195                                         state = BC_ListBoxToggle::TOGGLE_UPHI;
00196                                 *redraw_toggles = 1;
00197                         }
00198                         break;
00199         }
00200         return result;
00201 }
00202 
00203 int BC_ListBoxToggle::cursor_leave_event(int *redraw_toggles)
00204 {
00205         if(value)
00206                 state = BC_ListBoxToggle::TOGGLE_CHECKED;
00207         else
00208                 state = BC_ListBoxToggle::TOGGLE_UP;
00209 }
00210 
00211 int BC_ListBoxToggle::button_press_event()
00212 {
00213         int w = listbox->toggle_images[0]->get_w();
00214         int h = listbox->toggle_images[0]->get_h();
00215 
00216         if(listbox->gui->get_cursor_x() >= x && 
00217                 listbox->gui->get_cursor_x() < x + w &&
00218                 listbox->gui->get_cursor_y() >= y && 
00219                 listbox->gui->get_cursor_y() < y + h)
00220         {
00221                 state = BC_ListBoxToggle::TOGGLE_DOWN;
00222                 return 1;
00223         }
00224         return 0;
00225 }
00226 
00227 int BC_ListBoxToggle::button_release_event(int *redraw_toggles)
00228 {
00229         int result = 0;
00230         switch(state)
00231         {
00232                 case BC_ListBoxToggle::TOGGLE_DOWN:
00233                         value = !value;
00234                         if(value)
00235                                 state = BC_ListBoxToggle::TOGGLE_CHECKEDHI;
00236                         else
00237                                 state = BC_ListBoxToggle::TOGGLE_UPHI;
00238                         listbox->expand_item(item, value);
00239                         result = 1;
00240                         break;
00241 
00242                 case BC_ListBoxToggle::TOGGLE_DOWN_EXIT:
00243                         if(value)
00244                                 state = BC_ListBoxToggle::TOGGLE_CHECKED;
00245                         else
00246                                 state = BC_ListBoxToggle::TOGGLE_UP;
00247                         *redraw_toggles = 1;
00248                         result = 1;
00249                         break;
00250         }
00251         return result;
00252 }
00253 
00254 void BC_ListBoxToggle::draw(int flash)
00255 {
00256         if(listbox->gui)
00257         {
00258                 int image_number = 0;
00259                 int w = listbox->toggle_images[0]->get_w();
00260                 int h = listbox->toggle_images[0]->get_h();
00261 
00262                 switch(state)
00263                 {
00264                         case BC_ListBoxToggle::TOGGLE_UP: image_number = 0; break;
00265                         case BC_ListBoxToggle::TOGGLE_UPHI: image_number = 1; break;
00266                         case BC_ListBoxToggle::TOGGLE_CHECKED: image_number = 2; break;
00267                         case BC_ListBoxToggle::TOGGLE_DOWN: image_number = 3; break;
00268                         case BC_ListBoxToggle::TOGGLE_CHECKEDHI: image_number = 4; break;
00269                         case BC_ListBoxToggle::TOGGLE_DOWN_EXIT:
00270                                 if(value)
00271                                         image_number = 2;
00272                                 else
00273                                         image_number = 0;
00274                                 break;
00275                 }
00276 
00277 //printf("BC_ListBoxToggle::draw 1 %d\n", state);
00278                 listbox->gui->draw_pixmap(listbox->toggle_images[image_number],
00279                         x,
00280                         y);
00281 
00282 
00283                 if(flash)
00284                 {
00285                         listbox->gui->flash(x, y, w, h);
00286                         listbox->gui->flush();
00287                 }
00288         }
00289 }
00290 
00291 
00292 
00293 
00294 
00295 
00296 
00297 
00298 
00299 
00300 
00301 
00302 
00303 
00304 // ====================================================== box
00305 
00306 BC_ListBox::BC_ListBox(int x, 
00307         int y, 
00308         int w, 
00309         int h,
00310         int display_format,
00311         ArrayList<BC_ListBoxItem*> *data,
00312         char **column_titles,
00313         int *column_width,
00314         int columns,
00315         int yposition,
00316         int is_popup,
00317         int selection_mode,
00318         int icon_position,
00319         int allow_drag)
00320  : BC_SubWindow(x, y, w, h, -1)
00321 {
00322         justify = LISTBOX_RIGHT;
00323         xposition = 0;
00324         highlighted_item = -1;
00325         highlighted_title = -1;
00326         highlighted_division = -1;
00327         highlighted_ptr = 0;
00328         xscrollbar = 0;
00329         yscrollbar = 0;
00330         current_cursor = ARROW_CURSOR;
00331         gui = 0;
00332         view_h = 0;
00333         view_w = 0;
00334         title_h = 0;
00335         active = 0;
00336         new_value = 0;
00337         need_xscroll = 0;
00338         need_yscroll = 0;
00339         bg_tile = 0;
00340         drag_popup = 0;
00341         selection_number1 = -1;
00342         selection_number2 = -1;
00343         bg_surface = 0;
00344         bg_pixmap = 0;
00345 
00346         current_operation = NO_OPERATION;
00347         button_highlighted = 0;
00348 
00349         disabled = 0;
00350 
00351         list_highlighted = 0;
00352 
00353         allow_drag_scroll = 1;
00354         process_drag = 1;
00355 
00356         sort_column = -1;
00357         sort_order = 0;
00358 
00359         allow_drag_column = 0;
00360         master_column = 0;
00361         search_column = 0;
00362 
00363         popup_w = w;
00364         popup_h = h;
00365 
00366         for(int i = 0; i < 3; i++)
00367                 column_bg[i] = 0;
00368 
00369         for(int i = 0; i < 4; i++)
00370                 button_images[i] = 0;
00371 
00372         for(int i = 0; i < 5; i++)
00373                 toggle_images[i] = 0;
00374 
00375         column_sort_up = 0;
00376         column_sort_dn = 0;
00377 
00378 //printf("BC_ListBox::BC_ListBox 1\n");
00379         this->data = data;
00380         this->columns = columns;
00381         this->yposition = yposition;
00382         this->is_popup = is_popup;
00383         this->display_format = display_format;
00384         this->selection_mode = selection_mode;
00385         this->icon_position = icon_position;
00386         this->allow_drag = allow_drag;
00387         this->column_titles = 0;
00388         this->column_width = 0;
00389 //printf("BC_ListBox::BC_ListBox 1\n");
00390 
00391         if((!column_titles && column_width) ||
00392                 (column_titles && !column_width))
00393         {
00394                 printf("BC_ListBox::BC_ListBox either column_titles or column_widths == NULL but not both.\n");
00395         }
00396 //printf("BC_ListBox::BC_ListBox 2 %p %p\n", column_titles, column_width);
00397         set_columns(column_titles, 
00398                 column_width, 
00399                 columns);
00400 
00401 //printf("BC_ListBox::BC_ListBox 3\n");
00402 
00403         drag_icon_vframe = 0;
00404         drag_column_icon_vframe = 0;
00405 
00406 
00407 
00408 // reset the search engine
00409 //printf("BC_ListBox::BC_ListBox 4\n");
00410         reset_query();
00411 //printf("BC_ListBox::BC_ListBox 5\n");
00412 }
00413 
00414 BC_ListBox::~BC_ListBox()
00415 {
00416         expanders.remove_all_objects();
00417         if(bg_surface) delete bg_surface;
00418         if(bg_pixmap) delete bg_pixmap;
00419         if(xscrollbar) delete xscrollbar;
00420         if(yscrollbar) delete yscrollbar;
00421         for(int i = 0; i < 3; i++)
00422                 if(column_bg[i]) delete column_bg[i];
00423         for(int i = 0; i < 4; i++)
00424                 if(button_images[i]) delete button_images[i];
00425         for(int i = 0; i < 5; i++)
00426                 if(toggle_images[i]) delete toggle_images[i];
00427         if(column_sort_up) delete column_sort_up;
00428         if(column_sort_dn) delete column_sort_dn;
00429 
00430         delete_columns();
00431         if(drag_popup) delete drag_popup;
00432 }
00433 
00434 int BC_ListBox::enable()
00435 {
00436   disabled = 0;
00437   draw_button();
00438   return 1;
00439 }
00440 
00441 int BC_ListBox::disable()
00442 {
00443   disabled = 1;
00444   draw_button();
00445   return 1;
00446 }
00447 
00448 void BC_ListBox::reset_query()
00449 {
00450         query[0] = 0;  // reset query
00451 }
00452 
00453 int BC_ListBox::evaluate_query(int list_item, char *string)
00454 {
00455         return(strcmp(string, data[search_column].values[list_item]->text) <= 0 && 
00456                 data[search_column].values[list_item]->searchable);
00457 }
00458 
00459 int BC_ListBox::query_list()
00460 {
00461         if(query[0] == 0) return 0;
00462 
00463         int done = 0;
00464         int result;
00465         int selection_changed = 0;
00466         int prev_selection = -1;
00467         for(int i = 0; !done && i < data[0].total; i++)
00468         {
00469                 if(evaluate_query(i, query))
00470                 {
00471                         result = i;
00472                         done = 1;
00473                 }
00474         }
00475 
00476         if(done)
00477         {
00478 // Deselect all
00479                 for(int i = 0; i < data[0].total; i++)
00480                 {
00481                         for(int j = 0; j < columns; j++)
00482                         {
00483                                 if(data[j].values[i]->selected) prev_selection = i;
00484                                 data[j].values[i]->selected = 0;
00485                         }
00486                 }
00487 
00488 // Select one
00489                 if(prev_selection != result)
00490                         selection_changed = 1;
00491                 for(int j = 0; j < columns; j++)
00492                 {
00493                         data[j].values[result]->selected = 1;
00494                 }
00495                 center_selection(result);
00496         }
00497 
00498         return selection_changed;
00499 }
00500 
00501 void BC_ListBox::init_column_width()
00502 {
00503         if(!column_width && data)
00504         {
00505                 int widest = 5, w;
00506                 for(int i = 0; i < data[0].total; i++)
00507                 {
00508                         w = get_text_width(MEDIUMFONT, data[0].values[i]->get_text()) + 2 * LISTBOX_MARGIN;
00509                         if(w > widest) widest = w;
00510                 }
00511                 default_column_width[0] = widest;
00512         }
00513 }
00514 
00515 int BC_ListBox::initialize()
00516 {
00517         if(is_popup)
00518         {
00519                 for(int i = 0; i < 4; i++)
00520                 {
00521                         button_images[i] = new BC_Pixmap(parent_window, 
00522                                 BC_WindowBase::get_resources()->listbox_button[i], 
00523                                 PIXMAP_ALPHA);
00524                 }
00525                 w = button_images[0]->get_w();
00526                 h = button_images[0]->get_h();
00527                 
00528                 gui = 0;
00529                 current_operation = NO_OPERATION;
00530         }
00531         else
00532         {
00533                 gui = this;
00534                 current_operation = NO_OPERATION;
00535         }
00536 
00537         for(int i = 0; i < 3; i++)
00538         {
00539                 column_bg[i] = new BC_Pixmap(parent_window,
00540                         get_resources()->listbox_column[i],
00541                         PIXMAP_ALPHA);
00542         }
00543         for(int i = 0; i < 5; i++)
00544         {
00545                 toggle_images[i] = new BC_Pixmap(parent_window,
00546                         get_resources()->listbox_expand[i],
00547                         PIXMAP_ALPHA);
00548         }
00549 
00550         column_sort_up = new BC_Pixmap(parent_window, 
00551                 BC_WindowBase::get_resources()->listbox_up, 
00552                 PIXMAP_ALPHA);
00553         column_sort_dn = new BC_Pixmap(parent_window, 
00554                 BC_WindowBase::get_resources()->listbox_dn, 
00555                 PIXMAP_ALPHA);
00556 
00557 //printf("BC_ListBox::initialize 10\n");
00558         drag_icon_vframe = get_resources()->type_to_icon[ICON_UNKNOWN];
00559         drag_column_icon_vframe = get_resources()->type_to_icon[ICON_COLUMN];
00560 // = new BC_Pixmap(parent_window, 
00561 //              get_resources()->type_to_icon[ICON_UNKNOWN], 
00562 //              PIXMAP_ALPHA);
00563 //      drag_column_icon = new BC_Pixmap(parent_window,
00564 //              get_resources()->type_to_icon[ICON_COLUMN],
00565 //              PIXMAP_ALPHA);
00566         BC_SubWindow::initialize();
00567 
00568         init_column_width();
00569 
00570         if(top_level->get_resources()->listbox_bg)
00571                 bg_pixmap = new BC_Pixmap(this, 
00572                         get_resources()->listbox_bg, 
00573                         PIXMAP_OPAQUE);
00574 
00575         draw_button();
00576         draw_items(1);
00577         return 0;
00578 }
00579 
00580 void BC_ListBox::deactivate_selection()
00581 {
00582         current_operation = NO_OPERATION;
00583 }
00584 
00585 int BC_ListBox::draw_button()
00586 {
00587 // Draw the button for a popup listbox
00588         if(is_popup)
00589         {
00590                 int image_number = 0;
00591 
00592                 draw_top_background(parent_window, 0, 0, w, h);
00593 
00594                 if(button_highlighted)
00595                         image_number = 1;
00596                 if(current_operation == BUTTON_DN)
00597                         image_number = 2;
00598                 if(disabled)
00599                         image_number = 3;
00600 
00601 
00602                 button_images[image_number]->write_drawable(pixmap, 
00603                         0, 
00604                         0,
00605                         w,
00606                         h,
00607                         0,
00608                         0);
00609                 flash();
00610         }
00611         return 0;
00612 }
00613 
00614 int BC_ListBox::calculate_item_coords()
00615 {
00616         if(!data) return 0;
00617 
00618         int icon_x = 0;
00619         int next_icon_x = 0;
00620         int next_icon_y = 0;
00621         int next_text_y = 0;
00622 // Change the display_format to get the right item dimensions for both
00623 // text and icons.
00624         int display_format_temp = display_format;
00625 
00626 
00627 // Scan the first column for lowest y coord of all text
00628 // and lowest right x and y coord for all icons which aren't auto placable
00629         calculate_last_coords_recursive(data,
00630                 &icon_x,
00631                 &next_icon_x, 
00632                 &next_icon_y,
00633                 &next_text_y,
00634                 1);
00635 
00636 // Reset last column width.  It's recalculated based on text width.
00637 
00638         calculate_item_coords_recursive(data,
00639                 &icon_x,
00640                 &next_icon_x, 
00641                 &next_icon_y,
00642                 &next_text_y,
00643                 1);
00644 
00645 
00646 
00647         display_format = display_format_temp;
00648 
00649         return 0;
00650 }
00651 
00652 void BC_ListBox::calculate_last_coords_recursive(
00653         ArrayList<BC_ListBoxItem*> *data,
00654         int *icon_x,
00655         int *next_icon_x,
00656         int *next_icon_y,
00657         int *next_text_y,
00658         int top_level)
00659 {
00660         for(int i = 0; i < data[0].total; i++)
00661         {
00662                 int current_text_y = 0;
00663                 int current_icon_x = 0;
00664                 int current_icon_y = 0;
00665                 BC_ListBoxItem *item = data[0].values[i];
00666 
00667 // Get next_text_y
00668                 if(!item->autoplace_text)
00669                 {
00670 // Lowest text coordinate
00671                         display_format = LISTBOX_TEXT;
00672                         current_text_y = item->text_y + 
00673                                 get_text_height(MEDIUMFONT);
00674                         if(current_text_y > *next_text_y)
00675                                 *next_text_y = current_text_y;
00676 
00677 // Add sublist depth if it is expanded
00678                         if(item->get_sublist() && 
00679                                 item->get_columns() &&
00680                                 item->get_expand())
00681                         {
00682                                 calculate_last_coords_recursive(item->get_sublist(),
00683                                         icon_x,
00684                                         next_icon_x, 
00685                                         next_icon_y,
00686                                         next_text_y,
00687                                         0);
00688                         }
00689                 }
00690 
00691 // Get next_icon coordinate
00692                 if(top_level)
00693                 {
00694                         BC_ListBoxItem *item = data[master_column].values[i];
00695                         if(!item->autoplace_icon)
00696                         {
00697                                 display_format = LISTBOX_ICONS;
00698 // Lowest right icon coordinate.
00699                                 current_icon_x = item->icon_x;
00700                                 if(current_icon_x > *icon_x) *icon_x = current_icon_x;
00701                                 if(current_icon_x + get_item_w(item) > *next_icon_x)
00702                                         *next_icon_x = current_icon_x + get_item_w(item);
00703 
00704                                 current_icon_y = item->icon_y + get_item_h(item);
00705                                 if(current_icon_y > *next_icon_y) 
00706                                         *next_icon_y = current_icon_y;
00707                         }
00708                 }
00709         }
00710 }
00711 
00712 
00713 void BC_ListBox::calculate_item_coords_recursive(
00714         ArrayList<BC_ListBoxItem*> *data,
00715         int *icon_x,
00716         int *next_icon_x,
00717         int *next_icon_y,
00718         int *next_text_y,
00719         int top_level)
00720 {
00721 
00722 
00723 
00724 // Set up items which need autoplacement.
00725 // Should fill icons down and then across
00726         for(int i = 0; i < data[0].total; i++)
00727         {
00728 // Don't increase y unless the row requires autoplacing.
00729                 int total_autoplaced_columns = 0;
00730 
00731 // Set up icons in first column
00732                 if(top_level)
00733                 {
00734                         BC_ListBoxItem *item = data[master_column].values[i];
00735                         if(item->autoplace_icon)
00736                         {
00737 // 1 column only if icons are used
00738                                 display_format = LISTBOX_ICONS;
00739 // Test row height
00740 // Start new row.
00741                                 if(*next_icon_y + get_item_h(item) >= get_h() && 
00742                                         *next_icon_y > 0)
00743                                 {
00744                                         *icon_x = *next_icon_x;
00745                                         *next_icon_y = 0;
00746                                 }
00747 
00748                                 if(*icon_x + get_item_w(item) > *next_icon_x)
00749                                         *next_icon_x = *icon_x + get_item_w(item);
00750 
00751 
00752                                 item->set_icon_x(*icon_x);
00753                                 item->set_icon_y(*next_icon_y);
00754 
00755                                 *next_icon_y += get_item_h(item);
00756                         }
00757                 }
00758 
00759 
00760 
00761 // Set up a text row
00762                 int next_text_x = 0;
00763                 for(int j = 0; j < columns; j++)
00764                 {
00765                         BC_ListBoxItem *item = data[j].values[i];
00766                         if(item->autoplace_text)
00767                         {
00768                                 display_format = LISTBOX_TEXT;
00769                                 item->set_text_x(next_text_x);
00770                                 item->set_text_y(*next_text_y);
00771 
00772 // printf("BC_ListBox::calculate_item_coords_recursive %p %d %d %d %d %s \n", 
00773 // item->get_sublist(), 
00774 // item->get_columns(), 
00775 // item->get_expand(), 
00776 // next_text_x, 
00777 // *next_text_y,
00778 // item->get_text());
00779 // Increment position of next column
00780                                 if(j < columns - 1)
00781                                         next_text_x += (column_width ? 
00782                                                 column_width[j] : 
00783                                                 default_column_width[j]);
00784                                 else
00785 // Set last column width based on text width
00786                                 {
00787                                         int new_w = get_item_w(item);
00788 
00789                                         int *previous_w = (column_width ? 
00790                                                 &column_width[j] : 
00791                                                 &default_column_width[j]);
00792                                         if(new_w > *previous_w)
00793                                                 *previous_w = new_w;
00794 //printf("BC_ListBox::calculate_item_coords_recursive 1 %d\n", new_w);
00795                                 }
00796                                 total_autoplaced_columns++;
00797                         }
00798                 }
00799 
00800 // Increase the text vertical position
00801                 if(total_autoplaced_columns)
00802                 {
00803                         display_format = LISTBOX_TEXT;
00804                         *next_text_y += get_text_height(MEDIUMFONT);
00805                 }
00806 
00807 // Set up a sublist
00808                 BC_ListBoxItem *item = data[master_column].values[i];
00809                 if(item->get_sublist() &&
00810                         item->get_columns() &&
00811                         item->get_expand())
00812                 {
00813                         calculate_item_coords_recursive(
00814                                 item->get_sublist(),
00815                                 icon_x,
00816                                 next_icon_x,
00817                                 next_icon_y,
00818                                 next_text_y,
00819                                 0);
00820                 }
00821         }
00822 }
00823 
00824 void BC_ListBox::set_justify(int value)
00825 {
00826         this->justify = value;
00827 }
00828 
00829 void BC_ListBox::set_allow_drag_column(int value)
00830 {
00831         this->allow_drag_column = value;
00832 }
00833 
00834 void BC_ListBox::set_process_drag(int value)
00835 {
00836         this->process_drag = value;
00837 }
00838 
00839 void BC_ListBox::set_master_column(int value, int redraw)
00840 {
00841         this->master_column = value;
00842         if(redraw)
00843         {
00844                 draw_items(1);
00845         }
00846 }
00847 
00848 void BC_ListBox::set_search_column(int value)
00849 {
00850         this->search_column = value;
00851 }
00852 
00853 int BC_ListBox::get_sort_column()
00854 {
00855         return sort_column;
00856 }
00857 
00858 void BC_ListBox::set_sort_column(int value, int redraw)
00859 {
00860         sort_column = value;
00861         if(redraw)
00862         {
00863                 draw_titles(1);
00864         }
00865 }
00866 
00867 int BC_ListBox::get_sort_order()
00868 {
00869         return sort_order;
00870 }
00871 
00872 void BC_ListBox::set_sort_order(int value, int redraw)
00873 {
00874         sort_order = value;
00875         if(redraw)
00876         {
00877                 draw_titles(1);
00878         }
00879 }
00880 
00881 
00882 
00883 
00884 
00885 int BC_ListBox::get_display_mode()
00886 {
00887         return display_format;
00888 }
00889 
00890 int BC_ListBox::get_yposition()
00891 {
00892         return yposition;
00893 }
00894 
00895 int BC_ListBox::get_xposition()
00896 {
00897         return xposition;
00898 }
00899 
00900 int BC_ListBox::get_highlighted_item()
00901 {
00902         return highlighted_item;
00903 }
00904 
00905 
00906 int BC_ListBox::get_item_x(BC_ListBoxItem *item)
00907 {
00908         if(display_format == LISTBOX_TEXT)
00909                 return item->text_x - xposition + 2;
00910         else
00911                 return item->icon_x - xposition + 2;
00912 }
00913 
00914 int BC_ListBox::get_item_y(BC_ListBoxItem *item)
00915 {
00916         int result;
00917         if(display_format == LISTBOX_TEXT)
00918                 result = item->text_y - yposition + title_h + 2;
00919         else
00920                 result = item->icon_y - yposition + title_h + 2;
00921         return result;
00922 }
00923 
00924 int BC_ListBox::get_item_w(BC_ListBoxItem *item)
00925 {
00926         if(display_format == LISTBOX_ICONS)
00927         {
00928                 int x, y, w, h;
00929                 get_icon_mask(item, x, y, w, h);
00930                 int icon_w = w;
00931                 get_text_mask(item, x, y, w, h);
00932                 int text_w = w;
00933 
00934                 if(icon_position == ICON_LEFT)
00935                         return icon_w + text_w;
00936                 else
00937                         return (icon_w > text_w) ? icon_w : text_w;
00938         }
00939         else
00940         {
00941                 return get_text_width(MEDIUMFONT, item->text) + 2 * LISTBOX_MARGIN;
00942         }
00943 }
00944 
00945 int BC_ListBox::get_item_h(BC_ListBoxItem *item)
00946 {
00947         if(display_format == LISTBOX_ICONS)
00948         {
00949                 int x, y, w, h;
00950                 get_icon_mask(item, x, y, w, h);
00951                 int icon_h = h;
00952                 get_text_mask(item, x, y, w, h);
00953                 int text_h = h;
00954 
00955                 if(icon_position == ICON_LEFT)
00956                         return (icon_h > text_h) ? icon_h : text_h;
00957                 else
00958                         return icon_h + text_h;
00959         }
00960         else
00961         {
00962                 return get_text_height(MEDIUMFONT);
00963         }
00964         return 0;
00965 }
00966 
00967 
00968 int BC_ListBox::get_icon_w(BC_ListBoxItem *item)
00969 {
00970         BC_Pixmap *icon = item->icon;
00971         if(icon) return icon->get_w();
00972         return 0;
00973 }
00974 
00975 int BC_ListBox::get_icon_h(BC_ListBoxItem *item)
00976 {
00977         BC_Pixmap *icon = item->icon;
00978         if(icon) return icon->get_h();
00979         return 0;
00980 }
00981 
00982 int BC_ListBox::get_items_width()
00983 {
00984         int widest = 0;
00985 
00986         if(display_format == LISTBOX_ICONS)
00987         {
00988                 for(int i = 0; i < columns; i++)
00989                 {
00990                         for(int j = 0; j < data[i].total; j++)
00991                         {
00992                                 int x1, x, y, w, h;
00993                                 BC_ListBoxItem *item = data[i].values[j];
00994                                 x1 = item->icon_x;
00995 
00996                                 get_icon_mask(item, x, y, w, h);
00997                                 if(x1 + w > widest) widest = x1 + w;
00998 
00999                                 if(display_format == LISTBOX_ICONS && icon_position == ICON_LEFT)
01000                                         x1 += w;
01001 
01002                                 get_text_mask(item, x, y, w, h);
01003                                 if(x1 + w > widest) widest = x1 + w;
01004                         }
01005                 }
01006         }
01007         else
01008         if(display_format == LISTBOX_TEXT)
01009         {
01010                 return get_column_offset(columns);
01011         }
01012         return widest;
01013 }
01014 
01015 int BC_ListBox::get_items_height(ArrayList<BC_ListBoxItem*> *data, 
01016         int columns,
01017         int *result)
01018 {
01019         int temp = 0;
01020         int top_level = 0;
01021         int highest = 0;
01022         if(!result)
01023         {
01024                 result = &temp;
01025                 top_level = 1;
01026         }
01027 
01028 
01029 
01030 
01031 
01032         for(int j = 0; j < (data ? data[master_column].total : 0); j++)
01033         {
01034                 int y1, x, y, w, h;
01035                 BC_ListBoxItem *item = data[master_column].values[j];
01036 
01037                 if(display_format == LISTBOX_ICONS)
01038                 {
01039                         get_icon_mask(item, x, y, w, h);
01040                         if(y + h + yposition > highest) highest = y + h + yposition;
01041 
01042                         get_text_mask(item, x, y, w, h);
01043                         if(y + h + yposition > highest) highest = y + h + yposition;
01044                 }
01045                 else
01046                 {
01047                         get_text_mask(item, x, y, w, h);
01048                         *result += h;
01049 
01050 
01051 // Descend into sublist
01052                         if(item->get_sublist() &&
01053                                 item->get_expand())
01054                         {
01055                                 get_items_height(item->get_sublist(), 
01056                                         item->get_columns(), 
01057                                         result);
01058                         }
01059                 }
01060         }
01061         if(display_format == LISTBOX_TEXT && top_level) 
01062         {
01063                 highest = LISTBOX_MARGIN + *result;
01064         }
01065 
01066 
01067         return highest;
01068 }
01069 
01070 int BC_ListBox::set_yposition(int position, int draw_items)
01071 {
01072         this->yposition = position;
01073         if(draw_items)
01074         {
01075                 this->draw_items(1);
01076         }
01077         return 0;
01078 }
01079 
01080 int BC_ListBox::set_xposition(int position)
01081 {
01082         this->xposition = position;
01083         draw_items(1);
01084         return 0;
01085 }
01086 
01087 void BC_ListBox::expand_item(BC_ListBoxItem *item, int expand)
01088 {
01089         if(item)
01090         {
01091                 item->expand = expand;
01092 // Collapse sublists if this is collapsed to make it easier to calculate
01093 // coordinates
01094                 if(item->get_sublist())
01095                         collapse_recursive(item->get_sublist(), master_column);
01096 
01097 
01098 // Set everything for autoplacement
01099                 
01100                 set_autoplacement(data, 0, 1);
01101 
01102                 draw_items(1);
01103         }
01104 }
01105 
01106 void BC_ListBox::collapse_recursive(ArrayList<BC_ListBoxItem*> *data,
01107                 int master_column)
01108 {
01109         for(int i = 0; i < data[master_column].total; i++)
01110         {
01111                 BC_ListBoxItem *item = data[master_column].values[i];
01112                 if(item->get_sublist() && item->expand)
01113                 {
01114                         item->expand = 0;
01115                         collapse_recursive(item->get_sublist(), master_column);
01116                 }
01117         }
01118 }
01119 
01120 void BC_ListBox::set_autoplacement(ArrayList<BC_ListBoxItem*> *data,
01121         int do_icons, 
01122         int do_text)
01123 {
01124         for(int i = 0; i < data[0].total; i++)
01125         {
01126                 for(int j = 0; j < columns; j++)
01127                 {
01128                         if(do_icons) data[j].values[i]->autoplace_icon = 1;
01129                         if(do_text) data[j].values[i]->autoplace_text = 1;
01130                 }
01131 
01132                 BC_ListBoxItem *item = data[master_column].values[i];
01133                 if(item->get_sublist())
01134                 {
01135                         set_autoplacement(item->get_sublist(), do_icons, do_text);
01136                 }
01137         }
01138 }
01139 
01140 
01141 
01142 int BC_ListBox::get_w()
01143 {
01144         if(is_popup)
01145                 return BCPOPUPLISTBOX_W;
01146         else
01147                 return popup_w;
01148 }
01149 
01150 int BC_ListBox::get_h()
01151 {
01152         if(is_popup)
01153                 return BCPOPUPLISTBOX_H;
01154         else
01155                 return popup_h;
01156 }
01157 
01158 int BC_ListBox::get_yscroll_x()
01159 {
01160         if(is_popup)
01161                 return popup_w - get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w();
01162         else
01163                 return get_x() + 
01164                         popup_w - 
01165                         get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w();
01166 }
01167 
01168 int BC_ListBox::get_yscroll_y()
01169 {
01170         if(is_popup)
01171                 return 0;
01172         else
01173                 return get_y();
01174 }
01175 
01176 int BC_ListBox::get_yscroll_height()
01177 {
01178         return popup_h - (need_xscroll ? 
01179                 get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h() : 
01180                 0);
01181 }
01182 
01183 int BC_ListBox::get_xscroll_x()
01184 {
01185         if(is_popup)
01186                 return 0;
01187         else
01188                 return get_x();
01189 }
01190 
01191 int BC_ListBox::get_xscroll_y()
01192 {
01193         if(is_popup)
01194                 return popup_h - 
01195                         get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h();
01196         else
01197                 return get_y() + 
01198                         popup_h - 
01199                         get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h();
01200 }
01201 
01202 int BC_ListBox::get_xscroll_width()
01203 {
01204         return popup_w - (need_yscroll ? 
01205                 get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w() : 
01206                 0);
01207 }
01208 
01209 int BC_ListBox::get_column_offset(int column)
01210 {
01211         int x = 0;
01212         while(column > 0)
01213         {
01214                 x += column_width ? 
01215                         column_width[--column] : 
01216                         default_column_width[--column];
01217         }
01218         return x;
01219 }
01220 
01221 void BC_ListBox::column_width_boundaries()
01222 {
01223         if(column_width)
01224         {
01225                 for(int i = 0; i < columns; i++)
01226                 {
01227                         if(column_width[i] < MIN_COLUMN_WIDTH) column_width[i] = MIN_COLUMN_WIDTH;
01228                 }
01229         }
01230         else
01231         {
01232                 for(int i = 0; i < columns; i++)
01233                 {
01234                         if(default_column_width[i] < MIN_COLUMN_WIDTH) default_column_width[i] = MIN_COLUMN_WIDTH;
01235                 }
01236         }
01237 }
01238 
01239 int BC_ListBox::get_column_width(int column, int clamp_right)
01240 {
01241         if(column < columns - 1 || !clamp_right)
01242                 return column_width ? 
01243                         column_width[column] : 
01244                         default_column_width[column];
01245         else
01246                 return popup_w + 
01247                         xposition - 
01248                         get_column_offset(column);
01249 }
01250 
01251 int BC_ListBox::get_icon_mask(BC_ListBoxItem *item, 
01252         int &x, 
01253         int &y, 
01254         int &w, 
01255         int &h)
01256 {
01257         if(display_format == LISTBOX_ICONS)
01258         {
01259                 x = get_item_x(item);
01260                 y = get_item_y(item);
01261                 w = get_icon_w(item) + ICON_MARGIN * 2;
01262                 h = get_icon_h(item) + ICON_MARGIN * 2;
01263         }
01264         else
01265         if(display_format == LISTBOX_TEXT)
01266         {
01267                 x = y = w = h = 0;
01268         }
01269         return 0;
01270 }
01271 
01272 int BC_ListBox::get_text_mask(BC_ListBoxItem *item, 
01273         int &x, 
01274         int &y, 
01275         int &w, 
01276         int &h)
01277 {
01278         x =