Statistics
| Revision:

svn-gvsig-desktop / tags / v1_12_0_Build_1417 / docs / FMap.html @ 40002

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>&nbsp;</td>
13
    <td bgcolor="#E86D26" colspan="2"><a href="#1._Introducci%F3n" class="Nivel2"><font color="#FFFFFF">1.
14
      Introducci&oacute;n</font></a></td>
15
  </tr>
16
  <tr>
17
    <td width="25">&nbsp;</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>&nbsp;</td>
23
    <td colspan="2">&nbsp;&nbsp;&nbsp; <a
24
 href="#2.1_VectorialData">2.1 VectorialData</a></td>
25
  </tr>
26
  <tr>
27
    <td>&nbsp;</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>&nbsp;</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>&nbsp;</td>
38
    <td colspan="2">&nbsp;&nbsp;&nbsp; <a href="#AtomicEvents">4.1 AtomicEvent's</a></td>
39
  </tr>
40
  <tr>
41
    <td>&nbsp;</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>&nbsp;</td>
47
    <td colspan="2">&nbsp;&nbsp;&nbsp; <a href="#VectorialFileDriver">5.1
48
      VectorialFileDriver</a></td>
49
  </tr>
50
  <tr>
51
    <td>&nbsp;</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">&nbsp;</td>
57
    <td colspan="2">&nbsp;&nbsp;&nbsp; <a href="#MapControl">6.1
58
      MapControl</a></td>
59
  </tr>
60
  <tr>
61
    <td>&nbsp;</td>
62
    <td colspan="2">&nbsp;&nbsp;&nbsp; <a href="#MapBehaviors">6.2
63
      MapBehavior</a></td>
64
  </tr>
65
  <tr>
66
    <td height="31">&nbsp;</td>
67
    <td colspan="2">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <a
68
 href="#Creacion_de_una_herramienta_en_base_a_un">6.2.1 Creaci&oacute;n de una
69
      herramienta en base a un behavior existente</a><br>
70
      &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <a
71
 href="#Creacion_de_una_herramienta_con_un">6.2.2 Creaci&oacute;n de una herramienta
72
      con un comportamiento no implementado</a></td>
73
  </tr>
74
  <tr>
75
    <td width="25">&nbsp;</td>
76
    <td colspan="2">&nbsp;&nbsp;&nbsp; <a
77
 href="#Composicion_de_herramientas">6.3 Composici&oacute;n de herramientas</a></td>
78
  </tr>
79
  <tr>
80
</table>
81
<p><strong><font size="+2"><a name="1._Introduccion"></a>1. Introducci&oacute;n</font></strong><br><br>
82
  &nbsp;&nbsp;&nbsp; En el paquete FMap, un mapa est&aacute;
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&aacute; el mapa. T&iacute;picamente ser&aacute; un
90
MapControl, pero potencialmente puede ser cualquier control.</li>
91
  <li>Una instancia de ViewPort, en el cual se almacena la
92
informaci&oacute;n relativa a la parte de la cartograf&iacute;a que se
93
quiere ver, la ventana donde se muestra, la escala, ...</li>
94
  <li>Una colecci&oacute;n de capas: la cartograf&iacute;a</li>
95
</ul>
96
<p>&nbsp;&nbsp;&nbsp; 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&oacute;nde se
101
encuentran estos, de lo contrario saltar&aacute; una excepci&oacute;n.</li>
102
</ul>
103
<pre>        LayerFactory.setDriversPath("C:\\drivers");<br></pre>
104
<ul>
105
  <li>Configurar el ViewPort. Al a&ntilde;adir la capa al mapa, muchos de los
106
    datos relacionados con la cartograf&iacute;a se configurar&aacute;n autom&aacute;ticamente
107
    con lo que s&oacute;lo nos queda configurar el tama&ntilde;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>&nbsp;A&ntilde;adir cartograf&iacute;a al mapa. Esto se hace
