view scripts/gui/waitbar.m @ 21580:ecce63c99c3f

maint: Add semicolons to terminate code in %! blocks. * splineimages.m, Cell.cc, bsxfun.cc, cellfun.cc, conv2.cc, data.cc, debug.cc, file-io.cc, gcd.cc, getrusage.cc, graphics.cc, kron.cc, mappers.cc, oct-map.cc, ordschur.cc, psi.cc, rand.cc, variables.cc, __osmesa_print__.cc, amd.cc, audiodevinfo.cc, dmperm.cc, qr.cc, ov-bool-mat.cc, ov-class.cc, ov-fcn-handle.cc, ov-java.cc, oct-parse.in.yy, bicubic.m, delaunay3.m, accumarray.m, flip.m, fliplr.m, flipud.m, gradient.m, inputParser.m, interp1.m, narginchk.m, rot90.m, validateattributes.m, delaunay.m, delaunayn.m, griddata3.m, inpolygon.m, waitbar.m, gray2ind.m, hsv2rgb.m, im2double.m, image.m, imformats.m, imread.m, imshow.m, imwrite.m, ntsc2rgb.m, rgb2hsv.m, rgb2ntsc.m, isbanded.m, onenormest.m, edit.m, fullfile.m, license.m, ode23.m, ode45.m, glpk.m, annotation.m, legend.m, orient.m, text.m, area.m, barh.m, contour.m, line.m, plot.m, plot3.m, plotyy.m, quiver.m, stem.m, clf.m, copyobj.m, findobj.m, subplot.m, ppval.m, splinefit.m, ismember.m, freqz.m, unwrap.m, eigs.m, ichol.m, pcg.m, spdiags.m, svds.m, magic.m, lscov.m, median.m, ols.m, dec2base.m, strsplit.m, strtok.m, test.m, bug-31371.tst, bug-36025.tst, bug-44940.tst, build-sparse-tests.sh, class-concat.tst, classdef.tst, classes.tst, colormaps.tst, command.tst, ctor-vs-method.tst, error.tst, fcn-handle-derived-resolution.tst, for.tst, index.tst, io.tst, jit.tst, null-assign.tst, parser.tst, struct.tst, system.tst: Add semicolons to terminate code in %! blocks.
author Rik <rik@octave.org>
date Fri, 01 Apr 2016 16:03:29 -0700
parents 3d60ed163b70
children ffad2baa90f7
line wrap: on
line source

## Copyright (C) 2012-2015 John W. Eaton
##
## 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
## <http://www.gnu.org/licenses/>.

## -*- texinfo -*-
## @deftypefn  {} {@var{h} =} waitbar (@var{frac})
## @deftypefnx {} {@var{h} =} waitbar (@var{frac}, @var{msg})
## @deftypefnx {} {@var{h} =} waitbar (@dots{}, "createcancelbtn", @var{fcn}, @dots{})
## @deftypefnx {} {@var{h} =} waitbar (@dots{}, @var{prop}, @var{val}, @dots{})
## @deftypefnx {} {} waitbar (@var{frac})
## @deftypefnx {} {} waitbar (@var{frac}, @var{hwbar})
## @deftypefnx {} {} waitbar (@var{frac}, @var{hwbar}, @var{msg})
## Return a handle @var{h} to a new waitbar object.
##
## The waitbar is filled to fraction @var{frac} which must be in the range
## [0, 1].
##
## The optional message @var{msg} is centered and displayed above the waitbar.
##
## A cancel button can be added to the bottom of the waitbar using the
## @qcode{"createcancelbtn"} property of waitbar figures.  The action to be
## executed when the user presses the button is specified using a string or
## function handle @var{fcn}.
##
## The appearance of the waitbar figure window can be configured by passing
## @var{prop}/@var{val} pairs to the function.
##
## When called with a single input the current waitbar, if it exists, is
## updated to the new value @var{frac}.  If there are multiple outstanding
## waitbars they can be updated individually by passing the handle @var{hwbar}
## of the specific waitbar to modify.
## @end deftypefn

