neoGFX
Cross-platform C++ app/game engine
Loading...
Searching...
No Matches
drop_list.hpp
Go to the documentation of this file.
1// drop_list.hpp
2/*
3 neogfx C++ App/Game Engine
4 Copyright (c) 2015, 2020 Leigh Johnston. All Rights Reserved.
5
6 This program is free software: you can redistribute it and / or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18*/
19
20#pragma once
21
22#include <neogfx/neogfx.hpp>
26
27namespace neogfx
28{
29 class drop_list;
30
31 template <typename ItemModel = item_model>
33 {
35 public:
36 using item_model_type = ItemModel;
37 public:
38 default_drop_list_presentation_model(drop_list& aDropList) : base_type{}, iDropList{ aDropList }
39 {
40 }
41 default_drop_list_presentation_model(drop_list& aDropList, item_model_type& aModel) : base_type{ aModel }, iDropList{ aDropList }
42 {
43 }
44 public:
45 item_cell_flags column_flags(item_presentation_model_index::value_type aColumn) const override
46 {
47 return base_type::column_flags(aColumn) & ~item_cell_flags::Editable;
48 }
49 public:
50 optional_color cell_color(item_presentation_model_index const& aIndex, color_role aColorRole) const override
51 {
52 if (iDropList.view_created())
53 {
54 if (aColorRole == color_role::Background)
55 {
56 if ((base_type::cell_meta(aIndex).selection & item_cell_selection_flags::Current) == item_cell_selection_flags::Current)
57 {
58 auto backgroundColor = iDropList.list_view().palette_color(color_role::Void);
59 if (backgroundColor == iDropList.list_view().background_color())
60 backgroundColor = backgroundColor.shaded(0x20);
61 return backgroundColor;
62 }
63 else
64 return iDropList.list_view().palette_color(color_role::AlternateBase);
65 }
66 }
67 return {};
68 }
69 private:
70 drop_list& iDropList;
71 };
72
74 {
75 friend class drop_list_popup;
76 friend class drop_list;
77 public:
78 drop_list_view(i_layout& aLayout, drop_list& aDropList);
80 public:
82 protected:
83 void items_filtered() override;
84 protected:
85 void current_index_changed(const optional_item_presentation_model_index& aCurrentIndex, const optional_item_presentation_model_index& aPreviousIndex) override;
86 protected:
87 void mouse_button_released(mouse_button aButton, const point& aPosition) override;
88 bool mouse_wheel_scrolled(mouse_wheel aWheel, const point& aPosition, delta aDelta, key_modifiers_e aKeyModifiers) override;
89 protected:
90 bool key_pressed(scan_code_e aScanCode, key_code_e aKeyCode, key_modifiers_e aKeyModifiers) override;
91 private:
92 drop_list& iDropList;
93 };
94
95 class drop_list_popup : public window
96 {
97 friend class drop_list;
98 friend class drop_list_view;
99 public:
102 public:
103 const drop_list_view& list_view() const;
105 protected:
106 color frame_color() const override;
107 protected:
108 double rendering_priority() const override;
109 public:
110 using window::show;
111 bool show(bool aVisible) override;
112 protected:
113 neogfx::size_policy size_policy() const override;
114 bool has_ideal_size() const noexcept override;
115 size ideal_size(optional_size const& aAvailableSpace = optional_size{}) const override;
116 size minimum_size(optional_size const& aAvailableSpace = optional_size{}) const override;
117 public:
118 bool can_dismiss(const i_widget*) const override;
119 dismissal_type_e dismissal_type() const override;
120 bool dismissed() const override;
121 void dismiss() override;
122 private:
123 void update_placement();
124 private:
125 drop_list& iDropList;
126 drop_list_view iView;
127 };
128
130 {
131 public:
132 declare_event(text_changed)
133 public:
134 typedef i_drop_list_input_widget abstract_type;
136 {
137 public:
138 virtual void visit(i_drop_list_input_widget& aInputWidget, push_button& aButtonWidget) = 0;
139 virtual void visit(i_drop_list_input_widget& aInputWidget, line_edit& aTextWidget) = 0;
140 };
141 public:
142 virtual ~i_drop_list_input_widget() = default;
143 public:
144 virtual void accept(i_visitor& aVisitor) = 0;
145 public:
146 virtual const i_widget& as_widget() const = 0;
147 virtual i_widget& as_widget() = 0;
148 public:
149 virtual bool editable() const = 0;
150 virtual const i_widget& image_widget() const = 0;
151 virtual i_widget& image_widget() = 0;
152 virtual const i_widget& text_widget() const = 0;
153 virtual i_widget& text_widget() = 0;
154 virtual size spacing() const = 0;
155 virtual void set_spacing(const size& aSpacing) = 0;
156 virtual const i_texture& image() const = 0;
157 virtual void set_image(const i_texture& aImage) = 0;
158 virtual i_string const& text() const = 0;
159 virtual void set_text(i_string const& aText) = 0;
160 };
161
162 enum class drop_list_style : uint32_t
163 {
164 Normal = 0x0000,
165 Editable = 0x0001,
166 ListAlwaysVisible = 0x0002,
167 NoFilter = 0x0004
168 };
169}
170
177
178namespace neogfx
179{
181 {
182 return static_cast<drop_list_style>(static_cast<uint32_t>(aLhs) | static_cast<uint32_t>(aRhs));
183 }
184
186 {
187 return static_cast<drop_list_style>(static_cast<uint32_t>(aLhs) & static_cast<uint32_t>(aRhs));
188 }
189
191 {
192 return static_cast<drop_list_style>(~static_cast<uint32_t>(aLhs));
193 }
194
195 class drop_list : public widget<>, private i_drop_list_input_widget::i_visitor
196 {
197 friend class drop_list_view;
198 public:
199 define_event(SelectionChanged, selection_changed, optional_item_model_index)
200 public:
201 struct no_selection : std::runtime_error { no_selection() : std::runtime_error("neogfx::drop_list::no_selection") {} };
202 private:
203 class list_proxy
204 {
205 private:
206 class view_container : public framed_widget<>
207 {
208 typedef framed_widget<> base_type;
209 public:
210 view_container(i_layout& aLayout);
211 public:
212 color palette_color(color_role aColorRole) const override;
213 color frame_color() const override;
214 };
215 public:
216 struct no_view : std::logic_error { no_view() : std::logic_error("neogfx::drop_list::list_proxy::no_view") {} };
217 public:
218 list_proxy(drop_list& aDropList);
219 ~list_proxy();
220 public:
221 bool view_created() const;
222 bool view_visible() const;
223 drop_list_view& list_view() const;
224 dimension effective_frame_width() const;
225 public:
226 void show_view();
227 void hide_view();
228 void close_view();
229 void update_view_placement();
230 private:
231 drop_list& iDropList;
232 mutable std::optional<drop_list_popup> iPopup;
233 mutable std::optional<view_container> iViewContainer;
234 mutable std::optional<drop_list_view> iView;
235 sink iSink;
236 };
237 public:
238 drop_list(drop_list_style aStyle = drop_list_style::Normal);
239 drop_list(i_widget& aParent, drop_list_style aStyle = drop_list_style::Normal);
240 drop_list(i_layout& aLayout, drop_list_style aStyle = drop_list_style::Normal);
241 ~drop_list();
242 public:
243 bool has_model() const;
244 const i_item_model& model() const;
245 i_item_model& model();
246 void set_model(i_item_model& aModel);
247 void set_model(i_ref_ptr<i_item_model> const& aModel);
248 bool has_presentation_model() const;
249 const i_item_presentation_model& presentation_model() const;
250 i_item_presentation_model& presentation_model();
251 void set_presentation_model(i_item_presentation_model& aPresentationModel);
252 void set_presentation_model(i_ref_ptr<i_item_presentation_model> const& aPresentationModel);
253 bool has_selection_model() const;
254 const i_item_selection_model& selection_model() const;
255 i_item_selection_model& selection_model();
256 void set_selection_model(i_item_selection_model& aSelectionModel);
257 void set_selection_model(i_ref_ptr<i_item_selection_model> const& aSelectionModel);
258 public:
259 bool has_selection() const;
260 const item_model_index& selection() const;
261 public:
262 bool input_matches_current_item() const;
263 bool input_matches_selection() const;
264 public:
265 bool view_created() const;
266 bool view_visible() const;
267 void show_view();
268 void hide_view();
269 void close_view();
270 drop_list_view& list_view() const;
271 void accept_selection();
272 void cancel_selection(bool aClearInput = false);
273 void cancel_and_restore_selection(bool aOnlyRestoreIfViewCreated = false);
274 public:
275 drop_list_style style() const;
276 void set_style(drop_list_style aStyle);
277 bool editable() const;
278 void set_editable(bool aEditable);
279 bool list_always_visible() const;
280 void set_list_always_visible(bool aListAlwaysVisible);
281 bool filter_enabled() const;
282 void enable_filter(bool aEnableFilter);
283 bool has_input() const;
284 const i_drop_list_input_widget& input_widget() const;
285 i_drop_list_input_widget& input_widget();
286 public:
287 bool changing_text() const;
288 bool handling_text_change() const;
289 bool accepting_selection() const;
290 bool cancelling_selection() const;
291 public:
292 neogfx::size_policy size_policy() const override;
293 size minimum_size(optional_size const& aAvailableSpace = optional_size{}) const override;
294 private:
295 void visit(i_drop_list_input_widget& aInputWidget, push_button& aButtonWidget) override;
296 void visit(i_drop_list_input_widget& aInputWidget, line_edit& aTextWidget) override;
297 private:
298 void init();
299 void update_widgets(bool aForce = false);
300 void update_arrow();
301 void handle_clicked();
302 void handle_cancel_selection(bool aRestoreSavedSelection, bool aUpdateEditor = true);
303 bool handle_proxy_key_event(const neogfx::keyboard_event& aEvent);
304 private:
305 drop_list_style iStyle;
306 vertical_layout iLayout0;
307 horizontal_layout iLayout1;
308 std::unique_ptr<i_drop_list_input_widget> iInputWidget;
309 ref_ptr<i_item_model> iModel;
310 ref_ptr<i_item_presentation_model> iPresentationModel;
311 ref_ptr<i_item_selection_model> iSelectionModel;
312 sink iSink;
313 sink iSelectionSink;
314 mutable std::optional<std::pair<color, texture>> iDownArrowTexture;
315 image_widget iDownArrow;
316 list_proxy iListProxy;
317 optional_item_model_index iSavedSelection;
318 optional_item_model_index iSelection;
319 bool iChangingText;
320 bool iHandlingTextChange;
321 bool iAcceptingSelection;
322 bool iCancellingSelection;
323 };
324}
default_drop_list_presentation_model(drop_list &aDropList, item_model_type &aModel)
Definition drop_list.hpp:41
optional_color cell_color(item_presentation_model_index const &aIndex, color_role aColorRole) const override
Definition drop_list.hpp:50
item_cell_flags column_flags(item_presentation_model_index::value_type aColumn) const override
Definition drop_list.hpp:45
default_drop_list_presentation_model(drop_list &aDropList)
Definition drop_list.hpp:38
neogfx::size_policy size_policy() const override
const drop_list_view & list_view() const
dismissal_type_e dismissal_type() const override
size minimum_size(optional_size const &aAvailableSpace=optional_size{}) const override
drop_list_popup(drop_list &aDropList)
double rendering_priority() const override
bool dismissed() const override
bool has_ideal_size() const noexcept override
bool show(bool aVisible) override
bool can_dismiss(const i_widget *) const override
color frame_color() const override
drop_list_view & list_view()
size ideal_size(optional_size const &aAvailableSpace=optional_size{}) const override
void dismiss() override
bool key_pressed(scan_code_e aScanCode, key_code_e aKeyCode, key_modifiers_e aKeyModifiers) override
drop_list_view(i_layout &aLayout, drop_list &aDropList)
friend class drop_list
Definition drop_list.hpp:76
void items_filtered() override
void mouse_button_released(mouse_button aButton, const point &aPosition) override
bool mouse_wheel_scrolled(mouse_wheel aWheel, const point &aPosition, delta aDelta, key_modifiers_e aKeyModifiers) override
void current_index_changed(const optional_item_presentation_model_index &aCurrentIndex, const optional_item_presentation_model_index &aPreviousIndex) override
virtual void visit(i_drop_list_input_widget &aInputWidget, line_edit &aTextWidget)=0
virtual void visit(i_drop_list_input_widget &aInputWidget, push_button &aButtonWidget)=0
virtual void set_image(const i_texture &aImage)=0
virtual i_string const & text() const =0
virtual i_widget & text_widget()=0
virtual size spacing() const =0
virtual const i_widget & as_widget() const =0
virtual ~i_drop_list_input_widget()=default
virtual const i_widget & image_widget() const =0
virtual const i_texture & image() const =0
virtual bool editable() const =0
virtual const i_widget & text_widget() const =0
virtual i_widget & image_widget()=0
virtual i_widget & as_widget()=0
virtual void set_spacing(const size &aSpacing)=0
virtual void set_text(i_string const &aText)=0
virtual void accept(i_visitor &aVisitor)=0
size total_item_area(i_units_context const &aUnitsContext) const override
bool show(bool aVisible) override
#define end_declare_enum(enumName)
Definition i_enum.hpp:62
#define declare_enum_string(enumName, enumEnumerator)
Definition i_enum.hpp:59
#define begin_declare_enum(enumName)
Definition i_enum.hpp:52
constexpr style_aspect operator&(style_aspect aLhs, style_aspect aRhs)
Definition i_style.hpp:60
mouse_wheel
Definition i_mouse.hpp:42
audio_channel operator~(audio_channel lhs)
default_geometry_value_type dimension
mouse_button
Definition i_mouse.hpp:31
constexpr style_aspect operator|(style_aspect aLhs, style_aspect aRhs)
Definition i_style.hpp:55
sRGB_color color
Definition color.hpp:1067
std::optional< item_model_index > optional_item_model_index
@ AlternateBase
Definition i_palette.hpp:36
@ Background
Definition i_palette.hpp:33
basic_size< coordinate > size
Definition plf_hive.h:79
constexpr decltype(auto) visit(Visitor &&vis, neolib::variant< Types... > &&var)
Definition variant.hpp:60
#define meta_object(...)
Definition i_object.hpp:28
#define define_event(name, declName,...)
Definition event.hpp:200
#define declare_event(declName,...)
Definition i_event.hpp:305