View Javadoc
1   /**
2    * 
3    * Copyright (c) 2013-2014, Openflexo
4    * Copyright (c) 2011-2012, AgileBirds
5    * 
6    * This file is part of Gina-swing-editor, a component of the software infrastructure 
7    * developed at Openflexo.
8    * 
9    * 
10   * Openflexo is dual-licensed under the European Union Public License (EUPL, either 
11   * version 1.1 of the License, or any later version ), which is available at 
12   * https://joinup.ec.europa.eu/software/page/eupl/licence-eupl
13   * and the GNU General Public License (GPL, either version 3 of the License, or any 
14   * later version), which is available at http://www.gnu.org/licenses/gpl.html .
15   * 
16   * You can redistribute it and/or modify under the terms of either of these licenses
17   * 
18   * If you choose to redistribute it and/or modify under the terms of the GNU GPL, you
19   * must include the following additional permission.
20   *
21   *          Additional permission under GNU GPL version 3 section 7
22   *
23   *          If you modify this Program, or any covered work, by linking or 
24   *          combining it with software containing parts covered by the terms 
25   *          of EPL 1.0, the licensors of this Program grant you additional permission
26   *          to convey the resulting work. * 
27   * 
28   * This software is distributed in the hope that it will be useful, but WITHOUT ANY 
29   * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 
30   * PARTICULAR PURPOSE. 
31   *
32   * See http://www.openflexo.org/license.html for details.
33   * 
34   * 
35   * Please contact Openflexo (openflexo-contacts@openflexo.org)
36   * or visit www.openflexo.org if you need additional information.
37   * 
38   */
39  
40  package org.openflexo.gina.swing.editor.controller;
41  
42  import java.awt.Component;
43  import java.awt.Point;
44  import java.awt.event.ActionEvent;
45  import java.awt.event.ActionListener;
46  import java.util.Hashtable;
47  import java.util.logging.Logger;
48  
49  import javax.swing.AbstractAction;
50  import javax.swing.JComponent;
51  import javax.swing.JFrame;
52  import javax.swing.JMenu;
53  import javax.swing.JMenuItem;
54  import javax.swing.JPopupMenu;
55  import javax.swing.KeyStroke;
56  
57  import org.openflexo.gina.model.FIBComponent;
58  import org.openflexo.gina.model.FIBModelObject;
59  import org.openflexo.gina.swing.editor.FIBEditor;
60  import org.openflexo.gina.swing.editor.controller.action.CopyAction;
61  import org.openflexo.gina.swing.editor.controller.action.CutAction;
62  import org.openflexo.gina.swing.editor.controller.action.DeleteAction;
63  import org.openflexo.gina.swing.editor.controller.action.EditorAction;
64  import org.openflexo.gina.swing.editor.controller.action.InspectAction;
65  import org.openflexo.gina.swing.editor.controller.action.MakeReusableComponent;
66  import org.openflexo.gina.swing.editor.controller.action.MoveDown;
67  import org.openflexo.gina.swing.editor.controller.action.MoveToBottom;
68  import org.openflexo.gina.swing.editor.controller.action.MoveToTop;
69  import org.openflexo.gina.swing.editor.controller.action.MoveUp;
70  import org.openflexo.gina.swing.editor.controller.action.OpenComponent;
71  import org.openflexo.gina.swing.editor.controller.action.PasteAction;
72  import org.openflexo.gina.swing.editor.controller.action.WrapWithPanelAction;
73  import org.openflexo.gina.swing.editor.controller.action.WrapWithSplitPanelAction;
74  import org.openflexo.logging.FlexoLogger;
75  
76  public class ContextualMenu {
77  	@SuppressWarnings("unused")
78  	private static final Logger logger = FlexoLogger.getLogger(ContextualMenu.class.getPackage().getName());
79  
80  	private FIBEditorController editorController;
81  	private Hashtable<EditorAction, PopupMenuItem> actions;
82  	private JPopupMenu menu;
83  	private JFrame frame;
84  
85  	public ContextualMenu(FIBEditorController anEditorController, final JFrame frame) {
86  		this.editorController = anEditorController;
87  		this.frame = frame;
88  		actions = new Hashtable<>();
89  		menu = new JPopupMenu();
90  
91  		addToActions(new InspectAction(editorController));
92  		menu.addSeparator();
93  
94  		addToActions(new CopyAction(editorController));
95  		addToActions(new CutAction(editorController));
96  		addToActions(new PasteAction(editorController));
97  		menu.addSeparator();
98  
99  		// addToActions(new UndoAction(editorController));
100 		// addToActions(new RedoAction(editorController));
101 		// menu.addSeparator();
102 
103 		JMenu wrapWith = new JMenu(FIBEditor.EDITOR_LOCALIZATION.localizedForKey("wrap_with"));
104 		menu.add(wrapWith);
105 		addToActions(new WrapWithPanelAction(editorController), wrapWith);
106 		addToActions(new WrapWithSplitPanelAction(editorController), wrapWith);
107 		JMenu moveTo = new JMenu(FIBEditor.EDITOR_LOCALIZATION.localizedForKey("move"));
108 		menu.add(moveTo);
109 		addToActions(new MoveToTop(editorController), moveTo);
110 		addToActions(new MoveUp(editorController), moveTo);
111 		addToActions(new MoveDown(editorController), moveTo);
112 		addToActions(new MoveToBottom(editorController), moveTo);
113 		addToActions(new MakeReusableComponent(editorController, frame));
114 		addToActions(new OpenComponent(editorController));
115 
116 		menu.addSeparator();
117 
118 		addToActions(new DeleteAction(editorController, frame));
119 	}
120 
121 	public void addToActions(EditorAction action) {
122 		addToActions(action, null);
123 	}
124 
125 	@SuppressWarnings("serial")
126 	public void addToActions(EditorAction action, JMenu subMenu) {
127 		PopupMenuItem newMenuItem = new PopupMenuItem(action);
128 		if (action.getShortcut() != null) {
129 			newMenuItem.setAccelerator(action.getShortcut());
130 			registerActionForKeyStroke(new AbstractAction() {
131 				@Override
132 				public void actionPerformed(ActionEvent e) {
133 					if (action.isEnabledFor(editorController.getSelectedObject())) {
134 						// System.out.println("Execute action " + action + " for object " + editorController.getSelectedObject());
135 						action.performAction(editorController.getSelectedObject());
136 					}
137 				}
138 			}, action.getShortcut(), action.getActionName());
139 		}
140 		if (subMenu != null) {
141 			subMenu.add(newMenuItem);
142 		}
143 		else {
144 			menu.add(newMenuItem);
145 		}
146 
147 		actions.put(action, newMenuItem);
148 	}
149 
150 	public void displayPopupMenu(FIBModelObject object, Component invoker, Point p) {
151 		if (menu == null) {
152 			return;
153 		}
154 		for (EditorAction action : actions.keySet()) {
155 			PopupMenuItem menuItem = actions.get(action);
156 			menuItem.setObject(object);
157 		}
158 		if (p != null) {
159 			menu.show(invoker, p.x, p.y);
160 		}
161 	}
162 
163 	@SuppressWarnings("serial")
164 	class PopupMenuItem extends JMenuItem {
165 		private FIBModelObject object;
166 		private final EditorAction action;
167 
168 		public PopupMenuItem(EditorAction anAction) {
169 			super(anAction.getActionName(), anAction.getActionIcon());
170 			this.action = anAction;
171 			addActionListener(new ActionListener() {
172 				@Override
173 				public void actionPerformed(ActionEvent e) {
174 					FIBModelObject selectThis = action.performAction(object);
175 					if (selectThis instanceof FIBComponent) {
176 						editorController.setSelectedObject(selectThis);
177 					}
178 				}
179 			});
180 		}
181 
182 		public FIBModelObject getObject() {
183 			return object;
184 		}
185 
186 		public void setObject(FIBModelObject object) {
187 			this.object = object;
188 			setEnabled(action.isEnabledFor(object));
189 			setVisible(action.isVisibleFor(object));
190 		}
191 
192 	}
193 
194 	public void registerActionForKeyStroke(AbstractAction action, KeyStroke accelerator, String actionName) {
195 		String key = actionName;
196 		frame.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(accelerator, key);
197 		frame.getRootPane().getActionMap().put(key, action);
198 		if (accelerator.getKeyCode() == FIBEditor.DELETE_KEY_CODE) {
199 			int keyCode = FIBEditor.BACKSPACE_DELETE_KEY_CODE;
200 			frame.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
201 					.put(KeyStroke.getKeyStroke(keyCode, accelerator.getModifiers()), key);
202 		}
203 	}
204 
205 }