| /* |
| * 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.sample.dynatablerf.client; |
| |
| import com.google.gwt.core.client.GWT; |
| import com.google.gwt.event.dom.client.ClickEvent; |
| import com.google.gwt.event.dom.client.KeyCodes; |
| import com.google.gwt.event.dom.client.KeyUpEvent; |
| import com.google.gwt.event.dom.client.KeyUpHandler; |
| import com.google.gwt.event.logical.shared.ValueChangeEvent; |
| import com.google.gwt.event.shared.EventBus; |
| import com.google.gwt.sample.dynatablerf.client.events.EditPersonEvent; |
| import com.google.gwt.sample.dynatablerf.client.widgets.MentorSelector; |
| import com.google.gwt.sample.dynatablerf.client.widgets.PersonEditor; |
| import com.google.gwt.sample.dynatablerf.client.widgets.ScheduleEditor; |
| import com.google.gwt.sample.dynatablerf.client.widgets.TimeSlotListWidget; |
| import com.google.gwt.sample.dynatablerf.shared.DynaTableRequestFactory; |
| import com.google.gwt.sample.dynatablerf.shared.DynaTableRequestFactory.PersonRequest; |
| import com.google.gwt.sample.dynatablerf.shared.PersonProxy; |
| import com.google.gwt.uibinder.client.UiBinder; |
| import com.google.gwt.uibinder.client.UiField; |
| import com.google.gwt.uibinder.client.UiHandler; |
| import com.google.gwt.user.client.ui.CheckBox; |
| import com.google.gwt.user.client.ui.DialogBox; |
| import com.google.gwt.user.client.ui.HTMLPanel; |
| import com.google.web.bindery.requestfactory.gwt.client.RequestFactoryEditorDriver; |
| import com.google.web.bindery.requestfactory.shared.Receiver; |
| import com.google.web.bindery.requestfactory.shared.Request; |
| import com.google.web.bindery.requestfactory.shared.RequestContext; |
| |
| import java.util.Set; |
| |
| import javax.validation.ConstraintViolation; |
| |
| /** |
| * This class shows how the UI for editing a person is wired up to the |
| * RequestFactoryEditorDelegate. It is also responsible for showing and |
| * dismissing the PersonEditor. The use of the FavoriteManager shows integration |
| * between a remote service and a local service. |
| */ |
| public class PersonEditorWorkflow { |
| interface Binder extends UiBinder<DialogBox, PersonEditorWorkflow> { |
| Binder BINDER = GWT.create(Binder.class); |
| } |
| |
| interface Driver extends |
| RequestFactoryEditorDriver<PersonProxy, PersonEditor> { |
| } |
| |
| static void register(EventBus eventBus, |
| final DynaTableRequestFactory requestFactory, |
| final FavoritesManager manager) { |
| eventBus.addHandler(EditPersonEvent.TYPE, new EditPersonEvent.Handler() { |
| public void startEdit(PersonProxy person, RequestContext requestContext) { |
| new PersonEditorWorkflow(requestFactory, manager, person).edit(requestContext); |
| } |
| }); |
| } |
| |
| @UiField |
| HTMLPanel contents; |
| |
| @UiField |
| DialogBox dialog; |
| |
| @UiField |
| CheckBox favorite; |
| |
| @UiField(provided = true) |
| PersonEditor personEditor; |
| |
| private Driver editorDriver; |
| private final FavoritesManager manager; |
| private PersonProxy person; |
| private final DynaTableRequestFactory requestFactory; |
| |
| private PersonEditorWorkflow(DynaTableRequestFactory requestFactory, |
| FavoritesManager manager, PersonProxy person) { |
| this.requestFactory = requestFactory; |
| this.manager = manager; |
| this.person = person; |
| TimeSlotListWidget timeSlotEditor = new TimeSlotListWidget(requestFactory); |
| ScheduleEditor scheduleEditor = new ScheduleEditor(timeSlotEditor); |
| MentorSelector mentorEditor = new MentorSelector(requestFactory); |
| personEditor = new PersonEditor(mentorEditor, scheduleEditor); |
| Binder.BINDER.createAndBindUi(this); |
| contents.addDomHandler(new KeyUpHandler() { |
| public void onKeyUp(KeyUpEvent event) { |
| if (event.getNativeKeyCode() == KeyCodes.KEY_ESCAPE) { |
| onCancel(null); |
| } |
| } |
| }, KeyUpEvent.getType()); |
| this.favorite.setVisible(false); |
| } |
| |
| /** |
| * Called by the cancel button when it is clicked. This method will just tear |
| * down the UI and clear the state of the workflow. |
| */ |
| @UiHandler("cancel") |
| void onCancel(ClickEvent event) { |
| dialog.hide(); |
| } |
| |
| /** |
| * Called by the edit dialog's save button. This method will flush the |
| * contents of the UI into the PersonProxy that is being edited, check for |
| * errors, and send the request to the server. |
| */ |
| @UiHandler("save") |
| void onSave(ClickEvent event) { |
| // Flush the contents of the UI |
| RequestContext context = editorDriver.flush(); |
| |
| // Check for errors |
| if (editorDriver.hasErrors()) { |
| dialog.setText("Errors detected locally"); |
| return; |
| } |
| |
| // Send the request |
| context.fire(new Receiver<Void>() { |
| @Override |
| public void onConstraintViolation(Set<ConstraintViolation<?>> errors) { |
| // Otherwise, show ConstraintViolations in the UI |
| dialog.setText("Errors detected on the server"); |
| editorDriver.setConstraintViolations(errors); |
| } |
| |
| @Override |
| public void onSuccess(Void response) { |
| // If everything went as planned, just dismiss the dialog box |
| dialog.hide(); |
| } |
| }); |
| } |
| |
| /** |
| * Called by the favorite checkbox when its value has been toggled. |
| */ |
| @UiHandler("favorite") |
| void onValueChanged(ValueChangeEvent<Boolean> event) { |
| manager.setFavorite(person.stableId(), favorite.getValue()); |
| } |
| |
| /** |
| * Construct and display the UI that will be used to edit the current |
| * PersonProxy, using the given RequestContext to accumulate the edits. |
| */ |
| private void edit(RequestContext requestContext) { |
| editorDriver = GWT.create(Driver.class); |
| editorDriver.initialize(requestFactory, personEditor); |
| |
| if (requestContext == null) { |
| this.favorite.setVisible(true); |
| fetchAndEdit(); |
| return; |
| } |
| |
| editorDriver.edit(person, requestContext); |
| personEditor.focus(); |
| favorite.setValue(manager.isFavorite(person), false); |
| dialog.center(); |
| } |
| |
| private void fetchAndEdit() { |
| // The request is configured arbitrarily |
| Request<PersonProxy> fetchRequest = requestFactory.find(person.stableId()); |
| |
| // Add the paths that the EditorDrives computes |
| fetchRequest.with(editorDriver.getPaths()); |
| |
| // We could do more with the request, but we just fire it |
| fetchRequest.to(new Receiver<PersonProxy>() { |
| @Override |
| public void onSuccess(PersonProxy person) { |
| PersonEditorWorkflow.this.person = person; |
| // Start the edit process |
| PersonRequest context = requestFactory.personRequest(); |
| // Display the UI |
| edit(context); |
| // Configure the method invocation to be sent in the context |
| context.persist().using(person); |
| // The context will be fire()'ed from the onSave() method |
| } |
| }).fire(); |
| } |
| } |