Statistics
| Revision:

svn-gvsig-desktop / tags / v1_11_0_Build_1305 / docs / Andami developer guide.html @ 44114

History | View | Annotate | Download (16.6 KB)

1 1935 vcaballero
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
2
<html>
3
<head>
4
  <meta content="text/html; charset=ISO-8859-1"
5
 http-equiv="content-type">
6
  <title>Andami developer guide</title>
7
<link href="style.css" rel="stylesheet" type="text/css">
8
</head>
9
<body>
10
<table width="90%" border="0">
11
  <tr>
12
    <td class="Nivel2"><a href="#Introduccion"><strong><font color="#FFFFFF">Introducci&oacute;n</font></strong></a></td>
13
  </tr>
14
  <tr>
15
    <td class="Nivel2"><a href="#Creacion_de_plugins"><font color="#FFFFFF"><strong>Creaci&oacute;n
16
      de plugins</strong></font></a></td>
17
  </tr>
18
  <tr>
19
    <td class="Nivel2"><a href="#Funcionamiento_del_class_loader"><strong><font color="#FFFFFF">Funcionamiento
20
      del class loader</font></strong></a></td>
21
  </tr>
22
  <tr>
23
    <td class="Nivel2"><a href="#Servicios_a_los_plugins"><font color="#FFFFFF"><strong>Servicios
24
      a los plugins</strong></font></a></td>
25
  </tr>
26
  <tr>
27
    <td><strong>&nbsp;&nbsp;&nbsp; <a
28
 href="#Ejecucion_en_segundo_plano">Ejecuci&oacute;n en segundo plano</a></strong></td>
29
  </tr>
30
  <tr>
31
    <td><strong>&nbsp;&nbsp;&nbsp; <a href="#Acceso_a_las_extensiones">Acceso
32
      a las extensiones</a></strong></td>
33
  </tr>
34
  <tr>
35
    <td class="urbanismo"><strong>&nbsp;&nbsp;&nbsp; <a href="#Persistencia_de_los_plugins">Persistencia
36
      de los plugins</a></strong></td>
37
  </tr>
38
  <tr>
39
    <td><strong>&nbsp;&nbsp;&nbsp; <a href="#popupmenus">Pop-up menus</a></strong></td>
40
  </tr>
41
  <tr>
42
    <td><strong>&nbsp;&nbsp;&nbsp; <a href="#Vistas">Vistas</a></strong></td>
43
  </tr>
44
  <tr>
45
    <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#SingletonView">SingletonView's</a></td>
46
  </tr>
47
</table>
48
49
50
51
<p> <strong><font size="+1"><a name="Introduccion"></a>Introducci&oacute;n</font></strong></p>
52
<p> &nbsp;&nbsp;&nbsp; Andami es un framework orientado a plugins construido sobre
53
  swing que permite la construcci&oacute;n de forma r&aacute;pida y extensible
54
  de aplicaciones MDI (Multiple Document Interface). Tiene ya implementadas muchas
55
  de las funcionalidades requeridas para este tipo de aplicaciones tales como
56
  un men&uacute; Ventana, en la que van apareciendo las ventanas que se abren,
57
  soporte para el traducciones, configuraci&oacute;n personalizada para cada usuario,
58
  actualizaciones autom&aacute;ticas, tanto del propio Andami como de los plugins,
59
  persistencia del tama&ntilde;o y posici&oacute;n de la ventana, del idioma,
60
  distintos tipos de vista, con la finalidad de facilitar la programaci&oacute;n
61
  de ventanas especiales, ... Todo esto adem&aacute;s de tener ya solventados
62
  los problemas t&iacute;picos de la programaci&oacute;n de un entorno como &eacute;ste
63
  que no son pocos.<br>
64
  <br>
65
  &nbsp;&nbsp;&nbsp; Adem&aacute;s, Andami est&aacute; dise&ntilde;ada de forma
66
  que la propia l&oacute;gica MDI puede ser reemplazada. Si en lugar de una aplicaci&oacute;n
67
  estilo arcView, se quiere que cada vista que se a&ntilde;ada, se haga en una
68
  ventana de windows nueva (de las que aparecen en la barra de estado) o una vista
69
  como la de Eclipse, no hay m&aacute;s que desarrollar el plugin adecuado.<br>
