blob: 89a0da4ee3b5f1f005cdb876eb0abf6578f2bb84 [file] [log] [blame]
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.openapi.wm.impl;
import com.intellij.diagnostic.IdeMessagePanel;
import com.intellij.diagnostic.MessagePool;
import com.intellij.ide.DataManager;
import com.intellij.ide.actions.CustomizeUIAction;
import com.intellij.ide.actions.ViewToolbarAction;
import com.intellij.ide.ui.UISettings;
import com.intellij.ide.ui.UISettingsListener;
import com.intellij.ide.ui.customization.CustomActionsSchema;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.actionSystem.ex.ActionManagerEx;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.wm.*;
import com.intellij.openapi.wm.ex.IdeFrameEx;
import com.intellij.openapi.wm.impl.status.IdeStatusBarImpl;
import com.intellij.openapi.wm.impl.status.MemoryUsagePanel;
import com.intellij.ui.PopupHandler;
import com.intellij.ui.components.JBLayeredPane;
import com.intellij.ui.components.JBPanel;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;
/**
* @author Anton Katilin
* @author Vladimir Kondratyev
*/
public class IdeRootPane extends JRootPane implements UISettingsListener {
/**
* Toolbar and status bar.
*/
private JComponent myToolbar;
private IdeStatusBarImpl myStatusBar;
private final Box myNorthPanel = Box.createVerticalBox();
private final List<IdeRootPaneNorthExtension> myNorthComponents = new ArrayList<IdeRootPaneNorthExtension>();
/**
* Current <code>ToolWindowsPane</code>. If there is no such pane then this field is null.
*/
private ToolWindowsPane myToolWindowsPane;
private JBPanel myContentPane;
private final ActionManager myActionManager;
private final UISettings myUISettings;
private final boolean myGlassPaneInitialized;
private final IdeGlassPaneImpl myGlassPane;
private final Application myApplication;
private MemoryUsagePanel myMemoryWidget;
private final StatusBarCustomComponentFactory[] myStatusBarCustomComponentFactories;
private boolean myFullScreen;
public IdeRootPane(ActionManagerEx actionManager, UISettings uiSettings, DataManager dataManager, Application application, final IdeFrame frame) {
myActionManager = actionManager;
myUISettings = uiSettings;
myContentPane.add(myNorthPanel, BorderLayout.NORTH);
myStatusBarCustomComponentFactories = application.getExtensions(StatusBarCustomComponentFactory.EP_NAME);
myApplication = application;
createStatusBar(frame);
updateStatusBarVisibility();
updateToolbar();
myContentPane.add(myStatusBar, BorderLayout.SOUTH);
if (WindowManagerImpl.isFloatingMenuBarSupported()) {
menuBar = new IdeMenuBar(actionManager, dataManager);
getLayeredPane().add(menuBar, new Integer(JLayeredPane.DEFAULT_LAYER - 1));
if (frame instanceof IdeFrameEx) {
addPropertyChangeListener(WindowManagerImpl.FULL_SCREEN, new PropertyChangeListener() {
@Override public void propertyChange(PropertyChangeEvent evt) {
myFullScreen = ((IdeFrameEx)frame).isInFullScreen();
}
});
}
}
else {
setJMenuBar(new IdeMenuBar(actionManager, dataManager));
}
myGlassPane = new IdeGlassPaneImpl(this);
setGlassPane(myGlassPane);
myGlassPaneInitialized = true;
myGlassPane.setVisible(false);
}
@Override
protected LayoutManager createRootLayout() {
return WindowManagerImpl.isFloatingMenuBarSupported() ? new MyRootLayout() : super.createRootLayout();
}
@Override
public void setGlassPane(final Component glass) {
if (myGlassPaneInitialized) throw new IllegalStateException("Setting of glass pane for IdeFrame is prohibited");
super.setGlassPane(glass);
}
/**
* Invoked when enclosed frame is being shown.
*/
public final void addNotify(){
super.addNotify();
myUISettings.addUISettingsListener(this);
}
/**
* Invoked when enclosed frame is being disposed.
*/
public final void removeNotify(){
myUISettings.removeUISettingsListener(this);
super.removeNotify();
}
/**
* Sets current tool windows pane (panel where all tool windows are located).
* If <code>toolWindowsPane</code> is <code>null</code> then the method just removes
* the current tool windows pane.
*/
final void setToolWindowsPane(@Nullable final ToolWindowsPane toolWindowsPane) {
final JComponent contentPane = (JComponent)getContentPane();
if(myToolWindowsPane != null){
contentPane.remove(myToolWindowsPane);
}
myToolWindowsPane = toolWindowsPane;
if(myToolWindowsPane != null) {
contentPane.add(myToolWindowsPane,BorderLayout.CENTER);
}
contentPane.revalidate();
}
protected JLayeredPane createLayeredPane() {
JLayeredPane p = new JBLayeredPane();
p.setName(this.getName()+".layeredPane");
return p;
}
@Override
public void setLayout(LayoutManager mgr) {
//First time mgr comes from createRootLayout(), it's OK. But then Alloy spoils it and breaks FullScreen mode under Windows
if (getLayout() != null && UIUtil.isUnderAlloyLookAndFeel()) return;
super.setLayout(mgr);
}
protected final Container createContentPane(){
return myContentPane = new IdePanePanel(new BorderLayout());
}
void updateToolbar() {
if (myToolbar != null) {
myNorthPanel.remove(myToolbar);
}
myToolbar = createToolbar();
myNorthPanel.add(myToolbar, 0);
updateToolbarVisibility();
myContentPane.revalidate();
}
void updateNorthComponents() {
for (IdeRootPaneNorthExtension northComponent : myNorthComponents) {
northComponent.revalidate();
}
myContentPane.revalidate();
}
void updateMainMenuActions(){
((IdeMenuBar)menuBar).updateMenuActions();
menuBar.repaint();
}
private JComponent createToolbar() {
ActionGroup group = (ActionGroup)CustomActionsSchema.getInstance().getCorrectedAction(IdeActions.GROUP_MAIN_TOOLBAR);
final ActionToolbar toolBar= myActionManager.createActionToolbar(
ActionPlaces.MAIN_TOOLBAR,
group,
true
);
toolBar.setLayoutPolicy(ActionToolbar.WRAP_LAYOUT_POLICY);
DefaultActionGroup menuGroup = new DefaultActionGroup();
menuGroup.add(new ViewToolbarAction());
menuGroup.add(new CustomizeUIAction());
PopupHandler.installUnknownPopupHandler(toolBar.getComponent(), menuGroup, myActionManager);
return toolBar.getComponent();
}
private void createStatusBar(IdeFrame frame) {
myUISettings.addUISettingsListener(this, myApplication);
myStatusBar = new IdeStatusBarImpl();
myStatusBar.install(frame);
myMemoryWidget = new MemoryUsagePanel();
if (myStatusBarCustomComponentFactories != null) {
for (final StatusBarCustomComponentFactory<JComponent> componentFactory : myStatusBarCustomComponentFactories) {
final JComponent c = componentFactory.createComponent(myStatusBar);
myStatusBar.addWidget(new CustomStatusBarWidget() {
public JComponent getComponent() {
return c;
}
@NotNull
public String ID() {
return c.getClass().getSimpleName();
}
public WidgetPresentation getPresentation(@NotNull PlatformType type) {
return null;
}
public void install(@NotNull StatusBar statusBar) {
}
public void dispose() {
componentFactory.disposeComponent(myStatusBar, c);
}
}, "before " + MemoryUsagePanel.WIDGET_ID);
}
}
myStatusBar.addWidget(myMemoryWidget);
myStatusBar.addWidget(new IdeMessagePanel(MessagePool.getInstance()), "before " + MemoryUsagePanel.WIDGET_ID);
setMemoryIndicatorVisible(myUISettings.SHOW_MEMORY_INDICATOR);
}
void setMemoryIndicatorVisible(final boolean visible) {
if (myMemoryWidget != null) {
myMemoryWidget.setShowing(visible);
if (!SystemInfo.isMac) {
myStatusBar.setBorder(BorderFactory.createEmptyBorder(1, 4, 0, visible ? 0 : 2));
}
}
}
@Nullable
final StatusBar getStatusBar() {
return myStatusBar;
}
private void updateToolbarVisibility(){
myToolbar.setVisible(myUISettings.SHOW_MAIN_TOOLBAR && !UISettings.getInstance().PRESENTATION_MODE);
}
private void updateStatusBarVisibility(){
myStatusBar.setVisible(myUISettings.SHOW_STATUS_BAR && !myUISettings.PRESENTATION_MODE);
}
public void installNorthComponents(final Project project) {
ContainerUtil.addAll(myNorthComponents, Extensions.getExtensions(IdeRootPaneNorthExtension.EP_NAME, project));
for (IdeRootPaneNorthExtension northComponent : myNorthComponents) {
myNorthPanel.add(northComponent.getComponent());
northComponent.uiSettingsChanged(myUISettings);
}
}
public void deinstallNorthComponents(){
for (IdeRootPaneNorthExtension northComponent : myNorthComponents) {
myNorthPanel.remove(northComponent.getComponent());
Disposer.dispose(northComponent);
}
myNorthComponents.clear();
}
public IdeRootPaneNorthExtension findByName(String name) {
for (IdeRootPaneNorthExtension northComponent : myNorthComponents) {
if (Comparing.strEqual(name, northComponent.getKey())) {
return northComponent;
}
}
return null;
}
public void uiSettingsChanged(UISettings source) {
setMemoryIndicatorVisible(source.SHOW_MEMORY_INDICATOR);
updateToolbarVisibility();
updateStatusBarVisibility();
for (IdeRootPaneNorthExtension component : myNorthComponents) {
component.uiSettingsChanged(source);
}
}
public boolean isOptimizedDrawingEnabled() {
return !myGlassPane.hasPainters() && myGlassPane.getComponentCount() == 0;
}
public ToolWindowsPane getToolWindowsPane() {
return myToolWindowsPane;
}
private class MyRootLayout extends RootLayout {
public Dimension preferredLayoutSize(Container parent) {
Dimension rd, mbd;
Insets i = getInsets();
if (contentPane != null) {
rd = contentPane.getPreferredSize();
}
else {
rd = parent.getSize();
}
if (menuBar != null && menuBar.isVisible() && !myFullScreen) {
mbd = menuBar.getPreferredSize();
}
else {
mbd = new Dimension(0, 0);
}
return new Dimension(Math.max(rd.width, mbd.width) + i.left + i.right,
rd.height + mbd.height + i.top + i.bottom);
}
public Dimension minimumLayoutSize(Container parent) {
Dimension rd, mbd;
Insets i = getInsets();
if (contentPane != null) {
rd = contentPane.getMinimumSize();
}
else {
rd = parent.getSize();
}
if (menuBar != null && menuBar.isVisible() && !myFullScreen) {
mbd = menuBar.getMinimumSize();
}
else {
mbd = new Dimension(0, 0);
}
return new Dimension(Math.max(rd.width, mbd.width) + i.left + i.right,
rd.height + mbd.height + i.top + i.bottom);
}
public Dimension maximumLayoutSize(Container target) {
Dimension rd, mbd;
Insets i = getInsets();
if (menuBar != null && menuBar.isVisible() && !myFullScreen) {
mbd = menuBar.getMaximumSize();
}
else {
mbd = new Dimension(0, 0);
}
if (contentPane != null) {
rd = contentPane.getMaximumSize();
}
else {
rd = new Dimension(Integer.MAX_VALUE,
Integer.MAX_VALUE - i.top - i.bottom - mbd.height - 1);
}
return new Dimension(Math.min(rd.width, mbd.width) + i.left + i.right,
rd.height + mbd.height + i.top + i.bottom);
}
public void layoutContainer(Container parent) {
Rectangle b = parent.getBounds();
Insets i = getInsets();
int contentY = 0;
int w = b.width - i.right - i.left;
int h = b.height - i.top - i.bottom;
if (layeredPane != null) {
layeredPane.setBounds(i.left, i.top, w, h);
}
if (glassPane != null) {
glassPane.setBounds(i.left, i.top, w, h);
}
if (menuBar != null && menuBar.isVisible()) {
Dimension mbd = menuBar.getPreferredSize();
menuBar.setBounds(0, 0, w, mbd.height);
if (!myFullScreen) {
contentY += mbd.height;
}
}
if (contentPane != null) {
contentPane.setBounds(0, contentY, w, h - contentY);
}
}
}
}