views:

40

answers:

1

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.

A: 

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
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