1 // -*- C++ -*-
2 // --------------------------------------------------------------------
3 // A page of a document.
4 // --------------------------------------------------------------------
5 /*
6 
7     This file is part of the extensible drawing editor Ipe.
8     Copyright (c) 1993-2020 Otfried Cheong
9 
10     Ipe is free software; you can redistribute it and/or modify it
11     under the terms of the GNU General Public License as published by
12     the Free Software Foundation; either version 3 of the License, or
13     (at your option) any later version.
14 
15     As a special exception, you have permission to link Ipe with the
16     CGAL library and distribute executables, as long as you follow the
17     requirements of the Gnu General Public License in regard to all of
18     the software in the executable aside from CGAL.
19 
20     Ipe is distributed in the hope that it will be useful, but WITHOUT
21     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
22     or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
23     License for more details.
24 
25     You should have received a copy of the GNU General Public License
26     along with Ipe; if not, you can find it at
27     "http://www.gnu.org/copyleft/gpl.html", or write to the Free
28     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 
30 */
31 
32 #ifndef IPEPAGE_H
33 #define IPEPAGE_H
34 
35 #include "ipetext.h"
36 
37 // --------------------------------------------------------------------
38 
39 namespace ipe {
40 
41   class StyleSheet;
42 
43   // --------------------------------------------------------------------
44 
45   class Page {
46   public:
47     enum class SnapMode { Never, Visible, Always };
48 
49     explicit Page();
50 
51     static Page *basic();
52 
53     void saveAsXml(Stream &stream) const;
54     void saveAsIpePage(Stream &stream) const;
55     void saveSelection(Stream &stream) const;
56 
57     //! Return number of layers.
countLayers()58     inline int countLayers() const noexcept { return iLayers.size(); }
59     //! Return name of layer \a index.
layer(int index)60     inline String layer(int index) const noexcept {
61       return iLayers[index].iName; }
62 
63     //! Is layer \a i locked?
isLocked(int i)64     inline bool isLocked(int i) const noexcept { return iLayers[i].locked; }
65     //! Does layer \a i have snapping?
snapping(int i)66     inline SnapMode snapping(int i) const noexcept { return iLayers[i].snapMode; }
67     bool objSnapsInView(int objNo, int view) const noexcept;
68 
69     void setLocked(int i, bool flag);
70     void setSnapping(int i, SnapMode mode);
71 
72     void moveLayer(int index, int newIndex);
73     int findLayer(String name) const;
74     void addLayer(String name);
75     void addLayer();
76     void removeLayer(String name);
77     void renameLayer(String oldName, String newName);
78     void setLayerData(int index, String data);
79     //! Return layer data.
layerData(int index)80     inline String layerData(int index) const { return iLayers[index].iData; }
81 
82     //! Return number of views.
countViews()83     inline int countViews() const { return iViews.size(); }
84     int countMarkedViews() const;
85     //! Return effect of view.
effect(int index)86     inline Attribute effect(int index) const { return iViews[index].iEffect; }
87     void setEffect(int index, Attribute sym);
88     //! Return active layer of view.
active(int index)89     inline String active(int index) const { return iViews[index].iActive; }
90     //! Set active layer of view.
91     void setActive(int index, String name);
92     //! Return name of view.
viewName(int index)93     String viewName(int index) const noexcept { return iViews[index].iName; }
94     //! Set name of view.
setViewName(int index,String name)95     void setViewName(int index, String name) noexcept { iViews[index].iName = name; }
96     //! Return if view is marked.
markedView(int index)97     bool markedView(int index) const { return iViews[index].iMarked; }
98     //! Set if view is marked.
99     void setMarkedView(int index, bool marked);
100 
101     void insertView(int i, String active);
102     void removeView(int i);
103     void clearViews();
104 
105     int findView(String viewNumberOrName) const;
106 
viewMap(int index)107     const AttributeMap &viewMap(int index) const { return iViews[index].iAttributeMap; }
108     void setViewMap(int index, const AttributeMap &map);
109 
110     //! Is \a layer visible in \a view?
visible(int view,int layer)111     inline bool visible(int view, int layer) const {
112       return iLayers[layer].iVisible[view]; }
113     //! Is object at index \a objno visible in \a view?
objectVisible(int view,int objno)114     inline bool objectVisible(int view, int objno) const {
115       return iLayers[layerOf(objno)].iVisible[view]; }
116 
117     std::vector<Matrix> layerMatrices(int view) const;
clearLayerMatrices(int view)118     void clearLayerMatrices(int view) { iViews[view].iLayerMatrices.clear(); }
119     void setLayerMatrix(int view, int layer, const Matrix &m);
120 
121     void setVisible(int view, String layer, bool vis);
122 
123     //! Return title of this page.
124     String title() const;
125     void setTitle(String title);
126     String section(int level) const;
127     void setSection(int level, bool useTitle, String name);
128     //! Does this section title reflect the page title?
sectionUsesTitle(int level)129     bool sectionUsesTitle(int level) const { return iUseTitle[level]; }
130     const Text *titleText() const;
131     void applyTitleStyle(const Cascade *sheet);
132 
133     //! Return if page is marked for printing.
marked()134     bool marked() const { return iMarked; }
135     void setMarked(bool marked);
136 
137     //! Return notes for this page.
notes()138     String notes() const { return iNotes; }
139     void setNotes(String notes);
140 
141     //! Return number of objects on the page.
count()142     inline int count() const { return iObjects.size(); }
143 
144     void objectsPerLayer(std::vector<int> &objcounts) const;
145 
146     //! Return object at index \a i.
object(int i)147     inline Object *object(int i) { return iObjects[i].iObject; }
148     //! Return object at index \a i (const version).
object(int i)149     inline const Object *object(int i) const { return iObjects[i].iObject; }
150 
151     //! Return selection status of object at index \a i.
select(int i)152     inline TSelect select(int i) const { return iObjects[i].iSelect; }
153     //! Return layer of object at index \a i.
layerOf(int i)154     inline int layerOf(int i) const { return iObjects[i].iLayer; }
155 
156     //! Set selection status of object at index \a i.
setSelect(int i,TSelect sel)157     inline void setSelect(int i, TSelect sel) { iObjects[i].iSelect = sel; }
158     //! Set layer of object at index \a i.
setLayerOf(int i,int layer)159     inline void setLayerOf(int i, int layer) { iObjects[i].iLayer = layer; }
160 
161     Rect pageBBox(const Cascade *sheet) const;
162     Rect viewBBox(const Cascade *sheet, int view) const;
163     Rect bbox(int i) const;
164 
165     void transform(int i, const Matrix &m);
166     double distance(int i, const Vector &v, double bound) const;
167     void snapVtx(int i, const Vector &mouse, Vector &pos, double &bound) const;
168     void snapCtl(int i, const Vector &mouse, Vector &pos, double &bound) const;
169     void snapBnd(int i, const Vector &mouse, Vector &pos, double &bound) const;
170     void invalidateBBox(int i) const;
171 
172     void insert(int i, TSelect sel, int layer, Object *obj);
173     void append(TSelect sel, int layer, Object *obj);
174     void remove(int i);
175     void replace(int i, Object *obj);
176     bool setAttribute(int i, Property prop, Attribute value);
177 
178     int primarySelection() const;
179     bool hasSelection() const;
180     void deselectAll();
181     void ensurePrimarySelection();
182 
183   private:
184     struct SLayer {
185     public:
186       SLayer(String name);
187     public:
188       String iName;
189       String iData;
190       bool locked;
191       SnapMode snapMode;
192       // Invariant: iVisible.size() == iViews.size()
193       std::vector<bool> iVisible;
194     };
195     typedef std::vector<SLayer> LayerSeq;
196 
197     struct SLayerMatrix {
198       String iLayer;
199       Matrix iMatrix;
200     };
201 
202     struct SView {
203     public:
SViewSView204       SView() { iEffect = Attribute::NORMAL(); }
205     public:
206       Attribute iEffect;
207       String iActive;
208       bool iMarked;
209       String iName;
210       AttributeMap iAttributeMap;
211       std::vector<SLayerMatrix> iLayerMatrices;
212     };
213     typedef std::vector<SView> ViewSeq;
214 
215     struct SObject {
216       SObject();
217       SObject(const SObject &rhs);
218       ~SObject();
219       SObject &operator=(const SObject &rhs);
220 
221       TSelect iSelect;
222       int iLayer;
223       mutable Rect iBBox;
224       Object *iObject;
225     };
226     typedef std::vector<SObject> ObjSeq;
227 
228     LayerSeq iLayers;
229     ViewSeq iViews;
230 
231     String iTitle;
232     Text iTitleObject;
233     bool iUseTitle[2];
234     String iSection[2];
235     ObjSeq iObjects;
236     String iNotes;
237     bool iMarked;
238   };
239 
240 } // namespace
241 
242 // --------------------------------------------------------------------
243 #endif
244