//----------------------------------------------------------------------------- // Torque Game Engine // Copyright (C) GarageGames.com, Inc. //----------------------------------------------------------------------------- #ifndef _GUICONTROL_H_ #define _GUICONTROL_H_ #ifndef _PLATFORM_H_ #include "platform/platform.h" #endif #ifndef _MPOINT_H_ #include "math/mPoint.h" #endif #ifndef _MRECT_H_ #include "math/mRect.h" #endif #ifndef _COLOR_H_ #include "core/color.h" #endif #ifndef _SIMBASE_H_ #include "console/simBase.h" #endif #ifndef _GUITYPES_H_ #include "gui/core/guiTypes.h" #endif #ifndef _EVENT_H_ #include "platform/event.h" #endif #ifndef _LANG_H_ #include "i18n/lang.h" #endif class GuiCanvas; class GuiEditCtrl; /// Root class for all GUI controls in Torque. /// /// @see GUI for an overview of the Torque GUI system. /// /// @section GuiControl_Intro Introduction /// /// GuiControl is the base class for GUI controls in Torque. It provides these /// basic areas of functionality: /// - Inherits from SimGroup, so that controls can have children. /// - Interfacing with a GuiControlProfile. /// - An abstraction from the details of handling user input /// and so forth, providing friendly hooks like onMouseEnter(), onMouseMove(), /// and onMouseLeave(), onKeyDown(), and so forth. /// - An abstraction from the details of rendering and resizing. /// - Helper functions to manipulate the mouse (mouseLock and /// mouseUnlock), and convert coordinates (localToGlobalCoord() and /// globalToLocalCoord()). /// /// @ref GUI has an overview of the GUI system. /// /// @nosubgrouping class GuiControl : public SimGroup { private: typedef SimGroup Parent; StringTableEntry mClassName; StringTableEntry mSuperClassName; public: /// @name Control State /// @{ GuiControlProfile *mProfile; GuiControlProfile *mTooltipProfile; S32 mTipHoverTime; bool mVisible; bool mActive; bool mAwake; bool mSetFirstResponder; bool mCanSave; S32 mLayer; RectI mBounds; Point2I mMinExtent; StringTableEntry mLangTableName; LangTable *mLangTable; static bool smDesignTime; ///< static GuiControl boolean that specifies if the GUI Editor is active /// @} /// @name Design Time Editor Access /// @{ static GuiEditCtrl *smEditorHandle; ///< static GuiEditCtrl pointer that gives controls access to editor-NULL if editor is closed /// @} /// @name Keyboard Input /// @{ GuiControl *mFirstResponder; static GuiControl *smPrevResponder; static GuiControl *smCurResponder; /// @} enum horizSizingOptions { horizResizeRight = 0, ///< fixed on the left and width horizResizeWidth, ///< fixed on the left and right horizResizeLeft, ///< fixed on the right and width horizResizeCenter, horizResizeRelative ///< resize relative }; enum vertSizingOptions { vertResizeBottom = 0, ///< fixed on the top and in height vertResizeHeight, ///< fixed on the top and bottom vertResizeTop, ///< fixed in height and on the bottom vertResizeCenter, vertResizeRelative ///< resize relative }; protected: /// @name Control State /// @{ S32 mHorizSizing; ///< Set from horizSizingOptions. S32 mVertSizing; ///< Set from vertSizingOptions. StringTableEntry mConsoleVariable; StringTableEntry mConsoleCommand; StringTableEntry mAltConsoleCommand; StringTableEntry mAcceleratorKey; StringTableEntry mTooltip; /// @} /// @name Console /// The console variable collection of functions allows a console variable to be bound to the GUI control. /// /// This allows, say, an edit field to be bound to '$foo'. The value of the console /// variable '$foo' would then be equal to the text inside the text field. Changing /// either changes the other. /// @{ /// Sets the value of the console variable bound to this control /// @param value String value to assign to control's console variable void setVariable(const char *value); /// Sets the value of the console variable bound to this control /// @param value Integer value to assign to control's console variable void setIntVariable(S32 value); /// Sets the value of the console variable bound to this control /// @param value Float value to assign to control's console variable void setFloatVariable(F32 value); const char* getVariable(); ///< Returns value of control's bound variable as a string S32 getIntVariable(); ///< Returns value of control's bound variable as a integer F32 getFloatVariable(); ///< Returns value of control's bound variable as a float public: /// Set the name of the console variable which this GuiObject is bound to /// @param variable Variable name void setConsoleVariable(const char *variable); /// Set the name of the console function bound to, such as a script function /// a button calls when clicked. /// @param newCmd Console function to attach to this GuiControl void setConsoleCommand(const char *newCmd); const char * getConsoleCommand(); ///< Returns the name of the function bound to this GuiControl LangTable *getGUILangTable(void); const UTF8 *getGUIString(S32 id); /// @} /// @name Editor /// These functions are used by the GUI Editor /// @{ /// Sets the size of the GuiControl /// @param horz Width of the control /// @param vert Height of the control void setSizing(S32 horz, S32 vert); /// Overrides Parent Serialization to allow specific controls to not be saved (Dynamic Controls, etc) void write(Stream &stream, U32 tabStop, U32 flags); /// Returns boolean specifying if a control can be serialized bool getCanSave(); /// Set serialization flag void setCanSave(bool bCanSave); /// Returns boolean as to whether any parent of this control has the 'no serialization' flag set. bool getCanSaveParent(); /// @} public: /// @name Initialization /// @{ DECLARE_CONOBJECT(GuiControl); GuiControl(); virtual ~GuiControl(); static void initPersistFields(); /// @} /// @name Accessors /// @{ const Point2I& getPosition() { return mBounds.point; } ///< Returns position of the control const Point2I& getExtent() { return mBounds.extent; } ///< Returns extents of the control const RectI& getBounds() { return mBounds; } ///< Returns the bounds of the control const Point2I& getMinExtent() { return mMinExtent; } ///< Returns minimum size the control can be const S32 getLeft() { return mBounds.point.x; } ///< Returns the X position of the control const S32 getTop() { return mBounds.point.y; } ///< Returns the Y position of the control const S32 getWidth() { return mBounds.extent.x; } ///< Returns the width of the control const S32 getHeight() { return mBounds.extent.y; } ///< Returns the height of the control /// @} /// @name Flags /// @{ /// Sets the visibility of the control /// @param value True if object should be visible virtual void setVisible(bool value); inline bool isVisible() { return mVisible; } ///< Returns true if the object is visible /// Sets the status of this control as active and responding or inactive /// @param value True if this is active void setActive(bool value); bool isActive() { return mActive; } ///< Returns true if this control is active bool isAwake() { return mAwake; } ///< Returns true if this control is awake /// @} /// Get information about the size of a scroll line. /// /// @param rowHeight The height, in pixels, of a row /// @param columnWidth The width, in pixels, of a column virtual void getScrollLineSizes(U32 *rowHeight, U32 *columnWidth); /// Get information about the cursor. /// @param cursor Cursor information will be stored here /// @param showCursor Will be set to true if the cursor is visible /// @param lastGuiEvent GuiEvent containing cursor position and modifyer keys (ie ctrl, shift, alt etc) virtual void getCursor(GuiCursor *&cursor, bool &showCursor, const GuiEvent &lastGuiEvent); /// @name Children /// @{ /// Adds an object as a child of this object. /// @param obj New child object of this control void addObject(SimObject *obj); /// Removes a child object from this control. /// @param obj Object to remove from this control void removeObject(SimObject *obj); GuiControl *getParent(); ///< Returns the control which owns this one. GuiCanvas *getRoot(); ///< Returns the root canvas of this control. /// @} /// @name Coordinates /// @{ /// Translates local coordinates (wrt this object) into global coordinates /// /// @param src Local coordinates to translate Point2I localToGlobalCoord(const Point2I &src); /// Returns global coordinates translated into local space /// /// @param src Global coordinates to translate Point2I globalToLocalCoord(const Point2I &src); /// @} /// @name Resizing /// @{ /// Changes the size and/or position of this control /// @param newPosition New position of this control /// @param newExtent New size of this control virtual void resize(const Point2I &newPosition, const Point2I &newExtent); /// Changes the position of this control /// @param newPosition New position of this control virtual void setPosition( const Point2I &newPosition ); /// Changes the size of this control /// @param newExtent New size of this control virtual void setExtent( const Point2I &newExtent ); /// Changes the bounds of this control /// @param newBounds New bounds of this control virtual void setBounds( const RectI &newBounds ); /// Changes the X position of this control /// @param newXPosition New X Position of this control virtual void setLeft( S32 newLeft ); /// Changes the Y position of this control /// @param newYPosition New Y Position of this control virtual void setTop( S32 newTop ); /// Changes the width of this control /// @param newWidth New width of this control virtual void setWidth( S32 newWidth ); /// Changes the height of this control /// @param newHeight New Height of this control virtual void setHeight( S32 newHeight ); /// Called when a child control of the object is resized /// @param child Child object virtual void childResized(GuiControl *child); /// Called when this objects parent is resized /// @param oldParentExtent The old size of the parent object /// @param newParentExtent The new size of the parent object virtual void parentResized(const Point2I &oldParentExtent, const Point2I &newParentExtent); /// @} /// @name Rendering /// @{ /// Called when this control is to render itself /// @param offset The location this control is to begin rendering /// @param updateRect The screen area this control has drawing access to virtual void onRender(Point2I offset, const RectI &updateRect); virtual bool renderTooltip(Point2I cursorPos, const char* tipText = NULL ); /// Called when this control should render its children /// @param offset The location this control is to begin rendering /// @param updateRect The screen area this control has drawing access to void renderChildControls(Point2I offset, const RectI &updateRect); /// Sets the area (local coordinates) this control wants refreshed each frame /// @param pos UpperLeft point on rectangle of refresh area /// @param ext Extent of update rect void setUpdateRegion(Point2I pos, Point2I ext); /// Sets the update area of the control to encompass the whole control virtual void setUpdate(); /// @} //child hierarchy calls void awaken(); ///< Called when this control and its children have been wired up. void sleep(); ///< Called when this control is no more. void preRender(); ///< Prerender this control and all its children. /// @name Events /// /// If you subclass these, make sure to call the Parent::'s versions. /// /// @{ /// Called when this object is asked to wake up returns true if it's actually awake at the end virtual bool onWake(); /// Called when this object is asked to sleep virtual void onSleep(); /// Do special pre-render proecessing virtual void onPreRender(); /// Called when this object is removed virtual void onRemove(); /// Called when one of this objects children is removed virtual void onChildRemoved( GuiControl *child ); /// Called when this object is added to the scene bool onAdd(); /// Called when this object has a new child virtual void onChildAdded( GuiControl *child ); /// @} /// @name Console /// @{ /// Returns the value of the variable bound to this object virtual const char *getScriptValue(); /// Sets the value of the variable bound to this object virtual void setScriptValue(const char *value); /// @} /// @name Input (Keyboard/Mouse) /// @{ /// This function will return true if the provided coordinates (wrt parent object) are /// within the bounds of this control /// @param parentCoordPoint Coordinates to test virtual bool pointInControl(const Point2I& parentCoordPoint); /// Returns true if the global cursor is inside this control bool cursorInControl(); /// Returns the control which the provided point is under, with layering /// @param pt Point to test /// @param initialLayer Layer of gui objects to begin the search virtual GuiControl* findHitControl(const Point2I &pt, S32 initialLayer = -1); /// Lock the mouse within the provided control /// @param lockingControl Control to lock the mouse within void mouseLock(GuiControl *lockingControl); /// Turn on mouse locking with last used lock control void mouseLock(); /// Unlock the mouse void mouseUnlock(); /// Returns true if the mouse is locked bool isMouseLocked(); /// @} /// General input handler. virtual bool onInputEvent(const InputEvent &event); /// @name Mouse Events /// These functions are called when the input event which is /// in the name of the function occurs. /// @{ virtual void onMouseUp(const GuiEvent &event); virtual void onMouseDown(const GuiEvent &event); virtual void onMouseMove(const GuiEvent &event); virtual void onMouseDragged(const GuiEvent &event); virtual void onMouseEnter(const GuiEvent &event); virtual void onMouseLeave(const GuiEvent &event); virtual bool onMouseWheelUp(const GuiEvent &event); virtual bool onMouseWheelDown(const GuiEvent &event); virtual void onRightMouseDown(const GuiEvent &event); virtual void onRightMouseUp(const GuiEvent &event); virtual void onRightMouseDragged(const GuiEvent &event); virtual void onMiddleMouseDown(const GuiEvent &event); virtual void onMiddleMouseUp(const GuiEvent &event); virtual void onMiddleMouseDragged(const GuiEvent &event); /// @} /// @name Editor Mouse Events /// /// These functions are called when the input event which is /// in the name of the function occurs. Conversly from normal /// mouse events, these have a boolean return value that, if /// they return true, the editor will NOT act on them or be able /// to respond to this particular event. /// /// This is particularly useful for when writing controls so that /// they may become aware of the editor and allow customization /// of their data or appearance as if they were actually in use. /// For example, the GuiTabBookCtrl catches on mouse down to select /// a tab and NOT let the editor do any instant group manipulation. /// /// @{ /// Called when a mouseDown event occurs on a control and the GUI editor is active /// @param event the GuiEvent which caused the call to this function /// @param offset the offset which is representative of the units x and y that the editor takes up on screen virtual bool onMouseDownEditor(const GuiEvent &event, Point2I offset) { return false; }; /// Called when a mouseUp event occurs on a control and the GUI editor is active /// @param event the GuiEvent which caused the call to this function /// @param offset the offset which is representative of the units x and y that the editor takes up on screen virtual bool onMouseUpEditor(const GuiEvent &event, Point2I offset) { return false; }; /// Called when a rightMouseDown event occurs on a control and the GUI editor is active /// @param event the GuiEvent which caused the call to this function /// @param offset the offset which is representative of the units x and y that the editor takes up on screen virtual bool onRightMouseDownEditor(const GuiEvent &event, Point2I offset) { return false; }; /// Called when a mouseDragged event occurs on a control and the GUI editor is active /// @param event the GuiEvent which caused the call to this function /// @param offset the offset which is representative of the units x and y that the editor takes up on screen virtual bool onMouseDraggedEditor(const GuiEvent &event, Point2I offset) { return false; }; /// @} /// @name Tabs /// @{ /// Find the first tab-accessable child of this control virtual GuiControl* findFirstTabable(); /// Find the last tab-accessable child of this control /// @param firstCall Set to true to clear the global previous responder virtual GuiControl* findLastTabable(bool firstCall = true); /// Find previous tab-accessable control with respect to the provided one /// @param curResponder Current control /// @param firstCall Set to true to clear the global previous responder virtual GuiControl* findPrevTabable(GuiControl *curResponder, bool firstCall = true); /// Find next tab-accessable control with regards to the provided control. /// /// @param curResponder Current control /// @param firstCall Set to true to clear the global current responder virtual GuiControl* findNextTabable(GuiControl *curResponder, bool firstCall = true); /// @} /// Returns true if the provided control is a child (grandchild, or greatgrandchild) of this one. /// /// @param child Control to test virtual bool ControlIsChild(GuiControl *child); /// @name First Responder /// A first responder is the control which reacts first, in it's responder chain, to keyboard events /// The responder chain is set for each parent and so there is only one first responder amongst it's /// children. /// @{ /// Sets the first responder for child controls /// @param firstResponder First responder for this chain virtual void setFirstResponder(GuiControl *firstResponder); /// Sets up this control to be the first in it's group to respond to an input event /// @param value True if this should be a first responder virtual void makeFirstResponder(bool value); /// Returns true if this control is a first responder bool isFirstResponder(); /// Sets this object to be a first responder virtual void setFirstResponder(); /// Clears the first responder for this chain void clearFirstResponder(); /// Returns the first responder for this chain GuiControl *getFirstResponder() { return mFirstResponder; } /// Occurs when the first responder for this chain is lost virtual void onLoseFirstResponder(); /// @} /// @name Keyboard Events /// @{ /// Adds the accelerator key for this object to the canvas void addAcceleratorKey(); /// Adds this control's accelerator key to the accelerator map, and /// recursively tells all children to do the same. virtual void buildAcceleratorMap(); /// Occurs when the accelerator key for this control is pressed /// /// @param index Index in the acclerator map of the key virtual void acceleratorKeyPress(U32 index); /// Occurs when the accelerator key for this control is released /// /// @param index Index in the acclerator map of the key virtual void acceleratorKeyRelease(U32 index); /// Happens when a key is depressed /// @param event Event descriptor (which contains the key) virtual bool onKeyDown(const GuiEvent &event); /// Happens when a key is released /// @param event Event descriptor (which contains the key) virtual bool onKeyUp(const GuiEvent &event); /// Happens when a key is held down, resulting in repeated keystrokes. /// @param event Event descriptor (which contains the key) virtual bool onKeyRepeat(const GuiEvent &event); /// @} /// Sets the control profile for this control. /// /// @see GuiControlProfile /// @param prof Control profile to apply void setControlProfile(GuiControlProfile *prof); /// Occurs when this control performs its "action" virtual void onAction(); /// @name Peer Messaging /// Used to send a message to other GUIControls which are children of the same parent. /// /// This is mostly used by radio controls. /// @{ void messageSiblings(S32 message); ///< Send a message to all siblings virtual void onMessage(GuiControl *sender, S32 msg); ///< Receive a message from another control /// @} /// @name Canvas Events /// Functions called by the canvas /// @{ /// Called if this object is a dialog, when it is added to the visible layers virtual void onDialogPush(); /// Called if this object is a dialog, when it is removed from the visible layers virtual void onDialogPop(); /// @} /// Renders justified text using the profile. /// /// @note This should move into the graphics library at some point void renderJustifiedText(Point2I offset, Point2I extent, const char *text); void inspectPostApply(); void inspectPreApply(); }; #endif