[3719] | 1 | // License: GPL. For details, see LICENSE file.
|
---|
[1329] | 2 | package org.openstreetmap.josm.gui.download;
|
---|
| 3 |
|
---|
| 4 | import static org.openstreetmap.josm.tools.I18n.tr;
|
---|
| 5 |
|
---|
[2361] | 6 | import java.awt.BorderLayout;
|
---|
[1329] | 7 | import java.awt.Component;
|
---|
| 8 | import java.awt.Dimension;
|
---|
| 9 | import java.awt.GridBagLayout;
|
---|
[2717] | 10 | import java.awt.GridLayout;
|
---|
[1329] | 11 | import java.awt.event.ActionEvent;
|
---|
| 12 | import java.awt.event.MouseAdapter;
|
---|
| 13 | import java.awt.event.MouseEvent;
|
---|
[2361] | 14 | import java.io.IOException;
|
---|
[7033] | 15 | import java.io.Reader;
|
---|
[1329] | 16 | import java.net.URL;
|
---|
[2717] | 17 | import java.text.DecimalFormat;
|
---|
[2361] | 18 | import java.util.ArrayList;
|
---|
[2362] | 19 | import java.util.Collections;
|
---|
[2361] | 20 | import java.util.LinkedList;
|
---|
| 21 | import java.util.List;
|
---|
| 22 | import java.util.StringTokenizer;
|
---|
[1329] | 23 |
|
---|
[2361] | 24 | import javax.swing.AbstractAction;
|
---|
| 25 | import javax.swing.BorderFactory;
|
---|
| 26 | import javax.swing.DefaultListSelectionModel;
|
---|
[1329] | 27 | import javax.swing.JButton;
|
---|
| 28 | import javax.swing.JLabel;
|
---|
[7628] | 29 | import javax.swing.JOptionPane;
|
---|
[1329] | 30 | import javax.swing.JPanel;
|
---|
| 31 | import javax.swing.JScrollPane;
|
---|
| 32 | import javax.swing.JTable;
|
---|
| 33 | import javax.swing.ListSelectionModel;
|
---|
[2361] | 34 | import javax.swing.UIManager;
|
---|
| 35 | import javax.swing.event.DocumentEvent;
|
---|
| 36 | import javax.swing.event.DocumentListener;
|
---|
[1329] | 37 | import javax.swing.event.ListSelectionEvent;
|
---|
| 38 | import javax.swing.event.ListSelectionListener;
|
---|
[2361] | 39 | import javax.swing.table.DefaultTableColumnModel;
|
---|
[1329] | 40 | import javax.swing.table.DefaultTableModel;
|
---|
[2361] | 41 | import javax.swing.table.TableCellRenderer;
|
---|
| 42 | import javax.swing.table.TableColumn;
|
---|
[10212] | 43 | import javax.xml.parsers.ParserConfigurationException;
|
---|
[1329] | 44 |
|
---|
| 45 | import org.openstreetmap.josm.Main;
|
---|
[2327] | 46 | import org.openstreetmap.josm.data.Bounds;
|
---|
[2361] | 47 | import org.openstreetmap.josm.gui.ExceptionDialogUtil;
|
---|
[7628] | 48 | import org.openstreetmap.josm.gui.HelpAwareOptionPane;
|
---|
[12634] | 49 | import org.openstreetmap.josm.gui.MainApplication;
|
---|
[2361] | 50 | import org.openstreetmap.josm.gui.PleaseWaitRunnable;
|
---|
[7628] | 51 | import org.openstreetmap.josm.gui.util.GuiHelper;
|
---|
[2362] | 52 | import org.openstreetmap.josm.gui.widgets.HistoryComboBox;
|
---|
[5429] | 53 | import org.openstreetmap.josm.gui.widgets.JosmComboBox;
|
---|
[11002] | 54 | import org.openstreetmap.josm.io.NameFinder;
|
---|
| 55 | import org.openstreetmap.josm.io.NameFinder.SearchResult;
|
---|
[2361] | 56 | import org.openstreetmap.josm.io.OsmTransferException;
|
---|
[2717] | 57 | import org.openstreetmap.josm.tools.GBC;
|
---|
[9171] | 58 | import org.openstreetmap.josm.tools.HttpClient;
|
---|
[2361] | 59 | import org.openstreetmap.josm.tools.ImageProvider;
|
---|
[12620] | 60 | import org.openstreetmap.josm.tools.Logging;
|
---|
[5587] | 61 | import org.openstreetmap.josm.tools.Utils;
|
---|
[1329] | 62 | import org.xml.sax.SAXException;
|
---|
[7628] | 63 | import org.xml.sax.SAXParseException;
|
---|
[1329] | 64 |
|
---|
[9606] | 65 | /**
|
---|
| 66 | * Place selector.
|
---|
| 67 | * @since 1329
|
---|
| 68 | */
|
---|
[1329] | 69 | public class PlaceSelection implements DownloadSelection {
|
---|
[2362] | 70 | private static final String HISTORY_KEY = "download.places.history";
|
---|
[1329] | 71 |
|
---|
[2362] | 72 | private HistoryComboBox cbSearchExpression;
|
---|
[2361] | 73 | private NamedResultTableModel model;
|
---|
[2717] | 74 | private NamedResultTableColumnModel columnmodel;
|
---|
[2361] | 75 | private JTable tblSearchResults;
|
---|
| 76 | private DownloadDialog parent;
|
---|
[6883] | 77 | private static final Server[] SERVERS = new Server[] {
|
---|
[11002] | 78 | new Server("Nominatim", NameFinder.NOMINATIM_URL, tr("Class Type"), tr("Bounds"))
|
---|
[2717] | 79 | };
|
---|
[7017] | 80 | private final JosmComboBox<Server> server = new JosmComboBox<>(SERVERS);
|
---|
[2512] | 81 |
|
---|
[2717] | 82 | private static class Server {
|
---|
[8510] | 83 | public final String name;
|
---|
| 84 | public final String url;
|
---|
| 85 | public final String thirdcol;
|
---|
| 86 | public final String fourthcol;
|
---|
| 87 |
|
---|
[8836] | 88 | Server(String n, String u, String t, String f) {
|
---|
[2717] | 89 | name = n;
|
---|
| 90 | url = u;
|
---|
| 91 | thirdcol = t;
|
---|
| 92 | fourthcol = f;
|
---|
| 93 | }
|
---|
[8510] | 94 |
|
---|
| 95 | @Override
|
---|
| 96 | public String toString() {
|
---|
| 97 | return name;
|
---|
| 98 | }
|
---|
[2717] | 99 | }
|
---|
| 100 |
|
---|
[2361] | 101 | protected JPanel buildSearchPanel() {
|
---|
[9543] | 102 | JPanel lpanel = new JPanel(new GridLayout(2, 2));
|
---|
| 103 | JPanel panel = new JPanel(new GridBagLayout());
|
---|
[2512] | 104 |
|
---|
[2717] | 105 | lpanel.add(new JLabel(tr("Choose the server for searching:")));
|
---|
| 106 | lpanel.add(server);
|
---|
[6883] | 107 | String s = Main.pref.get("namefinder.server", SERVERS[0].name);
|
---|
| 108 | for (int i = 0; i < SERVERS.length; ++i) {
|
---|
| 109 | if (SERVERS[i].name.equals(s)) {
|
---|
[2717] | 110 | server.setSelectedIndex(i);
|
---|
[2898] | 111 | }
|
---|
[2717] | 112 | }
|
---|
| 113 | lpanel.add(new JLabel(tr("Enter a place name to search for:")));
|
---|
[2512] | 114 |
|
---|
[2362] | 115 | cbSearchExpression = new HistoryComboBox();
|
---|
| 116 | cbSearchExpression.setToolTipText(tr("Enter a place name to search for"));
|
---|
[7005] | 117 | List<String> cmtHistory = new LinkedList<>(Main.pref.getCollection(HISTORY_KEY, new LinkedList<String>()));
|
---|
[2362] | 118 | Collections.reverse(cmtHistory);
|
---|
| 119 | cbSearchExpression.setPossibleItems(cmtHistory);
|
---|
[2717] | 120 | lpanel.add(cbSearchExpression);
|
---|
[1329] | 121 |
|
---|
[2717] | 122 | panel.add(lpanel, GBC.std().fill(GBC.HORIZONTAL).insets(5, 5, 0, 5));
|
---|
[2361] | 123 | SearchAction searchAction = new SearchAction();
|
---|
[8464] | 124 | JButton btnSearch = new JButton(searchAction);
|
---|
[9484] | 125 | cbSearchExpression.getEditorComponent().getDocument().addDocumentListener(searchAction);
|
---|
| 126 | cbSearchExpression.getEditorComponent().addActionListener(searchAction);
|
---|
[2361] | 127 |
|
---|
[2717] | 128 | panel.add(btnSearch, GBC.eol().insets(5, 5, 0, 5));
|
---|
[2512] | 129 |
|
---|
| 130 | return panel;
|
---|
[2361] | 131 | }
|
---|
| 132 |
|
---|
[1329] | 133 | /**
|
---|
[2361] | 134 | * Adds a new tab to the download dialog in JOSM.
|
---|
| 135 | *
|
---|
| 136 | * This method is, for all intents and purposes, the constructor for this class.
|
---|
| 137 | */
|
---|
[6084] | 138 | @Override
|
---|
[2361] | 139 | public void addGui(final DownloadDialog gui) {
|
---|
[9543] | 140 | JPanel panel = new JPanel(new BorderLayout());
|
---|
[2361] | 141 | panel.add(buildSearchPanel(), BorderLayout.NORTH);
|
---|
| 142 |
|
---|
| 143 | DefaultListSelectionModel selectionModel = new DefaultListSelectionModel();
|
---|
| 144 | model = new NamedResultTableModel(selectionModel);
|
---|
[2717] | 145 | columnmodel = new NamedResultTableColumnModel();
|
---|
| 146 | tblSearchResults = new JTable(model, columnmodel);
|
---|
[2361] | 147 | tblSearchResults.setSelectionModel(selectionModel);
|
---|
| 148 | JScrollPane scrollPane = new JScrollPane(tblSearchResults);
|
---|
[8510] | 149 | scrollPane.setPreferredSize(new Dimension(200, 200));
|
---|
[2361] | 150 | panel.add(scrollPane, BorderLayout.CENTER);
|
---|
[2512] | 151 |
|
---|
[9606] | 152 | if (gui != null)
|
---|
| 153 | gui.addDownloadAreaSelector(panel, tr("Areas around places"));
|
---|
[2361] | 154 |
|
---|
[2512] | 155 | scrollPane.setPreferredSize(scrollPane.getPreferredSize());
|
---|
[2361] | 156 | tblSearchResults.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
---|
| 157 | tblSearchResults.getSelectionModel().addListSelectionListener(new ListSelectionHandler());
|
---|
| 158 | tblSearchResults.addMouseListener(new MouseAdapter() {
|
---|
[9606] | 159 | @Override
|
---|
| 160 | public void mouseClicked(MouseEvent e) {
|
---|
[2361] | 161 | if (e.getClickCount() > 1) {
|
---|
| 162 | SearchResult sr = model.getSelectedSearchResult();
|
---|
[9606] | 163 | if (sr != null) {
|
---|
| 164 | parent.startDownload(sr.getDownloadArea());
|
---|
| 165 | }
|
---|
[2361] | 166 | }
|
---|
| 167 | }
|
---|
[2512] | 168 | });
|
---|
[2361] | 169 | parent = gui;
|
---|
| 170 | }
|
---|
| 171 |
|
---|
[6084] | 172 | @Override
|
---|
[2361] | 173 | public void setDownloadArea(Bounds area) {
|
---|
[2626] | 174 | tblSearchResults.clearSelection();
|
---|
[2361] | 175 | }
|
---|
[2512] | 176 |
|
---|
[2361] | 177 | class SearchAction extends AbstractAction implements DocumentListener {
|
---|
[1329] | 178 |
|
---|
[8836] | 179 | SearchAction() {
|
---|
[2361] | 180 | putValue(NAME, tr("Search ..."));
|
---|
[8510] | 181 | putValue(SMALL_ICON, ImageProvider.get("dialogs", "search"));
|
---|
[2361] | 182 | putValue(SHORT_DESCRIPTION, tr("Click to start searching for places"));
|
---|
| 183 | updateEnabledState();
|
---|
| 184 | }
|
---|
[2512] | 185 |
|
---|
[6084] | 186 | @Override
|
---|
[2361] | 187 | public void actionPerformed(ActionEvent e) {
|
---|
[8394] | 188 | if (!isEnabled() || cbSearchExpression.getText().trim().isEmpty())
|
---|
[2361] | 189 | return;
|
---|
[2362] | 190 | cbSearchExpression.addCurrentItemToHistory();
|
---|
| 191 | Main.pref.putCollection(HISTORY_KEY, cbSearchExpression.getHistory());
|
---|
| 192 | NameQueryTask task = new NameQueryTask(cbSearchExpression.getText());
|
---|
[12634] | 193 | MainApplication.worker.submit(task);
|
---|
[2361] | 194 | }
|
---|
[2512] | 195 |
|
---|
[6890] | 196 | protected final void updateEnabledState() {
|
---|
[8461] | 197 | setEnabled(!cbSearchExpression.getText().trim().isEmpty());
|
---|
[2361] | 198 | }
|
---|
[1329] | 199 |
|
---|
[6084] | 200 | @Override
|
---|
[2361] | 201 | public void changedUpdate(DocumentEvent e) {
|
---|
| 202 | updateEnabledState();
|
---|
| 203 | }
|
---|
[1329] | 204 |
|
---|
[6084] | 205 | @Override
|
---|
[2361] | 206 | public void insertUpdate(DocumentEvent e) {
|
---|
| 207 | updateEnabledState();
|
---|
| 208 | }
|
---|
[1329] | 209 |
|
---|
[6084] | 210 | @Override
|
---|
[2361] | 211 | public void removeUpdate(DocumentEvent e) {
|
---|
| 212 | updateEnabledState();
|
---|
| 213 | }
|
---|
| 214 | }
|
---|
[2512] | 215 |
|
---|
[2361] | 216 | class NameQueryTask extends PleaseWaitRunnable {
|
---|
[2512] | 217 |
|
---|
[9078] | 218 | private final String searchExpression;
|
---|
[9309] | 219 | private HttpClient connection;
|
---|
[8318] | 220 | private List<SearchResult> data;
|
---|
[8840] | 221 | private boolean canceled;
|
---|
[9078] | 222 | private final Server useserver;
|
---|
[2361] | 223 | private Exception lastException;
|
---|
[2512] | 224 |
|
---|
[8836] | 225 | NameQueryTask(String searchExpression) {
|
---|
[8510] | 226 | super(tr("Querying name server"), false /* don't ignore exceptions */);
|
---|
[2361] | 227 | this.searchExpression = searchExpression;
|
---|
[8510] | 228 | useserver = (Server) server.getSelectedItem();
|
---|
[2717] | 229 | Main.pref.put("namefinder.server", useserver.name);
|
---|
[2361] | 230 | }
|
---|
[2512] | 231 |
|
---|
[2361] | 232 | @Override
|
---|
| 233 | protected void cancel() {
|
---|
| 234 | this.canceled = true;
|
---|
| 235 | synchronized (this) {
|
---|
| 236 | if (connection != null) {
|
---|
[2512] | 237 | connection.disconnect();
|
---|
| 238 | }
|
---|
| 239 | }
|
---|
[2361] | 240 | }
|
---|
[1329] | 241 |
|
---|
[2361] | 242 | @Override
|
---|
| 243 | protected void finish() {
|
---|
[2512] | 244 | if (canceled)
|
---|
[2361] | 245 | return;
|
---|
| 246 | if (lastException != null) {
|
---|
| 247 | ExceptionDialogUtil.explainException(lastException);
|
---|
| 248 | return;
|
---|
| 249 | }
|
---|
[2717] | 250 | columnmodel.setHeadlines(useserver.thirdcol, useserver.fourthcol);
|
---|
[2512] | 251 | model.setData(this.data);
|
---|
[2361] | 252 | }
|
---|
[1329] | 253 |
|
---|
[2361] | 254 | @Override
|
---|
[2512] | 255 | protected void realRun() throws SAXException, IOException, OsmTransferException {
|
---|
[8304] | 256 | String urlString = useserver.url+Utils.encodeUrl(searchExpression);
|
---|
[3255] | 257 |
|
---|
[2361] | 258 | try {
|
---|
| 259 | getProgressMonitor().indeterminateSubTask(tr("Querying name server ..."));
|
---|
[3255] | 260 | URL url = new URL(urlString);
|
---|
[8510] | 261 | synchronized (this) {
|
---|
[9309] | 262 | connection = HttpClient.create(url);
|
---|
| 263 | connection.connect();
|
---|
[2626] | 264 | }
|
---|
[9309] | 265 | try (Reader reader = connection.getResponse().getContentReader()) {
|
---|
[11002] | 266 | data = NameFinder.parseSearchResults(reader);
|
---|
[7033] | 267 | }
|
---|
[7628] | 268 | } catch (SAXParseException e) {
|
---|
| 269 | if (!canceled) {
|
---|
| 270 | // Nominatim sometimes returns garbage, see #5934, #10643
|
---|
[12620] | 271 | Logging.log(Logging.LEVEL_WARN, tr("Error occured with query ''{0}'': ''{1}''", urlString, e.getMessage()), e);
|
---|
[10611] | 272 | GuiHelper.runInEDTAndWait(() -> HelpAwareOptionPane.showOptionDialog(
|
---|
| 273 | Main.parent,
|
---|
| 274 | tr("Name server returned invalid data. Please try again."),
|
---|
| 275 | tr("Bad response"),
|
---|
| 276 | JOptionPane.WARNING_MESSAGE, null
|
---|
| 277 | ));
|
---|
[7628] | 278 | }
|
---|
[10212] | 279 | } catch (IOException | ParserConfigurationException e) {
|
---|
[7628] | 280 | if (!canceled) {
|
---|
| 281 | OsmTransferException ex = new OsmTransferException(e);
|
---|
| 282 | ex.setUrl(urlString);
|
---|
| 283 | lastException = ex;
|
---|
| 284 | }
|
---|
[1329] | 285 | }
|
---|
[2361] | 286 | }
|
---|
| 287 | }
|
---|
[2512] | 288 |
|
---|
[2626] | 289 | static class NamedResultTableModel extends DefaultTableModel {
|
---|
[8308] | 290 | private transient List<SearchResult> data;
|
---|
[9078] | 291 | private final transient ListSelectionModel selectionModel;
|
---|
[2512] | 292 |
|
---|
[8836] | 293 | NamedResultTableModel(ListSelectionModel selectionModel) {
|
---|
[7005] | 294 | data = new ArrayList<>();
|
---|
[2361] | 295 | this.selectionModel = selectionModel;
|
---|
| 296 | }
|
---|
[8510] | 297 |
|
---|
[2361] | 298 | @Override
|
---|
| 299 | public int getRowCount() {
|
---|
[9606] | 300 | return data != null ? data.size() : 0;
|
---|
[2361] | 301 | }
|
---|
[1329] | 302 |
|
---|
[2361] | 303 | @Override
|
---|
| 304 | public Object getValueAt(int row, int column) {
|
---|
[9606] | 305 | return data != null ? data.get(row) : null;
|
---|
[2361] | 306 | }
|
---|
[2512] | 307 |
|
---|
[2361] | 308 | public void setData(List<SearchResult> data) {
|
---|
| 309 | if (data == null) {
|
---|
| 310 | this.data.clear();
|
---|
| 311 | } else {
|
---|
[7005] | 312 | this.data = new ArrayList<>(data);
|
---|
[1329] | 313 | }
|
---|
[2361] | 314 | fireTableDataChanged();
|
---|
| 315 | }
|
---|
[8510] | 316 |
|
---|
[2361] | 317 | @Override
|
---|
| 318 | public boolean isCellEditable(int row, int column) {
|
---|
[2512] | 319 | return false;
|
---|
[2361] | 320 | }
|
---|
[2512] | 321 |
|
---|
[2361] | 322 | public SearchResult getSelectedSearchResult() {
|
---|
[2626] | 323 | if (selectionModel.getMinSelectionIndex() < 0)
|
---|
[2361] | 324 | return null;
|
---|
| 325 | return data.get(selectionModel.getMinSelectionIndex());
|
---|
| 326 | }
|
---|
| 327 | }
|
---|
[2512] | 328 |
|
---|
[2676] | 329 | static class NamedResultTableColumnModel extends DefaultTableColumnModel {
|
---|
[8840] | 330 | private TableColumn col3;
|
---|
| 331 | private TableColumn col4;
|
---|
[9606] | 332 |
|
---|
| 333 | NamedResultTableColumnModel() {
|
---|
| 334 | createColumns();
|
---|
| 335 | }
|
---|
| 336 |
|
---|
[6890] | 337 | protected final void createColumns() {
|
---|
[9606] | 338 | TableColumn col;
|
---|
[2361] | 339 | NamedResultCellRenderer renderer = new NamedResultCellRenderer();
|
---|
[1329] | 340 |
|
---|
[2361] | 341 | // column 0 - Name
|
---|
| 342 | col = new TableColumn(0);
|
---|
| 343 | col.setHeaderValue(tr("Name"));
|
---|
| 344 | col.setResizable(true);
|
---|
| 345 | col.setPreferredWidth(200);
|
---|
| 346 | col.setCellRenderer(renderer);
|
---|
| 347 | addColumn(col);
|
---|
[2512] | 348 |
|
---|
[2361] | 349 | // column 1 - Version
|
---|
| 350 | col = new TableColumn(1);
|
---|
| 351 | col.setHeaderValue(tr("Type"));
|
---|
| 352 | col.setResizable(true);
|
---|
| 353 | col.setPreferredWidth(100);
|
---|
| 354 | col.setCellRenderer(renderer);
|
---|
| 355 | addColumn(col);
|
---|
[2512] | 356 |
|
---|
[2361] | 357 | // column 2 - Near
|
---|
[2717] | 358 | col3 = new TableColumn(2);
|
---|
[6883] | 359 | col3.setHeaderValue(SERVERS[0].thirdcol);
|
---|
[2717] | 360 | col3.setResizable(true);
|
---|
| 361 | col3.setPreferredWidth(100);
|
---|
| 362 | col3.setCellRenderer(renderer);
|
---|
| 363 | addColumn(col3);
|
---|
[1329] | 364 |
|
---|
[2361] | 365 | // column 3 - Zoom
|
---|
[2717] | 366 | col4 = new TableColumn(3);
|
---|
[6883] | 367 | col4.setHeaderValue(SERVERS[0].fourthcol);
|
---|
[2717] | 368 | col4.setResizable(true);
|
---|
| 369 | col4.setPreferredWidth(50);
|
---|
| 370 | col4.setCellRenderer(renderer);
|
---|
| 371 | addColumn(col4);
|
---|
[2361] | 372 | }
|
---|
[8510] | 373 |
|
---|
[2717] | 374 | public void setHeadlines(String third, String fourth) {
|
---|
| 375 | col3.setHeaderValue(third);
|
---|
| 376 | col4.setHeaderValue(fourth);
|
---|
| 377 | fireColumnMarginChanged();
|
---|
| 378 | }
|
---|
[2361] | 379 | }
|
---|
[2512] | 380 |
|
---|
[2361] | 381 | class ListSelectionHandler implements ListSelectionListener {
|
---|
[6084] | 382 | @Override
|
---|
[2361] | 383 | public void valueChanged(ListSelectionEvent lse) {
|
---|
[2898] | 384 | SearchResult r = model.getSelectedSearchResult();
|
---|
[2361] | 385 | if (r != null) {
|
---|
| 386 | parent.boundingBoxChanged(r.getDownloadArea(), PlaceSelection.this);
|
---|
[1329] | 387 | }
|
---|
[2361] | 388 | }
|
---|
| 389 | }
|
---|
[2512] | 390 |
|
---|
[2626] | 391 | static class NamedResultCellRenderer extends JLabel implements TableCellRenderer {
|
---|
[2512] | 392 |
|
---|
[8510] | 393 | /**
|
---|
| 394 | * Constructs a new {@code NamedResultCellRenderer}.
|
---|
| 395 | */
|
---|
[8836] | 396 | NamedResultCellRenderer() {
|
---|
[2361] | 397 | setOpaque(true);
|
---|
[8510] | 398 | setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
|
---|
[2361] | 399 | }
|
---|
[2512] | 400 |
|
---|
[2361] | 401 | protected void reset() {
|
---|
| 402 | setText("");
|
---|
| 403 | setIcon(null);
|
---|
| 404 | }
|
---|
[2512] | 405 |
|
---|
[2361] | 406 | protected void renderColor(boolean selected) {
|
---|
| 407 | if (selected) {
|
---|
| 408 | setForeground(UIManager.getColor("Table.selectionForeground"));
|
---|
| 409 | setBackground(UIManager.getColor("Table.selectionBackground"));
|
---|
| 410 | } else {
|
---|
| 411 | setForeground(UIManager.getColor("Table.foreground"));
|
---|
[2512] | 412 | setBackground(UIManager.getColor("Table.background"));
|
---|
[2361] | 413 | }
|
---|
| 414 | }
|
---|
[2512] | 415 |
|
---|
[2361] | 416 | protected String lineWrapDescription(String description) {
|
---|
[6822] | 417 | StringBuilder ret = new StringBuilder();
|
---|
| 418 | StringBuilder line = new StringBuilder();
|
---|
[2361] | 419 | StringTokenizer tok = new StringTokenizer(description, " ");
|
---|
[8510] | 420 | while (tok.hasMoreElements()) {
|
---|
[2361] | 421 | String t = tok.nextToken();
|
---|
| 422 | if (line.length() == 0) {
|
---|
| 423 | line.append(t);
|
---|
| 424 | } else if (line.length() < 80) {
|
---|
[8390] | 425 | line.append(' ').append(t);
|
---|
[2361] | 426 | } else {
|
---|
[8390] | 427 | line.append(' ').append(t).append("<br>");
|
---|
[2361] | 428 | ret.append(line);
|
---|
[6822] | 429 | line = new StringBuilder();
|
---|
[1329] | 430 | }
|
---|
| 431 | }
|
---|
[2361] | 432 | ret.insert(0, "<html>");
|
---|
| 433 | ret.append("</html>");
|
---|
| 434 | return ret.toString();
|
---|
| 435 | }
|
---|
[2512] | 436 |
|
---|
[6084] | 437 | @Override
|
---|
[2361] | 438 | public Component getTableCellRendererComponent(JTable table, Object value,
|
---|
| 439 | boolean isSelected, boolean hasFocus, int row, int column) {
|
---|
[2512] | 440 |
|
---|
[2361] | 441 | reset();
|
---|
| 442 | renderColor(isSelected);
|
---|
[2512] | 443 |
|
---|
[9606] | 444 | if (value == null)
|
---|
| 445 | return this;
|
---|
[2361] | 446 | SearchResult sr = (SearchResult) value;
|
---|
| 447 | switch(column) {
|
---|
| 448 | case 0:
|
---|
[11009] | 449 | setText(sr.getName());
|
---|
[2361] | 450 | break;
|
---|
| 451 | case 1:
|
---|
[11009] | 452 | setText(sr.getInfo());
|
---|
[2361] | 453 | break;
|
---|
| 454 | case 2:
|
---|
[11009] | 455 | setText(sr.getNearestPlace());
|
---|
[2361] | 456 | break;
|
---|
| 457 | case 3:
|
---|
[11009] | 458 | if (sr.getBounds() != null) {
|
---|
| 459 | setText(sr.getBounds().toShortString(new DecimalFormat("0.000")));
|
---|
[2898] | 460 | } else {
|
---|
[11009] | 461 | setText(sr.getZoom() != 0 ? Integer.toString(sr.getZoom()) : tr("unknown"));
|
---|
[2898] | 462 | }
|
---|
[2361] | 463 | break;
|
---|
[10217] | 464 | default: // Do nothing
|
---|
[2361] | 465 | }
|
---|
[11009] | 466 | setToolTipText(lineWrapDescription(sr.getDescription()));
|
---|
[2361] | 467 | return this;
|
---|
| 468 | }
|
---|
[1329] | 469 | }
|
---|
| 470 | }
|
---|