1 /* Copyright (C) 2012 Wildfire Games.
2 * This file is part of 0 A.D.
4 * 0 A.D. is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
9 * 0 A.D. is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
19 The base class of an object
23 All objects are derived from this class, it's an ADT
24 so it can't be used per se
26 Also contains a Dummy object which is used for
27 completely blank objects.
31 Write about how to use it here
35 Provide examples of how to use this code, if necessary
43 #ifndef INCLUDED_IGUIOBJECT
44 #define INCLUDED_IGUIOBJECT
46 //--------------------------------------------------------
47 // Includes / Compiler directives
48 //--------------------------------------------------------
53 #include "lib/input.h" // just for IN_PASS
55 #include "ps/XML/Xeromyces.h"
57 #include "gui/scripting/JSInterface_IGUIObject.h"
62 class CScriptValRooted
;
64 //--------------------------------------------------------
66 //--------------------------------------------------------
68 //--------------------------------------------------------
70 //--------------------------------------------------------
73 typedef std::map
<CStr
, SGUISetting
> map_Settings
;
77 //--------------------------------------------------------
79 //--------------------------------------------------------
81 ERROR_TYPE(GUI
, UnableToParse
);
83 //--------------------------------------------------------
85 //--------------------------------------------------------
91 * For use of later macros, all names should be GUIST_ followed
92 * by the code name (case sensitive!).
94 #define TYPE(T) GUIST_##T,
102 * A GUI Setting is anything that can be inputted from XML as
103 * \<object\>-attributes (with exceptions). For instance:
104 * \<object style="null"\>
106 * "style" will be a SGUISetting.
110 SGUISetting() : m_pSetting(NULL
) {}
113 EGUISettingType m_Type
;
117 * Base settings, all objects possess these settings
118 * in their m_BaseSettings
119 * Instructions can be found in the documentations.
121 /*struct SGUIBaseSettings
125 CStr m_Caption; // Is usually set within an XML element and not in the attributes
134 //////////////////////////////////////////////////////////
137 * GUI object such as a button or an input-box.
138 * Abstract data type !
143 friend class CInternalCGUIAccessorBase
;
144 friend class IGUIScrollBar
;
145 friend class GUITooltip
;
147 // Allow getProperty to access things like GetParent()
148 friend JSBool
JSI_IGUIObject::getProperty(JSContext
* cx
, JSObject
* obj
, jsid id
, jsval
* vp
);
149 friend JSBool
JSI_IGUIObject::setProperty(JSContext
* cx
, JSObject
* obj
, jsid id
, JSBool strict
, jsval
* vp
);
150 friend JSBool
JSI_IGUIObject::getComputedSize(JSContext
* cx
, uintN argc
, jsval
* vp
);
154 virtual ~IGUIObject();
157 * Checks if mouse is hovering this object.
158 * The mouse position is cached in CGUI.
160 * This function checks if the mouse is hovering the
161 * rectangle that the base setting "size" makes.
162 * Although it is virtual, so one could derive
163 * an object from CButton, which changes only this
164 * to checking the circle that "size" makes.
166 * @return true if mouse is hovering
168 virtual bool MouseOver();
171 * Test if mouse position is over an icon
173 virtual bool MouseOverIcon();
175 //--------------------------------------------------------
176 /** @name Leaf Functions */
177 //--------------------------------------------------------
180 /// Get object name, name is unique
181 const CStr
& GetName() const { return m_Name
; }
184 void SetName(const CStr
& Name
) { m_Name
= Name
; }
186 // Get Presentable name.
187 // Will change all internally set names to something like "<unnamed object>"
188 CStr
GetPresentableName() const;
191 * Adds object and its children to the map, it's name being the
192 * first part, and the second being itself.
194 * @param ObjectMap Adds this to the map_pObjects.
196 * @throws PSERROR_GUI_ObjectNeedsName Name is missing
197 * @throws PSERROR_GUI_NameAmbiguity Name is already taken
199 void AddToPointersMap(map_pObjects
&ObjectMap
);
202 * Notice nothing will be returned or thrown if the child hasn't
203 * been inputted into the GUI yet. This is because that's were
204 * all is checked. Now we're just linking two objects, but
205 * it's when we're inputting them into the GUI we'll check
206 * validity! Notice also when adding it to the GUI this function
207 * will inevitably have been called by CGUI::AddObject which
208 * will catch the throw and return the error code.
209 * i.e. The user will never put in the situation wherein a throw
210 * must be caught, the GUI's internal error handling will be
211 * completely transparent to the interfacially sequential model.
213 * @param pChild Child to add
215 * @throws PSERROR_GUI from CGUI::UpdateObjects().
217 void AddChild(IGUIObject
*pChild
);
220 //--------------------------------------------------------
222 //--------------------------------------------------------
225 vector_pObjects::iterator
ChildrenItBegin() { return m_Children
.begin(); }
226 vector_pObjects::iterator
ChildrenItEnd() { return m_Children
.end(); }
229 //--------------------------------------------------------
230 /** @name Settings Management */
231 //--------------------------------------------------------
235 * Checks if settings exists, only available for derived
236 * classes that has this set up, that's why the base
237 * class just returns false
239 * @param Setting setting name
240 * @return True if settings exist.
242 bool SettingExists(const CStr
& Setting
) const;
245 * All sizes are relative to resolution, and the calculation
246 * is not wanted in real time, therefore it is cached, update
247 * the cached size with this function.
249 virtual void UpdateCachedSize();
252 * Set a setting by string, regardless of what type it is.
254 * example a CRect(10,10,20,20) would be "10 10 20 20"
256 * @param Setting Setting by name
257 * @param Value Value to set to
258 * @param SkipMessage Does not send a GUIM_SETTINGS_UPDATED if true
260 * @return PSRETURN (PSRETURN_OK if successful)
262 PSRETURN
SetSetting(const CStr
& Setting
, const CStrW
& Value
, const bool& SkipMessage
=false);
265 * Retrieves the type of a named setting.
267 * @param Setting Setting by name
268 * @param Type Stores an EGUISettingType
269 * @return PSRETURN (PSRETURN_OK if successful)
271 PSRETURN
GetSettingType(const CStr
& Setting
, EGUISettingType
&Type
) const;
274 * Set the script handler for a particular object-specific action
276 * @param Action Name of action
277 * @param Code Javascript code to execute when the action occurs
278 * @param pGUI GUI instance to associate the script with
280 void RegisterScriptHandler(const CStr
& Action
, const CStr
& Code
, CGUI
* pGUI
);
283 * Retrieves the JSObject representing this GUI object.
285 JSObject
* GetJSObject();
289 //--------------------------------------------------------
290 /** @name Called by CGUI and friends
292 * Methods that the CGUI will call using
293 * its friendship, these should not
295 * These functions' security are a lot
296 * what constitutes the GUI's
298 //--------------------------------------------------------
302 * Add a setting to m_Settings
304 * @param Type Setting type
305 * @param Name Setting reference name
307 void AddSetting(const EGUISettingType
&Type
, const CStr
& Name
);
310 * Calls Destroy on all children, and deallocates all memory.
311 * MEGA TODO Should it destroy it's children?
313 virtual void Destroy();
317 * This function is called with different messages
318 * for instance when the mouse enters the object.
320 * @param Message GUI Message
322 virtual void HandleMessage(SGUIMessage
& UNUSED(Message
)) {}
328 * @throws PSERROR if any. But this will mostlikely be
329 * very rare since if an object is drawn unsuccessfully
330 * it'll probably only output in the Error log, and not
331 * disrupt the whole GUI drawing.
333 virtual void Draw()=0;
336 * Some objects need to handle the SDL_Event_ manually.
337 * For instance the input box.
339 * Only the object with focus will have this function called.
341 * Returns either IN_PASS or IN_HANDLED. If IN_HANDLED, then
342 * the key won't be passed on and processed by other handlers.
343 * This is used for keys that the GUI uses.
345 virtual InReaction
ManuallyHandleEvent(const SDL_Event_
* UNUSED(ev
)) { return IN_PASS
; }
350 * @param GUIinstance Reference to the GUI
351 * @param StyleName Style by name
353 void LoadStyle(CGUI
&GUIinstance
, const CStr
& StyleName
);
358 * @param Style The style object.
360 void LoadStyle(const SGUIStyle
&Style
);
363 * Returns not the Z value, but the actual buffered Z value, i.e. if it's
364 * defined relative, then it will check its parent's Z value and add
367 * @return Actual Z value on the screen.
369 virtual float GetBufferedZ() const;
371 void SetGUI(CGUI
* const &pGUI
) { m_pGUI
= pGUI
; }
374 * Set parent of this object
376 void SetParent(IGUIObject
*pParent
) { m_pParent
= pParent
; }
379 * Reset internal state of this object
381 virtual void ResetStates()
383 // Notify the gui that we aren't hovered anymore
384 UpdateMouseOver(NULL
);
388 CGUI
*GetGUI() { return m_pGUI
; }
389 const CGUI
*GetGUI() const { return m_pGUI
; }
398 * Check if object is focused.
400 bool IsFocused() const;
403 * <b>NOTE!</b> This will not just return m_pParent, when that is
404 * need use it! There is one exception to it, when the parent is
405 * the top-node (the object that isn't a real object), this
406 * will return NULL, so that the top-node's children are
407 * seemingly parentless.
409 * @return Pointer to parent
411 IGUIObject
*GetParent() const;
414 * Get Mouse from CGUI.
416 CPos
GetMousePos() const;
419 * Handle additional children to the \<object\>-tag. In IGUIObject, this function does
420 * nothing. In CList and CDropDown, it handles the \<item\>, used to build the data.
422 * Returning false means the object doesn't recognize the child. Should be reported.
423 * Notice 'false' is default, because an object not using this function, should not
424 * have any additional children (and this function should never be called).
426 virtual bool HandleAdditionalChildren(const XMBElement
& UNUSED(child
),
427 CXeromyces
* UNUSED(pFile
)) { return false; }
430 * Cached size, real size m_Size is actually dependent on resolution
431 * and can have different *real* outcomes, this is the real outcome
432 * cached to avoid slow calculations in real time.
434 CRect m_CachedActualSize
;
437 * Send event to this GUI object (HandleMessage and ScriptEvent)
439 * @param type Type of GUI message to be handled
440 * @param EventName String representation of event name
441 * @return IN_HANDLED if event was handled, or IN_PASS if skipped
443 InReaction
SendEvent(EGUIMessageType type
, const CStr
& EventName
);
446 * Execute the script for a particular action.
447 * Does nothing if no script has been registered for that action.
448 * The mouse coordinates will be passed as the first argument.
450 * @param Action Name of action
452 void ScriptEvent(const CStr
& Action
);
455 * Execute the script for a particular action.
456 * Does nothing if no script has been registered for that action.
458 * @param Action Name of action
459 * @param Argument Argument to pass to action
461 void ScriptEvent(const CStr
& Action
, const CScriptValRooted
& Argument
);
463 void SetScriptHandler(const CStr
& Action
, JSObject
* Function
);
466 * Inputes the object that is currently hovered, this function
467 * updates this object accordingly (i.e. if it's the object
468 * being inputted one thing happens, and not, another).
470 * @param pMouseOver Object that is currently hovered,
471 * can OF COURSE be NULL too!
473 void UpdateMouseOver(IGUIObject
* const &pMouseOver
);
477 //--------------------------------------------------------
478 /** @name Internal functions */
479 //--------------------------------------------------------
483 * Inputs a reference pointer, checks if the new inputted object
484 * if hovered, if so, then check if this's Z value is greater
485 * than the inputted object... If so then the object is closer
486 * and we'll replace the pointer with this.
487 * Also Notice input can be NULL, which means the Z value demand
488 * is out. NOTICE you can't input NULL as const so you'll have
489 * to set an object to NULL.
491 * @param pObject Object pointer, can be either the old one, or
494 void ChooseMouseOverAndClosest(IGUIObject
* &pObject
);
496 // Is the object a Root object, in philosophy, this means it
497 // has got no parent, and technically, it's got the m_BaseObject
499 bool IsRootObject() const;
502 * Logs an invalid setting search and returns the correct return result
504 * @return the error result
506 PSRETURN
LogInvalidSettings(const CStr8
& Setting
) const;
514 // Constructed on the heap, will be destroyed along with the the object
515 // TODO Gee: really the above?
516 vector_pObjects m_Children
;
519 IGUIObject
*m_pParent
;
521 //This represents the last click time for each mouse button
522 double m_LastClickTime
[6];
525 * This is an array of true or false, each element is associated with
526 * a string representing a setting. Number of elements is equal to
527 * number of settings.
529 * A true means the setting has been manually set in the file when
530 * read. This is important to know because I don't want to force
531 * the user to include its \<styles\>-XML-files first, so somehow
532 * the GUI needs to know which settings were set, and which is meant
538 // Is mouse hovering the object? used with the function MouseOver()
539 bool m_MouseHovering
;
542 * Settings pool, all an object's settings are located here
543 * If a derived object has got more settings that the base
544 * settings, it's because they have a new version of the
545 * function SetupSettings().
547 * @see SetupSettings()
550 std::map
<CStr
, SGUISetting
> m_Settings
;
553 // An object can't function stand alone
556 // Internal storage for registered script handlers.
557 std::map
<CStr
, JSObject
**> m_ScriptHandlers
;
559 // Cached JSObject representing this GUI object
560 JSObject
*m_JSObject
;
565 * Dummy object used primarily for the root object
566 * or objects of type 'empty'
568 class CGUIDummyObject
: public IGUIObject
570 GUI_OBJECT(CGUIDummyObject
)
574 virtual void Draw() {}
575 // Empty can never be hovered. It is only a category.
576 virtual bool MouseOver() { return false; }