~ubuntu-branches/ubuntu/quantal/mysql-workbench/quantal

« back to all changes in this revision

Viewing changes to frontend/linux/workbench/properties_tree.cpp

  • Committer: Package Import Robot
  • Author(s): Dmitry Smirnov
  • Date: 2012-03-01 21:57:30 UTC
  • Revision ID: package-import@ubuntu.com-20120301215730-o7y8av8y38n162ro
Tags: upstream-5.2.38+dfsg
ImportĀ upstreamĀ versionĀ 5.2.38+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <memory>
 
2
#include <gtk/gtk.h>
 
3
#include <gtkmm/viewport.h>
 
4
#include <gtkmm/separator.h>
 
5
#include "gtk_helpers.h"
 
6
#include "properties_tree.h"
 
7
 
 
8
//------------------------------------------------------------------------------
 
9
PropertyValue::PropertyValue(PropertyInspector* owner, const bec::NodeId& node)
 
10
              : _owner(owner)
 
11
              , _prop_node(node)
 
12
{
 
13
  add(_text);
 
14
  _text.set_alignment(Gtk::ALIGN_LEFT);
 
15
  _text.set_single_line_mode(true);
 
16
  _text.set_ellipsize(Pango::ELLIPSIZE_END);
 
17
  _text.show();
 
18
  _conn = signal_event().connect(sigc::mem_fun(this, &PropertyValue::on_event));
 
19
 
 
20
  modify_bg(Gtk::STATE_NORMAL, Gdk::Color("#f5f5f5"));
 
21
}
 
22
    
 
23
//------------------------------------------------------------------------------
 
24
PropertyValue::~PropertyValue()
 
25
{
 
26
  _conn.disconnect();
 
27
}
 
28
 
 
29
//------------------------------------------------------------------------------
 
30
void PropertyValue::set_text(const std::string& text)
 
31
{
 
32
  _text.set_text(text);
 
33
}
 
34
 
 
35
//------------------------------------------------------------------------------
 
36
void PropertyValue::stop_edit()
 
37
{
 
38
  stop_editing();
 
39
  remove();
 
40
  add(label());
 
41
}
 
42
 
 
43
//------------------------------------------------------------------------------
 
44
void PropertyValue::start_edit()
 
45
{
 
46
  remove();
 
47
  add(editor());
 
48
  
 
49
  editor().property_width_request() = get_width()-2;
 
50
  editor().show();  
 
51
 
 
52
  start_editing();
 
53
}
 
54
 
 
55
//------------------------------------------------------------------------------
 
56
bool PropertyValue::on_event(GdkEvent* event)
 
57
{
 
58
  if ( event->type == GDK_BUTTON_PRESS && event->button.button == 1 )
 
59
  {
 
60
    _owner->handle_click(this);
 
61
    return true;
 
62
  }
 
63
  else if ( event->type == GDK_KEY_RELEASE )
 
64
  {
 
65
    const int key = event->key.keyval;                                                                                                  
 
66
    if ( key == GDK_Escape)
 
67
    {  
 
68
      _owner->edit_canceled();
 
69
      stop_edit();
 
70
      return true;
 
71
    }
 
72
    else if (key == GDK_Return)
 
73
    {   
 
74
      set_text(get_new_value());
 
75
      _owner->edit_done(this, true);
 
76
      stop_edit();
 
77
      return true;
 
78
    }
 
79
  }
 
80
  return false;
 
81
}
 
82
 
 
83
//==============================================================================
 
84
PropertyString::PropertyString(PropertyInspector* owner, const bec::NodeId& node) 
 
85
               : PropertyValue(owner,node)
 
86
{
 
87
  _entry.set_has_frame(false);
 
88
  _entry.set_alignment(Gtk::ALIGN_LEFT);
 
89
}
 
90
 
 
91
//------------------------------------------------------------------------------
 
92
std::string PropertyString::get_new_value() const
 
93
{
 
94
  return _entry.get_text();
 
95
}
 
96
 
 
97
//------------------------------------------------------------------------------
 
98
void PropertyString::start_editing()
 
99
{
 
100
  _entry.set_text(get_text());
 
101
  _entry.show();
 
102
}
 
103
 
 
104
//------------------------------------------------------------------------------
 
105
Gtk::Widget& PropertyString::editor()
 
106
{
 
107
  return _entry;
 
108
}
 
109
 
 
110
//==============================================================================
 
111
PropertyBool::PropertyBool(PropertyInspector* owner, const bec::NodeId& node) 
 
112
               : PropertyValue(owner,node)
 
113
{
 
114
  _conn = _button.signal_toggled().connect(sigc::mem_fun(this, &PropertyBool::on_value_changed));
 
115
 
 
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.
 
121
}
 
122
 
 
123
//------------------------------------------------------------------------------
 
