package org.openswing.swing.table.client;
import java.awt.*;
import javax.swing.*;
import javax.swing.plaf.*;
import javax.swing.plaf.metal.*;
/**
* <p>Title: OpenSwing Framework</p>
* <p>Description: Vertical scrollbar UI, used inside the pagination vertical scrollbar of the grid control, for Unix/Linux LnF.</p>
* <p>Copyright: Copyright (C) 2006 Mauro Carniel</p>
*
* <p> This file is part of OpenSwing Framework.
* This library is free software; you can redistribute it and/or
* modify it under the terms of the (LGPL) Lesser General Public
* License as published by the Free Software Foundation;
*
* GNU LESSER GENERAL PUBLIC LICENSE
* Version 2.1, February 1999
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* The author may be contacted at:
* maurocarniel@tin.it</p>
*
* @author Mauro Carniel
* @version 1.0
*/
public class MetalPaginationVerticalScrollbarUI extends MetalScrollBarUI implements PaginationVerticalScrollbarUI {
protected JButton nextPgButton;
protected JButton prevPgButton;
public MetalPaginationVerticalScrollbarUI() {
super();
}
public static ComponentUI createUI(JComponent c) {
return new MetalPaginationVerticalScrollbarUI();
}
protected JButton createPageButton(int orientation) {
return new PageArrowButton(orientation);
}
protected void installDefaults() {
super.installDefaults();
nextPgButton = createPageButton(SOUTH);
prevPgButton = createPageButton(NORTH);
scrollbar.add(prevPgButton);
scrollbar.add(nextPgButton);
}
protected void layoutVScrollbar(JScrollBar sb) {
Dimension sbSize = sb.getSize();
Insets sbInsets = sb.getInsets();
/*
* Width and left edge of the buttons and thumb.
*/
int itemW = sbSize.width - (sbInsets.left + sbInsets.right);
int itemX = sbInsets.left;
/* Nominal locations of the buttons, assuming their preferred
* size will fit.
*/
int prevPgButtonH = prevPgButton.getPreferredSize().height;
int prevPgButtonY = sbInsets.top;
int decrButtonH = decrButton.getPreferredSize().height;
int decrButtonY = prevPgButtonY+prevPgButtonH;
int incrButtonH = incrButton.getPreferredSize().height;
int nextPgButtonH = nextPgButton.getPreferredSize().height;
int incrButtonY = sbSize.height - (sbInsets.bottom + incrButtonH+nextPgButtonH);
int nextPgButtonY = sbSize.height - (sbInsets.bottom + nextPgButtonH);
/* The thumb must fit within the height left over after we
* subtract the preferredSize of the buttons and the insets.
*/
int sbInsetsH = sbInsets.top + sbInsets.bottom;
int sbButtonsH = decrButtonH + incrButtonH +prevPgButtonH +nextPgButtonH;
float trackH = sbSize.height - (sbInsetsH + sbButtonsH);
/* Compute the height and origin of the thumb. The case
* where the thumb is at the bottom edge is handled specially
* to avoid numerical problems in computing thumbY. Enforce
* the thumbs min/max dimensions. If the thumb doesn't
* fit in the track (trackH) we'll hide it later.
*/
float min = sb.getMinimum();
float extent = sb.getVisibleAmount();
float range = sb.getMaximum() - min;
float value = sb.getValue();
int thumbH = (range <= 0)
? getMaximumThumbSize().height : (int)(trackH * (extent / range));
thumbH = Math.max(thumbH, getMinimumThumbSize().height);
thumbH = Math.min(thumbH, getMaximumThumbSize().height);
int thumbY = incrButtonY - thumbH;
if (sb.getValue() < (sb.getMaximum() - sb.getVisibleAmount())) {
float thumbRange = trackH - thumbH;
thumbY = (int)(0.5f + (thumbRange * ((value - min) / (range - extent))));
thumbY += decrButtonY + decrButtonH;
}
/* If the buttons don't fit, allocate half of the available
* space to each and move the lower one (incrButton) down.
*/
int sbAvailButtonH = (sbSize.height - sbInsetsH);
if (sbAvailButtonH < sbButtonsH) {
incrButtonH = decrButtonH = sbAvailButtonH / 2;
incrButtonY = sbSize.height - (sbInsets.bottom + incrButtonH);
}
prevPgButton.setBounds(itemX, prevPgButtonY, itemW, prevPgButtonH);
decrButton.setBounds(itemX, decrButtonY, itemW, decrButtonH);
incrButton.setBounds(itemX, incrButtonY, itemW, incrButtonH);
nextPgButton.setBounds(itemX, nextPgButtonY, itemW, nextPgButtonH);
/* Update the trackRect field.
*/
int itrackY = decrButtonY + decrButtonH;
int itrackH = incrButtonY - itrackY;
trackRect.setBounds(itemX, itrackY, itemW, itrackH);
/* If the thumb isn't going to fit, zero it's bounds. Otherwise
* make sure it fits between the buttons. Note that setting the
* thumbs bounds will cause a repaint.
*/
if(thumbH >= (int)trackH) {
setThumbBounds(0, 0, 0, 0);
}
else {
if ((thumbY + thumbH) > incrButtonY) {
thumbY = incrButtonY - thumbH;
}
if (thumbY < (decrButtonY + decrButtonH)) {
thumbY = decrButtonY + decrButtonH + 1;
}
setThumbBounds(itemX, thumbY, itemW, thumbH);
}
}
protected void installListeners() {
super.installListeners();
}
protected void uninstallListeners() {
super.uninstallListeners();
}
public JButton getNextPgButton() {
return nextPgButton;
}
public JButton getDecrButton() {
return decrButton;
}
public JButton getIncrButton() {
return incrButton;
}
public JButton getPrevPgButton() {
return prevPgButton;
}
/**
* <p>Title: OpenSwing Framework</p>
* <p>Description: Inner class used to render the scrollbar buttons.</p>
* @author Mauro Carniel
* @version 1.0
*/
class PageArrowButton extends MetalScrollButton {
private Color highlightColor = UIManager.getColor("ScrollBar.highlight");
private Color shadowColor = UIManager.getColor("ScrollBar.darkShadow");
private Color arrowColor = MetalLookAndFeel.getControlInfo();
public PageArrowButton(int direction) {
super(
direction,
incrButton==null?scrollBarWidth:incrButton.getPreferredSize().width,
true
);
}
public void paint(Graphics g) {
boolean isPressed = getModel().isPressed();
int width = getWidth();
int height = getHeight();
int w = width;
int h = height;
int arrowHeight = (height + 1) / 4;
int arrowWidth = (height + 1) / 2;
if (isPressed) {
g.setColor(MetalLookAndFeel.getControlShadow());
}
else {
g.setColor(getBackground());
}
g.fillRect(0, 0, width, height);
if (getDirection() == NORTH) {
if (!isFreeStanding) {
height += 1;
g.translate(0, -1);
width += 2;
}
g.setColor(arrowColor);
// int startY = ( (h + 1) - arrowHeight) / 2;
int startY = ( (h + 1) - arrowHeight) - 3;
int startX = (w / 2);
for (int line = 0; line < arrowHeight; line++) {
g.drawLine(startX - line, startY + line, startX + line + 1,
startY + line);
}
startY = arrowHeight;
for (int line = 0; line < arrowHeight; line++) {
g.drawLine(startX - line, startY + line, startX + line + 1,
startY + line);
}
g.setColor(highlightColor);
if (!isPressed) {
g.drawLine(1, 1, width - 3, 1);
g.drawLine(1, 1, 1, height - 1);
}
g.drawLine(width - 1, 1, width - 1, height - 1);
g.setColor(shadowColor);
g.drawLine(0, 0, width - 2, 0);
g.drawLine(0, 0, 0, height - 1);
g.drawLine(width - 2, 2, width - 2, height - 1);
if (!isFreeStanding) {
height -= 1;
g.translate(0, 1);
width -= 2;
}
}
else if (getDirection() == SOUTH) {
if (!isFreeStanding) {
height += 1;
width += 2;
}
g.setColor(arrowColor);
// int startY = ( ( (h + 1) - arrowHeight) / 2) + arrowHeight - 1;
int startY = ( ( (h + 1) - arrowHeight)) - 2;
int startX = (w / 2);
for (int line = 0; line < arrowHeight; line++) {
g.drawLine(startX - line, startY - line, startX + line + 1,
startY - line);
}
startY = arrowHeight+2;
for (int line = 0; line < arrowHeight; line++) {
g.drawLine(startX - line, startY - line, startX + line + 1,
startY - line);
}
g.setColor(highlightColor);
if (!isPressed) {
g.drawLine(1, 0, width - 3, 0);
g.drawLine(1, 0, 1, height - 3);
}
g.drawLine(1, height - 1, width - 1, height - 1);
g.drawLine(width - 1, 0, width - 1, height - 1);
g.setColor(shadowColor);
g.drawLine(0, 0, 0, height - 2);
g.drawLine(width - 2, 0, width - 2, height - 2);
g.drawLine(2, height - 2, width - 2, height - 2);
if (!isFreeStanding) {
height -= 1;
width -= 2;
}
}
}
}
}