changeset 25970:3a66ae436d8a

movegui: new function * scripts/gui/movegui.m: New file. * scripts/gui/module.mk: Update. * gui.txi: Document.
author Guillaume Flandin <guillaume.offline@gmail.com>
date Fri, 26 Oct 2018 16:12:11 -0400
parents 7eeb89b0d2d5
children 456523d3cb4a
files doc/interpreter/gui.txi scripts/gui/module.mk scripts/gui/movegui.m
diffstat 3 files changed, 210 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/doc/interpreter/gui.txi	Fri Oct 26 15:00:33 2018 -0400
+++ b/doc/interpreter/gui.txi	Fri Oct 26 16:12:11 2018 -0400
@@ -134,6 +134,8 @@
 
 @DOCSTRING(isguirunning)
 
+@DOCSTRING(movegui)
+
 @c Not sure where this should go...
 @DOCSTRING(openvar)
 
--- a/scripts/gui/module.mk	Fri Oct 26 15:00:33 2018 -0400
+++ b/scripts/gui/module.mk	Fri Oct 26 16:12:11 2018 -0400
@@ -22,6 +22,7 @@
   %reldir%/inputdlg.m \
   %reldir%/isappdata.m \
   %reldir%/listdlg.m \
+  %reldir%/movegui.m \
   %reldir%/msgbox.m \
   %reldir%/questdlg.m \
   %reldir%/rmappdata.m \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/gui/movegui.m	Fri Oct 26 16:12:11 2018 -0400