## Author: jwe

function h = waitbar (varargin)

  persistent curr_waitbar;

  if (nargin < 1)
    print_usage ();
  endif

  frac = varargin{1};
  varargin(1) = [];

  if (! (isnumeric (frac) && isscalar (frac) && frac >= 0 && frac <= 1))
    error ("waitbar: FRAC must be between 0 and 1");
  endif

  ## Use existing waitbar if it still points to a valid graphics handle.
  if (nargin == 1 && ishandle (curr_waitbar))
    hf = curr_waitbar;
  else
    hf = false;
  endif

  if (! isempty (varargin) && isnumeric (varargin{1}))
    hf = varargin{1};
    varargin(1) = [];
    if (! isfigure (hf) || ! strcmp (get (hf, "tag"), "waitbar"))
      error ("waitbar: H must be a handle to a waitbar object");
    endif
  endif

  msg = false;

  if (! isempty (varargin))
    msg = varargin{1};
    varargin(1) = [];
    if (! (ischar (msg) || iscellstr (msg)))
      error ("waitbar: MSG must be a character string or cell array of strings");
    endif
  endif

  if (rem (numel (varargin), 2) != 0)
    error ("waitbar: invalid number of property/value pairs");
  endif

  if (hf)
    gd = get (hf, "__guidata__");
    ## Get the cached handles.
    ax = gd(1);
    hp = gd(2);

    set (hp, "xdata", [0; frac; frac; 0]);

    if (ischar (msg) || iscellstr (msg))
      th = get (ax, "title");
      curr_msg = get (th, "string");
      ## graphics handles always store data as column vectors
      if (iscellstr (msg))
        msg = msg(:);
      endif
      cmp = strcmp (msg, curr_msg);
      if (! all (cmp(:)))
        set (th, "string", msg);
      endif
    endif
  else
    ## Save and restore current figure
    cf = get (0, "currentfigure");

    hf = figure ("units", "pixels",
                 "position", [250, 500, 400, 100],
                 "numbertitle", "off",
                 "menubar", "none", "toolbar", "none",
                 "integerhandle", "off",
                 "handlevisibility", "callback",
                 "tag", "waitbar");

    ax = axes ("parent", hf,
               "xtick", [], "ytick", [],
               "xlim", [0, 1], "ylim", [0, 1],
               "position", [0.1, 0.3, 0.8, 0.2]);

    ## Add createcancelbtn property
    addproperty ("createcancelbtn", hf, "figurebuttondownfcn");
    addlistener (hf, "createcancelbtn", {@updatecancelbutton, ax});

    if (! isempty (varargin))
      set (hf, varargin{:});
    endif

    hp = patch (ax, [0; frac; frac; 0], [0; 0; 1; 1], [0, 0.35, 0.75]);

    ## Cache the axes and patch handles.
    set (hf, "__guidata__", [ax hp]);

    if (! (ischar (msg) || iscellstr (msg)))
      msg = "Please wait...";
    endif
    title (ax, msg);

    set (0, "currentfigure", cf);
  endif

  drawnow ();

  if (nargout > 0)
    h = hf;
  endif

  ## If there were no errors, update current waitbar.
  curr_waitbar = hf;

endfunction

function updatecancelbutton (hf, dummy, hax)
  if (! strcmpi (get (hf, "__graphics_toolkit__"), "qt"))
    return
  endif

  hbtn = findobj (hf, "type", "uicontrol", "-and", "style", "pushbutton");
  cb = get (hf, "createcancelbtn");
  if (! isempty (cb))
    if (isempty (hbtn))
      units = get (hax, "units");
      fpos = get (hf, "position");
      set (hax, "units", "pixels");
      apos = get (hax, "position");

      fpos (2) -= 40;
      fpos (4) += 40;
      apos (2) += 40;
      set (hf, "position", fpos);
      set (hax, "position", apos, "units", units);

      hbtn = uicontrol ("style", "pushbutton", "string", "Cancel", ...
                        "position", [fpos(3)-100 10 60 25],...
                        "callback", cb, "parent", hf);
    else
      set (hbtn, "callback", cb);
    endif
  elseif (! isempty (hbtn))
    delete (hbtn);
    units = get (hax, "units");
    fpos = get (hf, "position");
    set (hax, "units", "pixels");
    apos = get (hax, "position");

    fpos (2) += 40;
    fpos (4) -= 40;
    apos (2) -= 40;
    set (hf, "position", fpos);
    set (hax, "position", apos, "units", units);
  endif
