1 //------------------------------------------------------------------------------
2 // emListBox.h
3 //
4 // Copyright (C) 2015-2016 Oliver Hamann.
5 //
6 // Homepage: http://eaglemode.sourceforge.net/
7 //
8 // This program is free software: you can redistribute it and/or modify it under
9 // the terms of the GNU General Public License version 3 as published by the
10 // Free Software Foundation.
11 //
12 // This program is distributed in the hope that it will be useful, but WITHOUT
13 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 // FOR A PARTICULAR PURPOSE. See the GNU General Public License version 3 for
15 // more details.
16 //
17 // You should have received a copy of the GNU General Public License version 3
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 //------------------------------------------------------------------------------
20
21 #ifndef emListBox_h
22 #define emListBox_h
23
24 #ifndef emAnything_h
25 #include <emCore/emAnything.h>
26 #endif
27
28 #ifndef emRasterGroup_h
29 #include <emCore/emRasterGroup.h>
30 #endif
31
32
33 //==============================================================================
34 //================================= emListBox ==================================
35 //==============================================================================
36
37 class emListBox : public emRasterGroup {
38
39 public:
40
41 // Class for list box. It is an emRasterGroup which shows a group of
42 // text items, from which the user can select one item. Optionally,
43 // multi-selection can be enabled. Each item just consists of a text,
44 // but it is possible to derive from emListBox in order to create custom
45 // item panels, which show more than just a text.
46
47 enum SelectionType {
48 // Type of selection a user can make in an emListBox.
49 READY_ONLY_SELECTION,
50 SINGLE_SELECTION,
51 MULTI_SELECTION,
52 TOGGLE_SELECTION
53 };
54
55 emListBox(
56 ParentArg parent, const emString & name,
57 const emString & caption=emString(),
58 const emString & description=emString(),
59 const emImage & icon=emImage(),
60 SelectionType selType=SINGLE_SELECTION
61 );
62 // Constructor.
63 // Arguments:
64 // parent - Parent for this panel (emPanel or emView).
65 // name - The name for this panel.
66 // caption - The label's caption, or empty.
67 // description - The label's description, or empty.
68 // icon - The label's icon, or empty.
69 // selType - Type of selection.
70
71 virtual ~emListBox();
72 // Destructor.
73
74 SelectionType GetSelectionType() const;
75 void SetSelectionType(SelectionType selType);
76 // Get or set the type of selection, which the user can make in
77 // this list box.
78
79 int GetItemCount() const;
80 // Get number of Items.
81
82 void AddItem(
83 const emString & text,
84 const emAnything & data = emAnything()
85 );
86 // Add an item to the end of the list.
87 // Arguments:
88 // text - The text to be shown in the item.
89 // data - Any custom data to be stored in the item.
90
91 void InsertItem(
92 int index, const emString & text,
93 const emAnything & data = emAnything()
94 );
95 // Add an item at any position in the list.
96 // Arguments:
97 // index - Index of the new item.
98 // text - The text to be shown in the item.
99 // data - Any custom data to be stored in the item.
100
101 void RemoveItem(int index);
102 // Remove an item from the list.
103 // Arguments:
104 // index - Index of the item to be removed.
105
106 void ClearItems();
107 // Remove all items.
108
109 emString GetItemText(int index) const;
110 // Get the text of an item.
111 // Arguments:
112 // index - Index of the item.
113 // Returns: The text of the item, or an empty string if the
114 // index is out of range.
115
116 void SetItemText(int index, const emString & text);
117 // Set the text of an item.
118 // Arguments:
119 // index - Index of the item.
120 // text - The text to be shown in the item.
121
122 emAnything GetItemData(int index) const;
123 // Get the data of an item.
124 // Arguments:
125 // index - Index of the item.
126 // Returns: The data of the item, or an invalid emAnything if
127 // the index is out of range.
128
129 void SetItemData(int index, const emAnything & data);
130 // Set the data of an item.
131 // Arguments:
132 // index - Index of the item.
133 // data - Any custom data to be stored in the item.
134
135 int GetSelectionCount() const;
136 // Get number of selected items.
137
138 const emArray<int> & GetSelectedIndices() const;
139 // Get the indices of the selected items. The returned array is
140 // always sorted.
141
142 void SetSelectedIndices(const emArray<int> & itemIndices);
143 // Set the indices of the selected items.
144
145 int GetSelectedIndex() const;
146 // Get the index of the first (or solely) selected item. If no
147 // item is selected, -1 is returned.
148
149 void SetSelectedIndex(int index);
150 // Select a certain item solely.
151 // Arguments:
152 // index - Index of the item.
153
154 bool IsSelected(int index) const;
155 // Ask whether a certain item is selected.
156 // Arguments:
157 // index - Index of the item.
158
159 void Select(int index, bool solely=false);
160 // Select an item.
161 // Arguments:
162 // index - Index of the item.
163 // solely - Whether all other items should be deselected.
164
165 void Deselect(int index);
166 // Deselect an item.
167 // Arguments:
168 // index - Index of the item.
169
170 void ToggleSelection(int index);
171 // Invert the selection of an item.
172 // Arguments:
173 // index - Index of the item.
174
175 void SelectAll();
176 // Select all items.
177
178 void ClearSelection();
179 // Deselect all items.
180
181 const emSignal & GetSelectionSignal() const;
182 // This signal is signaled after each change of the selection.
183
184 const emSignal & GetItemTriggerSignal() const;
185 // This signal is signaled when an item is triggered by a double
186 // click or by pressing the enter key. The triggered item index
187 // can be get with GetTriggeredItemIndex().
188
189 int GetTriggeredItemIndex() const;
190 // Get the index of the item which was triggered by a double
191 // click or enter key press.
192
193 void TriggerItem(int index);
194 // Trigger an item programmatically.
195
196 class ItemPanelInterface {
197
198 public:
199
200 // Class for an interface to an item panel. This must be derived
201 // by custom item panel classes. Also see
202 // emListBox::CreateItemPanel(...).
203
204 ItemPanelInterface(emListBox & listBox, int itemIndex);
205 // Constructor.
206 // Arguments:
207 // listBox - The list box.
208 // itemIndex - The index of the item.
209
210 virtual ~ItemPanelInterface();
211 // Destructor.
212
213 emListBox & GetListBox() const;
214 // Get the list box.
215
216 int GetItemIndex() const;
217 // Get the item index.
218
219 emString GetItemText() const;
220 // The the text of the item.
221
222 emAnything GetItemData() const;
223 // The the data of the item.
224
225 bool IsItemSelected() const;
226 // Whether the item is selected.
227
228 protected:
229
230 void ProcessItemInput(
231 emPanel * panel, emInputEvent & event,
232 const emInputState & state
233 );
234 // Process mouse an keyboard events which select,
235 // deselect, or trigger an item. This method must be
236 // called from the Input method of the item panel.
237
238 virtual void ItemTextChanged() = 0;
239 // Called when the text of the item has changed.
240
241 virtual void ItemDataChanged() = 0;
242 // Called when the data of the item has changed.
243
244 virtual void ItemSelectionChanged() = 0;
245 // Called when the selection of the item has changed.
246
247 private:
248 friend class emListBox;
249 emListBox & ListBox;
250 int ItemIndex;
251 };
252
253 class DefaultItemPanel : public emPanel, public ItemPanelInterface {
254
255 public:
256
257 // Default class for an item panel.
258
259 DefaultItemPanel(emListBox & listBox, const emString & name,
260 int itemIndex);
261
262 virtual ~DefaultItemPanel();
263
264 protected:
265
266 virtual void Input(emInputEvent & event,
267 const emInputState & state,
268 double mx, double my);
269
270 virtual bool IsOpaque() const;
271
272 virtual void Paint(const emPainter & painter,
273 emColor canvasColor) const;
274
275 virtual void ItemTextChanged();
276
277 virtual void ItemDataChanged();
278
279 virtual void ItemSelectionChanged();
280 };
281
282 protected:
283
284 virtual void CreateItemPanel(const emString & name, int itemIndex);
285 // Create the panel for an item. This can be overloaded in order
286 // to have custom item panels. The default implementation
287 // creates an instance of emListBox::DefaultItemPanel. A derived
288 // class may create a panel of an other class. It just has to be
289 // a derivative of emPanel and mListBox::ItemPanelInterface.
290
291 virtual emString GetItemPanelName(int index) const;
292 // Get the name for an item panel. The default implementation
293 // simply converts the index to a decimal string.
294
295 virtual emPanel * GetItemPanel(int index) const;
296 // Get an item panel. The default implementation calls
297 // GetChild(..) with the name of the item panel.
298
299 virtual ItemPanelInterface * GetItemPanelInterface(int index) const;
300 // Get the ItemPanelInterface for an item panel. The default
301 // implementation calls GetItemPanel and does a dynamic cast.
302
303 virtual void Notice(NoticeFlags flags);
304
305 virtual void Input(emInputEvent & event, const emInputState & state,
306 double mx, double my);
307
308 virtual void AutoExpand();
309
310 // - - - - - - - - - - Depreciated methods - - - - - - - - - - - - - - -
311 // The following virtual non-const methods have been replaced by const
312 // methods (see above). The old versions still exist here with the
313 // "final" keyword added, so that old overridings will fail to compile.
314 // If you run into this, please adapt your overridings by adding "const".
315 virtual emPanel * GetItemPanel(int index) final;
316 virtual ItemPanelInterface * GetItemPanelInterface(int index) final;
317 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
318
319 private:
320
321 friend class ItemPanelInterface;
322
323 void ProcessItemInput(
324 int itemIndex, emPanel * panel, emInputEvent & event,
325 const emInputState & state
326 );
327
328 void SelectByInput(int itemIndex, bool shift, bool ctrl, bool trigger);
329
330 void KeyWalk(emInputEvent & event, const emInputState & state);
331
332 struct Item {
333 emString Text;
334 emAnything Data;
335 bool Selected;
336 };
337
338 SelectionType SelType;
339 emArray<Item> Items;
340 emArray<int> SelectedItemIndices;
341 int TriggeredItemIndex;
342 int PrevInputItemIndex;
343 emSignal SelectionSignal;
344 emSignal ItemTriggerSignal;
345 emString KeyWalkChars;
346 emUInt64 KeyWalkClock;
347 };
348
GetSelectionType()349 inline emListBox::SelectionType emListBox::GetSelectionType() const
350 {
351 return SelType;
352 }
353
GetItemCount()354 inline int emListBox::GetItemCount() const
355 {
356 return Items.GetCount();
357 }
358
GetSelectionCount()359 inline int emListBox::GetSelectionCount() const
360 {
361 return SelectedItemIndices.GetCount();
362 }
363
GetSelectedIndices()364 inline const emArray<int> & emListBox::GetSelectedIndices() const
365 {
366 return SelectedItemIndices;
367 }
368
GetSelectionSignal()369 inline const emSignal & emListBox::GetSelectionSignal() const
370 {
371 return SelectionSignal;
372 }
373
GetItemTriggerSignal()374 inline const emSignal & emListBox::GetItemTriggerSignal() const
375 {
376 return ItemTriggerSignal;
377 }
378
GetTriggeredItemIndex()379 inline int emListBox::GetTriggeredItemIndex() const
380 {
381 return TriggeredItemIndex;
382 }
383
GetListBox()384 inline emListBox & emListBox::ItemPanelInterface::GetListBox() const
385 {
386 return ListBox;
387 }
388
GetItemIndex()389 inline int emListBox::ItemPanelInterface::GetItemIndex() const
390 {
391 return ItemIndex;
392 }
393
GetItemText()394 inline emString emListBox::ItemPanelInterface::GetItemText() const
395 {
396 return ListBox.GetItemText(ItemIndex);
397 }
398
GetItemData()399 inline emAnything emListBox::ItemPanelInterface::GetItemData() const
400 {
401 return ListBox.GetItemData(ItemIndex);
402 }
403
IsItemSelected()404 inline bool emListBox::ItemPanelInterface::IsItemSelected() const
405 {
406 return ListBox.IsSelected(ItemIndex);
407 }
408
409
410 #endif
411