// BlogBridge -- RSS feed reader, manager, and web based service
// Copyright (C) 2002-2007 by R. Pito Salas
//
// This program 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 of the License, or (at your option) any later version.
//
// This program 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 this program;
// if not, write to the Free Software Foundation, Inc., 59 Temple Place,
// Suite 330, Boston, MA 02111-1307 USA
//
// Contact: R. Pito Salas
// mailto:pitosalas@users.sourceforge.net
// More information: about BlogBridge
// http://www.blogbridge.com
// http://sourceforge.net/projects/blogbridge
//
// $Id: PagingControl.java,v 1.4 2007/07/19 11:02:28 spyromus Exp $
//
package com.salas.bb.views;
import com.jgoodies.binding.value.ValueModel;
import javax.swing.*;
import java.awt.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
/**
* Shows two buttons and controls their state.
* Sends the events to the listeners when the user clicks on the buttons.
*/
public class PagingControl extends AbstractSelectorComponent
{
/** Mode / button code for the previous page button. */
private static final int PREV = 0;
/** Mode / button code for the next page button. */
private static final int NEXT = 1;
private static final String[] BUTTONS = { "left", "right" };
private static final Icon[][] ICONS = prepareIcons(BUTTONS);
/** The maximum number of pages. */
private int pageCount;
private int xSep;
private int xNext;
/** The model holding the number of pages. */
private final ValueModel pageCountModel;
/**
* Creates a control with the page model.
*
* @param pageModel the integer model containing the page number.
* @param pageCountModel the integer model for the number of pages.
*/
public PagingControl(ValueModel pageModel, ValueModel pageCountModel)
{
super(pageModel);
this.pageCountModel = pageCountModel;
pageCountModel.addValueChangeListener(new PageCountModelListener());
setPageCount((Integer)pageCountModel.getValue());
pageModel.addValueChangeListener(new PageModelListener());
}
/**
* Sets the maximum number of pages this control should
* operate with. If the model has page number greater than
* maximum, it's set to zero. If the <code>maxPages</code>
* is zero, the page number is still zero and controls are disabled.
*
* @param pageCount new number of pages.
*/
public void setPageCount(int pageCount)
{
this.pageCount = pageCount;
// Sets the last page if there are not enough pages
if (getCurrentPage() > pageCount - 2)
{
model.setValue(pageCount == 0 ? 0 : pageCount - 1);
}
repaint();
}
/**
* Returns current page.
*
* @return current page.
*/
public int getCurrentPage()
{
return (Integer)model.getValue();
}
@Override
protected Icon getIcon(int button, State state)
{
return ICONS[button][state.ordinal()];
}
@Override
protected void setMode(int mode)
{
int curPage = getCurrentPage();
if (mode == PREV)
{
// Previous page request
if (curPage > 0) model.setValue(curPage - 1);
} else
{
// Next page request
if (curPage < pageCount - 1) model.setValue(curPage + 1);
}
}
/**
* Invoked when painting of the component is necessary.
*
* @param g graphics context.
*/
protected void paintComponent(Graphics g)
{
int curPage = getCurrentPage();
State prevState = curPage < 1 ? State.OFF
: pressed == PREV && mouseOver ? State.PRESSED : State.ON;
State nextState = curPage >= pageCount - 1 ? State.OFF
: pressed == NEXT && mouseOver ? State.PRESSED : State.ON;
State sepaState = (prevState == State.ON || nextState == State.ON ||
prevState == State.PRESSED || nextState == State.PRESSED)
? State.PRESSED : State.OFF;
getIcon(PREV, prevState).paintIcon(this, g, 0, 0);
getSeparatorIcon(sepaState).paintIcon(this, g, xSep, 0);
getIcon(NEXT, nextState).paintIcon(this, g, xNext, 0);
}
@Override
protected int locationToMode(Point aPoint)
{
int md;
int x = aPoint.x;
if (x >= xNext)
{
md = NEXT;
} else
{
md = PREV;
}
return md;
}
/**
* Reports a desired dimensions for this component. Used during the construction (once).
*
* @return dimensions.
*/
protected Dimension getPreferredDimensions()
{
Dimension dimPrev = getIconDimension(PREV, State.ON);
Dimension divNext = getIconDimension(NEXT, State.ON);
Dimension dimSep = getIconDimensions(getSeparatorIcon(State.ON));
xSep = dimPrev.width;
xNext = xSep + dimSep.width;
return new Dimension(xNext + divNext.width, dimPrev.height);
}
/**
* Monitors the changes in the page count.
*/
private class PageCountModelListener implements PropertyChangeListener
{
/**
* Invoked when the property changes.
*
* @param evt event.
*/
public void propertyChange(PropertyChangeEvent evt)
{
setPageCount((Integer)evt.getNewValue());
}
}
/**
* Repaints the control when the page number changes from outside.
*/
private class PageModelListener implements PropertyChangeListener
{
/**
* Invoked when the property changes.
*
* @param evt event.
*/
public void propertyChange(PropertyChangeEvent evt)
{
repaint();
}
}
}