org.pushingpixels.flamingo.internal.ui.common.BasicScrollablePanelUI Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of flamengo Show documentation
Show all versions of flamengo Show documentation
Flamingo Swing component suite
The newest version!
/*
* Copyright (c) 2005-2010 Flamingo 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 Flamingo 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.pushingpixels.flamingo.internal.ui.common;
import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.*;
import javax.swing.plaf.ComponentUI;
import org.pushingpixels.flamingo.api.common.JCommandButton;
import org.pushingpixels.flamingo.api.common.JScrollablePanel;
import org.pushingpixels.flamingo.api.common.JScrollablePanel.ScrollType;
import org.pushingpixels.flamingo.internal.utils.DoubleArrowResizableIcon;
/**
* Basic UI for scrollable panel {@link JScrollablePanel}.
*
* @author Kirill Grouchnikov
*/
public class BasicScrollablePanelUI extends ScrollablePanelUI {
/**
* The associated scrollable panel.
*/
protected JScrollablePanel scrollablePanel;
private JPanel viewport;
private JCommandButton leadingScroller;
private JCommandButton trailingScroller;
private int viewOffset;
private MouseWheelListener mouseWheelListener;
private PropertyChangeListener propertyChangeListener;
private ComponentListener componentListener;
/*
* (non-Javadoc)
*
* @see javax.swing.plaf.ComponentUI#createUI(javax.swing.JComponent)
*/
public static ComponentUI createUI(JComponent c) {
return new BasicScrollablePanelUI();
}
/*
* (non-Javadoc)
*
* @see javax.swing.plaf.ComponentUI#installUI(javax.swing.JComponent)
*/
@Override
public void installUI(JComponent c) {
this.scrollablePanel = (JScrollablePanel) c;
super.installUI(this.scrollablePanel);
installDefaults();
installComponents();
installListeners();
}
protected void installListeners() {
this.mouseWheelListener = new MouseWheelListener() {
@Override
public void mouseWheelMoved(MouseWheelEvent e) {
if (scrollablePanel.getScrollType() != JScrollablePanel.ScrollType.VERTICALLY) {
return;
}
int scrollAmount = 8 * e.getScrollAmount()
* e.getWheelRotation();
viewOffset += scrollAmount;
syncScrolling();
}
};
this.scrollablePanel.addMouseWheelListener(this.mouseWheelListener);
this.propertyChangeListener = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if ("scrollOnRollover".equals(evt.getPropertyName())) {
boolean isScrollOnRollover = (Boolean) evt.getNewValue();
leadingScroller.setFireActionOnRollover(isScrollOnRollover);
trailingScroller
.setFireActionOnRollover(isScrollOnRollover);
}
}
};
this.scrollablePanel
.addPropertyChangeListener(this.propertyChangeListener);
if (this.scrollablePanel.getView() != null) {
this.componentListener = new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
scrollablePanel.doLayout();
}
};
this.scrollablePanel.getView().addComponentListener(
this.componentListener);
}
}
protected void installComponents() {
this.viewport = new JPanel(new LayoutManager() {
@Override
public void addLayoutComponent(String name, Component comp) {
}
@Override
public void removeLayoutComponent(Component comp) {
}
@Override
public Dimension preferredLayoutSize(Container parent) {
return new Dimension(10, 10);
}
@Override
public Dimension minimumLayoutSize(Container parent) {
return preferredLayoutSize(parent);
}
@Override
public void layoutContainer(Container parent) {
JComponent view = scrollablePanel.getView();
if (scrollablePanel.getScrollType() == ScrollType.HORIZONTALLY) {
int viewWidth = view.getPreferredSize().width;
int availWidth = parent.getWidth();
int offsetX = -viewOffset;
view.setBounds(offsetX, 0, Math.max(viewWidth, availWidth),
parent.getHeight());
} else {
int viewHeight = view.getPreferredSize().height;
int availHeight = parent.getHeight();
int offsetY = -viewOffset;
view.setBounds(0, offsetY, parent.getWidth(), Math.max(
viewHeight, availHeight));
}
}
});
JComponent view = scrollablePanel.getView();
if (view != null) {
this.viewport.add(view);
}
this.scrollablePanel.add(this.viewport);
this.leadingScroller = this.createLeadingScroller();
this.configureLeftScrollerButtonAction();
this.scrollablePanel.add(this.leadingScroller);
this.trailingScroller = this.createTrailingScroller();
this.configureRightScrollerButtonAction();
this.scrollablePanel.add(this.trailingScroller);
}
protected void installDefaults() {
this.scrollablePanel.setLayout(new ScrollablePanelLayout());
}
/*
* (non-Javadoc)
*
* @see javax.swing.plaf.ComponentUI#uninstallUI(javax.swing.JComponent)
*/
@Override
public void uninstallUI(JComponent c) {
uninstallListeners();
uninstallComponents();
uninstallDefaults();
super.uninstallUI(this.scrollablePanel);
}
protected void uninstallDefaults() {
}
protected void uninstallComponents() {
this.scrollablePanel.remove(this.viewport);
this.scrollablePanel.remove(this.leadingScroller);
this.scrollablePanel.remove(this.trailingScroller);
}
protected void uninstallListeners() {
this.scrollablePanel
.removePropertyChangeListener(this.propertyChangeListener);
this.propertyChangeListener = null;
this.scrollablePanel.removeMouseWheelListener(this.mouseWheelListener);
this.mouseWheelListener = null;
if (this.scrollablePanel.getView() != null) {
this.scrollablePanel.getView().removeComponentListener(
this.componentListener);
this.componentListener = null;
}
}
protected JCommandButton createLeadingScroller() {
JCommandButton b = new JCommandButton(
null,
new DoubleArrowResizableIcon(
new Dimension(9, 9),
this.scrollablePanel.getScrollType() == ScrollType.HORIZONTALLY ? SwingConstants.WEST
: SwingConstants.NORTH));
b.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
b.setFocusable(false);
b.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
b.putClientProperty(BasicCommandButtonUI.EMULATE_SQUARE_BUTTON,
Boolean.TRUE);
b.putClientProperty(BasicCommandButtonUI.DONT_DISPOSE_POPUPS,
Boolean.TRUE);
return b;
}
protected JCommandButton createTrailingScroller() {
JCommandButton b = new JCommandButton(
null,
new DoubleArrowResizableIcon(
new Dimension(9, 9),
this.scrollablePanel.getScrollType() == ScrollType.HORIZONTALLY ? SwingConstants.EAST
: SwingConstants.SOUTH));
b.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
b.setFocusable(false);
b.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
b.putClientProperty(BasicCommandButtonUI.EMULATE_SQUARE_BUTTON,
Boolean.TRUE);
b.putClientProperty(BasicCommandButtonUI.DONT_DISPOSE_POPUPS,
Boolean.TRUE);
return b;
}
private void syncScrolling() {
this.scrollablePanel.doLayout();
}
public void removeScrollers() {
if (this.leadingScroller.getParent() == this.scrollablePanel) {
this.scrollablePanel.remove(this.leadingScroller);
this.scrollablePanel.remove(this.trailingScroller);
syncScrolling();
this.scrollablePanel.revalidate();
this.scrollablePanel.repaint();
}
}
private void addScrollers() {
this.scrollablePanel.add(this.leadingScroller);
this.scrollablePanel.add(this.trailingScroller);
this.scrollablePanel.revalidate();
JComponent view = this.scrollablePanel.getView();
view.setPreferredSize(view.getMinimumSize());
view.setSize(view.getMinimumSize());
this.scrollablePanel.doLayout();
this.scrollablePanel.repaint();
}
protected void configureLeftScrollerButtonAction() {
this.leadingScroller.setAutoRepeatAction(true);
this.leadingScroller.setAutoRepeatActionIntervals(200, 50);
this.leadingScroller.setFireActionOnRollover(this.scrollablePanel
.isScrollOnRollover());
this.leadingScroller.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
viewOffset -= 12;
syncScrolling();
}
});
}
protected void configureRightScrollerButtonAction() {
this.trailingScroller.setAutoRepeatAction(true);
this.trailingScroller.setAutoRepeatActionIntervals(200, 50);
this.trailingScroller.setFireActionOnRollover(this.scrollablePanel
.isScrollOnRollover());
this.trailingScroller.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
viewOffset += 12;
syncScrolling();
}
});
}
@Override
public void scrollToIfNecessary(int startPosition, int span) {
if (this.scrollablePanel.getScrollType() == ScrollType.HORIZONTALLY) {
if (this.scrollablePanel.getComponentOrientation().isLeftToRight()) {
revealRightEdge(startPosition, span);
revealLeftEdge(startPosition);
} else {
revealLeftEdge(startPosition);
revealRightEdge(startPosition, span);
}
} else {
revealBottomEdge(startPosition, span);
revealTopEdge(startPosition);
}
}
private void revealLeftEdge(int x) {
if (x < viewOffset) {
// left edge is not visible
viewOffset = x - 5;
syncScrolling();
}
}
private void revealRightEdge(int x, int width) {
if ((x + width) > (viewOffset + viewport.getWidth())) {
// right edge is not visible
viewOffset = x + width - viewport.getWidth() + 5;
syncScrolling();
}
}
private void revealTopEdge(int y) {
if (y < viewOffset) {
// top edge is not visible
viewOffset = y - 5;
syncScrolling();
}
}
private void revealBottomEdge(int y, int height) {
if ((y + height) > (viewOffset + viewport.getHeight())) {
// bottom edge is not visible
viewOffset = y + height - viewport.getHeight() + 5;
syncScrolling();
}
}
@Override
public boolean isShowingScrollButtons() {
return (this.leadingScroller.isVisible());
}
/**
* Layout for the scrollable panel.
*
* @author Kirill Grouchnikov
* @author Topologi
*/
protected class ScrollablePanelLayout implements LayoutManager {
/**
* Creates new layout manager.
*/
public ScrollablePanelLayout() {
}
/*
* (non-Javadoc)
*
* @see java.awt.LayoutManager#addLayoutComponent(java.lang.String,
* java.awt.Component)
*/
public void addLayoutComponent(String name, Component c) {
}
/*
* (non-Javadoc)
*
* @see java.awt.LayoutManager#removeLayoutComponent(java.awt.Component)
*/
public void removeLayoutComponent(Component c) {
}
/*
* (non-Javadoc)
*
* @see java.awt.LayoutManager#preferredLayoutSize(java.awt.Container)
*/
public Dimension preferredLayoutSize(Container c) {
if (scrollablePanel.getScrollType() == ScrollType.HORIZONTALLY) {
return new Dimension(c.getWidth(), 21);
} else {
return new Dimension(21, c.getHeight());
}
}
/*
* (non-Javadoc)
*
* @see java.awt.LayoutManager#minimumLayoutSize(java.awt.Container)
*/
public Dimension minimumLayoutSize(Container c) {
if (scrollablePanel.getScrollType() == ScrollType.HORIZONTALLY) {
return new Dimension(10, 21);
} else {
return new Dimension(21, 10);
}
}
/*
* (non-Javadoc)
*
* @see java.awt.LayoutManager#layoutContainer(java.awt.Container)
*/
public void layoutContainer(Container c) {
int width = c.getWidth();
int height = c.getHeight();
Insets ins = c.getInsets();
JComponent view = scrollablePanel.getView();
Dimension viewPrefSize = view.getPreferredSize();
// System.out.println(width + "*" + height + " - "
// + viewPrefSize.width + "*" + viewPrefSize.height);
if (scrollablePanel.getScrollType() == ScrollType.HORIZONTALLY) {
boolean shouldShowScrollerButtons = (viewPrefSize.width > width);
leadingScroller.setVisible(shouldShowScrollerButtons);
trailingScroller.setVisible(shouldShowScrollerButtons);
int scrollPanelWidth = shouldShowScrollerButtons ? width
- ins.left - ins.right
- leadingScroller.getPreferredSize().width
- trailingScroller.getPreferredSize().width - 4 : width
- ins.left - ins.right;
int x = ins.left;
if (shouldShowScrollerButtons) {
int spw = leadingScroller.getPreferredSize().width;
leadingScroller.setBounds(x, ins.top, spw, height - ins.top
- ins.bottom);
x += spw + 2;
}
viewport.setBounds(x, ins.top, scrollPanelWidth, height
- ins.top - ins.bottom);
int viewPreferredWidth = view.getPreferredSize().width;
if (viewOffset < 0) {
viewOffset = 0;
}
if ((viewPreferredWidth > 0)
&& (viewOffset + scrollPanelWidth > viewPreferredWidth)) {
viewOffset = Math.max(0, viewPreferredWidth
- scrollPanelWidth);
}
viewport.doLayout();
x += scrollPanelWidth + 2;
if (shouldShowScrollerButtons) {
int spw = trailingScroller.getPreferredSize().width;
trailingScroller.setBounds(x, ins.top, spw, height
- ins.top - ins.bottom);
}
} else {
boolean shouldShowScrollerButtons = (viewPrefSize.height > height);
leadingScroller.setVisible(shouldShowScrollerButtons);
trailingScroller.setVisible(shouldShowScrollerButtons);
int scrollPanelHeight = shouldShowScrollerButtons ? height
- ins.top - ins.bottom
- leadingScroller.getPreferredSize().height
- trailingScroller.getPreferredSize().height - 4
: height - ins.top - ins.bottom;
int y = ins.top;
if (shouldShowScrollerButtons) {
int sph = leadingScroller.getPreferredSize().height;
leadingScroller.setBounds(ins.left, y, width - ins.left
- ins.right, sph);
y += sph + 2;
}
viewport.setBounds(ins.left, y, width - ins.left - ins.right,
scrollPanelHeight);
int viewPreferredHeight = view.getPreferredSize().height;
if (viewOffset < 0) {
viewOffset = 0;
}
if ((viewPreferredHeight > 0)
&& (viewOffset + scrollPanelHeight > viewPreferredHeight)) {
viewOffset = Math.max(0, viewPreferredHeight
- scrollPanelHeight);
}
viewport.doLayout();
y += scrollPanelHeight + 2;
if (shouldShowScrollerButtons) {
int sph = trailingScroller.getPreferredSize().height;
trailingScroller.setBounds(ins.left, y, width - ins.left
- ins.right, sph);
}
}
if (scrollablePanel.getScrollType() == ScrollType.HORIZONTALLY) {
trailingScroller
.setEnabled((viewOffset + viewport.getWidth()) < view
.getWidth());
} else {
trailingScroller
.setEnabled((viewOffset + viewport.getHeight()) < view
.getHeight());
}
leadingScroller.setEnabled(viewOffset > 0);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy