~inkscape.dev/inkscape/trunk

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
#ifndef SEEN_SP_DOCUMENT_H
#define SEEN_SP_DOCUMENT_H

/** \file
 * SPDocument: Typed SVG document implementation
 */
/* Authors:
 *   Lauris Kaplinski <lauris@kaplinski.com>
 *   MenTaLguY <mental@rydia.net>
 *   Jon A. Cruz <jon@joncruz.org>
 *   Abhishek Sharma
 *
 * Copyright (C) 2004-2005 MenTaLguY
 * Copyright (C) 1999-2002 Lauris Kaplinski
 * Copyright (C) 2000-2001 Ximian, Inc.
 *
 * Released under GNU GPL, read the file 'COPYING' for more information
 */

#include <glib-object.h>
#include <gtk/gtksignal.h>
#include <stddef.h>
#include <sigc++/sigc++.h>
#include <sigc++/class_slot.h>

#include "libcroco/cr-cascade.h"
#include <2geom/forward.h>

#include "gc-managed.h"
#include "gc-finalized.h"
#include "gc-anchored.h"
#include <glibmm/ustring.h>
#include "verbs.h"
#include "document-undo.h"
#include <vector>
#include <set>

namespace Avoid {
class Router;
}

struct NRRect;
struct SPDesktop;
struct SPItem;
struct SPObject;
struct SPGroup;

namespace Inkscape {
    struct Application;
    class Selection; 
    class UndoStackObserver;
    class EventLog;
    class ProfileManager;
    namespace XML {
        class Document;
        class Node;
    }
}

class SP3DBox;
class Persp3D;
class Persp3DImpl;

namespace Proj {
    class TransfMat3x4;
}

class SPDocumentPrivate;

