/* * The Unified Mapping Platform (JUMP) is an extensible, interactive GUI * for visualizing and manipulating spatial features with geometry and attributes. * * Copyright (C) 2003 Vivid Solutions * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jump.workbench.ui; import java.awt.BorderLayout; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.geom.NoninvertibleTransformException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import javax.swing.Icon; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JToolBar; import javax.swing.SwingUtilities; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import org.openjump.core.ui.plugin.tools.ReplaceValuePlugIn; import com.vividsolutions.jump.I18N; import com.vividsolutions.jump.workbench.WorkbenchContext; import com.vividsolutions.jump.workbench.model.CategoryEvent; import com.vividsolutions.jump.workbench.model.FeatureEvent; import com.vividsolutions.jump.workbench.model.Layer; import com.vividsolutions.jump.workbench.model.LayerEvent; import com.vividsolutions.jump.workbench.model.LayerEventType; import com.vividsolutions.jump.workbench.model.LayerListener; import com.vividsolutions.jump.workbench.model.LayerManager; import com.vividsolutions.jump.workbench.model.LayerManagerProxy; import com.vividsolutions.jump.workbench.model.Layerable; import com.vividsolutions.jump.workbench.plugin.EnableCheck; import com.vividsolutions.jump.workbench.plugin.MultiEnableCheck; import com.vividsolutions.jump.workbench.plugin.PlugIn; import com.vividsolutions.jump.workbench.plugin.PlugInContext; import com.vividsolutions.jump.workbench.ui.cursortool.FeatureInfoTool; import com.vividsolutions.jump.workbench.ui.images.IconLoader; import com.vividsolutions.jump.workbench.ui.plugin.FeatureInfoPlugIn; import com.vividsolutions.jump.workbench.ui.plugin.FeatureInstaller; /** * Implements an Attribute Tab. */ public class AttributeTab extends JPanel implements LayerNamePanel { private BorderLayout borderLayout1 = new BorderLayout(); private ErrorHandler errorHandler; private TaskFrame taskFrame; private LayerManagerProxy layerManagerProxy; //The String values returned by these EnableChecks are not used. //The only thing checked is whether they are null or not. [Jon Aquino] private EnableCheck taskFrameEnableCheck = new EnableCheck() { public String check(JComponent component) { return (!taskFrame.isVisible()) ? I18N.get("ui.AttributeTab.task-frame-must-be-open") : null; } }; private EnableCheck layersEnableCheck = new EnableCheck() { public String check(JComponent component) { return panel.getModel().getLayers().isEmpty() ? I18N.get("ui.AttributeTab.one-or-more-layers-must-be-present") : null; } }; private AttributePanel panel; private JScrollPane scrollPane = new JScrollPane(); private EnableCheck rowsSelectedEnableCheck = new EnableCheck() { public String check(JComponent component) { return panel.selectedFeatures().isEmpty() ? I18N.get("ui.AttributeTab.one-or-more-rows-must-be-selected") : null; } }; private EnableableToolBar toolBar = new EnableableToolBar(); private InfoModel model; private Layer[] selectedLayers = new Layer[] {}; private Layer[] lastSelectedLayers = new Layer[] {}; public InfoModel getModel() { return model; } public AttributeTab( final InfoModel model, final WorkbenchContext workbenchContext, final TaskFrame taskFrame, LayerManagerProxy layerManagerProxy, boolean addScrollPanesToChildren) { this.layerManagerProxy = layerManagerProxy; this.model = model; this.taskFrame = taskFrame; taskFrame .addInternalFrameListener( GUIUtil .toInternalFrameListener(new ActionListener() { public void actionPerformed(ActionEvent e) { toolBar.updateEnabledState(); } })); panel = new AttributePanel(model, workbenchContext, taskFrame, layerManagerProxy, addScrollPanesToChildren) { public void layerAdded(LayerTableModel layerTableModel) { super.layerAdded(layerTableModel); final AttributeTablePanel tablePanel = getTablePanel(layerTableModel.getLayer()); MouseListener mouseListener = new MouseAdapter() { public void mouseReleased(MouseEvent e) { if (!SwingUtilities.isRightMouseButton(e)) { return; } popupMenu(workbenchContext).setTitle( tablePanel.getModel().getLayer().getName()); lastSelectedLayers = new Layer[] { tablePanel.getModel().getLayer()}; //Call #setEnableLastSelectedLayers here for EnableChecks that //call #getSelectedLayers. [Jon Aquino] setEnableLastSelectedLayers(true, AttributeTab.this); try { popupMenu(workbenchContext).show( tablePanel.getLayerNameRenderer(), e.getX(), e.getY()); } finally { setEnableLastSelectedLayers(false, AttributeTab.this); } } }; tablePanel.addMouseListener(mouseListener); tablePanel.getTable().addMouseListener(mouseListener); tablePanel.getTable().getTableHeader().addMouseListener(mouseListener); tablePanel.getLayerNameRenderer().addMouseListener(mouseListener); } }; layerManagerProxy.getLayerManager().addLayerListener(new LayerListener() { public void featuresChanged(FeatureEvent e) {} public void layerChanged(LayerEvent e) { if (e.getType() == LayerEventType.METADATA_CHANGED) { //Editability may have changed. [Jon Aquino] toolBar.updateEnabledState(); } } public void categoryChanged(CategoryEvent e) {} }); model.addListener(new InfoModelListener() { public void layerAdded(LayerTableModel layerTableModel) { panel .getTablePanel(layerTableModel.getLayer()) .getTable() .getSelectionModel() .addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent e) { toolBar.updateEnabledState(); } }); toolBar.updateEnabledState(); } public void layerRemoved(LayerTableModel layerTableModel) { toolBar.updateEnabledState(); } }); this.errorHandler = workbenchContext.getErrorHandler(); try { jbInit(); } catch (Exception ex) { ex.printStackTrace(); } initScrollPane(); if (addScrollPanesToChildren) { remove(scrollPane); add(panel, BorderLayout.CENTER); } installToolBarButtons(workbenchContext, taskFrame); toolBar.updateEnabledState(); } private void installToolBarButtons(final WorkbenchContext workbenchContext, final TaskFrame taskFrame) { toolBar .add( new JButton(), I18N.get("ui.AttributeTab.pan-to-previous-row"), IconLoader.icon("SmallUp.gif"), new ActionListener() { public void actionPerformed(ActionEvent e) { try { pan(panel.topSelectedRow().previousRow()); } catch (Throwable t) { errorHandler.handleThrowable(t); } } }, new MultiEnableCheck().add(taskFrameEnableCheck).add(layersEnableCheck)); toolBar .add( new JButton(), I18N.get("ui.AttributeTab.zoom-to-previous-row"), IconLoader.icon("SmallMagnifyUp.gif"), new ActionListener() { public void actionPerformed(ActionEvent e) { try { zoom(panel.topSelectedRow().previousRow()); } catch (Throwable t) { errorHandler.handleThrowable(t); } } }, new MultiEnableCheck().add(taskFrameEnableCheck).add(layersEnableCheck)); toolBar .add( new JButton(), I18N.get("ui.AttributeTab.zoom-to-next-row"), IconLoader.icon("SmallMagnifyDown.gif"), new ActionListener() { public void actionPerformed(ActionEvent e) { try { zoom(panel.topSelectedRow().nextRow()); } catch (Throwable t) { errorHandler.handleThrowable(t); } } }, new MultiEnableCheck().add(taskFrameEnableCheck).add(layersEnableCheck)); toolBar .add( new JButton(), I18N.get("ui.AttributeTab.pan-to-next-row"), IconLoader.icon("SmallDown.gif"), new ActionListener() { public void actionPerformed(ActionEvent e) { try { pan(panel.topSelectedRow().nextRow()); } catch (Throwable t) { errorHandler.handleThrowable(t); } } }, new MultiEnableCheck().add(taskFrameEnableCheck).add(layersEnableCheck)); toolBar .add( new JButton(), I18N.get("ui.AttributeTab.zoom-to-selected-rows"), IconLoader.icon("SmallMagnify.gif"), new ActionListener() { public void actionPerformed(ActionEvent e) { try { panel.zoom(panel.selectedFeatures()); } catch (Throwable t) { errorHandler.handleThrowable(t); } } }, new MultiEnableCheck().add(taskFrameEnableCheck).add(layersEnableCheck).add( rowsSelectedEnableCheck)); toolBar .add( new JButton(), I18N.get("ui.AttributeTab.zoom-to-full-extent"), IconLoader.icon("SmallWorld.gif"), new ActionListener() { public void actionPerformed(ActionEvent e) { try { taskFrame.getLayerViewPanel().getViewport().zoomToFullExtent(); } catch (Throwable t) { errorHandler.handleThrowable(t); } } }, new MultiEnableCheck().add(taskFrameEnableCheck).add(layersEnableCheck)); toolBar .add( new JButton(), I18N.get("ui.AttributeTab.select-in-task-window"), IconLoader.icon("SmallSelect.gif"), new ActionListener() { public void actionPerformed(ActionEvent e) { try { panel.selectInLayerViewPanel(); } catch (Throwable t) { errorHandler.handleThrowable(t); } } }, new MultiEnableCheck().add(taskFrameEnableCheck).add(layersEnableCheck).add( rowsSelectedEnableCheck)); toolBar .add( new JButton(), I18N.get("ui.AttributeTab.flash-selected-rows"), IconLoader.icon("Flashlight.gif"), new ActionListener() { public void actionPerformed(ActionEvent e) { try { panel.flashSelectedFeatures(); } catch (Throwable t) { errorHandler.handleThrowable(t); } } }, new MultiEnableCheck().add(taskFrameEnableCheck).add(layersEnableCheck).add( rowsSelectedEnableCheck)); FeatureInfoPlugIn featureInfoPlugIn = new FeatureInfoPlugIn(); toolBar.add( new JButton(), featureInfoPlugIn.getName(), GUIUtil.toSmallIcon(FeatureInfoTool.ICON), FeatureInfoPlugIn.toActionListener(featureInfoPlugIn, workbenchContext, null), FeatureInfoPlugIn.createEnableCheck(workbenchContext)); //-- [sstein 4 nov 2006] added replace value /* but is not yet activated since problems appear: * either with enableCheck => nullpointer * or with actionPerformed => update of window? */ /** ReplaceValuePlugIn myReplacePlugIn = new ReplaceValuePlugIn(); toolBar.add( new JButton(), myReplacePlugIn.getName(), GUIUtil.toSmallIcon(ReplaceValuePlugIn.ICON), ReplaceValuePlugIn.toActionListener(myReplacePlugIn, workbenchContext, null), ReplaceValuePlugIn.createEnableCheck(workbenchContext)); **/ } public TaskFrame getTaskFrame() { return taskFrame; } public Layer chooseEditableLayer() { return TreeLayerNamePanel.chooseEditableLayer(this); } public LayerManager getLayerManager() { return layerManagerProxy.getLayerManager(); } void jbInit() throws Exception { this.setLayout(borderLayout1); toolBar.setOrientation(JToolBar.VERTICAL); scrollPane.getViewport().add(panel, null); this.add(scrollPane, BorderLayout.CENTER); this.add(toolBar, BorderLayout.WEST); } private void initScrollPane() { scrollPane.getVerticalScrollBar().setUnitIncrement(new JTable().getRowHeight()); } private void zoom(AttributePanel.Row row) throws NoninvertibleTransformException { panel.clearSelection(); //fixed : if the layer don't have any feature, do nothing. if (row.getPanel().getTable().getModel().getRowCount() == 0) { return; } row.getPanel().getTable().getSelectionModel().setSelectionInterval( row.getIndex(), row.getIndex()); Rectangle r = row.getPanel().getTable().getCellRect(row.getIndex(), 0, true); row.getPanel().getTable().scrollRectToVisible(r); if (row.isFirstRow()) { //Make header visible [Jon Aquino] row.getPanel().scrollRectToVisible(new Rectangle(0, 0, 1, 1)); } ArrayList features = new ArrayList(); features.add(row.getFeature()); panel.zoom(features); } private void pan(AttributePanel.Row row) throws NoninvertibleTransformException { panel.clearSelection(); //fixed : if the layer don't have any feature, do nothing. if (row.getPanel().getTable().getModel().getRowCount() == 0) { return; } row.getPanel().getTable().getSelectionModel().setSelectionInterval( row.getIndex(), row.getIndex()); Rectangle r = row.getPanel().getTable().getCellRect(row.getIndex(), 0, true); row.getPanel().getTable().scrollRectToVisible(r); if (row.isFirstRow()) { //Make header visible [Jon Aquino] row.getPanel().scrollRectToVisible(new Rectangle(0, 0, 1, 1)); } ArrayList features = new ArrayList(); features.add(row.getFeature()); panel.pan(features); } public static TitledPopupMenu popupMenu(WorkbenchContext context) { return (TitledPopupMenu) context.getWorkbench().getBlackboard().get( AttributeTab.class.getName() + " - LAYER POPUP MENU", new TitledPopupMenu()); } public static void addPopupMenuItem( WorkbenchContext workbenchContext, PlugIn plugIn, String menuItemName, boolean checkBox, Icon icon, EnableCheck enableCheck) { new FeatureInstaller(workbenchContext).addPopupMenuItem( popupMenu(workbenchContext), wrap(plugIn), menuItemName, checkBox, icon, enableCheck); } private static PlugIn wrap(final PlugIn plugIn) { //Can't simply add an ActionListener to the menu item to determine when the //plug-in finishes because ActionListeners are notified last to first (see //AbstractButton#fireActionPerformed). [Jon Aquino] return new PlugIn() { public void initialize(PlugInContext context) throws Exception { plugIn.initialize(context); } public boolean execute(PlugInContext context) throws Exception { //Save attributeTab before executing plug-in, as it may change active window. [Jon Aquino] AttributeTab attributeTab = (AttributeTab) context.getLayerNamePanel(); setEnableLastSelectedLayers(true, attributeTab); try { return plugIn.execute(context); } finally { setEnableLastSelectedLayers(false, attributeTab); } } public String getName() { return plugIn.getName(); } }; } private static void setEnableLastSelectedLayers( boolean enabled, AttributeTab attributeTab) { attributeTab.selectedLayers = enabled ? attributeTab.lastSelectedLayers : new Layer[] {}; } public Collection getSelectedCategories() { return new ArrayList(); } public Layer[] getSelectedLayers() { if (model.getLayers().size() == 1) { return new Layer[] {(Layer) model.getLayers().get(0)}; } return selectedLayers; } public Collection selectedNodes(Class c) { if (!Layerable.class.isAssignableFrom(c)) { return new ArrayList(); } return Arrays.asList(getSelectedLayers()); } public AttributePanel getPanel() { return panel; } public EnableableToolBar getToolBar() { return toolBar; } public void addListener(LayerNamePanelListener listener) {} public void removeListener(LayerNamePanelListener listener) {} public void dispose() {} }