ca.sqlpower.matchmaker.swingui.TranslateWordsEditor.java Source code

Java tutorial

Introduction

Here is the source code for ca.sqlpower.matchmaker.swingui.TranslateWordsEditor.java

Source

/*
 * Copyright (c) 2008, SQL Power Group Inc.
 *
 * This file is part of DQguru
 *
 * DQguru is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * DQguru is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>. 
 */

package ca.sqlpower.matchmaker.swingui;

import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.beans.PropertyChangeEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.tree.TreePath;

import org.apache.log4j.Logger;

import ca.sqlpower.matchmaker.MatchMakerTranslateGroup;
import ca.sqlpower.matchmaker.MatchMakerTranslateWord;
import ca.sqlpower.matchmaker.undo.AbstractUndoableEditorPane;
import ca.sqlpower.matchmaker.util.EditableJTable;
import ca.sqlpower.object.ObjectDependentException;
import ca.sqlpower.swingui.SPSUtils;
import ca.sqlpower.validation.Status;
import ca.sqlpower.validation.ValidateResult;
import ca.sqlpower.validation.swingui.FormValidationHandler;
import ca.sqlpower.validation.swingui.StatusComponent;

import com.jgoodies.forms.builder.ButtonBarBuilder;
import com.jgoodies.forms.builder.ButtonStackBuilder;
import com.jgoodies.forms.builder.PanelBuilder;
import com.jgoodies.forms.debug.FormDebugPanel;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;

/**
 * An editor pane that allows the user to add/remove/move 
 * translate word pares
 */
public class TranslateWordsEditor extends AbstractUndoableEditorPane<MatchMakerTranslateGroup> {

    private JScrollPane translateWordsScrollPane;
    private JTable translateWordsTable;
    private final JTextField from = new JTextField();
    private final JTextField to = new JTextField();
    private final JTextField groupName = new JTextField();

    private final FormValidationHandler handler;
    private final StatusComponent status = new StatusComponent();

    private static final Logger logger = Logger.getLogger(TranslateWordsEditor.class);

    public TranslateWordsEditor(MatchMakerSwingSession swingSession, MatchMakerTranslateGroup group) {
        super(swingSession, group);

        List<Action> groupActions = new ArrayList<Action>();
        groupActions.add(saveGroupAction);
        handler = new FormValidationHandler(status, groupActions);

        setupTable();
        buildUI();
        addListeners();
    }

    private void buildUI() {

        //This created the layout for the internal panel at the top wit
        //the lables and the text fields

        String txt = "fill:min(pref;" + (new JTextField().getMinimumSize().width) + "px):grow";
        FormLayout layout = new FormLayout(
                "4dlu,pref,4dlu," + txt + ",4dlu,pref,4dlu," + txt + ",4dlu,pref,4dlu,pref,4dlu", // columns
                "4dlu,pref,4dlu,pref,4dlu,pref,4dlu"); // rows
        //    1     2    3    4    5    6    7 

        PanelBuilder internalPB;
        JPanel internalP = logger.isDebugEnabled() ? new FormDebugPanel(layout) : new JPanel(layout);

        internalPB = new PanelBuilder(layout, internalP);
        CellConstraints cc = new CellConstraints();

        int row = 2;
        internalPB.add(status, cc.xy(4, row));

        row += 2;
        internalPB.add(new JLabel("Group Name:"), cc.xy(2, row, "r,t"));
        setGroupName();
        internalPB.add(groupName, cc.xy(4, row, "f,f"));

        row += 2;
        internalPB.add(new JLabel("From:"), cc.xy(2, row, "r,t"));
        internalPB.add(from, cc.xy(4, row, "f,f"));

        internalPB.add(new JLabel("To:"), cc.xy(6, row, "r,t"));
        internalPB.add(to, cc.xy(8, row, "f,f"));
        internalPB.add(new JButton(createWordsAction), cc.xy(10, row, "l,t"));

        //The layout for the external frame that houses the table and the button bars
        FormLayout bbLayout = new FormLayout(
                "4dlu,pref,50dlu,fill:min(pref;" + (new JComboBox().getMinimumSize().width)
                        + "px):grow, 4dlu,pref,4dlu", // columns
                "4dlu,pref,4dlu,fill:40dlu:grow,4dlu,pref,4dlu,pref,4dlu"); // rows
        //    1     2    3    4    5    6    7     8   9   

        PanelBuilder externalPB;
        JPanel externalP = logger.isDebugEnabled() ? new FormDebugPanel(bbLayout) : new JPanel(bbLayout);

        externalPB = new PanelBuilder(bbLayout, externalP);
        CellConstraints bbcc = new CellConstraints();

        row = 4;
        translateWordsScrollPane = new JScrollPane(translateWordsTable);
        externalPB.add(translateWordsScrollPane, bbcc.xy(4, row, "f,f"));

        ButtonStackBuilder bsb = new ButtonStackBuilder();
        bsb.addGridded(new JButton(moveTopAction));
        bsb.addRelatedGap();
        bsb.addGridded(new JButton(moveUpAction));
        bsb.addRelatedGap();
        bsb.addGridded(new JButton(moveDownAction));
        bsb.addRelatedGap();
        bsb.addGridded(new JButton(moveBottomAction));
        externalPB.add(bsb.getPanel(), bbcc.xy(6, row, "c,c"));

        row += 2;
        ButtonBarBuilder bbb = new ButtonBarBuilder();
        //new actions for delete and save should be extracted and be put into its own file.
        bbb.addGridded(new JButton(deleteWordsAction));
        bbb.addRelatedGap();
        bbb.addGridded(new JButton(saveGroupAction));

        externalPB.add(bbb.getPanel(), bbcc.xy(4, row, "c,c"));

        externalPB.add(internalPB.getPanel(), cc.xyw(2, 2, 4, "f,f"));

        MMODuplicateValidator mmoValidator = new MMODuplicateValidator(
                swingSession.getRootNode().getTranslateGroupParent(), null, "translate group name", 35, mmo);
        handler.addValidateObject(groupName, mmoValidator);
        TranslateWordValidator wordValidator = new TranslateWordValidator(translateWordsTable);
        handler.addValidateObject(translateWordsTable, wordValidator);

        panel = externalPB.getPanel();
    }

