package de.javasoft.synthetica.democenter.examples.datecombobox;

import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;

import org.jdesktop.swingx.JXMonthView;
import org.jdesktop.swingx.decorator.ColorHighlighter;
import org.jdesktop.swingx.decorator.ComponentAdapter;
import org.jdesktop.swingx.decorator.CompoundHighlighter;
import org.jdesktop.swingx.decorator.HighlightPredicate;
import org.jdesktop.swingx.decorator.Highlighter;
import org.jdesktop.swingx.plaf.basic.CalendarRenderingHandler;
import org.jdesktop.swingx.plaf.basic.CalendarState;
import org.jdesktop.swingx.plaf.basic.PublicCalendarRenderingHandler;
import org.jdesktop.swingx.plaf.basic.PublicCalendarRenderingHandler.MonthViewCalendarAdapter;

import de.javasoft.plaf.synthetica.MonthViewUI;
import de.javasoft.swing.DateComboBox;
import de.javasoft.swing.plaf.datecombobox.DateComboBoxMonthView;
import de.javasoft.swing.plaf.datecombobox.DateComboBoxPopup;
import de.javasoft.swing.plaf.datecombobox.DateComboBoxUI;
import de.javasoft.synthetica.addons.highlighter.ColorTextHighlighter;

/**
 * A DateComboBox application used to demonstrate the use of highlighters.<brx>
 * Note: requires SwingX 1.6.5 from the SyntheticaAddons package
 */
@SuppressWarnings("serial")
public class HighlighterDateComboBox extends JFrame
{
  public HighlighterDateComboBox()
  {
    super("HighlighterDateComboBox");
    
    //create and add the combobox panel and its components
    JPanel panel = new JPanel();
    createAndAddComponents(panel);
    add(panel);

    //setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);      
    setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    pack();
    setLocationRelativeTo(null);        //center
    setVisible(true);
  }

  private void createAndAddComponents(JPanel panel)
  {
    panel.setLayout(new GridBagLayout());    
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.gridx = 0;
    gbc.gridy = 0;
    gbc.gridwidth = 1;
    gbc.gridheight = 1;
    gbc.weightx = 1.0;
    gbc.insets = new Insets(5,5,5,5);
    gbc.fill = GridBagConstraints.HORIZONTAL;

    gbc.gridx = 0;
    gbc.gridy = 0;
    panel.add(new JLabel("Highlighter DateComboBox"), gbc);
    gbc.gridx = 1;
//@highlight
    DateComboBox dateCombo = new HighlighterDateCombo();
    dateCombo.setDateFormat(new SimpleDateFormat("MM/dd/yyyy"));
    panel.add(dateCombo, gbc);
//@/highlight

    panel.setBorder(new EmptyBorder(10,10,200,10));    
  }

  private static class HighlighterDateCombo extends DateComboBox
  {
    @Override
    public void updateUI()
    {
      if (getPopup() != null)
        getPopup().updateUI();
      setUI(new DateComboBoxUI(){
        @Override
        protected DateComboBoxPopup createDateComboBoxPopup(DateComboBox combo)
        {
          return new DateComboBoxPopup(combo){
            @Override
            protected DateComboBoxMonthView createMonthView(DateComboBox dateComboBox)
            {
              DateComboBoxMonthView monthView = new DateComboBoxMonthView(dateComboBox, this){
                @Override
                public void updateUI() 
                {
                  setUI(new MonthViewUI(){
                    @Override
                    protected CalendarRenderingHandler createRenderingHandler()
                    {                      
//@highlight
                      //install highlighters
                      PublicCalendarRenderingHandler renderer = new PublicCalendarRenderingHandler();
                      renderer.setHighlighters(createHighlighter());                        
                      return renderer;
//@/highlight
                    }
                  });
                }
              };
              configurMonthView(monthView);
              return monthView;
            }
          };
        }
      });
    }
    
    private Highlighter createHighlighter()
    {
      CompoundHighlighter highlighter = new CompoundHighlighter();

//@highlight
      //set unselectable date foreground equal to leadingDayForeground
      HighlightPredicate unselectable = new HighlightPredicate()
      {
        public boolean isHighlighted(Component renderer, ComponentAdapter adapter)
        {
          if (!(adapter instanceof MonthViewCalendarAdapter))
            return false;
          return ((MonthViewCalendarAdapter) adapter).isUnselectable();
        }
      };
      //transparent background color disables the red cross default
      ColorTextHighlighter unselectableHL = new ColorTextHighlighter(unselectable, new Color(0,0,0,0), UIManager.getColor("JXMonthView.leadingDayForeground")); //see MonthViewAddon    
      highlighter.addHighlighter(unselectableHL);
//@/highlight
      
      /*HighlightPredicate weekend = new HighlightPredicate()
      {
        public boolean isHighlighted(Component renderer, ComponentAdapter adapter)
        {
          if (!(adapter instanceof MonthViewCalendarAdapter))
            return false;
          return ((MonthViewCalendarAdapter) adapter).isWeekend();
        }
      };
      ColorTextHighlighter weekendHL = new ColorTextHighlighter(weekend, Color.CYAN, null);
      highlighter.addHighlighter(weekendHL);*/
      
//@highlight
      // flagged style - white on red
      HighlightPredicate flagged = new HighlightPredicate()
      {
        public boolean isHighlighted(Component renderer, ComponentAdapter adapter)
        {
          if (!(adapter instanceof MonthViewCalendarAdapter) || CalendarState.IN_MONTH != ((MonthViewCalendarAdapter)adapter).getCalendarState())
            return false;
          return ((MonthViewCalendarAdapter) adapter).isFlagged();
        }
      };
      //ColorTextHighlighter flaggedHL = new ColorTextHighlighter(flagged, Color.RED, Color.WHITE);
      ColorTextHighlighter flaggedHL = new ColorTextHighlighter(flagged, Color.RED, Color.WHITE, Color.RED, Color.WHITE);
      highlighter.addHighlighter(flaggedHL);
//@/highlight
      
//@highlight
      // marked style - mark some special dates with white on green
      HighlightPredicate marked = new HighlightPredicate()
      {
        public boolean isHighlighted(Component renderer, ComponentAdapter adapter)
        {
          if (!(adapter instanceof MonthViewCalendarAdapter) || CalendarState.IN_MONTH != ((MonthViewCalendarAdapter)adapter).getCalendarState())
            return false;
          Calendar cal = Calendar.getInstance();
          cal = Calendar.getInstance();
          cal.set(Calendar.DAY_OF_MONTH, 20);
          cal.set(Calendar.HOUR, 0);
          cal.set(Calendar.MINUTE, 0);
          cal.set(Calendar.SECOND, 0);
          cal.set(Calendar.MILLISECOND, 0);        
          cal.set(Calendar.AM_PM, Calendar.AM);
          Calendar cal2 = (Calendar)cal.clone();
          cal2.set(Calendar.DAY_OF_MONTH, 22);
          Date d = ((MonthViewCalendarAdapter) adapter).getCalendar().getTime(); 
          return d.equals(cal.getTime()) || d.equals(cal2.getTime());
        }
      };
      //ColorTextHighlighter markedHL = new ColorTextHighlighter(marked, new Color(0x00AA00), Color.WHITE);
      ColorTextHighlighter markedHL = new ColorTextHighlighter(marked, new Color(0x00AA00), Color.WHITE, new Color(0x00AA00), Color.WHITE);
      highlighter.addHighlighter(markedHL);
//@/highlight

//@highlight
      // use gray foreground for week of year
      HighlightPredicate week = new HighlightPredicate()
      {
        public boolean isHighlighted(Component renderer, ComponentAdapter adapter)
        {
          return (adapter instanceof MonthViewCalendarAdapter && CalendarState.WEEK_OF_YEAR == ((MonthViewCalendarAdapter)adapter).getCalendarState()) ? true : false;
        }
      };
      ColorHighlighter weekHL = new ColorHighlighter(week, null, Color.LIGHT_GRAY);
      highlighter.addHighlighter(weekHL);
//@/highlight
      
      //foreground setting - see CalendarCellContext#getSelectionForeground(), CalendarCellContext#getForeground(), DefaultVisuals#configureColors()
      return highlighter;
    }  
    
    private void configurMonthView(JXMonthView mv)
    {
      // dates in the past are unselectable
      /*mv.setSelectionModel(new DefaultDateSelectionModel(){
        @Override
        public boolean isUnselectableDate(Date date)
        {
          Calendar cal = Calendar.getInstance();
          cal.setTime(date);
          Calendar now = Calendar.getInstance();
          now.set(Calendar.HOUR, 0);
          now.set(Calendar.MINUTE, 0);
          now.set(Calendar.SECOND, 0);
          now.set(Calendar.MILLISECOND, 0);
          now.set(Calendar.AM_PM, Calendar.AM);
          return cal.before(now);
        }
      });*/
      
      // specify some unselectable dates
      Calendar cal = Calendar.getInstance();
      cal.set(Calendar.DAY_OF_MONTH, 2);
      Calendar cal2 = Calendar.getInstance();
      cal2.set(Calendar.DAY_OF_MONTH, 3);
      Calendar cal3 = Calendar.getInstance();
      cal3.set(Calendar.DAY_OF_MONTH, 4);
      mv.setUnselectableDates(cal.getTime(), cal2.getTime(), cal3.getTime());

      // create some dates that we want to flag as being important
      Calendar cal4 = Calendar.getInstance();
      cal4.set(Calendar.DAY_OF_MONTH, 1);
      Calendar cal5 = Calendar.getInstance();
      cal5.set(Calendar.DAY_OF_MONTH, 14);
      Calendar cal6 = Calendar.getInstance();
      cal6.set(Calendar.DAY_OF_MONTH, 16);
      mv.setFlaggedDates(cal4.getTime(), cal5.getTime(), cal6.getTime());    
         
      mv.setTraversable(true);
      mv.setShowingLeadingDays(true);
      mv.setShowingTrailingDays(true);
      mv.setShowingWeekNumber(true);
      // display year within header
      mv.setZoomable(true);      
      mv.setDayForeground(Calendar.SATURDAY, new Color(0xE04020));
      mv.setDayForeground(Calendar.SUNDAY, new Color(0xE04020));      
    }    
  }  
  
  /**
   * Static main method for application startup. 
   */
  public static void main(String[] args)
  {
    EventQueue.invokeLater(new Runnable()
    {
      public void run()
      {
        try
        {
          UIManager.setLookAndFeel("de.javasoft.plaf.synthetica.SyntheticaStandardLookAndFeel");
          new HighlighterDateComboBox();
        }
        catch (Exception e)
        {
          e.printStackTrace();
        }
      }
    });
  }  
}
