/* * This file is subject to the terms of the GFX License. If a copy of * the license was not distributed with this file, you can obtain one at: * * http://ugfx.io/license.html */ /* * @file src/gwin/gwin_class.h * @brief GWIN Graphic window subsystem header file. * * @defgroup Internal Internal * @ingroup GWIN * * @note These definitions are normally not used by an application program. They are useful * only if you want to create your own custom GWIN window or widget. * @note To access these definitions you must include "src/gwin/gwin_class.h" in your source file. * * @{ */ #ifndef _CLASS_GWIN_H #define _CLASS_GWIN_H #if GFX_USE_GWIN || defined(__DOXYGEN__) /** * @brief The predefined flags for a Window * @{ */ #define GWIN_FIRST_CONTROL_FLAG 0x00000001 /**< 8 bits free for the control to use. Don't change this value as it is relied upon definitions in widget header files. */ #define GWIN_LAST_CONTROL_FLAG 0x00000080 /**< 8 bits free for the control to use */ #define GWIN_FLG_VISIBLE 0x00000100 /**< The window is "visible" */ #define GWIN_FLG_SYSVISIBLE 0x00000200 /**< The window is visible after parents are tested */ #define GWIN_FLG_ENABLED 0x00000400 /**< The window is "enabled" */ #define GWIN_FLG_SYSENABLED 0x00000800 /**< The window is enabled after parents are tested */ #define GWIN_FLG_DYNAMIC 0x00001000 /**< The GWIN structure is allocated */ #define GWIN_FLG_ALLOCTXT 0x00002000 /**< The text/label is allocated */ #define GWIN_FLG_NEEDREDRAW 0x00004000 /**< Redraw is needed but has been delayed */ #define GWIN_FLG_BGREDRAW 0x00008000 /**< On redraw, if not visible redraw the revealed under-side */ #define GWIN_FLG_SUPERMASK 0x000F0000 /**< The bit mask to leave just the window superclass type */ #define GWIN_FLG_WIDGET 0x00010000 /**< This is a widget */ #define GWIN_FLG_CONTAINER 0x00020000 /**< This is a container */ #define GWIN_FLG_MINIMIZED 0x00100000 /**< The window is minimized */ #define GWIN_FLG_MAXIMIZED 0x00200000 /**< The window is maximized */ #define GWIN_FLG_MOUSECAPTURE 0x00400000 /**< The window has captured the mouse */ #define GWIN_FLG_FLASHING 0x00800000 /**< The window is flashing - see the _gwinFlashState boolean */ #define GWIN_FIRST_WM_FLAG 0x01000000 /**< 8 bits free for the window manager to use */ #define GWIN_LAST_WM_FLAG 0x80000000 /**< 8 bits free for the window manager to use */ /** @} */ /** * @brief The Virtual Method Table for a GWIN window * @{ */ typedef struct gwinVMT { const char * classname; /**< The GWIN classname (mandatory) */ gMemSize size; /**< The size of the class object */ void (*Destroy) (GWindowObject *gh); /**< The GWIN destroy function (optional) */ void (*Redraw) (GWindowObject *gh); /**< The GWIN redraw routine (optional) */ void (*AfterClear) (GWindowObject *gh); /**< The GWIN after-clear function (optional) */ } gwinVMT; /** @} */ #if GWIN_NEED_WIDGET || defined(__DOXYGEN__) /** * @brief An toggle/dial instance is not being used */ #define GWIDGET_NO_INSTANCE ((gU16)-1) /** * @brief The source handle that widgets use when sending events */ #define GWIDGET_SOURCE ((GSourceHandle)(void *)_gwidgetCreate) /** * @brief The Virtual Method Table for a widget * @note A widget must have a destroy function. Either use @p _gwidgetDestroy() or use your own function * which internally calls @p _gwidgetDestroy(). * @note A widget must have a redraw function. Use @p _gwidgetRedraw(). * @note If toggleroles != 0, ToggleAssign(), ToggleGet() and one or both of ToggleOff() and ToggleOn() must be specified. * @note If dialroles != 0, DialAssign(), DialGet() and DialMove() must be specified. * @{ */ typedef struct gwidgetVMT { struct gwinVMT g; /**< This is still a GWIN */ void (*DefaultDraw) (GWidgetObject *gw, void *param); /**< The default drawing routine (mandatory) */ #if GINPUT_NEED_MOUSE struct { void (*MouseDown) (GWidgetObject *gw, gCoord x, gCoord y); /**< Process mouse down events (optional) */ void (*MouseUp) (GWidgetObject *gw, gCoord x, gCoord y); /**< Process mouse up events (optional) */ void (*MouseMove) (GWidgetObject *gw, gCoord x, gCoord y); /**< Process mouse move events (optional) */ }; #endif #if GINPUT_NEED_KEYBOARD || GWIN_NEED_KEYBOARD struct { void (*KeyboardEvent) (GWidgetObject *gw, GEventKeyboard *pke); /**< Process keyboard events (optional) */ }; #endif #if GINPUT_NEED_TOGGLE struct { gU16 toggleroles; /**< The roles supported for toggles (0->toggleroles-1) */ void (*ToggleAssign) (GWidgetObject *gw, gU16 role, gU16 instance); /**< Assign a toggle to a role (optional) */ gU16 (*ToggleGet) (GWidgetObject *gw, gU16 role); /**< Return the instance for a particular role (optional) */ void (*ToggleOff) (GWidgetObject *gw, gU16 role); /**< Process toggle off events (optional) */ void (*ToggleOn) (GWidgetObject *gw, gU16 role); /**< Process toggle on events (optional) */ }; #endif #if GINPUT_NEED_DIAL struct { gU16 dialroles; /**< The roles supported for dials (0->dialroles-1) */ void (*DialAssign) (GWidgetObject *gw, gU16 role, gU16 instance); /**< Test the role and save the dial instance handle (optional) */ gU16 (*DialGet) (GWidgetObject *gw, gU16 role); /**< Return the instance for a particular role (optional) */ void (*DialMove) (GWidgetObject *gw, gU16 role, gU16 value, gU16 max); /**< Process dial move events (optional) */ }; #endif } gwidgetVMT; /** @} */ #endif #if GWIN_NEED_CONTAINERS || defined(__DOXYGEN__) /** * @brief The Virtual Method Table for a container * @note A container must have a destroy function. Either use @p _gcontainerDestroy() or use your own function * which internally calls @p _gcontainerDestroy(). * @note A container must have a gwin redraw function. Use @p _containerRedraw(). * @note If toggleroles != 0, ToggleAssign(), ToggleGet() and one or both of ToggleOff() and ToggleOn() must be specified. * @note If dialroles != 0, DialAssign(), DialGet() and DialMove() must be specified. * @{ */ typedef struct gcontainerVMT { gwidgetVMT gw; gCoord (*LeftBorder) (GHandle gh); /**< The size of the left border (mandatory) */ gCoord (*TopBorder) (GHandle gh); /**< The size of the top border (mandatory) */ gCoord (*RightBorder) (GHandle gh); /**< The size of the right border (mandatory) */ gCoord (*BottomBorder) (GHandle gh); /**< The size of the bottom border (mandatory) */ void (*NotifyAdd) (GHandle gh, GHandle ghChild); /**< Notification that a child has been added (optional) */ void (*NotifyDelete) (GHandle gh, GHandle ghChild); /**< Notification that a child has been deleted (optional) */ } gcontainerVMT; /** @} */ #endif #if GWIN_NEED_WINDOWMANAGER || defined(__DOXYGEN__) // @note There is only ever one instance of each GWindowManager type typedef struct GWindowManager { const struct gwmVMT *vmt; } GWindowManager; /** * @brief The Virtual Method Table for a window manager * @{ */ typedef struct gwmVMT { void (*Init) (void); /**< The window manager has just been set as the current window manager */ void (*DeInit) (void); /**< The window manager has just been removed as the current window manager */ gBool (*Add) (GHandle gh, const GWindowInit *pInit); /**< A window has been added */ void (*Delete) (GHandle gh); /**< A window has been deleted */ void (*Redraw) (GHandle gh); /**< A window needs to be redraw (or undrawn) */ void (*Size) (GHandle gh, gCoord w, gCoord h); /**< A window wants to be resized */ void (*Move) (GHandle gh, gCoord x, gCoord y); /**< A window wants to be moved */ void (*Raise) (GHandle gh); /**< A window wants to be on top */ void (*MinMax) (GHandle gh, GWindowMinMax minmax); /**< A window wants to be minimized/maximised */ } gwmVMT; /** @} */ /** * @brief The current window manager */ extern GWindowManager *_GWINwm; extern gBool _gwinFlashState; #endif /** * @brief Initialise (and allocate if necessary) the base GWIN object * * @param[in] g The GDisplay to use for this window * @param[in] pgw The GWindowObject structure. If NULL one is allocated from the heap * @param[in] pInit The user initialization parameters * @param[in] vmt The virtual method table for the GWIN object * @param[in] flags The default flags to use * * @return The GHandle of the created window * * @notapi */ GHandle _gwindowCreate(GDisplay *g, GWindowObject *pgw, const GWindowInit *pInit, const gwinVMT *vmt, gU32 flags); /** * @brief Redraw the window after a status change. * * @param[in] gh The widget to redraw * * @note Mark a window for redraw. * @note The window will get redrawn at some later time. * @note This call is designed to be fast and non-blocking * * @notapi */ void _gwinUpdate(GHandle gh); /** * @brief How to flush the redraws * @notes REDRAW_WAIT - Wait for a drawing session to be available * @notes REDRAW_NOWAIT - Do nothing if the drawing session is not available * @note REDRAW_INSESSION - We are already in a drawing session */ typedef enum GRedrawMethod { REDRAW_WAIT, REDRAW_NOWAIT, REDRAW_INSESSION } GRedrawMethod; /** * @brief Flush any pending redraws in the system. * * @param[in] how Do we wait for the lock? * * @note This call will attempt to flush any pending redraws * in the system. The doWait parameter tells this call * how to handle someone already holding the drawing lock. * If doWait is gTrue it waits to obtain the lock. If gFalse * and the drawing lock is free then the redraw is done * immediately. If the drawing lock was taken it will postpone the flush * on the basis that someone else will do it for us later. * * @notapi */ void _gwinFlushRedraws(GRedrawMethod how); /** * @brief Obtain a drawing session * @return gTrue if the drawing session was obtained, gFalse if the window is not visible * * @param[in] gh The window * * @note This function blocks until a drawing session is available if the window is visible */ gBool _gwinDrawStart(GHandle gh); /** * @brief Release a drawing session * * @param[in] gh The window */ void _gwinDrawEnd(GHandle gh); /** * @brief Destroy a window. * * @param[in] gh The window * @param[in] how Do we wait for the lock? * * @note If called without the drawing lock 'how' must be REDRAW_WAIT. * If called with the drawing lock 'how' must be REDRAW_INSESSION. * * @notapi */ void _gwinDestroy(GHandle gh, GRedrawMethod how); /** * @brief Add a window to the window manager and set its position and size * @return gTrue if successful * * @param[in] gh The window * @param[in] pInit The window init structure */ gBool _gwinWMAdd(GHandle gh, const GWindowInit *pInit); #if GWIN_NEED_WIDGET || defined(__DOXYGEN__) /** * @brief Initialise (and allocate if necessary) the base Widget object * * @param[in] g The GDisplay to display this window on * @param[in] pgw The GWidgetObject structure. If NULL one is allocated from the heap * @param[in] pInit The user initialization parameters * @param[in] vmt The virtual method table for the Widget object * * @return The GHandle of the created widget * * @notapi */ GHandle _gwidgetCreate(GDisplay *g, GWidgetObject *pgw, const GWidgetInit *pInit, const gwidgetVMT *vmt); /** * @brief Destroy the Widget object * * @param[in] gh The widget to destroy * * @notapi */ void _gwidgetDestroy(GHandle gh); /** * @brief Redraw the Widget object (VMT method only) * * @param[in] gh The widget to redraw * * @note Do not use this routine to update a widget after a status change. * Use @p _gwinUpdate() instead. This routine should only be used in the * VMT. * * @notapi */ void _gwidgetRedraw(GHandle gh); /** * @brief Send a standard GWIN event. * * @param[in] gh The window * @param[in] type The event type * * @note No consideration is given to recording EVENT LOST statuses. * * @notapi */ void _gwinSendEvent(GHandle gh, GEventType type); #if (GFX_USE_GINPUT && GINPUT_NEED_KEYBOARD) || GWIN_NEED_KEYBOARD || defined(__DOXYGEN__) /** * @brief Move the focus off the current focus window. * * @note The focus can stay on the same window if there is no other focusable window * * @notapi */ void _gwinMoveFocus(void); /** * @brief Do focus fixup's after a change of state for a window. * @details If a focus window has become invisible or disabled then * the focus must be taken away from it. If there is no focus * window and this window is eligible then this window becomes * the focus. * * @param[in] gh The window * * @note This routine does not actually do a redraw. It assumes that surrounding code * will because of the change of state that lead to this being called. * * @notapi */ void _gwinFixFocus(GHandle gh); /** * @brief Draw a simple focus rectangle in the default style. * * @param[in] gw The widget * @param[in] x, y The start x, y position (relative to the window) * @param[in] cx, cy The width & height of the rectangle * * @note Assumes the widget is in a state where it can draw. * @note Nothing is drawn if the window doesn't have focus. * @note The focus rectangle may be more than one pixel thick and may * not be a continuous line. * * @notapi */ void _gwidgetDrawFocusRect(GWidgetObject *gw, gCoord x, gCoord y, gCoord cx, gCoord cy); /** * @brief Draw a simple focus circle in the default style. * * @param[in] gw The widget * @param[in] radius The radius of the circle * * @note Assumes the widget is in a state where it can draw. * @note Nothing is drawn if the window doesn't have focus. * @note The focus circle may be more than one pixel thick. * * @notapi */ #if GDISP_NEED_CIRCLE void _gwidgetDrawFocusCircle(GWidgetObject *gx, gCoord radius); #endif #else #define _gwinFixFocus(gh) #define _gwidgetDrawFocusRect(gh,x,y,cx,cy) #define _gwidgetDrawFocusCircle(gh,radius) #endif #if GWIN_NEED_FLASHING || defined(__DOXYGEN__) /** * @brief Convert a chosen style color set pressed/enabled etc if flashing * @return The colorset - after flashing is taken into account * * @param[in] gw The widget * @param[in] pcol The style color set that has been chosen to reflect the state of the widget * @param[in] flashOffState Whether the off-state should be flashed as well. If false, only the * pressed color set is flashed. */ const GColorSet *_gwinGetFlashedColor(GWidgetObject *gw, const GColorSet *pcol, gBool flashOffState); #endif #else #define _gwinFixFocus(gh) #endif #if GWIN_NEED_CONTAINERS || defined(__DOXYGEN__) /** * @brief Initialise (and allocate if necessary) the base Container object * * @param[in] g The GDisplay to display this window on * @param[in] pgw The GContainerObject structure. If NULL one is allocated from the heap * @param[in] pInit The user initialization parameters * @param[in] vmt The virtual method table for the Container object * * @return The GHandle of the created widget * * @notapi */ GHandle _gcontainerCreate(GDisplay *g, GContainerObject *pgw, const GWidgetInit *pInit, const gcontainerVMT *vmt); /** * @brief Destroy the Container object * * @param[in] gh The container to destroy * * @notapi */ void _gcontainerDestroy(GHandle gh); /** * @brief Redraw the Container object (VMT method only) * * @param[in] gh The container to redraw * * @note Do not use this routine to update a container after a status change. * Use @p _gwinUpdate() instead. This routine should only be used in the * VMT. * * @notapi */ #define _gcontainerRedraw _gwidgetRedraw /** * @brief The visibility of something has changed. Ripple the changes. * * @note Does not actually trigger the redraw. It just marks as ready for redraw any * visibility changes. * * @notapi */ void _gwinRippleVisibility(void); #endif #endif /* GFX_USE_GWIN */ #endif /* _CLASS_GWIN_H */