tutorial biomedigupabellan/tutorialbiomedigu.pdf · gtk::drawingarea proporciona una area que...

68
Tutorial BioMedIGU Pascual Abell´ an 14 de julio de 2005

Upload: doanthuy

Post on 16-Oct-2018

219 views

Category:

Documents


0 download

TRANSCRIPT

Tutorial BioMedIGU

Pascual Abellan

14 de julio de 2005

Indice general

1. Introduccion 11.1. ¿Que es BioMedIGU? . . . . . . . . . . . . . . . . . . . . . . 11.2. Antes de la instalacion . . . . . . . . . . . . . . . . . . . . . . 11.3. Instalacion de BioMedIGU . . . . . . . . . . . . . . . . . . . . 2

1.3.1. GNU/Linux, Unix y Mac OS X . . . . . . . . . . . . 21.3.2. Microsoft Windows . . . . . . . . . . . . . . . . . . . . 3

1.4. Breve introduccion a Gtkmm . . . . . . . . . . . . . . . . . . 31.4.1. Widgets . . . . . . . . . . . . . . . . . . . . . . . . . . 41.4.2. Contenedores . . . . . . . . . . . . . . . . . . . . . . . 41.4.3. Dialogos . . . . . . . . . . . . . . . . . . . . . . . . . . 61.4.4. El puntero “inteligente” RefPtr . . . . . . . . . . . . . 71.4.5. Mecanismo de Signals/Slots . . . . . . . . . . . . . . . 8

2. Uso de BioMedIGU 92.1. Conceptos basicos . . . . . . . . . . . . . . . . . . . . . . . . 9

2.1.1. El puntero “inteligente” SmartPtr . . . . . . . . . . . 92.1.2. Inicializaciones . . . . . . . . . . . . . . . . . . . . . . 11

2.2. El gestor de ventanas . . . . . . . . . . . . . . . . . . . . . . . 112.3. Ventana de menus . . . . . . . . . . . . . . . . . . . . . . . . 132.4. Ventana de visualizacion grafica . . . . . . . . . . . . . . . . . 192.5. Ventana de parametros/opciones . . . . . . . . . . . . . . . . 282.6. Ventana asistente . . . . . . . . . . . . . . . . . . . . . . . . . 332.7. Ventana de edicion de funciones 2D . . . . . . . . . . . . . . 382.8. Creacion de la interfaz mediante ficheros de configuracion . . 42

3. Formato del fichero de configuracion 473.1. Introduccion . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47

3.1.1. Formato general de los ficheros de la BdDisc . . . . . 473.1.2. Leyenda de la descripcion . . . . . . . . . . . . . . . . 48

3.2. Descripcion de los objetos de BioMedIGU . . . . . . . . . . . 493.2.1. Ventana de menus . . . . . . . . . . . . . . . . . . . . 493.2.2. Ventana de visualizacion grafica . . . . . . . . . . . . 523.2.3. Ventana de parametros/opciones . . . . . . . . . . . . 54

IV INDICE GENERAL

3.2.4. Ventana de edicion de funciones 2D . . . . . . . . . . 583.2.5. Ventana Asistente . . . . . . . . . . . . . . . . . . . . 61

Bibliografıa 63

Capıtulo 1

Introduccion

1.1. ¿Que es BioMedIGU?

BioMedIGU es una librerıa que facilita la creacion de interfaces graficasde usuario disponible en multiples plataformas. Esta pensada principalmentepara su uso en ambitos de la investigacion donde es deseable que el desa-rrollo de la interfaz sea lo mas sencillo y rapido posible, a costa incluso dealgo de flexibilidad. En concreto esta orientada a aplicaciones biomedicas yde visualizacion grafica, aunque su uso esta indicado para todo aquel quequiera realizar interfaces graficas de forma rapida, sencilla y que pretendarealizar interfaces para aplicaciones similares, pues la reusabilidad es unacaracterıstica destacable de esta librerıa.

Esta basada en el toolkit grafico Gtkmm y proporciona varios componen-tes con un nivel de abstraccion mas alto, que permite reducir el conocimientonecesario que debe tener el programador sobre el toolkit. Aunque no es in-dispensable, sı serıa interesante que el lector tuviera algunos conocimientossobre Gtkmm para comprender mejor este tutorial.

En este tutorial se expondran las funcionalidades que proporciona y comousarlas correctamente.

1.2. Antes de la instalacion

BioMedIGU depende de varias librerıas que deberan estar instaladascorrectamente antes de proceder con su instalacion. En concreto BioMedIGUdepende directamente de las siguientes librerıas:

