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
|
// SPDX-License-Identifier: GPL-2.0-or-later
/** @file
* @brief A dialog for CSS selectors
*/
/* Authors:
* Kamalpreet Kaur Grewal
* Tavmjong Bah
*
* Copyright (C) Kamalpreet Kaur Grewal 2016 <grewalkamal005@gmail.com>
* Copyright (C) Tavmjong Bah 2017 <tavmjong@free.fr>
*
* Released under GNU GPL v2+, read the file 'COPYING' for more information.
*/
#ifndef STYLEDIALOG_H
#define STYLEDIALOG_H
#include <glibmm/regex.h>
#include <gtkmm/adjustment.h>
#include <gtkmm/builder.h>
#include <gtkmm/celleditable.h>
#include <gtkmm/cellrenderercombo.h>
#include <gtkmm/dialog.h>
#include <gtkmm/entry.h>
#include <gtkmm/entrycompletion.h>
#include <gtkmm/eventbox.h>
#include <gtkmm/liststore.h>
#include <gtkmm/paned.h>
#include <gtkmm/scrolledwindow.h>
#include <gtkmm/switch.h>
#include <gtkmm/tooltip.h>
#include <gtkmm/treemodelfilter.h>
#include <gtkmm/treeselection.h>
#include <gtkmm/treestore.h>
#include <gtkmm/treeview.h>
#include <gtkmm/viewport.h>
#include <memory>
#include <vector>
#include "style-enums.h"
#include "ui/dialog/dialog-base.h"
#include "xml/helper-observer.h"
namespace Inkscape {
XML::Node *get_first_style_text_node(XML::Node *root, bool create_if_missing);
namespace UI {
namespace Dialog {
/**
* @brief The StyleDialog class
* A list of CSS selectors will show up in this dialog. This dialog allows one to
* add and delete selectors. Elements can be added to and removed from the selectors
* in the dialog. Selection of any selector row selects the matching objects in
* the drawing and vice-versa. (Only simple selectors supported for now.)
*
* This class must keep two things in sync:
* 1. The text node of the style element.
* 2. The Gtk::TreeModel.
*/
class StyleDialog : public DialogBase
{
public:
// No default constructor, noncopyable, nonassignable
StyleDialog();
~StyleDialog() override;
StyleDialog(StyleDialog const &d) = delete;
StyleDialog operator=(StyleDialog const &d) = delete;
void documentReplaced() override;
void selectionChanged(Selection *selection) override;
static StyleDialog &getInstance() { return *new StyleDialog(); }
void setCurrentSelector(Glib::ustring current_selector);
Gtk::TreeView *_current_css_tree;
Gtk::TreeViewColumn *_current_value_col;
Gtk::TreeModel::Path _current_path;
bool _deletion;
Glib::ustring fixCSSSelectors(Glib::ustring selector);
void readStyleElement();
private:
// Monitor <style> element for changes.
class NodeObserver;
// Monitor all objects for addition/removal/attribute change
class NodeWatcher;
Glib::RefPtr<Glib::Regex> r_props = Glib::Regex::create("\\s*;\\s*");
Glib::RefPtr<Glib::Regex> r_pair = Glib::Regex::create("\\s*:\\s*");
void _nodeAdded(Inkscape::XML::Node &repr);
void _nodeRemoved(Inkscape::XML::Node &repr);
void _nodeChanged(Inkscape::XML::Node &repr);
void removeObservers();
/* void _stylesheetChanged( Inkscape::XML::Node &repr ); */
// Data structure
class ModelColumns : public Gtk::TreeModel::ColumnRecord {
public:
ModelColumns()
{
add(_colActive);
add(_colName);
add(_colValue);
add(_colStrike);
add(_colSelector);
add(_colSelectorPos);
add(_colOwner);
add(_colLinked);
add(_colHref);
}
Gtk::TreeModelColumn<bool> _colActive; // Active or inactive property
Gtk::TreeModelColumn<Glib::ustring> _colName; // Name of the property.
Gtk::TreeModelColumn<Glib::ustring> _colValue; // Value of the property.
Gtk::TreeModelColumn<bool> _colStrike; // Property not used, overloaded
Gtk::TreeModelColumn<Glib::ustring> _colSelector; // Style or matching object id.
Gtk::TreeModelColumn<gint> _colSelectorPos; // Position of the selector to handle dup selectors
Gtk::TreeModelColumn<Glib::ustring> _colOwner; // Store the owner of the property for popup
Gtk::TreeModelColumn<bool> _colLinked; // Other object linked
Gtk::TreeModelColumn<SPObject *> _colHref; // Is going to another object
};
ModelColumns _mColumns;
class CSSData : public Gtk::TreeModel::ColumnRecord {
public:
CSSData() { add(_colCSSData); }
Gtk::TreeModelColumn<Glib::ustring> _colCSSData; // Name of the property.
};
CSSData _mCSSData;
guint _deleted_pos;
// Widgets
Gtk::ScrolledWindow _scrolledWindow;
Glib::RefPtr<Gtk::Adjustment> _vadj;
Gtk::Box _mainBox;
Gtk::Box _styleBox;
// Reading and writing the style element.
Inkscape::XML::Node *_getStyleTextNode(bool create_if_missing = false);
Glib::RefPtr<Gtk::TreeModel> _selectTree(Glib::ustring selector);
void _writeStyleElement(Glib::RefPtr<Gtk::TreeStore> store, Glib::ustring selector,
Glib::ustring new_selector = "");
// void _selectorActivate(Glib::RefPtr<Gtk::TreeStore> store, Gtk::Label *selector, Gtk::Entry *selector_edit);
bool _selectorEditKeyPress(GdkEventKey *event, Glib::RefPtr<Gtk::TreeStore> store, Gtk::Label *selector,
Gtk::Entry *selector_edit);
bool _selectorStartEdit(GdkEventButton *event, Gtk::Label *selector, Gtk::Entry *selector_edit);
void _activeToggled(const Glib::ustring &path, Glib::RefPtr<Gtk::TreeStore> store);
bool _addRow(GdkEventButton *evt, Glib::RefPtr<Gtk::TreeStore> store, Gtk::TreeView *css_tree,
Glib::ustring selector, gint pos);
void _onPropDelete(Glib::ustring path, Glib::RefPtr<Gtk::TreeStore> store);
void _nameEdited(const Glib::ustring &path, const Glib::ustring &name, Glib::RefPtr<Gtk::TreeStore> store,
Gtk::TreeView *css_tree);
bool _onNameKeyReleased(GdkEventKey *event, Gtk::Entry *entry);
bool _onValueKeyReleased(GdkEventKey *event, Gtk::Entry *entry);
bool _onNameKeyPressed(GdkEventKey *event, Gtk::Entry *entry);
bool _onValueKeyPressed(GdkEventKey *event, Gtk::Entry *entry);
void _onLinkObj(Glib::ustring path, Glib::RefPtr<Gtk::TreeStore> store);
void _valueEdited(const Glib::ustring &path, const Glib::ustring &value, Glib::RefPtr<Gtk::TreeStore> store);
void _startNameEdit(Gtk::CellEditable *cell, const Glib::ustring &path);
void _startValueEdit(Gtk::CellEditable *cell, const Glib::ustring &path, Glib::RefPtr<Gtk::TreeStore> store);
void _setAutocompletion(Gtk::Entry *entry, SPStyleEnum const cssenum[]);
void _setAutocompletion(Gtk::Entry *entry, Glib::ustring name);
bool _on_foreach_iter(const Gtk::TreeModel::iterator &iter);
void _reload();
void _vscroll();
bool _scrollock;
double _scrollpos;
Glib::ustring _current_selector;
// Update watchers
std::unique_ptr<Inkscape::XML::NodeObserver> m_nodewatcher;
std::unique_ptr<Inkscape::XML::NodeObserver> m_styletextwatcher;
// Manipulate Tree
std::vector<SPObject *> _getObjVec(Glib::ustring selector);
std::map<Glib::ustring, Glib::ustring> parseStyle(Glib::ustring style_string);
std::map<Glib::ustring, Glib::ustring> _owner_style;
void _addOwnerStyle(Glib::ustring name, Glib::ustring selector);
// Variables
Inkscape::XML::Node *m_root = nullptr;
Inkscape::XML::Node *_textNode; // Track so we know when to add a NodeObserver.
bool _updating; // Prevent cyclic actions: read <-> write, select via dialog <-> via desktop
void _closeDialog(Gtk::Dialog *textDialogPtr);
};
} // namespace Dialog
} // namespace UI
} // namespace Inkscape
#endif // STYLEDIALOG_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 :
|