changeset 2587:cabc8dcc4b08

More tab look and feel tweaks review-thread: http://icedtea.classpath.org/pipermail/thermostat/2017-February/022135.html reviewed-by: almac
author Mario Torre <neugens.limasoftware@gmail.com>
date Thu, 09 Feb 2017 15:16:53 +0100
parents 2f3899d0dd36
children ac0f70abdcb1
files client/swing/src/main/java/com/redhat/thermostat/client/swing/components/CleanTabUI.java client/swing/src/main/java/com/redhat/thermostat/client/swing/components/HeaderPanel.java client/swing/src/main/java/com/redhat/thermostat/client/swing/components/ThermostatTabbedPane.java client/swing/src/test/java/com/redhat/thermostat/client/swing/components/ThermostatTabbedPaneDemo.java
diffstat 4 files changed, 219 insertions(+), 80 deletions(-) [+]
line wrap: on
line diff
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/CleanTabUI.java	Wed Feb 08 21:02:33 2017 +0100
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/CleanTabUI.java	Thu Feb 09 15:16:53 2017 +0100
@@ -36,24 +36,32 @@
 
 package com.redhat.thermostat.client.swing.components;
 
+import java.awt.Color;
+import java.awt.GradientPaint;
 import java.awt.Graphics;
+import java.awt.Graphics2D;
 import java.awt.Insets;
+import java.awt.Paint;
 import java.awt.Rectangle;
-import java.lang.reflect.Field;
+import java.awt.geom.AffineTransform;
 
 import javax.swing.JButton;
 import javax.swing.JComponent;
 import javax.swing.SwingConstants;
+import javax.swing.UIManager;
 import javax.swing.plaf.UIResource;
 import javax.swing.plaf.basic.BasicTabbedPaneUI;
 
-import com.redhat.thermostat.client.swing.IconResource;
+import com.redhat.thermostat.client.swing.GraphicsUtils;
+import com.redhat.thermostat.client.swing.UIDefaults;
+import com.redhat.thermostat.client.swing.internal.vmlist.UIDefaultsImpl;
 import com.redhat.thermostat.client.ui.Palette;
 
 class CleanTabUI extends BasicTabbedPaneUI {
     
     private Insets cleantabInsets;
-    
+    private UIDefaults uiDefaults = UIDefaultsImpl.getInstance();
+
     @SuppressWarnings("serial")
     private class ArrowButton extends ActionButton implements UIResource, SwingConstants {
 
@@ -68,7 +76,7 @@
     }
     
     public CleanTabUI() {
-        cleantabInsets = new Insets(5, 10, 2, 10);
+        cleantabInsets = new Insets(5, 10, 5, 10);
     }
     
     @Override
@@ -76,86 +84,137 @@
         super.installUI(c);
         tabPane.setOpaque(true);
     }
-    
+
+    @Override
+    protected int getTabLabelShiftY(int tabPlacement, int tabIndex, boolean isSelected) {
+        return 0;
+    }
+
     @Override
     protected void installDefaults() {
+        UIManager.getDefaults().put("TabbedPane.tabsOverlapBorder", true);
+        UIManager.getDefaults().put("TabbedPane.contentAreaColor", uiDefaults.getComponentBGColor());
+        UIManager.getDefaults().put("TabbedPane.shadow", Palette.GRAY.getColor());
+
         super.installDefaults();
-        lightHighlight = Palette.EARL_GRAY.getColor();
-        contentBorderInsets = new Insets(1, 1, 1, 1);
-        setTabsOverlap();
+        lightHighlight = Palette.GRAY.getColor();
+
+        contentBorderInsets = new Insets(1, 0, 0, 0);
+        selectedTabPadInsets = new Insets(0, 0, 0, 0);
+        tabAreaInsets = new Insets(1, 0, 1, 0);
+        tabInsets = cleantabInsets;
     }
