Package com.dci.intellij.dbn.data.editor.ui

Source Code of com.dci.intellij.dbn.data.editor.ui.CalendarPopupProviderForm$CalendarHeaderTableModel

package com.dci.intellij.dbn.data.editor.ui;

import com.dci.intellij.dbn.common.Icons;
import com.dci.intellij.dbn.common.locale.Formatter;
import com.dci.intellij.dbn.common.ui.KeyUtil;
import com.dci.intellij.dbn.common.util.ActionUtil;
import com.intellij.openapi.actionSystem.ActionToolbar;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.ui.popup.ComponentPopupBuilder;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.util.containers.HashSet;
import com.intellij.util.ui.UIUtil;

import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Font;
import java.awt.KeyboardFocusManager;
import java.awt.event.FocusEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.sql.Timestamp;
import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Set;

public class CalendarPopupProviderForm extends TextFieldPopupProviderForm implements TableModelListener {
    private static final Font BOLD = new Font(UIUtil.getMenuFont().getFontName(), Font.BOLD, UIUtil.getMenuFont().getSize());
    private TableCellRenderer CELL_RENDERER = new CalendarTableCellRenderer();
    private TableCellRenderer HEADER_CELL_RENDERER = new CalendarTableHeaderCellRenderer();
    private TableModel CALENDER_HEADER_TABLE_MODEL = new CalendarHeaderTableModel();
    private JPanel mainPanel;
    private JTable daysTable;
    private JTable weeksTable;
    private JLabel monthYearLabel;
    private JPanel calendarPanel;
    private JPanel actionsLeftPanel;
    private JPanel actionsRightPanel;
    private JPanel timePanel;
    private JTextField timeTextField;
    private JLabel timeLabel;
    private JPanel actionsPanelBottom;

    protected CalendarPopupProviderForm(TextFieldWithPopup textField, boolean isAutoPopup) {
        super(textField, isAutoPopup);
        calendarPanel.setBackground(weeksTable.getBackground());
        daysTable.addKeyListener(this);
        timeTextField.addKeyListener(this);

        weeksTable.setDefaultRenderer(Object.class, HEADER_CELL_RENDERER);
        weeksTable.setFocusable(false);
        calendarPanel.setBorder(UIUtil.getTextFieldBorder());

        daysTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        daysTable.setDefaultRenderer(Object.class, CELL_RENDERER);
        daysTable.getTableHeader().setDefaultRenderer(HEADER_CELL_RENDERER);
        daysTable.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
        daysTable.addMouseListener(new MouseAdapter(){
            @Override
            public void mouseClicked(MouseEvent e) {
                if (e.getButton() == MouseEvent.BUTTON1) {
                    selectDate();
                }
            }
        });
        /*tDays.addMouseMotionListener(new MouseMotionAdapter() {
            public void mouseMoved(MouseEvent e) {
                final Point point = e.getPoint();
                int rowIndex = tDays.rowAtPoint(point);
                int columnIndex = tDays.columnAtPoint(point);
                tDays.setRowSelectionInterval(rowIndex, rowIndex);
                tDays.setColumnSelectionInterval(columnIndex, columnIndex);
            }
        });*/

        ActionToolbar actionToolbarLeft = ActionUtil.createActionToolbar(
                "DBNavigator.Place.DataEditor.CalendarPopup", true,
                new PreviousYearAction(),
                new PreviousMonthAction());
        ActionToolbar actionToolbarRight = ActionUtil.createActionToolbar(
                "DBNavigator.Place.DataEditor.CalendarPopup", true,
                new NextMonthAction(),
                new NextYearAction());

        ActionToolbar actionToolbarBottom = ActionUtil.createActionToolbar(
                "DBNavigator.Place.DataEditor.CalendarPopup", true, new ClearTimeAction());

        actionsLeftPanel.add(actionToolbarLeft.getComponent(), BorderLayout.WEST);
        actionsRightPanel.add(actionToolbarRight.getComponent(), BorderLayout.EAST);
        actionsPanelBottom.add(actionToolbarBottom.getComponent(), BorderLayout.EAST);
    }

    public JComponent getComponent() {
        return mainPanel;
    }

    public Formatter getFormatter() {
        return Formatter.getInstance(getProject());
    }

    private Date getDateForPopup() {
        if (getEditorComponent().getUserValueHolder() == null) {
            String dateString = getEditorComponent().getTextField().getText();
            try {
                return getFormatter().parseDateTime(dateString);
            } catch (ParseException e) {
                return new Date();
            }
        } else {
            Object userValue = getEditorComponent().getUserValueHolder().getUserValue();
            return userValue instanceof Date ? (Date) userValue : new Date();
        }
    }

    public JBPopup createPopup() {
        Date date = getDateForPopup();
        CalendarTableModel tableModel = new CalendarTableModel(date);
        tableModel.addTableModelListener(this);

        daysTable.setModel(tableModel);
        weeksTable.setModel(CALENDER_HEADER_TABLE_MODEL);

        int rowIndex = tableModel.getInputDateRowIndex();
        int columnIndex = tableModel.getInputDateColumnIndex();
        daysTable.setRowSelectionInterval(rowIndex, rowIndex);
        daysTable.setColumnSelectionInterval(columnIndex, columnIndex);

        ComponentPopupBuilder popupBuilder = JBPopupFactory.getInstance().createComponentPopupBuilder(mainPanel, daysTable);
        popupBuilder.setRequestFocus(true);
        monthYearLabel.setText(tableModel.getCurrentMonthName() + " " + tableModel.getCurrentYear());

        timeTextField.setText(getFormatter().formatTime(date));
        timeLabel.setText("Time (" + getFormatter().getTimeFormatPattern() + ")");

        return popupBuilder.createPopup();
    }

    public void handleKeyPressedEvent(KeyEvent e) {}

    public void handleKeyReleasedEvent(KeyEvent e) {}

    public void handleFocusLostEvent(FocusEvent e) {}


    public String getKeyShortcutName() {
        return IdeActions.ACTION_SHOW_INTENTION_ACTIONS;
    }

    public String getDescription() {
        return "Calendar";
    }

    @Override
    public TextFieldPopupType getPopupType() {
        return TextFieldPopupType.CALENDAR;
    }

    private void selectDate() {
        CalendarTableModel model = (CalendarTableModel) daysTable.getModel();
        Date date = model.getTimestamp(daysTable.getSelectedRow(), daysTable.getSelectedColumn());
        editorComponent.setText(getFormatter().formatDateTime(date));
        hidePopup();
        getTextField().requestFocus();
    }

    /******************************************************
     *                   KeyListener                      *
     ******************************************************/
    public void keyPressed(KeyEvent e) {
        super.keyPressed(e);
        if (!e.isConsumed()) {
            if (e.getKeyCode() == KeyEvent.VK_ENTER ) {
                selectDate();
            }
            if (e.getKeyCode() == KeyEvent.VK_TAB  && e.getSource() == daysTable) {
                KeyboardFocusManager.getCurrentKeyboardFocusManager().focusNextComponent(daysTable);
                e.consume();
            }
        }
    }

    /******************************************************
     *                TableModelListener                  *
     ******************************************************/
    public void tableChanged(TableModelEvent e) {
        CalendarTableModel model = (CalendarTableModel) daysTable.getModel();
        monthYearLabel.setText(model.getCurrentMonthName() + " " + model.getCurrentYear());
    }

    /******************************************************
     *                  TableModels                       *
     ******************************************************/
    private class CalendarHeaderTableModel implements TableModel {
        public int getRowCount() {
            return 1;
        }

        public int getColumnCount() {
            return 7;
        }

        public String getColumnName(int columnIndex) {
            return null;
        }

        public Class<?> getColumnClass(int columnIndex) {
            return String.class;
        }

        public boolean isCellEditable(int rowIndex, int columnIndex) {
            return false;
        }

        public Object getValueAt(int rowIndex, int columnIndex) {
            switch (columnIndex) {
                case 0: return "S";
                case 1: return "M";
                case 2: return "T";
                case 3: return "W";
                case 4: return "T";
                case 5: return "F";
                case 6: return "S";
            }
            return null;
        }

        public void setValueAt(Object aValue, int rowIndex, int columnIndex) {}
        public void addTableModelListener(TableModelListener l) {}
        public void removeTableModelListener(TableModelListener l) {}
    }

    private class CalendarTableModel implements TableModel {
        private Set<TableModelListener> listeners = new HashSet<TableModelListener>();
        private Calendar inputDate = new GregorianCalendar();
        private Calendar activeMonth = new GregorianCalendar();
        private Calendar previousMonth = new GregorianCalendar();

        private CalendarTableModel(Date date) {
            if (date != null) {
                inputDate.setTime(date);
                activeMonth.setTime(date);
                previousMonth.setTime(date);
            }
            activeMonth.set(Calendar.DAY_OF_MONTH, 1);
            previousMonth.set(Calendar.DAY_OF_MONTH, 1);
            previousMonth.add(Calendar.MONTH, -1);
        }

        private CalendarTableModel() {
            this(null);
        }

        public int getRowCount() {
            return 6;
        }

        public int getColumnCount() {
            return 7;
        }

        public String getColumnName(int columnIndex) {
            return null;
        }

        String getCurrentMonthName() {
            return getMonthName(activeMonth.get(Calendar.MONTH));
        }

        String getCurrentYear() {
            return activeMonth.get(Calendar.YEAR) + "";
        }

        String getMonthName(int month) {
            switch (month) {
                case Calendar.JANUARY: return "January";
                case Calendar.FEBRUARY: return "February";
                case Calendar.MARCH: return "March";
                case Calendar.APRIL: return "April";
                case Calendar.MAY: return "May";
                case Calendar.JUNE: return "June";
                case Calendar.JULY: return "July";
                case Calendar.AUGUST: return "August";
                case Calendar.SEPTEMBER: return "September";
                case Calendar.OCTOBER: return "October";
                case Calendar.NOVEMBER: return "November";
                case Calendar.DECEMBER: return "December";
            }
            return null;
        }

        private boolean isFromActiveMonth(int rowIndex, int columnIndex) {
            return !isFromPreviousMonth(rowIndex, columnIndex) &&
                   !isFromNextMonth(rowIndex, columnIndex);
        }

        private boolean isFromPreviousMonth(int rowIndex, int columnIndex) {
            int value = rowIndex * 7 + columnIndex + 2 - activeMonth.get(Calendar.DAY_OF_WEEK);
            return value < 1;
        }

        private boolean isFromNextMonth(int rowIndex, int columnIndex) {
            int value = rowIndex * 7 + columnIndex + 2 - activeMonth.get(Calendar.DAY_OF_WEEK);
            return value > activeMonth.getActualMaximum(Calendar.DAY_OF_MONTH);
        }

        private boolean isInputDate(int rowIndex, int columnIndex) {
            int value = rowIndex * 7 + columnIndex + 2 - activeMonth.get(Calendar.DAY_OF_WEEK);
            return  inputDate.get(Calendar.YEAR) == activeMonth.get(Calendar.YEAR) &&
                    inputDate.get(Calendar.MONTH) == activeMonth.get(Calendar.MONTH) &&
                    value >= 1 && value <= activeMonth.getActualMaximum(Calendar.DAY_OF_MONTH) &&
                    value == inputDate.get(Calendar.DAY_OF_MONTH);
        }

        private int getInputDateColumnIndex() {
            return inputDate.get(Calendar.DAY_OF_WEEK) - 1;
        }

        private int getInputDateRowIndex() {
            return (activeMonth.get(Calendar.DAY_OF_WEEK) + inputDate.get(Calendar.DAY_OF_MONTH) - 2) / 7;
        }

