/*
* ====================================================================
*
* The ObjectStyle Group Software License, Version 1.0
*
* Copyright (c) 2005 The ObjectStyle Group and individual authors of the
* software. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The end-user documentation included with the redistribution, if any, must
* include the following acknowlegement: "This product includes software
* developed by the ObjectStyle Group (http://objectstyle.org/)." Alternately,
* this acknowlegement may appear in the software itself, if and wherever such
* third-party acknowlegements normally appear.
*
* 4. The names "ObjectStyle Group" and "Cayenne" must not be used to endorse or
* promote products derived from this software without prior written permission.
* For written permission, please contact andrus@objectstyle.org.
*
* 5. Products derived from this software may not be called "ObjectStyle" nor
* may "ObjectStyle" appear in their names without prior written permission of
* the ObjectStyle Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* OBJECTSTYLE GROUP OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many individuals on
* behalf of the ObjectStyle Group. For more information on the ObjectStyle
* Group, please see <http://objectstyle.org/>.
*
*/
package org.objectstyle.wolips.ruleeditor.editor;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.TableEditor;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.objectstyle.wolips.ruleeditor.filter.RulesFilter;
import org.objectstyle.wolips.ruleeditor.listener.FilterListener;
import org.objectstyle.wolips.ruleeditor.listener.NumberVerifyListener;
import org.objectstyle.wolips.ruleeditor.listener.TableSortSelectionListener;
import org.objectstyle.wolips.ruleeditor.model.D2WModel;
import org.objectstyle.wolips.ruleeditor.model.LeftHandSide;
import org.objectstyle.wolips.ruleeditor.model.RightHandSide;
import org.objectstyle.wolips.ruleeditor.model.Rule;
import org.objectstyle.wolips.ruleeditor.provider.TableContentProvider;
import org.objectstyle.wolips.ruleeditor.provider.TableLabelProvider;
import org.objectstyle.wolips.ruleeditor.sorter.AbstractInvertableTableSorter;
import org.objectstyle.wolips.ruleeditor.sorter.TextSorter;
/**
* The UI class for the rule editor.
*
* @author uli
* @author <a href="mailto:frederico@moleque.com.br">Frederico Lellis</a>
* @author <a href="mailto:georg@moleque.com.br">Georg von Bülow</a>
*/
public class RuleEditor {
public static TableSortSelectionListener createTableColumn(final TableViewer viewer, final String text, final String tooltip, final AbstractInvertableTableSorter sorter, final int initialDirection, final boolean keepDirection) {
TableColumn column = new TableColumn(viewer.getTable(), SWT.LEFT);
column.setText(text);
column.setToolTipText(tooltip);
return new TableSortSelectionListener(viewer, column, sorter, initialDirection, keepDirection);
}
private Text classtext;
private Text lhstext;
private D2WModel model;
private Text prioritytext;
private Text rhstext;
private Rule rule;
private Table table;
private TableViewer tableViewer;
protected boolean updating;
private Text valuetext;
/**
* Creates the main window's contents
*
* @param shell
* the main window
*/
public void createContents(final Composite parent) {
Composite container = new Composite(parent, SWT.NONE);
GridLayout layout1 = new GridLayout();
layout1.numColumns = 2;
layout1.makeColumnsEqualWidth = true;
container.setLayout(layout1);
// Create Button Group
GridData buttondata = new GridData();
buttondata.grabExcessHorizontalSpace = true;
buttondata.horizontalAlignment = GridData.FILL;
buttondata.verticalAlignment = GridData.CENTER;
RowLayout buttonlayout = new RowLayout();
buttonlayout.fill = true;
Group buttongroup = new Group(container, SWT.NONE);
buttongroup.setLayout(buttonlayout);
buttongroup.setLayoutData(buttondata);
final Button newrulebutton = new Button(buttongroup, SWT.PUSH);
newrulebutton.setText("New Rule");
newrulebutton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent event) {
rule = model.createEmptyRule();
updateRules();
table.select(table.getItemCount());
updating = false;
updateBottomDisplay();
}
});
final Button deletebutton = new Button(buttongroup, SWT.PUSH);
deletebutton.setText("Delete Rule");
deletebutton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent event) {
model.removeRule(selectedRule());
rule = null;
tableViewer.refresh();
updateRules();
updateBottomDisplay();
}
});
final Button duplicateButton = new Button(buttongroup, SWT.PUSH);
duplicateButton.setText("Duplicate");
duplicateButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent event) {
Rule ruleToCopy = (Rule) tableViewer.getElementAt(table.getSelectionIndex());
model.copyRule(ruleToCopy);
updateRules();
updateBottomDisplay();
}
});
// Search field
GridData searchdata = new GridData();
searchdata.grabExcessHorizontalSpace = true;
searchdata.verticalAlignment = GridData.CENTER;
searchdata.horizontalAlignment = GridData.FILL;
final Text searchtext = new Text(container, SWT.BORDER);
// text.setBounds(100, 50, 70, 20);
// text.setSize(50, 50);
searchtext.setLayoutData(searchdata);
searchtext.setText("Use this field to search any term");
searchtext.addFocusListener(new FocusAdapter() {
@Override
public void focusGained(final FocusEvent event) {
if (searchtext.getText().equals("Use this field to search any term")) {
searchtext.setText("");
}
}
});
searchtext.addListener(SWT.DefaultSelection, new Listener() {
public void handleEvent(final Event e) {
for (ViewerFilter filter : tableViewer.getFilters()) {
tableViewer.removeFilter(filter);
}
String regex = (searchtext.getText());
if (regex != null && !regex.equals("")) {
tableViewer.addFilter(new RulesFilter(regex));
}
}
});
GridData tabledata = new GridData(GridData.FILL_BOTH);
tabledata.horizontalSpan = 2;
tabledata.verticalAlignment = GridData.FILL;
tabledata.horizontalAlignment = GridData.FILL;
tabledata.grabExcessHorizontalSpace = true;
tabledata.grabExcessVerticalSpace = true;
// table = new Table(shell, SWT.SINGLE | SWT.FULL_SELECTION);
table = new Table(container, SWT.MULTI | SWT.FULL_SELECTION);
table.setHeaderVisible(true);
table.setLinesVisible(true);
table.setLayoutData(tabledata);
// Create the TableViewer to hold content and do update
tableViewer = new TableViewer(table);
tableViewer.setContentProvider(new TableContentProvider());
tableViewer.setLabelProvider(new TableLabelProvider());
tableViewer.setInput(model);
searchtext.addModifyListener(new FilterListener(tableViewer));
// Create an editor object to use for text editing
final TableEditor editor = new TableEditor(table);
editor.horizontalAlignment = SWT.LEFT;
editor.grabHorizontal = true;
// Use a mouse listener, not a selection listener, since we're
// interested
// in the selected column as well as row
table.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
rule = (Rule) tableViewer.getElementAt(table.getSelectionIndex());
updating = true;
updateBottomDisplay();
}
});
/*
* table.addMouseListener(new MouseAdapter() { TableItem item; int
* column = -1; public void mouseDown(MouseEvent event) { // Determine
* where the mouse was clicked Point pt = new Point(event.x, event.y); //
* Determine which row was selected item = table.getItem(pt); if (item !=
* null) { // Determine which column was selected for (int i = 0, n =
* table.getColumnCount(); i < n; i++) { Rectangle rect =
* item.getBounds(i); if (rect.contains(pt)) { // This is the selected
* column column = i; break; } } rule = (ERD2WExtendedRule)
* item.getData("rule"); if (rule.lhs() == null) lhstext.setText("");
* else lhstext.setText(rule.lhs().toString());
* classtext.setText(rule.assignmentClassName());
* rhstext.setText(rule.rhsKeyPath()); if (rule.rhs().value() == null)
* valuetext.setText(""); else
* valuetext.setText(rule.rhs().value().toString());
* prioritytext.setText((Integer.valueOf(rule.author())).toString()); } }
* public void mouseDoubleClick(MouseEvent event) { // Dispose any
* existing editor Control old = editor.getEditor(); if (old != null)
* old.dispose(); if (item != null) { // Create the Text object for our
* editor final Text edittabletext = new Text(table, SWT.NONE);
* edittabletext.setForeground(item.getForeground()); // Transfer any
* text from the cell to the Text control, // set the color to match
* this row, select the text, // and set focus to the control
* edittabletext.setText(item.getText(column));
* edittabletext.setForeground(item.getForeground());
* edittabletext.selectAll(); edittabletext.setFocus(); // Recalculate
* the minimum width for the editor editor.minimumWidth =
* edittabletext.getBounds().width; // Set the control into the editor
* editor.setEditor(edittabletext, item, column); // Add a handler to
* transfer the text back to the cell // any time it's modified final
* int col = column; edittabletext.addFocusListener(new FocusAdapter() {
* public void focusLost(FocusEvent event) { if (col == 0) //LHS
* setLHSKeyPath(edittabletext.getText()); else if (col == 1) { //RHS
* Key setRHSKeyPath(edittabletext.getText()); } else if (col == 2) {
* //RHS Value setRHSValue(edittabletext.getText()); } else if (col ==
* 3) { //Priority setPriority(edittabletext.getText()); } Control old =
* editor.getEditor(); if (old != null) old.dispose(); } }); } } });
*/
// Create the columns
RuleEditor.createTableColumn(tableViewer, "Lhs", "Left Hand Side", new TextSorter(0), SWT.DOWN, true).chooseColumnForSorting();
RuleEditor.createTableColumn(tableViewer, "Rhs Key", "Right Hand Side Key", new TextSorter(1), SWT.UP, false);
RuleEditor.createTableColumn(tableViewer, "Rhs Value", "Right Hand Side Value", new TextSorter(2), SWT.UP, false);
RuleEditor.createTableColumn(tableViewer, "Priority", "Priority", new TextSorter(3), SWT.UP, false);
// TableColumn c1 = new TableColumn(table, SWT.LEFT, 0);
// c1.setText("Lhs");
// c1.pack();
// TableColumn c2 = new TableColumn(table, SWT.LEFT, 1);
// c2.setText("Rhs Key");
// c2.pack();
// TableColumn c3 = new TableColumn(table, SWT.LEFT, 2);
// c3.setText("Rhs Value");
// c3.pack();
// TableColumn c4 = new TableColumn(table, SWT.RIGHT, 3);
// c4.setText("Priority");
// c4.pack();
table.addControlListener(new ControlAdapter() {
@Override
public void controlResized(final ControlEvent e) {
if (table.getColumnCount() < 2) {
return;
}
int tblWidth = table.getBounds().width;
int t0w = (int) (tblWidth * 0.4);
int t1w = (int) (tblWidth * 0.2);
int t2w = (int) (tblWidth * 0.3);
int t3w = tblWidth - (t0w + t1w + t2w + 40);
table.getColumn(0).setWidth(t0w);
table.getColumn(1).setWidth(t1w);
table.getColumn(2).setWidth(t2w);
table.getColumn(3).setWidth(t3w);
}
});
// Create LHS segment
GridData lhsdata = new GridData();
lhsdata.horizontalAlignment = GridData.FILL;
lhsdata.grabExcessHorizontalSpace = true;
lhsdata.verticalAlignment = GridData.FILL;
Group lhsgroup = new Group(container, SWT.NONE);
lhsgroup.setText("Left-Hand Side");
lhsgroup.setLayout(new FillLayout());
lhsgroup.setLayoutData(lhsdata);
lhstext = new Text(lhsgroup, SWT.BORDER | SWT.MULTI | SWT.WRAP);
lhstext.addFocusListener(new FocusAdapter() {
@Override
public void focusLost(final FocusEvent event) {
try {
if (lhstext.getText() != "") {
setLhsConditions(lhstext.getText());
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
lhstext.addFocusListener(new FocusAdapter() {
@Override
public void focusGained(final FocusEvent event) {
if (LeftHandSide.EMPTY_LHS_VALUE.equals(lhstext.getText())) {
lhstext.setText("");
}
}
});
// Create RHS segment
GridData rhsdata = new GridData();
rhsdata.horizontalAlignment = GridData.FILL;
rhsdata.grabExcessHorizontalSpace = true;
rhsdata.verticalAlignment = GridData.FILL;
GridLayout rhslayout = new GridLayout();
rhslayout.numColumns = 4;
rhslayout.makeColumnsEqualWidth = false;
GridData textdata = new GridData();
textdata.grabExcessHorizontalSpace = true;
textdata.verticalAlignment = GridData.CENTER;
textdata.horizontalSpan = 3;
textdata.horizontalAlignment = GridData.FILL;
Group rhsgroup = new Group(container, SWT.NONE);
rhsgroup.setText("Right-Hand Side");
rhsgroup.setLayout(rhslayout);
rhsgroup.setLayoutData(rhsdata);
Label classlabel = new Label(rhsgroup, SWT.NONE);
classlabel.setText("Class:");
classtext = new Text(rhsgroup, SWT.BORDER);
classtext.setLayoutData(textdata);
classtext.addFocusListener(new FocusAdapter() {
@Override
public void focusLost(final FocusEvent event) {
setClassName(classtext.getText());
}
});
Label keylabel = new Label(rhsgroup, SWT.NONE);
keylabel.setText("Key:");
rhstext = new Text(rhsgroup, SWT.BORDER);
rhstext.addFocusListener(new FocusAdapter() {
@Override
public void focusLost(final FocusEvent event) {
setRHSKeyPath(rhstext.getText());
}
});
GridData keydata = new GridData();
keydata.grabExcessHorizontalSpace = true;
keydata.verticalAlignment = GridData.CENTER;
keydata.horizontalAlignment = GridData.FILL;
keydata.minimumWidth = 180;
rhstext.setLayoutData(keydata);
Label prioritylabel = new Label(rhsgroup, SWT.NONE);
prioritylabel.setText("Priority:");
prioritytext = new Text(rhsgroup, SWT.BORDER);
GridData prioritydata = new GridData();
prioritydata.grabExcessHorizontalSpace = true;
prioritydata.verticalAlignment = GridData.CENTER;
prioritydata.horizontalAlignment = GridData.FILL;
prioritydata.minimumWidth = 50;
prioritytext.setLayoutData(prioritydata);
prioritytext.addVerifyListener(new NumberVerifyListener());
prioritytext.addFocusListener(new FocusAdapter() {
@Override
public void focusLost(final FocusEvent event) {
setPriority(prioritytext.getText());
}
});
Label valuelabel = new Label(rhsgroup, SWT.NONE);
valuelabel.setText("Value:");
valuetext = new Text(rhsgroup, SWT.BORDER | SWT.MULTI | SWT.WRAP);
GridData valuedata = new GridData(GridData.FILL_BOTH);
valuedata.grabExcessHorizontalSpace = true;
valuedata.grabExcessVerticalSpace = true;
// valuedata.minimumWidth = 150;
valuedata.minimumHeight = 150;
valuedata.horizontalSpan = 3;
valuedata.verticalSpan = 3;
valuetext.setLayoutData(valuedata);
valuetext.addFocusListener(new FocusAdapter() {
@Override
public void focusLost(final FocusEvent event) {
setRHSValue(valuetext.getText());
}
});
updateRules();
}
public Rule selectedRule() {
return (Rule) tableViewer.getElementAt(table.getSelectionIndex());
}
void setClassName(final String classname) {
rule.setAssignmentClassName(classname);
updateRules();
}
public void setD2WModel(final D2WModel model) {
this.model = model;
updateRules();
}
public void setFocus() {
// DO NOTHING
}
void setLhsConditions(final String conditions) {
rule.getLeftHandSide().setConditions(conditions);
updateRules();
}
void setPriority(final String priority) {
rule.setAuthor(priority);
updateRules();
}
void setRHSKeyPath(final String keypath) {
rule.getRightHandSide().setKeyPath(keypath);
updateRules();
}
void setRHSValue(final String value) {
rule.getRightHandSide().setValue(value);
updateRules();
}
void updateBottomDisplay() {
if (rule != null) {
LeftHandSide lhs = rule.getLeftHandSide();
lhstext.setText(lhs.toString());
RightHandSide rhs = rule.getRightHandSide();
classtext.setText(rhs.getAssignmentClassName());
rhstext.setText(rhs.getKeyPath());
if (rhs.getValue() == null) {
valuetext.setText("");
} else {
valuetext.setText(rhs.getValue());
}
prioritytext.setText(rule.getAuthor());
} else {
lhstext.setText("");
classtext.setText("");
rhstext.setText("");
prioritytext.setText("");
valuetext.setText("");
}
}
public void updateRules() {
if (table == null) {
return;
}
tableViewer.setInput(model);
tableViewer.refresh();
}
}