/// Typed SVG document implementation.
class SPDocument : public Inkscape::GC::Managed<>,
                    public Inkscape::GC::Finalized,
                    public Inkscape::GC::Anchored
{
public:
    typedef sigc::signal<void, SPObject *> IDChangedSignal;
    typedef sigc::signal<void> ResourcesChangedSignal;
    typedef sigc::signal<void, guint> ModifiedSignal;
    typedef sigc::signal<void, gchar const *> URISetSignal;
    typedef sigc::signal<void, double, double> ResizedSignal;
    typedef sigc::signal<void> ReconstructionStart;
    typedef sigc::signal<void> ReconstructionFinish;
    typedef sigc::signal<void> CommitSignal;

    SPDocument();
    virtual ~SPDocument();

    unsigned int keepalive : 1;
    unsigned int virgin    : 1; ///< Has the document never been touched?
    unsigned int modified_since_save : 1;

    Inkscape::XML::Document *rdoc; ///< Our Inkscape::XML::Document
    Inkscape::XML::Node *rroot; ///< Root element of Inkscape::XML::Document
    SPObject *root;             ///< Our SPRoot
    CRCascade *style_cascade;

protected:
    gchar *uri;   ///< A filename (not a URI yet), or NULL
    gchar *base;  ///< To be used for resolving relative hrefs.
    gchar *name;  ///< basename(uri) or other human-readable label for the document.

public:

    SPDocumentPrivate *priv;

    /// Last action key
    Glib::ustring actionkey;

    /// Handler ID
    guint modified_id;
    
    /// Connector rerouting handler ID
    guint rerouting_handler_id;

    Inkscape::ProfileManager* profileManager;

    // Instance of the connector router
    Avoid::Router *router;

    GSList *_collection_queue;

    bool oldSignalsConnected;

    /** Returns our SPRoot */
    SPObject *getRoot() { return root; }

    Inkscape::XML::Node *getReprRoot() { return rroot; }

    /** Our Inkscape::XML::Document. */
    Inkscape::XML::Document *getReprDoc() { return rdoc; }
    Inkscape::XML::Document const *getReprDoc() const { return rdoc; }

    /** A filename (not a URI yet), or NULL */
    gchar const *getURI() const { return uri; }
    void setUri(gchar const *uri);

    /** To be used for resolving relative hrefs. */
    gchar const *getBase() const { return base; };
    void setBase( gchar const* base );

    /** basename(uri) or other human-readable label for the document. */
    gchar const* getName() const { return name; }


    void setCurrentPersp3D(Persp3D * const persp);
    inline void setCurrentPersp3DImpl(Persp3DImpl * const persp_impl) { current_persp3d_impl = persp_impl; }
    /*
     * getCurrentPersp3D returns current_persp3d (if non-NULL) or the first
     * perspective in the defs. If no perspective exists, returns NULL.
     */
    Persp3D * getCurrentPersp3D();
    Persp3DImpl * getCurrentPersp3DImpl();

    void getPerspectivesInDefs(std::vector<Persp3D*> &list) const;

    unsigned int numPerspectivesInDefs() const {
        std::vector<Persp3D*> list;
        getPerspectivesInDefs(list);
        return list.size();
    }

    sigc::connection connectModified(ModifiedSignal::slot_type slot);
    sigc::connection connectURISet(URISetSignal::slot_type slot);
    sigc::connection connectResized(ResizedSignal::slot_type slot);
    sigc::connection connectCommit(CommitSignal::slot_type slot);

    void bindObjectToId(gchar const *id, SPObject *object);
    SPObject *getObjectById(gchar const *id) const;
    sigc::connection connectIdChanged(const gchar *id, IDChangedSignal::slot_type slot);

    void bindObjectToRepr(Inkscape::XML::Node *repr, SPObject *object);
    SPObject *getObjectByRepr(Inkscape::XML::Node *repr) const;

    Glib::ustring getLanguage() const;

    void queueForOrphanCollection(SPObject *object);
    void collectOrphans();

    void _emitModified();

    void addUndoObserver(Inkscape::UndoStackObserver& observer);
    void removeUndoObserver(Inkscape::UndoStackObserver& observer);

    bool _updateDocument();

    /// Are we currently in a transition between two "known good" states of the document?
    bool isSeeking() const;

    bool isModifiedSinceSave() const { return modified_since_save; }
    void setModifiedSinceSave(bool modified = true) {
        modified_since_save = modified;
    }

private:
    SPDocument(SPDocument const &); // no copy
    void operator=(SPDocument const &); // no assign

    Persp3D *current_persp3d; /**< Currently 'active' perspective (to which, e.g., newly created boxes are attached) */
    Persp3DImpl *current_persp3d_impl;

public:
    sigc::connection connectReconstructionStart(ReconstructionStart::slot_type slot);
    sigc::connection connectReconstructionFinish(ReconstructionFinish::slot_type slot);
    void emitReconstructionStart(void);
    void emitReconstructionFinish(void);

    unsigned long serial() const;
    void reset_key(void *dummy);
    sigc::connection _selection_changed_connection;
    sigc::connection _desktop_activated_connection;

    sigc::connection connectResourcesChanged(const gchar *key, SPDocument::ResourcesChangedSignal::slot_type slot);

    void fitToRect(Geom::Rect const &rect, bool with_margins = false);
    static SPDocument *createNewDoc(const gchar *uri, unsigned int keepalive, bool make_new = false);
    static SPDocument *createNewDocFromMem(const gchar *buffer, gint length, unsigned int keepalive);

    /**
     * Returns the bottommost item from the list which is at the point, or NULL if none.
     */
    static SPItem *getItemFromListAtPointBottom(unsigned int dkey, SPGroup *group, const GSList *list, Geom::Point const p, bool take_insensitive = false);

    // ToDo - Merge createDoc with createNewDoc
    static SPDocument *createDoc(Inkscape::XML::Document *rdoc, gchar const *uri, gchar const *base, gchar const *name, unsigned int keepalive);

    SPDocument *doRef();
    SPDocument *doUnref();
    gdouble getWidth() const;
    gdouble getHeight() const;
    Geom::Point getDimensions() const;
    void setWidth(gdouble width, const SPUnit *unit);
    void setHeight(gdouble height, const SPUnit *unit);
    void requestModified();
    gint ensureUpToDate();
    bool addResource(const gchar *key, SPObject *object);
    bool removeResource(const gchar *key, SPObject *object);
    const GSList *getResourceList(const gchar *key) const;
    GSList *getItemsInBox(unsigned int dkey, Geom::Rect const &box) const;
    GSList *getItemsPartiallyInBox(unsigned int dkey, Geom::Rect const &box) const;
    SPItem *getItemAtPoint(unsigned int key, Geom::Point const p, gboolean into_groups, SPItem *upto = NULL) const;
    GSList *getItemsAtPoints(unsigned const key, std::vector<Geom::Point> points) const;
    SPItem *getGroupAtPoint(unsigned int key,  Geom::Point const p) const;

    void changeUriAndHrefs(gchar const *uri);
    void emitResizedSignal(gdouble width, gdouble height);
	
    unsigned int vacuumDocument();

private:
    void do_change_uri(gchar const *const filename, bool const rebase);
};

struct SPUnit;

/*
 * Ideas: How to overcome style invalidation nightmare
 *
 * 1. There is reference request dictionary, that contains
 * objects (styles) needing certain id. Object::build checks
 * final id against it, and invokes necesary methods
 *
 * 2. Removing referenced object is simply prohibited -
 * needs analyse, how we can deal with situations, where
 * we simply want to ungroup etc. - probably we need
 * Repr::reparent method :( [Or was it ;)]
 *
 */

#endif // SEEN_SP_DOCUMENT_H

/*
  Local Variables:
  mode:c++
  c-file-style:"stroustrup"
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
  indent-tabs-mode:nil
  fill-column:99
  End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :