/**************************************************************************
* Copyright (c) 2001, 2002, 2003 by Acunia N.V. All rights reserved. *
* *
* This software is copyrighted by and is the sole property of Acunia N.V. *
* and its licensors, if any. All rights, title, ownership, or other *
* interests in the software remain the property of Acunia N.V. and its *
* licensors, if any. *
* *
* This software may only be used in accordance with the corresponding *
* license agreement. Any unauthorized use, duplication, transmission, *
* distribution or disclosure of this software is expressly forbidden. *
* *
* This Copyright notice may not be removed or modified without prior *
* written consent of Acunia N.V. *
* *
* Acunia N.V. reserves the right to modify this software without notice. *
* *
* Acunia N.V. *
* Philips-site 5, box 3 info@acunia.com *
* 3001 Leuven http://www.acunia.com *
* Belgium - EUROPE *
**************************************************************************/
package com.acunia.wonka.rudolph.peers;
import java.awt.event.*;
import java.awt.*;
/*
** Scrollbar wrapper: handles existence, movement commands,events of the scrollbar.
** the main painting job is passed on tho the RectangleComponents and rectanglePainters
*/
public abstract class ScrollPainter {
/*
** static variables, to be set in constructor by the derived
*/
public final int minimumThickness;
public final int lineUpSpan;
public final int lineDnSpan;
public final int minimumScreenSpan;
/*
** basic variables for scrollbar calculations:
*/
public int barPos = 0;
public int barSpan = 10;
public int barRange = 100;
public int screenPos = 0;
public int screenSpan = 10;
public int screenRange = 100;
public int paintedScreenPos = 0;
public int lineStep = 1;
public int blockStep = 10;
public int currentActive;
/*
** basic variables for scrollbar visibility:
*/
// current bar thickness, current active field
public int currentThickness;
public int crippledSpan = -1;
/*
** (Vertical)Offset if needed:
*/
public int barOffset;
//current foreground and background color
public Color[] barColors = RudolphScrollbarPeer.getBarColors();
/*
** Constructor
*/
public ScrollPainter(int thickness, int lineup, int linedn, int box) {
minimumThickness = thickness;
lineUpSpan = lineup;
lineDnSpan = linedn;
minimumScreenSpan = box;
}
/*
** scrollbar width and scrollbar position out of (x,y) dimension for horizontal and vertical scrollbars
*/
/*
** position in scrollbar from point (x,y) for horizontal and vertical scrollbar
*/
abstract public int getPos(int x, int y);
/*
** scrollbar thickness from dimension (width, height) for horizontal and vertical scrollbar
*/
abstract public int getThickness(int width, int height);
/*
** scrollbar length and thickness to (width, height) dimension for horizontal and vertical scrollbar
*/
abstract public Dimension getSize(int scrollbarlength, int scrollbarthickness);
/*
** GetSize derived functions: minimum size, preferred size, current size in (width,height) dimension (for horizontal and vertical scrollbar)
*/
public Dimension getMinimumSize() {
return getSize(lineUpSpan+lineDnSpan+minimumScreenSpan , minimumThickness);
}
public Dimension getPreferredSize(){
return getSize(lineUpSpan+lineDnSpan+screenRange , minimumThickness);
}
public Dimension getCurrentSize() {
return getSize(lineUpSpan+lineDnSpan+screenRange , currentThickness);
}
/*
** replace <thickness> of given dimension by scrollban minimum thickness
*/
public Dimension getPreferredSize(int width, int height) {
return getSize(getPos(width, height), minimumThickness);
}
/*
** scrollbar length and screen range from dimension (width, height) for horizontal and vertical scrollbar
** if the new scrollbar <length> is too small for the lineup and linedown boxes (and the scrollbar) to be shown,
** crippledSpan is initialised so that a <crippled> scrollbar will be displayed
* /
public boolean setRange(int totalrange)
{
int totalspan;
if(totalrange>(lineUpSpan+lineDnSpan)) {
// the scrollbar is 'crippled' : soo small to house at least a line-up and a line-down box
totalrange -= lineUpSpan+lineDnSpan;
totalspan = -1;
}
else {
// Ok, normal scrollbar, continue with the calculations deper down
totalrange = -1;
totalspan = totalrange;
}
if(totalrange != screenRange || totalspan != crippledSpan) {
screenRange = totalrange;
crippledSpan = totalspan;
setScreen();
return true;
}
return false;
}
*/
public boolean setRange(int totalwidth) {
if(totalwidth<=(lineUpSpan+lineDnSpan)) {
if(totalwidth==crippledSpan){
// the scrollbar width hasn't changes
return false;
}
//else
crippledSpan = totalwidth;
return true;
}
else {
crippledSpan=-1;
totalwidth = totalwidth-lineUpSpan-lineDnSpan;
if(totalwidth==screenRange) {
// the scrollbar width hasn't changes
return false;
}
//else
screenRange=totalwidth;
setScreen();
return true;
}
}
public boolean setRange(int width, int height) {
return setRange(getPos(width, height));
}
/*
** Get /set the scrollbar thickness
*/
/*
** get the minimum scrollbar thickness
*/
public int getMinimumThickness() {
return minimumThickness;
}
/*
** get the current scrollbar thickness
*/
public int getCurrentThickness() {
return currentThickness;
}
/*
** set the current scrollbar thickness to desired value (if value smaller then minimum thickness, set to minimum)
*/
public void setThickness(int newthickness) {
currentThickness =(newthickness>minimumThickness)?newthickness:minimumThickness;
}
/*
** id as setThickness(int), but thicknes out of a given dimension for horizontal or vertical scrollbar
*/
public void setThickness(int width, int height) {
setThickness(getThickness(width, height ));
}
/*
** set the current scrollbar thickness to minimum thickness
*/
public void setMinimumThickness() {
currentThickness = minimumThickness;
}
/*
** Get /set the scrollbar offset(if needed)
*/
public void setOffset(int offset) {
barOffset = offset;
}
public int getOffset() {
return barOffset;
}
/*
** get/Set the colors
*/
public void setBarColors(Color back, Color font) {
barColors = RudolphPeer.getBarColors(back, font);
}
public void setBarColors(Color[] newcolors) {
if(newcolors.length>=RudolphPeer.COLORWIDTH)
barColors = newcolors;
}
public Color getBackground(){
return barColors[0];
}
public Color getForeground(){
return barColors[4];
}
/*
** Get scrollbar calculation values
*/
public int getBarPos() {
return barPos;
}
public int getBarSpan() {
return barSpan;
}
public int getBarRange() {
return barRange;
}
public int getScreenPos() {
return screenPos;
}
public int getScreenSpan() {
return screenSpan;
}
public int getScreenRange() {
return screenRange;
}
public int getLineStep() {
return lineStep;
}
public int getBlockStep() {
return blockStep;
}
/*
** set scrollbar calculation values: line and page increment
*/
public void setLineStep(int step) {
lineStep = step;
}
public void setBlockStep(int step) {
blockStep = step;
}
/*
** set virtual bar scrollbox position. Return true if visual position changed => redraw would get visible results
*/
public boolean setBarPos(int newpos) {
//adjust position to boundaries
if(newpos <0) {
newpos =0;
}
else if((newpos+barSpan)>barRange) {
newpos = barRange - barSpan;
}
if(newpos != barPos) {
barPos = newpos;
setScreen();
return true;
}
//else
return false;
}
/*
** set virtual bar scrollbox span. Return true if visual position changed => redraw would get visible results
*/
public boolean setBarSpan(int newspan) {
//adjust span to boundaries
if(newspan <1) {
// minimum 1 item visible
newspan =1;
}
else if(newspan>barRange) {
newspan = barRange;
}
if(newspan != barSpan) {
barSpan = newspan;
//adjust position if necessary
if((barPos+barSpan)>barRange) {
barPos = barRange - barSpan;
}
//calculate screen values
setScreen();
return true;
}
return false;
}
/*
** set virtual bar range. Return true if visual position changed => redraw would get visible results
** (this is always when the range itself is changed)
*/
public boolean setBarRange(int newrange)
{
if(newrange<1) {
newrange=1;
}
if (newrange!= barRange) {
barRange = newrange;
if(barSpan > barRange) {
barSpan = barRange;
barPos = 0;
}
else if((barPos+barSpan) > barRange) {
barPos = barRange - barSpan;
}
//if needed and desired, mirror the new values to the screen settings
setScreen();
return true;
}
return false;
}
/*
** set new virtual bar values: position, span, range.
** Return true if visual position changed => redraw would get visible results
** (this is always when the range itself is changed)
*/
public boolean setBarValues(int newpos, int newspan, int newrange) {
if(newrange<1) {
newrange=1;
}
if(newspan<1) {
newspan=1;
}
else if(newspan>newrange) {
newspan = newrange;
}
if(newpos<0) {
newpos=0;
}
else if((newpos+newspan)>newrange) {
newpos = newrange-newspan;
}
if(newrange!=barRange || newspan!=barSpan || newpos != barPos) //data changed
{
barRange = newrange;
barSpan = newspan;
barPos = newpos;
setScreen();
return true;
}
return false;
}
/*
** On the screen side, we can only resize the screen and move the scrollbar up and down
*/
/*
** resize the screen and recalculate screenPos and screenSpan to new screenRange if needed
*/
public boolean setScreenRange(int range) {
if (range <1) {
range =1;
}
if(range != screenRange) {
screenRange = range;
setScreen();
return true;
}
return false;
}
/*
** move the scrollbar (and recalculate barPos if needed)
*/
public boolean setScreenPos(int newpos) {
//adjust new position to boundaries
if(newpos<0) {
newpos = 0;
}
else if((newpos+screenSpan)>screenRange) {
newpos = screenRange - screenSpan;
}
if(screenPos != newpos) {
screenPos = newpos;
return setBar();
}
return false;
}
/*
** move up/down commands from parent
*/
public boolean lineUp() {
//return setBarPos(barPos - lineStep);
if(barPos>0) {
// still space to subtract a whole step => do so
barPos= (barPos>lineStep)? barPos-lineStep: 0;
setScreen();
return true;
}
// else
return false;
}
public boolean lineDn() {
int lastpos=barRange-barSpan;
if(barPos<=lastpos) {
barPos=((barPos+lineStep)<lastpos)? barPos+lineStep: lastpos;
setScreen();
return true;
}
// else
return false;
}
public boolean pageUp() {
if(barPos>0) {
// still space to subtract a whole step => do so
barPos= (barPos>blockStep)? barPos-blockStep: 0;
setScreen();
return true;
}
// else
return false;
}
public boolean pageDn() {
int lastpos=barRange-barSpan;
if(barPos<=lastpos) {
barPos=((barPos+blockStep)<lastpos)? barPos+blockStep: lastpos;
setScreen();
return true;
}
// else
return false;
}
/*
** basic functions : calculate (visible)screen box position, screen box length out of given bar pos,span, range and screen width
** call if: barPos, barSpan or barRange changed / screenRange changed
*/
public void setScreen() {
if(barSpan >= barRange) {
// bar covers the whole screen
barPos = 0;
barSpan = barRange;
screenPos=0;
paintedScreenPos = 0;
screenSpan = screenRange;
}
else if(( minimumScreenSpan*barRange)>(screenRange*barSpan) ) {
//extended case: the desired scrollbox width is smaller then the minimum
screenSpan = minimumScreenSpan;//(definition)
if(barPos<=0) {
screenPos=0;
}
else if(barPos>=(barRange-barSpan)) {
screenPos=screenRange-screenSpan;
}
else {
screenPos = (barPos*(screenRange-minimumScreenSpan))/(barRange-barSpan);
}
paintedScreenPos = screenPos;
}
else {
//simple case
//System.out.println("For scrollbar height "+screenRange+", barpos"+barPos+", span="+barSpan+" range="+barRange);
screenSpan = (barSpan*screenRange)/barRange;
if(barPos<=0) {
screenPos=0;
}
else if(barPos>=(barRange-barSpan)) {
screenPos=screenRange-screenSpan;
}
else {
screenPos = (barPos*screenRange)/barRange;
}
paintedScreenPos = screenPos;
//System.out.println("..... found screen pos="+screenPos+", span="+screenSpan);
}
}
/*
** basic functions : calculate bar position and visible screen position out of given screen position
** @returns: true if visible screen position changed (redraw will show an effect)
** call if: screenPos changed
*/
public boolean setBar() {
if(screenPos<0) {
screenPos=0;
if(barPos>0) {
barPos = 0;
paintedScreenPos=0;
return true;
}
}
else if((screenPos+ screenSpan) >= screenRange) {
barPos = barRange-barSpan;
screenPos = screenRange - screenSpan;
if(paintedScreenPos != screenPos) {
paintedScreenPos=screenPos;
return true;
}
}
else if(( minimumScreenSpan*barRange)>(screenRange*barSpan) ) {
//extended case: the desired scrollbox width is smaller then the minimum
int newpos = screenPos * (barRange-barSpan) / (screenRange - minimumScreenSpan);
if(newpos != barPos) {
//new values for bar and visible screen
barPos = newpos;
paintedScreenPos = (newpos * (screenRange-minimumScreenSpan))/(barRange-barSpan);
return true;
}
}
else {
//simple case
int newpos = screenPos * barRange/screenRange;
if(newpos != barPos) {
//new values for bar and visible screen
barPos = newpos;
paintedScreenPos = (newpos * screenRange)/barRange;
return true;
}
}
return false;
}
/*
** basic functions : move screen box position and calculate bar position /visible screen position for new value
** return true if visible screen position changed (redraw will show an effect)
** (this function is equivalent to <screenpos+=dl; + setBar();> trimmed into one)
*/
public boolean moveBar(int dl) {
if((screenPos+dl)<0) {
screenPos=0;
if(barPos>0) {
barPos = 0;
paintedScreenPos=0;
return true;
}
}
else if((screenPos+dl+screenSpan) >= screenRange) {
barPos = barRange-barSpan;
screenPos = screenRange - screenSpan;
if(paintedScreenPos != screenPos) {
paintedScreenPos=screenPos;
return true;
}
}
else if(( minimumScreenSpan*barRange)>(screenRange*barSpan) )//extended case: the desired scrollbox width is smaller then the minimum
{
screenPos += dl;
int newpos = screenPos * (barRange-barSpan) / (screenRange - minimumScreenSpan);
if(newpos != barPos) {
//new values for bar and visible screen
barPos = newpos;
paintedScreenPos = (newpos * (screenRange-minimumScreenSpan))/(barRange-barSpan);
return true;
}
}
else {
//simple case
screenPos += dl;
int newpos = screenPos * barRange/screenRange;
if(newpos != barPos) {
//new values for bar and visible screen
barPos = newpos;
paintedScreenPos = (newpos * screenRange)/barRange;
return true;
}
}
return false;
}
/*
** Idem for non-select screen position (replace by subclas specific as soon as we know wether getPos(dx, dy)=x or getPos(dx, dy)=y
*/
public boolean moveScreenPos(int dx, int dy) {
return moveBar(getPos(dx, dy) );
}
/*
** Get set active part of screen
** as mouse events and scroll thread can try to access the currentActive value at the same time,
** all Active functions have to be synchronised
*/
public synchronized int getActive(){
return currentActive;
}
public synchronized void setNoSelected() {
currentActive = RudolphScrollbarPeer.FIELD_NONESELECTED;
}
public synchronized boolean isNoSelected() {
return(currentActive<0);
}
public synchronized boolean isSelected() {
return(currentActive>=0);
}
/*
** Scrollbar click functions for x,y locations:
** THESE FUNCTIONS USE getField() => REPLACE BY OVERWRITTEN getPos(x,y)=x OR getPos(x,y)=y FOR ALL HORIZONTAL AND VERTICAL SCROLLBARS
*/
public int getField(int x, int y) {
return getField(getPos(x,y));
}
public synchronized int setActive(int x, int y) {
currentActive = getField(getPos(x,y));
return currentActive;
}
/*
** Find the 'field' of the scrollbar in which the given x,y point is located. This is a basic function for clicking the scrollbar
** in any base class using this painter
*/
public int getField(int pos) {
int field = RudolphScrollbarPeer.FIELD_NONESELECTED;
if(crippledSpan>0 && pos>=0 && pos <= crippledSpan) {
// crippled scrollbar: there are only two possibilities: either UNIT_DECREMENT when in upper half or UNIT_INCREMENT in lower
field = (pos<crippledSpan/2)?AdjustmentEvent.UNIT_DECREMENT:AdjustmentEvent.UNIT_INCREMENT;
}
else if(pos>=0 && pos<=(lineUpSpan+screenRange+lineDnSpan) ) {
// the point is either in one of the line-up/line down blocks,in the scrollbox or in the area above or under the box
if(pos<=lineUpSpan) {
// point in upper (line-up) block
field = AdjustmentEvent.UNIT_DECREMENT;
}
else if(pos<(lineUpSpan + screenPos)) {
// point between line-up block and scrollbox
field = AdjustmentEvent.BLOCK_DECREMENT;
}
else if(pos<=(lineUpSpan + screenPos + screenSpan)) {
//point in scrollbox
field = AdjustmentEvent.TRACK;
}
else if(pos<(lineUpSpan + screenRange)) {
// point between scrollbox and lower line box
field = AdjustmentEvent.BLOCK_INCREMENT;
}
else {
//point in lower (line-lown)box
// if(pos>=(lineUpSpan + screenRange))
field = AdjustmentEvent.UNIT_INCREMENT;
}
}
return field;
}
/*
** paint command
*/
abstract public void paint(Graphics g);
/*
** Debugging
*/
public String toString() {
String param = "ScrollPainter: virtual bar <pos = "+barPos+", span = "+barSpan+", range = "+barRange+">";
param += "screen <pos = "+screenPos+", span = "+screenSpan+", range = "+screenRange+"> ";
param += "increment <unit = "+lineStep+",block = "+blockStep+">";
param += "current field <"+currentActive+">";
return param;
}
public String paramString() {
String param = "ScrollPainter:bar<pos"+barPos+",span"+barSpan+",range"+barRange+">";
param += "screen<pos"+screenPos+",span"+screenSpan+",range"+screenRange+">";
param += "increment<unit"+lineStep+",block"+blockStep+">";
param += "currentActive:"+currentActive;
return param;
}
}