Improve Download UI panel

* Remove favorites (no longer implementing), start trying to highlight
  relevant entries based off of mapview location.
* Hide the active layer table in download options
* Add deactivate/activate UI functionality
* Modify table so that rows can be removed.
  * This is so that we don't have duplicate columns in smaller views (e.g.
    Preferences).
* This also modifies column widths to better match string widths. This
  will most likely need to be modified.
* Have the map/list use more space
* Hide URL field in download window
* Highlight name field in download window
* Add a column for source provider information

Signed-off-by: Taylor Smock <taylor.smock@kaart.com>
pull/1/head
Taylor Smock 2020-06-01 17:26:27 -06:00
rodzic a8d60a9820
commit a958a8f04d
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 625F6A74A3E4311A
3 zmienionych plików z 242 dodań i 134 usunięć

Wyświetl plik

@ -31,11 +31,11 @@ public class MapWithAIDownloadOptions extends JPanel implements DownloadSelectio
public MapWithAIDownloadOptions() { public MapWithAIDownloadOptions() {
optionPanel = new JPanel(new GridBagLayout()); optionPanel = new JPanel(new GridBagLayout());
JPanel favorites = new JPanel(); JPanel infoHeader = new JPanel();
favorites.add(new JLabel("TODO: Favorites go here!")); // TODO infoHeader.add(new JLabel("Browse and download extra data sets to facilitate your mapping needs."));
optionPanel.add(favorites, GBC.eol().fill(GBC.HORIZONTAL).anchor(GBC.NORTH)); optionPanel.add(infoHeader, GBC.eol().fill(GBC.HORIZONTAL).anchor(GBC.NORTH));
mapwithaiProvidersPanel = new MapWithAIProvidersPanel(this, MapWithAILayerInfo.getInstance()); mapwithaiProvidersPanel = new MapWithAIProvidersPanel(this, MapWithAILayerInfo.getInstance(), false);
optionPanel.add(mapwithaiProvidersPanel, GBC.eol().fill(GBC.HORIZONTAL).anchor(GBC.CENTER)); optionPanel.add(mapwithaiProvidersPanel, GBC.eol().fill(GBC.BOTH).anchor(GBC.CENTER));
mapwithaiProvidersPanel.defaultMap.addPropertyChangeListener(this); mapwithaiProvidersPanel.defaultMap.addPropertyChangeListener(this);
} }
@ -47,6 +47,8 @@ public class MapWithAIDownloadOptions extends JPanel implements DownloadSelectio
@Override @Override
public void setDownloadArea(Bounds area) { public void setDownloadArea(Bounds area) {
// This is (currently) never called.
// See https://josm.openstreetmap.de/ticket/19310
mapwithaiProvidersPanel.setCurrentBounds(area); mapwithaiProvidersPanel.setCurrentBounds(area);
} }

Wyświetl plik

