added placement object for horizontal layout

This commit is contained in:
Martin Preuss
2023-11-15 00:31:04 +01:00
parent 596a86984f
commit d6a32eaa30
5 changed files with 409 additions and 0 deletions

View File

@@ -61,6 +61,8 @@
<headers dist="true" install="$(pkgincludedir)">
o_hlayout.h
o_hlayout-t.h
</headers>
@@ -70,6 +72,9 @@
<sources>
$(local/typefiles)
o_hlayout.c
o_hlayout-t.c
</sources>

View File

@@ -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 <config.h>
#endif
#include "o_hlayout-t.h"
#include "o_hlayout.h"
#include <aqdiagram/aqdg_api.h>
#include <gwenhywfar/debug.h>
#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

View File

@@ -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 <aqdiagram/aqdg_api.h>
#include <gwenhywfar/gwenhywfarapi.h>
#include <gwenhywfar/testframework.h>
AQDG_API int AQDG_HLayoutObject_AddTests(GWEN_TEST_MODULE *mod);
#endif

View File

@@ -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 <config.h>
#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);
}

View File

@@ -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 <aqdiagram/aqdg_api.h>
#include <aqdiagram/placement/object.h>
AQDG_API AQDG_OBJECT *AQDG_HLayoutObject_new(AQDG_OBJECT *parent, uint32_t options);
#endif