Java tutorial
/* * Scaffold Hunter * Copyright (C) 2006-2008 PG504 * Copyright (C) 2010-2011 PG552 * See README.txt in the root directory of the Scaffold Hunter source tree * for details. * * Scaffold Hunter is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * Scaffold Hunter 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package edu.udo.scaffoldhunter.gui.datasetmanagement; import static edu.udo.scaffoldhunter.util.I18n._; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Enumeration; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; import javax.swing.Action; import javax.swing.BorderFactory; import javax.swing.DefaultCellEditor; import javax.swing.DefaultListModel; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JDialog; import javax.swing.JEditorPane; import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JTextField; import javax.swing.ListSelectionModel; import javax.swing.border.Border; import javax.swing.event.CellEditorListener; import javax.swing.event.ChangeEvent; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkEvent.EventType; import javax.swing.event.HyperlinkListener; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import com.jgoodies.forms.builder.ButtonStackBuilder; import com.jgoodies.forms.builder.PanelBuilder; import com.jgoodies.forms.factories.ButtonBarFactory; import com.jgoodies.forms.layout.CellConstraints; import com.jgoodies.forms.layout.FormLayout; import edu.udo.scaffoldhunter.gui.util.AbstractAction; import edu.udo.scaffoldhunter.gui.util.DBExceptionHandler; import edu.udo.scaffoldhunter.gui.util.DBFunction; import edu.udo.scaffoldhunter.gui.util.StandardButtonFactory; import edu.udo.scaffoldhunter.gui.util.UrlOpener; import edu.udo.scaffoldhunter.model.RuleType; import edu.udo.scaffoldhunter.model.db.DatabaseException; import edu.udo.scaffoldhunter.model.db.Dataset; import edu.udo.scaffoldhunter.model.db.Rule; import edu.udo.scaffoldhunter.model.db.Ruleset; import edu.udo.scaffoldhunter.model.db.Tree; import edu.udo.scaffoldhunter.util.Resources; /** * Dialog to edit/create tree generation rulesets * * @author Philipp Lewe * */ public class ManageRulesetsDialog extends JDialog { private DatasetManagement controller; private JPanel container; private JPanel leftContainer; private JPanel rightContainer; // Rulesets Section private JList rulesetsList; private DefaultListModel rulesets; private JScrollPane rulesetsListScroll; private JButton newRulesetButton; private JButton deleteRulesetButton; // TODO: Changes private Ruleset createdNotSaved; // Ruleset Edit Section private JTextField rulesetTitle; private Border defaultRulesetTitleBorder; private RulesetTitleDocumentListener rulesetTitleListener; private JList existingRulesList; private DefaultListModel existingRules; private JScrollPane existingRulesListScroll; private JTable usedRulesTable; private RulesetTableModel usedRules; private JScrollPane usedRulesTableScroll; private ListSelectionListener ruleSelection; private JButton addRuleButton; private JButton removeRuleButton; private JButton ruleUpButton; private JButton ruleDownButton; private JButton saveButton; private JButton okButton; private JEditorPane infoLabel; private List<Ruleset> immutableRulesets; private Ruleset currentRulesetEditing = null; private boolean unsavedChanges = false; private boolean isNewRuleset = false; /** * Creates new dialog for management of rulesets * * @param owner * the owner of this dialog * @param controller * the dataset management controller * @throws DatabaseException * when the immutable rulesets list could not be loaded */ public ManageRulesetsDialog(Window owner, DatasetManagement controller) throws DatabaseException { super(owner); this.controller = controller; initGUI(); loadImmutableRulesets(); loadRulesets(); pack(); setLocationRelativeTo(getOwner()); } /** * Initialises all GUI components */ private void initGUI() { FormLayout containerLayout; PanelBuilder containerBuilder; FormLayout leftLayout; PanelBuilder leftBuilder; FormLayout rightLayout; PanelBuilder rightBuilder; ButtonStackBuilder rulesetListButtons; ButtonStackBuilder ruleAddRemoveButtons; ButtonStackBuilder ruleUpDownButtons; CellConstraints cc = new CellConstraints(); String listPrototypeElement = "____________________"; int listsNumRows = 15; JComboBox ascendingChooser; setTitle(_("ManageRulesets.WindowTitle")); setLayout(new BorderLayout()); setModal(true); container = new JPanel(); add(container, BorderLayout.CENTER); containerLayout = new FormLayout("p, 2dlu, p:g(1.0)", "f:p:g(1.0), p"); containerBuilder = new PanelBuilder(containerLayout, container); containerBuilder.setDefaultDialogBorder(); leftContainer = new JPanel(); leftContainer.setBorder(BorderFactory.createTitledBorder(_("ManageRulesets.Rulesets"))); containerBuilder.add(leftContainer, cc.rc(1, 1)); leftLayout = new FormLayout("p, 2dlu, p:g(1.0)", "f:p:g(1.0)"); leftBuilder = new PanelBuilder(leftLayout, leftContainer); rulesets = new DefaultListModel(); rulesetsList = new JList(rulesets); rulesetsList.setVisibleRowCount(listsNumRows); rulesetsList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); rulesetsList.setPrototypeCellValue(listPrototypeElement); rulesetsList.addListSelectionListener(new RulesetsListSelectionListener()); rulesetsListScroll = new JScrollPane(rulesetsList); leftBuilder.add(rulesetsListScroll, cc.rc(1, 1)); newRulesetButton = new JButton(new NewRulesetAction()); deleteRulesetButton = new JButton(new DeleteRulesetAction(this)); rulesetListButtons = new ButtonStackBuilder(); rulesetListButtons.addGridded(newRulesetButton); rulesetListButtons.addRelatedGap(); rulesetListButtons.addGridded(deleteRulesetButton); leftBuilder.add(rulesetListButtons.getPanel(), cc.rc(1, 3)); rightContainer = new JPanel(); rightContainer.setBorder(BorderFactory.createTitledBorder(_("ManageRulesets.Ruleset"))); containerBuilder.add(rightContainer, cc.rc(1, 3)); rulesetTitle = new JTextField(); rulesetTitleListener = new RulesetTitleDocumentListener(); rulesetTitle.getDocument().addDocumentListener(rulesetTitleListener); defaultRulesetTitleBorder = rulesetTitle.getBorder(); ruleSelection = new RuleSelectionListener(); existingRules = new DefaultListModel(); existingRulesList = new JList(existingRules); existingRulesList.setVisibleRowCount(listsNumRows); existingRulesList.setMinimumSize(new Dimension(120, 20)); existingRulesList.addListSelectionListener(ruleSelection); existingRulesListScroll = new JScrollPane(existingRulesList); existingRulesListScroll.setMinimumSize(new Dimension(160, 20)); existingRulesListScroll.setPreferredSize(new Dimension(160, 20)); usedRules = new RulesetTableModel(); usedRulesTable = new JTable(usedRules); usedRulesTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN); usedRulesTable.getSelectionModel().addListSelectionListener(ruleSelection); usedRulesTableScroll = new JScrollPane(usedRulesTable); usedRulesTableScroll.setPreferredSize(new Dimension(300, 200)); ascendingChooser = new JComboBox(); ascendingChooser.addItem(_("ManageRulesets.UsedRules.Ascending.True")); ascendingChooser.addItem(_("ManageRulesets.UsedRules.Ascending.False")); usedRulesTable.getColumnModel().getColumn(0).setPreferredWidth(150); usedRulesTable.getColumnModel().getColumn(1).setCellEditor(new DefaultCellEditor(ascendingChooser)); usedRulesTable.getColumnModel().getColumn(1).getCellEditor() .addCellEditorListener(new CellEditorListener() { @Override public void editingStopped(ChangeEvent e) { rulesetChanged(); } @Override public void editingCanceled(ChangeEvent e) { // do nothing } }); usedRulesTable.getColumnModel().getColumn(1).setPreferredWidth(170); usedRulesTable.setRowHeight(ascendingChooser.getPreferredSize().height); usedRulesTable.getTableHeader().setReorderingAllowed(false); addRuleButton = new JButton(new AddRuleAction()); removeRuleButton = new JButton(new RemoveRuleAction()); ruleAddRemoveButtons = new ButtonStackBuilder(); ruleAddRemoveButtons.addButton(addRuleButton, removeRuleButton); ruleUpButton = new JButton(new RuleUpAction()); ruleDownButton = new JButton(new RuleDownAction()); ruleUpDownButtons = new ButtonStackBuilder(); ruleUpDownButtons.addButton(ruleUpButton, ruleDownButton); infoLabel = new JEditorPane(); infoLabel.setContentType("text/html"); infoLabel.setText(_("ManageRulesets.HelpNoSelection")); infoLabel.setEditable(false); infoLabel.setBackground(rightContainer.getBackground()); infoLabel.setPreferredSize(new Dimension(30, 40)); infoLabel.setMaximumSize(new Dimension(30, 40)); infoLabel.addHyperlinkListener(new HyperlinkListener() { @Override public void hyperlinkUpdate(HyperlinkEvent e) { // if clicked, open url in browser if (e.getEventType() == EventType.ACTIVATED) { UrlOpener.browse(e.getURL()); } } }); saveButton = new JButton(new SaveAction()); saveButton.setEnabled(false); rightLayout = new FormLayout("p, 2dlu, l:m, d, p:g, d, f:m", // 7 colums "t:p, 2dlu, p, d, f:p:g, d, p, d, f:p"); // 9 rows rightLayout.setColumnGroups(new int[][] { /* { 1, 5 }, */{ 2, 4, 6 } }); rightLayout.setRowGroups(new int[][] { { 2, 4, 6, 8 } }); rightBuilder = new PanelBuilder(rightLayout, rightContainer); rightBuilder.addLabel(_("ManageRulesets.RulesetLabel"), cc.rc(1, 1)); rightBuilder.add(rulesetTitle, cc.rcw(1, 3, 5)); rightBuilder.addLabel(_("ManageRulesets.ExistingRules"), cc.rc(3, 1)); rightBuilder.add(existingRulesListScroll, cc.rc(5, 1)); rightBuilder.add(ruleAddRemoveButtons.getPanel(), cc.rc(5, 3)); rightBuilder.addLabel(_("ManageRulesets.UsedRules"), cc.rc(3, 5)); rightBuilder.add(usedRulesTableScroll, cc.rc(5, 5)); rightBuilder.add(ruleUpDownButtons.getPanel(), cc.rc(5, 7)); rightBuilder.add(saveButton, cc.rchw(7, 7, 3, 1)); rightBuilder.addLabel(_("ManageRulesets.Help"), cc.rc(7, 1)); rightBuilder.add(infoLabel, cc.rcw(9, 1, 5)); okButton = StandardButtonFactory.createCloseButton(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { confirmIfUnsavedChanges(); dispose(); } }); getRootPane().setDefaultButton(okButton); containerBuilder.add(ButtonBarFactory.buildOKBar(okButton), cc.rcw(2, 1, 3)); setRulesetEditingEnable(false, false); } /** * Loads all rulesets used by any tree in any dataset. Needed to ensure a * used ruleset is not editable * * @throws DatabaseException */ private void loadImmutableRulesets() throws DatabaseException { List<Dataset> datasets; Ruleset ruleset; immutableRulesets = new LinkedList<Ruleset>(); datasets = controller.getDbManager().getAllDatasets(); // loads all rulesets in any tree in any dataset for (Dataset dataset : datasets) { for (Tree tree : dataset.getTrees()) { ruleset = tree.getRuleset(); if (ruleset != null) { immutableRulesets.add(ruleset); } } } } private void loadRules(Ruleset ruleset) { Set<RuleType> usedRuleTypes = new HashSet<RuleType>(); Rule newRule; // load used rules usedRules.clear(); usedRules.addAllElements(ruleset.getOrderedRules()); // load existing rules existingRules.clear(); // collect all used ruletypes from ruleset for (Rule rule : ruleset.getOrderedRules()) { usedRuleTypes.add(rule.getRule()); } // create a rule for all ruletypes which are not present in the ruleset for (RuleType ruleType : RuleType.values()) { if (!usedRuleTypes.contains(ruleType)) { newRule = new Rule(); newRule.setRule(ruleType); newRule.setRuleset(ruleset); existingRules.addElement(newRule); } } } private void loadRulesets() { List<Ruleset> list; list = DBExceptionHandler.callDBManager(controller.getDbManager(), new DBFunction<List<Ruleset>>() { @Override public List<Ruleset> call() throws DatabaseException { return controller.getDbManager().getAllRulesets(); } }); rulesets.clear(); for (Ruleset ruleset : list) { rulesets.addElement(ruleset); } if (!rulesets.isEmpty()) { rulesetsList.setSelectedIndex(0); } } private void rulesetChanged() { unsavedChanges = true; if (validTitle()) { saveButton.setEnabled(true); rulesetTitle.setBorder(defaultRulesetTitleBorder); } else { saveButton.setEnabled(false); rulesetTitle.setBorder(BorderFactory.createLineBorder(Color.RED)); } } /** * Checks if the title entered by the user is valid * * @return <code>true</code> if the title is valid, <code>false</code> if * not. */ private boolean validTitle() { String title = rulesetTitle.getText().trim(); Ruleset ruleset; // empty title is not allowed if (title.isEmpty()) { return false; } // same titles for rulesets are not allowed for (Enumeration<?> e = rulesets.elements(); e.hasMoreElements();) { ruleset = (Ruleset) e.nextElement(); if (ruleset != currentRulesetEditing && ruleset.getTitle().toLowerCase().equals(rulesetTitle.getText().toLowerCase())) { return false; } } return true; } /** * Loads the given ruleset to the GUI * * @param ruleset * the <code>Ruleset</code> to load */ private void editRuleset(Ruleset ruleset) { unsavedChanges = false; currentRulesetEditing = ruleset; if (ruleset == null) { // if this is the case, the edited ruleset has been deleted return; } loadRules(ruleset); rulesetTitle.getDocument().removeDocumentListener(rulesetTitleListener); rulesetTitle.setText(currentRulesetEditing.getTitle()); rulesetTitle.selectAll(); rulesetTitle.getDocument().addDocumentListener(rulesetTitleListener); // if the ruleset is immutable, don't allow editing of rules if (isRulesetImmutable(currentRulesetEditing)) { setRulesetEditingEnable(false, true); infoLabel.setText(String.format("<html><font color=\"red\"><i>%s</i></font></html>", _("ManageRulesets.HelpRulesetNotModifiable"))); } else { setRulesetEditingEnable(true, true); infoLabel.setText(_("ManageRulesets.HelpNoSelection")); } if (isNewRuleset) { isNewRuleset = false; rulesetChanged(); } } private void setRulesetEditingEnable(boolean b, boolean enableTitleEditing) { usedRulesTable.setEnabled(b); existingRulesList.setEnabled(b); ruleUpButton.setEnabled(b); ruleDownButton.setEnabled(b); addRuleButton.setEnabled(b); removeRuleButton.setEnabled(b); rulesetTitle.setEnabled(enableTitleEditing); } /** * Checks if the given ruleset is immutable * * @return <code>true</code> if the ruleset is immutable, <code>false</code> * otherwise */ private boolean isRulesetImmutable(Ruleset ruleset) { for (Ruleset immRuleset : immutableRulesets) { if (ruleset.equalsDb(immRuleset)) { return true; } } return false; } /** * Saves the currently loaded ruleset */ private void save() { assert (!(currentRulesetEditing == null)) : "saving without editing should not be possible"; currentRulesetEditing.setTitle(rulesetTitle.getText().trim()); // if editing of this ruleset is allowed update the rules list of this // ruleset if (!isRulesetImmutable(currentRulesetEditing)) { currentRulesetEditing.setOrderedRules(usedRules.getRules()); } controller.saveRuleset(currentRulesetEditing); createdNotSaved = null; unsavedChanges = false; saveButton.setEnabled(false); deleteRulesetButton.setEnabled(true); rulesetsList.updateUI(); } /** * Shows information about the <code>Ruletype</code> of the given Rule * * @param rule * the rule the info should be displayed (or <code>null</code> if * there is no selection) */ private void showInfo(Rule rule) { String hyperlinkedDescription; String text; if (rule != null) { hyperlinkedDescription = rule.getRule().getDescription().replaceAll("http://[^ ]*", "<a href=\"$0\">$0</a>"); text = String.format("<html>%s: <i>%s</i><br><br></html>", rule.getRule().name(), hyperlinkedDescription); } else { text = String.format("<html>%s</html>", _("ManageRulesets.HelpNoSelection")); } infoLabel.setText(text); } /** * Shows a confirmation dialog if unsaved changes exist and saves the * ruleset if the user confirms saving */ public void confirmIfUnsavedChanges() { if (unsavedChanges) { int returnValue; returnValue = JOptionPane.showConfirmDialog(this, _("ManageRulesets.ConfirmUnsavedMessage", currentRulesetEditing.getTitle()), _("ManageRulesets.ConfirmUnsavedTitle"), JOptionPane.YES_NO_OPTION); if (returnValue == JOptionPane.YES_OPTION) { save(); } else { // if there is an unsaved ruleset it is deleted here if (createdNotSaved != null) { Ruleset tempRuleset = createdNotSaved; createdNotSaved = null; isNewRuleset = false; rulesets.removeElement(tempRuleset); } } } } /** * Used to fix errors when an cell with active cell editor is removed from * the list. Invoked by all button action listeners before removing / * switching an element from the table. */ private void stopCellEditors() { usedRulesTable.getColumnModel().getColumn(1).getCellEditor().stopCellEditing(); } /** * Internal method, used for generating new Ruleset names. * Searches for the smallest positive integer, for which the default Ruleset name is not in use. * @return Smallest positive integer, which can be used for a generic Ruleset name. */ private int smallestNameIndexNotUsed() { int size = rulesets.getSize(); // TODO: Could be implemented more efficiently for (int i = 1; i <= size; i++) { boolean used = false; for (int j = 0; j < size; j++) { String name = ((Ruleset) rulesets.get(j)).getTitle(); if (name.equals(_("ManageRulesets.NewRulesetDefaulTitle", i))) used = true; } if (!used) { return i; } } return size + 1; } private class RulesetTitleDocumentListener implements DocumentListener { @Override public void removeUpdate(DocumentEvent e) { update(); } @Override public void insertUpdate(DocumentEvent e) { update(); } @Override public void changedUpdate(DocumentEvent e) { update(); } private void update() { if (!currentRulesetEditing.getTitle().equals(rulesetTitle.getText())) { rulesetChanged(); } } } private class RulesetsListSelectionListener implements ListSelectionListener { @Override public void valueChanged(ListSelectionEvent e) { if (!e.getValueIsAdjusting()) { if (!rulesetsList.isSelectionEmpty()) { Ruleset ruleset = (Ruleset) rulesetsList.getSelectedValue(); confirmIfUnsavedChanges(); editRuleset(ruleset); if (isRulesetImmutable(ruleset)) { deleteRulesetButton.setEnabled(false); } else { deleteRulesetButton.setEnabled(true); } } else { deleteRulesetButton.setEnabled(false); setRulesetEditingEnable(false, false); } } } } private class RuleSelectionListener implements ListSelectionListener { /* * (non-Javadoc) * * @see * javax.swing.event.ListSelectionListener#valueChanged(javax.swing. * event.ListSelectionEvent) */ @Override public void valueChanged(ListSelectionEvent e) { ListSelectionModel model = null; Rule rule = null; if (!e.getValueIsAdjusting()) { if (e.getSource() instanceof ListSelectionModel) { model = (ListSelectionModel) e.getSource(); if (!model.isSelectionEmpty()) { rule = usedRules.get(model.getLeadSelectionIndex()); } } else if (e.getSource() instanceof JList) { model = ((JList) e.getSource()).getSelectionModel(); if (!model.isSelectionEmpty()) { rule = (Rule) existingRules.get(model.getLeadSelectionIndex()); } } showInfo(rule); } } } private class SaveAction extends AbstractAction { public SaveAction() { super(); putValue(NAME, _("ManageRulesets.Save")); putValue(Action.SMALL_ICON, Resources.getIcon("save.png")); } @Override public void actionPerformed(ActionEvent e) { save(); } } private class NewRulesetAction extends AbstractAction { NewRulesetAction() { super(_("ManageRulesets.New")); putValue(Action.SMALL_ICON, Resources.getIcon("new.png")); } @Override public void actionPerformed(ActionEvent arg0) { Ruleset newRuleset = new Ruleset(); String newTitle = _("ManageRulesets.NewRulesetDefaulTitle", smallestNameIndexNotUsed()); // if there is still an old unsaved ruleset, the user is asked to do so (or remove the old one) if (createdNotSaved != null) { confirmIfUnsavedChanges(); editRuleset(createdNotSaved); } newRuleset.setTitle(newTitle); rulesets.addElement(newRuleset); isNewRuleset = true; rulesetsList.setSelectedValue(newRuleset, true); deleteRulesetButton.setEnabled(false); // this should be set at last, otherwise the new created ruleset might be deleted immediately createdNotSaved = newRuleset; } } private class DeleteRulesetAction extends AbstractAction { Window window; DeleteRulesetAction(Window window) { super(_("ManageRulesets.Delete")); this.window = window; putValue(Action.SMALL_ICON, Resources.getIcon("delete.png")); } @Override public void actionPerformed(ActionEvent arg0) { if (!rulesetsList.isSelectionEmpty()) { Ruleset ruleset = (Ruleset) rulesetsList.getSelectedValue(); if (controller.showDeleteRulesetDialog(window, ruleset)) { rulesets.removeElement(ruleset); } } } } private class AddRuleAction extends AbstractAction { AddRuleAction() { super(); putValue(Action.SMALL_ICON, Resources.getIcon("right.png")); } @Override public void actionPerformed(ActionEvent arg0) { if (!existingRulesList.isSelectionEmpty()) { for (Object selected : existingRulesList.getSelectedValuesList()) { assert (selected instanceof Rule) : "wrong use"; usedRules.addElement((Rule) selected); existingRules.removeElement(selected); } rulesetChanged(); } } } private class RemoveRuleAction extends AbstractAction { RemoveRuleAction() { super(); putValue(Action.SMALL_ICON, Resources.getIcon("left.png")); } @Override public void actionPerformed(ActionEvent arg0) { Rule rule; if (!usedRulesTable.getSelectionModel().isSelectionEmpty()) { stopCellEditors(); for (int i : usedRulesTable.getSelectedRows()) { rule = usedRules.get(i); existingRules.addElement(rule); usedRules.removeElement(rule); } rulesetChanged(); } } } private class RuleUpAction extends AbstractAction { RuleUpAction() { super(); putValue(Action.SMALL_ICON, Resources.getIcon("up.png")); } @Override public void actionPerformed(ActionEvent arg0) { int minSelIndex = usedRulesTable.getSelectionModel().getMinSelectionIndex(); if (!usedRulesTable.getSelectionModel().isSelectionEmpty() && (minSelIndex > 0)) { int indices[] = usedRulesTable.getSelectedRows(); stopCellEditors(); for (int i : indices) { Rule value1 = usedRules.get(i - 1); Rule value2 = usedRules.get(i); // move entry i to position i-1 usedRules.set(i, value1); usedRules.set(i - 1, value2); // remove selection for i usedRulesTable.removeRowSelectionInterval(i, i); } for (int i : indices) { // add selection index for i-1 usedRulesTable.addRowSelectionInterval(i - 1, i - 1); } rulesetChanged(); } } } private class RuleDownAction extends AbstractAction { RuleDownAction() { super(); putValue(Action.SMALL_ICON, Resources.getIcon("down.png")); } @Override public void actionPerformed(ActionEvent arg0) { int maxSelIndex = usedRulesTable.getSelectionModel().getMaxSelectionIndex(); if (!usedRulesTable.getSelectionModel().isSelectionEmpty() && (maxSelIndex < usedRules.getSize() - 1)) { int indices[] = usedRulesTable.getSelectedRows(); stopCellEditors(); for (int i : indices) { Rule value1 = usedRules.get(i + 1); Rule value2 = usedRules.get(i); // move entry i to position i+1 usedRules.set(i, value1); usedRules.set(i + 1, value2); // remove selection for i usedRulesTable.removeRowSelectionInterval(i, i); } for (int i : indices) { // add selection index for i+1 usedRulesTable.addRowSelectionInterval(i + 1, i + 1); } rulesetChanged(); } } } }