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

Last change on this file since 4932 was 4912, checked in by framm, 12 years ago

override<->overwrite. sorry for three commits where one would have been sufficient.

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