- Timestamp:
- 2010-11-20T15:10:05+01:00 (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/gui/dialogs/LayerListDialog.java
r3408 r3661 5 5 import java.awt.BorderLayout; 6 6 import java.awt.Component; 7 import java.awt.Dimension; 8 import java.awt.Font; 7 9 import java.awt.Point; 8 10 import java.awt.Rectangle; 9 11 import java.awt.event.ActionEvent; 10 12 import java.awt.event.KeyEvent; 11 import java.awt.event.MouseAdapter;12 13 import java.awt.event.MouseEvent; 13 14 import java.beans.PropertyChangeEvent; … … 19 20 20 21 import javax.swing.AbstractAction; 21 import javax.swing.DefaultListCellRenderer; 22 import javax.swing.DefaultListModel; 22 import javax.swing.DefaultCellEditor; 23 23 import javax.swing.DefaultListSelectionModel; 24 import javax.swing.Icon; 24 import javax.swing.ImageIcon; 25 import javax.swing.JCheckBox; 25 26 import javax.swing.JComponent; 26 27 import javax.swing.JLabel; 27 import javax.swing.JList;28 28 import javax.swing.JMenuItem; 29 29 import javax.swing.JPanel; 30 30 import javax.swing.JScrollPane; 31 import javax.swing.JTable; 32 import javax.swing.JTextField; 33 import javax.swing.JViewport; 31 34 import javax.swing.KeyStroke; 32 import javax.swing.ListModel;33 35 import javax.swing.ListSelectionModel; 34 36 import javax.swing.UIManager; 35 37 import javax.swing.event.ListDataEvent; 36 import javax.swing.event.ListDataListener;37 38 import javax.swing.event.ListSelectionEvent; 38 39 import javax.swing.event.ListSelectionListener; 40 import javax.swing.event.TableModelEvent; 41 import javax.swing.event.TableModelListener; 42 import javax.swing.table.AbstractTableModel; 43 import javax.swing.table.DefaultTableCellRenderer; 44 import javax.swing.table.TableCellRenderer; 45 import javax.swing.table.TableModel; 39 46 40 47 import org.openstreetmap.josm.Main; … … 53 60 import org.openstreetmap.josm.tools.ImageProvider; 54 61 import org.openstreetmap.josm.tools.Shortcut; 55 import org.openstreetmap.josm.tools.ImageProvider.OverlayPosition;56 62 57 63 /** … … 97 103 private DefaultListSelectionModel selectionModel; 98 104 99 /** the list of layers */ 105 /** the list of layers (technically its a JTable, but appears like a list) */ 100 106 private LayerList layerList; 101 107 … … 168 174 layerList = new LayerList(model); 169 175 layerList.setSelectionModel(selectionModel); 170 layerList.addMouseListener(new DblClickAdapter());171 176 layerList.addMouseListener(new PopupMenuHandler()); 172 177 layerList.setBackground(UIManager.getColor("Button.background")); 173 layerList.setCellRenderer(new LayerListCellRenderer()); 178 layerList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); 179 layerList.setTableHeader(null); 180 layerList.setShowGrid(false); 181 layerList.setIntercellSpacing(new Dimension(0, 0)); 182 final int ICON_WIDTH = 16; 183 layerList.getColumnModel().getColumn(0).setCellRenderer(new ActiveLayerCellRenderer()); 184 layerList.getColumnModel().getColumn(0).setCellEditor(new DefaultCellEditor(new ActiveLayerCheckBox())); 185 layerList.getColumnModel().getColumn(0).setMaxWidth(ICON_WIDTH); 186 layerList.getColumnModel().getColumn(0).setPreferredWidth(ICON_WIDTH); 187 layerList.getColumnModel().getColumn(0).setResizable(false); 188 layerList.getColumnModel().getColumn(1).setCellRenderer(new LayerVisibleCellRenderer()); 189 layerList.getColumnModel().getColumn(1).setCellEditor(new DefaultCellEditor(new LayerVisibleCheckBox())); 190 layerList.getColumnModel().getColumn(1).setMaxWidth(ICON_WIDTH); 191 layerList.getColumnModel().getColumn(1).setPreferredWidth(ICON_WIDTH); 192 layerList.getColumnModel().getColumn(1).setResizable(false); 193 layerList.getColumnModel().getColumn(2).setCellRenderer(new LayerNameCellRenderer()); 194 layerList.getColumnModel().getColumn(2).setCellEditor(new LayerNameCellEditor(new JTextField())); 195 174 196 add(new JScrollPane(layerList), BorderLayout.CENTER); 175 197 … … 181 203 model.addLayerListModelListener( 182 204 new LayerListModelListener() { 183 public void makeVisible(int index, Layer layer) { 184 layerList.ensureIndexIsVisible(index); 205 public void makeVisible(int row, Layer layer) { 206 System.err.println(Thread.currentThread()); 207 layerList.scrollToVisible(row, 0); 208 layerList.repaint(); 185 209 } 186 210 public void refresh() { … … 210 234 } 211 235 212 pr ivateinterface IEnabledStateUpdating {236 protected interface IEnabledStateUpdating { 213 237 void updateEnabledState(); 214 238 } … … 240 264 * @param listSelectionModel the source emitting {@see ListDataEvent}s 241 265 */ 242 protected void adaptTo(final IEnabledStateUpdating listener, ListModel listModel) { 243 listModel.addListDataListener( 244 new ListDataListener() { 245 public void contentsChanged(ListDataEvent e) { 246 listener.updateEnabledState(); 247 } 248 249 public void intervalAdded(ListDataEvent e) { 250 listener.updateEnabledState(); 251 } 252 253 public void intervalRemoved(ListDataEvent e) { 254 listener.updateEnabledState(); 255 } 256 } 266 protected void adaptTo(final IEnabledStateUpdating listener, LayerListModel listModel) { 267 listModel.addTableModelListener( 268 new TableModelListener() { 269 270 @Override 271 public void tableChanged(TableModelEvent e) { 272 listener.updateEnabledState(); 273 } 274 } 257 275 ); 258 276 } … … 577 595 } 578 596 579 /** 580 * the list cell renderer used to render layer list entries 581 * 582 */ 583 static class LayerListCellRenderer extends DefaultListCellRenderer { 597 private static class ActiveLayerCheckBox extends JCheckBox { 598 public ActiveLayerCheckBox() { 599 setHorizontalAlignment(javax.swing.SwingConstants.CENTER); 600 ImageIcon blank = ImageProvider.get("dialogs/layerlist", "blank"); 601 ImageIcon active = ImageProvider.get("dialogs/layerlist", "active"); 602 setIcon(blank); 603 setSelectedIcon(active); 604 setRolloverIcon(blank); 605 setRolloverSelectedIcon(active); 606 setPressedIcon(active); 607 } 608 } 609 610 private static class LayerVisibleCheckBox extends JCheckBox { 611 public LayerVisibleCheckBox() { 612 setHorizontalAlignment(javax.swing.SwingConstants.CENTER); 613 ImageIcon eye = ImageProvider.get("dialogs/layerlist", "eye"); 614 ImageIcon eye_off = ImageProvider.get("dialogs/layerlist", "eye-off"); 615 setIcon(eye_off); 616 setSelectedIcon(eye); 617 setRolloverIcon(eye_off); 618 setRolloverSelectedIcon(eye); 619 setPressedIcon(ImageProvider.get("dialogs/layerlist", "eye-pressed")); 620 } 621 } 622 623 private static class ActiveLayerCellRenderer implements TableCellRenderer { 624 JCheckBox cb; 625 public ActiveLayerCellRenderer() { 626 cb = new ActiveLayerCheckBox(); 627 } 628 629 @Override 630 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { 631 boolean active = (Boolean) value; 632 cb.setSelected(active); 633 cb.setToolTipText(active ? tr("this layer is the active layer") : tr("this layer is not currently active (click to activate)")); 634 return cb; 635 } 636 } 637 638 private static class LayerVisibleCellRenderer implements TableCellRenderer { 639 JCheckBox cb; 640 public LayerVisibleCellRenderer() { 641 cb = new LayerVisibleCheckBox(); 642 } 643 644 @Override 645 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { 646 boolean visible = (Boolean) value; 647 cb.setSelected(visible); 648 cb.setToolTipText(visible ? tr("layer is currently visible (click to hide layer)") : tr("layer is currently hidden (click to show layer)")); 649 return cb; 650 } 651 } 652 653 private static class LayerNameCellRenderer extends DefaultTableCellRenderer { 584 654 585 655 protected boolean isActiveLayer(Layer layer) { … … 589 659 } 590 660 591 @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { 661 @Override 662 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { 592 663 Layer layer = (Layer)value; 593 JLabel label = (JLabel)super.getListCellRendererComponent(list, 594 layer.getName(), index, isSelected, cellHasFocus); 595 Icon icon = layer.getIcon(); 664 JLabel label = (JLabel)super.getTableCellRendererComponent(table, 665 layer.getName(), isSelected, hasFocus, row, column); 596 666 if (isActiveLayer(layer)) { 597 icon = ImageProvider.overlay(icon, "overlay/active", OverlayPosition.SOUTHWEST); 598 } 599 if (!layer.isVisible()) { 600 icon = ImageProvider.overlay(icon, "overlay/invisiblenew", OverlayPosition.SOUTHEAST); 601 } 602 label.setIcon(icon); 667 label.setFont(label.getFont().deriveFont(Font.BOLD)); 668 } 669 //label.setEnabled(layer.isVisible()); 670 label.setIcon(layer.getIcon()); 603 671 label.setToolTipText(layer.getToolTipText()); 604 672 return label; … … 606 674 } 607 675 676 private static class LayerNameCellEditor extends DefaultCellEditor { 677 public LayerNameCellEditor(JTextField tf) { 678 super(tf); 679 } 680 681 @Override 682 public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { 683 JTextField tf = (JTextField) super.getTableCellEditorComponent(table, value, isSelected, row, column); 684 Layer l = (Layer) value; 685 tf.setText(l.getName()); 686 return tf; 687 } 688 } 689 608 690 class PopupMenuHandler extends PopupMenuLauncher { 609 691 @Override 610 692 public void launch(MouseEvent evt) { 611 693 Point p = evt.getPoint(); 612 int index = layerList. locationToIndex(p);694 int index = layerList.rowAtPoint(p); 613 695 if (index < 0) return; 614 if (!layerList.getCell Bounds(index,index).contains(evt.getPoint()))696 if (!layerList.getCellRect(index, 2, false).contains(evt.getPoint())) 615 697 return; 616 if (!layerList.isSelected Index(index)) {617 layerList.set SelectedIndex(index);698 if (!layerList.isRowSelected(index)) { 699 layerList.setRowSelectionInterval(index, index); 618 700 } 619 701 Layer layer = model.getLayer(index); 620 702 LayerListPopup menu = new LayerListPopup(getModel().getSelectedLayers(), layer); 621 703 menu.show(LayerListDialog.this, p.x, p.y-3); 622 }623 }624 625 class DblClickAdapter extends MouseAdapter {626 @Override public void mouseClicked(MouseEvent e) {627 if (e.getClickCount() == 2) {628 int index = layerList.locationToIndex(e.getPoint());629 if (!layerList.getCellBounds(index, index).contains(e.getPoint()))630 return;631 Layer layer = model.getLayer(index);632 layer.toggleVisible();633 }634 704 } 635 705 } … … 686 756 * moving layers up and down, for toggling their visibility, and for activating a layer. 687 757 * 688 * The model is a {@see ListModel} and it provides a {@see ListSelectionModel}. It expectes758 * The model is a {@see TableModel} and it provides a {@see ListSelectionModel}. It expects 689 759 * to be configured with a {@see DefaultListSelectionModel}. The selection model is used 690 760 * to update the selection state of views depending on messages sent to the model. … … 696 766 * the properties {@see Layer#VISIBLE_PROP} and {@see Layer#NAME_PROP}. 697 767 */ 698 public static class LayerListModel extends DefaultListModel implements MapView.LayerChangeListener, PropertyChangeListener{ 699 768 public static class LayerListModel extends AbstractTableModel implements MapView.LayerChangeListener, PropertyChangeListener { 700 769 /** manages list selection state*/ 701 770 private DefaultListSelectionModel selectionModel; … … 768 837 layer.addPropertyChangeListener(this); 769 838 } 770 fire ContentsChanged(this, 0, getSize());839 fireTableDataChanged(); 771 840 } 772 841 … … 784 853 selectionModel.setSelectionInterval(idx, idx); 785 854 } 786 fireContentsChanged(this, 0, getSize());787 855 ensureSelectedIsVisible(); 788 856 } … … 831 899 return; 832 900 layer.removePropertyChangeListener(this); 833 int size = get Size();901 int size = getRowCount(); 834 902 List<Integer> rows = getSelectedRows(); 835 903 if (rows.isEmpty() && size > 0) { 836 904 selectionModel.setSelectionInterval(size-1, size-1); 837 905 } 906 fireTableDataChanged(); 838 907 fireRefresh(); 839 908 ensureActiveSelected(); … … 848 917 if (layer == null) return; 849 918 layer.addPropertyChangeListener(this); 850 fire ContentsChanged(this, 0, getSize());919 fireTableDataChanged(); 851 920 int idx = getLayers().indexOf(layer); 852 921 selectionModel.setSelectionInterval(idx, idx); … … 860 929 */ 861 930 public Layer getFirstLayer() { 862 if (get Size() == 0) return null;931 if (getRowCount() == 0) return null; 863 932 return getLayers().get(0); 864 933 } … … 872 941 */ 873 942 public Layer getLayer(int index) { 874 if (index < 0 || index >= get Size())943 if (index < 0 || index >= getRowCount()) 875 944 return null; 876 945 return getLayers().get(index); … … 902 971 Main.map.mapView.moveLayer(l1, row-1); 903 972 } 904 fire ContentsChanged(this, 0, getSize());973 fireTableDataChanged(); 905 974 selectionModel.clearSelection(); 906 975 for(int row: sel) { … … 936 1005 Main.map.mapView.moveLayer(l2, row); 937 1006 } 938 fire ContentsChanged(this, 0, getSize());1007 fireTableDataChanged(); 939 1008 selectionModel.clearSelection(); 940 1009 for(int row: sel) { … … 998 1067 */ 999 1068 protected void ensureActiveSelected() { 1000 if (getLayers().size() == 0) return; 1069 if (getLayers().isEmpty()) 1070 return; 1001 1071 if (getActiveLayer() != null) { 1002 1072 // there's an active layer - select it and make it … … 1024 1094 1025 1095 /* ------------------------------------------------------------------------------ */ 1026 /* Interface ListModel*/1096 /* Interface TableModel */ 1027 1097 /* ------------------------------------------------------------------------------ */ 1028 @Override 1029 public Object getElementAt(int index) { 1030 return getLayers().get(index); 1031 } 1032 1033 @Override 1034 public int getSize() { 1098 1099 @Override 1100 public int getRowCount() { 1035 1101 List<Layer> layers = getLayers(); 1036 1102 if (layers == null) return 0; … … 1038 1104 } 1039 1105 1106 @Override 1107 public int getColumnCount() { 1108 return 3; 1109 } 1110 1111 @Override 1112 public Object getValueAt(int row, int col) { 1113 switch (col) { 1114 case 0: return getLayers().get(row) == getActiveLayer(); 1115 case 1: return getLayers().get(row).isVisible(); 1116 case 2: return getLayers().get(row); 1117 default: throw new RuntimeException(); 1118 } 1119 } 1120 1121 public boolean isCellEditable(int row, int col) { 1122 if (col == 0 && getActiveLayer() == getLayers().get(row)) 1123 return false; 1124 return true; 1125 } 1126 1127 public void setValueAt(Object value, int row, int col) { 1128 Layer l = getLayers().get(row); 1129 switch (col) { 1130 case 0: 1131 Main.map.mapView.setActiveLayer(l); 1132 l.setVisible(true); 1133 break; 1134 case 1: 1135 l.setVisible((Boolean) value); 1136 break; 1137 case 2: 1138 l.setName((String) value); 1139 break; 1140 default: throw new RuntimeException(); 1141 } 1142 fireTableCellUpdated(row, col); 1143 } 1144 1040 1145 /* ------------------------------------------------------------------------------ */ 1041 1146 /* Interface LayerChangeListener */ 1042 1147 /* ------------------------------------------------------------------------------ */ 1148 @Override 1043 1149 public void activeLayerChange(Layer oldLayer, Layer newLayer) { 1044 1150 if (oldLayer != null) { 1045 1151 int idx = getLayers().indexOf(oldLayer); 1046 1152 if (idx >= 0) { 1047 fire ContentsChanged(this,idx,idx);1153 fireTableRowsUpdated(idx,idx); 1048 1154 } 1049 1155 } … … 1052 1158 int idx = getLayers().indexOf(newLayer); 1053 1159 if (idx >= 0) { 1054 fire ContentsChanged(this,idx,idx);1160 fireTableRowsUpdated(idx,idx); 1055 1161 } 1056 1162 } … … 1058 1164 } 1059 1165 1166 @Override 1060 1167 public void layerAdded(Layer newLayer) { 1061 1168 onAddLayer(newLayer); 1062 1169 } 1063 1170 1171 @Override 1064 1172 public void layerRemoved(final Layer oldLayer) { 1065 1173 onRemoveLayer(oldLayer); … … 1069 1177 /* Interface PropertyChangeListener */ 1070 1178 /* ------------------------------------------------------------------------------ */ 1179 @Override 1071 1180 public void propertyChange(PropertyChangeEvent evt) { 1072 1181 if (evt.getSource() instanceof Layer) { … … 1079 1188 } 1080 1189 1081 static class LayerList extends J List{1082 public LayerList( ListModel dataModel) {1190 static class LayerList extends JTable { 1191 public LayerList(TableModel dataModel) { 1083 1192 super(dataModel); 1084 1193 } 1085 1194 1086 @Override 1087 protected void processMouseEvent(MouseEvent e) { 1088 // if the layer list is embedded in a detached dialog, the last row is 1089 // selected if a user clicks in the empty space *below* the last row. 1090 // This mouse event filter prevents this. 1091 // 1092 int idx = locationToIndex(e.getPoint()); 1093 // sometimes bounds can be null, see #3539 1094 Rectangle bounds = getCellBounds(idx,idx); 1095 if (bounds != null && bounds.contains(e.getPoint())) { 1096 super.processMouseEvent(e); 1097 } 1195 public void scrollToVisible(int row, int col) { 1196 if (!(getParent() instanceof JViewport)) 1197 return; 1198 JViewport viewport = (JViewport) getParent(); 1199 Rectangle rect = getCellRect(row, col, true); 1200 Point pt = viewport.getViewPosition(); 1201 rect.setLocation(rect.x - pt.x, rect.y - pt.y); 1202 viewport.scrollRectToVisible(rect); 1098 1203 } 1099 1204 }
Note:
See TracChangeset
for help on using the changeset viewer.