summaryrefslogtreecommitdiffstats
path: root/src/ui/dialog/xml-tree.h
blob: 35866669e4badca5ccd24fac9790915fd436c3f3 (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
// SPDX-License-Identifier: GPL-2.0-or-later
/** @file
 * This is XML tree editor, which allows direct modifying of all elements
 *   of Inkscape document, including foreign ones.
 *//*
 * Authors: see git history
 * Lauris Kaplinski, 2000
 *
 * Copyright (C) 2018 Authors
 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
 */

#ifndef SEEN_UI_DIALOGS_XML_TREE_H
#define SEEN_UI_DIALOGS_XML_TREE_H

#include <gtkmm/button.h>
#include <gtkmm/entry.h>
#include <gtkmm/paned.h>
#include <gtkmm/radiobutton.h>
#include <gtkmm/scrolledwindow.h>
#include <gtkmm/separatortoolitem.h>
#include <gtkmm/switch.h>
#include <gtkmm/textview.h>
#include <gtkmm/toolbar.h>
#include <memory>

#include "message.h"
#include "ui/dialog/attrdialog.h"
#include "ui/dialog/dialog-base.h"

class SPObject;
struct SPXMLViewAttrList;
struct SPXMLViewContent;
struct SPXMLViewTree;

namespace Inkscape {
class MessageStack;
class MessageContext;

namespace XML {
class Node;
}

namespace UI {
namespace Dialog {

/**
 * A dialog widget to view and edit the document xml
 *
 */

class XmlTree : public DialogBase
{
public:
    XmlTree ();
    ~XmlTree () override;

    static XmlTree &getInstance() { return *new XmlTree(); }

private:
    void unsetDocument();
    void documentReplaced() override;
    void selectionChanged(Selection *selection) override;
    void desktopReplaced() override;

    /**
     * Select a node in the xml tree
     */
    void set_tree_repr(Inkscape::XML::Node *repr);

    /**
     * Sets the XML status bar when the tree is selected.
     */
    void tree_reset_context();

    /**
     * Is the selected tree node editable
     */
    gboolean xml_tree_node_mutable(GtkTreeIter *node);

    /**
     * Callback to close the add dialog on Escape key
     */
    static gboolean quit_on_esc (GtkWidget *w, GdkEventKey *event, GObject */*tbl*/);

    /**
     * Select a node in the xml tree
     */
    void set_tree_select(Inkscape::XML::Node *repr);

    /**
     * Set the attribute list to match the selected node in the tree
     */
    void propagate_tree_select(Inkscape::XML::Node *repr);

    /**
      * Find the current desktop selection
      */
    Inkscape::XML::Node *get_dt_select();

    /**
      * Select the current desktop selection
      */
    void set_dt_select(Inkscape::XML::Node *repr);

    /**
      * Callback for a node in the tree being selected
      */
    static void on_tree_select_row(GtkTreeSelection *selection, gpointer data);
    /**
     * Callback for deferring the `on_tree_select_row` response in order to
     * skip invalid intermediate selection states. In particular,
     * `gtk_tree_store_remove` makes an undesired selection that we will
     * immediately revert and don't want to an early response for.
     */
    static gboolean deferred_on_tree_select_row(gpointer);
    /// Event source ID for the last scheduled `deferred_on_tree_select_row` event.
    guint deferred_on_tree_select_row_id = 0;

    /**
      * Callback when a node is moved in the tree
      */
    static void after_tree_move(SPXMLViewTree *tree, gpointer value, gpointer data);

    /**
      * Callback for when an attribute is edited.
      */
    //static void on_attr_edited(SPXMLViewAttrList *attributes, const gchar * name, const gchar * value, gpointer /*data*/);

    /**
      * Callback for when attribute list values change
      */
    //static void on_attr_row_changed(SPXMLViewAttrList *attributes, const gchar * name, gpointer data);

    /**
      * Enable widgets based on current selections
      */
    void on_tree_select_row_enable(GtkTreeIter *node);
    void on_tree_unselect_row_disable();
    void on_tree_unselect_row_hide();
    void on_attr_unselect_row_disable();

    void onNameChanged();
    void onCreateNameChanged();

    /**
      * Callbacks for changes in desktop selection and current document
      */
    static void on_document_uri_set(gchar const *uri, SPDocument *document);
    static void _set_status_message(Inkscape::MessageType type, const gchar *message, GtkWidget *dialog);

    /**
      * Callbacks for toolbar buttons being pressed
      */
    void cmd_new_element_node();
    void cmd_new_text_node();
    void cmd_duplicate_node();
    void cmd_delete_node();
    void cmd_raise_node();
    void cmd_lower_node();
    void cmd_indent_node();
    void cmd_unindent_node();

    void _attrtoggler();
    void _toggleDirection(Gtk::RadioButton *vertical);
    void _resized();
    bool in_dt_coordsys(SPObject const &item);

    /**
     * Flag to ensure only one operation is performed at once
     */
    gint blocked;

    bool _updating;
    /**
     * Status bar
     */
    std::shared_ptr<Inkscape::MessageStack> _message_stack;
    std::unique_ptr<Inkscape::MessageContext> _message_context;

    /**
     * Signal handlers
     */
    sigc::connection _message_changed_connection;
    sigc::connection document_uri_set_connection;

    gint selected_attr;
    Inkscape::XML::Node *selected_repr;

    /* XmlTree Widgets */
    SPXMLViewTree *tree;
    //SPXMLViewAttrList *attributes;
    AttrDialog *attributes;
    Gtk::Box *_attrbox;

    /* XML Node Creation pop-up window */
    Gtk::Entry *name_entry;
    Gtk::Button *create_button;
    Gtk::Paned _paned;

    Gtk::Box node_box;
    Gtk::Box status_box;
    Gtk::Switch _attrswitch;
    Gtk::Label status;
    Gtk::Toolbar tree_toolbar;
    Gtk::ToolButton xml_element_new_button;
    Gtk::ToolButton xml_text_new_button;
    Gtk::ToolButton xml_node_delete_button;
    Gtk::SeparatorToolItem separator;
    Gtk::ToolButton xml_node_duplicate_button;
    Gtk::SeparatorToolItem separator2;
    Gtk::ToolButton unindent_node_button;
    Gtk::ToolButton indent_node_button;
    Gtk::ToolButton raise_node_button;
    Gtk::ToolButton lower_node_button;

    GtkWidget *new_window;

    gulong _selection_changed = 0;
    gulong _tree_move = 0;
};

}
}
}

#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:fileencoding=utf-8:textwidth=99 :