public static void reportExceptions( ArrayList exceptions, DataSourceQuery dataSourceQuery, WorkbenchContext context) { context .getIWorkbench() .getFrame() .getOutputFrame() .addHeader( 1, exceptions.size() + " problem" + StringUtil.s(exceptions.size()) + " loading " + dataSourceQuery.toString() + "." + ((exceptions.size() > 10) ? " First and last five:" : "")); context.getIWorkbench().getFrame().getOutputFrame().addText("See View / Log for stack traces"); context.getIWorkbench().getFrame().getOutputFrame().append("<ul>"); Collection exceptionsToReport = exceptions.size() <= 10 ? exceptions : CollectionUtil.concatenate( Arrays.asList( new Collection[] { exceptions.subList(0, 5), exceptions.subList(exceptions.size() - 5, exceptions.size()) })); for (Iterator j = exceptionsToReport.iterator(); j.hasNext(); ) { Exception exception = (Exception) j.next(); context.getIWorkbench().getGuiComponent().log(StringUtil.stackTrace(exception)); context.getIWorkbench().getFrame().getOutputFrame().append("<li>"); context .getIWorkbench() .getFrame() .getOutputFrame() .append(GUIUtil.escapeHTML(WorkbenchFrameImpl.toMessage(exception), true, true)); context.getIWorkbench().getFrame().getOutputFrame().append("</li>"); } context.getIWorkbench().getFrame().getOutputFrame().append("</ul>"); }
/** This class is responsible for the main window of the JUMP application. */ public class WorkbenchFrameImpl extends WorkbenchFrame implements LayerViewPanelContext, ViewportListener, WorkbenchGuiComponent { BorderLayout borderLayout1 = new BorderLayout(); JLabel coordinateLabel = new JLabel(); private JPopupMenu popupMenu = new TrackedPopupMenu(); JMenuBar menuBar = new JMenuBar(); JMenu fileMenu = (JMenu) FeatureInstaller.installMnemonic(new JMenu("File"), menuBar); JMenuItem exitMenuItem = FeatureInstaller.installMnemonic(new JMenuItem("E&xit"), fileMenu); GridBagLayout gridBagLayout1 = new GridBagLayout(); JLabel messageLabel = new JLabel(); JPanel statusPanel = new JPanel(); JLabel timeLabel = new JLabel(); // <<TODO:FEATURE>> Before JUMP Workbench closes, prompt the user to save // any // unsaved layers [Jon Aquino] WorkbenchToolBar toolBar; JMenu windowMenu = (JMenu) FeatureInstaller.installMnemonic(new JMenu("Window"), menuBar); private TitledPopupMenu categoryPopupMenu = new TitledPopupMenu() { { addPopupMenuListener( new PopupMenuListener() { public void popupMenuWillBecomeVisible(PopupMenuEvent e) { LayerNamePanel panel = ((LayerNamePanelProxy) getActiveInternalFrame()).getLayerNamePanel(); setTitle( (panel.selectedNodes(Category.class).size() != 1) ? ("(" + panel.selectedNodes(Category.class).size() + " categories selected)") : ((Category) panel.selectedNodes(Category.class).iterator().next()) .getName()); } public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {} public void popupMenuCanceled(PopupMenuEvent e) {} }); } }; private JDesktopPane desktopPane = new JDesktopPane(); // <<TODO:REMOVE>> Actually we're not using the three optimization // parameters // below. Remove. [Jon Aquino] private int envelopeRenderingThreshold = 500; private HTMLFrame outputFrame = new HTMLFrame(this) { public void setTitle(String title) { // Don't allow the title of the output frame to be changed. } { super.setTitle("Output"); } }; private ImageIcon icon; private TitledPopupMenu layerNamePopupMenu = new TitledPopupMenu() { { addPopupMenuListener( new PopupMenuListener() { public void popupMenuWillBecomeVisible(PopupMenuEvent e) { LayerNamePanel panel = ((LayerNamePanelProxy) getActiveInternalFrame()).getLayerNamePanel(); setTitle( (panel.selectedNodes(Layer.class).size() != 1) ? ("(" + panel.selectedNodes(Layer.class).size() + " layers selected)") : ((Layerable) panel.selectedNodes(Layer.class).iterator().next()) .getName()); } public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {} public void popupMenuCanceled(PopupMenuEvent e) {} }); } }; private TitledPopupMenu wmsLayerNamePopupMenu = new TitledPopupMenu() { { addPopupMenuListener( new PopupMenuListener() { public void popupMenuWillBecomeVisible(PopupMenuEvent e) { LayerNamePanel panel = ((LayerNamePanelProxy) getActiveInternalFrame()).getLayerNamePanel(); setTitle( (panel.selectedNodes(WMSLayer.class).size() != 1) ? ("(" + panel.selectedNodes(WMSLayer.class).size() + " WMS layers selected)") : ((Layerable) panel.selectedNodes(WMSLayer.class).iterator().next()) .getName()); } public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {} public void popupMenuCanceled(PopupMenuEvent e) {} }); } }; private LayerNamePanelListener layerNamePanelListener = new LayerNamePanelListener() { public void layerSelectionChanged() { toolBar.updateEnabledState(); } }; private LayerViewPanelListener layerViewPanelListener = new LayerViewPanelListener() { public void cursorPositionChanged(String x, String y) { coordinateLabel.setText("(" + x + ", " + y + ")"); } public void selectionChanged() { toolBar.updateEnabledState(); } public void fenceChanged() { toolBar.updateEnabledState(); } public void painted(Graphics graphics) {} }; // <<TODO:NAMING>> This name is not clear [Jon Aquino] private int maximumFeatureExtentForEnvelopeRenderingInPixels = 10; // <<TODO:NAMING>> This name is not clear [Jon Aquino] private int minimumFeatureExtentForAnyRenderingInPixels = 2; private StringBuffer log = new StringBuffer(); private int taskSequence = 1; private WorkbenchContext workbenchContext; private JLabel memoryLabel = new JLabel(); private String lastStatusMessage = ""; private Set choosableStyleClasses = new HashSet(); private JLabel wmsLabel = new JLabel(); private ArrayList easyKeyListeners = new ArrayList(); private Map nodeClassToLayerNamePopupMenuMap = CollectionUtil.createMap( new Object[] { Layer.class, layerNamePopupMenu, WMSLayer.class, wmsLayerNamePopupMenu, Category.class, categoryPopupMenu }); private int positionIndex = -1; private int primaryInfoFrameIndex = -1; public WorkbenchFrameImpl(String title, ImageIcon icon, final WorkbenchContext workbenchContext) throws Exception { setTitle(title); new Timer( 1000, new ActionListener() { public void actionPerformed(ActionEvent e) { memoryLabel.setText(getMBCommittedMemory() + " MB Committed Memory"); memoryLabel.setToolTipText( LayerManager.layerManagerCount() + " Layer Manager" + StringUtil.s(LayerManager.layerManagerCount())); } }) .start(); this.workbenchContext = workbenchContext; this.icon = icon; toolBar = new WorkbenchToolBar(workbenchContext); try { jbInit(); configureStatusLabel(messageLabel, 300); configureStatusLabel(coordinateLabel, 150); configureStatusLabel(timeLabel, 200); configureStatusLabel(wmsLabel, 100); } catch (Exception e) { e.printStackTrace(); } new RecursiveKeyListener(this) { public void keyTyped(KeyEvent e) { for (Iterator i = easyKeyListeners.iterator(); i.hasNext(); ) { KeyListener l = (KeyListener) i.next(); l.keyTyped(e); } } public void keyPressed(KeyEvent e) { for (Iterator i = new ArrayList(easyKeyListeners).iterator(); i.hasNext(); ) { KeyListener l = (KeyListener) i.next(); l.keyPressed(e); } } public void keyReleased(KeyEvent e) { for (Iterator i = new ArrayList(easyKeyListeners).iterator(); i.hasNext(); ) { KeyListener l = (KeyListener) i.next(); l.keyReleased(e); } } }; installKeyboardShortcutListener(); } /** * Unlike #add(KeyListener), listeners registered using this method are notified when KeyEvents * occur on this frame's child components. Note: Bug: KeyListeners registered using this method * may receive events multiple times. * * @see #addKeyboardShortcut */ public void addEasyKeyListener(KeyListener l) { easyKeyListeners.add(l); } public void removeEasyKeyListener(KeyListener l) { easyKeyListeners.remove(l); } public String getMBCommittedMemory() { return new DecimalFormat("###,###") .format( (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024 * 1024d)); } /** * @param newEnvelopeRenderingThreshold the number of on-screen features above which envelope * rendering should occur */ public void setEnvelopeRenderingThreshold(int newEnvelopeRenderingThreshold) { envelopeRenderingThreshold = newEnvelopeRenderingThreshold; } public void setMaximumFeatureExtentForEnvelopeRenderingInPixels( int newMaximumFeatureExtentForEnvelopeRenderingInPixels) { maximumFeatureExtentForEnvelopeRenderingInPixels = newMaximumFeatureExtentForEnvelopeRenderingInPixels; } public void log(String message) { log.append(new Date() + " " + message + System.getProperty("line.separator")); } public String getLog() { return log.toString(); } public void setMinimumFeatureExtentForAnyRenderingInPixels( int newMinimumFeatureExtentForAnyRenderingInPixels) { minimumFeatureExtentForAnyRenderingInPixels = newMinimumFeatureExtentForAnyRenderingInPixels; } public void displayLastStatusMessage() { setStatusMessage(lastStatusMessage); } public void setStatusMessage(String message) { lastStatusMessage = message; setStatusBarText(message); setStatusBarTextHighlighted(false, null); } private void setStatusBarText(String message) { // <<TODO:IMPROVE>> Treat null messages like "" [Jon Aquino] messageLabel.setText((message == "") ? " " : message); messageLabel.setToolTipText(message); // Make message at least a space so that status bar won't collapse [Jon // Aquino] } /** To highlight a message, call #warnUser. */ private void setStatusBarTextHighlighted(boolean highlighted, Color color) { // Use #coordinateLabel rather than (unattached) dummy label because // dummy label's background does not change when L&F changes. [Jon // Aquino] messageLabel.setForeground(highlighted ? Color.black : coordinateLabel.getForeground()); messageLabel.setBackground(highlighted ? color : coordinateLabel.getBackground()); } public void setTimeMessage(String message) { // <<TODO:IMPROVE>> Treat null messages like "" [Jon Aquino] timeLabel.setText((message == "") ? " " : message); // Make message at least a space so that status bar won't collapse [Jon // Aquino] } public TaskComponent getActiveTaskComponent() { if (desktopPane.getSelectedFrame() instanceof TaskComponent) return (TaskComponent) desktopPane.getSelectedFrame(); else return null; } public JInternalFrame getActiveInternalFrame() { return desktopPane.getSelectedFrame(); } public JInternalFrame[] getInternalFrames() { return desktopPane.getAllFrames(); } public TitledPopupMenu getCategoryPopupMenu() { return categoryPopupMenu; } public WorkbenchContext getContext() { return workbenchContext; } public Container getDesktopPane() { return desktopPane; } public int getEnvelopeRenderingThreshold() { return envelopeRenderingThreshold; } public TitledPopupMenu getLayerNamePopupMenu() { return layerNamePopupMenu; } public TitledPopupMenu getWMSLayerNamePopupMenu() { return wmsLayerNamePopupMenu; } public LayerViewPanelListener getLayerViewPanelListener() { return layerViewPanelListener; } public Map getNodeClassToPopupMenuMap() { return nodeClassToLayerNamePopupMenuMap; } public LayerNamePanelListener getLayerNamePanelListener() { return layerNamePanelListener; } public int getMaximumFeatureExtentForEnvelopeRenderingInPixels() { return maximumFeatureExtentForEnvelopeRenderingInPixels; } public int getMinimumFeatureExtentForAnyRenderingInPixels() { return minimumFeatureExtentForAnyRenderingInPixels; } public HTMLFrame getOutputFrame() { return outputFrame; } public WorkbenchToolBar getToolBar() { return toolBar; } // Aqui no creo que deba ir un TaskFrame por si se quiere activar otro tipo de JinternalFrame public void activateFrame(JInternalFrame frame) { frame.moveToFront(); frame.requestFocus(); try { frame.setSelected(true); if (!(frame instanceof TaskFrame)) { frame.setMaximum(false); } } catch (PropertyVetoException e) { warnUser(StringUtil.stackTrace(e)); } } /** * If internalFrame is a LayerManagerProxy, the close behaviour will be altered so that the user * is prompted if it is the last window on the LayerManager. */ // REVISAR: No parece necesario evitar el JInternalFrame // public void addInternalFrame(final TaskComponent internalFrame) { public void addInternalFrame(final JInternalFrame internalFrame) { addInternalFrame(internalFrame, false, true); } // REVISAR: No parece necesario evitar el JInternalFrame // public void addInternalFrame(final TaskComponent internalFrame, public void addInternalFrame( final JInternalFrame internalFrame, boolean alwaysOnTop, boolean autoUpdateToolBar) { if (internalFrame instanceof LayerManagerProxy) { setClosingBehaviour((LayerManagerProxy) internalFrame); installTitleBarModifiedIndicator((LayerManagerProxy) internalFrame); } // <<TODO:IMPROVE>> Listen for when the frame closes, and when it does, // activate the topmost frame. Because Swing does not seem to do this // automatically. [Jon Aquino] internalFrame.setFrameIcon(icon); // Call JInternalFrame#setVisible before JDesktopPane#add; otherwise, // the // TreeLayerNamePanel starts too narrow (100 pixels or so) for some // reason. // <<TODO>>Investigate. [Jon Aquino] internalFrame.setVisible(true); desktopPane.add( (Component) internalFrame, alwaysOnTop ? JLayeredPane.PALETTE_LAYER : JLayeredPane.DEFAULT_LAYER); if (autoUpdateToolBar) { internalFrame.addInternalFrameListener( new InternalFrameListener() { public void internalFrameActivated(InternalFrameEvent e) { toolBar.updateEnabledState(); // Associate current cursortool with the new frame [Jon // Aquino] toolBar.reClickSelectedCursorToolButton(); } public void internalFrameClosed(InternalFrameEvent e) { toolBar.updateEnabledState(); } public void internalFrameClosing(InternalFrameEvent e) { toolBar.updateEnabledState(); } public void internalFrameDeactivated(InternalFrameEvent e) { toolBar.updateEnabledState(); } public void internalFrameDeiconified(InternalFrameEvent e) { toolBar.updateEnabledState(); } public void internalFrameIconified(InternalFrameEvent e) { toolBar.updateEnabledState(); } public void internalFrameOpened(InternalFrameEvent e) { toolBar.updateEnabledState(); } }); // Call #activateFrame *after* adding the listener. [Jon Aquino] activateFrame(internalFrame); position(internalFrame); } } private void installTitleBarModifiedIndicator(final LayerManagerProxy internalFrame) { final JInternalFrame i = (JInternalFrame) internalFrame; new Block() { // Putting updatingTitle in a Block is better than making it an // instance variable, because this way there is one updatingTitle // for each // internal frame, rather than one for all internal frames. [Jon // Aquino] private boolean updatingTitle = false; private void updateTitle() { if (updatingTitle) { return; } updatingTitle = true; try { String newTitle = i.getTitle(); if (newTitle.charAt(0) == '*') { newTitle = newTitle.substring(1); } if (!internalFrame .getLayerManager() .getLayersWithModifiedFeatureCollections() .isEmpty()) { newTitle = '*' + newTitle; } i.setTitle(newTitle); } finally { updatingTitle = false; } } public Object yield() { internalFrame .getLayerManager() .addLayerListener( new LayerListener() { public void layerChanged(LayerEvent e) { if ((e.getType() == LayerEventType.METADATA_CHANGED) || (e.getType() == LayerEventType.REMOVED)) { updateTitle(); } } public void categoryChanged(CategoryEvent e) {} public void featuresChanged(FeatureEvent e) {} }); i.addPropertyChangeListener( JInternalFrame.TITLE_PROPERTY, new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent e) { updateTitle(); } }); return null; } }.yield(); } private void setClosingBehaviour(final LayerManagerProxy internalFrame) { final JInternalFrame i = (JInternalFrame) internalFrame; i.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); i.addInternalFrameListener( new InternalFrameAdapter() { public void internalFrameClosing(InternalFrameEvent e) { if (1 == getInternalFramesAssociatedWith((LayerManager) internalFrame.getLayerManager()) .size()) { if (confirmClose( "Close Task", internalFrame.getLayerManager().getLayersWithModifiedFeatureCollections())) { GUIUtil.dispose(i, desktopPane); internalFrame.getLayerManager().dispose(); } } else { GUIUtil.dispose(i, desktopPane); } } }); } private Collection getInternalFramesAssociatedWith(LayerManager layerManager) { ArrayList internalFramesAssociatedWithLayerManager = new ArrayList(); JInternalFrame[] internalFrames = getInternalFrames(); for (int i = 0; i < internalFrames.length; i++) { if (internalFrames[i] instanceof LayerManagerProxy && (((LayerManagerProxy) internalFrames[i]).getLayerManager() == layerManager)) { internalFramesAssociatedWithLayerManager.add(internalFrames[i]); } } return internalFramesAssociatedWithLayerManager; } public TaskFrame addTaskFrame() { TaskFrame f = addTaskFrame(createTask()); return f; } public Task createTask() { Task task = new Task(); // LayerManager shouldn't automatically add categories in its // constructor. // Sometimes we want to create a LayerManager with no categories // (e.g. in OpenProjectPlugIn). [Jon Aquino] task.getLayerManager().addCategory(StandardCategoryNames.WORKING); task.getLayerManager().addCategory(StandardCategoryNames.SYSTEM); task.setName("Task " + taskSequence++); return task; } public TaskFrame addTaskFrame(Task task) { return addTaskFrame(new TaskFrame(task, workbenchContext)); } public TaskFrame addTaskFrame(TaskFrame taskFrame) { taskFrame .getTask() .getLayerManager() .addLayerListener( new LayerListener() { public void featuresChanged(FeatureEvent e) {} public void categoryChanged(CategoryEvent e) { toolBar.updateEnabledState(); } public void layerChanged(LayerEvent layerEvent) { toolBar.updateEnabledState(); } }); addInternalFrame(taskFrame); taskFrame .getLayerViewPanel() .getLayerManager() .getUndoableEditReceiver() .add( new UndoableEditReceiver.Listener() { public void undoHistoryChanged() { toolBar.updateEnabledState(); } public void undoHistoryTruncated() { toolBar.updateEnabledState(); log("Undo history was truncated"); } }); return taskFrame; } public void flash(final HTMLFrame frame) { final Color originalColor = frame.getBackgroundColor(); new Timer( 100, new ActionListener() { private int tickCount = 0; public void actionPerformed(ActionEvent e) { try { tickCount++; frame.setBackgroundColor(((tickCount % 2) == 0) ? originalColor : Color.yellow); if (tickCount == 2) { Timer timer = (Timer) e.getSource(); timer.stop(); } } catch (Throwable t) { handleThrowable(t); } } }) .start(); } private void flashStatusMessage(final String message, final Color color) { new Timer( 100, new ActionListener() { private int tickCount = 0; public void actionPerformed(ActionEvent e) { tickCount++; // This message is important, so overwrite whatever is on the // status bar. [Jon Aquino] setStatusBarText(message); setStatusBarTextHighlighted((tickCount % 2) == 0, color); if (tickCount == 4) { Timer timer = (Timer) e.getSource(); timer.stop(); } } }) .start(); } /** * Can be called regardless of whether the current thread is the AWT event dispatch thread. * * @param t Description of the Parameter */ public void handleThrowable(final Throwable t) { log(StringUtil.stackTrace(t)); Component parent = this; Window[] ownedWindows = getOwnedWindows(); for (int i = 0; i < ownedWindows.length; i++) { if (ownedWindows[i] instanceof Dialog && ownedWindows[i].isVisible() && ((Dialog) ownedWindows[i]).isModal()) { parent = ownedWindows[i]; break; } } // if (lastFiveThrowableDates.size() == 5 && new Date().getTime() // - ((Date) lastFiveThrowableDates.get(0)).getTime() < 1000 * 60) { // flashStatusMessage(t.toString(), Color.red); // } else { handleThrowable(t, parent); // } } public static void handleThrowable(final Throwable t, final Component parent) { t.printStackTrace(System.err); SwingUtilities.invokeLater( new Runnable() { public void run() { ErrorDialog.show( parent, StringUtil.toFriendlyName(t.getClass().getName()), toMessage(t), StringUtil.stackTrace(t)); } }); } private ArrayList lastFiveThrowableDates = new ArrayList() { public boolean add(Object o) { if (size() == 5) { remove(0); } return super.add(o); } }; public static String toMessage(Throwable t) { String message; if (t.getLocalizedMessage() == null) { message = "No description was provided"; } else if (t.getLocalizedMessage().toLowerCase().indexOf("side location conflict") > -1) { message = t.getLocalizedMessage() + " -- Check for invalid geometries."; } else { message = t.getLocalizedMessage(); } return message + " (" + StringUtil.toFriendlyName(t.getClass().getName()) + ")"; } public boolean hasInternalFrame(JInternalFrame internalFrame) { JInternalFrame[] frames = desktopPane.getAllFrames(); for (int i = 0; i < frames.length; i++) { if (frames[i] == internalFrame) { return true; } } return false; } public void removeInternalFrame(JInternalFrame internalFrame) { // Looks like #closeFrame is the proper way to remove an internal // frame. // It will activate the next frame. [Jon Aquino] desktopPane.getDesktopManager().closeFrame(internalFrame); } public void warnUser(String warning) { log("Warning: " + warning); flashStatusMessage(warning, Color.yellow); } public void zoomChanged(Envelope modelEnvelope) { toolBar.updateEnabledState(); } void exitMenuItem_actionPerformed(ActionEvent e) { closeApplication(); } void this_componentShown(ComponentEvent e) { try { // If the first internal frame is not a TaskWindow (as may be the // case in // custom workbenches), #updateEnabledState() will ensure that the // cursor-tool buttons are disabled. [Jon Aquino] toolBar.updateEnabledState(); } catch (Throwable t) { handleThrowable(t); } } void this_windowClosing(WindowEvent e) { closeApplication(); } void windowMenu_menuSelected(MenuEvent e) { // <<TODO:MAINTAINABILITY>> This algorithm is not robust. It assumes // the Window // menu has exactly one "regular" menu item (newWindowMenuItem). [Jon // Aquino] if (windowMenu.getItemCount() > 0 && windowMenu.getItem(0) != null && windowMenu .getItem(0) .getText() .equals(AbstractPlugIn.createName(CloneWindowPlugIn.class))) { JMenuItem newWindowMenuItem = windowMenu.getItem(0); windowMenu.removeAll(); windowMenu.add(newWindowMenuItem); windowMenu.addSeparator(); } else { // ezLink doesn't have a Clone Window menu [Jon Aquino] windowMenu.removeAll(); } // final TaskComponent[] frames = (TaskComponent[]) desktopPane.getAllFrames(); final JInternalFrame[] frames = desktopPane.getAllFrames(); for (int i = 0; i < frames.length; i++) { JMenuItem menuItem = new JMenuItem(); // Increase truncation threshold from 20 to 40, for eziLink [Jon // Aquino] menuItem.setText(GUIUtil.truncateString(frames[i].getTitle(), 40)); associate(menuItem, frames[i]); windowMenu.add(menuItem); } if (windowMenu.getItemCount() == 0) { // For ezLink [Jon Aquino] windowMenu.add(new JMenuItem("(No Windows)")); } } private void associate(JMenuItem menuItem, final JInternalFrame frame) { menuItem.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { try { activateFrame((JInternalFrame) frame); } catch (Throwable t) { handleThrowable(t); } } }); } private void closeApplication() { if (confirmClose("Exit JUMP", getLayersWithModifiedFeatureCollections())) { // PersistentBlackboardPlugIn listens for when the workbench is // hidden [Jon Aquino] setVisible(false); // Invoke System#exit after all pending GUI events have been fired // (e.g. the hiding of this WorkbenchFrame) [Jon Aquino] SwingUtilities.invokeLater( new Runnable() { public void run() { System.exit(0); } }); } } private Collection getLayersWithModifiedFeatureCollections() { ArrayList layersWithModifiedFeatureCollections = new ArrayList(); for (Iterator i = getLayerManagers().iterator(); i.hasNext(); ) { LayerManager layerManager = (LayerManager) i.next(); layersWithModifiedFeatureCollections.addAll( layerManager.getLayersWithModifiedFeatureCollections()); } return layersWithModifiedFeatureCollections; } private Collection getLayerManagers() { // Multiple windows may point to the same LayerManager, so use // a Set. [Jon Aquino] HashSet layerManagers = new HashSet(); JInternalFrame[] internalFrames = getInternalFrames(); for (int i = 0; i < internalFrames.length; i++) { if (internalFrames[i] instanceof LayerManagerProxy) { layerManagers.add(((LayerManagerProxy) internalFrames[i]).getLayerManager()); } } return layerManagers; } private void configureStatusLabel(JLabel label, int width) { label.setMinimumSize(new Dimension(width, (int) label.getMinimumSize().getHeight())); label.setMaximumSize(new Dimension(width, (int) label.getMaximumSize().getHeight())); label.setPreferredSize(new Dimension(width, (int) label.getPreferredSize().getHeight())); } private void jbInit() throws Exception { setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); this.setIconImage(icon.getImage()); this.addComponentListener( new java.awt.event.ComponentAdapter() { public void componentShown(ComponentEvent e) { this_componentShown(e); } }); this.getContentPane().setLayout(borderLayout1); this.addWindowListener( new java.awt.event.WindowAdapter() { public void windowClosing(WindowEvent e) { this_windowClosing(e); } }); this.setJMenuBar(menuBar); // This size is chosen so that when the user hits the Info tool, the // window // fits between the lower edge of the TaskFrame and the lower edge of // the // WorkbenchFrame. See the call to #setSize in InfoFrame. [Jon Aquino] setSize(900, 665); // OUTLINE_DRAG_MODE is excruciatingly slow in JDK 1.4.1, so don't use // it. // (although it's supposed to be fixed in 1.4.2, which has not yet been // released). (see Sun Java Bug ID 4665237). [Jon Aquino] // desktopPane.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE); messageLabel.setOpaque(true); memoryLabel.setText("jLabel1"); wmsLabel.setHorizontalAlignment(SwingConstants.LEFT); wmsLabel.setText(" "); this.getContentPane().add(statusPanel, BorderLayout.SOUTH); exitMenuItem.addActionListener( new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { exitMenuItem_actionPerformed(e); } }); windowMenu.addMenuListener( new javax.swing.event.MenuListener() { public void menuCanceled(MenuEvent e) {} public void menuDeselected(MenuEvent e) {} public void menuSelected(MenuEvent e) { windowMenu_menuSelected(e); } }); coordinateLabel.setBorder(BorderFactory.createLoweredBevelBorder()); wmsLabel.setBorder(BorderFactory.createLoweredBevelBorder()); coordinateLabel.setText(" "); statusPanel.setLayout(gridBagLayout1); statusPanel.setBorder(BorderFactory.createRaisedBevelBorder()); messageLabel.setBorder(BorderFactory.createLoweredBevelBorder()); messageLabel.setText(" "); timeLabel.setBorder(BorderFactory.createLoweredBevelBorder()); timeLabel.setText(" "); memoryLabel.setBorder(BorderFactory.createLoweredBevelBorder()); memoryLabel.setText(" "); menuBar.add(fileMenu); menuBar.add(windowMenu); getContentPane().add(toolBar, BorderLayout.NORTH); getContentPane().add(desktopPane, BorderLayout.CENTER); fileMenu.addSeparator(); fileMenu.add(exitMenuItem); statusPanel.add( coordinateLabel, new GridBagConstraints( 5, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); statusPanel.add( timeLabel, new GridBagConstraints( 2, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); statusPanel.add( messageLabel, new GridBagConstraints( 1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); // Give memoryLabel the 1.0 weight. All the rest should have their // sizes // configured using #configureStatusLabel. [Jon Aquino] statusPanel.add( memoryLabel, new GridBagConstraints( 3, 1, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); statusPanel.add( wmsLabel, new GridBagConstraints( 4, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); } private void position(JInternalFrame internalFrame) { final int STEP = 5; GUIUtil.Location location = null; if (internalFrame instanceof PrimaryInfoFrame) { primaryInfoFrameIndex++; int offset = (primaryInfoFrameIndex % 3) * STEP; location = new GUIUtil.Location(offset, true, offset, true); } else { positionIndex++; int offset = (positionIndex % 5) * STEP; location = new GUIUtil.Location(offset, false, offset, false); } GUIUtil.setLocation((Component) internalFrame, location, desktopPane); } /** * Fundamental Style classes (like BasicStyle, VertexStyle, and LabelStyle) cannot be removed, and * are thus excluded from the choosable Style classes. */ public Set getChoosableStyleClasses() { return Collections.unmodifiableSet(choosableStyleClasses); } public void addChoosableStyleClass(Class choosableStyleClass) { Assert.isTrue(ChoosableStyle.class.isAssignableFrom(choosableStyleClass)); choosableStyleClasses.add(choosableStyleClass); } private HashMap keyCodeAndModifiersToPlugInAndEnableCheckMap = new HashMap(); /** * Adds a keyboard shortcut for a plugin. logs plugin exceptions. * * <p>note - attaching to keyCode 'a', modifiers =1 will detect shift-A events. It will *not* * detect caps-lock-'a'. This is due to inconsistencies in java.awt.event.KeyEvent. In the * unlikely event you actually do want to also also attach to caps-lock-'a', then make two * shortcuts - one to keyCode 'a' and modifiers =1 (shift-A) and one to keyCode 'A' and * modifiers=0 (caps-lock A). * * <p>For more details, see the java.awt.event.KeyEvent class - it has a full explaination. * * @param keyCode What key to attach to (See java.awt.event.KeyEvent) * @param modifiers 0= none, 1=shift, 2= cntrl, 8=alt, 3=shift+cntrl, etc... See the modifier mask * constants in the Event class * @param plugIn What plugin to execute * @param enableCheck Is the key enabled at the moment? */ public void addKeyboardShortcut( final int keyCode, final int modifiers, final PlugIn plugIn, final EnableCheck enableCheck) { // Overwrite existing shortcut [Jon Aquino] keyCodeAndModifiersToPlugInAndEnableCheckMap.put( keyCode + ":" + modifiers, new Object[] {plugIn, enableCheck}); } private void installKeyboardShortcutListener() { addEasyKeyListener( new KeyListener() { public void keyTyped(KeyEvent e) {} public void keyReleased(KeyEvent e) {} public void keyPressed(KeyEvent e) { Object[] plugInAndEnableCheck = (Object[]) keyCodeAndModifiersToPlugInAndEnableCheckMap.get( e.getKeyCode() + ":" + e.getModifiers()); if (plugInAndEnableCheck == null) { return; } PlugIn plugIn = (PlugIn) plugInAndEnableCheck[0]; EnableCheck enableCheck = (EnableCheck) plugInAndEnableCheck[1]; if (enableCheck != null && enableCheck.check(null) != null) { return; } // #toActionListener handles checking if the plugIn is a // ThreadedPlugIn, // and making calls to UndoableEditReceiver if necessary. [Jon // Aquino 10/15/2003] AbstractPlugIn.toActionListener(plugIn, workbenchContext, new TaskMonitorManager()) .actionPerformed(null); } }); } private boolean confirmClose(String action, Collection modifiedLayers) { if (modifiedLayers.isEmpty()) { return true; } JOptionPane pane = new JOptionPane( StringUtil.split( modifiedLayers.size() + " dataset" + StringUtil.s(modifiedLayers.size()) + " " + ((modifiedLayers.size() > 1) ? "have" : "has") + " been modified (" + ((modifiedLayers.size() > 3) ? "e.g. " : "") + StringUtil.toCommaDelimitedString( new ArrayList(modifiedLayers) .subList(0, Math.min(3, modifiedLayers.size()))) + "). Continue?", 80), JOptionPane.WARNING_MESSAGE); pane.setOptions(new String[] {action, "Cancel"}); pane.createDialog(this, AppContext.getMessage("GeopistaName")).setVisible(true); return pane.getValue().equals(action); } public WorkbenchToolBar getToolBar(String toolBarName) { return null; } /* (non-Javadoc) * @see com.geopista.editor.WorkbenchGuiComponent#getMainFrame() */ public JFrame getMainFrame() { return this; } public TaskComponent[] getInternalTaskComponents() { JInternalFrame[] internalFrames = desktopPane.getAllFrames(); TaskComponent[] taskComponents = new TaskComponent[internalFrames.length]; for (int n = 0; n < internalFrames.length; n++) { taskComponents[n] = (TaskComponent) internalFrames[n]; } return taskComponents; } public JPopupMenu getLayerViewPopupMenu() { // TODO Auto-generated method stub return popupMenu; } }