Next: La clase PNMatrix
Up: Diseño e implantación
Previous: La clase PNController
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: La clase PNMatrix
Up: Diseño e implantación
Previous: La clase PNController
Amilcar Meneses
2002-11-08