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
+