aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--demos/modules/gwin/frame/demo.mk3
-rw-r--r--demos/modules/gwin/frame/gfxconf.h107
-rw-r--r--demos/modules/gwin/frame/main.c47
-rw-r--r--demos/modules/gwin/imagebox/main.c2
-rw-r--r--demos/modules/gwin/label/main.c4
-rw-r--r--demos/modules/gwin/list/main.c4
-rw-r--r--demos/modules/gwin/progressbar/main.c2
-rw-r--r--demos/modules/gwin/widgets/gfxconf.h8
-rw-r--r--demos/modules/gwin/widgets/main.c298
-rw-r--r--docs/releases.txt25
-rw-r--r--gfxconf.example.h336
-rw-r--r--src/gdisp/gdisp.c16
-rw-r--r--src/gdisp/sys_defs.h10
-rw-r--r--src/gdisp/sys_options.h2
-rw-r--r--src/gfile/gfile.c18
-rw-r--r--src/gfile/sys_options.h2
-rw-r--r--src/gwin/button.c12
-rw-r--r--src/gwin/checkbox.c8
-rw-r--r--src/gwin/class_gwin.h146
-rw-r--r--src/gwin/frame.c233
-rw-r--r--src/gwin/frame.h70
-rw-r--r--src/gwin/gcontainer.c193
-rw-r--r--src/gwin/gcontainer.h136
-rw-r--r--src/gwin/gimage.c4
-rw-r--r--src/gwin/gwidget.c67
-rw-r--r--src/gwin/gwin.c249
-rw-r--r--src/gwin/gwm.c142
-rw-r--r--src/gwin/label.c4
-rw-r--r--src/gwin/list.c28
-rw-r--r--src/gwin/progressbar.c10
-rw-r--r--src/gwin/radio.c12
-rw-r--r--src/gwin/slider.c14
-rw-r--r--src/gwin/sys_defs.h69
-rw-r--r--src/gwin/sys_make.mk2
-rw-r--r--src/gwin/sys_options.h21
-rw-r--r--src/gwin/sys_rules.h18
-rw-r--r--tools/file2c/src/file2c.c2
37 files changed, 1787 insertions, 537 deletions
diff --git a/demos/modules/gwin/frame/demo.mk b/demos/modules/gwin/frame/demo.mk
new file mode 100644
index 00000000..b10701c9
--- /dev/null
+++ b/demos/modules/gwin/frame/demo.mk
@@ -0,0 +1,3 @@
+DEMODIR = $(GFXLIB)/demos/modules/gwin/frame
+GFXINC += $(DEMODIR)
+GFXSRC += $(DEMODIR)/main.c
diff --git a/demos/modules/gwin/frame/gfxconf.h b/demos/modules/gwin/frame/gfxconf.h
new file mode 100644
index 00000000..6809013d
--- /dev/null
+++ b/demos/modules/gwin/frame/gfxconf.h
@@ -0,0 +1,107 @@
+/**
+ * This file has a different license to the rest of the uGFX system.
+ * You can copy, modify and distribute this file as you see fit.
+ * You do not need to publish your source modifications to this file.
+ * The only thing you are not permitted to do is to relicense it
+ * under a different license.
+ */
+
+/**
+ * Copy this file into your project directory and rename it as gfxconf.h
+ * Edit your copy to turn on the uGFX features you want to use.
+ * The values below are the defaults. You should delete anything
+ * you are leaving as default.
+ *
+ * Please use spaces instead of tabs in this file.
+ */
+
+#ifndef _GFXCONF_H
+#define _GFXCONF_H
+
+/* The operating system to use. One of these must be defined - preferably in your Makefile */
+//#define GFX_USE_OS_CHIBIOS TRUE
+//#define GFX_USE_OS_WIN32 TRUE
+//#define GFX_USE_OS_LINUX TRUE
+//#define GFX_USE_OS_OSX TRUE
+
+
+///////////////////////////////////////////////////////////////////////////
+// GDISP //
+///////////////////////////////////////////////////////////////////////////
+#define GFX_USE_GDISP TRUE
+
+#define GDISP_NEED_AUTOFLUSH FALSE
+#define GDISP_NEED_TIMERFLUSH FALSE
+#define GDISP_NEED_VALIDATION TRUE
+#define GDISP_NEED_CLIP TRUE
+#define GDISP_NEED_TEXT TRUE
+ #define GDISP_INCLUDE_FONT_UI2 TRUE
+#define GDISP_NEED_CIRCLE TRUE
+#define GDISP_NEED_CONVEX_POLYGON TRUE
+#define GDISP_NEED_MULTITHREAD TRUE
+
+#define GDISP_DEFAULT_ORIENTATION GDISP_ROTATE_LANDSCAPE
+
+///////////////////////////////////////////////////////////////////////////
+// GWIN //
+///////////////////////////////////////////////////////////////////////////
+#define GFX_USE_GWIN TRUE
+
+#define GWIN_NEED_WINDOWMANAGER TRUE
+
+#define GWIN_NEED_CONSOLE TRUE
+ #define GWIN_CONSOLE_USE_HISTORY TRUE
+ #define GWIN_CONSOLE_HISTORY_AVERAGING TRUE
+ #define GWIN_CONSOLE_HISTORY_ATCREATE TRUE
+ #define GWIN_CONSOLE_ESCSEQ TRUE
+ #define GWIN_CONSOLE_USE_BASESTREAM TRUE
+#define GWIN_NEED_GRAPH TRUE
+
+#define GWIN_NEED_WIDGET TRUE
+ #define GWIN_NEED_LABEL TRUE
+ #define GWIN_LABEL_ATTRIBUTE TRUE
+ #define GWIN_NEED_BUTTON TRUE
+ #define GWIN_BUTTON_LAZY_RELEASE TRUE
+ #define GWIN_NEED_SLIDER TRUE
+ #define GWIN_NEED_CHECKBOX TRUE
+ #define GWIN_NEED_IMAGE FALSE
+ #define GWIN_NEED_IMAGE_ANIMATION TRUE
+ #define GWIN_NEED_RADIO TRUE
+ #define GWIN_NEED_LIST TRUE
+ #define GWIN_NEED_LIST_IMAGES FALSE
+ #define GWIN_NEED_PROGRESSBAR TRUE
+ #define GWIN_PROGRESSBAR_AUTO TRUE
+ #define GWIN_FLAT_STYLING TRUE
+#define GWIN_NEED_CONTAINERS TRUE
+ #define GWIN_NEED_CONTAINER TRUE
+ #define GWIN_NEED_FRAME TRUE
+
+
+///////////////////////////////////////////////////////////////////////////
+// GEVENT //
+///////////////////////////////////////////////////////////////////////////
+#define GFX_USE_GEVENT TRUE
+
+///////////////////////////////////////////////////////////////////////////
+// GTIMER //
+///////////////////////////////////////////////////////////////////////////
+#define GFX_USE_GTIMER TRUE
+
+///////////////////////////////////////////////////////////////////////////
+// GQUEUE //
+///////////////////////////////////////////////////////////////////////////
+#define GFX_USE_GQUEUE TRUE
+
+#define GQUEUE_NEED_ASYNC TRUE
+#define GQUEUE_NEED_GSYNC TRUE
+#define GQUEUE_NEED_FSYNC FALSE
+#define GQUEUE_NEED_BUFFERS FALSE
+
+///////////////////////////////////////////////////////////////////////////
+// GINPUT //
+///////////////////////////////////////////////////////////////////////////
+#define GFX_USE_GINPUT TRUE
+
+#define GINPUT_NEED_MOUSE TRUE
+
+#endif /* _GFXCONF_H */
diff --git a/demos/modules/gwin/frame/main.c b/demos/modules/gwin/frame/main.c
new file mode 100644
index 00000000..ebfeaa6e
--- /dev/null
+++ b/demos/modules/gwin/frame/main.c
@@ -0,0 +1,47 @@
+#include "gfx.h"
+
+static GListener gl;
+static GHandle ghFrame1;
+
+static void createWidgets(void) {
+ GWidgetInit wi;
+
+ // Apply some default values for GWIN
+ gwinWidgetClearInit(&wi);
+ wi.g.show = TRUE;
+
+ // Apply the frame parameters
+ wi.g.width = 400;
+ wi.g.height = 300;
+ wi.g.y = 10;
+ wi.g.x = 10;
+ wi.text = "Frame 1";
+
+ ghFrame1 = gwinFrameCreate(0, &wi, GWIN_FRAME_BORDER | GWIN_FRAME_CLOSE_BTN | GWIN_FRAME_MINMAX_BTN);
+}
+
+int main(void) {
+ // Initialize the display
+ gfxInit();
+
+ // Attach the mouse input
+ gwinAttachMouse(0);
+
+ // Set the widget defaults
+ gwinSetDefaultFont(gdispOpenFont("*"));
+ gwinSetDefaultStyle(&WhiteWidgetStyle, FALSE);
+ gdispClear(White);
+
+ // create the widget
+ createWidgets();
+
+ // We want to listen for widget events
+ geventListenerInit(&gl);
+ gwinAttachListener(&gl);
+
+ while(1) {
+ gfxSleepMilliseconds(1000);
+ }
+
+ return 0;
+}
diff --git a/demos/modules/gwin/imagebox/main.c b/demos/modules/gwin/imagebox/main.c
index c15f5fb3..d8ebbe73 100644
--- a/demos/modules/gwin/imagebox/main.c
+++ b/demos/modules/gwin/imagebox/main.c
@@ -41,7 +41,7 @@ static void createWidgets(void) {
// create the first image widget
wi.g.x = 10; wi.g.y = 10; wi.g.width = 200; wi.g.height = 100;
- ghImage1 = gwinImageCreate(NULL, &wi.g);
+ ghImage1 = gwinImageCreate(0, &wi.g);
gwinImageOpenFile(ghImage1, "ugfx_logo_banner.bmp");
}
diff --git a/demos/modules/gwin/label/main.c b/demos/modules/gwin/label/main.c
index 175c0d6e..918f2787 100644
--- a/demos/modules/gwin/label/main.c
+++ b/demos/modules/gwin/label/main.c
@@ -44,13 +44,13 @@ static void createWidgets(void) {
// Create the IP label
wi.g.width = 200; wi.g.height = 20; wi.g.x = 10, wi.g.y = 80;
wi.text = "192.168.1.42";
- ghLabel1 = gwinLabelCreate(NULL, &wi);
+ ghLabel1 = gwinLabelCreate(0, &wi);
gwinLabelSetAttribute(ghLabel1, 100, "Current IP:");
// Create the DHCP label
wi.g.width = 200; wi.g.height = 20; wi.g.x = 10, wi.g.y = 100;
wi.text = "Off";
- ghLabel2 = gwinLabelCreate(NULL, &wi);
+ ghLabel2 = gwinLabelCreate(0, &wi);
gwinLabelSetAttribute(ghLabel2, 100, "DHCP:");
}
diff --git a/demos/modules/gwin/list/main.c b/demos/modules/gwin/list/main.c
index 6d469626..ed5b6905 100644
--- a/demos/modules/gwin/list/main.c
+++ b/demos/modules/gwin/list/main.c
@@ -43,12 +43,12 @@ static void createWidgets(void) {
// Create the label for the first list
wi.g.width = 150; wi.g.height = 20; wi.g.x = 10, wi.g.y = 80;
wi.text = "List 1: Default";
- ghLabel1 = gwinLabelCreate(NULL, &wi);
+ ghLabel1 = gwinLabelCreate(0, &wi);
// Create the label for the second list
wi.g.width = 150; wi.g.height = 20; wi.g.x = 165, wi.g.y = 80;
wi.text = "List 2: Smooth scrolling";
- ghLabel1 = gwinLabelCreate(NULL, &wi);
+ ghLabel1 = gwinLabelCreate(0, &wi);
// The first list widget
wi.g.width = 150;
diff --git a/demos/modules/gwin/progressbar/main.c b/demos/modules/gwin/progressbar/main.c
index 6fb53c2e..8e9e8352 100644
--- a/demos/modules/gwin/progressbar/main.c
+++ b/demos/modules/gwin/progressbar/main.c
@@ -9,7 +9,7 @@ static void _createWidget(void) {
wi.g.show = TRUE;
wi.g.y = 10; wi.g.x = 10; wi.g.width = 200; wi.g.height = 20; wi.text = "Progress 1";
- ghProgressbar = gwinProgressbarCreate(NULL, &wi);
+ ghProgressbar = gwinProgressbarCreate(0, &wi);
}
int main(void) {
diff --git a/demos/modules/gwin/widgets/gfxconf.h b/demos/modules/gwin/widgets/gfxconf.h
index 25065b27..9f8601b8 100644
--- a/demos/modules/gwin/widgets/gfxconf.h
+++ b/demos/modules/gwin/widgets/gfxconf.h
@@ -43,6 +43,7 @@
#define GDISP_NEED_IMAGE_GIF TRUE
#define GDISP_DEFAULT_ORIENTATION GDISP_ROTATE_LANDSCAPE
+#define GDISP_NEED_MULTITHREAD TRUE
///////////////////////////////////////////////////////////////////////////
// GWIN //
@@ -52,10 +53,14 @@
#define GWIN_NEED_WINDOWMANAGER TRUE
#define GWIN_NEED_CONSOLE TRUE
+ #define GWIN_CONSOLE_USE_HISTORY TRUE
+ #define GWIN_CONSOLE_HISTORY_AVERAGING TRUE
+ #define GWIN_CONSOLE_HISTORY_ATCREATE TRUE
#define GWIN_NEED_GRAPH TRUE
#define GWIN_NEED_WIDGET TRUE
#define GWIN_NEED_LABEL TRUE
+ #define GWIN_LABEL_ATTRIBUTE TRUE
#define GWIN_NEED_BUTTON TRUE
// #define GWIN_BUTTON_LAZY_RELEASE TRUE
#define GWIN_NEED_SLIDER TRUE
@@ -67,6 +72,9 @@
#define GWIN_NEED_PROGRESSBAR TRUE
#define GWIN_PROGRESSBAR_AUTO TRUE
+#define GWIN_NEED_CONTAINERS TRUE
+ #define GWIN_NEED_CONTAINER TRUE
+
///////////////////////////////////////////////////////////////////////////
// GEVENT //
///////////////////////////////////////////////////////////////////////////
diff --git a/demos/modules/gwin/widgets/main.c b/demos/modules/gwin/widgets/main.c
index 9742a027..69f90285 100644
--- a/demos/modules/gwin/widgets/main.c
+++ b/demos/modules/gwin/widgets/main.c
@@ -25,7 +25,7 @@
* (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 <stdio.h>
#include "gfx.h"
/**
@@ -71,13 +71,15 @@ static const GWidgetStyle YellowWidgetStyle = {
};
/* The variables we need */
+static font_t font;
static GListener gl;
static GHandle ghConsole;
static GHandle ghTabButtons, ghTabSliders, ghTabCheckboxes, ghTabLabels, ghTabRadios, ghTabLists, ghTabImages, ghTabProgressbar;
+static GHandle ghPgButtons, ghPgSliders, ghPgCheckboxes, ghPgLabels, ghPgRadios, ghPgLists, ghPgImages, ghPgProgressbars;
static GHandle ghButton1, ghButton2, ghButton3, ghButton4;
static GHandle ghSlider1, ghSlider2, ghSlider3, ghSlider4;
static GHandle ghCheckbox1, ghCheckbox2, ghCheckDisableAll;
-static GHandle ghLabel1;
+static GHandle ghLabelSlider1, ghLabelSlider2, ghLabelSlider3, ghLabelSlider4, ghLabelRadio1;
static GHandle ghRadio1, ghRadio2;
static GHandle ghRadioBlack, ghRadioWhite, ghRadioYellow;
static GHandle ghList1, ghList2, ghList3, ghList4;
@@ -89,11 +91,12 @@ static gdispImage imgYesNo;
#define ScrWidth gdispGetWidth()
#define ScrHeight gdispGetHeight()
+#define BUTTON_PADDING 20
#define TAB_HEIGHT 30
-#define LABEL_HEIGHT 40
+#define LABEL_HEIGHT 15
#define BUTTON_WIDTH 50
#define BUTTON_HEIGHT 30
-#define LIST_WIDTH 100
+#define LIST_WIDTH 75
#define LIST_HEIGHT 80
#define SLIDER_WIDTH 20
#define CHECKBOX_WIDTH 80
@@ -106,6 +109,20 @@ static gdispImage imgYesNo;
#define GROUP_YESNO 1
#define GROUP_COLORS 2
+// Wrap tabs onto the next line if they don't fit.
+static void setbtntext(GWidgetInit *pwi, coord_t maxwidth, char *txt) {
+ if (pwi->g.x >= maxwidth) {
+ pwi->g.x = 0;
+ pwi->g.y += pwi->g.height;
+ }
+ pwi->text = txt;
+ pwi->g.width = gdispGetStringWidth(pwi->text, font) + BUTTON_PADDING;
+ if (pwi->g.x + pwi->g.width > maxwidth) {
+ pwi->g.x = 0;
+ pwi->g.y += pwi->g.height;
+ }
+}
+
/**
* Create all the widgets.
* With the exception of the Tabs they are all created invisible.
@@ -117,86 +134,132 @@ static void createWidgets(void) {
// Create the Tabs
wi.g.show = TRUE; wi.customDraw = gwinRadioDraw_Tab;
- wi.g.width = ScrWidth/7; wi.g.height = TAB_HEIGHT; wi.g.y = 0;
- wi.g.x = 0*wi.g.width; wi.text = "Buttons";
+ wi.g.height = TAB_HEIGHT; wi.g.y = 0;
+ wi.g.x = 0; setbtntext(&wi, ScrWidth, "Buttons");
ghTabButtons = gwinRadioCreate(0, &wi, GROUP_TABS);
- wi.g.x = 1*wi.g.width; wi.text = "Sliders";
+ wi.g.x += wi.g.width; setbtntext(&wi, ScrWidth, "Sliders");
ghTabSliders = gwinRadioCreate(0, &wi, GROUP_TABS);
- wi.g.x = 2*wi.g.width; wi.text = "Checkbox";
+ wi.g.x += wi.g.width; setbtntext(&wi, ScrWidth, "Checkbox");
ghTabCheckboxes = gwinRadioCreate(0, &wi, GROUP_TABS);
- wi.g.x = 3*wi.g.width; wi.text = "Radios";
+ wi.g.x += wi.g.width; setbtntext(&wi, ScrWidth, "Radios");
ghTabRadios = gwinRadioCreate(0, &wi, GROUP_TABS);
- wi.g.x = 4*wi.g.width; wi.text = "Lists";
+ wi.g.x += wi.g.width; setbtntext(&wi, ScrWidth, "Lists");
ghTabLists = gwinRadioCreate(0, &wi, GROUP_TABS);
- wi.g.x = 5*wi.g.width; wi.text = "Labels";
+ wi.g.x += wi.g.width; setbtntext(&wi, ScrWidth, "Labels");
ghTabLabels = gwinRadioCreate(0, &wi, GROUP_TABS);
- wi.g.x = 6*wi.g.width; wi.text = "Images";
+ wi.g.x += wi.g.width; setbtntext(&wi, ScrWidth, "Images");
ghTabImages = gwinRadioCreate(0, &wi, GROUP_TABS);
- wi.g.y = TAB_HEIGHT;
- wi.g.x = 0*wi.g.width; wi.text = "Progressbar";
+ wi.g.x += wi.g.width; setbtntext(&wi, ScrWidth, "Progressbar");
ghTabProgressbar = gwinRadioCreate(0, &wi, GROUP_TABS);
+ wi.g.y += wi.g.height;
+ wi.customDraw = 0;
+
+ // Create the Pages
+ wi.g.show = FALSE;
+ wi.g.x = 5; wi.g.y += 5;
+ wi.g.width = ScrWidth/2 - 10; wi.g.height = ScrHeight-wi.g.y-5;
+ ghPgButtons = gwinContainerCreate(0, &wi, GWIN_CONTAINER_BORDER);
+ ghPgSliders = gwinContainerCreate(0, &wi, GWIN_CONTAINER_BORDER);
+ ghPgCheckboxes = gwinContainerCreate(0, &wi, GWIN_CONTAINER_BORDER);
+ ghPgRadios = gwinContainerCreate(0, &wi, GWIN_CONTAINER_BORDER);
+ ghPgLists = gwinContainerCreate(0, &wi, GWIN_CONTAINER_BORDER);
+ ghPgLabels = gwinContainerCreate(0, &wi, GWIN_CONTAINER_BORDER);
+ ghPgImages = gwinContainerCreate(0, &wi, GWIN_CONTAINER_BORDER);
+ ghPgProgressbars = gwinContainerCreate(0, &wi, GWIN_CONTAINER_BORDER);
+ wi.g.show = TRUE;
+
+ // Console - we apply some special colors before making it visible
+ wi.g.x = ScrWidth/2+1;
+ wi.g.width = ScrWidth/2 - 5;
+ ghConsole = gwinConsoleCreate(0, &wi.g);
+ gwinSetColor(ghConsole, Yellow);
+ gwinSetBgColor(ghConsole, Black);
- // Buttons
- wi.g.show = FALSE; wi.customDraw = 0;
- wi.g.width = BUTTON_WIDTH; wi.g.height = BUTTON_HEIGHT; wi.g.y = 2*TAB_HEIGHT+10;
- wi.g.x = 0+0*(BUTTON_WIDTH+1); wi.text = "B1";
+ // Buttons
+ wi.g.parent = ghPgButtons;
+ wi.g.width = BUTTON_WIDTH; wi.g.height = BUTTON_HEIGHT; wi.g.y = 5;
+ wi.g.x = 5; setbtntext(&wi, gwinGetInnerWidth(ghPgButtons), "Button 1");
ghButton1 = gwinButtonCreate(0, &wi);
- wi.g.x = 0+1*(BUTTON_WIDTH+1); wi.text = "B2";
+ wi.g.x += wi.g.width+3; setbtntext(&wi, gwinGetInnerWidth(ghPgButtons), "Button 2");
ghButton2 = gwinButtonCreate(0, &wi);
- wi.g.x = 0+2*(BUTTON_WIDTH+1); wi.text = "B3";
+ wi.g.x += wi.g.width+3; setbtntext(&wi, gwinGetInnerWidth(ghPgButtons), "Button 3");
ghButton3 = gwinButtonCreate(0, &wi);
- wi.g.x = 0+3*(BUTTON_WIDTH+1); wi.text = "B4";
+ wi.g.x += wi.g.width+3; setbtntext(&wi, gwinGetInnerWidth(ghPgButtons), "Button 4");
ghButton4 = gwinButtonCreate(0, &wi);
// Horizontal Sliders
- wi.g.width = ScrWidth/2-2; wi.g.height = SLIDER_WIDTH; wi.g.x = ScrWidth/2+1;
- wi.g.y = ScrHeight/2-2*(SLIDER_WIDTH+1); wi.text = "S1";
+ wi.g.parent = ghPgSliders;
+ wi.g.width = gwinGetInnerWidth(ghPgSliders) - 10; wi.g.height = SLIDER_WIDTH;
+ wi.g.x = 5; wi.g.y = 5; wi.text = "S1";
ghSlider1 = gwinSliderCreate(0, &wi);
- wi.g.y = ScrHeight/2-1*(SLIDER_WIDTH+1); wi.text = "S2";
+ gwinSliderSetPosition(ghSlider1, 33);
+ wi.g.y += wi.g.height + 1; wi.text = "S2";
ghSlider2 = gwinSliderCreate(0, &wi);
+ gwinSliderSetPosition(ghSlider2, 86);
// Vertical Sliders
- wi.g.width = SLIDER_WIDTH; wi.g.height = ScrHeight/2-2; wi.g.y = ScrHeight/2+1;
- wi.g.x = 0+0*(SLIDER_WIDTH+1); wi.text = "S3";
+ wi.g.y += wi.g.height + 5;
+ wi.g.width = SLIDER_WIDTH; wi.g.height = gwinGetInnerHeight(ghPgSliders) - 5 - wi.g.y;
+ wi.g.x = 5; wi.text = "S3";
ghSlider3 = gwinSliderCreate(0, &wi);
- wi.g.x = 0+1*(SLIDER_WIDTH+1); wi.text = "S4";
+ gwinSliderSetPosition(ghSlider3, 13);
+ wi.g.x += wi.g.width+1; wi.text = "S4";
ghSlider4 = gwinSliderCreate(0, &wi);
+ gwinSliderSetPosition(ghSlider4, 76);
// Checkboxes - for the 2nd checkbox we apply special drawing before making it visible
- wi.g.width = CHECKBOX_WIDTH; wi.g.height = CHECKBOX_HEIGHT; wi.g.x = 0;
- wi.g.y = 2*TAB_HEIGHT+10+0*(CHECKBOX_HEIGHT+1); wi.text = "C1";
+ wi.g.parent = ghPgCheckboxes;
+ wi.g.width = CHECKBOX_WIDTH; wi.g.height = CHECKBOX_HEIGHT; wi.g.x = 5;
+ wi.g.y = 5; wi.text = "C1";
ghCheckbox1 = gwinCheckboxCreate(0, &wi);
wi.customDraw = gwinCheckboxDraw_CheckOnRight;
- wi.g.y = 2*TAB_HEIGHT+10+1*(CHECKBOX_HEIGHT+1); wi.text = "C2";
+ wi.g.y += wi.g.height+1; wi.text = "C2";
ghCheckbox2 = gwinCheckboxCreate(0, &wi);
wi.customDraw = 0; wi.g.width = DISABLEALL_WIDTH;
- wi.g.y = 2*TAB_HEIGHT+10+2*(CHECKBOX_HEIGHT+1); wi.text = "Disable All";
+ wi.g.y += wi.g.height+1; wi.text = "Disable All";
ghCheckDisableAll = gwinCheckboxCreate(0, &wi);
// Labels
- wi.g.width = 0; wi.g.height = LABEL_HEIGHT; // dynamic width, fixed height
- wi.g.y = 2*TAB_HEIGHT+10+2*(CHECKBOX_HEIGHT+1); wi.text = "Label";
- ghLabel1 = gwinLabelCreate(0, &wi);
+ wi.g.parent = ghPgLabels;
+ wi.g.width = 200; wi.g.height = LABEL_HEIGHT;
+ wi.g.x = wi.g.y = 5;wi.text = "N/A";
+ ghLabelSlider1 = gwinLabelCreate(0, &wi);
+ gwinLabelSetAttribute(ghLabelSlider1, 100, "Slider 1:");
+ wi.g.y += LABEL_HEIGHT + 2;
+ ghLabelSlider2 = gwinLabelCreate(0, &wi);
+ gwinLabelSetAttribute(ghLabelSlider2, 100, "Slider 2:");
+ wi.g.y += LABEL_HEIGHT + 2;
+ ghLabelSlider3 = gwinLabelCreate(0, &wi);
+ gwinLabelSetAttribute(ghLabelSlider3, 100, "Slider 3:");
+ wi.g.y += LABEL_HEIGHT + 2;
+ ghLabelSlider4 = gwinLabelCreate(0, &wi);
+ gwinLabelSetAttribute(ghLabelSlider4, 100, "Slider 4:");
+ wi.g.y += LABEL_HEIGHT + 2;
+ ghLabelRadio1 = gwinLabelCreate(0, &wi);
+ gwinLabelSetAttribute(ghLabelRadio1, 100, "RadioButton 1:");
+
// Radio Buttons
- wi.g.width = RADIO_WIDTH; wi.g.height = RADIO_HEIGHT; wi.g.y = 2*TAB_HEIGHT+10;
- wi.g.x = 0*wi.g.width; wi.text = "Yes";
+ wi.g.parent = ghPgRadios;
+ wi.g.width = RADIO_WIDTH; wi.g.height = RADIO_HEIGHT; wi.g.y = 5;
+ wi.g.x = 5; wi.text = "Yes";
ghRadio1 = gwinRadioCreate(0, &wi, GROUP_YESNO);
- wi.g.x = 1*wi.g.width; wi.text = "No";
+ wi.g.x += wi.g.width; wi.text = "No"; if (wi.g.x + wi.g.width > gwinGetInnerWidth(ghPgRadios)) { wi.g.x = 0; wi.g.y += RADIO_HEIGHT; }
ghRadio2 = gwinRadioCreate(0, &wi, GROUP_YESNO);
+ gwinRadioPress(ghRadio1);
wi.g.width = COLOR_WIDTH; wi.g.y += RADIO_HEIGHT+5;
- wi.g.x = 0*wi.g.width; wi.text = "Black";
+ wi.g.x = 5; wi.text = "Black";
ghRadioBlack = gwinRadioCreate(0, &wi, GROUP_COLORS);
- wi.g.x = 1*wi.g.width; wi.text = "White";
+ wi.g.x += wi.g.width; wi.text = "White"; if (wi.g.x + wi.g.width > gwinGetInnerWidth(ghPgRadios)) { wi.g.x = 0; wi.g.y += RADIO_HEIGHT; }
ghRadioWhite = gwinRadioCreate(0, &wi, GROUP_COLORS);
- wi.g.x = 2*wi.g.width; wi.text = "Yellow";
+ wi.g.x += wi.g.width; wi.text = "Yellow"; if (wi.g.x + wi.g.width > gwinGetInnerWidth(ghPgRadios)) { wi.g.x = 0; wi.g.y += RADIO_HEIGHT; }
ghRadioYellow = gwinRadioCreate(0, &wi, GROUP_COLORS);
gwinRadioPress(ghRadioWhite);
// Lists
- wi.g.show = FALSE; wi.customDraw = 0;
- wi.g.width = LIST_WIDTH; wi.g.height = LIST_HEIGHT; wi.g.y = 2*TAB_HEIGHT+10;
- wi.g.x = 0+0*(LIST_WIDTH+5); wi.text = "L1";
+ wi.g.parent = ghPgLists;
+ wi.g.width = LIST_WIDTH; wi.g.height = LIST_HEIGHT; wi.g.y = 5;
+ wi.g.x = 5; wi.text = "L1";
ghList1 = gwinListCreate(0, &wi, FALSE);
gwinListAddItem(ghList1, "Item 0", FALSE);
gwinListAddItem(ghList1, "Item 1", FALSE);
@@ -212,7 +275,7 @@ static void createWidgets(void) {
gwinListAddItem(ghList1, "Item 11", FALSE);
gwinListAddItem(ghList1, "Item 12", FALSE);
gwinListAddItem(ghList1, "Item 13", FALSE);
- wi.g.x = 0+1*(LIST_WIDTH+5); wi.text = "L2";
+ wi.text = "L2"; wi.g.x += LIST_WIDTH+1; if (wi.g.x + LIST_WIDTH > gwinGetInnerWidth(ghPgLists)) { wi.g.x = 0; wi.g.y += LIST_HEIGHT+1; }
ghList2 = gwinListCreate(0, &wi, TRUE);
gwinListAddItem(ghList2, "Item 0", FALSE);
gwinListAddItem(ghList2, "Item 1", FALSE);
@@ -228,7 +291,7 @@ static void createWidgets(void) {
gwinListAddItem(ghList2, "Item 11", FALSE);
gwinListAddItem(ghList2, "Item 12", FALSE);
gwinListAddItem(ghList2, "Item 13", FALSE);
- wi.g.x = 0+2*(LIST_WIDTH+5); wi.text = "L3";
+ wi.text = "L3"; wi.g.x += LIST_WIDTH+1; if (wi.g.x + LIST_WIDTH > gwinGetInnerWidth(ghPgLists)) { wi.g.x = 0; wi.g.y += LIST_HEIGHT+1; }
ghList3 = gwinListCreate(0, &wi, TRUE);
gwinListAddItem(ghList3, "Item 0", FALSE);
gwinListAddItem(ghList3, "Item 1", FALSE);
@@ -237,7 +300,7 @@ static void createWidgets(void) {
gdispImageOpenFile(&imgYesNo, "image_yesno.gif");
gwinListItemSetImage(ghList3, 1, &imgYesNo);
gwinListItemSetImage(ghList3, 3, &imgYesNo);
- wi.g.x = 0+3*(LIST_WIDTH+5); wi.text = "L4";
+ wi.text = "L4"; wi.g.x += LIST_WIDTH+1; if (wi.g.x + LIST_WIDTH > gwinGetInnerWidth(ghPgLists)) { wi.g.x = 0; wi.g.y += LIST_HEIGHT+1; }
ghList4 = gwinListCreate(0, &wi, TRUE);
gwinListAddItem(ghList4, "Item 0", FALSE);
gwinListAddItem(ghList4, "Item 1", FALSE);
@@ -256,23 +319,17 @@ static void createWidgets(void) {
gwinListSetScroll(ghList4, scrollSmooth);
// Image
- wi.g.x = 20; wi.g.y = 2*TAB_HEIGHT+20; wi.g.width = 200; wi.g.height = 100;
+ wi.g.parent = ghPgImages;
+ wi.g.x = wi.g.y = 0; wi.g.width = gwinGetInnerWidth(ghPgImages); wi.g.height = gwinGetInnerHeight(ghPgImages);
ghImage1 = gwinImageCreate(0, &wi.g);
gwinImageOpenFile(ghImage1, "romfs_img_ugfx.gif");
// Progressbar
- wi.g.show = FALSE; wi.customDraw = 0;
- wi.g.width = 200; wi.g.height = 20; wi.g.y = 2*TAB_HEIGHT+10;
- wi.g.x = 20; wi.text = "Progressbar 1";
+ wi.g.parent = ghPgProgressbars;
+ wi.g.width = gwinGetInnerWidth(ghPgImages)-5; wi.g.height = SLIDER_WIDTH; wi.g.y = 5;
+ wi.g.x = 5; wi.text = "Progressbar 1";
ghProgressbar1 = gwinProgressbarCreate(0, &wi);
gwinProgressbarSetResolution(ghProgressbar1, 10);
-
- // Console - we apply some special colors before making it visible
- wi.g.width = ScrWidth/2-1; wi.g.height = ScrHeight/2-1;
- wi.g.x = ScrWidth/2+1; wi.g.y = ScrHeight/2+1;
- ghConsole = gwinConsoleCreate(0, &wi.g);
- gwinSetColor(ghConsole, Yellow);
- gwinSetBgColor(ghConsole, Black);
}
/**
@@ -280,29 +337,14 @@ static void createWidgets(void) {
*/
static void setTab(GHandle tab) {
/* Make sure everything is invisible first */
- gwinSetVisible(ghButton1, FALSE);
- gwinSetVisible(ghButton2, FALSE);
- gwinSetVisible(ghButton3, FALSE);
- gwinSetVisible(ghButton4, FALSE);
- gwinSetVisible(ghSlider1, FALSE);
- gwinSetVisible(ghSlider2, FALSE);
- gwinSetVisible(ghSlider3, FALSE);
- gwinSetVisible(ghSlider4, FALSE);
- gwinSetVisible(ghCheckbox1, FALSE);
- gwinSetVisible(ghCheckbox2, FALSE);
- gwinSetVisible(ghCheckDisableAll, FALSE);
- gwinSetVisible(ghLabel1, FALSE);
- gwinSetVisible(ghRadio1, FALSE);
- gwinSetVisible(ghRadio2, FALSE);
- gwinSetVisible(ghRadioWhite, FALSE);
- gwinSetVisible(ghRadioBlack, FALSE);
- gwinSetVisible(ghRadioYellow, FALSE);
- gwinSetVisible(ghList1, FALSE);
- gwinSetVisible(ghList2, FALSE);
- gwinSetVisible(ghList3, FALSE);
- gwinSetVisible(ghList4, FALSE);
- gwinSetVisible(ghImage1, FALSE);
- gwinSetVisible(ghProgressbar1, FALSE);
+ gwinHide(ghPgButtons);
+ gwinHide(ghPgSliders);
+ gwinHide(ghPgCheckboxes);
+ gwinHide(ghPgLabels);
+ gwinHide(ghPgRadios);
+ gwinHide(ghPgLists);
+ gwinHide(ghPgImages);
+ gwinHide(ghPgProgressbars);
// Stop the progress bar
gwinProgressbarStop(ghProgressbar1);
@@ -310,36 +352,21 @@ static void setTab(GHandle tab) {
/* Turn on widgets depending on the tab selected */
if (tab == ghTabButtons) {
- gwinSetVisible(ghButton1, TRUE);
- gwinSetVisible(ghButton2, TRUE);
- gwinSetVisible(ghButton3, TRUE);
- gwinSetVisible(ghButton4, TRUE);
+ gwinShow(ghPgButtons);
} else if (tab == ghTabSliders) {
- gwinSetVisible(ghSlider1, TRUE);
- gwinSetVisible(ghSlider2, TRUE);
- gwinSetVisible(ghSlider3, TRUE);
- gwinSetVisible(ghSlider4, TRUE);
+ gwinShow(ghPgSliders);
} else if (tab == ghTabCheckboxes) {
- gwinSetVisible(ghCheckbox1, TRUE);
- gwinSetVisible(ghCheckbox2, TRUE);
- gwinSetVisible(ghCheckDisableAll, TRUE);
+ gwinShow(ghPgCheckboxes);
} else if (tab == ghTabLabels) {
- gwinSetVisible(ghLabel1, TRUE);
+ gwinShow(ghPgLabels);
} else if (tab == ghTabRadios) {
- gwinSetVisible(ghRadio1, TRUE);
- gwinSetVisible(ghRadio2, TRUE);
- gwinSetVisible(ghRadioWhite, TRUE);
- gwinSetVisible(ghRadioBlack, TRUE);
- gwinSetVisible(ghRadioYellow, TRUE);
+ gwinShow(ghPgRadios);
} else if (tab == ghTabLists) {
- gwinSetVisible(ghList1, TRUE);
- gwinSetVisible(ghList2, TRUE);
- gwinSetVisible(ghList3, TRUE);
- gwinSetVisible(ghList4, TRUE);
+ gwinShow(ghPgLists);
} else if (tab == ghTabImages) {
- gwinSetVisible(ghImage1, TRUE);
+ gwinShow(ghPgImages);
} else if (tab == ghTabProgressbar) {
- gwinSetVisible(ghProgressbar1, TRUE);
+ gwinShow(ghPgProgressbars);
// Start the progress bar
gwinProgressbarStart(ghProgressbar1, 500);
@@ -350,29 +377,17 @@ static void setTab(GHandle tab) {
* Set the enabled state of every widget (except the tabs etc)
*/
static void setEnabled(bool_t ena) {
- gwinSetEnabled(ghButton1, ena);
- gwinSetEnabled(ghButton2, ena);
- gwinSetEnabled(ghButton3, ena);
- gwinSetEnabled(ghButton4, ena);
- gwinSetEnabled(ghSlider1, ena);
- gwinSetEnabled(ghSlider2, ena);
- gwinSetEnabled(ghSlider3, ena);
- gwinSetEnabled(ghSlider4, ena);
+ gwinSetEnabled(ghPgButtons, ena);
+ gwinSetEnabled(ghPgSliders, ena);
+ gwinSetEnabled(ghPgLabels, ena);
+ gwinSetEnabled(ghPgRadios, ena);
+ gwinSetEnabled(ghPgLists, ena);
+ gwinSetEnabled(ghPgImages, ena);
+ gwinSetEnabled(ghPgProgressbars, ena);
+ // Checkboxes we need to do individually so we don't disable the checkbox to re-enable everything
gwinSetEnabled(ghCheckbox1, ena);
gwinSetEnabled(ghCheckbox2, ena);
//gwinSetEnabled(ghCheckDisableAll, TRUE);
- gwinSetEnabled(ghLabel1, ena);
- gwinSetEnabled(ghRadio1, ena);
- gwinSetEnabled(ghRadio2, ena);
- gwinSetEnabled(ghList1, ena);
- gwinSetEnabled(ghList2, ena);
- gwinSetEnabled(ghList3, ena);
- gwinSetEnabled(ghList4, ena);
- gwinSetEnabled(ghRadioWhite, ena);
- gwinSetEnabled(ghRadioBlack, ena);
- gwinSetEnabled(ghRadioYellow, ena);
- gwinSetEnabled(ghImage1, ena);
- gwinSetEnabled(ghProgressbar1, ena);
}
int main(void) {
@@ -387,7 +402,8 @@ int main(void) {
#endif
// Set the widget defaults
- gwinSetDefaultFont(gdispOpenFont("*"));
+ font = gdispOpenFont("*"); // Get the first defined font.
+ gwinSetDefaultFont(font);
gwinSetDefaultStyle(&WhiteWidgetStyle, FALSE);
gdispClear(White);
@@ -405,7 +421,7 @@ int main(void) {
#endif
// Make the console visible
- gwinSetVisible(ghConsole, TRUE);
+ gwinShow(ghConsole);
gwinClear(ghConsole);
// We want to listen for widget events
@@ -452,14 +468,26 @@ int main(void) {
// Set control visibility depending on the tab selected
setTab(((GEventGWinRadio *)pe)->radio);
- // Do some special animation for Label1 to demonstrate auto width sizing
+ // We show the state of some of the GUI elements here
if (((GEventGWinRadio *)pe)->radio == ghTabLabels) {
- gwinPrintf(ghConsole, "Change Label Text\n");
- gfxSleepMilliseconds(1000);
- gwinSetText(ghLabel1, "Very Big Label", FALSE);
-
- gfxSleepMilliseconds(1000);
- gwinSetText(ghLabel1, "Label", FALSE);
+ char tmp[20];
+
+ // The sliders
+ snprintf(tmp, sizeof(tmp), "%d%%", gwinSliderGetPosition(ghSlider1));
+ gwinSetText(ghLabelSlider1, tmp, TRUE);
+ snprintf(tmp, sizeof(tmp), "%d%%", gwinSliderGetPosition(ghSlider2));
+ gwinSetText(ghLabelSlider2, tmp, TRUE);
+ snprintf(tmp, sizeof(tmp), "%d%%", gwinSliderGetPosition(ghSlider3));
+ gwinSetText(ghLabelSlider3, tmp, TRUE);
+ snprintf(tmp, sizeof(tmp), "%d%%", gwinSliderGetPosition(ghSlider4));
+ gwinSetText(ghLabelSlider4, tmp, TRUE);
+
+ // The radio buttons
+ if (gwinRadioIsPressed(ghRadio1)) {
+ gwinSetText(ghLabelRadio1, "Yes", TRUE);
+ } else if (gwinRadioIsPressed(ghRadio2)) {
+ gwinSetText(ghLabelRadio1, "No", TRUE);
+ }
}
break;
@@ -480,11 +508,13 @@ int main(void) {
#if GDISP_NEED_CLIP
gdispUnsetClip();
#endif
- gdispFillArea(0, 0, ScrWidth, ScrHeight/2, pstyle->background);
- gdispFillArea(0, ScrHeight/2, ScrWidth/2, ScrHeight/2, pstyle->background);
+ gdispClear(pstyle->background);
// Update the style on all controls
gwinSetDefaultStyle(pstyle, TRUE);
+
+ // Redraw the console too
+ //gwinRedraw(ghConsole);
}
break;
}
diff --git a/docs/releases.txt b/docs/releases.txt
index b08f970e..b7c019aa 100644
--- a/docs/releases.txt
+++ b/docs/releases.txt
@@ -2,7 +2,7 @@
*** Releases ***
*****************************************************************************
-current release: 2.0
+*** Changes After 2.0 ***
FIX: Significant improvements to the way the MCU touch driver works.
FEATURE: Add support for edge to edge touch calibration.
FEATURE: Added progressbar widget
@@ -36,9 +36,12 @@ FEATURE: Added many GWIN simple demo's and updated the combined widget demo
FEATURE: Added gwinEnable() and gwinDisable()
FIX: Progressbar widget bug fix that could gwinProgressbarStop() to crash
FIX: Imagebox widget bug fix that could cause gwinImageOpenFile() to crash
+FEATURE: GWIN containers such as "container" and "frame" which provides parent/children widget management
+FEATURE: Added gdispContrastColor()
+FEATURE: Added gwinShow() and gwinHide()
-*** changes after 1.9 ***
+*** Release 2.0 ***
FEATURE: GDISP Streaming API and demos.
DEPRECATE: GDISP_NEED_ASYNC is now deprecated.
DEPRECATE: 3rd party boing demo is now deprecated (replaced by GDISP Streaming demo)
@@ -66,7 +69,7 @@ FEATURE: Board definitions, example projects and makefiles for the Marlin board.
FEATURE: New invsqrt() routine added to GMISC
-*** changes after 1.8 ***
+*** Release 1.9 ***
FEATURE: GWIN list boxes.
FIX: POSIX port removed, now dedicated OS-X and Linux ports
FIX: Several bugfixes
@@ -80,7 +83,7 @@ FEATURE: Added gwinListSetScroll()
FEATURE: Added gwinLabelSetBorder()
-*** changes after 1.7 ***
+*** Release 1.8 ***
FEATURE: Rename of the project from ChibiOS/GFX to uGFX
FEATURE: Moved from github.com to bitbucket.org
FEATURE: New website with a lot more of documentation
@@ -92,13 +95,13 @@ FIX: gfxHalt() fix for the Win32 port
FIX: Cleaned up board file mess
-*** changes after 1.6 ***
+*** Release 1.7 ***
FEATURE: Added RA8875 GDISP driver
FEATURE: Added FT5x06 GINPUT/touch driver
FIX: Several bugfixes
-*** changes after 1.5 ***
+*** Release 1.6 ***
FEATURE: Added ILI9325 driver - Thanks to Chris van Dongen aka _Sjaak
FEATURE: Added TDISP module
FIX: tdispGotoXY() renamed to tdispSetCursor()
@@ -130,7 +133,7 @@ FEATURE: Added GOS module (including sub modules such as GQUEUE)
FEATURE: Added some functionalities to the TDISP module by user 'Frysk'
-*** changes after 1.4 ***
+*** Release 1.5 ***
FEATURE: GEVENT - for passing event structures from Sources to Listeners
FEATURE: GTIMER - thread context based once-off and periodic timers.
FEATURE: GINPUT - extensible, multiple device-type, input sub-system.
@@ -150,7 +153,7 @@ FEATURE: Added a number of module demo and test programs
DEPRECATE: Remove of XPT2046 since full compatibility with ADS7843
-*** changes after 1.3 ***
+*** Release 1.4 ***
FIX: Nokia 6610 fix
FEATURE: New driver: Win32
FEATURE: implementation of gdispFillArc()
@@ -162,7 +165,7 @@ FEATURE: GWIN infrastructure
FEATURE: now we fully support doxygen
-*** changes after 1.2 ***
+*** Release 1.3 ***
FEATURE: added FSMC for SSD1289 / F4
FEATURE: added calibration storage interface
FIX: bugfix in filling functions for SSD1289
@@ -170,7 +173,7 @@ FEATURE: added point_t struct in gdisp.h
FEATURE: added graph module
-*** changer after 1.1 ***
+*** Release 1.2 ***
FIX: orientation macros changed
FIX: huge internal bugfix in orientation stuff (big thanks to Abhishek)
FEATURE: added TOUCHPAD_XY_INVERTED macro
@@ -182,7 +185,7 @@ FIX: lcdConsoleXXX() functions have been renamed to gfxConsoleXXX()
FEATURE: FSMC for SSD1289 F2/F4
-*** changes after 1.0 ***
+*** Release 1.1 ***
FIX: removed gdisp and touchpad prefix of driver directories
UPDATE: added SSD1963 driver
FIX: fixed Validation, VMT driver, console and BitBlit
diff --git a/gfxconf.example.h b/gfxconf.example.h
index 6b545307..652b6a1b 100644
--- a/gfxconf.example.h
+++ b/gfxconf.example.h
@@ -9,8 +9,12 @@
/**
* Copy this file into your project directory and rename it as gfxconf.h
* Edit your copy to turn on the uGFX features you want to use.
- * The values below are the defaults. You should delete anything
- * you are leaving as default.
+ * The values below are the defaults.
+ *
+ * Only remove the comments from lines where you want to change the
+ * default value. This allows definitions to be included from
+ * driver makefiles when required and provides the best future
+ * compatibility for your project.
*
* Please use spaces instead of tabs in this file.
*/
@@ -24,7 +28,7 @@
///////////////////////////////////////////////////////////////////////////
//#define GFX_USE_OS_CHIBIOS FALSE
//#define GFX_USE_OS_FREERTOS FALSE
- #define GFX_FREERTOS_USE_TRACE FALSE
+// #define GFX_FREERTOS_USE_TRACE FALSE
//#define GFX_USE_OS_WIN32 FALSE
//#define GFX_USE_OS_LINUX FALSE
//#define GFX_USE_OS_OSX FALSE
@@ -33,217 +37,221 @@
///////////////////////////////////////////////////////////////////////////
// GDISP //
///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GDISP FALSE
-
-#define GDISP_NEED_AUTOFLUSH FALSE
-#define GDISP_NEED_TIMERFLUSH FALSE
-#define GDISP_NEED_VALIDATION TRUE
-#define GDISP_NEED_CLIP TRUE
-#define GDISP_NEED_CIRCLE FALSE
-#define GDISP_NEED_ELLIPSE FALSE
-#define GDISP_NEED_ARC FALSE
-#define GDISP_NEED_CONVEX_POLYGON FALSE
-#define GDISP_NEED_SCROLL FALSE
-#define GDISP_NEED_PIXELREAD FALSE
-#define GDISP_NEED_CONTROL FALSE
-#define GDISP_NEED_QUERY FALSE
-#define GDISP_NEED_MULTITHREAD FALSE
-#define GDISP_NEED_STREAMING FALSE
-#define GDISP_NEED_TEXT FALSE
- #define GDISP_NEED_ANTIALIAS FALSE
- #define GDISP_NEED_UTF8 FALSE
- #define GDISP_NEED_TEXT_KERNING FALSE
- #define GDISP_INCLUDE_FONT_UI1 FALSE
- #define GDISP_INCLUDE_FONT_UI2 FALSE
- #define GDISP_INCLUDE_FONT_LARGENUMBERS FALSE
- #define GDISP_INCLUDE_FONT_DEJAVUSANS10 FALSE
- #define GDISP_INCLUDE_FONT_DEJAVUSANS12 FALSE
- #define GDISP_INCLUDE_FONT_DEJAVUSANS16 FALSE
- #define GDISP_INCLUDE_FONT_DEJAVUSANS24 FALSE
- #define GDISP_INCLUDE_FONT_DEJAVUSANS32 FALSE
- #define GDISP_INCLUDE_FONT_DEJAVUSANSBOLD12 FALSE
- #define GDISP_INCLUDE_FONT_FIXED_10X20 FALSE
- #define GDISP_INCLUDE_FONT_FIXED_7X14 FALSE
- #define GDISP_INCLUDE_FONT_FIXED_5X8 FALSE
- #define GDISP_INCLUDE_FONT_DEJAVUSANS12_AA FALSE
- #define GDISP_INCLUDE_FONT_DEJAVUSANS16_AA FALSE
- #define GDISP_INCLUDE_FONT_DEJAVUSANS24_AA FALSE
- #define GDISP_INCLUDE_FONT_DEJAVUSANS32_AA FALSE
- #define GDISP_INCLUDE_FONT_DEJAVUSANSBOLD12_AA FALSE
- #define GDISP_INCLUDE_USER_FONTS FALSE
-
-#define GDISP_NEED_IMAGE FALSE
- #define GDISP_NEED_IMAGE_NATIVE FALSE
- #define GDISP_NEED_IMAGE_GIF FALSE
- #define GDISP_NEED_IMAGE_BMP FALSE
- #define GDISP_NEED_IMAGE_BMP_1 FALSE
- #define GDISP_NEED_IMAGE_BMP_4 FALSE
- #define GDISP_NEED_IMAGE_BMP_4_RLE FALSE
- #define GDISP_NEED_IMAGE_BMP_8 FALSE
- #define GDISP_NEED_IMAGE_BMP_8_RLE FALSE
- #define GDISP_NEED_IMAGE_BMP_16 FALSE
- #define GDISP_NEED_IMAGE_BMP_24 FALSE
- #define GDISP_NEED_IMAGE_BMP_32 FALSE
- #define GDISP_NEED_IMAGE_JPG FALSE
- #define GDISP_NEED_IMAGE_PNG FALSE
- #define GDISP_NEED_IMAGE_ACCOUNTING FALSE
-
-#define GDISP_NEED_STARTUP_LOGO TRUE
-
-#define GDISP_DEFAULT_ORIENTATION GDISP_ROTATE_LANDSCAPE
-#define GDISP_LINEBUF_SIZE 128
-
-#define GDISP_TOTAL_DISPLAYS 1
- #if GDISP_TOTAL_DISPLAYS > 1
- #define GDISP_HARDWARE_STREAM_WRITE FALSE
- #define GDISP_HARDWARE_STREAM_READ FALSE
- #define GDISP_HARDWARE_STREAM_POS FALSE
- #define GDISP_HARDWARE_DRAWPIXEL FALSE
- #define GDISP_HARDWARE_CLEARS FALSE
- #define GDISP_HARDWARE_FILLS FALSE
- #define GDISP_HARDWARE_BITFILLS FALSE
- #define GDISP_HARDWARE_SCROLL FALSE
- #define GDISP_HARDWARE_PIXELREAD FALSE
- #define GDISP_HARDWARE_CONTROL FALSE
- #define GDISP_HARDWARE_QUERY FALSE
- #define GDISP_HARDWARE_CLIP FALSE
- #endif
-
-#define GDISP_TOTAL_CONTROLLERS 1
- #if GDISP_TOTAL_CONTROLLERS > 1
- #define GDISP_CONTROLLER_LIST GDISPVMT_Win32, GDISPVMT_Win32
- #define GDISP_CONTROLLER_DISPLAYS 1, 1
- #define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB888
- #endif
-
-#define GDISP_USE_GFXNET FALSE
- #define GDISP_GFXNET_PORT 13001
- #define GDISP_GFXNET_CUSTOM_LWIP_STARTUP FALSE
- #define GDISP_DONT_WAIT_FOR_NET_DISPLAY FALSE
- #define GDISP_GFXNET_UNSAFE_SOCKETS FALSE
+//#define GFX_USE_GDISP FALSE
+
+//#define GDISP_NEED_AUTOFLUSH FALSE
+//#define GDISP_NEED_TIMERFLUSH FALSE
+//#define GDISP_NEED_VALIDATION TRUE
+//#define GDISP_NEED_CLIP TRUE
+//#define GDISP_NEED_CIRCLE FALSE
+//#define GDISP_NEED_ELLIPSE FALSE
+//#define GDISP_NEED_ARC FALSE
+//#define GDISP_NEED_CONVEX_POLYGON FALSE
+//#define GDISP_NEED_SCROLL FALSE
+//#define GDISP_NEED_PIXELREAD FALSE
+//#define GDISP_NEED_CONTROL FALSE
+//#define GDISP_NEED_QUERY FALSE
+//#define GDISP_NEED_MULTITHREAD FALSE
+//#define GDISP_NEED_STREAMING FALSE
+//#define GDISP_NEED_TEXT FALSE
+// #define GDISP_NEED_ANTIALIAS FALSE
+// #define GDISP_NEED_UTF8 FALSE
+// #define GDISP_NEED_TEXT_KERNING FALSE
+// #define GDISP_INCLUDE_FONT_UI1 FALSE
+// #define GDISP_INCLUDE_FONT_UI2 FALSE // The smallest preferred font.
+// #define GDISP_INCLUDE_FONT_LARGENUMBERS FALSE
+// #define GDISP_INCLUDE_FONT_DEJAVUSANS10 FALSE
+// #define GDISP_INCLUDE_FONT_DEJAVUSANS12 FALSE
+// #define GDISP_INCLUDE_FONT_DEJAVUSANS16 FALSE
+// #define GDISP_INCLUDE_FONT_DEJAVUSANS24 FALSE
+// #define GDISP_INCLUDE_FONT_DEJAVUSANS32 FALSE
+// #define GDISP_INCLUDE_FONT_DEJAVUSANSBOLD12 FALSE
+// #define GDISP_INCLUDE_FONT_FIXED_10X20 FALSE
+// #define GDISP_INCLUDE_FONT_FIXED_7X14 FALSE
+// #define GDISP_INCLUDE_FONT_FIXED_5X8 FALSE
+// #define GDISP_INCLUDE_FONT_DEJAVUSANS12_AA FALSE
+// #define GDISP_INCLUDE_FONT_DEJAVUSANS16_AA FALSE
+// #define GDISP_INCLUDE_FONT_DEJAVUSANS24_AA FALSE
+// #define GDISP_INCLUDE_FONT_DEJAVUSANS32_AA FALSE
+// #define GDISP_INCLUDE_FONT_DEJAVUSANSBOLD12_AA FALSE
+// #define GDISP_INCLUDE_USER_FONTS FALSE
+
+//#define GDISP_NEED_IMAGE FALSE
+// #define GDISP_NEED_IMAGE_NATIVE FALSE
+// #define GDISP_NEED_IMAGE_GIF FALSE
+// #define GDISP_NEED_IMAGE_BMP FALSE
+// #define GDISP_NEED_IMAGE_BMP_1 FALSE
+// #define GDISP_NEED_IMAGE_BMP_4 FALSE
+// #define GDISP_NEED_IMAGE_BMP_4_RLE FALSE
+// #define GDISP_NEED_IMAGE_BMP_8 FALSE
+// #define GDISP_NEED_IMAGE_BMP_8_RLE FALSE
+// #define GDISP_NEED_IMAGE_BMP_16 FALSE
+// #define GDISP_NEED_IMAGE_BMP_24 FALSE
+// #define GDISP_NEED_IMAGE_BMP_32 FALSE
+// #define GDISP_NEED_IMAGE_JPG FALSE
+// #define GDISP_NEED_IMAGE_PNG FALSE
+// #define GDISP_NEED_IMAGE_ACCOUNTING FALSE
+
+//#define GDISP_NEED_STARTUP_LOGO TRUE
+
+//#define GDISP_DEFAULT_ORIENTATION GDISP_ROTATE_LANDSCAPE // If not defined the native hardware orientation is used.
+//#define GDISP_LINEBUF_SIZE 128
+
+//#define GDISP_TOTAL_DISPLAYS 1
+// #if GDISP_TOTAL_DISPLAYS > 1
+// // For code and speed optimization define as TRUE or FALSE if all displays have the same capability
+// #define GDISP_HARDWARE_STREAM_WRITE FALSE
+// #define GDISP_HARDWARE_STREAM_READ FALSE
+// #define GDISP_HARDWARE_STREAM_POS FALSE
+// #define GDISP_HARDWARE_DRAWPIXEL FALSE
+// #define GDISP_HARDWARE_CLEARS FALSE
+// #define GDISP_HARDWARE_FILLS FALSE
+// #define GDISP_HARDWARE_BITFILLS FALSE
+// #define GDISP_HARDWARE_SCROLL FALSE
+// #define GDISP_HARDWARE_PIXELREAD FALSE
+// #define GDISP_HARDWARE_CONTROL FALSE
+// #define GDISP_HARDWARE_QUERY FALSE
+// #define GDISP_HARDWARE_CLIP FALSE
+// #endif
+
+//#define GDISP_TOTAL_CONTROLLERS 1
+// #if GDISP_TOTAL_CONTROLLERS > 1
+// #define GDISP_CONTROLLER_LIST GDISPVMT_Win32, GDISPVMT_Win32
+// #define GDISP_CONTROLLER_DISPLAYS 1, 1
+// #define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB888
+// #endif
+
+//#define GDISP_USE_GFXNET FALSE
+// #define GDISP_GFXNET_PORT 13001
+// #define GDISP_GFXNET_CUSTOM_LWIP_STARTUP FALSE
+// #define GDISP_DONT_WAIT_FOR_NET_DISPLAY FALSE
+// #define GDISP_GFXNET_UNSAFE_SOCKETS FALSE
///////////////////////////////////////////////////////////////////////////
// GWIN //
///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GWIN FALSE
-
-#define GWIN_NEED_WINDOWMANAGER FALSE
-
-#define GWIN_NEED_CONSOLE FALSE
- #define GWIN_CONSOLE_USE_HISTORY FALSE
- #define GWIN_CONSOLE_HISTORY_AVERAGING FALSE
- #define GWIN_CONSOLE_HISTORY_ATCREATE FALSE
- #define GWIN_CONSOLE_ESCSEQ FALSE
- #define GWIN_CONSOLE_USE_BASESTREAM FALSE
- #define GWIN_CONSOLE_USE_FLOAT FALSE
-#define GWIN_NEED_GRAPH FALSE
-
-#define GWIN_NEED_WIDGET FALSE
- #define GWIN_NEED_LABEL FALSE
- #define GWIN_LABEL_ATTRIBUTE FALSE
- #define GWIN_NEED_BUTTON FALSE
- #define GWIN_BUTTON_LAZY_RELEASE FALSE
- #define GWIN_NEED_SLIDER FALSE
- #define GWIN_NEED_CHECKBOX FALSE
- #define GWIN_NEED_IMAGE FALSE
- #define GWIN_NEED_IMAGE_ANIMATION FALSE
- #define GWIN_NEED_RADIO FALSE
- #define GWIN_NEED_LIST FALSE
- #define GWIN_NEED_LIST_IMAGES FALSE
- #define GWIN_NEED_PROGRESSBAR FALSE
- #define GWIN_PROGRESSBAR_AUTO FALSE
- #define GWIN_FLAT_STYLING FALSE
+//#define GFX_USE_GWIN FALSE
+
+//#define GWIN_NEED_WINDOWMANAGER FALSE
+
+//#define GWIN_NEED_CONSOLE FALSE
+// #define GWIN_CONSOLE_USE_HISTORY FALSE
+// #define GWIN_CONSOLE_HISTORY_AVERAGING FALSE
+// #define GWIN_CONSOLE_HISTORY_ATCREATE FALSE
+// #define GWIN_CONSOLE_ESCSEQ FALSE
+// #define GWIN_CONSOLE_USE_BASESTREAM FALSE
+// #define GWIN_CONSOLE_USE_FLOAT FALSE
+//#define GWIN_NEED_GRAPH FALSE
+
+//#define GWIN_NEED_WIDGET FALSE
+// #define GWIN_NEED_LABEL FALSE
+// #define GWIN_LABEL_ATTRIBUTE FALSE
+// #define GWIN_NEED_BUTTON FALSE
+// #define GWIN_BUTTON_LAZY_RELEASE FALSE
+// #define GWIN_NEED_SLIDER FALSE
+// #define GWIN_NEED_CHECKBOX FALSE
+// #define GWIN_NEED_IMAGE FALSE
+// #define GWIN_NEED_IMAGE_ANIMATION FALSE
+// #define GWIN_NEED_RADIO FALSE
+// #define GWIN_NEED_LIST FALSE
+// #define GWIN_NEED_LIST_IMAGES FALSE
+// #define GWIN_NEED_PROGRESSBAR FALSE
+// #define GWIN_PROGRESSBAR_AUTO FALSE
+// #define GWIN_FLAT_STYLING FALSE
+
+//#define GWIN_NEED_CONTAINERS FALSE
+// #define GWIN_NEED_CONTAINER FALSE
+// #define GWIN_NEED_FRAME FALSE
///////////////////////////////////////////////////////////////////////////
// GEVENT //
///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GEVENT FALSE
+//#define GFX_USE_GEVENT FALSE
-#define GEVENT_ASSERT_NO_RESOURCE FALSE
-#define GEVENT_MAXIMUM_SIZE 32
-#define GEVENT_MAX_SOURCE_LISTENERS 32
+//#define GEVENT_ASSERT_NO_RESOURCE FALSE
+//#define GEVENT_MAXIMUM_SIZE 32
+//#define GEVENT_MAX_SOURCE_LISTENERS 32
///////////////////////////////////////////////////////////////////////////
// GTIMER //
///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GTIMER FALSE
+//#define GFX_USE_GTIMER FALSE
-#define GTIMER_THREAD_PRIORITY HIGH_PRIORITY
-#define GTIMER_THREAD_WORKAREA_SIZE 2048
+//#define GTIMER_THREAD_PRIORITY HIGH_PRIORITY
+//#define GTIMER_THREAD_WORKAREA_SIZE 2048
///////////////////////////////////////////////////////////////////////////
// GQUEUE //
///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GQUEUE FALSE
+//#define GFX_USE_GQUEUE FALSE
-#define GQUEUE_NEED_ASYNC FALSE
-#define GQUEUE_NEED_GSYNC FALSE
-#define GQUEUE_NEED_FSYNC FALSE
-#define GQUEUE_NEED_BUFFERS FALSE
+//#define GQUEUE_NEED_ASYNC FALSE
+//#define GQUEUE_NEED_GSYNC FALSE
+//#define GQUEUE_NEED_FSYNC FALSE
+//#define GQUEUE_NEED_BUFFERS FALSE
///////////////////////////////////////////////////////////////////////////
// GINPUT //
///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GINPUT FALSE
+//#define GFX_USE_GINPUT FALSE
-#define GINPUT_NEED_MOUSE FALSE
-#define GINPUT_NEED_KEYBOARD FALSE
-#define GINPUT_NEED_TOGGLE FALSE
-#define GINPUT_NEED_DIAL FALSE
+//#define GINPUT_NEED_MOUSE FALSE
+//#define GINPUT_NEED_KEYBOARD FALSE
+//#define GINPUT_NEED_TOGGLE FALSE
+//#define GINPUT_NEED_DIAL FALSE
///////////////////////////////////////////////////////////////////////////
// GFILE //
///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GFILE FALSE
+//#define GFX_USE_GFILE FALSE
-#define GFILE_NEED_PRINTG FALSE
-#define GFILE_NEED_SCANG FALSE
-#define GFILE_NEED_STRINGS FALSE
-#define GFILE_NEED_STDIO FALSE
- #define GFILE_ALLOW_FLOATS FALSE
- #define GFILE_ALLOW_DEVICESPECIFIC FALSE
- #define GFILE_MAX_GFILES 3
+//#define GFILE_NEED_PRINTG FALSE
+//#define GFILE_NEED_SCANG FALSE
+//#define GFILE_NEED_STRINGS FALSE
+//#define GFILE_NEED_STDIO FALSE
+// #define GFILE_ALLOW_FLOATS FALSE
+// #define GFILE_ALLOW_DEVICESPECIFIC FALSE
+// #define GFILE_MAX_GFILES 3
-#define GFILE_NEED_MEMFS FALSE
-#define GFILE_NEED_ROMFS FALSE
-#define GFILE_NEED_RAMFS FALSE
-#define GFILE_NEED_FATFS FALSE
-#define GFILE_NEED_NATIVEFS FALSE
-#define GFILE_NEED_CHBIOSFS FALSE
+//#define GFILE_NEED_MEMFS FALSE
+//#define GFILE_NEED_ROMFS FALSE
+//#define GFILE_NEED_RAMFS FALSE
+//#define GFILE_NEED_FATFS FALSE
+//#define GFILE_NEED_NATIVEFS FALSE
+//#define GFILE_NEED_CHBIOSFS FALSE
///////////////////////////////////////////////////////////////////////////
// GADC //
///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GADC FALSE
+//#define GFX_USE_GADC FALSE
-#define GADC_MAX_LOWSPEED_DEVICES 4
+//#define GADC_MAX_LOWSPEED_DEVICES 4
///////////////////////////////////////////////////////////////////////////
// GAUDIO //
///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GAUDIO FALSE
- #define GAUDIO_NEED_PLAY FALSE
- #define GAUDIO_NEED_RECORD FALSE
+//#define GFX_USE_GAUDIO FALSE
+// #define GAUDIO_NEED_PLAY FALSE
+// #define GAUDIO_NEED_RECORD FALSE
///////////////////////////////////////////////////////////////////////////
// GMISC //
///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GMISC FALSE
-
-#define GMISC_NEED_ARRAYOPS FALSE
-#define GMISC_NEED_FASTTRIG FALSE
-#define GMISC_NEED_FIXEDTRIG FALSE
-#define GMISC_NEED_INVSQRT FALSE
- #define GMISC_INVSQRT_MIXED_ENDIAN FALSE
- #define GMISC_INVSQRT_REAL_SLOW FALSE
-
+//#define GFX_USE_GMISC FALSE
+
+//#define GMISC_NEED_ARRAYOPS FALSE
+//#define GMISC_NEED_FASTTRIG FALSE
+//#define GMISC_NEED_FIXEDTRIG FALSE
+//#define GMISC_NEED_INVSQRT FALSE
+// #define GMISC_INVSQRT_MIXED_ENDIAN FALSE
+// #define GMISC_INVSQRT_REAL_SLOW FALSE
#endif /* _GFXCONF_H */
diff --git a/src/gdisp/gdisp.c b/src/gdisp/gdisp.c
index 9f3ff11b..e9ede8ab 100644
--- a/src/gdisp/gdisp.c
+++ b/src/gdisp/gdisp.c
@@ -3020,13 +3020,23 @@ color_t gdispBlendColor(color_t fg, color_t bg, uint8_t alpha)
g += GREEN_OF(bg) * bg_ratio;
b += BLUE_OF(bg) * bg_ratio;
- r /= 256;
- g /= 256;
- b /= 256;
+ r >>= 8;
+ g >>= 8;
+ b >>= 8;
return RGB2COLOR(r, g, b);
}
+color_t gdispContrastColor(color_t color) {
+ uint16_t r, g, b;
+
+ r = RED_OF(color) > 128 ? 0 : 255;
+ g = GREEN_OF(color) > 128 ? 0 : 255;
+ b = BLUE_OF(color) > 128 ? 0 : 255;
+
+ return RGB2COLOR(r, g, b);
+}
+
#if (!defined(gdispPackPixels) && !defined(GDISP_PIXELFORMAT_CUSTOM))
void gdispPackPixels(pixel_t *buf, coord_t cx, coord_t x, coord_t y, color_t color) {
/* No mutex required as we only read static data */
diff --git a/src/gdisp/sys_defs.h b/src/gdisp/sys_defs.h
index a40d6e80..72fdc621 100644
--- a/src/gdisp/sys_defs.h
+++ b/src/gdisp/sys_defs.h
@@ -211,6 +211,16 @@ extern "C" {
color_t gdispBlendColor(color_t fg, color_t bg, uint8_t alpha);
/**
+ * @brief Find a contrasting color
+ * @return The contrasting color
+ *
+ * @param[in] color The color to contrast
+ *
+ * @api
+ */
+color_t gdispContrastColor(color_t color);
+
+/**
* @brief Get the specified display
* @return The pointer to the display or NULL if the display doesn't exist
* @note The GDISP variable contains the display used by the gdispXxxx routines
diff --git a/src/gdisp/sys_options.h b/src/gdisp/sys_options.h
index a38e4c6f..466bbb98 100644
--- a/src/gdisp/sys_options.h
+++ b/src/gdisp/sys_options.h
@@ -26,7 +26,7 @@
* @details Defaults to TRUE
*/
#ifndef GDISP_NEED_STARTUP_LOGO
- #define GDISP_NEED_STARTUP_LOGO TRUE
+ #define GDISP_NEED_STARTUP_LOGO TRUE
#endif
/**
* @brief Should drawing operations be automatically flushed.
diff --git a/src/gfile/gfile.c b/src/gfile/gfile.c
index 8a3abf9c..c711cfef 100644
--- a/src/gfile/gfile.c
+++ b/src/gfile/gfile.c
@@ -595,7 +595,7 @@ bool_t gfileEOF(GFILE *f) {
if (c >= '0' && c <= '9')
c -= '0';
else if (c == '*')
- c = va_arg(ap, int);
+ c = va_arg(arg, int);
else
break;
width = width * 10 + c;
@@ -606,7 +606,7 @@ bool_t gfileEOF(GFILE *f) {
if (c >= '0' && c <= '9')
c -= '0';
else if (c == '*')
- c = va_arg(ap, int);
+ c = va_arg(arg, int);
else
break;
precision = precision * 10 + c;
@@ -627,11 +627,11 @@ bool_t gfileEOF(GFILE *f) {
return ret;
case 'c':
filler = ' ';
- *p++ = va_arg(ap, int);
+ *p++ = va_arg(arg, int);
break;
case 's':
filler = ' ';
- if ((s = va_arg(ap, char *)) == 0)
+ if ((s = va_arg(arg, char *)) == 0)
s = "(null)";
if (precision == 0)
precision = 32767;
@@ -640,9 +640,9 @@ bool_t gfileEOF(GFILE *f) {
case 'D':
case 'd':
if (is_long)
- l = va_arg(ap, long);
+ l = va_arg(arg, long);
else
- l = va_arg(ap, int);
+ l = va_arg(arg, int);
if (l < 0) {
*p++ = '-';
l = -l;
@@ -651,7 +651,7 @@ bool_t gfileEOF(GFILE *f) {
break;
#if GFILE_ALLOW_FLOATS
case 'f':
- f = (float) va_arg(ap, double);
+ f = (float) va_arg(arg, double);
if (f < 0) {
*p++ = '-';
f = -f;
@@ -676,9 +676,9 @@ bool_t gfileEOF(GFILE *f) {
c = 8;
unsigned_common:
if (is_long)
- l = va_arg(ap, long);
+ l = va_arg(arg, long);
else
- l = va_arg(ap, int);
+ l = va_arg(arg, int);
p = ltoa_wd(p, l, c, 0);
break;
default:
diff --git a/src/gfile/sys_options.h b/src/gfile/sys_options.h
index 6e36e6b7..564cc2d7 100644
--- a/src/gfile/sys_options.h
+++ b/src/gfile/sys_options.h
@@ -133,7 +133,7 @@
* @brief Add floating point support to printg/scang etc.
*/
#ifndef GFILE_ALLOW_FLOATS
- #define GFILE_ALLOW_FLOATS
+ #define GFILE_ALLOW_FLOATS FALSE
#endif
/**
* @brief Can the device be specified as part of the file name.
diff --git a/src/gwin/button.c b/src/gwin/button.c
index f34e4ba3..da68d267 100644
--- a/src/gwin/button.c
+++ b/src/gwin/button.c
@@ -55,14 +55,14 @@ static void SendButtonEvent(GWidgetObject *gw) {
static void MouseDown(GWidgetObject *gw, coord_t x, coord_t y) {
(void) x; (void) y;
gw->g.flags |= GBUTTON_FLG_PRESSED;
- _gwidgetRedraw((GHandle)gw);
+ _gwidgetUpdate((GHandle)gw);
}
// 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);
+ _gwidgetUpdate((GHandle)gw);
#if !GWIN_BUTTON_LAZY_RELEASE
// If the mouse up was not over the button then cancel the event
@@ -79,14 +79,14 @@ static void SendButtonEvent(GWidgetObject *gw) {
static void ToggleOff(GWidgetObject *gw, uint16_t role) {
(void) role;
gw->g.flags &= ~GBUTTON_FLG_PRESSED;
- _gwidgetRedraw((GHandle)gw);
+ _gwidgetUpdate((GHandle)gw);
}
// A toggle on has occurred
static void ToggleOn(GWidgetObject *gw, uint16_t role) {
(void) role;
gw->g.flags |= GBUTTON_FLG_PRESSED;
- _gwidgetRedraw((GHandle)gw);
+ _gwidgetUpdate((GHandle)gw);
// Trigger the event on button down (different than for mouse/touch)
SendButtonEvent(gw);
}
@@ -161,7 +161,7 @@ bool_t gwinButtonIsPressed(GHandle gh) {
*----------------------------------------------------------*/
static const GColorSet *getDrawColors(GWidgetObject *gw) {
- if (!(gw->g.flags & GWIN_FLG_ENABLED)) return &gw->pstyle->disabled;
+ if (!(gw->g.flags & GWIN_FLG_SYSENABLED)) return &gw->pstyle->disabled;
if ((gw->g.flags & GBUTTON_FLG_PRESSED)) return &gw->pstyle->pressed;
return &gw->pstyle->enabled;
}
@@ -336,7 +336,7 @@ static const GColorSet *getDrawColors(GWidgetObject *gw) {
if (gw->g.vmt != (gwinVMT *)&buttonVMT) return;
pcol = getDrawColors(gw);
- if (!(gw->g.flags & GWIN_FLG_ENABLED)) {
+ if (!(gw->g.flags & GWIN_FLG_SYSENABLED)) {
sy = 2 * gw->g.height;
} else if ((gw->g.flags & GBUTTON_FLG_PRESSED)) {
sy = gw->g.height;
diff --git a/src/gwin/checkbox.c b/src/gwin/checkbox.c
index 8cdd51d9..11d76cb2 100644
--- a/src/gwin/checkbox.c
+++ b/src/gwin/checkbox.c
@@ -48,7 +48,7 @@ static void SendCheckboxEvent(GWidgetObject *gw) {
static void MouseDown(GWidgetObject *gw, coord_t x, coord_t y) {
(void) x; (void) y;
gw->g.flags ^= GCHECKBOX_FLG_CHECKED;
- _gwidgetRedraw((GHandle)gw);
+ _gwidgetUpdate((GHandle)gw);
SendCheckboxEvent(gw);
}
#endif
@@ -57,7 +57,7 @@ static void SendCheckboxEvent(GWidgetObject *gw) {
static void ToggleOn(GWidgetObject *gw, uint16_t role) {
(void) role;
gw->g.flags ^= GCHECKBOX_FLG_CHECKED;
- _gwidgetRedraw((GHandle)gw);
+ _gwidgetUpdate((GHandle)gw);
SendCheckboxEvent(gw);
}
@@ -130,7 +130,7 @@ void gwinCheckboxCheck(GHandle gh, bool_t isChecked) {
if (!(gh->flags & GCHECKBOX_FLG_CHECKED)) return;
gh->flags &= ~GCHECKBOX_FLG_CHECKED;
}
- _gwidgetRedraw(gh);
+ _gwidgetUpdate(gh);
SendCheckboxEvent((GWidgetObject *)gh);
}
@@ -146,7 +146,7 @@ bool_t gwinCheckboxIsChecked(GHandle gh) {
*----------------------------------------------------------*/
static const GColorSet *getDrawColors(GWidgetObject *gw) {
- if (!(gw->g.flags & GWIN_FLG_ENABLED)) return &gw->pstyle->disabled;
+ if (!(gw->g.flags & GWIN_FLG_SYSENABLED)) return &gw->pstyle->disabled;
if ((gw->g.flags & GCHECKBOX_FLG_CHECKED)) return &gw->pstyle->pressed;
return &gw->pstyle->enabled;
}
diff --git a/src/gwin/class_gwin.h b/src/gwin/class_gwin.h
index 50dd480e..2c9b6a68 100644
--- a/src/gwin/class_gwin.h
+++ b/src/gwin/class_gwin.h
@@ -27,16 +27,20 @@
* @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_ENABLED 0x0010 // @< The window is enabled
-#define GWIN_FLG_WIDGET 0x0020 // @< This is a widget
-#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
+#define GWIN_FIRST_CONTROL_FLAG 0x00000001 // @< 8 bits free for the control to use
+#define GWIN_FLG_VISIBLE 0x00000100 // @< The window is "visible"
+#define GWIN_FLG_SYSVISIBLE 0x00000200 // @< The window is visible after parents are tested
+#define GWIN_FLG_ENABLED 0x00000400 // @< The window is "enabled"
+#define GWIN_FLG_SYSENABLED 0x00000800 // @< The window is enabled after parents are tested
+#define GWIN_FLG_DYNAMIC 0x00001000 // @< The GWIN structure is allocated
+#define GWIN_FLG_ALLOCTXT 0x00002000 // @< The text/label is allocated
+#define GWIN_FLG_MOUSECAPTURE 0x00004000 // @< The window has captured the mouse
+#define GWIN_FLG_SUPERMASK 0x000F0000 // @< The bit mask to leave just the window superclass type
+#define GWIN_FLG_WIDGET 0x00010000 // @< This is a widget
+#define GWIN_FLG_CONTAINER 0x00020000 // @< This is a container
+#define GWIN_FLG_MINIMIZED 0x00100000 // @< The window is minimized
+#define GWIN_FLG_MAXIMIZED 0x00200000 // @< The window is maximized
+#define GWIN_FIRST_WM_FLAG 0x01000000 // @< 8 bits free for the window manager to use
/* @} */
/**
@@ -104,6 +108,29 @@ typedef struct gwinVMT {
/* @} */
#endif
+#if GWIN_NEED_CONTAINERS || defined(__DOXYGEN__)
+
+ /**
+ * @brief The Virtual Method Table for a container
+ * @note A container must have a destroy function. Either use @p _gcontainerDestroy() or use your own function
+ * which internally calls @p _gcontainerDestroy().
+ * @note A container must have a gwin redraw function. Use @p _containerRedraw().
+ * @note If toggleroles != 0, ToggleAssign(), ToggleGet() and one or both of ToggleOff() and ToggleOn() must be specified.
+ * @note If dialroles != 0, DialAssign(), DialGet() and DialMove() must be specified.
+ * @{
+ */
+ typedef struct gcontainerVMT {
+ gwidgetVMT gw;
+ coord_t (*LeftBorder) (GHandle gh); // @< The size of the left border (mandatory)
+ coord_t (*TopBorder) (GHandle gh); // @< The size of the top border (mandatory)
+ coord_t (*RightBorder) (GHandle gh); // @< The size of the right border (mandatory)
+ coord_t (*BottomBorder) (GHandle gh); // @< The size of the bottom border (mandatory)
+ void (*NotifyAdd) (GHandle gh, GHandle ghChild); // @< Notification that a child has been added (optional)
+ void (*NotifyDelete) (GHandle gh, GHandle ghChild); // @< Notification that a child has been deleted (optional)
+ } gcontainerVMT;
+ /* @} */
+#endif
+
// These flags are needed whether or not we are running a window manager.
/**
* @brief Flags for redrawing after a visibility change
@@ -111,16 +138,11 @@ typedef struct gwinVMT {
*/
#define GWIN_WMFLG_PRESERVE 0x0001 // @< Preserve whatever existing contents possible if a window can't redraw
#define GWIN_WMFLG_NOBGCLEAR 0x0002 // @< Don't clear the area if the window is not visible
-#define GWIN_WMFLG_NOZORDER 0x0004 // @< Don't redraw higher z-order windows that overlap
+#define GWIN_WMFLG_KEEPCLIP 0x0004 // @< Don't modify the preset clipping area
+#define GWIN_WMFLG_NOZORDER 0x0008 // @< Don't redraw higher z-order windows that overlap
/* @} */
#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;
@@ -136,18 +158,14 @@ typedef struct gwinVMT {
bool_t (*Add) (GHandle gh, const GWindowInit *pInit); // @< A window has been added
void (*Delete) (GHandle gh); // @< A window has been deleted
void (*Redraw) (GHandle gh, int visflags); // @< A window needs to be redraw (or undrawn)
- 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 (*Size) (GHandle gh, coord_t w, coord_t h); // @< A window wants to be resized
+ void (*Move) (GHandle gh, coord_t x, coord_t y); // @< A window wants to be moved
void (*Raise) (GHandle gh); // @< A window wants to be on top
void (*MinMax) (GHandle gh, GWindowMinMax minmax); // @< A window wants to be minimized/maximised
} gwmVMT;
/* @} */
/**
- * @brief The list of all windows in the system
- */
- extern gfxQueueASync _GWINList;
-
- /**
* @brief The current window manager
*/
extern GWindowManager * _GWINwm;
@@ -197,13 +215,93 @@ GHandle _gwindowCreate(GDisplay *g, GWindowObject *pgw, const GWindowInit *pInit
void _gwidgetDestroy(GHandle gh);
/**
- * @brief Redraw the Widget object
+ * @brief Redraw the Widget object (VMT method only)
*
* @param[in] gh The widget to redraw
*
+ * @note Do not use this routine to update a widget after a status change.
+ * Use @p _gwidgetUpdate() instead. The difference is that this routine
+ * does not set the clip region. This routine should only be used in the
+ * VMT.
+ *
* @notapi
*/
void _gwidgetRedraw(GHandle gh);
+
+ /**
+ * @brief Redraw the Widget object after a widget status change.
+ *
+ * @param[in] gh The widget to redraw
+ *
+ * @note Use this routine to update a widget after a status change.
+ *
+ * @notapi
+ */
+ void _gwidgetUpdate(GHandle gh);
+#endif
+
+#if GWIN_NEED_CONTAINERS || defined(__DOXYGEN__)
+ /**
+ * @brief Initialise (and allocate if necessary) the base Container object
+ *
+ * @param[in] g The GDisplay to display this window on
+ * @param[in] pgw The GContainerObject structure. If NULL one is allocated from the heap
+ * @param[in] pInit The user initialization parameters
+ * @param[in] vmt The virtual method table for the Container object
+ *
+ * @return The GHandle of the created widget
+ *
+ * @notapi
+ */
+ GHandle _gcontainerCreate(GDisplay *g, GContainerObject *pgw, const GWidgetInit *pInit, const gcontainerVMT *vmt);
+
+ /**
+ * @brief Destroy the Container object
+ *
+ * @param[in] gh The container to destroy
+ *
+ * @notapi
+ */
+ void _gcontainerDestroy(GHandle gh);
+
+ /**
+ * @brief Redraw the Container object (VMT method only)
+ *
+ * @param[in] gh The container to redraw
+ *
+ * @note Do not use this routine to update a container after a status change.
+ * Use @p _gcontainerUpdate() instead. The difference is that this routine
+ * does not set the clip region. This routine should only be used in the
+ * VMT.
+ *
+ * @notapi
+ */
+ void _gcontainerRedraw(GHandle gh);
+
+ /**
+ * @brief Redraw the Container object after a container status change.
+ *
+ * @param[in] gh The container to redraw
+ *
+ * @note Use this routine to update a container after a status change.
+ *
+ * @notapi
+ */
+ void _gcontainerUpdate(GHandle gh);
+
+ /**
+ * @brief Apply the specified action to a window and its children.
+ * @note The action is applied to the parent first and then its children.
+ * @note This routine is built to keep stack usage from recursing to a minimum.
+ *
+ * @param[in] gh The window to recurse through
+ * @param[in] fn The function to apply. If it returns TRUE any children it has should also have the function applied
+ *
+ * @notapi
+ */
+ void _gwinRecurse(GHandle gh, bool_t (*fn)(GHandle gh));
+#else
+ #define _gwinRecurse(gh, fn) fn(gh)
#endif
#ifdef __cplusplus
diff --git a/src/gwin/frame.c b/src/gwin/frame.c
new file mode 100644
index 00000000..dad807ca
--- /dev/null
+++ b/src/gwin/frame.c
@@ -0,0 +1,233 @@
+/*
+ * This file is subject to the terms of the GFX License. If a copy of
+ * the license was not distributed with this file, you can obtain one at:
+ *
+ * http://ugfx.org/license.html
+ */
+
+/**
+ * @file src/gwin/frame.c
+ * @brief GWIN sub-system frame code.
+ *
+ * @defgroup Frame Frame
+ * @ingroup GWIN
+ *
+ * @{
+ */
+
+#include "gfx.h"
+
+#if GFX_USE_GWIN && GWIN_NEED_FRAME
+
+#include "src/gwin/class_gwin.h"
+
+#if GWIN_FRAME_BORDER != GWIN_FIRST_CONTROL_FLAG
+ #error "GWIN Frame: - Flag definitions don't match"
+#endif
+
+/* Some values for the default render */
+#define BORDER_X 5
+#define BORDER_Y 30
+#define BUTTON_X 20
+#define BUTTON_Y 20
+
+/* Some useful macros for data type conversions */
+#define gh2obj ((GFrameObject *)gh)
+
+/* Forware declarations */
+static void gwinFrameDraw_Std(GWidgetObject *gw, void *param);
+static void _callbackBtn(void *param, GEvent *pe);
+
+static coord_t BorderSizeLRB(GHandle gh) { return (gh->flags & GWIN_FRAME_BORDER) ? BORDER_X : 0; }
+static coord_t BorderSizeT(GHandle gh) { return (gh->flags & GWIN_FRAME_BORDER) ? BORDER_Y : 0; }
+
+static void _frameDestroy(GHandle gh) {
+ /* Deregister the button callback */
+ geventRegisterCallback(&gh2obj->gl, NULL, NULL);
+ geventDetachSource(&gh2obj->gl, NULL);
+
+ /* call the gcontainer standard destroy routine */
+ _gcontainerDestroy(gh);
+}
+
+#if 0 && GINPUT_NEED_MOUSE
+ static void _mouseDown(GWidgetObject *gw, coord_t x, coord_t y) {
+
+ }
+
+ static void _mouseUp(GWidgetObject *gw, coord_t x, coord_t y) {
+
+ }
+
+ static void _mouseMove(GWidgetObject *gw, coord_t x, coord_t y) {
+
+ }
+#endif
+
+static const gcontainerVMT frameVMT = {
+ {
+ {
+ "Frame", // The classname
+ sizeof(GFrameObject), // The object size
+ _frameDestroy, // The destroy routie
+ _gcontainerRedraw, // The redraw routine
+ 0, // The after-clear routine
+ },
+ gwinFrameDraw_Std, // The default drawing routine
+ #if GINPUT_NEED_MOUSE
+ {
+ 0,//_mouseDown, // Process mouse down event
+ 0,//_mouseUp, // Process mouse up events
+ 0,//_mouseMove, // Process mouse move events
+ },
+ #endif
+ #if GINPUT_NEED_TOGGLE
+ {
+ 0, // 1 toggle role
+ 0, // Assign Toggles
+ 0, // Get Toggles
+ 0, // Process toggle off events
+ 0, // Process toggle on events
+ },
+ #endif
+ #if GINPUT_NEED_DIAL
+ {
+ 0, // 1 dial roles
+ 0, // Assign Dials
+ 0, // Get Dials
+ 0, // Process dial move events
+ },
+ #endif
+ },
+ BorderSizeLRB, // The size of the left border (mandatory)
+ BorderSizeT, // The size of the top border (mandatory)
+ BorderSizeLRB, // The size of the right border (mandatory)
+ BorderSizeLRB, // The size of the bottom border (mandatory)
+ 0, // A child has been added (optional)
+ 0, // A child has been deleted (optional)
+};
+
+GHandle gwinGFrameCreate(GDisplay *g, GFrameObject *fo, GWidgetInit *pInit, uint32_t flags) {
+ if (!(fo = (GFrameObject *)_gcontainerCreate(g, &fo->gc, pInit, &frameVMT)))
+ return 0;
+
+ fo->btnClose = 0;
+ fo->btnMin = 0;
+ fo->btnMax = 0;
+
+ /* Buttons require a border */
+ if ((flags & (GWIN_FRAME_CLOSE_BTN|GWIN_FRAME_MINMAX_BTN)))
+ flags |= GWIN_FRAME_BORDER;
+
+ /* create and initialize the listener if any button is present. */
+ if ((flags & (GWIN_FRAME_CLOSE_BTN|GWIN_FRAME_MINMAX_BTN))) {
+ geventListenerInit(&fo->gl);
+ gwinAttachListener(&fo->gl);
+ geventRegisterCallback(&fo->gl, _callbackBtn, (GHandle)fo);
+ }
+
+ /* create close button if necessary */
+ if ((flags & GWIN_FRAME_CLOSE_BTN)) {
+ GWidgetInit wi;
+
+ gwinWidgetClearInit(&wi);
+ wi.g.show = TRUE;
+ wi.g.parent = &fo->gc.g;
+
+ wi.g.x = fo->gc.g.width - BORDER_X - BUTTON_X;
+ wi.g.y = (BORDER_Y - BUTTON_Y) / 2;
+ wi.g.width = BUTTON_X;
+ wi.g.height = BUTTON_Y;
+ wi.text = "X";
+ fo->btnClose = gwinGButtonCreate(g, 0, &wi);
+ }
+
+ /* create minimize and maximize buttons if necessary */
+ if ((flags & GWIN_FRAME_MINMAX_BTN)) {
+ GWidgetInit wi;
+
+ gwinWidgetClearInit(&wi);
+ wi.g.show = TRUE;
+ wi.g.parent = &fo->gc.g;
+
+ wi.g.x = (flags & GWIN_FRAME_CLOSE_BTN) ? fo->gc.g.width - 2*BORDER_X - 2*BUTTON_X : fo->gc.g.width - BORDER_X - BUTTON_X;
+ wi.g.y = (BORDER_Y - BUTTON_Y) / 2;
+ wi.g.width = BUTTON_X;
+ wi.g.height = BUTTON_Y;
+ wi.text = "O";
+ fo->btnMin = gwinGButtonCreate(g, 0, &wi);
+
+ wi.g.x = (flags & GWIN_FRAME_CLOSE_BTN) ? fo->gc.g.width - 3*BORDER_X - 3*BUTTON_X : fo->gc.g.width - BORDER_X - BUTTON_X;
+ wi.g.y = (BORDER_Y - BUTTON_Y) / 2;
+ wi.g.width = BUTTON_X;
+ wi.g.height = BUTTON_Y;
+ wi.text = "_";
+ fo->btnMax = gwinGButtonCreate(g, 0, &wi);
+ }
+
+ /* Apply flags. We apply these here so the controls above are outside the child area */
+ fo->gc.g.flags |= flags;
+
+ gwinSetVisible(&fo->gc.g, pInit->g.show);
+
+ return &fo->gc.g;
+}
+
+/* Process a button event */
+static void _callbackBtn(void *param, GEvent *pe) {
+ switch (pe->type) {
+ case GEVENT_GWIN_BUTTON:
+ if (((GEventGWinButton *)pe)->button == ((GFrameObject*)(GHandle)param)->btnClose)
+ gwinDestroy((GHandle)param);
+
+ else if (((GEventGWinButton *)pe)->button == ((GFrameObject*)(GHandle)param)->btnMin) {
+ ;/* ToDo */
+
+ } else if (((GEventGWinButton *)pe)->button == ((GFrameObject*)(GHandle)param)->btnMax) {
+ ;/* ToDo */
+ }
+
+ break;
+
+ default:
+ break;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Default render routines //
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+static const GColorSet* _getDrawColors(GWidgetObject *gw) {
+ if (!(gw->g.flags & GWIN_FLG_SYSENABLED))
+ return &gw->pstyle->disabled;
+ //if ((gw->g.flags & GBUTTON_FLG_PRESSED))
+ // return &gw->pstyle->pressed;
+
+ return &gw->pstyle->enabled;
+}
+
+static void gwinFrameDraw_Std(GWidgetObject *gw, void *param) {
+ const GColorSet *pcol;
+ (void)param;
+
+ if (gw->g.vmt != (gwinVMT *)&frameVMT)
+ return;
+
+ pcol = _getDrawColors(gw);
+
+ // Render the actual frame (with border, if any)
+ if (gw->g.flags & GWIN_FRAME_BORDER) {
+ gdispGFillArea(gw->g.display, gw->g.x + BORDER_X, gw->g.y + BORDER_Y, gw->g.width - 2*BORDER_X, gw->g.height - BORDER_Y - BORDER_X, gw->pstyle->background);
+ gdispGFillStringBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, BORDER_Y, gw->text, gw->g.font, gdispContrastColor(pcol->edge), pcol->edge, justifyCenter);
+ gdispGFillArea(gw->g.display, gw->g.x, gw->g.y+BORDER_Y, BORDER_X, gw->g.height-(BORDER_Y+BORDER_X), pcol->edge);
+ gdispGFillArea(gw->g.display, gw->g.x+gw->g.width-BORDER_X, gw->g.y+BORDER_Y, BORDER_X, gw->g.height-(BORDER_Y+BORDER_X), pcol->edge);
+ gdispGFillArea(gw->g.display, gw->g.x, gw->g.y+gw->g.height-BORDER_X, gw->g.width, BORDER_X, pcol->edge);
+ } else {
+ gdispGFillArea(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, gw->pstyle->background);
+ }
+}
+
+#endif /* (GFX_USE_GWIN && GWIN_NEED_FRAME) || defined(__DOXYGEN__) */
+/** @} */
+
diff --git a/src/gwin/frame.h b/src/gwin/frame.h
new file mode 100644
index 00000000..8116b1de
--- /dev/null
+++ b/src/gwin/frame.h
@@ -0,0 +1,70 @@
+/*
+ * This file is subject to the terms of the GFX License. If a copy of
+ * the license was not distributed with this file, you can obtain one at:
+ *
+ * http://ugfx.org/license.html
+ */
+
+/**
+ * @file src/gwin/frame.h
+ * @brief GWIN Graphic window subsystem header file.
+ *
+ * @defgroup Frame Frame
+ * @ingroup GWIN
+ *
+ * @details A frame is a rectangular window that can have optional border as well as buttons to
+ * close, maximize and minimize it. The main purpose of this widget is to contain children.
+ *
+ * @pre GFX_USE_GWIN must be set to TRUE in your gfxconf.h
+ * @pre GWIN_NEED_FRAME must be set to TRUE in your gfxconf.h
+ * @{
+ */
+
+#ifndef _GWIN_FRAME_H
+#define _GWIN_FRAME_H
+
+/**
+ * @brief Flags for gwinFrameCreate()
+ * @{
+ */
+#define GWIN_FRAME_BORDER 0x00000001
+#define GWIN_FRAME_CLOSE_BTN 0x00000002
+#define GWIN_FRAME_MINMAX_BTN 0x00000004
+/* @} */
+
+typedef struct GFrameObject {
+ GContainerObject gc;
+
+ GListener gl; // internal listener for the buttons
+ // These could probably be removed... I have to think harder later
+ GHandle btnClose;
+ GHandle btnMin;
+ GHandle btnMax;
+} GFrameObject;
+
+/**
+ * @brief Create a frame widget
+ *
+ * @details This widget provides a window like we know it from desktop systems. You usually use this together with
+ * gwinAddChild().
+ *
+ * @param[in] g The GDisplay to display this window on
+ * @param[in] fo The GFrameObject structure to initialize. If this is NULL the structure is dynamically allocated.
+ * @param[in] pInit The initialization parameters
+ * @param[in] flags Some flags, see notes.
+ *
+ * @note Possible flags are: GWIN_FRAME_BORDER, GWIN_FRAME_CLOSE_BTN, GWIN_FRAME_MINMAX_BTN.
+ * Whether the close or the minimize maximize buttons are used, the boarder is automatically invoked.
+ * @note These frame buttons are processed internally. The close button will invoke a gwinDestroy() which will
+ * destroy the window itself and EVERY child it contains (also children of children).
+ *
+ * @return NULL if there is no resulting widget. A valid GHandle otherwise.
+ *
+ * @api
+ */
+GHandle gwinGFrameCreate(GDisplay *g, GFrameObject *fo, GWidgetInit *pInit, uint32_t flags);
+#define gwinFrameCreate(fo, pInit, flags) gwinGFrameCreate(GDISP, fo, pInit, flags);
+
+#endif /* _GWIN_FRAME_H */
+/** @} */
+
diff --git a/src/gwin/gcontainer.c b/src/gwin/gcontainer.c
new file mode 100644
index 00000000..3f6bfb56
--- /dev/null
+++ b/src/gwin/gcontainer.c
@@ -0,0 +1,193 @@
+/*
+ * This file is subject to the terms of the GFX License. If a copy of
+ * the license was not distributed with this file, you can obtain one at:
+ *
+ * http://ugfx.org/license.html
+ */
+
+/**
+ * @file src/gwin/gcontainer.c
+ * @brief GWIN sub-system container code.
+ *
+ * @defgroup Containers Containers
+ * @ingroup GWIN
+ *
+ * @{
+ */
+
+#include "gfx.h"
+
+#if GFX_USE_GWIN && GWIN_NEED_CONTAINERS
+
+#include "src/gwin/class_gwin.h"
+
+void _gcontainerInit(void)
+{
+}
+
+void _gcontainerDeinit(void)
+{
+}
+
+GHandle _gcontainerCreate(GDisplay *g, GContainerObject *pgc, const GWidgetInit *pInit, const gcontainerVMT *vmt) {
+ if (!(pgc = (GContainerObject *)_gwidgetCreate(g, (GWidgetObject *)pgc, pInit, &vmt->gw)))
+ return 0;
+
+ pgc->g.flags |= GWIN_FLG_CONTAINER;
+
+ return &pgc->g;
+}
+
+void _gcontainerDestroy(GHandle gh) {
+ GHandle child;
+
+ while((child = gwinGetFirstChild(gh)))
+ gwinDestroy(child);
+ _gwidgetDestroy(gh);
+}
+
+void _gcontainerRedraw(GHandle gh) {
+ GHandle child;
+
+ if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
+ return;
+
+ ((GWidgetObject *)gh)->fnDraw((GWidgetObject *)gh, ((GWidgetObject *)gh)->fnParam);
+
+ for(child = gwinGetFirstChild(gh); child; child = gwinGetSibling(child))
+ gwinRedraw(child);
+}
+
+void _gcontainerUpdate(GHandle gh) {
+ GHandle child;
+
+ if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
+ return;
+
+ #if GDISP_NEED_CLIP
+ gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
+ #endif
+ ((GWidgetObject *)gh)->fnDraw((GWidgetObject *)gh, ((GWidgetObject *)gh)->fnParam);
+
+ for(child = gwinGetFirstChild(gh); child; child = gwinGetSibling(child))
+ gwinRedraw(child);
+}
+
+void _gwinRecurse(GHandle gh, bool_t (*fn)(GHandle gh)) {
+ if (fn(gh) && (gh->flags & GWIN_FLG_CONTAINER)) {
+ // Apply to this windows children
+ for(gh = gwinGetFirstChild(gh); gh; gh = gwinGetSibling(gh)) {
+ // Only recurse when we have to. Otherwise apply it directly
+ if ((gh->flags & GWIN_FLG_CONTAINER))
+ _gwinRecurse(gh, fn);
+ else
+ fn(gh);
+ }
+ }
+}
+
+GHandle gwinGetFirstChild(GHandle gh) {
+ GHandle child;
+
+ for(child = gwinGetNextWindow(0); child; child = gwinGetNextWindow(child))
+ if (child->parent == gh)
+ return child;
+ return 0;
+}
+
+GHandle gwinGetSibling(GHandle gh) {
+ GHandle child;
+
+ for(child = gwinGetNextWindow(gh), gh = gh->parent; child; child = gwinGetNextWindow(child))
+ if (child->parent == gh)
+ return child;
+ return 0;
+}
+
+coord_t gwinGetInnerWidth(GHandle gh) {
+ if (!(gh->flags & GWIN_FLG_CONTAINER))
+ return 0;
+ return gh->width - ((const gcontainerVMT *)gh->vmt)->LeftBorder(gh) - ((const gcontainerVMT *)gh->vmt)->RightBorder(gh);
+}
+
+coord_t gwinGetInnerHeight(GHandle gh) {
+ if (!(gh->flags & GWIN_FLG_CONTAINER))
+ return 0;
+ return gh->height - ((const gcontainerVMT *)gh->vmt)->TopBorder(gh) - ((const gcontainerVMT *)gh->vmt)->BottomBorder(gh);
+}
+
+#endif /* GFX_USE_GWIN && GWIN_NEED_CONTAINERS */
+/** @} */
+
+/*-----------------------------------------------
+ * The simplest container type - a container
+ *-----------------------------------------------
+ *
+ * @defgroup Containers Containers
+ * @ingroup GWIN
+ *
+ * @{
+ */
+
+#if GFX_USE_GWIN && GWIN_NEED_CONTAINER
+
+#if GWIN_CONTAINER_BORDER != GWIN_FIRST_CONTROL_FLAG
+ #error "GWIN Container: - Flag definitions don't match"
+#endif
+
+static coord_t BorderSize(GHandle gh) { return (gh->flags & GWIN_CONTAINER_BORDER) ? 2 : 0; }
+
+static void DrawSimpleContainer(GWidgetObject *gw, void *param) {
+ (void) param;
+ gdispGFillArea(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, gw->pstyle->background);
+ if ((gw->g.flags & GWIN_CONTAINER_BORDER))
+ gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, (gw->g.flags & GWIN_FLG_SYSENABLED) ? gw->pstyle->enabled.edge : gw->pstyle->disabled.edge);
+}
+
+// The container VMT table
+static const gcontainerVMT containerVMT = {
+ {
+ {
+ "Container", // The classname
+ sizeof(GContainerObject), // The object size
+ _gcontainerDestroy, // The destroy routine
+ _gcontainerRedraw, // The redraw routine
+ 0, // The after-clear routine
+ },
+ DrawSimpleContainer, // The default drawing routine
+ #if GINPUT_NEED_MOUSE
+ {
+ 0, 0, 0, // No mouse
+ },
+ #endif
+ #if GINPUT_NEED_TOGGLE
+ {
+ 0, 0, 0, 0, 0, // No toggles
+ },
+ #endif
+ #if GINPUT_NEED_DIAL
+ {
+ 0, 0, 0, 0, // No dials
+ },
+ #endif
+ },
+ BorderSize, // The size of the left border (mandatory)
+ BorderSize, // The size of the top border (mandatory)
+ BorderSize, // The size of the right border (mandatory)
+ BorderSize, // The size of the bottom border (mandatory)
+ 0, // A child has been added (optional)
+ 0, // A child has been deleted (optional)
+};
+
+GHandle gwinGContainerCreate(GDisplay *g, GContainerObject *gc, const GWidgetInit *pInit, uint32_t flags) {
+ if (!(gc = (GContainerObject *)_gcontainerCreate(g, gc, pInit, &containerVMT)))
+ return 0;
+
+ gc->g.flags |= flags;
+
+ gwinSetVisible((GHandle)gc, pInit->g.show);
+ return (GHandle)gc;
+}
+
+#endif
+/** @} */
diff --git a/src/gwin/gcontainer.h b/src/gwin/gcontainer.h
new file mode 100644
index 00000000..4a7b5632
--- /dev/null
+++ b/src/gwin/gcontainer.h
@@ -0,0 +1,136 @@
+/*
+ * This file is subject to the terms of the GFX License. If a copy of
+ * the license was not distributed with this file, you can obtain one at:
+ *
+ * http://ugfx.org/license.html
+ */
+
+/**
+ * @file src/gwin/gcontainer.h
+ * @brief GWIN Containers header file.
+ */
+
+#ifndef _GCONTAINER_H
+#define _GCONTAINER_H
+
+/* This file is included within "gwin/gwin.h" */
+
+/**
+ * @defgroup Containers Containers
+ * @ingroup GWIN
+ *
+ * @details A Container is a GWindow that supports child windows. It is also
+ * a widget in its own right and therefore can accept user input directly.
+ *
+ * @pre GFX_USE_GWIN and GWIN_NEED_CONTAINERS must be set to TRUE in your gfxconf.h
+ * @{
+ */
+
+// Forward definition
+struct GContainerObject;
+
+/**
+ * @brief The GWIN Container structure
+ * @note A container is a GWIN widget that can have children.
+ * @note Do not access the members directly. Treat it as a black-box and use the method functions.
+ *
+ * @{
+ */
+typedef GWidgetObject GContainerObject;
+/* @} */
+
+/**
+ * A comment/rant on the above structure:
+ * We would really like the GWidgetObject 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 Get the first child window
+ *
+ * @return The first child or NULL if are no children windows
+ *
+ * @param[in] gh The parent container or NULL to get the first top level window
+ *
+ * @api
+ */
+ GHandle gwinGetFirstChild(GHandle gh);
+
+ /**
+ * @brief Get the next child window in the z-order
+ *
+ * @return The next window or NULL if no more children
+ *
+ * @param[in] gh The window to obtain the next sibling of.
+ *
+ * @note This returns the next window under the current parent window.
+ * Unlike @p gwinGetNextWindow() it will only return windows that
+ * have the same parent as the supplied window.
+ *
+ * @api
+ */
+ GHandle gwinGetSibling(GHandle gh);
+
+ /**
+ * @brief Get the inner width of a container window
+ *
+ * @return The inner width of a container window or zero if this is not a container
+ *
+ * @param[in] gh The window
+ *
+ * @api
+ */
+ coord_t gwinGetInnerWidth(GHandle gh);
+
+ /**
+ * @brief Get the inner height of a container window
+ *
+ * @return The inner height of a container window or zero if this is not a container
+ *
+ * @param[in] gh The window
+ *
+ * @api
+ */
+ coord_t gwinGetInnerHeight(GHandle gh);
+
+
+ /**
+ * @brief Flags for gwinContainerCreate()
+ * @{
+ */
+ #define GWIN_CONTAINER_BORDER 0x00000001
+ /* @} */
+
+ /**
+ * @brief Create a simple container.
+ * @return NULL if there is no resultant drawing area, otherwise a window handle.
+ *
+ * @param[in] g The GDisplay to display this window on
+ * @param[in] gb The GContainerObject structure to initialise. If this is NULL the structure is dynamically allocated.
+ * @param[in] pInit The initialisation parameters
+ *
+ * @api
+ */
+ GHandle gwinGContainerCreate(GDisplay *g, GContainerObject *gw, const GWidgetInit *pInit, uint32_t flags);
+ #define gwinContainerCreate(gc, pInit, flags) gwinGContainerCreate(GDISP, gc, pInit, flags)
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Include extra container types */
+#if GWIN_NEED_FRAME || defined(__DOXYGEN__)
+ #include "src/gwin/frame.h"
+#endif
+
+#endif /* _GCONTAINER_H */
+/** @} */
diff --git a/src/gwin/gimage.c b/src/gwin/gimage.c
index 9d6363ba..baf14ad1 100644
--- a/src/gwin/gimage.c
+++ b/src/gwin/gimage.c
@@ -30,7 +30,7 @@ static void _destroy(GWindowObject *gh) {
#define gh ((GHandle)param)
// We need to re-test the visibility in case it has been made invisible since the last frame.
- if ((gh->flags & GWIN_FLG_VISIBLE)) {
+ if ((gh->flags & GWIN_FLG_SYSVISIBLE)) {
// Setting the clip here shouldn't be necessary if the redraw doesn't overdraw
// but we put it in for safety anyway
#if GDISP_NEED_CLIP
@@ -160,7 +160,7 @@ bool_t gwinImageOpenGFile(GHandle gh, GFILE *f) {
if ((gdispImageOpenGFile(&widget(gh)->image, f) & GDISP_IMAGE_ERR_UNRECOVERABLE))
return FALSE;
- if ((gh->flags & GWIN_FLG_VISIBLE)) {
+ if ((gh->flags & GWIN_FLG_SYSVISIBLE)) {
// Setting the clip here shouldn't be necessary if the redraw doesn't overdraw
// but we put it in for safety anyway
#if GDISP_NEED_CLIP
diff --git a/src/gwin/gwidget.c b/src/gwin/gwidget.c
index c46520ea..ccfbd26e 100644
--- a/src/gwin/gwidget.c
+++ b/src/gwin/gwidget.c
@@ -82,16 +82,15 @@ static const GWidgetStyle * defaultStyle = &BlackWidgetStyle;
/* 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;
+ GHandle gh;
#if GFX_USE_GINPUT && (GINPUT_NEED_TOGGLE || GINPUT_NEED_DIAL)
- uint16_t role;
+ uint16_t role;
#endif
- (void) param;
+ (void) param;
// Process various events
switch (pe->type) {
@@ -100,14 +99,14 @@ static void gwidgetEvent(void *param, GEvent *pe) {
case GEVENT_MOUSE:
case GEVENT_TOUCH:
// Cycle through all windows
- for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
+ for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
// check if the widget matches this display
if (gh->display != pme->display)
continue;
- // 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))
+ // check if it is a widget that is enabled and visible
+ if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED|GWIN_FLG_SYSVISIBLE)) != (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED|GWIN_FLG_SYSVISIBLE))
continue;
// Are we captured?
@@ -134,10 +133,10 @@ static void gwidgetEvent(void *param, GEvent *pe) {
#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
case GEVENT_TOGGLE:
// Cycle through all windows
- for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
+ for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
// 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))
+ if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED|GWIN_FLG_SYSVISIBLE)) != (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED|GWIN_FLG_SYSVISIBLE))
continue;
for(role = 0; role < wvmt->toggleroles; role++) {
@@ -158,10 +157,10 @@ static void gwidgetEvent(void *param, GEvent *pe) {
#if GFX_USE_GINPUT && GINPUT_NEED_DIAL
case GEVENT_DIAL:
// Cycle through all windows
- for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
+ for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
// 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))
+ if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED|GWIN_FLG_SYSVISIBLE)) != (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED|GWIN_FLG_SYSVISIBLE))
continue;
for(role = 0; role < wvmt->dialroles; role++) {
@@ -178,7 +177,6 @@ static void gwidgetEvent(void *param, GEvent *pe) {
break;
}
- #undef gh
#undef pme
#undef pte
#undef pde
@@ -186,11 +184,10 @@ static void gwidgetEvent(void *param, GEvent *pe) {
#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
static GHandle FindToggleUser(uint16_t instance) {
- #define gh QItem2GWindow(qi)
- const gfxQueueASyncItem * qi;
- uint16_t role;
+ GHandle gh;
+ uint16_t role;
- for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
+ for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
if (!(gh->flags & GWIN_FLG_WIDGET)) // check if it a widget
continue;
@@ -200,17 +197,15 @@ static void gwidgetEvent(void *param, GEvent *pe) {
}
}
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;
+ GHandle gh;
+ uint16_t role;
- for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
+ for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
if (!(gh->flags & GWIN_FLG_WIDGET)) // check if it a widget
continue;
@@ -220,7 +215,6 @@ static void gwidgetEvent(void *param, GEvent *pe) {
}
}
return 0;
- #undef gh
}
#endif
@@ -236,9 +230,14 @@ void _gwidgetDeinit(void)
}
GHandle _gwidgetCreate(GDisplay *g, GWidgetObject *pgw, const GWidgetInit *pInit, const gwidgetVMT *vmt) {
- if (!(pgw = (GWidgetObject *)_gwindowCreate(g, &pgw->g, &pInit->g, &vmt->g, GWIN_FLG_WIDGET|GWIN_FLG_ENABLED)))
+ if (!(pgw = (GWidgetObject *)_gwindowCreate(g, &pgw->g, &pInit->g, &vmt->g, GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED)))
return 0;
+ #if GWIN_NEED_COLLECTIONS
+ // This window can't be system enabled if the parent is not enabled
+ if (pgw->parent && !(pgw->parent->flags & GWIN_FLG_SYSENABLED))
+ pgw->g.flags &= ~GWIN_FLG_SYSENABLED;
+ #endif
pgw->text = pInit->text ? pInit->text : "";
pgw->fnDraw = pInit->customDraw ? pInit->customDraw : vmt->DefaultDraw;
pgw->fnParam = pInit->customParam;
@@ -287,13 +286,19 @@ void _gwidgetDestroy(GHandle gh) {
}
void _gwidgetRedraw(GHandle gh) {
- if (!(gh->flags & GWIN_FLG_VISIBLE))
+ if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
+ return;
+
+ gw->fnDraw(gw, gw->fnParam);
+}
+
+void _gwidgetUpdate(GHandle gh) {
+ if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return;
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
-
gw->fnDraw(gw, gw->fnParam);
}
@@ -310,13 +315,13 @@ void gwinSetDefaultStyle(const GWidgetStyle *pstyle, bool_t updateAll) {
pstyle = &BlackWidgetStyle;
if (updateAll) {
- const gfxQueueASyncItem * qi;
GHandle gh;
- for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
- gh = QItem2GWindow(qi);
+ for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
if ((gh->flags & GWIN_FLG_WIDGET) && ((GWidgetObject *)gh)->pstyle == defaultStyle)
gwinSetStyle(gh, pstyle);
+ else
+ gwinRedraw(gh);
}
}
gwinSetDefaultBgColor(pstyle->background);
@@ -359,7 +364,7 @@ void gwinSetText(GHandle gh, const char *text, bool_t useAlloc) {
gw->text = (const char *)str;
} else
gw->text = text;
- _gwidgetRedraw(gh);
+ _gwidgetUpdate(gh);
}
const char *gwinGetText(GHandle gh) {
@@ -375,7 +380,7 @@ void gwinSetStyle(GHandle gh, const GWidgetStyle *pstyle) {
gw->pstyle = pstyle ? pstyle : defaultStyle;
gh->bgcolor = pstyle->background;
gh->color = pstyle->enabled.text;
- _gwidgetRedraw(gh);
+ _gwidgetUpdate(gh);
}
const GWidgetStyle *gwinGetStyle(GHandle gh) {
@@ -391,7 +396,7 @@ void gwinSetCustomDraw(GHandle gh, CustomWidgetDrawFunction fn, void *param) {
gw->fnDraw = fn ? fn : wvmt->DefaultDraw;
gw->fnParam = param;
- _gwidgetRedraw(gh);
+ _gwidgetUpdate(gh);
}
bool_t gwinAttachListener(GListener *pl) {
diff --git a/src/gwin/gwin.c b/src/gwin/gwin.c
index 84443f9f..2e4144a7 100644
--- a/src/gwin/gwin.c
+++ b/src/gwin/gwin.c
@@ -39,10 +39,11 @@ static color_t defaultBgColor = Black;
#if GWIN_NEED_WINDOWMANAGER
#define _gwm_redraw(gh, flags) _GWINwm->vmt->Redraw(gh, flags)
- #define _gwm_redim(gh,x,y,w,h) _GWINwm->vmt->Redim(gh,x,y,w,h);
+ #define _gwm_move(gh,x,y) _GWINwm->vmt->Move(gh,x,y);
+ #define _gwm_resize(gh,w,h) _GWINwm->vmt->Size(gh,w,h);
#else
static void _gwm_redraw(GHandle gh, int flags) {
- if ((gh->flags & GWIN_FLG_VISIBLE)) {
+ if ((gh->flags & GWIN_FLG_SYSVISIBLE)) {
if (gh->vmt->Redraw) {
#if GDISP_NEED_CLIP
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
@@ -63,19 +64,22 @@ static color_t defaultBgColor = Black;
gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, defaultBgColor);
}
}
- static void _gwm_redim(GHandle gh, coord_t x, coord_t y, coord_t width, coord_t height) {
- gh->x = x; gh->y = y;
+ static void _gwm_resize(GHandle gh, coord_t width, coord_t height) {
gh->width = width; gh->height = height;
- if (gh->x < 0) { gh->width += gh->x; gh->x = 0; }
- if (gh->y < 0) { gh->height += gh->y; gh->y = 0; }
- if (gh->x > gdispGetWidth()-MIN_WIN_WIDTH) gh->x = gdispGetWidth()-MIN_WIN_WIDTH;
- if (gh->y > gdispGetHeight()-MIN_WIN_HEIGHT) gh->y = gdispGetHeight()-MIN_WIN_HEIGHT;
if (gh->width < MIN_WIN_WIDTH) { gh->width = MIN_WIN_WIDTH; }
if (gh->height < MIN_WIN_HEIGHT) { gh->height = MIN_WIN_HEIGHT; }
if (gh->x+gh->width > gdispGetWidth()) gh->width = gdispGetWidth() - gh->x;
if (gh->y+gh->height > gdispGetHeight()) gh->height = gdispGetHeight() - gh->y;
-
- // Redraw the window
+ _gwm_redraw(gh, GWIN_WMFLG_PRESERVE|GWIN_WMFLG_NOBGCLEAR);
+ }
+ static void _gwm_move(GHandle gh, coord_t x, coord_t y) {
+ gh->x = x; gh->y = y;
+ if (gh->x < 0) gh->x = 0;
+ if (gh->y < 0) gh->y = 0;
+ if (gh->x > gdispGetWidth()-MIN_WIN_WIDTH) gh->x = gdispGetWidth()-MIN_WIN_WIDTH;
+ if (gh->y > gdispGetHeight()-MIN_WIN_HEIGHT) gh->y = gdispGetHeight()-MIN_WIN_HEIGHT;
+ if (gh->x+gh->width > gdispGetWidth()) gh->width = gdispGetWidth() - gh->x;
+ if (gh->y+gh->height > gdispGetHeight()) gh->height = gdispGetHeight() - gh->y;
_gwm_redraw(gh, GWIN_WMFLG_PRESERVE|GWIN_WMFLG_NOBGCLEAR);
}
#endif
@@ -86,20 +90,30 @@ static color_t defaultBgColor = Black;
void _gwinInit(void)
{
+ #if GWIN_NEED_WINDOWMANAGER
+ extern void _gwmInit(void);
+
+ _gwmInit();
+ #endif
#if GWIN_NEED_WIDGET
extern void _gwidgetInit(void);
_gwidgetInit();
#endif
- #if GWIN_NEED_WINDOWMANAGER
- extern void _gwmInit(void);
+ #if GWIN_NEED_CONTAINERS
+ extern void _gcontainerInit(void);
- _gwmInit();
+ _gcontainerInit();
#endif
}
void _gwinDeinit(void)
{
+ #if GWIN_NEED_CONTAINERS
+ extern void _gcontainerDeinit(void);
+
+ _gcontainerDeinit();
+ #endif
#if GWIN_NEED_WIDGET
extern void _gwidgetDeinit(void);
@@ -132,6 +146,18 @@ GHandle _gwindowCreate(GDisplay *g, GWindowObject *pgw, const GWindowInit *pInit
pgw->font = defaultFont;
#endif
+ #if GWIN_NEED_CONTAINERS
+ if (pInit->parent) {
+ if (!(pInit->parent->flags & GWIN_FLG_CONTAINER) || pgw->display != pInit->parent->display) {
+ if ((pgw->flags & GWIN_FLG_DYNAMIC))
+ gfxFree(pgw);
+ return 0;
+ }
+ pgw->parent = pInit->parent;
+ } else
+ pgw->parent = 0;
+ #endif
+
#if GWIN_NEED_WINDOWMANAGER
if (!_GWINwm->vmt->Add(pgw, pInit)) {
if ((pgw->flags & GWIN_FLG_DYNAMIC))
@@ -139,7 +165,15 @@ GHandle _gwindowCreate(GDisplay *g, GWindowObject *pgw, const GWindowInit *pInit
return 0;
}
#else
- _gwm_redim(pgw, pInit->x, pInit->y, pInit->width, pInit->height);
+ pgw->x = pgw->y = pgw->width = pgw->height = 0;
+ _gwm_move(pgw, pInit->x, pInit->y);
+ _gwm_resize(pgw, pInit->width, pInit->height);
+ #endif
+
+ #if GWIN_NEED_CONTAINERS
+ // Notify the parent it has been added
+ if (pgw->parent && ((gcontainerVMT *)pgw->parent->vmt)->NotifyAdd)
+ ((gcontainerVMT *)pgw->parent->vmt)->NotifyAdd(pgw->parent, pgw);
#endif
return (GHandle)pgw;
@@ -203,6 +237,12 @@ void gwinDestroy(GHandle gh) {
// Make the window invisible
gwinSetVisible(gh, FALSE);
+ #if GWIN_NEED_CONTAINERS
+ // Notify the parent it is about to be deleted
+ if (gh->parent && ((gcontainerVMT *)gh->parent->vmt)->NotifyDelete)
+ ((gcontainerVMT *)gh->parent->vmt)->NotifyDelete(gh->parent, gh);
+ #endif
+
// Remove from the window manager
#if GWIN_NEED_WINDOWMANAGER
_GWINwm->vmt->Delete(gh);
@@ -224,48 +264,120 @@ 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;
- _gwm_redraw(gh, 0);
+#if GWIN_NEED_CONTAINERS
+ // These two sub-functions set/clear system visibility recursively.
+ static bool_t setSysVisFlag(GHandle gh) {
+ // If we are now visible and our parent is visible
+ if ((gh->flags & GWIN_FLG_VISIBLE) && (!gh->parent || (gh->parent->flags & GWIN_FLG_SYSVISIBLE))) {
+ gh->flags |= GWIN_FLG_SYSVISIBLE;
+ return TRUE;
}
- } else {
- if ((gh->flags & GWIN_FLG_VISIBLE)) {
- gh->flags &= ~GWIN_FLG_VISIBLE;
- _gwm_redraw(gh, 0);
+ return FALSE;
+ }
+ static bool_t clrSysVisFlag(GHandle gh) {
+ // If we are now not visible but our parent is visible
+ if (!(gh->flags & GWIN_FLG_VISIBLE) || (gh->parent && !(gh->parent->flags & GWIN_FLG_SYSVISIBLE))) {
+ gh->flags &= ~GWIN_FLG_SYSVISIBLE;
+ return TRUE;
}
+ return FALSE;
}
-}
+ void gwinSetVisible(GHandle gh, bool_t visible) {
+ if (visible) {
+ if (!(gh->flags & GWIN_FLG_VISIBLE)) {
+ gh->flags |= GWIN_FLG_VISIBLE;
+ _gwinRecurse(gh, setSysVisFlag);
+ _gwm_redraw(gh, 0);
+ }
+ } else {
+ if ((gh->flags & GWIN_FLG_VISIBLE)) {
+ gh->flags &= ~GWIN_FLG_VISIBLE;
+ _gwinRecurse(gh, clrSysVisFlag);
+ _gwm_redraw(gh, 0);
+ }
+ }
+ }
+#else
+ void gwinSetVisible(GHandle gh, bool_t visible) {
+ if (visible) {
+ if (!(gh->flags & GWIN_FLG_VISIBLE)) {
+ gh->flags |= (GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE);
+ _gwm_redraw(gh, 0);
+ }
+ } else {
+ if ((gh->flags & GWIN_FLG_VISIBLE)) {
+ gh->flags &= ~(GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE);
+ _gwm_redraw(gh, 0);
+ }
+ }
+ }
+#endif
bool_t gwinGetVisible(GHandle gh) {
- return (gh->flags & GWIN_FLG_VISIBLE) ? TRUE : FALSE;
+ return (gh->flags & GWIN_FLG_SYSVISIBLE) ? TRUE : FALSE;
}
-void gwinSetEnabled(GHandle gh, bool_t enabled) {
- if (enabled) {
- if (!(gh->flags & GWIN_FLG_ENABLED)) {
- gh->flags |= GWIN_FLG_ENABLED;
- _gwm_redraw(gh, GWIN_WMFLG_PRESERVE|GWIN_WMFLG_NOBGCLEAR);
+#if GWIN_NEED_CONTAINERS
+ // These two sub-functions set/clear system enable recursively.
+ static bool_t setSysEnaFlag(GHandle gh) {
+ // If we are now enabled and our parent is enabled
+ if ((gh->flags & GWIN_FLG_ENABLED) && (!gh->parent || (gh->parent->flags & GWIN_FLG_SYSENABLED))) {
+ gh->flags |= GWIN_FLG_SYSENABLED;
+ return TRUE;
}
- } else {
- if ((gh->flags & GWIN_FLG_ENABLED)) {
- gh->flags &= ~GWIN_FLG_ENABLED;
- _gwm_redraw(gh, GWIN_WMFLG_PRESERVE|GWIN_WMFLG_NOBGCLEAR);
+ return FALSE;
+ }
+ static bool_t clrSysEnaFlag(GHandle gh) {
+ // If we are now not enabled but our parent is enabled
+ if (!(gh->flags & GWIN_FLG_ENABLED) || (gh->parent && !(gh->parent->flags & GWIN_FLG_SYSENABLED))) {
+ gh->flags &= ~GWIN_FLG_SYSENABLED;
+ return TRUE;
}
+ return FALSE;
}
-}
+ void gwinSetEnabled(GHandle gh, bool_t enabled) {
+ if (enabled) {
+ if (!(gh->flags & GWIN_FLG_ENABLED)) {
+ gh->flags |= GWIN_FLG_ENABLED;
+ _gwinRecurse(gh, setSysEnaFlag);
+ if ((gh->flags & GWIN_FLG_SYSVISIBLE))
+ _gwm_redraw(gh, GWIN_WMFLG_PRESERVE);
+ }
+ } else {
+ if ((gh->flags & GWIN_FLG_ENABLED)) {
+ gh->flags &= ~GWIN_FLG_ENABLED;
+ _gwinRecurse(gh, clrSysEnaFlag);
+ if ((gh->flags & GWIN_FLG_SYSVISIBLE))
+ _gwm_redraw(gh, GWIN_WMFLG_PRESERVE);
+ }
+ }
+ }
+#else
+ void gwinSetEnabled(GHandle gh, bool_t enabled) {
+ if (enabled) {
+ if (!(gh->flags & GWIN_FLG_ENABLED)) {
+ gh->flags |= (GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED);
+ _gwm_redraw(gh, GWIN_WMFLG_PRESERVE|GWIN_WMFLG_NOBGCLEAR);
+ }
+ } else {
+ if ((gh->flags & GWIN_FLG_ENABLED)) {
+ gh->flags &= ~(GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED);
+ _gwm_redraw(gh, GWIN_WMFLG_PRESERVE|GWIN_WMFLG_NOBGCLEAR);
+ }
+ }
+ }
+#endif
bool_t gwinGetEnabled(GHandle gh) {
- return (gh->flags & GWIN_FLG_ENABLED) ? TRUE : FALSE;
+ return (gh->flags & GWIN_FLG_SYSENABLED) ? TRUE : FALSE;
}
void gwinMove(GHandle gh, coord_t x, coord_t y) {
- _gwm_redim(gh, x, y, gh->width, gh->height);
+ _gwm_move(gh, x, y);
}
void gwinResize(GHandle gh, coord_t width, coord_t height) {
- _gwm_redim(gh, gh->x, gh->y, width, height);
+ _gwm_resize(gh, width, height);
}
void gwinRedraw(GHandle gh) {
@@ -284,23 +396,28 @@ void gwinClear(GHandle gh) {
* still call the AfterClear() routine as some widgets will
* need this to clear internal buffers or similar
*/
- if (!((gh->flags & GWIN_FLG_VISIBLE))) {
+ if (!(gh->flags & GWIN_FLG_SYSVISIBLE)) {
if (gh->vmt->AfterClear)
gh->vmt->AfterClear(gh);
} else {
- #if GDISP_NEED_CLIP
- gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
- #endif
+ #if GDISP_NEED_CLIP
+ gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
+ #endif
- gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gh->bgcolor);
- if (gh->vmt->AfterClear)
- gh->vmt->AfterClear(gh);
+ gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gh->bgcolor);
+ if (gh->vmt->AfterClear)
+ gh->vmt->AfterClear(gh);
}
+
+ #if GWIN_NEED_CONTAINERS
+ for (gh = gwinGetFirstChild(gh); gh; gh = gwinGetSibling(gh))
+ gwinRedraw(gh);
+ #endif
}
void gwinDrawPixel(GHandle gh, coord_t x, coord_t y) {
- if (!((gh->flags & GWIN_FLG_VISIBLE)))
+ if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return;
#if GDISP_NEED_CLIP
@@ -310,7 +427,7 @@ 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)))
+ if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return;
#if GDISP_NEED_CLIP
@@ -320,7 +437,7 @@ 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)))
+ if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return;
#if GDISP_NEED_CLIP
@@ -330,7 +447,7 @@ 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)))
+ if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return;
#if GDISP_NEED_CLIP
@@ -340,7 +457,7 @@ 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)))
+ if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return;
#if GDISP_NEED_CLIP
@@ -351,7 +468,7 @@ 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)))
+ if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return;
#if GDISP_NEED_CLIP
@@ -361,7 +478,7 @@ 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)))
+ if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return;
#if GDISP_NEED_CLIP
@@ -373,7 +490,7 @@ 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)))
+ if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return;
#if GDISP_NEED_CLIP
@@ -383,7 +500,7 @@ 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)))
+ if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return;
#if GDISP_NEED_CLIP
@@ -395,7 +512,7 @@ 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)))
+ if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return;
#if GDISP_NEED_CLIP
@@ -405,7 +522,7 @@ 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)))
+ if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return;
#if GDISP_NEED_CLIP
@@ -417,7 +534,7 @@ 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)))
+ if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return defaultBgColor;
#if GDISP_NEED_CLIP
@@ -429,7 +546,7 @@ 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->flags & GWIN_FLG_VISIBLE)) || !gh->font)
+ if (!(gh->flags & GWIN_FLG_SYSVISIBLE) || !gh->font)
return;
#if GDISP_NEED_CLIP
@@ -439,7 +556,7 @@ 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->flags & GWIN_FLG_VISIBLE)) || !gh->font)
+ if (!(gh->flags & GWIN_FLG_SYSVISIBLE) || !gh->font)
return;
#if GDISP_NEED_CLIP
@@ -449,7 +566,7 @@ 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->flags & GWIN_FLG_VISIBLE)) || !gh->font)
+ if (!(gh->flags & GWIN_FLG_SYSVISIBLE) || !gh->font)
return;
#if GDISP_NEED_CLIP
@@ -459,7 +576,7 @@ 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->flags & GWIN_FLG_VISIBLE)) || !gh->font)
+ if (!(gh->flags & GWIN_FLG_SYSVISIBLE) || !gh->font)
return;
#if GDISP_NEED_CLIP
@@ -469,7 +586,7 @@ 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->flags & GWIN_FLG_VISIBLE)) || !gh->font)
+ if (!(gh->flags & GWIN_FLG_SYSVISIBLE) || !gh->font)
return;
#if GDISP_NEED_CLIP
@@ -479,7 +596,7 @@ 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->flags & GWIN_FLG_VISIBLE)) || !gh->font)
+ if (!(gh->flags & GWIN_FLG_SYSVISIBLE) || !gh->font)
return;
#if GDISP_NEED_CLIP
@@ -491,7 +608,7 @@ 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)))
+ if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return;
#if GDISP_NEED_CLIP
@@ -501,7 +618,7 @@ 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)))
+ if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return;
#if GDISP_NEED_CLIP
@@ -513,7 +630,7 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor
#if GDISP_NEED_IMAGE
gdispImageError gwinDrawImage(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)))
+ if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
return GDISP_IMAGE_ERR_OK;
#if GDISP_NEED_CLIP
diff --git a/src/gwin/gwm.c b/src/gwin/gwm.c
index 3140b03f..1c96d1c9 100644
--- a/src/gwin/gwm.c
+++ b/src/gwin/gwm.c
@@ -28,7 +28,8 @@ static void WM_DeInit(void);
static bool_t WM_Add(GHandle gh, const GWindowInit *pInit);
static void WM_Delete(GHandle gh);
static void WM_Redraw(GHandle gh, int flags);
-static void WM_Redim(GHandle gh, coord_t x, coord_t y, coord_t w, coord_t h);
+static void WM_Size(GHandle gh, coord_t w, coord_t h);
+static void WM_Move(GHandle gh, coord_t x, coord_t y);
static void WM_Raise(GHandle gh);
static void WM_MinMax(GHandle gh, GWindowMinMax minmax);
@@ -38,7 +39,8 @@ static const gwmVMT GNullWindowManagerVMT = {
WM_Add,
WM_Delete,
WM_Redraw,
- WM_Redim,
+ WM_Size,
+ WM_Move,
WM_Raise,
WM_MinMax,
};
@@ -47,7 +49,7 @@ static const GWindowManager GNullWindowManager = {
&GNullWindowManagerVMT,
};
-gfxQueueASync _GWINList;
+static gfxQueueASync _GWINList;
GWindowManager * _GWINwm;
#if GFX_USE_GTIMER
static GTimer RedrawTimer;
@@ -114,11 +116,9 @@ void gwinRedrawDisplay(GDisplay *g, bool_t preserve) {
(void) param;
#endif
- const gfxQueueASyncItem * qi;
GHandle gh;
- for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
- gh = QItem2GWindow(qi);
+ for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
if (!g || gh->display == g)
_GWINwm->vmt->Redraw(gh,
preserve ? (GWIN_WMFLG_PRESERVE|GWIN_WMFLG_NOBGCLEAR|GWIN_WMFLG_NOZORDER)
@@ -150,8 +150,11 @@ static bool_t WM_Add(GHandle gh, const GWindowInit *pInit) {
// Put it on the end of the queue
gfxQueueASyncPut(&_GWINList, &gh->wmq);
- // Make sure the size is valid
- WM_Redim(gh, pInit->x, pInit->y, pInit->width, pInit->height);
+ // Make sure the size/position is valid - prefer position over size.
+ gh->width = MIN_WIN_WIDTH; gh->height = MIN_WIN_HEIGHT;
+ gh->x = gh->y = 0;
+ WM_Move(gh, pInit->x, pInit->y);
+ WM_Size(gh, pInit->width, pInit->height);
return TRUE;
}
@@ -161,15 +164,20 @@ static void WM_Delete(GHandle gh) {
}
static void WM_Redraw(GHandle gh, int flags) {
- if ((gh->flags & GWIN_FLG_VISIBLE)) {
+ #if GWIN_NEED_CONTAINERS
+ redo_redraw:
+ #endif
+ if ((gh->flags & GWIN_FLG_SYSVISIBLE)) {
if (gh->vmt->Redraw) {
#if GDISP_NEED_CLIP
- gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
+ if (!(flags & GWIN_WMFLG_KEEPCLIP))
+ gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
gh->vmt->Redraw(gh);
} else if (!(flags & GWIN_WMFLG_PRESERVE)) {
#if GDISP_NEED_CLIP
- gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
+ if (!(flags & GWIN_WMFLG_KEEPCLIP))
+ gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
#endif
gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gh->bgcolor);
if (gh->vmt->AfterClear)
@@ -184,42 +192,101 @@ static void WM_Redraw(GHandle gh, int flags) {
} else if (!(flags & GWIN_WMFLG_NOBGCLEAR)) {
#if GDISP_NEED_CLIP
- gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
+ if (!(flags & GWIN_WMFLG_KEEPCLIP))
+ gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
+ #endif
+ #if GWIN_NEED_CONTAINERS
+ if (gh->parent) {
+ // Get the parent to redraw the area
+ gh = gh->parent;
+ flags |= GWIN_WMFLG_KEEPCLIP;
+ goto redo_redraw;
+ }
#endif
gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gwinGetDefaultBgColor());
}
}
-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 > gdispGGetWidth(gh->display)-MIN_WIN_WIDTH) x = gdispGGetWidth(gh->display)-MIN_WIN_WIDTH;
- if (y > gdispGGetHeight(gh->display)-MIN_WIN_HEIGHT) y = gdispGGetHeight(gh->display)-MIN_WIN_HEIGHT;
- if (w < MIN_WIN_WIDTH) { w = MIN_WIN_WIDTH; }
- if (h < MIN_WIN_HEIGHT) { h = MIN_WIN_HEIGHT; }
- if (x+w > gdispGGetWidth(gh->display)) w = gdispGGetWidth(gh->display) - x;
- if (y+h > gdispGGetHeight(gh->display)) h = gdispGGetHeight(gh->display) - y;
+static void WM_Size(GHandle gh, coord_t w, coord_t h) {
+ coord_t v;
+
+ #if GWIN_NEED_CONTAINERS
+ if (gh->parent) {
+ // Clip to the container
+ v = gh->parent->x + gh->parent->width - ((const gcontainerVMT *)gh->parent->vmt)->RightBorder(gh->parent);
+ if (gh->x+w > v) w = v - gh->x;
+ v = gh->parent->y + gh->parent->height - ((const gcontainerVMT *)gh->parent->vmt)->BottomBorder(gh->parent);
+ if (gh->y+h > v) h = v - gh->y;
+ }
+ #endif
+
+ // Clip to the screen
+ v = gdispGGetWidth(gh->display);
+ if (gh->x+w > v) w = v - gh->x;
+ v = gdispGGetHeight(gh->display);
+ if (gh->y+h > v) h = v - gh->y;
+
+ // Give it a minimum size
+ if (w < MIN_WIN_WIDTH) w = MIN_WIN_WIDTH;
+ if (h < MIN_WIN_HEIGHT) h = MIN_WIN_HEIGHT;
// If there has been no resize just exit
- if (gh->x == x && gh->y == y && gh->width == w && gh->height == h)
+ if (gh->width == w && gh->height == h)
return;
- // Clear the old area
- if ((gh->flags & GWIN_FLG_VISIBLE)) {
- #if GDISP_NEED_CLIP
- gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
- #endif
- gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gwinGetDefaultBgColor());
+ // Clear the old area and then redraw
+ if ((gh->flags & GWIN_FLG_SYSVISIBLE)) {
+ gh->flags &= ~GWIN_FLG_SYSVISIBLE;
+ WM_Redraw(gh, 0);
+ gh->width = w; gh->height = h;
+ gh->flags |= GWIN_FLG_SYSVISIBLE;
+ WM_Redraw(gh, 0);
+ } else {
+ gh->width = w; gh->height = h;
}
+}
+
+static void WM_Move(GHandle gh, coord_t x, coord_t y) {
+ coord_t v;
+
+ #if GWIN_NEED_CONTAINERS
+ if (gh->parent) {
+ // Clip to the parent size
+ v = gh->parent->width - ((const gcontainerVMT *)gh->parent->vmt)->LeftBorder(gh->parent) - ((const gcontainerVMT *)gh->parent->vmt)->RightBorder(gh->parent);
+ if (x+gh->width > v) x = v-gh->width;
+ v = gh->parent->height - ((const gcontainerVMT *)gh->parent->vmt)->TopBorder(gh->parent) - ((const gcontainerVMT *)gh->parent->vmt)->BottomBorder(gh->parent);
+ if (y+gh->height > v) y = v-gh->height;
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+
+ // Convert to absolute position
+ x += gh->parent->x + ((const gcontainerVMT *)gh->parent->vmt)->LeftBorder(gh->parent);
+ y += gh->parent->y + ((const gcontainerVMT *)gh->parent->vmt)->TopBorder(gh->parent);
+ }
+ #endif
- // Set the new size
- gh->x = x; gh->y = y;
- gh->width = w; gh->height = h;
+ // Clip to the screen
+ v = gdispGGetWidth(gh->display);
+ if (x+gh->width > v) x = v-gh->width;
+ v = gdispGGetHeight(gh->display);
+ if (y+gh->height > v) y = v-gh->height;
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
- // Redraw the window (if possible)
- WM_Redraw(gh, GWIN_WMFLG_PRESERVE|GWIN_WMFLG_NOBGCLEAR);
+ // If there has been no move just exit
+ if (gh->x == x && gh->y == y)
+ return;
+
+ // Clear the old area and then redraw
+ if ((gh->flags & GWIN_FLG_SYSVISIBLE)) {
+ gh->flags &= ~GWIN_FLG_SYSVISIBLE;
+ WM_Redraw(gh, 0);
+ gh->x = x; gh->y = y;
+ gh->flags |= GWIN_FLG_SYSVISIBLE;
+ WM_Redraw(gh, 0);
+ } else {
+ gh->x = x; gh->y = y;
+ }
}
static void WM_MinMax(GHandle gh, GWindowMinMax minmax) {
@@ -230,6 +297,7 @@ static void WM_MinMax(GHandle gh, GWindowMinMax minmax) {
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);
@@ -237,5 +305,9 @@ static void WM_Raise(GHandle gh) {
WM_Redraw(gh, GWIN_WMFLG_PRESERVE|GWIN_WMFLG_NOBGCLEAR);
}
+GHandle gwinGetNextWindow(GHandle gh) {
+ return gh ? (GHandle)gfxQueueASyncNext(&gh->wmq) : (GHandle)gfxQueueASyncPeek(&_GWINList);
+}
+
#endif /* GFX_USE_GWIN && GWIN_NEED_WINDOWMANAGER */
/** @} */
diff --git a/src/gwin/label.c b/src/gwin/label.c
index 2aa0c860..ffb9fa3d 100644
--- a/src/gwin/label.c
+++ b/src/gwin/label.c
@@ -147,7 +147,7 @@ static void gwinLabelDefaultDraw(GWidgetObject *gw, void *param) {
w = (gw->g.flags & GLABEL_FLG_WAUTO) ? getwidth(gw->text, gw->g.font, gdispGGetWidth(gw->g.display) - gw->g.x) : gw->g.width;
h = (gw->g.flags & GLABEL_FLG_HAUTO) ? getheight(gw->text, gw->g.font, gdispGGetWidth(gw->g.display) - gw->g.x) : gw->g.height;
- c = (gw->g.flags & GWIN_FLG_ENABLED) ? gw->pstyle->enabled.text : gw->pstyle->disabled.text;
+ c = (gw->g.flags & GWIN_FLG_SYSENABLED) ? gw->pstyle->enabled.text : gw->pstyle->disabled.text;
if (gw->g.width != w || gw->g.height != h) {
gwinResize(&gw->g, w, h);
@@ -167,7 +167,7 @@ static void gwinLabelDefaultDraw(GWidgetObject *gw, void *param) {
// render the border (if any)
if (gw->g.flags & GLABEL_FLG_BORDER)
- gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, w, h, (gw->g.flags & GWIN_FLG_ENABLED) ? gw->pstyle->enabled.edge : gw->pstyle->disabled.edge);
+ gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, w, h, (gw->g.flags & GWIN_FLG_SYSENABLED) ? gw->pstyle->enabled.edge : gw->pstyle->disabled.edge);
}
#endif // GFX_USE_GWIN && GFX_NEED_LABEL
diff --git a/src/gwin/list.c b/src/gwin/list.c
index 788e8828..a960e3ed 100644
--- a/src/gwin/list.c
+++ b/src/gwin/list.c
@@ -107,7 +107,7 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param);
}
}
- _gwidgetRedraw(&gw->g);
+ _gwidgetUpdate(&gw->g);
sendListEvent(gw, item);
}
@@ -136,14 +136,14 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param);
gw2obj->top -= iheight;
if (gw2obj->top < 0)
gw2obj->top = 0;
- _gwidgetRedraw(&gw->g);
+ _gwidgetUpdate(&gw->g);
}
} else if (y >= gw->g.height - 2*ARROW) {
if (gw2obj->top < gw2obj->cnt * iheight - pgsz) {
gw2obj->top += iheight;
if (gw2obj->top > gw2obj->cnt * iheight - pgsz)
gw2obj->top = gw2obj->cnt * iheight - pgsz;
- _gwidgetRedraw(&gw->g);
+ _gwidgetUpdate(&gw->g);
}
} else if (y < gw->g.height/2) {
if (gw2obj->top > 0) {
@@ -151,7 +151,7 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param);
gw2obj->top -= pgsz;
else
gw2obj->top = 0;
- _gwidgetRedraw(&gw->g);
+ _gwidgetUpdate(&gw->g);
}
} else {
if (gw2obj->top < gw2obj->cnt * iheight - pgsz) {
@@ -159,7 +159,7 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param);
gw2obj->top += pgsz;
else
gw2obj->top = gw2obj->cnt * iheight - pgsz;
- _gwidgetRedraw(&gw->g);
+ _gwidgetUpdate(&gw->g);
}
}
return;
@@ -197,7 +197,7 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param);
gw2obj->top = 0;
gw2obj->last_mouse_y = y;
if (oldtop != gw2obj->top)
- _gwidgetRedraw(&gw->g);
+ _gwidgetUpdate(&gw->g);
}
}
#endif
@@ -218,7 +218,7 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param);
if (qix) {
qi2li->flags &=~ GLIST_FLG_SELECTED;
qix2li->flags |= GLIST_FLG_SELECTED;
- _gwidgetRedraw(&gw->g);
+ _gwidgetUpdate(&gw->g);
}
break;
}
@@ -235,7 +235,7 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param);
if (qix) {
qi2li->flags &=~ GLIST_FLG_SELECTED;
qix2li->flags |= GLIST_FLG_SELECTED;
- _gwidgetRedraw(&gw->g);
+ _gwidgetUpdate(&gw->g);
}
break;
}
@@ -388,7 +388,7 @@ int gwinListAddItem(GHandle gh, const char* item_name, bool_t useAlloc) {
// increment the total amount of entries in the list widget
gh2obj->cnt++;
- _gwidgetRedraw(gh);
+ _gwidgetUpdate(gh);
// return the position in the list (-1 because we start with index 0)
return gh2obj->cnt-1;
@@ -486,7 +486,7 @@ void gwinListDeleteAll(GHandle gh) {
gh->flags &= ~GLIST_FLG_HASIMAGES;
gh2obj->cnt = 0;
gh2obj->top = 0;
- _gwidgetRedraw(gh);
+ _gwidgetUpdate(gh);
}
void gwinListItemDelete(GHandle gh, int item) {
@@ -507,7 +507,7 @@ void gwinListItemDelete(GHandle gh, int item) {
gfxFree((void *)qi);
if (gh2obj->top >= item && gh2obj->top)
gh2obj->top--;
- _gwidgetRedraw(gh);
+ _gwidgetUpdate(gh);
break;
}
}
@@ -620,7 +620,7 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param) {
if (!(gw->g.flags & GLIST_FLG_ENABLERENDER))
return;
- ps = (gw->g.flags & GWIN_FLG_ENABLED) ? &gw->pstyle->enabled : &gw->pstyle->disabled;
+ ps = (gw->g.flags & GWIN_FLG_SYSENABLED) ? &gw->pstyle->enabled : &gw->pstyle->disabled;
iheight = gdispGetFontMetric(gw->g.font, fontHeight) + VERTICAL_PADDING;
x = 1;
@@ -643,7 +643,7 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param) {
gdispGFillConvexPoly(gw->g.display, gw->g.x+iwidth+((SCROLLWIDTH-ARROW)/2+2), gw->g.y+(ARROW/2+1), upArrow, 3, ps->fill);
gdispGFillConvexPoly(gw->g.display, gw->g.x+iwidth+((SCROLLWIDTH-ARROW)/2+2), gw->g.y+gw->g.height-(ARROW+ARROW/2+1), downArrow, 3, ps->fill);
#else
- #warning "GWIN: Lists display better when GDISP_NEED_CONVEX_POLGON is turned on"
+ #warning "GWIN: Lists display better when GDISP_NEED_CONVEX_POLYGON is turned on"
gdispGFillArea(gw->g.display, gw->g.x+iwidth+((SCROLLWIDTH-ARROW)/2+2), gw->g.y+(ARROW/2+1), ARROW, ARROW, ps->fill);
gdispGFillArea(gw->g.display, gw->g.x+iwidth+((SCROLLWIDTH-ARROW)/2+2), gw->g.y+gw->g.height-(ARROW+ARROW/2+1), ARROW, ARROW, ps->fill);
#endif
@@ -677,7 +677,7 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param) {
if (qi2li->pimg && gdispImageIsOpen(qi2li->pimg)) {
// Calculate which image
sy = (qi2li->flags & GLIST_FLG_SELECTED) ? 0 : (iheight-VERTICAL_PADDING);
- if (!(gw->g.flags & GWIN_FLG_ENABLED))
+ if (!(gw->g.flags & GWIN_FLG_SYSENABLED))
sy += 2*(iheight-VERTICAL_PADDING);
while (sy > qi2li->pimg->height)
sy -= iheight-VERTICAL_PADDING;
diff --git a/src/gwin/progressbar.c b/src/gwin/progressbar.c
index 524a5346..ca267f0c 100644
--- a/src/gwin/progressbar.c
+++ b/src/gwin/progressbar.c
@@ -128,7 +128,7 @@ void gwinProgressbarSetPosition(GHandle gh, int pos) {
}
ResetDisplayPos(gsw);
- _gwidgetRedraw(gh);
+ _gwidgetUpdate(gh);
#undef gsw
}
@@ -159,7 +159,7 @@ void gwinProgressbarIncrement(GHandle gh) {
gsw->pos = gsw->max;
ResetDisplayPos(gsw);
- _gwidgetRedraw(gh);
+ _gwidgetUpdate(gh);
#undef gsw
}
@@ -178,7 +178,7 @@ void gwinProgressbarDecrement(GHandle gh) {
gsw->pos -= gsw->res;
ResetDisplayPos(gsw);
- _gwidgetRedraw(gh);
+ _gwidgetUpdate(gh);
#undef gsw
}
@@ -239,7 +239,7 @@ void gwinProgressbarDraw_Std(GWidgetObject *gw, void *param) {
return;
// get the colors right
- if ((gw->g.flags & GWIN_FLG_ENABLED))
+ if ((gw->g.flags & GWIN_FLG_SYSENABLED))
pcol = &gw->pstyle->pressed;
else
pcol = &gw->pstyle->disabled;
@@ -277,7 +277,7 @@ void gwinProgressbarDraw_Image(GWidgetObject *gw, void *param) {
if (gw->g.vmt != (gwinVMT *)&progressbarVMT)
return;
- if ((gw->g.flags & GWIN_FLG_ENABLED))
+ if ((gw->g.flags & GWIN_FLG_SYSENABLED))
pcol = &gw->pstyle->pressed;
else
pcol = &gw->pstyle->disabled;
diff --git a/src/gwin/radio.c b/src/gwin/radio.c
index 0ae5546a..da6aa5ea 100644
--- a/src/gwin/radio.c
+++ b/src/gwin/radio.c
@@ -133,10 +133,10 @@ void gwinRadioPress(GHandle gh) {
if ((gx = gwinRadioGetActive(((GRadioObject *)gh)->group))) {
gx->flags &= ~GRADIO_FLG_PRESSED;
- _gwidgetRedraw(gx);
+ _gwidgetUpdate(gx);
}
gh->flags |= GRADIO_FLG_PRESSED;
- _gwidgetRedraw(gh);
+ _gwidgetUpdate(gh);
SendRadioEvent((GWidgetObject *)gh);
}
@@ -148,11 +148,9 @@ bool_t gwinRadioIsPressed(GHandle gh) {
}
GHandle gwinRadioGetActive(uint16_t group) {
- const gfxQueueASyncItem * qi;
- GHandle gh;
+ GHandle gh;
- for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
- gh = QItem2GWindow(qi);
+ for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
if (gh->vmt == (gwinVMT *)&radioVMT && ((GRadioObject *)gh)->group == group && (gh->flags & GRADIO_FLG_PRESSED))
return gh;
}
@@ -164,7 +162,7 @@ GHandle gwinRadioGetActive(uint16_t group) {
*----------------------------------------------------------*/
static const GColorSet *getDrawColors(GWidgetObject *gw) {
- if (!(gw->g.flags & GWIN_FLG_ENABLED)) return &gw->pstyle->disabled;
+ if (!(gw->g.flags & GWIN_FLG_SYSENABLED)) return &gw->pstyle->disabled;
if ((gw->g.flags & GRADIO_FLG_PRESSED)) return &gw->pstyle->pressed;
return &gw->pstyle->enabled;
}
diff --git a/src/gwin/slider.c b/src/gwin/slider.c
index 4c91ede6..3266e20a 100644
--- a/src/gwin/slider.c
+++ b/src/gwin/slider.c
@@ -74,7 +74,7 @@ static void ResetDisplayPos(GSliderObject *gsw) {
if (x < 0 || x >= gh->width || y < 0 || y >= gh->height) {
// No - restore the slider
ResetDisplayPos(gsw);
- _gwidgetRedraw(gh);
+ _gwidgetUpdate(gh);
return;
}
#endif
@@ -97,7 +97,7 @@ static void ResetDisplayPos(GSliderObject *gsw) {
}
ResetDisplayPos(gsw);
- _gwidgetRedraw(gh);
+ _gwidgetUpdate(gh);
// Generate the event
SendSliderEvent(gw);
@@ -127,7 +127,7 @@ static void ResetDisplayPos(GSliderObject *gsw) {
}
// Update the display
- _gwidgetRedraw(&gw->g);
+ _gwidgetUpdate(&gw->g);
#undef gsw
}
#endif
@@ -169,7 +169,7 @@ static void ResetDisplayPos(GSliderObject *gsw) {
gsw->pos = (uint16_t)((uint32_t)value*(gsw->max-gsw->min)/max + gsw->min);
ResetDisplayPos(gsw);
- _gwidgetRedraw((GHandle)gw);
+ _gwidgetUpdate((GHandle)gw);
// Generate the event
SendSliderEvent(gw);
@@ -272,7 +272,7 @@ void gwinSliderSetPosition(GHandle gh, int pos) {
else gsw->pos = pos;
}
ResetDisplayPos(gsw);
- _gwidgetRedraw(gh);
+ _gwidgetUpdate(gh);
#undef gsw
}
@@ -289,7 +289,7 @@ void gwinSliderDraw_Std(GWidgetObject *gw, void *param) {
if (gw->g.vmt != (gwinVMT *)&sliderVMT)
return;
- if ((gw->g.flags & GWIN_FLG_ENABLED))
+ if ((gw->g.flags & GWIN_FLG_SYSENABLED))
pcol = &gw->pstyle->pressed;
else
pcol = &gw->pstyle->disabled;
@@ -334,7 +334,7 @@ void gwinSliderDraw_Image(GWidgetObject *gw, void *param) {
if (gw->g.vmt != (gwinVMT *)&sliderVMT)
return;
- if ((gw->g.flags & GWIN_FLG_ENABLED))
+ if ((gw->g.flags & GWIN_FLG_SYSENABLED))
pcol = &gw->pstyle->pressed;
else
pcol = &gw->pstyle->disabled;
diff --git a/src/gwin/sys_defs.h b/src/gwin/sys_defs.h
index c632b069..426b2c02 100644
--- a/src/gwin/sys_defs.h
+++ b/src/gwin/sys_defs.h
@@ -27,6 +27,9 @@
#if GFX_USE_GWIN || defined(__DOXYGEN__)
+/* Forward declaration */
+typedef struct GWindowObject *GHandle;
+
/**
* @brief A window object structure
* @note Do not access the members directly. Treat it as a black-box and use the method functions.
@@ -46,6 +49,9 @@ typedef struct GWindowObject {
#if GDISP_NEED_TEXT
font_t font; // @< The current font
#endif
+ #if GWIN_NEED_CONTAINERS
+ GHandle parent; // @< The parent window
+ #endif
} GWindowObject, * GHandle;
/* @} */
@@ -62,9 +68,12 @@ typedef struct GWindowObject {
* @{
*/
typedef struct GWindowInit {
- coord_t x, y; // @< The initial screen position
+ coord_t x, y; // @< The initial position relative to its parent
coord_t width, height; // @< The initial dimension
bool_t show; // @< Should the window be visible initially
+ #if GWIN_NEED_CONTAINERS
+ GHandle parent; // @< The parent - must be a container or NULL
+ #endif
} GWindowInit;
/* @} */
@@ -324,15 +333,39 @@ extern "C" {
* 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.
+ * @note Even when you mark a window as visible, it may still not be displayed
+ * if it's parent is invisible. When the parent becomes visible this child
+ * will automatically be shown because it is already marked as visible.
*
* @api
*/
void gwinSetVisible(GHandle gh, bool_t visible);
/**
+ * @brief Makes a widget become visible
+ *
+ * @param[in] gh The window handle
+ *
+ * @api
+ */
+ #define gwinShow(gh) gwinSetVisible(gh, TRUE);
+
+ /**
+ * @brief Makes a widget become invisible
+ *
+ * @param[in] gh The window handle
+ *
+ * @api
+ */
+ #define gwinHide(gh) gwinSetVisible(gh, FALSE);
+
+ /**
* @brief Gets the visibility of a window
* @return TRUE if visible
*
+ * @note It is possible for a child to be marked as visible by @p gwinSetVisible()
+ * but for this call to return FALSE if one of its parents are not visible.
+ *
* @param[in] gh The window
*
* @api
@@ -345,8 +378,10 @@ extern "C" {
* @param[in] gh The window handle
* @param[in] enabled Enable or disable the window
*
- * @note The window is automatically redrawn if it
- * supports self-redrawing.
+ * @note The window is automatically redrawn if it supports self-redrawing.
+ * @note Even when you mark a window as enabled, it may still remain disabled
+ * if it's parent is disabled. When the parent becomes enabled this child
+ * will automatically be enabled because it is already marked as enabled.
*
* @api
*/
@@ -374,6 +409,9 @@ extern "C" {
* @brief Gets the enabled state of a window
* @return TRUE if enabled
*
+ * @note It is possible for a child to be marked as enabled by @p gwinSetEnabled()
+ * but for this call to return FALSE if one of its parents are not enabled.
+ *
* @param[in] gh The window
*
* @api
@@ -491,6 +529,24 @@ extern "C" {
* @api
*/
void gwinRaise(GHandle gh);
+
+ /**
+ * @brief Get the next window in the z-order
+ * @return The next window or NULL if no more windows
+ *
+ * @param[in] gh The previous window or NULL to get the first window
+ *
+ * @note This returns the next window in the system from top to bottom.
+ * @note Where there are parent child relationships, this ignores them
+ * and will list all windows in the system. There is no defined
+ * order between children of siblings and they can in fact be mixed
+ * in order. The only relationship honored is that parents will be
+ * listed before their children.
+ *
+ * @api
+ */
+ GHandle gwinGetNextWindow(GHandle gh);
+
#endif
#if GDISP_NEED_TEXT || defined(__DOXYGEN__)
@@ -880,7 +936,12 @@ extern "C" {
#include "src/gwin/gwidget.h"
#endif
- /* Include extra window types */
+ /* Include containers */
+ #if GWIN_NEED_CONTAINERS || defined(__DOXYGEN__)
+ #include "src/gwin/gcontainer.h"
+ #endif
+
+ /* Include vanilla window objects */
#if GWIN_NEED_CONSOLE || defined(__DOXYGEN__)
#include "src/gwin/console.h"
#endif
diff --git a/src/gwin/sys_make.mk b/src/gwin/sys_make.mk
index 4c670ea2..95a2ba84 100644
--- a/src/gwin/sys_make.mk
+++ b/src/gwin/sys_make.mk
@@ -11,4 +11,6 @@ GFXSRC += $(GFXLIB)/src/gwin/gwin.c \
$(GFXLIB)/src/gwin/radio.c \
$(GFXLIB)/src/gwin/list.c \
$(GFXLIB)/src/gwin/progressbar.c \
+ $(GFXLIB)/src/gwin/gcontainer.c \
+ $(GFXLIB)/src/gwin/frame.c \
diff --git a/src/gwin/sys_options.h b/src/gwin/sys_options.h
index 41bc551f..39630de0 100644
--- a/src/gwin/sys_options.h
+++ b/src/gwin/sys_options.h
@@ -30,6 +30,13 @@
#define GWIN_NEED_WIDGET FALSE
#endif
/**
+ * @brief Should the widget hierarchy be included. This provides parent-child features.
+ * @details Defaults to FALSE
+ */
+ #ifndef GWIN_NEED_CONTAINERS
+ #define GWIN_NEED_CONTAINERS FALSE
+ #endif
+ /**
* @brief Should widget functions be included. Needed for any widget (eg Buttons, Sliders etc)
* @details Defaults to FALSE
*/
@@ -37,6 +44,20 @@
#define GWIN_NEED_WIDGET FALSE
#endif
/**
+ * @brief Should the simple container be included.
+ * @details Defaults to FALSE
+ */
+ #ifndef GWIN_NEED_CONTAINER
+ #define GWIN_NEED_CONTAINER FALSE
+ #endif
+ /**
+ * @brief Should the frame widget be included.
+ * @details Defaults to FALSE
+ */
+ #ifndef GWIN_NEED_FRAME
+ #define GWIN_NEED_FRAME FALSE
+ #endif
+ /**
* @brief Should console functions be included.
* @details Defaults to FALSE
*/
diff --git a/src/gwin/sys_rules.h b/src/gwin/sys_rules.h
index f9f00a48..ddfea3aa 100644
--- a/src/gwin/sys_rules.h
+++ b/src/gwin/sys_rules.h
@@ -28,6 +28,15 @@
#endif
// Objects require their super-class
+ #if GWIN_NEED_FRAME || GWIN_NEED_CONTAINER
+ #if !GWIN_NEED_CONTAINERS
+ #if GFX_DISPLAY_RULE_WARNINGS
+ #warning "GWIN: GWIN_NEED_CONTAINERS is required when a container is enabled. It has been turned on for you."
+ #endif
+ #undef GWIN_NEED_CONTAINERS
+ #define GWIN_NEED_CONTAINERS TRUE
+ #endif
+ #endif
#if GWIN_NEED_BUTTON || GWIN_NEED_SLIDER || GWIN_NEED_CHECKBOX || GWIN_NEED_LABEL || GWIN_NEED_RADIO || GWIN_NEED_LIST || \
GWIN_NEED_IMAGE || GWIN_NEED_CHECKBOX || GWIN_NEED_PROGRESSBAR
#if !GWIN_NEED_WIDGET
@@ -40,6 +49,15 @@
#endif
// Rules for the super-classes
+ #if GWIN_NEED_CONTAINERS
+ #if !GWIN_NEED_WIDGET
+ #if GFX_DISPLAY_RULE_WARNINGS
+ #warning "GWIN: GWIN_NEED_WIDGET is required when GWIN_NEED_CONTAINERS is enabled. It has been turned on for you."
+ #endif
+ #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."
diff --git a/tools/file2c/src/file2c.c b/tools/file2c/src/file2c.c
index 87ea88e9..079b1a59 100644
--- a/tools/file2c/src/file2c.c
+++ b/tools/file2c/src/file2c.c
@@ -168,7 +168,7 @@ size_t i;
if (opt_inputfile)
opt_arrayname = basenameof(strcpy(tname, opt_inputfile));
if (!opt_arrayname || !opt_arrayname[0]) {
- srand(time(NULL));
+ srand(time(0));
sprintf(tname, "filearray%u", rand());
opt_arrayname = tname;
}