Package pivot.wtk.skin.terra

Source Code of pivot.wtk.skin.terra.TerraTabPaneSkin

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you 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 pivot.wtk.skin.terra;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.GradientPaint;
import java.awt.Graphics2D;

import pivot.collections.Dictionary;
import pivot.collections.Sequence;
import pivot.util.Vote;
import pivot.wtk.Button;
import pivot.wtk.Component;
import pivot.wtk.Dimensions;
import pivot.wtk.FlowPane;
import pivot.wtk.HorizontalAlignment;
import pivot.wtk.Insets;
import pivot.wtk.Mouse;
import pivot.wtk.Orientation;
import pivot.wtk.Panorama;
import pivot.wtk.Bounds;
import pivot.wtk.TabPane;
import pivot.wtk.TabPaneListener;
import pivot.wtk.TabPaneSelectionListener;
import pivot.wtk.TabPaneAttributeListener;
import pivot.wtk.Theme;
import pivot.wtk.VerticalAlignment;
import pivot.wtk.Button.Group;
import pivot.wtk.content.ButtonData;
import pivot.wtk.content.ButtonDataRenderer;
import pivot.wtk.effects.ClipDecorator;
import pivot.wtk.effects.Transition;
import pivot.wtk.effects.TransitionListener;
import pivot.wtk.effects.easing.Easing;
import pivot.wtk.effects.easing.Quadratic;
import pivot.wtk.media.Image;
import pivot.wtk.skin.ButtonSkin;
import pivot.wtk.skin.ContainerSkin;

