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

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

Restrict WMS "save as" and "load" dialogs to WMS FileFilter + refactor WMS layer import/export to make WMSLayerImporter/Exporter real classes

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