001: /*
002: * The Unified Mapping Platform (JUMP) is an extensible, interactive GUI for
003: * 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 modify it under
008: * the terms of the GNU General Public License as published by the Free Software
009: * Foundation; either version 2 of the License, or (at your option) any later
010: * version.
011: *
012: * This program is distributed in the hope that it will be useful, but WITHOUT
013: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
014: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
015: * details.
016: *
017: * You should have received a copy of the GNU General Public License along with
018: * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
019: * Place - Suite 330, Boston, MA 02111-1307, USA.
020: *
021: * For more information, contact:
022: *
023: * Vivid Solutions Suite #1A 2328 Government Street Victoria BC V8T 5G5 Canada
024: *
025: * (250)385-6040 www.vividsolutions.com
026: */
027: package com.vividsolutions.jump.workbench.ui;
028:
029: import com.vividsolutions.jump.I18N;
030: import com.vividsolutions.jump.workbench.model.Layer;
031: import com.vividsolutions.jump.workbench.model.Layerable;
032: import com.vividsolutions.jump.workbench.model.WMSLayer;
033: import com.vividsolutions.jump.workbench.ui.images.IconLoader;
034: import com.vividsolutions.jump.workbench.ui.plugin.wms.MapLayerPanel;
035: import com.vividsolutions.jump.workbench.ui.renderer.RenderingManager;
036: import java.awt.Color;
037: import java.awt.Component;
038: import java.awt.Font;
039: import java.awt.GridBagConstraints;
040: import java.awt.GridBagLayout;
041: import java.awt.Insets;
042: import java.awt.Rectangle;
043: import javax.swing.DefaultListCellRenderer;
044: import javax.swing.Icon;
045: import javax.swing.JCheckBox;
046: import javax.swing.JLabel;
047: import javax.swing.JList;
048: import javax.swing.JPanel;
049: import javax.swing.JTree;
050: import javax.swing.ListCellRenderer;
051: import javax.swing.UIManager;
052: import javax.swing.tree.TreeCellRenderer;
053:
054: public class LayerNameRenderer extends JPanel implements
055: ListCellRenderer, TreeCellRenderer {
056: //<<TODO>> See how the colour looks with other L&F's. [Jon Aquino]
057:
058: public static final String USE_CLOCK_ANIMATION_KEY = LayerNameRenderer.class
059: .getName()
060: + " - USE CLOCK ANIMATION";
061:
062: private final static Color UNSELECTED_EDITABLE_FONT_COLOR = Color.red;
063: private final static Color SELECTED_EDITABLE_FONT_COLOR = Color.yellow;
064: protected JCheckBox checkBox = new JCheckBox();
065:
066: private LayerColorPanel colorPanel = new LayerColorPanel();
067:
068: GridBagLayout gridBagLayout = new GridBagLayout();
069:
070: protected JLabel label = new JLabel();
071:
072: private boolean indicatingEditability = false;
073: private boolean indicatingProgress = false;
074: private int progressIconSize = 13;
075: private Icon[] progressIcons = null;
076: private Icon clearProgressIcon = GUIUtil.resize(IconLoader
077: .icon("Clear.gif"), progressIconSize);
078:
079: public static String PROGRESS_ICON_KEY = "PROGRESS_ICON";
080:
081: private DefaultListCellRenderer defaultListCellRenderer = new DefaultListCellRenderer();
082: private RenderingManager renderingManager;
083: private JLabel progressIconLabel = new JLabel();
084: private Font font = new JLabel().getFont();
085: private Font editableFont = font.deriveFont(Font.BOLD);
086: private JLabel wmsIconLabel = new JLabel(MapLayerPanel.ICON);
087:
088: public LayerNameRenderer() {
089: try {
090: jbInit();
091: } catch (Exception ex) {
092: ex.printStackTrace();
093: }
094: }
095:
096: public void setIndicatingEditability(boolean indicatingEditability) {
097: this .indicatingEditability = indicatingEditability;
098: }
099:
100: public void setIndicatingProgress(boolean indicatingProgress,
101: RenderingManager renderingManager) {
102: this .indicatingProgress = indicatingProgress;
103: this .renderingManager = renderingManager;
104: }
105:
106: public JLabel getLabel() {
107: return label;
108: }
109:
110: /**
111: * @return relative to this panel
112: */
113: public Rectangle getCheckBoxBounds() {
114: int i = gridBagLayout.getConstraints(checkBox).gridx;
115: int x = 0;
116: for (int j = 0; j < i; j++) {
117: x += getColumnWidth(j);
118: }
119: return new Rectangle(x, 0, getColumnWidth(i), getRowHeight());
120: }
121:
122: /**
123: * @param i
124: * zero-based
125: */
126: protected int getColumnWidth(int i) {
127: validateTree();
128: return gridBagLayout.getLayoutDimensions()[0][i];
129: }
130:
131: protected int getRowHeight() {
132: validateTree();
133: return gridBagLayout.getLayoutDimensions()[1][0];
134: }
135:
136: public void setCheckBoxVisible(boolean checkBoxVisible) {
137: checkBox.setVisible(checkBoxVisible);
138: }
139:
140: /**
141: * Workaround for bug 4238829 in the Java bug database: "JComboBox
142: * containing JPanel fails to display selected item at creation time"
143: */
144: public void setBounds(int x, int y, int w, int h) {
145: super .setBounds(x, y, w, h);
146: validate();
147: }
148:
149: public Component getListCellRendererComponent(JList list,
150: Object value, int index, boolean isSelected,
151: boolean cellHasFocus) {
152: if (value == null) {
153: return defaultListCellRenderer
154: .getListCellRendererComponent(list, value, index,
155: isSelected, cellHasFocus);
156: }
157: Layerable layerable = (Layerable) value;
158: label.setText(layerable.getName());
159: setToolTipText(layerable.getName()
160: + ((layerable instanceof Layer
161: && (((Layer) layerable).getDescription() != null) && (((Layer) layerable)
162: .getDescription().trim().length() > 0)) ? (": " + ((Layer) layerable)
163: .getDescription())
164: : ""));
165: if (isSelected) {
166: label.setForeground(list.getSelectionForeground());
167: label.setBackground(list.getSelectionBackground());
168: setForeground(list.getSelectionForeground());
169: setBackground(list.getSelectionBackground());
170: } else {
171: label.setForeground(list.getForeground());
172: label.setBackground(list.getBackground());
173: setForeground(list.getForeground());
174: setBackground(list.getBackground());
175: }
176: colorPanel.setVisible(layerable instanceof Layer);
177: checkBox.setSelected(layerable.isVisible());
178: if (indicatingEditability && layerable instanceof Layer
179: && ((Layer) layerable).isEditable()) {
180: label.setFont(editableFont);
181: label
182: .setForeground(isSelected ? SELECTED_EDITABLE_FONT_COLOR
183: : UNSELECTED_EDITABLE_FONT_COLOR);
184: } else {
185: label.setFont(font);
186: }
187: wmsIconLabel.setVisible(layerable instanceof WMSLayer);
188: // Only show the progress icon (clocks) for WMSLayers and
189: // database-backed layers, not Layers. Otherwise it's too busy.
190: // [Jon Aquino]
191: if (layerable.getBlackboard().get(USE_CLOCK_ANIMATION_KEY,
192: false)
193: && indicatingProgress
194: && (renderingManager.getRenderer(layerable) != null)
195: && renderingManager.getRenderer(layerable)
196: .isRendering()) {
197: layerable.getBlackboard()
198: .put(
199: PROGRESS_ICON_KEY,
200: layerable.getBlackboard().get(
201: PROGRESS_ICON_KEY, 0) + 1);
202: if (layerable.getBlackboard().getInt(PROGRESS_ICON_KEY) > (getProgressIcons().length - 1)) {
203: layerable.getBlackboard().put(PROGRESS_ICON_KEY, 0);
204: }
205: progressIconLabel.setIcon(getProgressIcons()[layerable
206: .getBlackboard().getInt(PROGRESS_ICON_KEY)]);
207: } else {
208: progressIconLabel.setIcon(clearProgressIcon);
209: layerable.getBlackboard().put(PROGRESS_ICON_KEY, null);
210: }
211: Color backgroundColor = list.getBackground();
212: Color selectionBackgroundColor = list.getSelectionBackground();
213: if (layerable instanceof Layer) {
214: Layer layer = (Layer) layerable;
215: colorPanel.init(layer, isSelected, backgroundColor,
216: selectionBackgroundColor);
217: }
218: return this ;
219: }
220:
221: private JList list(JTree tree) {
222: JList list = new JList();
223: list.setForeground(tree.getForeground());
224: list.setBackground(tree.getBackground());
225: list.setSelectionForeground(UIManager
226: .getColor("Tree.selectionForeground"));
227: list.setSelectionBackground(UIManager
228: .getColor("Tree.selectionBackground"));
229: return list;
230: }
231:
232: public Component getTreeCellRendererComponent(JTree tree,
233: Object value, boolean selected, boolean expanded,
234: boolean leaf, int row, boolean hasFocus) {
235: Layerable layerable = (Layerable) value;
236: getListCellRendererComponent(list(tree), layerable, -1,
237: selected, hasFocus);
238: if (selected) {
239: label.setForeground(UIManager
240: .getColor("Tree.selectionForeground"));
241: label.setBackground(UIManager
242: .getColor("Tree.selectionBackground"));
243: setForeground(UIManager
244: .getColor("Tree.selectionForeground"));
245: setBackground(UIManager
246: .getColor("Tree.selectionBackground"));
247: } else {
248: label.setForeground(tree.getForeground());
249: label.setBackground(tree.getBackground());
250: setForeground(tree.getForeground());
251: setBackground(tree.getBackground());
252: }
253: if (indicatingEditability && layerable instanceof Layer) {
254: if (((Layer) layerable).isEditable()) {
255: label
256: .setForeground(selected ? SELECTED_EDITABLE_FONT_COLOR
257: : UNSELECTED_EDITABLE_FONT_COLOR);
258: }
259: }
260: return this ;
261: }
262:
263: void jbInit() throws Exception {
264: checkBox.setVisible(false);
265: this .setLayout(gridBagLayout);
266: label.setOpaque(false);
267: label.setText("Layer Name Goes Here");
268: checkBox.setOpaque(false);
269: this .add(progressIconLabel, new GridBagConstraints(0, 0, 1, 1,
270: 0.0, 0.0, GridBagConstraints.CENTER,
271: GridBagConstraints.NONE, new Insets(0, 0, 0, 2), 0, 0));
272: this .add(wmsIconLabel, new GridBagConstraints(1, 0, 1, 1, 0.0,
273: 0.0, GridBagConstraints.CENTER,
274: GridBagConstraints.NONE, new Insets(0, 0, 0, 2), 0, 0));
275: this .add(colorPanel, new GridBagConstraints(2, 0, 1, 1, 0.0,
276: 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE,
277: new Insets(0, 0, 0, 5), 0, 0));
278: this .add(checkBox, new GridBagConstraints(3, 0, 1, 1, 0.0, 0.0,
279: GridBagConstraints.CENTER, GridBagConstraints.NONE,
280: new Insets(0, 0, 0, 0), 0, 0));
281: this .add(label, new GridBagConstraints(4, 0, 1, 1, 1.0, 0.0,
282: GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
283: new Insets(0, 0, 0, 0), 0, 0));
284: }
285:
286: private Icon[] getProgressIcons() {
287: //Create lazily -- OptimizeIt tells me creating these images takes 20
288: //seconds [Jon Aquino 2004-05-14]
289: if (progressIcons == null) {
290: progressIcons = new Icon[] {
291: GUIUtil.resize(IconLoader.icon("ClockN.gif"),
292: progressIconSize),
293: GUIUtil.resize(IconLoader.icon("ClockNE.gif"),
294: progressIconSize),
295: GUIUtil.resize(IconLoader.icon("ClockE.gif"),
296: progressIconSize),
297: GUIUtil.resize(IconLoader.icon("ClockSE.gif"),
298: progressIconSize),
299: GUIUtil.resize(IconLoader.icon("ClockS.gif"),
300: progressIconSize),
301: GUIUtil.resize(IconLoader.icon("ClockSW.gif"),
302: progressIconSize),
303: GUIUtil.resize(IconLoader.icon("ClockW.gif"),
304: progressIconSize),
305: GUIUtil.resize(IconLoader.icon("ClockNW.gif"),
306: progressIconSize) };
307: }
308: return progressIcons;
309: }
310: }
|