/*! * This program is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software * Foundation. * * You should have received a copy of the GNU Lesser General Public License along with this * program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html * or from the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * This program 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 Lesser General Public License for more details. * * Copyright (c) 2002-2017 Pentaho Corporation.. All rights reserved. */ package org.pentaho.mantle.client.dialogs.scheduling; import com.google.gwt.user.client.ui.CaptionPanel; import com.google.gwt.user.client.ui.ChangeListener; import com.google.gwt.user.client.ui.CheckBox; import com.google.gwt.user.client.ui.ClickListener; import com.google.gwt.user.client.ui.DeckPanel; import com.google.gwt.user.client.ui.FlexTable; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.KeyboardListener; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.ListBox; import com.google.gwt.user.client.ui.Panel; import com.google.gwt.user.client.ui.RadioButton; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.Widget; import org.pentaho.gwt.widgets.client.controls.DateRangeEditor; import org.pentaho.gwt.widgets.client.controls.ErrorLabel; import org.pentaho.gwt.widgets.client.controls.TimePicker; import org.pentaho.gwt.widgets.client.ui.ICallback; import org.pentaho.gwt.widgets.client.ui.IChangeHandler; import org.pentaho.gwt.widgets.client.utils.CronParseException; import org.pentaho.gwt.widgets.client.utils.CronParser; import org.pentaho.gwt.widgets.client.utils.CronParser.RecurrenceType; import org.pentaho.gwt.widgets.client.utils.EnumException; import org.pentaho.gwt.widgets.client.utils.StringUtils; import org.pentaho.gwt.widgets.client.utils.TimeUtil; import org.pentaho.gwt.widgets.client.utils.TimeUtil.DayOfWeek; import org.pentaho.gwt.widgets.client.utils.TimeUtil.MonthOfYear; import org.pentaho.gwt.widgets.client.utils.TimeUtil.TimeOfDay; import org.pentaho.gwt.widgets.client.utils.TimeUtil.WeekOfMonth; import org.pentaho.mantle.client.messages.Messages; import java.util.ArrayList; import java.util.Date; import java.util.EnumSet; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; /** * @author Steven Barkdull * */ @SuppressWarnings( "deprecation" ) public class RecurrenceEditor extends VerticalPanel implements IChangeHandler { public static final int VALUE_OF_SUNDAY = 1; private static final String SCHEDULE_EDITOR_CAPTION_PANEL = "schedule-editor-caption-panel"; //$NON-NLS-1$ private static final String DOW_CHECKBOX = "day-of-week-checkbox"; //$NON-NLS-1$ private static final String EVERY_TXTBOX = "every-txtbox"; private static final String RECUR_PATTERN_HP = "recur-pattern-hp"; protected TimePicker startTimePicker = null; protected SecondlyRecurrenceEditor secondlyEditor = null; protected MinutelyRecurrenceEditor minutelyEditor = null; protected HourlyRecurrenceEditor hourlyEditor = null; protected DailyRecurrenceEditor dailyEditor = null; protected WeeklyRecurrenceEditor weeklyEditor = null; protected MonthlyRecurrenceEditor monthlyEditor = null; protected YearlyRecurrenceEditor yearlyEditor = null; protected DateRangeEditor dateRangeEditor = null; protected TemporalValue temporalState = null; private DeckPanel deckPanel = null; private static final String SPACE = " "; //$NON-NLS-1$ private ICallback<IChangeHandler> onChangeHandler; protected Map<TemporalValue, Panel> temporalPanelMap = new LinkedHashMap<TemporalValue, Panel>(); public enum TemporalValue { SECONDS( 0, Messages.getString( "schedule.seconds" ) ), MINUTES( 1, Messages.getString( "schedule.minutes" ) ), HOURS( 2, Messages.getString( "schedule.hours" ) ), DAILY( 3, Messages.getString( "schedule.daily" ) ), WEEKLY( 4, Messages.getString( "schedule.weekly" ) ), MONTHLY( 5, Messages.getString( "schedule.monthly" ) ), YEARLY( 6, Messages.getString( "schedule.yearly" ) ); private TemporalValue( int value, String name ) { this.value = value; this.name = name; } private final int value; private final String name; private static TemporalValue[] temporalValues = { SECONDS, MINUTES, HOURS, DAILY, WEEKLY, MONTHLY, YEARLY }; public int value() { return value; } public String toString() { return name; } public static TemporalValue get( int idx ) { return temporalValues[idx]; } public static int length() { return temporalValues.length; } public static TemporalValue stringToTemporalValue( String temporalValue ) throws EnumException { for ( TemporalValue v : EnumSet.range( TemporalValue.SECONDS, TemporalValue.YEARLY ) ) { if ( v.toString().equals( temporalValue ) ) { return v; } } throw new EnumException( Messages.getString( "schedule.invalidTemporalValue", temporalValue ) ); } } /* end enum */ private static final String DAILY_RB_GROUP = "daily-group"; //$NON-NLS-1$ private static final String MONTHLY_RB_GROUP = "monthly-group"; //$NON-NLS-1$ public RecurrenceEditor( final TimePicker startTimePicker ) { super(); this.setWidth( "100%" ); //$NON-NLS-1$ Widget p = createRecurrencePanel(); add( p ); Date now = new Date(); dateRangeEditor = new DateRangeEditor( now ); add( dateRangeEditor ); this.startTimePicker = startTimePicker; configureOnChangeHandler(); } public void reset( Date d ) { startTimePicker.setHour( "12" ); //$NON-NLS-1$ startTimePicker.setMinute( "00" ); //$NON-NLS-1$ startTimePicker.setTimeOfDay( TimeUtil.TimeOfDay.AM ); dateRangeEditor.reset( d ); secondlyEditor.reset(); minutelyEditor.reset(); hourlyEditor.reset(); dailyEditor.reset(); weeklyEditor.reset(); monthlyEditor.reset(); yearlyEditor.reset(); } /** * * @param recurrenceStr * @throws EnumException * thrown if recurrenceTokens[0] is not a valid ScheduleType String. */ public void inititalizeWithRecurrenceString( String recurrenceStr ) throws EnumException { String[] recurrenceTokens = recurrenceStr.split( "\\s" ); //$NON-NLS-1$ setStartTime( recurrenceTokens[1], recurrenceTokens[2], recurrenceTokens[3] ); RecurrenceType rt = RecurrenceType.stringToScheduleType( recurrenceTokens[0] ); switch ( rt ) { case EveryWeekday: setEveryWeekdayRecurrence( recurrenceTokens ); break; case WeeklyOn: setWeeklyOnRecurrence( recurrenceTokens ); break; case DayNOfMonth: setDayNOfMonthRecurrence( recurrenceTokens ); break; case NthDayNameOfMonth: setNthDayNameOfMonthRecurrence( recurrenceTokens ); break; case LastDayNameOfMonth: setLastDayNameOfMonthRecurrence( recurrenceTokens ); break; case EveryMonthNameN: setEveryMonthNameNRecurrence( recurrenceTokens ); break; case NthDayNameOfMonthName: setNthDayNameOfMonthNameRecurrence( recurrenceTokens ); break; case LastDayNameOfMonthName: setLastDayNameOfMonthNameRecurrence( recurrenceTokens ); break; default: } } private void setStartTime( String seconds, String minutes, String hours ) { TimeOfDay td = TimeUtil.getTimeOfDayBy0To23Hour( hours ); int intHours = Integer.parseInt( hours ); int intTwelveHour = TimeUtil.to12HourClock( intHours ); // returns 0..11 startTimePicker.setHour( Integer.toString( TimeUtil.map0Through11To12Through11( intTwelveHour ) ) ); startTimePicker.setMinute( minutes ); startTimePicker.setTimeOfDay( td ); } private void setEveryWeekdayRecurrence( String[] recurrenceTokens ) { setTemporalState( TemporalValue.DAILY ); dailyEditor.setEveryWeekday(); } private void setWeeklyOnRecurrence( String[] recurrenceTokens ) { setTemporalState( TemporalValue.WEEKLY ); String days = recurrenceTokens[4]; weeklyEditor.setCheckedDaysAsString( days, VALUE_OF_SUNDAY ); } private void setDayNOfMonthRecurrence( String[] recurrenceTokens ) { setTemporalState( TemporalValue.MONTHLY ); monthlyEditor.setDayNOfMonth(); String dayNOfMonth = recurrenceTokens[4]; monthlyEditor.setDayOfMonth( dayNOfMonth ); } private void setNthDayNameOfMonthRecurrence( String[] recurrenceTokens ) { setTemporalState( TemporalValue.MONTHLY ); monthlyEditor.setNthDayNameOfMonth(); monthlyEditor.setWeekOfMonth( WeekOfMonth.get( Integer.parseInt( recurrenceTokens[5] ) - 1 ) ); monthlyEditor.setDayOfWeek( DayOfWeek.get( Integer.parseInt( recurrenceTokens[4] ) - 1 ) ); } private void setLastDayNameOfMonthRecurrence( String[] recurrenceTokens ) { setTemporalState( TemporalValue.MONTHLY ); monthlyEditor.setNthDayNameOfMonth(); monthlyEditor.setWeekOfMonth( WeekOfMonth.LAST ); monthlyEditor.setDayOfWeek( DayOfWeek.get( Integer.parseInt( recurrenceTokens[4] ) - 1 ) ); } private void setEveryMonthNameNRecurrence( String[] recurrenceTokens ) { setTemporalState( TemporalValue.YEARLY ); yearlyEditor.setEveryMonthOnNthDay(); yearlyEditor.setDayOfMonth( recurrenceTokens[4] ); yearlyEditor.setMonthOfYear0( MonthOfYear.get( Integer.parseInt( recurrenceTokens[5] ) - 1 ) ); } private void setNthDayNameOfMonthNameRecurrence( String[] recurrenceTokens ) { setTemporalState( TemporalValue.YEARLY ); yearlyEditor.setNthDayNameOfMonthName(); yearlyEditor.setMonthOfYear1( MonthOfYear.get( Integer.parseInt( recurrenceTokens[6] ) - 1 ) ); yearlyEditor.setWeekOfMonth( WeekOfMonth.get( Integer.parseInt( recurrenceTokens[5] ) - 1 ) ); yearlyEditor.setDayOfWeek( DayOfWeek.get( Integer.parseInt( recurrenceTokens[4] ) - 1 ) ); } private void setLastDayNameOfMonthNameRecurrence( String[] recurrenceTokens ) { setTemporalState( TemporalValue.YEARLY ); yearlyEditor.setNthDayNameOfMonthName(); yearlyEditor.setMonthOfYear1( MonthOfYear.get( Integer.parseInt( recurrenceTokens[5] ) - 1 ) ); yearlyEditor.setWeekOfMonth( WeekOfMonth.LAST ); yearlyEditor.setDayOfWeek( DayOfWeek.get( Integer.parseInt( recurrenceTokens[4] ) - 1 ) ); } /** * * @param repeatInSecs */ public void inititalizeWithRepeatInSecs( int repeatInSecs ) { TemporalValue currentVal; long repeatTime; if ( TimeUtil.isSecondsWholeDay( repeatInSecs ) ) { repeatTime = TimeUtil.secsToDays( repeatInSecs ); currentVal = TemporalValue.DAILY; dailyEditor.setRepeatValue( Long.toString( repeatTime ) ); } else { SimpleRecurrencePanel p = null; if ( TimeUtil.isSecondsWholeHour( repeatInSecs ) ) { repeatTime = TimeUtil.secsToHours( repeatInSecs ); currentVal = TemporalValue.HOURS; } else if ( TimeUtil.isSecondsWholeMinute( repeatInSecs ) ) { repeatTime = TimeUtil.secsToMinutes( repeatInSecs ); currentVal = TemporalValue.MINUTES; } else { // the repeat time is seconds repeatTime = repeatInSecs; currentVal = TemporalValue.SECONDS; } p = (SimpleRecurrencePanel) temporalPanelMap.get( currentVal ); p.setValue( Long.toString( repeatTime ) ); } setTemporalState( currentVal ); } private Widget createRecurrencePanel() { CaptionPanel recurrenceGB = new CaptionPanel( Messages.getString( "schedule.recurrencePattern" ) ); recurrenceGB.setStyleName( SCHEDULE_EDITOR_CAPTION_PANEL ); deckPanel = new DeckPanel(); recurrenceGB.add( deckPanel ); secondlyEditor = new SecondlyRecurrenceEditor(); minutelyEditor = new MinutelyRecurrenceEditor(); hourlyEditor = new HourlyRecurrenceEditor(); dailyEditor = new DailyRecurrenceEditor(); weeklyEditor = new WeeklyRecurrenceEditor(); monthlyEditor = new MonthlyRecurrenceEditor(); yearlyEditor = new YearlyRecurrenceEditor(); createTemporalMap(); deckPanel.add( secondlyEditor ); deckPanel.add( minutelyEditor ); deckPanel.add( hourlyEditor ); deckPanel.add( dailyEditor ); deckPanel.add( weeklyEditor ); deckPanel.add( monthlyEditor ); deckPanel.add( yearlyEditor ); deckPanel.showWidget( 0 ); return recurrenceGB; } private void createTemporalMap() { // must come after creation of temporal panels assert dailyEditor != null : "Temporal panels must be initialized before calling createTemporalCombo."; //$NON-NLS-1$ temporalPanelMap.put( TemporalValue.SECONDS, secondlyEditor ); temporalPanelMap.put( TemporalValue.MINUTES, minutelyEditor ); temporalPanelMap.put( TemporalValue.HOURS, hourlyEditor ); temporalPanelMap.put( TemporalValue.DAILY, dailyEditor ); temporalPanelMap.put( TemporalValue.WEEKLY, weeklyEditor ); temporalPanelMap.put( TemporalValue.MONTHLY, monthlyEditor ); temporalPanelMap.put( TemporalValue.YEARLY, yearlyEditor ); } public class SimpleRecurrencePanel extends VerticalPanel implements IChangeHandler { private TextBox valueTb = new TextBox(); private ErrorLabel valueLabel = null; private ICallback<IChangeHandler> onChangeHandler; public SimpleRecurrencePanel( String strLabel ) { HorizontalPanel hp = new HorizontalPanel(); hp.setStyleName( RECUR_PATTERN_HP ); Label l = new Label( Messages.getString( "schedule.every" ) ); l.setStyleName( "startLabel" ); //$NON-NLS-1$ hp.add( l ); valueTb.setTitle( Messages.getString( "schedule.numberOfXToRepeat", strLabel ) ); valueTb.setStyleName( EVERY_TXTBOX ); hp.add( valueTb ); l = new Label( strLabel ); l.setStyleName( "endLabel" ); //$NON-NLS-1$ hp.add( l ); valueLabel = new ErrorLabel( hp ); add( valueLabel ); configureOnChangeHandler(); } public String getValue() { return valueTb.getText(); } public void setValue( String val ) { valueTb.setText( val ); } public void reset() { setValue( "" ); //$NON-NLS-1$ } public void setValueError( String errorMsg ) { valueLabel.setErrorMsg( errorMsg ); } public void setOnChangeHandler( ICallback<IChangeHandler> handler ) { this.onChangeHandler = handler; } private void changeHandler() { if ( null != onChangeHandler ) { onChangeHandler.onHandle( this ); } } private void configureOnChangeHandler() { final SimpleRecurrencePanel localThis = this; KeyboardListener keyboardListener = new KeyboardListener() { public void onKeyDown( Widget sender, char keyCode, int modifiers ) { } public void onKeyPress( Widget sender, char keyCode, int modifiers ) { } public void onKeyUp( Widget sender, char keyCode, int modifiers ) { localThis.changeHandler(); } }; valueTb.addKeyboardListener( keyboardListener ); } } public class SecondlyRecurrenceEditor extends SimpleRecurrencePanel { public SecondlyRecurrenceEditor() { super( Messages.getString( "seconds" ) ); } } public class MinutelyRecurrenceEditor extends SimpleRecurrencePanel { public MinutelyRecurrenceEditor() { super( Messages.getString( "schedule.minuteOrMinutes" ) ); } } public class HourlyRecurrenceEditor extends SimpleRecurrencePanel { public HourlyRecurrenceEditor() { super( Messages.getString( "schedule.hourOrHours" ) ); } } public class DailyRecurrenceEditor extends VerticalPanel implements IChangeHandler { private TextBox repeatValueTb = new TextBox(); protected RadioButton everyNDaysRb = new RadioButton( DAILY_RB_GROUP, Messages.getString( "schedule.every" ) ); protected RadioButton everyWeekdayRb = new RadioButton( DAILY_RB_GROUP, Messages.getString( "schedule.everyWeekDay" ) ); private ErrorLabel repeatLabel = null; private ICallback<IChangeHandler> onChangeHandler; public DailyRecurrenceEditor() { HorizontalPanel hp = new HorizontalPanel(); hp.setStyleName( RECUR_PATTERN_HP ); hp.getElement().setId( "daily-recur-hp" ); everyNDaysRb.setStyleName( "recurrenceRadioButton" ); //$NON-NLS-1$ everyNDaysRb.setChecked( true ); hp.add( everyNDaysRb ); repeatValueTb.setStyleName( EVERY_TXTBOX ); repeatValueTb.setTitle( Messages.getString( "schedule.numDaysToRepeat" ) ); hp.add( repeatValueTb ); Label l = new Label( Messages.getString( "schedule.dayOrDays" ) ); l.setStyleName( "endLabel" ); //$NON-NLS-1$ hp.add( l ); repeatLabel = new ErrorLabel( hp ); add( repeatLabel ); everyWeekdayRb.setStyleName( "recurrenceRadioButton" ); //$NON-NLS-1$ add( everyWeekdayRb ); configureOnChangeHandler(); } public void reset() { setRepeatValue( "" ); //$NON-NLS-1$ setEveryNDays(); } public String getRepeatValue() { return repeatValueTb.getText(); } public void setRepeatValue( String repeatValue ) { repeatValueTb.setText( repeatValue ); } public void setEveryNDays() { everyNDaysRb.setChecked( true ); everyWeekdayRb.setChecked( false ); } public boolean isEveryNDays() { return everyNDaysRb.isChecked(); } public void setEveryWeekday() { everyWeekdayRb.setChecked( true ); everyNDaysRb.setChecked( false ); } public boolean isEveryWeekday() { return everyWeekdayRb.isChecked(); } public void setRepeatError( String errorMsg ) { repeatLabel.setErrorMsg( errorMsg ); } public void setOnChangeHandler( ICallback<IChangeHandler> handler ) { this.onChangeHandler = handler; } private void changeHandler() { if ( null != onChangeHandler ) { onChangeHandler.onHandle( this ); } } private void configureOnChangeHandler() { final DailyRecurrenceEditor localThis = this; KeyboardListener keyboardListener = new KeyboardListener() { public void onKeyDown( Widget sender, char keyCode, int modifiers ) { } public void onKeyPress( Widget sender, char keyCode, int modifiers ) { } public void onKeyUp( Widget sender, char keyCode, int modifiers ) { localThis.changeHandler(); } }; ClickListener clickListener = new ClickListener() { public void onClick( Widget sender ) { localThis.changeHandler(); } }; repeatValueTb.addKeyboardListener( keyboardListener ); everyNDaysRb.addClickListener( clickListener ); everyNDaysRb.addKeyboardListener( keyboardListener ); everyWeekdayRb.addClickListener( clickListener ); everyWeekdayRb.addKeyboardListener( keyboardListener ); } } public class WeeklyRecurrenceEditor extends VerticalPanel implements IChangeHandler { protected Map<DayOfWeek, CheckBox> dayToCheckBox = new HashMap<DayOfWeek, CheckBox>(); private ErrorLabel everyWeekOnLabel = null; private ICallback<IChangeHandler> onChangeHandler; private static final String WEEKLY_RECUR = "weekly-recur"; public WeeklyRecurrenceEditor() { setStyleName( "weeklyRecurrencePanel" ); //$NON-NLS-1$ Label l = new Label( Messages.getString( "schedule.recurEveryWeek" ) ); everyWeekOnLabel = new ErrorLabel( l ); l.setStyleName( "startLabel" ); //$NON-NLS-1$ add( everyWeekOnLabel ); FlexTable gp = new FlexTable(); gp.getElement().setId( WEEKLY_RECUR ); gp.setCellPadding( 0 ); gp.setCellSpacing( 0 ); // add Sun - Wed final int ITEMS_IN_ROW = 4; for ( int ii = 0; ii < ITEMS_IN_ROW; ++ii ) { DayOfWeek day = DayOfWeek.get( ii ); CheckBox cb = new CheckBox( Messages.getString( day.toString() ) ); cb.setStylePrimaryName( DOW_CHECKBOX ); gp.setWidget( 0, ii, cb ); dayToCheckBox.put( day, cb ); } // Add Thur - Sat for ( int ii = ITEMS_IN_ROW; ii < DayOfWeek.length(); ++ii ) { DayOfWeek day = DayOfWeek.get( ii ); CheckBox cb = new CheckBox( Messages.getString( day.toString() ) ); cb.setStylePrimaryName( DOW_CHECKBOX ); gp.setWidget( 1, ii - 4, cb ); dayToCheckBox.put( day, cb ); } add( gp ); configureOnChangeHandler(); } public void reset() { for ( DayOfWeek d : dayToCheckBox.keySet() ) { CheckBox cb = dayToCheckBox.get( d ); cb.setChecked( false ); } } public List<DayOfWeek> getCheckedDays() { ArrayList<DayOfWeek> checkedDays = new ArrayList<DayOfWeek>(); for ( DayOfWeek d : EnumSet.range( DayOfWeek.SUN, DayOfWeek.SAT ) ) { CheckBox cb = dayToCheckBox.get( d ); if ( cb.isChecked() ) { checkedDays.add( d ); } } return checkedDays; } /** * * @param valueOfSunday * int used to adjust the starting point of the weekday sequence. If this value is 0, Sun-Sat maps to * 0-6, if this value is 1, Sun-Sat maps to 1-7, etc. * @return String comma separated list of numeric days of the week. */ public String getCheckedDaysAsString( int valueOfSunday ) { StringBuilder sb = new StringBuilder(); for ( DayOfWeek d : getCheckedDays() ) { sb.append( Integer.toString( d.value() + valueOfSunday ) ).append( "," ); //$NON-NLS-1$ } sb.deleteCharAt( sb.length() - 1 ); return sb.toString(); } /** * * @param valueOfSunday * int used to adjust the starting point of the weekday sequence. If this value is 0, Sun-Sat maps to * 0-6, if this value is 1, Sun-Sat maps to 1-7, etc. * @return String comma separated list of numeric days of the week. */ public void setCheckedDaysAsString( String strDays, int valueOfSunday ) { String[] days = strDays.split( "," ); //$NON-NLS-1$ for ( String day : days ) { int intDay = Integer.parseInt( day ) - valueOfSunday; DayOfWeek dayOfWeek = DayOfWeek.get( intDay ); CheckBox cb = dayToCheckBox.get( dayOfWeek ); cb.setChecked( true ); } } public int getNumCheckedDays() { int numCheckedDays = 0; // for ( DayOfWeek d : EnumSet.range( DayOfWeek.SUN, DayOfWeek.SAT) ) { for ( Map.Entry<DayOfWeek, CheckBox> cbEntry : dayToCheckBox.entrySet() ) { if ( cbEntry.getValue().isChecked() ) { numCheckedDays++; } } return numCheckedDays; } public void setEveryDayOnError( String errorMsg ) { everyWeekOnLabel.setErrorMsg( errorMsg ); } public void setOnChangeHandler( ICallback<IChangeHandler> handler ) { this.onChangeHandler = handler; } private void changeHandler() { if ( null != onChangeHandler ) { onChangeHandler.onHandle( this ); } } private void configureOnChangeHandler() { final WeeklyRecurrenceEditor localThis = this; KeyboardListener keyboardListener = new KeyboardListener() { public void onKeyDown( Widget sender, char keyCode, int modifiers ) { } public void onKeyPress( Widget sender, char keyCode, int modifiers ) { } public void onKeyUp( Widget sender, char keyCode, int modifiers ) { localThis.changeHandler(); } }; ClickListener clickListener = new ClickListener() { public void onClick( Widget sender ) { localThis.changeHandler(); } }; for ( DayOfWeek d : dayToCheckBox.keySet() ) { CheckBox cb = dayToCheckBox.get( d ); cb.addClickListener( clickListener ); cb.addKeyboardListener( keyboardListener ); } } } public class MonthlyRecurrenceEditor extends VerticalPanel implements IChangeHandler { protected RadioButton dayNOfMonthRb = new RadioButton( MONTHLY_RB_GROUP, Messages.getString( "schedule.day" ) ); protected RadioButton nthDayNameOfMonthRb = new RadioButton( MONTHLY_RB_GROUP, Messages.getString( "schedule.the" ) ); private TextBox dayOfMonthTb = new TextBox(); private ListBox whichWeekLb = createWhichWeekListBox(); private ListBox dayOfWeekLb = createDayOfWeekListBox(); private ErrorLabel dayNOfMonthLabel = null; private ICallback<IChangeHandler> onChangeHandler; public MonthlyRecurrenceEditor() { setSpacing( 6 ); this.setStyleName( RECUR_PATTERN_HP ); getElement().removeAttribute( "cellpadding" ); HorizontalPanel hp = new HorizontalPanel(); hp.getElement().setId( "day-n-of-month-radio" ); dayNOfMonthRb.setStyleName( "recurrenceRadioButton" ); //$NON-NLS-1$ dayNOfMonthRb.setChecked( true ); hp.add( dayNOfMonthRb ); dayOfMonthTb.setStyleName( EVERY_TXTBOX ); hp.add( dayOfMonthTb ); Label l = new Label( Messages.getString( "schedule.ofEveryMonth" ) ); l.setStyleName( "endLabel" ); //$NON-NLS-1$ hp.add( l ); dayNOfMonthLabel = new ErrorLabel( hp ); add( dayNOfMonthLabel ); hp = new HorizontalPanel(); nthDayNameOfMonthRb.setStyleName( "recurrenceRadioButton" ); //$NON-NLS-1$ hp.add( nthDayNameOfMonthRb ); hp.add( whichWeekLb ); dayOfWeekLb.getElement().setId( "day-of-week-lb" ); hp.add( dayOfWeekLb ); l = new Label( Messages.getString( "schedule.ofEveryMonth" ) ); l.setStyleName( "endLabel" ); //$NON-NLS-1$ hp.add( l ); add( hp ); configureOnChangeHandler(); } public void reset() { setDayNOfMonth(); setDayOfMonth( "" ); //$NON-NLS-1$ setWeekOfMonth( WeekOfMonth.FIRST ); setDayOfWeek( DayOfWeek.SUN ); } public void setDayNOfMonth() { dayNOfMonthRb.setChecked( true ); nthDayNameOfMonthRb.setChecked( false ); } public boolean isDayNOfMonth() { return dayNOfMonthRb.isChecked(); } public void setNthDayNameOfMonth() { nthDayNameOfMonthRb.setChecked( true ); dayNOfMonthRb.setChecked( false ); } public boolean isNthDayNameOfMonth() { return nthDayNameOfMonthRb.isChecked(); } public String getDayOfMonth() { return dayOfMonthTb.getText(); } public void setDayOfMonth( String dayOfMonth ) { dayOfMonthTb.setText( dayOfMonth ); } public WeekOfMonth getWeekOfMonth() { return WeekOfMonth.get( whichWeekLb.getSelectedIndex() ); } public void setWeekOfMonth( WeekOfMonth week ) { whichWeekLb.setSelectedIndex( week.value() ); } public DayOfWeek getDayOfWeek() { return DayOfWeek.get( dayOfWeekLb.getSelectedIndex() ); } public void setDayOfWeek( DayOfWeek day ) { dayOfWeekLb.setSelectedIndex( day.value() ); } public void setDayNOfMonthError( String errorMsg ) { dayNOfMonthLabel.setErrorMsg( errorMsg ); } public void setOnChangeHandler( ICallback<IChangeHandler> handler ) { this.onChangeHandler = handler; } private void changeHandler() { if ( null != onChangeHandler ) { onChangeHandler.onHandle( this ); } } private void configureOnChangeHandler() { final MonthlyRecurrenceEditor localThis = this; KeyboardListener keyboardListener = new KeyboardListener() { public void onKeyDown( Widget sender, char keyCode, int modifiers ) { } public void onKeyPress( Widget sender, char keyCode, int modifiers ) { } public void onKeyUp( Widget sender, char keyCode, int modifiers ) { localThis.changeHandler(); } }; ClickListener clickListener = new ClickListener() { public void onClick( Widget sender ) { localThis.changeHandler(); } }; ChangeListener changeListener = new ChangeListener() { public void onChange( Widget sender ) { localThis.changeHandler(); } }; dayNOfMonthRb.addClickListener( clickListener ); dayNOfMonthRb.addKeyboardListener( keyboardListener ); nthDayNameOfMonthRb.addClickListener( clickListener ); nthDayNameOfMonthRb.addKeyboardListener( keyboardListener ); dayOfMonthTb.addKeyboardListener( keyboardListener ); whichWeekLb.addChangeListener( changeListener ); dayOfWeekLb.addChangeListener( changeListener ); } } public class YearlyRecurrenceEditor extends VerticalPanel implements IChangeHandler { protected RadioButton everyMonthOnNthDayRb = new RadioButton( YEARLY_RB_GROUP, Messages.getString( "schedule.every" ) ); protected RadioButton nthDayNameOfMonthNameRb = new RadioButton( YEARLY_RB_GROUP, Messages.getString( "schedule.the" ) ); private TextBox dayOfMonthTb = new TextBox(); private ListBox monthOfYearLb0 = createMonthOfYearListBox(); private ListBox monthOfYearLb1 = createMonthOfYearListBox(); private ListBox whichWeekLb = createWhichWeekListBox(); private ListBox dayOfWeekLb = createDayOfWeekListBox(); private ErrorLabel dayOfMonthLabel = null; private ICallback<IChangeHandler> onChangeHandler; private static final String YEARLY_RB_GROUP = "yearly-group"; //$NON-NLS-1$ public YearlyRecurrenceEditor() { setSpacing( 6 ); this.setStyleName( RECUR_PATTERN_HP ); getElement().removeAttribute( "cellpadding" ); HorizontalPanel p = new HorizontalPanel(); p.getElement().setId( "every-month-on-nth-day-radio" ); everyMonthOnNthDayRb.setStyleName( "recurrenceRadioButton" ); //$NON-NLS-1$ everyMonthOnNthDayRb.setChecked( true ); p.add( everyMonthOnNthDayRb ); p.add( monthOfYearLb0 ); dayOfMonthTb.addStyleName( "DAY_OF_MONTH_TB" ); //$NON-NLS-1$ dayOfMonthTb.addStyleName( EVERY_TXTBOX ); dayOfMonthTb.getElement().setId( "day-of-month-tb" ); p.add( dayOfMonthTb ); dayOfMonthLabel = new ErrorLabel( p ); add( dayOfMonthLabel ); p = new HorizontalPanel(); nthDayNameOfMonthNameRb.setStyleName( "recurrenceRadioButton" ); //$NON-NLS-1$ p.add( nthDayNameOfMonthNameRb ); p.add( whichWeekLb ); dayOfWeekLb.getElement().setId( "day-of-week-lb" ); p.add( dayOfWeekLb ); Label l = new Label( Messages.getString( "schedule.of" ) ); l.setStyleName( "middleLabel" ); //$NON-NLS-1$ p.add( l ); p.add( monthOfYearLb1 ); add( p ); configureOnChangeHandler(); } public void reset() { setEveryMonthOnNthDay(); setMonthOfYear0( MonthOfYear.JAN ); setDayOfMonth( "" ); //$NON-NLS-1$ setWeekOfMonth( WeekOfMonth.FIRST ); setDayOfWeek( DayOfWeek.SUN ); setMonthOfYear1( MonthOfYear.JAN ); } public boolean isEveryMonthOnNthDay() { return everyMonthOnNthDayRb.isChecked(); } public void setEveryMonthOnNthDay() { everyMonthOnNthDayRb.setChecked( true ); nthDayNameOfMonthNameRb.setChecked( false ); } public boolean isNthDayNameOfMonthName() { return nthDayNameOfMonthNameRb.isChecked(); } public void setNthDayNameOfMonthName() { nthDayNameOfMonthNameRb.setChecked( true ); everyMonthOnNthDayRb.setChecked( false ); } public String getDayOfMonth() { return dayOfMonthTb.getText(); } public void setDayOfMonth( String dayOfMonth ) { dayOfMonthTb.setText( dayOfMonth ); } public WeekOfMonth getWeekOfMonth() { return WeekOfMonth.get( whichWeekLb.getSelectedIndex() ); } public void setWeekOfMonth( WeekOfMonth week ) { whichWeekLb.setSelectedIndex( week.value() ); } public DayOfWeek getDayOfWeek() { return DayOfWeek.get( dayOfWeekLb.getSelectedIndex() ); } public void setDayOfWeek( DayOfWeek day ) { dayOfWeekLb.setSelectedIndex( day.value() ); } public MonthOfYear getMonthOfYear0() { return MonthOfYear.get( monthOfYearLb0.getSelectedIndex() ); } public void setMonthOfYear0( MonthOfYear month ) { monthOfYearLb0.setSelectedIndex( month.value() ); } public MonthOfYear getMonthOfYear1() { return MonthOfYear.get( monthOfYearLb1.getSelectedIndex() ); } public void setMonthOfYear1( MonthOfYear month ) { monthOfYearLb1.setSelectedIndex( month.value() ); } public void setDayOfMonthError( String errorMsg ) { dayOfMonthLabel.setErrorMsg( errorMsg ); } public void setOnChangeHandler( ICallback<IChangeHandler> handler ) { this.onChangeHandler = handler; } private void changeHandler() { if ( null != onChangeHandler ) { onChangeHandler.onHandle( this ); } } private void configureOnChangeHandler() { final YearlyRecurrenceEditor localThis = this; KeyboardListener keyboardListener = new KeyboardListener() { public void onKeyDown( Widget sender, char keyCode, int modifiers ) { } public void onKeyPress( Widget sender, char keyCode, int modifiers ) { } public void onKeyUp( Widget sender, char keyCode, int modifiers ) { localThis.changeHandler(); } }; ClickListener clickListener = new ClickListener() { public void onClick( Widget sender ) { localThis.changeHandler(); } }; ChangeListener changeListener = new ChangeListener() { public void onChange( Widget sender ) { localThis.changeHandler(); } }; everyMonthOnNthDayRb.addClickListener( clickListener ); everyMonthOnNthDayRb.addKeyboardListener( keyboardListener ); nthDayNameOfMonthNameRb.addClickListener( clickListener ); nthDayNameOfMonthNameRb.addKeyboardListener( keyboardListener ); dayOfMonthTb.addKeyboardListener( keyboardListener ); monthOfYearLb0.addChangeListener( changeListener ); monthOfYearLb1.addChangeListener( changeListener ); whichWeekLb.addChangeListener( changeListener ); dayOfWeekLb.addChangeListener( changeListener ); } } private ListBox createDayOfWeekListBox() { ListBox l = new ListBox(); for ( int ii = 0; ii < DayOfWeek.length(); ++ii ) { DayOfWeek day = DayOfWeek.get( ii ); l.addItem( Messages.getString( day.toString() ) ); } return l; } private ListBox createMonthOfYearListBox() { ListBox l = new ListBox(); for ( int ii = 0; ii < MonthOfYear.length(); ++ii ) { MonthOfYear month = MonthOfYear.get( ii ); l.addItem( Messages.getString( month.toString() ) ); } return l; } private ListBox createWhichWeekListBox() { ListBox l = new ListBox(); for ( WeekOfMonth week : EnumSet.range( WeekOfMonth.FIRST, WeekOfMonth.LAST ) ) { l.addItem( Messages.getString( week.toString() ) ); } return l; } private void selectTemporalPanel( TemporalValue selectedTemporalValue ) { int i = 0; for ( Map.Entry<TemporalValue, Panel> me : temporalPanelMap.entrySet() ) { if ( me.getKey().equals( selectedTemporalValue ) ) { deckPanel.showWidget( i ); break; } i++; } } /** * * @return null if the selected schedule does not support repeat-in-seconds, otherwise return the number of * seconds between schedule execution. * @throws RuntimeException * if the temporal value (tv) is invalid. This condition occurs as a result of programmer error. */ public Long getRepeatInSecs() throws RuntimeException { switch ( temporalState ) { case WEEKLY: // fall through case MONTHLY: // fall through case YEARLY: return null; case SECONDS: return Long.parseLong( secondlyEditor.getValue() ); case MINUTES: return TimeUtil.minutesToSecs( Long.parseLong( minutelyEditor.getValue() ) ); case HOURS: return TimeUtil.hoursToSecs( Long.parseLong( hourlyEditor.getValue() ) ); case DAILY: return TimeUtil.daysToSecs( Long.parseLong( dailyEditor.getRepeatValue() ) ); default: throw new RuntimeException( Messages.getString( "schedule.invalidTemporalValueInGetRepeatInSecs", temporalState.toString() ) ); } } /** * * @return null if the selected schedule does not support CRON, otherwise return the CRON string. * @throws RuntimeException * if the temporal value (tv) is invalid. This condition occurs as a result of programmer error. */ public String getCronString() throws RuntimeException { switch ( temporalState ) { case SECONDS: // fall through case MINUTES: // fall through case HOURS: return null; case DAILY: return getDailyCronString(); case WEEKLY: return getWeeklyCronString(); case MONTHLY: return getMonthlyCronString(); case YEARLY: return getYearlyCronString(); default: throw new RuntimeException( Messages.getString( "schedule.invalidTemporalValueInGetCronString", temporalState.toString() ) ); } } public boolean isEveryNDays() { return ( temporalState == TemporalValue.DAILY ) && dailyEditor.isEveryNDays(); } public MonthOfYear getSelectedMonth() { MonthOfYear selectedMonth = null; if ( ( temporalState == TemporalValue.YEARLY ) && yearlyEditor.isNthDayNameOfMonthName() ) { selectedMonth = yearlyEditor.getMonthOfYear1(); } else if ( ( temporalState == TemporalValue.YEARLY ) && yearlyEditor.isEveryMonthOnNthDay() ) { selectedMonth = yearlyEditor.getMonthOfYear0(); } return selectedMonth; } public List<DayOfWeek> getSelectedDaysOfWeek() { ArrayList<DayOfWeek> selectedDaysOfWeek = new ArrayList<DayOfWeek>(); if ( ( temporalState == TemporalValue.DAILY ) && !dailyEditor.isEveryNDays() ) { selectedDaysOfWeek.add( DayOfWeek.MON ); selectedDaysOfWeek.add( DayOfWeek.TUE ); selectedDaysOfWeek.add( DayOfWeek.WED ); selectedDaysOfWeek.add( DayOfWeek.THU ); selectedDaysOfWeek.add( DayOfWeek.FRI ); } else if ( temporalState == TemporalValue.WEEKLY ) { selectedDaysOfWeek.addAll( weeklyEditor.getCheckedDays() ); } else if ( ( temporalState == TemporalValue.MONTHLY ) && monthlyEditor.isNthDayNameOfMonth() ) { selectedDaysOfWeek.add( monthlyEditor.getDayOfWeek() ); } else if ( ( temporalState == TemporalValue.YEARLY ) && yearlyEditor.isNthDayNameOfMonthName() ) { selectedDaysOfWeek.add( yearlyEditor.getDayOfWeek() ); } return selectedDaysOfWeek; } public WeekOfMonth getSelectedWeekOfMonth() { WeekOfMonth selectedWeekOfMonth = null; if ( ( temporalState == TemporalValue.MONTHLY ) && monthlyEditor.isNthDayNameOfMonth() ) { selectedWeekOfMonth = monthlyEditor.getWeekOfMonth(); } else if ( ( temporalState == TemporalValue.YEARLY ) && yearlyEditor.isNthDayNameOfMonthName() ) { selectedWeekOfMonth = yearlyEditor.getWeekOfMonth(); } return selectedWeekOfMonth; } public Integer getSelectedDayOfMonth() { Integer selectedDayOfMonth = null; if ( ( temporalState == TemporalValue.MONTHLY ) && monthlyEditor.isDayNOfMonth() ) { try { selectedDayOfMonth = Integer.parseInt( monthlyEditor.getDayOfMonth() ); } catch ( Exception ex ) { //ignored } } else if ( ( temporalState == TemporalValue.YEARLY ) && yearlyEditor.isEveryMonthOnNthDay() ) { try { selectedDayOfMonth = Integer.parseInt( yearlyEditor.getDayOfMonth() ); } catch ( Exception ex ) { //ignored } } return selectedDayOfMonth; } /** * * @return * @throws RuntimeException */ protected String getDailyCronString() throws RuntimeException { String cronStr; StringBuilder recurrenceSb = new StringBuilder(); if ( dailyEditor.isEveryNDays() ) { return null; } else { // must be every weekday recurrenceSb.append( RecurrenceType.EveryWeekday ).append( SPACE ).append( getTimeOfRecurrence() ); try { cronStr = CronParser.recurrenceStringToCronString( recurrenceSb.toString() ); } catch ( CronParseException e ) { throw new RuntimeException( Messages.getString( "schedule.invalidRecurrenceString", recurrenceSb.toString() ) ); } return cronStr; } } protected String getWeeklyCronString() throws RuntimeException { String cronStr; StringBuilder recurrenceSb = new StringBuilder(); // WeeklyOn 0 33 6 1,3,5 recurrenceSb.append( RecurrenceType.WeeklyOn ).append( SPACE ).append( getTimeOfRecurrence() ).append( SPACE ) .append( weeklyEditor.getCheckedDaysAsString( VALUE_OF_SUNDAY ) ); try { cronStr = CronParser.recurrenceStringToCronString( recurrenceSb.toString() ); } catch ( CronParseException e ) { throw new RuntimeException( Messages.getString( "schedule.invalidRecurrenceString", recurrenceSb.toString() ) ); } return cronStr; } protected String getMonthlyCronString() throws RuntimeException { String cronStr; StringBuilder recurrenceSb = new StringBuilder(); if ( monthlyEditor.isDayNOfMonth() ) { recurrenceSb.append( RecurrenceType.DayNOfMonth ).append( SPACE ).append( getTimeOfRecurrence() ).append( SPACE ) .append( monthlyEditor.getDayOfMonth() ); } else if ( monthlyEditor.isNthDayNameOfMonth() ) { if ( monthlyEditor.getWeekOfMonth() != WeekOfMonth.LAST ) { String weekOfMonth = Integer.toString( monthlyEditor.getWeekOfMonth().value() + 1 ); String dayOfWeek = Integer.toString( monthlyEditor.getDayOfWeek().value() + 1 ); recurrenceSb.append( RecurrenceType.NthDayNameOfMonth ).append( SPACE ).append( getTimeOfRecurrence() ).append( SPACE ).append( dayOfWeek ).append( SPACE ).append( weekOfMonth ); } else { String dayOfWeek = Integer.toString( monthlyEditor.getDayOfWeek().value() + 1 ); recurrenceSb.append( RecurrenceType.LastDayNameOfMonth ).append( SPACE ).append( getTimeOfRecurrence() ) .append( SPACE ).append( dayOfWeek ); } } else { throw new RuntimeException( Messages.getString( "schedule.noRadioBtnsSelected" ) ); } try { cronStr = CronParser.recurrenceStringToCronString( recurrenceSb.toString() ); } catch ( CronParseException e ) { throw new RuntimeException( Messages.getString( "schedule.invalidRecurrenceString", recurrenceSb.toString() ) ); } return cronStr; } protected String getYearlyCronString() throws RuntimeException { String cronStr; StringBuilder recurrenceSb = new StringBuilder(); if ( yearlyEditor.isEveryMonthOnNthDay() ) { String monthOfYear = Integer.toString( yearlyEditor.getMonthOfYear0().value() + 1 ); recurrenceSb.append( RecurrenceType.EveryMonthNameN ).append( SPACE ).append( getTimeOfRecurrence() ).append( SPACE ).append( yearlyEditor.getDayOfMonth() ).append( SPACE ).append( monthOfYear ); } else if ( yearlyEditor.isNthDayNameOfMonthName() ) { if ( yearlyEditor.getWeekOfMonth() != WeekOfMonth.LAST ) { String monthOfYear = Integer.toString( yearlyEditor.getMonthOfYear1().value() + 1 ); String dayOfWeek = Integer.toString( yearlyEditor.getDayOfWeek().value() + 1 ); String weekOfMonth = Integer.toString( yearlyEditor.getWeekOfMonth().value() + 1 ); recurrenceSb.append( RecurrenceType.NthDayNameOfMonthName ).append( SPACE ).append( getTimeOfRecurrence() ) .append( SPACE ).append( dayOfWeek ).append( SPACE ).append( weekOfMonth ).append( SPACE ).append( monthOfYear ); } else { String monthOfYear = Integer.toString( yearlyEditor.getMonthOfYear1().value() + 1 ); String dayOfWeek = Integer.toString( yearlyEditor.getDayOfWeek().value() + 1 ); recurrenceSb.append( RecurrenceType.LastDayNameOfMonthName ).append( SPACE ).append( getTimeOfRecurrence() ) .append( SPACE ).append( dayOfWeek ).append( SPACE ).append( monthOfYear ); } } else { throw new RuntimeException( Messages.getString( "schedule.noRadioBtnsSelected" ) ); } try { cronStr = CronParser.recurrenceStringToCronString( recurrenceSb.toString() ); } catch ( CronParseException e ) { throw new RuntimeException( Messages.getString( "schedule.invalidRecurrenceString", recurrenceSb.toString() ) ); } return cronStr; } private StringBuilder getTimeOfRecurrence() { int timeOfDayAdjust = ( startTimePicker.getTimeOfDay().equals( TimeUtil.TimeOfDay.AM ) ) ? TimeUtil.MIN_HOUR // 0 : TimeUtil.MAX_HOUR; // 12 String strHour = StringUtils.addStringToInt( startTimePicker.getHour(), timeOfDayAdjust ); return new StringBuilder().append( "00" ).append( SPACE ) //$NON-NLS-1$ .append( startTimePicker.getMinute() ).append( SPACE ).append( strHour ); } // TODO sbarkdull // private static DateFormat dateFormatter = DateFormat.getDateInstance(DateFormat.LONG, Locale.getDefault()); public void setStartTime( String startTime ) { startTimePicker.setTime( startTime ); } public String getStartTime() { return startTimePicker.getTime(); } public void setStartDate( Date startDate ) { dateRangeEditor.setStartDate( startDate ); } public Date getStartDate() { return dateRangeEditor.getStartDate(); } public void setEndDate( Date endDate ) { dateRangeEditor.setEndDate( endDate ); } public Date getEndDate() { return dateRangeEditor.getEndDate(); } public void setNoEndDate() { dateRangeEditor.setNoEndDate(); } public void setEndBy() { dateRangeEditor.setEndBy(); } public TemporalValue getTemporalState() { return temporalState; } public void setTemporalState( TemporalValue temporalState ) { this.temporalState = temporalState; selectTemporalPanel( temporalState ); } /** * NOTE: should only ever be used by validators. This is a backdoor into this class that shouldn't be here, do * not use this method unless you are validating. * * @return DateRangeEditor */ public DateRangeEditor getDateRangeEditor() { return dateRangeEditor; } /** * NOTE: should only ever be used by validators. This is a backdoor into this class that shouldn't be here, do * not use this method unless you are validating. * * @return SecondlyRecurrencePanel */ public SecondlyRecurrenceEditor getSecondlyEditor() { return secondlyEditor; } /** * NOTE: should only ever be used by validators. This is a backdoor into this class that shouldn't be here, do * not use this method unless you are validating. * * @return MinutelyRecurrencePanel */ public MinutelyRecurrenceEditor getMinutelyEditor() { return minutelyEditor; } /** * NOTE: should only ever be used by validators. This is a backdoor into this class that shouldn't be here, do * not use this method unless you are validating. * * @return HourlyRecurrencePanel */ public HourlyRecurrenceEditor getHourlyEditor() { return hourlyEditor; } /** * NOTE: should only ever be used by validators. This is a backdoor into this class that shouldn't be here, do * not use this method unless you are validating. * * @return DailyRecurrencePanel */ public DailyRecurrenceEditor getDailyEditor() { return dailyEditor; } /** * NOTE: should only ever be used by validators. This is a backdoor into this class that shouldn't be here, do * not use this method unless you are validating. * * @return WeeklyRecurrencePanel */ public WeeklyRecurrenceEditor getWeeklyEditor() { return weeklyEditor; } /** * NOTE: should only ever be used by validators. This is a backdoor into this class that shouldn't be here, do * not use this method unless you are validating. * * @return MonthlyRecurrencePanel */ public MonthlyRecurrenceEditor getMonthlyEditor() { return monthlyEditor; } /** * NOTE: should only ever be used by validators. This is a backdoor into this class that shouldn't be here, do * not use this method unless you are validating. * * @return YearlyRecurrencePanel */ public YearlyRecurrenceEditor getYearlyEditor() { return yearlyEditor; } public void setOnChangeHandler( ICallback<IChangeHandler> handler ) { this.onChangeHandler = handler; } private void changeHandler() { if ( null != onChangeHandler ) { onChangeHandler.onHandle( this ); } } private void configureOnChangeHandler() { final RecurrenceEditor localThis = this; ICallback<IChangeHandler> handler = new ICallback<IChangeHandler>() { public void onHandle( IChangeHandler o ) { localThis.changeHandler(); } }; startTimePicker.setOnChangeHandler( handler ); dateRangeEditor.setOnChangeHandler( handler ); secondlyEditor.setOnChangeHandler( handler ); minutelyEditor.setOnChangeHandler( handler ); hourlyEditor.setOnChangeHandler( handler ); dailyEditor.setOnChangeHandler( handler ); weeklyEditor.setOnChangeHandler( handler ); monthlyEditor.setOnChangeHandler( handler ); yearlyEditor.setOnChangeHandler( handler ); } }