From ce9f34cfd481418f6d5dc913839b4e9a741c1a73 Mon Sep 17 00:00:00 2001 From: Martin Preuss Date: Thu, 23 May 2024 10:48:37 +0200 Subject: [PATCH] added matrix layout object. --- src/lib/aqdiagram/placement/0BUILD | 3 + src/lib/aqdiagram/placement/o_layout.c | 74 +++-- src/lib/aqdiagram/placement/o_layout.h | 8 +- src/lib/aqdiagram/placement/o_mlayout.c | 343 ++++++++++++++++++++++ src/lib/aqdiagram/placement/o_mlayout.h | 23 ++ src/lib/aqdiagram/placement/o_mlayout_p.h | 25 ++ 6 files changed, 451 insertions(+), 25 deletions(-) create mode 100644 src/lib/aqdiagram/placement/o_mlayout.c create mode 100644 src/lib/aqdiagram/placement/o_mlayout.h create mode 100644 src/lib/aqdiagram/placement/o_mlayout_p.h diff --git a/src/lib/aqdiagram/placement/0BUILD b/src/lib/aqdiagram/placement/0BUILD index 005571a..81204ca 100644 --- a/src/lib/aqdiagram/placement/0BUILD +++ b/src/lib/aqdiagram/placement/0BUILD @@ -66,6 +66,8 @@ o_hlayout.h o_hlayout-t.h o_vlayout.h + o_mlayout.h + o_mlayout_p.h @@ -81,6 +83,7 @@ o_hlayout.c o_hlayout-t.c o_vlayout.c + o_mlayout.c diff --git a/src/lib/aqdiagram/placement/o_layout.c b/src/lib/aqdiagram/placement/o_layout.c index fb29db5..74fb533 100644 --- a/src/lib/aqdiagram/placement/o_layout.c +++ b/src/lib/aqdiagram/placement/o_layout.c @@ -50,19 +50,26 @@ int AQDG_LayoutObject_CountDirectChildren(const AQDG_OBJECT *object) AQDG_PLACEMENT_LAYOUT_ELEMENT *AQDG_LayoutObject_Children2ElementsX(const AQDG_OBJECT *object, int num) { - if (num) { + if (object && num) + return AQDG_LayoutObject_ObjectList2ElementsX(AQDG_Object_Tree2_GetFirstChild(object), num); + return NULL; +} + + + +AQDG_PLACEMENT_LAYOUT_ELEMENT *AQDG_LayoutObject_ObjectList2ElementsX(const AQDG_OBJECT *object, int num) +{ + if (object && 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, child); - child=AQDG_Object_Tree2_GetNext(child); + while(object && num) { + _setElementFromObjectX(eptr, object); + object=AQDG_Object_Tree2_GetNext(object); eptr++; num--; } @@ -77,19 +84,26 @@ AQDG_PLACEMENT_LAYOUT_ELEMENT *AQDG_LayoutObject_Children2ElementsX(const AQDG_O AQDG_PLACEMENT_LAYOUT_ELEMENT *AQDG_LayoutObject_Children2ElementsY(const AQDG_OBJECT *object, int num) { - if (num) { + if (object && num) + return AQDG_LayoutObject_ObjectList2ElementsY(AQDG_Object_Tree2_GetFirstChild(object), num); + return NULL; +} + + + +AQDG_PLACEMENT_LAYOUT_ELEMENT *AQDG_LayoutObject_ObjectList2ElementsY(const AQDG_OBJECT *object, int num) +{ + if (object && 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, child); - child=AQDG_Object_Tree2_GetNext(child); + while(object && num) { + _setElementFromObjectY(eptr, object); + object=AQDG_Object_Tree2_GetNext(object); eptr++; num--; } @@ -104,17 +118,23 @@ AQDG_PLACEMENT_LAYOUT_ELEMENT *AQDG_LayoutObject_Children2ElementsY(const AQDG_O void AQDG_LayoutObject_ChildrenFromElementsX(AQDG_OBJECT *object, const AQDG_PLACEMENT_LAYOUT_ELEMENT *elements, int num) { - if (num && elements) { - AQDG_OBJECT *child; + if (num && elements) + AQDG_LayoutObject_Elements2ObjectListX(AQDG_Object_Tree2_GetFirstChild(object), elements, num); +} + + + +void AQDG_LayoutObject_Elements2ObjectListX(AQDG_OBJECT *object, const AQDG_PLACEMENT_LAYOUT_ELEMENT *elements, int num) +{ + if (object && num && elements) { const AQDG_PLACEMENT_LAYOUT_ELEMENT *eptr; eptr=elements; - child=AQDG_Object_Tree2_GetFirstChild(object); - while(child && num) { - _setObjectFromElementX(child, eptr); + while(object && num) { + _setObjectFromElementX(object, eptr); eptr++; num--; - child=AQDG_Object_Tree2_GetNext(child); + object=AQDG_Object_Tree2_GetNext(object); } } } @@ -123,17 +143,23 @@ void AQDG_LayoutObject_ChildrenFromElementsX(AQDG_OBJECT *object, const AQDG_PLA void AQDG_LayoutObject_ChildrenFromElementsY(AQDG_OBJECT *object, const AQDG_PLACEMENT_LAYOUT_ELEMENT *elements, int num) { - if (num && elements) { - AQDG_OBJECT *child; + if (num && elements) + AQDG_LayoutObject_Elements2ObjectListY(AQDG_Object_Tree2_GetFirstChild(object), elements, num); +} + + + +void AQDG_LayoutObject_Elements2ObjectListY(AQDG_OBJECT *object, const AQDG_PLACEMENT_LAYOUT_ELEMENT *elements, int num) +{ + if (object && num && elements) { const AQDG_PLACEMENT_LAYOUT_ELEMENT *eptr; eptr=elements; - child=AQDG_Object_Tree2_GetFirstChild(object); - while(child && num) { - _setObjectFromElementY(child, eptr); + while(object && num) { + _setObjectFromElementY(object, eptr); eptr++; num--; - child=AQDG_Object_Tree2_GetNext(child); + object=AQDG_Object_Tree2_GetNext(object); } } } diff --git a/src/lib/aqdiagram/placement/o_layout.h b/src/lib/aqdiagram/placement/o_layout.h index 28918be..7abda35 100644 --- a/src/lib/aqdiagram/placement/o_layout.h +++ b/src/lib/aqdiagram/placement/o_layout.h @@ -19,9 +19,16 @@ 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_ObjectList2ElementsX(const AQDG_OBJECT *object, int num); + AQDG_API AQDG_PLACEMENT_LAYOUT_ELEMENT *AQDG_LayoutObject_Children2ElementsY(const AQDG_OBJECT *object, int num); +AQDG_API AQDG_PLACEMENT_LAYOUT_ELEMENT *AQDG_LayoutObject_ObjectList2ElementsY(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_Elements2ObjectListX(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); +AQDG_API void AQDG_LayoutObject_Elements2ObjectListY(AQDG_OBJECT *object, const AQDG_PLACEMENT_LAYOUT_ELEMENT *elements, int num); AQDG_API void AQDG_LayoutObject_SetChildrenWidths(AQDG_OBJECT *object); AQDG_API void AQDG_LayoutObject_SetChildrenHeights(AQDG_OBJECT *object); @@ -30,6 +37,5 @@ AQDG_API void AQDG_LayoutObject_SetChildrenHeights(AQDG_OBJECT *object); - #endif diff --git a/src/lib/aqdiagram/placement/o_mlayout.c b/src/lib/aqdiagram/placement/o_mlayout.c new file mode 100644 index 0000000..fc2dd8e --- /dev/null +++ b/src/lib/aqdiagram/placement/o_mlayout.c @@ -0,0 +1,343 @@ +/**************************************************************************** + * 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_mlayout_p.h" +#include "o_layout.h" + + +/* ------------------------------------------------------------------------------------------------ + * forward declarations + * ------------------------------------------------------------------------------------------------ + */ + +AQDG_OBJECT *_matrixLayoutObject_new(AQDG_OBJECT *parent, uint32_t options, int numRowsOrColumns); +static GWENHYWFAR_CB void _freeData(void *bp, void *p); +static int _layoutByRows(AQDG_OBJECT *object); +static int _layoutByColumns(AQDG_OBJECT *object); + +static void _layoutSecondaryY(AQDG_OBJECT *object, int numElements); +static void _layoutSecondaryX(AQDG_OBJECT *object, int numElements); +static AQDG_PLACEMENT_LAYOUT_ELEMENT *_mkEmptyElementList(int num); + +static void _mergeObjectsIntoElementsX(const AQDG_OBJECT *object, AQDG_PLACEMENT_LAYOUT_ELEMENT *ptrElements, int numElements); +static void _mergeObjectsIntoElementsY(const AQDG_OBJECT *object, AQDG_PLACEMENT_LAYOUT_ELEMENT *ptrElements, int numElements); + +static void _mergeObjectXIntoElement(AQDG_PLACEMENT_LAYOUT_ELEMENT *eptr, const AQDG_OBJECT *object); +static void _mergeObjectYIntoElement(AQDG_PLACEMENT_LAYOUT_ELEMENT *eptr, const AQDG_OBJECT *object); + +static void _setChildrenFromElementsX(AQDG_OBJECT *object, const AQDG_PLACEMENT_LAYOUT_ELEMENT *elements, int num); +static void _setChildrenFromElementsY(AQDG_OBJECT *object, const AQDG_PLACEMENT_LAYOUT_ELEMENT *elements, int num); +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 + * ------------------------------------------------------------------------------------------------ + */ + +GWEN_INHERIT(AQDG_OBJECT, AQDG_OBJECT_MLAYOUT); + + + +AQDG_OBJECT *AQDG_MatrixLayoutObjectByRows_new(AQDG_OBJECT *parent, uint32_t options, int columns) +{ + AQDG_OBJECT *object; + + object=_matrixLayoutObject_new(parent, options, columns); + AQDG_Object_SetLayoutFn(object, _layoutByRows); + return object; +} + + + +AQDG_OBJECT *AQDG_MatrixLayoutObjectByColumns_new(AQDG_OBJECT *parent, uint32_t options, int rows) +{ + AQDG_OBJECT *object; + + object=_matrixLayoutObject_new(parent, options, rows); + AQDG_Object_SetLayoutFn(object, _layoutByColumns); + return object; +} + + + + +AQDG_OBJECT *_matrixLayoutObject_new(AQDG_OBJECT *parent, uint32_t options, int numRowsOrColumns) +{ + AQDG_OBJECT *object; + AQDG_OBJECT_MLAYOUT *xo; + + object=AQDG_Object_new(); + GWEN_NEW_OBJECT(AQDG_OBJECT_MLAYOUT, xo); + GWEN_INHERIT_SETDATA(AQDG_OBJECT, AQDG_OBJECT_MLAYOUT, object, xo, _freeData); + + AQDG_Object_SetOptions(object, options); + xo->numRowsOrColumns=numRowsOrColumns; + + if (parent) + AQDG_Object_Tree2_AddChild(parent, object); + return object; +} + + + +GWENHYWFAR_CB void _freeData(void *bp, void *p) +{ +} + + + +int _layoutByRows(AQDG_OBJECT *object) +{ + AQDG_OBJECT_MLAYOUT *xo; + + xo=GWEN_INHERIT_GETDATA(AQDG_OBJECT, AQDG_OBJECT_MLAYOUT, object); + if (xo) { + AQDG_PLACEMENT_LAYOUT_ELEMENT *ptrElements; + int numElements; + + numElements=xo->numRowsOrColumns; + ptrElements=_mkEmptyElementList(numElements); + if (ptrElements) { + _mergeObjectsIntoElementsX(object, ptrElements, numElements); + AQDG_Placement_LayoutAndStretch(ptrElements, numElements, + AQDG_Object_GetWidth(object), + AQDG_Object_GetBorderLeft(object), + AQDG_Object_GetBorderRight(object), + AQDG_Object_GetHSpacing(object)); + _setChildrenFromElementsX(object, ptrElements, numElements); + free(ptrElements); + + _layoutSecondaryY(object, numElements); + } + } + return 0; +} + + + +int _layoutByColumns(AQDG_OBJECT *object) +{ + AQDG_OBJECT_MLAYOUT *xo; + + xo=GWEN_INHERIT_GETDATA(AQDG_OBJECT, AQDG_OBJECT_MLAYOUT, object); + if (xo) { + AQDG_PLACEMENT_LAYOUT_ELEMENT *ptrElements; + int numElements; + + numElements=xo->numRowsOrColumns; + ptrElements=_mkEmptyElementList(numElements); + if (ptrElements) { + _mergeObjectsIntoElementsY(object, ptrElements, numElements); + AQDG_Placement_LayoutAndStretch(ptrElements, numElements, + AQDG_Object_GetHeight(object), + AQDG_Object_GetBorderTop(object), + AQDG_Object_GetBorderBottom(object), + AQDG_Object_GetVSpacing(object)); + _setChildrenFromElementsY(object, ptrElements, numElements); + free(ptrElements); + + _layoutSecondaryX(object, numElements); + } + } + return 0; +} + + + +void _layoutSecondaryY(AQDG_OBJECT *object, int numElements) +{ + AQDG_OBJECT *child; + + child=AQDG_Object_Tree2_GetFirstChild(object); + while(child) { + AQDG_PLACEMENT_LAYOUT_ELEMENT *ptrElements; + int i; + + /* handle numElements */ + ptrElements=AQDG_LayoutObject_ObjectList2ElementsY(child, numElements); + AQDG_Placement_LayoutSecondaryAxis(ptrElements, numElements, + AQDG_Object_GetHeight(object), + AQDG_Object_GetBorderTop(object), + AQDG_Object_GetBorderBottom(object)); + AQDG_LayoutObject_Elements2ObjectListY(child, ptrElements, numElements); + free(ptrElements); + + /* skip numElements */ + i=0; + while(child && ipos=0; + len=AQDG_Object_GetWidth(object);; + eptr->length=(len>eptr->length)?len:(len>eptr->length); + 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 _mergeObjectYIntoElement(AQDG_PLACEMENT_LAYOUT_ELEMENT *eptr, const AQDG_OBJECT *object) +{ + uint32_t opts; + int len; + + opts=AQDG_Object_GetOptions(object); + eptr->pos=0; + len=AQDG_Object_GetHeight(object); + eptr->length=(len>eptr->length)?len:(len>eptr->length); + 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 _setChildrenFromElementsX(AQDG_OBJECT *object, const AQDG_PLACEMENT_LAYOUT_ELEMENT *elements, int num) +{ + if (num && elements) { + AQDG_OBJECT *child; + int i=0; + + child=AQDG_Object_Tree2_GetFirstChild(object); + while(child) { + _setObjectFromElementX(child, &elements[i%num]); + i++; + child=AQDG_Object_Tree2_GetNext(child); + } + } +} + + + +void _setChildrenFromElementsY(AQDG_OBJECT *object, const AQDG_PLACEMENT_LAYOUT_ELEMENT *elements, int num) +{ + if (num && elements) { + AQDG_OBJECT *child; + int i=0; + + child=AQDG_Object_Tree2_GetFirstChild(object); + while(child) { + _setObjectFromElementY(child, &elements[i%num]); + i++; + child=AQDG_Object_Tree2_GetNext(child); + } + } +} + + + +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_mlayout.h b/src/lib/aqdiagram/placement/o_mlayout.h new file mode 100644 index 0000000..1a26780 --- /dev/null +++ b/src/lib/aqdiagram/placement/o_mlayout.h @@ -0,0 +1,23 @@ +/**************************************************************************** + * 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_MLAYOUT_H +#define AQDG_PLACEMENT_O_MLAYOUT_H + +#include + +#include + + +AQDG_API AQDG_OBJECT *AQDG_MatrixLayoutObjectByRows_new(AQDG_OBJECT *parent, uint32_t options, int columns); +AQDG_API AQDG_OBJECT *AQDG_MatrixLayoutObjectByColumns_new(AQDG_OBJECT *parent, uint32_t options, int rows); + + + +#endif + diff --git a/src/lib/aqdiagram/placement/o_mlayout_p.h b/src/lib/aqdiagram/placement/o_mlayout_p.h new file mode 100644 index 0000000..3740750 --- /dev/null +++ b/src/lib/aqdiagram/placement/o_mlayout_p.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_MLAYOUT_P_H +#define AQDG_PLACEMENT_O_MLAYOUT_P_H + +#include + +#include + + +typedef struct AQDG_OBJECT_MLAYOUT AQDG_OBJECT_MLAYOUT; +struct AQDG_OBJECT_MLAYOUT { + int numRowsOrColumns; +}; + + + +#endif +