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
;
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
) {
40 public JList
getList() {
44 public RemoveActionDescription
addRemoveAction(final String actionName
) {
45 final RemoveActionDescription description
= new RemoveActionDescription(actionName
);
46 addActionDescription(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
);
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
);
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
);
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
));
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
));
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
);
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
) {
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
,
183 final ActionBehaviour
<V
> behaviour
) {
184 super(customActionDescription
, text
, description
, icon
, behaviour
);
187 public boolean displayTextInToolbar() {
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
);
225 protected Icon
getActionIcon() {
229 protected String
getActionName() {
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() {
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
);
274 protected abstract V
addInternal(final V v
);
276 public Icon
getActionIcon() {
280 public String
getActionName() {
281 return myActionDescription
;
284 public void setIcon(final Icon 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
) {
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
) {
309 for (T element
: t
) {
310 handleNewElement(element
);
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
;
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
);
338 public void updateAction(final AnActionEvent e
) {
339 final boolean applicable
= myList
.getSelectedIndices().length
== 1;
340 final Presentation presentation
= e
.getPresentation();
342 presentation
.setEnabled(applicable
);
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() {
357 public String
getActionName() {
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
) {
373 public AnAction
createAction(final JComponent component
) {