package org.rr.jeborker.gui; import static org.rr.commons.utils.StringUtil.EMPTY; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.MutableComboBoxModel; import org.rr.commons.swing.components.JRCheckBoxComboBox; import org.rr.commons.swing.components.JREditableHistoryComboBox; import org.rr.commons.swing.components.model.DefaultJRCheckBoxComboBoxModel; import org.rr.commons.swing.components.model.JRCheckBoxComboBoxModel; import org.rr.commons.utils.ListUtils; import org.rr.commons.utils.ReflectionUtils; import org.rr.commons.utils.StringUtil; import org.rr.jeborker.app.preferences.APreferenceStore; import org.rr.jeborker.app.preferences.PreferenceStoreFactory; import org.rr.jeborker.db.item.EbookPropertyItem; import org.rr.jeborker.db.item.ViewField; import org.rr.jeborker.gui.action.ActionFactory; import org.rr.jeborker.gui.action.ApplicationAction; import org.rr.jeborker.gui.additional.EbookPropertyItemFieldComperator; import net.miginfocom.swing.MigLayout; public class FilterPanelComponent extends JPanel { private static EbookPropertyItemFieldComperator ebookPropertyItemFieldComperator = new EbookPropertyItemFieldComperator(); private final JRCheckBoxComboBox<Field> filterFieldSelection = new JRCheckBoxComboBox<>(); private final JREditableHistoryComboBox filterField = new JREditableHistoryComboBox(); private final FilterFieldActionListener filterFieldActionListener = new FilterFieldActionListener(); FilterPanelComponent() { initialize(); } /** * {@link ActionListener} which starts the filter process if the user press enter in the combobox text field. */ private class FilterFieldActionListener implements ActionListener { @Override public void actionPerformed(ActionEvent e) { getSearchAction().invokeAction(e); } public ApplicationAction getNonThreadingSearchAction() { ApplicationAction action = getSearchAction(); action.putValue(ApplicationAction.NON_THREADED_ACTION_KEY, Boolean.TRUE); return action; } public ApplicationAction getSearchAction() { return ActionFactory.getAction(ActionFactory.COMMON_ACTION_TYPES.SEARCH_ACTION, null); } } private void initialize() { setLayout(new MigLayout("insets 0 5 0 0")); JLabel lblSearch = new JLabel(Bundle.getString("FilterPanelView.label.search")); add(lblSearch, "w 55!"); filterFieldSelection.setMinPopupWidth(200); Dimension filterFieldSelectionSize = new Dimension(80, filterFieldSelection.getPreferredSize().height); filterFieldSelection.setPreferredSize(filterFieldSelectionSize); filterFieldSelection.setMinimumSize(filterFieldSelectionSize); JRCheckBoxComboBoxModel<Field> sortColumnComboBoxModel = this.initFieldSelectionModel(); filterFieldSelection.setCheckBoxComboBoxModel(sortColumnComboBoxModel); add(filterFieldSelection, EMPTY); add(filterField, "w 100%"); JButton searchButton = new JButton(ActionFactory.getAction(ActionFactory.COMMON_ACTION_TYPES.SEARCH_ACTION, EMPTY)); add(searchButton); } public void initListeners() { filterField.getEditor().addActionListener(filterFieldActionListener); } /** * Gets the text from the filter/search field. * * @return The text from the filter/search field. Never returns <code>null</code>. */ public String getFilterText() { return filterField.getEditorValue(); } /** * get all {@link EbookPropertyItem} fields which should be included by the filter. * * @return The fields to be filtered. Never returns null. */ public List<Field> getSelectedFilterFields() { JRCheckBoxComboBoxModel<Field> model = filterFieldSelection.getCheckBoxComboBoxModel(); List<Field> checkeds = model.getCheckedValues(); return checkeds; } /** * get all {@link EbookPropertyItem} field names which are selected by the filter selection combobox. * * @return The field names to be filtered. Never returns null. */ public List<String> getSelectedFilterFieldNames() { List<Field> selectedFilterFields = getSelectedFilterFields(); ArrayList<String> result = new ArrayList<>(selectedFilterFields.size()); for (Field field : selectedFilterFields) { result.add(field.getName()); } return result; } /** * Initializes and set the data model to the combobox. * * @return The created model. */ private JRCheckBoxComboBoxModel<Field> initFieldSelectionModel() { // get fields to be displayed in the combobox final List<Field> listEntries = ReflectionUtils.getFieldsByAnnotation(ViewField.class, EbookPropertyItem.class); // sort the fields to the DBViewField.orderPriority() Collections.sort(listEntries, ebookPropertyItemFieldComperator); final JRCheckBoxComboBoxModel<Field> filterFieldColumnComboBoxModel = new DefaultJRCheckBoxComboBoxModel<Field>(listEntries, null) { @Override public String getLabel(int index) { Field value = getValueAt(index); ViewField annotation = ((Field) value).getAnnotation(ViewField.class); String localizedName = Bundle.getString(StringUtil.replace(annotation.name(), " ", EMPTY).toLowerCase()); if (localizedName != null) { return localizedName; } else { return annotation.name(); } } }; return filterFieldColumnComboBoxModel; } /** * Adds the given search expression to the beginning of the combobox list. If the list exceeds more than 10 entries, the last ones will be deleted. * * @param searchExpression * The search expression to be attached. */ public void addFilterFieldSearch(final String searchExpression) { filterField.addHistoryValue(searchExpression); } /** * Tells the text filter field to display it self in and active filter color. */ public void enableFilterColor(boolean enable) { filterField.enableFilterColor(enable); } /** * Stores the filter history in a comma separated list to the preference store. * * @see #restoreComponentProperties() */ void storeApplicationHistory() { storeFileHistory(); storeFilterHistory(); storeFilterSelection(); } private void storeFilterSelection() { APreferenceStore preferenceStore = PreferenceStoreFactory.getPreferenceStore(PreferenceStoreFactory.DB_STORE); preferenceStore.addGenericEntryAsString("FilterPanelControllerCurrentFilterFieldSelection", ListUtils.join(getSelectedFilterFieldNames(), ",")); } private void storeFilterHistory() { APreferenceStore preferenceStore = PreferenceStoreFactory.getPreferenceStore(PreferenceStoreFactory.DB_STORE); String historyValues = filterField.getHistoryValues(); preferenceStore.addGenericEntryAsString("FilterPanelControllerEntries", historyValues); } private void storeFileHistory() { APreferenceStore preferenceStore = PreferenceStoreFactory.getPreferenceStore(PreferenceStoreFactory.DB_STORE); preferenceStore.addGenericEntryAsString("FilterPanelControllerCurrentFilter", getFilterText()); } /** * Restore the previously stored filter history. * * @see #storeApplicationHistory() */ void restoreComponentProperties() { restoreFilterHistory(); restoreFilterSelection(); restoreFileHistory(); } private void restoreFilterHistory() { APreferenceStore preferenceStore = PreferenceStoreFactory.getPreferenceStore(PreferenceStoreFactory.DB_STORE); String filterEntries = preferenceStore.getGenericEntryAsString("FilterPanelControllerEntries"); filterField.setHistoryValues(filterEntries); } private void restoreFilterSelection() { APreferenceStore preferenceStore = PreferenceStoreFactory.getPreferenceStore(PreferenceStoreFactory.DB_STORE); String filterFieldSelectionEntries = preferenceStore.getGenericEntryAsString("FilterPanelControllerCurrentFilterFieldSelection"); List<String> splitted = ListUtils.split(filterFieldSelectionEntries, ","); final JRCheckBoxComboBoxModel<Field> model = filterFieldSelection.getCheckBoxComboBoxModel(); final int modelSize = model.getSize(); for (String split : splitted) { for (int j = 0; j < modelSize; j++) { if (model.getValueAt(j).getName().equals(split)) { model.addCheck((Field) model.getValueAt(j)); break; } } } } private void restoreFileHistory() { String latestSearch = PreferenceStoreFactory.getPreferenceStore(PreferenceStoreFactory.DB_STORE).getGenericEntryAsString( "FilterPanelControllerCurrentFilter"); filterField.setItem(latestSearch); filterFieldActionListener.getNonThreadingSearchAction().invokeAction(new ActionEvent(this, 0, "initialize")); } }