001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.io; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.awt.Component; 007import java.awt.Dimension; 008import java.awt.GridBagLayout; 009import java.awt.event.ActionEvent; 010import java.awt.event.ActionListener; 011import java.util.EventObject; 012 013import javax.swing.AbstractAction; 014import javax.swing.ActionMap; 015import javax.swing.JCheckBox; 016import javax.swing.JPanel; 017import javax.swing.JTable; 018import javax.swing.event.CellEditorListener; 019import javax.swing.table.TableCellEditor; 020import javax.swing.table.TableCellRenderer; 021 022import org.openstreetmap.josm.gui.util.CellEditorSupport; 023import org.openstreetmap.josm.tools.GBC; 024 025/** 026 * This class creates a table cell that features two checkboxes, Upload and Save. It 027 * handles everything on its own, in other words it renders itself and also functions 028 * as editor so the checkboxes may be set by the user. 029 * 030 * Intended usage is like this: 031 * <code> 032 * <br>ActionFlagsTableCell aftc = new ActionFlagsTableCell(); 033 * <br>col = new TableColumn(0); 034 * <br>col.setCellRenderer(aftc); 035 * <br>col.setCellEditor(aftc); 036 * </code> 037 */ 038class ActionFlagsTableCell extends JPanel implements TableCellRenderer, TableCellEditor { 039 private final JCheckBox[] checkBoxes = new JCheckBox[2]; 040 private final transient CellEditorSupport cellEditorSupport = new CellEditorSupport(this); 041 042 private final transient ActionListener al = new ActionListener() { 043 @Override 044 public void actionPerformed(ActionEvent e) { 045 cellEditorSupport.fireEditingStopped(); 046 } 047 }; 048 049 /** 050 * Constructs a new {@code ActionFlagsTableCell}. 051 */ 052 ActionFlagsTableCell() { 053 checkBoxes[0] = new JCheckBox(tr("Upload")); 054 checkBoxes[1] = new JCheckBox(tr("Save")); 055 setLayout(new GridBagLayout()); 056 057 ActionMap am = getActionMap(); 058 for (final JCheckBox b : checkBoxes) { 059 b.setPreferredSize(new Dimension(b.getPreferredSize().width, 19)); 060 b.addActionListener(al); 061 am.put(b.getText(), new AbstractAction() { 062 @Override 063 public void actionPerformed(ActionEvent e) { 064 b.setSelected(!b.isSelected()); 065 cellEditorSupport.fireEditingStopped(); 066 } 067 }); 068 } 069 } 070 071 protected void updateCheckboxes(Object v) { 072 if (v != null && checkBoxes[0] != null && checkBoxes[1] != null) { 073 boolean[] values; 074 if (v instanceof SaveLayerInfo) { 075 values = new boolean[2]; 076 values[0] = ((SaveLayerInfo) v).isDoUploadToServer(); 077 values[1] = ((SaveLayerInfo) v).isDoSaveToFile(); 078 } else { 079 values = (boolean[]) v; 080 } 081 checkBoxes[0].setSelected(values[0]); 082 checkBoxes[1].setSelected(values[1]); 083 } 084 } 085 086 private void updatePanel(SaveLayerInfo info) { 087 StringBuilder sb = new StringBuilder(128) 088 .append("<html>") 089 .append(tr("Select which actions to perform for this layer, if you click the leftmost button.")); 090 removeAll(); 091 if (info != null) { 092 if (info.isUploadable()) { 093 sb.append("<br/>") 094 .append(tr("Check \"Upload\" to upload the changes to the OSM server.")); 095 add(checkBoxes[0], GBC.eol().fill(GBC.HORIZONTAL)); 096 } 097 if (info.isSavable()) { 098 sb.append("<br/>") 099 .append(tr("Check \"Save\" to save the layer to the file specified on the left.")); 100 add(checkBoxes[1], GBC.eol().fill(GBC.HORIZONTAL)); 101 } 102 } 103 sb.append("</html>"); 104 setToolTipText(sb.toString()); 105 } 106 107 @Override 108 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { 109 updatePanel((SaveLayerInfo) value); 110 updateCheckboxes(value); 111 return this; 112 } 113 114 @Override 115 public void addCellEditorListener(CellEditorListener l) { 116 cellEditorSupport.addCellEditorListener(l); 117 } 118 119 @Override 120 public void cancelCellEditing() { 121 cellEditorSupport.fireEditingCanceled(); 122 } 123 124 @Override 125 public Object getCellEditorValue() { 126 boolean[] values = new boolean[2]; 127 values[0] = checkBoxes[0].isSelected(); 128 values[1] = checkBoxes[1].isSelected(); 129 return values; 130 } 131 132 @Override 133 public boolean isCellEditable(EventObject anEvent) { 134 return true; 135 } 136 137 @Override 138 public void removeCellEditorListener(CellEditorListener l) { 139 cellEditorSupport.removeCellEditorListener(l); 140 } 141 142 @Override 143 public boolean shouldSelectCell(EventObject anEvent) { 144 return true; 145 } 146 147 @Override 148 public boolean stopCellEditing() { 149 cellEditorSupport.fireEditingStopped(); 150 return true; 151 } 152 153 @Override 154 public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { 155 updatePanel((SaveLayerInfo) value); 156 updateCheckboxes(value); 157 return this; 158 } 159}