File indexing completed on 2024-05-12 05:40:25

0001 /***************************************************************************
0002  *  Copyright (C) 2022 by Renaud Guezennec                               *
0003  *   http://www.rolisteam.org/contact                                      *
0004  *                                                                         *
0005  *   This software is free software; you can redistribute it and/or modify *
0006  *   it under the terms of the GNU General Public License as published by  *
0007  *   the Free Software Foundation; either version 2 of the License, or     *
0008  *   (at your option) any later version.                                   *
0009  *                                                                         *
0010  *   This program is distributed in the hope that it will be useful,       *
0011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0013  *   GNU General Public License for more details.                          *
0014  *                                                                         *
0015  *   You should have received a copy of the GNU General Public License     *
0016  *   along with this program; if not, write to the                         *
0017  *   Free Software Foundation, Inc.,                                       *
0018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
0019  ***************************************************************************/
0020 #include "mindmap/data/packagenode.h"
0021 
0022 #include <QDebug>
0023 namespace mindmap
0024 {
0025 PackageNode::PackageNode(QObject* parent) : PositionedItem{MindItem::PackageType, parent}, m_title{tr("Package")}
0026 {
0027     connect(this, &PackageNode::itemDragged, this, [this](const QPointF& motion) {
0028         std::for_each(std::begin(m_internalChildren), std::end(m_internalChildren), [motion](PositionedItem* item) {
0029             if(!item)
0030                 return;
0031             auto pos= item->position();
0032             item->setPosition({pos.x() - motion.x(), pos.y() - motion.y()});
0033         });
0034     });
0035 
0036     connect(this, &PackageNode::widthChanged, this, &PackageNode::performLayout);
0037     connect(this, &PackageNode::heightChanged, this, &PackageNode::performLayout);
0038     connect(this, &PackageNode::visibleChanged, this, [this](bool visible) {
0039         std::for_each(std::begin(m_internalChildren), std::end(m_internalChildren),
0040                       [visible](PositionedItem* item) { item->setVisible(visible); });
0041     });
0042 }
0043 
0044 const QString& PackageNode::title() const
0045 {
0046     return m_title;
0047 }
0048 
0049 void PackageNode::setTitle(const QString& newTitle)
0050 {
0051     if(m_title == newTitle)
0052         return;
0053     m_title= newTitle;
0054     emit titleChanged();
0055 }
0056 
0057 void PackageNode::addChild(PositionedItem* item)
0058 {
0059     if(m_internalChildren.contains(item) || item == this || item == nullptr)
0060         return;
0061     m_internalChildren.append(item);
0062     performLayout();
0063     emit childAdded(item->id());
0064 }
0065 
0066 const QList<PositionedItem*>& PackageNode::children() const
0067 {
0068     return m_internalChildren;
0069 }
0070 
0071 void PackageNode::performLayout()
0072 {
0073     if(m_internalChildren.isEmpty())
0074         return;
0075 
0076     auto const itemCount= m_internalChildren.size();
0077     auto const w= width();
0078 
0079     std::vector<int> vec;
0080     std::transform(std::begin(m_internalChildren), std::end(m_internalChildren), std::back_inserter(vec),
0081                    [](PositionedItem* item) { return item->width(); });
0082     auto maxWidth= *std::max_element(std::begin(vec), std::end(vec));
0083 
0084     int itemPerLine= 1;
0085     while(maxWidth < (width() * 0.75) && itemCount > itemPerLine)
0086     {
0087         ++itemPerLine;
0088         int maxW= 0;
0089         std::vector<int> rows;
0090         rows.reserve(itemPerLine);
0091         for(auto w : vec)
0092         {
0093             if(rows.size() < itemPerLine)
0094             {
0095                 rows.push_back(w);
0096             }
0097             else
0098             {
0099                 maxW= std::max(std::accumulate(std::begin(rows), std::end(rows), 0), maxW);
0100                 rows.clear();
0101             }
0102         }
0103         maxW= std::max(std::accumulate(std::begin(rows), std::end(rows), 0), maxW);
0104         rows.clear();
0105         maxWidth= maxW;
0106         qDebug() << itemPerLine << " maxwidth:" << maxWidth;
0107     }
0108 
0109     if(maxWidth > width())
0110     {
0111         --itemPerLine;
0112     }
0113     // auto const itemPerLine= std::min(static_cast<int>((w - m_minimumMargin) / (m_sizeItem + m_minimumMargin)),
0114     //                                static_cast<int>(itemCount));
0115 
0116     auto currentMarge= (w - maxWidth) / (itemPerLine + 1);
0117 
0118     auto currentX= itemPerLine == itemCount ? currentMarge : m_minimumMargin;
0119     auto currentY= m_minimumMargin;
0120 
0121     int i= 0;
0122     qreal maxH= 0.;
0123     for(auto item : m_internalChildren)
0124     {
0125         auto p= position();
0126         QPointF a{currentX + p.x(), currentY + p.y()};
0127         // qDebug() << a;
0128         item->setPosition(a);
0129 
0130         currentX+= item->width() + currentMarge;
0131         maxH= std::max(item->height(), maxH);
0132         ++i;
0133         if(i >= itemPerLine)
0134         {
0135             currentY+= maxH + m_minimumMargin;
0136             currentX= m_minimumMargin;
0137             maxH= 0.;
0138         }
0139     }
0140 }
0141 
0142 int PackageNode::minimumMargin() const
0143 {
0144     return m_minimumMargin;
0145 }
0146 
0147 void PackageNode::setMinimumMargin(int newMinimumMargin)
0148 {
0149     if(m_minimumMargin == newMinimumMargin)
0150         return;
0151     m_minimumMargin= newMinimumMargin;
0152     emit minimumMarginChanged();
0153 }
0154 
0155 QStringList PackageNode::childrenId() const
0156 {
0157     QStringList res;
0158 
0159     std::transform(std::begin(m_internalChildren), std::end(m_internalChildren), std::back_inserter(res),
0160                    [](PositionedItem* item) { return item->id(); });
0161 
0162     return res;
0163 }
0164 
0165 } // namespace mindmap