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

Last change on this file since 13691 was 13647, checked in by Don-vip, 6 years ago

see #16204 - Allow to start and close JOSM in WebStart sandbox mode (where every external access is denied). This was very useful to reproduce some very tricky bugs that occured in real life but were almost impossible to diagnose.

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