]>
Commit | Line | Data |
---|---|---|
1e6feb95 VZ |
1 | /////////////////////////////////////////////////////////////////////////////// |
2 | // Name: wx/univ/listbox.h | |
3 | // Purpose: the universal listbox | |
4 | // Author: Vadim Zeitlin | |
5 | // Modified by: | |
6 | // Created: 30.08.00 | |
7 | // RCS-ID: $Id$ | |
a3870b2f | 8 | // Copyright: (c) 2000 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr> |
1e6feb95 VZ |
9 | // Licence: wxWindows licence |
10 | /////////////////////////////////////////////////////////////////////////////// | |
11 | ||
12 | #ifndef _WX_UNIV_LISTBOX_H_ | |
13 | #define _WX_UNIV_LISTBOX_H_ | |
14 | ||
12028905 | 15 | #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) |
11d13ed0 | 16 | #pragma interface "univlistbox.h" |
1e6feb95 VZ |
17 | #endif |
18 | ||
19 | #include "wx/scrolwin.h" // for wxScrollHelper | |
ed39ff57 | 20 | #include "wx/dynarray.h" |
18dbdd3c | 21 | #include "wx/arrstr.h" |
1e6feb95 VZ |
22 | |
23 | // ---------------------------------------------------------------------------- | |
24 | // the actions supported by this control | |
25 | // ---------------------------------------------------------------------------- | |
26 | ||
27 | // change the current item | |
28 | #define wxACTION_LISTBOX_SETFOCUS _T("setfocus") // select the item | |
29 | #define wxACTION_LISTBOX_MOVEDOWN _T("down") // select item below | |
30 | #define wxACTION_LISTBOX_MOVEUP _T("up") // select item above | |
31 | #define wxACTION_LISTBOX_PAGEDOWN _T("pagedown") // go page down | |
32 | #define wxACTION_LISTBOX_PAGEUP _T("pageup") // go page up | |
33 | #define wxACTION_LISTBOX_START _T("start") // go to first item | |
34 | #define wxACTION_LISTBOX_END _T("end") // go to last item | |
35 | #define wxACTION_LISTBOX_FIND _T("find") // find item by 1st letter | |
36 | ||
37 | // do something with the current item | |
38 | #define wxACTION_LISTBOX_ACTIVATE _T("activate") // activate (choose) | |
39 | #define wxACTION_LISTBOX_TOGGLE _T("toggle") // togglee selected state | |
40 | #define wxACTION_LISTBOX_SELECT _T("select") // sel this, unsel others | |
41 | #define wxACTION_LISTBOX_SELECTADD _T("selectadd") // add to selection | |
42 | #define wxACTION_LISTBOX_UNSELECT _T("unselect") // unselect | |
43 | #define wxACTION_LISTBOX_ANCHOR _T("selanchor") // anchor selection | |
44 | ||
45 | // do something with the selection globally (not for single selection ones) | |
46 | #define wxACTION_LISTBOX_SELECTALL _T("selectall") // select all items | |
47 | #define wxACTION_LISTBOX_UNSELECTALL _T("unselectall") // unselect all items | |
48 | #define wxACTION_LISTBOX_SELTOGGLE _T("togglesel") // invert the selection | |
49 | #define wxACTION_LISTBOX_EXTENDSEL _T("extend") // extend to item | |
50 | ||
51 | // ---------------------------------------------------------------------------- | |
52 | // wxListBox: a list of selectable items | |
53 | // ---------------------------------------------------------------------------- | |
54 | ||
d2a533a0 | 55 | class WXDLLEXPORT wxListBox : public wxListBoxBase, public wxScrollHelper |
1e6feb95 VZ |
56 | { |
57 | public: | |
58 | // ctors and such | |
6463b9f5 | 59 | wxListBox() { Init(); } |
1e6feb95 VZ |
60 | wxListBox(wxWindow *parent, |
61 | wxWindowID id, | |
62 | const wxPoint& pos = wxDefaultPosition, | |
63 | const wxSize& size = wxDefaultSize, | |
64 | int n = 0, const wxString choices[] = (const wxString *) NULL, | |
65 | long style = 0, | |
66 | const wxValidator& validator = wxDefaultValidator, | |
6463b9f5 JS |
67 | const wxString& name = wxListBoxNameStr ) |
68 | { | |
69 | Init(); | |
70 | ||
71 | Create(parent, id, pos, size, n, choices, style, validator, name); | |
72 | } | |
584ad2a3 MB |
73 | wxListBox(wxWindow *parent, |
74 | wxWindowID id, | |
75 | const wxPoint& pos, | |
76 | const wxSize& size, | |
77 | const wxArrayString& choices, | |
78 | long style = 0, | |
79 | const wxValidator& validator = wxDefaultValidator, | |
80 | const wxString& name = wxListBoxNameStr ); | |
1e6feb95 VZ |
81 | |
82 | virtual ~wxListBox(); | |
83 | ||
84 | bool Create(wxWindow *parent, | |
85 | wxWindowID id, | |
86 | const wxPoint& pos = wxDefaultPosition, | |
87 | const wxSize& size = wxDefaultSize, | |
88 | int n = 0, const wxString choices[] = (const wxString *) NULL, | |
89 | long style = 0, | |
90 | const wxValidator& validator = wxDefaultValidator, | |
91 | const wxString& name = wxListBoxNameStr); | |
584ad2a3 MB |
92 | bool Create(wxWindow *parent, |
93 | wxWindowID id, | |
94 | const wxPoint& pos, | |
95 | const wxSize& size, | |
96 | const wxArrayString& choices, | |
97 | long style = 0, | |
98 | const wxValidator& validator = wxDefaultValidator, | |
99 | const wxString& name = wxListBoxNameStr); | |
1e6feb95 VZ |
100 | |
101 | // implement the listbox interface defined by wxListBoxBase | |
102 | virtual void Clear(); | |
103 | virtual void Delete(int n); | |
104 | ||
18dbdd3c MB |
105 | virtual int GetCount() const { return (int)m_strings->GetCount(); } |
106 | virtual wxString GetString(int n) const { return (*m_strings)[n]; } | |
1e6feb95 VZ |
107 | virtual void SetString(int n, const wxString& s); |
108 | virtual int FindString(const wxString& s) const | |
18dbdd3c | 109 | { return IsSorted() ? m_stringsSorted->Index(s) : m_strings->Index(s); } |
1e6feb95 VZ |
110 | |
111 | virtual bool IsSelected(int n) const | |
112 | { return m_selections.Index(n) != wxNOT_FOUND; } | |
113 | virtual void SetSelection(int n, bool select = TRUE); | |
114 | virtual int GetSelection() const; | |
115 | virtual int GetSelections(wxArrayInt& aSelections) const; | |
116 | ||
117 | protected: | |
118 | virtual int DoAppend(const wxString& item); | |
119 | virtual void DoInsertItems(const wxArrayString& items, int pos); | |
120 | virtual void DoSetItems(const wxArrayString& items, void **clientData); | |
121 | ||
122 | virtual void DoSetFirstItem(int n); | |
123 | ||
124 | virtual void DoSetItemClientData(int n, void* clientData); | |
125 | virtual void* DoGetItemClientData(int n) const; | |
126 | virtual void DoSetItemClientObject(int n, wxClientData* clientData); | |
127 | virtual wxClientData* DoGetItemClientObject(int n) const; | |
128 | ||
129 | public: | |
130 | // override some more base class methods | |
131 | virtual bool SetFont(const wxFont& font); | |
132 | ||
133 | // the wxUniversal-specific methods | |
134 | // -------------------------------- | |
135 | ||
136 | // the current item is the same as the selected one for wxLB_SINGLE | |
137 | // listboxes but for the other ones it is just the focused item which may | |
138 | // be selected or not | |
139 | int GetCurrentItem() const { return m_current; } | |
140 | void SetCurrentItem(int n); | |
141 | ||
142 | // select the item which is diff items below the current one | |
143 | void ChangeCurrent(int diff); | |
144 | ||
145 | // activate (i.e. send a LISTBOX_DOUBLECLICKED message) the specified or | |
146 | // current (if -1) item | |
147 | void Activate(int item = -1); | |
148 | ||
149 | // select or unselect the specified or current (if -1) item | |
2b5f62a0 | 150 | void DoSelect(int item = -1, bool sel = TRUE); |
1e6feb95 VZ |
151 | |
152 | // more readable wrapper | |
2b5f62a0 | 153 | void DoUnselect(int item) { DoSelect(item, FALSE); } |
1e6feb95 VZ |
154 | |
155 | // select an item and send a notification about it | |
156 | void SelectAndNotify(int item); | |
157 | ||
158 | // ensure that the given item is visible by scrolling it into view | |
159 | virtual void EnsureVisible(int n); | |
160 | ||
161 | // find the first item [strictly] after the current one which starts with | |
162 | // the given string and make it the current one, return TRUE if the current | |
163 | // item changed | |
164 | bool FindItem(const wxString& prefix, bool strictlyAfter = FALSE); | |
165 | bool FindNextItem(const wxString& prefix) { return FindItem(prefix, TRUE); } | |
166 | ||
167 | // extend the selection to span the range from the anchor (see below) to | |
168 | // the specified or current item | |
169 | void ExtendSelection(int itemTo = -1); | |
170 | ||
171 | // make this item the new selection anchor: extending selection with | |
172 | // ExtendSelection() will work with it | |
173 | void AnchorSelection(int itemFrom) { m_selAnchor = itemFrom; } | |
174 | ||
175 | // get, calculating it if necessary, the number of items per page, the | |
176 | // height of each line and the max width of an item | |
177 | int GetItemsPerPage() const; | |
178 | wxCoord GetLineHeight() const; | |
179 | wxCoord GetMaxWidth() const; | |
180 | ||
181 | // override the wxControl virtual methods | |
182 | virtual bool PerformAction(const wxControlAction& action, | |
183 | long numArg = 0l, | |
184 | const wxString& strArg = wxEmptyString); | |
185 | ||
e39af974 JS |
186 | // idle processing |
187 | virtual void OnInternalIdle(); | |
81b344a5 | 188 | |
1e6feb95 VZ |
189 | protected: |
190 | // geometry | |
191 | virtual wxSize DoGetBestClientSize() const; | |
192 | virtual void DoSetSize(int x, int y, | |
193 | int width, int height, | |
194 | int sizeFlags = wxSIZE_AUTO); | |
195 | ||
196 | virtual void DoDraw(wxControlRenderer *renderer); | |
197 | virtual wxBorder GetDefaultBorder() const; | |
198 | ||
199 | // common part of all ctors | |
200 | void Init(); | |
201 | ||
202 | // event handlers | |
1e6feb95 VZ |
203 | void OnSize(wxSizeEvent& event); |
204 | ||
205 | // common part of Clear() and DoSetItems(): clears everything | |
206 | virtual void DoClear(); | |
207 | ||
208 | // refresh the given item(s) or everything | |
209 | void RefreshItems(int from, int count); | |
210 | void RefreshItem(int n); | |
211 | void RefreshFromItemToEnd(int n); | |
212 | void RefreshAll(); | |
213 | ||
214 | // send an event of the given type (using m_current by default) | |
215 | bool SendEvent(wxEventType type, int item = -1); | |
216 | ||
217 | // calculate the number of items per page using our current size | |
218 | void CalcItemsPerPage(); | |
219 | ||
220 | // can/should we have a horz scrollbar? | |
221 | bool HasHorzScrollbar() const | |
222 | { return (m_windowStyle & wxLB_HSCROLL) != 0; } | |
223 | ||
224 | // redraw the items in the given range only: called from DoDraw() | |
225 | virtual void DoDrawRange(wxControlRenderer *renderer, | |
226 | int itemFirst, int itemLast); | |
227 | ||
228 | // update the scrollbars and then ensure that the item is visible | |
229 | void DoEnsureVisible(int n); | |
230 | ||
231 | // mark horz scrollbar for updating | |
232 | void RefreshHorzScrollbar(); | |
233 | ||
234 | // update (show/hide/adjust) the scrollbars | |
235 | void UpdateScrollbars(); | |
236 | ||
237 | // refresh the items specified by m_updateCount and m_updateFrom | |
238 | void UpdateItems(); | |
239 | ||
240 | // the array containing all items (it is sorted if the listbox has | |
18dbdd3c MB |
241 | // wxLB_SORT style). Note the evil trick: the pointers share the |
242 | // same location, hence we use m_strings when we don't care if the | |
243 | // array is sorted or not, m_stringsSorted when we do | |
244 | union | |
245 | { | |
246 | wxArrayString* m_strings; | |
247 | wxSortedArrayString* m_stringsSorted; | |
248 | }; | |
1e6feb95 VZ |
249 | |
250 | // this array contains the indices of the selected items (for the single | |
251 | // selection listboxes only the first element of it is used and contains | |
252 | // the current selection) | |
253 | wxArrayInt m_selections; | |
254 | ||
255 | // and this one the client data (either void or wxClientData) | |
256 | wxArrayPtrVoid m_itemsClientData; | |
257 | ||
258 | // the current item | |
259 | int m_current; | |
260 | ||
261 | private: | |
262 | // the range of elements which must be updated: if m_updateCount is 0 no | |
263 | // update is needed, if it is -1 everything must be updated, otherwise | |
264 | // m_updateCount items starting from m_updateFrom have to be redrawn | |
265 | int m_updateFrom, | |
266 | m_updateCount; | |
267 | ||
268 | // the height of one line in the listbox (all lines have the same height) | |
269 | wxCoord m_lineHeight; | |
270 | ||
271 | // the maximal width of a listbox item and the item which has it | |
272 | wxCoord m_maxWidth; | |
273 | int m_maxWidthItem; | |
274 | ||
275 | // the extents of horz and vert scrollbars | |
276 | int m_scrollRangeX, | |
277 | m_scrollRangeY; | |
278 | ||
279 | // the number of items per page | |
280 | size_t m_itemsPerPage; | |
281 | ||
282 | // if the number of items has changed we may need to show/hide the | |
283 | // scrollbar | |
284 | bool m_updateScrollbarX, m_updateScrollbarY, | |
285 | m_showScrollbarX, m_showScrollbarY; | |
286 | ||
287 | // if the current item has changed, we might need to scroll if it went out | |
288 | // of the window | |
289 | bool m_currentChanged; | |
290 | ||
291 | // the anchor from which the selection is extended for the listboxes with | |
292 | // wxLB_EXTENDED style - this is set to the last item which was selected | |
293 | // by not extending the selection but by choosing it directly | |
294 | int m_selAnchor; | |
295 | ||
296 | DECLARE_EVENT_TABLE() | |
297 | DECLARE_DYNAMIC_CLASS(wxListBox) | |
298 | }; | |
299 | ||
300 | // ---------------------------------------------------------------------------- | |
301 | // wxStdListboxInputHandler: handles mouse and kbd in a single or multi | |
302 | // selection listbox | |
303 | // ---------------------------------------------------------------------------- | |
304 | ||
305 | class WXDLLEXPORT wxStdListboxInputHandler : public wxStdInputHandler | |
306 | { | |
307 | public: | |
308 | // if pressing the mouse button in a multiselection listbox should toggle | |
309 | // the item under mouse immediately, then specify TRUE as the second | |
310 | // parameter (this is the standard behaviour, under GTK the item is toggled | |
311 | // only when the mouse is released in the multi selection listbox) | |
312 | wxStdListboxInputHandler(wxInputHandler *inphand, | |
313 | bool toggleOnPressAlways = TRUE); | |
314 | ||
315 | // base class methods | |
23645bfa | 316 | virtual bool HandleKey(wxInputConsumer *consumer, |
1e6feb95 VZ |
317 | const wxKeyEvent& event, |
318 | bool pressed); | |
23645bfa | 319 | virtual bool HandleMouse(wxInputConsumer *consumer, |
1e6feb95 | 320 | const wxMouseEvent& event); |
23645bfa | 321 | virtual bool HandleMouseMove(wxInputConsumer *consumer, |
1e6feb95 VZ |
322 | const wxMouseEvent& event); |
323 | ||
324 | protected: | |
325 | // return the item under mouse, 0 if the mouse is above the listbox or | |
326 | // GetCount() if it is below it | |
327 | int HitTest(const wxListBox *listbox, const wxMouseEvent& event); | |
328 | ||
329 | // parts of HitTest(): first finds the pseudo (because not in range) index | |
330 | // of the item and the second one adjusts it if necessary - that is if the | |
331 | // third one returns FALSE | |
332 | int HitTestUnsafe(const wxListBox *listbox, const wxMouseEvent& event); | |
333 | int FixItemIndex(const wxListBox *listbox, int item); | |
334 | bool IsValidIndex(const wxListBox *listbox, int item); | |
335 | ||
336 | // init m_btnCapture and m_actionMouse | |
337 | wxControlAction SetupCapture(wxListBox *lbox, | |
338 | const wxMouseEvent& event, | |
339 | int item); | |
340 | ||
341 | wxRenderer *m_renderer; | |
342 | ||
343 | // the button which initiated the mouse capture (currently 0 or 1) | |
344 | int m_btnCapture; | |
345 | ||
346 | // the action to perform when the mouse moves while we capture it | |
347 | wxControlAction m_actionMouse; | |
348 | ||
349 | // the ctor parameter toggleOnPressAlways (see comments near it) | |
350 | bool m_toggleOnPressAlways; | |
351 | ||
352 | // do we track the mouse outside the window when it is captured? | |
353 | bool m_trackMouseOutside; | |
354 | }; | |
355 | ||
356 | #endif // _WX_UNIV_LISTBOX_H_ |