Gtkmm (2.4 o superior) Se trata de un toolkit para desarrollar interfacesgraficas de usuario. Podemos encontrar un manual de instalacion enla pagina principal de la librerıa.(http://www.gtkmm.org)

2 Introduccion

Gtkglextmm (1.1.0 o superior) Implementacion de un widget que per-mite visualizar graficos realizados mediante GL. En su pagina webpodemos encontrar instrucciones para su instalacion.(http://gtkglext.sourceforge.net)

Gnomecanvasmm (2.6 o superior) Implementacion de un canvas quepermite realizar graficos sencillos en 2D. En la pagina principal deGnome encontraremos informacion de su instalacion.(http://www.gnome.org)

BdDisc (0.1 o superior) Ofrece funciones para almacenar y recuperardesde fichero datos estructurados. Incluye la implementacion del ti-po Generic list.

Evidentemente tambien deberan estar instaladas correctamente todaslas dependencias de estas librerıas para poder instalar BioMedIGU. En laspaginas antes mencionadas se encuentra toda la informacion necesaria sobreestas dependencias.

Dependiendo de la plataforma escogida se deberan tener instaladas lasherramientas necesarias para la compilacion, si se procede a instalar desde lasfuentes. Para los sistemas Unix, GNU/Linux y Mac OS X, se deberan tenerinstaladas un compilador estandar de C++ y alguna version del programamake. Para el desarrollo de la librerıa se han utilizado la version de GNU(http://www.gnu.org) de ambos programas y son las recomendadas para lainstalacion. En sistemas Microsoft Windows se necesitara tener instaladoel entorno MSYS/MinGW (http://www.mingw.org). Sı se desea generartambien la documentacion sera necesario disponer del programa Doxygen(http://www.doxygen.org) y de un compilador de LATEX2ε.

1.3. Instalacion de BioMedIGU

1.3.1. GNU/Linux, Unix y Mac OS X

Antes de comenzar la instalacion deberemos descargar el fichero compri-mido que contiene el codigo de BioMedIGU y descomprimirlo en cualquierdirectorio con el siguiente comando:

# tar zxvf biomedigu -x.y.z.tar.gz

Una vez descomprimido podemos proceder con la instalacion tecleando lossiguientes comandos en una shell :

# ./ configure

# make

# make install

Para modificar el directorio de instalacion por defecto (/usr/local), debe-remos indicarselo como parametro al comando ./configure:

1.4 Breve introduccion a Gtkmm 3

# ./ configure --prefix =/opt/local

Para ver una lista de las opciones del comando ./configure podemos eje-cutar:

# ./ configure --help

Los siguientes comandos generan e instalan la documentacion de la librerıa:

# make doc

# make doc -install

1.3.2. Microsoft Windows

Las librerıas Gtk1 y Gtkmm2 se pueden instalar a partir de de los insta-ladores disponibles.

Las demas librerıas deberemos compilarlas con el entorno MSYS/MinGWo instalarlas a partir de compilaciones de terceros. Podemos encontrar unasguias tanto para la compilacion como para la instalacion3.

Una vez instaladas todas las dependencias podremos instalar la librerıaBioMedIGU desde un entorno MSYS/MinGW con los siguientes comandos:

# ./ configure --prefix=<directorio_de_instalacion >

# make

# make install

Aunque tambien existen compilaciones para Win324.

1.4. Breve introduccion a Gtkmm

En esta seccion se explican algunos conceptos basicos de Gtkmm quefacilitaran la comprension del tutorial. No se trata de un manual completoni de una guıa de referencia, para profundizar en el conocimiento de Gtkmmconsultar Programming with Gtkmm2 [1] y la referencia de la API [2].

Gtkmm es una encapsulacion en C++ de Gtk+ que le proporciona to-dos los beneficios de la orientacion a objetos (herencia, polimorfismo, etc.),ademas le anade otras cualidades como una mejora en la comprobacion detipos, codigo mas corto y legible o menor uso de punteros. No ser una librerıaescrita nativamente en C++, sino una envoltura de una implementada enC permite a los desarrolladores de Gtkmm emplear su tiempo en definiruna API lo mas clara posible, tarea facilitada gracias a los desarrolladoresde Gtk+ que han creado la librerıa en un C “pseudo orientado a objetos”,teniendo en mente las encapsulaciones en otros lenguajes.

1http://gladewin32.sourceforge.net/index.php2http://www.pcpm.ucl.ac.be/gustin/win32 ports3http://truja.lsi.upc.edu/movibio/ResearchLines/soft/Tricks4http://truja.lsi.upc.edu/movibio/projects/IM3/BioMedIGU/index html#descargas

4 Introduccion

1.4.1. Widgets

Se denomina widget a los componentes que podemos encontrar en unainterfaz grafica de usuario como botones, campos de texto, menus, etc. queen otros sistemas, como Microsoft Windows, suelen llamarse controles. EnGtkmm cada tipo de widget esta representado por un clase que agrupa todassus propiedades y funcionalidades. Mediante estos widgets se crean todas ycada una de las ventanas que forman la interfaz grafica, para ello debenorganizarse en contenedores que los almacenan y los distribuyen por la ven-tana.

Gtkmm proporciona todos los widgets basicos necesarios para construiruna interfaz grafica de usuario, a continuacion se nombran los mas comunes:

Gtk::Button Boton estandar que normalmente se muestra como una eti-queta y/o una imagen dentro de un recuadro. Cuando se aprieta sesuele ejecutar una accion.

Gtk::CheckButton Boton que se muestra como un pequeno cuadro quepuede tener dos estados, activado o desactivado.

Gtk::RadioButton Boton que agrupa diferentes opciones que se exclu-yen mutuamente. El nombre se debe a los botones de seleccion en lasantiguas radios de coches.

Gtk::Entry Widget que permite al usuario la entrada de texto.

Gtk::Combo Permite la seleccion de una opcion mediante una lista des-plegable, opcionalmente tambien permite la entrada de texto.

Gtk::SpinButton Combinacion de un Gtk::Entry y unos botones con unaflecha hacia arriba y hacia abajo que permite la entrada de un rangode valores numericos.

Gtk::Label Widget que muestra un texto no editable en la ventana.

Gtk::DrawingArea Proporciona una area que permite dibujar librementemediante primitivas basicas.

1.4.2. Contenedores

Gtkmm agrupa los diferentes contenedores en dos grupos principales, losque pueden almacenar diferentes widgets y los que solo pueden almacenaruno o un numero determinado de widgets. Los primeros ofrecen una interfazmas completa para anadir los widgets, proporcionando incluso una semejantea la ofrecida por los diferentes contenedores de la STL (Standard TemplateLibrary), ademas de la propia. Todos los contenedores son tambien widgetspor lo que se pueden anadir unos dentro de otros. Algunos poseen elementos

1.4 Breve introduccion a Gtkmm 5

Figura 1.1: Ventana con diferentes tipos de widgets.

visuales y otros simplemente se encargan de organizar los widgets en unadisposicion determinada.Los contenedores mas comunes que ofrece Gtkmm son los siguientes:

Gtk::Frame Encuadra un widget en un marco que opcionalmente puedetener un tıtulo.

Gtk::Paned Puede contener dos widgets que separa mediante un lıneadivisoria que se puede desplazar. Existen dos tipos diferentes que secomportan exactamente igual, a excepcion que uno hace la divisionvertical y el otro horizontalmente (Gtk::VPaned y Gtk::HPaned).

Gtk::ScrolledWindow Se utiliza para crear una area desplazable me-diante barras. Se fija el tamano del area visible y mediante las barrasse puede ver la totalidad del widget contenido.

Gtk::Box Puede contener multiples widgets que distribuye horizontal overticalmente (Gtk::HBox y Gtk::VBox).

Gtk::Table Distribuye los diferentes widgets organizandolos en forma detabla.

6 Introduccion

Gtk::Notebook Contenedor encargado de mostrar diferentes widgets enpestanas.

Existe algunos contenedores especiales que solo pueden contener un tipoespecıfico de widgets:

Gtk::MenuBar Tıpica barra de menus normalmente situada en la partesuperior de la ventana que contiene widgets del tipo Gtk::Menus

Gtk::Menu Contenedor de Gtk::MenuItems que pueden ser opciones uotros menus creando una jerarquıa de submenus

Gtk::Toolbar Usadas normalmente para crear accesos rapidos a las opcio-nes de menu, las barras de herramientas contienen una fila de botones.

1.4.3. Dialogos

Los dialogos son ventanas secundarias que se usan para mostrar ciertainformacion o para hacer preguntas. Gtkmm dispone de algunos dialogosque ayudan al programador y al usuario a realizar determinadas tareas. Sonmuy sencillos de utilizar y algunos de ellos proporcionan un entorno muycompleto para realizar una accion, como la seleccion de un color.Los dialogos proporcionados son los siguientes:

Gtk::MessageDialog Dialogo destinado a mostrar mensajes simples alusuario. En la constructora se puede especificar el texto, tipo de men-saje (de alerta, informacion, etc.) y que botones estandares mostrara.

Gtk::FileSelection Se usa para que el usuario seleccione un fichero o undirectorio, por ejemplo cuando se carga o se guarda algun fichero.

Gtk::ColorSelectionDialog Dialogo que permite al usuario la seleccionde un color. Se muestra su aspecto en la figura 1.2.

Gtk::FontSelectionDialog Permite al usuario elegir una fuente de lasmostradas por el dialogo.

En el siguiente ejemplo se puede ver el codigo necesario para mostrar undialogo que permite al usuario seleccionar un color:Gtk:: ColorSelectionDialog dialog;

int result = dialog.run();

switch (result)

{

case Gtk:: RESPONSE_OK:

// Hacer algo con el color seleccionado

Gdk:: Color col = dialog.get_colorsel ()->get_current_color

();

1.4 Breve introduccion a Gtkmm 7

. . .

break;

case Gtk:: RESPONSE_CANCEL:

// Codigo relativo a la cancelacion del usuario

. . .

break;

default:

break;

}

Figura 1.2: Dialogo de seleccion de un color.

1.4.4. El puntero “inteligente” RefPtr

Como es bien sabido, a diferencia de otros lenguajes, el C++ no disponeen el estandar de recolectores de basura que se encarguen de recuperar lamemoria ocupada por los objetos que no estan referenciados en ningunaparte. Pero existen diferentes implementaciones de punteros “inteligentes”que contabilizan las referencias al objeto y lo eliminan cuando llegan a cero,aunque estos de momento tampoco estan disponibles en el estandar.

Los desarrolladores de Gtkmm decidieron incorporar este tipo de punte-ros a la librerıa (Glib::RefPtr). Esta implementado mediante un templatey se puede utilizar con cualquier objeto que posea los metodos reference yunreference, que todas las clases de la librerıa implementan.

Su uso es parecido al de un puntero normal de C++, para acceder aun atributo o un metodo del objeto referenciado se utiliza el operador ->.Pueden hacerse conversiones entre tipos de punteros mediante las funcio-nes estaticas cast dynamic o cast static. Pero a diferencia de los punteros

8 Introduccion

normales, y otras implementaciones de punteros “inteligentes”, no se puedeutilizar el operador * para acceder a la instancia del objeto.

Muchas de las clases de la librerıa incorporan metodos estaticos paracrear este tipo de punteros referenciando a un nuevo objeto de esa clase,normalmente con los mismos parametros que sus constructoras.

1.4.5. Mecanismo de Signals/Slots

Gtkmm, como la mayorıa de librerıas para crear interfaces graficas, estaorientado a eventos. Cuando ocurre alguno de estos eventos, como que elusuario apriete un boton del raton, se emitira una senal (signal) concretapor el widget que ha recibido dicho evento. Cada widget emite un conjuntodeterminado de senales, que pueden ser capturadas por funciones y/o meto-dos de objetos a los que se denomina ranuras (slots). El siguiente ejemplomuestra como conectar un metodo de una clase a la senal emitida cuandose aprieta un boton de una interfaz:

boton1.signal_clicked ().connect( sigc:: mem_fun (*this , &

HolaMundo :: on_button_clicked));

La declaracion del metodo deberıa ser:

void on_button_clicked ();

Las senales emitidas pueden contener parametros que seran enviados alas ranuras conectadas. Gtkmm comprueba que el numero y tipo de parame-tros de las senales coincida con el de las ranuras que se conectan, pero existenfunciones para ocultar o anadir parametros que da aun mas versatilidad a es-te mecanismo. Por ejemplo, si la funcion a la que queremos conectar tiene unparametro mas que la senal podemos hacer que se anada automaticamenteal emitirse para esa conexion:

boton1.signal_clicked ().connect( sigc::bind( sigc:: mem_fun (*

this , &HolaMundo :: on_button_clicked), "boton 1") );

En este caso la declaracion del metodo serıa la siguiente:

void on_button_clicked(Glib:: ustring nombreBoton);

Capıtulo 2

Uso de BioMedIGU

2.1. Conceptos basicos

2.1.1. El puntero “inteligente” SmartPtr

En la librerıa BioMedIGU se utiliza constantemente el puntero “inte-ligente” SmartPtr. Este puntero permite descargar al usuario la tarea decontrolar la memoria dinamica, contabilizando las referencias a un objeto ydestruyendolo cuando no existe ninguna.

A diferencia de Glib::RefPtr no es intrusivo, es decir, el objeto referen-ciado no ha de implementar ningun metodo para que se pueda utilizar conSmartPtr. Tambien permite acceder a la instancia del objeto referenciado.Aunque es algo peligroso, en ocasiones el objeto ha de ser utilizado comoparametro a una funcion externa a la librerıa y para ello es necesario teneracceso a la instancia.

Muchas de las clases de la librerıa proporcionan metodos para crear unobjeto y devolver una referencia mediante el puntero SmartPtr. Pero tambiense pueden crear utilizando las constructoras de la clase del puntero, en esecaso simplemente se le tiene que pasar como parametro el puntero al objetoque deseamos que se referencie. Por ejemplo si tenemos la clase,

class Clase

{

public:

Clase ():unAtributo (0) {};

void unMetodo ()

{

// hacer algo

}

int unAtributo;

};

para crear una referencia a un objeto nuevo simplemente tendremos quehacer:

10 Uso de BioMedIGU

SmartPtr <Clase > refClase (new Clase ());

El uso de SmartPtr es identico al de un puntero normal. Para accedera los metodos y atributos del objeto referenciado se usa el operador ->, ypara acceder a la instancia del objeto se utiliza el operador *.refClase ->unMetodo ();

unaFuncion (* refClase);

Se puede crear una referencia sin ningun objeto asociado, esto dara evi-dentemente una referencia invalida. Para comprobar la validez de una refe-rencia simplemente se debe poner como condicion de un sentencia if.if (refClase)

{

// Hacer algo con la referencia.

}

SmartPtr tiene comprobacion de tipos en la compilacion, por lo que nose podran asignar referencias con tipos incompatibles, pero sı de una cla-se derivada a su clase base. Tambien se proporcionan un par de metodosestaticos para poder hacer conversiones de una clase base a una clase deri-vada, cast_dynamic y cast_static, que actuan de la misma manera quesus homologas de C++. Si tenemos una clase derivada de Clase,class Derivada : public Clase

{

public:

Derivada ():otroAtributo (0) {};

void otroMetodo ()

{

// hacer algo

}

protected:

int otroAtributo;

};

el siguiente codigo muestra las conversiones validas e invalidas:SmartPtr <Clase > refClase (new Clase ());

SmartPtr <Derivada > refDerivada (new Derivada ());

SmartPtr <Clase > refOtraClase;

SmartPtr <Derivada > refOtraDerivada;

// Valida , son de la misma clase

refOtraClase = refClase;

// Valida , Clase es base de Derivada

refOtraClase = refDerivada;

// Invalida , refOtraClase apunta a un objeto

// de la clase Derivada , pero ha

// de hacerse un cast explıcito

refOtraDerivada = refOtraClase;

2.2 El gestor de ventanas 11

// Valida , se hace el cast explıcito

refOtraDerivada = SmartPtr <Derivada >:: cast_dynamic(

refOtraClase);

// Invalida , el objeto referenciado no es de la

// clase Derivada

refOtraDerivada = SmartPtr <Derivada >:: cast_dynamic(refClase);

2.1.2. Inicializaciones

La librerıa debe inicializarse antes de crear algun objeto o llamar a algu-na funcion. Para ello se proporciona la funcion init, que ademas se encargade inicializar las librerıas de las que depende (Gtkmm, Gnomecanvasmm,Gtkglextmm). Esta funcion recibe como parametos los argumentos del pro-grama (argc, argv) y los modifica eliminando todas las opciones que seande la librerıa o alguna de las que se depende.

El siguiente ejemplo muestra el tıpico main de un programa que utilizala librerıa:

int main (int argc , char *argv [])

{

// Inicializar la librerıa.

BMI::init(argc ,argv);

// Crear la ventana principal

SmartPtr <VentanaPrincipal > win = VentanaPrincipal :: crear();

// Mostrar la ventana

win ->show();

// Iniciar el bucle de eventos

Gtk::Main::run(*win);

return 0;

}

2.2. El gestor de ventanas

BioMedIGU proporciona un gestor de ventanas que se encarga de man-tener la jerarquıa de las ventanas y de comunicar el cierre de una ventanaa las ventanas que dependan de ella. Para acceder al gestor se puede crearun objeto de la clase GestorVentanas o acceder mediante la clase Entornode la que solo existira una instancia.

GestorVentanas gv;

Entorno entorno = Entorno :: getInstancia ()

GestorVentanas& otro_gv = entorno.getGestorVentanas ();

12 Uso de BioMedIGU

Tambien se puede acceder al gestor al que pertenece una ventana me-diante el metodo getGestorVentanas que poseen todas las ventanas.

GestorVentanas& gv = refVentana ->getGestorVentanas ();

El gestor de ventanas proporciona metodos para anadir y eliminar ven-tanas con o sin dependencias.

//Se a~nade sin dependencias

gv.addVentana(refVentana);

//Se a~nade dependiendo de refVentanaPadre

gv.addVentana(refVentana , refVentanaPadre);

Al cerrar una ventana, llamando al metodo cerrar o usando el botonpara tal efecto, el gestor primero cerrara sus ventanas dependientes. Si al-guna no se cierra, por decision del usuario o del programador, tampocose cerrara la propia ventana. Para tomar estas decisiones antes de cerrarcualquier ventana se llama al metodo confirmarCerrar y se envıa unasenal a la que se han podido conectar ranuras (slots) mediante el metodoaddSlotConfirmarCerrar. Si el metodo o alguna de las ranuras devuelvefalso la ventana no se cerrara, y en consecuencia ninguna las ventanas de lasque depende. Una vez decidido el cierre de una ventana y antes de eliminarla instancia se lanza una senal a la que se pueden conectar ranuras medianteel metodo addSlotCerrar.

Esta caracterıstica permite facilmente anadir comprobaciones y/o de-legar en el usuario el cierre de la ventana, por ejemplo, presentandole undialogo informando que se tienen datos modificados y preguntarle si desarguardar, descartar los cambios o cancelar el cierre.

En el gestor de ventanas tambien se dispone de un mecanismo quepermite enviar mensajes de una ventana a sus dependientes. Para facili-tar el su uso existen dos metodos en la clase Ventana, enviarMensaje ymensajeRecibido. El primero envıa el mensaje (un entero) a sus ventanasdependientes y recibe como respuesta un booleano, que sera cierto si todaslas ventanas responden cierto, o falso si alguna responde falso. El segundoes un metodo abstracto que deberan reimplementar las ventanas suceptiblesde recibir mensajes. Como parametro se le pasara el mensaje (un entero) ydeberan devolver la respuesta (un booleano).

ventanaPadre.enviarMensaje(MENSAJE_ACTUALIZAR_DATOS);

bool VentanaDependiente :: mensajeRecibido(int mensaje)

{

bool respuesta;

switch (mensaje)

{

...

case MENSAJE_ACTUALIZAR_DATOS

actualizarDatos ();

respuesta = true;

2.3 Ventana de menus 13

break;

...

default:

respuesta = true;

}

return respuesta;

}

Normalmente los programas disponen de una ventana principal de la quedepende la ejecucion del programa, es decir, mientras la ventana esta abiertael programa esta en ejecucion. Pero en ocasiones un programa puede dispo-ner de varias ventanas principales. Por ejemplo podrıamos tener un editorde imagenes en el que estuvieramos editando varias imagenes en ventanasidenticas pero separadas. Evidentemente no quermos que el programa ter-mine cuando se cierra la primera ventana que se ha abierto.

En Gtkmm se pueden obtener ambos comportamientos mediante la claseGtk::Main. Existen dos funciones que inician el blucle principal de eventos.Una recibe como parametro una ventana y termina el bucle cuando se cierraesa ventana, (Gtk::Main::run(Window win)). La segunda no recibe ningunparametro (Gtk::Main::run()) y hay que finalizar el bucle explıcitamentemediante la funcion Gtk::Main::quit(). En este caso podemos hacer que elgestor de ventanas haga esa llamada por nosotros cuando se cierre la ultimaventana. Simplemente deberemos indicarlo al crear el gestor o mendiante elmetodo GestorVentanas::setPararMainLoop (bool parar).

2.3. Ventana de menus

La librerıa proporciona una ventana que implementa la tıpica ventana demenus, que permite de una manera muy sencilla insertar menus, submenusy opciones en la barra de menus y la barra de herramientas.

La manera mas sencilla es, una vez instanciada la ventana, anadir lasopciones que deseemos como se muestra a continuacion:

SmartPtr <VentanaMenu > refVen = VentanaMenu :: crear();

// A~nadir un menu

refVen ->addMenu("menu1","Menu1");

// A~nadir una opcion

refVen ->addOpcion("menu1", Opcion("opcion1", "Opcion1", sigc

:: ptr_fun(on_opcion1), "./ iconos/icono1.png", true));

Los slots se forman a partir de funciones o metodos que tienen la siguientedeclaracion:

void on_opcion1 (Opcion* op);

La opcion que se recibe como parametro es la que el usuario ha activado,mediante la cual podemos acceder a la VentanaMenu a la que pertenece:

14 Uso de BioMedIGU

VentanaMenu* pven = op ->getVentanaMenu ();

Una VentanaMenu nada mas instanciada no contiene nada en su par-te principal. Una vez anadidas las opciones que deseemos se puede anadircualquier widget a la area principal de la ventana accediendo al contenedormediante el metodo:

refVen ->getBoxContenido ().pack_start(algun_widget);

Esta serıa una forma de trabajar con la VentanaMenu, pero la forma mascorrecta que nos permitirıa reutilizar la ventana en otra parte del codigo,y extenderla anadiendole mas opciones o completando el contenido, serıacreando una clase que herede de la ventana de menus.

class VentanaPrincipal : public VentanaMenu

{

public:

VentanaPrincipal ()

{

// a~nadir los menus y las opciones que deseemos

addMenu("menu1", "Menu1");

addOpcion("menu1", Opcion("opcion1", "Opcion1", sigc::

mem_fun (*this , &VentanaPrincipal :: on_opcion1), "./

iconos/icono1.png",true));

// Crear e inicializar el widget del contenido.

widget_contenido = ...

// a~nadir el contenido que queramos

getBoxContenido ().pack_start(widget_contenido);

}

~VentanaPrincipal (){};

protected:

on_opcion1(Opcion *op)

{

// Hacer algo.

}

};

La ventana de menus proporciona un mecanismo que permite la activa-cion y desactivacion automatica de las opciones segun el contexto/estado dela ventana. Cada menu y opcion posee una lista de estados en los que debeestar activo, y las ventanas tienen un lista de los estados que actualmenteestan activos. Si una opcion posee algun estado de la lista de estados activosesta aparecera activada, en caso contrario aparecera desactivada. Excepcio-nalmente cuando una opcion no tiene ningun estado se interpretara que debeestar activa siempre. Los estados se representan con enteros y se anaden alos menus y opciones mediante los metodos addEstado.

// Crear el menu

Menu m ("menu1", "Menu1");

// A~nadir un estado al menu

2.3 Ventana de menus 15

m.addEstado (1);

// Crear una opcion

Opcion op("opcion1", "Opcion1", sigc:: mem_fun(on_opcion1),"./

iconos/icono1.png",true);

// A~nadir los estados en los que estara activa

op.addEstado (1);

op.addEstado (2);

// A~nadir la opcion al menu

m.addOpcion(op);

// A~nadir el menu a la ventana

refVen ->addMenu(m);

Los menus en realidad no se activan/desactivan, los estados son propa-gados a sus opciones y submenus.Para modificar la lista de estados activos de la ventana se disponen de losmetodos addEstadoActivo y delEstadoActivo.

refVen ->delEstadoActivo (2);

refVen ->addEstadoActivo (1);

Automaticamente se propaga el estado a todos los menus y la barra deherramientas, activandose o desactivandose las opciones.

Las opciones se anaden automaticamente a la barra de herramientas siası se ha indicado en la constructora mediante el parametro adecuado. Secreara un icono con la imagen que se ha proporcionado mediante el path,sino simplemente se creara con el texto de la opcion.

La ventana tambien proporciona una barra de estado donde podemosmostrar al usuario informacion textual. En principio solo tiene una zonadonde escribir pero se pueden crear las que queramos con un tamano prefi-jado o variable segun el texto que se muestra.

// Mostrar un texto en la zona por defecto , la 0.

refVen ->getBarraEstado ().ponerTexto("Texto Zona 0");

// Crear una zona sin tama~no prefijado

refVen ->getBarraEstado ().addZona ();

// Crear una zona con el tama~no prefijado a 100 pixels

refVen ->getBarraEstado ().addZona (100);

// Mostrar un texto en la zona 2

refVen ->getBarraEstado ().ponerTexto("Texto Zona 2" ,2);

Todas las barras que tiene la ventana pueden ocultarse o mostrarse,segun el criterio del programador, o del usuario si se ponen opciones paratal efecto.

//Se oculta la barra de herramientas.

refVen ->mostrarBarraHerramientas(false);

16 Uso de BioMedIGU

//Se muestra la barra de estado.

refVen ->mostrarBarraEstado(true);

//Se muestra la barra de menus.

refVen ->mostrarBarraMenu ();

El siguiente ejemplo muestra la creacion de una ventana de menus a laque se le ha anadido como contenido un widget que permite mostrar y editartexto. Se ha creado un menu con 3 opciones, una para salir de la ventana, ydos para mostrar el mecanismo de activacion/desactivacion automatica. Laventana se muestra en la figura 2.1.

Figura 2.1: Ejemplo de una ventana de menus.

#include <gtkmm/main.h>

#include <gtkmm/textview.h>

#include <gtkmm/messagedialog.h>

#include <iostream >

#include <stdlib.h>

#include <gui/init.h>

#include <gui/gestorventanas.h>

#include <gui/ventanamenu.h>

class VentanaPrincipal : public VentanaMenu

{

protected:

Gtk:: TextView m_TextView;

public:

VentanaPrincipal ()

{

// Consultar el directorio de instalacion

2.3 Ventana de menus 17

char *pdir = getenv("DEMODIR");

Glib:: ustring dir("./");

if (pdir)

dir = pdir;

// Poner el titulo a la ventana

set_title("Ejemplo VentanaMenu");

// Establecer el tama~no inicial de la ventana

set_default_size (300 ,300);

// Crear un menu

Menu m("menu1","Menu1");

// Crear un menu

Menu m2("submenu1","Submenu1");

// A~nadir un estado al menu

m2.addEstado (2);

// Crear una opcion

Opcion op1 ("opcion1","Opcion1",sigc:: mem_fun (*this ,&

VentanaPrincipal :: on_opcion1),dir + "/iconos/opcion1

.png",true ,"<control >1");

// A~nadir un estado a la opcion

op1.addEstado (1);

// Crear una opcion

Opcion op2 ("opcion2","Opcion2",sigc:: mem_fun (*this ,&

VentanaPrincipal :: on_opcion2),dir + "/iconos/opcion2

.png",true ,"<control >2");

// A~nadir un estado a la opcion

op2.addEstado (2);

// Crear una opcion

Opcion op21 ("op_nuevaVentana","Nueva Ventana",sigc::

mem_fun (*this ,& VentanaPrincipal :: on_nuevaVentana),

dir + "/iconos/opcion21.png",true ,"<control >3");

// Crear una opcion

Opcion op_salir("op_salir","Salir",sigc:: mem_fun (*this

,& VentanaPrincipal :: on_opcion_salir),false ,Glib::

ustring("<alt >s"));

// A~nadir las opciones al menu

m2.addOpcion(op21);

m.addOpcion(op1);

m.addOpcion(op2);

m.addSubMenu(m2);

m.addSeparador ();

m.addOpcion(op_salir);

// A~nadir el menu a la ventana

addMenu(m);

// A~nadir el contenido

18 Uso de BioMedIGU

getBoxContenido ().pack_start( m_TextView);

// Establecer el estado inicial

cambiarEstado (1);

// Mostrar el estado en la barra de estado

getBarraEstado ().ponerTexto("Estado 1");

// Mostrar todos los widgets

show_all_children ();

}

~VentanaPrincipal (){};

void on_opcion1(Opcion *op)

{

// Cambiar de estado la ventana

op->getVentanaMenu ()->cambiarEstado (2);

// Mostrar el estado en la barra de estado

op->getVentanaMenu ()->getBarraEstado ().ponerTexto("

Estado 2");

}

void on_opcion2(Opcion *op)

{

// Cambiar de estado la ventana

op->getVentanaMenu ()->cambiarEstado (1);

// Mostrar el estado en la barra de estado

op->getVentanaMenu ()->getBarraEstado ().ponerTexto("

Estado 1");

}

void on_opcion_salir(Opcion *op)

{

// Cerrar la ventana

op->getVentanaMenu ()->cerrar ();

}

void on_nuevaVentana(Opcion *op)

{

// Cerrar la ventana

SmartPtr <VentanaPrincipal > refVen = VentanaPrincipal ::

crear ();

op->getVentanaMenu ()->getGestorVentanas ().addVentana(

refVen ,this ->getIdVentana ());

refVen ->show();

}

static SmartPtr <VentanaPrincipal > crear ()

{

// Crear una referencia a una ventana nueva

return (SmartPtr <VentanaPrincipal >(new VentanaPrincipal

()));

}

virtual bool confirmarCerrar ()

{

2.4 Ventana de visualizacion grafica 19

int result;

Gtk:: MessageDialog m (*this , Glib:: convert(">Seguro que

quieres cerrar?","UTF -8", "ISO -8859 -15"),true ,Gtk::

MESSAGE_QUESTION , Gtk:: BUTTONS_OK_CANCEL ,true);

this ->raise();

result = m.run();

return (result == Gtk:: RESPONSE_OK);

}

};

int main (int argc , char *argv [])

{

// Inicializar las librerias

BMI::init(argc , argv);

// Crear un gestor de ventanas

GestorVentanas gv ;

// Crear la ventana

SmartPtr <VentanaPrincipal > refVen = VentanaPrincipal :: crear

();

// A~nadirla al gestor

gv.addVentana(refVen);

// Mostrar la ventana

refVen ->show();

// Iniciar el bucle de eventos

Gtk::Main::run(* refVen);

return 0;

}

2.4. Ventana de visualizacion grafica

BioMedIGU implementa una ventana que permite visualizar graficos me-diante la librerıa GL, y editarlos si se programan los eventos adecuadamente.Esta ventana proporciona cuatro areas de visualizacion independientes quecapturan los eventos del raton y los envıa a un conversor al que se conectanlas funciones o metodos que desee el programador. El conversor transfor-ma estos eventos en llamadas a esas funciones segun el estado en el quese encuentra. Esta ventana hereda de VentanaMenu, por lo tanto todo loexplicado en la seccion anterior es aplicable a esta ventana.

Para crear la ventana simplemente es necesario indicar el modo de con-figuracion de la librerıa GL. El modo viene determinado por la librerıa Gtk-glextmm, para conocer los modos existentes se puede consultar la referencia

20 Uso de BioMedIGU

de esa librerıa, que podemos encontrar en su web1.

SmartPtr <VentanaGL > refVenGL = VentanaGL ::crear(Gdk::GL::

MODE_RGB|Gdk::GL:: MODE_DEPTH|Gdk::GL:: MODE_DOUBLE);

Una vez creada podemos dar un nombre a las cuatro areas de la ventana.

refVenGL ->setNombreAreaGL (0,"FRONTAL");

refVenGL ->setNombreAreaGL (1,"LATERAL");

refVenGL ->setNombreAreaGL (2,"TRASERA");

refVenGL ->setNombreAreaGL (3,"ISOMETRICA");

Las areas poseen un campo entero (flag) que puede ser usado para al-macenar la informacion que desee el programador.

refVenGL ->getAreaGL (0).setFlag(info);

Los diferentes eventos del conversor a los que podemos conectar funciones ometodos son los siguiente:

Movimiento del raton: Se envıa cuando el usuario mueve el ratonsobre de la area.

Movimiento del raton con boton apretado: Se envıa cuando elusuario mueve el raton sobre de la area mientras mantiene uno de losbotones del raton apretado.

Apretar un boton: Se lanza cuando el usuario aprieta un botonsobre el area.

Soltar un boton: Se envıa cuando el usuario suelta el boton quepreviamente habıa apretado sobre una area.

Exposicion (Expose): Este evento se envıa cuando se visualiza laarea, por ejemplo la primera vez que se muestra o cuando se minimi-za/mueve una ventana que tapaba parcial o totalmente la area.

Creacion (Realize): Este evento se envıa una vez finalizada la crea-cion de la area. Se suele utilizar para inicializar la informacion nece-saria de esa area o la inicializacion del GL.

Redimension (Resize): Se lanza cuando la area cambia de tamano,suele utilizarse para recalcular el viewport y la camara si es necesario.

Cada uno de los eventos envıa unos parametros diferentes a las funciones.La siguientes funciones son un ejemplo de como han de estar definidas paracada tipo de evento.

1http://gtkglext.sourceforge.net

2.4 Ventana de visualizacion grafica 21

void on_move (ConversorEventosGL :: DatosMovimientoRaton dat ,

AreaGL *area);

void on_move_with_button (ConversorEventosGL ::

DatosMovimientoRaton dat ,guint boton , AreaGL *area);

void on_button_press (gdouble x, gdouble y, guint boton ,

AreaGL *area);

void on_button_release (gdouble x, gdouble y, guint boton ,

AreaGL *area);

void on_expose (AreaGL *area);

void on_realize(AreaGL *area);

void on_resize (int width ,int height , AreaGL *area);

Para conectar los eventos se proporciona un metodo para cada tipo deevento. Podemos conectar una funcion/metodo a un evento por cada areay/o cada estado del conversor, o bien si no los especificamos se conectara paratodas las areas y como la funcion por defecto, que se ejecutara si no hayninguna definida para el estado actual del conversor.

// Conecta una funcion al evento expose para todas

// las areas y como funcion por defecto.

refVenGL ->addSlotExpose( sigc:: ptr_fun (& on_expose) );

// Conecta una funcion al evento del movimiento del raton

// con un boton apretado para el estado 0 y la area 1.

refVenGL ->addSlotMovimientoRatonConBoton(sigc:: ptr_fun (&

on_move_with_button) ,0,1);

La ventana en un principio visualiza las cuatro areas, pero podemosmaximizar una area que ocupara todo el contenido de la parte principal dela ventana. Tambien podemos restaurar la vista para visualizar las cuatroareas de nuevo.

// Maximizar la area activa

refVenGL ->maximizarAreaGL ();

// Maximizar la area 2

refVenGL ->maximizarAreaGL (2);

// Volver a visualizar las cuatro areas

refVenGL ->restaurarVista ();

La ventana muestra en la barra de estado el nombre de la area activay las coordenadas del cursor cuando esta sobre el area activa. Si por algunmotivo no queremos que se muestra alguna de estas informaciones siemprepodemos ocultarlas, o podemos proporcionar al usuario alguna opcion paraque pueda cambiar el comportamiento.

// Se oculta la zona de la barra de estado donde se muestra

el nombre de la area activa

refVenGL ->mostrarAreaActiva(false);

// Se oculta la zona de la barra de estado donde se muestra

las coordenadas del cursor

refVenGL ->mostrarCoordenadasCursor(false);

22 Uso de BioMedIGU

Antes de realizar cualquier llamada a GL es necesario inicializar la areapara que “capture” los comandos de GL. Tambien es necesario indicar quese han finalizado las llamadas a GL y llamar al metodo swapGL para mostrarlos cambios. El siguiente codigo muestra la estructura correcta que tendrıaque tener una funcion que llame a funciones de GL, por ejemplo el eventode exposicion.void on_expose(AreaGL *area)

{

if (area ->initGL ())

{

// Codigo GL

.

.

.

area ->swapGL ();

area ->endGL();

}

}

Hasta ahora en esta seccion se ha mostrado como utilizar la VentanaGLinstanciandola, pero, como se ha comentado anteriormente, esta quizas noes la mejor manera de utilizar la librerıa. En el siguiente ejemplo se muestrala creacion de una ventana sencilla de visualizacion grafica heredando de laclase VentanaGL.

Figura 2.2: Ejemplo de una ventana de visualizacion grafica.

2.4 Ventana de visualizacion grafica 23

#include <GL/gl.h>

#include <GL/glu.h>

#include <gtkmm/main.h>

#include <gui/init.h>

#include <gtkmm/textview.h>

#include <libgnomecanvasmm/init.h>

#include <gui/gestorventanas.h>

#include <gui/ventanagl.h>

#include "cam.h"

#include "infoarea.h"

typedef enum {SINACCION , ZOOM , PAN , GIROX , GIROY , GIROZ}

TipoEstado;

class VentanaPrincipal : public VentanaGL

{

protected:

InfoArea infos [4];

public:

VentanaPrincipal(Gdk::GL:: ConfigMode modo)

: VentanaGL(modo)

{

char *pdir = getenv("DEMODIR");

Glib:: ustring dir("./");

if (pdir)

dir = pdir;

for (int i=0;i<4;i++)

{

infos[i]. is_solid = (i %2==0);

infos[i].cx=infos[i].cy=infos[i].cz =0.0;

infos[i].radi = 1.0;

infos[i].angx = infos[i].angy = infos[i].angz =

0.0;

infos[i].vrpx = 0;

infos[i].vrpy = 0;

infos[i].vrpz = 0;

infos[i]. is_set = true;

if (i==0 || i==1)

infos[i].d = 6;

else

infos[i].d = 5;

}

// Poner el titulo a la ventana

set_title("Ejemplo VentanaGL");

// Establecer el tama~no inicial de la ventana

set_default_size (600 ,600);

// A~nadir un menu

addMenu ("acciones", "Acciones");

addSubMenu ("acciones","girar", "Girar" ,0);

24 Uso de BioMedIGU

// A~nadir algunas opciones

addOpcion("acciones/girar", Opcion("ejex", "Eje X",sigc

::bind(sigc:: mem_fun (*this ,& VentanaPrincipal ::

cambiar_estado_conversor),GIROX),false ,Glib:: ustring

("<control >x")));

addOpcion("acciones/girar", Opcion("ejey", "Eje Y",sigc

::bind(sigc:: mem_fun (*this ,& VentanaPrincipal ::

cambiar_estado_conversor),GIROY),false ,Glib:: ustring

("<control >y")));

addOpcion("acciones/girar", Opcion("ejez", "Eje Z",sigc

::bind(sigc:: mem_fun (*this ,& VentanaPrincipal ::

cambiar_estado_conversor),GIROZ),false ,Glib:: ustring

("<control >z")));

addOpcion("acciones", Opcion("zoom", "Zoom",sigc::bind(

sigc:: mem_fun (*this ,& VentanaPrincipal ::

cambiar_estado_conversor),ZOOM),false ,Glib:: ustring(

"<control >a")));

addOpcion("acciones",Opcion("pan", "Pan",sigc::bind(

sigc:: mem_fun (*this ,& VentanaPrincipal ::

cambiar_estado_conversor),PAN),false ,Glib:: ustring("

<control >p")));

addSeparador("acciones");

addOpcion("acciones", Opcion("maximizar","Maximizar",

sigc:: mem_fun (*this ,& VentanaPrincipal ::

on_opcion_maximizar),dir + "/iconos/maximizar.png",

true ,Glib:: ustring("<control >m")));

addOpcion("acciones", Opcion("restaurar","Restaurar",

sigc:: mem_fun (*this ,& VentanaPrincipal ::

on_opcion_restaurar),dir + "/iconos/restaurar.png",

true ,Glib:: ustring("<control >r")));

addSeparador("acciones");

addOpcion("acciones",Opcion("salir","Salir",sigc::

mem_fun (*this ,& VentanaPrincipal :: on_opcion_salir),

false ,Glib:: ustring("<alt >s")));

// Poner nombres a las areas

setNombreAreaGL (0,"AREA0");

setNombreAreaGL (1,"AREA1");

setNombreAreaGL (2,"AREA2");

setNombreAreaGL (3,"AREA3");

// Cambiar el color del marco de la area activa

setColorMarcoActivo(Gdk::Color("red"));

// activarAreaGL (1);

// activarAreaGL (0);

// Conectar los metodos a los eventos

addSlotRealize(sigc:: mem_fun (*this , &VentanaPrincipal ::

on_realize));

addSlotResize(sigc:: mem_fun (*this , &VentanaPrincipal ::

on_resize));

addSlotExpose(sigc:: mem_fun (*this , &VentanaPrincipal ::

on_expose1) ,-1,0);

2.4 Ventana de visualizacion grafica 25

addSlotExpose(sigc:: mem_fun (*this , &VentanaPrincipal ::

on_expose1) ,-1,1);

addSlotExpose(sigc:: mem_fun (*this , &VentanaPrincipal ::

on_expose2) ,-1,2);

addSlotExpose(sigc:: mem_fun (*this , &VentanaPrincipal ::

on_expose2) ,-1,3);

addSlotMovimientoRatonConBoton(sigc:: mem_fun (*this , &

VentanaPrincipal :: on_giraXcam),GIROX ,-1);

addSlotMovimientoRatonConBoton(sigc:: mem_fun (*this , &

VentanaPrincipal :: on_giraYcam),GIROY ,-1);

addSlotMovimientoRatonConBoton(sigc:: mem_fun (*this , &

VentanaPrincipal :: on_giraZcam),GIROZ ,-1);

addSlotMovimientoRatonConBoton(sigc:: mem_fun (*this , &

VentanaPrincipal :: on_zoom),ZOOM ,-1);

addSlotMovimientoRatonConBoton(sigc:: mem_fun (*this , &

VentanaPrincipal :: on_pan),PAN ,-1);

// Mostrar todos los widgets

show_all_children ();

}

~VentanaPrincipal (){};

void on_opcion_maximizar(Opcion *op)

{

// Consultar la ventana a la que pertenece la opcion

VentanaGL *ven = dynamic_cast <VentanaGL *>(op->

getVentanaMenu ());

// Si es una VentanaGL maximizar la area activa

if (ven)

ven ->maximizarAreaGL ();

}

void on_opcion_restaurar(Opcion *op)

{

// Consultar la ventana a la que pertenece la opcion

VentanaGL *ven = dynamic_cast <VentanaGL *>(op->

getVentanaMenu ());

// Si es una VentanaGL mostrar las cuatro areas

if (ven)

ven ->restaurarVista ();

}

void on_opcion_salir(Opcion *op)

{

// Cerrar la ventana

op ->getVentanaMenu ()->cerrar ();

}

void on_expose1(AreaGL *area)

{

if (area ->initGL ())

{

// Codigo GL

26 Uso de BioMedIGU

glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

SetCameraGL(infos[area ->getIdAreaGL ()]);

PintaEsfera(infos[area ->getIdAreaGL ()]);

area ->swapGL ();

area ->endGL();

}

}

void on_expose2(AreaGL *area)

{

if (area ->initGL ())

{

// Codigo GL

glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

SetCameraGL(infos[area ->getIdAreaGL ()]);

PintaTeapot(infos[area ->getIdAreaGL ()]);

area ->swapGL ();

area ->endGL();

}

}

void on_realize (AreaGL *area)

{

if (area ->initGL ())

{

// Codigo GL

InitGLBasic(infos[area ->getIdAreaGL ()],area ->

get_width (), area ->get_height ());

area ->endGL();

}

}

void on_resize(int width ,int height ,AreaGL *area)

{

if (area ->initGL ())

{

// Codigo GL

glViewport (0,0,width ,height);

area ->endGL();

}

}

void on_giraXcam(ConversorEventosGL :: DatosMovimientoRaton

dat , guint boton , AreaGL *area)

{

GiraXCamera(infos[area ->getIdAreaGL ()],(int) -dat.xfin

, (int)-dat.yfin , (int)-dat.xini , (int)-dat.yini ,

area ->get_width (),area ->get_height ());

area ->queue_draw ();

}

2.4 Ventana de visualizacion grafica 27

void on_giraYcam(ConversorEventosGL :: DatosMovimientoRaton

dat , guint boton , AreaGL *area)

{

GiraYCamera(infos[area ->getIdAreaGL ()],(int)-dat.xfin ,

(int)-dat.yfin , (int)-dat.xini , (int)-dat.yini ,

area ->get_width (),area ->get_height ());

area ->queue_draw ();

}

void on_giraZcam(ConversorEventosGL :: DatosMovimientoRaton

dat , guint boton , AreaGL *area)

{

GiraZCamera(infos[area ->getIdAreaGL ()],(int)-dat.xfin ,

(int)-dat.yfin , (int)-dat.xini , (int)-dat.yini ,

area ->get_width (),area ->get_height ());

area ->queue_draw ();

}

void on_pan(ConversorEventosGL :: DatosMovimientoRaton dat ,

guint boton , AreaGL *area)

{

PanCamera(infos[area ->getIdAreaGL ()],(int)-dat.xfin , (

int)dat.yfin , (int)-dat.xini , (int)dat.yini , area ->

get_width (),area ->get_height ());

area ->queue_draw ();

}

void on_zoom(ConversorEventosGL :: DatosMovimientoRaton dat

, guint boton , AreaGL *area)

{

ModifCamera(infos[area ->getIdAreaGL ()],(int)dat.xfin ,

(int)dat.yfin , (int)dat.xini , (int)dat.yini , area ->

get_width (),area ->get_height ());

area ->queue_draw ();

}

void cambiar_estado_conversor(Opcion* op ,TipoEstado

estado)

{

for (int i=0; i<4; i++)

{

getConversorEventosGL(i).setEstado(estado);

}

}

static SmartPtr <VentanaPrincipal > crear(Gdk::GL::

ConfigMode modo)

{

// Crear una referencia a una ventana nueva

28 Uso de BioMedIGU

return (SmartPtr <VentanaPrincipal >(new VentanaPrincipal

(modo)));

}

};

int main (int argc , char *argv [])

{

// Inicializar las librerias

BMI::init(argc ,argv);

// Crear un gestor de ventanas

GestorVentanas gv ;

// Crear la ventana

SmartPtr <VentanaPrincipal > refVen = VentanaPrincipal :: crear

(Gdk::GL:: MODE_RGB|Gdk::GL:: MODE_DEPTH|Gdk::GL::

MODE_DOUBLE);

// A~nadirla al gestor

gv.addVentana(refVen);

// Mostrar la ventana

refVen ->show();

// Iniciar el bucle de eventos

Gtk::Main::run(* refVen);

return 0;

}

2.5. Ventana de parametros/opciones

BioMedIGU tambien ofrece un mecanismo que permite a un usuario en-trar/modificar parametros u opciones. Esta implementado mediante panelesque muestran los widgets necesarios para que el usuario pueda modificar losvalores de las opciones. Existen opciones para los tipos basicos (entero, real, booleano y texto) y algunas opciones para tipos mas especıficos (color,fichero y seleccion)

El panel verifica la entrada del usuario para que los valores devueltosal programador siempre sean validos. Tambien se ofrecen unas entradas es-peciales que estan formadas por un numero determinado de opciones delmismo tipo, ası por ejemplo podemos anadir una opcion para preguntar unpunto de 3 dimensiones mediante una sola entrada formada por tres numerosreales.

Las opciones se proporcionan mediante una lista organizada en gruposque se mostraran diferenciados, o no, segun el tipo de panel que se utilice.Al crear los grupos podemos indicar el numero de columnas con las que se

2.5 Ventana de parametros/opciones 29

mostraran las opciones de ese grupo.La librerıa proporciona un dialogo para cada tipo de panel que existe,

de modo que tenemos los siguientes tipos de ventanas de opciones:

VentanaOpcionesScroll: No diferencia los grupos y muestra las op-ciones una debajo de otra, pero anade barras de desplazamiento ver-tical y horizontal.

VentanaOpcionesTabs: Muestra cada grupo en una pestana dife-rente mostrando las opciones en el numero columnas indicado.

VentanaOpcionesMarcos: Anade alrededor de cada grupo con unmarco, mostrando el texto del grupo en la esquina superior-izquierda.Cada grupo se mostrara con el numero de columnas indicado.

El siguiente codigo muestra como crear esta lista de opciones.

// Crear la lista de opciones

ListaOpcionesEntrada lops;

// Crear los grupos

GrupoOpcionesEntrada grp1 ("grupo1","Grupo 1" ,2);

GrupoOpcionesEntrada grp2 ("grupo2","Grupo 2");

// A~nadir las opciones

grp1.addOpcion(EntradaString ("Opcion1","opcion1","valor

inicial"));

grp1.addOpcion(EntradaBool ("Opcion2","opcion2",false));

EntradaEntero ee("Opcion3","opcion3" ,25);

grp2.addOpcion(ee);

grp2.addOpcion(EntradaNReal ("Opcion4","opcion4" ,3));

// A~nadir los grupos a la lista

lops.addGrupo(grp1);

lops.addGrupo(grp2);

Una vez creada la lista simplemente tenemos que crear la ventana pasando-le la lista como parametro.

SmartPtr <VentanaOpcionesMarcos > refVen =

VentanaOpcionesMarcos :: crear(lops ,"Opciones");

Cuando esta creada deberemos mostrarla al usuario y dejarle interactuarcon ella. Para este cometido se dispone del metodo run que muestra laventana y le permite interactuar con ella. Cuando el usuario decide terminarla interaccion apretara uno de los botones que tiene la ventana, aceptar ocancelar. El metodo run devuelve el tipo de boton que ha apretado el usuarioy podemos acceder a la lista resultante de la interaccion, o la lista inicial siha apretado cancelar, mediante el metodo getListaOpcionesEntrada.

30 Uso de BioMedIGU

VentanaOpciones :: AccionUsuario result = refVen ->run();

if (result == VentanaOpciones :: RESULT_OK)

{

lops = refVen ->getListaOpcionesEntrada ();

// Hacer algo con la lista

...

}

else

{

// Codigo para cuando el usuario cancela

...

}

Mediante la lista de opciones podemos acceder al valor que ha quedadode la interaccion del usuario. Para ello se dispone de diferentes metodosmediante los que podemos acceder a una opcion concreta, acceder a ungrupo concreto e iterar por sus opciones, o iterar por todos los grupos y porsus opciones. Aunque la manera mas util y comoda es la primera.

SmartPtr <OpcionEntrada > refOp = lops.getOpcion("grupo1","

opcion1");

Podemos acceder al valor de la opcion mediante el metodo getValor, quedevuelve el texto que representa al valor, pero tambien podemos hacer uncast al tipo de opcion concreto y acceder mediante el metodo que devuelveel valor en el tipo adecuado.

// Acceder a la opcion

SmartPtr <OpcionEntrada > refOp = lops.getOpcion("grupo1","

opcion2");

// Acceder al string que representa la opcion

Glib:: ustring valor = refOp ->getValor ();

// Acceder al valor en booleano

SmartPtr <EntradaBool > refOpBool = SmartPtr <EntradaBool >::

cast_dynamic(refOp);

bool valor_bool = refOpBool ->getBool ();

Todas las opciones disponen de una senal que se lanza cuando son modi-ficadas. Conectando funciones o metodos a esas senales podemos modificaro activar/desactivar opciones durante la interaccion del usuario. Por ejem-plo, el valor de una determinada opcion puede depender del valor de otra,y mediante esta senal se puede crear una funcion que recalcule su valor y lamodifique. O, por ejemplo, unas opciones pueden ser necesarias solo cuandouna determinada opcion tiene un valor, podemos conectar una ranura a lasenal de esta opcion y activar/desactivar las otras opciones en funcion de suvalor.

Hay que tener en cuenta que la lista que tiene la ventana es una copiade la que se le pasa como parametro, ası que si deseamos modificar alguna

2.5 Ventana de parametros/opciones 31

opcion o activar/desactivarla deberemos acceder a la opcion de la lista de laventana.

Tambien debemos tener en cuenta que podemos caer en un bucle infi-nito, si modificamos en una ranura una opcion que tiene otra ranura quemodifica la opcion que acaba de modificar el usuario. En este caso podemosdesactivar momentaneamente la notificacion de cambios mediante el metodosetNotificarCambios.

En el siguiente ejemplo se puede ver como se crea una ventana sencillay se utiliza el mecanismo descrito en los parrafos anteriores.

Figura 2.3: Ejemplo de una ventana de opciones.

#include <gtkmm/main.h>

#include <gui/listaopcionesentrada.h>

#include <gui/ventanaopcionesmarcos.h>

#include <gui/entradastring.h>

#include <gui/entradanreal.h>

#include <gui/entradabool.h>

#include <gui/entradacolor.h>

#include <gui/entradaentero.h>

#include <gui/entradaseleccion.h>

#define _(x) Glib:: convert(x,"UTF -8","ISO -8859 -15")

32 Uso de BioMedIGU

void on_opcion_modificada(OpcionEntrada *op)

{

// Convertir la opcion a EntradaBool

EntradaBool *peb = dynamic_cast <EntradaBool *>(op);

// Activar o desactivar el grupo vista secundaria , segun el

valor de la opcion.

if (peb)

peb ->getListaOpcionesEntrada ()->getGrupo("vissec")->

activarGrupo(peb ->getBool ());

}

int main (int argc , char *argv [])

{

Gtk::Main kit (argc ,argv);

ListaOpcionesEntrada lops;

// Crear los grupos

GrupoOpcionesEntrada grp1 ("visprin","Vista Principal");

GrupoOpcionesEntrada grp2 ("vissec","Vista Secundaria");

// A~nadir las opciones a los grupos

grp1.addOpcion(EntradaString ("Objeto", "objeto", "

cilindro1"));

grp1.addOpcion(EntradaColor ("Color", "color" ,true));

EntradaEntero ee(_("Tama~no"), "tam" ,1 );

ee.setLimites (0,10);

grp1.addOpcion(ee);

grp1.addOpcion(EntradaBool ("Centrado", "centrado" , true)

);

// Crear una EntradaSeleccion

std::vector <EntradaSeleccion :: ItemSeleccion > vis;

EntradaSeleccion :: ItemSeleccion it;

it.texto = _("Metalico");

it.id.valInt = 1;

vis.push_back(it);

it.texto = _("Madera");

it.id.valInt = 2;

vis.push_back(it);

it.texto = _("Plastico");

it.id.valInt = 3;

vis.push_back(it);

grp1.addOpcion(EntradaSeleccion("Material","material",

SELECCION_COMBO ,vis));

EntradaBool eb ("Activar Vista Secundaria", "activar" ,

true);

eb.addSlotModificado(sigc:: ptr_fun (& on_opcion_modificada));

grp1.addOpcion(eb);

grp2.addOpcion(EntradaString ("Objeto", "objeto", "cubo2"

2.6 Ventana asistente 33

));

grp2.addOpcion(EntradaColor ("Color", "color" ,true));

grp2.addOpcion(ee);

grp2.addOpcion(EntradaBool ("Centrado", "centrado" , true)

);

grp2.addOpcion(EntradaSeleccion("Material","material",

SELECCION_COMBO ,vis));

// A~nadir los grupos a la lista

lops.addGrupo(grp1);

lops.addGrupo(grp2);

// Crear la ventana

SmartPtr <VentanaOpcionesMarcos > refVen =

VentanaOpcionesMarcos :: crear (lops ,"Opciones");

AccionUsuario result = refVen ->run();

if (result == RESULT_OK)

{

lops = refVen ->getListaOpcionesEntrada ();

// Mostrar algunas opciones como ejemplo de acceso.

std::cout << "Objeto vista principal: " << lops.getOpcion

("visprin","objeto")->getValor () << std::endl;

SmartPtr <EntradaBool > refActivar = SmartPtr <EntradaBool

>:: cast_dynamic(lops.getOpcion("visprin","activar"));

if (refActivar && refActivar ->getBool ())

{

std::cout << "Objeto vista secundaria: " << lops.

getOpcion("vissec","objeto")->getValor () << std::

endl;

}

}

return 0;

}

2.6. Ventana asistente

La ventana asistente (wizard) es un tipo especial de ventana de opcionesque va mostrando de forma ordenada las opciones al usuario. Esta divididaen nodos y cada nodo contiene un lista de opciones diferente.

VentanaAsistente ven("Ejemplo de Asistente");

// Crear una lista de opciones

SmartPtr <ListaOpcionesEntrada > lops = SmartPtr <

ListaOpcionesEntrada >(new ListaOpcionesEntrada);

lops ->addOpcion (...);

...

// Crear un nuevo nodo.

34 Uso de BioMedIGU

ven.addListaOpcionesEntrada (*lops ,"Nodo 1", "Descripcion Nodo

1");

...

En principio los nodos se muentran secuencialmente en el orden que hansido creados, pero este comportamiento se puede modificar asignando unranura al signalSiguiente que calcule el siguiente nodo en funcion delactual y los valores de sus opciones.La funcion o metodo debera tener la siguiente declaracion:bool on_siguiente (unsigned int& nodo);

Como parametro se recibe el ındice del nodo actual, y en el deberemosdevolver el del siguiente nodo. Mediante el retorno deberemos indicar si seha llegado al ultimo nodo o no, para que el asistente pueda activar/desactivarlos botones oportunos (atras, adelante y aceptar).signalSiguiente ().connect(sigc:: ptr_fun (& on_siguiente));

bool on_siguiente(unsigned int& nodo)

{

bool ultimo = false;

switch (nodo)

{

case 0:

nodo ++;

break;

case 1:

{

SmartPtr <EntradaSeleccion > es = SmartPtr <

EntradaSeleccion >:: cast_dynamic(

getListaOpcionesEntrada (1).getOpcion("snodo","

snodo"));

EntradaSeleccion :: IdSeleccion id;

es->getIdSeleccionado(id);

nodo = (unsigned int)id.valInt;

}

break;

case 2:

case 3:

case 4:

nodo = 4;

ultimo = true;

break;

default:

break;

}

return ultimo;

}

Una vez ejecutado el asistente (run) podemos consultar, si lo deseamos,el camino que se ha seguido mediante el metodo getCamino, que devuelveun vector con los ındices de los nodos que ha visitado el usuario.El siguiente ejemplo muestra un asistente sencillo.

2.6 Ventana asistente 35

Figura 2.4: Ejemplo de una ventana asistente.

#include <gtkmm/main.h>

#include <gui/ventanaasistente.h>

#include <gui/entradacolor.h>

#include <gui/entradabool.h>

#include <gui/entradaseleccion.h>

#include <gui/entradaentero.h>

#include <gui/entradafichero.h>

#include <gui/ustringutil.h>

#include <gui/init.h>

#define _(x) Glib:: convert(x,"UTF -8","ISO -8859 -15")

class EjemploAsistente : public VentanaAsistente

{

public:

EjemploAsistente ()

:VentanaAsistente("Ejemplo de Asistente ")

{

// Crear las listas de opciones

SmartPtr <ListaOpcionesEntrada > lops = SmartPtr <

ListaOpcionesEntrada >(new ListaOpcionesEntrada);

EntradaColor efondo("Fondo", "fondo");

efondo.mostrarEntradaNumerica(false);

efondo.setColor(Gdk:: Color("black"));

lops ->addOpcion(efondo);

36 Uso de BioMedIGU

EntradaEntero ezoom("Zoom", "zoom" ,1);

ezoom.setLimites (1 ,10);

lops ->addOpcion(ezoom);

EntradaEntero eslide("Corte", "slide" ,0);

eslide.setLimites (0 ,512);

lops ->addOpcion(eslide);

// Insertar la lista al asistente.

addListaOpcionesEntrada (*( lops), Glib:: ustring("Nodo

0"), Glib:: ustring("Descripcion del nodo 0"));

lops = SmartPtr <ListaOpcionesEntrada >(new

ListaOpcionesEntrada ());

EntradaSeleccion es("Siguiente Nodo", "snodo");

es.addItem("Nodo 2" ,2);

es.addItem("Nodo 3" ,3);

lops ->addOpcion(es ,"snodo");

// Insertar la lista al asistente.

addListaOpcionesEntrada (*( lops), Glib:: ustring("Nodo

1"), Glib:: ustring("Descripcion del nodo 1"));

lops = SmartPtr <ListaOpcionesEntrada >(new

ListaOpcionesEntrada ());

EntradaEntero ee ("Opcion Nodo 2", "nodo2" ,1);

ee.setLimites (1,12);

lops ->addOpcion(ee);

// Insertar la lista al asistente.

addListaOpcionesEntrada (*( lops), Glib:: ustring("Nodo

2"), Glib:: ustring("Descripcion del nodo 2"));

lops = SmartPtr <ListaOpcionesEntrada >(new

ListaOpcionesEntrada ());

EntradaFichero ef1("Opcion Nodo 3", "fichero1");

ef1.setAncho (50);

ef1.addFiltro("Archivo de texto", "*.txt");

ef1.addFiltro("Archivo PostScript", "*.ps");

ef1.addFiltro("Todos los archivos", "*");

ef1.setTituloDialogo("Guadar Como ...");

ef1.setUsarFileChooser(true ,Gtk::

FILE_CHOOSER_ACTION_SAVE);

lops ->addOpcion(ef1);

// Insertar la lista al asistente.

addListaOpcionesEntrada (*( lops), Glib:: ustring("Nodo

3"), Glib:: ustring("Descripcion del nodo 3"));

2.6 Ventana asistente 37

lops = SmartPtr <ListaOpcionesEntrada >(new

ListaOpcionesEntrada ());

EntradaEntero ee2 ("Opcion Nodo 4", "nodo4" ,1);

ee2.setLimites (1 ,12);

lops ->addOpcion(ee2);

// Insertar la lista al asistente.

addListaOpcionesEntrada (*( lops), Glib:: ustring("Nodo

4"), Glib:: ustring("Descripcion del nodo 4"));

// Conectar un metodo al signalSiguiente.

signalSiguiente ().connect(sigc:: mem_fun (*this ,&

EjemploAsistente :: on_siguiente));

set_default_size (500 ,400);

}

~EjemploAsistente (){};

static SmartPtr <EjemploAsistente > crear () {return

SmartPtr <EjemploAsistente >(new EjemploAsistente);}

protected:

bool on_siguiente(unsigned int& nodo)

{

bool ultimo = false;

switch (nodo)

{

case 0:

nodo ++;

break;

case 1:

{

// Consultar el valor de una opcion de

seleccion.

SmartPtr <EntradaSeleccion > es = SmartPtr <

EntradaSeleccion >:: cast_dynamic(

getListaOpcionesEntrada (1).getOpcion("snodo"

,"snodo"));

EntradaSeleccion :: IdSeleccion id;

es->getIdSeleccionado(id);

// Indicar el nuevo nodo mediante el parametro

de entrada.

nodo = (unsigned int)id.valInt;

}

break;

case 2:

case 3:

case 4:

nodo = 4;

ultimo = true;

break;

default:

38 Uso de BioMedIGU

break;

}

return ultimo;

}

};

int main (int argc , char *argv [])

{

// Inicializar la libreria.

BMI::init(argc ,argv);

// Crear la ventana.

SmartPtr <EjemploAsistente > refVen = EjemploAsistente :: crear

();

// Mostrarla.

int result = refVen ->run();

// Si el usuario ha terminado apretando ACEPTAR.

if (result == RESULT_OK)

{

ListaOpcionesEntrada &lops = refVen ->

getListaOpcionesEntrada (3);

// Mostrar alguna opcion como ejemplo de acceso.

std::cout << "Fichero nodo 3: " << lops.getOpcion("","

fichero1")->getValor () << std::endl;

}

return 0;

}

2.7. Ventana de edicion de funciones 2D

Se dispone tambien de una ventana para editar funciones 2D. Esta venta-na permite editar diferentes funciones a la vez, o simplemente visualizarlas.Para ello deberemos crear antes las funciones y anadirles, si es necesario, losvalores iniciales.

Al crearlas deberemos especificar que tipo de valores admite la funcion,tanto para el eje X como el eje Y, el nombre de la funcion y, si lo deseamos,el texto que se mostrara en la leyenda.

SmartPtr <Funcion2D > refFun = Funcion2D ::crear("R",

VALORES_REALES ,VALORES_REALES ,"Red");

Una vez creada podemos anadir los valores que deseemos.

refFun ->addValorXY(ValorXY (0.0 ,0.0));

refFun ->addValorXY(ValorXY (1.2 ,2.0));

refFun ->addValorXY(ValorXY (4.0 ,3.0));

2.7 Ventana de edicion de funciones 2D 39

Tambien podemos especificar el rango de los valores de la funcion para losdos ejes.refFun ->setRangoX (0.0 ,5.0);

refFun ->setRangoY (0.0 ,5.0);

Al crear la ventana podemos especificar si el usuario puede editar las fun-ciones, y si deseamos que se utilice antialiasing en la area donde se dibujanlas funciones. Tambien se puede espeficar si se instancia en modo avanzado,que presentara al usuario unas opciones adicionales que le permiten modifi-car cada cuanto se dibujan las marcas y etiquetas de los ejes.SmartPtr <VentanaFuncion2D > refVen = VentanaFuncion2D :: crear(

true ,true ,false);

Deberemos especificar el tıtulo de la ventana y las etiquetas para los ejes.refVen ->set_title("Funcion Transferencia");

refVen ->getPanelFuncion2D ().setEtiquetaEjeX("Valor");

refVen ->getPanelFuncion2D ().setEtiquetaEjeY("Propiedad");

Tambien podemos especificar el color de la funcion, si no nos gustan los quese asignan automaticamente.refVen ->getPanelFuncion2D ().setColorFuncion2D("R",Gdk::Color(

"red"));

Si no se desea que se muestre el grid en la zona de visualizacion/edicion delas funciones, podemos utilizar el metodo mostrarGrid.refVen ->getPanelFuncion2D ().mostrarGrid(false);

La precision de los numeros reales se puede especificar mediante el metodosetPrecision del la clase PanelFuncion2D indicando el numero de decima-les deseados.refVen ->getPanelFuncion2D ().setPrecision (2);

Opcionalmente cuando los valores del eje Y son enteros en vez de mostrarel valor numerico se puede mostrar un texto mediante la funcionPanelFuncion2D::addEtiquetaValor, de este modo se puede indicar que elnumero en realidad representa algo mas complejo. Por ejemplo, para editaruna funcion de transferencia que se utilizara para seleccionar el material conel que se visualizara un modelo de un cerebro en funcion de una propiedaddeterminada, como la densidad.refVen ->getPanelFuncion2D ().addEtiquetaValor("HUESO" ,1);

refVen ->getPanelFuncion2D ().addEtiquetaValor("MASA GRIS" ,2);

refVen ->getPanelFuncion2D ().addEtiquetaValor("MASA BLANCA" ,3)

;

Ahora ya tenemos la funcion creada con los valores iniciales y tenemos laventana creada y configurada a nuestro gusto. Simplemente nos queda anadirlas funciones.refVen ->addFuncion2D(refFun);

40 Uso de BioMedIGU

Los valores de las funciones se modifican con la interaccion del usuario. Nohace falta esperar a que se cierra la ventana para poder aplicar los cambiosque haya realizado. Existe una senal que se lanza cuando se aprieta un botona la que podemos conectar una ranura para aplicar los cambios.void on_aplicar(VentanaFuncion2D *pven);

...

refVen ->signalAplicar ().connect(sigc:: ptr_fun (& on_aplicar));

El siguiente ejemplo muestra la creacion de una VentanaFuncion2D pa-ra editar cuatro funciones transferencia de una propiedad a las diferentescomponentes de un color (RGBA).

Figura 2.5: Ejemplo de una ventana de edicion de funciones 2D.

Al usuario, si la ventana esta en modo de edicion, se le permite insertar,eliminar y modificar puntos de las diferentes funciones que se muestran. Laventana controla los cambios que realiza el usuario y se le permite deshacer-los (CONTROL-z) y rehacerlos (CONTROL-SHIFT-z). Tambien dispone deun boton para restaurar el estado inicial de las funciones, de un panel deopciones para cambiar el rango y si se muestra o no el grid, y una leyendadonde puede cambiar la funcion activa y el color con el que se muestran.

En la barra de estado se le muestra la posicion del cursor del raton, elmodo de edicion en el que se encuentra y la funcion que esta actualmenteactiva.#include <gtkmm/messagedialog.h>

#include <gtkmm/main.h>

#include <gui/init.h>

#include <gui/ventanafuncion2d.h>

2.7 Ventana de edicion de funciones 2D 41

#include <gui/ustringutil.h>

#define _(x) Glib:: convert(x,"UTF -8","ISO -8859 -15")

void on_aplicar(VentanaFuncion2D *pven)

{

Glib:: ustring mens (_("Valores de la funcion Red\n"));

// Aceder a la funcion

SmartPtr <Funcion2D > fred = pven ->getPanelFuncion2D ().

getFuncion2D("R");

// Inicializar los iteradores

Funcion2D :: IteradorValoresConst first = fred ->begin ();

Funcion2D :: IteradorValoresConst last = fred ->end();

// Se accede a los valores

while (first !=last)

{

mens = mens + Glib:: ustring("(") + convRealStr ((* first)->

getXreal ()) + Glib:: ustring(", ") + convRealStr ((*

first)->getYreal ()) + Glib:: ustring(")\n");

++ first;

}

Gtk:: MessageDialog m (mens);

m.run();

}

int main (int argc , char *argv [])

{

// Inicializar las librerias

BMI::init (argc , argv);

// Crear las funciones

SmartPtr <Funcion2D > refFunR = Funcion2D ::crear("R",

VALORES_REALES ,VALORES_REALES ,"Red");

SmartPtr <Funcion2D > refFunG = Funcion2D ::crear("G",

VALORES_REALES ,VALORES_REALES ,"Green");

SmartPtr <Funcion2D > refFunB = Funcion2D ::crear("B",

VALORES_REALES ,VALORES_REALES ,"Blue");

SmartPtr <Funcion2D > refFunA = Funcion2D ::crear("A",

VALORES_REALES ,VALORES_REALES ,"Alpha");

// A~nadir los valores iniciales

refFunR ->addValorXY(ValorXY (0.0 ,0.0));

refFunR ->addValorXY(ValorXY (0.25 ,0.98));

refFunR ->addValorXY(ValorXY (0.75 ,0.98));

refFunR ->addValorXY(ValorXY (1.0 ,0.0));

refFunG ->addValorXY(ValorXY (0.0 ,0.53));

refFunG ->addValorXY(ValorXY (1.0 ,0.53));

refFunB ->addValorXY(ValorXY (0.0 ,0.0));

42 Uso de BioMedIGU

refFunB ->addValorXY(ValorXY (0.45 ,0.43));

refFunB ->addValorXY(ValorXY (1.0 ,0.43));

refFunA ->addValorXY(ValorXY (0.0 ,0.78));

refFunA ->addValorXY(ValorXY (1.0 ,0.78));

// Asignar los rangos de las funciones.

refFunR ->setRango (0,1,0,1);

refFunG ->setRango (0,1,0,1);

refFunB ->setRango (0,1,0,1);

refFunA ->setRango (0,1,0,1);

// Crear la ventana

SmartPtr <VentanaFuncion2D > refVen = VentanaFuncion2D :: crear

(true ,true ,true ,"./ iconos");

// A~nadir las funciones

refVen ->addFuncion2D(refFunR);

refVen ->addFuncion2D(refFunG);

refVen ->addFuncion2D(refFunB);

refVen ->addFuncion2D(refFunA);

// Conectamos e signal aplicar a una funcion

refVen ->signalAplicar ().connect(sigc:: ptr_fun (& on_aplicar))

;

// Establecer los rangos del panel

refVen ->getPanelFuncion2D ().setRango (0,1,0,1);

// Establecer el nombre de la ventana y las etiquetas de

los ejes

refVen ->set_title("Funcion Transferencia");

refVen ->getPanelFuncion2D ().setEtiquetaEjeX("Valor");

refVen ->getPanelFuncion2D ().setEtiquetaEjeY("Propiedad");

// Establecer el tama~no de la ventana

refVen ->set_size_request (600,-1);

// Mostrar la ventana

refVen ->show();

// Iniciar el bucle de eventos del Gtkmm

Gtk::Main::run(* refVen);

return 0;

}

2.8. Creacion de la interfaz mediante ficheros deconfiguracion

Aparte de crear las ventana instanciandolas o heredando de una de ellas,BioMedIGU permite crearlas mediante ficheros de configuracion. En estos

2.8 Creacion de la interfaz mediante ficheros de configuracion 43

ficheros se describen todas las caracterısticas deseadas y se instancian sim-plemente llamando a un metodo.

Las ventanas se crean a partir de un objeto de la clase ConstructorGUI,al que se le a proporcionado un objeto que implemente el interfaz definidoen la clase InfoGUI, que sera el encargado de leer la informacion de losficheros. La librerıa proporciona una clase que lee los ficheros en el formatodescrito en el capıtulo 3 y que implementa dicho interfaz, InfoGUIBdDisc.Para crear un objeto de esta clase simplemente deberemos proporcionar elnombre del fichero principal de configuracion. En este fichero normalmentese indica la ubicacion por defecto de los demas ficheros que forman la BdDiscy a continuacion se incluyen.El siguiente texto muestra un ejemplo del fichero principal de configuracion:REGISTRE:DIRECTORIS

{

default : ./data

}

#include <ventanaopcion.cfg >

#include <ventanamenu.cfg >

#include <ventanagl.cfg >

Una vez tenemos definido el fichero principal podemos crear el constructorcomo muestra el siguiente codigo:InfoGUIBdDisc info("./data/bd.cfg");

ConstructorGUI cons (info);

Para instanciar una ventana definida en los ficheros que forman la Bd-Disc simplemente tendremos que llamar a uno de los metodos de la claseConstructorGUI, dependiendo del tipo de ventana que pretendamos crear:SmartPtr <VentanaGL > cons.crearVentanaGL("nombreVentanaGL");

En el siguiente ejemplo se muestran los ficheros de una BdDisc que de-finen una ventana de opciones, y como instanciarla y usarla.

Figura 2.6: Ejemplo de la ventana creada mediante el constructor.

El fichero principal de configuracion serıa:REGISTRE:DIRECTORIS

{

44 Uso de BioMedIGU

default : ./data

}

#include <ventanaopcion.cfg >

El fichero ventanaopcion.cfg podrıa ser:

VENTANAOPCIONES : ejemploopciones

{

titulo: EjemploVentanaOpciones

tipoVentanaOpciones : MARCOS

ngrupos : 1

grupo1 : grupo1

}

GRUPOOPCIONES : grupo1

{

nombre : grupo1

texto : Grupo1

nopciones : 3

opcion1 (OPCIONENTRADA ,opcion1)

opcion2 (OPCIONENTRADA ,opcion2)

opcion3 (ENTRADAN ,opcion3)

}

OPCIONENTRADA : opcion1

{

nombre : opcion1

texto : Opcion1

valor : HolaMundo

tipo : STRING

}

OPCIONENTRADA : opcion2

{

nombre : opcion2

texto : Opcion2

valor : cierto

tipo : BOOL

}

ENTRADAN : opcion3

{

nombre : opcion3

texto : Opcion3

tipo : NREAL

tipoDisposicion : HORIZONTAL

num : 3

valor1 : 1.1

valor2 : 2.2

valor3 : 3.3

}

Y el fichero main.cc que instancia la ventana quedarıa:

#include <gui/init.h>

2.8 Creacion de la interfaz mediante ficheros de configuracion 45

#include <gui/listaopcionesentrada.h>

#include <gui/ventanaopcionesmarcos.h>

#include <gui/entradastring.h>

#include <gui/infoguibddisc.h>

#include <gui/constructorgui.h>

int main (int argc , char *argv [])

{

// Inicializar las librerias

BMI::init(argc ,argv);

char *pdir = getenv("DEMODIR");

Glib:: ustring dir("./");

if (pdir)

dir = pdir;

// Crear el info con el fichero de configuracion

InfoGUIBdDisc info(dir + "/data/bd.cfg");

// Crear el constructor con el info creado

ConstructorGUI cons(info);

// Crear una lista de opciones para obtener las opciones de

la ventana

ListaOpcionesEntrada lops;

// Crear la ventana mediante el constructor

SmartPtr <VentanaOpciones > refVen = cons.

crearVentanaOpciones("ejemploopciones");

// Mostrar la ventana al usuario

AccionUsuario result = refVen ->run();

if (result == RESULT_OK)

{

lops = refVen ->getListaOpcionesEntrada ();

// Mostrar algunas opciones como ejemplo de acceso.

std::cout << "Valor opcion1 del grupo1: " << lops.

getOpcion("grupo1","opcion1")->getValor () << std::endl

;

}

return 0;

}

Capıtulo 3

Formato del fichero deconfiguracion

Nota: Se esta desarrollando una nueva implementacion de la BdDisc ba-sada en XML. El desarrollo de esta parte de la librerıa esta estancada hastaque se finalice la nueva implementacion. Aunque en principio la informacionde este capıtulo es correcta, no se incluyen las ultimas funcionalidades de lalibrerıa y, en algun caso, puede estar desfasada.

3.1. Introduccion

La librerıa desarrollada incluye un mecanismo para crear interfaces apartir de ficheros de configuracion. Se ha desarrollado de manera que pue-da soportar diferentes formatos, pero solo se ha implementado un formatoconcreto utilizando la librerıa desarrollada por la division de InformaticaGrafica del CREB llamada BdDisc. En este capıtulo se explica el formatogeneral que tiene los ficheros que puede leer la BdDisc y el formato concretoque se utiliza en la librerıa desarrollada.

3.1.1. Formato general de los ficheros de la BdDisc

Con librerıa BdDisc es posible leer de unos ficheros, con el formato quese describira a continuacion, una serie de propiedades organizadas en obje-tos. Estos objetos se caracterizan por una clave que hace referencia al tipode objeto al que pertenecen, y por los diferentes atributos que poseen. Unfichero esta formado principalmente por descripciones de objetos que tienenel siguiente formato general:

CLAVEOBJETO : nombreObjeto

{

nombreAtributo : valor

nombreAtributoMultiValor (valor , valor , ...)

}

48 Formato del fichero de configuracion

La clave del objeto es el nombre del tipo de objeto que se describira acontinuacion, por conveniencia se escribe en mayusculas. A continuacion seescribe, separado por dos puntos, el nombre identificativo del objeto y, entrellaves, los diferentes atributos del objeto con sus correspondientes valores.Los valores pueden ser enteros, reales o texto.

En ocasiones los objetos tienen propiedades que poseen un numero in-determinado de valores. Aunque la librerıa BdDisc ofrece varias maneras decrear estas listas, en este proyecto se ha elegido implementarlas mediantediferentes atributos. El primero de ellos es el numero de valores de la lista,y a continuacion se escriben todos los valores anadiendo al nombre del atri-buto el numero de la posicion del valor en la lista, comenzando desde 1. Unejemplo servira para entender mejor este mecanismo:

CLAVEOBJETO : nombreObjeto

{

numItems : 3

item1 : valor1

item2 : valor2

item3 : valor3

}

Los elementos de la lista pueden ser atributos multivalor. El ejemplo anteriorcon multivalores quedarıa de la siguiente forma:

CLAVEOBJETO : nombreObjeto

{

numItems : 3

item1 (valor11 , valor12 , ...)

item2 (valor21 , valor22 , ...)

item3 (valor31 , valor32 , ...)

}

3.1.2. Leyenda de la descripcion

En la siguiente seccion se describiran los objetos y los atributos que sepueden incluir en el fichero de configuracion para crear la interfaz grafica deusuario con la librerıa BioMedIGU. Para cada tipo de objeto se incluye unatabla que tiene el siguiente formato:

3.2 Descripcion de los objetos de BioMedIGU 49

Clave: CLAVEOBJETO

Nombre Tipo Descripcion

nombreAtributo Tipo del valor Descripcion

nombreAtributoMultivalor Multivalor Descripcion

TipoValor1 Descripcion

TipoValor2 Descripcion

nombreAtributo Enumeracion Descripcion

ENUM1 Descripcion

ENUM2 Descripcion

[nombreAtributo] Tipo del valor Descripcion

nombreAtributo# Tipo del valor Descripcion

En la primera fila de la tabla se especifica la clave del tipo de objetoque se describe, a continuacion se pone uno a uno los atributos que puedetener el objeto. Algunos atributos son del tipo enumeracion, esto quiere decirque solo pueden tener uno de los valores que se describen en las siguienteslıneas. Cuando el atributo se encuentra entre corchetes quiere decir que noes obligatorio ponerlo en la descripcion de un objeto de ese tipo. Cuando alfinal del nombre se le anade el caracter ‘#’ significa que forma parte de unalista y se debera sustituir el caracter por el numero de la posicion del valordentro de la lista.

3.2. Descripcion de los objetos de BioMedIGU

3.2.1. Ventana de menus

La siguiente tabla muestra los atributos que se deben/pueden especificarpara crear una ventana de menus a traves de un fichero de configuracion:

Clave: VENTANAMENU

Nombre Tipo Descripcion

[titulo] Texto Tıtulo de la ventana.

[ancho] Entero Ancho mınimo de la ventana (en pixels).

[alto] Entero Alto mınimo de la ventana (en pixels).

[slotCerrar] Multivalor Slot al que se conectara el signalCerrar de laventana.

Texto Nombre de la funcion.

Texto Nombre de la librerıa/modulo.

[slotConfirmarCerrar] Multivalor Slot al que se conectara el signalConfirmarCe-rrar de la ventana.

Texto Nombre de la funcion.

Texto Nombre de la librerıa/modulo.

[funcionCrear] Multivalor Funcion utilizada para crear la ventana.

Texto Nombre de la funcion.

Texto Nombre de la librerıa/modulo.

50 Formato del fichero de configuracion

Clave: VENTANAMENU (Continuacion)

Nombre Tipo Descripcion

[estadosIniciales] Multivalor Estados iniciales de la ventana.

Entero Un estado.

Entero Otro estado.

. . .

[barraHerramientas] Enumeracion Si se muestra o no la barra de herramientas.

cierto Se muestra la barra de herramientas.

falso No se muestra la barra de herramientas.

[barraEstado] Enumeracion Si se muestra o no la barra de estado.

cierto Se muestra la barra de estado.

falso No se muestra la barra de estado.

nmenus Entero Numero de menus que componen la ventana.

menu# Texto Nombre del objeto MENU que describe elmenu.

Como se puede observar para describir los menus hay que especificar unalista de nombres de objetos del tipo MENU. La siguiente tabla muestra losatributos que tienen los objetos de este tipo:

Clave: MENU

Nombre Tipo Descripcion

texto Texto Texto del menu.

[orden] Entero Orden del menu en la barra de menus o del menu si es unsubmenu.

[estados] Multivalor Estados en los que estara activo.

Entero Un estado.

Entero Otro estado.

. . .

nitems Entero Numero de ıtems (opciones o submenus que forman elmenu).

item# Multivalor Descripcion del item iesimo.

Texto Tipo de item (MENU,OPCION o SEPARADOR).

Texto Nombre del objeto MENU u OPCION. No es necesariopara el SEPARADOR

Los menus estan formados por ıtems que pueden ser un submenu (ME-NU), una opcion (OPCION) o un separador (SEPARADOR). Los separado-res no tienen atributos, simplemente se anade un separador visual al menu alque pertenecen en la posicion indicada. Las opciones tienen los atributos quese describen a continuacion:

3.2 Descripcion de los objetos de BioMedIGU 51

Clave: OPCION

Nombre Tipo Descripcion

texto Texto Texto del menu.

[orden] Entero Orden de la opcion en el menu.

[estados] Multivalor Estados en los que estara activa.

Entero Un estado.

Entero Otro estado.

. . .

[accelkey] Texto Teclas de aceleracion de la opcion (p.ej:CONTROLa o ALTs).

[pathicono] Texto Path al fichero de la imagen del icono.

nombreFuncion Texto Nombre de la funcion que se llamara cuando seactive la opcion.

nombreModulo Texto Nombre de la librerıa/modulo donde se encuentrala funcion.

[enBarra] Enumeracion Si se mostrara la opcion en la barra de herramien-tas.

cierto Se muestra en la barra de herramientas.

falso No se muestra en la barra de herramientas.

[ordenEnBarra] Entero Orden de la opcion en la barra de herramientas.

A continuacion se muestra un ejemplo con parte del contenido de unfichero para crear una ventana de menu:

VENTANAMENU: ventana1

{

titulo : EjemploVentanaMenu

slotCerrar (on_cerrar ,moduloejemplo)

estadoInicial : 2

barraHerramientas : cierto

barraEstado : falso

nmenus : 2

menu1 : menu1

menu2 : menu2

}

MENU: menu1

{

texto : textomenu1

estados (1,2)

nitems : 5

item1 (OPCION ,opcion1)

item2 (SEPARADOR)

item3 (MENU ,menu3)

item4 (OPCION ,opcion4)

item5 (OPCION ,opcion5)

}

OPCION: opcion1

{

texto : textoopcion1

52 Formato del fichero de configuracion

orden : 20

ordenEnBarra : 20

pathicono : ./ iconos/icon_0.gif

accelkey : CONTROLo

estados (1)

enBarra : cierto

nombreFuncion : funcion1

nombreModulo : moduloejemplo

}

.

.

.

3.2.2. Ventana de visualizacion grafica

Una ventana de visualizacion grafica (VentanaGL) es una ventana demenus a la que se ha anadido en el contenido areas para visualizar graficosmediante GL. Por eso todo lo dicho para la ventana de menus es aplicablea esta ventana. Ademas una VentanaGL tiene los siguientes atributos:

Clave: VENTANAGL

Nombre Tipo Descripcion

. . . Todos los atributos de VENTANAMENU . . .

[areaActivaInicial] Entero Numero de la area que se activara inicialmen-te.

[maximizarArea] Enumeracion Si se muestra la area activa maximizada.

cierto Se muestra la area maximizada.

falso No se muestra la area maximizada.

[conAreaActiva] Enumeracion Si se muestra en la barra de estado el nombrede la area que esta activa.

cierto Se muestra el nombre en la barra de estado.

falso No se muestra el nombre en la barra de estado.

[conCoordenadas] Enumeracion Si se muestra en la barra de estado las coor-denadas del cursor.

cierto Se muestran las coordenadas en la barra deestado.

falso No se muestra las coordenadas en la barra deestado.

[colorMarcoActivo] Multivalor Color del marco de la area activa.

Real Componente roja (R) del color.

Real Componente verde (G) del color.

Real Componente azul (B) del color.

[nslots] Entero Numero de slots que se conectan a la ventana.

3.2 Descripcion de los objetos de BioMedIGU 53

Clave: VENTANAGL (Continuacion)

Nombre Tipo Descripcion

[slot#] Multivalor Color del marco de la area activa.

Texto Nombre de la funcion que formara el slot.

Texto Nombre de la librerıa/modulo donde se en-cuentra la funcion.

Enumeracion Tipo de slot (MOVIMIENTO RATON,MOVIMIENTO RATON CLICK, BO-TON RATON APRETADO, BO-TON RATON SOLTADO, EXPOSE, REA-LIZE, RESIZE).

Entero Estado del conversor de eventos en al que seconecta el slot (-1 ≡ Todos).

Entero Numero de la area a la que se conecta el slot(-1 ≡ Todas)

[nareas] Entero Numero de areas de la ventana.

[area#] Multivalor Descripcion de la area iesima.

Texto Nombre de la area.

Entero Flag de la area.

El siguiente ejemplo muestra una posible descripcion de una VentanaGL:

VENTANAGL: ventanagl

{

titulo : EjemploVentanaGL

ancho : 600

alto : 600

slotCerrar (on_cerrar ,moduloejemplo)

nmenus : 1

menu1 : menugl1

maximizarArea : cierto

colorMarcoActivo (0.0 ,0.0 ,0.5)

conAreaActiva : cierto

conCoordenadas : cierto

areaActivaInicial : 3

nareas : 4

area1 (AREA1 ,1)

area2 (AREA2 ,2)

area3 (AREA3 ,3)

area4 (AREA4 ,4)

nslots: 5

slot1 (on_realize ,moduloejemplo ,REALIZE ,-1,-1)

slot2 (on_expose ,moduloejemplo ,EXPOSE ,-1,-1)

slot3 (on_button_press ,moduloejemplo ,BOTON_RATON_APRETADO

,-1,-1)

slot4 (on_button_release ,moduloejemplo ,BOTON_RATON_SOLTADO

,-1,-1)

slot5 (on_move ,moduloejemplo ,MOVIMIENTO_RATON_CLICK ,-1,-1)

}

...

54 Formato del fichero de configuracion

3.2.3. Ventana de parametros/opciones

Una ventana de opciones (VentanaOpciones) se describe mediante lossiguientes atributos:

Clave: VENTANAOPCIONES

Nombre Tipo Descripcion

[titulo] Texto Tıtulo de la ventana.

[ancho] Entero Ancho mınimo de la ventana (en pixels).

[alto] Entero Alto mınimo de la ventana (en pixels).

[slotCerrar] Multivalor Slot al que se conectara el signalCerrar de laventana.

Texto Nombre de la funcion.

Texto Nombre de la librerıa/modulo.

[slotConfirmarCerrar] Multivalor Slot al que se conectara el signalConfirmarCe-rrar de la ventana.

Texto Nombre de la funcion.

Texto Nombre de la librerıa/modulo.

[funcionCrear] Multivalor Funcion utilizada para crear la ventana.

Texto Nombre de la funcion.

Texto Nombre de la librerıa/modulo.

[tipoVentanaOpciones] Enumeracion Tipo de la ventana de opciones.

SCROLL Se creara una VentanaOpcionesScroll.

TABS Se creara una VentanaOpcionesTabs.

MARCOS Se creara una VentanaOpcionesMarcos.

listaOpciones Texto Nombre del objeto LISTAOPCIONES quedescribe la lista de opciones de entrada de laventana.

Como se puede ver una ventana de opciones esta formada por una listade opciones de entrada, que esta definida por un numero determinado degrupos de opciones:

Clave: LISTAOPCIONES

Nombre Tipo Descripcion

ngrupos Entero Numero de grupos de la lista de opciones.

grupo# Texto Nombre del objeto GRUPOOPCIONES iesimo.

3.2 Descripcion de los objetos de BioMedIGU 55

Clave: GRUPOOPCIONES

Nombre Tipo Descripcion

nombre Texto Nombre del grupo de opciones.

[texto] Texto Texto del grupo de opciones.

[numcols] Entero Numero de columnas del grupo de opciones.

nopciones Entero Numero opciones del grupo.

opcion# Multivalor Opcion iesima del grupo.

Enumeracion Tipo de objeto de la opcion (OPCIONENTRADA, EN-TRADAN, ENTRADANUMERICA, ENTRADAFICHE-RO, ENTRADASELECCION, ENTRADACOLOR).

Texto Nombre del objeto de la opcion.

En los grupos de opciones se definen las opciones que pertenecen al gru-po, que pueden ser opciones simples (OPCIONENTRADA,ENTRADANUMERICA,ENTRADAFICHERO, ENTRADASELECCION) o opciones compuestas porun numero determinado de entradas del mismo tipo (ENTRADAN, EN-TRADACOLOR). A continuacion se describen los atributos de los diferentestipos de objetos:

Clave: OPCIONENTRADA

Nombre Tipo Descripcion

nombre Texto Nombre de la opcion.

texto Texto Texto de la opcion.

tipo Enumeracion Tipo de opcion

BOOL Opcion de entrada de un booleano.

STRING Opcion de entrada de un texto.

[valor] Texto Valor de la opcion.

Clave: ENTRADAN

Nombre Tipo Descripcion

nombre Texto Nombre de la opcion.

texto Texto Texto de la opcion.

tipo Enumeracion Tipo de opcion

NBOOL Opcion de entrada de varios booleanos.

NREAL Opcion de entrada de varios reales.

NENTERO Opcion de entrada de varios enteros.

NSTRING Opcion de entrada de varios textos.

[valor] Texto Valor de la opcion.

[tipoDisposicion] Enumeracion Tipo de disposicion vertical o horizon-tal

VERTICAL Disposicion vertical.

HORIZONTAL Disposicion horizontal.

num Entero Numero de entradas de la opcion

[valor#] Texto Valor de la entrada iesima.

56 Formato del fichero de configuracion

Clave: ENTRADANUMERICA

Nombre Tipo Descripcion

nombre Texto Nombre de la opcion.

texto Texto Texto de la opcion.

tipo Enumeracion Tipo de opcion

REAL Opcion de entrada de un real.

ENTERO Opcion de entrada de un entero.

[valor] Real Valor de la opcion.

[valorMinimo] Real/Entero Valor mınimo que puede tomar la opcion.

[valorMaximo] Real/Entero Valor maximo que puede tomar la opcion.

[incrementoPaso] Real/Entero Incremento corto del valor de la opcion.

[incrementoPagina] Real/Entero Incremento de pagina (largo) del valor de la op-cion.

[tipoWidget] Enumeracion Tipo de widget de entrada para la opcion.

SPINBUTTON Entrada numerica.

HSCALE Barra de desplazamiento.

SPINBUTTON HSCALE Entrada numerica seguida de una barra de des-plazamiento.

HSCALE SPINBUTTON Barra de desplazamiento seguida de una entradanumerica.

[anchoMinimo] Entero Numero de pixels mınimo que tendra el widgetSCALE.

Clave: ENTRADAFICHERO

Nombre Tipo Descripcion

nombre Texto Nombre de la opcion.

texto Texto Texto de la opcion.

tipo Enumeracion Tipo de opcion

FICHERO Opcion de entrada de un fichero.

[valor] Texto Valor de la opcion.

[usarFileChooser] Enumeracion Si se usara el dialogo Gtk::FileChooserDialog.

cierto Se usara el dialogo Gtk::FileChooserDialog.

falso Se usara el dialogo Gtk::FileSelection.

[fileChooserAction] Enumeracion La accion con la que sera instanciado el dialog(solo en el caso de usar el FileChooserDialog).

OPEN Abre el dialogo con la accion abrir un fichero.

SAVE Abre el dialogo con la accion guardar un fichero.

CREATE FOLDER Abre el dialogo con la accion crear una carpeta.

SELECT FOLDER Abre el dialogo con la accion seleccionar una car-peta.

3.2 Descripcion de los objetos de BioMedIGU 57

Clave: ENTRADASELECCION

Nombre Tipo Descripcion

nombre Texto Nombre de la opcion.

texto Texto Texto de la opcion.

tipo Enumeracion Tipo de opcion

BOOL Opcion de entrada de un booleano.

STRING Opcion de entrada de un texto.

[tipoSeleccion] Enumeracion Tipo de widget de seleccion de la entrada

COMBO Se utilizara un Combo para la seleccion.

RADIO HORIZONTAL Se utilizara RadioButton en disposicion horizon-tal.

RADIO VERTICAL Se utilizara RadioButton en disposicion vertical.

nitems Entero Numero de items de la seleccion.

item# Multivalor Item iesimo de la seleccion.

Entero Identificador del ıtem.

Texto Texto del item que se mostrara en la seleccion.

Clave: ENTRADACOLOR

Nombre Tipo Descripcion

nombre Texto Nombre de la opcion.

texto Texto Texto de la opcion.

tipo Enumeracion Tipo de opcion

COLOR Opcion de entrada de un color.

[conAlpha] Enumeracion Si el color tiene componente de transparencia.

cierto Tiene componente de transparencia.

falso No tiene componente de transparencia.

[mostrarBoton] Enumeracion Si se muestra el boton del dialogo seleccion decolor.

cierto Se muestra el boton.

falso No se muestra el boton.

[mostrarEntNum] Enumeracion Si se muestra las entradas numericas para intro-ducir el color.

cierto Se muestran las entradas numericas.

falso No se muestran las entradas numericas.

El siguiente ejemplo muestra la definicion de una ventana de opciones sen-cilla:VENTANAOPCIONES : ventanaopciones

{

titulo: EjemploVentanaOpciones

tipoVentanaOpciones: MARCOS

listaOpciones: listaEjemplo

}

LISTAOPCIONES: listaEjemlo

{

ngrupos: 1

58 Formato del fichero de configuracion

grupo1: GrupoEjemplo

}

GRUPOOPCIONES : GrupoEjemplo

{

nombre : grupoejemplo

texto : GrupoEjemplo

numcols : 2

nopciones : 2

opcion1 (OPCIONENTRADA ,opcion1)

opcion3 (ENTRADANUMERICA ,opcion2)

}

OPCIONENTRADA : opcion1

{

nombre : opcion1

texto : Opcion1

valor : ValorInicial

tipo : STRING

}

ENTRADANUMERICA : opcion2

{

nombre: opcion2

texto: Opcion2

tipo: REAL

valorMinimo: 0

valorMaximo: 10

incrementoPaso: 0.1

incrementoPagina: 1

valor: 1.1

}

3.2.4. Ventana de edicion de funciones 2D

Esta ventana (VentanaFuncion2D) es una ventana de menus a la quese la ha anadido un panel para editar funciones 2D, por lo tanto todos losatributos descritos para la ventana de menus son validos para esta. Ademastiene los siguientes atributos:

Clave: VENTANAFUNCION2D

Nombre Tipo Descripcion

. . . Todos los atributos de VENTANAMENU . . .

[etiquetaX] Texto Etiqueta del eje de las X.

[etiquetaY] Texto Etiqueta del eje de las Y.

[pathIconos] Texto Path al directorio donde se encuentran los ico-nos de la vetana.

[precision] Entero Numero de decimales de los valores.

3.2 Descripcion de los objetos de BioMedIGU 59

Clave: VENTANAFUNCION2D (Continuacion)

Nombre Tipo Descripcion

[rangoX] Multivalor Rango inicial de visualizacion para el eje X.

Real Valor mınimo

Real Valor maximo

[rangoY] Multivalor Rango inicial de visualizacion para el eje Y.

Real Valor mınimo

Real Valor maximo

[mostrarGrid] Enumeracion Si se muestra el grid en el panel de edicion.

cierto Se muestra el grid.

falso No se muestra el grid.

[editable] Enumeracion Si se permite la edicion de las funciones.

cierto Se puede editar.

falso Solo se visualiza.

[antialias] Enumeracion Si se realizara antialiasing en el panel.

cierto Se realiza antialiasing.

falso No se realiza antialiasing.

[slotAplicar] Multivalor Slot que se ejecutara al apretar el boton aplicar.

Texto Nombre de la funcion que formara el slot.

Texto Nombre de la librerıa/modulo donde se encuentra la funcion.

[modoAvanzado] Enumeracion Si se muestran opciones avanzadas al usuario.

cierto Se muestran opciones avanzadas al usuario.

falso No se muestran opciones avanzadas al usuario.

[modoInicial] Enumeracion Modo inicial de edicion.

MODO INSERTAR Modo para insertar puntos.

MODO ELIMINAR Modo para eliminar puntos.

MODO MODIFICAR Modo para mover puntos.

MODO VISUALIZAR Modo para visualizar funciones.

[autoIncrementos] Enumeracion Si se calculan automaticamente los incrementos de las marcas.

cierto Se calculan automaticamente los incrementos de las marcas.

falso No se calculan automaticamente los incrementos de las marcas.

[numMarcas] Multivalor Numero de marcas deseado cuando se calcula automaticamentelos incrementos.

Entero Numero de marcas para el eje X.

Entero Numero de marcas para el eje Y.

[incMarcas] Real Incremento de las marcas.

Real Incremento para el eje X.

Real Incremento para el eje Y.

[incEtiquetas] Multivalor Numero de marcas deseado entre las etiquetas de los ejes.

Entero Numero de marcas entre las etiquetas en el eje X.

Entero Numero de marcas entre las etiquetas en el eje Y.

[colorFondo] Multivalor Color del fondo de la area de edicion/visualizacion.

Real Componente roja (R) del color.

Real Componente verde (G) del color.

Real Componente azul (B) del color.

60 Formato del fichero de configuracion

Clave: VENTANAFUNCION2D (Continuacion)

Nombre Tipo Descripcion

[colorEjes] Multivalor Color de los ejes.

Real Componente roja (R) del color.

Real Componente verde (G) del color.

Real Componente azul (B) del color.

[colorGrid] Multivalor Color del grid.

Real Componente roja (R) del color.

Real Componente verde (G) del color.

Real Componente azul (B) del color.

nfunciones Entero Numero de funciones que se editan en la ventana.

funcion# Texto Nombre del objeto FUNCION2D que define la funcion iesima.

Las funciones que se editan/visualizan en la ventana se definen con los si-guientes atributos:

Clave: FUNCION2D

Nombre Tipo Descripcion

nombre Texto Nombre de la funcion.

[texto] Texto Texto de la funcion.

[tipoValorX] Enumeracion Tipo de los valores del eje X.

VALORES REALES Valores reales.

VALORES ENTEROS Valores enteros.

[tipoValorY] Enumeracion Tipo de los valores del eje Y.

VALORES REALES Valores reales.

VALORES ENTEROS Valores enteros.

[rangoX] Multivalor Rango de la funcion en el eje X.

Real Valor mınimo

Real Valor maximo

[rangoY] Multivalor Rango de la funcion en el eje Y.

Real Valor mınimo

Real Valor maximo

[color] Multivalor Color de la funcion.

Real Componente roja (R) del color.

Real Componente verde (G) del color.

Real Componente azul (B) del color.

nvalores Entero Numero de valores iniciales de la funcion.

[valor#] Multivalor Valor iesimo de la funcion.

Real Componente X.

Real Componente Y.

El siguiente ejemplo muestra la definicion de una ventana de edicion defunciones 2D sencilla:

VENTANAFUNCION2D: ventanafuncion2d

3.2 Descripcion de los objetos de BioMedIGU 61

{

titulo : FuncionTransferencia

alto : 425

ancho : 600

slotCerrar (on_cerrar ,moduloejemplo)

etiquetaX : Valor

etiquetaY : Propiedad

antialias : cierto

editable : cierto

barraHerramientas : cierto

barraEstado : cierto

modoInicial : MODIFICAR

nfunciones : 1

funcion1 : funcion1

precision : 3

slotAplicar (on_aplicar ,moduloejemplo)

}

FUNCION2D : funcion1

{

nombre : funcion1

texto : Funcion1

tipoValorX : VALORES_REALES

tipoValorY : VALORES_REALES

rangoX (0,3)

rangoY (0,3)

color (0,0,1)

nvalores: 2

valor1 (1,1)

valor2 (2 ,2.5)

}

3.2.5. Ventana Asistente

La ventana asistente es un tipo de ventana que muestra al usuario deforma ordenada opciones de entrada. Esta formada por diferentes listas deopciones que se mostraran secuencialmente o segun se decida en una de-terminada funcion. Los atributos que definen este tipo de ventana son lossiguientes:

Clave: VENTANAASISTENTE

Nombre Tipo Descripcion

[titulo] Texto Tıtulo de la ventana.

[ancho] Entero Ancho mınimo de la ventana (en pixels).

[alto] Entero Alto mınimo de la ventana (en pixels).

[funcionCrear] Multivalor Funcion utilizada para crear la ventana.

Texto Nombre de la funcion.

Texto Nombre de la librerıa/modulo.

62 Formato del fichero de configuracion

Clave: VENTANAASISTENTE (Continuacion)

Nombre Tipo Descripcion

[slotSiguiente] Multivalor Funcion que calcula el siguiente nodo.

Texto Nombre de la funcion.

Texto Nombre de la librerıa/modulo.

[mostrarTextoGrupos] Enumeracion Si se muestra el texto del grupo en el marco.

cierto Se mostrara el texto.

falso No se mostrara el texto.

nnodos Entero Numero de nodos que forman la ventana.

nodo# Multivalor Definicion del nodo iesimo.

Texto Nombre del objeto LISTAOPCIONES que de-fine la lista del nodo

Texto Tıtulo del nodo.

Texto Texto descriptivo de las opciones del nodo.

La definicion de las lista de opciones estan descritas en la seccion 3.2.3.El siguiente ejemplo muestra la definicion de una ventana asistente sencilla:

VENTANAASISTENTE : asistente1

{

titulo : Asistente1

ancho : 600

alto : 600

slotSiguiente (on_siguiente ,moduloejemplo)

nnodos : 2

nodo1 (Titulo1 ,Texto1 ,lista1)

nodo2 (Titulo2 ,Texto2 ,lista2)

}

Bibliografıa

[1] Murray Cumming, Bernhard Rieder, Jason M’Sadoques, Ole Laur-sen, and Gene Ruebsamen. Programming with Gtkmm2, 2002.http://www.gtkmm.org/gtkmm2/docs/tutorial/html/index.html.

[2] Gtkmm API Reference, 2002. http://www.gtkmm.org/gtkmm2/docs/.