aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--demos/modules/gwin/widgets/gfxconf.h87
-rw-r--r--demos/modules/gwin/widgets/main.c140
-rw-r--r--demos/modules/gwin/widgets/readme.txt6
-rw-r--r--demos/readme.txt2
-rw-r--r--drivers/multiple/Win32/gdisp_lld.c4
-rw-r--r--gfxconf.example.h4
-rw-r--r--include/gfx_rules.h41
-rw-r--r--include/ginput/dial.h1
-rw-r--r--include/gqueue/gqueue.h44
-rw-r--r--include/gwin/button.h251
-rw-r--r--include/gwin/checkbox.h134
-rw-r--r--include/gwin/class_gwin.h192
-rw-r--r--include/gwin/console.h43
-rw-r--r--include/gwin/graph.h32
-rw-r--r--include/gwin/gwidget.h197
-rw-r--r--include/gwin/gwin.h968
-rw-r--r--include/gwin/internal.h41
-rw-r--r--include/gwin/options.h38
-rw-r--r--include/gwin/slider.h168
-rw-r--r--license.html384
-rw-r--r--src/gfx.c2
-rw-r--r--src/ginput/dial.c2
-rw-r--r--src/gqueue/gqueue.c37
-rw-r--r--src/gwin/button.c564
-rw-r--r--src/gwin/checkbox.c246
-rw-r--r--src/gwin/console.c56
-rw-r--r--src/gwin/graph.c73
-rw-r--r--src/gwin/gwidget.c376
-rw-r--r--src/gwin/gwin.c369
-rw-r--r--src/gwin/gwin.mk4
-rw-r--r--src/gwin/gwm.c144
-rw-r--r--src/gwin/slider.c467
32 files changed, 3239 insertions, 1878 deletions
diff --git a/demos/modules/gwin/widgets/gfxconf.h b/demos/modules/gwin/widgets/gfxconf.h
new file mode 100644
index 00000000..5c862441
--- /dev/null
+++ b/demos/modules/gwin/widgets/gfxconf.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2012, 2013, Joel Bodenmann aka Tectu <joel@unormal.org>
+ * Copyright (c) 2012, 2013, Andrew Hannam aka inmarket
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the <organization> nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _GFXCONF_H
+#define _GFXCONF_H
+
+#define GFX_USE_OS_CHIBIOS TRUE
+//#define GFX_USE_OS_WIN32 TRUE
+//#define GFX_USE_OS_POSIX TRUE
+
+/* GFX sub-systems to turn on */
+#define GFX_USE_GDISP TRUE
+#define GFX_USE_GWIN TRUE
+#define GFX_USE_GEVENT TRUE
+#define GFX_USE_GTIMER TRUE
+#define GFX_USE_GINPUT TRUE
+
+/* Features for the GDISP sub-system. */
+#define GDISP_NEED_VALIDATION TRUE
+#define GDISP_NEED_CLIP TRUE
+#define GDISP_NEED_TEXT TRUE
+#define GDISP_NEED_CIRCLE TRUE
+#define GDISP_NEED_ELLIPSE TRUE
+#define GDISP_NEED_ARC TRUE
+#define GDISP_NEED_CONVEX_POLYGON TRUE
+#define GDISP_NEED_SCROLL FALSE
+#define GDISP_NEED_PIXELREAD FALSE
+#define GDISP_NEED_CONTROL FALSE
+#define GDISP_NEED_IMAGE TRUE
+#define GDISP_NEED_MULTITHREAD TRUE
+#define GDISP_NEED_ASYNC FALSE
+#define GDISP_NEED_MSGAPI FALSE
+
+/* Builtin Fonts */
+#define GDISP_INCLUDE_FONT_SMALL FALSE
+#define GDISP_INCLUDE_FONT_LARGER FALSE
+#define GDISP_INCLUDE_FONT_UI1 FALSE
+#define GDISP_INCLUDE_FONT_UI2 TRUE
+#define GDISP_INCLUDE_FONT_LARGENUMBERS FALSE
+
+/* GDISP image decoders */
+#define GDISP_NEED_IMAGE_NATIVE FALSE
+#define GDISP_NEED_IMAGE_GIF TRUE
+#define GDISP_NEED_IMAGE_BMP FALSE
+#define GDISP_NEED_IMAGE_JPG FALSE
+#define GDISP_NEED_IMAGE_PNG FALSE
+
+/* Features for the GWIN sub-system. */
+#define GWIN_NEED_WINDOWMANAGER TRUE
+#define GWIN_NEED_CONSOLE TRUE
+#define GWIN_NEED_GRAPH FALSE
+#define GWIN_NEED_WIDGET TRUE
+#define GWIN_NEED_BUTTON TRUE
+#define GWIN_NEED_SLIDER TRUE
+#define GWIN_NEED_CHECKBOX TRUE
+
+/* Features for the GINPUT sub-system. */
+#define GINPUT_NEED_MOUSE TRUE
+#define GINPUT_NEED_TOGGLE TRUE
+#define GINPUT_NEED_DIAL FALSE
+
+#endif /* _GFXCONF_H */
diff --git a/demos/modules/gwin/widgets/main.c b/demos/modules/gwin/widgets/main.c
new file mode 100644
index 00000000..33c288f4
--- /dev/null
+++ b/demos/modules/gwin/widgets/main.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2012, 2013, Joel Bodenmann aka Tectu <joel@unormal.org>
+ * Copyright (c) 2012, 2013, Andrew Hannam aka inmarket
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the <organization> nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "gfx.h"
+
+static GListener gl;
+static GHandle ghConsole;
+static GHandle ghButton1, ghButton2, ghButton3, ghButton4;
+static GHandle ghSlider1, ghSlider2, ghSlider3, ghSlider4;
+static GHandle ghCheckbox1, ghCheckbox2;
+
+#define ScrWidth gdispGetWidth()
+#define ScrHeight gdispGetHeight()
+
+#define BUTTON_WIDTH 50
+#define BUTTON_HEIGHT 30
+#define SLIDER_WIDTH 20
+#define CHECKBOX_WIDTH 80
+#define CHECKBOX_HEIGHT 20
+
+int main(void) {
+ GEvent * pe;
+
+ // Initialize the display
+ gfxInit();
+ gdispClear(White);
+
+ // Set the widget defaults
+ gwinSetDefaultFont(gdispOpenFont("UI2"));
+ gwinSetDefaultColor(Black);
+ gwinSetDefaultBgColor(White);
+
+ // We want to listen for widget events
+ geventListenerInit(&gl);
+ gwinAttachListener(&gl);
+
+ // Connect the mouse
+ #if GINPUT_NEED_MOUSE
+ gwinAttachMouse(0);
+ #endif
+
+ // Create out gwin windows/widgets
+ ghConsole = gwinCreateConsole(NULL, ScrWidth/2+1, ScrHeight/2+1, ScrWidth/2-1, ScrHeight/2-1);
+ ghButton1 = gwinCreateButton(NULL, 0+0*(BUTTON_WIDTH+1), 0, BUTTON_WIDTH, BUTTON_HEIGHT);
+ ghButton2 = gwinCreateButton(NULL, 0+1*(BUTTON_WIDTH+1), 0, BUTTON_WIDTH, BUTTON_HEIGHT);
+ ghButton3 = gwinCreateButton(NULL, 0+2*(BUTTON_WIDTH+1), 0, BUTTON_WIDTH, BUTTON_HEIGHT);
+ ghButton4 = gwinCreateButton(NULL, 0+3*(BUTTON_WIDTH+1), 0, BUTTON_WIDTH, BUTTON_HEIGHT);
+ ghSlider1 = gwinCreateSlider(NULL, ScrWidth/2+1, ScrHeight/2-2*(SLIDER_WIDTH+1), ScrWidth/2-2, SLIDER_WIDTH);
+ ghSlider2 = gwinCreateSlider(NULL, ScrWidth/2+1, ScrHeight/2-1*(SLIDER_WIDTH+1), ScrWidth/2-2, SLIDER_WIDTH);
+ ghSlider3 = gwinCreateSlider(NULL, 0+0*(SLIDER_WIDTH+1), ScrHeight/2+1, SLIDER_WIDTH, ScrHeight/2-2);
+ ghSlider4 = gwinCreateSlider(NULL, 0+1*(SLIDER_WIDTH+1), ScrHeight/2+1, SLIDER_WIDTH, ScrHeight/2-2);
+ ghCheckbox1 = gwinCreateCheckbox(NULL, 0, BUTTON_HEIGHT+1, CHECKBOX_WIDTH, CHECKBOX_HEIGHT);
+ ghCheckbox2 = gwinCreateCheckbox(NULL, 0, BUTTON_HEIGHT+1+1*(CHECKBOX_HEIGHT+1), CHECKBOX_WIDTH, CHECKBOX_HEIGHT);
+
+ // Color everything and set special drawing for some widgets
+ gwinSetColor(ghConsole, Yellow);
+ gwinSetBgColor(ghConsole, Black);
+ gwinSetCustomDraw(ghCheckbox2, gwinCheckboxDraw_CheckOnRight, 0);
+
+ // Set the text on all the controls
+ gwinSetText(ghButton1, "B1", FALSE);
+ gwinSetText(ghButton2, "B2", FALSE);
+ gwinSetText(ghButton3, "B3", FALSE);
+ gwinSetText(ghButton4, "B4", FALSE);
+ gwinSetText(ghSlider1, "S1", FALSE);
+ gwinSetText(ghSlider2, "S2", FALSE);
+ gwinSetText(ghSlider3, "S3", FALSE);
+ gwinSetText(ghSlider4, "S4", FALSE);
+ gwinSetText(ghCheckbox1, "C1", FALSE);
+ gwinSetText(ghCheckbox2, "C2", FALSE);
+
+ // Assign toggles and dials to the buttons & sliders etc.
+ #if GINPUT_NEED_TOGGLE
+ gwinAttachToggle(ghButton1, 0, 0);
+ gwinAttachToggle(ghButton2, 0, 1);
+ #endif
+ #if GINPUT_NEED_DIAL
+ gwinAttachDial(ghSlider1, 0, 0);
+ gwinAttachDial(ghSlider3, 0, 1);
+ #endif
+
+ // Draw everything on the screen
+ gwinClear(ghConsole);
+ gwinSetVisible(ghButton1, TRUE);
+ gwinSetVisible(ghButton2, TRUE);
+ gwinSetVisible(ghButton3, TRUE);
+ gwinSetVisible(ghButton4, TRUE);
+ gwinSetVisible(ghSlider1, TRUE);
+ gwinSetVisible(ghSlider2, TRUE);
+ gwinSetVisible(ghSlider3, TRUE);
+ gwinSetVisible(ghSlider4, TRUE);
+ gwinSetVisible(ghCheckbox1, TRUE);
+ gwinSetVisible(ghCheckbox2, TRUE);
+
+ while(1) {
+ // Get an Event
+ pe = geventEventWait(&gl, TIME_INFINITE);
+
+ switch(pe->type) {
+ case GEVENT_GWIN_BUTTON:
+ gwinPrintf(ghConsole, "Button %s\n", gwinGetText(((GEventGWinButton *)pe)->button));
+ break;
+ case GEVENT_GWIN_SLIDER:
+ gwinPrintf(ghConsole, "Slider %s=%d\n", gwinGetText(((GEventGWinSlider *)pe)->slider), ((GEventGWinSlider *)pe)->position);
+ break;
+ case GEVENT_GWIN_CHECKBOX:
+ gwinPrintf(ghConsole, "Checkbox %s=%s\n", gwinGetText(((GEventGWinCheckbox *)pe)->checkbox), ((GEventGWinCheckbox *)pe)->isChecked ? "Checked" : "UnChecked");
+ break;
+ default:
+ gwinPrintf(ghConsole, "Unknown %d\n", pe->type);
+ break;
+ }
+ }
+ return 0;
+}
diff --git a/demos/modules/gwin/widgets/readme.txt b/demos/modules/gwin/widgets/readme.txt
new file mode 100644
index 00000000..02d733e9
--- /dev/null
+++ b/demos/modules/gwin/widgets/readme.txt
@@ -0,0 +1,6 @@
+This demo supports input from both a mouse/touch and/or a dial input.
+If your platform does not support one or the other, turn it off in
+gfxconf.h
+
+Note that you will need to include the drivers into your project
+makefile for whichever inputs you decide to use.
diff --git a/demos/readme.txt b/demos/readme.txt
index 5b2773db..3530c8e4 100644
--- a/demos/readme.txt
+++ b/demos/readme.txt
@@ -7,6 +7,7 @@ within each file:
/*
* Copyright (c) 2012, 2013, Joel Bodenmann aka Tectu <joel@unormal.org>
+ * Copyright (c) 2012, 2013, Andrew Hannam aka inmarket
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,3 +33,4 @@ within each file:
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+Files under the 3rdparty directory are licensed as per the original contributor.
diff --git a/drivers/multiple/Win32/gdisp_lld.c b/drivers/multiple/Win32/gdisp_lld.c
index 6923f08d..c528d7b4 100644
--- a/drivers/multiple/Win32/gdisp_lld.c
+++ b/drivers/multiple/Win32/gdisp_lld.c
@@ -119,8 +119,8 @@ static LRESULT myWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
break;
case WM_LBUTTONUP:
#if GINPUT_NEED_TOGGLE
- if ((toggles & 0xF0)) {
- toggles &= 0x0F;
+ if ((toggles & 0x0F)) {
+ toggles &= ~0x0F;
rect.left = 0;
rect.right = wWidth;
rect.top = wHeight;
diff --git a/gfxconf.example.h b/gfxconf.example.h
index 3cdd56fe..1797cadc 100644
--- a/gfxconf.example.h
+++ b/gfxconf.example.h
@@ -80,9 +80,11 @@
#define TDISP_NEED_MULTITHREAD FALSE
/* Features for the GWIN subsystem. */
-#define GWIN_NEED_BUTTON FALSE
+#define GWIN_NEED_WINDOWMANAGER FALSE
#define GWIN_NEED_CONSOLE FALSE
#define GWIN_NEED_GRAPH FALSE
+#define GWIN_NEED_WIDGET FALSE
+#define GWIN_NEED_BUTTON FALSE
#define GWIN_NEED_SLIDER FALSE
#define GWIN_NEED_CHECKBOX FALSE
diff --git a/include/gfx_rules.h b/include/gfx_rules.h
index 95874736..dfabe728 100644
--- a/include/gfx_rules.h
+++ b/include/gfx_rules.h
@@ -46,31 +46,50 @@
#warning "GWIN: Drawing can occur outside the defined windows as GDISP_NEED_CLIP is FALSE"
#endif
#endif
- #if GWIN_NEED_BUTTON
- #if !GDISP_NEED_TEXT
- #error "GWIN: GDISP_NEED_TEXT is required if GWIN_NEED_BUTTON is TRUE."
- #endif
- #if !GFX_USE_GEVENT
+ #if GWIN_NEED_BUTTON || GWIN_NEED_SLIDER || GWIN_NEED_CHECKBOX
+ #if !GWIN_NEED_WIDGET
#if GFX_DISPLAY_RULE_WARNINGS
- #warning "GWIN: GFX_USE_GEVENT is required if GWIN_NEED_BUTTON is TRUE. It has been turned on for you."
+ #warning "GWIN: GWIN_NEED_WIDGET is required when a Widget is used. It has been turned on for you."
#endif
- #undef GFX_USE_GEVENT
- #define GFX_USE_GEVENT TRUE
+ #undef GWIN_NEED_WIDGET
+ #define GWIN_NEED_WIDGET TRUE
+ #endif
+ #endif
+ #if GWIN_NEED_WIDGET
+ #if !GDISP_NEED_TEXT
+ #error "GWIN: GDISP_NEED_TEXT is required if GWIN_NEED_WIDGET is TRUE."
#endif
- #if !GFX_USE_GINPUT || !(GINPUT_NEED_MOUSE || GINPUT_NEED_TOGGLE)
+ #if !GFX_USE_GINPUT
+ // This test also ensures that GFX_USE_GEVENT is set
+ #error "GWIN: GFX_USE_GINPUT (and one or more input sources) is required if GWIN_NEED_WIDGET is TRUE"
+ #endif
+ #if !GWIN_NEED_WINDOWMANAGER
#if GFX_DISPLAY_RULE_WARNINGS
- #warning "GWIN: You have set GWIN_NEED_BUTTON to TRUE but no supported GINPUT (mouse/toggle) devices have been included"
+ #warning "GWIN: GWIN_NEED_WINDOWMANAGER is required if GWIN_NEED_WIDGET is TRUE. It has been turned on for you."
#endif
+ #undef GWIN_NEED_WINDOWMANAGER
+ #define GWIN_NEED_WINDOWMANAGER TRUE
#endif
#if !GDISP_NEED_MULTITHREAD && !GDISP_NEED_ASYNC
#if GFX_DISPLAY_RULE_WARNINGS
- #warning "GWIN: Either GDISP_NEED_MULTITHREAD or GDISP_NEED_ASYNC is required if GWIN_NEED_BUTTON is TRUE."
+ #warning "GWIN: Either GDISP_NEED_MULTITHREAD or GDISP_NEED_ASYNC is required if GWIN_NEED_WIDGET is TRUE."
#warning "GWIN: GDISP_NEED_MULTITHREAD has been turned on for you."
#endif
#undef GDISP_NEED_MULTITHREAD
#define GDISP_NEED_MULTITHREAD TRUE
#endif
#endif
+ #if GWIN_NEED_WINDOWMANAGER
+ #if !GFX_USE_GQUEUE || !GQUEUE_NEED_ASYNC
+ #if GFX_DISPLAY_RULE_WARNINGS
+ #warning "GWIN: GFX_USE_GQUEUE and GQUEUE_NEED_ASYNC is required if GWIN_NEED_WINDOWMANAGER is TRUE. It has been turned on for you."
+ #endif
+ #undef GFX_USE_GQUEUE
+ #undef GQUEUE_NEED_ASYNC
+ #define GFX_USE_GQUEUE TRUE
+ #define GQUEUE_NEED_ASYNC TRUE
+ #endif
+ #endif
#if GWIN_NEED_CONSOLE
#if !GDISP_NEED_TEXT
#error "GWIN: GDISP_NEED_TEXT is required if GWIN_NEED_CONSOLE is TRUE."
diff --git a/include/ginput/dial.h b/include/ginput/dial.h
index 19395789..38568994 100644
--- a/include/ginput/dial.h
+++ b/include/ginput/dial.h
@@ -36,6 +36,7 @@ typedef struct GEventDial_t {
GEventType type; // The type of this event (GEVENT_DIAL)
uint16_t instance; // The dial instance
uint16_t value; // The dial value
+ uint16_t maxvalue; // The maximum dial value
} GEventDial;
/*===========================================================================*/
diff --git a/include/gqueue/gqueue.h b/include/gqueue/gqueue.h
index 0f8f83ea..8ec3c9b9 100644
--- a/include/gqueue/gqueue.h
+++ b/include/gqueue/gqueue.h
@@ -91,7 +91,7 @@ void gfxQueueFSyncInit(gfxQueueFSync *pqueue);
/* @} */
/**
- * @brief Get an item from the head of the queue.
+ * @brief Get an item from the head of the queue (and remove it from the queue).
* @return NULL if the timeout expires before an item is available
*
* @param[in] pqueue A pointer to the queue
@@ -127,7 +127,7 @@ bool_t gfxQueueFSyncPut(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, delayti
/* @} */
/**
- * @brief Pop an item from the head of the queue.
+ * @brief Pop an item from the head of the queue (and remove it from the queue).
* @detail This is exactly the same as the Get operation above.
*
* @api
@@ -208,6 +208,46 @@ bool_t gfxQueueGSyncIsIn(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem);
bool_t gfxQueueFSyncIsIn(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem);
/* @} */
+/**
+ * @brief Get the first item from the head of the queue but do not remove it from the queue.
+ * @return NULL if no item is available.
+ *
+ * @param[in] pqueue A pointer to the queue
+ *
+ * @note This call does not block.
+ * @note This can be used as the first call to iterate all the elements in the queue.
+ * @note As that item is still on the queue, it should be treated as read-only. It could
+ * also be removed from the queue at any time by another thread (thereby altering the
+ * queue item).
+ *
+ * @api
+ * @{
+ */
+#define gfxQueueASyncPeek(pqueue) ((const gfxQueueASyncItem *)((pqueue)->head))
+#define gfxQueueGSyncPeek(pqueue) ((const gfxQueueGSyncItem *)((pqueue)->head))
+#define gfxQueueFSyncPeek(pqueue) ((const gfxQueueFSyncItem *)((pqueue)->head))
+/* @} */
+
+/**
+ * @brief Get the next item in the queue (but do not remove it from the queue).
+ * @return NULL if no item is available.
+ *
+ * @param[in] pitem The previous item in the queue
+ *
+ * @note This call does not block.
+ * @note This can be used as subsequent calls to iterate all the elements in the queue.
+ * @note As that item is still on the queue, it should be treated as read-only. It could
+ * also be removed from the queue at any time by another thread (thereby altering the
+ * queue item).
+ *
+ * @api
+ * @{
+ */
+#define gfxQueueASyncNext(pitem) ((const gfxQueueASyncItem *)((pitem)->next))
+#define gfxQueueGSyncNext(pitem) ((const gfxQueueGSyncItem *)((pitem)->next))
+#define gfxQueueFSyncNext(pitem) ((const gfxQueueFSyncItem *)((pitem)->next))
+/* @} */
+
#ifdef __cplusplus
}
#endif
diff --git a/include/gwin/button.h b/include/gwin/button.h
index 84994dc4..21de74bd 100644
--- a/include/gwin/button.h
+++ b/include/gwin/button.h
@@ -24,240 +24,141 @@
#ifndef _GWIN_BUTTON_H
#define _GWIN_BUTTON_H
-#if GWIN_NEED_BUTTON || defined(__DOXYGEN__)
+/* This file is included within "gwin/gwidget.h" */
-/*===========================================================================*/
-/* Driver constants. */
-/*===========================================================================*/
-
-#define GW_BUTTON 0x0002
+/**
+ * @brief The Event Type for a Button Event
+ */
#define GEVENT_GWIN_BUTTON (GEVENT_GWIN_FIRST+0)
-/*===========================================================================*/
-/* Type definitions */
-/*===========================================================================*/
-
-typedef struct GEventGWinButton_t {
+/**
+ * @brief A Button Event
+ * @note There are currently no GEventGWinButton listening flags - use 0 as the flags to @p gwinAttachListener()
+ */
+typedef struct GEventGWinButton {
GEventType type; // The type of this event (GEVENT_GWIN_BUTTON)
GHandle button; // The button that has been depressed (actually triggered on release)
} GEventGWinButton;
-// There are currently no GEventGWinButton listening flags - use 0
-
-typedef enum GButtonShape_e {
- GBTN_3D, GBTN_SQUARE, GBTN_ROUNDED, GBTN_ELLIPSE, GBTN_CUSTOM,
- GBTN_ARROW_UP, GBTN_ARROW_DOWN, GBTN_ARROW_LEFT, GBTN_ARROW_RIGHT,
-} GButtonShape;
-
-typedef struct GButtonDrawStyle_t {
+/**
+ * @brief Button colors
+ */
+typedef struct GButtonColors {
color_t color_edge;
color_t color_fill;
color_t color_txt;
-} GButtonDrawStyle;
-
-typedef enum GButtonType_e {
- GBTN_NORMAL, GBTN_TOGGLE
-} GButtonType;
-
-typedef enum GButtonState_e {
- GBTN_UP, GBTN_DOWN
-} GButtonState;
+} GButtonColors;
-typedef void (*GButtonDrawFunction)(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
-
-// A button window
+/**
+ * @brief The button widget structure
+ * @note Do not use the members directly - treat it as a black-box.
+ */
typedef struct GButtonObject_t {
- GWindowObject gwin;
-
- GButtonDrawStyle up;
- GButtonDrawStyle dn;
- GButtonState state;
- GButtonType type;
- const char *txt;
- GButtonDrawFunction fn;
- void *param;
- GListener listener;
+ GWidgetObject w;
+ uint16_t toggle;
+ GButtonColors c_up;
+ GButtonColors c_dn;
+ GButtonColors c_dis;
} GButtonObject;
-/*===========================================================================*/
-/* External declarations. */
-/*===========================================================================*/
-
#ifdef __cplusplus
extern "C" {
#endif
/**
- * @brief Create a button window.
+ * @brief Create a button widget.
* @return NULL if there is no resultant drawing area, otherwise a window handle.
*
* @param[in] gb The GButtonObject structure to initialise. If this is NULL the structure is dynamically allocated.
- * @param[in] x,y The screen co-ordinates for the bottom left corner of the window
+ * @param[in] x,y The screen co-ordinates for the top left corner of the window
* @param[in] width The width of the window
* @param[in] height The height of the window
- * @param[in] font The font to use
- * @param[in] type The type of button
- * @note The drawing color gets set to White and the background drawing color to Black.
+ *
+ * @note The drawing color and the background color get set to the current defaults. If you haven't called
+ * @p gwinSetDefaultColor() or @p gwinSetDefaultBgColor() then these are White and Black respectively.
+ * @note The font gets set to the current default font. If you haven't called @p gwinSetDefaultFont() then there
+ * is no default font and text drawing operations will no nothing.
* @note The dimensions and position may be changed to fit on the real screen.
- * @note The button is not automatically drawn. Call gwinButtonDraw() after changing the button style or setting the text.
+ * @note A button remembers its normal drawing state. If there is a window manager then it is automatically
+ * redrawn if the window is moved or its visibility state is changed.
+ * @note The button is initially marked as invisible so that more properties can be set before display.
+ * Call @p gwinSetVisible() to display it when ready.
+ * @note A button supports mouse and a toggle input.
+ * @note When assigning a toggle, only one toggle is supported. If you try to assign more than one toggle it will
+ * forget the previous toggle. When assigning a toggle the role parameter must be 0.
*
* @api
*/
-GHandle gwinCreateButton(GButtonObject *gb, coord_t x, coord_t y, coord_t width, coord_t height, font_t font, GButtonType type);
+GHandle gwinCreateButton(GButtonObject *gb, coord_t x, coord_t y, coord_t width, coord_t height);
/**
- * @brief Set the style of a button.
- * @details The button style is defined by its shape and colours.
+ * @brief Set the colors of a button.
*
- * @param[in] gh The window handle (must be a button window)
- * @param[in] shape The shape of the button.
- * @param[in] pUp The styling for the button when in the up state.
- * @param[in] pDown The styling for the button when in the down state.
+ * @param[in] gh The window handle (must be a button widget)
+ * @param[in] pUp The colors for the button when in the up state.
+ * @param[in] pDown The colors for the button when in the down state.
+ * @param[in] pDisabled The colors for the button when it is disabled.
*
* @note The button is not automatically redrawn. Call gwinButtonDraw() after changing the button style
* @note The button style is copied into the internal button structure - there is no need to
- * maintain a static style structures.
- * @note The pUp and pDown parameters can be NULL. If they are then the existing color styles
+ * maintain static style structures (they can be temporary structures on the stack).
+ * @note The pUp, pDown and pDisabled parameters can be NULL. If they are then the existing color styles
* are not changed for that button state.
+ * @note Some custom drawn buttons will ignore he specified colors
*
* @api
*/
-void gwinSetButtonStyle(GHandle gh, GButtonShape shape, const GButtonDrawStyle *pUp, const GButtonDrawStyle *pDown);
-
-/**
- * @brief Set the text of a button.
- *
- * @param[in] gh The window handle (must be a button window)
- * @param[in] txt The button text to set. This must be a constant string unless useAlloc is set.
- * @param[in] useAlloc If TRUE the string specified will be copied into dynamically allocated memory.
- * @note The button is not automatically redrawn. Call gwinButtonDraw() after changing the button text.
- *
- * @api
- */
-void gwinSetButtonText(GHandle gh, const char *txt, bool_t useAlloc);
-
-/**
- * @brief Redraw the button.
- *
- * @param[in] gh The window handle (must be a button window)
- *
- * @api
- */
-void gwinButtonDraw(GHandle gh);
-
-/**
- * @brief Enable or disable a button
- *
- * @param[in] gh The window handle (must be a button window)
- * @param[in] enabled Enable or disable the button
- *
- * @api
- */
-void gwinButtonSetEnabled(GHandle gh, bool_t enabled);
-
-/**
- * @brief Set the callback routine to perform a custom button drawing.
- *
- * @param[in] gh The window handle (must be a button window)
- * @param[in] fn The function to use to draw the button
- * @param[in] param A parameter to pass to the button drawing function
- *
- * @api
- */
-void gwinSetButtonCustom(GHandle gh, GButtonDrawFunction fn, void *param);
-
-/**
- * @brief Enable a button
- *
- * @api
- */
-#define gwinEnableButton(gh) gwinButtonSetEnabled( ((GButtonObject *)(gh)), TRUE)
-
-/**
- * @brief Disable a button
- *
- * @api
- */
-#define gwinDisableButton(gh) gwinButtonSetEnabled( ((GButtonObject *)(gh)), FALSE)
-
-/**
- * @brief Get the state of a button
- *
- * @param[in] gh The window handle (must be a button window)
- *
- * @api
- */
-#define gwinGetButtonState(gh) (((GButtonObject *)(gh))->state)
+void gwinSetButtonColors(GHandle gh, const GButtonColors *pUp, const GButtonColors *pDown, const GButtonColors *pDisabled);
/**
- * @brief Get the source handle of a button
- * @details Get the source handle of a button so the application can listen for events
+ * @brief Is the button current pressed
+ * @return TRUE if the button is depressed
*
- * @param[in] gh The window handle
+ * @param[in] gh The window handle (must be a button widget)
*
* @api
*/
-#define gwinGetButtonSource(gh) ((GSourceHandle)(gh))
-
-#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
- /**
- * @brief Attach a mouse to a button
- *
- * @param[in] gh The button handle
- * @param[in] instance The mouse instance
- *
- * @api
- */
- bool_t gwinAttachButtonMouse(GHandle gh, uint16_t instance);
-#endif
-
-#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
- /**
- * @brief Attach a toggle to a button
- *
- * @param[in] gh The button handle
- * @param[in] instance The toggle instance
- *
- * @api
- */
- bool_t gwinAttachButtonToggle(GHandle gh, uint16_t instance);
-#endif
+bool_t gwinIsButtonPressed(GHandle gh);
/**
- * @brief Standard button drawing routines
- * @details These routines are called to draw the standard button styles.
+ * @brief Some custom button drawing routines
+ * @details These function may be passed to @p gwinSetCustomDraw() to get different button drawing styles
*
- * @param[in] gh The button handle
- * @param[in] enabled Is the button currently enabled or disabled
- * @param[in] isdown Is the button currently down (depressed)
- * @param[in] txt The text to be display inside the button
- * @param[in] pstyle The current drawing style for the state we are in
+ * @param[in] gw The widget object (in this case a button)
* @param[in] param A parameter passed in from the user
*
* @note In your custom button drawing function you may optionally call these
* standard functions and then draw your extra details on top.
- * @note The standard functions below ignore the param parameter. It is there
- * only to ensure the functions match the GButtonDrawFunction type.
- * @note When called by a button press/release the framework ensure that it is
- * a button object and sets up clipping to the button object window. These
- * drawing routines then don't have to worry about explicitly doing that.
+ * @note The standard functions below ignore the param parameter except for @p gwinButtonDraw_Image().
+ * @note The image custom draw function @p gwinButtonDraw_Image() uses param to pass in the gdispImage pointer.
+ * The image must be already opened before calling @p gwinSetCustomDraw(). The image should be 3
+ * times the height of the button. The button image is repeated 3 times vertically, the first (top) for
+ * the "up" image, the 2nd for the "down" image, and the third (bottom) image for the disabled state. If
+ * the disabled state is never going to be used then the image can be just 2 times the button height.
+ * No checking is done to compare the size of the button to the size of the image.
+ * Note text is drawn on top of the image.
+ * @note These custom drawing routines don't have to worry about setting clipping as the framework
+ * sets clipping to the object window prior to calling these routines.
*
* @api
* @{
*/
-void gwinButtonDraw_3D(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
-void gwinButtonDraw_Square(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
+void gwinButtonDraw_3D(GWidgetObject *gw, void *param); // @< A standard 3D button
+void gwinButtonDraw_Box(GWidgetObject *gw, void *param); // @< A very simple box style button
#if GDISP_NEED_ARC || defined(__DOXYGEN__)
- void gwinButtonDraw_Rounded(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
+ void gwinButtonDraw_Rounded(GWidgetObject *gw, void *param); // @< A rounded rectangle button
#endif
#if GDISP_NEED_ELLIPSE || defined(__DOXYGEN__)
- void gwinButtonDraw_Ellipse(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
+ void gwinButtonDraw_Ellipse(GWidgetObject *gw, void *param); // @< A circular button
#endif
#if GDISP_NEED_CONVEX_POLYGON || defined(__DOXYGEN__)
- void gwinButtonDraw_ArrowUp(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
- void gwinButtonDraw_ArrowDown(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
- void gwinButtonDraw_ArrowLeft(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
- void gwinButtonDraw_ArrowRight(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
+ void gwinButtonDraw_ArrowUp(GWidgetObject *gw, void *param); // @< An up arrow button
+ void gwinButtonDraw_ArrowDown(GWidgetObject *gw, void *param); // @< A down arrow button
+ void gwinButtonDraw_ArrowLeft(GWidgetObject *gw, void *param); // @< A left arrow button
+ void gwinButtonDraw_ArrowRight(GWidgetObject *gw, void *param); // @< A right arrow button
+#endif
+#if GDISP_NEED_IMAGE || defined(__DOXYGEN__)
+ void gwinButtonDraw_Image(GWidgetObject *gw, void *param); // @< An image button - see the notes above on the param.
#endif
/** @} */
@@ -265,8 +166,6 @@ void gwinButtonDraw_Square(GHandle gh, bool_t enabled, bool_t isdown, const char
}
#endif
-#endif /* GWIN_NEED_BUTTON */
-
#endif /* _GWIN_BUTTON_H */
/** @} */
diff --git a/include/gwin/checkbox.h b/include/gwin/checkbox.h
index a17fb1ed..4a5e032a 100644
--- a/include/gwin/checkbox.h
+++ b/include/gwin/checkbox.h
@@ -12,7 +12,7 @@
* @defgroup Checkbox Checkbox
* @ingroup GWIN
*
- * @details GWIN allows it to easily create checkboxes.
+ * @details GWIN allows it to easily create a group of checkbox buttons.
*
* @pre GFX_USE_GWIN must be set to TRUE in your gfxconf.h
* @pre GWIN_NEED_CHECKBOX must be set to TRUE in your gfxconf.h
@@ -22,13 +22,12 @@
#ifndef _GWIN_CHECKBOX_H
#define _GWIN_CHECKBOX_H
-#if GWIN_NEED_CHECKBOX || defined(__DOXYGEN__)
+/* This file is included within "gwin/gwidget.h" */
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
-#define GW_CHECKBOX 0x0005
#define GEVENT_GWIN_CHECKBOX (GEVENT_GWIN_FIRST+2)
/*===========================================================================*/
@@ -41,124 +40,85 @@ typedef struct GEventGWinCheckbox_t {
bool_t isChecked; // Is the checkbox currently checked or unchecked?
} GEventGWinCheckbox;
-typedef enum GCheckboxState_e {
- GCHBX_UNCHECKED, GCHBX_CHECKED
-} GCheckboxState;
-
-typedef struct GCheckboxColor_t {
- color_t border;
- color_t checked;
- color_t bg;
-} GCheckboxColor;
-
-/* custom rendering interface */
-typedef void (*GCheckboxDrawFunction)(GHandle gh, bool_t enabled, bool_t state, void* param);
+typedef struct GCheckboxColors {
+ color_t color_border;
+ color_t color_checked;
+ color_t color_bg;
+ color_t color_txt;
+} GCheckboxColors;
/* A Checkbox window */
typedef struct GCheckboxObject_t {
- GWindowObject gwin;
- GListener listener;
-
- GCheckboxDrawFunction fn;
- GCheckboxColor *colors;
- bool_t isChecked;
- void *param;
+ GWidgetObject w;
+ uint16_t toggle;
+ GCheckboxColors c;
} GCheckboxObject;
/**
- * @brief Create a checkbox window.
+ * @brief Create a checkbox window.
+ * @return NULL if there is no resultant drawing area, otherwise a window handle.
*
* @param[in] gb The GCheckboxObject structure to initialise. If this is NULL, the structure is dynamically allocated.
- * @param[in] x,y The screen co-ordinates for the bottom left corner of the window
+ * @param[in] x,y The screen co-ordinates for the top left corner of the window
* @param[in] width The width of the window
* @param[in] height The height of the window
*
- * @note The checkbox is not automatically drawn. Call gwinCheckboxDraw() after changing the checkbox style.
- *
- * @return NULL if there is no resultant drawing area, otherwise a window handle.
+ * @note The drawing color and the background color get set to the current defaults. If you haven't called
+ * @p gwinSetDefaultColor() or @p gwinSetDefaultBgColor() then these are White and Black respectively.
+ * @note The font gets set to the current default font. If you haven't called @p gwinSetDefaultFont() then there
+ * is no default font and text drawing operations will no nothing.
+ * @note The dimensions and position may be changed to fit on the real screen.
+ * @note A checkbox remembers its normal drawing state. If there is a window manager then it is automatically
+ * redrawn if the window is moved or its visibility state is changed.
+ * @note The checkbox is initially marked as invisible so that more properties can be set before display.
+ * Call @p gwinSetVisible() to display it when ready.
+ * @note A checkbox supports mouse and a toggle input.
+ * @note When assigning a toggle, only one toggle is supported. If you try to assign more than one toggle it will
+ * forget the previous toggle. When assigning a toggle the role parameter must be 0.
*
* @api
*/
-GHandle gwinCheckboxCreate(GCheckboxObject *gb, coord_t x, coord_t y, coord_t width, coord_t height);
+GHandle gwinCreateCheckbox(GCheckboxObject *gb, coord_t x, coord_t y, coord_t width, coord_t height);
/**
- * @brief Redraw a checkbox
+ * @brief Get the state of a checkbox
+ * @return TRUE if the checkbox is currently checked
*
- * @param[in] gh The window handle (must be a checkbox window)
+ * @param[in] gh The window handle (must be a checkbox window)
*
* @api
*/
-void gwinCheckboxDraw(GHandle gh);
+bool_t gwinIsCheckboxChecked(GHandle gh);
/**
- * @brief Enable or disable a button
+ * @brief Set the colors used to draw the checkbox
*
* @param[in] gh The window handle (must be a checkbox window)
- * @param[in] enabled Enable or disable the button
+ * @param[in] pColors The colors to use
*
* @api
*/
-void gwinCheckboxSetEnabled(GHandle gh, bool_t enabled);
+void gwinCheckboxSetColors(GHandle gh, GCheckboxColors *pColors);
/**
- * @brief Set the callback routine to perform a custom drawing.
+ * @brief Some custom checkbox drawing routines
+ * @details These function may be passed to @p gwinSetCustomDraw() to get different checkbox drawing styles
*
- * @param[in] gh The window handle (must be a checkbox window)
- * @param[in] fn The function to use to draw the checkbox
- * @param[in] param A parameter to pass to the checkbox drawing function
+ * @param[in] gw The widget (which must be a checkbox)
+ * @param[in] param A parameter passed in from the user
*
- * @api
- */
-void gwinCheckboxSetCustom(GHandle gh, GCheckboxDrawFunction fn, void *param);
-
-/**
- * @brief Enable a checkbox
- *
- * @api
- */
-#define gwinCheckboxEnable(gh) gwinCheckboxSetEnabled( ((GCheckboxObject *)(gh)), TRUE)
-
-/**
- * @brief Disable a checkbox
- *
- * @api
-*/
-#define gwinCheckboxDisable(gh) gwinCheckboxSetEnabled( ((GCheckboxObject *)(gh)), FALSE)
-
-/**
- * @brief Get the state of a checkbox
- *
- * @param[in] gh The window handle (must be a checkbox window)
- *
- * @return The state of the checkbox (GCHBX_CHECKED or GCHBX_UNCHECKED)
- *
- * @api
- */
-#define gwinCheckboxGetState(gh) (((GCheckboxObject *)(gh))->isChecked)
-
-/**
- * @brief Get the source handle of a checkbox
- * @details Get the source handle of a checkbox so the application can listen for events
- *
- * @param[in] gh The window handle (must be a checkbox window)
+ * @note In your custom checkbox drawing function you may optionally call this
+ * standard functions and then draw your extra details on top.
+ * @note The standard functions below ignore the param parameter.
+ * @note These custom drawing routines don't have to worry about setting clipping as the framework
+ * sets clipping to the object window prior to calling these routines.
*
* @api
+ * @{
*/
-#define gwinCheckboxGetSource(gh) ((GSourceHandle)(gh))
-
-#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
- /**
- * @brief Attach a mouse to a checkbox
- *
- * @param[in] gh The checkbox handle
- * @param[in] instance The mouse instance
- *
- * @api
- */
- bool_t gwinCheckboxAttachMouse(GHandle gh, uint16_t instance);
-#endif /* GFX_USE_GINPUT && GINPUT_NEED_MOUSE */
-
-#endif /* _GWIN_NEED_CHECKBOX */
+void gwinCheckboxDraw_CheckOnLeft(GWidgetObject *gw, void *param);
+void gwinCheckboxDraw_CheckOnRight(GWidgetObject *gw, void *param);
+/* @} */
#endif /* _GWIN_CHECKBOX_H */
/** @} */
diff --git a/include/gwin/class_gwin.h b/include/gwin/class_gwin.h
new file mode 100644
index 00000000..eda69e1e
--- /dev/null
+++ b/include/gwin/class_gwin.h
@@ -0,0 +1,192 @@
+/*
+ * 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://chibios-gfx.com/license.html
+ */
+
+/**
+ * @file include/gwin/class_gwin.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 "gwin/class_gwin.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_FLG_DYNAMIC 0x0001 // @< The GWIN structure is allocated
+#define GWIN_FLG_VISIBLE 0x0002 // @< The window is visible
+#define GWIN_FLG_MINIMIZED 0x0004 // @< The window is minimized
+#define GWIN_FLG_MAXIMIZED 0x0008 // @< The window is maximized
+#define GWIN_FLG_WIDGET 0x0010 // @< This is a widget
+#define GWIN_FLG_ENABLED 0x0020 // @< The widget is enabled
+#define GWIN_FLG_ALLOCTXT 0x0040 // @< The widget text is allocated
+#define GWIN_FLG_MOUSECAPTURE 0x0080 // @< The widget has captured the mouse
+#define GWIN_FIRST_WM_FLAG 0x0100 // @< 4 bits free for the window manager to use
+#define GWIN_FIRST_CONTROL_FLAG 0x1000 // @< 4 bits free for Windows and Widgets to use
+/* @} */
+
+/**
+ * @brief The Virtual Method Table for a GWIN window
+ * @{
+ */
+typedef struct gwinVMT {
+ const char * classname; // @< The GWIN classname (mandatory)
+ 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)
+ 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)
+ };
+ 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)
+ };
+ 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)
+ };
+ } gwidgetVMT;
+ /* @} */
+#endif
+
+#if GWIN_NEED_WINDOWMANAGER || defined(__DOXYGEN__)
+ #if 1 // When we know that wmq is the first element of the GWindowObject structure
+ #define QItem2GWindow(qi) ((GHandle)qi)
+ #else
+ #define QItem2GWindow(qi) ((GHandle)(((char *)(qi)) - (size_t)(&(((GWindowObject *)0)->wmq))))
+ #endif
+
+ // @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, coord_t x, coord_t y, coord_t w, coord_t h); // @< A window has been added
+ void (*Delete) (GHandle gh); // @< A window has been deleted
+ void (*Visible) (GHandle gh); // @< A window has changed its visibility state
+ void (*Redim) (GHandle gh, coord_t x, coord_t y, coord_t w, coord_t h); // @< A window wants to be moved or resized
+ 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 list of all windows in the system
+ */
+ extern gfxQueueASync _GWINList;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Initialise (and allocate if necessary) the base GWIN object
+ *
+ * @param[in] pgw The GWindowObject structure. If NULL one is allocated from the heap
+ * @param[in] x, y The top left corner of the GWIN relative to the screen
+ * @param[in] w, h The width and height of the GWIN window
+ * @param[in] size The size of the GWIN object to allocate
+ * @param[in] vmt The virtual method table for the GWIN object
+ * @param[in] flags The default flags to use
+ *
+ * @notapi
+ */
+GHandle _gwindowCreate(GWindowObject *pgw, coord_t x, coord_t y, coord_t w, coord_t h, size_t size, const gwinVMT *vmt, uint16_t flags);
+
+#if GWIN_NEED_WIDGET || defined(__DOXYGEN__)
+ /**
+ * @brief Initialise (and allocate if necessary) the base Widget object
+ *
+ * @param[in] pgw The GWidgetObject structure. If NULL one is allocated from the heap
+ * @param[in] x, y The top left corner of the Widget relative to the screen
+ * @param[in] w, h The width and height of the Widget window
+ * @param[in] size The size of the Widget object to allocate
+ * @param[in] vmt The virtual method table for the Widget object
+ *
+ * @notapi
+ */
+ GHandle _gwidgetCreate(GWidgetObject *pgw, coord_t x, coord_t y, coord_t w, coord_t h, size_t size, 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
+ *
+ * @param[in] gh The widget to redraw
+ *
+ * @notapi
+ */
+ void _gwidgetRedraw(GHandle gh);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GFX_USE_GWIN */
+
+#endif /* _CLASS_GWIN_H */
+/** @} */
diff --git a/include/gwin/console.h b/include/gwin/console.h
index 9ea3eed6..5682113e 100644
--- a/include/gwin/console.h
+++ b/include/gwin/console.h
@@ -24,22 +24,13 @@
#ifndef _GWIN_CONSOLE_H
#define _GWIN_CONSOLE_H
-#if GWIN_NEED_CONSOLE || defined(__DOXYGEN__)
-
-/*===========================================================================*/
-/* Driver constants. */
-/*===========================================================================*/
-
-#define GW_CONSOLE 0x0001
-
-/*===========================================================================*/
-/* Type definitions */
-/*===========================================================================*/
+/* This file is included within "gwin/gwin.h" */
// A console window. Supports wrapped text writing and a cursor.
typedef struct GConsoleObject_t {
- GWindowObject gwin;
-
+ GWindowObject g;
+ coord_t cx, cy; // Cursor position
+
#if GFX_USE_OS_CHIBIOS && GWIN_CONSOLE_USE_BASESTREAM
struct GConsoleWindowStream_t {
const struct GConsoleWindowVMT_t *vmt;
@@ -47,15 +38,8 @@ typedef struct GConsoleObject_t {
} stream;
#endif
- coord_t cx,cy; // Cursor position
- uint8_t fy; // Current font height
- uint8_t fp; // Current font inter-character spacing
} GConsoleObject;
-/*===========================================================================*/
-/* External declarations. */
-/*===========================================================================*/
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -67,18 +51,23 @@ extern "C" {
* @return NULL if there is no resultant drawing area, otherwise a window handle.
*
* @param[in] gc The GConsoleObject structure to initialise. If this is NULL the structure is dynamically allocated.
- * @param[in] x,y The screen co-ordinates for the bottom left corner of the window
+ * @param[in] x,y The screen co-ordinates for the top left corner of the window
* @param[in] width The width of the window
* @param[in] height The height of the window
- * @param[in] font The font to use
- * @note The console is not automatically cleared on creation. You must do that by calling gwinClear() (possibly after changing your background color)
- * @note If the dispay does not support scrolling, the window will be cleared when the bottom line is reached.
- * @note The default drawing color gets set to White and the background drawing color to Black.
+ *
+ * @note The drawing color and the background color get set to the current defaults. If you haven't called
+ * @p gwinSetDefaultColor() or @p gwinSetDefaultBgColor() then these are White and Black respectively.
+ * @note The font gets set to the current default font. If you haven't called @p gwinSetDefaultFont() then there
+ * is no default font and text drawing operations will no nothing.
* @note The dimensions and position may be changed to fit on the real screen.
+ * @note On creation the window is marked as visible but is not automatically cleared. You may do that by calling @p gwinClear()
+ * (possibly after changing your background color)
+ * @note A console does not save the drawing state. It is not automatically redrawn if the window is moved or
+ * its visibility state is changed.
*
* @api
*/
-GHandle gwinCreateConsole(GConsoleObject *gc, coord_t x, coord_t y, coord_t width, coord_t height, font_t font);
+GHandle gwinCreateConsole(GConsoleObject *gc, coord_t x, coord_t y, coord_t width, coord_t height);
#if GFX_USE_OS_CHIBIOS && GWIN_CONSOLE_USE_BASESTREAM
/**
@@ -157,7 +146,5 @@ void gwinPrintf(GHandle gh, const char *fmt, ...);
}
#endif
-#endif /* GWIN_NEED_CONSOLE */
-
#endif /* _GWIN_CONSOLE_H */
/** @} */
diff --git a/include/gwin/graph.h b/include/gwin/graph.h
index e307187c..2595d2e7 100644
--- a/include/gwin/graph.h
+++ b/include/gwin/graph.h
@@ -22,20 +22,7 @@
#ifndef _GWIN_GRAPH_H
#define _GWIN_GRAPH_H
-#if GWIN_NEED_GRAPH || defined(__DOXYGEN__)
-
-/*===========================================================================*/
-/* Driver constants. */
-/*===========================================================================*/
-
-#define GW_GRAPH 0x0003
-
-/*===========================================================================*/
-/* Type definitions */
-/*===========================================================================*/
-
-// GDISP now has its own point structure
-#define GGraphPoint point
+/* This file is included within "gwin/gwin.h" */
typedef enum GGraphPointType_e {
GGRAPH_POINT_NONE, GGRAPH_POINT_DOT, GGRAPH_POINT_SQUARE, GGRAPH_POINT_CIRCLE
@@ -85,7 +72,7 @@ typedef struct GGraphStyle_t {
// A graph window
typedef struct GGraphObject_t {
- GWindowObject gwin;
+ GWindowObject g;
GGraphStyle style;
coord_t xorigin, yorigin;
coord_t lastx, lasty;
@@ -104,10 +91,19 @@ extern "C" {
* @return NULL if there is no resultant drawing area, otherwise a window handle.
*
* @param[in] gg The GGraphObject structure to initialise. If this is NULL the structure is dynamically allocated.
- * @param[in] x,y The screen co-ordinates for the bottom left corner of the window
+ * @param[in] x,y The screen co-ordinates for the top left corner of the window
* @param[in] width The width of the window
* @param[in] height The height of the window
- * @note The console is not automatically cleared on creation. You must do that by calling gwinClear() (possibly after changing your background color)
+ *
+ * @note The drawing color and the background color get set to the current defaults. If you haven't called
+ * @p gwinSetDefaultColor() or @p gwinSetDefaultBgColor() then these are White and Black respectively.
+ * @note The font gets set to the current default font. If you haven't called @p gwinSetDefaultFont() then there
+ * is no default font and text drawing operations will no nothing.
+ * @note The dimensions and position may be changed to fit on the real screen.
+ * @note On creation the window is marked as visible but is not automatically cleared. You may do that by calling @p gwinClear()
+ * (possibly after changing your background color)
+ * @note A graph does not save the drawing state. It is not automatically redrawn if the window is moved or
+ * its visibility state is changed.
* @note The coordinate system within the window for graphing operations (but not for any other drawing
* operation) is relative to the bottom left corner and then shifted right and up by the specified
* graphing x and y origin. Note that this system is inverted in the y direction relative to the display.
@@ -187,8 +183,6 @@ void gwinGraphDrawPoints(GHandle gh, const point *points, unsigned count);
}
#endif
-#endif /* GWIN_NEED_GRAPH */
-
#endif /* _GWIN_GRAPH_H */
/** @} */
diff --git a/include/gwin/gwidget.h b/include/gwin/gwidget.h
new file mode 100644
index 00000000..0c47dfde
--- /dev/null
+++ b/include/gwin/gwidget.h
@@ -0,0 +1,197 @@
+/*
+ * 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://chibios-gfx.com/license.html
+ */
+
+/**
+ * @file include/gwin/gwidget.h
+ * @brief GWIN Widgets header file.
+ */
+
+#ifndef _GWIDGET_H
+#define _GWIDGET_H
+
+/* This file is included within "gwin/gwin.h" */
+
+/**
+ * @defgroup Widget Widget
+ * @ingroup GWIN
+ *
+ * @details A Widget is a GWindow that supports interacting with the user
+ * via an input device such as a mouse or toggle buttons. It is the
+ * base class for widgets such as buttons and sliders.
+ *
+ * @pre GFX_USE_GWIN must be set to TRUE in your gfxconf.h
+ * @{
+ */
+
+// Forward definition
+struct GWidgetObject;
+
+/**
+ * @brief Defines a custom drawing function for a widget
+ */
+typedef void (*CustomWidgetDrawFunction)(struct GWidgetObject *gw, void *param);
+
+/**
+ * @brief The GWIN Widget structure
+ * @note A widget is a GWIN window that accepts user input.
+ * It also has a number of other properties such as its ability
+ * to redraw itself (a widget maintains drawing state).
+ * @note Do you access the members directly. Treat it as a black-box and use the method functions.
+ *
+ * @{
+ */
+typedef struct GWidgetObject {
+ GWindowObject g; // @< This is still a GWIN
+ const char * txt; // @< The widget text
+ CustomWidgetDrawFunction fnDraw; // @< The current draw function
+ void * fnParam; // @< A parameter for the current draw function
+} GWidgetObject;
+/* @} */
+
+/**
+ * A comment/rant on the above structure:
+ * We would really like the GWindowObject member to be anonymous. While this is
+ * allowed under the C11, C99, GNU and various other standards which have been
+ * around forever - compiler support often requires special flags e.g
+ * gcc requires the -fms-extensions flag (no wonder the language and compilers have
+ * not really progressed in 30 years). As portability is a key requirement
+ * we unfortunately won't use this useful feature in case we get a compiler that
+ * won't support it even with special flags.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Enable or disable a widget
+ *
+ * @param[in] gh The widget handle
+ * @param[in] enabled Enable or disable the widget
+ *
+ * @note The widget is automatically redrawn.
+ * @note Non-widgets will ignore this call.
+ *
+ * @api
+ */
+void gwinSetEnabled(GHandle gh, bool_t enabled);
+
+/**
+ * @brief Set the text of a widget.
+ *
+ * @param[in] gh The widget handle
+ * @param[in] txt The text to set. This must be a constant string unless useAlloc is set.
+ * @param[in] useAlloc If TRUE the string specified will be copied into dynamically allocated memory.
+ *
+ * @note The widget is automatically redrawn
+ * @note Non-widgets will ignore this call.
+ *
+ * @api
+ */
+void gwinSetText(GHandle gh, const char *txt, bool_t useAlloc);
+
+/**
+ * @brief Get the text of a widget.
+ * @return The widget text or NULL if it isn't a widget
+ *
+ * @param[in] gh The widget handle
+ *
+ * @api
+ */
+const char *gwinGetText(GHandle gh);
+
+/**
+ * @brief Set the routine to perform a custom widget drawing.
+ *
+ * @param[in] gh The widget handle
+ * @param[in] fn The function to use to draw the widget
+ * @param[in] param A parameter to pass to the widget drawing function
+ *
+ * @note The widget is not automatically redrawn. Call @p gwinDraw() to redraw the widget.
+ * @note Non-widgets will ignore this call.
+ *
+ * @api
+ */
+void gwinSetCustomDraw(GHandle gh, CustomWidgetDrawFunction fn, void *param);
+
+/**
+ * @brief Attach a Listener to listen for widget events
+ * @return TRUE on success
+ *
+ * @param[in] pl The listener
+ *
+ * @api
+ */
+bool_t gwinAttachListener(GListener *pl);
+
+#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
+ /**
+ * @brief Set the mouse to be used to control the widgets
+ * @return TRUE on success
+ *
+ * @param[in] instance The mouse instance
+ *
+ * @note Every widget uses the same mouse.
+ *
+ * @api
+ */
+ bool_t gwinAttachMouse(uint16_t instance);
+#endif
+
+#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
+ /**
+ * @brief Attach a toggle to a widget
+ * @return TRUE on success
+ *
+ * @param[in] gh The widget handle
+ * @param[in] role The function the toggle will perform for the widget
+ * @param[in] instance The toggle instance
+ *
+ * @note See the documentation on the specific widget to see the possible
+ * values for the role parameter. If it is out of range, this function
+ * will return FALSE
+ *
+ * @api
+ */
+ bool_t gwinAttachToggle(GHandle gh, uint16_t role, uint16_t instance);
+#endif
+
+#if GFX_USE_GINPUT && GINPUT_NEED_DIAL
+ /**
+ * @brief Attach a toggle to a widget
+ * @return TRUE on success
+ *
+ * @param[in] gh The widget handle
+ * @param[in] role The function the dial will perform for the widget
+ * @param[in] instance The dial instance
+ *
+ * @note See the documentation on the specific widget to see the possible
+ * values for the role parameter. If it is out of range, this function
+ * will return FALSE
+ *
+ * @api
+ */
+ bool_t gwinAttachDial(GHandle gh, uint16_t role, uint16_t instance);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Include extra widget types */
+#if GWIN_NEED_BUTTON || defined(__DOXYGEN__)
+ #include "gwin/button.h"
+#endif
+#if GWIN_NEED_SLIDER || defined(__DOXYGEN__)
+ #include "gwin/slider.h"
+#endif
+#if GWIN_NEED_CHECKBOX || defined(__DOXYGEN__)
+ #include "gwin/checkbox.h"
+#endif
+
+#endif /* _GWIDGET_H */
+/** @} */
diff --git a/include/gwin/gwin.h b/include/gwin/gwin.h
index 277dfab1..efce49fc 100644
--- a/include/gwin/gwin.h
+++ b/include/gwin/gwin.h
@@ -12,14 +12,12 @@
* @defgroup Window Window
* @ingroup GWIN
*
- * @details GWIN provides a basic window manager which allows it to easily
- * create and destroy different windows on runtime. Each window
- * will have it's own properties such as colors, brushes as well as
- * it's own drawing origin.
- * Moving the windows around is not supported yet.
+ * @details GWIN provides a basic window manager which allows it to easily
+ * create and destroy different windows at runtime. Each window
+ * will have it's own properties such as colors as well as
+ * it's own drawing origin.
*
* @pre GFX_USE_GWIN must be set to TRUE in your gfxconf.h
- *
* @{
*/
@@ -30,520 +28,716 @@
#if GFX_USE_GWIN || defined(__DOXYGEN__)
-/*===========================================================================*/
-/* Type definitions */
-/*===========================================================================*/
-
-typedef uint16_t GWindowType;
-#define GW_WINDOW 0x0000
-#define GW_FIRST_USER_WINDOW 0x8000
-
-// A basic window
-typedef struct GWindowObject_t {
- GWindowType type; // What type of window is this
- uint16_t flags; // Internal flags
- coord_t x, y; // Screen relative position
- coord_t width, height; // Dimensions of this window
- color_t color, bgcolor; // Current drawing colors
- bool_t enabled; // Enabled/Disabled state
-#if GDISP_NEED_TEXT
- font_t font; // Current font
-#endif
-} GWindowObject, * GHandle;
-
-/*===========================================================================*/
-/* External declarations. */
-/*===========================================================================*/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Base Functions */
-
-/**
- * @brief Create a basic window.
- * @return NULL if there is no resultant drawing area, otherwise a window handle.
- *
- * @param[in] gw The window structure to initialize. If this is NULL the structure is dynamically allocated.
- * @param[in] x,y The screen coordinates for the bottom left corner of the window
- * @param[in] width The width of the window
- * @param[in] height The height of the window
- * @note The default drawing color gets set to White and the background drawing color to Black.
- * @note No default font is set so make sure to set one before drawing any text.
- * @note The dimensions and position may be changed to fit on the real screen.
- * @note The window is not automatically cleared on creation. You must do that by calling gwinClear() (possibly after changing your background color)
- *
- * @api
- */
-GHandle gwinCreateWindow(GWindowObject *gw, coord_t x, coord_t y, coord_t width, coord_t height);
-
/**
- * @brief Destroy a window (of any type). Releases any dynamically allocated memory.
- *
- * @param[in] gh The window handle
- *
- * @api
- */
-void gwinDestroyWindow(GHandle gh);
-
-/**
- * @brief Enable or disable a widget (of any type).
- *
- * @param[in] gh The window handle
- * @param[in] enabled Enable or disable the widget
- *
- * @api
- */
-void gwinSetEnabled(GHandle gh, bool_t enabled);
-
-/**
- * @brief Get the X coordinate of the window
- * @details Returns the X coordinate of the origin of the window.
- * The coordinate is relative to the physical screen zero point.
- *
- * @param[in] gh The window
- */
-#define gwinGetScreenX(gh) ((gh)->x)
-
-/**
- * @brief Get the Y coordinate of the window
- * @details Returns the Y coordinate of the origin of the window.
- * The coordinate is relative to the physical screen zero point.
- *
- * @param[in] gh The window
- */
-#define gwinGetScreenY(gh) ((gh)->y)
-
-/**
- * @brief Get the width of the window
- *
- * @param[in] gh The window
- */
-#define gwinGetWidth(gh) ((gh)->width)
-
-/**
- * @brief Get the height of the window
- *
- * @param[in] gh The window
- */
-#define gwinGetHeight(gh) ((gh)->height)
-
-/**
- * @brief Set foreground color
- * @details Set the color which will be used to draw
- *
- * @param[in] gh The window
- * @param[in] clr The color to be set
+ * @brief A window object structure
+ * @note Do not access the members directly. Treat it as a black-box and use the method functions.
+ * @{
*/
-#define gwinSetColor(gh, clr) (gh)->color = (clr)
+typedef struct GWindowObject {
+ #if GWIN_NEED_WINDOWMANAGER
+ // This MUST be the first member of the struct
+ gfxQueueASyncItem wmq; // @< The next window (for the window manager)
+ #endif
+ const struct gwinVMT *vmt; // @< The VMT for this GWIN
+ coord_t x, y; // @< Screen relative position
+ coord_t width, height; // @< Dimensions of this window
+ color_t color, bgcolor; // @< The current drawing colors
+ uint16_t flags; // @< Window flags (the meaning is private to the GWIN class)
+ #if GDISP_NEED_TEXT
+ font_t font; // @< The current font
+ #endif
+} GWindowObject, * GHandle;
+/* @} */
/**
- * @brief Set background color
- * @details Set the color which will be used as background
- * @note gwinClear() must be called to set the background color
- *
- * @param[in] gh The window
- * @param[in] bgclr The background color
+ * @brief A window's minimized, maximized or normal size
*/
-#define gwinSetBgColor(gh, bgclr) (gh)->bgcolor = (bgclr)
+typedef enum { GWIN_NORMAL, GWIN_MAXIMIZE, GWIN_MINIMIZE } GWindowMinMax;
-/**
- * @brief Enable a window of any type
- *
- * @param[in] gh The window handle
- */
-#define gwinEnable(gh) gwinSetEnabled(gh, TRUE)
+#ifdef __cplusplus
+extern "C" {
+#endif
-/**
- * @brief Disable a window of any type
- *
- * @param[in] gh The window handle
- */
-#define gwinDisable(gh) gwinSetEnabled(gh, FALSE)
+/*-------------------------------------------------
+ * Window Manager functions
+ *-------------------------------------------------*/
-/* Set up for text */
+#if GWIN_NEED_WINDOWMANAGER
+ // Forward definition
+ struct GWindowManager;
-#if GDISP_NEED_TEXT || defined(__DOXYGEN__)
/**
- * @brief Set the current font for this window.
+ * @brief Set the window manager for the GWIN system.
*
- * @param[in] gh The window handle
- * @param[in] font The font to use for text functions
+ * @param[in] gwm The window manager to use. Can be NULL to turn off the existing window manager.
+ *
+ * @note A window manager is responsible for handling when window visibility is changed or
+ * a window is resized for moved. Note that only saved window states will be redrawn. Each
+ * window type can save different information (or none at all). See the documentation on each window
+ * type to see which information it saves (and can therefore be automatically redrawn).
+ * For window types that do not save any state information, the window manager determines what to do.
+ * Generally it will just clear the window to its background color.
*
* @api
*/
- void gwinSetFont(GHandle gh, font_t font);
+ void gwinSetWindowManager(struct GWindowManager *gwm);
#endif
-/* Drawing Functions */
+/*-------------------------------------------------
+ * Functions that affect all windows
+ *-------------------------------------------------*/
-/**
- * @brief Draw the window
- * @note Redraws the Window if the GWIN object has a draw routine
- *
- * @param[in] gh The window handle
- *
- * @api
- */
-void gwinDraw(GHandle gh);
+ /**
+ * @brief Set the default foreground color for all new GWIN windows
+ *
+ * @param[in] gh The window
+ * @param[in] clr The color to be set
+ *
+ * @api
+ */
+ void gwinSetDefaultColor(color_t clr);
-/**
- * @brief Clear the window
- * @note Uses the current background color to clear the window
- *
- * @param[in] gh The window handle
- *
- * @api
- */
-void gwinClear(GHandle gh);
+ /**
+ * @brief Set the default background color for all new GWIN windows
+ *
+ * @param[in] gh The window
+ * @param[in] bgclr The background color
+ *
+ * @api
+ */
+ void gwinSetDefaultBgColor(color_t bgclr);
-/**
- * @brief Set a pixel in the window
- * @note Uses the current foreground color to set the pixel
- * @note May leave GDISP clipping to this window's dimensions
- *
- * @param[in] gh The window handle
- * @param[in] x,y The coordinates of the pixel
- *
- * @api
- */
-void gwinDrawPixel(GHandle gh, coord_t x, coord_t y);
+ #if GDISP_NEED_TEXT || defined(__DOXYGEN__)
+ /**
+ * @brief Set the default font for all new GWIN windows
+ *
+ * @param[in] gh The window
+ *
+ * @api
+ */
+ void gwinSetDefaultFont(font_t font);
+ #endif
-/**
- * @brief Draw a line in the window
- * @note Uses the current foreground color to draw the line
- * @note May leave GDISP clipping to this window's dimensions
- *
- * @param[in] gh The window handle
- * @param[in] x0,y0 The start position
- * @param[in] x1,y1 The end position
- *
- * @api
- */
-void gwinDrawLine(GHandle gh, coord_t x0, coord_t y0, coord_t x1, coord_t y1);
-/**
- * @brief Draw a box in the window
- * @note Uses the current foreground color to draw the box
- * @note May leave GDISP clipping to this window's dimensions
- *
- * @param[in] gh The window handle
- * @param[in] x,y The start position
- * @param[in] cx,cy The size of the box (outside dimensions)
- *
- * @api
- */
-void gwinDrawBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy);
+/*-------------------------------------------------
+ * Base functions
+ *-------------------------------------------------*/
-/**
- * @brief Fill an rectangular area in the window
- * @note Uses the current foreground color to fill the box
- * @note May leave GDISP clipping to this window's dimensions
- *
- * @param[in] gh The window handle
- * @param[in] x,y The start position
- * @param[in] cx,cy The size of the box (outside dimensions)
- *
- * @api
- */
-void gwinFillArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy);
+ /**
+ * @brief Create a basic window.
+ * @return NULL if there is no resultant drawing area, otherwise a window handle.
+ *
+ * @param[in] pgw The window structure to initialize. If this is NULL the structure is dynamically allocated.
+ * @param[in] x,y The screen coordinates for the top left corner of the window
+ * @param[in] width The width of the window
+ * @param[in] height The height of the window
+ *
+ * @note The drawing color and the background color get set to the current defaults. If you haven't called
+ * @p gwinSetDefaultColor() or @p gwinSetDefaultBgColor() then these are White and Black respectively.
+ * @note The font gets set to the current default font. If you haven't called @p gwinSetDefaultFont() then there
+ * is no default font and text drawing operations will no nothing.
+ * @note The dimensions and position may be changed to fit on the real screen.
+ * @note On creation the window is marked as visible.
+ * @note A basic window does not save the drawing state. It is not automatically redrawn if the window is moved or
+ * its visibility state is changed.
+ *
+ * @api
+ */
+ GHandle gwinCreateWindow(GWindowObject *pgw, coord_t x, coord_t y, coord_t width, coord_t height);
-/**
- * @brief Fill an area in the window using the supplied bitmap.
- * @details The bitmap is in the pixel format specified by the low level driver
- * @note If GDISP_NEED_ASYNC is defined then the buffer must be static
- * or at least retained until this call has finished the blit. You can
- * tell when all graphics drawing is finished by @p gdispIsBusy() going FALSE.
- * @note May leave GDISP clipping to this window's dimensions
- *
- * @param[in] gh The window handle
- * @param[in] x, y The start filled area
- * @param[in] cx, cy The width and height to be filled
- * @param[in] srcx, srcy The bitmap position to start the fill from
- * @param[in] srccx The width of a line in the bitmap.
- * @param[in] buffer The pixels to use to fill the area.
- *
- * @api
- */
-void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer);
+ /**
+ * @brief Destroy a window (of any type). Releases any dynamically allocated memory.
+ *
+ * @param[in] gh The window handle
+ *
+ * @api
+ */
+ void gwinDestroy(GHandle gh);
-/* Circle Functions */
+ /**
+ * @brief Get the real class name of the GHandle
+ * @details Returns a string describing the object class.
+ *
+ * @param[in] gh The window
+ *
+ * @api
+ */
+ const char *gwinGetClassName(GHandle gh);
-#if GDISP_NEED_CIRCLE || defined(__DOXYGEN__)
/**
- * @brief Draw a circle in the window.
- * @note Uses the current foreground color to draw the circle
- * @note May leave GDISP clipping to this window's dimensions
+ * @brief Get an ID that uniquely describes the class of the GHandle
*
- * @param[in] gh The window handle
- * @param[in] x, y The center of the circle
- * @param[in] radius The radius of the circle
+ * @param[in] gh The window
*
* @api
*/
- void gwinDrawCircle(GHandle gh, coord_t x, coord_t y, coord_t radius);
+ #define gwinGetClassID(gh) ((void *)((gh)->vmt))
/**
- * @brief Draw a filled circle in the window.
- * @note Uses the current foreground color to draw the filled circle
- * @note May leave GDISP clipping to this window's dimensions
+ * @brief Get the X coordinate of the window
+ * @details Returns the X coordinate of the origin of the window.
+ * The coordinate is relative to the physical screen zero point.
*
- * @param[in] gh The window handle
- * @param[in] x, y The center of the circle
- * @param[in] radius The radius of the circle
+ * @param[in] gh The window
*
* @api
*/
- void gwinFillCircle(GHandle gh, coord_t x, coord_t y, coord_t radius);
-#endif
+ #define gwinGetScreenX(gh) ((gh)->x)
-/* Ellipse Functions */
+ /**
+ * @brief Get the Y coordinate of the window
+ * @details Returns the Y coordinate of the origin of the window.
+ * The coordinate is relative to the physical screen zero point.
+ *
+ * @param[in] gh The window
+ *
+ * @api
+ */
+ #define gwinGetScreenY(gh) ((gh)->y)
-#if GDISP_NEED_ELLIPSE || defined(__DOXYGEN__)
/**
- * @brief Draw an ellipse.
- * @note Uses the current foreground color to draw the ellipse
- * @note May leave GDISP clipping to this window's dimensions
+ * @brief Get the width of the window
*
- * @param[in] gh The window handle
- * @param[in] x,y The center of the ellipse
- * @param[in] a,b The dimensions of the ellipse
+ * @param[in] gh The window
*
* @api
*/
- void gwinDrawEllipse(GHandle gh, coord_t x, coord_t y, coord_t a, coord_t b);
+ #define gwinGetWidth(gh) ((gh)->width)
/**
- * @brief Draw an filled ellipse.
- * @note Uses the current foreground color to draw the filled ellipse
- * @note May leave GDISP clipping to this window's dimensions
+ * @brief Get the height of the window
*
- * @param[in] gh The window handle
- * @param[in] x,y The center of the ellipse
- * @param[in] a,b The dimensions of the ellipse
+ * @param[in] gh The window
*
* @api
*/
- void gwinFillEllipse(GHandle gh, coord_t x, coord_t y, coord_t a, coord_t b);
-#endif
+ #define gwinGetHeight(gh) ((gh)->height)
-/* Arc Functions */
+ /**
+ * @brief Set foreground color
+ * @details Set the color which will be used to draw
+ *
+ * @param[in] gh The window
+ * @param[in] clr The color to be set
+ *
+ * @api
+ */
+ #define gwinSetColor(gh, clr) (gh)->color = (clr)
-#if GDISP_NEED_ARC || defined(__DOXYGEN__)
- /*
- * @brief Draw an arc in the window.
- * @note Uses the current foreground color to draw the arc
- * @note May leave GDISP clipping to this window's dimensions
+ /**
+ * @brief Set background color
+ * @details Set the color which will be used as background
+ * @note gwinClear() must be called to set the background color
*
- * @param[in] gh The window handle
- * @param[in] x,y The center point
- * @param[in] radius The radius of the arc
- * @param[in] start The start angle (0 to 360)
- * @param[in] end The end angle (0 to 360)
+ * @param[in] gh The window
+ * @param[in] bgclr The background color
*
* @api
*/
- void gwinDrawArc(GHandle gh, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle);
+ #define gwinSetBgColor(gh, bgclr) (gh)->bgcolor = (bgclr)
- /*
- * @brief Draw a filled arc in the window.
- * @note Uses the current foreground color to draw the filled arc
- * @note May leave GDISP clipping to this window's dimensions
+ /**
+ * @brief Sets whether a window is visible or not
*
- * @param[in] gh The window handle
- * @param[in] x,y The center point
- * @param[in] radius The radius of the arc
- * @param[in] start The start angle (0 to 360)
- * @param[in] end The end angle (0 to 360)
+ * @param[in] gh The window
+ * @param[in] visible Whether the window should be visible or not
+ *
+ * @note When a window is marked as not visible, drawing operations
+ * on the window do nothing.
+ * @note When a window is marked as visible, it is not automatically
+ * redrawn as many window types don't remember their drawing state.
+ * Widgets such as Buttons, Sliders etc will be redrawn.
+ * @note If there is no window manager in use, when a window is marked
+ * as not visible, nothing is done to remove the window from the screen.
+ * When there is a window manager, it is up to the window manager to
+ * handle what happens.
*
* @api
*/
- void gwinFillArc(GHandle gh, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle);
-#endif
+ void gwinSetVisible(GHandle gh, bool_t visible);
-/* Read a pixel Function */
+ /**
+ * @brief Gets the visibility of a window
+ * @return TRUE if visible
+ *
+ * @param[in] gh The window
+ *
+ * @api
+ */
+ bool_t gwinGetVisible(GHandle gh);
-#if GDISP_NEED_PIXELREAD || defined(__DOXYGEN__)
/**
- * @brief Get the color of a pixel in the window.
- * @return The color of the pixel.
- * @note May leave GDISP clipping to this window's dimensions
+ * @brief Move a window
*
- * @param[in] gh The window handle
- * @param[in] x,y The position in the window
+ * @param[in] gh The window
+ * @param[in] x, y The new position (screen relative) for this window
+ *
+ * @note The final window position may not be the requested position. Windows
+ * are clipped to the screen area and the window manager may also affect the position.
+ * @note The window is redrawn if it is visible. See the comments in @p gwinSetVisible()
+ * with regard to what can be redrawn and what can't.
+ * @note It is up to the window manager to determine what happens with the screen area
+ * uncovered by moving the window. When there is no window manager, nothing
+ * is done with the uncovered area.
*
* @api
*/
- color_t gwinGetPixelColor(GHandle gh, coord_t x, coord_t y);
-#endif
+ void gwinMove(GHandle gh, coord_t x, coord_t y);
-/* Extra Text Functions */
+ /**
+ * @brief Resize a window
+ *
+ * @param[in] gh The window
+ * @param[in] width, height The new size of the window
+ *
+ * @note The final window size may not be the requested size. Windows
+ * are clipped to the screen area and the window manager may also affect the size.
+ * @note The window is redrawn if it is visible. See the comments in @p gwinSetVisible()
+ * with regard to what can be redrawn and what can't.
+ * @note It is up to the window manager to determine what happens with any screen area
+ * uncovered by resizing the window. When there is no window manager, nothing
+ * is done with the uncovered area.
+ *
+ * @api
+ */
+ void gwinResize(GHandle gh, coord_t width, coord_t height);
-#if GDISP_NEED_TEXT || defined(__DOXYGEN__)
/**
- * @brief Draw a text character at the specified position in the window.
- * @pre The font must have been set.
- * @note Uses the current foreground color to draw the character
- * @note May leave GDISP clipping to this window's dimensions
+ * @brief Minimize, Maximize or Restore a window
*
- * @param[in] gh The window handle
- * @param[in] x,y The position for the text
- * @param[in] c The character to draw
+ * @param[in] gh The window
+ * @param[in] minmax The new minimized/maximized state
+ *
+ * @note The final window state may not be the requested state. Window Managers
+ * do not need to implement changing the minmax state. If there is no
+ * window manager this call is ignored.
+ * @note The window is redrawn if it is changed. See the comments in @p gwinSetVisible()
+ * with regard to what can be redrawn and what can't.
+ * @note It is up to the window manager to determine what happens with any screen area
+ * uncovered by resizing the window.
+ * @note When a window is minimised it may be asked to draw the window or the window
+ * manager may draw the minimised window.
*
* @api
*/
- void gwinDrawChar(GHandle gh, coord_t x, coord_t y, char c);
+ void gwinSetMinMax(GHandle gh, GWindowMinMax minmax);
/**
- * @brief Draw a text character with a filled background at the specified position in the window.
- * @pre The font must have been set.
- * @note Uses the current foreground color to draw the character and fills the background using the background drawing color
- * @note May leave GDISP clipping to this window's dimensions
+ * @brief Get the Minimized/Maximized state of a window
*
- * @param[in] gh The window handle
- * @param[in] x,y The position for the text
- * @param[in] c The character to draw
+ * @param[in] gh The window
*
* @api
*/
- void gwinFillChar(GHandle gh, coord_t x, coord_t y, char c);
+ GWindowMinMax gwinGetMinMax(GHandle gh);
/**
- * @brief Draw a text string in the window
- * @pre The font must have been set.
- * @note Uses the current foreground color to draw the character
- * @note May leave GDISP clipping to this window's dimensions
+ * @brief Raise a window to the top of the z-order
*
- * @param[in] gh The window handle
- * @param[in] x,y The position for the text
- * @param[in] str The string to draw
+ * @param[in] gh The window
+ *
+ * @note The window z-order is only supported by some window managers. If there is no
+ * window manager this call simple tries to redraw the window. See the comments
+ * in @p gwinSetVisible() with regard to what can be redrawn and what can't.
*
* @api
*/
- void gwinDrawString(GHandle gh, coord_t x, coord_t y, const char *str);
+ void gwinRaise(GHandle gh);
+
+ #if GDISP_NEED_TEXT || defined(__DOXYGEN__)
+ /**
+ * @brief Set the current font for this window.
+ *
+ * @param[in] gh The window handle
+ * @param[in] font The font to use for text functions
+ *
+ * @api
+ */
+ void gwinSetFont(GHandle gh, font_t font);
+ #endif
+
+/*-------------------------------------------------
+ * Drawing functions
+ *-------------------------------------------------*/
/**
- * @brief Draw a text string with a filled background in the window
- * @pre The font must have been set.
- * @note Uses the current foreground color to draw the character and fills the background using the background drawing color
- * @note May leave GDISP clipping to this window's dimensions
+ * @brief Clear the window
+ * @note Uses the current background color to clear the window
*
* @param[in] gh The window handle
- * @param[in] x,y The position for the text
- * @param[in] str The string to draw
*
* @api
*/
- void gwinFillString(GHandle gh, coord_t x, coord_t y, const char *str);
+ void gwinClear(GHandle gh);
/**
- * @brief Draw a text string verticly centered within the specified box.
- * @pre The font must have been set.
- * @note Uses the current foreground color to draw the character.
- * @note The specified box does not need to align with the window box
+ * @brief Set a pixel in the window
+ * @note Uses the current foreground color to set the pixel
* @note May leave GDISP clipping to this window's dimensions
*
* @param[in] gh The window handle
- * @param[in] x,y The position for the text (need to define top-right or base-line - check code)
- * @param[in] cx,cy The width and height of the box
- * @param[in] str The string to draw
- * @param[in] justify Justify the text left, center or right within the box
+ * @param[in] x,y The coordinates of the pixel
*
* @api
*/
- void gwinDrawStringBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, justify_t justify);
+ void gwinDrawPixel(GHandle gh, coord_t x, coord_t y);
/**
- * @brief Draw a text string verticly centered within the specified filled box.
- * @pre The font must have been set.
- * @note Uses the current foreground color to draw the character and fills the background using the background drawing color
- * @note The entire box is filled. Note this box does not need to align with the window box
+ * @brief Draw a line in the window
+ * @note Uses the current foreground color to draw the line
* @note May leave GDISP clipping to this window's dimensions
*
* @param[in] gh The window handle
- * @param[in] x,y The position for the text (need to define top-right or base-line - check code)
- * @param[in] cx,cy The width and height of the box
- * @param[in] str The string to draw
- * @param[in] justify Justify the text left, center or right within the box
+ * @param[in] x0,y0 The start position
+ * @param[in] x1,y1 The end position
*
* @api
*/
- void gwinFillStringBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, justify_t justify);
-#endif
+ void gwinDrawLine(GHandle gh, coord_t x0, coord_t y0, coord_t x1, coord_t y1);
-#if GDISP_NEED_CONVEX_POLYGON || defined(__DOXYGEN__)
/**
- * @brief Draw an enclosed polygon (convex, non-convex or complex).
- *
- * @note Uses the current foreground color.
+ * @brief Draw a box in the window
+ * @note Uses the current foreground color to draw the box
+ * @note May leave GDISP clipping to this window's dimensions
*
* @param[in] gh The window handle
- * @param[in] tx, ty Transform all points in pntarray by tx, ty
- * @param[in] pntarray An array of points
- * @param[in] cnt The number of points in the array
+ * @param[in] x,y The start position
+ * @param[in] cx,cy The size of the box (outside dimensions)
*
* @api
*/
- void gwinDrawPoly(GHandle gh, coord_t tx, coord_t ty, const point *pntarray, unsigned cnt);
+ void gwinDrawBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy);
/**
- * @brief Fill a convex polygon
- * @details Doesn't handle non-convex or complex polygons.
- *
- * @note Uses the current foreground color.
+ * @brief Fill an rectangular area in the window
+ * @note Uses the current foreground color to fill the box
+ * @note May leave GDISP clipping to this window's dimensions
*
* @param[in] gh The window handle
- * @param[in] tx, ty Transform all points in pntarray by tx, ty
- * @param[in] pntarray An array of points
- * @param[in] cnt The number of points in the array
- *
- * @note Convex polygons are those that have no internal angles. That is;
- * you can draw a line from any point on the polygon to any other point
- * on the polygon without it going outside the polygon. In our case we generalise
- * this a little by saying that an infinite horizontal line (at any y value) will cross
- * no more than two edges on the polygon. Some non-convex polygons do fit this criteria
- * and can therefore be drawn.
- * @note This routine is designed to be very efficient with even simple display hardware.
+ * @param[in] x,y The start position
+ * @param[in] cx,cy The size of the box (outside dimensions)
*
* @api
*/
- void gwinFillConvexPoly(GHandle gh, coord_t tx, coord_t ty, const point *pntarray, unsigned cnt);
-#endif
+ void gwinFillArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy);
-#if GDISP_NEED_IMAGE || defined(__DOXYGEN__)
/**
- * @brief Draw the image
- * @return GDISP_IMAGE_ERR_OK (0) on success or an error code.
+ * @brief Fill an area in the window using the supplied bitmap.
+ * @details The bitmap is in the pixel format specified by the low level driver
+ * @note If GDISP_NEED_ASYNC is defined then the buffer must be static
+ * or at least retained until this call has finished the blit. You can
+ * tell when all graphics drawing is finished by @p gdispIsBusy() going FALSE.
+ * @note May leave GDISP clipping to this window's dimensions
*
* @param[in] gh The window handle
- * @param[in] img The image structure
- * @param[in] x,y The window location to draw the image
- * @param[in] cx,cy The area on the screen to draw
- * @param[in] sx,sy The image position to start drawing at
- *
- * @pre gdispImageOpen() must have returned successfully.
- *
- * @note If sx,sy + cx,cy is outside the image boundaries the area outside the image
- * is simply not drawn.
- * @note If @p gdispImageCache() has been called first for this frame, this routine will draw using a
- * fast blit from the cached frame. If not, it reads the input and decodes it as it
- * is drawing. This may be significantly slower than if the image has been cached (but
- * uses a lot less RAM)
+ * @param[in] x, y The start filled area
+ * @param[in] cx, cy The width and height to be filled
+ * @param[in] srcx, srcy The bitmap position to start the fill from
+ * @param[in] srccx The width of a line in the bitmap.
+ * @param[in] buffer The pixels to use to fill the area.
+ *
+ * @api
*/
- gdispImageError gwinImageDraw(GHandle gh, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy);
-#endif
+ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer);
+
+/*-------------------------------------------------
+ * Circle, ellipse and arc functions
+ *-------------------------------------------------*/
+
+ #if GDISP_NEED_CIRCLE || defined(__DOXYGEN__)
+ /**
+ * @brief Draw a circle in the window.
+ * @note Uses the current foreground color to draw the circle
+ * @note May leave GDISP clipping to this window's dimensions
+ *
+ * @param[in] gh The window handle
+ * @param[in] x, y The center of the circle
+ * @param[in] radius The radius of the circle
+ *
+ * @api
+ */
+ void gwinDrawCircle(GHandle gh, coord_t x, coord_t y, coord_t radius);
+
+ /**
+ * @brief Draw a filled circle in the window.
+ * @note Uses the current foreground color to draw the filled circle
+ * @note May leave GDISP clipping to this window's dimensions
+ *
+ * @param[in] gh The window handle
+ * @param[in] x, y The center of the circle
+ * @param[in] radius The radius of the circle
+ *
+ * @api
+ */
+ void gwinFillCircle(GHandle gh, coord_t x, coord_t y, coord_t radius);
+ #endif
+
+ #if GDISP_NEED_ELLIPSE || defined(__DOXYGEN__)
+ /**
+ * @brief Draw an ellipse.
+ * @note Uses the current foreground color to draw the ellipse
+ * @note May leave GDISP clipping to this window's dimensions
+ *
+ * @param[in] gh The window handle
+ * @param[in] x,y The center of the ellipse
+ * @param[in] a,b The dimensions of the ellipse
+ *
+ * @api
+ */
+ void gwinDrawEllipse(GHandle gh, coord_t x, coord_t y, coord_t a, coord_t b);
+
+ /**
+ * @brief Draw an filled ellipse.
+ * @note Uses the current foreground color to draw the filled ellipse
+ * @note May leave GDISP clipping to this window's dimensions
+ *
+ * @param[in] gh The window handle
+ * @param[in] x,y The center of the ellipse
+ * @param[in] a,b The dimensions of the ellipse
+ *
+ * @api
+ */
+ void gwinFillEllipse(GHandle gh, coord_t x, coord_t y, coord_t a, coord_t b);
+ #endif
+
+ #if GDISP_NEED_ARC || defined(__DOXYGEN__)
+ /*
+ * @brief Draw an arc in the window.
+ * @note Uses the current foreground color to draw the arc
+ * @note May leave GDISP clipping to this window's dimensions
+ *
+ * @param[in] gh The window handle
+ * @param[in] x,y The center point
+ * @param[in] radius The radius of the arc
+ * @param[in] start The start angle (0 to 360)
+ * @param[in] end The end angle (0 to 360)
+ *
+ * @api
+ */
+ void gwinDrawArc(GHandle gh, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle);
+
+ /*
+ * @brief Draw a filled arc in the window.
+ * @note Uses the current foreground color to draw the filled arc
+ * @note May leave GDISP clipping to this window's dimensions
+ *
+ * @param[in] gh The window handle
+ * @param[in] x,y The center point
+ * @param[in] radius The radius of the arc
+ * @param[in] start The start angle (0 to 360)
+ * @param[in] end The end angle (0 to 360)
+ *
+ * @api
+ */
+ void gwinFillArc(GHandle gh, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle);
+ #endif
+
+/*-------------------------------------------------
+ * Pixel read-back functions
+ *-------------------------------------------------*/
+
+ #if GDISP_NEED_PIXELREAD || defined(__DOXYGEN__)
+ /**
+ * @brief Get the color of a pixel in the window.
+ * @return The color of the pixel.
+ * @note May leave GDISP clipping to this window's dimensions
+ *
+ * @param[in] gh The window handle
+ * @param[in] x,y The position in the window
+ *
+ * @api
+ */
+ color_t gwinGetPixelColor(GHandle gh, coord_t x, coord_t y);
+ #endif
+
+/*-------------------------------------------------
+ * Text functions
+ *-------------------------------------------------*/
+
+ #if GDISP_NEED_TEXT || defined(__DOXYGEN__)
+ /**
+ * @brief Draw a text character at the specified position in the window.
+ * @pre The font must have been set.
+ * @note Uses the current foreground color to draw the character
+ * @note May leave GDISP clipping to this window's dimensions
+ *
+ * @param[in] gh The window handle
+ * @param[in] x,y The position for the text
+ * @param[in] c The character to draw
+ *
+ * @api
+ */
+ void gwinDrawChar(GHandle gh, coord_t x, coord_t y, char c);
+
+ /**
+ * @brief Draw a text character with a filled background at the specified position in the window.
+ * @pre The font must have been set.
+ * @note Uses the current foreground color to draw the character and fills the background using the background drawing color
+ * @note May leave GDISP clipping to this window's dimensions
+ *
+ * @param[in] gh The window handle
+ * @param[in] x,y The position for the text
+ * @param[in] c The character to draw
+ *
+ * @api
+ */
+ void gwinFillChar(GHandle gh, coord_t x, coord_t y, char c);
+
+ /**
+ * @brief Draw a text string in the window
+ * @pre The font must have been set.
+ * @note Uses the current foreground color to draw the character
+ * @note May leave GDISP clipping to this window's dimensions
+ *
+ * @param[in] gh The window handle
+ * @param[in] x,y The position for the text
+ * @param[in] str The string to draw
+ *
+ * @api
+ */
+ void gwinDrawString(GHandle gh, coord_t x, coord_t y, const char *str);
+
+ /**
+ * @brief Draw a text string with a filled background in the window
+ * @pre The font must have been set.
+ * @note Uses the current foreground color to draw the character and fills the background using the background drawing color
+ * @note May leave GDISP clipping to this window's dimensions
+ *
+ * @param[in] gh The window handle
+ * @param[in] x,y The position for the text
+ * @param[in] str The string to draw
+ *
+ * @api
+ */
+ void gwinFillString(GHandle gh, coord_t x, coord_t y, const char *str);
+
+ /**
+ * @brief Draw a text string verticly centered within the specified box.
+ * @pre The font must have been set.
+ * @note Uses the current foreground color to draw the character.
+ * @note The specified box does not need to align with the window box
+ * @note May leave GDISP clipping to this window's dimensions
+ *
+ * @param[in] gh The window handle
+ * @param[in] x,y The position for the text (need to define top-right or base-line - check code)
+ * @param[in] cx,cy The width and height of the box
+ * @param[in] str The string to draw
+ * @param[in] justify Justify the text left, center or right within the box
+ *
+ * @api
+ */
+ void gwinDrawStringBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, justify_t justify);
+
+ /**
+ * @brief Draw a text string verticly centered within the specified filled box.
+ * @pre The font must have been set.
+ * @note Uses the current foreground color to draw the character and fills the background using the background drawing color
+ * @note The entire box is filled. Note this box does not need to align with the window box
+ * @note May leave GDISP clipping to this window's dimensions
+ *
+ * @param[in] gh The window handle
+ * @param[in] x,y The position for the text (need to define top-right or base-line - check code)
+ * @param[in] cx,cy The width and height of the box
+ * @param[in] str The string to draw
+ * @param[in] justify Justify the text left, center or right within the box
+ *
+ * @api
+ */
+ void gwinFillStringBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, justify_t justify);
+ #endif
+
+/*-------------------------------------------------
+ * Polygon functions
+ *-------------------------------------------------*/
+
+ #if GDISP_NEED_CONVEX_POLYGON || defined(__DOXYGEN__)
+ /**
+ * @brief Draw an enclosed polygon (convex, non-convex or complex).
+ *
+ * @note Uses the current foreground color.
+ *
+ * @param[in] gh The window handle
+ * @param[in] tx, ty Transform all points in pntarray by tx, ty
+ * @param[in] pntarray An array of points
+ * @param[in] cnt The number of points in the array
+ *
+ * @api
+ */
+ void gwinDrawPoly(GHandle gh, coord_t tx, coord_t ty, const point *pntarray, unsigned cnt);
+
+ /**
+ * @brief Fill a convex polygon
+ * @details Doesn't handle non-convex or complex polygons.
+ *
+ * @note Uses the current foreground color.
+ *
+ * @param[in] gh The window handle
+ * @param[in] tx, ty Transform all points in pntarray by tx, ty
+ * @param[in] pntarray An array of points
+ * @param[in] cnt The number of points in the array
+ *
+ * @note Convex polygons are those that have no internal angles. That is;
+ * you can draw a line from any point on the polygon to any other point
+ * on the polygon without it going outside the polygon. In our case we generalise
+ * this a little by saying that an infinite horizontal line (at any y value) will cross
+ * no more than two edges on the polygon. Some non-convex polygons do fit this criteria
+ * and can therefore be drawn.
+ * @note This routine is designed to be very efficient with even simple display hardware.
+ *
+ * @api
+ */
+ void gwinFillConvexPoly(GHandle gh, coord_t tx, coord_t ty, const point *pntarray, unsigned cnt);
+ #endif
+
+/*-------------------------------------------------
+ * Image functions
+ *-------------------------------------------------*/
+
+ #if GDISP_NEED_IMAGE || defined(__DOXYGEN__)
+ /**
+ * @brief Draw the image
+ * @return GDISP_IMAGE_ERR_OK (0) on success or an error code.
+ *
+ * @param[in] gh The window handle
+ * @param[in] img The image structure
+ * @param[in] x,y The window location to draw the image
+ * @param[in] cx,cy The area on the screen to draw
+ * @param[in] sx,sy The image position to start drawing at
+ *
+ * @pre gdispImageOpen() must have returned successfully.
+ *
+ * @note If sx,sy + cx,cy is outside the image boundaries the area outside the image
+ * is simply not drawn.
+ * @note If @p gdispImageCache() has been called first for this frame, this routine will draw using a
+ * fast blit from the cached frame. If not, it reads the input and decodes it as it
+ * is drawing. This may be significantly slower than if the image has been cached (but
+ * uses a lot less RAM)
+ *
+ * @api
+ */
+ gdispImageError gwinImageDraw(GHandle gh, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy);
+ #endif
#ifdef __cplusplus
}
#endif
-/* Include extra window types */
-#include "gwin/console.h" /* 0x0001 */
-#include "gwin/button.h" /* 0x0002 */
-#include "gwin/graph.h" /* 0x0003 */
-#include "gwin/slider.h" /* 0x0004 */
-#include "gwin/checkbox.h" /* 0x0005 */
+/*-------------------------------------------------
+ * Additional functionality
+ *-------------------------------------------------*/
+
+ /* Include widgets */
+ #if GWIN_NEED_WIDGET || defined(__DOXYGEN__)
+ #include "gwin/gwidget.h"
+ #endif
+
+ /* Include extra window types */
+ #if GWIN_NEED_CONSOLE || defined(__DOXYGEN__)
+ #include "gwin/console.h"
+ #endif
+ #if GWIN_NEED_GRAPH || defined(__DOXYGEN__)
+ #include "gwin/graph.h"
+ #endif
#endif /* GFX_USE_GWIN */
diff --git a/include/gwin/internal.h b/include/gwin/internal.h
deleted file mode 100644
index 0b750b2c..00000000
--- a/include/gwin/internal.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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://chibios-gfx.com/license.html
- */
-
-/**
- * @file include/gwin/internal.h
- * @brief GWIN Graphic window subsystem header file.
- *
- * @addtogroup GWIN
- * @{
- */
-#ifndef _GWIN_INTERNAL_H
-#define _GWIN_INTERNAL_H
-
-#if GFX_USE_GWIN || defined(__DOXYGEN__)
-
-/*===========================================================================*/
-/* Sub-system constants. */
-/*===========================================================================*/
-
-#define GWIN_FLG_DYNAMIC 0x0001
-#define GBTN_FLG_ALLOCTXT 0x0002
-#define GWIN_FIRST_CONTROL_FLAG 0x0004
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-GHandle _gwinInit(GWindowObject *gw, coord_t x, coord_t y, coord_t width, coord_t height, size_t size);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* GFX_USE_GWIN */
-
-#endif /* _GWIN_INTERNAL_H */
-/** @} */
diff --git a/include/gwin/options.h b/include/gwin/options.h
index 1ee9b836..cc164259 100644
--- a/include/gwin/options.h
+++ b/include/gwin/options.h
@@ -21,20 +21,22 @@
* @{
*/
/**
- * @brief Should button functions be included.
+ * @brief Should window manager support be included
* @details Defaults to FALSE
*/
- #ifndef GWIN_NEED_BUTTON
- #define GWIN_NEED_BUTTON FALSE
+ #ifndef GWIN_NEED_WINDOWMANAGER
+ #define GWIN_NEED_WIDGET FALSE
+ #endif
+ /**
+ * @brief Should widget functions be included. Needed for any widget (eg Buttons, Sliders etc)
+ * @details Defaults to FALSE
+ */
+ #ifndef GWIN_NEED_WIDGET
+ #define GWIN_NEED_WIDGET FALSE
#endif
/**
* @brief Should console functions be included.
* @details Defaults to FALSE
- * @note To use chprintf() for printing in a console window you need to
- * include in your application source file...
- * \#include "chprintf.h"
- * Also in your makefile, as part of your list of C source files, include
- * ${CHIBIOS}/os/various/chprintf.c
*/
#ifndef GWIN_NEED_CONSOLE
#define GWIN_NEED_CONSOLE FALSE
@@ -47,12 +49,26 @@
#define GWIN_NEED_GRAPH FALSE
#endif
/**
+ * @brief Should button functions be included.
+ * @details Defaults to FALSE
+ */
+ #ifndef GWIN_NEED_BUTTON
+ #define GWIN_NEED_BUTTON FALSE
+ #endif
+ /**
* @brief Should slider functions be included.
* @details Defaults to FALSE
*/
#ifndef GWIN_NEED_SLIDER
#define GWIN_NEED_SLIDER FALSE
#endif
+ /**
+ * @brief Should checkbox functions be included.
+ * @details Defaults to FALSE
+ */
+ #ifndef GWIN_NEED_CHECKBOX
+ #define GWIN_NEED_CHECKBOX FALSE
+ #endif
/**
* @}
*
@@ -76,6 +92,12 @@
/**
* @brief Console Windows need BaseStreamSequential support (ChibiOS only)
* @details Defaults to FALSE
+ * @note To use the ChibiOS basestream functions such as chprintf()
+ * for printing in a console window you need to set this option to
+ * TRUE in your gfxconf.h and include in your application source file...
+ * \#include "chprintf.h"
+ * In your makefile, as part of your list of C source files, include
+ * ${CHIBIOS}/os/various/chprintf.c
*/
#ifndef GWIN_CONSOLE_USE_BASESTREAM
#define GWIN_CONSOLE_USE_BASESTREAM FALSE
diff --git a/include/gwin/slider.h b/include/gwin/slider.h
index 310cb0eb..9baecbb1 100644
--- a/include/gwin/slider.h
+++ b/include/gwin/slider.h
@@ -22,19 +22,10 @@
#ifndef _GWIN_SLIDER_H
#define _GWIN_SLIDER_H
-#if GWIN_NEED_SLIDER || defined(__DOXYGEN__)
+/* This file is included within "gwin/gwidget.h" */
-/*===========================================================================*/
-/* Driver constants. */
-/*===========================================================================*/
-
-#define GW_SLIDER 0x0004
#define GEVENT_GWIN_SLIDER (GEVENT_GWIN_FIRST+1)
-/*===========================================================================*/
-/* Type definitions */
-/*===========================================================================*/
-
typedef struct GEventGWinSlider_t {
GEventType type; // The type of this event (GEVENT_GWIN_BUTTON)
GHandle slider; // The slider that is returning results
@@ -43,33 +34,27 @@ typedef struct GEventGWinSlider_t {
// There are currently no GEventGWinSlider listening flags - use 0
-typedef struct GSliderDrawStyle_t {
+typedef struct GSliderColors {
color_t color_edge;
color_t color_thumb;
color_t color_active;
color_t color_inactive;
-} GSliderDrawStyle;
-
-typedef void (*GSliderDrawFunction)(GHandle gh, bool_t isVertical, coord_t thumbpos, const GSliderDrawStyle *pstyle, void *param);
+ color_t color_txt;
+} GSliderColors;
// A slider window
typedef struct GSliderObject_t {
- GWindowObject gwin;
-
- GSliderDrawStyle style;
- bool_t tracking;
+ GWidgetObject w;
+ uint16_t t_dn;
+ uint16_t t_up;
+ uint16_t dial;
+ coord_t dpos;
int min;
int max;
int pos;
- GSliderDrawFunction fn;
- void *param;
- GListener listener;
+ GSliderColors c;
} GSliderObject;
-/*===========================================================================*/
-/* External declarations. */
-/*===========================================================================*/
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -79,13 +64,26 @@ extern "C" {
* @return NULL if there is no resultant drawing area, otherwise a window handle.
*
* @param[in] gb The GSliderObject structure to initialise. If this is NULL the structure is dynamically allocated.
- * @param[in] x,y The screen co-ordinates for the bottom left corner of the window
+ * @param[in] x,y The screen co-ordinates for the top left corner of the window
* @param[in] width The width of the window
* @param[in] height The height of the window
- * @note The drawing color gets set to White and the background drawing color to Black.
+ *
+ * @note The drawing color and the background color get set to the current defaults. If you haven't called
+ * @p gwinSetDefaultColor() or @p gwinSetDefaultBgColor() then these are White and Black respectively.
+ * @note The font gets set to the current default font. If you haven't called @p gwinSetDefaultFont() then there
+ * is no default font and text drawing operations will no nothing.
* @note The dimensions and position may be changed to fit on the real screen.
- * @note The slider is not automatically drawn. Call gwinSliderDraw() after changing the slider style.
- * @note Sets the slider range from 0 to 100 with an initial position of 0
+ * @note A slider remembers its normal drawing state. If there is a window manager then it is automatically
+ * redrawn if the window is moved or its visibility state is changed.
+ * @note The slider is initially marked as invisible so that more properties can be set before display.
+ * Call @p gwinSetVisible() to display it when ready.
+ * @note The initial slider range is from 0 to 100 with an initial position of 0.
+ * @note A slider supports mouse, toggle and dial input.
+ * @note When assigning a toggle, only one toggle is supported per role. If you try to assign more than
+ * one toggle to a role it will forget the previous toggle. Two roles are supported:
+ * Role 0 = toggle for down, Role 1 = toggle for up.
+ * @note When assigning a dial, only one dial is supported. If you try to assign more than one dial
+ * it will forget the previous dial. Only dial role 0 is supported.
*
* @api
*/
@@ -130,51 +128,7 @@ void gwinSetSliderPosition(GHandle gh, int pos);
*
* @api
*/
-void gwinSetSliderStyle(GHandle gh, const GSliderDrawStyle *pStyle);
-
-/**
- * @brief Redraw the slider.
- *
- * @param[in] gh The window handle (must be a slider window)
- *
- * @api
- */
-void gwinSliderDraw(GHandle gh);
-
-/**
- * @brief Enable or disable a button
- *
- * @param[in] gh The window handle (must be a slider window)
- * @param[in] enabled Enable or disable the slider
- *
- * @api
- */
-void gwinSliderSetEnabled(GHandle gh, bool_t enabled);
-
-/**
- * @brief Set the callback routine to perform a custom slider drawing.
- *
- * @param[in] gh The window handle (must be a slider window)
- * @param[in] fn The function to use to draw the slider
- * @param[in] param A parameter to pass to the slider drawing function
- *
- * @api
- */
-void gwinSetSliderCustom(GHandle gh, GSliderDrawFunction fn, void *param);
-
-/**
- * @brief Enable a slider
- *
- * @api
- */
-#define gwinEnableSlider(gh) gwinSliderSetEnabled( ((GSliderObject *)(gh)), TRUE)
-
-/**
- * @brief Disable a slider
- *
- * @api
- */
-#define gwinDisableSlider(gh) gwinSliderSetEnabled( ((GSliderObject *)(gh)), FALSE)
+void gwinSetSliderColors(GHandle gh, const GSliderColors *pStyle);
/**
* @brief Get the current slider position.
@@ -190,69 +144,35 @@ void gwinSetSliderCustom(GHandle gh, GSliderDrawFunction fn, void *param);
#define gwinGetSliderPosition(gh) (((GSliderObject *)(gh))->pos)
/**
- * @brief Get the source handle of a slider
- * @details Get the source handle of a slider so the application can listen for events
+ * @brief Some custom slider drawing routines
+ * @details These function may be passed to @p gwinSetCustomDraw() to get different slider drawing styles
*
- * @param[in] gh The window handle
- *
- * @api
- */
-#define gwinGetSliderSource(gh) ((GSourceHandle)(gh))
-
-#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
- /**
- * @brief Attach a mouse source
- * @details Attach a mouse to a slider
- *
- * @param[in] gh The slider handle
- * @param[in] instance The mouse instance
- *
- * @api
- */
- bool_t gwinAttachSliderMouse(GHandle gh, uint16_t instance);
-#endif
-
-#if GFX_USE_GINPUT && GINPUT_NEED_DIAL
- /**
- * @brief Attach a dial source
- * @details Attach a dial to a slider
- *
- * @param[in] gh The dial handle
- * @param[in] instance The dial instance
- *
- * @api
- */
- bool_t gwinAttachSliderDial(GHandle gh, uint16_t instance);
-#endif
-
-/**
- * @brief Standard slider drawing routines
- * @details This routine is called to draw the standard slider.
- *
- * @param[in] gh The slider handle
- * @param[in] isVertical The slider is vertically oriented instead of horizontal
- * @param[in] thumbpos The position of the slider (0..cx-1 or cy-1..0)
- * @param[in] pstyle The current drawing style
+ * @param[in] gw The widget (which must be a slider)
* @param[in] param A parameter passed in from the user
*
* @note In your custom slider drawing function you may optionally call this
* standard functions and then draw your extra details on top.
- * @note The standard functions below ignore the param parameter. It is there
- * only to ensure the functions match the GSliderDrawFunction type.
- * @note When called by a slider the framework ensure that it is
- * a slider object and sets up clipping to the slider object window. These
- * drawing routines then don't have to worry about explicitly doing that.
+ * @note The standard functions below ignore the param parameter except for @p gwinSliderDraw_Image().
+ * @note The image custom draw function @p gwinSliderDraw_Image() uses param to pass in the gdispImage pointer.
+ * The image must be already opened before calling @p gwinSetCustomDraw(). The image is tiled to fill
+ * the active area of the slider. The normal colors apply to the border and inactive area and the dividing line
+ * between the active and inactive areas.
+ * No checking is done to compare the dimensions of the slider to the size of the image.
+ * Note text is drawn on top of the image.
+ * @note These custom drawing routines don't have to worry about setting clipping as the framework
+ * sets clipping to the object window prior to calling these routines.
*
* @api
+ * @{
*/
-void gwinSliderDraw_Std(GHandle gh, bool_t isVertical, coord_t thumbpos, const GSliderDrawStyle *pstyle, void *param);
+void gwinSliderDraw_Std(GWidgetObject *gw, void *param);
+void gwinSliderDraw_Image(GWidgetObject *gw, void *param);
+/* @} */
#ifdef __cplusplus
}
#endif
-#endif /* GWIN_NEED_SLIDER */
-
#endif /* _GWIN_SLIDER_H */
/** @} */
diff --git a/license.html b/license.html
index fa207416..4aee4953 100644
--- a/license.html
+++ b/license.html
@@ -1,192 +1,192 @@
-<!DOCTYPE html>
-<html>
-<head>
- <meta charset="utf-8" />
- <title>GFX License, version 1.1</title>
- <!--[if lt IE 9]>
- <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
- <![endif]-->
- <style type="text/css">
- body {
- font-family: sans-serif;
- max-width: 50em;
- margin-left:auto;
- margin-right:auto;
- text-align: justify;
- -moz-hyphens: auto;
- }
-
- h1, h2, h3 {
- font-family: sans-serif;
- font-variant: small-caps;
- font-weight: bold;
- }
-
- h1 {
- text-align: center;
- -moz-hyphens: none;
- font-size: 160%;
- }
- h2 {
- font-size: 140%;
- -moz-hyphens: none;
- text-align: left;
- }
- h3 {
- font-size: 120%;
- -moz-hyphens: none;
- text-align: left;
- }
-
- blockquote {
- font-family: mono;
- text-align: left;
- -moz-hyphens: none;
- }
-
- code {
- font-family: mono;
- }
-
- em {
- background: #FEFD80;
- border: 30px solid #FEFD80;
- float: left;
- line-height: 1.25em;
- margin-left: 10px;
- margin-right: 10px;
- margin-bottom: 10px;
- margin-top:-10px;
- font-style: normal;
- }
-
- dt {
- font-family: sans-serif;
- font-weight: bold;
- }
- </style>
-</head>
-<body>
-<h1>GFX License<br>Version 1.1</h1>
-<h2>1. Definitions</h2>
-<dl>
-<dt>1.1. Works</dt>
-<dd><p>means the library commonly known as GFX or ChibiOS-GFX or ChibiOS/GFX, in source code or binary form, linked or unlinked with an application or another library.</p></dd>
-<dt>1.2. Contributor</dt>
-<dd><p>means each individual or legal entity that creates, contributes to the creation of the Works.</p></dd>
-<dt>1.3. Contribution</dt>
-<dd><p>means Software of a particular Contributor that has been offered to form part of the Works.</p></dd>
-<dt>1.4. Executable form</dt>
-<dd><p>means any form of the Works other than Source Code Form.</p></dd>
-<dt>1.5. Application</dt>
-<dd><p>means a work or software that combines the Works with other material, in a separate file or files whether in executable format or in library format, as Software or on a device.</p></dd>
-<dt>1.6. License</dt>
-<dd><p>means this document.</p></dd>
-<dt>1.7. Modifications</dt>
-<dd><p>means any of the following:</p>
-<ol type="a">
-<li><p>any file in Source Code Form that results from an addition to, deletion from, or modification of the contents of the Works; or</p></li>
-<li><p>any new file in Source Code Form that contains any part of the Works.</p></li>
-</ol>
-</dd>
-<dt>1.8. Patent Claims of a Contributor</dt>
-<dd><p>means any patent claim(s), including without limitation, method, process, and apparatus claims, in any patent Licensable by such Contributor that would be infringed, but for the grant of the License, by the making, using, selling, offering for sale, having made, import, or transfer of its Contributions.</p></dd>
-<dt>1.9. Source Code Form</dt>
-<dd><p>means the form of the work preferred for making modifications.</p></dd>
-<dt>1.10. You (or Your)</dt>
-<dd><p>means an individual or a legal entity exercising rights under this License. For legal entities, You includes any entity that controls, is controlled by, or is under common control with You. For purposes of this definition, control means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity.</p></dd>
-<dt>1.11. License Owner</dt>
-<dd><p>means Joel Bodenmann (joel@unormal.org) and Andrew Hannam (andrewh@inmarket.com.au). Both parties are joint and severely owners of the license.</p></dd>
-<dt>1.12. Commercial Use</dt>
-<dd><p>means any use of the Works that may result in income or equivalent benefit in any form. Examples of Commercial Use include; selling an Application or Device containing the Works,
- offering paid support to modify the Works, selling a library containing the Works. Examples of use that are NOT Commercial Use include; using the Works for Education, use of the Works in hobbyist projects that have no expectation of income, use of the Works in building what will later become a Commercial Use product.
- Note that Commercial Use does not the prototyping and preparation for income generating activities - only the income producing activity itself.</p></dd>
-</dl>
-
-<h2>2. Non Commercial Use</h2>
-<h3>2.1. Distribution of source form</h3>
-<p>If You distribute the Works in an source form then:</p>
-<ol type="a">
-<li><p>All distribution of the Works in Source Code Form, including any Modifications that You create or to which You contribute, must be under the terms of this License; and</p></li>
-<li><p>You must inform recipients that the Source Code Form of the Works is governed by the terms of this License, and how they can obtain a copy of this License. You may not attempt to alter the recipients rights in the Source Code Form; and</p></li>
-<li><p>Any modification to the Works must be contributed to the License Owners, as per Section 4, prior to distribution with the exception of a working public source control repository. In this situation, modifications of the Works must be contributed to the License Owners within one calendar month; and</p></li>
-<li><p>source code not forming part of the Works that are distributed in conjunction with the Works do not need to be contributed to the License Owners or use this License.</p></li>
-</ol>
-<i><p>Note: This means that you must contribute changes you make to the library, you do not need to contribute your application or any other code outside of GFX library itself.</p></i>
-<h3>2.2. Distribution of Executable form</h3>
-<p>If You distribute the Works in an Executable form then:</p>
-<ol type="a">
-<li><p>and You must inform recipients of the Executable form that it contains the Works and how they can obtain a copy of the Works in Source Code Form from the License Owners master repository; and</p></li>
-<li><p>Any modification to the Works must be contributed to the License Owners as per Section 4 prior to distribution; and</p></li>
-<li><p>You may distribute such Executable form under the terms of this License, or license it under different terms, provided that the license for the Executable form does not allow for Commercial Use of the Works or attempt to limit or alter the recipients' rights in the Source Code Form under this License.</p></li>
-</ol>
-
-<h2>3. Commercial Use</h2>
-<h3>3.1. Commercial Use Agreement</h3>
-<p>A "Commercial Use Agreement" explicitly signed by the License Owner will override any specified terms of this License for the party to the agreement under the terms of the agreement. All other terms of this License will still apply.</p>
-<h3>3.2. Distribution</h3>
-<p>Other than as provided for in a signed "Commercial Use Agreement", where there is a Commercial Use involved or implied; you are not permitted to distribute the Works, in any form, either in source code or Executable form,
- either as software or on a device or in any other way.</p>
-
-<h2>4. Contributions</h2>
-<h3>4.1. Contributor Grants</h3>
-<p>Each Contributor hereby irrevocably grants to the License Owner without fee or charge:</p>
-<ol type="a">
-<li><p>under intellectual property rights (other than patent or trademark) Licensable by such Contributor to use, reproduce, make available, modify, display, perform, distribute, relicense and otherwise exploit its Contributions, either on an unmodified basis, with Modifications, or as part of a Larger Work; and</p></li>
-<li><p>under Patent Claims of such Contributor to make, use, sell, offer for sale, have made, import, relicense and otherwise transfer its Contributions.</p></li>
-</ol>
-<h3>4.2. Effective Date</h3>
-<p>The licenses granted in Section&nbsp;4.1 with respect to any Contribution become effective for each Contribution on the date the Contributor first contributes or distributes such Contribution.</p>
-<h3>4.3. Limitations on Grant Scope</h3>
-<p>The grants made in this Section&nbsp;4 are the only rights granted. No additional rights or licenses will be implied from the distribution or licensing of the Works under this License. Notwithstanding Section&nbsp;4.1(b) above, no patent license is granted by a Contributor:</p>
-<ol type="a">
-<li><p>for any code that a Contributor has removed from Contribution; or</p></li>
-<li><p>under Patent Claims infringed by the Works in the absence of its Contributions.</p></li>
-</ol>
-<p>This License does not grant any rights in the trademarks, service marks, or logos of any Contributor (except as may be necessary to comply with the requirements in Section&nbsp;4.4).</p>
-<h3>4.4. Representation</h3>
-<p>Each Contributor represents that the Contributor believes its Contributions are its original creation(s) or it has sufficient rights to grant the rights to its Contributions conveyed by this License. Each Contributor accepts sole responsibility for the legal position of its Contribution and holds blameless the License Owners for such Contribution or any modification to it.</p>
-<h3>4.5. Deeming of Contributions</h3>
-<p>Each Contributor deems that by Contributing to the Works, through any method offered by the License Owners, irrespective of the license provided in the Contribution, is agreeing to the Contribution being licensed under this License with its Grants, Scope and Representation.</p>
-<h3>4.6. Original Source Rights</h3>
-<p>By contributing to the Works, the Contributor is not removing their own copyright in their original work. The original work retains all existing copyrights and other rights, except the rights as described above have been granted to the license owners on the copy of the contribution as contributed.</p>
-<p>This is equivelent to the "forking" of the contribution to two different licenses, one as part of the works (GFX) and the other as in its original form.</p>
-<h3>4.7. Additional Rights</h3>
-<p>A Contribution does not convey any extra distribution rights for the Contributor to the Works under this license.</p>
-
-
-<h2>5. Notices</h2>
-<p>You may not remove or alter the substance of any license notices (including copyright notices, patent notices, disclaimers of warranty, or limitations of liability) contained within the Source Code Form of the Works, except that You may alter any license notices to the extent required to remedy known factual inaccuracies.</p>
-<h2>6. Inability to Comply Due to Statute or Regulation</h2>
-<p>If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Works due to statute, judicial order, or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be Contributed to the License Owners and placed in a text file included with all distributions of the Works under this License. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it.</p>
-<h2>7. Termination</h2>
-<p>7.1. The distribution rights granted under this License will terminate automatically if You fail to comply with any of its terms. However, if You become compliant, then the rights granted under this License (a) provisionally, unless and until the License Owner explicitly and finally terminates Your grants, and (b) on an ongoing basis, if the License Owner fails to notify You of the non-compliance by some reasonable means prior to 60 days after You have come back into compliance.</p>
-<p>7.2. If You initiate litigation against any entity by asserting a patent infringement claim (excluding declaratory judgment actions, counter-claims, and cross-claims) alleging that the License Owner directly or indirectly infringes any patent, then the rights granted to You by the License Owner for the Works shall terminate.</p>
-<h2>8. Disclaimer of Warranty</h2>
-<p><em>Covered Software is provided under this License on an as is basis, without warranty of any kind, either expressed, implied, or statutory, including, without limitation, warranties that the Works is free of defects, merchantable, fit for a particular purpose or non-infringing. The entire risk as to the quality and performance of the Works is with You. Should any of the Works prove defective in any respect, You assume the cost of any necessary servicing, repair, or correction. This disclaimer of warranty constitutes an essential part of this License. No use of the Works is authorized under this License except under this disclaimer.</em></p>
-<h2>9. Limitation of Liability</h2>
-<p><em>Under no circumstances and under no legal theory, whether tort (including negligence), contract, or otherwise, shall the License Owner, any Contributor, or anyone who distributes the Works as permitted above, be liable to You for any direct, indirect, special, incidental, or consequential damages of any character including, without limitation, damages for lost profits, loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses, even if such party shall have been informed of the possibility of such damages.</em></p>
-<h2>10. Litigation</h2>
-<p>Any litigation relating to this License may be brought only in the courts of a jurisdiction where the defendant maintains its principal place of business and such litigation shall be governed by laws of that jurisdiction, without reference to its conflict-of-law provisions. Nothing in this Section shall prevent a party's ability to bring cross-claims or counter-claims.</p>
-<h2>11. Miscellaneous</h2>
-<p>This License represents the complete agreement concerning the subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not be used to construe this License against a Contributor ro the License Owner.</p>
-<h2>12. Versions of the License</h2>
-<h3>12.1. New Versions</h3>
-<p>The License Owner is the license steward. Except as provided in Section&nbsp;12.3, no one other than the license steward has the right to modify or publish new versions of this License. Each version will be given a distinguishing version number.</p>
-<h3>12.2. Effect of New Versions</h3>
-<p>You may distribute the Works under the terms of the version of the License under which You originally received the Works, or under the terms of any subsequent version published by the license steward.</p>
-<h3>12.3. Modified Versions</h3>
-<p>If you create software not governed by this License, and you want to create a new license for such software, you may create and use a modified version of this License if you rename the license and remove any references to the name of the License Owner (except to note that such modified license differs from this License).</p>
-
-<h2>Exhibit A - Source Code Form License Notice</h2>
-<pre>
-/*
- * 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://chibios-gfx.com/license.html
- */
-</pre>
-<p>If it is not possible or desirable to put the notice in a particular file, then You may include the notice in a location (such as a LICENSE file in a relevant directory) where a recipient would be likely to look for such a notice.</p>
-</body>
-</html>
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <title>GFX License, version 1.1</title>
+ <!--[if lt IE 9]>
+ <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
+ <![endif]-->
+ <style type="text/css">
+ body {
+ font-family: sans-serif;
+ max-width: 50em;
+ margin-left:auto;
+ margin-right:auto;
+ text-align: justify;
+ -moz-hyphens: auto;
+ }
+
+ h1, h2, h3 {
+ font-family: sans-serif;
+ font-variant: small-caps;
+ font-weight: bold;
+ }
+
+ h1 {
+ text-align: center;
+ -moz-hyphens: none;
+ font-size: 160%;
+ }
+ h2 {
+ font-size: 140%;
+ -moz-hyphens: none;
+ text-align: left;
+ }
+ h3 {
+ font-size: 120%;
+ -moz-hyphens: none;
+ text-align: left;
+ }
+
+ blockquote {
+ font-family: mono;
+ text-align: left;
+ -moz-hyphens: none;
+ }
+
+ code {
+ font-family: mono;
+ }
+
+ em {
+ background: #FEFD80;
+ border: 30px solid #FEFD80;
+ float: left;
+ line-height: 1.25em;
+ margin-left: 10px;
+ margin-right: 10px;
+ margin-bottom: 10px;
+ margin-top:-10px;
+ font-style: normal;
+ }
+
+ dt {
+ font-family: sans-serif;
+ font-weight: bold;
+ }
+ </style>
+</head>
+<body>
+<h1>GFX License<br>Version 1.1</h1>
+<h2>1. Definitions</h2>
+<dl>
+<dt>1.1. Works</dt>
+<dd><p>means the library commonly known as GFX or ChibiOS-GFX or ChibiOS/GFX, in source code or binary form, linked or unlinked with an application or another library.</p></dd>
+<dt>1.2. Contributor</dt>
+<dd><p>means each individual or legal entity that creates, contributes to the creation of the Works.</p></dd>
+<dt>1.3. Contribution</dt>
+<dd><p>means Software of a particular Contributor that has been offered to form part of the Works.</p></dd>
+<dt>1.4. Executable form</dt>
+<dd><p>means any form of the Works other than Source Code Form.</p></dd>
+<dt>1.5. Application</dt>
+<dd><p>means a work or software that combines the Works with other material, in a separate file or files whether in executable format or in library format, as Software or on a device.</p></dd>
+<dt>1.6. License</dt>
+<dd><p>means this document.</p></dd>
+<dt>1.7. Modifications</dt>
+<dd><p>means any of the following:</p>
+<ol type="a">
+<li><p>any file in Source Code Form that results from an addition to, deletion from, or modification of the contents of the Works; or</p></li>
+<li><p>any new file in Source Code Form that contains any part of the Works.</p></li>
+</ol>
+</dd>
+<dt>1.8. Patent Claims of a Contributor</dt>
+<dd><p>means any patent claim(s), including without limitation, method, process, and apparatus claims, in any patent Licensable by such Contributor that would be infringed, but for the grant of the License, by the making, using, selling, offering for sale, having made, import, or transfer of its Contributions.</p></dd>
+<dt>1.9. Source Code Form</dt>
+<dd><p>means the form of the work preferred for making modifications.</p></dd>
+<dt>1.10. You (or Your)</dt>
+<dd><p>means an individual or a legal entity exercising rights under this License. For legal entities, You includes any entity that controls, is controlled by, or is under common control with You. For purposes of this definition, control means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity.</p></dd>
+<dt>1.11. License Owner</dt>
+<dd><p>means Joel Bodenmann (joel@unormal.org) and Andrew Hannam (andrewh@inmarket.com.au). Both parties are joint and severely owners of the license.</p></dd>
+<dt>1.12. Commercial Use</dt>
+<dd><p>means any use of the Works that may result in income or equivalent benefit in any form. Examples of Commercial Use include; selling an Application or Device containing the Works,
+ offering paid support to modify the Works, selling a library containing the Works. Examples of use that are NOT Commercial Use include; using the Works for Education, use of the Works in hobbyist projects that have no expectation of income, use of the Works in building what will later become a Commercial Use product.
+ Note that Commercial Use does not the prototyping and preparation for income generating activities - only the income producing activity itself.</p></dd>
+</dl>
+
+<h2>2. Non Commercial Use</h2>
+<h3>2.1. Distribution of source form</h3>
+<p>If You distribute the Works in an source form then:</p>
+<ol type="a">
+<li><p>All distribution of the Works in Source Code Form, including any Modifications that You create or to which You contribute, must be under the terms of this License; and</p></li>
+<li><p>You must inform recipients that the Source Code Form of the Works is governed by the terms of this License, and how they can obtain a copy of this License. You may not attempt to alter the recipients rights in the Source Code Form; and</p></li>
+<li><p>Any modification to the Works must be contributed to the License Owners, as per Section 4, prior to distribution with the exception of a working public source control repository. In this situation, modifications of the Works must be contributed to the License Owners within one calendar month; and</p></li>
+<li><p>source code not forming part of the Works that are distributed in conjunction with the Works do not need to be contributed to the License Owners or use this License.</p></li>
+</ol>
+<i><p>Note: This means that you must contribute changes you make to the library, you do not need to contribute your application or any other code outside of GFX library itself.</p></i>
+<h3>2.2. Distribution of Executable form</h3>
+<p>If You distribute the Works in an Executable form then:</p>
+<ol type="a">
+<li><p>and You must inform recipients of the Executable form that it contains the Works and how they can obtain a copy of the Works in Source Code Form from the License Owners master repository; and</p></li>
+<li><p>Any modification to the Works must be contributed to the License Owners as per Section 4 prior to distribution; and</p></li>
+<li><p>You may distribute such Executable form under the terms of this License, or license it under different terms, provided that the license for the Executable form does not allow for Commercial Use of the Works or attempt to limit or alter the recipients' rights in the Source Code Form under this License.</p></li>
+</ol>
+
+<h2>3. Commercial Use</h2>
+<h3>3.1. Commercial Use Agreement</h3>
+<p>A "Commercial Use Agreement" explicitly signed by the License Owner will override any specified terms of this License for the party to the agreement under the terms of the agreement. All other terms of this License will still apply.</p>
+<h3>3.2. Distribution</h3>
+<p>Other than as provided for in a signed "Commercial Use Agreement", where there is a Commercial Use involved or implied; you are not permitted to distribute the Works, in any form, either in source code or Executable form,
+ either as software or on a device or in any other way.</p>
+
+<h2>4. Contributions</h2>
+<h3>4.1. Contributor Grants</h3>
+<p>Each Contributor hereby irrevocably grants to the License Owner without fee or charge:</p>
+<ol type="a">
+<li><p>under intellectual property rights (other than patent or trademark) Licensable by such Contributor to use, reproduce, make available, modify, display, perform, distribute, relicense and otherwise exploit its Contributions, either on an unmodified basis, with Modifications, or as part of a Larger Work; and</p></li>
+<li><p>under Patent Claims of such Contributor to make, use, sell, offer for sale, have made, import, relicense and otherwise transfer its Contributions.</p></li>
+</ol>
+<h3>4.2. Effective Date</h3>
+<p>The licenses granted in Section&nbsp;4.1 with respect to any Contribution become effective for each Contribution on the date the Contributor first contributes or distributes such Contribution.</p>
+<h3>4.3. Limitations on Grant Scope</h3>
+<p>The grants made in this Section&nbsp;4 are the only rights granted. No additional rights or licenses will be implied from the distribution or licensing of the Works under this License. Notwithstanding Section&nbsp;4.1(b) above, no patent license is granted by a Contributor:</p>
+<ol type="a">
+<li><p>for any code that a Contributor has removed from Contribution; or</p></li>
+<li><p>under Patent Claims infringed by the Works in the absence of its Contributions.</p></li>
+</ol>
+<p>This License does not grant any rights in the trademarks, service marks, or logos of any Contributor (except as may be necessary to comply with the requirements in Section&nbsp;4.4).</p>
+<h3>4.4. Representation</h3>
+<p>Each Contributor represents that the Contributor believes its Contributions are its original creation(s) or it has sufficient rights to grant the rights to its Contributions conveyed by this License. Each Contributor accepts sole responsibility for the legal position of its Contribution and holds blameless the License Owners for such Contribution or any modification to it.</p>
+<h3>4.5. Deeming of Contributions</h3>
+<p>Each Contributor deems that by Contributing to the Works, through any method offered by the License Owners, irrespective of the license provided in the Contribution, is agreeing to the Contribution being licensed under this License with its Grants, Scope and Representation.</p>
+<h3>4.6. Original Source Rights</h3>
+<p>By contributing to the Works, the Contributor is not removing their own copyright in their original work. The original work retains all existing copyrights and other rights, except the rights as described above have been granted to the license owners on the copy of the contribution as contributed.</p>
+<p>This is equivelent to the "forking" of the contribution to two different licenses, one as part of the works (GFX) and the other as in its original form.</p>
+<h3>4.7. Additional Rights</h3>
+<p>A Contribution does not convey any extra distribution rights for the Contributor to the Works under this license.</p>
+
+
+<h2>5. Notices</h2>
+<p>You may not remove or alter the substance of any license notices (including copyright notices, patent notices, disclaimers of warranty, or limitations of liability) contained within the Source Code Form of the Works, except that You may alter any license notices to the extent required to remedy known factual inaccuracies.</p>
+<h2>6. Inability to Comply Due to Statute or Regulation</h2>
+<p>If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Works due to statute, judicial order, or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be Contributed to the License Owners and placed in a text file included with all distributions of the Works under this License. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it.</p>
+<h2>7. Termination</h2>
+<p>7.1. The distribution rights granted under this License will terminate automatically if You fail to comply with any of its terms. However, if You become compliant, then the rights granted under this License (a) provisionally, unless and until the License Owner explicitly and finally terminates Your grants, and (b) on an ongoing basis, if the License Owner fails to notify You of the non-compliance by some reasonable means prior to 60 days after You have come back into compliance.</p>
+<p>7.2. If You initiate litigation against any entity by asserting a patent infringement claim (excluding declaratory judgment actions, counter-claims, and cross-claims) alleging that the License Owner directly or indirectly infringes any patent, then the rights granted to You by the License Owner for the Works shall terminate.</p>
+<h2>8. Disclaimer of Warranty</h2>
+<p><em>Covered Software is provided under this License on an as is basis, without warranty of any kind, either expressed, implied, or statutory, including, without limitation, warranties that the Works is free of defects, merchantable, fit for a particular purpose or non-infringing. The entire risk as to the quality and performance of the Works is with You. Should any of the Works prove defective in any respect, You assume the cost of any necessary servicing, repair, or correction. This disclaimer of warranty constitutes an essential part of this License. No use of the Works is authorized under this License except under this disclaimer.</em></p>
+<h2>9. Limitation of Liability</h2>
+<p><em>Under no circumstances and under no legal theory, whether tort (including negligence), contract, or otherwise, shall the License Owner, any Contributor, or anyone who distributes the Works as permitted above, be liable to You for any direct, indirect, special, incidental, or consequential damages of any character including, without limitation, damages for lost profits, loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses, even if such party shall have been informed of the possibility of such damages.</em></p>
+<h2>10. Litigation</h2>
+<p>Any litigation relating to this License may be brought only in the courts of a jurisdiction where the defendant maintains its principal place of business and such litigation shall be governed by laws of that jurisdiction, without reference to its conflict-of-law provisions. Nothing in this Section shall prevent a party's ability to bring cross-claims or counter-claims.</p>
+<h2>11. Miscellaneous</h2>
+<p>This License represents the complete agreement concerning the subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not be used to construe this License against a Contributor ro the License Owner.</p>
+<h2>12. Versions of the License</h2>
+<h3>12.1. New Versions</h3>
+<p>The License Owner is the license steward. Except as provided in Section&nbsp;12.3, no one other than the license steward has the right to modify or publish new versions of this License. Each version will be given a distinguishing version number.</p>
+<h3>12.2. Effect of New Versions</h3>
+<p>You may distribute the Works under the terms of the version of the License under which You originally received the Works, or under the terms of any subsequent version published by the license steward.</p>
+<h3>12.3. Modified Versions</h3>
+<p>If you create software not governed by this License, and you want to create a new license for such software, you may create and use a modified version of this License if you rename the license and remove any references to the name of the License Owner (except to note that such modified license differs from this License).</p>
+
+<h2>Exhibit A - Source Code Form License Notice</h2>
+<pre>
+/*
+ * 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://chibios-gfx.com/license.html
+ */
+</pre>
+<p>If it is not possible or desirable to put the notice in a particular file, then You may include the notice in a location (such as a LICENSE file in a relevant directory) where a recipient would be likely to look for such a notice.</p>
+</body>
+</html>
diff --git a/src/gfx.c b/src/gfx.c
index 6a73d672..1791ef89 100644
--- a/src/gfx.c
+++ b/src/gfx.c
@@ -19,7 +19,7 @@ void DEPRECATED("Use gfxInit() instead") gdispInit() { gfxInit(); }
/* These init functions are defined by each module but not published */
extern void _gosInit(void);
-#if GFX_USE_GDISP && (GDISP_NEED_MULTITHREAD || GDISP_NEED_ASYNC)
+#if GFX_USE_GDISP
extern void _gdispInit(void);
#endif
#if GFX_USE_TDISP
diff --git a/src/ginput/dial.c b/src/ginput/dial.c
index 3afb4796..d978aa65 100644
--- a/src/ginput/dial.c
+++ b/src/ginput/dial.c
@@ -57,6 +57,7 @@ static void DialCallback(uint16_t instance, uint16_t rawvalue) {
pe->type = GEVENT_DIAL;
pe->instance = instance;
pe->value = pds->lastvalue;
+ pe->maxvalue = pds->max;
geventSendEvent(psl);
}
}
@@ -144,6 +145,7 @@ bool_t ginputGetDialStatus(uint16_t instance, GEventDial *pdial) {
pdial->type = GEVENT_DIAL;
pdial->instance = instance;
pdial->value = DialStatus[instance].lastvalue;
+ pdial->maxvalue = DialStatus[instance].max;
return TRUE;
}
diff --git a/src/gqueue/gqueue.c b/src/gqueue/gqueue.c
index 7cd1c9d9..beb42a2e 100644
--- a/src/gqueue/gqueue.c
+++ b/src/gqueue/gqueue.c
@@ -9,6 +9,9 @@
* @file src/gqueue/gqueue.c
* @brief GQUEUE source file.
*/
+
+#include "gfx.h"
+
#if GFX_USE_GQUEUE
#if GQUEUE_NEED_ASYNC
@@ -22,7 +25,8 @@
gfxSystemLock();
if ((pi = pqueue->head))
pqueue->head = pi->next;
- gfxSytemUnlock();
+ pi->next = 0;
+ gfxSystemUnlock();
return pi;
}
void gfxQueueASyncPut(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) {
@@ -46,17 +50,21 @@
gfxSystemUnlock();
}
void gfxQueueASyncRemove(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) {
+ gfxQueueASyncItem *pi;
+
if (!pitem) return;
gfxSystemLock();
if (pqueue->head) {
if (pqueue->head == pitem) {
pqueue->head = pitem->next;
+ pitem->next = 0;
} else {
- for(gfxQueueASyncItem *pi = pqueue->head; pi->next; pi = pi->next) {
+ for(pi = pqueue->head; pi->next; pi = pi->next) {
if (pi->next == pitem) {
pi->next = pitem->next;
if (pqueue->tail == pitem)
pqueue->tail = pi;
+ pitem->next = 0;
break;
}
}
@@ -68,8 +76,10 @@
return pqueue->head == NULL;
}
bool_t gfxQueueASyncIsIn(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) {
+ gfxQueueASyncItem *pi;
+
gfxSystemLock();
- for(gfxQueueASyncItem *pi = pqueue->head; pi; pi = pi->next) {
+ for(pi = pqueue->head; pi; pi = pi->next) {
if (pi == pitem) {
gfxSystemUnlock();
return TRUE;
@@ -92,6 +102,7 @@
gfxSystemLock();
pi = pqueue->head;
pqueue->head = pi->next;
+ pi->next = 0;
gfxSytemUnlock();
return pi;
}
@@ -120,17 +131,21 @@
gfxSemSignal(&pqueue->sem);
}
void gfxQueueGSyncRemove(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) {
+ gfxQueueGSyncItem *pi;
+
if (!pitem) return;
gfxSystemLock();
if (pqueue->head) {
if (pqueue->head == pitem) {
pqueue->head = pitem->next;
+ pitem->next = 0;
} else {
- for(gfxQueueGSyncItem *pi = pqueue->head; pi->next; pi = pi->next) {
+ for(pi = pqueue->head; pi->next; pi = pi->next) {
if (pi->next == pitem) {
pi->next = pitem->next;
if (pqueue->tail == pitem)
pqueue->tail = pi;
+ pitem->next = 0;
break;
}
}
@@ -142,8 +157,10 @@
return pqueue->head == NULL;
}
bool_t gfxQueueGSyncIsIn(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) {
+ gfxQueueGSyncItem *pi;
+
gfxSystemLock();
- for(gfxQueueGSyncItem *pi = pqueue->head; pi; pi = pi->next) {
+ for(pi = pqueue->head; pi; pi = pi->next) {
if (pi == pitem) {
gfxSystemUnlock();
return TRUE;
@@ -166,6 +183,7 @@
gfxSystemLock();
pi = pqueue->head;
pqueue->head = pi->next;
+ pi->next = 0;
gfxSytemUnlock();
gfxSemSignalI(&pi->sem);
@@ -202,18 +220,21 @@
return gfxSemWait(&pitem->sem, ms);
}
void gfxQueueFSyncRemove(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem) {
+ gfxQueueFSyncItem *pi;
+
if (!pitem) return;
gfxSystemLock();
if (pqueue->head) {
if (pqueue->head == pitem) {
pqueue->head = pitem->next;
found:
+ pitem->next = 0;
gfxSystemUnlock();
gfxSemSignal(&pitem->sem);
gfxSemDestroy(&pitem->sem);
return;
}
- for(gfxQueueFSyncItem *pi = pqueue->head; pi->next; pi = pi->next) {
+ for(pi = pqueue->head; pi->next; pi = pi->next) {
if (pi->next == pitem) {
pi->next = pitem->next;
if (pqueue->tail == pitem)
@@ -228,8 +249,10 @@
return pqueue->head == NULL;
}
bool_t gfxQueueFSyncIsIn(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem) {
+ gfxQueueASyncItem *pi;
+
gfxSystemLock();
- for(gfxQueueFSyncItem *pi = pqueue->head; pi; pi = pi->next) {
+ for(pi = pqueue->head; pi; pi = pi->next) {
if (pi == pitem) {
gfxSystemUnlock();
return TRUE;
diff --git a/src/gwin/button.c b/src/gwin/button.c
index 6b7306b5..fc432cb4 100644
--- a/src/gwin/button.c
+++ b/src/gwin/button.c
@@ -19,392 +19,336 @@
#if (GFX_USE_GWIN && GWIN_NEED_BUTTON) || defined(__DOXYGEN__)
-/* Parameters for various shapes */
+#include "gwin/class_gwin.h"
+
+// Parameters for various shapes
#define RND_CNR_SIZE 5 // Rounded corner size for rounded buttons
#define ARROWHEAD_DIVIDER 4 // A quarter of the height for the arrow head
#define ARROWBODY_DIVIDER 4 // A quarter of the width for the arrow body
-#include <string.h>
-
-#include "gwin/internal.h"
-
-#define GWIN_BUTTON_DEFAULT_SHAPE GBTN_3D
+// Our pressed state
+#define GBUTTON_FLG_PRESSED (GWIN_FIRST_CONTROL_FLAG<<0)
+
+// Prototypes for button VMT functions
+static void MouseDown(GWidgetObject *gw, coord_t x, coord_t y);
+static void MouseUp(GWidgetObject *gw, coord_t x, coord_t y);
+static void ToggleOff(GWidgetObject *gw, uint16_t role);
+static void ToggleOn(GWidgetObject *gw, uint16_t role);
+static void ToggleAssign(GWidgetObject *gw, uint16_t role, uint16_t instance);
+static uint16_t ToggleGet(GWidgetObject *gw, uint16_t role);
+
+// The button VMT table
+static const gwidgetVMT buttonVMT = {
+ {
+ "Button", // The classname
+ _gwidgetDestroy, // The destroy routine
+ _gwidgetRedraw, // The redraw routine
+ 0, // The after-clear routine
+ },
+ gwinButtonDraw_3D, // The default drawing routine
+ {
+ MouseDown, // Process mouse down events
+ MouseUp, // Process mouse up events
+ 0, // Process mouse move events (NOT USED)
+ },
+ {
+ 1, // 1 toggle role
+ ToggleAssign, // Assign Toggles
+ ToggleGet, // Get Toggles
+ ToggleOff, // Process toggle off events
+ ToggleOn, // Process toggle on events
+ },
+ {
+ 0, // No dial roles
+ 0, // Assign Dials (NOT USED)
+ 0, // Get Dials (NOT USED)
+ 0, // Process dial move events (NOT USED)
+ }
+};
-static const GButtonDrawStyle GButtonDefaultStyleUp = {
+// Default color scheme
+static const GButtonColors GButtonDefaultColorsUp = {
HTML2COLOR(0x404040), // color_up_edge;
HTML2COLOR(0xE0E0E0), // color_up_fill;
HTML2COLOR(0x000000), // color_up_txt;
};
-
-static const GButtonDrawStyle GButtonDefaultStyleDown = {
+static const GButtonColors GButtonDefaultColorsDown = {
HTML2COLOR(0x404040), // color_dn_edge;
HTML2COLOR(0x808080), // color_dn_fill;
HTML2COLOR(0x404040), // color_dn_txt;
};
+static const GButtonColors GButtonDefaultColorsDisabled = {
+ HTML2COLOR(0x808080), // color_dis_edge;
+ HTML2COLOR(0xE0E0E0), // color_dis_fill;
+ HTML2COLOR(0xC0C0C0), // color_dis_txt;
+};
-// Process an event callback
-static void gwinButtonCallback(void *param, GEvent *pe) {
- GSourceListener *psl;
- #define gh ((GHandle)param)
- #define gbw ((GButtonObject *)param)
- #define gsh ((GSourceHandle)param)
- #define pme ((GEventMouse *)pe)
- #define pte ((GEventTouch *)pe)
- #define pxe ((GEventToggle *)pe)
- #define pbe ((GEventGWinButton *)pe)
-
- // check if button is disabled
- if (!gh->enabled)
- return;
-
- switch (pe->type) {
- #if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
- case GEVENT_MOUSE:
- case GEVENT_TOUCH:
- // Ignore anything other than the primary mouse button going up or down
- if (!((pme->current_buttons ^ pme->last_buttons) & GINPUT_MOUSE_BTN_LEFT))
- return;
-
- if (gbw->state == GBTN_UP) {
- // Our button is UP: Test for button down over the button
- if ((pme->current_buttons & GINPUT_MOUSE_BTN_LEFT)
- && pme->x >= gbw->gwin.x && pme->x < gbw->gwin.x + gbw->gwin.width
- && pme->y >= gbw->gwin.y && pme->y < gbw->gwin.y + gbw->gwin.height) {
- gbw->state = GBTN_DOWN;
- gwinButtonDraw((GHandle)param);
- }
- return;
- }
-
- // Our button is DOWN
-
- // Skip more mouse downs
- if ((pme->current_buttons & GINPUT_MOUSE_BTN_LEFT))
- return;
-
- // This must be a mouse up - set the button as UP
- gbw->state = GBTN_UP;
- gwinButtonDraw((GHandle)param);
-
- #if GWIN_BUTTON_LAZY_RELEASE
- break;
- #else
- // If the mouse up was over the button then create the event
- if (pme->x >= gbw->gwin.x && pme->x < gbw->gwin.x + gbw->gwin.width
- && pme->y >= gbw->gwin.y && pme->y < gbw->gwin.y + gbw->gwin.height)
- break;
-
- return;
- #endif
- #endif
-
- #if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
- case GEVENT_TOGGLE:
- // State has changed - update the button
- gbw->state = pxe->on ? GBTN_DOWN : GBTN_UP;
- gwinButtonDraw((GHandle)param);
-
- // Trigger the event on button down (different than for mouse/touch)
- if (gbw->state == GBTN_DOWN)
- break;
-
- return;
- #endif
-
- default:
- return;
- }
+// Send the button event
+static void SendButtonEvent(GWidgetObject *gw) {
+ GSourceListener * psl;
+ GEvent * pe;
+ #define pbe ((GEventGWinButton *)pe)
// Trigger a GWIN Button Event
psl = 0;
- while ((psl = geventGetSourceListener(gsh, psl))) {
+ while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) {
if (!(pe = geventGetEventBuffer(psl)))
continue;
pbe->type = GEVENT_GWIN_BUTTON;
- pbe->button = gh;
+ pbe->button = (GHandle)gw;
geventSendEvent(psl);
}
#undef pbe
- #undef pme
- #undef pte
- #undef pxe
- #undef gsh
- #undef gbw
- #undef gh
}
-GHandle gwinCreateButton(GButtonObject *gb, coord_t x, coord_t y, coord_t width, coord_t height, font_t font, GButtonType type) {
- if (!(gb = (GButtonObject *)_gwinInit((GWindowObject *)gb, x, y, width, height, sizeof(GButtonObject))))
- return 0;
-
- gb->gwin.type = GW_BUTTON;
- gb->fn = 0;
- gb->param = 0;
- gwinSetFont(&gb->gwin, font);
- gwinSetButtonStyle(&gb->gwin, GWIN_BUTTON_DEFAULT_SHAPE, &GButtonDefaultStyleUp, &GButtonDefaultStyleDown);
- gb->type = type;
- gb->state = GBTN_UP;
- gb->txt = "";
- geventListenerInit(&gb->listener);
- geventRegisterCallback(&gb->listener, gwinButtonCallback, gb);
-
- // buttons are enabled by default
- gb->gwin.enabled = TRUE;
-
- return (GHandle)gb;
+// A mouse down has occurred over the button
+static void MouseDown(GWidgetObject *gw, coord_t x, coord_t y) {
+ (void) x; (void) y;
+ gw->g.flags |= GBUTTON_FLG_PRESSED;
+ _gwidgetRedraw((GHandle)gw);
}
-void gwinSetButtonStyle(GHandle gh, GButtonShape shape, const GButtonDrawStyle *pUp, const GButtonDrawStyle *pDown) {
- #define gbw ((GButtonObject *)gh)
- if (gh->type != GW_BUTTON)
- return;
+// A mouse up has occurred (it may or may not be over the button)
+static void MouseUp(GWidgetObject *gw, coord_t x, coord_t y) {
+ (void) x; (void) y;
+ gw->g.flags &= ~GBUTTON_FLG_PRESSED;
+ _gwidgetRedraw((GHandle)gw);
- switch(shape) {
- case GBTN_SQUARE: gbw->fn = gwinButtonDraw_Square; break;
- #if GDISP_NEED_ARC
- case GBTN_ROUNDED: gbw->fn = gwinButtonDraw_Rounded; break;
- #endif
- #if GDISP_NEED_ELLIPSE
- case GBTN_ELLIPSE: gbw->fn = gwinButtonDraw_Ellipse; break;
- #endif
-
- #if GDISP_NEED_CONVEX_POLYGON
- case GBTN_ARROW_UP: gbw->fn = gwinButtonDraw_ArrowUp; break;
- case GBTN_ARROW_DOWN: gbw->fn = gwinButtonDraw_ArrowDown; break;
- case GBTN_ARROW_LEFT: gbw->fn = gwinButtonDraw_ArrowLeft; break;
- case GBTN_ARROW_RIGHT: gbw->fn = gwinButtonDraw_ArrowRight; break;
- #endif
-
- case GBTN_CUSTOM: if (gbw->fn) break; /* Fall Through */
- case GBTN_3D: /* Fall through */
- default: gbw->fn = gwinButtonDraw_3D; break;
- }
- if (pUp) {
- gbw->up.color_edge = pUp->color_edge;
- gbw->up.color_fill = pUp->color_fill;
- gbw->up.color_txt = pUp->color_txt;
- }
- if (pDown) {
- gbw->dn.color_edge = pDown->color_edge;
- gbw->dn.color_fill = pDown->color_fill;
- gbw->dn.color_txt = pDown->color_txt;
- }
- #undef gbw
+ #if !GWIN_BUTTON_LAZY_RELEASE
+ // If the mouse up was not over the button then cancel the event
+ if (x < 0 || y < 0 || x >= gw->g.width || y >= gw->g.height)
+ return;
+ #endif
+
+ SendButtonEvent(gw);
}
-void gwinSetButtonText(GHandle gh, const char *txt, bool_t useAlloc) {
- #define gbw ((GButtonObject *)gh)
- if (gh->type != GW_BUTTON)
- return;
+// A toggle off has occurred
+static void ToggleOff(GWidgetObject *gw, uint16_t role) {
+ (void) role;
+ gw->g.flags &= ~GBUTTON_FLG_PRESSED;
+ _gwidgetRedraw((GHandle)gw);
+}
- // Dispose of the old string
- if ((gh->flags & GBTN_FLG_ALLOCTXT)) {
- gh->flags &= ~GBTN_FLG_ALLOCTXT;
- if (gbw->txt) {
- gfxFree((void *)gbw->txt);
- gbw->txt = "";
- }
- }
- // Alloc the new text if required
- if (txt && useAlloc) {
- char *str;
-
- if ((str = (char *)gfxAlloc(strlen(txt)+1))) {
- gh->flags |= GBTN_FLG_ALLOCTXT;
- strcpy(str, txt);
- }
- txt = (const char *)str;
- }
-
- gbw->txt = txt ? txt : "";
- #undef gbw
+// A toggle on has occurred
+static void ToggleOn(GWidgetObject *gw, uint16_t role) {
+ (void) role;
+ gw->g.flags |= GBUTTON_FLG_PRESSED;
+ _gwidgetRedraw((GHandle)gw);
+ // Trigger the event on button down (different than for mouse/touch)
+ SendButtonEvent(gw);
}
-void gwinButtonDraw(GHandle gh) {
- #define gbw ((GButtonObject *)gh)
-
- if (gh->type != GW_BUTTON)
- return;
+static void ToggleAssign(GWidgetObject *gw, uint16_t role, uint16_t instance) {
+ (void) role;
+ ((GButtonObject *)gw)->toggle = instance;
+}
- #if GDISP_NEED_CLIP
- gdispSetClip(gh->x, gh->y, gh->width, gh->height);
- #endif
+static uint16_t ToggleGet(GWidgetObject *gw, uint16_t role) {
+ (void) role;
+ return ((GButtonObject *)gw)->toggle;
+}
- gbw->fn(gh,
- gbw->gwin.enabled,
- gbw->state == GBTN_DOWN,
- gh->font && gbw->txt ? gbw->txt : "",
- gbw->state == GBTN_DOWN ? &gbw->dn : &gbw->up,
- gbw->param);
+GHandle gwinCreateButton(GButtonObject *gw, coord_t x, coord_t y, coord_t width, coord_t height) {
+ if (!(gw = (GButtonObject *)_gwidgetCreate((GWidgetObject *)gw, x, y, width, height, sizeof(GButtonObject), &buttonVMT)))
+ return 0;
- #undef gbw
+ gw->toggle = GWIDGET_NO_INSTANCE;
+ gw->c_up = GButtonDefaultColorsUp;
+ gw->c_dn = GButtonDefaultColorsDown;
+ gw->c_dis = GButtonDefaultColorsDisabled;
+ return (GHandle)gw;
}
-void gwinSetButtonCustom(GHandle gh, GButtonDrawFunction fn, void *param) {
- #define gbw ((GButtonObject *)gh)
-
- if (gh->type != GW_BUTTON)
+void gwinSetButtonColors(GHandle gh, const GButtonColors *pUp, const GButtonColors *pDown, const GButtonColors *pDisabled) {
+ if (gh->vmt != (gwinVMT *)&buttonVMT)
return;
- gbw->fn = fn ? fn : gwinButtonDraw_3D;
- gbw->param = param;
+ if (pUp) ((GButtonObject *)gh)->c_up = *pUp;
+ if (pDown) ((GButtonObject *)gh)->c_dn = *pDown;
+ if (pDisabled) ((GButtonObject *)gh)->c_dis = *pDisabled;
+}
+
+bool_t gwinIsButtonPressed(GHandle gh) {
+ if (gh->vmt != (gwinVMT *)&buttonVMT)
+ return FALSE;
- #undef gbw
+ return (gh->flags & GBUTTON_FLG_PRESSED) ? TRUE : FALSE;
}
-void gwinButtonSetEnabled(GHandle gh, bool_t enabled) {
- if (gh->type != GW_BUTTON)
- return;
+/*----------------------------------------------------------
+ * Custom Draw Routines
+ *----------------------------------------------------------*/
- gh->enabled = enabled;
+static GButtonColors *getDrawColors(GWidgetObject *gw) {
+ if (!(gw->g.flags & GWIN_FLG_ENABLED)) return &((GButtonObject *)gw)->c_dis;
+ if ((gw->g.flags & GBUTTON_FLG_PRESSED)) return &((GButtonObject *)gw)->c_dn;
+ return &((GButtonObject *)gw)->c_up;
}
-void gwinButtonDraw_3D(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
- (void) enabled;
- (void) isdown;
- (void) param;
+void gwinButtonDraw_3D(GWidgetObject *gw, void *param) {
+ (void) param;
+ GButtonColors * pcol;
- gdispFillStringBox(gh->x, gh->y, gh->width-1, gh->height-1, txt, gh->font, pstyle->color_txt, pstyle->color_fill, justifyCenter);
- gdispDrawLine(gh->x+gh->width-1, gh->y, gh->x+gh->width-1, gh->y+gh->height-1, pstyle->color_edge);
- gdispDrawLine(gh->x, gh->y+gh->height-1, gh->x+gh->width-2, gh->y+gh->height-1, pstyle->color_edge);
+ if (gw->g.vmt != (gwinVMT *)&buttonVMT) return;
+ pcol = getDrawColors(gw);
+
+ gdispFillStringBox(gw->g.x, gw->g.y, gw->g.width-1, gw->g.height-1, gw->txt, gw->g.font, pcol->color_txt, pcol->color_fill, justifyCenter);
+ gdispDrawLine(gw->g.x+gw->g.width-1, gw->g.y, gw->g.x+gw->g.width-1, gw->g.y+gw->g.height-1, pcol->color_edge);
+ gdispDrawLine(gw->g.x, gw->g.y+gw->g.height-1, gw->g.x+gw->g.width-2, gw->g.y+gw->g.height-1, pcol->color_edge);
}
-void gwinButtonDraw_Square(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
- (void) enabled;
- (void) isdown;
- (void) param;
+void gwinButtonDraw_Box(GWidgetObject *gw, void *param) {
+ (void) param;
+ GButtonColors * pcol;
- gdispFillStringBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, txt, gh->font, pstyle->color_txt, pstyle->color_fill, justifyCenter);
- gdispDrawBox(gh->x, gh->y, gh->width, gh->height, pstyle->color_edge);
+ if (gw->g.vmt != (gwinVMT *)&buttonVMT) return;
+ pcol = getDrawColors(gw);
+
+ gdispFillStringBox(gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->txt, gw->g.font, pcol->color_txt, pcol->color_fill, justifyCenter);
+ gdispDrawBox(gw->g.x, gw->g.y, gw->g.width, gw->g.height, pcol->color_edge);
}
#if GDISP_NEED_ARC
- void gwinButtonDraw_Rounded(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
- (void) enabled;
- (void) isdown;
- (void) param;
-
- if (gh->width >= 2*RND_CNR_SIZE+10) {
- gdispFillRoundedBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, RND_CNR_SIZE-1, pstyle->color_fill);
- gdispDrawStringBox(gh->x+1, gh->y+RND_CNR_SIZE, gh->width-2, gh->height-(2*RND_CNR_SIZE), txt, gh->font, pstyle->color_txt, justifyCenter);
- gdispDrawRoundedBox(gh->x, gh->y, gh->width, gh->height, RND_CNR_SIZE, pstyle->color_edge);
+ void gwinButtonDraw_Rounded(GWidgetObject *gw, void *param) {
+ (void) param;
+ GButtonColors * pcol;
+
+ if (gw->g.vmt != (gwinVMT *)&buttonVMT) return;
+ pcol = getDrawColors(gw);
+
+ if (gw->g.width >= 2*RND_CNR_SIZE+10) {
+ gdispFillRoundedBox(gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, RND_CNR_SIZE-1, pcol->color_fill);
+ gdispDrawStringBox(gw->g.x+1, gw->g.y+RND_CNR_SIZE, gw->g.width-2, gw->g.height-(2*RND_CNR_SIZE), gw->txt, gw->g.font, pcol->color_txt, justifyCenter);
+ gdispDrawRoundedBox(gw->g.x, gw->g.y, gw->g.width, gw->g.height, RND_CNR_SIZE, pcol->color_edge);
} else {
- gdispFillStringBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, txt, gh->font, pstyle->color_txt, pstyle->color_fill, justifyCenter);
- gdispDrawBox(gh->x, gh->y, gh->width, gh->height, pstyle->color_edge);
+ gdispFillStringBox(gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->txt, gw->g.font, pcol->color_txt, pcol->color_fill, justifyCenter);
+ gdispDrawBox(gw->g.x, gw->g.y, gw->g.width, gw->g.height, pcol->color_edge);
}
}
#endif
#if GDISP_NEED_ELLIPSE
- void gwinButtonDraw_Ellipse(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
- (void) enabled;
- (void) isdown;
- (void) param;
-
- gdispFillEllipse(gh->x+1, gh->y+1, gh->width/2-1, gh->height/2-1, pstyle->color_fill);
- gdispDrawStringBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, txt, gh->font, pstyle->color_txt, justifyCenter);
- gdispDrawEllipse(gh->x, gh->y, gh->width/2, gh->height/2, pstyle->color_edge);
+ void gwinButtonDraw_Ellipse(GWidgetObject *gw, void *param) {
+ (void) param;
+ GButtonColors * pcol;
+
+ if (gw->g.vmt != (gwinVMT *)&buttonVMT) return;
+ pcol = getDrawColors(gw);
+
+ gdispFillEllipse(gw->g.x+1, gw->g.y+1, gw->g.width/2-1, gw->g.height/2-1, pcol->color_fill);
+ gdispDrawStringBox(gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->txt, gw->g.font, pcol->color_txt, justifyCenter);
+ gdispDrawEllipse(gw->g.x, gw->g.y, gw->g.width/2, gw->g.height/2, pcol->color_edge);
}
#endif
#if GDISP_NEED_CONVEX_POLYGON
- void gwinButtonDraw_ArrowUp(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
- (void) enabled;
- (void) isdown;
- (void) param;
- point arw[7];
-
- arw[0].x = gh->width/2; arw[0].y = 0;
- arw[1].x = gh->width-1; arw[1].y = gh->height/ARROWHEAD_DIVIDER;
- arw[2].x = (gh->width + gh->width/ARROWBODY_DIVIDER)/2; arw[2].y = gh->height/ARROWHEAD_DIVIDER;
- arw[3].x = (gh->width + gh->width/ARROWBODY_DIVIDER)/2; arw[3].y = gh->height-1;
- arw[4].x = (gh->width - gh->width/ARROWBODY_DIVIDER)/2; arw[4].y = gh->height-1;
- arw[5].x = (gh->width - gh->width/ARROWBODY_DIVIDER)/2; arw[5].y = gh->height/ARROWHEAD_DIVIDER;
- arw[6].x = 0; arw[6].y = gh->height/ARROWHEAD_DIVIDER;
-
- gdispFillConvexPoly(gh->x, gh->y, arw, 7, pstyle->color_fill);
- gdispDrawPoly(gh->x, gh->y, arw, 7, pstyle->color_edge);
- gdispDrawStringBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, txt, gh->font, pstyle->color_txt, justifyCenter);
+ void gwinButtonDraw_ArrowUp(GWidgetObject *gw, void *param) {
+ (void) param;
+ GButtonColors * pcol;
+ point arw[7];
+
+ if (gw->g.vmt != (gwinVMT *)&buttonVMT) return;
+ pcol = getDrawColors(gw);
+
+ arw[0].x = gw->g.width/2; arw[0].y = 0;
+ arw[1].x = gw->g.width-1; arw[1].y = gw->g.height/ARROWHEAD_DIVIDER;
+ arw[2].x = (gw->g.width + gw->g.width/ARROWBODY_DIVIDER)/2; arw[2].y = gw->g.height/ARROWHEAD_DIVIDER;
+ arw[3].x = (gw->g.width + gw->g.width/ARROWBODY_DIVIDER)/2; arw[3].y = gw->g.height-1;
+ arw[4].x = (gw->g.width - gw->g.width/ARROWBODY_DIVIDER)/2; arw[4].y = gw->g.height-1;
+ arw[5].x = (gw->g.width - gw->g.width/ARROWBODY_DIVIDER)/2; arw[5].y = gw->g.height/ARROWHEAD_DIVIDER;
+ arw[6].x = 0; arw[6].y = gw->g.height/ARROWHEAD_DIVIDER;
+
+ gdispFillConvexPoly(gw->g.x, gw->g.y, arw, 7, pcol->color_fill);
+ gdispDrawPoly(gw->g.x, gw->g.y, arw, 7, pcol->color_edge);
+ gdispDrawStringBox(gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->txt, gw->g.font, pcol->color_txt, justifyCenter);
}
- void gwinButtonDraw_ArrowDown(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
- (void) enabled;
- (void) isdown;
- (void) param;
- point arw[7];
-
- arw[0].x = gh->width/2; arw[0].y = gh->height-1;
- arw[1].x = gh->width-1; arw[1].y = gh->height-1-gh->height/ARROWHEAD_DIVIDER;
- arw[2].x = (gh->width + gh->width/ARROWBODY_DIVIDER)/2; arw[2].y = gh->height-1-gh->height/ARROWHEAD_DIVIDER;
- arw[3].x = (gh->width + gh->width/ARROWBODY_DIVIDER)/2; arw[3].y = 0;
- arw[4].x = (gh->width - gh->width/ARROWBODY_DIVIDER)/2; arw[4].y = 0;
- arw[5].x = (gh->width - gh->width/ARROWBODY_DIVIDER)/2; arw[5].y = gh->height-1-gh->height/ARROWHEAD_DIVIDER;
- arw[6].x = 0; arw[6].y = gh->height-1-gh->height/ARROWHEAD_DIVIDER;
-
- gdispFillConvexPoly(gh->x, gh->y, arw, 7, pstyle->color_fill);
- gdispDrawPoly(gh->x, gh->y, arw, 7, pstyle->color_edge);
- gdispDrawStringBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, txt, gh->font, pstyle->color_txt, justifyCenter);
+ void gwinButtonDraw_ArrowDown(GWidgetObject *gw, void *param) {
+ (void) param;
+ GButtonColors * pcol;
+ point arw[7];
+
+ if (gw->g.vmt != (gwinVMT *)&buttonVMT) return;
+ pcol = getDrawColors(gw);
+
+ arw[0].x = gw->g.width/2; arw[0].y = gw->g.height-1;
+ arw[1].x = gw->g.width-1; arw[1].y = gw->g.height-1-gw->g.height/ARROWHEAD_DIVIDER;
+ arw[2].x = (gw->g.width + gw->g.width/ARROWBODY_DIVIDER)/2; arw[2].y = gw->g.height-1-gw->g.height/ARROWHEAD_DIVIDER;
+ arw[3].x = (gw->g.width + gw->g.width/ARROWBODY_DIVIDER)/2; arw[3].y = 0;
+ arw[4].x = (gw->g.width - gw->g.width/ARROWBODY_DIVIDER)/2; arw[4].y = 0;
+ arw[5].x = (gw->g.width - gw->g.width/ARROWBODY_DIVIDER)/2; arw[5].y = gw->g.height-1-gw->g.height/ARROWHEAD_DIVIDER;
+ arw[6].x = 0; arw[6].y = gw->g.height-1-gw->g.height/ARROWHEAD_DIVIDER;
+
+ gdispFillConvexPoly(gw->g.x, gw->g.y, arw, 7, pcol->color_fill);
+ gdispDrawPoly(gw->g.x, gw->g.y, arw, 7, pcol->color_edge);
+ gdispDrawStringBox(gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->txt, gw->g.font, pcol->color_txt, justifyCenter);
}
- void gwinButtonDraw_ArrowLeft(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
- (void) enabled;
- (void) isdown;
- (void) param;
- point arw[7];
-
- arw[0].x = 0; arw[0].y = gh->height/2;
- arw[1].x = gh->width/ARROWHEAD_DIVIDER; arw[1].y = 0;
- arw[2].x = gh->width/ARROWHEAD_DIVIDER; arw[2].y = (gh->height - gh->height/ARROWBODY_DIVIDER)/2;
- arw[3].x = gh->width-1; arw[3].y = (gh->height - gh->height/ARROWBODY_DIVIDER)/2;
- arw[4].x = gh->width-1; arw[4].y = (gh->height + gh->height/ARROWBODY_DIVIDER)/2;
- arw[5].x = gh->width/ARROWHEAD_DIVIDER; arw[5].y = (gh->height + gh->height/ARROWBODY_DIVIDER)/2;
- arw[6].x = gh->width/ARROWHEAD_DIVIDER; arw[6].y = gh->height-1;
-
- gdispFillConvexPoly(gh->x, gh->y, arw, 7, pstyle->color_fill);
- gdispDrawPoly(gh->x, gh->y, arw, 7, pstyle->color_edge);
- gdispDrawStringBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, txt, gh->font, pstyle->color_txt, justifyCenter);
+ void gwinButtonDraw_ArrowLeft(GWidgetObject *gw, void *param) {
+ (void) param;
+ GButtonColors * pcol;
+ point arw[7];
+
+ if (gw->g.vmt != (gwinVMT *)&buttonVMT) return;
+ pcol = getDrawColors(gw);
+
+ arw[0].x = 0; arw[0].y = gw->g.height/2;
+ arw[1].x = gw->g.width/ARROWHEAD_DIVIDER; arw[1].y = 0;
+ arw[2].x = gw->g.width/ARROWHEAD_DIVIDER; arw[2].y = (gw->g.height - gw->g.height/ARROWBODY_DIVIDER)/2;
+ arw[3].x = gw->g.width-1; arw[3].y = (gw->g.height - gw->g.height/ARROWBODY_DIVIDER)/2;
+ arw[4].x = gw->g.width-1; arw[4].y = (gw->g.height + gw->g.height/ARROWBODY_DIVIDER)/2;
+ arw[5].x = gw->g.width/ARROWHEAD_DIVIDER; arw[5].y = (gw->g.height + gw->g.height/ARROWBODY_DIVIDER)/2;
+ arw[6].x = gw->g.width/ARROWHEAD_DIVIDER; arw[6].y = gw->g.height-1;
+
+ gdispFillConvexPoly(gw->g.x, gw->g.y, arw, 7, pcol->color_fill);
+ gdispDrawPoly(gw->g.x, gw->g.y, arw, 7, pcol->color_edge);
+ gdispDrawStringBox(gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->txt, gw->g.font, pcol->color_txt, justifyCenter);
}
- void gwinButtonDraw_ArrowRight(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
- (void) enabled;
- (void) isdown;
- (void) param;
- point arw[7];
-
- arw[0].x = gh->width-1; arw[0].y = gh->height/2;
- arw[1].x = gh->width-1-gh->width/ARROWHEAD_DIVIDER; arw[1].y = 0;
- arw[2].x = gh->width-1-gh->width/ARROWHEAD_DIVIDER; arw[2].y = (gh->height - gh->height/ARROWBODY_DIVIDER)/2;
- arw[3].x = 0; arw[3].y = (gh->height - gh->height/ARROWBODY_DIVIDER)/2;
- arw[4].x = 0; arw[4].y = (gh->height + gh->height/ARROWBODY_DIVIDER)/2;
- arw[5].x = gh->width-1-gh->width/ARROWHEAD_DIVIDER; arw[5].y = (gh->height + gh->height/ARROWBODY_DIVIDER)/2;
- arw[6].x = gh->width-1-gh->width/ARROWHEAD_DIVIDER; arw[6].y = gh->height-1;
-
- gdispFillConvexPoly(gh->x, gh->y, arw, 7, pstyle->color_fill);
- gdispDrawPoly(gh->x, gh->y, arw, 7, pstyle->color_edge);
- gdispDrawStringBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, txt, gh->font, pstyle->color_txt, justifyCenter);
+ void gwinButtonDraw_ArrowRight(GWidgetObject *gw, void *param) {
+ (void) param;
+ GButtonColors * pcol;
+ point arw[7];
+
+ if (gw->g.vmt != (gwinVMT *)&buttonVMT) return;
+ pcol = getDrawColors(gw);
+
+ arw[0].x = gw->g.width-1; arw[0].y = gw->g.height/2;
+ arw[1].x = gw->g.width-1-gw->g.width/ARROWHEAD_DIVIDER; arw[1].y = 0;
+ arw[2].x = gw->g.width-1-gw->g.width/ARROWHEAD_DIVIDER; arw[2].y = (gw->g.height - gw->g.height/ARROWBODY_DIVIDER)/2;
+ arw[3].x = 0; arw[3].y = (gw->g.height - gw->g.height/ARROWBODY_DIVIDER)/2;
+ arw[4].x = 0; arw[4].y = (gw->g.height + gw->g.height/ARROWBODY_DIVIDER)/2;
+ arw[5].x = gw->g.width-1-gw->g.width/ARROWHEAD_DIVIDER; arw[5].y = (gw->g.height + gw->g.height/ARROWBODY_DIVIDER)/2;
+ arw[6].x = gw->g.width-1-gw->g.width/ARROWHEAD_DIVIDER; arw[6].y = gw->g.height-1;
+
+ gdispFillConvexPoly(gw->g.x, gw->g.y, arw, 7, pcol->color_fill);
+ gdispDrawPoly(gw->g.x, gw->g.y, arw, 7, pcol->color_edge);
+ gdispDrawStringBox(gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->txt, gw->g.font, pcol->color_txt, justifyCenter);
}
#endif
-#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
- bool_t gwinAttachButtonMouse(GHandle gh, uint16_t instance) {
- GSourceHandle gsh;
-
- if (gh->type != GW_BUTTON || !(gsh = ginputGetMouse(instance)))
- return FALSE;
+#if GDISP_NEED_IMAGE || defined(__DOXYGEN__)
+ void gwinButtonDraw_Image(GWidgetObject *gw, void *param) {
+ GButtonColors * pcol;
+ coord_t sy;
- return geventAttachSource(&((GButtonObject *)gh)->listener, gsh, GLISTEN_MOUSEMETA);
- }
-#endif
+ if (gw->g.vmt != (gwinVMT *)&buttonVMT) return;
-#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
- bool_t gwinAttachButtonToggle(GHandle gh, uint16_t instance) {
- GSourceHandle gsh;
-
- if (gh->type != GW_BUTTON || !(gsh = ginputGetToggle(instance)))
- return FALSE;
+ if (!(gw->g.flags & GWIN_FLG_ENABLED)) {
+ pcol = &((GButtonObject *)gw)->c_dis;
+ sy = 2 * gw->g.height;
+ } else if ((gw->g.flags & GBUTTON_FLG_PRESSED)) {
+ pcol = &((GButtonObject *)gw)->c_dn;
+ sy = gw->g.height;
+ } else {
+ pcol = &((GButtonObject *)gw)->c_up;
+ sy = 0;
+ }
- return geventAttachSource(&((GButtonObject *)gh)->listener, gsh, GLISTEN_TOGGLE_OFF|GLISTEN_TOGGLE_ON);
+ gdispImageDraw((gdispImage *)param, gw->g.x, gw->g.y, gw->g.width, gw->g.height, 0, sy);
+ gdispDrawStringBox(gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->txt, gw->g.font, pcol->color_txt, justifyCenter);
}
#endif
diff --git a/src/gwin/checkbox.c b/src/gwin/checkbox.c
index faea0ef9..0282df42 100644
--- a/src/gwin/checkbox.c
+++ b/src/gwin/checkbox.c
@@ -7,7 +7,7 @@
/**
* @file src/gwin/checkbox.c
- * @brief GWIN sub-system checkbox code.
+ * @brief GWIN sub-system button code.
*
* @defgroup Checkbox Checkbox
* @ingroup GWIN
@@ -19,168 +19,160 @@
#if (GFX_USE_GWIN && GWIN_NEED_CHECKBOX) || defined(__DOXYGEN__)
-static const GCheckboxColor defaultColors = {
- Grey, // border
- Grey, // selected
- Black // background
+#include "gwin/class_gwin.h"
+
+// Our checked state
+#define GCHECKBOX_FLG_CHECKED (GWIN_FIRST_CONTROL_FLAG<<0)
+
+// Prototypes for button VMT functions
+static void MouseDown(GWidgetObject *gw, coord_t x, coord_t y);
+static void ToggleOn(GWidgetObject *gw, uint16_t role);
+static void ToggleAssign(GWidgetObject *gw, uint16_t role, uint16_t instance);
+static uint16_t ToggleGet(GWidgetObject *gw, uint16_t role);
+
+// The button VMT table
+static const gwidgetVMT checkboxVMT = {
+ {
+ "Checkbox", // The classname
+ _gwidgetDestroy, // The destroy routine
+ _gwidgetRedraw, // The redraw routine
+ 0, // The after-clear routine
+ },
+ gwinCheckboxDraw_CheckOnLeft, // The default drawing routine
+ {
+ MouseDown, // Process mouse down events
+ 0, // Process mouse up events (NOT USED)
+ 0, // Process mouse move events (NOT USED)
+ },
+ {
+ 1, // 1 toggle role
+ ToggleAssign, // Assign Toggles
+ ToggleGet, // Get Toggles
+ 0, // Process toggle off events (NOT USED)
+ ToggleOn, // Process toggle on events
+ },
+ {
+ 0, // No dial roles
+ 0, // Assign Dials (NOT USED)
+ 0, // Get Dials (NOT USED)
+ 0, // Process dial move events (NOT USED)
+ }
};
-/* default style drawing routine */
-static void gwinCheckboxDrawDefaultStyle(GHandle gh, bool_t enabled, bool_t isChecked, void* param) {
- #define gcw ((GCheckboxObject *)gh)
-
- (void) enabled;
- (void) param;
-
- gdispDrawBox(gh->x, gh->y, gh->width, gh->height, gcw->colors->border);
-
- if (isChecked)
- gdispFillArea(gh->x+2, gh->y+2, gh->width-4, gh->height-4, gcw->colors->checked);
- else
- gdispFillArea(gh->x+2, gh->y+2, gh->width-4, gh->height-4, gcw->colors->bg);
-
- #undef gcw
-}
-
-/* process an event callback */
-static void gwinCheckboxCallback(void *param, GEvent *pe) {
- GSourceListener *psl;
- #define gh ((GHandle)param)
- #define gbw ((GCheckboxObject *)param)
- #define gsh ((GSourceHandle)param)
- #define pme ((GEventMouse *)pe)
- #define pte ((GEventTouch *)pe)
- #define pxe ((GEventToggle *)pe)
- #define pbe ((GEventGWinCheckbox *)pe)
-
- /* check if checkbox is disabled */
- if (!gh->enabled)
- return;
-
- switch (pe->type) {
- #if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
- case GEVENT_MOUSE:
- case GEVENT_TOUCH:
-
- // Ignore anything other than the primary mouse button going up or down
- if (!((pme->current_buttons ^ pme->last_buttons) & GINPUT_MOUSE_BTN_LEFT))
- return;
-
- if ((pme->current_buttons & GINPUT_MOUSE_BTN_LEFT)
- && pme->x >= gbw->gwin.x && pme->x < gbw->gwin.x + gbw->gwin.width
- && pme->y >= gbw->gwin.y && pme->y < gbw->gwin.y + gbw->gwin.height) {
-
- gbw->isChecked = !gbw->isChecked;
+static const GCheckboxColors defaultColors = {
+ Black, // border
+ Grey, // selected
+ White, // background
+ Black, // text
+};
- gwinCheckboxDraw((GHandle)param);
- break;
- }
- return;
- #endif /* GFX_USE_GINPUT && GINPUT_NEED_MOUSE */
+// Send the checkbox event
+static void SendCheckboxEvent(GWidgetObject *gw) {
+ GSourceListener * psl;
+ GEvent * pe;
+ #define pce ((GEventGWinCheckbox *)pe)
- default:
- return;
- }
-
- // Trigger a GWIN checkbox event
+ // Trigger a GWIN Checkbox Event
psl = 0;
- while ((psl = geventGetSourceListener(gsh, psl))) {
+ while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) {
if (!(pe = geventGetEventBuffer(psl)))
continue;
- pbe->type = GEVENT_GWIN_CHECKBOX;
- pbe->checkbox = gh;
- pbe->isChecked = gbw->isChecked;
+ pce->type = GEVENT_GWIN_CHECKBOX;
+ pce->checkbox = &gw->g;
+ pce->isChecked = (gw->g.flags & GCHECKBOX_FLG_CHECKED) ? TRUE : FALSE;
geventSendEvent(psl);
- }
-
- #undef gh
- #undef pbe
- #undef pme
- #undef pte
- #undef pxe
- #undef gsh
- #undef gbw
-}
+ }
-GHandle gwinCheckboxCreate(GCheckboxObject *gb, coord_t x, coord_t y, coord_t width, coord_t height) {
- if (!(gb = (GCheckboxObject *)_gwinInit((GWindowObject *)gb, x, y, width, height, sizeof(GCheckboxObject))))
- return 0;
+ #undef pce
+}
- gb->gwin.type = GW_CHECKBOX; // create a window of the type checkbox
- gb->fn = gwinCheckboxDrawDefaultStyle; // set the default style drawing routine
- gb->colors = &defaultColors; // asign the default colors
- gb->param = 0; // some safe value here
- gb->isChecked = GCHBX_UNCHECKED; // checkbox is currently unchecked
- gb->gwin.enabled = TRUE; // checkboxes are enabled by default
+// A mouse down has occurred over the checkbox
+static void MouseDown(GWidgetObject *gw, coord_t x, coord_t y) {
+ (void) x; (void) y;
+ gw->g.flags ^= GCHECKBOX_FLG_CHECKED;
+ _gwidgetRedraw((GHandle)gw);
+ SendCheckboxEvent(gw);
+}
- geventListenerInit(&gb->listener);
- geventRegisterCallback(&gb->listener, gwinCheckboxCallback, gb);
+// A toggle on has occurred
+static void ToggleOn(GWidgetObject *gw, uint16_t role) {
+ (void) role;
+ gw->g.flags ^= GCHECKBOX_FLG_CHECKED;
+ _gwidgetRedraw((GHandle)gw);
+ SendCheckboxEvent(gw);
+}
- // checkboxes are enabled by default
- gb->gwin.enabled = TRUE;
+static void ToggleAssign(GWidgetObject *gw, uint16_t role, uint16_t instance) {
+ (void) role;
+ ((GCheckboxObject *)gw)->toggle = instance;
+}
- return (GHandle)gb;
+static uint16_t ToggleGet(GWidgetObject *gw, uint16_t role) {
+ (void) role;
+ return ((GCheckboxObject *)gw)->toggle;
}
-void gwinCheckboxSetCustom(GHandle gh, GCheckboxDrawFunction fn, void *param) {
- #define gcw ((GCheckboxObject *)gh)
+GHandle gwinCreateCheckbox(GCheckboxObject *gb, coord_t x, coord_t y, coord_t width, coord_t height) {
+ if (!(gb = (GCheckboxObject *)_gwidgetCreate((GWidgetObject *)gb, x, y, width, height, sizeof(GCheckboxObject), &checkboxVMT)))
+ return 0;
- if (gh->type != GW_CHECKBOX)
- return;
+ gb->toggle = (uint16_t) -1;
+ gb->c = defaultColors; // assign the default colors
+ return (GHandle)gb;
+}
- gcw->fn = fn;
- gcw->param = param;
+bool_t gwinIsCheckboxChecked(GHandle gh) {
+ if (gh->vmt != (gwinVMT *)&checkboxVMT)
+ return FALSE;
- #undef gcw
+ return (gh->flags & GCHECKBOX_FLG_CHECKED) ? TRUE : FALSE;
}
-
-void gwinCheckboxSetEnabled(GHandle gh, bool_t enabled) {
- if (gh->type != GW_CHECKBOX)
+void gwinCheckboxSetColors(GHandle gh, GCheckboxColors *pColors) {
+ if (gh->vmt != (gwinVMT *)&checkboxVMT)
return;
- gh->enabled = enabled;
+ ((GCheckboxObject *)gh)->c = *pColors;
}
-void gwinCheckboxDraw(GHandle gh) {
- #define gcw ((GCheckboxObject *)gh)
+void gwinCheckboxDraw_CheckOnLeft(GWidgetObject *gw, void *param) {
+ #define gcw ((GCheckboxObject *)gw)
+ coord_t ld, df;
+ (void) param;
- if (gh->type != GW_CHECKBOX)
+ if (gw->g.vmt != (gwinVMT *)&checkboxVMT)
return;
- #if GDISP_NEED_CLIP
- //gdispSetClip(gh->x, gh->y, gh->width, gh->height);
- #endif
+ ld = gw->g.width < gw->g.height ? gw->g.width : gw->g.height;
+ gdispFillArea(gw->g.x+1, gw->g.y+1, ld, ld-2, gcw->c.color_bg);
+ gdispDrawBox(gw->g.x, gw->g.y, ld, ld, gcw->c.color_border);
- gcw->fn(gh,
- gcw->gwin.enabled,
- gcw->isChecked,
- gcw->param);
+ df = ld < 4 ? 1 : 2;
+ if (gw->g.flags & GCHECKBOX_FLG_CHECKED)
+ gdispFillArea(gw->g.x+df, gw->g.y+df, ld-2*df, ld-2*df, gcw->c.color_checked);
+ gdispFillStringBox(gw->g.x+ld+1, gw->g.y, gw->g.width-ld-1, gw->g.height, gw->txt, gw->g.font, gcw->c.color_txt, gcw->c.color_bg, justifyLeft);
#undef gcw
}
-#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
- bool_t gwinCheckboxAttachMouse(GHandle gh, uint16_t instance) {
- GSourceHandle gsh;
-
- if (gh->type != GW_CHECKBOX || !(gsh = ginputGetMouse(instance)))
- return FALSE;
-
- return geventAttachSource(&((GCheckboxObject *)gh)->listener, gsh, GLISTEN_MOUSEMETA);
- }
-#endif
-
-void gwinCheckboxSetColors(GHandle gh, color_t border, color_t checked, color_t bg) {
- #define gcw ((GCheckboxObject *)gh)
+void gwinCheckboxDraw_CheckOnRight(GWidgetObject *gw, void *param) {
+ #define gcw ((GCheckboxObject *)gw)
+ coord_t ep, ld, df;
+ (void) param;
- if (gh->type != GW_CHECKBOX)
+ if (gw->g.vmt != (gwinVMT *)&checkboxVMT)
return;
- gcw->colors->border = border;
- gcw->colors->checked = checked,
- gcw->colors->bg = bg;
+ ld = gw->g.width < gw->g.height ? gw->g.width : gw->g.height;
+ ep = gw->g.width-ld-1;
+ gdispFillArea(gw->g.x+ep-1, gw->g.y+1, ld, ld-2, gcw->c.color_bg);
+ gdispDrawBox(gw->g.x+ep, gw->g.y, ld, ld, gcw->c.color_border);
+
+ df = ld < 4 ? 1 : 2;
+ if (gw->g.flags & GCHECKBOX_FLG_CHECKED)
+ gdispFillArea(gw->g.x+ep+df, gw->g.y+df, ld-2*df, ld-2*df, gcw->c.color_checked);
+ gdispFillStringBox(gw->g.x, gw->g.y, ep, gw->g.height, gw->txt, gw->g.font, gcw->c.color_txt, gcw->c.color_bg, justifyRight);
#undef gcw
}
diff --git a/src/gwin/console.c b/src/gwin/console.c
index a4cd428c..38e2ea8b 100644
--- a/src/gwin/console.c
+++ b/src/gwin/console.c
@@ -8,20 +8,15 @@
/**
* @file src/gwin/console.c
* @brief GWIN sub-system console code.
- *
- * @defgroup Console Console
- * @ingroup GWIN
- *
- * @{
*/
#include "gfx.h"
-#if (GFX_USE_GWIN && GWIN_NEED_CONSOLE) || defined(__DOXYGEN__)
+#if GFX_USE_GWIN && GWIN_NEED_CONSOLE
#include <string.h>
-#include "gwin/internal.h"
+#include "gwin/class_gwin.h"
#define GWIN_CONSOLE_USE_CLEAR_LINES TRUE
#define GWIN_CONSOLE_USE_FILLED_CHARS FALSE
@@ -58,11 +53,21 @@
};
#endif
-GHandle gwinCreateConsole(GConsoleObject *gc, coord_t x, coord_t y, coord_t width, coord_t height, font_t font) {
- if (!(gc = (GConsoleObject *)_gwinInit((GWindowObject *)gc, x, y, width, height, sizeof(GConsoleObject))))
+static void AfterClear(GWindowObject *gh) {
+ ((GConsoleObject *)gh)->cx = 0;
+ ((GConsoleObject *)gh)->cy = 0;
+}
+
+static const gwinVMT consoleVMT = {
+ "Console", // The classname
+ 0, // The destroy routine
+ 0, // The redraw routine
+ AfterClear, // The after-clear routine
+};
+
+GHandle gwinCreateConsole(GConsoleObject *gc, coord_t x, coord_t y, coord_t width, coord_t height) {
+ if (!(gc = (GConsoleObject *)_gwindowCreate((GWindowObject *)gc, x, y, width, height, sizeof(GConsoleObject), &consoleVMT, GWIN_FLG_VISIBLE)))
return 0;
- gc->gwin.type = GW_CONSOLE;
- gwinSetFont(&gc->gwin, font);
#if GFX_USE_OS_CHIBIOS && GWIN_CONSOLE_USE_BASESTREAM
gc->stream.vmt = &GWindowConsoleVMT;
#endif
@@ -73,17 +78,21 @@ GHandle gwinCreateConsole(GConsoleObject *gc, coord_t x, coord_t y, coord_t widt
#if GFX_USE_OS_CHIBIOS && GWIN_CONSOLE_USE_BASESTREAM
BaseSequentialStream *gwinGetConsoleStream(GHandle gh) {
- if (gh->type != GW_CONSOLE)
+ if (gh->vmt != &consoleVMT)
return 0;
return (BaseSequentialStream *)&(((GConsoleObject *)(gh))->stream);
}
#endif
void gwinPutChar(GHandle gh, char c) {
- uint8_t width;
#define gcw ((GConsoleObject *)gh)
+ uint8_t width, fy, fp;
+
+ if (gh->vmt != &consoleVMT || !gh->font)
+ return;
- if (gh->type != GW_CONSOLE || !gh->font) return;
+ fy = gdispGetFontMetric(gh->font, fontHeight);
+ fp = gdispGetFontMetric(gh->font, fontCharPadding);
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
@@ -91,24 +100,24 @@ void gwinPutChar(GHandle gh, char c) {
if (c == '\n') {
gcw->cx = 0;
- gcw->cy += gcw->fy;
+ gcw->cy += fy;
// We use lazy scrolling here and only scroll when the next char arrives
} else if (c == '\r') {
// gcw->cx = 0;
} else {
- width = gdispGetCharWidth(c, gh->font) + gcw->fp;
+ width = gdispGetCharWidth(c, gh->font) + fp;
if (gcw->cx + width >= gh->width) {
gcw->cx = 0;
- gcw->cy += gcw->fy;
+ gcw->cy += fy;
}
- if (gcw->cy + gcw->fy > gh->height) {
+ if (gcw->cy + fy > gh->height) {
#if GDISP_NEED_SCROLL
/* scroll the console */
- gdispVerticalScroll(gh->x, gh->y, gh->width, gh->height, gcw->fy, gh->bgcolor);
+ gdispVerticalScroll(gh->x, gh->y, gh->width, gh->height, fy, gh->bgcolor);
/* reset the cursor to the start of the last line */
gcw->cx = 0;
- gcw->cy = (((coord_t)(gh->height/gcw->fy))-1)*gcw->fy;
+ gcw->cy = (((coord_t)(gh->height/fy))-1)*fy;
#else
/* clear the console */
gdispFillArea(gh->x, gh->y, gh->width, gh->height, gh->bgcolor);
@@ -121,7 +130,7 @@ void gwinPutChar(GHandle gh, char c) {
#if GWIN_CONSOLE_USE_CLEAR_LINES
/* clear to the end of the line */
if (gcw->cx == 0)
- gdispFillArea(gh->x, gh->y + gcw->cy, gh->width, gcw->fy, gh->bgcolor);
+ gdispFillArea(gh->x, gh->y + gcw->cy, gh->width, fy, gh->bgcolor);
#endif
#if GWIN_CONSOLE_USE_FILLED_CHARS
gdispFillChar(gh->x + gcw->cx, gh->y + gcw->cy, c, gh->font, gh->color, gh->bgcolor);
@@ -200,7 +209,8 @@ void gwinPrintf(GHandle gh, const char *fmt, ...) {
char tmpbuf[MAX_FILLER + 1];
#endif
- if (gh->type != GW_CONSOLE || !gh->font) return;
+ if (gh->vmt != &consoleVMT || !gh->font)
+ return;
va_start(ap, fmt);
while (TRUE) {
@@ -343,5 +353,5 @@ void gwinPrintf(GHandle gh, const char *fmt, ...) {
}
#endif /* GFX_USE_GWIN && GWIN_NEED_CONSOLE */
-/** @} */
+
diff --git a/src/gwin/graph.c b/src/gwin/graph.c
index 72dcce9d..708b90cb 100644
--- a/src/gwin/graph.c
+++ b/src/gwin/graph.c
@@ -8,18 +8,13 @@
/**
* @file src/gwin/graph.c
* @brief GWIN sub-system button code.
- *
- * @defgroup Graph Graph
- * @ingroup GWIN
- *
- * @{
*/
#include "gfx.h"
-#if (GFX_USE_GWIN && GWIN_NEED_GRAPH) || defined(__DOXYGEN__)
+#if GFX_USE_GWIN && GWIN_NEED_GRAPH
-#include "gwin/internal.h"
+#include "gwin/class_gwin.h"
#define GGRAPH_FLG_CONNECTPOINTS (GWIN_FIRST_CONTROL_FLAG<<0)
#define GGRAPH_ARROW_SIZE 5
@@ -34,13 +29,20 @@ static const GGraphStyle GGraphDefaultStyle = {
GWIN_GRAPH_STYLE_XAXIS_ARROWS|GWIN_GRAPH_STYLE_YAXIS_ARROWS // flags
};
+static const gwinVMT graphVMT = {
+ "Graph", // The classname
+ 0, // The destroy routine
+ 0, // The redraw routine
+ 0, // The after-clear routine
+};
+
static void pointto(GGraphObject *gg, coord_t x, coord_t y, const GGraphPointStyle *style) {
if (style->type == GGRAPH_POINT_NONE)
return;
// Convert to device space. Note the y-axis is inverted.
- x += gg->gwin.x + gg->xorigin;
- y = gg->gwin.y + gg->gwin.height - 1 - gg->yorigin - y;
+ x += gg->g.x + gg->xorigin;
+ y = gg->g.y + gg->g.height - 1 - gg->yorigin - y;
if (style->size <= 1) {
gdispDrawPixel(x, y, style->color);
@@ -73,10 +75,10 @@ static void lineto(GGraphObject *gg, coord_t x0, coord_t y0, coord_t x1, coord_t
return;
// Convert to device space. Note the y-axis is inverted.
- x0 += gg->gwin.x + gg->xorigin;
- y0 = gg->gwin.y + gg->gwin.height - 1 - gg->yorigin - y0;
- x1 += gg->gwin.x + gg->xorigin;
- y1 = gg->gwin.y + gg->gwin.height - 1 - gg->yorigin - y1;
+ x0 += gg->g.x + gg->xorigin;
+ y0 = gg->g.y + gg->g.height - 1 - gg->yorigin - y0;
+ x1 += gg->g.x + gg->xorigin;
+ y1 = gg->g.y + gg->g.height - 1 - gg->yorigin - y1;
if (style->size <= 0) {
// Use the driver to draw a solid line
@@ -163,41 +165,26 @@ static void lineto(GGraphObject *gg, coord_t x0, coord_t y0, coord_t x1, coord_t
}
GHandle gwinCreateGraph(GGraphObject *gg, coord_t x, coord_t y, coord_t width, coord_t height) {
- if (!(gg = (GGraphObject *)_gwinInit((GWindowObject *)gg, x, y, width, height, sizeof(GGraphObject))))
+ if (!(gg = (GGraphObject *)_gwindowCreate((GWindowObject *)gg, x, y, width, height, sizeof(GGraphObject), &graphVMT, GWIN_FLG_VISIBLE)))
return 0;
- gg->gwin.type = GW_GRAPH;
gg->xorigin = gg->yorigin = 0;
gg->lastx = gg->lasty = 0;
- gwinGraphSetStyle(&gg->gwin, &GGraphDefaultStyle);
+ gwinGraphSetStyle((GHandle)gg, &GGraphDefaultStyle);
return (GHandle)gg;
}
void gwinGraphSetStyle(GHandle gh, const GGraphStyle *pstyle) {
#define gg ((GGraphObject *)gh)
- if (gh->type != GW_GRAPH)
+ if (gh->vmt != &graphVMT)
return;
- gg->style.point.type = pstyle->point.type;
- gg->style.point.size = pstyle->point.size;
- gg->style.point.color = pstyle->point.color;
- gg->style.line.type = pstyle->line.type;
- gg->style.line.size = pstyle->line.size;
- gg->style.line.color = pstyle->line.color;
- gg->style.xaxis.type = pstyle->xaxis.type;
- gg->style.xaxis.size = pstyle->xaxis.size;
- gg->style.xaxis.color = pstyle->xaxis.color;
- gg->style.yaxis.type = pstyle->yaxis.type;
- gg->style.yaxis.size = pstyle->yaxis.size;
- gg->style.yaxis.color = pstyle->yaxis.color;
- gg->style.xgrid.type = pstyle->xgrid.type;
- gg->style.xgrid.size = pstyle->xgrid.size;
- gg->style.xgrid.color = pstyle->xgrid.color;
- gg->style.xgrid.spacing = pstyle->xgrid.spacing;
- gg->style.ygrid.type = pstyle->ygrid.type;
- gg->style.ygrid.size = pstyle->ygrid.size;
- gg->style.ygrid.color = pstyle->ygrid.color;
- gg->style.ygrid.spacing = pstyle->ygrid.spacing;
+ gg->style.point = pstyle->point;
+ gg->style.line = pstyle->line;
+ gg->style.xaxis = pstyle->xaxis;
+ gg->style.yaxis = pstyle->yaxis;
+ gg->style.xgrid = pstyle->xgrid;
+ gg->style.ygrid = pstyle->ygrid;
gg->style.flags = pstyle->flags;
#undef gg
@@ -206,7 +193,7 @@ void gwinGraphSetStyle(GHandle gh, const GGraphStyle *pstyle) {
void gwinGraphSetOrigin(GHandle gh, coord_t x, coord_t y) {
#define gg ((GGraphObject *)gh)
- if (gh->type != GW_GRAPH)
+ if (gh->vmt != &graphVMT)
return;
gg->xorigin = x;
@@ -219,7 +206,7 @@ void gwinGraphDrawAxis(GHandle gh) {
#define gg ((GGraphObject *)gh)
coord_t i, xmin, ymin, xmax, ymax;
- if (gh->type != GW_GRAPH)
+ if (gh->vmt != &graphVMT)
return;
xmin = -gg->xorigin;
@@ -277,7 +264,7 @@ void gwinGraphDrawAxis(GHandle gh) {
}
void gwinGraphStartSet(GHandle gh) {
- if (gh->type != GW_GRAPH)
+ if (gh->vmt != &graphVMT)
return;
gh->flags &= ~GGRAPH_FLG_CONNECTPOINTS;
@@ -286,7 +273,7 @@ void gwinGraphStartSet(GHandle gh) {
void gwinGraphDrawPoint(GHandle gh, coord_t x, coord_t y) {
#define gg ((GGraphObject *)gh)
- if (gh->type != GW_GRAPH)
+ if (gh->vmt != &graphVMT)
return;
if ((gh->flags & GGRAPH_FLG_CONNECTPOINTS)) {
@@ -314,7 +301,7 @@ void gwinGraphDrawPoints(GHandle gh, const point *points, unsigned count) {
unsigned i;
const point *p;
- if (gh->type != GW_GRAPH)
+ if (gh->vmt != &graphVMT)
return;
// Draw the connecting lines
@@ -344,5 +331,3 @@ void gwinGraphDrawPoints(GHandle gh, const point *points, unsigned count) {
}
#endif /* GFX_USE_GWIN && GWIN_NEED_GRAPH */
-/** @} */
-
diff --git a/src/gwin/gwidget.c b/src/gwin/gwidget.c
new file mode 100644
index 00000000..9d634c58
--- /dev/null
+++ b/src/gwin/gwidget.c
@@ -0,0 +1,376 @@
+/*
+ * 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://chibios-gfx.com/license.html
+ */
+
+#include "gfx.h"
+
+#if GFX_USE_GWIN && GWIN_NEED_WIDGET
+
+#include <string.h>
+
+#include "gwin/class_gwin.h"
+
+/* Our listener for events for widgets */
+static GListener gl;
+
+/* We use these everywhere in this file */
+#define gw ((GWidgetObject *)gh)
+#define wvmt ((gwidgetVMT *)gh->vmt)
+
+/* Process an event */
+static void gwidgetEvent(void *param, GEvent *pe) {
+ #define gh QItem2GWindow(qi)
+ #define pme ((GEventMouse *)pe)
+ #define pte ((GEventToggle *)pe)
+ #define pde ((GEventDial *)pe)
+
+ const gfxQueueASyncItem * qi;
+ #if GFX_USE_GINPUT && (GINPUT_NEED_TOGGLE || GINPUT_NEED_DIAL)
+ uint16_t role;
+ #endif
+ (void) param;
+
+ // Process various events
+ switch (pe->type) {
+
+ #if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
+ case GEVENT_MOUSE:
+ case GEVENT_TOUCH:
+ // Cycle through all windows
+ for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
+
+ // check if it a widget that is enabled and visible
+ if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE)) != (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE))
+ continue;
+
+ // Are we captured?
+ if ((gw->g.flags & GWIN_FLG_MOUSECAPTURE)) {
+ if ((pme->last_buttons & ~pme->current_buttons & GINPUT_MOUSE_BTN_LEFT)) {
+ gw->g.flags &= ~GWIN_FLG_MOUSECAPTURE;
+ if (wvmt->MouseUp)
+ wvmt->MouseUp(gw, pme->x - gw->g.x, pme->y - gw->g.y);
+ } else if (wvmt->MouseMove)
+ wvmt->MouseMove(gw, pme->x - gw->g.x, pme->y - gw->g.y);
+
+ // We are not captured - look for mouse downs over the widget
+ } else if ((~pme->last_buttons & pme->current_buttons & GINPUT_MOUSE_BTN_LEFT)
+ && pme->x >= gw->g.x && pme->x < gw->g.x + gw->g.width
+ && pme->y >= gw->g.y && pme->y < gw->g.y + gw->g.height) {
+ gw->g.flags |= GWIN_FLG_MOUSECAPTURE;
+ if (wvmt->MouseDown)
+ wvmt->MouseDown(gw, pme->x - gw->g.x, pme->y - gw->g.y);
+ }
+ }
+ break;
+ #endif
+
+ #if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
+ case GEVENT_TOGGLE:
+ // Cycle through all windows
+ for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
+
+ // check if it a widget that is enabled and visible
+ if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE)) != (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE))
+ continue;
+
+ for(role = 0; role < wvmt->toggleroles; role++) {
+ if (wvmt->ToggleGet(gw, role) == pte->instance) {
+ if (pte->on) {
+ if (wvmt->ToggleOn)
+ wvmt->ToggleOn(gw, role);
+ } else {
+ if (wvmt->ToggleOff)
+ wvmt->ToggleOff(gw, role);
+ }
+ }
+ }
+ }
+ break;
+ #endif
+
+ #if GFX_USE_GINPUT && GINPUT_NEED_DIAL
+ case GEVENT_DIAL:
+ // Cycle through all windows
+ for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
+
+ // check if it a widget that is enabled and visible
+ if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE)) != (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE))
+ continue;
+
+ for(role = 0; role < wvmt->dialroles; role++) {
+ if (wvmt->DialGet(gw, role) == pte->instance) {
+ if (wvmt->DialMove)
+ wvmt->DialMove(gw, role, pde->value, pde->maxvalue);
+ }
+ }
+ }
+ break;
+ #endif
+
+ default:
+ break;
+ }
+
+ #undef gh
+ #undef pme
+ #undef pte
+ #undef pde
+}
+
+#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
+ static GHandle FindToggleUser(uint16_t instance) {
+ #define gh QItem2GWindow(qi)
+ const gfxQueueASyncItem * qi;
+ uint16_t role;
+
+ for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
+ if (!(gh->flags & GWIN_FLG_WIDGET)) // check if it a widget
+ continue;
+
+ for(role = 0; role < wvmt->toggleroles; role++) {
+ if (wvmt->ToggleGet(gw, role) == instance)
+ return gh;
+ }
+ }
+ return 0;
+ #undef gh
+ }
+#endif
+
+#if GFX_USE_GINPUT && GINPUT_NEED_DIAL
+ static GHandle FindDialUser(uint16_t instance) {
+ #define gh QItem2GWindow(qi)
+ const gfxQueueASyncItem * qi;
+ uint16_t role;
+
+ for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
+ if (!(gh->flags & GWIN_FLG_WIDGET)) // check if it a widget
+ continue;
+
+ for(role = 0; role < wvmt->dialroles; role++) {
+ if (wvmt->DialGet(gw, role) == instance)
+ return gh;
+ }
+ }
+ return 0;
+ #undef gh
+ }
+#endif
+
+void _gwidgetInit(void) {
+ geventListenerInit(&gl);
+ geventRegisterCallback(&gl, gwidgetEvent, 0);
+}
+
+GHandle _gwidgetCreate(GWidgetObject *pgw, coord_t x, coord_t y, coord_t width, coord_t height, size_t size, const gwidgetVMT *vmt) {
+ if (!(pgw = (GWidgetObject *)_gwindowCreate((GWindowObject *)pgw, x, y, width, height, size, (const gwinVMT *)vmt, GWIN_FLG_WIDGET|GWIN_FLG_ENABLED)))
+ return 0;
+
+ pgw->txt = "";
+ pgw->fnDraw = vmt->DefaultDraw;
+ pgw->fnParam = 0;
+
+ return (GHandle)pgw;
+}
+
+void _gwidgetDestroy(GHandle gh) {
+ #if GFX_USE_GINPUT && (GINPUT_NEED_TOGGLE || GINPUT_NEED_DIAL)
+ uint16_t role, instance;
+ #endif
+
+ // Deallocate the text (if necessary)
+ if ((gh->flags & GWIN_FLG_ALLOCTXT)) {
+ gh->flags &= ~GWIN_FLG_ALLOCTXT;
+ gfxFree((void *)gw->txt);
+ }
+
+ #if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
+ // Detach any toggles from this object
+ for(role = 0; role < wvmt->toggleroles; role++) {
+ instance = wvmt->ToggleGet(gw, role);
+ if (instance != GWIDGET_NO_INSTANCE) {
+ wvmt->ToggleAssign(gw, role, GWIDGET_NO_INSTANCE);
+ if (!FindToggleUser(instance))
+ geventDetachSource(&gl, ginputGetToggle(instance));
+ }
+ }
+ #endif
+
+ #if GFX_USE_GINPUT && GINPUT_NEED_DIAL
+ // Detach any dials from this object
+ for(role = 0; role < wvmt->dialroles; role++) {
+ instance = wvmt->DialGet(gw, role);
+ if (instance != GWIDGET_NO_INSTANCE) {
+ wvmt->DialAssign(gw, role, GWIDGET_NO_INSTANCE);
+ if (!FindDialUser(instance))
+ geventDetachSource(&gl, ginputGetDial(instance));
+ }
+ }
+ #endif
+
+ // Remove any listeners on this object.
+ geventDetachSourceListeners((GSourceHandle)gh);
+}
+
+void _gwidgetRedraw(GHandle gh) {
+ if (!(gh->flags & GWIN_FLG_VISIBLE))
+ return;
+
+ #if GDISP_NEED_CLIP
+ gdispSetClip(gh->x, gh->y, gh->width, gh->height);
+ #endif
+
+ gw->fnDraw(gw, gw->fnParam);
+}
+
+void gwinSetEnabled(GHandle gh, bool_t enabled) {
+ if (!(gh->flags & GWIN_FLG_WIDGET))
+ return;
+
+ if (enabled) {
+ if (!(gh->flags & GWIN_FLG_ENABLED)) {
+ gh->flags |= GWIN_FLG_ENABLED;
+ _gwidgetRedraw(gh);
+ }
+ } else {
+ if ((gh->flags & GWIN_FLG_ENABLED)) {
+ gh->flags &= ~GWIN_FLG_ENABLED;
+ _gwidgetRedraw(gh);
+ }
+ }
+}
+
+void gwinSetText(GHandle gh, const char *txt, bool_t useAlloc) {
+ if (!(gh->flags & GWIN_FLG_WIDGET))
+ return;
+
+ // Dispose of the old string
+ if ((gh->flags & GWIN_FLG_ALLOCTXT)) {
+ gh->flags &= ~GWIN_FLG_ALLOCTXT;
+ if (gw->txt) {
+ gfxFree((void *)gw->txt);
+ gw->txt = "";
+ }
+ }
+
+ // Alloc the new text if required
+ if (txt && !*txt) txt = 0;
+ if (txt && useAlloc) {
+ char *str;
+
+ if ((str = (char *)gfxAlloc(strlen(txt)+1))) {
+ gh->flags |= GWIN_FLG_ALLOCTXT;
+ strcpy(str, txt);
+ }
+ txt = (const char *)str;
+ }
+
+ gw->txt = txt ? txt : "";
+ _gwidgetRedraw(gh);
+}
+
+const char *gwinGetText(GHandle gh) {
+ if (!(gh->flags & GWIN_FLG_WIDGET))
+ return 0;
+
+ return gw->txt;
+}
+
+void gwinSetCustomDraw(GHandle gh, CustomWidgetDrawFunction fn, void *param) {
+ if (!(gh->flags & GWIN_FLG_WIDGET))
+ return;
+
+ gw->fnDraw = fn ? fn : wvmt->DefaultDraw;
+ gw->fnParam = param;
+ _gwidgetRedraw(gh);
+}
+
+bool_t gwinAttachListener(GListener *pl) {
+ return geventAttachSource(pl, GWIDGET_SOURCE, 0);
+}
+
+#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
+ bool_t gwinAttachMouse(uint16_t instance) {
+ GSourceHandle gsh;
+
+ if (!(gsh = ginputGetMouse(instance)))
+ return FALSE;
+
+ return geventAttachSource(&gl, gsh, GLISTEN_MOUSEMETA|GLISTEN_MOUSEDOWNMOVES);
+ }
+#endif
+
+#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
+ bool_t gwinAttachToggle(GHandle gh, uint16_t role, uint16_t instance) {
+ GSourceHandle gsh;
+ uint16_t oi;
+
+ // Is this a widget
+ if (!(gh->flags & GWIN_FLG_WIDGET))
+ return FALSE;
+
+ // Is the role valid
+ if (role >= wvmt->toggleroles)
+ return FALSE;
+
+ // Is this a valid device
+ if (!(gsh = ginputGetToggle(instance)))
+ return FALSE;
+
+ // Is this already done?
+ oi = wvmt->ToggleGet(gw, role);
+ if (instance == oi)
+ return TRUE;
+
+ // Remove the old instance
+ if (oi != GWIDGET_NO_INSTANCE) {
+ wvmt->ToggleAssign(gw, role, GWIDGET_NO_INSTANCE);
+ if (!FindToggleUser(oi))
+ geventDetachSource(&gl, ginputGetToggle(oi));
+ }
+
+ // Assign the new
+ wvmt->ToggleAssign(gw, role, instance);
+ return geventAttachSource(&gl, gsh, GLISTEN_TOGGLE_ON|GLISTEN_TOGGLE_OFF);
+ }
+#endif
+
+#if GFX_USE_GINPUT && GINPUT_NEED_DIAL
+ bool_t gwinAttachDial(GHandle gh, uint16_t role, uint16_t instance) {
+ GSourceHandle gsh;
+ uint16_t oi;
+
+ if (!(gh->flags & GWIN_FLG_WIDGET))
+ return FALSE;
+
+ // Is the role valid
+ if (role >= wvmt->dialroles)
+ return FALSE;
+
+ // Is this a valid device
+ if (!(gsh = ginputGetDial(instance)))
+ return FALSE;
+
+ // Is this already done?
+ oi = wvmt->DialGet(gw, role);
+ if (instance == oi)
+ return TRUE;
+
+ // Remove the old instance
+ if (oi != GWIDGET_NO_INSTANCE) {
+ wvmt->DialAssign(gw, role, GWIDGET_NO_INSTANCE);
+ if (!FindDialUser(oi))
+ geventDetachSource(&gl, ginputGetDial(oi));
+ }
+
+ // Assign the new
+ wvmt->DialAssign(gw, role, instance);
+ return geventAttachSource(&gl, gsh, 0);
+ }
+#endif
+
+#endif /* GFX_USE_GWIN && GWIN_NEED_WIDGET */
+/** @} */
diff --git a/src/gwin/gwin.c b/src/gwin/gwin.c
index 2f9d2dfd..b918d297 100644
--- a/src/gwin/gwin.c
+++ b/src/gwin/gwin.c
@@ -9,127 +9,266 @@
#if GFX_USE_GWIN
-#include "gwin/internal.h"
+#include "gwin/class_gwin.h"
+
+// Needed if there is no window manager
+#define MIN_WIN_WIDTH 1
+#define MIN_WIN_HEIGHT 1
+
+/*-----------------------------------------------
+ * Data
+ *-----------------------------------------------*/
+
+static const gwinVMT basegwinVMT = {
+ "GWIN", // The classname
+ 0, // The destroy routine
+ 0, // The redraw routine
+ 0, // The after-clear routine
+};
+
+static color_t defaultFgColor = White;
+static color_t defaultBgColor = Black;
+#if GDISP_NEED_TEXT
+ static font_t defaultFont;
+#endif
+#if GWIN_NEED_WINDOWMANAGER
+ gfxQueueASync _GWINList;
+ extern GWindowManager GNullWindowManager;
+ static GWindowManager * cwm;
+#endif
+
+/*-----------------------------------------------
+ * Helper Routines
+ *-----------------------------------------------*/
+
+#if !GWIN_NEED_WINDOWMANAGER
+ static void _gwm_vis(GHandle gh) {
+ if (gh->vmt->Redraw) {
+ #if GDISP_NEED_CLIP
+ gdispSetClip(gh->x, gh->y, gh->width, gh->height);
+ #endif
+ gh->vmt->Redraw(gh);
+ } else
+ gwinClear(gh);
+ }
+ static void _gwm_redim(GHandle gh, coord_t x, coord_t y, coord_t w, coord_t h) {
+ if (x < 0) { w += x; x = 0; }
+ if (y < 0) { h += y; y = 0; }
+ if (x > gdispGetWidth()-MIN_WIN_WIDTH) x = gdispGetWidth()-MIN_WIN_WIDTH;
+ if (y > gdispGetHeight()-MIN_WIN_HEIGHT) y = gdispGetHeight()-MIN_WIN_HEIGHT;
+ if (w < MIN_WIN_WIDTH) { w = MIN_WIN_WIDTH; }
+ if (h < MIN_WIN_HEIGHT) { h = MIN_WIN_HEIGHT; }
+ if (x+w > gdispGetWidth()) w = gdispGetWidth() - x;
+ if (y+h > gdispGetHeight()) h = gdispGetHeight() - y;
+ gh->x = x; gh->y = y;
+ gh->width = w; gh->height = h;
+ }
+#endif
+
+/*-----------------------------------------------
+ * Class Routines
+ *-----------------------------------------------*/
+
+void _gwinInit(void) {
+ #if GWIN_NEED_WIDGET
+ extern void _gwidgetInit(void);
+
+ _gwidgetInit();
+ #endif
+ #if GWIN_NEED_WINDOWMANAGER
+ gfxQueueASyncInit(&_GWINList);
+ cwm = &GNullWindowManager;
+ cwm->vmt->Init();
+ #endif
+}
// Internal routine for use by GWIN components only
-// Initialise a window creating it dynamicly if required.
-GHandle _gwinInit(GWindowObject *gw, coord_t x, coord_t y, coord_t width, coord_t height, size_t size) {
- coord_t w, h;
-
- // Check the window size against the screen size
- w = gdispGetWidth();
- h = gdispGetHeight();
- if (x < 0) { width += x; x = 0; }
- if (y < 0) { height += y; y = 0; }
- if (x >= w || y >= h) return 0;
- if (x+width > w) width = w - x;
- if (y+height > h) height = h - y;
-
+// Initialise a window creating it dynamically if required.
+GHandle _gwindowCreate(GWindowObject *pgw, coord_t x, coord_t y, coord_t width, coord_t height, size_t size, const gwinVMT *vmt, uint16_t flags) {
// Allocate the structure if necessary
- if (!gw) {
- if (!(gw = (GWindowObject *)gfxAlloc(size)))
+ if (!pgw) {
+ if (!(pgw = (GWindowObject *)gfxAlloc(size)))
return 0;
- gw->flags = GWIN_FLG_DYNAMIC;
+ pgw->flags = flags|GWIN_FLG_DYNAMIC;
} else
- gw->flags = 0;
+ pgw->flags = flags;
- // Initialise all basic fields (except the type)
- gw->x = x;
- gw->y = y;
- gw->width = width;
- gw->height = height;
- gw->color = White;
- gw->bgcolor = Black;
+ // Initialise all basic fields
+ pgw->vmt = vmt;
+ pgw->color = defaultFgColor;
+ pgw->bgcolor = defaultBgColor;
#if GDISP_NEED_TEXT
- gw->font = 0;
+ pgw->font = defaultFont;
#endif
- return (GHandle)gw;
-}
-GHandle gwinCreateWindow(GWindowObject *gw, coord_t x, coord_t y, coord_t width, coord_t height) {
- if (!(gw = (GWindowObject *)_gwinInit((GWindowObject *)gw, x, y, width, height, sizeof(GWindowObject))))
- return 0;
- gw->type = GW_WINDOW;
- return (GHandle)gw;
-}
+ #if GWIN_NEED_WINDOWMANAGER
+ if (!cwm->vmt->Add(pgw, x, y, width, height)) {
+ if ((pgw->flags & GWIN_FLG_DYNAMIC))
+ gfxFree(pgw);
+ return 0;
+ }
+ #else
+ _gwm_redim(pgw, x, y, width, height);
+ if ((pgw->flags & GWIN_FLG_VISIBLE))
+ _gwm_vis(pgw);
+ #endif
-void gwinSetEnabled(GHandle gh, bool_t enabled) {
- (void)gh;
- (void)enabled;
+ return (GHandle)pgw;
}
-void gwinDestroyWindow(GHandle gh) {
- // Clean up any type specific dynamic memory allocations
- switch(gh->type) {
-#if GWIN_NEED_BUTTON
- case GW_BUTTON:
- if ((gh->flags & GBTN_FLG_ALLOCTXT)) {
- gh->flags &= ~GBTN_FLG_ALLOCTXT; // To be sure, to be sure
- gfxFree((void *)((GButtonObject *)gh)->txt);
+/*-----------------------------------------------
+ * Routines that affect all windows
+ *-----------------------------------------------*/
+
+#if GWIN_NEED_WINDOWMANAGER
+ void gwinSetWindowManager(struct GWindowManager *gwm) {
+ if (!gwm)
+ gwm = &GNullWindowManager;
+ if (cwm != gwm) {
+ cwm->vmt->DeInit();
+ cwm = gwm;
+ cwm->vmt->Init();
}
- geventDetachSource(&((GButtonObject *)gh)->listener, 0);
- geventDetachSourceListeners((GSourceHandle)gh);
- break;
-#endif
-#if GWIN_NEED_SLIDER
- case GW_SLIDER:
- geventDetachSource(&((GSliderObject *)gh)->listener, 0);
- geventDetachSourceListeners((GSourceHandle)gh);
- break;
+ }
#endif
- default:
- break;
+
+void gwinSetDefaultColor(color_t clr) {
+ defaultFgColor = clr;
+}
+
+void gwinSetDefaultBgColor(color_t bgclr) {
+ defaultBgColor = bgclr;
+}
+
+#if GDISP_NEED_TEXT
+ void gwinSetDefaultFont(font_t font) {
+ defaultFont = font;
}
+#endif
+
+/*-----------------------------------------------
+ * The GWindow Routines
+ *-----------------------------------------------*/
+
+GHandle gwinCreateWindow(GWindowObject *pgw, coord_t x, coord_t y, coord_t width, coord_t height) {
+ return _gwindowCreate(pgw, x, y, width, height, sizeof(GWindowObject), &basegwinVMT, GWIN_FLG_VISIBLE);
+}
+
+void gwinDestroy(GHandle gh) {
+ // Remove from the window manager
+ #if GWIN_NEED_WINDOWMANAGER
+ cwm->vmt->Delete(gh);
+ #endif
+
+ // Class destroy routine
+ if (gh->vmt->Destroy)
+ gh->vmt->Destroy(gh);
// Clean up the structure
- if (gh->flags & GWIN_FLG_DYNAMIC) {
- gh->flags = 0; // To be sure, to be sure
+ if (gh->flags & GWIN_FLG_DYNAMIC)
gfxFree((void *)gh);
+
+ gh->flags = 0; // To be sure, to be sure
+}
+
+const char *gwinGetClassName(GHandle gh) {
+ return gh->vmt->classname;
+}
+
+void gwinSetVisible(GHandle gh, bool_t visible) {
+ if (visible) {
+ if (!(gh->flags & GWIN_FLG_VISIBLE)) {
+ gh->flags |= GWIN_FLG_VISIBLE;
+ #if GWIN_NEED_WINDOWMANAGER
+ cwm->vmt->Visible(gh);
+ #else
+ _gwm_vis(gh);
+ #endif
+ }
+ } else {
+ if ((gh->flags & GWIN_FLG_VISIBLE)) {
+ gh->flags &= ~GWIN_FLG_VISIBLE;
+ #if GWIN_NEED_WINDOWMANAGER
+ cwm->vmt->Visible(gh);
+ #endif
+ }
}
}
-void gwinDraw(GHandle gh) {
- switch(gh->type) {
- #if GWIN_NEED_BUTTON
- case GW_BUTTON:
- gwinButtonDraw(gh);
- break;
+bool_t gwinGetVisible(GHandle gh) {
+ return (gh->flags & GWIN_FLG_VISIBLE) ? TRUE : FALSE;
+}
+
+void gwinMove(GHandle gh, coord_t x, coord_t y) {
+ #if GWIN_NEED_WINDOWMANAGER
+ cwm->vmt->Redim(gh, x, y, gh->width, gh->height);
+ #else
+ _gwm_redim(gh, x, y, gh->width, gh->height);
#endif
- #if GWIN_NEED_SLIDER
- case GW_SLIDER:
- gwinSliderDraw(gh);
- break;
+}
+
+void gwinResize(GHandle gh, coord_t width, coord_t height) {
+ #if GWIN_NEED_WINDOWMANAGER
+ cwm->vmt->Redim(gh, gh->x, gh->y, width, height);
+ #else
+ _gwm_redim(gh, gh->x, gh->y, width, height);
+ #endif
+}
+
+void gwinSetMinMax(GHandle gh, GWindowMinMax minmax) {
+ #if GWIN_NEED_WINDOWMANAGER
+ cwm->vmt->MinMax(gh, minmax);
+ #else
+ (void) gh;
+ (void) minmax;
+ #endif
+}
+
+void gwinRaise(GHandle gh) {
+ #if GWIN_NEED_WINDOWMANAGER
+ cwm->vmt->Raise(gh);
+ #else
+ if ((gh->flags & GWIN_FLG_VISIBLE)) {
+ if (gh->vmt->Redraw) {
+ #if GDISP_NEED_CLIP
+ gdispSetClip(gh->x, gh->y, gh->width, gh->height);
+ #endif
+ gh->vmt->Redraw(gh);
+ }
+ }
#endif
- }
+}
+
+GWindowMinMax gwinGetMinMax(GHandle gh) {
+ if (gh->flags & GWIN_FLG_MINIMIZED)
+ return GWIN_MINIMIZE;
+ if (gh->flags & GWIN_FLG_MAXIMIZED)
+ return GWIN_MAXIMIZE;
+ return GWIN_NORMAL;
}
#if GDISP_NEED_TEXT
void gwinSetFont(GHandle gh, font_t font) {
gh->font = font;
- #if GWIN_NEED_CONSOLE
- if (font && gh->type == GW_CONSOLE) {
- ((GConsoleObject *)gh)->fy = gdispGetFontMetric(font, fontHeight);
- ((GConsoleObject *)gh)->fp = gdispGetFontMetric(font, fontCharPadding);
- }
- #endif
}
#endif
void gwinClear(GHandle gh) {
+ if (!((gh->flags & GWIN_FLG_VISIBLE)))
+ return;
+
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
gdispFillArea(gh->x, gh->y, gh->width, gh->height, gh->bgcolor);
-
- #if GWIN_NEED_CONSOLE
- if (gh->type == GW_CONSOLE) {
- ((GConsoleObject *)gh)->cx = 0;
- ((GConsoleObject *)gh)->cy = 0;
- }
- #endif
+ if (gh->vmt->AfterClear)
+ gh->vmt->AfterClear(gh);
}
void gwinDrawPixel(GHandle gh, coord_t x, coord_t y) {
+ if (!((gh->flags & GWIN_FLG_VISIBLE)))
+ return;
+
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@@ -137,6 +276,9 @@ void gwinDrawPixel(GHandle gh, coord_t x, coord_t y) {
}
void gwinDrawLine(GHandle gh, coord_t x0, coord_t y0, coord_t x1, coord_t y1) {
+ if (!((gh->flags & GWIN_FLG_VISIBLE)))
+ return;
+
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@@ -144,6 +286,9 @@ void gwinDrawLine(GHandle gh, coord_t x0, coord_t y0, coord_t x1, coord_t y1) {
}
void gwinDrawBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy) {
+ if (!((gh->flags & GWIN_FLG_VISIBLE)))
+ return;
+
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@@ -151,6 +296,9 @@ void gwinDrawBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy) {
}
void gwinFillArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy) {
+ if (!((gh->flags & GWIN_FLG_VISIBLE)))
+ return;
+
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@@ -158,6 +306,9 @@ void gwinFillArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy) {
}
void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) {
+ if (!((gh->flags & GWIN_FLG_VISIBLE)))
+ return;
+
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@@ -166,6 +317,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor
#if GDISP_NEED_CIRCLE
void gwinDrawCircle(GHandle gh, coord_t x, coord_t y, coord_t radius) {
+ if (!((gh->flags & GWIN_FLG_VISIBLE)))
+ return;
+
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@@ -173,6 +327,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor
}
void gwinFillCircle(GHandle gh, coord_t x, coord_t y, coord_t radius) {
+ if (!((gh->flags & GWIN_FLG_VISIBLE)))
+ return;
+
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@@ -182,6 +339,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor
#if GDISP_NEED_ELLIPSE
void gwinDrawEllipse(GHandle gh, coord_t x, coord_t y, coord_t a, coord_t b) {
+ if (!((gh->flags & GWIN_FLG_VISIBLE)))
+ return;
+
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@@ -189,6 +349,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor
}
void gwinFillEllipse(GHandle gh, coord_t x, coord_t y, coord_t a, coord_t b) {
+ if (!((gh->flags & GWIN_FLG_VISIBLE)))
+ return;
+
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@@ -198,6 +361,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor
#if GDISP_NEED_ARC
void gwinDrawArc(GHandle gh, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle) {
+ if (!((gh->flags & GWIN_FLG_VISIBLE)))
+ return;
+
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@@ -205,6 +371,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor
}
void gwinFillArc(GHandle gh, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle) {
+ if (!((gh->flags & GWIN_FLG_VISIBLE)))
+ return;
+
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@@ -214,6 +383,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor
#if GDISP_NEED_PIXELREAD
color_t gwinGetPixelColor(GHandle gh, coord_t x, coord_t y) {
+ if (!((gh->flags & GWIN_FLG_VISIBLE)))
+ return;
+
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@@ -223,7 +395,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor
#if GDISP_NEED_TEXT
void gwinDrawChar(GHandle gh, coord_t x, coord_t y, char c) {
- if (!gh->font) return;
+ if (!((gh->flags & GWIN_FLG_VISIBLE)) || !gh->font)
+ return;
+
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@@ -231,7 +405,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor
}
void gwinFillChar(GHandle gh, coord_t x, coord_t y, char c) {
- if (!gh->font) return;
+ if (!((gh->flags & GWIN_FLG_VISIBLE)) || !gh->font)
+ return;
+
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@@ -239,7 +415,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor
}
void gwinDrawString(GHandle gh, coord_t x, coord_t y, const char *str) {
- if (!gh->font) return;
+ if (!((gh->flags & GWIN_FLG_VISIBLE)) || !gh->font)
+ return;
+
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@@ -247,7 +425,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor
}
void gwinFillString(GHandle gh, coord_t x, coord_t y, const char *str) {
- if (!gh->font) return;
+ if (!((gh->flags & GWIN_FLG_VISIBLE)) || !gh->font)
+ return;
+
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@@ -255,7 +435,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor
}
void gwinDrawStringBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, justify_t justify) {
- if (!gh->font) return;
+ if (!((gh->flags & GWIN_FLG_VISIBLE)) || !gh->font)
+ return;
+
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@@ -263,7 +445,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor
}
void gwinFillStringBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, justify_t justify) {
- if (!gh->font) return;
+ if (!((gh->flags & GWIN_FLG_VISIBLE)) || !gh->font)
+ return;
+
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@@ -273,6 +457,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor
#if GDISP_NEED_CONVEX_POLYGON
void gwinDrawPoly(GHandle gh, coord_t tx, coord_t ty, const point *pntarray, unsigned cnt) {
+ if (!((gh->flags & GWIN_FLG_VISIBLE)))
+ return;
+
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@@ -280,6 +467,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor
}
void gwinFillConvexPoly(GHandle gh, coord_t tx, coord_t ty, const point *pntarray, unsigned cnt) {
+ if (!((gh->flags & GWIN_FLG_VISIBLE)))
+ return;
+
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@@ -289,6 +479,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor
#if GDISP_NEED_IMAGE
gdispImageError gwinImageDraw(GHandle gh, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy) {
+ if (!((gh->flags & GWIN_FLG_VISIBLE)))
+ return GDISP_IMAGE_ERR_OK;
+
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
diff --git a/src/gwin/gwin.mk b/src/gwin/gwin.mk
index be6301c6..fb8fdfd1 100644
--- a/src/gwin/gwin.mk
+++ b/src/gwin/gwin.mk
@@ -1,7 +1,9 @@
GFXSRC += $(GFXLIB)/src/gwin/gwin.c \
+ $(GFXLIB)/src/gwin/gwidget.c \
+ $(GFXLIB)/src/gwin/gwm.c \
$(GFXLIB)/src/gwin/console.c \
+ $(GFXLIB)/src/gwin/graph.c \
$(GFXLIB)/src/gwin/button.c \
$(GFXLIB)/src/gwin/slider.c \
- $(GFXLIB)/src/gwin/graph.c \
$(GFXLIB)/src/gwin/checkbox.c \
diff --git a/src/gwin/gwm.c b/src/gwin/gwm.c
new file mode 100644
index 00000000..5a533c40
--- /dev/null
+++ b/src/gwin/gwm.c
@@ -0,0 +1,144 @@
+/*
+ * 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://chibios-gfx.com/license.html
+ */
+
+#include "gfx.h"
+
+// Used by the NULL window manager
+#define MIN_WIN_WIDTH 3
+#define MIN_WIN_HEIGHT 3
+
+/*-----------------------------------------------
+ * The default window manager (GNullWindowManager)
+ *-----------------------------------------------*/
+
+#if GFX_USE_GWIN && GWIN_NEED_WINDOWMANAGER
+
+#include "gwin/class_gwin.h"
+
+/*-----------------------------------------------
+ * Data
+ *-----------------------------------------------*/
+
+static void WM_Init(void);
+static void WM_DeInit(void);
+static bool_t WM_Add(GHandle gh, coord_t x, coord_t y, coord_t w, coord_t h);
+static void WM_Delete(GHandle gh);
+static void WM_Visible(GHandle gh);
+static void WM_Redim(GHandle gh, coord_t x, coord_t y, coord_t w, coord_t h);
+static void WM_Raise(GHandle gh);
+static void WM_MinMax(GHandle gh, GWindowMinMax minmax);
+
+static const gwmVMT GNullWindowManagerVMT = {
+ WM_Init,
+ WM_DeInit,
+ WM_Add,
+ WM_Delete,
+ WM_Visible,
+ WM_Redim,
+ WM_Raise,
+ WM_MinMax,
+};
+
+const GWindowManager GNullWindowManager = {
+ &GNullWindowManagerVMT,
+};
+
+/*-----------------------------------------------
+ * Window Manager Routines
+ *-----------------------------------------------*/
+
+static void WM_Init(void) {
+ // We don't need to do anything here.
+ // A full window manager would move the windows around, add borders etc
+
+ // clear the screen
+ // cycle through the windows already defined displaying them
+ // or cut all the window areas out of the screen and clear the remainder
+}
+
+static void WM_DeInit(void) {
+ // We don't need to do anything here.
+ // A full window manager would remove any borders etc
+}
+
+static bool_t WM_Add(GHandle gh, coord_t x, coord_t y, coord_t w, coord_t h) {
+ // Put it on the queue
+ gfxQueueASyncPut(&_GWINList, &gh->wmq);
+
+ // Make sure the size is valid
+ WM_Redim(gh, x, y, w, h);
+
+ // Display it if it is visible
+ WM_Visible(gh);
+ return TRUE;
+}
+
+static void WM_Delete(GHandle gh) {
+ // A real window manager would make the window invisible
+ // (and then clear the area underneath)
+
+ // Just remove it from the queue
+ gfxQueueASyncRemove(&_GWINList, &gh->wmq);
+}
+
+static void WM_Visible(GHandle gh) {
+ if ((gh->flags & GWIN_FLG_VISIBLE)) {
+ if (gh->vmt->Redraw) {
+ #if GDISP_NEED_CLIP
+ gdispSetClip(gh->x, gh->y, gh->width, gh->height);
+ #endif
+ gh->vmt->Redraw(gh);
+ } else
+ gwinClear(gh);
+ // A real window manager would also redraw the borders
+ }
+
+ // else
+ // A real window manager would make the window invisible
+ // (and then clear the area underneath)
+
+}
+
+static void WM_Redim(GHandle gh, coord_t x, coord_t y, coord_t w, coord_t h) {
+ // This is the simplest way of doing it - just clip the the screen
+ // If it won't fit on the screen move it around until it does.
+ if (x < 0) { w += x; x = 0; }
+ if (y < 0) { h += y; y = 0; }
+ if (x > gdispGetWidth()-MIN_WIN_WIDTH) x = gdispGetWidth()-MIN_WIN_WIDTH;
+ if (y > gdispGetHeight()-MIN_WIN_HEIGHT) y = gdispGetHeight()-MIN_WIN_HEIGHT;
+ if (w < MIN_WIN_WIDTH) { w = MIN_WIN_WIDTH; }
+ if (h < MIN_WIN_HEIGHT) { h = MIN_WIN_HEIGHT; }
+ if (x+w > gdispGetWidth()) w = gdispGetWidth() - x;
+ if (y+h > gdispGetHeight()) h = gdispGetHeight() - y;
+ gh->x = x; gh->y = y;
+ gh->width = w; gh->height = h;
+}
+
+static void WM_MinMax(GHandle gh, GWindowMinMax minmax) {
+ (void)gh; (void) minmax;
+ // We don't support minimising, maximising or restoring
+}
+
+static void WM_Raise(GHandle gh) {
+ // Take it off the list and then put it back on top
+ // The order of the list then reflects the z-order.
+ gfxQueueASyncRemove(&_GWINList, &gh->wmq);
+ gfxQueueASyncPut(&_GWINList, &gh->wmq);
+
+ // Redraw the window
+ if ((gh->flags & GWIN_FLG_VISIBLE)) {
+ if (gh->vmt->Redraw) {
+ #if GDISP_NEED_CLIP
+ gdispSetClip(gh->x, gh->y, gh->width, gh->height);
+ #endif
+ gh->vmt->Redraw(gh);
+ }
+ }
+}
+
+#endif /* GFX_USE_GWIN && GWIN_NEED_WINDOWMANAGER */
+/** @} */
diff --git a/src/gwin/slider.c b/src/gwin/slider.c
index 01df189d..f2052524 100644
--- a/src/gwin/slider.c
+++ b/src/gwin/slider.c
@@ -19,140 +19,237 @@
#if (GFX_USE_GWIN && GWIN_NEED_SLIDER) || defined(__DOXYGEN__)
-#include "gwin/internal.h"
+#include "gwin/class_gwin.h"
#ifndef GWIN_SLIDER_DEAD_BAND
#define GWIN_SLIDER_DEAD_BAND 5
#endif
-#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
- static void trackSliderDraw(GHandle gh, coord_t x, coord_t y);
+#ifndef GWIN_SLIDER_TOGGLE_INC
+ #define GWIN_SLIDER_TOGGLE_INC 20 // How many toggles to go from minimum to maximum
#endif
-static const GSliderDrawStyle GSliderDefaultStyle = {
- HTML2COLOR(0x404040), // color_edge;
- HTML2COLOR(0x000000), // color_thumb;
- HTML2COLOR(0x00E000), // color_active;
- HTML2COLOR(0xE0E0E0), // color_inactive;
+// Prototypes for slider VMT functions
+static void MouseUp(GWidgetObject *gw, coord_t x, coord_t y);
+static void MouseMove(GWidgetObject *gw, coord_t x, coord_t y);
+static void ToggleOn(GWidgetObject *gw, uint16_t role);
+static void DialMove(GWidgetObject *gw, uint16_t role, uint16_t value, uint16_t max);
+static void ToggleAssign(GWidgetObject *gw, uint16_t role, uint16_t instance);
+static void DialAssign(GWidgetObject *gw, uint16_t role, uint16_t instance);
+static uint16_t ToggleGet(GWidgetObject *gw, uint16_t role);
+static uint16_t DialGet(GWidgetObject *gw, uint16_t role);
+
+// The button VMT table
+static const gwidgetVMT sliderVMT = {
+ {
+ "Slider", // The classname
+ _gwidgetDestroy, // The destroy routine
+ _gwidgetRedraw, // The redraw routine
+ 0, // The after-clear routine
+ },
+ gwinSliderDraw_Std, // The default drawing routine
+ {
+ 0, // Process mouse down events (NOT USED)
+ MouseUp, // Process mouse up events
+ MouseMove, // Process mouse move events
+ },
+ {
+ 2, // 1 toggle role
+ ToggleAssign, // Assign Toggles
+ ToggleGet, // Get Toggles
+ 0, // Process toggle off events (NOT USED)
+ ToggleOn, // Process toggle on events
+ },
+ {
+ 1, // 1 dial roles
+ DialAssign, // Assign Dials
+ DialGet, // Get Dials
+ DialMove, // Process dial move events
+ }
};
-// Process an event callback
-static void gwinSliderCallback(void *param, GEvent *pe) {
- GSourceListener *psl;
- #define gh ((GHandle)param)
- #define gsw ((GSliderObject *)param)
- #define gsh ((GSourceHandle)param)
- #define pme ((GEventMouse *)pe)
- #define pde ((GEventDial *)pe)
- #define pse ((GEventGWinSlider *)pe)
-
- switch (pe->type) {
- #if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
- case GEVENT_MOUSE:
- case GEVENT_TOUCH:
- // If not tracking we only only interested in a mouse down over the slider
- if (!gsw->tracking) {
- if ((pme->meta & GMETA_MOUSE_DOWN)
- && pme->x >= gh->x && pme->x < gh->x + gh->width
- && pme->y >= gh->y && pme->y < gh->y + gh->height) {
- gsw->tracking = TRUE;
- trackSliderDraw(gh, pme->x-gh->x, pme->y-gh->y);
- }
- return;
- }
+static const GSliderColors GSliderDefaultColors = {
+ HTML2COLOR(0x404040), // color_edge
+ HTML2COLOR(0x000000), // color_thumb
+ HTML2COLOR(0x00E000), // color_active
+ HTML2COLOR(0xE0E0E0), // color_inactive
+ HTML2COLOR(0xFFFFFF), // color_txt
+};
- // We are tracking the mouse
-
- // Test for button up
- if ((pme->meta & GMETA_MOUSE_UP)) {
- gsw->tracking = FALSE;
-
- #if !GWIN_BUTTON_LAZY_RELEASE
- // Are we over the slider?
- if (pme->x < gh->x || pme->x >= gh->x + gh->width
- || pme->y < gh->y || pme->y >= gh->y + gh->height) {
- // No - restore the slider
- gwinSliderDraw(gh);
- return;
- }
- #endif
-
- // Set the new position
- if (gh->width < gh->height)
- gwinSetSliderPosition(gh,
- (uint16_t)((uint32_t)(gh->height-1-pme->y+gh->y-GWIN_SLIDER_DEAD_BAND)*(gsw->max-gsw->min)/(gh->height-2*GWIN_SLIDER_DEAD_BAND) + gsw->min));
- else
- gwinSetSliderPosition(gh,
- (uint16_t)((uint32_t)(pme->x-gh->x-GWIN_SLIDER_DEAD_BAND)*(gsw->max-gsw->min)/(gh->width-2*GWIN_SLIDER_DEAD_BAND) + gsw->min));
-
- // Update the display
- gwinSliderDraw(gh);
-
- // Generate the event
- break;
- }
+// Send the slider event
+static void SendSliderEvent(GWidgetObject *gw) {
+ GSourceListener * psl;
+ GEvent * pe;
+ #define pse ((GEventGWinSlider *)pe)
+
+ // Trigger a GWIN Button Event
+ psl = 0;
+ while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) {
+ if (!(pe = geventGetEventBuffer(psl)))
+ continue;
+ pse->type = GEVENT_GWIN_SLIDER;
+ pse->slider = (GHandle)gw;
+ pse->position = ((GSliderObject *)gw)->pos;
+ geventSendEvent(psl);
+ }
+
+ #undef pse
+}
- // If mouse down - track movement
- if ((pme->current_buttons & GINPUT_MOUSE_BTN_LEFT))
- trackSliderDraw(gh, pme->x-gh->x, pme->y-gh->y);
+// Reset the display position back to the value predicted by the saved slider position
+static void ResetDisplayPos(GSliderObject *gsw) {
+ if (gsw->w.g.width < gsw->w.g.height)
+ gsw->dpos = gsw->w.g.height-1-((gsw->w.g.height-1)*(gsw->pos-gsw->min))/(gsw->max-gsw->min);
+ else
+ gsw->dpos = ((gsw->w.g.width-1)*(gsw->pos-gsw->min))/(gsw->max-gsw->min);
+}
+// A mouse up event
+static void MouseUp(GWidgetObject *gw, coord_t x, coord_t y) {
+ #define gsw ((GSliderObject *)gw)
+ #define gh ((GHandle)gw)
+
+ #if GWIN_BUTTON_LAZY_RELEASE
+ // Clip to the slider
+ if (x < 0) x = 0;
+ else if (x >= gh->width) x = gh->width-1;
+ if (y < 0) y = 0;
+ else if (y >= gh->height) x = gh->height-1;
+ #else
+ // Are we over the slider?
+ if (x < 0 || x >= gh->width || y < 0 || y >= gh->height) {
+ // No - restore the slider
+ ResetDisplayPos(gsw);
+ _gwidgetRedraw(gh);
return;
+ }
#endif
- #if GFX_USE_GINPUT && GINPUT_NEED_DIAL
- case GEVENT_DIAL:
- // Set the new position
- gwinSetSliderPosition(gh, (uint16_t)((uint32_t)pde->value*(gsw->max-gsw->min)/ginputGetDialRange(pde->instance) + gsw->min));
- // Update the display
- gwinSliderDraw(gh);
+ // Set the new position
+ if (gh->width < gh->height) {
+ if (y > gh->height-GWIN_SLIDER_DEAD_BAND)
+ gsw->pos = gsw->min;
+ else if (y < GWIN_SLIDER_DEAD_BAND)
+ gsw->pos = gsw->max;
+ else
+ gsw->pos = (uint16_t)((int32_t)(gh->height-1-y-GWIN_SLIDER_DEAD_BAND)*(gsw->max-gsw->min)/(gh->height-2*GWIN_SLIDER_DEAD_BAND) + gsw->min);
+ } else {
+ if (x > gh->width-GWIN_SLIDER_DEAD_BAND)
+ gsw->pos = gsw->max;
+ else if (x < GWIN_SLIDER_DEAD_BAND)
+ gsw->pos = gsw->min;
+ else
+ gsw->pos = (uint16_t)((int32_t)(x-GWIN_SLIDER_DEAD_BAND)*(gsw->max-gsw->min)/(gh->width-2*GWIN_SLIDER_DEAD_BAND) + gsw->min);
+ }
- // Generate the event
- break;
- #endif
+ ResetDisplayPos(gsw);
+ _gwidgetRedraw(gh);
- default:
- return;
+ // Generate the event
+ SendSliderEvent(gw);
+ #undef gh
+ #undef gsw
+}
+
+// A mouse move (or mouse down) event
+static void MouseMove(GWidgetObject *gw, coord_t x, coord_t y) {
+ #define gsw ((GSliderObject *)gw)
+
+ // Determine the temporary display position (with range checking)
+ if (gw->g.width < gw->g.height) {
+ if (y < 0)
+ gsw->dpos = 0;
+ else if (y >= gw->g.height)
+ gsw->dpos = gw->g.height-1;
+ else
+ gsw->dpos = y;
+ } else {
+ if (x < 0)
+ gsw->dpos = 0;
+ else if (x >= gw->g.width)
+ gsw->dpos = gw->g.width-1;
+ else
+ gsw->dpos = x;
}
- // Trigger a GWIN Slider Event
- psl = 0;
- while ((psl = geventGetSourceListener(gsh, psl))) {
- if (!(pe = geventGetEventBuffer(psl)))
- continue;
- pse->type = GEVENT_GWIN_SLIDER;
- pse->slider = gh;
- pse->position = gsw->pos;
- geventSendEvent(psl);
+ // Update the display
+ _gwidgetRedraw(&gw->g);
+ #undef gsw
+}
+
+// A toggle on has occurred
+static void ToggleOn(GWidgetObject *gw, uint16_t role) {
+ #define gsw ((GSliderObject *)gw)
+
+ if (role) {
+ gwinSetSliderPosition((GHandle)gw, gsw->pos+(gsw->max-gsw->min)/GWIN_SLIDER_TOGGLE_INC);
+ SendSliderEvent(gw);
+ } else {
+ gwinSetSliderPosition((GHandle)gw, gsw->pos-(gsw->max-gsw->min)/GWIN_SLIDER_TOGGLE_INC);
+ SendSliderEvent(gw);
}
+ #undef gsw
+}
- #undef pse
- #undef pme
- #undef pxe
- #undef gsh
+// A dial move event
+static void DialMove(GWidgetObject *gw, uint16_t role, uint16_t value, uint16_t max) {
+#if GFX_USE_GINPUT && GINPUT_NEED_DIAL
+ #define gsw ((GSliderObject *)gw)
+ (void) role;
+
+ // Set the new position
+ gsw->pos = (uint16_t)((uint32_t)value*(gsw->max-gsw->min)/max + gsw->min);
+
+ ResetDisplayPos(gsw);
+ gwinDraw(&gw->g);
+
+ // Generate the event
+ SendSliderEvent(gw);
#undef gsw
- #undef gh
+#else
+ (void)gw; (void)role; (void)value; (void)max;
+#endif
+}
+
+static void ToggleAssign(GWidgetObject *gw, uint16_t role, uint16_t instance) {
+ if (role)
+ ((GSliderObject *)gw)->t_up = instance;
+ else
+ ((GSliderObject *)gw)->t_dn = instance;
+}
+
+static uint16_t ToggleGet(GWidgetObject *gw, uint16_t role) {
+ return role ? ((GSliderObject *)gw)->t_up : ((GSliderObject *)gw)->t_dn;
+}
+
+static void DialAssign(GWidgetObject *gw, uint16_t role, uint16_t instance) {
+ (void) role;
+ ((GSliderObject *)gw)->dial = instance;
+}
+
+static uint16_t DialGet(GWidgetObject *gw, uint16_t role) {
+ (void) role;
+ return ((GSliderObject *)gw)->dial;
}
GHandle gwinCreateSlider(GSliderObject *gs, coord_t x, coord_t y, coord_t width, coord_t height) {
- if (!(gs = (GSliderObject *)_gwinInit((GWindowObject *)gs, x, y, width, height, sizeof(GSliderObject))))
+ if (!(gs = (GSliderObject *)_gwidgetCreate((GWidgetObject *)gs, x, y, width, height, sizeof(GSliderObject), &sliderVMT)))
return 0;
- gs->gwin.type = GW_SLIDER;
- gs->fn = gwinSliderDraw_Std;
- gs->param = 0;
- gwinSetSliderStyle(&gs->gwin, &GSliderDefaultStyle);
+ gs->t_dn = (uint16_t) -1;
+ gs->t_up = (uint16_t) -1;
+ gs->dial = (uint16_t) -1;
+ gs->c = GSliderDefaultColors;
gs->min = 0;
gs->max = 100;
gs->pos = 0;
- gs->tracking = FALSE;
- geventListenerInit(&gs->listener);
- geventRegisterCallback(&gs->listener, gwinSliderCallback, gs);
+ ResetDisplayPos(gs);
return (GHandle)gs;
}
void gwinSetSliderRange(GHandle gh, int min, int max) {
#define gsw ((GSliderObject *)gh)
- if (gh->type != GW_SLIDER)
+ if (gh->vmt != (gwinVMT *)&sliderVMT)
return;
if (min == max) // prevent divide by 0 errors.
@@ -160,13 +257,14 @@ void gwinSetSliderRange(GHandle gh, int min, int max) {
gsw->min = min;
gsw->max = max;
gsw->pos = min;
+ ResetDisplayPos(gsw);
#undef gsw
}
void gwinSetSliderPosition(GHandle gh, int pos) {
#define gsw ((GSliderObject *)gh)
- if (gh->type != GW_SLIDER)
+ if (gh->vmt != (gwinVMT *)&sliderVMT)
return;
if (gsw->min <= gsw->max) {
@@ -178,125 +276,96 @@ void gwinSetSliderPosition(GHandle gh, int pos) {
else if (pos < gsw->max) gsw->pos = gsw->max;
else gsw->pos = pos;
}
+ ResetDisplayPos(gsw);
#undef gsw
}
-void gwinSetSliderStyle(GHandle gh, const GSliderDrawStyle *pStyle) {
- #define gsw ((GSliderObject *)gh)
-
- if (gh->type != GW_SLIDER)
+void gwinSetSliderColors(GHandle gh, const GSliderColors *pColors) {
+ if (gh->vmt != (gwinVMT *)&sliderVMT)
return;
- gsw->style.color_edge = pStyle->color_edge;
- gsw->style.color_thumb = pStyle->color_thumb;
- gsw->style.color_active = pStyle->color_active;
- gsw->style.color_inactive = pStyle->color_inactive;
- #undef gsw
-}
-
-#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
- static void trackSliderDraw(GHandle gh, coord_t x, coord_t y) {
- #define gsw ((GSliderObject *)gh)
-
- #if GDISP_NEED_CLIP
- gdispSetClip(gh->x, gh->y, gh->width, gh->height);
- #endif
-
- if (gh->height <= gh->width)
- gsw->fn(gh, FALSE, x, &gsw->style, gsw->param);
- else
- gsw->fn(gh, TRUE, y, &gsw->style, gsw->param);
-
- #undef gbw
- }
-#endif
-
-void gwinSliderDraw(GHandle gh) {
- #define gsw ((GSliderObject *)gh)
-
- if (gh->type != GW_SLIDER)
- return;
-
- #if GDISP_NEED_CLIP
- gdispSetClip(gh->x, gh->y, gh->width, gh->height);
- #endif
-
- if (gh->height <= gh->width)
- gsw->fn(gh, FALSE, ((gh->width-1)*(gsw->pos-gsw->min))/(gsw->max-gsw->min), &gsw->style, gsw->param);
- else
- gsw->fn(gh, TRUE, gh->height-1-((gh->height-1)*(gsw->pos-gsw->min))/(gsw->max-gsw->min), &gsw->style, gsw->param);
-
- #undef gbw
+ ((GSliderObject *)gh)->c = *pColors;
}
-void gwinSetSliderCustom(GHandle gh, GSliderDrawFunction fn, void *param) {
- #define gsw ((GSliderObject *)gh)
+void gwinSliderDraw_Std(GWidgetObject *gw, void *param) {
+ #define gsw ((GSliderObject *)gw)
+ (void) param;
- if (gh->type != GW_SLIDER)
+ if (gw->g.vmt != (gwinVMT *)&sliderVMT)
return;
- gsw->fn = fn ? fn : gwinSliderDraw_Std;
- gsw->param = param;
+ if (gw->g.width < gw->g.height) { // Vertical slider
+ if (gsw->dpos != gw->g.height-1)
+ gdispFillArea(gw->g.x, gw->g.y+gsw->dpos, gw->g.width, gw->g.height - gsw->dpos, gsw->c.color_active);
+ if (gsw->dpos != 0)
+ gdispFillArea(gw->g.x, gw->g.y, gw->g.width, gsw->dpos, gsw->c.color_inactive);
+ gdispDrawBox(gw->g.x, gw->g.y, gw->g.width, gw->g.height, gsw->c.color_edge);
+ gdispDrawLine(gw->g.x, gw->g.y+gsw->dpos, gw->g.x+gw->g.width-1, gw->g.y+gsw->dpos, gsw->c.color_thumb);
+ if (gsw->dpos >= 2)
+ gdispDrawLine(gw->g.x, gw->g.y+gsw->dpos-2, gw->g.x+gw->g.width-1, gw->g.y+gsw->dpos-2, gsw->c.color_thumb);
+ if (gsw->dpos <= gw->g.height-2)
+ gdispDrawLine(gw->g.x, gw->g.y+gsw->dpos+2, gw->g.x+gw->g.width-1, gw->g.y+gsw->dpos+2, gsw->c.color_thumb);
+
+ // Horizontal slider
+ } else {
+ if (gsw->dpos != gw->g.width-1)
+ gdispFillArea(gw->g.x+gsw->dpos, gw->g.y, gw->g.width-gsw->dpos, gw->g.height, gsw->c.color_inactive);
+ if (gsw->dpos != 0)
+ gdispFillArea(gw->g.x, gw->g.y, gsw->dpos, gw->g.height, gsw->c.color_active);
+ gdispDrawBox(gw->g.x, gw->g.y, gw->g.width, gw->g.height, gsw->c.color_edge);
+ gdispDrawLine(gw->g.x+gsw->dpos, gw->g.y, gw->g.x+gsw->dpos, gw->g.y+gw->g.height-1, gsw->c.color_thumb);
+ if (gsw->dpos >= 2)
+ gdispDrawLine(gw->g.x+gsw->dpos-2, gw->g.y, gw->g.x+gsw->dpos-2, gw->g.y+gw->g.height-1, gsw->c.color_thumb);
+ if (gsw->dpos <= gw->g.width-2)
+ gdispDrawLine(gw->g.x+gsw->dpos+2, gw->g.y, gw->g.x+gsw->dpos+2, gw->g.y+gw->g.height-1, gsw->c.color_thumb);
+ }
+ gdispDrawStringBox(gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->txt, gw->g.font, gsw->c.color_txt, justifyCenter);
#undef gsw
}
-void gwinSliderSetEnabled(GHandle gh, bool_t enabled) {
- if (gh->type != GW_SLIDER)
- return;
+void gwinSliderDraw_Image(GWidgetObject *gw, void *param) {
+ #define gsw ((GSliderObject *)gw)
+ #define gi ((gdispImage *)param)
+ coord_t z, v;
- gh->enabled = enabled;
-}
+ if (gw->g.vmt != (gwinVMT *)&sliderVMT)
+ return;
-void gwinSliderDraw_Std(GHandle gh, bool_t isVertical, coord_t thumbpos, const GSliderDrawStyle *pstyle, void *param) {
- (void) param;
+ if (gw->g.width < gw->g.height) { // Vertical slider
+ if (gsw->dpos != 0) // The unfilled area
+ gdispFillArea(gw->g.x, gw->g.y, gw->g.width, gsw->dpos, gsw->c.color_inactive);
+ if (gsw->dpos != gw->g.height-1) { // The filled area
+ for(z=gw->g.height, v=gi->height; z > gsw->dpos;) {
+ z -= v;
+ if (z < gsw->dpos) {
+ v -= gsw->dpos - z;
+ z = gsw->dpos;
+ }
+ gdispImageDraw(gi, gw->g.x, gw->g.y+z, gw->g.width, v, 0, gi->height-v);
+ }
+ }
+ gdispDrawBox(gw->g.x, gw->g.y, gw->g.width, gw->g.height, gsw->c.color_edge);
+ gdispDrawLine(gw->g.x, gw->g.y+gsw->dpos, gw->g.x+gw->g.width-1, gw->g.y+gsw->dpos, gsw->c.color_thumb);
- if (isVertical) {
- if (thumbpos != gh->height-1)
- gdispFillArea(gh->x, gh->y+thumbpos, gh->width, gh->height - thumbpos, pstyle->color_active);
- if (thumbpos != 0)
- gdispFillArea(gh->x, gh->y, gh->width, thumbpos, pstyle->color_inactive);
- gdispDrawBox(gh->x, gh->y, gh->width, gh->height, pstyle->color_edge);
- gdispDrawLine(gh->x, gh->y+thumbpos, gh->x+gh->width-1, gh->y+thumbpos, pstyle->color_thumb);
- if (thumbpos >= 2)
- gdispDrawLine(gh->x, gh->y+thumbpos-2, gh->x+gh->width-1, gh->y+thumbpos-2, pstyle->color_thumb);
- if (thumbpos <= gh->height-2)
- gdispDrawLine(gh->x, gh->y+thumbpos+2, gh->x+gh->width-1, gh->y+thumbpos+2, pstyle->color_thumb);
+ // Horizontal slider
} else {
- if (thumbpos != gh->width-1)
- gdispFillArea(gh->x+thumbpos, gh->y, gh->width-thumbpos, gh->height, pstyle->color_inactive);
- if (thumbpos != 0)
- gdispFillArea(gh->x, gh->y, thumbpos, gh->height, pstyle->color_active);
- gdispDrawBox(gh->x, gh->y, gh->width, gh->height, pstyle->color_edge);
- gdispDrawLine(gh->x+thumbpos, gh->y, gh->x+thumbpos, gh->y+gh->height-1, pstyle->color_thumb);
- if (thumbpos >= 2)
- gdispDrawLine(gh->x+thumbpos-2, gh->y, gh->x+thumbpos-2, gh->y+gh->height-1, pstyle->color_thumb);
- if (thumbpos <= gh->width-2)
- gdispDrawLine(gh->x+thumbpos+2, gh->y, gh->x+thumbpos+2, gh->y+gh->height-1, pstyle->color_thumb);
- }
-}
-
-#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
- bool_t gwinAttachSliderMouse(GHandle gh, uint16_t instance) {
- GSourceHandle gsh;
-
- if (gh->type != GW_SLIDER || !(gsh = ginputGetMouse(instance)))
- return FALSE;
-
- return geventAttachSource(&((GSliderObject *)gh)->listener, gsh, GLISTEN_MOUSEMETA|GLISTEN_MOUSEDOWNMOVES);
+ if (gsw->dpos != gw->g.width-1) // The unfilled area
+ gdispFillArea(gw->g.x+gsw->dpos, gw->g.y, gw->g.width-gsw->dpos, gw->g.height, gsw->c.color_inactive);
+ if (gsw->dpos != 0) { // The filled area
+ for(z=0, v=gi->width; z < gsw->dpos; z += v) {
+ if (z+v > gsw->dpos)
+ v -= z+v - gsw->dpos;
+ gdispImageDraw(gi, gw->g.x+z, gw->g.y, v, gw->g.height, 0, 0);
+ }
+ }
+ gdispDrawBox(gw->g.x, gw->g.y, gw->g.width, gw->g.height, gsw->c.color_edge);
+ gdispDrawLine(gw->g.x+gsw->dpos, gw->g.y, gw->g.x+gsw->dpos, gw->g.y+gw->g.height-1, gsw->c.color_thumb);
}
-#endif
-
-#if GFX_USE_GINPUT && GINPUT_NEED_DIAL
- bool_t gwinAttachSliderDial(GHandle gh, uint16_t instance) {
- GSourceHandle gsh;
-
- if (gh->type != GW_SLIDER || !(gsh = ginputGetDial(instance)))
- return FALSE;
+ gdispDrawStringBox(gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->txt, gw->g.font, gsw->c.color_txt, justifyCenter);
- return geventAttachSource(&((GSliderObject *)gh)->listener, gsh, 0);
- }
-#endif
+ #undef gsw
+}
#endif /* GFX_USE_GWIN && GWIN_NEED_BUTTON */
/** @} */