/* Copyright (c) 2009 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.appengine.demos.sticky.client;
import com.google.appengine.demos.sticky.client.model.Model;
import com.google.appengine.demos.sticky.client.model.Note;
import com.google.appengine.demos.sticky.client.model.Surface;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.user.client.ui.AbstractImagePrototype;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.ImageBundle;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.TextBox;
/**
* A widget for displaying the list of available surfaces to a user and for
* adding new surfaces.
*
* @author knorton@google.com (Kelly Norton)
*/
public class SurfaceListView extends FlowPanel implements Model.DataObserver {
/**
* Declaration of image bundle resources used in this widget.
*/
public interface Images extends ImageBundle {
@Resource("surface-list-add-hv.gif")
AbstractImagePrototype surfaceListAddSurfaceButtonHv();
@Resource("surface-list-add-up.gif")
AbstractImagePrototype surfaceListAddSurfaceButtonUp();
}
/**
* Provides a way to react to events generated by a {@link SurfaceListView}.
*/
public interface Observer {
/**
* Invoked when the {@link SurfaceListView} is hidden with a call to
* {@link SurfaceListView#hide()}.
*/
void onHide();
/**
* Invoked when the {@link SurfaceListView} is shown with a call to
* {@link SurfaceListView#show()}.
*/
void onShow();
}
/**
* A widget that provides inline editing when the user adds a new surface.
*/
private class EditView extends FlowPanel implements BlurHandler,
KeyPressHandler {
private final TextBox titleTextBox;
/**
*
*/
public EditView() {
final Document document = Document.get();
final Element element = getElement();
final Element rowElement = element.appendChild(document
.createDivElement());
rowElement.setClassName("surface-item-edit");
titleTextBox = new TextBox();
titleTextBox.setStyleName("surface-item-title");
add(titleTextBox, rowElement.<com.google.gwt.user.client.Element> cast());
titleTextBox.addBlurHandler(this);
titleTextBox.addKeyPressHandler(this);
final Element authorsElement = rowElement.appendChild(document
.createDivElement());
authorsElement.setClassName("surface-item-authors");
authorsElement.setInnerText("/w Only You.");
SurfaceListView.this.add(this, listElement
.<com.google.gwt.user.client.Element> cast());
titleTextBox.setFocus(true);
}
public void onBlur(BlurEvent event) {
commit();
}
public void onKeyPress(KeyPressEvent event) {
switch (event.getCharCode()) {
case KeyCodes.KEY_ENTER:
commit();
break;
case KeyCodes.KEY_ESCAPE:
break;
}
}
private void commit() {
final String value = titleTextBox.getValue().trim();
SurfaceListView.this.remove(this);
if (value.length() > 0) {
model.createSurface(value);
hide();
}
}
}
/**
* A widget to display information about a surface in a list.
*/
private class ItemView extends SimplePanel implements ClickHandler {
private final Element titleElement, authorsElement, noteCountElement;
private final Surface surface;
/**
* @param surface
* the surface to be displayed
*/
public ItemView(Surface surface) {
this.surface = surface;
final Document document = Document.get();
final Element element = getElement();
final Element rowElement = element.appendChild(document
.createDivElement());
titleElement = rowElement.appendChild(document.createSpanElement());
noteCountElement = rowElement.appendChild(document.createSpanElement());
authorsElement = rowElement.appendChild(document.createDivElement());
rowElement.setClassName("surface-item" + getNextStyleNameSuffix());
titleElement.setClassName("surface-item-title");
noteCountElement.setClassName("surface-item-count");
authorsElement.setClassName("surface-item-authors");
titleElement.setInnerText(surface.getTitle());
authorsElement.setInnerText(surface.getAuthorNamesAsString());
noteCountElement.setInnerText("(" + surface.getNoteCount() + " notes)");
addDomHandler(this, ClickEvent.getType());
// Add to parent.
SurfaceListView.this.add(this, listElement
.<com.google.gwt.user.client.Element> cast());
}
public void onClick(ClickEvent event) {
model.selectSurface(surface);
hide();
}
}
private final DivElement listElement;
private int count;
private final Model model;
private final Observer observer;
/**
* @param model
* the model to which the Ui will bind itself
* @param observer
* a single observer to receive callbacks from this object
*/
public SurfaceListView(Images images, Model model, Observer observer) {
this.model = model;
this.observer = observer;
setVisible(false);
setStyleName("surface-list");
final Element element = getElement();
final Element titleElement = element.appendChild(Document.get()
.createDivElement());
titleElement.setClassName("surface-list-title");
titleElement.setInnerText("Your Sticky Surfaces");
final Element innerElement = element.appendChild(Document.get()
.createDivElement());
innerElement.setClassName("surface-list-list");
listElement = innerElement.appendChild(Document.get().createDivElement());
add(Buttons.createPushButtonWithImageStates(images
.surfaceListAddSurfaceButtonUp().createImage(), images
.surfaceListAddSurfaceButtonHv().createImage(), "surface-list-add",
new ClickHandler() {
public void onClick(ClickEvent event) {
new EditView();
}
}), innerElement.<com.google.gwt.user.client.Element> cast());
model.addDataObserver(this);
}
/**
* Hides the Ui for this widget and notifies the {@link Observer} accordingly.
*/
public void hide() {
setVisible(false);
observer.onHide();
}
public void onNoteCreated(Note note) {
}
public void onSurfaceCreated(Surface surface) {
new ItemView(surface);
}
public void onSurfaceNotesReceived(Note[] notes) {
}
public void onSurfaceSelected(Surface nowSelected, Surface wasSelected) {
}
public void onSurfacesReceived(Surface[] surfaces) {
for (int i = 0, n = surfaces.length; i < n; i++) {
new ItemView(surfaces[i]);
}
}
/**
* Makes the Ui for this widget visible and notifies the {@link Observer}.
*/
public void show() {
setVisible(true);
}
private String getNextStyleNameSuffix() {
return ((count++ & 1) == 0) ? "-odd" : "-even";
}
}