package org.simtk.isimsu;

import java.awt.Graphics;
import java.awt.Rectangle;
import java.util.Set;
import javax.swing.JSlider;
import javax.swing.plaf.basic.BasicSliderUI;
import javax.swing.plaf.metal.MetalSliderUI;
import com.sun.java.swing.plaf.windows.WindowsSliderUI;

public class NativeTickedSlider {
	public static void setNativeTickUI(JSlider slider) {
        // Try to make a slider that can show custom tick labels, but
        // which is not a lowest-common-denominator UI
        if (slider.getUI().getClass().equals(MetalSliderUI.class)) {
            slider.setUI(new CustomTickMetalSliderUI());
        }
        else if (slider.getUI().getClass().equals(BasicSliderUI.class)) {
            slider.setUI(new CustomTickBasicSliderUI(slider));
        }
        else if (slider.getUI().getClass().equals(WindowsSliderUI.class)) {
            slider.setUI(new CustomTickWindowsSliderUI(slider));
        }
        else {
        	System.out.println("Unknown SliderUI Class: "+slider.getUI().getClass());
        }
            

	}	
}

class CustomTickMetalSliderUI extends MetalSliderUI
implements CustomTickSliderUI
{
    protected Set<Integer> majorTickPositions;
    protected Set<Integer> minorTickPositions;
    
    public void setMajorTickPositions(Set<Integer> tickPositions){
        majorTickPositions = tickPositions;
    }
    public void setMinorTickPositions(Set<Integer> tickPositions) {
        minorTickPositions = tickPositions;
    }
    
    public void paintTicks(Graphics g) {
        super.paintTicks(g);
        
        boolean haveCustomMajorTicks = false;
        if ( (majorTickPositions != null) && (majorTickPositions.size() > 0) )
            haveCustomMajorTicks = true;

        boolean haveCustomMinorTicks = false;
        if ( (minorTickPositions != null) && (minorTickPositions.size() > 0) )
            haveCustomMinorTicks = true;
        
        boolean haveCustomTicks = (haveCustomMajorTicks || haveCustomMinorTicks);

        if (haveCustomMajorTicks) {
            for (int value : majorTickPositions) {
                paintMajorTick(g, value);
            }
        }
        if (haveCustomMinorTicks) {
            for (int value : minorTickPositions) {
                paintMinorTick(g, value);
            }
        }
    }
    
    public void paintMajorTick(Graphics g, int value) {
        Rectangle tickBounds = tickRect;

        // TODO - what if slider is vertical?
        if (slider.getOrientation() == JSlider.HORIZONTAL) {
            g.translate(0, tickBounds.y);
            int xPos = xPositionForValue(value);
            paintMajorTickForHorizSlider(g, tickBounds, xPos);
            g.translate(0, -tickBounds.y);
        }
        else if (slider.getOrientation() == JSlider.VERTICAL) {
            g.translate(tickBounds.x, 0);
            int yPos = yPositionForValue(value);
            paintMajorTickForHorizSlider(g, tickBounds, yPos);
            g.translate(-tickBounds.x, 0);
        }
    }

    public void paintMinorTick(Graphics g, int value) {
        Rectangle tickBounds = tickRect;

        if (slider.getOrientation() == JSlider.HORIZONTAL) {
            g.translate(0, tickBounds.y);
            int xPos = xPositionForValue(value);
            paintMinorTickForHorizSlider(g, tickBounds, xPos);
            g.translate(0, -tickBounds.y);
        }
        else if (slider.getOrientation() == JSlider.VERTICAL) {
            g.translate(tickBounds.x, 0);
            int yPos = yPositionForValue(value);
            paintMinorTickForHorizSlider(g, tickBounds, yPos);
            g.translate(-tickBounds.x, 0);
        }
    }
}

