001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.history; 003 004import java.util.HashSet; 005import java.util.Set; 006 007import javax.swing.DefaultListSelectionModel; 008import javax.swing.ListSelectionModel; 009import javax.swing.event.ListSelectionEvent; 010import javax.swing.event.ListSelectionListener; 011 012/** 013 * Helper class to ensure that two (or more) {@link javax.swing.JTable}s always 014 * have the same entries selected. 015 * 016 * The tables are usually displayed side-by-side. 017 */ 018public class SelectionSynchronizer implements ListSelectionListener { 019 020 private final Set<ListSelectionModel> participants; 021 private boolean preventRecursion; 022 023 /** 024 * Constructs a new {@code SelectionSynchronizer}. 025 */ 026 public SelectionSynchronizer() { 027 participants = new HashSet<>(); 028 } 029 030 /** 031 * Add {@link ListSelectionModel} of the table to participate in selection 032 * synchronization. 033 * 034 * Call this method for all tables that should have their selection synchronized. 035 * @param model the selection model of the table 036 */ 037 public void participateInSynchronizedSelection(ListSelectionModel model) { 038 if (model == null) 039 return; 040 if (participants.contains(model)) 041 return; 042 participants.add(model); 043 model.addListSelectionListener(this); 044 } 045 046 @Override 047 public void valueChanged(ListSelectionEvent e) { 048 if (preventRecursion) { 049 return; 050 } 051 preventRecursion = true; 052 DefaultListSelectionModel referenceModel = (DefaultListSelectionModel) e.getSource(); 053 int i = referenceModel.getMinSelectionIndex(); 054 int j = referenceModel.getMaxSelectionIndex(); 055 for (ListSelectionModel model : participants) { 056 if (model == e.getSource()) { 057 continue; 058 } 059 model.setSelectionInterval(i, j); 060 } 061 preventRecursion = false; 062 } 063}