/* This file is part of RouteConverter. RouteConverter 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 2 of the License, or (at your option) any later version. RouteConverter 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 RouteConverter; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Copyright (C) 2007 Christian Pesch. All Rights Reserved. */ package slash.navigation.converter.gui.models; import org.jfree.data.xy.XYSeries; import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelListener; import static java.lang.Integer.MAX_VALUE; import static java.lang.Math.min; import static javax.swing.event.TableModelEvent.*; import static slash.navigation.converter.gui.models.PositionColumns.*; /** * Synchronizes changes at a {@link PositionsModel} with a {@link XYSeries}. * * @author Christian Pesch */ public abstract class PositionsModelToXYSeriesSynchronizer { private PositionsModel positions; private PatchedXYSeries series; protected PositionsModelToXYSeriesSynchronizer(PositionsModel positions, PatchedXYSeries series) { this.positions = positions; this.series = series; initialize(); } protected PositionsModel getPositions() { return positions; } protected PatchedXYSeries getSeries() { return series; } private void initialize() { handleAdd(0, positions.getRowCount() - 1); positions.addTableModelListener(new TableModelListener() { public void tableChanged(TableModelEvent e) { switch (e.getType()) { case INSERT: handleAdd(e.getFirstRow(), e.getLastRow()); break; case UPDATE: handleUpdate(e.getFirstRow(), e.getLastRow(), e.getColumn()); break; case DELETE: if (getPositions().isContinousRange()) return; handleRemove(e.getFirstRow(), e.getLastRow()); break; default: throw new IllegalArgumentException("Event type " + e.getType() + " is not supported"); } } }); } protected void handleAdd(int firstRow, int lastRow) { for (int i = firstRow; i < lastRow + 1; i++) { series.add(i - firstRow, i); } } private void handleUpdate(int firstRow, int lastRow, int columnIndex) { // special treatment for fireTableDataChanged() notifications if (firstRow == 0 && lastRow == MAX_VALUE || // since PositionsModel#revert fires fireTableRowsUpdated(-1, -1) for a complete update firstRow == -1 && lastRow == -1) { handleFullUpdate(); } else { // ignored updates on columns not displayed if (columnIndex == LONGITUDE_COLUMN_INDEX || columnIndex == LATITUDE_COLUMN_INDEX || columnIndex == ALL_COLUMNS) { handleIntervalXUpdate(firstRow, lastRow); } else if (columnIndex == ELEVATION_COLUMN_INDEX || columnIndex == SPEED_COLUMN_INDEX) { handleIntervalYUpdate(firstRow, lastRow); } } } protected void handleFullUpdate() { series.delete(0, series.getItemCount() - 1); if (positions.getRowCount() > 0) handleAdd(0, positions.getRowCount() - 1); } protected void handleIntervalXUpdate(int firstRow, int lastRow) { getSeries().setFireSeriesChanged(false); series.delete(firstRow, min(lastRow, series.getItemCount() - 1)); handleAdd(firstRow, lastRow); getSeries().setFireSeriesChanged(true); getSeries().fireSeriesChanged(); } protected void handleIntervalYUpdate(int firstRow, int lastRow) { for (int i = firstRow; i < lastRow + 1; i++) { series.update((double) i - firstRow, i); } } protected void handleRemove(int firstRow, int lastRow) { series.delete(firstRow, lastRow); } }