124
std::string PropertyBool::get_new_value() const
 
125
{
 
126
  return _button.get_active() ? "1" : "0";
 
127
}
 
128
 
 
129
//------------------------------------------------------------------------------
 
130
void PropertyBool::set_text(const std::string& text)
 
131
{   
 
132
  _conn.block();
 
133
  _button.set_active(text == "1" ? 1 : 0);
 
134
  _conn.unblock();
 
135
}
 
136
 
 
137
//------------------------------------------------------------------------------
 
138
std::string PropertyBool::get_text() const
 
139
{
 
140
  return _button.get_active() ? "1" : "0";
 
141
}
 
142
 
 
143
//------------------------------------------------------------------------------
 
144
void PropertyBool::start_editing()
 
145
{
 
146
  _button.show();
 
147
}
 
148
 
 
149
//------------------------------------------------------------------------------
 
150
Gtk::Widget& PropertyBool::editor()
 
151
{
 
152
  //return _combo;
 
153
  return _button;
 
154
}
 
155
 
 
156
//------------------------------------------------------------------------------
 
157
Gtk::Widget& PropertyBool::label()
 
158
{
 
159
  return _button;
 
160
}
 
161
 
 
162
//------------------------------------------------------------------------------
 
163
void PropertyBool::on_value_changed()
 
164
{
 
165
  PropertyValue::set_text(_button.get_active() ? "True" : "False");
 
166
  _owner->edit_done(this);
 
167
}
 
168
 
 
169
//==============================================================================
 
170
PropertyColor::PropertyColor(PropertyInspector* owner, const bec::NodeId& node)
 
171
              : PropertyValue(owner,node)
 
172
              , _button("...")
 
173
{
 
174
  _hbox.pack_start(_entry);
 
175
  _hbox.pack_end(_button, false, false);
 
176
  _hbox.show_all();
 
177
 
 
178
  _button.signal_clicked().connect(sigc::mem_fun(this, &PropertyColor::show_dlg));
 
179
}
 
180
 
 
181
//------------------------------------------------------------------------------
 
182
std::string PropertyColor::get_new_value() const
 
183
{
 
184
  return _entry.get_text();
 
185
}
 
186
 
 
187
//------------------------------------------------------------------------------
 
188
void PropertyColor::start_editing()
 
189
{
 
190
  _entry.set_text(get_text());
 
191
}
 
192
 
 
193
//------------------------------------------------------------------------------
 
194
void PropertyColor::show_dlg()
 
195
{
 
196
  _dlg.get_colorsel()->set_current_color(Gdk::Color(get_text()));
 
197
  const int resp = _dlg.run();
 
198
 
 
199
  if ( resp == Gtk::RESPONSE_OK )
 
200
  {     
 
201
    const Gdk::Color color(_dlg.get_colorsel()->get_current_color());
 
202
    char buffer[32];
 
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;
 
205
 
 
206
    _entry.set_text(buffer);
 
207
    set_text(buffer);
 
208
    _owner->edit_done(this);
 
209
    _entry.grab_focus();
 
210
  }
 
211
  _dlg.hide();
 
212
}
 
213
 
 
214
//------------------------------------------------------------------------------
 
215
Gtk::Widget& PropertyColor::editor()    
 
216
{
 
217
  return _hbox;
 
218
}
 
219
 
 
220
//==============================================================================
 
221
PropertyText::PropertyText(PropertyInspector* owner, const bec::NodeId& node)
 
222
             : PropertyValue(owner, node)
 
223
             , _ctrl(false)
 
224
{
 
225
  _scroll.add(_text);
 
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());
 
230
  _wnd.resize(128,96);
 
231
  _text.signal_event().connect(sigc::mem_fun(this, &PropertyText::handle_event));
 
232
}
 
233
 
 
234
//------------------------------------------------------------------------------
 
235
std::string PropertyText::get_new_value() const
 
236
{
 
237
  Gtk::TextView *tv = const_cast<Gtk::TextView*>(&_text);
 
238
  return tv->get_buffer()->get_text();
 
239
}
 
240
 
 
241
//------------------------------------------------------------------------------
 
242
void PropertyText::start_editing()
 
243
{
 
244
  _text.get_buffer()->set_text(get_text());
 
245
  _wnd.show_all();
 
246
}
 
247
 
 
248
//------------------------------------------------------------------------------
 
249
void PropertyText::stop_editing()
 
250
{
 
251
  _wnd.hide();
 
252
}
 
253
 
 
254
//------------------------------------------------------------------------------
 
255
bool PropertyText::handle_event(GdkEvent* event)
 
