1 /*
2  Copyright (c) 2008-2020, Benoit AUTHEMAN All rights reserved.
3 
4  Redistribution and use in source and binary forms, with or without
5  modification, are permitted provided that the following conditions are met:
6     * Redistributions of source code must retain the above copyright
7       notice, this list of conditions and the following disclaimer.
8     * Redistributions in binary form must reproduce the above copyright
9       notice, this list of conditions and the following disclaimer in the
10       documentation and/or other materials provided with the distribution.
11     * Neither the name of the author or Destrat.io nor the
12       names of its contributors may be used to endorse or promote products
13       derived from this software without specific prior written permission.
14 
15  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18  DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
19  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26 
27 //-----------------------------------------------------------------------------
28 // This file is a part of the QuickQanava library. Copyright 2016 Benoit AUTHEMAN.
29 //
30 // \file	qanLineGrid.h
31 // \author	benoit@destrat.io
32 // \date	2019 11 09 (initial code 2017 01 29)
33 //-----------------------------------------------------------------------------
34 
35 #pragma once
36 
37 // Qt headers
38 #include <QtQml>
39 #include <QQuickItem>
40 #include <QQmlListProperty>
41 
42 // QuickQanava headers
43 #include "./qanGrid.h"
44 
45 namespace qan {  // ::qan
46 
47 /*! \brief Abstract grid with orthogonal geometry.
48  *
49  * \warning Changing \c geometryComponent dynamically is impossible and sill issue
50  * a warning.
51  *
52  * \nosubgrouping
53  */
54 class OrthoGrid : public Grid
55 {
56     /*! \name OrthoGrid Object Management *///---------------------------------
57     //@{
58     Q_OBJECT
59 public:
60     explicit OrthoGrid(QQuickItem* parent = nullptr);
61     virtual ~OrthoGrid() override = default;
62     OrthoGrid(const OrthoGrid&) = delete;
63     //@}
64     //-------------------------------------------------------------------------
65 
66     /*! \name Grid Management *///---------------------------------------------
67     //@{
68 public:
69     virtual bool    updateGrid(const QRectF& viewRect,
70                                const QQuickItem& container,
71                                const QQuickItem& navigable) noexcept override;
72 protected:
73     virtual bool    updateGrid() noexcept override;
74 
75 private:
76     //! View rect cached updated in updateGrid(), allow updateGrid() use with no arguments.
77     QRectF                  _viewRectCache;
78     //! Cache for container targetted by this grid, updated in updateGrid(), allow updateGrid() use with no arguments.
79     QPointer<QQuickItem>    _containerCache;
80     //! Cache for navigable where this grid is used, updated in updateGrid(), allow updateGrid() use with no arguments.
81     QPointer<QQuickItem>    _navigableCache;
82     //@}
83     //-------------------------------------------------------------------------
84 };
85 
86 namespace impl {  // ::qan::impl
87 
88 /*! \brief Private utility class based on QObject to feed line to QML grid backend.
89  */
90 class GridLine : public QObject
91 {
92     Q_OBJECT
93 public:
94     GridLine() = default;
GridLine(QObject * parent)95     GridLine(QObject* parent) : QObject{parent} {}
GridLine(const QPointF && p1,const QPointF && p2)96     GridLine(const QPointF&& p1, const QPointF&& p2) :
97         QObject{nullptr},
98         _p1{p1}, _p2{p2} {}
99     ~GridLine() = default;
100     GridLine(const GridLine&) = delete;
101 
102 public:
Q_PROPERTY(QPointF p1 READ getP1)103     Q_PROPERTY(QPointF p1 READ getP1)
104     Q_PROPERTY(QPointF p2 READ getP2)
105 
106     const QPointF&  getP1() const { return _p1; }
getP2()107     const QPointF&  getP2() const { return _p2; }
getP1()108     QPointF&        getP1() { return _p1; }
getP2()109     QPointF&        getP2() { return _p2; }
110 private:
111     QPointF _p1;
112     QPointF _p2;
113 };
114 
115 } // ::qan::impl
116 
117 /*! * \brief Draw an orthogonal grid with lines.
118  *
119  * \code
120  *  Qan.Navigable {
121  *    navigable: true
122  *    Qan.LineGrid { id: lineGrid }
123  *    grid: lineGrid
124  *  }
125  * \endcode
126  *
127  * \nosubgrouping
128  */
129 class LineGrid : public OrthoGrid
130 {
131     /*! \name LineGrid Object Management *///----------------------------------
132     //@{
133     Q_OBJECT
134 public:
135     explicit LineGrid( QQuickItem* parent = nullptr );
136     virtual ~LineGrid() override;
137     LineGrid(const LineGrid&) = delete;
138     //@}
139     //-------------------------------------------------------------------------
140 
141     /*! \name Grid Management *///---------------------------------------------
142     //@{
143 signals:
144     /*! \brief Emmitted when the grid's lines have to be redrawned.
145      * \c minorLineToDrawCount and \c majorLineToDrawCount respectively the number of lines
146      * to redraw.
147      */
148     void            redrawLines(int minorLineToDrawCount, int majorLineToDrawCount);
149 
150 public:
151     virtual bool    updateGrid(const QRectF& viewRect,
152                                const QQuickItem& container,
153                                const QQuickItem& navigable ) noexcept override;
154 public:
155     Q_PROPERTY(QQmlListProperty<qan::impl::GridLine> minorLines READ getMinorLines)
156     Q_PROPERTY(QQmlListProperty<qan::impl::GridLine> majorLines READ getMajorLines)
157 
158 protected:
159     QQmlListProperty<qan::impl::GridLine> getMinorLines();
160     QQmlListProperty<qan::impl::GridLine> getMajorLines();
161 
162 private:
163 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
164     using size_type = int;
165 #else
166     using size_type = qsizetype;
167 #endif
168 
169     size_type                   minorLinesCount() const;
170     impl::GridLine*             minorLinesAt(size_type index) const;
171     QVector<impl::GridLine*>    _minorLines;
172 
173     size_type                   majorLinesCount() const;
174     impl::GridLine*             majorLinesAt(size_type index) const;
175     QVector<impl::GridLine*>    _majorLines;
176 
177 private:
178     static size_type        callMinorLinesCount(QQmlListProperty<impl::GridLine>*);
179     static impl::GridLine*  callMinorLinesAt(QQmlListProperty<impl::GridLine>*, size_type index);
180 
181     static size_type        callMajorLinesCount(QQmlListProperty<impl::GridLine>*);
182     static impl::GridLine*  callMajorLinesAt(QQmlListProperty<impl::GridLine>*, size_type index);
183     //@}
184     //-------------------------------------------------------------------------
185 };
186 
187 }  // ::qan
188 
189 QML_DECLARE_TYPE(qan::OrthoGrid);
190 QML_DECLARE_TYPE(qan::impl::GridLine);
191 QML_DECLARE_TYPE(qan::LineGrid);
192