#pragma once /* * Copyright (C) 2005-2017 Team Kodi * http://kodi.tv * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with KODI; see the file COPYING. If not, see * . * */ #include "../AddonBase.h" #include "ListItem.h" #ifdef BUILD_KODI_ADDON #include "../ActionIDs.h" #else #include "input/ActionIDs.h" #endif namespace kodi { namespace gui { class CListItem; //============================================================================ /// /// \defgroup cpp_kodi_gui_CWindow Window /// \ingroup cpp_kodi_gui /// @brief \cpp_class{ kodi::gui::CWindow } /// **Main window control class** /// /// The with \ref Window.h "#include " /// included file brings support to create a window or dialog on Kodi. /// /// -------------------------------------------------------------------------- /// /// On functions defined input variable controlId (GUI control identifier) /// is the on window.xml defined value behind type added with id="..." and /// used to identify for changes there and on callbacks. /// /// ~~~~~~~~~~~~~{.xml} /// /// Title Label /// ... /// /// /// progress control /// ... /// /// ~~~~~~~~~~~~~ /// /// //============================================================================ /// /// \defgroup cpp_kodi_gui_CWindow_Defs Definitions, structures and enumerators /// \ingroup cpp_kodi_gui_CWindow /// @brief Library definition values /// class CWindow : public CAddonGUIControlBase { public: //========================================================================== /// /// \ingroup cpp_kodi_gui_CWindow /// @brief Class constructor with needed values for window / dialog. /// /// Creates a new Window class. /// /// @param[in] xmlFilename XML file for the skin /// @param[in] defaultSkin default skin to use if needed not available /// @param[in] asDialog Use window as dialog if set /// @param[in] isMedia [opt] bool - if False, create a regular window. /// if True, create a mediawindow. /// (default=false) /// @note only usable for windows not for dialogs. /// /// CWindow(const std::string& xmlFilename, const std::string& defaultSkin, bool asDialog, bool isMedia = false) : CAddonGUIControlBase(nullptr) { m_controlHandle = m_interface->kodi_gui->window->create(m_interface->kodiBase, xmlFilename.c_str(), defaultSkin.c_str(), asDialog, isMedia); if (!m_controlHandle) kodi::Log(ADDON_LOG_FATAL, "kodi::gui::CWindow can't create window class from Kodi !!!"); m_interface->kodi_gui->window->set_callbacks(m_interface->kodiBase, m_controlHandle, this, CBOnInit, CBOnFocus, CBOnClick, CBOnAction, CBGetContextButtons, CBOnContextButton); } //-------------------------------------------------------------------------- //========================================================================== /// /// \ingroup CWindow /// @brief Class destructor /// /// /// virtual ~CWindow() { if (m_controlHandle) m_interface->kodi_gui->window->destroy(m_interface->kodiBase, m_controlHandle); } //-------------------------------------------------------------------------- //========================================================================== /// /// \ingroup cpp_kodi_gui_CWindow /// @brief Show this window. /// /// Shows this window by activating it, calling close() after it wil activate the /// current window again. /// /// @note If your Add-On ends this window will be closed to. To show it forever, /// make a loop at the end of your Add-On or use doModal() instead. /// /// @return Return true if call and show is successed, /// if false was something failed to get needed /// skin parts. /// bool Show() { return m_interface->kodi_gui->window->show(m_interface->kodiBase, m_controlHandle); } //-------------------------------------------------------------------------- //========================================================================== /// /// \ingroup cpp_kodi_gui_CWindow /// @brief Closes this window. /// /// Closes this window by activating the old window. /// @note The window is not deleted with this method. /// void Close() { m_interface->kodi_gui->window->close(m_interface->kodiBase, m_controlHandle); } //-------------------------------------------------------------------------- //========================================================================== /// /// \ingroup cpp_kodi_gui_CWindow /// @brief Display this window until close() is called. /// void DoModal() { m_interface->kodi_gui->window->do_modal(m_interface->kodiBase, m_controlHandle); } //-------------------------------------------------------------------------- //========================================================================== /// /// \ingroup cpp_kodi_gui_CWindow /// @brief Function delete all entries in integrated list. /// /// /// void ClearList() { m_interface->kodi_gui->window->clear_item_list(m_interface->kodiBase, m_controlHandle); } //-------------------------------------------------------------------------- //========================================================================== /// /// \ingroup cpp_kodi_gui_CWindow /// @brief To add a list item in the on window integrated list. /// /// @param[in] item List item to add /// @param[in] itemPosition [opt] The position for item, default is on end /// /// void AddListItem(ListItemPtr item, int itemPosition = -1) { m_interface->kodi_gui->window->add_list_item(m_interface->kodiBase, m_controlHandle, item->m_controlHandle, itemPosition); } //-------------------------------------------------------------------------- //========================================================================== /// /// \ingroup cpp_kodi_gui_CWindow /// @brief To add a list item based upon string in the on window integrated list. /// /// @param[in] item List item to add /// @param[in] itemPosition [opt] The position for item, default is on end /// /// void AddListItem(const std::string item, int itemPosition = -1) { m_interface->kodi_gui->window->add_list_item(m_interface->kodiBase, m_controlHandle, std::make_shared(item)->m_controlHandle, itemPosition); } //-------------------------------------------------------------------------- //========================================================================== /// /// \ingroup cpp_kodi_gui_CWindow /// @brief To get list item control class on wanted position. /// /// @param[in] listPos Position from where control is needed /// @return The list item control class or null if not found /// /// @warning Function returns a new generated **CListItem** class! /// ListItemPtr GetListItem(int listPos) { GUIHANDLE handle = m_interface->kodi_gui->window->get_list_item(m_interface->kodiBase, m_controlHandle, listPos); if (!handle) return ListItemPtr(); return std::make_shared(handle); } //-------------------------------------------------------------------------- //========================================================================== // /// @defgroup cpp_kodi_gui_CWindow_callbacks Callback functions from Kodi to add-on /// \ingroup cpp_kodi_gui_CWindow //@{ /// @brief GUI window callback functions. /// /// Functions to handle control callbacks from Kodi /// /// ------------------------------------------------------------------------ /// /// @link cpp_kodi_gui_CWindow Go back to normal functions from CWindow@endlink // //========================================================================== /// /// \ingroup cpp_kodi_gui_CWindow_callbacks /// @brief OnInit method. /// /// @return Return true if initialize was done successful /// /// virtual bool OnInit() { return false; } //-------------------------------------------------------------------------- //========================================================================== /// /// \ingroup cpp_kodi_gui_CWindow_callbacks /// @brief OnFocus method. /// /// @param[in] controlId GUI control identifier /// @return Return true if focus condition was handled there or false to handle them by Kodi itself /// /// virtual bool OnFocus(int controlId) { return false; } //-------------------------------------------------------------------------- //========================================================================== /// /// \ingroup cpp_kodi_gui_CWindow_callbacks /// @brief OnClick method. /// /// @param[in] controlId GUI control identifier /// @return Return true if click was handled there /// or false to handle them by Kodi itself /// /// virtual bool OnClick(int controlId) { return false; } //-------------------------------------------------------------------------- //========================================================================== /// /// \ingroup cpp_kodi_gui_CWindow_callbacks /// @brief OnAction method. /// /// @param[in] actionId The action id to perform, see /// \ref kodi_key_action_ids to get list of /// them /// @return Return true if action was handled there /// or false to handle them by Kodi itself /// /// /// This method will receive all actions that the main program will send /// to this window. /// /// @note /// - By default, only the \c PREVIOUS_MENU and \c NAV_BACK actions are handled. /// - Overwrite this method to let your code handle all actions. /// - Don't forget to capture \c ACTION_PREVIOUS_MENU or \c ACTION_NAV_BACK, else the user can't close this window. /// /// ///-------------------------------------------------------------------------- /// /// **Example:** /// ~~~~~~~~~~~~~{.cpp} /// .. /// /* Window used with parent / child way */ /// bool cYOUR_CLASS::OnAction(int actionId) /// { /// switch (action) /// { /// case ACTION_PREVIOUS_MENU: /// case ACTION_NAV_BACK: /// printf("action recieved: previous"); /// Close(); /// return true; /// case ACTION_SHOW_INFO: /// printf("action recieved: show info"); /// break; /// case ACTION_STOP: /// printf("action recieved: stop"); /// break; /// case ACTION_PAUSE: /// printf("action recieved: pause"); /// break; /// default: /// break; /// } /// return false; /// } /// .. /// ~~~~~~~~~~~~~ /// virtual bool OnAction(int actionId) { switch (actionId) { case ACTION_PREVIOUS_MENU: case ACTION_NAV_BACK: Close(); return true; default: break; } return false; } //-------------------------------------------------------------------------- //========================================================================== /// /// \ingroup cpp_kodi_gui_CWindow_callbacks /// @brief Get context menu buttons for list entry /// /// @param[in] itemNumber selected list item entry /// @param[in] buttons list where context menus becomes added with his /// identifier and name. /// virtual void GetContextButtons(int itemNumber, std::vector< std::pair > &buttons) { } //-------------------------------------------------------------------------- //========================================================================== /// /// \ingroup cpp_kodi_gui_CWindow_callbacks /// @brief Called after selection in context menu /// /// @param[in] itemNumber selected list item entry /// @param[in] button the pressed button id /// @return true if handled, otherwise false /// virtual bool OnContextButton(int itemNumber, unsigned int button) { return false; } //-------------------------------------------------------------------------- //========================================================================== /// /// \ingroup cpp_kodi_gui_CWindow_callbacks /// @brief **Set independent callbacks** /// /// If the class is used independent (with "new CWindow") and /// not as parent (with "cCLASS_own : CWindow") from own must be the /// callback from Kodi to add-on overdriven with own functions! /// /// @param[in] cbhdl The pointer to own handle data /// structure / class /// @param[in] CBOnInit Own defined window init function /// @param[in] CBOnFocus Own defined focus function /// @param[in] CBOnClick Own defined click function /// @param[in] CBOnAction Own defined action function /// @param[in] CBGetContextButtons [opt] To get context menu entries for /// lists function /// @param[in] CBOnContextButton [opt] Used context menu entry function /// /// ///-------------------------------------------------------------------------- /// /// **Example:** /// ~~~~~~~~~~~~~{.cpp} /// ... /// /// bool OnInit(GUIHANDLE cbhdl) /// { /// ... /// return true; /// } /// /// bool OnFocus(GUIHANDLE cbhdl, int controlId) /// { /// ... /// return true; /// } /// /// bool OnClick(GUIHANDLE cbhdl, int controlId) /// { /// ... /// return true; /// } /// /// bool OnAction(GUIHANDLE cbhdl, int actionId) /// { /// ... /// return true; /// } /// /// ... /// /* Somewhere where you create the window */ /// CWindow myWindow = new CWindow; /// myWindow->SetIndependentCallbacks(myWindow, OnInit, OnFocus, OnClick, OnAction); /// ... /// ~~~~~~~~~~~~~ /// void SetIndependentCallbacks( GUIHANDLE cbhdl, bool (*CBOnInit) (GUIHANDLE cbhdl), bool (*CBOnFocus) (GUIHANDLE cbhdl, int controlId), bool (*CBOnClick) (GUIHANDLE cbhdl, int controlId), bool (*CBOnAction) (GUIHANDLE cbhdl, int actionId), void (*CBGetContextButtons) (GUIHANDLE cbhdl, int itemNumber, gui_context_menu_pair* buttons, unsigned int* size) = nullptr, bool (*CBOnContextButton) (GUIHANDLE cbhdl, int itemNumber, unsigned int button) = nullptr) { if (!cbhdl || !CBOnInit || !CBOnFocus || !CBOnClick || !CBOnAction) { kodi::Log(ADDON_LOG_FATAL, "kodi::gui::CWindow::%s called with nullptr !!!", __FUNCTION__); return; } m_interface->kodi_gui->window->set_callbacks(m_interface->kodiBase, m_controlHandle, cbhdl, CBOnInit, CBOnFocus, CBOnClick, CBOnAction, CBGetContextButtons, CBOnContextButton); } //-------------------------------------------------------------------------- //@} private: static bool CBOnInit(GUIHANDLE cbhdl) { return static_cast(cbhdl)->OnInit(); } static bool CBOnFocus(GUIHANDLE cbhdl, int controlId) { return static_cast(cbhdl)->OnFocus(controlId); } static bool CBOnClick(GUIHANDLE cbhdl, int controlId) { return static_cast(cbhdl)->OnClick(controlId); } static bool CBOnAction(GUIHANDLE cbhdl, int actionId) { return static_cast(cbhdl)->OnAction(actionId); } static void CBGetContextButtons(GUIHANDLE cbhdl, int itemNumber, gui_context_menu_pair* buttons, unsigned int* size) { std::vector< std::pair > buttonList; static_cast(cbhdl)->GetContextButtons(itemNumber, buttonList); if (!buttonList.empty()) { unsigned int presentSize = buttonList.size(); if (presentSize > *size) kodi::Log(ADDON_LOG_WARNING, "GetContextButtons: More as allowed '%i' entries present!", *size); else *size = presentSize; for (unsigned int i = 0; i < *size; ++i) { buttons[i].id = buttonList[i].first; strncpy(buttons[i].name, buttonList[i].second.c_str(), ADDON_MAX_CONTEXT_ENTRY_NAME_LENGTH); } } } static bool CBOnContextButton(GUIHANDLE cbhdl, int itemNumber, unsigned int button) { return static_cast(cbhdl)->OnContextButton(itemNumber, button); } }; } /* namespace gui */ } /* namespace kodi */