2019-11-19 16:47:45 +00:00
|
|
|
// License: GPL. For details, see LICENSE file.
|
2020-03-26 22:16:42 +00:00
|
|
|
package org.openstreetmap.josm.plugins.mapwithai.gui.preferences;
|
2019-09-24 12:06:49 +00:00
|
|
|
|
|
|
|
import static org.openstreetmap.josm.tools.I18n.tr;
|
|
|
|
|
2021-10-20 21:18:26 +00:00
|
|
|
import javax.swing.Box;
|
|
|
|
import javax.swing.JButton;
|
|
|
|
import javax.swing.JCheckBox;
|
|
|
|
import javax.swing.JLabel;
|
|
|
|
import javax.swing.JPanel;
|
|
|
|
import javax.swing.JScrollPane;
|
|
|
|
import javax.swing.JSpinner;
|
|
|
|
import javax.swing.JTabbedPane;
|
|
|
|
import javax.swing.SpinnerNumberModel;
|
|
|
|
|
2019-09-30 20:36:18 +00:00
|
|
|
import java.awt.Component;
|
2019-11-21 22:04:25 +00:00
|
|
|
import java.awt.Cursor;
|
2019-10-29 15:40:15 +00:00
|
|
|
import java.awt.Dimension;
|
2019-09-24 12:06:49 +00:00
|
|
|
import java.awt.GridBagConstraints;
|
|
|
|
import java.awt.GridBagLayout;
|
2019-11-21 22:04:25 +00:00
|
|
|
import java.awt.event.MouseAdapter;
|
|
|
|
import java.awt.event.MouseEvent;
|
2019-10-29 15:40:15 +00:00
|
|
|
import java.util.ArrayList;
|
2019-11-13 14:33:55 +00:00
|
|
|
import java.util.Arrays;
|
2019-10-29 15:40:15 +00:00
|
|
|
import java.util.Collections;
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.Map;
|
|
|
|
import java.util.TreeMap;
|
|
|
|
|
|
|
|
import org.openstreetmap.josm.actions.ExpertToggleAction;
|
2020-07-01 14:44:05 +00:00
|
|
|
import org.openstreetmap.josm.data.preferences.BooleanProperty;
|
2020-03-26 22:45:41 +00:00
|
|
|
import org.openstreetmap.josm.gui.preferences.DefaultTabPreferenceSetting;
|
2019-09-24 12:06:49 +00:00
|
|
|
import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane;
|
2019-10-29 15:40:15 +00:00
|
|
|
import org.openstreetmap.josm.gui.preferences.advanced.PrefEntry;
|
2020-03-26 22:16:42 +00:00
|
|
|
import org.openstreetmap.josm.plugins.mapwithai.MapWithAIPlugin;
|
2019-10-17 18:08:37 +00:00
|
|
|
import org.openstreetmap.josm.plugins.mapwithai.backend.MapWithAIPreferenceHelper;
|
2020-03-26 22:45:41 +00:00
|
|
|
import org.openstreetmap.josm.plugins.mapwithai.data.mapwithai.MapWithAILayerInfo;
|
|
|
|
import org.openstreetmap.josm.plugins.mapwithai.gui.preferences.mapwithai.MapWithAIProvidersPanel;
|
2019-10-29 15:40:15 +00:00
|
|
|
import org.openstreetmap.josm.spi.preferences.StringSetting;
|
|
|
|
import org.openstreetmap.josm.tools.GBC;
|
2019-11-21 22:04:25 +00:00
|
|
|
import org.openstreetmap.josm.tools.ImageProvider;
|
|
|
|
import org.openstreetmap.josm.tools.OpenBrowser;
|
2019-09-24 12:06:49 +00:00
|
|
|
|
2020-03-26 22:45:41 +00:00
|
|
|
public class MapWithAIPreferences extends DefaultTabPreferenceSetting {
|
2019-10-03 18:09:26 +00:00
|
|
|
private final JCheckBox switchLayerCheckBox;
|
2019-10-17 18:08:37 +00:00
|
|
|
private final JCheckBox mergeBuildingAddressCheckBox;
|
2019-10-03 18:09:26 +00:00
|
|
|
private final JSpinner maximumAdditionSpinner;
|
2019-11-13 14:33:55 +00:00
|
|
|
private final ReplacementPreferenceTable replacementPreferenceTable;
|
|
|
|
private final List<PrefEntry> replacementTableDisplayData;
|
2019-10-30 15:56:27 +00:00
|
|
|
private static final int MAX_SELECTED_TO_EDIT = 1;
|
2019-10-03 18:09:26 +00:00
|
|
|
|
2019-10-11 15:02:38 +00:00
|
|
|
public MapWithAIPreferences() {
|
2020-03-26 22:45:41 +00:00
|
|
|
super("mapwithai", tr("MapWithAI preferences"), tr("Modify MapWithAI preferences"), false, new JTabbedPane());
|
|
|
|
|
2019-10-03 18:09:26 +00:00
|
|
|
switchLayerCheckBox = new JCheckBox();
|
2021-03-16 20:17:50 +00:00
|
|
|
maximumAdditionSpinner = new JSpinner(new SpinnerNumberModel(MapWithAIPreferenceHelper.getMaximumAddition(), 0,
|
|
|
|
MapWithAIPreferenceHelper.getDefaultMaximumAddition() * 10, 1));
|
2019-10-17 18:08:37 +00:00
|
|
|
mergeBuildingAddressCheckBox = new JCheckBox();
|
2019-11-13 14:33:55 +00:00
|
|
|
replacementTableDisplayData = new ArrayList<>();
|
|
|
|
fillReplacementTagDisplayData(replacementTableDisplayData);
|
|
|
|
replacementPreferenceTable = new ReplacementPreferenceTable(replacementTableDisplayData);
|
2019-10-29 15:40:15 +00:00
|
|
|
}
|
|
|
|
|
2019-11-13 14:33:55 +00:00
|
|
|
private static void fillReplacementTagDisplayData(List<PrefEntry> list) {
|
2019-10-30 15:56:27 +00:00
|
|
|
final Map<String, String> current = new TreeMap<>(MapWithAIPreferenceHelper.getReplacementTags());
|
2020-07-01 18:04:14 +00:00
|
|
|
for (final Map.Entry<String, String> entry : current.entrySet()) {
|
2019-11-20 22:00:01 +00:00
|
|
|
list.add(
|
|
|
|
new PrefEntry(entry.getKey(), new StringSetting(entry.getValue()), new StringSetting(null), false));
|
2019-10-29 15:40:15 +00:00
|
|
|
}
|
2019-10-03 18:09:26 +00:00
|
|
|
}
|
2019-09-30 20:36:18 +00:00
|
|
|
|
2019-09-26 19:28:20 +00:00
|
|
|
@Override
|
|
|
|
public void addGui(PreferenceTabbedPane gui) {
|
2020-03-26 22:45:41 +00:00
|
|
|
final JPanel p = gui.createPreferenceTab(this);
|
|
|
|
final JTabbedPane panel = getTabPane();
|
|
|
|
if (panel.getTabCount() == 0) {
|
|
|
|
panel.addTab(tr("Servers"), getServerList(gui));
|
|
|
|
panel.addTab(tr("Settings"), getSettingsPanel(gui));
|
|
|
|
}
|
2020-12-23 16:01:55 +00:00
|
|
|
p.add(panel, GBC.std().fill(GridBagConstraints.BOTH));
|
2020-03-26 22:45:41 +00:00
|
|
|
}
|
|
|
|
|
2020-07-01 18:04:14 +00:00
|
|
|
private static Component getServerList(PreferenceTabbedPane gui) {
|
2020-06-18 20:20:59 +00:00
|
|
|
return new MapWithAIProvidersPanel(gui, MapWithAIProvidersPanel.Options.SHOW_ACTIVE);
|
2020-03-26 22:45:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private Component getSettingsPanel(PreferenceTabbedPane gui) {
|
|
|
|
final JPanel pane = new JPanel(new GridBagLayout());
|
2019-11-20 22:00:01 +00:00
|
|
|
final int width = 200;
|
|
|
|
final int height = 200;
|
2019-10-03 18:09:26 +00:00
|
|
|
final JLabel switchLayer = new JLabel(tr("Automatically switch layers"));
|
|
|
|
final JLabel maximumAddition = new JLabel(tr("Maximum features (add)"));
|
2019-10-21 22:01:19 +00:00
|
|
|
final JLabel mergeBuildingWithAddress = new JLabel(tr("Merge address nodes and buildings"));
|
2019-09-26 19:28:20 +00:00
|
|
|
|
2019-11-06 23:55:57 +00:00
|
|
|
switchLayer.setToolTipText(
|
|
|
|
tr("If checked, automatically switch from the {0} layer to the OSM layer when objects are added",
|
|
|
|
MapWithAIPlugin.NAME));
|
|
|
|
maximumAddition.setToolTipText(tr(
|
|
|
|
"This is the maximum number of complete OSM objects that can be added from the {0} layer, child objects do not count to this limit",
|
|
|
|
MapWithAIPlugin.NAME));
|
|
|
|
mergeBuildingWithAddress.setToolTipText(tr(
|
2020-03-31 16:11:54 +00:00
|
|
|
"If checked, automatically merge address nodes onto added buildings, if and only if one address is within the building boundary"));
|
2019-11-06 23:55:57 +00:00
|
|
|
|
2019-10-17 18:08:37 +00:00
|
|
|
switchLayerCheckBox.setSelected(MapWithAIPreferenceHelper.isSwitchLayers());
|
2019-11-14 17:11:07 +00:00
|
|
|
switchLayerCheckBox.setToolTipText(switchLayer.getToolTipText());
|
2019-10-17 18:08:37 +00:00
|
|
|
mergeBuildingAddressCheckBox.setSelected(MapWithAIPreferenceHelper.isMergeBuildingAddress());
|
2019-11-14 17:11:07 +00:00
|
|
|
mergeBuildingAddressCheckBox.setToolTipText(mergeBuildingWithAddress.getToolTipText());
|
2019-09-26 19:28:20 +00:00
|
|
|
|
2019-11-13 14:33:55 +00:00
|
|
|
pane.setAlignmentY(Component.TOP_ALIGNMENT);
|
|
|
|
pane.setAlignmentX(Component.LEFT_ALIGNMENT);
|
|
|
|
|
2019-11-20 22:00:01 +00:00
|
|
|
final GBC first = GBC.std().weight(0, 1).anchor(GridBagConstraints.WEST);
|
|
|
|
final GBC second = GBC.eol().fill(GridBagConstraints.HORIZONTAL);
|
|
|
|
final GBC buttonInsets = GBC.std().insets(5, 5, 0, 0);
|
2019-11-13 14:33:55 +00:00
|
|
|
|
|
|
|
pane.add(switchLayer, first);
|
2019-10-29 15:40:15 +00:00
|
|
|
|
2019-11-13 14:33:55 +00:00
|
|
|
pane.add(switchLayerCheckBox, second);
|
2019-11-14 17:11:07 +00:00
|
|
|
switchLayerCheckBox.setToolTipText(switchLayer.getToolTipText());
|
2019-10-29 15:40:15 +00:00
|
|
|
|
2019-11-13 14:33:55 +00:00
|
|
|
pane.add(maximumAddition, first);
|
|
|
|
pane.add(maximumAdditionSpinner, second);
|
2019-11-14 17:11:07 +00:00
|
|
|
maximumAdditionSpinner.setToolTipText(maximumAddition.getToolTipText());
|
2019-10-29 15:40:15 +00:00
|
|
|
|
2019-11-13 14:33:55 +00:00
|
|
|
pane.add(mergeBuildingWithAddress, first);
|
|
|
|
pane.add(mergeBuildingAddressCheckBox, second);
|
2019-10-29 15:40:15 +00:00
|
|
|
|
2019-11-13 14:33:55 +00:00
|
|
|
final Component expertHorizontalGlue = Box.createHorizontalGlue();
|
|
|
|
pane.add(expertHorizontalGlue, GBC.eol().fill(GridBagConstraints.HORIZONTAL));
|
2020-07-01 14:44:05 +00:00
|
|
|
final JLabel previewFeatureSets = new JLabel(tr("Show Preview DataSets"));
|
|
|
|
final JCheckBox previewFeatureSetCheckbox = new JCheckBox();
|
2020-10-07 13:27:58 +00:00
|
|
|
BooleanProperty previewFeatureSetProperty = MapWithAILayerInfo.SHOW_PREVIEW;
|
2020-07-01 14:44:05 +00:00
|
|
|
previewFeatureSetCheckbox.setToolTipText(tr("If selected, show datasets which may have various issues"));
|
|
|
|
previewFeatureSetCheckbox.setSelected(Boolean.TRUE.equals(previewFeatureSetProperty.get()));
|
|
|
|
previewFeatureSetCheckbox
|
|
|
|
.addChangeListener(l -> previewFeatureSetProperty.put(previewFeatureSetCheckbox.isSelected()));
|
|
|
|
pane.add(previewFeatureSets, first);
|
|
|
|
pane.add(previewFeatureSetCheckbox, second);
|
|
|
|
|
2020-03-19 13:18:04 +00:00
|
|
|
final JLabel replacementTags = new JLabel(tr("Replacement Tags (to be replaced on download)"));
|
2019-11-13 14:33:55 +00:00
|
|
|
pane.add(replacementTags, first);
|
|
|
|
final JScrollPane scroll2 = new JScrollPane(replacementPreferenceTable);
|
|
|
|
pane.add(scroll2, GBC.eol().fill(GridBagConstraints.BOTH));
|
|
|
|
scroll2.setPreferredSize(new Dimension(width, height));
|
2019-10-29 15:40:15 +00:00
|
|
|
|
2019-11-13 14:33:55 +00:00
|
|
|
pane.add(new JLabel(), first);
|
2019-11-20 22:00:01 +00:00
|
|
|
final JPanel replaceAddEditDeleteScroll2 = new JPanel(new GridBagLayout());
|
2019-11-14 17:11:07 +00:00
|
|
|
pane.add(replaceAddEditDeleteScroll2, second);
|
|
|
|
final JButton addScroll2 = new JButton(tr("Add"));
|
|
|
|
replaceAddEditDeleteScroll2.add(addScroll2, buttonInsets);
|
|
|
|
addScroll2.addActionListener(e -> {
|
2019-11-13 14:33:55 +00:00
|
|
|
final PrefEntry pe = replacementPreferenceTable.addPreference(gui);
|
2019-11-20 22:00:01 +00:00
|
|
|
if ((pe != null) && (pe.getValue() instanceof StringSetting)) {
|
2019-11-13 14:33:55 +00:00
|
|
|
replacementTableDisplayData.add(pe);
|
|
|
|
Collections.sort(replacementTableDisplayData);
|
|
|
|
replacementPreferenceTable.fireDataChanged();
|
2019-10-29 15:40:15 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2019-11-14 17:11:07 +00:00
|
|
|
final JButton editScroll2 = new JButton(tr("Edit"));
|
|
|
|
replaceAddEditDeleteScroll2.add(editScroll2, buttonInsets);
|
|
|
|
editScroll2.addActionListener(e -> {
|
2019-11-13 14:33:55 +00:00
|
|
|
final List<PrefEntry> toEdit = replacementPreferenceTable.getSelectedItems();
|
2019-10-30 15:56:27 +00:00
|
|
|
if (toEdit.size() == MAX_SELECTED_TO_EDIT) {
|
2019-11-13 14:33:55 +00:00
|
|
|
replacementPreferenceTable.editPreference(gui);
|
2019-10-29 15:40:15 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2019-11-14 17:11:07 +00:00
|
|
|
final JButton deleteScroll2 = new JButton(tr("Delete"));
|
|
|
|
replaceAddEditDeleteScroll2.add(deleteScroll2, buttonInsets);
|
|
|
|
deleteScroll2.addActionListener(e -> {
|
2019-11-13 14:33:55 +00:00
|
|
|
final List<PrefEntry> toRemove = replacementPreferenceTable.getSelectedItems();
|
2019-10-29 15:40:15 +00:00
|
|
|
if (!toRemove.isEmpty()) {
|
2019-11-13 14:33:55 +00:00
|
|
|
replacementTableDisplayData.removeAll(toRemove);
|
2019-10-29 15:40:15 +00:00
|
|
|
}
|
2019-11-13 14:33:55 +00:00
|
|
|
replacementPreferenceTable.fireDataChanged();
|
2019-10-29 15:40:15 +00:00
|
|
|
});
|
|
|
|
|
2019-11-21 22:04:25 +00:00
|
|
|
pane.add(Box.createHorizontalGlue(), second);
|
|
|
|
|
|
|
|
JButton kaartLogo = new JButton(ImageProvider.getIfAvailable("kaart") == null ? null
|
|
|
|
: new ImageProvider("kaart").setHeight(ImageProvider.ImageSizes.SETTINGS_TAB.getAdjustedHeight())
|
|
|
|
.get());
|
|
|
|
kaartLogo.setToolTipText(tr("Link to source code repository"));
|
|
|
|
kaartLogo.addMouseListener(new MouseAdapter() {
|
|
|
|
@Override
|
|
|
|
public void mouseClicked(MouseEvent e) {
|
2022-10-10 14:49:07 +00:00
|
|
|
OpenBrowser.displayUrl("https://github.com/JOSM/MapWithAI");
|
2019-11-21 22:04:25 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
kaartLogo.setCursor(new Cursor(Cursor.HAND_CURSOR));
|
|
|
|
pane.add(kaartLogo, GBC.std().anchor(GridBagConstraints.WEST));
|
|
|
|
|
|
|
|
JButton mapWithAILogo = new JButton(ImageProvider.getIfAvailable("mapwithai_text") == null ? null
|
|
|
|
: new ImageProvider("mapwithai_text")
|
|
|
|
.setHeight(ImageProvider.ImageSizes.SETTINGS_TAB.getAdjustedHeight()).get());
|
|
|
|
mapWithAILogo.setCursor(new Cursor(Cursor.HAND_CURSOR));
|
|
|
|
mapWithAILogo.addMouseListener(new MouseAdapter() {
|
|
|
|
@Override
|
|
|
|
public void mouseClicked(MouseEvent e) {
|
|
|
|
OpenBrowser.displayUrl("https://mapwith.ai");
|
|
|
|
}
|
|
|
|
});
|
|
|
|
pane.add(mapWithAILogo, GBC.eol().anchor(GridBagConstraints.EAST));
|
|
|
|
|
2020-07-01 14:44:05 +00:00
|
|
|
Arrays.asList(replaceAddEditDeleteScroll2, scroll2, expertHorizontalGlue, replacementTags, previewFeatureSets,
|
|
|
|
previewFeatureSetCheckbox).forEach(ExpertToggleAction::addVisibilitySwitcher);
|
2020-03-26 22:45:41 +00:00
|
|
|
return pane;
|
2019-09-26 19:28:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean ok() {
|
2019-10-17 18:08:37 +00:00
|
|
|
MapWithAIPreferenceHelper.setSwitchLayers(switchLayerCheckBox.isSelected(), true);
|
2019-10-03 18:09:26 +00:00
|
|
|
final Object value = maximumAdditionSpinner.getValue();
|
2021-10-20 21:18:26 +00:00
|
|
|
MapWithAIPreferenceHelper.setMergeBuildingAddress(this.mergeBuildingAddressCheckBox.isSelected(), true);
|
2019-10-03 16:45:26 +00:00
|
|
|
if (value instanceof Number) {
|
2019-10-17 18:08:37 +00:00
|
|
|
MapWithAIPreferenceHelper.setMaximumAddition(((Number) value).intValue(), true);
|
2019-09-30 20:36:18 +00:00
|
|
|
}
|
2020-06-18 20:20:59 +00:00
|
|
|
MapWithAILayerInfo.getInstance().save();
|
|
|
|
MapWithAILayerInfo.getInstance().clear();
|
|
|
|
MapWithAILayerInfo.getInstance().load(false);
|
2019-11-13 14:33:55 +00:00
|
|
|
MapWithAIPreferenceHelper.setReplacementTags(convertReplacementPrefToMap(replacementTableDisplayData));
|
2019-09-26 19:28:20 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-11-13 14:33:55 +00:00
|
|
|
private static Map<String, String> convertReplacementPrefToMap(List<PrefEntry> displayData) {
|
2019-10-30 15:56:27 +00:00
|
|
|
final Map<String, String> returnMap = displayData.isEmpty() ? Collections.emptyMap() : new TreeMap<>();
|
2019-10-29 15:40:15 +00:00
|
|
|
displayData.forEach(entry -> returnMap.put(entry.getKey(), entry.getValue().getValue().toString()));
|
|
|
|
return returnMap;
|
|
|
|
}
|
|
|
|
|
2019-09-26 19:28:20 +00:00
|
|
|
@Override
|
|
|
|
public boolean isExpert() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-10-03 18:09:26 +00:00
|
|
|
/**
|
2020-07-01 18:04:14 +00:00
|
|
|
* This method returns the checkbox used for deciding if layers should be
|
|
|
|
* switched.
|
|
|
|
*
|
2019-10-03 18:09:26 +00:00
|
|
|
* @return The {@code JCheckBox} for whether or not we are switching layers.
|
|
|
|
*/
|
|
|
|
public JCheckBox getSwitchLayerCheckBox() {
|
|
|
|
return switchLayerCheckBox;
|
|
|
|
}
|
|
|
|
|
2020-07-01 18:04:14 +00:00
|
|
|
/**
|
|
|
|
* Get the checkbox for merging buildings/addresses
|
|
|
|
*
|
|
|
|
* @return The checkbox
|
|
|
|
*/
|
2019-10-17 18:08:37 +00:00
|
|
|
public JCheckBox getMergeBuildingAddressCheckBox() {
|
|
|
|
return mergeBuildingAddressCheckBox;
|
|
|
|
}
|
|
|
|
|
2019-10-03 18:09:26 +00:00
|
|
|
/**
|
2020-07-01 18:04:14 +00:00
|
|
|
* This is the spinner used to determine maximum additions (and maximum
|
|
|
|
* selections).
|
|
|
|
*
|
2019-10-03 18:09:26 +00:00
|
|
|
* @return {@code JSpinner} for the maximum additions
|
|
|
|
*/
|
|
|
|
public JSpinner getMaximumAdditionSpinner() {
|
|
|
|
return maximumAdditionSpinner;
|
|
|
|
}
|
2019-09-24 12:06:49 +00:00
|
|
|
}
|