added matrix layout object.

This commit is contained in:
Martin Preuss
2024-05-23 10:48:37 +02:00
parent ff72f5f0ce
commit ce9f34cfd4
6 changed files with 451 additions and 25 deletions

View File

@@ -66,6 +66,8 @@
o_hlayout.h o_hlayout.h
o_hlayout-t.h o_hlayout-t.h
o_vlayout.h o_vlayout.h
o_mlayout.h
o_mlayout_p.h
</headers> </headers>
@@ -81,6 +83,7 @@
o_hlayout.c o_hlayout.c
o_hlayout-t.c o_hlayout-t.c
o_vlayout.c o_vlayout.c
o_mlayout.c
</sources> </sources>

View File

@@ -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) 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; AQDG_PLACEMENT_LAYOUT_ELEMENT *elements;
elements=(AQDG_PLACEMENT_LAYOUT_ELEMENT*) malloc(num*sizeof(AQDG_PLACEMENT_LAYOUT_ELEMENT)); elements=(AQDG_PLACEMENT_LAYOUT_ELEMENT*) malloc(num*sizeof(AQDG_PLACEMENT_LAYOUT_ELEMENT));
if (elements) { if (elements) {
const AQDG_OBJECT *child;
AQDG_PLACEMENT_LAYOUT_ELEMENT *eptr; AQDG_PLACEMENT_LAYOUT_ELEMENT *eptr;
eptr=elements; eptr=elements;
child=AQDG_Object_Tree2_GetFirstChild(object); while(object && num) {
while(child && num) { _setElementFromObjectX(eptr, object);
_setElementFromObjectX(eptr, child); object=AQDG_Object_Tree2_GetNext(object);
child=AQDG_Object_Tree2_GetNext(child);
eptr++; eptr++;
num--; 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) 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; AQDG_PLACEMENT_LAYOUT_ELEMENT *elements;
elements=(AQDG_PLACEMENT_LAYOUT_ELEMENT*) malloc(num*sizeof(AQDG_PLACEMENT_LAYOUT_ELEMENT)); elements=(AQDG_PLACEMENT_LAYOUT_ELEMENT*) malloc(num*sizeof(AQDG_PLACEMENT_LAYOUT_ELEMENT));
if (elements) { if (elements) {
const AQDG_OBJECT *child;
AQDG_PLACEMENT_LAYOUT_ELEMENT *eptr; AQDG_PLACEMENT_LAYOUT_ELEMENT *eptr;
eptr=elements; eptr=elements;
child=AQDG_Object_Tree2_GetFirstChild(object); while(object && num) {
while(child && num) { _setElementFromObjectY(eptr, object);
_setElementFromObjectY(eptr, child); object=AQDG_Object_Tree2_GetNext(object);
child=AQDG_Object_Tree2_GetNext(child);
eptr++; eptr++;
num--; 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) void AQDG_LayoutObject_ChildrenFromElementsX(AQDG_OBJECT *object, const AQDG_PLACEMENT_LAYOUT_ELEMENT *elements, int num)
{ {
if (num && elements) { if (num && elements)
AQDG_OBJECT *child; 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; const AQDG_PLACEMENT_LAYOUT_ELEMENT *eptr;
eptr=elements; eptr=elements;
child=AQDG_Object_Tree2_GetFirstChild(object); while(object && num) {
while(child && num) { _setObjectFromElementX(object, eptr);
_setObjectFromElementX(child, eptr);
eptr++; eptr++;
num--; 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) void AQDG_LayoutObject_ChildrenFromElementsY(AQDG_OBJECT *object, const AQDG_PLACEMENT_LAYOUT_ELEMENT *elements, int num)
{ {
if (num && elements) { if (num && elements)
AQDG_OBJECT *child; 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; const AQDG_PLACEMENT_LAYOUT_ELEMENT *eptr;
eptr=elements; eptr=elements;
child=AQDG_Object_Tree2_GetFirstChild(object); while(object && num) {
while(child && num) { _setObjectFromElementY(object, eptr);
_setObjectFromElementY(child, eptr);
eptr++; eptr++;
num--; num--;
child=AQDG_Object_Tree2_GetNext(child); object=AQDG_Object_Tree2_GetNext(object);
} }
} }
} }

View File

@@ -19,9 +19,16 @@
AQDG_API int AQDG_LayoutObject_CountDirectChildren(const AQDG_OBJECT *object); 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_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_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_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_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_SetChildrenWidths(AQDG_OBJECT *object);
AQDG_API void AQDG_LayoutObject_SetChildrenHeights(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 #endif

View File

@@ -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 <config.h>
#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 && i<numElements) {
child=AQDG_Object_Tree2_GetNext(child);
i++;
}
}
}
void _layoutSecondaryX(AQDG_OBJECT *object, int numElements)
{
AQDG_OBJECT *child;
child=AQDG_Object_Tree2_GetFirstChild(object);
while(child) {
AQDG_PLACEMENT_LAYOUT_ELEMENT *ptrElements;
int i;
ptrElements=AQDG_LayoutObject_ObjectList2ElementsX(child, numElements);
AQDG_Placement_LayoutSecondaryAxis(ptrElements, numElements,
AQDG_Object_GetWidth(object),
AQDG_Object_GetBorderLeft(object),
AQDG_Object_GetBorderRight(object));
AQDG_LayoutObject_Elements2ObjectListX(child, ptrElements, numElements);
free(ptrElements);
i=0;
while(child && i<numElements) {
child=AQDG_Object_Tree2_GetNext(child);
i++;
}
}
}
AQDG_PLACEMENT_LAYOUT_ELEMENT *_mkEmptyElementList(int num)
{
if (num) {
AQDG_PLACEMENT_LAYOUT_ELEMENT *elements;
elements=(AQDG_PLACEMENT_LAYOUT_ELEMENT*) malloc(num*sizeof(AQDG_PLACEMENT_LAYOUT_ELEMENT));
if (elements) {
memset(elements, 0, num*sizeof(AQDG_PLACEMENT_LAYOUT_ELEMENT));
return elements;
}
}
return NULL;
}
void _mergeObjectsIntoElementsX(const AQDG_OBJECT *object, AQDG_PLACEMENT_LAYOUT_ELEMENT *ptrElements, int numElements)
{
const AQDG_OBJECT *child;
int i=0;
child=AQDG_Object_Tree2_GetFirstChild(object);
while(child) {
_mergeObjectXIntoElement(&ptrElements[i%numElements], child);
i++;
child=AQDG_Object_Tree2_GetNext(child);
}
}
void _mergeObjectsIntoElementsY(const AQDG_OBJECT *object, AQDG_PLACEMENT_LAYOUT_ELEMENT *ptrElements, int numElements)
{
const AQDG_OBJECT *child;
int i=0;
child=AQDG_Object_Tree2_GetFirstChild(object);
while(child) {
_mergeObjectYIntoElement(&ptrElements[i%numElements], child);
i++;
child=AQDG_Object_Tree2_GetNext(child);
}
}
void _mergeObjectXIntoElement(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_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);
}

View File

@@ -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 <aqdiagram/aqdg_api.h>
#include <aqdiagram/placement/object.h>
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

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_MLAYOUT_P_H
#define AQDG_PLACEMENT_O_MLAYOUT_P_H
#include <aqdiagram/aqdg_api.h>
#include <aqdiagram/placement/object.h>
typedef struct AQDG_OBJECT_MLAYOUT AQDG_OBJECT_MLAYOUT;
struct AQDG_OBJECT_MLAYOUT {
int numRowsOrColumns;
};
#endif