svn-gvsig-desktop / tags / v1_9_Build_1237 / docs / FMap.html @ 34757
History | View | Annotate | Download (23.2 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>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> |