package calendar;

import org.gnu.gtk.Button;
import org.gnu.gtk.ButtonBoxStyle;
import org.gnu.gtk.Calendar;
import org.gnu.gtk.CalendarDisplayOptions;
import org.gnu.gtk.CheckButton;
import org.gnu.gtk.FontSelectionDialog;
import org.gnu.gtk.Frame;
import org.gnu.gtk.Gtk;
import org.gnu.gtk.HBox;
import org.gnu.gtk.HButtonBox;
import org.gnu.gtk.Label;
import org.gnu.gtk.VBox;
import org.gnu.gtk.VSeparator;
import org.gnu.gtk.Window;
import org.gnu.gtk.WindowType;
import org.gnu.gtk.event.ButtonEvent;
import org.gnu.gtk.event.ButtonListener;
import org.gnu.gtk.event.CalendarEvent;
import org.gnu.gtk.event.CalendarListener;
import org.gnu.gtk.event.LifeCycleEvent;
import org.gnu.gtk.event.LifeCycleListener;
import org.gnu.gtk.event.ToggleEvent;
import org.gnu.gtk.event.ToggleListener;
import org.gnu.gtk.GtkStockItem;
import org.gnu.pango.FontDescription;

public class CalendarExample {

    private String flags[] = { "Show Heading", "Show Day Names",
            "No Month Change", "Show Week Numbers" };

    private Label selected;

    private Label selectedDoubleClick;

    private Label month;

    private CheckButton[] toggle = new CheckButton[4];

    protected FontSelectionDialog fontsel;

    private boolean showHeading = false;

    private boolean showDayNames = false;

    private boolean noMonthChange = false;

    private boolean showWeekNumbers = false;

    private Calendar calendar;

    public CalendarExample() {

        Window window = new Window(WindowType.TOPLEVEL);
        window.setBorderWidth(5);
        window.setTitle("Calendar Example");
        window.addListener(new LifeCycleListener() {
            public void lifeCycleEvent(LifeCycleEvent event) {
            }

            public boolean lifeCycleQuery(LifeCycleEvent event) {
                if (event.isOfType(LifeCycleEvent.Type.DESTROY)
                        || event.isOfType(LifeCycleEvent.Type.DELETE)) {
                    Gtk.mainQuit();
                }
                return false;
            }
        });

        VBox vbox = new VBox(false, 10);
        window.add(vbox);

        // The top part of the window, Calendar, flags, and fontsel.
        HBox hbox = new HBox(false, 10);
        vbox.packStart(hbox, true, true, 10);
        HButtonBox hbbox = new HButtonBox();
        hbox.packStart(hbbox, false, false, 10);
        hbbox.setLayout(ButtonBoxStyle.SPREAD);
        hbbox.setSpacing(5);

        // Calendar Widget
        Frame frame = new Frame("Calendar");
        hbbox.packStart(frame, true, true, 10);
        calendar = new Calendar();
        // setup the initial state of the calendar widget
        calendarSetFlags();
        calendar.markDay(19);
        calendar.addListener(new CalendarListener() {
            public void calendarEvent(CalendarEvent event) {
                if (event.isOfType(CalendarEvent.Type.MONTH_CHANGED_NEXT)
                        || event
                                .isOfType(CalendarEvent.Type.MONTH_CHANGED_PREV)) {
                    calendarMonthChanged();
                } else if (event.isOfType(CalendarEvent.Type.DAY_SELECTED)) {
                    calendarDaySelected();
                } else if (event
                        .isOfType(CalendarEvent.Type.DAY_SELECTED_DOUBLE_CLICK)) {
                    calendarDaySelectedDoubleClick();
                }
            }
        });
        frame.add(calendar);

        VSeparator separator = new VSeparator();
        hbox.packStart(separator, false, true, 0);

        VBox vbox2 = new VBox(false, 10);
        hbox.packStart(vbox2, false, false, 10);

        frame = new Frame("Flags");
        vbox2.packStart(frame, true, true, 10);
        VBox vbox3 = new VBox(true, 5);
        frame.add(vbox3);

        for (int i = 0; i < 4; i++) {
            toggle[i] = new CheckButton(flags[i], false);
            toggle[i].addListener(new ToggleListener() {
                public void toggleEvent(ToggleEvent event) {
                    calendarToggleFlag();
                }
            });
            vbox3.packStart(toggle[i], true, true, 0);
        }

        // Build the right font-button
        Button button = new Button("Font...", false);
        button.addListener(new ButtonListener() {
            public void buttonEvent(ButtonEvent event) {
                if (event.isOfType(ButtonEvent.Type.CLICK)) {
                    calendarSelectFont();
                }
            }
        });
        vbox2.packStart(button, false, false, 0);

        // Build the signal-event part.
        frame = new Frame("Signal events");
        vbox.packStart(frame, true, true, 10);
        vbox2 = new VBox(true, 5);
        frame.add(vbox2);

        hbox = new HBox(false, 5);
        vbox2.packStart(hbox, false, true, 0);
        Label label = new Label("Day selected:");
        hbox.packStart(label, false, true, 0);
        selected = new Label("");
        hbox.packStart(selected, false, true, 0);

        hbox = new HBox(false, 5);
        vbox2.packStart(hbox, false, true, 0);
        label = new Label("Day selected double click:");
        hbox.packStart(label, false, true, 0);
        selectedDoubleClick = new Label("");
        hbox.packStart(selectedDoubleClick, false, true, 0);

        hbox = new HBox(false, 5);
        vbox2.packStart(hbox, false, true, 0);
        label = new Label("Month change:");
        hbox.packStart(label, false, true, 0);
        month = new Label("");
        hbox.packStart(month, false, true, 0);

        HButtonBox bbox = new HButtonBox();
        vbox.packStart(bbox, false, false, 0);
        bbox.setLayout(ButtonBoxStyle.END);

        button = new Button(GtkStockItem.CLOSE);
        button.addListener(new ButtonListener() {
            public void buttonEvent(ButtonEvent event) {
                if (event.isOfType(ButtonEvent.Type.CLICK)) {
                    Gtk.mainQuit();
                }
            }
        });
        bbox.add(button);

        window.showAll();

        calendarDaySelected();
    }

