The offical µGFX repository.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

439 lines
16 KiB

/*
* 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.org/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) */
size_t 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 ((uint16_t)-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, coord_t x, coord_t y); /**< Process mouse down events (optional) */
void (*MouseUp) (GWidgetObject *gw, coord_t x, coord_t y); /**< Process mouse up events (optional) */
void (*MouseMove) (GWidgetObject *gw, coord_t x, coord_t 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 {
uint16_t toggleroles; /**< The roles supported for toggles (0->toggleroles-1) */
void (*ToggleAssign) (GWidgetObject *gw, uint16_t role, uint16_t instance); /**< Assign a toggle to a role (optional) */
uint16_t (*ToggleGet) (GWidgetObject *gw, uint16_t role); /**< Return the instance for a particular role (optional) */
void (*ToggleOff) (GWidgetObject *gw, uint16_t role); /**< Process toggle off events (optional) */
void (*ToggleOn) (GWidgetObject *gw, uint16_t role); /**< Process toggle on events (optional) */
};
#endif
#if GINPUT_NEED_DIAL
struct {
uint16_t dialroles; /**< The roles supported for dials (0->dialroles-1) */
void (*DialAssign) (GWidgetObject *gw, uint16_t role, uint16_t instance); /**< Test the role and save the dial instance handle (optional) */
uint16_t (*DialGet) (GWidgetObject *gw, uint16_t role); /**< Return the instance for a particular role (optional) */
void (*DialMove) (GWidgetObject *gw, uint16_t role, uint16_t value, uint16_t 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;
coord_t (*LeftBorder) (GHandle gh); /**< The size of the left border (mandatory) */
coord_t (*TopBorder) (GHandle gh); /**< The size of the top border (mandatory) */
coord_t (*RightBorder) (GHandle gh); /**< The size of the right border (mandatory) */
coord_t (*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 */
bool_t (*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, coord_t w, coord_t h); /**< A window wants to be resized */
void (*Move) (GHandle gh, coord_t x, coord_t 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 bool_t _gwinFlashState;
#endif
#ifdef __cplusplus
extern "C" {
#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, uint32_t 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 TRUE it waits to obtain the lock. If FALSE
* 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 TRUE if the drawing session was obtained, FALSE 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
*/
bool_t _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 TRUE if successful
*
* @param[in] gh The window
* @param[in] pInit The window init structure
*/
bool_t _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, coord_t x, coord_t y, coord_t cx, coord_t cy);
#else
#define _gwinFixFocus(gh)
#define _gwidgetDrawFocusRect(gh,x,y,cx,cy)
#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, bool_t 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
#ifdef __cplusplus
}
#endif
#endif /* GFX_USE_GWIN */
#endif /* _CLASS_GWIN_H */
/** @} */