-    
-    private void setTabsOverlap() {
-        try {
-            Field tabsOverlapBorderField = getClass().getSuperclass().getDeclaredField("tabsOverlapBorder");
-            tabsOverlapBorderField.setAccessible(true);
-            tabsOverlapBorderField.set(this, true);
-            
-        } catch (IllegalArgumentException | IllegalAccessException |
-                 NoSuchFieldException | SecurityException ignore) {}
-    }
-    
+
     @Override
     public void paint(Graphics g, JComponent c) {
-        lightHighlight = Palette.EARL_GRAY.getColor();
+        lightHighlight = Palette.GRAY.getColor();
+
+        g.setColor((Color) uiDefaults.getComponentBGColor());
+        g.fillRect(0, 0, tabPane.getWidth(), tabPane.getHeight());
+
+        g.setColor(lightHighlight);
         super.paint(g, c);
+
+        if (tabPane.getTabPlacement() == TOP) {
+            g.setColor(Palette.DARK_GRAY.getColor());
+            g.drawLine(0, 0, tabPane.getWidth(), 0);
+            g.setColor(Palette.GRAY.getColor());
+            g.drawLine(0, 1, tabPane.getWidth(), 1);
+        }
     }
-    
+
     @Override
     protected void paintTabBorder(Graphics g, int tabPlacement, int tabIndex,
                                   int x, int y, int width, int height,
                                   boolean isSelected)
     {
-        if (!isSelected) {
-            // TODO: implement for all orientations
-            g.setColor(Palette.PALE_GRAY.getColor().darker());
-            g.drawRect(x, y, width, height);
+        g.setColor(Palette.DARK_GRAY.getColor());
+
+        if (tabIndex > 0) {
+            g.drawLine(x, y, x, y + height - 1);
+        }
 
-            g.setColor(lightHighlight);
-            g.drawLine(x, y + height, x + width + 1, y + height);
-     
-        } else {
-            g.setColor(lightHighlight);
-            g.drawRect(x, y, width, height - 2);
-            
-            g.setColor(Palette.GRANITA_ORANGE.getColor());
-            g.fillRect(x, y, width + 1, y + 1);
-            
-            g.setColor(Palette.LIGHT_GRAY.getColor());
-            g.drawLine(x + 1, y + height - 2, x + width - 1, y + height - 2);
+        if (tabIndex == tabPane.getTabCount() - 1) {
+            g.drawLine(x + width, y, x + width, y + height - 1);
+        }
+
+        if (isSelected && tabPlacement == TOP) {
+            g.setColor((Color) uiDefaults.getComponentBGColor());
+            g.drawLine(x + (tabIndex > 0 ? 1 : 0), y - 1, x + width - 1, y - 1);
         }
     }
     
     protected JButton createScrollButton(int direction) {
 
-        IconResource resource = IconResource.ARROW_LEFT;
+        FontAwesomeIcon resource = null;
         switch (direction) {
         case EAST:
         case NORTH:
-            resource = IconResource.ARROW_RIGHT;
+            resource = new FontAwesomeIcon('\uf105', 20, uiDefaults.getSelectedComponentBGColor());
             break;
 
         case WEST:
         case SOUTH:
         default:
-            resource = IconResource.ARROW_LEFT;
+            resource = new FontAwesomeIcon('\uf104', 20, uiDefaults.getSelectedComponentBGColor());
             break;
         }
         
-        return new ArrowButton(resource.getIcon());
+        return new ArrowButton(resource);
+    }
+
+    private void paintTabAreaTopInset(Graphics2D graphics2D) {
+        if (tabPane.getTabPlacement() == TOP) {
+            graphics2D.setColor(Palette.DARK_GRAY.getColor());
+            graphics2D.drawLine(0, 0, tabPane.getWidth(), 0);
+
+            graphics2D.setColor(Palette.GRAY.getColor());
+            graphics2D.drawLine(0, 1, tabPane.getWidth(), 1);
+        }
+    }
+
+    private void paintTabAreaBottomInset(Graphics2D graphics2D) {
+        if (tabPane.getTabPlacement() == TOP) {
+            graphics2D.setColor(Palette.DARK_GRAY.getColor());
+            Rectangle tabBounds = rects[0].getBounds();
+            int h = tabBounds.height + tabAreaInsets.bottom;
+            graphics2D.drawLine(tabPane.getX(), h, tabPane.getWidth(), h);
+        }
     }
-    
+
+    @Override
+    protected void paintTabArea(Graphics g, int tabPlacement, int selectedIndex) {
+
+        Graphics2D graphics2D = (Graphics2D) g;
+
+        graphics2D.setColor((Color) uiDefaults.getComponentBGColor());
+        graphics2D.fillRect(0, 0, tabPane.getWidth(), tabPane.getHeight());
+
+        // this is a bit weird, we need to do it twice with and without the
+        // affine transform because the caller sometime shift the content
+        // depending if the scroll buttons are visible or not but unfortunately
+        // we can't access this information
+        paintTabAreaTopInset(graphics2D);
+        AffineTransform transform = graphics2D.getTransform();
+        graphics2D.setTransform(new AffineTransform());
+        paintTabAreaTopInset(graphics2D);
+
+        graphics2D.setTransform(transform);
+        super.paintTabArea(g, tabPlacement, selectedIndex);
+
+        paintTabAreaBottomInset(graphics2D);
+        transform = graphics2D.getTransform();
+        graphics2D.setTransform(new AffineTransform());
+        paintTabAreaBottomInset(graphics2D);
+        graphics2D.setTransform(transform);
+    }
+
     @Override
     protected void paintContentBorderBottomEdge(Graphics g, int tabPlacement,
                                                 int selectedIndex, int x, int y,
                                                 int w, int h)
     {
-        g.setColor(lightHighlight);
-        if (tabPlacement != BOTTOM) {
-            g.drawLine(x, y + h - 1, x + w, y + h - 1);
-        } else {
-            // TODO
-        }
+        // no border
     }
     
     @Override
@@ -163,12 +222,7 @@
                                               int selectedIndex, int x, int y,
                                               int w, int h)
     {
-        g.setColor(lightHighlight);
-        if (tabPlacement != LEFT) {
-            g.drawLine(x, y, x, y + h - 1);
-        } else {
-            // TODO
-        }
+        // no border
     }
     
     @Override
