
Este es un post que tenía pendiente desde hace tiempo, en esta ocasión voy a hablar sobre las herramientas (tools) de Flash y de como personalizarlas o como es nuestro caso crear una nueva herramienta con JSFL.
INTRODUCCIÓN
Recuerdo en los tiempos de Flash 4 que fué cuando empecé con Flash que por comodidad y sobre todo por desconocimiento de la aplicación, quería hacer tablas en Flash y por mucho que busqué no encontré una herramienta que me sirviera para esto, así que al final aprendí a utilizar las herramientas de dibujo y a través de cuadros y líneas con las herramientas rectángulo y trazo conseguí hacer las tablas que quería, luego con el tiempo descubrí el panel alineación y distribución y con eso perfeccioné la tarea y me fué más fácil hacer estas tablas.
Bueno, pues la idea es que vamos a crear una herramienta para crear tablas de una manera fácil como si de rectángulos se tratara.
DESARROLLO
JSFL nos permite extender la funcionalidad de la aplicación, como hemos hablado ya en otras ocasiones, lo podemos hacer con comandos y paneles, pero también existe otro modo de extender y automatizar procesos, me refiero a la creación de herramientas.
Las herramientas al igual que los comandos y paneles se programan con JSFL y se almacenan en las siguiente rutas respectivamente por sistema operativo:
unidad de arranque\Users\nombre de usuario\Local Settings\Application Data\Adobe\Flash
CS4\idioma\Configuration\Tools
unidad de arranque\Documents and Settings\usuario\Local Settings\Application Data\Adobe\Flash
CS4\idioma\Configuration\Tools
Macintosh HD/Usuarios/nombre de usuario/Librería/Application Support/Adobe/Flash
CS4/idioma/Configuration/Tools
A diferencia de los comandos y los paneles en las herramientas tenemos acceso a funciones y métodos de nivel superior que nos ayudan a desarrollar y controlar el estado de nuestra herramienta, las funciones disponibles son las siguiente:
- activate()
- configureTool()
- deactivate()
- keyDown()
- keyUp()
- mouseDoubleClick()
- mouseDown()
- mouseMove()
- mouseUp()
- notifySettingsChanged()
- setCursor()
Las que utilizaremos para la creación de la herramienta tablas serán, activate que se dispara cuando la herramienta es seleccionada por el usuario, deactivate que se dispara cuando el usuario cambia a otra herramienta, notifySettingsChanged que se dispara cuando el usuario modifica las propiedades de nuestra herramienta, mouseDown, mouseMove y mouseUp que se disparan cuando el usuario hace lo que el nombre de la función dice
. Esto con respecto a los eventos para controlar nuestra herramienta.
Pero ¿cómo accedemos a la herramienta?
Pues fácil, como todo en JSFL son objetos necesitamos obtener la referencia a la herramienta activa que será nuestra herramienta, esto lo hacemos con la propiedad activeTool del objeto tools, en el ejemplo siguiente se muestra como obtener una referencia a la herramienta.
theTool = fl.tools.activeTool;
Guay, ¿Y para qué quiero tener una referencia al objeto herramienta?
Pues para asignar a nuestra herramienta nombre, tooltip, icono, opciones, especificar el tipo para el inspector de propiedades por ejemplo y muchas más cosas. Como se muestra a continuación.
// Set the standard tool information
theTool = fl.tools.activeTool;
theTool.setToolName("Tablas");
theTool.setIcon("Tablas.png");
theTool.setMenuString("Herramienta Tablas");
theTool.setToolTip("Herramienta Tablas");
theTool.setOptionsFile("Tablas.xml");
// This tool uses the Shape property inspector
theTool.setPI( "shape" );
Vale, vale, ya me entero, pero ¿Cómo dibujo?
Ah, muy cierto, pues para pintar / dibujar debemos hacer una nota importante y es que tenemos dos momento de dibujo:
- El momento de la previsualización
- El momento del dibujo final
Para el momento de la pre-visualización utilizaremos el objeto drawingLayer y sus métodos moveTo y lineTo que son idénticos a los que utilizamos en la API de dibujo de ActionScript y los método beginFrame y endFrame para indicar el incio y el fin del dibujo de la pre-visualización. Por ejemplo, con el siguiente código dibujaríamos un cuadro de 20×20 en 0, 0:
fl.drawingLayer.beginFrame();
fl.drawingLayer.moveTo(0, 0);
fl.drawingLayer.lineTo(20, 0);
fl.drawingLayer.lineTo(20, 20);
fl.drawingLayer.lineTo(0, 20);
fl.drawingLayer.lineTo(0, 0);
fl.drawingLayer.endFrame();
Y para el momento del dibujo final utilizaremos también el objeto drawingLayer para crear un objeto path con el método newPath, luego utilizaremos los métodos addPoint y makeShape para crear nuestro dibujo. Por ejemplo:
var myPath = fl.drawingLayer.newPath();
myPath.addPoint(0, 20);
myPath.addPoint(20, 20);
myPath.addPoint(20, 0);
myPath.addPoint(0, 0);
myPath.makeShape(false, true);
Perfecto, y ahora ¿cómo modifico las propiedades de mi herramienta?
Vale, para esto debemos recordar que en un principio utilizamos el método setOptionsFile del objeto tool donde indicamos un fichero xml, este fichero xml contiene la definición de las propiedades que utilizaremos en la herramienta. Por ejemplo para la herramienta tabla, utilizo dos propiedades nColumns y nRows. Un ejemplo del fichero xml de configuración es el siguiente:
property name="Columnas: " variable="nColumns" min="1" max="100" defaultValue="3" type="Number"
property name="Filas: " variable="nRows" min="1" max="100" defaultValue="3" type="Number"
Cuando el usuario modifique estos valores en el panel de propiedades se nos notificará en el evento (la función) notifySettingsChanged. Un ejemplo de como utilizar los valores modificados es el siguiente:
function notifySettingsChanged()
{
var theTool = fl.tools.activeTool;
this.nColumns = theTool.nColumns;
this.nRows = theTool.nRows;
}
Y listo, con esto ya tenemos controladas todas las fases del diseño de una herramienta.
EJEMPLOS
A continuación un par de ejemplos de lo que podemos conseguir de una manera sencilla con esta herramienta.



