package com.onaro.util.jfc.date; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.text.DateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.EnumMap; import java.util.EnumSet; import java.util.List; import java.util.Map; import java.util.ResourceBundle; import javax.swing.JComboBox; import javax.swing.JDialog; import javax.swing.JOptionPane; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import com.onaro.client.DateFormats; import com.onaro.commons.prefs.PreferenceNotFoundException; import com.onaro.commons.prefs.PreferencesWrapper; import com.onaro.util.InvalidConfigException; import com.onaro.util.jfc.AdvancedComboBox; public class TimeFilterCombo { private final DateFormat format = DateFormats.getMediumDateTimeFormat(); static final Logger logger = LogManager.getLogger(TimeFilterCombo.class); /** * The time-filter combo box. */ private JComboBox timeFilterCombo; /** * Keeps the most recent selection between invocations. */ private PreferencesWrapper prefs; /** * Used to notify listeners that the selected time filter changed. */ private PropertyChangeSupport listeners = new PropertyChangeSupport(this); private EnumSet timeFilterOptions; private FilterEntry[] timeFilters; /** * Map to keep track of the combo box filter entries that correspond to the time filter enum * values. */ private Map filterEnumToEntryMap; private ResourceBundle resources; private String resourcePrefix; /** * Holds the current active filter. */ private TimeFilter currentFilter; public final static String TIME_FILTER_PROPERTY = "TIME_FILTER_PROPERTY"; //$NON-NLS-1$ public TimeFilterCombo(ResourceBundle resources, String resourcePrefix, PreferencesWrapper prefs, EnumSet filtersToShow) { this.resources = resources; this.resourcePrefix = resourcePrefix; this.prefs = prefs; this.timeFilterOptions = filtersToShow; timeFilters = createFilterEntries(resources, resourcePrefix, filtersToShow); timeFilterCombo = new AdvancedComboBox(resources, resourcePrefix, timeFilters); timeFilterCombo.setToolTipText(resources.getString(getResourceName(resourcePrefix, ".tooltip"))); //$NON-NLS-1$ /** * Restore the selected filter to be thesame as in the last time it was used. */ // String timeFilterStr = prefs.get("timeFilter", new StringBuilder(resourcePrefix).append(".today").toString()); String timeFilterStr = new StringBuilder(resourcePrefix).append(".today").toString(); //$NON-NLS-1$ if (timeFilterStr != null) { for (int i = 0; i < timeFilters.length; ++i) { if (timeFilters[i].getResourceName().equals(timeFilterStr)) { timeFilters[i].restoreSelection(); break; } } } } public void setTimeFilterOptions(EnumSet options) { if (timeFilterOptions != null && timeFilterOptions.equals(options)) { return; } this.timeFilterOptions = options; timeFilters = createFilterEntries(resources, resourcePrefix, timeFilterOptions); FilterEntry existingSelection = (FilterEntry)timeFilterCombo.getSelectedItem(); timeFilterCombo.removeAllItems(); for (FilterEntry timeFilter : timeFilters) { timeFilterCombo.addItem(timeFilter); } timeFilterCombo.setSelectedItem(existingSelection); } private FilterEntry[] createFilterEntries(ResourceBundle resources, String resourcePrefix, EnumSet filtersToShow) { List entries = new ArrayList(); filterEnumToEntryMap = new EnumMap(TimeFilterEnum.class); FilterEntry currentEntry; // All if (filtersToShow.contains(TimeFilterEnum.ALL)) { currentEntry = new TimeFilterEntry(resources, getResourceName(resourcePrefix, ".all")); //$NON-NLS-1$ filterEnumToEntryMap.put(TimeFilterEnum.ALL, currentEntry); entries.add(currentEntry); } // Today currentEntry = new TimeFilterEntry(resources, getResourceName(resourcePrefix, ".today"), new TimeFilterThis(Calendar.DAY_OF_MONTH)); //$NON-NLS-1$ filterEnumToEntryMap.put(TimeFilterEnum.TODAY, currentEntry); entries.add(currentEntry); // This week currentEntry = new TimeFilterEntry(resources, getResourceName(resourcePrefix, ".thisWeek"), new TimeFilterThis(Calendar.WEEK_OF_MONTH)); //$NON-NLS-1$ filterEnumToEntryMap.put(TimeFilterEnum.THIS_WEEK, currentEntry); entries.add(currentEntry); // Last week currentEntry = new TimeFilterEntry(resources, getResourceName(resourcePrefix, ".lastWeek"), new TimeFilterLast(Calendar.WEEK_OF_MONTH)); //$NON-NLS-1$ filterEnumToEntryMap.put(TimeFilterEnum.LAST_WEEK, currentEntry); entries.add(currentEntry); // This month currentEntry = new TimeFilterEntry(resources, getResourceName(resourcePrefix, ".thisMonth"), new TimeFilterThis(Calendar.MONTH)); //$NON-NLS-1$ filterEnumToEntryMap.put(TimeFilterEnum.THIS_MONTH, currentEntry); entries.add(currentEntry); // Last month currentEntry = new TimeFilterEntry(resources, getResourceName(resourcePrefix, ".lastMonth"), new TimeFilterLast(Calendar.MONTH)); //$NON-NLS-1$ filterEnumToEntryMap.put(TimeFilterEnum.LAST_MONTH, currentEntry); entries.add(currentEntry); // Custom currentEntry = new CustomTimeFilterEntry(resources, getResourceName(resourcePrefix, ".custom")); //$NON-NLS-1$ filterEnumToEntryMap.put(TimeFilterEnum.CUSTOM, currentEntry); entries.add(currentEntry); if (filtersToShow.contains(TimeFilterEnum.SELECTION)) { // Selection currentEntry = new TimeFilterEntry(resources, getResourceName(resourcePrefix, ".selection"), BySelectionTimeFilter.INSTANCE); //$NON-NLS-1$ filterEnumToEntryMap.put(TimeFilterEnum.SELECTION, currentEntry); entries.add(currentEntry); } return entries.toArray(new FilterEntry[entries.size()]); } /** * Select the given time filter in the combo box. This method does not support selecting * the Custom time filter (since that requires a prompt from the user to select the time). * If timeFilterEnum is not in the list of options present in this combo, the combo's selection * will not change. * * @param timeFilterEnum the time filter to select * @throws IllegalArgumentException if TimeFilterEnum.CUSTOM is passed to this method. */ public void selectTimeFilter(TimeFilterEnum timeFilterEnum) { if (TimeFilterEnum.CUSTOM == timeFilterEnum) { throw new IllegalArgumentException("Method does not support CUSTOM filter"); //$NON-NLS-1$ } FilterEntry filterEntry = filterEnumToEntryMap.get(timeFilterEnum); if (filterEntry != null) { timeFilterCombo.setSelectedItem(filterEntry); } } public void selectTimeFilter(TimeFilter timeFilter) { FilterEntry selectedEntry = null; for (FilterEntry entry : timeFilters) { if (entry instanceof TimeFilterEntry) { TimeFilterEntry timeEntry = (TimeFilterEntry)entry; if (timeEntry.filter == null) { if (timeFilter == null) { selectedEntry = entry; break; } } else if (timeEntry.filter.equals(timeFilter)) { selectedEntry = entry; break; } } else if (entry instanceof CustomTimeFilterEntry) { CustomTimeFilterEntry customEntry = (CustomTimeFilterEntry) entry; customEntry.setTimeFilter(timeFilter); return; } } if (selectedEntry != null) { timeFilterCombo.setSelectedItem(selectedEntry); } } private String getResourceName(String resourcePrefix, String resource) { return new StringBuilder(resourcePrefix).append(resource).toString(); } public TimeFilter getCurrentFilter() { return currentFilter; } public String getCurrentFilterDesc() { if (timeFilterCombo.getSelectedItem() instanceof CustomTimeFilterEntry) { CustomTimeFilterEntry entry = (CustomTimeFilterEntry)timeFilterCombo.getSelectedItem(); return format.format(entry.from) + " - " + format.format(entry.to); //$NON-NLS-1$ } else { return getStartTimeDesc(); } } public String getStartTimeDesc() { return ((FilterEntry)timeFilterCombo.getSelectedItem()).getSelectedName(); } public JComboBox getComboBox() { return timeFilterCombo; } /** * Adds a listener that will be notified whenever the selected time fitler changes.

* Events are sent with the property set to {@link TimeFilterCombo#TIME_FILTER_PROPERTY} and a value * of type {@link TimeFilter}. * * @param listener the listener to add */ public void addPropertyChangeListener(PropertyChangeListener listener) { listeners.addPropertyChangeListener(listener); } /** * Remove a listeners. * * @param listener the listener to remove */ public void removePropertyChangeListener(PropertyChangeListener listener) { listeners.removePropertyChangeListener(listener); } private void setSelectedFilter(TimeFilter filter) { Object oldFilter = currentFilter; listeners.firePropertyChange(TIME_FILTER_PROPERTY, oldFilter, currentFilter = filter); } /** * Entry of the time-filter combo box that allows the user to select specific * start time. */ private class CustomTimeFilterEntry extends FilterEntry { /** * The selected start time. */ Date from; /** * The selected start time. */ Date to; /** * Used when restoring selection to prevent the dialog from poping up. */ boolean ignoreSelection = false; /** * Initialize the entry, reading its name and tooltip from the resorces. * @param bundle locale-dependant resources * @param resourceName resource group name from which the name and tooltip * are read * @throws InvalidConfigException if some resources were missing */ public CustomTimeFilterEntry(ResourceBundle bundle, String resourceName) { super(bundle, resourceName); } /** * If a start time is selected than the combo-box's tooltip should display * it instead of the option's name. */ public String getToolTip() { if (from != null && to != null) { return Messages.INSTANCE.getChangeOcurredToolTipMessage(format.format(from), format.format(to)); } else { return super.getToolTip(); } } /** * When selected, pops up a dialog box letting the user to choose a specific * start time. If the user selected a time and clicked the "ok" button, * than a custom-filter is applied to director using this time. * @return true if the user selected a start time, false if "cancel" was pressed */ public boolean setSelected() { if (ignoreSelection) { return true; } from = new Date(prefs.getLong("timeFilterCustom.from", System.currentTimeMillis())); //$NON-NLS-1$ to = new Date(prefs.getLong("timeFilterCustom.to", System.currentTimeMillis())); //$NON-NLS-1$ Date newFrom = from; Date newTo = to; // Repeatedly show the time filter dialog until a valid selection is made boolean validSelection = false; while (!validSelection) { CustomFilterPanel customFilterPanel = new CustomFilterPanel(newFrom, newTo); customFilterPanel.setMaxDate(new Date()); JOptionPane pane = new JOptionPane(customFilterPanel, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION); JDialog dialog = pane.createDialog(timeFilterCombo.getRootPane(), Messages.INSTANCE.getFromToTimesMesssage()); dialog.setVisible(true); Integer rv = (Integer) pane.getValue(); if (rv != null && rv.intValue() == JOptionPane.OK_OPTION) { newFrom = customFilterPanel.getFrom(); newTo = customFilterPanel.getTo(); if (newFrom.after(newTo)) { JOptionPane.showMessageDialog(timeFilterCombo.getRootPane(), Messages.INSTANCE.getEndTimeAfterStartTimeMessage(), Messages.INSTANCE.getInvalidTimeFilter(), JOptionPane.ERROR_MESSAGE); } else { from = newFrom; to = newTo; setSelectedFilter(new TimeFilterCustom(from,to)); //save the selection for next time in the registry prefs.put("timeFilter", getResourceName()); //$NON-NLS-1$ prefs.putLong("timeFilterCustom.from", from.getTime()); //$NON-NLS-1$ prefs.putLong("timeFilterCustom.to", to.getTime()); //$NON-NLS-1$ return true; } } else { // Cancelling is a valid selection validSelection = true; } } return false; } /** * When restoring filter selection and this is the selected option than * apply this filter on the director not before the setSelected() * is disabled to prevent it from poping up the dialog. */ public void restoreSelection() { try { from = new Date(prefs.getLong("timeFilterCustom.from")); //$NON-NLS-1$ to = new Date(prefs.getLong("timeFilterCustom.to")); //$NON-NLS-1$ } catch (PreferenceNotFoundException e) { try { //try to get the info from the old registy - 'timeFilterCustom' from = new Date(prefs.getLong("timeFilterCustom")); //$NON-NLS-1$ to = new Date(); } catch (PreferenceNotFoundException e1) { //nothing in the registry long currTime = System.currentTimeMillis(); from = new Date(currTime - 1000 * 60 * 60 * 24);//day diff to = new Date(currTime); } } ignoreSelection = true; timeFilterCombo.setSelectedItem(this); setSelectedFilter(new TimeFilterCustom(from,to)); ignoreSelection = false; } private void setTimeFilter(TimeFilter filter) { ignoreSelection = true; from = filter.getStartTime(); to = filter.getEndTime(); timeFilterCombo.setSelectedItem(this); setSelectedFilter(filter); ignoreSelection = false; } } /** * Entry of the time-filter combo box. */ private class TimeFilterEntry extends FilterEntry { /** * The time filter associated with this entry. */ TimeFilter filter; /** * Initialize no-filter entry, reading its name and tooltip from the resources. * @param bundle locale-dependent resources * @param resourceName resource group name from which the name and tooltip * are read * @throws InvalidConfigException if some resources were missing */ public TimeFilterEntry(ResourceBundle bundle, String resourceName) { super(bundle, resourceName); } /** * Initialize an entry with the given filter, reading its name and tooltip * from the resources. * @param bundle locale-dependent resources * @param resourceName resource group name from which the name and tooltip * are read * @param filter the filter associated with this entry * @throws InvalidConfigException if some resources were missing */ public TimeFilterEntry(ResourceBundle bundle, String resourceName, TimeFilter filter) { super(bundle, resourceName); this.filter = filter; } /** * When selected, apply the filter on the director and save the selection. * @return true */ public boolean setSelected() { setSelectedFilter(filter); prefs.put("timeFilter", getResourceName()); //$NON-NLS-1$ return true; } /** * When restoring filter selection and this is the selected option than * simply apply this filter on the director. */ public void restoreSelection() { timeFilterCombo.setSelectedItem(this); } } }