///////////////////////////////////////////////////////////////////////////// // // Project ProjectForge Community Edition // www.projectforge.org // // Copyright (C) 2001-2014 Kai Reinhard (k.reinhard@micromata.de) // // ProjectForge is dual-licensed. // // This community edition is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as published // by the Free Software Foundation; version 3 of the License. // // This community edition is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General // Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, see http://www.gnu.org/licenses/. // ///////////////////////////////////////////////////////////////////////////// package org.projectforge.web.wicket.components; import java.sql.Timestamp; import java.util.Date; import org.apache.commons.lang.ClassUtils; import org.apache.wicket.AttributeModifier; import org.apache.wicket.datetime.markup.html.form.DateTextField; import org.apache.wicket.markup.html.form.DropDownChoice; import org.apache.wicket.markup.html.form.FormComponent; import org.apache.wicket.markup.html.form.FormComponentPanel; import org.apache.wicket.model.IModel; import org.apache.wicket.model.PropertyModel; import org.projectforge.common.DateFormats; import org.projectforge.common.DateHolder; import org.projectforge.common.DatePrecision; import org.projectforge.common.StringHelper; import org.projectforge.common.TimeNotation; import org.projectforge.web.wicket.flowlayout.ComponentWrapperPanel; /** * Model for date and time of day components. * @author Kai Reinhard (k.reinhard@micromata.de) * */ public class DateTimePanel extends FormComponentPanel<Date> implements ComponentWrapperPanel { private static final long serialVersionUID = -3835388673051184738L; private static final LabelValueChoiceRenderer<Integer> HOURS_OF_DAY_RENDERER_12; private static final LabelValueChoiceRenderer<Integer> HOURS_OF_DAY_RENDERER_24; private static final LabelValueChoiceRenderer<Integer> MINUTES_1_RENDERER; private static final LabelValueChoiceRenderer<Integer> MINUTES_5_RENDERER; private static final LabelValueChoiceRenderer<Integer> MINUTES_15_RENDERER; static { HOURS_OF_DAY_RENDERER_24 = new LabelValueChoiceRenderer<Integer>(); for (int i = 0; i <= 23; i++) { HOURS_OF_DAY_RENDERER_24.addValue(i, StringHelper.format2DigitNumber(i)); } HOURS_OF_DAY_RENDERER_12 = new LabelValueChoiceRenderer<Integer>(); HOURS_OF_DAY_RENDERER_12.addValue(0, "12 AM"); for (int i = 1; i <= 11; i++) { HOURS_OF_DAY_RENDERER_12.addValue(i, StringHelper.format2DigitNumber(i) + " AM"); } HOURS_OF_DAY_RENDERER_12.addValue(12, "12 PM"); for (int i = 1; i <= 12; i++) { HOURS_OF_DAY_RENDERER_12.addValue(i + 12, StringHelper.format2DigitNumber(i) + " PM"); } MINUTES_1_RENDERER = new LabelValueChoiceRenderer<Integer>(); for (int i = 0; i <= 59; i++) { MINUTES_1_RENDERER.addValue(i, StringHelper.format2DigitNumber(i)); } MINUTES_15_RENDERER = new LabelValueChoiceRenderer<Integer>(); MINUTES_15_RENDERER.addValue(0, "00"); MINUTES_15_RENDERER.addValue(15, "15"); MINUTES_15_RENDERER.addValue(30, "30"); MINUTES_15_RENDERER.addValue(45, "45"); MINUTES_5_RENDERER = new LabelValueChoiceRenderer<Integer>(); for (int i = 0; i <= 55; i += 5) { MINUTES_5_RENDERER.addValue(i, StringHelper.format2DigitNumber(i)); } } private final DateHolder dateHolder; private boolean isNull; private final DatePanel datePanel; private final DropDownChoice<Integer> hourOfDayDropDownChoice; private final DropDownChoice<Integer> minuteDropDownChoice; protected boolean modelMarkedAsChanged; protected DateTimePanelSettings settings; public static LabelValueChoiceRenderer<Integer> getHourOfDayRenderer() { return getHourOfDayRenderer(DateFormats.ensureAndGetDefaultTimeNotation()); } public static LabelValueChoiceRenderer<Integer> getHourOfDayRenderer(final TimeNotation timeNotation) { return timeNotation == TimeNotation.H12 ? HOURS_OF_DAY_RENDERER_12 : HOURS_OF_DAY_RENDERER_24; } /** * 0, 1, ...59 or 0, 15, 30, 45 dependent on DatePrecision. * @return */ public static LabelValueChoiceRenderer<Integer> getMinutesRenderer(final DatePrecision precision) { if (precision == DatePrecision.MINUTE_15) { return MINUTES_15_RENDERER; } if (precision == DatePrecision.MINUTE_5) { return MINUTES_5_RENDERER; } return MINUTES_1_RENDERER; } /** * @param id * @param label Only for displaying the field's name on validation messages. * @param model * @param precision * @param settings.tabIndex Use tabIndex as html tab index of date field, hours and minutes. */ public DateTimePanel(final String id, final IModel<Date> model, final DateTimePanelSettings settings, final DatePrecision precision) { super(id, model); this.settings = settings; setType(settings.targetType); dateHolder = new DateHolder(model.getObject(), precision); final PropertyModel<Date> dateFieldModel = new PropertyModel<Date>(this, "date"); add(datePanel = new DatePanel("date", dateFieldModel, settings)); datePanel.setRequired(settings.required); hourOfDayDropDownChoice = new DropDownChoice<Integer>("hourOfDay", new PropertyModel<Integer>(this, "hourOfDay"), getHourOfDayRenderer().getValues(), getHourOfDayRenderer()); hourOfDayDropDownChoice.setNullValid(!settings.required); hourOfDayDropDownChoice.setRequired(settings.required); add(hourOfDayDropDownChoice); minuteDropDownChoice = new DropDownChoice<Integer>("minute", new PropertyModel<Integer>(this, "minute"), getMinutesRenderer( dateHolder.getPrecision()).getValues(), getMinutesRenderer(dateHolder.getPrecision())); minuteDropDownChoice.setNullValid(!settings.required); minuteDropDownChoice.setRequired(settings.required); add(minuteDropDownChoice); if (settings.tabIndex != null) { datePanel.dateField.add(AttributeModifier.replace("tabindex", String.valueOf(settings.tabIndex))); hourOfDayDropDownChoice.add(AttributeModifier.replace("tabindex", String.valueOf(settings.tabIndex + 1))); minuteDropDownChoice.add(AttributeModifier.replace("tabindex", String.valueOf(settings.tabIndex + 2))); } } /** * @see org.apache.wicket.markup.html.form.FormComponent#setLabel(org.apache.wicket.model.IModel) */ @Override public DateTimePanel setLabel(final IModel<String> labelModel) { datePanel.setLabel(labelModel); super.setLabel(labelModel); return this; } /** * @param field * @param amount * @see DateHolder#add(int, int) */ public void add(final int field, final int amount) { dateHolder.add(field, amount); } public DateHolder getDateHolder() { return dateHolder; } public void setDate(final Date date) { if (date == null && settings.required == false) { isNull = true; } else { this.dateHolder.setDate(date); } } public void setDate(final long millis) { this.dateHolder.setDate(millis); } public void setDay(final DateHolder dateHolder) { this.dateHolder.setDay(dateHolder.getCalendar()); } public Date getDate() { if (isNull == true) { return null; } return dateHolder.getDate(); } public Timestamp getTimestamp() { if (isNull == true) { return null; } return this.dateHolder.getTimestamp(); } public Integer getHourOfDay() { if (isNull == true) { return null; } return dateHolder.getHourOfDay(); } public void setHourOfDay(final Integer hourOfDay) { if (hourOfDay != null) { dateHolder.setHourOfDay(hourOfDay); } } public Integer getMinute() { if (isNull == true) { return null; } return dateHolder.getMinute(); } public void setMinute(final Integer minute) { if (minute != null) { dateHolder.setMinute(minute); } } /** * Work around: If you change the model call this method, so onBeforeRender calls DateField.modelChanged() for updating the form text * field. */ public void markModelAsChanged() { modelMarkedAsChanged = true; datePanel.markModelAsChanged(); } public DatePanel getDatePanel() { return datePanel; } public DateTextField getDateField() { return datePanel.getDateField(); } public void setFocus() { datePanel.setFocus(); } @Override protected void onBeforeRender() { final Date date = getModelObject(); if (date != null) { dateHolder.setDate(date); isNull = false; } else if (settings.required == false) { isNull = true; } if (modelMarkedAsChanged == true) { hourOfDayDropDownChoice.modelChanged(); minuteDropDownChoice.modelChanged(); modelMarkedAsChanged = false; } super.onBeforeRender(); } @Override protected void convertInput() { final Date date = datePanel.getConvertedInput(); if (date != null) { isNull = false; getDateHolder().setDate(date); final Integer hours = hourOfDayDropDownChoice.getConvertedInput(); final Integer minutes = minuteDropDownChoice.getConvertedInput(); if (hours != null) { dateHolder.setHourOfDay(hours); } if (minutes != null) { dateHolder.setMinute(minutes); } if (ClassUtils.isAssignable(getType(), Timestamp.class) == true) { setConvertedInput(dateHolder.getTimestamp()); } else { setConvertedInput(dateHolder.getDate()); } } else if (settings.required == false) { isNull = true; setConvertedInput(null); } } @Override public String toString() { if (isNull == true) { return null; } return dateHolder.getDate().toString(); } /** * @see org.projectforge.web.wicket.flowlayout.ComponentWrapperPanel#getComponentOutputId() */ @Override public String getComponentOutputId() { return datePanel.getComponentOutputId(); } /** * @return the minuteDropDownChoice */ public DropDownChoice<Integer> getMinuteDropDownChoice() { return minuteDropDownChoice; } /** * @return the hourOfDayDropDownChoice */ public DropDownChoice<Integer> getHourOfDayDropDownChoice() { return hourOfDayDropDownChoice; } /** * @see org.projectforge.web.wicket.flowlayout.ComponentWrapperPanel#getFormComponent() */ @Override public FormComponent< ? > getFormComponent() { return datePanel.getDateField(); } }