001: /*
002: * The Unified Mapping Platform (JUMP) is an extensible, interactive GUI
003: * for visualizing and manipulating spatial features with geometry and attributes.
004: *
005: * Copyright (C) 2003 Vivid Solutions
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * as published by the Free Software Foundation; either version 2
010: * of the License, or (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
020: *
021: * For more information, contact:
022: *
023: * Vivid Solutions
024: * Suite #1A
025: * 2328 Government Street
026: * Victoria BC V8T 5G5
027: * Canada
028: *
029: * (250)385-6040
030: * www.vividsolutions.com
031: */
032:
033: package com.vividsolutions.jump.workbench.ui;
034:
035: import java.awt.BorderLayout;
036: import java.awt.Dimension;
037: import java.awt.FlowLayout;
038: import java.awt.Frame;
039: import java.awt.GridBagConstraints;
040: import java.awt.GridBagLayout;
041: import java.awt.Insets;
042: import java.awt.event.ActionEvent;
043: import java.awt.event.ActionListener;
044: import java.awt.event.ComponentEvent;
045: import java.awt.event.ItemEvent;
046: import java.util.Iterator;
047: import java.util.WeakHashMap;
048:
049: import javax.swing.BorderFactory;
050: import javax.swing.JComboBox;
051: import javax.swing.JDialog;
052: import javax.swing.JLabel;
053: import javax.swing.JOptionPane;
054: import javax.swing.JPanel;
055:
056: import com.vividsolutions.jump.workbench.driver.AbstractDriver;
057: import com.vividsolutions.jump.workbench.model.Layer;
058:
059: /**
060: * Base Driver Dialog.
061: */
062: //<<TODO:DESIGN>> Strange that every driver-panel must supply its own OK and Cancel
063: //buttons. But I remember there was a reason for this. Revisit this design. [Jon Aquino]
064: public class DriverDialog extends JDialog implements ActionListener {
065: JPanel centrePanel = new JPanel();
066: BorderLayout borderLayout1 = new BorderLayout();
067: BorderLayout borderLayout2 = new BorderLayout();
068: private java.util.List drivers;
069: private AbstractDriverPanel dummyDriverPanel = new AbstractDriverPanel() {
070: public boolean wasOKPressed() {
071: return false;
072: }
073:
074: public String getValidationError() {
075: return null;
076: }
077:
078: public void addActionListener(ActionListener l) {
079: }
080:
081: public void removeActionListener(ActionListener l) {
082: }
083: };
084:
085: protected AbstractDriverPanel currentDriverPanel = dummyDriverPanel;
086: JPanel northPanel = new JPanel();
087: JPanel innerNorthPanel = new JPanel();
088: JLabel driverLabel = new JLabel();
089: JComboBox driverComboBox = new JComboBox();
090: FlowLayout flowLayout1 = new FlowLayout();
091: GridBagLayout gridBagLayout1 = new GridBagLayout();
092: private boolean closeInitiatedByPanelButton;
093: private boolean okPressed;
094: private WeakHashMap layerToDriverPanelCacheMap = new WeakHashMap();
095: private Layer layer;
096:
097: public DriverDialog(Frame frame, String title, boolean modal) {
098: super (frame, title, modal);
099:
100: try {
101: jbInit();
102: pack();
103: } catch (Exception ex) {
104: ex.printStackTrace();
105: }
106: }
107:
108: public DriverDialog() {
109: this (null, "", false);
110: }
111:
112: public void initialize(java.util.List drivers) {
113: /* Moved this code into show() to ensure the comboBox is updated
114: * if the list of drivers is updated during run-time
115: */
116: /*
117: for (Iterator i = drivers.iterator(); i.hasNext();) {
118: AbstractDriver driver = (AbstractDriver) i.next();
119: driverComboBox.addItem(driver);
120: centrePanel.setPreferredSize(merge(centrePanel.getPreferredSize(),
121: driver.getPanel().getPreferredSize()));
122: }
123: */
124: this .drivers = drivers;
125: }
126:
127: public void show() {
128: driverComboBox.removeAllItems();
129: for (Iterator i = drivers.iterator(); i.hasNext();) {
130: AbstractDriver driver = (AbstractDriver) i.next();
131: driverComboBox.addItem(driver);
132: centrePanel.setPreferredSize(merge(centrePanel
133: .getPreferredSize(), driver.getPanel()
134: .getPreferredSize()));
135: }
136: pack();
137: super .show();
138: }
139:
140: private Dimension merge(Dimension envelopeA, Dimension envelopeB) {
141: return new Dimension((int) Math.max(envelopeA.getWidth(),
142: envelopeB.getWidth()), (int) Math.max(envelopeA
143: .getHeight(), envelopeB.getHeight()));
144: }
145:
146: void jbInit() throws Exception {
147: centrePanel.setLayout(borderLayout1);
148: this .getContentPane().setLayout(borderLayout2);
149: innerNorthPanel.setLayout(flowLayout1);
150: driverLabel.setText("Format:");
151: driverComboBox
152: .addItemListener(new java.awt.event.ItemListener() {
153: public void itemStateChanged(ItemEvent e) {
154: driverComboBox_itemStateChanged(e);
155: }
156: });
157: northPanel.setLayout(gridBagLayout1);
158: northPanel.setBorder(BorderFactory.createEtchedBorder());
159: this
160: .addComponentListener(new java.awt.event.ComponentAdapter() {
161: public void componentShown(ComponentEvent e) {
162: this _componentShown(e);
163: }
164:
165: public void componentHidden(ComponentEvent e) {
166: this _componentHidden(e);
167: }
168: });
169: getContentPane().add(centrePanel, BorderLayout.CENTER);
170: this .getContentPane().add(northPanel, BorderLayout.NORTH);
171: northPanel.add(innerNorthPanel, new GridBagConstraints(0, 0, 2,
172: 1, 1.0, 0.0, GridBagConstraints.WEST,
173: GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
174: innerNorthPanel.add(driverLabel, null);
175: innerNorthPanel.add(driverComboBox, null);
176: centrePanel.add(currentDriverPanel, BorderLayout.CENTER);
177: }
178:
179: public AbstractDriver getCurrentDriver() {
180: return (AbstractDriver) driverComboBox.getSelectedItem();
181: }
182:
183: public boolean wasOKPressed() {
184: if (!closeInitiatedByPanelButton) {
185: //The dialog's close button was pressed instead. [Jon Aquino]
186: return false;
187: }
188:
189: //Can't simply return currentDriverPanel.wasOKPressed() because the current
190: //driver panel is reset in #this_componentHidden(Component)
191: return okPressed;
192: }
193:
194: void driverComboBox_itemStateChanged(ItemEvent e) {
195: if (e.getStateChange() != ItemEvent.SELECTED) {
196: return;
197: }
198:
199: updateCentrePanel(getCurrentDriver().getPanel());
200: }
201:
202: private void updateCentrePanel(AbstractDriverPanel newDriverPanel) {
203: currentDriverPanel.removeActionListener(this );
204: centrePanel.remove(currentDriverPanel);
205: currentDriverPanel = newDriverPanel;
206: centrePanel.add(currentDriverPanel, BorderLayout.CENTER);
207: currentDriverPanel.addActionListener(this );
208: validateTree();
209: repaint();
210: }
211:
212: public void actionPerformed(ActionEvent e) {
213: okPressed = currentDriverPanel.wasOKPressed();
214:
215: if (!currentDriverPanel.wasOKPressed()
216: || currentDriverPanel.isInputValid()) {
217: closeInitiatedByPanelButton = true;
218: setVisible(false);
219:
220: if (currentDriverPanel.wasOKPressed()) {
221: updateDriverPanelCache();
222: }
223:
224: return;
225: }
226:
227: reportValidationError(currentDriverPanel.getValidationError());
228: }
229:
230: private void reportValidationError(String errorMessage) {
231: JOptionPane.showMessageDialog(this , errorMessage, "JUMP",
232: JOptionPane.ERROR_MESSAGE);
233: }
234:
235: void this _componentShown(ComponentEvent e) {
236: closeInitiatedByPanelButton = false;
237:
238: AbstractDriver cachedDriver = (AbstractDriver) driverPanelCache(
239: layer).get(DriverPanelCache.DRIVER_CACHE_KEY);
240:
241: if (cachedDriver != null) {
242: driverComboBox.setSelectedItem(cachedDriver);
243: }
244:
245: applyDriverPanelCache();
246: updateCentrePanel(getCurrentDriver().getPanel());
247: }
248:
249: void this _componentHidden(ComponentEvent e) {
250: //Disconnect the currentDriverPanel, because other instances of DriverDialog
251: //may use it [Jon Aquino]
252: updateCentrePanel(dummyDriverPanel);
253: }
254:
255: private void applyDriverPanelCache() {
256: for (int i = 0; i < driverComboBox.getItemCount(); i++) {
257: AbstractDriver driver = (AbstractDriver) driverComboBox
258: .getItemAt(i);
259: driver.getPanel().setCache(driverPanelCache(layer));
260: }
261: }
262:
263: private void updateDriverPanelCache() {
264: driverPanelCache(layer).addAll(currentDriverPanel.getCache());
265: driverPanelCache(layer).put(DriverPanelCache.DRIVER_CACHE_KEY,
266: driverComboBox.getSelectedItem());
267: }
268:
269: private DriverPanelCache driverPanelCache(Layer layer) {
270: //e.g. open dialog will have no layer set. [Jon Aquino]
271: if (layer == null) {
272: return new DriverPanelCache();
273: }
274:
275: DriverPanelCache cache = (DriverPanelCache) layerToDriverPanelCacheMap
276: .get(layer);
277:
278: if (cache == null) {
279: cache = new DriverPanelCache();
280: cache.put(DriverPanelCache.DRIVER_CACHE_KEY, driverComboBox
281: .getSelectedItem());
282: layerToDriverPanelCacheMap.put(layer, cache);
283: }
284:
285: return cache;
286: }
287:
288: /**
289: * This DriverDialog will attempt to retrieve the last values used for the
290: * given Layer.
291: * @see DriverPanelCache
292: */
293: public void setLayer(Layer layer) {
294: this.layer = layer;
295: }
296: }
|