Package org.jvnet.substance.utils

Source Code of org.jvnet.substance.utils.SubstanceSplitPaneDivider

/*
* Copyright (c) 2005-2009 Substance Kirill Grouchnikov. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
*  o Redistributions of source code must retain the above copyright notice,
*    this list of conditions and the following disclaimer.
*
*  o Redistributions in binary form must reproduce the above copyright notice,
*    this list of conditions and the following disclaimer in the documentation
*    and/or other materials provided with the distribution.
*
*  o Neither the name of Substance Kirill Grouchnikov nor the names of
*    its contributors may be used to endorse or promote products derived
*    from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jvnet.substance.utils;

import java.awt.*;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.basic.BasicSplitPaneDivider;
import javax.swing.plaf.basic.BasicSplitPaneUI;

import org.jvnet.lafwidget.animation.*;
import org.jvnet.lafwidget.layout.TransitionLayout;
import org.jvnet.substance.SubstanceLookAndFeel;
import org.jvnet.substance.SubstanceSplitPaneUI;
import org.jvnet.substance.api.*;
import org.jvnet.substance.painter.utils.BackgroundPaintingUtils;
import org.jvnet.substance.utils.icon.TransitionAwareIcon;

/**
* Split pane divider in <code>Substance</code> look and feel.
*
* @author Kirill Grouchnikov
*/
public class SubstanceSplitPaneDivider extends BasicSplitPaneDivider implements
    Trackable {
  /**
   * Listener for fade animations.
   */
  private RolloverControlListener substanceRolloverListener;
  /**
   * Listener for fade animations.
   */
  protected FadeStateListener substanceFadeStateListener;
  /**
   * Listener on property change events.
   */
  private PropertyChangeListener substancePropertyChangeListener;
  /**
   * Surrogate button model for tracking the thumb transitions.
   */
  private ButtonModel gripModel;

  /**
   * Simple constructor.
   *
   * @param ui
   *            Associated UI.
   */
  public SubstanceSplitPaneDivider(SubstanceSplitPaneUI ui) {
    super(ui);
    this.setLayout(new SubstanceDividerLayout());
  }

  @Override
  public void setBasicSplitPaneUI(BasicSplitPaneUI newUI) {
    if (this.splitPane != null) {
      // fix for defect 358 - multiple listeners were installed
      // on the same split pane
      this.uninstall();
    }

    if (newUI != null) {
      // installing
      this.splitPane = newUI.getSplitPane();

      this.gripModel = new DefaultButtonModel();
      this.gripModel.setArmed(false);
      this.gripModel.setSelected(false);
      this.gripModel.setPressed(false);
      this.gripModel.setRollover(false);
      this.gripModel.setEnabled(this.splitPane.isEnabled());

      // fix for defect 109 - memory leak on changing skin
      this.substanceRolloverListener = new RolloverControlListener(this,
          this.gripModel);
      this.addMouseListener(this.substanceRolloverListener);
      this.addMouseMotionListener(this.substanceRolloverListener);

      this.substancePropertyChangeListener = new PropertyChangeListener() {
        public void propertyChange(PropertyChangeEvent evt) {
          if ("enabled".equals(evt.getPropertyName())) {
            boolean isEnabled = splitPane.isEnabled();
            gripModel.setEnabled(isEnabled);
            if (leftButton != null)
              leftButton.setEnabled(isEnabled);
            if (rightButton != null)
              rightButton.setEnabled(isEnabled);
            setEnabled(isEnabled);
          }
        }
      };
      // System.out.println("Registering " + this.hashCode() + ":"
      // + this.substancePropertyChangeListener.hashCode() + " on "
      // + this.splitPane.hashCode());
      this.splitPane
          .addPropertyChangeListener(this.substancePropertyChangeListener);

      this.substanceFadeStateListener = new FadeStateListener(this,
          this.gripModel, SubstanceCoreUtilities.getFadeCallback(
              this.splitPane, this.gripModel, false, false, this));
      this.substanceFadeStateListener.registerListeners(false);
    } else {
      uninstall();
    }
    super.setBasicSplitPaneUI(newUI);
  }

  /**
   * Uninstalls this divider.
   */
  private void uninstall() {
    // uninstalling
    // fix for defect 109 - memory leak on changing skin
    this.removeMouseListener(this.substanceRolloverListener);
    this.removeMouseMotionListener(this.substanceRolloverListener);
    this.substanceRolloverListener = null;

    if (this.substancePropertyChangeListener != null) {
      // System.out.println("Unregistering " + this.hashCode() + ":"
      // + this.substancePropertyChangeListener.hashCode()
      // + " from " + this.splitPane.hashCode());
      this.splitPane
          .removePropertyChangeListener(this.substancePropertyChangeListener);
      this.substancePropertyChangeListener = null;
    }

    if (this.substanceFadeStateListener != null) {
      this.substanceFadeStateListener.unregisterListeners();
      this.substanceFadeStateListener = null;
    }
  }

  /*
   * (non-Javadoc)
   *
   * @see java.awt.Component#paint(java.awt.Graphics)
   */
  @Override
  public void paint(Graphics g) {
    if (SubstanceCoreUtilities.hasFlatAppearance(this.splitPane, true)) {
      BackgroundPaintingUtils.updateIfOpaque(g, this.splitPane);
    }

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

    ComponentState currState = ComponentState.getState(this.gripModel,
        this.splitPane);
    ComponentState prevState = SubstanceCoreUtilities
        .getPrevComponentState(this.splitPane);
    float alpha = SubstanceColorSchemeUtilities.getAlpha(this.splitPane,
        currState);

    if (alpha < 1.0f) {
      graphics.setComposite(TransitionLayout.getAlphaComposite(
          this.splitPane, alpha, g));
    }

    FadeState fadeState = SubstanceFadeUtilities.getFadeState(this,
        FadeKind.ROLLOVER, FadeKind.SELECTION, FadeKind.PRESS);
    float cyclePos = 1.0f;
    if (fadeState != null) {
      cyclePos = fadeState.getFadePosition();
      if (fadeState.isFadingIn())
        cyclePos = 1.0f - cyclePos;
    }

    // compute the grip handle dimension
    int minSizeForGripPresence = SubstanceSizeUtils.getAdjustedSize(
        SubstanceSizeUtils.getComponentFontSize(this), 30, 1, 2, false);
    int maxGripSize = SubstanceSizeUtils.getAdjustedSize(SubstanceSizeUtils
        .getComponentFontSize(this), 40, 1, 3, false);
    if (this.splitPane.getOrientation() == JSplitPane.HORIZONTAL_SPLIT) {
      int thumbHeight = this.getHeight();
      if (thumbHeight >= minSizeForGripPresence) {
        int gripHeight = thumbHeight / 4;
        if (gripHeight > maxGripSize)
          gripHeight = maxGripSize;

        int thumbWidth = this.getWidth();

        int gripX = 0;
        int gripY = (thumbHeight - gripHeight) / 2;

        // draw the grip bumps
        SubstanceImageCreator.paintSplitDividerBumpImage(graphics,
            this, gripX, gripY, thumbWidth, gripHeight, false,
            currState, SubstanceColorSchemeUtilities
                .getColorScheme(this,
                    ColorSchemeAssociationKind.MARK,
                    currState),
            SubstanceColorSchemeUtilities.getColorScheme(this,
                ColorSchemeAssociationKind.MARK, prevState),
            cyclePos);
      }
    } else {
      int thumbWidth = this.getWidth();
      if (thumbWidth >= minSizeForGripPresence) {
        int gripWidth = thumbWidth / 4;
        if (gripWidth > maxGripSize)
          gripWidth = maxGripSize;

        int thumbHeight = this.getHeight();
        // int gripHeight = thumbHeight * 2 / 3;

        int gripX = (thumbWidth - gripWidth) / 2;
        int gripY = 1;
        // draw the grip bumps
        SubstanceImageCreator.paintSplitDividerBumpImage(graphics,
            this, gripX, gripY, gripWidth, thumbHeight, true,
            currState, SubstanceColorSchemeUtilities
                .getColorScheme(this,
                    ColorSchemeAssociationKind.MARK,
                    currState),
            SubstanceColorSchemeUtilities.getColorScheme(this,
                ColorSchemeAssociationKind.MARK, prevState),
            cyclePos);
      }
    }

    graphics.dispose();

    super.paint(g);
  }

  /*
   * (non-Javadoc)
   *
   * @see
   * javax.swing.plaf.basic.BasicSplitPaneDivider#createLeftOneTouchButton()
   */
  @Override
  protected JButton createLeftOneTouchButton() {
    JButton oneTouchButton = new JButton() {
      // Don't want the button to participate in focus traversable.
      @Override
      public boolean isFocusable() {
        return false;
      }
    };
    Icon verticalSplit = new TransitionAwareIcon(oneTouchButton,
        new TransitionAwareIcon.Delegate() {
          public Icon getColorSchemeIcon(SubstanceColorScheme scheme) {
            int fontSize = SubstanceSizeUtils
                .getComponentFontSize(splitPane);
            return SubstanceImageCreator.getArrowIcon(
                SubstanceSizeUtils
                    .getSplitPaneArrowIconWidth(fontSize),
                SubstanceSizeUtils
                    .getSplitPaneArrowIconHeight(fontSize),
                SubstanceSizeUtils
                    .getArrowStrokeWidth(fontSize),
                SwingConstants.NORTH, scheme);
          }
        }, "substance.splitPane.left.vertical");
    Icon horizontalSplit = new TransitionAwareIcon(oneTouchButton,
        new TransitionAwareIcon.Delegate() {
          public Icon getColorSchemeIcon(SubstanceColorScheme scheme) {
            int fontSize = SubstanceSizeUtils
                .getComponentFontSize(splitPane);
            return SubstanceImageCreator.getArrowIcon(
                SubstanceSizeUtils
                    .getSplitPaneArrowIconWidth(fontSize),
                SubstanceSizeUtils
                    .getSplitPaneArrowIconHeight(fontSize),
                SubstanceSizeUtils
                    .getArrowStrokeWidth(fontSize),
                SwingConstants.WEST, scheme);
          }
        }, "substance.splitPane.left.horizontal");
    oneTouchButton
        .setIcon(this.splitPane.getOrientation() == JSplitPane.VERTICAL_SPLIT ? verticalSplit
            : horizontalSplit);

    oneTouchButton.putClientProperty(
        SubstanceLookAndFeel.BUTTON_PAINT_NEVER_PROPERTY, Boolean.TRUE);
    // fix for issue 281 - set empty border so that the arrow
    // icon is not cropped
    oneTouchButton.setBorder(new EmptyBorder(0, 0, 0, 0));

    oneTouchButton.setRequestFocusEnabled(false);
    oneTouchButton
        .setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
    oneTouchButton.setFocusPainted(false);
    oneTouchButton.setBorderPainted(false);
    return oneTouchButton;
  }

  /*
   * (non-Javadoc)
   *
   * @see
   * javax.swing.plaf.basic.BasicSplitPaneDivider#createRightOneTouchButton()
   */
  @Override
  protected JButton createRightOneTouchButton() {
    JButton oneTouchButton = new JButton() {
      // Don't want the button to participate in focus traversable.
      @Override
      public boolean isFocusable() {
        return false;
      }
    };
    Icon verticalSplit = new TransitionAwareIcon(oneTouchButton,
        new TransitionAwareIcon.Delegate() {
          public Icon getColorSchemeIcon(SubstanceColorScheme scheme) {
            int fontSize = SubstanceSizeUtils
                .getComponentFontSize(splitPane);
            return SubstanceImageCreator.getArrowIcon(
                SubstanceSizeUtils
                    .getSplitPaneArrowIconWidth(fontSize),
                SubstanceSizeUtils
                    .getSplitPaneArrowIconHeight(fontSize),
                SubstanceSizeUtils
                    .getArrowStrokeWidth(fontSize),
                SwingConstants.SOUTH, scheme);
          }
        }, "substance.splitPane.right.vertical");
    Icon horizontalSplit = new TransitionAwareIcon(oneTouchButton,
        new TransitionAwareIcon.Delegate() {
          public Icon getColorSchemeIcon(SubstanceColorScheme scheme) {
            int fontSize = SubstanceSizeUtils
                .getComponentFontSize(splitPane);
            return SubstanceImageCreator.getArrowIcon(
                SubstanceSizeUtils
                    .getSplitPaneArrowIconWidth(fontSize),
                SubstanceSizeUtils
                    .getSplitPaneArrowIconHeight(fontSize),
                SubstanceSizeUtils
                    .getArrowStrokeWidth(fontSize),
                SwingConstants.EAST, scheme);
          }
        }, "substance.splitPane.right.horizontal");
    oneTouchButton
        .setIcon(this.splitPane.getOrientation() == JSplitPane.VERTICAL_SPLIT ? verticalSplit
            : horizontalSplit);

    oneTouchButton.putClientProperty(
        SubstanceLookAndFeel.BUTTON_PAINT_NEVER_PROPERTY, Boolean.TRUE);
    // fix for issue 281 - set empty border so that the arrow
    // icon is not cropped
    oneTouchButton.setBorder(new EmptyBorder(0, 0, 0, 0));

    oneTouchButton
        .setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
    oneTouchButton.setFocusPainted(false);
    oneTouchButton.setBorderPainted(false);
    oneTouchButton.setRequestFocusEnabled(false);
    // b.setOpaque(false);
    return oneTouchButton;
  }

  /**
   * Updates the one-touch buttons.
   *
   * @param orientation
   *            Split pane orientation.
   */
  public void updateOneTouchButtons(int orientation) {
    if (orientation == JSplitPane.VERTICAL_SPLIT) {
      if (this.leftButton != null) {
        this.leftButton.setIcon(new TransitionAwareIcon(
            this.leftButton, new TransitionAwareIcon.Delegate() {
              public Icon getColorSchemeIcon(
                  SubstanceColorScheme scheme) {
                int fontSize = SubstanceSizeUtils
                    .getComponentFontSize(splitPane);
                return SubstanceImageCreator
                    .getArrowIcon(
                        SubstanceSizeUtils
                            .getSplitPaneArrowIconWidth(fontSize),
                        SubstanceSizeUtils
                            .getSplitPaneArrowIconHeight(fontSize),
                        SubstanceSizeUtils
                            .getArrowStrokeWidth(fontSize),
                        SwingConstants.NORTH, scheme);
              }
            }, "substance.splitPane.left.vertical"));
      }
      if (this.rightButton != null) {
        this.rightButton.setIcon(new TransitionAwareIcon(
            this.rightButton, new TransitionAwareIcon.Delegate() {
              public Icon getColorSchemeIcon(
                  SubstanceColorScheme scheme) {
                int fontSize = SubstanceSizeUtils
                    .getComponentFontSize(splitPane);
                return SubstanceImageCreator
                    .getArrowIcon(
                        SubstanceSizeUtils
                            .getSplitPaneArrowIconWidth(fontSize),
                        SubstanceSizeUtils
                            .getSplitPaneArrowIconHeight(fontSize),
                        SubstanceSizeUtils
                            .getArrowStrokeWidth(fontSize),
                        SwingConstants.SOUTH, scheme);
              }
            }, "substance.splitPane.right.vertical"));
      }
    } else {
      if (this.leftButton != null) {
        this.leftButton.setIcon(new TransitionAwareIcon(
            this.leftButton, new TransitionAwareIcon.Delegate() {
              public Icon getColorSchemeIcon(
                  SubstanceColorScheme scheme) {
                int fontSize = SubstanceSizeUtils
                    .getComponentFontSize(splitPane);
                return SubstanceImageCreator
                    .getArrowIcon(
                        SubstanceSizeUtils
                            .getSplitPaneArrowIconWidth(fontSize),
                        SubstanceSizeUtils
                            .getSplitPaneArrowIconHeight(fontSize),
                        SubstanceSizeUtils
                            .getArrowStrokeWidth(fontSize),
                        SwingConstants.WEST, scheme);
              }
            }, "substance.splitPane.left.horizontal"));
      }
      if (this.rightButton != null) {
        this.rightButton.setIcon(new TransitionAwareIcon(
            this.rightButton, new TransitionAwareIcon.Delegate() {
              public Icon getColorSchemeIcon(
                  SubstanceColorScheme scheme) {
                int fontSize = SubstanceSizeUtils
                    .getComponentFontSize(splitPane);
                return SubstanceImageCreator
                    .getArrowIcon(
                        SubstanceSizeUtils
                            .getSplitPaneArrowIconWidth(fontSize),
                        SubstanceSizeUtils
                            .getSplitPaneArrowIconHeight(fontSize),
                        SubstanceSizeUtils
                            .getArrowStrokeWidth(fontSize),
                        SwingConstants.EAST, scheme);
              }
            }, "substance.splitPane.right.horizontal"));
      }
    }
  }

  /*
   * (non-Javadoc)
   *
   * @see
   * org.jvnet.substance.utils.Trackable#isInside(java.awt.event.MouseEvent)
   */
  public boolean isInside(MouseEvent me) {
    // entire area is sensitive
    return true;
  }

  /**
   * Layout manager for the split pane divider.
   *
   * @author Kirill Grouchnikov
   */
  protected class SubstanceDividerLayout extends DividerLayout {
    @Override
    public void layoutContainer(Container c) {
      if (leftButton != null && rightButton != null
          && c == SubstanceSplitPaneDivider.this) {
        if (splitPane.isOneTouchExpandable()) {
          Insets insets = getInsets();

          if (orientation == JSplitPane.VERTICAL_SPLIT) {
            int extraX = (insets != null) ? insets.left : 0;
            int blockSize = getHeight();

            if (insets != null) {
              blockSize -= (insets.top + insets.bottom);
              blockSize = Math.max(blockSize, 0);
            }

            int y = (c.getSize().height - blockSize) / 2;

            int offset = SubstanceSizeUtils
                .getSplitPaneButtonOffset(SubstanceSizeUtils
                    .getComponentFontSize(splitPane));
            leftButton.setBounds(extraX + offset, y, leftButton
                .getPreferredSize().width * 2 / 3, blockSize);
            rightButton.setBounds(leftButton.getX()
                + leftButton.getWidth(), y, rightButton
                .getPreferredSize().width * 2 / 3, blockSize);
          } else {
            int extraY = (insets != null) ? insets.top : 0;
            int blockSize = getWidth();

            if (insets != null) {
              blockSize -= (insets.left + insets.right);
              blockSize = Math.max(blockSize, 0);
            }

            int x = (c.getSize().width - blockSize) / 2;

            int offset = SubstanceSizeUtils
                .getSplitPaneButtonOffset(SubstanceSizeUtils
                    .getComponentFontSize(splitPane));
            leftButton.setBounds(x, extraY + offset, blockSize,
                leftButton.getPreferredSize().height * 2 / 3);
            rightButton.setBounds(x, leftButton.getY()
                + leftButton.getHeight(), blockSize, leftButton
                .getPreferredSize().height * 2 / 3);
          }
        } else {
          leftButton.setBounds(-5, -5, 1, 1);
          rightButton.setBounds(-5, -5, 1, 1);
        }
      }
    }
  }
}
TOP

Related Classes of org.jvnet.substance.utils.SubstanceSplitPaneDivider

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.