File indexing completed on 2024-05-05 03:49:47

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2009 Bastian Holst <bastianholst@gmx.de>
0004 //
0005 
0006 // Self
0007 #include "MarbleGraphicsGridLayout.h"
0008 
0009 // Marble
0010 #include "MarbleDebug.h"
0011 #include "ScreenGraphicsItem.h"
0012 
0013 // Qt
0014 #include <QHash>
0015 #include <QRectF>
0016 #include <QSizeF>
0017 #include <QVector>
0018 
0019 namespace Marble
0020 {
0021 
0022 class MarbleGraphicsGridLayoutPrivate
0023 {
0024  public:
0025     MarbleGraphicsGridLayoutPrivate( int rows, int columns )
0026             : m_rows( rows ),
0027               m_columns( columns ),
0028               m_spacing( 0 ),
0029               m_alignment( Qt::AlignLeft | Qt::AlignTop )
0030     {
0031         m_items = new ScreenGraphicsItem **[rows];
0032         for ( int i = 0; i < rows; ++i ) {
0033             m_items[i] = new ScreenGraphicsItem *[columns];
0034         }
0035         for ( int row = 0; row < rows; row++ ) {
0036             for ( int column = 0; column < columns; column++ ) {
0037                 m_items[row][column] = nullptr;
0038             }
0039         }
0040     }
0041 
0042     ~MarbleGraphicsGridLayoutPrivate()
0043     {
0044         for ( int i = 0; i < m_rows; ++i ) {
0045             delete[] m_items[i];
0046         }
0047         delete[] m_items;
0048     }
0049 
0050     // A two dimensional array of pointers to ScreenGraphicsItems
0051     ScreenGraphicsItem ***m_items;
0052     int m_rows;
0053     int m_columns;
0054     int m_spacing;
0055     Qt::Alignment m_alignment;
0056     QHash<ScreenGraphicsItem*, Qt::Alignment> m_itemAlignment;
0057 };
0058 
0059 MarbleGraphicsGridLayout::MarbleGraphicsGridLayout( int rows, int columns )
0060         : d( new MarbleGraphicsGridLayoutPrivate( rows, columns ) )
0061 {
0062 }
0063 
0064 MarbleGraphicsGridLayout::~MarbleGraphicsGridLayout()
0065 {
0066     delete d;
0067 }
0068 
0069 void MarbleGraphicsGridLayout::addItem( ScreenGraphicsItem *item, int row, int column )
0070 {
0071     if ( row < d->m_rows
0072          && column < d->m_columns )
0073     {
0074         d->m_items[row][column] = item;
0075     }
0076 }
0077 
0078 void MarbleGraphicsGridLayout::updatePositions( MarbleGraphicsItem *parent )
0079 {
0080     // Initialize with 0.0
0081     QVector<double> maxWidth( d->m_columns, 0.0 );
0082     QVector<double> maxHeight( d->m_rows, 0.0 );
0083 
0084     // Determining the cell sizes
0085     for ( int row = 0; row < d->m_rows; row++ ) {
0086         for ( int column = 0; column < d->m_columns; column++ ) {
0087             if ( d->m_items[row][column] == nullptr ) {
0088                 continue;
0089             }
0090 
0091             QSizeF size = d->m_items[row][column]->size();
0092             double width = size.width();
0093             double height = size.height();
0094 
0095             if ( width > maxWidth[column] ) {
0096                 maxWidth[column] = width;
0097             }
0098             if ( height > maxHeight[row] ) {
0099                 maxHeight[row] = height;
0100             }
0101         }
0102     }
0103 
0104     QVector<double> startX( d->m_columns );
0105     QVector<double> endX( d->m_columns );
0106     QVector<double> startY( d->m_rows );
0107     QVector<double> endY( d->m_rows );
0108     QRectF contentRect = parent->contentRect();
0109 
0110     for ( int i = 0; i < d->m_columns; i++ ) {
0111         if ( i == 0 ) {
0112             startX[0] = contentRect.left();
0113         }
0114         else if ( maxWidth[i] == 0 ) {
0115             startX[i] = endX[i-1];
0116         }
0117         else {
0118             startX[i] = endX[i-1] + d->m_spacing;
0119         }
0120 
0121         endX[i] = startX[i] + maxWidth[i];
0122     }
0123 
0124     for ( int i = 0; i < d->m_rows; i++ ) {
0125         if ( i == 0 ) {
0126             startY[0] = contentRect.left();
0127         }
0128         else if ( maxHeight[i] == 0 ) {
0129             startY[i] = endY[i-1];
0130         }
0131         else {
0132             startY[i] = endY[i-1] + d->m_spacing;
0133         }
0134 
0135         endY[i] = startY[i] + maxHeight[i];
0136     }
0137 
0138     // Setting the positions
0139     for ( int row = 0; row < d->m_rows; row++ ) {
0140         for ( int column = 0; column < d->m_columns; column++ ) {
0141             if ( d->m_items[row][column] == nullptr ) {
0142                 continue;
0143             }
0144 
0145             double xPos, yPos;
0146 
0147             Qt::Alignment align = alignment( d->m_items[row][column] );
0148 
0149             if ( align & Qt::AlignRight ) {
0150                 xPos = endX[column] - d->m_items[row][column]->size().width();
0151             }
0152             else if ( align & Qt::AlignHCenter ) {
0153                 xPos = startX[column]
0154                        + ( maxWidth[column] - d->m_items[row][column]->size().width() ) / 2.0;
0155             }
0156             else {
0157                 xPos = startX[column];
0158             }
0159 
0160             if ( align & Qt::AlignBottom ) {
0161                 yPos = endY[row] - d->m_items[row][column]->size().height();
0162             }
0163             else if ( align & Qt::AlignVCenter ) {
0164                 yPos = startY[row]
0165                        + ( maxHeight[row] - d->m_items[row][column]->size().height() ) / 2.0;
0166             }
0167             else {
0168                 yPos = startY[row];
0169             }
0170 
0171             d->m_items[row][column]->setPosition( QPointF( xPos, yPos ) );
0172         }
0173     }
0174 
0175     parent->setContentSize( QSizeF( endX[d->m_columns - 1] - contentRect.left(),
0176                                     endY[d->m_rows - 1] - contentRect.top() ) );
0177 }
0178 
0179 Qt::Alignment MarbleGraphicsGridLayout::alignment() const
0180 {
0181     return d->m_alignment;
0182 }
0183 
0184 Qt::Alignment MarbleGraphicsGridLayout::alignment( ScreenGraphicsItem *item ) const
0185 {
0186     return d->m_itemAlignment.value( item, d->m_alignment );
0187 }
0188 
0189 void MarbleGraphicsGridLayout::setAlignment( Qt::Alignment align )
0190 {
0191     d->m_alignment = align;
0192 }
0193 
0194 void MarbleGraphicsGridLayout::setAlignment( ScreenGraphicsItem *item, Qt::Alignment align )
0195 {
0196     d->m_itemAlignment.insert( item, align );
0197 }
0198 
0199 int MarbleGraphicsGridLayout::spacing() const
0200 {
0201     return d->m_spacing;
0202 }
0203 
0204 void MarbleGraphicsGridLayout::setSpacing( int spacing )
0205 {
0206     d->m_spacing = spacing;
0207 }
0208 
0209 } // namespace Marble