/******************************************************************************
* Copyright: GPL v3 *
* *
* This program 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. *
* *
* This program 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 dba.gui.FDWizard;
import dba.gui.newRelation.auxClasses.MultiListSelectionModel;
import dba.utils.GetIcons;
import dba.utils.Localization;
import dba.utils.constants;
import dbaCore.data.Attribute;
import dbaCore.data.FunctionalDependency;
import dbaCore.data.RelationSchema;
import net.miginfocom.swing.MigLayout;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
/**
* Frame for the New FD Wizard
*
* @author Andreas Freitag
*/
public class FDWizard extends JDialog implements constants {
/**
*
*/
private static final long serialVersionUID = 5047143456941921933L;
private JPanel contentPane;
private RelationSchema relation;
private DefaultListModel<Attribute> lstMSource;
private DefaultListModel<Attribute> lstMTarget;
private JList<Attribute> listSource;
private JList<Attribute> listTarget;
private JButton btnFinish;
private boolean relationChanged;
private Localization locale;
/**
* Constructor to create the frame.
*
* @param rel Relation where the FD will be stored
* @param functionalDependency FD which will be edited (null if new FD will be created)
*/
public FDWizard(RelationSchema rel, FunctionalDependency functionalDependency) {
super();
locale = Localization.getInstance();
FunctionalDependency fd = functionalDependency;
relationChanged = false;
if (fd == null) {
this.setTitle(locale.getString("WIZ_FDNewTitle"));
fd = new FunctionalDependency();
} else {
this.setTitle(locale.getString("WIZ_FDEditTitle"));
}
GetIcons getIcons = GetIcons.getInstance();
ImageIcon iconFdArrow = getIcons.getFdArrow();
ImageIcon iconFinish = getIcons.getButtonFinish();
ImageIcon iconCancel = getIcons.getButtonCancel();
ImageIcon iconFrame = getIcons.getIconFDWizardFrame();
setIconImage(iconFrame.getImage());
setModal(true);
contentPane = new JPanel();
JPanel pnlMain = new JPanel(new MigLayout("wrap 3", "[fill, grow][grow,fill,32:32:32][fill, grow]"));
// contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
contentPane.setLayout(new BorderLayout());
contentPane.add(pnlMain, BorderLayout.CENTER);
setSize(600, 250);
setMinimumSize(new Dimension(480, 250));
lstMSource = new DefaultListModel<>();
lstMTarget = new DefaultListModel<>();
listSource = new JList<>(lstMSource);
listSource.setVisibleRowCount(100);
listTarget = new JList<>(lstMTarget);
listTarget.setVisibleRowCount(100);
JScrollPane spSource = new JScrollPane(listSource);
JScrollPane spTarget = new JScrollPane(listTarget);
btnFinish = new JButton(locale.getString("Finish"), iconFinish);
JButton btnCancel = new JButton(locale.getString("Cancel"), iconCancel);
relation = rel;
// Label FDs
JLabel lblFd = new JLabel(locale.getString("FunctionalDependency"));
pnlMain.add(lblFd, "spanx");
// Label Source
JLabel lblSource = new JLabel(locale.getString("WIZ_FdSource"));
pnlMain.add(lblSource, "growx");
// Label Target
JLabel lblTarget = new JLabel(locale.getString("WIZ_FdTarget"));
pnlMain.add(lblTarget, "growx, cell 2 1");
// List Source
listSource.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent arg0) {
setSelectableElements(listSource, listTarget);
checkForButton();
}
});
listSource.setSelectionModel(new MultiListSelectionModel());
pnlMain.add(spSource, "grow, spany");
// Label FD Arrow
JLabel label = new JLabel(iconFdArrow);
pnlMain.add(label, "grow, spany");
// List Target
listTarget.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent arg0) {
setSelectableElements(listTarget, listSource);
checkForButton();
}
});
listTarget.setSelectionModel(new MultiListSelectionModel());
pnlMain.add(spTarget, "grow, spany");
updateAttrLists();
selectSourceTarget(fd);
// Buttons
JPanel pnlButtons = new JPanel(new GridLayout(1, 4));
btnCancel.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
dispose();
}
});
pnlButtons.add(btnCancel);
pnlButtons.add(new JLabel(""));
pnlButtons.add(new JLabel(""));
btnFinish.setEnabled(false);
btnFinish.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
FunctionalDependency fd = new FunctionalDependency(getSourceAttributes(), getTargetAttributes());
for (FunctionalDependency functionalDependency : relation.getFunctionalDependencies()) {
if (fd.equals(functionalDependency)) {
JOptionPane.showMessageDialog(contentPane, locale.getString("WIZ_FDAlreadyExistingMsg"));
return;
}
}
relation.addFunctionalDependency(fd);
relationChanged = true;
dispose();
}
});
pnlButtons.add(btnFinish);
contentPane.add(pnlButtons, BorderLayout.SOUTH);
setLocationRelativeTo(null);
}
private void setSelectableElements(JList<Attribute> list, JList<Attribute> otherList) {
for (int i : otherList.getSelectedIndices()) {
for (int j : list.getSelectedIndices()) {
if (i == j) {
list.removeSelectionInterval(j, j);
// TODO: Change color to grey if item is already selected in
// other list!!!
}
}
}
}
/**
* Method to update the JLists containing the Sources and Targets
*/
private void updateAttrLists() {
lstMSource.clear();
lstMTarget.clear();
for (Attribute attr : relation.getAttributes()) {
lstMSource.addElement(attr);
lstMTarget.addElement(attr);
}
}
private void checkForButton() {
if (listSource.getSelectedIndices().length != 0 && listTarget.getSelectedIndices().length != 0) {
btnFinish.setEnabled(true);
} else {
btnFinish.setEnabled(false);
}
}
public boolean getRelationChanged() {
return relationChanged;
}
/**
* Getter for the SourceAttributes
*
* @return ArrayList with all SourceAttributes
*/
private ArrayList<Attribute> getSourceAttributes() {
ArrayList<Attribute> sourceAttributes = new ArrayList<>();
for (Attribute attr : listSource.getSelectedValuesList()) {
sourceAttributes.add(attr);
}
return sourceAttributes;
}
/**
* Getter for the TargetAttributes
*
* @return ArrayList with all TargetAttributes
*/
private ArrayList<Attribute> getTargetAttributes() {
ArrayList<Attribute> targetAttributes = new ArrayList<>();
for (Attribute attr : listTarget.getSelectedValuesList()) {
targetAttributes.add(attr);
}
return targetAttributes;
}
private void selectSourceTarget(FunctionalDependency fd) {
int[] sources = new int[fd.getSourceAttributes().size()];
int[] targets = new int[fd.getTargetAttributes().size()];
int i = 0;
for (Attribute a : relation.getAttributes()) {
if (fd.getSourceAttributes().contains(a)) {
sources[i++] = relation.getAttributes().indexOf(a);
}
}
i = 0;
for (Attribute a : fd.getTargetAttributes()) {
if (fd.getTargetAttributes().contains(a)) {
targets[i++] = relation.getAttributes().indexOf(a);
}
}
listSource.setSelectedIndices(sources);
listTarget.setSelectedIndices(targets);
}
}