@@ -0,0 +1,207 @@
+## Copyright (C) 2018 Guillaume Flandin
+##
+## 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.
+## 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 filename COPYING.  If not, see
+## <https://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {Command} {} movegui
+## @deftypefnx  {Command} {} movegui (@var{h})
+## @deftypefnx  {Command} {} movegui (@var{pos})
+## @deftypefnx  {Command} {} movegui (@var{h}, @var{pos})
+## @deftypefnx  {Command} {} movegui (@var{h}, @var{event})
+## @deftypefnx  {Command} {} movegui (@var{h}, @var{event}, @var{pos})
+## Move a figure specified by figure handle @var{h} to a position on the screen
+## defined by @var{pos}.
+##
+## @var{h} is a figure handle, or a handle to a graphics object.  In the latter
+## case, its parent figure will be used.  If unspecified, @var{h} will be set to
+## the handle of the relevant figure if a callback is being executed, otherwise
+## it will be set to the handle of the current figure.
+##
+## @var{pos} is a numeric or char array.  If a numeric array, @var{pos} is a
+## two-value array specifying the horizontal and vertical offsets of the figure
+## with respect to the screen.  A positive value indicates the offset between the
+## left (resp. bottom) of the screen and the left (resp. bottom) of the figure.
+## A negative value indicates the offset between the right (resp. top) of the
+## screen and the right (resp. top) of the figure.
+##
+## Possible values for @var{pos} as a char array are
+##
+## @table @code
+## @item north
+## Top center of the screen.
+## @item south
+## Bottom center of the screen.
+## @item east
+## Right center of the screen.
+## @item west
+## Left center of the screen.
+## @item northeast
+## Top right of the screen.
+## @item northwest
+## Top left of the screen.
+## @item southeast
+## Bottom right of the screen.
+## @item southwest
+## Bottom left of the screen.
+## @item center
+## Center of the screen.
+## @item onscreen
+## The figure will be minimally moved to be entirely visible on the screen, with
+## a 30 pixel extra padding from the sides of the screen.
+## This is the default value if none is provided.
+## @end table
+##
+## @var{event} contains event data that will be ignored.  This construct
+## facilitates a call to movegui from a callback.
+##
+## @end deftypefn
+
+function movegui (varargin)
+
+  if (nargin > 3)
+    print_usage ();
+  endif
+
+  ## Default values for input arguments
+  h = [];
+  pos = "onscreen";
+
+  ## Get input arguments
+  if (nargin == 3)
+    h = varargin{1};
+    pos = varargin{3};
+  elseif (nargin == 2)
+    h = varargin{1};
+    pos = varargin{2};
+  elseif (nargin == 1)
+    if (ishghandle (varargin{1}) && isscalar (varargin{1}))
+      h = varargin{1};
+    else
+      pos = varargin{1};
+    endif
+  endif
+
+  ## Check figure handle
+  if (isempty (h))
+    h = gcbf ();
+    if (isempty (h))
+      h = gcf ();
+    endif
+  endif
+  if (ishghandle (h))
+    h = ancestor (h, "figure");
+  else
+    error ("movegui: invalid figure handle");
+  endif
+
+  ## Get current position
+  units = get (h, "Units");
+  set (h, "Units", "pixels");
+  fpos = get (h, "Position"); # OuterPosition seems unreliable
+  set (h, "Units", units);
+
+  ## Get screen size
+  units_groot = get (groot (), "Units");
+  screen_size = get (groot (), "ScreenSize");
+  set (groot (), "Units", units_groot);
+
+  ## Set default figure and screen border sizes [left, top, right, bottom]
+  f = [0 90 0 30];
+  s = [0  0 0 30];
+
+  ## Make sure figure is not larger than screen
+  fpos(1) = max (fpos(1), 1);
+  fpos(2) = max (fpos(2), 1);
+  fpos(3) = min (fpos(3), screen_size(3));
+  fpos(4) = min (fpos(4), screen_size(4));
+
+  ## Standard figure coordinates
+  ## left, middle, right
+  x = [s(1)+f(1), (screen_size(3)-fpos(3))/2, screen_size(3)-fpos(3)-s(3)-f(3)];
+  ## bottom, middle top
+  y = [s(4)+f(4), (screen_size(4)-fpos(4))/2, screen_size(4)-fpos(4)-s(2)-f(2)];
+
+  ## Compute new position
+  if (isnumeric (pos) && isreal (pos) && numel (pos) == 2)
+    fpos(1) = ifelse (pos(1) >= 0, pos(1), pos(1) + x(3));
+    fpos(2) = ifelse (pos(2) >= 0, pos(2), pos(2) + y(3));
+  elseif (ischar (pos))
+    switch (tolower (pos))
+      case "north"
+        fpos(1:2) = [x(2) y(3)];
+      case "south"
+        fpos(1:2) = [x(2) y(1)];
+      case "east"
+        fpos(1:2) = [x(3) y(2)];
+      case "west"
+        fpos(1:2) = [x(1) y(2)];
+      case "northeast"
+        fpos(1:2) = [x(3) y(3)];
+      case "northwest"
+        fpos(1:2) = [x(1) y(3)];
+      case "southeast"
+        fpos(1:2) = [x(3) y(1)];
+      case "southwest"
+        fpos(1:2) = [x(1) y(1)];
+      case "center"
+        fpos(1:2) = [x(2) y(2)];
+      case "onscreen"
+        if (fpos(1) > x(3))
+          fpos(1) = x(3) - 30;
+        endif
+        if (fpos(2) > y(3))
+          fpos(2) = y(3) - 30;
+        endif
+        fpos(1) = max(fpos(1), 30);
+        fpos(2) = max(fpos(2), 30);
+      otherwise
+        error ("movegui: invalid position");
+    endswitch
+  elseif (nargin == 2 && ! isempty (gcbo))
+    ## Ignore event data (from callback)
+    movegui (h);
+    return;
+  else
+    error ("movegui: invalid position");
+  endif
+
+  ## Move figure
+  units = get (h, "Units");
+  set (h, "Units", "pixels");
+  set (h, "Position", fpos);
+  set (h, "Units", units);
+
+endfunction
+
+%!test
+%! unwind_protect
+%!   h = figure ("Visible", "off");
+%!   pos = {[10 10], [10 -10], [-10 10], [-10 -10], [10 10]',...
+%!     "north", "east", "south", "west", ...
+%!     "northwest", "northeast", "southeast", "southwest", ...
+%!     "center", "onscreen"};
+%!   for i = 1:numel (pos)
+%!     movegui (h, pos{i});
+%!     movegui (pos{i});
+%!     movegui (h, struct ("evt", []), pos{i});
+%!   endfor
+%!   movegui ();
+%!   movegui (h);
+%! unwind_protect_cleanup
+%!   close (h);
+%! end_unwind_protect