70
  <br>
71
  &nbsp;&nbsp;&nbsp; Andami est&aacute; dise&ntilde;ada para ser amistosa con
72
  el usuario y para ello incorpora la posibilidad de a&ntilde;adir tooltips y
73
  enabletexts a los botones. El tooltip es el texto que aparece cuando el rat&oacute;n
74
  se detiene sobre un bot&oacute;n o men&uacute;. El enableText es el texto que
75
  aparece en el caso anterior cuando el bot&oacute;n est&aacute; desactivado,
76
  permitiendo mostrar al usuario qu&eacute; es lo que debe hacer para que dicho
77
  bot&oacute;n se active (o cualquier otro mensaje).<br>
78
  <br>
79
  &nbsp;&nbsp;&nbsp; Por &uacute;ltimo, Andami tiene una gesti&oacute;n de errores
80
  que agradar&aacute; a cualquier programador, ya que en casos de errores graves,
81
  el propio framework avisa de dicho fallo y aconseja al usuario salvar los cambios
82
  y reiniciar el programa, a parte de que toda excepci&oacute;n no capturada por
83
  el usuario se redirige a un fichero de log configurable en el que se escribir&aacute;
84
  su traza.<br>
85
</p>
86
<p> <strong><font size="+1"><a name="Creacion_de_plugins"></a>Creaci&oacute;n
87
  de plugins</font></strong></p>
88
<p> &nbsp;&nbsp;&nbsp; Andami gira en torno al concepto de plugin. Andami mantiene
89
  un directorio como directorio de los plugins, que se puede cambiar en cualquier
90
  momento. Un plugin viene definido por la existencia de un subdirectorio dentro
91
  del directorio de los plugins, siendo el nombre del plugin el nombre de dicho
92
  directorio. Dentro de dicho directorio debe haber un fichero config.xml en el
93
  que se configuran los puntos de entrada y salida del plugin (men&uacute;es,
94
  barras de herramientas, etiquetas de la barra de estado, men&uacute;es contextuales),
95
  las librer&iacute;as que va a usar, el paquete de traducciones, los plugins
96
  de los que depende, etc. El fichero plugin-config.xsd contiene el esquema que
97
  ha de seguir este fichero y est&aacute;n comentados todos los elementos. En
98
  el CorePlugin que viene con Adami se puede ver un ejemplo de config.xml.<br>
99
  <br>
100
  &nbsp;&nbsp;&nbsp; Las rutas de los directorios son siempre relativas al directorio
101
  del plugin y los textos de los men&uacute;es, tooltips y enabletext's son claves
102
  en el fichero de traducciones en caso de que haya y textos literales en caso
103
  de que no haya traducciones. El fichero de traducciones es un fichero de propiedades
104
  com&uacute;n: ver ResourceBundle en la API de Java.<br>
105
  <br>
106
  &nbsp;&nbsp;&nbsp; Dentro de los plugins aparece el concepto de extensi&oacute;n.
107
  Una extensi&oacute;n es instalada por los plugins mediante la implementaci&oacute;n
108
  de la interfaz com.iver.andami.plugins.Extension y la instalaci&oacute;n de
109
  unos controles geobernados por &eacute;sta en el fichero config.xml. Mediante
110
  esta implementaci&oacute;n se le dice a Andami la condici&oacute;n que se debe
111
  cumplir para que los controles sean visibles o est&eacute;n activos. Adem&aacute;s
112
  se implementa la acci&oacute;n a llevar a cabo cuando se selecciona uno de los
113
  men&uacute;es o botones asociados a la extensi&oacute;n. Cabe resaltar que Andami
114
  crea una instancia de cada extensi&oacute;n configurada en config.xml, por lo
115
  que las clases que implementen la interfaz Extension deben de tener un constructor
116
  sin argumentos.<br>
117
  <br>
118
  &nbsp;&nbsp;&nbsp; En los tag 'extension' existe un atributo class-name en el
119
  que se especifica la clase que gobierna el punto de extensi&oacute;n que se
120
  est&aacute; definiendo. Esta clase deber&aacute; implementar la interfaz com.iver.andami.plugins.Extension
121
  y ser&aacute; mediante &eacute;sta que gobernar&aacute; los men&uacute;es y
