summaryrefslogtreecommitdiffstats
path: root/src/document.h
blob: 8a4e65bb373fe57541f868a79aca6c9aafcf1838 (plain)
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
281
#ifndef __SP_DOCUMENT_H__
#define __SP_DOCUMENT_H__

/** \file
 * SPDocument: Typed SVG document implementation
 *
 * Authors:
 *   Lauris Kaplinski <lauris@kaplinski.com>
 *   MenTaLguY <mental@rydia.net>
 *
 * 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 <sigc++/sigc++.h>
#include <sigc++/class_slot.h>

#include "libcroco/cr-cascade.h"
#include "libnr/nr-forward.h"

#include "gc-managed.h"
#include "gc-finalized.h"
#include "gc-anchored.h"
#include <glibmm/ustring.h>
#include "verbs.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;

namespace Proj {
  class TransfMat3x4;
}

class SPDocumentPrivate;

/// Typed SVG document implementation.
struct SPDocument : public Inkscape::GC::Managed<>,
                    public Inkscape::GC::Finalized,
                    public Inkscape::GC::Anchored
{
    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;

    gchar *uri; ///< URI string or NULL
    gchar *base;
    gchar *name;

    SPDocumentPrivate *priv;

    /// Last action key
    const gchar *actionkey;
    /// Handler ID
    guint modified_id;

    Inkscape::ProfileManager* profileManager;

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

    GSList *perspectives;

    Persp3D *current_persp3d; // "currently active" perspective (e.g., newly created boxes are attached to this one)
    std::set<Persp3D *> persps_sel; // perspectives associated to currently selected boxes

    void add_persp3d (Persp3D * const persp);
    void remove_persp3d (Persp3D * const persp);

    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);
    sigc::connection connectIdChanged(const gchar *id, IDChangedSignal::slot_type slot);

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

    Glib::ustring getLanguage();

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

    void _emitModified();

    GSList *_collection_queue;

    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

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;

    void fitToRect(NR::Rect const &rect);
};

SPDocument *sp_document_new (const gchar *uri, unsigned int keepalive, bool make_new = false);
SPDocument *sp_document_new_from_mem (const gchar *buffer, gint length, unsigned int keepalive);

SPDocument *sp_document_ref (SPDocument *doc);
SPDocument *sp_document_unref (SPDocument *doc);


SPDocument *sp_document_create(Inkscape::XML::Document *rdoc, gchar const *uri, gchar const *base, gchar const *name, unsigned int keepalive);

/*
 * Access methods
 */

#define sp_document_repr_doc(d) (d->rdoc)
#define sp_document_repr_root(d) (d->rroot)
#define sp_document_root(d) (d->root)
#define SP_DOCUMENT_ROOT(d)  (d->root)

gdouble sp_document_width (SPDocument * document);
gdouble sp_document_height (SPDocument * document);

struct SPUnit;

void sp_document_set_width (SPDocument * document, gdouble width, const SPUnit *unit);
void sp_document_set_height (SPDocument * document, gdouble height, const SPUnit *unit);

#define SP_DOCUMENT_URI(d) (d->uri)
#define SP_DOCUMENT_NAME(d) (d->name)
#define SP_DOCUMENT_BASE(d) (d->base)

/*
 * Dictionary
 */

/*
 * Undo & redo
 */

void sp_document_set_undo_sensitive (SPDocument * document, bool sensitive);
bool sp_document_get_undo_sensitive (SPDocument const * document);

void sp_document_clear_undo (SPDocument * document);
void sp_document_clear_redo (SPDocument * document);

void sp_document_child_added (SPDocument *doc, SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *ref);
void sp_document_child_removed (SPDocument *doc, SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *ref);
void sp_document_attr_changed (SPDocument *doc, SPObject *object, const gchar *key, const gchar *oldval, const gchar *newval);
void sp_document_content_changed (SPDocument *doc, SPObject *object, const gchar *oldcontent, const gchar *newcontent);
void sp_document_order_changed (SPDocument *doc, SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *oldref, Inkscape::XML::Node *newref);

/* Object modification root handler */
void sp_document_request_modified (SPDocument *doc);
gint sp_document_ensure_up_to_date (SPDocument *doc);

/* Save all previous actions to stack, as one undo step */
void sp_document_done (SPDocument *document, unsigned int event_type, Glib::ustring event_description);
void sp_document_maybe_done (SPDocument *document, const gchar *keyconst, unsigned int event_type, Glib::ustring event_description);
void sp_document_reset_key (Inkscape::Application *inkscape, SPDesktop *desktop, GtkObject *base);

/* Cancel (and revert) current unsaved actions */
void sp_document_cancel (SPDocument *document);

/* Undo and redo */
gboolean sp_document_undo (SPDocument * document);
gboolean sp_document_redo (SPDocument * document);

/* Resource management */
gboolean sp_document_add_resource (SPDocument *document, const gchar *key, SPObject *object);
gboolean sp_document_remove_resource (SPDocument *document, const gchar *key, SPObject *object);
const GSList *sp_document_get_resource_list (SPDocument *document, const gchar *key);
sigc::connection sp_document_resources_changed_connect(SPDocument *document, const gchar *key, SPDocument::ResourcesChangedSignal::slot_type slot);


/*
 * 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 ;)]
 *
 */

/*
 * Misc
 */

GSList * sp_document_items_in_box(SPDocument *document, unsigned int dkey, NR::Rect const &box);
GSList * sp_document_partial_items_in_box(SPDocument *document, unsigned int dkey, NR::Rect const &box);
SPItem* sp_document_item_from_list_at_point_bottom (unsigned int dkey, SPGroup *group, const GSList *list, NR::Point const p, bool take_insensitive = false);
SPItem * sp_document_item_at_point (SPDocument *document, unsigned int key, NR::Point const p, gboolean into_groups, SPItem *upto = NULL);
GSList *sp_document_items_at_points(SPDocument *document, unsigned const key, std::vector<NR::Point> points);
SPItem *sp_document_group_at_point (SPDocument *document, unsigned int key,  NR::Point const p);

void sp_document_set_uri (SPDocument *document, const gchar *uri);
void sp_document_resized_signal_emit (SPDocument *doc, gdouble width, gdouble height);

unsigned int vacuum_document (SPDocument *document);

#endif

/*
  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:encoding=utf-8:textwidth=99 :