2014-05-09 15:11:30 +00:00
|
|
|
/*
|
|
|
|
* 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:
|
|
|
|
*
|
2018-10-01 15:32:39 +00:00
|
|
|
* http://ugfx.io/license.html
|
2014-05-09 15:11:30 +00:00
|
|
|
*/
|
|
|
|
|
2014-05-10 08:20:05 +00:00
|
|
|
/**
|
2014-08-20 07:42:53 +00:00
|
|
|
* @file src/gwin/gwin_container.c
|
2014-05-20 16:05:38 +00:00
|
|
|
* @brief GWIN sub-system container code
|
2014-05-10 08:20:05 +00:00
|
|
|
*/
|
|
|
|
|
2015-11-21 09:27:08 +00:00
|
|
|
#include "../../gfx.h"
|
2014-05-09 15:11:30 +00:00
|
|
|
|
|
|
|
#if GFX_USE_GWIN && GWIN_NEED_CONTAINERS
|
|
|
|
|
2014-08-20 07:42:53 +00:00
|
|
|
#include "gwin_class.h"
|
2014-05-09 15:11:30 +00:00
|
|
|
|
|
|
|
void _gcontainerInit(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void _gcontainerDeinit(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
GHandle _gcontainerCreate(GDisplay *g, GContainerObject *pgc, const GWidgetInit *pInit, const gcontainerVMT *vmt) {
|
|
|
|
if (!(pgc = (GContainerObject *)_gwidgetCreate(g, (GWidgetObject *)pgc, pInit, &vmt->gw)))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
pgc->g.flags |= GWIN_FLG_CONTAINER;
|
|
|
|
|
|
|
|
return &pgc->g;
|
|
|
|
}
|
|
|
|
|
|
|
|
void _gcontainerDestroy(GHandle gh) {
|
|
|
|
GHandle child;
|
|
|
|
|
|
|
|
while((child = gwinGetFirstChild(gh)))
|
|
|
|
gwinDestroy(child);
|
|
|
|
_gwidgetDestroy(gh);
|
|
|
|
}
|
|
|
|
|
|
|
|
GHandle gwinGetFirstChild(GHandle gh) {
|
|
|
|
GHandle child;
|
|
|
|
|
|
|
|
for(child = gwinGetNextWindow(0); child; child = gwinGetNextWindow(child))
|
|
|
|
if (child->parent == gh)
|
|
|
|
return child;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
GHandle gwinGetSibling(GHandle gh) {
|
|
|
|
GHandle child;
|
|
|
|
|
|
|
|
for(child = gwinGetNextWindow(gh), gh = gh->parent; child; child = gwinGetNextWindow(child))
|
|
|
|
if (child->parent == gh)
|
|
|
|
return child;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-07-08 00:54:19 +00:00
|
|
|
gCoord gwinGetInnerWidth(GHandle gh) {
|
2014-05-11 10:11:16 +00:00
|
|
|
if (!(gh->flags & GWIN_FLG_CONTAINER))
|
|
|
|
return 0;
|
|
|
|
return gh->width - ((const gcontainerVMT *)gh->vmt)->LeftBorder(gh) - ((const gcontainerVMT *)gh->vmt)->RightBorder(gh);
|
|
|
|
}
|
|
|
|
|
2018-07-08 00:54:19 +00:00
|
|
|
gCoord gwinGetInnerHeight(GHandle gh) {
|
2014-05-11 10:11:16 +00:00
|
|
|
if (!(gh->flags & GWIN_FLG_CONTAINER))
|
|
|
|
return 0;
|
|
|
|
return gh->height - ((const gcontainerVMT *)gh->vmt)->TopBorder(gh) - ((const gcontainerVMT *)gh->vmt)->BottomBorder(gh);
|
|
|
|
}
|
|
|
|
|
2014-05-09 15:11:30 +00:00
|
|
|
#endif /* GFX_USE_GWIN && GWIN_NEED_CONTAINERS */
|
2014-05-10 08:20:05 +00:00
|
|
|
|
|
|
|
/*-----------------------------------------------
|
|
|
|
* The simplest container type - a container
|
|
|
|
*-----------------------------------------------
|
|
|
|
*
|
|
|
|
* @defgroup Containers Containers
|
|
|
|
* @ingroup GWIN
|
|
|
|
*
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
|
|
|
|
#if GFX_USE_GWIN && GWIN_NEED_CONTAINER
|
|
|
|
|
2014-05-11 10:11:16 +00:00
|
|
|
#if GWIN_CONTAINER_BORDER != GWIN_FIRST_CONTROL_FLAG
|
|
|
|
#error "GWIN Container: - Flag definitions don't match"
|
|
|
|
#endif
|
|
|
|
|
2014-08-16 13:35:50 +00:00
|
|
|
#define BORDER_WIDTH 2
|
2014-05-11 10:11:16 +00:00
|
|
|
|
2018-07-08 00:54:19 +00:00
|
|
|
static gCoord ContainerBorderSize(GHandle gh) { return (gh->flags & GWIN_CONTAINER_BORDER) ? BORDER_WIDTH : 0; }
|
2014-05-10 08:20:05 +00:00
|
|
|
|
|
|
|
// The container VMT table
|
|
|
|
static const gcontainerVMT containerVMT = {
|
|
|
|
{
|
|
|
|
{
|
|
|
|
"Container", // The classname
|
|
|
|
sizeof(GContainerObject), // The object size
|
|
|
|
_gcontainerDestroy, // The destroy routine
|
|
|
|
_gcontainerRedraw, // The redraw routine
|
|
|
|
0, // The after-clear routine
|
|
|
|
},
|
2014-08-16 13:35:50 +00:00
|
|
|
gwinContainerDraw_Std, // The default drawing routine
|
2014-05-10 08:20:05 +00:00
|
|
|
#if GINPUT_NEED_MOUSE
|
|
|
|
{
|
|
|
|
0, 0, 0, // No mouse
|
|
|
|
},
|
|
|
|
#endif
|
2015-08-16 14:18:54 +00:00
|
|
|
#if GINPUT_NEED_KEYBOARD || GWIN_NEED_KEYBOARD
|
2015-08-12 15:32:38 +00:00
|
|
|
{
|
|
|
|
0 // Process keyboard events
|
|
|
|
},
|
|
|
|
#endif
|
2014-05-10 08:20:05 +00:00
|
|
|
#if GINPUT_NEED_TOGGLE
|
|
|
|
{
|
|
|
|
0, 0, 0, 0, 0, // No toggles
|
|
|
|
},
|
|
|
|
#endif
|
|
|
|
#if GINPUT_NEED_DIAL
|
|
|
|
{
|
|
|
|
0, 0, 0, 0, // No dials
|
|
|
|
},
|
|
|
|
#endif
|
|
|
|
},
|
2015-06-08 04:14:40 +00:00
|
|
|
ContainerBorderSize, // The size of the left border (mandatory)
|
|
|
|
ContainerBorderSize, // The size of the top border (mandatory)
|
|
|
|
ContainerBorderSize, // The size of the right border (mandatory)
|
|
|
|
ContainerBorderSize, // The size of the bottom border (mandatory)
|
2014-05-10 08:20:05 +00:00
|
|
|
0, // A child has been added (optional)
|
|
|
|
0, // A child has been deleted (optional)
|
|
|
|
};
|
|
|
|
|
2018-11-03 00:51:23 +00:00
|
|
|
GHandle gwinGContainerCreate(GDisplay *g, GContainerObject *gc, const GWidgetInit *pInit, gU32 flags) {
|
2014-05-11 10:11:16 +00:00
|
|
|
if (!(gc = (GContainerObject *)_gcontainerCreate(g, gc, pInit, &containerVMT)))
|
2014-05-10 08:20:05 +00:00
|
|
|
return 0;
|
|
|
|
|
2014-08-16 13:35:50 +00:00
|
|
|
gc->g.flags |= (flags & GWIN_CONTAINER_BORDER);
|
2014-05-11 10:11:16 +00:00
|
|
|
|
|
|
|
gwinSetVisible((GHandle)gc, pInit->g.show);
|
|
|
|
return (GHandle)gc;
|
2014-05-10 08:20:05 +00:00
|
|
|
}
|
|
|
|
|
2014-08-16 13:35:50 +00:00
|
|
|
void gwinContainerDraw_Transparent(GWidgetObject *gw, void *param) {
|
|
|
|
(void)param;
|
|
|
|
|
|
|
|
if (gw->g.vmt != (gwinVMT *)&containerVMT)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if ((gw->g.flags & GWIN_CONTAINER_BORDER))
|
|
|
|
gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, (gw->g.flags & GWIN_FLG_SYSENABLED) ? gw->pstyle->enabled.edge : gw->pstyle->disabled.edge);
|
|
|
|
|
|
|
|
// Don't touch the client area
|
|
|
|
}
|
|
|
|
|
|
|
|
void gwinContainerDraw_Std(GWidgetObject *gw, void *param) {
|
|
|
|
(void)param;
|
|
|
|
|
|
|
|
if (gw->g.vmt != (gwinVMT *)&containerVMT)
|
|
|
|
return;
|
|
|
|
|
|
|
|
gdispGFillArea(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, gw->pstyle->background);
|
|
|
|
gwinContainerDraw_Transparent(gw, param);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if GDISP_NEED_IMAGE
|
|
|
|
void gwinContainerDraw_Image(GWidgetObject *gw, void *param) {
|
2019-04-10 15:33:15 +00:00
|
|
|
#define gi ((gImage *)param)
|
2018-07-08 00:54:19 +00:00
|
|
|
gCoord x, y, iw, ih, mx, my;
|
2014-08-16 13:35:50 +00:00
|
|
|
|
|
|
|
if (gw->g.vmt != (gwinVMT *)&containerVMT)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Draw the frame
|
|
|
|
gwinContainerDraw_Transparent(gw, param);
|
|
|
|
|
|
|
|
// Draw the client area by tiling the image
|
|
|
|
mx = gw->g.x+gw->g.width;
|
|
|
|
my = gw->g.y+gw->g.height;
|
|
|
|
y = gw->g.y;
|
|
|
|
if ((gw->g.flags & GWIN_CONTAINER_BORDER)) {
|
|
|
|
mx--;
|
|
|
|
my--;
|
|
|
|
y++;
|
|
|
|
}
|
|
|
|
for(ih=gi->height; y < my; y += ih) {
|
|
|
|
if (ih > my - y)
|
|
|
|
ih = my - y;
|
|
|
|
x = gw->g.x;
|
|
|
|
if ((gw->g.flags & GWIN_CONTAINER_BORDER))
|
|
|
|
x++;
|
|
|
|
for(iw=gi->width; x < mx; x += iw) {
|
|
|
|
if (iw > mx - x)
|
|
|
|
iw = mx - x;
|
2015-02-28 02:05:04 +00:00
|
|
|
gdispGImageDraw(gw->g.display, gi, x, y, iw, ih, 0, 0);
|
2014-08-16 13:35:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef gi
|
|
|
|
}
|
2021-04-13 16:32:47 +00:00
|
|
|
#endif /* GDISP_NEED_IMAGE */
|
2014-08-16 13:35:50 +00:00
|
|
|
|
2021-04-13 16:32:47 +00:00
|
|
|
#endif /* GFX_USE_GWIN && GWIN_NEED_CONTAINERS */
|
|
|
|
|
|
|
|
/** @} */
|