001: /*
002: * Copyright 2001-2006 C:1 Financial Services GmbH
003: *
004: * This software is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License Version 2.1, as published by the Free Software Foundation.
007: *
008: * This software is distributed in the hope that it will be useful,
009: * but WITHOUT ANY WARRANTY; without even the implied warranty of
010: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
011: * Lesser General Public License for more details.
012: *
013: * You should have received a copy of the GNU Lesser General Public
014: * License along with this library; if not, write to the Free Software
015: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
016: */
017:
018: package de.finix.contelligent.client.gui.explorer;
019:
020: import java.awt.event.ActionEvent;
021: import java.util.ArrayList;
022: import java.util.Collections;
023: import java.util.HashMap;
024: import java.util.Iterator;
025: import java.util.List;
026: import java.util.Map;
027: import java.util.StringTokenizer;
028: import java.util.logging.Level;
029:
030: import javax.swing.AbstractAction;
031: import javax.swing.Action;
032: import javax.swing.ImageIcon;
033: import javax.swing.JMenu;
034: import javax.swing.JMenuItem;
035: import javax.swing.JOptionPane;
036: import javax.swing.tree.DefaultMutableTreeNode;
037:
038: import de.finix.contelligent.client.base.ComponentNotFoundException;
039: import de.finix.contelligent.client.base.ComponentReference;
040: import de.finix.contelligent.client.base.ContelligentComponent;
041: import de.finix.contelligent.client.base.Errors;
042: import de.finix.contelligent.client.base.TypeFactory;
043: import de.finix.contelligent.client.base.TypeNotFoundException;
044: import de.finix.contelligent.client.gui.ContelligentSubmenuAction;
045: import de.finix.contelligent.client.gui.text.StringOptionPane;
046: import de.finix.contelligent.client.i18n.Resources;
047: import de.finix.contelligent.client.modules.preferences.PreferencesModule;
048: import de.finix.contelligent.client.remote.ActionResult;
049: import de.finix.contelligent.client.remote.Actions;
050: import de.finix.contelligent.client.remote.RemoteActionException;
051: import de.finix.contelligent.client.util.ExceptionDialog;
052: import de.finix.contelligent.client.util.MenuAndToolbarComposer;
053:
054: public class CreateTypeInstanceAction extends AbstractAction implements
055: ContelligentSubmenuAction {
056:
057: /**
058: *
059: */
060: private final ExplorerEditor editor;
061:
062: public JMenuItem menu;
063:
064: public CreateTypeInstanceAction(ExplorerEditor editor) {
065: super ("create_type_instance", Resources.createComponentIcon);
066: this .editor = editor;
067: putValue(ROLLOVER_ICON, Resources.createComponentIconRollOver);
068: putValue(TYPE, SUBMENU_ACTION);
069: putValue(ACTION_TYPE, EDIT_ACTION);
070: putValue(MENU_TARGET, NO_MENU);
071: putValue(BUTTON_TARGET, NO_BUTTON);
072: putValue(POPUP_TARGET, POPUP_MENU);
073: // generate a specialized menu item for this action...
074: menu = new JMenu(Resources.getLocalString(
075: "create_type_instance", false));
076: // menu.setIcon(Resources.createComponentIcon);
077: calculateMenuStructure();
078: }
079:
080: public void setEnabled(boolean enabled) {
081: // We cant let the parent class handle en-/disabling since we build
082: // our own menu and dont want the leaf nodes to end up disabled when
083: // they shouldnt.
084: menu.setEnabled(enabled);
085: }
086:
087: public boolean isEnabled() {
088: return menu.isEnabled();
089: }
090:
091: public void calculateMenuStructure() {
092: resetMenu();
093:
094: String allowedString = this .editor.getView()
095: .getAllowedTypesString();
096: Map types = TypeFactory.getInstance().getAllowedTypes(
097: allowedString);
098: List typeList = new ArrayList(types.keySet());
099: Collections.sort(typeList);
100:
101: String favoriteString = this .editor.getView()
102: .getFavoriteTypesString();
103: Map favoriteTypes = TypeFactory.getInstance().getAllowedTypes(
104: favoriteString, false);
105: List favoriteTypeList = new ArrayList(favoriteTypes.keySet());
106: Collections.sort(favoriteTypeList);
107:
108: addSubmenuHierarchy(menu, typeList.iterator(), favoriteTypeList
109: .iterator(), this );
110: }
111:
112: private void addSubmenuHierarchy(JMenuItem menu, Iterator iterator,
113: Iterator favoriteIterator, Action action) {
114: Map submenus = new HashMap(); // a list of string/menu items
115: TypeFactory typeFactory = TypeFactory.getInstance();
116: while (iterator.hasNext()) {
117: String typeName = (String) iterator.next();
118: // ignore types with no package prefix
119: int lastDot = typeName.lastIndexOf('.');
120: if (lastDot > 0) {
121: ImageIcon typeIcon = null;
122: try {
123: typeIcon = typeFactory.getType(typeName).getIcon();
124: } catch (TypeNotFoundException tnfe) {
125: // ignore
126: }
127: String prefix = typeName.substring(0, lastDot);
128: String name = typeName.substring(typeName
129: .lastIndexOf('.') + 1);
130: if (submenus.containsKey(prefix)) {
131: JMenuItem parentSubmenu = (JMenuItem) submenus
132: .get(prefix);
133: JMenuItem submenu = new JMenuItem(action);
134: submenu.setText(name);
135: submenu.setIcon(typeIcon);
136: submenu.setActionCommand(typeName);
137: addSubmenuToParent((JMenu) parentSubmenu, submenu);
138: } else {
139: StringBuffer key = new StringBuffer(255);
140: StringTokenizer tokenizer = new StringTokenizer(
141: typeName, ".");
142: String parentKey = null;
143: int numberOfTokens = tokenizer.countTokens();
144: for (int i = 0; i < numberOfTokens - 1; i++) {
145: String token = tokenizer.nextToken();
146: key.append(token);
147: if (!submenus.containsKey(key.toString())) {
148: JMenuItem submenu = new JMenu(token);
149: if (parentKey != null) {
150: JMenuItem parentSubmenu = (JMenuItem) submenus
151: .get(parentKey);
152: parentSubmenu.add(submenu);
153: } else {
154: menu.add(submenu);
155: }
156: submenus.put(key.toString(), submenu);
157: }
158: parentKey = key.toString();
159: key.append('.');
160: }
161: JMenuItem parentSubmenu = (JMenuItem) submenus
162: .get(prefix);
163: // set action
164: JMenuItem submenu = new JMenuItem(action);
165: submenu.setActionCommand(typeName);
166: submenu.setIcon(typeIcon);
167: submenu.setText(name);
168: addSubmenuToParent((JMenu) parentSubmenu, submenu);
169: }
170: }
171: }
172: while (favoriteIterator.hasNext()) {
173: String typeName = (String) favoriteIterator.next();
174: ImageIcon typeIcon = null;
175: try {
176: typeIcon = typeFactory.getType(typeName).getIcon();
177: } catch (TypeNotFoundException tnfe) {
178: // ignore
179: }
180: JMenuItem submenu = new JMenuItem(action);
181: submenu.setActionCommand(typeName);
182: submenu.setIcon(typeIcon);
183: submenu.setText(typeName);
184: menu.add(submenu);
185: }
186: }
187:
188: private void addSubmenuToParent(JMenu menu, JMenuItem submenu) {
189: while (true) {
190: int itemCount = menu.getItemCount();
191: if (itemCount >= this .editor.MAX_SUBMENU_ITEMS) {
192: // check if there is a 'more' item...
193: JMenuItem lastMenuItem = menu.getItem(itemCount - 1);
194: if (lastMenuItem instanceof JMenu) {
195: menu = (JMenu) lastMenuItem;
196: } else {
197: JMenu moreItem = new JMenu(Resources
198: .getLocalString("more"));
199: menu.add(moreItem);
200: menu = moreItem;
201: break;
202: }
203: } else {
204: break;
205: }
206: }
207: menu.add(submenu);
208: }
209:
210: private void resetMenu() {
211: if (menu != null) {
212: menu.removeAll();
213: }
214: // XXX this is dangerous as it might also drop listeners not registered
215: // here
216: MenuAndToolbarComposer.resetActionListeners(this );
217: }
218:
219: public JMenuItem getMenuItem() {
220: return menu;
221: }
222:
223: public void actionPerformed(ActionEvent e) {
224: DefaultMutableTreeNode node = (DefaultMutableTreeNode) this .editor.tree
225: .getLastSelectedPathComponent();
226: // create new component on selected node
227: if (node != null
228: && node.getUserObject() instanceof ComponentReference) {
229: try {
230: // remote add on server
231: ContelligentComponent parent = ((ComponentReference) node
232: .getUserObject()).getComponent();
233: // ask for the name of the new component
234: StringOptionPane stringOptionPane = new StringOptionPane();
235: stringOptionPane.setAllowString(ContelligentComponent
236: .getAllowString());
237: String defaultName = "";
238: String type = ((JMenuItem) e.getSource())
239: .getActionCommand();
240: if (PreferencesModule.getPreferences().getBoolean(
241: PreferencesModule.PREFILL_NEW_NAME,
242: PreferencesModule.DEFAULT_PREFILL_NEW_NAME)) {
243: try {
244: defaultName = type.substring(type
245: .lastIndexOf('.') + 1);
246: if (defaultName.length() >= 2) {
247: // Change first character to lower case
248: defaultName = defaultName.substring(0, 1)
249: .toLowerCase()
250: + defaultName.substring(1);
251: } else {
252: defaultName = defaultName.toLowerCase();
253: }
254: } catch (Exception ex) {
255: ExplorerEditor.logger
256: .log(
257: Level.INFO,
258: "Failed to get default component name: ",
259: ex);
260: defaultName = "";
261: }
262: }
263: if (stringOptionPane.showStringDialog(Resources
264: .getLocalString("create_component_from_type",
265: false), Resources.getLocalString(
266: "create_component_name", false), defaultName,
267: true) == StringOptionPane.OK_OPTION) {
268: String name = stringOptionPane.getText();
269: if (name != null && name.length() > 0) {
270: ActionResult response = Actions.createFromType(
271: editor.getView().getEnvironment(),
272: type, name, parent.getPath() + "/",
273: false);
274:
275: if (response.hasError(Errors.COMPONENT_EXISTS)) {
276: if (JOptionPane
277: .showOptionDialog(
278: this .editor.getParent(),
279: Resources
280: .getLocalString("component_exists_override"),
281: Resources
282: .getLocalString("component_exists"),
283: JOptionPane.YES_NO_OPTION,
284: JOptionPane.WARNING_MESSAGE,
285: null,
286: ExplorerEditor.YES_CANCEL_OPTIONS,
287: ExplorerEditor.YES_CANCEL_OPTIONS[0]) == JOptionPane.YES_OPTION) {
288: response = Actions.createFromType(
289: editor.getView()
290: .getEnvironment(),
291: type, name, parent.getPath()
292: + "/", true);
293: response.showErrors();
294: } else {
295: response
296: .showErrorsIgnore(Errors.COMPONENT_EXISTS);
297: }
298: } else {
299: response.showErrors();
300: }
301: if (response.getState().equals(ActionResult.OK)) {
302: this .editor.createdComponent = parent
303: .getPath()
304: + "/" + name;
305: this .editor.editCreatedComponent = false;
306: }
307: }
308: }
309: } catch (RemoteActionException rae) {
310: ExceptionDialog.show(rae);
311: } catch (ComponentNotFoundException cnfe) {
312: ExceptionDialog.show(cnfe);
313: }
314: }
315: }
316: }
|