Ignore:
Timestamp:
13.02.2010 17:45:10 (2 years ago)
Author:
Gubaer
Message:

fixed #4506: relation-editor: tag-delete-button does not work
removed duplicated code
fixed selection behaviour for tags tag in RelationEditor and UploadDialog

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/tagging/TagTable.java

    r2626 r2974  
    44import static org.openstreetmap.josm.tools.I18n.tr; 
    55 
     6import java.applet.Applet; 
    67import java.awt.AWTException; 
     8import java.awt.Component; 
    79import java.awt.Container; 
    810import java.awt.Dimension; 
     11import java.awt.KeyboardFocusManager; 
    912import java.awt.MouseInfo; 
    1013import java.awt.Point; 
    1114import java.awt.Rectangle; 
    1215import java.awt.Robot; 
     16import java.awt.Window; 
    1317import java.awt.event.ActionEvent; 
    1418import java.awt.event.InputEvent; 
    1519import java.awt.event.KeyEvent; 
    1620import java.awt.event.KeyListener; 
     21import java.beans.PropertyChangeEvent; 
     22import java.beans.PropertyChangeListener; 
     23import java.util.EventObject; 
     24import java.util.concurrent.CopyOnWriteArrayList; 
    1725import java.util.logging.Level; 
    1826import java.util.logging.Logger; 
    1927 
    2028import javax.swing.AbstractAction; 
    21 import javax.swing.Action; 
     29import javax.swing.CellEditor; 
     30import javax.swing.DefaultListSelectionModel; 
    2231import javax.swing.JComponent; 
    2332import javax.swing.JTable; 
     
    3544import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionCache; 
    3645import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionList; 
     46import org.openstreetmap.josm.tools.ImageProvider; 
    3747 
    3848/** 
     
    4050 * 
    4151 */ 
    42 @SuppressWarnings("serial") 
    4352public class TagTable extends JTable  { 
    4453 
    45     private static Logger logger = Logger.getLogger(TagTable.class.getName()); 
     54    private static final Logger logger = Logger.getLogger(TagTable.class.getName()); 
    4655 
    4756    /** the table cell editor used by this table */ 
    4857    private TagCellEditor editor = null; 
    4958 
     59    /** a list of components to which focus can be transferred withouth stopping 
     60     * cell editing this table. 
     61     */ 
     62    private final CopyOnWriteArrayList<Component> doNotStopCellEditingWhenFocused = new CopyOnWriteArrayList<Component>(); 
     63    private CellEditorRemover editorRemover; 
     64 
    5065    /** 
    5166     * The table has two columns. The first column is used for editing rendering and 
     
    5469     */ 
    5570    static class TagTableColumnModel extends DefaultTableColumnModel { 
    56  
    57         public TagTableColumnModel() { 
     71        public TagTableColumnModel(DefaultListSelectionModel selectionModel) { 
     72            setSelectionModel(selectionModel); 
    5873            TableColumn col = null; 
    5974            TagCellRenderer renderer = new TagCellRenderer(); 
     
    7287            col.setCellRenderer(renderer); 
    7388            addColumn(col); 
    74  
    7589        } 
    7690    } 
     
    8599     *   last cell in the table</li> 
    86100     * <ul> 
    87      * 
    88      * @author gubaer 
    89101     * 
    90102     */ 
     
    167179    class DeleteAction extends RunnableAction implements ListSelectionListener { 
    168180 
     181        public DeleteAction() { 
     182            putValue(SMALL_ICON, ImageProvider.get("dialogs", "delete")); 
     183            putValue(SHORT_DESCRIPTION, tr("Delete the selection in the tag table")); 
     184            getSelectionModel().addListSelectionListener(this); 
     185            getColumnModel().getSelectionModel().addListSelectionListener(this); 
     186            updateEnabledState(); 
     187        } 
     188 
    169189        /** 
    170190         * delete a selection of tag names 
     
    194214        } 
    195215 
    196         /** 
    197          * constructor 
    198          */ 
    199         public DeleteAction() { 
    200             putValue(Action.NAME, tr("Delete")); 
    201             getSelectionModel().addListSelectionListener(this); 
    202             getColumnModel().getSelectionModel().addListSelectionListener(this); 
    203         } 
    204  
    205216        @Override 
    206217        public void run() { 
    207218            if (!isEnabled()) 
    208219                return; 
    209             getCellEditor().stopCellEditing(); 
    210             if (getSelectedColumnCount() == 1) { 
     220            switch(getSelectedColumnCount()) { 
     221            case 1: 
    211222                if (getSelectedColumn() == 0) { 
    212223                    deleteTagNames(); 
     
    216227                    // should not happen 
    217228                    // 
    218                     throw new IllegalStateException("unexpected selected clolumn: getSelectedColumn() is " + getSelectedColumn()); 
    219             } else if (getSelectedColumnCount() == 2) { 
     229                    throw new IllegalStateException("unexpected selected column: getSelectedColumn() is " + getSelectedColumn()); 
     230                break; 
     231            case 2: 
    220232                deleteTags(); 
    221             } 
     233                break; 
     234            } 
     235 
     236            if (isEditing()) { 
     237                CellEditor editor = getCellEditor(); 
     238                if (editor != null) { 
     239                    editor.cancelCellEditing(); 
     240                } 
     241            } 
     242 
    222243            TagEditorModel model = (TagEditorModel)getModel(); 
    223244            if (model.getRowCount() == 0) { 
     
    231252         */ 
    232253        public void valueChanged(ListSelectionEvent e) { 
     254            updateEnabledState(); 
     255        } 
     256 
     257        protected void updateEnabledState() { 
    233258            if (isEditing() && getSelectedColumnCount() == 1 && getSelectedRowCount() == 1) { 
    234259                setEnabled(false); 
     
    240265                setEnabled(false); 
    241266            } 
    242  
    243267        } 
    244268    } 
     
    249273     * 
    250274     */ 
    251     class AddAction extends RunnableAction { 
    252  
     275    class AddAction extends RunnableAction implements PropertyChangeListener{ 
    253276        public AddAction() { 
    254             putValue(Action.NAME, tr("Add")); 
     277            putValue(SMALL_ICON, ImageProvider.get("dialogs", "add")); 
     278            putValue(SHORT_DESCRIPTION, tr("Add a new tag")); 
     279            TagTable.this.addPropertyChangeListener(this); 
     280            updateEnabledState(); 
    255281        } 
    256282 
    257283        @Override 
    258284        public void run() { 
    259             getCellEditor().stopCellEditing(); 
     285            CellEditor editor = getCellEditor(); 
     286            if (editor != null) { 
     287                getCellEditor().stopCellEditing(); 
     288            } 
    260289            ((TagEditorModel)getModel()).appendNewTag(); 
    261290            final int rowIdx = getModel().getRowCount()-1; 
    262291            requestFocusInCell(rowIdx, 0); 
    263292        } 
     293 
     294        protected void updateEnabledState() { 
     295            setEnabled(TagTable.this.isEnabled()); 
     296        } 
     297 
     298        public void propertyChange(PropertyChangeEvent evt) { 
     299            updateEnabledState(); 
     300        } 
    264301    } 
    265302 
     
    287324    protected void init() { 
    288325        setAutoResizeMode(JTable.AUTO_RESIZE_OFF); 
    289         setCellSelectionEnabled(true); 
     326        //setCellSelectionEnabled(true); 
     327        setRowSelectionAllowed(true); 
     328        setColumnSelectionAllowed(true); 
    290329        setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); 
    291         putClientProperty("terminateEditOnFocusLost", Boolean.TRUE); 
    292330 
    293331        // make ENTER behave like TAB 
     
    316354        // 
    317355        editor = new TagCellEditor(); 
    318         editor.setTagEditorModel((TagEditorModel)getModel()); 
    319356        getColumnModel().getColumn(0).setCellEditor(editor); 
    320357        getColumnModel().getColumn(1).setCellEditor(editor); 
     358 
     359        getSelectionModel().addListSelectionListener(new ListSelectionListener() { 
     360 
     361            public void valueChanged(ListSelectionEvent e) { 
     362                ListSelectionModel rm = getSelectionModel(); 
     363                ListSelectionModel cm = getColumnModel().getSelectionModel(); 
     364            } 
     365        }); 
    321366    } 
    322367 
     
    327372     * @param columnModel 
    328373     */ 
    329     public TagTable(TableModel model) { 
    330         super(model, new TagTableColumnModel()); 
     374    public TagTable(TableModel model, DefaultListSelectionModel rowSelectionModel, DefaultListSelectionModel colSelectionModel) { 
     375        super(model, new TagTableColumnModel(colSelectionModel), rowSelectionModel); 
    331376        init(); 
    332377    } 
     
    430475        } 
    431476    } 
     477 
     478    public void addComponentNotStoppingCellEditing(Component component) { 
     479        if (component == null) return; 
     480        doNotStopCellEditingWhenFocused.addIfAbsent(component); 
     481    } 
     482 
     483    public void removeComponentNotStoppingCellEditing(Component component) { 
     484        if (component == null) return; 
     485        doNotStopCellEditingWhenFocused.remove(component); 
     486    } 
     487 
     488    @Override 
     489    public boolean editCellAt(int row, int column, EventObject e){ 
     490 
     491        // a snipped copied from the Java 1.5 implementation of JTable 
     492        // 
     493        if (cellEditor != null && !cellEditor.stopCellEditing()) 
     494            return false; 
     495 
     496        if (row < 0 || row >= getRowCount() || 
     497                column < 0 || column >= getColumnCount()) 
     498            return false; 
     499 
     500        if (!isCellEditable(row, column)) 
     501            return false; 
     502 
     503        // make sure our custom implementation of CellEditorRemover is created 
     504        if (editorRemover == null) { 
     505            KeyboardFocusManager fm = 
     506                KeyboardFocusManager.getCurrentKeyboardFocusManager(); 
     507            editorRemover = new CellEditorRemover(fm); 
     508            fm.addPropertyChangeListener("permanentFocusOwner", editorRemover); 
     509        } 
     510 
     511        // delegate to the default implementation 
     512        return super.editCellAt(row, column,e); 
     513    } 
     514 
     515 
     516    @Override 
     517    public void removeEditor() { 
     518        // make sure we unregister our custom implementation of CellEditorRemover 
     519        KeyboardFocusManager.getCurrentKeyboardFocusManager(). 
     520        removePropertyChangeListener("permanentFocusOwner", editorRemover); 
     521        editorRemover = null; 
     522        super.removeEditor(); 
     523    } 
     524 
     525    @Override 
     526    public void removeNotify() { 
     527        // make sure we unregister our custom implementation of CellEditorRemover 
     528        KeyboardFocusManager.getCurrentKeyboardFocusManager(). 
     529        removePropertyChangeListener("permanentFocusOwner", editorRemover); 
     530        editorRemover = null; 
     531        super.removeNotify(); 
     532    } 
     533 
     534    /** 
     535     * This is a custom implementation of the CellEditorRemover used in JTable 
     536     * to handle the client property <tt>terminateEditOnFocusLost</tt>. 
     537     *  
     538     * This implementation also checks whether focus is transferred to one of a list 
     539     * of dedicated components, see {@see TagTable#doNotStopCellEditingWhenFocused}. 
     540     * A typical example for such a component is a button in {@see TagEditorPanel} 
     541     * which isn't a child component of {@see TagTable} but which should respond to 
     542     * to focus transfer in a similar way to a child of TagTable. 
     543     * 
     544     */ 
     545    class CellEditorRemover implements PropertyChangeListener { 
     546        KeyboardFocusManager focusManager; 
     547 
     548        public CellEditorRemover(KeyboardFocusManager fm) { 
     549            this.focusManager = fm; 
     550        } 
     551 
     552        public void propertyChange(PropertyChangeEvent ev) { 
     553            if (!isEditing()) 
     554                return; 
     555 
     556            Component c = focusManager.getPermanentFocusOwner(); 
     557            while (c != null) { 
     558                if (c == TagTable.this) 
     559                    // focus remains inside the table 
     560                    return; 
     561                if (doNotStopCellEditingWhenFocused.contains(c)) 
     562                    // focus remains on one of the associated components 
     563                    return; 
     564                else if ((c instanceof Window) || 
     565                        (c instanceof Applet && c.getParent() == null)) { 
     566                    if (c == SwingUtilities.getRoot(TagTable.this)) { 
     567                        if (!getCellEditor().stopCellEditing()) { 
     568                            getCellEditor().cancelCellEditing(); 
     569                        } 
     570                    } 
     571                    break; 
     572                } 
     573                c = c.getParent(); 
     574            } 
     575        } 
     576    } 
    432577} 
Note: See TracChangeset for help on using the changeset viewer.