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 /*!
12 \file GUIControl.h
13 \brief
14 */
15 
16 #include "DirtyRegion.h"
17 #include "VisibleEffect.h" // needed for the CAnimation members
18 #include "guiinfo/GUIInfoBool.h"
19 #include "guiinfo/GUIInfoColor.h" // needed for CGUIInfoColor to handle infolabel'ed colors
20 #include "utils/Color.h"
21 #include "windowing/GraphicContext.h" // needed by any rendering operation (all controls)
22 
23 #include <vector>
24 
25 class CGUIListItem; // forward
26 class CAction;
27 class CMouseEvent;
28 class CGUIMessage;
29 class CGUIAction;
30 
31 enum ORIENTATION { HORIZONTAL = 0, VERTICAL };
32 
33 class CControlState
34 {
35 public:
CControlState(int id,int data)36   CControlState(int id, int data)
37   {
38     m_id = id;
39     m_data = data;
40   }
41   int m_id;
42   int m_data;
43 };
44 
45 struct GUICONTROLSTATS
46 {
47   unsigned int nCountTotal;
48   unsigned int nCountVisible;
49 
ResetGUICONTROLSTATS50   void Reset()
51   {
52     nCountTotal = nCountVisible = 0;
53   };
54 };
55 
56 /*!
57  \brief Results of OnMouseEvent()
58  Any value not equal to EVENT_RESULT_UNHANDLED indicates that the event was handled.
59  */
60 enum EVENT_RESULT { EVENT_RESULT_UNHANDLED                      = 0x00,
61                     EVENT_RESULT_HANDLED                        = 0x01,
62                     EVENT_RESULT_PAN_HORIZONTAL                 = 0x02,
63                     EVENT_RESULT_PAN_VERTICAL                   = 0x04,
64                     EVENT_RESULT_PAN_VERTICAL_WITHOUT_INERTIA   = 0x08,
65                     EVENT_RESULT_PAN_HORIZONTAL_WITHOUT_INERTIA = 0x10,
66                     EVENT_RESULT_ROTATE                         = 0x20,
67                     EVENT_RESULT_ZOOM                           = 0x40,
68                     EVENT_RESULT_SWIPE                          = 0x80
69 };
70 
71 /*!
72  \ingroup controls
73  \brief Base class for controls
74  */
75 class CGUIControl
76 {
77 public:
78   CGUIControl();
79   CGUIControl(int parentID, int controlID, float posX, float posY, float width, float height);
80   CGUIControl(const CGUIControl &);
81   virtual ~CGUIControl(void);
82   virtual CGUIControl *Clone() const=0;
83 
84   virtual void DoProcess(unsigned int currentTime, CDirtyRegionList &dirtyregions);
85   virtual void Process(unsigned int currentTime, CDirtyRegionList &dirtyregions);
86   virtual void DoRender();
Render()87   virtual void Render() {};
88   // Called after the actual rendering is completed to trigger additional
89   // non GUI rendering operations
RenderEx()90   virtual void RenderEx() {};
91 
92   /*! \brief Returns whether or not we have processed */
HasProcessed()93   bool HasProcessed() const { return m_hasProcessed; };
94 
95   // OnAction() is called by our window when we are the focused control.
96   // We should process any control-specific actions in the derived classes,
97   // and return true if we have taken care of the action.  Returning false
98   // indicates that the message may be handed down to the window or application
99   // levels.  This base class implementation handles basic movement, and should
100   // be called from the derived classes when the action has not been handled.
101   // Return true to indicate that the action has been dealt with.
102   virtual bool OnAction(const CAction &action);
103 
104   // Common actions to make the code easier to read (no ugly switch statements in derived controls)
105   virtual void OnUp();
106   virtual void OnDown();
107   virtual void OnLeft();
108   virtual void OnRight();
109   virtual bool OnBack();
110   virtual bool OnInfo();
111   virtual void OnNextControl();
112   virtual void OnPrevControl();
OnFocus()113   virtual void OnFocus() {};
OnUnFocus()114   virtual void OnUnFocus() {};
115 
116   /*! \brief React to a mouse event
117 
118    Mouse events are sent from the window to all controls, and each control can react based on the event
119    and location of the event.
120 
121    \param point the location in transformed skin coordinates from the upper left corner of the parent control.
122    \param event the mouse event to perform
123    \return EVENT_RESULT corresponding to whether the control handles this event
124    \sa HitTest, CanFocusFromPoint, CMouseEvent, EVENT_RESULT
125    */
126   virtual EVENT_RESULT SendMouseEvent(const CPoint &point, const CMouseEvent &event);
127 
128   /*! \brief Perform a mouse action
129 
130    Mouse actions are sent from the window to all controls, and each control can react based on the event
131    and location of the actions.
132 
133    \param point the location in transformed skin coordinates from the upper left corner of the parent control.
134    \param event the mouse event to perform
135    \return EVENT_RESULT corresponding to whether the control handles this event
136    \sa SendMouseEvent, HitTest, CanFocusFromPoint, CMouseEvent
137    */
OnMouseEvent(const CPoint & point,const CMouseEvent & event)138   virtual EVENT_RESULT OnMouseEvent(const CPoint &point, const CMouseEvent &event) { return EVENT_RESULT_UNHANDLED; };
139 
140   /*! \brief Unfocus the control if the given point on screen is not within it's boundary
141    \param point the location in transformed skin coordinates from the upper left corner of the parent control.
142    \sa CanFocusFromPoint
143    */
144   virtual void UnfocusFromPoint(const CPoint &point);
145 
146   /*! \brief Used to test whether the point is inside a control.
147    \param point location to test
148    \return true if the point is inside the bounds of this control.
149    \sa SetHitRect
150    */
151   virtual bool HitTest(const CPoint &point) const;
152 
153   virtual bool OnMessage(CGUIMessage& message);
154   virtual int GetID(void) const;
SetID(int id)155   virtual void SetID(int id) { m_controlID = id; };
156   int GetParentID() const;
157   virtual bool HasFocus() const;
158   virtual void AllocResources();
159   virtual void FreeResources(bool immediately = false);
160   virtual void DynamicResourceAlloc(bool bOnOff);
IsDynamicallyAllocated()161   virtual bool IsDynamicallyAllocated() { return false; };
162   virtual bool CanFocus() const;
163   virtual bool IsVisible() const;
IsVisibleFromSkin()164   bool IsVisibleFromSkin() const { return m_visibleFromSkinCondition; };
165   virtual bool IsDisabled() const;
166   virtual void SetPosition(float posX, float posY);
167   virtual void SetHitRect(const CRect &rect, const UTILS::Color &color);
168   virtual void SetCamera(const CPoint &camera);
169   virtual void SetStereoFactor(const float &factor);
170   bool SetColorDiffuse(const KODI::GUILIB::GUIINFO::CGUIInfoColor &color);
171   CPoint GetRenderPosition() const;
172   virtual float GetXPosition() const;
173   virtual float GetYPosition() const;
174   virtual float GetWidth() const;
175   virtual float GetHeight() const;
176 
177   void MarkDirtyRegion(const unsigned int dirtyState = DIRTY_STATE_CONTROL);
IsControlDirty()178   bool IsControlDirty() const { return m_controlDirtyState != 0; };
179 
180   /*! \brief return the render region in screen coordinates of this control
181    */
GetRenderRegion()182   const CRect &GetRenderRegion() const { return m_renderRegion; };
183   /*! \brief calculate the render region in parentcontrol coordinates of this control
184    Called during process to update m_renderRegion
185    */
186   virtual CRect CalcRenderRegion() const;
187 
188   /*! \brief Set actions to perform on navigation
189    \param actions ActionMap of actions
190    \sa SetNavigationAction
191    */
192   typedef std::map<int, CGUIAction> ActionMap;
193   void SetActions(const ActionMap &actions);
194 
195   /*! \brief Set actions to perform on navigation
196    Navigations are set if replace is true or if there is no previously set action
197    \param actionID id of the navigation action
198    \param action CGUIAction to set
199    \param replace Actions are set only if replace is true or there is no previously set action.  Defaults to true
200    \sa SetNavigationActions
201    */
202   void SetAction(int actionID, const CGUIAction &action, bool replace = true);
203 
204   /*! \brief Get an action the control can be perform.
205    \param actionID The actionID to retrieve.
206    */
207   CGUIAction GetAction(int actionID) const;
208 
209   /*! \brief  Start navigating in given direction.
210    */
211   bool Navigate(int direction) const;
212   virtual void SetFocus(bool focus);
213   virtual void SetWidth(float width);
214   virtual void SetHeight(float height);
215   virtual void SetVisible(bool bVisible, bool setVisState = false);
216   void SetVisibleCondition(const std::string &expression, const std::string &allowHiddenFocus = "");
HasVisibleCondition()217   bool HasVisibleCondition() const { return m_visibleCondition != NULL; };
218   void SetEnableCondition(const std::string &expression);
219   virtual void UpdateVisibility(const CGUIListItem *item);
220   virtual void SetInitialVisibility();
221   virtual void SetEnabled(bool bEnable);
SetInvalid()222   virtual void SetInvalid() { m_bInvalidated = true; };
SetPulseOnSelect(bool pulse)223   virtual void SetPulseOnSelect(bool pulse) { m_pulseOnSelect = pulse; };
GetDescription()224   virtual std::string GetDescription() const { return ""; };
GetDescriptionByIndex(int index)225   virtual std::string GetDescriptionByIndex(int index) const { return ""; };
226 
227   void SetAnimations(const std::vector<CAnimation> &animations);
GetAnimations()228   const std::vector<CAnimation> &GetAnimations() const { return m_animations; };
229 
230   virtual void QueueAnimation(ANIMATION_TYPE anim);
231   virtual bool IsAnimating(ANIMATION_TYPE anim);
232   virtual bool HasAnimation(ANIMATION_TYPE anim);
233   CAnimation *GetAnimation(ANIMATION_TYPE type, bool checkConditions = true);
234   virtual void ResetAnimation(ANIMATION_TYPE type);
235   virtual void ResetAnimations();
236 
237   // push information updates
238   virtual void UpdateInfo(const CGUIListItem *item = NULL) {};
SetPushUpdates(bool pushUpdates)239   virtual void SetPushUpdates(bool pushUpdates) { m_pushedUpdates = pushUpdates; };
240 
IsGroup()241   virtual bool IsGroup() const { return false; };
IsContainer()242   virtual bool IsContainer() const { return false; };
GetCondition(int condition,int data)243   virtual bool GetCondition(int condition, int data) const { return false; };
244 
SetParentControl(CGUIControl * control)245   void SetParentControl(CGUIControl *control) { m_parentControl = control; };
GetParentControl(void)246   CGUIControl *GetParentControl(void) const { return m_parentControl; };
247   virtual void SaveStates(std::vector<CControlState> &states);
248   virtual CGUIControl *GetControl(int id, std::vector<CGUIControl*> *idCollector = nullptr);
249 
250 
SetControlStats(GUICONTROLSTATS * controlStats)251   void SetControlStats(GUICONTROLSTATS *controlStats) { m_controlStats = controlStats; };
252   virtual void UpdateControlStats();
253 
254   enum GUICONTROLTYPES {
255     GUICONTROL_UNKNOWN,
256     GUICONTROL_BUTTON,
257     GUICONTROL_FADELABEL,
258     GUICONTROL_IMAGE,
259     GUICONTROL_BORDEREDIMAGE,
260     GUICONTROL_LABEL,
261     GUICONTROL_LISTGROUP,
262     GUICONTROL_PROGRESS,
263     GUICONTROL_RADIO,
264     GUICONTROL_RSS,
265     GUICONTROL_SLIDER,
266     GUICONTROL_SETTINGS_SLIDER,
267     GUICONTROL_SPIN,
268     GUICONTROL_SPINEX,
269     GUICONTROL_TEXTBOX,
270     GUICONTROL_TOGGLEBUTTON,
271     GUICONTROL_VIDEO,
272     GUICONTROL_GAME,
273     GUICONTROL_MOVER,
274     GUICONTROL_RESIZE,
275     GUICONTROL_EDIT,
276     GUICONTROL_VISUALISATION,
277     GUICONTROL_RENDERADDON,
278     GUICONTROL_MULTI_IMAGE,
279     GUICONTROL_GROUP,
280     GUICONTROL_GROUPLIST,
281     GUICONTROL_SCROLLBAR,
282     GUICONTROL_LISTLABEL,
283     GUICONTROL_GAMECONTROLLER,
284     GUICONTAINER_LIST,
285     GUICONTAINER_WRAPLIST,
286     GUICONTAINER_FIXEDLIST,
287     GUICONTAINER_EPGGRID,
288     GUICONTAINER_PANEL,
289     GUICONTROL_RANGES
290   };
GetControlType()291   GUICONTROLTYPES GetControlType() const { return ControlType; }
292 
293   enum GUIVISIBLE { HIDDEN = 0, DELAYED, VISIBLE };
294 
295   enum GUISCROLLVALUE { FOCUS = 0, NEVER, ALWAYS };
296 
297 #ifdef _DEBUG
DumpTextureUse()298   virtual void DumpTextureUse() {};
299 #endif
300 protected:
301   /*!
302    \brief Return the coordinates of the top left of the control, in the control's parent coordinates
303    \return The top left coordinates of the control
304    */
GetPosition()305   virtual CPoint GetPosition() const { return CPoint(GetXPosition(), GetYPosition()); };
306 
307   /*! \brief Called when the mouse is over the control.
308    Default implementation selects the control.
309    \param point location of the mouse in transformed skin coordinates
310    \return true if handled, false otherwise.
311    */
312   virtual bool OnMouseOver(const CPoint &point);
313 
314   /*! \brief Test whether we can focus a control from a point on screen
315    \param point the location in vanilla skin coordinates from the upper left corner of the parent control.
316    \return true if the control can be focused from this location
317    \sa UnfocusFromPoint, HitRect
318    */
319   virtual bool CanFocusFromPoint(const CPoint &point) const;
320 
321   virtual bool UpdateColors();
322   virtual bool Animate(unsigned int currentTime);
323   virtual bool CheckAnimation(ANIMATION_TYPE animType);
324   void UpdateStates(ANIMATION_TYPE type, ANIMATION_PROCESS currentProcess, ANIMATION_STATE currentState);
325   bool SendWindowMessage(CGUIMessage &message) const;
326 
327   // navigation and actions
328   ActionMap m_actions;
329 
330   float m_posX;
331   float m_posY;
332   float m_height;
333   float m_width;
334   CRect m_hitRect;
335   UTILS::Color m_hitColor = 0xffffffff;
336   KODI::GUILIB::GUIINFO::CGUIInfoColor m_diffuseColor;
337   int m_controlID;
338   int m_parentID;
339   bool m_bHasFocus;
340   bool m_bInvalidated;
341   bool m_bAllocated;
342   bool m_pulseOnSelect;
343   GUICONTROLTYPES ControlType;
344   GUICONTROLSTATS *m_controlStats;
345 
346   CGUIControl *m_parentControl;   // our parent control if we're part of a group
347 
348   // visibility condition/state
349   INFO::InfoPtr m_visibleCondition;
350   GUIVISIBLE m_visible;
351   bool m_visibleFromSkinCondition;
352   bool m_forceHidden;       // set from the code when a hidden operation is given - overrides m_visible
353   KODI::GUILIB::GUIINFO::CGUIInfoBool m_allowHiddenFocus;
354   bool m_hasProcessed;
355   // enable/disable state
356   INFO::InfoPtr m_enableCondition;
357   bool m_enabled;
358 
359   bool m_pushedUpdates;
360 
361   // animation effects
362   std::vector<CAnimation> m_animations;
363   CPoint m_camera;
364   bool m_hasCamera;
365   float m_stereo;
366   TransformMatrix m_transform;
367   TransformMatrix m_cachedTransform; // Contains the absolute transform the control
368 
369   static const unsigned int DIRTY_STATE_CONTROL = 1; //This control is dirty
370   static const unsigned int DIRTY_STATE_CHILD = 2; //One / more children are dirty
371 
372   unsigned int  m_controlDirtyState;
373   CRect m_renderRegion;         // In screen coordinates
374 };
375 
376