122
  botones asociados a este punto de extensi&oacute;n<br>
123
  <br>
124
  &nbsp;&nbsp;&nbsp; Una problema com&uacute;n en este framework es no ver c&oacute;mo
125
  se mantiene la informaci&oacute;n del proyecto concreto que se est&aacute; desarrollando.
126
  El lugar adecuado es una de las extensiones instaladas. Por ejemplo en el caso
127
  de gvSIG est&aacute; la extensi&oacute;n com.iver.cit.gvsig.ProjectExtension,
128
  en la cual hay un atributo Project que es la ra&iacute;z del &aacute;rbol jer&aacute;rquico
129
  del cual penden las vistas, mapas, tablas, ... Adem&aacute;s esta extensi&oacute;n
130
  tiene un m&eacute;todo getProject que devuelve la referencia al proyecto, de
131
  manera que se puede acceder desde cualquier punto de la aplicaci&oacute;n. Para
132
  ver el acceso a las instancias de las extensiones ver <a href="#Acceso_a_las_extensiones">acceso
133
  a las extensiones</a></p>
134
<p><br>
135
  <font size="+1"><strong><a name="Funcionamiento_del_class_loader"></a>Funcionamiento
136
  del class loader</strong></font></p>
137
<p> En Andami, el class loader de cada plugin delega primero en el classloader
138
  del sistemaes decir, que si se ejecuta desde eclipse buscar&aacute; por todos
139
  los jars que haya en el classpath del proyecto, y si se ejecuta desde la linea
140
  de comandos, buscar&aacute; en la variable de entorno CLASSPATH o en el argumento
141
  -classpath que se pase como par&aacute;metro a java.<br>
142
  <br>
143
  Si el class loader del sistema no satisface la b&uacute;squeda, se buscar&aacute;
144
  en los jars del directorio especificado por el config.xml del plugin que intenta
145
  cargar la clase y si no se encuentra en dichos jars, se buscar&aacute; en los
146
  jars de los plugins de los cuales depende el plugin que intenta cargar la clase.<br>
147
  <br>
148
  <strong><font size="+1"><a name="Servicios_a_los_plugins"></a>Servicios
149
  a los plugins</font></strong></p>
150
<p><br>
151
&nbsp;&nbsp;&nbsp; Andami ofrece a los plugins distintos servicios
152
  a trav&eacute;s de la clase PluginServices en cuyo javadoc se puede obtener
153
  informaci&oacute;n sobre como usarlos. Existen unos servicios gen&eacute;ricos
154
  que vienen dados por m&eacute;todos est&aacute;ticos de dicha clase y luego
155
  est&aacute; el m&eacute;todo getPluginServices que obtiene una instancia de
156
  esta clase espec&iacute;fica del plugin, mediante la cual puede acceder a servicios
157
  concretos de cada plugin, traducciones, persistencia, directorio del plugin,
158
  ...<br>
159
  &nbsp;<br>
160
  <strong><a name="Ejecucion_en_segundo_plano"></a>Ejecuci&oacute;n en segundo
161
  plano</strong><br>
162
  &nbsp;&nbsp;&nbsp; Es conveniente que la interfaz gr&aacute;fica est&eacute;
163
  siempre en funcionamiento, nunca bloqueada, aunque sea s&oacute;lo para mostrar
164
  al usuario que el programa est&aacute; procesando. Para ello hay que realizar
165
  las tareas que puedan tomar demasiado tiempo en un thread a parte. La clase
166
  PluginServices proporciona un m&eacute;todo est&aacute;tico backgroundExecution
167
  al cual se le pasa un objeto Runnable, que es ejecutado en segundo plano, dejando
168
  el thread de la interfaz libre para responder pero con sus eventos bloqueados
169
  con el fin de que la interfaz responda y se redibuje, pero se ignoren los eventos
170
  que produce el usuario mientras se procesa la petici&oacute;n<br>
171
  <br>
172
  <a name="Acceso_a_las_extensiones"></a><strong>Acceso a las extensiones</strong><br>
173
  &nbsp;&nbsp;&nbsp; Para acceder a la instancia de una extensi&oacute;n
174
  se puede usar simplemente el m&eacute;todo de PluginServices getExtension(Class)