    private void setupTable() {
        translateWordsTable = new EditableJTable();
        translateWordsTable.setName("Translate Words");
        TranslateWordsTableModel tm = new TranslateWordsTableModel(mmo);
        translateWordsTable.setModel(tm);
        translateWordsTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
            public void valueChanged(ListSelectionEvent e) {
                if (e.getValueIsAdjusting())
                    return;
                int row = translateWordsTable.getSelectedRow();
                if (row >= 0) {
                    MatchMakerTranslateWord translateWord = mmo.getChildren().get(row);
                    MatchMakerTreeModel treeModel = (MatchMakerTreeModel) swingSession.getTree().getModel();
                    TreePath menuPath = treeModel.getPathForNode(translateWord);
                    swingSession.getTree().setSelectionPath(menuPath);
                    logger.debug("tree selection path is " + swingSession.getTree().getSelectionPath());
                }
            }
        });
    }

    private void addListeners() {
        groupName.addKeyListener(new KeyListener() {
            public void keyPressed(KeyEvent e) {
            }

            public void keyReleased(KeyEvent e) {
                mmo.setName(groupName.getText());
            }

            public void keyTyped(KeyEvent e) {
            }
        });
    }

    public boolean applyChanges() {
        ValidateResult result = handler.getWorstValidationStatus();
        if (result.getStatus() == Status.FAIL) {
            JOptionPane.showMessageDialog(swingSession.getFrame(),
                    "You have to fix the error before you can save the translation group", "Save",
                    JOptionPane.ERROR_MESSAGE);
            return false;
        }

        if (mmo.getParent() == null) {
            // add the new node to the parent
            swingSession.getTranslations().addChild(mmo);
        }

        return super.applyChanges();
    }

    public boolean hasUnsavedChanges() {
        if (mmo.getParent() == null) {
            return true;
        }
        return super.hasUnsavedChanges();
    }

    /**
     * By giving it the location of a certain column in the table, it scrolls through the  
     * translateTable to make sure that the column is visible.
     * 
     * @param index - the index location of the column you want to focus on in the translateTable
     */
    private void scrollToSelected(int index) {
        Rectangle cellRect = translateWordsTable.getCellRect(index, 0, false);
        if (!translateWordsTable.getVisibleRect().getBounds().contains(cellRect)) {
            translateWordsTable.scrollRectToVisible(cellRect);
        }
    }

    Action createWordsAction = new AbstractAction("Create Translation") {

        public void actionPerformed(ActionEvent e) {
            MatchMakerTranslateWord word = new MatchMakerTranslateWord();
            word.setFrom(from.getText());
            word.setTo(to.getText());
            mmo.addChild(word);
            translateWordsTable.scrollRectToVisible(
                    translateWordsTable.getCellRect(mmo.getChildren().size() - 1, 0, true).getBounds());
            from.setText("");
            to.setText("");
            from.requestFocus();
        }

    };

    Action deleteWordsAction = new AbstractAction("Delete Selected Translations") {

        public void actionPerformed(ActionEvent e) {
            ArrayList<Integer> selectedIndeces = new ArrayList<Integer>();
            for (int selectedRowIndex : translateWordsTable.getSelectedRows()) {
                selectedIndeces.add(new Integer(selectedRowIndex));
            }
            for (int i = selectedIndeces.size() - 1; i >= 0; i--) {
                try {
                    mmo.removeChild(mmo.getChildren().get((int) selectedIndeces.get(i)));
                } catch (ObjectDependentException ex) {
                    throw new RuntimeException(ex);
                }
            }
        }
    };

    Action saveGroupAction = new AbstractAction("Save Group") {

        public void actionPerformed(ActionEvent e) {
            applyChanges();
        }

    };

    Action moveUpAction = new AbstractAction("", SPSUtils.createIcon("chevrons_up1", "Move Up")) {
        public void actionPerformed(ActionEvent e) {
            final int index = translateWordsTable.getSelectedRow();
            if (index >= 0 && index < translateWordsTable.getRowCount()) {
                if (translateWordsTable.getSelectedRowCount() == 1 && index > 0) {
                    mmo.moveChild(index, index - 1, MatchMakerTranslateWord.class);
                    translateWordsTable.setRowSelectionInterval(index - 1, index - 1);
                    scrollToSelected(index - 1);
                }
            }
        }
    };

    Action moveDownAction = new AbstractAction("", SPSUtils.createIcon("chevrons_down1", "Move Down")) {
        public void actionPerformed(ActionEvent e) {
            final int index = translateWordsTable.getSelectedRow();
            if (index >= 0 && index < translateWordsTable.getRowCount()) {
                if (translateWordsTable.getSelectedRowCount() == 1
                        && index < (translateWordsTable.getRowCount() - 1)) {
                    mmo.moveChild(index, index + 1, MatchMakerTranslateWord.class);
                    translateWordsTable.setRowSelectionInterval(index + 1, index + 1);
                    scrollToSelected(index + 1);
                }
            }
        }
    };

    Action moveTopAction = new AbstractAction("", SPSUtils.createIcon("chevrons_up2", "Move To Top")) {
        public void actionPerformed(ActionEvent e) {
            final int index = translateWordsTable.getSelectedRow();
            if (index >= 0 && index < translateWordsTable.getRowCount()) {
                if (translateWordsTable.getSelectedRowCount() == 1 && index > 0) {
                    mmo.moveChild(index, 0, MatchMakerTranslateWord.class);
                    translateWordsTable.setRowSelectionInterval(0, 0);
                    scrollToSelected(0);
                }
            }
        }
    };

    Action moveBottomAction = new AbstractAction("", SPSUtils.createIcon("chevrons_down2", "Move To Bottom")) {
        public void actionPerformed(ActionEvent e) {
            final int index = translateWordsTable.getSelectedRow();
            if (index >= 0 && index < translateWordsTable.getRowCount()) {
                if (translateWordsTable.getSelectedRowCount() == 1
                        && index < (translateWordsTable.getRowCount() - 1)) {
                    mmo.moveChild(index, mmo.getChildren(MatchMakerTranslateWord.class).size() - 1,
                            MatchMakerTranslateWord.class);
                    translateWordsTable.setRowSelectionInterval(mmo.getChildren().size() - 1,
                            mmo.getChildren().size() - 1);
                    scrollToSelected(mmo.getChildren().size() - 1);
                }
            }
        }
    };

    /**
     * @return Returns the MatchMakerTranslateGroup that this editor pane is editing
     */
    public MatchMakerTranslateGroup getGroup() {
        return mmo;
    }

    /**
     * Sets the selected row for the table.
     * @param selectedWord The word to be selected.
     */
    public void setSelectedWord(MatchMakerTranslateWord selectedWord) {
        if (selectedWord != null) {
            int selected = mmo.getChildren().indexOf(selectedWord);
            if (selected >= 0 && selected < translateWordsTable.getRowCount()) {
                translateWordsTable.setRowSelectionInterval(selected, selected);
            }
        }
    }

    @Override
    public void undoEventFired(PropertyChangeEvent evt) {
        groupName.setText(mmo.getName());
    }

    public void setGroupName() {
        List<String> names = new ArrayList<String>();
        for (MatchMakerTranslateGroup tg : swingSession.getRootNode().getTranslateGroupParent()
                .getTranslateGroups()) {
            names.add(tg.getName());
        }
        if (names.contains(mmo.getName())) {
            int i = 1;
            while (names.contains(mmo.getName() + i)) {
                i++;
            }
            mmo.setName(mmo.getName() + i);
        }
        groupName.setText(mmo.getName());
    }
}