tge/engine/gui/core/guiControl.h
2017-04-17 06:17:10 -06:00

615 lines
23 KiB
C++
Executable File

//-----------------------------------------------------------------------------
// 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