175
  a la cual habr&aacute; que pasar como par&aacute;metro la clase de la extensi&oacute;n
176
  a la que se quiere acceder. Dicho m&eacute;todo retorna un objeto Extensi&oacute;n
177
  y por tanto habr&aacute; que hacer casting a la clase concreta de dicha extensi&oacute;n,
178
  habiendo obtenido as&iacute; la referencia a la instancia de la extensi&oacute;n
179
  deseada.<br>
180
  &nbsp;&nbsp;&nbsp; A la hora de desarrollar habr&aacute; que tener en el build
181
  path del entorno de desarrollo que se use, el jar del plugin dentro del cual
182
  est&aacute; la extensi&oacute;n que se quiere obtener, para poder pasarle como
183
  par&aacute;metro a getExtension(Class) la clase de la misma.<br>
184
  <br>
185
  <strong><a name="Persistencia_de_los_plugins"></a>Persistencia de
186
  los plugins</strong><br>
187
  &nbsp;&nbsp;&nbsp; Uno de los servicios que ofrece Andami a los
188
  plugins es la facilidad de guardar datos gen&eacute;ricos de los mismos en el
189
  directorio del usuario de manera que cada usuario mantiene su propia configuraci&oacute;n
190
  de los plugins. Para ello, las instancias de PluginServices contienen una propiedad
191
  persistentXML que puede ser obtenida y asignada y que es de tipo XMLEntity,
192
  pudiendo a&ntilde;adir informaci&oacute;n de tipo b&aacute;sico (String, int,
193
  long, ...) a dicha instancia y siendo esta informaci&oacute;n persistente entre
194
  ejecuciones.<br>
195
  <br>
196
  <strong><a name="popupmenus"></a>Pop-up menus</strong><br>
197
  &nbsp;&nbsp;&nbsp;&nbsp; Otro servicio proporcionado por Andami es el de pop-up
198
  menu's extensibles. Mediante el XML se puede definir un pop-up menu con un nombre
199
  y unas entradas al igual que cualquier otro men&uacute;, con la &uacute;nica
200
  diferencia que para mostrar el popup men&uacute; habr&aacute; que registrar
201
  un listener de la siguiente manera:<br>
202
</p>
203
<div style="text-align: center;">
204
<pre><>public void addPopupMenuListener(String name, Component c, ActionListener listener)</><br></pre>
205
</div>
206
&nbsp;&nbsp;&nbsp; Lo cual har&aacute; que al pinchar con el
207
bot&oacute;n derecho sobre el componente 'c' aparezca el men&uacute;
208
'name' del fichero de configuraci&oacute;n del plugin y al seleccionar
209
cualquier entrada se ejecutar&aacute; el ActionListener que se pasa
210
como par&aacute;metro.<br>
211
<br>
212
&nbsp;&nbsp;&nbsp; Estos men&uacute;es son extensibles porque cualquier
213
otro plugin puede a&ntilde;adir entradas a dicho men&uacute; en su
214
propio fichero config.xml referenciando el men&uacute; al que quiere
215
extender mediante el nombre del plugin m&aacute;s el nombre del
216
men&uacute;. Un ejemplo. Tenemos un plugin llamado com.iver.cit.gvsig
217
que instala un men&uacute; de la siguiente manera:<br>
218
<pre>                &lt;popupMenu name="cascada"&gt;<br>                        &lt;entry text="Cascada" <br>                                tooltip="cascada_tooltip" <br>                                enableText="cascada_enable" actionCommand="CASCADA"/&gt;<br>                        &lt;entry text="Tile" <br>                                tooltip="tile_tooltip" <br>                                enableText="cascada_enable" actionCommand="CASCADA"/&gt;<br>                &lt;/popupMenu&gt;<br></pre>
219
y tenemos otro plugin que quiere a&ntilde;adir una entrada a dicho
220
men&uacute;. Para ello deber&aacute; de incluir un fragmento similar a
221
este en su fichero config.xml:<br>
222
<pre>                &lt;popupMenu name="com.iver.cit.gvsig.cascada"&gt;<br>                        &lt;entry text="Nueva entrada" actionCommand="NUEVA"/&gt;<br>                &lt;/popupMenu&gt;<br></pre>
223
y adem&aacute;s deber&aacute; de registrarse como listener de la manera
224
que se explic&oacute; anteriormente.<br>
225
<br>
226
<strong><a name="Vistas"></a>Vistas</strong><br>
227
&nbsp;&nbsp;&nbsp; El servicio m&aacute;s importante que
228
proporciona Andami es el de a&ntilde;adir vistas al marco principal.
229
Podemos calsificar las vistas por varios criterios:<br>
230
<ul>
231
  <li>Por su modalidad</li>
