# HG changeset patch # User Konstantinos Poulios # Date 1297606316 -3600 # Node ID 2ed62b9f949e88fccad10a0161c54525572c3177 # Parent ab4c6bbff14ae39db182df9135a57d0ee34b4867 synchronization of axes position and outerposition diff --git a/scripts/ChangeLog b/scripts/ChangeLog --- a/scripts/ChangeLog +++ b/scripts/ChangeLog @@ -1,3 +1,7 @@ +2011-02-13 Konstantinos Poulios + + * plot/legend.m: Ignore outerposition. + 2011-02-10 Ben Abbott * plot/legend.m, plot/plotyy.m, plot/sombrero.m, plot/shading.m, diff --git a/scripts/plot/legend.m b/scripts/plot/legend.m --- a/scripts/plot/legend.m +++ b/scripts/plot/legend.m @@ -120,7 +120,7 @@ endif if (strcmp (get (ca, "tag"), "plotyy")) - plty = get(ca (strcmp (get (ca, "tag"), "plotyy")), "userdata"); + plty = get(ca, "userdata"); if (isscalar (plty)) ca = [ca, plty]; else @@ -492,7 +492,7 @@ if (isempty (hlegend)) addprops = true; hlegend = axes ("tag", "legend", "userdata", struct ("handle", ud), - "box", box, "outerposition", [0, 0, 0, 0], + "box", box, "xtick", [], "ytick", [], "xticklabel", "", "yticklabel", "", "zticklabel", "", "xlim", [0, 1], "ylim", [0, 1], "visible", "off", @@ -582,8 +582,6 @@ lpos(4)]; new_pos = [ca_pos(1), ca_pos(2), ca_pos(3), ca_pos(4) - lpos(4)]; - new_outpos = [ca_outpos(1), ca_outpos(2), ca_outpos(3), ... - ca_outpos(4) - lpos(4)]; else lpos = [ca_pos(1) + (ca_pos(3) - lpos(3)) / 2, ... ca_pos(2) + ca_pos(4) - lpos(4) - ypad, lpos(3), lpos(4)]; @@ -594,8 +592,6 @@ ca_outpos(2) + ypad, lpos(3), lpos(4)]; new_pos = [ca_pos(1), ca_pos(2) + lpos(4), ca_pos(3), ... ca_pos(4) - lpos(4)]; - new_outpos = [ca_outpos(1), ca_outpos(2) + lpos(4), ... - ca_outpos(3), ca_outpos(4) - lpos(4)]; else lpos = [ca_pos(1) + (ca_pos(3) - lpos(3)) / 2, ... ca_pos(2) + ypad, lpos(3), lpos(4)]; @@ -605,8 +601,6 @@ lpos = [ca_outpos(1) + ca_outpos(3) - lpos(3) - ypad, ... ca_pos(2) + (ca_pos(4) - lpos(4)) / 2, lpos(3), lpos(4)]; new_pos = [ca_pos(1), ca_pos(2), ca_pos(3) - lpos(3), ca_pos(4)]; - new_outpos = [ca_outpos(1), ca_outpos(2), ... - ca_outpos(3) - lpos(3), ca_outpos(4)]; else lpos = [ca_pos(1) + ca_pos(3) - lpos(3) - ypad, ... ca_pos(2) + (ca_pos(4) - lpos(4)) / 2, lpos(3), lpos(4)]; @@ -618,8 +612,6 @@ lpos(3), lpos(4)]; new_pos = [ca_pos(1) + lpos(3), ca_pos(2), ... ca_pos(3) - lpos(3), ca_pos(4)]; - new_outpos = [ca_outpos(1) + lpos(3), ca_outpos(2), ... - ca_outpos(3) - lpos(3), ca_outpos(4)]; else lpos = [ca_pos(1) + ypad, ... ca_pos(2) + (ca_pos(4) - lpos(4)) / 2, lpos(3), lpos(4)]; @@ -629,8 +621,6 @@ lpos = [ca_outpos(1) + ca_outpos(3) - lpos(3) - ypad, ... ca_pos(2) + ca_pos(4) - lpos(4), lpos(3), lpos(4)]; new_pos = [ca_pos(1), ca_pos(2), ca_pos(3) - lpos(3), ca_pos(4)]; - new_outpos = [ca_outpos(1), ca_outpos(2), ... - ca_outpos(3) - lpos(3), ca_outpos(4)]; else lpos = [ca_pos(1) + ca_pos(3) - lpos(3) - ypad, ... ca_pos(2) + ca_pos(4) - lpos(4) - ypad, lpos(3), lpos(4)]; @@ -641,8 +631,6 @@ lpos(3), lpos(4)]; new_pos = [ca_pos(1) + lpos(3), ca_pos(2), ... ca_pos(3) - lpos(3), ca_pos(4)]; - new_outpos = [ca_outpos(1) + lpos(3), ca_outpos(2), ... - ca_outpos(3) - lpos(3), ca_outpos(4)]; else lpos = [ca_pos(1) + ypad, ... ca_pos(2) + ca_pos(4) - lpos(4) - ypad, lpos(3), lpos(4)]; @@ -653,8 +641,6 @@ ca_pos(2), lpos(3), lpos(4)]; new_pos = [ca_pos(1), ca_pos(2), ... ca_pos(3) - lpos(3), ca_pos(4)]; - new_outpos = [ca_outpos(1), ca_outpos(2), ... - ca_outpos(3) - lpos(3), ca_outpos(4)]; else lpos = [ca_pos(1) + ca_pos(3) - lpos(3) - ypad, ... ca_pos(2) + ypad, lpos(3), lpos(4)]; @@ -664,8 +650,6 @@ lpos = [ca_outpos(1) + ypad, ca_pos(2), lpos(3), lpos(4)]; new_pos = [ca_pos(1) + lpos(3), ca_pos(2), ... ca_pos(3) - lpos(3), ca_pos(4)]; - new_outpos = [ca_outpos(1) + lpos(3), ca_outpos(2), ... - ca_outpos(3) - lpos(3), ca_outpos(4)]; else lpos = [ca_pos(1) + ypad, ca_pos(2) + ypad, lpos(3), lpos(4)]; endif @@ -674,7 +658,7 @@ units = get (hlegend, "units"); unwind_protect set (hlegend, "units", "points"); - set (hlegend, "position", lpos, "outerposition", lpos); + set (hlegend, "position", lpos); unwind_protect_cleanup set (hlegend, "units", units); end_unwind_protect @@ -750,7 +734,7 @@ units = get (ca(i), "units"); unwind_protect set (ca(i), "units", "points"); - set (ca (i), "position", new_pos, "outerposition", new_outpos); + set (ca (i), "position", new_pos); unwind_protect_cleanup set (ca(i), "units", units); end_unwind_protect @@ -759,8 +743,7 @@ set (hlegend, "deletefcn", {@deletelegend2, ca, ... ca_pos, ca_outpos, t1, hplots}); addlistener (hlegend, "visible", {@hideshowlegend, ca, ... - ca_pos, new_pos, ... - ca_outpos, new_outpos}); + ca_pos, new_pos}); else set (hlegend, "deletefcn", {@deletelegend2, ca, [], [], t1, hplots}); endif @@ -841,7 +824,7 @@ endwhile endfunction -function hideshowlegend (h, d, ca, pos1, pos2, outpos1, outpos2) +function hideshowlegend (h, d, ca, pos1, pos2) isvisible = strcmp (get (h, "visible"), "off"); if (! isvisible) kids = get (h, "children"); @@ -861,9 +844,9 @@ unwind_protect set (ca(i), "units", "points"); if (isvisible) - set (ca(i), "position", pos2, "outerposition", outpos2); + set (ca(i), "position", pos2); else - set (ca(i), "position", pos1, "outerposition", outpos1); + set (ca(i), "position", pos1); endif unwind_protect_cleanup set (ca(i), "units", units); @@ -889,7 +872,7 @@ units = get (ca(i), "units"); unwind_protect set (ca(i), "units", "points"); - set (ca(i), "position", pos, "outerposition", outpos, "deletefcn", ""); + set (ca(i), "position", pos, "deletefcn", ""); unwind_protect_cleanup set (ca(i), "units", units); end_unwind_protect diff --git a/src/ChangeLog b/src/ChangeLog --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,30 @@ +2011-02-13 Konstantinos Poulios + + * graphics.h.in (axes::properties::get_extent, + axes::properties::calc_tightbox): New functions prototypes. + (axes::properties::update_view): Hook sync_positions. + (axes::properties::update_outerposition, + axes::properties::update_position): Set activepositionproperty + appropriately. + (text::properties::update_string): Call update_text_extent after + request_autopos. + * graphics.cc (axes::properties::sync_positions): Enable + synchronization of position and outer position. Take label and + title extents in the calculation of outerposition into account. + Do iterative calculation of position when activepositionproperty + is set to outerposition. + (axes::properties::update_title_position): Use new function + get_extent. + (axes::properties::update_autopos): Handle new tag "sync". + (axes::properties::get_extent): New function calculating the + tight box which contains all axes labels and axes title. + (axes::properties::calc_tightbox): New function calculating axes + tight box. + (axes::properties::update_units): Don't call any hooks and listeners + for position, outerposition and tightset. + (text::properties::update_text_extent): Request axes positions + synchronization when axes labels or title extents change. + 2011-02-11 John W. Eaton * load-path.cc (strip_trailing_separators): Declare K as size_t diff --git a/src/graphics.cc b/src/graphics.cc --- a/src/graphics.cc +++ b/src/graphics.cc @@ -3229,38 +3229,109 @@ adopt (title.handle_value ()); } +Matrix +axes::properties::calc_tightbox (const Matrix& init_pos) +{ + Matrix pos = init_pos; + graphics_object obj = gh_manager::get_object (get_parent ()); + Matrix parent_bb = obj.get_properties ().get_boundingbox (true); + Matrix ext = get_extent (true); + ext(1) = parent_bb(3) - ext(1) - ext(3); + ext(0)++; + ext(1)++; + ext = convert_position (ext, "pixels", get_units (), + parent_bb.extract_n (0, 2, 1, 2)); + if (ext(0) < pos(0)) + { + pos(2) += pos(0)-ext(0); + pos(0) = ext(0); + } + if (ext(0)+ext(2) > pos(0)+pos(2)) + pos(2) = ext(0)+ext(2)-pos(0); + + if (ext(1) < pos(1)) + { + pos(3) += pos(1)-ext(1); + pos(1) = ext(1); + } + if (ext(1)+ext(3) > pos(1)+pos(3)) + pos(3) = ext(1)+ext(3)-pos(1); + return pos; +} + void axes::properties::sync_positions (void) { -#if 0 - // FIXME -- this should take font metrics into consideration, - // and also the fact that the colorbox leaves the outerposition - // alone but alters the position. For now just don't adjust the - // positions relative to each other. + Matrix defpos = default_axes_position (); if (activepositionproperty.is ("outerposition")) { Matrix outpos = outerposition.get ().matrix_value (); - Matrix defpos = default_axes_position (); Matrix pos(outpos); pos(0) = outpos(0) + defpos(0) * outpos(2); pos(1) = outpos(1) + defpos(1) * outpos(3); pos(2) = outpos(2) * defpos(2); pos(3) = outpos(3) * defpos(3); + position = pos; + update_transform (); + Matrix tightpos = calc_tightbox (pos); + + double thrshldx = 0.005*outpos(2); + double thrshldy = 0.005*outpos(3); + for (int i = 0; i < 10; i++) + { + double dt; + bool modified = false; + dt = outpos(0)+outpos(2)-tightpos(0)-tightpos(2); + if (dt < -thrshldx) + { + pos(2) += dt; + modified = true; + } + dt = outpos(1)+outpos(3)-tightpos(1)-tightpos(3); + if (dt < -thrshldy) + { + pos(3) += dt; + modified = true; + } + dt = outpos(0)-tightpos(0); + if (dt > thrshldx) + { + pos(0) += dt; + pos(2) -= dt; + modified = true; + } + dt = outpos(1)-tightpos(1); + if (dt > thrshldy) + { + pos(1) += dt; + pos(3) -= dt; + modified = true; + } + + if (modified) + { + position = pos; + update_transform (); + tightpos = calc_tightbox (pos); + } + else + break; + } } else { + update_transform (); + Matrix pos = position.get ().matrix_value (); - pos(0) -= pos(2)*0.05; - pos(1) -= pos(3)*0.05; - pos(2) *= 1.1; - pos(3) *= 1.1; - outerposition = pos; - } -#endif - - update_transform (); + pos(0) -= pos(2)*defpos(0)/defpos(2); + pos(1) -= pos(3)*defpos(1)/defpos(3); + pos(2) /= defpos(2); + pos(3) /= defpos(3); + + outerposition = calc_tightbox (pos); + } } void @@ -4408,27 +4479,7 @@ graphics_xform xform = get_transform (); // FIXME: bbox should be stored in axes::properties - ColumnVector bbox(4); - bbox(0) = octave_Inf; - bbox(1) = octave_Inf; - bbox(2) = -octave_Inf; - bbox(3) = -octave_Inf; - for (int i = 0; i <= 1; i++) - for (int j = 0; j <= 1; j++) - for (int k = 0; k <= 1; k++) - { - ColumnVector p = xform.transform (i ? xPlaneN : xPlane, - j ? yPlaneN : yPlane, - k ? zPlaneN : zPlane, false); - bbox(0) = std::min (bbox(0), p(0)); - bbox(1) = std::min (bbox(1), p(1)); - bbox(2) = std::max (bbox(2), p(0)); - bbox(3) = std::max (bbox(3), p(1)); - } - - bbox(2) = bbox(2)-bbox(0); - bbox(3) = bbox(3)-bbox(1); - + Matrix bbox = get_extent (false); ColumnVector p = xform.untransform (bbox(0)+bbox(2)/2, (bbox(1)-10), (x_zlim(0)+x_zlim(1))/2, true); @@ -4451,6 +4502,8 @@ update_zlabel_position (); else if (elem_type == "title") update_title_position (); + else if (elem_type == "sync") + sync_positions (); } static void @@ -4615,7 +4668,6 @@ get_position ().matrix_value () : get_outerposition ().matrix_value ()); - pos = convert_position (pos, get_units (), "pixels", parent_bb.extract_n (0, 2, 1, 2)); @@ -4626,6 +4678,66 @@ return pos; } +Matrix +axes::properties::get_extent (bool with_text) const +{ + graphics_xform xform = get_transform (); + + Matrix ext (1, 4, 0.0); + ext(0) = octave_Inf; + ext(1) = octave_Inf; + ext(2) = -octave_Inf; + ext(3) = -octave_Inf; + for (int i = 0; i <= 1; i++) + for (int j = 0; j <= 1; j++) + for (int k = 0; k <= 1; k++) + { + ColumnVector p = xform.transform (i ? xPlaneN : xPlane, + j ? yPlaneN : yPlane, + k ? zPlaneN : zPlane, false); + ext(0) = std::min (ext(0), p(0)); + ext(1) = std::min (ext(1), p(1)); + ext(2) = std::max (ext(2), p(0)); + ext(3) = std::max (ext(3), p(1)); + } + + if (with_text) + { + for (int i = 0; i < 4; i++) + { + graphics_handle text_handle; + if (i == 0) + text_handle = get_title (); + else if (i == 1) + text_handle = get_xlabel (); + else if (i == 2) + text_handle = get_ylabel (); + else if (i == 3) + text_handle = get_zlabel (); + + text::properties& text_props = reinterpret_cast + (gh_manager::get_object (text_handle).get_properties ()); + + if (! text_props.get_string ().empty ()) + { + Matrix text_ext = text_props.get_extent_matrix (); + Matrix text_pos = text_props.get_position ().matrix_value (); + text_pos = xform.transform (text_pos(0), text_pos(1), text_pos(2)); + + ext(0) = std::min (ext(0), text_pos(0)+text_ext(0)); + ext(1) = std::min (ext(1), text_pos(1)-text_ext(1)-text_ext(3)); + ext(2) = std::max (ext(2), text_pos(0)+text_ext(0)+text_ext(2)); + ext(3) = std::max (ext(3), text_pos(1)-text_ext(1)); + } + } + } + + ext(2) = ext(2)-ext(0); + ext(3) = ext(3)-ext(1); + + return ext; +} + void axes::properties::set_units (const octave_value& v) { @@ -4646,9 +4758,9 @@ graphics_object obj = gh_manager::get_object (get_parent ()); Matrix parent_bb = obj.get_properties ().get_boundingbox (true).extract_n (0, 2, 1, 2); caseless_str new_units = get_units (); - set_position (octave_value (convert_position (get_position().matrix_value(), old_units, new_units, parent_bb))); - set_outerposition (octave_value (convert_position (get_outerposition().matrix_value(), old_units, new_units, parent_bb))); - set_tightinset (octave_value (convert_position (get_tightinset().matrix_value(), old_units, new_units, parent_bb))); + position.set (octave_value (convert_position (get_position().matrix_value(), old_units, new_units, parent_bb)), false); + outerposition.set (octave_value (convert_position (get_outerposition().matrix_value(), old_units, new_units, parent_bb)), false); + tightinset.set (octave_value (convert_position (get_tightinset().matrix_value(), old_units, new_units, parent_bb)), false); } void @@ -5724,6 +5836,10 @@ set_extent (bbox); #endif + + if (autopos_tag_is ("xlabel") || autopos_tag_is ("ylabel") || + autopos_tag_is ("zlabel") || autopos_tag_is ("title")) + update_autopos ("sync"); } void diff --git a/src/graphics.h.in b/src/graphics.h.in --- a/src/graphics.h.in +++ b/src/graphics.h.in @@ -3077,6 +3077,7 @@ const scaler& get_z_scaler (void) const { return sz; } Matrix get_boundingbox (bool internal = false) const; + Matrix get_extent (bool with_text = false) const; void update_boundingbox (void) { @@ -3305,7 +3306,7 @@ void update_yscale (void) { sy = get_yscale (); } void update_zscale (void) { sz = get_zscale (); } - void update_view (void) { update_camera (); update_axes_layout (); } + void update_view (void) { sync_positions (); } void update_dataaspectratio (void) { update_transform (); } void update_dataaspectratiomode (void) { update_transform (); } void update_plotboxaspectratio (void) { update_transform (); } @@ -3381,8 +3382,17 @@ } void sync_positions (void); - void update_outerposition (void) { sync_positions ();} - void update_position (void) { sync_positions (); } + void update_outerposition (void) + { + set_activepositionproperty ("outerposition"); + sync_positions (); + } + + void update_position (void) + { + set_activepositionproperty ("position"); + sync_positions (); + } double calc_tick_sep (double minval, double maxval); void calc_ticks_and_lims (array_property& lims, array_property& ticks, array_property& mticks, @@ -3412,6 +3422,8 @@ } } + Matrix calc_tightbox (const Matrix& init_pos); + public: Matrix get_axis_limits (double xmin, double xmax, double min_pos, bool logscale); @@ -3713,7 +3725,7 @@ void update_horizontalalignmentmode (void) { request_autopos (); } void update_verticalalignmentmode (void) { request_autopos (); } - void update_string (void) { update_text_extent (); request_autopos ();} + void update_string (void) { request_autopos (); update_text_extent (); } void update_rotation (void) { update_text_extent (); } void update_fontname (void) { update_text_extent (); } void update_fontsize (void) { update_text_extent (); }