endfunction


%!demo
%! h = waitbar (0, '0.00%');
%! for i = 0:0.01:1
%!   waitbar (i, h, sprintf ('%.2f%%', 100*i));
%! end
%! close (h);

%!demo
%! h = waitbar (0, 'please wait...');
%! for i = 0:0.01:0.6
%!   waitbar (i);
%! end
%! i = 0.3;
%! waitbar (i, h, 'don''t you hate taking a step backward?');
%! pause (0.5);
%! for i = i:0.005:0.7
%!   waitbar (i, h);
%! end
%! waitbar (i, h, 'or stalling?');
%! pause (1);
%! for i = i:0.003:0.8
%!   waitbar (i, h, 'just a little longer now');
%! end
%! for i = i:0.001:1
%!   waitbar (i, h, 'please don''t be impatient');
%! end
%! close (h);

%!demo
%! h1 = waitbar (0, 'Waitbar #1');
%! h2 = waitbar (0, 'Waitbar #2');
%! h2pos = get (h2, 'position');
%! h2pos(1) = h2pos(1) + (h2pos(3) + 50);
%! set (h2, 'position', h2pos);
%! pause (0.5);
%! for i = 1:4
%!   waitbar (i/4, h1);
%!   pause (0.5);
%!   waitbar (i/4, h2);
%!   pause (0.5);
%! end
%! pause (0.5);
%! close (h1);
%! close (h2);

%!demo
%! clf ();
%! niter = 9;
%! l = 1;
%! xx = [0 l];
%! yy = [0 0];
%! hli = plot (xx, yy);
%!
%! disp ("Push the cancel to stop the process.");
%! hf = waitbar(0,"0","Name","Building Koch curve ...",...
%!              "createcancelbtn", "setappdata (gcbf,'interrupt', true)");
%! for ii = 1:niter
%!   ## Check cancel request
%!   if (! ishandle (hf))
%!     break;
%!   elseif (getappdata (hf, "interrupt"))
%!     delete (hf);
%!     break;
%!   else
%!     waitbar (ii/niter, hf, sprintf ("Step %d/%d", ii, niter));
%!   endif
%!
%!   ## Increasingly lengthy computation
%!   l /= 3;
%!   theta = angle (complex (diff (xx), diff (yy)));
%!
%!   xy = @(th, x0, y0) [cos(th) -sin(th) x0
%!                       sin(th) cos(th) y0] * [0 l l*3/2      2*l;
%!                                              0 0 l*(3)^.5/2 0;
%!                                              1 1 1          1];
%!   tmp = arrayfun (xy, theta, xx(1:end-1), yy(1:end-1),
%!                  "uniformoutput", false);
%!
%!   tmp = cell2mat (tmp);
%!   xx = [tmp(1,:) xx(end)];
%!   yy = [tmp(2,:) yy(end)];
%!   set (hli, "xdata", xx, "ydata", yy);
%!   drawnow ();
%!   pause (0.5);
%! endfor
%!
%! if (ishandle (hf))
%!   delete (hf);
%! endif

## Test input validation
%!error <FRAC must be between 0 and 1> waitbar (-0.5)
%!error <FRAC must be between 0 and 1> waitbar (1.5)
%!error <MSG must be a character string> waitbar (0.5, struct ())
%!error <invalid number of property/value pairs> waitbar (0.5, "msg", "Name")