001: /*
002: * This file is part of the GeOxygene project source files.
003: *
004: * GeOxygene aims at providing an open framework which implements OGC/ISO specifications for
005: * the development and deployment of geographic (GIS) applications. It is a open source
006: * contribution of the COGIT laboratory at the Institut Géographique National (the French
007: * National Mapping Agency).
008: *
009: * See: http://oxygene-project.sourceforge.net
010: *
011: * Copyright (C) 2005 Institut Géographique National
012: *
013: * This library is free software; you can redistribute it and/or modify it under the terms
014: * of the GNU Lesser General Public License as published by the Free Software Foundation;
015: * either version 2.1 of the License, or any later version.
016: *
017: * This library is distributed in the hope that it will be useful, but WITHOUT ANY
018: * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
019: * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
020: *
021: * You should have received a copy of the GNU Lesser General Public License along with
022: * this library (see file LICENSE if present); if not, write to the Free Software
023: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
024: *
025: */
026:
027: package fr.ign.cogit.geoxygene.util.viewer;
028:
029: import java.awt.BorderLayout;
030: import java.awt.Color;
031: import java.awt.Dimension;
032: import java.awt.event.MouseEvent;
033: import java.awt.event.MouseListener;
034: import java.awt.event.MouseMotionListener;
035: import java.io.File;
036: import java.io.FileInputStream;
037: import java.net.URL;
038: import java.util.Observable;
039: import java.util.Observer;
040: import java.util.Vector;
041:
042: import javax.swing.Box;
043: import javax.swing.BoxLayout;
044: import javax.swing.JFrame;
045: import javax.swing.JPanel;
046: import javax.swing.JScrollPane;
047: import javax.swing.JSplitPane;
048:
049: import uk.ac.leeds.ccg.geotools.DataSource;
050: import uk.ac.leeds.ccg.geotools.GeoData;
051: import uk.ac.leeds.ccg.geotools.GeoRectangle;
052: import uk.ac.leeds.ccg.geotools.HighlightManager;
053: import uk.ac.leeds.ccg.geotools.MonoShader;
054: import uk.ac.leeds.ccg.geotools.SelectionChangedEvent;
055: import uk.ac.leeds.ccg.geotools.SelectionChangedListener;
056: import uk.ac.leeds.ccg.geotools.SelectionManager;
057: import uk.ac.leeds.ccg.geotools.ShadeStyle;
058: import uk.ac.leeds.ccg.geotools.ShapefileReader;
059: import uk.ac.leeds.ccg.geotools.Theme;
060: import uk.ac.leeds.ccg.geotools.Viewer;
061: import uk.ac.leeds.ccg.raster.ImageLayer;
062: import fr.ign.cogit.geoxygene.datatools.Geodatabase;
063: import fr.ign.cogit.geoxygene.feature.FT_Feature;
064: import fr.ign.cogit.geoxygene.feature.FT_FeatureCollection;
065:
066: /**
067: * This class instanciates the GUI of the (Geo)Object Viewer.
068: *
069: * @author Thierry Badard & Arnaud Braun
070: * @version 1.0
071: *
072: */
073:
074: class ObjectViewerInterface extends JFrame implements Observer {
075:
076: /** This constant defines if themes can be selected when they are loaded or added (default = true), or not (false). */
077: private static final boolean THEME_SELECTION = true;
078:
079: /** This constant defines if themes are displayed when they are loaded or added (default = true), or not (false). */
080: private static final boolean THEME_VISIBILITY = true;
081:
082: /** It is a reference to the Geotools viewer. */
083: protected Viewer view = new Viewer();
084:
085: /** It is a reference to the status bar of the ObjectViewer's GUI. */
086: private ObjectViewerStatusBar statusbar;
087:
088: /** It is a reference to the tool bar of the GUI of the ObjectViewer. */
089: private ObjectViewerToolBar jtb;
090:
091: /** It is a reference to the menu bar of the GUI of the ObjectViewer. */
092: private ObjectViewerMenuBar jmb;
093:
094: /** List of themes properties */
095: //private Vector themesList;
096: /** List of properties of themes. */
097: private Vector themesPropertiesList;
098:
099: /** List of actives themes (button is pressed) */
100: private Vector activeThemes;
101:
102: /** JPanel for themes. */
103: protected JPanel panel_themes = new JPanel();
104:
105: /** JScrollPane. */
106: private JScrollPane scrolling_panel_themes;
107:
108: /** Selected ID objects */
109: private Vector selectedObjects;
110:
111: protected ObjectViewerInterface(String titre, Geodatabase db) {
112: super (titre);
113: InterfaceInit(db);
114: }
115:
116: public void update(Observable o, Object rect) {
117:
118: }
119:
120: private void InterfaceInit(Geodatabase db) {
121:
122: // Init the lists
123: themesPropertiesList = new Vector();
124: activeThemes = new Vector();
125:
126: // Init GUI
127: this .getContentPane().setLayout(new BorderLayout());
128: panel_themes.setLayout(new BoxLayout(panel_themes,
129: BoxLayout.Y_AXIS));
130: scrolling_panel_themes = new JScrollPane(panel_themes);
131: scrolling_panel_themes.setMinimumSize(new Dimension(180, 200));
132: JPanel view_panel = new JPanel();
133: view_panel.setLayout(new BorderLayout());
134: view.setSize(300, 200);
135: view.setBackground(Color.white);
136: view_panel.add(view);
137: JSplitPane jsp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
138: true, scrolling_panel_themes, view_panel);
139: jsp.setDividerLocation(0.4);
140: this .getContentPane().add(jsp);
141:
142: // Definition of the ToolBar.
143: jtb = new ObjectViewerToolBar(this , db);
144: this .getContentPane().add(jtb, BorderLayout.NORTH);
145:
146: // Definition of the MenuBar.
147: jmb = new ObjectViewerMenuBar(this , db);
148: this .setJMenuBar(jmb);
149:
150: // Definition of the StatusBar
151: statusbar = new ObjectViewerStatusBar(this );
152: this .getContentPane().add(statusbar, BorderLayout.SOUTH);
153:
154: // Mouse listener for view
155: view.addMouseMotionListener(new MouseMotionListener() {
156: public void mouseDragged(MouseEvent e) {
157:
158: }
159:
160: public void mouseMoved(MouseEvent e) {
161: double x = view.getMapGeoPoint().getX();
162: double y = view.getMapGeoPoint().getY();
163: statusbar.setText("X=" + (int) x + " Y=" + (int) y);
164: }
165: });
166: }
167:
168: /** Add a new Theme with the given name to the viewer, and the kind of DataSource. */
169: private void addTheme(Theme t, String sourcetype, DataSource source) {
170:
171: // init theme properties
172: ObjectViewerThemeProperties objectViewerThemeProperties = new ObjectViewerThemeProperties(
173: this , t, sourcetype, source, THEME_SELECTION,
174: THEME_VISIBILITY);
175:
176: // fill vectors of themes and theme properties
177: themesPropertiesList.add(objectViewerThemeProperties);
178: activeThemes.add(t);
179:
180: // Init
181: initTheme(t, objectViewerThemeProperties);
182:
183: // Init "theme button"
184: setThemeButton(themesPropertiesList.size() - 1,
185: objectViewerThemeProperties);
186:
187: // Add theme to geotools viewer
188: view.addTheme(t);
189: view.setThemeIsVisible(t, THEME_VISIBILITY, true);
190: panel_themes.revalidate();
191: panel_themes.repaint();
192:
193: // Gestion de l'ordre d'affichage
194: for (int i = 0; i < themesPropertiesList.size(); i++) {
195: Theme th = ((ObjectViewerThemeProperties) themesPropertiesList
196: .get(i)).getObjectViewerTheme();
197: view.setThemeWaighting(th, -i);
198: }
199: }
200:
201: /** Refresh theme at the given index. */
202: private void setTheme(Theme t, String sourcetype,
203: DataSource source, int index, boolean active,
204: boolean visible) {
205:
206: // init theme properties
207: ObjectViewerThemeProperties objectViewerThemeProperties = new ObjectViewerThemeProperties(
208: this , t, sourcetype, source, active, visible);
209:
210: // fill vectors of themes and theme properties
211: themesPropertiesList.set(index, objectViewerThemeProperties);
212:
213: // Init
214: initTheme(t, objectViewerThemeProperties);
215:
216: // Remove "theme button" and init new one
217: panel_themes.remove(index);
218: setThemeButton(index, objectViewerThemeProperties);
219:
220: // Add theme to geotools viewer
221: view.addTheme(t);
222: view.setThemeIsVisible(t, visible, true);
223: panel_themes.revalidate();
224: panel_themes.repaint();
225: }
226:
227: private void initTheme(Theme t,
228: ObjectViewerThemeProperties objectViewerThemeProperties) {
229:
230: // Add a Shader
231: t.setShader(new MonoShader(objectViewerThemeProperties
232: .getFillInThemeColor()));
233:
234: // Add a HighlightManager
235: t.setHighlightManager(new HighlightManager());
236: ShadeStyle themeHighlightShadeStyle = new ShadeStyle();
237: themeHighlightShadeStyle
238: .setFillColor(objectViewerThemeProperties
239: .getFillInHighlightColor());
240: themeHighlightShadeStyle
241: .setLineColor(objectViewerThemeProperties
242: .getOutlineHighlightColor());
243: t.setHighlightStyle(themeHighlightShadeStyle);
244: objectViewerThemeProperties.setThemeHighlightManager(t
245: .getHighlightManager());
246:
247: // Add a SelectionManager
248: SelectionManager themeSelectMgr = new SelectionManager();
249: ShadeStyle themeSelectShadeStyle = new ShadeStyle();
250: themeSelectShadeStyle.setFillColor(objectViewerThemeProperties
251: .getFillInSelectionColor());
252: themeSelectShadeStyle.setLineColor(objectViewerThemeProperties
253: .getOutlineSelectionColor());
254: t.setSelectionStyle(themeSelectShadeStyle);
255:
256: themeSelectMgr
257: .addSelectionChangedListener(new SelectionChangedListener() {
258: public void selectionChanged(
259: SelectionChangedEvent hce) {
260: System.out
261: .println("Selection sur un theme ...");
262: selectedObjects = new Vector();
263: for (int i = 0; i < themesPropertiesList.size(); i++) {
264: Theme activetheme = ((ObjectViewerThemeProperties) (themesPropertiesList
265: .get(i))).getObjectViewerTheme();
266: if (isActive(activetheme)) {
267: System.out.println("Themes: "
268: + activetheme.getName());
269: GeoData activethemeGeoData = activetheme
270: .getGeoData();
271:
272: int[] selectedIdObjects = activetheme
273: .getSelectionManager()
274: .getSelection();
275: Vector selectedIdObjectsNotNullVector = new Vector();
276: int nbselectedIdObjects = selectedIdObjects.length;
277: for (int j = 0; j < nbselectedIdObjects; j++) {
278: if (selectedIdObjects[j] != -1) {
279: System.out
280: .println(" ObjectID: "
281: + selectedIdObjects[j]);
282: selectedIdObjectsNotNullVector
283: .add(new Integer(
284: selectedIdObjects[j]));
285: }
286: }
287: int[] selectedIdObjectsNotNullArray = new int[selectedIdObjectsNotNullVector
288: .size()];
289: for (int j = 0; j < selectedIdObjectsNotNullArray.length; j++)
290: selectedIdObjectsNotNullArray[j] = ((Integer) selectedIdObjectsNotNullVector
291: .get(j)).intValue();
292: selectedObjects
293: .add(new ObjectsIDAndSource(
294: selectedIdObjectsNotNullArray,
295: ((ObjectViewerThemeProperties) themesPropertiesList
296: .get(i))
297: .getDataSource()));
298: }
299: }
300: }
301: });
302: t.setSelectionManager(themeSelectMgr);
303: objectViewerThemeProperties.setThemeSelectionManager(t
304: .getSelectionManager());
305:
306: }
307:
308: /** Display objects stored in the FeatureCollection, with a given name. */
309: protected void addAShapefileTheme(URL url) {
310: ShapefileReader sfr = new ShapefileReader(url);
311: final Theme t = sfr.getTheme();
312: String theme_name = t.getName();
313: String shapefile_name = theme_name.substring(theme_name
314: .lastIndexOf("/") + 1);
315: t.setName(shapefile_name);
316: this .addTheme(t, Utils.SHAPEFILE, sfr);
317: }
318:
319: /** Display objects stored in the FeatureCollection, in a Theme with the given name. */
320: protected void addAFeatureCollectionTheme(
321: FT_FeatureCollection fColl, String themeName) {
322: GeOxygeneReader geOxyRead = new GeOxygeneReader(fColl);
323: final Theme t = geOxyRead.getTheme();
324: t.setName(themeName);
325: this .addTheme(t, Utils.GEOXYGENE, geOxyRead);
326: }
327:
328: /** Refresh the FeatureCollection displayed in the viewer with this given name. */
329: protected void refreshAFeatureCollectionTheme(
330: FT_FeatureCollection fColl, String themeName) {
331: // Get the GeOxygeneReader of this collection
332: if (themesPropertiesList.size() > 0) {
333: for (int i = 0; i < themesPropertiesList.size(); i++) {
334: ObjectViewerThemeProperties oldThemeProp = (ObjectViewerThemeProperties) themesPropertiesList
335: .get(i);
336: Theme oldTheme = oldThemeProp.getObjectViewerTheme();
337: // theme exists !!
338: if (oldThemeProp.getDataSourceType().equals(
339: Utils.GEOXYGENE)
340: && oldTheme.getName().equals(themeName)) {
341: GeOxygeneReader oldGeOxyRead = (GeOxygeneReader) oldThemeProp
342: .getDataSource();
343: int index = themesPropertiesList
344: .indexOf(oldThemeProp);
345: view.removeStaticTheme(oldTheme);
346: GeOxygeneReader newGeOxyRead = new GeOxygeneReader(
347: fColl);
348: final Theme newTheme = newGeOxyRead.getTheme();
349: newTheme.setName(themeName);
350: this .setTheme(newTheme, Utils.GEOXYGENE,
351: newGeOxyRead, index, oldThemeProp
352: .isActive(), oldThemeProp
353: .isVisible());
354: activeThemes.remove(oldTheme);
355: activeThemes.add(newTheme);
356: return;
357: }
358: }
359: }
360: // Theme doesn't exist yet
361: System.out
362: .println(" ## REFRESH : the Theme doesn't exist yet ! ");
363: return;
364: }
365:
366: /** Refresh the FeatureCollection displayed in the viewer with this given name with this feature.
367: * The feature must already belong to the collection. */
368: // ATTENTION apres un refresh, le highlight manager continue a etre active meme si le theme est deselectionne ...
369: public void refreshAFeatureCollectionTheme(FT_Feature feature,
370: String themeName) {
371: // Get the GeOxygeneReader of this collection
372: if (themesPropertiesList.size() > 0) {
373: for (int i = 0; i < themesPropertiesList.size(); i++) {
374: ObjectViewerThemeProperties themeProp = (ObjectViewerThemeProperties) themesPropertiesList
375: .get(i);
376: Theme theme = themeProp.getObjectViewerTheme();
377: // theme exists !!
378: if (themeProp.getDataSourceType().equals(
379: Utils.GEOXYGENE)
380: && theme.getName().equals(themeName)) {
381: GeOxygeneReader geOxyRead = (GeOxygeneReader) themeProp
382: .getDataSource();
383: FT_FeatureCollection fColl = geOxyRead
384: .getFeatureCollection();
385: if (!fColl.getElements().contains(feature)) {
386: System.out
387: .println(" ## REFRESH : the Feature Collection does not contain the Feature !");
388: return;
389: }
390: geOxyRead.refreshFeature(feature);
391: return;
392: }
393: }
394: }
395: // Theme doesn't exist yet
396: System.out
397: .println(" ## REFRESH : the Theme doesn't exist yet ! ");
398: return;
399:
400: }
401:
402: /** Display a JPEG image */
403: protected void addAnImageTheme(String fileName, int x, int y,
404: int width, int height) {
405: File fichier = new File(fileName);
406: System.out.println(fichier.getAbsolutePath());
407: try {
408: FileInputStream fis = new FileInputStream(fichier);
409: ImageLayer imageLayer = new ImageLayer(fis,
410: new GeoRectangle(x, y, width, height));
411: Theme t = new Theme(imageLayer);
412: String theme_name = fileName.substring(fileName
413: .lastIndexOf("/") + 1, fileName.lastIndexOf("."));
414: t.setName(theme_name);
415: this .addTheme(t, Utils.IMAGE, new ImageReader());
416: } catch (Exception e) {
417: e.printStackTrace();
418: }
419: }
420:
421: protected Vector getSelectedObjects() {
422: return selectedObjects;
423: }
424:
425: protected Vector getActiveThemes() {
426: return activeThemes;
427: }
428:
429: private boolean isActive(Theme t) {
430: if (activeThemes.contains(t))
431: return true;
432: else
433: return false;
434: }
435:
436: private void setThemeButton(int index,
437: ObjectViewerThemeProperties prop) {
438: // Init "theme button"
439: ObjectViewerThemeButton theme_chkbox = new ObjectViewerThemeButton(
440: this , prop);
441:
442: // Add a popup for the "theme button"
443: ObjectViewerThemePopupMenu ThemePopup = new ObjectViewerThemePopupMenu(
444: this , theme_chkbox, prop);
445:
446: // Add a listener for popups.
447: MouseListener popupListener = new PopupListener(ThemePopup);
448: theme_chkbox.addMouseListener(popupListener);
449:
450: // Get "theme button" and remove it
451: panel_themes.add(theme_chkbox, index);
452: panel_themes.add(Box.createVerticalStrut(2));
453: theme_chkbox.setPreferredSize(new Dimension(177, 30));
454: theme_chkbox.setMaximumSize(new Dimension(177, 30));
455:
456: }
457:
458: /** Move up a theme */
459: protected void upTheme(Theme t) {
460: for (int k = 1; k < themesPropertiesList.size(); k++) {
461: ObjectViewerThemeProperties thPr1 = (ObjectViewerThemeProperties) themesPropertiesList
462: .get(k);
463: Theme t1 = thPr1.getObjectViewerTheme();
464: if (t1.equals(t)) {
465: ObjectViewerThemeProperties thPr0 = (ObjectViewerThemeProperties) themesPropertiesList
466: .get(k - 1);
467: Theme t0 = thPr0.getObjectViewerTheme();
468: view.swapThemes(t0, t1);
469: themesPropertiesList.set(k - 1, thPr1);
470: themesPropertiesList.set(k, thPr0);
471: panel_themes.remove(k - 1);
472: setThemeButton(k - 1, thPr1);
473: panel_themes.remove(k);
474: setThemeButton(k, thPr0);
475: panel_themes.revalidate();
476: panel_themes.repaint();
477: break;
478: }
479: }
480: }
481:
482: /** Moves down a theme */
483: protected void downTheme(Theme t) {
484: for (int k = 0; k < themesPropertiesList.size() - 1; k++) {
485: ObjectViewerThemeProperties thPr1 = (ObjectViewerThemeProperties) themesPropertiesList
486: .get(k);
487: Theme t1 = thPr1.getObjectViewerTheme();
488: if (t1.equals(t)) {
489: ObjectViewerThemeProperties thPr0 = (ObjectViewerThemeProperties) themesPropertiesList
490: .get(k + 1);
491: Theme t0 = thPr0.getObjectViewerTheme();
492: view.swapThemes(t0, t1);
493: themesPropertiesList.set(k + 1, thPr1);
494: themesPropertiesList.set(k, thPr0);
495: panel_themes.remove(k + 1);
496: setThemeButton(k + 1, thPr1);
497: panel_themes.remove(k);
498: setThemeButton(k, thPr0);
499: panel_themes.revalidate();
500: panel_themes.repaint();
501: break;
502: }
503: }
504: }
505:
506: protected void removeTheme(ObjectViewerThemeProperties prop) {
507: int index = themesPropertiesList.indexOf(prop);
508: Theme t = prop.getObjectViewerTheme();
509: view.setThemeIsVisible(t, false, true);
510: panel_themes.remove(index);
511: panel_themes.revalidate();
512: panel_themes.repaint();
513: view.removeStaticTheme(t);
514: activeThemes.remove(t);
515: themesPropertiesList.remove(index);
516: }
517:
518: /** Structure for IDs and DataSource */
519: protected class ObjectsIDAndSource {
520: public int[] objectsID;
521: public DataSource source;
522:
523: public ObjectsIDAndSource(int[] ids, DataSource s) {
524: objectsID = ids;
525: source = s;
526: }
527:
528: public int[] getObjectsID() {
529: return objectsID;
530: }
531:
532: public DataSource getDataSource() {
533: return source;
534: }
535: }
536:
537: }
|