114
mediante la clase LayerFactory la cual contiene m&eacute;todos para
115
crear capas a partir de ficheros, urls de servidores, ... en los que
116
hay que especificar adem&aacute;s el driver que se quiere usar para
117
leer los datos. A continuaci&oacute;n tenemos un ejemplo en el que se
118
crea una capa vectorial a partir de un shapefile y luego se
119
a&ntilde;ade al mapa. (TODO: Explicar la relaci&oacute;n entre las
120
proyecciones del viewport y la de la capa que se a&ntilde;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
  &nbsp;&nbsp;&nbsp; Cada mapa visualiza en una imagen cartograf&iacute;a
135
  cuyo origen puede ser muy diverso: ficheros, servidores WMS, ... Para a&ntilde;adir
136
  un origen de datos cartogr&aacute;ficos a un mapa aparece el concepto de Capa.
137
  Las capas representan un origen de datos cartogr&aacute;ficos independientemente
138
  de su ubicaci&oacute;n y naturaleza. Fmap tiene un m&eacute;todo getLayers()
139
  el cual devuelve una capa especial, consistente en un conjunto de capas inicialmente
140
  vac&iacute;o que son utilizadas para realizar las operaciones de dibujado, impresi&oacute;n,
141
  ... <br>
142
  &nbsp;&nbsp;&nbsp; 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&aacute;s
144
  de esta interfaz, hay un conjunto de interfaces que definen las caracter&iacute;sticas
145
  de una capa. Estas est&aacute;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
  &nbsp;&nbsp;&nbsp; Por otro lado, la creaci&oacute;n de las capas que inicialmente
149
  parten con gvSIG est&aacute; centralizada en FLayers teniendo &eacute;sta m&eacute;todos
150
  est&aacute;ticos para crear cualquiera de estas capas f&aacute;cilmente.<br>
151
  &nbsp;&nbsp;&nbsp; Una vez se obtiene una referencia a FLayer, si se quiere
152
  realizar una operaci&oacute;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&oacute;n, teniendo que hacer un casting para realizar
155
  la operaci&oacute;n. Por ejemplo, el siguiente c&oacute;digo borrar&iacute;a
156
  la selecci&oacute;n de todas las capas activas con soporte de selecci&oacute;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>&nbsp;&nbsp;&nbsp; Para entender de forma m&aacute;s completa las operaciones
161
  que se pueden hacer con las capas se puede leer la documentaci&oacute;n a nivel
162
  de API de las interfaces del paquete mencionado anteriormente.<br>
163
  &nbsp;&nbsp;&nbsp; (TODO: Poner la descripci&oacute;n de las interfaces aqu&iacute;)<br>
164
  <br>
165
  <strong><font size="+1"><a name="2.1_VectorialData"></a>2.1 VectorialData</font></strong><br>
166
  <br>
167
  &nbsp;&nbsp;&nbsp; Menci&oacute;n a parte merece la interfaz VectorialData
168
  por su sofistificaci&oacute;n. Las capas vectoriales en FMap pueden tener una
169
  fuente de datos secuencial o aleatoria, en funci&oacute;n del driver utilizado,
170
  por lo que una selecci&oacute;n por rect&aacute;ngulo deber&iacute;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&eacute;todos: start, visit y stop. Estos m&eacute;todos
175
  est&aacute;n documentados en la API. Pongamos un sencillo ejemplo: para realizar
176
  una selecci&oacute;n por rect&aacute;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&aacute;ngulo mediante el
181
cual se va a realizar la selecci&oacute;n:</li>
182
</ul>
183
<pre>        public void setRect(Rectangle2D r) {<br>                rect = r;<br>        }<br></pre>
184
<ul>
185
  <li>En el m&eacute;todo start se comprueba que la capa es
186
seleccionable, porque es una condici&oacute;n necesaria para hacer una
187
selecci&oacute;n por rect&aacute;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&eacute;todo visit, que ser&aacute; invocado para cada
192
geometr&iacute;a de la capa, se comprueba si la geometr&iacute;a ha de
193
ser seleccionada. Si es seleccionada se guarda dicha informaci&oacute;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&oacute;n, en el m&eacute;todo
199
stop se seleccionan las geometr&iacute;as de la capa sobre la cual se
200
ha operado que se han comprobado que quedaban dentro del
201
rect&aacute;ngulo.</li>
202
</ul>
203
<pre>                ((Selectable) layer).setSelection(bitset);<br></pre>
204
<ul>
205
  <li>Por &uacute;ltimo queda ejecutar el algoritmo de selecci&oacute;n
206
sobre una capa. Nada m&aacute;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&aacute;ngulo
209
con el que seleccionaremos e invocar:</li>
210
</ul>
211
<pre>                ((VectorialData) layer).process(new SelectionByRectVisitor(r));<br><br></pre>
212
<p>&nbsp;&nbsp;&nbsp; Como se puede comprobar, en ning&uacute;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&aacute;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
  &nbsp;&nbsp;&nbsp;
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
  &nbsp;&nbsp;&nbsp; FMap pone a disposici&oacute;n del programador todo un mecanismo
227
  para que se pueda saber "lo que est&aacute; pasando por dentro del mapa". Cada
228
  elemento de FMap tiene un m&eacute;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&oacute;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&eacute;todo addViewPortListener ser&aacute; notificada
233
  de los eventos de cambio de extent y cambio de color de fondo en el ViewPort
234
  mediante invocaciones a los m&eacute;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&oacute;n
237
  de capas, de manera que cuando se a&ntilde;ade una capa o se modifica el extent
238
  se redibuja la imagen que muestra. Resulta que cuando se a&ntilde;ade la primera
239
  capa se modifica tambi&eacute;n el extent por lo que en el caso del control
240
  del ejemplo se refrescar&aacute; la imagen dos veces de manera innecesaria.
241
  La soluci&oacute;n son los AtomicEvent's.<br>
242
  <br>
243
  <strong><font size="+1">&nbsp;&nbsp;&nbsp; <a name="AtomicEvents"></a>4.1 AtomicEvent's</font></strong><br>
244
  <br>
245
  &nbsp;&nbsp;&nbsp; Para solucionar el problema anterior FMap incorpora dos m&eacute;todos
246
  beginAtomicEvent y endAtomicEvent. Estos m&eacute;todos no afectan a la gesti&oacute;n
247
  de eventos de los elementos individuales de FMap, afecta a la gesti&oacute;n
248
  de eventos desde FMap. Al igual que otros elementos del paquete FMap contiene
249
  un m&eacute;todo addAtomicEventListener con la funcionalidad an&aacute;loga
250
  a los addXXXListener comentados antes. Una vez registrado, el listener ser&aacute;
251
  notificado de cualquier evento que suceda por dentro de esa instancia de FMap
252
  (en las capas, viewport, leyenda, ...) con la &uacute;nica diferencia que podr&aacute;
253
  ser notificado de varios eventos al mismo tiempo. Si un trozo de c&oacute;digo
254
  se encuentra entre las instrucciones beginAtomicEvent y endAtomicEvent, los
255
  objetos individuales (ViewPort, Layers, ...) disparar&aacute;n eventos de la
256
  misma manera, pero la instancia de FMap acumular&aacute; los eventos desde que
257
  se ejecuta beginAtomicEvent hasta que se ejecuta endAtomicEvent, momento en
258
  el cual se disparar&aacute; 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&aacute; eventos, pero seguir&aacute; dispar&aacute;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&oacute;digo que usa beginAtomicEvent y endAtomicEvent tenemos
264
  el m&eacute;todo execute de la extensi&oacute;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
  &nbsp;&nbsp;&nbsp; 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
  &nbsp;&nbsp;&nbsp; Cada tipo de driver (vectorial, raster, ...) debe ser implementado
280
  mediante una interfaz distinta (VectorialFileDriver, WMSDriver, ...) y adem&aacute;s
281
  de implementar esta interfaz, se pueden implementar otras interfaces que a&ntilde;aden
282
  un valor a&ntilde;adido al driver.<br>
283
  <br>
284
  <strong><font size="+1"><a name="VectorialFileDriver"></a>5.1 VectorialFileDriver</font><br>
285
  <br>
286
  </strong>&nbsp;&nbsp;&nbsp; Para crear un driver de un fichero de
287
  tipo vectorial hay que implementar la interfaz VectorialFileDriver cuyos m&eacute;todos
288
  est&aacute;n documentados en el JavaDoc. Mediante esta interfaz el driver obtiene
289
  el acceso a los datos geogr&aacute;ficos de los ficheros vectoriales. Adem&aacute;s
290
  de esta interfaz hay que implementar una interfaz para el acceso a los datos
291
  alfanum&eacute;ricos. Dependiendo de c&oacute;mo est&eacute;n organizados estos
292
  datos se puede implementar com.iver.cit.gvsig.fmap.drivers.ExternalData, que
293
  es una interfaz &uacute;til para cuando los datos alfanum&eacute;ricos se encuentran
294
  en un fichero distinto al fichero de datos geogr&aacute;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&eacute;ricos se encuentra
297
  en el mismo soporte que los datos geogr&aacute;ficos (caso del DGN).<br>
298
  <br>
299
  &nbsp;&nbsp;&nbsp; Una vez implementadas estas dos interfaces, se pueden implementar
300
  otras para darle un valor a&ntilde;adido a los drivers:<br>
301
</p>
302
<ul>
303
  <li>BoundedShapes: Acelera el procesado de las geometr&iacute;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
  &nbsp;&nbsp;&nbsp; Con el paquete FMap se proporciona un control de interfaz
314
  de usuario junto con una serie de herramientas dise&ntilde;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&oacute;n del interfaz gr&aacute;fico
317
  de un mapa, lanzando el dibujado en un segundo plano, redibujando autom&aacute;ticamente
318
  cuando el FMap que tiene por debajo queda invalidado, ... Adem&aacute;s se proporcionan
319
  una serie de herramientas preparadas para su uso y extensibles de manera que
320
  la incorporaci&oacute;n de nuevas herramientas por parte del usuario sea un
321
  proceso trivial siempre que el comportamiento de la herramienta ya est&eacute;
322
  programado. En las secciones posteriores se ver&aacute; esto en m&aacute;s detalle.<br>
323
  <br>
324
  <strong><a name="MapControl"></a><font size="+1">6.1 MapControl</font></strong><br>
325
  <br>
326
  &nbsp;&nbsp;&nbsp; MapControl es un control de usuario que tiene
327
  como modelo una instancia de FMap a la que se puede acceder mediante el m&eacute;todo
328
  getMapContext(). A continuaci&oacute;n presentamos los pasos b&aacute;sicos
329
  para mostrar un Frame con un MapControl sin herramientas. En la secci&oacute;n
330
  siguiente se a&ntilde;adir&aacute;n herramientas con comportamientos ya existentes
331
  y c&oacute;mo a&ntilde;adir herramientas con un comportamiento no programado
332
  todav&iacute;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>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; LayerFactory.setDriversPath(</pre>
341
<pre>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; "C:\\eclipse3\\workspace\\Andami\\gvSIG\\extensiones\\com.iver.cit.gvsig\\drivers");</pre>
342
<ul>
343
  <li>Se a&ntilde;aden las capas al mapa que hay como modelo del
344
MapControl</li>
345
</ul>
346
<pre>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; FLayer l = LayerFactory.createLayer("Vias", "gvSIG shp driver",</pre>
347
<pre>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; new File("C:/Documents and Settings/fernando/Mis documentos/vias.shp"),</pre>
348
<pre>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ProjectionPool.get("EPSG:23030"));</pre>
349
<pre>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; newMapControl.getMapContext().getLayers().addLayer(l);</pre>
350
<ul>
351
  <li>Se a&ntilde;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
  &nbsp;&nbsp;&nbsp; Las herramientas que se proporcionan en FMap
357
  son en realidad comportamientos. Se define un comportamiento del rat&oacute;n
358
  tal como hacer un rect&aacute;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&aacute;ngulo
361
  cuando el usuario termina de dibujar el rect&aacute;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&aacute;ngulo (zoom in, selecci&oacute;n por rect&aacute;ngulo,
365
  ...) s&oacute;lo tienen que implementarse los listeners de los eventos. En el
366
  ejemplo anterior hemos visto como se a&ntilde;ad&iacute;a una herramienta al
367
  MapControl mediante el behavior RectangleMapBehavior el cual toma en su constructor
368
  la acci&oacute;n que se realiza con el rect&aacute;ngulo (acercar la imagen).<br>
369
  <br>
370
  <strong><a name="Creacion_de_una_herramienta_en_base_a_un"></a>6.2.1 Creaci&oacute;n
371
  de una herramienta en base a un behavior existente</strong><br><br>
372
  &nbsp;&nbsp;&nbsp; Para crear una herramienta con un comportamiento ya
373
  implementado, hay que implementar la interfaz que dicho behavior espera. Para
374
  averiguar qu&eacute; interfaz es &eacute;sta hay que leer la documentaci&oacute;n
375
  de cada behavior. En el paquete "com.iver.cit.gvsig.fmap.tools" hay m&uacute;ltiples
376
  ejemplos sobre como implementar las interfaces de los distintos behaviors.<br>
377
  &nbsp;&nbsp; <br>
378
  <strong><a name="Creacion_de_una_herramienta_con_un"></a>6.2.2 Creaci&oacute;n
379
  de una herramienta con un comportamiento no implementado</strong><br><br>
380
  &nbsp;&nbsp;&nbsp; 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&eacute;todos necesarios. Para m&aacute;s informaci&oacute;n sobre
393
c&oacute;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&oacute;n
398
  de herramientas</font></strong><br>
399
  <br>
400
  &nbsp;&nbsp;&nbsp; El modelo de herramientas sigue un patr&oacute;n
401
  composite. Esto quiere decir que existe una herramienta especial que consiste
402
  realmente en un conjunto de herramientas. Teor&iacute;a a parte, esto quiere
403
  decir que podemos tener varias herramientas seleccionadas simult&aacute;neamente
404
  como una s&oacute;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&oacute;n
406
  derecho del rat&oacute;n y a la vez que tenemos una maptool que muestra la coordenada
407
  de la posici&oacute;n actual del rat&oacute;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>&nbsp;&nbsp;&nbsp; Que a&ntilde;ade la herramienta compuesta por las 3 herramientas
412
  simples deseadas. Tambi&eacute;n existe un m&eacute;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>