@ -83,7 +83,7 @@ public class MapWithAIPreferences extends DefaultTabPreferenceSetting {
private Component getServerList(PreferenceTabbedPane gui) { private Component getServerList(PreferenceTabbedPane gui) {
info = new MapWithAILayerInfo(MapWithAILayerInfo.instance); info = new MapWithAILayerInfo(MapWithAILayerInfo.instance);
return new MapWithAIProvidersPanel(gui, info); return new MapWithAIProvidersPanel(gui, info, true);
} }
private Component getSettingsPanel(PreferenceTabbedPane gui) { private Component getSettingsPanel(PreferenceTabbedPane gui) {

Wyświetl plik

@ -12,7 +12,10 @@ import java.awt.GridBagLayout;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter; import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -20,6 +23,8 @@ import java.util.Optional;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.swing.AbstractAction; import javax.swing.AbstractAction;
import javax.swing.Box; import javax.swing.Box;
@ -41,10 +46,11 @@ import javax.swing.table.TableColumnModel;
import org.openstreetmap.gui.jmapviewer.Coordinate; import org.openstreetmap.gui.jmapviewer.Coordinate;
import org.openstreetmap.gui.jmapviewer.MapPolygonImpl; import org.openstreetmap.gui.jmapviewer.MapPolygonImpl;
import org.openstreetmap.gui.jmapviewer.MapRectangleImpl; import org.openstreetmap.gui.jmapviewer.MapRectangleImpl;
import org.openstreetmap.gui.jmapviewer.interfaces.ICoordinate;
import org.openstreetmap.gui.jmapviewer.interfaces.MapPolygon; import org.openstreetmap.gui.jmapviewer.interfaces.MapPolygon;
import org.openstreetmap.gui.jmapviewer.interfaces.MapRectangle; import org.openstreetmap.gui.jmapviewer.interfaces.MapRectangle;
import org.openstreetmap.josm.data.Bounds; import org.openstreetmap.josm.data.Bounds;
import org.openstreetmap.josm.data.imagery.ImageryInfo; import org.openstreetmap.josm.data.coor.LatLon;
import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryBounds; import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryBounds;
import org.openstreetmap.josm.data.imagery.Shape; import org.openstreetmap.josm.data.imagery.Shape;
import org.openstreetmap.josm.data.preferences.NamedColorProperty; import org.openstreetmap.josm.data.preferences.NamedColorProperty;
@ -60,6 +66,7 @@ import org.openstreetmap.josm.plugins.mapwithai.data.mapwithai.MapWithAILayerInf
import org.openstreetmap.josm.tools.GBC; import org.openstreetmap.josm.tools.GBC;
import org.openstreetmap.josm.tools.ImageProvider; import org.openstreetmap.josm.tools.ImageProvider;
import org.openstreetmap.josm.tools.ImageProvider.ImageSizes; import org.openstreetmap.josm.tools.ImageProvider.ImageSizes;
import org.openstreetmap.josm.tools.ImageResource;
import org.openstreetmap.josm.tools.ListenerList; import org.openstreetmap.josm.tools.ListenerList;
import org.openstreetmap.josm.tools.Logging; import org.openstreetmap.josm.tools.Logging;
@ -110,51 +117,84 @@ public class MapWithAIProvidersPanel extends JPanel {
} }
/** /**
* class to render the URL information of MapWithAI source * class to render an information of MapWithAI source
* *
* @since 8065 * @param <T> type of information
*/ */
private static class MapWithAIURLTableCellRenderer extends DefaultTableCellRenderer implements AreaListener { private static class MapWithAITableCellRenderer<T> extends DefaultTableCellRenderer implements AreaListener {
private static final long serialVersionUID = 184934756853356357L; private static final long serialVersionUID = 1739280307217707613L;
private static final NamedColorProperty IMAGERY_BACKGROUND_COLOR = new NamedColorProperty( private static final NamedColorProperty IMAGERY_BACKGROUND_COLOR = new NamedColorProperty(
marktr("MapWithAI Background: Default"), new Color(200, 255, 200)); marktr("MapWithAI Background: Default"), new Color(200, 255, 200));
private static final NamedColorProperty MAPWITHAI_AREA_BACKGROUND_COLOR = new NamedColorProperty( private static final NamedColorProperty MAPWITHAI_AREA_BACKGROUND_COLOR = new NamedColorProperty(
marktr("MapWithAI Background: Layer in area"), Color.decode("#f1ffc7")); marktr("MapWithAI Background: Layer in area"), Color.decode("#f1ffc7"));
private final transient List<MapWithAIInfo> layers; private final Function<T, Object> mapper;
private final Function<T, String> tooltip;
private final BiConsumer<T, JLabel> decorator;
private final Function<Object, MapWithAIInfo> reverseMapper;
private Bounds area; private final boolean highlightIfActive;
MapWithAIURLTableCellRenderer(List<MapWithAIInfo> layers) { private transient Bounds area;
this.layers = layers;
private MapWithAIProvidersPanel provider;
/**
* Initialize a cell renderer with specific rules
*
* @param mapper Map from <T> to an Object (to get a cell renderer)
* @param reverseMapper Map from an Object to <T>
* @param tooltip The tooltip to show
* @param decorator The decorator
* @param highlightIfActive If true, highlight when the entry is activated
*/
MapWithAITableCellRenderer(MapWithAIProvidersPanel panel, Function<T, Object> mapper,
Function<Object, MapWithAIInfo> reverseMapper, Function<T, String> tooltip,
BiConsumer<T, JLabel> decorator, boolean highlightIfActive) {
this.provider = panel;
this.mapper = mapper;
this.reverseMapper = reverseMapper;
this.tooltip = tooltip;
this.decorator = decorator;
this.highlightIfActive = highlightIfActive;
} }
@Override @Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, @SuppressWarnings("unchecked")
int row, int column) { public final Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, boolean hasFocus, int row, int column) {
column); T obj = (T) value;
JLabel label = (JLabel) super.getTableCellRendererComponent(table, mapper.apply(obj), isSelected, hasFocus,
row, column);
Color defaultColor = UIManager.getColor("Table.background"); Color defaultColor = UIManager.getColor("Table.background");
Color selectedColor = UIManager.getColor("Table.selectionBackground");
GuiHelper.setBackgroundReadable(label, defaultColor); GuiHelper.setBackgroundReadable(label, defaultColor);
if (value != null) { // Fix #8159
String t = value.toString(); GuiHelper.setBackgroundReadable(label, isSelected ? selectedColor : defaultColor);
MapWithAIInfo info = layers.stream().filter(i -> t.equals(i.getUrl())).findFirst().orElse(null); if (this.highlightIfActive) {
if (info != null) { MapWithAIInfo info = obj instanceof MapWithAIInfo ? (MapWithAIInfo) obj : reverseMapper.apply(obj);
GuiHelper.setBackgroundReadable(label, IMAGERY_BACKGROUND_COLOR.get()); if (info == null) {
GuiHelper.setBackgroundReadable(label, defaultColor);
} else { } else {
info = MapWithAILayerInfo.getInstance().getAllDefaultLayers().stream() if (provider.activeModel.contains(info)) {
.filter(i -> t.equals(i.getUrl())).findFirst().orElse(null); Color t = IMAGERY_BACKGROUND_COLOR.get();
if (info != null) { GuiHelper.setBackgroundReadable(label, isSelected ? t.darker() : t);
if (this.area != null && (this.area.intersects(info.getBounds()) } else if (this.area != null && (this.area.intersects(info.getBounds())
|| (info.getBounds() != null && info.getBounds().intersects(this.area)))) { || (info.getBounds() != null && info.getBounds().intersects(this.area)))) {
GuiHelper.setBackgroundReadable(label, MAPWITHAI_AREA_BACKGROUND_COLOR.get()); Color t = MAPWITHAI_AREA_BACKGROUND_COLOR.get();
} else { GuiHelper.setBackgroundReadable(label, isSelected ? t.darker() : t);
GuiHelper.setBackgroundReadable(label, defaultColor); } else {
} GuiHelper.setBackgroundReadable(label, isSelected ? selectedColor : defaultColor);
} }
} }
label.setToolTipText((String) value);
}
if (obj != null) {
label.setToolTipText(tooltip.apply(obj));
if (decorator != null) {
decorator.accept(obj, label);
}
} }
return label; return label;
} }
@ -166,39 +206,16 @@ public class MapWithAIProvidersPanel extends JPanel {
} }
/** /**
* class to render an information of MapWithAI source * class to render the URL information of MapWithAI source
* *
* @param <T> type of information * @since 8065
*/ */
private static class MapWithAITableCellRenderer<T> extends DefaultTableCellRenderer { private static class MapWithAIURLTableCellRenderer extends MapWithAITableCellRenderer<String> {
private static final long serialVersionUID = 1739280307217707613L; private static final long serialVersionUID = 184934756853356357L;
private final Function<T, Object> mapper;
private final Function<T, String> tooltip;
private final BiConsumer<T, JLabel> decorator;
MapWithAITableCellRenderer(Function<T, Object> mapper, Function<T, String> tooltip, MapWithAIURLTableCellRenderer(MapWithAIProvidersPanel panel) {
BiConsumer<T, JLabel> decorator) { super(panel, s -> s, u -> MapWithAILayerInfo.getInstance().getAllDefaultLayers().stream()
this.mapper = mapper; .filter(i -> u.equals(i.getUrl())).findFirst().orElse(null), u -> u, null, true);
this.tooltip = tooltip;
this.decorator = decorator;
}
@Override
@SuppressWarnings("unchecked")
public final Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
T obj = (T) value;
JLabel label = (JLabel) super.getTableCellRendererComponent(table, mapper.apply(obj), isSelected, hasFocus,
row, column);
GuiHelper.setBackgroundReadable(label, isSelected ? UIManager.getColor("Table.selectionBackground")
: UIManager.getColor("Table.background"));
if (obj != null) {
label.setToolTipText(tooltip.apply(obj));
if (decorator != null) {
decorator.accept(obj, label);
}
}
return label;
} }
} }
@ -209,24 +226,37 @@ public class MapWithAIProvidersPanel extends JPanel {
extends MapWithAIProvidersPanel.MapWithAITableCellRenderer<MapWithAICategory> { extends MapWithAIProvidersPanel.MapWithAITableCellRenderer<MapWithAICategory> {
private static final long serialVersionUID = -6729184413815746598L; private static final long serialVersionUID = -6729184413815746598L;
MapWithAICategoryTableCellRenderer() { MapWithAICategoryTableCellRenderer(MapWithAIProvidersPanel panel) {
super(cat -> null, cat -> tr("MapWithAI category: {0}", cat.getDescription()), super(panel, cat -> null, i -> null, cat -> tr("MapWithAI category: {0}", cat.getDescription()),
(cat, label) -> label.setIcon(cat.getIcon(ImageSizes.TABLE))); (cat, label) -> label.setIcon(cat.getIcon(ImageSizes.TABLE)), false);
} }
} }
/** /**
* class to render the country information of MapWithAI source * class to render the country information of MapWithAI source
*/ */
private static class MapWithAICountryTableCellRenderer private static class MapWithAITypeTableCellRenderer
extends MapWithAIProvidersPanel.MapWithAITableCellRenderer<String> { extends MapWithAIProvidersPanel.MapWithAITableCellRenderer<MapWithAICategory> {
private static final long serialVersionUID = 5975643008500799758L; private static final long serialVersionUID = 5975643008500799758L;
MapWithAICountryTableCellRenderer() { MapWithAITypeTableCellRenderer(MapWithAIProvidersPanel panel) {
super(code -> code, ImageryInfo::getLocalizedCountry, null); super(panel, MapWithAICategory::getDescription, i -> null, MapWithAICategory::getDescription, null, false);
} }
} }
/**
* class to render the source provider information of a MapWithAI source
*/
private static class MapWithAIProviderTableCellRenderer
extends MapWithAIProvidersPanel.MapWithAITableCellRenderer<String> {
private static final long serialVersionUID = -3824289458721409139L;
MapWithAIProviderTableCellRenderer(MapWithAIProvidersPanel panel) {
super(panel, s -> s, s -> null, s -> s, null, false);
}
}
/** /**
* class to render the name information of Imagery source * class to render the name information of Imagery source
*/ */
@ -234,8 +264,9 @@ public class MapWithAIProvidersPanel extends JPanel {
extends MapWithAIProvidersPanel.MapWithAITableCellRenderer<MapWithAIInfo> { extends MapWithAIProvidersPanel.MapWithAITableCellRenderer<MapWithAIInfo> {
private static final long serialVersionUID = 6669934435517244629L; private static final long serialVersionUID = 6669934435517244629L;
MapWithAINameTableCellRenderer() { MapWithAINameTableCellRenderer(MapWithAIProvidersPanel panel, boolean showActive) {
super(info -> info == null ? null : info.getName(), MapWithAIInfo::getToolTipText, null); super(panel, info -> info == null ? null : info.getName(), i -> null, MapWithAIInfo::getToolTipText, null,
showActive);
} }
} }
@ -244,8 +275,9 @@ public class MapWithAIProvidersPanel extends JPanel {
* *
* @param gui The parent preference tab pane * @param gui The parent preference tab pane
* @param layerInfoArg The list of imagery entries to display * @param layerInfoArg The list of imagery entries to display
* @param showActive If true, show selected entries along with custom entries.
*/ */
public MapWithAIProvidersPanel(final JComponent gui, MapWithAILayerInfo layerInfoArg) { public MapWithAIProvidersPanel(final JComponent gui, MapWithAILayerInfo layerInfoArg, boolean showActive) {
super(new GridBagLayout()); super(new GridBagLayout());
this.gui = gui; this.gui = gui;
this.layerInfo = layerInfoArg; this.layerInfo = layerInfoArg;
@ -275,26 +307,40 @@ public class MapWithAIProvidersPanel extends JPanel {
defaultModel.addTableModelListener(e -> activeTable.repaint()); defaultModel.addTableModelListener(e -> activeTable.repaint());
activeModel.addTableModelListener(e -> defaultTable.repaint()); activeModel.addTableModelListener(e -> defaultTable.repaint());
int tenXWidth = activeTable.getFontMetrics(activeTable.getFont()).stringWidth("XXXXXXXXXX");
TableColumnModel mod = defaultTable.getColumnModel(); TableColumnModel mod = defaultTable.getColumnModel();
mod.getColumn(3).setPreferredWidth(775); int urlWidth = (showActive ? 3 : 0) * tenXWidth;
MapWithAIURLTableCellRenderer defaultTableCellRenderer = new MapWithAIURLTableCellRenderer( mod.getColumn(4).setPreferredWidth((showActive ? 2 : 0) * tenXWidth);
layerInfo.getLayers()); mod.getColumn(4).setCellRenderer(new MapWithAIProviderTableCellRenderer(this));
areaListeners.addListener(defaultTableCellRenderer); mod.getColumn(3).setPreferredWidth(urlWidth);
mod.getColumn(3).setCellRenderer(defaultTableCellRenderer); MapWithAIURLTableCellRenderer defaultUrlTableCellRenderer = new MapWithAIURLTableCellRenderer(this);
mod.getColumn(2).setPreferredWidth(475); mod.getColumn(3).setCellRenderer(defaultUrlTableCellRenderer);
mod.getColumn(2).setCellRenderer(new MapWithAINameTableCellRenderer()); mod.getColumn(2).setPreferredWidth((int) ((showActive ? 0 : 0.3) * tenXWidth));
mod.getColumn(1).setCellRenderer(new MapWithAICountryTableCellRenderer());
mod.getColumn(0).setPreferredWidth(50); mod.getColumn(2).setCellRenderer(new MapWithAITypeTableCellRenderer(this));
mod.getColumn(0).setCellRenderer(new MapWithAICategoryTableCellRenderer());
mod.getColumn(0).setPreferredWidth(50); MapWithAINameTableCellRenderer defaultNameTableCellRenderer = new MapWithAINameTableCellRenderer(this,
!showActive);
mod.getColumn(1).setCellRenderer(defaultNameTableCellRenderer);
mod.getColumn(1).setPreferredWidth((showActive ? 3 : 2) * tenXWidth);
mod.getColumn(0).setCellRenderer(new MapWithAICategoryTableCellRenderer(this));
mod.getColumn(0).setMaxWidth(ImageProvider.ImageSizes.MENU.getAdjustedWidth() + 5);
if (showActive) {
defaultTable.removeColumn(mod.getColumn(4));
defaultTable.removeColumn(mod.getColumn(2));
areaListeners.addListener(defaultUrlTableCellRenderer);
} else {
defaultTable.removeColumn(mod.getColumn(3));
areaListeners.addListener(defaultNameTableCellRenderer);
}
mod = activeTable.getColumnModel(); mod = activeTable.getColumnModel();
mod.getColumn(1).setPreferredWidth(800); mod.getColumn(1).setPreferredWidth(800);
MapWithAIURLTableCellRenderer activeTableCellRenderer = new MapWithAIURLTableCellRenderer( MapWithAIURLTableCellRenderer activeTableCellRenderer = new MapWithAIURLTableCellRenderer(this);
layerInfo.getAllDefaultLayers());
areaListeners.addListener(activeTableCellRenderer); areaListeners.addListener(activeTableCellRenderer);
mod.getColumn(1).setCellRenderer(activeTableCellRenderer); mod.getColumn(1).setCellRenderer(activeTableCellRenderer);
mod.getColumn(0).setPreferredWidth(200); mod.getColumn(0).setMaxWidth(200);
RemoveEntryAction remove = new RemoveEntryAction(); RemoveEntryAction remove = new RemoveEntryAction();
activeTable.getSelectionModel().addListSelectionListener(remove); activeTable.getSelectionModel().addListSelectionListener(remove);
@ -373,10 +419,7 @@ public class MapWithAIProvidersPanel extends JPanel {
add(Box.createHorizontalGlue(), GBC.eol().fill(GridBagConstraints.HORIZONTAL)); add(Box.createHorizontalGlue(), GBC.eol().fill(GridBagConstraints.HORIZONTAL));
add(new JLabel(tr("Selected entries:")), GBC.eol().insets(5, 0, 0, 0));
JScrollPane scroll = new JScrollPane(activeTable); JScrollPane scroll = new JScrollPane(activeTable);
add(scroll, GBC.std().fill(GridBagConstraints.BOTH).span(GridBagConstraints.RELATIVE).weight(1.0, 0.4).insets(5,
0, 0, 5));
scroll.setPreferredSize(new Dimension(200, 200)); scroll.setPreferredSize(new Dimension(200, 200));
activeToolbar = new JToolBar(JToolBar.VERTICAL); activeToolbar = new JToolBar(JToolBar.VERTICAL);
@ -386,7 +429,12 @@ public class MapWithAIProvidersPanel extends JPanel {
activeToolbar.add(new NewEntryAction(MapWithAIInfo.MapWithAIType.THIRD_PARTY)); activeToolbar.add(new NewEntryAction(MapWithAIInfo.MapWithAIType.THIRD_PARTY));
activeToolbar.add(edit); activeToolbar.add(edit);
activeToolbar.add(remove); activeToolbar.add(remove);
add(activeToolbar, GBC.eol().anchor(GBC.NORTH).insets(0, 0, 5, 5)); if (showActive) {
add(new JLabel(tr("Selected entries:")), GBC.eol().insets(5, 0, 0, 0));
add(scroll, GBC.std().fill(GridBagConstraints.BOTH).span(GridBagConstraints.RELATIVE).weight(1.0, 0.4)
.insets(5, 0, 0, 5));
add(activeToolbar, GBC.eol().anchor(GBC.NORTH).insets(0, 0, 5, 5));
}
} }
/** /**
@ -615,6 +663,8 @@ public class MapWithAIProvidersPanel extends JPanel {
private class ActivateAction extends AbstractAction implements ListSelectionListener { private class ActivateAction extends AbstractAction implements ListSelectionListener {
private static final long serialVersionUID = -452335751201424801L; private static final long serialVersionUID = -452335751201424801L;
private final ImageResource activate;
private final ImageResource deactivate;
/** /**
* Constructs a new {@code ActivateAction}. * Constructs a new {@code ActivateAction}.
@ -622,11 +672,27 @@ public class MapWithAIProvidersPanel extends JPanel {
ActivateAction() { ActivateAction() {
putValue(NAME, tr("Activate")); putValue(NAME, tr("Activate"));
putValue(SHORT_DESCRIPTION, tr("Copy selected default entries from the list above into the list below.")); putValue(SHORT_DESCRIPTION, tr("Copy selected default entries from the list above into the list below."));
new ImageProvider("preferences", "activate-down").getResource().attachImageIcon(this, true); activate = new ImageProvider("svpDown").setMaxSize(ImageProvider.ImageSizes.MENU).getResource();
activate.attachImageIcon(this, true);
deactivate = new ImageProvider("svpUp").setMaxSize(ImageProvider.ImageSizes.MENU).getResource();
} }
protected void updateEnabledState() { protected void updateEnabledState() {
setEnabled(defaultTable.getSelectedRowCount() > 0); setEnabled(defaultTable.getSelectedRowCount() > 0);
List<MapWithAIInfo> selected = Arrays.stream(defaultTable.getSelectedRows())
.map(defaultTable::convertRowIndexToModel).mapToObj(defaultModel::getRow)
.collect(Collectors.toList());
if (selected.stream().anyMatch(activeModel::doesNotContain)) {
activate.attachImageIcon(this, true);
putValue(NAME, tr("Activate"));
putValue(SHORT_DESCRIPTION,
tr("Copy selected default entries from the list above into the list below."));
} else {
deactivate.attachImageIcon(this, true);
putValue(NAME, tr("Deactivate"));
putValue(SHORT_DESCRIPTION,
tr("Remove selected default entries from the list above into the list below."));
}
} }
@Override @Override
@ -642,26 +708,29 @@ public class MapWithAIProvidersPanel extends JPanel {
JOptionPane.INFORMATION_MESSAGE); JOptionPane.INFORMATION_MESSAGE);
return; return;
} }
List<MapWithAIInfo> selected = Arrays.stream(defaultTable.getSelectedRows())
outer: for (int line : lines) { .map(defaultTable::convertRowIndexToModel).mapToObj(defaultModel::getRow)
MapWithAIInfo info = defaultModel.getRow(defaultTable.convertRowIndexToModel(line)); .collect(Collectors.toList());
if (selected.stream().anyMatch(activeModel::doesNotContain)) {
// Check if an entry with exactly the same values already exists List<MapWithAIInfo> toAdd = selected.stream().filter(activeModel::doesNotContain)
for (int j = 0; j < activeModel.getRowCount(); j++) { .collect(Collectors.toList());
if (info.equalsBaseValues(activeModel.getRow(j))) { activeTable.getSelectionModel().clearSelection();
// Select the already existing row so the user has for (MapWithAIInfo info : toAdd) {
// some feedback in case an entry exists activeModel.addRow(new MapWithAIInfo(info));
activeTable.getSelectionModel().setSelectionInterval(j, j); int lastLine = activeModel.getRowCount() - 1;
activeTable.scrollRectToVisible(activeTable.getCellRect(j, 0, true)); activeTable.getSelectionModel().setSelectionInterval(lastLine, lastLine);
continue outer; activeTable.scrollRectToVisible(activeTable.getCellRect(lastLine, 0, true));
}
} }
selected.removeIf(toAdd::contains);
activeModel.addRow(new MapWithAIInfo(info)); selected.stream().mapToInt(activeModel::getRowIndex).filter(i -> i >= 0).forEach(j -> {
int lastLine = activeModel.getRowCount() - 1; activeTable.getSelectionModel().addSelectionInterval(j, j);
activeTable.getSelectionModel().setSelectionInterval(lastLine, lastLine); activeTable.scrollRectToVisible(activeTable.getCellRect(j, 0, true));
activeTable.scrollRectToVisible(activeTable.getCellRect(lastLine, 0, true)); });
} else {
selected.stream().mapToInt(activeModel::getRowIndex).filter(i -> i >= 0).boxed()
.sorted(Collections.reverseOrder()).sorted().forEach(activeModel::removeRow);
} }
updateEnabledState();
} }
} }
@ -765,6 +834,41 @@ public class MapWithAIProvidersPanel extends JPanel {
throw new ArrayIndexOutOfBoundsException(Integer.toString(column)); throw new ArrayIndexOutOfBoundsException(Integer.toString(column));
} }
} }
/**
* Check if the active table contains the MapWithAIInfo object
*
* @param info The info to check
* @return {@code true} if any of the active layers is functionally equal
*/
public boolean contains(MapWithAIInfo info) {
return layerInfo.getLayers().stream().anyMatch(info::equalsBaseValues);
}
/**
* Check if the active table does not contain the MapWithAIInfo object
*
* @param info The info to check
* @return {@code true} if none of the active layers is functionally equal
*/
public boolean doesNotContain(MapWithAIInfo info) {
return !contains(info);
}
/**
* Get the index that a specified MapWithAIInfo resides at
*
* @param info The MapWithAIInfo to find
* @return The row index, or -1 if it isn't in the model
*/
public int getRowIndex(MapWithAIInfo info) {
for (int j = 0; j < getRowCount(); j++) {
if (info.equalsBaseValues(getRow(j))) {
return j;
}
}
return -1;
}
} }
/** /**
@ -772,12 +876,23 @@ public class MapWithAIProvidersPanel extends JPanel {
*/ */
public class MapWithAIDefaultLayerTableModel extends DefaultTableModel { public class MapWithAIDefaultLayerTableModel extends DefaultTableModel {
private static final long serialVersionUID = -2966437364160797385L; private static final long serialVersionUID = -2966437364160797385L;
private final List<Class<?>> columnTypes;
private final List<Function<MapWithAIInfo, Object>> columnDataRetrieval;
/** /**
* Constructs a new {@code MapWithAIDefaultLayerTableModel}. * Constructs a new {@code MapWithAIDefaultLayerTableModel}.
*/ */
public MapWithAIDefaultLayerTableModel() { public MapWithAIDefaultLayerTableModel() {
setColumnIdentifiers(new String[] { "", "", tr("Menu Name (Default)"), tr("MapWithAI URL (Default)") }); setColumnIdentifiers(new String[] { "", tr("Menu Name (Default)"), tr("Type"),
tr("MapWithAI URL (Default)"), tr("Provider") });
columnTypes = Stream.of(MapWithAICategory.class, MapWithAIInfo.class, MapWithAICategory.class, String.class,
String.class).collect(Collectors.toCollection(ArrayList::new));
columnDataRetrieval = new ArrayList<>();
columnDataRetrieval.add(info -> Optional.ofNullable(info.getCategory()).orElse(MapWithAICategory.OTHER));
columnDataRetrieval.add(info -> info);
columnDataRetrieval.add(info -> Optional.ofNullable(info.getCategory()).orElse(MapWithAICategory.OTHER));
columnDataRetrieval.add(MapWithAIInfo::getUrl);
columnDataRetrieval.add(i -> i.getAttributionText(0, null, null));
} }
/** /**
@ -790,6 +905,13 @@ public class MapWithAIProvidersPanel extends JPanel {
return layerInfo.getAllDefaultLayers().get(row); return layerInfo.getAllDefaultLayers().get(row);
} }
@Override
public void removeRow(int row) {
columnTypes.remove(row);
columnDataRetrieval.remove(row);
super.removeRow(row);
}
@Override @Override
public int getRowCount() { public int getRowCount() {
return layerInfo.getAllDefaultLayers().size(); return layerInfo.getAllDefaultLayers().size();
@ -797,35 +919,19 @@ public class MapWithAIProvidersPanel extends JPanel {
@Override @Override
public Class<?> getColumnClass(int columnIndex) { public Class<?> getColumnClass(int columnIndex) {
switch (columnIndex) { if (columnIndex < columnTypes.size()) {
case 0: return columnTypes.get(columnIndex);
return MapWithAICategory.class;
case 1:
return String.class;
case 2:
return MapWithAIInfo.class;
case 3:
return String.class;
default:
return super.getColumnClass(columnIndex);
} }
return super.getColumnClass(columnIndex);
} }
@Override @Override
public Object getValueAt(int row, int column) { public Object getValueAt(int row, int column) {
MapWithAIInfo info = layerInfo.getAllDefaultLayers().get(row); MapWithAIInfo info = layerInfo.getAllDefaultLayers().get(row);
switch (column) { if (column < columnDataRetrieval.size()) {
case 0: return columnDataRetrieval.get(column).apply(info);
return Optional.ofNullable(info.getCategory()).orElse(MapWithAICategory.OTHER);
case 1:
return info.getCountryCode();
case 2:
return info;
case 3:
return info.getUrl();
default:
return null;
} }
return null;
} }
@Override @Override