232
  <ul>
233
    <li>Modales</li>
234
    <li>No modales</li>
235
  </ul>
236
</ul>
237
<ul>
238
  <li>Por su contenido</li>
239
  <ul>
240
    <li>Singleton (Contenido identificable)</li>
241
    <li>Normales (Contenido no identificable)</li>
242
  </ul>
243
</ul>
244
&nbsp;&nbsp;&nbsp; Para crear una vista hay que hacer una clase que
245
derive de JPanel en la que se pone toda la funcionalidad como si de un
246
di&aacute;logo normal se tratara. Adem&aacute;s esta clase ha de
247
implementar la interfaz View la cual proporciona un m&eacute;todo
248
getViewInfo que es invocado una vez en la vida de la vista. Este objeto
249
contiene las caracter&iacute;sticas que tendr&aacute; la vista:
250
maximizable, resizable, title, ... y puede ser actualizado en cualquier
251
momento, reflej&aacute;ndose estos cambios de manera autom&aacute;tica
252
en la interfaz de usuario. Una vez implementada la vista, hay que
253
a&ntilde;adirla al manger MDI, que es el encargado de manejar toda la
254
l&oacute;gica relacionada con las vistas. Para obtener una referencia
255
al manager MDI la clase PluginServices tiene un m&eacute;todo
256
getMDIManager, el cual a su vez tiene un m&eacute;todo addView mediante
257
el cual se puede a&ntilde;adir la vista.<br>
258
<br>
259
&nbsp;&nbsp;&nbsp; Si durante la ejecuci&oacute;n se quiere cambiar
260
alguna propiedad de la vista tal como el tama&ntilde;o, la
261
posici&oacute;n o el
262
t&iacute;tulo, s&oacute;lo hay que acceder al objeto ViewInfo de la
263
misma y realizar los cambios de la manera deseada. El siguiente trozo
264
de c&oacute;digo cambia el t&iacute;tulo de una ventana (se supone que
265
es ejecutado desde la clase que implementa View).<br>
266
<pre>        PluginServices.getMDIManager().getViewInfo(this).setTitle("Nuevo t&iacute;tulo");<br></pre>
267
&nbsp;&nbsp;&nbsp; Puede ser necesario que algunas vistas realicen
268
alg&uacute;n tipo de procesamiento al ser activadas pero esto no se
269
sabe cuando ocurre ya que lo que se entrega al manager MDI es un
270
JPanel. Para recibir los eventos sobre las vistas, adem&aacute;s de
271
implementar View hay que implementar ViewListener la cual
272
proporcionar&aacute; los m&eacute;todos que ser&aacute;n invocados
273
cuando sucedan los eventos oportunos en las vistas.<br>
274
<br>
275
<big><a name="SingletonView"></a>SingletonView<br>
276
</big>&nbsp;&nbsp;&nbsp; Un tipo especial de vistas son las
277
SingletonView. Su principal caracter&iacute;stica es que se les define
278
el contenido de las mismas, de manera que cuando hay una SingletonView
279
minimizada en el proyecto y se intenta a&ntilde;adir un JPanel con el
280
mismo contenido, en lugar de aparecer otra ventana en el escritorio, lo
281
que sucede es que la ventana que estaba minimizada se restaura a su
282
posici&oacute;n anterior. Para esto, el m&eacute;todo addView devuelve
283
una referencia a la vista que se muestra, sea esta la que se
284
est&aacute; a&ntilde;adiendo o la que ya est&aacute; a&ntilde;adida.
285
Adem&aacute;s, al cerrar dicha ventana se guardan las dimensiones y la
286
posici&oacute;n de las mismas, de manera que al volverla a abrir se
287
recuerdan estos datos.<br>
288
</body>
289
</html>