losing the battle with TabbedPaneUI, switch back to old school

This commit is contained in:
Ben Fry
2015-05-19 00:52:35 -04:00
parent 114d0b9989
commit 63a892fe47
6 changed files with 279 additions and 33 deletions
+82 -26
View File
@@ -37,27 +37,31 @@ import javax.swing.*;
*/
public class EditorHeader extends JComponent {
// height of this tab bar
static final int HIGH = 30;
static final int HIGH = 29;
// standard UI sizing (OS-specific, but generally consistent)
// static final int SCROLLBAR_WIDTH = 16;
// amount of space on the left edge before the tabs start
static final int MARGIN_WIDTH = Editor.LEFT_GUTTER;
// static final int MARGIN_WIDTH = Editor.LEFT_GUTTER;
static final int ARROW_TAB_WIDTH = 23;
static final int ARROW_TAB_WIDTH = 18;
// distance from the righthand side of a tab to the drop-down arrow
// static final int ARROW_GAP_WIDTH = 8;
// indent x/y for notch on the tab
static final int ARROW_TOP = 12;
static final int ARROW_BOTTOM = 20;
static final int ARROW_WIDTH = 9;
static final int ARROW_TOP = 11;
static final int ARROW_BOTTOM = 18;
static final int ARROW_WIDTH = 6;
static final int CURVE_RADIUS = 6;
// static final int NOTCH = 0;
// how far to raise the tab from the bottom of this Component
static final int TAB_HEIGHT = HIGH;
// static final int TAB_HEIGHT = HIGH;
static final int TAB_TOP = 0;
static final int TAB_BOTTOM = 27;
// // line that continues across all of the tabs for the current one
// static final int TAB_STRETCH = 3;
// amount of extra space between individual tabs
static final int TAB_BETWEEN = 4;
static final int TAB_BETWEEN = 3;
// amount of margin on the left/right for the text on the tab
static final int TEXT_MARGIN = 16;
// width of the tab when no text visible
@@ -201,12 +205,9 @@ public class EditorHeader extends JComponent {
public void paintComponent(Graphics screen) {
setOpaque(false);
if (screen == null) return;
Sketch sketch = editor.getSketch();
if (sketch == null) return; // ??
if (sketch == null) return; // possible?
Dimension size = getSize();
if ((size.width != sizeW) || (size.height != sizeH)) {
@@ -274,7 +275,7 @@ public class EditorHeader extends JComponent {
font.getStringBounds(tab.text, g2.getFontRenderContext()).getWidth();
}
// make sure everything can fit
if (!placeTabs(MARGIN_WIDTH, tabMax, null)) {
if (!placeTabs(Editor.LEFT_GUTTER, tabMax, null)) {
//System.arraycopy(tabs, 0, visitOrder, 0, tabs.length);
// always show the tab with the sketch's name
// System.arraycopy(tabs, 1, visitOrder, 0, tabs.length - 1);
@@ -292,14 +293,14 @@ public class EditorHeader extends JComponent {
// Keep shrinking the tabs one-by-one until things fit properly
for (int i = 0; i < visitOrder.length; i++) {
tabs[visitOrder[i].index].textVisible = false;
if (placeTabs(MARGIN_WIDTH, tabMax, null)) {
if (placeTabs(Editor.LEFT_GUTTER, tabMax, null)) {
break;
}
}
}
// now actually draw the tabs
if(!placeTabs(MARGIN_WIDTH, tabMax - ARROW_TAB_WIDTH, g2)){
if (!placeTabs(Editor.LEFT_GUTTER, tabMax - ARROW_TAB_WIDTH, g2)){
// draw the dropdown menu target at the right of the window
menuRight = tabMax;
menuLeft = menuRight - ARROW_TAB_WIDTH;
@@ -310,12 +311,18 @@ public class EditorHeader extends JComponent {
}
g.setColor(tabColor[UNSELECTED]);
drawTab(g, menuLeft, menuRight);
drawTab(g, menuLeft, menuRight, false, true);
// int arrowY = (getHeight() - TAB_HEIGHT - TAB_STRETCH) + (TAB_HEIGHT - ARROW_HEIGHT)/2;
// g.drawImage(tabArrow, menuLeft, arrowY,
// ARROW_WIDTH, ARROW_HEIGHT, null);
// TODO draw arrow here
g.setColor(tabColor[SELECTED]);
// can't be done with lines, b/c retina leaves tiny hairlines
g.fillRect(Editor.LEFT_GUTTER, TAB_BOTTOM,
editor.getWidth(), 2);
g.setColor(arrowColor);
GeneralPath trianglePath = new GeneralPath();
float x1 = menuLeft + (ARROW_TAB_WIDTH - ARROW_WIDTH) / 2f;
@@ -334,8 +341,8 @@ public class EditorHeader extends JComponent {
Sketch sketch = editor.getSketch();
int x = left;
final int bottom = getHeight(); // - TAB_STRETCH;
final int top = bottom - TAB_HEIGHT;
// final int bottom = getHeight(); // - TAB_STRETCH;
// final int top = bottom - TAB_HEIGHT;
// GeneralPath path = null;
for (int i = 0; i < sketch.getCodeCount(); i++) {
@@ -376,7 +383,7 @@ public class EditorHeader extends JComponent {
if (g != null && tab.right < right) {
g.setColor(tabColor[state]);
drawTab(g, tab.left, tab.right);
drawTab(g, tab.left, tab.right, i == 0, false);
// path.lineTo(x - NOTCH, top);
// path.lineTo(x, top + NOTCH);
// path.lineTo(x, bottom);
@@ -392,8 +399,8 @@ public class EditorHeader extends JComponent {
g.setColor(textColor[state]);
// int baseline = (int) Math.ceil((sizeH + fontAscent) / 2.0);
//int baseline = bottom - (TAB_HEIGHT - fontAscent)/2;
int tabHeight = TAB_HEIGHT; //bottom - top;
int baseline = top + (tabHeight + fontAscent) / 2;
int tabHeight = TAB_BOTTOM - TAB_TOP;
int baseline = TAB_TOP + (tabHeight + fontAscent) / 2;
//g.drawString(sketch.code[i].name, textLeft, baseline);
g.drawString(tab.text, textLeft, baseline);
// g.drawLine(tab.left, baseline-fontAscent, tab.right, baseline-fontAscent);
@@ -403,7 +410,7 @@ public class EditorHeader extends JComponent {
if (code.isModified()) {
g.setColor(modifiedColor);
//g.drawLine(tab.left + NOTCH, top, tab.right - NOTCH, top);
g.drawLine(tab.left, top, tab.right, top);
g.drawLine(tab.left, TAB_TOP, tab.right, TAB_TOP);
}
}
@@ -425,10 +432,59 @@ public class EditorHeader extends JComponent {
}
private void drawTab(Graphics g, int left, int right) {
final int bottom = getHeight(); // - TAB_STRETCH;
final int top = bottom - TAB_HEIGHT;
g.fillRect(left, top, right - left, bottom - top);
private void drawTab(Graphics g, int left, int right,
boolean leftNotch, boolean rightNotch) {
// final int bottom = getHeight(); // - TAB_STRETCH;
// final int top = bottom - TAB_HEIGHT;
// g.fillRect(left, top, right - left, bottom - top);
Graphics2D g2 = (Graphics2D) g;
// GeneralPath path = new GeneralPath();
roundRect(g2, left, TAB_TOP, right, TAB_BOTTOM,
leftNotch ? CURVE_RADIUS : 0,
rightNotch ? CURVE_RADIUS : 0,
0, 0);
// path.moveTo(left, TAB_BOTTOM);
// if (left == MARGIN_WIDTH) { // first tab on the left
// path.lineTo(left, TAB_TOP - CURVE_RADIUS);
// }
}
private void roundRect(Graphics2D g2,
float x1, float y1, float x2, float y2,
float tl, float tr, float br, float bl) {
GeneralPath path = new GeneralPath();
// vertex(x1+tl, y1);
if (tr != 0) {
path.moveTo(x2-tr, y1);
path.quadTo(x2, y1, x2, y1+tr);
} else {
path.moveTo(x2, y1);
}
if (br != 0) {
path.lineTo(x2, y2-br);
path.quadTo(x2, y2, x2-br, y2);
} else {
path.lineTo(x2, y2);
}
if (bl != 0) {
path.lineTo(x1+bl, y2);
path.quadTo(x1, y2, x1, y2-bl);
} else {
path.lineTo(x1, y2);
}
if (tl != 0) {
path.lineTo(x1, y1+tl);
path.quadTo(x1, y1, x1+tl, y1);
} else {
path.lineTo(x1, y1);
}
path.closePath();
g2.fill(path);
}
+2 -2
View File
@@ -722,7 +722,7 @@ public class Toolkit {
monoFont = createFont("SourceCodePro-Regular.ttf", size);
//monoBoldFont = createFont("SourceCodePro-Semibold.ttf", size);
monoBoldFont = createFont("SourceCodePro-Bold.ttf", size);
// additional language constraints
if ("el".equals(Language.getLanguage())) {
if (!monoFont.canDisplay(GREEK_SMALL_LETTER_ALPHA) ||
@@ -758,7 +758,7 @@ public class Toolkit {
try {
sansFont = createFont("SourceSansPro-Regular.ttf", size);
sansBoldFont = createFont("SourceSansPro-Semibold.ttf", size);
// additional language constraints
if ("el".equals(Language.getLanguage())) {
if (!sansFont.canDisplay(GREEK_SMALL_LETTER_ALPHA) ||
+10 -5
View File
@@ -10,14 +10,19 @@ status.font = processing.sans,plain,14
# TABS
# Settings for the tab area at the top.
header.text.font = processing.sans,bold,15
header.text.font = processing.sans,bold,13
header.text.selected.color = #000000
header.text.unselected.color = #ffffff
header.tab.selected.color = #ffffff
header.tab.unselected.color = #657d87
header.tab.arrow.color = #000000
#header.tab.arrow.color = #000000
header.tab.arrow.color = #ffffff
header.gradient.top = #132638
header.gradient.bottom = #122535
#header.tab.selected.color = #ffffff
#header.tab.unselected.color = #657d87
# r11-002
header.tab.selected.color = #e0fffd
header.tab.unselected.color = #2d4251
# CONSOLE
# The font is handled by preferences, so its size/etc are modifiable.
@@ -51,7 +56,7 @@ divider.dot.color = #505050
#toolbar.sketch.color = #ffffff
toolbar.rollover.font = processing.sans,plain,12
toolbar.rollover.color = #ffffff
toolbar.gradient.top = #142c40
toolbar.gradient.top = #142a3e
toolbar.gradient.bottom = #132638
# MODE SELECTOR
@@ -211,6 +211,8 @@ public class JavaEditor extends Editor {
JTabbedPane tabPane = new JTabbedPane(JTabbedPane.BOTTOM);
// tabPane.setUI(new BasicTabbedPaneUI());
tabPane.setUI(new SimpleTabbedPaneUI());
// tabPane.setUI(new SillyTabbedPaneUI());
// tabPane.setUI(new PlasticTabbedPaneUI());
// tabPane.setBorder(BorderFactory.createEmptyBorder());
// tabPane.setBackground(Color.RED);
@@ -0,0 +1,179 @@
package processing.mode.java;
import javax.swing.*;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicTabbedPaneUI;
import java.awt.*;
public class SillyTabbedPaneUI extends BasicTabbedPaneUI {
static final int HIGH = 30;
// controls the ugly extra amount at the top
static private final Insets NO_INSETS = new Insets(0, 0, 0, 0);
// private Font selectedFont;
// private FontMetrics selectedMetrics;
// /**
// * The color to use to fill in the background
// */
// private Color fillColor;
static public ComponentUI createUI(JComponent c) {
return new SillyTabbedPaneUI();
}
protected void installDefaults() {
super.installDefaults();
tabAreaInsets.left = 4;
selectedTabPadInsets = new Insets(0, 0, 0, 0);
tabInsets = selectedTabPadInsets;
// tabPane.setBackground(Color.CYAN);
// Color background = tabPane.getBackground();
// fillColor = background.darker();
// selectedFont = tabPane.getFont().deriveFont(Font.BOLD);
// selectedMetrics = tabPane.getFontMetrics(selectedFont);
}
public int getTabRunCount(JTabbedPane pane) {
return 1;
}
protected Insets getContentBorderInsets(int tabPlacement) {
return NO_INSETS;
}
protected int calculateTabHeight(int tabPlacement, int tabIndex, int fontHeight) {
return HIGH;
// int vHeight = fontHeight;
// if (vHeight % 2 > 0) {
// vHeight++;
// }
// return vHeight;
}
protected int calculateTabWidth(int tabPlacement, int tabIndex, FontMetrics metrics) {
return super.calculateTabWidth(tabPlacement, tabIndex, metrics) + metrics.getHeight();
}
protected void paintTabBackground(Graphics g, int tabPlacement, int tabIndex,
int x, int y, int w, int h, boolean isSelected) {
g.setColor(isSelected ? Color.RED : Color.ORANGE);
g.fillRect(x, y, w, h);
/*
Polygon shape = new Polygon();
shape.addPoint(x, y + h);
shape.addPoint(x, y);
shape.addPoint(x + w - (h / 2), y);
if (isSelected || (tabIndex == (rects.length - 1)))
{
shape.addPoint(x + w + (h / 2), y + h);
}
else
{
shape.addPoint(x + w, y + (h / 2));
shape.addPoint(x + w, y + h);
}
g.setColor(tabPane.getBackground());
g.fillPolygon(shape);
*/
}
/** Paint the border of an individual tab */
protected void paintTabBorder(Graphics g, int tabPlacement, int tabIndex,
int x, int y, int w, int h, boolean isSelected) {
}
protected void paintContentBorderTopEdge(Graphics g, int tabPlacement, int selectedIndex,
int x, int y, int w, int h) {
/*
Rectangle selectedRect = selectedIndex < 0 ? null : getTabBounds(selectedIndex, calcRect);
selectedRect.width = selectedRect.width + (selectedRect.height / 2) - 1;
g.setColor(Color.BLACK);
g.drawLine(x, y, selectedRect.x, y);
g.drawLine(selectedRect.x + selectedRect.width + 1, y, x + w, y);
g.setColor(Color.WHITE);
g.drawLine(x, y + 1, selectedRect.x, y + 1);
g.drawLine(selectedRect.x + 1, y + 1, selectedRect.x + 1, y);
g.drawLine(selectedRect.x + selectedRect.width + 2, y + 1, x + w, y + 1);
g.setColor(shadow);
g.drawLine(selectedRect.x + selectedRect.width, y, selectedRect.x + selectedRect.width + 1, y + 1);
*/
}
protected void paintContentBorderRightEdge(Graphics g, int tabPlacement, int selectedIndex,
int x, int y, int w, int h) {
}
protected void paintContentBorderLeftEdge(Graphics g, int tabPlacement, int selectedIndex,
int x, int y, int w, int h) {
}
protected void paintContentBorderBottomEdge(Graphics g, int tabPlacement, int selectedIndex,
int x, int y, int w, int h) {
}
protected void paintFocusIndicator(Graphics g, int tabPlacement, Rectangle[] rects,
int tabIndex, Rectangle iconRect,
Rectangle textRect, boolean isSelected) {
}
protected void paintTabArea(Graphics g, int tabPlacement, int selectedIndex) {
int tw = tabPane.getBounds().width;
// g.setColor(fillColor);
g.setColor(Color.YELLOW);
g.fillRect(0, 0, tw, rects[0].height + 3);
super.paintTabArea(g, tabPlacement, selectedIndex);
}
/*
protected void paintText(Graphics g, int tabPlacement, Font font, FontMetrics metrics, int tabIndex, String title, Rectangle textRect, boolean isSelected)
{
if (isSelected)
{
int vDifference = (int)(selectedMetrics.getStringBounds(title,g).getWidth()) - textRect.width;
textRect.x -= (vDifference / 2);
super.paintText(g, tabPlacement, selectedFont, selectedMetrics, tabIndex, title, textRect, isSelected);
}
else
{
super.paintText(g, tabPlacement, font, metrics, tabIndex, title, textRect, isSelected);
}
}
*/
protected int getTabLabelShiftY(int tabPlacement, int tabIndex, boolean isSelected)
{
return 0;
}
}
@@ -197,6 +197,10 @@ public class SimpleTabbedPaneUI extends BasicTabbedPaneUI {
0, 21, colorSet.bottomGradColor2));
g2d.fillRect(xpos, 10, width, 11);
// System.out.println("drawing orange");
// g2d.setColor(Color.ORANGE);
// g2d.fillRect(xpos, 0, width, 21);
if (contentTopBorderDrawn) {
g2d.setColor(lineColor);
g2d.drawLine(rect.x, 20, rect.x + rect.width - 1, 20);