Mercurial > hg > octave-thorsten
diff src/graphics.h.in @ 13281:834f904a3dcb
Add support for full asynchronous graphics toolkit running in a separate
thread. Add uicontrol and uipanel implementation.
* oct-mutex.h (octave_base_mutex::try_lock): New method.
(octave_mutex::try_lock): Likewise.
(octave_auto_lock::octave_auto_lock): New argument for
blocking/non-blocking locks.
(octave_auto_lock::ok): New method to test locking state.
(octave_auto_lock::operator bool): Likewise.
(octave_thread): New utility class.
* oct-mutex.cc (octave_base_mutex::try_lock): New method.
(octave_w32_mutex::try_lock): Implement it for Win32.
(octave_pthread_mutex::try_lock): Implement it for pthread.
(octave_thread): Implement new utility class.
* octave.cc (octave_main): Initialize octave_thread.
* genprops.awk (emit_get_string_array): New function.
(emit_declarations): Use it for string_array_property.
* graphics.h.in (base_property::set): New argument to control toolkit
notifying.
(property::set): Likewise.
(string_array_property::string_vector_value): New method.
(radio_property::do_set): Add warning about abbreviated radio values.
(base_graphics_toolkit::initialize): Returns bool.
(graphics_toolkit::initialize): Likewise.
(base_graphics_object::toolkit_flag): New member.
(base_graphics_object::base_graphics_object): Initialize it.
(base_graphics_object::valid_toolkit_object): New method.
(base_graphics_object::initialize, base_graphics_object::finalize,
base_graphics_object::update): Likewise.
(graphics_object::initialize, graphics_object::finalize,
graphics_object::update): Likewise.
(figure::properties::set_toolkit): Move implementation to source file.
(base_properties::get_boundingbox): Add parent size argument for optimization.
(figure::properties::get_boundingbox): Likewise.
(axes::properties::get_boundingbox): Likewise.
(figure::properties::map_from_boundingbox): New utility method.
(figure::properties::map_to_boundingbox): Likewise.
(axes::properties::get_fontsize_points): New utility method.
(text::properties::get_fontsize_points): Likewise.
(axes::properties::xlabel, axes::properties::ylabel, axes::properties::zlabel,
axes::properties::title): Don't notify toolkit on initialization.
(axes::initialize): New method override.
(uicontrol): New class.
(uipanel): Likewise.
(graphics_event::create_callback_event): New static method overload.
(graphics_event::create_set_event): New argument to prevent circular
behavior when property change is triggered from the toolkit.
(gh_manager::post_set): Likewise.
(gh_manager::do_post_set): Likewise.
(gh_manager::make_graphics_handle): New argument controlling toolkit notify.
(gh_manager::make_figure_handle): Likewise.
(gh_manager::do_make_graphics_handle): Likewise.
(gh_manager::do_make_figure_handle): Likewise.
(gh_manager::try_lock): New static method.
(gh_manager::execute_listener): Likewise.
(gh_manager::enable_event_processing): Likewise.
(gh_manager::do_try_lock): New method.
(gh_manager::do_execute_listener): Likewise.
(gh_manager::do_enable_event_processing): Likewise.
(gh_manager::event_processing): New member.
(gh_manager::execute_callback): Protect graphics_object access.
(gh_manager::auto_lock): Inherits from octave_autolock. Renamed from autolock.
(gh_manager::auto_lock::auto_lock): New blocking/non-blocking argument.
* graphics.cc (default_control_position, default_control_sliderstep,
default_panel_position): New utility functions.
(convert_font_size): New utility function.
(convert_position): Support 2D-only positions.
(lookup_object_name): Support uicontrol and uipanel.
(make_graphics_object_from_type): Likewise.
(root_figure::init_factory_properties): Likewise.
(property_list::set, property_list::lookup): Likewise.
(base_property::set): New argument controlling toolkit notifying.
(base_property::run_listeners): Call gh_manager::execute_listener, allowing
to set a property from another thread and run listeners synchronously with
octave.
(color_property::do_set): Add warning about abbreviated radio value.
(double_radio_property::do_set): Likewise.
(finalize_r, initialize_r, xinitialize): New utility functions.
(gh_manager::do_free): Calls graphics_object::finalize.
(base_graphics_toolkit::initialize): Returns bool.
(gnuplot_toolkit::initialize): Likewise.
(figure::properties::set_toolkit): Move implementation from header.
(figure::properties::get_boundingbox): New argument for parent size.
(axes::properties::get_boundingbox): Likewise.
(figure::properties::map_from_boundingbox): New utility method.
(figure::properties::map_to_boundingbox): Likewise.
(axes::properties::update_fontunits): Use convert_font_size.
(axes::properties::get_fontsize_points): New utility method.
(text::properties::get_fontsize_points): Likewise.
(axes::initialize): New method override to trigger initialization of
labels and title.
(uicontrol): New class.
(uipanel): Likewise.
(gh_manager::gh_manager): Initialize new event_processing member.
(gh_manager::do_make_graphics_handle): New argument controlling toolkit
notifying.
(gh_manager::do_make_figure_handle): Likewise.
(callback_event::callback): New member.
(callback_event::callback_event): Initialize it.
(callback_event::execute): Use it.
(set_event::notify_toolkit): New member.
(set_event::set_event): Initialize it.
(set_event::execute): Use it. Also allow to set read-only properties.
(graphics_event::create_callback_event): New static method overload.
(graphics_event::create_set_event): New argument controlling toolkit notifying.
(gh_manager::do_restore_gcbo): Rename autolock to auto_lock.
(gh_manager::do_post_callback, gh_manager::do_post_function): Likewise.
(Fishandle, Fset, Fget, F__get__): Likewise.
(F__go_figure__, F__calc_dimensions__, GO_BODY): Likewise.
(F__go_delete__, F__go_axes_init__, F__go_handles__, F__go_figure_handles__,
Favailable_graphics_toolkits, Faddlistener, Fdellistener, Faddproperty):
Likewise.
(get_property_from_handle, set_property_in_handle): Likewise.
(gh_manager::do_post_set): Likewise. New argument controlling toolkit
notifying.
(gh_manager::do_execute_listener): New method.
(gh_manager::do_enable_event_processing): Likewise.
(gh_manager::do_execute_callback): Check callback argument validity.
Rename autolock to auto_lock.
(gh_manager::do_process_events): Execute drawnow at the end of event
processing loop, avoiding recursivity. Maintain the input event hook
if gh_manager::event_processing is non zero.
(make_graphics_object): Postpone object's toolkit initialization at
the end of the object creation.
(F__go_figure__): Likewise.
(F__go_uicontrol__, F__go_uipanel__): New functions.
* __init_fltk__.cc (fltk_graphics_toolkit::initialise): New method.
* gl-render.h (opengl_renderer::draw): New argument to identify top-level
calls.
(opengl_renderer::draw_uipanel): New method.
(opengl_renderer::init_gl_context): Likewise.
* gl-render.cc (opengl_renderer::draw): New argument to identify top-level
calls. Skip uicontrol objects. Handle uipanel objects when top-level.
(opengl_renderer::init_gl_context): New method.
(opengl_renderer::draw_figure): Use it.
(opengl_renderer::draw_uipanel): New method.
author | Michael Goffioul <michael.goffioul@gmail.com> |
---|---|
date | Thu, 06 Oct 2011 16:44:18 +0100 (2011-10-06) |
parents | 8bb526fb3349 |
children | cbdefe0ec514 |
line wrap: on
line diff
--- a/src/graphics.h.in +++ b/src/graphics.h.in @@ -364,7 +364,8 @@ // Sets property value, notifies graphics toolkit. // If do_run is true, runs associated listeners. - bool set (const octave_value& v, bool do_run = true); + bool set (const octave_value& v, bool do_run = true, + bool do_notify_toolkit = true); virtual octave_value get (void) const { @@ -599,6 +600,8 @@ Cell cell_value (void) const {return Cell (str);} + string_vector string_vector_value (void) const { return str; } + string_array_property& operator = (const octave_value& val) { set (val); @@ -1008,6 +1011,11 @@ { if (match != current_val) { + if (s.length () != match.length ()) + warning_with_id ("Octave:abbreviated-property-match", + "%s: allowing %s to match %s value %s", + "set", s.c_str (), get_name ().c_str (), + match.c_str ()); current_val = match; return true; } @@ -1903,8 +1911,9 @@ octave_value get (void) const { return rep->get (); } - bool set (const octave_value& val) - { return rep->set (val); } + bool set (const octave_value& val, bool do_run = true, + bool do_notify_toolkit = true) + { return rep->set (val, do_run, do_notify_toolkit); } std::string values_as_string (void) const { return rep->values_as_string (); } @@ -2073,10 +2082,10 @@ // Callback function executed when the given graphics object is // created. This allows the graphics toolkit to do toolkit-specific // initializations for a newly created object. - virtual void initialize (const graphics_object&) - { gripe_invalid ("base_graphics_toolkit::initialize"); } - - void initialize (const graphics_handle&); + virtual bool initialize (const graphics_object&) + { gripe_invalid ("base_graphics_toolkit::initialize"); return false; } + + bool initialize (const graphics_handle&); // Callback function executed just prior to deleting the given // graphics object. This allows the graphics toolkit to perform @@ -2168,11 +2177,11 @@ { rep->update (h, id); } // Notifies graphics toolkit that new object was created. - void initialize (const graphics_object& go) - { rep->initialize (go); } - - void initialize (const graphics_handle& h) - { rep->initialize (h); } + bool initialize (const graphics_object& go) + { return rep->initialize (go); } + + bool initialize (const graphics_handle& h) + { return rep->initialize (h); } // Notifies graphics toolkit that object was destroyed. // This is called only for explicitly deleted object. Children are @@ -2230,6 +2239,7 @@ // --------------------------------------------------------------------- class base_graphics_object; +class graphics_object; class OCTINTERP_API base_properties { @@ -2298,7 +2308,8 @@ virtual graphics_toolkit get_toolkit (void) const; - virtual Matrix get_boundingbox (bool /*internal*/ = false) const + virtual Matrix get_boundingbox (bool /*internal*/ = false, + const Matrix& /*parent_pix_size*/ = Matrix ()) const { return Matrix (1, 4, 0.0); } virtual void update_boundingbox (void); @@ -2442,7 +2453,7 @@ public: friend class graphics_object; - base_graphics_object (void) : count (1) { } + base_graphics_object (void) : count (1), toolkit_flag (false) { } virtual ~base_graphics_object (void) { } @@ -2603,6 +2614,8 @@ virtual bool valid_object (void) const { return false; } + bool valid_toolkit_object (void) const { return toolkit_flag; } + virtual std::string type (void) const { return (valid_object () ? get_properties ().graphics_object_name () @@ -2655,9 +2668,35 @@ } protected: + virtual void initialize (const graphics_object& go) + { + if (! toolkit_flag) + toolkit_flag = get_toolkit ().initialize (go); + } + + virtual void finalize (const graphics_object& go) + { + if (toolkit_flag) + { + get_toolkit ().finalize (go); + toolkit_flag = false; + } + } + + virtual void update (const graphics_object& go, int id) + { + if (toolkit_flag) + get_toolkit ().update (go, id); + } + +protected: // A reference count. int count; + // A flag telling whether this object is a valid object + // in the backend context. + bool toolkit_flag; + // No copying! base_graphics_object (const base_graphics_object&); @@ -2853,6 +2892,12 @@ listener_mode mode = POSTSET) { rep->delete_property_listener (nm, v, mode); } + void initialize (void) { rep->initialize (*this); } + + void finalize (void) { rep->finalize (*this); } + + void update (int id) { rep->update (*this, id); } + void reset_default_properties (void) { rep->reset_default_properties (); } @@ -3025,15 +3070,7 @@ return toolkit; } - void set_toolkit (const graphics_toolkit& b) - { - if (toolkit) - toolkit.finalize (__myhandle__); - toolkit = b; - __graphics_toolkit__ = b.get_name (); - __plot_stream__ = Matrix (); - mark_modified (); - } + void set_toolkit (const graphics_toolkit& b); void set___graphics_toolkit__ (const octave_value& val) { @@ -3058,10 +3095,15 @@ } } - Matrix get_boundingbox (bool internal = false) const; + Matrix get_boundingbox (bool internal = false, + const Matrix& parent_pix_size = Matrix ()) const; void set_boundingbox (const Matrix& bb); + Matrix map_from_boundingbox (double x, double y) const; + + Matrix map_to_boundingbox (double x, double y) const; + void update_units (const caseless_str& old_units); void update_paperunits (const caseless_str& old_paperunits); @@ -3314,9 +3356,12 @@ const scaler& get_y_scaler (void) const { return sy; } const scaler& get_z_scaler (void) const { return sz; } - Matrix get_boundingbox (bool internal = false) const; + Matrix get_boundingbox (bool internal = false, + const Matrix& parent_pix_size = Matrix ()) const; Matrix get_extent (bool with_text = false, bool only_text_height=false) const; + double get_fontsize_points (double box_pix_height = 0) const; + void update_boundingbox (void) { if (units_is ("normalized")) @@ -3456,10 +3501,10 @@ radio_property zlimmode al , "{auto}|manual" radio_property climmode al , "{auto}|manual" radio_property alimmode , "{auto}|manual" - handle_property xlabel SOf , gh_manager::make_graphics_handle ("text", __myhandle__, false) - handle_property ylabel SOf , gh_manager::make_graphics_handle ("text", __myhandle__, false) - handle_property zlabel SOf , gh_manager::make_graphics_handle ("text", __myhandle__, false) - handle_property title SOf , gh_manager::make_graphics_handle ("text", __myhandle__, false) + handle_property xlabel SOf , gh_manager::make_graphics_handle ("text", __myhandle__, false, false) + handle_property ylabel SOf , gh_manager::make_graphics_handle ("text", __myhandle__, false, false) + handle_property zlabel SOf , gh_manager::make_graphics_handle ("text", __myhandle__, false, false) + handle_property title SOf , gh_manager::make_graphics_handle ("text", __myhandle__, false, false) bool_property xgrid , "off" bool_property ygrid , "off" bool_property zgrid , "off" @@ -3817,6 +3862,9 @@ void reset_default_properties (void); +protected: + void initialize (const graphics_object& go); + private: property_list default_properties; }; @@ -3902,6 +3950,8 @@ class OCTINTERP_API properties : public base_properties { public: + double get_fontsize_points (double box_pix_height = 0) const; + // See the genprops.awk script for an explanation of the // properties declarations. @@ -4561,6 +4611,162 @@ // --------------------------------------------------------------------- +class OCTINTERP_API uicontrol : public base_graphics_object +{ +public: + class OCTINTERP_API properties : public base_properties + { + public: + Matrix get_boundingbox (bool internal = false, + const Matrix& parent_pix_size = Matrix ()) const; + + double get_fontsize_points (double box_pix_height = 0) const; + + // See the genprops.awk script for an explanation of the + // properties declarations. + + BEGIN_PROPERTIES (uicontrol) + any_property __object__ , Matrix () + color_property backgroundcolor , color_values (1, 1, 1) + callback_property callback , Matrix () + array_property cdata , Matrix () + bool_property clipping , "on" + radio_property enable , "{on}|inactive|off" + array_property extent rG , Matrix (1, 4, 0.0) + radio_property fontangle u , "{normal}|italic|oblique" + string_property fontname u , OCTAVE_DEFAULT_FONTNAME + double_property fontsize u , 10 + radio_property fontunits S , "inches|centimeters|normalized|{points}|pixels" + radio_property fontweight u , "light|{normal}|demi|bold" + color_property foregroundcolor , color_values (0, 0, 0) + radio_property horizontalalignment , "{left}|center|right" + callback_property keypressfcn , Matrix () + double_property listboxtop , 1 + double_property max , 1 + double_property min , 0 + array_property position , default_control_position () + array_property sliderstep , default_control_sliderstep () + string_array_property string u , "" + radio_property style S , "{pushbutton}|togglebutton|radiobutton|checkbox|edit|text|slider|frame|listbox|popupmenu" + string_property tooltipstring , "" + radio_property units u , "normalized|inches|centimeters|points|{pixels}|characters" + row_vector_property value , Matrix (1, 1, 1.0) + radio_property verticalalignment , "top|{middle}|bottom" + END_PROPERTIES + + private: + std::string cached_units; + + protected: + void init (void) + { + cdata.add_constraint ("double"); + cdata.add_constraint (dim_vector (-1, -1, 3)); + position.add_constraint (dim_vector (1, 4)); + sliderstep.add_constraint (dim_vector (1, 2)); + cached_units = get_units (); + } + + void update_text_extent (void); + + void update_string (void) { update_text_extent (); } + void update_fontname (void) { update_text_extent (); } + void update_fontsize (void) { update_text_extent (); } + void update_fontangle (void) { update_text_extent (); } + void update_fontweight (void) { update_text_extent (); } + void update_fontunits (const caseless_str& old_units); + + void update_units (void); + + }; + +private: + properties xproperties; + +public: + uicontrol (const graphics_handle& mh, const graphics_handle& p) + : base_graphics_object (), xproperties (mh, p) + { + xproperties.override_defaults (*this); + } + + ~uicontrol (void) { xproperties.delete_children (); } + + base_properties& get_properties (void) { return xproperties; } + + const base_properties& get_properties (void) const { return xproperties; } + + bool valid_object (void) const { return true; } +}; + +// --------------------------------------------------------------------- + +class OCTINTERP_API uipanel : public base_graphics_object +{ +public: + class OCTINTERP_API properties : public base_properties + { + public: + Matrix get_boundingbox (bool internal = false, + const Matrix& parent_pix_size = Matrix ()) const; + + double get_fontsize_points (double box_pix_height = 0) const; + + // See the genprops.awk script for an explanation of the + // properties declarations. + + BEGIN_PROPERTIES (uipanel) + any_property __object__ , Matrix () + color_property backgroundcolor , color_values (1, 1, 1) + radio_property bordertype , "none|{etchedin}|etchedout|beveledin|beveledout|line" + double_property borderwidth , 1 + radio_property fontangle , "{normal}|italic|oblique" + string_property fontname , OCTAVE_DEFAULT_FONTNAME + double_property fontsize , 10 + radio_property fontunits S , "inches|centimeters|normalized|{points}|pixels" + radio_property fontweight , "light|{normal}|demi|bold" + color_property foregroundcolor , color_values (0, 0, 0) + color_property highlightcolor , color_values (1, 1, 1) + array_property position , default_panel_position () + callback_property resizefcn , Matrix () + color_property shadowcolor , color_values (0, 0, 0) + string_property title , "" + radio_property titleposition , "{lefttop}|centertop|righttop|leftbottom|centerbottom|rightbottom" + radio_property units S , "{normalized}|inches|centimeters|points|pixels|characters" + END_PROPERTIES + + protected: + void init (void) + { + position.add_constraint (dim_vector (1, 4)); + } + + void update_units (const caseless_str& old_units); + void update_fontunits (const caseless_str& old_units); + + }; + +private: + properties xproperties; + +public: + uipanel (const graphics_handle& mh, const graphics_handle& p) + : base_graphics_object (), xproperties (mh, p) + { + xproperties.override_defaults (*this); + } + + ~uipanel (void) { xproperties.delete_children (); } + + base_properties& get_properties (void) { return xproperties; } + + const base_properties& get_properties (void) const { return xproperties; } + + bool valid_object (void) const { return true; } +}; + +// --------------------------------------------------------------------- + octave_value get_property_from_handle (double handle, const std::string &property, const std::string &func); @@ -4632,14 +4838,19 @@ create_callback_event (const graphics_handle& h, const std::string& name, const octave_value& data = Matrix ()); + + static graphics_event + create_callback_event (const graphics_handle& h, + const octave_value& cb, + const octave_value& data = Matrix ()); static graphics_event create_function_event (event_fcn fcn, void *data = 0); static graphics_event - create_set_event (const graphics_handle& h, - const std::string& name, - const octave_value& value); + create_set_event (const graphics_handle& h, const std::string& name, + const octave_value& value, + bool notify_toolkit = true); private: base_graphics_event *rep; }; @@ -4698,17 +4909,21 @@ static graphics_handle make_graphics_handle (const std::string& go_name, - const graphics_handle& parent, bool do_createfcn = true) + const graphics_handle& parent, bool do_createfcn = true, + bool do_notify_toolkit = true) { return instance_ok () - ? instance->do_make_graphics_handle (go_name, parent, do_createfcn) + ? instance->do_make_graphics_handle (go_name, parent, do_createfcn, + do_notify_toolkit) : graphics_handle (); } - static graphics_handle make_figure_handle (double val) + static graphics_handle make_figure_handle (double val, + bool do_notify_toolkit = true) { return instance_ok () - ? instance->do_make_figure_handle (val) : graphics_handle (); + ? instance->do_make_figure_handle (val, do_notify_toolkit) + : graphics_handle (); } static void push_figure (const graphics_handle& h) @@ -4740,30 +4955,50 @@ instance->do_lock (); } + static bool try_lock (void) + { + if (instance_ok ()) + return instance->do_try_lock (); + else + return false; + } + static void unlock (void) { if (instance_ok ()) instance->do_unlock (); } - + static Matrix figure_handle_list (void) { return instance_ok () ? instance->do_figure_handle_list () : Matrix (); } + static void execute_listener (const graphics_handle& h, + const octave_value& l) + { + if (instance_ok ()) + instance->do_execute_listener (h, l); + } + static void execute_callback (const graphics_handle& h, const std::string& name, const octave_value& data = Matrix ()) { - graphics_object go = get_object (h); - - if (go.valid_object ()) + octave_value cb; + + if (true) { - octave_value cb = go.get (name); - - if (! error_state) - execute_callback (h, cb, data); + gh_manager::auto_lock lock; + + graphics_object go = get_object (h); + + if (go.valid_object ()) + cb = go.get (name); } + + if (! error_state) + execute_callback (h, cb, data); } static void execute_callback (const graphics_handle& h, @@ -4781,19 +5016,18 @@ if (instance_ok ()) instance->do_post_callback (h, name, data); } - + static void post_function (graphics_event::event_fcn fcn, void* data = 0) { if (instance_ok ()) instance->do_post_function (fcn, data); } - static void post_set (const graphics_handle& h, - const std::string& name, - const octave_value& value) + static void post_set (const graphics_handle& h, const std::string& name, + const octave_value& value, bool notify_toolkit = true) { if (instance_ok ()) - instance->do_post_set (h, name, value); + instance->do_post_set (h, name, value, notify_toolkit); } static int process_events (void) @@ -4806,6 +5040,12 @@ return (instance_ok () ? instance->do_process_events (true) : 0); } + static void enable_event_processing (bool enable = true) + { + if (instance_ok ()) + instance->do_enable_event_processing (enable); + } + static bool is_handle_visible (const graphics_handle& h) { bool retval = false; @@ -4819,18 +5059,21 @@ } public: - class autolock + class auto_lock : public octave_autolock { public: - autolock (void) { lock (); } - - ~autolock (void) { unlock (); } + auto_lock (bool wait = true) + : octave_autolock (instance_ok () + ? instance->graphics_lock + : octave_mutex (), + wait) + { } private: // No copying! - autolock (const autolock&); - autolock& operator = (const autolock&); + auto_lock (const auto_lock&); + auto_lock& operator = (const auto_lock&); }; private: @@ -4868,6 +5111,9 @@ // The stack of callback objects. std::list<graphics_object> callback_objects; + // A flag telling whether event processing must be constantly on. + int event_processing; + graphics_handle get_handle (const std::string& go_name); void do_free (const graphics_handle& h); @@ -4887,9 +5133,10 @@ } graphics_handle do_make_graphics_handle (const std::string& go_name, - const graphics_handle& p, bool do_createfcn); - - graphics_handle do_make_figure_handle (double val); + const graphics_handle& p, bool do_createfcn, + bool do_notify_toolkit); + + graphics_handle do_make_figure_handle (double val, bool do_notify_toolkit); Matrix do_handle_list (void) { @@ -4928,18 +5175,22 @@ void do_lock (void) { graphics_lock.lock (); } + bool do_try_lock (void) { return graphics_lock.try_lock (); } + void do_unlock (void) { graphics_lock.unlock (); } + void do_execute_listener (const graphics_handle& h, const octave_value& l); + void do_execute_callback (const graphics_handle& h, const octave_value& cb, const octave_value& data); void do_post_callback (const graphics_handle& h, const std::string name, const octave_value& data); - + void do_post_function (graphics_event::event_fcn fcn, void* fcn_data); void do_post_set (const graphics_handle& h, const std::string name, - const octave_value& value); + const octave_value& value, bool notify_toolkit = true); int do_process_events (bool force = false); @@ -4952,6 +5203,8 @@ void do_restore_gcbo (void); void do_post_event (const graphics_event& e); + + void do_enable_event_processing (bool enable = true); }; void get_children_limits (double& min_val, double& max_val,