diff --git a/src/lib/aqdiagram/placement/0BUILD b/src/lib/aqdiagram/placement/0BUILD index 73f0952..f769747 100644 --- a/src/lib/aqdiagram/placement/0BUILD +++ b/src/lib/aqdiagram/placement/0BUILD @@ -61,6 +61,8 @@ + o_hlayout.h + o_hlayout-t.h @@ -70,6 +72,9 @@ $(local/typefiles) + + o_hlayout.c + o_hlayout-t.c diff --git a/src/lib/aqdiagram/placement/o_hlayout-t.c b/src/lib/aqdiagram/placement/o_hlayout-t.c new file mode 100644 index 0000000..f5f4d7c --- /dev/null +++ b/src/lib/aqdiagram/placement/o_hlayout-t.c @@ -0,0 +1,201 @@ +/**************************************************************************** + * This file is part of the project AqDiagram. + * AqDiagram (c) by 2023 Martin Preuss, all rights reserved. + * + * The license for this file can be found in the file COPYING which you + * should have received along with this file. + ****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "o_hlayout-t.h" +#include "o_hlayout.h" + +#include + +#include + + + +#ifdef AQDIAGRAM_ENABLE_TESTCODE + + + +/* ------------------------------------------------------------------------------------------------ + * forward declarations + * ------------------------------------------------------------------------------------------------ + */ + +static int GWENHYWFAR_CB test1(GWEN_TEST_MODULE *mod); + +static AQDG_OBJECT *_createBox10x10(uint32_t opts); +static int _boxGetDefaultWidth10(AQDG_OBJECT *object); +static int _boxGetDefaultHeight10(AQDG_OBJECT *object); + + + +/* ------------------------------------------------------------------------------------------------ + * implementations + * ------------------------------------------------------------------------------------------------ + */ + +int AQDG_HLayoutObject_AddTests(GWEN_TEST_MODULE *mod) +{ + GWEN_TEST_MODULE *newMod; + + newMod=GWEN_Test_Module_AddModule(mod, "AQDG_HLayoutObject", NULL); + + GWEN_Test_Module_AddTest(newMod, "test1", test1, NULL); + + return 0; +} + + + +int test1(GWEN_UNUSED GWEN_TEST_MODULE *mod) +{ + AQDG_OBJECT *hlayout; + AQDG_OBJECT *box1; + AQDG_OBJECT *box2; + AQDG_OBJECT *box3; + int x; + int y; + int w; + int h; + int errors=0; + + hlayout=AQDG_HLayoutObject_new(NULL, 0); + AQDG_Object_SetWidth(hlayout, 100); + AQDG_Object_SetHeight(hlayout, 50); + AQDG_Object_SetBorderLeft(hlayout, 2); + AQDG_Object_SetBorderRight(hlayout, 4); + AQDG_Object_SetBorderTop(hlayout, 3); + AQDG_Object_SetBorderBottom(hlayout, 5); + AQDG_Object_SetHSpacing(hlayout, 2); + AQDG_Object_SetVSpacing(hlayout, 3); + + box1=_createBox10x10(AQDG_OBJECT_OPTIONS_STRETCHY); + AQDG_Object_Tree2_AddChild(hlayout, box1); + + box2=_createBox10x10(AQDG_OBJECT_OPTIONS_STRETCHX | AQDG_OBJECT_OPTIONS_VALIGNCENTER); + AQDG_Object_Tree2_AddChild(hlayout, box2); + + box3=_createBox10x10(AQDG_OBJECT_OPTIONS_VALIGNBOTTOM); + AQDG_Object_Tree2_AddChild(hlayout, box3); + + AQDG_Object_Layout(hlayout); + + x=AQDG_Object_GetRelativeX(box1); + y=AQDG_Object_GetRelativeY(box1); + w=AQDG_Object_GetWidth(box1); + h=AQDG_Object_GetHeight(box1); + DBG_INFO(AQDG_LOGDOMAIN, "x=%d, y=%d, w=%d, h=%d", x, y, w, h); + if (x!=2) { + DBG_ERROR(AQDG_LOGDOMAIN, "X of box 1 is not 2 (%d)", x); + errors++; + } + if (w!=10) { + DBG_ERROR(AQDG_LOGDOMAIN, "WIDTH of box 1 is not 10 (%d)", w); + errors++; + } + if (y!=3) { + DBG_ERROR(AQDG_LOGDOMAIN, "Y of box 1 is not 3 (%d)", y); + errors++; + } + if (h!=42) { + DBG_ERROR(AQDG_LOGDOMAIN, "HEIGHT of box 1 is not 42 (%d)", y); + errors++; + } + + x=AQDG_Object_GetRelativeX(box2); + y=AQDG_Object_GetRelativeY(box2); + w=AQDG_Object_GetWidth(box2); + h=AQDG_Object_GetHeight(box2); + DBG_INFO(AQDG_LOGDOMAIN, "x=%d, y=%d, w=%d, h=%d", x, y, w, h); + + if (x!=14) { + DBG_ERROR(AQDG_LOGDOMAIN, "X of box 2 is not 14 (%d)", x); + errors++; + } + if (w!=70) { + DBG_ERROR(AQDG_LOGDOMAIN, "WIDTH of box 2 is not 70 (%d)", w); + errors++; + } + if (y!=16) { + DBG_ERROR(AQDG_LOGDOMAIN, "Y of box 2 is not 16 (%d)", y); + errors++; + } + if (h!=10) { + DBG_ERROR(AQDG_LOGDOMAIN, "HEIGHT of box 2 is not 10 (%d)", y); + errors++; + } + + x=AQDG_Object_GetRelativeX(box3); + y=AQDG_Object_GetRelativeY(box3); + w=AQDG_Object_GetWidth(box3); + h=AQDG_Object_GetHeight(box3); + DBG_INFO(AQDG_LOGDOMAIN, "x=%d, y=%d, w=%d, h=%d", x, y, w, h); + if (x!=86) { + DBG_ERROR(AQDG_LOGDOMAIN, "X of box 3 is not 86 (%d)", x); + errors++; + } + if (w!=10) { + DBG_ERROR(AQDG_LOGDOMAIN, "WIDTH of box 3 is not 10 (%d)", w); + errors++; + } + if (y!=35) { + DBG_ERROR(AQDG_LOGDOMAIN, "Y of box 3 is not 35 (%d)", y); + errors++; + } + if (h!=10) { + DBG_ERROR(AQDG_LOGDOMAIN, "HEIGHT of box 3 is not 10 (%d)", y); + errors++; + } + + + return errors?GWEN_ERROR_GENERIC:0; +} + + + +AQDG_OBJECT *_createBox10x10(uint32_t opts) +{ + AQDG_OBJECT *box; + + box=AQDG_Object_new(); + AQDG_Object_SetOptions(box, opts); + AQDG_Object_SetGetDefaultWidthFn(box, _boxGetDefaultWidth10); + AQDG_Object_SetGetDefaultHeightFn(box, _boxGetDefaultHeight10); + return box; +} + + + +int _boxGetDefaultWidth10(AQDG_OBJECT *object) +{ + return 10; +} + + + +int _boxGetDefaultHeight10(AQDG_OBJECT *object) +{ + return 10; +} + + + + + +#else + +int AQDG_HLayoutObject_AddTests(GWEN_TEST_MODULE *mod) +{ + DBG_ERROR(GWEN_LOGDOMAIN, "AqDiagram was compiled without test code enabled."); + return GWEN_ERROR_GENERIC; +} + + +#endif diff --git a/src/lib/aqdiagram/placement/o_hlayout-t.h b/src/lib/aqdiagram/placement/o_hlayout-t.h new file mode 100644 index 0000000..a4c18e8 --- /dev/null +++ b/src/lib/aqdiagram/placement/o_hlayout-t.h @@ -0,0 +1,25 @@ +/**************************************************************************** + * This file is part of the project AqDiagram. + * AqDiagram (c) by 2023 Martin Preuss, all rights reserved. + * + * The license for this file can be found in the file COPYING which you + * should have received along with this file. + ****************************************************************************/ + +#ifndef AQDG_PLACEMENT_O_LAYOUT_T_H +#define AQDG_PLACEMENT_O_LAYOUT_T_H + +#include + +#include +#include + + + +AQDG_API int AQDG_HLayoutObject_AddTests(GWEN_TEST_MODULE *mod); + + + + +#endif + diff --git a/src/lib/aqdiagram/placement/o_hlayout.c b/src/lib/aqdiagram/placement/o_hlayout.c new file mode 100644 index 0000000..7441b97 --- /dev/null +++ b/src/lib/aqdiagram/placement/o_hlayout.c @@ -0,0 +1,154 @@ +/**************************************************************************** + * This file is part of the project AqDiagram. + * AqDiagram (c) by 2023 Martin Preuss, all rights reserved. + * + * The license for this file can be found in the file COPYING which you + * should have received along with this file. + ****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "o_hlayout.h" + + +/* ------------------------------------------------------------------------------------------------ + * forward declarations + * ------------------------------------------------------------------------------------------------ + */ + +static int _layout(AQDG_OBJECT *object); +static void _vAlignChild(AQDG_OBJECT *child, uint32_t childOpts, int parentHeight, int borderTop, int borderBottom); + + + +/* ------------------------------------------------------------------------------------------------ + * implementations + * ------------------------------------------------------------------------------------------------ + */ + +AQDG_OBJECT *AQDG_HLayoutObject_new(AQDG_OBJECT *parent, uint32_t options) +{ + AQDG_OBJECT *object; + + object=AQDG_Object_new(); + AQDG_Object_SetOptions(object, options); + + AQDG_Object_SetLayoutFn(object, _layout); + + if (parent) + AQDG_Object_Tree2_AddChild(parent, object); + return object; +} + + + + +int _layout(AQDG_OBJECT *object) +{ + AQDG_OBJECT *child; + int stretchables=0; + int minWidth; + int selfWidth; + int selfHeight; + int hSpacing; + int borderTop; + int borderBottom; + + selfWidth=AQDG_Object_GetWidth(object); + selfHeight=AQDG_Object_GetHeight(object); + borderTop=AQDG_Object_GetBorderTop(object); + borderBottom=AQDG_Object_GetBorderBottom(object); + hSpacing=AQDG_Object_GetHSpacing(object); + + minWidth=AQDG_Object_GetBorderLeft(object); + child=AQDG_Object_Tree2_GetFirstChild(object); + while(child) { + int childDefWidth; + uint32_t childOpts; + + childOpts=AQDG_Object_GetOptions(child); + AQDG_Object_SetRelativeX(child, minWidth); + + if (childOpts & AQDG_OBJECT_OPTIONS_FIXEDWIDTH) + childDefWidth=AQDG_Object_GetWidth(child); + else { + childDefWidth=AQDG_Object_GetDefaultWidth(child); + AQDG_Object_SetWidth(child, childDefWidth); + } + minWidth+=childDefWidth; + + _vAlignChild(child, childOpts, selfHeight, borderTop, borderBottom); + + if (childOpts & AQDG_OBJECT_OPTIONS_STRETCHX) + stretchables++; + + child=AQDG_Object_Tree2_GetNext(child); + if (child) + minWidth+=hSpacing; + } + minWidth+=AQDG_Object_GetBorderRight(object); + + if (stretchables && (selfWidth>minWidth)) { + int diffWidth; + int toAdd; + int pos; + + diffWidth=selfWidth-minWidth; + toAdd=diffWidth/stretchables; + + pos=AQDG_Object_GetBorderLeft(object); + child=AQDG_Object_Tree2_GetFirstChild(object); + while(child) { + int w; + + AQDG_Object_SetRelativeX(child, pos); + w=AQDG_Object_GetWidth(child); + if (AQDG_Object_GetOptions(child) & AQDG_OBJECT_OPTIONS_STRETCHX) { + w+=toAdd; + AQDG_Object_SetWidth(child, w); + } + pos+=w; + child=AQDG_Object_Tree2_GetNext(child); + if (child) + pos+=hSpacing; + } /* while */ + } + return 0; +} + + + +void _vAlignChild(AQDG_OBJECT *child, uint32_t childOpts, int parentHeight, int borderTop, int borderBottom) +{ + int childHeight; + int y; + int rawParentHeight; + + rawParentHeight=parentHeight-borderTop-borderBottom; + if (childOpts & AQDG_OBJECT_OPTIONS_FIXEDHEIGHT) + childHeight=AQDG_Object_GetHeight(child); + else { + if (childOpts & AQDG_OBJECT_OPTIONS_STRETCHY) + childHeight=rawParentHeight; + else + childHeight=AQDG_Object_GetDefaultHeight(child); + AQDG_Object_SetHeight(child, childHeight); + } + + if (childOpts & AQDG_OBJECT_OPTIONS_VALIGNBOTTOM) + y=parentHeight-borderBottom-childHeight; + else if (childOpts & AQDG_OBJECT_OPTIONS_VALIGNCENTER) + y=(rawParentHeight-childHeight)/2; + else + y=borderTop; + AQDG_Object_SetRelativeY(child, y); +} + + + + + + + diff --git a/src/lib/aqdiagram/placement/o_hlayout.h b/src/lib/aqdiagram/placement/o_hlayout.h new file mode 100644 index 0000000..a23ff71 --- /dev/null +++ b/src/lib/aqdiagram/placement/o_hlayout.h @@ -0,0 +1,24 @@ +/**************************************************************************** + * This file is part of the project AqDiagram. + * AqDiagram (c) by 2023 Martin Preuss, all rights reserved. + * + * The license for this file can be found in the file COPYING which you + * should have received along with this file. + ****************************************************************************/ + +#ifndef AQDG_PLACEMENT_O_LAYOUT_H +#define AQDG_PLACEMENT_O_LAYOUT_H + +#include + +#include + + + +AQDG_API AQDG_OBJECT *AQDG_HLayoutObject_new(AQDG_OBJECT *parent, uint32_t options); + + + + +#endif +