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.plugin.wms;
034:
035: import java.awt.Component;
036: import java.awt.GridBagConstraints;
037: import java.awt.GridBagLayout;
038: import java.awt.Insets;
039: import java.awt.event.ActionEvent;
040: import java.awt.event.ActionListener;
041: import java.util.ArrayList;
042: import java.util.Collection;
043: import java.util.Enumeration;
044: import java.util.Iterator;
045: import java.util.List;
046:
047: import javax.swing.DefaultListCellRenderer;
048: import javax.swing.DefaultListModel;
049: import javax.swing.ImageIcon;
050: import javax.swing.JCheckBox;
051: import javax.swing.JLabel;
052: import javax.swing.JList;
053: import javax.swing.JPanel;
054: import javax.swing.JTree;
055: import javax.swing.UIManager;
056: import javax.swing.event.ListDataEvent;
057: import javax.swing.event.ListDataListener;
058: import javax.swing.tree.DefaultTreeCellRenderer;
059:
060: import com.vividsolutions.jts.util.Assert;
061: import com.vividsolutions.jump.I18N;
062: import com.vividsolutions.jump.util.StringUtil;
063: import com.vividsolutions.jump.workbench.ui.GUIUtil;
064: import com.vividsolutions.jump.workbench.ui.InputChangedFirer;
065: import com.vividsolutions.jump.workbench.ui.InputChangedListener;
066: import com.vividsolutions.jump.workbench.ui.addremove.AddRemoveListModel;
067: import com.vividsolutions.jump.workbench.ui.addremove.AddRemovePanel;
068: import com.vividsolutions.jump.workbench.ui.addremove.DefaultAddRemoveList;
069: import com.vividsolutions.jump.workbench.ui.addremove.TreeAddRemoveList;
070: import com.vividsolutions.jump.workbench.ui.addremove.TreeAddRemoveListModel;
071: import com.vividsolutions.jump.workbench.ui.images.IconLoader;
072: import com.vividsolutions.wms.MapLayer;
073: import com.vividsolutions.wms.WMService;
074:
075: public class MapLayerPanel extends JPanel {
076: public final static ImageIcon ICON = GUIUtil.resize(IconLoader
077: .icon("country.gif"), 13);
078: private InputChangedFirer inputChangedFirer = new InputChangedFirer();
079: private GridBagLayout gridBagLayout1 = new GridBagLayout();
080: private AddRemovePanel addRemovePanel = new AddRemovePanel(true);
081: private JCheckBox checkBox = new JCheckBox(I18N
082: .get("ui.plugin.wms.MapLayerPanel.sort"), true);
083:
084: public MapLayerPanel() {
085: try {
086: jbInit();
087: } catch (Exception e) {
088: e.printStackTrace();
089: }
090:
091: initAddRemovePanel();
092: }
093:
094: public List getChosenMapLayers() {
095: ArrayList mapLayers = new ArrayList();
096:
097: for (Iterator i = addRemovePanel.getRightItems().iterator(); i
098: .hasNext();) {
099: MapLayerTreeModel.LayerNode node = (MapLayerTreeModel.LayerNode) i
100: .next();
101: Assert.isTrue(node.getLayer().getName() != null);
102: mapLayers.add(node.getLayer());
103: }
104:
105: return mapLayers;
106: }
107:
108: private void setRendererText(JLabel renderer, MapLayer layer) {
109: renderer.setText(layer.getTitle()
110: + " ["
111: + StringUtil.toCommaDelimitedString(layer
112: .getFullSRSList()) + "]");
113: }
114:
115: void jbInit() throws Exception {
116: addRemovePanel.setRightText(I18N
117: .get("ui.plugin.wms.MapLayerPanel.chosen-layers"));
118: this .setLayout(gridBagLayout1);
119: this .add(addRemovePanel, new GridBagConstraints(0, 2, 1, 1,
120: 1.0, 1.0, GridBagConstraints.CENTER,
121: GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
122: }
123:
124: public void add(InputChangedListener listener) {
125: inputChangedFirer.add(listener);
126: }
127:
128: public void remove(InputChangedListener listener) {
129: inputChangedFirer.remove(listener);
130: }
131:
132: private void addIfOnList(MapLayer layer, AddRemoveListModel model,
133: Collection names) {
134: if (names.contains(layer.getName())) {
135: //Just leave the second argument as null, because it's only needed for sorting the left list, and
136: //here we're dealing with the right list. [Jon Aquino]
137: model.add(new MapLayerTreeModel.LayerNode(layer, null));
138: }
139:
140: for (Iterator i = layer.getSubLayerList().iterator(); i
141: .hasNext();) {
142: MapLayer child = (MapLayer) i.next();
143: addIfOnList(child, model, names);
144: }
145: }
146:
147: public List commonSRSList() {
148: List mapLayers = getChosenMapLayers();
149:
150: if (mapLayers.isEmpty()) {
151: return new ArrayList();
152: }
153:
154: ArrayList commonSRSList = new ArrayList(((MapLayer) mapLayers
155: .get(0)).getFullSRSList());
156:
157: for (Iterator i = mapLayers.iterator(); i.hasNext();) {
158: MapLayer layer = (MapLayer) i.next();
159: commonSRSList.retainAll(layer.getFullSRSList());
160: }
161:
162: return commonSRSList;
163: }
164:
165: private void initAddRemovePanel() {
166: TreeAddRemoveList leftList = new TreeAddRemoveList() {
167: public List getSelectedItems() {
168: List selectedItems = new ArrayList(super
169: .getSelectedItems());
170:
171: for (Iterator i = selectedItems.iterator(); i.hasNext();) {
172: MapLayerTreeModel.LayerNode node = (MapLayerTreeModel.LayerNode) i
173: .next();
174:
175: //Don't want to add containers to the right-hand list. [Jon Aquino]
176: if (node.isContainer()) {
177: i.remove();
178: }
179: }
180:
181: return selectedItems;
182: }
183: };
184:
185: addRemovePanel.setLeftList(leftList);
186: leftList.getTree().setCellRenderer(
187: new DefaultTreeCellRenderer() {
188: public Component getTreeCellRendererComponent(
189: JTree tree, Object value, boolean sel,
190: boolean expanded, boolean leaf, int row,
191: boolean hasFocus) {
192: JLabel component = (JLabel) super
193: .getTreeCellRendererComponent(tree,
194: value, sel, expanded, leaf,
195: row, hasFocus);
196:
197: if (!(value instanceof MapLayerTreeModel.LayerNode)) {
198: //This happens during initialization. [Jon Aquino]
199: return component;
200: }
201:
202: MapLayer layer = ((MapLayerTreeModel.LayerNode) value)
203: .getLayer();
204: setRendererText(component, layer);
205:
206: if (layer.getName() == null) {
207: //Node is just a container. [Jon Aquino]
208: if (expanded) {
209: component.setIcon(UIManager
210: .getIcon("Tree.openIcon"));
211: } else {
212: component.setIcon(UIManager
213: .getIcon("Tree.closedIcon"));
214: }
215: } else {
216: component.setIcon(ICON);
217: }
218:
219: return component;
220: }
221: });
222:
223: DefaultAddRemoveList rightList = new DefaultAddRemoveList(
224: new DefaultListModel() {
225: public void addElement(Object obj) {
226: if (contains(obj)) {
227: //Possible because items are never removed from the tree on the left. [Jon Aquino]
228: return;
229: }
230:
231: super .addElement(obj);
232: }
233: });
234: addRemovePanel.setRightList(rightList);
235: rightList.getList().setCellRenderer(
236: new DefaultListCellRenderer() {
237: public Component getListCellRendererComponent(
238: JList list, Object value, int index,
239: boolean isSelected, boolean cellHasFocus) {
240: JLabel component = (JLabel) super
241: .getListCellRendererComponent(list,
242: value, index, isSelected,
243: cellHasFocus);
244: MapLayer layer = ((MapLayerTreeModel.LayerNode) value)
245: .getLayer();
246: setRendererText(component, layer);
247: component.setIcon(ICON);
248:
249: return component;
250: }
251: });
252: leftList.add(new InputChangedListener() {
253: public void inputChanged() {
254: inputChangedFirer.fire();
255: }
256: });
257: rightList.add(new InputChangedListener() {
258: public void inputChanged() {
259: inputChangedFirer.fire();
260: }
261: });
262: rightList.getList().getModel().addListDataListener(
263: new ListDataListener() {
264: public void intervalAdded(ListDataEvent e) {
265: inputChangedFirer.fire();
266: }
267:
268: public void intervalRemoved(ListDataEvent e) {
269: inputChangedFirer.fire();
270: }
271:
272: public void contentsChanged(ListDataEvent e) {
273: inputChangedFirer.fire();
274: }
275: });
276:
277: JPanel leftLabelPanel = new JPanel();
278: leftLabelPanel.setLayout(new GridBagLayout());
279: leftLabelPanel.add(new JLabel(I18N
280: .get("ui.plugin.wms.MapLayerPanel.available-layers")),
281: new GridBagConstraints(0, 0, 1, 1, 0, 0,
282: GridBagConstraints.WEST,
283: GridBagConstraints.NONE,
284: new Insets(0, 0, 0, 0), 0, 0));
285: leftLabelPanel.add(new JPanel(), new GridBagConstraints(1, 0,
286: 1, 1, 1, 0, GridBagConstraints.WEST,
287: GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
288:
289: checkBox.addActionListener(new ActionListener() {
290: public void actionPerformed(ActionEvent e) {
291: setSorted(checkBox.isSelected());
292: }
293: });
294: leftLabelPanel.add(checkBox, new GridBagConstraints(2, 0, 1, 1,
295: 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE,
296: new Insets(0, 0, 0, 0), 0, 0));
297:
298: addRemovePanel.setLeftLabel(leftLabelPanel);
299: }
300:
301: private void setSorted(boolean isSorted) {
302: TreeAddRemoveList tarl = (TreeAddRemoveList) addRemovePanel
303: .getLeftList();
304: TreeAddRemoveListModel tarlm = (TreeAddRemoveListModel) tarl
305: .getModel();
306: MapLayerTreeModel mltm = (MapLayerTreeModel) tarlm
307: .getTreeModel();
308:
309: mltm.setSorted(isSorted);
310: }
311:
312: /**
313: * @param chosenMapLayers null to leave unspecified
314: */
315: public void init(WMService service,
316: Collection initialChosenMapLayers) {
317: final MapLayerTreeModel treeModel = new MapLayerTreeModel(
318: service.getCapabilities().getTopLayer());
319:
320: treeModel.setSorted(checkBox.isSelected());
321:
322: TreeAddRemoveListModel treeAddRemoveListModel = new TreeAddRemoveListModel(
323: treeModel) {
324: public List getItems() {
325: ArrayList items = new ArrayList(
326: items((MapLayerTreeModel.LayerNode) treeModel
327: .getRoot()));
328:
329: for (Iterator i = items.iterator(); i.hasNext();) {
330: MapLayerTreeModel.LayerNode node = (MapLayerTreeModel.LayerNode) i
331: .next();
332:
333: //Don't want to add containers to the right-hand list. [Jon Aquino]
334: if (node.isContainer()) {
335: i.remove();
336: }
337: }
338:
339: return items;
340: }
341: };
342:
343: ((TreeAddRemoveList) addRemovePanel.getLeftList())
344: .setModel(treeAddRemoveListModel);
345:
346: if (initialChosenMapLayers != null) {
347: addIfOnList(service.getCapabilities().getTopLayer(),
348: addRemovePanel.getRightList().getModel(),
349: initialChosenMapLayers);
350: }
351:
352: addRemovePanel.updateEnabled();
353: }
354:
355: private List items(MapLayerTreeModel.LayerNode node) {
356: ArrayList items = new ArrayList();
357: items.add(node);
358:
359: for (Enumeration e = node.children(); e.hasMoreElements();) {
360: MapLayerTreeModel.LayerNode child = (MapLayerTreeModel.LayerNode) e
361: .nextElement();
362: items.addAll(items(child));
363: }
364:
365: //Remove any items already on the right-hand list, so that the ">>" button enables/disables properly. [Jon Aquino]
366: items.removeAll(addRemovePanel.getRightItems());
367:
368: return items;
369: }
370: }
|