001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.acacia.client.widgets.serialdate;
029
030import org.opencms.acacia.client.css.I_CmsWidgetsLayoutBundle;
031import org.opencms.acacia.shared.I_CmsSerialDateValue.EndType;
032import org.opencms.acacia.shared.I_CmsSerialDateValue.PatternType;
033import org.opencms.ade.contenteditor.client.Messages;
034import org.opencms.gwt.client.ui.CmsFieldSet;
035import org.opencms.gwt.client.ui.CmsPopup;
036import org.opencms.gwt.client.ui.CmsPushButton;
037import org.opencms.gwt.client.ui.CmsScrollPanel;
038import org.opencms.gwt.client.ui.css.I_CmsInputLayoutBundle;
039import org.opencms.gwt.client.ui.input.CmsCheckBox;
040import org.opencms.gwt.client.ui.input.CmsLabel;
041import org.opencms.gwt.client.ui.input.CmsRadioButton;
042import org.opencms.gwt.client.ui.input.CmsRadioButtonGroup;
043import org.opencms.gwt.client.ui.input.datebox.CmsDateBox;
044import org.opencms.gwt.client.ui.input.datebox.CmsDateBoxEvent;
045import org.opencms.util.CmsPair;
046
047import java.util.Collection;
048import java.util.Date;
049import java.util.HashMap;
050import java.util.Map;
051
052import com.google.gwt.core.shared.GWT;
053import com.google.gwt.dom.client.Style;
054import com.google.gwt.dom.client.Style.Unit;
055import com.google.gwt.event.dom.client.ClickEvent;
056import com.google.gwt.event.dom.client.ClickHandler;
057import com.google.gwt.event.dom.client.FocusEvent;
058import com.google.gwt.event.dom.client.FocusHandler;
059import com.google.gwt.event.logical.shared.CloseEvent;
060import com.google.gwt.event.logical.shared.CloseHandler;
061import com.google.gwt.event.logical.shared.ValueChangeEvent;
062import com.google.gwt.event.logical.shared.ValueChangeHandler;
063import com.google.gwt.uibinder.client.UiBinder;
064import com.google.gwt.uibinder.client.UiField;
065import com.google.gwt.uibinder.client.UiHandler;
066import com.google.gwt.user.client.ui.Composite;
067import com.google.gwt.user.client.ui.FlowPanel;
068import com.google.gwt.user.client.ui.Label;
069import com.google.gwt.user.client.ui.SimplePanel;
070import com.google.gwt.user.client.ui.VerticalPanel;
071import com.google.gwt.user.client.ui.Widget;
072
073/** The serial date widgets UI. */
074public class CmsSerialDateView extends Composite
075implements I_CmsSerialDateValueChangeObserver, CloseHandler<CmsFieldSet> {
076
077    /** The UI binder interface. */
078    interface I_CmsSerialDateUiBinder extends UiBinder<Widget, CmsSerialDateView> {
079        // nothing to do
080    }
081
082    /** The UI binder instance. */
083    private static I_CmsSerialDateUiBinder uiBinder = GWT.create(I_CmsSerialDateUiBinder.class);
084
085    /* The status field */
086
087    /** Panel containing the field set for the exceptions. */
088    @UiField
089    protected FlowPanel m_exceptionsPanelContainer;
090
091    /** Controller. */
092    CmsSerialDateController m_controller;
093
094    /* 1. The dates panel. */
095
096    /** The check box, indicating if the event should be displayed as "current" till it ends (checked state), or only till it starts (unchecked). */
097    @UiField
098    CmsCheckBox m_currentTillEndCheckBox;
099
100    /** The daily pattern. */
101    CmsPatternPanelDailyView m_dailyPattern;
102
103    /** The panel with the basic dates. */
104    @UiField
105    FlowPanel m_datesPanel;
106
107    /** Panel only shown when the widget is deactivated. */
108    @UiField
109    FlowPanel m_deactivationPanel;
110
111    /** Information on the widget in deactivated state. */
112    @UiField
113    Label m_deactivationText;
114
115    /** The panel with the serial date duration options. */
116    @UiField
117    FlowPanel m_durationPanel;
118
119    /** The end time label. */
120    @UiField
121    Label m_endLabel;
122
123    /* 2. The serial options panel */
124
125    /** The ends after radio button. */
126    @UiField(provided = true)
127    CmsRadioButton m_endsAfterRadioButton;
128
129    /* 2.1 The pattern options */
130
131    /** The ends at radio button. */
132    @UiField(provided = true)
133    CmsRadioButton m_endsAtRadioButton;
134
135    /** The end date box. */
136    @UiField
137    CmsDateBox m_endTime;
138
139    /** The UI element for the list with exceptions. */
140    @UiField(provided = true)
141    CmsCheckableDatePanel m_exceptionsList;
142
143    /** The panel with the serial date exceptions. */
144    @UiField
145    CmsFieldSet m_exceptionsPanel;
146
147    /** The individual pattern. */
148    CmsPatternPanelIndividualView m_individualPattern;
149
150    /* 3. The manage exceptions and preview button that triggers the preview pop-up. */
151    /** The button to manage exceptions. */
152    @UiField
153    CmsPushButton m_manageExceptionsButton;
154
155    /** Model. */
156    I_CmsObservableSerialDateValue m_model;
157
158    /* 2.2. The duration panel */
159
160    /** The monthly pattern. */
161    CmsPatternPanelMonthlyView m_monthlyPattern;
162
163    /** The times text box. */
164    @UiField
165    CmsFocusAwareTextBox m_occurrences;
166
167    /** The label that displays the dependency to another series. */
168    @UiField
169    CmsLabel m_origSeriesLabel;
170
171    /** The list shown in the pop-up panel to manage exceptions. */
172    CmsCheckableDatePanel m_overviewList;
173
174    /** The pop-up where the preview list is shown in. */
175    CmsPopup m_overviewPopup;
176
177    /** The label at the start of the duration line (text is "Ends"). */
178    @UiField
179    Label m_durationPrefixLabel;
180
181    /** The label after the occurrences text box (text is "times"). */
182    @UiField
183    Label m_durationAfterPostfixLabel;
184
185    /* 2.3. The exceptions panel */
186
187    /** The pattern options panel, where the pattern specific options are displayed. */
188    @UiField
189    SimplePanel m_patternOptions;
190
191    /** The panel with the serial date pattern options. */
192    @UiField
193    FlowPanel m_patternPanel;
194
195    /** The panel to place the radio buttons for pattern selection. */
196    @UiField
197    VerticalPanel m_patternRadioButtonsPanel;
198
199    /** The panel with all serial date options. */
200    @UiField
201    CmsFieldSet m_serialOptionsPanel;
202
203    /* 4. The preview & exceptions selection pop-up */
204
205    /** The preview list (with checkboxes to manage exceptions. */
206
207    /** The check box, indicating if the date is a serial date. */
208    @UiField
209    CmsCheckBox m_seriesCheckBox;
210
211    /* 5. Panel for de-active state */
212
213    /** The end datebox. */
214    @UiField
215    CmsDateBox m_seriesEndDate;
216
217    /** The start time label. */
218    @UiField
219    Label m_startLabel;
220
221    /* Member variables for managing the internal state. */
222
223    /** The start date box. */
224    @UiField
225    CmsDateBox m_startTime;
226
227    /** The label that displays the current status. */
228    @UiField
229    CmsLabel m_statusLabel;
230
231    /** The weekly pattern. */
232    CmsPatternPanelWeeklyView m_weeklyPattern;
233
234    /** The check box, indicating if the event should last the whole day. */
235    @UiField
236    CmsCheckBox m_wholeDayCheckBox;
237
238    /** The yearly pattern. */
239    CmsPatternPanelYearlyView m_yearlyPattern;
240
241    /** Format with date only. */
242    private String m_dateFormat = Messages.get().keyDefault(Messages.GUI_SERIALDATE_DATE_FORMAT_0, null);
243
244    /* Date and time formats */
245
246    /** Value of the radio group duration. */
247    private CmsRadioButtonGroup m_groupDuration;
248
249    /* Controller and model */
250
251    /** Value of the radio group pattern. */
252    private CmsRadioButtonGroup m_groupPattern;
253
254    /** Map from the various patterns to the radio buttons for chosing the patterns. */
255    private Map<PatternType, CmsRadioButton> m_patternButtons;
256
257    /** Flag, indicating if change actions should not be triggered. */
258    private boolean m_triggerChangeActions = true;
259
260    /** The pop-up panel's "update exceptions" button. */
261    private CmsPushButton m_updateExceptionsButton;
262
263    /**
264     * Category field widgets for ADE forms.<p>
265     * @param controller the controller to communicate with
266     * @param model the model to get values from
267     */
268    public CmsSerialDateView(CmsSerialDateController controller, I_CmsObservableSerialDateValue model) {
269
270        m_controller = controller;
271        m_model = model;
272        m_model.registerValueChangeObserver(this);
273        initDurationButtonGroup();
274        m_exceptionsList = new CmsCheckableDatePanel(m_dateFormat, CmsCheckableDatePanel.Style.THREE_COLUMNS, true);
275
276        // bind the ui
277        initWidget(uiBinder.createAndBindUi(this));
278        addStyleName(I_CmsInputLayoutBundle.INSTANCE.inputCss().highTextBoxes());
279
280        m_origSeriesLabel.setVisible(m_model.isFromOtherSeries());
281        m_origSeriesLabel.setText(Messages.get().key(Messages.GUI_SERIALDATE_FROM_SERIES_INFORMATION_0));
282
283        initPatternButtonGroup();
284        initDeactivationPanel();
285        initDatesPanel();
286        initSerialOptionsPanel();
287        initOverviewPopup();
288    }
289
290    /**
291     * @see com.google.gwt.event.logical.shared.CloseHandler#onClose(com.google.gwt.event.logical.shared.CloseEvent)
292     */
293    public void onClose(CloseEvent<CmsFieldSet> event) {
294
295        m_controller.sizeChanged();
296
297    }
298
299    /**
300     * @see org.opencms.acacia.client.widgets.serialdate.I_CmsSerialDateValueChangeObserver#onValueChange()
301     */
302    @Override
303    public void onValueChange() {
304
305        m_triggerChangeActions = false;
306        m_origSeriesLabel.setVisible(m_model.isFromOtherSeries());
307        m_startTime.setValue(m_model.getStart());
308        m_endTime.setValue(m_model.getEnd());
309        m_wholeDayCheckBox.setChecked(m_model.isWholeDay());
310        m_currentTillEndCheckBox.setChecked(m_model.isCurrentTillEnd());
311
312        onPatternChange();
313        m_triggerChangeActions = true;
314    }
315
316    /**
317     * Enable/disable the management button.
318     * @param enabled flag, indicating if the management button should be enabled.
319     */
320    public void setManagementButtonEnabled(boolean enabled) {
321
322        m_manageExceptionsButton.setEnabled(enabled);
323
324    }
325
326    /**
327     * Sets the current status.
328     * @param status the status to set.
329     */
330    public void setStatus(String status) {
331
332        m_statusLabel.setText(status);
333    }
334
335    /**
336     * Shows the provided list of dates as current dates.
337     * @param dates the current dates to show, accompanied with the information if they are exceptions or not.
338     */
339    public void showCurrentDates(Collection<CmsPair<Date, Boolean>> dates) {
340
341        m_overviewList.setDatesWithCheckState(dates);
342        m_overviewPopup.center();
343
344    }
345
346    /**
347     * Updates the exceptions panel.
348     */
349    public void updateExceptions() {
350
351        m_exceptionsList.setDates(m_model.getExceptions());
352        if (m_model.getExceptions().size() > 0) {
353            m_exceptionsPanel.setVisible(true);
354        } else {
355            m_exceptionsPanel.setVisible(false);
356        }
357    }
358
359    /**
360     * Returns a flag, indicating if change actions should be triggered.
361     * @return a flag, indicating if change actions should be triggered.
362     */
363    boolean handleChange() {
364
365        return m_triggerChangeActions;
366    }
367
368    /**
369     * Handle a "current till end" change event.
370     * @param event the change event.
371     */
372    @UiHandler("m_currentTillEndCheckBox")
373    void onCurrentTillEndChange(ValueChangeEvent<Boolean> event) {
374
375        if (handleChange()) {
376            m_controller.setCurrentTillEnd(event.getValue());
377        }
378    }
379
380    /**
381     * Handle an end time change.
382     * @param event the change event.
383     */
384    @UiHandler("m_endTime")
385    void onEndTimeChange(CmsDateBoxEvent event) {
386
387        if (handleChange() && !event.isUserTyping()) {
388            m_controller.setEndTime(event.getDate());
389        }
390    }
391
392    /**
393     * Called when the end type is changed.
394     */
395    void onEndTypeChange() {
396
397        EndType endType = m_model.getEndType();
398        m_groupDuration.selectButton(getDurationButtonForType(endType));
399        switch (endType) {
400            case DATE:
401            case TIMES:
402                m_durationPanel.setVisible(true);
403                m_seriesEndDate.setValue(m_model.getSeriesEndDate());
404                int occurrences = m_model.getOccurrences();
405                if (!m_occurrences.isFocused()) {
406                    m_occurrences.setFormValueAsString(occurrences > 0 ? "" + occurrences : "");
407                }
408                break;
409            default:
410                m_durationPanel.setVisible(false);
411                break;
412        }
413        updateExceptions();
414    }
415
416    /**
417     * Handler for click events on the manage exceptions button.
418     * @param e the click event.
419     */
420    @UiHandler("m_manageExceptionsButton")
421    void onManageExceptionClicked(ClickEvent e) {
422
423        if (handleChange()) {
424            m_controller.executeShowDatesAction();
425        }
426    }
427
428    /**
429     * Handles the ends after change event.<p>
430     *
431     * @param event the change event
432     */
433    @UiHandler("m_occurrences")
434    void onOccurrencesChange(ValueChangeEvent<String> event) {
435
436        if (handleChange()) {
437            m_controller.setOccurrences(m_occurrences.getFormValueAsString());
438        }
439    }
440
441    /**
442     * Handles the ends after focus event.<p>
443     *
444     * @param event the focus event
445     */
446    @UiHandler("m_occurrences")
447    void onOccurrencesFocus(FocusEvent event) {
448
449        if (handleChange()) {
450            m_groupDuration.selectButton(m_endsAfterRadioButton);
451        }
452    }
453
454    /**
455     * Called when the pattern has changed.
456     */
457    void onPatternChange() {
458
459        PatternType patternType = m_model.getPatternType();
460        boolean isSeries = !patternType.equals(PatternType.NONE);
461        setSerialOptionsVisible(isSeries);
462        m_seriesCheckBox.setChecked(isSeries);
463        if (isSeries) {
464            m_groupPattern.selectButton(m_patternButtons.get(patternType));
465            m_controller.getPatternView().onValueChange();
466            m_patternOptions.setWidget(m_controller.getPatternView());
467            onEndTypeChange();
468        }
469        m_controller.sizeChanged();
470    }
471
472    /**
473     * Handle changes of the series check box.
474     * @param event the change event.
475     */
476    @UiHandler("m_seriesCheckBox")
477    void onSeriesChange(ValueChangeEvent<Boolean> event) {
478
479        if (handleChange()) {
480            m_controller.setIsSeries(event.getValue());
481        }
482    }
483
484    /**
485     * Handles the end date change event.<p>
486     *
487     * @param event the change event
488     */
489    @UiHandler("m_seriesEndDate")
490    void onSeriesEndDateChange(CmsDateBoxEvent event) {
491
492        if (handleChange() && !event.isUserTyping()) {
493            m_controller.setSeriesEndDate(event.getDate());
494        }
495    }
496
497    /**
498     * Handles the focus event on the series end date date box.
499     * @param event the focus event
500     */
501    void onSeriesEndDateFocus(FocusEvent event) {
502
503        m_groupDuration.selectButton(m_endsAtRadioButton);
504
505    }
506
507    /**
508     * Handle a start time change.
509     *
510     * @param event the change event
511     */
512    @UiHandler("m_startTime")
513    void onStartTimeChange(CmsDateBoxEvent event) {
514
515        if (handleChange() && !event.isUserTyping()) {
516            m_controller.setStartTime(event.getDate());
517        }
518    }
519
520    /**
521     * Handle a whole day change event.
522     * @param event the change event.
523     */
524    @UiHandler("m_wholeDayCheckBox")
525    void onWholeDayChange(ValueChangeEvent<Boolean> event) {
526
527        //TODO: Improve - adjust time selections?
528        if (handleChange()) {
529            m_controller.setWholeDay(event.getValue());
530        }
531    }
532
533    /**
534     * Sets the radio buttons active or inactive.<p>
535     * @param active true or false to activate or deactivate
536     * */
537    void setActive(boolean active) {
538
539        m_deactivationPanel.setVisible(!active);
540        m_datesPanel.setVisible(active);
541        if (m_seriesCheckBox.getFormValue().booleanValue()) {
542            setSerialOptionsVisible(active);
543        }
544        m_controller.sizeChanged();
545    }
546
547    /**
548     * Creates a pattern choice radio button and adds it where necessary.
549     * @param pattern the pattern that should be chosen by the button.
550     * @param messageKey the message key for the button's label.
551     */
552    private void createAndAddButton(PatternType pattern, String messageKey) {
553
554        CmsRadioButton btn = new CmsRadioButton(pattern.toString(), Messages.get().key(messageKey));
555        btn.addStyleName(I_CmsWidgetsLayoutBundle.INSTANCE.widgetCss().radioButtonlabel());
556        btn.setGroup(m_groupPattern);
557        m_patternButtons.put(pattern, btn);
558        m_patternRadioButtonsPanel.add(btn);
559
560    }
561
562    /**
563     * Returns the duration button for type.<p>
564     *
565     * @param type the type
566     *
567     * @return the button
568     */
569    private CmsRadioButton getDurationButtonForType(EndType type) {
570
571        switch (type) {
572            case DATE:
573                return m_endsAtRadioButton;
574            default:
575                return m_endsAfterRadioButton;
576        }
577    }
578
579    /** Initialize dates panel elements. */
580    private void initDatesPanel() {
581
582        m_startLabel.setText(Messages.get().key(Messages.GUI_SERIALDATE_TIME_STARTTIME_0));
583        m_startTime.setAllowInvalidValue(true);
584        m_startTime.setValue(m_model.getStart());
585        m_endLabel.setText(Messages.get().key(Messages.GUI_SERIALDATE_TIME_ENDTIME_0));
586        m_endTime.setAllowInvalidValue(true);
587        m_endTime.setValue(m_model.getEnd());
588        m_seriesCheckBox.setText(Messages.get().key(Messages.GUI_SERIALDATE_SERIES_CHECKBOX_0));
589        m_wholeDayCheckBox.setText(Messages.get().key(Messages.GUI_SERIALDATE_WHOLE_DAY_CHECKBOX_0));
590        m_currentTillEndCheckBox.setText(Messages.get().key(Messages.GUI_SERIALDATE_CURRENT_TILL_END_CHECKBOX_0));
591        m_currentTillEndCheckBox.getButton().setTitle(
592            Messages.get().key(Messages.GUI_SERIALDATE_CURRENT_TILL_END_CHECKBOX_HELP_0));
593    }
594
595    /**
596     * Initialize elements of the panel displayed for the deactivated widget.
597     */
598    private void initDeactivationPanel() {
599
600        m_deactivationPanel.setVisible(false);
601        m_deactivationText.setText(Messages.get().key(Messages.GUI_SERIALDATE_DEACTIVE_TEXT_0));
602
603    }
604
605    /**
606     * Configure all UI elements in the "ending"-options panel.
607     */
608    private void initDurationButtonGroup() {
609
610        m_groupDuration = new CmsRadioButtonGroup();
611
612        m_endsAfterRadioButton = new CmsRadioButton(
613            EndType.TIMES.toString(),
614            Messages.get().key(Messages.GUI_SERIALDATE_DURATION_ENDTYPE_OCC_0));
615        m_endsAfterRadioButton.setGroup(m_groupDuration);
616        m_endsAtRadioButton = new CmsRadioButton(
617            EndType.DATE.toString(),
618            Messages.get().key(Messages.GUI_SERIALDATE_DURATION_ENDTYPE_DATE_0));
619        m_endsAtRadioButton.setGroup(m_groupDuration);
620        m_groupDuration.addValueChangeHandler(new ValueChangeHandler<String>() {
621
622            public void onValueChange(ValueChangeEvent<String> event) {
623
624                if (handleChange()) {
625                    String value = event.getValue();
626                    if (null != value) {
627                        m_controller.setEndType(value);
628                    }
629                }
630            }
631        });
632
633    }
634
635    /** Initialize elements from the duration panel. */
636    private void initDurationPanel() {
637
638        m_durationPrefixLabel.setText(Messages.get().key(Messages.GUI_SERIALDATE_DURATION_PREFIX_0));
639        m_durationAfterPostfixLabel.setText(Messages.get().key(Messages.GUI_SERIALDATE_DURATION_ENDTYPE_OCC_POSTFIX_0));
640        m_seriesEndDate.setDateOnly(true);
641        m_seriesEndDate.setAllowInvalidValue(true);
642        m_seriesEndDate.setValue(m_model.getSeriesEndDate());
643        m_seriesEndDate.getTextField().addFocusHandler(new FocusHandler() {
644
645            public void onFocus(FocusEvent event) {
646
647                if (handleChange()) {
648                    onSeriesEndDateFocus(event);
649                }
650
651            }
652        });
653    }
654
655    /**
656     * Configure all UI elements in the exceptions panel.
657     */
658    private void initExceptionsPanel() {
659
660        m_exceptionsPanel.setLegend(Messages.get().key(Messages.GUI_SERIALDATE_PANEL_EXCEPTIONS_0));
661        m_exceptionsPanel.addCloseHandler(this);
662        m_exceptionsPanel.setVisible(false);
663    }
664
665    /**
666     * Initialize the ui elements for the management part.
667     */
668    private void initManagementPart() {
669
670        m_manageExceptionsButton.setText(Messages.get().key(Messages.GUI_SERIALDATE_BUTTON_MANAGE_EXCEPTIONS_0));
671        m_manageExceptionsButton.getElement().getStyle().setFloat(Style.Float.RIGHT);
672    }
673
674    /**
675     * Initialize the overview/handle exceptions popup.
676     */
677    private void initOverviewPopup() {
678
679        m_updateExceptionsButton = new CmsPushButton();
680        m_updateExceptionsButton.setText(Messages.get().key(Messages.GUI_LOCALE_DIALOG_OK_0));
681        m_updateExceptionsButton.addClickHandler(new ClickHandler() {
682
683            public void onClick(ClickEvent event) {
684
685                if (handleChange()) {
686                    m_controller.updateExceptions(m_overviewList.getUncheckedDates());
687                    m_overviewPopup.hide();
688                }
689
690            }
691        });
692        m_overviewPopup = new CmsPopup(Messages.get().key(Messages.GUI_SERIALDATE_OVERVIEW_POPUP_TITLE_0), 800);
693        m_overviewPopup.center();
694        m_overviewPopup.setAutoHideEnabled(true);
695        m_overviewPopup.addDialogClose(null);
696        m_overviewPopup.addButton(m_updateExceptionsButton);
697        CmsScrollPanel panel = new CmsScrollPanel();
698        m_overviewList = new CmsCheckableDatePanel(m_dateFormat, CmsCheckableDatePanel.Style.TWO_COLUMNS);
699        m_overviewList.addDate(new Date());
700        panel.getElement().getStyle().setPaddingLeft(10, Unit.PX);
701        panel.getElement().getStyle().setProperty("maxHeight", m_overviewPopup.getAvailableHeight(0), Unit.PX);
702        panel.add(m_overviewList);
703        m_overviewPopup.add(panel);
704        m_overviewPopup.hide();
705
706    }
707
708    /**
709     * Initialize the pattern choice button group.
710     */
711    private void initPatternButtonGroup() {
712
713        m_groupPattern = new CmsRadioButtonGroup();
714        m_patternButtons = new HashMap<>();
715
716        createAndAddButton(PatternType.DAILY, Messages.GUI_SERIALDATE_TYPE_DAILY_0);
717        m_patternButtons.put(PatternType.NONE, m_patternButtons.get(PatternType.DAILY));
718        createAndAddButton(PatternType.WEEKLY, Messages.GUI_SERIALDATE_TYPE_WEEKLY_0);
719        createAndAddButton(PatternType.MONTHLY, Messages.GUI_SERIALDATE_TYPE_MONTHLY_0);
720        createAndAddButton(PatternType.YEARLY, Messages.GUI_SERIALDATE_TYPE_YEARLY_0);
721        // createAndAddButton(PatternType.INDIVIDUAL, Messages.GUI_SERIALDATE_TYPE_INDIVIDUAL_0);
722
723        m_groupPattern.addValueChangeHandler(new ValueChangeHandler<String>() {
724
725            public void onValueChange(ValueChangeEvent<String> event) {
726
727                if (handleChange()) {
728                    String value = event.getValue();
729                    if (value != null) {
730                        m_controller.setPattern(value);
731                    }
732                }
733            }
734        });
735
736    }
737
738    /** Initialize elements from the serial options panel (and all sub-panels). */
739    private void initSerialOptionsPanel() {
740
741        m_serialOptionsPanel.setLegend(Messages.get().key(Messages.GUI_SERIALDATE_PANEL_SERIAL_OPTIONS_0));
742        m_serialOptionsPanel.addCloseHandler(this);
743        setSerialOptionsVisible(false);
744        initDurationPanel();
745        initExceptionsPanel();
746        initManagementPart();
747    }
748
749    /**
750     * Shows / hides serial options and exceptions.<p>
751     *
752     * @param visible  true if the widgets should be shown, false if they should be hidden
753     */
754    private void setSerialOptionsVisible(boolean visible) {
755
756        m_serialOptionsPanel.setVisible(visible);
757        m_exceptionsPanelContainer.setVisible(visible);
758    }
759
760}