Ignore:
Timestamp:
2013-03-23T19:56:44+01:00 (13 years ago)
Author:
akks
Message:

Membership tabled in properties toggle dialog supports multiselect (and multiple membership deletion)
Property toggle dialog refactoring - methods splitting and reordering
see #7846: more RelationListDialog refactoring, all other relation-related actions separated from dialogs, @Override, JavaDocs

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/dialogs/properties/PropertiesDialog.java

    r5793 r5799  
    2323import java.util.EnumSet;
    2424import java.util.HashMap;
    25 import java.util.HashSet;
    2625import java.util.LinkedList;
    2726import java.util.List;
     
    8180import org.openstreetmap.josm.gui.dialogs.ToggleDialog;
    8281import org.openstreetmap.josm.gui.dialogs.properties.PresetListPanel.PresetHandler;
    83 import org.openstreetmap.josm.gui.dialogs.relation.DownloadRelationMemberTask;
    8482import org.openstreetmap.josm.gui.dialogs.relation.RelationEditor;
    8583import org.openstreetmap.josm.gui.layer.OsmDataLayer;
     
    113111 */
    114112public class PropertiesDialog extends ToggleDialog implements SelectionChangedListener, MapView.EditLayerChangeListener, DataSetListenerAdapter.Listener {
    115     /**
    116      * Watches for mouse clicks
    117      * @author imi
    118      */
    119     public class MouseClickWatch extends MouseAdapter {
    120         @Override public void mouseClicked(MouseEvent e) {
    121             if (e.getClickCount() < 2)
    122             {
    123                 // single click, clear selection in other table not clicked in
    124                 if (e.getSource() == propertyTable) {
    125                     membershipTable.clearSelection();
    126                 } else if (e.getSource() == membershipTable) {
    127                     propertyTable.clearSelection();
    128                 }
    129             }
    130             // double click, edit or add property
    131             else if (e.getSource() == propertyTable)
    132             {
    133                 int row = propertyTable.rowAtPoint(e.getPoint());
    134                 if (row > -1) {
    135                     boolean focusOnKey = (propertyTable.columnAtPoint(e.getPoint()) == 0);
    136                     editHelper.editProperty(row, focusOnKey);
    137                 } else {
    138                     editHelper.addProperty();
    139                     btnAdd.requestFocusInWindow();
    140                 }
    141             } else if (e.getSource() == membershipTable) {
    142                 int row = membershipTable.rowAtPoint(e.getPoint());
    143                 if (row > -1) {
    144                     editMembership(row);
    145                 }
    146             }
    147             else
    148             {
    149                 editHelper.addProperty();
    150                 btnAdd.requestFocusInWindow();
    151             }
    152         }
    153         @Override public void mousePressed(MouseEvent e) {
    154             if (e.getSource() == propertyTable) {
    155                 membershipTable.clearSelection();
    156             } else if (e.getSource() == membershipTable) {
    157                 propertyTable.clearSelection();
    158             }
    159         }
    160 
    161     }
    162 
    163113    // hook for roadsigns plugin to display a small
    164114    // button in the upper right corner of this dialog
    165115    public static final JPanel pluginHook = new JPanel();
    166116
     117    /**
     118     * The property data of selected objects.
     119     */
     120    private final DefaultTableModel propertyData = new ReadOnlyTableModel();
     121
     122    /**
     123     * The membership data of selected objects.
     124     */
     125    private final DefaultTableModel membershipData = new ReadOnlyTableModel();
     126
     127    /**
     128     * The properties table.
     129     */
     130    private final JTable propertyTable = new JTable(propertyData);
     131    /**
     132     * The membership table.
     133     */
     134    private final JTable membershipTable = new JTable(membershipData);
     135
    167136    private JPopupMenu propertyMenu;
    168137    private JPopupMenu membershipMenu;
    169138
    170139    private final Map<String, Map<String, Integer>> valueCount = new TreeMap<String, Map<String, Integer>>();
    171 
     140    /**
     141     * This sub-object is responsible for all adding and editing of properties
     142     */
     143    private final TagEditHelper editHelper = new TagEditHelper(propertyData, valueCount);
    172144   
    173145    private final DataSetListenerAdapter dataChangedAdapter = new DataSetListenerAdapter(this);
     
    190162    private final SelectRelationAction selectRelationAction = new SelectRelationAction(false);
    191163   
    192     @Override
    193     public void showNotify() {
    194         DatasetEventManager.getInstance().addDatasetListener(dataChangedAdapter, FireMode.IN_EDT_CONSOLIDATED);
    195         SelectionEventManager.getInstance().addSelectionListener(this, FireMode.IN_EDT_CONSOLIDATED);
    196         MapView.addEditLayerChangeListener(this);
    197         for (JosmAction action : josmActions) {
    198             Main.registerActionShortcut(action);
    199         }
    200         updateSelection();
    201     }
    202 
    203     @Override
    204     public void hideNotify() {
    205         DatasetEventManager.getInstance().removeDatasetListener(dataChangedAdapter);
    206         SelectionEventManager.getInstance().removeSelectionListener(this);
    207         MapView.removeEditLayerChangeListener(this);
    208         for (JosmAction action : josmActions) {
    209             Main.unregisterActionShortcut(action);
    210         }
    211     }
    212 
    213     /**
    214      * This simply fires up an {@link RelationEditor} for the relation shown; everything else
    215      * is the editor's business.
    216      *
    217      * @param row
    218      */
    219     private void editMembership(int row) {
    220         Relation relation = (Relation)membershipData.getValueAt(row, 0);
    221         Main.map.relationListDialog.selectRelation(relation);
    222         RelationEditor.getEditor(
    223                 Main.map.mapView.getEditLayer(),
    224                 relation,
    225                 ((MemberInfo) membershipData.getValueAt(row, 1)).role).setVisible(true);
    226     }
    227 
    228     /**
    229      * The property data of selected objects.
    230      */
    231     private final DefaultTableModel propertyData = new DefaultTableModel() {
    232         @Override public boolean isCellEditable(int row, int column) {
    233             return false;
    234         }
    235         @Override public Class<?> getColumnClass(int columnIndex) {
    236             return String.class;
    237         }
    238     };
    239 
    240     /**
    241      * The membership data of selected objects.
    242      */
    243     private final DefaultTableModel membershipData = new DefaultTableModel() {
    244         @Override public boolean isCellEditable(int row, int column) {
    245             return false;
    246         }
    247         @Override public Class<?> getColumnClass(int columnIndex) {
    248             return String.class;
    249         }
    250     };
    251 
    252     /**
    253      * The properties table.
    254      */
    255     private final JTable propertyTable = new JTable(propertyData);
    256     /**
    257      * The membership table.
    258      */
    259     private final JTable membershipTable = new JTable(membershipData);
    260 
    261     /**
    262      * This sub-object is responsible for all adding and editing of properties
    263      */
    264     private final TagEditHelper editHelper = new TagEditHelper(propertyData, valueCount);
    265    
    266164    /**
    267165     * The Add button (needed to be able to disable it)
    268166     */
    269     private final SideButton btnAdd;
     167    private final SideButton btnAdd = new SideButton(addAction);
    270168    /**
    271169     * The Edit button (needed to be able to disable it)
    272170     */
    273     private final SideButton btnEdit;
     171    private final SideButton btnEdit = new SideButton(editAction);
    274172    /**
    275173     * The Delete button (needed to be able to disable it)
    276174     */
    277     private final SideButton btnDel;
     175    private final SideButton btnDel = new SideButton(deleteAction);
    278176    /**
    279177     * Matching preset display class
    280178     */
    281179    private final PresetListPanel presets = new PresetListPanel();
    282 
     180   
    283181    /**
    284182     * Text to display when nothing selected.
     
    287185            + tr("Select objects for which to change properties.") + "</p></html>");
    288186
    289     static class MemberInfo {
    290         List<RelationMember> role = new ArrayList<RelationMember>();
    291         List<Integer> position = new ArrayList<Integer>();
    292         private String positionString = null;
    293         void add(RelationMember r, Integer p) {
    294             role.add(r);
    295             position.add(p);
    296         }
    297         String getPositionString() {
    298             if (positionString == null) {
    299                 Collections.sort(position);
    300                 positionString = String.valueOf(position.get(0));
    301                 int cnt = 0;
    302                 int last = position.get(0);
    303                 for (int i = 1; i < position.size(); ++i) {
    304                     int cur = position.get(i);
    305                     if (cur == last + 1) {
    306                         ++cnt;
    307                     } else if (cnt == 0) {
    308                         positionString += "," + String.valueOf(cur);
    309                     } else {
    310                         positionString += "-" + String.valueOf(last);
    311                         positionString += "," + String.valueOf(cur);
    312                         cnt = 0;
    313                     }
    314                     last = cur;
    315                 }
    316                 if (cnt >= 1) {
    317                     positionString += "-" + String.valueOf(last);
    318                 }
    319             }
    320             if (positionString.length() > 20) {
    321                 positionString = positionString.substring(0, 17) + "...";
    322             }
    323             return positionString;
    324         }
    325     }
    326 
     187    private PresetHandler presetHandler = new PresetHandler() {
     188        @Override public void updateTags(List<Tag> tags) {
     189            Command command = TaggingPreset.createCommand(getSelection(), tags);
     190            if (command != null) Main.main.undoRedo.add(command);
     191        }
     192
     193        @Override public Collection<OsmPrimitive> getSelection() {
     194            if (Main.main == null) return null;
     195            if (Main.main.getCurrentDataSet() == null) return null;
     196            return Main.main.getCurrentDataSet().getSelected();
     197        }
     198    };
     199   
     200    // <editor-fold defaultstate="collapsed" desc="Dialog construction and helper methods">
     201   
    327202    /**
    328203     * Create a new PropertiesDialog
     
    333208                        Shortcut.ALT_SHIFT), 150, true);
    334209
     210        setupPropertiesMenu();
     211        buildPropertiesTable();
     212
     213        setupMembershipMenu();
     214        buildMembershipTable();
     215       
     216        // combine both tables and wrap them in a scrollPane
     217        JPanel bothTables = new JPanel();
     218        boolean top = Main.pref.getBoolean("properties.presets.top", true);
     219        bothTables.setLayout(new GridBagLayout());
     220        if(top) {
     221            bothTables.add(presets, GBC.std().fill(GBC.HORIZONTAL).insets(5, 2, 5, 2).anchor(GBC.NORTHWEST));
     222            double epsilon = Double.MIN_VALUE; // need to set a weight or else anchor value is ignored
     223            bothTables.add(pluginHook, GBC.eol().insets(0,1,1,1).anchor(GBC.NORTHEAST).weight(epsilon, epsilon));
     224        }
     225        bothTables.add(selectSth, GBC.eol().fill().insets(10, 10, 10, 10));
     226        bothTables.add(propertyTable.getTableHeader(), GBC.eol().fill(GBC.HORIZONTAL));
     227        bothTables.add(propertyTable, GBC.eol().fill(GBC.BOTH));
     228        bothTables.add(membershipTable.getTableHeader(), GBC.eol().fill(GBC.HORIZONTAL));
     229        bothTables.add(membershipTable, GBC.eol().fill(GBC.BOTH));
     230        if(!top) {
     231            bothTables.add(presets, GBC.eol().fill(GBC.HORIZONTAL).insets(5, 2, 5, 2));
     232        }
     233       
     234        setupKeyboardShortcuts();
     235
     236        // Let the action know when selection in the tables change
     237        propertyTable.getSelectionModel().addListSelectionListener(editAction);
     238        membershipTable.getSelectionModel().addListSelectionListener(editAction);
     239        propertyTable.getSelectionModel().addListSelectionListener(deleteAction);
     240        membershipTable.getSelectionModel().addListSelectionListener(deleteAction);
     241       
     242
     243        JScrollPane scrollPane = (JScrollPane) createLayout(bothTables, true, Arrays.asList(new SideButton[] {
     244                this.btnAdd, this.btnEdit, this.btnDel
     245        }));
     246
     247        MouseClickWatch mouseClickWatch = new MouseClickWatch();
     248        propertyTable.addMouseListener(mouseClickWatch);
     249        membershipTable.addMouseListener(mouseClickWatch);
     250        scrollPane.addMouseListener(mouseClickWatch);
     251
     252        selectSth.setPreferredSize(scrollPane.getSize());
     253        presets.setSize(scrollPane.getSize());
     254
     255        editHelper.loadTagsIfNeeded();
     256    }
     257       
     258    private void buildPropertiesTable() {
    335259        // setting up the properties table
    336         propertyMenu = new JPopupMenu();
    337         propertyMenu.add(pasteValueAction);
    338         propertyMenu.add(copyValueAction);
    339         propertyMenu.add(copyKeyValueAction);
    340         propertyMenu.add(copyAllKeyValueAction);
    341         propertyMenu.addSeparator();
    342         propertyMenu.add(searchActionAny);
    343         propertyMenu.add(searchActionSame);
    344         propertyMenu.addSeparator();
    345         propertyMenu.add(helpAction);
    346260
    347261        propertyData.setColumnIdentifiers(new String[]{tr("Key"),tr("Value")});
    348262        propertyTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
    349263        propertyTable.getTableHeader().setReorderingAllowed(false);
    350         propertyTable.addMouseListener(new PopupMenuLauncher() {
    351             @Override
    352             public void launch(MouseEvent evt) {
    353                 Point p = evt.getPoint();
    354                 int row = propertyTable.rowAtPoint(p);
    355                 if (row > -1) {
    356                     propertyTable.changeSelection(row, 0, false, false);
    357                     propertyMenu.show(propertyTable, p.x, p.y-3);
    358                 }
    359             }
    360         });
    361 
     264       
    362265        propertyTable.getColumnModel().getColumn(1).setCellRenderer(new DefaultTableCellRenderer(){
    363266            @Override public Component getTableCellRendererComponent(JTable table, Object value,
     
    385288            }
    386289        });
    387 
    388         // setting up the membership table
    389         membershipMenu = new JPopupMenu();
    390         membershipMenu.add(addRelationToSelectionAction);
    391         membershipMenu.add(selectRelationAction);
    392         membershipMenu.add(addMembersToSelectionAction);
    393         membershipMenu.add(downloadSelectedIncompleteMembersAction);
    394         membershipMenu.addSeparator();
    395         membershipMenu.add(helpAction);
    396 
     290    }
     291
     292    private void buildMembershipTable() {
    397293        membershipData.setColumnIdentifiers(new String[]{tr("Member Of"),tr("Role"),tr("Position")});
    398294        membershipTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
    399         membershipTable.addMouseListener(new PopupMenuLauncher() {
    400             @Override
    401             public void launch(MouseEvent evt) {
    402                 Point p = evt.getPoint();
    403                 int row = membershipTable.rowAtPoint(p);
    404                 membershipTable.changeSelection(row, 0, false, false);
    405                 int idx[] = membershipTable.getSelectedRows();
    406                 List<Relation> rels =  new ArrayList<Relation>(10);
    407                 if (idx!=null) {
    408                     for (int i: idx) {
    409                         Relation r = (Relation) (membershipData.getValueAt(i, 0));
    410                         rels.add(r);
    411                     }
    412                 }
    413                 selectRelationAction.setRelations(rels);
    414                 addMembersToSelectionAction.setRelations(rels);
    415                 addMembersToSelectionAction.setRelations(rels);
    416                 downloadSelectedIncompleteMembersAction.setRelations(rels);
    417                 membershipMenu.show(membershipTable, p.x, p.y-3);
    418             }
    419         });
    420295
    421296        TableColumnModel mod = membershipTable.getColumnModel();
     
    488363        mod.getColumn(1).setPreferredWidth(40);
    489364        mod.getColumn(0).setPreferredWidth(200);
    490 
    491         // combine both tables and wrap them in a scrollPane
    492         JPanel bothTables = new JPanel();
    493         boolean top = Main.pref.getBoolean("properties.presets.top", true);
    494         bothTables.setLayout(new GridBagLayout());
    495         if(top) {
    496             bothTables.add(presets, GBC.std().fill(GBC.HORIZONTAL).insets(5, 2, 5, 2).anchor(GBC.NORTHWEST));
    497             double epsilon = Double.MIN_VALUE; // need to set a weight or else anchor value is ignored
    498             bothTables.add(pluginHook, GBC.eol().insets(0,1,1,1).anchor(GBC.NORTHEAST).weight(epsilon, epsilon));
    499         }
    500         bothTables.add(selectSth, GBC.eol().fill().insets(10, 10, 10, 10));
    501         bothTables.add(propertyTable.getTableHeader(), GBC.eol().fill(GBC.HORIZONTAL));
    502         bothTables.add(propertyTable, GBC.eol().fill(GBC.BOTH));
    503         bothTables.add(membershipTable.getTableHeader(), GBC.eol().fill(GBC.HORIZONTAL));
    504         bothTables.add(membershipTable, GBC.eol().fill(GBC.BOTH));
    505         if(!top) {
    506             bothTables.add(presets, GBC.eol().fill(GBC.HORIZONTAL).insets(5, 2, 5, 2));
    507         }
     365    }
     366   
     367    /**
     368     * creates the popup menu @field membershipMenu and its launcher on membership table
     369     */
     370    private void setupMembershipMenu() {
     371        // setting up the membership table
     372        membershipMenu = new JPopupMenu();
     373        membershipMenu.add(addRelationToSelectionAction);
     374        membershipMenu.add(selectRelationAction);
     375        membershipMenu.add(addMembersToSelectionAction);
     376        membershipMenu.add(downloadSelectedIncompleteMembersAction);
     377        membershipMenu.addSeparator();
     378        membershipMenu.add(helpAction);
     379
     380        membershipTable.addMouseListener(new PopupMenuLauncher() {
     381            @Override
     382            public void launch(MouseEvent evt) {
     383                Point p = evt.getPoint();
     384                int row = membershipTable.rowAtPoint(p);
     385                int idx[] = membershipTable.getSelectedRows();
     386                // if nothing or one row is selected, select row under mouse instead
     387                if (idx.length<2 && row>-1) {
     388                    membershipTable.changeSelection(row, 0, false, false);
     389                    idx = new int[]{row};
     390                }
     391                List<Relation> rels =  new ArrayList<Relation>(10);
     392                for (int i: idx) {
     393                    Relation r = (Relation) (membershipData.getValueAt(i, 0));
     394                    rels.add(r);
     395                }
     396                selectRelationAction.setRelations(rels);
     397                addMembersToSelectionAction.setRelations(rels);
     398                addMembersToSelectionAction.setRelations(rels);
     399                downloadSelectedIncompleteMembersAction.setRelations(rels);
     400                membershipMenu.show(membershipTable, p.x, p.y-3);
     401            }
     402        });
     403    }
     404   
     405    /**
     406     * creates the popup menu @field propertyMenu and its launcher on property table
     407     */
     408    private void setupPropertiesMenu() {
     409        propertyMenu = new JPopupMenu();
     410        propertyMenu.add(pasteValueAction);
     411        propertyMenu.add(copyValueAction);
     412        propertyMenu.add(copyKeyValueAction);
     413        propertyMenu.add(copyAllKeyValueAction);
     414        propertyMenu.addSeparator();
     415        propertyMenu.add(searchActionAny);
     416        propertyMenu.add(searchActionSame);
     417        propertyMenu.addSeparator();
     418        propertyMenu.add(helpAction);
     419        propertyTable.addMouseListener(new PopupMenuLauncher() {
     420            @Override
     421            public void launch(MouseEvent evt) {
     422                Point p = evt.getPoint();
     423                int row = propertyTable.rowAtPoint(p);
     424                if (row > -1) {
     425                    propertyTable.changeSelection(row, 0, false, false);
     426                    propertyMenu.show(propertyTable, p.x, p.y-3);
     427                }
     428            }
     429        });
     430    }
     431   
     432    /**
     433     * Assignas all needed keys like Enter and Spacebar to most important actions
     434     */
     435    private void setupKeyboardShortcuts() {
    508436       
    509         // Open edit dialog whe enter pressed in tables
     437        // ENTER = editAction, open "edit" dialog
    510438        propertyTable.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
    511439                .put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0),"onTableEnter");
     
    515443        membershipTable.getActionMap().put("onTableEnter",editAction);
    516444       
    517         // Open add property dialog when INS is pressed in tables
     445        // INSERT button = addAction, open "add property" dialog
    518446        propertyTable.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
    519447                .put(KeyStroke.getKeyStroke(KeyEvent.VK_INSERT, 0),"onTableInsert");
    520448        propertyTable.getActionMap().put("onTableInsert",addAction);
    521449       
    522         //  unassign some standard shortcuts for JTable to allow upload / download
     450        // unassign some standard shortcuts for JTable to allow upload / download
    523451        InputMapUtils.unassignCtrlShiftUpDown(propertyTable, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
     452        // allow using enter to add tags for all look&feel configurations
     453        InputMapUtils.enableEnter(this.btnAdd);
    524454       
    525         // -- add action and shortcut
    526         this.btnAdd = new SideButton(addAction);
    527         InputMapUtils.enableEnter(this.btnAdd);
    528 
    529         // -- edit action
    530         //
    531         propertyTable.getSelectionModel().addListSelectionListener(editAction);
    532         membershipTable.getSelectionModel().addListSelectionListener(editAction);
    533         this.btnEdit = new SideButton(editAction);
    534 
    535         // -- delete action
    536         //
    537         this.btnDel = new SideButton(deleteAction);
    538         membershipTable.getSelectionModel().addListSelectionListener(deleteAction);
    539         propertyTable.getSelectionModel().addListSelectionListener(deleteAction);
     455        // DEL button = deleteAction
    540456        getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
    541457                KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0),"delete"
    542458                );
    543459        getActionMap().put("delete", deleteAction);
    544 
    545         JScrollPane scrollPane = (JScrollPane) createLayout(bothTables, true, Arrays.asList(new SideButton[] {
    546                 this.btnAdd, this.btnEdit, this.btnDel
    547         }));
    548 
    549         MouseClickWatch mouseClickWatch = new MouseClickWatch();
    550         propertyTable.addMouseListener(mouseClickWatch);
    551         membershipTable.addMouseListener(mouseClickWatch);
    552         scrollPane.addMouseListener(mouseClickWatch);
    553 
    554         selectSth.setPreferredSize(scrollPane.getSize());
    555         presets.setSize(scrollPane.getSize());
    556 
    557         editHelper.loadTagsIfNeeded();
    558         // -- help action
    559         //
     460       
     461        // F1 button = custom help action
    560462        getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
    561463                KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0), "onHelp");
    562464        getActionMap().put("onHelp", helpAction);
     465    }
     466   
     467         /**
     468     * This simply fires up an {@link RelationEditor} for the relation shown; everything else
     469     * is the editor's business.
     470     *
     471     * @param row
     472     */
     473    private void editMembership(int row) {
     474        Relation relation = (Relation)membershipData.getValueAt(row, 0);
     475        Main.map.relationListDialog.selectRelation(relation);
     476        RelationEditor.getEditor(
     477                Main.map.mapView.getEditLayer(),
     478                relation,
     479                ((MemberInfo) membershipData.getValueAt(row, 1)).role).setVisible(true);
     480    }
     481   
     482    private int findRow(TableModel model, Object value) {
     483        for (int i=0; i<model.getRowCount(); i++) {
     484            if (model.getValueAt(i, 0).equals(value))
     485                return i;
     486        }
     487        return -1;
     488    }
     489   
     490    /**
     491     * Update selection status, call @{link #selectionChanged} function.
     492     */
     493    private void updateSelection() {
     494        if (Main.main.getCurrentDataSet() == null) {
     495            selectionChanged(Collections.<OsmPrimitive>emptyList());
     496        } else {
     497            selectionChanged(Main.main.getCurrentDataSet().getSelected());
     498        }
     499    }
     500   
     501   // </editor-fold>
     502
     503    // <editor-fold defaultstate="collapsed" desc="Event listeners methods">
     504   
     505    @Override
     506    public void showNotify() {
     507        DatasetEventManager.getInstance().addDatasetListener(dataChangedAdapter, FireMode.IN_EDT_CONSOLIDATED);
     508        SelectionEventManager.getInstance().addSelectionListener(this, FireMode.IN_EDT_CONSOLIDATED);
     509        MapView.addEditLayerChangeListener(this);
     510        for (JosmAction action : josmActions) {
     511            Main.registerActionShortcut(action);
     512        }
     513        updateSelection();
     514    }
     515
     516    @Override
     517    public void hideNotify() {
     518        DatasetEventManager.getInstance().removeDatasetListener(dataChangedAdapter);
     519        SelectionEventManager.getInstance().removeSelectionListener(this);
     520        MapView.removeEditLayerChangeListener(this);
     521        for (JosmAction action : josmActions) {
     522            Main.unregisterActionShortcut(action);
     523        }
    563524    }
    564525
     
    570531        }
    571532    }
    572 
    573     private int findRow(TableModel model, Object value) {
    574         for (int i=0; i<model.getRowCount(); i++) {
    575             if (model.getValueAt(i, 0).equals(value))
    576                 return i;
    577         }
    578         return -1;
    579     }
    580 
    581     private PresetHandler presetHandler = new PresetHandler() {
    582 
    583         @Override
    584         public void updateTags(List<Tag> tags) {
    585             Command command = TaggingPreset.createCommand(getSelection(), tags);
    586             if (command != null) {
    587                 Main.main.undoRedo.add(command);
    588             }
    589         }
    590 
    591         @Override
    592         public Collection<OsmPrimitive> getSelection() {
    593             if (Main.main == null) return null;
    594             if (Main.main.getCurrentDataSet() == null) return null;
    595 
    596             return Main.main.getCurrentDataSet().getSelected();
    597         }
    598     };
     533   
     534    @Override
     535    public void destroy() {
     536        super.destroy();
     537        for (JosmAction action : josmActions) {
     538            action.destroy();
     539        }
     540        Container parent = pluginHook.getParent();
     541        if (parent != null) {
     542            parent.remove(pluginHook);
     543        }
     544    }
    599545
    600546    @Override
     
    725671        }
    726672    }
    727 
    728     /**
    729      * Update selection status, call @{link #selectionChanged} function.
    730      */
    731     private void updateSelection() {
    732         if (Main.main.getCurrentDataSet() == null) {
    733             selectionChanged(Collections.<OsmPrimitive>emptyList());
    734         } else {
    735             selectionChanged(Main.main.getCurrentDataSet().getSelected());
    736         }
    737     }
    738 
     673   
    739674    /* ---------------------------------------------------------------------------------- */
    740675    /* EditLayerChangeListener                                                            */
     
    753688    }
    754689
     690    // </editor-fold>
     691
     692    // <editor-fold defaultstate="collapsed" desc="Methods that are called by plugins to extend fuctionalty ">
     693    public void addPropertyPopupMenuSeparator() {
     694        propertyMenu.addSeparator();
     695    }
     696
     697    public JMenuItem addPropertyPopupMenuAction(Action a) {
     698        return propertyMenu.add(a);
     699    }
     700
     701    public void addPropertyPopupMenuListener(PopupMenuListener l) {
     702        propertyMenu.addPopupMenuListener(l);
     703    }
     704
     705    public void removePropertyPopupMenuListener(PopupMenuListener l) {
     706        propertyMenu.addPopupMenuListener(l);
     707    }
     708
     709    @SuppressWarnings("unchecked")
     710    public Tag getSelectedProperty() {
     711        int row = propertyTable.getSelectedRow();
     712        if (row == -1) return null;
     713        TreeMap<String, Integer> map = (TreeMap<String, Integer>) propertyData.getValueAt(row, 1);
     714        return new Tag(
     715                propertyData.getValueAt(row, 0).toString(),
     716                map.size() > 1 ? "" : map.keySet().iterator().next());
     717    }
     718
     719    public void addMembershipPopupMenuSeparator() {
     720        membershipMenu.addSeparator();
     721    }
     722
     723    public JMenuItem addMembershipPopupMenuAction(Action a) {
     724        return membershipMenu.add(a);
     725    }
     726
     727    public void addMembershipPopupMenuListener(PopupMenuListener l) {
     728        membershipMenu.addPopupMenuListener(l);
     729    }
     730
     731    public void removeMembershipPopupMenuListener(PopupMenuListener l) {
     732        membershipMenu.addPopupMenuListener(l);
     733    }
     734
     735    public IRelation getSelectedMembershipRelation() {
     736        int row = membershipTable.getSelectedRow();
     737        return row > -1 ? (IRelation) membershipData.getValueAt(row, 0) : null;
     738    }
     739       
     740    // </editor-fold>
     741   
     742     /**
     743     * Class that watches for mouse clicks
     744     * @author imi
     745     */
     746    public class MouseClickWatch extends MouseAdapter {
     747        @Override public void mouseClicked(MouseEvent e) {
     748            if (e.getClickCount() < 2)
     749            {
     750                // single click, clear selection in other table not clicked in
     751                if (e.getSource() == propertyTable) {
     752                    membershipTable.clearSelection();
     753                } else if (e.getSource() == membershipTable) {
     754                    propertyTable.clearSelection();
     755                }
     756            }
     757            // double click, edit or add property
     758            else if (e.getSource() == propertyTable)
     759            {
     760                int row = propertyTable.rowAtPoint(e.getPoint());
     761                if (row > -1) {
     762                    boolean focusOnKey = (propertyTable.columnAtPoint(e.getPoint()) == 0);
     763                    editHelper.editProperty(row, focusOnKey);
     764                } else {
     765                    editHelper.addProperty();
     766                    btnAdd.requestFocusInWindow();
     767                }
     768            } else if (e.getSource() == membershipTable) {
     769                int row = membershipTable.rowAtPoint(e.getPoint());
     770                if (row > -1) {
     771                    editMembership(row);
     772                }
     773            }
     774            else
     775            {
     776                editHelper.addProperty();
     777                btnAdd.requestFocusInWindow();
     778            }
     779        }
     780        @Override public void mousePressed(MouseEvent e) {
     781            if (e.getSource() == propertyTable) {
     782                membershipTable.clearSelection();
     783            } else if (e.getSource() == membershipTable) {
     784                propertyTable.clearSelection();
     785            }
     786        }
     787
     788    }
     789
     790    static class MemberInfo {
     791        List<RelationMember> role = new ArrayList<RelationMember>();
     792        List<Integer> position = new ArrayList<Integer>();
     793        private String positionString = null;
     794        void add(RelationMember r, Integer p) {
     795            role.add(r);
     796            position.add(p);
     797        }
     798        String getPositionString() {
     799            if (positionString == null) {
     800                Collections.sort(position);
     801                positionString = String.valueOf(position.get(0));
     802                int cnt = 0;
     803                int last = position.get(0);
     804                for (int i = 1; i < position.size(); ++i) {
     805                    int cur = position.get(i);
     806                    if (cur == last + 1) {
     807                        ++cnt;
     808                    } else if (cnt == 0) {
     809                        positionString += "," + String.valueOf(cur);
     810                    } else {
     811                        positionString += "-" + String.valueOf(last);
     812                        positionString += "," + String.valueOf(cur);
     813                        cnt = 0;
     814                    }
     815                    last = cur;
     816                }
     817                if (cnt >= 1) {
     818                    positionString += "-" + String.valueOf(last);
     819                }
     820            }
     821            if (positionString.length() > 20) {
     822                positionString = positionString.substring(0, 17) + "...";
     823            }
     824            return positionString;
     825        }
     826    }
     827
     828    /**
     829     * Class that allows fast creation of read-only table model with String columns
     830     */
     831    public static class ReadOnlyTableModel extends DefaultTableModel {
     832        @Override public boolean isCellEditable(int row, int column) {
     833            return false;
     834        }
     835        @Override public Class<?> getColumnClass(int columnIndex) {
     836            return String.class;
     837        }
     838    };
     839   
    755840    /**
    756841     * Action handling delete button press in properties dialog.
     
    839924                deleteProperties(rows);
    840925            } else if (membershipTable.getSelectedRowCount() > 0) {
    841                 int row = membershipTable.getSelectedRow();
    842                 deleteFromRelation(row);
     926                int[] rows = membershipTable.getSelectedRows();
     927                // delete from last relation to convserve row numbers in the table
     928                for (int i=rows.length-1; i>=0; i--) {
     929                    deleteFromRelation(rows[i]);
     930                }
    843931            }
    844932        }
     
    848936            setEnabled(
    849937                    (propertyTable != null && propertyTable.getSelectedRowCount() >= 1)
    850                     || (membershipTable != null && membershipTable.getSelectedRowCount() == 1)
     938                    || (membershipTable != null && membershipTable.getSelectedRowCount() > 0)
    851939                    );
    852940        }
     
    9201008        }
    9211009
     1010        @Override
    9221011        public void actionPerformed(ActionEvent e) {
    9231012            try {
     
    9591048
    9601049                Main.worker.execute(new Runnable(){
    961                     public void run() {
     1050                    @Override public void run() {
    9621051                        try {
    9631052                            // find a page that actually exists in the wiki
     
    10071096    }
    10081097
    1009     public void addPropertyPopupMenuSeparator() {
    1010         propertyMenu.addSeparator();
    1011     }
    1012 
    1013     public JMenuItem addPropertyPopupMenuAction(Action a) {
    1014         return propertyMenu.add(a);
    1015     }
    1016 
    1017     public void addPropertyPopupMenuListener(PopupMenuListener l) {
    1018         propertyMenu.addPopupMenuListener(l);
    1019     }
    1020 
    1021     public void removePropertyPopupMenuListener(PopupMenuListener l) {
    1022         propertyMenu.addPopupMenuListener(l);
    1023     }
    1024 
    1025     @SuppressWarnings("unchecked")
    1026     public Tag getSelectedProperty() {
    1027         int row = propertyTable.getSelectedRow();
    1028         if (row == -1) return null;
    1029         TreeMap<String, Integer> map = (TreeMap<String, Integer>) propertyData.getValueAt(row, 1);
    1030         return new Tag(
    1031                 propertyData.getValueAt(row, 0).toString(),
    1032                 map.size() > 1 ? "" : map.keySet().iterator().next());
    1033     }
    1034 
    1035     public void addMembershipPopupMenuSeparator() {
    1036         membershipMenu.addSeparator();
    1037     }
    1038 
    1039     public JMenuItem addMembershipPopupMenuAction(Action a) {
    1040         return membershipMenu.add(a);
    1041     }
    1042 
    1043     public void addMembershipPopupMenuListener(PopupMenuListener l) {
    1044         membershipMenu.addPopupMenuListener(l);
    1045     }
    1046 
    1047     public void removeMembershipPopupMenuListener(PopupMenuListener l) {
    1048         membershipMenu.addPopupMenuListener(l);
    1049     }
    1050 
    1051     public IRelation getSelectedMembershipRelation() {
    1052         int row = membershipTable.getSelectedRow();
    1053         return row > -1 ? (IRelation) membershipData.getValueAt(row, 0) : null;
    1054     }
    1055 
    10561098    class PasteValueAction extends AbstractAction {
    10571099        public PasteValueAction() {
     
    11551197        }
    11561198
     1199        @Override
    11571200        public void actionPerformed(ActionEvent e) {
    11581201            if (propertyTable.getSelectedRowCount() != 1)
     
    11891232        }
    11901233    }
    1191 
    1192     @Override
    1193     public void destroy() {
    1194         super.destroy();
    1195         for (JosmAction action : josmActions) {
    1196             action.destroy();
    1197         }
    1198         Container parent = pluginHook.getParent();
    1199         if (parent != null) {
    1200             parent.remove(pluginHook);
    1201         }
    1202     }
    12031234}
Note: See TracChangeset for help on using the changeset viewer.