3
#include <gtkmm/viewport.h>
4
#include <gtkmm/separator.h>
5
#include "gtk_helpers.h"
6
#include "properties_tree.h"
8
//------------------------------------------------------------------------------
9
PropertyValue::PropertyValue(PropertyInspector* owner, const bec::NodeId& node)
14
_text.set_alignment(Gtk::ALIGN_LEFT);
15
_text.set_single_line_mode(true);
16
_text.set_ellipsize(Pango::ELLIPSIZE_END);
18
_conn = signal_event().connect(sigc::mem_fun(this, &PropertyValue::on_event));
20
modify_bg(Gtk::STATE_NORMAL, Gdk::Color("#f5f5f5"));
23
//------------------------------------------------------------------------------
24
PropertyValue::~PropertyValue()
29
//------------------------------------------------------------------------------
30
void PropertyValue::set_text(const std::string& text)
35
//------------------------------------------------------------------------------
36
void PropertyValue::stop_edit()
43
//------------------------------------------------------------------------------
44
void PropertyValue::start_edit()
49
editor().property_width_request() = get_width()-2;
55
//------------------------------------------------------------------------------
56
bool PropertyValue::on_event(GdkEvent* event)
58
if ( event->type == GDK_BUTTON_PRESS && event->button.button == 1 )
60
_owner->handle_click(this);
63
else if ( event->type == GDK_KEY_RELEASE )
65
const int key = event->key.keyval;
66
if ( key == GDK_Escape)
68
_owner->edit_canceled();
72
else if (key == GDK_Return)
74
set_text(get_new_value());
75
_owner->edit_done(this, true);
83
//==============================================================================
84
PropertyString::PropertyString(PropertyInspector* owner, const bec::NodeId& node)
85
: PropertyValue(owner,node)
87
_entry.set_has_frame(false);
88
_entry.set_alignment(Gtk::ALIGN_LEFT);
91
//------------------------------------------------------------------------------
92
std::string PropertyString::get_new_value() const
94
return _entry.get_text();
97
//------------------------------------------------------------------------------
98
void PropertyString::start_editing()
100
_entry.set_text(get_text());
104
//------------------------------------------------------------------------------
105
Gtk::Widget& PropertyString::editor()
110
//==============================================================================
111
PropertyBool::PropertyBool(PropertyInspector* owner, const bec::NodeId& node)
112
: PropertyValue(owner,node)
114
_conn = _button.signal_toggled().connect(sigc::mem_fun(this, &PropertyBool::on_value_changed));
116
start_edit(); // That's because when PropertyValue set ups label its vtable points to PropertyValue
117
// So we need to update Table with our control. As we have the same CheckButton
118
// for label and for editor it is ok to call start_edit. It will replace label
119
// widget with editor widget. But at this moment label() and editor() will
120
// return PropertyBool's widgets.
123
//------------------------------------------------------------------------------
124
std::string PropertyBool::get_new_value() const
126
return _button.get_active() ? "1" : "0";
129
//------------------------------------------------------------------------------
130
void PropertyBool::set_text(const std::string& text)
133
_button.set_active(text == "1" ? 1 : 0);
137
//------------------------------------------------------------------------------
138
std::string PropertyBool::get_text() const
140
return _button.get_active() ? "1" : "0";
143
//------------------------------------------------------------------------------
144
void PropertyBool::start_editing()
149
//------------------------------------------------------------------------------
150
Gtk::Widget& PropertyBool::editor()
156
//------------------------------------------------------------------------------
157
Gtk::Widget& PropertyBool::label()
162
//------------------------------------------------------------------------------
163
void PropertyBool::on_value_changed()
165
PropertyValue::set_text(_button.get_active() ? "True" : "False");
166
_owner->edit_done(this);
169
//==============================================================================
170
PropertyColor::PropertyColor(PropertyInspector* owner, const bec::NodeId& node)
171
: PropertyValue(owner,node)
174
_hbox.pack_start(_entry);
175
_hbox.pack_end(_button, false, false);
178
_button.signal_clicked().connect(sigc::mem_fun(this, &PropertyColor::show_dlg));
181
//------------------------------------------------------------------------------
182
std::string PropertyColor::get_new_value() const
184
return _entry.get_text();
187
//------------------------------------------------------------------------------
188
void PropertyColor::start_editing()
190
_entry.set_text(get_text());
193
//------------------------------------------------------------------------------
194
void PropertyColor::show_dlg()
196
_dlg.get_colorsel()->set_current_color(Gdk::Color(get_text()));
197
const int resp = _dlg.run();
199
if ( resp == Gtk::RESPONSE_OK )
201
const Gdk::Color color(_dlg.get_colorsel()->get_current_color());
203
snprintf(buffer, sizeof(buffer)-1, "#%02x%02x%02x", color.get_red()>>8, color.get_green()>>8, color.get_blue()>>8);
204
buffer[sizeof(buffer)-1] = 0;
206
_entry.set_text(buffer);
208
_owner->edit_done(this);
214
//------------------------------------------------------------------------------
215
Gtk::Widget& PropertyColor::editor()
220
//==============================================================================
221
PropertyText::PropertyText(PropertyInspector* owner, const bec::NodeId& node)
222
: PropertyValue(owner, node)
226
_wnd.get_vbox()->add(_scroll);
227
_wnd.set_position(Gtk::WIN_POS_MOUSE);
228
_wnd.set_has_separator(false);
229
_wnd.set_transient_for(*get_mainwindow());
231
_text.signal_event().connect(sigc::mem_fun(this, &PropertyText::handle_event));
234
//------------------------------------------------------------------------------
235
std::string PropertyText::get_new_value() const
237
Gtk::TextView *tv = const_cast<Gtk::TextView*>(&_text);
238
return tv->get_buffer()->get_text();
241
//------------------------------------------------------------------------------
242
void PropertyText::start_editing()
244
_text.get_buffer()->set_text(get_text());
248
//------------------------------------------------------------------------------
249
void PropertyText::stop_editing()
254
//------------------------------------------------------------------------------
255
bool PropertyText::handle_event(GdkEvent* event)
257
if ( event->type == GDK_KEY_PRESS )
259
const int key = event->key.keyval;
260
if ( key == GDK_Control_L || key == GDK_Control_R )
263
if ( event->type == GDK_KEY_RELEASE )
265
const int key = event->key.keyval;
266
if ( key == GDK_Control_L || key == GDK_Control_R )
269
if ( key == GDK_Escape)
271
_owner->edit_canceled();
275
else if (key == GDK_KP_Enter || (_ctrl && key == GDK_Return))
277
set_text(get_new_value());
278
_owner->edit_done(this, true);
286
//==============================================================================
287
PropertyInspector::PropertyInspector()
288
: _edited_property(0)
291
_table = new Gtk::Table();
292
_table->set_border_width(4);
296
//------------------------------------------------------------------------------
297
static void remove_child(Gtk::Widget& w)
303
//------------------------------------------------------------------------------
304
PropertyInspector::~PropertyInspector()
310
//------------------------------------------------------------------------------
311
void PropertyInspector::clear()
313
_edited_property = 0;
314
_table->foreach(sigc::ptr_fun(&::remove_child));
318
_table = new Gtk::Table();
319
_table->set_border_width(4);
320
_table->set_row_spacings(2);
323
Gtk::Viewport* vp = static_cast<Gtk::Viewport*>(_table->get_parent());
324
vp->modify_bg(Gtk::STATE_NORMAL, Gdk::Color("#ffffff"));
327
//------------------------------------------------------------------------------
328
void PropertyInspector::populate()
333
_table->property_n_columns() = 2;
334
const int count = _get_properties_count();
337
_table->property_n_rows() = count+1;
339
for ( int i = 0; i < count; ++i )
345
const std::string type = _get_type_slot(node);
346
const std::string name = _get_value_slot(node,true); // true means name
348
Gtk::Label* name_label = new Gtk::Label(name);
349
name_label->property_xalign() = 0.0;
350
_table->attach(*name_label, 0, 1, i2, i2+1, Gtk::FILL, Gtk::AttachOptions());
352
//g_message("prop %s, type %s", name.c_str(), type.c_str());
355
prop = new PropertyString(this, node);
356
else if ("bool" == type)
357
prop = new PropertyBool(this, node);
358
else if ("color" == type)
359
prop = new PropertyColor(this, node);
360
else if ("longtext" == type)
361
prop = new PropertyText(this, node);
363
prop = new PropertyString(this, node);
365
_table->attach(*prop, 1, 2, i2, i2+1, Gtk::EXPAND|Gtk::FILL, Gtk::AttachOptions());
367
Gtk::HSeparator *sep = new Gtk::HSeparator();
368
_table->attach(*sep, 0, 1, i2+1, i2+2, Gtk::FILL, Gtk::AttachOptions());
369
sep = new Gtk::HSeparator();
370
_table->attach(*sep, 1, 2, i2+1, i2+2, Gtk::FILL, Gtk::AttachOptions());
372
_properties.push_back(prop);
376
_table->show_all_children();
380
//------------------------------------------------------------------------------
381
void PropertyInspector::update()
384
const int count = _properties.size();
388
PropertyValue* prop = 0;
389
for ( int i = 0; i < count; ++i )
391
prop = _properties[i];
392
prop->set_text(_get_value_slot(prop->node(), false));
399
//------------------------------------------------------------------------------
400
void PropertyInspector::handle_click(PropertyValue* property)
402
if ( !_updating && _edited_property != property )
404
if ( _edited_property )
406
edit_done(_edited_property);
407
_edited_property->stop_edit();
410
_edited_property = property;
411
property->start_edit();
415
//------------------------------------------------------------------------------
416
void PropertyInspector::edit_done(PropertyValue* property, const bool finish)
420
_set_value_slot(property->node(), property->get_new_value(), property->type());
421
property->set_text(_get_value_slot(property->node(), false));
423
_edited_property = 0;
427
//------------------------------------------------------------------------------
428
void PropertyInspector::edit_canceled()
430
_edited_property = 0;
433
//------------------------------------------------------------------------------
434
PropertiesTree::PropertiesTree(wb::WBContextUI *wb)
435
: _wb(wb), _inspector(0)
437
pack_start(_combo, false, false);
438
pack_start(_inspector_view, true, true);
440
_inspector_view.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
441
_inspector_view.set_shadow_type(Gtk::SHADOW_IN);
446
//------------------------------------------------------------------------------
447
PropertiesTree::~PropertiesTree()
452
//------------------------------------------------------------------------------
453
void PropertiesTree::update()
455
std::vector<std::string> items;
459
_inspector = _wb->create_inspector_for_selection(_wb->get_active_main_form(), items);
461
_inspector_view.clear();
464
_inspector_view.set_count_slot(sigc::mem_fun(this, &PropertiesTree::get_properties_count));
465
_inspector_view.set_value_slot_setter(sigc::mem_fun(this, &PropertiesTree::set_value));
466
_inspector_view.set_value_slot_getter(sigc::mem_fun(this, &PropertiesTree::get_value));
467
_inspector_view.set_type_slot_getter(sigc::mem_fun(this, &PropertiesTree::get_prop_type));
469
_inspector_view.populate();
470
_inspector_view.update();
472
_inspector->set_refresh_ui_slot(sigc::mem_fun(this, &PropertiesTree::refresh));
475
_combo.clear_items();
476
for (std::vector<std::string>::const_iterator iter= items.begin();
477
iter != items.end(); ++iter)
479
_combo.append_text(*iter);
482
_combo.set_active(0);
486
//------------------------------------------------------------------------------
487
void PropertiesTree::refresh()
490
_inspector_view.update();
493
//------------------------------------------------------------------------------
494
int PropertiesTree::get_properties_count() const
496
return _inspector ? _inspector->count() : 0;
499
//------------------------------------------------------------------------------
500
std::string PropertiesTree::get_prop_type(const bec::NodeId& node) const
503
_inspector->get_field(node, ::bec::ValueInspectorBE::EditMethod, type);
507
//------------------------------------------------------------------------------
508
void PropertiesTree::set_value(const bec::NodeId& node, const std::string& value, const grt::Type type)
514
case grt::IntegerType:
516
const int iv = atoi(value.c_str());
517
_inspector->set_field(node, ::bec::ValueInspectorBE::Value, iv);
520
case grt::DoubleType:
522
const int dv = atof(value.c_str());
523
_inspector->set_field(node, ::bec::ValueInspectorBE::Value, dv);
526
case grt::StringType:
528
_inspector->set_field(node, ::bec::ValueInspectorBE::Value, value);
532
g_message("PropertiesTree::set_value: unhandled value type");
537
//------------------------------------------------------------------------------
538
std::string PropertiesTree::get_value(const bec::NodeId& node, const bool is_name) const
543
_inspector->get_field(node, is_name ? bec::ValueInspectorBE::Name : bec::ValueInspectorBE::Value, val);