1########################################################################
2##
3## Copyright (C) 2014-2021 The Octave Project Developers
4##
5## See the file COPYRIGHT.md in the top-level directory of this
6## distribution or <https://octave.org/copyright/>.
7##
8## This file is part of Octave.
9##
10## Octave is free software: you can redistribute it and/or modify it
11## under the terms of the GNU General Public License as published by
12## the Free Software Foundation, either version 3 of the License, or
13## (at your option) any later version.
14##
15## Octave is distributed in the hope that it will be useful, but
16## WITHOUT ANY WARRANTY; without even the implied warranty of
17## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18## GNU General Public License for more details.
19##
20## You should have received a copy of the GNU General Public License
21## along with Octave; see the file COPYING.  If not, see
22## <https://www.gnu.org/licenses/>.
23##
24########################################################################
25
26## -*- texinfo -*-
27## @deftypefn  {} {} zoom
28## @deftypefnx {} {} zoom (@var{factor})
29## @deftypefnx {} {} zoom on
30## @deftypefnx {} {} zoom off
31## @deftypefnx {} {} zoom xon
32## @deftypefnx {} {} zoom yon
33## @deftypefnx {} {} zoom out
34## @deftypefnx {} {} zoom reset
35## @deftypefnx {} {} zoom (@var{hfig}, @var{option})
36## Zoom the current axes object or control the interactive zoom mode of a
37## figure in the GUI.
38##
39## Given a numeric argument greater than zero, zoom by the given factor.  If
40## the zoom factor is greater than one, zoom in on the plot.  If the factor
41## is less than one, zoom out.  If the zoom factor is a two- or three-element
42## vector, then the elements specify the zoom factors for the x, y, and z
43## axes respectively.
44##
45## Given the option @qcode{"on"} or @qcode{"off"}, set the interactive zoom
46## mode on or off.
47##
48## With no arguments, toggle the current zoom mode on or off.
49##
50## Given the option @qcode{"xon"} or @qcode{"yon"}, enable zoom mode for the
51## x or y-axis only.
52##
53## Given the option @qcode{"out"}, zoom to the initial zoom setting.
54##
55## Given the option @qcode{"reset"}, store the current zoom setting so that
56## @code{zoom out} will return to this zoom level.
57##
58## If the first argument @var{hfig} is a figure, then operate on the given
59## figure rather than the current figure as returned by @code{gcf}.
60##
61## @seealso{pan, rotate3d}
62## @end deftypefn
63
64## Eventually we need to also support these features:
65## @deftypefnx {} {zoom_object_handle =} zoom (@var{hfig})
66
67function zoom (varargin)
68
69  nargs = nargin;
70  if (nargs > 2)
71    print_usage ();
72  endif
73
74  if (nargs == 1 && nargout > 0 && isfigure (varargin{1}))
75    error ("zoom: syntax 'handle = zoom (hfig)' not implemented");
76  endif
77
78  hfig = NaN;
79  if (nargs == 2)
80    hfig = varargin{1};
81    if (isfigure (hfig))
82      varargin(1) = [];
83      nargs -= 1;
84    else
85      error ("zoom: invalid figure handle HFIG");
86    endif
87  endif
88
89  if (isnan (hfig))
90    hfig = gcf ();
91  endif
92
93  if (nargs == 0)
94    zm = get (hfig, "__zoom_mode__");
95    if (strcmp (zm.Enable, "on"))
96      zm.Enable = "off";
97    else
98      zm.Enable = "on";
99    endif
100    set (hfig, "__zoom_mode__", zm);
101    update_mouse_mode (hfig, zm.Enable);
102  elseif (nargs == 1)
103    arg = varargin{1};
104    if (isnumeric (arg))
105      factor = arg;
106      switch (numel (factor))
107        case 2
108          xfactor = factor(1);
109          yfactor = factor(2);
110        case 1
111          xfactor = yfactor = factor;
112        otherwise
113          error ("zoom: invalid FACTOR");
114      endswitch
115      if (xfactor < 0 || yfactor < 0)
116        error ("zoom: FACTOR must be greater than 1");
117      elseif (xfactor == 1 && yfactor == 1)
118        return;
119      endif
120      cax = get (hfig, "currentaxes");
121      if (! isempty (cax))
122        if (xfactor != 1)
123          if (yfactor != 1)
124            mode = "both";
125          else
126            mode = "horizontal";
127          endif
128        else
129          if (yfactor != 1)
130            mode = "vertical";
131          endif
132        endif
133        __zoom__ (cax, mode, factor);
134      endif
135    elseif (ischar (arg))
136      switch (arg)
137        case {"on", "off", "xon", "yon"}
138          zm = get (hfig, "__zoom_mode__");
139          switch (arg)
140            case {"on", "off"}
141              zm.Enable = arg;
142              zm.Motion = "both";
143            case "xon"
144              zm.Enable = "on";
145              zm.Motion = "horizontal";
146            case "yon"
147              zm.Enable = "on";
148              zm.Motion = "vertical";
149          endswitch
150          set (hfig, "__zoom_mode__", zm);
151          update_mouse_mode (hfig, arg);
152        case "out"
153          cax = get (hfig, "currentaxes");
154          if (! isempty (cax))
155            __zoom__ (cax, "out");
156          endif
157        case "reset"
158          cax = get (hfig, "currentaxes");
159          if (! isempty (cax))
160            __zoom__ (cax, "reset");
161          endif
162        otherwise
163          error ("zoom: unrecognized OPTION '%s'", arg);
164      endswitch
165    else
166      error ("zoom: wrong type argument '%s'", class (arg));
167    endif
168  endif
169
170endfunction
171
172function update_mouse_mode (hfig, arg)
173
174  if (strcmp (arg, "off"))
175    set (hfig, "__mouse_mode__", "none");
176  else
177    ## FIXME: Is there a better way other than calling these functions
178    ##        to set the other mouse mode Enable fields to "off"?
179    pan ("off");
180    rotate3d ("off");
181    set (hfig, "__mouse_mode__", "zoom");
182  endif
183
184endfunction
185
186
187%!demo
188%! clf;
189%! sombrero ();
190%! title ("zoom() demo #1");
191%! pause (1);
192%! ## zoom in by a factor of 2
193%! zoom (2);
194%! pause (1);
195%! ## return to original zoom level
196%! zoom out;
197%! pause (1);
198%! ## zoom in by a factor of 2
199%! zoom (2);
200%! pause (1);
201%! ## set this zoom level as the "initial zoom level"
202%! ## and zoom in some more
203%! zoom reset;
204%! zoom (2);
205%! pause (1);
206%! ## return to zoom level set by last call to "zoom reset"
207%! zoom out;
208