comparison foosdk/sdk/foobar2000/SDK/ui_element.h @ 1:20d02a178406 default tip

*: check in everything else yay
author Paper <paper@tflc.us>
date Mon, 05 Jan 2026 02:15:46 -0500
parents
children
comparison
equal deleted inserted replaced
0:e9bb126753e7 1:20d02a178406
1 #pragma once
2
3 //! Configuration of a UI element instance.
4 class NOVTABLE ui_element_config : public service_base {
5 public:
6 //! Returns GUID of the UI element this configuration data belongs to.
7 virtual GUID get_guid() const = 0;
8 //! Returns raw configuration data pointer.
9 virtual const void * get_data() const = 0;
10 //! Returns raw configuration data size, in bytes.
11 virtual t_size get_data_size() const = 0;
12
13
14 //! Helper.
15 static service_ptr_t<ui_element_config> g_create(const GUID& id, const void * data, t_size size);
16
17 template<typename t_source> static service_ptr_t<ui_element_config> g_create(const GUID& id, t_source const & data) {
18 pfc::assert_byte_type<typename t_source::t_item>();
19 return g_create(id, data.get_ptr(), data.get_size());
20 }
21
22 static service_ptr_t<ui_element_config> g_create_empty(const GUID & id = pfc::guid_null) {return g_create(id,NULL,0);}
23
24 static service_ptr_t<ui_element_config> g_create(const GUID & id, stream_reader * in, t_size bytes, abort_callback & abort);
25 static service_ptr_t<ui_element_config> g_create(stream_reader * in, t_size bytes, abort_callback & abort);
26 static service_ptr_t<ui_element_config> g_create(const void * data, t_size size);
27 service_ptr_t<ui_element_config> clone() const {
28 return g_create(get_guid(), get_data(), get_data_size());
29 }
30
31 FB2K_MAKE_SERVICE_INTERFACE(ui_element_config,service_base);
32 };
33
34 //! Helper for reading data from ui_element_config.
35 class ui_element_config_parser : public stream_reader_formatter<> {
36 public:
37 ui_element_config_parser(ui_element_config::ptr in) : stream_reader_formatter(_m_stream, fb2k::noAbort), m_data(in), _m_stream(in->get_data(),in->get_data_size()) {}
38
39 void reset() {_m_stream.reset();}
40 t_size get_remaining() const {return _m_stream.get_remaining();}
41
42 ui_element_config::ptr subelement(t_size size);
43 ui_element_config::ptr subelement(const GUID & id, t_size dataSize);
44 private:
45 const ui_element_config::ptr m_data;
46 stream_reader_memblock_ref _m_stream;
47 };
48
49 //! Helper creating ui_element_config from your data.
50 class ui_element_config_builder : public stream_writer_formatter<> {
51 public:
52 ui_element_config_builder() : stream_writer_formatter(_m_stream,fb2k::noAbort) {}
53 ui_element_config::ptr finish(const GUID & id) {
54 return ui_element_config::g_create(id,_m_stream.m_buffer);
55 }
56 void reset() {
57 _m_stream.m_buffer.set_size(0);
58 }
59 private:
60 stream_writer_buffer_simple _m_stream;
61 };
62
63
64 FB2K_STREAM_WRITER_OVERLOAD(ui_element_config::ptr) {
65 stream << value->get_guid();
66 t_size size = value->get_data_size();
67 stream << pfc::downcast_guarded<t_uint32>(size);
68 stream.write_raw(value->get_data(),size);
69 return stream;
70 }
71 FB2K_STREAM_READER_OVERLOAD(ui_element_config::ptr) {
72 GUID guid;
73 t_uint32 size;
74 stream >> guid >> size;
75 value = ui_element_config::g_create(guid,&stream.m_stream,size,stream.m_abort);
76 return stream;
77 }
78
79
80 typedef uint32_t t_ui_color;
81 typedef fb2k::hfont_t t_ui_font;
82 typedef fb2k::hicon_t t_ui_icon;
83
84 constexpr GUID ui_color_text = { 0x5dd38be7, 0xff8a, 0x416f, { 0x88, 0x2d, 0xa4, 0x8e, 0x31, 0x87, 0x85, 0xb2 } };
85 constexpr GUID ui_color_background = { 0x16fc40c1, 0x1cba, 0x4385, { 0x93, 0x3b, 0xe9, 0x32, 0x7f, 0x6e, 0x35, 0x1f } };
86 constexpr GUID ui_color_highlight = { 0xd2f98042, 0x3e6a, 0x423a, { 0xb8, 0x66, 0x65, 0x1, 0xfe, 0xa9, 0x75, 0x93 } };
87 constexpr GUID ui_color_selection = { 0xebe1a36b, 0x7e0a, 0x469a, { 0x8e, 0xc5, 0xcf, 0x3, 0x12, 0x90, 0x40, 0xb5 } };
88 // Special pseudo-color - black or white depending on dark mode state, undefined in fb2k versions that don't recognize dark mode.
89 constexpr GUID ui_color_darkmode = { 0x9050bca9, 0x4ed, 0x40e9, { 0xb0, 0xfc, 0x9c, 0x67, 0x9c, 0xc2, 0x28, 0x6d } };
90
91
92 constexpr GUID ui_font_default = { 0x9ef02cef, 0xe58a, 0x4f99, { 0x9f, 0xe3, 0x85, 0x39, 0xb, 0xed, 0xc5, 0xe0 } };
93 constexpr GUID ui_font_tabs = { 0x65ffd7ac, 0x71ce, 0x495c, { 0xa5, 0x99, 0x48, 0x5b, 0xbf, 0x7a, 0x4, 0x7b } };
94 constexpr GUID ui_font_lists = { 0xa86198b3, 0xb5d8, 0x40cf, { 0xac, 0x19, 0xf9, 0xda, 0xc, 0xb5, 0xd4, 0x24 } };
95 constexpr GUID ui_font_playlists = { 0xd85b7b7e, 0xbf83, 0x41ed, { 0x88, 0xce, 0x1, 0x99, 0x31, 0x94, 0x3e, 0x2f } };
96 constexpr GUID ui_font_statusbar = { 0xc7fd555b, 0xbd15, 0x4f74, { 0x93, 0xe, 0xba, 0x55, 0x52, 0x9d, 0xd9, 0x71 } };
97 constexpr GUID ui_font_console = { 0xb08c619d, 0xd3d1, 0x4089, { 0x93, 0xb2, 0xd5, 0xb, 0x87, 0x2d, 0x1a, 0x25 } };
98
99
100 #ifdef _WIN32
101
102 //! @returns -1 when the GUID is unknown / unmappable, index that can be passed over to GetSysColor() otherwise.
103 int ui_color_to_sys_color_index(const GUID & p_guid);
104 GUID ui_color_from_sys_color_index( int idx );
105
106 struct ui_element_min_max_info {
107 t_uint32 m_min_width = 0, m_max_width = UINT32_MAX, m_min_height = 0, m_max_height = UINT32_MAX;
108
109 const ui_element_min_max_info & operator|=(const ui_element_min_max_info & p_other);
110 ui_element_min_max_info operator|(const ui_element_min_max_info & p_other) const;
111 void adjustForWindow(HWND wnd);
112 };
113
114 typedef SIZE ui_size;
115 typedef RECT ui_rect;
116 #else
117 struct ui_element_min_max_info {}; // dummy
118 struct ui_size { int cx = 0, cy = 0; };
119 struct ui_rect { int l = 0, t = 0, r = 0, b = 0; };
120 #endif
121
122 //! Callback class passed by a UI element host to a UI element instance, allowing each UI element instance to communicate with its host. \n
123 //! Each ui_element_instance_callback implementation must also implement ui_element_instance_callback_v2.
124 class NOVTABLE ui_element_instance_callback : public service_base {
125 FB2K_MAKE_SERVICE_INTERFACE(ui_element_instance_callback,service_base);
126 public:
127 virtual void on_min_max_info_change() = 0;
128 //! Deprecated, does nothing.
129 virtual void on_alt_pressed(bool p_state) = 0;
130 //! Returns true on success, false when the color is undefined and defaults such as global windows settings should be used.
131 virtual bool query_color(const GUID & p_what,t_ui_color & p_out) = 0;
132 //! Tells the host that specified element wants to activate itself as a result of some kind of external user command (eg. menu command). Host should ensure that requesting child element's window is visible.\n
133 //! @returns True when relevant child element window has been properly made visible and requesting code should proceed to SetFocus their window etc, false when denied.
134 virtual bool request_activation(service_ptr_t<class ui_element_instance> p_item) = 0;
135
136 //! Queries whether "edit mode" is enabled. Most of UI element editing functionality should be locked when it's not.
137 virtual bool is_edit_mode_enabled() = 0;
138
139 //! Tells the host that the user has requested the element to be replaced with another one.
140 //! Note: this is generally used only when "edit mode" is enabled, but legal to call when it's not (eg. dummy element calls it regardless of settings when clicked).
141 virtual void request_replace(service_ptr_t<class ui_element_instance> p_item) = 0;
142
143 //! Deprecated - use query_font_ex. Equivalent to query_font_ex(ui_font_default).
144 t_ui_font query_font() {return query_font_ex(ui_font_default);}
145
146 //! Retrieves an user-configurable font to use for specified kind of display. See ui_font_* constant for possible parameters.
147 virtual t_ui_font query_font_ex(const GUID & p_what) = 0;
148
149 //! Helper - a wrapper around query_color(), if the color is not user-overridden, returns relevant system color.
150 t_ui_color query_std_color(const GUID & p_what);
151 #ifdef _WIN32
152 t_ui_color getSysColor( int sysColorIndex );
153 #endif
154
155 bool is_elem_visible_(service_ptr_t<class ui_element_instance> elem);
156
157 t_size notify_(ui_element_instance * source, const GUID & what, t_size param1, const void * param2, t_size param2size);
158 bool set_elem_label(ui_element_instance * source, const char * label);
159 t_uint32 get_dialog_texture(ui_element_instance * source);
160 bool is_border_needed(ui_element_instance * source);
161
162 bool is_dark_mode();
163 };
164
165
166 class NOVTABLE ui_element_instance_callback_v2 : public ui_element_instance_callback {
167 FB2K_MAKE_SERVICE_INTERFACE(ui_element_instance_callback_v2, ui_element_instance_callback);
168 public:
169 virtual bool is_elem_visible(service_ptr_t<class ui_element_instance> elem) = 0;
170 };
171
172 class NOVTABLE ui_element_instance_callback_v3 : public ui_element_instance_callback_v2 {
173 FB2K_MAKE_SERVICE_INTERFACE(ui_element_instance_callback_v3, ui_element_instance_callback_v2)
174 public:
175 //! Returns zero when the notification was not handled, return value depends on the notification otherwise.
176 virtual t_size notify(ui_element_instance * source, const GUID & what, t_size param1, const void * param2, t_size param2size) = 0;
177 };
178
179 typedef service_ptr_t<ui_element_instance_callback> ui_element_instance_callback_ptr;
180
181 //! ui_element_instance_callback implementation helper.
182 template<typename t_receiver> class ui_element_instance_callback_impl : public ui_element_instance_callback_v3 {
183 public:
184 ui_element_instance_callback_impl(t_receiver * p_receiver) : m_receiver(p_receiver) {}
185 void on_min_max_info_change() {
186 if (m_receiver != NULL) m_receiver->on_min_max_info_change();
187 }
188 void on_alt_pressed(bool p_state) { (void)p_state; }
189
190 bool query_color(const GUID & p_what,t_ui_color & p_out) {
191 if (m_receiver != NULL) return m_receiver->query_color(p_what,p_out);
192 else return false;
193 }
194
195 bool request_activation(service_ptr_t<class ui_element_instance> p_item) {
196 if (m_receiver) return m_receiver->request_activation(p_item);
197 else return false;
198 }
199
200 bool is_edit_mode_enabled() {
201 if (m_receiver) return m_receiver->is_edit_mode_enabled();
202 else return false;
203 }
204 void request_replace(service_ptr_t<class ui_element_instance> p_item) {
205 if (m_receiver) m_receiver->request_replace(p_item);
206 }
207
208 t_ui_font query_font_ex(const GUID & p_what) {
209 if (m_receiver) return m_receiver->query_font_ex(p_what);
210 else return NULL;
211 }
212
213 void orphan() {m_receiver = NULL;}
214
215 bool is_elem_visible(service_ptr_t<class ui_element_instance> elem) {
216 if (m_receiver) return m_receiver->is_elem_visible(elem);
217 else return false;
218 }
219 t_size notify(ui_element_instance * source, const GUID & what, t_size param1, const void * param2, t_size param2size) {
220 if (m_receiver) return m_receiver->host_notify(source, what, param1, param2, param2size);
221 else return 0;
222 }
223 private:
224 t_receiver * m_receiver;
225 };
226
227 //! ui_element_instance_callback implementation helper.
228 class ui_element_instance_callback_receiver {
229 public:
230 virtual void on_min_max_info_change() {}
231 virtual bool query_color(const GUID& p_what, t_ui_color& p_out) { (void)p_what; (void)p_out; return false; }
232 virtual bool request_activation(service_ptr_t<class ui_element_instance> p_item) { (void)p_item; return false; }
233 virtual bool is_edit_mode_enabled() {return false;}
234 virtual void request_replace(service_ptr_t<class ui_element_instance> p_item) {}
235 virtual t_ui_font query_font_ex(const GUID&) {return NULL;}
236 virtual bool is_elem_visible(service_ptr_t<ui_element_instance> elem) {return true;}
237 virtual t_size host_notify(ui_element_instance* source, const GUID& what, t_size param1, const void* param2, t_size param2size) { (void)source; (void)what; (void)param1; (void)param2; (void)param2size; return 0; }
238 ui_element_instance_callback_ptr ui_element_instance_callback_get_ptr() {
239 if (m_callback.is_empty()) m_callback = new service_impl_t<t_callback>(this);
240 return m_callback;
241 }
242 void ui_element_instance_callback_release() {
243 if (m_callback.is_valid()) {
244 m_callback->orphan();
245 m_callback.release();
246 }
247 }
248 protected:
249 ~ui_element_instance_callback_receiver() {
250 ui_element_instance_callback_release();
251 }
252 ui_element_instance_callback_receiver() {}
253
254 private:
255 typedef ui_element_instance_callback_receiver t_self;
256 typedef ui_element_instance_callback_impl<t_self> t_callback;
257 service_ptr_t<t_callback> m_callback;
258 };
259
260 //! Instance of a UI element.
261 class NOVTABLE ui_element_instance : public service_base {
262 public:
263 //! Returns ui_element_instance's window handle.\n
264 //! UI Element's window must be created when the ui_element_instance object is created. The window may or may not be destroyed by caller before the ui_element_instance itself is destroyed. If caller doesn't destroy the window before ui_element_instance destruction, ui_element_instance destructor should do it.
265 virtual fb2k::hwnd_t get_wnd() = 0;
266
267 //! Alters element's current configuration. Specified ui_element_config's GUID must be the same as this element's GUID.
268 virtual void set_configuration(ui_element_config::ptr data) = 0;
269 //! Retrieves element's current configuration. Returned object's GUID must be set to your element's GUID so your element can be re-instantiated with stored settings.
270 virtual ui_element_config::ptr get_configuration() = 0;
271
272 //! Returns GUID of the element. The return value must be the same as your ui_element::get_guid().
273 virtual GUID get_guid() = 0;
274 //! Returns subclass GUID of the element. The return value must be the same as your ui_element::get_subclass().
275 virtual GUID get_subclass() = 0;
276
277 //! Returns element's focus priority.
278 virtual double get_focus_priority() {return 0;}
279 //! Elements that host other elements should pass the call to the child with the highest priority. Override for container elements.
280 virtual void set_default_focus() {set_default_focus_fallback();}
281
282 //! Overridden by containers only.
283 virtual bool get_focus_priority_subclass(double & p_out,const GUID & p_subclass) {
284 if (p_subclass == get_subclass()) {p_out = get_focus_priority(); return true;}
285 else {return false;}
286 }
287 //! Overridden by containers only.
288 virtual bool set_default_focus_subclass(const GUID & p_subclass) {
289 if (p_subclass == get_subclass()) {set_default_focus(); return true;}
290 else {return false;}
291 }
292
293 //! Retrieves element's minimum/maximum window size. Default implementation will fall back to WM_GETMINMAXINFO.
294 virtual ui_element_min_max_info get_min_max_info();
295
296 //! Used by host to notify the element about various events. See ui_element_notify_* GUIDs for possible p_what parameter; meaning of other parameters depends on p_what value. Container classes should dispatch all notifications to their children.
297 virtual void notify(const GUID& p_what, t_size p_param1, const void* p_param2, t_size p_param2size) { (void)p_what; (void)p_param1; (void)p_param2; (void)p_param2size; }
298
299 #ifdef _WIN32
300 //! @param p_point Context menu point in screen coordinates. Always within out window's rect.
301 //! @return True to request edit_mode_context_menu_build() call to add our own items to the menu, false if we can't supply a context menu for this point.
302 virtual bool edit_mode_context_menu_test(const POINT& p_point, bool p_fromkeyboard) { (void)p_point; (void)p_fromkeyboard; return false; }
303 virtual void edit_mode_context_menu_build(const POINT& p_point, bool p_fromkeyboard, HMENU p_menu, unsigned p_id_base) { (void)p_point; (void)p_fromkeyboard; (void)p_menu; (void)p_id_base; }
304 virtual void edit_mode_context_menu_command(const POINT& p_point, bool p_fromkeyboard, unsigned p_id, unsigned p_id_base) { (void)p_point; (void)p_fromkeyboard; (void)p_id; (void)p_id_base; }
305 //! @param p_point Receives the point to spawn context menu over when user has pressed the context menu key; in screen coordinates.
306 virtual bool edit_mode_context_menu_get_focus_point(POINT& p_point) { (void)p_point; return false; }
307
308 virtual bool edit_mode_context_menu_get_description(unsigned p_id, unsigned p_id_base, pfc::string_base& p_out) { (void)p_id; (void)p_id_base; (void)p_out; return false; }
309 #endif // _WIN32
310
311 //! Helper.
312 void set_default_focus_fallback() {
313 #ifdef _WIN32
314 const HWND thisWnd = this->get_wnd();
315 if (thisWnd != NULL) ::SetFocus(thisWnd);
316 #endif
317 }
318
319
320 FB2K_MAKE_SERVICE_INTERFACE(ui_element_instance,service_base);
321 };
322
323 typedef service_ptr_t<ui_element_instance> ui_element_instance_ptr;
324
325
326 //! Interface to enumerate and possibly alter children of a container element. Obtained from ui_element::enumerate_children().
327 class NOVTABLE ui_element_children_enumerator : public service_base {
328 public:
329 //! Retrieves the container's children count.
330 virtual t_size get_count() = 0;
331 //! Retrieves the configuration of the child at specified index, 0 <= index < get_count().
332 virtual ui_element_config::ptr get_item(t_size p_index) = 0;
333
334 //! Returns whether children count can be altered. For certain containers, children count is fixed and this method returns false.
335 virtual bool can_set_count() = 0;
336 //! Alters container's children count (behavior is undefined when can_set_count() returns false). Newly allocated children get default empty element configuration.
337 virtual void set_count(t_size count) = 0;
338 //! Alters the selected item.
339 virtual void set_item(t_size p_index,ui_element_config::ptr cfg) = 0;
340 //! Creates a new ui_element_config for this container, with our changes (set_count(), set_item()) applied.
341 virtual ui_element_config::ptr commit() = 0;
342
343 FB2K_MAKE_SERVICE_INTERFACE(ui_element_children_enumerator,service_base);
344 };
345
346
347 typedef service_ptr_t<ui_element_children_enumerator> ui_element_children_enumerator_ptr;
348
349
350 //! Entrypoint interface for each UI element implementation.
351 class NOVTABLE ui_element : public service_base {
352 public:
353 //! Retrieves GUID of the element.
354 virtual GUID get_guid() = 0;
355
356 //! Retrieves subclass GUID of the element. Typically one of ui_element_subclass_* values, but you can create your own custom subclasses. Subclass GUIDs are used for various purposes such as focusing an UI element that provides specific functionality.
357 virtual GUID get_subclass() = 0;
358
359 //! Retrieves a simple human-readable name of the element.
360 virtual void get_name(pfc::string_base & p_out) = 0;
361
362 //! Instantiates the element using specified settings.
363 virtual ui_element_instance_ptr instantiate(fb2k::hwnd_t p_parent,ui_element_config::ptr cfg,ui_element_instance_callback_ptr p_callback) = 0;
364
365 //! Retrieves default configuration of the element.
366 virtual ui_element_config::ptr get_default_configuration() = 0;
367
368 //! Implemented by container elements only. Returns NULL for non-container elements. \n
369 //! Allows caller to parse and edit child element structure of container elements.
370 virtual ui_element_children_enumerator_ptr enumerate_children(ui_element_config::ptr cfg) = 0;
371
372
373 //! In certain cases, an UI element can import settings of another UI element (eg. vertical<=>horizontal splitter, tabs<=>splitters) when user directly replaces one of such elements with another. Overriding this function allows special handling of such cases. \n
374 //! Implementation hint: when implementing a multi-child container, you probably want to takeover child elements replacing another container element; use enumerate_children() on the element the configuration belongs to to grab those.
375 //! @returns A new ui_element_config on success, a null pointer when the input data could not be parsed / is in an unknown format.
376 virtual ui_element_config::ptr import(ui_element_config::ptr cfg) {return NULL;}
377
378 //! Override this to return false when your element is for internal use only and should not be user-addable.
379 virtual bool is_user_addable() {return true;}
380
381 //! Returns an icon to show in available UI element lists, etc. Returns NULL when there is no icon to display.
382 virtual t_ui_icon get_icon() {return NULL;}
383
384 //! Retrieves a human-readable description of the element.
385 virtual bool get_description(pfc::string_base& p_out) { (void)p_out; return false; }
386
387 //! Retrieves a human-readable description of the element's function to use for grouping in the element list. The default implementation relies on get_subclass() return value.
388 virtual bool get_element_group(pfc::string_base & p_out);
389
390 static bool g_find(service_ptr_t<ui_element> & out, const GUID & id);
391 static bool g_get_name(pfc::string_base & p_out,const GUID & p_guid);
392
393 FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT(ui_element);
394 };
395
396 //! Extended interface for a UI element implementation.
397 class NOVTABLE ui_element_v2 : public ui_element {
398 public:
399 enum {
400 //! Indicates that bump() method is supported.
401 KFlagSupportsBump = 1 << 0,
402 //! Tells UI backend to auto-generate a menu command activating your element - bumping an existing instance if possible, spawning a popup otherwise.
403 //! Currently menu commands are generated for ui_element_subclass_playback_visualisation, ui_element_subclass_media_library_viewers and ui_element_subclass_utility subclasses, in relevant menus.
404 KFlagHavePopupCommand = 1 << 1,
405 //! Tells backend that your element supports fullscreen mode (typically set only for visualisations).
406 KFlagHaveFullscreen = 1 << 2,
407
408 KFlagPopupCommandHidden = 1 << 3,
409
410 KFlagsVisualisation = KFlagHavePopupCommand | KFlagHaveFullscreen,
411 };
412 virtual t_uint32 get_flags() = 0;
413 //! Called only when get_flags() return value has KFlagSupportsBump bit set.
414 //! Returns true when an existing instance of this element has been "bumped" - brought to user's attention in some way, false when there's no instance to bump or none of existing instances could be bumped for whatever reason.
415 virtual bool bump() = 0;
416
417 //! Override to use another GUID for our menu command. Relevant only when KFlagHavePopupCommand is set.
418 virtual GUID get_menu_command_id() {return get_guid();}
419
420 //! Override to use another description for our menu command. Relevant only when KFlagHavePopupCommand is set.
421 virtual bool get_menu_command_description(pfc::string_base & out) {
422 pfc::string8 name; get_name(name);
423 out = PFC_string_formatter() << "Activates " << name << " window.";
424 return true;
425 }
426
427 //! Override to use another name for our menu command. Relevant only when KFlagHavePopupCommand is set.
428 virtual void get_menu_command_name(pfc::string_base & out) {get_name(out);}
429
430 //! Relevant only when KFlagHavePopupCommand is set.
431 //! @param defSize Default window size @ 96DPI. If screen DPI is different, it will be rescaled appropriately.
432 //! @param title Window title to use.
433 //! @returns True when implemented, false when not - caller will automatically determine default size and window title then.
434 virtual bool get_popup_specs(ui_size& defSize, pfc::string_base& title) { (void)defSize; (void)title; return false; }
435
436
437 FB2K_MAKE_SERVICE_INTERFACE(ui_element_v2, ui_element)
438 };
439
440 class NOVTABLE ui_element_popup_host_callback : public service_base {
441 public:
442 virtual void on_resize(t_uint32 width, t_uint32 height) = 0;
443 virtual void on_close() = 0;
444 virtual void on_destroy() = 0;
445
446 FB2K_MAKE_SERVICE_INTERFACE(ui_element_popup_host_callback,service_base);
447 };
448
449 class NOVTABLE ui_element_popup_host : public service_base {
450 FB2K_MAKE_SERVICE_INTERFACE(ui_element_popup_host,service_base);
451 public:
452 virtual ui_element_instance::ptr get_root_elem() = 0;
453 virtual fb2k::hwnd_t get_wnd() = 0;
454 virtual ui_element_config::ptr get_config() = 0;
455 virtual void set_config(ui_element_config::ptr cfg) = 0;
456 //! Sets edit mode on/off. Default: off.
457 virtual void set_edit_mode(bool state) = 0;
458 };
459
460 class NOVTABLE ui_element_popup_host_v2 : public ui_element_popup_host {
461 FB2K_MAKE_SERVICE_INTERFACE(ui_element_popup_host_v2, ui_element_popup_host);
462 public:
463 virtual void set_window_title(const char * title) = 0;
464 virtual void allow_element_specified_title(bool allow) = 0;
465 };
466
467 //! Shared implementation of common UI Element methods. Use ui_element_common_methods::get() to obtain an instance.
468 class NOVTABLE ui_element_common_methods : public service_base {
469 FB2K_MAKE_SERVICE_COREAPI(ui_element_common_methods);
470 public:
471 virtual void copy(ui_element_config::ptr cfg) = 0;
472 virtual void cut(ui_element_instance_ptr & p_instance,fb2k::hwnd_t p_parent,ui_element_instance_callback_ptr p_callback) = 0;
473 virtual bool paste(ui_element_instance_ptr & p_instance,fb2k::hwnd_t p_parent,ui_element_instance_callback_ptr p_callback) = 0;
474 virtual bool is_paste_available() = 0;
475 virtual bool paste(ui_element_config::ptr & out) = 0;
476
477 #ifdef _WIN32
478 virtual bool parse_dataobject_check(pfc::com_ptr_t<IDataObject> in, DWORD & dropEffect) = 0;
479 virtual bool parse_dataobject(pfc::com_ptr_t<IDataObject> in,ui_element_config::ptr & out, DWORD & dropEffect) = 0;
480
481 virtual pfc::com_ptr_t<IDataObject> create_dataobject(ui_element_config::ptr in) = 0;
482 #endif
483
484 virtual fb2k::hwnd_t spawn_scratchbox(fb2k::hwnd_t parent,ui_element_config::ptr cfg) = 0;
485
486 virtual ui_element_popup_host::ptr spawn_host(fb2k::hwnd_t parent, ui_element_config::ptr cfg, ui_element_popup_host_callback::ptr callback, ui_element::ptr elem = NULL
487 #ifdef _WIN32
488 ,DWORD style = WS_POPUPWINDOW|WS_CAPTION|WS_THICKFRAME, DWORD styleEx = WS_EX_CONTROLPARENT
489 #endif
490 ) = 0;
491
492 void copy(ui_element_instance_ptr p_instance) {copy(p_instance->get_configuration());}
493
494
495 };
496
497 //! Shared implementation of common UI Element methods. Use ui_element_common_methods_v2::get() to obtain an instance.
498 class NOVTABLE ui_element_common_methods_v2 : public ui_element_common_methods {
499 FB2K_MAKE_SERVICE_COREAPI_EXTENSION(ui_element_common_methods_v2, ui_element_common_methods);
500 public:
501 virtual void spawn_host_simple(fb2k::hwnd_t parent, ui_element::ptr elem, bool fullScreenMode) = 0;
502
503 void spawn_host_simple(fb2k::hwnd_t parent, const GUID & elem, bool fullScreenMode) {
504 spawn_host_simple(parent, service_by_guid<ui_element>(elem), fullScreenMode);
505 }
506
507 virtual void toggle_fullscreen(ui_element::ptr elem, fb2k::hwnd_t parent) = 0;
508
509 void toggle_fullscreen(const GUID & elem, fb2k::hwnd_t parent) {
510 toggle_fullscreen(service_by_guid<ui_element>(elem), parent);
511 }
512 };
513
514 //! \since 1.4
515 //! Callback class for "Replace UI Element" dialog.
516 class NOVTABLE ui_element_replace_dialog_notify : public service_base {
517 FB2K_MAKE_SERVICE_INTERFACE(ui_element_replace_dialog_notify, service_base);
518 public:
519 virtual void on_cancelled() = 0;
520 virtual void on_ok( const GUID & guid ) = 0;
521
522 //! Helper; reply is called with new elem GUID on OK and with a null GUID on cancel.
523 static ui_element_replace_dialog_notify::ptr create( std::function<void (GUID)> reply );
524 };
525
526 //! \since 1.4
527 class NOVTABLE ui_element_common_methods_v3 : public ui_element_common_methods_v2 {
528 public:
529 FB2K_MAKE_SERVICE_COREAPI_EXTENSION(ui_element_common_methods_v3, ui_element_common_methods_v2);
530 public:
531 //! Creates a "Replace UI Element" or "Add New UI Element" dialog.
532 //! @param wndElem Parent *element* window handle, the dialog will be a child of its parent popup window but centered on top of the specified window.
533 //! @param elemReplacing GUID of element being replaced; specify null to show "Add UI Element" dialog.
534 //! @param notify Callback object receiving OK/Cancel notifications.
535 //! @returns Handle to the newly created dialog. You can just destroy this window if you need to abort the dialog programatically.
536 virtual fb2k::hwnd_t replace_element_dialog_start(fb2k::hwnd_t wndElem, const GUID & elemReplacing, ui_element_replace_dialog_notify::ptr notify) = 0;
537
538 //! Highlights the element, creating an overlay window above it. Caller is responsible for destroying the overlay.
539 virtual fb2k::hwnd_t highlight_element( fb2k::hwnd_t wndElem ) = 0;
540 };
541
542 //! Dispatched through ui_element_instance::notify() when host changes color settings. Other parameters are not used and should be set to zero.
543 constexpr GUID ui_element_notify_colors_changed = { 0xeedda994, 0xe3d2, 0x441a, { 0xbe, 0x47, 0xa1, 0x63, 0x5b, 0x71, 0xab, 0x60 } };
544 constexpr GUID ui_element_notify_font_changed = { 0x7a6964a8, 0xc797, 0x4737, { 0x90, 0x55, 0x7d, 0x84, 0xe7, 0x3d, 0x63, 0x6e } };
545 constexpr GUID ui_element_notify_edit_mode_changed = { 0xf72f00af, 0xec76, 0x4251, { 0xb2, 0x67, 0x89, 0x4c, 0x52, 0x5f, 0x18, 0xc6 } };
546
547 //! Sent when a portion of the GUI is shown/hidden. First parameter is a bool flag indicating whether your UI Element is now visible.
548 constexpr GUID ui_element_notify_visibility_changed = { 0x313c22b9, 0x287a, 0x4804, { 0x8e, 0x6c, 0xff, 0xef, 0x4, 0x10, 0xcd, 0xea } };
549
550 //! Sent to retrieve areas occupied by elements to show overlay labels. Param1 is ignored, param2 is a pointer to ui_element_notify_get_element_labels_callback, param2size is ignored.
551 constexpr GUID ui_element_notify_get_element_labels = { 0x4850a2cb, 0x6cfc, 0x4d74, { 0x9a, 0x6d, 0xc, 0x7b, 0x29, 0x16, 0x5e, 0x69 } };
552
553
554 //! Set to ui_element_instance_callback_v3 to set our element's label. Param1 is ignored, param2 is a pointer to a UTF-8 string containing the new label. Return value is 1 if the label is user-visible, 0 if the host does not support displaying overridden labels.
555 constexpr GUID ui_element_host_notify_set_elem_label = { 0x24598cb7, 0x9c5c, 0x488e, { 0xba, 0xff, 0xd, 0x2f, 0x11, 0x93, 0xe4, 0xf2 } };
556 constexpr GUID ui_element_host_notify_get_dialog_texture = { 0xbb98eb99, 0x7b07, 0x42f3, { 0x8c, 0xd1, 0x12, 0xa2, 0xc2, 0x23, 0xb5, 0xbc } };
557 constexpr GUID ui_element_host_notify_is_border_needed = { 0x2974f554, 0x2f31, 0x49c5, { 0xab, 0x4, 0x76, 0x4a, 0xf7, 0x94, 0x7c, 0x4f } };
558
559
560
561 class ui_element_notify_get_element_labels_callback {
562 public:
563 virtual void set_area_label(const ui_rect & rc, const char * name) = 0;
564 virtual void set_visible_element(ui_element_instance::ptr item) = 0;
565 protected:
566 ui_element_notify_get_element_labels_callback() {}
567 ~ui_element_notify_get_element_labels_callback() {}
568
569 PFC_CLASS_NOT_COPYABLE_EX(ui_element_notify_get_element_labels_callback);
570 };
571
572
573 constexpr GUID ui_element_subclass_playlist_renderers = { 0x3c4c68a0, 0xfc5, 0x400a, { 0xa3, 0x4a, 0x2e, 0x3a, 0xae, 0x6e, 0x90, 0x76 } };
574 constexpr GUID ui_element_subclass_media_library_viewers = { 0x58455355, 0x289d, 0x459c, { 0x8f, 0x8a, 0xe1, 0x49, 0x6, 0xfc, 0x14, 0x56 } };
575 constexpr GUID ui_element_subclass_containers = { 0x72dc5954, 0x1f26, 0x41be, { 0xae, 0xf2, 0x92, 0x9d, 0x25, 0xb5, 0x8d, 0xcf } };
576 constexpr GUID ui_element_subclass_selection_information = { 0x68084e43, 0x7359, 0x46a5, { 0xb6, 0x84, 0x3c, 0xd7, 0x57, 0xf6, 0xde, 0xfd } };
577 constexpr GUID ui_element_subclass_playback_visualisation = { 0x1f3c62f2, 0x8bb5, 0x4700, { 0x9e, 0x82, 0x8c, 0x48, 0x22, 0xf0, 0x18, 0x35 } };
578 constexpr GUID ui_element_subclass_playback_information = { 0x84859f2d, 0xbb9c, 0x4e70, { 0x9d, 0x4, 0x14, 0x71, 0xb5, 0x63, 0x1f, 0x7f } };
579 constexpr GUID ui_element_subclass_utility = { 0xffa4f4fc, 0xc169, 0x4766, { 0x9c, 0x94, 0xfa, 0xef, 0xae, 0xb2, 0x7e, 0xf } };
580 constexpr GUID ui_element_subclass_dsp = { 0xa6a93251, 0xf0f8, 0x4bed,{ 0xb9, 0x5a, 0xf9, 0xe, 0x7e, 0x4f, 0xf2, 0xd0 } };
581
582
583 bool ui_element_subclass_description(const GUID & id, pfc::string_base & out);
584
585
586 #define ReplaceUIElementCommand "Replace UI Element..."
587 #define ReplaceUIElementDescription "Replaces this UI Element with another one."
588
589 #define CopyUIElementCommand "Copy UI Element"
590 #define CopyUIElementDescription "Copies this UI Element to Windows Clipboard."
591
592 #define PasteUIElementCommand "Paste UI Element"
593 #define PasteUIElementDescription "Replaces this UI Element with Windows Clipboard content."
594
595 #define CutUIElementCommand "Cut UI Element"
596 #define CutUIElementDescription "Copies this UI Element to Windows Clipboard and replaces it with an empty UI Element."
597
598 #define AddNewUIElementCommand "Add New UI Element..."
599 #define AddNewUIElementDescription "Replaces the selected empty space with a new UI Element."
600
601 //! \since 2.0
602 class NOVTABLE ui_config_callback {
603 public:
604 //! Called when user changes configuration of fonts.
605 virtual void ui_fonts_changed() {}
606 //! Called when user changes configuration of colors (also as a result of toggling dark mode). \n
607 //! Note that for the duration of these callbacks, both old handles previously returned by query_font() as well as new ones are valid; old font objects are released when the callback cycle is complete.
608 virtual void ui_colors_changed() {}
609 };
610
611 //! \since 2.0
612 class NOVTABLE ui_config_manager : public service_base {
613 FB2K_MAKE_SERVICE_COREAPI(ui_config_manager);
614 public:
615 //! Registers a callback to receive notifications about colors/fonts change. \n
616 //! Main thread only!
617 virtual void add_callback(ui_config_callback*) = 0;
618 //! Unregisters a callback to receive notifications about colors/fonts change. \n
619 //! Main thread only!
620 virtual void remove_callback(ui_config_callback*) = 0;
621
622 //! Queries actual color to be used for the specified ui_color_* element. \n
623 //! Main thread only! \n
624 //! @returns True if color is user-overridden, false if system-default color should be used.
625 virtual bool query_color(const GUID& p_what, t_ui_color& p_out) = 0;
626 //! Queries font to be used for the specified ui_font_* element. \n
627 //! Main thread only! \n
628 //! The returned font handle is valid until the next font change callback cycle *completes*, that is, during a font change callback, both old and new handle are momentarily valid.
629 virtual t_ui_font query_font(const GUID& p_what) = 0;
630
631 //! Helper using query_color(); returns true if dark mode is in effect, false otherwise.
632 bool is_dark_mode();
633
634 #ifdef _WIN32
635 t_ui_color getSysColor(int sysColorIndex);
636 #endif
637
638 //! Special method that's safe to call without checking if ui_config_manager exists, that is, it works on foobar2000 < 2.0. \n
639 //! Returns false if ui_conifg_manager doesn't exist and therefore dark mode isn't supported by this foobar2000 revision. \n
640 //! Main thread only!
641 static bool g_is_dark_mode();
642 };
643
644 //! \since 2.0
645 class NOVTABLE ui_config_manager_v2 : public ui_config_manager {
646 FB2K_MAKE_SERVICE_COREAPI_EXTENSION(ui_config_manager_v2, ui_config_manager)
647 public:
648 //! Tells ui_config_manager about system theme having changed. \n
649 //! Intended for keeping track of live dark mode toggle when foo_ui_std is not the active UI. Do not use.
650 virtual void notify_system_theme_changed() = 0;
651 };
652
653 //! \since 2.0
654 //! Does nothing (fails to register quietly) if used in fb2k prior to 2.0 \n
655 //! Use in main thread only!
656 class ui_config_callback_impl : public ui_config_callback {
657 public:
658 ui_config_callback_impl();
659 ~ui_config_callback_impl();
660 ui_config_callback_impl(const ui_config_callback_impl&) = delete;
661 void operator=(const ui_config_callback_impl&) = delete;
662 };