Mercurial > foo_out_sdl
comparison foosdk/sdk/foobar2000/SDK/contextmenu.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 #include "metadb_handle.h" | |
| 3 #include <functional> | |
| 4 | |
| 5 //! Reserved for future use. | |
| 6 typedef void * t_glyph; | |
| 7 | |
| 8 | |
| 9 class NOVTABLE contextmenu_item_node { | |
| 10 public: | |
| 11 enum t_flags { | |
| 12 FLAG_CHECKED = 1, | |
| 13 FLAG_DISABLED = 2, | |
| 14 FLAG_GRAYED = 4, | |
| 15 FLAG_DISABLED_GRAYED = FLAG_DISABLED|FLAG_GRAYED, | |
| 16 FLAG_RADIOCHECKED = 8, //new in 0.9.5.2 - overrides FLAG_CHECKED, set together with FLAG_CHECKED for backwards compatibility. | |
| 17 }; | |
| 18 | |
| 19 enum t_type { | |
| 20 type_group, | |
| 21 type_command, | |
| 22 type_separator, | |
| 23 | |
| 24 //for compatibility | |
| 25 TYPE_POPUP = type_group,TYPE_COMMAND = type_command,TYPE_SEPARATOR = type_separator, | |
| 26 }; | |
| 27 | |
| 28 virtual bool get_display_data(pfc::string_base & p_out,unsigned & p_displayflags,metadb_handle_list_cref p_data,const GUID & p_caller) = 0; | |
| 29 virtual t_type get_type() = 0; | |
| 30 virtual void execute(metadb_handle_list_cref p_data,const GUID & p_caller) = 0; | |
| 31 virtual t_glyph get_glyph(metadb_handle_list_cref p_data, const GUID& p_caller) { (void)p_data; (void)p_caller; return 0; }//RESERVED | |
| 32 virtual t_size get_children_count() = 0; | |
| 33 virtual contextmenu_item_node * get_child(t_size p_index) = 0; | |
| 34 virtual bool get_description(pfc::string_base & p_out) = 0; | |
| 35 virtual GUID get_guid() = 0; | |
| 36 virtual bool is_mappable_shortcut() = 0; | |
| 37 | |
| 38 protected: | |
| 39 contextmenu_item_node() {} | |
| 40 ~contextmenu_item_node() {} | |
| 41 }; | |
| 42 | |
| 43 class NOVTABLE contextmenu_item_node_root : public contextmenu_item_node | |
| 44 { | |
| 45 public: | |
| 46 virtual ~contextmenu_item_node_root() {} | |
| 47 }; | |
| 48 | |
| 49 class NOVTABLE contextmenu_item_node_leaf : public contextmenu_item_node | |
| 50 { | |
| 51 public: | |
| 52 t_type get_type() {return TYPE_COMMAND;} | |
| 53 t_size get_children_count() {return 0;} | |
| 54 contextmenu_item_node * get_child(t_size) {return NULL;} | |
| 55 }; | |
| 56 | |
| 57 class NOVTABLE contextmenu_item_node_root_leaf : public contextmenu_item_node_root | |
| 58 { | |
| 59 public: | |
| 60 t_type get_type() {return TYPE_COMMAND;} | |
| 61 t_size get_children_count() {return 0;} | |
| 62 contextmenu_item_node * get_child(t_size) {return NULL;} | |
| 63 }; | |
| 64 | |
| 65 class NOVTABLE contextmenu_item_node_popup : public contextmenu_item_node | |
| 66 { | |
| 67 public: | |
| 68 t_type get_type() override {return TYPE_POPUP;} | |
| 69 void execute(metadb_handle_list_cref data, const GUID& caller) override { (void)data; (void)caller; } | |
| 70 bool get_description(pfc::string_base& p_out) override { (void)p_out; return false; } | |
| 71 }; | |
| 72 | |
| 73 class NOVTABLE contextmenu_item_node_root_popup : public contextmenu_item_node_root | |
| 74 { | |
| 75 public: | |
| 76 t_type get_type() override {return TYPE_POPUP;} | |
| 77 void execute(metadb_handle_list_cref data, const GUID& caller) override { (void)data; (void)caller; } | |
| 78 bool get_description(pfc::string_base& p_out) override { (void)p_out; return false; } | |
| 79 }; | |
| 80 | |
| 81 class contextmenu_item_node_separator : public contextmenu_item_node | |
| 82 { | |
| 83 public: | |
| 84 t_type get_type() override {return TYPE_SEPARATOR;} | |
| 85 void execute(metadb_handle_list_cref data, const GUID& caller) override { (void)data; (void)caller; } | |
| 86 bool get_description(pfc::string_base& p_out) override { (void)p_out; return false; } | |
| 87 t_size get_children_count() override {return 0;} | |
| 88 bool get_display_data(pfc::string_base & p_out,unsigned & p_displayflags,metadb_handle_list_cref p_data,const GUID & p_caller) override | |
| 89 { | |
| 90 (void)p_data; (void)p_caller; | |
| 91 p_displayflags = 0; | |
| 92 p_out = "---"; | |
| 93 return true; | |
| 94 } | |
| 95 contextmenu_item_node * get_child(t_size) override {return NULL;} | |
| 96 GUID get_guid() override {return pfc::guid_null;} | |
| 97 bool is_mappable_shortcut() override {return false;} | |
| 98 }; | |
| 99 | |
| 100 /*! | |
| 101 Service class for declaring context menu commands.\n | |
| 102 See contextmenu_item_simple for implementation helper without dynamic menu generation features.\n | |
| 103 All methods are valid from main app thread only. | |
| 104 */ | |
| 105 class NOVTABLE contextmenu_item : public service_base { | |
| 106 public: | |
| 107 enum t_enabled_state { | |
| 108 FORCE_OFF, | |
| 109 DEFAULT_OFF, | |
| 110 DEFAULT_ON, | |
| 111 }; | |
| 112 | |
| 113 //! Retrieves number of menu items provided by this contextmenu_item implementation. | |
| 114 virtual unsigned get_num_items() = 0; | |
| 115 //! Instantiates a context menu item (including sub-node tree for items that contain dynamically-generated sub-items). | |
| 116 virtual contextmenu_item_node_root * instantiate_item(unsigned p_index,metadb_handle_list_cref p_data,const GUID & p_caller) = 0; | |
| 117 //! Retrieves GUID of the context menu item. | |
| 118 virtual GUID get_item_guid(unsigned p_index) = 0; | |
| 119 //! Retrieves human-readable name of the context menu item. | |
| 120 virtual void get_item_name(unsigned p_index,pfc::string_base & p_out) = 0; | |
| 121 //! Obsolete since v1.0, don't use or override in new components. | |
| 122 virtual void get_item_default_path(unsigned p_index, pfc::string_base& p_out) { (void)p_index; p_out = ""; } | |
| 123 //! Retrieves item's description to show in the status bar. Set p_out to the string to be displayed and return true if you provide a description, return false otherwise. | |
| 124 virtual bool get_item_description(unsigned p_index,pfc::string_base & p_out) = 0; | |
| 125 //! Controls default state of context menu preferences for this item: \n | |
| 126 //! Return DEFAULT_ON to show this item in the context menu by default - useful for most cases. \n | |
| 127 //! Return DEFAULT_OFF to hide this item in the context menu by default - useful for rarely used utility commands. \n | |
| 128 //! Return FORCE_OFF to hide this item by default and prevent the user from making it visible (very rarely used). \n | |
| 129 //! foobar2000 v1.6 and newer: FORCE_OFF items are meant for being shown only in the keyboard shortcut list, not anywhere else. \n | |
| 130 //! Values returned by this method should be constant for this context menu item and not change later. Do not use this to conditionally hide the item - return false from get_display_data() instead. | |
| 131 virtual t_enabled_state get_enabled_state(unsigned p_index) = 0; | |
| 132 //! Executes the menu item command without going thru the instantiate_item path. For items with dynamically-generated sub-items, p_node is identifies of the sub-item command to execute. | |
| 133 virtual void item_execute_simple(unsigned p_index,const GUID & p_node,metadb_handle_list_cref p_data,const GUID & p_caller) = 0; | |
| 134 | |
| 135 bool item_get_display_data_root(pfc::string_base & p_out,unsigned & displayflags,unsigned p_index,metadb_handle_list_cref p_data,const GUID & p_caller); | |
| 136 bool item_get_display_data(pfc::string_base & p_out,unsigned & displayflags,unsigned p_index,const GUID & p_node,metadb_handle_list_cref p_data,const GUID & p_caller); | |
| 137 | |
| 138 GUID get_parent_fallback(); | |
| 139 GUID get_parent_(); | |
| 140 | |
| 141 //! Deprecated - use caller_active_playlist_selection instead. | |
| 142 static const GUID caller_playlist; | |
| 143 | |
| 144 static const GUID caller_active_playlist_selection, caller_active_playlist, caller_playlist_manager, caller_now_playing, caller_keyboard_shortcut_list, caller_media_library_viewer; | |
| 145 static const GUID caller_undefined; | |
| 146 | |
| 147 FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT(contextmenu_item); | |
| 148 }; | |
| 149 | |
| 150 //! \since 1.0 | |
| 151 class NOVTABLE contextmenu_item_v2 : public contextmenu_item { | |
| 152 FB2K_MAKE_SERVICE_INTERFACE(contextmenu_item_v2, contextmenu_item) | |
| 153 public: | |
| 154 virtual double get_sort_priority() {return 0;} | |
| 155 virtual GUID get_parent() {return get_parent_fallback();} | |
| 156 }; | |
| 157 | |
| 158 //! contextmenu_item implementation helper for implementing non-dynamically-generated context menu items; derive from this instead of from contextmenu_item directly if your menu items are static. | |
| 159 class NOVTABLE contextmenu_item_simple : public contextmenu_item_v2 { | |
| 160 private: | |
| 161 public: | |
| 162 //! Same as contextmenu_item_node::t_flags. | |
| 163 enum t_flags | |
| 164 { | |
| 165 FLAG_CHECKED = 1, | |
| 166 FLAG_DISABLED = 2, | |
| 167 FLAG_GRAYED = 4, | |
| 168 FLAG_DISABLED_GRAYED = FLAG_DISABLED|FLAG_GRAYED, | |
| 169 FLAG_RADIOCHECKED = 8, //new in 0.9.5.2 - overrides FLAG_CHECKED, set together with FLAG_CHECKED for backwards compatibility. | |
| 170 }; | |
| 171 | |
| 172 | |
| 173 // Functions to be overridden by implementers (some are not mandatory). | |
| 174 virtual t_enabled_state get_enabled_state(unsigned p_index) { (void)p_index; return contextmenu_item::DEFAULT_ON; } | |
| 175 virtual unsigned get_num_items() = 0; | |
| 176 virtual void get_item_name(unsigned p_index,pfc::string_base & p_out) = 0; | |
| 177 virtual void context_command(unsigned p_index,metadb_handle_list_cref p_data,const GUID& p_caller) = 0; | |
| 178 virtual bool context_get_display(unsigned p_index,metadb_handle_list_cref p_data,pfc::string_base & p_out,unsigned & p_displayflags,const GUID & p_caller) { | |
| 179 (void)p_caller; (void)p_data; (void)p_displayflags; | |
| 180 PFC_ASSERT(p_index>=0 && p_index<get_num_items()); | |
| 181 get_item_name(p_index,p_out); | |
| 182 return true; | |
| 183 } | |
| 184 virtual GUID get_item_guid(unsigned p_index) = 0; | |
| 185 virtual bool get_item_description(unsigned p_index,pfc::string_base & p_out) = 0; | |
| 186 | |
| 187 | |
| 188 private: | |
| 189 class contextmenu_item_node_impl : public contextmenu_item_node_root_leaf { | |
| 190 public: | |
| 191 contextmenu_item_node_impl(contextmenu_item_simple * p_owner,unsigned p_index) : m_owner(p_owner), m_index(p_index) {} | |
| 192 bool get_display_data(pfc::string_base & p_out,unsigned & p_displayflags,metadb_handle_list_cref p_data,const GUID & p_caller) {return m_owner->get_display_data(m_index,p_data,p_out,p_displayflags,p_caller);} | |
| 193 void execute(metadb_handle_list_cref p_data,const GUID & p_caller) {m_owner->context_command(m_index,p_data,p_caller);} | |
| 194 bool get_description(pfc::string_base & p_out) {return m_owner->get_item_description(m_index,p_out);} | |
| 195 GUID get_guid() {return pfc::guid_null;} | |
| 196 bool is_mappable_shortcut() {return m_owner->item_is_mappable_shortcut(m_index);} | |
| 197 private: | |
| 198 service_ptr_t<contextmenu_item_simple> m_owner; | |
| 199 unsigned m_index; | |
| 200 }; | |
| 201 | |
| 202 contextmenu_item_node_root * instantiate_item(unsigned p_index,metadb_handle_list_cref p_data,const GUID & p_caller) | |
| 203 { | |
| 204 (void)p_data; (void)p_caller; | |
| 205 return new contextmenu_item_node_impl(this,p_index); | |
| 206 } | |
| 207 | |
| 208 | |
| 209 void item_execute_simple(unsigned p_index,const GUID & p_node,metadb_handle_list_cref p_data,const GUID & p_caller) | |
| 210 { | |
| 211 if (p_node == pfc::guid_null) | |
| 212 context_command(p_index,p_data,p_caller); | |
| 213 } | |
| 214 | |
| 215 virtual bool item_is_mappable_shortcut(unsigned p_index) | |
| 216 { | |
| 217 (void)p_index; | |
| 218 return true; | |
| 219 } | |
| 220 | |
| 221 | |
| 222 virtual bool get_display_data(unsigned n,metadb_handle_list_cref data,pfc::string_base & p_out,unsigned & displayflags,const GUID & caller) | |
| 223 { | |
| 224 bool rv = false; | |
| 225 assert(n>=0 && n<get_num_items()); | |
| 226 if (data.get_count()>0) | |
| 227 { | |
| 228 rv = context_get_display(n,data,p_out,displayflags,caller); | |
| 229 } | |
| 230 return rv; | |
| 231 } | |
| 232 | |
| 233 }; | |
| 234 | |
| 235 | |
| 236 //! Helper. | |
| 237 template<typename T> | |
| 238 class contextmenu_item_factory_t : public service_factory_single_t<T> {}; | |
| 239 | |
| 240 | |
| 241 //! Helper. | |
| 242 #define DECLARE_CONTEXT_MENU_ITEM(P_CLASSNAME,P_NAME,P_DEFAULTPATH,P_FUNC,P_GUID,P_DESCRIPTION) \ | |
| 243 namespace { \ | |
| 244 class P_CLASSNAME : public contextmenu_item_simple { \ | |
| 245 public: \ | |
| 246 unsigned get_num_items() {return 1;} \ | |
| 247 void get_item_name(unsigned p_index,pfc::string_base & p_out) {p_out = P_NAME;} \ | |
| 248 void get_item_default_path(unsigned p_index,pfc::string_base & p_out) {p_out = P_DEFAULTPATH;} \ | |
| 249 void context_command(unsigned p_index,metadb_handle_list_cref p_data,const GUID& p_caller) {P_FUNC(p_data);} \ | |
| 250 GUID get_item_guid(unsigned p_index) {return P_GUID;} \ | |
| 251 bool get_item_description(unsigned p_index,pfc::string_base & p_out) {if (P_DESCRIPTION[0] == 0) return false;p_out = P_DESCRIPTION; return true;} \ | |
| 252 }; \ | |
| 253 static contextmenu_item_factory_t<P_CLASSNAME> g_##P_CLASSNAME##_factory; \ | |
| 254 } | |
| 255 | |
| 256 | |
| 257 | |
| 258 | |
| 259 //! New in 0.9.5.1. Static methods safe to use in prior versions as it will use slow fallback mode when the service isn't present. \n | |
| 260 //! Functionality provided by menu_item_resolver methods isn't much different from just walking all registered contextmenu_item / mainmenu_commands implementations to find the command we want, but it uses a hint map to locate the service we're looking for without walking all of them which may be significantly faster in certain scenarios. | |
| 261 class menu_item_resolver : public service_base { | |
| 262 FB2K_MAKE_SERVICE_COREAPI(menu_item_resolver) | |
| 263 public: | |
| 264 virtual bool resolve_context_command(const GUID & id, service_ptr_t<class contextmenu_item> & out, t_uint32 & out_index) = 0; | |
| 265 virtual bool resolve_main_command(const GUID & id, service_ptr_t<class mainmenu_commands> & out, t_uint32 & out_index) = 0; | |
| 266 | |
| 267 static bool g_resolve_context_command(const GUID & id, service_ptr_t<class contextmenu_item> & out, t_uint32 & out_index); | |
| 268 static bool g_resolve_main_command(const GUID & id, service_ptr_t<class mainmenu_commands> & out, t_uint32 & out_index); | |
| 269 | |
| 270 | |
| 271 }; | |
| 272 | |
| 273 //! \since 1.0 | |
| 274 class NOVTABLE contextmenu_group : public service_base { | |
| 275 FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT(contextmenu_group); | |
| 276 public: | |
| 277 virtual GUID get_guid() = 0; | |
| 278 virtual GUID get_parent() = 0; | |
| 279 virtual double get_sort_priority() = 0; | |
| 280 }; | |
| 281 | |
| 282 //! \since 1.0 | |
| 283 class NOVTABLE contextmenu_group_popup : public contextmenu_group { | |
| 284 FB2K_MAKE_SERVICE_INTERFACE(contextmenu_group_popup, contextmenu_group) | |
| 285 public: | |
| 286 virtual void get_display_string(pfc::string_base & out) = 0; | |
| 287 void get_name(pfc::string_base & out) {get_display_string(out);} | |
| 288 }; | |
| 289 | |
| 290 class contextmenu_groups { | |
| 291 public: | |
| 292 static const GUID root, utilities, tagging, tagging_pictures, replaygain, fileoperations, playbackstatistics, properties, convert, legacy; | |
| 293 }; | |
| 294 | |
| 295 class contextmenu_group_impl : public contextmenu_group { | |
| 296 public: | |
| 297 contextmenu_group_impl(const GUID & guid, const GUID & parent, double sortPriority = 0) : m_guid(guid), m_parent(parent), m_sortPriority(sortPriority) {} | |
| 298 GUID get_guid() {return m_guid;} | |
| 299 GUID get_parent() {return m_parent;} | |
| 300 double get_sort_priority() {return m_sortPriority;} | |
| 301 private: | |
| 302 const GUID m_guid, m_parent; | |
| 303 const double m_sortPriority; | |
| 304 }; | |
| 305 | |
| 306 class contextmenu_group_popup_impl : public contextmenu_group_popup { | |
| 307 public: | |
| 308 contextmenu_group_popup_impl(const GUID & guid, const GUID & parent, const char * name, double sortPriority = 0) : m_guid(guid), m_parent(parent), m_sortPriority(sortPriority), m_name(name) {} | |
| 309 GUID get_guid() {return m_guid;} | |
| 310 GUID get_parent() {return m_parent;} | |
| 311 double get_sort_priority() {return m_sortPriority;} | |
| 312 void get_display_string(pfc::string_base & out) {out = m_name;} | |
| 313 private: | |
| 314 const GUID m_guid, m_parent; | |
| 315 const double m_sortPriority; | |
| 316 const char * const m_name; | |
| 317 }; | |
| 318 | |
| 319 | |
| 320 | |
| 321 namespace contextmenu_priorities { | |
| 322 enum { | |
| 323 root_queue = -100, | |
| 324 root_main = -50, | |
| 325 root_tagging, | |
| 326 root_fileoperations, | |
| 327 root_convert, | |
| 328 root_utilities, | |
| 329 root_replaygain, | |
| 330 root_playbackstatistics, | |
| 331 root_legacy = 99, | |
| 332 root_properties = 100, | |
| 333 tagging_pictures = 100, | |
| 334 }; | |
| 335 }; | |
| 336 | |
| 337 | |
| 338 | |
| 339 class contextmenu_group_factory : public service_factory_single_t<contextmenu_group_impl> { | |
| 340 public: | |
| 341 contextmenu_group_factory(const GUID & guid, const GUID & parent, double sortPriority = 0) : service_factory_single_t<contextmenu_group_impl>(guid, parent, sortPriority) {} | |
| 342 }; | |
| 343 | |
| 344 class contextmenu_group_popup_factory : public service_factory_single_t<contextmenu_group_popup_impl> { | |
| 345 public: | |
| 346 contextmenu_group_popup_factory(const GUID & guid, const GUID & parent, const char * name, double sortPriority = 0) : service_factory_single_t<contextmenu_group_popup_impl>(guid, parent, name, sortPriority) {} | |
| 347 }; | |
| 348 | |
| 349 | |
| 350 | |
| 351 class contextmenu_item_lambda : public contextmenu_item_simple { | |
| 352 public: | |
| 353 typedef std::function<void(metadb_handle_list_cref)> func_t; | |
| 354 contextmenu_item_lambda(func_t f, const char* n, const GUID& g, const GUID& pg, const char* d = nullptr, double sp = 0) : m_func(f), m_name(n), m_guid(g), m_parentGuid(pg), m_desc(d), m_sortPriority(sp) {} | |
| 355 | |
| 356 unsigned get_num_items() override { return 1; } | |
| 357 void get_item_name(unsigned p_index, pfc::string_base& p_out) override { (void)p_index; p_out = m_name; } | |
| 358 void context_command(unsigned p_index, metadb_handle_list_cref p_data, const GUID& p_caller) override { (void)p_index; (void)p_caller; m_func(p_data); } | |
| 359 GUID get_item_guid(unsigned p_index) override { (void)p_index; return m_guid; } | |
| 360 bool get_item_description(unsigned p_index, pfc::string_base& p_out) override { | |
| 361 (void)p_index; | |
| 362 if (m_desc == nullptr) return false; | |
| 363 p_out = m_desc; | |
| 364 return true; | |
| 365 } | |
| 366 double get_sort_priority() override { return m_sortPriority; } | |
| 367 GUID get_parent() override { return m_parentGuid; } | |
| 368 private: | |
| 369 const std::function<void(metadb_handle_list_cref)> m_func; | |
| 370 const char* const m_name; | |
| 371 const GUID m_guid, m_parentGuid; | |
| 372 const char* const m_desc; | |
| 373 const double m_sortPriority; | |
| 374 }; | |
| 375 | |
| 376 #define FB2K_DECLARE_CONTEXT_MENU_ITEM(func, name, guid, parent, desc, sort) FB2K_SERVICE_FACTORY_PARAMS(contextmenu_item_lambda, func, name, guid, parent, desc, sort) |