        public Class<?> getColumnClass(int columnIndex) {
            return String.class;
        }

        public boolean isCellEditable(int rowIndex, int columnIndex) {
            return false;
        }

        public Object getValueAt(int rowIndex, int columnIndex) {
            int value = rowIndex * 7 + columnIndex + 2 - activeMonth.get(Calendar.DAY_OF_WEEK);
            if (value < 1) {
                value = previousMonth.getActualMaximum(Calendar.DAY_OF_MONTH) + value;
            } else if (value > activeMonth.getActualMaximum(Calendar.DAY_OF_MONTH)) {
                value = value - activeMonth.getActualMaximum(Calendar.DAY_OF_MONTH);
            }
            return value;
        }

        public void setValueAt(Object aValue, int rowIndex, int columnIndex) {}
        public void addTableModelListener(TableModelListener l) {listeners.add(l);}
        public void removeTableModelListener(TableModelListener l) {listeners.remove(l);}

        private void rollMonth(int amount) {
            activeMonth.add(Calendar.MONTH, amount);
            previousMonth.add(Calendar.MONTH, amount);
            notifyListeners();
        }

        private void rollYear(int amount) {
            activeMonth.add(Calendar.YEAR, amount);
            previousMonth.add(Calendar.YEAR, amount);
            notifyListeners();
        }

        private void notifyListeners() {
            TableModelEvent event = new TableModelEvent(this, 0, 5);
            for (TableModelListener listener : listeners) {
                listener.tableChanged(event);
            }
        }

        public Timestamp getTimestamp(int rowIndex, int columnIndex) {
            Calendar calendar = (Calendar) activeMonth.clone();
            if (isFromPreviousMonth(rowIndex,  columnIndex)) {
                calendar.add(Calendar.MONTH, -1);
            } else if (isFromNextMonth(rowIndex,  columnIndex)) {
                calendar.add(Calendar.MONTH, 1);
            }
            int day = (Integer) getValueAt(rowIndex, columnIndex);
            calendar.set(Calendar.DAY_OF_MONTH, day);

            String timeText = timeTextField.getText();
            try {
                Date time = getFormatter().parseTime(timeText);
                Calendar timeCalendar = new GregorianCalendar();
                timeCalendar.setTime(time);
                calendar.set(Calendar.HOUR_OF_DAY, timeCalendar.get(Calendar.HOUR_OF_DAY));
                calendar.set(Calendar.MINUTE, timeCalendar.get(Calendar.MINUTE));
                calendar.set(Calendar.SECOND, timeCalendar.get(Calendar.SECOND));
                calendar.set(Calendar.MILLISECOND, timeCalendar.get(Calendar.MILLISECOND));
            } catch (ParseException e) {
                calendar.set(Calendar.HOUR_OF_DAY, 0);
                calendar.set(Calendar.MINUTE, 0);
                calendar.set(Calendar.SECOND, 0);
                calendar.set(Calendar.MILLISECOND, 0);
            }

            return new Timestamp(calendar.getTime().getTime());
        }
    }

    /******************************************************
     *                       Actions                      *
     ******************************************************/
    private class NextMonthAction extends AnAction {
        private NextMonthAction() {
            super("Next month", null, Icons.CALENDAR_CELL_EDIT_NEXT_MONTH);
            setShortcutSet(KeyUtil.createShortcutSet(KeyEvent.VK_RIGHT, InputEvent.CTRL_MASK));
            registerAction(this);
        }
        public void actionPerformed(AnActionEvent e) {
            CalendarTableModel tableModel = (CalendarTableModel) daysTable.getModel();
            tableModel.rollMonth(1);
        }
    }

    private class NextYearAction extends AnAction {
        private NextYearAction() {
            super("Next year", null, Icons.CALENDAR_CELL_EDIT_NEXT_YEAR);
            setShortcutSet(KeyUtil.createShortcutSet(KeyEvent.VK_UP, InputEvent.CTRL_MASK));
            registerAction(this);
        }
        public void actionPerformed(AnActionEvent e) {
            CalendarTableModel tableModel = (CalendarTableModel) daysTable.getModel();
            tableModel.rollYear(1);
        }
    }

    private class PreviousMonthAction extends AnAction {
        private PreviousMonthAction() {
            super("Previous month", null, Icons.CALENDAR_CELL_EDIT_PREVIOUS_MONTH);
            setShortcutSet(KeyUtil.createShortcutSet(KeyEvent.VK_LEFT, InputEvent.CTRL_MASK));
            registerAction(this);

        }
        public void actionPerformed(AnActionEvent e) {
            CalendarTableModel tableModel = (CalendarTableModel) daysTable.getModel();
            tableModel.rollMonth(-1);
        }
    }

    private class PreviousYearAction extends AnAction {
        private PreviousYearAction() {
            super("Previous year", null, Icons.CALENDAR_CELL_EDIT_PREVIOUS_YEAR);
            setShortcutSet(KeyUtil.createShortcutSet(KeyEvent.VK_DOWN, InputEvent.CTRL_MASK));
            registerAction(this);
        }
        public void actionPerformed(AnActionEvent e) {
            CalendarTableModel tableModel = (CalendarTableModel) daysTable.getModel();
            tableModel.rollYear(-1);
        }
    }

    private class ClearTimeAction extends AnAction {
        private ClearTimeAction() {
            super("Reset time", null, Icons.CALENDAR_CELL_EDIT_CLEAR_TIME);
            registerAction(this);
        }
        public void actionPerformed(AnActionEvent e) {
            Calendar calendar = new GregorianCalendar(2000,1,0,0,0,0);
            String timeString = getFormatter().formatTime(calendar.getTime());
            timeTextField.setText(timeString);
        }
    }

    /******************************************************
     *                  TableCellRenderers                *
     ******************************************************/
    private static class CalendarTableCellRenderer extends DefaultTableCellRenderer {
        static final Border SELECTION_BORDER = new CompoundBorder(new LineBorder(Color.BLACK, 1, false), new EmptyBorder(0, 0, 0, 6));
        static final Border EMPTY_BORDER = new EmptyBorder(1, 1, 1, 9);

        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            CalendarTableModel model = (CalendarTableModel) table.getModel();

            boolean isInputDate = model.isInputDate(row, column);
            boolean isFromActiveMonth = model.isFromActiveMonth(row, column);
            Color foreground =
                    isInputDate ? UIUtil.getTableForeground() :
                            isFromActiveMonth ? UIUtil.getTableForeground() : Color.LIGHT_GRAY;

            setForeground(isSelected ? UIUtil.getTableSelectionForeground() : foreground);
            setHorizontalAlignment(RIGHT);
            setBorder(isInputDate && !isSelected ? SELECTION_BORDER : EMPTY_BORDER);
            setBackground(isSelected ?
                    table.hasFocus() ?  UIUtil.getListSelectionBackground() : Color.LIGHT_GRAY :
                    UIUtil.getTableBackground());
            //setBorder(new DottedBorder(Color.BLACK));
            return component;
        }
    }


    private static class CalendarTableHeaderCellRenderer extends DefaultTableCellRenderer {
        static final Border EMPTY_BORDER = new EmptyBorder(1, 1, 1, 9);
        public static final Color FOREGROUND_COLOR = new Color(67, 123, 203);

        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            setHorizontalAlignment(RIGHT);
            setFont(BOLD);
            setBorder(EMPTY_BORDER);
            //setForeground(column == 0 ? Color.RED : GUIUtil.getTableForeground());
            setForeground(FOREGROUND_COLOR);
            return component;
        }
    }

    @Override
    public void dispose() {
        super.dispose();
    }
}
TOP

Related Classes of com.dci.intellij.dbn.data.editor.ui.CalendarPopupProviderForm$CalendarHeaderTableModel

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.