DESCARGAS
Tenemos dos tipos de descargas, para instalar simplemente la herramienta Tablas y para descargar el JSFL:
- Extensión Herramienta Tablas (instalador mxp).
- Paquete zip con la Herramienta Tablas (ficheros jsfl, xml y png).
INSTALACIÓN
Una vez que se haya instalado la extensión debemos asignarla a un grupo de herramienta desde el panel Personalizar panel de herramientas y listo ya se puede utilizar.

Dudas, sugerencias o comentarios, aquí estaré.
Saludos.
Entradas relacionadas

Desde siempre me han llamado la atención las marquesinas. Quizá por las veo muy habitualmente en el tren que viajo todos los días para ir de la casa al trabajo y del trabajo a casa, aunque ya desde mucho antes me gustaban.
NOTA
Puede ser interesante leer antes o después este otro post de Introducción a Comandos para saber qué son, dónde van y cómo funcionan.
INTRODUCCIÓN
Bueno, pues con esa idea en la cabeza se me ocurrió hacer un comando que en si mismo no tiene una utilidad claro, sino más bien abstracta o artística, pero que me viene muy bien para explicar el Objeto Timeline de JSFL.
El comando Escribir palabra no tiene una utilidad clara, es decir, no se creó con el fin de resolver un problema, sencillamente se hizo porque una tarde con una visión muy al estilo matrix (puede ser por la película o por una matriz) y con la nostalgia de las marquesinas de leds en la mente (quizá influenciado por las pantallas de los trenes de cercanías), si hizo.
TUTORIAL
Primero utilizaremos el objeto Document para acceder a su biblioteca (library), creamos y editamos un MovieClip en ella y por último acceder a su línea de tiempo (Timeline).
var oDoc;
var oLib;
var oTimeline;
this.oDoc = fl.getDocumentDOM();
this.oLib = this.oDoc.library;
this.oLib.addNewItem("movie clip", "Nombre_MovieClip");
this.oLib.editItem("Nombre_MovieClip");
this.oTimeline = this.oDoc.getTimeline();
Una vez que tenemos una referencia al objeto Timeline podremos utilizar sus métodos y propiedades, en este caso vamos a utilizar el método addNewLayer para agregar tantas capas como necesitemos.
this.oTimeline.addNewLayer();
Luego seleccionamos los fotogramas con los que vamos a trabajar, esto lo hacemos con el método setSelectedFrames y los convertimos en fotogramas clave:
this.oTimeline.setSelectedFrames(INICIO, FIN, REMPLAZAR_SELECCIÓN);
this.oTimeline.convertToKeyframes();
Y listo lo siguiente es simplemente ir creando algo en cada fotograma en función de un patrón para que la línea de tiempo tenga forma. Una forma sencilla de hacer esto es dibujando un círculo en el escenario, de esta manera el fotograma dejará de estar vacío, para dibujar el círculo utilizamos el método addNewOval del objeto Document:
this.oDoc.addNewOval({left:0, top:0, right:10, bottom:10});
El resultado al que queremos llegar es el que se muestra en la siguiente imagen.
Quizá sea mejor verlo desde lejos, porque muy cerca de la pantalla cuesta un poco leerlo.

