1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 //
3 // SPDX-FileCopyrightText: 2009 Bastian Holst <bastianholst@gmx.de>
4 //
5
6 // Self
7 #include "MarbleGraphicsGridLayout.h"
8
9 // Marble
10 #include "MarbleDebug.h"
11 #include "ScreenGraphicsItem.h"
12
13 // Qt
14 #include <QHash>
15 #include <QRectF>
16 #include <QSizeF>
17 #include <QVector>
18
19 namespace Marble
20 {
21
22 class MarbleGraphicsGridLayoutPrivate
23 {
24 public:
MarbleGraphicsGridLayoutPrivate(int rows,int columns)25 MarbleGraphicsGridLayoutPrivate( int rows, int columns )
26 : m_rows( rows ),
27 m_columns( columns ),
28 m_spacing( 0 ),
29 m_alignment( Qt::AlignLeft | Qt::AlignTop )
30 {
31 m_items = new ScreenGraphicsItem **[rows];
32 for ( int i = 0; i < rows; ++i ) {
33 m_items[i] = new ScreenGraphicsItem *[columns];
34 }
35 for ( int row = 0; row < rows; row++ ) {
36 for ( int column = 0; column < columns; column++ ) {
37 m_items[row][column] = nullptr;
38 }
39 }
40 }
41
~MarbleGraphicsGridLayoutPrivate()42 ~MarbleGraphicsGridLayoutPrivate()
43 {
44 for ( int i = 0; i < m_rows; ++i ) {
45 delete[] m_items[i];
46 }
47 delete[] m_items;
48 }
49
50 // A two dimensional array of pointers to ScreenGraphicsItems
51 ScreenGraphicsItem ***m_items;
52 int m_rows;
53 int m_columns;
54 int m_spacing;
55 Qt::Alignment m_alignment;
56 QHash<ScreenGraphicsItem*, Qt::Alignment> m_itemAlignment;
57 };
58
MarbleGraphicsGridLayout(int rows,int columns)59 MarbleGraphicsGridLayout::MarbleGraphicsGridLayout( int rows, int columns )
60 : d( new MarbleGraphicsGridLayoutPrivate( rows, columns ) )
61 {
62 }
63
~MarbleGraphicsGridLayout()64 MarbleGraphicsGridLayout::~MarbleGraphicsGridLayout()
65 {
66 delete d;
67 }
68
addItem(ScreenGraphicsItem * item,int row,int column)69 void MarbleGraphicsGridLayout::addItem( ScreenGraphicsItem *item, int row, int column )
70 {
71 if ( row < d->m_rows
72 && column < d->m_columns )
73 {
74 d->m_items[row][column] = item;
75 }
76 }
77
updatePositions(MarbleGraphicsItem * parent)78 void MarbleGraphicsGridLayout::updatePositions( MarbleGraphicsItem *parent )
79 {
80 // Initialize with 0.0
81 QVector<double> maxWidth( d->m_columns, 0.0 );
82 QVector<double> maxHeight( d->m_rows, 0.0 );
83
84 // Determining the cell sizes
85 for ( int row = 0; row < d->m_rows; row++ ) {
86 for ( int column = 0; column < d->m_columns; column++ ) {
87 if ( d->m_items[row][column] == nullptr ) {
88 continue;
89 }
90
91 QSizeF size = d->m_items[row][column]->size();
92 double width = size.width();
93 double height = size.height();
94
95 if ( width > maxWidth[column] ) {
96 maxWidth[column] = width;
97 }
98 if ( height > maxHeight[row] ) {
99 maxHeight[row] = height;
100 }
101 }
102 }
103
104 QVector<double> startX( d->m_columns );
105 QVector<double> endX( d->m_columns );
106 QVector<double> startY( d->m_rows );
107 QVector<double> endY( d->m_rows );
108 QRectF contentRect = parent->contentRect();
109
110 for ( int i = 0; i < d->m_columns; i++ ) {
111 if ( i == 0 ) {
112 startX[0] = contentRect.left();
113 }
114 else if ( maxWidth[i] == 0 ) {
115 startX[i] = endX[i-1];
116 }
117 else {
118 startX[i] = endX[i-1] + d->m_spacing;
119 }
120
121 endX[i] = startX[i] + maxWidth[i];
122 }
123
124 for ( int i = 0; i < d->m_rows; i++ ) {
125 if ( i == 0 ) {
126 startY[0] = contentRect.left();
127 }
128 else if ( maxHeight[i] == 0 ) {
129 startY[i] = endY[i-1];
130 }
131 else {
132 startY[i] = endY[i-1] + d->m_spacing;
133 }
134
135 endY[i] = startY[i] + maxHeight[i];
136 }
137
138 // Setting the positions
139 for ( int row = 0; row < d->m_rows; row++ ) {
140 for ( int column = 0; column < d->m_columns; column++ ) {
141 if ( d->m_items[row][column] == nullptr ) {
142 continue;
143 }
144
145 double xPos, yPos;
146
147 Qt::Alignment align = alignment( d->m_items[row][column] );
148
149 if ( align & Qt::AlignRight ) {
150 xPos = endX[column] - d->m_items[row][column]->size().width();
151 }
152 else if ( align & Qt::AlignHCenter ) {
153 xPos = startX[column]
154 + ( maxWidth[column] - d->m_items[row][column]->size().width() ) / 2.0;
155 }
156 else {
157 xPos = startX[column];
158 }
159
160 if ( align & Qt::AlignBottom ) {
161 yPos = endY[row] - d->m_items[row][column]->size().height();
162 }
163 else if ( align & Qt::AlignVCenter ) {
164 yPos = startY[row]
165 + ( maxHeight[row] - d->m_items[row][column]->size().height() ) / 2.0;
166 }
167 else {
168 yPos = startY[row];
169 }
170
171 d->m_items[row][column]->setPosition( QPointF( xPos, yPos ) );
172 }
173 }
174
175 parent->setContentSize( QSizeF( endX[d->m_columns - 1] - contentRect.left(),
176 endY[d->m_rows - 1] - contentRect.top() ) );
177 }
178
alignment() const179 Qt::Alignment MarbleGraphicsGridLayout::alignment() const
180 {
181 return d->m_alignment;
182 }
183
alignment(ScreenGraphicsItem * item) const184 Qt::Alignment MarbleGraphicsGridLayout::alignment( ScreenGraphicsItem *item ) const
185 {
186 return d->m_itemAlignment.value( item, d->m_alignment );
187 }
188
setAlignment(Qt::Alignment align)189 void MarbleGraphicsGridLayout::setAlignment( Qt::Alignment align )
190 {
191 d->m_alignment = align;
192 }
193
setAlignment(ScreenGraphicsItem * item,Qt::Alignment align)194 void MarbleGraphicsGridLayout::setAlignment( ScreenGraphicsItem *item, Qt::Alignment align )
195 {
196 d->m_itemAlignment.insert( item, align );
197 }
198
spacing() const199 int MarbleGraphicsGridLayout::spacing() const
200 {
201 return d->m_spacing;
202 }
203
setSpacing(int spacing)204 void MarbleGraphicsGridLayout::setSpacing( int spacing )
205 {
206 d->m_spacing = spacing;
207 }
208
209 } // namespace Marble
210