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