Merge branch 'GWIN'

ugfx_release_2.6
Joel Bodenmann 2013-07-14 20:02:28 +02:00
commit 38a2a44b3d
46 changed files with 5383 additions and 2251 deletions

View File

@ -1730,7 +1730,7 @@ DOT_NUM_THREADS = 0
# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
# directory containing the font.
DOT_FONTNAME = FreeSans
DOT_FONTNAME =
# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
# The default size is 10pt.

View File

@ -28,7 +28,6 @@
*/
#include "gfx.h"
#include "chprintf.h"
static GConsoleObject gc;
static GButtonObject gNext;
@ -39,15 +38,15 @@ static GListener gl;
* GINPUT Touch Driver Calibrator. *
*------------------------------------------------------------------------*/
int main(void) {
GSourceHandle gs, gsNext, gsPrev;
GSourceHandle gs;
GEvent *pe;
GEventMouse *pem;
GEventGWinButton *peb;
coord_t swidth, sheight;
GHandle ghc, ghNext, ghPrev;
BaseSequentialStream *gp;
GEventType deviceType;
font_t font;
GWidgetInit wi;
gfxInit(); // Initialize the display
@ -58,12 +57,13 @@ int main(void) {
// Create our title
font = gdispOpenFont("UI2");
gwinSetDefaultFont(font);
gdispFillStringBox(0, 0, swidth, 20, "Touch Calibration", font, Red, White, justifyLeft);
// Create our main display window
ghc = gwinCreateConsole(&gc, 0, 20, swidth, sheight-20, font);
wi.g.show = TRUE; wi.g.x = 0; wi.g.y = 20; wi.g.width = swidth; wi.g.height = sheight-20;
ghc = gwinConsoleCreate(&gc, &wi.g);
gwinClear(ghc);
gp = gwinGetConsoleStream(ghc);
// Initialize the mouse in our special no calibration mode.
geventListenerInit(&gl);
@ -77,22 +77,22 @@ int main(void) {
StepDeviceType:
gwinClear(ghc);
gwinSetColor(ghc, Yellow);
chprintf(gp, "\n1. DEVICE TYPE\n\n");
gwinPrintf(ghc, "\n1. DEVICE TYPE\n\n");
pem = (GEventMouse *)&gl.event;
ginputGetMouseStatus(0, pem);
deviceType = pem->type;
gwinSetColor(ghc, White);
chprintf(gp, "This is detected as a %s device\n\n",
gwinPrintf(ghc, "This is detected as a %s device\n\n",
deviceType == GEVENT_MOUSE ? "MOUSE" : (pem->type == GEVENT_TOUCH ? "TOUCH" : "UNKNOWN"));
if (ghNext)
chprintf(gp, "Press Next or Back to continue.\n");
gwinPrintf(ghc, "Press Next or Back to continue.\n");
else if (deviceType == GEVENT_MOUSE)
chprintf(gp, "Click the mouse button to move on to the next test.\n");
gwinPrintf(ghc, "Click the mouse button to move on to the next test.\n");
else
chprintf(gp, "Press and release your finger to move on to the next test.\n");
gwinPrintf(ghc, "Press and release your finger to move on to the next test.\n");
while(1) {
pe = geventEventWait(&gl, TIME_INFINITE);
@ -117,23 +117,23 @@ StepDeviceType:
StepRawJitter:
gwinClear(ghc);
gwinSetColor(ghc, Yellow);
chprintf(gp, "\n2. GINPUT_MOUSE_READ_CYCLES\n\n");
gwinPrintf(ghc, "\n2. GINPUT_MOUSE_READ_CYCLES\n\n");
gwinSetColor(ghc, White);
if (deviceType == GEVENT_MOUSE)
chprintf(gp, "Press and hold the mouse button.\n\n");
gwinPrintf(ghc, "Press and hold the mouse button.\n\n");
else
chprintf(gp, "Press and hold on the surface.\n\n");
chprintf(gp, "Numbers will display in this window.\n"
gwinPrintf(ghc, "Press and hold on the surface.\n\n");
gwinPrintf(ghc, "Numbers will display in this window.\n"
"Ensure that values don't jump around very much when your finger is stationary.\n\n"
"Increasing GINPUT_MOUSE_READ_CYCLES helps reduce jitter but increases CPU usage.\n\n");
if (ghNext)
chprintf(gp, "Press Next or Back to continue.\n");
gwinPrintf(ghc, "Press Next or Back to continue.\n");
else if (deviceType == GEVENT_MOUSE)
chprintf(gp, "Release the mouse button to move on to the next test.\n");
gwinPrintf(ghc, "Release the mouse button to move on to the next test.\n");
else
chprintf(gp, "Release your finger to move on to the next test.\n");
gwinPrintf(ghc, "Release your finger to move on to the next test.\n");
// For this test turn on ALL mouse movement events
geventAttachSource(&gl, gs, GLISTEN_MOUSEDOWNMOVES|GLISTEN_MOUSEMETA|GLISTEN_MOUSENOFILTER);
@ -150,7 +150,7 @@ StepRawJitter:
if (pe->type == GEVENT_MOUSE || pe->type == GEVENT_TOUCH) {
pem = (GEventMouse *)pe;
if ((pem->current_buttons & GINPUT_MOUSE_BTN_LEFT))
chprintf(gp, "%u:%u\n", pem->x, pem->y);
gwinPrintf(ghc, "%u:%u\n", pem->x, pem->y);
if (!ghNext && (pem->meta & GMETA_MOUSE_UP))
break;
}
@ -166,19 +166,19 @@ StepRawJitter:
StepCalibrate:
gwinClear(ghc);
gwinSetColor(ghc, Yellow);
chprintf(gp, "\n3. GINPUT_MOUSE_CALIBRATION_ERROR\n\n");
gwinPrintf(ghc, "\n3. GINPUT_MOUSE_CALIBRATION_ERROR\n\n");
gwinSetColor(ghc, Gray);
chprintf(gp, "Ensure GINPUT_MOUSE_NEED_CALIBRATION = TRUE and GINPUT_MOUSE_CALIBRATION_ERROR is >= 0\n\n");
gwinPrintf(ghc, "Ensure GINPUT_MOUSE_NEED_CALIBRATION = TRUE and GINPUT_MOUSE_CALIBRATION_ERROR is >= 0\n\n");
gwinSetColor(ghc, White);
chprintf(gp, "You will be presented with a number of points to touch.\nPress them in turn.\n\n"
gwinPrintf(ghc, "You will be presented with a number of points to touch.\nPress them in turn.\n\n"
"If the calibration repeatedly fails, increase GINPUT_MOUSE_CALIBRATION_ERROR and try again.\n\n");
if (ghNext)
chprintf(gp, "Press Next to start the calibration.\n");
gwinPrintf(ghc, "Press Next to start the calibration.\n");
else if (deviceType == GEVENT_MOUSE)
chprintf(gp, "Click the mouse button to start the calibration.\n");
gwinPrintf(ghc, "Click the mouse button to start the calibration.\n");
else
chprintf(gp, "Press and release your finger to start the calibration.\n");
gwinPrintf(ghc, "Press and release your finger to start the calibration.\n");
while(1) {
pe = geventEventWait(&gl, TIME_INFINITE);
@ -201,37 +201,21 @@ StepCalibrate:
/* From now on we can use Next and Previous Buttons */
if (!ghNext) {
gwinAttachMouse(0);
gwinAttachListener(&gl);
ghNext = gwinCreateButton(&gNext, swidth-50, 0, 50, 20, font, GBTN_NORMAL);
gwinSetButtonText(ghNext, "Next", FALSE);
gsNext = gwinGetButtonSource(ghNext);
geventAttachSource(&gl, gsNext, 0);
gwinAttachButtonMouse(ghNext, 0);
wi.customDraw = 0; wi.customParam = 0; wi.customStyle = 0;
wi.g.show = TRUE; wi.g.x = swidth-50; wi.g.y = 0; wi.g.width = 50; wi.g.height = 20;
wi.text = "Next"; ghNext = gwinButtonCreate(&gNext, &wi);
ghPrev = gwinCreateButton(&gPrev, swidth-100, 0, 50, 20, font, GBTN_NORMAL);
gwinSetButtonText(ghPrev, "Back", FALSE);
gsPrev = gwinGetButtonSource(ghPrev);
geventAttachSource(&gl, gsPrev, 0);
gwinAttachButtonMouse(ghPrev, 0);
#if 0
{
// Attach a couple of hardware toggle buttons to our Next and Back buttons as well.
// We can always use the mouse to trigger the buttons if you don't want to use hardware toggles.
// This code depends on your hardware. Turn it on only if you have
// defined a board definition for your toggle driver. Then change
// the next two lines to be correct for your hardware. The values
// below are correct for the Win32 toggle driver.
gwinAttachButtonToggle(ghNext, GINPUT_TOGGLE_MOMENTARY1);
gwinAttachButtonToggle(ghPrev, GINPUT_TOGGLE_MOMENTARY2);
}
#endif
wi.g.show = TRUE; wi.g.x = swidth-100;
wi.text = "Back"; ghPrev = gwinButtonCreate(&gPrev, &wi);
}
// Calibration used the whole screen - re-establish our title
gdispFillStringBox(0, 0, swidth, 20, "Touch Calibration", font, Green, White, justifyLeft);
gwinButtonDraw(ghNext);
gwinButtonDraw(ghPrev);
gwinRedraw(ghNext);
gwinRedraw(ghPrev);
/*
* Test: Mouse movement jitter
@ -240,18 +224,18 @@ StepCalibrate:
StepJitter:
gwinClear(ghc);
gwinSetColor(ghc, Yellow);
chprintf(gp, "\n4. GINPUT_MOUSE_MOVE_JITTER\n\n");
gwinPrintf(ghc, "\n4. GINPUT_MOUSE_MOVE_JITTER\n\n");
gwinSetColor(ghc, White);
if (deviceType == GEVENT_MOUSE)
chprintf(gp, "Press and hold the mouse button and move around as if to draw.\n\n");
gwinPrintf(ghc, "Press and hold the mouse button and move around as if to draw.\n\n");
else
chprintf(gp, "Press firmly on the surface and move around as if to draw.\n\n");
gwinPrintf(ghc, "Press firmly on the surface and move around as if to draw.\n\n");
chprintf(gp, "Dots will display in this window. Ensure that when you stop moving your finger that "
gwinPrintf(ghc, "Dots will display in this window. Ensure that when you stop moving your finger that "
"new dots stop displaying.\nNew dots should only display when your finger is moving.\n\n"
"Adjust GINPUT_MOUSE_MOVE_JITTER to the smallest value that this reliably works for.\n\n");
chprintf(gp, "Press Next or Back to continue.\n\n");
gwinPrintf(ghc, "Press Next or Back to continue.\n\n");
while(1) {
pe = geventEventWait(&gl, TIME_INFINITE);
@ -265,7 +249,7 @@ StepJitter:
if (pe->type == GEVENT_MOUSE || pe->type == GEVENT_TOUCH) {
pem = (GEventMouse *)pe;
if ((pem->current_buttons & GINPUT_MOUSE_BTN_LEFT))
chprintf(gp, ".");
gwinPrintf(ghc, ".");
}
}
@ -276,16 +260,16 @@ StepJitter:
StepPolling:
gwinClear(ghc);
gwinSetColor(ghc, Yellow);
chprintf(gp, "\n5. GINPUT_MOUSE_POLL_PERIOD\n\n");
gwinPrintf(ghc, "\n5. GINPUT_MOUSE_POLL_PERIOD\n\n");
gwinSetColor(ghc, White);
chprintf(gp, "Press firmly on the surface (or press and hold the mouse button) and move around as if to draw.\n\n");
chprintf(gp, "A green line will follow your finger.\n"
gwinPrintf(ghc, "Press firmly on the surface (or press and hold the mouse button) and move around as if to draw.\n\n");
gwinPrintf(ghc, "A green line will follow your finger.\n"
"Adjust GINPUT_MOUSE_POLL_PERIOD to the highest value that provides a line without "
"gaps that are too big.\nDecreasing the value increases CPU usage.\n"
"About 25 (millisecs) normally produces good results."
"This test can be ignored for interrupt driven drivers.\n\n");
chprintf(gp, "Press Next or Back to continue.\n\n");
gwinPrintf(ghc, "Press Next or Back to continue.\n\n");
while(1) {
pe = geventEventWait(&gl, TIME_INFINITE);
@ -310,18 +294,18 @@ StepPolling:
StepClickJitter:
gwinClear(ghc);
gwinSetColor(ghc, Yellow);
chprintf(gp, "\n6. GINPUT_MOUSE_MAX_CLICK_JITTER\n\n");
gwinPrintf(ghc, "\n6. GINPUT_MOUSE_MAX_CLICK_JITTER\n\n");
gwinSetColor(ghc, White);
chprintf(gp, "Press and release the touch surface to \"click\".\nTry both short and long presses.\n");
chprintf(gp, "For a mouse click with the left and right buttons.\n\n");
chprintf(gp, "Dots will display in this window. A yellow dash is a left (or short) click. "
gwinPrintf(ghc, "Press and release the touch surface to \"click\".\nTry both short and long presses.\n");
gwinPrintf(ghc, "For a mouse click with the left and right buttons.\n\n");
gwinPrintf(ghc, "Dots will display in this window. A yellow dash is a left (or short) click. "
"A red x is a right (or long) click.\n\n"
"Adjust GINPUT_MOUSE_CLICK_JITTER to the smallest value that this reliably works for.\n"
"Adjust GINPUT_MOUSE_CLICK_TIME to adjust distinguishing short vs long presses.\n"
"TIME_INFINITE means there are no long presses (although a right mouse button will still work).\n\n"
"Note: moving your finger (mouse) during a click cancels it.\n\n");
chprintf(gp, "This is the last test but you can press Next or Back to continue.\n\n");
gwinPrintf(ghc, "This is the last test but you can press Next or Back to continue.\n\n");
while(1) {
pe = geventEventWait(&gl, TIME_INFINITE);
@ -336,11 +320,11 @@ StepClickJitter:
pem = (GEventMouse *)pe;
if ((pem->meta & GMETA_MOUSE_CLICK)) {
gwinSetColor(ghc, Yellow);
chprintf(gp, "-");
gwinPrintf(ghc, "-");
}
if ((pem->meta & GMETA_MOUSE_CXTCLICK)) {
gwinSetColor(ghc, Red);
chprintf(gp, "x");
gwinPrintf(ghc, "x");
}
}
}

View File

@ -40,8 +40,14 @@ int main(void) {
gdispClear(Lime);
/* Create two windows */
GW1 = gwinCreateWindow(NULL, 20, 10, 200, 150);
GW2 = gwinCreateWindow(NULL, 50, 190, 150, 100);
{
GWindowInit wi;
wi.show = TRUE; wi.x = 20; wi.y = 10; wi.width = 200; wi.height = 150;
GW1 = gwinWindowCreate(NULL, &wi);
wi.show = TRUE; wi.x = 50; wi.y = 190; wi.width = 150; wi.height = 100;
GW2 = gwinWindowCreate(NULL, &wi);
}
/* Set fore- and background colors for both windows */
gwinSetColor(GW1, Black);
@ -53,9 +59,9 @@ int main(void) {
gwinClear(GW1);
gwinClear(GW2);
gwinDrawLine (GW1, 5, 30, 150, 110);
gwinDrawLine(GW1, 5, 30, 150, 110);
for(i=5, j=0; i < 200 && j < 150; i+=3, j+=i/20)
gwinDrawPixel (GW1, i, j);
gwinDrawPixel(GW1, i, j);
/*
* Draw two filled circles at the same coordinate

View File

@ -28,27 +28,37 @@
*/
#include "gfx.h"
#include "chprintf.h"
/* The handles for our three consoles */
GHandle GW1, GW2, GW3;
/* The streams for our three consoles */
BaseSequentialStream *S1, *S2, *S3;
int main(void) {
uint8_t i;
font_t font1, font2;
/* initialize and clear the display */
gfxInit();
font1 = gdispOpenFont("UI2 Double");
font2 = gdispOpenFont("Small");
/* create the three console windows and set a font for each */
GW1 = gwinCreateConsole(NULL, 0, 0, gdispGetWidth(), gdispGetHeight()/2, font1);
GW2 = gwinCreateConsole(NULL, 0, gdispGetHeight()/2, gdispGetWidth()/2, gdispGetHeight(), font2);
GW3 = gwinCreateConsole(NULL, gdispGetWidth()/2, gdispGetHeight()/2, gdispGetWidth(), gdispGetHeight(), font2);
/* Set some fonts */
font1 = gdispOpenFont("Small");
font2 = gdispOpenFont("UI2 Double");
gwinSetDefaultFont(font1);
/* create the three console windows */
{
GWindowInit wi;
wi.show = TRUE;
wi.x = 0; wi.y = 0; wi.width = gdispGetWidth(); wi.height = gdispGetHeight()/2;
GW1 = gwinConsoleCreate(NULL, &wi);
wi.y = gdispGetHeight()/2; wi.width = gdispGetWidth()/2; wi.height = gdispGetHeight();
GW2 = gwinConsoleCreate(NULL, &wi);
wi.x = gdispGetWidth()/2; wi.height = gdispGetHeight();
GW3 = gwinConsoleCreate(NULL, &wi);
}
/* Use a special font for GW1 */
gwinSetFont(GW1, font2);
/* Set the fore- and background colors for each console */
gwinSetColor(GW1, Green);
@ -63,24 +73,19 @@ int main(void) {
gwinClear(GW2);
gwinClear(GW3);
/* receive the stream pointers of each console */
S1 = gwinGetConsoleStream(GW1);
S2 = gwinGetConsoleStream(GW2);
S3 = gwinGetConsoleStream(GW3);
/* Output some data on the first console */
for(i = 0; i < 10; i++) {
chprintf(S1, "Hello ChibiOS/GFX!\r\n");
gwinPrintf(GW1, "Hello ChibiOS/GFX!\r\n");
}
/* Output some data on the second console */
for(i = 0; i < 16; i++) {
chprintf(S2, "Message Nr.: %d\r\n", i+1);
gwinPrintf(GW2, "Message Nr.: %d\r\n", i+1);
}
/* Output some data on the third console */
for(i = 0; i < 18; i++) {
chprintf(S3, "Message Nr.: %d\r\n", i+1);
gwinPrintf(GW3, "Message Nr.: %d\r\n", i+1);
}
while(TRUE) {

View File

@ -1,97 +0,0 @@
/*
* Copyright (c) 2012, 2013, Joel Bodenmann aka Tectu <joel@unormal.org>
* Copyright (c) 2012, 2013, Andrew Hannam aka inmarket
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the <organization> nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "gfx.h"
#include "chprintf.h"
static GListener gl;
#define SLIDER_WIDTH 20
int main(void) {
coord_t swidth, sheight;
GHandle ghSliderH, ghSliderV, ghConsole;
font_t fui2;
GEvent * pe;
GEventGWinSlider * pSliderEvent;
BaseSequentialStream *consout;
gfxInit(); // Initialize the display
// Get the display dimensions
swidth = gdispGetWidth();
sheight = gdispGetHeight();
// Get the font
fui2 = gdispOpenFont("UI2");
// Create out gwin windows/widgets
ghSliderH = gwinCreateSlider(NULL, 5, 5, swidth-10, SLIDER_WIDTH);
ghSliderV = gwinCreateSlider(NULL, 5, 10+SLIDER_WIDTH, SLIDER_WIDTH, sheight-15+SLIDER_WIDTH);
ghConsole = gwinCreateConsole(NULL, 10+SLIDER_WIDTH, 10+SLIDER_WIDTH, swidth-15-SLIDER_WIDTH, sheight-15-SLIDER_WIDTH, fui2);
consout = gwinGetConsoleStream(ghConsole);
// Color up the console window
gwinSetColor(ghConsole, White);
gwinSetBgColor(ghConsole, Blue);
// Assign the mouse and dials to the sliders.
#if GINPUT_NEED_MOUSE
gwinAttachSliderMouse(ghSliderH, 0);
gwinAttachSliderMouse(ghSliderV, 0);
#endif
#if GINPUT_NEED_DIAL
gwinAttachSliderDial(ghSliderV, 0);
gwinAttachSliderDial(ghSliderH, 1);
#endif
// We want to listen for slider events
geventListenerInit(&gl);
geventAttachSource(&gl, gwinGetSliderSource(ghSliderH), 0);
geventAttachSource(&gl, gwinGetSliderSource(ghSliderV), 0);
// Draw everything on the screen
gwinClear(ghConsole);
gwinSliderDraw(ghSliderH);
gwinSliderDraw(ghSliderV);
while(1) {
// Get an Event
pe = geventEventWait(&gl, TIME_INFINITE);
switch(pe->type) {
case GEVENT_GWIN_SLIDER:
pSliderEvent = (GEventGWinSlider *)pe;
chprintf(consout, "%c=%d\n", pSliderEvent->slider == ghSliderH ? 'H' : 'V', pSliderEvent->position);
break;
}
}
return 0;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

View File

@ -1,7 +1,6 @@
/*
* Copyright (c) 2012, 2013, Joel Bodenmann aka Tectu <joel@unormal.org>
* Copyright (c) 2012, 2013, Andrew Hannam aka inmarket
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -30,10 +29,9 @@
#ifndef _GFXCONF_H
#define _GFXCONF_H
/* The operating system to use - one of these must be defined */
#define GFX_USE_OS_CHIBIOS TRUE
#define GFX_USE_OS_WIN32 FALSE
#define GFX_USE_OS_POSIX FALSE
//#define GFX_USE_OS_WIN32 TRUE
//#define GFX_USE_OS_POSIX TRUE
/* GFX sub-systems to turn on */
#define GFX_USE_GDISP TRUE
@ -46,14 +44,14 @@
#define GDISP_NEED_VALIDATION TRUE
#define GDISP_NEED_CLIP TRUE
#define GDISP_NEED_TEXT TRUE
#define GDISP_NEED_CIRCLE FALSE
#define GDISP_NEED_CIRCLE TRUE
#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_IMAGE FALSE
#define GDISP_NEED_IMAGE TRUE
#define GDISP_NEED_MULTITHREAD TRUE
#define GDISP_NEED_ASYNC FALSE
#define GDISP_NEED_MSGAPI FALSE
@ -67,18 +65,26 @@
/* GDISP image decoders */
#define GDISP_NEED_IMAGE_NATIVE FALSE
#define GDISP_NEED_IMAGE_GIF FALSE
#define GDISP_NEED_IMAGE_GIF TRUE
#define GDISP_NEED_IMAGE_BMP FALSE
#define GDISP_NEED_IMAGE_JPG FALSE
#define GDISP_NEED_IMAGE_PNG FALSE
/* Features for the GWIN sub-system. */
#define GWIN_NEED_BUTTON FALSE
#define GWIN_NEED_WINDOWMANAGER TRUE
#define GWIN_NEED_CONSOLE TRUE
#define GWIN_NEED_GRAPH TRUE
#define GWIN_NEED_WIDGET TRUE
#define GWIN_NEED_BUTTON TRUE
#define GWIN_NEED_SLIDER TRUE
#define GWIN_NEED_CHECKBOX TRUE
#define GWIN_NEED_LABEL TRUE
#define GWIN_NEED_IMAGE TRUE
#define GWIN_NEED_RADIO TRUE
/* Features for the GINPUT sub-system. */
#define GINPUT_NEED_MOUSE TRUE
#define GINPUT_NEED_DIAL TRUE
#define GINPUT_NEED_TOGGLE FALSE
#define GINPUT_NEED_DIAL FALSE
#endif /* _GFXCONF_H */

View File

@ -0,0 +1,637 @@
static const unsigned char image_chibios[] = {
0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x74, 0x00, 0x74, 0x00, 0xE7, 0xFE, 0x00, 0x08, 0x07, 0x02,
0x00, 0x0A, 0x03, 0x08, 0x07, 0x0E, 0x05, 0x0D, 0x00, 0x00, 0x11, 0x02, 0x03, 0x16, 0x01, 0x09,
0x15, 0x00, 0x00, 0x19, 0x03, 0x14, 0x16, 0x06, 0x00, 0x1D, 0x02, 0x07, 0x1C, 0x01, 0x0F, 0x1A,
0x01, 0x2D, 0x12, 0x0F, 0x09, 0x1F, 0x00, 0x1F, 0x18, 0x10, 0x03, 0x22, 0x02, 0x10, 0x1F, 0x00,
0x19, 0x1B, 0x1E, 0x01, 0x26, 0x00, 0x1C, 0x1D, 0x0B, 0x18, 0x21, 0x04, 0x17, 0x20, 0x13, 0x12,
0x24, 0x00, 0x0B, 0x26, 0x01, 0x0A, 0x22, 0x2F, 0x17, 0x22, 0x0E, 0x02, 0x2C, 0x00, 0x0A, 0x2B,
0x00, 0x3B, 0x1A, 0x1A, 0x14, 0x27, 0x0D, 0x11, 0x2A, 0x00, 0x17, 0x2A, 0x06, 0x00, 0x33, 0x00,
0x08, 0x31, 0x00, 0x12, 0x30, 0x00, 0x21, 0x2A, 0x11, 0x23, 0x27, 0x2C, 0x0E, 0x32, 0x0A, 0x1D,
0x2F, 0x01, 0x0D, 0x35, 0x05, 0x07, 0x38, 0x00, 0x18, 0x32, 0x0C, 0x24, 0x2D, 0x1B, 0x2D, 0x2A,
0x21, 0x10, 0x36, 0x00, 0x1F, 0x31, 0x12, 0x18, 0x35, 0x00, 0x16, 0x35, 0x06, 0x20, 0x33, 0x0D,
0x20, 0x32, 0x19, 0x0D, 0x3D, 0x06, 0x15, 0x3B, 0x05, 0x10, 0x3D, 0x00, 0x06, 0x40, 0x00, 0x23,
0x34, 0x3B, 0x1F, 0x3B, 0x0E, 0x2C, 0x36, 0x1A, 0x49, 0x2D, 0x22, 0x3F, 0x31, 0x1F, 0x1F, 0x3D,
0x08, 0x1B, 0x3F, 0x01, 0x15, 0x41, 0x03, 0x21, 0x3E, 0x02, 0x12, 0x43, 0x00, 0x1A, 0x40, 0x0B,
0x28, 0x3B, 0x16, 0x29, 0x3C, 0x10, 0x2F, 0x38, 0x2C, 0x22, 0x3E, 0x17, 0x2F, 0x39, 0x25, 0x29,
0x3C, 0x1F, 0x38, 0x37, 0x3A, 0x11, 0x48, 0x08, 0x14, 0x48, 0x00, 0x0C, 0x4B, 0x03, 0x1A, 0x47,
0x09, 0x1D, 0x47, 0x01, 0x23, 0x46, 0x12, 0x12, 0x4E, 0x00, 0x1B, 0x4C, 0x00, 0x25, 0x48, 0x0B,
0x1A, 0x4D, 0x05, 0x1F, 0x4C, 0x0E, 0x22, 0x4C, 0x06, 0x33, 0x46, 0x1A, 0x2E, 0x47, 0x21, 0x0D,
0x54, 0x02, 0x37, 0x43, 0x2F, 0x2A, 0x4C, 0x06, 0x39, 0x44, 0x2A, 0x18, 0x52, 0x01, 0x17, 0x53,
0x0B, 0x31, 0x4A, 0x1D, 0x20, 0x52, 0x0B, 0x38, 0x48, 0x28, 0x34, 0x49, 0x2E, 0x1B, 0x55, 0x04,
0x16, 0x58, 0x00, 0x25, 0x52, 0x14, 0x25, 0x54, 0x04, 0x14, 0x59, 0x07, 0x1F, 0x57, 0x00, 0x29,
0x53, 0x0E, 0x2F, 0x51, 0x15, 0x3C, 0x49, 0x41, 0x1F, 0x58, 0x07, 0x2F, 0x51, 0x1E, 0x25, 0x57,
0x10, 0x1C, 0x5C, 0x01, 0x13, 0x60, 0x03, 0x44, 0x4C, 0x3A, 0x1B, 0x5D, 0x0D, 0x47, 0x4A, 0x4D,
0x5A, 0x47, 0x3C, 0x24, 0x5C, 0x0D, 0x27, 0x5D, 0x03, 0x20, 0x60, 0x05, 0x1B, 0x64, 0x00, 0x1A,
0x64, 0x09, 0x3E, 0x51, 0x5D, 0x25, 0x62, 0x00, 0x2F, 0x5D, 0x18, 0x41, 0x55, 0x36, 0x42, 0x52,
0x52, 0x31, 0x5E, 0x10, 0x32, 0x5C, 0x21, 0x24, 0x63, 0x0A, 0x40, 0x5B, 0x19, 0x2C, 0x63, 0x15,
0x3C, 0x5E, 0x1A, 0x4C, 0x56, 0x3C, 0x19, 0x6B, 0x05, 0x4D, 0x56, 0x43, 0x1F, 0x69, 0x0F, 0x24,
0x6A, 0x05, 0x7D, 0x49, 0x47, 0x51, 0x59, 0x33, 0x4C, 0x58, 0x4F, 0x2D, 0x6A, 0x06, 0x5B, 0x55,
0x52, 0x2C, 0x6A, 0x12, 0x44, 0x61, 0x2C, 0x23, 0x70, 0x00, 0x20, 0x71, 0x0D, 0x34, 0x6A, 0x18,
0x3B, 0x68, 0x19, 0x2A, 0x6F, 0x0D, 0x3D, 0x69, 0x25, 0x44, 0x68, 0x2B, 0x20, 0x79, 0x0A, 0x2A,
0x77, 0x09, 0x30, 0x75, 0x14, 0x58, 0x64, 0x48, 0x4F, 0x68, 0x42, 0x34, 0x77, 0x0A, 0x55, 0x64,
0x67, 0x3B, 0x73, 0x1F, 0x3A, 0x75, 0x15, 0x53, 0x68, 0x4D, 0x5C, 0x65, 0x5C, 0x61, 0x66, 0x54,
0x49, 0x72, 0x30, 0x2D, 0x7F, 0x05, 0x2D, 0x7E, 0x12, 0x4A, 0x77, 0x29, 0x58, 0x72, 0x4A, 0x3D,
0x81, 0x22, 0x48, 0x80, 0x2A, 0x62, 0x74, 0x5A, 0x61, 0x75, 0x6D, 0x6C, 0x73, 0x62, 0x5F, 0x75,
0x76, 0x55, 0x7F, 0x3C, 0x6E, 0x73, 0x6D, 0x72, 0x75, 0x7C, 0x56, 0x8D, 0x2F, 0x46, 0x92, 0x30,
0x54, 0x8D, 0x3B, 0x62, 0x89, 0x3F, 0x7A, 0x81, 0x73, 0x7B, 0x82, 0x6C, 0x6F, 0x89, 0x5D, 0x76,
0x86, 0x6B, 0x76, 0x85, 0x89, 0x69, 0x8F, 0x50, 0x7C, 0x87, 0x82, 0x6E, 0x95, 0x4C, 0x82, 0x93,
0x8D, 0x7B, 0x96, 0x84, 0x8C, 0x92, 0x7C, 0x67, 0xA2, 0x4F, 0x8B, 0x93, 0x84, 0x81, 0x96, 0x9B,
0x87, 0x98, 0x79, 0x8D, 0x93, 0x99, 0x91, 0xA5, 0x84, 0x90, 0xA3, 0x9C, 0xA1, 0x9F, 0x95, 0x89,
0xAB, 0x6D, 0x9B, 0xA4, 0x96, 0x91, 0xA7, 0xA6, 0x8F, 0xA8, 0xB0, 0xA2, 0xA7, 0x91, 0xA0, 0xA6,
0xB1, 0xAA, 0xB1, 0xA1, 0x9F, 0xB7, 0xA7, 0xA6, 0xB4, 0xBB, 0xA2, 0xB8, 0xB0, 0x9C, 0xB9, 0xBE,
0xA8, 0xB9, 0x9B, 0xB2, 0xB7, 0x9D, 0xBC, 0xB7, 0xB5, 0xC2, 0xC0, 0xA5, 0xAD, 0xC7, 0xC4, 0xA4,
0xC9, 0xD5, 0xC1, 0xC4, 0xB7, 0xBD, 0xC7, 0xB3, 0xAB, 0xCA, 0xCD, 0xB7, 0xCC, 0xB2, 0xBD, 0xCB,
0xD5, 0xC9, 0xCD, 0xCB, 0xC8, 0xD3, 0xAD, 0xBB, 0xD6, 0xD2, 0xAF, 0xDC, 0xE4, 0xBE, 0xD9, 0xE2,
0xC7, 0xDA, 0xC1, 0xD3, 0xD6, 0xC8, 0xD0, 0xDA, 0xC5, 0xCA, 0xD9, 0xE6, 0xDE, 0xDD, 0xC0, 0xD6,
0xE5, 0xDF, 0xD9, 0xE5, 0xF2, 0xDF, 0xEA, 0xD3, 0xC5, 0xEF, 0xF4, 0xDC, 0xEA, 0xEA, 0xE7, 0xE9,
0xD9, 0xD3, 0xED, 0xF5, 0xEA, 0xE8, 0xEC, 0xEB, 0xEC, 0xE9, 0xE6, 0xF2, 0xFC, 0xF6, 0xF4, 0xEB,
0xF0, 0xFA, 0xDA, 0xEC, 0xFB, 0xFB, 0xFA, 0xF7, 0xFC, 0xF2, 0xFC, 0xE3, 0xF7, 0xF9, 0xF5, 0xF3,
0xFE, 0xEB, 0xFF, 0xFB, 0xFA, 0xFA, 0xFE, 0xEC, 0xFB, 0xFD, 0xF9, 0xF5, 0xFF, 0xFA, 0xF8, 0xFF,
0xF4, 0xF9, 0xFE, 0xFF, 0xFF, 0xFE, 0xF5, 0xFF, 0xFD, 0xFF, 0xFD, 0xFF, 0xFC, 0x2C, 0x00, 0x00,
0x00, 0x00, 0x74, 0x00, 0x74, 0x00, 0x00, 0x08, 0xFE, 0x00, 0xFF, 0xFD, 0xF3, 0xE7, 0x4F, 0xA0,
0x40, 0x82, 0xFE, 0xF8, 0xC9, 0x93, 0xF7, 0xEF, 0x5E, 0xC1, 0x7C, 0xFC, 0xFE, 0xE9, 0x3B, 0x88,
0xB0, 0x5F, 0xBF, 0x81, 0x06, 0x33, 0x6A, 0xDC, 0x48, 0x11, 0x21, 0xC7, 0x8C, 0x08, 0x43, 0x8A,
0x2C, 0xD8, 0x51, 0xE4, 0xC7, 0x93, 0x1C, 0x23, 0x7A, 0xA4, 0xF8, 0x8F, 0x9F, 0xCB, 0x86, 0x04,
0xF9, 0x4D, 0xFC, 0x57, 0x6F, 0xE0, 0x4A, 0x94, 0x38, 0x73, 0x6A, 0x2C, 0x48, 0xD2, 0x60, 0x48,
0x90, 0x23, 0x7B, 0xEA, 0x44, 0xF9, 0x53, 0x60, 0x3E, 0x81, 0xFC, 0xF2, 0xDD, 0x73, 0xE8, 0xEF,
0xDE, 0x3F, 0x8B, 0x30, 0x85, 0x0E, 0xD5, 0x18, 0x91, 0xE3, 0xC8, 0xA9, 0x58, 0xB3, 0x66, 0x9C,
0x68, 0xF2, 0x68, 0xD4, 0xA5, 0x4E, 0x9F, 0xDA, 0xB3, 0xD7, 0x8F, 0x69, 0x55, 0xAD, 0x27, 0x83,
0x4A, 0x35, 0xE8, 0xF2, 0x2C, 0xDA, 0xB7, 0x25, 0x0D, 0x2E, 0x6D, 0x9A, 0x11, 0xDF, 0xB8, 0x6E,
0xE8, 0x2E, 0xC6, 0x3C, 0x08, 0xF7, 0x23, 0xC9, 0x97, 0x7D, 0xAD, 0xAE, 0xD5, 0x4A, 0xD0, 0x60,
0xCD, 0x7C, 0x47, 0xBD, 0x62, 0x33, 0x02, 0xC1, 0xC3, 0x0D, 0x6D, 0x17, 0x5B, 0xFA, 0x1C, 0x9C,
0xF6, 0x66, 0x60, 0xAC, 0x85, 0x2F, 0x03, 0x7E, 0x6A, 0x71, 0x9F, 0xBE, 0xCF, 0x05, 0x44, 0xF4,
0xE8, 0x21, 0xC2, 0xC2, 0x38, 0xB6, 0x72, 0x29, 0x6F, 0xBC, 0xBA, 0xDA, 0xB2, 0xE0, 0xAB, 0xAA,
0xFB, 0x66, 0x6E, 0x59, 0xB5, 0x9F, 0x8A, 0x01, 0x04, 0x3A, 0x64, 0xD9, 0x37, 0xAB, 0xC1, 0x24,
0x48, 0x63, 0xCC, 0x5C, 0xC0, 0xC1, 0x57, 0xE0, 0xDC, 0xA1, 0x57, 0x37, 0xDB, 0x9C, 0x8D, 0xF4,
0xAC, 0xDA, 0xA2, 0x97, 0x81, 0xB2, 0xAD, 0xEA, 0xA6, 0xC1, 0x0E, 0x1E, 0x40, 0x0E, 0x60, 0xFA,
0x95, 0x22, 0xD4, 0x2B, 0x48, 0x7C, 0x76, 0xFE, 0x28, 0xD8, 0x67, 0xD3, 0x28, 0x73, 0x83, 0x89,
0x77, 0x86, 0x8C, 0xE8, 0x36, 0xE3, 0x3E, 0x7C, 0xFB, 0x3C, 0xD3, 0x6E, 0x5B, 0xF5, 0x28, 0x41,
0xA6, 0x09, 0x41, 0x1E, 0xAD, 0xF9, 0x76, 0x76, 0x55, 0x7C, 0x10, 0x9C, 0xD1, 0x85, 0x16, 0x5D,
0xB0, 0xF0, 0x81, 0x36, 0x05, 0xC8, 0x72, 0xCA, 0x2B, 0x7C, 0xB8, 0xD0, 0xC0, 0x45, 0x4E, 0x79,
0xE5, 0xD5, 0x49, 0x12, 0x7A, 0x55, 0x9F, 0x40, 0x13, 0xF5, 0x13, 0xDF, 0x38, 0xCC, 0xD8, 0x12,
0x04, 0x11, 0x29, 0x5C, 0x90, 0x80, 0x02, 0x31, 0x5C, 0x81, 0xC6, 0x27, 0xC7, 0x88, 0xB3, 0x8F,
0x86, 0x91, 0xFD, 0xB3, 0x9F, 0x57, 0xCC, 0x4D, 0x98, 0x95, 0x54, 0x05, 0x81, 0xD2, 0x00, 0x29,
0x8A, 0x28, 0x52, 0x46, 0x1E, 0x1E, 0xE0, 0x33, 0x82, 0x0F, 0xA4, 0x8C, 0x31, 0xC5, 0x0D, 0x0B,
0x90, 0x07, 0x15, 0x44, 0xED, 0x65, 0x74, 0x18, 0x47, 0xFA, 0x68, 0x68, 0xCF, 0x38, 0x98, 0xE0,
0x10, 0x44, 0x03, 0x0F, 0xA4, 0x20, 0xC2, 0x03, 0x12, 0x84, 0xC0, 0xC2, 0x0C, 0x40, 0x9C, 0x70,
0xC2, 0x0B, 0x25, 0x5C, 0x70, 0x40, 0x01, 0x0D, 0xE8, 0x86, 0x09, 0x36, 0x1A, 0xBA, 0xB8, 0x51,
0x4D, 0xF5, 0xC8, 0x08, 0x97, 0x47, 0x6E, 0x08, 0x41, 0xCA, 0x2B, 0x92, 0x94, 0x81, 0x85, 0x09,
0xF1, 0xD0, 0x53, 0x80, 0x0F, 0x53, 0xF0, 0xF0, 0xC1, 0x02, 0xFD, 0xCC, 0x92, 0x41, 0x00, 0x6E,
0xF4, 0x03, 0x51, 0x4E, 0x32, 0x6A, 0xB8, 0x8F, 0x36, 0x99, 0xDC, 0x70, 0xC1, 0x05, 0x21, 0xF0,
0x20, 0x85, 0x18, 0x94, 0x4A, 0x11, 0x45, 0x17, 0x98, 0x66, 0xBA, 0x44, 0x0F, 0x34, 0x60, 0xF7,
0xC2, 0x06, 0x0F, 0x8C, 0xA8, 0x40, 0x06, 0xBF, 0xC4, 0x17, 0x19, 0x7F, 0xD1, 0xF1, 0x55, 0x18,
0x28, 0x10, 0xE0, 0xC2, 0x09, 0x24, 0xFE, 0x69, 0x60, 0x01, 0x01, 0x35, 0xF1, 0x50, 0x21, 0x81,
0x0C, 0x33, 0x18, 0xA0, 0xCC, 0x35, 0x03, 0x64, 0xA2, 0x06, 0x01, 0x57, 0x60, 0x44, 0x21, 0x7F,
0x47, 0x59, 0xE4, 0xE1, 0x05, 0x2C, 0x4C, 0x31, 0x06, 0x24, 0x7E, 0x34, 0x0B, 0x06, 0x18, 0x98,
0x3A, 0xE1, 0x84, 0x16, 0x69, 0xC8, 0x01, 0x86, 0x16, 0x5A, 0x3C, 0x31, 0x46, 0x14, 0x49, 0x6C,
0x8A, 0x02, 0x0B, 0x1B, 0x5C, 0xD0, 0x40, 0x01, 0x0A, 0x5C, 0x81, 0x66, 0x8B, 0x46, 0xA5, 0x8A,
0x51, 0x3F, 0x0B, 0x78, 0x70, 0x86, 0x18, 0x4B, 0xF8, 0x60, 0x01, 0x0E, 0xF1, 0xA4, 0xF0, 0xC0,
0x0C, 0x23, 0xD2, 0x23, 0x08, 0x0C, 0x8D, 0x50, 0xF2, 0xEB, 0x31, 0x0E, 0x71, 0xE4, 0xE6, 0x3F,
0xFB, 0xEC, 0x7B, 0xC1, 0x0C, 0x81, 0x00, 0x32, 0x87, 0x1F, 0x75, 0x18, 0xC2, 0x46, 0x18, 0x74,
0xA4, 0x21, 0xED, 0xB4, 0x60, 0xB0, 0x41, 0x07, 0x1B, 0x5A, 0x28, 0x31, 0x6D, 0x1A, 0x69, 0x60,
0x1A, 0x05, 0x0D, 0x34, 0xB0, 0xC0, 0xC2, 0x0B, 0x0D, 0x10, 0x40, 0xC0, 0x02, 0xC7, 0x5C, 0x84,
0xEA, 0xC0, 0xC8, 0xAD, 0xE5, 0x4E, 0xA0, 0x7A, 0x28, 0xE0, 0xC1, 0x0B, 0x2F, 0x28, 0x60, 0x41,
0x01, 0x25, 0x6C, 0x70, 0x40, 0x38, 0xF4, 0x58, 0x27, 0x8B, 0x2C, 0xAC, 0x98, 0x60, 0x80, 0x6A,
0x4B, 0xFE, 0xD3, 0x8A, 0x02, 0x33, 0xAC, 0x11, 0x0B, 0x20, 0xD8, 0xA6, 0xC1, 0xC6, 0xD3, 0x61,
0x58, 0x11, 0x46, 0xB5, 0x5A, 0x80, 0x51, 0x6D, 0x1A, 0x56, 0x6F, 0xB1, 0x85, 0x12, 0x4A, 0x68,
0xCD, 0xF1, 0xB3, 0x49, 0x24, 0xD1, 0xC3, 0x0C, 0x22, 0xA4, 0x00, 0x81, 0x01, 0x03, 0x0C, 0x31,
0xCD, 0x64, 0xFD, 0xE5, 0xD7, 0xA4, 0x45, 0x91, 0x69, 0xD8, 0xC1, 0x05, 0x37, 0xB8, 0x10, 0x02,
0x97, 0x27, 0x48, 0xE0, 0x41, 0xFE, 0x13, 0x09, 0x48, 0x61, 0x46, 0x24, 0x66, 0x88, 0xD0, 0x41,
0x4E, 0xFD, 0x60, 0xD3, 0x01, 0x04, 0xB5, 0x70, 0xC2, 0x48, 0x18, 0x61, 0xB0, 0x41, 0x06, 0x19,
0x6F, 0x00, 0x42, 0x86, 0xB5, 0x69, 0xBC, 0x51, 0xB5, 0x16, 0xDC, 0x86, 0x5D, 0xC3, 0xE6, 0x9C,
0xFF, 0xE0, 0x84, 0xD5, 0xD8, 0x42, 0x2B, 0xC5, 0x12, 0x3B, 0x78, 0xF0, 0x41, 0x0B, 0x01, 0x0C,
0xF0, 0x8B, 0x71, 0x85, 0xF1, 0x34, 0x55, 0x53, 0x49, 0x11, 0x4C, 0x8F, 0x1E, 0x2D, 0x74, 0x40,
0x88, 0x86, 0xF8, 0x3C, 0xC0, 0xC2, 0x12, 0x97, 0x76, 0x21, 0xB6, 0x06, 0x1A, 0xD0, 0x30, 0x45,
0x14, 0x79, 0x48, 0x11, 0xC2, 0x03, 0x2B, 0x22, 0x25, 0x10, 0xAA, 0xFB, 0xD8, 0x72, 0xC0, 0x12,
0xC6, 0x30, 0xCB, 0xC6, 0xB5, 0x56, 0x58, 0x41, 0x86, 0x1F, 0x6F, 0xC8, 0x81, 0x75, 0xD6, 0x3F,
0x2C, 0x21, 0x03, 0xF0, 0x21, 0xD0, 0x90, 0x04, 0xD7, 0x35, 0xA0, 0x60, 0x7E, 0x12, 0x72, 0x68,
0x9F, 0x7E, 0x1A, 0x51, 0xF4, 0xC0, 0x42, 0x08, 0x1B, 0xA4, 0xD0, 0xC0, 0x00, 0xB3, 0xD8, 0xC7,
0x5A, 0x6B, 0x1F, 0xF5, 0x43, 0x4F, 0x10, 0x0F, 0xC0, 0x5F, 0x40, 0x01, 0xA0, 0xF0, 0xC4, 0x03,
0x7A, 0x10, 0x05, 0x6C, 0x59, 0xE1, 0x59, 0x9B, 0xE2, 0xC1, 0x0C, 0x78, 0xA0, 0xC0, 0x0B, 0xB4,
0x80, 0x2C, 0x18, 0x39, 0x4B, 0xE1, 0x3E, 0xF0, 0x82, 0x3C, 0x70, 0x42, 0x11, 0x86, 0xA0, 0x43,
0x18, 0xA8, 0x95, 0x86, 0xC7, 0x91, 0xE1, 0x59, 0x63, 0x18, 0x83, 0xEF, 0x6A, 0x40, 0x03, 0x0D,
0x68, 0x69, 0x06, 0x3D, 0xE0, 0xDD, 0xB3, 0xB6, 0x10, 0x05, 0x26, 0xD0, 0xA0, 0x06, 0x5A, 0x20,
0x03, 0xE3, 0xB4, 0x20, 0x2D, 0x6E, 0xF5, 0x00, 0x04, 0x33, 0x08, 0x17, 0xA1, 0xA2, 0x12, 0x92,
0x7B, 0x0C, 0x8C, 0x39, 0xFE, 0x24, 0x89, 0x8F, 0x11, 0x24, 0xD0, 0x83, 0x1A, 0x20, 0x61, 0x06,
0x12, 0x38, 0x40, 0xFF, 0x92, 0xC0, 0x31, 0x3A, 0xD0, 0x81, 0x0C, 0x5A, 0x58, 0xC2, 0x0C, 0x52,
0xF0, 0x01, 0x0B, 0x10, 0x60, 0x00, 0x45, 0x10, 0x87, 0x45, 0xEA, 0x11, 0x93, 0x26, 0xE1, 0xA3,
0x05, 0x0A, 0x08, 0x41, 0x2C, 0x3A, 0xE1, 0x07, 0x46, 0x3C, 0xAC, 0x0C, 0x73, 0x80, 0xDA, 0x01,
0xD3, 0x30, 0x06, 0x26, 0xF0, 0xC0, 0x6E, 0x28, 0x48, 0x02, 0x12, 0x96, 0x40, 0xC7, 0x24, 0x44,
0x01, 0x0C, 0x8F, 0x4B, 0xC3, 0x16, 0x7C, 0xE7, 0x39, 0x32, 0x3C, 0xED, 0x83, 0xD8, 0xE2, 0x16,
0xC8, 0x58, 0x70, 0x03, 0x18, 0x10, 0x60, 0x02, 0xEB, 0x18, 0x08, 0x7E, 0x06, 0x03, 0xC4, 0xA4,
0xEC, 0xC3, 0x1E, 0x1E, 0x98, 0x41, 0x17, 0xAE, 0x25, 0x36, 0x20, 0xB0, 0xA0, 0x07, 0x5D, 0x90,
0x83, 0xC5, 0xDA, 0x40, 0x06, 0x25, 0x2C, 0x41, 0x04, 0x05, 0x58, 0x80, 0x0A, 0x7E, 0x21, 0x8E,
0x74, 0x09, 0x6B, 0x1F, 0xE8, 0xA8, 0xC2, 0x05, 0xCC, 0x70, 0x41, 0x3C, 0x64, 0xD0, 0x8F, 0x69,
0x0C, 0xC3, 0xB3, 0xA8, 0x56, 0x03, 0xF8, 0x89, 0x80, 0x07, 0x49, 0xD0, 0xDA, 0x1E, 0xB7, 0x70,
0x35, 0x0E, 0x66, 0x6C, 0x0B, 0x4E, 0xB0, 0xC2, 0x1B, 0xDA, 0xD0, 0x06, 0xEC, 0x5D, 0x2B, 0x0A,
0x51, 0xF8, 0x41, 0x0D, 0xC4, 0x30, 0x83, 0x17, 0x98, 0x20, 0x94, 0xA5, 0x64, 0x5D, 0xC0, 0xD4,
0x03, 0x92, 0x79, 0x10, 0x2C, 0x1A, 0x0D, 0x90, 0x82, 0x1C, 0xEC, 0xD0, 0x06, 0x40, 0x44, 0x01,
0x05, 0x52, 0xC8, 0x24, 0x23, 0xCC, 0x38, 0xB5, 0x28, 0x00, 0xE1, 0x02, 0x46, 0x18, 0x07, 0x79,
0x5C, 0x72, 0x9F, 0x84, 0xF0, 0xA3, 0x1F, 0xA8, 0xB8, 0xC0, 0x12, 0xE4, 0xC0, 0x88, 0x39, 0xD0,
0xC1, 0x0F, 0xC4, 0xFE, 0x2C, 0x44, 0x18, 0x3C, 0xA8, 0x47, 0x24, 0xD4, 0x00, 0x04, 0xE2, 0x0B,
0xDB, 0xE7, 0xC8, 0x60, 0x05, 0x2D, 0x58, 0xEF, 0x0D, 0x6F, 0x48, 0x03, 0x07, 0xA5, 0x55, 0xBD,
0x30, 0x10, 0x73, 0x83, 0xD9, 0x7A, 0xC2, 0x13, 0xC0, 0x30, 0xAD, 0x1F, 0xAC, 0x61, 0x09, 0x21,
0xF0, 0x80, 0x02, 0x46, 0x90, 0x3C, 0xD6, 0xE1, 0x8F, 0x6D, 0xEF, 0x69, 0xC0, 0x19, 0x00, 0xC1,
0x88, 0x4B, 0x90, 0x22, 0x0F, 0x7D, 0x98, 0x41, 0x08, 0xCC, 0x20, 0x07, 0x4E, 0xD0, 0x81, 0x86,
0x4B, 0x78, 0x41, 0x02, 0xC8, 0x43, 0x9B, 0x96, 0x78, 0x64, 0x1F, 0x59, 0x28, 0x80, 0x19, 0x00,
0xF1, 0x30, 0x30, 0xDC, 0xB3, 0x0D, 0x86, 0x68, 0xC3, 0x1A, 0xBB, 0xF0, 0x03, 0xF3, 0xA1, 0xE0,
0x52, 0x55, 0xAB, 0x5C, 0xC6, 0x18, 0xC7, 0xD4, 0xA7, 0x5D, 0xEC, 0x61, 0x8C, 0x6B, 0x43, 0xC3,
0xDA, 0xB0, 0x41, 0x27, 0x84, 0xED, 0x09, 0xE9, 0xA3, 0x43, 0x41, 0x93, 0x10, 0xB2, 0x0B, 0x40,
0x60, 0x00, 0x2B, 0x8A, 0xCC, 0x5A, 0x80, 0x58, 0x90, 0x7E, 0xAC, 0xA3, 0x03, 0x2F, 0x60, 0x05,
0x29, 0x9E, 0x10, 0x0A, 0x11, 0x10, 0xA0, 0x00, 0x30, 0xB8, 0x00, 0x08, 0x18, 0x41, 0xD1, 0x24,
0x00, 0x61, 0x03, 0x1D, 0xA0, 0x29, 0x7F, 0xE8, 0xD3, 0x0F, 0x2F, 0x5C, 0x80, 0x0F, 0xE4, 0x7C,
0x9C, 0x26, 0xFD, 0x60, 0x07, 0x3B, 0xF8, 0xA1, 0x0B, 0x3D, 0x08, 0x81, 0x06, 0x60, 0x38, 0x4E,
0x0D, 0xCA, 0x12, 0x0C, 0x5B, 0xC0, 0x16, 0xC4, 0xEC, 0x50, 0x87, 0x3A, 0x38, 0xE2, 0xB2, 0x8E,
0x30, 0x84, 0x21, 0x1A, 0x76, 0xD9, 0xCA, 0xDA, 0x21, 0x0C, 0x13, 0x4B, 0x03, 0xE3, 0x5E, 0xDA,
0xAD, 0x26, 0x88, 0x20, 0x08, 0x0B, 0x18, 0x00, 0x3E, 0x54, 0x36, 0x15, 0xA7, 0xF4, 0x63, 0x1C,
0x05, 0x70, 0xFE, 0x17, 0x14, 0xC8, 0x04, 0x1F, 0x7C, 0x0C, 0x43, 0x02, 0x90, 0x78, 0x02, 0x57,
0x6B, 0x96, 0xD7, 0x8C, 0x58, 0xE8, 0x1F, 0x59, 0xB8, 0x40, 0x24, 0x3A, 0x51, 0x59, 0xC6, 0x59,
0xCF, 0x89, 0xF7, 0x5C, 0x43, 0x0F, 0x36, 0xA0, 0x01, 0x26, 0xA4, 0x01, 0x9F, 0x75, 0x68, 0x83,
0xC5, 0xA6, 0x57, 0x35, 0xE4, 0xFA, 0xC1, 0x10, 0x96, 0x10, 0x85, 0x76, 0x45, 0x61, 0x89, 0xEE,
0x5A, 0x62, 0x14, 0xDD, 0x7D, 0x84, 0x24, 0xA8, 0xCA, 0x54, 0x3F, 0xB0, 0xC1, 0x09, 0xEC, 0x93,
0x01, 0x0F, 0x9A, 0x40, 0x04, 0x0B, 0x28, 0xA0, 0x48, 0xE8, 0x42, 0xC9, 0x4C, 0x0C, 0x52, 0xB0,
0x50, 0x6A, 0x23, 0x79, 0xC7, 0x30, 0x00, 0x14, 0x10, 0xDB, 0xCC, 0x71, 0x11, 0x22, 0xAC, 0x70,
0xD3, 0x10, 0x33, 0x16, 0x30, 0x83, 0xE1, 0x4A, 0x42, 0x12, 0x41, 0x15, 0xEA, 0xC5, 0x38, 0xD6,
0x05, 0x20, 0x48, 0x00, 0x05, 0x6B, 0x90, 0xC3, 0x1B, 0x20, 0xC6, 0x86, 0xCA, 0xD6, 0xC1, 0x89,
0x5A, 0x58, 0x58, 0x19, 0x4B, 0x7A, 0x89, 0x51, 0x6C, 0xD7, 0xBB, 0x1F, 0x1E, 0xC5, 0x23, 0x1E,
0xB1, 0x59, 0x0B, 0x6B, 0x10, 0x73, 0x53, 0x90, 0x82, 0x1A, 0x5E, 0x70, 0x03, 0x0F, 0x14, 0x20,
0x03, 0x34, 0x45, 0xCA, 0x43, 0x36, 0xF2, 0x19, 0xF4, 0x10, 0x0C, 0x1F, 0x38, 0xDE, 0x07, 0x33,
0x06, 0x60, 0x80, 0x20, 0x84, 0x93, 0x74, 0x1F, 0x30, 0x40, 0x0C, 0xC2, 0xF1, 0x1E, 0x66, 0x08,
0x42, 0x05, 0x06, 0x48, 0xB2, 0x02, 0x24, 0xD0, 0x05, 0x4E, 0x48, 0xA2, 0x61, 0x78, 0xA0, 0xAC,
0xC3, 0x36, 0xF8, 0x4D, 0x09, 0x2C, 0x61, 0x0D, 0x6F, 0x90, 0xA1, 0x1F, 0xE9, 0x50, 0x08, 0xA7,
0xA6, 0x61, 0x0E, 0x72, 0x80, 0x04, 0x20, 0xD6, 0xC0, 0x84, 0x3B, 0xF2, 0xB4, 0x10, 0x8A, 0x83,
0x44, 0xFE, 0x27, 0xB0, 0xFB, 0xDD, 0x4B, 0x74, 0x17, 0xBC, 0x8E, 0x20, 0x71, 0x06, 0x15, 0x6A,
0x43, 0x28, 0x8C, 0xCC, 0xC5, 0xAA, 0xB8, 0xC8, 0xA1, 0x92, 0xB4, 0x91, 0x79, 0x04, 0x11, 0x1D,
0xB3, 0x2B, 0x00, 0x10, 0xFA, 0x10, 0x0A, 0x39, 0x68, 0x01, 0x5C, 0x1F, 0xF8, 0x9F, 0x02, 0x08,
0xA0, 0x80, 0x07, 0x3C, 0xE0, 0x02, 0x55, 0xAC, 0x42, 0x08, 0xBA, 0x50, 0x61, 0xCD, 0x4A, 0xB7,
0x59, 0x8A, 0xC0, 0xC3, 0xD4, 0xDE, 0x57, 0x03, 0x46, 0xF8, 0x61, 0x9F, 0x08, 0x8D, 0x61, 0xE8,
0xB4, 0xE6, 0xCD, 0xEC, 0x0C, 0x40, 0x37, 0x10, 0x50, 0x80, 0x98, 0xFE, 0x77, 0x01, 0x11, 0xEC,
0xB4, 0x9E, 0xD7, 0x75, 0x84, 0x28, 0x2A, 0x41, 0x6B, 0x47, 0x0C, 0xA2, 0x10, 0x6F, 0xB8, 0x96,
0x16, 0xB6, 0xC0, 0xD5, 0xFE, 0x16, 0x20, 0xC6, 0x44, 0xE9, 0xA1, 0x41, 0xEC, 0x11, 0x0D, 0x02,
0x2C, 0x81, 0x13, 0x12, 0x66, 0x83, 0x12, 0x6A, 0xD0, 0x83, 0x1D, 0x38, 0x5B, 0x04, 0x33, 0x88,
0xF6, 0x09, 0x44, 0x40, 0xED, 0x10, 0x44, 0x21, 0x0C, 0x9A, 0xAD, 0x03, 0x1B, 0x84, 0xD9, 0xAC,
0xA7, 0xC9, 0x21, 0x09, 0x12, 0xA0, 0x81, 0x1F, 0x24, 0x81, 0xB1, 0xAA, 0x69, 0x0F, 0x5A, 0x4A,
0x08, 0x1B, 0x12, 0x68, 0xF0, 0x80, 0x0F, 0x94, 0x0A, 0x26, 0x06, 0xB9, 0x46, 0x31, 0x7E, 0x81,
0x03, 0x02, 0x3C, 0x40, 0x0A, 0xA1, 0x70, 0x1A, 0x1B, 0x1C, 0x51, 0x09, 0xED, 0x56, 0xC2, 0x12,
0xAF, 0xAC, 0x1E, 0xB6, 0x40, 0xF6, 0x82, 0x14, 0x14, 0x20, 0xCF, 0xE9, 0xF9, 0x08, 0x53, 0xAC,
0xA9, 0xA6, 0x7F, 0xA0, 0x23, 0x08, 0x2C, 0x80, 0x84, 0x24, 0x46, 0xFC, 0x08, 0xA1, 0x42, 0x0B,
0x53, 0x6B, 0x68, 0xDF, 0x68, 0x36, 0xD5, 0x83, 0x24, 0x58, 0xC1, 0x10, 0x92, 0xF8, 0xB4, 0xF5,
0xFE, 0xA6, 0x4B, 0x06, 0x27, 0x44, 0x41, 0x03, 0x3F, 0xE8, 0x02, 0x24, 0x9C, 0x50, 0x83, 0xB0,
0x21, 0xD3, 0x77, 0x9A, 0x03, 0x41, 0x13, 0x1A, 0xC0, 0x51, 0x08, 0x9D, 0xE7, 0x29, 0xF8, 0xB0,
0xC5, 0x05, 0x4E, 0x00, 0xE1, 0x37, 0x60, 0xF7, 0xC3, 0x0E, 0x9B, 0x18, 0x0D, 0x9D, 0xE0, 0xBE,
0x0B, 0x28, 0xC0, 0x00, 0xF1, 0x65, 0x8F, 0x46, 0xEE, 0xE1, 0xE7, 0x8C, 0xDC, 0x63, 0x1F, 0x41,
0x98, 0x01, 0x27, 0x0C, 0x31, 0x88, 0xE8, 0xB6, 0xC1, 0x72, 0x5A, 0x48, 0x9F, 0xC6, 0xEC, 0x68,
0xC7, 0x2E, 0x38, 0x21, 0x0C, 0x8F, 0x00, 0xB8, 0xE3, 0xDE, 0xF0, 0xE9, 0x87, 0x75, 0x0C, 0x04,
0x28, 0x00, 0x04, 0x20, 0xBA, 0x80, 0xF6, 0x1A, 0xFC, 0x20, 0x99, 0xA3, 0xE1, 0x94, 0xFB, 0x52,
0xB0, 0x80, 0x68, 0x22, 0x24, 0x2C, 0x34, 0x69, 0xBA, 0x3E, 0x1E, 0x39, 0x0C, 0x22, 0x48, 0x40,
0x0C, 0x80, 0x50, 0x44, 0x77, 0xB9, 0xEB, 0x88, 0x3A, 0x58, 0x41, 0x63, 0x55, 0xB3, 0x6A, 0x08,
0x44, 0x00, 0x83, 0x01, 0xE4, 0xD9, 0x27, 0x1C, 0x81, 0x07, 0x5B, 0x6A, 0x4C, 0x10, 0x71, 0xF8,
0x26, 0x16, 0x5A, 0x35, 0x45, 0x2C, 0x94, 0x00, 0xBA, 0xC6, 0xED, 0x93, 0x5A, 0x60, 0xB0, 0x02,
0x1B, 0xA4, 0x3A, 0x08, 0xF1, 0x4A, 0xF7, 0x69, 0x68, 0xD4, 0x2D, 0x0A, 0xE8, 0xF9, 0x06, 0x1C,
0x2E, 0x21, 0x09, 0x9C, 0x1B, 0x0D, 0x0D, 0x50, 0x70, 0x02, 0xA3, 0x1B, 0x00, 0x1F, 0x92, 0xF7,
0xCB, 0x5E, 0x70, 0x1E, 0x83, 0x04, 0xCC, 0x60, 0x12, 0x8C, 0xD0, 0x44, 0x76, 0xB9, 0x5B, 0x07,
0xD0, 0x2A, 0x01, 0x8A, 0x95, 0xF4, 0x40, 0x0C, 0x0C, 0x70, 0x8D, 0x86, 0x4B, 0x26, 0x23, 0x91,
0x01, 0x4C, 0x3E, 0x0A, 0x83, 0x03, 0x35, 0x4C, 0x62, 0x0C, 0x5A, 0x60, 0x43, 0x2C, 0xC0, 0xFE,
0x90, 0x04, 0x30, 0xCC, 0x81, 0xC2, 0x0A, 0x8D, 0x61, 0x85, 0x07, 0xE1, 0x08, 0x4B, 0x3C, 0xA2,
0x61, 0xDA, 0x6E, 0xDC, 0x1C, 0x9E, 0x00, 0x82, 0x30, 0x7F, 0x9B, 0x05, 0x50, 0x00, 0xD9, 0xE6,
0x40, 0x66, 0xBE, 0xDA, 0x8F, 0xCB, 0x00, 0xE4, 0x91, 0x90, 0xD3, 0x3D, 0x22, 0x41, 0x69, 0x18,
0x40, 0x04, 0xA1, 0x50, 0x06, 0x92, 0xD0, 0x5D, 0x99, 0x85, 0x31, 0xC1, 0x44, 0x06, 0x95, 0x44,
0x04, 0xA8, 0x45, 0x08, 0xA6, 0xD4, 0x32, 0x04, 0x73, 0x01, 0x8D, 0x30, 0x09, 0x65, 0x30, 0x7A,
0x52, 0x63, 0x31, 0xC5, 0xE7, 0x04, 0x4C, 0x30, 0x3C, 0xCF, 0xC5, 0x66, 0x96, 0x30, 0x08, 0x9B,
0xA5, 0x69, 0xA0, 0x17, 0x47, 0x90, 0x20, 0x07, 0xEF, 0x23, 0x7B, 0x32, 0x60, 0x3E, 0x20, 0x03,
0x02, 0xB5, 0x37, 0x2A, 0x06, 0x00, 0x00, 0xCA, 0xE3, 0x5B, 0x1E, 0x71, 0x77, 0x47, 0xE1, 0x5A,
0x10, 0xF0, 0x00, 0x81, 0x20, 0x07, 0x20, 0x67, 0x08, 0xDD, 0x66, 0x05, 0xD3, 0x62, 0x55, 0xB8,
0xF2, 0x02, 0x8D, 0x77, 0x0C, 0x88, 0x61, 0x10, 0xF1, 0x35, 0x56, 0x24, 0xA1, 0x0D, 0x04, 0x40,
0x09, 0x91, 0x00, 0x72, 0x7E, 0x40, 0x07, 0xAE, 0x64, 0x08, 0xA0, 0x35, 0x09, 0x79, 0xD0, 0x05,
0x65, 0x50, 0x07, 0xA6, 0x60, 0x09, 0x99, 0x55, 0x08, 0x94, 0x55, 0x07, 0x73, 0x20, 0x24, 0x37,
0x14, 0x09, 0x63, 0x90, 0x04, 0x1A, 0x00, 0x6D, 0x3D, 0xF0, 0x2D, 0x21, 0x10, 0x02, 0xDF, 0x32,
0x03, 0x1E, 0xD0, 0x00, 0x14, 0x90, 0x01, 0x08, 0x00, 0x00, 0xDC, 0xC0, 0x1C, 0x5C, 0xE4, 0x0F,
0x0C, 0xC7, 0x43, 0x4C, 0x91, 0x0F, 0xEC, 0x22, 0x01, 0x11, 0x86, 0x7A, 0x8E, 0x35, 0x43, 0x4E,
0xB0, 0x6E, 0x33, 0x60, 0x02, 0x10, 0x30, 0x04, 0xFA, 0xC0, 0x45, 0x02, 0x81, 0x2E, 0xFE, 0x37,
0x77, 0x53, 0x7A, 0xE0, 0x01, 0xC7, 0x76, 0x09, 0x9E, 0x56, 0x62, 0xC5, 0x87, 0x2D, 0xD9, 0x67,
0x08, 0xE5, 0xA7, 0x6D, 0x17, 0xD3, 0x06, 0x76, 0x00, 0x08, 0x66, 0xE0, 0x02, 0x16, 0x80, 0x05,
0xB2, 0xB0, 0x04, 0x1A, 0xF0, 0x00, 0x5E, 0x22, 0x32, 0xF0, 0x23, 0x01, 0x8F, 0x52, 0x00, 0x16,
0x00, 0x01, 0x23, 0x30, 0x02, 0x13, 0x00, 0x00, 0x8B, 0x80, 0x10, 0xF5, 0x90, 0x14, 0x31, 0x51,
0x15, 0x5C, 0xD1, 0x3A, 0x65, 0x85, 0x0E, 0x0A, 0x20, 0x02, 0x4C, 0xA0, 0x05, 0x65, 0x40, 0x43,
0x6C, 0xC0, 0x30, 0xDA, 0xC6, 0x83, 0x49, 0xC0, 0x03, 0x22, 0x80, 0x3A, 0xCF, 0xE0, 0x67, 0xE7,
0x31, 0x18, 0xC7, 0xF1, 0x48, 0x7A, 0x70, 0x03, 0x93, 0xA0, 0x76, 0x73, 0xC0, 0x08, 0x4F, 0xC5,
0x38, 0x0F, 0xD3, 0x06, 0x97, 0x50, 0x75, 0x52, 0x93, 0x65, 0x10, 0x23, 0x07, 0x52, 0xF0, 0x01,
0x1F, 0xA0, 0x0B, 0x66, 0xF0, 0x02, 0x90, 0x02, 0x3F, 0x1B, 0x40, 0x6D, 0xA0, 0x92, 0x6A, 0x38,
0x40, 0x01, 0x06, 0xB0, 0x00, 0x06, 0x80, 0x00, 0x0E, 0x70, 0x04, 0x33, 0x58, 0x53, 0x32, 0x11,
0x1F, 0x7B, 0xE7, 0x22, 0x24, 0xD1, 0x13, 0xFB, 0x10, 0x0D, 0x10, 0xE0, 0x6A, 0x86, 0xF6, 0x75,
0x76, 0x30, 0x71, 0x19, 0xB4, 0x41, 0x4C, 0xC0, 0x02, 0x06, 0x37, 0x04, 0xFC, 0x40, 0x87, 0x40,
0x24, 0x2C, 0xFB, 0x17, 0x44, 0xF1, 0xF4, 0x77, 0x94, 0x90, 0x39, 0xD7, 0xE2, 0x54, 0xCD, 0xA2,
0x55, 0xD3, 0x32, 0x07, 0x0A, 0x05, 0x06, 0x1F, 0xF3, 0x00, 0x50, 0x30, 0x09, 0x53, 0x00, 0x01,
0x16, 0x60, 0x8E, 0x17, 0xB0, 0x01, 0x1B, 0x20, 0x01, 0x0D, 0x30, 0x01, 0x13, 0xB0, 0x00, 0xEA,
0xB8, 0x00, 0x05, 0x60, 0x00, 0x2B, 0x00, 0x00, 0xC7, 0x40, 0x1E, 0x3D, 0x71, 0xFE, 0x0C, 0x10,
0x40, 0x00, 0x82, 0x60, 0x2A, 0xF3, 0x61, 0x4A, 0xFD, 0xC0, 0x0C, 0x06, 0xE0, 0x02, 0x53, 0x30,
0x61, 0x6C, 0x30, 0x80, 0x95, 0x90, 0x59, 0xDA, 0xB6, 0x5B, 0x1F, 0x10, 0x00, 0x2A, 0x41, 0x56,
0x1B, 0xA1, 0x14, 0x2B, 0xB1, 0x0F, 0xE1, 0xC0, 0x3F, 0x8E, 0x76, 0x02, 0x33, 0x20, 0x3E, 0xA2,
0x67, 0x31, 0x7E, 0xA0, 0x05, 0x9E, 0xE3, 0x7D, 0x10, 0x95, 0x58, 0x21, 0x10, 0x08, 0x6B, 0x30,
0x03, 0x16, 0x00, 0x03, 0x76, 0x33, 0x92, 0x22, 0x69, 0x7B, 0x13, 0x40, 0x01, 0xEC, 0x48, 0x00,
0x06, 0x50, 0x00, 0x13, 0x30, 0x00, 0x2A, 0x10, 0x63, 0xFB, 0x50, 0x04, 0x05, 0x50, 0x05, 0x55,
0x00, 0x01, 0x31, 0x40, 0x1E, 0x9F, 0x11, 0x11, 0xFC, 0xC1, 0x45, 0xF7, 0xD0, 0x0F, 0xB4, 0x60,
0x00, 0x3C, 0xE0, 0x04, 0x66, 0xE4, 0x66, 0xFF, 0x96, 0x59, 0x74, 0x40, 0x74, 0x2C, 0xE0, 0x01,
0x03, 0x40, 0x0C, 0x47, 0xD1, 0x74, 0x6C, 0xB3, 0x74, 0x0B, 0x97, 0x19, 0xFD, 0x80, 0x0F, 0xA8,
0x10, 0x03, 0x1D, 0x50, 0x00, 0x44, 0x40, 0x03, 0xD9, 0x67, 0x4C, 0x49, 0xF0, 0x03, 0x60, 0x10,
0x06, 0x94, 0x35, 0x3D, 0x3C, 0xB0, 0x01, 0x81, 0x10, 0x0A, 0x50, 0xB0, 0x01, 0x2F, 0x70, 0x4B,
0xA5, 0x68, 0x8A, 0x0F, 0x30, 0x2E, 0x2B, 0x99, 0x96, 0x1F, 0x00, 0x03, 0x47, 0x87, 0x96, 0x06,
0x30, 0x04, 0xAD, 0x50, 0x0C, 0x01, 0x70, 0x01, 0x4D, 0xD0, 0x04, 0x6A, 0x20, 0x04, 0x5E, 0x80,
0x00, 0xBE, 0x95, 0x1A, 0x04, 0xD1, 0x0F, 0x38, 0xE0, 0x01, 0x03, 0x52, 0x08, 0x40, 0x89, 0x85,
0x41, 0xE7, 0x3E, 0x2E, 0x56, 0x01, 0x72, 0xB1, 0x1A, 0x3B, 0xE1, 0x10, 0x8B, 0x54, 0x56, 0xF1,
0xB1, 0x0F, 0x57, 0xA0, 0x00, 0x40, 0x40, 0x69, 0x4D, 0xF8, 0x6D, 0xD9, 0xFE, 0x47, 0x07, 0x52,
0x46, 0x07, 0xCB, 0x25, 0x0B, 0x9B, 0xD8, 0x00, 0x28, 0x84, 0x86, 0x1A, 0x20, 0x01, 0xAB, 0xD9,
0x00, 0x0D, 0x90, 0x00, 0x63, 0xD2, 0x02, 0x41, 0xD0, 0x01, 0x1D, 0x10, 0x03, 0x89, 0x86, 0x9E,
0xFF, 0x63, 0x00, 0x01, 0x40, 0x04, 0xA0, 0xA4, 0x00, 0x0A, 0x80, 0x0A, 0x15, 0xD0, 0x0A, 0xAF,
0xD1, 0x14, 0xEB, 0x10, 0x04, 0x1B, 0x10, 0x05, 0x6C, 0x70, 0x85, 0x58, 0x48, 0x62, 0x61, 0xB0,
0x6C, 0x23, 0x73, 0x74, 0xEB, 0x10, 0x5F, 0x90, 0x07, 0x79, 0x42, 0xF1, 0x13, 0x46, 0x82, 0x0F,
0x05, 0xD0, 0x04, 0x60, 0x60, 0x07, 0x96, 0xE6, 0x79, 0xDC, 0x09, 0x54, 0x7E, 0x00, 0x32, 0x9C,
0x30, 0x06, 0x16, 0xF0, 0x01, 0x3B, 0x30, 0x7B, 0x1A, 0x00, 0x2A, 0x0A, 0x10, 0x4A, 0x10, 0xA0,
0x44, 0x5C, 0xD0, 0x78, 0xA9, 0xB3, 0x00, 0x29, 0x20, 0x01, 0x5E, 0x22, 0x02, 0x25, 0xE0, 0x01,
0x10, 0x10, 0x00, 0x4F, 0x11, 0x1F, 0xB9, 0x41, 0x00, 0x1D, 0x65, 0x1E, 0x21, 0xF1, 0x5A, 0x05,
0xC0, 0x03, 0x72, 0x70, 0x60, 0xE5, 0x37, 0x65, 0x2C, 0xA7, 0x01, 0x2F, 0x10, 0x64, 0xCC, 0x10,
0x56, 0x56, 0x01, 0x12, 0x1F, 0x45, 0x5F, 0x05, 0x00, 0x05, 0x69, 0x60, 0x59, 0x8F, 0x50, 0x75,
0x96, 0x08, 0x5D, 0x74, 0x70, 0x54, 0x7E, 0xF0, 0x04, 0x10, 0x40, 0x41, 0x2C, 0x50, 0x9E, 0x09,
0x90, 0x00, 0x05, 0x80, 0x64, 0x0B, 0x90, 0x00, 0x5C, 0x90, 0x02, 0x38, 0xFA, 0x14, 0x06, 0x90,
0x02, 0x28, 0x24, 0x36, 0x28, 0xA0, 0x01, 0x29, 0x00, 0x00, 0xFE, 0x20, 0x00, 0x11, 0xF0, 0x0F,
0x01, 0xB0, 0x00, 0x1D, 0x50, 0x73, 0x34, 0x21, 0x63, 0x99, 0x81, 0x0F, 0x46, 0x70, 0x01, 0x6B,
0xE0, 0x07, 0xAF, 0xA0, 0x09, 0x4F, 0x16, 0x4C, 0x2C, 0x17, 0x02, 0xFE, 0x61, 0x52, 0x00, 0x57,
0xF0, 0x1E, 0x0C, 0x8A, 0x11, 0xB1, 0xF1, 0x7C, 0x4F, 0x31, 0x0E, 0x09, 0x20, 0x06, 0x74, 0x40,
0x89, 0x83, 0x69, 0x08, 0x78, 0x30, 0x5D, 0xB2, 0xA4, 0x01, 0x6B, 0xA0, 0x05, 0xE0, 0xE6, 0x01,
0x22, 0x00, 0x2A, 0x5E, 0x9A, 0x3A, 0x03, 0x00, 0x00, 0x00, 0x90, 0x9B, 0x01, 0xE0, 0x0E, 0xA2,
0x0A, 0x00, 0xFD, 0xF0, 0x01, 0x4D, 0x10, 0x05, 0x9F, 0x23, 0x36, 0x2F, 0x30, 0x00, 0xF9, 0x20,
0x00, 0xB2, 0xFA, 0x0F, 0xB9, 0xB1, 0x00, 0x79, 0xE1, 0x7C, 0x47, 0xF1, 0x12, 0xFD, 0x80, 0x0E,
0x0D, 0xC0, 0x03, 0x63, 0xA0, 0x08, 0x9A, 0xA0, 0x09, 0x86, 0xC0, 0x83, 0xDC, 0x47, 0xA8, 0xF2,
0x03, 0x63, 0x50, 0xD1, 0xA0, 0xCA, 0xFA, 0x11, 0x0C, 0xB7, 0x0F, 0x46, 0xB0, 0x01, 0x5D, 0x70,
0x5D, 0x96, 0x50, 0x09, 0xE0, 0xB5, 0x59, 0x6C, 0x90, 0x65, 0x60, 0xF0, 0x03, 0x20, 0x30, 0x85,
0x62, 0x38, 0x96, 0x25, 0x3A, 0x00, 0x08, 0x00, 0x37, 0x06, 0xD0, 0x08, 0x03, 0xF0, 0x0F, 0x02,
0x70, 0xAA, 0xFD, 0xA0, 0x00, 0x62, 0x20, 0x07, 0x7E, 0x70, 0x40, 0x51, 0xB0, 0x01, 0x1F, 0x10,
0xAA, 0xE7, 0xFA, 0x0F, 0x15, 0xD0, 0x01, 0x0D, 0xA0, 0x07, 0x89, 0xFA, 0x12, 0x78, 0x88, 0x09,
0xAB, 0x34, 0x07, 0x9D, 0x20, 0xAC, 0xA0, 0xA5, 0xA9, 0x20, 0xB0, 0x78, 0x37, 0x23, 0x1F, 0x95,
0x71, 0x73, 0x77, 0x4A, 0x17, 0xE3, 0x80, 0x34, 0xD1, 0x3A, 0x80, 0xDE, 0x55, 0x62, 0x1C, 0xB3,
0x06, 0x20, 0x50, 0x03, 0x6B, 0xC7, 0x04, 0x8B, 0x17, 0x2E, 0x07, 0x40, 0x00, 0x00, 0x80, 0x87,
0xFB, 0x30, 0x00, 0x5E, 0x00, 0x56, 0x00, 0x10, 0xB2, 0xD3, 0x00, 0x00, 0xFB, 0xF0, 0x00, 0x63,
0x70, 0x5D, 0xD2, 0xD5, 0x05, 0x1A, 0xD0, 0x08, 0x01, 0x00, 0xFE, 0x00, 0x23, 0x0B, 0x00, 0xE2,
0x60, 0x00, 0x1E, 0x90, 0x02, 0xFD, 0x40, 0x12, 0x43, 0x78, 0x93, 0x91, 0xF9, 0x01, 0x1B, 0xC0,
0xAE, 0x78, 0x20, 0x09, 0x2F, 0xC5, 0x3E, 0x89, 0xF5, 0x02, 0x41, 0x30, 0x1E, 0x0A, 0xF9, 0x1A,
0x1F, 0x31, 0x7D, 0xFE, 0xD0, 0x0F, 0x59, 0xB0, 0x01, 0x4B, 0xB0, 0x81, 0xE5, 0xD7, 0x5D, 0x9B,
0x65, 0x07, 0x69, 0xB0, 0x06, 0x62, 0xA0, 0x01, 0x4E, 0xE0, 0x07, 0x60, 0x30, 0x05, 0xEF, 0x83,
0xB1, 0x04, 0x70, 0x14, 0xFB, 0xD0, 0x7B, 0x7A, 0x40, 0xA3, 0xB2, 0x0A, 0x00, 0x03, 0x50, 0xB6,
0xBE, 0x8A, 0x4F, 0x4F, 0x03, 0x06, 0x28, 0x00, 0x05, 0x09, 0x10, 0xAA, 0x21, 0x0B, 0x0F, 0x67,
0x7A, 0x01, 0x71, 0x48, 0x23, 0xEE, 0xC1, 0x0C, 0x0D, 0x10, 0x05, 0x17, 0x33, 0x4E, 0x9F, 0x97,
0x04, 0x2C, 0xB0, 0x03, 0x41, 0x00, 0x01, 0xC7, 0xB0, 0x11, 0xCA, 0xB1, 0x1C, 0x3C, 0xB1, 0x12,
0x4E, 0x81, 0x0F, 0x16, 0x30, 0x03, 0x15, 0x53, 0x59, 0x4F, 0x7B, 0x09, 0x51, 0x3B, 0x3D, 0x52,
0x00, 0x02, 0x56, 0x60, 0x07, 0x11, 0x53, 0x3E, 0x1A, 0x70, 0x01, 0x05, 0x00, 0xAB, 0xFF, 0x60,
0x04, 0x0F, 0xB0, 0x04, 0x2C, 0xFB, 0xA6, 0xE7, 0x6A, 0x6F, 0x28, 0x40, 0x0A, 0x49, 0xF5, 0x47,
0xDC, 0x77, 0x02, 0x0F, 0x90, 0x3A, 0x00, 0x00, 0xB7, 0x33, 0xB9, 0x09, 0xDB, 0xE0, 0x0F, 0xC4,
0x62, 0x19, 0xFD, 0xD0, 0x01, 0x28, 0xF0, 0x06, 0x52, 0xA3, 0x59, 0x09, 0xF5, 0x04, 0x4C, 0xE0,
0x02, 0x37, 0xD0, 0x02, 0x6E, 0x50, 0xB4, 0x83, 0xFB, 0x1C, 0x7C, 0x81, 0x0D, 0x0D, 0x30, 0x05,
0xD9, 0x37, 0x7A, 0x86, 0x30, 0x62, 0x4F, 0x16, 0x5D, 0x8E, 0x03, 0x7B, 0x93, 0xEB, 0x07, 0x73,
0x90, 0x04, 0x6B, 0x9A, 0x44, 0x04, 0x40, 0x30, 0x09, 0xFE, 0xC0, 0x0A, 0xED, 0x03, 0xB2, 0x03,
0x10, 0x5B, 0xDA, 0x74, 0x6E, 0xD5, 0x62, 0x05, 0x74, 0xF0, 0x06, 0x51, 0x20, 0x05, 0x6A, 0x78,
0x45, 0xF4, 0x90, 0x1B, 0x0A, 0x00, 0x00, 0xAE, 0xB0, 0x90, 0x24, 0x31, 0x13, 0xA0, 0xA0, 0x01,
0x4A, 0x30, 0xB9, 0x08, 0x46, 0x07, 0x60, 0xA0, 0xBB, 0xEB, 0x05, 0x03, 0x14, 0x50, 0xB4, 0xAF,
0x73, 0x1F, 0xFF, 0xF0, 0x05, 0x56, 0x46, 0x51, 0x4A, 0x10, 0x06, 0x85, 0x90, 0x6D, 0x75, 0x50,
0x58, 0x16, 0xA3, 0x05, 0x35, 0xA0, 0x04, 0xF7, 0xC4, 0x06, 0x61, 0xC3, 0x02, 0x17, 0x40, 0x00,
0x6D, 0x39, 0x00, 0xCF, 0x15, 0x0B, 0x1A, 0xB0, 0x04, 0x63, 0x62, 0x6D, 0x4B, 0x73, 0xAD, 0x55,
0xE9, 0x04, 0x1E, 0x54, 0x95, 0x5D, 0xC0, 0x04, 0x52, 0xB0, 0xA5, 0x8D, 0xD0, 0x62, 0x1F, 0x70,
0x74, 0x5A, 0xC4, 0x43, 0x3B, 0xB1, 0x0F, 0x09, 0x10, 0xAD, 0xC9, 0x4B, 0x62, 0x69, 0x10, 0x36,
0x63, 0x23, 0x04, 0x80, 0xB2, 0xA8, 0xBA, 0xE7, 0x0F, 0xF9, 0xB0, 0x0F, 0xC8, 0x72, 0x47, 0x4E,
0xC0, 0x79, 0xD7, 0x65, 0x89, 0x8C, 0x60, 0xC0, 0x69, 0xB0, 0x6C, 0x80, 0x60, 0x5E, 0x9A, 0x1A,
0x02, 0x98, 0xBB, 0x0F, 0x01, 0xA0, 0x06, 0x6D, 0x00, 0x0B, 0x97, 0x40, 0x07, 0xE3, 0xC4, 0x06,
0xBE, 0x20, 0x09, 0xE0, 0xDB, 0x84, 0x0A, 0xC5, 0xC1, 0x6F, 0xE0, 0x6D, 0x21, 0x14, 0x05, 0x48,
0x80, 0x02, 0x4B, 0x80, 0x02, 0x65, 0xD3, 0x02, 0x03, 0xC0, 0x0C, 0x7A, 0xE1, 0x1A, 0xFE, 0x50,
0xB2, 0x51, 0xE0, 0x07, 0x61, 0x97, 0x59, 0x34, 0x24, 0x36, 0xCD, 0xC4, 0x7C, 0x78, 0x37, 0x23,
0x4F, 0x11, 0x0E, 0x0F, 0xC0, 0x03, 0x3A, 0xAC, 0x04, 0x69, 0xC0, 0x08, 0x41, 0x25, 0x7A, 0xDC,
0x54, 0x08, 0x07, 0xF4, 0x04, 0x98, 0xBA, 0x38, 0xFE, 0x87, 0x07, 0x04, 0x1E, 0x80, 0xA3, 0x04,
0x20, 0x06, 0xA6, 0x50, 0x09, 0x75, 0xF0, 0x08, 0x1E, 0x06, 0x0B, 0x52, 0x55, 0x59, 0x78, 0x30,
0x07, 0x16, 0xA9, 0x3D, 0x4E, 0x03, 0xBD, 0xD7, 0xB2, 0x05, 0xEB, 0x26, 0x03, 0x40, 0x40, 0xB0,
0x05, 0xF0, 0x0B, 0x36, 0x97, 0x8C, 0x2A, 0xDC, 0x03, 0x68, 0xDC, 0x5D, 0x52, 0x8C, 0x39, 0x63,
0x63, 0x02, 0x0A, 0x30, 0x0B, 0x34, 0x8C, 0x12, 0xFB, 0x80, 0x0A, 0x56, 0x16, 0x05, 0x12, 0xF3,
0x75, 0x9A, 0x75, 0x5E, 0x61, 0x50, 0x59, 0x7C, 0x8C, 0x91, 0x21, 0xB0, 0x04, 0xCC, 0x12, 0xC8,
0x25, 0x50, 0x24, 0x03, 0xB0, 0x04, 0x61, 0x00, 0x0B, 0x4E, 0xF0, 0x08, 0xFF, 0xD6, 0x06, 0xA6,
0xE0, 0x0B, 0x8A, 0xB3, 0x7E, 0x66, 0xD0, 0x03, 0x52, 0x00, 0x05, 0x3D, 0xB0, 0x06, 0x99, 0xA2,
0xC5, 0x40, 0xD0, 0x04, 0x5E, 0xB2, 0x01, 0xA6, 0x53, 0x00, 0xB3, 0x60, 0x28, 0xF8, 0x91, 0xC2,
0x29, 0x80, 0x02, 0x7E, 0x70, 0x59, 0x96, 0x70, 0x09, 0xA0, 0x15, 0x05, 0x35, 0x20, 0x03, 0x82,
0x98, 0x08, 0x7D, 0xA1, 0x0F, 0xF6, 0x20, 0x69, 0x03, 0x22, 0x31, 0x93, 0x38, 0x08, 0x07, 0xAA,
0x05, 0xB4, 0x9C, 0x50, 0x63, 0x40, 0x03, 0x21, 0x30, 0xC4, 0x56, 0xC0, 0x42, 0x2C, 0xD0, 0x00,
0x57, 0x50, 0x9F, 0xB1, 0x20, 0x01, 0x64, 0xE0, 0xB8, 0x78, 0x20, 0x07, 0x62, 0x80, 0x02, 0x8A,
0x85, 0x25, 0x23, 0x32, 0x00, 0x14, 0x40, 0x01, 0x23, 0xF0, 0x01, 0x26, 0x30, 0x33, 0xEC, 0x25,
0x97, 0x06, 0xD7, 0x02, 0x46, 0x3A, 0xC6, 0x9E, 0x5C, 0x05, 0xDC, 0x8C, 0x85, 0xDF, 0xBC, 0x41,
0x5B, 0xF0, 0x03, 0x87, 0x09, 0x01, 0xBF, 0x0B, 0x17, 0xE8, 0xCC, 0x05, 0x3D, 0x20, 0x31, 0x58,
0x23, 0x07, 0x89, 0x6C, 0x09, 0x6D, 0xA0, 0xFE, 0x04, 0xF0, 0x5C, 0xC0, 0xD0, 0x2B, 0x24, 0x1A,
0xD0, 0x05, 0xBA, 0x10, 0x7E, 0x9F, 0x54, 0x00, 0x01, 0x50, 0x05, 0xBA, 0x60, 0x9E, 0x49, 0x30,
0xCF, 0x1B, 0x30, 0x00, 0x17, 0xF0, 0x05, 0x8F, 0x66, 0x04, 0x09, 0x50, 0x01, 0x00, 0xA0, 0x03,
0x3A, 0x90, 0x03, 0x44, 0xAD, 0x92, 0x05, 0xF0, 0x56, 0x26, 0xE3, 0x09, 0x03, 0x10, 0x03, 0xAA,
0x45, 0xD1, 0x1C, 0xD1, 0x0F, 0x41, 0x10, 0x02, 0x6C, 0xE0, 0x5D, 0xE0, 0xBC, 0x55, 0xE0, 0xA2,
0x00, 0x1F, 0xFD, 0x16, 0xFD, 0x60, 0x0F, 0x4D, 0xC0, 0x99, 0x1C, 0x24, 0xAD, 0xA3, 0x30, 0x08,
0x05, 0x85, 0x7E, 0x8A, 0x20, 0x8D, 0x69, 0xE0, 0x3E, 0x81, 0x40, 0x0A, 0x73, 0xF0, 0x39, 0x52,
0x70, 0x03, 0x06, 0x40, 0x00, 0xAC, 0xE0, 0x0B, 0x60, 0x30, 0x86, 0x30, 0x70, 0x26, 0xE3, 0xE0,
0x0D, 0xDE, 0x60, 0x0E, 0xEB, 0x60, 0x0F, 0xEB, 0xB0, 0x08, 0x0E, 0x90, 0x03, 0x87, 0x70, 0x08,
0x71, 0x30, 0x01, 0x45, 0xC0, 0x0C, 0xC7, 0xD0, 0x0C, 0x8A, 0x7D, 0x0D, 0xC7, 0x50, 0x01, 0x6D,
0xD9, 0x0F, 0x73, 0x38, 0x18, 0xFD, 0x20, 0x08, 0x12, 0x90, 0x06, 0x94, 0x68, 0x09, 0xE4, 0x86,
0x2D, 0xE5, 0xB3, 0x01, 0x0D, 0x40, 0x88, 0x70, 0xF1, 0x48, 0x5C, 0x40, 0x03, 0xDE, 0xC7, 0x8B,
0x7E, 0x40, 0x7E, 0xA3, 0xE0, 0x08, 0x8C, 0xE3, 0xC8, 0x3D, 0xFB, 0x69, 0x60, 0x70, 0x37, 0xA4,
0x10, 0x09, 0x4F, 0x13, 0x1C, 0x3B, 0xD0, 0x00, 0x7D, 0xC0, 0x07, 0x80, 0x80, 0x0B, 0xC1, 0x70,
0x0D, 0xD7, 0xC0, 0x0D, 0xD9, 0x00, 0x0E, 0xEC, 0x40, 0x0E, 0xEA, 0x60, 0x0E, 0xEE, 0x00, 0x0F,
0x81, 0x3D, 0xD8, 0x71, 0xB0, 0x02, 0x2B, 0x60, 0x0E, 0xDE, 0x50, 0x0D, 0xCC, 0x5D, 0x0D, 0xC4,
0x30, 0x00, 0xEB, 0x40, 0x53, 0x4C, 0xFE, 0xF1, 0x11, 0xC7, 0x70, 0x01, 0x63, 0xD0, 0x30, 0x24,
0x56, 0x6E, 0xE5, 0x23, 0x02, 0x0D, 0x50, 0x04, 0x81, 0xB1, 0x0F, 0x55, 0x20, 0x03, 0x03, 0xF2,
0x34, 0xAE, 0x34, 0xAD, 0x00, 0x87, 0x7E, 0x78, 0x10, 0x65, 0xDC, 0x54, 0x06, 0x3D, 0xF0, 0x00,
0x9E, 0x08, 0x09, 0xEA, 0x97, 0x07, 0x28, 0x40, 0x03, 0x93, 0xC0, 0x07, 0xC6, 0x70, 0x0C, 0xD3,
0x40, 0x0E, 0xD0, 0x00, 0x0E, 0xE9, 0x20, 0x0F, 0xEA, 0x90, 0x0F, 0xC3, 0x0D, 0x0F, 0x2B, 0xC0,
0x00, 0xC6, 0xED, 0x00, 0x2B, 0x20, 0x0F, 0xCB, 0x0D, 0x0E, 0xD9, 0x90, 0x0D, 0x9B, 0x80, 0x06,
0xC0, 0x86, 0xB0, 0x04, 0x63, 0x01, 0x6B, 0xC0, 0x38, 0x07, 0x06, 0x51, 0xDB, 0xDD, 0x00, 0x19,
0x90, 0xA8, 0x53, 0xB1, 0xCA, 0x01, 0xAA, 0x6F, 0x9C, 0x65, 0xDE, 0x71, 0x36, 0xA5, 0x52, 0xC5,
0x06, 0x51, 0xC0, 0x03, 0x12, 0x10, 0x0A, 0x90, 0xF0, 0x54, 0x6C, 0x20, 0x07, 0x21, 0x10, 0x0A,
0x91, 0x80, 0x0B, 0xC7, 0xE0, 0x0C, 0xCE, 0xC0, 0x0E, 0xDF, 0xF0, 0x0D, 0xEC, 0xF0, 0x0E, 0xEA,
0x50, 0x0F, 0xEE, 0x50, 0x0F, 0xC5, 0x00, 0x00, 0x0C, 0xC0, 0x01, 0x0E, 0x00, 0x00, 0xCE, 0x60,
0x0E, 0xEC, 0x90, 0x0E, 0xE0, 0x60, 0x0D, 0xE0, 0x60, 0x03, 0xC4, 0xF0, 0x9C, 0xF9, 0xD3, 0x01,
0x66, 0xA0, 0x05, 0xD8, 0xA6, 0x4F, 0x94, 0x24, 0x03, 0x9C, 0x5D, 0x97, 0x6F, 0x11, 0x11, 0xFD,
0x70, 0x0C, 0x09, 0xD0, 0xB4, 0xD1, 0x55, 0x59, 0x97, 0x3D, 0x0A, 0xE0, 0x55, 0x7C, 0x8F, 0xD3,
0x38, 0x74, 0xB0, 0x76, 0x67, 0xC8, 0x0A, 0x90, 0x60, 0x61, 0x7E, 0x00, 0x7F, 0xB2, 0x40, 0x09,
0x89, 0x40, 0x0E, 0xDB, 0x60, 0x0D, 0xE9, 0x60, 0xE3, 0xEC, 0xA0, 0x0E, 0x0B, 0x21, 0x0F, 0xFA,
0xB0, 0x0B, 0x41, 0x0E, 0x00, 0xFE, 0xC8, 0x20, 0x0F, 0xDF, 0x90, 0x0E, 0xE9, 0x60, 0x0D, 0xD6,
0x90, 0x0C, 0x36, 0x70, 0x16, 0x2C, 0xA3, 0x11, 0x1D, 0x20, 0x05, 0x50, 0x6E, 0x08, 0xFA, 0x24,
0x31, 0x35, 0x40, 0x36, 0x0A, 0xA0, 0x02, 0x1A, 0x9E, 0x13, 0x55, 0x71, 0x0D, 0x10, 0x30, 0x03,
0x69, 0x30, 0xE2, 0x6C, 0x80, 0x07, 0x0D, 0x93, 0x5D, 0x63, 0xCD, 0x49, 0x15, 0x78, 0x4F, 0x5A,
0x20, 0x06, 0x21, 0xC0, 0x04, 0xB1, 0x30, 0x71, 0x75, 0xC0, 0x08, 0x5D, 0x20, 0x01, 0x91, 0x60,
0x0C, 0xA8, 0x70, 0x0B, 0x71, 0x5E, 0xE3, 0x45, 0xCE, 0x0E, 0xF2, 0x40, 0xEB, 0x39, 0xFE, 0x0F,
0xDC, 0xB0, 0x10, 0x80, 0x3E, 0xE7, 0x48, 0x7E, 0x07, 0xB7, 0x10, 0x11, 0xFA, 0x87, 0x12, 0x1D,
0x20, 0x06, 0x5A, 0x00, 0x54, 0x50, 0x28, 0x31, 0x34, 0x30, 0x45, 0x05, 0xB0, 0xD5, 0x6F, 0xB1,
0x97, 0x05, 0xF0, 0x02, 0x5A, 0xE0, 0x44, 0x61, 0x50, 0x06, 0x4E, 0xD4, 0x06, 0x83, 0x00, 0xE6,
0x96, 0x50, 0x7C, 0xD5, 0xF3, 0x34, 0x8E, 0x33, 0xBE, 0x2C, 0xF0, 0x03, 0x25, 0xD5, 0x09, 0x90,
0x10, 0x09, 0x28, 0xE0, 0x04, 0x7C, 0x10, 0x0D, 0x82, 0x90, 0x0A, 0xE0, 0x00, 0x0D, 0x35, 0x9E,
0x0E, 0xEC, 0x70, 0xE3, 0xED, 0xE0, 0x0F, 0x3B, 0xEE, 0x0E, 0xEE, 0xA0, 0x0E, 0x80, 0x5E, 0xE3,
0x35, 0x8E, 0x01, 0xE4, 0xC0, 0x98, 0x3A, 0x01, 0x01, 0x66, 0x30, 0xCB, 0xD9, 0x7D, 0x5E, 0x52,
0x74, 0x01, 0x06, 0xB0, 0x3A, 0x70, 0x31, 0x7D, 0xB3, 0xBB, 0x01, 0x49, 0xF0, 0x38, 0x07, 0xA4,
0x49, 0x56, 0xD0, 0x06, 0xDE, 0x55, 0x78, 0x15, 0x18, 0x35, 0x11, 0xD3, 0x3E, 0x20, 0xF0, 0x03,
0x5A, 0x70, 0x0A, 0x7C, 0x90, 0x07, 0xB0, 0x07, 0x09, 0x81, 0x30, 0x0C, 0x99, 0xC0, 0x0B, 0xDE,
0x90, 0x0D, 0x73, 0x7E, 0xFE, 0xE3, 0xEF, 0xD0, 0x0E, 0xED, 0x70, 0x0F, 0xF3, 0x5E, 0xEB, 0xDF,
0x00, 0x0D, 0x81, 0x0E, 0x0C, 0x85, 0xEE, 0x11, 0x87, 0x4E, 0x84, 0x0A, 0x70, 0xDD, 0x41, 0x7A,
0x31, 0x44, 0xE7, 0x02, 0xF1, 0x7A, 0x0D, 0x33, 0xAF, 0x13, 0x37, 0xDC, 0x01, 0x1B, 0x50, 0xEE,
0xD8, 0xC2, 0x4B, 0x04, 0x35, 0xCB, 0xC3, 0x57, 0x78, 0xC4, 0x54, 0x4C, 0xF7, 0x34, 0x07, 0xDC,
0x62, 0xB9, 0x2C, 0x20, 0x01, 0xC0, 0x53, 0xDF, 0x54, 0x5B, 0x02, 0xCD, 0x50, 0x0D, 0xE0, 0x40,
0x0E, 0xE4, 0xF0, 0x0E, 0xEF, 0x70, 0x0E, 0xFC, 0x20, 0x0C, 0xD3, 0x50, 0x0F, 0x0B, 0xC1, 0x0E,
0xD0, 0x90, 0x0C, 0x47, 0x6E, 0x03, 0xC2, 0x40, 0x10, 0xC8, 0xD8, 0xF3, 0x04, 0xF3, 0x00, 0x3F,
0x4A, 0xAD, 0x1E, 0x78, 0x5E, 0x34, 0x50, 0xA4, 0x01, 0x10, 0x4D, 0x6F, 0xE1, 0x15, 0x19, 0x80,
0x2C, 0x35, 0x70, 0x47, 0x1D, 0x24, 0x70, 0xD8, 0x36, 0x7C, 0x09, 0x66, 0x58, 0x65, 0xD4, 0xD6,
0xDC, 0x22, 0x45, 0x2E, 0xB0, 0x03, 0x94, 0xB0, 0x01, 0x4C, 0xC0, 0x09, 0x9C, 0x30, 0x09, 0x6A,
0x50, 0x00, 0xDC, 0xF0, 0x0C, 0xE7, 0x70, 0x0E, 0xE4, 0x70, 0x0E, 0xFE, 0x6D, 0xE7, 0xEA, 0xA0,
0x0E, 0xE4, 0xF0, 0xEE, 0xDB, 0xB0, 0xF9, 0x02, 0x10, 0xEF, 0x08, 0x01, 0xEC, 0x28, 0xC1, 0xAB,
0x6D, 0x8F, 0xC8, 0xE6, 0x45, 0x74, 0x27, 0x30, 0x3F, 0xA8, 0x42, 0xE9, 0x1A, 0x61, 0x1F, 0xFF,
0x30, 0x04, 0x0B, 0xF0, 0x02, 0x71, 0x64, 0x50, 0x51, 0xD3, 0x49, 0x57, 0x3B, 0x80, 0x0E, 0x63,
0xA9, 0x18, 0x63, 0x2D, 0xC8, 0xA4, 0x01, 0x09, 0x60, 0x02, 0x26, 0x20, 0x22, 0x58, 0x40, 0x27,
0x74, 0xB0, 0x06, 0x1E, 0x70, 0x0C, 0xDE, 0x00, 0x0E, 0x92, 0xBF, 0xF5, 0xFC, 0xD0, 0x0E, 0x76,
0xBE, 0xF5, 0xE0, 0xFE, 0xF0, 0xFC, 0xDB, 0x70, 0x0B, 0x24, 0x50, 0x1E, 0x40, 0x51, 0x18, 0xD2,
0x07, 0x0A, 0xD6, 0x4D, 0x75, 0x98, 0xCD, 0x06, 0x2F, 0x5C, 0x03, 0x0E, 0x5C, 0x00, 0xF0, 0x86,
0x12, 0xEC, 0x21, 0x13, 0x9C, 0x91, 0x11, 0xEB, 0xD0, 0x2E, 0x2C, 0xE0, 0xCA, 0xC6, 0x45, 0x06,
0x5B, 0x03, 0xCF, 0x08, 0x86, 0xBC, 0x9B, 0xC5, 0x83, 0x4E, 0x90, 0x3E, 0xDF, 0xB2, 0x03, 0x35,
0xE8, 0x20, 0x58, 0xB0, 0x66, 0x6C, 0xC0, 0x07, 0x2F, 0x10, 0x0C, 0x23, 0x1F, 0xF9, 0x00, 0x41,
0xAE, 0xDD, 0x3C, 0x6E, 0xF2, 0xC8, 0x91, 0x03, 0x47, 0xCE, 0x9A, 0x35, 0x72, 0x24, 0x84, 0xFD,
0xF3, 0xF7, 0x4F, 0x22, 0x3F, 0x89, 0xFE, 0x2C, 0xFA, 0xE3, 0x97, 0x91, 0xDF, 0xBD, 0x7E, 0x82,
0x3C, 0x8C, 0x09, 0x53, 0x67, 0x90, 0x1D, 0x30, 0x4F, 0xA2, 0x20, 0x61, 0xF1, 0xA0, 0x40, 0x45,
0x89, 0x2D, 0x5D, 0x5E, 0x6C, 0xB9, 0x0F, 0x5B, 0x91, 0x11, 0x6E, 0xC6, 0xED, 0xB3, 0x47, 0xAF,
0x85, 0x97, 0x0D, 0x20, 0x94, 0xC8, 0x61, 0x63, 0x85, 0x8C, 0x16, 0x2D, 0x4E, 0xEA, 0x48, 0x72,
0x24, 0xD2, 0x91, 0xA5, 0x41, 0x6D, 0xC2, 0xB0, 0xA1, 0xC3, 0x28, 0x49, 0x97, 0x0D, 0x3E, 0xFA,
0x98, 0xF1, 0x80, 0x85, 0x51, 0x9D, 0x30, 0x6B, 0x76, 0xA0, 0xD2, 0x56, 0xED, 0xE0, 0xB9, 0x79,
0xDB, 0xD4, 0x79, 0x33, 0x07, 0xCE, 0x1A, 0x34, 0x68, 0xDB, 0x36, 0x91, 0xE0, 0x67, 0xB1, 0x25,
0xC5, 0x97, 0xFF, 0x34, 0xFE, 0xEB, 0xD7, 0xC2, 0x05, 0x18, 0x2B, 0x83, 0x1E, 0x31, 0x9A, 0xA3,
0xA5, 0x0B, 0x8D, 0x10, 0x07, 0x7E, 0x41, 0x74, 0x99, 0x18, 0xE2, 0xC5, 0x7A, 0xFB, 0x54, 0x0D,
0x50, 0xF0, 0xE1, 0x02, 0x81, 0x0B, 0xA5, 0xE2, 0x65, 0x1A, 0x40, 0xA4, 0x89, 0x14, 0x30, 0x69,
0xCA, 0xCC, 0xFE, 0x01, 0x03, 0x26, 0x24, 0xD2, 0xA5, 0xA2, 0x4C, 0x3B, 0x32, 0x24, 0x49, 0xD3,
0x25, 0x3F, 0x20, 0xCC, 0x04, 0xCA, 0x83, 0x82, 0x07, 0x29, 0x46, 0x4E, 0xBB, 0x34, 0xA9, 0x12,
0x76, 0xDB, 0x32, 0x57, 0xDB, 0xB8, 0xA9, 0x7B, 0x56, 0x8D, 0x6D, 0xB2, 0x64, 0xC0, 0x04, 0x6C,
0xAB, 0x18, 0xD1, 0x6E, 0xE2, 0x7C, 0x76, 0xE9, 0xF6, 0x5B, 0xC0, 0x43, 0x4E, 0x98, 0x41, 0x83,
0xFC, 0xA4, 0x49, 0x93, 0x04, 0x85, 0x88, 0x02, 0xFB, 0x9A, 0x2B, 0x7E, 0x69, 0xF1, 0xDE, 0xBF,
0x7D, 0x04, 0x82, 0xEC, 0xE0, 0xB1, 0x64, 0x89, 0x8B, 0x0B, 0x1E, 0x54, 0x5A, 0xB8, 0x31, 0x23,
0x4A, 0x9A, 0x31, 0x60, 0xCA, 0xB0, 0xF1, 0x63, 0x48, 0x93, 0xA3, 0x47, 0x96, 0x4C, 0x9F, 0x1E,
0x25, 0x40, 0x49, 0x6A, 0xF0, 0x03, 0x90, 0x48, 0x7A, 0x48, 0x63, 0x0E, 0x36, 0xD8, 0xD0, 0x62,
0x0B, 0x29, 0x36, 0xD0, 0xE6, 0x19, 0x67, 0x84, 0x71, 0x66, 0x1B, 0x61, 0xD0, 0x78, 0x86, 0x98,
0x55, 0x90, 0x01, 0xC6, 0xB8, 0x65, 0x32, 0xF2, 0xE7, 0x1E, 0xE5, 0x96, 0x73, 0x29, 0xA3, 0x96,
0xF0, 0x69, 0x40, 0x8C, 0xAD, 0x50, 0xA3, 0x43, 0x8B, 0x93, 0x66, 0x78, 0x60, 0x81, 0x7E, 0x14,
0x1B, 0xB1, 0x25, 0x8B, 0xF2, 0xE9, 0xA7, 0x97, 0x06, 0x76, 0x30, 0x63, 0x0C, 0x39, 0xE4, 0x30,
0x03, 0x0A, 0x20, 0x80, 0x78, 0x41, 0x84, 0x0B, 0x24, 0xA0, 0x21, 0x8A, 0x27, 0xC0, 0x80, 0xCA,
0x8E, 0xD4, 0x24, 0xB1, 0xC3, 0x49, 0x4B, 0x96, 0x1A, 0xC5, 0x11, 0x51, 0x2C, 0x91, 0xE4, 0x12,
0x3B, 0xC2, 0xE0, 0x23, 0x89, 0x32, 0xAC, 0xF0, 0x83, 0x28, 0x07, 0x35, 0x68, 0x86, 0x98, 0x64,
0x9C, 0x59, 0xC6, 0x99, 0x6A, 0x76, 0x69, 0x26, 0x95, 0x3D, 0x76, 0xB9, 0x45, 0x00, 0x57, 0x28,
0xCA, 0xFE, 0x07, 0xA6, 0x89, 0x14, 0xA3, 0x2B, 0x1F, 0x65, 0x36, 0xE0, 0x43, 0x92, 0x47, 0x58,
0x74, 0xB1, 0x87, 0x17, 0x08, 0x98, 0xE5, 0xBB, 0xF0, 0xEE, 0x5C, 0x2C, 0x1F, 0x7C, 0x5A, 0xB8,
0xA0, 0x0B, 0x2D, 0x18, 0x64, 0x44, 0x8B, 0x34, 0xA2, 0x88, 0x02, 0x90, 0x2D, 0x06, 0x63, 0x21,
0x84, 0x1F, 0xC8, 0xF0, 0x03, 0x8F, 0x3A, 0x9C, 0xF4, 0xC3, 0x0A, 0x27, 0xAC, 0x60, 0x43, 0x11,
0x45, 0x0C, 0x31, 0xC4, 0x12, 0x4B, 0xEA, 0x30, 0x84, 0x2B, 0x36, 0xCA, 0xE0, 0xEB, 0x0D, 0x30,
0xB4, 0x58, 0x63, 0x89, 0x12, 0xCA, 0x3C, 0xD3, 0x99, 0x64, 0x90, 0x79, 0x66, 0x17, 0x62, 0x76,
0xD9, 0x65, 0x8F, 0x23, 0xE8, 0xFA, 0x67, 0xBC, 0x11, 0x89, 0x75, 0x69, 0xBC, 0x7E, 0xB2, 0x08,
0x41, 0x0E, 0x49, 0xA6, 0xE4, 0x0A, 0x8C, 0x2E, 0x42, 0x48, 0xC1, 0x80, 0x7D, 0x16, 0x3B, 0xD4,
0x39, 0x6C, 0xF1, 0x09, 0x42, 0x03, 0xA0, 0x5A, 0x0D, 0xA3, 0x0D, 0x36, 0xDE, 0x20, 0xC3, 0x89,
0xA2, 0xA2, 0x80, 0x82, 0x05, 0x14, 0x94, 0xA0, 0x83, 0x8E, 0x05, 0x17, 0xD4, 0x22, 0x89, 0x24,
0x94, 0x30, 0x17, 0xBF, 0x3A, 0x8E, 0xAA, 0xA3, 0x8D, 0x36, 0xAC, 0x48, 0xE3, 0x8D, 0x37, 0x44,
0x7D, 0xA2, 0x0B, 0x19, 0x6E, 0x7D, 0x86, 0xB8, 0x33, 0x91, 0x41, 0x66, 0x97, 0x5C, 0x76, 0xD9,
0x24, 0x02, 0x13, 0xFF, 0x69, 0xAE, 0xCE, 0x1A, 0xC3, 0xF3, 0x07, 0x47, 0x05, 0x7A, 0xF0, 0xE3,
0x12, 0x4B, 0x0C, 0xD9, 0x77, 0xB0, 0x19, 0x5A, 0x90, 0x11, 0x3C, 0xB9, 0xEE, 0xBC, 0x11, 0x1F,
0x18, 0x50, 0x00, 0xA4, 0xBF, 0x3A, 0xD8, 0x90, 0xA4, 0x55, 0x3C, 0xCA, 0x20, 0xEA, 0x89, 0x24,
0xA2, 0x48, 0xA2, 0x06, 0x25, 0xB4, 0x20, 0xE3, 0x29, 0x36, 0x66, 0x8D, 0xF7, 0x07, 0x39, 0xD2,
0xFE, 0x70, 0x82, 0x8D, 0x7B, 0x57, 0x0E, 0x83, 0x0C, 0x32, 0xD2, 0xE0, 0x39, 0x8A, 0x25, 0x24,
0xF0, 0xA4, 0x19, 0x64, 0xA0, 0x39, 0x33, 0x19, 0x61, 0x7E, 0x6D, 0xA5, 0x15, 0x01, 0xB8, 0x41,
0xD4, 0x50, 0xF0, 0xB0, 0xC5, 0xAB, 0x80, 0x35, 0x0A, 0xB9, 0x44, 0x13, 0xAE, 0xAC, 0x88, 0x62,
0x86, 0x41, 0x8F, 0xB1, 0x31, 0x5B, 0x12, 0x2B, 0xC6, 0xE7, 0x81, 0x25, 0xD8, 0x58, 0xCA, 0x94,
0x4B, 0x0C, 0x79, 0x84, 0x63, 0x45, 0xE6, 0x80, 0x59, 0x52, 0x30, 0x9C, 0x30, 0x17, 0xE7, 0x76,
0xE7, 0xF8, 0x59, 0x8B, 0x9B, 0xF9, 0x0E, 0xC3, 0x8F, 0x28, 0xF3, 0xBE, 0x34, 0x0A, 0x27, 0x92,
0xA0, 0x01, 0x8A, 0x02, 0x8E, 0x21, 0x06, 0x18, 0x64, 0x92, 0xB9, 0x03, 0x98, 0x5B, 0x6E, 0xF9,
0xE5, 0x13, 0x00, 0xA6, 0x81, 0x88, 0xA2, 0x7A, 0x24, 0xD2, 0x3A, 0x31, 0x8B, 0xE6, 0x81, 0xF8,
0x9A, 0x0B, 0xD2, 0x38, 0x0A, 0x5C, 0x2D, 0x90, 0x78, 0x01, 0x86, 0x01, 0xFA, 0xC9, 0x27, 0xAE,
0x1A, 0x47, 0x5E, 0xFB, 0x1F, 0x7B, 0x88, 0x90, 0x42, 0x0E, 0x55, 0x15, 0xF1, 0xA3, 0x90, 0x56,
0x97, 0xDA, 0xD8, 0xDD, 0x37, 0xD6, 0xD8, 0x82, 0x28, 0x26, 0xDB, 0x85, 0xCA, 0x5D, 0x36, 0xC2,
0x10, 0x6A, 0x41, 0x3F, 0xE8, 0x28, 0xE9, 0x24, 0x24, 0x6A, 0xE8, 0xA1, 0x07, 0x1A, 0x44, 0x80,
0xE0, 0x18, 0x61, 0x6E, 0xE9, 0x70, 0x93, 0xCB, 0x73, 0xF9, 0x64, 0x00, 0x07, 0x16, 0x89, 0x58,
0x64, 0x1A, 0xE5, 0xEA, 0x07, 0x95, 0x17, 0x50, 0x37, 0x44, 0x11, 0x3A, 0xC2, 0xD8, 0x02, 0x08,
0x0F, 0x5A, 0x50, 0x61, 0x39, 0xDA, 0xB9, 0x4E, 0x96, 0x3C, 0x2F, 0xA0, 0x70, 0xD6, 0x12, 0x36,
0x08, 0x0C, 0xD7, 0x20, 0x02, 0x14, 0x3C, 0x32, 0x6C, 0x61, 0x0B, 0xA1, 0xD1, 0x82, 0xCE, 0xFE,
0x74, 0xF6, 0xAE, 0x05, 0x15, 0xED, 0x0D, 0x93, 0x4A, 0x42, 0xF5, 0x68, 0x30, 0xC1, 0x19, 0xC8,
0x4F, 0x15, 0xB9, 0xD8, 0xDE, 0x2A, 0x56, 0x71, 0x8B, 0x4D, 0x80, 0x6F, 0x00, 0x43, 0x58, 0x01,
0x00, 0x3E, 0xB1, 0x35, 0xFC, 0x25, 0x27, 0x22, 0xE8, 0xF8, 0xC0, 0x0C, 0xC8, 0x50, 0x07, 0x53,
0xB1, 0x81, 0x0C, 0x65, 0x0B, 0xC2, 0x00, 0x98, 0xE1, 0x9C, 0x10, 0xA9, 0xCD, 0x46, 0x8D, 0x49,
0x61, 0x1E, 0xFC, 0x60, 0x0A, 0x3A, 0x24, 0xE1, 0x01, 0x6B, 0x00, 0x43, 0x21, 0x54, 0xA3, 0x09,
0x43, 0x30, 0x48, 0x09, 0x51, 0x00, 0x43, 0x60, 0xC2, 0x90, 0x86, 0xA2, 0x91, 0xE1, 0x5D, 0xEE,
0x0A, 0x83, 0x98, 0xBA, 0xB0, 0x84, 0x1E, 0xC8, 0x00, 0x05, 0x2C, 0x60, 0xC1, 0x0C, 0x4E, 0x50,
0x82, 0x18, 0xFC, 0xA2, 0x15, 0xAE, 0x70, 0xC5, 0x26, 0x56, 0xB1, 0x89, 0x54, 0x84, 0x2F, 0x0B,
0x23, 0xC0, 0x81, 0x0A, 0x00, 0x70, 0x8D, 0x6B, 0x85, 0xCE, 0x4E, 0x8B, 0x89, 0xC8, 0x3E, 0x7A,
0x71, 0x81, 0xB7, 0xB1, 0x0A, 0x0F, 0x51, 0x44, 0xC2, 0x09, 0x0A, 0xA0, 0x02, 0xD8, 0xD1, 0x49,
0x74, 0xE6, 0xDB, 0xC7, 0x02, 0x84, 0x60, 0x06, 0x48, 0x9C, 0x62, 0x0E, 0x4F, 0x08, 0x81, 0x04,
0xD6, 0x90, 0x86, 0x4E, 0xB4, 0x0C, 0x0F, 0x43, 0x51, 0x82, 0x12, 0x3A, 0xD3, 0x19, 0xEC, 0x54,
0x32, 0x0D, 0x81, 0x13, 0x0C, 0xA5, 0x90, 0x50, 0x45, 0x2B, 0xB2, 0xE0, 0x05, 0x5B, 0x24, 0x82,
0x27, 0x52, 0xE1, 0x0A, 0x38, 0xC0, 0x61, 0x13, 0x9B, 0xF8, 0x44, 0x2A, 0x02, 0xA0, 0x07, 0x18,
0x58, 0x00, 0x02, 0x10, 0x50, 0x63, 0x3F, 0x66, 0x74, 0x3E, 0xE5, 0xC0, 0x04, 0x1D, 0x5E, 0x10,
0x41, 0x17, 0xF2, 0x83, 0x07, 0x3A, 0x58, 0x61, 0x0B, 0x32, 0x10, 0x01, 0x01, 0xD0, 0xFE, 0xD6,
0x92, 0xCF, 0xD5, 0x45, 0x74, 0x11, 0xC9, 0x51, 0x03, 0xCE, 0x20, 0x0B, 0x33, 0x44, 0x62, 0x12,
0x62, 0x90, 0x00, 0x08, 0xA2, 0x20, 0x87, 0xE7, 0xED, 0xAC, 0x28, 0x44, 0x11, 0xD3, 0x16, 0x28,
0x45, 0xB3, 0x93, 0xD4, 0x80, 0x7A, 0xD5, 0xAB, 0x9E, 0x0C, 0xAC, 0x88, 0x82, 0x10, 0xBC, 0xC0,
0x3D, 0x31, 0xF8, 0xC4, 0x1E, 0x36, 0x71, 0x84, 0x23, 0x6C, 0x22, 0x11, 0x89, 0x18, 0x80, 0x11,
0xAA, 0x70, 0x03, 0x13, 0x28, 0xC0, 0x02, 0x31, 0x30, 0x00, 0x02, 0xAE, 0xF5, 0x8F, 0x79, 0x8C,
0xC8, 0x4E, 0x35, 0xEC, 0x07, 0x36, 0x2C, 0xC0, 0x83, 0x31, 0xF8, 0xE1, 0x5E, 0x0C, 0x2A, 0x5B,
0x03, 0xB2, 0x80, 0x8F, 0x96, 0x90, 0x8E, 0x84, 0x36, 0xAA, 0x18, 0x79, 0x6C, 0x51, 0x00, 0x13,
0xFC, 0x21, 0x10, 0xA1, 0x58, 0x42, 0x14, 0x34, 0x40, 0x03, 0x33, 0x50, 0x6A, 0x71, 0x49, 0x58,
0x02, 0x13, 0x98, 0xB0, 0x04, 0x19, 0xCC, 0x40, 0x5D, 0x28, 0x20, 0x27, 0x0B, 0x4E, 0x20, 0x82,
0x17, 0xBC, 0x20, 0x04, 0x21, 0xC8, 0x94, 0x16, 0x43, 0xB0, 0x81, 0x0D, 0x5C, 0xA0, 0x01, 0x05,
0x70, 0x43, 0x22, 0x4A, 0x59, 0xCA, 0x3D, 0xA0, 0x01, 0x00, 0x59, 0xC8, 0xC4, 0x0E, 0x66, 0x00,
0xD3, 0x9A, 0x76, 0x60, 0x01, 0x6E, 0x98, 0xD1, 0xC8, 0x2E, 0xA2, 0x9C, 0xF1, 0xFC, 0x03, 0x1F,
0xC3, 0x28, 0x80, 0x19, 0xE6, 0xD0, 0x2E, 0x77, 0x6D, 0x61, 0x09, 0x1B, 0x18, 0x00, 0x36, 0x66,
0xF4, 0xB0, 0x87, 0x2A, 0x46, 0x96, 0xE3, 0xC8, 0x82, 0x02, 0x78, 0x90, 0x87, 0x2E, 0x4C, 0x51,
0x02, 0x22, 0x68, 0xC2, 0x0E, 0x5A, 0x2A, 0x02, 0x21, 0x40, 0xE0, 0x03, 0x0A, 0x20, 0x00, 0x01,
0x3A, 0x90, 0x02, 0x2E, 0xCC, 0xA0, 0x09, 0x25, 0x50, 0x80, 0x01, 0xF4, 0x5A, 0xFE, 0x80, 0x06,
0x7C, 0xC0, 0x02, 0xEE, 0x91, 0xC0, 0x03, 0x1A, 0xA0, 0x80, 0x3D, 0x26, 0x02, 0x0D, 0xA5, 0x3C,
0x02, 0x1C, 0x48, 0x00, 0x80, 0x21, 0xA0, 0x42, 0x0D, 0x4B, 0xE8, 0x42, 0x04, 0x97, 0x30, 0x83,
0x1B, 0x5C, 0xC0, 0x00, 0xB3, 0x48, 0xEA, 0x45, 0x9A, 0x0A, 0x91, 0xF1, 0xC0, 0x03, 0x1F, 0x62,
0x05, 0x84, 0xBB, 0xAC, 0x60, 0x05, 0x2D, 0xF4, 0xE0, 0x06, 0x04, 0x00, 0x05, 0xC4, 0xBA, 0xBA,
0x5A, 0x88, 0xED, 0xA3, 0x00, 0x3D, 0xC8, 0x43, 0x14, 0x6A, 0xE5, 0x82, 0x04, 0x0C, 0xB6, 0x01,
0x06, 0x98, 0x40, 0x2F, 0x40, 0x21, 0x0D, 0x71, 0xAC, 0x03, 0x1D, 0x30, 0x78, 0xC0, 0x03, 0x36,
0x10, 0x8F, 0x75, 0xF4, 0xE3, 0x1A, 0xBF, 0x40, 0x03, 0x01, 0x06, 0x60, 0x00, 0x05, 0x0C, 0x96,
0xB0, 0x03, 0xA8, 0x40, 0x22, 0xF6, 0xB0, 0x88, 0x23, 0x90, 0x40, 0x00, 0x72, 0x6A, 0x05, 0x00,
0x0A, 0x20, 0x04, 0x31, 0x00, 0x71, 0x66, 0x9B, 0x04, 0x42, 0x0A, 0x02, 0x30, 0x82, 0x7D, 0xC0,
0xAE, 0x58, 0xE3, 0xF9, 0x9C, 0x3B, 0x24, 0xB2, 0x0F, 0x2F, 0x68, 0x20, 0x0F, 0xF7, 0x99, 0xD5,
0x16, 0x7E, 0x30, 0x83, 0x0B, 0x4C, 0xC0, 0x39, 0xFC, 0x28, 0x26, 0x6B, 0x15, 0xF3, 0xB9, 0x7D,
0xEC, 0x43, 0x01, 0x21, 0x20, 0x6B, 0xBC, 0x7A, 0xB0, 0x01, 0x18, 0x18, 0x40, 0x19, 0xF8, 0x58,
0x07, 0x3C, 0xF6, 0x81, 0x0F, 0x7A, 0x34, 0xD7, 0xA4, 0x0F, 0x50, 0xC0, 0x35, 0x66, 0xA9, 0x0F,
0x7D, 0xFC, 0xE2, 0x0A, 0x06, 0x18, 0x40, 0x00, 0x32, 0x3C, 0x00, 0x00, 0x44, 0x00, 0x00, 0x1D,
0x86, 0x83, 0x30, 0xE4, 0xB2, 0x8F, 0x2B, 0x0C, 0x00, 0x06, 0x6A, 0x98, 0x04, 0x18, 0xC8, 0x00,
0x06, 0x25, 0x6C, 0xB2, 0x09, 0x0F, 0x20, 0x40, 0x16, 0xFA, 0x2B, 0x91, 0xFE, 0xCD, 0xE2, 0x05,
0x1B, 0x05, 0xE8, 0x82, 0x13, 0x8B, 0xD2, 0x05, 0x14, 0xD0, 0x77, 0x00, 0xE2, 0xE0, 0x5A, 0x88,
0xEE, 0xD7, 0xD5, 0xFC, 0xFE, 0x83, 0xC2, 0x1D, 0x90, 0x40, 0x1E, 0xFC, 0x55, 0x03, 0x4F, 0x52,
0x00, 0x01, 0xF8, 0x80, 0xC7, 0x3F, 0xD6, 0xB1, 0x0E, 0x44, 0x34, 0x60, 0x33, 0x62, 0x68, 0x02,
0x0C, 0x10, 0xA0, 0xDE, 0x7F, 0xD4, 0x43, 0x1F, 0xFD, 0xDD, 0x87, 0x38, 0x98, 0x71, 0x0C, 0x20,
0x73, 0x63, 0x1A, 0x22, 0xF2, 0x47, 0x3F, 0x47, 0x8C, 0x8F, 0x7E, 0xA8, 0x80, 0x00, 0x4D, 0x90,
0xC3, 0xA8, 0x9C, 0x90, 0x86, 0x35, 0x74, 0xA1, 0x07, 0x30, 0x52, 0x80, 0x11, 0x8A, 0xDB, 0xE5,
0x7F, 0xB8, 0xA3, 0x1F, 0xEB, 0xB0, 0xF2, 0x16, 0x00, 0x61, 0xAE, 0x28, 0xF4, 0x60, 0xA6, 0x04,
0xE8, 0x85, 0x2C, 0x55, 0x5B, 0xAC, 0xA5, 0xAE, 0xF6, 0x3B, 0xE5, 0x6B, 0x6D, 0x0B, 0x92, 0x1C,
0x1A, 0x26, 0x6C, 0xC0, 0x95, 0x0B, 0xB0, 0xC7, 0x82, 0xCB, 0x81, 0x00, 0x0F, 0x40, 0xA1, 0x0B,
0x51, 0xA0, 0xC1, 0x06, 0x20, 0x80, 0x8F, 0x7B, 0xDC, 0xA3, 0x1E, 0x8F, 0x6E, 0x89, 0x88, 0xD0,
0xBC, 0xD4, 0x88, 0xE0, 0xE8, 0x5A, 0xFD, 0x60, 0x86, 0x02, 0x92, 0x9C, 0x40, 0xD2, 0x4E, 0x45,
0x0C, 0x3C, 0xA0, 0x2D, 0x01, 0x04, 0x01, 0xE4, 0xE6, 0xE0, 0xC3, 0x0B, 0x3F, 0x5C, 0xA4, 0x80,
0x8D, 0x04, 0x01, 0x23, 0xA0, 0xE3, 0x1A, 0xE2, 0x28, 0x6F, 0x3F, 0x9A, 0xFA, 0xC6, 0x87, 0x86,
0x6E, 0x1E, 0xA4, 0xC3, 0x47, 0x0A, 0x42, 0x30, 0x09, 0x17, 0x49, 0x81, 0x05, 0x17, 0x38, 0x40,
0x73, 0x41, 0x46, 0x01, 0xF4, 0xD8, 0xF5, 0x06, 0x09, 0x10, 0xC4, 0x3A, 0xEA, 0xB4, 0x9C, 0xE6,
0x08, 0x79, 0x74, 0xAC, 0x8E, 0x28, 0x73, 0xC6, 0xF1, 0x01, 0x3E, 0xFE, 0x5D, 0x33, 0x0D, 0x5D,
0x60, 0x42, 0x14, 0x98, 0x00, 0x85, 0x1D, 0x34, 0x20, 0x00, 0x2A, 0xF8, 0xC5, 0x3E, 0x04, 0x91,
0x00, 0x20, 0x20, 0x41, 0x0C, 0x91, 0x9D, 0x6F, 0x3D, 0x0D, 0x60, 0x04, 0x03, 0x2C, 0xC0, 0x00,
0x1D, 0x40, 0x85, 0xA2, 0xE1, 0xC8, 0xDA, 0x62, 0x16, 0xB3, 0x39, 0x1C, 0xB1, 0x47, 0x15, 0x36,
0x30, 0x89, 0x31, 0x78, 0xB3, 0x07, 0x3D, 0x3E, 0xC1, 0x06, 0x58, 0x20, 0x02, 0x11, 0x78, 0x20,
0xAF, 0x03, 0x70, 0x03, 0xA3, 0xF9, 0x99, 0x6A, 0xD9, 0xB1, 0x1A, 0x74, 0x10, 0xAB, 0x07, 0xB2,
0x38, 0xB2, 0x0E, 0x05, 0x88, 0x20, 0x0F, 0xD7, 0x34, 0x17, 0x76, 0x64, 0xD6, 0x04, 0x22, 0x2C,
0x60, 0x00, 0xCB, 0x85, 0xC1, 0x0B, 0x66, 0x40, 0x45, 0x1A, 0x6C, 0x47, 0x01, 0x0B, 0xA0, 0x00,
0x65, 0x3C, 0x70, 0x83, 0x06, 0x40, 0x00, 0x1B, 0x0C, 0x65, 0x89, 0x7E, 0xCD, 0xF7, 0x0F, 0x74,
0x54, 0xC1, 0xE5, 0x83, 0x76, 0xC2, 0x16, 0x6A, 0x20, 0x85, 0x25, 0x6C, 0x72, 0x03, 0x05, 0x10,
0x04, 0x36, 0xC4, 0x21, 0x4B, 0xF5, 0x96, 0xDB, 0x50, 0x14, 0xC1, 0xC8, 0xC4, 0x52, 0x9E, 0xB5,
0x88, 0xC0, 0x43, 0x1C, 0x06, 0x68, 0x42, 0x1E, 0x90, 0xE6, 0x07, 0x3F, 0x30, 0x48, 0xC0, 0x40,
0xB8, 0x01, 0x0C, 0x3E, 0xD0, 0x00, 0x0F, 0x6C, 0xE0, 0x06, 0x27, 0xC0, 0xFB, 0x06, 0xE0, 0x8A,
0x83, 0x05, 0x78, 0xE0, 0x05, 0x4D, 0x98, 0xC1, 0x0E, 0x12, 0x40, 0x8B, 0x59, 0x2A, 0x9D, 0x84,
0x4D, 0xC5, 0x89, 0x08, 0x98, 0x10, 0x0B, 0x46, 0xB8, 0x0B, 0x0C, 0x63, 0xA0, 0x94, 0x14, 0x24,
0x50, 0x0B, 0x7A, 0xD0, 0x23, 0x18, 0x10, 0xB0, 0xA7, 0x02, 0x8E, 0xD1, 0x8F, 0xFC, 0x22, 0x0B,
0x3C, 0x1A, 0x01, 0x51, 0xBA, 0xFB, 0xF1, 0x0B, 0x05, 0x9C, 0xFE, 0x41, 0x0B, 0xF9, 0x69, 0x43,
0x8B, 0x9C, 0xB0, 0x4D, 0x26, 0x58, 0x6F, 0x03, 0x0F, 0x48, 0x41, 0x02, 0x52, 0xE0, 0xD7, 0x01,
0x8C, 0xA0, 0x1C, 0x14, 0x68, 0xC1, 0x06, 0x64, 0x20, 0x05, 0x29, 0x34, 0xE1, 0x02, 0x09, 0x47,
0x94, 0xE1, 0x5B, 0xF2, 0x1D, 0x8C, 0x90, 0x27, 0x1A, 0x09, 0x98, 0xC4, 0x29, 0x24, 0x51, 0x87,
0x97, 0x69, 0x41, 0x5A, 0x17, 0xA8, 0x42, 0x34, 0x2C, 0x50, 0x00, 0x9D, 0xB3, 0x00, 0x06, 0x14,
0x90, 0xF0, 0x77, 0x3C, 0xFF, 0x50, 0x35, 0x27, 0xE6, 0x0A, 0x17, 0xC0, 0x05, 0x1D, 0x52, 0xB3,
0xB2, 0xA2, 0xF4, 0xCD, 0x09, 0x3F, 0x00, 0x42, 0x02, 0x0A, 0xD0, 0x02, 0x08, 0x50, 0x60, 0x00,
0x98, 0x3D, 0x06, 0x00, 0x5A, 0x10, 0x02, 0x19, 0xD4, 0x40, 0x0C, 0x6A, 0x68, 0x00, 0x36, 0xA2,
0xBC, 0x7D, 0xE1, 0xE7, 0x43, 0x44, 0x31, 0x81, 0x80, 0x26, 0x90, 0x85, 0x67, 0xB1, 0x0E, 0x36,
0x90, 0x83, 0x24, 0x00, 0x02, 0x0B, 0x50, 0x00, 0x13, 0x00, 0x02, 0x31, 0xD8, 0x02, 0x24, 0xD8,
0x01, 0x02, 0xD0, 0xAA, 0x87, 0x42, 0x37, 0x98, 0xA8, 0x98, 0x88, 0xC9, 0x88, 0x7D, 0xF8, 0x00,
0x35, 0x08, 0x04, 0x48, 0x68, 0xA4, 0xE5, 0x0B, 0x83, 0x32, 0x80, 0x19, 0x90, 0xA2, 0x96, 0xB8,
0x9A, 0x80, 0x01, 0x28, 0x82, 0x04, 0x7B, 0x8C, 0x0F, 0x08, 0x01, 0x20, 0x58, 0x82, 0x26, 0x90,
0x80, 0x0E, 0x50, 0x36, 0xBB, 0xE8, 0x27, 0xE1, 0x73, 0x09, 0xF5, 0x12, 0x11, 0xBA, 0x90, 0x86,
0x06, 0xC0, 0x05, 0x46, 0xF0, 0x93, 0xE5, 0x71, 0x02, 0x26, 0x70, 0x01, 0x0F, 0xF8, 0x80, 0x1D,
0xE8, 0x02, 0x30, 0x60, 0x84, 0x34, 0xE0, 0x01, 0x0B, 0xB0, 0x05, 0xCE, 0x23, 0xA1, 0x0A, 0x94,
0x8B, 0xAF, 0x33, 0x91, 0x7D, 0x80, 0x80, 0x07, 0x30, 0xFE, 0x03, 0x4E, 0xE8, 0x84, 0x4B, 0xD0,
0xC2, 0x4E, 0xB8, 0x1B, 0x3B, 0xB3, 0xAB, 0x0F, 0xB8, 0xB9, 0x75, 0xE8, 0xAF, 0x75, 0x20, 0x84,
0x0E, 0xB0, 0x80, 0x97, 0x92, 0x80, 0x0B, 0xC8, 0x84, 0x6B, 0x59, 0xB5, 0x89, 0xB1, 0xC1, 0x52,
0xAB, 0xA1, 0x5F, 0x20, 0x80, 0x46, 0xD0, 0xA5, 0xF7, 0x89, 0x17, 0x20, 0xF8, 0x00, 0x13, 0x70,
0x81, 0x1E, 0x80, 0x04, 0x49, 0x50, 0x04, 0x48, 0xC0, 0x02, 0x08, 0x48, 0x34, 0x13, 0x81, 0x42,
0x28, 0x7C, 0x34, 0x3B, 0xE9, 0x07, 0x7C, 0x08, 0x86, 0x04, 0xD0, 0x80, 0x1A, 0xE0, 0x03, 0x0F,
0xEC, 0x84, 0x58, 0x20, 0x05, 0x3E, 0x98, 0x82, 0x1F, 0xE8, 0x01, 0x11, 0x88, 0xA1, 0x5F, 0x50,
0xB0, 0x70, 0x80, 0x0C, 0xBF, 0x93, 0x80, 0x14, 0xC8, 0x34, 0x36, 0x4C, 0xB3, 0x21, 0xB3, 0xC1,
0x96, 0xF8, 0xB3, 0x05, 0xB0, 0x00, 0x2E, 0x80, 0x02, 0x26, 0x98, 0x97, 0x1A, 0x08, 0x81, 0xDB,
0x82, 0x00, 0x13, 0x10, 0x83, 0x34, 0x30, 0x85, 0x57, 0x20, 0x05, 0x28, 0x80, 0x00, 0x74, 0x88,
0x1D, 0x13, 0x8A, 0x88, 0x5E, 0x84, 0x28, 0xF1, 0x80, 0x98, 0xEF, 0x40, 0xAF, 0x7E, 0x90, 0x09,
0x2F, 0x48, 0x00, 0x14, 0x78, 0x02, 0x0D, 0x40, 0x81, 0x1A, 0x00, 0x84, 0x49, 0xC0, 0x05, 0x5C,
0x98, 0x84, 0x99, 0xE9, 0x81, 0x1D, 0xB0, 0x80, 0x01, 0x50, 0x05, 0x6D, 0xB8, 0x80, 0x07, 0x68,
0x82, 0x17, 0x08, 0xAC, 0x4C, 0xEB, 0x07, 0x7D, 0x28, 0x45, 0x1A, 0x19, 0x8F, 0x5D, 0xDC, 0x07,
0x5B, 0x80, 0x80, 0x04, 0xD8, 0x01, 0x13, 0x30, 0x81, 0xBF, 0x32, 0xA9, 0x04, 0xF8, 0x02, 0x7A,
0x10, 0x84, 0x00, 0xD8, 0x81, 0x48, 0xE0, 0x04, 0x52, 0xC8, 0x03, 0x05, 0xB0, 0x85, 0x6B, 0x61,
0xB6, 0xAE, 0xF2, 0x3C, 0x59, 0xEA, 0x87, 0x62, 0xFE, 0x20, 0x84, 0x0F, 0x10, 0x01, 0x3E, 0x4C,
0x03, 0x52, 0x60, 0x82, 0x44, 0x7A, 0x80, 0x0B, 0xD8, 0x81, 0x33, 0x30, 0x83, 0x24, 0x90, 0x19,
0x28, 0x70, 0x81, 0xE6, 0x0A, 0x81, 0x25, 0xA0, 0x01, 0x19, 0x78, 0x81, 0x06, 0x60, 0x33, 0x53,
0x94, 0xA5, 0xD0, 0x51, 0xBA, 0x56, 0x5B, 0x2F, 0x4F, 0xF8, 0x2F, 0x29, 0xE0, 0x81, 0x0B, 0x80,
0x00, 0x03, 0xB0, 0x80, 0x17, 0xB8, 0xBA, 0x60, 0xC0, 0x07, 0x7C, 0xD8, 0xC1, 0x19, 0xE0, 0x81,
0x1D, 0x50, 0x00, 0x54, 0xD8, 0x07, 0x7D, 0x90, 0x18, 0x37, 0x7C, 0xA8, 0x62, 0x5A, 0x30, 0x6D,
0xC8, 0x02, 0xE6, 0x4A, 0x81, 0x46, 0xE8, 0x83, 0x35, 0xD0, 0x82, 0x31, 0x60, 0x02, 0x1E, 0xA0,
0xB9, 0x0F, 0xD0, 0x2B, 0x08, 0xF0, 0x80, 0x33, 0x98, 0x8F, 0x99, 0xA1, 0xBA, 0x28, 0x50, 0x82,
0x29, 0x9A, 0x01, 0x85, 0xFA, 0x85, 0x22, 0x38, 0x80, 0x05, 0x80, 0x80, 0x02, 0x58, 0x80, 0xF2,
0x0A, 0x47, 0x46, 0xEB, 0x07, 0x5A, 0x28, 0x00, 0x3E, 0xF0, 0x03, 0x30, 0xE8, 0x01, 0x05, 0x40,
0xB0, 0x01, 0x28, 0x92, 0x10, 0x80, 0xBE, 0x70, 0xB0, 0x07, 0x7C, 0xC0, 0x86, 0x59, 0xC0, 0x86,
0xF2, 0x02, 0x47, 0xD9, 0x61, 0x8E, 0x60, 0x94, 0x88, 0x7A, 0x90, 0xA5, 0xFE, 0x32, 0xAE, 0x59,
0x70, 0x83, 0x14, 0xB8, 0x00, 0x0D, 0x08, 0x01, 0x31, 0xC8, 0x83, 0x3A, 0xFB, 0x34, 0x4B, 0x04,
0x02, 0x11, 0x50, 0x89, 0x21, 0x28, 0x06, 0x89, 0x00, 0x85, 0x01, 0x80, 0x82, 0x35, 0x48, 0x02,
0x2D, 0x90, 0x03, 0xA3, 0x19, 0x8A, 0x93, 0x38, 0x01, 0x0B, 0x68, 0x80, 0x89, 0xAC, 0xB3, 0x3C,
0xD0, 0xBB, 0x75, 0xD8, 0x4A, 0x88, 0x61, 0x06, 0x02, 0xA0, 0x04, 0x4E, 0xB8, 0x04, 0x36, 0x48,
0x82, 0x0F, 0xC0, 0x07, 0x71, 0x20, 0x80, 0xFE, 0x17, 0xE0, 0x81, 0xA1, 0x4C, 0x80, 0x20, 0xC8,
0xC8, 0x52, 0x5B, 0xB4, 0xC5, 0xB8, 0x87, 0xD0, 0xC9, 0x07, 0x71, 0xB8, 0x86, 0xDB, 0x54, 0x06,
0x54, 0x30, 0x82, 0x06, 0x58, 0x2E, 0x08, 0xB8, 0x80, 0x19, 0x90, 0x82, 0x35, 0x20, 0x1E, 0x30,
0xD0, 0x26, 0xF5, 0xD8, 0x38, 0xF5, 0xCB, 0x02, 0x74, 0xE8, 0x07, 0xCD, 0xF2, 0x4A, 0x29, 0x48,
0x83, 0x05, 0x29, 0x04, 0x3A, 0x58, 0xB1, 0x08, 0x32, 0x9B, 0x81, 0x94, 0x03, 0x4E, 0x80, 0x04,
0x39, 0xE8, 0x83, 0x05, 0xB8, 0x86, 0xCE, 0xEC, 0x87, 0x22, 0x68, 0x84, 0x49, 0x88, 0x85, 0x4E,
0x48, 0x83, 0x10, 0x68, 0x81, 0x7E, 0x50, 0x86, 0x02, 0xE8, 0x83, 0x77, 0x9B, 0x46, 0x0B, 0x40,
0x07, 0x7D, 0xF4, 0x07, 0x87, 0xAB, 0xC9, 0x1B, 0xF9, 0x07, 0x71, 0x18, 0x02, 0x04, 0xD8, 0x2B,
0xBE, 0x92, 0x00, 0x0D, 0x60, 0x81, 0x33, 0x80, 0x82, 0x33, 0x10, 0x03, 0x31, 0x98, 0x02, 0x26,
0x98, 0xA0, 0x97, 0x34, 0xCC, 0xC8, 0xF8, 0x00, 0x41, 0xC0, 0x87, 0x19, 0x43, 0x33, 0xA7, 0xBA,
0x00, 0x16, 0x50, 0x9C, 0x34, 0x20, 0x8A, 0xD5, 0x93, 0x82, 0x0B, 0xB0, 0x27, 0x13, 0xA0, 0x84,
0x2E, 0x88, 0x84, 0x48, 0xE0, 0x03, 0x4A, 0x80, 0x00, 0x20, 0xDB, 0xCA, 0x7E, 0x20, 0x80, 0x61,
0x98, 0x04, 0x4E, 0x98, 0x83, 0x35, 0xD8, 0x00, 0x37, 0xD0, 0xB7, 0x0B, 0x00, 0x84, 0x53, 0x88,
0x04, 0x33, 0xF0, 0x01, 0x05, 0x08, 0x06, 0xEF, 0x20, 0xC5, 0x46, 0xFB, 0x87, 0xF0, 0x31, 0x80,
0x0C, 0xE8, 0x80, 0x16, 0x20, 0x82, 0x1B, 0x00, 0x82, 0xDD, 0xEB, 0x81, 0x2E, 0x30, 0x83, 0xD6,
0xE3, 0x01, 0x1F, 0xD8, 0x81, 0x1B, 0xF8, 0xB9, 0x05, 0x18, 0x81, 0x59, 0x58, 0x50, 0x30, 0x03,
0xC7, 0xEF, 0x48, 0xC4, 0x14, 0x10, 0xFE, 0x01, 0x2A, 0xFA, 0xB4, 0x24, 0x98, 0x82, 0x1E, 0x90,
0x00, 0x08, 0x90, 0x06, 0x69, 0x28, 0x00, 0x09, 0xA0, 0x04, 0x5D, 0x90, 0x05, 0x56, 0x50, 0x03,
0x0B, 0x40, 0xBA, 0x37, 0xC4, 0x8B, 0x0E, 0x28, 0x85, 0x33, 0x60, 0x82, 0x29, 0x70, 0x81, 0x0F,
0xED, 0x87, 0x18, 0xB8, 0x01, 0x0F, 0xB4, 0xC7, 0x33, 0x48, 0x00, 0x99, 0x64, 0x89, 0x7C, 0x40,
0x35, 0x3B, 0xD1, 0x07, 0x71, 0x50, 0x81, 0x0C, 0xD8, 0xAB, 0x04, 0x48, 0x80, 0x07, 0xD0, 0x80,
0x41, 0xCD, 0xA2, 0x6C, 0xB4, 0x00, 0x25, 0x2D, 0x02, 0x09, 0x33, 0xAF, 0xB9, 0x34, 0xB2, 0x7D,
0x08, 0x87, 0x23, 0xA9, 0x20, 0x11, 0x00, 0x82, 0x3B, 0x5B, 0xC7, 0x5E, 0x58, 0xC9, 0x45, 0x59,
0x40, 0x17, 0xB8, 0x81, 0x0F, 0x18, 0x87, 0xC2, 0x13, 0x3E, 0xE5, 0x98, 0x05, 0x02, 0x30, 0x81,
0x6D, 0x5C, 0x00, 0x42, 0x90, 0xA5, 0x00, 0xA8, 0x85, 0x28, 0xE0, 0x04, 0x5D, 0x08, 0x84, 0x26,
0x28, 0x80, 0x68, 0x80, 0x9D, 0x34, 0x73, 0x09, 0x61, 0x74, 0xC3, 0xBB, 0xC4, 0x86, 0x60, 0xF0,
0x84, 0x2F, 0x20, 0x82, 0x79, 0x22, 0x82, 0x14, 0x08, 0x02, 0x5B, 0xB8, 0x89, 0x19, 0xC1, 0xD3,
0x73, 0x4B, 0xB7, 0x88, 0xF8, 0xB2, 0x70, 0x08, 0x82, 0x0B, 0x20, 0x12, 0x7B, 0x6A, 0x80, 0x22,
0xF9, 0x00, 0x37, 0x25, 0x8F, 0x05, 0x8B, 0x86, 0x61, 0x08, 0x06, 0x7B, 0x58, 0xD4, 0x37, 0xAC,
0x18, 0x7D, 0x60, 0x86, 0x11, 0x78, 0x25, 0x65, 0x98, 0xA5, 0x6B, 0x98, 0x43, 0x5C, 0xA0, 0x04,
0x28, 0xC8, 0xB3, 0x8C, 0xB4, 0x93, 0x43, 0x44, 0x35, 0x34, 0x2B, 0xB5, 0xCD, 0xDA, 0x07, 0x31,
0x4C, 0x36, 0x3E, 0x2B, 0x37, 0xC5, 0xA8, 0x93, 0x1A, 0xDC, 0x07, 0x54, 0xB8, 0x00, 0x11, 0xE0,
0x81, 0x6B, 0x73, 0xCD, 0x0C, 0xFE, 0x68, 0x80, 0x1B, 0x48, 0x01, 0x08, 0x40, 0x2A, 0x48, 0xD3,
0x4A, 0xC4, 0x28, 0xC5, 0x1A, 0x92, 0x08, 0x59, 0x82, 0xB2, 0x62, 0xAA, 0xB0, 0x02, 0xC8, 0x43,
0x08, 0xF0, 0x82, 0x05, 0x65, 0xB4, 0xFB, 0xE1, 0x48, 0x38, 0xAA, 0xC0, 0x36, 0x24, 0xD8, 0x3B,
0xF1, 0x23, 0xCE, 0x3A, 0x53, 0x13, 0x08, 0x05, 0x33, 0x98, 0xA2, 0x06, 0x08, 0x86, 0x7E, 0x98,
0x05, 0x0B, 0x10, 0x81, 0x1D, 0x10, 0x01, 0x05, 0x90, 0x06, 0xF3, 0x82, 0x09, 0xB9, 0x2C, 0x58,
0x93, 0x9B, 0xA5, 0x91, 0x59, 0x07, 0x65, 0x50, 0x86, 0x71, 0xB0, 0x56, 0x88, 0xB1, 0xD1, 0xAE,
0x42, 0xB7, 0x5F, 0x1C, 0x19, 0xD0, 0x83, 0xA8, 0xE1, 0xEB, 0x07, 0x0A, 0x10, 0x02, 0x63, 0xD0,
0x05, 0x3E, 0x18, 0x83, 0x25, 0x28, 0x00, 0x69, 0xC8, 0x87, 0x6B, 0x38, 0x80, 0x55, 0x1C, 0xCA,
0x0B, 0xA0, 0x05, 0x8A, 0x4D, 0x9B, 0x96, 0x5D, 0x2A, 0xD8, 0xFC, 0x9C, 0xE2, 0xFB, 0x07, 0x78,
0xF0, 0xC7, 0xE4, 0x68, 0xD0, 0x8E, 0x3C, 0x26, 0x9B, 0xFC, 0x45, 0x12, 0xB9, 0x06, 0x0A, 0x30,
0x86, 0x2F, 0xE5, 0x03, 0x33, 0xE0, 0x01, 0x08, 0xB0, 0x07, 0xF2, 0xB8, 0x00, 0x2C, 0xE0, 0x03,
0x3E, 0xD0, 0x02, 0x29, 0x30, 0x80, 0x6B, 0xB8, 0xD9, 0xAD, 0xF4, 0x45, 0xFE, 0xD3, 0x2C, 0x88,
0x81, 0x43, 0x93, 0x0B, 0x47, 0xBA, 0xE0, 0x3F, 0x5E, 0x2C, 0xBE, 0x80, 0xB2, 0x80, 0x5A, 0xA0,
0x04, 0x56, 0x08, 0x12, 0x13, 0x90, 0x41, 0xF2, 0xD8, 0x80, 0x40, 0xD0, 0x85, 0x48, 0x88, 0x94,
0x06, 0x48, 0x2D, 0x52, 0x2C, 0x58, 0x6D, 0x21, 0xA6, 0x89, 0x28, 0x44, 0xBD, 0xDD, 0x5B, 0xAE,
0xA2, 0x25, 0xB9, 0xB0, 0xCB, 0x45, 0x49, 0xCA, 0x3F, 0x68, 0x82, 0x1B, 0x80, 0x80, 0x60, 0x75,
0x83, 0x06, 0xF8, 0x52, 0xB1, 0x59, 0x60, 0x84, 0x2E, 0x30, 0x81, 0x59, 0xB8, 0xD8, 0xCE, 0x5C,
0xDD, 0x9E, 0xA5, 0x93, 0xF9, 0x9C, 0x5B, 0xD6, 0xEA, 0x45, 0x93, 0xC3, 0xDC, 0x9E, 0x2D, 0x91,
0xF5, 0xC2, 0x87, 0x79, 0xB2, 0x80, 0x0F, 0x58, 0x80, 0x5F, 0x98, 0xA5, 0x7D, 0xE8, 0x80, 0x5A,
0x30, 0x06, 0x5C, 0x60, 0x85, 0x1D, 0x18, 0x80, 0xEE, 0x64, 0x5D, 0x1B, 0x4A, 0x0E, 0xCF, 0xDB,
0xDA, 0xBE, 0xDD, 0x9A, 0xFB, 0x89, 0x5D, 0x8A, 0xB5, 0xC9, 0xEF, 0x58, 0xB0, 0xB5, 0xAC, 0x59,
0xEA, 0x05, 0x85, 0x05, 0x08, 0x82, 0x1B, 0xF0, 0x80, 0x20, 0xF0, 0x56, 0x12, 0x49, 0x5E, 0xE8,
0x3D, 0x57, 0xE6, 0x88, 0x9D, 0xDA, 0x7D, 0x5E, 0xAF, 0x9D, 0x98, 0x9C, 0x4D, 0x0C, 0x70, 0x94,
0x4D, 0x0A, 0x03, 0x9D, 0xB8, 0x70, 0x28, 0x58, 0xEB, 0x85, 0xF9, 0x45, 0x07, 0x71, 0x88, 0xB2,
0xE4, 0xB5, 0x5D, 0xE9, 0xAD, 0x31, 0x3C, 0x31, 0xDF, 0xF3, 0xD1, 0x2F, 0xF5, 0x15, 0x99, 0x1A,
0x5C, 0x8E, 0x92, 0x1B, 0x11, 0x7F, 0x54, 0xB8, 0x63, 0xC2, 0xDF, 0x85, 0x4B, 0xE0, 0x05, 0x46,
0xE0, 0x3F, 0x62, 0xE0, 0x07, 0x86, 0xE0, 0x08, 0x96, 0xE0, 0x09, 0xA6, 0xE0, 0x0A, 0xB6, 0xE0,
0x0B, 0xC6, 0x60, 0xF0, 0x08, 0x08, 0x00, 0x3B,
};

View File

@ -0,0 +1,338 @@
/*
* Copyright (c) 2012, 2013, Joel Bodenmann aka Tectu <joel@unormal.org>
* Copyright (c) 2012, 2013, Andrew Hannam aka inmarket
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the <organization> nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "gfx.h"
// include our chibios logo in a .gif format
#include "image_chibios.h"
/**
* This demo demonstrates many of the GWIN widgets.
* On the "Radio" tab try playing with the color radio buttons.
* On the "Checkbox" tab try playing with the "Disable All" checkbox.
*/
/* Our custom yellow style */
static const GWidgetStyle YellowWidgetStyle = {
Yellow, // window background
// enabled color set
{
HTML2COLOR(0x0000FF), // text
HTML2COLOR(0x404040), // edge
HTML2COLOR(0xE0E0E0), // fill
HTML2COLOR(0xE0E0E0), // progress - inactive area
},
// disabled color set
{
HTML2COLOR(0xC0C0C0), // text
HTML2COLOR(0x808080), // edge
HTML2COLOR(0xE0E0E0), // fill
HTML2COLOR(0xC0E0C0), // progress - active area
},
// pressed color set
{
HTML2COLOR(0xFF00FF), // text
HTML2COLOR(0x404040), // edge
HTML2COLOR(0x808080), // fill
HTML2COLOR(0x00E000), // progress - active area
},
};
/* The variables we need */
static GListener gl;
static GHandle ghConsole;
static GHandle ghTabButtons, ghTabSliders, ghTabCheckboxes, ghTabLabels, ghTabRadios, ghTabImages;
static GHandle ghButton1, ghButton2, ghButton3, ghButton4;
static GHandle ghSlider1, ghSlider2, ghSlider3, ghSlider4;
static GHandle ghCheckbox1, ghCheckbox2, ghCheckDisableAll;
static GHandle ghLabel1;
static GHandle ghRadio1, ghRadio2;
static GHandle ghRadioBlack, ghRadioWhite, ghRadioYellow;
static GHandle ghImage1;
/* Some useful macros */
#define ScrWidth gdispGetWidth()
#define ScrHeight gdispGetHeight()
#define TAB_HEIGHT 30
#define LABEL_HEIGHT 40
#define BUTTON_WIDTH 50
#define BUTTON_HEIGHT 30
#define SLIDER_WIDTH 20
#define CHECKBOX_WIDTH 80
#define CHECKBOX_HEIGHT 20
#define RADIO_WIDTH 50
#define RADIO_HEIGHT 20
#define COLOR_WIDTH 80
#define DISABLEALL_WIDTH 100
#define GROUP_TABS 0
#define GROUP_YESNO 1
#define GROUP_COLORS 2
/**
* Create all the widgets.
* With the exception of the Tabs they are all created invisible.
*/
static void createWidgets(void) {
GWidgetInit wi;
wi.customDraw = 0; wi.customParam = 0; wi.customStyle = 0;
// Create the Tabs
wi.g.show = TRUE; wi.customDraw = gwinRadioDraw_Tab;
wi.g.width = ScrWidth/6; wi.g.height = TAB_HEIGHT; wi.g.y = 0;
wi.g.x = 0*wi.g.width; wi.text = "Buttons"; ghTabButtons = gwinRadioCreate(NULL, &wi, GROUP_TABS);
wi.g.x = 1*wi.g.width; wi.text = "Sliders"; ghTabSliders = gwinRadioCreate(NULL, &wi, GROUP_TABS);
wi.g.x = 2*wi.g.width; wi.text = "Checkbox"; ghTabCheckboxes = gwinRadioCreate(NULL, &wi, GROUP_TABS);
wi.g.x = 3*wi.g.width; wi.text = "Radios"; ghTabRadios = gwinRadioCreate(NULL, &wi, GROUP_TABS);
wi.g.x = 4*wi.g.width; wi.text = "Labels"; ghTabLabels = gwinRadioCreate(NULL, &wi, GROUP_TABS);
wi.g.x = 5*wi.g.width; wi.text = "Images"; ghTabImages = gwinRadioCreate(NULL, &wi, GROUP_TABS);
// Buttons
wi.g.show = FALSE; wi.customDraw = 0;
wi.g.width = BUTTON_WIDTH; wi.g.height = BUTTON_HEIGHT; wi.g.y = TAB_HEIGHT+5;
wi.g.x = 0+0*(BUTTON_WIDTH+1); wi.text = "B1"; ghButton1 = gwinButtonCreate(NULL, &wi);
wi.g.x = 0+1*(BUTTON_WIDTH+1); wi.text = "B2"; ghButton2 = gwinButtonCreate(NULL, &wi);
wi.g.x = 0+2*(BUTTON_WIDTH+1); wi.text = "B3"; ghButton3 = gwinButtonCreate(NULL, &wi);
wi.g.x = 0+3*(BUTTON_WIDTH+1); wi.text = "B4"; ghButton4 = gwinButtonCreate(NULL, &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"; ghSlider1 = gwinSliderCreate(NULL, &wi);
wi.g.y = ScrHeight/2-1*(SLIDER_WIDTH+1); wi.text = "S2"; ghSlider2 = gwinSliderCreate(NULL, &wi);
// 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"; ghSlider3 = gwinSliderCreate(NULL, &wi);
wi.g.x = 0+1*(SLIDER_WIDTH+1); wi.text = "S4"; ghSlider4 = gwinSliderCreate(NULL, &wi);
// 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 = TAB_HEIGHT+5+0*(CHECKBOX_HEIGHT+1); wi.text = "C1"; ghCheckbox1 = gwinCheckboxCreate(NULL, &wi);
wi.customDraw = gwinCheckboxDraw_CheckOnRight;
wi.g.y = TAB_HEIGHT+5+1*(CHECKBOX_HEIGHT+1); wi.text = "C2"; ghCheckbox2 = gwinCheckboxCreate(NULL, &wi);
wi.customDraw = 0; wi.g.width = DISABLEALL_WIDTH;
wi.g.y = TAB_HEIGHT+5+2*(CHECKBOX_HEIGHT+1); wi.text = "Disable All"; ghCheckDisableAll = gwinCheckboxCreate(NULL, &wi);
// Labels
wi.g.width = 0; wi.g.height = LABEL_HEIGHT; // dynamic width, fixed height
wi.g.y = TAB_HEIGHT+5+2*(CHECKBOX_HEIGHT+1); wi.text = "Label"; ghLabel1 = gwinLabelCreate(NULL, &wi);
// Radio Buttons
wi.g.width = RADIO_WIDTH; wi.g.height = RADIO_HEIGHT; wi.g.y = TAB_HEIGHT+5;
wi.g.x = 0*wi.g.width; wi.text = "Yes"; ghRadio1 = gwinRadioCreate(NULL, &wi, GROUP_YESNO);
wi.g.x = 1*wi.g.width; wi.text = "No"; ghRadio2 = gwinRadioCreate(NULL, &wi, GROUP_YESNO);
wi.g.width = COLOR_WIDTH; wi.g.y += RADIO_HEIGHT+5;
wi.g.x = 0*wi.g.width; wi.text = "Black"; ghRadioBlack = gwinRadioCreate(NULL, &wi, GROUP_COLORS);
wi.g.x = 1*wi.g.width; wi.text = "White"; ghRadioWhite = gwinRadioCreate(NULL, &wi, GROUP_COLORS);
wi.g.x = 2*wi.g.width; wi.text = "Yellow"; ghRadioYellow = gwinRadioCreate(NULL, &wi, GROUP_COLORS);
gwinRadioPress(ghRadioWhite);
// Image
wi.g.x = ScrWidth-210; wi.g.y = TAB_HEIGHT + 10; wi.g.width = 200; wi.g.height = 200;
ghImage1 = gwinImageCreate(NULL, &wi.g);
gwinImageOpenMemory(ghImage1, image_chibios);
gwinImageCache(ghImage1);
// 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(NULL, &wi.g);
gwinSetColor(ghConsole, Yellow);
gwinSetBgColor(ghConsole, Black);
}
/**
* Set the visibility of widgets based on which tab is selected.
*/
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(ghImage1, FALSE);
/* Turn on widgets depending on the tab selected */
if (tab == ghTabButtons) {
gwinSetVisible(ghButton1, TRUE); gwinSetVisible(ghButton2, TRUE);
gwinSetVisible(ghButton3, TRUE); gwinSetVisible(ghButton4, TRUE);
} else if (tab == ghTabSliders) {
gwinSetVisible(ghSlider1, TRUE); gwinSetVisible(ghSlider2, TRUE);
gwinSetVisible(ghSlider3, TRUE); gwinSetVisible(ghSlider4, TRUE);
} else if (tab == ghTabCheckboxes) {
gwinSetVisible(ghCheckbox1, TRUE); gwinSetVisible(ghCheckbox2, TRUE); gwinSetVisible(ghCheckDisableAll, TRUE);
} else if (tab == ghTabLabels) {
gwinSetVisible(ghLabel1, TRUE);
} else if (tab == ghTabRadios) {
gwinSetVisible(ghRadio1, TRUE); gwinSetVisible(ghRadio2, TRUE);
gwinSetVisible(ghRadioWhite, TRUE); gwinSetVisible(ghRadioBlack, TRUE); gwinSetVisible(ghRadioYellow, TRUE);
} else if (tab == ghTabImages) {
gwinSetVisible(ghImage1, TRUE);
}
}
/**
* 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(ghCheckbox1, ena); gwinSetEnabled(ghCheckbox2, ena); //gwinSetEnabled(ghCheckDisableAll, TRUE);
gwinSetEnabled(ghLabel1, ena);
gwinSetEnabled(ghRadio1, ena); gwinSetEnabled(ghRadio2, ena);
gwinSetEnabled(ghRadioWhite, ena); gwinSetEnabled(ghRadioBlack, ena); gwinSetEnabled(ghRadioYellow, ena);
gwinSetEnabled(ghImage1, ena);
}
int main(void) {
GEvent * pe;
// Initialize the display
gfxInit();
// Set the widget defaults
gwinSetDefaultFont(gdispOpenFont("UI2"));
gwinSetDefaultStyle(&WhiteWidgetStyle, FALSE);
gdispClear(White);
// Connect the mouse
#if GINPUT_NEED_MOUSE
gwinAttachMouse(0);
#endif
// Create the gwin windows/widgets
createWidgets();
// Assign toggles and dials to specific buttons & sliders etc.
#if GINPUT_NEED_TOGGLE
gwinAttachToggle(ghButton1, 0, 0);
gwinAttachToggle(ghButton2, 0, 1);
#endif
#if GINPUT_NEED_DIAL
gwinAttachDial(ghSlider1, 0, 0);
gwinAttachDial(ghSlider3, 0, 1);
#endif
// Make the console visible
gwinSetVisible(ghConsole, TRUE);
gwinClear(ghConsole);
// We want to listen for widget events
geventListenerInit(&gl);
gwinAttachListener(&gl);
// Press the Tab we want visible
gwinRadioPress(ghTabButtons);
while(1) {
// Get an Event
pe = geventEventWait(&gl, TIME_INFINITE);
switch(pe->type) {
case GEVENT_GWIN_BUTTON:
gwinPrintf(ghConsole, "Button %s\n", gwinGetText(((GEventGWinButton *)pe)->button));
break;
case GEVENT_GWIN_SLIDER:
gwinPrintf(ghConsole, "Slider %s=%d\n", gwinGetText(((GEventGWinSlider *)pe)->slider), ((GEventGWinSlider *)pe)->position);
break;
case GEVENT_GWIN_CHECKBOX:
gwinPrintf(ghConsole, "Checkbox %s=%s\n", gwinGetText(((GEventGWinCheckbox *)pe)->checkbox), ((GEventGWinCheckbox *)pe)->isChecked ? "Checked" : "UnChecked");
// If it is the Disable All checkbox then do that.
if (((GEventGWinCheckbox *)pe)->checkbox == ghCheckDisableAll) {
gwinPrintf(ghConsole, "%s All\n", ((GEventGWinCheckbox *)pe)->isChecked ? "Disable" : "Enable");
setEnabled(!((GEventGWinCheckbox *)pe)->isChecked);
}
break;
case GEVENT_GWIN_RADIO:
gwinPrintf(ghConsole, "Radio Group %u=%s\n", ((GEventGWinRadio *)pe)->group, gwinGetText(((GEventGWinRadio *)pe)->radio));
switch(((GEventGWinRadio *)pe)->group) {
case GROUP_TABS:
// Set control visibility depending on the tab selected
setTab(((GEventGWinRadio *)pe)->radio);
// Do some special animation for Label1 to demonstrate auto width sizing
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);
}
break;
case GROUP_COLORS:
{
const GWidgetStyle *pstyle;
gwinPrintf(ghConsole, "Change Color Scheme\n");
if (((GEventGWinRadio *)pe)->radio == ghRadioYellow)
pstyle = &YellowWidgetStyle;
else if (((GEventGWinRadio *)pe)->radio == ghRadioBlack)
pstyle = &BlackWidgetStyle;
else
pstyle = &WhiteWidgetStyle;
// Clear the screen to the new color - we avoid the console area as it can't redraw itself
#if GDISP_NEED_CLIP
gdispUnsetClip();
#endif
gdispFillArea(0, 0, ScrWidth, ScrHeight/2, pstyle->background);
gdispFillArea(0, ScrHeight/2, ScrWidth/2, ScrHeight/2, pstyle->background);
// Update the style on all controls
gwinSetDefaultStyle(pstyle, TRUE);
}
break;
}
break;
default:
gwinPrintf(ghConsole, "Unknown %d\n", pe->type);
break;
}
}
return 0;
}

View File

@ -1,6 +1,8 @@
This demo supports input from both a mouse/touch and/or a dial input.
This demo supports input from both a mouse/touch, toggles and/or a dial input.
If your platform does not support one or the other, turn it off in
gfxconf.h
Note that you will need to include the drivers into your project
makefile for whichever inputs you decide to use.
For some fun have a play with the "colors" radio group and the "Disable All" checkbox.

View File

@ -7,6 +7,7 @@ within each file:
/*
* Copyright (c) 2012, 2013, Joel Bodenmann aka Tectu <joel@unormal.org>
* Copyright (c) 2012, 2013, Andrew Hannam aka inmarket
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -32,3 +33,4 @@ within each file:
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
Files under the 3rdparty directory are licensed as per the original contributor.

View File

@ -119,8 +119,8 @@ static LRESULT myWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
break;
case WM_LBUTTONUP:
#if GINPUT_NEED_TOGGLE
if ((toggles & 0xF0)) {
toggles &= 0x0F;
if ((toggles & 0x0F)) {
toggles &= ~0x0F;
rect.left = 0;
rect.right = wWidth;
rect.top = wHeight;

View File

@ -80,9 +80,11 @@
#define TDISP_NEED_MULTITHREAD FALSE
/* Features for the GWIN subsystem. */
#define GWIN_NEED_BUTTON FALSE
#define GWIN_NEED_WINDOWMANAGER FALSE
#define GWIN_NEED_CONSOLE FALSE
#define GWIN_NEED_GRAPH FALSE
#define GWIN_NEED_WIDGET FALSE
#define GWIN_NEED_BUTTON FALSE
#define GWIN_NEED_SLIDER FALSE
#define GWIN_NEED_CHECKBOX FALSE

View File

@ -48,7 +48,7 @@ typedef uint16_t GEventType;
typedef union GEvent_u {
GEventType type; // The type of this event
char pad[GEVENT_MAXIMUM_SIZE]; // This is here to allow static initialisation of GEventObject's in the application.
} GEvent;
} GEvent;
// A special callback function
typedef void (*GEventCallbackFn)(void *param, GEvent *pe);

View File

@ -46,31 +46,62 @@
#warning "GWIN: Drawing can occur outside the defined windows as GDISP_NEED_CLIP is FALSE"
#endif
#endif
#if GWIN_NEED_BUTTON
#if GWIN_NEED_IMAGE
#if !GDISP_NEED_IMAGE
#error "GWIN: GDISP_NEED_IMAGE is required when GWIN_NEED_IMAGE is TRUE."
#endif
#endif
#if GWIN_NEED_RADIO
#if !GDISP_NEED_CIRCLE
#if GFX_DISPLAY_RULE_WARNINGS
#warning "GWIN: GDISP_NEED_CIRCLE should be set to TRUE for much nicer radio button widgets."
#endif
#endif
#endif
#if GWIN_NEED_BUTTON || GWIN_NEED_SLIDER || GWIN_NEED_CHECKBOX || GWIN_NEED_LABEL || GWIN_NEED_RADIO
#if !GWIN_NEED_WIDGET
#if GFX_DISPLAY_RULE_WARNINGS
#warning "GWIN: GWIN_NEED_WIDGET is required when a Widget is used. 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_BUTTON is TRUE."
#error "GWIN: GDISP_NEED_TEXT is required if GWIN_NEED_WIDGET is TRUE."
#endif
#if !GFX_USE_GEVENT
#if GFX_DISPLAY_RULE_WARNINGS
#warning "GWIN: GFX_USE_GEVENT is required if GWIN_NEED_BUTTON is TRUE. It has been turned on for you."
#endif
#undef GFX_USE_GEVENT
#define GFX_USE_GEVENT TRUE
#if !GFX_USE_GINPUT
// This test also ensures that GFX_USE_GEVENT is set
#error "GWIN: GFX_USE_GINPUT (and one or more input sources) is required if GWIN_NEED_WIDGET is TRUE"
#endif
#if !GFX_USE_GINPUT || !(GINPUT_NEED_MOUSE || GINPUT_NEED_TOGGLE)
#if !GWIN_NEED_WINDOWMANAGER
#if GFX_DISPLAY_RULE_WARNINGS
#warning "GWIN: You have set GWIN_NEED_BUTTON to TRUE but no supported GINPUT (mouse/toggle) devices have been included"
#warning "GWIN: GWIN_NEED_WINDOWMANAGER is required if GWIN_NEED_WIDGET is TRUE. It has been turned on for you."
#endif
#undef GWIN_NEED_WINDOWMANAGER
#define GWIN_NEED_WINDOWMANAGER TRUE
#endif
#if !GDISP_NEED_MULTITHREAD && !GDISP_NEED_ASYNC
#if GFX_DISPLAY_RULE_WARNINGS
#warning "GWIN: Either GDISP_NEED_MULTITHREAD or GDISP_NEED_ASYNC is required if GWIN_NEED_BUTTON is TRUE."
#warning "GWIN: Either GDISP_NEED_MULTITHREAD or GDISP_NEED_ASYNC is required if GWIN_NEED_WIDGET is TRUE."
#warning "GWIN: GDISP_NEED_MULTITHREAD has been turned on for you."
#endif
#undef GDISP_NEED_MULTITHREAD
#define GDISP_NEED_MULTITHREAD TRUE
#endif
#endif
#if GWIN_NEED_WINDOWMANAGER
#if !GFX_USE_GQUEUE || !GQUEUE_NEED_ASYNC
#if GFX_DISPLAY_RULE_WARNINGS
#warning "GWIN: GFX_USE_GQUEUE and GQUEUE_NEED_ASYNC is required if GWIN_NEED_WINDOWMANAGER is TRUE. It has been turned on for you."
#endif
#undef GFX_USE_GQUEUE
#undef GQUEUE_NEED_ASYNC
#define GFX_USE_GQUEUE TRUE
#define GQUEUE_NEED_ASYNC TRUE
#endif
#endif
#if GWIN_NEED_CONSOLE
#if !GDISP_NEED_TEXT
#error "GWIN: GDISP_NEED_TEXT is required if GWIN_NEED_CONSOLE is TRUE."

View File

@ -36,6 +36,7 @@ typedef struct GEventDial_t {
GEventType type; // The type of this event (GEVENT_DIAL)
uint16_t instance; // The dial instance
uint16_t value; // The dial value
uint16_t maxvalue; // The maximum dial value
} GEventDial;
/*===========================================================================*/

View File

@ -91,7 +91,7 @@ void gfxQueueFSyncInit(gfxQueueFSync *pqueue);
/* @} */
/**
* @brief Get an item from the head of the queue.
* @brief Get an item from the head of the queue (and remove it from the queue).
* @return NULL if the timeout expires before an item is available
*
* @param[in] pqueue A pointer to the queue
@ -127,7 +127,7 @@ bool_t gfxQueueFSyncPut(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, delayti
/* @} */
/**
* @brief Pop an item from the head of the queue.
* @brief Pop an item from the head of the queue (and remove it from the queue).
* @detail This is exactly the same as the Get operation above.
*
* @api
@ -208,6 +208,46 @@ bool_t gfxQueueGSyncIsIn(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem);
bool_t gfxQueueFSyncIsIn(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem);
/* @} */
/**
* @brief Get the first item from the head of the queue but do not remove it from the queue.
* @return NULL if no item is available.
*
* @param[in] pqueue A pointer to the queue
*
* @note This call does not block.
* @note This can be used as the first call to iterate all the elements in the queue.
* @note As that item is still on the queue, it should be treated as read-only. It could
* also be removed from the queue at any time by another thread (thereby altering the
* queue item).
*
* @api
* @{
*/
#define gfxQueueASyncPeek(pqueue) ((const gfxQueueASyncItem *)((pqueue)->head))
#define gfxQueueGSyncPeek(pqueue) ((const gfxQueueGSyncItem *)((pqueue)->head))
#define gfxQueueFSyncPeek(pqueue) ((const gfxQueueFSyncItem *)((pqueue)->head))
/* @} */
/**
* @brief Get the next item in the queue (but do not remove it from the queue).
* @return NULL if no item is available.
*
* @param[in] pitem The previous item in the queue
*
* @note This call does not block.
* @note This can be used as subsequent calls to iterate all the elements in the queue.
* @note As that item is still on the queue, it should be treated as read-only. It could
* also be removed from the queue at any time by another thread (thereby altering the
* queue item).
*
* @api
* @{
*/
#define gfxQueueASyncNext(pitem) ((const gfxQueueASyncItem *)((pitem)->next))
#define gfxQueueGSyncNext(pitem) ((const gfxQueueGSyncItem *)((pitem)->next))
#define gfxQueueFSyncNext(pitem) ((const gfxQueueFSyncItem *)((pitem)->next))
/* @} */
#ifdef __cplusplus
}
#endif

View File

@ -24,240 +24,106 @@
#ifndef _GWIN_BUTTON_H
#define _GWIN_BUTTON_H
#if GWIN_NEED_BUTTON || defined(__DOXYGEN__)
/* This file is included within "gwin/gwidget.h" */
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
#define GW_BUTTON 0x0002
/**
* @brief The Event Type for a Button Event
*/
#define GEVENT_GWIN_BUTTON (GEVENT_GWIN_FIRST+0)
/*===========================================================================*/
/* Type definitions */
/*===========================================================================*/
typedef struct GEventGWinButton_t {
/**
* @brief A Button Event
* @note There are currently no GEventGWinButton listening flags - use 0 as the flags to @p gwinAttachListener()
*/
typedef struct GEventGWinButton {
GEventType type; // The type of this event (GEVENT_GWIN_BUTTON)
GHandle button; // The button that has been depressed (actually triggered on release)
} GEventGWinButton;
// There are currently no GEventGWinButton listening flags - use 0
typedef enum GButtonShape_e {
GBTN_3D, GBTN_SQUARE, GBTN_ROUNDED, GBTN_ELLIPSE, GBTN_CUSTOM,
GBTN_ARROW_UP, GBTN_ARROW_DOWN, GBTN_ARROW_LEFT, GBTN_ARROW_RIGHT,
} GButtonShape;
typedef struct GButtonDrawStyle_t {
color_t color_edge;
color_t color_fill;
color_t color_txt;
} GButtonDrawStyle;
typedef enum GButtonType_e {
GBTN_NORMAL, GBTN_TOGGLE
} GButtonType;
typedef enum GButtonState_e {
GBTN_UP, GBTN_DOWN
} GButtonState;
typedef void (*GButtonDrawFunction)(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
// A button window
typedef struct GButtonObject_t {
GWindowObject gwin;
GButtonDrawStyle up;
GButtonDrawStyle dn;
GButtonState state;
GButtonType type;
const char *txt;
GButtonDrawFunction fn;
void *param;
GListener listener;
/**
* @brief The button widget structure
* @note Do not use the members directly - treat it as a black-box.
*/
typedef struct GButtonObject {
GWidgetObject w;
#if GINPUT_NEED_TOGGLE
uint16_t toggle;
#endif
} GButtonObject;
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Create a button window.
* @brief Create a button widget.
* @return NULL if there is no resultant drawing area, otherwise a window handle.
*
* @param[in] gb The GButtonObject structure to initialise. If this is NULL the structure is dynamically allocated.
* @param[in] x,y The screen co-ordinates for the bottom left corner of the window
* @param[in] width The width of the window
* @param[in] height The height of the window
* @param[in] font The font to use
* @param[in] type The type of button
* @note The drawing color gets set to White and the background drawing color to Black.
* @note The dimensions and position may be changed to fit on the real screen.
* @note The button is not automatically drawn. Call gwinButtonDraw() after changing the button style or setting the text.
* @param[in] pInit The initialisation parameters
*
* @note The drawing color and the background color get set to the current defaults. If you haven't called
* @p gwinSetDefaultColor() or @p gwinSetDefaultBgColor() then these are White and Black respectively.
* @note The font gets set to the current default font. If you haven't called @p gwinSetDefaultFont() then there
* is no default font and text drawing operations will no nothing.
* @note A button remembers its normal drawing state. If there is a window manager then it is automatically
* redrawn if the window is moved or its visibility state is changed.
* @note A button supports mouse and a toggle input.
* @note When assigning a toggle, only one toggle is supported. If you try to assign more than one toggle it will
* forget the previous toggle. When assigning a toggle the role parameter must be 0.
*
* @api
*/
GHandle gwinCreateButton(GButtonObject *gb, coord_t x, coord_t y, coord_t width, coord_t height, font_t font, GButtonType type);
GHandle gwinButtonCreate(GButtonObject *gb, const GWidgetInit *pInit);
/**
* @brief Set the style of a button.
* @details The button style is defined by its shape and colours.
* @brief Is the button current pressed
* @return TRUE if the button is depressed
*
* @param[in] gh The window handle (must be a button window)
* @param[in] shape The shape of the button.
* @param[in] pUp The styling for the button when in the up state.
* @param[in] pDown The styling for the button when in the down state.
*
* @note The button is not automatically redrawn. Call gwinButtonDraw() after changing the button style
* @note The button style is copied into the internal button structure - there is no need to
* maintain a static style structures.
* @note The pUp and pDown parameters can be NULL. If they are then the existing color styles
* are not changed for that button state.
* @param[in] gh The window handle (must be a button widget)
*
* @api
*/
void gwinSetButtonStyle(GHandle gh, GButtonShape shape, const GButtonDrawStyle *pUp, const GButtonDrawStyle *pDown);
bool_t gwinButtonIsPressed(GHandle gh);
/**
* @brief Set the text of a button.
* @brief Some custom button drawing routines
* @details These function may be passed to @p gwinSetCustomDraw() to get different button drawing styles
*
* @param[in] gh The window handle (must be a button window)
* @param[in] txt The button text to set. This must be a constant string unless useAlloc is set.
* @param[in] useAlloc If TRUE the string specified will be copied into dynamically allocated memory.
* @note The button is not automatically redrawn. Call gwinButtonDraw() after changing the button text.
*
* @api
*/
void gwinSetButtonText(GHandle gh, const char *txt, bool_t useAlloc);
/**
* @brief Redraw the button.
*
* @param[in] gh The window handle (must be a button window)
*
* @api
*/
void gwinButtonDraw(GHandle gh);
/**
* @brief Enable or disable a button
*
* @param[in] gh The window handle (must be a button window)
* @param[in] enabled Enable or disable the button
*
* @api
*/
void gwinButtonSetEnabled(GHandle gh, bool_t enabled);
/**
* @brief Set the callback routine to perform a custom button drawing.
*
* @param[in] gh The window handle (must be a button window)
* @param[in] fn The function to use to draw the button
* @param[in] param A parameter to pass to the button drawing function
*
* @api
*/
void gwinSetButtonCustom(GHandle gh, GButtonDrawFunction fn, void *param);
/**
* @brief Enable a button
*
* @api
*/
#define gwinEnableButton(gh) gwinButtonSetEnabled( ((GButtonObject *)(gh)), TRUE)
/**
* @brief Disable a button
*
* @api
*/
#define gwinDisableButton(gh) gwinButtonSetEnabled( ((GButtonObject *)(gh)), FALSE)
/**
* @brief Get the state of a button
*
* @param[in] gh The window handle (must be a button window)
*
* @api
*/
#define gwinGetButtonState(gh) (((GButtonObject *)(gh))->state)
/**
* @brief Get the source handle of a button
* @details Get the source handle of a button so the application can listen for events
*
* @param[in] gh The window handle
*
* @api
*/
#define gwinGetButtonSource(gh) ((GSourceHandle)(gh))
#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
/**
* @brief Attach a mouse to a button
*
* @param[in] gh The button handle
* @param[in] instance The mouse instance
*
* @api
*/
bool_t gwinAttachButtonMouse(GHandle gh, uint16_t instance);
#endif
#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
/**
* @brief Attach a toggle to a button
*
* @param[in] gh The button handle
* @param[in] instance The toggle instance
*
* @api
*/
bool_t gwinAttachButtonToggle(GHandle gh, uint16_t instance);
#endif
/**
* @brief Standard button drawing routines
* @details These routines are called to draw the standard button styles.
*
* @param[in] gh The button handle
* @param[in] enabled Is the button currently enabled or disabled
* @param[in] isdown Is the button currently down (depressed)
* @param[in] txt The text to be display inside the button
* @param[in] pstyle The current drawing style for the state we are in
* @param[in] gw The widget object (in this case a button)
* @param[in] param A parameter passed in from the user
*
* @note In your custom button drawing function you may optionally call these
* standard functions and then draw your extra details on top.
* @note The standard functions below ignore the param parameter. It is there
* only to ensure the functions match the GButtonDrawFunction type.
* @note When called by a button press/release the framework ensure that it is
* a button object and sets up clipping to the button object window. These
* drawing routines then don't have to worry about explicitly doing that.
* @note The standard functions below ignore the param parameter except for @p gwinButtonDraw_Image().
* @note The image custom draw function @p gwinButtonDraw_Image() uses param to pass in the gdispImage pointer.
* The image must be already opened before calling @p gwinSetCustomDraw(). The image should be 3
* times the height of the button. The button image is repeated 3 times vertically, the first (top) for
* the "up" image, the 2nd for the "down" image, and the third (bottom) image for the disabled state. If
* the disabled state is never going to be used then the image can be just 2 times the button height.
* No checking is done to compare the size of the button to the size of the image.
* Note text is drawn on top of the image.
* @note These custom drawing routines don't have to worry about setting clipping as the framework
* sets clipping to the object window prior to calling these routines.
*
* @api
* @{
*/
void gwinButtonDraw_3D(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
void gwinButtonDraw_Square(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
void gwinButtonDraw_3D(GWidgetObject *gw, void *param); // @< A standard 3D button
#if GDISP_NEED_ARC || defined(__DOXYGEN__)
void gwinButtonDraw_Rounded(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
void gwinButtonDraw_Rounded(GWidgetObject *gw, void *param); // @< A rounded rectangle button
#endif
#if GDISP_NEED_ELLIPSE || defined(__DOXYGEN__)
void gwinButtonDraw_Ellipse(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
void gwinButtonDraw_Ellipse(GWidgetObject *gw, void *param); // @< A circular button
#endif
#if GDISP_NEED_CONVEX_POLYGON || defined(__DOXYGEN__)
void gwinButtonDraw_ArrowUp(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
void gwinButtonDraw_ArrowDown(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
void gwinButtonDraw_ArrowLeft(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
void gwinButtonDraw_ArrowRight(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
void gwinButtonDraw_ArrowUp(GWidgetObject *gw, void *param); // @< An up arrow button
void gwinButtonDraw_ArrowDown(GWidgetObject *gw, void *param); // @< A down arrow button
void gwinButtonDraw_ArrowLeft(GWidgetObject *gw, void *param); // @< A left arrow button
void gwinButtonDraw_ArrowRight(GWidgetObject *gw, void *param); // @< A right arrow button
#endif
#if GDISP_NEED_IMAGE || defined(__DOXYGEN__)
void gwinButtonDraw_Image(GWidgetObject *gw, void *param); // @< An image button - see the notes above on the param.
#endif
/** @} */
@ -265,8 +131,6 @@ void gwinButtonDraw_Square(GHandle gh, bool_t enabled, bool_t isdown, const char
}
#endif
#endif /* GWIN_NEED_BUTTON */
#endif /* _GWIN_BUTTON_H */
/** @} */

View File

@ -12,7 +12,7 @@
* @defgroup Checkbox Checkbox
* @ingroup GWIN
*
* @details GWIN allows it to easily create checkboxes.
* @details GWIN allows it to easily create a group of checkbox buttons.
*
* @pre GFX_USE_GWIN must be set to TRUE in your gfxconf.h
* @pre GWIN_NEED_CHECKBOX must be set to TRUE in your gfxconf.h
@ -22,143 +22,92 @@
#ifndef _GWIN_CHECKBOX_H
#define _GWIN_CHECKBOX_H
#if GWIN_NEED_CHECKBOX || defined(__DOXYGEN__)
/* This file is included within "gwin/gwidget.h" */
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
#define GW_CHECKBOX 0x0005
#define GEVENT_GWIN_CHECKBOX (GEVENT_GWIN_FIRST+2)
/*===========================================================================*/
/* Type definitions */
/*===========================================================================*/
typedef struct GEventGWinCheckbox_t {
typedef struct GEventGWinCheckbox {
GEventType type; // The type of this event (GEVENT_GWIN_CHECKBOX)
GHandle checkbox; // The checkbox that has been depressed (actually triggered on release)
bool_t isChecked; // Is the checkbox currently checked or unchecked?
} GEventGWinCheckbox;
typedef enum GCheckboxState_e {
GCHBX_UNCHECKED, GCHBX_CHECKED
} GCheckboxState;
typedef struct GCheckboxColor_t {
color_t border;
color_t checked;
color_t bg;
} GCheckboxColor;
/* custom rendering interface */
typedef void (*GCheckboxDrawFunction)(GHandle gh, bool_t enabled, bool_t state, void* param);
/* A Checkbox window */
typedef struct GCheckboxObject_t {
GWindowObject gwin;
GListener listener;
GCheckboxDrawFunction fn;
GCheckboxColor *colors;
bool_t isChecked;
void *param;
typedef struct GCheckboxObject {
GWidgetObject w;
#if GINPUT_NEED_TOGGLE
uint16_t toggle;
#endif
} GCheckboxObject;
/**
* @brief Create a checkbox window.
*
* @param[in] gb The GCheckboxObject structure to initialise. If this is NULL, the structure is dynamically allocated.
* @param[in] x,y The screen co-ordinates for the bottom left corner of the window
* @param[in] width The width of the window
* @param[in] height The height of the window
*
* @note The checkbox is not automatically drawn. Call gwinCheckboxDraw() after changing the checkbox style.
*
* @brief Create a checkbox window.
* @return NULL if there is no resultant drawing area, otherwise a window handle.
*
* @param[in] gb The GCheckboxObject structure to initialise. If this is NULL, the structure is dynamically allocated.
* @param[in] pInit The initialization parameters to use
*
* @note The drawing color and the background color get set to the current defaults. If you haven't called
* @p gwinSetDefaultColor() or @p gwinSetDefaultBgColor() then these are White and Black respectively.
* @note The font gets set to the current default font. If you haven't called @p gwinSetDefaultFont() then there
* is no default font and text drawing operations will no nothing.
* @note A checkbox remembers its normal drawing state. If there is a window manager then it is automatically
* redrawn if the window is moved or its visibility state is changed.
* @note A checkbox supports mouse and a toggle input.
* @note When assigning a toggle, only one toggle is supported. If you try to assign more than one toggle it will
* forget the previous toggle. When assigning a toggle the role parameter must be 0.
*
* @api
*/
GHandle gwinCheckboxCreate(GCheckboxObject *gb, coord_t x, coord_t y, coord_t width, coord_t height);
GHandle gwinCheckboxCreate(GCheckboxObject *gb, const GWidgetInit *pInit);
/**
* @brief Redraw a checkbox
* @brief Set the state of a checkbox
*
* @param[in] gh The window handle (must be a checkbox window)
* @param[in] isChecked TRUE to set the check, FALSE to uncheck.
*
* @api
*/
void gwinCheckboxDraw(GHandle gh);
/**
* @brief Enable or disable a button
*
* @param[in] gh The window handle (must be a checkbox window)
* @param[in] enabled Enable or disable the button
*
* @api
*/
void gwinCheckboxSetEnabled(GHandle gh, bool_t enabled);
/**
* @brief Set the callback routine to perform a custom drawing.
*
* @param[in] gh The window handle (must be a checkbox window)
* @param[in] fn The function to use to draw the checkbox
* @param[in] param A parameter to pass to the checkbox drawing function
*
* @api
*/
void gwinCheckboxSetCustom(GHandle gh, GCheckboxDrawFunction fn, void *param);
/**
* @brief Enable a checkbox
*
* @api
*/
#define gwinCheckboxEnable(gh) gwinCheckboxSetEnabled( ((GCheckboxObject *)(gh)), TRUE)
/**
* @brief Disable a checkbox
*
* @api
*/
#define gwinCheckboxDisable(gh) gwinCheckboxSetEnabled( ((GCheckboxObject *)(gh)), FALSE)
void gwinCheckboxCheck(GHandle gh, bool_t isChecked);
/**
* @brief Get the state of a checkbox
* @return TRUE if the checkbox is currently checked
*
* @param[in] gh The window handle (must be a checkbox window)
*
* @return The state of the checkbox (GCHBX_CHECKED or GCHBX_UNCHECKED)
*
* @api
*/
#define gwinCheckboxGetState(gh) (((GCheckboxObject *)(gh))->isChecked)
bool_t gwinCheckboxIsChecked(GHandle gh);
/**
* @brief Get the source handle of a checkbox
* @details Get the source handle of a checkbox so the application can listen for events
* @brief Some custom checkbox drawing routines
* @details These function may be passed to @p gwinSetCustomDraw() to get different checkbox drawing styles
*
* @param[in] gh The window handle (must be a checkbox window)
* @param[in] gw The widget (which must be a checkbox)
* @param[in] param A parameter passed in from the user
*
* @note In your custom checkbox drawing function you may optionally call this
* standard functions and then draw your extra details on top.
* @note The standard functions below ignore the param parameter.
* @note These custom drawing routines don't have to worry about setting clipping as the framework
* sets clipping to the object window prior to calling these routines.
*
* @api
* @{
*/
#define gwinCheckboxGetSource(gh) ((GSourceHandle)(gh))
#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
/**
* @brief Attach a mouse to a checkbox
*
* @param[in] gh The checkbox handle
* @param[in] instance The mouse instance
*
* @api
*/
bool_t gwinCheckboxAttachMouse(GHandle gh, uint16_t instance);
#endif /* GFX_USE_GINPUT && GINPUT_NEED_MOUSE */
#endif /* _GWIN_NEED_CHECKBOX */
void gwinCheckboxDraw_CheckOnLeft(GWidgetObject *gw, void *param);
void gwinCheckboxDraw_CheckOnRight(GWidgetObject *gw, void *param);
/* @} */
#endif /* _GWIN_CHECKBOX_H */
/** @} */

View File

@ -0,0 +1,200 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://chibios-gfx.com/license.html
*/
/**
* @file include/gwin/class_gwin.h
* @brief GWIN Graphic window subsystem header file.
*
* @defgroup Internal Internal
* @ingroup GWIN
*
* @note These definitions are normally not used by an application program. They are useful
* only if you want to create your own custom GWIN window or widget.
* @note To access these definitions you must include "gwin/class_gwin.h" in your source file.
*
* @{
*/
#ifndef _CLASS_GWIN_H
#define _CLASS_GWIN_H
#if GFX_USE_GWIN || defined(__DOXYGEN__)
/**
* @brief The predefined flags for a Window
* @{
*/
#define GWIN_FLG_DYNAMIC 0x0001 // @< The GWIN structure is allocated
#define GWIN_FLG_VISIBLE 0x0002 // @< The window is visible
#define GWIN_FLG_MINIMIZED 0x0004 // @< The window is minimized
#define GWIN_FLG_MAXIMIZED 0x0008 // @< The window is maximized
#define GWIN_FLG_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
/* @} */
/**
* @brief The Virtual Method Table for a GWIN window
* @{
*/
typedef struct gwinVMT {
const char * classname; // @< The GWIN classname (mandatory)
size_t size; // @< The size of the class object
void (*Destroy) (GWindowObject *gh); // @< The GWIN destroy function (optional)
void (*Redraw) (GWindowObject *gh); // @< The GWIN redraw routine (optional)
void (*AfterClear) (GWindowObject *gh); // @< The GWIN after-clear function (optional)
} gwinVMT;
/* @} */
#if GWIN_NEED_WIDGET || defined(__DOXYGEN__)
/**
* @brief An toggle/dial instance is not being used
*/
#define GWIDGET_NO_INSTANCE ((uint16_t)-1)
/**
* @brief The source handle that widgets use when sending events
*/
#define GWIDGET_SOURCE ((GSourceHandle)(void *)_gwidgetCreate)
/**
* @brief The Virtual Method Table for a widget
* @note A widget must have a destroy function. Either use @p _gwidgetDestroy() or use your own function
* which internally calls @p _gwidgetDestroy().
* @note A widget must have a redraw function. Use @p _gwidgetRedraw().
* @note If toggleroles != 0, ToggleAssign(), ToggleGet() and one or both of ToggleOff() and ToggleOn() must be specified.
* @note If dialroles != 0, DialAssign(), DialGet() and DialMove() must be specified.
* @{
*/
typedef struct gwidgetVMT {
struct gwinVMT g; // @< This is still a GWIN
void (*DefaultDraw) (GWidgetObject *gw, void *param); // @< The default drawing routine (mandatory)
#if GINPUT_NEED_MOUSE
struct {
void (*MouseDown) (GWidgetObject *gw, coord_t x, coord_t y); // @< Process mouse down events (optional)
void (*MouseUp) (GWidgetObject *gw, coord_t x, coord_t y); // @< Process mouse up events (optional)
void (*MouseMove) (GWidgetObject *gw, coord_t x, coord_t y); // @< Process mouse move events (optional)
};
#endif
#if GINPUT_NEED_TOGGLE
struct {
uint16_t toggleroles; // @< The roles supported for toggles (0->toggleroles-1)
void (*ToggleAssign) (GWidgetObject *gw, uint16_t role, uint16_t instance); // @< Assign a toggle to a role (optional)
uint16_t (*ToggleGet) (GWidgetObject *gw, uint16_t role); // @< Return the instance for a particular role (optional)
void (*ToggleOff) (GWidgetObject *gw, uint16_t role); // @< Process toggle off events (optional)
void (*ToggleOn) (GWidgetObject *gw, uint16_t role); // @< Process toggle on events (optional)
};
#endif
#if GINPUT_NEED_TOGGLE
struct {
uint16_t dialroles; // @< The roles supported for dials (0->dialroles-1)
void (*DialAssign) (GWidgetObject *gw, uint16_t role, uint16_t instance); // @< Test the role and save the dial instance handle (optional)
uint16_t (*DialGet) (GWidgetObject *gw, uint16_t role); // @< Return the instance for a particular role (optional)
void (*DialMove) (GWidgetObject *gw, uint16_t role, uint16_t value, uint16_t max); // @< Process dial move events (optional)
};
#endif
} gwidgetVMT;
/* @} */
#endif
#if GWIN_NEED_WINDOWMANAGER || defined(__DOXYGEN__)
#if 1 // When we know that wmq is the first element of the GWindowObject structure
#define QItem2GWindow(qi) ((GHandle)qi)
#else
#define QItem2GWindow(qi) ((GHandle)(((char *)(qi)) - (size_t)(&(((GWindowObject *)0)->wmq))))
#endif
// @note There is only ever one instance of each GWindowManager type
typedef struct GWindowManager {
const struct gwmVMT *vmt;
} GWindowManager;
/**
* @brief The Virtual Method Table for a window manager
* @{
*/
typedef struct gwmVMT {
void (*Init) (void); // @< The window manager has just been set as the current window manager
void (*DeInit) (void); // @< The window manager has just been removed as the current window manager
bool_t (*Add) (GHandle gh, const GWindowInit *pInit); // @< A window has been added
void (*Delete) (GHandle gh); // @< A window has been deleted
void (*Visible) (GHandle gh); // @< A window has changed its visibility state
void (*Redim) (GHandle gh, coord_t x, coord_t y, coord_t w, coord_t h); // @< A window wants to be moved or resized
void (*Raise) (GHandle gh); // @< A window wants to be on top
void (*MinMax) (GHandle gh, GWindowMinMax minmax); // @< A window wants to be minimized/maximised
} gwmVMT;
/* @} */
/**
* @brief The list of all windows in the system
*/
extern gfxQueueASync _GWINList;
/**
* @brief The current window manager
*/
extern GWindowManager * _GWINwm;
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Initialise (and allocate if necessary) the base GWIN object
*
* @param[in] pgw The GWindowObject structure. If NULL one is allocated from the heap
* @param[in] pInit The user initialization parameters
* @param[in] vmt The virtual method table for the GWIN object
* @param[in] flags The default flags to use
*
* @notapi
*/
GHandle _gwindowCreate(GWindowObject *pgw, const GWindowInit *pInit, const gwinVMT *vmt, uint16_t flags);
#if GWIN_NEED_WIDGET || defined(__DOXYGEN__)
/**
* @brief Initialise (and allocate if necessary) the base Widget object
*
* @param[in] pgw The GWidgetObject structure. If NULL one is allocated from the heap
* @param[in] pInit The user initialization parameters
* @param[in] vmt The virtual method table for the Widget object
*
* @notapi
*/
GHandle _gwidgetCreate(GWidgetObject *pgw, const GWidgetInit *pInit, const gwidgetVMT *vmt);
/**
* @brief Destroy the Widget object
*
* @param[in] gh The widget to destroy
*
* @notapi
*/
void _gwidgetDestroy(GHandle gh);
/**
* @brief Redraw the Widget object
*
* @param[in] gh The widget to redraw
*
* @notapi
*/
void _gwidgetRedraw(GHandle gh);
#endif
#ifdef __cplusplus
}
#endif
#endif /* GFX_USE_GWIN */
#endif /* _CLASS_GWIN_H */
/** @} */

View File

@ -24,22 +24,13 @@
#ifndef _GWIN_CONSOLE_H
#define _GWIN_CONSOLE_H
#if GWIN_NEED_CONSOLE || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
#define GW_CONSOLE 0x0001
/*===========================================================================*/
/* Type definitions */
/*===========================================================================*/
/* This file is included within "gwin/gwin.h" */
// A console window. Supports wrapped text writing and a cursor.
typedef struct GConsoleObject_t {
GWindowObject gwin;
typedef struct GConsoleObject {
GWindowObject g;
coord_t cx, cy; // Cursor position
#if GFX_USE_OS_CHIBIOS && GWIN_CONSOLE_USE_BASESTREAM
struct GConsoleWindowStream_t {
const struct GConsoleWindowVMT_t *vmt;
@ -47,38 +38,33 @@ typedef struct GConsoleObject_t {
} stream;
#endif
coord_t cx,cy; // Cursor position
uint8_t fy; // Current font height
uint8_t fp; // Current font inter-character spacing
} GConsoleObject;
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Create a console window.
* @details A console window allows text to be written using chprintf() (and the console functions defined here).
* @brief Text in a console window supports newlines and will wrap text as required.
* @details A console window allows text to be written.
* @note Text in a console window supports newlines and will wrap text as required.
* @return NULL if there is no resultant drawing area, otherwise a window handle.
*
* @param[in] gc The GConsoleObject structure to initialise. If this is NULL the structure is dynamically allocated.
* @param[in] x,y The screen co-ordinates for the bottom left corner of the window
* @param[in] width The width of the window
* @param[in] height The height of the window
* @param[in] font The font to use
* @note The console is not automatically cleared on creation. You must do that by calling gwinClear() (possibly after changing your background color)
* @note If the dispay does not support scrolling, the window will be cleared when the bottom line is reached.
* @note The default drawing color gets set to White and the background drawing color to Black.
* @note The dimensions and position may be changed to fit on the real screen.
* @param[in] pInit The initialization parameters to use
*
* @note The drawing color and the background color get set to the current defaults. If you haven't called
* @p gwinSetDefaultColor() or @p gwinSetDefaultBgColor() then these are White and Black respectively.
* @note The font gets set to the current default font. If you haven't called @p gwinSetDefaultFont() then there
* is no default font and text drawing operations will no nothing.
* @note On creation even if the window is visible it is not automatically cleared.
* You may do that by calling @p gwinClear() (possibly after changing your background color)
* @note A console does not save the drawing state. It is not automatically redrawn if the window is moved or
* its visibility state is changed.
*
* @api
*/
GHandle gwinCreateConsole(GConsoleObject *gc, coord_t x, coord_t y, coord_t width, coord_t height, font_t font);
GHandle gwinConsoleCreate(GConsoleObject *gc, const GWindowInit *pInit);
#if GFX_USE_OS_CHIBIOS && GWIN_CONSOLE_USE_BASESTREAM
/**
@ -91,7 +77,7 @@ GHandle gwinCreateConsole(GConsoleObject *gc, coord_t x, coord_t y, coord_t widt
*
* @api
*/
BaseSequentialStream *gwinGetConsoleStream(GHandle gh);
BaseSequentialStream *gwinConsoleGetStream(GHandle gh);
#endif
/**
@ -157,7 +143,5 @@ void gwinPrintf(GHandle gh, const char *fmt, ...);
}
#endif
#endif /* GWIN_NEED_CONSOLE */
#endif /* _GWIN_CONSOLE_H */
/** @} */

View File

@ -22,20 +22,7 @@
#ifndef _GWIN_GRAPH_H
#define _GWIN_GRAPH_H
#if GWIN_NEED_GRAPH || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
#define GW_GRAPH 0x0003
/*===========================================================================*/
/* Type definitions */
/*===========================================================================*/
// GDISP now has its own point structure
#define GGraphPoint point
/* This file is included within "gwin/gwin.h" */
typedef enum GGraphPointType_e {
GGRAPH_POINT_NONE, GGRAPH_POINT_DOT, GGRAPH_POINT_SQUARE, GGRAPH_POINT_CIRCLE
@ -84,8 +71,8 @@ typedef struct GGraphStyle_t {
} GGraphStyle;
// A graph window
typedef struct GGraphObject_t {
GWindowObject gwin;
typedef struct GGraphObject {
GWindowObject g;
GGraphStyle style;
coord_t xorigin, yorigin;
coord_t lastx, lasty;
@ -104,10 +91,15 @@ extern "C" {
* @return NULL if there is no resultant drawing area, otherwise a window handle.
*
* @param[in] gg The GGraphObject structure to initialise. If this is NULL the structure is dynamically allocated.
* @param[in] x,y The screen co-ordinates for the bottom left corner of the window
* @param[in] width The width of the window
* @param[in] height The height of the window
* @note The console is not automatically cleared on creation. You must do that by calling gwinClear() (possibly after changing your background color)
* @param[in] pInit The initialization parameters to use
*
* @note The drawing color and the background color get set to the current defaults. If you haven't called
* @p gwinSetDefaultColor() or @p gwinSetDefaultBgColor() then these are White and Black respectively.
* @note The font gets set to the current default font. If you haven't called @p gwinSetDefaultFont() then there
* is no default font and text drawing operations will no nothing.
* @note The dimensions and position may be changed to fit on the real screen.
* @note A graph does not save the drawing state. It is not automatically redrawn if the window is moved or
* its visibility state is changed.
* @note The coordinate system within the window for graphing operations (but not for any other drawing
* operation) is relative to the bottom left corner and then shifted right and up by the specified
* graphing x and y origin. Note that this system is inverted in the y direction relative to the display.
@ -115,7 +107,7 @@ extern "C" {
*
* @api
*/
GHandle gwinCreateGraph(GGraphObject *gg, coord_t x, coord_t y, coord_t width, coord_t height);
GHandle gwinGraphCreate(GGraphObject *gg, const GWindowInit *pInit);
/**
* @brief Set the style of the graphing operations.
@ -187,8 +179,6 @@ void gwinGraphDrawPoints(GHandle gh, const point *points, unsigned count);
}
#endif
#endif /* GWIN_NEED_GRAPH */
#endif /* _GWIN_GRAPH_H */
/** @} */

View File

@ -0,0 +1,291 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://chibios-gfx.com/license.html
*/
/**
* @file include/gwin/gwidget.h
* @brief GWIN Widgets header file.
*/
#ifndef _GWIDGET_H
#define _GWIDGET_H
/* This file is included within "gwin/gwin.h" */
/**
* @defgroup Widget Widget
* @ingroup GWIN
*
* @details A Widget is a GWindow that supports interacting with the user
* via an input device such as a mouse or toggle buttons. It is the
* base class for widgets such as buttons and sliders.
*
* @pre GFX_USE_GWIN and GWIN_NEED_WIDGET must be set to TRUE in your gfxconf.h
* @{
*/
// Forward definition
struct GWidgetObject;
/**
* @brief The GColorSet structure
* @{
*/
typedef struct GColorSet {
color_t text; // @< The text color
color_t edge; // @< The edge color
color_t fill; // @< The fill color
color_t progress; // @< The color of progress bars
} GColorSet;
/* @} */
/**
* @brief The GWidgetStyle structure
* @details A GWidgetStyle is a set of colors that together form a "style".
* These colors should not be confused with the GWindow foreground
* and background colors which are used for drawing operations.
* @{
*/
typedef struct GWidgetStyle {
color_t background; // @< The window background color
GColorSet enabled; // @< The colors when enabled
GColorSet disabled; // @< The colors when disabled
GColorSet pressed; // @< The colors when pressed
} GWidgetStyle;
/* @} */
/**
* @brief We define a couple of GWidgetStyle's that you can use in your
* application. The Black style is the default style if you don't
* specify one.
* @note BlackWidgetStyle means that it is designed for a Black background.
* Similarly WhiteWidgetStyle is designed for a White background.
* @{
*/
extern const GWidgetStyle BlackWidgetStyle;
extern const GWidgetStyle WhiteWidgetStyle;
/* @} */
/**
* @brief Defines a custom drawing function for a widget
*/
typedef void (*CustomWidgetDrawFunction)(struct GWidgetObject *gw, void *param);
/**
* @brief The structure to initialise a widget.
*
* @note Some widgets may have extra parameters.
* @note The text element must be static string (not stack allocated). If you want to use
* a dynamic string (eg a stack allocated string) use NULL for this member and then call
* @p gwinSetText() with useAlloc set to TRUE.
*
* @{
*/
typedef struct GWidgetInit {
GWindowInit g; // @< The GWIN initializer
const char * text; // @< The initial text
CustomWidgetDrawFunction customDraw; // @< A custom draw function - use NULL for the standard
void * customParam; // @< A parameter for the custom draw function (default = NULL)
const GWidgetStyle * customStyle; // @< A custom style to use - use NULL for the default style
} GWidgetInit;
/* @} */
/**
* @brief The GWIN Widget structure
* @note A widget is a GWIN window that accepts user input.
* It also has a number of other properties such as its ability
* to redraw itself (a widget maintains drawing state).
* @note Do not access the members directly. Treat it as a black-box and use the method functions.
*
* @{
*/
typedef struct GWidgetObject {
GWindowObject g; // @< This is still a GWIN
const char * text; // @< The widget text
CustomWidgetDrawFunction fnDraw; // @< The current draw function
void * fnParam; // @< A parameter for the current draw function
const GWidgetStyle * pstyle; // @< The current widget style colors
} GWidgetObject;
/* @} */
/**
* A comment/rant on the above structure:
* We would really like the GWindowObject member to be anonymous. While this is
* allowed under the C11, C99, GNU and various other standards which have been
* around forever - compiler support often requires special flags e.g
* gcc requires the -fms-extensions flag (no wonder the language and compilers have
* not really progressed in 30 years). As portability is a key requirement
* we unfortunately won't use this useful feature in case we get a compiler that
* won't support it even with special flags.
*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Set the default style for widgets created hereafter.
*
* @param[in] pstyle The default style. Passing NULL uses the system compiled style.
* @param[in] updateAll If TRUE then all existing widgets that are using the current default style
* will be updated to use this new style. Widgets that have custom styles different
* from the default style will not be updated.
*
* @note The style must be allocated statically (not on the stack) as only the pointer is stored.
*
* @api
*/
void gwinSetDefaultStyle(const GWidgetStyle *pstyle, bool_t updateAll);
/**
* @brief Get the current default style.
*
* @api
*/
const GWidgetStyle *gwinGetDefaultStyle(void);
/**
* @brief Set the text of a widget.
*
* @param[in] gh The widget handle
* @param[in] text The text to set. This must be a constant string unless useAlloc is set.
* @param[in] useAlloc If TRUE the string specified will be copied into dynamically allocated memory.
*
* @note The widget is automatically redrawn
* @note Non-widgets will ignore this call.
*
* @api
*/
void gwinSetText(GHandle gh, const char *text, bool_t useAlloc);
/**
* @brief Get the text of a widget.
* @return The widget text or NULL if it isn't a widget
*
* @param[in] gh The widget handle
*
* @api
*/
const char *gwinGetText(GHandle gh);
/**
* @brief Set the style of a widget.
*
* @param[in] gh The widget handle
* @param[in] pstyle The style to set. This must be a static structure (not allocated on a transient stack).
* Use NULL to reset to the default style.
*
* @note The widget is automatically redrawn
* @note Non-widgets will ignore this call.
*
* @api
*/
void gwinSetStyle(GHandle gh, const GWidgetStyle *pstyle);
/**
* @brief Get the style of a widget.
* @return The widget style or NULL if it isn't a widget
*
* @param[in] gh The widget handle
*
* @api
*/
const GWidgetStyle *gwinGetStyle(GHandle gh);
/**
* @brief Set the routine to perform a custom widget drawing.
*
* @param[in] gh The widget handle
* @param[in] fn The function to use to draw the widget
* @param[in] param A parameter to pass to the widget drawing function
*
* @note The widget is not automatically redrawn. Call @p gwinDraw() to redraw the widget.
* @note Non-widgets will ignore this call.
*
* @api
*/
void gwinSetCustomDraw(GHandle gh, CustomWidgetDrawFunction fn, void *param);
/**
* @brief Attach a Listener to listen for widget events
* @return TRUE on success
*
* @param[in] pl The listener
*
* @api
*/
bool_t gwinAttachListener(GListener *pl);
#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
/**
* @brief Set the mouse to be used to control the widgets
* @return TRUE on success
*
* @param[in] instance The mouse instance
*
* @note Every widget uses the same mouse.
*
* @api
*/
bool_t gwinAttachMouse(uint16_t instance);
#endif
#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
/**
* @brief Attach a toggle to a widget
* @return TRUE on success
*
* @param[in] gh The widget handle
* @param[in] role The function the toggle will perform for the widget
* @param[in] instance The toggle instance
*
* @note See the documentation on the specific widget to see the possible
* values for the role parameter. If it is out of range, this function
* will return FALSE
*
* @api
*/
bool_t gwinAttachToggle(GHandle gh, uint16_t role, uint16_t instance);
#endif
#if GFX_USE_GINPUT && GINPUT_NEED_DIAL
/**
* @brief Attach a toggle to a widget
* @return TRUE on success
*
* @param[in] gh The widget handle
* @param[in] role The function the dial will perform for the widget
* @param[in] instance The dial instance
*
* @note See the documentation on the specific widget to see the possible
* values for the role parameter. If it is out of range, this function
* will return FALSE
*
* @api
*/
bool_t gwinAttachDial(GHandle gh, uint16_t role, uint16_t instance);
#endif
#ifdef __cplusplus
}
#endif
/* Include extra widget types */
#if GWIN_NEED_BUTTON || defined(__DOXYGEN__)
#include "gwin/button.h"
#endif
#if GWIN_NEED_SLIDER || defined(__DOXYGEN__)
#include "gwin/slider.h"
#endif
#if GWIN_NEED_CHECKBOX || defined(__DOXYGEN__)
#include "gwin/checkbox.h"
#endif
#if GWIN_NEED_RADIO || defined(__DOXYGEN__)
#include "gwin/radio.h"
#endif
#endif /* _GWIDGET_H */
/** @} */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,113 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://chibios-gfx.com/license.html
*/
/**
* @file include/gwin/image.h
* @brief GWIN image widget header file.
*
* @defgroup Image Image
* @ingroup GWIN
*
* @details GWIN allos it to create an image widget. The widget
* takes no user input.
*
* @pre GFX_USE_GDISP must be set to TRUE in your gfxconf.h
* @pre GFX_USE_GWIN must be set to TRUE in your gfxconf.h
* @pre GDISP_NEED_IMAGE must be set to TRUE in your gfxconf.h
* @pre GWIN_NEED_IMAGE must be set to TRUE in your gfxconf.h
* @pre At least one image type must be enabled in your gfxconf.h
*
* @{
*/
#ifndef _GWIN_IMAGE_H
#define _GWIN_IMAGE_H
// This file is included within "gwin/gwin.h"
// An image window
typedef struct GImageObject {
GWindowObject g;
gdispImage image;
} GImageObject;
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Create an image widget.
* @details Display's a picture.
* @return NULL if there is no resultant drawing area, otherwise the widget handle.
*
* @param[in] widget The image widget structure to initialise. If this is NULL, the structure is dynamically allocated.
* @param[in] pInit The initialization parameters to use.
*
* @note The default background color gets set to the current default one.
* @note An image window knows how to redraw.
*
* @api
*/
GHandle gwinImageCreate(GImageObject *widget, GWindowInit *pInit);
/**
* @brief Sets the input routines that support reading the image from memory
* in RAM or flash.
* @return TRUE if the IO open function succeeds
*
* @param[in] gh The widget (must be an image widget)
* @param[in] memory A pointer to the image in RAM or Flash
*
* @api
*/
bool_t gwinImageOpenMemory(GHandle gh, const void* memory);
#if defined(WIN32) || GFX_USE_OS_WIN32 || GFX_USE_OS_POSIX || defined(__DOXYGEN__)
/**
* @brief Sets the input routines that support reading the image from a file
* @return TRUE if the IO open function succeeds
*
* @param[in] gh The widget (must be an image widget)
* @param[in] filename The filename to open
*
* @api
*/
bool_t gwinImageOpenFile(GHandle gh, const char* filename);
#endif
#if GFX_USE_OS_CHIBIOS || defined(__DOXYGEN__)
/**
* @brief Sets the input routines that support reading the image from a BaseFileStream (eg. an SD-Card).
* @return TRUE if the IO open function succeeds
*
* @param[in] gh The widget (must be an image widget)
* @param[in] streamPtr A pointer to the (open) BaseFileStream object.
*
* @api
*/
bool_t gwinImageOpenStream(GHandle gh, void *streamPtr);
#endif
/**
* @brief Cache the image.
* @details Decodes and caches the current frame into RAM.
*
* param[in] gh The widget (must be an image widget)
*
* @return GDISP_IMAGE_ERR_OK (0) on success or an error code.
*
* @api
*/
gdispImageError gwinImageCache(GHandle gh);
#ifdef __cplusplus
}
#endif
#endif // _GWIN_IMAGE_H
/** @} */

View File

@ -1,41 +0,0 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://chibios-gfx.com/license.html
*/
/**
* @file include/gwin/internal.h
* @brief GWIN Graphic window subsystem header file.
*
* @addtogroup GWIN
* @{
*/
#ifndef _GWIN_INTERNAL_H
#define _GWIN_INTERNAL_H
#if GFX_USE_GWIN || defined(__DOXYGEN__)
/*===========================================================================*/
/* Sub-system constants. */
/*===========================================================================*/
#define GWIN_FLG_DYNAMIC 0x0001
#define GBTN_FLG_ALLOCTXT 0x0002
#define GWIN_FIRST_CONTROL_FLAG 0x0004
#ifdef __cplusplus
extern "C" {
#endif
GHandle _gwinInit(GWindowObject *gw, coord_t x, coord_t y, coord_t width, coord_t height, size_t size);
#ifdef __cplusplus
}
#endif
#endif /* GFX_USE_GWIN */
#endif /* _GWIN_INTERNAL_H */
/** @} */

View File

@ -0,0 +1,60 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://chibios-gfx.com/license.html
*/
/**
* @file include/gwin/label.h
* @brief GWIN label widget header file.
*
* @defgroup Label Label
* @ingroup GWIN
*
* @details GWIN allos it to create an label widget. The widget
* takes no user input.
*
* @pre GFX_USE_GDISP must be set to TRUE in your gfxconf.h
* @pre GFX_USE_GWIN must be set to TRUE in your gfxconf.h
* @pre GDISP_NEED_TEXT must be set to TRUE in your gfxconf.h
* @pre GWIN_NEED_LABEL must be set to TRUE in your gfxconf.h
* @pre The fonts you want to use must be enabled in your gfxconf.h
*
* @{
*/
#ifndef _GWIN_LABEL_H
#define _GWIN_LABEL_H
// This file is included within "gwin/gwin.h"
// An label window
typedef struct GLabelObject {
GWidgetObject w;
} GLabelObject;
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Create a label widget.
* @details A label widget is a simple window which has a static text.
*
* @param[in] widget The label structure to initialise. If this is NULL, the structure is dynamically allocated.
* @param[in] pinit The initialisation parameters to use.
*
* @return NULL if there is no resultat drawing area, otherwise the widget handle.
*
* @api
*/
GHandle gwinLabelCreate(GLabelObject *widget, GWidgetInit *pInit);
#ifdef __cplusplus
}
#endif
#endif // _GWIN_LABEL_H
/** @} */

View File

@ -21,20 +21,22 @@
* @{
*/
/**
* @brief Should button functions be included.
* @brief Should window manager support be included
* @details Defaults to FALSE
*/
#ifndef GWIN_NEED_BUTTON
#define GWIN_NEED_BUTTON FALSE
#ifndef GWIN_NEED_WINDOWMANAGER
#define GWIN_NEED_WIDGET FALSE
#endif
/**
* @brief Should widget functions be included. Needed for any widget (eg Buttons, Sliders etc)
* @details Defaults to FALSE
*/
#ifndef GWIN_NEED_WIDGET
#define GWIN_NEED_WIDGET FALSE
#endif
/**
* @brief Should console functions be included.
* @details Defaults to FALSE
* @note To use chprintf() for printing in a console window you need to
* include in your application source file...
* \#include "chprintf.h"
* Also in your makefile, as part of your list of C source files, include
* ${CHIBIOS}/os/various/chprintf.c
*/
#ifndef GWIN_NEED_CONSOLE
#define GWIN_NEED_CONSOLE FALSE
@ -46,6 +48,13 @@
#ifndef GWIN_NEED_GRAPH
#define GWIN_NEED_GRAPH FALSE
#endif
/**
* @brief Should button functions be included.
* @details Defaults to FALSE
*/
#ifndef GWIN_NEED_BUTTON
#define GWIN_NEED_BUTTON FALSE
#endif
/**
* @brief Should slider functions be included.
* @details Defaults to FALSE
@ -53,6 +62,34 @@
#ifndef GWIN_NEED_SLIDER
#define GWIN_NEED_SLIDER FALSE
#endif
/**
* @brief Should checkbox functions be included.
* @details Defaults to FALSE
*/
#ifndef GWIN_NEED_CHECKBOX
#define GWIN_NEED_CHECKBOX FALSE
#endif
/**
* @brief Should image functions be included.
* @details Defaults to FALSE
*/
#ifndef GWIN_NEED_IMAGE
#define GWIN_NEED_IMAGE FALSE
#endif
/**
* @brief Should label functions be included.
* @details Defaults to FALSE
*/
#ifndef GWIN_NEED_LABEL
#define GWIN_NEED_LABEL FALSE
#endif
/**
* @brief Should radio button functions be included.
* @details Defaults to FALSE
*/
#ifndef GWIN_NEED_RADIO
#define GWIN_NEED_RADIO FALSE
#endif
/**
* @}
*
@ -76,6 +113,12 @@
/**
* @brief Console Windows need BaseStreamSequential support (ChibiOS only)
* @details Defaults to FALSE
* @note To use the ChibiOS basestream functions such as chprintf()
* for printing in a console window you need to set this option to
* TRUE in your gfxconf.h and include in your application source file...
* \#include "chprintf.h"
* In your makefile, as part of your list of C source files, include
* ${CHIBIOS}/os/various/chprintf.c
*/
#ifndef GWIN_CONSOLE_USE_BASESTREAM
#define GWIN_CONSOLE_USE_BASESTREAM FALSE

View File

@ -0,0 +1,138 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://chibios-gfx.com/license.html
*/
/**
* @file include/gwin/radio.h
* @brief GWIN Graphic window subsystem header file.
*
* @defgroup RadioButton RadioButton
* @ingroup GWIN
*
* @details GWIN allows it to easily create radio buttons with different styles.
*
* @pre GFX_USE_GWIN must be set to TRUE in your gfxconf.h
* @pre GWIN_NEED_RADIO must be set to TRUE in your gfxconf.h
* @{
*/
#ifndef _GWIN_RADIO_H
#define _GWIN_RADIO_H
/* This file is included within "gwin/gwidget.h" */
/**
* @brief The Event Type for a Radio Event
*/
#define GEVENT_GWIN_RADIO (GEVENT_GWIN_FIRST+3)
/**
* @brief A Button Event
* @note There are currently no GEventGWinRadio listening flags - use 0 as the flags to @p gwinAttachListener()
*/
typedef struct GEventGWinRadio {
GEventType type; // The type of this event (GEVENT_GWIN_RADIO)
GHandle radio; // The radio button that has been depressed
uint16_t group; // The group for this radio button
} GEventGWinRadio;
/**
* @brief The radio button widget structure
* @note Do not use the members directly - treat it as a black-box.
*/
typedef struct GRadioObject {
GWidgetObject w;
#if GINPUT_NEED_TOGGLE
uint16_t toggle;
#endif
uint16_t group;
} GRadioObject;
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Create a radio widget.
* @return NULL if there is no resultant drawing area, otherwise a window handle.
*
* @param[in] gb The GRadioObject structure to initialise. If this is NULL the structure is dynamically allocated.
* @param[in] pInit The initialisation parameters
* @param[in] group The group of radio buttons this radio button belongs to.
*
* @note Only one radio button in any group is ever pressed at one time. Pressing one radio button will
* release all others in the group.
* @note The drawing color and the background color get set to the current defaults. If you haven't called
* @p gwinSetDefaultColor() or @p gwinSetDefaultBgColor() then these are White and Black respectively.
* @note The font gets set to the current default font. If you haven't called @p gwinSetDefaultFont() then there
* is no default font and text drawing operations will no nothing.
* @note A radio button remembers its normal drawing state. If there is a window manager then it is automatically
* redrawn if the window is moved or its visibility state is changed.
* @note A radio button supports mouse and a toggle input.
* @note When assigning a toggle, only one toggle is supported. If you try to assign more than one toggle it will
* forget the previous toggle. When assigning a toggle the role parameter must be 0.
*
* @api
*/
GHandle gwinRadioCreate(GRadioObject *gb, const GWidgetInit *pInit, uint16_t group);
/**
* @brief Press this radio button (and by definition unset any others in the group)
*
* @param[in] gh The window handle (must be a radio widget)
*
* @api
*/
void gwinRadioPress(GHandle gh);
/**
* @brief Is the radio button currently pressed
* @return TRUE if the button is pressed
*
* @param[in] gh The window handle (must be a radio widget)
*
* @api
*/
bool_t gwinRadioIsPressed(GHandle gh);
/**
* @brief Find the currently pressed radio button in the specified group
* @return The handle of the pressed radio button or NULL if none are pressed
*
* @param[in] gh The window handle (must be a radio widget)
*
* @api
*/
GHandle gwinRadioGetActive(uint16_t group);
/**
* @brief Some custom radio button drawing routines
* @details These function may be passed to @p gwinSetCustomDraw() to get different radio button drawing styles
*
* @param[in] gw The widget object (in this case a radio button)
* @param[in] param A parameter passed in from the user
*
* @note In your custom radio drawing function you may optionally call these
* standard functions and then draw your extra details on top.
* @note The standard functions below ignore the param parameter.
* @note These custom drawing routines don't have to worry about setting clipping as the framework
* sets clipping to the object window prior to calling these routines.
*
* @api
* @{
*/
void gwinRadioDraw_Radio(GWidgetObject *gw, void *param); // @< A standard radio button
void gwinRadioDraw_Button(GWidgetObject *gw, void *param); // @< Draw as a button
void gwinRadioDraw_Tab(GWidgetObject *gw, void *param); // @< Draw as a tab
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* _GWIN_RADIO_H */
/** @} */

View File

@ -22,20 +22,11 @@
#ifndef _GWIN_SLIDER_H
#define _GWIN_SLIDER_H
#if GWIN_NEED_SLIDER || defined(__DOXYGEN__)
/* This file is included within "gwin/gwidget.h" */
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
#define GW_SLIDER 0x0004
#define GEVENT_GWIN_SLIDER (GEVENT_GWIN_FIRST+1)
/*===========================================================================*/
/* Type definitions */
/*===========================================================================*/
typedef struct GEventGWinSlider_t {
typedef struct GEventGWinSlider {
GEventType type; // The type of this event (GEVENT_GWIN_BUTTON)
GHandle slider; // The slider that is returning results
int position;
@ -43,33 +34,22 @@ typedef struct GEventGWinSlider_t {
// There are currently no GEventGWinSlider listening flags - use 0
typedef struct GSliderDrawStyle_t {
color_t color_edge;
color_t color_thumb;
color_t color_active;
color_t color_inactive;
} GSliderDrawStyle;
typedef void (*GSliderDrawFunction)(GHandle gh, bool_t isVertical, coord_t thumbpos, const GSliderDrawStyle *pstyle, void *param);
// A slider window
typedef struct GSliderObject_t {
GWindowObject gwin;
GSliderDrawStyle style;
bool_t tracking;
typedef struct GSliderObject {
GWidgetObject w;
#if GINPUT_NEED_TOGGLE
uint16_t t_dn;
uint16_t t_up;
#endif
#if GINPUT_NEED_DIAL
uint16_t dial;
#endif
coord_t dpos;
int min;
int max;
int pos;
GSliderDrawFunction fn;
void *param;
GListener listener;
} GSliderObject;
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
@ -79,17 +59,25 @@ extern "C" {
* @return NULL if there is no resultant drawing area, otherwise a window handle.
*
* @param[in] gb The GSliderObject structure to initialise. If this is NULL the structure is dynamically allocated.
* @param[in] x,y The screen co-ordinates for the bottom left corner of the window
* @param[in] width The width of the window
* @param[in] height The height of the window
* @note The drawing color gets set to White and the background drawing color to Black.
* @note The dimensions and position may be changed to fit on the real screen.
* @note The slider is not automatically drawn. Call gwinSliderDraw() after changing the slider style.
* @note Sets the slider range from 0 to 100 with an initial position of 0
* @param[in] pInit The initialization parameters to use
*
* @note The drawing color and the background color get set to the current defaults. If you haven't called
* @p gwinSetDefaultColor() or @p gwinSetDefaultBgColor() then these are White and Black respectively.
* @note The font gets set to the current default font. If you haven't called @p gwinSetDefaultFont() then there
* is no default font and text drawing operations will no nothing.
* @note A slider remembers its normal drawing state. If there is a window manager then it is automatically
* redrawn if the window is moved or its visibility state is changed.
* @note The initial slider range is from 0 to 100 with an initial position of 0.
* @note A slider supports mouse, toggle and dial input.
* @note When assigning a toggle, only one toggle is supported per role. If you try to assign more than
* one toggle to a role it will forget the previous toggle. Two roles are supported:
* Role 0 = toggle for down, Role 1 = toggle for up.
* @note When assigning a dial, only one dial is supported. If you try to assign more than one dial
* it will forget the previous dial. Only dial role 0 is supported.
*
* @api
*/
GHandle gwinCreateSlider(GSliderObject *gb, coord_t x, coord_t y, coord_t width, coord_t height);
GHandle gwinSliderCreate(GSliderObject *gb, const GWidgetInit *pInit);
/**
* @brief Set the slider range.
@ -102,7 +90,7 @@ GHandle gwinCreateSlider(GSliderObject *gb, coord_t x, coord_t y, coord_t width,
*
* @api
*/
void gwinSetSliderRange(GHandle gh, int min, int max);
void gwinSliderSetRange(GHandle gh, int min, int max);
/**
* @brief Set the slider position.
@ -115,66 +103,7 @@ void gwinSetSliderRange(GHandle gh, int min, int max);
*
* @api
*/
void gwinSetSliderPosition(GHandle gh, int pos);
/**
* @brief Set the style of a slider.
* @details The slider style is defined by its colours.
*
* @param[in] gh The window handle (must be a slider window)
* @param[in] pStyle The styling for the slider.
*
* @note The slider is not automatically redrawn. Call gwinSliderDraw() after changing the slider style
* @note The slider style is copied into the internal slider structure - there is no need to
* maintain a static style structure.
*
* @api
*/
void gwinSetSliderStyle(GHandle gh, const GSliderDrawStyle *pStyle);
/**
* @brief Redraw the slider.
*
* @param[in] gh The window handle (must be a slider window)
*
* @api
*/
void gwinSliderDraw(GHandle gh);
/**
* @brief Enable or disable a button
*
* @param[in] gh The window handle (must be a slider window)
* @param[in] enabled Enable or disable the slider
*
* @api
*/
void gwinSliderSetEnabled(GHandle gh, bool_t enabled);
/**
* @brief Set the callback routine to perform a custom slider drawing.
*
* @param[in] gh The window handle (must be a slider window)
* @param[in] fn The function to use to draw the slider
* @param[in] param A parameter to pass to the slider drawing function
*
* @api
*/
void gwinSetSliderCustom(GHandle gh, GSliderDrawFunction fn, void *param);
/**
* @brief Enable a slider
*
* @api
*/
#define gwinEnableSlider(gh) gwinSliderSetEnabled( ((GSliderObject *)(gh)), TRUE)
/**
* @brief Disable a slider
*
* @api
*/
#define gwinDisableSlider(gh) gwinSliderSetEnabled( ((GSliderObject *)(gh)), FALSE)
void gwinSliderSetPosition(GHandle gh, int pos);
/**
* @brief Get the current slider position.
@ -187,72 +116,38 @@ void gwinSetSliderCustom(GHandle gh, GSliderDrawFunction fn, void *param);
*
* @api
*/
#define gwinGetSliderPosition(gh) (((GSliderObject *)(gh))->pos)
#define gwinSliderGetPosition(gh) (((GSliderObject *)(gh))->pos)
/**
* @brief Get the source handle of a slider
* @details Get the source handle of a slider so the application can listen for events
* @brief Some custom slider drawing routines
* @details These function may be passed to @p gwinSetCustomDraw() to get different slider drawing styles
*
* @param[in] gh The window handle
*
* @api
*/
#define gwinGetSliderSource(gh) ((GSourceHandle)(gh))
#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
/**
* @brief Attach a mouse source
* @details Attach a mouse to a slider
*
* @param[in] gh The slider handle
* @param[in] instance The mouse instance
*
* @api
*/
bool_t gwinAttachSliderMouse(GHandle gh, uint16_t instance);
#endif
#if GFX_USE_GINPUT && GINPUT_NEED_DIAL
/**
* @brief Attach a dial source
* @details Attach a dial to a slider
*
* @param[in] gh The dial handle
* @param[in] instance The dial instance
*
* @api
*/
bool_t gwinAttachSliderDial(GHandle gh, uint16_t instance);
#endif
/**
* @brief Standard slider drawing routines
* @details This routine is called to draw the standard slider.
*
* @param[in] gh The slider handle
* @param[in] isVertical The slider is vertically oriented instead of horizontal
* @param[in] thumbpos The position of the slider (0..cx-1 or cy-1..0)
* @param[in] pstyle The current drawing style
* @param[in] gw The widget (which must be a slider)
* @param[in] param A parameter passed in from the user
*
* @note In your custom slider drawing function you may optionally call this
* standard functions and then draw your extra details on top.
* @note The standard functions below ignore the param parameter. It is there
* only to ensure the functions match the GSliderDrawFunction type.
* @note When called by a slider the framework ensure that it is
* a slider object and sets up clipping to the slider object window. These
* drawing routines then don't have to worry about explicitly doing that.
* @note The standard functions below ignore the param parameter except for @p gwinSliderDraw_Image().
* @note The image custom draw function @p gwinSliderDraw_Image() uses param to pass in the gdispImage pointer.
* The image must be already opened before calling @p gwinSetCustomDraw(). The image is tiled to fill
* the active area of the slider. The normal colors apply to the border and inactive area and the dividing line
* between the active and inactive areas.
* No checking is done to compare the dimensions of the slider to the size of the image.
* Note text is drawn on top of the image.
* @note These custom drawing routines don't have to worry about setting clipping as the framework
* sets clipping to the object window prior to calling these routines.
*
* @api
* @{
*/
void gwinSliderDraw_Std(GHandle gh, bool_t isVertical, coord_t thumbpos, const GSliderDrawStyle *pstyle, void *param);
void gwinSliderDraw_Std(GWidgetObject *gw, void *param);
void gwinSliderDraw_Image(GWidgetObject *gw, void *param);
/* @} */
#ifdef __cplusplus
}
#endif
#endif /* GWIN_NEED_SLIDER */
#endif /* _GWIN_SLIDER_H */
/** @} */

View File

@ -1,192 +1,192 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>GFX License, version 1.1</title>
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<style type="text/css">
body {
font-family: sans-serif;
max-width: 50em;
margin-left:auto;
margin-right:auto;
text-align: justify;
-moz-hyphens: auto;
}
h1, h2, h3 {
font-family: sans-serif;
font-variant: small-caps;
font-weight: bold;
}
h1 {
text-align: center;
-moz-hyphens: none;
font-size: 160%;
}
h2 {
font-size: 140%;
-moz-hyphens: none;
text-align: left;
}
h3 {
font-size: 120%;
-moz-hyphens: none;
text-align: left;
}
blockquote {
font-family: mono;
text-align: left;
-moz-hyphens: none;
}
code {
font-family: mono;
}
em {
background: #FEFD80;
border: 30px solid #FEFD80;
float: left;
line-height: 1.25em;
margin-left: 10px;
margin-right: 10px;
margin-bottom: 10px;
margin-top:-10px;
font-style: normal;
}
dt {
font-family: sans-serif;
font-weight: bold;
}
</style>
</head>
<body>
<h1>GFX License<br>Version 1.1</h1>
<h2>1. Definitions</h2>
<dl>
<dt>1.1. Works</dt>
<dd><p>means the library commonly known as GFX or ChibiOS-GFX or ChibiOS/GFX, in source code or binary form, linked or unlinked with an application or another library.</p></dd>
<dt>1.2. Contributor</dt>
<dd><p>means each individual or legal entity that creates, contributes to the creation of the Works.</p></dd>
<dt>1.3. Contribution</dt>
<dd><p>means Software of a particular Contributor that has been offered to form part of the Works.</p></dd>
<dt>1.4. Executable form</dt>
<dd><p>means any form of the Works other than Source Code Form.</p></dd>
<dt>1.5. Application</dt>
<dd><p>means a work or software that combines the Works with other material, in a separate file or files whether in executable format or in library format, as Software or on a device.</p></dd>
<dt>1.6. License</dt>
<dd><p>means this document.</p></dd>
<dt>1.7. Modifications</dt>
<dd><p>means any of the following:</p>
<ol type="a">
<li><p>any file in Source Code Form that results from an addition to, deletion from, or modification of the contents of the Works; or</p></li>
<li><p>any new file in Source Code Form that contains any part of the Works.</p></li>
</ol>
</dd>
<dt>1.8. Patent Claims of a Contributor</dt>
<dd><p>means any patent claim(s), including without limitation, method, process, and apparatus claims, in any patent Licensable by such Contributor that would be infringed, but for the grant of the License, by the making, using, selling, offering for sale, having made, import, or transfer of its Contributions.</p></dd>
<dt>1.9. Source Code Form</dt>
<dd><p>means the form of the work preferred for making modifications.</p></dd>
<dt>1.10. You (or Your)</dt>
<dd><p>means an individual or a legal entity exercising rights under this License. For legal entities, You includes any entity that controls, is controlled by, or is under common control with You. For purposes of this definition, control means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity.</p></dd>
<dt>1.11. License Owner</dt>
<dd><p>means Joel Bodenmann (joel@unormal.org) and Andrew Hannam (andrewh@inmarket.com.au). Both parties are joint and severely owners of the license.</p></dd>
<dt>1.12. Commercial Use</dt>
<dd><p>means any use of the Works that may result in income or equivalent benefit in any form. Examples of Commercial Use include; selling an Application or Device containing the Works,
offering paid support to modify the Works, selling a library containing the Works. Examples of use that are NOT Commercial Use include; using the Works for Education, use of the Works in hobbyist projects that have no expectation of income, use of the Works in building what will later become a Commercial Use product.
Note that Commercial Use does not the prototyping and preparation for income generating activities - only the income producing activity itself.</p></dd>
</dl>
<h2>2. Non Commercial Use</h2>
<h3>2.1. Distribution of source form</h3>
<p>If You distribute the Works in an source form then:</p>
<ol type="a">
<li><p>All distribution of the Works in Source Code Form, including any Modifications that You create or to which You contribute, must be under the terms of this License; and</p></li>
<li><p>You must inform recipients that the Source Code Form of the Works is governed by the terms of this License, and how they can obtain a copy of this License. You may not attempt to alter the recipients rights in the Source Code Form; and</p></li>
<li><p>Any modification to the Works must be contributed to the License Owners, as per Section 4, prior to distribution with the exception of a working public source control repository. In this situation, modifications of the Works must be contributed to the License Owners within one calendar month; and</p></li>
<li><p>source code not forming part of the Works that are distributed in conjunction with the Works do not need to be contributed to the License Owners or use this License.</p></li>
</ol>
<i><p>Note: This means that you must contribute changes you make to the library, you do not need to contribute your application or any other code outside of GFX library itself.</p></i>
<h3>2.2. Distribution of Executable form</h3>
<p>If You distribute the Works in an Executable form then:</p>
<ol type="a">
<li><p>and You must inform recipients of the Executable form that it contains the Works and how they can obtain a copy of the Works in Source Code Form from the License Owners master repository; and</p></li>
<li><p>Any modification to the Works must be contributed to the License Owners as per Section 4 prior to distribution; and</p></li>
<li><p>You may distribute such Executable form under the terms of this License, or license it under different terms, provided that the license for the Executable form does not allow for Commercial Use of the Works or attempt to limit or alter the recipients' rights in the Source Code Form under this License.</p></li>
</ol>
<h2>3. Commercial Use</h2>
<h3>3.1. Commercial Use Agreement</h3>
<p>A "Commercial Use Agreement" explicitly signed by the License Owner will override any specified terms of this License for the party to the agreement under the terms of the agreement. All other terms of this License will still apply.</p>
<h3>3.2. Distribution</h3>
<p>Other than as provided for in a signed "Commercial Use Agreement", where there is a Commercial Use involved or implied; you are not permitted to distribute the Works, in any form, either in source code or Executable form,
either as software or on a device or in any other way.</p>
<h2>4. Contributions</h2>
<h3>4.1. Contributor Grants</h3>
<p>Each Contributor hereby irrevocably grants to the License Owner without fee or charge:</p>
<ol type="a">
<li><p>under intellectual property rights (other than patent or trademark) Licensable by such Contributor to use, reproduce, make available, modify, display, perform, distribute, relicense and otherwise exploit its Contributions, either on an unmodified basis, with Modifications, or as part of a Larger Work; and</p></li>
<li><p>under Patent Claims of such Contributor to make, use, sell, offer for sale, have made, import, relicense and otherwise transfer its Contributions.</p></li>
</ol>
<h3>4.2. Effective Date</h3>
<p>The licenses granted in Section&nbsp;4.1 with respect to any Contribution become effective for each Contribution on the date the Contributor first contributes or distributes such Contribution.</p>
<h3>4.3. Limitations on Grant Scope</h3>
<p>The grants made in this Section&nbsp;4 are the only rights granted. No additional rights or licenses will be implied from the distribution or licensing of the Works under this License. Notwithstanding Section&nbsp;4.1(b) above, no patent license is granted by a Contributor:</p>
<ol type="a">
<li><p>for any code that a Contributor has removed from Contribution; or</p></li>
<li><p>under Patent Claims infringed by the Works in the absence of its Contributions.</p></li>
</ol>
<p>This License does not grant any rights in the trademarks, service marks, or logos of any Contributor (except as may be necessary to comply with the requirements in Section&nbsp;4.4).</p>
<h3>4.4. Representation</h3>
<p>Each Contributor represents that the Contributor believes its Contributions are its original creation(s) or it has sufficient rights to grant the rights to its Contributions conveyed by this License. Each Contributor accepts sole responsibility for the legal position of its Contribution and holds blameless the License Owners for such Contribution or any modification to it.</p>
<h3>4.5. Deeming of Contributions</h3>
<p>Each Contributor deems that by Contributing to the Works, through any method offered by the License Owners, irrespective of the license provided in the Contribution, is agreeing to the Contribution being licensed under this License with its Grants, Scope and Representation.</p>
<h3>4.6. Original Source Rights</h3>
<p>By contributing to the Works, the Contributor is not removing their own copyright in their original work. The original work retains all existing copyrights and other rights, except the rights as described above have been granted to the license owners on the copy of the contribution as contributed.</p>
<p>This is equivelent to the "forking" of the contribution to two different licenses, one as part of the works (GFX) and the other as in its original form.</p>
<h3>4.7. Additional Rights</h3>
<p>A Contribution does not convey any extra distribution rights for the Contributor to the Works under this license.</p>
<h2>5. Notices</h2>
<p>You may not remove or alter the substance of any license notices (including copyright notices, patent notices, disclaimers of warranty, or limitations of liability) contained within the Source Code Form of the Works, except that You may alter any license notices to the extent required to remedy known factual inaccuracies.</p>
<h2>6. Inability to Comply Due to Statute or Regulation</h2>
<p>If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Works due to statute, judicial order, or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be Contributed to the License Owners and placed in a text file included with all distributions of the Works under this License. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it.</p>
<h2>7. Termination</h2>
<p>7.1. The distribution rights granted under this License will terminate automatically if You fail to comply with any of its terms. However, if You become compliant, then the rights granted under this License (a) provisionally, unless and until the License Owner explicitly and finally terminates Your grants, and (b) on an ongoing basis, if the License Owner fails to notify You of the non-compliance by some reasonable means prior to 60 days after You have come back into compliance.</p>
<p>7.2. If You initiate litigation against any entity by asserting a patent infringement claim (excluding declaratory judgment actions, counter-claims, and cross-claims) alleging that the License Owner directly or indirectly infringes any patent, then the rights granted to You by the License Owner for the Works shall terminate.</p>
<h2>8. Disclaimer of Warranty</h2>
<p><em>Covered Software is provided under this License on an as is basis, without warranty of any kind, either expressed, implied, or statutory, including, without limitation, warranties that the Works is free of defects, merchantable, fit for a particular purpose or non-infringing. The entire risk as to the quality and performance of the Works is with You. Should any of the Works prove defective in any respect, You assume the cost of any necessary servicing, repair, or correction. This disclaimer of warranty constitutes an essential part of this License. No use of the Works is authorized under this License except under this disclaimer.</em></p>
<h2>9. Limitation of Liability</h2>
<p><em>Under no circumstances and under no legal theory, whether tort (including negligence), contract, or otherwise, shall the License Owner, any Contributor, or anyone who distributes the Works as permitted above, be liable to You for any direct, indirect, special, incidental, or consequential damages of any character including, without limitation, damages for lost profits, loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses, even if such party shall have been informed of the possibility of such damages.</em></p>
<h2>10. Litigation</h2>
<p>Any litigation relating to this License may be brought only in the courts of a jurisdiction where the defendant maintains its principal place of business and such litigation shall be governed by laws of that jurisdiction, without reference to its conflict-of-law provisions. Nothing in this Section shall prevent a party's ability to bring cross-claims or counter-claims.</p>
<h2>11. Miscellaneous</h2>
<p>This License represents the complete agreement concerning the subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not be used to construe this License against a Contributor ro the License Owner.</p>
<h2>12. Versions of the License</h2>
<h3>12.1. New Versions</h3>
<p>The License Owner is the license steward. Except as provided in Section&nbsp;12.3, no one other than the license steward has the right to modify or publish new versions of this License. Each version will be given a distinguishing version number.</p>
<h3>12.2. Effect of New Versions</h3>
<p>You may distribute the Works under the terms of the version of the License under which You originally received the Works, or under the terms of any subsequent version published by the license steward.</p>
<h3>12.3. Modified Versions</h3>
<p>If you create software not governed by this License, and you want to create a new license for such software, you may create and use a modified version of this License if you rename the license and remove any references to the name of the License Owner (except to note that such modified license differs from this License).</p>
<h2>Exhibit A - Source Code Form License Notice</h2>
<pre>
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://chibios-gfx.com/license.html
*/
</pre>
<p>If it is not possible or desirable to put the notice in a particular file, then You may include the notice in a location (such as a LICENSE file in a relevant directory) where a recipient would be likely to look for such a notice.</p>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>GFX License, version 1.1</title>
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<style type="text/css">
body {
font-family: sans-serif;
max-width: 50em;
margin-left:auto;
margin-right:auto;
text-align: justify;
-moz-hyphens: auto;
}
h1, h2, h3 {
font-family: sans-serif;
font-variant: small-caps;
font-weight: bold;
}
h1 {
text-align: center;
-moz-hyphens: none;
font-size: 160%;
}
h2 {
font-size: 140%;
-moz-hyphens: none;
text-align: left;
}
h3 {
font-size: 120%;
-moz-hyphens: none;
text-align: left;
}
blockquote {
font-family: mono;
text-align: left;
-moz-hyphens: none;
}
code {
font-family: mono;
}
em {
background: #FEFD80;
border: 30px solid #FEFD80;
float: left;
line-height: 1.25em;
margin-left: 10px;
margin-right: 10px;
margin-bottom: 10px;
margin-top:-10px;
font-style: normal;
}
dt {
font-family: sans-serif;
font-weight: bold;
}
</style>
</head>
<body>
<h1>GFX License<br>Version 1.1</h1>
<h2>1. Definitions</h2>
<dl>
<dt>1.1. Works</dt>
<dd><p>means the library commonly known as GFX or ChibiOS-GFX or ChibiOS/GFX, in source code or binary form, linked or unlinked with an application or another library.</p></dd>
<dt>1.2. Contributor</dt>
<dd><p>means each individual or legal entity that creates, contributes to the creation of the Works.</p></dd>
<dt>1.3. Contribution</dt>
<dd><p>means Software of a particular Contributor that has been offered to form part of the Works.</p></dd>
<dt>1.4. Executable form</dt>
<dd><p>means any form of the Works other than Source Code Form.</p></dd>
<dt>1.5. Application</dt>
<dd><p>means a work or software that combines the Works with other material, in a separate file or files whether in executable format or in library format, as Software or on a device.</p></dd>
<dt>1.6. License</dt>
<dd><p>means this document.</p></dd>
<dt>1.7. Modifications</dt>
<dd><p>means any of the following:</p>
<ol type="a">
<li><p>any file in Source Code Form that results from an addition to, deletion from, or modification of the contents of the Works; or</p></li>
<li><p>any new file in Source Code Form that contains any part of the Works.</p></li>
</ol>
</dd>
<dt>1.8. Patent Claims of a Contributor</dt>
<dd><p>means any patent claim(s), including without limitation, method, process, and apparatus claims, in any patent Licensable by such Contributor that would be infringed, but for the grant of the License, by the making, using, selling, offering for sale, having made, import, or transfer of its Contributions.</p></dd>
<dt>1.9. Source Code Form</dt>
<dd><p>means the form of the work preferred for making modifications.</p></dd>
<dt>1.10. You (or Your)</dt>
<dd><p>means an individual or a legal entity exercising rights under this License. For legal entities, You includes any entity that controls, is controlled by, or is under common control with You. For purposes of this definition, control means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity.</p></dd>
<dt>1.11. License Owner</dt>
<dd><p>means Joel Bodenmann (joel@unormal.org) and Andrew Hannam (andrewh@inmarket.com.au). Both parties are joint and severely owners of the license.</p></dd>
<dt>1.12. Commercial Use</dt>
<dd><p>means any use of the Works that may result in income or equivalent benefit in any form. Examples of Commercial Use include; selling an Application or Device containing the Works,
offering paid support to modify the Works, selling a library containing the Works. Examples of use that are NOT Commercial Use include; using the Works for Education, use of the Works in hobbyist projects that have no expectation of income, use of the Works in building what will later become a Commercial Use product.
Note that Commercial Use does not the prototyping and preparation for income generating activities - only the income producing activity itself.</p></dd>
</dl>
<h2>2. Non Commercial Use</h2>
<h3>2.1. Distribution of source form</h3>
<p>If You distribute the Works in an source form then:</p>
<ol type="a">
<li><p>All distribution of the Works in Source Code Form, including any Modifications that You create or to which You contribute, must be under the terms of this License; and</p></li>
<li><p>You must inform recipients that the Source Code Form of the Works is governed by the terms of this License, and how they can obtain a copy of this License. You may not attempt to alter the recipients rights in the Source Code Form; and</p></li>
<li><p>Any modification to the Works must be contributed to the License Owners, as per Section 4, prior to distribution with the exception of a working public source control repository. In this situation, modifications of the Works must be contributed to the License Owners within one calendar month; and</p></li>
<li><p>source code not forming part of the Works that are distributed in conjunction with the Works do not need to be contributed to the License Owners or use this License.</p></li>
</ol>
<i><p>Note: This means that you must contribute changes you make to the library, you do not need to contribute your application or any other code outside of GFX library itself.</p></i>
<h3>2.2. Distribution of Executable form</h3>
<p>If You distribute the Works in an Executable form then:</p>
<ol type="a">
<li><p>and You must inform recipients of the Executable form that it contains the Works and how they can obtain a copy of the Works in Source Code Form from the License Owners master repository; and</p></li>
<li><p>Any modification to the Works must be contributed to the License Owners as per Section 4 prior to distribution; and</p></li>
<li><p>You may distribute such Executable form under the terms of this License, or license it under different terms, provided that the license for the Executable form does not allow for Commercial Use of the Works or attempt to limit or alter the recipients' rights in the Source Code Form under this License.</p></li>
</ol>
<h2>3. Commercial Use</h2>
<h3>3.1. Commercial Use Agreement</h3>
<p>A "Commercial Use Agreement" explicitly signed by the License Owner will override any specified terms of this License for the party to the agreement under the terms of the agreement. All other terms of this License will still apply.</p>
<h3>3.2. Distribution</h3>
<p>Other than as provided for in a signed "Commercial Use Agreement", where there is a Commercial Use involved or implied; you are not permitted to distribute the Works, in any form, either in source code or Executable form,
either as software or on a device or in any other way.</p>
<h2>4. Contributions</h2>
<h3>4.1. Contributor Grants</h3>
<p>Each Contributor hereby irrevocably grants to the License Owner without fee or charge:</p>
<ol type="a">
<li><p>under intellectual property rights (other than patent or trademark) Licensable by such Contributor to use, reproduce, make available, modify, display, perform, distribute, relicense and otherwise exploit its Contributions, either on an unmodified basis, with Modifications, or as part of a Larger Work; and</p></li>
<li><p>under Patent Claims of such Contributor to make, use, sell, offer for sale, have made, import, relicense and otherwise transfer its Contributions.</p></li>
</ol>
<h3>4.2. Effective Date</h3>
<p>The licenses granted in Section&nbsp;4.1 with respect to any Contribution become effective for each Contribution on the date the Contributor first contributes or distributes such Contribution.</p>
<h3>4.3. Limitations on Grant Scope</h3>
<p>The grants made in this Section&nbsp;4 are the only rights granted. No additional rights or licenses will be implied from the distribution or licensing of the Works under this License. Notwithstanding Section&nbsp;4.1(b) above, no patent license is granted by a Contributor:</p>
<ol type="a">
<li><p>for any code that a Contributor has removed from Contribution; or</p></li>
<li><p>under Patent Claims infringed by the Works in the absence of its Contributions.</p></li>
</ol>
<p>This License does not grant any rights in the trademarks, service marks, or logos of any Contributor (except as may be necessary to comply with the requirements in Section&nbsp;4.4).</p>
<h3>4.4. Representation</h3>
<p>Each Contributor represents that the Contributor believes its Contributions are its original creation(s) or it has sufficient rights to grant the rights to its Contributions conveyed by this License. Each Contributor accepts sole responsibility for the legal position of its Contribution and holds blameless the License Owners for such Contribution or any modification to it.</p>
<h3>4.5. Deeming of Contributions</h3>
<p>Each Contributor deems that by Contributing to the Works, through any method offered by the License Owners, irrespective of the license provided in the Contribution, is agreeing to the Contribution being licensed under this License with its Grants, Scope and Representation.</p>
<h3>4.6. Original Source Rights</h3>
<p>By contributing to the Works, the Contributor is not removing their own copyright in their original work. The original work retains all existing copyrights and other rights, except the rights as described above have been granted to the license owners on the copy of the contribution as contributed.</p>
<p>This is equivelent to the "forking" of the contribution to two different licenses, one as part of the works (GFX) and the other as in its original form.</p>
<h3>4.7. Additional Rights</h3>
<p>A Contribution does not convey any extra distribution rights for the Contributor to the Works under this license.</p>
<h2>5. Notices</h2>
<p>You may not remove or alter the substance of any license notices (including copyright notices, patent notices, disclaimers of warranty, or limitations of liability) contained within the Source Code Form of the Works, except that You may alter any license notices to the extent required to remedy known factual inaccuracies.</p>
<h2>6. Inability to Comply Due to Statute or Regulation</h2>
<p>If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Works due to statute, judicial order, or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be Contributed to the License Owners and placed in a text file included with all distributions of the Works under this License. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it.</p>
<h2>7. Termination</h2>
<p>7.1. The distribution rights granted under this License will terminate automatically if You fail to comply with any of its terms. However, if You become compliant, then the rights granted under this License (a) provisionally, unless and until the License Owner explicitly and finally terminates Your grants, and (b) on an ongoing basis, if the License Owner fails to notify You of the non-compliance by some reasonable means prior to 60 days after You have come back into compliance.</p>
<p>7.2. If You initiate litigation against any entity by asserting a patent infringement claim (excluding declaratory judgment actions, counter-claims, and cross-claims) alleging that the License Owner directly or indirectly infringes any patent, then the rights granted to You by the License Owner for the Works shall terminate.</p>
<h2>8. Disclaimer of Warranty</h2>
<p><em>Covered Software is provided under this License on an as is basis, without warranty of any kind, either expressed, implied, or statutory, including, without limitation, warranties that the Works is free of defects, merchantable, fit for a particular purpose or non-infringing. The entire risk as to the quality and performance of the Works is with You. Should any of the Works prove defective in any respect, You assume the cost of any necessary servicing, repair, or correction. This disclaimer of warranty constitutes an essential part of this License. No use of the Works is authorized under this License except under this disclaimer.</em></p>
<h2>9. Limitation of Liability</h2>
<p><em>Under no circumstances and under no legal theory, whether tort (including negligence), contract, or otherwise, shall the License Owner, any Contributor, or anyone who distributes the Works as permitted above, be liable to You for any direct, indirect, special, incidental, or consequential damages of any character including, without limitation, damages for lost profits, loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses, even if such party shall have been informed of the possibility of such damages.</em></p>
<h2>10. Litigation</h2>
<p>Any litigation relating to this License may be brought only in the courts of a jurisdiction where the defendant maintains its principal place of business and such litigation shall be governed by laws of that jurisdiction, without reference to its conflict-of-law provisions. Nothing in this Section shall prevent a party's ability to bring cross-claims or counter-claims.</p>
<h2>11. Miscellaneous</h2>
<p>This License represents the complete agreement concerning the subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not be used to construe this License against a Contributor ro the License Owner.</p>
<h2>12. Versions of the License</h2>
<h3>12.1. New Versions</h3>
<p>The License Owner is the license steward. Except as provided in Section&nbsp;12.3, no one other than the license steward has the right to modify or publish new versions of this License. Each version will be given a distinguishing version number.</p>
<h3>12.2. Effect of New Versions</h3>
<p>You may distribute the Works under the terms of the version of the License under which You originally received the Works, or under the terms of any subsequent version published by the license steward.</p>
<h3>12.3. Modified Versions</h3>
<p>If you create software not governed by this License, and you want to create a new license for such software, you may create and use a modified version of this License if you rename the license and remove any references to the name of the License Owner (except to note that such modified license differs from this License).</p>
<h2>Exhibit A - Source Code Form License Notice</h2>
<pre>
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://chibios-gfx.com/license.html
*/
</pre>
<p>If it is not possible or desirable to put the notice in a particular file, then You may include the notice in a location (such as a LICENSE file in a relevant directory) where a recipient would be likely to look for such a notice.</p>
</body>
</html>

View File

@ -19,7 +19,7 @@ void DEPRECATED("Use gfxInit() instead") gdispInit() { gfxInit(); }
/* These init functions are defined by each module but not published */
extern void _gosInit(void);
#if GFX_USE_GDISP && (GDISP_NEED_MULTITHREAD || GDISP_NEED_ASYNC)
#if GFX_USE_GDISP
extern void _gdispInit(void);
#endif
#if GFX_USE_TDISP

View File

@ -57,6 +57,7 @@ static void DialCallback(uint16_t instance, uint16_t rawvalue) {
pe->type = GEVENT_DIAL;
pe->instance = instance;
pe->value = pds->lastvalue;
pe->maxvalue = pds->max;
geventSendEvent(psl);
}
}
@ -144,6 +145,7 @@ bool_t ginputGetDialStatus(uint16_t instance, GEventDial *pdial) {
pdial->type = GEVENT_DIAL;
pdial->instance = instance;
pdial->value = DialStatus[instance].lastvalue;
pdial->maxvalue = DialStatus[instance].max;
return TRUE;
}

View File

@ -9,6 +9,9 @@
* @file src/gqueue/gqueue.c
* @brief GQUEUE source file.
*/
#include "gfx.h"
#if GFX_USE_GQUEUE
#if GQUEUE_NEED_ASYNC
@ -22,7 +25,8 @@
gfxSystemLock();
if ((pi = pqueue->head))
pqueue->head = pi->next;
gfxSytemUnlock();
pi->next = 0;
gfxSystemUnlock();
return pi;
}
void gfxQueueASyncPut(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) {
@ -46,17 +50,21 @@
gfxSystemUnlock();
}
void gfxQueueASyncRemove(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) {
gfxQueueASyncItem *pi;
if (!pitem) return;
gfxSystemLock();
if (pqueue->head) {
if (pqueue->head == pitem) {
pqueue->head = pitem->next;
pitem->next = 0;
} else {
for(gfxQueueASyncItem *pi = pqueue->head; pi->next; pi = pi->next) {
for(pi = pqueue->head; pi->next; pi = pi->next) {
if (pi->next == pitem) {
pi->next = pitem->next;
if (pqueue->tail == pitem)
pqueue->tail = pi;
pitem->next = 0;
break;
}
}
@ -68,8 +76,10 @@
return pqueue->head == NULL;
}
bool_t gfxQueueASyncIsIn(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) {
gfxQueueASyncItem *pi;
gfxSystemLock();
for(gfxQueueASyncItem *pi = pqueue->head; pi; pi = pi->next) {
for(pi = pqueue->head; pi; pi = pi->next) {
if (pi == pitem) {
gfxSystemUnlock();
return TRUE;
@ -92,6 +102,7 @@
gfxSystemLock();
pi = pqueue->head;
pqueue->head = pi->next;
pi->next = 0;
gfxSytemUnlock();
return pi;
}
@ -120,17 +131,21 @@
gfxSemSignal(&pqueue->sem);
}
void gfxQueueGSyncRemove(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) {
gfxQueueGSyncItem *pi;
if (!pitem) return;
gfxSystemLock();
if (pqueue->head) {
if (pqueue->head == pitem) {
pqueue->head = pitem->next;
pitem->next = 0;
} else {
for(gfxQueueGSyncItem *pi = pqueue->head; pi->next; pi = pi->next) {
for(pi = pqueue->head; pi->next; pi = pi->next) {
if (pi->next == pitem) {
pi->next = pitem->next;
if (pqueue->tail == pitem)
pqueue->tail = pi;
pitem->next = 0;
break;
}
}
@ -142,8 +157,10 @@
return pqueue->head == NULL;
}
bool_t gfxQueueGSyncIsIn(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) {
gfxQueueGSyncItem *pi;
gfxSystemLock();
for(gfxQueueGSyncItem *pi = pqueue->head; pi; pi = pi->next) {
for(pi = pqueue->head; pi; pi = pi->next) {
if (pi == pitem) {
gfxSystemUnlock();
return TRUE;
@ -166,6 +183,7 @@
gfxSystemLock();
pi = pqueue->head;
pqueue->head = pi->next;
pi->next = 0;
gfxSytemUnlock();
gfxSemSignalI(&pi->sem);
@ -202,18 +220,21 @@
return gfxSemWait(&pitem->sem, ms);
}
void gfxQueueFSyncRemove(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem) {
gfxQueueFSyncItem *pi;
if (!pitem) return;
gfxSystemLock();
if (pqueue->head) {
if (pqueue->head == pitem) {
pqueue->head = pitem->next;
found:
pitem->next = 0;
gfxSystemUnlock();
gfxSemSignal(&pitem->sem);
gfxSemDestroy(&pitem->sem);
return;
}
for(gfxQueueFSyncItem *pi = pqueue->head; pi->next; pi = pi->next) {
for(pi = pqueue->head; pi->next; pi = pi->next) {
if (pi->next == pitem) {
pi->next = pitem->next;
if (pqueue->tail == pitem)
@ -228,8 +249,10 @@
return pqueue->head == NULL;
}
bool_t gfxQueueFSyncIsIn(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem) {
gfxQueueASyncItem *pi;
gfxSystemLock();
for(gfxQueueFSyncItem *pi = pqueue->head; pi; pi = pi->next) {
for(pi = pqueue->head; pi; pi = pi->next) {
if (pi == pitem) {
gfxSystemUnlock();
return TRUE;

View File

@ -17,394 +17,308 @@
#include "gfx.h"
#if (GFX_USE_GWIN && GWIN_NEED_BUTTON) || defined(__DOXYGEN__)
#if GFX_USE_GWIN && GWIN_NEED_BUTTON
/* Parameters for various shapes */
#include "gwin/class_gwin.h"
// Parameters for various shapes
#define RND_CNR_SIZE 5 // Rounded corner size for rounded buttons
#define ARROWHEAD_DIVIDER 4 // A quarter of the height for the arrow head
#define ARROWBODY_DIVIDER 4 // A quarter of the width for the arrow body
#include <string.h>
// Our pressed state
#define GBUTTON_FLG_PRESSED (GWIN_FIRST_CONTROL_FLAG<<0)
#include "gwin/internal.h"
#define GWIN_BUTTON_DEFAULT_SHAPE GBTN_3D
static const GButtonDrawStyle GButtonDefaultStyleUp = {
HTML2COLOR(0x404040), // color_up_edge;
HTML2COLOR(0xE0E0E0), // color_up_fill;
HTML2COLOR(0x000000), // color_up_txt;
};
static const GButtonDrawStyle GButtonDefaultStyleDown = {
HTML2COLOR(0x404040), // color_dn_edge;
HTML2COLOR(0x808080), // color_dn_fill;
HTML2COLOR(0x404040), // color_dn_txt;
};
// Process an event callback
static void gwinButtonCallback(void *param, GEvent *pe) {
GSourceListener *psl;
#define gh ((GHandle)param)
#define gbw ((GButtonObject *)param)
#define gsh ((GSourceHandle)param)
#define pme ((GEventMouse *)pe)
#define pte ((GEventTouch *)pe)
#define pxe ((GEventToggle *)pe)
#define pbe ((GEventGWinButton *)pe)
// check if button is disabled
if (!gh->enabled)
return;
switch (pe->type) {
#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
case GEVENT_MOUSE:
case GEVENT_TOUCH:
// Ignore anything other than the primary mouse button going up or down
if (!((pme->current_buttons ^ pme->last_buttons) & GINPUT_MOUSE_BTN_LEFT))
return;
if (gbw->state == GBTN_UP) {
// Our button is UP: Test for button down over the button
if ((pme->current_buttons & GINPUT_MOUSE_BTN_LEFT)
&& pme->x >= gbw->gwin.x && pme->x < gbw->gwin.x + gbw->gwin.width
&& pme->y >= gbw->gwin.y && pme->y < gbw->gwin.y + gbw->gwin.height) {
gbw->state = GBTN_DOWN;
gwinButtonDraw((GHandle)param);
}
return;
}
// Our button is DOWN
// Skip more mouse downs
if ((pme->current_buttons & GINPUT_MOUSE_BTN_LEFT))
return;
// This must be a mouse up - set the button as UP
gbw->state = GBTN_UP;
gwinButtonDraw((GHandle)param);
#if GWIN_BUTTON_LAZY_RELEASE
break;
#else
// If the mouse up was over the button then create the event
if (pme->x >= gbw->gwin.x && pme->x < gbw->gwin.x + gbw->gwin.width
&& pme->y >= gbw->gwin.y && pme->y < gbw->gwin.y + gbw->gwin.height)
break;
return;
#endif
#endif
#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
case GEVENT_TOGGLE:
// State has changed - update the button
gbw->state = pxe->on ? GBTN_DOWN : GBTN_UP;
gwinButtonDraw((GHandle)param);
// Trigger the event on button down (different than for mouse/touch)
if (gbw->state == GBTN_DOWN)
break;
return;
#endif
default:
return;
}
// Send the button event
static void SendButtonEvent(GWidgetObject *gw) {
GSourceListener * psl;
GEvent * pe;
#define pbe ((GEventGWinButton *)pe)
// Trigger a GWIN Button Event
psl = 0;
while ((psl = geventGetSourceListener(gsh, psl))) {
while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) {
if (!(pe = geventGetEventBuffer(psl)))
continue;
pbe->type = GEVENT_GWIN_BUTTON;
pbe->button = gh;
pbe->button = (GHandle)gw;
geventSendEvent(psl);
}
#undef pbe
#undef pme
#undef pte
#undef pxe
#undef gsh
#undef gbw
#undef gh
}
GHandle gwinCreateButton(GButtonObject *gb, coord_t x, coord_t y, coord_t width, coord_t height, font_t font, GButtonType type) {
if (!(gb = (GButtonObject *)_gwinInit((GWindowObject *)gb, x, y, width, height, sizeof(GButtonObject))))
#if GINPUT_NEED_MOUSE
// A mouse down has occurred over the button
static void MouseDown(GWidgetObject *gw, coord_t x, coord_t y) {
(void) x; (void) y;
gw->g.flags |= GBUTTON_FLG_PRESSED;
_gwidgetRedraw((GHandle)gw);
}
// 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);
#if !GWIN_BUTTON_LAZY_RELEASE
// If the mouse up was not over the button then cancel the event
if (x < 0 || y < 0 || x >= gw->g.width || y >= gw->g.height)
return;
#endif
SendButtonEvent(gw);
}
#endif
#if GINPUT_NEED_TOGGLE
// A toggle off has occurred
static void ToggleOff(GWidgetObject *gw, uint16_t role) {
(void) role;
gw->g.flags &= ~GBUTTON_FLG_PRESSED;
_gwidgetRedraw((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);
// Trigger the event on button down (different than for mouse/touch)
SendButtonEvent(gw);
}
static void ToggleAssign(GWidgetObject *gw, uint16_t role, uint16_t instance) {
(void) role;
((GButtonObject *)gw)->toggle = instance;
}
static uint16_t ToggleGet(GWidgetObject *gw, uint16_t role) {
(void) role;
return ((GButtonObject *)gw)->toggle;
}
#endif
// The button VMT table
static const gwidgetVMT buttonVMT = {
{
"Button", // The classname
sizeof(GButtonObject), // The object size
_gwidgetDestroy, // The destroy routine
_gwidgetRedraw, // The redraw routine
0, // The after-clear routine
},
gwinButtonDraw_3D, // The default drawing routine
#if GINPUT_NEED_MOUSE
{
MouseDown, // Process mouse down events
MouseUp, // Process mouse up events
0, // Process mouse move events (NOT USED)
},
#endif
#if GINPUT_NEED_TOGGLE
{
1, // 1 toggle role
ToggleAssign, // Assign Toggles
ToggleGet, // Get Toggles
ToggleOff, // Process toggle off events
ToggleOn, // Process toggle on events
},
#endif
#if GINPUT_NEED_DIAL
{
0, // No dial roles
0, // Assign Dials (NOT USED)
0, // Get Dials (NOT USED)
0, // Process dial move events (NOT USED)
},
#endif
};
GHandle gwinButtonCreate(GButtonObject *gw, const GWidgetInit *pInit) {
if (!(gw = (GButtonObject *)_gwidgetCreate(&gw->w, pInit, &buttonVMT)))
return 0;
gb->gwin.type = GW_BUTTON;
gb->fn = 0;
gb->param = 0;
gwinSetFont(&gb->gwin, font);
gwinSetButtonStyle(&gb->gwin, GWIN_BUTTON_DEFAULT_SHAPE, &GButtonDefaultStyleUp, &GButtonDefaultStyleDown);
gb->type = type;
gb->state = GBTN_UP;
gb->txt = "";
geventListenerInit(&gb->listener);
geventRegisterCallback(&gb->listener, gwinButtonCallback, gb);
// buttons are enabled by default
gb->gwin.enabled = TRUE;
return (GHandle)gb;
}
void gwinSetButtonStyle(GHandle gh, GButtonShape shape, const GButtonDrawStyle *pUp, const GButtonDrawStyle *pDown) {
#define gbw ((GButtonObject *)gh)
if (gh->type != GW_BUTTON)
return;
switch(shape) {
case GBTN_SQUARE: gbw->fn = gwinButtonDraw_Square; break;
#if GDISP_NEED_ARC
case GBTN_ROUNDED: gbw->fn = gwinButtonDraw_Rounded; break;
#endif
#if GDISP_NEED_ELLIPSE
case GBTN_ELLIPSE: gbw->fn = gwinButtonDraw_Ellipse; break;
#endif
#if GDISP_NEED_CONVEX_POLYGON
case GBTN_ARROW_UP: gbw->fn = gwinButtonDraw_ArrowUp; break;
case GBTN_ARROW_DOWN: gbw->fn = gwinButtonDraw_ArrowDown; break;
case GBTN_ARROW_LEFT: gbw->fn = gwinButtonDraw_ArrowLeft; break;
case GBTN_ARROW_RIGHT: gbw->fn = gwinButtonDraw_ArrowRight; break;
#endif
case GBTN_CUSTOM: if (gbw->fn) break; /* Fall Through */
case GBTN_3D: /* Fall through */
default: gbw->fn = gwinButtonDraw_3D; break;
}
if (pUp) {
gbw->up.color_edge = pUp->color_edge;
gbw->up.color_fill = pUp->color_fill;
gbw->up.color_txt = pUp->color_txt;
}
if (pDown) {
gbw->dn.color_edge = pDown->color_edge;
gbw->dn.color_fill = pDown->color_fill;
gbw->dn.color_txt = pDown->color_txt;
}
#undef gbw
}
void gwinSetButtonText(GHandle gh, const char *txt, bool_t useAlloc) {
#define gbw ((GButtonObject *)gh)
if (gh->type != GW_BUTTON)
return;
// Dispose of the old string
if ((gh->flags & GBTN_FLG_ALLOCTXT)) {
gh->flags &= ~GBTN_FLG_ALLOCTXT;
if (gbw->txt) {
gfxFree((void *)gbw->txt);
gbw->txt = "";
}
}
// Alloc the new text if required
if (txt && useAlloc) {
char *str;
if ((str = (char *)gfxAlloc(strlen(txt)+1))) {
gh->flags |= GBTN_FLG_ALLOCTXT;
strcpy(str, txt);
}
txt = (const char *)str;
}
gbw->txt = txt ? txt : "";
#undef gbw
}
void gwinButtonDraw(GHandle gh) {
#define gbw ((GButtonObject *)gh)
if (gh->type != GW_BUTTON)
return;
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#if GINPUT_NEED_TOGGLE
gw->toggle = GWIDGET_NO_INSTANCE;
#endif
gbw->fn(gh,
gbw->gwin.enabled,
gbw->state == GBTN_DOWN,
gh->font && gbw->txt ? gbw->txt : "",
gbw->state == GBTN_DOWN ? &gbw->dn : &gbw->up,
gbw->param);
#undef gbw
gwinSetVisible((GHandle)gw, pInit->g.show);
return (GHandle)gw;
}
void gwinSetButtonCustom(GHandle gh, GButtonDrawFunction fn, void *param) {
#define gbw ((GButtonObject *)gh)
bool_t gwinButtonIsPressed(GHandle gh) {
if (gh->vmt != (gwinVMT *)&buttonVMT)
return FALSE;
if (gh->type != GW_BUTTON)
return;
gbw->fn = fn ? fn : gwinButtonDraw_3D;
gbw->param = param;
#undef gbw
return (gh->flags & GBUTTON_FLG_PRESSED) ? TRUE : FALSE;
}
void gwinButtonSetEnabled(GHandle gh, bool_t enabled) {
if (gh->type != GW_BUTTON)
return;
/*----------------------------------------------------------
* Custom Draw Routines
*----------------------------------------------------------*/
gh->enabled = enabled;
static const GColorSet *getDrawColors(GWidgetObject *gw) {
if (!(gw->g.flags & GWIN_FLG_ENABLED)) return &gw->pstyle->disabled;
if ((gw->g.flags & GBUTTON_FLG_PRESSED)) return &gw->pstyle->pressed;
return &gw->pstyle->enabled;
}
void gwinButtonDraw_3D(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
(void) enabled;
(void) isdown;
(void) param;
void gwinButtonDraw_3D(GWidgetObject *gw, void *param) {
const GColorSet * pcol;
(void) param;
gdispFillStringBox(gh->x, gh->y, gh->width-1, gh->height-1, txt, gh->font, pstyle->color_txt, pstyle->color_fill, justifyCenter);
gdispDrawLine(gh->x+gh->width-1, gh->y, gh->x+gh->width-1, gh->y+gh->height-1, pstyle->color_edge);
gdispDrawLine(gh->x, gh->y+gh->height-1, gh->x+gh->width-2, gh->y+gh->height-1, pstyle->color_edge);
}
void gwinButtonDraw_Square(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
(void) enabled;
(void) isdown;
(void) param;
gdispFillStringBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, txt, gh->font, pstyle->color_txt, pstyle->color_fill, justifyCenter);
gdispDrawBox(gh->x, gh->y, gh->width, gh->height, pstyle->color_edge);
if (gw->g.vmt != (gwinVMT *)&buttonVMT) return;
pcol = getDrawColors(gw);
gdispFillStringBox(gw->g.x, gw->g.y, gw->g.width-1, gw->g.height-1, gw->text, gw->g.font, pcol->text, pcol->fill, justifyCenter);
gdispDrawLine(gw->g.x+gw->g.width-1, gw->g.y, gw->g.x+gw->g.width-1, gw->g.y+gw->g.height-1, pcol->edge);
gdispDrawLine(gw->g.x, gw->g.y+gw->g.height-1, gw->g.x+gw->g.width-2, gw->g.y+gw->g.height-1, pcol->edge);
}
#if GDISP_NEED_ARC
void gwinButtonDraw_Rounded(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
(void) enabled;
(void) isdown;
(void) param;
void gwinButtonDraw_Rounded(GWidgetObject *gw, void *param) {
const GColorSet * pcol;
(void) param;
if (gh->width >= 2*RND_CNR_SIZE+10) {
gdispFillRoundedBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, RND_CNR_SIZE-1, pstyle->color_fill);
gdispDrawStringBox(gh->x+1, gh->y+RND_CNR_SIZE, gh->width-2, gh->height-(2*RND_CNR_SIZE), txt, gh->font, pstyle->color_txt, justifyCenter);
gdispDrawRoundedBox(gh->x, gh->y, gh->width, gh->height, RND_CNR_SIZE, pstyle->color_edge);
if (gw->g.vmt != (gwinVMT *)&buttonVMT) return;
pcol = getDrawColors(gw);
gdispFillArea(gw->g.x, gw->g.y, ld, ld, gw->pstyle->background);
if (gw->g.width >= 2*RND_CNR_SIZE+10) {
gdispFillRoundedBox(gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, RND_CNR_SIZE-1, pcol->fill);
gdispDrawStringBox(gw->g.x+1, gw->g.y+RND_CNR_SIZE, gw->g.width-2, gw->g.height-(2*RND_CNR_SIZE), gw->text, gw->g.font, pcol->text, justifyCenter);
gdispDrawRoundedBox(gw->g.x, gw->g.y, gw->g.width, gw->g.height, RND_CNR_SIZE, pcol->edge);
} else {
gdispFillStringBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, txt, gh->font, pstyle->color_txt, pstyle->color_fill, justifyCenter);
gdispDrawBox(gh->x, gh->y, gh->width, gh->height, pstyle->color_edge);
gdispFillStringBox(gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->text, gw->g.font, pcol->text, pcol->fill, justifyCenter);
gdispDrawBox(gw->g.x, gw->g.y, gw->g.width, gw->g.height, pcol->edge);
}
}
#endif
#if GDISP_NEED_ELLIPSE
void gwinButtonDraw_Ellipse(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
(void) enabled;
(void) isdown;
(void) param;
void gwinButtonDraw_Ellipse(GWidgetObject *gw, void *param) {
const GColorSet * pcol;
(void) param;
gdispFillEllipse(gh->x+1, gh->y+1, gh->width/2-1, gh->height/2-1, pstyle->color_fill);
gdispDrawStringBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, txt, gh->font, pstyle->color_txt, justifyCenter);
gdispDrawEllipse(gh->x, gh->y, gh->width/2, gh->height/2, pstyle->color_edge);
if (gw->g.vmt != (gwinVMT *)&buttonVMT) return;
pcol = getDrawColors(gw);
gdispFillArea(gw->g.x, gw->g.y, ld, ld, gw->pstyle->background);
gdispFillEllipse(gw->g.x+1, gw->g.y+1, gw->g.width/2-1, gw->g.height/2-1, pcol->fill);
gdispDrawStringBox(gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->text, gw->g.font, pcol->text, justifyCenter);
gdispDrawEllipse(gw->g.x, gw->g.y, gw->g.width/2, gw->g.height/2, pcol->edge);
}
#endif
#if GDISP_NEED_CONVEX_POLYGON
void gwinButtonDraw_ArrowUp(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
(void) enabled;
(void) isdown;
(void) param;
point arw[7];
void gwinButtonDraw_ArrowUp(GWidgetObject *gw, void *param) {
const GColorSet * pcol;
(void) param;
point arw[7];
arw[0].x = gh->width/2; arw[0].y = 0;
arw[1].x = gh->width-1; arw[1].y = gh->height/ARROWHEAD_DIVIDER;
arw[2].x = (gh->width + gh->width/ARROWBODY_DIVIDER)/2; arw[2].y = gh->height/ARROWHEAD_DIVIDER;
arw[3].x = (gh->width + gh->width/ARROWBODY_DIVIDER)/2; arw[3].y = gh->height-1;
arw[4].x = (gh->width - gh->width/ARROWBODY_DIVIDER)/2; arw[4].y = gh->height-1;
arw[5].x = (gh->width - gh->width/ARROWBODY_DIVIDER)/2; arw[5].y = gh->height/ARROWHEAD_DIVIDER;
arw[6].x = 0; arw[6].y = gh->height/ARROWHEAD_DIVIDER;
if (gw->g.vmt != (gwinVMT *)&buttonVMT) return;
pcol = getDrawColors(gw);
gdispFillConvexPoly(gh->x, gh->y, arw, 7, pstyle->color_fill);
gdispDrawPoly(gh->x, gh->y, arw, 7, pstyle->color_edge);
gdispDrawStringBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, txt, gh->font, pstyle->color_txt, justifyCenter);
arw[0].x = gw->g.width/2; arw[0].y = 0;
arw[1].x = gw->g.width-1; arw[1].y = gw->g.height/ARROWHEAD_DIVIDER;
arw[2].x = (gw->g.width + gw->g.width/ARROWBODY_DIVIDER)/2; arw[2].y = gw->g.height/ARROWHEAD_DIVIDER;
arw[3].x = (gw->g.width + gw->g.width/ARROWBODY_DIVIDER)/2; arw[3].y = gw->g.height-1;
arw[4].x = (gw->g.width - gw->g.width/ARROWBODY_DIVIDER)/2; arw[4].y = gw->g.height-1;
arw[5].x = (gw->g.width - gw->g.width/ARROWBODY_DIVIDER)/2; arw[5].y = gw->g.height/ARROWHEAD_DIVIDER;
arw[6].x = 0; arw[6].y = gw->g.height/ARROWHEAD_DIVIDER;
gdispFillArea(gw->g.x, gw->g.y, ld, ld, gw->pstyle->background);
gdispFillConvexPoly(gw->g.x, gw->g.y, arw, 7, pcol->fill);
gdispDrawPoly(gw->g.x, gw->g.y, arw, 7, pcol->edge);
gdispDrawStringBox(gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->text, gw->g.font, pcol->text, justifyCenter);
}
void gwinButtonDraw_ArrowDown(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
(void) enabled;
(void) isdown;
(void) param;
point arw[7];
void gwinButtonDraw_ArrowDown(GWidgetObject *gw, void *param) {
const GColorSet * pcol;
(void) param;
point arw[7];
arw[0].x = gh->width/2; arw[0].y = gh->height-1;
arw[1].x = gh->width-1; arw[1].y = gh->height-1-gh->height/ARROWHEAD_DIVIDER;
arw[2].x = (gh->width + gh->width/ARROWBODY_DIVIDER)/2; arw[2].y = gh->height-1-gh->height/ARROWHEAD_DIVIDER;
arw[3].x = (gh->width + gh->width/ARROWBODY_DIVIDER)/2; arw[3].y = 0;
arw[4].x = (gh->width - gh->width/ARROWBODY_DIVIDER)/2; arw[4].y = 0;
arw[5].x = (gh->width - gh->width/ARROWBODY_DIVIDER)/2; arw[5].y = gh->height-1-gh->height/ARROWHEAD_DIVIDER;
arw[6].x = 0; arw[6].y = gh->height-1-gh->height/ARROWHEAD_DIVIDER;
if (gw->g.vmt != (gwinVMT *)&buttonVMT) return;
pcol = getDrawColors(gw);
gdispFillConvexPoly(gh->x, gh->y, arw, 7, pstyle->color_fill);
gdispDrawPoly(gh->x, gh->y, arw, 7, pstyle->color_edge);
gdispDrawStringBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, txt, gh->font, pstyle->color_txt, justifyCenter);
arw[0].x = gw->g.width/2; arw[0].y = gw->g.height-1;
arw[1].x = gw->g.width-1; arw[1].y = gw->g.height-1-gw->g.height/ARROWHEAD_DIVIDER;
arw[2].x = (gw->g.width + gw->g.width/ARROWBODY_DIVIDER)/2; arw[2].y = gw->g.height-1-gw->g.height/ARROWHEAD_DIVIDER;
arw[3].x = (gw->g.width + gw->g.width/ARROWBODY_DIVIDER)/2; arw[3].y = 0;
arw[4].x = (gw->g.width - gw->g.width/ARROWBODY_DIVIDER)/2; arw[4].y = 0;
arw[5].x = (gw->g.width - gw->g.width/ARROWBODY_DIVIDER)/2; arw[5].y = gw->g.height-1-gw->g.height/ARROWHEAD_DIVIDER;
arw[6].x = 0; arw[6].y = gw->g.height-1-gw->g.height/ARROWHEAD_DIVIDER;
gdispFillArea(gw->g.x, gw->g.y, ld, ld, gw->pstyle->background);
gdispFillConvexPoly(gw->g.x, gw->g.y, arw, 7, pcol->fill);
gdispDrawPoly(gw->g.x, gw->g.y, arw, 7, pcol->edge);
gdispDrawStringBox(gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->text, gw->g.font, pcol->text, justifyCenter);
}
void gwinButtonDraw_ArrowLeft(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
(void) enabled;
(void) isdown;
(void) param;
point arw[7];
void gwinButtonDraw_ArrowLeft(GWidgetObject *gw, void *param) {
const GColorSet * pcol;
(void) param;
point arw[7];
arw[0].x = 0; arw[0].y = gh->height/2;
arw[1].x = gh->width/ARROWHEAD_DIVIDER; arw[1].y = 0;
arw[2].x = gh->width/ARROWHEAD_DIVIDER; arw[2].y = (gh->height - gh->height/ARROWBODY_DIVIDER)/2;
arw[3].x = gh->width-1; arw[3].y = (gh->height - gh->height/ARROWBODY_DIVIDER)/2;
arw[4].x = gh->width-1; arw[4].y = (gh->height + gh->height/ARROWBODY_DIVIDER)/2;
arw[5].x = gh->width/ARROWHEAD_DIVIDER; arw[5].y = (gh->height + gh->height/ARROWBODY_DIVIDER)/2;
arw[6].x = gh->width/ARROWHEAD_DIVIDER; arw[6].y = gh->height-1;
if (gw->g.vmt != (gwinVMT *)&buttonVMT) return;
pcol = getDrawColors(gw);
gdispFillConvexPoly(gh->x, gh->y, arw, 7, pstyle->color_fill);
gdispDrawPoly(gh->x, gh->y, arw, 7, pstyle->color_edge);
gdispDrawStringBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, txt, gh->font, pstyle->color_txt, justifyCenter);
arw[0].x = 0; arw[0].y = gw->g.height/2;
arw[1].x = gw->g.width/ARROWHEAD_DIVIDER; arw[1].y = 0;
arw[2].x = gw->g.width/ARROWHEAD_DIVIDER; arw[2].y = (gw->g.height - gw->g.height/ARROWBODY_DIVIDER)/2;
arw[3].x = gw->g.width-1; arw[3].y = (gw->g.height - gw->g.height/ARROWBODY_DIVIDER)/2;
arw[4].x = gw->g.width-1; arw[4].y = (gw->g.height + gw->g.height/ARROWBODY_DIVIDER)/2;
arw[5].x = gw->g.width/ARROWHEAD_DIVIDER; arw[5].y = (gw->g.height + gw->g.height/ARROWBODY_DIVIDER)/2;
arw[6].x = gw->g.width/ARROWHEAD_DIVIDER; arw[6].y = gw->g.height-1;
gdispFillArea(gw->g.x, gw->g.y, ld, ld, gw->pstyle->background);
gdispFillConvexPoly(gw->g.x, gw->g.y, arw, 7, pcol->fill);
gdispDrawPoly(gw->g.x, gw->g.y, arw, 7, pcol->edge);
gdispDrawStringBox(gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->text, gw->g.font, pcol->text, justifyCenter);
}
void gwinButtonDraw_ArrowRight(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
(void) enabled;
(void) isdown;
(void) param;
point arw[7];
void gwinButtonDraw_ArrowRight(GWidgetObject *gw, void *param) {
const GColorSet * pcol;
(void) param;
point arw[7];
arw[0].x = gh->width-1; arw[0].y = gh->height/2;
arw[1].x = gh->width-1-gh->width/ARROWHEAD_DIVIDER; arw[1].y = 0;
arw[2].x = gh->width-1-gh->width/ARROWHEAD_DIVIDER; arw[2].y = (gh->height - gh->height/ARROWBODY_DIVIDER)/2;
arw[3].x = 0; arw[3].y = (gh->height - gh->height/ARROWBODY_DIVIDER)/2;
arw[4].x = 0; arw[4].y = (gh->height + gh->height/ARROWBODY_DIVIDER)/2;
arw[5].x = gh->width-1-gh->width/ARROWHEAD_DIVIDER; arw[5].y = (gh->height + gh->height/ARROWBODY_DIVIDER)/2;
arw[6].x = gh->width-1-gh->width/ARROWHEAD_DIVIDER; arw[6].y = gh->height-1;
if (gw->g.vmt != (gwinVMT *)&buttonVMT) return;
pcol = getDrawColors(gw);
gdispFillConvexPoly(gh->x, gh->y, arw, 7, pstyle->color_fill);
gdispDrawPoly(gh->x, gh->y, arw, 7, pstyle->color_edge);
gdispDrawStringBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, txt, gh->font, pstyle->color_txt, justifyCenter);
arw[0].x = gw->g.width-1; arw[0].y = gw->g.height/2;
arw[1].x = gw->g.width-1-gw->g.width/ARROWHEAD_DIVIDER; arw[1].y = 0;
arw[2].x = gw->g.width-1-gw->g.width/ARROWHEAD_DIVIDER; arw[2].y = (gw->g.height - gw->g.height/ARROWBODY_DIVIDER)/2;
arw[3].x = 0; arw[3].y = (gw->g.height - gw->g.height/ARROWBODY_DIVIDER)/2;
arw[4].x = 0; arw[4].y = (gw->g.height + gw->g.height/ARROWBODY_DIVIDER)/2;
arw[5].x = gw->g.width-1-gw->g.width/ARROWHEAD_DIVIDER; arw[5].y = (gw->g.height + gw->g.height/ARROWBODY_DIVIDER)/2;
arw[6].x = gw->g.width-1-gw->g.width/ARROWHEAD_DIVIDER; arw[6].y = gw->g.height-1;
gdispFillArea(gw->g.x, gw->g.y, ld, ld, gw->pstyle->background);
gdispFillConvexPoly(gw->g.x, gw->g.y, arw, 7, pcol->fill);
gdispDrawPoly(gw->g.x, gw->g.y, arw, 7, pcol->edge);
gdispDrawStringBox(gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->text, gw->g.font, pcol->text, justifyCenter);
}
#endif
#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
bool_t gwinAttachButtonMouse(GHandle gh, uint16_t instance) {
GSourceHandle gsh;
#if GDISP_NEED_IMAGE || defined(__DOXYGEN__)
void gwinButtonDraw_Image(GWidgetObject *gw, void *param) {
const GColorSet * pcol;
coord_t sy;
if (gh->type != GW_BUTTON || !(gsh = ginputGetMouse(instance)))
return FALSE;
if (gw->g.vmt != (gwinVMT *)&buttonVMT) return;
pcol = getDrawColors(gw);
return geventAttachSource(&((GButtonObject *)gh)->listener, gsh, GLISTEN_MOUSEMETA);
}
#endif
if (!(gw->g.flags & GWIN_FLG_ENABLED)) {
sy = 2 * gw->g.height;
} else if ((gw->g.flags & GBUTTON_FLG_PRESSED)) {
sy = gw->g.height;
} else {
sy = 0;
}
#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
bool_t gwinAttachButtonToggle(GHandle gh, uint16_t instance) {
GSourceHandle gsh;
if (gh->type != GW_BUTTON || !(gsh = ginputGetToggle(instance)))
return FALSE;
return geventAttachSource(&((GButtonObject *)gh)->listener, gsh, GLISTEN_TOGGLE_OFF|GLISTEN_TOGGLE_ON);
gdispImageDraw((gdispImage *)param, gw->g.x, gw->g.y, gw->g.width, gw->g.height, 0, sy);
gdispDrawStringBox(gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->text, gw->g.font, pcol->text, justifyCenter);
}
#endif

View File

@ -7,7 +7,7 @@
/**
* @file src/gwin/checkbox.c
* @brief GWIN sub-system checkbox code.
* @brief GWIN sub-system button code.
*
* @defgroup Checkbox Checkbox
* @ingroup GWIN
@ -19,168 +19,178 @@
#if (GFX_USE_GWIN && GWIN_NEED_CHECKBOX) || defined(__DOXYGEN__)
static const GCheckboxColor defaultColors = {
Grey, // border
Grey, // selected
Black // background
};
#include "gwin/class_gwin.h"
/* default style drawing routine */
static void gwinCheckboxDrawDefaultStyle(GHandle gh, bool_t enabled, bool_t isChecked, void* param) {
#define gcw ((GCheckboxObject *)gh)
// Our checked state
#define GCHECKBOX_FLG_CHECKED (GWIN_FIRST_CONTROL_FLAG<<0)
(void) enabled;
(void) param;
// Send the checkbox event
static void SendCheckboxEvent(GWidgetObject *gw) {
GSourceListener * psl;
GEvent * pe;
#define pce ((GEventGWinCheckbox *)pe)
gdispDrawBox(gh->x, gh->y, gh->width, gh->height, gcw->colors->border);
if (isChecked)
gdispFillArea(gh->x+2, gh->y+2, gh->width-4, gh->height-4, gcw->colors->checked);
else
gdispFillArea(gh->x+2, gh->y+2, gh->width-4, gh->height-4, gcw->colors->bg);
#undef gcw
}
/* process an event callback */
static void gwinCheckboxCallback(void *param, GEvent *pe) {
GSourceListener *psl;
#define gh ((GHandle)param)
#define gbw ((GCheckboxObject *)param)
#define gsh ((GSourceHandle)param)
#define pme ((GEventMouse *)pe)
#define pte ((GEventTouch *)pe)
#define pxe ((GEventToggle *)pe)
#define pbe ((GEventGWinCheckbox *)pe)
/* check if checkbox is disabled */
if (!gh->enabled)
return;
switch (pe->type) {
#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
case GEVENT_MOUSE:
case GEVENT_TOUCH:
// Ignore anything other than the primary mouse button going up or down
if (!((pme->current_buttons ^ pme->last_buttons) & GINPUT_MOUSE_BTN_LEFT))
return;
if ((pme->current_buttons & GINPUT_MOUSE_BTN_LEFT)
&& pme->x >= gbw->gwin.x && pme->x < gbw->gwin.x + gbw->gwin.width
&& pme->y >= gbw->gwin.y && pme->y < gbw->gwin.y + gbw->gwin.height) {
gbw->isChecked = !gbw->isChecked;
gwinCheckboxDraw((GHandle)param);
break;
}
return;
#endif /* GFX_USE_GINPUT && GINPUT_NEED_MOUSE */
default:
return;
}
// Trigger a GWIN checkbox event
// Trigger a GWIN Checkbox Event
psl = 0;
while ((psl = geventGetSourceListener(gsh, psl))) {
while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) {
if (!(pe = geventGetEventBuffer(psl)))
continue;
pbe->type = GEVENT_GWIN_CHECKBOX;
pbe->checkbox = gh;
pbe->isChecked = gbw->isChecked;
pce->type = GEVENT_GWIN_CHECKBOX;
pce->checkbox = &gw->g;
pce->isChecked = (gw->g.flags & GCHECKBOX_FLG_CHECKED) ? TRUE : FALSE;
geventSendEvent(psl);
}
}
#undef gh
#undef pbe
#undef pme
#undef pte
#undef pxe
#undef gsh
#undef gbw
#undef pce
}
GHandle gwinCheckboxCreate(GCheckboxObject *gb, coord_t x, coord_t y, coord_t width, coord_t height) {
if (!(gb = (GCheckboxObject *)_gwinInit((GWindowObject *)gb, x, y, width, height, sizeof(GCheckboxObject))))
return 0;
gb->gwin.type = GW_CHECKBOX; // create a window of the type checkbox
gb->fn = gwinCheckboxDrawDefaultStyle; // set the default style drawing routine
gb->colors = &defaultColors; // asign the default colors
gb->param = 0; // some safe value here
gb->isChecked = GCHBX_UNCHECKED; // checkbox is currently unchecked
gb->gwin.enabled = TRUE; // checkboxes are enabled by default
geventListenerInit(&gb->listener);
geventRegisterCallback(&gb->listener, gwinCheckboxCallback, gb);
// checkboxes are enabled by default
gb->gwin.enabled = TRUE;
return (GHandle)gb;
}
void gwinCheckboxSetCustom(GHandle gh, GCheckboxDrawFunction fn, void *param) {
#define gcw ((GCheckboxObject *)gh)
if (gh->type != GW_CHECKBOX)
return;
gcw->fn = fn;
gcw->param = param;
#undef gcw
}
void gwinCheckboxSetEnabled(GHandle gh, bool_t enabled) {
if (gh->type != GW_CHECKBOX)
return;
gh->enabled = enabled;
}
void gwinCheckboxDraw(GHandle gh) {
#define gcw ((GCheckboxObject *)gh)
if (gh->type != GW_CHECKBOX)
return;
#if GDISP_NEED_CLIP
//gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
gcw->fn(gh,
gcw->gwin.enabled,
gcw->isChecked,
gcw->param);
#undef gcw
}
#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
bool_t gwinCheckboxAttachMouse(GHandle gh, uint16_t instance) {
GSourceHandle gsh;
if (gh->type != GW_CHECKBOX || !(gsh = ginputGetMouse(instance)))
return FALSE;
return geventAttachSource(&((GCheckboxObject *)gh)->listener, gsh, GLISTEN_MOUSEMETA);
#if GINPUT_NEED_MOUSE
static void MouseDown(GWidgetObject *gw, coord_t x, coord_t y) {
(void) x; (void) y;
gw->g.flags ^= GCHECKBOX_FLG_CHECKED;
_gwidgetRedraw((GHandle)gw);
SendCheckboxEvent(gw);
}
#endif
void gwinCheckboxSetColors(GHandle gh, color_t border, color_t checked, color_t bg) {
#define gcw ((GCheckboxObject *)gh)
#if GINPUT_NEED_TOGGLE
static void ToggleOn(GWidgetObject *gw, uint16_t role) {
(void) role;
gw->g.flags ^= GCHECKBOX_FLG_CHECKED;
_gwidgetRedraw((GHandle)gw);
SendCheckboxEvent(gw);
}
if (gh->type != GW_CHECKBOX)
static void ToggleAssign(GWidgetObject *gw, uint16_t role, uint16_t instance) {
(void) role;
((GCheckboxObject *)gw)->toggle = instance;
}
static uint16_t ToggleGet(GWidgetObject *gw, uint16_t role) {
(void) role;
return ((GCheckboxObject *)gw)->toggle;
}
#endif
// The checkbox VMT table
static const gwidgetVMT checkboxVMT = {
{
"Checkbox", // The classname
sizeof(GCheckboxObject),// The object size
_gwidgetDestroy, // The destroy routine
_gwidgetRedraw, // The redraw routine
0, // The after-clear routine
},
gwinCheckboxDraw_CheckOnLeft, // The default drawing routine
#if GINPUT_NEED_MOUSE
{
MouseDown, // Process mouse down events
0, // Process mouse up events (NOT USED)
0, // Process mouse move events (NOT USED)
},
#endif
#if GINPUT_NEED_TOGGLE
{
1, // 1 toggle role
ToggleAssign, // Assign Toggles
ToggleGet, // Get Toggles
0, // Process toggle off events (NOT USED)
ToggleOn, // Process toggle on events
},
#endif
#if GINPUT_NEED_DIAL
{
0, // No dial roles
0, // Assign Dials (NOT USED)
0, // Get Dials (NOT USED)
0, // Process dial move events (NOT USED)
},
#endif
};
GHandle gwinCheckboxCreate(GCheckboxObject *gb, const GWidgetInit *pInit) {
if (!(gb = (GCheckboxObject *)_gwidgetCreate(&gb->w, pInit, &checkboxVMT)))
return 0;
#if GINPUT_NEED_TOGGLE
gb->toggle = GWIDGET_NO_INSTANCE;
#endif
gwinSetVisible((GHandle)gb, pInit->g.show);
return (GHandle)gb;
}
void gwinCheckboxCheck(GHandle gh, bool_t isChecked) {
if (gh->vmt != (gwinVMT *)&checkboxVMT)
return;
gcw->colors->border = border;
gcw->colors->checked = checked,
gcw->colors->bg = bg;
if (isChecked) {
if ((gh->flags & GCHECKBOX_FLG_CHECKED)) return;
gh->flags |= GCHECKBOX_FLG_CHECKED;
} else {
if (!(gh->flags & GCHECKBOX_FLG_CHECKED)) return;
gh->flags &= ~GCHECKBOX_FLG_CHECKED;
}
_gwidgetRedraw(gh);
SendCheckboxEvent((GWidgetObject *)gh);
}
bool_t gwinCheckboxIsChecked(GHandle gh) {
if (gh->vmt != (gwinVMT *)&checkboxVMT)
return FALSE;
return (gh->flags & GCHECKBOX_FLG_CHECKED) ? TRUE : FALSE;
}
/*----------------------------------------------------------
* Custom Draw Routines
*----------------------------------------------------------*/
static const GColorSet *getDrawColors(GWidgetObject *gw) {
if (!(gw->g.flags & GWIN_FLG_ENABLED)) return &gw->pstyle->disabled;
if ((gw->g.flags & GCHECKBOX_FLG_CHECKED)) return &gw->pstyle->pressed;
return &gw->pstyle->enabled;
}
void gwinCheckboxDraw_CheckOnLeft(GWidgetObject *gw, void *param) {
#define gcw ((GCheckboxObject *)gw)
coord_t ld, df;
const GColorSet * pcol;
(void) param;
if (gw->g.vmt != (gwinVMT *)&checkboxVMT) return;
pcol = getDrawColors(gw);
ld = gw->g.width < gw->g.height ? gw->g.width : gw->g.height;
gdispFillArea(gw->g.x+1, gw->g.y+1, ld, ld-2, gw->pstyle->background);
gdispDrawBox(gw->g.x, gw->g.y, ld, ld, pcol->edge);
df = ld < 4 ? 1 : 2;
if (gw->g.flags & GCHECKBOX_FLG_CHECKED)
gdispFillArea(gw->g.x+df, gw->g.y+df, ld-2*df, ld-2*df, pcol->fill);
gdispFillStringBox(gw->g.x+ld+1, gw->g.y, gw->g.width-ld-1, gw->g.height, gw->text, gw->g.font, pcol->text, gw->pstyle->background, justifyLeft);
#undef gcw
}
void gwinCheckboxDraw_CheckOnRight(GWidgetObject *gw, void *param) {
#define gcw ((GCheckboxObject *)gw)
coord_t ep, ld, df;
const GColorSet * pcol;
(void) param;
if (gw->g.vmt != (gwinVMT *)&checkboxVMT) return;
pcol = getDrawColors(gw);
ld = gw->g.width < gw->g.height ? gw->g.width : gw->g.height;
ep = gw->g.width-ld-1;
gdispFillArea(gw->g.x+ep-1, gw->g.y+1, ld, ld-2, gw->pstyle->background);
gdispDrawBox(gw->g.x+ep, gw->g.y, ld, ld, pcol->edge);
df = ld < 4 ? 1 : 2;
if (gw->g.flags & GCHECKBOX_FLG_CHECKED)
gdispFillArea(gw->g.x+ep+df, gw->g.y+df, ld-2*df, ld-2*df, pcol->fill);
gdispFillStringBox(gw->g.x, gw->g.y, ep, gw->g.height, gw->text, gw->g.font, pcol->text, gw->pstyle->background, justifyRight);
#undef gcw
}

View File

@ -8,20 +8,15 @@
/**
* @file src/gwin/console.c
* @brief GWIN sub-system console code.
*
* @defgroup Console Console
* @ingroup GWIN
*
* @{
*/
#include "gfx.h"
#if (GFX_USE_GWIN && GWIN_NEED_CONSOLE) || defined(__DOXYGEN__)
#if GFX_USE_GWIN && GWIN_NEED_CONSOLE
#include <string.h>
#include "gwin/internal.h"
#include "gwin/class_gwin.h"
#define GWIN_CONSOLE_USE_CLEAR_LINES TRUE
#define GWIN_CONSOLE_USE_FILLED_CHARS FALSE
@ -58,32 +53,48 @@
};
#endif
GHandle gwinCreateConsole(GConsoleObject *gc, coord_t x, coord_t y, coord_t width, coord_t height, font_t font) {
if (!(gc = (GConsoleObject *)_gwinInit((GWindowObject *)gc, x, y, width, height, sizeof(GConsoleObject))))
static void AfterClear(GWindowObject *gh) {
((GConsoleObject *)gh)->cx = 0;
((GConsoleObject *)gh)->cy = 0;
}
static const gwinVMT consoleVMT = {
"Console", // The classname
sizeof(GConsoleObject), // The object size
0, // The destroy routine
0, // The redraw routine
AfterClear, // The after-clear routine
};
GHandle gwinConsoleCreate(GConsoleObject *gc, const GWindowInit *pInit) {
if (!(gc = (GConsoleObject *)_gwindowCreate(&gc->g, pInit, &consoleVMT, 0)))
return 0;
gc->gwin.type = GW_CONSOLE;
gwinSetFont(&gc->gwin, font);
#if GFX_USE_OS_CHIBIOS && GWIN_CONSOLE_USE_BASESTREAM
gc->stream.vmt = &GWindowConsoleVMT;
#endif
gc->cx = 0;
gc->cy = 0;
gwinSetVisible((GHandle)gc, pInit->show);
return (GHandle)gc;
}
#if GFX_USE_OS_CHIBIOS && GWIN_CONSOLE_USE_BASESTREAM
BaseSequentialStream *gwinGetConsoleStream(GHandle gh) {
if (gh->type != GW_CONSOLE)
BaseSequentialStream *gwinConsoleGetStream(GHandle gh) {
if (gh->vmt != &consoleVMT)
return 0;
return (BaseSequentialStream *)&(((GConsoleObject *)(gh))->stream);
}
#endif
void gwinPutChar(GHandle gh, char c) {
uint8_t width;
#define gcw ((GConsoleObject *)gh)
uint8_t width, fy, fp;
if (gh->type != GW_CONSOLE || !gh->font) return;
if (gh->vmt != &consoleVMT || !gh->font)
return;
fy = gdispGetFontMetric(gh->font, fontHeight);
fp = gdispGetFontMetric(gh->font, fontCharPadding);
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
@ -91,24 +102,24 @@ void gwinPutChar(GHandle gh, char c) {
if (c == '\n') {
gcw->cx = 0;
gcw->cy += gcw->fy;
gcw->cy += fy;
// We use lazy scrolling here and only scroll when the next char arrives
} else if (c == '\r') {
// gcw->cx = 0;
} else {
width = gdispGetCharWidth(c, gh->font) + gcw->fp;
width = gdispGetCharWidth(c, gh->font) + fp;
if (gcw->cx + width >= gh->width) {
gcw->cx = 0;
gcw->cy += gcw->fy;
gcw->cy += fy;
}
if (gcw->cy + gcw->fy > gh->height) {
if (gcw->cy + fy > gh->height) {
#if GDISP_NEED_SCROLL
/* scroll the console */
gdispVerticalScroll(gh->x, gh->y, gh->width, gh->height, gcw->fy, gh->bgcolor);
gdispVerticalScroll(gh->x, gh->y, gh->width, gh->height, fy, gh->bgcolor);
/* reset the cursor to the start of the last line */
gcw->cx = 0;
gcw->cy = (((coord_t)(gh->height/gcw->fy))-1)*gcw->fy;
gcw->cy = (((coord_t)(gh->height/fy))-1)*fy;
#else
/* clear the console */
gdispFillArea(gh->x, gh->y, gh->width, gh->height, gh->bgcolor);
@ -121,7 +132,7 @@ void gwinPutChar(GHandle gh, char c) {
#if GWIN_CONSOLE_USE_CLEAR_LINES
/* clear to the end of the line */
if (gcw->cx == 0)
gdispFillArea(gh->x, gh->y + gcw->cy, gh->width, gcw->fy, gh->bgcolor);
gdispFillArea(gh->x, gh->y + gcw->cy, gh->width, fy, gh->bgcolor);
#endif
#if GWIN_CONSOLE_USE_FILLED_CHARS
gdispFillChar(gh->x + gcw->cx, gh->y + gcw->cy, c, gh->font, gh->color, gh->bgcolor);
@ -200,7 +211,8 @@ void gwinPrintf(GHandle gh, const char *fmt, ...) {
char tmpbuf[MAX_FILLER + 1];
#endif
if (gh->type != GW_CONSOLE || !gh->font) return;
if (gh->vmt != &consoleVMT || !gh->font)
return;
va_start(ap, fmt);
while (TRUE) {
@ -343,5 +355,5 @@ void gwinPrintf(GHandle gh, const char *fmt, ...) {
}
#endif /* GFX_USE_GWIN && GWIN_NEED_CONSOLE */
/** @} */

175
src/gwin/gimage.c 100644
View File

@ -0,0 +1,175 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://chibios-gfx.com/license.html
*/
/**
* @file src/gwin/image.c
* @brief GWIN sub-system image code.
*/
#include "gfx.h"
#if GFX_USE_GWIN && GWIN_NEED_IMAGE
#include "gwin/class_gwin.h"
#define widget(gh) ((GImageObject *)gh)
static void _destroy(GWindowObject *gh) {
if (gdispImageIsOpen(&widget(gh)->image))
gdispImageClose(&widget(gh)->image);
}
static void _redraw(GHandle gh) {
coord_t x, y, w, h, dx, dy;
color_t bg;
// The default display area
x = gh->x;
y = gh->y;
w = gh->width;
h = gh->height;
bg = gwinGetDefaultBgColor();
// If the image isn't open just clear the area
if (!gdispImageIsOpen(&widget(gh)->image)) {
gdispFillArea(x, y, w, h, bg);
return;
}
// Center horizontally if the area is larger than the image
if (widget(gh)->image.width < w) {
w = widget(gh)->image.width;
dx = (gh->width-w)/2;
x += dx;
if (dx)
gdispFillArea(gh->x, y, dx, h, bg);
gdispFillArea(x+w, y, gh->width-dx-w, h, bg);
dx = 0;
}
// Center image horizontally if the area is smaller than the image
else if (widget(gh)->image.width > w) {
dx = (widget(gh)->image.width - w)/2;
}
// Center vertically if the area is larger than the image
if (widget(gh)->image.height < h) {
h = widget(gh)->image.height;
dy = (gh->height-h)/2;
y += dy;
if (dy)
gdispFillArea(x, gh->y, w, dy, bg);
gdispFillArea(x, y+h, w, gh->height-dy-h, bg);
dy = 0;
}
// Center image vertically if the area is smaller than the image
else if (widget(gh)->image.height > h) {
dy = (widget(gh)->image.height - h)/2;
}
// Reset the background color in case it has changed
gdispImageSetBgColor(&widget(gh)->image, bg);
// Display the image
gdispImageDraw(&widget(gh)->image, x, y, w, h, dx, dy);
}
static const gwinVMT imageVMT = {
"Image", // The class name
sizeof(GImageObject), // The object size
_destroy, // The destroy routine
_redraw, // The redraw routine
0, // The after-clear routine
};
GHandle gwinImageCreate(GImageObject *gobj, GWindowInit *pInit) {
if (!(gobj = (GImageObject *)_gwindowCreate(&gobj->g, pInit, &imageVMT, 0)))
return 0;
// Ensure the gdispImageIsOpen() gives valid results
gobj->image.type = 0;
gwinSetVisible((GHandle)gobj, pInit->show);
return (GHandle)gobj;
}
bool_t gwinImageOpenMemory(GHandle gh, const void* memory) {
if (gdispImageIsOpen(&widget(gh)->image))
gdispImageClose(&widget(gh)->image);
if (!gdispImageSetMemoryReader(&widget(gh)->image, memory))
return FALSE;
if (gdispImageOpen(&widget(gh)->image) != GDISP_IMAGE_ERR_OK)
return FALSE;
if ((gh->flags & GWIN_FLG_VISIBLE)) {
// 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
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
_redraw(gh);
}
return TRUE;
}
#if defined(WIN32) || GFX_USE_OS_WIN32 || GFX_USE_OS_POSIX || defined(__DOXYGEN__)
bool_t gwinImageOpenFile(GHandle gh, const char* filename) {
if (gdispImageIsOpen(&widget(gh)->image))
gdispImageClose(&widget(gh)->image);
if (!gdispImageSetFileReader(&widget(gh)->image, filename))
return FALSE;
if (gdispImageOpen(&widget(gh)->image) != GDISP_IMAGE_ERR_OK)
return FALSE;
if ((gh->flags & GWIN_FLG_VISIBLE)) {
// 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
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
_redraw(gh);
}
return TRUE;
}
#endif
#if GFX_USE_OS_CHIBIOS || defined(__DOXYGEN__)
bool_t gwinImageOpenStream(GHandle gh, void *streamPtr) {
if (gdispImageIsOpen(&widget(gh)->image))
gdispImageClose(&widget(gh)->image);
if (!gdispImageSetBaseFileStreamReader(&widget(gh)->image, streamPtr))
return FALSE;
if (gdispImageOpen(&widget(gh)->image) != GDISP_IMAGE_ERR_OK)
return FALSE;
if ((gh->flags & GWIN_FLG_VISIBLE)) {
// 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
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
_redraw(gh);
}
return TRUE;
}
#endif
gdispImageError gwinImageCache(GHandle gh) {
return gdispImageCache(&widget(gh)->image);
}
#endif // GFX_USE_GWIN && GWIN_NEED_IMAGE
/** @} */

View File

@ -8,18 +8,13 @@
/**
* @file src/gwin/graph.c
* @brief GWIN sub-system button code.
*
* @defgroup Graph Graph
* @ingroup GWIN
*
* @{
*/
#include "gfx.h"
#if (GFX_USE_GWIN && GWIN_NEED_GRAPH) || defined(__DOXYGEN__)
#if GFX_USE_GWIN && GWIN_NEED_GRAPH
#include "gwin/internal.h"
#include "gwin/class_gwin.h"
#define GGRAPH_FLG_CONNECTPOINTS (GWIN_FIRST_CONTROL_FLAG<<0)
#define GGRAPH_ARROW_SIZE 5
@ -34,13 +29,21 @@ static const GGraphStyle GGraphDefaultStyle = {
GWIN_GRAPH_STYLE_XAXIS_ARROWS|GWIN_GRAPH_STYLE_YAXIS_ARROWS // flags
};
static const gwinVMT graphVMT = {
"Graph", // The classname
sizeof(GGraphObject), // The object size
0, // The destroy routine
0, // The redraw routine
0, // The after-clear routine
};
static void pointto(GGraphObject *gg, coord_t x, coord_t y, const GGraphPointStyle *style) {
if (style->type == GGRAPH_POINT_NONE)
return;
// Convert to device space. Note the y-axis is inverted.
x += gg->gwin.x + gg->xorigin;
y = gg->gwin.y + gg->gwin.height - 1 - gg->yorigin - y;
x += gg->g.x + gg->xorigin;
y = gg->g.y + gg->g.height - 1 - gg->yorigin - y;
if (style->size <= 1) {
gdispDrawPixel(x, y, style->color);
@ -73,10 +76,10 @@ static void lineto(GGraphObject *gg, coord_t x0, coord_t y0, coord_t x1, coord_t
return;
// Convert to device space. Note the y-axis is inverted.
x0 += gg->gwin.x + gg->xorigin;
y0 = gg->gwin.y + gg->gwin.height - 1 - gg->yorigin - y0;
x1 += gg->gwin.x + gg->xorigin;
y1 = gg->gwin.y + gg->gwin.height - 1 - gg->yorigin - y1;
x0 += gg->g.x + gg->xorigin;
y0 = gg->g.y + gg->g.height - 1 - gg->yorigin - y0;
x1 += gg->g.x + gg->xorigin;
y1 = gg->g.y + gg->g.height - 1 - gg->yorigin - y1;
if (style->size <= 0) {
// Use the driver to draw a solid line
@ -162,42 +165,28 @@ static void lineto(GGraphObject *gg, coord_t x0, coord_t y0, coord_t x1, coord_t
}
}
GHandle gwinCreateGraph(GGraphObject *gg, coord_t x, coord_t y, coord_t width, coord_t height) {
if (!(gg = (GGraphObject *)_gwinInit((GWindowObject *)gg, x, y, width, height, sizeof(GGraphObject))))
GHandle gwinGraphCreate(GGraphObject *gg, const GWindowInit *pInit) {
if (!(gg = (GGraphObject *)_gwindowCreate(&gg->g, pInit, &graphVMT, 0)))
return 0;
gg->gwin.type = GW_GRAPH;
gg->xorigin = gg->yorigin = 0;
gg->lastx = gg->lasty = 0;
gwinGraphSetStyle(&gg->gwin, &GGraphDefaultStyle);
gwinGraphSetStyle((GHandle)gg, &GGraphDefaultStyle);
gwinSetVisible((GHandle)gg, pInit->show);
return (GHandle)gg;
}
void gwinGraphSetStyle(GHandle gh, const GGraphStyle *pstyle) {
#define gg ((GGraphObject *)gh)
if (gh->type != GW_GRAPH)
if (gh->vmt != &graphVMT)
return;
gg->style.point.type = pstyle->point.type;
gg->style.point.size = pstyle->point.size;
gg->style.point.color = pstyle->point.color;
gg->style.line.type = pstyle->line.type;
gg->style.line.size = pstyle->line.size;
gg->style.line.color = pstyle->line.color;
gg->style.xaxis.type = pstyle->xaxis.type;
gg->style.xaxis.size = pstyle->xaxis.size;
gg->style.xaxis.color = pstyle->xaxis.color;
gg->style.yaxis.type = pstyle->yaxis.type;
gg->style.yaxis.size = pstyle->yaxis.size;
gg->style.yaxis.color = pstyle->yaxis.color;
gg->style.xgrid.type = pstyle->xgrid.type;
gg->style.xgrid.size = pstyle->xgrid.size;
gg->style.xgrid.color = pstyle->xgrid.color;
gg->style.xgrid.spacing = pstyle->xgrid.spacing;
gg->style.ygrid.type = pstyle->ygrid.type;
gg->style.ygrid.size = pstyle->ygrid.size;
gg->style.ygrid.color = pstyle->ygrid.color;
gg->style.ygrid.spacing = pstyle->ygrid.spacing;
gg->style.point = pstyle->point;
gg->style.line = pstyle->line;
gg->style.xaxis = pstyle->xaxis;
gg->style.yaxis = pstyle->yaxis;
gg->style.xgrid = pstyle->xgrid;
gg->style.ygrid = pstyle->ygrid;
gg->style.flags = pstyle->flags;
#undef gg
@ -206,7 +195,7 @@ void gwinGraphSetStyle(GHandle gh, const GGraphStyle *pstyle) {
void gwinGraphSetOrigin(GHandle gh, coord_t x, coord_t y) {
#define gg ((GGraphObject *)gh)
if (gh->type != GW_GRAPH)
if (gh->vmt != &graphVMT)
return;
gg->xorigin = x;
@ -219,7 +208,7 @@ void gwinGraphDrawAxis(GHandle gh) {
#define gg ((GGraphObject *)gh)
coord_t i, xmin, ymin, xmax, ymax;
if (gh->type != GW_GRAPH)
if (gh->vmt != &graphVMT)
return;
xmin = -gg->xorigin;
@ -277,7 +266,7 @@ void gwinGraphDrawAxis(GHandle gh) {
}
void gwinGraphStartSet(GHandle gh) {
if (gh->type != GW_GRAPH)
if (gh->vmt != &graphVMT)
return;
gh->flags &= ~GGRAPH_FLG_CONNECTPOINTS;
@ -286,7 +275,7 @@ void gwinGraphStartSet(GHandle gh) {
void gwinGraphDrawPoint(GHandle gh, coord_t x, coord_t y) {
#define gg ((GGraphObject *)gh)
if (gh->type != GW_GRAPH)
if (gh->vmt != &graphVMT)
return;
if ((gh->flags & GGRAPH_FLG_CONNECTPOINTS)) {
@ -314,7 +303,7 @@ void gwinGraphDrawPoints(GHandle gh, const point *points, unsigned count) {
unsigned i;
const point *p;
if (gh->type != GW_GRAPH)
if (gh->vmt != &graphVMT)
return;
// Draw the connecting lines
@ -344,5 +333,3 @@ void gwinGraphDrawPoints(GHandle gh, const point *points, unsigned count) {
}
#endif /* GFX_USE_GWIN && GWIN_NEED_GRAPH */
/** @} */

461
src/gwin/gwidget.c 100644
View File

@ -0,0 +1,461 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://chibios-gfx.com/license.html
*/
#include "gfx.h"
#if GFX_USE_GWIN && GWIN_NEED_WIDGET
#include <string.h>
#include "gwin/class_gwin.h"
/* Our listener for events for widgets */
static GListener gl;
/* Our default style - a white background theme */
const GWidgetStyle WhiteWidgetStyle = {
HTML2COLOR(0xFFFFFF), // window background
// enabled color set
{
HTML2COLOR(0x000000), // text
HTML2COLOR(0x404040), // edge
HTML2COLOR(0xE0E0E0), // fill
HTML2COLOR(0xE0E0E0), // progress - inactive area
},
// disabled color set
{
HTML2COLOR(0xC0C0C0), // text
HTML2COLOR(0x808080), // edge
HTML2COLOR(0xE0E0E0), // fill
HTML2COLOR(0xC0E0C0), // progress - active area
},
// pressed color set
{
HTML2COLOR(0x404040), // text
HTML2COLOR(0x404040), // edge
HTML2COLOR(0x808080), // fill
HTML2COLOR(0x00E000), // progress - active area
},
};
/* Our black style */
const GWidgetStyle BlackWidgetStyle = {
HTML2COLOR(0x000000), // window background
// enabled color set
{
HTML2COLOR(0xC0C0C0), // text
HTML2COLOR(0xC0C0C0), // edge
HTML2COLOR(0x606060), // fill
HTML2COLOR(0x404040), // progress - inactive area
},
// disabled color set
{
HTML2COLOR(0x808080), // text
HTML2COLOR(0x404040), // edge
HTML2COLOR(0x404040), // fill
HTML2COLOR(0x004000), // progress - active area
},
// pressed color set
{
HTML2COLOR(0xFFFFFF), // text
HTML2COLOR(0xC0C0C0), // edge
HTML2COLOR(0xE0E0E0), // fill
HTML2COLOR(0x008000), // progress - active area
},
};
static const GWidgetStyle * defaultStyle = &BlackWidgetStyle;
/* We use these everywhere in this file */
#define gw ((GWidgetObject *)gh)
#define wvmt ((gwidgetVMT *)gh->vmt)
/* Process an event */
static void gwidgetEvent(void *param, GEvent *pe) {
#define gh QItem2GWindow(qi)
#define pme ((GEventMouse *)pe)
#define pte ((GEventToggle *)pe)
#define pde ((GEventDial *)pe)
const gfxQueueASyncItem * qi;
#if GFX_USE_GINPUT && (GINPUT_NEED_TOGGLE || GINPUT_NEED_DIAL)
uint16_t role;
#endif
(void) param;
// Process various events
switch (pe->type) {
#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
case GEVENT_MOUSE:
case GEVENT_TOUCH:
// Cycle through all windows
for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
// check if it a widget that is enabled and visible
if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE)) != (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE))
continue;
// Are we captured?
if ((gw->g.flags & GWIN_FLG_MOUSECAPTURE)) {
if ((pme->last_buttons & ~pme->current_buttons & GINPUT_MOUSE_BTN_LEFT)) {
gw->g.flags &= ~GWIN_FLG_MOUSECAPTURE;
if (wvmt->MouseUp)
wvmt->MouseUp(gw, pme->x - gw->g.x, pme->y - gw->g.y);
} else if (wvmt->MouseMove)
wvmt->MouseMove(gw, pme->x - gw->g.x, pme->y - gw->g.y);
// We are not captured - look for mouse downs over the widget
} else if ((~pme->last_buttons & pme->current_buttons & GINPUT_MOUSE_BTN_LEFT)
&& pme->x >= gw->g.x && pme->x < gw->g.x + gw->g.width
&& pme->y >= gw->g.y && pme->y < gw->g.y + gw->g.height) {
gw->g.flags |= GWIN_FLG_MOUSECAPTURE;
if (wvmt->MouseDown)
wvmt->MouseDown(gw, pme->x - gw->g.x, pme->y - gw->g.y);
}
}
break;
#endif
#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
case GEVENT_TOGGLE:
// Cycle through all windows
for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
// check if it a widget that is enabled and visible
if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE)) != (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE))
continue;
for(role = 0; role < wvmt->toggleroles; role++) {
if (wvmt->ToggleGet(gw, role) == pte->instance) {
if (pte->on) {
if (wvmt->ToggleOn)
wvmt->ToggleOn(gw, role);
} else {
if (wvmt->ToggleOff)
wvmt->ToggleOff(gw, role);
}
}
}
}
break;
#endif
#if GFX_USE_GINPUT && GINPUT_NEED_DIAL
case GEVENT_DIAL:
// Cycle through all windows
for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
// check if it a widget that is enabled and visible
if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE)) != (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE))
continue;
for(role = 0; role < wvmt->dialroles; role++) {
if (wvmt->DialGet(gw, role) == pte->instance) {
if (wvmt->DialMove)
wvmt->DialMove(gw, role, pde->value, pde->maxvalue);
}
}
}
break;
#endif
default:
break;
}
#undef gh
#undef pme
#undef pte
#undef pde
}
#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
static GHandle FindToggleUser(uint16_t instance) {
#define gh QItem2GWindow(qi)
const gfxQueueASyncItem * qi;
uint16_t role;
for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
if (!(gh->flags & GWIN_FLG_WIDGET)) // check if it a widget
continue;
for(role = 0; role < wvmt->toggleroles; role++) {
if (wvmt->ToggleGet(gw, role) == instance)
return gh;
}
}
return 0;
#undef gh
}
#endif
#if GFX_USE_GINPUT && GINPUT_NEED_DIAL
static GHandle FindDialUser(uint16_t instance) {
#define gh QItem2GWindow(qi)
const gfxQueueASyncItem * qi;
uint16_t role;
for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
if (!(gh->flags & GWIN_FLG_WIDGET)) // check if it a widget
continue;
for(role = 0; role < wvmt->dialroles; role++) {
if (wvmt->DialGet(gw, role) == instance)
return gh;
}
}
return 0;
#undef gh
}
#endif
void _gwidgetInit(void) {
geventListenerInit(&gl);
geventRegisterCallback(&gl, gwidgetEvent, 0);
}
GHandle _gwidgetCreate(GWidgetObject *pgw, const GWidgetInit *pInit, const gwidgetVMT *vmt) {
if (!(pgw = (GWidgetObject *)_gwindowCreate(&pgw->g, &pInit->g, &vmt->g, GWIN_FLG_WIDGET|GWIN_FLG_ENABLED)))
return 0;
pgw->text = pInit->text ? pInit->text : "";
pgw->fnDraw = pInit->customDraw ? pInit->customDraw : vmt->DefaultDraw;
pgw->fnParam = pInit->customParam;
pgw->pstyle = pInit->customStyle ? pInit->customStyle : defaultStyle;
return &pgw->g;
}
void _gwidgetDestroy(GHandle gh) {
#if GFX_USE_GINPUT && (GINPUT_NEED_TOGGLE || GINPUT_NEED_DIAL)
uint16_t role, instance;
#endif
// Deallocate the text (if necessary)
if ((gh->flags & GWIN_FLG_ALLOCTXT)) {
gh->flags &= ~GWIN_FLG_ALLOCTXT;
gfxFree((void *)gw->text);
}
#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
// Detach any toggles from this object
for(role = 0; role < wvmt->toggleroles; role++) {
instance = wvmt->ToggleGet(gw, role);
if (instance != GWIDGET_NO_INSTANCE) {
wvmt->ToggleAssign(gw, role, GWIDGET_NO_INSTANCE);
if (!FindToggleUser(instance))
geventDetachSource(&gl, ginputGetToggle(instance));
}
}
#endif
#if GFX_USE_GINPUT && GINPUT_NEED_DIAL
// Detach any dials from this object
for(role = 0; role < wvmt->dialroles; role++) {
instance = wvmt->DialGet(gw, role);
if (instance != GWIDGET_NO_INSTANCE) {
wvmt->DialAssign(gw, role, GWIDGET_NO_INSTANCE);
if (!FindDialUser(instance))
geventDetachSource(&gl, ginputGetDial(instance));
}
}
#endif
// Remove any listeners on this object.
geventDetachSourceListeners((GSourceHandle)gh);
}
void _gwidgetRedraw(GHandle gh) {
if (!(gh->flags & GWIN_FLG_VISIBLE))
return;
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
gw->fnDraw(gw, gw->fnParam);
}
void gwinSetDefaultStyle(const GWidgetStyle *pstyle, bool_t updateAll) {
if (!pstyle)
pstyle = &BlackWidgetStyle;
if (updateAll) {
const gfxQueueASyncItem * qi;
GHandle gh;
for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
gh = QItem2GWindow(qi);
if ((gh->flags & GWIN_FLG_WIDGET) && ((GWidgetObject *)gh)->pstyle == defaultStyle)
gwinSetStyle(gh, pstyle);
}
}
gwinSetDefaultBgColor(pstyle->background);
defaultStyle = pstyle;
}
/**
* @brief Get the current default style.
*
* @api
*/
const GWidgetStyle *gwinGetDefaultStyle(void) {
return defaultStyle;
}
void gwinSetText(GHandle gh, const char *text, bool_t useAlloc) {
if (!(gh->flags & GWIN_FLG_WIDGET))
return;
// Dispose of the old string
if ((gh->flags & GWIN_FLG_ALLOCTXT)) {
gh->flags &= ~GWIN_FLG_ALLOCTXT;
if (gw->text) {
gfxFree((void *)gw->text);
gw->text = "";
}
}
// Alloc the new text if required
if (!text || !*text)
gw->text = "";
else if (useAlloc) {
char *str;
if ((str = (char *)gfxAlloc(strlen(text)+1))) {
gh->flags |= GWIN_FLG_ALLOCTXT;
strcpy(str, text);
}
gw->text = (const char *)str;
} else
gw->text = text;
_gwidgetRedraw(gh);
}
const char *gwinGetText(GHandle gh) {
if (!(gh->flags & GWIN_FLG_WIDGET))
return 0;
return gw->text;
}
void gwinSetStyle(GHandle gh, const GWidgetStyle *pstyle) {
if (!(gh->flags & GWIN_FLG_WIDGET))
return;
gw->pstyle = pstyle ? pstyle : defaultStyle;
gh->bgcolor = pstyle->background;
gh->color = pstyle->enabled.text;
_gwidgetRedraw(gh);
}
const GWidgetStyle *gwinGetStyle(GHandle gh) {
return gw->pstyle;
}
void gwinSetCustomDraw(GHandle gh, CustomWidgetDrawFunction fn, void *param) {
if (!(gh->flags & GWIN_FLG_WIDGET))
return;
gw->fnDraw = fn ? fn : wvmt->DefaultDraw;
gw->fnParam = param;
_gwidgetRedraw(gh);
}
bool_t gwinAttachListener(GListener *pl) {
return geventAttachSource(pl, GWIDGET_SOURCE, 0);
}
#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
bool_t gwinAttachMouse(uint16_t instance) {
GSourceHandle gsh;
if (!(gsh = ginputGetMouse(instance)))
return FALSE;
return geventAttachSource(&gl, gsh, GLISTEN_MOUSEMETA|GLISTEN_MOUSEDOWNMOVES);
}
#endif
#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
bool_t gwinAttachToggle(GHandle gh, uint16_t role, uint16_t instance) {
GSourceHandle gsh;
uint16_t oi;
// Is this a widget
if (!(gh->flags & GWIN_FLG_WIDGET))
return FALSE;
// Is the role valid
if (role >= wvmt->toggleroles)
return FALSE;
// Is this a valid device
if (!(gsh = ginputGetToggle(instance)))
return FALSE;
// Is this already done?
oi = wvmt->ToggleGet(gw, role);
if (instance == oi)
return TRUE;
// Remove the old instance
if (oi != GWIDGET_NO_INSTANCE) {
wvmt->ToggleAssign(gw, role, GWIDGET_NO_INSTANCE);
if (!FindToggleUser(oi))
geventDetachSource(&gl, ginputGetToggle(oi));
}
// Assign the new
wvmt->ToggleAssign(gw, role, instance);
return geventAttachSource(&gl, gsh, GLISTEN_TOGGLE_ON|GLISTEN_TOGGLE_OFF);
}
#endif
#if GFX_USE_GINPUT && GINPUT_NEED_DIAL
bool_t gwinAttachDial(GHandle gh, uint16_t role, uint16_t instance) {
GSourceHandle gsh;
uint16_t oi;
if (!(gh->flags & GWIN_FLG_WIDGET))
return FALSE;
// Is the role valid
if (role >= wvmt->dialroles)
return FALSE;
// Is this a valid device
if (!(gsh = ginputGetDial(instance)))
return FALSE;
// Is this already done?
oi = wvmt->DialGet(gw, role);
if (instance == oi)
return TRUE;
// Remove the old instance
if (oi != GWIDGET_NO_INSTANCE) {
wvmt->DialAssign(gw, role, GWIDGET_NO_INSTANCE);
if (!FindDialUser(oi))
geventDetachSource(&gl, ginputGetDial(oi));
}
// Assign the new
wvmt->DialAssign(gw, role, instance);
return geventAttachSource(&gl, gsh, 0);
}
#endif
#endif /* GFX_USE_GWIN && GWIN_NEED_WIDGET */
/** @} */

View File

@ -9,127 +9,278 @@
#if GFX_USE_GWIN
#include "gwin/internal.h"
#include "gwin/class_gwin.h"
// Internal routine for use by GWIN components only
// Initialise a window creating it dynamicly if required.
GHandle _gwinInit(GWindowObject *gw, coord_t x, coord_t y, coord_t width, coord_t height, size_t size) {
coord_t w, h;
// Needed if there is no window manager
#define MIN_WIN_WIDTH 1
#define MIN_WIN_HEIGHT 1
// Check the window size against the screen size
w = gdispGetWidth();
h = gdispGetHeight();
if (x < 0) { width += x; x = 0; }
if (y < 0) { height += y; y = 0; }
if (x >= w || y >= h) return 0;
if (x+width > w) width = w - x;
if (y+height > h) height = h - y;
// Allocate the structure if necessary
if (!gw) {
if (!(gw = (GWindowObject *)gfxAlloc(size)))
return 0;
gw->flags = GWIN_FLG_DYNAMIC;
} else
gw->flags = 0;
// Initialise all basic fields (except the type)
gw->x = x;
gw->y = y;
gw->width = width;
gw->height = height;
gw->color = White;
gw->bgcolor = Black;
#if GDISP_NEED_TEXT
gw->font = 0;
/*-----------------------------------------------
* Data
*-----------------------------------------------*/
static const gwinVMT basegwinVMT = {
"GWIN", // The classname
sizeof(GWindowObject), // The object size
0, // The destroy routine
0, // The redraw routine
0, // The after-clear routine
};
static color_t defaultFgColor = White;
static color_t defaultBgColor = Black;
#if GDISP_NEED_TEXT
static font_t defaultFont;
#endif
/*-----------------------------------------------
* Helper Routines
*-----------------------------------------------*/
#if !GWIN_NEED_WINDOWMANAGER
static void _gwm_vis(GHandle gh) {
if (gh->vmt->Redraw) {
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
gh->vmt->Redraw(gh);
} else
gwinClear(gh);
}
static void _gwm_redim(GHandle gh, coord_t x, coord_t y, coord_t width, coord_t height) {
gh->x = x; gh->y = y;
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
if ((gh->flags & GWIN_FLG_VISIBLE)) {
if (gh->vmt->Redraw) {
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
gh->vmt->Redraw(gh);
}
}
}
#endif
/*-----------------------------------------------
* Class Routines
*-----------------------------------------------*/
void _gwinInit(void) {
#if GWIN_NEED_WIDGET
extern void _gwidgetInit(void);
_gwidgetInit();
#endif
#if GWIN_NEED_WINDOWMANAGER
extern void _gwmInit(void);
_gwmInit();
#endif
return (GHandle)gw;
}
GHandle gwinCreateWindow(GWindowObject *gw, coord_t x, coord_t y, coord_t width, coord_t height) {
if (!(gw = (GWindowObject *)_gwinInit((GWindowObject *)gw, x, y, width, height, sizeof(GWindowObject))))
// Internal routine for use by GWIN components only
// Initialise a window creating it dynamically if required.
GHandle _gwindowCreate(GWindowObject *pgw, const GWindowInit *pInit, const gwinVMT *vmt, uint16_t flags) {
// Allocate the structure if necessary
if (!pgw) {
if (!(pgw = (GWindowObject *)gfxAlloc(vmt->size)))
return 0;
pgw->flags = flags|GWIN_FLG_DYNAMIC;
} else
pgw->flags = flags;
// Initialise all basic fields
pgw->vmt = vmt;
pgw->color = defaultFgColor;
pgw->bgcolor = defaultBgColor;
#if GDISP_NEED_TEXT
pgw->font = defaultFont;
#endif
#if GWIN_NEED_WINDOWMANAGER
if (!_GWINwm->vmt->Add(pgw, pInit)) {
if ((pgw->flags & GWIN_FLG_DYNAMIC))
gfxFree(pgw);
return 0;
gw->type = GW_WINDOW;
return (GHandle)gw;
}
#else
_gwm_redim(pgw, pInit->x, pInit->y, pInit->width, pInit->height);
#endif
return (GHandle)pgw;
}
/*-----------------------------------------------
* Routines that affect all windows
*-----------------------------------------------*/
void gwinSetDefaultColor(color_t clr) {
defaultFgColor = clr;
}
color_t gwinGetDefaultColor(void) {
return defaultFgColor;
}
void gwinSetDefaultBgColor(color_t bgclr) {
defaultBgColor = bgclr;
}
color_t gwinGetDefaultBgColor(void) {
return defaultBgColor;
}
#if GDISP_NEED_TEXT
void gwinSetDefaultFont(font_t font) {
defaultFont = font;
}
font_t gwinGetDefaultFont(void) {
return defaultFont;
}
#endif
/*-----------------------------------------------
* The GWindow Routines
*-----------------------------------------------*/
GHandle gwinWindowCreate(GWindowObject *pgw, const GWindowInit *pInit) {
if (!(pgw = _gwindowCreate(pgw, pInit, &basegwinVMT, 0)))
return 0;
gwinSetVisible(pgw, pInit->show);
return pgw;
}
void gwinDestroy(GHandle gh) {
// Remove from the window manager
#if GWIN_NEED_WINDOWMANAGER
_GWINwm->vmt->Delete(gh);
#endif
// Class destroy routine
if (gh->vmt->Destroy)
gh->vmt->Destroy(gh);
// Clean up the structure
if (gh->flags & GWIN_FLG_DYNAMIC)
gfxFree((void *)gh);
gh->flags = 0; // To be sure, to be sure
}
const char *gwinGetClassName(GHandle gh) {
return gh->vmt->classname;
}
void gwinSetVisible(GHandle gh, bool_t visible) {
if (visible) {
if (!(gh->flags & GWIN_FLG_VISIBLE)) {
gh->flags |= GWIN_FLG_VISIBLE;
#if GWIN_NEED_WINDOWMANAGER
_GWINwm->vmt->Visible(gh);
#else
_gwm_vis(gh);
#endif
}
} else {
if ((gh->flags & GWIN_FLG_VISIBLE)) {
gh->flags &= ~GWIN_FLG_VISIBLE;
#if GWIN_NEED_WINDOWMANAGER
_GWINwm->vmt->Visible(gh);
#endif
}
}
}
bool_t gwinGetVisible(GHandle gh) {
return (gh->flags & GWIN_FLG_VISIBLE) ? TRUE : FALSE;
}
void gwinSetEnabled(GHandle gh, bool_t enabled) {
(void)gh;
(void)enabled;
}
void gwinDestroyWindow(GHandle gh) {
// Clean up any type specific dynamic memory allocations
switch(gh->type) {
#if GWIN_NEED_BUTTON
case GW_BUTTON:
if ((gh->flags & GBTN_FLG_ALLOCTXT)) {
gh->flags &= ~GBTN_FLG_ALLOCTXT; // To be sure, to be sure
gfxFree((void *)((GButtonObject *)gh)->txt);
if (enabled) {
if (!(gh->flags & GWIN_FLG_ENABLED)) {
gh->flags |= GWIN_FLG_ENABLED;
if ((gh->flags & GWIN_FLG_VISIBLE) && gh->vmt->Redraw) {
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
gh->vmt->Redraw(gh);
}
}
} else {
if ((gh->flags & GWIN_FLG_ENABLED)) {
gh->flags &= ~GWIN_FLG_ENABLED;
if ((gh->flags & GWIN_FLG_VISIBLE) && gh->vmt->Redraw) {
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
gh->vmt->Redraw(gh);
}
}
geventDetachSource(&((GButtonObject *)gh)->listener, 0);
geventDetachSourceListeners((GSourceHandle)gh);
break;
#endif
#if GWIN_NEED_SLIDER
case GW_SLIDER:
geventDetachSource(&((GSliderObject *)gh)->listener, 0);
geventDetachSourceListeners((GSourceHandle)gh);
break;
#endif
default:
break;
}
// Clean up the structure
if (gh->flags & GWIN_FLG_DYNAMIC) {
gh->flags = 0; // To be sure, to be sure
gfxFree((void *)gh);
}
}
void gwinDraw(GHandle gh) {
switch(gh->type) {
#if GWIN_NEED_BUTTON
case GW_BUTTON:
gwinButtonDraw(gh);
break;
bool_t gwinGetEnabled(GHandle gh) {
return (gh->flags & GWIN_FLG_ENABLED) ? TRUE : FALSE;
}
void gwinMove(GHandle gh, coord_t x, coord_t y) {
#if GWIN_NEED_WINDOWMANAGER
_GWINwm->vmt->Redim(gh, x, y, gh->width, gh->height);
#else
_gwm_redim(gh, x, y, gh->width, gh->height);
#endif
#if GWIN_NEED_SLIDER
case GW_SLIDER:
gwinSliderDraw(gh);
break;
}
void gwinResize(GHandle gh, coord_t width, coord_t height) {
#if GWIN_NEED_WINDOWMANAGER
_GWINwm->vmt->Redim(gh, gh->x, gh->y, width, height);
#else
_gwm_redim(gh, gh->x, gh->y, width, height);
#endif
}
void gwinRedraw(GHandle gh) {
#if GWIN_NEED_WINDOWMANAGER
gwinRaise(gh);
#else
if ((gh->flags & GWIN_FLG_VISIBLE))
_gwm_vis(gh);
#endif
}
}
#if GDISP_NEED_TEXT
void gwinSetFont(GHandle gh, font_t font) {
gh->font = font;
#if GWIN_NEED_CONSOLE
if (font && gh->type == GW_CONSOLE) {
((GConsoleObject *)gh)->fy = gdispGetFontMetric(font, fontHeight);
((GConsoleObject *)gh)->fp = gdispGetFontMetric(font, fontCharPadding);
}
#endif
}
#endif
void gwinClear(GHandle gh) {
if (!((gh->flags & GWIN_FLG_VISIBLE)))
return;
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
gdispFillArea(gh->x, gh->y, gh->width, gh->height, gh->bgcolor);
#if GWIN_NEED_CONSOLE
if (gh->type == GW_CONSOLE) {
((GConsoleObject *)gh)->cx = 0;
((GConsoleObject *)gh)->cy = 0;
}
#endif
if (gh->vmt->AfterClear)
gh->vmt->AfterClear(gh);
}
void gwinDrawPixel(GHandle gh, coord_t x, coord_t y) {
if (!((gh->flags & GWIN_FLG_VISIBLE)))
return;
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@ -137,6 +288,9 @@ void gwinDrawPixel(GHandle gh, coord_t x, coord_t y) {
}
void gwinDrawLine(GHandle gh, coord_t x0, coord_t y0, coord_t x1, coord_t y1) {
if (!((gh->flags & GWIN_FLG_VISIBLE)))
return;
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@ -144,6 +298,9 @@ void gwinDrawLine(GHandle gh, coord_t x0, coord_t y0, coord_t x1, coord_t y1) {
}
void gwinDrawBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy) {
if (!((gh->flags & GWIN_FLG_VISIBLE)))
return;
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@ -151,6 +308,9 @@ void gwinDrawBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy) {
}
void gwinFillArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy) {
if (!((gh->flags & GWIN_FLG_VISIBLE)))
return;
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@ -158,6 +318,9 @@ void gwinFillArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy) {
}
void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) {
if (!((gh->flags & GWIN_FLG_VISIBLE)))
return;
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@ -166,6 +329,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor
#if GDISP_NEED_CIRCLE
void gwinDrawCircle(GHandle gh, coord_t x, coord_t y, coord_t radius) {
if (!((gh->flags & GWIN_FLG_VISIBLE)))
return;
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@ -173,6 +339,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor
}
void gwinFillCircle(GHandle gh, coord_t x, coord_t y, coord_t radius) {
if (!((gh->flags & GWIN_FLG_VISIBLE)))
return;
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@ -182,6 +351,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor
#if GDISP_NEED_ELLIPSE
void gwinDrawEllipse(GHandle gh, coord_t x, coord_t y, coord_t a, coord_t b) {
if (!((gh->flags & GWIN_FLG_VISIBLE)))
return;
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@ -189,6 +361,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor
}
void gwinFillEllipse(GHandle gh, coord_t x, coord_t y, coord_t a, coord_t b) {
if (!((gh->flags & GWIN_FLG_VISIBLE)))
return;
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@ -198,6 +373,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor
#if GDISP_NEED_ARC
void gwinDrawArc(GHandle gh, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle) {
if (!((gh->flags & GWIN_FLG_VISIBLE)))
return;
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@ -205,6 +383,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor
}
void gwinFillArc(GHandle gh, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle) {
if (!((gh->flags & GWIN_FLG_VISIBLE)))
return;
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@ -214,6 +395,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor
#if GDISP_NEED_PIXELREAD
color_t gwinGetPixelColor(GHandle gh, coord_t x, coord_t y) {
if (!((gh->flags & GWIN_FLG_VISIBLE)))
return;
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@ -223,7 +407,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor
#if GDISP_NEED_TEXT
void gwinDrawChar(GHandle gh, coord_t x, coord_t y, char c) {
if (!gh->font) return;
if (!((gh->flags & GWIN_FLG_VISIBLE)) || !gh->font)
return;
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@ -231,7 +417,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor
}
void gwinFillChar(GHandle gh, coord_t x, coord_t y, char c) {
if (!gh->font) return;
if (!((gh->flags & GWIN_FLG_VISIBLE)) || !gh->font)
return;
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@ -239,7 +427,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor
}
void gwinDrawString(GHandle gh, coord_t x, coord_t y, const char *str) {
if (!gh->font) return;
if (!((gh->flags & GWIN_FLG_VISIBLE)) || !gh->font)
return;
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@ -247,7 +437,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor
}
void gwinFillString(GHandle gh, coord_t x, coord_t y, const char *str) {
if (!gh->font) return;
if (!((gh->flags & GWIN_FLG_VISIBLE)) || !gh->font)
return;
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@ -255,7 +447,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor
}
void gwinDrawStringBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, justify_t justify) {
if (!gh->font) return;
if (!((gh->flags & GWIN_FLG_VISIBLE)) || !gh->font)
return;
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@ -263,7 +457,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor
}
void gwinFillStringBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, justify_t justify) {
if (!gh->font) return;
if (!((gh->flags & GWIN_FLG_VISIBLE)) || !gh->font)
return;
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@ -273,6 +469,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor
#if GDISP_NEED_CONVEX_POLYGON
void gwinDrawPoly(GHandle gh, coord_t tx, coord_t ty, const point *pntarray, unsigned cnt) {
if (!((gh->flags & GWIN_FLG_VISIBLE)))
return;
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@ -280,6 +479,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor
}
void gwinFillConvexPoly(GHandle gh, coord_t tx, coord_t ty, const point *pntarray, unsigned cnt) {
if (!((gh->flags & GWIN_FLG_VISIBLE)))
return;
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
@ -288,7 +490,10 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor
#endif
#if GDISP_NEED_IMAGE
gdispImageError gwinImageDraw(GHandle gh, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy) {
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)))
return GDISP_IMAGE_ERR_OK;
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif

View File

@ -1,7 +1,12 @@
GFXSRC += $(GFXLIB)/src/gwin/gwin.c \
$(GFXLIB)/src/gwin/gwidget.c \
$(GFXLIB)/src/gwin/gwm.c \
$(GFXLIB)/src/gwin/console.c \
$(GFXLIB)/src/gwin/graph.c \
$(GFXLIB)/src/gwin/button.c \
$(GFXLIB)/src/gwin/slider.c \
$(GFXLIB)/src/gwin/graph.c \
$(GFXLIB)/src/gwin/checkbox.c \
$(GFXLIB)/src/gwin/gimage.c \
$(GFXLIB)/src/gwin/label.c \
$(GFXLIB)/src/gwin/radio.c \

201
src/gwin/gwm.c 100644
View File

@ -0,0 +1,201 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://chibios-gfx.com/license.html
*/
#include "gfx.h"
// Used by the NULL window manager
#define MIN_WIN_WIDTH 3
#define MIN_WIN_HEIGHT 3
/*-----------------------------------------------
* The default window manager (GNullWindowManager)
*-----------------------------------------------*/
#if GFX_USE_GWIN && GWIN_NEED_WINDOWMANAGER
#include "gwin/class_gwin.h"
/*-----------------------------------------------
* Data
*-----------------------------------------------*/
static void WM_Init(void);
static void WM_DeInit(void);
static bool_t WM_Add(GHandle gh, const GWindowInit *pInit);
static void WM_Delete(GHandle gh);
static void WM_Visible(GHandle gh);
static void WM_Redim(GHandle gh, coord_t x, coord_t y, coord_t w, coord_t h);
static void WM_Raise(GHandle gh);
static void WM_MinMax(GHandle gh, GWindowMinMax minmax);
static const gwmVMT GNullWindowManagerVMT = {
WM_Init,
WM_DeInit,
WM_Add,
WM_Delete,
WM_Visible,
WM_Redim,
WM_Raise,
WM_MinMax,
};
static const GWindowManager GNullWindowManager = {
&GNullWindowManagerVMT,
};
gfxQueueASync _GWINList;
GWindowManager * _GWINwm;
/*-----------------------------------------------
* Window Routines
*-----------------------------------------------*/
void _gwmInit(void) {
gfxQueueASyncInit(&_GWINList);
_GWINwm = (GWindowManager *)&GNullWindowManager;
_GWINwm->vmt->Init();
}
void gwinSetWindowManager(struct GWindowManager *gwm) {
if (!gwm)
gwm = (GWindowManager *)&GNullWindowManager;
if (_GWINwm != gwm) {
_GWINwm->vmt->DeInit();
_GWINwm = gwm;
_GWINwm->vmt->Init();
}
}
void gwinSetMinMax(GHandle gh, GWindowMinMax minmax) {
_GWINwm->vmt->MinMax(gh, minmax);
}
void gwinRaise(GHandle gh) {
_GWINwm->vmt->Raise(gh);
}
GWindowMinMax gwinGetMinMax(GHandle gh) {
if (gh->flags & GWIN_FLG_MINIMIZED)
return GWIN_MINIMIZE;
if (gh->flags & GWIN_FLG_MAXIMIZED)
return GWIN_MAXIMIZE;
return GWIN_NORMAL;
}
/*-----------------------------------------------
* Window Manager Routines
*-----------------------------------------------*/
static void WM_Init(void) {
// We don't need to do anything here.
// A full window manager would move the windows around, add borders etc
// clear the screen
// cycle through the windows already defined displaying them
// or cut all the window areas out of the screen and clear the remainder
}
static void WM_DeInit(void) {
// We don't need to do anything here.
// A full window manager would remove any borders etc
}
static bool_t WM_Add(GHandle gh, const GWindowInit *pInit) {
// Note the window will not be marked as visible yet
// Put it on the queue
gfxQueueASyncPut(&_GWINList, &gh->wmq);
// Make sure the size is valid
WM_Redim(gh, pInit->x, pInit->y, pInit->width, pInit->height);
return TRUE;
}
static void WM_Delete(GHandle gh) {
// Make the window invisible and clear the area underneath
if ((gh->flags & GWIN_FLG_VISIBLE)) {
gh->flags &= ~GWIN_FLG_VISIBLE;
gdispFillArea(gh->x, gh->y, gh->width, gh->height, gwinGetDefaultBgColor());
}
// Remove it from the queue
gfxQueueASyncRemove(&_GWINList, &gh->wmq);
}
static void WM_Visible(GHandle gh) {
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
if ((gh->flags & GWIN_FLG_VISIBLE)) {
if (gh->vmt->Redraw)
gh->vmt->Redraw(gh);
else
gdispFillArea(gh->x, gh->y, gh->width, gh->height, gh->bgcolor);
// A real window manager would also redraw the borders here
} else
gdispFillArea(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 > gdispGetWidth()-MIN_WIN_WIDTH) x = gdispGetWidth()-MIN_WIN_WIDTH;
if (y > gdispGetHeight()-MIN_WIN_HEIGHT) y = gdispGetHeight()-MIN_WIN_HEIGHT;
if (w < MIN_WIN_WIDTH) { w = MIN_WIN_WIDTH; }
if (h < MIN_WIN_HEIGHT) { h = MIN_WIN_HEIGHT; }
if (x+w > gdispGetWidth()) w = gdispGetWidth() - x;
if (y+h > gdispGetHeight()) h = gdispGetHeight() - y;
// If there has been no resize just exit
if (gh->x == x && gh->y == y && gh->width == w && gh->height == h)
return;
// Clear the old area
if ((gh->flags & GWIN_FLG_VISIBLE))
gdispFillArea(gh->x, gh->y, gh->width, gh->height, gwinGetDefaultBgColor());
// Set the new size
gh->x = x; gh->y = y;
gh->width = w; gh->height = h;
// Redraw the window (if possible)
if ((gh->flags & GWIN_FLG_VISIBLE)) {
if (gh->vmt->Redraw) {
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
gh->vmt->Redraw(gh);
}
}
}
static void WM_MinMax(GHandle gh, GWindowMinMax minmax) {
(void)gh; (void) minmax;
// We don't support minimising, maximising or restoring
}
static void WM_Raise(GHandle gh) {
// Take it off the list and then put it back on top
// The order of the list then reflects the z-order.
gfxQueueASyncRemove(&_GWINList, &gh->wmq);
gfxQueueASyncPut(&_GWINList, &gh->wmq);
// Redraw the window
if ((gh->flags & GWIN_FLG_VISIBLE)) {
if (gh->vmt->Redraw) {
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
gh->vmt->Redraw(gh);
}
}
}
#endif /* GFX_USE_GWIN && GWIN_NEED_WINDOWMANAGER */
/** @} */

118
src/gwin/label.c 100644
View File

@ -0,0 +1,118 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://chibios-gfx.com/license.html
*/
/**
* @file include/gwin/label.h
* @brief GWIN label widget header file.
*
* @defgroup Label Label
* @ingroup GWIN
*
* @{
*/
#include "gfx.h"
#if GFX_USE_GWIN && GWIN_NEED_LABEL
#include "gwin/class_gwin.h"
#define GLABEL_FLG_WAUTO (GWIN_FIRST_CONTROL_FLAG<<0)
#define GLABEL_FLG_HAUTO (GWIN_FIRST_CONTROL_FLAG<<1)
// Simple: single line with no wrapping
static coord_t getwidth(const char *text, font_t font, coord_t maxwidth) {
(void) maxwidth;
return gdispGetStringWidth(text, font)+2; // Allow one pixel of padding on each side
}
// Simple: single line with no wrapping
static coord_t getheight(const char *text, font_t font, coord_t maxwidth) {
(void) text;
(void) maxwidth;
return gdispGetFontMetric(font, fontHeight);
}
static void gwinLabelDefaultDraw(GWidgetObject *gw, void *param) {
coord_t w, h;
(void) param;
w = (gw->g.flags & GLABEL_FLG_WAUTO) ? getwidth(gw->text, gw->g.font, gdispGetWidth() - gw->g.x) : gw->g.width;
h = (gw->g.flags & GLABEL_FLG_HAUTO) ? getheight(gw->text, gw->g.font, gdispGetWidth() - gw->g.x) : gw->g.height;
if (gw->g.width != w || gw->g.height != h) {
gwinResize(&gw->g, w, h);
return;
}
gdispFillStringBox(gw->g.x, gw->g.y, gw->g.width, gw->g.height, gw->text, gw->g.font,
(gw->g.flags & GWIN_FLG_ENABLED) ? gw->pstyle->enabled.text : gw->pstyle->disabled.text, gw->pstyle->background,
justifyLeft);
}
static const gwidgetVMT labelVMT = {
{
"Label", // The class name
sizeof(GLabelObject), // The object size
_gwidgetDestroy, // The destroy routine
_gwidgetRedraw, // The redraw routine
0, // The after-clear routine
},
gwinLabelDefaultDraw, // default drawing routine
#if GINPUT_NEED_MOUSE
{
0, // Process mose down events (NOT USED)
0, // Process mouse up events (NOT USED)
0, // Process mouse move events (NOT USED)
},
#endif
#if GINPUT_NEED_TOGGLE
{
0, // No toggle role
0, // Assign Toggles (NOT USED)
0, // Get Toggles (NOT USED)
0, // Process toggle off event (NOT USED)
0, // Process toggle on event (NOT USED)
},
#endif
#if GINPUT_NEED_DIAL
{
0, // No dial roles
0, // Assign Dials (NOT USED)
0, // Get Dials (NOT USED)
0, // Procees dial move events (NOT USED)
},
#endif
};
GHandle gwinLabelCreate(GLabelObject *widget, GWidgetInit *pInit) {
uint16_t flags = 0;
// auto assign width
if (pInit->g.width <= 0) {
flags |= GLABEL_FLG_WAUTO;
pInit->g.width = getwidth(pInit->text, gwinGetDefaultFont(), gdispGetWidth() - pInit->g.x);
}
// auto assign height
if (pInit->g.height <= 0) {
flags |= GLABEL_FLG_HAUTO;
pInit->g.height = getheight(pInit->text, gwinGetDefaultFont(), gdispGetWidth() - pInit->g.x);
}
if (!(widget = (GLabelObject *)_gwidgetCreate(&widget->w, pInit, &labelVMT)))
return 0;
widget->w.g.flags |= flags;
gwinSetVisible(&widget->w.g, pInit->g.show);
return (GHandle)widget;
}
#endif // GFX_USE_GWIN && GFX_NEED_LABEL

229
src/gwin/radio.c 100644
View File

@ -0,0 +1,229 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://chibios-gfx.com/license.html
*/
/**
* @file src/gwin/radio.c
* @brief GWIN sub-system radio button code.
*
* @defgroup RadioButton RadioButton
* @ingroup GWIN
*
* @{
*/
#include "gfx.h"
#if GFX_USE_GWIN && GWIN_NEED_RADIO
#include "gwin/class_gwin.h"
// Our pressed state
#define GRADIO_FLG_PRESSED (GWIN_FIRST_CONTROL_FLAG<<0)
// Send the button event
static void SendRadioEvent(GWidgetObject *gw) {
GSourceListener * psl;
GEvent * pe;
#define pbe ((GEventGWinRadio *)pe)
// Trigger a GWIN Button Event
psl = 0;
while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) {
if (!(pe = geventGetEventBuffer(psl)))
continue;
pbe->type = GEVENT_GWIN_RADIO;
pbe->radio = (GHandle)gw;
pbe->group = ((GRadioObject *)gw)->group;
geventSendEvent(psl);
}
#undef pbe
}
#if GINPUT_NEED_MOUSE
// A mouse down has occurred over the button
static void MouseDown(GWidgetObject *gw, coord_t x, coord_t y) {
(void) x; (void) y;
gwinRadioPress((GHandle)gw);
}
#endif
#if GINPUT_NEED_TOGGLE
// A toggle on has occurred
static void ToggleOn(GWidgetObject *gw, uint16_t role) {
(void) role;
gwinRadioPress((GHandle)gw);
}
static void ToggleAssign(GWidgetObject *gw, uint16_t role, uint16_t instance) {
(void) role;
((GRadioObject *)gw)->toggle = instance;
}
static uint16_t ToggleGet(GWidgetObject *gw, uint16_t role) {
(void) role;
return ((GRadioObject *)gw)->toggle;
}
#endif
// The radio button VMT table
static const gwidgetVMT radioVMT = {
{
"Radio", // The classname
sizeof(GRadioObject), // The object size
_gwidgetDestroy, // The destroy routine
_gwidgetRedraw, // The redraw routine
0, // The after-clear routine
},
gwinRadioDraw_Radio, // The default drawing routine
#if GINPUT_NEED_MOUSE
{
MouseDown, // Process mouse down events
0, // Process mouse up events (NOT USED)
0, // Process mouse move events (NOT USED)
},
#endif
#if GINPUT_NEED_TOGGLE
{
1, // 1 toggle role
ToggleAssign, // Assign Toggles
ToggleGet, // Get Toggles
0, // Process toggle off events (NOT USED)
ToggleOn, // Process toggle on events
},
#endif
#if GINPUT_NEED_DIAL
{
0, // No dial roles
0, // Assign Dials (NOT USED)
0, // Get Dials (NOT USED)
0, // Process dial move events (NOT USED)
},
#endif
};
GHandle gwinRadioCreate(GRadioObject *gw, const GWidgetInit *pInit, uint16_t group) {
if (!(gw = (GRadioObject *)_gwidgetCreate(&gw->w, pInit, &radioVMT)))
return 0;
#if GINPUT_NEED_TOGGLE
gw->toggle = GWIDGET_NO_INSTANCE;
#endif
gw->group = group;
gwinSetVisible((GHandle)gw, pInit->g.show);
return (GHandle)gw;
}
void gwinRadioPress(GHandle gh) {
GHandle gx;
if (gh->vmt != (gwinVMT *)&radioVMT || (gh->flags & GRADIO_FLG_PRESSED))
return;
if ((gx = gwinRadioGetActive(((GRadioObject *)gh)->group))) {
gx->flags &= ~GRADIO_FLG_PRESSED;
_gwidgetRedraw(gx);
}
gh->flags |= GRADIO_FLG_PRESSED;
_gwidgetRedraw(gh);
SendRadioEvent((GWidgetObject *)gh);
}
bool_t gwinRadioIsPressed(GHandle gh) {
if (gh->vmt != (gwinVMT *)&radioVMT)
return FALSE;
return (gh->flags & GRADIO_FLG_PRESSED) ? TRUE : FALSE;
}
GHandle gwinRadioGetActive(uint16_t group) {
const gfxQueueASyncItem * qi;
GHandle gh;
for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
gh = QItem2GWindow(qi);
if (gh->vmt == (gwinVMT *)&radioVMT && ((GRadioObject *)gh)->group == group && (gh->flags & GRADIO_FLG_PRESSED))
return gh;
}
return 0;
}
/*----------------------------------------------------------
* Custom Draw Routines
*----------------------------------------------------------*/
static const GColorSet *getDrawColors(GWidgetObject *gw) {
if (!(gw->g.flags & GWIN_FLG_ENABLED)) return &gw->pstyle->disabled;
if ((gw->g.flags & GRADIO_FLG_PRESSED)) return &gw->pstyle->pressed;
return &gw->pstyle->enabled;
}
void gwinRadioDraw_Radio(GWidgetObject *gw, void *param) {
#define gcw ((GRadioObject *)gw)
coord_t ld, df;
const GColorSet * pcol;
(void) param;
if (gw->g.vmt != (gwinVMT *)&radioVMT) return;
pcol = getDrawColors(gw);
ld = gw->g.width < gw->g.height ? gw->g.width : gw->g.height;
#if GDISP_NEED_CIRCLE
df = (ld-1)/2;
gdispFillArea(gw->g.x, gw->g.y, ld, ld, gw->pstyle->background);
gdispDrawCircle(gw->g.x+df, gw->g.y+df, df, pcol->edge);
if (gw->g.flags & GRADIO_FLG_PRESSED)
gdispFillCircle(gw->g.x+df, gw->g.y+df, df <= 2 ? 1 : (df-2), pcol->fill);
#else
gdispFillArea(gw->g.x+1, gw->g.y+1, ld, ld-2, gw->pstyle->background);
gdispDrawBox(gw->g.x, gw->g.y, ld, ld, pcol->edge);
df = ld < 4 ? 1 : 2;
if (gw->g.flags & GRADIO_FLG_PRESSED)
gdispFillArea(gw->g.x+df, gw->g.y+df, ld-2*df, ld-2*df, pcol->fill);
#endif
gdispFillStringBox(gw->g.x+ld+1, gw->g.y, gw->g.width-ld-1, gw->g.height, gw->text, gw->g.font, pcol->text, gw->pstyle->background, justifyLeft);
#undef gcw
}
void gwinRadioDraw_Button(GWidgetObject *gw, void *param) {
const GColorSet * pcol;
(void) param;
if (gw->g.vmt != (gwinVMT *)&radioVMT) return;
pcol = getDrawColors(gw);
gdispFillStringBox(gw->g.x, gw->g.y, gw->g.width-1, gw->g.height-1, gw->text, gw->g.font, pcol->text, pcol->fill, justifyCenter);
gdispDrawLine(gw->g.x+gw->g.width-1, gw->g.y, gw->g.x+gw->g.width-1, gw->g.y+gw->g.height-1, pcol->edge);
gdispDrawLine(gw->g.x, gw->g.y+gw->g.height-1, gw->g.x+gw->g.width-2, gw->g.y+gw->g.height-1, pcol->edge);
}
void gwinRadioDraw_Tab(GWidgetObject *gw, void *param) {
const GColorSet * pcol;
(void) param;
if (gw->g.vmt != (gwinVMT *)&radioVMT) return;
pcol = getDrawColors(gw);
if ((gw->g.flags & GRADIO_FLG_PRESSED)) {
gdispDrawBox(gw->g.x, gw->g.y, gw->g.width, gw->g.height, pcol->edge);
gdispFillStringBox(gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-1, gw->text, gw->g.font, pcol->text, pcol->fill, justifyCenter);
} else {
gdispFillStringBox(gw->g.x, gw->g.y, gw->g.width-1, gw->g.height-1, gw->text, gw->g.font, pcol->text, pcol->fill, justifyCenter);
gdispDrawLine(gw->g.x+gw->g.width-1, gw->g.y, gw->g.x+gw->g.width-1, gw->g.y+gw->g.height-1, pcol->edge);
gdispDrawLine(gw->g.x, gw->g.y+gw->g.height-1, gw->g.x+gw->g.width-2, gw->g.y+gw->g.height-1, pcol->edge);
}
}
#endif /* GFX_USE_GWIN && GWIN_NEED_BUTTON */
/** @} */

View File

@ -19,140 +19,232 @@
#if (GFX_USE_GWIN && GWIN_NEED_SLIDER) || defined(__DOXYGEN__)
#include "gwin/internal.h"
#include "gwin/class_gwin.h"
#ifndef GWIN_SLIDER_DEAD_BAND
#define GWIN_SLIDER_DEAD_BAND 5
#endif
#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
static void trackSliderDraw(GHandle gh, coord_t x, coord_t y);
#ifndef GWIN_SLIDER_TOGGLE_INC
#define GWIN_SLIDER_TOGGLE_INC 20 // How many toggles to go from minimum to maximum
#endif
static const GSliderDrawStyle GSliderDefaultStyle = {
HTML2COLOR(0x404040), // color_edge;
HTML2COLOR(0x000000), // color_thumb;
HTML2COLOR(0x00E000), // color_active;
HTML2COLOR(0xE0E0E0), // color_inactive;
};
// Send the slider event
static void SendSliderEvent(GWidgetObject *gw) {
GSourceListener * psl;
GEvent * pe;
#define pse ((GEventGWinSlider *)pe)
// Process an event callback
static void gwinSliderCallback(void *param, GEvent *pe) {
GSourceListener *psl;
#define gh ((GHandle)param)
#define gsw ((GSliderObject *)param)
#define gsh ((GSourceHandle)param)
#define pme ((GEventMouse *)pe)
#define pde ((GEventDial *)pe)
#define pse ((GEventGWinSlider *)pe)
switch (pe->type) {
#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
case GEVENT_MOUSE:
case GEVENT_TOUCH:
// If not tracking we only only interested in a mouse down over the slider
if (!gsw->tracking) {
if ((pme->meta & GMETA_MOUSE_DOWN)
&& pme->x >= gh->x && pme->x < gh->x + gh->width
&& pme->y >= gh->y && pme->y < gh->y + gh->height) {
gsw->tracking = TRUE;
trackSliderDraw(gh, pme->x-gh->x, pme->y-gh->y);
}
return;
}
// We are tracking the mouse
// Test for button up
if ((pme->meta & GMETA_MOUSE_UP)) {
gsw->tracking = FALSE;
#if !GWIN_BUTTON_LAZY_RELEASE
// Are we over the slider?
if (pme->x < gh->x || pme->x >= gh->x + gh->width
|| pme->y < gh->y || pme->y >= gh->y + gh->height) {
// No - restore the slider
gwinSliderDraw(gh);
return;
}
#endif
// Set the new position
if (gh->width < gh->height)
gwinSetSliderPosition(gh,
(uint16_t)((uint32_t)(gh->height-1-pme->y+gh->y-GWIN_SLIDER_DEAD_BAND)*(gsw->max-gsw->min)/(gh->height-2*GWIN_SLIDER_DEAD_BAND) + gsw->min));
else
gwinSetSliderPosition(gh,
(uint16_t)((uint32_t)(pme->x-gh->x-GWIN_SLIDER_DEAD_BAND)*(gsw->max-gsw->min)/(gh->width-2*GWIN_SLIDER_DEAD_BAND) + gsw->min));
// Update the display
gwinSliderDraw(gh);
// Generate the event
break;
}
// If mouse down - track movement
if ((pme->current_buttons & GINPUT_MOUSE_BTN_LEFT))
trackSliderDraw(gh, pme->x-gh->x, pme->y-gh->y);
return;
#endif
#if GFX_USE_GINPUT && GINPUT_NEED_DIAL
case GEVENT_DIAL:
// Set the new position
gwinSetSliderPosition(gh, (uint16_t)((uint32_t)pde->value*(gsw->max-gsw->min)/ginputGetDialRange(pde->instance) + gsw->min));
// Update the display
gwinSliderDraw(gh);
// Generate the event
break;
#endif
default:
return;
}
// Trigger a GWIN Slider Event
// Trigger a GWIN Button Event
psl = 0;
while ((psl = geventGetSourceListener(gsh, psl))) {
while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) {
if (!(pe = geventGetEventBuffer(psl)))
continue;
pse->type = GEVENT_GWIN_SLIDER;
pse->slider = gh;
pse->position = gsw->pos;
pse->slider = (GHandle)gw;
pse->position = ((GSliderObject *)gw)->pos;
geventSendEvent(psl);
}
#undef pse
#undef pme
#undef pxe
#undef gsh
#undef gsw
#undef gh
}
GHandle gwinCreateSlider(GSliderObject *gs, coord_t x, coord_t y, coord_t width, coord_t height) {
if (!(gs = (GSliderObject *)_gwinInit((GWindowObject *)gs, x, y, width, height, sizeof(GSliderObject))))
// Reset the display position back to the value predicted by the saved slider position
static void ResetDisplayPos(GSliderObject *gsw) {
if (gsw->w.g.width < gsw->w.g.height)
gsw->dpos = gsw->w.g.height-1-((gsw->w.g.height-1)*(gsw->pos-gsw->min))/(gsw->max-gsw->min);
else
gsw->dpos = ((gsw->w.g.width-1)*(gsw->pos-gsw->min))/(gsw->max-gsw->min);
}
#if GINPUT_NEED_MOUSE
// A mouse up event
static void MouseUp(GWidgetObject *gw, coord_t x, coord_t y) {
#define gsw ((GSliderObject *)gw)
#define gh ((GHandle)gw)
#if GWIN_BUTTON_LAZY_RELEASE
// Clip to the slider
if (x < 0) x = 0;
else if (x >= gh->width) x = gh->width-1;
if (y < 0) y = 0;
else if (y >= gh->height) x = gh->height-1;
#else
// Are we over the slider?
if (x < 0 || x >= gh->width || y < 0 || y >= gh->height) {
// No - restore the slider
ResetDisplayPos(gsw);
_gwidgetRedraw(gh);
return;
}
#endif
// Set the new position
if (gh->width < gh->height) {
if (y > gh->height-GWIN_SLIDER_DEAD_BAND)
gsw->pos = gsw->min;
else if (y < GWIN_SLIDER_DEAD_BAND)
gsw->pos = gsw->max;
else
gsw->pos = (uint16_t)((int32_t)(gh->height-1-y-GWIN_SLIDER_DEAD_BAND)*(gsw->max-gsw->min)/(gh->height-2*GWIN_SLIDER_DEAD_BAND) + gsw->min);
} else {
if (x > gh->width-GWIN_SLIDER_DEAD_BAND)
gsw->pos = gsw->max;
else if (x < GWIN_SLIDER_DEAD_BAND)
gsw->pos = gsw->min;
else
gsw->pos = (uint16_t)((int32_t)(x-GWIN_SLIDER_DEAD_BAND)*(gsw->max-gsw->min)/(gh->width-2*GWIN_SLIDER_DEAD_BAND) + gsw->min);
}
ResetDisplayPos(gsw);
_gwidgetRedraw(gh);
// Generate the event
SendSliderEvent(gw);
#undef gh
#undef gsw
}
// A mouse move (or mouse down) event
static void MouseMove(GWidgetObject *gw, coord_t x, coord_t y) {
#define gsw ((GSliderObject *)gw)
// Determine the temporary display position (with range checking)
if (gw->g.width < gw->g.height) {
if (y < 0)
gsw->dpos = 0;
else if (y >= gw->g.height)
gsw->dpos = gw->g.height-1;
else
gsw->dpos = y;
} else {
if (x < 0)
gsw->dpos = 0;
else if (x >= gw->g.width)
gsw->dpos = gw->g.width-1;
else
gsw->dpos = x;
}
// Update the display
_gwidgetRedraw(&gw->g);
#undef gsw
}
#endif
#if GINPUT_NEED_TOGGLE
// A toggle on has occurred
static void ToggleOn(GWidgetObject *gw, uint16_t role) {
#define gsw ((GSliderObject *)gw)
if (role) {
gwinSliderSetPosition((GHandle)gw, gsw->pos+(gsw->max-gsw->min)/GWIN_SLIDER_TOGGLE_INC);
SendSliderEvent(gw);
} else {
gwinSliderSetPosition((GHandle)gw, gsw->pos-(gsw->max-gsw->min)/GWIN_SLIDER_TOGGLE_INC);
SendSliderEvent(gw);
}
#undef gsw
}
static void ToggleAssign(GWidgetObject *gw, uint16_t role, uint16_t instance) {
if (role)
((GSliderObject *)gw)->t_up = instance;
else
((GSliderObject *)gw)->t_dn = instance;
}
static uint16_t ToggleGet(GWidgetObject *gw, uint16_t role) {
return role ? ((GSliderObject *)gw)->t_up : ((GSliderObject *)gw)->t_dn;
}
#endif
#if GINPUT_NEED_DIAL
// A dial move event
static void DialMove(GWidgetObject *gw, uint16_t role, uint16_t value, uint16_t max) {
#define gsw ((GSliderObject *)gw)
(void) role;
// Set the new position
gsw->pos = (uint16_t)((uint32_t)value*(gsw->max-gsw->min)/max + gsw->min);
ResetDisplayPos(gsw);
_gwidgetRedraw((GHandle)gw);
// Generate the event
SendSliderEvent(gw);
#undef gsw
}
static void DialAssign(GWidgetObject *gw, uint16_t role, uint16_t instance) {
(void) role;
((GSliderObject *)gw)->dial = instance;
}
static uint16_t DialGet(GWidgetObject *gw, uint16_t role) {
(void) role;
return ((GSliderObject *)gw)->dial;
}
#endif
// The slider VMT table
static const gwidgetVMT sliderVMT = {
{
"Slider", // The classname
sizeof(GSliderObject), // The object size
_gwidgetDestroy, // The destroy routine
_gwidgetRedraw, // The redraw routine
0, // The after-clear routine
},
gwinSliderDraw_Std, // The default drawing routine
#if GINPUT_NEED_MOUSE
{
0, // Process mouse down events (NOT USED)
MouseUp, // Process mouse up events
MouseMove, // Process mouse move events
},
#endif
#if GINPUT_NEED_TOGGLE
{
2, // 1 toggle role
ToggleAssign, // Assign Toggles
ToggleGet, // Get Toggles
0, // Process toggle off events (NOT USED)
ToggleOn, // Process toggle on events
},
#endif
#if GINPUT_NEED_DIAL
{
1, // 1 dial roles
DialAssign, // Assign Dials
DialGet, // Get Dials
DialMove, // Process dial move events
},
#endif
};
GHandle gwinSliderCreate(GSliderObject *gs, const GWidgetInit *pInit) {
if (!(gs = (GSliderObject *)_gwidgetCreate(&gs->w, pInit, &sliderVMT)))
return 0;
gs->gwin.type = GW_SLIDER;
gs->fn = gwinSliderDraw_Std;
gs->param = 0;
gwinSetSliderStyle(&gs->gwin, &GSliderDefaultStyle);
#if GINPUT_NEED_TOGGLE
gs->t_dn = GWIDGET_NO_INSTANCE;
gs->t_up = GWIDGET_NO_INSTANCE;
#endif
#if GINPUT_NEED_DIAL
gs->dial = GWIDGET_NO_INSTANCE;
#endif
gs->min = 0;
gs->max = 100;
gs->pos = 0;
gs->tracking = FALSE;
geventListenerInit(&gs->listener);
geventRegisterCallback(&gs->listener, gwinSliderCallback, gs);
ResetDisplayPos(gs);
gwinSetVisible((GHandle)gs, pInit->g.show);
return (GHandle)gs;
}
void gwinSetSliderRange(GHandle gh, int min, int max) {
void gwinSliderSetRange(GHandle gh, int min, int max) {
#define gsw ((GSliderObject *)gh)
if (gh->type != GW_SLIDER)
if (gh->vmt != (gwinVMT *)&sliderVMT)
return;
if (min == max) // prevent divide by 0 errors.
@ -160,13 +252,14 @@ void gwinSetSliderRange(GHandle gh, int min, int max) {
gsw->min = min;
gsw->max = max;
gsw->pos = min;
ResetDisplayPos(gsw);
#undef gsw
}
void gwinSetSliderPosition(GHandle gh, int pos) {
void gwinSliderSetPosition(GHandle gh, int pos) {
#define gsw ((GSliderObject *)gh)
if (gh->type != GW_SLIDER)
if (gh->vmt != (gwinVMT *)&sliderVMT)
return;
if (gsw->min <= gsw->max) {
@ -178,126 +271,106 @@ void gwinSetSliderPosition(GHandle gh, int pos) {
else if (pos < gsw->max) gsw->pos = gsw->max;
else gsw->pos = pos;
}
ResetDisplayPos(gsw);
#undef gsw
}
void gwinSetSliderStyle(GHandle gh, const GSliderDrawStyle *pStyle) {
#define gsw ((GSliderObject *)gh)
/*----------------------------------------------------------
* Custom Draw Routines
*----------------------------------------------------------*/
if (gh->type != GW_SLIDER)
void gwinSliderDraw_Std(GWidgetObject *gw, void *param) {
#define gsw ((GSliderObject *)gw)
const GColorSet * pcol;
(void) param;
if (gw->g.vmt != (gwinVMT *)&sliderVMT)
return;
gsw->style.color_edge = pStyle->color_edge;
gsw->style.color_thumb = pStyle->color_thumb;
gsw->style.color_active = pStyle->color_active;
gsw->style.color_inactive = pStyle->color_inactive;
#undef gsw
}
#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
static void trackSliderDraw(GHandle gh, coord_t x, coord_t y) {
#define gsw ((GSliderObject *)gh)
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
if (gh->height <= gh->width)
gsw->fn(gh, FALSE, x, &gsw->style, gsw->param);
else
gsw->fn(gh, TRUE, y, &gsw->style, gsw->param);
#undef gbw
}
#endif
void gwinSliderDraw(GHandle gh) {
#define gsw ((GSliderObject *)gh)
if (gh->type != GW_SLIDER)
return;
#if GDISP_NEED_CLIP
gdispSetClip(gh->x, gh->y, gh->width, gh->height);
#endif
if (gh->height <= gh->width)
gsw->fn(gh, FALSE, ((gh->width-1)*(gsw->pos-gsw->min))/(gsw->max-gsw->min), &gsw->style, gsw->param);
if ((gw->g.flags & GWIN_FLG_ENABLED))
pcol = &gw->pstyle->pressed;
else
gsw->fn(gh, TRUE, gh->height-1-((gh->height-1)*(gsw->pos-gsw->min))/(gsw->max-gsw->min), &gsw->style, gsw->param);
pcol = &gw->pstyle->disabled;
#undef gbw
}
if (gw->g.width < gw->g.height) { // Vertical slider
if (gsw->dpos != gw->g.height-1)
gdispFillArea(gw->g.x, gw->g.y+gsw->dpos, gw->g.width, gw->g.height - gsw->dpos, pcol->progress); // Active Area
if (gsw->dpos != 0)
gdispFillArea(gw->g.x, gw->g.y, gw->g.width, gsw->dpos, gw->pstyle->enabled.progress); // Inactive area
gdispDrawBox(gw->g.x, gw->g.y, gw->g.width, gw->g.height, pcol->edge); // Edge
gdispDrawLine(gw->g.x, gw->g.y+gsw->dpos, gw->g.x+gw->g.width-1, gw->g.y+gsw->dpos, pcol->edge); // Thumb
if (gsw->dpos >= 2)
gdispDrawLine(gw->g.x, gw->g.y+gsw->dpos-2, gw->g.x+gw->g.width-1, gw->g.y+gsw->dpos-2, pcol->edge); // Thumb
if (gsw->dpos <= gw->g.height-2)
gdispDrawLine(gw->g.x, gw->g.y+gsw->dpos+2, gw->g.x+gw->g.width-1, gw->g.y+gsw->dpos+2, pcol->edge); // Thumb
void gwinSetSliderCustom(GHandle gh, GSliderDrawFunction fn, void *param) {
#define gsw ((GSliderObject *)gh)
if (gh->type != GW_SLIDER)
return;
gsw->fn = fn ? fn : gwinSliderDraw_Std;
gsw->param = param;
// Horizontal slider
} else {
if (gsw->dpos != gw->g.width-1)
gdispFillArea(gw->g.x+gsw->dpos, gw->g.y, gw->g.width-gsw->dpos, gw->g.height, gw->pstyle->enabled.progress); // Inactive area
if (gsw->dpos != 0)
gdispFillArea(gw->g.x, gw->g.y, gsw->dpos, gw->g.height, pcol->progress); // Active Area
gdispDrawBox(gw->g.x, gw->g.y, gw->g.width, gw->g.height, pcol->edge); // Edge
gdispDrawLine(gw->g.x+gsw->dpos, gw->g.y, gw->g.x+gsw->dpos, gw->g.y+gw->g.height-1, pcol->edge); // Thumb
if (gsw->dpos >= 2)
gdispDrawLine(gw->g.x+gsw->dpos-2, gw->g.y, gw->g.x+gsw->dpos-2, gw->g.y+gw->g.height-1, pcol->edge); // Thumb
if (gsw->dpos <= gw->g.width-2)
gdispDrawLine(gw->g.x+gsw->dpos+2, gw->g.y, gw->g.x+gsw->dpos+2, gw->g.y+gw->g.height-1, pcol->edge); // Thumb
}
gdispDrawStringBox(gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->text, gw->g.font, pcol->text, justifyCenter);
#undef gsw
}
void gwinSliderSetEnabled(GHandle gh, bool_t enabled) {
if (gh->type != GW_SLIDER)
void gwinSliderDraw_Image(GWidgetObject *gw, void *param) {
#define gsw ((GSliderObject *)gw)
#define gi ((gdispImage *)param)
const GColorSet * pcol;
coord_t z, v;
if (gw->g.vmt != (gwinVMT *)&sliderVMT)
return;
gh->enabled = enabled;
}
if ((gw->g.flags & GWIN_FLG_ENABLED))
pcol = &gw->pstyle->pressed;
else
pcol = &gw->pstyle->disabled;
void gwinSliderDraw_Std(GHandle gh, bool_t isVertical, coord_t thumbpos, const GSliderDrawStyle *pstyle, void *param) {
(void) param;
if (gw->g.width < gw->g.height) { // Vertical slider
if (gsw->dpos != 0) // The unfilled area
gdispFillArea(gw->g.x, gw->g.y, gw->g.width, gsw->dpos, gw->pstyle->enabled.progress); // Inactive area
if (gsw->dpos != gw->g.height-1) { // The filled area
for(z=gw->g.height, v=gi->height; z > gsw->dpos;) {
z -= v;
if (z < gsw->dpos) {
v -= gsw->dpos - z;
z = gsw->dpos;
}
gdispImageDraw(gi, gw->g.x, gw->g.y+z, gw->g.width, v, 0, gi->height-v);
}
}
gdispDrawBox(gw->g.x, gw->g.y, gw->g.width, gw->g.height, pcol->edge); // Edge
gdispDrawLine(gw->g.x, gw->g.y+gsw->dpos, gw->g.x+gw->g.width-1, gw->g.y+gsw->dpos, pcol->edge); // Thumb
if (isVertical) {
if (thumbpos != gh->height-1)
gdispFillArea(gh->x, gh->y+thumbpos, gh->width, gh->height - thumbpos, pstyle->color_active);
if (thumbpos != 0)
gdispFillArea(gh->x, gh->y, gh->width, thumbpos, pstyle->color_inactive);
gdispDrawBox(gh->x, gh->y, gh->width, gh->height, pstyle->color_edge);
gdispDrawLine(gh->x, gh->y+thumbpos, gh->x+gh->width-1, gh->y+thumbpos, pstyle->color_thumb);
if (thumbpos >= 2)
gdispDrawLine(gh->x, gh->y+thumbpos-2, gh->x+gh->width-1, gh->y+thumbpos-2, pstyle->color_thumb);
if (thumbpos <= gh->height-2)
gdispDrawLine(gh->x, gh->y+thumbpos+2, gh->x+gh->width-1, gh->y+thumbpos+2, pstyle->color_thumb);
// Horizontal slider
} else {
if (thumbpos != gh->width-1)
gdispFillArea(gh->x+thumbpos, gh->y, gh->width-thumbpos, gh->height, pstyle->color_inactive);
if (thumbpos != 0)
gdispFillArea(gh->x, gh->y, thumbpos, gh->height, pstyle->color_active);
gdispDrawBox(gh->x, gh->y, gh->width, gh->height, pstyle->color_edge);
gdispDrawLine(gh->x+thumbpos, gh->y, gh->x+thumbpos, gh->y+gh->height-1, pstyle->color_thumb);
if (thumbpos >= 2)
gdispDrawLine(gh->x+thumbpos-2, gh->y, gh->x+thumbpos-2, gh->y+gh->height-1, pstyle->color_thumb);
if (thumbpos <= gh->width-2)
gdispDrawLine(gh->x+thumbpos+2, gh->y, gh->x+thumbpos+2, gh->y+gh->height-1, pstyle->color_thumb);
if (gsw->dpos != gw->g.width-1) // The unfilled area
gdispFillArea(gw->g.x+gsw->dpos, gw->g.y, gw->g.width-gsw->dpos, gw->g.height, gw->pstyle->enabled.progress); // Inactive area
if (gsw->dpos != 0) { // The filled area
for(z=0, v=gi->width; z < gsw->dpos; z += v) {
if (z+v > gsw->dpos)
v -= z+v - gsw->dpos;
gdispImageDraw(gi, gw->g.x+z, gw->g.y, v, gw->g.height, 0, 0);
}
}
gdispDrawBox(gw->g.x, gw->g.y, gw->g.width, gw->g.height, pcol->edge); // Edge
gdispDrawLine(gw->g.x+gsw->dpos, gw->g.y, gw->g.x+gsw->dpos, gw->g.y+gw->g.height-1, pcol->edge); // Thumb
}
gdispDrawStringBox(gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->text, gw->g.font, pcol->text, justifyCenter);
#undef gsw
}
#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
bool_t gwinAttachSliderMouse(GHandle gh, uint16_t instance) {
GSourceHandle gsh;
if (gh->type != GW_SLIDER || !(gsh = ginputGetMouse(instance)))
return FALSE;
return geventAttachSource(&((GSliderObject *)gh)->listener, gsh, GLISTEN_MOUSEMETA|GLISTEN_MOUSEDOWNMOVES);
}
#endif
#if GFX_USE_GINPUT && GINPUT_NEED_DIAL
bool_t gwinAttachSliderDial(GHandle gh, uint16_t instance) {
GSourceHandle gsh;
if (gh->type != GW_SLIDER || !(gsh = ginputGetDial(instance)))
return FALSE;
return geventAttachSource(&((GSliderObject *)gh)->listener, gsh, 0);
}
#endif
#endif /* GFX_USE_GWIN && GWIN_NEED_BUTTON */
/** @} */