/** * * Copyright * 2009-2015 Jayway Products AB * 2016-2017 Föreningen Sambruk * * Licensed under AGPL, Version 3.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.gnu.org/licenses/agpl.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package se.streamsource.streamflow.client.ui.account; import javax.swing.*; import java.beans.PropertyVetoException; import java.beans.VetoableChangeListener; import java.beans.VetoableChangeSupport; /** * Quick impl of a list selection model which respects a veto before * changing selection state. The veto is effect in SINGLE_SELECTION mode * only. * Remark: Thanks to Jeanette Winzenburg (SwingLabs project) for the code example. */ public class VetoableListSelectionModel extends DefaultListSelectionModel { private VetoableChangeSupport vetoableChangeSupport; /** * Defaults to SINGLE_SELECTION mode. */ public VetoableListSelectionModel() { super(); setSelectionMode( SINGLE_SELECTION ); } public void addVetoableChangeListener( VetoableChangeListener l ) { if (vetoableChangeSupport == null) { vetoableChangeSupport = new VetoableChangeSupport( this ); } vetoableChangeSupport.addVetoableChangeListener( l ); } public void removeVetoableChangeListener( VetoableChangeListener l ) { if (vetoableChangeSupport == null) return; vetoableChangeSupport.removeVetoableChangeListener( l ); } private void fireVetoableChange( int oldSelectionIndex, int newSelectionIndex ) throws PropertyVetoException { if (!isVetoable()) return; vetoableChangeSupport.fireVetoableChange( "selectedIndex", oldSelectionIndex, newSelectionIndex ); } private boolean isVetoable() { return !((vetoableChangeSupport == null) || (getSelectionMode() != SINGLE_SELECTION)) && vetoableChangeSupport.hasListeners( null ); } @Override public void clearSelection() { if (isSelectionEmpty()) return; if (isVetoable()) { try { fireVetoableChange( getMinSelectionIndex() , -1 ); } catch (PropertyVetoException e) { // vetoed - do nothing return; } } super.clearSelection(); } @Override public void moveLeadSelectionIndex( int leadIndex ) { if (isVetoable()) { try { fireVetoableChange( getLeadSelectionIndex(), leadIndex ); } catch (PropertyVetoException e) { // vetoed - do nothing return; } } super.moveLeadSelectionIndex( leadIndex ); } @Override public void removeSelectionInterval( int index0, int index1 ) { if (isSelectionEmpty() || invalidRange( index0, index1 )) return; if (isVetoable() && inRange( index0, index1 )) { try { fireVetoableChange( getMinSelectionIndex(), -1 ); } catch (PropertyVetoException e) { // vetoed - do nothing return; } } super.removeSelectionInterval( index0, index1 ); } /** * @param index0 one end of the range, must be non-negative * @param index1 the other end of the range, must be non-negative * @return true if current min selection in range, false otherwise */ private boolean inRange( int index0, int index1 ) { int clearMin = Math.min( index0, index1 ); int clearMax = Math.max( index0, index1 ); return getMinSelectionIndex() >= clearMin && getMinSelectionIndex() <= clearMax; } /** * @param index0 * @param index1 */ private boolean invalidRange( int index0, int index1 ) { return index0 == -1 || index1 == -1; } @Override public void setLeadSelectionIndex( int leadIndex ) { if (isVetoable()) { try { fireVetoableChange( getLeadSelectionIndex(), leadIndex ); } catch (PropertyVetoException e) { // vetoed - do nothing return; } } super.setLeadSelectionIndex( leadIndex ); } @Override public void setSelectionInterval( int index0, int index1 ) { if (isVetoable()) { try { fireVetoableChange( getMinSelectionIndex(), index0 ); } catch (PropertyVetoException e) { // vetoed - do nothing return; } } super.setSelectionInterval( index0, index1 ); } public void insertIndexInterval( int index, int length, boolean before ) { if ((SINGLE_SELECTION == getSelectionMode()) && isSelectedIndex( index ) && before) { // keep the selection on whatever it was before setSelectionInterval( index + length, index + length ); } else { super.insertIndexInterval( index, length, before ); } } }