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

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

improve performance and simplify file copy operations (major performance gain when downloading geotools plugin)

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