Added common code for layouting.
This commit is contained in:
@@ -61,6 +61,8 @@
|
||||
|
||||
|
||||
<headers dist="true" install="$(pkgincludedir)">
|
||||
layout.h
|
||||
o_layout.h
|
||||
o_hlayout.h
|
||||
o_hlayout-t.h
|
||||
</headers>
|
||||
@@ -73,6 +75,8 @@
|
||||
<sources>
|
||||
$(local/typefiles)
|
||||
|
||||
layout.c
|
||||
o_layout.c
|
||||
o_hlayout.c
|
||||
o_hlayout-t.c
|
||||
</sources>
|
||||
|
||||
196
src/lib/aqdiagram/placement/layout.c
Normal file
196
src/lib/aqdiagram/placement/layout.c
Normal file
@@ -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 <config.h>
|
||||
#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 && w<destLength) {
|
||||
int d;
|
||||
|
||||
d=(destLength-w)/stretchables;
|
||||
if (d)
|
||||
_placeAndStretch(ptrElements, numElements, borderBegin, spacing, d);
|
||||
else
|
||||
_place(ptrElements, numElements, borderBegin, spacing);
|
||||
}
|
||||
else
|
||||
_place(ptrElements, numElements, borderBegin, spacing);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQDG_Placement_LayoutWithEqualLength(AQDG_PLACEMENT_LAYOUT_ELEMENT *ptrElements, int numElements,
|
||||
int destLength, int borderBegin, int borderEnd, int spacing)
|
||||
{
|
||||
if (numElements) {
|
||||
int maxElementWidth;
|
||||
int w;
|
||||
int stretch=0;
|
||||
|
||||
maxElementWidth=_getMaxElementWidth(ptrElements, numElements);
|
||||
w=borderBegin+maxElementWidth+borderEnd+(numElements-1)*spacing;
|
||||
if (w<destLength)
|
||||
stretch=(destLength-w)/numElements;
|
||||
_placeAndStretchWithEqualLength(ptrElements, numElements, borderBegin, spacing, maxElementWidth, (stretch>0)?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; i<numElements; i++) {
|
||||
int pos;
|
||||
|
||||
if (ptr->opts & 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; i<numElements; i++)
|
||||
w+=(ptrElements++)->length;
|
||||
return w;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _getStretchableElements(const AQDG_PLACEMENT_LAYOUT_ELEMENT *ptrElements, int numElements)
|
||||
{
|
||||
int i;
|
||||
int n=0;
|
||||
|
||||
for (i=0; i<numElements; i++)
|
||||
if (((ptrElements++)->opts) & 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; i<numElements; i++) {
|
||||
w=(ptrElements->length>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; i<numElements; i++) {
|
||||
ptr->pos=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; i<numElements; i++) {
|
||||
ptr->pos=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; i<numElements; i++) {
|
||||
ptr->pos=pos;
|
||||
pos+=ptr->length+spacing;
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
48
src/lib/aqdiagram/placement/layout.h
Normal file
48
src/lib/aqdiagram/placement/layout.h
Normal file
@@ -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 <aqdiagram/aqdg_api.h>
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
|
||||
|
||||
#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
|
||||
|
||||
|
||||
@@ -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 <aqdiagram/aqdg_api.h>
|
||||
|
||||
|
||||
189
src/lib/aqdiagram/placement/o_layout.c
Normal file
189
src/lib/aqdiagram/placement/o_layout.c
Normal file
@@ -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 <config.h>
|
||||
#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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
32
src/lib/aqdiagram/placement/o_layout.h
Normal file
32
src/lib/aqdiagram/placement/o_layout.h
Normal file
@@ -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 <aqdiagram/aqdg_api.h>
|
||||
|
||||
#include <aqdiagram/placement/object.h>
|
||||
#include <aqdiagram/placement/layout.h>
|
||||
|
||||
|
||||
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user