package fr.umlv.uidemo.slider;

import java.awt.BorderLayout;
import java.text.*;
import java.util.*;

import javax.swing.*;
import javax.swing.event.*;

/**
 * @author Remi Forax
 *
 */
public class DateSliderExample {

  static class DateModel {
    public DateModel(Date date) {
      this.time=date.getTime();
    }
    
    public long getTime() {
      return time;
    }

    public void setTime(long time) {
      this.time=time;
      fireStateChanged();
    }
    
    public void addChangeListener(ChangeListener l) {
      list.add(l);
    }

    public void removeChangeListener(ChangeListener l) {
      list.remove(l);
    }
    
    protected void fireStateChanged() {
      ChangeEvent event=new ChangeEvent(this);
      for(int i=list.size();--i>=0;)
        ((ChangeListener)list.get(i)).stateChanged(event);
    }
    
    private long time;
    private ArrayList list=new ArrayList();
  }
  
  static class SliderDateModel implements BoundedRangeModel {
    public SliderDateModel(DateModel model,int calendarField) {
      this.model=model;
      this.calendarField=calendarField;
    }
    
    public int getExtent() {
      int value=getValue();
      return (value==getMinimum() || value==getMaximum())?0:1;
    }

    public int getMaximum() {
      calendar.setTimeInMillis(model.getTime());
      return calendar.getActualMaximum(calendarField);
    }

    public int getMinimum() {
      calendar.setTimeInMillis(model.getTime());
      return calendar.getActualMinimum(calendarField);
    }

    public int getValue() {
      calendar.setTimeInMillis(model.getTime());
      return calendar.get(calendarField);
    }

    public boolean getValueIsAdjusting() {
      return valueIsAdjusting;
    }

    public void setExtent(int newExtent) {
      throw new UnsupportedOperationException();
    }

    public void setMaximum(int newMaximum) {
      throw new UnsupportedOperationException();
    }

    public void setMinimum(int newMinimum) {
      throw new UnsupportedOperationException();
    }

    public void setValue(int newValue) {
      calendar.setTimeInMillis(model.getTime());
      calendar.set(calendarField,newValue);
      model.setTime(calendar.getTimeInMillis());
    }

    public void setRangeProperties(int value, int extent, int min, int max, boolean adjusting) {
      throw new UnsupportedOperationException();
    }

    public void setValueIsAdjusting(boolean valueIsAdjusting) {
      this.valueIsAdjusting=valueIsAdjusting;
    }

    public void addChangeListener(ChangeListener l) {
      model.addChangeListener(l);
    }

    public void removeChangeListener(ChangeListener l) {
      model.addChangeListener(l);
    }
    
    private boolean valueIsAdjusting;
    private int calendarField;
    private final DateModel model;
    private final transient Calendar calendar=Calendar.getInstance();
  }

  static class DateView extends JLabel {
    public DateView(final DateModel model) {
      model.addChangeListener(new ChangeListener() {
        public void stateChanged(ChangeEvent e) {
          setText(model);
        }
      });
      setText(model);
    }
    
    void setText(DateModel model) {
      setText(format.format(new Date(model.getTime())));
    }
    
    private final DateFormat format=DateFormat.getDateTimeInstance(DateFormat.FULL,DateFormat.SHORT);
  }

  private static JPanel createPanel(DateModel model,int calendarField,String title,String[] labels) {
    
    final SliderDateModel sliderModel=new SliderDateModel(model,calendarField);
    
    final JSlider slider=new JSlider(sliderModel);
    slider.setPaintTicks(true);
    slider.setSnapToTicks(true);
    
    if (labels!=null) {
      Hashtable table=new Hashtable();
      for(int i=0;i<labels.length;i++)
        table.put(new Integer(i),new JLabel(labels[i]));
      slider.setLabelTable(table);
    }
    slider.setPaintLabels(true);
    
    slider.setMajorTickSpacing(1);
      
    JPanel panel=new JPanel(new BorderLayout());
    panel.setBorder(BorderFactory.createTitledBorder(title));
    panel.add(slider);
    return panel;
  }

  public static void main(String[] args) {
    int[] fields=new int[] {
      Calendar.DAY_OF_MONTH, Calendar.DAY_OF_YEAR, Calendar.DAY_OF_WEEK,
      Calendar.AM_PM,Calendar.HOUR,Calendar.HOUR_OF_DAY
    };
    
    String[] titles=new String[] {
      "DAY_OF_MONTH", "DAY_OF_YEAR",  "DAY_OF_WEEK",
      "AM_PM",        "HOUR",          "HOUR_OF_DAY"
    };
    
    DateFormatSymbols symbols=new DateFormatSymbols();
    String[][] labels=new String[][] {
      null, null, symbols.getShortWeekdays(),
      symbols.getAmPmStrings(), null,  null
    };
    
    Date date=new Date();
    DateModel model=new DateModel(date);
    
    JPanel panel=new JPanel(null);
    panel.setLayout(new BoxLayout(panel,BoxLayout.Y_AXIS));
    panel.add(new DateView(model));
    for(int i=0;i<fields.length;i++) {
      panel.add(createPanel(model,fields[i],titles[i],labels[i]));
    }
    
    JFrame frame=new JFrame();
    frame.setContentPane(panel);
    frame.pack();
    frame.show();
  }
}
