com.twineworks.kettle.ruby.step.RubyStepDialog Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ruby-for-pentaho-kettle Show documentation
Show all versions of ruby-for-pentaho-kettle Show documentation
Scripting steps for Pentaho kettle.
/*
* Ruby for pentaho kettle
* Copyright (C) 2017 Twineworks GmbH
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.twineworks.kettle.ruby.step;
import com.twineworks.kettle.ruby.step.RubyStepSamplesHelper.SampleType;
import com.twineworks.kettle.ruby.step.meta.OutputFieldMeta;
import com.twineworks.kettle.ruby.step.meta.RoleStepMeta;
import com.twineworks.kettle.ruby.step.meta.RubyScriptMeta;
import com.twineworks.kettle.ruby.step.meta.RubyScriptMeta.Role;
import com.twineworks.kettle.ruby.step.meta.RubyVariableMeta;
import org.apache.commons.io.FileUtils;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.*;
import org.jruby.Ruby;
import org.jruby.runtime.builtin.IRubyObject;
import org.pentaho.di.core.Const;
import org.pentaho.di.core.Props;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.core.plugins.PluginRegistry;
import org.pentaho.di.core.plugins.StepPluginType;
import org.pentaho.di.core.row.RowMetaInterface;
import org.pentaho.di.core.row.ValueMetaInterface;
import org.pentaho.di.core.row.value.ValueMetaFactory;
import org.pentaho.di.i18n.BaseMessages;
import org.pentaho.di.trans.TransMeta;
import org.pentaho.di.trans.step.BaseStepMeta;
import org.pentaho.di.trans.step.StepDialogInterface;
import org.pentaho.di.ui.core.gui.GUIResource;
import org.pentaho.di.ui.core.widget.ColumnInfo;
import org.pentaho.di.ui.core.widget.StyledTextComp;
import org.pentaho.di.ui.core.widget.TableView;
import org.pentaho.di.ui.core.widget.TextVar;
import org.pentaho.di.ui.spoon.Spoon;
import org.pentaho.di.ui.trans.step.BaseStepDialog;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class RubyStepDialog extends BaseStepDialog implements StepDialogInterface {
private static Class> PKG = RubyStepMeta.class; // for i18n purposes
final private String[] NO_YES = new String[2];
int margin = Const.MARGIN;
private RubyStepSyntaxHighlighter syntaxHighlighter;
private RubyStepParseErrorHelper parseErrorHelper;
// output field name
private RubyStepMeta input;
private boolean changedInDialog;
private CTabFolder wScriptsFolder;
private ModifyListener lsMod;
private TableView wFields;
private Button wClearInputFields;
private Label wlEditingPosition;
private Composite wTopLeft;
private GUIResource guiResource = GUIResource.getInstance();
private Label wlSyntaxCheck;
private CTabFolder wLeftFolder;
private SashForm wTop;
private ToolItem itemSettings;
private ToolBar wScriptToolBar;
private Label wSeparator;
private CTabFolder wBottomFolder;
private String[] prevStepNames;
private String[] nextStepNames;
private TableView wScopeVariables;
private TableView wInfoSteps;
private TableView wTargetSteps;
private Image scriptImage;
private Image rubyImage;
private Image checkImage;
private Menu scriptMenu;
private Image addImage;
private Image renameImage;
private MenuItem renameItem;
private Image initScriptImage;
private Image disposeScriptImage;
private Image libScriptImage;
private MenuItem rowScriptItem;
private MenuItem libScriptItem;
private MenuItem initScriptItem;
private MenuItem disposeScriptItem;
private Image rowScriptImage;
private Image infoStepImage;
private Tree wTree;
private TreeItem inputTreeItem;
private HashMap infoTreeItems;
private Image inputImage;
private Image fieldImage;
private TreeItem inputFolderTreeItem;
private Image folderImage;
private TreeItem outputFolderTreeItem;
private TreeItem outputTreeItem;
private Image outputImage;
private HashMap targetTreeItems;
private Image targetStepImage;
private Image fieldChangedImage;
private TreeItem errorTreeItem;
private Image errorOutputImage;
private Image fieldErrorImage;
private Label wRubyVersion;
private Tree wSamplesTree;
private File pluginBaseFile;
private Image transformationImage;
private Image webDocumentImage;
private RubyStepSamplesHelper samplesHelper;
private Menu sampleMenu;
private MenuItem showSampleItem;
private int middle;
private TextVar wGemHome;
private String pluginBaseDir;
private String pluginImageDir = "com/twineworks/kettle/ruby/step/resources/";
public RubyStepDialog(Shell parent, Object in, TransMeta transMeta, String sname) {
super(parent, (BaseStepMeta) in, transMeta, sname);
input = (RubyStepMeta) in;
NO_YES[0] = BaseMessages.getString(PKG, "System.Combo.No");
NO_YES[1] = BaseMessages.getString(PKG, "System.Combo.Yes");
}
private Image getResourceImage(String name) {
return guiResource.getImage(pluginImageDir + name, this.getClass().getClassLoader(), 16, 16);
}
public String open() {
changed = input.hasChanged();
changedInDialog = false;
Shell parent = getParent();
Display display = parent.getDisplay();
shell = new Shell(parent, SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MIN | SWT.MAX);
syntaxHighlighter = new RubyStepSyntaxHighlighter();
parseErrorHelper = new RubyStepParseErrorHelper();
props.setLook(shell);
setShellImage(shell, input);
lsMod = new ModifyListener() {
public void modifyText(ModifyEvent e) {
input.setChanged();
changedInDialog = true;
}
};
FormLayout formLayout = new FormLayout();
formLayout.marginWidth = Const.FORM_MARGIN;
formLayout.marginHeight = Const.FORM_MARGIN;
shell.setLayout(formLayout);
shell.setText(BaseMessages.getString(PKG, "RubyStep.Shell.Title"));
middle = props.getMiddlePct();
// load images
if (!guiResource.getImageMap().containsKey("TypeExitRubyStep:empty16x16")) {
guiResource.getImageMap().put("TypeExitRubyStep:empty16x16", new Image(display, 16, 16));
}
pluginBaseDir = PluginRegistry.getInstance().findPluginWithId(StepPluginType.class, "TypeExitRubyStep").getPluginDirectory().toString();
URL pluginBaseURL = PluginRegistry.getInstance().findPluginWithId(StepPluginType.class, "TypeExitRubyStep").getPluginDirectory();
try {
pluginBaseFile = new File(pluginBaseURL.toURI());
} catch (URISyntaxException e) {
pluginBaseFile = new File(pluginBaseURL.getPath());
}
try {
scriptImage = getResourceImage("libScript.png");
checkImage = getResourceImage("check.png");
rubyImage = getResourceImage("ruby_16.png");
addImage = getResourceImage("addSmall.png");
renameImage = getResourceImage("edit.png");
rowScriptImage = rubyImage;
initScriptImage = getResourceImage("startScript.png");
disposeScriptImage = getResourceImage("endScript.png");
libScriptImage = scriptImage;
infoStepImage = getResourceImage("info_step.png");
targetStepImage = getResourceImage("target_step.png");
inputImage = getResourceImage("input.png");
outputImage = getResourceImage("output.png");
fieldImage = getResourceImage("field.png");
fieldChangedImage = getResourceImage("field_changed.png");
folderImage = getResourceImage("folder.png");
errorOutputImage = getResourceImage("error_output.png");
fieldErrorImage = getResourceImage("field_error.png");
// transformationImage = getResourceImage("transformation.png");
transformationImage = guiResource.getImage("ui/images/transformation_tree.png");
webDocumentImage = getResourceImage("web.png");
} catch (Exception e) {
Image empty = guiResource.getImage("TypeExitRubyStep:empty16x16");
scriptImage = empty;
checkImage = empty;
rubyImage = empty;
addImage = empty;
renameImage = empty;
rowScriptImage = empty;
initScriptImage = empty;
disposeScriptImage = empty;
libScriptImage = empty;
infoStepImage = empty;
targetStepImage = empty;
inputImage = empty;
outputImage = empty;
fieldImage = empty;
fieldChangedImage = empty;
fieldErrorImage = empty;
folderImage = empty;
errorOutputImage = empty;
transformationImage = empty;
webDocumentImage = empty;
}
samplesHelper = new RubyStepSamplesHelper();
samplesHelper.setFolderImage(folderImage);
samplesHelper.setSampleImage(fieldImage);
samplesHelper.setScriptImage(libScriptImage);
samplesHelper.setTransformationImage(transformationImage);
samplesHelper.setWebDocumentImage(webDocumentImage);
// start construction
// Stepname line
wlStepname = new Label(shell, SWT.RIGHT);
wlStepname.setText(BaseMessages.getString(PKG, "System.Label.StepName"));
props.setLook(wlStepname);
fdlStepname = new FormData();
fdlStepname.left = new FormAttachment(0, 0);
fdlStepname.right = new FormAttachment(middle, -margin);
fdlStepname.top = new FormAttachment(0, margin);
wlStepname.setLayoutData(fdlStepname);
wStepname = new Text(shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
wStepname.setText(stepname);
props.setLook(wStepname);
wStepname.addModifyListener(lsMod);
fdStepname = new FormData();
fdStepname.left = new FormAttachment(middle, 0);
fdStepname.top = new FormAttachment(0, margin);
fdStepname.right = new FormAttachment(100, 0);
wStepname.setLayoutData(fdStepname);
SashForm wSash = new SashForm(shell, SWT.VERTICAL);
props.setLook(wSash);
/*------------------------------------------------------------------------------------------------------------------------------------------------
* Upper part of form
------------------------------------------------------------------------------------------------------------------------------------------------*/
// top part
wTop = new SashForm(wSash, SWT.HORIZONTAL);
FormLayout topLayout = new FormLayout();
topLayout.marginWidth = Const.FORM_MARGIN;
topLayout.marginHeight = Const.FORM_MARGIN;
wTop.setLayout(topLayout);
props.setLook(wTop);
addLeftArea();
addScriptArea();
FormData fdTop = new FormData();
fdTop.left = new FormAttachment(0, 0);
fdTop.top = new FormAttachment(0, 0);
fdTop.right = new FormAttachment(100, 0);
fdTop.bottom = new FormAttachment(100, 0);
wTop.setLayoutData(fdTop);
wTop.SASH_WIDTH = margin;
wTop.setWeights(new int[]{32, 68});
/*------------------------------------------------------------------------------------------------------------------------------------------------
* Bottom part of form
------------------------------------------------------------------------------------------------------------------------------------------------*/
Composite wBottom = new Composite(wSash, SWT.NONE);
props.setLook(wBottom);
FormLayout bottomLayout = new FormLayout();
bottomLayout.marginWidth = Const.FORM_MARGIN;
bottomLayout.marginHeight = Const.FORM_MARGIN;
wBottom.setLayout(bottomLayout);
// separator
wSeparator = new Label(wBottom, SWT.SEPARATOR | SWT.HORIZONTAL);
FormData fdSeparator = new FormData();
fdSeparator.left = new FormAttachment(0, 0);
fdSeparator.right = new FormAttachment(100, 0);
fdSeparator.top = new FormAttachment(0, -margin);
wSeparator.setLayoutData(fdSeparator);
props.setLook(wSeparator);
// bottom tab folder
wBottomFolder = new CTabFolder(wBottom, SWT.BORDER | SWT.RESIZE);
wBottomFolder.setSimple(false);
wBottomFolder.setUnselectedImageVisible(true);
wBottomFolder.setUnselectedCloseVisible(false);
wBottomFolder.setMaximizeVisible(false);
wBottomFolder.setMinimizeVisible(false);
props.setLook(wBottomFolder);
addOutputFieldsTab();
prevStepNames = transMeta.getPrevStepNames(stepMeta);
addInfoStepsTab();
nextStepNames = transMeta.getNextStepNames(stepMeta);
addTargetStepsTab();
addScopeVariablesTab();
addRuntimeTab();
// set selected item in tab
wBottomFolder.setSelection(0);
// layout tab folder below the label
FormData fdBottomFolder = new FormData();
fdBottomFolder.left = new FormAttachment(0, 0);
fdBottomFolder.top = new FormAttachment(wSeparator, margin);
fdBottomFolder.right = new FormAttachment(100, 0);
fdBottomFolder.bottom = new FormAttachment(100, 0);
wBottomFolder.setLayoutData(fdBottomFolder);
FormData fdBottom = new FormData();
fdBottom.left = new FormAttachment(0, 0);
fdBottom.top = new FormAttachment(0, 0);
fdBottom.right = new FormAttachment(100, 0);
fdBottom.bottom = new FormAttachment(100, 0);
wBottom.setLayoutData(fdBottom);
/*------------------------------------------------------------------------------------------------------------------------------------------------
* Wrapping up form
------------------------------------------------------------------------------------------------------------------------------------------------*/
FormData fdSash = new FormData();
fdSash.left = new FormAttachment(0, 0);
fdSash.top = new FormAttachment(wStepname, margin);
fdSash.right = new FormAttachment(100, 0);
fdSash.bottom = new FormAttachment(100, -50);
wSash.setLayoutData(fdSash);
wSash.SASH_WIDTH = margin;
wSash.setWeights(new int[]{75, 25});
// OK and cancel buttons
wOK = new Button(shell, SWT.PUSH);
wOK.setText(BaseMessages.getString(PKG, "System.Button.OK"));
wCancel = new Button(shell, SWT.PUSH);
wCancel.setText(BaseMessages.getString(PKG, "System.Button.Cancel"));
BaseStepDialog.positionBottomButtons(shell, new Button[]{wOK, wCancel}, margin, wSash);
// Add listeners
lsCancel = new Listener() {
public void handleEvent(Event e) {
cancel();
}
};
lsOK = new Listener() {
public void handleEvent(Event e) {
ok();
}
};
wCancel.addListener(SWT.Selection, lsCancel);
wOK.addListener(SWT.Selection, lsOK);
lsDef = new SelectionAdapter() {
public void widgetDefaultSelected(SelectionEvent e) {
ok();
}
};
wStepname.addSelectionListener(lsDef);
// Detect X or ALT-F4 or something that kills this window...
shell.addShellListener(new ShellAdapter() {
public void shellClosed(ShellEvent e) {
if (!cancel()) {
e.doit = false;
}
}
});
// Set the shell size, based upon previous time...
setSize();
getData();
// make sure there's at least one default script
if (wScriptsFolder.getItemCount() == 0) {
addScriptTab(RubyScriptMeta.DEFAULT_SCRIPT);
}
wScriptsFolder.setSelection(wScriptsFolder.getItem(0));
highlightSyntax();
input.setChanged(changed);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
return stepname;
}
private void addScopeVariablesTab() {
CTabItem outFieldsItem = new CTabItem(wBottomFolder, SWT.NONE);
outFieldsItem.setText(BaseMessages.getString(PKG, "RubyStepDialog.ScopeVariables.Label"));
Composite wPanel = new Composite(wBottomFolder, SWT.NONE);
wPanel.setLayout(new FormLayout());
FormData fdPanel = new FormData();
fdPanel.left = new FormAttachment(0, 0);
fdPanel.top = new FormAttachment(0, 0);
fdPanel.right = new FormAttachment(100, 0);
fdPanel.bottom = new FormAttachment(100, 0);
wPanel.setLayoutData(fdPanel);
outFieldsItem.setControl(wPanel);
final int nrRows = input.getRubyVariables().size();
ColumnInfo[] colinf = new ColumnInfo[]{
new ColumnInfo(BaseMessages.getString(PKG, "RubyStepDialog.ColumnInfo.ScopeVariable"), ColumnInfo.COLUMN_TYPE_TEXT, false), //$NON-NLS-1$
new ColumnInfo(BaseMessages.getString(PKG, "RubyStepDialog.ColumnInfo.ScopeVariableValue"), ColumnInfo.COLUMN_TYPE_TEXT, false), //$NON-NLS-1$
};
colinf[1].setUsingVariables(true);
wScopeVariables = new TableView(transMeta, wPanel, SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI, colinf, nrRows, lsMod, props);
FormData fdFields = new FormData();
fdFields.left = new FormAttachment(0, 0);
fdFields.top = new FormAttachment(0, 0);
fdFields.right = new FormAttachment(100, 0);
fdFields.bottom = new FormAttachment(100, 0);
wScopeVariables.setLayoutData(fdFields);
}
private void addOutputFieldsTab() {
CTabItem outFieldsItem = new CTabItem(wBottomFolder, SWT.NONE);
outFieldsItem.setText(BaseMessages.getString(PKG, "RubyStepDialog.Fields.Label"));
Composite wPanel = new Composite(wBottomFolder, SWT.NONE);
wPanel.setLayout(new FormLayout());
props.setLook(wPanel);
FormData fdPanel = new FormData();
fdPanel.left = new FormAttachment(0, 0);
fdPanel.top = new FormAttachment(0, 0);
fdPanel.right = new FormAttachment(100, 0);
fdPanel.bottom = new FormAttachment(100, 0);
wPanel.setLayoutData(fdPanel);
outFieldsItem.setControl(wPanel);
wClearInputFields = new Button(wPanel, SWT.CHECK);
wClearInputFields.setText(BaseMessages.getString(PKG, "RubyStepDialog.ClearFields.Label")); //$NON-NLS-1$
props.setLook(wClearInputFields);
FormData fdClearResultFields = new FormData();
fdClearResultFields.right = new FormAttachment(100, 0);
fdClearResultFields.bottom = new FormAttachment(100, 0);
wClearInputFields.setLayoutData(fdClearResultFields);
final int fieldsRows = input.getOutputFields().size();
ColumnInfo[] colinf = new ColumnInfo[]{
new ColumnInfo(BaseMessages.getString(PKG, "RubyStepDialog.ColumnInfo.Fieldname"), ColumnInfo.COLUMN_TYPE_TEXT, false), //$NON-NLS-1$
new ColumnInfo(BaseMessages.getString(PKG, "RubyStepDialog.ColumnInfo.Type"), ColumnInfo.COLUMN_TYPE_CCOMBO, ValueMetaFactory.getAllValueMetaNames()), //$NON-NLS-1$
new ColumnInfo(BaseMessages.getString(PKG, "RubyStepDialog.ColumnInfo.UpdateExisting"), ColumnInfo.COLUMN_TYPE_CCOMBO, NO_YES) //$NON-NLS-1$
};
wFields = new TableView(transMeta, wPanel, SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI, colinf, fieldsRows, lsMod, props);
FormData fdFields = new FormData();
fdFields.left = new FormAttachment(0, 0);
fdFields.top = new FormAttachment(0, 0);
fdFields.right = new FormAttachment(100, 0);
fdFields.bottom = new FormAttachment(wClearInputFields, -margin);
wFields.setLayoutData(fdFields);
}
private void addInfoStepsTab() {
CTabItem infoStepsItem = new CTabItem(wBottomFolder, SWT.NONE);
infoStepsItem.setText(BaseMessages.getString(PKG, "RubyStepDialog.InfoSteps.Label"));
Composite wPanel = new Composite(wBottomFolder, SWT.NONE);
wPanel.setLayout(new FormLayout());
props.setLook(wPanel);
FormData fdPanel = new FormData();
fdPanel.left = new FormAttachment(0, 0);
fdPanel.top = new FormAttachment(0, 0);
fdPanel.right = new FormAttachment(100, 0);
fdPanel.bottom = new FormAttachment(100, 0);
wPanel.setLayoutData(fdPanel);
infoStepsItem.setControl(wPanel);
final int nrRows = input.getInfoSteps().size();
ColumnInfo[] colinf = new ColumnInfo[]{
new ColumnInfo(BaseMessages.getString(PKG, "RubyStepDialog.ColumnInfo.InfoStepTag"), ColumnInfo.COLUMN_TYPE_TEXT, false), //$NON-NLS-1$
new ColumnInfo(BaseMessages.getString(PKG, "RubyStepDialog.ColumnInfo.InfoStepName"), ColumnInfo.COLUMN_TYPE_CCOMBO, prevStepNames), //$NON-NLS-1$
};
wInfoSteps = new TableView(transMeta, wPanel, SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI, colinf, nrRows, lsMod, props);
FormData fdFields = new FormData();
fdFields.left = new FormAttachment(0, 0);
fdFields.top = new FormAttachment(0, 0);
fdFields.right = new FormAttachment(100, 0);
fdFields.bottom = new FormAttachment(100, 0);
wInfoSteps.setLayoutData(fdFields);
}
private void addTargetStepsTab() {
CTabItem targetStepsItem = new CTabItem(wBottomFolder, SWT.NONE);
targetStepsItem.setText(BaseMessages.getString(PKG, "RubyStepDialog.TargetSteps.Label"));
Composite wPanel = new Composite(wBottomFolder, SWT.NONE);
wPanel.setLayout(new FormLayout());
props.setLook(wPanel);
FormData fdPanel = new FormData();
fdPanel.left = new FormAttachment(0, 0);
fdPanel.top = new FormAttachment(0, 0);
fdPanel.right = new FormAttachment(100, 0);
fdPanel.bottom = new FormAttachment(100, 0);
wPanel.setLayoutData(fdPanel);
targetStepsItem.setControl(wPanel);
final int nrRows = input.getTargetSteps().size();
ColumnInfo[] colinf = new ColumnInfo[]{
new ColumnInfo(BaseMessages.getString(PKG, "RubyStepDialog.ColumnInfo.TargetStepTag"), ColumnInfo.COLUMN_TYPE_TEXT, false), //$NON-NLS-1$
new ColumnInfo(BaseMessages.getString(PKG, "RubyStepDialog.ColumnInfo.TargetStepName"), ColumnInfo.COLUMN_TYPE_CCOMBO, nextStepNames), //$NON-NLS-1$
};
wTargetSteps = new TableView(transMeta, wPanel, SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI, colinf, nrRows, lsMod, props);
FormData fdFields = new FormData();
fdFields.left = new FormAttachment(0, 0);
fdFields.top = new FormAttachment(0, 0);
fdFields.right = new FormAttachment(100, 0);
fdFields.bottom = new FormAttachment(100, 0);
wTargetSteps.setLayoutData(fdFields);
}
private void addFieldSummaryTab() {
CTabItem fieldSummaryItem = new CTabItem(wLeftFolder, SWT.NONE);
fieldSummaryItem.setText(BaseMessages.getString(PKG, "RubyStepDialog.FieldSummary.Label"));
Composite wPanel = new Composite(wLeftFolder, SWT.NONE);
wPanel.setLayout(new FormLayout());
props.setLook(wPanel);
wTree = new Tree(wPanel, SWT.H_SCROLL | SWT.V_SCROLL);
wTree.setHeaderVisible(true);
TreeColumn column1 = new TreeColumn(wTree, SWT.LEFT);
column1.setText(BaseMessages.getString(PKG, "RubyStepDialog.TreeColumn.Field"));
column1.setWidth(180);
TreeColumn column2 = new TreeColumn(wTree, SWT.LEFT);
column2.setText(BaseMessages.getString(PKG, "RubyStepDialog.TreeColumn.Type"));
column2.setWidth(90);
TreeColumn column3 = new TreeColumn(wTree, SWT.LEFT);
column3.setText(BaseMessages.getString(PKG, "RubyStepDialog.TreeColumn.AvailableAs"));
column3.setWidth(160);
props.setLook(wTree);
inputFolderTreeItem = new TreeItem(wTree, SWT.NONE);
inputFolderTreeItem.setText(new String[]{"input", "", ""});
inputFolderTreeItem.setImage(folderImage);
outputFolderTreeItem = new TreeItem(wTree, SWT.NONE);
outputFolderTreeItem.setText(new String[]{"output", "", ""});
outputFolderTreeItem.setImage(folderImage);
infoTreeItems = new HashMap();
// insert markers for info streams
for (RoleStepMeta s : input.getInfoSteps()) {
TreeItem item = new TreeItem(inputFolderTreeItem, SWT.NONE);
item.setText(new String[]{s.getRoleName(), "row stream", "$info_steps[\"" + s.getRoleName() + "\"]"});
item.setImage(infoStepImage);
infoTreeItems.put(s.getStepName(), item);
}
// insert markers for input stream
inputTreeItem = new TreeItem(inputFolderTreeItem, SWT.NONE);
inputTreeItem.setText(new String[]{"input", "row stream", "$input"});
inputTreeItem.setImage(inputImage);
// insert markers for target steps
targetTreeItems = new HashMap();
// insert markers for target streams
for (RoleStepMeta s : input.getTargetSteps()) {
TreeItem item = new TreeItem(outputFolderTreeItem, SWT.NONE);
item.setText(new String[]{s.getRoleName(), "row stream", "$target_steps[\"" + s.getRoleName() + "\"]"});
item.setImage(targetStepImage);
targetTreeItems.put(s.getStepName(), item);
}
// insert marker for output stream
outputTreeItem = new TreeItem(outputFolderTreeItem, SWT.NONE);
outputTreeItem.setText(new String[]{"output", "row stream", "$output"});
outputTreeItem.setImage(outputImage);
// insert marker for error stream
if (input.getParentStepMeta().isDoingErrorHandling()) {
errorTreeItem = new TreeItem(outputFolderTreeItem, SWT.NONE);
errorTreeItem.setText(new String[]{"error", "row stream", "$error"});
errorTreeItem.setImage(errorOutputImage);
}
inputFolderTreeItem.setExpanded(true);
outputFolderTreeItem.setExpanded(true);
final Runnable runnable = new Runnable() {
public void run() {
try {
// collect main input fields
RowMetaInterface inputFields = transMeta.getPrevStepFields(input.getParentStepMeta());
// collect fields from input steps
HashMap infoStepFields = new HashMap();
for (String step : input.getStepIOMeta().getInfoStepnames()) {
infoStepFields.put(step, transMeta.getStepFields(step));
}
// collect output fields
RowMetaInterface outputFields = transMeta.getStepFields(stepname);
RowMetaInterface errorFields = null;
if (input.getParentStepMeta().isDoingErrorHandling()) {
errorFields = input.getParentStepMeta().getStepErrorMeta().getErrorFields();
}
setTreeFields(inputFields, infoStepFields, outputFields, errorFields);
} catch (KettleException e) {
logError(BaseMessages.getString(PKG, "System.Dialog.GetFieldsFailed.Message"));
}
}
};
new Thread(runnable).start();
wTree.addListener(SWT.MouseDoubleClick, new Listener() {
@Override
public void handleEvent(Event e) {
if (e.button != 1)
return;
Point point = new Point(e.x, e.y);
TreeItem item = wTree.getItem(point);
if (item != null) {
StyledTextComp wScript = (StyledTextComp) wScriptsFolder.getSelection().getControl();
wScript.getStyledText().insert(item.getText(2));
}
}
});
FormData fdTree = new FormData();
fdTree.left = new FormAttachment(0, 0);
fdTree.top = new FormAttachment(0, 0);
fdTree.right = new FormAttachment(100, 0);
fdTree.bottom = new FormAttachment(100, 0);
wTree.setLayoutData(fdTree);
FormData fdPanel = new FormData();
fdPanel.left = new FormAttachment(0, 0);
fdPanel.top = new FormAttachment(0, 0);
fdPanel.right = new FormAttachment(100, 0);
fdPanel.bottom = new FormAttachment(100, 0);
wPanel.setLayoutData(fdPanel);
fieldSummaryItem.setControl(wPanel);
}
protected void setTreeFields(final RowMetaInterface inputFields, final HashMap infoFields, final RowMetaInterface outputFields, final RowMetaInterface errorFields) {
shell.getDisplay().syncExec(new Runnable() {
@Override
public void run() {
inputTreeItem.removeAll();
if (inputFields != null) {
for (ValueMetaInterface v : inputFields.getValueMetaList()) {
TreeItem m = new TreeItem(inputTreeItem, SWT.NONE);
m.setText(new String[]{v.getName(), v.getTypeDesc(), "$row[\"" + v.getName() + "\"]"});
m.setImage(fieldImage);
}
if (inputFields.size() == 0) {
inputTreeItem.dispose();
} else {
inputTreeItem.setExpanded(true);
}
}
for (String step : infoFields.keySet()) {
TreeItem parent = infoTreeItems.get(step);
if (parent != null) {
parent.removeAll();
RowMetaInterface stepFields = infoFields.get(step);
for (ValueMetaInterface v : stepFields.getValueMetaList()) {
TreeItem m = new TreeItem(parent, SWT.NONE);
m.setText(new String[]{v.getName(), v.getTypeDesc(), ""});
m.setImage(fieldImage);
}
parent.setExpanded(true);
}
}
// output stream
outputTreeItem.removeAll();
if (outputFields != null) {
for (ValueMetaInterface v : outputFields.getValueMetaList()) {
TreeItem m = new TreeItem(outputTreeItem, SWT.NONE);
m.setText(new String[]{v.getName(), v.getTypeDesc(), ""});
m.setImage(input.addsOrChangesField(v.getName()) ? fieldChangedImage : fieldImage);
}
outputTreeItem.setExpanded(true);
}
// target steps
for (RoleStepMeta step : input.getTargetSteps()) {
TreeItem parent = targetTreeItems.get(step.getStepName());
if (parent != null) {
parent.removeAll();
for (ValueMetaInterface v : outputFields.getValueMetaList()) {
TreeItem m = new TreeItem(parent, SWT.NONE);
m.setText(new String[]{v.getName(), v.getTypeDesc(), ""});
m.setImage(input.addsOrChangesField(v.getName()) ? fieldChangedImage : fieldImage);
}
parent.setExpanded(true);
}
}
// error stream
if (errorFields != null && input.getParentStepMeta().isDoingErrorHandling() && errorTreeItem != null) {
errorTreeItem.removeAll();
if (inputFields != null) {
for (ValueMetaInterface v : inputFields.getValueMetaList()) {
TreeItem m = new TreeItem(errorTreeItem, SWT.NONE);
m.setText(new String[]{v.getName(), v.getTypeDesc(), ""});
m.setImage(fieldImage);
}
}
if (errorFields != null) {
for (ValueMetaInterface v : errorFields.getValueMetaList()) {
TreeItem m = new TreeItem(errorTreeItem, SWT.NONE);
m.setText(new String[]{v.getName(), v.getTypeDesc(), ""});
m.setImage(fieldErrorImage);
}
}
errorTreeItem.setExpanded(true);
}
}
});
}
private void addRuntimeTab() {
CTabItem runtimeItem = new CTabItem(wBottomFolder, SWT.NONE);
runtimeItem.setText(BaseMessages.getString(PKG, "RubyStepDialog.ExecutionModel.Label"));
Composite wPanel = new Composite(wBottomFolder, SWT.NONE);
wPanel.setLayout(new FormLayout());
props.setLook(wPanel);
Label lRubyVersion = new Label(wPanel, SWT.RIGHT);
lRubyVersion.setText(BaseMessages.getString(PKG, "RubyStepDialog.ExecutionModel.Version"));
props.setLook(lRubyVersion);
FormData fdlRubyVersion = new FormData();
fdlRubyVersion.left = new FormAttachment(0, 0);
fdlRubyVersion.right = new FormAttachment(middle, -margin);
fdlRubyVersion.top = new FormAttachment(0, margin);
lRubyVersion.setLayoutData(fdlRubyVersion);
wRubyVersion = new Label(wPanel, SWT.LEFT);
IRubyObject rubyDesc = Ruby.getGlobalRuntime().evalScriptlet("RUBY_DESCRIPTION");
wRubyVersion.setText(rubyDesc != null ? rubyDesc.asJavaString() : "error getting RUBY_DESCRIPTION");
props.setLook(wRubyVersion);
FormData fdRubyVersion = new FormData();
fdRubyVersion.left = new FormAttachment(middle, 0);
fdRubyVersion.top = new FormAttachment(0, margin);
wRubyVersion.setLayoutData(fdRubyVersion);
// add gem home folder entry
Label lGemHome = new Label(wPanel, SWT.RIGHT);
lGemHome.setText(BaseMessages.getString(PKG, "RubyStepDialog.ExecutionModel.GemHome"));
props.setLook(lGemHome);
FormData fdlGemHome = new FormData();
fdlGemHome.left = new FormAttachment(0, 0);
fdlGemHome.right = new FormAttachment(middle, -margin);
fdlGemHome.top = new FormAttachment(wRubyVersion, margin);
lGemHome.setLayoutData(fdlGemHome);
wGemHome = new TextVar(transMeta, wPanel, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
wGemHome.setText(input.getGemHome());
props.setLook(wGemHome);
wGemHome.addModifyListener(lsMod);
FormData fdGemHome = new FormData();
fdGemHome.left = new FormAttachment(middle, 0);
fdGemHome.top = new FormAttachment(wRubyVersion, margin);
fdGemHome.right = new FormAttachment(100, -margin);
wGemHome.setLayoutData(fdGemHome);
runtimeItem.setControl(wPanel);
}
private void addScriptArea() {
// top right composite
Composite wTopRight = new Composite(wTop, SWT.NONE);
FormLayout topRightLayout = new FormLayout();
topRightLayout.marginWidth = 0;
topRightLayout.marginHeight = 0;
wTopRight.setLayout(topRightLayout);
props.setLook(wTopRight);
// script tab folder
wScriptsFolder = new CTabFolder(wTopRight, SWT.BORDER | SWT.RESIZE);
wScriptsFolder.setSimple(false);
wScriptsFolder.setUnselectedImageVisible(true);
wScriptsFolder.setUnselectedCloseVisible(true);
props.setLook(wScriptsFolder);
styleTabFolder(wScriptsFolder);
// confirms closing script tabs, and will never close the last one
wScriptsFolder.addCTabFolder2Listener(new CTabFolder2Adapter() {
public void close(CTabFolderEvent event) {
CTabItem cItem = (CTabItem) event.item;
event.doit = false;
if (cItem != null && wScriptsFolder.getItemCount() > 1) {
MessageBox messageBox = new MessageBox(shell, SWT.ICON_QUESTION | SWT.NO | SWT.YES);
messageBox.setText(BaseMessages.getString(PKG, "RubyStepDialog.DeleteItem.Label"));
messageBox.setMessage(BaseMessages.getString(PKG, "RubyStepDialog.ConfirmDeleteItem.Label", cItem.getText()));
switch (messageBox.open()) {
case SWT.YES:
event.doit = true;
input.setChanged();
changedInDialog = true;
break;
}
}
}
});
addScriptFolderDnD();
addScriptPopupMenu();
// toolbar below the script window
wScriptToolBar = new ToolBar(wTopRight, SWT.FLAT | SWT.RIGHT);
props.setLook(wScriptToolBar);
itemSettings = new ToolItem(wScriptToolBar, SWT.NONE);
itemSettings.setImage(scriptImage);
itemSettings.setText(BaseMessages.getString(PKG, "RubyStepDialog.AdvancedSettings.Label")); //$NON-NLS-1$
itemSettings.setEnabled(false);
itemSettings.addSelectionListener(new SelectionAdapter() {
@Override
// logic to display the advanced settings area
public void widgetSelected(SelectionEvent e) {
wTop.SASH_WIDTH = margin;
wTop.setWeights(new int[]{32, 68});
itemSettings.setEnabled(false);
}
});
ToolItem item = new ToolItem(wScriptToolBar, SWT.NONE);
item.setImage(checkImage);
item.setText(BaseMessages.getString(PKG, "RubyStepDialog.CheckSyntax.Label")); //$NON-NLS-1$
item.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
checkForParseErrors();
}
});
wScriptToolBar.pack();
// layout toolbar
FormData fdBar = new FormData();
fdBar.left = new FormAttachment(0, 0);
fdBar.bottom = new FormAttachment(100, 0);
wScriptToolBar.setLayoutData(fdBar);
// layout scripts folder
FormData fdFolder = new FormData();
fdFolder.left = new FormAttachment(0, 0);
fdFolder.right = new FormAttachment(100, 0);
fdFolder.top = new FormAttachment(0, 0);
fdFolder.bottom = new FormAttachment(wScriptToolBar, 0);
wScriptsFolder.setLayoutData(fdFolder);
// editing position label
wlEditingPosition = new Label(wTopRight, SWT.RIGHT);
wlEditingPosition.setText("0 : 0 ");
props.setLook(wlEditingPosition);
FormData fdPos = new FormData();
fdPos.left = new FormAttachment(100, -60);
fdPos.right = new FormAttachment(100, -margin);
fdPos.bottom = new FormAttachment(100, -margin + 1);
wlEditingPosition.setLayoutData(fdPos);
// syntax check result label
wlSyntaxCheck = new Label(wTopRight, SWT.LEFT);
wlSyntaxCheck.setText("");
FormData fdSyntaxCheck = new FormData();
fdSyntaxCheck.left = new FormAttachment(wScriptToolBar, margin);
fdSyntaxCheck.bottom = new FormAttachment(100, -margin + 1);
fdSyntaxCheck.right = new FormAttachment(wlEditingPosition, -margin);
wlSyntaxCheck.setLayoutData(fdSyntaxCheck);
props.setLook(wlSyntaxCheck);
}
private void addScriptFolderDnD() {
wScriptsFolder.addListener(SWT.DragDetect, new Listener() {
Display display = shell.getDisplay();
CTabFolder folder = wScriptsFolder;
Tracker t;
public void handleEvent(Event e) {
CTabItem dragItem = folder.getItem(folder.toControl(display.getCursorLocation()));
if (dragItem == null)
return;
// open a tracker with current item's bounds
t = new Tracker(folder, SWT.NONE);
Rectangle[] rects = {dragItem.getBounds()};
t.setRectangles(rects);
t.addListener(SWT.Move, new Listener() {
@Override
public void handleEvent(Event e) {
// when moving the tracker around, set the rectangles to whatever item we're hovering over. if hovering over nothing, no rectangles
Point p = new Point(e.x, e.y); // display coords
Point folderPoint = folder.toControl(p);
CTabItem hoverItem = folder.getItem(folderPoint);
if (hoverItem != null) {
t.setRectangles(new Rectangle[]{hoverItem.getBounds()});
} else {
t.setRectangles(new Rectangle[0]);
}
}
});
t.setCursor(display.getSystemCursor(SWT.CURSOR_HAND));
t.open();
// user finished dragging the tab around, let's drop it
Point folderPoint = folder.toControl(display.getCursorLocation());
CTabItem dropItem = folder.getItem(folderPoint);
if (dropItem == null || dropItem == dragItem) {
return;
}
// first find out where this is going
int idx = folder.indexOf(dropItem);
if (folder.indexOf(dragItem) < idx) {
idx++;
}
// make a copy of the item we're dragging around, as the original is going to be disposed of
CTabItem newItem = new CTabItem(folder, dragItem.getStyle(), idx);
newItem.setText(dragItem.getText());
newItem.setImage(dragItem.getImage());
Control c = dragItem.getControl();
dragItem.setControl(null);
newItem.setControl(c);
newItem.setData("role", dragItem.getData("role"));
dragItem.dispose();
folder.setSelection(newItem);
folder.redraw();
}
});
}
// Read data and place it in the dialog
public void getData() {
wStepname.selectAll();
// load the different scripts
for (RubyScriptMeta rubyScriptMeta : input.getScripts()) {
addScriptTab(rubyScriptMeta);
}
// load output fields
int rowNum = 0;
for (OutputFieldMeta outField : input.getOutputFields()) {
TableItem row = wFields.table.getItem(rowNum++);
row.setText(1, outField.getName());
row.setText(2, ValueMetaFactory.getValueMetaName(outField.getType()));
row.setText(3, outField.isUpdate() ? NO_YES[1] : NO_YES[0]);
}
wFields.optWidth(true);
wFields.setRowNums();
// load clear input fields flag
wClearInputFields.setSelection(input.isClearInputFields());
// load ruby vars
int varNum = 0;
for (RubyVariableMeta var : input.getRubyVariables()) {
TableItem row = wScopeVariables.table.getItem(varNum++);
row.setText(1, var.getName());
row.setText(2, var.getValue());
}
wScopeVariables.optWidth(true);
wScopeVariables.setRowNums();
// load info steps
int infoNum = 0;
for (RoleStepMeta step : input.getInfoSteps()) {
TableItem row = wInfoSteps.table.getItem(infoNum++);
row.setText(1, step.getRoleName());
row.setText(2, step.getStepName());
}
wInfoSteps.optWidth(true);
wInfoSteps.setRowNums();
// load target steps
int targetNum = 0;
for (RoleStepMeta step : input.getTargetSteps()) {
TableItem row = wTargetSteps.table.getItem(targetNum++);
row.setText(1, step.getRoleName());
row.setText(2, step.getStepName());
}
wTargetSteps.optWidth(true);
wTargetSteps.setRowNums();
}
private boolean cancel() {
if (changedInDialog) {
MessageBox box = new MessageBox(shell, SWT.YES | SWT.NO | SWT.APPLICATION_MODAL);
box.setText(BaseMessages.getString(PKG, "RubyStepDialog.WarningDialogChanged.Title"));
box.setMessage(BaseMessages.getString(PKG, "RubyStepDialog.WarningDialogChanged.Message", Const.CR));
int answer = box.open();
if (answer == SWT.NO) {
return false;
}
}
stepname = null;
input.setChanged(changed);
dispose();
return true;
}
// let the plugin know about the entered data
private void ok() {
// if there's syntax error, warn the user
if (!hasRowScript()) {
MessageBox box = new MessageBox(shell, SWT.YES | SWT.NO | SWT.APPLICATION_MODAL);
box.setText(BaseMessages.getString(PKG, "RubyStepDialog.WarningDialogNoRowScript.Title"));
box.setMessage(BaseMessages.getString(PKG, "RubyStepDialog.WarningDialogNoRowScript.Message", Const.CR));
int answer = box.open();
if (answer == SWT.NO) {
return;
}
}
stepname = wStepname.getText(); // return value
// generate scripts
List scripts = input.getScripts();
scripts.clear();
scripts.addAll(collectScripts());
// generate output fields
List outFields = input.getOutputFields();
outFields.clear();
int fieldCount = wFields.nrNonEmpty();
for (int i = 0; i < fieldCount; i++) {
TableItem t = wFields.getNonEmpty(i);
outFields.add(new OutputFieldMeta(t.getText(1), ValueMetaFactory.getIdForValueMeta(t.getText(2)), NO_YES[1].equalsIgnoreCase(t.getText(3))));
}
// save clear input fields flag
input.setClearInputFields(wClearInputFields.getSelection());
// generate ruby vars
List rubyVars = input.getRubyVariables();
rubyVars.clear();
int varCount = wScopeVariables.nrNonEmpty();
for (int i = 0; i < varCount; i++) {
TableItem t = wScopeVariables.getNonEmpty(i);
String varName = t.getText(1).trim();
if (!varName.startsWith("$")) {
varName = "$" + varName;
}
// replace white space with underscores
varName = varName.replaceAll("\\s", "_");
rubyVars.add(new RubyVariableMeta(varName, t.getText(2)));
}
// generate info steps
List infoSteps = input.getInfoSteps();
infoSteps.clear();
int infoCount = wInfoSteps.nrNonEmpty();
for (int i = 0; i < infoCount; i++) {
TableItem t = wInfoSteps.getNonEmpty(i);
infoSteps.add(new RoleStepMeta(t.getText(2), t.getText(1)));
}
// generate target steps
List targetSteps = input.getTargetSteps();
targetSteps.clear();
int targetCount = wTargetSteps.nrNonEmpty();
for (int i = 0; i < targetCount; i++) {
TableItem t = wTargetSteps.getNonEmpty(i);
targetSteps.add(new RoleStepMeta(t.getText(2), t.getText(1)));
}
// set gem home
input.setGemHome(wGemHome.getText());
// make sure the input finds its info and target step metas alright
input.searchInfoAndTargetSteps(transMeta.getSteps());
dispose();
}
private boolean hasRowScript() {
for (CTabItem item : wScriptsFolder.getItems()) {
if (item.getData("role") == RubyScriptMeta.Role.ROW_SCRIPT) {
return true;
}
}
return false;
}
private List collectScripts() {
List retval = new ArrayList(wScriptsFolder.getItemCount());
CTabItem[] items = wScriptsFolder.getItems();
for (int i = 0; i < items.length; i++) {
CTabItem item = items[i];
StyledTextComp wText = (StyledTextComp) item.getControl();
retval.add(new RubyScriptMeta(item.getText(), wText.getText(), (Role) item.getData("role")));
}
return retval;
}
private void addLeftArea() {
// top left composite
wTopLeft = new Composite(wTop, SWT.NONE);
FormLayout topLeftLayout = new FormLayout();
topLeftLayout.marginWidth = 0;
topLeftLayout.marginHeight = 0;
wTopLeft.setLayout(topLeftLayout);
props.setLook(wTopLeft);
// header line
// top left tab folder
wLeftFolder = new CTabFolder(wTopLeft, SWT.BORDER | SWT.RESIZE);
wLeftFolder.setSimple(false);
wLeftFolder.setUnselectedImageVisible(true);
wLeftFolder.setUnselectedCloseVisible(true);
wLeftFolder.setMaximizeVisible(false);
wLeftFolder.setMinimizeVisible(true);
props.setLook(wLeftFolder);
//styleTabFolder(wLeftFolder);
// implement minimize logic
wLeftFolder.addCTabFolder2Listener(new CTabFolder2Adapter() {
@Override
public void minimize(CTabFolderEvent e) {
itemSettings.setEnabled(true);
wTop.SASH_WIDTH = 0;
wTop.setWeights(new int[]{0, 100});
}
});
addFieldSummaryTab();
addSamplesTab();
// layout tab folder below the label
FormData fdLeftFolder = new FormData();
fdLeftFolder.left = new FormAttachment(0, 0);
fdLeftFolder.top = new FormAttachment(0, 0);
fdLeftFolder.right = new FormAttachment(100, 0);
fdLeftFolder.bottom = new FormAttachment(100, 0);
wLeftFolder.setLayoutData(fdLeftFolder);
// set selected item in tab
wLeftFolder.setSelection(0);
}
private void addSamplesTab() {
CTabItem samplesItem = new CTabItem(wLeftFolder, SWT.NONE);
samplesItem.setText(BaseMessages.getString(PKG, "RubyStepDialog.Samples.Label"));
Composite wPanel = new Composite(wLeftFolder, SWT.NONE);
wPanel.setLayout(new FillLayout());
props.setLook(wPanel);
wSamplesTree = new Tree(wPanel, SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI);
wSamplesTree.setLayout(new FillLayout());
wSamplesTree.setHeaderVisible(true);
props.setLook(wSamplesTree);
TreeColumn column1 = new TreeColumn(wSamplesTree, SWT.LEFT);
column1.setText(BaseMessages.getString(PKG, "RubyStepDialog.SampleTreeColumn.Sample"));
column1.setWidth(280);
TreeColumn column2 = new TreeColumn(wSamplesTree, SWT.LEFT);
column2.setText(BaseMessages.getString(PKG, "RubyStepDialog.SampleTreeColumn.Type"));
column2.setWidth(120);
File samplesDir = new File(pluginBaseFile.getAbsolutePath() + Const.FILE_SEPARATOR + "step" + Const.FILE_SEPARATOR + "samples");
TreeItem rootTreeItem = new TreeItem(wSamplesTree, SWT.NONE);
rootTreeItem.setText(new String[]{"samples", ""});
rootTreeItem.setImage(folderImage);
rootTreeItem.setData("type", SampleType.DIR);
rootTreeItem.setData("file", samplesDir);
samplesHelper.fillSamplesDir(rootTreeItem, samplesDir);
rootTreeItem.setExpanded(true);
samplesItem.setControl(wPanel);
wSamplesTree.addMouseListener(new MouseAdapter() {
public void mouseDoubleClick(MouseEvent e) {
if (e.button != 1)
return;
Point click = new Point(e.x, e.y);
TreeItem item = wSamplesTree.getItem(click);
if (item != null) {
openSample(item);
}
}
});
addSamplesMenu();
}
private void addSamplesMenu() {
sampleMenu = new Menu(shell, SWT.POP_UP);
showSampleItem = new MenuItem(sampleMenu, SWT.PUSH);
showSampleItem.setText(BaseMessages.getString(PKG, "RubyStepDialog.SamplesMenu.ShowSample"));
//showSampleItem.setImage(libScriptImage);
showSampleItem.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event e) {
for (TreeItem item : wSamplesTree.getSelection()) {
openSample(item);
}
}
});
// menu is about to show, let's enable/disable stuff
sampleMenu.addListener(SWT.Show, new Listener() {
@Override
public void handleEvent(Event e) {
showSampleItem.setEnabled(false);
// any non-folder selection enables the show sample
for (TreeItem item : wSamplesTree.getSelection()) {
switch ((SampleType) item.getData("type")) {
case TRANS:
case SCRIPT:
case WEB:
showSampleItem.setEnabled(true);
return;
}
}
}
});
wSamplesTree.setMenu(sampleMenu);
}
private void openSample(TreeItem item) {
File f = (File) item.getData("file");
if (f != null && f.isFile()) {
SampleType type = (SampleType) item.getData("type");
switch (type) {
case SCRIPT:
try {
// add a new sample script
String title = RubyScriptMeta.getUniqueName(item.getText(), collectScripts());
RubyScriptMeta script = new RubyScriptMeta(title, FileUtils.readFileToString(f, "UTF-8"), Role.LIB_SCRIPT);
addScriptTab(script);
wScriptsFolder.setSelection(wScriptsFolder.getItemCount() - 1); // select newest tab
input.setChanged();
changedInDialog = true;
} catch (IOException e1) {
e1.printStackTrace();
}
break;
case TRANS:
// load the file, but make it forget where it came from (prevents the original from be modified accidentally)
// File tmpFile = new File(System.getProperty("java.io.tmpdir") + Const.FILE_SEPARATOR + f.getName());
// FileUtils.copyFile(f, tmpFile);
// Spoon.getInstance().openFile(tmpFile.toString(), false);
Spoon.getInstance().openFile(f.toString(), false);
// assuming that the new one is the last one... a shame openFile does not return the opened TransMeta
TransMeta[] transForms = Spoon.getInstance().getLoadedTransformations();
TransMeta newOne = transForms[transForms.length - 1];
// make it a prestine transformation
newOne.setFilename(null);
newOne.setChanged();
if (changedInDialog) {
MessageBox messageBox = new MessageBox(shell, SWT.ICON_QUESTION | SWT.NO | SWT.YES);
messageBox.setText(BaseMessages.getString(PKG, "RubyStepDialog.OpenedSample.Title"));
messageBox.setMessage(BaseMessages.getString(PKG, "RubyStepDialog.OpenedSample.Message"));
if (messageBox.open() == SWT.YES) {
ok();
}
} else {
cancel();
}
break;
case WEB:
try {
BareBonesBrowserLaunch.openURL(f.toURI().toURL().toString());
} catch (MalformedURLException e) {
e.printStackTrace();
}
break;
}
}
}
private void styleTabFolder(CTabFolder folder) {
Display display = folder.getDisplay();
folder.setSelectionBackground(new Color[]{
display.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND),
display.getSystemColor(SWT.COLOR_TITLE_BACKGROUND_GRADIENT)
},
new int[]{75}, true);
folder.setBackground(display.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
}
private void addScriptPopupMenu() {
scriptMenu = new Menu(shell, SWT.POP_UP);
MenuItem addNewItem = new MenuItem(scriptMenu, SWT.PUSH);
addNewItem.setText(BaseMessages.getString(PKG, "RubyStepDialog.Menu.AddNewTab"));
addNewItem.setImage(addImage);
addNewItem.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event e) {
RubyScriptMeta script = RubyScriptMeta.createScriptWithUniqueName(collectScripts());
addScriptTab(script);
input.setChanged();
changedInDialog = true;
wScriptsFolder.setSelection(wScriptsFolder.getItemCount() - 1); // select newest tab
}
});
new MenuItem(scriptMenu, SWT.SEPARATOR);
renameItem = new MenuItem(scriptMenu, SWT.PUSH);
renameItem.setText(BaseMessages.getString(PKG, "RubyStepDialog.Menu.RenameScript"));
renameItem.setImage(renameImage);
renameItem.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event e) {
RubyStepRenameDialog d = new RubyStepRenameDialog(shell);
String newName = d.open(wScriptsFolder.getSelection().getText(), collectInactiveScriptNames());
if (newName != null) {
wScriptsFolder.getSelection().setText(newName);
input.setChanged();
changedInDialog = true;
}
}
});
new MenuItem(scriptMenu, SWT.SEPARATOR);
rowScriptItem = new MenuItem(scriptMenu, SWT.RADIO);
rowScriptItem.setText(BaseMessages.getString(PKG, "RubyStepDialog.Menu.RowScript"));
rowScriptItem.setImage(rowScriptImage);
rowScriptItem.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
MenuItem item = (MenuItem) e.widget;
if (item.getSelection()) {
setActiveTabRowScript();
}
}
});
libScriptItem = new MenuItem(scriptMenu, SWT.RADIO);
libScriptItem.setText(BaseMessages.getString(PKG, "RubyStepDialog.Menu.LibScript"));
libScriptItem.setImage(libScriptImage);
libScriptItem.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
MenuItem item = (MenuItem) e.widget;
if (item.getSelection()) {
setActiveTabLibScript();
}
}
});
initScriptItem = new MenuItem(scriptMenu, SWT.RADIO);
initScriptItem.setText(BaseMessages.getString(PKG, "RubyStepDialog.Menu.InitScript"));
initScriptItem.setImage(initScriptImage);
initScriptItem.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
MenuItem item = (MenuItem) e.widget;
if (item.getSelection()) {
setActiveTabInitScript();
}
}
});
disposeScriptItem = new MenuItem(scriptMenu, SWT.RADIO);
disposeScriptItem.setText(BaseMessages.getString(PKG, "RubyStepDialog.Menu.DisposeScript"));
disposeScriptItem.setImage(disposeScriptImage);
disposeScriptItem.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
MenuItem item = (MenuItem) e.widget;
if (item.getSelection()) {
setActiveTabDisposeScript();
}
}
});
wScriptsFolder.setMenu(scriptMenu);
// menu is about to show, let's enable/disable stuff
scriptMenu.addListener(SWT.Show, new Listener() {
@Override
public void handleEvent(Event e) {
// set the label on the rename item
renameItem.setText(BaseMessages.getString(PKG, "RubyStepDialog.Menu.RenameScript", wScriptsFolder.getSelection().getText()));
// set selection for the correct role
rowScriptItem.setSelection(false);
libScriptItem.setSelection(false);
initScriptItem.setSelection(false);
disposeScriptItem.setSelection(false);
switch ((Role) wScriptsFolder.getSelection().getData("role")) {
case LIB_SCRIPT:
libScriptItem.setSelection(true);
break;
case ROW_SCRIPT:
rowScriptItem.setSelection(true);
break;
case INIT_SCRIPT:
initScriptItem.setSelection(true);
break;
case DISPOSE_SCRIPT:
disposeScriptItem.setSelection(true);
break;
}
}
});
}
protected void setActiveTabRowScript() {
CTabItem[] items = wScriptsFolder.getItems();
for (int i = 0; i < items.length; i++) {
if (i != wScriptsFolder.getSelectionIndex() && items[i].getData("role") == Role.ROW_SCRIPT) {
// the old script gets its row script status revoked, simply replaced with lib
items[i].setData("role", Role.LIB_SCRIPT);
items[i].setImage(libScriptImage);
}
}
wScriptsFolder.getSelection().setData("role", Role.ROW_SCRIPT);
wScriptsFolder.getSelection().setImage(rowScriptImage);
input.setChanged();
changedInDialog = true;
}
protected void setActiveTabInitScript() {
CTabItem[] items = wScriptsFolder.getItems();
for (int i = 0; i < items.length; i++) {
if (i != wScriptsFolder.getSelectionIndex() && items[i].getData("role") == Role.INIT_SCRIPT) {
// the old script gets its init script status revoked, simply replaced with lib
items[i].setData("role", Role.LIB_SCRIPT);
items[i].setImage(libScriptImage);
}
}
wScriptsFolder.getSelection().setData("role", Role.INIT_SCRIPT);
wScriptsFolder.getSelection().setImage(initScriptImage);
input.setChanged();
changedInDialog = true;
}
protected void setActiveTabDisposeScript() {
CTabItem[] items = wScriptsFolder.getItems();
for (int i = 0; i < items.length; i++) {
if (i != wScriptsFolder.getSelectionIndex() && items[i].getData("role") == Role.DISPOSE_SCRIPT) {
// the old script gets its dispose script status revoked, simply replaced with lib
items[i].setData("role", Role.LIB_SCRIPT);
items[i].setImage(libScriptImage);
}
}
wScriptsFolder.getSelection().setData("role", Role.DISPOSE_SCRIPT);
wScriptsFolder.getSelection().setImage(disposeScriptImage);
input.setChanged();
changedInDialog = true;
}
protected void setActiveTabLibScript() {
wScriptsFolder.getSelection().setData("role", Role.LIB_SCRIPT);
wScriptsFolder.getSelection().setImage(libScriptImage);
input.setChanged();
changedInDialog = true;
}
protected List collectInactiveScriptNames() {
List retval = new ArrayList(wScriptsFolder.getItemCount());
CTabItem[] items = wScriptsFolder.getItems();
for (int i = 0; i < items.length; i++) {
if (i != wScriptsFolder.getSelectionIndex()) {
retval.add(items[i].getText());
}
}
return retval;
}
private void addScriptTab(RubyScriptMeta script) {
CTabItem item = new CTabItem(wScriptsFolder, SWT.CLOSE);
item.setText(script.getTitle());
switch (script.getRole()) {
case DISPOSE_SCRIPT:
item.setImage(disposeScriptImage);
break;
case INIT_SCRIPT:
item.setImage(initScriptImage);
break;
case LIB_SCRIPT:
item.setImage(libScriptImage);
break;
case ROW_SCRIPT:
item.setImage(rowScriptImage);
break;
}
item.setData("role", script.getRole());
StyledTextComp wScript = new StyledTextComp(transMeta, item.getParent(), SWT.MULTI | SWT.LEFT | SWT.H_SCROLL | SWT.V_SCROLL, script.getTitle(), false);
wScript.setText(script.getScript());
props.setLook(wScript, Props.WIDGET_STYLE_FIXED);
wScript.addModifyListener(lsMod);
item.setControl(wScript);
wScript.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
hideParseErrors();
highlightSyntax();
}
});
wScript.addListener(SWT.Show, new Listener() {
@Override
public void handleEvent(Event e) {
highlightSyntax();
hideParseErrors();
}
}
);
wScript.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
updateEditingPosition();
}
public void keyReleased(KeyEvent e) {
updateEditingPosition();
}
});
wScript.addFocusListener(new FocusAdapter() {
public void focusGained(FocusEvent e) {
updateEditingPosition();
}
public void focusLost(FocusEvent e) {
updateEditingPosition();
}
});
wScript.addMouseListener(new MouseAdapter() {
public void mouseDoubleClick(MouseEvent e) {
updateEditingPosition();
}
public void mouseDown(MouseEvent e) {
updateEditingPosition();
}
public void mouseUp(MouseEvent e) {
updateEditingPosition();
}
});
wScript.getStyledText().addMouseTrackListener(new MouseTrackListener() {
@Override
public void mouseHover(MouseEvent e) {
updateErrorToolTip(e.x, e.y);
}
@Override
public void mouseExit(MouseEvent arg0) {
}
@Override
public void mouseEnter(MouseEvent arg0) {
}
});
}
protected void updateErrorToolTip(int x, int y) {
CTabItem item = wScriptsFolder.getSelection();
StyledTextComp wText = (StyledTextComp) item.getControl();
parseErrorHelper.updateErrorToolTip(wText, x, y);
}
private void updateEditingPosition() {
CTabItem item = wScriptsFolder.getSelection();
StyledTextComp wText = (StyledTextComp) item.getControl();
// calculate line and col
int caret = wText.getCaretOffset();
int line = wText.getLineAtOffset(caret) + 1;
int col = 1;
String txt = wText.getText();
caret -= 1;
while (caret >= 0) {
if (txt.charAt(caret) != '\n' && txt.charAt(caret) != '\r') {
caret--;
col++;
} else {
break;
}
}
wlEditingPosition.setText("" + line + " : " + col);
}
private void highlightSyntax() {
CTabItem item = wScriptsFolder.getSelection();
StyledTextComp wText = (StyledTextComp) item.getControl();
syntaxHighlighter.highlight(item.getText(), wText);
}
private boolean checkForParseErrors() {
boolean hasErrors = false;
for (CTabItem item : wScriptsFolder.getItems()) {
StyledTextComp wText = (StyledTextComp) item.getControl();
if (parseErrorHelper.hasParseErrors(wText)) {
wScriptsFolder.setSelection(item);
parseErrorHelper.showParseErrors(wText, wlSyntaxCheck);
hasErrors = true;
break;
}
}
if (!hasErrors) {
wlSyntaxCheck.setText("OK");
}
return !hasErrors;
}
private void hideParseErrors() {
CTabItem item = wScriptsFolder.getSelection();
StyledTextComp wText = (StyledTextComp) item.getControl();
parseErrorHelper.hideParseErrors(wText, wlSyntaxCheck);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy