next up previous contents
Next: La clase PNMatrix Up: Diseño e implantación Previous: La clase PNController

La clase PNView

Esta clase es de las más importantes en PetrA, debido a que los objetos de esta clase representan gráficamente a la red de Petri. La clase PNView es una subclase de NSView del AppKit de Apple, lo que le permite recibir eventos del usuario (a través del teclado y del ratón) y desplegar información en su área de dibujo. Como toda clase View del AppKit, PNView tiene relación con la ventana que lo contiene. En el modelo vista-control, los objetos PNView representa la parte visible y mantiene una relación con su objeto de control asociado (objetos PNController). Además esta clase mantiene una estrecha relación con la clase PNMatrix, que es la clase que representa las distintas interacciones entre la red de Petri en forma de matriz de incidencia.

Los objetos PNView se encargan de desplegar los elementos gráficos de la red de Petri (lugares, transiciones y arcos), por lo cual, tamién tiene una relación con la familia de clases Figure (de las cuales se desprenden Place, Transition y Connection).

PNView tiene declaradas varias variables y métodos de instancia, los más significativo se muestran a continuación:

@interface PNView : NSView 
{
   PNMatrix  *matrixC; //Matriz de Incidencia
   ... 
   id    controller;   //Controller Object Id
   id    lastGraph;    //Last Graph builded 
   Class factory;      //Clase del nuevo objeto
   BOOL  running; 
}
...
- (void)runPetriNet:(id)sender;
- (void)cut:(id)sender;
- (void)print:(id)sender;
... 
- (void)mouseDown:(NSEvent *)event;
- (void)mouseUp:(NSEvent *)theEvent;
- (void)mouseDragged:(NSEvent *)theEvent;
- (void)drawRect:(NSRect)rect;
...
@end

La variable matrixC hace referencia a un objeto que representa la matriz de incidencia la red de Petri. Y de donde los objetos PNView obtienen información de la red de Petri (conexiones de los arcos, número de lugares, número de transiciones, etc). Al inicializar un objeto PNView, esta matriz no tiene ninguna información de la red de Petri, sin embargo, conforme el usuario carge la red desde un archivo, o la edite gráficamente, este objeto irá almacenando toda la información necesaria, de hecho muchos métodos de la clase PNView están orientados atrabajar exclusivamente con la matriz de incidencia.

La variable controller hace referencia al objeto de control de la red de Petri (objeto de la clase PNController). Este objeto es el encargado de enviarle los mensajes provenientes del objeto de control de la red (Controller), principalmente para el manejo de la red como documento (salvar, obtener nueva matriz de incidencia, e imprimir) y para actualizar a la clase que se ha seleccionado en el panel Tools, con la finalidad de que la instancia correspondiente se agregue a la red de Petri.

La variable lastGraph hace referencia al último objeto que se ha creado en la red de Petri durante los eventos de ratón: mouseDown, mouseDragged y mouseUp. Esto permite que el último objeto creado en el área de dibujo del objeto PNView pueda recibir eventos del usuario para definir su origen y dimensión (en el caso de los objeto Connection).

La variable factory hace referencia al constructor de la clase del objeto que se agregará a la red de Petri. Esta referencia se obtiene del objeto Controller, a través del objeto PNController.

Finalmente la variable running, se utiliza para indicar si el documento red de Petri se está ejecutando. Ya que en caso de estarlo, no se pueden agregar o eliminar elementos de la red. Esta variable cobra importancia cuando se estan ejecutando los hilos de las transiciones, ya que una condición para que continúen su ejecución es que esta variable este encendida.

Los métodos instancia de los objetos PNView se utilizan, principalmente para la edición gráfica, para manejar a la red de Petri como un documento y para desplegar gráficamente a la red. Estos métodos trabajan de la siguiente forma:

runPetriNet
Este método lo envía el usuario directamente al objeto PNView a través de un botón en la ventana del documento. Cuando el objeto PNView recibe este mensaje le manda un mensaje al objeto PNMatrix, referenciado por la variable matrixC, el mensaje runTransitions para mandar a ejecutar a la red de Petri, y la variable running se activa. Si la variable running se encuentra activa cuando se manda a ejecutar este método, entonces se apaga esta bandera --con esta acción lo hilos de las transiciones terminan su ejecución, ya que sensan a esta variable cada vez que se ejecutan.

cut
Este método lo envía el usuario a través del objeto PNController. Cuando se recibe este mensaje, el objeto PNView elimina los objetos gráficos que el usuario tenga seleccionados.

print
Este método lo envía el usuario a través del objeto PNController o directamente con el botón que esta en la ventana del documento. Cuando se recibe este mensaje se revisan las dimensiones y orientación que se define en los documentos a través del panel Page Setup. Después se crea un objeto PNRenderinView donde se dibujará la red de Petri con la resolución de la impresora. Y se manda como argumento al controlador de impresora a través de la clase NSPrintOperation. Esta clase se encarga de establecer comunicación entre PetrA y el manejador de impresora para definir el tipo de impresora o si se redirecciona la salida a un archivo pdf.

mouseDown
Este método lo envía directamente el usuario a través del ratón. La implantación de este método es un poco compleja, debido a las distintas respuestas que se esperan de una acción como esta. Básicamente este método se utiliza para agregar un nuevo elemento a la red de Petri --el que se haya seleccionado en el panel Tools y del cual se haga referencia a su constructor con la variable factory--, para seleccionar un objeto para una operación posterior (eliminar, ver sus atributos en el Inspector, o mover su posición), o para agregarlo a los objetos seleccionados.

Cuando se recibe este mensaje, lo primero que se hace es definir el punto en el área de dibujo donde se realizó el evento del usuario. Después se verifica que se tenga algún objeto fabrica seleccionado (esto garantiza que se tiene seleccionado una herramienta del panel Tools) y de que no se este ejecutando la red. En caso de que se cumplan estas condiciones, se procede a crear el nuevo objeto y se incorpora a la red de Petri en caso de ser Place o Transition, se actualiza la información de la red de Petri en el Inpector y, finalmente, se les manda el mensaje mouseDown a estos objetos para que registren el punto donde se ha ejecutado el evento del usuario (esto les es de utilidad cuando se recibe el mensaje mouseDragged). Si el objeto que se ha creado es un objeto Token se debe verificar que el evento del ratón se haya hecho sobre un objeto Place, si es así, se le envía al objeto Place correpondiente el mensaje addToken y se elimina el objeto Token que se creo (por el momento los objetos Token son auxiliares en la edición de la red de Petri). Si el objeto que se ha creado es un objeto Transition se verifica que el evento se haya realizado sobre algún objeto Transition o Place, de ser así, se mantiene vivo el objeto, pero aún no se agrega a la red de Petri, pues se debe revisar que el objeto destino sea válido.

Si no se tiene referencia a algún constructor o si la red de Petri se está ejecutando, entonces se procede a verificar si algún objeto gráfico de la red de Petri contiene al punto donde se realizó el evento. Si algún objeto lo contiene, entonces se procede a seleccionarlo o deseleccionarlo según sea el caso. Si el número de objetos seleccionados es 1, entonces se despliega el Inspector con los atributos de este objeto, si el número de objeto seleccionados es mayor a 1 o cero, entonces el Inspector despliega la información general de la red de Petri.

Después de ejecutar cualquiera de los casos anteriores, se manda a redibujar el objeto PNView.

mouseUp
Este método lo envía directamente el usuario a través del ratón. Cuando se recibe este mensaje, el objeto PNView identifica si se tiene por almacenar un objeto Connection (en caso de tenerlo se debe verificar que el objeto destino sea válido), o nó. Si el objeto que se ha creado (referenciado por lastGraph) es Place o Transition, se les envía el mensaje mouseUp para que actualicen algunas variables de instancia --que se utilizan en caso de haber respondido a un evento mouseDragged--. Si se comprueba que la referencia de lastGraph es de un objeto Connection, entonces se verifica que el objeto final que contiene al punto donde se realizó el evento mouseDown es válido para el objeto Connection --es decir, si el objeto origen es Place entonces el destino es Transition, o viceversa--, entonces se procede a incorporar a este objeto a la matriz de incidencia asociada a PNView enviándole el mensaje addConnection. El objeto PNMatrix le regresa a PNView el resultado de la anexión del objeto Connection para enviarle la información el objeto Controller para que se pueda actualizar contenido del Inspector. Si el punto donde se realiza este evento no pertenece a ningún objeto válido entonces se procede a eliminar definitivamente al objeto Connection.

mouseDragged
Este mensaje es enviado directamente por el usuario a través del ratón. Cuando el objeto recibe este mensaje lo que debe hacer es cambiar la posición de los objetos Place o Transition o dirigir a un nuevo objeto Connection hacia su objeto final. Cuando se ejecuta este mensaje se debe tener en consideración de si se ha seleccionado o agregado una figura en el método mouseDown. Si la variable factory hace referencia a algún contructor, entonces el método mouseDown ha agregado un nuevo objeto gráfico y este método, en consecuencia, debe cambiar la posición del objeto (si es un objeto Place o Transition); si lastGraph hace referencia a un objeto Connection se debe cambiar su dimensión para dar el efecto de mover el arco hacia otro objeto en el área de dibujo. Si factory hace referencia a un valor nulo, entonces se tiene que se ha hecho una selección y se deben mover sólo los objetos Place o Transition, y por consiguiente, se deben redibujar los arcos que se conectan este objeto.

drawRect
La manera de representar los objetos gráficos de la red de Petri, se realiza con ayuda de dos arreglos auxiliares, uno para todos los objetos gráficos, y otra para los objetos seleccionados. En ambos arreglos se colocan al inicio los arcos y después los lugares y transiciones.


next up previous contents
Next: La clase PNMatrix Up: Diseño e implantación Previous: La clase PNController
Amilcar Meneses
2002-11-08