/********************************************************************************
* *
* (c) Copyright 2010 Verizon Communications USA and The Open University UK *
* *
* This software is freely distributed in accordance with *
* the GNU Lesser General Public (LGPL) license, version 3 or later *
* as published by the Free Software Foundation. *
* For details see LGPL: http://www.fsf.org/licensing/licenses/lgpl.html *
* and GPL: http://www.fsf.org/licensing/licenses/gpl-3.0.html *
* *
* 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. *
* *
********************************************************************************/
package com.compendium.ui.popups;
import java.awt.AWTException;
import java.awt.Point;
import java.awt.Robot;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.SwingUtilities;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.compendium.LanguageProperties;
import com.compendium.ProjectCompendium;
import com.compendium.core.ICoreConstants;
import com.compendium.core.datamodel.Code;
import com.compendium.core.datamodel.IModel;
import com.compendium.core.datamodel.NodeSummary;
import com.compendium.core.datamodel.PCSession;
import com.compendium.core.datamodel.ShortCutNodeSummary;
import com.compendium.core.datamodel.View;
import com.compendium.ui.IUIArrange;
import com.compendium.ui.UIAlign;
import com.compendium.ui.UILink;
import com.compendium.ui.UIMapViewFrame;
import com.compendium.ui.UINode;
import com.compendium.ui.UIUtilities;
import com.compendium.ui.UIViewPane;
import com.compendium.ui.dialogs.UIExportDialog;
import com.compendium.ui.dialogs.UIExportViewDialog;
import com.compendium.ui.dialogs.UIImportDialog;
import com.compendium.ui.edits.DeleteEdit;
import com.compendium.ui.plaf.NodeUI;
import com.compendium.ui.plaf.ViewPaneUI;
import com.compendium.ui.stencils.DraggableStencilIcon;
/**
* This class has generic methods for the right-click menu options for
* map and map node right-click menus
*
* @author Michelle Bachler
*/
public abstract class UIBaseMapPopupMenu extends UIBasePopupMenu implements ActionListener{
/**
* class's own logger
*/
final Logger log = LoggerFactory.getLogger(getClass());
/** The JMenu to perform a arrange operation.*/
protected JMenu mnuArrange = null;
/** The JMenuItem to perform a arrange operation.*/
protected JMenuItem miMenuItemLeftRightArrange = null;
/** The JMenuItem to perform a arrange operation.*/
protected JMenuItem miMenuItemTopDownArrange = null;
/** The JMenu to perform a arrange operation.*/
protected JMenu mnuViewAlign = null;
/** The JMenuItem to perform a arrange operation.*/
protected JMenuItem miMenuItemAlignTop = null;
/** The JMenuItem to perform a arrange operation.*/
protected JMenuItem miMenuItemAlignMiddle = null;
/** The JMenuItem to perform a arrange operation.*/
protected JMenuItem miMenuItemAlignBottom = null;
/** The JMenuItem to perform a arrange operation.*/
protected JMenuItem miMenuItemAlignLeft = null;
/** The JMenuItem to perform a arrange operation.*/
protected JMenuItem miMenuItemAlignCenter = null;
/** The JMenuItem to perform a arrange operation.*/
protected JMenuItem miMenuItemAlignRight = null;
/** The JMenuItem to delink the currently selected nodes, or the node associated with this popup.*/
protected JMenuItem miMenuItemDelink = null;
/** The JMenuItem to import an external folder of image files into the current map.*/
protected JMenuItem miImportImageFolder = null;
/** JMenuItem to export the current map to a Jpge file.*/
protected JMenuItem miSaveAsJpeg = null;
/** The ViewPaneUI associated with this popup menu.*/
protected ViewPaneUI oViewPaneUI = null;
/** The UIViewPane associated with this popup menu.*/
protected UIViewPane oViewPane = null;
/**
* Constructor.
* @param title the title for this popup menu.
*/
public UIBaseMapPopupMenu(String title) {
super(title);
}
/**
* Constructor. Create the menus and items and draws the popup menu.
* @param title, the title for this popup menu.
* @param viewpaneUI com.compendium.ui.plaf.ViewPaneUI, the associated map for this popup menu.
*/
public UIBaseMapPopupMenu(String title, ViewPaneUI viewpaneUI) {
super(title);
setViewPaneUI(viewpaneUI);
init();
}
/**
* Add the menu noption to save the current map as a JPeg.
*/
protected void addSaveAsJPEG() {
miSaveAsJpeg = new JMenuItem(LanguageProperties.getString(LanguageProperties.POPUPS_BUNDLE, "UIBaseMapPopupMenu.jpegFile")); //$NON-NLS-1$
miSaveAsJpeg.addActionListener(this);
mnuExport.add(miSaveAsJpeg);
}
/**
* Add the menu item to import and image folder.
*/
protected void addImportImage() {
miImportImageFolder = new JMenuItem(LanguageProperties.getString(LanguageProperties.POPUPS_BUNDLE, "UIBaseMapPopupMenu.imageFolder")); //$NON-NLS-1$
miImportImageFolder.addActionListener(this);
mnuImport.add(miImportImageFolder);
}
/**
* Add the menu item to delink selected nodes.
*/
protected void addDelink() {
miMenuItemDelink = new JMenuItem(LanguageProperties.getString(LanguageProperties.POPUPS_BUNDLE, "UIBaseMapPopupMenu.delink")); //$NON-NLS-1$
miMenuItemDelink.addActionListener(this);
add(miMenuItemDelink);
}
/**
* Create the arrange submenu and items
*/
protected void createArrangeMenu() {
// Begin edit, Lakshmi (11/3/05)
// include Top - Down and Left - Right Option in Arrange Menu.
mnuArrange = new JMenu(LanguageProperties.getString(LanguageProperties.POPUPS_BUNDLE, "UIBaseMapPopupMenu.arrange")); //$NON-NLS-1$
mnuArrange.addActionListener(this);
miMenuItemLeftRightArrange = new JMenuItem(LanguageProperties.getString(LanguageProperties.POPUPS_BUNDLE, "UIBaseMapPopupMenu.leftToRight")); //$NON-NLS-1$
miMenuItemLeftRightArrange.addActionListener(this);
mnuArrange.add(miMenuItemLeftRightArrange);
mnuArrange.addSeparator();
miMenuItemTopDownArrange = new JMenuItem(LanguageProperties.getString(LanguageProperties.POPUPS_BUNDLE, "UIBaseMapPopupMenu.topDown")); //$NON-NLS-1$
miMenuItemTopDownArrange.addActionListener(this);
mnuArrange.add(miMenuItemTopDownArrange);
add(mnuArrange);
}
/**
* Create the view align submenu and items
*/
protected void createViewAlignMenu() {
mnuViewAlign = new JMenu(LanguageProperties.getString(LanguageProperties.POPUPS_BUNDLE, "UIBaseMapPopupMenu.align")); //$NON-NLS-1$
mnuViewAlign.setEnabled(true);
miMenuItemAlignLeft = new JMenuItem(LanguageProperties.getString(LanguageProperties.POPUPS_BUNDLE, "UIBaseMapPopupMenu.left")); //$NON-NLS-1$
miMenuItemAlignLeft.addActionListener(this);
mnuViewAlign.add(miMenuItemAlignLeft);
miMenuItemAlignCenter = new JMenuItem(LanguageProperties.getString(LanguageProperties.POPUPS_BUNDLE, "UIBaseMapPopupMenu.center")); //$NON-NLS-1$
miMenuItemAlignCenter.addActionListener(this);
mnuViewAlign.add(miMenuItemAlignCenter);
miMenuItemAlignRight = new JMenuItem(LanguageProperties.getString(LanguageProperties.POPUPS_BUNDLE, "UIBaseMapPopupMenu.right")); //$NON-NLS-1$
miMenuItemAlignRight.addActionListener(this);
mnuViewAlign.add(miMenuItemAlignRight);
mnuViewAlign.addSeparator();
miMenuItemAlignTop = new JMenuItem(LanguageProperties.getString(LanguageProperties.POPUPS_BUNDLE, "UIBaseMapPopupMenu.top")); //$NON-NLS-1$
miMenuItemAlignTop.addActionListener(this);
mnuViewAlign.add(miMenuItemAlignTop);
miMenuItemAlignMiddle = new JMenuItem(LanguageProperties.getString(LanguageProperties.POPUPS_BUNDLE, "UIBaseMapPopupMenu.middle")); //$NON-NLS-1$
miMenuItemAlignMiddle.addActionListener(this);
mnuViewAlign.add(miMenuItemAlignMiddle);
miMenuItemAlignBottom = new JMenuItem(LanguageProperties.getString(LanguageProperties.POPUPS_BUNDLE, "UIBaseMapPopupMenu.bottom")); //$NON-NLS-1$
miMenuItemAlignBottom.addActionListener(this);
mnuViewAlign.add(miMenuItemAlignBottom);
add(mnuViewAlign);
}
/**
* Set the UIViewPane associated with this popup menu.
* @param viewPane com.compendium.ui.UIViewPane, the UIViewPane associated with this popup menu.
*/
public void setViewPane(UIViewPane viewPane) {
oViewPane = viewPane;
}
/**
* Set the associated ViewPaneUI.
* @param viewpaneUI com.compendium.ui.plaf.ViewPaneUI, the associated map for this popup menu.
*/
public void setViewPaneUI(ViewPaneUI viewpaneUI) {
oViewPaneUI = viewpaneUI;
oViewPane = oViewPaneUI.getViewPane();
}
/**
* Handles the event of an option being selected.
* @param evt, the event associated with the option being selected.
*/
public void actionPerformed(ActionEvent evt) {
ProjectCompendium.APP.setWaitCursor();
Object source = evt.getSource();
if(source.equals(miMenuItemTopDownArrange)) {
ProjectCompendium.APP.onViewArrange(IUIArrange.TOPDOWN);
}
else if(source.equals(miMenuItemLeftRightArrange)) {
ProjectCompendium.APP.onViewArrange(IUIArrange.LEFTRIGHT);
}
else if(source.equals(miMenuItemAlignTop))
ProjectCompendium.APP.onViewAlign(UIAlign.TOP);
else if(source.equals(miMenuItemAlignCenter))
ProjectCompendium.APP.onViewAlign(UIAlign.CENTER);
else if(source.equals(miMenuItemAlignBottom))
ProjectCompendium.APP.onViewAlign(UIAlign.BOTTOM);
else if(source.equals(miMenuItemAlignRight))
ProjectCompendium.APP.onViewAlign(UIAlign.RIGHT);
else if(source.equals(miMenuItemAlignMiddle))
ProjectCompendium.APP.onViewAlign(UIAlign.MIDDLE);
else if(source.equals(miMenuItemAlignLeft))
ProjectCompendium.APP.onViewAlign(UIAlign.LEFT);
else if (source.equals(miImportImageFolder)) {
importImageFolder();
} else if(source.equals(miMenuItemDelink)) {
delinkNodes();
} else if (source.equals(miSaveAsJpeg)) {
ProjectCompendium.APP.onSaveAsJpeg();
} else {
super.actionPerformed(evt);
}
ProjectCompendium.APP.setDefaultCursor();
}
/**
* Change the type of the selected nodes to the given stencil item
* Subclasses should implement this method.
*/
protected void changeStencilType(DraggableStencilIcon item) {
String sImage = item.getImage();
String sBackgroundImage = item.getBackgroundImage();
String sTemplate = item.getTemplate();
String sLabel = item.getLabel();
int nType = item.getNodeType();
Vector vtTags = item.getTags();
String sAuthor= oViewPane.getCurrentAuthor();
for(Enumeration e = oViewPane.getSelectedNodes();e.hasMoreElements();) {
UINode uinode = (UINode)e.nextElement();
boolean changeType = false;
if (uinode.getType() != nType) {
if (uinode.setType(item.getNodeType())) {
changeType = true;
}
} else {
changeType = true;
}
if (changeType) {
// ADD LABEL IF NODE HAS NO LABEL
if (uinode.getText().equals("")) {
uinode.setText(sLabel);
}
// ADD REFERENCE IMAGE
uinode.setReferenceIcon(sImage);
try {
uinode.getNode().setSource(uinode.getNode().getSource(), sImage, sAuthor); //$NON-NLS-1$
}
catch(Exception ex) {
log.info("error in UIViewPane.createNodeFromStencil) \n\n"+ex.getMessage()); //$NON-NLS-1$
}
// ADD THE TAGS
IModel oModel = ProjectCompendium.APP.getModel();
PCSession oSession = oModel.getSession();
NodeSummary nodeSum = uinode.getNode();
int count = vtTags.size();
for(int i=0; i<count;i++) {
Vector data = (Vector)vtTags.elementAt(i);
String sID = (String)data.elementAt(0);
String sName = (String)data.elementAt(1);
String sTheAuthor = (String)data.elementAt(2);
String sDescription = (String)data.elementAt(3);
String sBehavior = (String)data.elementAt(4);
Date dCreated = (Date)data.elementAt(5);
Date dLastModified = (Date)data.elementAt(6);
Code codeObj = null;
try {
// CHECK IF ALREADY IN DATABASE
Vector existingCodesForName = (oModel.getCodeService()).getCodeIDs(oSession, sName);
if (existingCodesForName.size() == 0) {
codeObj = oModel.getCodeService().createCode(oSession, sID, sTheAuthor, dCreated,
dLastModified, sName, sDescription, sBehavior);
oModel.addCode(codeObj);
}
else {
String existingCodeID = (String)existingCodesForName.elementAt(0);
codeObj = oModel.getCodeService().getCode(oSession, existingCodeID);
}
nodeSum.addCode(codeObj);
}
catch(Exception ex) { log.info("Unable to add tag = "+codeObj.getName()+"\n\ndue to:\n\n"+ex.getMessage()); } //$NON-NLS-1$ //$NON-NLS-2$
}
// ADD BACKGROUND IMAGE AND TEMPLATE IF REQUIRED
if (uinode.getNode() instanceof View) {
View view = (View)uinode.getNode();
if (sBackgroundImage != null && !sBackgroundImage.equals("")) { //$NON-NLS-1$
try {
view.setBackgroundImage(sBackgroundImage);
view.updateViewLayer();
}
catch(Exception ex) {
log.info("error in UIViewPane.createNodeFromStencil) \n\n"+ex.getMessage()); //$NON-NLS-1$
}
}
if (sTemplate != null && !sTemplate.equals("")) { //$NON-NLS-1$
UIMapViewFrame mapFrame = null;
try {
view.initializeMembers();
mapFrame = new UIMapViewFrame(view, view.getLabel());
}
catch(Exception ex) {
log.error("Error...", ex);
}
if (mapFrame != null) {
ProjectCompendium.APP.onTemplateImport(sTemplate, mapFrame.getViewPane());
}
}
}
uinode.getUI().refreshBounds();
oViewPane.setSelectedNode(uinode,ICoreConstants.MULTISELECT);
uinode.requestFocus();
}
}
}
/**
* Change the type of all selected nodes to the given type.
* @param type the new type to set the selected nodes to.
*/
protected void changeType(int nType) {
for(Enumeration e = oViewPane.getSelectedNodes();e.hasMoreElements();) {
UINode uinode = (UINode)e.nextElement();
if (uinode.setType(nType)) {
oViewPane.setSelectedNode(uinode,ICoreConstants.MULTISELECT);
uinode.requestFocus();
}
}
}
/**
* Process a node creation request.
* @param nType, the type of the new node to create.
*/
protected void createNode(int nType) {
// MOVE THE MOUSE POINTER TO THE CORRECT POSITION
try {
Point pos = new Point(nX, nY);
SwingUtilities.convertPointToScreen(pos, oViewPane);
Robot rob = new Robot();
rob.mouseMove(pos.x, pos.y);
}
catch(AWTException ex) {}
// MOVE X AN Y FOR NODE OUT A BIT SO MOUSEPOINTER NOT RIGHT ON EDGE
nX -= 20;
nY -= 20;
oViewPaneUI.addNewNode(nType, nX, nY);
}
/**
* Import an image folder.
*/
protected void importImageFolder() {
ProjectCompendium.APP.onFileImportImageFolder(oViewPane.getViewFrame());
}
/**
* Move the first page of details of the currently selected nodes into their respective labels.
*/
protected void moveDetailToLabel() {
for(Enumeration e = oViewPane.getSelectedNodes();e.hasMoreElements();) {
UINode uinode = (UINode)e.nextElement();
uinode.onMoveDetails();
}
ProjectCompendium.APP.setStatus(""); //$NON-NLS-1$
oViewPane.getUI().redraw();
}
/**
* Move the labels of the currently selected nodes into their respective details pages.
*/
protected void moveLabelToDetail() {
for(Enumeration e = oViewPane.getSelectedNodes();e.hasMoreElements();) {
UINode uinode = (UINode)e.nextElement();
uinode.onMoveLabel();
}
ProjectCompendium.APP.setStatus(""); //$NON-NLS-1$
oViewPane.getUI().redraw();
}
/**
* Handle a Questmap import request.
* @param showViewList, true if importing to mulitpl views, else false.
*/
protected void onImportFile(boolean showViewList) {
UIImportDialog uid = new UIImportDialog(ProjectCompendium.APP, showViewList);
uid.setViewPaneUI(oViewPaneUI);
uid.setVisible(true);
}
/**
* Exports the current view to a HTML outline file.
*/
protected void onExportFile() {
UIExportDialog export = new UIExportDialog(ProjectCompendium.APP, oViewPane.getViewFrame());
export.setVisible(true);
}
/**
* Exports the current view to a HTML Views file.
*/
protected void onExportView() {
UIExportViewDialog dialog2 = new UIExportViewDialog(ProjectCompendium.APP, oViewPane.getViewFrame());
UIUtilities.centerComponent(dialog2, ProjectCompendium.APP);
dialog2.setVisible(true);
}
/**
* Mark the currently selected Nodes as seen.
*/
protected void markSeen() {
try {
Enumeration e = oViewPane.getSelectedNodes();
for(;e.hasMoreElements();){
UINode node = (UINode) e.nextElement();
NodeSummary oNode = node.getNode();
oNode.setState(ICoreConstants.READSTATE);
}
}
catch(Exception io) {
log.info(LanguageProperties.getString(LanguageProperties.POPUPS_BUNDLE, "UIBasePopupMenu.unableMarkRead")); //$NON-NLS-1$
}
}
/**
* Mark the currently selected nodes as unseen.
*/
protected void markUnseen() {
try {
Enumeration e = oViewPane.getSelectedNodes();
for(;e.hasMoreElements();){
UINode node = (UINode) e.nextElement();
NodeSummary oNode = node.getNode();
oNode.setState(ICoreConstants.UNREADSTATE);
}
}
catch(Exception io) {
log.info(LanguageProperties.getString(LanguageProperties.POPUPS_BUNDLE, "UIBasePopupMenu.unableMarkUnread")); //$NON-NLS-1$
}
}
/**
* delink the currently selected nodes.
*/
protected void delinkNodes() {
for(Enumeration e = oViewPane.getSelectedNodes();e.hasMoreElements();) {
UINode uinode = (UINode)e.nextElement();
NodeUI nodeui = (uinode.getUI());
ProjectCompendium.APP.setStatus(LanguageProperties.getString(LanguageProperties.POPUPS_BUNDLE, "UINodePopupMenu.delinking") + nodeui.getUINode().getNode().getLabel()); //$NON-NLS-1$
nodeui.delink();
}
ProjectCompendium.APP.setStatus(""); //$NON-NLS-1$
}
/**
* Create Shortcuts for the selected nodes.
*/
protected void shortcutNodes() {
int nOffset = 55;
Vector uinodes = new Vector(50);
for(Enumeration e = oViewPane.getSelectedNodes();e.hasMoreElements();) {
UINode uinode = (UINode)e.nextElement();
if( !(uinode.getNode() instanceof ShortCutNodeSummary) ) {
NodeUI nodeui = (uinode.getUI());
ProjectCompendium.APP.setStatus(LanguageProperties.getString(LanguageProperties.POPUPS_BUNDLE, "UIBasePopupMenu.makingShortcut") + nodeui.getUINode().getNode().getLabel()); //$NON-NLS-1$
int x = uinode.getX();
int y = uinode.getY();
UINode tmpuinode = oViewPaneUI.createShortCutNode(uinode, x+nOffset, y+nOffset);
uinodes.addElement(tmpuinode);
}
}
oViewPane.setSelectedNode(null, ICoreConstants.DESELECTALL);
oViewPane.setSelectedLink(null, ICoreConstants.DESELECTALL);
for(int i=0;i<uinodes.size();i++) {
UINode uinode = (UINode)uinodes.elementAt(i);
uinode.requestFocus();
uinode.setSelected(true);
oViewPane.setSelectedNode(uinode,ICoreConstants.MULTISELECT);
}
ProjectCompendium.APP.setStatus(""); //$NON-NLS-1$
oViewPane.getUI().redraw();
}
/**
* Clone the currently selected nodes.
*/
protected void cloneNodes() {
int nOffset = 55;
Hashtable cloneNodes = new Hashtable();
Vector uinodes = new Vector(50);
for(Enumeration e = oViewPane.getSelectedNodes();e.hasMoreElements();) {
UINode uinode = (UINode)e.nextElement();
NodeUI nodeui = (uinode.getUI());
ProjectCompendium.APP.setStatus(LanguageProperties.getString(LanguageProperties.POPUPS_BUNDLE, "UIBasePopupMenu.cloning") + nodeui.getUINode().getNode().getLabel()); //$NON-NLS-1$
int x = uinode.getX();
int y = uinode.getY();
UINode tmpuinode = oViewPaneUI.createCloneNode(uinode, x+nOffset, y+nOffset);
cloneNodes.put(uinode,tmpuinode);
uinodes.addElement(tmpuinode);
}
oViewPane.setSelectedNode(null, ICoreConstants.DESELECTALL);
for(int i=0;i<uinodes.size();i++) {
UINode uinode = (UINode)uinodes.elementAt(i);
uinode.requestFocus();
uinode.setSelected(true);
oViewPane.setSelectedNode(uinode,ICoreConstants.MULTISELECT);
}
ProjectCompendium.APP.setStatus(""); //$NON-NLS-1$
Vector linkList = new Vector();
for(Enumeration e = oViewPane.getSelectedLinks();e.hasMoreElements();) {
UILink link = (UILink)e.nextElement();
UINode uiFrom = link.getFromNode();
UINode uiTo = link.getToNode();
if ((cloneNodes.get(uiFrom) != null) && (cloneNodes.get(uiTo) != null) ) {
UILink tmpLink = (uiFrom.getUI()).createLink(
(UINode)cloneNodes.get(uiFrom),
(UINode)cloneNodes.get(uiTo),
link.getLink().getType(),
link.getLinkProperties());
linkList.addElement(tmpLink);
}
}
oViewPane.setSelectedLink(null, ICoreConstants.DESELECTALL);
for(int i=0;i<linkList.size();i++) {
UILink uiLink = (UILink)linkList.elementAt(i);
uiLink.setSelected(true);
oViewPane.setSelectedLink(uiLink,ICoreConstants.MULTISELECT);
}
}
/**
* Delete the currently selected nodes.
*/
protected void delete() {
DeleteEdit edit = new DeleteEdit(oViewPane.getViewFrame());
oViewPane.deleteSelectedNodesAndLinks(edit);
oViewPane.getViewFrame().getUndoListener().postEdit(edit);
ProjectCompendium.APP.setTrashBinIcon();
}
}