action system: transparent actions + debugger actions made transparent

This commit is contained in:
Kirill Kalishev
2010-06-21 17:36:24 +04:00
parent f9bf5a7fe7
commit 1850d79e98
7 changed files with 125 additions and 26 deletions
@@ -159,6 +159,10 @@ public abstract class ActionManager implements ApplicationComponent {
public abstract void removeTimerListener(TimerListener listener);
public abstract void addTransparrentTimerListener(int delay, TimerListener listener);
public abstract void removeTransparrentTimerListener(TimerListener listener);
public abstract ActionCallback tryToExecute(@NotNull AnAction action, @NotNull InputEvent inputEvent, @Nullable Component contextComponent,
@Nullable String place, boolean now);
@@ -70,7 +70,9 @@ public abstract class AnAction {
private static final ShortcutSet ourEmptyShortcutSet = new CustomShortcutSet(new Shortcut[0]);
private boolean myIsDefaultIcon = true;
private boolean myWorksInInjected;
private boolean myTransparentUpdate = false;
/**
* Creates a new action with its text, description and icon set to <code>null</code>.
*/
@@ -288,4 +290,12 @@ public abstract class AnAction {
public boolean isInInjectedContext() {
return myWorksInInjected;
}
public boolean isTransparentUpdate() {
return myTransparentUpdate;
}
public void setTransparentUpdate(boolean transparentUpdate) {
myTransparentUpdate = transparentUpdate;
}
}
@@ -144,5 +144,6 @@ public abstract class ActionManagerEx extends ActionManager{
public abstract boolean isActionPopupStackEmpty();
public abstract boolean isTransparrentOnlyActionsUpdateNow();
}
@@ -120,6 +120,7 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat
private final Map<AnAction, AnActionEvent> myQueuedNotificationsEvents = new LinkedHashMap<AnAction, AnActionEvent>();
private Runnable myPreloadActionsRunnable;
private boolean myTransparrentOnlyUpdate;
ActionManagerImpl(KeymapManager keymapManager, DataManager dataManager) {
myId2Action = new THashMap<String, Object>();
@@ -145,20 +146,39 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat
}
public void addTimerListener(int delay, final TimerListener listener) {
_addTimerListener(delay, listener, false);
}
public void removeTimerListener(TimerListener listener) {
_removeTimerListener(listener, false);
}
@Override
public void addTransparrentTimerListener(int delay, TimerListener listener) {
_addTimerListener(delay, listener, true);
}
@Override
public void removeTransparrentTimerListener(TimerListener listener) {
_removeTimerListener(listener, true);
}
private void _addTimerListener(int delay, final TimerListener listener, boolean transparrent) {
if (ApplicationManager.getApplication().isUnitTestMode()) return;
if (myTimer == null) {
myTimer = new MyTimer();
myTimer.start();
}
myTimer.addTimerListener(listener);
myTimer.addTimerListener(listener, transparrent);
}
public void removeTimerListener(TimerListener listener) {
private void _removeTimerListener(TimerListener listener, boolean transparrent) {
if (ApplicationManager.getApplication().isUnitTestMode()) return;
LOG.assertTrue(myTimer != null);
myTimer.removeTimerListener(listener);
myTimer.removeTimerListener(listener, transparrent);
}
public ActionPopupMenu createActionPopupMenu(String place, @NotNull ActionGroup group, @Nullable PresentationFactory presentationFactory) {
@@ -975,6 +995,11 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat
return myPopups.isEmpty();
}
@Override
public boolean isTransparrentOnlyActionsUpdateNow() {
return myTransparrentOnlyUpdate;
}
private void flushActionPerformed() {
final Set<AnAction> actions = myQueuedNotifications.keySet();
for (final AnAction eachAction : actions) {
@@ -1147,6 +1172,7 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat
private class MyTimer extends Timer implements ActionListener {
private final List<TimerListener> myTimerListeners = Collections.synchronizedList(new ArrayList<TimerListener>());
private final List<TimerListener> myTransparrentTimerListeners = Collections.synchronizedList(new ArrayList<TimerListener>());
private int myLastTimePerformed;
MyTimer() {
@@ -1155,12 +1181,20 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat
setRepeats(true);
}
public void addTimerListener(TimerListener listener){
myTimerListeners.add(listener);
public void addTimerListener(TimerListener listener, boolean transparent){
if (transparent) {
myTransparrentTimerListeners.add(listener);
} else {
myTimerListeners.add(listener);
}
}
public void removeTimerListener(TimerListener listener){
myTimerListeners.remove(listener);
public void removeTimerListener(TimerListener listener, boolean transparent){
if (transparent) {
myTransparrentTimerListeners.remove(listener);
} else {
myTimerListeners.remove(listener);
}
}
public void actionPerformed(ActionEvent e) {
@@ -1171,16 +1205,34 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat
final int lastEventCount = myLastTimePerformed;
myLastTimePerformed = ActivityTracker.getInstance().getCount();
if (myLastTimePerformed == lastEventCount) {
return;
}
boolean transparentOnly = myLastTimePerformed == lastEventCount;
final TimerListener[] listeners = myTimerListeners.toArray(new TimerListener[myTimerListeners.size()]);
try {
HashSet<TimerListener> notified = new HashSet<TimerListener>();
myTransparrentOnlyUpdate = transparentOnly;
notifyListeners(myTransparrentTimerListeners, notified);
if (transparentOnly) {
return;
}
notifyListeners(myTimerListeners, notified);
}
finally {
myTransparrentOnlyUpdate = false;
}
}
private void notifyListeners(final List<TimerListener> timerListeners, final Set<TimerListener> notified) {
final TimerListener[] listeners = timerListeners.toArray(new TimerListener[timerListeners.size()]);
IdeFocusManager.getInstance(null).doWhenFocusSettlesDown(new Runnable() {
public void run() {
for (TimerListener listener : listeners) {
if (myTimerListeners.contains(listener)) {
runListenerAction(listener);
if (timerListeners.contains(listener)) {
if (!notified.contains(listener)) {
notified.add(listener);
runListenerAction(listener);
}
}
}
}
@@ -73,7 +73,6 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
private final ActionGroup myActionGroup;
private final String myPlace;
@SuppressWarnings({"FieldCanBeLocal"}) private final MyKeymapManagerListener myKeymapManagerListener;
@SuppressWarnings({"FieldCanBeLocal"}) private final MyTimerListener myTimerListener;
private ArrayList<AnAction> myNewVisibleActions;
protected ArrayList<AnAction> myVisibleActions;
private final PresentationFactory myPresentationFactory;
@@ -100,6 +99,8 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
private JComponent myTargetComponent;
private boolean myReservePlaceAutoPopupIcon = true;
private WeakTimerListener myWeakTimerListener;
private ActionToolbarImpl.MyTimerListener myTimerListener;
public ActionToolbarImpl(final String place,
final ActionGroup actionGroup,
@@ -127,7 +128,6 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
myActionGroup = actionGroup;
myPresentationFactory = new PresentationFactory();
myKeymapManagerListener = new MyKeymapManagerListener();
myTimerListener = new MyTimerListener();
myVisibleActions = new ArrayList<AnAction>();
myNewVisibleActions = new ArrayList<AnAction>();
myDataManager = dataManager;
@@ -138,15 +138,30 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
mySecondaryActions.getTemplatePresentation().setIcon(mySecondaryGroupIcon);
mySecondaryActions.setPopup(true);
updateActions(updateActionsNow);
updateActions(updateActionsNow, false);
//
keymapManager.addKeymapManagerListener(new WeakKeymapManagerListener(keymapManager, myKeymapManagerListener));
actionManager.addTimerListener(500, new WeakTimerListener(actionManager, myTimerListener));
myTimerListener = new MyTimerListener();
myWeakTimerListener = new WeakTimerListener(actionManager, myTimerListener);
// If the panel doesn't handle mouse event then it will be passed to its parent.
// It means that if the panel is in slidindg mode then the focus goes to the editor
// and panel will be automatically hidden.
enableEvents(AWTEvent.MOUSE_MOTION_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK);
enableEvents(AWTEvent.MOUSE_MOTION_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK | AWTEvent.COMPONENT_EVENT_MASK | AWTEvent.CONTAINER_EVENT_MASK);
}
@Override
public void addNotify() {
super.addNotify();
myActionManager.addTimerListener(500, myWeakTimerListener);
myActionManager.addTransparrentTimerListener(500, myWeakTimerListener);
}
@Override
public void removeNotify() {
super.removeNotify();
myActionManager.removeTimerListener(myWeakTimerListener);
myActionManager.removeTransparrentTimerListener(myWeakTimerListener);
}
public JComponent getComponent() {
@@ -656,6 +671,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
}
private final class MyTimerListener implements TimerListener {
public ModalityState getModalityState() {
return ModalityState.stateForComponent(ActionToolbarImpl.this);
}
@@ -682,7 +698,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
}
}
updateActions(false);
updateActions(false, myActionManager.isTransparrentOnlyActionsUpdateNow());
}
}
@@ -715,16 +731,16 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
public void updateActionsImmediately() {
ApplicationManager.getApplication().assertIsDispatchThread();
updateActions(true);
updateActions(true, false);
}
private void updateActions(boolean now) {
private void updateActions(boolean now, final boolean transparrentOnly) {
final Runnable updateRunnable = new Runnable() {
public void run() {
myNewVisibleActions.clear();
final DataContext dataContext = getDataContext();
Utils.expandActionGroup(myActionGroup, myNewVisibleActions, myPresentationFactory, dataContext, myPlace, myActionManager);
Utils.expandActionGroup(myActionGroup, myNewVisibleActions, myPresentationFactory, dataContext, myPlace, myActionManager, transparrentOnly);
if (!myNewVisibleActions.equals(myVisibleActions)) {
// should rebuild UI
@@ -781,7 +797,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
if (myTargetComponent != null && myTargetComponent.isVisible()) {
ApplicationManager.getApplication().invokeLater(new DumbAwareRunnable() {
public void run() {
updateActions(false);
updateActions(false, false);
}
}, ModalityState.stateForComponent(myTargetComponent));
}
@@ -927,7 +943,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
Disposer.dispose(myPopup);
myPopup = null;
updateActions(false);
updateActions(false, false);
}
abstract static class PopupToolbar extends ActionToolbarImpl implements AnActionListener, Disposable {
@@ -80,6 +80,17 @@ public class Utils{
PresentationFactory presentationFactory,
DataContext context,
String place, ActionManager actionManager){
expandActionGroup(group, list, presentationFactory, context, place, actionManager, false);
}
/**
* @param actionManager manager
* @param list this list contains expanded actions.
*/
public static void expandActionGroup(@NotNull ActionGroup group,
ArrayList<AnAction> list,
PresentationFactory presentationFactory,
DataContext context,
String place, ActionManager actionManager, boolean transparrentOnly){
Presentation presentation = presentationFactory.getPresentation(group);
AnActionEvent e = new AnActionEvent(
null,
@@ -106,7 +117,11 @@ public class Utils{
presentation = presentationFactory.getPresentation(child);
AnActionEvent e1 = new AnActionEvent(null, context, place, presentation, actionManager, 0);
e1.setInjectedContext(child.isInInjectedContext());
if (!doUpdate(child, e1, presentation)) continue;
if ((transparrentOnly && child.isTransparentUpdate()) || !transparrentOnly) {
if (!doUpdate(child, e1, presentation)) continue;
}
if (!presentation.isVisible()) { // don't create invisible items in the menu
continue;
}
@@ -29,6 +29,7 @@ public abstract class XDebuggerActionBase extends AnAction {
protected XDebuggerActionBase() {
this(false);
setTransparentUpdate(true);
}
protected XDebuggerActionBase(final boolean hideDisabledInPopup) {