File indexing completed on 2024-05-12 04:43:04

0001 /***************************************************************************
0002  *   Copyright (C) 2018 by Emmanuel Lepage Vallee                          *
0003  *   Author : Emmanuel Lepage Vallee <emmanuel.lepage@kde.org>             *
0004  *                                                                         *
0005  *   This program 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 3 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, see <http://www.gnu.org/licenses/>. *
0017  **************************************************************************/
0018 #include "geometry_p.h"
0019 
0020 #include <private/viewport_p.h>
0021 
0022 #define S StateTracker::Geometry::State::
0023 const StateTracker::Geometry::State StateTracker::Geometry::m_fStateMap[5][7] = {
0024 /*              MOVE      RESIZE      PLACE     RESET    MODIFY     DECORATE       VIEW   */
0025 /*INIT     */ { S INIT, S SIZE   , S POSITION, S INIT, S INIT    , S INIT    , S INIT     },
0026 /*SIZE     */ { S SIZE, S SIZE   , S PENDING , S INIT, S SIZE    , S SIZE    , S SIZE     },
0027 /*POSITION */ { S INIT, S PENDING, S POSITION, S INIT, S POSITION, S POSITION, S POSITION },
0028 /*PENDING  */ { S SIZE, S PENDING, S PENDING , S INIT, S POSITION, S PENDING , S VALID    },
0029 /*VALID    */ { S SIZE, S PENDING, S PENDING , S INIT, S POSITION, S PENDING , S VALID    },
0030 };
0031 #undef S
0032 
0033 #define A &StateTracker::Geometry::
0034 const StateTracker::Geometry::StateF StateTracker::Geometry::m_fStateMachine[5][7] = {
0035 /*                  MOVE        RESIZE        PLACE         RESET         MODIFY      DECORATE       VIEW    */
0036 /*INIT     */ { A nothing   , A nothing  , A nothing  , A nothing   , A nothing   , A nothing  , A error     },
0037 /*SIZE     */ { A nothing   , A dropSize , A nothing  , A dropSize  , A nothing   , A nothing  , A error     },
0038 /*POSITION */ { A invalidate, A nothing  , A nothing  , A dropPos   , A nothing   , A nothing  , A error     },
0039 /*PENDING  */ { A nothing   , A nothing  , A nothing  , A invalidate, A invalidate, A nothing  , A buildCache},
0040 /*VALID    */ { A nothing   , A dropCache, A dropCache, A invalidate, A dropCache , A dropCache, A buildCache},
0041 };
0042 #undef A
0043 
0044 void StateTracker::Geometry::nothing()
0045 {}
0046 
0047 void StateTracker::Geometry::invalidate()
0048 {
0049     dropCache();
0050 }
0051 
0052 void StateTracker::Geometry::error()
0053 {
0054     Q_ASSERT(false);
0055 }
0056 
0057 void StateTracker::Geometry::dropCache()
0058 {
0059     //TODO
0060 }
0061 
0062 void StateTracker::Geometry::buildCache()
0063 {
0064     //TODO
0065 }
0066 
0067 void StateTracker::Geometry::dropSize()
0068 {
0069     dropCache();
0070     m_Size = {};
0071 }
0072 
0073 void StateTracker::Geometry::dropPos()
0074 {
0075     dropCache();
0076     m_Position = {};
0077 }
0078 
0079 StateTracker::Geometry::State StateTracker::Geometry::performAction(IndexMetadata::GeometryAction a)
0080 {
0081     const int s = (int)m_State;
0082     m_State     = m_fStateMap[s][(int)a];
0083 
0084     (this->*StateTracker::Geometry::m_fStateMachine[s][(int)a])();
0085 
0086     // Validate the state
0087     //BEGIN debug
0088     /*switch(m_State) {
0089         case StateTracker::Geometry::State::VALID:
0090         case StateTracker::Geometry::State::PENDING:
0091             Q_ASSERT(!(m_Position.x() == -1 && m_Position.y() == -1));
0092             Q_ASSERT(m_Size.isValid());
0093             break;
0094         case StateTracker::Geometry::State::SIZE:
0095             Q_ASSERT(m_Size.isValid());
0096             break;
0097         case StateTracker::Geometry::State::POSITION:
0098             Q_ASSERT(!(m_Position.x() == -1 && m_Position.y() == -1));
0099             break;
0100         case StateTracker::Geometry::State::INIT:
0101             break;
0102     }*/
0103     //END debug
0104 
0105     return m_State;
0106 }
0107 
0108 QRectF StateTracker::Geometry::rawGeometry() const
0109 {
0110     const_cast<StateTracker::Geometry*>(this)->performAction(IndexMetadata::GeometryAction::VIEW);
0111 
0112     Q_ASSERT(m_State == StateTracker::Geometry::State::VALID);
0113 
0114     return QRectF(m_Position, m_Size);
0115 }
0116 
0117 QRectF StateTracker::Geometry::contentGeometry() const
0118 {
0119     auto g = rawGeometry();
0120 
0121     g.setY(g.y() + borderDecoration( Qt::TopEdge  ));
0122     g.setX(g.x() + borderDecoration( Qt::LeftEdge ));
0123 
0124     return g;
0125 }
0126 
0127 QRectF StateTracker::Geometry::decoratedGeometry() const
0128 {
0129     //TODO cache this, extend the state machine to have a "really valid" state
0130     auto g = rawGeometry();
0131 
0132     const auto topDeco = borderDecoration( Qt::TopEdge    );
0133     const auto botDeco = borderDecoration( Qt::BottomEdge );
0134     const auto lefDeco = borderDecoration( Qt::LeftEdge   );
0135     const auto rigDeco = borderDecoration( Qt::RightEdge  );
0136 
0137     g.setHeight(g.height() + topDeco + botDeco);
0138     g.setWidth (g.width () + lefDeco + rigDeco);
0139 
0140     return g;
0141 }
0142 
0143 QSizeF StateTracker::Geometry::size() const
0144 {
0145     Q_ASSERT(m_State != StateTracker::Geometry::State::INIT);
0146     Q_ASSERT(m_State != StateTracker::Geometry::State::POSITION);
0147 
0148     return m_State == StateTracker::Geometry::State::SIZE ?
0149         m_Size : decoratedGeometry().size();
0150 }
0151 
0152 QPointF StateTracker::Geometry::position() const
0153 {
0154     return m_State == StateTracker::Geometry::State::POSITION ?
0155         m_Position : decoratedGeometry().topLeft();
0156 }
0157 
0158 void StateTracker::Geometry::setPosition(const QPointF& pos)
0159 {
0160     m_Position = pos;
0161     performAction(IndexMetadata::GeometryAction::PLACE);
0162 }
0163 
0164 void StateTracker::Geometry::setSize(const QSizeF& size)
0165 {
0166     m_Size = size;
0167     performAction(IndexMetadata::GeometryAction::RESIZE);
0168 }
0169 
0170 StateTracker::Geometry::State StateTracker::Geometry::state() const
0171 {
0172     return m_State;
0173 }
0174 
0175 qreal StateTracker::Geometry::borderDecoration(Qt::Edge e) const
0176 {
0177     return m_lBorderDecoration.get(e);
0178 }
0179 
0180 void StateTracker::Geometry::setBorderDecoration(Qt::Edge e, qreal r)
0181 {
0182     if (m_lBorderDecoration.get(e) == r)
0183         return;
0184 
0185     m_lBorderDecoration.set(r, e);
0186 
0187     performAction(IndexMetadata::GeometryAction::DECORATE);
0188 }