/[svn]/gigedit/trunk/src/gigedit/MacroEditor.cpp
ViewVC logotype

Annotation of /gigedit/trunk/src/gigedit/MacroEditor.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3154 - (hide annotations) (download)
Sat May 6 13:46:14 2017 UTC (3 years, 3 months ago) by schoenebeck
File size: 11169 byte(s)
* WIP Macro Editor: Implemented deleting of rows.
* WIP Macro Editor: Implemented changing values 
  of rows.
* WIP Macro Editor: show type column in gray color.
* Bumped version (1.0.0.svn36).

1 schoenebeck 3151 /*
2     Copyright (c) MMXVII Christian Schoenebeck
3    
4     This file is part of "gigedit" and released under the terms of the
5     GNU General Public License version 2.
6     */
7    
8     #include "MacroEditor.h"
9     #include "global.h"
10     #include <assert.h>
11    
12     MacroEditor::MacroEditor() :
13     m_macroOriginal(NULL),
14     m_statusLabel("", Gtk::ALIGN_START),
15 schoenebeck 3154 m_deleteButton(_("Delete")),
16     m_inverseDeleteButton(_("Inverse Delete")),
17 schoenebeck 3151 m_applyButton(_("_Apply"), true),
18     m_cancelButton(_("_Cancel"), true)
19     {
20     add(m_vbox);
21    
22     set_default_size(800, 600);
23    
24     // create Macro treeview (including its data model)
25     m_treeStoreMacro = MacroTreeStore::create(m_treeModelMacro);
26     m_treeViewMacro.set_model(m_treeStoreMacro);
27     m_treeViewMacro.get_selection()->set_mode(Gtk::SELECTION_MULTIPLE);
28     //m_treeViewMacro.set_tooltip_text(_(""));
29     m_treeViewMacro.append_column(_("Key"), m_treeModelMacro.m_col_name);
30     m_treeViewMacro.append_column(_("Type"), m_treeModelMacro.m_col_type);
31     m_treeViewMacro.append_column_editable(_("Value"), m_treeModelMacro.m_col_value);
32 schoenebeck 3154 {
33     Gtk::TreeViewColumn* column = m_treeViewMacro.get_column(1);
34     Gtk::CellRendererText* cellrenderer =
35     dynamic_cast<Gtk::CellRendererText*>(column->get_first_cell());
36     cellrenderer->property_foreground().set_value("#bababa");
37     }
38 schoenebeck 3151 /*{
39     Gtk::TreeViewColumn* column = m_treeViewMacro.get_column(0);
40     Gtk::CellRendererText* cellrenderer =
41     dynamic_cast<Gtk::CellRendererText*>(column->get_first_cell());
42     column->add_attribute(
43     cellrenderer->property_foreground(), m_SamplesModel.m_color
44     );
45     }*/
46     /*{
47     Gtk::TreeViewColumn* column = m_treeViewMacro.get_column(1);
48     Gtk::CellRendererText* cellrenderer =
49     dynamic_cast<Gtk::CellRendererText*>(column->get_first_cell());
50     column->add_attribute(
51     cellrenderer->property_foreground(), m_SamplesModel.m_color
52     );
53     }*/
54     m_treeViewMacro.set_headers_visible(true);
55 schoenebeck 3154 m_treeViewMacro.get_selection()->signal_changed().connect(
56     sigc::mem_fun(*this, &MacroEditor::onTreeViewSelectionChanged)
57     );
58     m_treeViewMacro.signal_key_release_event().connect_notify(
59     sigc::mem_fun(*this, &MacroEditor::onMacroTreeViewKeyRelease)
60     );
61     m_treeStoreMacro->signal_row_changed().connect(
62     sigc::mem_fun(*this, &MacroEditor::onMacroTreeViewRowValueChanged)
63     );
64     m_ignoreTreeViewValueChange = false;
65 schoenebeck 3151
66     m_scrolledWindow.add(m_treeViewMacro);
67     m_scrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
68     m_vbox.pack_start(m_scrolledWindow);
69    
70 schoenebeck 3154 m_buttonBoxL.set_layout(Gtk::BUTTONBOX_START);
71     m_buttonBoxL.pack_start(m_deleteButton);
72     m_buttonBoxL.pack_start(m_inverseDeleteButton);
73     m_deleteButton.set_sensitive(false);
74     m_inverseDeleteButton.set_sensitive(false);
75    
76 schoenebeck 3151 m_buttonBox.set_layout(Gtk::BUTTONBOX_END);
77     m_buttonBox.pack_start(m_applyButton);
78     m_buttonBox.pack_start(m_cancelButton);
79     m_applyButton.set_can_default();
80     m_applyButton.set_sensitive(false);
81     m_applyButton.grab_focus();
82    
83     #if GTKMM_MAJOR_VERSION >= 3
84     m_statusLabel.set_margin_left(6);
85     m_statusLabel.set_margin_right(6);
86     #else
87     m_statusHBox.set_spacing(6);
88     #endif
89    
90     m_statusHBox.pack_start(m_statusLabel);
91     m_statusHBox.show_all_children();
92    
93 schoenebeck 3154 m_footerHBox.pack_start(m_buttonBoxL, Gtk::PACK_SHRINK);
94 schoenebeck 3151 m_footerHBox.pack_start(m_statusHBox);
95     m_footerHBox.pack_start(m_buttonBox, Gtk::PACK_SHRINK);
96    
97     m_vbox.pack_start(m_footerHBox, Gtk::PACK_SHRINK);
98    
99     m_applyButton.signal_clicked().connect(
100     sigc::mem_fun(*this, &MacroEditor::onButtonApply)
101     );
102    
103     m_cancelButton.signal_clicked().connect(
104     sigc::mem_fun(*this, &MacroEditor::onButtonCancel)
105     );
106    
107 schoenebeck 3154 m_deleteButton.signal_clicked().connect(
108     sigc::mem_fun(*this, &MacroEditor::deleteSelectedRows)
109     );
110    
111     m_inverseDeleteButton.signal_clicked().connect(
112     sigc::mem_fun(*this, &MacroEditor::inverseDeleteSelectedRows)
113     );
114    
115 schoenebeck 3151 signal_hide().connect(
116     sigc::mem_fun(*this, &MacroEditor::onWindowHide)
117     );
118    
119     signal_delete_event().connect(
120     sigc::mem_fun(*this, &MacroEditor::onWindowDelete)
121     );
122    
123     show_all_children();
124     updateStatus();
125     }
126    
127     MacroEditor::~MacroEditor() {
128     printf("MacroEditor destruct\n");
129     }
130    
131     void MacroEditor::setMacro(Serialization::Archive* macro) {
132     m_macroOriginal = macro;
133     if (!macro) {
134     set_title(_("No Macro"));
135     return;
136     }
137    
138     //set_title(std::string(_("Macro Editor:")) + " \"" + macro->name() + "\"");
139     set_title(std::string(_("Macro Editor:")));
140    
141     // copy for non-destructive editing
142     m_macro = *macro;
143    
144     reloadTreeView();
145     }
146    
147     void MacroEditor::buildTreeView(const Gtk::TreeModel::Row& parentRow, const Serialization::Object& parentObject) {
148     for (int iMember = 0; iMember < parentObject.members().size(); ++iMember) {
149     const Serialization::Member& member = parentObject.members()[iMember];
150     const Serialization::Object& object = m_macro.objectByUID(member.uid());
151     Gtk::TreeModel::iterator iterRow = m_treeStoreMacro->append(parentRow.children());
152     Gtk::TreeModel::Row row = *iterRow;
153     row[m_treeModelMacro.m_col_name] = gig_to_utf8(member.name());
154     row[m_treeModelMacro.m_col_type] = gig_to_utf8(member.type().asLongDescr());
155     row[m_treeModelMacro.m_col_uid] = object.uid();
156     if (object.type().isClass()) {
157     row[m_treeModelMacro.m_col_value] = "(class)";
158     buildTreeView(row, object);
159     } else {
160     row[m_treeModelMacro.m_col_value] = m_macro.valueAsString(object);
161     }
162     }
163     }
164    
165     void MacroEditor::reloadTreeView() {
166 schoenebeck 3154 m_ignoreTreeViewValueChange = true;
167    
168 schoenebeck 3151 m_treeStoreMacro->clear();
169    
170     const Serialization::Object& rootObject = m_macro.rootObject();
171    
172     Gtk::TreeModel::iterator iterRoot = m_treeStoreMacro->append();
173     Gtk::TreeModel::Row rowRoot = *iterRoot;
174     rowRoot[m_treeModelMacro.m_col_name] = "(Root)";
175     rowRoot[m_treeModelMacro.m_col_type] = gig_to_utf8(rootObject.type().asLongDescr());
176     rowRoot[m_treeModelMacro.m_col_value] = "";
177     rowRoot[m_treeModelMacro.m_col_uid] = rootObject.uid();
178    
179     buildTreeView(rowRoot, rootObject);
180    
181     m_treeViewMacro.expand_all();
182    
183     updateStatus();
184 schoenebeck 3154
185     m_ignoreTreeViewValueChange = false;
186 schoenebeck 3151 }
187    
188 schoenebeck 3154 void MacroEditor::onTreeViewSelectionChanged() {
189     std::vector<Gtk::TreeModel::Path> v = m_treeViewMacro.get_selection()->get_selected_rows();
190     const bool bValidSelection = !v.empty();
191     m_deleteButton.set_sensitive(bValidSelection);
192     m_inverseDeleteButton.set_sensitive(bValidSelection);
193     }
194    
195     void MacroEditor::onMacroTreeViewKeyRelease(GdkEventKey* key) {
196     if (key->keyval == GDK_KEY_BackSpace || key->keyval == GDK_KEY_Delete)
197     deleteSelectedRows();
198     }
199    
200     void MacroEditor::onMacroTreeViewRowValueChanged(const Gtk::TreeModel::Path& path,
201     const Gtk::TreeModel::iterator& iter)
202     {
203     if (m_ignoreTreeViewValueChange) return;
204     if (!iter) return;
205     Gtk::TreeModel::Row row = *iter;
206     Glib::ustring value = row[m_treeModelMacro.m_col_value];
207     Serialization::UID uid = row[m_treeModelMacro.m_col_uid];
208     Serialization::String gigvalue(gig_from_utf8(value));
209     Serialization::Object& object = m_macro.objectByUID(uid);
210     std::string errorText;
211     try {
212     m_macro.setAutoValue(object, gigvalue);
213     } catch (Serialization::Exception e) {
214     errorText = e.Message;
215     } catch (...) {
216     errorText = _("Unknown exception during object value change");
217     }
218     if (!errorText.empty()) {
219     Glib::ustring txt = _("Couldn't change value:\n") + errorText;
220     Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
221     msg.run();
222     }
223     }
224    
225     void MacroEditor::deleteSelectedRows() {
226     Glib::RefPtr<Gtk::TreeSelection> sel = m_treeViewMacro.get_selection();
227     std::vector<Gtk::TreeModel::Path> rows = sel->get_selected_rows();
228     for (int r = rows.size() - 1; r >= 0; --r) {
229     Gtk::TreeModel::iterator it = m_treeStoreMacro->get_iter(rows[r]);
230     if (!it) continue;
231     Gtk::TreeModel::Row row = *it;
232     Serialization::UID uid = row[m_treeModelMacro.m_col_uid];
233     if (uid == m_macro.rootObject().uid()) continue; // prohibit deleting root object
234     Gtk::TreeModel::iterator itParent = row.parent();
235     if (!itParent) continue;
236     Gtk::TreeModel::Row rowParent = *itParent;
237     Serialization::UID uidParent = rowParent[m_treeModelMacro.m_col_uid];
238     //Serialization::Object& object = m_macro.objectByUID(uid);
239     Serialization::Object& parentObject = m_macro.objectByUID(uidParent);
240     const Serialization::Member& member = parentObject.memberByUID(uid);
241     m_macro.removeMember(parentObject, member);
242     //m_macro.remove(object);
243     }
244     reloadTreeView();
245     }
246    
247     void MacroEditor::inverseDeleteSelectedRows() {
248     }
249    
250 schoenebeck 3151 void MacroEditor::updateStatus() {
251     m_applyButton.set_sensitive(isModified());
252     updateStatusBar();
253     }
254    
255     void MacroEditor::updateStatusBar() {
256     // update status text
257     std::string txt;
258     m_statusLabel.set_markup(txt);
259     }
260    
261     bool MacroEditor::onWindowDelete(GdkEventAny* e) {
262     //printf("onWindowDelete\n");
263    
264     if (!isModified()) return false; // propagate event further (which will close this window)
265    
266     //gchar* msg = g_strdup_printf(_("Apply changes to macro \"%s\" before closing?"),
267     // m_macroOriginal->Name.c_str());
268     gchar* msg = g_strdup_printf(_("Apply changes to macro before closing?"));
269     Gtk::MessageDialog dialog(*this, msg, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE);
270     g_free(msg);
271     dialog.set_secondary_text(_("If you close without applying, your changes will be lost."));
272     dialog.add_button(_("Close _Without Applying"), Gtk::RESPONSE_NO);
273     dialog.add_button(_("_Cancel"), Gtk::RESPONSE_CANCEL);
274     dialog.add_button(_("_Apply"), Gtk::RESPONSE_YES);
275     dialog.set_default_response(Gtk::RESPONSE_YES);
276     int response = dialog.run();
277     dialog.hide();
278    
279     // user decided to close macro editor without saving
280     if (response == Gtk::RESPONSE_NO)
281     return false; // propagate event further (which will close this window)
282    
283     // user cancelled dialog, thus don't close macro editor
284     if (response == Gtk::RESPONSE_CANCEL) {
285     show();
286     return true; // drop event (prevents closing this window)
287     }
288    
289     // user wants to apply the changes, afterwards close window
290     if (response == Gtk::RESPONSE_YES) {
291     onButtonApply();
292     return false; // propagate event further (which will close this window)
293     }
294    
295     // should never ever make it to this point actually
296     return false;
297     }
298    
299     bool MacroEditor::isModified() const {
300     return m_macro.isModified();
301     }
302    
303     void MacroEditor::onButtonCancel() {
304     bool dropEvent = onWindowDelete(NULL);
305     if (dropEvent) return;
306     hide();
307     }
308    
309     void MacroEditor::onButtonApply() {
310     //m_macro.encode();
311     *m_macroOriginal = m_macro;
312     }
313    
314     void MacroEditor::onWindowHide() {
315     delete this; // this is the end, my friend
316     }

  ViewVC Help
Powered by ViewVC