/**
* Tab pane skin.
* <p>
* TODO Make tab buttons focusable?
* <p>
* TODO Disable the tab button when the component is disabled? We'd need
* style properties to present a disabled tab button state. We'd also need
* to manage button enabled state independently of tab pane enabled state.
* <p>
* TODO Add showCloseButton style.
*
* @author gbrown
*/
public class TerraTabPaneSkin extends ContainerSkin
    implements TabPaneListener, TabPaneSelectionListener, TabPaneAttributeListener,
        Button.GroupListener {
    protected class TabButton extends Button {
      private boolean active = false;

      public TabButton() {
            this(null);
        }

        public TabButton(Object buttonData) {
            super(buttonData);

            super.setToggleButton(true);
            setDataRenderer(DEFAULT_DATA_RENDERER);

            setSkin(new TabButtonSkin());
        }

        @Override
        public void setEnabled(boolean enabled) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void setToggleButton(boolean toggleButton) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void setTriState(boolean triState) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void press() {
            // If the tab pane is collapsible, toggle the button selection;
            // otherwise, select it
            TabPane tabPane = (TabPane)TerraTabPaneSkin.this.getComponent();
            setSelected(tabPane.isCollapsible() ? !isSelected() : true);

            super.press();
        }
    }

    protected class TabButtonSkin extends ButtonSkin {
        public int getPreferredWidth(int height) {
            TabButton tabButton = (TabButton)getComponent();
            TabPane tabPane = (TabPane)TerraTabPaneSkin.this.getComponent();

            Button.DataRenderer dataRenderer = tabButton.getDataRenderer();
            dataRenderer.render(tabButton.getButtonData(), tabButton, false);

            // Include padding in constraint
            if (height != -1) {
                height = Math.max(height - (buttonPadding.top + buttonPadding.bottom + 2), 0);
            }

            int preferredWidth = 0;
            switch (tabPane.getTabOrientation()) {
                case HORIZONTAL: {
                    preferredWidth = dataRenderer.getPreferredWidth(height)
                        + buttonPadding.left + buttonPadding.right + 2;
                    break;
                }

                case VERTICAL: {
                    preferredWidth = dataRenderer.getPreferredHeight(height)
                        + buttonPadding.top + buttonPadding.bottom + 2;
                    break;
                }
            }

            return preferredWidth;
        }

        public int getPreferredHeight(int width) {
            TabButton tabButton = (TabButton)getComponent();
            TabPane tabPane = (TabPane)TerraTabPaneSkin.this.getComponent();

            Button.DataRenderer dataRenderer = tabButton.getDataRenderer();
            dataRenderer.render(tabButton.getButtonData(), tabButton, false);

            // Include padding in constraint
            if (width != -1) {
                width = Math.max(width - (buttonPadding.left + buttonPadding.right + 2), 0);
            }

            int preferredHeight = 0;
            switch (tabPane.getTabOrientation()) {
                case HORIZONTAL: {
                    preferredHeight = dataRenderer.getPreferredHeight(width)
                        + buttonPadding.top + buttonPadding.bottom + 2;
                    break;
                }

                case VERTICAL: {
                    preferredHeight = dataRenderer.getPreferredWidth(width)
                        + buttonPadding.left + buttonPadding.right + 2;
                    break;
                }
            }

            return preferredHeight;
        }

        public Dimensions getPreferredSize() {
            TabButton tabButton = (TabButton)getComponent();
            TabPane tabPane = (TabPane)TerraTabPaneSkin.this.getComponent();

            Button.DataRenderer dataRenderer = tabButton.getDataRenderer();
            dataRenderer.render(tabButton.getButtonData(), tabButton, false);

            Dimensions preferredContentSize = dataRenderer.getPreferredSize();

            int preferredWidth = 0;
            int preferredHeight = 0;
            switch (tabPane.getTabOrientation()) {
                case HORIZONTAL: {
                    preferredWidth = preferredContentSize.width
                        + buttonPadding.left + buttonPadding.right + 2;

                    preferredHeight = preferredContentSize.height
                        + buttonPadding.top + buttonPadding.bottom + 2;

                    break;
                }

                case VERTICAL: {
                    preferredWidth = preferredContentSize.height
                        + buttonPadding.top + buttonPadding.bottom + 2;

                    preferredHeight = preferredContentSize.width
                        + buttonPadding.left + buttonPadding.right + 2;

                    break;
                }
            }

            return new Dimensions(preferredWidth, preferredHeight);
        }

        public void paint(Graphics2D graphics) {
            TabButton tabButton = (TabButton)getComponent();
            TabPane tabPane = (TabPane)TerraTabPaneSkin.this.getComponent();
            Orientation tabOrientation = tabPane.getTabOrientation();

            Color backgroundColor = (tabButton.isSelected()
            || tabButton.active) ?
                activeTabColor : inactiveTabColor;

            int width = getWidth();
            int height = getHeight();

            graphics.setStroke(new BasicStroke());

            // Draw the background
            graphics.setPaint(backgroundColor);
            graphics.fillRect(0, 0, width, height);

            // Draw the bevel
            graphics.setPaint(new GradientPaint(width / 2, 1, buttonBevelColor,
                width / 2, GRADIENT_BEVEL_THICKNESS, backgroundColor));

            switch(tabOrientation) {
              case HORIZONTAL: {
                  graphics.fillRect(1, 1, width - 2, GRADIENT_BEVEL_THICKNESS);
                  break;
              }

              case VERTICAL: {
                graphics.fillRect(1, 1, width - 1, GRADIENT_BEVEL_THICKNESS);
                  break;
              }
          }

            // Draw the border
            graphics.setPaint(borderColor);

            if (tabButton.isSelected()
            || tabButton.active) {
                switch(tabOrientation) {
                case HORIZONTAL: {
                    graphics.drawLine(0, height - 1, 0, 0);
                    graphics.drawLine(0, 0, width - 1, 0);
                    graphics.drawLine(width - 1, 0, width - 1, height - 1);
                    break;
                }

                case VERTICAL: {
                    graphics.drawLine(width, 0, 0, 0);
                    graphics.drawLine(0, 0, 0, height - 1);
                    graphics.drawLine(0, height - 1, width - 1, height - 1);
                    break;
                }
              }
            } else {
              graphics.drawRect(0, 0, width - 1, height - 1);
            }

            // Paint the content
            Button.DataRenderer dataRenderer = tabButton.getDataRenderer();
            dataRenderer.render(tabButton.getButtonData(), tabButton, false);

            Graphics2D contentGraphics = (Graphics2D)graphics.create();

            switch (tabOrientation) {
                case HORIZONTAL: {
                    dataRenderer.setSize(Math.max(getWidth() - (buttonPadding.left + buttonPadding.right + 2), 0),
                        Math.max(getHeight() - (buttonPadding.top + buttonPadding.bottom + 2), 0));

                    contentGraphics.translate(buttonPadding.left + 1, buttonPadding.top + 1);
                    break;
                }

                case VERTICAL: {
                    dataRenderer.setSize(Math.max(getHeight() - (buttonPadding.top + buttonPadding.bottom + 2), 0),
                        Math.max(getWidth() - (buttonPadding.left + buttonPadding.right + 2), 0));

                    contentGraphics.translate(buttonPadding.top + 1, buttonPadding.left + 1);
                    contentGraphics.rotate(-Math.PI / 2d);
                    contentGraphics.translate(-dataRenderer.getWidth(), 0);
                    break;
                }
            }

            contentGraphics.clipRect(0, 0, dataRenderer.getWidth(), dataRenderer.getHeight());
            dataRenderer.paint(contentGraphics);

            contentGraphics.dispose();
        }

        @Override
        public boolean isFocusable() {
            return false;
        }

        @Override
        public boolean mouseClick(Component component, Mouse.Button button, int x, int y, int count) {
            boolean consumed = super.mouseClick(component, button, x, y, count);

            TabButton tabButton = (TabButton)getComponent();
            tabButton.press();

            return consumed;
        }

        public Font getFont() {
          return buttonFont;
        }

        public Color getColor() {
          return buttonColor;
        }

        public Color getDisabledColor() {
          return buttonColor;
        }
    }

    public class ExpandTransition extends Transition {
      boolean collapse;
        private Easing easing = new Quadratic();
        private ClipDecorator clipDecorator = new ClipDecorator();

        public ExpandTransition(boolean collapse, int duration, int rate) {
            super(duration, rate, false);
            this.collapse = collapse;
        }

        public float getScale() {
            int elapsedTime = getElapsedTime();
            int duration = getDuration();

            float scale;
            if (collapse) {
                scale = easing.easeIn(elapsedTime, 1, -1, duration);
            } else {
                scale = easing.easeOut(elapsedTime, 0, 1, duration);
            }

            return scale;
        }

        @Override
        public void start(TransitionListener transitionListener) {
          TabPane tabPane = (TabPane)getComponent();
          Component selectedTab = tabPane.getSelectedTab();
          selectedTab.getDecorators().add(clipDecorator);

          int selectedIndex = tabPane.getSelectedIndex();
          TabButton tabButton = (TabButton)buttonFlowPane.get(selectedIndex);
          tabButton.active = true;

          getComponent().setEnabled(false);

            super.start(transitionListener);
        }

        @Override
        public void stop() {
          TabPane tabPane = (TabPane)getComponent();
          Component selectedTab = tabPane.getSelectedTab();
          selectedTab.getDecorators().remove(clipDecorator);

          int selectedIndex = tabPane.getSelectedIndex();
          TabButton tabButton = (TabButton)buttonFlowPane.get(selectedIndex);
          tabButton.active = false;

          getComponent().setEnabled(true);

          super.stop();
        }

        @Override
        protected void update() {
            invalidateComponent();
        }
    }

    protected Panorama buttonPanorama = new Panorama();
    protected FlowPane buttonFlowPane = new FlowPane();
    private Button.Group tabButtonGroup = new Button.Group();

    private Color activeTabColor;
    private Color inactiveTabColor;
    private Color borderColor;
    private Insets padding;
    private Font buttonFont;
    private Color buttonColor;
    private Insets buttonPadding;

    // Derived colors
    private Color buttonBevelColor;

    private ExpandTransition expandTransition = null;

    private static final int EXPAND_DURATION = 250;
    private static final int EXPAND_RATE = 30;

  public static final int GRADIENT_BEVEL_THICKNESS = 4;
  private static final Button.DataRenderer DEFAULT_DATA_RENDERER = new ButtonDataRenderer();

    public TerraTabPaneSkin() {
        TerraTheme theme = (TerraTheme)Theme.getTheme();
        activeTabColor = theme.getColor(11);
        inactiveTabColor = theme.getColor(9);
        borderColor = theme.getColor(7);
        padding = new Insets(6);
        buttonFont = theme.getFont();
        buttonColor = theme.getColor(1);
        buttonPadding = new Insets(3, 4, 3, 4);

        // Set the derived colors
        buttonBevelColor = TerraTheme.brighten(inactiveTabColor);

        tabButtonGroup.getGroupListeners().add(this);

        buttonFlowPane.getStyles().put("spacing", 2);
    }

  @Override
  public void setSize(int width, int height) {
    TabPane tabPane = (TabPane)getComponent();
    Orientation tabOrientation = tabPane.getTabOrientation();

    if (expandTransition != null) {
      if ((tabOrientation == Orientation.HORIZONTAL && width != getWidth())
        || (tabOrientation == Orientation.VERTICAL && height != getHeight())) {
        expandTransition.end();
        expandTransition = null;
      }
    }

    super.setSize(width, height);
  }

    public void install(Component component) {
        super.install(component);

        TabPane tabPane = (TabPane)component;

        // Add this as a listener on the tab pane
        tabPane.getTabPaneListeners().add(this);
        tabPane.getTabPaneSelectionListeners().add(this);
        tabPane.getTabPaneAttributeListeners().add(this);

        // Add the button panorama and flow pane
        buttonPanorama.getStyles().put("buttonBackgroundColor", borderColor);
        buttonPanorama.getStyles().put("buttonPadding", 6);
        buttonPanorama.setView(buttonFlowPane);
        tabPane.add(buttonPanorama);

        // Apply the current tab orientation
        tabOrientationChanged(tabPane);

        // Add buttons for all existing tabs
        for (Component tab : tabPane.getTabs()) {
            TabButton tabButton = new TabButton(new ButtonData(TabPane.getIcon(tab),
                TabPane.getName(tab)));
            tabButton.setGroup(tabButtonGroup);

            buttonFlowPane.add(tabButton);
        }

        selectedIndexChanged(tabPane, -1);
    }

    public void uninstall() {
        TabPane tabPane = (TabPane)getComponent();

        // Remove this as a listener on the tab pane
        tabPane.getTabPaneListeners().remove(this);
        tabPane.getTabPaneSelectionListeners().remove(this);
        tabPane.getTabPaneAttributeListeners().remove(this);

        // Remove the button panorama
        tabPane.remove(buttonPanorama);

        super.uninstall();
    }

    public int getPreferredWidth(int height) {
        int preferredWidth;

        TabPane tabPane = (TabPane)getComponent();
        Orientation tabOrientation = tabPane.getTabOrientation();

        if (expandTransition == null
        || tabOrientation == Orientation.VERTICAL) {
          preferredWidth = 0;

            Component selectedTab = tabPane.getSelectedTab();
            Component corner = tabPane.getCorner();

            switch (tabOrientation) {
                case HORIZONTAL: {
                    if (height != -1) {
                        if (corner != null
                            && corner.isDisplayable()) {
                            height = Math.max(height - Math.max(corner.getPreferredHeight(-1),
                                Math.max(buttonPanorama.getPreferredHeight(-1) - 1, 0)), 0);
                        } else {
                            height = Math.max(height - (buttonPanorama.getPreferredHeight(-1) - 1), 0);
                        }

                        height = Math.max(height - (padding.top + padding.bottom + 2), 0);
                    }

                    if (selectedTab != null) {
                        for (Component tab : tabPane.getTabs()) {
                            preferredWidth = Math.max(preferredWidth,
                                tab.getPreferredWidth(height));
                        }

                        preferredWidth += (padding.left + padding.right + 2);
                    }

                    int buttonAreaPreferredWidth = buttonPanorama.getPreferredWidth(-1);

                    if (corner != null
                        && corner.isDisplayable()) {
                        buttonAreaPreferredWidth += corner.getPreferredWidth(-1);
                    }

                    preferredWidth = Math.max(preferredWidth,
                        buttonAreaPreferredWidth);

                    break;
                }

                case VERTICAL: {
                    if (height != -1) {
                        height = Math.max(height - (padding.top + padding.bottom + 2), 0);
                    }

                    if (selectedTab != null) {
                      if (expandTransition == null) {
                          int contentWidth = 0;
                            for (Component tab : tabPane.getTabs()) {
                                contentWidth = Math.max(contentWidth,
                                    tab.getPreferredWidth(height));
                            }

                            preferredWidth += (padding.left + padding.right + contentWidth);
                      } else {
                            float scale = expandTransition.getScale();
                            preferredWidth += (int)(scale * (float)(padding.left + padding.right
                            + selectedTab.getWidth()));
                      }

                        preferredWidth += 2;
                    } else {
                        preferredWidth += 1;
                    }

                    if (corner != null
                        && corner.isDisplayable()) {
                        preferredWidth += Math.max(corner.getPreferredWidth(-1),
                            Math.max(buttonPanorama.getPreferredWidth(-1) - 1, 0));
                    } else {
                        preferredWidth += Math.max(buttonPanorama.getPreferredWidth(-1) - 1, 0);
                    }

                    break;
                }
            }
        } else {
          preferredWidth = getWidth();
        }

        return preferredWidth;
    }

    public int getPreferredHeight(int width) {
        int preferredHeight;

        TabPane tabPane = (TabPane)getComponent();
        Orientation tabOrientation = tabPane.getTabOrientation();

        if (expandTransition == null
        || tabOrientation == Orientation.HORIZONTAL) {
          preferredHeight = 0;
            Component selectedTab = tabPane.getSelectedTab();
            Component corner = tabPane.getCorner();

            switch (tabOrientation) {
                case HORIZONTAL: {
                    if (width != -1) {
                        width = Math.max(width - (padding.left + padding.right + 2), 0);
                    }

                    if (selectedTab != null) {
                      if (expandTransition == null) {
                        int contentHeight = 0;
                            for (Component tab : tabPane.getTabs()) {
                              contentHeight = Math.max(contentHeight,
                                    tab.getPreferredHeight(width));
                            }

                            preferredHeight += (padding.top + padding.bottom + contentHeight);
                      } else {
                        float scale = expandTransition.getScale();
                            preferredHeight += (int)(scale * (float)(padding.top + padding.bottom
                            + selectedTab.getHeight()));
                      }

                        preferredHeight += 2;
                    } else {
                        preferredHeight += 1;
                    }

                    if (corner != null
                        && corner.isDisplayable()) {
                        preferredHeight += Math.max(corner.getPreferredHeight(-1),
                            Math.max(buttonPanorama.getPreferredHeight(-1) - 1, 0));
                    } else {
                        preferredHeight += Math.max(buttonPanorama.getPreferredHeight(-1) - 1, 0);
                    }

                    break;
                }

                case VERTICAL: {
                    if (width != -1) {
                        if (corner != null
                            && corner.isDisplayable()) {
                            width = Math.max(width - Math.max(corner.getPreferredWidth(-1),
                                Math.max(buttonPanorama.getPreferredWidth(-1) - 1, 0)), 0);
                        } else {
                            width = Math.max(width - (buttonPanorama.getPreferredWidth(-1) - 1), 0);
                        }

                        width = Math.max(width - (padding.left + padding.right + 2), 0);
                    }

                    if (selectedTab != null) {
                        for (Component tab : tabPane.getTabs()) {
                            preferredHeight = Math.max(preferredHeight,
                                tab.getPreferredHeight(width));
                        }

                        preferredHeight += (padding.top + padding.bottom + 2);
                    }

                    int buttonAreaPreferredHeight = buttonPanorama.getPreferredHeight(-1);

                    if (corner != null
                        && corner.isDisplayable()) {
                        buttonAreaPreferredHeight += corner.getPreferredHeight(-1);
                    }

                    preferredHeight = Math.max(preferredHeight,
                        buttonAreaPreferredHeight);

                    break;
                }
            }
        } else {
          preferredHeight = getHeight();
        }

        return preferredHeight;
    }

    public Dimensions getPreferredSize() {
        // TODO Optimize
        return new Dimensions(getPreferredWidth(-1), getPreferredHeight(-1));
    }

    public void layout() {
        TabPane tabPane = (TabPane)getComponent();
        int width = getWidth();
        int height = getHeight();

        int tabX = 0;
        int tabY = 0;
        int tabWidth = 0;
        int tabHeight = 0;

        Component selectedTab = tabPane.getSelectedTab();
        Component corner = tabPane.getCorner();

        Dimensions buttonPanoramaSize;
        if (expandTransition == null) {
          buttonPanoramaSize = buttonPanorama.getPreferredSize();
        } else {
          buttonPanoramaSize = buttonPanorama.getSize();
        }

        Orientation tabOrientation = tabPane.getTabOrientation();
        switch (tabOrientation) {
            case HORIZONTAL: {
                int buttonPanoramaWidth = Math.min(width,
                    buttonPanoramaSize.width);
                int buttonPanoramaHeight = buttonPanoramaSize.height;
                int buttonPanoramaX = 0;
                int buttonPanoramaY = 0;

                if (corner != null) {
                    if (corner.isDisplayable()) {
                        int cornerWidth = width - buttonPanoramaWidth;
                        int cornerHeight = Math.max(corner.getPreferredHeight(-1), buttonPanoramaSize.height - 1);
                        int cornerX = buttonPanoramaWidth;
                        int cornerY = Math.max(buttonPanoramaHeight - cornerHeight - 1, 0);

                        buttonPanoramaY = Math.max(cornerHeight - buttonPanoramaHeight + 1, 0);

                        corner.setVisible(true);
                        corner.setLocation(cornerX, cornerY);
                        corner.setSize(cornerWidth, cornerHeight);
                    } else {
                        corner.setVisible(false);
                    }
                }

                buttonPanorama.setLocation(buttonPanoramaX, buttonPanoramaY);
                buttonPanorama.setSize(buttonPanoramaWidth, buttonPanoramaHeight);

                tabX = padding.left + 1;
                tabY = padding.top + buttonPanoramaY + buttonPanoramaHeight;
                tabWidth = Math.max(width - (padding.left + padding.right + 2), 0);
                tabHeight = Math.max(height - (padding.top + padding.bottom
                    + buttonPanoramaY + buttonPanoramaHeight + 1), 0);

                break;
            }

            case VERTICAL: {
                int buttonPanoramaWidth = buttonPanoramaSize.width;
                int buttonPanoramaHeight = Math.min(height,
                    buttonPanoramaSize.height);
                int buttonPanoramaX = 0;
                int buttonPanoramaY = 0;

                if (corner != null) {
                    if (corner.isDisplayable()) {
                        int cornerWidth = corner.getPreferredWidth(-1);
                        int cornerHeight = height - buttonPanoramaHeight;
                        int cornerX = Math.max(buttonPanoramaWidth - cornerWidth - 1, 0);
                        int cornerY = buttonPanoramaHeight;

                        buttonPanoramaX = Math.max(cornerWidth - buttonPanoramaWidth + 1, 0);

                        corner.setVisible(true);
                        corner.setLocation(cornerX, cornerY);
                        corner.setSize(cornerWidth, cornerHeight);
                    } else {
                        corner.setVisible(false);
                    }
                }

                buttonPanorama.setLocation(buttonPanoramaX, buttonPanoramaY);
                buttonPanorama.setSize(buttonPanoramaWidth, buttonPanoramaHeight);

                tabX = padding.left + buttonPanoramaX + buttonPanoramaWidth;
                tabY = padding.top + 1;
                tabWidth = Math.max(width - (padding.left + padding.right
                    + buttonPanoramaX + buttonPanoramaWidth + 1), 0);
                tabHeight = Math.max(height - (padding.top + padding.bottom + 2), 0);

                break;
            }
        }

        if (expandTransition == null) {
            for (Component tab : tabPane.getTabs()) {
                if (tab == selectedTab) {
                    // Show the selected tab
                    tab.setVisible(true);

                    // Set the tab's size and location
                    tab.setLocation(tabX, tabY);
                    tab.setSize(tabWidth, tabHeight);
                } else {
                    tab.setVisible(false);
                }
            }
        } else {
          if (expandTransition.isRunning()) {
              // Update the clip
              expandTransition.clipDecorator.setWidth(tabWidth);
              expandTransition.clipDecorator.setHeight(tabHeight);
          } else {
              switch (tabOrientation) {
                case HORIZONTAL: {
                  tabHeight = 0;
                  for (Component tab : tabPane.getTabs()) {
                    tabHeight = Math.max(tab.getPreferredHeight(tabWidth), tabHeight);
                  }

                  break;
                }

                case VERTICAL: {
                  tabWidth = 0;
                  for (Component tab : tabPane.getTabs()) {
                    tabWidth = Math.max(tab.getPreferredWidth(tabHeight), tabWidth);
                  }

                  break;
                }
              }

                selectedTab.setLocation(tabX, tabY);
                selectedTab.setSize(tabWidth, tabHeight);

              selectedTab.setVisible(true);
          }

        }
    }

    @Override
    public void paint(Graphics2D graphics) {
        TabPane tabPane = (TabPane)getComponent();

        Bounds tabPaneBounds = tabPane.getBounds();

        // Call the base class to paint the background
        super.paint(graphics);

        graphics.setStroke(new BasicStroke());

        // Paint the content background and border
        int x = 0;
        int y = 0;
        int width = 0;
        int height = 0;

        Orientation tabOrientation = tabPane.getTabOrientation();

        switch (tabOrientation) {
            case HORIZONTAL: {
                x = 0;
                y = Math.max(buttonPanorama.getY() + buttonPanorama.getHeight() - 1, 0);
                width = tabPaneBounds.width;
                height = Math.max(tabPaneBounds.height - y, 0);

                break;
            }

            case VERTICAL: {
                x = Math.max(buttonPanorama.getX() + buttonPanorama.getWidth() - 1, 0);
                y = 0;
                width = Math.max(tabPaneBounds.width - x, 0);
                height = tabPaneBounds.height;

                break;
            }
        }

        Bounds contentBounds = new Bounds(x, y, width, height);

        if (!contentBounds.isEmpty()) {
            // If a tab is selected, paint the active background color; otherwise,
            // paint the inactive background color
            int selectedIndex = tabPane.getSelectedIndex();
            graphics.setPaint((selectedIndex == -1) ? inactiveTabColor : activeTabColor);
            graphics.fillRect(contentBounds.x, contentBounds.y,
                contentBounds.width, contentBounds.height);

            // Draw the border
            graphics.setPaint(borderColor);
            graphics.drawRect(contentBounds.x, contentBounds.y,
                Math.max(contentBounds.width - 1, 0),
                Math.max(contentBounds.height - 1, 0));

            // Draw the bevel for vertical tabs
            if (tabOrientation == Orientation.VERTICAL) {
              graphics.setPaint(new GradientPaint(width / 2, contentBounds.y + 1, buttonBevelColor,
                  width / 2, contentBounds.y + 1 + GRADIENT_BEVEL_THICKNESS, activeTabColor));
              graphics.fillRect(contentBounds.x + 1, contentBounds.y + 1,
                    contentBounds.width - 2, GRADIENT_BEVEL_THICKNESS);
            }
        }
    }

    public Color getActiveTabColor() {
        return activeTabColor;
    }

    public void setActiveTabColor(Color activeTabColor) {
        if (activeTabColor == null) {
            throw new IllegalArgumentException("activeTabColor is null.");
        }

        this.activeTabColor = activeTabColor;
        repaintComponent();
    }

    public final void setActiveTabColor(String activeTabColor) {
        if (activeTabColor == null) {
            throw new IllegalArgumentException("activeTabColor is null.");
        }

        setActiveTabColor(decodeColor(activeTabColor));
    }

    public Color getInactiveTabColor() {
        return inactiveTabColor;
    }

    public void setInactiveTabColor(Color inactiveTabColor) {
        if (inactiveTabColor == null) {
            throw new IllegalArgumentException("inactiveTabColor is null.");
        }

        this.inactiveTabColor = inactiveTabColor;
        buttonBevelColor = TerraTheme.brighten(inactiveTabColor);
        repaintComponent();
    }

    public final void setInactiveTabColor(String inactiveTabColor) {
        if (inactiveTabColor == null) {
            throw new IllegalArgumentException("inactiveTabColor is null.");
        }

        setInactiveTabColor(decodeColor(inactiveTabColor));
    }

    public Color getBorderColor() {
        return borderColor;
    }

    public void setBorderColor(Color borderColor) {
        if (borderColor == null) {
            throw new IllegalArgumentException("borderColor is null.");
        }

        this.borderColor = borderColor;
        buttonPanorama.getStyles().put("buttonBackgroundColor", borderColor);
        repaintComponent();
    }

    public final void setBorderColor(String borderColor) {
        if (borderColor == null) {
            throw new IllegalArgumentException("borderColor is null.");
        }

        setBorderColor(decodeColor(borderColor));
    }

    public Insets getPadding() {
        return padding;
    }

    public void setPadding(Insets padding) {
        if (padding == null) {
            throw new IllegalArgumentException("padding is null.");
        }

        this.padding = padding;
        invalidateComponent();
    }

    public final void setPadding(Dictionary<String, ?> padding) {
        if (padding == null) {
            throw new IllegalArgumentException("padding is null.");
        }

        setPadding(new Insets(padding));
    }

    public final void setPadding(int padding) {
        setPadding(new Insets(padding));
    }

    public final void setPadding(Number padding) {
        if (padding == null) {
            throw new IllegalArgumentException("padding is null.");
        }

        setPadding(padding.intValue());
    }

    public Font getButtonFont() {
        return buttonFont;
    }

    public void setButtonFont(Font buttonFont) {
        if (buttonFont == null) {
            throw new IllegalArgumentException("buttonFont is null.");
        }

        this.buttonFont = buttonFont;
        invalidateComponent();
    }

    public final void setButtonFont(String buttonFont) {
        if (buttonFont == null) {
            throw new IllegalArgumentException("buttonFont is null.");
        }

        setButtonFont(Font.decode(buttonFont));
    }

    public Color getButtonColor() {
        return buttonColor;
    }

    public void setButtonColor(Color buttonColor) {
        if (buttonColor == null) {
            throw new IllegalArgumentException("buttonColor is null.");
        }

        this.buttonColor = buttonColor;
        repaintComponent();
    }

    public final void setButtonColor(String buttonColor) {
        if (buttonColor == null) {
            throw new IllegalArgumentException("buttonColor is null.");
        }

        setButtonColor(decodeColor(buttonColor));
    }

    public Insets getButtonPadding() {
        return buttonPadding;
    }

    public void setButtonPadding(Insets buttonPadding) {
        if (buttonPadding == null) {
            throw new IllegalArgumentException("buttonPadding is null.");
        }

        this.buttonPadding = buttonPadding;
        invalidateComponent();
    }

    public final void setButtonPadding(int buttonPadding) {
        setButtonPadding(new Insets(buttonPadding));
    }

    public int getButtonSpacing() {
        return (Integer)buttonFlowPane.getStyles().get("spacing");
    }

    public void setButtonSpacing(int buttonSpacing) {
        buttonFlowPane.getStyles().put("spacing", buttonSpacing);
    }

    protected void updateButtonData(Component tab) {
        TabPane tabPane = (TabPane)getComponent();
        int tabIndex = tabPane.getTabs().indexOf(tab);

        if (tabIndex != -1) {
            TabButton tabButton =
                (TabButton)buttonFlowPane.get(tabIndex);

            tabButton.setButtonData(new ButtonData(TabPane.getIcon(tab),
                TabPane.getName(tab)));
        }
    }

    // Tab pane events
    public void tabOrientationChanged(TabPane tabPane) {
        Orientation tabOrientation = tabPane.getTabOrientation();

        buttonFlowPane.setOrientation(tabOrientation);

        Component.StyleDictionary buttonFlowPaneStyles = buttonFlowPane.getStyles();
        switch (tabOrientation) {
            case HORIZONTAL: {
                buttonFlowPaneStyles.put("horizontalAlignment", HorizontalAlignment.LEFT);
                buttonFlowPaneStyles.put("verticalAlignment", VerticalAlignment.JUSTIFY);
                break;
            }

            case VERTICAL: {
                buttonFlowPaneStyles.put("horizontalAlignment", HorizontalAlignment.JUSTIFY);
                buttonFlowPaneStyles.put("verticalAlignment", VerticalAlignment.TOP);
                break;
            }
        }
    }

    public void collapsibleChanged(TabPane tabPane) {
        // No-op
    }

    public void tabInserted(TabPane tabPane, int index) {
      if (expandTransition != null) {
        expandTransition.stop();
        expandTransition = null;
      }

        // Create a new button for the tab
        Component tab = tabPane.getTabs().get(index);
        TabButton tabButton = new TabButton(new ButtonData(TabPane.getIcon(tab),
            TabPane.getName(tab)));
        tabButton.setGroup(tabButtonGroup);

        buttonFlowPane.insert(tabButton, index);
    }

    public void tabsRemoved(TabPane tabPane, int index, Sequence<Component> tabs) {
      if (expandTransition != null) {
        expandTransition.stop();
        expandTransition = null;
      }

      // Remove the buttons
        Sequence<Component> removed = buttonFlowPane.remove(index, tabs.getLength());

        for (int i = 0, n = removed.getLength(); i < n; i++) {
            TabButton tabButton = (TabButton)removed.get(i);
            tabButton.setGroup((Group)null);
        }
    }

    public void cornerChanged(TabPane tabPane, Component previousCorner) {
        invalidateComponent();
    }

    // Tab pane selection events
  public Vote previewSelectedIndexChange(final TabPane tabPane, final int selectedIndex) {
        Vote vote = Vote.APPROVE;

        if (tabPane.isShowing()) {
            if (expandTransition == null) {
                if (selectedIndex == -1) {
                    expandTransition = new ExpandTransition(true, EXPAND_DURATION, EXPAND_RATE);

                    layout();
                    expandTransition.start(new TransitionListener() {
                        public void transitionCompleted(Transition transition) {
                            tabPane.setSelectedIndex(-1);
                            expandTransition = null;
                        }
                    });

                    vote = Vote.DEFER;
                }
            } else {
              if (expandTransition.isRunning()) {
                  vote = Vote.DEFER;
              }
            }
        }

        return vote;
  }

  public void selectedIndexChangeVetoed(TabPane tabPane, Vote reason) {
        if (reason == Vote.DENY
            && expandTransition != null) {
            expandTransition.stop();
            expandTransition = null;
            invalidateComponent();
        }
  }

  public void selectedIndexChanged(TabPane tabPane, int previousSelectedIndex) {
        int selectedIndex = tabPane.getSelectedIndex();

        if (selectedIndex == -1) {
            Button button = tabButtonGroup.getSelection();
            if (button != null) {
                button.setSelected(false);
            }
        } else {
            Button button = (Button)buttonFlowPane.get(selectedIndex);
            button.setSelected(true);

            if (previousSelectedIndex == -1) {
                if (tabPane.isShowing()) {
                    expandTransition = new ExpandTransition(false, EXPAND_DURATION, EXPAND_RATE);

                    layout();
                    expandTransition.start(new TransitionListener() {
                        public void transitionCompleted(Transition transition) {
                            expandTransition = null;
                        }
                    });
                }
            }
        }

        invalidateComponent();
    }

    // Tab pane attribute events
    public void nameChanged(TabPane tabPane, Component component, String previousName) {
        updateButtonData(component);
    }

    public void iconChanged(TabPane tabPane, Component component, Image previousIcon) {
        updateButtonData(component);
    }

    // Button group events
    public void selectionChanged(Group group, Button previousSelection) {
        Button button = tabButtonGroup.getSelection();
        int index = (button == null) ? -1 : buttonFlowPane.indexOf(button);

        TabPane tabPane = (TabPane)getComponent();
        tabPane.setSelectedIndex(index);
    }
}
TOP

Related Classes of pivot.wtk.skin.terra.TerraTabPaneSkin

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.