class CustomTickBasicSliderUI extends BasicSliderUI
implements CustomTickSliderUI
{
    protected Set<Integer> majorTickPositions;
    protected Set<Integer> minorTickPositions;
    
    public CustomTickBasicSliderUI(JSlider slider) {
        super(slider);
    }
    
    public void setMajorTickPositions(Set<Integer> tickPositions){
        majorTickPositions = tickPositions;
    }
    public void setMinorTickPositions(Set<Integer> tickPositions) {
        minorTickPositions = tickPositions;
    }
    
    public void paintTicks(Graphics g) {
        super.paintTicks(g);
        
        boolean haveCustomMajorTicks = false;
        if ( (majorTickPositions != null) && (majorTickPositions.size() > 0) )
            haveCustomMajorTicks = true;

        boolean haveCustomMinorTicks = false;
        if ( (minorTickPositions != null) && (minorTickPositions.size() > 0) )
            haveCustomMinorTicks = true;
        
        boolean haveCustomTicks = (haveCustomMajorTicks || haveCustomMinorTicks);

        if (haveCustomMajorTicks) {
            for (int value : majorTickPositions) {
                paintMajorTick(g, value);
            }
        }
        if (haveCustomMinorTicks) {
            for (int value : minorTickPositions) {
                paintMinorTick(g, value);
            }
        }
    }
    
    public void paintMajorTick(Graphics g, int value) {
        Rectangle tickBounds = tickRect;

        // TODO - what if slider is vertical?
        if (slider.getOrientation() == JSlider.HORIZONTAL) {
            g.translate(0, tickBounds.y);
            int xPos = xPositionForValue(value);
            paintMajorTickForHorizSlider(g, tickBounds, xPos);
            g.translate(0, -tickBounds.y);
        }
        else if (slider.getOrientation() == JSlider.VERTICAL) {
            g.translate(tickBounds.x, 0);
            int yPos = yPositionForValue(value);
            paintMajorTickForHorizSlider(g, tickBounds, yPos);
            g.translate(-tickBounds.x, 0);
        }
    }

    public void paintMinorTick(Graphics g, int value) {
        Rectangle tickBounds = tickRect;

        if (slider.getOrientation() == JSlider.HORIZONTAL) {
            g.translate(0, tickBounds.y);
            int xPos = xPositionForValue(value);
            paintMinorTickForHorizSlider(g, tickBounds, xPos);
            g.translate(0, -tickBounds.y);
        }
        else if (slider.getOrientation() == JSlider.VERTICAL) {
            g.translate(tickBounds.x, 0);
            int yPos = yPositionForValue(value);
            paintMinorTickForHorizSlider(g, tickBounds, yPos);
            g.translate(-tickBounds.x, 0);
        }
    }
}
    
class CustomTickWindowsSliderUI extends WindowsSliderUI
implements CustomTickSliderUI
{
    CustomTickWindowsSliderUI(JSlider slider) {
        super(slider);
    }
    
    protected Set<Integer> majorTickPositions;
    protected Set<Integer> minorTickPositions;
    
    public void setMajorTickPositions(Set<Integer> tickPositions){
        majorTickPositions = tickPositions;
    }
    public void setMinorTickPositions(Set<Integer> tickPositions) {
        minorTickPositions = tickPositions;
    }
    
    public void paintTicks(Graphics g) {
        super.paintTicks(g);
        
        boolean haveCustomMajorTicks = false;
        if ( (majorTickPositions != null) && (majorTickPositions.size() > 0) )
            haveCustomMajorTicks = true;

        boolean haveCustomMinorTicks = false;
        if ( (minorTickPositions != null) && (minorTickPositions.size() > 0) )
            haveCustomMinorTicks = true;
        
        boolean haveCustomTicks = (haveCustomMajorTicks || haveCustomMinorTicks);

        if (haveCustomMajorTicks) {
            for (int value : majorTickPositions) {
                paintMajorTick(g, value);
            }
        }
        if (haveCustomMinorTicks) {
            for (int value : minorTickPositions) {
                paintMinorTick(g, value);
            }
        }
    }
    
    public void paintMajorTick(Graphics g, int value) {
        Rectangle tickBounds = tickRect;

        // TODO - what if slider is vertical?
        if (slider.getOrientation() == JSlider.HORIZONTAL) {
            g.translate(0, tickBounds.y);
            int xPos = xPositionForValue(value);
            paintMajorTickForHorizSlider(g, tickBounds, xPos);
            g.translate(0, -tickBounds.y);
        }
        else if (slider.getOrientation() == JSlider.VERTICAL) {
            g.translate(tickBounds.x, 0);
            int yPos = yPositionForValue(value);
            paintMajorTickForHorizSlider(g, tickBounds, yPos);
            g.translate(-tickBounds.x, 0);
        }
    }

    public void paintMinorTick(Graphics g, int value) {
        Rectangle tickBounds = tickRect;

        if (slider.getOrientation() == JSlider.HORIZONTAL) {
            g.translate(0, tickBounds.y);
            int xPos = xPositionForValue(value);
            paintMinorTickForHorizSlider(g, tickBounds, xPos);
            g.translate(0, -tickBounds.y);
        }
        else if (slider.getOrientation() == JSlider.VERTICAL) {
            g.translate(tickBounds.x, 0);
            int yPos = yPositionForValue(value);
            paintMinorTickForHorizSlider(g, tickBounds, yPos);
            g.translate(-tickBounds.x, 0);
        }
    }
}
