source: josm/trunk/src/org/openstreetmap/josm/gui/dialogs/MapPaintDialog.java@ 11856

Last change on this file since 11856 was 11856, checked in by Don-vip, 7 years ago

sonar - fb-contrib:IOI_DOUBLE_BUFFER_COPY - Performance - Method passes a Buffered Stream/Reader/Writer to a already buffering copy method

  • Property svn:eol-style set to native
File size: 27.6 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.dialogs;
3
4import static org.openstreetmap.josm.tools.I18n.marktr;
5import static org.openstreetmap.josm.tools.I18n.tr;
6
7import java.awt.Component;
8import java.awt.Dimension;
9import java.awt.Font;
10import java.awt.GridBagLayout;
11import java.awt.Insets;
12import java.awt.Point;
13import java.awt.Rectangle;
14import java.awt.event.ActionEvent;
15import java.awt.event.KeyEvent;
16import java.awt.event.MouseEvent;
17import java.io.BufferedReader;
18import java.io.File;
19import java.io.IOException;
20import java.io.InputStream;
21import java.io.InputStreamReader;
22import java.nio.charset.StandardCharsets;
23import java.nio.file.Files;
24import java.nio.file.StandardCopyOption;
25import java.util.ArrayList;
26import java.util.Arrays;
27import java.util.Collection;
28import java.util.List;
29
30import javax.swing.AbstractAction;
31import javax.swing.DefaultButtonModel;
32import javax.swing.DefaultListSelectionModel;
33import javax.swing.ImageIcon;
34import javax.swing.JCheckBox;
35import javax.swing.JFileChooser;
36import javax.swing.JLabel;
37import javax.swing.JMenu;
38import javax.swing.JPanel;
39import javax.swing.JPopupMenu;
40import javax.swing.JScrollPane;
41import javax.swing.JTabbedPane;
42import javax.swing.JTable;
43import javax.swing.JViewport;
44import javax.swing.ListSelectionModel;
45import javax.swing.SingleSelectionModel;
46import javax.swing.SwingConstants;
47import javax.swing.SwingUtilities;
48import javax.swing.UIManager;
49import javax.swing.border.EmptyBorder;
50import javax.swing.event.ListSelectionEvent;
51import javax.swing.event.ListSelectionListener;
52import javax.swing.filechooser.FileFilter;
53import javax.swing.table.AbstractTableModel;
54import javax.swing.table.DefaultTableCellRenderer;
55import javax.swing.table.TableCellRenderer;
56import javax.swing.table.TableModel;
57
58import org.openstreetmap.josm.Main;
59import org.openstreetmap.josm.actions.ExtensionFileFilter;
60import org.openstreetmap.josm.actions.JosmAction;
61import org.openstreetmap.josm.actions.PreferencesAction;
62import org.openstreetmap.josm.gui.ExtendedDialog;
63import org.openstreetmap.josm.gui.PleaseWaitRunnable;
64import org.openstreetmap.josm.gui.SideButton;
65import org.openstreetmap.josm.gui.mappaint.MapPaintStyles;
66import org.openstreetmap.josm.gui.mappaint.MapPaintStyles.MapPaintSylesUpdateListener;
67import org.openstreetmap.josm.gui.mappaint.StyleSetting;
68import org.openstreetmap.josm.gui.mappaint.StyleSource;
69import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSStyleSource;
70import org.openstreetmap.josm.gui.preferences.SourceEntry;
71import org.openstreetmap.josm.gui.preferences.map.MapPaintPreference;
72import org.openstreetmap.josm.gui.util.FileFilterAllFiles;
73import org.openstreetmap.josm.gui.util.GuiHelper;
74import org.openstreetmap.josm.gui.widgets.AbstractFileChooser;
75import org.openstreetmap.josm.gui.widgets.FileChooserManager;
76import org.openstreetmap.josm.gui.widgets.HtmlPanel;
77import org.openstreetmap.josm.gui.widgets.JosmTextArea;
78import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher;
79import org.openstreetmap.josm.tools.GBC;
80import org.openstreetmap.josm.tools.ImageOverlay;
81import org.openstreetmap.josm.tools.ImageProvider;
82import org.openstreetmap.josm.tools.ImageProvider.ImageSizes;
83import org.openstreetmap.josm.tools.InputMapUtils;
84import org.openstreetmap.josm.tools.Shortcut;
85import org.openstreetmap.josm.tools.Utils;
86
87/**
88 * Dialog to configure the map painting style.
89 * @since 3843
90 */
91public class MapPaintDialog extends ToggleDialog {
92
93 protected StylesTable tblStyles;
94 protected StylesModel model;
95 protected final DefaultListSelectionModel selectionModel = new DefaultListSelectionModel();
96
97 protected OnOffAction onoffAction;
98 protected ReloadAction reloadAction;
99 protected MoveUpDownAction upAction;
100 protected MoveUpDownAction downAction;
101 protected JCheckBox cbWireframe;
102
103 /**
104 * Action that opens the map paint preferences.
105 */
106 public static final JosmAction PREFERENCE_ACTION = PreferencesAction.forPreferenceSubTab(
107 tr("Map paint preferences"), null, MapPaintPreference.class, /* ICON */ "dialogs/mappaintpreference");
108
109 /**
110 * Constructs a new {@code MapPaintDialog}.
111 */
112 public MapPaintDialog() {
113 super(tr("Map Paint Styles"), "mapstyle", tr("configure the map painting style"),
114 Shortcut.registerShortcut("subwindow:mappaint", tr("Toggle: {0}", tr("MapPaint")),
115 KeyEvent.VK_M, Shortcut.ALT_SHIFT), 150, false, MapPaintPreference.class);
116 build();
117 }
118
119 protected void build() {
120 model = new StylesModel();
121
122 cbWireframe = new JCheckBox();
123 JLabel wfLabel = new JLabel(tr("Wireframe View"), ImageProvider.get("dialogs/mappaint", "wireframe_small"), JLabel.HORIZONTAL);
124 wfLabel.setFont(wfLabel.getFont().deriveFont(Font.PLAIN));
125 wfLabel.setLabelFor(cbWireframe);
126
127 cbWireframe.setModel(new DefaultButtonModel() {
128 @Override
129 public void setSelected(boolean b) {
130 super.setSelected(b);
131 tblStyles.setEnabled(!b);
132 onoffAction.updateEnabledState();
133 upAction.updateEnabledState();
134 downAction.updateEnabledState();
135 }
136 });
137 cbWireframe.addActionListener(e -> Main.main.menu.wireFrameToggleAction.actionPerformed(null));
138 cbWireframe.setBorder(new EmptyBorder(new Insets(1, 1, 1, 1)));
139
140 tblStyles = new StylesTable(model);
141 tblStyles.setSelectionModel(selectionModel);
142 tblStyles.addMouseListener(new PopupMenuHandler());
143 tblStyles.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
144 tblStyles.setBackground(UIManager.getColor("Panel.background"));
145 tblStyles.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
146 tblStyles.setTableHeader(null);
147 tblStyles.getColumnModel().getColumn(0).setMaxWidth(1);
148 tblStyles.getColumnModel().getColumn(0).setResizable(false);
149 tblStyles.getColumnModel().getColumn(0).setCellRenderer(new MyCheckBoxRenderer());
150 tblStyles.getColumnModel().getColumn(1).setCellRenderer(new StyleSourceRenderer());
151 tblStyles.setShowGrid(false);
152 tblStyles.setIntercellSpacing(new Dimension(0, 0));
153
154 JPanel p = new JPanel(new GridBagLayout());
155 p.add(cbWireframe, GBC.std(0, 0));
156 p.add(wfLabel, GBC.std(1, 0).weight(1, 0));
157 p.add(tblStyles, GBC.std(0, 1).span(2).fill());
158
159 reloadAction = new ReloadAction();
160 onoffAction = new OnOffAction();
161 upAction = new MoveUpDownAction(false);
162 downAction = new MoveUpDownAction(true);
163 selectionModel.addListSelectionListener(onoffAction);
164 selectionModel.addListSelectionListener(reloadAction);
165 selectionModel.addListSelectionListener(upAction);
166 selectionModel.addListSelectionListener(downAction);
167
168 // Toggle style on Enter and Spacebar
169 InputMapUtils.addEnterAction(tblStyles, onoffAction);
170 InputMapUtils.addSpacebarAction(tblStyles, onoffAction);
171
172 createLayout(p, true, Arrays.asList(
173 new SideButton(onoffAction, false),
174 new SideButton(upAction, false),
175 new SideButton(downAction, false),
176 new SideButton(PREFERENCE_ACTION, false)
177 ));
178 }
179
180 protected static class StylesTable extends JTable {
181
182 public StylesTable(TableModel dm) {
183 super(dm);
184 }
185
186 public void scrollToVisible(int row, int col) {
187 if (!(getParent() instanceof JViewport))
188 return;
189 JViewport viewport = (JViewport) getParent();
190 Rectangle rect = getCellRect(row, col, true);
191 Point pt = viewport.getViewPosition();
192 rect.setLocation(rect.x - pt.x, rect.y - pt.y);
193 viewport.scrollRectToVisible(rect);
194 }
195 }
196
197 @Override
198 public void showNotify() {
199 MapPaintStyles.addMapPaintSylesUpdateListener(model);
200 Main.main.menu.wireFrameToggleAction.addButtonModel(cbWireframe.getModel());
201 }
202
203 @Override
204 public void hideNotify() {
205 Main.main.menu.wireFrameToggleAction.removeButtonModel(cbWireframe.getModel());
206 MapPaintStyles.removeMapPaintSylesUpdateListener(model);
207 }
208
209 protected class StylesModel extends AbstractTableModel implements MapPaintSylesUpdateListener {
210
211 private final Class<?>[] columnClasses = {Boolean.class, StyleSource.class};
212
213 private transient List<StyleSource> data = new ArrayList<>();
214
215 /**
216 * Constructs a new {@code StylesModel}.
217 */
218 public StylesModel() {
219 data = new ArrayList<>(MapPaintStyles.getStyles().getStyleSources());
220 }
221
222 private StyleSource getRow(int i) {
223 return data.get(i);
224 }
225
226 @Override
227 public int getColumnCount() {
228 return 2;
229 }
230
231 @Override
232 public int getRowCount() {
233 return data.size();
234 }
235
236 @Override
237 public Object getValueAt(int row, int column) {
238 if (column == 0)
239 return getRow(row).active;
240 else
241 return getRow(row);
242 }
243
244 @Override
245 public boolean isCellEditable(int row, int column) {
246 return column == 0;
247 }
248
249 @Override
250 public Class<?> getColumnClass(int column) {
251 return columnClasses[column];
252 }
253
254 @Override
255 public void setValueAt(Object aValue, int row, int column) {
256 if (row < 0 || row >= getRowCount() || aValue == null)
257 return;
258 if (column == 0) {
259 MapPaintStyles.toggleStyleActive(row);
260 }
261 }
262
263 /**
264 * Make sure the first of the selected entry is visible in the
265 * views of this model.
266 */
267 public void ensureSelectedIsVisible() {
268 int index = selectionModel.getMinSelectionIndex();
269 if (index < 0)
270 return;
271 if (index >= getRowCount())
272 return;
273 tblStyles.scrollToVisible(index, 0);
274 tblStyles.repaint();
275 }
276
277 @Override
278 public void mapPaintStylesUpdated() {
279 data = new ArrayList<>(MapPaintStyles.getStyles().getStyleSources());
280 fireTableDataChanged();
281 tblStyles.repaint();
282 }
283
284 @Override
285 public void mapPaintStyleEntryUpdated(int idx) {
286 data = new ArrayList<>(MapPaintStyles.getStyles().getStyleSources());
287 fireTableRowsUpdated(idx, idx);
288 tblStyles.repaint();
289 }
290 }
291
292 private class MyCheckBoxRenderer extends JCheckBox implements TableCellRenderer {
293
294 /**
295 * Constructs a new {@code MyCheckBoxRenderer}.
296 */
297 MyCheckBoxRenderer() {
298 setHorizontalAlignment(SwingConstants.CENTER);
299 setVerticalAlignment(SwingConstants.CENTER);
300 }
301
302 @Override
303 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
304 if (value == null)
305 return this;
306 boolean b = (Boolean) value;
307 setSelected(b);
308 setEnabled(!cbWireframe.isSelected());
309 return this;
310 }
311 }
312
313 private class StyleSourceRenderer extends DefaultTableCellRenderer {
314 @Override
315 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
316 if (value == null)
317 return this;
318 StyleSource s = (StyleSource) value;
319 JLabel label = (JLabel) super.getTableCellRendererComponent(table,
320 s.getDisplayString(), isSelected, hasFocus, row, column);
321 label.setIcon(s.getIcon());
322 label.setToolTipText(s.getToolTipText());
323 label.setEnabled(!cbWireframe.isSelected());
324 return label;
325 }
326 }
327
328 protected class OnOffAction extends AbstractAction implements ListSelectionListener {
329 /**
330 * Constructs a new {@code OnOffAction}.
331 */
332 public OnOffAction() {
333 putValue(NAME, tr("On/Off"));
334 putValue(SHORT_DESCRIPTION, tr("Turn selected styles on or off"));
335 new ImageProvider("apply").getResource().attachImageIcon(this, true);
336 updateEnabledState();
337 }
338
339 protected void updateEnabledState() {
340 setEnabled(!cbWireframe.isSelected() && tblStyles.getSelectedRowCount() > 0);
341 }
342
343 @Override
344 public void valueChanged(ListSelectionEvent e) {
345 updateEnabledState();
346 }
347
348 @Override
349 public void actionPerformed(ActionEvent e) {
350 int[] pos = tblStyles.getSelectedRows();
351 MapPaintStyles.toggleStyleActive(pos);
352 selectionModel.setValueIsAdjusting(true);
353 selectionModel.clearSelection();
354 for (int p: pos) {
355 selectionModel.addSelectionInterval(p, p);
356 }
357 selectionModel.setValueIsAdjusting(false);
358 }
359 }
360
361 /**
362 * The action to move down the currently selected entries in the list.
363 */
364 protected class MoveUpDownAction extends AbstractAction implements ListSelectionListener {
365
366 private final int increment;
367
368 /**
369 * Constructs a new {@code MoveUpDownAction}.
370 * @param isDown {@code true} to move the entry down, {@code false} to move it up
371 */
372 public MoveUpDownAction(boolean isDown) {
373 increment = isDown ? 1 : -1;
374 putValue(NAME, isDown ? tr("Down") : tr("Up"));
375 new ImageProvider("dialogs", isDown ? "down" : "up").getResource().attachImageIcon(this, true);
376 putValue(SHORT_DESCRIPTION, isDown ? tr("Move the selected entry one row down.") : tr("Move the selected entry one row up."));
377 updateEnabledState();
378 }
379
380 public void updateEnabledState() {
381 int[] sel = tblStyles.getSelectedRows();
382 setEnabled(!cbWireframe.isSelected() && MapPaintStyles.canMoveStyles(sel, increment));
383 }
384
385 @Override
386 public void actionPerformed(ActionEvent e) {
387 int[] sel = tblStyles.getSelectedRows();
388 MapPaintStyles.moveStyles(sel, increment);
389
390 selectionModel.setValueIsAdjusting(true);
391 selectionModel.clearSelection();
392 for (int row: sel) {
393 selectionModel.addSelectionInterval(row + increment, row + increment);
394 }
395 selectionModel.setValueIsAdjusting(false);
396 model.ensureSelectedIsVisible();
397 }
398
399 @Override
400 public void valueChanged(ListSelectionEvent e) {
401 updateEnabledState();
402 }
403 }
404
405 protected class ReloadAction extends AbstractAction implements ListSelectionListener {
406 /**
407 * Constructs a new {@code ReloadAction}.
408 */
409 public ReloadAction() {
410 putValue(NAME, tr("Reload from file"));
411 putValue(SHORT_DESCRIPTION, tr("reload selected styles from file"));
412 new ImageProvider("dialogs", "refresh").getResource().attachImageIcon(this);
413 setEnabled(getEnabledState());
414 }
415
416 protected boolean getEnabledState() {
417 if (cbWireframe.isSelected())
418 return false;
419 int[] pos = tblStyles.getSelectedRows();
420 if (pos.length == 0)
421 return false;
422 for (int i : pos) {
423 if (!model.getRow(i).isLocal())
424 return false;
425 }
426 return true;
427 }
428
429 @Override
430 public void valueChanged(ListSelectionEvent e) {
431 setEnabled(getEnabledState());
432 }
433
434 @Override
435 public void actionPerformed(ActionEvent e) {
436 final int[] rows = tblStyles.getSelectedRows();
437 MapPaintStyles.reloadStyles(rows);
438 Main.worker.submit(() -> SwingUtilities.invokeLater(() -> {
439 selectionModel.setValueIsAdjusting(true);
440 selectionModel.clearSelection();
441 for (int r: rows) {
442 selectionModel.addSelectionInterval(r, r);
443 }
444 selectionModel.setValueIsAdjusting(false);
445 }));
446 }
447 }
448
449 protected class SaveAsAction extends AbstractAction {
450
451 /**
452 * Constructs a new {@code SaveAsAction}.
453 */
454 public SaveAsAction() {
455 putValue(NAME, tr("Save as..."));
456 putValue(SHORT_DESCRIPTION, tr("Save a copy of this Style to file and add it to the list"));
457 new ImageProvider("copy").getResource().attachImageIcon(this);
458 setEnabled(tblStyles.getSelectedRows().length == 1);
459 }
460
461 @Override
462 public void actionPerformed(ActionEvent e) {
463 int sel = tblStyles.getSelectionModel().getLeadSelectionIndex();
464 if (sel < 0 || sel >= model.getRowCount())
465 return;
466 final StyleSource s = model.getRow(sel);
467
468 FileChooserManager fcm = new FileChooserManager(false, "mappaint.clone-style.lastDirectory", System.getProperty("user.home"));
469 String suggestion = fcm.getInitialDirectory() + File.separator + s.getFileNamePart();
470
471 FileFilter ff;
472 if (s instanceof MapCSSStyleSource) {
473 ff = new ExtensionFileFilter("mapcss,css,zip", "mapcss", tr("Map paint style file (*.mapcss, *.zip)"));
474 } else {
475 ff = new ExtensionFileFilter("xml,zip", "xml", tr("Map paint style file (*.xml, *.zip)"));
476 }
477 fcm.createFileChooser(false, null, Arrays.asList(ff, FileFilterAllFiles.getInstance()), ff, JFileChooser.FILES_ONLY)
478 .getFileChooser().setSelectedFile(new File(suggestion));
479 AbstractFileChooser fc = fcm.openFileChooser();
480 if (fc == null)
481 return;
482 Main.worker.submit(new SaveToFileTask(s, fc.getSelectedFile()));
483 }
484
485 private class SaveToFileTask extends PleaseWaitRunnable {
486 private final StyleSource s;
487 private final File file;
488
489 private boolean canceled;
490 private boolean error;
491
492 SaveToFileTask(StyleSource s, File file) {
493 super(tr("Reloading style sources"));
494 this.s = s;
495 this.file = file;
496 }
497
498 @Override
499 protected void cancel() {
500 canceled = true;
501 }
502
503 @Override
504 protected void realRun() {
505 getProgressMonitor().indeterminateSubTask(
506 tr("Save style ''{0}'' as ''{1}''", s.getDisplayString(), file.getPath()));
507 try {
508 try (InputStream in = s.getSourceInputStream()) {
509 Files.copy(in, file.toPath(), StandardCopyOption.REPLACE_EXISTING);
510 }
511 } catch (IOException e) {
512 Main.warn(e);
513 error = true;
514 }
515 }
516
517 @Override
518 protected void finish() {
519 SwingUtilities.invokeLater(() -> {
520 if (!error && !canceled) {
521 SourceEntry se = new SourceEntry(s);
522 se.url = file.getPath();
523 MapPaintStyles.addStyle(se);
524 tblStyles.getSelectionModel().setSelectionInterval(model.getRowCount() - 1, model.getRowCount() - 1);
525 model.ensureSelectedIsVisible();
526 }
527 });
528 }
529 }
530 }
531
532 /**
533 * Displays information about selected paint style in a new dialog.
534 */
535 protected class InfoAction extends AbstractAction {
536
537 private boolean errorsTabLoaded;
538 private boolean warningsTabLoaded;
539 private boolean sourceTabLoaded;
540
541 /**
542 * Constructs a new {@code InfoAction}.
543 */
544 public InfoAction() {
545 putValue(NAME, tr("Info"));
546 putValue(SHORT_DESCRIPTION, tr("view meta information, error log and source definition"));
547 new ImageProvider("info").getResource().attachImageIcon(this);
548 setEnabled(tblStyles.getSelectedRows().length == 1);
549 }
550
551 @Override
552 public void actionPerformed(ActionEvent e) {
553 int sel = tblStyles.getSelectionModel().getLeadSelectionIndex();
554 if (sel < 0 || sel >= model.getRowCount())
555 return;
556 final StyleSource s = model.getRow(sel);
557 ExtendedDialog info = new ExtendedDialog(Main.parent, tr("Map Style info"), new String[] {tr("Close")});
558 info.setPreferredSize(new Dimension(600, 400));
559 info.setButtonIcons(new String[] {"ok.png"});
560
561 final JTabbedPane tabs = new JTabbedPane();
562
563 JLabel lblInfo = new JLabel(tr("Info"));
564 lblInfo.setLabelFor(tabs.add("Info", buildInfoPanel(s)));
565 lblInfo.setFont(lblInfo.getFont().deriveFont(Font.PLAIN));
566 tabs.setTabComponentAt(0, lblInfo);
567
568 final JPanel pErrors = addErrorOrWarningTab(tabs, lblInfo,
569 s.getErrors(), marktr("Errors"), 1, ImageProvider.get("misc", "error"));
570 final JPanel pWarnings = addErrorOrWarningTab(tabs, lblInfo,
571 s.getWarnings(), marktr("Warnings"), 2, ImageProvider.get("warning-small"));
572
573 final JPanel pSource = new JPanel(new GridBagLayout());
574 JLabel lblSource = new JLabel(tr("Source"));
575 lblSource.setLabelFor(tabs.add("Source", pSource));
576 lblSource.setFont(lblSource.getFont().deriveFont(Font.PLAIN));
577 tabs.setTabComponentAt(3, lblSource);
578
579 tabs.getModel().addChangeListener(e1 -> {
580 if (!errorsTabLoaded && ((SingleSelectionModel) e1.getSource()).getSelectedIndex() == 1) {
581 errorsTabLoaded = true;
582 buildErrorsOrWarningPanel(s.getErrors(), pErrors);
583 }
584 if (!warningsTabLoaded && ((SingleSelectionModel) e1.getSource()).getSelectedIndex() == 2) {
585 warningsTabLoaded = true;
586 buildErrorsOrWarningPanel(s.getWarnings(), pWarnings);
587 }
588 if (!sourceTabLoaded && ((SingleSelectionModel) e1.getSource()).getSelectedIndex() == 3) {
589 sourceTabLoaded = true;
590 buildSourcePanel(s, pSource);
591 }
592 });
593 info.setContent(tabs, false);
594 info.showDialog();
595 }
596
597 private JPanel addErrorOrWarningTab(final JTabbedPane tabs, JLabel lblInfo,
598 Collection<?> items, String title, int pos, ImageIcon icon) {
599 final JPanel pErrors = new JPanel(new GridBagLayout());
600 tabs.add(title, pErrors);
601 if (items.isEmpty()) {
602 JLabel lblErrors = new JLabel(tr(title));
603 lblErrors.setLabelFor(pErrors);
604 lblErrors.setFont(lblInfo.getFont().deriveFont(Font.PLAIN));
605 lblErrors.setEnabled(false);
606 tabs.setTabComponentAt(pos, lblErrors);
607 tabs.setEnabledAt(pos, false);
608 } else {
609 JLabel lblErrors = new JLabel(tr(title), icon, JLabel.HORIZONTAL);
610 lblErrors.setLabelFor(pErrors);
611 tabs.setTabComponentAt(pos, lblErrors);
612 }
613 return pErrors;
614 }
615
616 private JPanel buildInfoPanel(StyleSource s) {
617 JPanel p = new JPanel(new GridBagLayout());
618 StringBuilder text = new StringBuilder("<table cellpadding=3>");
619 text.append(tableRow(tr("Title:"), s.getDisplayString()));
620 if (s.url.startsWith("http://") || s.url.startsWith("https://")) {
621 text.append(tableRow(tr("URL:"), s.url));
622 } else if (s.url.startsWith("resource://")) {
623 text.append(tableRow(tr("Built-in Style, internal path:"), s.url));
624 } else {
625 text.append(tableRow(tr("Path:"), s.url));
626 }
627 if (s.icon != null) {
628 text.append(tableRow(tr("Icon:"), s.icon));
629 }
630 if (s.getBackgroundColorOverride() != null) {
631 text.append(tableRow(tr("Background:"), Utils.toString(s.getBackgroundColorOverride())));
632 }
633 text.append(tableRow(tr("Style is currently active?"), s.active ? tr("Yes") : tr("No")))
634 .append("</table>");
635 p.add(new JScrollPane(new HtmlPanel(text.toString())), GBC.eol().fill(GBC.BOTH));
636 return p;
637 }
638
639 private String tableRow(String firstColumn, String secondColumn) {
640 return "<tr><td><b>" + firstColumn + "</b></td><td>" + secondColumn + "</td></tr>";
641 }
642
643 private void buildSourcePanel(StyleSource s, JPanel p) {
644 JosmTextArea txtSource = new JosmTextArea();
645 txtSource.setFont(GuiHelper.getMonospacedFont(txtSource));
646 txtSource.setEditable(false);
647 p.add(new JScrollPane(txtSource), GBC.std().fill());
648
649 try {
650 InputStream is = s.getSourceInputStream();
651 try (BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
652 String line;
653 while ((line = reader.readLine()) != null) {
654 txtSource.append(line + '\n');
655 }
656 } finally {
657 s.closeSourceInputStream(is);
658 }
659 } catch (IOException ex) {
660 Main.error(ex);
661 txtSource.append("<ERROR: failed to read file!>");
662 }
663 txtSource.setCaretPosition(0);
664 }
665
666 private <T> void buildErrorsOrWarningPanel(Collection<T> items, JPanel p) {
667 JosmTextArea txtErrors = new JosmTextArea();
668 txtErrors.setFont(GuiHelper.getMonospacedFont(txtErrors));
669 txtErrors.setEditable(false);
670 p.add(new JScrollPane(txtErrors), GBC.std().fill());
671 for (T t : items) {
672 txtErrors.append(t.toString() + '\n');
673 }
674 txtErrors.setCaretPosition(0);
675 }
676 }
677
678 class PopupMenuHandler extends PopupMenuLauncher {
679 @Override
680 public void launch(MouseEvent evt) {
681 if (cbWireframe.isSelected())
682 return;
683 super.launch(evt);
684 }
685
686 @Override
687 protected void showMenu(MouseEvent evt) {
688 menu = new MapPaintPopup();
689 super.showMenu(evt);
690 }
691 }
692
693 /**
694 * The popup menu displayed when right-clicking a map paint entry
695 */
696 public class MapPaintPopup extends JPopupMenu {
697 /**
698 * Constructs a new {@code MapPaintPopup}.
699 */
700 public MapPaintPopup() {
701 add(reloadAction);
702 add(new SaveAsAction());
703
704 JMenu setMenu = new JMenu(tr("Style settings"));
705 setMenu.setIcon(new ImageProvider("preference").setMaxSize(ImageSizes.POPUPMENU).addOverlay(
706 new ImageOverlay(new ImageProvider("dialogs/mappaint", "pencil"), 0.5, 0.5, 1.0, 1.0)).get());
707 setMenu.setToolTipText(tr("Customize the style"));
708 add(setMenu);
709
710 int sel = tblStyles.getSelectionModel().getLeadSelectionIndex();
711 StyleSource style = null;
712 if (sel >= 0 && sel < model.getRowCount()) {
713 style = model.getRow(sel);
714 }
715 if (style == null || style.settings.isEmpty()) {
716 setMenu.setEnabled(false);
717 } else {
718 for (StyleSetting s : style.settings) {
719 s.addMenuEntry(setMenu);
720 }
721 }
722
723 addSeparator();
724 add(new InfoAction());
725 }
726 }
727}
Note: See TracBrowser for help on using the repository browser.