// ============================================================================
//
// Copyright (C) 2006-2012 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.core.ui.context;
import java.util.Collections;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.CheckboxCellEditor;
import org.eclipse.jface.viewers.ICellEditorListener;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.TreeEditor;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.internal.IWorkbenchGraphicConstants;
import org.eclipse.ui.internal.WorkbenchImages;
import org.eclipse.ui.internal.WorkbenchMessages;
import org.talend.commons.ui.runtime.image.ImageProvider;
import org.talend.commons.ui.swt.tooltip.AbstractTreeTooltip;
import org.talend.core.language.ECodeLanguage;
import org.talend.core.language.LanguageManager;
import org.talend.core.model.metadata.types.PerlTypesManager;
import org.talend.core.model.process.IContextManager;
import org.talend.core.model.process.IContextParameter;
import org.talend.core.model.utils.ContextParameterUtils;
import org.talend.core.runtime.i18n.Messages;
import org.talend.core.ui.context.model.ContextProviderProxy;
import org.talend.core.ui.context.model.ContextValueErrorChecker;
import org.talend.core.ui.context.model.ContextViewerProvider;
import org.talend.core.ui.context.model.tree.ContextTreeCellModifier;
import org.talend.core.ui.context.model.tree.ContextTreeConstants;
import org.talend.core.ui.context.model.tree.GroupByContextAction;
import org.talend.core.ui.context.model.tree.GroupByVariableAction;
import org.talend.core.ui.context.model.tree.GroupByVariableProvider;
/**
* DOC bqian class global comment. Detailled comment <br/>
*
*/
public class ContextTreeValuesComposite extends AbstractContextTabEditComposite {
private TreeViewer viewer;
private TreeColumn column1st;
private TreeColumn column2nd;
private ContextViewerProvider provider;
private IContextModelManager modelManager;
private GroupByVariableAction groupByVariable;
private GroupByContextAction groupByContext;
private ContextTreeCellModifier cellModifier;
private DefaultCellEditorFactory cellFactory;
private ConfigureContextAction configContext;
private ToolItem contextConfigButton;
private ContextValueErrorChecker valueChecker;
/**
* bqian ConextTemplateComposite constructor comment.
*
* @param parent
* @param style
*/
public ContextTreeValuesComposite(Composite parent, IContextModelManager manager) {
super(parent, SWT.NONE);
this.setBackground(parent.getBackground());
modelManager = manager;
cellFactory = new DefaultCellEditorFactory(this);
this.setLayout(GridLayoutFactory.swtDefaults().spacing(0, 0).create());
initializeUI();
}
/**
* bqian Comment method "initializeUI".
*/
private void initializeUI() {
Composite toolbarContainer = new Composite(this, SWT.NONE);
toolbarContainer.setLayout(GridLayoutFactory.swtDefaults().spacing(0, 0).margins(0, 0).numColumns(2).create());
GridDataFactory.swtDefaults().align(SWT.RIGHT, SWT.TOP).grab(true, false).applyTo(toolbarContainer);
final ToolBar toolBar = new ToolBar(toolbarContainer, SWT.FLAT | SWT.NO_BACKGROUND);
GridDataFactory.swtDefaults().align(SWT.RIGHT, SWT.TOP).applyTo(toolBar);
createToolBar(toolBar);
final ToolBar menuBar = new ToolBar(toolbarContainer, SWT.FLAT | SWT.NO_BACKGROUND);
GridDataFactory.swtDefaults().align(SWT.RIGHT, SWT.TOP).applyTo(menuBar);
createMenuBar(menuBar);
viewer = new TreeViewer(this, SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
final Tree tree = viewer.getTree();
tree.setHeaderVisible(true);
tree.setLinesVisible(true);
tree.setLayoutData(new GridData(GridData.FILL_BOTH));
column1st = new TreeColumn(tree, SWT.NONE);
column1st.setText(ContextTreeConstants.getVariableColumnName());
column1st.setWidth(ContextTableValuesComposite.CONTEXT_COLUMN_WIDTH);
column2nd = new TreeColumn(tree, SWT.NONE);
column2nd.setText(ContextTreeConstants.getContextColumnName());
column2nd.setWidth(ContextTableValuesComposite.CONTEXT_COLUMN_WIDTH);
TreeColumn column = new TreeColumn(tree, SWT.NONE);
column.setResizable(false);
column.setWidth(20);
column = new TreeColumn(tree, SWT.NONE);
column.setText(Messages.getString("ContextTreeConstants.promptName")); //$NON-NLS-1$
column.setWidth(ContextTableValuesComposite.CONTEXT_COLUMN_WIDTH);
column = new TreeColumn(tree, SWT.NONE);
column.setText(Messages.getString("ContextTreeConstants.valueName")); //$NON-NLS-1$
column.setWidth(ContextTableValuesComposite.CONTEXT_COLUMN_WIDTH);
boolean isRepositoryContext = (modelManager instanceof ContextComposite)
&& ((ContextComposite) modelManager).isRepositoryContext();
viewer.setCellEditors(new CellEditor[] { null, null, new CheckboxCellEditor(tree), new TextCellEditor(tree),
new TextCellEditor(tree) });
cellModifier = new ContextTreeCellModifier(this, isRepositoryContext);
viewer.setCellModifier(cellModifier);
provider = new ContextViewerProvider();
provider.setProvider(new GroupByVariableProvider(modelManager));
viewer.setLabelProvider(provider);
viewer.setContentProvider(provider);
addSorter(viewer);
setDefaultPresentationType();
final TreeEditor treeEditor = new TreeEditor(tree);
createEditorListener(treeEditor);
tree.addMouseListener(new MouseAdapter() {
@Override
public void mouseDown(MouseEvent e) {
if (modelManager.isReadOnly()) {
return;
}
Point pt = new Point(e.x, e.y);
TreeItem item = tree.getItem(pt);
// deactivate the current cell editor
if (cellEditor != null && !cellEditor.getControl().isDisposed()) {
deactivateCellEditor(treeEditor);
}
if (item != null && !item.isDisposed()) {
Rectangle rect = item.getBounds(ContextTreeConstants.VARIABLE_COLUMN_INDEX);
if (rect.contains(pt)) {
handleSelect(item, tree, treeEditor);
}
}
}
});
valueChecker = new ContextValueErrorChecker(viewer);
if (LanguageManager.getCurrentLanguage() == ECodeLanguage.PERL) {
createTreeTooltip(tree);
}
}
/**
* DOC bqian Comment method "createTreeTooltip".
*
* @param tree
*/
protected void createTreeTooltip(Tree tree) {
new AbstractTreeTooltip(tree) {
/*
* (non-Javadoc)
*
* @see
* org.talend.commons.ui.swt.tooltip.AbstractTreeTooltip#getTooltipContent(org.eclipse.swt.widgets.TreeItem)
*/
@Override
public String getTooltipContent(TreeItem item) {
IContextParameter para = cellModifier.getRealParameter(item.getData());
// see the third note of the bug 3749.
if (para != null && para.getType().equalsIgnoreCase(PerlTypesManager.STRING)) {
return Messages.getString("PromptDialog.stringTip"); //$NON-NLS-1$
}
return null;
}
};
}
/**
* DOC bqian Comment method "addSorter".
*
* @param viewer2
*/
private void addSorter(final TreeViewer viewer2) {
final Tree table = viewer2.getTree();
Listener sortListener = new Listener() {
private int direction = 1;
public void handleEvent(Event e) {
final TreeColumn column = (TreeColumn) e.widget;
if (column == table.getSortColumn()) {
direction = -direction;
}
if (direction == 1) {
table.setSortDirection(SWT.UP);
} else {
table.setSortDirection(SWT.DOWN);
}
table.setSortColumn(column);
viewer2.setSorter(new ViewerSorter() {
int index = 0;
@Override
public void sort(Viewer viewer, Object[] elements) {
while (index < table.getColumns().length && table.getColumn(index) != column) {
index++;
}
super.sort(viewer, elements);
}
@Override
public int compare(Viewer viewer, Object e1, Object e2) {
ITableLabelProvider labelProvider = (ITableLabelProvider) viewer2.getLabelProvider();
String columnText = labelProvider.getColumnText(e1, index) != null ? labelProvider.getColumnText(e1,
index) : ""; //$NON-NLS-1$
String columnText2 = labelProvider.getColumnText(e2, index) != null ? labelProvider.getColumnText(e2,
index) : ""; //$NON-NLS-1$
return getComparator().compare(columnText, columnText2) * direction;
}
});
viewer2.expandAll();
}
};
table.getColumn(0).addListener(SWT.Selection, sortListener);
table.getColumn(1).addListener(SWT.Selection, sortListener);
table.setSortColumn(table.getColumn(0));
table.setSortDirection(SWT.UP);
}
@Override
public void setEnabled(boolean enabled) {
configContext.setEnabled(enabled);
}
public TreeViewer getViewer() {
return this.viewer;
}
public IContextModelManager getContextModelManager() {
return this.modelManager;
}
public ContextValueErrorChecker getValueChecker() {
return this.valueChecker;
}
private void activateCellEditor(final TreeItem item, final Tree tree, final TreeEditor treeEditor) {
IContextParameter para = cellModifier.getRealParameter(item.getData());
if (para == null) {
return;
}
valueChecker.checkErrors(item, ContextTreeConstants.VARIABLE_COLUMN_INDEX, para);
if (!para.isBuiltIn()) {
// not built-in
return;
}
cellEditor = cellFactory.getCustomCellEditor(para, tree);
if (cellEditor == null) {
// unable to create the editor
return;
}
// activate the cell editor
cellEditor.activate();
// if the cell editor has no control we can stop now
Control control = cellEditor.getControl();
if (control == null) {
cellEditor.deactivate();
cellEditor = null;
return;
}
Text textControl = valueChecker.getTextControl(control);
if (textControl != null) {
if (ContextParameterUtils.isPasswordType(para)) {
textControl.setEchoChar('*');
} else {
textControl.setEchoChar((char) 0);
}
}
valueChecker.register(control);
// add our editor listener
cellEditor.addListener(createEditorListener(treeEditor));
// set the layout of the tree editor to match the cell editor
CellEditor.LayoutData layout = cellEditor.getLayoutData();
treeEditor.horizontalAlignment = layout.horizontalAlignment;
treeEditor.grabHorizontal = layout.grabHorizontal;
treeEditor.minimumWidth = layout.minimumWidth;
treeEditor.setEditor(control, item, ContextTreeConstants.VARIABLE_COLUMN_INDEX);
// give focus to the cell editor
cellEditor.setFocus();
}
protected void handleSelect(final TreeItem item, final Tree tree, final TreeEditor treeEditor) {
// get the new selection
activateCellEditor(item, tree, treeEditor);
}
private void deactivateCellEditor(final TreeEditor tableEditor) {
tableEditor.setEditor(null, null, ContextTreeConstants.VARIABLE_COLUMN_INDEX);
if (cellEditor != null) {
Control control = cellEditor.getControl();
if (control != null) {
valueChecker.unregister(control);
}
cellEditor.deactivate();
cellEditor.removeListener(editorListener);
cellEditor = null;
}
}
private ICellEditorListener createEditorListener(final TreeEditor tableEditor) {
editorListener = new ICellEditorListener() {
public void cancelEditor() {
deactivateCellEditor(tableEditor);
}
public void editorValueChanged(boolean oldValidState, boolean newValidState) {
}
public void applyEditorValue() {
}
};
return editorListener;
}
private ICellEditorListener editorListener;
private CellEditor cellEditor;
/**
* bqian Comment method "createMenuBar".
*
* @param toolBar
*/
private void createToolBar(final ToolBar toolBar) {
configContext = new ConfigureContextAction(modelManager, this.getShell());
contextConfigButton = new ToolItem(toolBar, SWT.PUSH);
// contextConfigButton.setDisabledImage();
contextConfigButton.setImage(ImageProvider.getImage(configContext.getImageDescriptor()));
contextConfigButton.setToolTipText(configContext.getText());
contextConfigButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
configContext.run();
}
});
}
private void createMenuBar(final ToolBar menuBar) {
ToolItem pullDownButton = new ToolItem(menuBar, SWT.PUSH);
Image hoverImage = WorkbenchImages.getImage(IWorkbenchGraphicConstants.IMG_LCL_RENDERED_VIEW_MENU);
pullDownButton.setDisabledImage(hoverImage);
pullDownButton.setImage(hoverImage);
pullDownButton.setToolTipText(WorkbenchMessages.Menu);
pullDownButton.setWidth(5);
MenuManager menuManager = new MenuManager("Context Presentation"); //$NON-NLS-1$
groupByVariable = new GroupByVariableAction(this);
groupByContext = new GroupByContextAction(this);
menuManager.add(groupByVariable);
menuManager.add(groupByContext);
final Menu aMenu = menuManager.createContextMenu(menuBar.getParent());
pullDownButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
Point toolbarSize = menuBar.getSize();
toolbarSize = menuBar.toDisplay(0, toolbarSize.y);
aMenu.setLocation(toolbarSize);
aMenu.setVisible(true);
}
});
}
@Override
public void refresh() {
IContextManager cm = modelManager.getContextManager();
viewer.setInput(cm.getListContext());
// viewer.expandAll();
contextConfigButton.setEnabled(!modelManager.isReadOnly());
// (feature 1597)
checkItemValueErrors(viewer.getTree().getItems());
}
public void checkItemValueErrors(final TreeItem[] items) {
if (items == null) {
return;
}
for (TreeItem item : items) {
IContextParameter para = cellModifier.getRealParameter(item.getData());
if (para != null && para instanceof IContextParameter) {
valueChecker.checkErrors(item, ContextTreeConstants.VARIABLE_COLUMN_INDEX, para);
}
checkItemValueErrors(item.getItems());
}
}
/**
* Clear the data in this viewer.
*
* @param jobContextManager2
*/
public void clear() {
viewer.setInput(Collections.EMPTY_LIST);
}
public TreeColumn getColumn1st() {
return this.column1st;
}
public TreeColumn getColumn2nd() {
return this.column2nd;
}
public void setProviderProxy(ContextProviderProxy providerProxy) {
this.provider.setProvider(providerProxy);
}
private void setDefaultPresentationType() {
IPreferenceStore store = getPreferenceStore();
String presentationType = store.getString(ContextTreeConstants.PRESENTATION_TYPE_KEY);
if (presentationType == null
|| presentationType.length() == 0
|| store.getString(ContextTreeConstants.PRESENTATION_TYPE_KEY).equals(
ContextTreeConstants.VARIABLE_COLUMN_PROPERTY)) {
groupByVariable.setChecked(true);
groupByContext.setChecked(false);
groupByVariable.run();
} else if (store.getString(ContextTreeConstants.PRESENTATION_TYPE_KEY).equals(
ContextTreeConstants.CONTEXT_COLUMN_PROPERTY)) {
groupByContext.setChecked(true);
groupByVariable.setChecked(false);
groupByContext.run();
}
}
/*
* (non-Javadoc)
*
* @see org.talend.core.ui.context.AbstractContextTabEditComposite#isGroupBySource()
*/
@Override
public boolean isGroupBySource() {
return false;
}
}