/*
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.actions;
import slash.navigation.base.BaseNavigationPosition;
import slash.navigation.common.BoundingBox;
import slash.navigation.common.NavigationPosition;
import slash.navigation.converter.gui.RouteConverter;
import slash.navigation.converter.gui.helpers.PositionAugmenter;
import slash.navigation.converter.gui.models.PositionsModel;
import slash.navigation.converter.gui.models.PositionsSelectionModel;
import slash.navigation.gui.actions.FrameAction;
import javax.swing.*;
import java.util.ArrayList;
import java.util.List;
import static java.util.Arrays.asList;
import static javax.swing.SwingUtilities.invokeLater;
import static slash.common.io.Transfer.toArray;
import static slash.navigation.gui.events.Range.revert;
import static slash.navigation.gui.helpers.JTableHelper.scrollToPosition;
/**
* {@link Action} that inserts a new {@link BaseNavigationPosition} after
* the last selected row of a {@link JTable}.
*
* @author Christian Pesch
*/
public class AddPositionAction extends FrameAction {
private JTable table;
private PositionsModel positionsModel;
private PositionsSelectionModel positionsSelectionModel;
public AddPositionAction(JTable table, PositionsModel positionsModel, PositionsSelectionModel positionsSelectionModel) {
this.table = table;
this.positionsModel = positionsModel;
this.positionsSelectionModel = positionsSelectionModel;
}
private NavigationPosition calculateCenter(int row) {
NavigationPosition position = positionsModel.getPosition(row);
// if there is only one position or it is the first row, choose the map center
if (row >= positionsModel.getRowCount() - 1)
return null;
// otherwise center between given positions
NavigationPosition second = positionsModel.getPosition(row + 1);
if (!second.hasCoordinates() || !position.hasCoordinates())
return null;
return new BoundingBox(asList(second, position)).getCenter();
}
private PositionAugmenter getBatchPositionAugmenter() {
return RouteConverter.getInstance().getPositionAugmenter();
}
private NavigationPosition insertRow(int row, NavigationPosition position) {
String description = getBatchPositionAugmenter().createDescription(positionsModel.getRowCount() + 1, null);
positionsModel.add(row, position.getLongitude(), position.getLatitude(), position.getElevation(),
position.getSpeed(), position.getTime(), description);
return positionsModel.getPosition(row);
}
private void complementRow(int row) {
getBatchPositionAugmenter().addData(new int[]{row}, true, true, true, true, false);
}
public void run() {
boolean hasInsertedRowInMapCenter = false;
List<NavigationPosition> insertedPositions = new ArrayList<>();
int[] rowIndices = revert(table.getSelectedRows());
// append to table if there is nothing selected
boolean areRowsSelected = rowIndices.length > 0;
if (!areRowsSelected)
rowIndices = new int[]{table.getRowCount()};
for (int row : rowIndices) {
int insertRow = row > positionsModel.getRowCount() - 1 ? row : row + 1;
NavigationPosition center = areRowsSelected ? calculateCenter(row) :
positionsModel.getRowCount() > 0 ? calculateCenter(positionsModel.getRowCount() - 1) : null;
if (center == null) {
// only insert row in map center once
if (hasInsertedRowInMapCenter)
continue;
center = RouteConverter.getInstance().getMapCenter();
hasInsertedRowInMapCenter = true;
}
insertedPositions.add(insertRow(insertRow, center));
}
if (insertedPositions.size() > 0) {
List<Integer> insertedRows = new ArrayList<>();
for (NavigationPosition position : insertedPositions) {
int index = positionsModel.getIndex(position);
insertedRows.add(index);
complementRow(index);
}
final int[] rows = toArray(insertedRows);
final int insertRow = rows.length > 0 ? rows[0] : table.getRowCount();
invokeLater(new Runnable() {
public void run() {
scrollToPosition(table, insertRow);
positionsSelectionModel.setSelectedPositions(rows, true);
}
});
}
}
}