svn-gvsig-desktop / tags / v1_9_Build_1244 / docs / FMap.html @ 33182
History | View | Annotate | Download (23.2 KB)
1 |
<!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>FMap</title> |
7 |
<link href="style.css" rel="stylesheet" type="text/css"> |
8 |
</head>
|
9 |
<body>
|
10 |
<table width="600" border="0"> |
11 |
<tr>
|
12 |
<td> </td> |
13 |
<td bgcolor="#E86D26" colspan="2"><a href="#1._Introducci%F3n" class="Nivel2"><font color="#FFFFFF">1. |
14 |
Introducción</font></a></td> |
15 |
</tr>
|
16 |
<tr>
|
17 |
<td width="25"> </td> |
18 |
<td bgcolor="#E86D26" colspan="2"><font color="#FFFFFF"><a href="#2._Capas" class="Nivel2"><font color="#FFFFFF">2. |
19 |
Capas</font></a></font></td> |
20 |
</tr>
|
21 |
<tr>
|
22 |
<td> </td> |
23 |
<td colspan="2"> <a |
24 |
href="#2.1_VectorialData">2.1 VectorialData</a></td> |
25 |
</tr>
|
26 |
<tr>
|
27 |
<td> </td> |
28 |
<td colspan="2" class="Nivel2"><a href="#ViewPort"><font color="#FFFFFF">3. |
29 |
ViewPort</font></a></td> |
30 |
</tr>
|
31 |
<tr>
|
32 |
<td> </td> |
33 |
<td colspan="2" class="Nivel2"><a href="#Eventos"><font color="#FFFFFF">4. |
34 |
Eventos</font></a></td> |
35 |
</tr>
|
36 |
<tr>
|
37 |
<td> </td> |
38 |
<td colspan="2"> <a href="#AtomicEvents">4.1 AtomicEvent's</a></td> |
39 |
</tr>
|
40 |
<tr>
|
41 |
<td> </td> |
42 |
<td colspan="2" class="Nivel2"><a href="#Drivers" class="Nivel2"><font color="#FFFFFF">5. |
43 |
Drivers</font></a></td> |
44 |
</tr>
|
45 |
<tr>
|
46 |
<td> </td> |
47 |
<td colspan="2"> <a href="#VectorialFileDriver">5.1 |
48 |
VectorialFileDriver</a></td> |
49 |
</tr>
|
50 |
<tr>
|
51 |
<td> </td> |
52 |
<td colspan="2" class="Nivel2"><a href="#Interfaz_de_usuario" class="Nivel2"><font color="#FFFFFF">6. |
53 |
Interfaz de usuario</font></a></td> |
54 |
</tr>
|
55 |
<tr>
|
56 |
<td height="16"> </td> |
57 |
<td colspan="2"> <a href="#MapControl">6.1 |
58 |
MapControl</a></td> |
59 |
</tr>
|
60 |
<tr>
|
61 |
<td> </td> |
62 |
<td colspan="2"> <a href="#MapBehaviors">6.2 |
63 |
MapBehavior</a></td> |
64 |
</tr>
|
65 |
<tr>
|
66 |
<td height="31"> </td> |
67 |
<td colspan="2"> <a |
68 |
href="#Creacion_de_una_herramienta_en_base_a_un">6.2.1 Creación de una |
69 |
herramienta en base a un behavior existente</a><br> |
70 |
<a |
71 |
href="#Creacion_de_una_herramienta_con_un">6.2.2 Creación de una herramienta |
72 |
con un comportamiento no implementado</a></td> |
73 |
</tr>
|
74 |
<tr>
|
75 |
<td width="25"> </td> |
76 |
<td colspan="2"> <a |
77 |
href="#Composicion_de_herramientas">6.3 Composición de herramientas</a></td> |
78 |
</tr>
|
79 |
<tr>
|
80 |
</table>
|
81 |
<p><strong><font size="+2"><a name="1._Introduccion"></a>1. Introducción</font></strong><br><br> |
82 |
En el paquete FMap, un mapa está |
83 |
compuesto por:<br>
|
84 |
</p>
|
85 |
<ul>
|
86 |
<li>Una instancia de la clase FMap que sirve como frontend al usuario
|
87 |
programador.</li>
|
88 |
<li>Un elemento de interfaz de usuario en el que se
|
89 |
visualizará el mapa. Típicamente será un |
90 |
MapControl, pero potencialmente puede ser cualquier control.</li>
|
91 |
<li>Una instancia de ViewPort, en el cual se almacena la
|
92 |
información relativa a la parte de la cartografía que se |
93 |
quiere ver, la ventana donde se muestra, la escala, ...</li>
|
94 |
<li>Una colección de capas: la cartografía</li> |
95 |
</ul>
|
96 |
<p> Para obtener una imagen de un mapa hay que:<br> |
97 |
</p>
|
98 |
<ul>
|
99 |
<li>Configurar el directorio de los drivers. Debido a que FMap es
|
100 |
extensible por medio de drivers, hay que decirle dónde se
|
101 |
encuentran estos, de lo contrario saltará una excepción.</li> |
102 |
</ul>
|
103 |
<pre> LayerFactory.setDriversPath("C:\\drivers");<br></pre> |
104 |
<ul>
|
105 |
<li>Configurar el ViewPort. Al añadir la capa al mapa, muchos de los |
106 |
datos relacionados con la cartografía se configurarán automáticamente |
107 |
con lo que sólo nos queda configurar el tamaño de la ventana. |
108 |
(TODO: Explicar algo de proyecciones)<br>
|
109 |
</li>
|
110 |
</ul>
|
111 |
<pre> ViewPort vp = new ViewPort(ProjectionPool.get("ed50utm30"));<br> vp.setImageSize(new Dimension(100, 100));<br> FMap mapa = new FMap(vp);<br></pre> |
112 |
<ul>
|
113 |
<li> Añadir cartografía al mapa. Esto se hace |
114 |
mediante la clase LayerFactory la cual contiene métodos para
|
115 |
crear capas a partir de ficheros, urls de servidores, ... en los que |
116 |
hay que especificar además el driver que se quiere usar para
|
117 |
leer los datos. A continuación tenemos un ejemplo en el que se
|
118 |
crea una capa vectorial a partir de un shapefile y luego se |
119 |
añade al mapa. (TODO: Explicar la relación entre las |
120 |
proyecciones del viewport y la de la capa que se añade)</li> |
121 |
</ul>
|
122 |
</div>
|
123 |
<pre> l = LayerFactory.createLayer("Vias", "DemoSHPDriver", new File("c:\\vias.shp"), ProjectionPool.get("ed50utm30"));<br> mapa.getLayers().addLayer(l);<br></pre> |
124 |
<ul>
|
125 |
<li>Ahora ya solo queda dibujar la imagen</li> |
126 |
</ul>
|
127 |
<pre> BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);<br> mapa.draw(img, img.createGraphics());<br><br></pre> |
128 |
<p>El ejemplo concreto que se acaba de mostrar se corresponde al ImageFrame del
|
129 |
ejemplo "com.iver.cit.gvsig.fmap.DrawImage". Para un ejemplo de uso de FMap |
130 |
desde un elemento complejo de interfaz de usuario ver <a
|
131 |
href="#Interfaz_de_usuario">Interfaz de usuario</a><br> |
132 |
<br>
|
133 |
<strong><a name="2._Capas"></a><font size="+2">2. Capas</font></strong><br><br> |
134 |
Cada mapa visualiza en una imagen cartografía |
135 |
cuyo origen puede ser muy diverso: ficheros, servidores WMS, ... Para añadir
|
136 |
un origen de datos cartográficos a un mapa aparece el concepto de Capa.
|
137 |
Las capas representan un origen de datos cartográficos independientemente
|
138 |
de su ubicación y naturaleza. Fmap tiene un método getLayers() |
139 |
el cual devuelve una capa especial, consistente en un conjunto de capas inicialmente |
140 |
vacío que son utilizadas para realizar las operaciones de dibujado, impresión, |
141 |
... <br>
|
142 |
En FMap, una capa viene definida por la interfaz FLayer de |
143 |
modo que toda clase que implemente la interfaz FLayer es una capa. Además
|
144 |
de esta interfaz, hay un conjunto de interfaces que definen las características
|
145 |
de una capa. Estas están en el paquete "com.iver.cit.gvsig.fmap.layer.layerOperations"
|
146 |
y permiten crear capas con distintas capacidades a medida de la necesidad del |
147 |
programador, usuario, estandar, ...<br>
|
148 |
Por otro lado, la creación de las capas que inicialmente |
149 |
parten con gvSIG está centralizada en FLayers teniendo ésta métodos |
150 |
estáticos para crear cualquiera de estas capas fácilmente.<br> |
151 |
Una vez se obtiene una referencia a FLayer, si se quiere |
152 |
realizar una operación concreta, se debe de comprobar si dicha capa implementa
|
153 |
la interfaz del paquete "com.iver.cit.gvsig.fmap.layer.layerOperations" que |
154 |
da soporte a dicha operación, teniendo que hacer un casting para realizar
|
155 |
la operación. Por ejemplo, el siguiente código borraría |
156 |
la selección de todas las capas activas con soporte de selección |
157 |
de un array layers :<br>
|
158 |
</p>
|
159 |
<pre> for (Iterator iter = layers.iterator(); iter.hasNext();) {<br> FLayer layer = (FLayer) iter.next();<br><br> if (layer.isActive()) {<br> if (layer instanceof Selectable) {<br> ((Selectable) layer).clearSelection();<br> }<br> }<br> }<br></pre> |
160 |
<p> Para entender de forma más completa las operaciones |
161 |
que se pueden hacer con las capas se puede leer la documentación a nivel
|
162 |
de API de las interfaces del paquete mencionado anteriormente.<br>
|
163 |
(TODO: Poner la descripción de las interfaces aquí)<br> |
164 |
<br>
|
165 |
<strong><font size="+1"><a name="2.1_VectorialData"></a>2.1 VectorialData</font></strong><br> |
166 |
<br>
|
167 |
Mención a parte merece la interfaz VectorialData |
168 |
por su sofistificación. Las capas vectoriales en FMap pueden tener una
|
169 |
fuente de datos secuencial o aleatoria, en función del driver utilizado,
|
170 |
por lo que una selección por rectángulo debería de implementarse |
171 |
dos veces, una para cada tipo de driver. Para evitar esto hemos empleado un |
172 |
mecanismo mediante el cual, el programador debe implementar unas clases que |
173 |
derivan de com.iver.cit.gvsig.fmap.operations.strategies.FeatureVisitor. En |
174 |
esta interfaz hay 3 métodos: start, visit y stop. Estos métodos |
175 |
están documentados en la API. Pongamos un sencillo ejemplo: para realizar
|
176 |
una selección por rectángulo tendra que<br> |
177 |
</p>
|
178 |
<ul>
|
179 |
<li>Crear una clase que implemente FeatureVisitor y que reciba en su
|
180 |
constructor o mediante un "setter" el rectángulo mediante el
|
181 |
cual se va a realizar la selección:</li> |
182 |
</ul>
|
183 |
<pre> public void setRect(Rectangle2D r) {<br> rect = r;<br> }<br></pre> |
184 |
<ul>
|
185 |
<li>En el método start se comprueba que la capa es |
186 |
seleccionable, porque es una condición necesaria para hacer una
|
187 |
selección por rectángulo.</li> |
188 |
</ul>
|
189 |
<pre> public boolean start(FLayer layer) {<br> return layer instanceof Selectable;<br> }<br></pre> |
190 |
<ul>
|
191 |
<li>En el método visit, que será invocado para cada |
192 |
geometría de la capa, se comprueba si la geometría ha de |
193 |
ser seleccionada. Si es seleccionada se guarda dicha información
|
194 |
en un BitSet.</li>
|
195 |
</ul>
|
196 |
<pre> public void visit(IGeometry g, int index) {<br> if (g.intersects(rect)) {<br> bitset.set(index, true);<br> } else {<br> bitset.set(index, false);<br> }<br> }<br></pre> |
197 |
<ul>
|
198 |
<li>Para terminar con la implementación, en el método |
199 |
stop se seleccionan las geometrías de la capa sobre la cual se
|
200 |
ha operado que se han comprobado que quedaban dentro del |
201 |
rectángulo.</li> |
202 |
</ul>
|
203 |
<pre> ((Selectable) layer).setSelection(bitset);<br></pre> |
204 |
<ul>
|
205 |
<li>Por último queda ejecutar el algoritmo de selección |
206 |
sobre una capa. Nada más facil que comprobar si la capa
|
207 |
implementa VectorialData (acepta FeatureVisitor's), crear una instancia |
208 |
del visitor que acabamos de implementar, pasarle el rectángulo
|
209 |
con el que seleccionaremos e invocar:</li>
|
210 |
</ul>
|
211 |
<pre> ((VectorialData) layer).process(new SelectionByRectVisitor(r));<br><br></pre> |
212 |
<p> Como se puede comprobar, en ningún momento hemos |
213 |
necesitado saber si el origen de la capa es secuencial o aleatorio. En el paquete |
214 |
"com.iver.cit.gvsig.fmap.operations.strategies" hay muchos más ejemplos
|
215 |
de FeatureVisitors.<br>
|
216 |
<br>
|
217 |
<strong><font size="+2"><a name="ViewPort"></a>3. ViewPort</font></strong><font size="+2"></font></strong><br><br> |
218 |
|
219 |
La clase ViewPort guarda la informaci?n relativa a las transformaci?nes de coordenadas y datos acerca de la proyecci?n |
220 |
actual. Para ello, almacena el tama?o de la imagen sobre la que se dibuja, el rect?ngulo de visualizaci?n, el rect?ngulo |
221 |
ajustado al marco de visualizaci?n, etc. |
222 |
Tambi?n se ocupa de gestionar los "listeners" que escuchan los eventos de cambio de "extent", y de realizar los c?lculos |
223 |
de ?rea, per?metro y distancia. <br> <br> |
224 |
<strong><font size="+2"><a name="Eventos"></a>4. Eventos</font></strong><br> |
225 |
<br>
|
226 |
FMap pone a disposición del programador todo un mecanismo |
227 |
para que se pueda saber "lo que está pasando por dentro del mapa". Cada
|
228 |
elemento de FMap tiene un método de la forma addXXXListener, mediente
|
229 |
el cual el programador puede registrarse como observador de los eventos que |
230 |
ocurren en el objeto en cuestión. Por ejemplo, el ViewPort tiene un addViewPortListener
|
231 |
que recibe una interfaz ViewPortListener. La clase que implemente esta interfaz |
232 |
y sea registrada mediante el método addViewPortListener será notificada |
233 |
de los eventos de cambio de extent y cambio de color de fondo en el ViewPort |
234 |
mediante invocaciones a los métodos de la interfaz que implementa. Esto
|
235 |
presenta un problema y para mostrarlo vamos a suponer que tenemos un control |
236 |
de interfaz de usuario que escucha eventos del ViewPort y de la colección
|
237 |
de capas, de manera que cuando se añade una capa o se modifica el extent
|
238 |
se redibuja la imagen que muestra. Resulta que cuando se añade la primera
|
239 |
capa se modifica también el extent por lo que en el caso del control
|
240 |
del ejemplo se refrescará la imagen dos veces de manera innecesaria.
|
241 |
La solución son los AtomicEvent's.<br> |
242 |
<br>
|
243 |
<strong><font size="+1"> <a name="AtomicEvents"></a>4.1 AtomicEvent's</font></strong><br> |
244 |
<br>
|
245 |
Para solucionar el problema anterior FMap incorpora dos métodos |
246 |
beginAtomicEvent y endAtomicEvent. Estos métodos no afectan a la gestión |
247 |
de eventos de los elementos individuales de FMap, afecta a la gestión
|
248 |
de eventos desde FMap. Al igual que otros elementos del paquete FMap contiene |
249 |
un método addAtomicEventListener con la funcionalidad análoga |
250 |
a los addXXXListener comentados antes. Una vez registrado, el listener será
|
251 |
notificado de cualquier evento que suceda por dentro de esa instancia de FMap |
252 |
(en las capas, viewport, leyenda, ...) con la única diferencia que podrá |
253 |
ser notificado de varios eventos al mismo tiempo. Si un trozo de código
|
254 |
se encuentra entre las instrucciones beginAtomicEvent y endAtomicEvent, los |
255 |
objetos individuales (ViewPort, Layers, ...) dispararán eventos de la
|
256 |
misma manera, pero la instancia de FMap acumulará los eventos desde que
|
257 |
se ejecuta beginAtomicEvent hasta que se ejecuta endAtomicEvent, momento en |
258 |
el cual se disparará un AtomicEvent con los eventos acumulados embebidos
|
259 |
en el anterior. En caso de que no se use beginAtomicEvent y endAtomicEvent FMap |
260 |
no acumulará eventos, pero seguirá disparándolos a medida |
261 |
que le van llegando. Como ejemplo de listener de AtomicEvent tenemos la clase |
262 |
NewMapControl, la cual escucha atomic events en la clase interna MapContextListener. |
263 |
Como ejemplo de código que usa beginAtomicEvent y endAtomicEvent tenemos
|
264 |
el método execute de la extensión com.iver.cit.gvsig.Abrir en |
265 |
gvSIG<br>
|
266 |
<br>
|
267 |
<strong><font size="+2"><a name="Drivers"></a>5 Drivers</font></strong><br> |
268 |
<br>
|
269 |
FMap lee las fuentes de datos mediante el uso de drivers, |
270 |
lo cual permite a cualquiera implementar un driver determinado para cualquier |
271 |
formato existente. Para ello hay que configurar un directorio en el que se colocan |
272 |
los drivers cada uno dentro de su directorio de la siguiente manera:<br>
|
273 |
<br>
|
274 |
</p>
|
275 |
<div style="text-align: center;"><img alt="" src="images/dir.png" |
276 |
style="width: 293px; height: 189px;"><br> |
277 |
</div>
|
278 |
<p><br> |
279 |
Cada tipo de driver (vectorial, raster, ...) debe ser implementado |
280 |
mediante una interfaz distinta (VectorialFileDriver, WMSDriver, ...) y además
|
281 |
de implementar esta interfaz, se pueden implementar otras interfaces que añaden
|
282 |
un valor añadido al driver.<br> |
283 |
<br>
|
284 |
<strong><font size="+1"><a name="VectorialFileDriver"></a>5.1 VectorialFileDriver</font><br> |
285 |
<br>
|
286 |
</strong> Para crear un driver de un fichero de |
287 |
tipo vectorial hay que implementar la interfaz VectorialFileDriver cuyos métodos
|
288 |
están documentados en el JavaDoc. Mediante esta interfaz el driver obtiene
|
289 |
el acceso a los datos geográficos de los ficheros vectoriales. Además |
290 |
de esta interfaz hay que implementar una interfaz para el acceso a los datos |
291 |
alfanuméricos. Dependiendo de cómo estén organizados estos |
292 |
datos se puede implementar com.iver.cit.gvsig.fmap.drivers.ExternalData, que |
293 |
es una interfaz útil para cuando los datos alfanuméricos se encuentran |
294 |
en un fichero distinto al fichero de datos geográficos (caso del shapefile),
|
295 |
o se puede implementar com.hardcode.gdbms.engine.data.FileDriver que es adecuado |
296 |
para los casos en los que la tabla de datos alfanuméricos se encuentra
|
297 |
en el mismo soporte que los datos geográficos (caso del DGN).<br> |
298 |
<br>
|
299 |
Una vez implementadas estas dos interfaces, se pueden implementar |
300 |
otras para darle un valor añadido a los drivers:<br> |
301 |
</p>
|
302 |
<ul>
|
303 |
<li>BoundedShapes: Acelera el procesado de las geometrías a la |
304 |
hora de dibujar<br>
|
305 |
</li>
|
306 |
<li>WithDefaultLegend: Establece la leyenda por defecto de los
|
307 |
ficheros del driver.<br>
|
308 |
</li>
|
309 |
</ul>
|
310 |
<p><br> |
311 |
<strong><font size="+2"><a name="Interfaz_de_usuario"></a>6 Interfaz de usuario</font></strong><br> |
312 |
<br>
|
313 |
Con el paquete FMap se proporciona un control de interfaz |
314 |
de usuario junto con una serie de herramientas diseñadas para este control.
|
315 |
MapControl es la interfaz de usuario sobre FMap que se proporciona con gvSIG |
316 |
y automatiza gran parte de la programación del interfaz gráfico |
317 |
de un mapa, lanzando el dibujado en un segundo plano, redibujando automáticamente
|
318 |
cuando el FMap que tiene por debajo queda invalidado, ... Además se proporcionan
|
319 |
una serie de herramientas preparadas para su uso y extensibles de manera que |
320 |
la incorporación de nuevas herramientas por parte del usuario sea un
|
321 |
proceso trivial siempre que el comportamiento de la herramienta ya esté
|
322 |
programado. En las secciones posteriores se verá esto en más detalle.<br> |
323 |
<br>
|
324 |
<strong><a name="MapControl"></a><font size="+1">6.1 MapControl</font></strong><br> |
325 |
<br>
|
326 |
MapControl es un control de usuario que tiene |
327 |
como modelo una instancia de FMap a la que se puede acceder mediante el método
|
328 |
getMapContext(). A continuación presentamos los pasos básicos |
329 |
para mostrar un Frame con un MapControl sin herramientas. En la sección
|
330 |
siguiente se añadirán herramientas con comportamientos ya existentes |
331 |
y cómo añadir herramientas con un comportamiento no programado |
332 |
todavía.<br> |
333 |
</p>
|
334 |
<ul>
|
335 |
<li>Partimos de un JFrame con un BorderLayout y un MapControl en el
|
336 |
centro.</li>
|
337 |
<li>Se configura el directorio de los drivers como en el ejemplo
|
338 |
ImageFrame</li>
|
339 |
</ul>
|
340 |
<pre> LayerFactory.setDriversPath(</pre> |
341 |
<pre> "C:\\eclipse3\\workspace\\Andami\\gvSIG\\extensiones\\com.iver.cit.gvsig\\drivers");</pre> |
342 |
<ul>
|
343 |
<li>Se añaden las capas al mapa que hay como modelo del |
344 |
MapControl</li>
|
345 |
</ul>
|
346 |
<pre> FLayer l = LayerFactory.createLayer("Vias", "gvSIG shp driver",</pre> |
347 |
<pre> new File("C:/Documents and Settings/fernando/Mis documentos/vias.shp"),</pre> |
348 |
<pre> ProjectionPool.get("EPSG:23030"));</pre> |
349 |
<pre> newMapControl.getMapContext().getLayers().addLayer(l);</pre> |
350 |
<ul>
|
351 |
<li>Se añade una herramienta y se selecciona</li> |
352 |
</ul>
|
353 |
<pre> newMapControl.addMapTool("zoom", new RectangleBehavior(new ZoomInListenerImpl(newMapControl)));<br> newMapControl.setTool("zoom");<br><br></pre> |
354 |
<p><strong><font size="+1"><a name="MapBehaviors"></a>6.2 MapBehaviors</font></strong><br> |
355 |
<br>
|
356 |
Las herramientas que se proporcionan en FMap |
357 |
son en realidad comportamientos. Se define un comportamiento del ratón
|
358 |
tal como hacer un rectángulo (clase RectangleBehavior), dibujar una polilinea
|
359 |
(PolylineBehavior), etc. y estos comportamientos disparan eventos relacionados |
360 |
con su propio comportamiento, por ejemplo, la herramienta de hacer rectángulo
|
361 |
cuando el usuario termina de dibujar el rectángulo se lanza un evento
|
362 |
rectangle definido en la interfaz com.iver.cit.gvsig.fmap.tools.RectangleListener. |
363 |
De esta manera, para implementar las herramientas que tengan el comportamiento |
364 |
de dibujado de rectángulo (zoom in, selección por rectángulo, |
365 |
...) sólo tienen que implementarse los listeners de los eventos. En el
|
366 |
ejemplo anterior hemos visto como se añadía una herramienta al |
367 |
MapControl mediante el behavior RectangleMapBehavior el cual toma en su constructor |
368 |
la acción que se realiza con el rectángulo (acercar la imagen).<br> |
369 |
<br>
|
370 |
<strong><a name="Creacion_de_una_herramienta_en_base_a_un"></a>6.2.1 Creación |
371 |
de una herramienta en base a un behavior existente</strong><br><br> |
372 |
Para crear una herramienta con un comportamiento ya |
373 |
implementado, hay que implementar la interfaz que dicho behavior espera. Para |
374 |
averiguar qué interfaz es ésta hay que leer la documentación |
375 |
de cada behavior. En el paquete "com.iver.cit.gvsig.fmap.tools" hay múltiples
|
376 |
ejemplos sobre como implementar las interfaces de los distintos behaviors.<br>
|
377 |
<br> |
378 |
<strong><a name="Creacion_de_una_herramienta_con_un"></a>6.2.2 Creación |
379 |
de una herramienta con un comportamiento no implementado</strong><br><br> |
380 |
Para realizar una herramienta para la cual no haya |
381 |
un behavior definido se pueden realizar dos aproximaciones:<br>
|
382 |
</p>
|
383 |
<ul>
|
384 |
<li>Implementar un behavior que delegue mediante eventos el
|
385 |
comportamiento de la herramienta del mismo modo que hacen los behaviors |
386 |
de FMap y luego implementar un listener de los eventos que la behavior |
387 |
implementada genera, lo cual queda lejos del alcance del presente |
388 |
documento.</li>
|
389 |
<li>Implementar una herramienta de forma completa. Para ello hay que
|
390 |
crear una clase que derive de |
391 |
com.iver.cit.gvsig.fmap.tools.Behavior.Behavior e implementar los |
392 |
métodos necesarios. Para más información sobre |
393 |
cómo implementar esta clase se puede ver el javadoc de la misma.<br> |
394 |
</li>
|
395 |
</ul>
|
396 |
<p><br> |
397 |
<strong><font size="+1"><a name="Composicion_de_herramientas"></a>6.3 Composición |
398 |
de herramientas</font></strong><br> |
399 |
<br>
|
400 |
El modelo de herramientas sigue un patrón |
401 |
composite. Esto quiere decir que existe una herramienta especial que consiste |
402 |
realmente en un conjunto de herramientas. Teoría a parte, esto quiere
|
403 |
decir que podemos tener varias herramientas seleccionadas simultáneamente
|
404 |
como una sóla. Por ejemplo, podemos tener una herramienta que haga zoom
|
405 |
in, a la vez que podemos tener la herramienta que haga zoomout con el botón
|
406 |
derecho del ratón y a la vez que tenemos una maptool que muestra la coordenada
|
407 |
de la posición actual del ratón. Tenemos un ejemplo de esto en |
408 |
la clase View de gvSIG:<br>
|
409 |
</p>
|
410 |
<pre> m_MapControl.addMapTool("zoomIn", new CompoundBehavior(new RectangleBehavior(zil),<br> new PointBehavior(zoil), new MouseMovementBehavior(sbl)));<br></pre> |
411 |
<p> Que añade la herramienta compuesta por las 3 herramientas |
412 |
simples deseadas. También existe un método de conveniencia que |
413 |
acepta un array de Behaviour's y crea internamente el CompoundBehavior.<br>
|
414 |
<br>
|
415 |
</p>
|
416 |
</body>
|
417 |
</html>
|