changeset 28331:be3dab3212e9

getpixelposition.m: Implement new function (bug #58181) * graphics.cc (F__get_position__): New builtin function. * scripts/gui/getpixelposition.m: new function. * scripts/gui/module.mk: Add new function to build system. * gui.txi: Add doc string to the manual.
author Pantxo Diribarne <pantxo.diribarne@gmail.com>
date Sun, 19 Apr 2020 20:25:11 +0200
parents cf20fd68305e
children d9551fd70fc6
files NEWS doc/interpreter/gui.txi libinterp/corefcn/graphics.cc scripts/gui/getpixelposition.m scripts/gui/module.mk
diffstat 5 files changed, 167 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Mon May 18 16:15:25 2020 -0400
+++ b/NEWS	Sun Apr 19 20:25:11 2020 +0200
@@ -96,6 +96,7 @@
 
 ### Alphabetical list of new functions added in Octave 7
 
+* `getpixelposition`
 * `endsWith`
 * `rng`
 * `startsWith`
--- a/doc/interpreter/gui.txi	Mon May 18 16:15:25 2020 -0400
+++ b/doc/interpreter/gui.txi	Sun Apr 19 20:25:11 2020 +0200
@@ -141,6 +141,8 @@
 
 @DOCSTRING(isguirunning)
 
+@DOCSTRING(getpixelposition)
+
 @DOCSTRING(movegui)
 
 @DOCSTRING(openvar)
--- a/libinterp/corefcn/graphics.cc	Mon May 18 16:15:25 2020 -0400
+++ b/libinterp/corefcn/graphics.cc	Sun Apr 19 20:25:11 2020 +0200
@@ -14661,6 +14661,42 @@
   return ovl (go.get_toolkit ().get_pixels (go));
 }
 
