summaryrefslogtreecommitdiffstats
path: root/src/ui/dialog/xml-tree.h
blob: 0a6c4d920f132d0c9b5b36addb17089e1492a2b6 (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
// 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 INKSCAPE_UI_DIALOG_XML_TREE_H
#define INKSCAPE_UI_DIALOG_XML_TREE_H

#include <glibmm/ustring.h>
#include <gtkmm/treeview.h>
#include <gtkmm/widget.h>
#include <memory>
#include <glibmm/refptr.h>
#include <gtkmm/builder.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 "message.h"
#include "attrdialog.h"
#include "dialog-base.h"
#include "preferences.h"
#include "ui/syntax.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;

    void setSyntaxStyle(Inkscape::UI::Syntax::XMLStyles const &new_style);

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);

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

    /**
     * Select a node in the xml tree
     */
    void set_tree_select(Inkscape::XML::Node *repr, bool edit = false);

    /**
     * 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 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.
     */
    Inkscape::auto_connection _tree_select_idle;
    bool deferred_on_tree_select_row();

    /**
      * 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 _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 _resized();
    bool in_dt_coordsys(SPObject const &item);

    void rebuildTree();
    void stopNodeEditing(bool ok, Glib::ustring const &path, Glib::ustring name);
    void startNodeEditing(Gtk::CellEditable *cell, Glib::ustring const &path);

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

    /**
     * Signal handlers
     */
    Inkscape::XML::Node *selected_repr = nullptr;

    /* XmlTree Widgets */
    SPXMLViewTree *tree = nullptr;
    Gtk::TreeView* _treemm = nullptr;
    AttrDialog *attributes;
    Gtk::Box *_attrbox;

    /* XML Node Creation pop-up window */
    Glib::RefPtr<Gtk::Builder> _builder;
    Gtk::Entry *name_entry;
    Gtk::Button *create_button;
    Gtk::Paned& _paned;

    // Gtk::Box node_box;
    Gtk::Switch _attrswitch;
    Gtk::Label status;
    Gtk::Button& xml_element_new_button;
    Gtk::Button& xml_text_new_button;
    Gtk::Button& xml_node_delete_button;
    Gtk::Button& xml_node_duplicate_button;
    Gtk::Button& unindent_node_button;
    Gtk::Button& indent_node_button;
    Gtk::Button& raise_node_button;
    Gtk::Button& lower_node_button;

    enum DialogLayout: int { Auto = 0, Horizontal, Vertical };
    DialogLayout _layout = Auto;
    Pref<Glib::ustring> _syntax_theme;
    Pref<bool> _mono_font;
    Inkscape::XML::Node* _dummy = nullptr;
    Inkscape::XML::Node* _node_parent = nullptr;
};

} // namespace Dialog
} // namespace UI
} // namespace Inkscape

#endif // INKSCAPE_UI_DIALOG_XML_TREE_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 :