From 0638a58e1640511a0afd57ea373b9b140cca3533 Mon Sep 17 00:00:00 2001 From: Martin Preuss Date: Sat, 18 Nov 2023 17:02:30 +0100 Subject: [PATCH] Added common code for layouting. --- src/lib/aqdiagram/placement/0BUILD | 4 + src/lib/aqdiagram/placement/layout.c | 196 ++++++++++++++++++++++++ src/lib/aqdiagram/placement/layout.h | 48 ++++++ src/lib/aqdiagram/placement/o_hlayout.h | 4 +- src/lib/aqdiagram/placement/o_layout.c | 189 +++++++++++++++++++++++ src/lib/aqdiagram/placement/o_layout.h | 32 ++++ 6 files changed, 471 insertions(+), 2 deletions(-) create mode 100644 src/lib/aqdiagram/placement/layout.c create mode 100644 src/lib/aqdiagram/placement/layout.h create mode 100644 src/lib/aqdiagram/placement/o_layout.c create mode 100644 src/lib/aqdiagram/placement/o_layout.h diff --git a/src/lib/aqdiagram/placement/0BUILD b/src/lib/aqdiagram/placement/0BUILD index f769747..52c7176 100644 --- a/src/lib/aqdiagram/placement/0BUILD +++ b/src/lib/aqdiagram/placement/0BUILD @@ -61,6 +61,8 @@ + layout.h + o_layout.h o_hlayout.h o_hlayout-t.h @@ -73,6 +75,8 @@ $(local/typefiles) + layout.c + o_layout.c o_hlayout.c o_hlayout-t.c diff --git a/src/lib/aqdiagram/placement/layout.c b/src/lib/aqdiagram/placement/layout.c new file mode 100644 index 0000000..807e545 --- /dev/null +++ b/src/lib/aqdiagram/placement/layout.c @@ -0,0 +1,196 @@ +/**************************************************************************** + * 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 "./layout.h" + + +static int _getSumOfElementWidths(const AQDG_PLACEMENT_LAYOUT_ELEMENT *ptrElements, int numElements); +static int _getStretchableElements(const AQDG_PLACEMENT_LAYOUT_ELEMENT *ptrElements, int numElements); +static int _getMaxElementWidth(const AQDG_PLACEMENT_LAYOUT_ELEMENT *ptrElements, int numElements); +static void _placeAndStretch(AQDG_PLACEMENT_LAYOUT_ELEMENT *ptrElements, int numElements, int borderBegin, int spacing, int stretch); +static void _placeAndStretchWithEqualLength(AQDG_PLACEMENT_LAYOUT_ELEMENT *ptrElements, int numElements, + int borderBegin, int spacing, int itemLength, int stretch); +static void _place(AQDG_PLACEMENT_LAYOUT_ELEMENT *ptrElements, int numElements, int borderBegin, int spacing); + + + + +void AQDG_Placement_LayoutAndStretch(AQDG_PLACEMENT_LAYOUT_ELEMENT *ptrElements, int numElements, + int destLength, int borderBegin, int borderEnd, int spacing) +{ + if (numElements) { + int w; + int stretchables; + + w=borderBegin+_getSumOfElementWidths(ptrElements, numElements)+borderEnd+(numElements-1)*spacing; + stretchables=_getStretchableElements(ptrElements, numElements); + if (stretchables && w0)?stretch:0); + } +} + + + +void AQDG_Placement_LayoutSecondaryAxis(AQDG_PLACEMENT_LAYOUT_ELEMENT *ptrElements, int numElements, + int destLength, int borderBegin, int borderEnd) +{ + if (numElements) { + int i; + int rawLength; + AQDG_PLACEMENT_LAYOUT_ELEMENT *ptr; + + rawLength=destLength-borderBegin-borderEnd; + ptr=ptrElements; + for (i=0; iopts & AQDG_PLACEMENT_LAYOUT_ELEMENT_OPTS_RIGHT) { + pos=destLength-borderEnd-ptr->length; + } + else if (ptr->opts & AQDG_PLACEMENT_LAYOUT_ELEMENT_OPTS_CENTER) { + pos=borderBegin+(rawLength-ptr->length)/2; + } + else + pos=borderBegin; + + ptr->pos=(pos>borderBegin)?pos:borderBegin; + ptr++; + } + } +} + + + + + + +int _getSumOfElementWidths(const AQDG_PLACEMENT_LAYOUT_ELEMENT *ptrElements, int numElements) +{ + int i; + int w=0; + + for (i=0; ilength; + return w; +} + + + +int _getStretchableElements(const AQDG_PLACEMENT_LAYOUT_ELEMENT *ptrElements, int numElements) +{ + int i; + int n=0; + + for (i=0; iopts) & AQDG_PLACEMENT_LAYOUT_ELEMENT_OPTS_STRETCH) + n++; + return n; +} + + + +int _getMaxElementWidth(const AQDG_PLACEMENT_LAYOUT_ELEMENT *ptrElements, int numElements) +{ + int i; + int w=-1; + + for (i=0; ilength>w)?(ptrElements->length):w; + ptrElements++; + } + return w; +} + + + +void _placeAndStretch(AQDG_PLACEMENT_LAYOUT_ELEMENT *ptrElements, int numElements, int borderBegin, int spacing, int stretch) +{ + int i; + int pos=0; + AQDG_PLACEMENT_LAYOUT_ELEMENT *ptr; + + pos=borderBegin; + ptr=ptrElements; + for (i=0; ipos=pos; + if (ptr->opts & AQDG_PLACEMENT_LAYOUT_ELEMENT_OPTS_STRETCH) + ptr->length+=stretch; + pos+=ptr->length+spacing; + ptr++; + } +} + + + +void _placeAndStretchWithEqualLength(AQDG_PLACEMENT_LAYOUT_ELEMENT *ptrElements, int numElements, + int borderBegin, int spacing, int itemLength, int stretch) +{ + int i; + int pos=0; + AQDG_PLACEMENT_LAYOUT_ELEMENT *ptr; + + pos=borderBegin; + ptr=ptrElements; + for (i=0; ipos=pos; + ptr->length=itemLength; + pos+=itemLength+spacing+stretch; + ptr++; + } +} + + + +void _place(AQDG_PLACEMENT_LAYOUT_ELEMENT *ptrElements, int numElements, int borderBegin, int spacing) +{ + int i; + int pos=0; + AQDG_PLACEMENT_LAYOUT_ELEMENT *ptr; + + pos=borderBegin; + ptr=ptrElements; + for (i=0; ipos=pos; + pos+=ptr->length+spacing; + ptr++; + } +} + + + diff --git a/src/lib/aqdiagram/placement/layout.h b/src/lib/aqdiagram/placement/layout.h new file mode 100644 index 0000000..8fbf64c --- /dev/null +++ b/src/lib/aqdiagram/placement/layout.h @@ -0,0 +1,48 @@ +/**************************************************************************** + * 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_LAYOUT_H +#define AQDG_PLACEMENT_LAYOUT_H + +#include + +#include + + + +#define AQDG_PLACEMENT_LAYOUT_ELEMENT_OPTS_STRETCH 0x0001 +#define AQDG_PLACEMENT_LAYOUT_ELEMENT_OPTS_CENTER 0x0002 +#define AQDG_PLACEMENT_LAYOUT_ELEMENT_OPTS_RIGHT 0x0004 + + + + +typedef struct AQDG_PLACEMENT_LAYOUT_ELEMENT AQDG_PLACEMENT_LAYOUT_ELEMENT; +struct AQDG_PLACEMENT_LAYOUT_ELEMENT { + int pos; + int length; + uint32_t opts; +}; + + + + +AQDG_API void AQDG_Placement_LayoutAndStretch(AQDG_PLACEMENT_LAYOUT_ELEMENT *ptrElements, int numElements, + int destLength, int borderBegin, int borderEnd, int spacing); + +AQDG_API void AQDG_Placement_LayoutWithEqualLength(AQDG_PLACEMENT_LAYOUT_ELEMENT *ptrElements, int numElements, + int destLength, int borderBegin, int borderEnd, int spacing); + +AQDG_API void AQDG_Placement_LayoutSecondaryAxis(AQDG_PLACEMENT_LAYOUT_ELEMENT *ptrElements, int numElements, + int destLength, int borderBegin, int borderEnd); + + + +#endif + + diff --git a/src/lib/aqdiagram/placement/o_hlayout.h b/src/lib/aqdiagram/placement/o_hlayout.h index a23ff71..50a5399 100644 --- a/src/lib/aqdiagram/placement/o_hlayout.h +++ b/src/lib/aqdiagram/placement/o_hlayout.h @@ -6,8 +6,8 @@ * should have received along with this file. ****************************************************************************/ -#ifndef AQDG_PLACEMENT_O_LAYOUT_H -#define AQDG_PLACEMENT_O_LAYOUT_H +#ifndef AQDG_PLACEMENT_O_HLAYOUT_H +#define AQDG_PLACEMENT_O_HLAYOUT_H #include diff --git a/src/lib/aqdiagram/placement/o_layout.c b/src/lib/aqdiagram/placement/o_layout.c new file mode 100644 index 0000000..958b51f --- /dev/null +++ b/src/lib/aqdiagram/placement/o_layout.c @@ -0,0 +1,189 @@ +/**************************************************************************** + * 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_layout.h" + + + +/* ------------------------------------------------------------------------------------------------ + * forward declarations + * ------------------------------------------------------------------------------------------------ + */ + +static void _setElementFromObjectX(AQDG_PLACEMENT_LAYOUT_ELEMENT *eptr, const AQDG_OBJECT *object); +static void _setElementFromObjectY(AQDG_PLACEMENT_LAYOUT_ELEMENT *eptr, const AQDG_OBJECT *object); +static void _setObjectFromElementX(AQDG_OBJECT *object, const AQDG_PLACEMENT_LAYOUT_ELEMENT *eptr); +static void _setObjectFromElementY(AQDG_OBJECT *object, const AQDG_PLACEMENT_LAYOUT_ELEMENT *eptr); + + + +/* ------------------------------------------------------------------------------------------------ + * implementations + * ------------------------------------------------------------------------------------------------ + */ + + +int AQDG_LayoutObject_CountDirectChildren(const AQDG_OBJECT *object) +{ + int c=0; + const AQDG_OBJECT *child; + + child=AQDG_Object_Tree2_GetFirstChild(object); + while(child) { + c++; + child=AQDG_Object_Tree2_GetNext(child); + } + + return c; +} + + + +AQDG_PLACEMENT_LAYOUT_ELEMENT *AQDG_LayoutObject_Children2ElementsX(const AQDG_OBJECT *object, int num) +{ + if (num) { + AQDG_PLACEMENT_LAYOUT_ELEMENT *elements; + + elements=(AQDG_PLACEMENT_LAYOUT_ELEMENT*) malloc(num*sizeof(AQDG_PLACEMENT_LAYOUT_ELEMENT)); + if (elements) { + const AQDG_OBJECT *child; + AQDG_PLACEMENT_LAYOUT_ELEMENT *eptr; + + eptr=elements; + child=AQDG_Object_Tree2_GetFirstChild(object); + while(child && num) { + _setElementFromObjectX(eptr, object); + child=AQDG_Object_Tree2_GetNext(child); + eptr++; + num--; + } + return elements; + } + } + + return NULL; +} + + + +AQDG_PLACEMENT_LAYOUT_ELEMENT *AQDG_LayoutObject_Children2ElementsY(const AQDG_OBJECT *object, int num) +{ + if (num) { + AQDG_PLACEMENT_LAYOUT_ELEMENT *elements; + + elements=(AQDG_PLACEMENT_LAYOUT_ELEMENT*) malloc(num*sizeof(AQDG_PLACEMENT_LAYOUT_ELEMENT)); + if (elements) { + const AQDG_OBJECT *child; + AQDG_PLACEMENT_LAYOUT_ELEMENT *eptr; + + eptr=elements; + child=AQDG_Object_Tree2_GetFirstChild(object); + while(child && num) { + _setElementFromObjectY(eptr, object); + child=AQDG_Object_Tree2_GetNext(child); + eptr++; + num--; + } + return elements; + } + } + + return NULL; +} + + + +void AQDG_LayoutObject_ChildrenFromElementsX(AQDG_OBJECT *object, const AQDG_PLACEMENT_LAYOUT_ELEMENT *elements, int num) +{ + if (num && elements) { + AQDG_OBJECT *child; + const AQDG_PLACEMENT_LAYOUT_ELEMENT *eptr; + + eptr=elements; + child=AQDG_Object_Tree2_GetFirstChild(object); + while(child && num) { + _setObjectFromElementX(child, eptr); + eptr++; + num--; + child=AQDG_Object_Tree2_GetNext(child); + } + } +} + + + +void AQDG_LayoutObject_ChildrenFromElementsY(AQDG_OBJECT *object, const AQDG_PLACEMENT_LAYOUT_ELEMENT *elements, int num) +{ + if (num && elements) { + AQDG_OBJECT *child; + const AQDG_PLACEMENT_LAYOUT_ELEMENT *eptr; + + eptr=elements; + child=AQDG_Object_Tree2_GetFirstChild(object); + while(child && num) { + _setObjectFromElementY(child, eptr); + eptr++; + num--; + child=AQDG_Object_Tree2_GetNext(child); + } + } +} + + + +void _setElementFromObjectX(AQDG_PLACEMENT_LAYOUT_ELEMENT *eptr, const AQDG_OBJECT *object) +{ + uint32_t opts; + + opts=AQDG_Object_GetOptions(object); + eptr->pos=0; + eptr->length=AQDG_Object_GetWidth(object); + eptr->opts=(opts & AQDG_OBJECT_OPTIONS_STRETCHX)?AQDG_PLACEMENT_LAYOUT_ELEMENT_OPTS_STRETCH:0; + eptr->opts|=(opts & AQDG_OBJECT_OPTIONS_HALIGNCENTER)?AQDG_PLACEMENT_LAYOUT_ELEMENT_OPTS_CENTER:0; + eptr->opts|=(opts & AQDG_OBJECT_OPTIONS_HALIGNRIGHT)?AQDG_PLACEMENT_LAYOUT_ELEMENT_OPTS_RIGHT:0; +} + + + +void _setElementFromObjectY(AQDG_PLACEMENT_LAYOUT_ELEMENT *eptr, const AQDG_OBJECT *object) +{ + uint32_t opts; + + opts=AQDG_Object_GetOptions(object); + eptr->pos=0; + eptr->length=AQDG_Object_GetHeight(object); + eptr->opts=(opts & AQDG_OBJECT_OPTIONS_STRETCHY)?AQDG_PLACEMENT_LAYOUT_ELEMENT_OPTS_STRETCH:0; + eptr->opts|=(opts & AQDG_OBJECT_OPTIONS_VALIGNCENTER)?AQDG_PLACEMENT_LAYOUT_ELEMENT_OPTS_CENTER:0; + eptr->opts|=(opts & AQDG_OBJECT_OPTIONS_VALIGNBOTTOM)?AQDG_PLACEMENT_LAYOUT_ELEMENT_OPTS_RIGHT:0; +} + + + +void _setObjectFromElementX(AQDG_OBJECT *object, const AQDG_PLACEMENT_LAYOUT_ELEMENT *eptr) +{ + AQDG_Object_SetRelativeX(object, eptr->pos); + AQDG_Object_SetWidth(object, eptr->length); +} + + + +void _setObjectFromElementY(AQDG_OBJECT *object, const AQDG_PLACEMENT_LAYOUT_ELEMENT *eptr) +{ + AQDG_Object_SetRelativeY(object, eptr->pos); + AQDG_Object_SetHeight(object, eptr->length); +} + + + + + + diff --git a/src/lib/aqdiagram/placement/o_layout.h b/src/lib/aqdiagram/placement/o_layout.h new file mode 100644 index 0000000..fac4325 --- /dev/null +++ b/src/lib/aqdiagram/placement/o_layout.h @@ -0,0 +1,32 @@ +/**************************************************************************** + * 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 +#include + + + +AQDG_API int AQDG_LayoutObject_CountDirectChildren(const AQDG_OBJECT *object); + +AQDG_API AQDG_PLACEMENT_LAYOUT_ELEMENT *AQDG_LayoutObject_Children2ElementsX(const AQDG_OBJECT *object, int num); +AQDG_API AQDG_PLACEMENT_LAYOUT_ELEMENT *AQDG_LayoutObject_Children2ElementsY(const AQDG_OBJECT *object, int num); +AQDG_API void AQDG_LayoutObject_ChildrenFromElementsX(AQDG_OBJECT *object, const AQDG_PLACEMENT_LAYOUT_ELEMENT *elements, int num); +AQDG_API void AQDG_LayoutObject_ChildrenFromElementsY(AQDG_OBJECT *object, const AQDG_PLACEMENT_LAYOUT_ELEMENT *elements, int num); + + + + + + +#endif +