@@ -176,12 +230,7 @@
                                                int selectedIndex, int x, int y,
                                                int w, int h)
     {
-        g.setColor(lightHighlight);
-        if (tabPlacement != RIGHT) {
-            g.drawLine(x + w - 1, y, x + w - 1, y + h - 1);
-        } else {
-            // TODO
-        }
+        // no border
     }
     
     @Override
@@ -189,32 +238,28 @@
                                              int selectedIndex, int x, int y,
                                              int w, int h)
     {
-        Rectangle bounds = selectedIndex < 0 ? null : getTabBounds(selectedIndex, calcRect);
-
-        g.setColor(lightHighlight);
-        if (tabPlacement != TOP || bounds == null) {
-            g.drawLine(x, y, x + w - 1, y);
+        g.setColor(Palette.DARK_GRAY.getColor());
+        g.drawLine(x, y, x + w, y);
+    }
 
-        } else {
-            g.drawLine(x, y, bounds.x, y);
-            g.drawLine(bounds.x + bounds.width, y, x + w - 1, y);
-            
-            g.setColor(Palette.LIGHT_GRAY.getColor());
-            g.drawLine(bounds.x + 1, y, bounds.x + bounds.width - 1, y);
-        }
-    }
-        
     @Override
     protected void paintTabBackground(Graphics g, int tabPlacement, int tabIndex,
                                       int x, int y, int width, int height,
                                       boolean isSelected)
     {
-        g.setColor(Palette.LIGHT_GRAY.getColor());
-        int delta = 2;
-        if (!isSelected) {
-            delta = 1;
+        GraphicsUtils utils = GraphicsUtils.getInstance();
+        Graphics2D graphics = utils.createAAGraphics(g);
+        if (isSelected) {
+            Paint gradient = new GradientPaint(x, y, (Color) uiDefaults.getComponentBGColor(),
+                                               x, height, Palette.GRAY.getColor());
+            graphics.setPaint(gradient);
+
+        } else {
+            graphics.setColor(Palette.GRAY.getColor());
         }
-        g.fillRect(x, y + 1, width, height - delta);
+
+        graphics.fillRect(x, y, width, height);
+        graphics.dispose();
     }
         
     @Override
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/HeaderPanel.java	Wed Feb 08 21:02:33 2017 +0100
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/HeaderPanel.java	Thu Feb 09 15:16:53 2017 +0100
@@ -59,6 +59,7 @@
 import javax.swing.SwingUtilities;
 
 import com.redhat.thermostat.client.swing.internal.LocaleResources;
+import com.redhat.thermostat.client.swing.internal.vmlist.UIDefaultsImpl;
 import com.redhat.thermostat.shared.locale.LocalizedString;
 import com.redhat.thermostat.shared.locale.Translate;
 
@@ -104,7 +105,7 @@
         setName(HeaderPanel.class.getName());
         
         headerLabel = new ShadowLabel(header, new EmptyIcon(5, 5));
-        headerPanel = new GradientPanel(Color.WHITE, getBackground());
+        headerPanel = new GradientPanel(Color.WHITE, UIDefaultsImpl.getInstance().getComponentBGColor());
         headerPanel.setName("clickableArea");
         headerPanel.setPreferredSize(new Dimension(HeaderPanel.this.getWidth(), 40));
         
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/ThermostatTabbedPane.java	Wed Feb 08 21:02:33 2017 +0100
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/ThermostatTabbedPane.java	Thu Feb 09 15:16:53 2017 +0100
@@ -45,6 +45,7 @@
 public class ThermostatTabbedPane extends JTabbedPane {
 
     public ThermostatTabbedPane() {
+        super(TOP, SCROLL_TAB_LAYOUT);
         setUI(new CleanTabUI());
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/components/ThermostatTabbedPaneDemo.java	Thu Feb 09 15:16:53 2017 +0100
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.client.swing.components;
+
+import com.redhat.thermostat.shared.locale.LocalizedString;
+
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.SwingConstants;
+import javax.swing.SwingUtilities;
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+
+/**
+ */
+public class ThermostatTabbedPaneDemo {
+    public static void main(String[] args) {
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                JFrame frame = new JFrame();
+                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+                frame.setMinimumSize(new Dimension(500, 500));
+
+                HeaderPanel header = new HeaderPanel(new LocalizedString("A Simple Tab Demo"));
+                frame.setContentPane(header);
+
+                ThermostatTabbedPane tabs = new ThermostatTabbedPane();
+                tabs.addTab("Content #1", createContent("Some Content"));
+                tabs.addTab("Content #2", createContent("Some Other Content"));
+                tabs.addTab("Content #3", createContent("Some More Content Longer"));
+                tabs.addTab("Content #4", createContent("Some More Content Even Longer"));
+                tabs.addTab("Content #5", createContent("Some More Content Very Very Long!!!"));
+                tabs.addTab("Content #6", createContent("Some More Content The Longest One!!!!!!!!"));
+
+                header.setContent(tabs);
+
+                frame.setVisible(true);
+            }
+        });
+    }
+
+    private static Component createContent(String text) {
+        JPanel panel = new JPanel();
+        panel.setBackground(Color.WHITE);
+
+        panel.setLayout(new BorderLayout());
+        JLabel content = new JLabel(text);
+        content.setHorizontalAlignment(SwingConstants.CENTER);
+
+        panel.add(content);
+
+        return panel;
+    }
+}
\ No newline at end of file