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

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

fix #10024 - Add an option in Preferences/Look-and-Feel to use native file-choosing dialogs.
They look nicer but they do not support file filters, so we cannot use them (yet) as default.
Based on patch by Lesath and code review by simon04.
The native dialogs are not used if selection mode is not supported ("files and directories" on all platforms, "directories" on systems other than OS X)

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