X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=radiant%2Fentityinspector.cpp;h=c5aeaa8b7fb0c7aae6a8e3a78c18557029822bca;hb=9dfae1c9b270ee369c6362903a9205b30751b95f;hp=de3086d8afa9fa6c018c0a7cae4e060ed5cbc235;hpb=d403cec8ee423acf0d27de872fbc3ba0b6bccbd8;p=xonotic%2Fnetradiant.git diff --git a/radiant/entityinspector.cpp b/radiant/entityinspector.cpp index de3086d8..c5aeaa8b 100644 --- a/radiant/entityinspector.cpp +++ b/radiant/entityinspector.cpp @@ -1,27 +1,28 @@ /* -Copyright (C) 1999-2006 Id Software, Inc. and contributors. -For a list of contributors, see the accompanying CONTRIBUTORS file. + Copyright (C) 1999-2006 Id Software, Inc. and contributors. + For a list of contributors, see the accompanying CONTRIBUTORS file. -This file is part of GtkRadiant. + This file is part of GtkRadiant. -GtkRadiant is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + GtkRadiant is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. -GtkRadiant is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + GtkRadiant is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with GtkRadiant; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ + You should have received a copy of the GNU General Public License + along with GtkRadiant; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ #include "entityinspector.h" #include "debugging/debugging.h" +#include #include "ientity.h" #include "ifilesystem.h" @@ -33,22 +34,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include #include "os/path.h" @@ -76,1126 +62,1117 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "entity.h" #include "mainframe.h" #include "textureentry.h" +#include "groupdialog.h" -GtkEntry* numeric_entry_new() +ui::Entry numeric_entry_new() { - GtkEntry* entry = GTK_ENTRY(gtk_entry_new()); - gtk_widget_show(GTK_WIDGET(entry)); - gtk_widget_set_size_request(GTK_WIDGET(entry), 64, -1); - return entry; + auto entry = ui::Entry(ui::New); + entry.show(); + entry.dimensions(64, -1); + return entry; } -namespace -{ - typedef std::map KeyValues; - KeyValues g_selectedKeyValues; - KeyValues g_selectedDefaultKeyValues; +namespace { + typedef std::map KeyValues; + KeyValues g_selectedKeyValues; + KeyValues g_selectedDefaultKeyValues; } -const char* SelectedEntity_getValueForKey(const char* key) +const char *SelectedEntity_getValueForKey(const char *key) { - { - KeyValues::const_iterator i = g_selectedKeyValues.find(key); - if(i != g_selectedKeyValues.end()) { - return (*i).second.c_str(); + KeyValues::const_iterator i = g_selectedKeyValues.find(key); + if (i != g_selectedKeyValues.end()) { + return (*i).second.c_str(); + } } - } - { - KeyValues::const_iterator i = g_selectedDefaultKeyValues.find(key); - if(i != g_selectedDefaultKeyValues.end()) { - return (*i).second.c_str(); + KeyValues::const_iterator i = g_selectedDefaultKeyValues.find(key); + if (i != g_selectedDefaultKeyValues.end()) { + return (*i).second.c_str(); + } } - } - return ""; + return ""; } -void Scene_EntitySetKeyValue_Selected_Undoable(const char* key, const char* value) +void Scene_EntitySetKeyValue_Selected_Undoable(const char *key, const char *value) { - StringOutputStream command(256); - command << "entitySetKeyValue -key " << makeQuoted(key) << " -value " << makeQuoted(value); - UndoableCommand undo(command.c_str()); - Scene_EntitySetKeyValue_Selected(key, value); + StringOutputStream command(256); + command << "entitySetKeyValue -key " << makeQuoted(key) << " -value " << makeQuoted(value); + UndoableCommand undo(command.c_str()); + Scene_EntitySetKeyValue_Selected(key, value); } -class EntityAttribute -{ +class EntityAttribute { public: - virtual GtkWidget* getWidget() const = 0; - virtual void update() = 0; - virtual void release() = 0; + virtual ~EntityAttribute() = default; + + virtual ui::Widget getWidget() const = 0; + + virtual void update() = 0; + + virtual void release() = 0; }; -class BooleanAttribute : public EntityAttribute -{ - CopiedString m_key; - GtkCheckButton* m_check; +class BooleanAttribute : public EntityAttribute { + CopiedString m_key; + ui::CheckButton m_check; + + static gboolean toggled(ui::Widget widget, BooleanAttribute *self) + { + self->apply(); + return FALSE; + } - static gboolean toggled(GtkWidget *widget, BooleanAttribute* self) - { - self->apply(); - return FALSE; - } public: - BooleanAttribute(const char* key) : - m_key(key), - m_check(0) - { - GtkCheckButton* check = GTK_CHECK_BUTTON(gtk_check_button_new()); - gtk_widget_show(GTK_WIDGET(check)); - - m_check = check; - - guint handler = g_signal_connect(G_OBJECT(check), "toggled", G_CALLBACK(toggled), this); - g_object_set_data(G_OBJECT(check), "handler", gint_to_pointer(handler)); - - update(); - } - GtkWidget* getWidget() const - { - return GTK_WIDGET(m_check); - } - void release() - { - delete this; - } - void apply() - { - Scene_EntitySetKeyValue_Selected_Undoable(m_key.c_str(), gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(m_check)) ? "1" : "0"); - } - typedef MemberCaller ApplyCaller; - - void update() - { - const char* value = SelectedEntity_getValueForKey(m_key.c_str()); - if(!string_empty(value)) - { - toggle_button_set_active_no_signal(GTK_TOGGLE_BUTTON(m_check), atoi(value) != 0); - } - else - { - toggle_button_set_active_no_signal(GTK_TOGGLE_BUTTON(m_check), false); - } - } - typedef MemberCaller UpdateCaller; + BooleanAttribute(const char *key) : + m_key(key), + m_check(ui::null) + { + auto check = ui::CheckButton(ui::New); + check.show(); + + m_check = check; + + guint handler = check.connect("toggled", G_CALLBACK(toggled), this); + g_object_set_data(G_OBJECT(check), "handler", gint_to_pointer(handler)); + + update(); + } + + ui::Widget getWidget() const + { + return m_check; + } + + void release() + { + delete this; + } + + void apply() + { + Scene_EntitySetKeyValue_Selected_Undoable(m_key.c_str(), m_check.active() ? "1" : "0"); + } + + typedef MemberCaller ApplyCaller; + + void update() + { + const char *value = SelectedEntity_getValueForKey(m_key.c_str()); + if (!string_empty(value)) { + toggle_button_set_active_no_signal(m_check, atoi(value) != 0); + } else { + toggle_button_set_active_no_signal(m_check, false); + } + } + + typedef MemberCaller UpdateCaller; }; -class StringAttribute : public EntityAttribute -{ - CopiedString m_key; - GtkEntry* m_entry; - NonModalEntry m_nonModal; +class StringAttribute : public EntityAttribute { + CopiedString m_key; + ui::Entry m_entry; + NonModalEntry m_nonModal; public: - StringAttribute(const char* key) : - m_key(key), - m_entry(0), - m_nonModal(ApplyCaller(*this), UpdateCaller(*this)) - { - GtkEntry* entry = GTK_ENTRY(gtk_entry_new()); - gtk_widget_show(GTK_WIDGET(entry)); - gtk_widget_set_size_request(GTK_WIDGET(entry), 50, -1); - - m_entry = entry; - m_nonModal.connect(m_entry); - } - GtkWidget* getWidget() const - { - return GTK_WIDGET(m_entry); - } - GtkEntry* getEntry() const - { - return m_entry; - } - - void release() - { - delete this; - } - void apply() - { - StringOutputStream value(64); - value << ConvertUTF8ToLocale(gtk_entry_get_text(m_entry)); - Scene_EntitySetKeyValue_Selected_Undoable(m_key.c_str(), value.c_str()); - } - typedef MemberCaller ApplyCaller; + StringAttribute(const char *key) : + m_key(key), + m_entry(ui::null), + m_nonModal(ApplyCaller(*this), UpdateCaller(*this)) + { + auto entry = ui::Entry(ui::New); + entry.show(); + entry.dimensions(50, -1); - void update() - { - StringOutputStream value(64); - value << ConvertLocaleToUTF8(SelectedEntity_getValueForKey(m_key.c_str())); - gtk_entry_set_text(m_entry, value.c_str()); - } - typedef MemberCaller UpdateCaller; + m_entry = entry; + m_nonModal.connect(m_entry); + } + + ui::Widget getWidget() const + { + return m_entry; + } + + ui::Entry getEntry() const + { + return m_entry; + } + + void release() + { + delete this; + } + + void apply() + { + StringOutputStream value(64); + value << m_entry.text(); + Scene_EntitySetKeyValue_Selected_Undoable(m_key.c_str(), value.c_str()); + } + + typedef MemberCaller ApplyCaller; + + void update() + { + StringOutputStream value(64); + value << SelectedEntity_getValueForKey(m_key.c_str()); + m_entry.text(value.c_str()); + } + + typedef MemberCaller UpdateCaller; }; -class ShaderAttribute : public StringAttribute -{ +class ShaderAttribute : public StringAttribute { public: - ShaderAttribute(const char* key) : StringAttribute(key) - { - GlobalShaderEntryCompletion::instance().connect(StringAttribute::getEntry()); - } + ShaderAttribute(const char *key) : StringAttribute(key) + { + GlobalShaderEntryCompletion::instance().connect(StringAttribute::getEntry()); + } }; -class ModelAttribute : public EntityAttribute -{ - CopiedString m_key; - BrowsedPathEntry m_entry; - NonModalEntry m_nonModal; +class ModelAttribute : public EntityAttribute { + CopiedString m_key; + BrowsedPathEntry m_entry; + NonModalEntry m_nonModal; public: - ModelAttribute(const char* key) : - m_key(key), - m_entry(BrowseCaller(*this)), - m_nonModal(ApplyCaller(*this), UpdateCaller(*this)) - { - m_nonModal.connect(m_entry.m_entry.m_entry); - } - void release() - { - delete this; - } - GtkWidget* getWidget() const - { - return GTK_WIDGET(m_entry.m_entry.m_frame); - } - void apply() - { - StringOutputStream value(64); - value << ConvertUTF8ToLocale(gtk_entry_get_text(GTK_ENTRY(m_entry.m_entry.m_entry))); - Scene_EntitySetKeyValue_Selected_Undoable(m_key.c_str(), value.c_str()); - } - typedef MemberCaller ApplyCaller; - void update() - { - StringOutputStream value(64); - value << ConvertLocaleToUTF8(SelectedEntity_getValueForKey(m_key.c_str())); - gtk_entry_set_text(GTK_ENTRY(m_entry.m_entry.m_entry), value.c_str()); - } - typedef MemberCaller UpdateCaller; - void browse(const BrowsedPathEntry::SetPathCallback& setPath) - { - const char *filename = misc_model_dialog(gtk_widget_get_toplevel(GTK_WIDGET(m_entry.m_entry.m_frame))); - - if(filename != 0) - { - setPath(filename); - apply(); - } - } - typedef MemberCaller1 BrowseCaller; + ModelAttribute(const char *key) : + m_key(key), + m_entry(BrowseCaller(*this)), + m_nonModal(ApplyCaller(*this), UpdateCaller(*this)) + { + m_nonModal.connect(m_entry.m_entry.m_entry); + } + + void release() + { + delete this; + } + + ui::Widget getWidget() const + { + return m_entry.m_entry.m_frame; + } + + void apply() + { + StringOutputStream value(64); + value << m_entry.m_entry.m_entry.text(); + Scene_EntitySetKeyValue_Selected_Undoable(m_key.c_str(), value.c_str()); + } + + typedef MemberCaller ApplyCaller; + + void update() + { + StringOutputStream value(64); + value << SelectedEntity_getValueForKey(m_key.c_str()); + m_entry.m_entry.m_entry.text(value.c_str()); + } + + typedef MemberCaller UpdateCaller; + + void browse(const BrowsedPathEntry::SetPathCallback &setPath) + { + const char *filename = misc_model_dialog(m_entry.m_entry.m_frame.window()); + + if (filename != 0) { + setPath(filename); + apply(); + } + } + + typedef MemberCaller BrowseCaller; }; -const char* browse_sound(GtkWidget* parent) +const char *browse_sound(ui::Widget parent) { - StringOutputStream buffer(1024); + StringOutputStream buffer(1024); - buffer << g_qeglobals.m_userGamePath.c_str() << "sound/"; + buffer << g_qeglobals.m_userGamePath.c_str() << "sound/"; - if(!file_readable(buffer.c_str())) - { - // just go to fsmain - buffer.clear(); - buffer << g_qeglobals.m_userGamePath.c_str() << "/"; - } + if (!file_readable(buffer.c_str())) { + // just go to fsmain + buffer.clear(); + buffer << g_qeglobals.m_userGamePath.c_str() << "/"; + } - const char* filename = file_dialog(parent, TRUE, "Open Wav File", buffer.c_str(), "sound"); - if(filename != 0) - { - const char* relative = path_make_relative(filename, GlobalFileSystem().findRoot(filename)); - if(relative == filename) - { - globalOutputStream() << "WARNING: could not extract the relative path, using full path instead\n"; + const char *filename = parent.file_dialog(TRUE, "Open Wav File", buffer.c_str(), "sound"); + if (filename != 0) { + const char *relative = path_make_relative(filename, GlobalFileSystem().findRoot(filename)); + if (relative == filename) { + globalOutputStream() << "WARNING: could not extract the relative path, using full path instead\n"; + } + return relative; } - return relative; - } - return filename; + return filename; } -class SoundAttribute : public EntityAttribute -{ - CopiedString m_key; - BrowsedPathEntry m_entry; - NonModalEntry m_nonModal; +class SoundAttribute : public EntityAttribute { + CopiedString m_key; + BrowsedPathEntry m_entry; + NonModalEntry m_nonModal; public: - SoundAttribute(const char* key) : - m_key(key), - m_entry(BrowseCaller(*this)), - m_nonModal(ApplyCaller(*this), UpdateCaller(*this)) - { - m_nonModal.connect(m_entry.m_entry.m_entry); - } - void release() - { - delete this; - } - GtkWidget* getWidget() const - { - return GTK_WIDGET(m_entry.m_entry.m_frame); - } - void apply() - { - StringOutputStream value(64); - value << ConvertUTF8ToLocale(gtk_entry_get_text(GTK_ENTRY(m_entry.m_entry.m_entry))); - Scene_EntitySetKeyValue_Selected_Undoable(m_key.c_str(), value.c_str()); - } - typedef MemberCaller ApplyCaller; - void update() - { - StringOutputStream value(64); - value << ConvertLocaleToUTF8(SelectedEntity_getValueForKey(m_key.c_str())); - gtk_entry_set_text(GTK_ENTRY(m_entry.m_entry.m_entry), value.c_str()); - } - typedef MemberCaller UpdateCaller; - void browse(const BrowsedPathEntry::SetPathCallback& setPath) - { - const char *filename = browse_sound(gtk_widget_get_toplevel(GTK_WIDGET(m_entry.m_entry.m_frame))); - - if(filename != 0) - { - setPath(filename); - apply(); - } - } - typedef MemberCaller1 BrowseCaller; + SoundAttribute(const char *key) : + m_key(key), + m_entry(BrowseCaller(*this)), + m_nonModal(ApplyCaller(*this), UpdateCaller(*this)) + { + m_nonModal.connect(m_entry.m_entry.m_entry); + } + + void release() + { + delete this; + } + + ui::Widget getWidget() const + { + return ui::Widget(m_entry.m_entry.m_frame); + } + + void apply() + { + StringOutputStream value(64); + value << m_entry.m_entry.m_entry.text(); + Scene_EntitySetKeyValue_Selected_Undoable(m_key.c_str(), value.c_str()); + } + + typedef MemberCaller ApplyCaller; + + void update() + { + StringOutputStream value(64); + value << SelectedEntity_getValueForKey(m_key.c_str()); + m_entry.m_entry.m_entry.text(value.c_str()); + } + + typedef MemberCaller UpdateCaller; + + void browse(const BrowsedPathEntry::SetPathCallback &setPath) + { + const char *filename = browse_sound(m_entry.m_entry.m_frame.window()); + + if (filename != 0) { + setPath(filename); + apply(); + } + } + + typedef MemberCaller BrowseCaller; }; inline double angle_normalised(double angle) { - return float_mod(angle, 360.0); + return float_mod(angle, 360.0); } -class AngleAttribute : public EntityAttribute -{ - CopiedString m_key; - GtkEntry* m_entry; - NonModalEntry m_nonModal; +class AngleAttribute : public EntityAttribute { + CopiedString m_key; + ui::Entry m_entry; + NonModalEntry m_nonModal; public: - AngleAttribute(const char* key) : - m_key(key), - m_entry(0), - m_nonModal(ApplyCaller(*this), UpdateCaller(*this)) - { - GtkEntry* entry = numeric_entry_new(); - m_entry = entry; - m_nonModal.connect(m_entry); - } - void release() - { - delete this; - } - GtkWidget* getWidget() const - { - return GTK_WIDGET(m_entry); - } - void apply() - { - StringOutputStream angle(32); - angle << angle_normalised(entry_get_float(m_entry)); - Scene_EntitySetKeyValue_Selected_Undoable(m_key.c_str(), angle.c_str()); - } - typedef MemberCaller ApplyCaller; - - void update() - { - const char* value = SelectedEntity_getValueForKey(m_key.c_str()); - if(!string_empty(value)) - { - StringOutputStream angle(32); - angle << angle_normalised(atof(value)); - gtk_entry_set_text(m_entry, angle.c_str()); - } - else - { - gtk_entry_set_text(m_entry, "0"); - } - } - typedef MemberCaller UpdateCaller; + AngleAttribute(const char *key) : + m_key(key), + m_entry(ui::null), + m_nonModal(ApplyCaller(*this), UpdateCaller(*this)) + { + auto entry = numeric_entry_new(); + m_entry = entry; + m_nonModal.connect(m_entry); + } + + void release() + { + delete this; + } + + ui::Widget getWidget() const + { + return ui::Widget(m_entry); + } + + void apply() + { + StringOutputStream angle(32); + angle << angle_normalised(entry_get_float(m_entry)); + Scene_EntitySetKeyValue_Selected_Undoable(m_key.c_str(), angle.c_str()); + } + + typedef MemberCaller ApplyCaller; + + void update() + { + const char *value = SelectedEntity_getValueForKey(m_key.c_str()); + if (!string_empty(value)) { + StringOutputStream angle(32); + angle << angle_normalised(atof(value)); + m_entry.text(angle.c_str()); + } else { + m_entry.text("0"); + } + } + + typedef MemberCaller UpdateCaller; }; -namespace -{ - typedef const char* String; - const String buttons[] = { "up", "down", "z-axis" }; +namespace { + typedef const char *String; + const String buttons[] = {"up", "down", "z-axis"}; } -class DirectionAttribute : public EntityAttribute -{ - CopiedString m_key; - GtkEntry* m_entry; - NonModalEntry m_nonModal; - RadioHBox m_radio; - NonModalRadio m_nonModalRadio; - GtkHBox* m_hbox; +class DirectionAttribute : public EntityAttribute { + CopiedString m_key; + ui::Entry m_entry; + NonModalEntry m_nonModal; + RadioHBox m_radio; + NonModalRadio m_nonModalRadio; + ui::HBox m_hbox{ui::null}; public: - DirectionAttribute(const char* key) : - m_key(key), - m_entry(0), - m_nonModal(ApplyCaller(*this), UpdateCaller(*this)), - m_radio(RadioHBox_new(STRING_ARRAY_RANGE(buttons))), - m_nonModalRadio(ApplyRadioCaller(*this)) - { - GtkEntry* entry = numeric_entry_new(); - m_entry = entry; - m_nonModal.connect(m_entry); - - m_nonModalRadio.connect(m_radio.m_radio); - - m_hbox = GTK_HBOX(gtk_hbox_new(FALSE, 4)); - gtk_widget_show(GTK_WIDGET(m_hbox)); - - gtk_box_pack_start(GTK_BOX(m_hbox), GTK_WIDGET(m_radio.m_hbox), TRUE, TRUE, 0); - gtk_box_pack_start(GTK_BOX(m_hbox), GTK_WIDGET(m_entry), TRUE, TRUE, 0); - } - void release() - { - delete this; - } - GtkWidget* getWidget() const - { - return GTK_WIDGET(m_hbox); - } - void apply() - { - StringOutputStream angle(32); - angle << angle_normalised(entry_get_float(m_entry)); - Scene_EntitySetKeyValue_Selected_Undoable(m_key.c_str(), angle.c_str()); - } - typedef MemberCaller ApplyCaller; - - void update() - { - const char* value = SelectedEntity_getValueForKey(m_key.c_str()); - if(!string_empty(value)) - { - float f = float(atof(value)); - if(f == -1) - { - gtk_widget_set_sensitive(GTK_WIDGET(m_entry), FALSE); - radio_button_set_active_no_signal(m_radio.m_radio, 0); - gtk_entry_set_text(m_entry, ""); - } - else if(f == -2) - { - gtk_widget_set_sensitive(GTK_WIDGET(m_entry), FALSE); - radio_button_set_active_no_signal(m_radio.m_radio, 1); - gtk_entry_set_text(m_entry, ""); - } - else - { - gtk_widget_set_sensitive(GTK_WIDGET(m_entry), TRUE); - radio_button_set_active_no_signal(m_radio.m_radio, 2); - StringOutputStream angle(32); - angle << angle_normalised(f); - gtk_entry_set_text(m_entry, angle.c_str()); - } + DirectionAttribute(const char *key) : + m_key(key), + m_entry(ui::null), + m_nonModal(ApplyCaller(*this), UpdateCaller(*this)), + m_radio(RadioHBox_new(STRING_ARRAY_RANGE(buttons))), + m_nonModalRadio(ApplyRadioCaller(*this)) + { + auto entry = numeric_entry_new(); + m_entry = entry; + m_nonModal.connect(m_entry); + + m_nonModalRadio.connect(m_radio.m_radio); + + m_hbox = ui::HBox(FALSE, 4); + m_hbox.show(); + + m_hbox.pack_start(m_radio.m_hbox, TRUE, TRUE, 0); + m_hbox.pack_start(m_entry, TRUE, TRUE, 0); + } + + void release() + { + delete this; } - else + + ui::Widget getWidget() const { - gtk_entry_set_text(m_entry, "0"); + return ui::Widget(m_hbox); } - } - typedef MemberCaller UpdateCaller; - void applyRadio() - { - int index = radio_button_get_active(m_radio.m_radio); - if(index == 0) + void apply() { - Scene_EntitySetKeyValue_Selected_Undoable(m_key.c_str(), "-1"); + StringOutputStream angle(32); + angle << angle_normalised(entry_get_float(m_entry)); + Scene_EntitySetKeyValue_Selected_Undoable(m_key.c_str(), angle.c_str()); } - else if(index == 1) + + typedef MemberCaller ApplyCaller; + + void update() { - Scene_EntitySetKeyValue_Selected_Undoable(m_key.c_str(), "-2"); + const char *value = SelectedEntity_getValueForKey(m_key.c_str()); + if (!string_empty(value)) { + float f = float(atof(value)); + if (f == -1) { + gtk_widget_set_sensitive(m_entry, FALSE); + radio_button_set_active_no_signal(m_radio.m_radio, 0); + m_entry.text(""); + } else if (f == -2) { + gtk_widget_set_sensitive(m_entry, FALSE); + radio_button_set_active_no_signal(m_radio.m_radio, 1); + m_entry.text(""); + } else { + gtk_widget_set_sensitive(m_entry, TRUE); + radio_button_set_active_no_signal(m_radio.m_radio, 2); + StringOutputStream angle(32); + angle << angle_normalised(f); + m_entry.text(angle.c_str()); + } + } else { + m_entry.text("0"); + } } - else if(index == 2) + + typedef MemberCaller UpdateCaller; + + void applyRadio() { - apply(); + int index = radio_button_get_active(m_radio.m_radio); + if (index == 0) { + Scene_EntitySetKeyValue_Selected_Undoable(m_key.c_str(), "-1"); + } else if (index == 1) { + Scene_EntitySetKeyValue_Selected_Undoable(m_key.c_str(), "-2"); + } else if (index == 2) { + apply(); + } } - } - typedef MemberCaller ApplyRadioCaller; + + typedef MemberCaller ApplyRadioCaller; }; -class AnglesEntry -{ +class AnglesEntry { public: - GtkEntry* m_roll; - GtkEntry* m_pitch; - GtkEntry* m_yaw; - AnglesEntry() : m_roll(0), m_pitch(0), m_yaw(0) - { - } + ui::Entry m_roll; + ui::Entry m_pitch; + ui::Entry m_yaw; + + AnglesEntry() : m_roll(ui::null), m_pitch(ui::null), m_yaw(ui::null) + { + } }; typedef BasicVector3 DoubleVector3; -class AnglesAttribute : public EntityAttribute -{ - CopiedString m_key; - AnglesEntry m_angles; - NonModalEntry m_nonModal; - GtkBox* m_hbox; +class AnglesAttribute : public EntityAttribute { + CopiedString m_key; + AnglesEntry m_angles; + NonModalEntry m_nonModal; + ui::HBox m_hbox; public: - AnglesAttribute(const char* key) : - m_key(key), - m_nonModal(ApplyCaller(*this), UpdateCaller(*this)) - { - m_hbox = GTK_BOX(gtk_hbox_new(TRUE, 4)); - gtk_widget_show(GTK_WIDGET(m_hbox)); - { - GtkEntry* entry = numeric_entry_new(); - gtk_box_pack_start(m_hbox, GTK_WIDGET(entry), TRUE, TRUE, 0); - m_angles.m_pitch = entry; - m_nonModal.connect(m_angles.m_pitch); - } - { - GtkEntry* entry = numeric_entry_new(); - gtk_box_pack_start(m_hbox, GTK_WIDGET(entry), TRUE, TRUE, 0); - m_angles.m_yaw = entry; - m_nonModal.connect(m_angles.m_yaw); - } - { - GtkEntry* entry = numeric_entry_new(); - gtk_box_pack_start(m_hbox, GTK_WIDGET(entry), TRUE, TRUE, 0); - m_angles.m_roll = entry; - m_nonModal.connect(m_angles.m_roll); - } - } - void release() - { - delete this; - } - GtkWidget* getWidget() const - { - return GTK_WIDGET(m_hbox); - } - void apply() - { - StringOutputStream angles(64); - angles << angle_normalised(entry_get_float(m_angles.m_pitch)) - << " " << angle_normalised(entry_get_float(m_angles.m_yaw)) - << " " << angle_normalised(entry_get_float(m_angles.m_roll)); - Scene_EntitySetKeyValue_Selected_Undoable(m_key.c_str(), angles.c_str()); - } - typedef MemberCaller ApplyCaller; - - void update() - { - StringOutputStream angle(32); - const char* value = SelectedEntity_getValueForKey(m_key.c_str()); - if(!string_empty(value)) - { - DoubleVector3 pitch_yaw_roll; - if(!string_parse_vector3(value, pitch_yaw_roll)) - { - pitch_yaw_roll = DoubleVector3(0, 0, 0); - } - - angle << angle_normalised(pitch_yaw_roll.x()); - gtk_entry_set_text(m_angles.m_pitch, angle.c_str()); - angle.clear(); - - angle << angle_normalised(pitch_yaw_roll.y()); - gtk_entry_set_text(m_angles.m_yaw, angle.c_str()); - angle.clear(); - - angle << angle_normalised(pitch_yaw_roll.z()); - gtk_entry_set_text(m_angles.m_roll, angle.c_str()); - angle.clear(); - } - else - { - gtk_entry_set_text(m_angles.m_pitch, "0"); - gtk_entry_set_text(m_angles.m_yaw, "0"); - gtk_entry_set_text(m_angles.m_roll, "0"); - } - } - typedef MemberCaller UpdateCaller; + AnglesAttribute(const char *key) : + m_key(key), + m_nonModal(ApplyCaller(*this), UpdateCaller(*this)), + m_hbox(ui::HBox(TRUE, 4)) + { + m_hbox.show(); + { + auto entry = numeric_entry_new(); + m_hbox.pack_start(entry, TRUE, TRUE, 0); + m_angles.m_pitch = entry; + m_nonModal.connect(m_angles.m_pitch); + } + { + auto entry = numeric_entry_new(); + m_hbox.pack_start(entry, TRUE, TRUE, 0); + m_angles.m_yaw = entry; + m_nonModal.connect(m_angles.m_yaw); + } + { + auto entry = numeric_entry_new(); + m_hbox.pack_start(entry, TRUE, TRUE, 0); + m_angles.m_roll = entry; + m_nonModal.connect(m_angles.m_roll); + } + } + + void release() + { + delete this; + } + + ui::Widget getWidget() const + { + return ui::Widget(m_hbox); + } + + void apply() + { + StringOutputStream angles(64); + angles << angle_normalised(entry_get_float(m_angles.m_pitch)) + << " " << angle_normalised(entry_get_float(m_angles.m_yaw)) + << " " << angle_normalised(entry_get_float(m_angles.m_roll)); + Scene_EntitySetKeyValue_Selected_Undoable(m_key.c_str(), angles.c_str()); + } + + typedef MemberCaller ApplyCaller; + + void update() + { + StringOutputStream angle(32); + const char *value = SelectedEntity_getValueForKey(m_key.c_str()); + if (!string_empty(value)) { + DoubleVector3 pitch_yaw_roll; + if (!string_parse_vector3(value, pitch_yaw_roll)) { + pitch_yaw_roll = DoubleVector3(0, 0, 0); + } + + angle << angle_normalised(pitch_yaw_roll.x()); + m_angles.m_pitch.text(angle.c_str()); + angle.clear(); + + angle << angle_normalised(pitch_yaw_roll.y()); + m_angles.m_yaw.text(angle.c_str()); + angle.clear(); + + angle << angle_normalised(pitch_yaw_roll.z()); + m_angles.m_roll.text(angle.c_str()); + angle.clear(); + } else { + m_angles.m_pitch.text("0"); + m_angles.m_yaw.text("0"); + m_angles.m_roll.text("0"); + } + } + + typedef MemberCaller UpdateCaller; }; -class Vector3Entry -{ +class Vector3Entry { public: - GtkEntry* m_x; - GtkEntry* m_y; - GtkEntry* m_z; - Vector3Entry() : m_x(0), m_y(0), m_z(0) - { - } + ui::Entry m_x; + ui::Entry m_y; + ui::Entry m_z; + + Vector3Entry() : m_x(ui::null), m_y(ui::null), m_z(ui::null) + { + } }; -class Vector3Attribute : public EntityAttribute -{ - CopiedString m_key; - Vector3Entry m_vector3; - NonModalEntry m_nonModal; - GtkBox* m_hbox; +class Vector3Attribute : public EntityAttribute { + CopiedString m_key; + Vector3Entry m_vector3; + NonModalEntry m_nonModal; + ui::Box m_hbox{ui::null}; public: - Vector3Attribute(const char* key) : - m_key(key), - m_nonModal(ApplyCaller(*this), UpdateCaller(*this)) - { - m_hbox = GTK_BOX(gtk_hbox_new(TRUE, 4)); - gtk_widget_show(GTK_WIDGET(m_hbox)); - { - GtkEntry* entry = numeric_entry_new(); - gtk_box_pack_start(m_hbox, GTK_WIDGET(entry), TRUE, TRUE, 0); - m_vector3.m_x = entry; - m_nonModal.connect(m_vector3.m_x); - } - { - GtkEntry* entry = numeric_entry_new(); - gtk_box_pack_start(m_hbox, GTK_WIDGET(entry), TRUE, TRUE, 0); - m_vector3.m_y = entry; - m_nonModal.connect(m_vector3.m_y); - } - { - GtkEntry* entry = numeric_entry_new(); - gtk_box_pack_start(m_hbox, GTK_WIDGET(entry), TRUE, TRUE, 0); - m_vector3.m_z = entry; - m_nonModal.connect(m_vector3.m_z); - } - } - void release() - { - delete this; - } - GtkWidget* getWidget() const - { - return GTK_WIDGET(m_hbox); - } - void apply() - { - StringOutputStream vector3(64); - vector3 << entry_get_float(m_vector3.m_x) - << " " << entry_get_float(m_vector3.m_y) - << " " << entry_get_float(m_vector3.m_z); - Scene_EntitySetKeyValue_Selected_Undoable(m_key.c_str(), vector3.c_str()); - } - typedef MemberCaller ApplyCaller; - - void update() - { - StringOutputStream buffer(32); - const char* value = SelectedEntity_getValueForKey(m_key.c_str()); - if(!string_empty(value)) - { - DoubleVector3 x_y_z; - if(!string_parse_vector3(value, x_y_z)) - { - x_y_z = DoubleVector3(0, 0, 0); - } - - buffer << x_y_z.x(); - gtk_entry_set_text(m_vector3.m_x, buffer.c_str()); - buffer.clear(); - - buffer << x_y_z.y(); - gtk_entry_set_text(m_vector3.m_y, buffer.c_str()); - buffer.clear(); - - buffer << x_y_z.z(); - gtk_entry_set_text(m_vector3.m_z, buffer.c_str()); - buffer.clear(); - } - else - { - gtk_entry_set_text(m_vector3.m_x, "0"); - gtk_entry_set_text(m_vector3.m_y, "0"); - gtk_entry_set_text(m_vector3.m_z, "0"); - } - } - typedef MemberCaller UpdateCaller; + Vector3Attribute(const char *key) : + m_key(key), + m_nonModal(ApplyCaller(*this), UpdateCaller(*this)) + { + m_hbox = ui::HBox(TRUE, 4); + m_hbox.show(); + { + auto entry = numeric_entry_new(); + m_hbox.pack_start(entry, TRUE, TRUE, 0); + m_vector3.m_x = entry; + m_nonModal.connect(m_vector3.m_x); + } + { + auto entry = numeric_entry_new(); + m_hbox.pack_start(entry, TRUE, TRUE, 0); + m_vector3.m_y = entry; + m_nonModal.connect(m_vector3.m_y); + } + { + auto entry = numeric_entry_new(); + m_hbox.pack_start(entry, TRUE, TRUE, 0); + m_vector3.m_z = entry; + m_nonModal.connect(m_vector3.m_z); + } + } + + void release() + { + delete this; + } + + ui::Widget getWidget() const + { + return ui::Widget(m_hbox); + } + + void apply() + { + StringOutputStream vector3(64); + vector3 << entry_get_float(m_vector3.m_x) + << " " << entry_get_float(m_vector3.m_y) + << " " << entry_get_float(m_vector3.m_z); + Scene_EntitySetKeyValue_Selected_Undoable(m_key.c_str(), vector3.c_str()); + } + + typedef MemberCaller ApplyCaller; + + void update() + { + StringOutputStream buffer(32); + const char *value = SelectedEntity_getValueForKey(m_key.c_str()); + if (!string_empty(value)) { + DoubleVector3 x_y_z; + if (!string_parse_vector3(value, x_y_z)) { + x_y_z = DoubleVector3(0, 0, 0); + } + + buffer << x_y_z.x(); + m_vector3.m_x.text(buffer.c_str()); + buffer.clear(); + + buffer << x_y_z.y(); + m_vector3.m_y.text(buffer.c_str()); + buffer.clear(); + + buffer << x_y_z.z(); + m_vector3.m_z.text(buffer.c_str()); + buffer.clear(); + } else { + m_vector3.m_x.text("0"); + m_vector3.m_y.text("0"); + m_vector3.m_z.text("0"); + } + } + + typedef MemberCaller UpdateCaller; }; -class NonModalComboBox -{ - Callback m_changed; - guint m_changedHandler; +class NonModalComboBox { + Callback m_changed; + guint m_changedHandler; - static gboolean changed(GtkComboBox *widget, NonModalComboBox* self) - { - self->m_changed(); - return FALSE; - } + static gboolean changed(ui::ComboBox widget, NonModalComboBox *self) + { + self->m_changed(); + return FALSE; + } public: - NonModalComboBox(const Callback& changed) : m_changed(changed), m_changedHandler(0) - { - } - void connect(GtkComboBox* combo) - { - m_changedHandler = g_signal_connect(G_OBJECT(combo), "changed", G_CALLBACK(changed), this); - } - void setActive(GtkComboBox* combo, int value) - { - g_signal_handler_disconnect(G_OBJECT(combo), m_changedHandler); - gtk_combo_box_set_active(combo, value); - connect(combo); - } + NonModalComboBox(const Callback &changed) : m_changed(changed), m_changedHandler(0) + { + } + + void connect(ui::ComboBox combo) + { + m_changedHandler = combo.connect("changed", G_CALLBACK(changed), this); + } + + void setActive(ui::ComboBox combo, int value) + { + g_signal_handler_disconnect(G_OBJECT(combo), m_changedHandler); + gtk_combo_box_set_active(combo, value); + connect(combo); + } }; -class ListAttribute : public EntityAttribute -{ - CopiedString m_key; - GtkComboBox* m_combo; - NonModalComboBox m_nonModal; - const ListAttributeType& m_type; +class ListAttribute : public EntityAttribute { + CopiedString m_key; + ui::ComboBox m_combo; + NonModalComboBox m_nonModal; + const ListAttributeType &m_type; public: - ListAttribute(const char* key, const ListAttributeType& type) : - m_key(key), - m_combo(0), - m_nonModal(ApplyCaller(*this)), - m_type(type) - { - GtkComboBox* combo = GTK_COMBO_BOX(gtk_combo_box_new_text()); - - for(ListAttributeType::const_iterator i = type.begin(); i != type.end(); ++i) - { - gtk_combo_box_append_text(GTK_COMBO_BOX(combo), (*i).first.c_str()); - } - - gtk_widget_show(GTK_WIDGET(combo)); - m_nonModal.connect(combo); - - m_combo = combo; - } - void release() - { - delete this; - } - GtkWidget* getWidget() const - { - return GTK_WIDGET(m_combo); - } - void apply() - { - Scene_EntitySetKeyValue_Selected_Undoable(m_key.c_str(), m_type[gtk_combo_box_get_active(m_combo)].second.c_str()); - } - typedef MemberCaller ApplyCaller; - - void update() - { - const char* value = SelectedEntity_getValueForKey(m_key.c_str()); - ListAttributeType::const_iterator i = m_type.findValue(value); - if(i != m_type.end()) - { - m_nonModal.setActive(m_combo, static_cast(std::distance(m_type.begin(), i))); - } - else - { - m_nonModal.setActive(m_combo, 0); - } - } - typedef MemberCaller UpdateCaller; + ListAttribute(const char *key, const ListAttributeType &type) : + m_key(key), + m_combo(ui::null), + m_nonModal(ApplyCaller(*this)), + m_type(type) + { + auto combo = ui::ComboBoxText(ui::New); + + for (ListAttributeType::const_iterator i = type.begin(); i != type.end(); ++i) { + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), (*i).first.c_str()); + } + + combo.show(); + m_nonModal.connect(combo); + + m_combo = combo; + } + + void release() + { + delete this; + } + + ui::Widget getWidget() const + { + return ui::Widget(m_combo); + } + + void apply() + { + Scene_EntitySetKeyValue_Selected_Undoable(m_key.c_str(), + m_type[gtk_combo_box_get_active(m_combo)].second.c_str()); + } + + typedef MemberCaller ApplyCaller; + + void update() + { + const char *value = SelectedEntity_getValueForKey(m_key.c_str()); + ListAttributeType::const_iterator i = m_type.findValue(value); + if (i != m_type.end()) { + m_nonModal.setActive(m_combo, static_cast( std::distance(m_type.begin(), i))); + } else { + m_nonModal.setActive(m_combo, 0); + } + } + + typedef MemberCaller UpdateCaller; }; -namespace -{ - GtkWidget* g_entity_split1 = 0; - GtkWidget* g_entity_split2 = 0; - int g_entitysplit1_position; - int g_entitysplit2_position; - - bool g_entityInspector_windowConstructed = false; - - GtkTreeView* g_entityClassList; - GtkTextView* g_entityClassComment; - - GtkCheckButton* g_entitySpawnflagsCheck[MAX_FLAGS]; - - GtkEntry* g_entityKeyEntry; - GtkEntry* g_entityValueEntry; - - GtkListStore* g_entlist_store; - GtkListStore* g_entprops_store; - const EntityClass* g_current_flags = 0; - const EntityClass* g_current_comment = 0; - const EntityClass* g_current_attributes = 0; - - // the number of active spawnflags - int g_spawnflag_count; - // table: index, match spawnflag item to the spawnflag index (i.e. which bit) - int spawn_table[MAX_FLAGS]; - // we change the layout depending on how many spawn flags we need to display - // the table is a 4x4 in which we need to put the comment box g_entityClassComment and the spawn flags.. - GtkTable* g_spawnflagsTable; - - GtkVBox* g_attributeBox = 0; - typedef std::vector EntityAttributes; - EntityAttributes g_entityAttributes; +namespace { + ui::Widget g_entity_split1{ui::null}; + ui::Widget g_entity_split2{ui::null}; + int g_entitysplit1_position; + int g_entitysplit2_position; + + bool g_entityInspector_windowConstructed = false; + + ui::TreeView g_entityClassList{ui::null}; + ui::TextView g_entityClassComment{ui::null}; + + GtkCheckButton *g_entitySpawnflagsCheck[MAX_FLAGS]; + + ui::Entry g_entityKeyEntry{ui::null}; + ui::Entry g_entityValueEntry{ui::null}; + + ui::ListStore g_entlist_store{ui::null}; + ui::ListStore g_entprops_store{ui::null}; + const EntityClass *g_current_flags = 0; + const EntityClass *g_current_comment = 0; + const EntityClass *g_current_attributes = 0; + +// the number of active spawnflags + int g_spawnflag_count; +// table: index, match spawnflag item to the spawnflag index (i.e. which bit) + int spawn_table[MAX_FLAGS]; +// we change the layout depending on how many spawn flags we need to display +// the table is a 4x4 in which we need to put the comment box g_entityClassComment and the spawn flags.. + ui::Table g_spawnflagsTable{ui::null}; + + ui::VBox g_attributeBox{ui::null}; + typedef std::vector EntityAttributes; + EntityAttributes g_entityAttributes; } void GlobalEntityAttributes_clear() { - for(EntityAttributes::iterator i = g_entityAttributes.begin(); i != g_entityAttributes.end(); ++i) - { - (*i)->release(); - } - g_entityAttributes.clear(); + for (EntityAttributes::iterator i = g_entityAttributes.begin(); i != g_entityAttributes.end(); ++i) { + (*i)->release(); + } + g_entityAttributes.clear(); } -class GetKeyValueVisitor : public Entity::Visitor -{ - KeyValues& m_keyvalues; +class GetKeyValueVisitor : public Entity::Visitor { + KeyValues &m_keyvalues; public: - GetKeyValueVisitor(KeyValues& keyvalues) - : m_keyvalues(keyvalues) - { - } + GetKeyValueVisitor(KeyValues &keyvalues) + : m_keyvalues(keyvalues) + { + } - void visit(const char* key, const char* value) - { - m_keyvalues.insert(KeyValues::value_type(CopiedString(key), CopiedString(value))); - } + void visit(const char *key, const char *value) + { + m_keyvalues.insert(KeyValues::value_type(CopiedString(key), CopiedString(value))); + } }; -void Entity_GetKeyValues(const Entity& entity, KeyValues& keyvalues, KeyValues& defaultValues) +void Entity_GetKeyValues(const Entity &entity, KeyValues &keyvalues, KeyValues &defaultValues) { - GetKeyValueVisitor visitor(keyvalues); + GetKeyValueVisitor visitor(keyvalues); - entity.forEachKeyValue(visitor); + entity.forEachKeyValue(visitor); - const EntityClassAttributes& attributes = entity.getEntityClass().m_attributes; + const EntityClassAttributes &attributes = entity.getEntityClass().m_attributes; - for(EntityClassAttributes::const_iterator i = attributes.begin(); i != attributes.end(); ++i) - { - defaultValues.insert(KeyValues::value_type((*i).first, (*i).second.m_value)); - } + for (EntityClassAttributes::const_iterator i = attributes.begin(); i != attributes.end(); ++i) { + defaultValues.insert(KeyValues::value_type((*i).first, (*i).second.m_value)); + } } -void Entity_GetKeyValues_Selected(KeyValues& keyvalues, KeyValues& defaultValues) +void Entity_GetKeyValues_Selected(KeyValues &keyvalues, KeyValues &defaultValues) { - class EntityGetKeyValues : public SelectionSystem::Visitor - { - KeyValues& m_keyvalues; - KeyValues& m_defaultValues; - mutable std::set m_visited; - public: - EntityGetKeyValues(KeyValues& keyvalues, KeyValues& defaultValues) - : m_keyvalues(keyvalues), m_defaultValues(defaultValues) - { - } - void visit(scene::Instance& instance) const - { - Entity* entity = Node_getEntity(instance.path().top()); - if(entity == 0 && instance.path().size() != 1) - { - entity = Node_getEntity(instance.path().parent()); - } - if(entity != 0 && m_visited.insert(entity).second) - { - Entity_GetKeyValues(*entity, m_keyvalues, m_defaultValues); - } - } - } visitor(keyvalues, defaultValues); - GlobalSelectionSystem().foreachSelected(visitor); + class EntityGetKeyValues : public SelectionSystem::Visitor { + KeyValues &m_keyvalues; + KeyValues &m_defaultValues; + mutable std::set m_visited; + public: + EntityGetKeyValues(KeyValues &keyvalues, KeyValues &defaultValues) + : m_keyvalues(keyvalues), m_defaultValues(defaultValues) + { + } + + void visit(scene::Instance &instance) const + { + Entity *entity = Node_getEntity(instance.path().top()); + if (entity == 0 && instance.path().size() != 1) { + entity = Node_getEntity(instance.path().parent()); + } + if (entity != 0 && m_visited.insert(entity).second) { + Entity_GetKeyValues(*entity, m_keyvalues, m_defaultValues); + } + } + } visitor(keyvalues, defaultValues); + GlobalSelectionSystem().foreachSelected(visitor); } -const char* keyvalues_valueforkey(KeyValues& keyvalues, const char* key) +const char *keyvalues_valueforkey(KeyValues &keyvalues, const char *key) { - KeyValues::iterator i = keyvalues.find(CopiedString(key)); - if(i != keyvalues.end()) - return (*i).second.c_str(); - return ""; + KeyValues::iterator i = keyvalues.find(CopiedString(key)); + if (i != keyvalues.end()) { + return (*i).second.c_str(); + } + return ""; } -class EntityClassListStoreAppend : public EntityClassVisitor -{ - GtkListStore* store; +class EntityClassListStoreAppend : public EntityClassVisitor { + ui::ListStore store; public: - EntityClassListStoreAppend(GtkListStore* store_) : store(store_) - { - } - void visit(EntityClass* e) - { - GtkTreeIter iter; - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, 0, e->name(), 1, e, -1); - } + EntityClassListStoreAppend(ui::ListStore store_) : store(store_) + { + } + + void visit(EntityClass *e) + { + store.append(0, e->name(), 1, e); + } }; void EntityClassList_fill() { - EntityClassListStoreAppend append(g_entlist_store); - GlobalEntityClassManager().forEach(append); + EntityClassListStoreAppend append(g_entlist_store); + GlobalEntityClassManager().forEach(append); } void EntityClassList_clear() { - gtk_list_store_clear(g_entlist_store); + g_entlist_store.clear(); } -void SetComment(EntityClass* eclass) +void SetComment(EntityClass *eclass) { - if(eclass == g_current_comment) - return; + if (eclass == g_current_comment) { + return; + } - g_current_comment = eclass; + g_current_comment = eclass; - GtkTextBuffer* buffer = gtk_text_view_get_buffer(g_entityClassComment); - gtk_text_buffer_set_text(buffer, eclass->comments(), -1); + g_entityClassComment.text(eclass->comments()); } -void SurfaceFlags_setEntityClass(EntityClass* eclass) +void SurfaceFlags_setEntityClass(EntityClass *eclass) { - if(eclass == g_current_flags) - return; + if (eclass == g_current_flags) { + return; + } - g_current_flags = eclass; + g_current_flags = eclass; - int spawnflag_count = 0; + unsigned int spawnflag_count = 0; - { - // do a first pass to count the spawn flags, don't touch the widgets, we don't know in what state they are - for (int i=0 ; iflagnames[i] && eclass->flagnames[i][0] != 0 && strcmp(eclass->flagnames[i],"-")) - { - spawn_table[spawnflag_count] = i; - spawnflag_count++; - } + // do a first pass to count the spawn flags, don't touch the widgets, we don't know in what state they are + for (int i = 0; i < MAX_FLAGS; i++) { + if (eclass->flagnames[i] && eclass->flagnames[i][0] != 0 && strcmp(eclass->flagnames[i], "-")) { + spawn_table[spawnflag_count] = i; + spawnflag_count++; + } + } } - } - // disable all remaining boxes - // NOTE: these boxes might not even be on display - { - for (int i = 0; i < g_spawnflag_count; ++i) + // disable all remaining boxes + // NOTE: these boxes might not even be on display { - GtkWidget* widget = GTK_WIDGET(g_entitySpawnflagsCheck[i]); - gtk_label_set_text(GTK_LABEL(GTK_BIN(widget)->child), " "); - gtk_widget_hide(widget); - gtk_widget_ref(widget); - gtk_container_remove(GTK_CONTAINER(g_spawnflagsTable), widget); + for (int i = 0; i < g_spawnflag_count; ++i) { + auto widget = ui::CheckButton::from(g_entitySpawnflagsCheck[i]); + auto label = ui::Label::from(gtk_bin_get_child(GTK_BIN(widget))); + label.text(" "); + widget.hide(); + widget.ref(); + g_spawnflagsTable.remove(widget); + } } - } - g_spawnflag_count = spawnflag_count; + g_spawnflag_count = spawnflag_count; - { - for (int i = 0; i < g_spawnflag_count; ++i) { - GtkWidget* widget = GTK_WIDGET(g_entitySpawnflagsCheck[i]); - gtk_widget_show (widget); - - StringOutputStream str(16); - str << LowerCase(eclass->flagnames[spawn_table[i]]); - - gtk_table_attach(g_spawnflagsTable, widget, i%4, i%4+1, i/4, i/4+1, - (GtkAttachOptions)(GTK_FILL), - (GtkAttachOptions)(GTK_FILL), 0, 0); - gtk_widget_unref(widget); - - gtk_label_set_text(GTK_LABEL(GTK_BIN(widget)->child), str.c_str()); + for (unsigned int i = 0; (int) i < g_spawnflag_count; ++i) { + auto widget = ui::CheckButton::from(g_entitySpawnflagsCheck[i]); + widget.show(); + + StringOutputStream str(16); + str << LowerCase(eclass->flagnames[spawn_table[i]]); + + g_spawnflagsTable.attach(widget, {i % 4, i % 4 + 1, i / 4, i / 4 + 1}, {GTK_FILL, GTK_FILL}); + widget.unref(); + + auto label = ui::Label::from(gtk_bin_get_child(GTK_BIN(widget))); + label.text(str.c_str()); + } } - } } -void EntityClassList_selectEntityClass(EntityClass* eclass) +void EntityClassList_selectEntityClass(EntityClass *eclass) { - GtkTreeModel* model = GTK_TREE_MODEL(g_entlist_store); - GtkTreeIter iter; - for(gboolean good = gtk_tree_model_get_iter_first(model, &iter); good != FALSE; good = gtk_tree_model_iter_next(model, &iter)) - { - char* text; - gtk_tree_model_get(model, &iter, 0, &text, -1); - if (strcmp (text, eclass->name()) == 0) - { - GtkTreeView* view = g_entityClassList; - GtkTreePath* path = gtk_tree_model_get_path(model, &iter); - gtk_tree_selection_select_path(gtk_tree_view_get_selection(view), path); - if(GTK_WIDGET_REALIZED(view)) - { - gtk_tree_view_scroll_to_cell(view, path, 0, FALSE, 0, 0); - } - gtk_tree_path_free(path); - good = FALSE; + auto model = g_entlist_store; + GtkTreeIter iter; + for (gboolean good = gtk_tree_model_get_iter_first(model, &iter); + good != FALSE; good = gtk_tree_model_iter_next(model, &iter)) { + char *text; + gtk_tree_model_get(model, &iter, 0, &text, -1); + if (strcmp(text, eclass->name()) == 0) { + auto view = ui::TreeView(g_entityClassList); + auto path = gtk_tree_model_get_path(model, &iter); + gtk_tree_selection_select_path(gtk_tree_view_get_selection(view), path); + if (gtk_widget_get_realized(view)) { + gtk_tree_view_scroll_to_cell(view, path, 0, FALSE, 0, 0); + } + gtk_tree_path_free(path); + good = FALSE; + } + g_free(text); } - g_free(text); - } } -void EntityInspector_appendAttribute(const char* name, EntityAttribute& attribute) +void EntityInspector_appendAttribute(const char *name, EntityAttribute &attribute) { - GtkTable* row = DialogRow_new(name, attribute.getWidget()); - DialogVBox_packRow(g_attributeBox, GTK_WIDGET(row)); + auto row = DialogRow_new(name, attribute.getWidget()); + DialogVBox_packRow(ui::VBox(g_attributeBox), row); } template -class StatelessAttributeCreator -{ +class StatelessAttributeCreator { public: - static EntityAttribute* create(const char* name) - { - return new Attribute(name); - } + static EntityAttribute *create(const char *name) + { + return new Attribute(name); + } }; -class EntityAttributeFactory -{ - typedef EntityAttribute* (*CreateFunc)(const char* name); - typedef std::map Creators; - Creators m_creators; +class EntityAttributeFactory { + typedef EntityAttribute *( *CreateFunc )(const char *name); + + typedef std::map Creators; + Creators m_creators; public: - EntityAttributeFactory() - { - m_creators.insert(Creators::value_type("string", &StatelessAttributeCreator::create)); - m_creators.insert(Creators::value_type("color", &StatelessAttributeCreator::create)); - m_creators.insert(Creators::value_type("integer", &StatelessAttributeCreator::create)); - m_creators.insert(Creators::value_type("real", &StatelessAttributeCreator::create)); - m_creators.insert(Creators::value_type("shader", &StatelessAttributeCreator::create)); - m_creators.insert(Creators::value_type("boolean", &StatelessAttributeCreator::create)); - m_creators.insert(Creators::value_type("angle", &StatelessAttributeCreator::create)); - m_creators.insert(Creators::value_type("direction", &StatelessAttributeCreator::create)); - m_creators.insert(Creators::value_type("angles", &StatelessAttributeCreator::create)); - m_creators.insert(Creators::value_type("model", &StatelessAttributeCreator::create)); - m_creators.insert(Creators::value_type("sound", &StatelessAttributeCreator::create)); - m_creators.insert(Creators::value_type("vector3", &StatelessAttributeCreator::create)); - } - EntityAttribute* create(const char* type, const char* name) - { - Creators::iterator i = m_creators.find(type); - if(i != m_creators.end()) - { - return (*i).second(name); - } - const ListAttributeType* listType = GlobalEntityClassManager().findListType(type); - if(listType != 0) - { - return new ListAttribute(name, *listType); - } - return 0; - } + EntityAttributeFactory() + { + m_creators.insert(Creators::value_type("string", &StatelessAttributeCreator::create)); + m_creators.insert(Creators::value_type("color", &StatelessAttributeCreator::create)); + m_creators.insert(Creators::value_type("integer", &StatelessAttributeCreator::create)); + m_creators.insert(Creators::value_type("real", &StatelessAttributeCreator::create)); + m_creators.insert(Creators::value_type("shader", &StatelessAttributeCreator::create)); + m_creators.insert(Creators::value_type("boolean", &StatelessAttributeCreator::create)); + m_creators.insert(Creators::value_type("angle", &StatelessAttributeCreator::create)); + m_creators.insert(Creators::value_type("direction", &StatelessAttributeCreator::create)); + m_creators.insert(Creators::value_type("angles", &StatelessAttributeCreator::create)); + m_creators.insert(Creators::value_type("model", &StatelessAttributeCreator::create)); + m_creators.insert(Creators::value_type("sound", &StatelessAttributeCreator::create)); + m_creators.insert(Creators::value_type("vector3", &StatelessAttributeCreator::create)); + m_creators.insert(Creators::value_type("real3", &StatelessAttributeCreator::create)); + } + + EntityAttribute *create(const char *type, const char *name) + { + Creators::iterator i = m_creators.find(type); + if (i != m_creators.end()) { + return (*i).second(name); + } + const ListAttributeType *listType = GlobalEntityClassManager().findListType(type); + if (listType != 0) { + return new ListAttribute(name, *listType); + } + return 0; + } }; typedef Static GlobalEntityAttributeFactory; void EntityInspector_setEntityClass(EntityClass *eclass) { - EntityClassList_selectEntityClass(eclass); - SurfaceFlags_setEntityClass(eclass); - - if(eclass != g_current_attributes) - { - g_current_attributes = eclass; - - container_remove_all(GTK_CONTAINER(g_attributeBox)); - GlobalEntityAttributes_clear(); - - for(EntityClassAttributes::const_iterator i = eclass->m_attributes.begin(); i != eclass->m_attributes.end(); ++i) - { - EntityAttribute* attribute = GlobalEntityAttributeFactory::instance().create((*i).second.m_type.c_str(), (*i).first.c_str()); - if(attribute != 0) - { - g_entityAttributes.push_back(attribute); - EntityInspector_appendAttribute(EntityClassAttributePair_getName(*i), *g_entityAttributes.back()); - } + EntityClassList_selectEntityClass(eclass); + SurfaceFlags_setEntityClass(eclass); + + if (eclass != g_current_attributes) { + g_current_attributes = eclass; + + container_remove_all(g_attributeBox); + GlobalEntityAttributes_clear(); + + for (EntityClassAttributes::const_iterator i = eclass->m_attributes.begin(); + i != eclass->m_attributes.end(); ++i) { + EntityAttribute *attribute = GlobalEntityAttributeFactory::instance().create((*i).second.m_type.c_str(), + (*i).first.c_str()); + if (attribute != 0) { + g_entityAttributes.push_back(attribute); + EntityInspector_appendAttribute(EntityClassAttributePair_getName(*i), *g_entityAttributes.back()); + } + } } - } } void EntityInspector_updateSpawnflags() { - { - int f = atoi(SelectedEntity_getValueForKey("spawnflags")); - for (int i = 0; i < g_spawnflag_count; ++i) { - int v = !!(f&(1<update(); - } + for (EntityAttributes::const_iterator i = g_entityAttributes.begin(); i != g_entityAttributes.end(); ++i) { + (*i)->update(); + } } -class EntityInspectorDraw -{ - IdleDraw m_idleDraw; +class EntityInspectorDraw { + IdleDraw m_idleDraw; public: - EntityInspectorDraw() : m_idleDraw(FreeCaller()) - { - } - void queueDraw() - { - m_idleDraw.queueDraw(); - } + EntityInspectorDraw() : m_idleDraw(makeCallbackF(EntityInspector_updateKeyValues)) + { + } + + void queueDraw() + { + m_idleDraw.queueDraw(); + } }; EntityInspectorDraw g_EntityInspectorDraw; @@ -1203,539 +1180,509 @@ EntityInspectorDraw g_EntityInspectorDraw; void EntityInspector_keyValueChanged() { - g_EntityInspectorDraw.queueDraw(); + g_EntityInspectorDraw.queueDraw(); } -void EntityInspector_selectionChanged(const Selectable&) + +void EntityInspector_selectionChanged(const Selectable &) { - EntityInspector_keyValueChanged(); + EntityInspector_keyValueChanged(); } // Creates a new entity based on the currently selected brush and entity type. // void EntityClassList_createEntity() { - GtkTreeView* view = g_entityClassList; + auto view = g_entityClassList; - // find out what type of entity we are trying to create - GtkTreeModel* model; - GtkTreeIter iter; - if(gtk_tree_selection_get_selected(gtk_tree_view_get_selection(view), &model, &iter) == FALSE) - { - gtk_MessageBox(gtk_widget_get_toplevel(GTK_WIDGET(g_entityClassList)), "You must have a selected class to create an entity", "info"); - return; - } + // find out what type of entity we are trying to create + GtkTreeModel *model; + GtkTreeIter iter; + if (gtk_tree_selection_get_selected(gtk_tree_view_get_selection(g_entityClassList), &model, &iter) == FALSE) { + ui::alert(view.window(), "You must have a selected class to create an entity", "info"); + return; + } - char* text; - gtk_tree_model_get(model, &iter, 0, &text, -1); + char *text; + gtk_tree_model_get(model, &iter, 0, &text, -1); - { - StringOutputStream command; - command << "entityCreate -class " << text; + { + StringOutputStream command; + command << "entityCreate -class " << text; - UndoableCommand undo(command.c_str()); + UndoableCommand undo(command.c_str()); - Entity_createFromSelection(text, g_vector3_identity); - } - g_free(text); + Entity_createFromSelection(text, g_vector3_identity); + } + g_free(text); } void EntityInspector_applyKeyValue() { - // Get current selection text - StringOutputStream key(64); - key << ConvertUTF8ToLocale(gtk_entry_get_text(g_entityKeyEntry)); - StringOutputStream value(64); - value << ConvertUTF8ToLocale(gtk_entry_get_text(g_entityValueEntry)); - - - // TTimo: if you change the classname to worldspawn you won't merge back in the structural brushes but create a parasite entity - if (!strcmp(key.c_str(), "classname") && !strcmp(value.c_str(), "worldspawn")) - { - gtk_MessageBox(gtk_widget_get_toplevel(GTK_WIDGET(g_entityKeyEntry)), "Cannot change \"classname\" key back to worldspawn.", 0, eMB_OK ); - return; - } - - - // RR2DO2: we don't want spaces in entity keys - if (strstr( key.c_str(), " " )) - { - gtk_MessageBox(gtk_widget_get_toplevel(GTK_WIDGET(g_entityKeyEntry)), "No spaces are allowed in entity keys.", 0, eMB_OK ); - return; - } - - if(strcmp(key.c_str(), "classname") == 0) - { - StringOutputStream command; - command << "entitySetClass -class " << value.c_str(); - UndoableCommand undo(command.c_str()); - Scene_EntitySetClassname_Selected(value.c_str()); - } - else - { - Scene_EntitySetKeyValue_Selected_Undoable(key.c_str(), value.c_str()); - } + // Get current selection text + StringOutputStream key(64); + key << gtk_entry_get_text(g_entityKeyEntry); + StringOutputStream value(64); + value << gtk_entry_get_text(g_entityValueEntry); + + + // TTimo: if you change the classname to worldspawn you won't merge back in the structural brushes but create a parasite entity + if (!strcmp(key.c_str(), "classname") && !strcmp(value.c_str(), "worldspawn")) { + ui::alert(g_entityKeyEntry.window(), "Cannot change \"classname\" key back to worldspawn.", 0, + ui::alert_type::OK); + return; + } + + + // RR2DO2: we don't want spaces in entity keys + if (strstr(key.c_str(), " ")) { + ui::alert(g_entityKeyEntry.window(), "No spaces are allowed in entity keys.", 0, ui::alert_type::OK); + return; + } + + if (strcmp(key.c_str(), "classname") == 0) { + StringOutputStream command; + command << "entitySetClass -class " << value.c_str(); + UndoableCommand undo(command.c_str()); + Scene_EntitySetClassname_Selected(value.c_str()); + } else { + Scene_EntitySetKeyValue_Selected_Undoable(key.c_str(), value.c_str()); + } } void EntityInspector_clearKeyValue() { - // Get current selection text - StringOutputStream key(64); - key << ConvertUTF8ToLocale(gtk_entry_get_text(g_entityKeyEntry)); - - if(strcmp(key.c_str(), "classname") != 0) - { - StringOutputStream command; - command << "entityDeleteKey -key " << key.c_str(); - UndoableCommand undo(command.c_str()); - Scene_EntitySetKeyValue_Selected(key.c_str(), ""); - } + // Get current selection text + StringOutputStream key(64); + key << gtk_entry_get_text(g_entityKeyEntry); + + if (strcmp(key.c_str(), "classname") != 0) { + StringOutputStream command; + command << "entityDeleteKey -key " << key.c_str(); + UndoableCommand undo(command.c_str()); + Scene_EntitySetKeyValue_Selected(key.c_str(), ""); + } } void EntityInspector_clearAllKeyValues() { - UndoableCommand undo("entityClear"); + UndoableCommand undo("entityClear"); - // remove all keys except classname - for(KeyValues::iterator i = g_selectedKeyValues.begin(); i != g_selectedKeyValues.end(); ++i) - { - if(strcmp((*i).first.c_str(), "classname") != 0) - { - Scene_EntitySetKeyValue_Selected((*i).first.c_str(), ""); + // remove all keys except classname + for (KeyValues::iterator i = g_selectedKeyValues.begin(); i != g_selectedKeyValues.end(); ++i) { + if (strcmp((*i).first.c_str(), "classname") != 0) { + Scene_EntitySetKeyValue_Selected((*i).first.c_str(), ""); + } } - } } // ============================================================================= // callbacks -static void EntityClassList_selection_changed(GtkTreeSelection* selection, gpointer data) +static void EntityClassList_selection_changed(ui::TreeSelection selection, gpointer data) { - GtkTreeModel* model; - GtkTreeIter selected; - if(gtk_tree_selection_get_selected(selection, &model, &selected)) - { - EntityClass* eclass; - gtk_tree_model_get(model, &selected, 1, &eclass, -1); - if(eclass != 0) - { - SetComment(eclass); + GtkTreeModel *model; + GtkTreeIter selected; + if (gtk_tree_selection_get_selected(selection, &model, &selected)) { + EntityClass *eclass; + gtk_tree_model_get(model, &selected, 1, &eclass, -1); + if (eclass != 0) { + SetComment(eclass); + } } - } } -static gint EntityClassList_button_press(GtkWidget *widget, GdkEventButton *event, gpointer data) +static gint EntityClassList_button_press(ui::Widget widget, GdkEventButton *event, gpointer data) { - if (event->type == GDK_2BUTTON_PRESS) - { - EntityClassList_createEntity(); - return TRUE; - } - return FALSE; + if (event->type == GDK_2BUTTON_PRESS) { + EntityClassList_createEntity(); + return TRUE; + } + return FALSE; } -static gint EntityClassList_keypress(GtkWidget* widget, GdkEventKey* event, gpointer data) +static gint EntityClassList_keypress(ui::Widget widget, GdkEventKey *event, gpointer data) { - unsigned int code = gdk_keyval_to_upper (event->keyval); - - if (event->keyval == GDK_Return) - { - EntityClassList_createEntity(); - return TRUE; - } - - // select the entity that starts with the key pressed - if (code <= 'Z' && code >= 'A') - { - GtkTreeView* view = g_entityClassList; - GtkTreeModel* model; - GtkTreeIter iter; - if(gtk_tree_selection_get_selected(gtk_tree_view_get_selection(view), &model, &iter) == FALSE - || gtk_tree_model_iter_next(model, &iter) == FALSE) - { - gtk_tree_model_get_iter_first(model, &iter); - } + unsigned int code = gdk_keyval_to_upper(event->keyval); - for(std::size_t count = gtk_tree_model_iter_n_children(model, 0); count > 0; --count) - { - char* text; - gtk_tree_model_get(model, &iter, 0, &text, -1); + if (event->keyval == GDK_KEY_Return) { + EntityClassList_createEntity(); + return TRUE; + } - if (toupper (text[0]) == (int)code) - { - GtkTreePath* path = gtk_tree_model_get_path(model, &iter); - gtk_tree_selection_select_path(gtk_tree_view_get_selection(view), path); - if(GTK_WIDGET_REALIZED(view)) - { - gtk_tree_view_scroll_to_cell(view, path, 0, FALSE, 0, 0); + // select the entity that starts with the key pressed + if (code <= 'Z' && code >= 'A') { + auto view = ui::TreeView(g_entityClassList); + GtkTreeModel *model; + GtkTreeIter iter; + if (gtk_tree_selection_get_selected(gtk_tree_view_get_selection(view), &model, &iter) == FALSE + || gtk_tree_model_iter_next(model, &iter) == FALSE) { + gtk_tree_model_get_iter_first(model, &iter); } - gtk_tree_path_free(path); - count = 1; - } - g_free(text); + for (std::size_t count = gtk_tree_model_iter_n_children(model, 0); count > 0; --count) { + char *text; + gtk_tree_model_get(model, &iter, 0, &text, -1); + + if (toupper(text[0]) == (int) code) { + auto path = gtk_tree_model_get_path(model, &iter); + gtk_tree_selection_select_path(gtk_tree_view_get_selection(view), path); + if (gtk_widget_get_realized(view)) { + gtk_tree_view_scroll_to_cell(view, path, 0, FALSE, 0, 0); + } + gtk_tree_path_free(path); + count = 1; + } - if(gtk_tree_model_iter_next(model, &iter) == FALSE) - gtk_tree_model_get_iter_first(model, &iter); - } + g_free(text); - return TRUE; - } - return FALSE; + if (gtk_tree_model_iter_next(model, &iter) == FALSE) { + gtk_tree_model_get_iter_first(model, &iter); + } + } + + return TRUE; + } + return FALSE; } -static void EntityProperties_selection_changed(GtkTreeSelection* selection, gpointer data) +static void EntityProperties_selection_changed(ui::TreeSelection selection, gpointer data) { - // find out what type of entity we are trying to create - GtkTreeModel* model; - GtkTreeIter iter; - if(gtk_tree_selection_get_selected(selection, &model, &iter) == FALSE) - { - return; - } - - char* key; - char* val; - gtk_tree_model_get(model, &iter, 0, &key, 1, &val, -1); - - gtk_entry_set_text(g_entityKeyEntry, key); - gtk_entry_set_text(g_entityValueEntry, val); - - g_free(key); - g_free(val); + // find out what type of entity we are trying to create + GtkTreeModel *model; + GtkTreeIter iter; + if (gtk_tree_selection_get_selected(selection, &model, &iter) == FALSE) { + return; + } + + char *key; + char *val; + gtk_tree_model_get(model, &iter, 0, &key, 1, &val, -1); + + g_entityKeyEntry.text(key); + g_entityValueEntry.text(val); + + g_free(key); + g_free(val); } -static void SpawnflagCheck_toggled(GtkWidget *widget, gpointer data) +static void SpawnflagCheck_toggled(ui::Widget widget, gpointer data) { - EntityInspector_applySpawnflags(); + EntityInspector_applySpawnflags(); } -static gint EntityEntry_keypress(GtkEntry* widget, GdkEventKey* event, gpointer data) +static gint EntityEntry_keypress(ui::Entry widget, GdkEventKey *event, gpointer data) { - if (event->keyval == GDK_Return) - { - if(widget == g_entityKeyEntry) - { - gtk_entry_set_text(g_entityValueEntry, ""); - gtk_window_set_focus(GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(widget))), GTK_WIDGET(g_entityValueEntry)); + if (event->keyval == GDK_KEY_Return) { + if (widget._handle == g_entityKeyEntry._handle) { + g_entityValueEntry.text(""); + gtk_window_set_focus(widget.window(), g_entityValueEntry); + } else { + EntityInspector_applyKeyValue(); + } + return TRUE; } - else - { - EntityInspector_applyKeyValue(); + if (event->keyval == GDK_KEY_Escape) { + gtk_window_set_focus(widget.window(), NULL); + return TRUE; } - return TRUE; - } - if (event->keyval == GDK_Escape) - { - gtk_window_set_focus(GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(widget))), NULL); - return TRUE; - } - return FALSE; + return FALSE; } -void EntityInspector_destroyWindow(GtkWidget* widget, gpointer data) +void EntityInspector_destroyWindow(ui::Widget widget, gpointer data) { - g_entitysplit1_position = gtk_paned_get_position(GTK_PANED(g_entity_split1)); - g_entitysplit2_position = gtk_paned_get_position(GTK_PANED(g_entity_split2)); + g_entitysplit1_position = gtk_paned_get_position(GTK_PANED(g_entity_split1)); + g_entitysplit2_position = gtk_paned_get_position(GTK_PANED(g_entity_split2)); - g_entityInspector_windowConstructed = false; - GlobalEntityAttributes_clear(); + g_entityInspector_windowConstructed = false; + GlobalEntityAttributes_clear(); } -GtkWidget* EntityInspector_constructWindow(GtkWindow* toplevel) +ui::Widget EntityInspector_constructWindow(ui::Window toplevel) { - GtkWidget* vbox = gtk_vbox_new(FALSE, 2); - gtk_widget_show (vbox); - gtk_container_set_border_width(GTK_CONTAINER (vbox), 2); + auto vbox = ui::VBox(FALSE, 2); + vbox.show(); + gtk_container_set_border_width(GTK_CONTAINER(vbox), 2); - g_signal_connect(G_OBJECT(vbox), "destroy", G_CALLBACK(EntityInspector_destroyWindow), 0); - - { - GtkWidget* split1 = gtk_vpaned_new(); - gtk_box_pack_start(GTK_BOX(vbox), split1, TRUE, TRUE, 0); - gtk_widget_show (split1); - - g_entity_split1 = split1; + vbox.connect("destroy", G_CALLBACK(EntityInspector_destroyWindow), 0); { - GtkWidget* split2 = gtk_vpaned_new(); - gtk_paned_add1 (GTK_PANED (split1), split2); - gtk_widget_show (split2); - - g_entity_split2 = split2; + auto split1 = ui::VPaned(ui::New); + vbox.pack_start(split1, TRUE, TRUE, 0); + split1.show(); - { - // class list - GtkWidget* scr = gtk_scrolled_window_new (0, 0); - gtk_widget_show (scr); - gtk_paned_add1 (GTK_PANED (split2), scr); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN); + g_entity_split1 = split1; { - GtkListStore* store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_POINTER); + ui::Widget split2 = ui::VPaned(ui::New); + gtk_paned_add1(GTK_PANED(split1), split2); + split2.show(); - GtkTreeView* view = GTK_TREE_VIEW(gtk_tree_view_new_with_model(GTK_TREE_MODEL(store))); - gtk_tree_view_set_headers_visible(view, FALSE); - g_signal_connect(G_OBJECT(view), "button_press_event", G_CALLBACK(EntityClassList_button_press), 0); - g_signal_connect(G_OBJECT(view), "key_press_event", G_CALLBACK(EntityClassList_keypress), 0); + g_entity_split2 = split2; - { - GtkCellRenderer* renderer = gtk_cell_renderer_text_new(); - GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("Key", renderer, "text", 0, 0); - gtk_tree_view_append_column(view, column); - } - - { - GtkTreeSelection* selection = gtk_tree_view_get_selection(view); - g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(EntityClassList_selection_changed), 0); - } - - gtk_widget_show(GTK_WIDGET(view)); - - gtk_container_add(GTK_CONTAINER(scr), GTK_WIDGET(view)); - - g_object_unref(G_OBJECT(store)); - g_entityClassList = view; - g_entlist_store = store; - } - } - - { - GtkWidget* scr = gtk_scrolled_window_new (0, 0); - gtk_widget_show (scr); - gtk_paned_add2 (GTK_PANED (split2), scr); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN); - - { - GtkTextView* text = GTK_TEXT_VIEW(gtk_text_view_new()); - gtk_widget_set_size_request(GTK_WIDGET(text), 0, -1); // allow shrinking - gtk_text_view_set_wrap_mode(text, GTK_WRAP_WORD); - gtk_text_view_set_editable(text, FALSE); - gtk_widget_show(GTK_WIDGET(text)); - gtk_container_add(GTK_CONTAINER(scr), GTK_WIDGET(text)); - g_entityClassComment = text; - } - } - } - - { - GtkWidget* split2 = gtk_vpaned_new(); - gtk_paned_add2 (GTK_PANED (split1), split2); - gtk_widget_show(split2); - - { - GtkWidget* vbox2 = gtk_vbox_new (FALSE, 2); - gtk_widget_show (vbox2); - gtk_paned_pack1(GTK_PANED(split2), vbox2, FALSE, FALSE); + { + // class list + auto scr = ui::ScrolledWindow(ui::New); + scr.show(); + gtk_paned_add1(GTK_PANED(split2), scr); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scr), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN); + + { + ui::ListStore store = ui::ListStore::from(gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_POINTER)); + + auto view = ui::TreeView(ui::TreeModel::from(store._handle)); + gtk_tree_view_set_enable_search(view, FALSE); + gtk_tree_view_set_headers_visible(view, FALSE); + view.connect("button_press_event", G_CALLBACK(EntityClassList_button_press), 0); + view.connect("key_press_event", G_CALLBACK(EntityClassList_keypress), 0); + + { + auto renderer = ui::CellRendererText(ui::New); + auto column = ui::TreeViewColumn("Key", renderer, {{"text", 0}}); + gtk_tree_view_append_column(view, column); + } + + { + auto selection = ui::TreeSelection::from(gtk_tree_view_get_selection(view)); + selection.connect("changed", G_CALLBACK(EntityClassList_selection_changed), 0); + } + + view.show(); + + scr.add(view); + + store.unref(); + g_entityClassList = view; + g_entlist_store = store; + } + } - { - // Spawnflags (4 colums wide max, or window gets too wide.) - GtkTable* table = GTK_TABLE(gtk_table_new(4, 4, FALSE)); - gtk_box_pack_start (GTK_BOX (vbox2), GTK_WIDGET(table), FALSE, TRUE, 0); - gtk_widget_show(GTK_WIDGET(table)); - - g_spawnflagsTable = table; - - for (int i = 0; i < MAX_FLAGS; i++) - { - GtkCheckButton* check = GTK_CHECK_BUTTON(gtk_check_button_new_with_label("")); - gtk_widget_ref(GTK_WIDGET(check)); - g_object_set_data(G_OBJECT(check), "handler", gint_to_pointer(g_signal_connect(G_OBJECT(check), "toggled", G_CALLBACK(SpawnflagCheck_toggled), 0))); - g_entitySpawnflagsCheck[i] = check; - } + { + auto scr = ui::ScrolledWindow(ui::New); + scr.show(); + gtk_paned_add2(GTK_PANED(split2), scr); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scr), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN); + + { + auto text = ui::TextView(ui::New); + text.dimensions(0, -1); // allow shrinking + gtk_text_view_set_wrap_mode(text, GTK_WRAP_WORD); + gtk_text_view_set_editable(text, FALSE); + text.show(); + scr.add(text); + g_entityClassComment = text; + } + } } { - // key/value list - GtkWidget* scr = gtk_scrolled_window_new (0, 0); - gtk_widget_show (scr); - gtk_box_pack_start (GTK_BOX (vbox2), scr, TRUE, TRUE, 0); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN); - - { - GtkListStore* store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING); - - GtkWidget* view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); - gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE); + ui::Widget split2 = ui::VPaned(ui::New); + gtk_paned_add2(GTK_PANED(split1), split2); + split2.show(); { - GtkCellRenderer* renderer = gtk_cell_renderer_text_new(); - GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("", renderer, "text", 0, 0); - gtk_tree_view_append_column(GTK_TREE_VIEW(view), column); + auto vbox2 = ui::VBox(FALSE, 2); + vbox2.show(); + gtk_paned_pack1(GTK_PANED(split2), vbox2, FALSE, FALSE); + + { + // Spawnflags (4 colums wide max, or window gets too wide.) + auto table = ui::Table(4, 4, FALSE); + vbox2.pack_start(table, FALSE, TRUE, 0); + table.show(); + + g_spawnflagsTable = table; + + for (int i = 0; i < MAX_FLAGS; i++) { + auto check = ui::CheckButton(""); + check.ref(); + g_object_set_data(G_OBJECT(check), "handler", gint_to_pointer( + check.connect("toggled", G_CALLBACK(SpawnflagCheck_toggled), 0))); + g_entitySpawnflagsCheck[i] = check; + } + } + + { + // key/value list + auto scr = ui::ScrolledWindow(ui::New); + scr.show(); + vbox2.pack_start(scr, TRUE, TRUE, 0); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scr), GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN); + + { + ui::ListStore store = ui::ListStore::from(gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING)); + + auto view = ui::TreeView(ui::TreeModel::from(store._handle)); + gtk_tree_view_set_enable_search(view, FALSE); + gtk_tree_view_set_headers_visible(view, FALSE); + + { + auto renderer = ui::CellRendererText(ui::New); + auto column = ui::TreeViewColumn("", renderer, {{"text", 0}}); + gtk_tree_view_append_column(view, column); + } + + { + auto renderer = ui::CellRendererText(ui::New); + auto column = ui::TreeViewColumn("", renderer, {{"text", 1}}); + gtk_tree_view_append_column(view, column); + } + + { + auto selection = ui::TreeSelection::from(gtk_tree_view_get_selection(view)); + selection.connect("changed", G_CALLBACK(EntityProperties_selection_changed), 0); + } + + view.show(); + + scr.add(view); + + store.unref(); + + g_entprops_store = store; + } + } + + { + // key/value entry + auto table = ui::Table(2, 2, FALSE); + table.show(); + vbox2.pack_start(table, FALSE, TRUE, 0); + gtk_table_set_row_spacings(table, 3); + gtk_table_set_col_spacings(table, 5); + + { + auto entry = ui::Entry(ui::New); + entry.show(); + table.attach(entry, {1, 2, 0, 1}, {GTK_EXPAND | GTK_FILL, 0}); + gtk_widget_set_events(entry, GDK_KEY_PRESS_MASK); + entry.connect("key_press_event", G_CALLBACK(EntityEntry_keypress), 0); + g_entityKeyEntry = entry; + } + + { + auto entry = ui::Entry(ui::New); + entry.show(); + table.attach(entry, {1, 2, 1, 2}, {GTK_EXPAND | GTK_FILL, 0}); + gtk_widget_set_events(entry, GDK_KEY_PRESS_MASK); + entry.connect("key_press_event", G_CALLBACK(EntityEntry_keypress), 0); + g_entityValueEntry = entry; + } + + { + auto label = ui::Label("Value"); + label.show(); + table.attach(label, {0, 1, 1, 2}, {GTK_FILL, 0}); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + } + + { + auto label = ui::Label("Key"); + label.show(); + table.attach(label, {0, 1, 0, 1}, {GTK_FILL, 0}); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + } + } + + { + auto hbox = ui::HBox(TRUE, 4); + hbox.show(); + vbox2.pack_start(hbox, FALSE, TRUE, 0); + + { + auto button = ui::Button("Clear All"); + button.show(); + button.connect("clicked", G_CALLBACK(EntityInspector_clearAllKeyValues), 0); + hbox.pack_start(button, TRUE, TRUE, 0); + } + { + auto button = ui::Button("Delete Key"); + button.show(); + button.connect("clicked", G_CALLBACK(EntityInspector_clearKeyValue), 0); + hbox.pack_start(button, TRUE, TRUE, 0); + } + } } { - GtkCellRenderer* renderer = gtk_cell_renderer_text_new(); - GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("", renderer, "text", 1, 0); - gtk_tree_view_append_column(GTK_TREE_VIEW(view), column); - } + auto scr = ui::ScrolledWindow(ui::New); + scr.show(); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scr), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); - { - GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); - g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(EntityProperties_selection_changed), 0); - } + auto viewport = ui::Container::from(gtk_viewport_new(0, 0)); + viewport.show(); + gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE); - gtk_widget_show(view); + g_attributeBox = ui::VBox(FALSE, 2); + g_attributeBox.show(); - gtk_container_add(GTK_CONTAINER (scr), view); + viewport.add(g_attributeBox); + scr.add(viewport); + gtk_paned_pack2(GTK_PANED(split2), scr, FALSE, FALSE); + } + } + } - g_object_unref(G_OBJECT(store)); - g_entprops_store = store; - } + { + // show the sliders in any case + if (g_entitysplit2_position > 22) { + gtk_paned_set_position(GTK_PANED(g_entity_split2), g_entitysplit2_position); + } else { + g_entitysplit2_position = 22; + gtk_paned_set_position(GTK_PANED(g_entity_split2), 22); } - - { - // key/value entry - GtkTable* table = GTK_TABLE(gtk_table_new(2, 2, FALSE)); - gtk_widget_show(GTK_WIDGET(table)); - gtk_box_pack_start(GTK_BOX(vbox2), GTK_WIDGET(table), FALSE, TRUE, 0); - gtk_table_set_row_spacings(table, 3); - gtk_table_set_col_spacings(table, 5); - - { - GtkEntry* entry = GTK_ENTRY(gtk_entry_new()); - gtk_widget_show(GTK_WIDGET(entry)); - gtk_table_attach(table, GTK_WIDGET(entry), 1, 2, 0, 1, - (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), - (GtkAttachOptions)(0), 0, 0); - gtk_widget_set_events(GTK_WIDGET(entry), GDK_KEY_PRESS_MASK); - g_signal_connect(G_OBJECT(entry), "key_press_event", G_CALLBACK(EntityEntry_keypress), 0); - g_entityKeyEntry = entry; - } - - { - GtkEntry* entry = GTK_ENTRY(gtk_entry_new()); - gtk_widget_show(GTK_WIDGET(entry)); - gtk_table_attach(table, GTK_WIDGET(entry), 1, 2, 1, 2, - (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), - (GtkAttachOptions)(0), 0, 0); - gtk_widget_set_events(GTK_WIDGET(entry), GDK_KEY_PRESS_MASK); - g_signal_connect(G_OBJECT(entry), "key_press_event", G_CALLBACK(EntityEntry_keypress), 0); - g_entityValueEntry = entry; - } - - { - GtkLabel* label = GTK_LABEL(gtk_label_new("Value")); - gtk_widget_show(GTK_WIDGET(label)); - gtk_table_attach(table, GTK_WIDGET(label), 0, 1, 1, 2, - (GtkAttachOptions)(GTK_FILL), - (GtkAttachOptions)(0), 0, 0); - gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - } - - { - GtkLabel* label = GTK_LABEL(gtk_label_new("Key")); - gtk_widget_show(GTK_WIDGET(label)); - gtk_table_attach(table, GTK_WIDGET(label), 0, 1, 0, 1, - (GtkAttachOptions)(GTK_FILL), - (GtkAttachOptions)(0), 0, 0); - gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - } + if ((g_entitysplit1_position - g_entitysplit2_position) > 27) { + gtk_paned_set_position(GTK_PANED(g_entity_split1), g_entitysplit1_position); + } else { + gtk_paned_set_position(GTK_PANED(g_entity_split1), g_entitysplit2_position + 27); } + } - { - GtkBox* hbox = GTK_BOX(gtk_hbox_new(TRUE, 4)); - gtk_widget_show(GTK_WIDGET(hbox)); - gtk_box_pack_start(GTK_BOX(vbox2), GTK_WIDGET(hbox), FALSE, TRUE, 0); - - { - GtkButton* button = GTK_BUTTON(gtk_button_new_with_label("Clear All")); - gtk_widget_show(GTK_WIDGET(button)); - g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(EntityInspector_clearAllKeyValues), 0); - gtk_box_pack_start(hbox, GTK_WIDGET(button), TRUE, TRUE, 0); - } - { - GtkButton* button = GTK_BUTTON(gtk_button_new_with_label("Delete Key")); - gtk_widget_show(GTK_WIDGET(button)); - g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(EntityInspector_clearKeyValue), 0); - gtk_box_pack_start(hbox, GTK_WIDGET(button), TRUE, TRUE, 0); - } - } - } + g_entityInspector_windowConstructed = true; + EntityClassList_fill(); - { - GtkWidget* scr = gtk_scrolled_window_new(0, 0); - gtk_widget_show(scr); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scr), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + typedef FreeCaller EntityInspectorSelectionChangedCaller; + GlobalSelectionSystem().addSelectionChangeCallback(EntityInspectorSelectionChangedCaller()); + GlobalEntityCreator().setKeyValueChangedFunc(EntityInspector_keyValueChanged); - GtkWidget* viewport = gtk_viewport_new(0, 0); - gtk_widget_show(viewport); - gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE); + // hack + gtk_container_set_focus_chain(GTK_CONTAINER(vbox), NULL); - g_attributeBox = GTK_VBOX(gtk_vbox_new(FALSE, 2)); - gtk_widget_show(GTK_WIDGET(g_attributeBox)); + return vbox; +} - gtk_container_add(GTK_CONTAINER(viewport), GTK_WIDGET(g_attributeBox)); - gtk_container_add(GTK_CONTAINER(scr), viewport); - gtk_paned_pack2(GTK_PANED(split2), scr, FALSE, FALSE); - } +class EntityInspector : public ModuleObserver { + std::size_t m_unrealised; +public: + EntityInspector() : m_unrealised(1) + { } - } - - { - // show the sliders in any case - if(g_entitysplit2_position > 22) + void realise() { - gtk_paned_set_position (GTK_PANED(g_entity_split2), g_entitysplit2_position); - } else { - g_entitysplit2_position = 22; - gtk_paned_set_position (GTK_PANED(g_entity_split2), 22); + if (--m_unrealised == 0) { + if (g_entityInspector_windowConstructed) { + //globalOutputStream() << "Entity Inspector: realise\n"; + EntityClassList_fill(); + } + } } - if((g_entitysplit1_position - g_entitysplit2_position) > 27) + + void unrealise() { - gtk_paned_set_position (GTK_PANED(g_entity_split1), g_entitysplit1_position); - } else { - gtk_paned_set_position (GTK_PANED(g_entity_split1), g_entitysplit2_position + 27); + if (++m_unrealised == 1) { + if (g_entityInspector_windowConstructed) { + //globalOutputStream() << "Entity Inspector: unrealise\n"; + EntityClassList_clear(); + } + } } - } - - g_entityInspector_windowConstructed = true; - EntityClassList_fill(); - - typedef FreeCaller1 EntityInspectorSelectionChangedCaller; - GlobalSelectionSystem().addSelectionChangeCallback(EntityInspectorSelectionChangedCaller()); - GlobalEntityCreator().setKeyValueChangedFunc(EntityInspector_keyValueChanged); - - // hack - gtk_container_set_focus_chain(GTK_CONTAINER(vbox), NULL); - - return vbox; -} - -class EntityInspector : public ModuleObserver -{ - std::size_t m_unrealised; -public: - EntityInspector() : m_unrealised(1) - { - } - void realise() - { - if(--m_unrealised == 0) - { - if(g_entityInspector_windowConstructed) - { - //globalOutputStream() << "Entity Inspector: realise\n"; - EntityClassList_fill(); - } - } - } - void unrealise() - { - if(++m_unrealised == 1) - { - if(g_entityInspector_windowConstructed) - { - //globalOutputStream() << "Entity Inspector: unrealise\n"; - EntityClassList_clear(); - } - } - } }; EntityInspector g_EntityInspector; @@ -1745,15 +1692,25 @@ EntityInspector g_EntityInspector; void EntityInspector_construct() { - GlobalEntityClassManager().attach(g_EntityInspector); + GlobalEntityClassManager().attach(g_EntityInspector); - GlobalPreferenceSystem().registerPreference("EntitySplit1", IntImportStringCaller(g_entitysplit1_position), IntExportStringCaller(g_entitysplit1_position)); - GlobalPreferenceSystem().registerPreference("EntitySplit2", IntImportStringCaller(g_entitysplit2_position), IntExportStringCaller(g_entitysplit2_position)); + GlobalPreferenceSystem().registerPreference("EntitySplit1", make_property_string(g_entitysplit1_position)); + GlobalPreferenceSystem().registerPreference("EntitySplit2", make_property_string(g_entitysplit2_position)); } void EntityInspector_destroy() { - GlobalEntityClassManager().detach(g_EntityInspector); + GlobalEntityClassManager().detach(g_EntityInspector); } +const char *EntityInspector_getCurrentKey() +{ + if (!GroupDialog_isShown()) { + return 0; + } + if (GroupDialog_getPage() != g_page_entity) { + return 0; + } + return gtk_entry_get_text(g_entityKeyEntry); +}