/*******************************************************************************
* Copyright (c)                                                                *
*           2005   Tristan Allwood,                                            *
*           2005   Daniel Burke,                                               *
*           2005   Marc Hull,                                                  *
*           2005   Ekaterina Itskova,                                          *
*           2005   Steve Zymler                                                *
*                                                                              *
* Permission is hereby granted, free of charge, to any person obtaining a      *
* copy of this software and associated documentation files (the                *
* "Software"), to deal in the Software without restriction, including          *
* without limitation the rights to use, copy, modify, merge, publish,          *
* distribute, sublicense, and/or sell copies of the Software, and to           *
* permit persons to whom the Software is furnished to do so, subject to        *
* the following conditions:                                                    *
*                                                                              *
* The above copyright notice and this permission notice shall be included      *
* in all copies or substantial portions of the Software.                       *
*                                                                              *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS      *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF                   *
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.       *
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY         *
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,         *
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE            *
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                       *
*******************************************************************************/
/*
 * Created on 14-Nov-2004
 *
 */
package uk.ac.ic.doc.kevlar.gui.internal.widgets.scrollbars;

import java.io.FileNotFoundException;

import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Display;

import uk.ac.ic.doc.kevlar.gui.internal.AMouseListenerObject;
import uk.ac.ic.doc.kevlar.gui.internal.caches.ImageCache;
import uk.ac.ic.doc.kevlar.gui.internal.widgets.IScrollingWindow;

/**
 * @author Marc
 **/
public abstract class AScrollbar extends AMouseListenerObject {

    public static final int SCROLLBAR_SIZE = 17;
    public static final String SCROLL_BAR_BACKGROUND_IMAGE = "semitransparent.png";
    
    protected AScrollDecrementButton button1;
    protected AScrollIncrementButton button2;
    protected AScrollbarSlider slider;
    protected IScrollingWindow window;
    protected int value;
    protected int size;
    protected int max;
    protected int increment;
    protected Image background;
        
    public AScrollbar(IScrollingWindow window) {
        
        this.window = window;
        
        try {
        
            this.background = ImageCache.get(SCROLL_BAR_BACKGROUND_IMAGE);
            
        } catch (FileNotFoundException e) {
            
            System.err.println("File not found: "+SCROLL_BAR_BACKGROUND_IMAGE);
            this.background = new Image(Display.getDefault(), 1, 1);
            
        }
        
    }
    
    public boolean isUsingFullSpace()
    {
    	return size >= max;
    }
    
    public void updateSlider() {
        
        int availableSpace = getSpace();
        double barSize = 0;
        double position = 0;
                
        if (size >= max) {
            
            barSize = availableSpace;
            
        } else {
        
            barSize = size*(double)availableSpace/max;
            
        }
        
        if (max-size <= 0) {
            
            position = 0;
            
        } else {
        
            position = ((double)value/(max-size))*(availableSpace-barSize);
            
        }
        
/*        slider.setPosition(new Point((int)Math.round(19+position), 0));
        slider.setSize(new Point((int)Math.round(barSize), Scrollbar.SCROLLBAR_SIZE)); */
        slider.setPosition((int)Math.round(SCROLLBAR_SIZE+position));
        slider.setSize((int)Math.round(barSize));
        slider.redraw();
        
    }
        
    public void setSize(int size) {

        this.size = size;
        
    }
    
    public void setMaximum(int max) {
        
        if (this.max != max) {
        
            this.max = max;
            
            if (value > (max-size)) {
                
                value = max-size;
                
                if (value < 0) {
                    
                    value = 0;
                    
                }
                
                updateWindow();
                
            }
            
            updateSlider();
            
        }
        
    }
    
    public void setIncrement(int increment) {
        
        this.increment = increment;
        
    }
    
    public void increment() {
     
        if (value < (max-size)) {
        
            if (value+increment < (max-size)) {
            
                value += increment;
                
            } else {
            
                value = max-size;
                
                if (value < 0) {
                    
                    value = 0;
                    
                }
                
            }
            
            updateWindow();
            updateSlider();
            
        }
        
    }
    
    public void decrement() {
        
        if (value > 0) {
        
            if (value-increment > 0) {
            
                value -= increment;
                
            } else {
            
                value = 0;
                
            }
            
            updateWindow();
            updateSlider();
            
        }
        
    }

    public void moveBy(int amount) {
        
        if (value+amount > 0) {
            
            if (value+amount < max-size) {
                
                value += amount;
                
            } else {
                
                value = max-size;
                
                if (value < 0) {
                    
                    value = 0;
                    
                }
                
            }
            
        } else {
            
            value = 0;
            
        }
        
        updateWindow();
        updateSlider();
        
    }
    
    public void setValue(int newValue) {
        
        if (newValue < 0) {
            
            value = 0;
            
        } else if (newValue+size > max) {
            
            value = max-size;
            
        } else {
            
            value = newValue;
            
        }
        
        updateWindow();
        updateSlider();
        
    }
    
    public void parentResized(Point size) {
        
        super.parentResized(size);
        updateSlider();
        
    }
    
    public void drawBefore(GC gc, Rectangle redrawArea) {
        
        Rectangle imgBounds = background.getBounds();
        gc.drawImage(background, 0, 0, imgBounds.width, imgBounds.height, redrawArea.x, redrawArea.y, redrawArea.width, redrawArea.height);
        
    }
    
    public int scrollbarValueToRealValue(int scrollbarValue) {
        
        int availableSpace = getSpace();
        double barSize = 0;
                
        if (size >= max) {
            
            barSize = availableSpace;
            
        } else {
        
            barSize = size*(double)availableSpace/max;
            
        }
        
        if (max-size <= 0) {
            
            return 0;
            
        } else {
        
            return (int)(((double)scrollbarValue/(max-size))*(availableSpace-barSize));
            
        }
        
    }
    
    public int realValueToScrollbarValue(int realValue) {
        
        int availableSpace = getSpace();
        double barSize = 0;
                
        if (size >= max) {
            
            barSize = availableSpace;
            
        } else {
        
            barSize = size*(double)availableSpace/max;
            
        }
        
//        return (int)(realValue*(max-size)/(availableSpace-barSize)-barSize/2);        
        return (int)(realValue*(max-size)/(availableSpace-barSize));        
        
    }
    
    public abstract void updateWindow();
    public abstract void updateFromWindow();
    public abstract int getSpace();
    
}
