Mercurial > hg > octave-lojdl
changeset 11162:a981e2f56ec1
Don't plot patch outlines with the gnuplot backend if the marker property is set to none. Fixes contourf(peaks(),'edgecolor','none')
author | David Bateman <dbateman@free.fr> |
---|---|
date | Fri, 29 Oct 2010 00:25:04 +0200 |
parents | 2e32236eaa90 |
children | 31e7e9f94850 |
files | scripts/ChangeLog scripts/plot/__go_draw_axes__.m scripts/plot/private/__contour__.m src/gl-render.cc src/graphics.cc src/graphics.h.in |
diffstat | 6 files changed, 747 insertions(+), 207 deletions(-) [+] |
line wrap: on
line diff
--- a/scripts/ChangeLog +++ b/scripts/ChangeLog @@ -1,3 +1,8 @@ +2010-10-27 David Bateman <dbateman@free.fr> + + * plot/__go_draw_axes__.m: Don't attempt to plot patch outlines if + the marker property is set to none. + 2010-10-28 Ben Abbott <bpabbott@mac.com> * plot/daspect.m, plot/pbaspect.m: Add demos setting both data and
--- a/scripts/plot/__go_draw_axes__.m +++ b/scripts/plot/__go_draw_axes__.m @@ -719,8 +719,9 @@ ## patch outline if (!(strncmp (obj.edgecolor, "none", 4) - && strncmp (obj.markeredgecolor, "none", 4) - && strncmp (obj.markerfacecolor, "none", 4))) + && (strncmp (obj.marker, "none", 4) + || (strncmp (obj.markeredgecolor, "none", 4) + && strncmp (obj.markerfacecolor, "none", 4))))) data_idx++; is_image_data(data_idx) = false;
--- a/scripts/plot/private/__contour__.m +++ b/scripts/plot/private/__contour__.m @@ -143,10 +143,10 @@ ## allow the use of contourgroups with the contour3, meshc and surfc ## functions. if (isnumeric (zlevel)) - addproperty ("zlevelmode", hg, "radio", "{none}|auto|manual", "manual") + addproperty ("zlevelmode", hg, "radio", "{none}|auto|manual", "manual"); addproperty ("zlevel", hg, "data", zlevel); else - addproperty ("zlevelmode", hg, "radio", "{none}|auto|manual", zlevel) + addproperty ("zlevelmode", hg, "radio", "{none}|auto|manual", zlevel); if (ischar (zlevel) && strcmpi (zlevel, "manual")) z = varargin{3}; z = 2 * (min (z(:)) - max (z(:))); @@ -211,6 +211,8 @@ add_patch_children (hg); + axis("tight"); + if (!isempty (opts)) set (hg, opts{:}); endif @@ -220,12 +222,13 @@ c = get (hg, "contourmatrix"); lev = get (hg, "levellist"); fill = get (hg, "fill"); - z = get (hg, "zlevel"); + zlev = get (hg, "zlevel"); zmode = get (hg, "zlevelmode"); lc = get (hg, "linecolor"); lw = get (hg, "linewidth"); ls = get (hg, "linestyle"); filled = get (hg, "fill"); + ca = gca (); if (strcmpi (lc, "auto")) lc = "flat"; @@ -243,11 +246,7 @@ cont_lev(ncont) = c(1, i1); cont_len(ncont) = c(2, i1); cont_idx(ncont) = i1+1; - ii = i1+1:i1+cont_len(ncont); - cur_cont = c(:, ii); - startidx = ii(1); - stopidx = ii(end); cont_area(ncont) = polyarea (c(1, ii), c(2, ii)); i1 += c(2, i1) + 1; endwhile @@ -320,17 +319,19 @@ else ## Special case unclosed contours endif - h = [h; patch(ctmp(1, :), ctmp(2, :), cont_lev(idx), "edgecolor", lc, - "linestyle", ls, "linewidth", lw, "parent", hg)]; + h = [h; __go_patch__(ca, "xdata", ctmp(1, :)(:), "ydata", ctmp(2, :)(:), + "vertices", ctmp.', "faces", 1:(cont_len(idx)-1), + "facevertexcdata", cont_lev(idx), + "facecolor", "flat", "cdata", cont_lev(idx), + "edgecolor", lc, "linestyle", ls, + "linewidth", lw, "parent", hg)]; endfor if (min (lev) == max (lev)) - set (gca (), "clim", [min(lev)-1, max(lev)+1]); + set (ca, "clim", [min(lev)-1, max(lev)+1], "layer", "top"); else - set (gca(), "clim", [min(lev), max(lev)]); + set (ca, "clim", [min(lev), max(lev)], "layer", "top"); endif - - set (gca (), "layer", "top"); else ## Decode contourc output format. i1 = 1; @@ -340,28 +341,40 @@ clen = c(2,i1); if (all (c(:,i1+1) == c(:,i1+clen))) - p = c(:, i1+1:i1+clen-1); + p = c(:, i1+1:i1+clen-1).'; else - p = [c(:, i1+1:i1+clen), NaN(2, 1)]; + p = [c(:, i1+1:i1+clen), NaN(2, 1)].'; endif switch (zmode) case "none" - h = [h; patch(p(1,:), p(2,:), "facecolor", "none", - "edgecolor", lc, "linestyle", ls, "linewidth", lw, - "cdata", clev, "parent", hg)]; + h = [h; __go_patch__(ca, "xdata", p(:,1), "ydata", p(:,2), + "zdata", [], "facecolor", "none", + "vertices", p, "faces", 1:rows(p), + "facevertexcdata", clev, + "edgecolor", lc, "linestyle", ls, + "linewidth", lw, + "cdata", clev, "parent", hg)]; case "auto" - h = [h; patch(p(1,:), p(2,:), clev * ones (1, columns (p)), - "facecolor", "none", "edgecolor", lc, - "linestyle", ls, "linewidth", lw, "cdata", clev, - "parent", hg)]; + h = [h; __go_patch__(ca, "xdata", p(:,1), "ydata", p(:,2), + "zdata", clev * ones(rows(p),1), + "vertices", [p, clev * ones(rows(p),1)], + "faces", 1:rows(p), + "facevertexcdata", clev, + "facecolor", "none", "edgecolor", lc, + "linestyle", ls, "linewidth", lw, + "cdata", clev, "parent", hg)]; otherwise - h = [h; patch(p(1,:), p(2,:), z * ones (1, columns (p)), - "facecolor", "none", "edgecolor", lc, - "linestyle", ls, "linewidth", lw, "cdata", clev, - "parent", hg)]; + h = [h; __go_patch__(ca, "xdata", p(:,1), "ydata", p(:,2), + "zdata", zlev * ones (rows(p), 1), + "vertices", [p, zlev * ones(rows(p),1)], + "faces", 1:rows(p), + "facevertexcdata", clev, + "facecolor", "none", "edgecolor", lc, + "linestyle", ls, "linewidth", lw, + "cdata", clev, "parent", hg)]; endswitch - i1 += clen+1; + i1 += clen + 1; endwhile endif
--- a/src/gl-render.cc +++ b/src/gl-render.cc @@ -2578,6 +2578,7 @@ set_linestyle (props.get_linestyle (), false); set_linewidth (props.get_linewidth ()); + // FIXME: use __index__ property from patch object; should we // offset patch contour as well? patch_tesselator tess (this, ec_mode, el_mode); @@ -2585,20 +2586,47 @@ for (int i = 0; i < nf; i++) { if (clip_f(i)) - continue; - - tess.begin_polygon (false); - tess.begin_contour (); - - for (int j = 0; j < count_f(i); j++) { - vertex_data::vertex_data_rep *vv = vdata[i+j*fr].get_rep (); - - tess.add_vertex (vv->coords.fortran_vec (), vv); + // This is an unclosed contour. Draw it as a line + bool flag = false; + + for (int j = 0; j < count_f(i); j++) + { + if (! clip(int (f(i,j) - 1))) + { + vertex_data::vertex_data_rep *vv = vdata[i+j*fr].get_rep (); + const Matrix m = vv->coords; + if (! flag) + { + flag = true; + glBegin (GL_LINE_STRIP); + } + glVertex3d (m(0), m(1), m(2)); + } + else if (flag) + { + flag = false; + glEnd (); + } + } + + if (flag) + glEnd (); } - - tess.end_contour (); - tess.end_polygon (); + else + { + tess.begin_polygon (false); + tess.begin_contour (); + + for (int j = 0; j < count_f(i); j++) + { + vertex_data::vertex_data_rep *vv = vdata[i+j*fr].get_rep (); + tess.add_vertex (vv->coords.fortran_vec (), vv); + } + + tess.end_contour (); + tess.end_polygon (); + } } set_linestyle ("-");
--- a/src/graphics.cc +++ b/src/graphics.cc @@ -688,7 +688,8 @@ { double e = double (data[i]); - if (! (xisinf (e) || xisnan (e))) + // Don't need to test for NaN here as NaN>x and NaN<x is always false + if (! xisinf (e)) { if (e < emin) emin = e; @@ -1206,6 +1207,62 @@ return false; } +Matrix +children_property::do_get_children (bool return_hidden) const +{ + Matrix retval (children_list.size (), 1); + octave_idx_type k = 0; + + graphics_object go = gh_manager::get_object (0); + + root_figure::properties& props = + dynamic_cast<root_figure::properties&> (go.get_properties ()); + + if (! props.is_showhiddenhandles ()) + { + for (const_children_list_iterator p = children_list.begin (); + p != children_list.end (); p++) + { + graphics_handle kid = *p; + + if (gh_manager::is_handle_visible (kid)) + { + if (! return_hidden) + retval(k++) = *p; + } + else if (return_hidden) + retval(k++) = *p; + } + + retval.resize (k, 1); + } + else + { + for (const_children_list_iterator p = children_list.begin (); + p != children_list.end (); p++) + retval(k++) = *p; + } + + return retval; +} + +void +children_property::do_delete_children (bool clear) +{ + for (children_list_iterator p = children_list.begin (); + p != children_list.end (); p++) + { + graphics_object go = gh_manager::get_object (*p); + + if (go.valid_object ()) + gh_manager::free (*p); + + } + + if (clear) + children_list.clear (); +} + bool callback_property::validate (const octave_value& v) const { @@ -1883,7 +1940,6 @@ } } - static octave_value xget (const graphics_handle& h, const caseless_str& name) { @@ -1952,7 +2008,6 @@ adopt (const graphics_handle& p, const graphics_handle& h) { graphics_object parent_obj = gh_manager::get_object (p); - parent_obj.adopt (h); } @@ -2147,34 +2202,6 @@ } void -base_properties::remove_child (const graphics_handle& h) -{ - octave_idx_type k = -1; - octave_idx_type n = children.numel (); - for (octave_idx_type i = 0; i < n; i++) - { - if (h.value () == children(i)) - { - k = i; - break; - } - } - - if (k >= 0) - { - Matrix new_kids (n-1, 1); - octave_idx_type j = 0; - for (octave_idx_type i = 0; i < n; i++) - { - if (i != k) - new_kids(j++) = children(i); - } - children = new_kids; - mark_modified (); - } -} - -void base_properties::set_parent (const octave_value& val) { double tmp = val.double_value (); @@ -2203,45 +2230,6 @@ } void -base_properties::set_children (const octave_value& val) -{ - const Matrix new_kids = val.matrix_value (); - - octave_idx_type nel = new_kids.numel (); - - const Matrix new_kids_column = new_kids.reshape (dim_vector (nel, 1)); - - bool ok = true; - - if (! error_state) - { - const Matrix visible_kids = get_children (); - - if (visible_kids.numel () == new_kids.numel ()) - { - Matrix t1 = visible_kids.sort (); - Matrix t2 = new_kids_column.sort (); - - if (t1 != t2) - ok = false; - } - else - ok = false; - - if (! ok) - error ("set: new children must be a permutation of existing children"); - } - else - { - ok = false; - error ("set: expecting children to be array of graphics handles"); - } - - if (ok) - children = new_kids_column.stack (get_hidden_children ()); -} - -void base_properties::mark_modified (void) { __modified__ = "on"; @@ -2269,19 +2257,13 @@ } void -base_properties::delete_children (void) -{ - octave_idx_type n = children.numel (); - - // A callback function might have already deleted the child, - // so check before deleting - for (octave_idx_type i = 0; i < n; i++) - { - graphics_object go = gh_manager::get_object (children(i)); - - if (go.valid_object ()) - gh_manager::free (children(i)); - } +base_properties::update_axis_limits (const std::string& axis_type, + const graphics_handle& h) const +{ + graphics_object obj = gh_manager::get_object (__myhandle__); + + if (obj) + obj.update_axis_limits (axis_type, h); } graphics_backend @@ -2470,6 +2452,21 @@ } void +base_graphics_object::update_axis_limits (const std::string& axis_type, + const graphics_handle& h) +{ + if (valid_object ()) + { + graphics_object parent_obj = gh_manager::get_object (get_parent ()); + + if (parent_obj) + parent_obj.update_axis_limits (axis_type, h); + } + else + error ("base_graphics_object::update_axis_limits: invalid graphics object"); +} + +void base_graphics_object::remove_all_listeners (void) { octave_map m = get (true).map_value (); @@ -2728,9 +2725,11 @@ { graphics_handle new_currentaxes; - for (octave_idx_type i = 0; i < children.numel (); i++) + Matrix kids = get_children (); + + for (octave_idx_type i = 0; i < kids.numel (); i++) { - graphics_handle kid = children(i); + graphics_handle kid = kids(i); graphics_object go = gh_manager::get_object (kid); @@ -3418,9 +3417,7 @@ activepositionproperty = "outerposition"; } - delete_children (); - - children = Matrix (); + delete_children (true); xlabel = gh_manager::make_graphics_handle ("text", __myhandle__, false); ylabel = gh_manager::make_graphics_handle ("text", __myhandle__, false); @@ -3504,54 +3501,6 @@ base_properties::remove_child (h); } -Matrix -base_properties::get_children_internal (bool return_hidden) const -{ - Matrix retval = children; - - graphics_object go = gh_manager::get_object (0); - - root_figure::properties& props = - dynamic_cast<root_figure::properties&> (go.get_properties ()); - - if (! props.is_showhiddenhandles ()) - { - octave_idx_type k = 0; - - for (octave_idx_type i = 0; i < children.numel (); i++) - { - graphics_handle kid = children (i); - - if (gh_manager::is_handle_visible (kid)) - { - if (! return_hidden) - retval(k++) = children(i); - } - else - { - if (return_hidden) - retval(k++) = children(i); - } - } - - retval.resize (k, 1); - } - - return retval; -} - -Matrix -base_properties::get_children (void) const -{ - return get_children_internal (false); -} - -Matrix -base_properties::get_hidden_children (void) const -{ - return get_children_internal (true); -} - inline Matrix xform_matrix (void) { @@ -4446,6 +4395,198 @@ static bool updating_axis_limits = false; void +axes::update_axis_limits (const std::string& axis_type, + const graphics_handle& h) +{ + if (updating_axis_limits) + return; + + Matrix kids = Matrix (1, 1, h.value ()); + + double min_val = octave_Inf; + double max_val = -octave_Inf; + double min_pos = octave_Inf; + + char update_type = 0; + + Matrix limits; + double val; + +#define FIX_LIMITS \ + if (limits.numel() == 3) \ + { \ + val = limits(0); \ + if (! (xisinf (val) || xisnan (val))) \ + min_val = val; \ + val = limits(1); \ + if (! (xisinf (val) || xisnan (val))) \ + max_val = val; \ + val = limits(2); \ + if (! (xisinf (val) || xisnan (val))) \ + min_pos = val; \ + } \ + else \ + { \ + limits.resize(3, 1); \ + limits(0) = min_val; \ + limits(1) = max_val; \ + limits(2) = min_pos; \ + } + + if (axis_type == "xdata" || axis_type == "xscale" + || axis_type == "xlimmode" || axis_type == "xliminclude" + || axis_type == "xlim") + { + if (xproperties.xlimmode_is ("auto")) + { + limits = xproperties.get_xlim ().matrix_value (); + FIX_LIMITS ; + + get_children_limits (min_val, max_val, min_pos, kids, 'x'); + + limits = xproperties.get_axis_limits (min_val, max_val, min_pos, + xproperties.xscale_is ("log")); + + update_type = 'x'; + } + } + else if (axis_type == "ydata" || axis_type == "yscale" + || axis_type == "ylimmode" || axis_type == "yliminclude" + || axis_type == "ylim") + { + if (xproperties.ylimmode_is ("auto")) + { + limits = xproperties.get_ylim ().matrix_value (); + FIX_LIMITS ; + + get_children_limits (min_val, max_val, min_pos, kids, 'y'); + + limits = xproperties.get_axis_limits (min_val, max_val, min_pos, + xproperties.yscale_is ("log")); + + update_type = 'y'; + } + } + else if (axis_type == "zdata" || axis_type == "zscale" + || axis_type == "zlimmode" || axis_type == "zliminclude" + || axis_type == "zlim") + { + if (xproperties.zlimmode_is ("auto")) + { + limits = xproperties.get_zlim ().matrix_value (); + FIX_LIMITS ; + + get_children_limits (min_val, max_val, min_pos, kids, 'z'); + + limits = xproperties.get_axis_limits (min_val, max_val, min_pos, + xproperties.zscale_is ("log")); + + update_type = 'z'; + } + } + else if (axis_type == "cdata" || axis_type == "climmode" + || axis_type == "cdatamapping" || axis_type == "climinclude" + || axis_type == "clim") + { + if (xproperties.climmode_is ("auto")) + { + limits = xproperties.get_clim ().matrix_value (); + FIX_LIMITS ; + + get_children_limits (min_val, max_val, min_pos, kids, 'c'); + + if (min_val > max_val) + { + min_val = min_pos = 0; + max_val = 1; + } + else if (min_val == max_val) + max_val = min_val + 1; + + limits.resize (1, 2); + + limits(0) = min_val; + limits(1) = max_val; + + update_type = 'c'; + } + + } + else if (axis_type == "alphadata" || axis_type == "alimmode" + || axis_type == "alphadatamapping" || axis_type == "aliminclude" + || axis_type == "alim") + { + if (xproperties.alimmode_is ("auto")) + { + limits = xproperties.get_alim ().matrix_value (); + FIX_LIMITS ; + + get_children_limits (min_val, max_val, min_pos, kids, 'a'); + + if (min_val > max_val) + { + min_val = min_pos = 0; + max_val = 1; + } + else if (min_val == max_val) + max_val = min_val + 1; + + limits.resize (1, 2); + + limits(0) = min_val; + limits(1) = max_val; + + update_type = 'a'; + } + + } + +#undef FIX_LIMITS + + unwind_protect frame; + frame.protect_var (updating_axis_limits); + + updating_axis_limits = true; + + switch (update_type) + { + case 'x': + xproperties.set_xlim (limits); + xproperties.set_xlimmode ("auto"); + xproperties.update_xlim (); + break; + + case 'y': + xproperties.set_ylim (limits); + xproperties.set_ylimmode ("auto"); + xproperties.update_ylim (); + break; + + case 'z': + xproperties.set_zlim (limits); + xproperties.set_zlimmode ("auto"); + xproperties.update_zlim (); + break; + + case 'c': + xproperties.set_clim (limits); + xproperties.set_climmode ("auto"); + break; + + case 'a': + xproperties.set_alim (limits); + xproperties.set_alimmode ("auto"); + break; + + default: + break; + } + + xproperties.update_transform (); + +} + +void axes::update_axis_limits (const std::string& axis_type) { if (updating_axis_limits) @@ -4957,9 +5098,151 @@ // --------------------------------------------------------------------- +void +hggroup::properties::update_limits (void) const +{ + graphics_object obj = gh_manager::get_object (__myhandle__); + + if (obj) + { + obj.update_axis_limits ("xlim"); + obj.update_axis_limits ("ylim"); + obj.update_axis_limits ("zlim"); + obj.update_axis_limits ("clim"); + obj.update_axis_limits ("alim"); + } +} + +void +hggroup::properties::update_limits (const graphics_handle& h) const +{ + graphics_object obj = gh_manager::get_object (__myhandle__); + + if (obj) + { + obj.update_axis_limits ("xlim", h); + obj.update_axis_limits ("ylim", h); + obj.update_axis_limits ("zlim", h); + obj.update_axis_limits ("clim", h); + obj.update_axis_limits ("alim", h); + } +} + +static bool updating_hggroup_limits = false; + +void +hggroup::update_axis_limits (const std::string& axis_type, + const graphics_handle& h) +{ + if (updating_hggroup_limits) + return; + + Matrix kids = Matrix (1, 1, h.value ()); + + double min_val = octave_Inf; + double max_val = -octave_Inf; + double min_pos = octave_Inf; + + Matrix limits; + double val; + + char update_type = 0; + + if (axis_type == "xlim" || axis_type == "xliminclude") + { + limits = xproperties.get_xlim ().matrix_value (); + update_type = 'x'; + } + else if (axis_type == "ylim" || axis_type == "yliminclude") + { + limits = xproperties.get_ylim ().matrix_value (); + update_type = 'y'; + } + else if (axis_type == "zlim" || axis_type == "zliminclude") + { + limits = xproperties.get_zlim ().matrix_value (); + update_type = 'z'; + } + else if (axis_type == "clim" || axis_type == "climinclude") + { + limits = xproperties.get_clim ().matrix_value (); + update_type = 'c'; + } + else if (axis_type == "alim" || axis_type == "aliminclude") + { + limits = xproperties.get_alim ().matrix_value (); + update_type = 'a'; + } + + if (limits.numel() == 3) + { + val = limits(0); + if (! (xisinf (val) || xisnan (val))) + min_val = val; + val = limits(1); + if (! (xisinf (val) || xisnan (val))) + max_val = val; + val = limits(2); + if (! (xisinf (val) || xisnan (val))) + min_pos = val; + } + else + { + limits.resize(3,1); + limits(0) = min_val; + limits(1) = max_val; + limits(2) = min_pos; + } + + get_children_limits (min_val, max_val, min_pos, kids, update_type); + + unwind_protect frame; + frame.protect_var (updating_hggroup_limits); + + updating_hggroup_limits = true; + + if (limits(0) != min_val || limits(1) != max_val || limits(2) != min_pos) + { + limits(0) = min_val; + limits(1) = max_val; + limits(2) = min_pos; + + switch (update_type) + { + case 'x': + xproperties.set_xlim (limits); + break; + + case 'y': + xproperties.set_ylim (limits); + break; + + case 'z': + xproperties.set_zlim (limits); + break; + + case 'c': + xproperties.set_clim (limits); + break; + + case 'a': + xproperties.set_alim (limits); + break; + + default: + break; + } + + base_graphics_object::update_axis_limits (axis_type, h); + } +} + void hggroup::update_axis_limits (const std::string& axis_type) { + if (updating_hggroup_limits) + return; + Matrix kids = xproperties.get_children (); double min_val = octave_Inf; @@ -4971,7 +5254,7 @@ if (axis_type == "xlim" || axis_type == "xliminclude") { get_children_limits (min_val, max_val, min_pos, kids, 'x'); - + update_type = 'x'; } else if (axis_type == "ylim" || axis_type == "yliminclude") @@ -4991,7 +5274,6 @@ get_children_limits (min_val, max_val, min_pos, kids, 'c'); update_type = 'c'; - } else if (axis_type == "alim" || axis_type == "aliminclude") { @@ -5000,6 +5282,11 @@ update_type = 'a'; } + unwind_protect frame; + frame.protect_var (updating_hggroup_limits); + + updating_hggroup_limits = true; + Matrix limits (1, 3, 0.0); limits(0) = min_val; @@ -5774,6 +6061,10 @@ make_graphics_object (const std::string& go_name, const octave_value_list& args) { + //octave_time now; + //double t1, t2, t3; + //double t0 = now.double_value (); + octave_value retval; double val = octave_NaN; @@ -5816,9 +6107,15 @@ if (! error_state) { adopt (parent, h); + //now.stamp(); + //t1 = now.double_value (); xset (h, xargs); + //now.stamp(); + //t2 = now.double_value (); xcreatefcn (h); + //now.stamp(); + //t3 = now.double_value (); retval = h.value (); @@ -5835,6 +6132,10 @@ else error ("__go_%s__: invalid parent", go_name.c_str ()); + + //now.stamp(); + //octave_stdout << "Make object times : " << t1 - t0 << " " << t2 - t1 << " " << t3 - t2 << " " << now.double_value() - t3 << " seconds.\n"; + return retval; }
--- a/src/graphics.h.in +++ b/src/graphics.h.in @@ -1368,6 +1368,174 @@ // --------------------------------------------------------------------- +class children_property : public base_property +{ +public: + children_property (void) + : base_property ("", graphics_handle ()) + { + do_init_children (Matrix ()); + } + + children_property (const std::string& nm, const graphics_handle& h, + const Matrix &val) + : base_property (nm, h) + { + do_init_children (val); + } + + children_property (const children_property& p) + : base_property (p) + { + do_init_children (p.children_list); + } + + children_property& operator = (const octave_value& val) + { + set (val); + return *this; + } + + base_property* clone (void) const { return new children_property (*this); } + + bool remove_child (const double &val) + { + return do_remove_child (val); + } + + void adopt (const double &val) + { + do_adopt_child (val); + } + + Matrix get_children (void) const + { + return do_get_children (false); + } + + Matrix get_hidden (void) const + { + return do_get_children (true); + } + + Matrix get_all (void) const + { + return do_get_all_children (); + } + + octave_value get (void) const + { + return octave_value (get_children ()); + } + + void delete_children (bool clear = false) + { + do_delete_children (clear); + } + +private: + typedef std::list<double>::iterator children_list_iterator; + typedef std::list<double>::const_iterator const_children_list_iterator; + std::list<double> children_list; + +protected: + bool do_set (const octave_value& val) + { + const Matrix new_kids = val.matrix_value (); + + octave_idx_type nel = new_kids.numel (); + + const Matrix new_kids_column = new_kids.reshape (dim_vector (nel, 1)); + + bool is_ok = true; + + if (! error_state) + { + const Matrix visible_kids = do_get_children (false); + + if (visible_kids.numel () == new_kids.numel ()) + { + Matrix t1 = visible_kids.sort (); + Matrix t2 = new_kids_column.sort (); + + if (t1 != t2) + is_ok = false; + } + else + is_ok = false; + + if (! is_ok) + error ("set: new children must be a permutation of existing children"); + } + else + { + is_ok = false; + error ("set: expecting children to be array of graphics handles"); + } + + if (is_ok) + { + children_list.clear (); + do_init_children (new_kids_column.stack (get_hidden ())); + } + + return is_ok; + } + +private: + void do_init_children (const Matrix &val) + { + children_list.clear (); + for (octave_idx_type i = 0; i < val.numel (); i++) + children_list.push_front (val.xelem (i)); + } + + void do_init_children (const std::list<double> &val) + { + children_list.clear (); + for (const_children_list_iterator p = val.begin (); p != val.end (); p++) + children_list.push_front (*p); + } + + Matrix do_get_children (bool return_hidden) const; + + Matrix do_get_all_children (void) const + { + Matrix retval (children_list.size (), 1); + octave_idx_type i = 0; + + for (const_children_list_iterator p = children_list.begin (); + p != children_list.end (); p++) + retval(i++) = *p; + return retval; + } + + bool do_remove_child (double child) + { + for (children_list_iterator p = children_list.begin (); + p != children_list.end (); p++) + { + if (*p == child) + { + children_list.erase (p); + return true; + } + } + return false; + } + + void do_adopt_child (const double &val) + { + children_list.push_front (val); + } + + void do_delete_children (bool clear); +}; + + + +// --------------------------------------------------------------------- + class callback_property : public base_property { public: @@ -1848,15 +2016,15 @@ bool is_modified (void) const { return is___modified__ (); } - virtual void remove_child (const graphics_handle& h); + virtual void remove_child (const graphics_handle& h) + { + if (children.remove_child (h.value ())) + mark_modified (); + } virtual void adopt (const graphics_handle& h) { - octave_idx_type n = children.numel (); - children.resize (n+1, 1); - for (octave_idx_type i = n; i > 0; i--) - children(i) = children(i-1); - children(0) = h.value (); + children.adopt (h.value ()); mark_modified (); } @@ -1877,11 +2045,20 @@ void set_parent (const octave_value& val); - Matrix get_all_children (void) const { return children; } - - Matrix get_hidden_children (void) const; - - void set_children (const octave_value& val); + Matrix get_children (void) const + { + return children.get_children (); + } + + Matrix get_all_children (void) const + { + return children.get_all (); + } + + Matrix get_hidden_children (void) const + { + return children.get_hidden (); + } void set_modified (const octave_value& val) { set___modified__ (val); } @@ -1894,8 +2071,14 @@ virtual void update_axis_limits (const std::string& axis_type) const; - virtual void delete_children (void); - + virtual void update_axis_limits (const std::string& axis_type, + const graphics_handle& h) const; + + virtual void delete_children (bool clear = false) + { + children.delete_children (clear); + } + static property_list::pval_map_type factory_defaults (void); // FIXME -- these functions should be generated automatically by the @@ -1940,8 +2123,7 @@ bool_property beingdeleted , "off" radio_property busyaction , "{queue}|cancel" callback_property buttondownfcn , Matrix () - // FIXME -- use a property class for children. - Matrix children Gfs , Matrix () + children_property children gf , Matrix () bool_property clipping , "on" callback_property createfcn , Matrix () callback_property deletefcn , Matrix () @@ -1983,9 +2165,6 @@ { insert_property (name, property (&p, true)); } virtual void init (void) { } - -private: - Matrix get_children_internal (bool return_hidden) const; }; class OCTINTERP_API base_graphics_object @@ -2151,6 +2330,9 @@ virtual void update_axis_limits (const std::string& axis_type); + virtual void update_axis_limits (const std::string& axis_type, + const graphics_handle& h); + virtual bool valid_object (void) const { return false; } virtual std::string type (void) const @@ -2336,6 +2518,12 @@ rep->update_axis_limits (axis_type); } + void update_axis_limits (const std::string& axis_type, + const graphics_handle& h) + { + rep->update_axis_limits (axis_type, h); + } + bool valid_object (void) const { return rep->valid_object (); } std::string type (void) const { return rep->type (); } @@ -3191,6 +3379,9 @@ void update_axis_limits (const std::string& axis_type); + void update_axis_limits (const std::string& axis_type, + const graphics_handle& h); + bool valid_object (void) const { return true; } void reset_default_properties (void); @@ -3796,8 +3987,9 @@ void adopt (const graphics_handle& h) { + base_properties::adopt (h); - update_limits (); + update_limits (h); } // See the genprops.awk script for an explanation of the @@ -3818,18 +4010,14 @@ END_PROPERTIES private: - void update_limits (void) - { - update_axis_limits ("xlim"); - update_axis_limits ("ylim"); - update_axis_limits ("zlim"); - update_axis_limits ("clim"); - update_axis_limits ("alim"); - } + void update_limits (void) const; + + void update_limits (const graphics_handle& h) const; protected: void init (void) { } + }; private: @@ -3849,8 +4037,12 @@ const base_properties& get_properties (void) const { return xproperties; } bool valid_object (void) const { return true; } - + void update_axis_limits (const std::string& axis_type); + + void update_axis_limits (const std::string& axis_type, + const graphics_handle& h); + }; // ---------------------------------------------------------------------