Changeset 10113 in josm for trunk


Ignore:
Timestamp:
2016-04-06T23:06:38+02:00 (9 years ago)
Author:
Don-vip
Message:

refactor relation editor to allow unit tests in headless mode

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditor.java

    r10089 r10113  
    1111import java.awt.GridBagConstraints;
    1212import java.awt.GridBagLayout;
     13import java.awt.Window;
    1314import java.awt.event.ActionEvent;
    1415import java.awt.event.FocusAdapter;
     
    3435import javax.swing.JComponent;
    3536import javax.swing.JLabel;
    36 import javax.swing.JMenu;
    3737import javax.swing.JMenuItem;
    3838import javax.swing.JOptionPane;
    3939import javax.swing.JPanel;
     40import javax.swing.JRootPane;
    4041import javax.swing.JScrollPane;
    4142import javax.swing.JSplitPane;
    4243import javax.swing.JTabbedPane;
     44import javax.swing.JTable;
    4345import javax.swing.JToolBar;
    4446import javax.swing.KeyStroke;
     
    111113
    112114    /** the member table and its model */
    113     private MemberTable memberTable;
     115    private final MemberTable memberTable;
    114116    private final MemberTableModel memberTableModel;
    115117
    116118    /** the selection table and its model */
    117     private SelectionTable selectionTable;
     119    private final SelectionTable selectionTable;
    118120    private final SelectionTableModel selectionTableModel;
    119121
    120     private AutoCompletingTextField tfRole;
     122    private final AutoCompletingTextField tfRole;
    121123
    122124    /**
     
    125127    private JMenuItem windowMenuItem;
    126128    /**
    127      * Button for performing the {@link org.openstreetmap.josm.gui.dialogs.relation.actions.SortBelowAction}.
    128      */
    129     private JButton sortBelowButton;
     129     * The toolbar with the buttons on the left
     130     */
     131    private final LeftButtonToolbar leftButtonToolbar;
    130132    /**
    131133     * Action for performing the {@link RefreshAction}
    132134     */
    133     private RefreshAction refreshAction;
     135    private final RefreshAction refreshAction;
    134136    /**
    135137     * Action for performing the {@link ApplyAction}
    136138     */
    137     private ApplyAction applyAction;
     139    private final ApplyAction applyAction;
     140    /**
     141     * Action for performing the {@link DuplicateRelationAction}
     142     */
     143    private final DuplicateRelationAction duplicateAction;
     144    /**
     145     * Action for performing the {@link DeleteCurrentRelationAction}
     146     */
     147    private final DeleteCurrentRelationAction deleteAction;
     148    /**
     149     * Action for performing the {@link OKAction}
     150     */
     151    private final OKAction okAction;
    138152    /**
    139153     * Action for performing the {@link CancelAction}
    140154     */
    141     private CancelAction cancelAction;
     155    private final CancelAction cancelAction;
    142156
    143157    /**
     
    184198        tagEditorPanel.getModel().ensureOneTag();
    185199
    186         JSplitPane pane = buildSplitPane();
     200        // setting up the member table
     201        memberTable = new MemberTable(getLayer(), getRelation(), memberTableModel);
     202        memberTable.addMouseListener(new MemberTableDblClickAdapter());
     203        memberTableModel.addMemberModelListener(memberTable);
     204
     205        MemberRoleCellEditor ce = (MemberRoleCellEditor) memberTable.getColumnModel().getColumn(0).getCellEditor();
     206        selectionTable = new SelectionTable(selectionTableModel, memberTableModel);
     207        selectionTable.setRowHeight(ce.getEditor().getPreferredSize().height);
     208
     209        leftButtonToolbar = new LeftButtonToolbar(memberTable, memberTableModel, this);
     210        tfRole = buildRoleTextField(this);
     211
     212        JSplitPane pane = buildSplitPane(
     213                buildTagEditorPanel(tagEditorPanel),
     214                buildMemberEditorPanel(memberTable, memberTableModel, selectionTable, selectionTableModel, this, leftButtonToolbar, tfRole),
     215                this);
    187216        pane.setPreferredSize(new Dimension(100, 100));
    188217
     
    211240        );
    212241
    213         getContentPane().add(buildToolBar(), BorderLayout.NORTH);
     242        refreshAction = new RefreshAction(memberTable, memberTableModel, tagEditorPanel.getModel(), getLayer(), this);
     243        applyAction = new ApplyAction(memberTable, memberTableModel, tagEditorPanel.getModel(), getLayer(), this);
     244        duplicateAction = new DuplicateRelationAction(memberTableModel, tagEditorPanel.getModel(), getLayer());
     245        deleteAction = new DeleteCurrentRelationAction(getLayer(), this);
     246        addPropertyChangeListener(deleteAction);
     247
     248        okAction = new OKAction(memberTable, memberTableModel, tagEditorPanel.getModel(), getLayer(), this, tfRole);
     249        cancelAction = new CancelAction(memberTable, memberTableModel, tagEditorPanel.getModel(), getLayer(), this, tfRole);
     250
     251        getContentPane().add(buildToolBar(refreshAction, applyAction, duplicateAction, deleteAction), BorderLayout.NORTH);
    214252        getContentPane().add(tabbedPane, BorderLayout.CENTER);
    215         getContentPane().add(buildOkCancelButtonPanel(), BorderLayout.SOUTH);
     253        getContentPane().add(buildOkCancelButtonPanel(okAction, cancelAction), BorderLayout.SOUTH);
    216254
    217255        setSize(findMaxDialogSize());
     
    222260                    @Override
    223261                    public void windowOpened(WindowEvent e) {
    224                         cleanSelfReferences();
     262                        cleanSelfReferences(memberTableModel, getRelation());
    225263                    }
    226264
     
    233271        // CHECKSTYLE.OFF: LineLength
    234272        registerCopyPasteAction(tagEditorPanel.getPasteAction(), "PASTE_TAGS",
    235                 Shortcut.registerShortcut("system:pastestyle", tr("Edit: {0}", tr("Paste Tags")), KeyEvent.VK_V, Shortcut.CTRL_SHIFT).getKeyStroke());
     273                Shortcut.registerShortcut("system:pastestyle", tr("Edit: {0}", tr("Paste Tags")), KeyEvent.VK_V, Shortcut.CTRL_SHIFT).getKeyStroke(),
     274                getRootPane(), memberTable, selectionTable);
    236275        // CHECKSTYLE.ON: LineLength
    237276
     
    242281                tfRole.requestFocusInWindow();
    243282            }
    244         }, "PASTE_MEMBERS", Shortcut.getPasteKeyStroke());
     283        }, "PASTE_MEMBERS", Shortcut.getPasteKeyStroke(), getRootPane(), memberTable, selectionTable);
    245284
    246285        registerCopyPasteAction(new CopyMembersAction(memberTableModel, getLayer(), this),
    247                 "COPY_MEMBERS", Shortcut.getCopyKeyStroke());
     286                "COPY_MEMBERS", Shortcut.getCopyKeyStroke(), getRootPane(), memberTable, selectionTable);
    248287
    249288        tagEditorPanel.setNextFocusComponent(memberTable);
     
    292331    /**
    293332     * Creates the toolbar
     333     * @param refreshAction refresh action
     334     * @param applyAction apply action
     335     * @param duplicateAction duplicate action
     336     * @param deleteAction delete action
    294337     *
    295338     * @return the toolbar
    296339     */
    297     protected JToolBar buildToolBar() {
     340    protected static JToolBar buildToolBar(RefreshAction refreshAction, ApplyAction applyAction,
     341            DuplicateRelationAction duplicateAction, DeleteCurrentRelationAction deleteAction) {
    298342        JToolBar tb = new JToolBar();
    299343        tb.setFloatable(false);
    300         refreshAction = new RefreshAction(memberTable, memberTableModel, tagEditorPanel.getModel(), getLayer(), this);
    301         applyAction = new ApplyAction(memberTable, memberTableModel, tagEditorPanel.getModel(), getLayer(), this);
    302344        tb.add(refreshAction);
    303345        tb.add(applyAction);
    304         tb.add(new DuplicateRelationAction(memberTableModel, tagEditorPanel.getModel(), getLayer()));
    305         DeleteCurrentRelationAction deleteAction = new DeleteCurrentRelationAction(getLayer(), this);
    306         addPropertyChangeListener(deleteAction);
     346        tb.add(duplicateAction);
    307347        tb.add(deleteAction);
    308348        return tb;
     
    311351    /**
    312352     * builds the panel with the OK and the Cancel button
     353     * @param okAction OK action
     354     * @param cancelAction Cancel action
    313355     *
    314356     * @return the panel with the OK and the Cancel button
    315357     */
    316     protected JPanel buildOkCancelButtonPanel() {
     358    protected static JPanel buildOkCancelButtonPanel(OKAction okAction, CancelAction cancelAction) {
    317359        JPanel pnl = new JPanel(new FlowLayout(FlowLayout.CENTER));
    318         pnl.add(new SideButton(new OKAction(memberTable, memberTableModel, tagEditorPanel.getModel(), getLayer(), this, tfRole)));
    319         cancelAction = new CancelAction(memberTable, memberTableModel, tagEditorPanel.getModel(), getLayer(), this, tfRole);
     360        pnl.add(new SideButton(okAction));
    320361        pnl.add(new SideButton(cancelAction));
    321362        pnl.add(new SideButton(new ContextSensitiveHelpAction(ht("/Dialog/RelationEditor"))));
     
    325366    /**
    326367     * builds the panel with the tag editor
     368     * @param tagEditorPanel tag editor panel
    327369     *
    328370     * @return the panel with the tag editor
    329371     */
    330     protected JPanel buildTagEditorPanel() {
     372    protected static JPanel buildTagEditorPanel(TagEditorPanel tagEditorPanel) {
    331373        JPanel pnl = new JPanel(new GridBagLayout());
    332374
     
    353395
    354396    /**
     397     * builds the role text field
     398     * @param re relation editor
     399     * @return the role text field
     400     */
     401    protected static AutoCompletingTextField buildRoleTextField(final IRelationEditor re) {
     402        final AutoCompletingTextField tfRole = new AutoCompletingTextField(10);
     403        tfRole.setToolTipText(tr("Enter a role and apply it to the selected relation members"));
     404        tfRole.addFocusListener(new FocusAdapter() {
     405            @Override
     406            public void focusGained(FocusEvent e) {
     407                tfRole.selectAll();
     408            }
     409        });
     410        tfRole.setAutoCompletionList(new AutoCompletionList());
     411        tfRole.addFocusListener(
     412                new FocusAdapter() {
     413                    @Override
     414                    public void focusGained(FocusEvent e) {
     415                        AutoCompletionList list = tfRole.getAutoCompletionList();
     416                        if (list != null) {
     417                            list.clear();
     418                            re.getLayer().data.getAutoCompletionManager().populateWithMemberRoles(list, re.getRelation());
     419                        }
     420                    }
     421                }
     422        );
     423        tfRole.setText(Main.pref.get("relation.editor.generic.lastrole", ""));
     424        return tfRole;
     425    }
     426
     427    /**
    355428     * builds the panel for the relation member editor
     429     * @param memberTable member table
     430     * @param memberTableModel member table model
     431     * @param selectionTable selection table
     432     * @param selectionTableModel selection table model
     433     * @param re relation editor
     434     * @param leftButtonToolbar left button toolbar
     435     * @param tfRole role text field
    356436     *
    357437     * @return the panel for the relation member editor
    358438     */
    359     protected JPanel buildMemberEditorPanel() {
     439    protected static JPanel buildMemberEditorPanel(final MemberTable memberTable, MemberTableModel memberTableModel,
     440            SelectionTable selectionTable, SelectionTableModel selectionTableModel, IRelationEditor re,
     441            LeftButtonToolbar leftButtonToolbar, final AutoCompletingTextField tfRole) {
    360442        final JPanel pnl = new JPanel(new GridBagLayout());
    361         // setting up the member table
    362         memberTable = new MemberTable(getLayer(), getRelation(), memberTableModel);
    363         memberTable.addMouseListener(new MemberTableDblClickAdapter());
    364         memberTableModel.addMemberModelListener(memberTable);
    365 
    366443        final JScrollPane scrollPane = new JScrollPane(memberTable);
    367444
     
    384461        gc.weightx = 0.0;
    385462        gc.weighty = 1.0;
    386         pnl.add(buildLeftButtonPanel(), gc);
     463        pnl.add(leftButtonToolbar, gc);
    387464
    388465        gc.gridx = 1;
     
    398475        JPanel p3 = new JPanel(new FlowLayout(FlowLayout.LEFT));
    399476        p3.add(new JLabel(tr("Apply Role:")));
    400         tfRole = new AutoCompletingTextField(10);
    401         tfRole.setToolTipText(tr("Enter a role and apply it to the selected relation members"));
    402         tfRole.addFocusListener(new FocusAdapter() {
    403             @Override
    404             public void focusGained(FocusEvent e) {
    405                 tfRole.selectAll();
    406             }
    407         });
    408         tfRole.setAutoCompletionList(new AutoCompletionList());
    409         tfRole.addFocusListener(
    410                 new FocusAdapter() {
    411                     @Override
    412                     public void focusGained(FocusEvent e) {
    413                         AutoCompletionList list = tfRole.getAutoCompletionList();
    414                         if (list != null) {
    415                             list.clear();
    416                             getLayer().data.getAutoCompletionManager().populateWithMemberRoles(list, getRelation());
    417                         }
    418                     }
    419                 }
    420         );
    421         tfRole.setText(Main.pref.get("relation.editor.generic.lastrole", ""));
    422477        p3.add(tfRole);
    423478        SetRoleAction setRoleAction = new SetRoleAction(memberTable, memberTableModel, tfRole);
     
    467522        gc.weightx = 0.0;
    468523        gc.weighty = 1.0;
    469         pnl2.add(buildSelectionControlButtonPanel(), gc);
     524        pnl2.add(buildSelectionControlButtonToolbar(memberTable, memberTableModel, selectionTableModel, re), gc);
    470525
    471526        gc.gridx = 1;
     
    474529        gc.weighty = 1.0;
    475530        gc.fill = GridBagConstraints.BOTH;
    476         pnl2.add(buildSelectionTablePanel(), gc);
     531        pnl2.add(buildSelectionTablePanel(selectionTable), gc);
    477532
    478533        final JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
     
    480535        splitPane.setRightComponent(pnl2);
    481536        splitPane.setOneTouchExpandable(false);
    482         addWindowListener(new WindowAdapter() {
    483             @Override
    484             public void windowOpened(WindowEvent e) {
    485                 // has to be called when the window is visible, otherwise
    486                 // no effect
    487                 splitPane.setDividerLocation(0.6);
    488             }
    489         });
     537        if (re instanceof Window) {
     538            ((Window) re).addWindowListener(new WindowAdapter() {
     539                @Override
     540                public void windowOpened(WindowEvent e) {
     541                    // has to be called when the window is visible, otherwise no effect
     542                    splitPane.setDividerLocation(0.6);
     543                }
     544            });
     545        }
    490546
    491547        JPanel pnl3 = new JPanel(new BorderLayout());
     
    497553    /**
    498554     * builds the panel with the table displaying the currently selected primitives
     555     * @param selectionTable selection table
    499556     *
    500557     * @return panel with current selection
    501558     */
    502     protected JPanel buildSelectionTablePanel() {
     559    protected static JPanel buildSelectionTablePanel(SelectionTable selectionTable) {
    503560        JPanel pnl = new JPanel(new BorderLayout());
    504         MemberRoleCellEditor ce = (MemberRoleCellEditor) memberTable.getColumnModel().getColumn(0).getCellEditor();
    505         selectionTable = new SelectionTable(selectionTableModel, memberTableModel);
    506         selectionTable.setRowHeight(ce.getEditor().getPreferredSize().height);
    507561        pnl.add(new JScrollPane(selectionTable), BorderLayout.CENTER);
    508562        return pnl;
     
    511565    /**
    512566     * builds the {@link JSplitPane} which divides the editor in an upper and a lower half
     567     * @param top top panel
     568     * @param bottom bottom panel
     569     * @param re relation editor
    513570     *
    514571     * @return the split panel
    515572     */
    516     protected JSplitPane buildSplitPane() {
     573    protected static JSplitPane buildSplitPane(JPanel top, JPanel bottom, IRelationEditor re) {
    517574        final JSplitPane pane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
    518         pane.setTopComponent(buildTagEditorPanel());
    519         pane.setBottomComponent(buildMemberEditorPanel());
     575        pane.setTopComponent(top);
     576        pane.setBottomComponent(bottom);
    520577        pane.setOneTouchExpandable(true);
    521         addWindowListener(new WindowAdapter() {
    522             @Override
    523             public void windowOpened(WindowEvent e) {
    524                 // has to be called when the window is visible, otherwise no effect
    525                 pane.setDividerLocation(0.3);
    526             }
    527         });
     578        if (re instanceof Window) {
     579            ((Window) re).addWindowListener(new WindowAdapter() {
     580                @Override
     581                public void windowOpened(WindowEvent e) {
     582                    // has to be called when the window is visible, otherwise no effect
     583                    pane.setDividerLocation(0.3);
     584                }
     585            });
     586        }
    528587        return pane;
    529588    }
    530589
    531590    /**
    532      * build the panel with the buttons on the left
    533      *
    534      * @return left button panel
    535      */
    536     protected JToolBar buildLeftButtonPanel() {
    537         JToolBar tb = new JToolBar();
    538         tb.setOrientation(JToolBar.VERTICAL);
    539         tb.setFloatable(false);
    540 
    541         // -- move up action
    542         MoveUpAction moveUpAction = new MoveUpAction(memberTable, memberTableModel, "moveUp");
    543         memberTableModel.getSelectionModel().addListSelectionListener(moveUpAction);
    544         tb.add(moveUpAction);
    545 
    546         // -- move down action
    547         MoveDownAction moveDownAction = new MoveDownAction(memberTable, memberTableModel, "moveDown");
    548         memberTableModel.getSelectionModel().addListSelectionListener(moveDownAction);
    549         tb.add(moveDownAction);
    550 
    551         tb.addSeparator();
    552 
    553         // -- edit action
    554         EditAction editAction = new EditAction(memberTable, memberTableModel, getLayer());
    555         memberTableModel.getSelectionModel().addListSelectionListener(editAction);
    556         tb.add(editAction);
    557 
    558         // -- delete action
    559         RemoveAction removeSelectedAction = new RemoveAction(memberTable, memberTableModel, "removeSelected");
    560         memberTable.getSelectionModel().addListSelectionListener(removeSelectedAction);
    561         tb.add(removeSelectedAction);
    562 
    563         tb.addSeparator();
    564         // -- sort action
    565         SortAction sortAction = new SortAction(memberTable, memberTableModel);
    566         memberTableModel.addTableModelListener(sortAction);
    567         tb.add(sortAction);
    568         final SortBelowAction sortBelowAction = new SortBelowAction(memberTable, memberTableModel);
    569         memberTableModel.addTableModelListener(sortBelowAction);
    570         memberTableModel.getSelectionModel().addListSelectionListener(sortBelowAction);
    571         sortBelowButton = tb.add(sortBelowAction);
    572 
    573         // -- reverse action
    574         ReverseAction reverseAction = new ReverseAction(memberTable, memberTableModel);
    575         memberTableModel.addTableModelListener(reverseAction);
    576         tb.add(reverseAction);
    577 
    578         tb.addSeparator();
    579 
    580         // -- download action
    581         DownloadIncompleteMembersAction downloadIncompleteMembersAction = new DownloadIncompleteMembersAction(
    582                 memberTable, memberTableModel, "downloadIncomplete", getLayer(), this);
    583         memberTable.getModel().addTableModelListener(downloadIncompleteMembersAction);
    584         tb.add(downloadIncompleteMembersAction);
    585 
    586         // -- download selected action
    587         DownloadSelectedIncompleteMembersAction downloadSelectedIncompleteMembersAction = new DownloadSelectedIncompleteMembersAction(
    588                 memberTable, memberTableModel, null, getLayer(), this);
    589         memberTable.getModel().addTableModelListener(downloadSelectedIncompleteMembersAction);
    590         memberTable.getSelectionModel().addListSelectionListener(downloadSelectedIncompleteMembersAction);
    591         tb.add(downloadSelectedIncompleteMembersAction);
    592 
    593         InputMap inputMap = memberTable.getInputMap(MemberTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
    594         inputMap.put((KeyStroke) removeSelectedAction.getValue(AbstractAction.ACCELERATOR_KEY), "removeSelected");
    595         inputMap.put((KeyStroke) moveUpAction.getValue(AbstractAction.ACCELERATOR_KEY), "moveUp");
    596         inputMap.put((KeyStroke) moveDownAction.getValue(AbstractAction.ACCELERATOR_KEY), "moveDown");
    597         inputMap.put((KeyStroke) downloadIncompleteMembersAction.getValue(AbstractAction.ACCELERATOR_KEY), "downloadIncomplete");
    598 
    599         return tb;
    600     }
    601 
    602     /**
    603      * build the panel with the buttons for adding or removing the current selection
     591     * The toolbar with the buttons on the left
     592     */
     593    static class LeftButtonToolbar extends JToolBar {
     594
     595        /**
     596         * Button for performing the {@link org.openstreetmap.josm.gui.dialogs.relation.actions.SortBelowAction}.
     597         */
     598        final JButton sortBelowButton;
     599
     600        /**
     601         * Constructs a new {@code LeftButtonToolbar}.
     602         * @param memberTable member table
     603         * @param memberTableModel member table model
     604         * @param re relation editor
     605         */
     606        LeftButtonToolbar(MemberTable memberTable, MemberTableModel memberTableModel, IRelationEditor re) {
     607            setOrientation(JToolBar.VERTICAL);
     608            setFloatable(false);
     609
     610            // -- move up action
     611            MoveUpAction moveUpAction = new MoveUpAction(memberTable, memberTableModel, "moveUp");
     612            memberTableModel.getSelectionModel().addListSelectionListener(moveUpAction);
     613            add(moveUpAction);
     614
     615            // -- move down action
     616            MoveDownAction moveDownAction = new MoveDownAction(memberTable, memberTableModel, "moveDown");
     617            memberTableModel.getSelectionModel().addListSelectionListener(moveDownAction);
     618            add(moveDownAction);
     619
     620            addSeparator();
     621
     622            // -- edit action
     623            EditAction editAction = new EditAction(memberTable, memberTableModel, re.getLayer());
     624            memberTableModel.getSelectionModel().addListSelectionListener(editAction);
     625            add(editAction);
     626
     627            // -- delete action
     628            RemoveAction removeSelectedAction = new RemoveAction(memberTable, memberTableModel, "removeSelected");
     629            memberTable.getSelectionModel().addListSelectionListener(removeSelectedAction);
     630            add(removeSelectedAction);
     631
     632            addSeparator();
     633            // -- sort action
     634            SortAction sortAction = new SortAction(memberTable, memberTableModel);
     635            memberTableModel.addTableModelListener(sortAction);
     636            add(sortAction);
     637            final SortBelowAction sortBelowAction = new SortBelowAction(memberTable, memberTableModel);
     638            memberTableModel.addTableModelListener(sortBelowAction);
     639            memberTableModel.getSelectionModel().addListSelectionListener(sortBelowAction);
     640            sortBelowButton = add(sortBelowAction);
     641
     642            // -- reverse action
     643            ReverseAction reverseAction = new ReverseAction(memberTable, memberTableModel);
     644            memberTableModel.addTableModelListener(reverseAction);
     645            add(reverseAction);
     646
     647            addSeparator();
     648
     649            // -- download action
     650            DownloadIncompleteMembersAction downloadIncompleteMembersAction = new DownloadIncompleteMembersAction(
     651                    memberTable, memberTableModel, "downloadIncomplete", re.getLayer(), re);
     652            memberTable.getModel().addTableModelListener(downloadIncompleteMembersAction);
     653            add(downloadIncompleteMembersAction);
     654
     655            // -- download selected action
     656            DownloadSelectedIncompleteMembersAction downloadSelectedIncompleteMembersAction = new DownloadSelectedIncompleteMembersAction(
     657                    memberTable, memberTableModel, null, re.getLayer(), re);
     658            memberTable.getModel().addTableModelListener(downloadSelectedIncompleteMembersAction);
     659            memberTable.getSelectionModel().addListSelectionListener(downloadSelectedIncompleteMembersAction);
     660            add(downloadSelectedIncompleteMembersAction);
     661
     662            InputMap inputMap = memberTable.getInputMap(MemberTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
     663            inputMap.put((KeyStroke) removeSelectedAction.getValue(AbstractAction.ACCELERATOR_KEY), "removeSelected");
     664            inputMap.put((KeyStroke) moveUpAction.getValue(AbstractAction.ACCELERATOR_KEY), "moveUp");
     665            inputMap.put((KeyStroke) moveDownAction.getValue(AbstractAction.ACCELERATOR_KEY), "moveDown");
     666            inputMap.put((KeyStroke) downloadIncompleteMembersAction.getValue(AbstractAction.ACCELERATOR_KEY), "downloadIncomplete");
     667        }
     668    }
     669
     670    /**
     671     * build the toolbar with the buttons for adding or removing the current selection
     672     * @param memberTable member table
     673     * @param memberTableModel member table model
     674     * @param selectionTableModel selection table model
     675     * @param re relation editor
    604676     *
    605677     * @return control buttons panel for selection/members
    606678     */
    607     protected JToolBar buildSelectionControlButtonPanel() {
     679    protected static JToolBar buildSelectionControlButtonToolbar(MemberTable memberTable,
     680            MemberTableModel memberTableModel, SelectionTableModel selectionTableModel, IRelationEditor re) {
    608681        JToolBar tb = new JToolBar(JToolBar.VERTICAL);
    609682        tb.setFloatable(false);
     
    611684        // -- add at start action
    612685        AddSelectedAtStartAction addSelectionAction = new AddSelectedAtStartAction(
    613                 memberTableModel, selectionTableModel, this);
     686                memberTableModel, selectionTableModel, re);
    614687        selectionTableModel.addTableModelListener(addSelectionAction);
    615688        tb.add(addSelectionAction);
     
    617690        // -- add before selected action
    618691        AddSelectedBeforeSelection addSelectedBeforeSelectionAction = new AddSelectedBeforeSelection(
    619                 memberTableModel, selectionTableModel, this);
     692                memberTableModel, selectionTableModel, re);
    620693        selectionTableModel.addTableModelListener(addSelectedBeforeSelectionAction);
    621694        memberTableModel.getSelectionModel().addListSelectionListener(addSelectedBeforeSelectionAction);
     
    624697        // -- add after selected action
    625698        AddSelectedAfterSelection addSelectedAfterSelectionAction = new AddSelectedAfterSelection(
    626                 memberTableModel, selectionTableModel, this);
     699                memberTableModel, selectionTableModel, re);
    627700        selectionTableModel.addTableModelListener(addSelectedAfterSelectionAction);
    628701        memberTableModel.getSelectionModel().addListSelectionListener(addSelectedAfterSelectionAction);
     
    631704        // -- add at end action
    632705        AddSelectedAtEndAction addSelectedAtEndAction = new AddSelectedAtEndAction(
    633                 memberTableModel, selectionTableModel, this);
     706                memberTableModel, selectionTableModel, re);
    634707        selectionTableModel.addTableModelListener(addSelectedAtEndAction);
    635708        tb.add(addSelectedAtEndAction);
     
    639712        // -- select members action
    640713        SelectedMembersForSelectionAction selectMembersForSelectionAction = new SelectedMembersForSelectionAction(
    641                 memberTableModel, selectionTableModel, getLayer());
     714                memberTableModel, selectionTableModel, re.getLayer());
    642715        selectionTableModel.addTableModelListener(selectMembersForSelectionAction);
    643716        memberTableModel.addTableModelListener(selectMembersForSelectionAction);
     
    646719        // -- select action
    647720        SelectPrimitivesForSelectedMembersAction selectAction = new SelectPrimitivesForSelectedMembersAction(
    648                 memberTable, memberTableModel, getLayer());
     721                memberTable, memberTableModel, re.getLayer());
    649722        memberTable.getSelectionModel().addListSelectionListener(selectAction);
    650723        tb.add(selectAction);
     
    653726
    654727        // -- remove selected action
    655         RemoveSelectedAction removeSelectedAction = new RemoveSelectedAction(memberTableModel, selectionTableModel, getLayer());
     728        RemoveSelectedAction removeSelectedAction = new RemoveSelectedAction(memberTableModel, selectionTableModel, re.getLayer());
    656729        selectionTableModel.addTableModelListener(removeSelectedAction);
    657730        tb.add(removeSelectedAction);
     
    672745        super.setVisible(visible);
    673746        if (visible) {
    674             sortBelowButton.setVisible(ExpertToggleAction.isExpert());
     747            leftButtonToolbar.sortBelowButton.setVisible(ExpertToggleAction.isExpert());
    675748            RelationDialogManager.getRelationDialogManager().positionOnScreen(this);
    676749            if (windowMenuItem == null) {
    677                 addToWindowMenu();
     750                windowMenuItem = addToWindowMenu(this, getLayer().getName());
    678751            }
    679752            tagEditorPanel.requestFocusInWindow();
     
    693766    }
    694767
    695     /** adds current relation editor to the windows menu (in the "volatile" group) o*/
    696     protected void addToWindowMenu() {
    697         String name = getRelation() == null ? tr("New Relation") : getRelation().getLocalName();
    698         final String tt = tr("Focus Relation Editor with relation ''{0}'' in layer ''{1}''",
    699                 name, getLayer().getName());
    700         name = tr("Relation Editor: {0}", name == null ? getRelation().getId() : name);
    701         final JMenu wm = Main.main.menu.windowMenu;
    702         final JosmAction focusAction = new JosmAction(name, "dialogs/relationlist", tt, null, false, false) {
     768    /**
     769     * Adds current relation editor to the windows menu (in the "volatile" group)
     770     * @param re relation editor
     771     * @param layerName layer name
     772     * @return created menu item
     773     */
     774    protected static JMenuItem addToWindowMenu(IRelationEditor re, String layerName) {
     775        Relation r = re.getRelation();
     776        String name = r == null ? tr("New Relation") : r.getLocalName();
     777        JosmAction focusAction = new JosmAction(
     778                tr("Relation Editor: {0}", name == null && r != null ? r.getId() : name),
     779                "dialogs/relationlist",
     780                tr("Focus Relation Editor with relation ''{0}'' in layer ''{1}''", name, layerName),
     781                null, false, false) {
    703782            @Override
    704783            public void actionPerformed(ActionEvent e) {
    705                 final RelationEditor r = (RelationEditor) getValue("relationEditor");
    706                 r.setVisible(true);
     784                ((RelationEditor) getValue("relationEditor")).setVisible(true);
    707785            }
    708786        };
    709         focusAction.putValue("relationEditor", this);
    710         windowMenuItem = MainMenu.add(wm, focusAction, MainMenu.WINDOW_MENU_GROUP.VOLATILE);
     787        focusAction.putValue("relationEditor", re);
     788        return MainMenu.add(Main.main.menu.windowMenu, focusAction, MainMenu.WINDOW_MENU_GROUP.VOLATILE);
    711789    }
    712790
     
    714792     * checks whether the current relation has members referring to itself. If so,
    715793     * warns the users and provides an option for removing these members.
    716      *
    717      */
    718     protected void cleanSelfReferences() {
     794     * @param memberTableModel member table model
     795     * @param relation relation
     796     */
     797    protected static void cleanSelfReferences(MemberTableModel memberTableModel, Relation relation) {
    719798        List<OsmPrimitive> toCheck = new ArrayList<>();
    720         toCheck.add(getRelation());
     799        toCheck.add(relation);
    721800        if (memberTableModel.hasMembersReferringTo(toCheck)) {
    722801            int ret = ConditionalOptionPaneUtil.showOptionDialog(
     
    745824    }
    746825
    747     private void registerCopyPasteAction(AbstractAction action, Object actionName, KeyStroke shortcut) {
     826    private static void registerCopyPasteAction(AbstractAction action, Object actionName, KeyStroke shortcut,
     827            JRootPane rootPane, JTable... tables) {
    748828        int mods = shortcut.getModifiers();
    749829        int code = shortcut.getKeyCode();
     
    752832            return;
    753833        }
    754         getRootPane().getActionMap().put(actionName, action);
    755         getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(shortcut, actionName);
     834        rootPane.getActionMap().put(actionName, action);
     835        rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(shortcut, actionName);
    756836        // Assign also to JTables because they have their own Copy&Paste implementation
    757837        // (which is disabled in this case but eats key shortcuts anyway)
    758         memberTable.getInputMap(JComponent.WHEN_FOCUSED).put(shortcut, actionName);
    759         memberTable.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(shortcut, actionName);
    760         memberTable.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(shortcut, actionName);
    761         selectionTable.getInputMap(JComponent.WHEN_FOCUSED).put(shortcut, actionName);
    762         selectionTable.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(shortcut, actionName);
    763         selectionTable.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(shortcut, actionName);
     838        for (JTable table : tables) {
     839            table.getInputMap(JComponent.WHEN_FOCUSED).put(shortcut, actionName);
     840            table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(shortcut, actionName);
     841            table.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(shortcut, actionName);
     842        }
    764843    }
    765844
  • trunk/src/org/openstreetmap/josm/gui/dialogs/relation/IRelationEditor.java

    r9665 r10113  
    33
    44import org.openstreetmap.josm.data.osm.Relation;
     5import org.openstreetmap.josm.gui.layer.OsmDataLayer;
    56
    67/**
     
    4546     */
    4647    void reloadDataFromRelation();
     48
     49    /**
     50     * Replies the {@link OsmDataLayer} in whose context this relation editor is open
     51     *
     52     * @return the {@link OsmDataLayer} in whose context this relation editor is open
     53     */
     54    OsmDataLayer getLayer();
    4755}
  • trunk/src/org/openstreetmap/josm/gui/dialogs/relation/RelationEditor.java

    r9997 r10113  
    149149    }
    150150
    151     /**
    152      * Replies the {@link OsmDataLayer} in whose context this relation editor is open
    153      *
    154      * @return the {@link OsmDataLayer} in whose context this relation editor is open
    155      */
    156     protected final OsmDataLayer getLayer() {
     151    @Override
     152    public final OsmDataLayer getLayer() {
    157153        return layer;
    158154    }
  • trunk/test/unit/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditorTest.java

    r9669 r10113  
    77import java.util.Collections;
    88
     9import javax.swing.JPanel;
     10
    911import org.junit.BeforeClass;
    1012import org.junit.Test;
    1113import org.openstreetmap.josm.JOSMFixture;
     14import org.openstreetmap.josm.data.osm.DataSet;
    1215import org.openstreetmap.josm.data.osm.Node;
    1316import org.openstreetmap.josm.data.osm.OsmPrimitive;
    1417import org.openstreetmap.josm.data.osm.Relation;
    1518import org.openstreetmap.josm.data.osm.Way;
     19import org.openstreetmap.josm.gui.dialogs.relation.GenericRelationEditor.LeftButtonToolbar;
     20import org.openstreetmap.josm.gui.dialogs.relation.actions.ApplyAction;
     21import org.openstreetmap.josm.gui.dialogs.relation.actions.CancelAction;
     22import org.openstreetmap.josm.gui.dialogs.relation.actions.DeleteCurrentRelationAction;
     23import org.openstreetmap.josm.gui.dialogs.relation.actions.DuplicateRelationAction;
     24import org.openstreetmap.josm.gui.dialogs.relation.actions.OKAction;
     25import org.openstreetmap.josm.gui.dialogs.relation.actions.RefreshAction;
     26import org.openstreetmap.josm.gui.layer.OsmDataLayer;
     27import org.openstreetmap.josm.gui.tagging.TagEditorModel;
     28import org.openstreetmap.josm.gui.tagging.TagEditorPanel;
     29import org.openstreetmap.josm.gui.tagging.ac.AutoCompletingTextField;
    1630
    1731/**
     
    2539    @BeforeClass
    2640    public static void setUpBeforeClass() {
    27         JOSMFixture.createUnitTestFixture().init();
     41        JOSMFixture.createUnitTestFixture().init(true);
     42    }
     43
     44    /**
     45     * Returns a new relation editor for unit tests.
     46     * @param orig relation
     47     * @param layer data layer
     48     * @return new relation editor for unit tests
     49     */
     50    public static IRelationEditor newRelationEditor(final Relation orig, final OsmDataLayer layer) {
     51        return new IRelationEditor() {
     52            private Relation r = orig;
     53
     54            @Override
     55            public void setRelation(Relation relation) {
     56                r = relation;
     57            }
     58
     59            @Override
     60            public boolean isDirtyRelation() {
     61                return false;
     62            }
     63
     64            @Override
     65            public Relation getRelationSnapshot() {
     66                return r;
     67            }
     68
     69            @Override
     70            public Relation getRelation() {
     71                return r;
     72            }
     73
     74            @Override
     75            public void reloadDataFromRelation() {
     76                // Do nothing
     77            }
     78
     79            @Override
     80            public OsmDataLayer getLayer() {
     81                return layer;
     82            }
     83        };
    2884    }
    2985
     
    4197    }
    4298
     99    /**
     100     * Unit test of {@code GenericRelationEditor#build*} methods.
     101     */
     102    @Test
     103    public void testBuild() {
     104        DataSet ds = new DataSet();
     105        Relation relation = new Relation(1);
     106        ds.addPrimitive(relation);
     107        OsmDataLayer layer = new OsmDataLayer(ds, "test", null);
     108        IRelationEditor re = newRelationEditor(relation, layer);
     109
     110        MemberTableModel memberTableModel = new MemberTableModel(relation, layer, null);
     111        MemberTable memberTable = new MemberTable(layer, relation, memberTableModel);
     112
     113        SelectionTableModel selectionTableModel = new SelectionTableModel(layer);
     114        SelectionTable selectionTable = new SelectionTable(selectionTableModel, memberTableModel);
     115
     116        LeftButtonToolbar leftButtonToolbar = new LeftButtonToolbar(memberTable, memberTableModel, re);
     117        assertNotNull(leftButtonToolbar.sortBelowButton);
     118
     119        AutoCompletingTextField tfRole = GenericRelationEditor.buildRoleTextField(re);
     120        assertNotNull(tfRole);
     121
     122        TagEditorPanel tagEditorPanel = new TagEditorPanel(relation, null);
     123
     124        JPanel top = GenericRelationEditor.buildTagEditorPanel(tagEditorPanel);
     125        JPanel bottom = GenericRelationEditor.buildMemberEditorPanel(
     126                memberTable, memberTableModel, selectionTable, selectionTableModel, re, leftButtonToolbar, tfRole);
     127        assertNotNull(top);
     128        assertNotNull(bottom);
     129        assertNotNull(GenericRelationEditor.buildSplitPane(top, bottom, re));
     130
     131        TagEditorModel tagModel = tagEditorPanel.getModel();
     132
     133        assertNotNull(GenericRelationEditor.buildOkCancelButtonPanel(
     134                new OKAction(memberTable, memberTableModel, tagModel, layer, re, tfRole),
     135                new CancelAction(memberTable, memberTableModel, tagModel, layer, re, tfRole)));
     136        assertNotNull(GenericRelationEditor.buildSelectionControlButtonToolbar(memberTable, memberTableModel, selectionTableModel, re));
     137        assertNotNull(GenericRelationEditor.buildSelectionTablePanel(selectionTable));
     138
     139        assertNotNull(GenericRelationEditor.buildToolBar(
     140                new RefreshAction(memberTable, memberTableModel, tagModel, layer, re),
     141                new ApplyAction(memberTable, memberTableModel, tagModel, layer, re),
     142                new DuplicateRelationAction(memberTableModel, tagModel, layer),
     143                new DeleteCurrentRelationAction(layer, re)));
     144    }
    43145}
  • trunk/test/unit/org/openstreetmap/josm/gui/dialogs/relation/actions/RelationEditorActionsTest.java

    r9669 r10113  
    77import org.openstreetmap.josm.data.osm.DataSet;
    88import org.openstreetmap.josm.data.osm.Relation;
     9import org.openstreetmap.josm.gui.dialogs.relation.GenericRelationEditorTest;
    910import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
    1011import org.openstreetmap.josm.gui.dialogs.relation.MemberTable;
     
    3637        final Relation orig = new Relation(1);
    3738        ds.addPrimitive(orig);
    38         OsmDataLayer layer = new OsmDataLayer(new DataSet(), "test", null);
     39        final OsmDataLayer layer = new OsmDataLayer(ds, "test", null);
    3940        MemberTableModel memberTableModel = new MemberTableModel(orig, layer, null);
    4041        SelectionTableModel selectionTableModel = new SelectionTableModel(layer);
    4142
    42         IRelationEditor editor = new IRelationEditor() {
    43             private Relation r = orig;
    44 
    45             @Override
    46             public void setRelation(Relation relation) {
    47                 r = relation;
    48             }
    49 
    50             @Override
    51             public boolean isDirtyRelation() {
    52                 return false;
    53             }
    54 
    55             @Override
    56             public Relation getRelationSnapshot() {
    57                 return r;
    58             }
    59 
    60             @Override
    61             public Relation getRelation() {
    62                 return r;
    63             }
    64 
    65             @Override
    66             public void reloadDataFromRelation() {
    67                 // Do nothing
    68             }
    69         };
     43        IRelationEditor editor = GenericRelationEditorTest.newRelationEditor(orig, layer);
    7044
    7145        MemberTable memberTable = new MemberTable(layer, editor.getRelation(), memberTableModel);
Note: See TracChangeset for help on using the changeset viewer.