IconAnimateCmdImpl.mesa
Copyright Ó 1988, 1991, 1992 by Xerox Corporation. All rights reserved.
Bloomenthal, September 24, 1989 11:41:17 am PDT
Kenneth A. Pier, May 24, 1991 5:37 pm PDT
DIRECTORY Args, Commander, Containers, FS, Icons, Process, Real, Rope, ViewerClasses, ViewerOps;
IconAnimateCmdImpl: CEDAR PROGRAM
IMPORTS Args, Commander, Containers, FS, Icons, Process, Real, ViewerOps
~ BEGIN
Data: TYPE ~ RECORD [
v:    ViewerClasses.Viewer,
icons:   ARRAY [0..100) OF Icons.IconFlavor, -- the icons
pause:   INT ¬ 2000,        -- milliSeconds to pause after a cycle
delay:   NAT ¬ 100,        -- milliSeconds delay between each icon
first:   NAT ¬ 0,         -- first icon
last:    NAT ¬ 0,         -- last icon
bounce:  BOOL ¬ FALSE,       -- forwards/backwards?
forward:  BOOL ¬ TRUE       -- current direction
];
IconAnimateCmd: Commander.CommandProc ~ {
iconsA, bounceA, pauseA, delayA, frameA, firstA, lastA: Args.Arg;
[iconsA, pauseA, delayA, bounceA, frameA, firstA, lastA] ¬
Args.ArgsGet[cmd, "%s-pause%r-speed%r-bounce%b-frame%i-first%i-last%i"
! Args.Error => {msg ¬ reason; CONTINUE}];
IF msg # NIL
THEN RETURN[$Failure, msg]
ELSE TRUSTED {
d: REF Data ¬ NEW[Data];
FOR i: NAT IN [0..100) DO
d.icons[i] ¬ Icons.NewIconFromFile[iconsA.rope, i ! FS.Error => GOTO Bad];
IF d.icons[i] = LOOPHOLE[177777B] THEN EXIT;
d.last ¬ i+1;
ENDLOOP;
IF pauseA.ok THEN d.pause ¬ Real.Round[1000.0*pauseA.real];
IF firstA.ok THEN d.first ¬ firstA.int;
IF lastA.ok THEN d.last ¬ MIN[lastA.int, d.last];
IF bounceA.ok THEN d.bounce ¬ bounceA.bool;
IF delayA.ok AND delayA.real # 0.0 THEN d.delay ¬ Real.Round[100/delayA.real];
d.v ¬ Containers.Create[info: [name: "Icon View", iconic: TRUE]];
IF frameA.ok
THEN Paint[d, frameA.int]
ELSE TRUSTED {Process.Detach[FORK CycleIcon[d]]};
};
EXITS Bad => RETURN[$Failure, "Can't find the icon file"];
};
Paint: PROC [d: REF Data, i: INT] ~ {
d.v.icon ¬ d.icons[i];
ViewerOps.PaintViewer[d.v, all];
Process.Pause[Process.MsecToTicks[d.delay]];
};
CycleIcon: PROC [d: REF Data] ~ {
d.v.icon ¬ d.icons[0];
WHILE NOT d.v.destroyed DO
IF d.forward
THEN FOR i: INT IN [d.first..d.last) DO IF d.v.iconic THEN Paint[d, i]; ENDLOOP
ELSE FOR i:INT DECREASING IN [d.first..d.last) DO IF d.v.iconic THEN Paint[d,i]; ENDLOOP;
IF d.bounce THEN d.forward ¬ NOT d.forward;
Process.Pause[Process.MsecToTicks[d.pause]];
ENDLOOP;
};
usage: Rope.ROPE ¬ "
Usage: IconAnimate <Icon FileName> [-option]
 Options include:
  -pause <seconds: real> (default: 2)
  -speed <real> (default: 1)
  -first <first animation frame: integer> (default: 0)
  -last <last animation frame: integer> (default: last)
  -bounce (forward-backward-forward-etc.)";
ViewerOps.RegisterViewerClass[$IconAnimate, NEW[ViewerClasses.ViewerClassRec ¬ []]];
Commander.Register["IconAnimate", IconAnimateCmd, usage];
END.