| /* |
| * Copyright 2010 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| * use this file except in compliance with the License. You may obtain a copy of |
| * the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| package com.google.gwt.app.place; |
| |
| import com.google.gwt.app.place.ProxyPlace.Operation; |
| import com.google.gwt.event.shared.EventBus; |
| import com.google.gwt.requestfactory.shared.Receiver; |
| import com.google.gwt.requestfactory.shared.RecordRequest; |
| import com.google.gwt.requestfactory.shared.RequestFactory; |
| import com.google.gwt.requestfactory.shared.RequestObject; |
| import com.google.gwt.user.client.Window; |
| import com.google.gwt.valuestore.shared.Record; |
| import com.google.gwt.valuestore.shared.SyncResult; |
| import com.google.gwt.valuestore.shared.Value; |
| |
| import java.util.Set; |
| |
| /** |
| * <p> |
| * <span style="color:red">Experimental API: This class is still under rapid |
| * development, and is very likely to be deleted. Use it at your own risk. |
| * </span> |
| * </p> |
| * Abstract activity for editing a record. |
| * |
| * @param <R> the type of Record being edited |
| */ |
| public abstract class AbstractRecordEditActivity<R extends Record> implements |
| Activity, RecordEditView.Delegate { |
| |
| private RequestObject<Void> requestObject; |
| |
| private final boolean creating; |
| private final RecordEditView<R> view; |
| private final Class<R> proxyType; |
| private final RequestFactory requests; |
| private final PlaceController placeController; |
| |
| private R record; |
| private Long futureId; |
| private Display display; |
| |
| public AbstractRecordEditActivity(RecordEditView<R> view, R record, |
| Class<R> proxyType, boolean creating, RequestFactory requests, |
| PlaceController placeController) { |
| |
| this.view = view; |
| this.record = record; |
| this.proxyType = proxyType; |
| this.placeController = placeController; |
| this.creating = creating; |
| this.requests = requests; |
| } |
| |
| public void cancelClicked() { |
| String unsavedChangesWarning = mayStop(); |
| if ((unsavedChangesWarning == null) |
| || Window.confirm(unsavedChangesWarning)) { |
| if (requestObject != null) { |
| // silence the next mayStop() call when place changes |
| requestObject.reset(); |
| } |
| exit(false); |
| } |
| } |
| |
| public R getRecord() { |
| return record; |
| } |
| |
| public RecordEditView<R> getView() { |
| return view; |
| } |
| |
| public String mayStop() { |
| if (requestObject != null && requestObject.isChanged()) { |
| return "Are you sure you want to abandon your changes?"; |
| } |
| |
| return null; |
| } |
| |
| public void onCancel() { |
| onStop(); |
| } |
| |
| public void onStop() { |
| this.display = null; |
| } |
| |
| public void saveClicked() { |
| assert requestObject != null; |
| if (!requestObject.isChanged()) { |
| return; |
| } |
| view.setEnabled(false); |
| |
| final RequestObject<Void> toCommit = requestObject; |
| requestObject = null; |
| |
| Receiver<Void> receiver = new Receiver<Void>() { |
| public void onSuccess(Void ignore, Set<SyncResult> response) { |
| if (display == null) { |
| return; |
| } |
| boolean hasViolations = false; |
| |
| for (SyncResult syncResult : response) { |
| Record syncRecord = syncResult.getRecord(); |
| if (creating) { |
| if (futureId == null || !futureId.equals(syncResult.getFutureId())) { |
| continue; |
| } |
| record = cast(syncRecord); |
| } else { |
| if (!syncRecord.getId().equals(record.getId())) { |
| continue; |
| } |
| } |
| if (syncResult.hasViolations()) { |
| hasViolations = true; |
| view.showErrors(syncResult.getViolations()); |
| } |
| } |
| if (!hasViolations) { |
| exit(true); |
| } else { |
| requestObject = toCommit; |
| requestObject.clearUsed(); |
| view.setEnabled(true); |
| } |
| } |
| }; |
| toCommit.fire(receiver); |
| } |
| |
| public void start(Display display, EventBus eventBus) { |
| this.display = display; |
| |
| view.setDelegate(this); |
| view.setCreating(creating); |
| |
| if (creating) { |
| R tempRecord = requests.create(proxyType); |
| futureId = tempRecord.getId(); |
| doStart(display, tempRecord); |
| } else { |
| RecordRequest<R> findRequest = getFindRequest(Value.of(getRecord().getId())); |
| findRequest.with(getView().getPaths()).fire(new Receiver<R>() { |
| public void onSuccess(R record, Set<SyncResult> syncResults) { |
| if (AbstractRecordEditActivity.this.display != null) { |
| doStart(AbstractRecordEditActivity.this.display, record); |
| } |
| } |
| }); |
| } |
| } |
| |
| /** |
| * Called when the user cancels or has successfully saved. This default |
| * implementation tells the {@link PlaceController} to show the details of the |
| * edited record, or clears the display if a creation was canceled. |
| * <p> |
| * If we're creating, a call to getRecord() from here will return a record |
| * with the correct id. However, other properties may be stale or unset. |
| * |
| * @param saved true if changes were comitted |
| */ |
| protected void exit(boolean saved) { |
| if (!saved && creating) { |
| display.showActivityWidget(null); |
| } else { |
| placeController.goTo(new ProxyPlace(getRecord(), Operation.DETAILS)); |
| } |
| } |
| |
| /** |
| * Called to fetch the details of the edited record. |
| */ |
| protected abstract RecordRequest<R> getFindRequest(Value<Long> id); |
| |
| protected abstract RequestObject<Void> getPersistRequest(R record); |
| |
| @SuppressWarnings("unchecked") |
| private R cast(Record syncRecord) { |
| return (R) syncRecord; |
| } |
| |
| private void doStart(final Display display, R record) { |
| requestObject = getPersistRequest(record); |
| R editableRecord = requestObject.edit(record); |
| view.setEnabled(true); |
| view.setValue(editableRecord); |
| view.showErrors(null); |
| display.showActivityWidget(view); |
| } |
| } |