5

I found this forum thread which suggests overriding ListSelectionModel to prevent rows from being selected.

I would like to prevent selection changes when there are unsaved changes (external to the table) for the currently selected item UNTIL the user confirms the discard. Something like:

public class confirmSelectionChange extends DefaultListSelectionModel {
    public void setSelectionInterval(int index0, int index1) {
        if (unsavedChanges()) {
            super.setSelectionInterval(int index0, int index1);
        }
    }

    private boolean unsavedChanges() {
        if (noUnsavedChangesExist) {
            return true;
        }

        // Present modal dialog: save, discard cancel
        if (dialogAnswer == SAVE) {
            // save changes
            return true;
        } else if (dialogAnswer == DISCARD) {
            return true;
        } else {
            return false;
        }
    }
}

Is it possible to insert blocking code in the middle of ListSelectionModel changes? Is there a better way to intercept selection change events?

I'm already listening for them but the change has already happened by then.

trashgod
  • 203,806
  • 29
  • 246
  • 1,045
Matt
  • 123
  • 1
  • 6

1 Answers1

4

My final solution (thanks in part to this code guru) was to create an anonymous inner class that extends JTable and overrides changeSelection(). Tried a separate class since I read that some people don't think anonymous inner classes are good OO design but I needed to know about the editing state plus I had to call save/discard methods. Who needs encapsulation when it's your own code anyway? ;-)

jTableMemberList = new JTable() {
    public void changeSelection(int rowIndex, int columnIndex, boolean toggle,
                                boolean extend) {
        // Member is being edited and they've clicked on a DIFFERENT row (this
        // method gets called even when the selection isn't actually changing)
        if (editModeIsActive && getSelectedRow() != rowIndex) {
            // User was editing, now they're trying to move away without saving
            Object[] options = {"Save", "Discard", "Cancel"};
            int n = JOptionPane.showOptionDialog(this,
                                            "There are unsaved changes for the "
                                            + "currently selected member.\n\n"
                                            + "Would you like to save them?",
                                            "Save changes?",
                                            JOptionPane.YES_NO_CANCEL_OPTION,
                                            JOptionPane.WARNING_MESSAGE,
                                            null,
                                            options,
                                            options[0]);

            if (n == JOptionPane.YES_OPTION) {
                saveChanges();
            } else if (n == JOptionPane.NO_OPTION) {
                discardChanges();
            } else {
                // Exit without passing call on to super
                return;
            }
        }

        // make the selection change
        super.changeSelection(rowIndex, columnIndex, toggle, extend);
    }
};

This solution seems to work so far but I haven't tested it extensively. There may be bugs or gotcha's lurking in one of the dark corners of this code...

Hope it helps someone else!

Matt
  • 123
  • 1
  • 6
  • Sorry if it's bad form to ask, answer AND comment but I just wanted to add that in my actual program I moved the above dialog code to its own method since there are other circumstances when I needed the same save/discard/cancel functionality (e.g. on quit). – Matt Jun 17 '10 at 20:17