+DEFMETHOD (__get_position__, interp, args, ,
+           doc: /* -*- texinfo -*-
+@deftypefn {} {@var{pos} =} __get_position__ (@var{h}, @var{units})
+Internal function.
+
+Return the position of the graphics object @var{h} in the specified
+@var{units}.
+@end deftypefn */)
+{
+  if (args.length () != 2)
+    print_usage ();
+
+  double h
+    = args(0).xdouble_value ("__get_position__: H must be a graphics handle");
+
+  std::string units
+    = args(1).xstring_value ("__get_position__: UNITS must be a string");
+
+  gh_manager& gh_mgr = interp.get_gh_manager ();
+
+  graphics_object go = gh_mgr.get_object (h);
+
+  if (h == 0 || ! go)
+    error ("__get_position__: H must be a handle to a valid graphics object");
+
+  graphics_object parent_go = gh_mgr.get_object (go.get_parent ());
+  Matrix bbox = parent_go.get_properties ().get_boundingbox (true)
+                .extract_n (0, 2, 1, 2);
+
+  Matrix pos = convert_position (go.get ("position").matrix_value (),
+                                 go.get ("units").string_value (),
+                                 units, bbox);
+
+  return ovl (pos);
+}
+
 DEFUN (__get_system_fonts__, args, ,
        doc: /* -*- texinfo -*-
 @deftypefn {} {@var{font_struct} =} __get_system_fonts__ ()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/gui/getpixelposition.m	Sun Apr 19 20:25:11 2020 +0200
@@ -0,0 +1,127 @@
+########################################################################
+##
+## Copyright (C) 2020 The Octave Project Developers
+##
+## See the file COPYRIGHT.md in the top-level directory of this
+## distribution or <https://octave.org/copyright/>.
+##
+## This file is part of Octave.
+##
+## Octave is free software: you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <https://www.gnu.org/licenses/>.
+##
+########################################################################
+
+## -*- texinfo -*-
+## @deftypefn  {} {@var{pos} =} getpixelposition (@var{h})
+## @deftypefnx {} {@var{pos} =} getpixelposition (@var{h}, @var{rel_to_fig})
+## Return the position of a user interface component in pixel units.
+##
+## The first argument @var{h} must be a handle to a valid graphics object of
+## type uibuttongroup, uicontrol, uipanel, uitable, axes, or figure.  For other
+## object types, the function returns zeros.
+##
+## By default, the position is returned relative to the object's parent.
+## If the second argument @var{rel_to_fig} is logically true, the position
+## is computed relative to the enclosing figure object.
+##
+## The return value @var{pos} is a 4-element vector with values
+## @code{[ lower_left_X, lower_left_Y, width, height ]}.
+##
+## @seealso{get}
+## @end deftypefn
+
+function pos = getpixelposition (h, rel_to_fig = false)
+
+  if (nargin < 1 || nargin > 2)
+    print_usage ();
+  endif
+
+  if (! isscalar (h) || ! ishghandle (h))
+    error ("getpixelposition: H must be a scalar graphics handle");
+  endif
+
+  if (! any (strcmp (get (h, "type"), {"uibuttongroup", "uicontrol", ...
+                                       "uitable", "uipanel", ...
+                                       "axes", "figure"})))
+    pos = zeros (1, 4);
+    return;
+  endif
+
+  pos = __get_position__ (h, "pixels");
+
+  if (rel_to_fig)
+    while (! isfigure (h))
+      h = get (h, "parent");
+      pos(1:2) += __get_position__ (h, "pixels")(1:2);
+    endwhile
+  endif
+
+endfunction
+
+
+%!demo
+%! clf ();
+%! hax = axes ("position", [0.25 0.25 0.5 0.5])
+%! pos = getpixelposition (hax);
+%! han = annotation ("rectangle");
+%! set (han, "units", "pixels", "position", pos, "color", "r")
+
+%!demo
+%! hf = clf ();
+%! hbg = uibuttongroup (hf, "position", [0.2 0.7 0.2 0.2]);
+%! hb1 = uicontrol (hbg, "style", "radiobutton", ...
+%!                       "string", "Choice 1", ...
+%!                       "units", "normalized", ...
+%!                       "position", [0.01 0.5 0.98 0.5]);
+%! hb2 = uicontrol (hbg, "style", "radiobutton", ...
+%!                       "string", "Choice 2", ...
+%!                       "units", "normalized", ...
+%!                       "position", [0.01 0 0.98 0.5]);
+%! pos = getpixelposition (hbg);
+%! han = annotation ("rectangle");
+%! set (han, "units", "pixels", "position", pos, "color", "r")
+
+
+%!test
+%! pos = [0 0 400 400];
+%! hf = figure ("visible", "off", "menubar", "none", "position", pos);
+%! unwind_protect
+%!   hp = uipanel (hf, "position", [0.5 0.5 0.5 0.5]);
+%!   hax = axes (hp, "position", [0.5 0.5 0.5 0.5]);
+%!   assert (getpixelposition (hax), [100 100 100 100], 2);
+%!   assert (getpixelposition (hax, true), [300 300 100 100], 2);
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+%!test
+%! ## Compatibility: return zeros for root figure
+%! assert (getpixelposition (groot), zeros (1, 4));
+
+%!test
+%! ## Compatibility: return the same for figures regardless of rel_to_fig
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   assert (getpixelposition (hf), getpixelposition (hf, true));
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+## Test input validation
+%!error getpixelposition ()
+%!error getpixelposition (1,2,3)
+%!error <H must be a scalar> getpixelposition ([1, 2])
+%!error <H must be a .* graphics handle> getpixelposition (-1)
+
--- a/scripts/gui/module.mk	Mon May 18 16:15:25 2020 -0400
+++ b/scripts/gui/module.mk	Sun Apr 19 20:25:11 2020 +0200
@@ -17,6 +17,7 @@
   %reldir%/dialog.m \
   %reldir%/errordlg.m \
   %reldir%/getappdata.m \
+  %reldir%/getpixelposition.m \
   %reldir%/guidata.m \
   %reldir%/guihandles.m \
   %reldir%/helpdlg.m \