blob: 5be40aedd921635f5db881d180758b446ebca15b [file] [log] [blame]
/*
* Copyright 2000-2012 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.diff.impl.util;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.diff.DiffRequest;
import com.intellij.openapi.diff.DiffToolbar;
import com.intellij.openapi.diff.ex.DiffStatusBar;
import com.intellij.openapi.diff.impl.DiffToolbarComponent;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.util.Getter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.util.List;
public class DiffPanelOuterComponent extends JPanel implements DataProvider {
private final DiffStatusBar myStatusBar;
private final DiffToolbarComponent myToolbar;
@Nullable private DiffRequest.ToolbarAddons myDefaultActions;
private DataProvider myDataProvider = null;
private DeferScrollToFirstDiff myScrollState = NO_SCROLL_NEEDED;
private ScrollingPanel myScrollingPanel = null;
private final JPanel myBottomContainer;
private JComponent myBottomComponent;
private JPanel myWrapper;
private Getter<Integer> myPreferredHeightGetter;
private int myPrefferedWidth;
private Getter<Integer> myDefaultHeight;
public DiffPanelOuterComponent(List<TextDiffType> diffTypes, @Nullable DiffRequest.ToolbarAddons toolbarAddons) {
super(new BorderLayout());
myStatusBar = new DiffStatusBar(diffTypes);
myBottomContainer = new JPanel(new BorderLayout());
myBottomContainer.add(myStatusBar, BorderLayout.SOUTH);
add(myBottomContainer, BorderLayout.SOUTH);
myDefaultActions = toolbarAddons;
myToolbar = new DiffToolbarComponent(this);
disableToolbar(false);
myWrapper = new JPanel(new BorderLayout());
add(myWrapper, BorderLayout.CENTER);
myDefaultHeight = new Getter<Integer>() {
@Override
public Integer get() {
return 400;
}
};
myPreferredHeightGetter = myDefaultHeight;
myPrefferedWidth = 600;
}
public void setToolbarActions(@NotNull DiffRequest.ToolbarAddons toolbarAddons) {
myDefaultActions = toolbarAddons;
}
public DiffToolbar resetToolbar() {
if (myDefaultActions != null) {
myToolbar.resetToolbar(myDefaultActions);
}
return myToolbar.getToolbar();
}
public void resetDiffComponent(JComponent component, ScrollingPanel scrollingPanel) {
myWrapper.removeAll();
insertDiffComponent(component, scrollingPanel);
}
public void insertDiffComponent(JComponent component, ScrollingPanel scrollingPanel) {
myWrapper.add(component, BorderLayout.CENTER);
setScrollingPanel(scrollingPanel);
}
public void insertTopComponent(JComponent component) {
myWrapper.add(component, BorderLayout.NORTH);
}
public JComponent getBottomComponent() {
return myBottomComponent;
}
public void setBottomComponent(JComponent component) {
if (myBottomComponent != null) {
myBottomContainer.remove(myBottomComponent);
}
myBottomComponent = component;
if (myBottomComponent != null) {
myBottomContainer.add(BorderLayout.CENTER, component);
}
}
public void setDataProvider(DataProvider dataProvider) {
myDataProvider = dataProvider;
}
public void setStatusBarText(String text) {
myStatusBar.setText(text);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(myPrefferedWidth, myPreferredHeightGetter.get());
}
public void setPrefferedWidth(int prefferedWidth) {
myPrefferedWidth = prefferedWidth;
}
public void setPreferredHeightGetter(final Getter<Integer> getter) {
if (getter == null) {
myPreferredHeightGetter = myDefaultHeight;
} else {
myPreferredHeightGetter = getter;
}
}
public void removeStatusBar() {
if (myStatusBar != null) {
myStatusBar.setVisible(false);
}
}
public Object getData(String dataId) {
if (PlatformDataKeys.SOURCE_NAVIGATION_LOCKED.is(dataId)) {
return Boolean.TRUE;
}
if (myDataProvider == null) {
return null;
}
if (CommonDataKeys.EDITOR.is(dataId)) {
if (myBottomComponent != null) {
// we don't want editor actions to be executed when the bottom component has focus
final Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
if (myBottomComponent.isAncestorOf(focusOwner)) {
return null;
}
}
final FocusDiffSide side = (FocusDiffSide)myDataProvider.getData(FocusDiffSide.DATA_KEY.getName());
if (side != null) {
final Editor editor = side.getEditor();
return editor != null && editor.getComponent().hasFocus() ? editor : null;
}
}
return myDataProvider.getData(dataId);
}
public void setScrollingPanel(ScrollingPanel scrollingPanel) {
myScrollingPanel = scrollingPanel;
}
public void requestScrollEditors() {
myScrollState = SCROLL_WHEN_POSSIBLE;
tryScrollNow();
}
private void tryScrollNow() {
if (myScrollingPanel == null) return;
myScrollState.deferScroll(this);
}
private void performScroll() {
DeferScrollToFirstDiff newState = myScrollState.scrollNow(myScrollingPanel, this);
if (newState != null) myScrollState = newState;
}
public void addNotify() {
super.addNotify();
tryScrollNow();
}
public void setBounds(int x, int y, int width, int height) {
super.setBounds(x, y, width, height);
tryScrollNow();
}
protected void validateTree() {
super.validateTree();
tryScrollNow();
}
public void cancelScrollEditors() {
myScrollState = NO_SCROLL_NEEDED;
}
public void removeTopComponent(final JComponent jComponent) {
myWrapper.remove(jComponent);
}
public void addStatusBar() {
if (myStatusBar != null) {
myStatusBar.setVisible(true);
}
}
private interface DeferScrollToFirstDiff {
DeferScrollToFirstDiff scrollNow(ScrollingPanel panel, JComponent component);
void deferScroll(DiffPanelOuterComponent outer);
}
public interface ScrollingPanel {
void scrollEditors();
}
private static final DeferScrollToFirstDiff NO_SCROLL_NEEDED = new DeferScrollToFirstDiff() {
public DeferScrollToFirstDiff scrollNow(ScrollingPanel panel, JComponent component) {
return NO_SCROLL_NEEDED;
}
public void deferScroll(DiffPanelOuterComponent outer) {
}
};
private static final DeferScrollToFirstDiff SCROLL_WHEN_POSSIBLE = new DeferScrollToFirstDiff() {
public DeferScrollToFirstDiff scrollNow(ScrollingPanel panel, JComponent component) {
if (!component.isDisplayable()) return null;
panel.scrollEditors();
return NO_SCROLL_NEEDED;
}
public void deferScroll(final DiffPanelOuterComponent outer) {
if (!outer.isDisplayable()) return;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
outer.performScroll();
}
});
}
};
public void disableToolbar(boolean disable) {
if (disable && isToolbarEnabled()) remove(myToolbar);
else if (myToolbar.getParent() == null) add(myToolbar, BorderLayout.NORTH);
}
public boolean isToolbarEnabled() {
return myToolbar.getParent() != null;
}
public void registerToolbarActions() {
myToolbar.getToolbar().registerKeyboardActions(this);
}
public void setColorScheme(EditorColorsScheme scheme) {
myStatusBar.setColorScheme(scheme);
}
}