cd83e19c9c6828955573417bf3ffb04e65ce9b7b
[fedora-idea.git] / platform / platform-api / src / com / intellij / openapi / ui / NamedItemsListEditor.java
blobcd83e19c9c6828955573417bf3ffb04e65ce9b7b
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * @author max
20 package com.intellij.openapi.ui;
22 import com.intellij.openapi.actionSystem.AnAction;
23 import com.intellij.openapi.actionSystem.AnActionEvent;
24 import com.intellij.openapi.actionSystem.CommonShortcuts;
25 import com.intellij.openapi.actionSystem.CustomShortcutSet;
26 import com.intellij.openapi.options.ConfigurationException;
27 import com.intellij.openapi.options.UnnamedConfigurable;
28 import com.intellij.openapi.util.*;
29 import com.intellij.util.Icons;
30 import com.intellij.util.ui.tree.TreeUtil;
31 import gnu.trove.Equality;
32 import org.jetbrains.annotations.Nullable;
34 import javax.swing.*;
35 import javax.swing.tree.DefaultMutableTreeNode;
36 import javax.swing.tree.TreeNode;
37 import java.awt.event.KeyEvent;
38 import java.text.MessageFormat;
39 import java.util.ArrayList;
40 import java.util.Collections;
41 import java.util.List;
43 public abstract class NamedItemsListEditor<T> extends MasterDetailsComponent {
44 private final Namer<T> myNamer;
45 private final Factory<T> myFactory;
46 private final Cloner<T> myCloner;
47 private final List<T> myItems = new ArrayList<T>();
48 private final Equality<T> myComparer;
49 private List<T> myResultItems;
50 private final List<T> myOriginalItems;
52 protected NamedItemsListEditor(Namer<T> namer,
53 Factory<T> factory,
54 Cloner<T> cloner,
55 Equality<T> comparer,
56 List<T> items) {
57 myNamer = namer;
58 myFactory = factory;
59 myCloner = cloner;
60 myComparer = comparer;
62 myOriginalItems = items;
63 myResultItems = items;
64 reset();
66 initTree();
69 public void reset() {
70 myResultItems = myOriginalItems;
71 myItems.clear();
73 myRoot.removeAllChildren();
74 for (T item : myOriginalItems) {
75 addNewNode(myCloner.cloneOf(item));
78 super.reset();
81 protected void processRemovedItems() {
84 protected boolean wasObjectStored(Object editableObject) {
85 return true;
88 protected String subjDisplayName() {
89 return "item";
92 @Nullable
93 public String askForProfileName(String titlePattern) {
94 String title = MessageFormat.format(titlePattern, subjDisplayName());
95 return Messages.showInputDialog("New " + subjDisplayName() + " name:", title, Messages.getQuestionIcon(), "", new InputValidator() {
96 public boolean checkInput(String s) {
97 return s.length() > 0 && findByName(s) == null;
100 public boolean canClose(String s) {
101 return checkInput(s);
106 @Nullable
107 private T findByName(String name) {
108 for (T item : myItems) {
109 if (Comparing.equal(name, myNamer.getName(item))) return item;
112 return null;
115 @Nullable
116 protected ArrayList<AnAction> createActions(boolean fromPopup) {
117 ArrayList<AnAction> result = new ArrayList<AnAction>();
118 result.add(new AddAction());
120 result.add(new MyDeleteAction(new Condition<Object>() {
121 @SuppressWarnings({"unchecked"})
122 public boolean value(Object o) {
123 return canDelete((T) ((MyNode) o).getConfigurable().getEditableObject());
125 }));
127 result.add(new CopyAction());
129 return result;
132 private void addNewNode(T item) {
133 addNode(new MyNode(new ItemConfigurable(item)), myRoot);
134 myItems.add(item);
137 protected boolean canDelete(T item) {
138 return true;
141 protected abstract UnnamedConfigurable createConfigurable(T item);
143 @Override
144 protected void onItemDeleted(Object item) {
145 myItems.remove((T)item);
148 protected void setDisplayName(T item, String name) {
149 myNamer.setName(item, name);
152 @Nullable
153 protected UnnamedConfigurable getItemConfigurable(final T item) {
154 final Ref<UnnamedConfigurable> result = new Ref<UnnamedConfigurable>();
155 TreeUtil.traverse((TreeNode)myTree.getModel().getRoot(), new TreeUtil.Traverse() {
156 public boolean accept(Object node) {
157 final NamedConfigurable configurable = (NamedConfigurable)((DefaultMutableTreeNode)node).getUserObject();
158 if (configurable.getEditableObject() == item) {
159 result.set(((ItemConfigurable)configurable).myConfigurable);
160 return false;
162 else {
163 return true;
167 return result.get();
170 private class ItemConfigurable extends NamedConfigurable {
171 private final T myItem;
172 private final UnnamedConfigurable myConfigurable;
174 public ItemConfigurable(T item) {
175 super(myNamer.canRename(item), TREE_UPDATER);
176 myItem = item;
177 myConfigurable = createConfigurable(item);
180 public void setDisplayName(String name) {
181 NamedItemsListEditor.this.setDisplayName(myItem, name);
184 public Object getEditableObject() {
185 return myItem;
188 public String getBannerSlogan() {
189 return myNamer.getName(myItem);
192 public JComponent createOptionsPanel() {
193 return myConfigurable.createComponent();
196 public String getDisplayName() {
197 return myNamer.getName(myItem);
200 public Icon getIcon() {
201 if (myConfigurable instanceof Iconable) {
202 return ((Iconable)myConfigurable).getIcon(0);
204 return null;
207 public String getHelpTopic() {
208 return null;
211 public boolean isModified() {
212 return myConfigurable.isModified();
215 public void apply() throws ConfigurationException {
216 myConfigurable.apply();
219 public void reset() {
220 myConfigurable.reset();
223 public void disposeUIResources() {
224 myConfigurable.disposeUIResources();
228 @Override
229 public boolean isModified() {
230 if (myResultItems.size() != myItems.size()) return true;
232 for (int i = 0; i < myItems.size(); i++) {
233 if (!myComparer.equals(myItems.get(i), myResultItems.get(i))) return true;
236 return super.isModified();
239 public void apply() throws ConfigurationException {
240 super.apply();
241 myResultItems = myItems;
244 protected List<T> getCurrentItems() {
245 return Collections.unmodifiableList(myItems);
248 public List<T> getItems() {
249 return myResultItems;
252 public T getSelectedItem() {
253 return (T) getSelectedObject();
257 private class CopyAction extends AnAction {
258 public CopyAction() {
259 super("Copy", "Copy", MasterDetailsComponent.COPY_ICON);
260 registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_D, KeyEvent.CTRL_MASK)), myTree);
263 public void actionPerformed(AnActionEvent event) {
264 final String profileName = askForProfileName("Copy {0}");
265 if (profileName == null) return;
267 final T clone = myCloner.copyOf((T) getSelectedObject());
268 myNamer.setName(clone, profileName);
269 addNewNode(clone);
270 selectNodeInTree(clone);
271 onItemCloned(clone);
275 public void update(AnActionEvent event) {
276 super.update(event);
277 event.getPresentation().setEnabled(getSelectedObject() != null);
281 protected void onItemCloned(T clone) {
284 private class AddAction extends AnAction {
285 public AddAction() {
286 super("Add", "Add", Icons.ADD_ICON);
287 registerCustomShortcutSet(CommonShortcuts.INSERT, myTree);
290 public void actionPerformed(AnActionEvent event) {
291 final T newItem = createItem();
292 if (newItem != null) {
293 onItemCreated(newItem);
298 public void selectItem(T item) {
299 selectNodeInTree(findByName(myNamer.getName(item)));
302 @Nullable
303 protected T createItem() {
304 final String name = askForProfileName("Create new {0}");
305 if (name == null) return null;
306 final T newItem = myFactory.create();
307 myNamer.setName(newItem, name);
308 return newItem;
311 protected void onItemCreated(T newItem) {
312 addNewNode(newItem);
313 selectNodeInTree(newItem);