blob: 5e0f6e58d10696d47948ea5c4b55cb90dd117fec [file] [log] [blame]
/*
* Copyright 2000-2014 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.ide.navigationToolbar.ui;
import com.intellij.ide.navigationToolbar.NavBarItem;
import com.intellij.ide.navigationToolbar.NavBarPanel;
import com.intellij.ide.navigationToolbar.NavBarRootPaneExtension;
import com.intellij.ide.ui.UISettings;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.ui.ColorUtil;
import com.intellij.ui.Gray;
import com.intellij.util.containers.HashMap;
import com.intellij.util.ui.JBInsets;
import com.intellij.util.ui.UIUtil;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.Path2D;
import java.awt.image.BufferedImage;
import java.util.Map;
/**
* @author Konstantin Bulenkov
*/
public abstract class AbstractNavBarUI implements NavBarUI {
private final static Map<NavBarItem, Map<ImageType, BufferedImage>> myCache = new THashMap<NavBarItem, Map<ImageType, BufferedImage>>();
private enum ImageType {
INACTIVE, NEXT_ACTIVE, ACTIVE, INACTIVE_FLOATING, NEXT_ACTIVE_FLOATING, ACTIVE_FLOATING,
INACTIVE_NO_TOOLBAR, NEXT_ACTIVE_NO_TOOLBAR, ACTIVE_NO_TOOLBAR
}
@Override
public Insets getElementIpad(boolean isPopupElement) {
return isPopupElement ? new Insets(1, 2, 1, 2) : JBInsets.NONE;
}
@Override
public JBInsets getElementPadding() {
return new JBInsets(3, 3, 3, 3);
}
@Override
public Font getElementFont(NavBarItem navBarItem) {
return SystemInfo.isMac ? UIUtil.getLabelFont(UIUtil.FontSize.SMALL) : UIUtil.getLabelFont();
}
@Override
public Color getBackground(boolean selected, boolean focused) {
return selected && focused ? UIUtil.getListSelectionBackground() : UIUtil.getListBackground();
}
@Nullable
@Override
public Color getForeground(boolean selected, boolean focused, boolean inactive) {
return (selected && focused) ? UIUtil.getListSelectionForeground()
: inactive ? UIUtil.getInactiveTextColor() : null;
}
@Override
public short getSelectionAlpha() {
return (short)(UIUtil.isUnderAlloyLookAndFeel() && !UIUtil.isUnderAlloyIDEALookAndFeel() ? 255 : 150);
}
@Override
public boolean isDrawMacShadow(boolean selected, boolean focused) {
return false;
}
@Override
public void doPaintNavBarItem(Graphics2D g, NavBarItem item, NavBarPanel navbar) {
final boolean floating = navbar.isInFloatingMode();
boolean toolbarVisible = UISettings.getInstance().SHOW_MAIN_TOOLBAR;
final boolean selected = item.isSelected() && item.isFocused();
boolean nextSelected = item.isNextSelected() && navbar.hasFocus();
Map<ImageType, BufferedImage> cached = myCache.get(item);
ImageType type;
if (floating) {
type = selected ? ImageType.ACTIVE_FLOATING : nextSelected ? ImageType.NEXT_ACTIVE_FLOATING : ImageType.INACTIVE_FLOATING;
} else {
if (toolbarVisible) {
type = selected ? ImageType.ACTIVE : nextSelected ? ImageType.NEXT_ACTIVE : ImageType.INACTIVE;
} else {
type = selected ? ImageType.ACTIVE_NO_TOOLBAR : nextSelected ? ImageType.NEXT_ACTIVE_NO_TOOLBAR : ImageType.INACTIVE_NO_TOOLBAR;
}
}
if (cached == null) {
cached = new HashMap<ImageType, BufferedImage>();
myCache.put(item, cached);
}
BufferedImage image = cached.get(type);
if (image == null) {
image = drawToBuffer(item, floating, toolbarVisible, selected, navbar);
cached.put(type, image);
}
UIUtil.drawImage(g, image, 0, 0, null);
Icon icon = item.getIcon();
final int offset = item.isFirstElement() ? getFirstElementLeftOffset() : 0;
final int iconOffset = getElementPadding().left + offset;
icon.paintIcon(item, g, iconOffset, (item.getHeight() - icon.getIconHeight()) / 2);
final int textOffset = icon.getIconWidth() + getElementPadding().width() + offset;
item.doPaintText(g, textOffset);
}
private BufferedImage drawToBuffer(NavBarItem item, boolean floating, boolean toolbarVisible, boolean selected, NavBarPanel navbar) {
int w = item.getWidth();
int h = item.getHeight();
int offset = (w - getDecorationOffset());
int h2 = h / 2;
BufferedImage result = UIUtil.createImage(w, h, BufferedImage.TYPE_INT_ARGB);
Color defaultBg = UIUtil.isUnderDarcula() ? Gray._100 : Color.WHITE;
final Paint bg = floating ? defaultBg : null;/*UIUtil.getGradientPaint(0, 0, new Color(255, 255, 255, 30), 0, h, new Color(255, 255, 255, 10));*/
final Color selection = UIUtil.getListSelectionBackground();
Graphics2D g2 = result.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Path2D.Double shape = new Path2D.Double();
shape.moveTo(0, 0);
shape.lineTo(offset, 0);
shape.lineTo(w, h2);
shape.lineTo(offset, h);
shape.lineTo(0, h);
shape.closePath();
Path2D.Double endShape = new Path2D.Double();
endShape.moveTo(offset, 0);
endShape.lineTo(w, 0);
endShape.lineTo(w, h);
endShape.lineTo(offset, h);
endShape.lineTo(w, h2);
endShape.closePath();
if (bg != null && toolbarVisible) {
g2.setPaint(bg);
g2.fill(shape);
if (!item.isLastElement() || floating) {
g2.fill(endShape);
}
}
if (selected) {
Path2D.Double focusShape = new Path2D.Double();
if (toolbarVisible || floating) {
focusShape.moveTo(offset, 0);
} else {
focusShape.moveTo(0, 0);
focusShape.lineTo(offset, 0);
}
focusShape.lineTo(w - 1, h2);
focusShape.lineTo(offset, h - 1);
if (!toolbarVisible && !floating) {
focusShape.lineTo(0, h - 1);
}
g2.setColor(selection);
if (floating && item.isLastElement()) {
g2.fillRect(0, 0, w, h);
} else {
g2.fill(shape);
g2.setColor(new Color(0, 0, 0, 70));
g2.draw(focusShape);
}
}
if (item.isNextSelected() && navbar.hasFocus()) {
g2.setColor(selection);
g2.fill(endShape);
Path2D.Double endFocusShape = new Path2D.Double();
if (toolbarVisible || floating) {
endFocusShape.moveTo(offset, 0);
} else {
endFocusShape.moveTo(w, 0);
endFocusShape.lineTo(offset, 0);
}
endFocusShape.lineTo(w - 1, h2);
endFocusShape.lineTo(offset, h - 1);
if (!toolbarVisible && !floating) {
endFocusShape.lineTo(w, h - 1);
}
g2.setColor(new Color(0, 0, 0, 70));
g2.draw(endFocusShape);
}
g2.translate(offset, 0);
int off = getDecorationOffset() - 1;
if (!floating || !item.isLastElement()) {
if (toolbarVisible || floating) {
if (!selected && (!navbar.hasFocus() | !item.isNextSelected())) {
Color hl = UIUtil.isUnderDarcula()? Gray._128.withAlpha(100) : UIUtil.isUnderAlloyLookAndFeel() ? new Color(255, 255, 255, 200) : Gray._205;
drawArrow(g2, new Color(0, 0, 0, 70), hl, off, h, !selected && !floating, false);
}
} else {
if (!selected && (!navbar.hasFocus() | !item.isNextSelected())) {
Color hl = UIUtil.isUnderDarcula() ? Gray._128.withAlpha(100) : Gray._255.withAlpha(200);
drawArrow(g2, new Color(0, 0, 0, 150), hl, off, h, !selected && !floating, true);
}
}
}
g2.dispose();
return result;
}
private static void drawArrow(Graphics2D g2d, Color c, Color light, int decorationOffset, int h, boolean highlight, boolean gradient) {
int off = decorationOffset - 1;
g2d.setColor(c);
if (gradient) {
g2d.setPaint(UIUtil.getGradientPaint(0, 0, ColorUtil.toAlpha(c, 10), 0, h / 2, c));
}
g2d.drawLine(0, 0, off, h / 2);
if (gradient) {
g2d.setPaint(UIUtil.getGradientPaint(0, h / 2, c, 0, h, ColorUtil.toAlpha(c, 10)));
}
g2d.drawLine(off, h / 2, 0, h);
if (highlight) {
g2d.translate(-1, 0);
g2d.setColor(light);
if (gradient) {
g2d.setPaint(UIUtil.getGradientPaint(0, 0, ColorUtil.toAlpha(light, 10), 0, h / 2, light));
}
g2d.drawLine(0, 0, off, h / 2);
if (gradient) {
g2d.setPaint(UIUtil.getGradientPaint(0, h / 2, light, 0, h, ColorUtil.toAlpha(light, 10)));
}
g2d.drawLine(off, h / 2, 0, h);
}
}
private int getDecorationOffset() {
return 8;
}
private int getFirstElementLeftOffset() {
return 6;
}
@Override
public Dimension getOffsets(NavBarItem item) {
final Dimension size = new Dimension();
if (! item.isPopupElement()) {
size.width += getDecorationOffset() + getElementPadding().width() + (item.isFirstElement() ? getFirstElementLeftOffset() : 0);
size.height += getElementPadding().height();
}
return size;
}
@Override
public Insets getWrapperPanelInsets(Insets insets) {
return new Insets(insets.top + (shouldPaintWrapperPanel() ? 1 : 0), insets.left, insets.bottom, insets.right);
}
private static boolean shouldPaintWrapperPanel() {
return !UISettings.getInstance().SHOW_MAIN_TOOLBAR && NavBarRootPaneExtension.runToolbarExists();
}
protected Color getBackgroundColor() {
return UIUtil.getSlightlyDarkerColor(UIUtil.getPanelBackground());
}
@Override
public void doPaintNavBarPanel(Graphics2D g, Rectangle r, boolean mainToolbarVisible, boolean undocked) {
g.setColor(getBackgroundColor());
if (!UIUtil.isUnderAquaLookAndFeel() && mainToolbarVisible) {
g.fillRect(0, 0, r.width, r.height);
}
}
@Override
public void clearItems() {
myCache.clear();
}
@Override
public int getPopupOffset(@NotNull NavBarItem item) {
return item.isFirstElement() ? 0 : 5;
}
}