package org.rr.jeborker.gui; import static org.rr.commons.utils.StringUtil.EMPTY; import java.awt.event.ActionEvent; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.swing.AbstractAction; import javax.swing.Icon; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JToggleButton; import net.miginfocom.swing.MigLayout; import org.rr.commons.log.LoggerFactory; import org.rr.commons.swing.components.JRCheckBoxComboBox; import org.rr.commons.swing.components.event.ListCheckListener; import org.rr.commons.swing.components.event.ListEvent; 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.OrderDirection; import org.rr.jeborker.db.item.EbookPropertyItem; import org.rr.jeborker.db.item.ViewField; import org.rr.jeborker.gui.additional.EbookPropertyItemFieldComperator; import org.rr.jeborker.gui.model.EbookPropertyDBTableModel; import org.rr.jeborker.gui.resources.ImageResourceBundle; class SortColumnComponent extends JPanel { private final JRCheckBoxComboBox<Field> orderFieldComboBox = new JRCheckBoxComboBox<>(); private JToggleButton sortOrderAscButton; private JToggleButton sortOrderDescButton; private JLabel sortLabel; private final EbookPropertyItemFieldComperator ebookPropertyItemFieldComperator = new EbookPropertyItemFieldComperator();; private final ArrayList<Field> internalCheckList = new ArrayList<>(); public SortColumnComponent() { this.initialize(); } private void initialize() { setLayout(new MigLayout("insets 0 5 0 0")); // T, L, B, R. sortLabel = new JLabel(Bundle.getString("EborkerMainView.sortby")); add(sortLabel, EMPTY); initSortButtons(); add(sortOrderAscButton, "w 25!, h 25!"); add(sortOrderDescButton, "w 25!, h 25!"); JRCheckBoxComboBoxModel<Field> sortColumnComboBoxModel = initModel(); orderFieldComboBox.setCheckBoxComboBoxModel(sortColumnComboBoxModel); add(orderFieldComboBox, "w 100%, h 25!"); initSortAction(sortColumnComboBoxModel); initClosedViewValue(); } private void initSortButtons() { sortOrderAscButton = new JToggleButton(); sortOrderDescButton = new JToggleButton(); Icon ascOrderIcon = ImageResourceBundle.getResourceAsImageIcon("sort_asc.gif"); sortOrderAscButton.setIcon(ascOrderIcon); Icon descOrderIcon = ImageResourceBundle.getResourceAsImageIcon("sort_desc.gif"); sortOrderDescButton.setIcon(descOrderIcon); sortOrderAscButton.setAction(new AbstractAction(null, ascOrderIcon) { @Override public void actionPerformed(ActionEvent e) { sortOrderDescButton.setSelected(false); sortOrderAscButton.setSelected(true); MainController.getController().changeToDatabaseModel().setOrderDirection(new OrderDirection(OrderDirection.DIRECTION_ASC)); MainController.getController().getEbookTableHandler().refreshTable(); } }); sortOrderDescButton.setAction(new AbstractAction(null, descOrderIcon) { @Override public void actionPerformed(ActionEvent e) { sortOrderAscButton.setSelected(false); sortOrderDescButton.setSelected(true); MainController.getController().changeToDatabaseModel().setOrderDirection(new OrderDirection(OrderDirection.DIRECTION_DESC)); MainController.getController().getEbookTableHandler().refreshTable(); } }); if(!sortOrderAscButton.isSelected() && !sortOrderDescButton.isSelected()) { //ascending order by default sortOrderAscButton.setSelected(true); } } /** * Initialize the combobox actions to be triggered on a selection change. * @param sortColumnComboBoxModel The model where the selections are triggered. */ private void initSortAction(JRCheckBoxComboBoxModel<Field> sortColumnComboBoxModel) { sortColumnComboBoxModel.addListCheckListener(new ListCheckListener<Field>() { @Override public void removeCheck(ListEvent<Field> event) { internalCheckList.removeAll(event.getValues()); this.changed(event); } @Override public void addCheck(ListEvent<Field> event) { internalCheckList.addAll(event.getValues()); this.changed(event); } private void changed(ListEvent<Field> event) { final EbookPropertyDBTableModel tableModel = MainController.getController().changeToDatabaseModel(); tableModel.setOrderByColumns(internalCheckList); MainController.getController().getEbookTableHandler().refreshTable(); } }); } /** * Setup the value which is shown if the combobox is closed. * * @param filterFieldSelection The combobox to be setup. */ private void initClosedViewValue() { orderFieldComboBox.setTextFor(JRCheckBoxComboBox.CheckState.MULTIPLE, new CharSequence() { @Override public CharSequence subSequence(int start, int end) { return getTextValues().subSequence(start, end); } @Override public int length() { return getTextValues().length(); } @Override public char charAt(int index) { return getTextValues().charAt(index); } private StringBuilder getTextValues() { StringBuilder text = new StringBuilder(); for (Object field : internalCheckList) { if(text.length() > 0) { text.append(", "); } String name = ((Field)field).getAnnotation(ViewField.class).name(); text.append(name); } return text; } @Override public String toString() { return getTextValues().toString(); } }); } /** * Initializes and set the data model to the combobox. * @return The created model. */ private JRCheckBoxComboBoxModel<Field> initModel() { //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 DefaultJRCheckBoxComboBoxModel<Field> sortColumnComboBoxModel = new DefaultJRCheckBoxComboBoxModel<Field>(listEntries, null) { @Override public String getLabel(int index) { Field value = getValueAt(index); ViewField annotation = value.getAnnotation(ViewField.class); String localizedName = Bundle.getString(StringUtil.replace(annotation.name(), " ", EMPTY).toLowerCase()); if(localizedName != null) { return localizedName; } else { return annotation.name(); } } }; return sortColumnComboBoxModel; } /** * Gets the fields which are checked. * @return The checked fields. Never returns <code>null</code>. */ public List<Field> getSelectedFields() { final List<Field> checkeds = orderFieldComboBox.getCheckBoxComboBoxModel().getCheckedValues(); //sort the fields to the DBViewField.orderPriority() Collections.sort(checkeds, ebookPropertyItemFieldComperator); final ArrayList<Field> result = new ArrayList<>(checkeds.size()); for (Field field : checkeds) { result.add(field); } return result; } /** * Reads the order columns from the preferences to the combobox model. */ private void readOrderColumnsFromPreferences() { final APreferenceStore preferenceStore = PreferenceStoreFactory.getPreferenceStore(PreferenceStoreFactory.DB_STORE); final String entryString = preferenceStore.getGenericEntryAsString("sortColumnFields"); if (entryString != null && entryString.length() > 0) { final List<String> splitted = ListUtils.split(entryString, ",", -1); final JRCheckBoxComboBoxModel<Field> model = orderFieldComboBox.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; } } } } else { //set a default set of sort values final EbookPropertyDBTableModel tableModel = MainController.getController().changeToDatabaseModel(); List<Field> orderByColumns = tableModel.getOrderByColumns(); try { orderByColumns.add(EbookPropertyItem.class.getDeclaredField("authorSort")); orderByColumns.add(EbookPropertyItem.class.getDeclaredField("title")); } catch (Exception e) { LoggerFactory.logWarning(this, "Field named author is not available at " + EbookPropertyItem.class, e); } } } void storeApplicationProperties() { //store the sort order properties. final APreferenceStore preferenceStore = PreferenceStoreFactory.getPreferenceStore(PreferenceStoreFactory.DB_STORE); final List<Field> selectedFields = getSelectedFields(); final StringBuilder value = new StringBuilder(); for (Field field : selectedFields) { if(value.length() > 0) { value.append(","); } value.append(field.getName()); } preferenceStore.addGenericEntryAsString("sortColumnFields", value.toString()); storeSortButtonProperties(); } /** * Restores the order fields and put them to view and model. */ void restoreComponentProperties() { readOrderColumnsFromPreferences(); restoreSortButtonProperties(); } void storeSortButtonProperties() { APreferenceStore preferenceStore = PreferenceStoreFactory.getPreferenceStore(PreferenceStoreFactory.DB_STORE); String value = sortOrderAscButton.isSelected() ? "asc" : "desc"; preferenceStore.addGenericEntryAsString("sortColumnOrder", value); } /** * Restores the order fields and put them to view and model. */ private void restoreSortButtonProperties() { final APreferenceStore preferenceStore = PreferenceStoreFactory.getPreferenceStore(PreferenceStoreFactory.DB_STORE); String sortColumnOrder = preferenceStore.getGenericEntryAsString("sortColumnOrder"); if (sortColumnOrder != null) { if (sortColumnOrder.equalsIgnoreCase("asc")) { ActionEvent e = new ActionEvent(sortOrderAscButton, ActionEvent.ACTION_PERFORMED, null); sortOrderAscButton.getAction().actionPerformed(e); } else if (sortColumnOrder.equalsIgnoreCase("desc")) { ActionEvent e = new ActionEvent(sortOrderDescButton, ActionEvent.ACTION_PERFORMED, null); sortOrderDescButton.getAction().actionPerformed(e); } } } }