El código completo es el siguiente:
var oDoc;
var oLib;
var oTimeline;
var aLetters;
var aWord;
this.config();
function config()
{
fl.showIdleMessage(false);
fl.outputPanel.clear();
if(fl.getDocumentDOM())
{
this.oDoc = fl.getDocumentDOM();
this.oLib = this.oDoc.library;
this.init();
}
else
{
alert("Debes tener un documento abierto.");
}
}
function init()
{
this.configLetters();
this.configWord();
var nTotalLetters = this.aWord.length;
for(var i = 0; i < nTotalLetters; i++)
{
this.createLetter(this.aWord[i], i * 6);
}
}
function configLetters()
{
this.aLetters = new Array();
this.aLetters[" "] = "0,0,0,0,0|0,0,0,0,0|0,0,0,0,0|0,0,0,0,0|0,0,0,0,0|0,0,0,0,0|0,0,0,0,0";
this.aLetters["A"] = "0,1,1,1,0|1,0,0,0,1|1,0,0,0,1|1,1,1,1,1|1,0,0,0,1|1,0,0,0,1|1,0,0,0,1";
this.aLetters["B"] = "1,1,1,1,0|1,0,0,0,1|1,0,0,0,1|1,1,1,1,0|1,0,0,0,1|1,0,0,0,1|1,1,1,1,0";
this.aLetters["C"] = "0,1,1,1,0|1,0,0,0,1|1,0,0,0,0|1,0,0,0,0|1,0,0,0,0|1,0,0,0,1|0,1,1,1,0";
this.aLetters["D"] = "1,1,1,1,0|1,0,0,0,1|1,0,0,0,1|1,0,0,0,1|1,0,0,0,1|1,0,0,0,1|1,1,1,1,0";
this.aLetters["E"] = "1,1,1,1,1|1,0,0,0,0|1,0,0,0,0|1,1,1,1,0|1,0,0,0,0|1,0,0,0,0|1,1,1,1,1";
this.aLetters["F"] = "1,1,1,1,1|1,0,0,0,0|1,0,0,0,0|1,1,1,1,0|1,0,0,0,0|1,0,0,0,0|1,0,0,0,0";
this.aLetters["G"] = "0,1,1,1,0|1,0,0,0,1|1,0,0,0,0|1,0,1,1,1|1,0,0,0,1|1,0,0,0,1|0,1,1,1,0";
this.aLetters["H"] = "1,0,0,0,1|1,0,0,0,1|1,0,0,0,1|1,1,1,1,1|1,0,0,0,1|1,0,0,0,1|1,0,0,0,1";
this.aLetters["I"] = "0,1,1,1,0|0,0,1,0,0|0,0,1,0,0|0,0,1,0,0|0,0,1,0,0|0,0,1,0,0|0,1,1,1,0";
this.aLetters["J"] = "0,0,0,0,1|0,0,0,0,1|0,0,0,0,1|0,0,0,0,1|0,0,0,0,1|1,0,0,0,1|0,1,1,1,0";
this.aLetters["K"] = "1,0,0,0,1|1,0,0,1,0|1,0,1,0,0|1,1,0,0,0|1,0,1,0,0|1,0,0,1,0|1,0,0,0,1";
this.aLetters["L"] = "1,0,0,0,0|1,0,0,0,0|1,0,0,0,0|1,0,0,0,0|1,0,0,0,0|1,0,0,0,0|1,1,1,1,1";
this.aLetters["M"] = "1,0,0,0,1|1,1,0,1,1|1,0,1,0,1|1,0,1,0,1|1,0,0,0,1|1,0,0,0,1|1,0,0,0,1";
this.aLetters["N"] = "1,0,0,0,1|1,0,0,0,1|1,1,0,0,1|1,0,1,0,1|1,0,0,1,1|1,0,0,0,1|1,0,0,0,1";
this.aLetters["O"] = "0,1,1,1,0|1,0,0,0,1|1,0,0,0,1|1,0,0,0,1|1,0,0,0,1|1,0,0,0,1|0,1,1,1,0";
this.aLetters["P"] = "1,1,1,1,0|1,0,0,0,1|1,0,0,0,1|1,0,0,0,1|1,1,1,1,0|1,0,0,0,0|1,0,0,0,0";
this.aLetters["Q"] = "0,1,1,1,0|1,0,0,0,1|1,0,0,0,1|1,0,0,0,1|1,0,0,0,1|1,0,0,1,1|0,1,1,1,1";
this.aLetters["R"] = "1,1,1,1,0|1,0,0,0,1|1,0,0,0,1|1,0,0,0,1|1,1,1,1,0|1,0,0,1,0|1,0,0,0,1";
this.aLetters["S"] = "0,1,1,1,0|1,0,0,0,1|1,0,0,0,0|0,1,1,1,0|0,0,0,0,1|1,0,0,0,1|0,1,1,1,0";
this.aLetters["T"] = "1,1,1,1,1|0,0,1,0,0|0,0,1,0,0|0,0,1,0,0|0,0,1,0,0|0,0,1,0,0|0,0,1,0,0";
this.aLetters["U"] = "1,0,0,0,1|1,0,0,0,1|1,0,0,0,1|1,0,0,0,1|1,0,0,0,1|1,0,0,0,1|0,1,1,1,0";
this.aLetters["V"] = "1,0,0,0,1|1,0,0,0,1|1,0,0,0,1|1,0,0,0,1|0,1,0,1,0|0,1,0,1,0|0,0,1,0,0";
this.aLetters["W"] = "1,0,0,0,1|1,0,0,0,1|1,0,0,0,1|1,0,1,0,1|1,0,1,0,1|1,1,0,1,1|1,0,0,0,1";
this.aLetters["X"] = "1,0,0,0,1|1,0,0,0,1|0,1,0,1,0|0,0,1,0,0|0,1,0,1,0|1,0,0,0,1|1,0,0,0,1";
this.aLetters["Y"] = "1,0,0,0,1|1,0,0,0,1|1,0,0,0,1|0,1,0,1,0|0,0,1,0,0|0,0,1,0,0|0,0,1,0,0";
this.aLetters["Z"] = "1,1,1,1,1|0,0,0,0,1|0,0,0,1,0|0,0,1,0,0|0,1,0,0,0|1,0,0,0,0|1,1,1,1,1";
}
function configWord()
{
sWord = prompt("Escribe una palabra.");
this.aWord = new Array();
var nWordLength = sWord.length;
for(var i = 0; i < nWordLength; i++)
{
this.aWord.push(sWord.substring(i, i + 1));
}
this.createTimeline(sWord);
}
function createTimeline(_sWord)
{
var sWordLengthInFrames = _sWord.length * 6;
this.oLib.addNewItem("movie clip", _sWord);
this.oLib.editItem(_sWord);
this.oTimeline = this.oDoc.getTimeline();
this.oTimeline.setSelectedFrames(0, sWordLengthInFrames, true);
this.oTimeline.convertToKeyframes();
for(var i = 0; i < 6; i++)
{
this.oTimeline.addNewLayer();
this.oTimeline.setSelectedFrames(0, sWordLengthInFrames, true);
this.oTimeline.convertToKeyframes();
}
}
function createLetter(_sLetter, _nStartFrame)
{
var sConfigLetter = this.aLetters[_sLetter];
if(sConfigLetter)
{
var aConfigLetter = sConfigLetter.split("|");
for(var i = 0; i < 7; i++) aConfigLetter[i] = aConfigLetter[i].split(",");
for(var i = 0; i < 7; i++)
{
for(var j = 0; j < 5; j++)
{
if(aConfigLetter[i][j] == "1")
{
this.oTimeline.setSelectedLayers(i);
this.oTimeline.setSelectedFrames(_nStartFrame + j, _nStartFrame + j + 1, true);
this.oDoc.addNewOval({left:0, top:0, right:10, bottom:10});
}
}
}
}
else
{
alert("No existe el caracter: " + _sLetter);
}
}
DESCARGAS
Tenemos dos tipos de descargas, para instalar simplemente el comando y para descargar el JSFL:
- Extensión Escribir palabra (instalador mxp).
- Comando Escribir palabra (fichero jsfl).
Dudas, sugerencias o comentarios, aquí estaré.
Saludos.
Entradas relacionadas