Commit e13886c0 authored by Pascal Hartig's avatar Pascal Hartig

Merge pull request #882 from dprotti/gwtcleanmodel

gwt - model objects agnostic of presenters
parents e8f8532b 72a52baf
...@@ -11,10 +11,14 @@ import com.google.gwt.dom.client.EventTarget; ...@@ -11,10 +11,14 @@ import com.google.gwt.dom.client.EventTarget;
import com.google.gwt.dom.client.InputElement; import com.google.gwt.dom.client.InputElement;
import com.google.gwt.dom.client.NativeEvent; import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.safehtml.client.SafeHtmlTemplates; import com.google.gwt.safehtml.client.SafeHtmlTemplates;
import com.google.gwt.safehtml.shared.SafeHtml; import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder; import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.safehtml.shared.SafeHtmlUtils; import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.todo.client.events.ToDoEvent;
import com.todo.client.events.ToDoRemovedEvent;
import com.todo.client.events.ToDoUpdatedEvent;
/** /**
* A cell that renders {@link ToDoItem} instances. This cell is rendered in both view and edit modes * A cell that renders {@link ToDoItem} instances. This cell is rendered in both view and edit modes
...@@ -69,8 +73,11 @@ public class ToDoCell extends AbstractCell<ToDoItem> { ...@@ -69,8 +73,11 @@ public class ToDoCell extends AbstractCell<ToDoItem> {
*/ */
private boolean beginningEdit = false; private boolean beginningEdit = false;
private EventBus eventBus;
public ToDoCell() { public ToDoCell() {
super("click", "keyup", "blur", "dblclick"); super("click", "keyup", "blur", "dblclick");
eventBus = ToDoEvent.getGlobalEventBus();
} }
@Override @Override
...@@ -81,8 +88,8 @@ public class ToDoCell extends AbstractCell<ToDoItem> { ...@@ -81,8 +88,8 @@ public class ToDoCell extends AbstractCell<ToDoItem> {
sb.append(rendered); sb.append(rendered);
} else { } else {
SafeHtml rendered = SafeHtml rendered =
templates.view(value.isDone() ? templates.inputChecked() : templates.inputClear(), templates.view(value.isCompleted() ? templates.inputChecked() : templates.inputClear(),
SafeHtmlUtils.fromString(value.getTitle()), value.isDone() ? "listItem view completed" SafeHtmlUtils.fromString(value.getTitle()), value.isCompleted() ? "listItem view completed"
: "listItem view", : "listItem view",
// NOTE: The addition of a timestamp here is a bit of a HACK! The problem // NOTE: The addition of a timestamp here is a bit of a HACK! The problem
// is that the CellList uses a HasDataPresenter for rendering. This class // is that the CellList uses a HasDataPresenter for rendering. This class
...@@ -152,9 +159,10 @@ public class ToDoCell extends AbstractCell<ToDoItem> { ...@@ -152,9 +159,10 @@ public class ToDoCell extends AbstractCell<ToDoItem> {
// check whether the checkbox was clicked // check whether the checkbox was clicked
if (tagName.equals("INPUT")) { if (tagName.equals("INPUT")) {
// if so, synchronise the model state // if so, synchronize the model state
InputElement input = clickedElement.cast(); InputElement input = clickedElement.cast();
value.setDone(input.isChecked()); value.setCompleted(input.isChecked());
eventBus.fireEvent(new ToDoUpdatedEvent(value));
// update the 'row' style // update the 'row' style
if (input.isChecked()) { if (input.isChecked()) {
...@@ -165,7 +173,7 @@ public class ToDoCell extends AbstractCell<ToDoItem> { ...@@ -165,7 +173,7 @@ public class ToDoCell extends AbstractCell<ToDoItem> {
} else if (tagName.equals("BUTTON")) { } else if (tagName.equals("BUTTON")) {
// if the delete anchor was clicked - delete the item // if the delete anchor was clicked - delete the item
value.delete(); eventBus.fireEvent(new ToDoRemovedEvent(value));
} }
} }
} }
...@@ -178,6 +186,7 @@ public class ToDoCell extends AbstractCell<ToDoItem> { ...@@ -178,6 +186,7 @@ public class ToDoCell extends AbstractCell<ToDoItem> {
private void commitEdit(Element parent, ToDoItem value) { private void commitEdit(Element parent, ToDoItem value) {
InputElement input = getInputElement(parent); InputElement input = getInputElement(parent);
value.setTitle(input.getValue()); value.setTitle(input.getValue());
eventBus.fireEvent(new ToDoUpdatedEvent(value));
} }
/** /**
......
...@@ -4,39 +4,30 @@ package com.todo.client; ...@@ -4,39 +4,30 @@ package com.todo.client;
* An individual ToDo item. * An individual ToDo item.
* *
* @author ceberhardt * @author ceberhardt
* @author dprotti
* *
*/ */
public class ToDoItem { public class ToDoItem {
private final ToDoPresenter presenter;
private String title; private String title;
private boolean done; private boolean completed;
public ToDoItem(String text, ToDoPresenter presenter) { public ToDoItem(String title) {
this.title = text; this(title, false);
this.done = false;
this.presenter = presenter;
} }
public ToDoItem(String title, boolean done, ToDoPresenter presenter) { public ToDoItem(String title, boolean completed) {
this.title = title; this.title = title;
this.done = done; this.completed = completed;
this.presenter = presenter;
}
public boolean isDone() {
return done;
} }
public void setDone(boolean done) { public boolean isCompleted() {
this.done = done; return completed;
presenter.itemStateChanged(this);
} }
public void delete() { public void setCompleted(boolean completed) {
presenter.deleteTask(this); this.completed = completed;
} }
public String getTitle() { public String getTitle() {
...@@ -44,13 +35,7 @@ public class ToDoItem { ...@@ -44,13 +35,7 @@ public class ToDoItem {
} }
public void setTitle(String title) { public void setTitle(String title) {
setTitle(title, true);
}
public void setTitle(String title, boolean notify) {
this.title = title; this.title = title;
if (notify) {
presenter.itemStateChanged(this);
}
} }
} }
...@@ -6,6 +6,7 @@ import java.util.List; ...@@ -6,6 +6,7 @@ import java.util.List;
import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.json.client.JSONArray; import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONBoolean; import com.google.gwt.json.client.JSONBoolean;
import com.google.gwt.json.client.JSONObject; import com.google.gwt.json.client.JSONObject;
...@@ -15,12 +16,18 @@ import com.google.gwt.storage.client.Storage; ...@@ -15,12 +16,18 @@ import com.google.gwt.storage.client.Storage;
import com.google.gwt.user.client.History; import com.google.gwt.user.client.History;
import com.google.gwt.view.client.AbstractDataProvider; import com.google.gwt.view.client.AbstractDataProvider;
import com.google.gwt.view.client.ListDataProvider; import com.google.gwt.view.client.ListDataProvider;
import com.todo.client.ToDoItem;
import com.todo.client.ToDoRouting;
import com.todo.client.events.ToDoEvent;
import com.todo.client.events.ToDoRemovedEvent;
import com.todo.client.events.ToDoUpdatedEvent;
/** /**
* The presenter for the ToDo application. This class is responsible for the lifecycle of the * The presenter for the ToDo application. This class is responsible for the lifecycle of the
* {@link ToDoItem} instances. * {@link ToDoItem} instances.
* *
* @author ceberhardt * @author ceberhardt
* @author dprotti
* *
*/ */
public class ToDoPresenter { public class ToDoPresenter {
...@@ -111,7 +118,7 @@ public class ToDoPresenter { ...@@ -111,7 +118,7 @@ public class ToDoPresenter {
private ToDoRouting routing = ToDoRouting.ALL; private ToDoRouting routing = ToDoRouting.ALL;
private boolean suppressStateChanged = false; private EventBus eventBus;
public ToDoPresenter(View view) { public ToDoPresenter(View view) {
this.view = view; this.view = view;
...@@ -127,6 +134,25 @@ public class ToDoPresenter { ...@@ -127,6 +134,25 @@ public class ToDoPresenter {
updateTaskStatistics(); updateTaskStatistics();
setupHistoryHandler(); setupHistoryHandler();
eventBus = ToDoEvent.getGlobalEventBus();
// listen to edits on individual items
eventBus.addHandler(ToDoUpdatedEvent.TYPE, new ToDoUpdatedEvent.Handler() {
@Override
public void onEvent(ToDoUpdatedEvent event) {
itemStateChanged(event.getToDo());
}
});
// listen to removals
eventBus.addHandler(ToDoRemovedEvent.TYPE, new ToDoRemovedEvent.Handler() {
@Override
public void onEvent(ToDoRemovedEvent event) {
deleteTask(event.getToDo());
}
});
} }
/** /**
...@@ -176,7 +202,7 @@ public class ToDoPresenter { ...@@ -176,7 +202,7 @@ public class ToDoPresenter {
int completeTask = 0; int completeTask = 0;
for (ToDoItem task : todos) { for (ToDoItem task : todos) {
if (task.isDone()) { if (task.isCompleted()) {
completeTask++; completeTask++;
} }
} }
...@@ -197,12 +223,7 @@ public class ToDoPresenter { ...@@ -197,12 +223,7 @@ public class ToDoPresenter {
*/ */
protected void itemStateChanged(ToDoItem toDoItem) { protected void itemStateChanged(ToDoItem toDoItem) {
if (suppressStateChanged) { toDoItem.setTitle(toDoItem.getTitle().trim());
return;
}
boolean notify = false;
toDoItem.setTitle(toDoItem.getTitle().trim(), notify);
if (toDoItem.getTitle().isEmpty()) { if (toDoItem.getTitle().isEmpty()) {
todos.remove(toDoItem); todos.remove(toDoItem);
...@@ -225,12 +246,9 @@ public class ToDoPresenter { ...@@ -225,12 +246,9 @@ public class ToDoPresenter {
*/ */
private void markAllCompleted(boolean completed) { private void markAllCompleted(boolean completed) {
// update the completed state of each item
suppressStateChanged = true;
for (ToDoItem task : todos) { for (ToDoItem task : todos) {
task.setDone(completed); task.setCompleted(completed);
} }
suppressStateChanged = false;
taskStateChanged(); taskStateChanged();
} }
...@@ -245,7 +263,7 @@ public class ToDoPresenter { ...@@ -245,7 +263,7 @@ public class ToDoPresenter {
if (taskTitle.equals("")) if (taskTitle.equals(""))
return; return;
ToDoItem toDoItem = new ToDoItem(taskTitle, this); ToDoItem toDoItem = new ToDoItem(taskTitle);
view.clearTaskText(); view.clearTaskText();
todos.add(toDoItem); todos.add(toDoItem);
...@@ -259,7 +277,7 @@ public class ToDoPresenter { ...@@ -259,7 +277,7 @@ public class ToDoPresenter {
Iterator<ToDoItem> iterator = todos.iterator(); Iterator<ToDoItem> iterator = todos.iterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {
ToDoItem item = iterator.next(); ToDoItem item = iterator.next();
if (item.isDone()) { if (item.isCompleted()) {
iterator.remove(); iterator.remove();
} }
} }
...@@ -280,7 +298,7 @@ public class ToDoPresenter { ...@@ -280,7 +298,7 @@ public class ToDoPresenter {
ToDoItem toDoItem = todos.get(i); ToDoItem toDoItem = todos.get(i);
JSONObject jsonObject = new JSONObject(); JSONObject jsonObject = new JSONObject();
jsonObject.put("task", new JSONString(toDoItem.getTitle())); jsonObject.put("task", new JSONString(toDoItem.getTitle()));
jsonObject.put("complete", JSONBoolean.getInstance(toDoItem.isDone())); jsonObject.put("complete", JSONBoolean.getInstance(toDoItem.isCompleted()));
todoItems.set(i, jsonObject); todoItems.set(i, jsonObject);
} }
...@@ -304,7 +322,7 @@ public class ToDoPresenter { ...@@ -304,7 +322,7 @@ public class ToDoPresenter {
String task = jsonObject.get("task").isString().stringValue(); String task = jsonObject.get("task").isString().stringValue();
boolean completed = jsonObject.get("complete").isBoolean().booleanValue(); boolean completed = jsonObject.get("complete").isBoolean().booleanValue();
// add a new item to our list // add a new item to our list
todos.add(new ToDoItem(task, completed, this)); todos.add(new ToDoItem(task, completed));
} }
} catch (Exception e) { } catch (Exception e) {
......
...@@ -40,7 +40,7 @@ public enum ToDoRouting { ...@@ -40,7 +40,7 @@ public enum ToDoRouting {
private static class MatchActive implements Matcher { private static class MatchActive implements Matcher {
@Override @Override
public boolean matches(ToDoItem item) { public boolean matches(ToDoItem item) {
return !item.isDone(); return !item.isCompleted();
} }
} }
...@@ -50,7 +50,7 @@ public enum ToDoRouting { ...@@ -50,7 +50,7 @@ public enum ToDoRouting {
private static class MatchCompleted implements Matcher { private static class MatchCompleted implements Matcher {
@Override @Override
public boolean matches(ToDoItem item) { public boolean matches(ToDoItem item) {
return item.isDone(); return item.isCompleted();
} }
} }
......
package com.todo.client.events;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.event.shared.EventHandler;
import com.google.gwt.event.shared.GwtEvent;
import com.google.gwt.event.shared.SimpleEventBus;
import com.todo.client.ToDoItem;
public abstract class ToDoEvent<H extends EventHandler> extends GwtEvent<H> {
private final ToDoItem toDo;
public ToDoEvent(ToDoItem toDo) {
this.toDo = toDo;
}
public ToDoItem getToDo() {
return toDo;
}
/* This acts as a global event bus factory */
private static EventBus eventBus = new SimpleEventBus();
public static EventBus getGlobalEventBus() {
return eventBus;
}
}
package com.todo.client.events;
import com.google.gwt.event.shared.EventHandler;
import com.todo.client.ToDoItem;
public class ToDoRemovedEvent extends ToDoEvent<ToDoRemovedEvent.Handler> {
public static final Type<ToDoRemovedEvent.Handler> TYPE = new Type<ToDoRemovedEvent.Handler>();
public static interface Handler extends EventHandler {
void onEvent(ToDoRemovedEvent event);
}
public ToDoRemovedEvent(ToDoItem toDo) {
super(toDo);
}
@Override
public Type<ToDoRemovedEvent.Handler> getAssociatedType() {
return TYPE;
}
@Override
protected void dispatch(ToDoRemovedEvent.Handler handler) {
handler.onEvent(this);
}
}
\ No newline at end of file
package com.todo.client.events;
import com.google.gwt.event.shared.EventHandler;
import com.todo.client.ToDoItem;
public class ToDoUpdatedEvent extends ToDoEvent<ToDoUpdatedEvent.Handler> {
public static final Type<ToDoUpdatedEvent.Handler> TYPE = new Type<ToDoUpdatedEvent.Handler>();
public static interface Handler extends EventHandler {
void onEvent(ToDoUpdatedEvent event);
}
public ToDoUpdatedEvent(ToDoItem toDo) {
super(toDo);
}
@Override
public Type<ToDoUpdatedEvent.Handler> getAssociatedType() {
return TYPE;
}
@Override
protected void dispatch(ToDoUpdatedEvent.Handler handler) {
handler.onEvent(this);
}
}
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment