1 /* === S I N F G =========================================================== */
2 /*! \file cellrenderer_value.cpp
3 ** \brief Template File
5 ** $Id: cellrenderer_value.cpp,v 1.1.1.1 2005/01/07 03:34:36 darco Exp $
8 ** Copyright (c) 2002 Robert B. Quattlebaum Jr.
10 ** This software and associated documentation
11 ** are CONFIDENTIAL and PROPRIETARY property of
12 ** the above-mentioned copyright holder.
14 ** You may not copy, print, publish, or in any
15 ** other way distribute this software without
16 ** a prior written agreement with
17 ** the copyright holder.
20 /* ========================================================================= */
22 /* === H E A D E R S ======================================================= */
31 #include <gtkmm/label.h>
32 #include <ETL/stringf>
33 #include <gtkmm/celleditable.h>
34 #include <gtkmm/editable.h>
35 #include <gtkmm/entry.h>
36 #include <gtkmm/eventbox.h>
37 #include <gtk/gtkentry.h> /* see XXX below */
40 #include "widget_value.h"
41 #include "widget_vector.h"
42 #include "widget_filename.h"
43 #include "widget_enum.h"
44 #include "widget_color.h"
45 #include "widget_canvaschooser.h"
46 #include "widget_time.h"
48 #include "cellrenderer_gradient.h"
49 #include "cellrenderer_value.h"
51 #include "widget_gradient.h"
52 #include "dialog_gradient.h"
53 #include "dialog_color.h"
54 #include <gtkmm/textview.h>
58 using namespace sinfg;
61 using namespace studio;
63 /* === M A C R O S ========================================================= */
67 #define use_colorspace_gamma() App::use_colorspace_gamma
68 #define colorspace_gamma() (2.2f)
69 #define gamma_in(x) pow((float)x,1.0f/colorspace_gamma())
70 #define gamma_out(x) pow((float)x,colorspace_gamma())
72 /* === G L O B A L S ======================================================= */
74 class studio::ValueBase_Entry : public Gtk::EventBox, public Gtk::CellEditable
77 Widget_ValueBase *valuewidget;
78 bool edit_done_called;
82 Glib::ObjectBase (typeid(ValueBase_Entry)),
87 edit_done_called=false;
89 Gtk::HBox *const hbox = new Gtk::HBox(false, 0);
90 add(*Gtk::manage(hbox));
92 Gtk::Entry *entry_ = new Gtk::Entry();
93 entry_->set_text("bleh");
94 hbox->pack_start(*Gtk::manage(entry_), Gtk::PACK_EXPAND_WIDGET);
95 entry_->set_has_frame(false);
96 entry_->gobj()->is_cell_renderer = true; // XXX
99 valuewidget=manage(new class Widget_ValueBase());
100 valuewidget->inside_cellrenderer();
104 //set_flags(Gtk::CAN_FOCUS);
105 //set_events(Gdk::KEY_PRESS_MASK | Gdk::KEY_RELEASE_MASK);
108 set_events(//(Gdk::ALL_EVENTS_MASK)
109 ~( Gdk::EXPOSURE_MASK
110 | Gdk::ENTER_NOTIFY_MASK
111 | Gdk::LEAVE_NOTIFY_MASK
112 | Gdk::FOCUS_CHANGE_MASK
113 | Gdk::STRUCTURE_MASK
114 | Gdk::PROPERTY_CHANGE_MASK
115 | Gdk::VISIBILITY_NOTIFY_MASK
116 | Gdk::PROXIMITY_IN_MASK
117 | Gdk::PROXIMITY_OUT_MASK
118 | Gdk::SUBSTRUCTURE_MASK
122 //signal_editing_done().connect(sigc::mem_fun(*this, &studio::ValueBase_Entry::hide));
123 //signal_remove_widget().connect(sigc::mem_fun(*this, &studio::ValueBase_Entry::hide));
127 //signal_show().connect(sigc::mem_fun(*this, &ValueBase_Entry::grab_focus));
134 void on_editing_done()
137 if(parent)parent->grab_focus();
138 if(!edit_done_called)
140 edit_done_called=true;
141 Gtk::CellEditable::on_editing_done();
145 sinfg::error("on_editing_done(): Called twice!");
148 void set_parent(Gtk::Widget*x) { parent=x; }
149 void on_remove_widget()
152 edit_done_called=true;
153 if(parent)parent->grab_focus();
154 Gtk::CellEditable::on_remove_widget();
156 void start_editing_vfunc(GdkEvent *event)
158 valuewidget->signal_activate().connect(sigc::mem_fun(*this, &studio::ValueBase_Entry::editing_done));
160 //valuewidget->grab_focus();
161 //get_window()->set_focus(*valuewidget);
163 bool on_event(GdkEvent *event)
165 if(event->any.type==GDK_BUTTON_PRESS ||
166 event->any.type==GDK_2BUTTON_PRESS ||
167 event->any.type==GDK_KEY_PRESS ||
168 event->any.type==GDK_KEY_RELEASE ||
169 event->any.type==GDK_SCROLL ||
170 event->any.type==GDK_3BUTTON_PRESS)
172 return Gtk::EventBox::on_event(event);
176 Gtk::EventBox::on_grab_focus();
178 valuewidget->grab_focus();
180 void set_path(const Glib::ustring &p)
184 void set_value(const sinfg::ValueBase &data)
187 valuewidget->set_value(data);
188 //valuewidget->grab_focus();
190 void set_canvas(const etl::handle<sinfg::Canvas> &data)
194 valuewidget->set_canvas(data);
196 void set_param_desc(const sinfg::ParamDesc &data)
199 valuewidget->set_param_desc(data);
202 const sinfg::ValueBase &get_value()
205 return valuewidget->get_value();
206 return sinfg::ValueBase();
208 const Glib::ustring &get_path()
215 /* === P R O C E D U R E S ================================================= */
217 bool get_paragraph(sinfg::String& text)
220 _("Paragraph"), // Title
222 true // use_separator
224 Gtk::Label label(_("Enter Paragraph Text Here:"));
226 dialog.get_vbox()->pack_start(label);
229 Glib::RefPtr<Gtk::TextBuffer> text_buffer(Gtk::TextBuffer::create());
230 text_buffer->set_text(text);
232 Gtk::TextView text_view(text_buffer);
234 dialog.get_vbox()->pack_start(text_view);
238 entry.set_text(text);
240 entry.set_activates_default(true);
241 dialog.get_vbox()->pack_start(entry);
244 dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
245 dialog.add_button(Gtk::StockID("gtk-cancel"),Gtk::RESPONSE_CANCEL);
246 dialog.set_default_response(Gtk::RESPONSE_OK);
248 //text_entry.signal_activate().connect(sigc::bind(sigc::mem_fun(dialog,&Gtk::Dialog::response),Gtk::RESPONSE_OK));
252 if(dialog.run()!=Gtk::RESPONSE_OK)
255 text=text_buffer->get_text();
260 /* === M E T H O D S ======================================================= */
262 CellRenderer_ValueBase::CellRenderer_ValueBase():
263 Glib::ObjectBase (typeid(CellRenderer_ValueBase)),
264 Gtk::CellRendererText (),
265 property_value_ (*this,"value",sinfg::ValueBase()),
266 property_canvas_(*this,"canvas",etl::handle<sinfg::Canvas>()),
267 property_param_desc_(*this,"param_desc",sinfg::ParamDesc())
269 CellRendererText::signal_edited().connect(sigc::mem_fun(*this,&CellRenderer_ValueBase::string_edited_));
270 value_entry=new ValueBase_Entry();
273 Pango::AttrList attr_list;
275 Pango::AttrInt pango_size(Pango::Attribute::create_attr_size(Pango::SCALE*8));
276 pango_size.set_start_index(0);
277 pango_size.set_end_index(64);
278 attr_list.change(pango_size);
280 property_attributes()=attr_list;
282 property_foreground()=Glib::ustring("#7f7f7f");
283 property_inconsistant()=false;
286 CellRenderer_ValueBase::~CellRenderer_ValueBase()
288 // sinfg::info("CellRenderer_ValueBase::~CellRenderer_ValueBase(): deleted");
292 CellRenderer_ValueBase::string_edited_(const Glib::ustring&path,const Glib::ustring&str)
294 ValueBase old_value=property_value_.get_value();
297 if(old_value.get_type()==ValueBase::TYPE_TIME)
299 value=ValueBase(Time((String)str,get_canvas()->rend_desc().get_frame_rate()));
302 value=ValueBase((String)str);
305 signal_edited_(path,value);
309 CellRenderer_ValueBase::render_vfunc(
310 const Glib::RefPtr<Gdk::Drawable>& window,
312 const Gdk::Rectangle& background_area,
313 const Gdk::Rectangle& ca,
314 const Gdk::Rectangle& expose_area,
315 Gtk::CellRendererState flags)
319 // const unsigned int cell_xpad = property_xpad();
320 // const unsigned int cell_ypad = property_ypad();
322 //int x_offset = 0, y_offset = 0;
323 // int width = ca.get_width();
324 int height = ca.get_height();
325 // get_size(widget, ca, x_offset, y_offset, width, height);
327 // width -= cell_xpad * 2;
328 // height -= cell_ypad * 2;
330 // if(width <= 0 || height <= 0)
333 Gtk::StateType state = Gtk::STATE_INSENSITIVE;
334 if(property_editable())
335 state = Gtk::STATE_NORMAL;
336 if((flags & Gtk::CELL_RENDERER_SELECTED) != 0)
337 state = (widget.has_focus()) ? Gtk::STATE_SELECTED : Gtk::STATE_ACTIVE;
339 ValueBase data=property_value_.get_value();
341 switch(data.get_type())
343 case ValueBase::TYPE_REAL:
344 if(((sinfg::ParamDesc)property_param_desc_).get_is_distance())
346 Distance x(data.get(Real()),Distance::SYSTEM_UNITS);
347 x.convert(App::distance_system,get_canvas()->rend_desc());
348 property_text()=(Glib::ustring)x.get_string(6).c_str();
351 property_text()=(Glib::ustring)strprintf("%.6f",data.get(Real()));
353 case ValueBase::TYPE_TIME:
354 property_text()=(Glib::ustring)data.get(Time()).get_string(get_canvas()->rend_desc().get_frame_rate(),App::get_time_format());
356 case ValueBase::TYPE_ANGLE:
357 property_text()=(Glib::ustring)strprintf("%.2f DEG",(Real)Angle::deg(data.get(Angle())).get());
359 case ValueBase::TYPE_INTEGER:
360 if(((sinfg::ParamDesc)property_param_desc_).get_hint()!="enum")
362 property_text()=(Glib::ustring)strprintf("%i",data.get(int()));
366 property_text()=(Glib::ustring)strprintf("(%i)",data.get(int()));
367 std::list<sinfg::ParamDesc::EnumData> enum_list=((sinfg::ParamDesc)property_param_desc_).get_enum_list();
368 std::list<sinfg::ParamDesc::EnumData>::iterator iter;
370 for(iter=enum_list.begin();iter!=enum_list.end();iter++)
371 if(iter->value==data.get(int()))
373 property_text()=(Glib::ustring)iter->local_name;
379 case ValueBase::TYPE_VECTOR:
381 Vector vector=data.get(Vector());
382 Distance x(vector[0],Distance::SYSTEM_UNITS),y(vector[1],Distance::SYSTEM_UNITS);
383 x.convert(App::distance_system,get_canvas()->rend_desc());
384 y.convert(App::distance_system,get_canvas()->rend_desc());
385 property_text()=static_cast<Glib::ustring>(strprintf("%s,%s",x.get_string(6).c_str(),y.get_string(6).c_str()));
389 case ValueBase::TYPE_STRING:
391 if(data.get_type()==ValueBase::TYPE_STRING)
393 if(!data.get(sinfg::String()).empty())
394 property_text()=static_cast<Glib::ustring>(data.get(sinfg::String()));
396 property_text()=Glib::ustring("<empty>");
399 case ValueBase::TYPE_CANVAS:
400 if(data.get(etl::handle<sinfg::Canvas>()))
402 if(data.get(etl::handle<sinfg::Canvas>())->is_inline())
403 property_text()="<Inline Canvas>";
405 property_text()=(Glib::ustring)data.get(etl::handle<sinfg::Canvas>())->get_id();
408 property_text()="<No Image Selected>";
410 case ValueBase::TYPE_COLOR:
412 render_color_to_window(window,ca,data.get(Color()));
416 case ValueBase::TYPE_BOOL:
418 widget.get_style()->paint_check(
419 Glib::RefPtr<Gdk::Window>::cast_static(window), state,
420 data.get(bool())?Gtk::SHADOW_IN:Gtk::SHADOW_OUT,
421 ca, widget, "cellcheck",
422 ca.get_x()/* + x_offset + cell_xpad*/,
423 ca.get_y()/* + y_offset + cell_ypad*/,
428 case ValueBase::TYPE_NIL:
429 //property_text()=(Glib::ustring)" ";
432 case ValueBase::TYPE_SEGMENT:
433 property_text()=(Glib::ustring)_("Segment");
435 case ValueBase::TYPE_GRADIENT:
436 render_gradient_to_window(window,ca,data.get(Gradient()));
439 case ValueBase::TYPE_LIST:
440 property_text()=(Glib::ustring)_("List");
442 case ValueBase::TYPE_BLINEPOINT:
443 property_text()=(Glib::ustring)_("BLine Point");
446 property_text()=static_cast<Glib::ustring>(_("UNKNOWN"));
449 CellRendererText::render_vfunc(window,widget,background_area,ca,expose_area,flags);
455 CellRenderer_ValueBase::activate_vfunc( GdkEvent* event,
457 const Glib::ustring& path,
458 const Gdk::Rectangle& background_area,
459 const Gdk::Rectangle& cell_area,
460 Gtk::CellRendererState flags)
462 ValueBase data=(ValueBase)property_value_.get_value();
466 case ValueBase::TYPE_BOOL:
467 if(property_editable())
468 signal_edited_(path,ValueBase(!data.get(bool())));
470 case ValueBase::TYPE_STRING:
471 return CellRendererText::activate_vfunc(event,widget,path,background_area,cell_area,flags);
478 CellRenderer_ValueBase::gradient_edited(sinfg::Gradient gradient, Glib::ustring path)
480 ValueBase old_value(property_value_.get_value());
481 ValueBase value(gradient);
483 signal_edited_(path,value);
487 CellRenderer_ValueBase::color_edited(sinfg::Color color, Glib::ustring path)
489 ValueBase old_value(property_value_.get_value());
490 ValueBase value(color);
492 signal_edited_(path,value);
496 CellRenderer_ValueBase::start_editing_vfunc(
499 const Glib::ustring& path,
500 const Gdk::Rectangle& background_area,
501 const Gdk::Rectangle& cell_area,
502 Gtk::CellRendererState flags)
504 // If we aren't editable, then there is nothing to do
505 if(!property_editable())
508 ValueBase data=property_value_.get_value();
510 switch(data.get_type())
512 case ValueBase::TYPE_BOOL:
513 signal_edited_(path,ValueBase(!data.get(bool())));
515 //case ValueBase::TYPE_TIME:
516 // property_text()=(Glib::ustring)data.get(Time()).get_string(get_canvas()->rend_desc().get_frame_rate(),App::get_time_format()|Time::FORMAT_FULL);
517 // return CellRendererText::start_editing_vfunc(event,widget,path,background_area,cell_area,flags);
519 case ValueBase::TYPE_GRADIENT:
520 App::dialog_gradient->reset();
521 App::dialog_gradient->set_gradient(data.get(Gradient()));
522 App::dialog_gradient->signal_edited().connect(
524 sigc::mem_fun(*this,&studio::CellRenderer_ValueBase::gradient_edited),
528 App::dialog_gradient->present();
532 case ValueBase::TYPE_COLOR:
533 App::dialog_color->reset();
534 App::dialog_color->set_color(data.get(Color()));
535 App::dialog_color->signal_edited().connect(
537 sigc::mem_fun(*this,&studio::CellRenderer_ValueBase::color_edited),
541 App::dialog_color->present();
544 case ValueBase::TYPE_STRING:
545 if(get_param_desc().get_hint()=="paragraph")
547 sinfg::String string;
548 string=data.get(string);
549 if(get_paragraph(string))
551 signal_edited_(path,ValueBase(string));
555 if(get_param_desc().get_hint()!="filename")
556 return CellRendererText::start_editing_vfunc(event,widget,path,background_area,cell_area,flags);
559 assert(get_canvas());
560 //delete value_entry;
561 value_entry=manage(new ValueBase_Entry());
562 value_entry->set_path(path);
563 value_entry->set_canvas(get_canvas());
564 value_entry->set_param_desc(get_param_desc());
565 value_entry->set_value(data);
566 value_entry->set_parent(&widget);
567 value_entry->signal_editing_done().connect(sigc::mem_fun(*this, &CellRenderer_ValueBase::on_value_editing_done));
575 CellRenderer_ValueBase::on_value_editing_done()
579 ValueBase old_value(property_value_.get_value());
580 ValueBase value(value_entry->get_value());
583 signal_edited_(value_entry->get_path(),value);
585 //delete value_entry;