/** * Copyright 2009 Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.safehaus.penrose.studio.views; import java.util.ArrayList; import java.util.Iterator; import java.util.Collection; import org.eclipse.swt.SWT; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.events.ShellAdapter; import org.eclipse.swt.events.ShellEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableItem; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.forms.events.ExpansionAdapter; import org.eclipse.ui.forms.events.ExpansionEvent; import org.eclipse.ui.forms.widgets.Section; import org.eclipse.ui.forms.widgets.TableWrapData; import org.eclipse.ui.forms.widgets.TableWrapLayout; import org.safehaus.penrose.mapping.*; import org.safehaus.penrose.studio.PenroseStudio; import org.safehaus.penrose.studio.PenroseImage; import org.safehaus.penrose.studio.util.Pair; import org.safehaus.penrose.partition.PartitionConfig; import org.safehaus.penrose.source.SourceConfig; import org.safehaus.penrose.source.FieldConfig; import org.safehaus.penrose.directory.EntryConfig; import org.safehaus.penrose.directory.EntryAttributeConfig; import org.safehaus.penrose.directory.EntryFieldConfig; import org.safehaus.penrose.directory.EntrySourceConfig; import org.apache.log4j.Logger; public class ExpressionEditorDialog extends BaseDialog { Logger log = Logger.getLogger(getClass()); Object obj; int type = EXPRESSION; Text name; Text expression; Button saveButton; public final static int NAME_VALUE = 1; public final static int EXPRESSION = 2; NameChecker nameChecker; Shell codeAssistShell; boolean ctrlPressed; private EntryConfig entry; public ExpressionEditorDialog(Shell parent, Object obj, String shellTitle, String formTitle) { super(parent); this.obj = obj; // if (obj instanceof EntryFieldConfig) { type = EXPRESSION; } else if (obj instanceof EntryAttributeConfig) { type = EXPRESSION; } else if (obj instanceof Pair) { type = NAME_VALUE; } // Layout TableWrapLayout layout = new TableWrapLayout(); form.getBody().setLayout(layout); // Title shell.setText(shellTitle); form.setText(formTitle); // Sections createExpressionSection(new TableWrapData(TableWrapData.FILL_GRAB, TableWrapData.TOP)); createFootSection(new TableWrapData(TableWrapData.FILL_GRAB, TableWrapData.TOP)); // Prepopulate if (obj != null) { load(obj); } } public void load(Object obj) { if (obj == null) return; if (obj instanceof EntryFieldConfig) { EntryFieldConfig field = (EntryFieldConfig) obj; if (field.getExpression() != null) expression.setText(field.getExpression().getScript()); } else if (obj instanceof EntryAttributeConfig) { EntryAttributeConfig attr = (EntryAttributeConfig) obj; if (attr.getExpression() != null) expression.setText(attr.getExpression().getScript()); } else if (obj instanceof Pair) { Pair pair = (Pair) obj; if (pair.getName() != null) name.setText(pair.getName()); if (pair.getValue() != null) expression.setText(pair.getValue()); } } public void store(Object obj) { PenroseStudio penroseStudio = PenroseStudio.getInstance(); penroseStudio.setDirty(true); if (obj instanceof EntryFieldConfig) { String s = expression.getText().trim(); if (s.equals("")) s = null; EntryFieldConfig field = (EntryFieldConfig) obj; Expression exp = new Expression(); exp.setScript(s); field.setExpression(exp); } else if (obj instanceof EntryAttributeConfig) { EntryAttributeConfig attr = (EntryAttributeConfig) obj; attr.getExpression().setScript(expression.getText()); } else if (obj instanceof Pair) { Pair pair = (Pair) obj; pair.setName(name.getText()); pair.setValue(expression.getText()); } } /** * "Modules" Section */ public Section createExpressionSection(TableWrapData layoutData) { Section section = toolkit.createSection(form.getBody(), Section.DESCRIPTION | Section.EXPANDED); section.setLayoutData(layoutData); section.addExpansionListener(new ExpansionAdapter() { public void expansionStateChanged(ExpansionEvent e) { form.reflow(true); } }); if (type == NAME_VALUE) { section.setDescription("Edit the value below."); } else if (type == EXPRESSION) { section.setDescription("Edit the value or BeanShell (Java-like) expression below."); } else { section.setDescription(""); } // Section Client Composite sectionClient = toolkit.createComposite(section); sectionClient.setLayoutData(new TableWrapData(TableWrapData.FILL, TableWrapData.FILL)); TableWrapLayout sectionLayout = new TableWrapLayout(); sectionLayout.numColumns = 2; sectionClient.setLayout(sectionLayout); // Name: if (type == NAME_VALUE) { toolkit.createLabel(sectionClient, "Name:"); name = toolkit.createText(sectionClient, "", SWT.BORDER); name.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB, TableWrapData.FILL_GRAB, 1, 1)); name.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { if (nameChecker == null) return; String errorMessage = nameChecker.checkName(name.getText()); if (errorMessage != null) { name.setForeground(shell.getDisplay().getSystemColor(SWT.COLOR_RED)); name.setBackground(shell.getDisplay().getSystemColor(SWT.COLOR_YELLOW)); name.setToolTipText(errorMessage); saveButton.setEnabled(false); } else { name.setForeground(shell.getDisplay().getSystemColor(SWT.COLOR_LIST_FOREGROUND)); name.setBackground(shell.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND)); name.setToolTipText(errorMessage); saveButton.setEnabled(true); } } }); } // Value/Expression: if (type == NAME_VALUE) { Label label = toolkit.createLabel(sectionClient, "Value:"); label.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB, TableWrapData.FILL_GRAB, 1, 2)); } else if (type == EXPRESSION) { Label label = toolkit.createLabel(sectionClient, "Value or Expression: (use CTRL-Space for code assist/completion)"); label.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB, TableWrapData.FILL_GRAB, 1, 2)); } // (text) TableWrapData twd = new TableWrapData(TableWrapData.FILL_GRAB, TableWrapData.FILL_GRAB, 1, 2); twd.heightHint = 300; expression = toolkit.createText(sectionClient, "", SWT.BORDER | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); expression.setLayoutData(twd); expression.addKeyListener(new KeyListener() { public void keyPressed(KeyEvent e) { switch (e.keyCode) { case SWT.CTRL: ctrlPressed = true; break; case ' ': if (ctrlPressed) { e.doit = false; CodeAssist codeAssist = new CodeAssist(); codeAssist.open(); } } } public void keyReleased(KeyEvent e) { switch (e.keyCode) { case SWT.CTRL: ctrlPressed = false; break; } } }); // end section.setClient(sectionClient); return section; } /** * "Foot" Section */ public Section createFootSection(TableWrapData layoutData) { Section section = toolkit.createSection(form.getBody(), Section.EXPANDED); section.setLayoutData(layoutData); section.addExpansionListener(new ExpansionAdapter() { public void expansionStateChanged(ExpansionEvent e) { form.reflow(true); } }); Composite sectionClient = toolkit.createComposite(section); TableWrapLayout sectionLayout = new TableWrapLayout(); sectionLayout.numColumns = 2; sectionClient.setLayout(sectionLayout); // [Save] saveButton = new Button(sectionClient, SWT.PUSH); saveButton.setText("Save"); saveButton.addSelectionListener(new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { } public void widgetSelected(SelectionEvent e) { try { store(obj); shell.close(); } catch (Exception ex) { log.debug(ex.getMessage(), ex); } } }); // [Cancel] Button cancelButton = new Button(sectionClient, SWT.PUSH); cancelButton.setText("Cancel"); cancelButton.addSelectionListener(new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { } public void widgetSelected(SelectionEvent e) { shell.close(); } }); // end section.setClient(sectionClient); return section; } public void setNameChecker(NameChecker nameChecker) { this.nameChecker = nameChecker; } public Object getObject() { return obj; } public interface NameChecker { public String checkName(String name); } class CodeAssist { Table myTable; ArrayList hints; public CodeAssist() { Point location = expression.getCaretLocation(); for (Control c=expression; c != null; c=c.getParent()) { location = add(location, c.getLocation()); if (c instanceof Shell) break; } if (codeAssistShell == null || codeAssistShell.isDisposed()) { codeAssistShell = new Shell(shell, SWT.RESIZE); codeAssistShell.setBackground(shell.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND)); codeAssistShell.setLayout(new FillLayout()); codeAssistShell.addShellListener(new ShellAdapter() { public void shellDeactivated(ShellEvent e) { codeAssistShell.dispose(); } }); myTable = new Table(codeAssistShell, SWT.H_SCROLL | SWT.V_SCROLL); myTable.addKeyListener(new KeyListener() { public void keyPressed(KeyEvent e) { switch (e.keyCode) { case SWT.CTRL: ctrlPressed = true; break; } } public void keyReleased(KeyEvent e) { switch (e.keyCode) { case SWT.CR: // add selected item to expression at caret location if (myTable.getSelectionCount() > 0) { String s = myTable.getSelection()[0].getText(); expression.insert(s); codeAssistShell.dispose(); } break; case SWT.CTRL: ctrlPressed = false; break; } } }); } location = add(location, new Point(10, 42)); codeAssistShell.setSize(200, 200); codeAssistShell.setLocation(location); codeAssistShell.open(); populateTable(); } void populateTable() { // populate code assist table myTable.removeAll(); populateHints(); } void populateHints() { if (entry == null) return; // add all sources Collection sources = entry.getSourceConfigs(); for (Iterator i=sources.iterator(); i.hasNext(); ) { EntrySourceConfig source = (EntrySourceConfig)i.next(); PartitionConfig partitionConfig = null; //partition.getPartitionConfig(); SourceConfig sourceConfig = partitionConfig.getSourceConfigManager().getSourceConfig(source.getSourceName()); Object[] fields = sourceConfig.getFieldConfigs().toArray(); Image icon = PenroseStudio.getImage(PenroseImage.SOURCE); for (int j=0; j<fields.length; j++) { FieldConfig field = (FieldConfig) fields[j]; addHint(icon, source.getAlias()+"."+field.getName()); } } // add all attributes Object[] attributes = entry.getAttributeConfigs().toArray(); for (int i=0; i<attributes.length; i++) { EntryAttributeConfig attribute = (EntryAttributeConfig) attributes[i]; addHint(PenroseStudio.getImage(PenroseImage.NOKEY), attribute.getName()); } } public void open() { codeAssistShell.open(); } public void addHint(Image icon, String text) { TableItem item = new TableItem(myTable, SWT.NONE); item.setText(text); item.setImage(icon); } } Point add(Point a, Point b) { return new Point(a.x + b.x, a.y + b.y); } public EntryConfig getEntry() { return entry; } public void setEntry(EntryConfig entry) { this.entry = entry; } }