001: package org.drools.brms.client.ruleeditor;
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.AssetFormats;
020: import org.drools.brms.client.common.DirtyableComposite;
021: import org.drools.brms.client.common.DirtyableFlexTable;
022: import org.drools.brms.client.common.ErrorPopup;
023: import org.drools.brms.client.common.FormStylePopup;
024: import org.drools.brms.client.common.LoadingPopup;
025: import org.drools.brms.client.packages.SuggestionCompletionCache;
026: import org.drools.brms.client.rpc.RepositoryServiceFactory;
027: import org.drools.brms.client.rpc.RuleAsset;
028:
029: import com.google.gwt.user.client.Command;
030: import com.google.gwt.user.client.rpc.AsyncCallback;
031: import com.google.gwt.user.client.ui.Button;
032: import com.google.gwt.user.client.ui.ClickListener;
033: import com.google.gwt.user.client.ui.Composite;
034: import com.google.gwt.user.client.ui.HTML;
035: import com.google.gwt.user.client.ui.HasHorizontalAlignment;
036: import com.google.gwt.user.client.ui.HasVerticalAlignment;
037: import com.google.gwt.user.client.ui.HorizontalPanel;
038: import com.google.gwt.user.client.ui.Widget;
039: import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
040:
041: /**
042: * The main layout parent/controller the rule viewer.
043: *
044: * @author Michael Neale
045: */
046: public class RuleViewer extends Composite {
047:
048: private Command closeCommand;
049: protected RuleAsset asset;
050: private final DirtyableFlexTable layout;
051:
052: private boolean readOnly;
053:
054: private MetaDataWidget metaWidget;
055: private RuleDocumentWidget doco;
056: private Widget editor;
057:
058: private ActionToolbar toolbar;
059:
060: public RuleViewer(RuleAsset asset) {
061: this (asset, false);
062: }
063:
064: /**
065: * @param UUID The resource to open.
066: * @param format The type of resource (may determine what editor is used).
067: * @param name The name to be displayed.
068: * @param historicalReadOnly true if this is a read only view for historical purposes.
069: */
070: public RuleViewer(RuleAsset asset, boolean historicalReadOnly) {
071: this .asset = asset;
072: this .readOnly = historicalReadOnly;
073: layout = new DirtyableFlexTable();
074:
075: doWidgets();
076: initWidget(this .layout);
077:
078: LoadingPopup.close();
079: }
080:
081: /**
082: * This will actually load up the data (this is called by the callback
083: * when we get the data back from the server,
084: * also determines what widgets to load up).
085: */
086: private void doWidgets() {
087: this .layout.clear();
088:
089: FlexCellFormatter formatter = layout.getFlexCellFormatter();
090:
091: //the action widgets (checkin/close etc).
092: toolbar = new ActionToolbar(asset, new Command() {
093: public void execute() {
094: doCheckin();
095: }
096: }, new Command() {
097: public void execute() {
098: doArchive();
099: }
100: }, new Command() {
101: public void execute() {
102: zoomIntoAsset();
103: }
104: }, new Command() {
105: public void execute() {
106: doDelete();
107: }
108: }, readOnly);
109:
110: layout.setWidget(0, 0, toolbar);
111: formatter.setAlignment(0, 0,
112: HasHorizontalAlignment.ALIGN_RIGHT,
113: HasVerticalAlignment.ALIGN_MIDDLE);
114:
115: metaWidget = new MetaDataWidget(this .asset.metaData, readOnly,
116: this .asset.uuid, new Command() {
117: public void execute() {
118: refreshDataAndView();
119: }
120:
121: });
122:
123: //now the main layout table
124: layout.setWidget(0, 1, metaWidget);
125:
126: formatter.setRowSpan(0, 1, 3);
127: formatter.setVerticalAlignment(0, 1,
128: HasVerticalAlignment.ALIGN_TOP);
129: formatter.setWidth(0, 1, "30%");
130:
131: //REMEMBER: subsequent rows have only one column, doh that is confusing !
132: //GAAAAAAAAAAAAAAAAAAAAAAAAAAH
133:
134: editor = EditorLauncher.getEditorViewer(asset, this );
135: toolbar.setCloseCommand(new Command() {
136: public void execute() {
137: if (layout.hasDirty()) {
138: doCloseUnsavedWarning();
139: } else {
140:
141: closeCommand.execute();
142: }
143: }
144: });
145:
146: layout.setWidget(1, 0, editor);
147:
148: //the document widget
149: doco = new RuleDocumentWidget(asset.metaData);
150: layout.setWidget(2, 0, doco);
151: }
152:
153: void doDelete() {
154: RepositoryServiceFactory.getService().deleteUncheckedRule(
155: this .asset.uuid, this .asset.metaData.packageName,
156: new AsyncCallback() {
157:
158: public void onFailure(Throwable err) {
159: ErrorPopup.showMessage(err.getMessage());
160: }
161:
162: public void onSuccess(Object o) {
163: closeCommand.execute();
164: }
165: });
166: }
167:
168: /**
169: * This responds to the checkin command.
170: */
171:
172: void doArchive() {
173: this .asset.archived = true;
174: this .doCheckin();
175: this .closeCommand.execute();
176: }
177:
178: void doCheckin() {
179: this .layout.clear();
180:
181: LoadingPopup.showMessage("Saving, please wait...");
182: RepositoryServiceFactory.getService().checkinVersion(
183: this .asset, new AsyncCallback() {
184:
185: public void onFailure(Throwable err) {
186: ErrorPopup.showMessage(err.getMessage());
187: }
188:
189: public void onSuccess(Object o) {
190:
191: flushSuggestionCompletionCache();
192:
193: String uuid = (String) o;
194:
195: if (editor instanceof DirtyableComposite) {
196: ((DirtyableComposite) editor).resetDirty();
197: }
198:
199: metaWidget.resetDirty();
200: doco.resetDirty();
201:
202: if (uuid == null) {
203: ErrorPopup
204: .showMessage("Failed to check in the item. Please contact your system administrator.");
205: return;
206: }
207: refreshDataAndView();
208: }
209: });
210: }
211:
212: /**
213: * In some cases we will want to flush the package dependency stuff for suggestion completions.
214: * The user will still need to reload the asset editor though.
215: */
216: public void flushSuggestionCompletionCache() {
217: if (AssetFormats
218: .isPackageDependency(this .asset.metaData.format)) {
219: LoadingPopup
220: .showMessage("Refreshing content assistance...");
221: SuggestionCompletionCache.getInstance().refreshPackage(
222: this .asset.metaData.packageName, new Command() {
223: public void execute() {
224: LoadingPopup.close();
225: }
226: });
227: }
228: }
229:
230: /**
231: * This will reload the contents from the database, and refresh the widgets.
232: */
233: public void refreshDataAndView() {
234:
235: RepositoryServiceFactory.getService().loadRuleAsset(asset.uuid,
236: new AsyncCallback() {
237: public void onFailure(Throwable t) {
238: ErrorPopup.showMessage(t.getMessage());
239: }
240:
241: public void onSuccess(Object a) {
242: asset = (RuleAsset) a;
243: doWidgets();
244: LoadingPopup.close();
245: }
246: });
247: }
248:
249: /**
250: * Calling this will toggle the visibility of the meta-data widget (effectively zooming
251: * in the rule asset).
252: */
253: public void zoomIntoAsset() {
254:
255: boolean vis = !layout.getFlexCellFormatter().isVisible(2, 0);
256: this .layout.getFlexCellFormatter().setVisible(0, 1, vis);
257: this .layout.getFlexCellFormatter().setVisible(2, 0, vis);
258: }
259:
260: /**
261: * This needs to be called to allow the opened viewer to close itself.
262: * @param c
263: */
264: public void setCloseCommand(Command c) {
265: this .closeCommand = c;
266: }
267:
268: /**
269: * Called when user wants to close, but there is "dirtyness".
270: */
271: protected void doCloseUnsavedWarning() {
272: final FormStylePopup pop = new FormStylePopup(
273: "images/warning-large.png",
274: "WARNING: Un-committed changes.");
275: Button dis = new Button("Discard");
276: Button can = new Button("Cancel");
277: HorizontalPanel hor = new HorizontalPanel();
278:
279: hor.add(dis);
280: hor.add(can);
281:
282: pop
283: .addRow(new HTML(
284: "Are you sure you want to discard changes?"));
285: pop.addRow(hor);
286:
287: dis.addClickListener(new ClickListener() {
288: public void onClick(Widget w) {
289: closeCommand.execute();
290: pop.hide();
291: }
292: });
293:
294: can.addClickListener(new ClickListener() {
295: public void onClick(Widget w) {
296: pop.hide();
297: }
298: });
299:
300: pop.setStyleName("warning-Popup");
301:
302: pop.setPopupPosition((DirtyableComposite.getWidth() - pop
303: .getOffsetWidth()) / 2, 100);
304: pop.show();
305: }
306:
307: }
|