CursorManager AS2.0 Class

A continuación un post para inagurar el plugin iG:Syntax Hiliter de wordpress que permite colorear el código, que ya tení­a ganas de publicar algo de código como dios manda :).

Cuando creamos RIAs un tema importante a tener en cuenta es el cambio del cursor o puntero del ratón para mejorar la usabilidad de nuestra aplicación y que el usuario sepa cuando se encuentra en una zona de la pantalla en la que puede interactuar de una determinada manera con la aplicación o simplemente indicar (por ejemplo con un reloj de arena) que en ese determinado momento estamos accediendo a datos del servidor.

Lo siquiente es una clase sencillita que se encarga de controlar ese cambio de cursores:

import mx.managers.DepthManager;
import mx.utils.Delegate;

/*
 	Class: CursorManager

	Manager for cursors

	Author:
		Carlos Rovira - carlos.rovira@nulllycos.es
		
		<http ://www.carlosrovira.com>

	Package:
		com.carlosrovira.managers
	
	Usage:
	
		- First import and get the sigleton instance as follows:
		>	import com.carlosrovira.managers.CursorManager;
		>	var c:CursorManager = CursorManager.getCursorManager();
	
		- To set a MovieClip cursor with the "loading_arrow" identifier:
	
		>	c.setCursor("loading_arrow");
	
		- If you don't want to hide default cursor:
	
		>	c.setCursor("loading_arrow", true);
		
		- To remove the cursor:
		
		>	c.removeCursor();
	
	See Also:
		mx.managers.DepthManager
		mx.utils.Delegate
*/
class com.carlosrovira.managers.CursorManager { 

	/* Property: cursorInstance
	
		Holds the unique class instance allowed
	*/
	private static var cursorInstance:CursorManager;
	
	/* Property: cursor
		The current cursor
	*/
	private var cursor:MovieClip;
	private static var cursorID:Number;
	
	/*
		Function: getCursorManager
	
		CursorManager is a Singleton and this is the function to retrieve the unique instance
	
		Returns:
	
			The CursorManager reference
	*/
	public static function getCursorManager():CursorManager {
		
		if(cursorInstance == null) {
			cursorInstance = new CursorManager();
			return cursorInstance;
		} else {
			return cursorInstance;
		}
	}
	
	/*
		Function: CursorManager (Constructor)
	
		Private constructor (to complete the Singleton)
	
		Returns:
	
			Nothing
	*/
	private function CursorManager() {
		
	}
	
	/*
		Function: setCursor
	
		Changes the current cursor for another movieclip
	
		Parameters:
		
			cursorReference - (String) the movieclip's identifier
			dontHideDefault - (Boolean) false to hide the SO cursor, true to show.
			
		Returns:
	
			Nothing
	*/
	public function setCursor(cursorReference:String, dontHideDefault:Boolean):Number {
		
		// --- Remove posible cursor
		removeCursor();
		
		// --- Create Instance with DepthManager at kCursor special depth
		cursor = DepthManager.createObjectAtDepth(
				cursorReference, 
				DepthManager.kCursor, 
				{_x:_root._xmouse, _y:_root._ymouse}
			); 
		cursor.onMouseMove = Delegate.create(this, moveCursor);
		
		// --- Add Listener so cursor follows mouse
		Mouse.addListener(cursor); 
		
		// --- Maybe you don't want to hide default cursor 😉
		if(!dontHideDefault)
			Mouse.hide();
			
		cursorID = Math.round(Math.random()*(100));
		
		return cursorID;
	}
	
	/*
		Function: removeCursor
	
		Removes the current cursor
	
		Returns:
	
			Nothing
	*/
	public function removeCursor(ID:Number):Void {
		
		Mouse.removeListener(cursor);
		Mouse.show();
		
		//if(cursorID == ID)
			cursor.removeMovieClip();
		
		cursor = null;
		cursorID = null;
	}
	
	/*
		Function: moveCursor
	
		Handler for onMouseMove event
	
		Returns:
	
			Nothing
	*/
	private function moveCursor():Void { 
		cursor._x = _root._xmouse; 
		cursor._y = _root._ymouse;
		
		updateAfterEvent();
	}
}

CursorManager.as

