// ============================================================================
//
// Copyright (C) 2006-2016 Talend Inc. - www.talend.com
//
// This source code is available under agreement available at
// %InstallDIR%\features\org.talend.rcp.branding.%PRODUCTNAME%\%PRODUCTNAME%license.txt
//
// You should have received a copy of the agreement
// along with this program; if not, write to Talend SA
// 9 rue Pages 92150 Suresnes, France
//
// ============================================================================
package org.talend.dataprofiler.core.ui.editor.analysis;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.forms.editor.FormEditor;
import org.eclipse.ui.forms.events.HyperlinkAdapter;
import org.eclipse.ui.forms.events.HyperlinkEvent;
import org.eclipse.ui.forms.widgets.ExpandableComposite;
import org.eclipse.ui.forms.widgets.ImageHyperlink;
import org.eclipse.ui.forms.widgets.ScrolledForm;
import org.eclipse.ui.forms.widgets.Section;
import org.talend.dataprofiler.core.ImageLib;
import org.talend.dataprofiler.core.i18n.internal.DefaultMessagesImpl;
import org.talend.dataprofiler.core.model.dynamic.DynamicIndicatorModel;
import org.talend.dataprofiler.core.ui.action.actions.RunAnalysisAction;
import org.talend.dataprofiler.core.ui.events.DynamicBAWChartEventReceiver;
import org.talend.dataprofiler.core.ui.events.DynamicChartEventReceiver;
import org.talend.dataprofiler.core.ui.events.EventEnum;
import org.talend.dataprofiler.core.ui.events.EventManager;
import org.talend.dataprofiler.core.ui.events.EventReceiver;
import org.talend.dataprofiler.core.ui.utils.AnalysisUtils;
import org.talend.dataprofiler.core.ui.utils.WorkbenchUtils;
import org.talend.dataquality.analysis.Analysis;
import org.talend.dataquality.indicators.Indicator;
import org.talend.dq.indicators.preview.EIndicatorChartType;
/**
* DOC yyin class global comment. Detailled comment
*/
public abstract class DynamicAnalysisMasterPage extends AbstractAnalysisMetadataPage {
protected SashForm sForm;
protected Composite previewComp;
protected Section previewSection = null;
protected Composite chartComposite;
abstract List<ExpandableComposite> getPreviewChartList();
protected Map<Indicator, EventReceiver> eventReceivers = new IdentityHashMap<Indicator, EventReceiver>();
private EventReceiver registerDynamicRefreshEvent;
private EventReceiver switchBetweenPageEvent;
/**
* DOC yyin DynamicAnalysisMasterPage constructor comment.
*
* @param editor
* @param id
* @param title
*/
public DynamicAnalysisMasterPage(FormEditor editor, String id, String title) {
super(editor, id, title);
}
protected void createPreviewComposite() {
previewComp = toolkit.createComposite(sForm);
previewComp.setLayoutData(new GridData(GridData.FILL_BOTH));
previewComp.setLayout(new GridLayout());
// add by hcheng for 0007290: Chart cannot auto compute it's size in
// DQRule analsyis Editor
previewComp.addControlListener(new ControlAdapter() {
@Override
public void controlResized(ControlEvent e) {
super.controlResized(e);
sForm.redraw();
form.reflow(true);
}
});
}
void createPreviewSection(final ScrolledForm form1, Composite parent) {
previewSection = createSection(
form1,
parent,
DefaultMessagesImpl.getString("ColumnMasterDetailsPage.graphics"), DefaultMessagesImpl.getString("ColumnMasterDetailsPage.space")); //$NON-NLS-1$ //$NON-NLS-2$
previewSection.setLayoutData(new GridData(GridData.FILL_BOTH));
Composite sectionClient = toolkit.createComposite(previewSection);
sectionClient.setLayout(new GridLayout());
sectionClient.setLayoutData(new GridData(GridData.FILL_BOTH));
Composite actionBarComp = toolkit.createComposite(sectionClient);
GridLayout gdLayout = new GridLayout();
gdLayout.numColumns = 3;
actionBarComp.setLayout(gdLayout);
createCollapseAllLink(actionBarComp);
createExpandAllLink(actionBarComp);
Button chartButton = new Button(actionBarComp, SWT.NONE);
chartButton.setText(DefaultMessagesImpl.getString("ColumnMasterDetailsPage.refreshGraphics")); //$NON-NLS-1$
final Label message = toolkit.createLabel(sectionClient,
DefaultMessagesImpl.getString("ColumnMasterDetailsPage.spaceWhite")); //$NON-NLS-1$
message.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_RED));
message.setVisible(false);
chartButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
disposeChartComposite();
Analysis analysis = getAnalysisHandler().getAnalysis();
boolean analysisStatue = analysis.getResults().getResultMetadata() != null
&& analysis.getResults().getResultMetadata().getExecutionDate() != null;
if (!analysisStatue) {
boolean returnCode = MessageDialog.openConfirm(null,
DefaultMessagesImpl.getString("ColumnMasterDetailsPage.ViewResult"), //$NON-NLS-1$
DefaultMessagesImpl.getString("ColumnMasterDetailsPage.RunOrSeeSampleData")); //$NON-NLS-1$
if (returnCode) {
new RunAnalysisAction().run();
message.setVisible(false);
} else {
createPreviewCharts(form1, chartComposite);
message.setText(DefaultMessagesImpl.getString("ColumnMasterDetailsPage.warning")); //$NON-NLS-1$
message.setVisible(true);
}
} else {
createPreviewCharts(form1, chartComposite);
}
reLayoutChartComposite();
}
});
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.TOP).applyTo(sectionClient);
chartComposite = toolkit.createComposite(sectionClient);
chartComposite.setLayout(new GridLayout());
chartComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
previewSection.setClient(sectionClient);
}
private void createExpandAllLink(Composite actionBarComp) {
ImageHyperlink expandAllImageLink = toolkit.createImageHyperlink(actionBarComp, SWT.NONE);
expandAllImageLink.setToolTipText(getExpandString());
WorkbenchUtils.setHyperlinkImage(expandAllImageLink, ImageLib.getImage(ImageLib.EXPAND_ALL));
expandAllImageLink.addHyperlinkListener(new HyperlinkAdapter() {
@Override
public void linkActivated(HyperlinkEvent e) {
List<ExpandableComposite> previewChartList = getPreviewChartList();
if (previewChartList != null && !previewChartList.isEmpty()) {
for (ExpandableComposite comp : previewChartList) {
comp.setExpanded(true);
comp.getParent().pack();
}
}
if (getChartComposite() != null) {
getChartComposite().getParent().pack();
}
}
});
}
public abstract void createPreviewCharts(final ScrolledForm form1, final Composite composite);
abstract String getExpandString();
abstract String getCollapseAllString();
private void createCollapseAllLink(Composite actionBarComp) {
ImageHyperlink collapseAllImageLink = toolkit.createImageHyperlink(actionBarComp, SWT.NONE);
collapseAllImageLink.setToolTipText(getCollapseAllString());
WorkbenchUtils.setHyperlinkImage(collapseAllImageLink, ImageLib.getImage(ImageLib.COLLAPSE_ALL));
collapseAllImageLink.addHyperlinkListener(new HyperlinkAdapter() {
@Override
public void linkActivated(HyperlinkEvent e) {
List<ExpandableComposite> previewChartList = getPreviewChartList();
if (previewChartList != null && !previewChartList.isEmpty()) {
for (ExpandableComposite comp : previewChartList) {
comp.setExpanded(false);
comp.getParent().pack();
}
}
}
});
}
/**
* Added TDQ-8787 20140613 yyin: create all charts before running, register each chart with its related indicator.
*/
public void registerDynamicEvent() {
// only worked for the analysis which support dynamic chart
// create all charts for related indicator in current page
createDynamicChartsBeforeRun();
// get all indicators and datasets
List<DynamicIndicatorModel> indiAndDatasets = getDynamicDatasets();
// register dynamic event,for the indicator (for each column)
for (DynamicIndicatorModel oneCategoryIndicatorModel : indiAndDatasets) {
if (EIndicatorChartType.SUMMARY_STATISTICS.equals(oneCategoryIndicatorModel.getChartType())) {
// when all summary indicators are selected
DynamicBAWChartEventReceiver bawReceiver = AnalysisUtils.createDynamicBAWChartEventReceiver(
oneCategoryIndicatorModel, eventReceivers);
bawReceiver.setChartComposite(chartComposite);
// no need to register the parent baw receiver with one of summary indicator, no need to handle baw
// actually
} else {
int index = 0;
for (Indicator oneIndicator : oneCategoryIndicatorModel.getIndicatorList()) {
// if the indicator is a frequency indicator, create a Frequency Event Receiver
DynamicChartEventReceiver eReceiver = createEventReceiver(oneCategoryIndicatorModel, index++, oneIndicator);
eReceiver.setChartComposite(chartComposite);
// clear data
eReceiver.clearValue();
registerIndicatorEvent(oneIndicator, eReceiver);
}
}
}
reLayoutChartComposite();
registerOtherDynamicEvent();
}
/**
* DOC yyin Comment method "createEventReceiver".
*
* @param categoryDataset
* @param index
* @param oneIndicator
* @param eIndicatorChartType
* @return
*/
protected DynamicChartEventReceiver createEventReceiver(DynamicIndicatorModel indicatorModel, int index,
Indicator oneIndicator) {
return AnalysisUtils.createDynamicChartEventReceiver(indicatorModel, index, oneIndicator);
}
private void registerIndicatorEvent(Indicator oneIndicator, DynamicChartEventReceiver eReceiver) {
eventReceivers.put(oneIndicator, eReceiver);
EventManager.getInstance().register(oneIndicator, EventEnum.DQ_DYMANIC_CHART, eReceiver);
}
public void reLayoutChartComposite() {
if (chartComposite != null) {
chartComposite.getParent().pack();
}
}
/**
* refresh the composite of the chart, to show the changes on the chart.
*/
private void registerOtherDynamicEvent() {
registerDynamicRefreshEvent = new EventReceiver() {
@Override
public boolean handle(Object data) {
reLayoutChartComposite();
return true;
}
};
EventManager.getInstance().register(chartComposite, EventEnum.DQ_DYNAMIC_REFRESH_DYNAMIC_CHART,
registerDynamicRefreshEvent);
// register a event to handle switch between master and result page
switchBetweenPageEvent = new EventReceiver() {
int times = 0;
@Override
public boolean handle(Object data) {
// only need to refresh for the first time switch, and must be during a running.
if (times == 0) {
times++;
((AnalysisEditor) currentEditor).getResultPage().refresh(((AnalysisEditor) currentEditor).getMasterPage());
}
return true;
}
};
EventManager.getInstance().register(getCurrentModelElement(), EventEnum.DQ_DYNAMIC_SWITCH_MASTER_RESULT_PAGE,
switchBetweenPageEvent);
}
/**
* unregister every dynamic events which registered before executing analysis
*
* @param eventReceivers
*/
public void unRegisterDynamicEvent() {
EventManager.getInstance().clearEvent(getCurrentModelElement(), EventEnum.DQ_DYNAMIC_SWITCH_MASTER_RESULT_PAGE);
for (Indicator oneIndicator : eventReceivers.keySet()) {
DynamicChartEventReceiver eventReceiver = (DynamicChartEventReceiver) eventReceivers.get(oneIndicator);
eventReceiver.clear();
EventManager.getInstance().clearEvent(oneIndicator, EventEnum.DQ_DYMANIC_CHART);
}
eventReceivers.clear();
EventManager.getInstance().clearEvent(chartComposite, EventEnum.DQ_DYNAMIC_REFRESH_DYNAMIC_CHART);
clearDynamicDatasets();
}
/**
* dispose ChartComposite.
*/
public void disposeChartComposite() {
if (chartComposite != null && !chartComposite.isDisposed()) {
for (Control control : chartComposite.getChildren()) {
control.dispose();
}
}
}
public void createDynamicChartsBeforeRun() {
// call refresh to create all charts
refreshGraphicsInSettingsPage();
}
// should be implemented in child classes
abstract public List<DynamicIndicatorModel> getDynamicDatasets();
public void clearDynamicDatasets() {
// make the run button workable again
((AnalysisEditor) currentEditor).setRunActionButtonState(true);
}
}