256
{
 
257
  if ( event->type == GDK_KEY_PRESS )
 
258
  {
 
259
    const int key = event->key.keyval;                                                                                                  
 
260
    if ( key == GDK_Control_L || key == GDK_Control_R )
 
261
      _ctrl = true;
 
262
  }
 
263
  if ( event->type == GDK_KEY_RELEASE )
 
264
  {
 
265
    const int key = event->key.keyval;                                                                                                  
 
266
    if ( key == GDK_Control_L || key == GDK_Control_R )
 
267
      _ctrl = false;
 
268
      
 
269
    if ( key == GDK_Escape)
 
270
    {
 
271
      _owner->edit_canceled();
 
272
      stop_edit();
 
273
      return true;
 
274
    }
 
275
    else if (key == GDK_KP_Enter || (_ctrl && key == GDK_Return))
 
276
    {   
 
277
      set_text(get_new_value());
 
278
      _owner->edit_done(this, true);
 
279
      stop_edit();
 
280
      return true;
 
281
    }
 
282
  }
 
283
  return false;
 
284
}
 
285
 
 
286
//==============================================================================
 
287
PropertyInspector::PropertyInspector()
 
288
                  : _edited_property(0)
 
289
                  , _updating(0)
 
290
{
 
291
  _table = new Gtk::Table();
 
292
  _table->set_border_width(4);
 
293
  add(*_table);
 
294
}
 
295
 
 
296
//------------------------------------------------------------------------------
 
297
static void remove_child(Gtk::Widget& w)
 
298
{
 
299
  w.hide();
 
300
  delete &w;
 
301
}
 
302
 
 
303
//------------------------------------------------------------------------------
 
304
PropertyInspector::~PropertyInspector()
 
305
{
 
306
  clear();
 
307
  delete _table;
 
308
}
 
309
 
 
310
//------------------------------------------------------------------------------
 
311
void PropertyInspector::clear()
 
312
{
 
313
  _edited_property = 0;
 
314
  _table->foreach(sigc::ptr_fun(&::remove_child));
 
315
  _properties.clear();
 
316
  remove();
 
317
  delete _table;
 
318
  _table = new Gtk::Table();
 
319
  _table->set_border_width(4);
 
320
  _table->set_row_spacings(2);
 
321
  add(*_table);
 
322
  _table->show();
 
323
  Gtk::Viewport* vp = static_cast<Gtk::Viewport*>(_table->get_parent());
 
324
  vp->modify_bg(Gtk::STATE_NORMAL, Gdk::Color("#ffffff"));
 
325
}
 
326
 
 
327
//------------------------------------------------------------------------------
 
328
void PropertyInspector::populate()
 
329
{
 
330
  _updating = 1;
 
331
  clear();
 
332
  
 
333
  _table->property_n_columns() = 2;
 
334
  const int count = _get_properties_count();
 
335
  if ( count > 0 )
 
336
  {
 
337
    _table->property_n_rows() = count+1;
 
338
    
 
339
    for ( int i = 0; i < count; ++i )
 
340
    {
 
341
      const int i2 = i*2;
 
342
      bec::NodeId node;
 
343
      node.append(i);
 
344
      
 
345
      const std::string type  = _get_type_slot(node);
 
346
      const std::string name  = _get_value_slot(node,true); // true means name 
 
347
 
 
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());
 
351
 
 
352
      //g_message("prop %s, type %s", name.c_str(), type.c_str());
 
353
      PropertyValue *prop;
 
354
      if (type.empty())
 
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);
 
362
      else  
 
363
        prop = new PropertyString(this, node);
 
364
  
 
365
      _table->attach(*prop, 1, 2, i2, i2+1, Gtk::EXPAND|Gtk::FILL, Gtk::AttachOptions());
 
366
 
 
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());
 
371
 
 
372
      _properties.push_back(prop);
 
373
    }
 
374
  }
 
375
  
 
376
  _table->show_all_children();
 
377
  _updating = 0;
 
378
}
 
379
    
 
380
//------------------------------------------------------------------------------
 
381
void PropertyInspector::update()
 
382
{
 
383
  _updating = 1;
 
384
  const int count = _properties.size();
 
385
 
 
386
  if ( count > 0 )
 
387
  {
 
388
    PropertyValue* prop = 0;
 
389
    for ( int i = 0; i < count; ++i )
 
390
    {
 
391
      prop = _properties[i];
 
392
      prop->set_text(_get_value_slot(prop->node(), false));
 
393
    }
 
394
  }
 
395
  _updating = 0;
 
396
}
 
397
    
 
398
 
 
399
//------------------------------------------------------------------------------
 
400
void PropertyInspector::handle_click(PropertyValue* property)
 
401
{
 
402
  if ( !_updating && _edited_property != property )
 
403
  {
 
404
    if ( _edited_property )
 
405
    {
 
406
      edit_done(_edited_property);
 
407
      _edited_property->stop_edit();
 
408
    }
 
409
    
 
410
    _edited_property = property;
 
411
    property->start_edit();
 
412
  }
 
413
}
 