La clase está basada en el framework v2 de Macromedia pues usa dos de sus clases: Delegate y DepthManager y está pensada para su uso con estos componentes. La clase en cuestión es un Singleton, por lo que solo tendremos una instancia de la clase en toda la aplicación. La clase se maneja principalmente mediante dos métodos: setCursor y removeCursor.

Por último decir que Flex tiene una clase parecida pero que además maneja una cola de prioridad para los cursores, a mi de momento no me ha sido necesaria…pero quién sabe…a lo mejor en el futuro se la implemento ;).

13 Comentarios

  1. – Algo debo hacer mal… DepthManager.createObjectAtDepth () me devuelve undefined 😮
    – Una duda… es necesario utilizar:
    cursor.onMouseMove = Delegate.create (this, moveCursor); ?
    Pq si ya estas en el ámbito de la clase no harí­a falta mapear el evento no?
    es decir,
    cursor.onMouseMove = moveCursor;
    deberí­a funcionar, no?
    – El coloreador es muy chulo, lo único que le veo es que al copiar el código copias los números de lí­nea con el código, o el sí­mbolo # ( con un busca y reemplaza se puede arreglar )

    Saludos!

  2. Hola Joan,

    Estás usando la clase con al menos un componente en la librerí­a?. Como digo en el post la clase está hecha para funcionar con el framework v2.

    En cuanto a Delegate. Efectivamente aquí­ es una cuestión de hacer el código más elegante debido a que esa refactorización no es estrictamente necesaria, pero si conveniente a la hora de acostumbrarnos a usar “Best-Practices” como esta y manejar el ambito desde los propios métodos de la clase…por supuesto para gustos colores 🙂

    Lo del código no me habí­a dado cuenta…pero me parece que no es culpa de Geshi y si del formato del fichero del que he hecho copy-paste…luego cuando saque tiempo lo arreglo.

  3. Una cosa más… el hecho de necesitar el framework v2 es debido a que bajo el telón DepthManager usa “createObjectAtDepth” para llamar a “createChildAtDepth” el cual a su vez llama a “createObject” que es un metodo que “UIObject” añade en tiempo de ejecución al prototipo de la clase MovieClip (esto se hace en “mx.core.ext.UIObjectExtensions”).

  4. Ok, creí­a que bastaba con importar las clases. Ya sabí­a yo que me perdí­a algo…
    Y el hecho de utilizar Delegate.create(), pues nunca me habí­a planteado lo que sugieres, pero me parece muy correcto y lógico bajo esos argumentos.
    Tomo nota del consejo.

    Gracias por las aclaraciones 😉

  5. Hola. Este plugin para colorear codigo funciona en wordpress 1.5?
    En la web lo indican para 1.2, asi que no me atrevo a intalarlo a lo loco

    saludos

  6. Carlos,
    I’m able to get this work properly.
    The Mouse will hide, but the MovieClip doesn’t attach to the Mouse position.

  7. Hi Carlos,

    I am facing the same problem as John, I have set the linkage name but just the mouse is hiding, there is nothing attached.

  8. Hi Arpit,

    After some emails with John, I discovered that he was using the class without the v2 framework. Please notice that CursorManager uses mx.managers.DepthManager…for this reason you must have at least one v2 component in your library in order to activate the mixins and addons to MovieClip prototype that comes with the framework.

  9. Pingback: v2 framework SplitPane component take 1 : Joan Garnet :: Arquitectura y desarrollo RIA

  10. Una pregunta Carlos.

    Para utilizar los componentes v2 se necesita cambiar los getNextHighestDepth por DepthManager ¿tienes un ejemplo de utilización de DepthManager para sustituir ls getNextHighestDepth?

    Gracias

  11. Hola Carlos

    He probado una solución, y es utilizar swapDepths antes de hacer el removeMovieClip y parece que funciona. No es una solución que me guste demasiado pero inicialmente parece que me vale porque en otro caso tendría que modifiar muchos createEmptyMovieClip.

    Lo que no me parece lógico es la ayuda de Adobe indicando simplemente que si se utilizan componentes v2 es necesario utilizar DepthManager en lugar de darle una solución al problema.

    Saludos,
    Rodrigo

    Saludos

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *