Package org.apache.isis.viewer.dnd.field

Source Code of org.apache.isis.viewer.dnd.field.SimpleDatePicker

/*
*  Licensed to the Apache Software Foundation (ASF) under one
*  or more contributor license agreements.  See the NOTICE file
*  distributed with this work for additional information
*  regarding copyright ownership.  The ASF licenses this file
*  to you under the Apache License, Version 2.0 (the
*  "License"); you may not use this file except in compliance
*  with the License.  You may obtain a copy of the License at
*
*        http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing,
*  software distributed under the License is distributed on an
*  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
*  KIND, either express or implied.  See the License for the
*  specific language governing permissions and limitations
*  under the License.
*/
package org.apache.isis.viewer.dnd.field;

import java.awt.event.KeyEvent;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
import org.apache.isis.core.progmodel.facets.value.date.DateValueFacet;
import org.apache.isis.viewer.dnd.drawing.Canvas;
import org.apache.isis.viewer.dnd.drawing.Color;
import org.apache.isis.viewer.dnd.drawing.ColorsAndFonts;
import org.apache.isis.viewer.dnd.drawing.Location;
import org.apache.isis.viewer.dnd.drawing.Shape;
import org.apache.isis.viewer.dnd.drawing.Size;
import org.apache.isis.viewer.dnd.drawing.Text;
import org.apache.isis.viewer.dnd.view.Click;
import org.apache.isis.viewer.dnd.view.Content;
import org.apache.isis.viewer.dnd.view.KeyboardAction;
import org.apache.isis.viewer.dnd.view.Toolkit;
import org.apache.isis.viewer.dnd.view.base.AbstractView;
import org.apache.isis.viewer.dnd.view.content.FieldContent;
import org.apache.isis.viewer.dnd.view.content.TextParseableContent;

public class SimpleDatePicker extends AbstractView implements DatePicker {
    private static class Button {
        private final char key;
        private final int period;
        private final int increment;

        public Button(final char key, final int period, final int increment) {
            this.key = key;
            this.period = period;
            this.increment = increment;
        }

        public void adjustDate(final Calendar date) {
            date.add(period, increment);
        }

        public String getLabel() {
            return "" + key;
        }
    }

    private static final Button[] buttons = new Button[] { new Button('W', Calendar.WEEK_OF_YEAR, 1),
        new Button('F', Calendar.WEEK_OF_YEAR, 2), new Button('M', Calendar.MONTH, 1),
        new Button('Q', Calendar.MONTH, 3), new Button('Y', Calendar.YEAR, 1), new Button('D', Calendar.YEAR, 10),

        new Button('w', Calendar.WEEK_OF_YEAR, -1), new Button('f', Calendar.WEEK_OF_YEAR, -2),
        new Button('m', Calendar.MONTH, -1), new Button('q', Calendar.MONTH, -3), new Button('y', Calendar.YEAR, -1),
        new Button('d', Calendar.YEAR, -10) };
    private static final int ROWS = 7;
    private static final int COLUMNS = 7;
    private static final int PADDING = 5;
    private final Calendar date;
    private final Text style = Toolkit.getText(ColorsAndFonts.TEXT_NORMAL);
    private final int labelWidth = style.stringWidth("XXX 0000") * 4 / 3;
    private final int cellWidth = style.stringWidth("00") * 8 / 5;
    private final int cellHeight = style.getLineHeight() * 4 / 3;
    private final int headerHeight = style.getLineHeight() + PADDING * 2;
    private final int firstRowBaseline = headerHeight + style.getLineHeight();
    private final int calendarHeight = cellHeight * ROWS;
    private final int controlWidth = style.charWidth('W') + 4;
    private final int controlHeight = style.getLineHeight() * 11 / 10 + controlWidth + 4 + PADDING * 2;
    private int mouseOverButton = -1;
    private int mouseOverRow = -1;
    private int mouseOverColumn;
    private Calendar currentDate;
    private final Calendar today;
    private final DateFormat monthFormat = new SimpleDateFormat("MMM");
    private final DateFormat dayFormat = new SimpleDateFormat("EEE");
    private final boolean isEditable;

    public SimpleDatePicker(final Content content) {
        super(content);

        isEditable = content instanceof FieldContent && ((FieldContent) content).isEditable().isAllowed();

        today = Calendar.getInstance();
        clearTime(today);

        date = Calendar.getInstance();
        final ObjectAdapter dateAdapter = ((TextParseableContent) getContent()).getAdapter();
        if (dateAdapter != null) {
            final DateValueFacet facet = dateAdapter.getSpecification().getFacet(DateValueFacet.class);
            currentDate = Calendar.getInstance();
            final Date dateValue = facet.dateValue(dateAdapter);
            currentDate.setTime(dateValue);
            clearTime(currentDate);
            date.setTime(dateValue);
        }
        clearTime(date);
        date.add(Calendar.DAY_OF_MONTH, -21);
        roundDownDate();
    }

    private void roundDownDate() {
        date.add(Calendar.DAY_OF_MONTH, date.getFirstDayOfWeek() - date.get(Calendar.DAY_OF_WEEK));
    }

    private void clearTime(final Calendar date) {
        date.clear(Calendar.AM_PM);
        date.clear(Calendar.HOUR);
        date.clear(Calendar.HOUR_OF_DAY);
        date.clear(Calendar.MINUTE);
        date.clear(Calendar.SECOND);
        date.clear(Calendar.MILLISECOND);
    }

    /*
     * (non-Javadoc)
     *
     * @see org.nakedobjects.plugins.dnd.field.DatePicker#getRequiredSize(org.nakedobjects.plugins.dnd.drawing.Size)
     */
    @Override
    public Size getRequiredSize(final Size availableSpace) {
        return new Size(labelWidth + COLUMNS * cellWidth + 2, headerHeight + calendarHeight + controlHeight + 2);
    }

    /*
     * (non-Javadoc)
     *
     * @see org.nakedobjects.plugins.dnd.field.DatePicker#draw(org.nakedobjects.plugins.dnd.drawing.Canvas)
     */
    @Override
    public void draw(final Canvas canvas) {
        final int width = getSize().getWidth();
        final int height = getSize().getHeight();

        final Color secondaryTextColor = Toolkit.getColor(ColorsAndFonts.COLOR_WHITE);
        final Color mainTextColor = Toolkit.getColor(ColorsAndFonts.COLOR_BLACK);

        drawBackground(canvas, width, height);
        drawDaysOfWeek(canvas, secondaryTextColor);
        if (isEditable) {
            drawDayMarker(canvas);
        }
        drawMonthsAndWeeks(canvas, secondaryTextColor);
        drawDays(canvas, mainTextColor);
        drawControls(canvas, width);
    }

    private void drawBackground(final Canvas canvas, final int width, final int height) {
        canvas.drawSolidRectangle(0, 0, width - 1, headerHeight, Toolkit.getColor(ColorsAndFonts.COLOR_SECONDARY1));
        canvas.drawSolidRectangle(0, 0, labelWidth, height - 1, Toolkit.getColor(ColorsAndFonts.COLOR_SECONDARY1));
        canvas.drawSolidRectangle(labelWidth, headerHeight, width - labelWidth - 1, height - cellHeight - 1,
            Toolkit.getColor(ColorsAndFonts.COLOR_WINDOW));
        canvas.drawRectangle(0, 0, width - 1, height - 1, Toolkit.getColor(ColorsAndFonts.COLOR_SECONDARY1));
    }

    private void drawDaysOfWeek(final Canvas canvas, final Color textColor) {
        final Calendar d = Calendar.getInstance();
        d.setTime(date.getTime());
        int x = labelWidth + cellWidth / 2;
        final int y = PADDING + style.getAscent();
        for (int column = 0; column < 7; column++) {
            final String day = dayFormat.format(d.getTime()).substring(0, 1);
            canvas.drawText(day, x - style.stringWidth(day) / 2, y, textColor, style);
            x += cellWidth;
            d.add(Calendar.DAY_OF_MONTH, 1);
        }
    }

