001: package org.drools.brms.client.modeldriven.ui;
002:
003: /*
004: * Copyright 2005 JBoss Inc
005: *
006: * Licensed under the Apache License, Version 2.0 (the "License");
007: * you may not use this file except in compliance with the License.
008: * You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */
018:
019: import org.drools.brms.client.common.DirtyableComposite;
020: import org.drools.brms.client.common.DirtyableFlexTable;
021: import org.drools.brms.client.common.FieldEditListener;
022: import org.drools.brms.client.common.FormStylePopup;
023: import org.drools.brms.client.common.ImageButton;
024: import org.drools.brms.client.common.Lbl;
025: import org.drools.brms.client.common.YesNoDialog;
026: import org.drools.brms.client.modeldriven.HumanReadable;
027: import org.drools.brms.client.modeldriven.SuggestionCompletionEngine;
028: import org.drools.brms.client.modeldriven.brl.ActionFieldValue;
029: import org.drools.brms.client.modeldriven.brl.ActionSetField;
030: import org.drools.brms.client.modeldriven.brl.ActionUpdateField;
031: import org.drools.brms.client.modeldriven.brl.FactPattern;
032: import org.drools.brms.client.modeldriven.brl.RuleModel;
033:
034: import com.google.gwt.user.client.Command;
035: import com.google.gwt.user.client.ui.ChangeListener;
036: import com.google.gwt.user.client.ui.ClickListener;
037: import com.google.gwt.user.client.ui.Composite;
038: import com.google.gwt.user.client.ui.FlexTable;
039: import com.google.gwt.user.client.ui.HorizontalPanel;
040: import com.google.gwt.user.client.ui.Image;
041: import com.google.gwt.user.client.ui.KeyboardListener;
042: import com.google.gwt.user.client.ui.Label;
043: import com.google.gwt.user.client.ui.ListBox;
044: import com.google.gwt.user.client.ui.SimplePanel;
045: import com.google.gwt.user.client.ui.TextBox;
046: import com.google.gwt.user.client.ui.Widget;
047:
048: /**
049: * This widget is for setting fields on a bound fact or global variable.
050: *
051: * @author Michael Neale
052: */
053: public class ActionSetFieldWidget extends DirtyableComposite {
054:
055: final private ActionSetField model;
056: final private SuggestionCompletionEngine completions;
057: final private DirtyableFlexTable layout;
058: private boolean isBoundFact = false;
059:
060: final private String[] fieldCompletions;
061: final private RuleModeller modeller;
062: final private String variableClass;
063:
064: public ActionSetFieldWidget(RuleModeller mod, ActionSetField set,
065: SuggestionCompletionEngine com) {
066: this .model = set;
067: this .completions = com;
068: this .layout = new DirtyableFlexTable();
069: this .modeller = mod;
070:
071: layout.setStyleName("model-builderInner-Background");
072: if (completions.isGlobalVariable(set.variable)) {
073: this .fieldCompletions = completions
074: .getFieldCompletionsForGlobalVariable(set.variable);
075: this .variableClass = (String) completions.globalTypes
076: .get(set.variable);
077: } else {
078: FactPattern pattern = mod.getModel().getBoundFact(
079: set.variable);
080: this .fieldCompletions = completions
081: .getFieldCompletions(pattern.factType);
082: this .variableClass = pattern.factType;
083: this .isBoundFact = true;
084: }
085:
086: doLayout();
087:
088: initWidget(this .layout);
089: }
090:
091: private void doLayout() {
092: layout.clear();
093: layout.setWidget(0, 0, getSetterLabel());
094:
095: DirtyableFlexTable inner = new DirtyableFlexTable();
096:
097: for (int i = 0; i < model.fieldValues.length; i++) {
098: ActionFieldValue val = model.fieldValues[i];
099:
100: inner.setWidget(i, 0, fieldSelector(val));
101: inner.setWidget(i, 1, valueEditor(val));
102: final int idx = i;
103: Image remove = new ImageButton(
104: "images/delete_item_small.gif");
105: remove.addClickListener(new ClickListener() {
106: public void onClick(Widget w) {
107: YesNoDialog diag = new YesNoDialog(
108: "Remove this item?", new Command() {
109: public void execute() {
110: model.removeField(idx);
111: modeller.refreshWidget();
112: }
113: });
114: diag.setPopupPosition(w.getAbsoluteLeft(), w
115: .getAbsoluteTop());
116: diag.show();
117: }
118: });
119: inner.setWidget(i, 2, remove);
120: }
121:
122: layout.setWidget(0, 1, inner);
123:
124: }
125:
126: private Widget getSetterLabel() {
127:
128: HorizontalPanel horiz = new HorizontalPanel();
129:
130: Image edit = new ImageButton("images/add_field_to_fact.gif");
131: edit
132: .setTitle("Add another field to this so you can set its value.");
133: edit.addClickListener(new ClickListener() {
134: public void onClick(Widget w) {
135: showAddFieldPopup(w);
136: }
137: });
138: String modifyType = "set";
139: if (this .model instanceof ActionUpdateField) {
140: modifyType = "modify";
141: }
142: horiz
143: .add(new Lbl(HumanReadable
144: .getActionDisplayName(modifyType)
145: + " [" + model.variable + "]",
146: "modeller-action-Label"));
147: horiz.add(edit);
148:
149: return horiz;
150: }
151:
152: protected void showAddFieldPopup(Widget w) {
153: final FormStylePopup popup = new FormStylePopup(
154: "images/newex_wiz.gif", "Add a field");
155: popup.setStyleName("ks-popups-Popup");
156: final ListBox box = new ListBox();
157: box.addItem("...");
158:
159: for (int i = 0; i < fieldCompletions.length; i++) {
160: box.addItem(fieldCompletions[i]);
161: }
162:
163: box.setSelectedIndex(0);
164:
165: popup.addAttribute("Add field", box);
166: box.addChangeListener(new ChangeListener() {
167: public void onChange(Widget w) {
168: String fieldName = box.getItemText(box
169: .getSelectedIndex());
170:
171: String fieldType = completions.getFieldType(
172: variableClass, fieldName);
173: model.addFieldValue(new ActionFieldValue(fieldName, "",
174: fieldType));
175: modeller.refreshWidget();
176: popup.hide();
177: }
178: });
179:
180: popup.setPopupPosition(w.getAbsoluteLeft(), w.getAbsoluteTop());
181: popup.show();
182:
183: }
184:
185: private Widget valueEditor(final ActionFieldValue val) {
186:
187: String enumKey = this .variableClass + "." + val.field;
188: if (this .completions.dataEnumLists.containsKey(enumKey)) {
189: return ConstraintValueEditor.enumDropDown(val.value,
190: new ConstraintValueEditor.ValueChanged() {
191: public void valueChanged(String newValue) {
192: val.value = newValue;
193: }
194: }, (String[]) this .completions.dataEnumLists
195: .get(enumKey));
196: } else {
197:
198: SimplePanel panel = new SimplePanel();
199: final TextBox box = new TextBox();
200: box.setText(val.value);
201: if (val.value.length() != 0) {
202: box.setVisibleLength(val.value.length());
203: }
204:
205: if (val.type
206: .equals(SuggestionCompletionEngine.TYPE_NUMERIC)) {
207: box.addKeyboardListener(getNumericFilter(box));
208: }
209:
210: box.addChangeListener(new ChangeListener() {
211: public void onChange(Widget w) {
212: val.value = box.getText();
213: }
214: });
215:
216: box.addKeyboardListener(new FieldEditListener(
217: new Command() {
218: public void execute() {
219: box
220: .setVisibleLength(box.getText()
221: .length());
222: }
223: }));
224: panel.add(box);
225: return panel;
226: }
227: }
228:
229: /**
230: * This will return a keyboard listener for field setters, which
231: * will obey numeric conventions - it will also allow formulas
232: * (a formula is when the first value is a "=" which means
233: * it is meant to be taken as the user typed)
234: */
235: public static KeyboardListener getNumericFilter(final TextBox box) {
236: return new KeyboardListener() {
237:
238: public void onKeyDown(Widget arg0, char arg1, int arg2) {
239:
240: }
241:
242: public void onKeyPress(Widget w, char c, int i) {
243: if (Character.isLetter(c) && c != '='
244: && !(box.getText().startsWith("="))) {
245: ((TextBox) w).cancelKey();
246: }
247: }
248:
249: public void onKeyUp(Widget arg0, char arg1, int arg2) {
250: }
251:
252: };
253: }
254:
255: private Widget fieldSelector(final ActionFieldValue val) {
256: return new Label(val.field);
257: }
258:
259: /**
260: * This returns true if the values being set are on a fact.
261: */
262: public boolean isBoundFact() {
263: return isBoundFact;
264: }
265:
266: public boolean isDirty() {
267: return layout.hasDirty();
268: }
269:
270: }
|