1 ///////////////////////////////////////////////////////////////////////////////
2 // Name:        wx/vlbox.h
3 // Purpose:     wxVListBox is a virtual listbox with lines of variable height
4 // Author:      Vadim Zeitlin
5 // Modified by:
6 // Created:     31.05.03
7 // Copyright:   (c) 2003 Vadim Zeitlin <vadim@wxwidgets.org>
8 // Licence:     wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
10 
11 #ifndef _WX_VLBOX_H_
12 #define _WX_VLBOX_H_
13 
14 #include "wx/vscroll.h"         // base class
15 #include "wx/bitmap.h"
16 
17 class WXDLLIMPEXP_FWD_CORE wxSelectionStore;
18 
19 extern WXDLLIMPEXP_DATA_CORE(const char) wxVListBoxNameStr[];
20 
21 // ----------------------------------------------------------------------------
22 // wxVListBox
23 // ----------------------------------------------------------------------------
24 
25 /*
26     This class has two main differences from a regular listbox: it can have an
27     arbitrarily huge number of items because it doesn't store them itself but
28     uses OnDrawItem() callback to draw them and its items can have variable
29     height as determined by OnMeasureItem().
30 
31     It emits the same events as wxListBox and the same event macros may be used
32     with it.
33  */
34 class WXDLLIMPEXP_CORE wxVListBox : public wxVScrolledWindow
35 {
36 public:
37     // constructors and such
38     // ---------------------
39 
40     // default constructor, you must call Create() later
wxVListBox()41     wxVListBox() { Init(); }
42 
43     // normal constructor which calls Create() internally
44     wxVListBox(wxWindow *parent,
45                wxWindowID id = wxID_ANY,
46                const wxPoint& pos = wxDefaultPosition,
47                const wxSize& size = wxDefaultSize,
48                long style = 0,
49                const wxString& name = wxASCII_STR(wxVListBoxNameStr))
50     {
51         Init();
52 
53         (void)Create(parent, id, pos, size, style, name);
54     }
55 
56     // really creates the control and sets the initial number of items in it
57     // (which may be changed later with SetItemCount())
58     //
59     // the only special style which may be specified here is wxLB_MULTIPLE
60     //
61     // returns true on success or false if the control couldn't be created
62     bool Create(wxWindow *parent,
63                 wxWindowID id = wxID_ANY,
64                 const wxPoint& pos = wxDefaultPosition,
65                 const wxSize& size = wxDefaultSize,
66                 long style = 0,
67                 const wxString& name = wxASCII_STR(wxVListBoxNameStr));
68 
69     // dtor does some internal cleanup (deletes m_selStore if any)
70     virtual ~wxVListBox();
71 
72 
73     // accessors
74     // ---------
75 
76     // get the number of items in the control
GetItemCount()77     size_t GetItemCount() const { return GetRowCount(); }
78 
79     // does this control use multiple selection?
HasMultipleSelection()80     bool HasMultipleSelection() const { return m_selStore != NULL; }
81 
82     // get the currently selected item or wxNOT_FOUND if there is no selection
83     //
84     // this method is only valid for the single selection listboxes
GetSelection()85     int GetSelection() const
86     {
87         wxASSERT_MSG( !HasMultipleSelection(),
88                         wxT("GetSelection() can't be used with wxLB_MULTIPLE") );
89 
90         return m_current;
91     }
92 
93     // is this item the current one?
IsCurrent(size_t item)94     bool IsCurrent(size_t item) const { return item == (size_t)m_current; }
95     #ifdef __WXUNIVERSAL__
IsCurrent()96     bool IsCurrent() const { return wxVScrolledWindow::IsCurrent(); }
97     #endif
98 
99     // is this item selected?
100     bool IsSelected(size_t item) const;
101 
102     // get the number of the selected items (maybe 0)
103     //
104     // this method is valid for both single and multi selection listboxes
105     size_t GetSelectedCount() const;
106 
107     // get the first selected item, returns wxNOT_FOUND if none
108     //
109     // cookie is an opaque parameter which should be passed to
110     // GetNextSelected() later
111     //
112     // this method is only valid for the multi selection listboxes
113     int GetFirstSelected(unsigned long& cookie) const;
114 
115     // get next selection item, return wxNOT_FOUND if no more
116     //
117     // cookie must be the same parameter that was passed to GetFirstSelected()
118     // before
119     //
120     // this method is only valid for the multi selection listboxes
121     int GetNextSelected(unsigned long& cookie) const;
122 
123     // get the margins around each item
GetMargins()124     wxPoint GetMargins() const { return m_ptMargins; }
125 
126     // get the background colour of selected cells
GetSelectionBackground()127     const wxColour& GetSelectionBackground() const { return m_colBgSel; }
128 
129     // get the item rect, returns empty rect if the item is not visible
130     wxRect GetItemRect(size_t n) const;
131 
132     // operations
133     // ----------
134 
135     // set the number of items to be shown in the control
136     //
137     // this is just a synonym for wxVScrolledWindow::SetRowCount()
138     virtual void SetItemCount(size_t count);
139 
140     // delete all items from the control
Clear()141     void Clear() { SetItemCount(0); }
142 
143     // set the selection to the specified item, if it is wxNOT_FOUND the
144     // selection is unset
145     //
146     // this function is only valid for the single selection listboxes
147     void SetSelection(int selection);
148 
149     // selects or deselects the specified item which must be valid (i.e. not
150     // equal to wxNOT_FOUND)
151     //
152     // return true if the items selection status has changed or false
153     // otherwise
154     //
155     // this function is only valid for the multiple selection listboxes
156     bool Select(size_t item, bool select = true);
157 
158     // selects the items in the specified range whose end points may be given
159     // in any order
160     //
161     // return true if any items selection status has changed, false otherwise
162     //
163     // this function is only valid for the single selection listboxes
164     bool SelectRange(size_t from, size_t to);
165 
166     // toggle the selection of the specified item (must be valid)
167     //
168     // this function is only valid for the multiple selection listboxes
Toggle(size_t item)169     void Toggle(size_t item) { Select(item, !IsSelected(item)); }
170 
171     // select all items in the listbox
172     //
173     // the return code indicates if any items were affected by this operation
174     // (true) or if nothing has changed (false)
SelectAll()175     bool SelectAll() { return DoSelectAll(true); }
176 
177     // unselect all items in the listbox
178     //
179     // the return code has the same meaning as for SelectAll()
DeselectAll()180     bool DeselectAll() { return DoSelectAll(false); }
181 
182     // set the margins: horizontal margin is the distance between the window
183     // border and the item contents while vertical margin is half of the
184     // distance between items
185     //
186     // by default both margins are 0
187     void SetMargins(const wxPoint& pt);
SetMargins(wxCoord x,wxCoord y)188     void SetMargins(wxCoord x, wxCoord y) { SetMargins(wxPoint(x, y)); }
189 
190     // change the background colour of the selected cells
191     void SetSelectionBackground(const wxColour& col);
192 
193     // refreshes only the selected items
194     void RefreshSelected();
195 
196 
GetDefaultAttributes()197     virtual wxVisualAttributes GetDefaultAttributes() const wxOVERRIDE
198     {
199         return GetClassDefaultAttributes(GetWindowVariant());
200     }
201 
202     static wxVisualAttributes
203     GetClassDefaultAttributes(wxWindowVariant variant = wxWINDOW_VARIANT_NORMAL);
204 
205 protected:
GetDefaultBorder()206     virtual wxBorder GetDefaultBorder() const wxOVERRIDE { return wxBORDER_THEME; }
207 
208     // the derived class must implement this function to actually draw the item
209     // with the given index on the provided DC
210     virtual void OnDrawItem(wxDC& dc, const wxRect& rect, size_t n) const = 0;
211 
212     // the derived class must implement this method to return the height of the
213     // specified item
214     virtual wxCoord OnMeasureItem(size_t n) const = 0;
215 
216     // this method may be used to draw separators between the lines; note that
217     // the rectangle may be modified, typically to deflate it a bit before
218     // passing to OnDrawItem()
219     //
220     // the base class version doesn't do anything
221     virtual void OnDrawSeparator(wxDC& dc, wxRect& rect, size_t n) const;
222 
223     // this method is used to draw the items background and, maybe, a border
224     // around it
225     //
226     // the base class version implements a reasonable default behaviour which
227     // consists in drawing the selected item with the standard background
228     // colour and drawing a border around the item if it is either selected or
229     // current
230     virtual void OnDrawBackground(wxDC& dc, const wxRect& rect, size_t n) const;
231 
232     // we implement OnGetRowHeight() in terms of OnMeasureItem() because this
233     // allows us to add borders to the items easily
234     //
235     // this function is not supposed to be overridden by the derived classes
236     virtual wxCoord OnGetRowHeight(size_t line) const wxOVERRIDE;
237 
238 
239     // event handlers
240     void OnPaint(wxPaintEvent& event);
241     void OnKeyDown(wxKeyEvent& event);
242     void OnLeftDown(wxMouseEvent& event);
243     void OnLeftDClick(wxMouseEvent& event);
244     void OnSetOrKillFocus(wxFocusEvent& event);
245     void OnSize(wxSizeEvent& event);
246 
247     // common part of all ctors
248     void Init();
249 
250     // send the wxEVT_LISTBOX event
251     void SendSelectedEvent();
252     virtual void InitEvent(wxCommandEvent& event, int n);
253 
254     // common implementation of SelectAll() and DeselectAll()
255     bool DoSelectAll(bool select);
256 
257     // change the current item (in single selection listbox it also implicitly
258     // changes the selection); current may be wxNOT_FOUND in which case there
259     // will be no current item any more
260     //
261     // return true if the current item changed, false otherwise
262     bool DoSetCurrent(int current);
263 
264     // flags for DoHandleItemClick
265     enum
266     {
267         ItemClick_Shift = 1,        // item shift-clicked
268         ItemClick_Ctrl  = 2,        //       ctrl
269         ItemClick_Kbd   = 4         // item selected from keyboard
270     };
271 
272     // common part of keyboard and mouse handling processing code
273     void DoHandleItemClick(int item, int flags);
274 
275     // paint the background of the given item using the provided colour if it's
276     // valid, otherwise just return false and do nothing (this is used by
277     // OnDrawBackground())
278     bool DoDrawSolidBackground(const wxColour& col,
279                                wxDC& dc,
280                                const wxRect& rect,
281                                size_t n) const;
282 
283 private:
284     // the current item or wxNOT_FOUND
285     //
286     // if m_selStore == NULL this is also the selected item, otherwise the
287     // selections are managed by m_selStore
288     int m_current;
289 
290     // the anchor of the selection for the multiselection listboxes:
291     // shift-clicking an item extends the selection from m_anchor to the item
292     // clicked, for example
293     //
294     // always wxNOT_FOUND for single selection listboxes
295     int m_anchor;
296 
297     // the object managing our selected items if not NULL
298     wxSelectionStore *m_selStore;
299 
300     // margins
301     wxPoint m_ptMargins;
302 
303     // the selection bg colour
304     wxColour m_colBgSel;
305 
306     wxDECLARE_EVENT_TABLE();
307     wxDECLARE_NO_COPY_CLASS(wxVListBox);
308     wxDECLARE_ABSTRACT_CLASS(wxVListBox);
309 };
310 
311 #endif // _WX_VLBOX_H_
312 
313