    private void drawDayMarker(final Canvas canvas) {
        if (mouseOverColumn >= 0 && mouseOverColumn < COLUMNS && mouseOverRow >= 0 && mouseOverRow < ROWS) {
            canvas.drawRectangle(labelWidth + mouseOverColumn * cellWidth, headerHeight + mouseOverRow * cellHeight,
                cellWidth, cellHeight, Toolkit.getColor(ColorsAndFonts.COLOR_PRIMARY3));
        }
    }

    private int drawMonthsAndWeeks(final Canvas canvas, final Color color) {
        final Calendar d = Calendar.getInstance();
        d.setTime(date.getTime());
        int y = firstRowBaseline;
        String lastMonth = "";
        for (int row = 0; row < ROWS; row++) {
            final int x = labelWidth;
            final String month = monthFormat.format(d.getTime()) + " " + d.get(Calendar.YEAR);
            if (!month.equals(lastMonth)) {
                canvas.drawText(month, x - style.stringWidth(month) - PADDING, y, color, style);
                lastMonth = month;
            } else {
                final String week = "wk " + (d.get(Calendar.WEEK_OF_YEAR));
                canvas.drawText(week == null ? "*" : week, x - style.stringWidth(week) - PADDING, y, color, style);
            }
            d.add(Calendar.DAY_OF_MONTH, 7);
            y += cellHeight;
        }
        return y;
    }

    private int drawDays(final Canvas canvas, final Color mainTextColor) {
        final Calendar d = Calendar.getInstance();
        d.setTime(date.getTime());
        int y = firstRowBaseline;
        for (int row = 0; row < ROWS; row++) {
            int x = labelWidth;
            for (int column = 0; column < COLUMNS; column++) {
                final String day = "" + d.get(Calendar.DAY_OF_MONTH);
                if (currentDate != null && currentDate.equals(d)) {
                    canvas.drawSolidRectangle(x, headerHeight + row * cellHeight, cellWidth, cellHeight,
                        Toolkit.getColor(ColorsAndFonts.COLOR_PRIMARY2));
                }
                if (today.getTime().equals(d.getTime())) {
                    canvas.drawRectangle(x, headerHeight + row * cellHeight, cellWidth, cellHeight,
                        Toolkit.getColor(ColorsAndFonts.COLOR_SECONDARY2));
                }
                canvas.drawText(day, x - PADDING / 2 + cellWidth - style.stringWidth(day), y, mainTextColor, style);
                x += cellWidth;
                d.add(Calendar.DAY_OF_MONTH, 1);
            }
            y += cellHeight;
        }
        return y;
    }

    private void drawControls(final Canvas canvas, final int width) {
        int x = labelWidth + PADDING;
        final int y = headerHeight + calendarHeight + PADDING;

        final int spaceTaken = width - labelWidth - 2 * PADDING - 6 * controlWidth;
        final int spaceBetween = spaceTaken / 5;
        final int adjustment = spaceTaken - 5 * spaceBetween - 2;

        for (int i = 0; i < buttons.length / 2; i++) {
            drawControl(canvas, x, y, controlWidth, controlHeight - PADDING * 2, buttons[i].getLabel(), i);
            x += controlWidth + spaceBetween + (i == 3 ? adjustment : 0);
        }
    }

    private void drawControl(final Canvas canvas, final int x, final int y, final int width, final int height,
        final String label, final int over) {
        if (Toolkit.debug) {
            canvas.drawRectangle(x - 2, y, width + 4, height, Toolkit.getColor(ColorsAndFonts.COLOR_DEBUG_BOUNDS_VIEW));
        }
        final Color color = Toolkit.getColor(ColorsAndFonts.COLOR_SECONDARY2);

        final int arrowHeight = width / 2;
        final Shape upArrow = new Shape(0, arrowHeight);
        upArrow.addVector(arrowHeight, -arrowHeight);
        upArrow.addVector(arrowHeight, arrowHeight);
        if (mouseOverButton == over + 6) {
            canvas.drawSolidShape(upArrow, x, y + 2, color);
        } else {
            canvas.drawShape(upArrow, x, y + 2, color);
        }

        final Shape downArrow = new Shape(0, 0);
        downArrow.addVector(arrowHeight, arrowHeight);
        downArrow.addVector(arrowHeight, -arrowHeight);
        if (mouseOverButton == over) {
            canvas.drawSolidShape(downArrow, x, y + height - 4 - arrowHeight, color);
        } else {
            canvas.drawShape(downArrow, x, y + height - 4 - arrowHeight, color);
        }
        final int charWidth = style.stringWidth(label);
        canvas.drawText(label, x + width / 2 - charWidth / 2, y + 2 + arrowHeight + style.getAscent(), color, style);

    }

