mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Smart menu for full screen mode (MS Windows)
This commit is contained in:
@@ -29,11 +29,21 @@ import com.intellij.openapi.actionSystem.impl.WeakTimerListener;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.wm.ex.WindowManagerEx;
|
||||
import com.intellij.ui.ScreenUtil;
|
||||
import com.intellij.util.ui.Animator;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.AWTEventListener;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
@@ -43,6 +53,17 @@ import java.util.ArrayList;
|
||||
* @author Vladimir Kondratyev
|
||||
*/
|
||||
public class IdeMenuBar extends JMenuBar {
|
||||
|
||||
private static final int COLLAPSED_HEIGHT = 2;
|
||||
|
||||
private enum State {
|
||||
EXPANDED, COLLAPSING, COLLAPSED, EXPANDING, TEMPORARY_EXPANDED;
|
||||
|
||||
boolean isInProgress() {
|
||||
return this == COLLAPSING || this == EXPANDING;
|
||||
}
|
||||
}
|
||||
|
||||
private final MyTimerListener myTimerListener;
|
||||
private ArrayList<AnAction> myVisibleActions;
|
||||
private ArrayList<AnAction> myNewVisibleActions;
|
||||
@@ -52,6 +73,13 @@ public class IdeMenuBar extends JMenuBar {
|
||||
private final Disposable myDisposable = Disposer.newDisposable();
|
||||
private boolean DISABLED = false;
|
||||
|
||||
@Nullable private final Animator myAnimator;
|
||||
@Nullable private final Timer myActivationWatcher;
|
||||
@NotNull private State myState = State.EXPANDED;
|
||||
private double myProgress = 0;
|
||||
private boolean myMouseInside = false;
|
||||
private boolean myActivated = false;
|
||||
|
||||
public IdeMenuBar(ActionManagerEx actionManager, DataManager dataManager) {
|
||||
myActionManager = actionManager;
|
||||
myTimerListener = new MyTimerListener();
|
||||
@@ -59,6 +87,121 @@ public class IdeMenuBar extends JMenuBar {
|
||||
myNewVisibleActions = new ArrayList<AnAction>();
|
||||
myPresentationFactory = new MenuItemPresentationFactory();
|
||||
myDataManager = dataManager;
|
||||
if (SystemInfo.isWindows) {
|
||||
myAnimator = new Animator("MenuBarAnimator", 8, 300, false) {
|
||||
@Override
|
||||
public void paintNow(int frame, int totalFrames, int cycle) {
|
||||
myProgress = (1 - Math.cos(Math.PI * ((float)frame / totalFrames))) / 2;
|
||||
revalidate();
|
||||
repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintCycleEnd() {
|
||||
myProgress = 1;
|
||||
switch (myState) {
|
||||
case COLLAPSING:
|
||||
setState(State.COLLAPSED);
|
||||
break;
|
||||
case EXPANDING:
|
||||
setState(State.TEMPORARY_EXPANDED);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
revalidate();
|
||||
repaint();
|
||||
}
|
||||
};
|
||||
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
|
||||
@Override
|
||||
public void eventDispatched(AWTEvent event) {
|
||||
MouseEvent mouseEvent = (MouseEvent)event;
|
||||
Component component = mouseEvent.getComponent();
|
||||
Component deepestComponent = SwingUtilities.getDeepestComponentAt(mouseEvent.getComponent(), mouseEvent.getX(), mouseEvent.getY());
|
||||
if (deepestComponent != null) {
|
||||
component = deepestComponent;
|
||||
}
|
||||
|
||||
if (myState != State.EXPANDED && !myState.isInProgress()) {
|
||||
myMouseInside = myActivated || isDescendingFrom(component, IdeMenuBar.this);
|
||||
if (myMouseInside && myState == State.COLLAPSED) {
|
||||
setState(State.EXPANDING);
|
||||
restartAnimator();
|
||||
}
|
||||
else if (!myMouseInside && myState != State.COLLAPSING && myState != State.COLLAPSED) {
|
||||
setState(State.COLLAPSING);
|
||||
restartAnimator();
|
||||
}
|
||||
}
|
||||
}
|
||||
}, AWTEvent.MOUSE_MOTION_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK);
|
||||
myActivationWatcher = new Timer(100, new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (myState == State.EXPANDED || myState == State.EXPANDING)
|
||||
return;
|
||||
boolean activated = isActivated();
|
||||
if (myActivated && !activated && myState == State.TEMPORARY_EXPANDED) {
|
||||
myActivated = false;
|
||||
setState(State.COLLAPSING);
|
||||
restartAnimator();
|
||||
}
|
||||
if (activated)
|
||||
myActivated = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
myAnimator = null;
|
||||
myActivationWatcher = null;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isDescendingFrom(@Nullable Component a, @NotNull Component b) {
|
||||
while (a != null) {
|
||||
if (a == b) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (a instanceof JPopupMenu) {
|
||||
a = ((JPopupMenu)a).getInvoker();
|
||||
} else {
|
||||
a = a.getParent();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isActivated() {
|
||||
int index = getSelectionModel().getSelectedIndex();
|
||||
if (index ==-1)
|
||||
return false;
|
||||
return getMenu(index).isPopupMenuVisible();
|
||||
}
|
||||
|
||||
|
||||
private void setState(@NotNull State state) {
|
||||
myState = state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
Dimension dimension = super.getPreferredSize();
|
||||
if (myState.isInProgress()) {
|
||||
dimension.height =
|
||||
COLLAPSED_HEIGHT + (int)((myState == State.COLLAPSING ? (1 - myProgress) : myProgress) * (dimension.height - COLLAPSED_HEIGHT));
|
||||
}
|
||||
else if (myState == State.COLLAPSED) {
|
||||
dimension.height = COLLAPSED_HEIGHT;
|
||||
}
|
||||
return dimension;
|
||||
}
|
||||
|
||||
private void restartAnimator() {
|
||||
if (myAnimator != null) {
|
||||
myAnimator.reset();
|
||||
myAnimator.resume();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,8 +211,24 @@ public class IdeMenuBar extends JMenuBar {
|
||||
public void addNotify() {
|
||||
super.addNotify();
|
||||
updateMenuActions();
|
||||
if (!ScreenUtil.isStandardAddRemoveNotify(this))
|
||||
if (!ScreenUtil.isStandardAddRemoveNotify(this)) {
|
||||
Window window = SwingUtilities.getWindowAncestor(this);
|
||||
if (window instanceof IdeFrameImpl) {
|
||||
boolean fullScreen = WindowManagerEx.getInstanceEx().isFullScreen((IdeFrameImpl)window);
|
||||
if (fullScreen) {
|
||||
setState(State.COLLAPSING);
|
||||
restartAnimator();
|
||||
} else {
|
||||
if (myAnimator != null) {
|
||||
myAnimator.suspend();
|
||||
}
|
||||
setState(State.EXPANDED);
|
||||
revalidate();
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Add updater for menus
|
||||
myActionManager.addTimerListener(1000, new WeakTimerListener(myActionManager, myTimerListener));
|
||||
UISettingsListener UISettingsListener = new UISettingsListener() {
|
||||
@@ -80,6 +239,9 @@ public class IdeMenuBar extends JMenuBar {
|
||||
};
|
||||
UISettings.getInstance().addUISettingsListener(UISettingsListener, myDisposable);
|
||||
Disposer.register(ApplicationManager.getApplication(), myDisposable);
|
||||
if (myActivationWatcher != null) {
|
||||
myActivationWatcher.start();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -88,6 +250,12 @@ public class IdeMenuBar extends JMenuBar {
|
||||
@Override
|
||||
public void removeNotify() {
|
||||
if (ScreenUtil.isStandardAddRemoveNotify(this)) {
|
||||
if (myActivationWatcher != null) {
|
||||
myActivationWatcher.stop();
|
||||
}
|
||||
if (myAnimator != null) {
|
||||
myAnimator.suspend();
|
||||
}
|
||||
Disposer.dispose(myDisposable);
|
||||
}
|
||||
super.removeNotify();
|
||||
@@ -144,6 +312,21 @@ public class IdeMenuBar extends JMenuBar {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintChildren(Graphics g) {
|
||||
if (SystemInfo.isWindows && myState.isInProgress()) {
|
||||
Graphics2D g2 = (Graphics2D)g;
|
||||
AffineTransform oldTransform = g2.getTransform();
|
||||
AffineTransform newTransform = oldTransform != null ? new AffineTransform(oldTransform) : new AffineTransform();
|
||||
newTransform.concatenate(AffineTransform.getTranslateInstance(0, getHeight() - super.getPreferredSize().height));
|
||||
g2.setTransform(newTransform);
|
||||
super.paintChildren(g2);
|
||||
g2.setTransform(oldTransform);
|
||||
} else {
|
||||
super.paintChildren(g);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hacks a problem under Alloy LaF which draws menu bar in different background menu items are drawn in.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user