cleanup
[fedora-idea.git] / platform / platform-api / src / com / intellij / ui / ReorderableListController.java
blob72f40f3d79edb22b28463cfea55ff9cd5b9c92a9
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.
16 package com.intellij.ui;
18 import com.intellij.openapi.actionSystem.*;
19 import com.intellij.openapi.util.Condition;
20 import com.intellij.openapi.util.Factory;
21 import com.intellij.openapi.util.IconLoader;
22 import com.intellij.util.containers.Convertor;
23 import org.jetbrains.annotations.Nullable;
25 import javax.swing.*;
26 import java.util.*;
28 /**
29 * @author dyoma
31 public abstract class ReorderableListController <T> {
32 private final JList myList;
33 private static final Icon REMOVE_ICON = IconLoader.getIcon("/general/remove.png");
34 private static final Icon COPY_ICON = IconLoader.getIcon("/actions/copy.png");
36 protected ReorderableListController(final JList list) {
37 myList = list;
40 public JList getList() {
41 return myList;
44 public RemoveActionDescription addRemoveAction(final String actionName) {
45 final RemoveActionDescription description = new RemoveActionDescription(actionName);
46 addActionDescription(description);
47 return description;
50 protected abstract void addActionDescription(ActionDescription description);
52 public AddActionDescription addAddAction(final String actionName, final Factory<T> creator, final boolean createShortcut) {
53 final AddActionDescription description = new AddActionDescription(actionName, creator, createShortcut);
54 addActionDescription(description);
55 return description;
58 public AddMultipleActionDescription addAddMultipleAction(final String actionName, final Factory<Collection<T>> creator, final boolean createShortcut) {
59 final AddMultipleActionDescription description = new AddMultipleActionDescription(actionName, creator, createShortcut);
60 addActionDescription(description);
61 return description;
64 public CopyActionDescription addCopyAction(final String actionName, final Convertor<T, T> copier, final Condition<T> enableCondition) {
65 final CopyActionDescription description = new CopyActionDescription(actionName, copier, enableCondition);
66 addActionDescription(description);
67 return description;
70 public void addMoveUpAction() {
71 addAction(new AnAction(UIBundle.message("move.up.action.name"), null, IconLoader.getIcon("/actions/moveUp.png")) {
72 public void actionPerformed(final AnActionEvent e) {
73 ListUtil.moveSelectedItemsUp(myList);
76 public void update(final AnActionEvent e) {
77 e.getPresentation().setEnabled(ListUtil.canMoveSelectedItemsUp(myList));
79 });
82 public void addMoveDownAction() {
83 addAction(new AnAction(UIBundle.message("move.down.action.name"), null, IconLoader.getIcon("/actions/moveDown.png")) {
84 public void actionPerformed(final AnActionEvent e) {
85 ListUtil.moveSelectedItemsDown(myList);
88 public void update(final AnActionEvent e) {
89 e.getPresentation().setEnabled(ListUtil.canMoveSelectedItemsDown(myList));
91 });
94 public void addAction(final AnAction action) {
95 addActionDescription(new FixedActionDescription(action));
98 private void handleNewElement(final T element) {
99 final ListModel listModel = myList.getModel();
100 if (listModel instanceof SortedListModel) {
101 ((SortedListModel<T>)listModel).add(element);
103 else {
104 ((DefaultListModel)listModel).addElement(element);
106 myList.clearSelection();
107 ListScrollingUtil.selectItem(myList, element);
110 public static <T> ReorderableListController<T> create(final JList list, final DefaultActionGroup actionGroup) {
111 return new ReorderableListController<T>(list) {
112 protected void addActionDescription(final ActionDescription description) {
113 actionGroup.add(description.createAction(list));
118 protected static abstract class ActionDescription {
119 public abstract AnAction createAction(JComponent component);
122 public interface ActionNotification <T> {
123 void afterActionPerformed(T change);
126 public static abstract class CustomActionDescription <V> extends ActionDescription {
127 private final ArrayList<ActionNotification<V>> myPostHandlers = new ArrayList<ActionNotification<V>>(1);
128 private boolean myShowText = false;
130 public void addPostHandler(final ActionNotification<V> runnable) {
131 myPostHandlers.add(runnable);
134 protected void runPostHandlers(final V change) {
135 for (Iterator<ActionNotification<V>> iterator = myPostHandlers.iterator(); iterator.hasNext();) {
136 final ActionNotification<V> runnable = iterator.next();
137 runnable.afterActionPerformed(change);
141 public abstract CustomActionDescription.BaseAction createAction(JComponent component);
143 BaseAction createAction(final ActionBehaviour behaviour) {
144 return myShowText ?
145 new ActionWithText(this, getActionName(), null, getActionIcon(), behaviour) :
146 new BaseAction(this, getActionName(), null, getActionIcon(), behaviour);
149 protected abstract Icon getActionIcon();
151 protected abstract String getActionName();
153 public void setShowText(final boolean showText) {
154 myShowText = showText;
157 protected static class BaseAction<V> extends AnAction {
158 private final ActionBehaviour<V> myBehaviour;
159 private final CustomActionDescription<V> myCustomActionDescription;
161 public BaseAction(final CustomActionDescription<V> customActionDescription,
162 final String text, final String description, final Icon icon, final ActionBehaviour<V> behaviour) {
163 super(text, description, icon);
164 myBehaviour = behaviour;
165 this.myCustomActionDescription = customActionDescription;
168 public void actionPerformed(final AnActionEvent e) {
169 final V change = myBehaviour.performAction(e);
170 if (change == null) return;
171 myCustomActionDescription.runPostHandlers(change);
174 public void update(final AnActionEvent e) {
175 myBehaviour.updateAction(e);
179 private static class ActionWithText<V> extends BaseAction {
180 public ActionWithText(final CustomActionDescription<V> customActionDescription, final String text,
181 final String description,
182 final Icon icon,
183 final ActionBehaviour<V> behaviour) {
184 super(customActionDescription, text, description, icon, behaviour);
187 public boolean displayTextInToolbar() {
188 return true;
193 static interface ActionBehaviour<T> {
194 T performAction(AnActionEvent e);
195 void updateAction(AnActionEvent e);
198 public class RemoveActionDescription extends CustomActionDescription<List<T>> {
199 private final String myActionName;
200 private Condition<List<T>> myConfirmation;
201 private Condition<T> myEnableCondition;
203 public RemoveActionDescription(final String actionName) {
204 myActionName = actionName;
207 public BaseAction createAction(final JComponent component) {
208 final ActionBehaviour<List<T>> behaviour = new ActionBehaviour<List<T>>() {
209 public List<T> performAction(final AnActionEvent e) {
210 if (myConfirmation != null && !myConfirmation.value((List<T>)Arrays.asList(myList.getSelectedValues()))) {
211 return Collections.emptyList();
213 return ListUtil.removeSelectedItems(myList, myEnableCondition);
216 public void updateAction(final AnActionEvent e) {
217 e.getPresentation().setEnabled(ListUtil.canRemoveSelectedItems(myList, myEnableCondition));
220 final BaseAction action = createAction(behaviour);
221 action.registerCustomShortcutSet(CommonShortcuts.DELETE, component);
222 return action;
225 protected Icon getActionIcon() {
226 return REMOVE_ICON;
229 protected String getActionName() {
230 return myActionName;
233 public void setConfirmation(final Condition<List<T>> confirmation) {
234 myConfirmation = confirmation;
237 public void setEnableCondition(final Condition<T> enableCondition) {
238 myEnableCondition = enableCondition;
241 public JList getList() {
242 return myList;
246 public abstract class AddActionDescriptionBase<V> extends CustomActionDescription<V> {
247 private final String myActionDescription;
248 private final Factory<V> myAddHandler;
249 private final boolean myCreateShortcut;
250 private Icon myIcon = IconLoader.getIcon("/general/add.png");
252 public AddActionDescriptionBase(final String actionDescription, final Factory<V> addHandler, final boolean createShortcut) {
253 myActionDescription = actionDescription;
254 myAddHandler = addHandler;
255 myCreateShortcut = createShortcut;
258 public BaseAction createAction(final JComponent component) {
259 final ActionBehaviour<V> behaviour = new ActionBehaviour<V>() {
260 public V performAction(final AnActionEvent e) {
261 return addInternal(myAddHandler.create());
264 public void updateAction(final AnActionEvent e) {}
266 final BaseAction action = createAction(behaviour);
267 if (myCreateShortcut) {
268 action.registerCustomShortcutSet(CommonShortcuts.INSERT, component);
270 return action;
273 @Nullable
274 protected abstract V addInternal(final V v);
276 public Icon getActionIcon() {
277 return myIcon;
280 public String getActionName() {
281 return myActionDescription;
284 public void setIcon(final Icon icon) {
285 myIcon = icon;
289 public class AddActionDescription extends AddActionDescriptionBase<T> {
290 public AddActionDescription(final String actionDescription, final Factory<T> addHandler, final boolean createShortcut) {
291 super(actionDescription, addHandler, createShortcut);
294 protected T addInternal(final T t) {
295 if (t != null) {
296 handleNewElement(t);
298 return t;
302 public class AddMultipleActionDescription extends AddActionDescriptionBase<Collection<T>> {
303 public AddMultipleActionDescription(final String actionDescription, final Factory<Collection<T>> addHandler, final boolean createShortcut) {
304 super(actionDescription, addHandler, createShortcut);
307 protected Collection<T> addInternal(final Collection<T> t) {
308 if (t != null) {
309 for (T element : t) {
310 handleNewElement(element);
313 return t;
317 public class CopyActionDescription extends CustomActionDescription<T> {
318 private final Convertor<T, T> myCopier;
319 private final Condition<T> myEnabled;
320 private final String myActionName;
321 private boolean myVisibleWhenDisabled;
323 public CopyActionDescription(final String actionName, final Convertor<T, T> copier, final Condition<T> enableCondition) {
324 myActionName = actionName;
325 myCopier = copier;
326 myEnabled = enableCondition;
327 myVisibleWhenDisabled = true;
330 public BaseAction createAction(final JComponent component) {
331 final ActionBehaviour<T> behaviour = new ActionBehaviour<T>() {
332 public T performAction(final AnActionEvent e) {
333 final T newElement = myCopier.convert((T)myList.getSelectedValue());
334 handleNewElement(newElement);
335 return newElement;
338 public void updateAction(final AnActionEvent e) {
339 final boolean applicable = myList.getSelectedIndices().length == 1;
340 final Presentation presentation = e.getPresentation();
341 if (!applicable) {
342 presentation.setEnabled(applicable);
343 return;
345 final boolean enabled = myEnabled.value((T)myList.getSelectedValue());
346 presentation.setEnabled(enabled);
347 presentation.setVisible(enabled || myVisibleWhenDisabled);
350 return createAction(behaviour);
353 public Icon getActionIcon() {
354 return COPY_ICON;
357 public String getActionName() {
358 return myActionName;
361 public void setVisibleWhenDisabled(final boolean visible) {
362 myVisibleWhenDisabled = visible;
366 private static class FixedActionDescription extends ActionDescription {
367 private final AnAction myAction;
369 public FixedActionDescription(final AnAction action) {
370 myAction = action;
373 public AnAction createAction(final JComponent component) {
374 return myAction;