summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/interactiveanimation
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/interactiveanimation
Initial commit
Diffstat (limited to 'macros/latex/contrib/interactiveanimation')
-rw-r--r--macros/latex/contrib/interactiveanimation/README84
-rwxr-xr-xmacros/latex/contrib/interactiveanimation/clock.pdf.gzbin0 -> 2134215 bytes
-rw-r--r--macros/latex/contrib/interactiveanimation/interactiveanimation.pdfbin0 -> 2741144 bytes
-rw-r--r--macros/latex/contrib/interactiveanimation/interactiveanimation.sty596
-rwxr-xr-xmacros/latex/contrib/interactiveanimation/interactiveanimation.tex208
-rw-r--r--macros/latex/contrib/interactiveanimation/javascript/DocLevel.js417
6 files changed, 1305 insertions, 0 deletions
diff --git a/macros/latex/contrib/interactiveanimation/README b/macros/latex/contrib/interactiveanimation/README
new file mode 100644
index 0000000000..81b9763a09
--- /dev/null
+++ b/macros/latex/contrib/interactiveanimation/README
@@ -0,0 +1,84 @@
+The interactiveanimation Package
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+Authors:
+
+ Luis González <luisg123v@gmail.com>,
+ Javier Toro <javier.toro@dct.com.ve>,
+ Pedro Linares <plinares@uc.edu.ve>
+
+
+Description:
+
+ This package provides an interface to create Portable Document Format
+ (PDF) files with branching animations. Animations are built up as a set
+ of concatenated interactive frames. Each interactive frame can be set
+ to display an image and a set of buttons that allows the course of
+ the overall animation to be controlled by the user. Buttons can be
+ configured to transfer the action focus to another interactive frame
+ and to display an animated image sequence before the forthcoming
+ frame is displayed.
+
+ By now, the only supported way for compiling using this package is by
+ producing the PDF file with pdfTeX.
+
+ The final PDF can be viewed in current Adobe Readers on all supported
+ platforms as long as they have JavaScript support.
+
+ Note: this file only gives a summary of usage and available button
+ options. Please refer to the documentation `interactiveanimation.pdf'
+ for details and examples.
+
+Keywords:
+ build button controllable animationbranching
+ animation LaTeX pdfLaTeX JavaScript Adobe Reader
+
+
+Usage:
+
+ \usepackage{interactiveanimation}
+
+
+ \begin{animation}{<width>}{<height>}
+ \begin{aframe}{<frame name>}{<image file>[,<file page>]}
+ \controlbutton[<sequence file>,<start page>[,<end page>]]
+ {<caption>}{<target frame>}{<button options>}
+ ... other buttons
+ \end{aframe}
+ ... other frames
+ \end{animation}
+
+ * Button options: X=<coordinate> | start | center | end,
+ Y=<coordinate> | start | center | end,
+ position=left | right | above | below | center | from,
+ width=<width>, height=<height>, scale=<factor>,
+ span=<milliseconds>, transparent, hidden, keep
+
+
+Requirements:
+
+ pdfTeX, version 1.20
+ Adobe Reader, version 6
+
+
+Installation:
+
+ Unzip the file `interactiveanimation.zip' and copy the file
+ `interactiveanimation.sty' and the folder `javascript' in a place
+ where LaTeX can find them.
+
+ MiKTeX users should run the package manager for installation.
+
+
+License:
+
+ This material is subject to the LaTeX Project Public License. See
+
+ http://www.ctan.org/tex-archive/help/Catalogue/licenses.lppl.html
+
+ for the details of that license.
+
+Thanks to:
+ * University: Universidad de Carabobo (http://uc.edu.ve/)
+ * Company: DCT (http://www.dct.com.ve/)
diff --git a/macros/latex/contrib/interactiveanimation/clock.pdf.gz b/macros/latex/contrib/interactiveanimation/clock.pdf.gz
new file mode 100755
index 0000000000..441871e29d
--- /dev/null
+++ b/macros/latex/contrib/interactiveanimation/clock.pdf.gz
Binary files differ
diff --git a/macros/latex/contrib/interactiveanimation/interactiveanimation.pdf b/macros/latex/contrib/interactiveanimation/interactiveanimation.pdf
new file mode 100644
index 0000000000..f63e943791
--- /dev/null
+++ b/macros/latex/contrib/interactiveanimation/interactiveanimation.pdf
Binary files differ
diff --git a/macros/latex/contrib/interactiveanimation/interactiveanimation.sty b/macros/latex/contrib/interactiveanimation/interactiveanimation.sty
new file mode 100644
index 0000000000..c53d28d7b6
--- /dev/null
+++ b/macros/latex/contrib/interactiveanimation/interactiveanimation.sty
@@ -0,0 +1,596 @@
+% File `interactiveanimation.sty'
+
+% Copyright 2012--2013 Luis González, Javier Toro, Pedro Linares
+
+% This material is subject to the LaTeX Project Public License. See
+% http://www.ctan.org/tex-archive/help/Catalogue/licenses.lppl.html
+% for the details of that license.
+
+% This package provides an interface to create Portable Document
+% Format (PDF) files with branching and button controllable
+% animations.
+
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{interactiveanimation}[2013/05/21]
+
+% Check if pdfTeX is running in PDF mode
+\RequirePackage{ifpdf}
+\ifpdf
+\else
+ \PackageWarningNoLine{interactiveanimation}{%
+ Loading aborted, because pdfTeX is not running in PDF mode%
+ }%
+ \expandafter\endinput
+\fi
+\RequirePackage{keyval}
+
+% Package options
+\DeclareOption*{%
+ \PackageWarning{interactiveanimation}{%
+ Unknown option `\CurrentOption'}}
+\ProcessOptions\relax
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% String and Integer Variables %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\def\inta@JSFile{javascript/DocLevel.js}% The name of JavaScript file
+\def\inta@JSCode{}% JavaScript code that will be executed at first level
+\def\inta@appearanceNames{}% Unique names for inserted images
+\def\inta@fields{}% PDF fields array
+\def\inta@buttonActions{}% Actions to be performed when a button is pressed
+\newcount\inta@numanims\inta@numanims=0% Number of inserted animation widgets
+\newcount\inta@numframes\inta@numframes=0% Number of inserted animation frames
+\newcount\inta@numbuttons\inta@numbuttons=0% Number of inserted control buttons
+\newcount\inta@numimages\inta@numimages=0% Number of inserted external images
+\newif\ifinta@animation\inta@animationfalse% Flag to check if is inside of an animation
+\newif\ifinta@aframe\inta@aframefalse% Flag to check if is inside of an aframe
+\newcount\inta@notequal
+\newcount\inta@I
+\newcount\inta@loopStart
+\newcount\inta@loopEnd
+\newcount\inta@step
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Internal Helper Functions %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% inserts string #2 at the end of #1
+\def\inta@concat#1#2{%
+ \expandafter\xdef
+ \csname inta@#1\endcsname
+ {\csname inta@#1\endcsname#2}
+}
+
+% add JavaScript code to te code that is being built
+\def\inta@addJS#1{%
+ \inta@concat{JSCode}{#1}
+}
+
+% Add a field to the fields array
+\def\inta@addField{
+ \inta@concat{fields}{\the\pdflastannot\space 0 R }
+}
+
+% add appearance name for an inserted image; #1: name, #2: reference number
+\def\inta@addAP#1#2{
+ \inta@concat{appearanceNames}{ (#1) \the#2 0 R }
+}
+
+% Insert an action given in #2 for a button given in #1
+\def\inta@addAction#1#2{%
+ \inta@concat{buttonActions}{#1=#2,}
+}
+
+% Tests if argument is a non-negative number
+\def\inta@isNumber#1{%
+ \ifnum9<1#1\space% Non-negative number
+ 1%
+ \else% Negative or invalid number
+ 0%
+ \fi
+}
+
+% Check if a string is empty or only contains spaces
+\def\inta@isEmpty#1{%
+ \ifnum\pdfstrcmp{#1}{\space}=0
+ 1
+ \else\ifnum\pdfstrcmp{#1}{\space\space}=0
+ 1
+ \else\ifnum\pdfstrcmp{#1}{\@empty}=0
+ 1
+ \else
+ 0
+ \fi\fi\fi
+}
+
+% Extract option and argument from expression option=argument
+\def\inta@extractOptArg#1=#2\relax{%
+ \xdef\inta@opt{#1}
+ \xdef\inta@arg{#2}
+}
+
+% Removes spaces at the beginning of a string
+\def\inta@removeSpaces#1{%
+ \if\space#1\else
+ #1\fi
+}
+
+% Transform a number in a three digits number filling with zeros
+\def\inta@threeDigits#1{%
+ \ifnum#1<10
+ 00%
+ \else\ifnum#1<100
+ 0%
+ \fi\fi
+ \the#1%
+}
+
+% Insert an object given in #2 into the PDF and saves its reference in #1
+\def\inta@insertObject#1#2{%
+ \immediate\pdfobj{#2}%
+ \expandafter\xdef
+ \csname inta@obj:#1\endcsname
+ {\the\pdflastobj \space 0 R}
+}
+
+% Insert an external image and saves its name in \inta@imageName. #1: file name, #2: page
+\def\inta@insertImage#1#2{
+ % Cheks if name and page are valid
+ \edef\inta@filePage{#2}
+ \IfFileExists{#1}%
+ {
+ \ifnum\inta@isEmpty{#2}=1 % if filePage not specified, first one is silently assumed
+ \def\inta@filePage{1}
+ \else\ifnum\inta@isNumber{#2}=0 % Not a valid number
+ \PackageError{interactiveanimation}{%
+ `#2' of file `\inta@fileName' is not a valid page number%
+ }{
+ A page number must be a positive integer
+ }
+ \def\inta@filePage{1}
+ \else\ifnum#2=0 % Zero-based numbering page
+ \PackageWarning{interactiveanimation}{%
+ Page numbers starts in number one%
+ \MessageBreak%
+ Page number 1 (first page) was assumed.%
+ }
+ \def\inta@filePage{1}
+ \fi\fi\fi
+ \@ifundefined{inta@img:#1,\inta@filePage}% Only inserts if was not previously inserted
+ {
+ \immediate\pdfximage%
+ page \inta@filePage {#1}
+ \expandafter\xdef
+ \csname inta@img:#1,\inta@filePage\endcsname
+ {image\inta@threeDigits{\inta@numimages}}
+ \inta@addAP%
+ {image\inta@threeDigits{\inta@numimages}}%
+ {\pdflastximage}
+ \global\advance\inta@numimages by 1
+ }{
+ }
+ \xdef\inta@imageName{%
+ \csname inta@img:#1,\inta@filePage\endcsname}
+ }{% File is invalid or not specified
+ \ifnum\inta@isEmpty{\inta@fileName}=0% Specified but invalid
+ \PackageError{interactiveanimation}{%
+ Could not find file `\inta@fileName'%
+ }
+ {}
+ \fi
+ }
+}
+
+% Refer an object previowsly inserted using \inta@insertObject
+\def\inta@refObj#1{%
+ \csname inta@obj:#1\endcsname}
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Initial PDF Setups %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% An AcroForm dictionary is inserted in the catalog,
+% containing the Fields array
+\pdfobj reserveobjnum
+\newcount\inta@fieldsnum
+\inta@fieldsnum=\pdflastobj
+\pdfcatalog{%
+ /AcroForm <<
+ /Fields \the\inta@fieldsnum\space 0 R
+ /NeedAppearances true
+ >>
+}
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Command and Environment Definitions %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Inserts an animation widget
+\newcount\inta@animationWidth\newcount\inta@animationHeight
+\newdimen\inta@dimen\inta@dimen=0pt% Auxiliar dimension
+\newenvironment{animation}[2]{% Two arguments: width and height
+ \ifinta@animation% if inside of another animation
+ \PackageError{interactiveanimation}{%
+ You can not define an animation inside%
+ \MessageBreak%
+ another one.
+ }
+ {}
+ \fi
+ \inta@animationtrue
+ \xdef\inta@animationName{animation\the\inta@numanims}
+ \inta@dimen=#1% Avoid printing measure, e.g. `pt'
+ \divide\inta@dimen by 65536% Converts to pt
+ \global\inta@animationWidth=\inta@dimen% store width
+ \inta@dimen=#2
+ \divide\inta@dimen by 65536
+ \global\inta@animationHeight=\inta@dimen
+ \strut\vskip #2% Displaying of widget start from lower left corner
+
+ % inserts a dummy widget for reserving its dimentions and position
+ \hbox{\pdfannot
+ width #1 height #2 {%
+ /Subtype /Widget /FT /Btn
+ /Ff 65536 % Not necessary, but avoids some warnings
+ /T (\inta@animationName)
+ }}
+ \inta@addField
+
+ \inta@addJS{
+ var \inta@animationName = extendField(this.getField("\inta@animationName"));
+ }
+}%
+{
+ \inta@animationfalse
+ \inta@addJS{\inta@animationName.displayFirstFrame();}
+
+ % Process button's actions
+ \@for \inta@tmp :=\inta@buttonActions\do%
+ {
+ \ifnum\pdfmatch{=}{\inta@tmp}=1\relax% Is an action
+ \expandafter\inta@extractOptArg\inta@tmp\relax
+ \def\inta@buttonName{\inta@opt}
+
+ % Action = previous frame
+ \ifnum\pdfstrcmp{previous}{\inta@arg}=0
+ \inta@addJS{
+ \inta@buttonName.targetAction = function()
+ { \inta@animationName.displayPreviousFrame(); };
+ }
+
+ % Action = next frame
+ \else\ifnum\pdfstrcmp{next}{\inta@arg}=0
+ \inta@addJS{
+ \inta@buttonName.targetAction = function()
+ { \inta@animationName.displayNextFrame(); };
+ }
+
+ % Action = first frame
+ \else\ifnum\pdfstrcmp{first}{\inta@arg}=0
+ \inta@addJS{
+ \inta@buttonName.targetAction = function()
+ { \inta@animationName.displayFirstFrame(); };
+ }
+
+ % Action = last frame
+ \else\ifnum\pdfstrcmp{last}{\inta@arg}=0
+ \inta@addJS{
+ \inta@buttonName.targetAction = function()
+ { \inta@animationName.displayLastFrame(); };
+ }
+
+ % Action = given frame name
+ \else\@ifundefined{inta@frm:\inta@arg}% undefined frame name
+ {
+ \PackageError{interactiveanimation}{%
+ There is no frame named `\inta@arg'%
+ }{%
+ Please specify a valid frame name%
+ Or use: `previous', `next', `first' or `last'}
+ }{
+ \def\inta@frameNumber{\csname inta@frm:\inta@arg\endcsname}
+ \inta@addJS{
+ \inta@buttonName.targetAction = function()
+ { \inta@animationName.displayFrame("frame\inta@frameNumber");};
+ }
+ }\fi\fi\fi\fi
+ \fi
+ }
+ \global\advance\inta@numanims by 1
+ \gdef\inta@buttonActions{}% It is cleared just in case it will be used again
+}
+
+% Inserts a frame to be displayed by the animation widget
+\newenvironment{aframe}[2]{% Two arguments: frame name and image
+ \ifinta@animation\else% if outside an animation
+ \PackageError{interactiveanimation}{%
+ You can not define an aframe outside%
+ \MessageBreak%
+ an animation.
+ }
+ {}
+ \fi
+ \ifinta@aframe% if inside another aframe
+ \PackageError{interactiveanimation}{%
+ You can not define an aframe inside%
+ \MessageBreak%
+ another one.
+ }
+ {}
+ \fi
+
+ \inta@aframetrue
+ \xdef\inta@frameName{frame\the\inta@numframes}
+ \vskip-\baselineskip
+
+ \hbox{\pdfannot{%
+ /Subtype /Widget /FT /Btn
+ /Ff 65537% No user interaction
+ /T (\inta@frameName)
+ /BS << /W 0 >>% No border is drawn
+ /MK << /BG [1]% White background color
+ /IF << /S /A >> % Non-proportional scaling
+ /TP 1 >>% Only image, no text caption
+ }}
+ \inta@addField
+
+ \inta@addJS{%
+ var \inta@frameName = extendField(this.getField("\inta@frameName"));
+ \inta@animationName.addFrame(\inta@frameName);
+ }
+
+ % Animation frame image
+ \inta@I=0
+ \gdef\inta@fileName{}\gdef\inta@filePage{}
+ \@for \inta@tmp :=#2\do% Iterates each element in the comma separated list
+ {
+ \ifnum\inta@I=0% File name
+ \edef\inta@fileName{\inta@tmp}
+ \else\ifnum\inta@I=1% File page
+ \edef\inta@filePage{\inta@removeSpaces{\inta@tmp}}
+ \fi\fi
+ \advance\inta@I by 1
+ }
+
+ % Image is inserted, if it is all right associates it with frame
+ \inta@insertImage{\inta@fileName}{\inta@filePage}
+ \ifnum\inta@isEmpty{\inta@imageName}=0
+ \inta@addJS{%
+ \inta@frameName.buttonSetIcon(this.getIcon("\inta@imageName"));
+ \inta@frameName.buttonPosition = position.iconOnly;
+ }
+ \fi
+
+ % Saves number frame for actual frame's name
+ \expandafter\xdef\csname inta@frm:#1\endcsname
+ {\the\inta@numframes}
+ \global\advance\inta@numframes by 1
+}%
+{
+ \inta@aframefalse
+}
+
+% Definitions for keyval needed
+\define@key{inta}{position}{#1}
+
+% option=position
+\define@key{inta}{position}{%
+ % Check if option has a valid argument
+ \ifnum\pdfmatch{#1}{ left right above below center from }=1
+ \inta@addJS{\inta@buttonName .relatPosition = option.#1;}
+ \else% if it is invalid, does not process option and display an error
+ \PackageError{interactiveanimation}{%
+ `#1' is not a valid position.}{%
+ Valid positions are:%
+ \MessageBreak%
+ `left', `right', `above', `below' and `from'}
+ \fi
+}
+% option=X
+\define@key{inta}{X}{%
+ \ifnum\inta@isNumber{#1}=1% if is a non-negative integer
+ % Defines the coordinate depending on the animation width
+ % so the animation can be resized
+ \inta@addJS{%
+ \inta@buttonName.pointX = #1 * \inta@animationName.width / \the\inta@animationWidth;
+ }
+ \else\ifnum\pdfmatch{#1}{ start center end }=1
+ \inta@addJS{\inta@buttonName .positionX = option.#1;}
+ \else% if it is invalid, does not process option and displays an error
+ \PackageError{interactiveanimation}{%
+ `#1' is not a valid X coordinate}{%
+ Valid X coordinate are:%
+ \MessageBreak%
+ A non-negative integer, or `start', `center' or `end'}
+ \fi\fi
+}
+% option=Y
+\define@key{inta}{Y}{%
+ \ifnum\inta@isNumber{#1}=1% if is a non-negative integer
+ \inta@addJS{%
+ \inta@buttonName.pointY = #1 * \inta@animationName.height / \the\inta@animationHeight;
+ }
+ \else\ifnum\pdfmatch{#1}{ start center end }=1
+ \inta@addJS{\inta@buttonName .positionY = option.#1;}
+ \else% if it is invalid, does not process option and displays an error
+ \PackageError{interactiveanimation}{%
+ `#1' is not a valid Y coordinate}{%
+ Valid Y coordinate are:%
+ \MessageBreak%
+ A non-negative integer, or `start', `center' or `end'}
+ \fi\fi
+}
+% option=scale
+\define@key{inta}{scale}[1]{%
+ \inta@addJS{\inta@buttonName.scale(#1);}
+}
+% option=hidden
+\define@key{inta}{hidden}[true]{%
+ \inta@addJS{\inta@buttonName.toggleHidden = true;}
+}
+% option=transparent
+\define@key{inta}{transparent}[true]{%
+ \inta@addJS{ \inta@buttonName.transparent = true;}
+}
+% option=width
+\define@key{inta}{width}{%
+ \inta@addJS{%
+ \inta@buttonName.width = #1 * \inta@animationName.width / \the\inta@animationWidth;
+ }
+}
+% option=height
+\define@key{inta}{height}{%
+ \inta@addJS{%
+ \inta@buttonName.height = #1 * \inta@animationName.height / \the\inta@animationHeight;
+ }
+}
+% option=span
+\define@key{inta}{span}[1000]{%
+ \inta@addJS{\inta@buttonName.timeSpan = #1;}
+}
+% option=keep
+\define@key{inta}{keep}[true]{%
+ \inta@addJS{\inta@buttonName.keep = true;}
+}
+
+% Insert a button for interacting with the animation
+\newdimen\inta@buttonWidth
+\newcommand{\controlbutton}[4][]{% Four arguments: [animation], button's caption, destination frame and specification in a comma separated list
+ \ifinta@animation\else% if outside an animation
+ \PackageError{interactiveanimation}{%
+ You cannot define a control button%
+ \MessageBreak%
+ outside an animation.
+ }
+ {}
+ \fi
+ \edef\inta@buttonName{button\the\inta@numbuttons}
+ \setbox0=\hbox{ #2 \strut}
+ \inta@buttonWidth=\wd0
+ \vskip-\baselineskip
+
+ % Button is inserted
+ \hbox{\pdfannot
+ width \inta@buttonWidth{%
+ /Subtype /Widget /FT /Btn% Button field
+ /Ff 65536% Push button type
+ /T (\inta@buttonName)% Button's name, accessible from JavaScript
+ /BS << /S /B >>% Beveled border style
+ /MK << /BG [0.6]% 60% white background color
+ /CA (#2) >>% Caption
+ /H /P% Push highlighting mode
+ /A << /S /JavaScript /JS (% JavaScript action to be performed
+ \inta@buttonName.buttonAction();
+ ) >>
+ }\strut}
+ \inta@addField
+
+ \inta@addJS{
+ var \inta@buttonName = extendField(this.getField("\inta@buttonName"));
+ \inta@buttonName.images = new Array();
+ }
+
+ % If present, button's action is stored and will be processed at end of animation environment
+ \ifnum\inta@isEmpty{#3}=0
+ \inta@addAction{\inta@buttonName}{#3}
+ \else
+ \inta@addJS{
+ \inta@buttonName.targetAction = function()
+ { \inta@animationName.displayFrame("\inta@frameName");};
+ }
+ \fi
+
+ % Button's options are processed
+ \setkeys{inta}{#4}
+
+ % Button's image sequence is processed
+ \def\inta@rangeStart{}\def\inta@rangeEnd{}
+ \def\inta@fileName{}
+ \inta@I=0
+ \@for \inta@tmp :=#1\do
+ {
+ \ifnum\inta@I=0% File name
+ \edef\inta@fileName{\inta@tmp}
+ \else\ifnum\inta@I=1% Start range
+ \edef\inta@rangeStart{\inta@removeSpaces{\inta@tmp}}
+ \else\ifnum\inta@I=2% End range
+ \edef\inta@rangeEnd{\inta@removeSpaces{\inta@tmp}}
+ \fi\fi\fi
+ \advance\inta@I by 1
+ }
+ % Check if ranges are specified and valid
+ \ifnum\inta@isEmpty{\inta@fileName}=0
+ \ifnum\inta@isEmpty{\inta@rangeStart}=1
+ \def\inta@rangeStart{1}
+ \def\inta@rangeEnd{1}
+ \else\ifnum\inta@isNumber{\inta@rangeStart}=0
+ %\inta@insertImage will display the appropriate error
+ \inta@insertImage{\inta@fileName}{\inta@rangeStart}
+ \def\inta@rangeStart{1}
+ \def\inta@rangeEnd{1}
+ \fi\fi
+ \ifnum\inta@isEmpty{\inta@rangeEnd}=1% if only one number was given, set range to (1,number)
+ \edef\inta@rangeEnd{\inta@rangeStart}
+ \def\inta@rangeStart{1}
+ \else\ifnum\inta@isNumber{\inta@rangeEnd}=0
+ %\inta@insertImage will display the appropriate error
+ \inta@insertImage{\inta@fileName}{\inta@rangeEnd}
+ \edef\inta@rangeEnd{\inta@rangeStart}
+ \def\inta@rangeStart{1}
+ \fi\fi\fi
+
+ % If was given an animation action for the button, all animation frames are inserted
+ \ifnum\inta@isEmpty{\inta@fileName}=0
+ \inta@notequal=1% End loop flag
+ \inta@loopStart=\inta@rangeStart
+ \inta@loopEnd=\inta@rangeEnd\relax
+ \ifnum\inta@loopStart>\inta@loopEnd% Descending order
+ \inta@step=-1
+ \else
+ \inta@step=1
+ \fi
+ \inta@I=\inta@loopStart\loop
+ \inta@insertImage{\inta@fileName}{\the\inta@I}
+ \inta@addJS{
+ \inta@buttonName.addImage("\inta@imageName"); }
+ \ifnum\inta@I=\inta@loopEnd
+ \inta@notequal=0% Ends loop
+ \fi
+ \advance\inta@I by \inta@step
+ \ifnum\inta@notequal=1\repeat
+ \fi
+
+ \inta@addJS{\inta@frameName.addButton(\inta@buttonName);}
+ \global\advance\inta@numbuttons by 1
+}
+
+% JavaScript code is inserted into the PDF
+\input\inta@JSFile\relax
+\AtEndDocument{\inta@insertObject{JavaScript}{
+ << /S /JavaScript /JS (
+ \inta@JSCode
+ ) >>
+}}
+
+% A reference to the JavaScript code is inserted intho the names dictionary,
+% so the JavaScript actions perform when the document is opened
+\AtEndDocument{\pdfnames{
+ /JavaScript <<
+ /Names [ (interactiveanimation) \inta@refObj{JavaScript} ] >>
+}}
+
+% Appearance names dictionary is inserted into the names dictionary,%
+% so it is posible accessing inserted images from JavaScript
+\AtEndDocument{\pdfnames{
+ /AP <<
+ /Names [\inta@appearanceNames] >>
+}}
+
+% Array fields is inserted
+\AtEndDocument{\immediate\pdfobj useobjnum \inta@fieldsnum {%
+ [\inta@fields]%
+}}
+
diff --git a/macros/latex/contrib/interactiveanimation/interactiveanimation.tex b/macros/latex/contrib/interactiveanimation/interactiveanimation.tex
new file mode 100755
index 0000000000..35c052de52
--- /dev/null
+++ b/macros/latex/contrib/interactiveanimation/interactiveanimation.tex
@@ -0,0 +1,208 @@
+\documentclass[a4paper,12pt]{article}
+\usepackage[english]{babel}
+\usepackage{interactiveanimation}
+\usepackage{hyperref}
+
+\def\keywords{build button controllable animation branching animation LaTeX pdfLaTeX JavaScript Adobe Reader}
+
+\hypersetup{
+ pdftitle={The interactiveanimation Package},
+ pdfauthor={Luis Gonz\'alez, Javier Toro, Pedro Linares},
+ pdfsubject={Documentation},
+ pdfkeywords={\keywords}
+}
+
+\begin{document}
+\title{The {\sffamily interactiveanimation} Package}
+\author{Luis Gonz\'alez, Javier Toro, Pedro Linares}
+\maketitle
+
+\begin{abstract}\noindent
+A \LaTeX{} package for creating branching and button controllable PDF animations from image files.
+\vskip 0.2\baselineskip
+
+\emph{Keywords}: \keywords
+\end{abstract}
+
+\tableofcontents
+
+%\newpage
+\section{Introduction}
+This package provides an interface to create Portable Document Format (PDF) files with branching animations. Animations are built up as a set of concatenated interactive frames. Each interactive frame can be set to display an image and a set of buttons that allows the course of the overall animation to be controlled by the user. Buttons can be configured to transfer the action focus to another interactive frame and to display an animated image sequence before the forthcoming frame is displayed.
+
+By now, the only supported way for compiling using this package is by producing the PDF file with pdf\TeX{}.
+
+The final PDF can be viewed in current Adobe Readers on all supported platforms as long as they have JavaScript support.
+
+\section{Requirements}
+\begin{trivlist}
+\item pdf\TeX{}, version $\ge1.20$
+\item Adobe Reader, version $\ge6$
+\end{trivlist}
+
+\section{Installation}
+Unzip the file `interactiveanimation.zip' and copy the `interactiveanimation.sty' and the folder `javascript' in a place where \LaTeX{} can find them.
+
+MiK\TeX{} users should run the package manager for installation.
+
+\section{Using the package}
+Invoke the package by putting the line
+\begin{verbatim}
+ \usepackage{interactiveanimation}
+\end{verbatim}
+to the preamble of your document, i.\,e. somewhere between \verb+\documentclass+ and \verb+\begin{document}+.
+
+\section{The user interface}
+Interactive animations are defined using three basic instructions provided by this package:
+\begin{itemize}
+\item The animation is inserted, using the environment \verb+animation+.
+\item Frames are inserted, using the environment \verb+aframe+ inside of \verb+animation+.
+\item Control buttons are inserted, using the command \verb+\controlbutton+ inside \verb+aframe+.
+\end{itemize}
+
+\begin{verbatim}
+\begin{animation}{<width>}{<height>}
+\begin{aframe}{<frame name>}{<image file>[,<file page>]}
+\controlbutton[<sequence file>,<start page>[,<end page>]]
+{<caption>}{<target frame>}{<options>}
+ ... other buttons
+\end{aframe}
+ ... other frames
+\end{animation}
+\end{verbatim}
+
+\subsection{Inserting the animation}
+The \verb+<width>+ and \verb+<height>+ arguments must be given in valid \TeX{} dimensions. Horizontal and vertical dimensions of the animation are scaled independently to fit \verb+<width>+ and \verb+<height>+.
+
+\subsection{Inserting frames}
+If present, argument \verb+<frame name>+ is used in control buttons to identify which frame will be displayed when the button is pressed, so it should be unique in current animation.
+
+\verb+<image file>+ and \verb+<file page>+ specify a page of a PDF file to be displayed as an image by the frame. If \verb+<file page>+ is not specified, first page is assumed; if any image is not specified, a blank frame will be displayed.
+
+\subsection{Inserting control buttons}
+A control button may display, before changing the current frame, a sequence of images. All of those images must be into the same external PDF file. If you want to display a sequence, you should specify the file where images are stored in \verb+<sequence file>+ and the start and end page range in \verb+<start page>+ and \verb+<end page>+, respectively; if only \verb+<start page>+ is given in the range, first page is assumed as range start and the given number as range end. Range may also be decreasing if \verb+<end page>+ is less than \verb+<start page>+.
+
+\verb+<caption>+ gives a text to be displayed by the control button.
+
+\verb+<target frame>+ specifies the name of a frame to be displayed when that control button is pressed, you may also, instead of specifying a frame name, use \verb+first+, \verb+last+, \verb+previous+ or \verb+next+ for first, last, previous and next frame defined into the animation, respectively. If not specified, current frame is assumed.
+
+\verb+<options>+ a comma-separated list that describes the appearance and behavior of the control button. See section below for more details.
+
+\subsubsection{Control button options}
+\begin{verbatim}
+X=<coordinate> | start | center | end
+Y=<coordinate> | start | center | end
+\end{verbatim}
+give X and Y coordinates of a point to take reference for specifying where button's drawing should start (see below). The coordinates should be non-negative integers and represent a point into the animation. Point \verb+X=0,Y=0+ will be the lower left corner.
+
+Instead of given a number, you can also use \verb+start+, \verb+center+ and \verb+end+ to specify the start, center or end (X or Y) coordinates of the animation, respectively. For example, for an animation of $400\times300$, \verb+X=end+ whould be equivalent to \verb+X=400+ and \verb+Y=center+ whould be equivalent to \verb+Y=150+.
+
+Note that \verb+X+ and \verb+Y+ are uppercase, so if you use lowercase it will not work.
+\begin{verbatim}
+position=left | right | above | below | center | from
+\end{verbatim}
+Describes where the button will be positioned relative to the given point. For example, if \verb+position=right+ is specified, the button will be at the right of the given point, if below, it will be below of the point and so on. If \verb+from+ is specified, the point will be the upper left corner of the button.
+
+Note: if \verb+position+ is not specified, the button will be at upper corner of the animation for first button or at right for other buttons. If it is especified but it was not given any point, the reference will be the last inserted button.
+
+\begin{verbatim}
+width=<width>
+height=<height>
+scale=<factor>
+\end{verbatim}
+By default, button's width and height are automatically set to fit button's caption. However, you may also set specific dimensions using those options. If specified, \verb+width+ and \verb+height+'s argument must be a non-negative integer representing a distance in points. In addition, instead of setting manually the dimensions, you may scale automatically fixed dimensions using \verb+scale+; that allows you to increase the size of a button without breaking the proportion; for example, \verb+scale=2+ will multiply width and height by 2.
+\medskip
+\begin{verbatim}
+hidden
+\end{verbatim}
+Makes the button becomes visible only when the mouse is over it and invisible otherwise.
+\begin{verbatim}
+transparent
+\end{verbatim}
+Makes visible only button's caption, the button still being pressable. If you want a fully transparent button, you just should specify a blank caption.
+
+Note: if you want to define a transparent button on the same area of others, make sure to define it before those other buttons so it is not over them to prevent from activating.
+\begin{verbatim}
+span=<milliseconds>
+\end{verbatim}
+If the button has an associated sequence of images, this option sets the time span, in milliseconds, for images change. Default value is \verb+1000+.
+\begin{verbatim}
+keep
+\end{verbatim}
+Keep running the image sequence until frame is pressed.
+
+\section{Examples}
+The following example is an analog clock and consist of four frames. Each frame displays an interval of 15 minutes on the clock and has two buttons to going back and going forward. Before going back and forward, the buttons display a sequence which represents the movement that performs hand of the clock to reach, passing throught every minute between original and destination positions.
+
+The file `clock.pdf', where images are stored, consists of 60 images cor\-re\-spond\-ing with 60 minutes of an our.
+
+\small
+\begin{verbatim}
+\begin{animation}{450 pt}{450 pt}
+ \begin{aframe}{12:00}{clock.pdf,60}
+ \controlbutton[clock.pdf,60,45]{<< Backward}{12:45}{%
+ position=right, X=start, Y=start, span=75}
+ \controlbutton[clock.pdf,1,15]{Forward >>}{12:15}{%
+ position=left, X=end, Y=start, span=75}
+ \end{aframe}
+
+ \begin{aframe}{12:15}{clock.pdf,15}
+ \controlbutton[clock.pdf,15,1]{<< Backward}{12:00}{%
+ position=right, X=start, Y=start, span=75}
+ \controlbutton[clock.pdf,15,30]{Forward >>}{12:30}{%
+ position=left, X=end, Y=start, span=75}
+ \end{aframe}
+
+ \begin{aframe}{12:30}{clock.pdf,30}
+ \controlbutton[clock.pdf,30,15]{<< Backward}{12:15}{%
+ position=right, X=start, Y=start, span=75}
+ \controlbutton[clock.pdf,30,45]{Forward >>}{12:45}{%
+ position=left, X=end, Y=start, span=75}
+ \end{aframe}
+
+ \begin{aframe}{12:45}{clock.pdf,45}
+ \controlbutton[clock.pdf,45,30]{<< Backward}{12:30}{%
+ position=right, X=start, Y=start, span=75}
+ \controlbutton[clock.pdf,45,60]{Forward >>}{12:00}{%
+ position=left, X=end, Y=start, span=75}
+ \end{aframe}
+\end{animation}
+\end{verbatim}
+\normalsize
+
+\newpage
+\begin{animation}{450 pt}{450 pt}
+ \begin{aframe}{12:00}{clock.pdf,60}
+ \controlbutton[clock.pdf,60,45]{<< Backward}{12:45}{%
+ position=right, X=start, Y=start, span=75}
+ \controlbutton[clock.pdf,1,15]{Forward >>}{12:15}{%
+ position=left, X=end, Y=start, span=75}
+ \end{aframe}
+
+ \begin{aframe}{12:15}{clock.pdf,15}
+ \controlbutton[clock.pdf,15,1]{<< Backward}{12:00}{%
+ position=right, X=start, Y=start, span=75}
+ \controlbutton[clock.pdf,15,30]{Forward >>}{12:30}{%
+ position=left, X=end, Y=start, span=75}
+ \end{aframe}
+
+ \begin{aframe}{12:30}{clock.pdf,30}
+ \controlbutton[clock.pdf,30,15]{<< Backward}{12:15}{%
+ position=right, X=start, Y=start, span=75}
+ \controlbutton[clock.pdf,30,45]{Forward >>}{12:45}{%
+ position=left, X=end, Y=start, span=75}
+ \end{aframe}
+
+ \begin{aframe}{12:45}{clock.pdf,45}
+ \controlbutton[clock.pdf,45,30]{<< Backward}{12:30}{%
+ position=right, X=start, Y=start, span=75}
+ \controlbutton[clock.pdf,45,60]{Forward >>}{12:00}{%
+ position=left, X=end, Y=start, span=75}
+ \end{aframe}
+\end{animation}
+
+\section{Known issues}
+
+ When trying to insert an animation with not enought space in current page, the animation will be placed in the next one. However, only the part wich could not fit in previous page will be visible. The simplest solution to solve it is inserting a page skip before the animation, e.\,g. \verb+\newpage+.
+
+\end{document}
diff --git a/macros/latex/contrib/interactiveanimation/javascript/DocLevel.js b/macros/latex/contrib/interactiveanimation/javascript/DocLevel.js
new file mode 100644
index 0000000000..d7d2bac410
--- /dev/null
+++ b/macros/latex/contrib/interactiveanimation/javascript/DocLevel.js
@@ -0,0 +1,417 @@
+% File `DocLevel.js'
+
+% Copyright 2012--2013 Luis González, Javier Toro, Pedro Linares
+
+% This material is subject to the LaTeX Project Public License. See
+% http://www.ctan.org/tex-archive/help/Catalogue/licenses.lppl.html
+% for the details of that license.
+
+\inta@addJS{
+var option = /* option constants */
+{
+ error : 0,
+ left : 1,
+ right : 2,
+ above : 3,
+ below : 4,
+ from : 5,
+ start : 6,
+ center : 7,
+ end : 8
+};
+%
+/* Adds methods and properties to fields to facilitate manipuling them */
+function extendField(field)
+{
+ field.startX = field.rect[0];
+ field.endX = field.rect[2];
+ field.startY = field.rect[1];
+ field.endY = field.rect[3];
+ /* If the coordinates are inverted */
+ if(field.startX > field.endX)
+ {
+ field.startX = field.rect[2];
+ field.endX = field.rect[0];
+ }
+ if(field.startY > field.endY)
+ {
+ field.startY = field.rect[3];
+ field.endY = field.rect[1];
+ }
+ /* width and height are calculated and stored */
+ field.width = field.endX - field.startX;
+ field.height = field.endY - field.startY;
+ /* Central points */
+ field.centerX = field.startX + (field.width / 2);
+ field.centerY = field.startY + (field.height / 2);
+ /* Function to move to a given coordinates */
+ field.moveTo = function(x, y)
+ {
+ field.startX = x;
+ field.startY = y;
+ field.endX = x + field.width;
+ field.endY = y + field.height;
+ field.centerX = field.startX + (field.width / 2);
+ field.centerY = field.startY + (field.height / 2);
+ field.rect = [field.startX, field.startY, field.endX, field.endY];
+ };
+ /* Function to move to the left of a point */
+ field.moveToLeft = function(x, y)
+ { field.moveTo(x - field.width, y - (field.height / 2)); };
+ /* Function to move to the right of a point */
+ field.moveToRight = function(x, y)
+ { field.moveTo(x, y - (field.height / 2)); };
+ /* Function to move above a point */
+ field.moveAbove = function(x, y)
+ { field.moveTo(x - (field.width / 2), y); };
+ /* Function to move below a point */
+ field.moveBelow = function(x, y)
+ { field.moveTo(x - (field.width / 2), y - field.height); };
+ /* Function to move centering on a point */
+ field.moveCenter = function(x, y)
+ { field.moveTo(x - (field.width / 2), y - (field.height / 2)); };
+ /* Function to scale according to a numeric constant */
+ field.scale = function(c)
+ {
+ field.width *= c;
+ field.height *= c;
+ field.moveTo(field.startX, field.startY);
+ field.textSize *= c;
+ };
+%
+ /* Animation frame function - insert a button and place it into frame */
+ field.addButton = function(newButton)
+ {
+ newButton.display = display.hidden; /* Initially, all buttons and frames will be hidden */
+ newButton.parentFrame = field;
+ newButton.originalFillColor = newButton.fillColor;
+ newButton.originalBorderWidth = newButton.borderWidth;
+ newButton.originalPosition = newButton.buttonPosition;
+%
+ /* Optional specifications */
+ if(typeof newButton.transparent != "undefined")
+ {
+ newButton.makeTransparent(true);
+ newButton.setAction( /* transparent buttons should not hold focus */
+ "OnFocus",
+ field.name + ".releaseFocus();"
+ );
+ }
+ else
+ newButton.transparent = false;
+ if(typeof newButton.toggleHidden != "undefined")
+ {
+ newButton.setAction(
+ "MouseEnter",
+ newButton.name + ".makeTransparent(false);"
+ );
+ newButton.setAction(
+ "MouseExit",
+ newButton.name + ".makeTransparent(true);"
+ );
+ }
+ else
+ newButton.toggleHidden = false;
+ if(typeof newButton.timeSpan == "undefined")
+ newButton.timeSpan = 1000; /* Milliseconds */
+ if(typeof newButton.keep == "undefined")
+ newButton.keep = false;
+ field.buttons.push(newButton);
+%
+ /* if it is first button, places it in left upper corner. Otherwise, to the right of previous button */
+ if(typeof newButton.relatPosition == "undefined") /* Position option not specified */
+ {
+ if(field.buttons.length == 1)
+ {
+ newButton.moveTo(field.startX , field.endY - newButton.height);
+ return;
+ }
+ else
+ {
+ newButton.relatPosition = option.right;
+ delete newButton.pointX;
+ delete newButton.pointY;
+ delete newButton.positionX;
+ delete newButton.positionY;
+ }
+ }
+%
+ /**
+ * if it was given an alias instead a coordinate (like start or end)
+ * assigngs its corresponding numeric value to X coordinate
+ */
+ if(typeof newButton.positionX != "undefined")
+ switch(newButton.positionX)
+ {
+ case option.start:
+ newButton.pointX = field.startX;
+ break;
+ case option.center:
+ newButton.pointX = field.centerX;
+ break;
+ case option.end:
+ newButton.pointX = field.endX;
+ break;
+ default:
+ console.println("There was an error processing argument of X coordinate ");
+ console.show();
+ }
+ else if(typeof newButton.pointX != "undefined") /* If it was given X coordinate, traslade it into animation */
+ newButton.pointX += field.startX;
+%
+ /* Now the same thing with Y coordinate */
+ if(typeof newButton.positionY != "undefined")
+ switch(newButton.positionY)
+ {
+ case option.start:
+ newButton.pointY = field.startY;
+ break;
+ case option.center:
+ newButton.pointY = field.centerY;
+ break;
+ case option.end:
+ newButton.pointY = field.endY;
+ break;
+ default:
+ console.println("There was an error processing argument of Y coordinate ");
+ console.show();
+ }
+ else if(typeof newButton.pointY != "undefined")
+ newButton.pointY += field.startY;
+%
+ /* If pointX or pointY are not defined, it assumes that the button is the reference point */
+ if(typeof newButton.pointX == "undefined"
+ || typeof newButton.pointY == "undefined")
+ {
+ var previousButton = field.buttons[field.buttons.length - 2];
+ switch(newButton.relatPosition)
+ {
+ case option.left:
+ newButton.pointX = previousButton.startX;
+ newButton.pointY = previousButton.centerY;
+ break;
+ case option.from:
+ newButton.relatPosition = option.right;
+ case option.right:
+ newButton.pointX = previousButton.endX;
+ newButton.pointY = previousButton.centerY;
+ break;
+ case option.above:
+ newButton.pointX = previousButton.centerX;
+ newButton.pointY = previousButton.endY;
+ break;
+ case option.below:
+ newButton.pointX = previousButton.centerX;
+ newButton.pointY = previousButton.startY;
+ break;
+ case option.center:
+ newButton.pointX = previousButton.centerX;
+ newButton.pointY = previousButton.centerY;
+ break;
+ default:
+ console.println("There was an error placing a button");
+ console.show();
+ }
+ }
+%
+ /* now it is time for placing the button */
+ switch(newButton.relatPosition)
+ {
+ case option.left:
+ newButton.moveToLeft(newButton.pointX, newButton.pointY);
+ break;
+ case option.right:
+ newButton.moveToRight(newButton.pointX, newButton.pointY);
+ break;
+ case option.above:
+ newButton.moveAbove(newButton.pointX, newButton.pointY);
+ break;
+ case option.below:
+ newButton.moveBelow(newButton.pointX, newButton.pointY);
+ break;
+ case option.from:
+ newButton.moveTo(newButton.pointX, newButton.pointY - newButton.height);
+ break;
+ case option.center:
+ newButton.moveCenter(newButton.pointX, newButton.pointY);
+ break;
+ default:
+ console.println("There was an error placing a button" + i);
+ console.show();
+ }
+ };
+%
+ /* Animation frame function - hide all buttons associated with the frame */
+ field.hideButtons = function()
+ {
+ for(var i in field.buttons)
+ {
+ field.buttons[i].display = display.hidden;
+ if(field.buttons[i].toggleHidden)
+ field.buttons[i].makeTransparent(false);
+ }
+ };
+%
+ /* Animation frame function - makes visible all buttons associated with the frame */
+ field.showButtons = function()
+ {
+ for(var i in field.buttons)
+ {
+ field.buttons[i].display = display.visible;
+ if(field.buttons[i].toggleHidden)
+ field.buttons[i].makeTransparent(true);
+ }
+ };
+%
+ /* Animation frame function - set focus to last button */
+ field.releaseFocus = function()
+ {
+ if(length = field.buttons.length)
+ field.buttons[length - 1].setFocus();
+ };
+%
+ /* Animation widget function - add a frame */
+ field.addFrame = function(newFrame)
+ {
+ if(typeof field.frames == "undefined")
+ field.frames = new Array(); /* Frames to be displayed by the animation */
+ newFrame.buttons = new Array(); /* Buttons that are into the animation frame */
+ newFrame.width = field.width;
+ newFrame.height = field.height;
+ newFrame.moveTo(field.startX, field.startY);
+ newFrame.display = display.hidden; /* Initially, all buttons and frames will be hidden */
+ field.frames.push(newFrame);
+ };
+%
+ /* Animation widget function - Displays the specified frame and hide current */
+ field.displayFrame = function(frameIndex)
+ {
+ if(typeof frameIndex == "string") /* if was given a name instead of a index */
+ frameIndex = field.frames.indexOf(field.doc.getField(frameIndex));
+ if(typeof field.frames == "undefined"
+ || frameIndex >= field.frames.length) /* discards invalid argument */
+ return;
+%
+ /* If it is not first time, hides current frame */
+ if(typeof field.currentFrame != "undefined")
+ {
+ field.frames[field.currentFrame].hideButtons();
+ field.frames[field.currentFrame].display = display.hidden;
+ }
+%
+ /* Now displays the specified frame */
+ field.frames[frameIndex].showButtons();
+ field.frames[frameIndex].delay = true;
+ field.frames[frameIndex].display = display.visible;
+ field.frames[frameIndex].delay = false;
+ field.currentFrame = frameIndex;
+ };
+%
+ /* Animation widget function - displays first frame */
+ field.displayFirstFrame = function()
+ {
+ field.displayFrame(0);
+ };
+%
+ /* Animation widget function - displays last frame */
+ field.displayLastFrame = function()
+ {
+ field.displayFrame(field.frames.length - 1);
+ };
+%
+ /* Animation widget function - displays previous frame */
+ field.displayPreviousFrame = function()
+ {
+ if(field.currentFrame == 0)
+ field.displayLastFrame();
+ else
+ field.displayFrame(field.currentFrame - 1);
+ };
+%
+ /* Animation widget function - displays next frame */
+ field.displayNextFrame = function()
+ {
+ if(field.currentFrame == field.frames.length - 1)
+ field.displayFirstFrame();
+ else
+ field.displayFrame(field.currentFrame + 1);
+ };
+%
+ /* Control button function - add an image sequence */
+ field.addImage = function(imageName)
+ {
+ field.images.push(field.doc.getIcon(imageName));
+ };
+%
+ /* Control button function - makes button transparent or return it to visible */
+ field.makeTransparent = function(transparent)
+ {
+ field.delay = true;
+ if(transparent)
+ {
+ field.fillColor = color.transparent;
+ field.borderWidth = 0;
+ if(field.toggleHidden && !field.transparent) /* if only hidden, makes fully invisible */
+ field.buttonPosition = position.iconOnly;
+ }
+ else
+ {
+ field.fillColor = field.originalFillColor;
+ field.borderWidth = field.originalBorderWidth;
+ field.buttonPosition = field.originalPosition;
+ }
+ field.delay = false;
+ };
+%
+ /* Control button function - action to perform when a button is pressed */
+ field.buttonAction = function()
+ {
+ /* Displays the image sequence only if exist */
+ if(field.images.length == 0)
+ field.targetAction();
+ else
+ {
+ field.parentFrame.hideButtons();
+ field.parentFrame.readonly = false;
+ field.originalIcon = field.parentFrame.buttonGetIcon();
+ field.currentImage = 0;
+ field.interval = app.setInterval(
+ field.name + ".playAnimation()",
+ field.timeSpan
+ );
+ field.parentFrame.buttonSetIcon(field.images[0]);
+ field.parentFrame.setAction(
+ "MouseDown",
+ field.name + ".stopAnimation();"
+ );
+ }
+ };
+%
+ /* Control button function - animation function to be called in time intervals */
+ field.playAnimation = function()
+ {
+ field.currentImage++;
+ if(field.keep && field.currentImage == field.images.length)
+ field.currentImage = 0;
+ if(field.currentImage == field.images.length) /* all images were displayed */
+ field.stopAnimation();
+ else
+ {
+ field.parentFrame.delay = true;
+ field.parentFrame.buttonSetIcon(field.images[field.currentImage]);
+ field.parentFrame.delay = false;
+ }
+ };
+%
+ /* Control button function - stops animation function */
+ field.stopAnimation = function()
+ {
+ app.clearInterval(field.interval);
+ field.targetAction();
+ field.parentFrame.buttonSetIcon(field.originalIcon);
+ field.parentFrame.readonly = true;
+ };
+%
+ return field;
+}/* End of extendField() */
+} \endinput