414
 
 
415
//------------------------------------------------------------------------------
 
416
void PropertyInspector::edit_done(PropertyValue* property, const bool finish)
 
417
{
 
418
  if ( !_updating )
 
419
  {
 
420
    _set_value_slot(property->node(), property->get_new_value(), property->type());
 
421
    property->set_text(_get_value_slot(property->node(), false));
 
422
    if ( finish )
 
423
      _edited_property = 0;
 
424
  }
 
425
}
 
426
    
 
427
//------------------------------------------------------------------------------
 
428
void PropertyInspector::edit_canceled()
 
429
{
 
430
  _edited_property = 0;
 
431
}
 
432
 
 
433
//------------------------------------------------------------------------------
 
434
PropertiesTree::PropertiesTree(wb::WBContextUI *wb)
 
435
  : _wb(wb), _inspector(0)
 
436
{
 
437
  pack_start(_combo, false, false);
 
438
  pack_start(_inspector_view, true, true);
 
439
 
 
440
  _inspector_view.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
 
441
  _inspector_view.set_shadow_type(Gtk::SHADOW_IN);
 
442
 
 
443
  show_all();
 
444
}
 
445
 
 
446
//------------------------------------------------------------------------------
 
447
PropertiesTree::~PropertiesTree()
 
448
{
 
449
  delete _inspector;
 
450
}
 
451
 
 
452
//------------------------------------------------------------------------------
 
453
void PropertiesTree::update()
 
454
{
 
455
  std::vector<std::string> items;
 
456
  
 
457
  delete _inspector;
 
458
  _inspector = 0;
 
459
  _inspector = _wb->create_inspector_for_selection(_wb->get_active_main_form(), items);
 
460
  
 
461
  _inspector_view.clear();
 
462
  if (_inspector)
 
463
  {
 
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));
 
468
 
 
469
    _inspector_view.populate();
 
470
    _inspector_view.update();
 
471
 
 
472
    _inspector->set_refresh_ui_slot(sigc::mem_fun(this, &PropertiesTree::refresh));
 
473
  }
 
474
 
 
475
  _combo.clear_items();
 
476
  for (std::vector<std::string>::const_iterator iter= items.begin();
 
477
       iter != items.end(); ++iter)
 
478
  {
 
479
    _combo.append_text(*iter);
 
480
  }
 
481
 
 
482
  _combo.set_active(0);
 
483
}
 
484
 
 
485
 
 
486
//------------------------------------------------------------------------------
 
487
void PropertiesTree::refresh()
 
488
{
 
489
  if (_inspector)
 
490
    _inspector_view.update();
 
491
}
 
492
 
 
493
//------------------------------------------------------------------------------
 
494
int PropertiesTree::get_properties_count() const
 
495
{
 
496
  return _inspector ? _inspector->count() : 0;
 
497
}
 
498
 
 
499
//------------------------------------------------------------------------------
 
500
std::string PropertiesTree::get_prop_type(const bec::NodeId& node) const
 
501
{
 
502
  std::string type;
 
503
  _inspector->get_field(node, ::bec::ValueInspectorBE::EditMethod, type);
 
504
  return type;  
 
505
}
 
506
 
 
507
//------------------------------------------------------------------------------
 
508
void PropertiesTree::set_value(const bec::NodeId& node, const std::string& value, const grt::Type type)
 
509
 
510
  if (node.is_valid())
 
511
  {
 
512
    switch ( type )
 
513
    {
 
514
      case grt::IntegerType:
 
515
      {
 
516
        const int iv = atoi(value.c_str());
 
517
        _inspector->set_field(node, ::bec::ValueInspectorBE::Value, iv);
 
518
        break;
 
519
      }
 
520
      case grt::DoubleType:
 
521
      {
 
522
        const int dv = atof(value.c_str());
 
523
        _inspector->set_field(node, ::bec::ValueInspectorBE::Value, dv);
 
524
        break;
 
525
      }
 
526
      case grt::StringType:
 
527
      {
 
528
        _inspector->set_field(node, ::bec::ValueInspectorBE::Value, value);
 
529
        break;
 
530
      }
 
531
      default:
 
532
        g_message("PropertiesTree::set_value: unhandled value type");
 
533
    }
 
534
  }
 
535
}
 
536
 
 
537
//------------------------------------------------------------------------------
 
538
std::string PropertiesTree::get_value(const bec::NodeId& node, const bool is_name) const
 
539
{
 
540
  if (node.is_valid())
 
541
  {
 
542
    std::string val;
 
543
    _inspector->get_field(node, is_name ? bec::ValueInspectorBE::Name : bec::ValueInspectorBE::Value, val);
 
544
    return val;
 
545
  }
 
546
  return "";
 
547
}