Merge branch 'TextEdit'
This commit is contained in:
commit
10c7471149
29 changed files with 1096 additions and 119 deletions
|
@ -42,7 +42,7 @@
|
||||||
/* Our custom yellow style */
|
/* Our custom yellow style */
|
||||||
static const GWidgetStyle YellowWidgetStyle = {
|
static const GWidgetStyle YellowWidgetStyle = {
|
||||||
Yellow, // window background
|
Yellow, // window background
|
||||||
//HTML2COLOR(0x800000), // focus - for text edit.
|
HTML2COLOR(0x800000), // focus - for text edit.
|
||||||
|
|
||||||
// enabled color set
|
// enabled color set
|
||||||
{
|
{
|
||||||
|
|
3
demos/modules/gwin/textedit/demo.mk
Normal file
3
demos/modules/gwin/textedit/demo.mk
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
DEMODIR = $(GFXLIB)/demos/modules/gwin/textedit
|
||||||
|
GFXINC += $(DEMODIR)
|
||||||
|
GFXSRC += $(DEMODIR)/main.c
|
76
demos/modules/gwin/textedit/gfxconf.h
Normal file
76
demos/modules/gwin/textedit/gfxconf.h
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 2013, Joel Bodenmann aka Tectu <joel@unormal.org>
|
||||||
|
* Copyright (c) 2012, 2013, Andrew Hannam aka inmarket
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the <organization> nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _GFXCONF_H
|
||||||
|
#define _GFXCONF_H
|
||||||
|
|
||||||
|
/* The operating system to use. One of these must be defined - preferably in your Makefile */
|
||||||
|
//#define GFX_USE_OS_CHIBIOS FALSE
|
||||||
|
//#define GFX_USE_OS_WIN32 FALSE
|
||||||
|
//#define GFX_USE_OS_LINUX FALSE
|
||||||
|
//#define GFX_USE_OS_OSX FALSE
|
||||||
|
|
||||||
|
/* GFX sub-systems to turn on */
|
||||||
|
#define GFX_USE_GDISP TRUE
|
||||||
|
#define GFX_USE_GWIN TRUE
|
||||||
|
#define GFX_USE_GINPUT TRUE
|
||||||
|
#define GFX_USE_GEVENT TRUE
|
||||||
|
#define GFX_USE_GTIMER TRUE
|
||||||
|
|
||||||
|
/* Features for the GDISP sub-system. */
|
||||||
|
#define GDISP_NEED_VALIDATION TRUE
|
||||||
|
#define GDISP_NEED_CLIP TRUE
|
||||||
|
#define GDISP_NEED_TEXT TRUE
|
||||||
|
#define GDISP_NEED_TEXT_KERNING TRUE
|
||||||
|
#define GDISP_NEED_MULTITHREAD TRUE
|
||||||
|
|
||||||
|
/* GDISP fonts to include */
|
||||||
|
#define GDISP_INCLUDE_FONT_UI2 TRUE
|
||||||
|
#define GDISP_INCLUDE_FONT_DEJAVUSANS16 TRUE
|
||||||
|
|
||||||
|
/* Features for the GWIN subsystem. */
|
||||||
|
#define GWIN_NEED_WINDOWMANAGER TRUE
|
||||||
|
#define GWIN_NEED_WIDGET TRUE
|
||||||
|
#define GWIN_NEED_CONSOLE TRUE
|
||||||
|
#define GWIN_NEED_TEXTEDIT TRUE
|
||||||
|
#define GWIN_NEED_BUTTON TRUE
|
||||||
|
|
||||||
|
/* Features for the GINPUT subsystem. */
|
||||||
|
#define GINPUT_NEED_MOUSE TRUE
|
||||||
|
|
||||||
|
/* One or both of these */
|
||||||
|
#define GINPUT_NEED_KEYBOARD TRUE
|
||||||
|
#define GWIN_NEED_KEYBOARD TRUE
|
||||||
|
|
||||||
|
/* Features for the GQUEUE subsystem. */
|
||||||
|
#define GFX_USE_GQUEUE TRUE
|
||||||
|
#define GQUEUE_NEED_ASYNC TRUE
|
||||||
|
|
||||||
|
#endif /* _GFXCONF_H */
|
||||||
|
|
157
demos/modules/gwin/textedit/main.c
Normal file
157
demos/modules/gwin/textedit/main.c
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 2013, Joel Bodenmann aka Tectu <joel@unormal.org>
|
||||||
|
* Copyright (c) 2012, 2013, Andrew Hannam aka inmarket
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the <organization> nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gfx.h"
|
||||||
|
|
||||||
|
static GHandle ghConsole;
|
||||||
|
static GHandle ghTextedit1;
|
||||||
|
static GHandle ghTextedit2;
|
||||||
|
static GHandle ghTextedit3;
|
||||||
|
static GListener gl;
|
||||||
|
#if GWIN_NEED_KEYBOARD
|
||||||
|
static GHandle ghKeyboard;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void guiCreate(void)
|
||||||
|
{
|
||||||
|
GWidgetInit wi;
|
||||||
|
gwinWidgetClearInit(&wi);
|
||||||
|
|
||||||
|
// Console
|
||||||
|
wi.g.show = TRUE;
|
||||||
|
wi.g.x = 0;
|
||||||
|
wi.g.y = 0;
|
||||||
|
wi.g.width = gdispGetWidth()/2;
|
||||||
|
wi.g.height = gdispGetHeight();
|
||||||
|
ghConsole = gwinConsoleCreate(0, &wi.g);
|
||||||
|
gwinSetColor(ghConsole, Yellow);
|
||||||
|
gwinSetBgColor(ghConsole, Black);
|
||||||
|
gwinSetFont(ghConsole, gdispOpenFont("UI2"));
|
||||||
|
gwinClear(ghConsole);
|
||||||
|
|
||||||
|
// TextEdit1
|
||||||
|
wi.g.show = TRUE;
|
||||||
|
wi.g.x = gdispGetWidth()/2 + 10;
|
||||||
|
wi.g.y = 20;
|
||||||
|
wi.g.width = 200;
|
||||||
|
wi.g.height = 35;
|
||||||
|
wi.text = "Use the TAB key";
|
||||||
|
ghTextedit1 = gwinTexteditCreate(0, &wi, 100);
|
||||||
|
|
||||||
|
// TextEdit2
|
||||||
|
wi.g.show = TRUE;
|
||||||
|
wi.g.x = gdispGetWidth()/2 + 10;
|
||||||
|
wi.g.y = 100;
|
||||||
|
wi.g.width = 200;
|
||||||
|
wi.g.height = 35;
|
||||||
|
wi.text = "to switch between";
|
||||||
|
ghTextedit2 = gwinTexteditCreate(0, &wi, 20);
|
||||||
|
//gwinTexteditSetBorder(ghTextedit2, FALSE);
|
||||||
|
|
||||||
|
// TextEdit3
|
||||||
|
wi.g.show = TRUE;
|
||||||
|
wi.g.x = gdispGetWidth()/2 + 10;
|
||||||
|
wi.g.y = 180;
|
||||||
|
wi.g.width = 200;
|
||||||
|
wi.g.height = 35;
|
||||||
|
wi.text = "the different widgets";
|
||||||
|
ghTextedit3 = gwinTexteditCreate(0, &wi, 100);
|
||||||
|
//gwinTexteditSetBorder(ghTextedit3, TRUE);
|
||||||
|
|
||||||
|
// Virtual keyboard
|
||||||
|
#if GWIN_NEED_KEYBOARD
|
||||||
|
wi.g.show = TRUE;
|
||||||
|
wi.g.x = 0;
|
||||||
|
wi.g.y = gdispGetHeight()*3/4;
|
||||||
|
wi.g.width = gdispGetWidth();
|
||||||
|
wi.g.height = gdispGetHeight()/4;
|
||||||
|
ghKeyboard = gwinKeyboardCreate(0, &wi);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
GEventKeyboard* pk;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
gfxInit();
|
||||||
|
|
||||||
|
gdispClear(Silver);
|
||||||
|
gwinSetDefaultFont(gdispOpenFont("DejaVuSans16"));
|
||||||
|
gwinSetDefaultStyle(&WhiteWidgetStyle, FALSE);
|
||||||
|
gwinSetDefaultColor(Black);
|
||||||
|
gwinSetDefaultBgColor(White);
|
||||||
|
|
||||||
|
geventListenerInit(&gl);
|
||||||
|
geventAttachSource(&gl, ginputGetKeyboard(0), GLISTEN_KEYTRANSITIONS|GLISTEN_KEYUP);
|
||||||
|
|
||||||
|
guiCreate();
|
||||||
|
|
||||||
|
gwinPrintf(ghConsole, "Keyboard Monitor...\n");
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
// Get an Event
|
||||||
|
pk = (GEventKeyboard *)geventEventWait(&gl, TIME_INFINITE);
|
||||||
|
|
||||||
|
if (pk->type != GEVENT_KEYBOARD)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
gwinPrintf(ghConsole, "KEYSTATE: 0x%04X [ %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s]",
|
||||||
|
pk->keystate,
|
||||||
|
(!pk->keystate ? "NONE " : ""),
|
||||||
|
((pk->keystate & GKEYSTATE_KEYUP) ? "KEYUP " : ""),
|
||||||
|
((pk->keystate & GKEYSTATE_REPEAT) ? "REPEAT " : ""),
|
||||||
|
((pk->keystate & GKEYSTATE_SPECIAL) ? "SPECIAL " : ""),
|
||||||
|
((pk->keystate & GKEYSTATE_RAW) ? "RAW " : ""),
|
||||||
|
((pk->keystate & GKEYSTATE_SHIFT_L) ? "LSHIFT " : ""),
|
||||||
|
((pk->keystate & GKEYSTATE_SHIFT_R) ? "RSHIFT " : ""),
|
||||||
|
((pk->keystate & GKEYSTATE_CTRL_L) ? "LCTRL " : ""),
|
||||||
|
((pk->keystate & GKEYSTATE_CTRL_R) ? "RCTRL " : ""),
|
||||||
|
((pk->keystate & GKEYSTATE_ALT_L) ? "LALT " : ""),
|
||||||
|
((pk->keystate & GKEYSTATE_ALT_R) ? "RALT " : ""),
|
||||||
|
((pk->keystate & GKEYSTATE_FN) ? "FN " : ""),
|
||||||
|
((pk->keystate & GKEYSTATE_COMPOSE) ? "COMPOSE " : ""),
|
||||||
|
((pk->keystate & GKEYSTATE_WINKEY) ? "WINKEY " : ""),
|
||||||
|
((pk->keystate & GKEYSTATE_CAPSLOCK) ? "CAPSLOCK " : ""),
|
||||||
|
((pk->keystate & GKEYSTATE_NUMLOCK) ? "NUMLOCK " : ""),
|
||||||
|
((pk->keystate & GKEYSTATE_SCROLLLOCK) ? "SCROLLLOCK " : "")
|
||||||
|
);
|
||||||
|
if (pk->bytecount) {
|
||||||
|
gwinPrintf(ghConsole, " Keys:");
|
||||||
|
for (i = 0; i < pk->bytecount; i++)
|
||||||
|
gwinPrintf(ghConsole, " 0x%02X", (uint8_t)pk->c[i]);
|
||||||
|
gwinPrintf(ghConsole, " [");
|
||||||
|
for (i = 0; i < pk->bytecount; i++)
|
||||||
|
gwinPrintf(ghConsole, "%c", pk->c[i] >= ' ' && pk->c[i] <= '~' ? pk->c[i] : ' ');
|
||||||
|
gwinPrintf(ghConsole, "]");
|
||||||
|
}
|
||||||
|
gwinPrintf(ghConsole, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -49,6 +49,7 @@
|
||||||
/* Our custom yellow style */
|
/* Our custom yellow style */
|
||||||
static const GWidgetStyle YellowWidgetStyle = {
|
static const GWidgetStyle YellowWidgetStyle = {
|
||||||
Yellow, // window background
|
Yellow, // window background
|
||||||
|
HTML2COLOR(0x800000), // focus
|
||||||
|
|
||||||
// enabled color set
|
// enabled color set
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,6 +13,10 @@ FEATURE: Renaming GFX_NO_OS_INIT to GFX_OS_NO_INIT
|
||||||
FEATURE: New demo applications/combo
|
FEATURE: New demo applications/combo
|
||||||
FEATURE: Adding more font metrics (BaselineX and BaselineY)
|
FEATURE: Adding more font metrics (BaselineX and BaselineY)
|
||||||
FEATURE: Adding gdispGetStringWidthCount()
|
FEATURE: Adding gdispGetStringWidthCount()
|
||||||
|
FEATURE: Implementing widget focusing. See gwinSetFocus() and gwinGetFocus()
|
||||||
|
FEATURE: Adding TextEdit widget
|
||||||
|
FEATURE: Added color to widget style for focused widgets
|
||||||
|
FEATURE: Added GWIN_FOCUS_HIGHLIGHT_WIDTH as an option in the configuration file
|
||||||
|
|
||||||
*** Release 2.3 ***
|
*** Release 2.3 ***
|
||||||
FEATURE: Added more events to the slider widget
|
FEATURE: Added more events to the slider widget
|
||||||
|
|
|
@ -167,6 +167,7 @@
|
||||||
//#define GWIN_NEED_GL3D FALSE
|
//#define GWIN_NEED_GL3D FALSE
|
||||||
|
|
||||||
//#define GWIN_NEED_WIDGET FALSE
|
//#define GWIN_NEED_WIDGET FALSE
|
||||||
|
//#define GWIN_FOCUS_HIGHLIGHT_WIDTH 1
|
||||||
// #define GWIN_NEED_LABEL FALSE
|
// #define GWIN_NEED_LABEL FALSE
|
||||||
// #define GWIN_LABEL_ATTRIBUTE FALSE
|
// #define GWIN_LABEL_ATTRIBUTE FALSE
|
||||||
// #define GWIN_NEED_BUTTON FALSE
|
// #define GWIN_NEED_BUTTON FALSE
|
||||||
|
@ -186,6 +187,7 @@
|
||||||
// #define GWIN_NEED_KEYBOARD FALSE
|
// #define GWIN_NEED_KEYBOARD FALSE
|
||||||
// #define GWIN_KEYBOARD_DEFAULT_LAYOUT VirtualKeyboard_English1
|
// #define GWIN_KEYBOARD_DEFAULT_LAYOUT VirtualKeyboard_English1
|
||||||
// #define GWIN_NEED_KEYBOARD_ENGLISH1 TRUE
|
// #define GWIN_NEED_KEYBOARD_ENGLISH1 TRUE
|
||||||
|
// #define GWIN_NEED_TEXTEDIT FALSE
|
||||||
// #define GWIN_FLAT_STYLING FALSE
|
// #define GWIN_FLAT_STYLING FALSE
|
||||||
// #define GWIN_WIDGET_TAGS FALSE
|
// #define GWIN_WIDGET_TAGS FALSE
|
||||||
|
|
||||||
|
|
|
@ -164,13 +164,11 @@ typedef struct GEventKeyboard_t {
|
||||||
#define GLISTEN_KEYTRANSITIONS 0x0008 // Return transitions to the key state
|
#define GLISTEN_KEYTRANSITIONS 0x0008 // Return transitions to the key state
|
||||||
#define GLISTEN_KEYRAW 0x0010 // Return raw scan-codes. This turns off normal character processing.
|
#define GLISTEN_KEYRAW 0x0010 // Return raw scan-codes. This turns off normal character processing.
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if GINPUT_NEED_KEYBOARD || defined(__DOXYGEN__)
|
|
||||||
|
|
||||||
// All keyboards
|
// All keyboards
|
||||||
#define GKEYBOARD_ALL_INSTANCES ((unsigned)-1)
|
#define GKEYBOARD_ALL_INSTANCES ((unsigned)-1)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
/* External declarations. */
|
/* External declarations. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
@ -188,33 +186,34 @@ extern "C" {
|
||||||
*/
|
*/
|
||||||
GSourceHandle ginputGetKeyboard(unsigned instance);
|
GSourceHandle ginputGetKeyboard(unsigned instance);
|
||||||
|
|
||||||
/**
|
#if GINPUT_NEED_KEYBOARD || defined(__DOXYGEN__)
|
||||||
* @brief Get the current keyboard status
|
|
||||||
*
|
|
||||||
* @param[in] instance The ID of the keyboard input instance
|
|
||||||
* @param[in] pkeyboard The keyboard event struct
|
|
||||||
*
|
|
||||||
* @return Returns FALSE on an error (eg invalid instance)
|
|
||||||
*/
|
|
||||||
bool_t ginputGetKeyboardStatus(unsigned instance, GEventKeyboard *pkeyboard);
|
|
||||||
|
|
||||||
#if !GKEYBOARD_LAYOUT_OFF || defined(__DOXYGEN__)
|
|
||||||
/**
|
/**
|
||||||
* @brief Set the keyboard layout
|
* @brief Get the current keyboard status
|
||||||
*
|
*
|
||||||
* @param[in] instance The ID of the keyboard input instance
|
* @param[in] instance The ID of the keyboard input instance
|
||||||
* @param[in] pLayout The keyboard layout micro-code. Passing NULL defaults to the driver's default layout.
|
* @param[in] pkeyboard The keyboard event struct
|
||||||
*
|
*
|
||||||
* @return Returns FALSE on an error (eg invalid instance)
|
* @return Returns FALSE on an error (eg invalid instance)
|
||||||
*/
|
*/
|
||||||
bool_t ginputSetKeyboardLayout(unsigned instance, const void *pLayout);
|
bool_t ginputGetKeyboardStatus(unsigned instance, GEventKeyboard *pkeyboard);
|
||||||
#endif
|
|
||||||
|
#if !GKEYBOARD_LAYOUT_OFF || defined(__DOXYGEN__)
|
||||||
|
/**
|
||||||
|
* @brief Set the keyboard layout
|
||||||
|
*
|
||||||
|
* @param[in] instance The ID of the keyboard input instance
|
||||||
|
* @param[in] pLayout The keyboard layout micro-code. Passing NULL defaults to the driver's default layout.
|
||||||
|
*
|
||||||
|
* @return Returns FALSE on an error (eg invalid instance)
|
||||||
|
*/
|
||||||
|
bool_t ginputSetKeyboardLayout(unsigned instance, const void *pLayout);
|
||||||
|
#endif
|
||||||
|
#endif /* GINPUT_NEED_KEYBOARD */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* GINPUT_NEED_KEYBOARD */
|
|
||||||
|
|
||||||
#endif /* _GINPUT_KEYBOARD_H */
|
#endif /* _GINPUT_KEYBOARD_H */
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
|
@ -21,6 +21,7 @@ GFXSRC += $(GFXLIB)/src/gwin/gwin.c \
|
||||||
$(GFXLIB)/src/gwin/gwin_tabset.c \
|
$(GFXLIB)/src/gwin/gwin_tabset.c \
|
||||||
$(GFXLIB)/src/gwin/gwin_gl3d.c \
|
$(GFXLIB)/src/gwin/gwin_gl3d.c \
|
||||||
$(GFXLIB)/src/gwin/gwin_keyboard.c \
|
$(GFXLIB)/src/gwin/gwin_keyboard.c \
|
||||||
$(GFXLIB)/src/gwin/gwin_keyboard_layout.c
|
$(GFXLIB)/src/gwin/gwin_keyboard_layout.c \
|
||||||
|
$(GFXLIB)/src/gwin/gwin_textedit.c
|
||||||
|
|
||||||
GFXINC += $(GFXLIB)/3rdparty/tinygl-0.4-ugfx/include
|
GFXINC += $(GFXLIB)/3rdparty/tinygl-0.4-ugfx/include
|
||||||
|
|
|
@ -50,6 +50,24 @@
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if GINPUT_NEED_KEYBOARD || GWIN_NEED_KEYBOARD
|
||||||
|
static void ButtonKeyboard(GWidgetObject* gw, GEventKeyboard* pke)
|
||||||
|
{
|
||||||
|
// ENTER and SPACE keys to press the button
|
||||||
|
if (pke->c[0] == GKEY_ENTER || pke->c[0] == GKEY_SPACE) {
|
||||||
|
|
||||||
|
// Press or release event?
|
||||||
|
if (pke->keystate & GKEYSTATE_KEYUP) {
|
||||||
|
gw->g.flags &= ~GBUTTON_FLG_PRESSED;
|
||||||
|
} else {
|
||||||
|
gw->g.flags |= GBUTTON_FLG_PRESSED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_gwinUpdate((GHandle)gw);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if GINPUT_NEED_TOGGLE
|
#if GINPUT_NEED_TOGGLE
|
||||||
// A toggle off has occurred
|
// A toggle off has occurred
|
||||||
static void ButtonToggleOff(GWidgetObject *gw, uint16_t role) {
|
static void ButtonToggleOff(GWidgetObject *gw, uint16_t role) {
|
||||||
|
@ -95,6 +113,11 @@ static const gwidgetVMT buttonVMT = {
|
||||||
0, // Process mouse move events (NOT USED)
|
0, // Process mouse move events (NOT USED)
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
|
#if GINPUT_NEED_KEYBOARD || GWIN_NEED_KEYBOARD
|
||||||
|
{
|
||||||
|
ButtonKeyboard // Process keyboard events
|
||||||
|
},
|
||||||
|
#endif
|
||||||
#if GINPUT_NEED_TOGGLE
|
#if GINPUT_NEED_TOGGLE
|
||||||
{
|
{
|
||||||
1, // 1 toggle role
|
1, // 1 toggle role
|
||||||
|
|
|
@ -55,6 +55,23 @@ static void SendCheckboxEvent(GWidgetObject *gw) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if GINPUT_NEED_KEYBOARD || GWIN_NEED_KEYBOARD
|
||||||
|
static void CheckboxKeyboard(GWidgetObject* gw, GEventKeyboard* pke)
|
||||||
|
{
|
||||||
|
// Only react on KEYDOWN events. Ignore KEYUP events.
|
||||||
|
if (pke->keystate & GKEYSTATE_KEYUP) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ENTER and SPACE keys to check/uncheck the checkbox
|
||||||
|
if (pke->c[0] == GKEY_ENTER || pke->c[0] == GKEY_SPACE) {
|
||||||
|
gw->g.flags ^= GCHECKBOX_FLG_CHECKED;
|
||||||
|
}
|
||||||
|
|
||||||
|
_gwinUpdate((GHandle)gw);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if GINPUT_NEED_TOGGLE
|
#if GINPUT_NEED_TOGGLE
|
||||||
static void CheckboxToggleOn(GWidgetObject *gw, uint16_t role) {
|
static void CheckboxToggleOn(GWidgetObject *gw, uint16_t role) {
|
||||||
(void) role;
|
(void) role;
|
||||||
|
@ -91,6 +108,11 @@ static const gwidgetVMT checkboxVMT = {
|
||||||
0, // Process mouse move events (NOT USED)
|
0, // Process mouse move events (NOT USED)
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
|
#if GINPUT_NEED_KEYBOARD || GWIN_NEED_KEYBOARD
|
||||||
|
{
|
||||||
|
CheckboxKeyboard // Process keyboard events
|
||||||
|
},
|
||||||
|
#endif
|
||||||
#if GINPUT_NEED_TOGGLE
|
#if GINPUT_NEED_TOGGLE
|
||||||
{
|
{
|
||||||
1, // 1 toggle role
|
1, // 1 toggle role
|
||||||
|
|
|
@ -31,25 +31,25 @@
|
||||||
* @brief The predefined flags for a Window
|
* @brief The predefined flags for a Window
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
#define GWIN_FIRST_CONTROL_FLAG 0x00000001 // @< 8 bits free for the control to use
|
#define GWIN_FIRST_CONTROL_FLAG 0x00000001 /**< 8 bits free for the control to use */
|
||||||
#define GWIN_LAST_CONTROL_FLAG 0x00000080 // @< 8 bits free for the control to use
|
#define GWIN_LAST_CONTROL_FLAG 0x00000080 /**< 8 bits free for the control to use */
|
||||||
#define GWIN_FLG_VISIBLE 0x00000100 // @< The window is "visible"
|
#define GWIN_FLG_VISIBLE 0x00000100 /**< The window is "visible" */
|
||||||
#define GWIN_FLG_SYSVISIBLE 0x00000200 // @< The window is visible after parents are tested
|
#define GWIN_FLG_SYSVISIBLE 0x00000200 /**< The window is visible after parents are tested */
|
||||||
#define GWIN_FLG_ENABLED 0x00000400 // @< The window is "enabled"
|
#define GWIN_FLG_ENABLED 0x00000400 /**< The window is "enabled" */
|
||||||
#define GWIN_FLG_SYSENABLED 0x00000800 // @< The window is enabled after parents are tested
|
#define GWIN_FLG_SYSENABLED 0x00000800 /**< The window is enabled after parents are tested */
|
||||||
#define GWIN_FLG_DYNAMIC 0x00001000 // @< The GWIN structure is allocated
|
#define GWIN_FLG_DYNAMIC 0x00001000 /**< The GWIN structure is allocated */
|
||||||
#define GWIN_FLG_ALLOCTXT 0x00002000 // @< The text/label is allocated
|
#define GWIN_FLG_ALLOCTXT 0x00002000 /**< The text/label is allocated */
|
||||||
#define GWIN_FLG_NEEDREDRAW 0x00004000 // @< Redraw is needed but has been delayed
|
#define GWIN_FLG_NEEDREDRAW 0x00004000 /**< Redraw is needed but has been delayed */
|
||||||
#define GWIN_FLG_BGREDRAW 0x00008000 // @< On redraw, if not visible redraw the revealed under-side
|
#define GWIN_FLG_BGREDRAW 0x00008000 /**< On redraw, if not visible redraw the revealed under-side */
|
||||||
#define GWIN_FLG_SUPERMASK 0x000F0000 // @< The bit mask to leave just the window superclass type
|
#define GWIN_FLG_SUPERMASK 0x000F0000 /**< The bit mask to leave just the window superclass type */
|
||||||
#define GWIN_FLG_WIDGET 0x00010000 // @< This is a widget
|
#define GWIN_FLG_WIDGET 0x00010000 /**< This is a widget */
|
||||||
#define GWIN_FLG_CONTAINER 0x00020000 // @< This is a container
|
#define GWIN_FLG_CONTAINER 0x00020000 /**< This is a container */
|
||||||
#define GWIN_FLG_MINIMIZED 0x00100000 // @< The window is minimized
|
#define GWIN_FLG_MINIMIZED 0x00100000 /**< The window is minimized */
|
||||||
#define GWIN_FLG_MAXIMIZED 0x00200000 // @< The window is maximized
|
#define GWIN_FLG_MAXIMIZED 0x00200000 /**< The window is maximized */
|
||||||
#define GWIN_FLG_MOUSECAPTURE 0x00400000 // @< The window has captured the mouse
|
#define GWIN_FLG_MOUSECAPTURE 0x00400000 /**< The window has captured the mouse */
|
||||||
#define GWIN_FLG_FLASHING 0x00800000 // @< The window is flashing - see the _gwinFlashState boolean
|
#define GWIN_FLG_FLASHING 0x00800000 /**< The window is flashing - see the _gwinFlashState boolean */
|
||||||
#define GWIN_FIRST_WM_FLAG 0x01000000 // @< 8 bits free for the window manager to use
|
#define GWIN_FIRST_WM_FLAG 0x01000000 /**< 8 bits free for the window manager to use */
|
||||||
#define GWIN_LAST_WM_FLAG 0x80000000 // @< 8 bits free for the window manager to use
|
#define GWIN_LAST_WM_FLAG 0x80000000 /**< 8 bits free for the window manager to use */
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -57,11 +57,11 @@
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
typedef struct gwinVMT {
|
typedef struct gwinVMT {
|
||||||
const char * classname; // @< The GWIN classname (mandatory)
|
const char * classname; /**< The GWIN classname (mandatory) */
|
||||||
size_t size; // @< The size of the class object
|
size_t size; /**< The size of the class object */
|
||||||
void (*Destroy) (GWindowObject *gh); // @< The GWIN destroy function (optional)
|
void (*Destroy) (GWindowObject *gh); /**< The GWIN destroy function (optional) */
|
||||||
void (*Redraw) (GWindowObject *gh); // @< The GWIN redraw routine (optional)
|
void (*Redraw) (GWindowObject *gh); /**< The GWIN redraw routine (optional) */
|
||||||
void (*AfterClear) (GWindowObject *gh); // @< The GWIN after-clear function (optional)
|
void (*AfterClear) (GWindowObject *gh); /**< The GWIN after-clear function (optional) */
|
||||||
} gwinVMT;
|
} gwinVMT;
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
@ -87,30 +87,35 @@ typedef struct gwinVMT {
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
typedef struct gwidgetVMT {
|
typedef struct gwidgetVMT {
|
||||||
struct gwinVMT g; // @< This is still a GWIN
|
struct gwinVMT g; /**< This is still a GWIN */
|
||||||
void (*DefaultDraw) (GWidgetObject *gw, void *param); // @< The default drawing routine (mandatory)
|
void (*DefaultDraw) (GWidgetObject *gw, void *param); /**< The default drawing routine (mandatory) */
|
||||||
#if GINPUT_NEED_MOUSE
|
#if GINPUT_NEED_MOUSE
|
||||||
struct {
|
struct {
|
||||||
void (*MouseDown) (GWidgetObject *gw, coord_t x, coord_t y); // @< Process mouse down events (optional)
|
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 (*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)
|
void (*MouseMove) (GWidgetObject *gw, coord_t x, coord_t y); /**< Process mouse move events (optional) */
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
#if GINPUT_NEED_KEYBOARD || GWIN_NEED_KEYBOARD
|
||||||
|
struct {
|
||||||
|
void (*KeyboardEvent) (GWidgetObject *gw, GEventKeyboard *pke); /**< Process keyboard events (optional) */
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
#if GINPUT_NEED_TOGGLE
|
#if GINPUT_NEED_TOGGLE
|
||||||
struct {
|
struct {
|
||||||
uint16_t toggleroles; // @< The roles supported for toggles (0->toggleroles-1)
|
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)
|
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)
|
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 (*ToggleOff) (GWidgetObject *gw, uint16_t role); /**< Process toggle off events (optional) */
|
||||||
void (*ToggleOn) (GWidgetObject *gw, uint16_t role); // @< Process toggle on events (optional)
|
void (*ToggleOn) (GWidgetObject *gw, uint16_t role); /**< Process toggle on events (optional) */
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
#if GINPUT_NEED_DIAL
|
#if GINPUT_NEED_DIAL
|
||||||
struct {
|
struct {
|
||||||
uint16_t dialroles; // @< The roles supported for dials (0->dialroles-1)
|
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)
|
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)
|
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)
|
void (*DialMove) (GWidgetObject *gw, uint16_t role, uint16_t value, uint16_t max); /**< Process dial move events (optional) */
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
} gwidgetVMT;
|
} gwidgetVMT;
|
||||||
|
@ -130,12 +135,12 @@ typedef struct gwinVMT {
|
||||||
*/
|
*/
|
||||||
typedef struct gcontainerVMT {
|
typedef struct gcontainerVMT {
|
||||||
gwidgetVMT gw;
|
gwidgetVMT gw;
|
||||||
coord_t (*LeftBorder) (GHandle gh); // @< The size of the left border (mandatory)
|
coord_t (*LeftBorder) (GHandle gh); /**< The size of the left border (mandatory) */
|
||||||
coord_t (*TopBorder) (GHandle gh); // @< The size of the top border (mandatory)
|
coord_t (*TopBorder) (GHandle gh); /**< The size of the top border (mandatory) */
|
||||||
coord_t (*RightBorder) (GHandle gh); // @< The size of the right border (mandatory)
|
coord_t (*RightBorder) (GHandle gh); /**< The size of the right border (mandatory) */
|
||||||
coord_t (*BottomBorder) (GHandle gh); // @< The size of the bottom border (mandatory)
|
coord_t (*BottomBorder) (GHandle gh); /**< The size of the bottom border (mandatory) */
|
||||||
void (*NotifyAdd) (GHandle gh, GHandle ghChild); // @< Notification that a child has been added (optional)
|
void (*NotifyAdd) (GHandle gh, GHandle ghChild); /**< Notification that a child has been added (optional) */
|
||||||
void (*NotifyDelete) (GHandle gh, GHandle ghChild); // @< Notification that a child has been deleted (optional)
|
void (*NotifyDelete) (GHandle gh, GHandle ghChild); /**< Notification that a child has been deleted (optional) */
|
||||||
} gcontainerVMT;
|
} gcontainerVMT;
|
||||||
/** @} */
|
/** @} */
|
||||||
#endif
|
#endif
|
||||||
|
@ -151,22 +156,22 @@ typedef struct gwinVMT {
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
typedef struct gwmVMT {
|
typedef struct gwmVMT {
|
||||||
void (*Init) (void); // @< The window manager has just been set as the current window manager
|
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
|
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
|
bool_t (*Add) (GHandle gh, const GWindowInit *pInit); /**< A window has been added */
|
||||||
void (*Delete) (GHandle gh); // @< A window has been deleted
|
void (*Delete) (GHandle gh); /**< A window has been deleted */
|
||||||
void (*Redraw) (GHandle gh); // @< A window needs to be redraw (or undrawn)
|
void (*Redraw) (GHandle gh); /**< A window needs to be redraw (or undrawn) */
|
||||||
void (*Size) (GHandle gh, coord_t w, coord_t h); // @< A window wants to be resized
|
void (*Size) (GHandle gh, coord_t w, coord_t h); /**< A window wants to be resized */
|
||||||
void (*Move) (GHandle gh, coord_t x, coord_t y); // @< A window wants to be moved
|
void (*Move) (GHandle gh, coord_t x, coord_t y); /**< A window wants to be moved */
|
||||||
void (*Raise) (GHandle gh); // @< A window wants to be on top
|
void (*Raise) (GHandle gh); /**< A window wants to be on top */
|
||||||
void (*MinMax) (GHandle gh, GWindowMinMax minmax); // @< A window wants to be minimized/maximised
|
void (*MinMax) (GHandle gh, GWindowMinMax minmax); /**< A window wants to be minimized/maximised */
|
||||||
} gwmVMT;
|
} gwmVMT;
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The current window manager
|
* @brief The current window manager
|
||||||
*/
|
*/
|
||||||
extern GWindowManager * _GWINwm;
|
extern GWindowManager *_GWINwm;
|
||||||
extern bool_t _gwinFlashState;
|
extern bool_t _gwinFlashState;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -251,9 +256,8 @@ void _gwinDrawEnd(GHandle gh);
|
||||||
* @param[in] gh The window
|
* @param[in] gh The window
|
||||||
* @param[in] how Do we wait for the lock?
|
* @param[in] how Do we wait for the lock?
|
||||||
*
|
*
|
||||||
* @note This call will delete the window. If called without the
|
* @note If called without the drawing lock 'how' must be REDRAW_WAIT.
|
||||||
* drawing lock 'how' must be REDRAW_WAIT. If called with the drawing
|
* If called with the drawing lock 'how' must be REDRAW_INSESSION.
|
||||||
* lock 'how' must be REDRAW_INSESSION.
|
|
||||||
*
|
*
|
||||||
* @notapi
|
* @notapi
|
||||||
*/
|
*/
|
||||||
|
@ -317,6 +321,52 @@ bool_t _gwinWMAdd(GHandle gh, const GWindowInit *pInit);
|
||||||
*/
|
*/
|
||||||
void _gwinSendEvent(GHandle gh, GEventType type);
|
void _gwinSendEvent(GHandle gh, GEventType type);
|
||||||
|
|
||||||
|
#if (GFX_USE_GINPUT && GINPUT_NEED_KEYBOARD) || defined(__DOXYGEN__)
|
||||||
|
/**
|
||||||
|
* @brief Move the focus off the current focus window.
|
||||||
|
*
|
||||||
|
* @note The focus can stay on the same window if there is no other focusable window
|
||||||
|
*
|
||||||
|
* @notapi
|
||||||
|
*/
|
||||||
|
void _gwinMoveFocus(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Do focus fixup's after a change of state for a window.
|
||||||
|
* @details If a focus window has become invisible or disabled then
|
||||||
|
* the focus must be taken away from it. If there is no focus
|
||||||
|
* window and this window is eligible then this window becomes
|
||||||
|
* the focus.
|
||||||
|
*
|
||||||
|
* @param[in] gh The window
|
||||||
|
*
|
||||||
|
* @note This routine does not actually do a redraw. It assumes that surrounding code
|
||||||
|
* will because of the change of state that lead to this being called.
|
||||||
|
*
|
||||||
|
* @notapi
|
||||||
|
*/
|
||||||
|
void _gwinFixFocus(GHandle gh);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Draw a simple focus rectangle in the default style.
|
||||||
|
*
|
||||||
|
* @param[in] gw The widget
|
||||||
|
* @param[in] x, y The start x, y position (relative to the window)
|
||||||
|
* @param[in] cx, cy The width & height of the rectangle
|
||||||
|
*
|
||||||
|
* @note Assumes the widget is in a state where it can draw.
|
||||||
|
* @note Nothing is drawn if the window doesn't have focus.
|
||||||
|
* @note The focus rectangle may be more than one pixel thick and may
|
||||||
|
* not be a continuous line.
|
||||||
|
*
|
||||||
|
* @notapi
|
||||||
|
*/
|
||||||
|
void _gwidgetDrawFocusRect(GWidgetObject *gw, coord_t x, coord_t y, coord_t cx, coord_t cy);
|
||||||
|
|
||||||
|
#else
|
||||||
|
#define _gwinFixFocus(gh)
|
||||||
|
#define _gwidgetDrawFocusRect(gh,x,y,cx,cy)
|
||||||
|
#endif
|
||||||
|
|
||||||
#if GWIN_NEED_FLASHING || defined(__DOXYGEN__)
|
#if GWIN_NEED_FLASHING || defined(__DOXYGEN__)
|
||||||
/**
|
/**
|
||||||
|
@ -330,6 +380,8 @@ bool_t _gwinWMAdd(GHandle gh, const GWindowInit *pInit);
|
||||||
*/
|
*/
|
||||||
const GColorSet *_gwinGetFlashedColor(GWidgetObject *gw, const GColorSet *pcol, bool_t flashOffState);
|
const GColorSet *_gwinGetFlashedColor(GWidgetObject *gw, const GColorSet *pcol, bool_t flashOffState);
|
||||||
#endif
|
#endif
|
||||||
|
#else
|
||||||
|
#define _gwinFixFocus(gh)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if GWIN_NEED_CONTAINERS || defined(__DOXYGEN__)
|
#if GWIN_NEED_CONTAINERS || defined(__DOXYGEN__)
|
||||||
|
|
|
@ -110,6 +110,11 @@ static const gcontainerVMT containerVMT = {
|
||||||
0, 0, 0, // No mouse
|
0, 0, 0, // No mouse
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
|
#if GINPUT_NEED_KEYBOARD || GWIN_NEED_KEYBOARD
|
||||||
|
{
|
||||||
|
0 // Process keyboard events
|
||||||
|
},
|
||||||
|
#endif
|
||||||
#if GINPUT_NEED_TOGGLE
|
#if GINPUT_NEED_TOGGLE
|
||||||
{
|
{
|
||||||
0, 0, 0, 0, 0, // No toggles
|
0, 0, 0, 0, 0, // No toggles
|
||||||
|
|
|
@ -178,6 +178,11 @@ static const gcontainerVMT frameVMT = {
|
||||||
0, // Process mouse move events
|
0, // Process mouse move events
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
|
#if GINPUT_NEED_KEYBOARD || GWIN_NEED_KEYBOARD
|
||||||
|
{
|
||||||
|
0 // Process keyboard events
|
||||||
|
},
|
||||||
|
#endif
|
||||||
#if GINPUT_NEED_TOGGLE
|
#if GINPUT_NEED_TOGGLE
|
||||||
{
|
{
|
||||||
0, // 1 toggle role
|
0, // 1 toggle role
|
||||||
|
|
|
@ -30,6 +30,8 @@ typedef uint32_t utf32;
|
||||||
// A character code - note this is not UTF-32 but a representation of the UTF-8 code stream for a single character.
|
// A character code - note this is not UTF-32 but a representation of the UTF-8 code stream for a single character.
|
||||||
typedef uint32_t ucode;
|
typedef uint32_t ucode;
|
||||||
|
|
||||||
|
static GSourceHandle AllKeyboards;
|
||||||
|
|
||||||
// Get the length of a UTF-8 string
|
// Get the length of a UTF-8 string
|
||||||
static int UTF8StrLen(const utf8 *s) {
|
static int UTF8StrLen(const utf8 *s) {
|
||||||
int len;
|
int len;
|
||||||
|
@ -164,6 +166,11 @@ static void SendKeyboardEventToListener(GSourceListener *psl, GKeyboardObject *g
|
||||||
static void SendKeyboardEvent(GKeyboardObject *gk) {
|
static void SendKeyboardEvent(GKeyboardObject *gk) {
|
||||||
GSourceListener *psl;
|
GSourceListener *psl;
|
||||||
|
|
||||||
|
// Send to the "All Keyboards" source listeners
|
||||||
|
psl = 0;
|
||||||
|
while ((psl = geventGetSourceListener(AllKeyboards, psl)))
|
||||||
|
SendKeyboardEventToListener(psl, gk);
|
||||||
|
|
||||||
// Send to the keyboard specific source listeners
|
// Send to the keyboard specific source listeners
|
||||||
psl = 0;
|
psl = 0;
|
||||||
while ((psl = geventGetSourceListener((GSourceHandle)gk, psl)))
|
while ((psl = geventGetSourceListener((GSourceHandle)gk, psl)))
|
||||||
|
@ -313,6 +320,11 @@ static const gwidgetVMT keyboardVMT = {
|
||||||
KeyMouseMove, // Process mouse move events
|
KeyMouseMove, // Process mouse move events
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
|
#if GINPUT_NEED_KEYBOARD || GWIN_NEED_KEYBOARD
|
||||||
|
{
|
||||||
|
0 // Process keyboard events
|
||||||
|
},
|
||||||
|
#endif
|
||||||
#if GINPUT_NEED_TOGGLE
|
#if GINPUT_NEED_TOGGLE
|
||||||
{
|
{
|
||||||
0, // No toggle roles
|
0, // No toggle roles
|
||||||
|
@ -339,6 +351,10 @@ GHandle gwinGKeyboardCreate(GDisplay *g, GKeyboardObject *gk, const GWidgetInit
|
||||||
gk->keytable = &GWIN_KEYBOARD_DEFAULT_LAYOUT;
|
gk->keytable = &GWIN_KEYBOARD_DEFAULT_LAYOUT;
|
||||||
gk->keyset = gk->keytable->ksets[0];
|
gk->keyset = gk->keytable->ksets[0];
|
||||||
gk->lastkeyrow = gk->lastkeycol = gk->keyrow = gk->keycol = GKEY_BAD_ROWCOL;
|
gk->lastkeyrow = gk->lastkeycol = gk->keyrow = gk->keycol = GKEY_BAD_ROWCOL;
|
||||||
|
|
||||||
|
if (!AllKeyboards)
|
||||||
|
AllKeyboards = ginputGetKeyboard(GKEYBOARD_ALL_INSTANCES);
|
||||||
|
|
||||||
gwinSetVisible((GHandle)gk, pInit->g.show);
|
gwinSetVisible((GHandle)gk, pInit->g.show);
|
||||||
return (GHandle)gk;
|
return (GHandle)gk;
|
||||||
}
|
}
|
||||||
|
@ -468,4 +484,12 @@ void gwinKeyboardDraw_Normal(GWidgetObject *gw, void *param) {
|
||||||
#undef gk
|
#undef gk
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !(GFX_USE_GINPUT && GINPUT_NEED_KEYBOARD)
|
||||||
|
GSourceHandle ginputGetKeyboard(unsigned instance) {
|
||||||
|
if (instance == GKEYBOARD_ALL_INSTANCES)
|
||||||
|
return (GSourceHandle)&AllKeyboards;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* GFX_USE_GWIN && GWIN_NEED_KEYBOARD */
|
#endif /* GFX_USE_GWIN && GWIN_NEED_KEYBOARD */
|
||||||
|
|
|
@ -58,6 +58,11 @@ static const gwidgetVMT labelVMT = {
|
||||||
0, // Process mouse move events (NOT USED)
|
0, // Process mouse move events (NOT USED)
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
|
#if GINPUT_NEED_KEYBOARD || GWIN_NEED_KEYBOARD
|
||||||
|
{
|
||||||
|
0 // Process keyboard key down events
|
||||||
|
},
|
||||||
|
#endif
|
||||||
#if GINPUT_NEED_TOGGLE
|
#if GINPUT_NEED_TOGGLE
|
||||||
{
|
{
|
||||||
0, // No toggle role
|
0, // No toggle role
|
||||||
|
|
|
@ -279,6 +279,11 @@ static const gwidgetVMT listVMT = {
|
||||||
ListMouseMove,
|
ListMouseMove,
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
|
#if GINPUT_NEED_KEYBOARD || GWIN_NEED_KEYBOARD
|
||||||
|
{
|
||||||
|
0 // Process keyboard events
|
||||||
|
},
|
||||||
|
#endif
|
||||||
#if GINPUT_NEED_TOGGLE
|
#if GINPUT_NEED_TOGGLE
|
||||||
{
|
{
|
||||||
2, // two toggle roles
|
2, // two toggle roles
|
||||||
|
|
|
@ -24,3 +24,4 @@
|
||||||
#include "gwin_gl3d.c"
|
#include "gwin_gl3d.c"
|
||||||
#include "gwin_keyboard.c"
|
#include "gwin_keyboard.c"
|
||||||
#include "gwin_keyboard_layout.c"
|
#include "gwin_keyboard_layout.c"
|
||||||
|
#include "gwin_textedit.c"
|
||||||
|
|
|
@ -44,6 +44,13 @@
|
||||||
#ifndef GWIN_NEED_WIDGET
|
#ifndef GWIN_NEED_WIDGET
|
||||||
#define GWIN_NEED_WIDGET FALSE
|
#define GWIN_NEED_WIDGET FALSE
|
||||||
#endif
|
#endif
|
||||||
|
/**
|
||||||
|
* @brief The width of the rectangle that highlights a widget that is focused
|
||||||
|
* @details Defaults to 1
|
||||||
|
*/
|
||||||
|
#ifndef GWIN_FOCUS_HIGHLIGHT_WIDTH
|
||||||
|
#define GWIN_FOCUS_HIGHLIGHT_WIDTH 1
|
||||||
|
#endif
|
||||||
/**
|
/**
|
||||||
* @brief Should the simple container be included.
|
* @brief Should the simple container be included.
|
||||||
* @details Defaults to FALSE
|
* @details Defaults to FALSE
|
||||||
|
@ -142,6 +149,13 @@
|
||||||
#ifndef GWIN_NEED_KEYBOARD
|
#ifndef GWIN_NEED_KEYBOARD
|
||||||
#define GWIN_NEED_KEYBOARD FALSE
|
#define GWIN_NEED_KEYBOARD FALSE
|
||||||
#endif
|
#endif
|
||||||
|
/**
|
||||||
|
* @brief Should the textedit widget be included.
|
||||||
|
* @details Defaults to FALSE
|
||||||
|
*/
|
||||||
|
#ifndef GWIN_NEED_TEXTEDIT
|
||||||
|
#define GWIN_NEED_TEXTEDIT FALSE
|
||||||
|
#endif
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*
|
*
|
||||||
|
|
|
@ -51,6 +51,11 @@ static const gwidgetVMT progressbarVMT = {
|
||||||
0, // Process mouse move events
|
0, // Process mouse move events
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
|
#if GINPUT_NEED_KEYBOARD || GWIN_NEED_KEYBOARD
|
||||||
|
{
|
||||||
|
0 // Process keyboard events
|
||||||
|
},
|
||||||
|
#endif
|
||||||
#if GINPUT_NEED_TOGGLE
|
#if GINPUT_NEED_TOGGLE
|
||||||
{
|
{
|
||||||
0, // 1 toggle role
|
0, // 1 toggle role
|
||||||
|
|
|
@ -92,6 +92,11 @@ static const gwidgetVMT radioVMT = {
|
||||||
0, // Process mouse move events (NOT USED)
|
0, // Process mouse move events (NOT USED)
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
|
#if GINPUT_NEED_KEYBOARD || GWIN_NEED_KEYBOARD
|
||||||
|
{
|
||||||
|
0 // Process keyboard events
|
||||||
|
},
|
||||||
|
#endif
|
||||||
#if GINPUT_NEED_TOGGLE
|
#if GINPUT_NEED_TOGGLE
|
||||||
{
|
{
|
||||||
1, // 1 toggle role
|
1, // 1 toggle role
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#if GWIN_NEED_BUTTON || GWIN_NEED_SLIDER || GWIN_NEED_CHECKBOX || GWIN_NEED_LABEL || GWIN_NEED_RADIO || GWIN_NEED_LIST || \
|
#if GWIN_NEED_BUTTON || GWIN_NEED_SLIDER || GWIN_NEED_CHECKBOX || GWIN_NEED_LABEL || GWIN_NEED_RADIO || GWIN_NEED_LIST || \
|
||||||
GWIN_NEED_IMAGE || GWIN_NEED_CHECKBOX || GWIN_NEED_PROGRESSBAR || GWIN_NEED_KEYBOARD
|
GWIN_NEED_IMAGE || GWIN_NEED_CHECKBOX || GWIN_NEED_PROGRESSBAR || GWIN_NEED_KEYBOARD || GWIN_NEED_TEXTEDIT
|
||||||
#if !GWIN_NEED_WIDGET
|
#if !GWIN_NEED_WIDGET
|
||||||
#if GFX_DISPLAY_RULE_WARNINGS
|
#if GFX_DISPLAY_RULE_WARNINGS
|
||||||
#warning "GWIN: GWIN_NEED_WIDGET is required when a widget is used. It has been turned on for you."
|
#warning "GWIN: GWIN_NEED_WIDGET is required when a widget is used. It has been turned on for you."
|
||||||
|
@ -123,6 +123,14 @@
|
||||||
#error "GWIN: GDISP_NEED_TEXT is required if GWIN_NEED_CONSOLE is TRUE."
|
#error "GWIN: GDISP_NEED_TEXT is required if GWIN_NEED_CONSOLE is TRUE."
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
#if GWIN_NEED_TEXTEDIT
|
||||||
|
#if !GDISP_NEED_TEXT
|
||||||
|
#error "GWIN: GDISP_NEED_TEXT is required if GWIN_NEED_TEXTEDIT is TRUE."
|
||||||
|
#endif
|
||||||
|
#if !(GINPUT_NEED_KEYBOARD || GWIN_NEED_KEYBOARD)
|
||||||
|
#error "GWIN: GINPUT_NEED_KEYBOARD or GWIN_NEED_KEYBOARD is required if GWIN_NEED_TEXTEDIT is TRUE."
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* _GWIN_RULES_H */
|
#endif /* _GWIN_RULES_H */
|
||||||
|
|
|
@ -250,6 +250,11 @@ static const gwidgetVMT sliderVMT = {
|
||||||
SliderMouseMove, // Process mouse move events
|
SliderMouseMove, // Process mouse move events
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
|
#if GINPUT_NEED_KEYBOARD || GWIN_NEED_KEYBOARD
|
||||||
|
{
|
||||||
|
0 // Process keyboard events
|
||||||
|
},
|
||||||
|
#endif
|
||||||
#if GINPUT_NEED_TOGGLE
|
#if GINPUT_NEED_TOGGLE
|
||||||
{
|
{
|
||||||
2, // 1 toggle role
|
2, // 1 toggle role
|
||||||
|
|
|
@ -77,6 +77,11 @@ static const gcontainerVMT tabpageVMT = {
|
||||||
0, // Process mouse move events
|
0, // Process mouse move events
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
|
#if GINPUT_NEED_KEYBOARD || GWIN_NEED_KEYBOARD
|
||||||
|
{
|
||||||
|
0 // Process keyboard events
|
||||||
|
},
|
||||||
|
#endif
|
||||||
#if GINPUT_NEED_TOGGLE
|
#if GINPUT_NEED_TOGGLE
|
||||||
{
|
{
|
||||||
0, // 1 toggle role
|
0, // 1 toggle role
|
||||||
|
|
253
src/gwin/gwin_textedit.c
Normal file
253
src/gwin/gwin_textedit.c
Normal file
|
@ -0,0 +1,253 @@
|
||||||
|
/*
|
||||||
|
* This file is subject to the terms of the GFX License. If a copy of
|
||||||
|
* the license was not distributed with this file, you can obtain one at:
|
||||||
|
*
|
||||||
|
* http://ugfx.org/license.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file src/gwin/gwin_textedit.c
|
||||||
|
* @brief GWIN TextEdit widget header file
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gfx.h"
|
||||||
|
|
||||||
|
#if GFX_USE_GWIN && GWIN_NEED_TEXTEDIT
|
||||||
|
|
||||||
|
#include "gwin_class.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
// Some settings
|
||||||
|
#define TEXT_PADDING_LEFT 4
|
||||||
|
#define CURSOR_PADDING_LEFT 0
|
||||||
|
#define CURSOR_EXTRA_HEIGHT 1
|
||||||
|
|
||||||
|
// Macros to assist in data type conversions
|
||||||
|
#define gh2obj ((GTexteditObject *)gh)
|
||||||
|
#define gw2obj ((GTexteditObject *)gw)
|
||||||
|
|
||||||
|
static bool_t resizeText(GWidgetObject* gw, size_t pos, int32_t diff) {
|
||||||
|
char *p, *q;
|
||||||
|
size_t sz;
|
||||||
|
|
||||||
|
p = (char *)gw->text;
|
||||||
|
sz = strlen(p)+1;
|
||||||
|
if (diff < 0)
|
||||||
|
memcpy(p+pos, p+pos-diff, sz-pos+diff);
|
||||||
|
if (!(p = gfxRealloc(p, sz, sz+diff)))
|
||||||
|
return FALSE;
|
||||||
|
gw->text = p;
|
||||||
|
if (diff > 0) {
|
||||||
|
q = p + sz;
|
||||||
|
p += pos;
|
||||||
|
while(--q >= p)
|
||||||
|
q[diff] = q[0];
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (GFX_USE_GINPUT && GINPUT_NEED_KEYBOARD) || GWIN_NEED_KEYBOARD
|
||||||
|
static void TextEditKeyboard(GWidgetObject* gw, GEventKeyboard* pke) {
|
||||||
|
// Only react on KEYDOWN events. Ignore KEYUP events.
|
||||||
|
if ((pke->keystate & GKEYSTATE_KEYUP) || !pke->bytecount)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Is it a special key?
|
||||||
|
if (pke->keystate & GKEYSTATE_SPECIAL) {
|
||||||
|
|
||||||
|
// Arrow keys to move the cursor
|
||||||
|
switch ((uint8_t)pke->c[0]) {
|
||||||
|
case GKEY_LEFT:
|
||||||
|
if (!gw2obj->cursorPos)
|
||||||
|
return;
|
||||||
|
gw2obj->cursorPos--;
|
||||||
|
break;
|
||||||
|
case GKEY_RIGHT:
|
||||||
|
if (!gw->text[gw2obj->cursorPos])
|
||||||
|
return;
|
||||||
|
gw2obj->cursorPos++;
|
||||||
|
break;
|
||||||
|
case GKEY_HOME:
|
||||||
|
if (!gw2obj->cursorPos)
|
||||||
|
return;
|
||||||
|
gw2obj->cursorPos = 0;
|
||||||
|
break;
|
||||||
|
case GKEY_END:
|
||||||
|
if (!gw->text[gw2obj->cursorPos])
|
||||||
|
return;
|
||||||
|
gw2obj->cursorPos = strlen(gw->text);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Normal key press
|
||||||
|
switch((uint8_t)pke->c[0]) {
|
||||||
|
case GKEY_BACKSPACE:
|
||||||
|
// Backspace
|
||||||
|
if (!gw2obj->cursorPos)
|
||||||
|
return;
|
||||||
|
gw2obj->cursorPos--;
|
||||||
|
resizeText(gw, gw2obj->cursorPos, -1);
|
||||||
|
break;
|
||||||
|
case GKEY_TAB:
|
||||||
|
case GKEY_LF:
|
||||||
|
case GKEY_CR:
|
||||||
|
// Move to the next field
|
||||||
|
_gwinMoveFocus();
|
||||||
|
return;
|
||||||
|
case GKEY_DEL:
|
||||||
|
// Delete
|
||||||
|
if (!gw->text[gw2obj->cursorPos])
|
||||||
|
return;
|
||||||
|
resizeText(gw, gw2obj->cursorPos, -1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Ignore any other control characters
|
||||||
|
if ((uint8_t)pke->c[0] < GKEY_SPACE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Keep the edit length to less than the maximum
|
||||||
|
if (gw2obj->maxSize && gw2obj->cursorPos+pke->bytecount > gw2obj->maxSize)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Make space
|
||||||
|
resizeText(gw, gw2obj->cursorPos, pke->bytecount);
|
||||||
|
|
||||||
|
// Insert the character
|
||||||
|
memcpy((char *)gw->text+gw2obj->cursorPos, pke->c, pke->bytecount);
|
||||||
|
gw2obj->cursorPos += pke->bytecount;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_gwinUpdate((GHandle)gw);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void gwinTexteditDefaultDraw(GWidgetObject* gw, void* param);
|
||||||
|
|
||||||
|
static const gwidgetVMT texteditVMT = {
|
||||||
|
{
|
||||||
|
"TextEdit", // The class name
|
||||||
|
sizeof(GTexteditObject), // The object size
|
||||||
|
_gwidgetDestroy, // The destroy routine
|
||||||
|
_gwidgetRedraw, // The redraw routine
|
||||||
|
0, // The after-clear routine
|
||||||
|
},
|
||||||
|
gwinTexteditDefaultDraw, // default drawing routine
|
||||||
|
#if GINPUT_NEED_MOUSE
|
||||||
|
{
|
||||||
|
0, // Process mouse down events (NOT USED)
|
||||||
|
0, // Process mouse up events (NOT USED)
|
||||||
|
0, // Process mouse move events (NOT USED)
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#if (GFX_USE_GINPUT && GINPUT_NEED_KEYBOARD) || GWIN_NEED_KEYBOARD
|
||||||
|
{
|
||||||
|
TextEditKeyboard // Process keyboard key down events
|
||||||
|
},
|
||||||
|
#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 gwinGTexteditCreate(GDisplay* g, GTexteditObject* wt, GWidgetInit* pInit, size_t maxSize)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
// Create the underlying widget
|
||||||
|
if (!(wt = (GTexteditObject*)_gwidgetCreate(g, &wt->w, pInit, &texteditVMT)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
wt->maxSize = maxSize;
|
||||||
|
|
||||||
|
// Reallocate the text (if necessary)
|
||||||
|
if (!(wt->w.g.flags & GWIN_FLG_ALLOCTXT)) {
|
||||||
|
if (!(p = gfxAlloc(wt->maxSize+1)))
|
||||||
|
return 0;
|
||||||
|
strncpy(p, wt->w.text, wt->maxSize);
|
||||||
|
wt->w.text = p;
|
||||||
|
wt->w.g.flags |= GWIN_FLG_ALLOCTXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set text and cursor position
|
||||||
|
wt->cursorPos = strlen(wt->w.text);
|
||||||
|
|
||||||
|
gwinSetVisible(&wt->w.g, pInit->g.show);
|
||||||
|
|
||||||
|
return (GHandle)wt;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gwinTexteditDefaultDraw(GWidgetObject* gw, void* param)
|
||||||
|
{
|
||||||
|
const char *p;
|
||||||
|
coord_t cpos, tpos;
|
||||||
|
color_t ccol, tcol;
|
||||||
|
(void)param;
|
||||||
|
|
||||||
|
// Is it a valid handle?
|
||||||
|
if (gw->g.vmt != (gwinVMT*)&texteditVMT)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Retrieve colors
|
||||||
|
tcol = (gw->g.flags & GWIN_FLG_SYSENABLED) ? gw->pstyle->enabled.text : gw->pstyle->disabled.text;
|
||||||
|
ccol = (gw->g.flags & GWIN_FLG_SYSENABLED) ? gw->pstyle->enabled.edge : gw->pstyle->disabled.edge;
|
||||||
|
|
||||||
|
// Adjust the text position so the cursor fits in the window
|
||||||
|
p = gw->text;
|
||||||
|
if (!gw2obj->cursorPos)
|
||||||
|
tpos = 0;
|
||||||
|
else {
|
||||||
|
for(cpos = gw2obj->cursorPos; ; p++, cpos--) {
|
||||||
|
tpos = gdispGetStringWidthCount(p, gw->g.font, cpos);
|
||||||
|
if (tpos < gw->g.width-(TEXT_PADDING_LEFT+CURSOR_PADDING_LEFT))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render background and string
|
||||||
|
#if TEXT_PADDING_LEFT
|
||||||
|
gdispGFillArea(gw->g.display, gw->g.x, gw->g.y, TEXT_PADDING_LEFT, gw->g.height, gw->pstyle->background);
|
||||||
|
#endif
|
||||||
|
gdispGFillStringBox(gw->g.display, gw->g.x + TEXT_PADDING_LEFT, gw->g.y, gw->g.width-TEXT_PADDING_LEFT, gw->g.height, p, gw->g.font, tcol, gw->pstyle->background, justifyLeft);
|
||||||
|
|
||||||
|
// Render cursor (if focused)
|
||||||
|
if (gwinGetFocus() == (GHandle)gw) {
|
||||||
|
// Calculate cursor stuff
|
||||||
|
|
||||||
|
// Draw cursor
|
||||||
|
tpos += gw->g.x + CURSOR_PADDING_LEFT + TEXT_PADDING_LEFT + gdispGetFontMetric(gw->g.font, fontBaselineX)/2;
|
||||||
|
cpos = (gw->g.height - gdispGetFontMetric(gw->g.font, fontHeight))/2 - CURSOR_EXTRA_HEIGHT;
|
||||||
|
gdispGDrawLine(gw->g.display, tpos, gw->g.y + cpos, tpos, gw->g.y + gw->g.height - cpos, ccol);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render border
|
||||||
|
gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, ccol);
|
||||||
|
|
||||||
|
// Render highlighted border of focused
|
||||||
|
_gwidgetDrawFocusRect(gw, 1, 1, gw->g.width-2, gw->g.height-2);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef gh2obj
|
||||||
|
#undef gw2obj
|
||||||
|
|
||||||
|
#endif // GFX_USE_GWIN && GWIN_NEED_TEXTEDIT
|
68
src/gwin/gwin_textedit.h
Normal file
68
src/gwin/gwin_textedit.h
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* This file is subject to the terms of the GFX License. If a copy of
|
||||||
|
* the license was not distributed with this file, you can obtain one at:
|
||||||
|
*
|
||||||
|
* http://ugfx.org/license.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file src/gwin/gwin_textedit.h
|
||||||
|
* @brief GWIN textedit widget header file
|
||||||
|
*
|
||||||
|
* @defgroup TextEdit TextEdit
|
||||||
|
* @ingroup Widgets
|
||||||
|
*
|
||||||
|
* @details A GWIN TextEdit widget allows 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_TEXTEDIT 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_TEXTEDIT_H
|
||||||
|
#define _GWIN_TEXTEDIT_H
|
||||||
|
|
||||||
|
// This file is included within "src/gwin/gwin_widget.h"
|
||||||
|
|
||||||
|
// A TextEdit widget
|
||||||
|
typedef struct GTexteditObject {
|
||||||
|
GWidgetObject w;
|
||||||
|
|
||||||
|
char* textBuffer;
|
||||||
|
size_t maxSize;
|
||||||
|
uint16_t cursorPos;
|
||||||
|
} GTexteditObject;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a TextEdit widget
|
||||||
|
* @details A TextEdit widget is a rectangular box which allows the user to input data through a keyboard.
|
||||||
|
* The keyboard can either be a physical one or a virtual on-screen keyboard as the keyboard driver
|
||||||
|
* is abstracted through the GINPUT module.
|
||||||
|
*
|
||||||
|
* @param[in] g The GDisplay on which the textedit should be displayed
|
||||||
|
* @param[in] wt The TextEdit structure to initialise. If this is NULL, the structure is dynamically allocated.
|
||||||
|
* @param[in] pInit The initialisation parameters to use.
|
||||||
|
* @param[in] maxSize The maximum number of characters the TextEdit widget can hold. (0 means unlimited).
|
||||||
|
*
|
||||||
|
* @return NULL if there is no resultant drawing area, otherwise the widget handle.
|
||||||
|
*
|
||||||
|
* @note If the initial text set is larger than maxSize then the text is truncated at maxSize characters.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
GHandle gwinGTexteditCreate(GDisplay* g, GTexteditObject* wt, GWidgetInit* pInit, size_t maxSize);
|
||||||
|
#define gwinTexteditCreate(wt, pInit, maxSize) gwinGTexteditCreate(GDISP, wt, pInit, maxSize)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // _GWIN_TEXTEDIT_H
|
||||||
|
/** @} */
|
|
@ -18,19 +18,25 @@
|
||||||
|
|
||||||
#include "gwin_class.h"
|
#include "gwin_class.h"
|
||||||
|
|
||||||
/* Our listener for events for widgets */
|
// Our listener for events for widgets
|
||||||
static GListener gl;
|
static GListener gl;
|
||||||
|
|
||||||
/* Our default style - a white background theme */
|
#if GFX_USE_GINPUT && GINPUT_NEED_KEYBOARD
|
||||||
|
// Our current focus window
|
||||||
|
static GHandle _widgetInFocus;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Our default style - a white background theme
|
||||||
const GWidgetStyle WhiteWidgetStyle = {
|
const GWidgetStyle WhiteWidgetStyle = {
|
||||||
HTML2COLOR(0xFFFFFF), // window background
|
HTML2COLOR(0xFFFFFF), // window background
|
||||||
|
HTML2COLOR(0x2A8FCD), // focused
|
||||||
|
|
||||||
// enabled color set
|
// enabled color set
|
||||||
{
|
{
|
||||||
HTML2COLOR(0x000000), // text
|
HTML2COLOR(0x000000), // text
|
||||||
HTML2COLOR(0x404040), // edge
|
HTML2COLOR(0x404040), // edge
|
||||||
HTML2COLOR(0xE0E0E0), // fill
|
HTML2COLOR(0xE0E0E0), // fill
|
||||||
HTML2COLOR(0xE0E0E0), // progress - inactive area
|
HTML2COLOR(0xE0E0E0) // progress - inactive area
|
||||||
},
|
},
|
||||||
|
|
||||||
// disabled color set
|
// disabled color set
|
||||||
|
@ -38,7 +44,7 @@ const GWidgetStyle WhiteWidgetStyle = {
|
||||||
HTML2COLOR(0xC0C0C0), // text
|
HTML2COLOR(0xC0C0C0), // text
|
||||||
HTML2COLOR(0x808080), // edge
|
HTML2COLOR(0x808080), // edge
|
||||||
HTML2COLOR(0xE0E0E0), // fill
|
HTML2COLOR(0xE0E0E0), // fill
|
||||||
HTML2COLOR(0xC0E0C0), // progress - active area
|
HTML2COLOR(0xC0E0C0) // progress - active area
|
||||||
},
|
},
|
||||||
|
|
||||||
// pressed color set
|
// pressed color set
|
||||||
|
@ -46,20 +52,21 @@ const GWidgetStyle WhiteWidgetStyle = {
|
||||||
HTML2COLOR(0x404040), // text
|
HTML2COLOR(0x404040), // text
|
||||||
HTML2COLOR(0x404040), // edge
|
HTML2COLOR(0x404040), // edge
|
||||||
HTML2COLOR(0x808080), // fill
|
HTML2COLOR(0x808080), // fill
|
||||||
HTML2COLOR(0x00E000), // progress - active area
|
HTML2COLOR(0x00E000) // progress - active area
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Our black style */
|
/* Our black style */
|
||||||
const GWidgetStyle BlackWidgetStyle = {
|
const GWidgetStyle BlackWidgetStyle = {
|
||||||
HTML2COLOR(0x000000), // window background
|
HTML2COLOR(0x000000), // window background
|
||||||
|
HTML2COLOR(0x2A8FCD), // focused
|
||||||
|
|
||||||
// enabled color set
|
// enabled color set
|
||||||
{
|
{
|
||||||
HTML2COLOR(0xC0C0C0), // text
|
HTML2COLOR(0xC0C0C0), // text
|
||||||
HTML2COLOR(0xC0C0C0), // edge
|
HTML2COLOR(0xC0C0C0), // edge
|
||||||
HTML2COLOR(0x606060), // fill
|
HTML2COLOR(0x606060), // fill
|
||||||
HTML2COLOR(0x404040), // progress - inactive area
|
HTML2COLOR(0x404040) // progress - inactive area
|
||||||
},
|
},
|
||||||
|
|
||||||
// disabled color set
|
// disabled color set
|
||||||
|
@ -67,7 +74,7 @@ const GWidgetStyle BlackWidgetStyle = {
|
||||||
HTML2COLOR(0x808080), // text
|
HTML2COLOR(0x808080), // text
|
||||||
HTML2COLOR(0x404040), // edge
|
HTML2COLOR(0x404040), // edge
|
||||||
HTML2COLOR(0x404040), // fill
|
HTML2COLOR(0x404040), // fill
|
||||||
HTML2COLOR(0x004000), // progress - active area
|
HTML2COLOR(0x004000) // progress - active area
|
||||||
},
|
},
|
||||||
|
|
||||||
// pressed color set
|
// pressed color set
|
||||||
|
@ -75,19 +82,20 @@ const GWidgetStyle BlackWidgetStyle = {
|
||||||
HTML2COLOR(0xFFFFFF), // text
|
HTML2COLOR(0xFFFFFF), // text
|
||||||
HTML2COLOR(0xC0C0C0), // edge
|
HTML2COLOR(0xC0C0C0), // edge
|
||||||
HTML2COLOR(0xE0E0E0), // fill
|
HTML2COLOR(0xE0E0E0), // fill
|
||||||
HTML2COLOR(0x008000), // progress - active area
|
HTML2COLOR(0x008000) // progress - active area
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const GWidgetStyle * defaultStyle = &BlackWidgetStyle;
|
static const GWidgetStyle * defaultStyle = &BlackWidgetStyle;
|
||||||
|
|
||||||
/* We use these everywhere in this file */
|
// We use these everywhere in this file
|
||||||
#define gw ((GWidgetObject *)gh)
|
#define gw ((GWidgetObject *)gh)
|
||||||
#define wvmt ((gwidgetVMT *)gh->vmt)
|
#define wvmt ((gwidgetVMT *)gh->vmt)
|
||||||
|
|
||||||
/* Process an event */
|
// Process an event
|
||||||
static void gwidgetEvent(void *param, GEvent *pe) {
|
static void gwidgetEvent(void *param, GEvent *pe) {
|
||||||
#define pme ((GEventMouse *)pe)
|
#define pme ((GEventMouse *)pe)
|
||||||
|
#define pke ((GEventKeyboard *)pe)
|
||||||
#define pte ((GEventToggle *)pe)
|
#define pte ((GEventToggle *)pe)
|
||||||
#define pde ((GEventDial *)pe)
|
#define pde ((GEventDial *)pe)
|
||||||
|
|
||||||
|
@ -105,7 +113,7 @@ static void gwidgetEvent(void *param, GEvent *pe) {
|
||||||
case GEVENT_MOUSE:
|
case GEVENT_MOUSE:
|
||||||
case GEVENT_TOUCH:
|
case GEVENT_TOUCH:
|
||||||
// Cycle through all windows
|
// Cycle through all windows
|
||||||
for(gh = 0, h = gwinGetNextWindow(0); h; h = gwinGetNextWindow(h)) {
|
for (gh = 0, h = gwinGetNextWindow(0); h; h = gwinGetNextWindow(h)) {
|
||||||
|
|
||||||
// The window must be on this display and visible to be relevant
|
// The window must be on this display and visible to be relevant
|
||||||
if (h->display != pme->display || !(h->flags & GWIN_FLG_SYSVISIBLE))
|
if (h->display != pme->display || !(h->flags & GWIN_FLG_SYSVISIBLE))
|
||||||
|
@ -123,6 +131,7 @@ static void gwidgetEvent(void *param, GEvent *pe) {
|
||||||
|
|
||||||
// There is only ever one captured mouse. Prevent normal mouse processing if there is a captured mouse
|
// There is only ever one captured mouse. Prevent normal mouse processing if there is a captured mouse
|
||||||
gh = 0;
|
gh = 0;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,6 +144,13 @@ static void gwidgetEvent(void *param, GEvent *pe) {
|
||||||
if (gh && (gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED)) == (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED)) {
|
if (gh && (gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED)) == (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED)) {
|
||||||
if ((pme->buttons & GMETA_MOUSE_DOWN)) {
|
if ((pme->buttons & GMETA_MOUSE_DOWN)) {
|
||||||
gh->flags |= GWIN_FLG_MOUSECAPTURE;
|
gh->flags |= GWIN_FLG_MOUSECAPTURE;
|
||||||
|
|
||||||
|
#if (GFX_USE_GINPUT && GINPUT_NEED_KEYBOARD) || GWIN_NEED_KEYBOARD
|
||||||
|
// We should try and capture the focus on this window.
|
||||||
|
// If we can't then we don't change the focus
|
||||||
|
gwinSetFocus(gh);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (wvmt->MouseDown)
|
if (wvmt->MouseDown)
|
||||||
wvmt->MouseDown(gw, pme->x - gh->x, pme->y - gh->y);
|
wvmt->MouseDown(gw, pme->x - gh->x, pme->y - gh->y);
|
||||||
}
|
}
|
||||||
|
@ -142,6 +158,21 @@ static void gwidgetEvent(void *param, GEvent *pe) {
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if (GFX_USE_GINPUT && GINPUT_NEED_KEYBOARD) || GWIN_NEED_KEYBOARD
|
||||||
|
case GEVENT_KEYBOARD:
|
||||||
|
// If Tab key pressed then set focus to next widget
|
||||||
|
if (pke->bytecount == 1 && pke->c[0] == GKEY_TAB) {
|
||||||
|
if (!(pke->keystate & GKEYSTATE_KEYUP))
|
||||||
|
_gwinMoveFocus();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, send keyboard events only to widget in focus
|
||||||
|
if (_widgetInFocus)
|
||||||
|
((gwidgetVMT*)_widgetInFocus->vmt)->KeyboardEvent((GWidgetObject*)_widgetInFocus, pke);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
|
#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
|
||||||
case GEVENT_TOGGLE:
|
case GEVENT_TOGGLE:
|
||||||
// Cycle through all windows
|
// Cycle through all windows
|
||||||
|
@ -191,9 +222,108 @@ static void gwidgetEvent(void *param, GEvent *pe) {
|
||||||
|
|
||||||
#undef pme
|
#undef pme
|
||||||
#undef pte
|
#undef pte
|
||||||
|
#undef pke
|
||||||
#undef pde
|
#undef pde
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (GFX_USE_GINPUT && GINPUT_NEED_KEYBOARD) || GWIN_NEED_KEYBOARD
|
||||||
|
GHandle gwinGetFocus(void) {
|
||||||
|
return _widgetInFocus;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t gwinSetFocus(GHandle gh) {
|
||||||
|
GHandle oldFocus;
|
||||||
|
|
||||||
|
// Do we already have the focus?
|
||||||
|
if (gh == _widgetInFocus)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
// The new window must be NULLL or a visible enabled widget with a keyboard handler
|
||||||
|
if (!gh || ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED|GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE)) == (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED|GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE)
|
||||||
|
&& ((gwidgetVMT*)gh->vmt)->KeyboardEvent)) {
|
||||||
|
// Move the current focus
|
||||||
|
oldFocus = _widgetInFocus;
|
||||||
|
_widgetInFocus = gh;
|
||||||
|
if (oldFocus) _gwinUpdate(oldFocus);
|
||||||
|
if (gh) _gwinUpdate(gh);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _gwinMoveFocus(void) {
|
||||||
|
GHandle gh;
|
||||||
|
bool_t looponce;
|
||||||
|
|
||||||
|
// Find a new focus window (one may or may not exist).
|
||||||
|
looponce = FALSE;
|
||||||
|
for(gh = gwinGetNextWindow(_widgetInFocus); ; gh = gwinGetNextWindow(gh)) {
|
||||||
|
if (!gh && !looponce) {
|
||||||
|
looponce = TRUE;
|
||||||
|
gh = gwinGetNextWindow(0);
|
||||||
|
}
|
||||||
|
if (gwinSetFocus(gh))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _gwinFixFocus(GHandle gh) {
|
||||||
|
GHandle oldFocus;
|
||||||
|
|
||||||
|
if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED|GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE)) == (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED|GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE)
|
||||||
|
&& ((gwidgetVMT*)gh->vmt)->KeyboardEvent) {
|
||||||
|
|
||||||
|
// We are a candidate to be able to claim the focus
|
||||||
|
|
||||||
|
// Claim the focus if no-one else has
|
||||||
|
if (!_widgetInFocus)
|
||||||
|
_widgetInFocus = gh;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have lost any right to the focus
|
||||||
|
|
||||||
|
// Did we have the focus
|
||||||
|
if (gh != _widgetInFocus)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// We did - we need to find a new focus window
|
||||||
|
oldFocus = _widgetInFocus;
|
||||||
|
for(gh = gwinGetNextWindow(oldFocus); gh && gh != oldFocus; gh = gwinGetNextWindow(gh)) {
|
||||||
|
|
||||||
|
// Must be a visible enabled widget with a keyboard handler
|
||||||
|
if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED|GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE)) == (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED|GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE)
|
||||||
|
&& ((gwidgetVMT*)gh->vmt)->KeyboardEvent) {
|
||||||
|
|
||||||
|
// Grab the focus for the new window
|
||||||
|
_widgetInFocus = gh;
|
||||||
|
|
||||||
|
// This new window still needs to be marked for redraw (but don't actually do it yet).
|
||||||
|
gh->flags |= GWIN_FLG_NEEDREDRAW;
|
||||||
|
// RedrawPending |= DOREDRAW_VISIBLES; - FIX LATER
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No-one has the right to the focus
|
||||||
|
_widgetInFocus = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _gwidgetDrawFocusRect(GWidgetObject *gx, coord_t x, coord_t y, coord_t cx, coord_t cy) {
|
||||||
|
// Don't do anything if we don't have the focus
|
||||||
|
if (&gx->g != _widgetInFocus)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Use the very simplest possible focus rectangle for now
|
||||||
|
uint16_t i = 0;
|
||||||
|
for (i = 0; i < GWIN_FOCUS_HIGHLIGHT_WIDTH; i++) {
|
||||||
|
gdispGDrawBox(gx->g.display, gx->g.x+x+i, gx->g.y+y+i, cx-2*i, cy-2*i, gx->pstyle->focus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
|
#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
|
||||||
static GHandle FindToggleUser(uint16_t instance) {
|
static GHandle FindToggleUser(uint16_t instance) {
|
||||||
GHandle gh;
|
GHandle gh;
|
||||||
|
@ -235,6 +365,10 @@ void _gwidgetInit(void)
|
||||||
geventListenerInit(&gl);
|
geventListenerInit(&gl);
|
||||||
geventRegisterCallback(&gl, gwidgetEvent, 0);
|
geventRegisterCallback(&gl, gwidgetEvent, 0);
|
||||||
geventAttachSource(&gl, ginputGetMouse(GMOUSE_ALL_INSTANCES), GLISTEN_MOUSEMETA|GLISTEN_MOUSEDOWNMOVES);
|
geventAttachSource(&gl, ginputGetMouse(GMOUSE_ALL_INSTANCES), GLISTEN_MOUSEMETA|GLISTEN_MOUSEDOWNMOVES);
|
||||||
|
|
||||||
|
#if GINPUT_NEED_KEYBOARD
|
||||||
|
geventAttachSource(&gl, ginputGetKeyboard(GKEYBOARD_ALL_INSTANCES), GLISTEN_KEYUP);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void _gwidgetDeinit(void)
|
void _gwidgetDeinit(void)
|
||||||
|
@ -267,6 +401,10 @@ void _gwidgetDestroy(GHandle gh) {
|
||||||
uint16_t role, instance;
|
uint16_t role, instance;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Make the window is invisible so it is not eligible for focus
|
||||||
|
gh->flags &= ~GWIN_FLG_VISIBLE;
|
||||||
|
_gwinFixFocus(gh);
|
||||||
|
|
||||||
// Deallocate the text (if necessary)
|
// Deallocate the text (if necessary)
|
||||||
if ((gh->flags & GWIN_FLG_ALLOCTXT)) {
|
if ((gh->flags & GWIN_FLG_ALLOCTXT)) {
|
||||||
gh->flags &= ~GWIN_FLG_ALLOCTXT;
|
gh->flags &= ~GWIN_FLG_ALLOCTXT;
|
||||||
|
@ -361,7 +499,6 @@ const GWidgetStyle *gwinGetDefaultStyle(void) {
|
||||||
return defaultStyle;
|
return defaultStyle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void gwinSetText(GHandle gh, const char *text, bool_t useAlloc) {
|
void gwinSetText(GHandle gh, const char *text, bool_t useAlloc) {
|
||||||
if (!(gh->flags & GWIN_FLG_WIDGET))
|
if (!(gh->flags & GWIN_FLG_WIDGET))
|
||||||
return;
|
return;
|
||||||
|
@ -398,12 +535,22 @@ const char *gwinGetText(GHandle gh) {
|
||||||
return gw->text;
|
return gw->text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool_t gwinIsWidget(GHandle gh) {
|
||||||
|
if (gh->flags & GWIN_FLG_WIDGET) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
void gwinSetStyle(GHandle gh, const GWidgetStyle *pstyle) {
|
void gwinSetStyle(GHandle gh, const GWidgetStyle *pstyle) {
|
||||||
if (!(gh->flags & GWIN_FLG_WIDGET))
|
if (!(gh->flags & GWIN_FLG_WIDGET))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
gw->pstyle = pstyle ? pstyle : defaultStyle;
|
gw->pstyle = pstyle ? pstyle : defaultStyle;
|
||||||
gh->bgcolor = pstyle->background;
|
gh->bgcolor = pstyle->background;
|
||||||
gh->color = pstyle->enabled.text;
|
gh->color = pstyle->enabled.text;
|
||||||
|
|
||||||
_gwinUpdate(gh);
|
_gwinUpdate(gh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,10 +33,10 @@ struct GWidgetObject;
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
typedef struct GColorSet {
|
typedef struct GColorSet {
|
||||||
color_t text; // @< The text color
|
color_t text; /**< The text color */
|
||||||
color_t edge; // @< The edge color
|
color_t edge; /**< The edge color */
|
||||||
color_t fill; // @< The fill color
|
color_t fill; /**< The fill color */
|
||||||
color_t progress; // @< The color of progress bars
|
color_t progress; /**< The color of progress bars */
|
||||||
} GColorSet;
|
} GColorSet;
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
@ -48,10 +48,11 @@ typedef struct GColorSet {
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
typedef struct GWidgetStyle {
|
typedef struct GWidgetStyle {
|
||||||
color_t background; // @< The window background color
|
color_t background; /**< The window background color */
|
||||||
GColorSet enabled; // @< The colors when enabled
|
color_t focus; /**< The color when a widget is focused */
|
||||||
GColorSet disabled; // @< The colors when disabled
|
GColorSet enabled; /**< The colors when enabled */
|
||||||
GColorSet pressed; // @< The colors when pressed
|
GColorSet disabled; /**< The colors when disabled */
|
||||||
|
GColorSet pressed; /**< The colors when pressed */
|
||||||
} GWidgetStyle;
|
} GWidgetStyle;
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
@ -92,13 +93,13 @@ typedef uint16_t WidgetTag;
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
typedef struct GWidgetInit {
|
typedef struct GWidgetInit {
|
||||||
GWindowInit g; // @< The GWIN initializer
|
GWindowInit g; /**< The GWIN initializer */
|
||||||
const char * text; // @< The initial text
|
const char * text; /**< The initial text */
|
||||||
CustomWidgetDrawFunction customDraw; // @< A custom draw function - use NULL for the standard
|
CustomWidgetDrawFunction customDraw; /**< A custom draw function - use NULL for the standard */
|
||||||
void * customParam; // @< A parameter for the custom draw function (default = NULL)
|
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
|
const GWidgetStyle * customStyle; /**< A custom style to use - use NULL for the default style */
|
||||||
#if GWIN_WIDGET_TAGS || defined(__DOXYGEN__)
|
#if GWIN_WIDGET_TAGS || defined(__DOXYGEN__)
|
||||||
WidgetTag tag; // @< The tag to associate with the widget
|
WidgetTag tag; /**< The tag to associate with the widget */
|
||||||
#endif
|
#endif
|
||||||
} GWidgetInit;
|
} GWidgetInit;
|
||||||
/** @} */
|
/** @} */
|
||||||
|
@ -113,13 +114,13 @@ typedef struct GWidgetInit {
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
typedef struct GWidgetObject {
|
typedef struct GWidgetObject {
|
||||||
GWindowObject g; // @< This is still a GWIN
|
GWindowObject g; /**< This is still a GWIN */
|
||||||
const char * text; // @< The widget text
|
const char * text; /**< The widget text */
|
||||||
CustomWidgetDrawFunction fnDraw; // @< The current draw function
|
CustomWidgetDrawFunction fnDraw; /**< The current draw function */
|
||||||
void * fnParam; // @< A parameter for the current draw function
|
void * fnParam; /**< A parameter for the current draw function */
|
||||||
const GWidgetStyle * pstyle; // @< The current widget style colors
|
const GWidgetStyle * pstyle; /**< The current widget style colors */
|
||||||
#if GWIN_WIDGET_TAGS || defined(__DOXYGEN__)
|
#if GWIN_WIDGET_TAGS || defined(__DOXYGEN__)
|
||||||
WidgetTag tag; // @< The widget tag
|
WidgetTag tag; /**< The widget tag */
|
||||||
#endif
|
#endif
|
||||||
} GWidgetObject;
|
} GWidgetObject;
|
||||||
/** @} */
|
/** @} */
|
||||||
|
@ -144,10 +145,10 @@ typedef struct GWidgetObject {
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
typedef struct GEventGWin {
|
typedef struct GEventGWin {
|
||||||
GEventType type; // The type of this event
|
GEventType type; /**< The type of this event */
|
||||||
GHandle gwin; // The gwin window handle
|
GHandle gwin; /**< The gwin window handle */
|
||||||
#if GWIN_NEED_WIDGET && GWIN_WIDGET_TAGS
|
#if GWIN_NEED_WIDGET && GWIN_WIDGET_TAGS
|
||||||
WidgetTag tag; // The tag (if applicable)
|
WidgetTag tag; /**< The tag (if applicable) */
|
||||||
#endif
|
#endif
|
||||||
} GEventGWin;
|
} GEventGWin;
|
||||||
/** @} */
|
/** @} */
|
||||||
|
@ -228,6 +229,17 @@ void gwinSetText(GHandle gh, const char *text, bool_t useAlloc);
|
||||||
*/
|
*/
|
||||||
const char *gwinGetText(GHandle gh);
|
const char *gwinGetText(GHandle gh);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check whether a handles is a widget handle or not
|
||||||
|
*
|
||||||
|
* @param[in] gh The handle to check.
|
||||||
|
*
|
||||||
|
* @return TRUE if the passed handle is a widget handle. FALSE otherwise.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
bool_t gwinIsWidget(GHandle gh);
|
||||||
|
|
||||||
#if GWIN_WIDGET_TAGS || defined(__DOXYGEN__)
|
#if GWIN_WIDGET_TAGS || defined(__DOXYGEN__)
|
||||||
/**
|
/**
|
||||||
* @brief Set the tag of a widget.
|
* @brief Set the tag of a widget.
|
||||||
|
@ -344,6 +356,36 @@ bool_t gwinAttachListener(GListener *pl);
|
||||||
bool_t gwinAttachDial(GHandle gh, uint16_t role, uint16_t instance);
|
bool_t gwinAttachDial(GHandle gh, uint16_t role, uint16_t instance);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if (GFX_USE_GINPUT && GINPUT_NEED_KEYBOARD) || GWIN_NEED_KEYBOARD || defined(__DOXYGEN__)
|
||||||
|
/**
|
||||||
|
* @brief Set the keyboard focus to a specific window
|
||||||
|
* @return Returns TRUE if the focus could be set to that window
|
||||||
|
*
|
||||||
|
* @param[in] gh The window
|
||||||
|
*
|
||||||
|
* @note Passing NULL will remove the focus from any window.
|
||||||
|
* @note Only visible enabled widgets are capable of getting the focus.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
bool_t gwinSetFocus(GHandle gh);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the widget that is currently in focus
|
||||||
|
*
|
||||||
|
* @details The widget that is currently in focus is the widget that
|
||||||
|
* receives mouse and keyboard events.
|
||||||
|
*
|
||||||
|
* @return The handle of the widget that is currently in focus. May be NULL.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
GHandle gwinGetFocus(void);
|
||||||
|
#else
|
||||||
|
#define gwinGetFocus() (0)
|
||||||
|
#define gwinSetFocus(gh) (FALSE)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -381,5 +423,9 @@ bool_t gwinAttachListener(GListener *pl);
|
||||||
#include "gwin_keyboard.h"
|
#include "gwin_keyboard.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if GWIN_NEED_TEXTEDIT || defined(__DOXYGEN__)
|
||||||
|
#include "gwin_textedit.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* _GWIDGET_H */
|
#endif /* _GWIDGET_H */
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
|
@ -162,7 +162,6 @@
|
||||||
extern const GWindowManager GNullWindowManager;
|
extern const GWindowManager GNullWindowManager;
|
||||||
GWindowManager * _GWINwm;
|
GWindowManager * _GWINwm;
|
||||||
bool_t _gwinFlashState;
|
bool_t _gwinFlashState;
|
||||||
|
|
||||||
static gfxSem gwinsem;
|
static gfxSem gwinsem;
|
||||||
static gfxQueueASync _GWINList;
|
static gfxQueueASync _GWINList;
|
||||||
#if GWIN_NEED_FLASHING
|
#if GWIN_NEED_FLASHING
|
||||||
|
@ -331,14 +330,23 @@ void _gwinUpdate(GHandle gh) {
|
||||||
if (!gh->parent || (gh->parent->flags & GWIN_FLG_SYSVISIBLE)) {
|
if (!gh->parent || (gh->parent->flags & GWIN_FLG_SYSVISIBLE)) {
|
||||||
// We have been made visible
|
// We have been made visible
|
||||||
gh->flags |= (GWIN_FLG_SYSVISIBLE|GWIN_FLG_NEEDREDRAW|GWIN_FLG_BGREDRAW);
|
gh->flags |= (GWIN_FLG_SYSVISIBLE|GWIN_FLG_NEEDREDRAW|GWIN_FLG_BGREDRAW);
|
||||||
|
|
||||||
|
// Do we want to grab the focus
|
||||||
|
_gwinFixFocus(gh);
|
||||||
|
|
||||||
RedrawPending |= DOREDRAW_VISIBLES;
|
RedrawPending |= DOREDRAW_VISIBLES;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case (GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE):
|
case (GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE):
|
||||||
if (!gh->parent || (gh->parent->flags & GWIN_FLG_SYSVISIBLE))
|
if (!gh->parent || (gh->parent->flags & GWIN_FLG_SYSVISIBLE))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Parent has been made invisible
|
// Parent has been made invisible
|
||||||
gh->flags &= ~GWIN_FLG_SYSVISIBLE;
|
gh->flags &= ~GWIN_FLG_SYSVISIBLE;
|
||||||
|
|
||||||
|
// No focus for us anymore
|
||||||
|
_gwinFixFocus(gh);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case GWIN_FLG_SYSVISIBLE:
|
case GWIN_FLG_SYSVISIBLE:
|
||||||
// We have been made invisible
|
// We have been made invisible
|
||||||
|
@ -346,6 +354,10 @@ void _gwinUpdate(GHandle gh) {
|
||||||
if (!gh->parent || (gh->parent->flags & GWIN_FLG_SYSVISIBLE)) {
|
if (!gh->parent || (gh->parent->flags & GWIN_FLG_SYSVISIBLE)) {
|
||||||
// The parent is visible so we must clear the area we took
|
// The parent is visible so we must clear the area we took
|
||||||
gh->flags |= (GWIN_FLG_NEEDREDRAW|GWIN_FLG_BGREDRAW);
|
gh->flags |= (GWIN_FLG_NEEDREDRAW|GWIN_FLG_BGREDRAW);
|
||||||
|
|
||||||
|
// No focus for us anymore
|
||||||
|
_gwinFixFocus(gh);
|
||||||
|
|
||||||
RedrawPending |= DOREDRAW_INVISIBLES;
|
RedrawPending |= DOREDRAW_INVISIBLES;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -455,6 +467,10 @@ void gwinRedraw(GHandle gh) {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
if (!(gh->flags & GWIN_FLG_VISIBLE)) {
|
if (!(gh->flags & GWIN_FLG_VISIBLE)) {
|
||||||
gh->flags |= (GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE|GWIN_FLG_NEEDREDRAW|GWIN_FLG_BGREDRAW);
|
gh->flags |= (GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE|GWIN_FLG_NEEDREDRAW|GWIN_FLG_BGREDRAW);
|
||||||
|
|
||||||
|
// Do we want to grab the focus
|
||||||
|
_gwinFixFocus(gh);
|
||||||
|
|
||||||
RedrawPending |= DOREDRAW_VISIBLES;
|
RedrawPending |= DOREDRAW_VISIBLES;
|
||||||
TriggerRedraw();
|
TriggerRedraw();
|
||||||
}
|
}
|
||||||
|
@ -462,6 +478,10 @@ void gwinRedraw(GHandle gh) {
|
||||||
if ((gh->flags & GWIN_FLG_VISIBLE)) {
|
if ((gh->flags & GWIN_FLG_VISIBLE)) {
|
||||||
gh->flags &= ~(GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE);
|
gh->flags &= ~(GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE);
|
||||||
gh->flags |= (GWIN_FLG_NEEDREDRAW|GWIN_FLG_BGREDRAW);
|
gh->flags |= (GWIN_FLG_NEEDREDRAW|GWIN_FLG_BGREDRAW);
|
||||||
|
|
||||||
|
// No focus for us anymore
|
||||||
|
_gwinFixFocus(gh);
|
||||||
|
|
||||||
RedrawPending |= DOREDRAW_INVISIBLES;
|
RedrawPending |= DOREDRAW_INVISIBLES;
|
||||||
TriggerRedraw();
|
TriggerRedraw();
|
||||||
}
|
}
|
||||||
|
@ -482,6 +502,10 @@ void gwinRedraw(GHandle gh) {
|
||||||
for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
|
for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
|
||||||
if ((gh->flags & (GWIN_FLG_SYSENABLED|GWIN_FLG_ENABLED)) == GWIN_FLG_ENABLED && (!gh->parent || (gh->parent->flags & GWIN_FLG_SYSENABLED))) {
|
if ((gh->flags & (GWIN_FLG_SYSENABLED|GWIN_FLG_ENABLED)) == GWIN_FLG_ENABLED && (!gh->parent || (gh->parent->flags & GWIN_FLG_SYSENABLED))) {
|
||||||
gh->flags |= GWIN_FLG_SYSENABLED; // Fix it
|
gh->flags |= GWIN_FLG_SYSENABLED; // Fix it
|
||||||
|
|
||||||
|
// Do we want to grab the focus
|
||||||
|
_gwinFixFocus(gh);
|
||||||
|
|
||||||
_gwinUpdate(gh);
|
_gwinUpdate(gh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -495,6 +519,10 @@ void gwinRedraw(GHandle gh) {
|
||||||
for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
|
for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
|
||||||
if ((gh->flags & GWIN_FLG_SYSENABLED) && (!(gh->flags & GWIN_FLG_ENABLED) || (gh->parent && !(gh->parent->flags & GWIN_FLG_SYSENABLED)))) {
|
if ((gh->flags & GWIN_FLG_SYSENABLED) && (!(gh->flags & GWIN_FLG_ENABLED) || (gh->parent && !(gh->parent->flags & GWIN_FLG_SYSENABLED)))) {
|
||||||
gh->flags &= ~GWIN_FLG_SYSENABLED; // Fix it
|
gh->flags &= ~GWIN_FLG_SYSENABLED; // Fix it
|
||||||
|
|
||||||
|
// No focus for us anymore
|
||||||
|
_gwinFixFocus(gh);
|
||||||
|
|
||||||
_gwinUpdate(gh);
|
_gwinUpdate(gh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -506,11 +534,19 @@ void gwinRedraw(GHandle gh) {
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
if (!(gh->flags & GWIN_FLG_ENABLED)) {
|
if (!(gh->flags & GWIN_FLG_ENABLED)) {
|
||||||
gh->flags |= (GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED);
|
gh->flags |= (GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED);
|
||||||
|
|
||||||
|
// Do we want to grab the focus
|
||||||
|
_gwinFixFocus(gh);
|
||||||
|
|
||||||
_gwinUpdate(gh);
|
_gwinUpdate(gh);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ((gh->flags & GWIN_FLG_ENABLED)) {
|
if ((gh->flags & GWIN_FLG_ENABLED)) {
|
||||||
gh->flags &= ~(GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED);
|
gh->flags &= ~(GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED);
|
||||||
|
|
||||||
|
// No focus for us anymore
|
||||||
|
_gwinFixFocus(gh);
|
||||||
|
|
||||||
_gwinUpdate(gh);
|
_gwinUpdate(gh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue