Package org.openquark.gems.client

Source Code of org.openquark.gems.client.GemCutterBrowserTreeExtensions$MouseListener

/*
* Copyright (c) 2007 BUSINESS OBJECTS SOFTWARE LIMITED
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
*     * Redistributions of source code must retain the above copyright notice,
*       this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in the
*       documentation and/or other materials provided with the distribution.
*     * Neither the name of Business Objects nor the names of its contributors
*       may be used to endorse or promote products derived from this software
*       without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/


/*
* GemCutterBrowserTreeExtensions.java
* Creation date: Oct 23, 2002.
* By: Edward Lam
*/
package org.openquark.gems.client;

import java.awt.Color;
import java.awt.Component;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JPopupMenu;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;

import org.openquark.cal.compiler.ModuleName;
import org.openquark.cal.module.Cal.Core.CAL_Prelude;
import org.openquark.cal.services.GemEntity;
import org.openquark.cal.services.ModuleRevision;
import org.openquark.cal.services.Vault;
import org.openquark.cal.services.VaultElementInfo;
import org.openquark.gems.client.AutoburnLogic.AutoburnUnifyStatus;
import org.openquark.gems.client.IntellicutManager.IntellicutInfo;
import org.openquark.gems.client.IntellicutManager.IntellicutMode;
import org.openquark.gems.client.browser.BrowserTree;
import org.openquark.gems.client.browser.BrowserTreeCellRenderer;
import org.openquark.gems.client.browser.BrowserTreeModel;
import org.openquark.gems.client.browser.BrowserTreeNode;
import org.openquark.gems.client.browser.GemDrawer;
import org.openquark.gems.client.browser.GemTreeNode;
import org.openquark.gems.client.browser.LeafNodeTriggeredEvent;
import org.openquark.gems.client.browser.LeafNodeTriggeredListener;
import org.openquark.util.UnsafeCast;
import org.openquark.util.ui.UIUtilities;


/**
* Extensions are declared as outer-inner classes in this file.
* @author Frank Worsley
*/
class GemCutterBrowserTreeExtensions {

    /**
     * The GemCutterVaultTreeCellRenderer is an extension to the BrowserTreeCellRenderer
     * that displays additional visual cues for intellicut.
     * @author Edward Lam
     */
    static class CellRenderer extends BrowserTreeCellRenderer {

        private static final long serialVersionUID = -7121628652443578657L;
        /** The icons representing the scope of gem tree nodes, to be added to gem icons */
        private static final ImageIcon SCOPE_PUBLIC_ICON = new ImageIcon(Object.class.getResource("/Resources/scope_public.gif"));
        private static final ImageIcon SCOPE_PROTECTED_ICON = new ImageIcon(Object.class.getResource("/Resources/scope_protected.gif"));
        private static final ImageIcon SCOPE_PRIVATE_ICON = new ImageIcon(Object.class.getResource("/Resources/scope_private.gif"));
       
        /** The little decal we add to the gem icon, if the gem has a design available. */
        private static final ImageIcon GEM_DESIGN_DECAL = new ImageIcon(CellRenderer.class.getResource("/Resources/gemDesignDecal.gif"));
   
        /** The icon to use for gems that can't be connected at all. */
        private static final ImageIcon CANNOT_CONNECT_ICON = new ImageIcon(CellRenderer.class.getResource("/Resources/noParking.gif"));
   
        /** The icon to use for gems that can only be connected via burning. */
        private static final ImageIcon BURN_ICON = TableTopPanel.burnImageIconSmall;
   
        /** The icon to use for gems that can be connected directly and via burning. */
        private static final ImageIcon AMBIGUOUS_ICON = TableTopPanel.burnQuestionImageIconSmall;
   
        /** The text color for gems that can not be connected at all. */
        private static final Color CANNOT_CONNECT_COLOR = UIManager.getColor("TextField.inactiveForeground");
   
        /** The text color to use for gems that can only be connected by burning. */
        private static final Color BURN_COLOR = Color.red;
   
        /** The text color to use for gems that can be connected directly or via burning. */
        private static final Color AMBIGUOUS_COLOR = Color.red;

        /** The GemCutter this renderer is for. */
        private final GemCutter gemCutter;

        // Cache for the scope decorated icons
        private final Map<Icon, Icon> imageCache_public = new HashMap<Icon, Icon>();
        private final Map<Icon, Icon> imageCache_protected = new HashMap<Icon, Icon>();
        private final Map<Icon, Icon> imageCache_private = new HashMap<Icon, Icon>();
       
       
        /**
         * Default GemCutterVaultTreeCellRenderer constructor.
         * @param gemCutter the GemCutter this renderer is for
         */
        public CellRenderer(GemCutter gemCutter) {
       
            if (gemCutter == null) {
                throw new NullPointerException();
            }
       
            this.gemCutter = gemCutter;
        }

        /**
         * {@inheritDoc}
         * We override this to draw items differently if Intellicut is active.
         */
        @Override
        public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {

            super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);

            BrowserTreeModel browserTreeModel = (BrowserTreeModel) tree.getModel();
            IntellicutManager intellicutManager = gemCutter.getIntellicutManager();
       
            if (intellicutManager.getIntellicutMode() == IntellicutMode.NOTHING) {
                // If Intellicut is not active

                if (value instanceof GemTreeNode) {
                  
                    // Add scope icon (public, protected, private) to the gem icon on the bottom right corner
                    // Uses a cache to store icons already combined
                    GemEntity entity = (GemEntity) ((GemTreeNode) value).getUserObject();
                    Icon baseGemIcon = getIcon();
                    Icon overlayIcon = null;
                    Map<Icon, Icon> cache = null;
                   
                    if (entity.getScope().isPublic()) {
                        cache = imageCache_public;
                        overlayIcon = SCOPE_PUBLIC_ICON;
                  
                    } else if (entity.getScope().isProtected()) {
                        cache = imageCache_protected;
                        overlayIcon = SCOPE_PROTECTED_ICON;

                    } else { //entity.getScope().isPrivate()
                        cache = imageCache_private;
                        overlayIcon = SCOPE_PRIVATE_ICON;
                    }

                    Icon cachedImage = cache.get(baseGemIcon);
                    if (cachedImage != null) {
                        setIcon(cachedImage);

                    } else {
                        Icon newIcon = UIUtilities.combineIcons(baseGemIcon, overlayIcon);
                        setIcon(newIcon);
                        cache.put(baseGemIcon, newIcon);
                    }

                    if (((GemTreeNode) value).hasDesign()) {
                        // Add a design decal to the gem icon
                        baseGemIcon = getIcon();
                        Icon newIcon = UIUtilities.combineIcons(baseGemIcon, GEM_DESIGN_DECAL);
                        setIcon(newIcon);
                    }
                }
           
                return this;
            }

            // If Intellicut is active, use special Intellicut icons to indicate Intellicut status.
       
            if (leaf) {
           
                // This is a gem. Give it an icon and text color that indicates how intellicut can connect it.
           
                GemEntity gemEntity = (GemEntity) ((GemTreeNode) value).getUserObject();
           
                if (browserTreeModel.isVisibleGem(gemEntity)) {
               
                    IntellicutInfo intellicutInfo = intellicutManager.getIntellicutInfo(gemEntity);
                    AutoburnUnifyStatus autoburnStatus = intellicutInfo.getAutoburnUnifyStatus();

                    if (autoburnStatus == AutoburnUnifyStatus.UNAMBIGUOUS) {
                        setIcon(BURN_ICON);
                        setForeground(BURN_COLOR);
                   
                    } else if (autoburnStatus == AutoburnUnifyStatus.AMBIGUOUS) {
                        setIcon(AMBIGUOUS_ICON);
                        setForeground(AMBIGUOUS_COLOR);
                   
                    } else if (autoburnStatus == AutoburnUnifyStatus.NOT_POSSIBLE) {
                        setIcon(CANNOT_CONNECT_ICON);
                        setForeground(CANNOT_CONNECT_COLOR);

                    } else if (autoburnStatus == AutoburnUnifyStatus.UNAMBIGUOUS_NOT_NECESSARY &&                   
                               intellicutInfo.getBurnTypeCloseness() > intellicutInfo.getNoBurnTypeCloseness()) {
                              
                        setIcon(BURN_ICON);
                        setForeground(BURN_COLOR);
               
                    } else if (autoburnStatus == AutoburnUnifyStatus.AMBIGUOUS_NOT_NECESSARY &&
                               intellicutInfo.getBurnTypeCloseness() > intellicutInfo.getNoBurnTypeCloseness()) {

                        setIcon(AMBIGUOUS_ICON);
                        setForeground(AMBIGUOUS_COLOR);
                    }
               
                } else {
                    setIcon(CANNOT_CONNECT_ICON);
                    setForeground(CANNOT_CONNECT_COLOR);               
                }
   
            } else {

                // This is a folder. Determine if and how it should pulse.

                // Assume we can't connect at all to start with.
                Color folderColor = CANNOT_CONNECT_COLOR;

                Enumeration<TreeNode> subTreeEnum = UnsafeCast.<Enumeration<TreeNode>>unsafeCast(((DefaultMutableTreeNode)value).breadthFirstEnumeration());
           
                while (subTreeEnum.hasMoreElements()) {

                    DefaultMutableTreeNode childTreeNode = (DefaultMutableTreeNode) subTreeEnum.nextElement();
               
                    if (childTreeNode instanceof GemTreeNode) {

                        GemEntity gemEntity = (GemEntity) childTreeNode.getUserObject();

                        if (browserTreeModel.isVisibleGem(gemEntity)) {

                            IntellicutInfo intellicutInfo = intellicutManager.getIntellicutInfo(gemEntity);
                            AutoburnUnifyStatus autoburnStatus = intellicutInfo.getAutoburnUnifyStatus();

                            if (autoburnStatus == AutoburnUnifyStatus.NOT_NECESSARY) {
                                // Connections take precedence. If we find a connection then stop.
                                folderColor = null;
                                break;
                           
                            } else if (autoburnStatus == AutoburnUnifyStatus.UNAMBIGUOUS ||
                                       autoburnStatus == AutoburnUnifyStatus.AMBIGUOUS) {

                                folderColor = BURN_COLOR;

                             } else if ((autoburnStatus == AutoburnUnifyStatus.UNAMBIGUOUS_NOT_NECESSARY ||
                                        autoburnStatus == AutoburnUnifyStatus.AMBIGUOUS_NOT_NECESSARY)) {
                                       
                                if (intellicutInfo.getBurnTypeCloseness() > intellicutInfo.getNoBurnTypeCloseness()) {
                                    folderColor = BURN_COLOR;
                                } else {
                                    folderColor = null;
                                    break;
                                }
                             }
                        }
                    }
                }
           
                if (folderColor != null) {
                    setForeground(folderColor);
                }
            }

            return this;
        }
    }

    /**
     * A customized popup menu provider for the BrowserTree. It adds GemCutter specific menu items.
     * @author Frank Worsley
     */
    static class PopupMenuProvider implements BrowserTree.PopupMenuProvider {
   
        /** The GemCutter this provider is for. */
        private final GemCutter gemCutter;
   
        /**
         * Constructor for a new GemCutterVaultTreePopupMenuProvider.
         * @param gemCutter the GemCutter the provider is for
         */
        public PopupMenuProvider(GemCutter gemCutter) {
       
            if (gemCutter == null) {
                throw new NullPointerException();
            }
       
            this.gemCutter = gemCutter;
        }
   
        /**
         * @see org.openquark.gems.client.browser.BrowserTree.PopupMenuProvider#getPopupMenu(javax.swing.tree.TreePath)
         */
        public JPopupMenu getPopupMenu(TreePath selectionPath) {

            // Create the popup menu so we can add our custom items.
            JPopupMenu popupMenu = new JPopupMenu();

            BrowserTreeNode selectedNode = (selectionPath == null) ? null : (BrowserTreeNode) selectionPath.getLastPathComponent();

            if (selectedNode instanceof GemDrawer) {
                // The node represents a "module".
               
                if (((GemDrawer)selectedNode).isNamespaceNode()) {
                    // a module namespace node is a 'phantom' node that does not really
                    // correspond to an actual module
                   
                } else {
                    // Add the 'Change Working Module' menu item.
                    ModuleName moduleName = ((GemDrawer) selectedNode).getModuleName();
                    Action changeModuleAction = getChangeModuleAction(moduleName);
                    popupMenu.add(GemCutter.makeNewMenuItem(changeModuleAction));

                    // Add a separator.
                    popupMenu.addSeparator();

                    // Add menu items for the workspace.
                    popupMenu.add(GemCutter.makeNewMenuItem(getSyncModuleAction(moduleName)));
                    popupMenu.add(GemCutter.makeNewMenuItem(getSyncModuleToRevisionAction(moduleName)));
                    popupMenu.add(GemCutter.makeNewMenuItem(getRevertModuleAction(moduleName)));
                    popupMenu.addSeparator();
                    popupMenu.add(GemCutter.makeNewMenuItem(getAddTypeDeclsToModuleAction(moduleName)));
                    popupMenu.add(GemCutter.makeNewMenuItem(getCleanModuleImportsAction(moduleName)));
                    popupMenu.add(GemCutter.makeNewMenuItem(getRenameModuleAction(moduleName)));
                    popupMenu.add(GemCutter.makeNewMenuItem(getRemoveModuleAction(moduleName)));
                }
                   
            } else if (selectedNode instanceof GemTreeNode) {
                // The node represents a gem.
                // Add a 'Load Design...' menu item to load the gem design.
           
                GemEntity gemEntity = (GemEntity) selectedNode.getUserObject();
                popupMenu.add(GemCutter.makeNewMenuItem(getOpenDesignAction(gemEntity)));
                popupMenu.add(GemCutter.makeNewMenuItem(getRenameGemAction(gemEntity)));
                popupMenu.add(GemCutter.makeNewMenuItem(getSearchForGemAction(gemEntity)));
                popupMenu.add(GemCutter.makeNewMenuItem(getSearchForGemDefinitionAction(gemEntity)));
            }
                   
            if (popupMenu.getComponentCount() > 0) {
                popupMenu.addSeparator();
            }

            // Add the default menu items.
            gemCutter.getBrowserTree().getBrowserTreeActions().addDefaultMenuItems(popupMenu, selectedNode);

            return popupMenu;
        }
   
   
        /**
         * @param gemEntity the entity to load a saved design for
         * @return an action to load a saved design.
         */
        private Action getOpenDesignAction(final GemEntity gemEntity) {
       
            Action loadDesignAction = new AbstractAction(GemCutter.getResourceString("OpenDesign")) {
                private static final long serialVersionUID = -7655463979081031688L;

                public void actionPerformed(ActionEvent e) {
                    gemCutter.openGemDesign(gemEntity);
                }
            };
       
            loadDesignAction.putValue(Action.SMALL_ICON, new ImageIcon(GemCutter.class.getResource("/Resources/open.gif")));
            loadDesignAction.putValue(Action.SHORT_DESCRIPTION, GemCutter.getResourceString("OpenDesignToolTip"));       
            loadDesignAction.setEnabled(gemCutter.getGUIState() == GemCutter.GUIState.EDIT && gemEntity.hasDesign());
       
            return loadDesignAction;
        }
       
        private Action getRenameModuleAction(final ModuleName moduleName) {
            Action renameModuleAction = new AbstractAction(GemCutter.getResourceString("RenameModule")) {
                private static final long serialVersionUID = 4668938145711913122L;

                public void actionPerformed(ActionEvent e) {
                    gemCutter.showRenameModuleDialog(moduleName);
                }
            };
           
            renameModuleAction.putValue(Action.SHORT_DESCRIPTION, GemCutter.getResourceString("RenameModuleToolTip"));
            renameModuleAction.setEnabled(gemCutter.getGUIState() == GemCutter.GUIState.EDIT &&
                    (!moduleName.equals(CAL_Prelude.MODULE_NAME) || gemCutter.isAllowPreludeRenamingMode()));
           
            return renameModuleAction;
        }
       
        /**
         * @param gemEntity the entity to rename
         * @return an action to popup the rename refactoring dialog.
         */
        private Action getRenameGemAction(final GemEntity gemEntity) {
       
            Action renameGemAction = new AbstractAction(GemCutter.getResourceString("RenameGem")) {
                private static final long serialVersionUID = 5715650083979358935L;

                public void actionPerformed(ActionEvent e) {
                    gemCutter.showRenameEntityDialog(RenameRefactoringDialog.EntityType.Gem, gemEntity.getName().getQualifiedName());
                }
            };
       
            renameGemAction.putValue(Action.SHORT_DESCRIPTION, GemCutter.getResourceString("RenameGemToolTip"));       
            renameGemAction.setEnabled(gemCutter.getGUIState() == GemCutter.GUIState.EDIT &&
                    ((!gemEntity.getName().getModuleName().equals(CAL_Prelude.MODULE_NAME))
                    || gemCutter.isAllowPreludeRenamingMode()));
       
            return renameGemAction;
        }

        /**
         * @param gemEntity the entity to search for
         * @return an action to popup the search dialog with the qualified name of the
         *          currently-selected gem filled in.
         */
        private Action getSearchForGemAction(final GemEntity gemEntity) {
           
            Action searchForGemAction = new AbstractAction(GemCutter.getResourceString("SearchForGemPopup")) {
                private static final long serialVersionUID = -6698686245610450051L;

                public void actionPerformed(ActionEvent e) {
                    SearchDialog searchDialog = gemCutter.showSearchDialog();
                    searchDialog.performSearch(gemEntity.getName().getQualifiedName(), SearchDialog.SearchType.REFERENCES);
                }
            };

            searchForGemAction.putValue(Action.MNEMONIC_KEY, Integer.valueOf(GemCutterActionKeys.MNEMONIC_SEARCH));
            searchForGemAction.putValue(Action.SHORT_DESCRIPTION, GemCutter.getResourceString("SearchForGemPopupToolTip"));
            searchForGemAction.setEnabled(!gemCutter.isSearchPending());
           
            return searchForGemAction;
        }   
       
        /**
         * @param gemEntity the entity to search for the definition of
         * @return an action to popup the search dialog with the qualified name of the
         *          currently-selected gem filled in.
         */
        private Action getSearchForGemDefinitionAction(final GemEntity gemEntity) {
           
            Action searchForGemDefinitionAction = new AbstractAction(GemCutter.getResourceString("SearchForGemDefinitionPopup")) {
                private static final long serialVersionUID = 8119618611507146279L;

                public void actionPerformed(ActionEvent e) {
                    SearchDialog searchDialog = gemCutter.showSearchDialog();
                    searchDialog.performSearch(gemEntity.getName().getQualifiedName(), SearchDialog.SearchType.DEFINITION);
                }
            };

            searchForGemDefinitionAction.putValue(Action.SHORT_DESCRIPTION, GemCutter.getResourceString("SearchForGemDefinitionPopupToolTip"));
            searchForGemDefinitionAction.setEnabled(!gemCutter.isSearchPending());
           
            return searchForGemDefinitionAction;
        }   
       
        /**
         * Return a new action to change the module
         * @param newModuleName the name of the module to which to change.
         * @return Action the new action.
         */
        private Action getChangeModuleAction(final ModuleName newModuleName) {
       
            Action changeModuleAction = new AbstractAction (GemCutter.getResourceString("ChangeModulePopup")) {
                private static final long serialVersionUID = 7260606500969827421L;

                public void actionPerformed(ActionEvent evt) {
                    gemCutter.doChangeModuleUserAction(newModuleName);
                }
            };
       
            changeModuleAction.putValue(Action.SHORT_DESCRIPTION, GemCutter.getResourceString("ChangeModulePopupToolTip"));
            changeModuleAction.setEnabled(gemCutter.getGUIState() == GemCutter.GUIState.EDIT &&
                                          !newModuleName.equals(gemCutter.getWorkingModuleName()));
           
            return changeModuleAction;
        }
       
        /**
         * Return a new action to perform the Add Type Declarations refactoring on a module
         * @param targetModule String name of the module to refactor
         * @return Action the new action
         */
        private Action getAddTypeDeclsToModuleAction(final ModuleName targetModule) {
       
            Action addTypeDeclsAction = new AbstractAction (GemCutter.getResourceString("AddTypedeclsPopup")) {
                private static final long serialVersionUID = 4895749473356263923L;

                public void actionPerformed(ActionEvent evt) {
                    gemCutter.doAddTypeDeclsUserAction(targetModule);
                }
            };
       
            addTypeDeclsAction.putValue(Action.SHORT_DESCRIPTION, GemCutter.getResourceString("AddTypedeclsPopupToolTip"));
            addTypeDeclsAction.setEnabled(gemCutter.getGUIState() == GemCutter.GUIState.EDIT);
           
            return addTypeDeclsAction;
        }

        /**
         * Return a new action to perform the Clean Imports refactoring on a module
         * @param targetModule String name of the module to refactor
         * @return Action the new action
         */
        private Action getCleanModuleImportsAction(final ModuleName targetModule) {
       
            Action cleanImportsAction = new AbstractAction (GemCutter.getResourceString("CleanImportsPopup")) {
                private static final long serialVersionUID = 5792348192459545571L;

                public void actionPerformed(ActionEvent evt) {
                    gemCutter.doCleanImportsUserAction(targetModule);
                }
            };
       
            cleanImportsAction.putValue(Action.SHORT_DESCRIPTION, GemCutter.getResourceString("CleanImportsPopupToolTip"));
            cleanImportsAction.setEnabled(gemCutter.getGUIState() == GemCutter.GUIState.EDIT);
           
            return cleanImportsAction;
        }

        /**
         * Return a new action to remove a module from the workspace.
         * @param moduleNameToRemove the name of the module to remove from the workspace.
         * @return Action the new action.
         */
        private Action getRemoveModuleAction(final ModuleName moduleNameToRemove) {
       
            Action syncModuleAction = new AbstractAction (GemCutter.getResourceString("RemoveModulePopup")) {
                private static final long serialVersionUID = 7205929596263407738L;

                public void actionPerformed(ActionEvent evt) {
                    gemCutter.doRemoveModuleUserAction(moduleNameToRemove);
                }
            };
       
            syncModuleAction.putValue(Action.SHORT_DESCRIPTION, GemCutter.getResourceString("RemoveModulePopupToolTip"));
            syncModuleAction.setEnabled(gemCutter.getGUIState() == GemCutter.GUIState.EDIT &&
                                        !moduleNameToRemove.equals(CAL_Prelude.MODULE_NAME));
           
            return syncModuleAction;
        }
       
        /**
         * Return a new action to sync a module
         * @param moduleNameToSync the name of the module to sync with its vault.
         * @return Action the new action.
         */
        private Action getSyncModuleAction(final ModuleName moduleNameToSync) {
       
            Action syncModuleAction = new AbstractAction (GemCutter.getResourceString("SyncModulePopup")) {
                private static final long serialVersionUID = -2098576892178968782L;

                public void actionPerformed(ActionEvent evt) {
                    gemCutter.doSyncModulesToLatestUserAction(Collections.singletonList(moduleNameToSync));
                }
            };
       
            syncModuleAction.putValue(Action.SHORT_DESCRIPTION, GemCutter.getResourceString("SyncModulePopupToolTip"));
            syncModuleAction.setEnabled(gemCutter.getGUIState() == GemCutter.GUIState.EDIT);
           
            return syncModuleAction;
        }
       
        /**
         * Return a new action to sync a module to a given revision
         * @param moduleNameToSync the name of the module to sync with its vault.
         * @return Action the new action.
         */
        private Action getSyncModuleToRevisionAction(final ModuleName moduleNameToSync) {
       
            Action syncModuleToRevisionAction = new AbstractAction (GemCutter.getResourceString("SyncModuleToRevisionPopup")) {
               
                private static final long serialVersionUID = 2447645113483308106L;

                public void actionPerformed(ActionEvent evt) {
                    // Get the associated vault.
                    Vault vault = gemCutter.getWorkspace().getVault(moduleNameToSync);
                   
                    // Show a dialog to get the revision with which to sync.
                    VaultRevisionChooser revisionChooserDialog = new VaultRevisionChooser(gemCutter, vault, true);
                    Integer selectedRevision = revisionChooserDialog.showDialog(moduleNameToSync.toSourceText());
                   
                    // If any revision was selected, sync.
                    if (selectedRevision != null) {
                        int selectedRevisionNum = selectedRevision.intValue();
                        ModuleRevision moduleRevision = new ModuleRevision(moduleNameToSync, selectedRevisionNum);
                        gemCutter.doSyncModulesUserAction(Collections.singletonList(moduleRevision), false);
                    }
                }
            };
       
            syncModuleToRevisionAction.putValue(Action.SHORT_DESCRIPTION, GemCutter.getResourceString("SyncModuleToRevisionPopupToolTip"));
            syncModuleToRevisionAction.setEnabled(gemCutter.getGUIState() == GemCutter.GUIState.EDIT);
           
            return syncModuleToRevisionAction;
        }

        /**
         * Return a new action to sync a module to a given revision
         * @param moduleNameToSync the name of the module to sync with its vault.
         * @return Action the new action.
         */
        private Action getRevertModuleAction(final ModuleName moduleNameToSync) {
            final VaultElementInfo vaultInfo = gemCutter.getWorkspace().getVaultInfo(moduleNameToSync);
            boolean hasVaultInfo = vaultInfo != null;
           
            Action revertModuleAction = new AbstractAction (GemCutter.getResourceString("RevertModulePopup")) {
                private static final long serialVersionUID = 5546677553785665358L;

                public void actionPerformed(ActionEvent evt) {
                    int moduleRevision = vaultInfo.getRevision();       // shouldn't be null.
                    gemCutter.doSyncModulesUserAction(Collections.singletonList(new ModuleRevision(moduleNameToSync, moduleRevision)), true);
                }
            };
           
            // Calculate whether the action should be enabled..
            boolean enableRevert;
            if (gemCutter.getGUIState() != GemCutter.GUIState.EDIT || !hasVaultInfo) {
                enableRevert = false;
           
            } else {
                // Getting the vault status communicates with the vault.
                // This might lead to the undesirable situation where invoking the popup prompts for log on to Enterprise.
               
//                // enabled if the module is modified.
//                VaultStatus moduleVaultStatus = gemCutter.getWorkspace().getVaultStatus(moduleNameToSync);
//                enableRevert = moduleVaultStatus.isModuleModified(moduleNameToSync);
               
                enableRevert = true;
            }
           
            revertModuleAction.putValue(Action.SHORT_DESCRIPTION, GemCutter.getResourceString("RevertModulePopupToolTip"));
            revertModuleAction.setEnabled(enableRevert);
           
            return revertModuleAction;
        }

    }

   
    /**
     * This listener will add gems from the gem browser to the table top. They are connected
     * using intellicut if intellicut is active.
     * @author Frank Worsley
     */
    static class LeafNodeListener implements LeafNodeTriggeredListener {

        /** The GemCutter this listener is for. */
        private final GemCutter gemCutter;
   
        /**
         * Constructor for a new GemCutterVaultTreeLeafNodeListener.
         * @param gemCutter the GemCutter the listener is for
         */
        public LeafNodeListener(GemCutter gemCutter) {
       
            if (gemCutter == null) {
                throw new NullPointerException();
            }
       
            this.gemCutter = gemCutter;
        }
   
        /**
         * @see org.openquark.gems.client.browser.LeafNodeTriggeredListener#leafNodeTriggered(org.openquark.gems.client.browser.LeafNodeTriggeredEvent)
         */
        public void leafNodeTriggered(LeafNodeTriggeredEvent evt) {

            IntellicutManager intellicutManager = gemCutter.getIntellicutManager();
            TableTop tableTop = gemCutter.getTableTop();
       
            BrowserTreeModel browserTreeModel = (BrowserTreeModel) gemCutter.getBrowserTree().getModel();
           
            if (intellicutManager.getIntellicutMode() != IntellicutMode.NOTHING) {

                // evt.getTriggeredObjects() could be empty if a module is selected
                if (!evt.getTriggeredObjects().isEmpty()){
                    Object obj = evt.getTriggeredObjects().get(0);

                    if (obj instanceof GemEntity) {

                        GemEntity gemEntity = (GemEntity) obj;
                        IntellicutInfo intellicutInfo = intellicutManager.getIntellicutInfo(gemEntity);
                        AutoburnUnifyStatus autoburnStatus = intellicutInfo.getAutoburnUnifyStatus();

                        if (autoburnStatus != AutoburnUnifyStatus.NOT_POSSIBLE) {

                            tableTop.getUndoableEditSupport().beginUpdate();

                            // Add the new gem to the table top.
                            DisplayedGem dGem = gemCutter.getTableTop().createDisplayedFunctionalAgentGem(new Point(), gemEntity);
                            Point location = tableTop.findAvailableDisplayedGemLocation(dGem);
                            tableTop.doAddGemUserAction(dGem, location);

                            intellicutManager.attemptIntellicutAutoConnect(dGem);
                            intellicutManager.stopIntellicut();

                            // Set the proper undo name.
                            tableTop.getUndoableEditSupport().setEditName(GemCutterMessages.getString("UndoText_Add", dGem.getDisplayText()));                       
                            tableTop.getUndoableEditSupport().endUpdate();
                        }
                    }
                }

            } else {

                gemCutter.getTableTop().getUndoableEditSupport().beginUpdate();

                List<Object> triggeredObjects = evt.getTriggeredObjects();
               
                for (final Object triggeredObj : triggeredObjects) {
   
                    if (triggeredObj instanceof GemEntity) {
                       
                        GemEntity gemEntity = (GemEntity) triggeredObj;
                       
                        if (browserTreeModel.isVisibleGem(gemEntity)) {
                            DisplayedGem dGem = gemCutter.getTableTop().createDisplayedFunctionalAgentGem(new Point(), gemEntity);
                            gemCutter.getTableTop().doAddGemUserAction(dGem);
                        }
                           
                        // TODO: in future we may want to warn the user if they are trying to add an entity from a module
                        //   which is not visible, and give them the option of importing it.
                    }
                }
   
                // Override the default undo name if more than one gem was added.
                if (triggeredObjects.size() > 1) {
                    gemCutter.getTableTop().getUndoableEditSupport().setEditName(GemCutter.getResourceString("UndoText_AddGems"));
                }

                gemCutter.getTableTop().getUndoableEditSupport().endUpdate();
            }
        }
    }

    /**
     * If intellicut is pulsing this will display a status message if
     * the user hovers the mouse over a gem in the gem browser.
     * @author Edward Lam
     */
    static class MouseListener extends MouseMotionAdapter {

        /** The GemCutter the mouse listener is for. */
        private final GemCutter gemCutter;
   
        /**
         * Constructs a new GemCutterVaultTreeMouseListener
         * @param gemCutter the GemCutter the listener is for
         */
        public MouseListener(GemCutter gemCutter) {
       
            if (gemCutter == null) {
                throw new NullPointerException();
            }
       
            this.gemCutter = gemCutter;
        }
   
        /**
         * @see java.awt.event.MouseMotionListener#mouseMoved(java.awt.event.MouseEvent)
         */
        @Override
        public void mouseMoved(MouseEvent e) {

            IntellicutManager intellicutManager = gemCutter.getIntellicutManager();
            StatusMessageDisplayer statusMessageDisplayer = gemCutter.getStatusMessageDisplayer();
       
            TreePath path = gemCutter.getBrowserTree().getPathForLocation(e.getX(), e.getY());
            Object lastPathComponent = path != null ? path.getLastPathComponent() : null;

            if (!(lastPathComponent instanceof GemTreeNode)) {
                statusMessageDisplayer.clearMessage(this);

            } else {

                // If we've hovering over a gem display an appropriate message
                GemTreeNode treeNode = (GemTreeNode) lastPathComponent;
                GemEntity gemEntity = (GemEntity) treeNode.getUserObject();

                if (intellicutManager.getIntellicutMode() == IntellicutManager.IntellicutMode.NOTHING) {
                    statusMessageDisplayer.clearMessage(this);

                } else if (((BrowserTreeModel) gemCutter.getBrowserTree().getModel()).isVisibleGem(gemEntity)) {

                    IntellicutInfo intellicutInfo = intellicutManager.getIntellicutInfo(gemEntity);
                    AutoburnUnifyStatus autoburnStatus = intellicutInfo.getAutoburnUnifyStatus();

                    if (autoburnStatus.isAutoConnectable()) {
                        statusMessageDisplayer.setMessageFromResource(this, "SM_IntellicutGemConnectable", StatusMessageDisplayer.MessageType.PERSISTENT);
                    } else {
                        statusMessageDisplayer.clearMessage(this);
                    }

                } else {
                    statusMessageDisplayer.clearMessage(this);
                }
            }
        }
    }
}
TOP

Related Classes of org.openquark.gems.client.GemCutterBrowserTreeExtensions$MouseListener

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.