    /*
     * (non-Javadoc)
     *
     * @see org.nakedobjects.plugins.dnd.field.DatePicker#mouseMoved(org.nakedobjects.plugins.dnd.drawing.Location)
     */
    @Override
    public void mouseMoved(final Location location) {
        final int over = overButton(location);
        if (over == -1) {
            mouseOverButton = -1;
            final int col = column(location);
            final int row = row(location);
            if (col != mouseOverColumn || row != mouseOverRow) {
                if (isEditable) {
                    mouseOverColumn = col;
                    mouseOverRow = row;
                }
                markDamaged();
            }
        } else if (over != mouseOverButton) {
            mouseOverButton = over;
            markDamaged();
        }
    }

    /*
     * (non-Javadoc)
     *
     * @see org.nakedobjects.plugins.dnd.field.DatePicker#exited()
     */
    @Override
    public void exited() {
        mouseOverButton = -1;
        super.exited();
    }

    private int overButton(final Location location) {
        final int x = location.getX();
        final int y = location.getY();
        final int verticalBoundary = headerHeight + calendarHeight + PADDING;
        final int height = controlHeight - PADDING * 2;
        if (x > labelWidth && y > verticalBoundary && y < verticalBoundary + height) {
            int column = (x - labelWidth) / ((getSize().getWidth() - labelWidth) / 6);
            if (y <= verticalBoundary + height / 2) {
                column += 6;
            }
            return column;
        } else {
            return -1;
        }
    }

    /*
     * (non-Javadoc)
     *
     * @see org.nakedobjects.plugins.dnd.field.DatePicker#firstClick(org.nakedobjects.plugins.dnd.view.Click)
     */
    @Override
    public void firstClick(final Click click) {
        if (mouseOverButton != -1) {
            buttons[mouseOverButton].adjustDate(date);
            roundDownDate();
            markDamaged();
            return;
        }

        if (isEditable) {
            final Location location = click.getLocation();
            final int col = column(location);
            final int row = row(location);
            if (col >= 0 && col < COLUMNS && row >= 0 && row < ROWS) {
                date.add(Calendar.DAY_OF_MONTH, row * 7 + col);
                final Content content = getContent();
                final DateValueFacet facet = content.getSpecification().getFacet(DateValueFacet.class);
                final ObjectAdapter value = facet.createValue(date.getTime());
                ((TextParseableContent) content).parseTextEntry(value.titleString());
                ((TextParseableContent) content).entryComplete();
                /*
                 * if (content.isObject()) { ((ObjectContent) content).setObject(value); }
                 */
                // content.
                getView().refresh();

                // content.
            }
        }
        getViewManager().clearOverlayView();
    }

    private int row(final Location location) {
        return (location.getY() - headerHeight) / cellHeight;
    }

    private int column(final Location location) {
        return (location.getX() - labelWidth) / cellWidth;
    }

    /*
     * (non-Javadoc)
     *
     * @see org.nakedobjects.plugins.dnd.field.DatePicker#keyPressed(org.nakedobjects.plugins.dnd.view.KeyboardAction)
     */
    @Override
    public void keyPressed(final KeyboardAction key) {
        if (isEditable && key.getKeyCode() == KeyEvent.VK_ESCAPE) {
            getViewManager().clearOverlayView();
        } else {
            super.keyPressed(key);
        }
    }
}
TOP

Related Classes of org.apache.isis.viewer.dnd.field.SimpleDatePicker

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.