/* 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 slash.navigation.base.*; import slash.navigation.converter.gui.helpers.AbstractListDataListener; import javax.swing.*; import javax.swing.event.*; import java.util.List; import static javax.swing.event.ListDataEvent.CONTENTS_CHANGED; import static slash.navigation.converter.gui.models.CharacteristicsModel.IGNORE; import static slash.navigation.converter.gui.models.PositionColumns.DISTANCE_COLUMN_INDEX; import static slash.navigation.gui.helpers.JTableHelper.isFirstToLastRow; /** * Acts as a {@link ComboBoxModel} for the routes of a {@link FormatAndRoutes}. * * @author Christian Pesch */ public class FormatAndRoutesModelImpl extends AbstractListModel implements FormatAndRoutesModel { private final PositionsModel positionsModel; private final CharacteristicsModel characteristicsModel; private boolean modified = false; private FormatAndRoutes formatAndRoutes; public FormatAndRoutesModelImpl(PositionsModel positionsModel, CharacteristicsModel characteristicsModel) { this.positionsModel = positionsModel; this.characteristicsModel = characteristicsModel; positionsModel.addTableModelListener(new TableModelListener() { public void tableChanged(TableModelEvent e) { // ignore events following setSelectedRoute() if (isFirstToLastRow(e)) return; // ignore distance column updates from the overlay position model if (e.getColumn() == DISTANCE_COLUMN_INDEX) return; setModified(true); } }); addListDataListener(new AbstractListDataListener() { public void process(ListDataEvent e) { // ignore events following setSelectedRoute() if (e.getType() == CONTENTS_CHANGED && e.getIndex0() == -1 && e.getIndex1() == -1) return; setModified(true); } }); characteristicsModel.addListDataListener(new ListDataListener() { public void intervalAdded(ListDataEvent e) { } public void intervalRemoved(ListDataEvent e) { } public void contentsChanged(ListDataEvent e) { // ignore events following setRoute() if (e.getType() == CONTENTS_CHANGED && e.getIndex0() == IGNORE && e.getIndex1() == IGNORE) return; if (formatAndRoutes.getFormat().isWritingRouteCharacteristics()) setModified(true); fireContentsChanged(this, -1, -1); } }); } @SuppressWarnings("unchecked") public List<BaseRoute> getRoutes() { return formatAndRoutes != null ? formatAndRoutes.getRoutes() : null; } public void setRoutes(FormatAndRoutes<BaseNavigationFormat, BaseRoute, BaseNavigationPosition> formatAndRoutes) { int index1 = getRoutes() != null ? getRoutes().size() - 1 : 0; if (index1 != -1) fireIntervalRemoved(this, 0, index1); this.formatAndRoutes = formatAndRoutes; index1 = getRoutes().size() - 1; if (index1 != -1) { setSelectedItem(getRoutes().get(0)); fireIntervalAdded(this, 0, index1); } else { setSelectedItem(null); } setModified(false); } @SuppressWarnings("unchecked") public NavigationFormat<BaseRoute> getFormat() { return formatAndRoutes != null ? formatAndRoutes.getFormat() : null; } @SuppressWarnings("unchecked") public void setFormat(NavigationFormat<BaseRoute> format) { formatAndRoutes.setFormat(format); fireContentsChanged(this, -1, -1); } public void addPositionList(int index, BaseRoute route) { getRoutes().add(index, route); fireIntervalAdded(this, index, index); } public void renamePositionList(String name) { BaseRoute route = getSelectedRoute(); route.setName(name); int index = getRoutes().indexOf(route); fireContentsChanged(this, index, index); } public void removePositionList(BaseRoute route) { int index = getIndex(route); if (index != -1) { if (getElementAt(index) == getSelectedRoute()) { if (index == 0) { setSelectedItem(getSize() == 1 ? null : getElementAt(index + 1)); } else { setSelectedItem(getElementAt(index - 1)); } } getRoutes().remove(index); fireIntervalRemoved(this, index, index); } } public int getSize() { return getRoutes() != null ? getRoutes().size() : 0; } public Object getElementAt(int index) { return getRoute(index); } public BaseRoute getRoute(int index) { return getRoutes().get(index); } public int getIndex(BaseRoute route) { return getRoutes().indexOf(route); } public boolean isModified() { return modified; } public void setModified(boolean modified) { if (this.modified != modified) { this.modified = modified; fireModified(); } } protected void fireModified() { Object[] listeners = listenerList.getListenerList(); for (int i = listeners.length - 2; i >= 0; i -= 2) { if (listeners[i] == ChangeListener.class) { ((ChangeListener) listeners[i + 1]).stateChanged(null); } } } public void addModifiedListener(ChangeListener listener) { listenerList.add(ChangeListener.class, listener); } public Object getSelectedItem() { return getSelectedRoute(); } public BaseRoute getSelectedRoute() { return positionsModel.getRoute(); } @SuppressWarnings("unchecked") public void setSelectedItem(Object anItem) { setSelectedRoute((BaseRoute) anItem); } @SuppressWarnings("unchecked") public void setSelectedRoute(BaseRoute route) { if ((getSelectedRoute() != null && !getSelectedRoute().equals(route)) || getSelectedRoute() == null && route != null) { positionsModel.setRoute(route); characteristicsModel.setRoute(route); fireContentsChanged(this, -1, -1); } } }