1 /*
2  *  Copyright (C) 2005-2018 Team Kodi
3  *  This file is part of Kodi - https://kodi.tv
4  *
5  *  SPDX-License-Identifier: GPL-2.0-or-later
6  *  See LICENSES/README.md for more information.
7  */
8 
9 #pragma once
10 
11 #include "../AddonBase.h"
12 #include "../c-api/gui/window.h"
13 #include "ListItem.h"
14 #include "input/ActionIDs.h"
15 
16 #ifdef __cplusplus
17 
18 namespace kodi
19 {
20 namespace gui
21 {
22 
23 //==============================================================================
24 /// @defgroup cpp_kodi_gui_windows_window_Defs Definitions, structures and enumerators
25 /// @ingroup cpp_kodi_gui_windows_window
26 /// @brief **Library definition values**\n
27 /// Additional values, structures and things that are used in the Window class.
28 ///
29 /// ------------------------------------------------------------------------
30 ///
31 /// @link cpp_kodi_gui_windows_window Go back to normal functions from CWindow@endlink
32 ///
33 
34 //==============================================================================
35 /// @ingroup cpp_kodi_gui_windows_window_Defs
36 /// @brief **Handler for addon-sided processing class**\n
37 /// If the callback functions used by the window are not used directly in the
38 /// @ref cpp_kodi_gui_windows_window "CWindow" class and are outside of it.
39 ///
40 /// This value here corresponds to a <b>`void*`</b> and returns the address
41 /// requested by the add-on for callbacks.
42 ///
43 using ClientHandle = KODI_GUI_CLIENT_HANDLE;
44 //------------------------------------------------------------------------------
45 
46 class CListItem;
47 
48 //==============================================================================
49 /// @addtogroup cpp_kodi_gui_windows_window
50 /// @brief @cpp_class{ kodi::gui::CWindow }
51 /// **Main window control class**\n
52 /// The addon uses its own skin xml file and displays it in Kodi using this class.
53 ///
54 /// The with  @ref Window.h "#include <kodi/gui/Window.h>"
55 /// included file brings support to create a window or dialog on Kodi.
56 ///
57 /// The add-on has to integrate its own @ref cpp_kodi_gui_windows_window_callbacks "callback functions"
58 /// in order to process the necessary user access to its window.
59 ///
60 ///
61 /// --------------------------------------------------------------------------
62 ///
63 /// **Window header example:**
64 /// ~~~~~~~~~~~~~{.xml}
65 /// <?xml version="1.0" encoding="UTF-8"?>
66 /// <window>
67 ///   <onload>RunScript(script.foobar)</onload>
68 ///   <onunload>SetProperty(foo,bar)</onunload>
69 ///   <defaultcontrol always="false">2</defaultcontrol>
70 ///   <menucontrol>9000</menucontrol>
71 ///   <backgroundcolor>0xff00ff00</backgroundcolor>
72 ///   <views>50,51,509,510</views>
73 ///   <visible>Window.IsActive(Home)</visible>
74 ///   <animation effect="fade" time="100">WindowOpen</animation>
75 ///   <animation effect="slide" end="0,576" time="100">WindowClose</animation>
76 ///   <zorder>1</zorder>
77 ///   <coordinates>
78 ///     <left>40</left>
79 ///     <top>50</top>
80 ///     <origin x="100" y="50">Window.IsActive(Home)</origin>
81 ///   </coordinates>
82 ///   <previouswindow>MyVideos</previouswindow>
83 ///   <controls>
84 ///     <control>
85 ///     </control>
86 ///     ....
87 ///   </controls>
88 /// </window>
89 /// ~~~~~~~~~~~~~
90 ///
91 /// --------------------------------------------------------------------------
92 ///
93 /// On functions defined input variable <b><tt>controlId</tt> (GUI control identifier)</b>
94 /// is the on window.xml defined value behind type added with <tt><b>id="..."</b></tt> and
95 /// used to identify for changes there and on callbacks.
96 ///
97 /// ~~~~~~~~~~~~~{.xml}
98 ///  <control type="label" id="31">
99 ///    <description>Title Label</description>
100 ///    ...
101 ///  </control>
102 ///  <control type="progress" id="32">
103 ///    <description>progress control</description>
104 ///    ...
105 ///  </control>
106 /// ~~~~~~~~~~~~~
107 ///
108 ///
109 class ATTRIBUTE_HIDDEN CWindow : public CAddonGUIControlBase
110 {
111 public:
112   //============================================================================
113   /// @ingroup cpp_kodi_gui_windows_window
114   /// @brief Class constructor with needed values for window / dialog.
115   ///
116   /// Creates a new Window class.
117   ///
118   /// @param[in] xmlFilename XML file for the skin
119   /// @param[in] defaultSkin Default skin to use if needed not available
120   /// @param[in] asDialog Use window as dialog if set
121   /// @param[in] isMedia [opt] bool - if False, create a regular window.
122   ///                    if True, create a mediawindow. (default=false)
123   ///
124   /// @note <b>`isMedia`</b> value as true only usable for windows not for dialogs.
125   ///
126   CWindow(const std::string& xmlFilename,
127           const std::string& defaultSkin,
128           bool asDialog,
129           bool isMedia = false)
CAddonGUIControlBase(nullptr)130     : CAddonGUIControlBase(nullptr)
131   {
132     m_controlHandle = m_interface->kodi_gui->window->create(
133         m_interface->kodiBase, xmlFilename.c_str(), defaultSkin.c_str(), asDialog, isMedia);
134     if (!m_controlHandle)
135       kodi::Log(ADDON_LOG_FATAL, "kodi::gui::CWindow can't create window class from Kodi !!!");
136     m_interface->kodi_gui->window->set_callbacks(m_interface->kodiBase, m_controlHandle, this,
137                                                  CBOnInit, CBOnFocus, CBOnClick, CBOnAction,
138                                                  CBGetContextButtons, CBOnContextButton);
139   }
140   //----------------------------------------------------------------------------
141 
142   //============================================================================
143   /// @ingroup CWindow
144   /// @brief Class destructor.
145   ///
~CWindow()146   ~CWindow() override
147   {
148     if (m_controlHandle)
149       m_interface->kodi_gui->window->destroy(m_interface->kodiBase, m_controlHandle);
150   }
151   //----------------------------------------------------------------------------
152 
153   //============================================================================
154   /// @ingroup cpp_kodi_gui_windows_window
155   /// @brief Show this window.
156   ///
157   /// Shows this window by activating it, calling close() after it wil activate
158   /// the current window again.
159   ///
160   /// @note If your Add-On ends this window will be closed to. To show it forever,
161   /// make a loop at the end of your Add-On or use @ref DoModal() instead.
162   ///
163   /// @warning If used must be the class be global present until Kodi becomes
164   /// closed. The creation can be done before "Show" becomes called, but
165   /// not delete class after them.
166   ///
167   /// @return Return true if call and show is successed, if false was something
168   /// failed to get needed skin parts.
169   ///
Show()170   bool Show()
171   {
172     return m_interface->kodi_gui->window->show(m_interface->kodiBase, m_controlHandle);
173   }
174   //----------------------------------------------------------------------------
175 
176   //============================================================================
177   /// @ingroup cpp_kodi_gui_windows_window
178   /// @brief Closes this window.
179   ///
180   /// Closes this window by activating the old window.
181   /// @note The window is not deleted with this method.
182   ///
Close()183   void Close() { m_interface->kodi_gui->window->close(m_interface->kodiBase, m_controlHandle); }
184   //----------------------------------------------------------------------------
185 
186   //============================================================================
187   /// @ingroup cpp_kodi_gui_windows_window
188   /// @brief Display this window until close() is called.
189   ///
DoModal()190   void DoModal()
191   {
192     m_interface->kodi_gui->window->do_modal(m_interface->kodiBase, m_controlHandle);
193   }
194   //----------------------------------------------------------------------------
195 
196   //============================================================================
197   /// @ingroup cpp_kodi_gui_windows_window
198   /// @brief Gives the control with the supplied focus.
199   ///
200   /// @param[in] controlId On skin defined id of control
201   /// @return Return true if call and focus is successed, if false was something
202   /// failed to get needed skin parts
203   ///
SetFocusId(int controlId)204   bool SetFocusId(int controlId)
205   {
206     return m_interface->kodi_gui->window->set_focus_id(m_interface->kodiBase, m_controlHandle,
207                                                        controlId);
208   }
209   //----------------------------------------------------------------------------
210 
211   //============================================================================
212   /// @ingroup cpp_kodi_gui_windows_window
213   /// @brief Returns the id of the control which is focused.
214   ///
215   /// @return Focused control id
216   ///
GetFocusId()217   int GetFocusId()
218   {
219     return m_interface->kodi_gui->window->get_focus_id(m_interface->kodiBase, m_controlHandle);
220   }
221   //----------------------------------------------------------------------------
222 
223   //============================================================================
224   /// @ingroup cpp_kodi_gui_windows_window
225   /// @brief To set the used label on given control id.
226   ///
227   /// @param[in] controlId Control id where label need to set
228   /// @param[in] label Label to use
229   ///
SetControlLabel(int controlId,const std::string & label)230   void SetControlLabel(int controlId, const std::string& label)
231   {
232     m_interface->kodi_gui->window->set_control_label(m_interface->kodiBase, m_controlHandle,
233                                                      controlId, label.c_str());
234   }
235   //----------------------------------------------------------------------------
236 
237   //============================================================================
238   /// @ingroup cpp_kodi_gui_windows_window
239   /// @brief To set the visibility on given control id.
240   ///
241   /// @param[in] controlId Control id where visibility is changed
242   /// @param[in] visible Boolean value with `true` for visible, `false` for hidden
243   ///
SetControlVisible(int controlId,bool visible)244   void SetControlVisible(int controlId, bool visible)
245   {
246     m_interface->kodi_gui->window->set_control_visible(m_interface->kodiBase, m_controlHandle,
247                                                        controlId, visible);
248   }
249   //----------------------------------------------------------------------------
250 
251   //============================================================================
252   /// @ingroup cpp_kodi_gui_windows_window
253   /// @brief To set the selection on given control id.
254   ///
255   /// @param[in] controlId Control id where selection is changed
256   /// @param[in] selected Boolean value with `true` for selected, `false` for not
257   ///
SetControlSelected(int controlId,bool selected)258   void SetControlSelected(int controlId, bool selected)
259   {
260     m_interface->kodi_gui->window->set_control_selected(m_interface->kodiBase, m_controlHandle,
261                                                         controlId, selected);
262   }
263   //----------------------------------------------------------------------------
264 
265   //============================================================================
266   /// @ingroup cpp_kodi_gui_windows_window
267   /// @brief Sets a window property, similar to an infolabel.
268   ///
269   /// @param[in] key string - property name.
270   /// @param[in] value string or unicode - value of property.
271   ///
272   /// @note  Key is NOT case sensitive. Setting value to an empty string is
273   ///        equivalent to clearProperty(key).\n
274   ///        You can use the above as keywords for arguments and skip certain
275   ///        optional arguments.\n
276   ///        Once you use a keyword, all following arguments require the keyword.
277   ///
SetProperty(const std::string & key,const std::string & value)278   void SetProperty(const std::string& key, const std::string& value)
279   {
280     m_interface->kodi_gui->window->set_property(m_interface->kodiBase, m_controlHandle, key.c_str(),
281                                                 value.c_str());
282   }
283   //----------------------------------------------------------------------------
284 
285   //============================================================================
286   /// @ingroup cpp_kodi_gui_windows_window
287   /// @brief Returns a window property as a string, similar to an infolabel.
288   ///
289   /// @param[in] key string - property name.
290   /// @return The property as string (if present)
291   ///
292   /// @note  Key is NOT case sensitive. Setting value to an empty string is
293   ///        equivalent to clearProperty(key).\n
294   ///        You can use the above as keywords for arguments and skip certain
295   ///        optional arguments.\n
296   ///        Once you use a keyword, all following arguments require the keyword.
297   ///
GetProperty(const std::string & key)298   std::string GetProperty(const std::string& key) const
299   {
300     std::string label;
301     char* ret = m_interface->kodi_gui->window->get_property(m_interface->kodiBase, m_controlHandle,
302                                                             key.c_str());
303     if (ret != nullptr)
304     {
305       if (std::strlen(ret))
306         label = ret;
307       m_interface->free_string(m_interface->kodiBase, ret);
308     }
309     return label;
310   }
311   //----------------------------------------------------------------------------
312 
313   //============================================================================
314   /// @ingroup cpp_kodi_gui_windows_window
315   /// @brief Sets a window property with integer value
316   ///
317   /// @param[in] key string - property name.
318   /// @param[in] value integer value to set
319   ///
SetPropertyInt(const std::string & key,int value)320   void SetPropertyInt(const std::string& key, int value)
321   {
322     m_interface->kodi_gui->window->set_property_int(m_interface->kodiBase, m_controlHandle,
323                                                     key.c_str(), value);
324   }
325   //----------------------------------------------------------------------------
326 
327   //============================================================================
328   /// @ingroup cpp_kodi_gui_windows_window
329   /// @brief Returns a window property with integer value
330   ///
331   /// @param[in] key string - property name.
332   /// @return integer value of property
333   ///
GetPropertyInt(const std::string & key)334   int GetPropertyInt(const std::string& key) const
335   {
336     return m_interface->kodi_gui->window->get_property_int(m_interface->kodiBase, m_controlHandle,
337                                                            key.c_str());
338   }
339   //----------------------------------------------------------------------------
340 
341   //============================================================================
342   /// @ingroup cpp_kodi_gui_windows_window
343   /// @brief Sets a window property with boolean value
344   ///
345   /// @param[in] key string - property name.
346   /// @param[in] value boolean value to set
347   ///
SetPropertyBool(const std::string & key,bool value)348   void SetPropertyBool(const std::string& key, bool value)
349   {
350     m_interface->kodi_gui->window->set_property_bool(m_interface->kodiBase, m_controlHandle,
351                                                      key.c_str(), value);
352   }
353   //----------------------------------------------------------------------------
354 
355   //============================================================================
356   /// @ingroup cpp_kodi_gui_windows_window
357   /// @brief Returns a window property with boolean value
358   ///
359   /// @param[in] key string - property name.
360   /// @return boolean value of property
361   ///
GetPropertyBool(const std::string & key)362   bool GetPropertyBool(const std::string& key) const
363   {
364     return m_interface->kodi_gui->window->get_property_bool(m_interface->kodiBase, m_controlHandle,
365                                                             key.c_str());
366   }
367   //----------------------------------------------------------------------------
368 
369   //============================================================================
370   /// @ingroup cpp_kodi_gui_windows_window
371   /// @brief Sets a window property with double value
372   ///
373   /// @param[in] key string - property name.
374   /// @param[in] value double value to set
375   ///
SetPropertyDouble(const std::string & key,double value)376   void SetPropertyDouble(const std::string& key, double value)
377   {
378     m_interface->kodi_gui->window->set_property_double(m_interface->kodiBase, m_controlHandle,
379                                                        key.c_str(), value);
380   }
381   //----------------------------------------------------------------------------
382 
383   //============================================================================
384   /// @ingroup cpp_kodi_gui_windows_window
385   /// @brief Returns a window property with double value
386   ///
387   /// @param[in] key string - property name.
388   /// @return double value of property
389   ///
GetPropertyDouble(const std::string & key)390   double GetPropertyDouble(const std::string& key) const
391   {
392     return m_interface->kodi_gui->window->get_property_double(m_interface->kodiBase,
393                                                               m_controlHandle, key.c_str());
394   }
395   //----------------------------------------------------------------------------
396 
397   //============================================================================
398   /// @ingroup cpp_kodi_gui_windows_window
399   /// @brief Remove all present properties from window
400   ///
ClearProperties()401   void ClearProperties()
402   {
403     m_interface->kodi_gui->window->clear_properties(m_interface->kodiBase, m_controlHandle);
404   }
405   //----------------------------------------------------------------------------
406 
407   //============================================================================
408   /// @ingroup cpp_kodi_gui_windows_window
409   /// @brief Clears the specific window property.
410   ///
411   /// @param[in] key string - property name.
412   ///
413   /// @note Key is NOT case sensitive. Equivalent to SetProperty(key, "")
414   ///       You can use the above as keywords for arguments and skip certain
415   ///       optional arguments.
416   ///       Once you use a keyword, all following arguments require the
417   ///       keyword.
418   ///
419   ///
420   ///-----------------------------------------------------------------------
421   ///
422   /// **Example:**
423   /// ~~~~~~~~~~~~~{.cpp}
424   /// ..
425   /// ClearProperty('Category')
426   /// ..
427   /// ~~~~~~~~~~~~~
428   ///
ClearProperty(const std::string & key)429   void ClearProperty(const std::string& key)
430   {
431     m_interface->kodi_gui->window->clear_property(m_interface->kodiBase, m_controlHandle,
432                                                   key.c_str());
433   }
434   //----------------------------------------------------------------------------
435 
436   /// @{
437   //============================================================================
438   /// @ingroup cpp_kodi_gui_windows_window
439   /// @brief Function delete all entries in integrated list.
440   ///
ClearList()441   void ClearList()
442   {
443     m_interface->kodi_gui->window->clear_item_list(m_interface->kodiBase, m_controlHandle);
444   }
445   //----------------------------------------------------------------------------
446 
447   //============================================================================
448   /// @ingroup cpp_kodi_gui_windows_window
449   /// @brief To add a list item in the on window integrated list.
450   ///
451   /// @param[in] item List item to add
452   /// @param[in] itemPosition [opt] The position for item, default is on end
453   ///
454   void AddListItem(const std::shared_ptr<CListItem>& item, int itemPosition = -1)
455   {
456     m_interface->kodi_gui->window->add_list_item(m_interface->kodiBase, m_controlHandle,
457                                                  item->m_controlHandle, itemPosition);
458   }
459   //----------------------------------------------------------------------------
460 
461   //============================================================================
462   /// @ingroup cpp_kodi_gui_windows_window
463   /// @brief To add a list item based upon string in the on window integrated list.
464   ///
465   /// @param[in] item List item to add
466   /// @param[in] itemPosition [opt] The position for item, default is on end
467   ///
468   void AddListItem(const std::string& item, int itemPosition = -1)
469   {
470     m_interface->kodi_gui->window->add_list_item(
471         m_interface->kodiBase, m_controlHandle,
472         std::make_shared<kodi::gui::CListItem>(item)->m_controlHandle, itemPosition);
473   }
474   //----------------------------------------------------------------------------
475 
476   //============================================================================
477   /// @ingroup cpp_kodi_gui_windows_window
478   /// @brief Remove list item on position.
479   ///
480   /// @param[in] itemPosition List position to remove
481   ///
RemoveListItem(int itemPosition)482   void RemoveListItem(int itemPosition)
483   {
484     m_interface->kodi_gui->window->remove_list_item_from_position(m_interface->kodiBase,
485                                                                   m_controlHandle, itemPosition);
486   }
487   //----------------------------------------------------------------------------
488 
489   //============================================================================
490   /// @ingroup cpp_kodi_gui_windows_window
491   /// @brief Remove item with given control class from list.
492   ///
493   /// @param[in] item List item control class to remove
494   ///
RemoveListItem(const std::shared_ptr<CListItem> & item)495   void RemoveListItem(const std::shared_ptr<CListItem>& item)
496   {
497     m_interface->kodi_gui->window->remove_list_item(m_interface->kodiBase, m_controlHandle,
498                                                     item->m_controlHandle);
499   }
500   //----------------------------------------------------------------------------
501 
502   //============================================================================
503   /// @ingroup cpp_kodi_gui_windows_window
504   /// @brief To get list item control class on wanted position.
505   ///
506   /// @param[in] listPos Position from where control is needed
507   /// @return The list item control class or null if not found
508   ///
509   /// @warning Function returns a new generated **CListItem** class!
510   ///
GetListItem(int listPos)511   std::shared_ptr<CListItem> GetListItem(int listPos)
512   {
513     KODI_GUI_LISTITEM_HANDLE handle = m_interface->kodi_gui->window->get_list_item(
514         m_interface->kodiBase, m_controlHandle, listPos);
515     if (!handle)
516       return std::shared_ptr<CListItem>();
517 
518     return std::make_shared<kodi::gui::CListItem>(handle);
519   }
520   //----------------------------------------------------------------------------
521 
522   //============================================================================
523   /// @ingroup cpp_kodi_gui_windows_window
524   /// @brief To set position of selected part in list.
525   ///
526   /// @param[in] listPos Position to use
527   ///
SetCurrentListPosition(int listPos)528   void SetCurrentListPosition(int listPos)
529   {
530     m_interface->kodi_gui->window->set_current_list_position(m_interface->kodiBase, m_controlHandle,
531                                                              listPos);
532   }
533   //----------------------------------------------------------------------------
534 
535   //============================================================================
536   /// @ingroup cpp_kodi_gui_windows_window
537   /// @brief To get current selected position in list
538   ///
539   /// @return Current list position
540   ///
GetCurrentListPosition()541   int GetCurrentListPosition()
542   {
543     return m_interface->kodi_gui->window->get_current_list_position(m_interface->kodiBase,
544                                                                     m_controlHandle);
545   }
546   //----------------------------------------------------------------------------
547 
548   //============================================================================
549   /// @ingroup cpp_kodi_gui_windows_window
550   /// @brief To get the amount of entries in the list.
551   ///
552   /// @return Size of in window integrated control class
553   ///
GetListSize()554   int GetListSize()
555   {
556     return m_interface->kodi_gui->window->get_list_size(m_interface->kodiBase, m_controlHandle);
557   }
558   //----------------------------------------------------------------------------
559 
560   //============================================================================
561   /// @ingroup cpp_kodi_gui_windows_window
562   /// @brief Sets a container property, similar to an infolabel.
563   ///
564   /// @param[in] key string - property name.
565   /// @param[in] value string or unicode - value of property.
566   ///
567   /// @note Key is NOT case sensitive.\n
568   /// You can use the above as keywords for arguments and skip certain
569   /// optional arguments.\n
570   /// Once you use a keyword, all following arguments require the keyword.
571   ///
SetContainerProperty(const std::string & key,const std::string & value)572   void SetContainerProperty(const std::string& key, const std::string& value)
573   {
574     m_interface->kodi_gui->window->set_container_property(m_interface->kodiBase, m_controlHandle,
575                                                           key.c_str(), value.c_str());
576   }
577   //----------------------------------------------------------------------------
578 
579   //============================================================================
580   /// @ingroup cpp_kodi_gui_windows_window
581   /// @brief Sets the content type of the container.
582   ///
583   /// @param[in] value string or unicode - content value.
584   ///
585   /// __Available content types__
586   /// | Name        | Media                                    |
587   /// |:-----------:|:-----------------------------------------|
588   /// | actors      | Videos
589   /// | addons      | Addons, Music, Pictures, Programs, Videos
590   /// | albums      | Music, Videos
591   /// | artists     | Music, Videos
592   /// | countries   | Music, Videos
593   /// | directors   | Videos
594   /// | files       | Music, Videos
595   /// | games       | Games
596   /// | genres      | Music, Videos
597   /// | images      | Pictures
598   /// | mixed       | Music, Videos
599   /// | movies      | Videos
600   /// | Musicvideos | Music, Videos
601   /// | playlists   | Music, Videos
602   /// | seasons     | Videos
603   /// | sets        | Videos
604   /// | songs       | Music
605   /// | studios     | Music, Videos
606   /// | tags        | Music, Videos
607   /// | tvshows     | Videos
608   /// | videos      | Videos
609   /// | years       | Music, Videos
610   ///
SetContainerContent(const std::string & value)611   void SetContainerContent(const std::string& value)
612   {
613     m_interface->kodi_gui->window->set_container_content(m_interface->kodiBase, m_controlHandle,
614                                                          value.c_str());
615   }
616   //----------------------------------------------------------------------------
617 
618   //============================================================================
619   /// @ingroup cpp_kodi_gui_windows_window
620   /// @brief Get the id of the currently visible container.
621   ///
622   /// @return currently visible container id
623   ///
GetCurrentContainerId()624   int GetCurrentContainerId()
625   {
626     return m_interface->kodi_gui->window->get_current_container_id(m_interface->kodiBase,
627                                                                    m_controlHandle);
628   }
629   //----------------------------------------------------------------------------
630   /// @}
631 
632   //============================================================================
633   /// @ingroup cpp_kodi_gui_windows_window
634   /// @brief To inform Kodi that it need to render region new.
635   ///
MarkDirtyRegion()636   void MarkDirtyRegion()
637   {
638     return m_interface->kodi_gui->window->mark_dirty_region(m_interface->kodiBase, m_controlHandle);
639   }
640   //----------------------------------------------------------------------------
641 
642   //============================================================================
643   /// @defgroup cpp_kodi_gui_windows_window_callbacks Callback functions from Kodi to add-on
644   /// @ingroup cpp_kodi_gui_windows_window
645   /// @{
646   /// @brief <b>GUI window callback functions.</b>\n
647   /// Functions to handle control callbacks from Kodi
648   ///
649   /// ------------------------------------------------------------------------
650   ///
651   /// @link cpp_kodi_gui_windows_window Go back to normal functions from CWindow@endlink
652   //
653 
654   //============================================================================
655   /// @ingroup cpp_kodi_gui_windows_window_callbacks
656   /// @brief OnInit method.
657   ///
658   /// @return Return true if initialize was done successful
659   ///
660   ///
OnInit()661   virtual bool OnInit() { return false; }
662   //----------------------------------------------------------------------------
663 
664   //============================================================================
665   /// @ingroup cpp_kodi_gui_windows_window_callbacks
666   /// @brief OnFocus method.
667   ///
668   /// @param[in] controlId GUI control identifier
669   /// @return Return true if focus condition was handled there or false to handle
670   ///         them by Kodi itself
671   ///
672   ///
OnFocus(int controlId)673   virtual bool OnFocus(int controlId) { return false; }
674   //----------------------------------------------------------------------------
675 
676   //============================================================================
677   /// @ingroup cpp_kodi_gui_windows_window_callbacks
678   /// @brief OnClick method.
679   ///
680   /// @param[in] controlId GUI control identifier
681   /// @return Return true if click was handled there or false to handle them by
682   ///         Kodi itself
683   ///
684   ///
OnClick(int controlId)685   virtual bool OnClick(int controlId) { return false; }
686   //----------------------------------------------------------------------------
687 
688   //============================================================================
689   /// @ingroup cpp_kodi_gui_windows_window_callbacks
690   /// @brief OnAction method.
691   ///
692   /// @param[in] actionId             The action id to perform, see
693   ///                                 @ref kodi_key_action_ids to get list of
694   ///                                 them
695   /// @return Return true if action was handled there
696   ///                                 or false to handle them by Kodi itself
697   ///
698   ///
699   /// This method will receive all actions that the main program will send
700   /// to this window.
701   ///
702   /// @note
703   /// - By default, only the @c ADDON_ACTION_PREVIOUS_MENU and @c ADDON_ACTION_NAV_BACK actions are handled.
704   /// - Overwrite this method to let your code handle all actions.
705   /// - Don't forget to capture @ref ADDON_ACTION_PREVIOUS_MENU or @ref ADDON_ACTION_NAV_BACK, else the user can't close this window.
706   ///
707   ///
708   ///----------------------------------------------------------------------------
709   ///
710   /// **Example:**
711   /// ~~~~~~~~~~~~~{.cpp}
712   /// ..
713   /// // Window used with parent / child way
714   /// bool cYOUR_CLASS::OnAction(ADDON_ACTION actionId)
715   /// {
716   ///   switch (action)
717   ///   {
718   ///     case ADDON_ACTION_PREVIOUS_MENU:
719   ///     case ADDON_ACTION_NAV_BACK:
720   ///       printf("action recieved: previous");
721   ///       Close();
722   ///       return true;
723   ///     case ADDON_ACTION_SHOW_INFO:
724   ///       printf("action recieved: show info");
725   ///       break;
726   ///     case ADDON_ACTION_STOP:
727   ///       printf("action recieved: stop");
728   ///       break;
729   ///     case ADDON_ACTION_PAUSE:
730   ///       printf("action recieved: pause");
731   ///       break;
732   ///     default:
733   ///       break;
734   ///   }
735   ///   return false;
736   /// }
737   /// ..
738   /// ~~~~~~~~~~~~~
739   ///
OnAction(ADDON_ACTION actionId)740   virtual bool OnAction(ADDON_ACTION actionId)
741   {
742     switch (actionId)
743     {
744       case ADDON_ACTION_PREVIOUS_MENU:
745       case ADDON_ACTION_NAV_BACK:
746         Close();
747         return true;
748       default:
749         break;
750     }
751     return false;
752   }
753   //----------------------------------------------------------------------------
754 
755   //============================================================================
756   /// @ingroup cpp_kodi_gui_windows_window_callbacks
757   /// @brief Get context menu buttons for list entry.
758   ///
759   /// @param[in] itemNumber Selected list item entry
760   /// @param[in] buttons List where context menus becomes added with his
761   ///                    identifier and name
762   ///
GetContextButtons(int itemNumber,std::vector<std::pair<unsigned int,std::string>> & buttons)763   virtual void GetContextButtons(int itemNumber,
764                                  std::vector<std::pair<unsigned int, std::string>>& buttons)
765   {
766   }
767   //----------------------------------------------------------------------------
768 
769   //============================================================================
770   /// @ingroup cpp_kodi_gui_windows_window_callbacks
771   /// @brief Called after selection in context menu.
772   ///
773   /// @param[in] itemNumber Selected list item entry
774   /// @param[in] button The pressed button id
775   /// @return true if handled, otherwise false
776   ///
OnContextButton(int itemNumber,unsigned int button)777   virtual bool OnContextButton(int itemNumber, unsigned int button) { return false; }
778   //----------------------------------------------------------------------------
779 
780   //============================================================================
781   /// @ingroup cpp_kodi_gui_windows_window_callbacks
782   /// @brief **Set independent callbacks**
783   ///
784   /// If the class is used independent (with "new CWindow") and
785   /// not as parent (with \"cCLASS_own : public @ref cpp_kodi_gui_windows_window "kodi::gui::CWindow"\") from own must be the
786   /// callback from Kodi to add-on overdriven with own functions!
787   ///
788   /// @param[in] cbhdl The pointer to own handle data structure / class
789   /// @param[in] CBOnInit Own defined window init function
790   /// @param[in] CBOnFocus Own defined focus function
791   /// @param[in] CBOnClick Own defined click function
792   /// @param[in] CBOnAction Own defined action function
793   /// @param[in] CBGetContextButtons [opt] To get context menu entries for
794   ///                                lists function
795   /// @param[in] CBOnContextButton [opt] Used context menu entry function
796   ///
797   ///
798   ///----------------------------------------------------------------------------
799   ///
800   /// **Example:**
801   /// ~~~~~~~~~~~~~{.cpp}
802   /// ...
803   ///
804   /// bool OnInit(kodi::gui::ClientHandle cbhdl)
805   /// {
806   ///   ...
807   ///   return true;
808   /// }
809   ///
810   /// bool OnFocus(kodi::gui::ClientHandle cbhdl, int controlId)
811   /// {
812   ///   ...
813   ///   return true;
814   /// }
815   ///
816   /// bool OnClick(kodi::gui::ClientHandle cbhdl, int controlId)
817   /// {
818   ///   ...
819   ///   return true;
820   /// }
821   ///
822   /// bool OnAction(kodi::gui::ClientHandle cbhdl, ADDON_ACTION actionId)
823   /// {
824   ///   ...
825   ///   return true;
826   /// }
827   ///
828   /// ...
829   /// // Somewhere where you create the window
830   /// CWindow myWindow = new CWindow;
831   /// myWindow->SetIndependentCallbacks(myWindow, OnInit, OnFocus, OnClick, OnAction);
832   /// ...
833   /// ~~~~~~~~~~~~~
834   ///
835   void SetIndependentCallbacks(kodi::gui::ClientHandle cbhdl,
836                                bool (*CBOnInit)(kodi::gui::ClientHandle cbhdl),
837                                bool (*CBOnFocus)(kodi::gui::ClientHandle cbhdl, int controlId),
838                                bool (*CBOnClick)(kodi::gui::ClientHandle cbhdl, int controlId),
839                                bool (*CBOnAction)(kodi::gui::ClientHandle cbhdl,
840                                                   ADDON_ACTION actionId),
841                                void (*CBGetContextButtons)(kodi::gui::ClientHandle cbhdl,
842                                                            int itemNumber,
843                                                            gui_context_menu_pair* buttons,
844                                                            unsigned int* size) = nullptr,
845                                bool (*CBOnContextButton)(kodi::gui::ClientHandle cbhdl,
846                                                          int itemNumber,
847                                                          unsigned int button) = nullptr)
848   {
849     if (!cbhdl || !CBOnInit || !CBOnFocus || !CBOnClick || !CBOnAction)
850     {
851       kodi::Log(ADDON_LOG_FATAL, "kodi::gui::CWindow::%s called with nullptr !!!", __FUNCTION__);
852       return;
853     }
854 
855     m_interface->kodi_gui->window->set_callbacks(m_interface->kodiBase, m_controlHandle, cbhdl,
856                                                  CBOnInit, CBOnFocus, CBOnClick, CBOnAction,
857                                                  CBGetContextButtons, CBOnContextButton);
858   }
859   //----------------------------------------------------------------------------
860   /// @}
861 
862 private:
CBOnInit(KODI_GUI_CLIENT_HANDLE cbhdl)863   static bool CBOnInit(KODI_GUI_CLIENT_HANDLE cbhdl)
864   {
865     return static_cast<CWindow*>(cbhdl)->OnInit();
866   }
867 
CBOnFocus(KODI_GUI_CLIENT_HANDLE cbhdl,int controlId)868   static bool CBOnFocus(KODI_GUI_CLIENT_HANDLE cbhdl, int controlId)
869   {
870     return static_cast<CWindow*>(cbhdl)->OnFocus(controlId);
871   }
872 
CBOnClick(KODI_GUI_CLIENT_HANDLE cbhdl,int controlId)873   static bool CBOnClick(KODI_GUI_CLIENT_HANDLE cbhdl, int controlId)
874   {
875     return static_cast<CWindow*>(cbhdl)->OnClick(controlId);
876   }
877 
CBOnAction(KODI_GUI_CLIENT_HANDLE cbhdl,ADDON_ACTION actionId)878   static bool CBOnAction(KODI_GUI_CLIENT_HANDLE cbhdl, ADDON_ACTION actionId)
879   {
880     return static_cast<CWindow*>(cbhdl)->OnAction(actionId);
881   }
882 
CBGetContextButtons(KODI_GUI_CLIENT_HANDLE cbhdl,int itemNumber,gui_context_menu_pair * buttons,unsigned int * size)883   static void CBGetContextButtons(KODI_GUI_CLIENT_HANDLE cbhdl,
884                                   int itemNumber,
885                                   gui_context_menu_pair* buttons,
886                                   unsigned int* size)
887   {
888     std::vector<std::pair<unsigned int, std::string>> buttonList;
889     static_cast<CWindow*>(cbhdl)->GetContextButtons(itemNumber, buttonList);
890     if (!buttonList.empty())
891     {
892       unsigned int presentSize = static_cast<unsigned int>(buttonList.size());
893       if (presentSize > *size)
894         kodi::Log(ADDON_LOG_WARNING, "GetContextButtons: More as allowed '%i' entries present!",
895                   *size);
896       else
897         *size = presentSize;
898       for (unsigned int i = 0; i < *size; ++i)
899       {
900         buttons[i].id = buttonList[i].first;
901         strncpy(buttons[i].name, buttonList[i].second.c_str(), ADDON_MAX_CONTEXT_ENTRY_NAME_LENGTH);
902       }
903     }
904   }
905 
CBOnContextButton(KODI_GUI_CLIENT_HANDLE cbhdl,int itemNumber,unsigned int button)906   static bool CBOnContextButton(KODI_GUI_CLIENT_HANDLE cbhdl, int itemNumber, unsigned int button)
907   {
908     return static_cast<CWindow*>(cbhdl)->OnContextButton(itemNumber, button);
909   }
910 };
911 
912 } /* namespace gui */
913 } /* namespace kodi */
914 
915 #endif /* __cplusplus */
916