/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo 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.
*
* OpenFlexo 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 OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openflexo.components.validation;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.BorderFactory;
import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumn;
import org.openflexo.FlexoCst;
import org.openflexo.GeneralPreferences;
import org.openflexo.components.AskParametersDialog;
import org.openflexo.components.ProgressWindow;
import org.openflexo.foundation.DataModification;
import org.openflexo.foundation.FlexoObservable;
import org.openflexo.foundation.GraphicalFlexoObserver;
import org.openflexo.foundation.validation.FixProposal;
import org.openflexo.foundation.validation.ParameteredFixProposal;
import org.openflexo.foundation.validation.ProblemIssue;
import org.openflexo.foundation.validation.Validable;
import org.openflexo.foundation.validation.ValidationFinishedNotification;
import org.openflexo.foundation.validation.ValidationInitNotification;
import org.openflexo.foundation.validation.ValidationIssue;
import org.openflexo.foundation.validation.ValidationModel;
import org.openflexo.foundation.validation.ValidationNotification;
import org.openflexo.foundation.validation.ValidationProgressNotification;
import org.openflexo.foundation.validation.ValidationReport;
import org.openflexo.foundation.validation.ValidationReport.ReportMode;
import org.openflexo.foundation.validation.ValidationRule;
import org.openflexo.foundation.validation.ValidationRuleSet;
import org.openflexo.icon.IconLibrary;
import org.openflexo.localization.FlexoLocalization;
import org.openflexo.view.controller.FlexoController;
/**
* Defines the panel allowing to show and edit a ValidationReport
*
* @author sguerin
*
*/
public class ValidationReportEditor extends JPanel implements GraphicalFlexoObserver {
static final Logger logger = Logger.getLogger(ValidationReportEditor.class.getPackage().getName());
ValidationReport _validationReport;
ValidationIssue _currentIssue;
FixProposal _currentFixProposal;
JTable _validationReportTable;
JList fixProposalList;
private final JLabel _title;
JLabel _subTitle;
private final JButton disableRuleButton;
private final JButton fixButton;
private final JButton checkButton;
private final JButton closeButton;
private final JTextArea _ruleDescription;
JComboBox reportMode;
ConsistencyCheckDialogInterface _consistencyCheckDialog;
private ListSelectionListener issueSelectionListener;
public ValidationReportEditor(ConsistencyCheckDialogInterface consistencyCheckDialog, ValidationReport validationReport) {
super();
setLayout(new BorderLayout());
_consistencyCheckDialog = consistencyCheckDialog;
_validationReport = validationReport;
// _currentIssue = new InformationIssue(null, null);
JPanel titlePanel = new JPanel();
titlePanel.setLayout(new BorderLayout());
_title = new JLabel(_validationReport.getLocalizedTitle(), SwingConstants.CENTER);
_title.setFont(FlexoCst.BIG_FONT);
_title.setForeground(Color.BLACK);
_subTitle = new JLabel(_validationReport.getLocalizedSubTitle(), SwingConstants.CENTER);
_subTitle.setFont(FlexoCst.SMALL_FONT);
_subTitle.setForeground(Color.DARK_GRAY);
titlePanel.add(_title, BorderLayout.CENTER);
titlePanel.add(_subTitle, BorderLayout.SOUTH);
titlePanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
reportMode = new JComboBox(ReportMode.values());
reportMode.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
_validationReport.setMode((ReportMode) reportMode.getSelectedItem());
}
});
reportMode.setRenderer(new DefaultListCellRenderer() {
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
JLabel l = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
l.setText(((ReportMode) value).getLocalizedName());
return l;
}
});
reportMode.setSelectedItem(_validationReport.getMode());
titlePanel.add(reportMode, BorderLayout.EAST);
_validationReportTable = new JTable(_validationReport);
for (int i = 0; i < _validationReport.getColumnCount(); i++) {
TableColumn col = _validationReportTable.getColumnModel().getColumn(i);
col.setPreferredWidth(getValidationReportPreferedColumnSize(i));
if (i == 0) {
col.setResizable(false);
col.setMinWidth(getValidationReportPreferedColumnSize(i));
col.setMaxWidth(getValidationReportPreferedColumnSize(i));
}
}
_validationReportTable.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
if (_currentIssue != null && _currentIssue.getSize() > 0) {
applyFixProposal((FixProposal) _currentIssue.getElementAt(0));
}
}
}
});
_validationReportTable.setDefaultRenderer(ValidationIssue.class, new ValidationReportCellRenderer());
_validationReportTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
_validationReportTable.setMinimumSize(new Dimension(600, 150));
ListSelectionModel rowSM = _validationReportTable.getSelectionModel();
rowSM.addListSelectionListener(issueSelectionListener = new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
// Ignore extra messages.
if (e.getValueIsAdjusting()) {
return;
}
ListSelectionModel lsm = (ListSelectionModel) e.getSource();
if (lsm.isSelectionEmpty()) {
// no rows are selected
setCurrentIssue(null);
} else {
int selectedRow = lsm.getMinSelectionIndex();
ValidationIssue issue = _validationReport.getIssueAt(selectedRow);
setCurrentIssue(issue);
if (_consistencyCheckDialog.getController() instanceof FlexoController) {
_consistencyCheckDialog.getController().selectAndFocusObject(issue.getSelectableObject());
}
ValidationReportEditor.this.grabFocus();
}
}
});
JPanel topPanel = new JPanel();
topPanel.setLayout(new BorderLayout());
topPanel.add(_validationReportTable.getTableHeader(), BorderLayout.NORTH);
topPanel.add(new JScrollPane(_validationReportTable), BorderLayout.CENTER);
topPanel.setPreferredSize(new Dimension(500, 300));
topPanel.setMinimumSize(_validationReportTable.getMinimumSize());
fixProposalList = new JList();
fixProposalList.setCellRenderer(new FixProposalRenderer());
fixProposalList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
fixProposalList.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
// Ignore extra messages.
if (e.getValueIsAdjusting()) {
return;
}
int selectedRow = fixProposalList.getSelectedIndex();
if (selectedRow >= 0 && selectedRow < _currentIssue.getSize()) {
FixProposal proposal = (FixProposal) _currentIssue.getElementAt(selectedRow);
setCurrentFixProposal(proposal);
} else {
setCurrentFixProposal(null);
}
}
});
fixProposalList.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
applyFixProposal(_currentFixProposal);
}
}
});
JScrollPane scrollableFixProposalList = new JScrollPane(fixProposalList);
JPanel bottomPanel = new JPanel();
bottomPanel.setLayout(new BorderLayout());
_ruleDescription = new JTextArea(4, 20);
_ruleDescription.setLineWrap(true);
_ruleDescription.setWrapStyleWord(true);
_ruleDescription.setForeground(Color.DARK_GRAY);
_ruleDescription.setFont(FlexoCst.MEDIUM_FONT);
bottomPanel.add(_ruleDescription, BorderLayout.NORTH);
bottomPanel.add(scrollableFixProposalList, BorderLayout.CENTER);
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, topPanel, bottomPanel);
splitPane.setDividerLocation(0.8);
JPanel controlPanel = new JPanel();
controlPanel.setLayout(new FlowLayout());
disableRuleButton = new JButton();
disableRuleButton.setText(FlexoLocalization.localizedForKey("disableRule", disableRuleButton));
fixButton = new JButton();
fixButton.setText(FlexoLocalization.localizedForKey("fix", fixButton));
checkButton = new JButton();
checkButton.setText(FlexoLocalization.localizedForKey("check_again", checkButton));
checkButton.setEnabled(_validationReport.getRootObject() != null);
closeButton = new JButton();
closeButton.setText(FlexoLocalization.localizedForKey(getCloseButtonName(), closeButton));
closeButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
close();
}
});
checkButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
checkAgain();
}
});
fixButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
applyFixProposal(_currentFixProposal);
}
});
disableRuleButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
disableRule(_currentIssue);
}
});
fixButton.setEnabled(false);
disableRuleButton.setEnabled(false);
// if(ModuleLoader.isDevelopperRelease() || ModuleLoader.isMaintainerRelease())
controlPanel.add(disableRuleButton);
controlPanel.add(fixButton);
controlPanel.add(checkButton);
controlPanel.add(closeButton);
add(titlePanel, BorderLayout.NORTH);
add(splitPane, BorderLayout.CENTER);
add(controlPanel, BorderLayout.SOUTH);
validate();
}
public String getCloseButtonName() {
return "close";
}
public void close() {
_consistencyCheckDialog.hide();
}
public void checkAgain() {
if (_validationReport.getRootObject() != null) {
consistencyCheckWithValidationModel(_validationReport.getRootObject(), _validationReport.getValidationModel());
// if (_validationReport.getRowCount() > 0) {
// setCurrentIssue(_validationReport.getIssueAt(_validationReport.getRowCount() - 1));
// }
}
}
protected void disableRule(ValidationIssue issue) {
issue.getCause().setIsEnabled(!issue.getCause().getIsEnabled());
GeneralPreferences.setValidationRuleEnabled(issue.getCause(), issue.getCause().getIsEnabled());
GeneralPreferences.save();
disableRuleButton.setText(issue.getCause().getIsEnabled() ? FlexoLocalization.localizedForKey("disableRule", disableRuleButton)
: FlexoLocalization.localizedForKey("enableRule", disableRuleButton));
}
protected void applyFixProposal(FixProposal fixProposal) {
if (fixProposal != null) {
if (fixProposal instanceof ParameteredFixProposal) {
/*AskParametersDialog askParams = new AskParametersDialog(FlexoLocalization.localizedForKey("validation_error_fixing"),
fixProposal.getLocalizedMessage(), ((ParameteredFixProposal) fixProposal).getLabels(),
((ParameteredFixProposal) fixProposal).getParams());*/
((ParameteredFixProposal) fixProposal).updateBeforeApply();
AskParametersDialog askParams = AskParametersDialog.createAskParametersDialog(fixProposal.getProject(), null,
FlexoLocalization.localizedForKey("validation_error_fixing"), fixProposal.getLocalizedMessage(),
((ParameteredFixProposal) fixProposal).getParameters());
if (askParams.getStatus() == AskParametersDialog.CANCEL) {
return;
}
} else if (fixProposal.askConfirmation()) {
if (!FlexoController.confirm(FlexoLocalization.localizedForKey("would_you_like_to_delete_this_object"))) {
return;
}
}
if (logger.isLoggable(Level.INFO)) {
logger.info("Applying " + fixProposal.getMessage());
}
fixProposal.apply();
if (_validationReport.getRowCount() > 0) {
setCurrentIssue(_validationReport.getIssueAt(_validationReport.getRowCount() - 1));
} else {
setCurrentIssue(null);
}
_subTitle.setText(_validationReport.getLocalizedSubTitle());
}
}
void setCurrentIssue(ValidationIssue issue) {
_currentIssue = issue;
fixProposalList.setModel(_currentIssue == null ? new DefaultListModel() : _currentIssue);
if (issue instanceof ProblemIssue) {
_ruleDescription.setText(((ProblemIssue) issue).getValidationRule().getLocalizedDescription());
} else {
_ruleDescription.setText("");
}
fixButton.setEnabled(false);
_currentFixProposal = null;
if (_currentIssue != null) {
if (_currentIssue.getSize() > 0) {
fixProposalList.setSelectedIndex(0);
}
disableRuleButton.setEnabled(_currentIssue.getCause() != null);
if (_currentIssue.getCause() != null) {
if (_currentIssue.getCause().getIsEnabled()) {
disableRuleButton.setText(FlexoLocalization.localizedForKey("disableRule", disableRuleButton));
} else {
disableRuleButton.setText(FlexoLocalization.localizedForKey("enableRule", disableRuleButton));
}
}
}
}
void setCurrentFixProposal(FixProposal proposal) {
_currentFixProposal = proposal;
if (proposal != null) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("setCurrentFixProposal " + _currentFixProposal.getMessage());
}
fixButton.setEnabled(true);
} else {
fixButton.setEnabled(false);
}
}
private int getValidationReportPreferedColumnSize(int columnIndex) {
switch (columnIndex) {
case 0:
return 20; // icon
case 1:
return 330; // message
case 2:
return 150; // object
default:
return 50;
}
}
public void setValidationReport(ValidationReport validationReport) {
if (_validationReport.hasCustomLocalizedTitle()) {
validationReport.setLocalizedTitle(_validationReport.getLocalizedTitle());
}
_validationReport = validationReport;
_validationReport.setMode((ReportMode) reportMode.getSelectedItem());
_validationReportTable.getSelectionModel().removeListSelectionListener(issueSelectionListener);
_validationReportTable.setModel(_validationReport);
_validationReportTable.getSelectionModel().addListSelectionListener(issueSelectionListener);
for (int i = 0; i < _validationReport.getColumnCount(); i++) {
TableColumn col = _validationReportTable.getColumnModel().getColumn(i);
col.setPreferredWidth(getValidationReportPreferedColumnSize(i));
if (i == 0) {
col.setResizable(false);
col.setMinWidth(getValidationReportPreferedColumnSize(i));
col.setMaxWidth(getValidationReportPreferedColumnSize(i));
}
}
_title.setText(_validationReport.getLocalizedTitle());
_subTitle.setText(_validationReport.getLocalizedSubTitle());
fixButton.setEnabled(false);
checkButton.setEnabled(_validationReport.getRootObject() != null);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
_consistencyCheckDialog.toFront();
}
});
}
public ValidationReport getValidationReport() {
return _validationReport;
}
public void consistencyCheckWithDefaultValidationModel(Validable objectToValidate) {
consistencyCheckWithValidationModel(objectToValidate, objectToValidate.getDefaultValidationModel());
}
public void consistencyCheckWithValidationModel(Validable objectToValidate, ValidationModel validationModel) {
for (int i = 0; i < validationModel.getSize(); i++) {
ValidationRuleSet ruleSet = validationModel.getElementAt(i);
for (ValidationRule rule : ruleSet.getRules()) {
rule.setIsEnabled(GeneralPreferences.isValidationRuleEnabled(rule));
}
}
validationModel.addObserver(this);
ValidationReport report = objectToValidate.validate(validationModel);
if (report == null) {
report = new ValidationReport(validationModel, objectToValidate);
}
setValidationReport(report);
validationModel.deleteObserver(this);
}
/**
* Implements
*
* @see org.openflexo.foundation.FlexoObserver#update(org.openflexo.foundation.FlexoObservable,
* org.openflexo.foundation.DataModification)
* @see org.openflexo.foundation.FlexoObserver#update(org.openflexo.foundation.FlexoObservable,
* org.openflexo.foundation.DataModification)
*/
@Override
public void update(FlexoObservable observable, DataModification dataModification) {
if (dataModification instanceof ValidationNotification) {
if (dataModification instanceof ValidationInitNotification) {
ValidationInitNotification initNotification = (ValidationInitNotification) dataModification;
ProgressWindow.showProgressWindow(FlexoLocalization.localizedForKey("validating") + " "
+ initNotification.getRootObject().getFullyQualifiedName(), initNotification.getNbOfObjectToValidate());
} else if (dataModification instanceof ValidationProgressNotification) {
ValidationProgressNotification progressNotification = (ValidationProgressNotification) dataModification;
ProgressWindow.setProgressInstance(FlexoLocalization.localizedForKey("validating") + " "
+ progressNotification.getValidatedObject().getFullyQualifiedName());
} else if (dataModification instanceof ValidationFinishedNotification) {
ProgressWindow.hideProgressWindow();
}
}
}
protected class ValidationReportCellRenderer extends DefaultTableCellRenderer {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Component returned = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (column == 0) {
if (returned instanceof JLabel) {
JLabel label = (JLabel) returned;
label.setText("");
label.setIcon(IconLibrary.getIconForValidationIssue((ValidationIssue) value));
}
}
return returned;
}
}
protected class FixProposalRenderer extends DefaultListCellRenderer {
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
Component returned = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (returned instanceof JLabel) {
JLabel label = (JLabel) returned;
label.setText(((FixProposal) value).getLocalizedMessage());
label.setIcon(IconLibrary.FIX_PROPOSAL_ICON);
}
return returned;
}
}
}