1 //
2 // "$Id$"
3 //
4 // Common browser header file for the Fast Light Tool Kit (FLTK).
5 //
6 // Copyright 1998-2016 by Bill Spitzak and others.
7 //
8 // This library is free software. Distribution and use rights are outlined in
9 // the file "COPYING" which should have been included with this file.  If this
10 // file is missing or damaged, see the license at:
11 //
12 //     http://www.fltk.org/COPYING.php
13 //
14 // Please report all bugs and problems on the following page:
15 //
16 //     http://www.fltk.org/str.php
17 //
18 
19 /* \file
20    Fl_Browser_ widget . */
21 
22 // Yes, I know this should be a template...
23 
24 #ifndef Fl_Browser__H
25 #define Fl_Browser__H
26 
27 #ifndef Fl_Group_H
28 #include "Fl_Group.H"
29 #endif
30 #include "Fl_Scrollbar.H"
31 #include <FL/Fl.H>		// Fl::scrollbar_size()
32 
33 #define FL_NORMAL_BROWSER	0	/**< type() of Fl_Browser */
34 #define FL_SELECT_BROWSER	1	/**< type() of FL_Select_Browser */
35 #define FL_HOLD_BROWSER		2	/**< type() of Fl_Hold_Browser */
36 #define FL_MULTI_BROWSER	3	/**< type() of Fl_Multi_Browser */
37 
38 #define FL_SORT_ASCENDING	0	/**< sort browser items in ascending alphabetic order. */
39 #define FL_SORT_DESCENDING	1	/**< sort in descending order */
40 
41 /**
42   This is the base class for browsers.  To be useful it must be
43   subclassed and several virtual functions defined.  The Forms-compatible
44   browser and the file chooser's browser are subclassed off of this.
45 
46   This has been designed so that the subclass has complete control
47   over the storage of the data, although because next() and
48   prev() functions are used to index, it works best as a linked list
49   or as a large block of characters in which the line breaks must be
50   searched for.
51 
52   A great deal of work has been done so that the "height" of a data
53   object does not need to be determined until it is drawn.  This is
54   useful if actually figuring out the size of an object requires
55   accessing image data or doing stat() on a file or doing some
56   other slow operation.
57 
58   Keyboard navigation of browser items
59   ------------------------------------
60   The keyboard navigation of browser items is only possible if
61   visible_focus() is enabled. If disabled, the widget rejects keyboard focus;
62   Tab and Shift-Tab focus navigation will skip the widget.
63 
64   In 'Select' and 'Normal' mode, the widget rejects keyboard focus;
65   no navigation keys are supported (other than scrollbar positioning).
66 
67   In 'Hold' mode, the widget accepts keyboard focus, and Up/Down arrow
68   keys can navigate the selected item.
69 
70   In 'Multi' mode, the widget accepts keyboard focus, and Up/Down arrow
71   keys navigate the focus box; Space toggles the current item's selection,
72   Enter selects only the current item (deselects all others).  If Shift
73   (or Ctrl) is combined with Up/Down arrow keys, the current item's
74   selection state is extended to the next item. In this way one can
75   extend a selection or de-selection.
76 */
77 class FL_EXPORT Fl_Browser_ : public Fl_Group {
78   int position_;	// where user wants it scrolled to
79   int real_position_;	// the current vertical scrolling position
80   int hposition_;	// where user wants it panned to
81   int real_hposition_;	// the current horizontal scrolling position
82   int offset_;		// how far down top_ item the real_position is
83   int max_width;	// widest object seen so far
84   uchar has_scrollbar_;	// which scrollbars are enabled
85   Fl_Font textfont_;
86   Fl_Fontsize textsize_;
87   Fl_Color textcolor_;
88   void* top_;		// which item scrolling position is in
89   void* selection_;	// which is selected (except for FL_MULTI_BROWSER)
90   void *redraw1,*redraw2; // minimal update pointers
91   void* max_width_item;	// which item has max_width_
92   int scrollbar_size_;	// size of scrollbar trough
93 
94   void update_top();
95 
96 protected:
97 
98   // All of the following must be supplied by the subclass:
99   /**
100     This method must be provided by the subclass
101     to return the first item in the list.
102     \see item_first(), item_next(), item_last(), item_prev()
103    */
104   virtual void *item_first() const = 0;
105   /**
106     This method must be provided by the subclass
107     to return the item in the list after \p item.
108     \see item_first(), item_next(), item_last(), item_prev()
109    */
110   virtual void *item_next(void *item) const = 0;
111   /**
112     This method must be provided by the subclass
113     to return the item in the list before \p item.
114     \see item_first(), item_next(), item_last(), item_prev()
115    */
116   virtual void *item_prev(void *item) const = 0;
117   /**
118     This method must be provided by the subclass
119     to return the last item in the list.
120     \see item_first(), item_next(), item_last(), item_prev()
121    */
item_last()122   virtual void *item_last() const { return 0L; }
123   /**
124     This method must be provided by the subclass to return
125     the height of \p item in pixels.
126     Allow for two additional pixels for the list selection box.
127     \param[in] item The item whose height is returned.
128     \returns The height of the specified \p item in pixels.
129     \see item_height(), item_width(), item_quick_height()
130   */
131   virtual int item_height(void *item) const = 0;
132   /**
133     This method must be provided by the subclass to return the width of the
134     \p item in pixels.  Allow for two additional pixels for the list
135     selection box.
136     \param[in] item The item whose width is returned.
137     \returns The width of the item in pixels.
138   */
139   virtual int item_width(void *item) const = 0;
140   virtual int item_quick_height(void *item) const ;
141   /**
142     This method must be provided by the subclass to draw the \p item
143     in the area indicated by \p X, \p Y, \p W, \p H.
144   */
145   virtual void item_draw(void *item,int X,int Y,int W,int H) const = 0;
146   /**
147     This optional method returns a string (label) that may be used for sorting.
148     \param[in] item The item whose label text is returned.
149     \returns The item's text label. (Can be NULL if blank)
150    */
item_text(void * item)151   virtual const char *item_text(void *item) const { (void)item; return 0L; }
152   /**
153     This optional method should be provided by the subclass
154     to efficiently swap browser items \p a and \p b, such as for sorting.
155     \param[in] a,b The two items to be swapped.
156    */
item_swap(void * a,void * b)157   virtual void item_swap(void *a,void *b) { (void)a; (void)b; }
158   /**
159     This method must be provided by the subclass
160     to return the item for the specified \p index.
161     \param[in] index The \p index of the item to be returned
162     \returns The item at the specified \p index.
163    */
item_at(int index)164   virtual void *item_at(int index) const { (void)index; return 0L; }
165   // you don't have to provide these but it may help speed it up:
166   virtual int full_width() const ;	// current width of all items
167   virtual int full_height() const ;	// current height of all items
168   virtual int incr_height() const ;	// average height of an item
169   // These only need to be done by subclass if you want a multi-browser:
170   virtual void item_select(void *item,int val=1);
171   virtual int item_selected(void *item) const ;
172 
173   // things the subclass may want to call:
174   /**
175     Returns the item that appears at the top of the list.
176    */
top()177   void *top() const { return top_; }
178   /**
179     Returns the item currently selected, or NULL if there is no selection.
180 
181     For multiple selection browsers this call returns the currently focused item,
182     even if it is not selected. To find all selected items, call
183     Fl_Multi_Browser::selected() for every item in question.
184   */
selection()185   void *selection() const { return selection_; }
186   void new_list(); // completely clobber all data, as though list replaced
187   void deleting(void *item); // get rid of any pointers to item
188   void replacing(void *a,void *b); // change a pointers to b
189   void swapping(void *a,void *b); // exchange pointers a and b
190   void inserting(void *a,void *b); // insert b near a
191   int displayed(void *item) const ; // true if this item is visible
192   void redraw_line(void *item); // minimal update, no change in size
193   /**
194     This method will cause the entire list to be redrawn.
195     \see redraw_lines(), redraw_line()
196    */
redraw_lines()197   void redraw_lines() { damage(FL_DAMAGE_SCROLL); } // redraw all of them
198   void bbox(int &X,int &Y,int &W,int &H) const;
199   int leftedge() const;	// x position after scrollbar & border
200   void *find_item(int ypos); // item under mouse
201 
202   void draw();
203   Fl_Browser_(int X,int Y,int W,int H,const char *L=0);
204 
205 public:
206 
207   /**
208     Vertical scrollbar. Public, so that it can be accessed directly.
209    */
210   Fl_Scrollbar scrollbar;
211   /**
212     Horizontal scrollbar. Public, so that it can be accessed directly.
213    */
214   Fl_Scrollbar hscrollbar;
215 
216   int handle(int event);
217   void resize(int X,int Y,int W,int H);
218 
219   int select(void *item,int val=1,int docallbacks=0);
220   int select_only(void *item,int docallbacks=0);
221   int deselect(int docallbacks=0);
222   /**
223     Gets the vertical scroll position of the list as a pixel position \p pos.
224     The position returned is how many pixels of the list are scrolled off the top edge
225     of the screen.  Example: A position of '3' indicates the top 3 pixels of
226     the list are scrolled off the top edge of the screen.
227     \see position(), hposition()
228   */
position()229   int position() const { return position_; }
230   void position(int pos); // scroll to here
231   /**
232     Gets the horizontal scroll position of the list as a pixel position \p pos.
233     The position returned is how many pixels of the list are scrolled off the left edge
234     of the screen. Example: A position of '18' indicates the left 18 pixels of
235     the list are scrolled off the left edge of the screen.
236     \see position(), hposition()
237   */
hposition()238   int hposition() const { return hposition_; }
239   void hposition(int); // pan to here
240   void display(void *item); // scroll so this item is shown
241 
242   /**
243     Values for has_scrollbar().
244    */
245   /** Anonymous enum bit flags for has_scrollbar().
246      -  bit 0: horizontal
247      -  bit 1: vertical
248      -  bit 2: 'always' (to be combined with bits 0 and 1)
249      -  bit 3-31: reserved for future use
250    */
251   enum { // values for has_scrollbar()
252     HORIZONTAL = 1,		///< Only show horizontal scrollbar.
253     VERTICAL = 2,		///< Only show vertical scrollbar.
254     BOTH = 3,			///< Show both scrollbars. (default)
255     ALWAYS_ON = 4,		///< Specified scrollbar(s) should 'always' be shown (to be used with HORIZONTAL/VERTICAL)
256     HORIZONTAL_ALWAYS = 5,	///< Horizontal scrollbar always on.
257     VERTICAL_ALWAYS = 6,	///< Vertical scrollbar always on.
258     BOTH_ALWAYS = 7		///< Both scrollbars always on.
259   };
260   /**
261     Returns the current scrollbar mode, see Fl_Browser_::has_scrollbar(uchar)
262    */
has_scrollbar()263   uchar has_scrollbar() const { return has_scrollbar_; }
264   /**
265     Sets whether the widget should have scrollbars or not (default Fl_Browser_::BOTH).
266     By default you can scroll in both directions, and the scrollbars
267     disappear if the data will fit in the widget.
268     has_scrollbar() changes this based on the value of \p mode:
269 
270     - 0 - No scrollbars.
271 
272     - Fl_Browser_::HORIZONTAL - Only a horizontal scrollbar.
273 
274     - Fl_Browser_::VERTICAL - Only a vertical scrollbar.
275 
276     - Fl_Browser_::BOTH - The default is both scrollbars.
277 
278     - Fl_Browser_::HORIZONTAL_ALWAYS - Horizontal scrollbar always on,
279       vertical always off.
280 
281     - Fl_Browser_::VERTICAL_ALWAYS - Vertical scrollbar always on,
282       horizontal always off.
283 
284     - Fl_Browser_::BOTH_ALWAYS - Both always on.
285   */
has_scrollbar(uchar mode)286   void has_scrollbar(uchar mode) { has_scrollbar_ = mode; }
287 
288   /**
289     Gets the default text font for the lines in the browser.
290     \see textfont(), textsize(), textcolor()
291   */
textfont()292   Fl_Font textfont() const { return textfont_; }
293   /**
294     Sets the default text font for the lines in the browser to \p font.
295   */
textfont(Fl_Font font)296   void textfont(Fl_Font font) { textfont_ = font; }
297 
298   /**
299     Gets the default text size (in pixels) for the lines in the browser.
300   */
textsize()301   Fl_Fontsize textsize() const { return textsize_; }
302   /**
303     Sets the default text size (in pixels) for the lines in the browser to \p size.
304   */
textsize(Fl_Fontsize newSize)305   void textsize(Fl_Fontsize newSize) { textsize_ = newSize; }
306 
307   /**
308     Gets the default text color for the lines in the browser.
309   */
textcolor()310   Fl_Color textcolor() const { return textcolor_; }
311   /**
312     Sets the default text color for the lines in the browser to color \p col.
313   */
textcolor(Fl_Color col)314   void textcolor(Fl_Color col) { textcolor_ = col; }
315 
316   /**
317     Gets the current size of the scrollbars' troughs, in pixels.
318 
319     If this value is zero (default), this widget will use the
320     Fl::scrollbar_size() value as the scrollbar's width.
321 
322     \returns Scrollbar size in pixels, or 0 if the global Fl::scrollbar_size() is being used.
323     \see Fl::scrollbar_size(int)
324   */
scrollbar_size()325   int scrollbar_size() const {
326       return(scrollbar_size_);
327   }
328   /**
329     Sets the pixel size of the scrollbars' troughs to \p newSize, in pixels.
330 
331     Normally you should not need this method, and should use
332     Fl::scrollbar_size(int) instead to manage the size of ALL
333     your widgets' scrollbars. This ensures your application
334     has a consistent UI, is the default behavior, and is normally
335     what you want.
336 
337     Only use THIS method if you really need to override the global
338     scrollbar size. The need for this should be rare.
339 
340     Setting \p newSize to the special value of 0 causes the widget to
341     track the global Fl::scrollbar_size(), which is the default.
342 
343     \param[in] newSize Sets the scrollbar size in pixels.\n
344                     If 0 (default), scrollbar size tracks the global Fl::scrollbar_size()
345     \see Fl::scrollbar_size()
346   */
scrollbar_size(int newSize)347   void scrollbar_size(int newSize) {
348       scrollbar_size_ = newSize;
349   }
350   /**
351     This method has been deprecated, existing for backwards compatibility only.
352     Use scrollbar_size() instead.
353     This method always returns the global value Fl::scrollbar_size().
354     \returns Always returns the global value Fl::scrollbar_size().
355     \todo This method should eventually be removed in 1.4+
356   */
scrollbar_width()357   int scrollbar_width() const {
358       return(Fl::scrollbar_size());
359   }
360   /**
361     This method has been deprecated, existing for backwards compatibility only.
362     Use scrollbar_size(int) instead.
363     This method sets the global Fl::scrollbar_size(), and forces this
364     instance of the widget to use it.
365     \todo This method should eventually be removed in 1.4+
366   */
scrollbar_width(int width)367   void scrollbar_width(int width) {
368       Fl::scrollbar_size(width);
369       scrollbar_size_ = 0;
370   }
371   /**
372     Moves the vertical scrollbar to the righthand side of the list.
373     For back compatibility.
374   */
scrollbar_right()375   void scrollbar_right() { scrollbar.align(FL_ALIGN_RIGHT); }
376   /**
377     Moves the vertical scrollbar to the lefthand side of the list.
378     For back compatibility.
379   */
scrollbar_left()380   void scrollbar_left() { scrollbar.align(FL_ALIGN_LEFT); }
381   void sort(int flags=0);
382 };
383 
384 #endif
385 
386 //
387 // End of "$Id$".
388 //
389