    public void calendarMonthChanged() {
        int[] ymd = calendar.getDate();
        month.setText(Integer.toString(ymd[1]));
    }

    public void calendarDaySelected() {
        int[] ymd = calendar.getDate();
        selected.setText(Integer.toString(ymd[2]));
    }

    public void calendarDaySelectedDoubleClick() {
        int[] ymd = calendar.getDate();
        selectedDoubleClick.setText(Integer.toString(ymd[2]));
    }

    public void calendarToggleFlag() {
        showHeading = toggle[0].getState();
        showDayNames = toggle[1].getState();
        noMonthChange = toggle[2].getState();
        showWeekNumbers = toggle[3].getState();

        calendarSetFlags();
    }

    public void calendarSelectFont() {
        fontsel = new FontSelectionDialog("Font Selection Dialog");
        Button okButton = fontsel.getOKButton();
        okButton.addListener(new ButtonListener() {
            public void buttonEvent(ButtonEvent event) {
                if (event.isOfType(ButtonEvent.Type.CLICK)) {
                    calendarFontSelectionOK();
                }
            }
        });
        Button cancelButton = fontsel.getCancelButton();
        cancelButton.addListener(new ButtonListener() {
            public void buttonEvent(ButtonEvent event) {
                if (event.isOfType(ButtonEvent.Type.CLICK)) {
                    fontsel.destroy();
                }
            }
        });

        fontsel.show();
    }

    public void calendarFontSelectionOK() {
        String fontname = fontsel.getFontName();
        if (fontname != null) {
            FontDescription fontDesc = new FontDescription(fontname);
            calendar.setFont(fontDesc);
        }
    }

    public void calendarSetFlags() {
        int options = 0;

        if (showHeading)
            options += (1 << 0);
        if (showDayNames)
            options += (1 << 1);
        if (noMonthChange)
            options += (1 << 2);
        if (showWeekNumbers)
            options += (1 << 3);

        calendar.setDisplayOptions(CalendarDisplayOptions.intern(options));
    }

    public static void main(String[] args) {
        // Initialize GTK
        Gtk.init(args);
        new CalendarExample();
        Gtk.main();
    }
}
