3 * Copyright (C) 2010 Adam Williams <broadcast at earthling dot net>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "bcdragwindow.inc"
25 #include "bclistboxitem.inc"
26 #include "bcpixmap.inc"
27 #include "bcscrollbar.h"
28 #include "bcsubwindow.h"
32 #define BCPOPUPLISTBOX_W 25
33 #define BCPOPUPLISTBOX_H 25
35 class BC_ListBoxYScroll;
36 class BC_ListBoxXScroll;
37 class BC_ListBoxToggle;
40 #define MIN_COLUMN_WIDTH 10
43 class BC_ListBoxYScroll : public BC_ScrollBar
47 BC_ListBoxYScroll(BC_ListBox *listbox);
52 class BC_ListBoxXScroll : public BC_ScrollBar
56 BC_ListBoxXScroll(BC_ListBox *listbox);
61 class BC_ListBoxToggle
64 BC_ListBoxToggle(BC_ListBox *listbox, BC_ListBoxItem *item, int x, int y);
66 int cursor_motion_event(int *redraw_toggles);
67 int cursor_leave_event(int *redraw_toggles);
68 int button_press_event();
69 int button_release_event(int *redraw_toggles);
70 void update(BC_ListBoxItem *item, int x, int y, int flash);
84 // Button pressed then moved out
90 class BC_ListBox : public BC_SubWindow
92 friend class BC_ListBoxYScroll;
93 friend class BC_ListBoxXScroll;
94 friend class BC_ListBoxToggle;
96 BC_ListBox(int x, int y, int w, int h,
97 int display_format, // Display text list or icons
98 ArrayList<BC_ListBoxItem*> *data = 0, // Each column has an ArrayList of BC_ListBoxItems.
99 const char **column_titles = 0, // Titles for columns. Set to 0 for no titles
100 int *column_width = 0, // width of each column
101 int columns = 1, // Total columns. Only 1 in icon mode
102 int yposition = 0, // Pixel of top of window.
103 int is_popup = 0, // If this listbox is a popup window with a button
104 int selection_mode = LISTBOX_SINGLE, // Select one item or multiple items
105 int icon_position = ICON_LEFT, // Position of icon relative to text of each item
106 int allow_drag = 0); // Allow user to drag icons around
107 virtual ~BC_ListBox();
111 // User event handler for new selections
112 virtual int selection_changed() { return 0; };
113 // User event handler for triggering a selection
114 virtual int handle_event() { return 0; };
115 // User event handler for a column resize
116 virtual int column_resize_event() { return 0; };
117 // Draw background on bg_surface
118 virtual void draw_background();
119 // Draw on bg_surface
120 virtual int draw_images() { return 0; }
121 // Column sort order. This must return 1 or BC_ListBox will perform a default
123 virtual int sort_order_event() { return 0; };
125 virtual int move_column_event() { return 0; };
126 // item highlight changed
127 virtual int mouse_over_event(int no) { return 0; }
132 // Get the column movement
133 int get_from_column();
136 // Get the item in the given column which is the selection_number of the total
137 // selected rows. Returns 0 on failure.
138 BC_ListBoxItem* get_selection(int column, int selection_number);
139 BC_ListBoxItem* get_selection_recursive(ArrayList<BC_ListBoxItem*> *data,
141 int selection_number);
143 // Get the flat index of the item in the given column which is the selection_number
144 // of the total selected rows. Returns -1 on failure. The column
145 // argument is really useless because it only checks column 1 and returns the row
147 int get_selection_number(int column, int selection_number);
148 int get_selection_number_recursive(ArrayList<BC_ListBoxItem*> *data,
150 int selection_number,
153 virtual int evaluate_query(char *string);
154 void expand_item(BC_ListBoxItem *item, int expand);
155 // Collapse all items
156 static void collapse_recursive(ArrayList<BC_ListBoxItem*> *data,
158 // Convert recursive pointer to flat index.
159 // The pointer can be any item in the row corresponding to the index.
160 // Returns -1 if no item was found.
161 int item_to_index(ArrayList<BC_ListBoxItem*> *data,
162 BC_ListBoxItem *item,
164 // Convert flat index and column to desired item.
165 BC_ListBoxItem* index_to_item(ArrayList<BC_ListBoxItem*> *data,
169 // Get all items with recursion for text mode
170 static int get_total_items(ArrayList<BC_ListBoxItem*> *data,
171 int *result /* = 0 */,
174 virtual int focus_out_event();
175 virtual int keypress_event();
176 virtual int button_press_event();
177 virtual int button_release_event();
178 virtual int cursor_enter_event();
179 virtual int cursor_leave_event();
180 virtual int cursor_motion_event();
181 virtual int drag_start_event();
182 virtual int drag_motion_event();
183 virtual int drag_stop_event();
185 // After popping up a menu call this to interrupt the selection process
186 void deactivate_selection();
188 // take_focus - used by the suggestion box to keep it from taking focus from the
190 int activate(int take_focus = 1);
191 int activate(int x, int y, int w=-1, int h=-1);
194 int expander_active();
196 // get item no at current cursor position
197 int get_cursor_item_no();
198 // get top data item no, and item at current cursor position
199 int get_cursor_data_item_no(BC_ListBoxItem **item_return=0);
201 int translation_event();
202 int repeat_event(int64_t duration);
203 BC_DragWindow* get_drag_popup();
204 // If the popup window should show a button.
205 // Must be called in the constructor.
206 void set_use_button(int value);
207 void set_is_suggestions(int value);
208 void set_scroll_repeat();
209 void unset_scroll_repeat();
212 // change the contents
213 int update(ArrayList<BC_ListBoxItem*> *data,
214 const char **column_titles, int *column_widths, int columns,
215 int xposition = 0, int yposition = 0,
216 int highlighted_number = -1, // Flat index of item cursor is over
217 int recalc_positions = 0, // set all autoplace flags to 1
219 void center_selection();
220 void update_format(int display_format, int redraw);
223 // Allow scrolling when dragging items
224 void set_drag_scroll(int value);
225 // Allow column repositioning
226 void set_allow_drag_column(int value);
227 // Allow automatic moving of objects after drag
228 void set_process_drag(int value);
230 // Set the column to use for icons and sublists.
231 void set_master_column(int value, int redraw);
232 // Set column to search
233 void set_search_column(int value);
234 int set_selection_mode(int mode);
235 int set_yposition(int position, int draw_items = 1);
237 int set_xposition(int position);
239 // Return the flat index of the highlighted item
240 int get_highlighted_item();
243 int get_yscroll_height();
246 int get_xscroll_width();
247 void set_scroll_stretch(int xv, int yv);
248 int get_column_offset(int column);
249 int get_column_width(int column, int clamp_right = 0);
251 int get_display_mode();
252 void set_justify(int value);
253 int get_w() { return is_popup ? BCPOPUPLISTBOX_W : popup_w; }
254 int get_h() { return is_popup ? BCPOPUPLISTBOX_H : popup_h; }
255 int gui_tooltip(const char *text) {
256 return is_popup && gui ? gui->show_tooltip(text, gui->get_w(),0, -1,-1) : -1;
258 int get_view_w() { return view_w; }
259 int get_view_h() { return view_h; }
260 int get_row_height() { return row_height; }
261 int get_row_ascent() { return row_ascent; }
262 int get_row_descent() { return row_descent; }
263 int get_first_visible() { return first_in_view; }
264 int get_last_visible() { return last_in_view; }
272 int get_sort_column();
273 void set_sort_column(int value, int redraw = 0);
274 int get_sort_order();
275 void set_sort_order(int value, int redraw = 0);
279 int get_show_query() { return show_query; }
280 void set_show_query(int v) { show_query = v; }
282 int reposition_window(int x,
287 BC_Pixmap* get_bg_surface();
288 // Set all items for autoplacement with recursion into sublists
289 void set_autoplacement(ArrayList<BC_ListBoxItem*> *data,
292 // Set selection status on all items with recursion
293 void set_all_selected(ArrayList<BC_ListBoxItem*> *data, int value);
294 // Set selection status of single row with recursion
295 // item_number - the flat index of the row to select
296 void set_selected(ArrayList<BC_ListBoxItem*> *data,
301 // Called by keypress_event for cursor up. Selects previous and next visible
302 // row, skipping desired number of visible rows.
303 int select_previous(int skip,
304 BC_ListBoxItem *selected_item = 0,
306 ArrayList<BC_ListBoxItem*> *data = 0,
308 int *got_second = 0);
309 int select_next(int skip,
310 BC_ListBoxItem *selected_item = 0,
312 ArrayList<BC_ListBoxItem*> *data = 0,
314 int *got_second = 0);
316 // Called by cursor_motion_event to select different item if selection_number
317 // changed. Returns 1 if redraw is required.
318 int update_selection(ArrayList<BC_ListBoxItem*> *data,
319 int selection_number,
322 static void dump(ArrayList<BC_ListBoxItem*> *data,
324 int indent /* = 0 */,
327 int get_icon_x(BC_ListBoxItem *item);
328 int get_icon_y(BC_ListBoxItem *item);
329 int get_icon_w(BC_ListBoxItem *item);
330 int get_icon_h(BC_ListBoxItem *item);
331 int get_text_w(BC_ListBoxItem *item);
332 int get_text_h(BC_ListBoxItem *item);
333 int get_item_x(BC_ListBoxItem *item);
334 int get_item_y(BC_ListBoxItem *item);
335 int get_item_w(BC_ListBoxItem *item);
336 int get_item_h(BC_ListBoxItem *item);
338 // Draw the list items
339 int draw_items(int flash, int bg_draw=0);
340 int is_highlighted();
343 void delete_columns();
344 void set_columns(const char **column_titles,
347 // Draw the button for a popup listbox
348 int draw_button(int flush);
350 int draw_border(int flash);
351 // Draw column titles
352 void draw_title(int number);
353 int draw_titles(int flash);
355 void draw_toggles(int flash);
356 // Draw selection rectangle
357 int draw_rectangle(int flash);
360 void draw_text_recursive(ArrayList<BC_ListBoxItem*> *data,
363 int *current_toggle);
364 // Returns 1 if selection changed
366 void init_column_width();
367 void reset_cursor(int new_cursor);
368 // Fix boundary conditions after resize
369 void column_width_boundaries();
370 // Recursive function to get the first item selected in text mode.
371 // Returns > -1 only if it got it. Always increments *result
372 int get_first_selection(ArrayList<BC_ListBoxItem*> *data, int *result = 0);
373 // Recursive function to get the last item selected in text mode.
374 // Returns > -1 only if it got it. Always increments *result
375 int get_last_selection(ArrayList<BC_ListBoxItem*> *data, int *result = 0);
376 // Called by button_press_event and cursor_motion_event to expand the selection.
377 // Returns 1 if redraw is required.
378 int expand_selection(int button_press, int selection_number);
379 // Called by button_press_event and cursor_motion_event
380 // to select a range in text mode
381 void select_range(ArrayList<BC_ListBoxItem*> *data,
385 // Called by button_press_event to toggle the selection status of a single item.
386 // Called for both text and icon mode. In text mode it's recursive and fills
387 // the entire row with the first item's value. Returns 1 when the item was toggled.
388 int toggle_item_selection(ArrayList<BC_ListBoxItem*> *data,
389 int selection_number,
391 // Set value of selected in all selected items to new value
392 void promote_selections(ArrayList<BC_ListBoxItem*> *data,
397 int test_column_divisions(int cursor_x, int cursor_y, int &new_cursor);
398 int test_column_titles(int cursor_x, int cursor_y);
399 int test_expanders();
401 int calculate_item_coords();
402 void calculate_last_coords_recursive(
403 ArrayList<BC_ListBoxItem*> *data,
409 void calculate_item_coords_recursive(
410 ArrayList<BC_ListBoxItem*> *data,
417 int get_items_width();
418 int get_items_height(ArrayList<BC_ListBoxItem*> *data,
421 int get_baseline(BC_ListBoxItem *item);
422 int get_item_highlight(ArrayList<BC_ListBoxItem*> *data, int column, int item);
423 int get_item_color(ArrayList<BC_ListBoxItem*> *data, int column, int item);
424 int get_icon_mask(BC_ListBoxItem *item, int &x, int &y, int &w, int &h);
425 int get_text_mask(BC_ListBoxItem *item, int &x, int &y, int &w, int &h);
426 // Copy sections of the bg_surface to the gui
427 void clear_listbox(int x, int y, int w, int h);
429 // Tests for cursor outside boundaries
430 int test_drag_scroll(int cursor_x, int cursor_y);
431 // Called by select_scroll_event, rectangle_scroll_event to execute for movement
432 int drag_scroll_event();
433 int select_scroll_event();
434 int rectangle_scroll_event();
437 void move_vertical(int pixels);
438 void move_horizontal(int pixels);
439 void clamp_positions();
441 int get_scrollbars();
442 void update_scrollbars(int flush);
444 // Flat index of the item the cursor is over.
445 // Points *item_return to the first item in the row or 0 if no item was found.
446 // if it's nonzero. Returns -1 if no item was found. Clamps the y coordinate
447 // only if the current operation is not SELECT, so scrolling is possible.
448 // expanded = 1 if items in this table should be tested for cursor coverage
449 // expanded = -1 returns only the top level master column index/item
450 int get_cursor_item(ArrayList<BC_ListBoxItem*> *data,
453 BC_ListBoxItem **item_return = 0,
456 // Select the items in the rectangle and deselect the items outside of it.
457 // Returns 1 if redraw is required.
458 int select_rectangle(ArrayList<BC_ListBoxItem*> *data,
463 // Convert the row of the item to a pointer.
464 BC_ListBoxItem* number_to_item(int row);
465 int reposition_item(ArrayList<BC_ListBoxItem*> *data,
466 int selection_number,
470 // Move selected items to src_items
471 void move_selection(ArrayList<BC_ListBoxItem*> *dst,
472 ArrayList<BC_ListBoxItem*> *src);
473 // Put items from the src table into the data table starting at flat item number
475 int put_selection(ArrayList<BC_ListBoxItem*> *data,
476 ArrayList<BC_ListBoxItem*> *src,
480 int center_selection(int selection,
481 ArrayList<BC_ListBoxItem*> *data = 0,
484 // Array of one list of pointers for each column
485 ArrayList<BC_ListBoxItem*> *data;
488 // 1 if a button is used to make the listbox display
489 int is_popup; // popup
490 // If the button for a popup should be shown
492 // background update needed
495 // Dimensions for a popup if there is one
496 int popup_w, popup_h;
497 // pixel of top of display relative to top of list
499 // pixel of left display relative to first column
501 // dimensions of a row in the list
502 int row_height, row_ascent, row_descent;
507 int temp_display_format;
509 // Scrollbars are created as needed
510 BC_ListBoxXScroll *xscrollbar;
511 BC_ListBoxYScroll *yscrollbar;
512 ArrayList<BC_ListBoxToggle*> expanders;
513 char query[BCTEXTLEN];
516 // Window containing the listbox
519 // Size of the popup if there is one
520 char **column_titles;
522 int default_column_width[32];
528 int first_in_view, last_in_view;
530 // Maximum width of items. Calculated by get_items_width
533 // In BCLISTBOX_SELECT mode determines the value to set items to
535 int need_xscroll, need_yscroll;
536 int xscroll_orientation, yscroll_orientation;
537 // Move items during drag operation of text items.
540 int allow_drag_scroll;
541 int allow_drag_column;
542 // Background color of listbox
547 BC_Pixmap *button_images[4];
549 BC_Pixmap *toggle_images[5];
550 // Background for drawing on
551 BC_Pixmap *bg_surface;
552 // Background if 9 segment
554 // Drag icon for text mode
555 VFrame *drag_icon_vframe;
557 VFrame *drag_column_icon_vframe;
558 // Background picon to be drawn in the upper right
559 BC_Pixmap *bg_pixmap;
562 // Column title backgrounds
563 BC_Pixmap *column_bg[3];
565 BC_Pixmap *column_sort_up;
566 BC_Pixmap *column_sort_dn;
571 // Number of column to sort
573 // Sort order. -1 means no column is being sorted.
580 // State of the list box and button when the mouse button is pressed.
581 int current_operation;
586 BUTTON_DOWN_SELECT, // Pressed button and slid off to select items.
588 DRAG_DIVISION, // Dragging column division
589 DRAG_COLUMN, // Dragging column
590 DRAG_ITEM, // Dragging item
591 SELECT, // Select item
592 SELECT_RECT, // Selection rectangle
593 WHEEL, // Wheel mouse
594 COLUMN_DN, // column title down
595 COLUMN_DRAG, // column title is being dragged
596 EXPAND_DN // Expander is down
600 // More state variables
601 int button_highlighted;
602 int list_highlighted;
604 // item cursor is over. May not exist in tables.
605 // Must be an index since this is needed to change the database.
606 int highlighted_item;
607 BC_ListBoxItem* highlighted_ptr;
608 // column title if the cursor is over a column title
609 int highlighted_title;
610 // Division the cursor is operating on when resizing
611 int highlighted_division;
612 // Column title being dragged
614 // start of column title drag
618 // Selection range being extended
619 int selection_start, selection_end, selection_center;
620 // Item being dragged or last item selected in a double click operation
621 int selection_number;
622 // Used in button_press_event and button_release_event to detect double clicks
623 int selection_number1, selection_number2;
629 // Popup listboxes have different behavior for suggestion boxes where the
630 // textbox needs to be active when the listbox is visible.
633 // Button release counter for double clicking
636 // Starting coordinates of rectangle
637 int rect_x1, rect_y1;
638 int rect_x2, rect_y2;
642 // Window for dragging
643 BC_DragWindow *drag_popup;