You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by do...@apache.org on 2013/08/21 18:35:18 UTC

svn commit: r1516205 [3/9] - in /james/hupa/trunk: ./ client/src/main/java/org/apache/hupa/ client/src/main/java/org/apache/hupa/client/ client/src/main/java/org/apache/hupa/client/gin/ client/src/main/java/org/apache/hupa/client/mvp/ client/src/main/j...

Added: james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/MainPresenter.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/MainPresenter.java?rev=1516205&view=auto
==============================================================================
--- james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/MainPresenter.java (added)
+++ james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/MainPresenter.java Wed Aug 21 16:35:16 2013
@@ -0,0 +1,544 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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 org.apache.hupa.client.mvp;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import net.customware.gwt.presenter.client.EventBus;
+import net.customware.gwt.presenter.client.widget.WidgetContainerDisplay;
+import net.customware.gwt.presenter.client.widget.WidgetContainerPresenter;
+
+import org.apache.hupa.client.CachingDispatchAsync;
+import org.apache.hupa.client.HupaCallback;
+import org.apache.hupa.client.mvp.MessageSendPresenter.Type;
+import org.apache.hupa.client.widgets.HasDialog;
+import org.apache.hupa.client.widgets.IMAPTreeItem;
+import org.apache.hupa.shared.data.IMAPFolder;
+import org.apache.hupa.shared.data.Message;
+import org.apache.hupa.shared.data.MessageDetails;
+import org.apache.hupa.shared.data.User;
+import org.apache.hupa.shared.data.Message.IMAPFlag;
+import org.apache.hupa.shared.events.BackEvent;
+import org.apache.hupa.shared.events.BackEventHandler;
+import org.apache.hupa.shared.events.DecreaseUnseenEvent;
+import org.apache.hupa.shared.events.DecreaseUnseenEventHandler;
+import org.apache.hupa.shared.events.ExpandMessageEvent;
+import org.apache.hupa.shared.events.ExpandMessageEventHandler;
+import org.apache.hupa.shared.events.FolderSelectionEvent;
+import org.apache.hupa.shared.events.FolderSelectionEventHandler;
+import org.apache.hupa.shared.events.ForwardMessageEvent;
+import org.apache.hupa.shared.events.ForwardMessageEventHandler;
+import org.apache.hupa.shared.events.IncreaseUnseenEvent;
+import org.apache.hupa.shared.events.IncreaseUnseenEventHandler;
+import org.apache.hupa.shared.events.LoadMessagesEvent;
+import org.apache.hupa.shared.events.LoadMessagesEventHandler;
+import org.apache.hupa.shared.events.LoginEvent;
+import org.apache.hupa.shared.events.LoginEventHandler;
+import org.apache.hupa.shared.events.MessagesReceivedEvent;
+import org.apache.hupa.shared.events.MessagesReceivedEventHandler;
+import org.apache.hupa.shared.events.NewMessageEvent;
+import org.apache.hupa.shared.events.NewMessageEventHandler;
+import org.apache.hupa.shared.events.ReplyMessageEvent;
+import org.apache.hupa.shared.events.ReplyMessageEventHandler;
+import org.apache.hupa.shared.events.SentMessageEvent;
+import org.apache.hupa.shared.events.SentMessageEventHandler;
+import org.apache.hupa.shared.rpc.CreateFolder;
+import org.apache.hupa.shared.rpc.DeleteFolder;
+import org.apache.hupa.shared.rpc.FetchFolders;
+import org.apache.hupa.shared.rpc.FetchFoldersResult;
+import org.apache.hupa.shared.rpc.GenericResult;
+import org.apache.hupa.shared.rpc.GetMessageDetails;
+import org.apache.hupa.shared.rpc.GetMessageDetailsResult;
+import org.apache.hupa.shared.rpc.RenameFolder;
+import org.apache.hupa.widgets.event.EditEvent;
+import org.apache.hupa.widgets.event.EditHandler;
+import org.apache.hupa.widgets.ui.HasEditable;
+import org.apache.hupa.widgets.ui.HasEnable;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.HasClickHandlers;
+import com.google.gwt.event.logical.shared.HasSelectionHandlers;
+import com.google.gwt.event.logical.shared.SelectionEvent;
+import com.google.gwt.event.logical.shared.SelectionHandler;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.google.gwt.user.client.ui.TreeItem;
+import com.google.inject.Inject;
+
+/**
+ *
+ */
+public class MainPresenter extends WidgetContainerPresenter<MainPresenter.Display> {
+
+    public interface Display extends NameAwareWidgetDisplay, WidgetContainerDisplay {
+      
+        public HasSelectionHandlers<TreeItem> getTree();
+
+        public void bindTreeItems(List<IMAPTreeItem> treeList);
+
+        public HasClickHandlers getRenameClick();
+
+        public HasClickHandlers getDeleteClick();
+
+        public HasClickHandlers getNewClick();
+
+        public HasDialog getDeleteConfirmDialog();
+
+        public HasClickHandlers getDeleteConfirmClick();
+
+        public HasEnable getRenameEnable();
+
+        public HasEnable getDeleteEnable();
+
+        public HasEnable getNewEnable();
+
+        public void updateTreeItem(IMAPFolder folder);
+
+        public void deleteSelectedFolder();
+
+        public HasEditable createFolder(EditHandler handler);
+
+        public void increaseUnseenMessageCount(IMAPFolder folder, int amount);
+
+        public void decreaseUnseenMessageCount(IMAPFolder folder, int amount);
+        
+        public void setLoadingFolders(boolean loading);
+        public void setLoadingMessage(boolean loading);
+
+    }
+
+    private CachingDispatchAsync cachingDispatcher;
+    private User user;
+    private IMAPFolder folder;
+    private String searchValue;
+    private IMAPMessageListPresenter messageListPresenter;
+    private IMAPMessagePresenter messagePresenter;
+    private MessageSendPresenter sendPresenter;
+    private IMAPTreeItem tItem;
+    private HasEditable editableTreeItem;
+    
+    @Inject
+    public MainPresenter(MainPresenter.Display display, EventBus bus, CachingDispatchAsync cachingDispatcher, IMAPMessageListPresenter messageListPresenter, IMAPMessagePresenter messagePresenter,
+            MessageSendPresenter sendPresenter) {
+        super(display, bus, messageListPresenter, messagePresenter, sendPresenter);
+        this.cachingDispatcher = cachingDispatcher;
+        this.messageListPresenter = messageListPresenter;
+        this.messagePresenter = messagePresenter;
+        this.sendPresenter = sendPresenter;
+        
+    }
+
+    protected void loadTreeItems() {
+        display.setLoadingFolders(true);
+        cachingDispatcher.execute(new FetchFolders(), new HupaCallback<FetchFoldersResult>(cachingDispatcher, eventBus, display) {
+            public void callback(FetchFoldersResult result) {
+                display.bindTreeItems(createTreeNodes(result.getFolders()));
+                // disable
+                display.getDeleteEnable().setEnabled(false);
+                display.getRenameEnable().setEnabled(false);
+                display.setLoadingFolders(false);
+
+            }
+        });
+    }
+
+    /**
+     * Create recursive the TreeNodes with all childs
+     * 
+     * @param list
+     * @return
+     */
+    private List<IMAPTreeItem> createTreeNodes(List<IMAPFolder> list) {
+        List<IMAPTreeItem> tList = new ArrayList<IMAPTreeItem>();
+
+        for (IMAPFolder iFolder : list) {
+
+            final IMAPTreeItem record = new IMAPTreeItem(iFolder);
+            record.addEditHandler(new EditHandler() {
+
+                public void onEditEvent(EditEvent event) {
+                    if (event.getEventType().equals(EditEvent.EventType.Stop)) {
+                        IMAPFolder iFolder = new IMAPFolder((String) event.getOldValue());
+                        final String newName = (String) event.getNewValue();
+                        if (iFolder.getFullName().equalsIgnoreCase(newName) == false) {
+                            cachingDispatcher.execute(new RenameFolder(iFolder, newName), new HupaCallback<GenericResult>(cachingDispatcher, eventBus) {
+                                public void callback(GenericResult result) {
+                                    folder.setFullName(newName);
+                                }
+                                public void callbackError(Throwable caught) {
+                                    record.cancelEdit();
+                                }
+                            }); 
+                        }
+                    }
+                }
+
+            });
+            record.setUserObject(iFolder);
+
+            List<IMAPFolder> childFolders = iFolder.getChildIMAPFolders();
+            List<IMAPTreeItem> items = createTreeNodes(childFolders);
+            for (IMAPTreeItem item : items) {
+                record.addItem(item);
+            }
+
+            // Store the INBOX as starting point after first loading
+            if (iFolder.getFullName().equals(user.getSettings().getInboxFolderName())) {
+                folder = iFolder;
+                tItem = record;
+            }
+
+            tList.add(record);
+        }
+
+        // Sort tree
+        Collections.sort(tList, new Comparator<TreeItem>() {
+
+            public int compare(TreeItem o1, TreeItem o2) {
+                return o1.getText().compareTo(o2.getText());
+            }
+
+        });
+        return tList;
+    }
+
+    private void showMessageTable(User user, IMAPFolder folder, String searchValue) {
+        this.user = user;
+        this.folder = folder;
+        this.searchValue = searchValue;
+        firePresenterChangedEvent();
+
+        messageListPresenter.revealDisplay(user, folder, searchValue);
+    }
+
+    private void showMessage(User user, IMAPFolder folder, Message message, MessageDetails details) {
+        messagePresenter.revealDisplay(user, folder, message, details);
+    }
+
+    private void showNewMessage() {
+        sendPresenter.revealDisplay(user);
+    }
+
+    private void showForwardMessage(ForwardMessageEvent event) {
+        sendPresenter.revealDisplay(event.getUser(), event.getFolder(), event.getMessage(), event.getMessageDetails(), Type.FORWARD);
+    }
+
+    private void showReplyMessage(ReplyMessageEvent event) {
+        if (event.getReplyAll()) {
+            sendPresenter.revealDisplay(event.getUser(), event.getFolder(), event.getMessage(), event.getMessageDetails(), Type.REPLY_ALL);
+        } else {
+            sendPresenter.revealDisplay(event.getUser(), event.getFolder(), event.getMessage(), event.getMessageDetails(), Type.REPLY);
+
+        }
+        sendPresenter.revealDisplay();
+    }
+
+    /**
+     * Reset the presenter and display
+     */
+    private void reset() {
+        // clear the cache
+        cachingDispatcher.clear();
+    }
+
+
+    @Override
+    protected void onBind() {
+        super.onBind();
+        registerHandler(eventBus.addHandler(LoadMessagesEvent.TYPE, new LoadMessagesEventHandler() {
+
+            public void onLoadMessagesEvent(LoadMessagesEvent loadMessagesEvent) {
+                showMessageTable(loadMessagesEvent.getUser(), loadMessagesEvent.getFolder(), loadMessagesEvent.getSearchValue());
+            }
+
+        }));
+
+
+        registerHandler(eventBus.addHandler(ExpandMessageEvent.TYPE, new ExpandMessageEventHandler() {
+
+            public void onExpandMessage(ExpandMessageEvent event) {
+                final boolean decreaseUnseen;
+                final Message message = event.getMessage();
+                // check if the message was already seen in the past
+                if (event.getMessage().getFlags().contains(IMAPFlag.SEEN) == false) {
+                    decreaseUnseen = true;
+                } else {
+                    decreaseUnseen = false;
+                }
+
+                display.setLoadingMessage(true);
+                cachingDispatcher.executeWithCache(new GetMessageDetails(event.getFolder(), message.getUid()), new HupaCallback<GetMessageDetailsResult>(cachingDispatcher, eventBus, display) {
+                    public void callback(GetMessageDetailsResult result) {
+                        if (decreaseUnseen) {
+                            eventBus.fireEvent(new DecreaseUnseenEvent(user, folder));
+                        }
+                        display.setLoadingMessage(false);
+                        showMessage(user, folder, message, result.getMessageDetails());
+                    }
+                });
+            }
+
+        }));
+        registerHandler(eventBus.addHandler(NewMessageEvent.TYPE, new NewMessageEventHandler() {
+
+            public void onNewMessageEvent(NewMessageEvent event) {
+                showNewMessage();
+            }
+
+        }));
+
+        registerHandler(eventBus.addHandler(SentMessageEvent.TYPE, new SentMessageEventHandler() {
+
+            public void onSentMessageEvent(SentMessageEvent ev) {
+                showMessageTable(user, folder, searchValue);
+            }
+
+        }));
+
+        registerHandler(eventBus.addHandler(ForwardMessageEvent.TYPE, new ForwardMessageEventHandler() {
+
+            public void onForwardMessageEvent(ForwardMessageEvent event) {
+                showForwardMessage(event);
+            }
+
+        }));
+        registerHandler(eventBus.addHandler(ReplyMessageEvent.TYPE, new ReplyMessageEventHandler() {
+
+            public void onReplyMessageEvent(ReplyMessageEvent event) {
+                showReplyMessage(event);
+            }
+
+        }));
+        registerHandler(eventBus.addHandler(FolderSelectionEvent.TYPE, new FolderSelectionEventHandler() {
+
+            public void onFolderSelectionEvent(FolderSelectionEvent event) {
+                user = event.getUser();
+                folder = event.getFolder();
+                showMessageTable(user, event.getFolder(), searchValue);
+            }
+
+        }));
+
+        registerHandler(eventBus.addHandler(BackEvent.TYPE, new BackEventHandler() {
+
+            public void onBackEvent(BackEvent event) {
+                showMessageTable(user, folder, searchValue);
+            }
+
+        }));
+
+        registerHandler(eventBus.addHandler(ExpandMessageEvent.TYPE, new ExpandMessageEventHandler() {
+
+            public void onExpandMessage(ExpandMessageEvent event) {
+                if (editableTreeItem != null && editableTreeItem.isEdit()) {
+                    editableTreeItem.cancelEdit();
+                }
+            }
+
+        }));
+        registerHandler(eventBus.addHandler(NewMessageEvent.TYPE, new NewMessageEventHandler() {
+
+            public void onNewMessageEvent(NewMessageEvent event) {
+                if (editableTreeItem != null && editableTreeItem.isEdit()) {
+                    editableTreeItem.cancelEdit();
+                }
+            }
+
+        }));
+        registerHandler(eventBus.addHandler(DecreaseUnseenEvent.TYPE, new DecreaseUnseenEventHandler() {
+
+            public void onDecreaseUnseenEvent(DecreaseUnseenEvent event) {
+                display.decreaseUnseenMessageCount(event.getFolder(), event.getAmount());
+            }
+
+        }));
+        registerHandler(eventBus.addHandler(IncreaseUnseenEvent.TYPE, new IncreaseUnseenEventHandler() {
+
+            public void onIncreaseUnseenEvent(IncreaseUnseenEvent event) {
+                display.increaseUnseenMessageCount(event.getFolder(), event.getAmount());
+            }
+
+        }));
+        registerHandler(display.getTree().addSelectionHandler(new SelectionHandler<TreeItem>() {
+
+            public void onSelection(SelectionEvent<TreeItem> event) {
+                tItem = (IMAPTreeItem) event.getSelectedItem();
+                if (tItem.isEdit()) 
+                    return;
+                folder = (IMAPFolder) tItem.getUserObject();
+                eventBus.fireEvent(new LoadMessagesEvent(user, folder));
+            }
+
+        }));
+
+        registerHandler(display.getTree().addSelectionHandler(new SelectionHandler<TreeItem>() {
+
+            public void onSelection(SelectionEvent<TreeItem> event) {
+                tItem = (IMAPTreeItem) event.getSelectedItem();
+                if (tItem.isEdit()) 
+                    return;
+                folder = (IMAPFolder) tItem.getUserObject();
+                if (folder.getFullName().equalsIgnoreCase(user.getSettings().getInboxFolderName())) {
+                    display.getDeleteEnable().setEnabled(false);
+                    display.getRenameEnable().setEnabled(false);
+                } else {
+                    display.getDeleteEnable().setEnabled(true);
+                    display.getRenameEnable().setEnabled(true);
+                }
+            }
+
+        }));
+
+        registerHandler(display.getRenameClick().addClickHandler(new ClickHandler() {
+
+            public void onClick(ClickEvent event) {
+                tItem.startEdit();
+            }
+
+        }));
+
+        registerHandler(display.getDeleteClick().addClickHandler(new ClickHandler() {
+
+            public void onClick(ClickEvent event) {
+                display.getDeleteConfirmDialog().show();
+            }
+
+        }));
+
+        registerHandler(display.getDeleteConfirmClick().addClickHandler(new ClickHandler() {
+
+            public void onClick(ClickEvent event) {
+                cachingDispatcher.execute(new DeleteFolder(folder), new AsyncCallback<GenericResult>() {
+
+                    public void onFailure(Throwable caught) {
+                        GWT.log("ERROR while deleting", caught);
+                    }
+
+                    public void onSuccess(GenericResult result) {
+                        display.deleteSelectedFolder();
+                    }
+
+                });
+            }
+
+        }));
+
+        registerHandler(display.getNewClick().addClickHandler(new ClickHandler() {
+
+            public void onClick(ClickEvent event) {
+                editableTreeItem = display.createFolder(new EditHandler() {
+
+                    public void onEditEvent(EditEvent event) {
+                        final IMAPTreeItem item = (IMAPTreeItem) event.getSource();
+                        final String newValue = (String) event.getNewValue();
+                        if (event.getEventType().equals(EditEvent.EventType.Stop)) {
+                            cachingDispatcher.execute(new CreateFolder(new IMAPFolder(newValue.trim())), new AsyncCallback<GenericResult>() {
+
+                                public void onFailure(Throwable caught) {
+                                    GWT.log("Error while create folder", caught);
+                                    item.cancelEdit();
+                                }
+
+                                public void onSuccess(GenericResult result) {
+                                    // Nothing todo
+                                }
+
+                            });
+                        }
+                    }
+
+                });
+            }
+
+        }));
+
+        registerHandler(eventBus.addHandler(MessagesReceivedEvent.TYPE, new MessagesReceivedEventHandler() {
+
+            public void onMessagesReceived(MessagesReceivedEvent event) {
+                IMAPFolder f = event.getFolder();
+                display.updateTreeItem(f);
+            }
+
+        }));
+        
+        registerHandler(eventBus.addHandler(LoginEvent.TYPE,  new LoginEventHandler() {
+
+            public void onLogin(LoginEvent event) {
+                user = event.getUser();
+                folder = new IMAPFolder(user.getSettings().getInboxFolderName());
+                messageListPresenter.revealDisplay(user, folder, null);
+            }
+            
+        }));
+        
+        // Export native javascript methods
+        exportJSMethods(this);
+
+    }
+
+
+    @Override
+    protected void onUnbind() {
+        reset();
+
+        super.onUnbind();
+    }
+
+    
+    public void revealDisplay(User user) {
+        this.user = user;
+        loadTreeItems();  
+        revealDisplay();
+    }
+    
+    @Override
+    protected void onRevealDisplay() {
+        showMessageTable(user, folder, searchValue);
+        super.onRevealDisplay();
+    }
+    
+    public void openLink(String url) {
+        Window.open(url, "_blank", "");
+    }
+
+    public void mailTo(String mailto) {
+        sendPresenter.revealDisplay(user, mailto);
+    }
+    
+    private native void exportJSMethods(MainPresenter presenter) /*-{
+      $wnd.openLink = function(url) {
+        try {
+           presenter.@org.apache.hupa.client.mvp.MainPresenter::openLink(Ljava/lang/String;) (url);
+        } catch(e) {}
+        return false;
+      };
+      $wnd.mailTo = function(mail) {
+        try {
+           presenter.@org.apache.hupa.client.mvp.MainPresenter::mailTo(Ljava/lang/String;) (mail);
+        } catch(e) {}
+        return false;
+      };
+    }-*/;
+}

Added: james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/MainView.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/MainView.java?rev=1516205&view=auto
==============================================================================
--- james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/MainView.java (added)
+++ james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/MainView.java Wed Aug 21 16:35:16 2013
@@ -0,0 +1,577 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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 org.apache.hupa.client.mvp;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.customware.gwt.presenter.client.EventBus;
+
+import org.apache.hupa.client.HupaCSS;
+import org.apache.hupa.client.HupaConstants;
+import org.apache.hupa.client.HupaMessages;
+import org.apache.hupa.client.bundles.IMAPTreeImages;
+import org.apache.hupa.client.dnd.PagingScrollTableRowDragController;
+import org.apache.hupa.client.widgets.ConfirmDialogBox;
+import org.apache.hupa.client.widgets.HasDialog;
+import org.apache.hupa.client.widgets.IMAPTreeItem;
+import org.apache.hupa.shared.data.IMAPFolder;
+import org.apache.hupa.shared.data.Message;
+import org.apache.hupa.shared.data.User;
+import org.apache.hupa.shared.data.Message.IMAPFlag;
+import org.apache.hupa.shared.events.LoginEvent;
+import org.apache.hupa.shared.events.LoginEventHandler;
+import org.apache.hupa.shared.events.LogoutEvent;
+import org.apache.hupa.shared.events.LogoutEventHandler;
+import org.apache.hupa.shared.events.MoveMessageEvent;
+import org.apache.hupa.widgets.event.EditEvent;
+import org.apache.hupa.widgets.event.EditHandler;
+import org.apache.hupa.widgets.ui.EnableHyperlink;
+import org.apache.hupa.widgets.ui.HasEditable;
+import org.apache.hupa.widgets.ui.HasEnable;
+import org.apache.hupa.widgets.ui.Loading;
+import org.apache.hupa.widgets.ui.RndPanel;
+
+import com.allen_sauer.gwt.dnd.client.DragContext;
+import com.allen_sauer.gwt.dnd.client.VetoDragException;
+import com.allen_sauer.gwt.dnd.client.drop.DropController;
+import com.allen_sauer.gwt.dnd.client.drop.SimpleDropController;
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.event.dom.client.HasClickHandlers;
+import com.google.gwt.event.logical.shared.HasSelectionHandlers;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.DockPanel;
+import com.google.gwt.user.client.ui.HorizontalPanel;
+import com.google.gwt.user.client.ui.SimplePanel;
+import com.google.gwt.user.client.ui.Tree;
+import com.google.gwt.user.client.ui.TreeItem;
+import com.google.gwt.user.client.ui.VerticalPanel;
+import com.google.gwt.user.client.ui.Widget;
+import com.google.inject.Inject;
+
+/**
+ * MainView acts like a container of other widgets which will get displayed after the user successfully logged in
+ * 
+ *
+ */
+public class MainView extends Composite implements MainPresenter.Display {
+
+    private DockPanel dockPanel;
+    private VerticalPanel north;
+    private HupaConstants constants;
+    private RndPanel west;
+    private IMAPTreeImages tImages = GWT.create(IMAPTreeImages.class);
+    private Tree folderTree = new Tree(tImages, true);
+  
+    private Widget centerWidget;
+    private RndPanel center;
+    private IMAPMessageListView mListView;
+    private HupaMessages messages;
+    private VerticalPanel folderPanel = new VerticalPanel();
+    private SimplePanel panel = new SimplePanel();
+    private HorizontalPanel folderButtonBar = new HorizontalPanel();
+    private EnableHyperlink newFolderButton;
+    private EnableHyperlink renameFolderButton;
+    private EnableHyperlink deleteFolderButton;
+    private ConfirmDialogBox confirmFolderDeleteBox = new ConfirmDialogBox();
+    private Loading loader;
+    private Loading messageLoader = new Loading();
+    private List<DropController> dropControllerList = new ArrayList<DropController>();
+    private EventBus bus;
+    private PagingScrollTableRowDragController controller;
+    protected User user;
+
+    @Inject
+    public MainView(EventBus bus, PagingScrollTableRowDragController controllerProvider, HupaConstants constants, HupaMessages messages) {
+        this.constants = constants;
+        this.messages = messages;
+        this.controller = controllerProvider;
+        this.bus = bus;
+        loader = new Loading(constants.loading());
+        newFolderButton = new EnableHyperlink(constants.newFolder(), "");
+        renameFolderButton = new EnableHyperlink(constants.renameFolder(), "");
+        deleteFolderButton = new EnableHyperlink(constants.deleteFolder(), "");
+        
+        dockPanel = new DockPanel();
+
+        dockPanel.setSpacing(10);
+        dockPanel.setWidth("100%");
+
+        createNorth();
+        createWest();
+        createCenter();
+
+        dockPanel.add(north, DockPanel.NORTH);
+        dockPanel.add(west, DockPanel.WEST);
+        dockPanel.setCellWidth(west, "160px");
+        dockPanel.add(center, DockPanel.CENTER);
+        dockPanel.setCellHorizontalAlignment(north, DockPanel.ALIGN_RIGHT);
+        dockPanel.setCellHorizontalAlignment(center, DockPanel.ALIGN_LEFT);
+
+        initWidget(dockPanel);
+    }
+
+    private void createWest() {
+        west = new RndPanel();
+        west.add(folderTree);
+        west.addStyleName(HupaCSS.C_tree_container);
+
+        folderTree.setAnimationEnabled(true);
+        folderPanel.setSpacing(5);
+
+        folderButtonBar.setSpacing(3);
+        folderButtonBar.add(newFolderButton);
+        folderButtonBar.add(renameFolderButton);
+        folderButtonBar.add(deleteFolderButton);
+        folderPanel.add(folderButtonBar);
+        folderPanel.add(folderTree);
+        panel.add(loader);
+        confirmFolderDeleteBox.setText(messages.confirmDeleteFolder());
+        bus.addHandler(LoginEvent.TYPE, new LoginEventHandler() {
+
+            public void onLogin(LoginEvent event) {
+                user = event.getUser();
+            }
+
+        });
+        bus.addHandler(LogoutEvent.TYPE, new LogoutEventHandler() {
+
+            public void onLogout(LogoutEvent event) {
+                user = null;
+            }
+
+        });
+        west.add(panel);
+    }
+
+    private void createNorth() {
+        north = new VerticalPanel();
+        north.setWidth("100%");
+    }
+
+    private void createCenter() {
+        center = new RndPanel();
+        center.setWidth("100%");
+        // FIXME: 
+        if (mListView != null)
+            center.add(mListView);
+    }
+
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.hupa.client.mvp.MainPresenter.Display#bindTreeItems(java.util.ArrayList)
+     */
+    public void bindTreeItems(List<IMAPTreeItem> treeList) {
+        folderTree.clear();
+        for (DropController dropController : dropControllerList) {
+            controller.unregisterDropController(dropController);
+        }
+
+        for (IMAPTreeItem iTreeItem : treeList) {
+            bindDropController(iTreeItem);
+            folderTree.addItem(iTreeItem);
+
+            if (((IMAPFolder) iTreeItem.getUserObject()).getFullName().equalsIgnoreCase(user.getSettings().getInboxFolderName())) {
+                folderTree.setSelectedItem(iTreeItem, false);
+            }
+
+        }
+    }
+
+    /**
+     * Bind a IMAPFolderDropController to the given Item and all its childs
+     * 
+     * @param item
+     */
+    private void bindDropController(IMAPTreeItem item) {
+        IMAPFolderDropController dropController = new IMAPFolderDropController(item);
+        controller.registerDropController(dropController);
+        dropControllerList.add(dropController);
+
+        if (item.getChildCount() > 0) {
+            for (int i = 0; i < item.getChildCount(); i++) {
+                bindDropController((IMAPTreeItem) item.getChild(i));
+            }
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.hupa.client.mvp.IMAPFolderPresenter.Display#getTree()
+     */
+    public HasSelectionHandlers<TreeItem> getTree() {
+        return folderTree;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see net.customware.gwt.presenter.client.widget.WidgetDisplay#asWidget()
+     */
+    public Widget asWidget() {
+        return this;
+    }
+
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.hupa.client.mvp.MainPresenter.Display#setLoadingFolders(boolean)
+     */
+    public void setLoadingFolders(boolean load) {
+        if (load) {
+            loader.show();
+            panel.clear();
+            panel.add(loader);
+        } else {
+            panel.clear();
+            panel.add(folderPanel);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.hupa.client.mvp.MainPresenter.Display#setLoadingMessage(boolean)
+     */
+    public void setLoadingMessage(boolean load) {
+        if (load) {
+            messageLoader.show();
+        } else {
+            messageLoader.hide();
+        }
+    }
+
+    /**
+     * Drop controller which handle drop on TreeItems
+     * 
+     * 
+     */
+    private class IMAPFolderDropController extends SimpleDropController {
+        private IMAPTreeItem item;
+
+        public IMAPFolderDropController(IMAPTreeItem item) {
+            super(item.getWidget());
+            this.item = item;
+        }
+
+        /**
+         * Veto the Drop if the folder is the same
+         */
+        @Override
+        public void onPreviewDrop(DragContext context) throws VetoDragException {
+            if (item.equals(folderTree.getSelectedItem())) {
+                throw new VetoDragException();
+            }
+        }
+
+        /**
+         * Set the right unseen count on the folders and fire an event
+         */
+        @Override
+        public void onDrop(DragContext context) {
+            IMAPTreeItem oldTreeItem = (IMAPTreeItem) folderTree.getSelectedItem();
+            Message message = (Message) controller.getDragValue();
+            if (message.getFlags().contains(IMAPFlag.SEEN) == false) {
+                oldTreeItem.decreaseUnseenMessageCount();
+                item.increaseUnseenMessageCount();
+            }
+            bus.fireEvent(new MoveMessageEvent(user, (IMAPFolder) oldTreeItem.getUserObject(), (IMAPFolder) item.getUserObject(), message));
+        }
+
+        /**
+         * Update the proxy widget to show its valid to drop it
+         * 
+         */
+        @Override
+        public void onEnter(DragContext context) {
+            if (item.equals(folderTree.getSelectedItem()) == false) {
+                controller.getCurrentProxy().setIsValid(true);
+            }
+            super.onEnter(context);
+        }
+
+        /**
+         * Update the proxy widget to show its invalid to drop it
+         */
+        @Override
+        public void onLeave(DragContext context) {
+            controller.getCurrentProxy().setIsValid(false);
+            super.onLeave(context);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.hupa.client.mvp.IMAPFolderPresenter.Display#getRenameClick()
+     */
+    public HasClickHandlers getRenameClick() {
+        return renameFolderButton;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.hupa.client.mvp.IMAPFolderPresenter.Display#getDeleteEnable()
+     */
+    public HasEnable getDeleteEnable() {
+        return deleteFolderButton;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.hupa.client.mvp.IMAPFolderPresenter.Display#getNewEnable()
+     */
+    public HasEnable getNewEnable() {
+        return newFolderButton;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.hupa.client.mvp.IMAPFolderPresenter.Display#getRenameEnable()
+     */
+    public HasEnable getRenameEnable() {
+        return renameFolderButton;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.hupa.client.mvp.IMAPFolderPresenter.Display#getDeleteClick()
+     */
+    public HasClickHandlers getDeleteClick() {
+        return deleteFolderButton;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.hupa.client.mvp.IMAPFolderPresenter.Display#getNewClick()
+     */
+    public HasClickHandlers getNewClick() {
+        return newFolderButton;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.hupa.client.mvp.IMAPFolderPresenter.Display#getDeleteConfirmDialog
+     * ()
+     */
+    public HasDialog getDeleteConfirmDialog() {
+        return confirmFolderDeleteBox;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.hupa.client.mvp.IMAPFolderPresenter.Display#getDeleteConfirmClick
+     * ()
+     */
+    public HasClickHandlers getDeleteConfirmClick() {
+        return confirmFolderDeleteBox;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.hupa.client.mvp.IMAPFolderPresenter.Display#deleteSelectedFolder
+     * ()
+     */
+    public void deleteSelectedFolder() {
+        folderTree.getSelectedItem().remove();
+
+        // Select the INBOX after delete folder
+        for (int i = 0; i < folderTree.getItemCount(); i++) {
+            IMAPTreeItem item = (IMAPTreeItem) folderTree.getItem(i);
+            if (((IMAPFolder) item.getUserObject()).getFullName().equalsIgnoreCase(user.getSettings().getInboxFolderName())) {
+                folderTree.setSelectedItem(item, true);
+                break;
+            }
+        }
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.hupa.client.mvp.IMAPFolderPresenter.Display#createFolder(org
+     * .apache.hupa.client.widgets.EditHandler)
+     */
+    public HasEditable createFolder(EditHandler handler) {
+        final IMAPTreeItem selected = (IMAPTreeItem) folderTree.getSelectedItem();
+        
+        if (selected.isEdit())
+            return null;
+        
+        IMAPFolder oldFolder = (IMAPFolder) selected.getUserObject();
+
+        // Generate a new folder with a whitespace as name, this is needed as
+        // workaround
+        IMAPFolder folder = new IMAPFolder(oldFolder.getFullName() + oldFolder.getDelimiter() + " ");
+        folder.setDelimiter(oldFolder.getDelimiter());
+
+        final IMAPTreeItem newItem = new IMAPTreeItem(folder);
+
+        // add the new item as child
+        folderTree.getSelectedItem().addItem(newItem);
+        newItem.addEditHandler(handler);
+        newItem.addEditHandler(new EditHandler() {
+
+            public void onEditEvent(EditEvent event) {
+                if (event.getEventType().equals(EditEvent.EventType.Cancel)) {
+                    // remove the folder
+                    newItem.remove();
+                    folderTree.setSelectedItem(selected, false);
+                } else if (event.getEventType().equals(EditEvent.EventType.Stop)) {
+                    // add the new item to dnd controller 
+                    bindDropController(newItem);
+                    // Select the parent folder to avoid an issue in gmail, because
+                    // the new folder takes a while until it is available
+                    folderTree.setSelectedItem(selected, false);
+                }
+            }
+
+        });
+        // Expand the parent
+        folderTree.getSelectedItem().setState(true, false);
+
+        // Select the new folder and start editing it
+        folderTree.setSelectedItem(newItem, false);
+        newItem.startEdit();
+
+        // reset the text of the new item (remove the whitespace)
+        newItem.setText("");
+        
+        return newItem;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @seeorg.apache.hupa.client.mvp.IMAPFolderPresenter.Display#
+     * decreaseUnseenMessageCount(org.apache.hupa.shared.data.IMAPFolder, int)
+     */
+    public void decreaseUnseenMessageCount(IMAPFolder folder, int amount) {
+        int count = folderTree.getItemCount();
+        for (int i = 0; i < count; i++) {
+            IMAPTreeItem item = findTreeItemForFolder((IMAPTreeItem) folderTree.getItem(i), folder);
+            if (item != null) {
+                item.descreaseUnseenMessageCount(amount);
+                break;
+            }
+
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @seeorg.apache.hupa.client.mvp.IMAPFolderPresenter.Display#
+     * increaseUnseenMessageCount(org.apache.hupa.shared.data.IMAPFolder, int)
+     */
+    public void increaseUnseenMessageCount(IMAPFolder folder, int amount) {
+        int count = folderTree.getItemCount();
+        for (int i = 0; i < count; i++) {
+            IMAPTreeItem item = findTreeItemForFolder((IMAPTreeItem) folderTree.getItem(i), folder);
+            if (item != null) {
+                item.increaseUnseenMessageCount(amount);
+                break;
+            }
+
+        }
+    }
+
+    
+    private IMAPTreeItem findTreeItemForFolder(IMAPTreeItem item, IMAPFolder folder) {
+        if (folder.getFullName().equalsIgnoreCase(((IMAPFolder) item.getUserObject()).getFullName())) {
+            return item;
+        }
+        for (int i = 0; i < item.getChildCount(); i++) {
+            IMAPTreeItem tItem = findTreeItemForFolder((IMAPTreeItem) item.getChild(i), folder);
+            if (tItem != null) {
+                return tItem;
+            }
+        }
+        return null;
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.hupa.client.mvp.MainPresenter.Display#updateTreeItem(org.apache.hupa.shared.data.IMAPFolder)
+     */
+    public void updateTreeItem(IMAPFolder folder) {
+        int count = folderTree.getItemCount();
+        for (int i = 0; i < count; i++) {
+            IMAPTreeItem item = findTreeItemForFolder((IMAPTreeItem) folderTree.getItem(i), folder);
+            if (item != null) {
+                item.setUserObject(folder);
+                break;
+            }
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see net.customware.gwt.presenter.client.widget.WidgetContainerDisplay#addWidget(com.google.gwt.user.client.ui.Widget)
+     */
+    public void addWidget(Widget widget) {
+        showWidget(widget);
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see net.customware.gwt.presenter.client.widget.WidgetContainerDisplay#removeWidget(com.google.gwt.user.client.ui.Widget)
+     */
+    public void removeWidget(Widget widget) {
+        centerWidget = null;
+        center.remove(widget); 
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see net.customware.gwt.presenter.client.widget.WidgetContainerDisplay#showWidget(com.google.gwt.user.client.ui.Widget)
+     */
+    public void showWidget(Widget widget) {
+        centerWidget = widget;
+        center.setWidget(centerWidget); 
+    }
+
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.hupa.client.mvp.NameAwareDisplay#getName()
+     */
+    public String getName() {
+        return constants.mailTab();
+    }
+}

Added: james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/MessageSendPresenter.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/MessageSendPresenter.java?rev=1516205&view=auto
==============================================================================
--- james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/MessageSendPresenter.java (added)
+++ james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/MessageSendPresenter.java Wed Aug 21 16:35:16 2013
@@ -0,0 +1,407 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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 org.apache.hupa.client.mvp;
+
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.HasClickHandlers;
+import com.google.gwt.user.client.ui.Focusable;
+import com.google.gwt.user.client.ui.HasHTML;
+import com.google.gwt.user.client.ui.HasText;
+import com.google.inject.Inject;
+
+import gwtupload.client.IUploader;
+import gwtupload.client.IUploadStatus.Status;
+import gwtupload.client.IUploader.OnCancelUploaderHandler;
+import gwtupload.client.IUploader.OnFinishUploaderHandler;
+import gwtupload.client.IUploader.OnStatusChangedHandler;
+
+import net.customware.gwt.dispatch.client.DispatchAsync;
+import net.customware.gwt.dispatch.shared.Action;
+import net.customware.gwt.presenter.client.EventBus;
+import net.customware.gwt.presenter.client.widget.WidgetDisplay;
+import net.customware.gwt.presenter.client.widget.WidgetPresenter;
+
+import org.apache.hupa.client.HupaCallback;
+import org.apache.hupa.client.validation.EmailListValidator;
+import org.apache.hupa.shared.Util;
+import org.apache.hupa.shared.data.IMAPFolder;
+import org.apache.hupa.shared.data.Message;
+import org.apache.hupa.shared.data.MessageAttachment;
+import org.apache.hupa.shared.data.MessageDetails;
+import org.apache.hupa.shared.data.SMTPMessage;
+import org.apache.hupa.shared.data.User;
+import org.apache.hupa.shared.events.BackEvent;
+import org.apache.hupa.shared.events.ContactsUpdatedEvent;
+import org.apache.hupa.shared.events.ContactsUpdatedEventHandler;
+import org.apache.hupa.shared.events.FlashEvent;
+import org.apache.hupa.shared.events.FolderSelectionEvent;
+import org.apache.hupa.shared.events.FolderSelectionEventHandler;
+import org.apache.hupa.shared.events.LoadMessagesEvent;
+import org.apache.hupa.shared.events.LoadMessagesEventHandler;
+import org.apache.hupa.shared.events.SentMessageEvent;
+import org.apache.hupa.shared.rpc.ForwardMessage;
+import org.apache.hupa.shared.rpc.GenericResult;
+import org.apache.hupa.shared.rpc.ReplyMessage;
+import org.apache.hupa.shared.rpc.SendMessage;
+import org.apache.hupa.shared.rpc.ContactsResult.Contact;
+import org.apache.hupa.widgets.ui.HasEnable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Presenter which handles the sending, reply, replay-all, forward of mails
+ * 
+ */
+public class MessageSendPresenter extends WidgetPresenter<MessageSendPresenter.Display> {
+
+    private DispatchAsync dispatcher;
+    private ArrayList<MessageAttachment> attachments = new ArrayList<MessageAttachment>();
+    private Type type = Type.NEW;
+    private IMAPFolder folder;
+    private Message oldmessage;
+    
+    protected SMTPMessage message = null;
+    
+    @SuppressWarnings("unused")
+    private MessageDetails oldDetails;
+
+    private OnFinishUploaderHandler onFinishUploadHandler = new OnFinishUploaderHandler() {
+        public void onFinish(IUploader uploader) {
+            if (uploader.getStatus() == Status.SUCCESS) {
+                String name = uploader.getInputName();
+                MessageAttachment attachment = new MessageAttachment();
+                attachment.setName(name);
+                attachments.add(attachment);
+                display.getSendEnable().setEnabled(true);
+            }
+        }
+    };
+
+    private OnStatusChangedHandler onStatusChangedHandler = new OnStatusChangedHandler() {
+        public void onStatusChanged(IUploader uploader) {
+            Status stat = display.getUploader().getStatus();
+            if (stat == Status.INPROGRESS)
+                display.getSendEnable().setEnabled(false);
+            else
+                display.getSendEnable().setEnabled(true);
+        }
+    };
+
+    private OnCancelUploaderHandler onCancelUploadHandler = new OnCancelUploaderHandler() {
+        public void onCancel(IUploader uploader) {
+            for (MessageAttachment attachment : attachments) {
+                if (attachment.getName().equals(uploader.getInputName()))
+                    attachments.remove(attachment);
+            }
+        }
+    };
+    
+    @Inject
+    public MessageSendPresenter(Display display, EventBus eventBus, DispatchAsync dispatcher) {
+        super(display, eventBus);
+        this.display = display;
+        this.dispatcher = dispatcher;
+    }
+    
+    public Display display;
+
+    /**
+     * The Type for which the SendPresenter will get used
+     */
+    public enum Type {
+        NEW, REPLY, REPLY_ALL, FORWARD
+    }
+
+    public interface Display extends WidgetDisplay {
+        public HasText getFromText();
+
+        public HasText getToText();
+
+        public HasText getCcText();
+
+        public HasText getBccText();
+
+        public HasText getSubjectText();
+
+        public HasHTML getMessageHTML();
+        
+        public Focusable getEditorFocus();
+
+        public HasClickHandlers getSendClick();
+
+        public HasEnable getSendEnable();
+
+        public IUploader getUploader();
+
+        public HasClickHandlers getBackButtonClick();
+        
+        public void refresh();
+
+        public void setLoading(boolean loading);
+        
+        public void fillContactList(Contact[] contacts);
+        
+        public boolean validate();
+    }
+
+    @Override
+    protected void onBind() {
+        registerHandler(eventBus.addHandler(LoadMessagesEvent.TYPE, new LoadMessagesEventHandler() {
+            public void onLoadMessagesEvent(LoadMessagesEvent loadMessagesEvent) {
+                reset();
+            }
+        }));
+        registerHandler(eventBus.addHandler(FolderSelectionEvent.TYPE, new FolderSelectionEventHandler() {
+            public void onFolderSelectionEvent(FolderSelectionEvent event) {
+                reset();
+            }
+        }));
+        registerHandler(eventBus.addHandler(ContactsUpdatedEvent.TYPE, new ContactsUpdatedEventHandler() {
+            public void onContactsUpdated(ContactsUpdatedEvent event) {
+                display.fillContactList(event.getContacts());
+            }
+        }));        
+        registerHandler(display.getSendClick().addClickHandler(sendClickHandler));
+        registerHandler(display.getBackButtonClick().addClickHandler(new ClickHandler() {
+            public void onClick(ClickEvent event) {
+                eventBus.fireEvent(new BackEvent());
+            }
+        }));
+
+        display.getUploader().addOnStatusChangedHandler(onStatusChangedHandler);
+        display.getUploader().addOnFinishUploadHandler(onFinishUploadHandler);
+        display.getUploader().addOnCancelUploadHandler(onCancelUploadHandler);
+
+        reset();
+    }
+    
+    protected ClickHandler sendClickHandler = new ClickHandler() {
+        public void onClick(ClickEvent event) {
+            if (validate()) {
+                message = new SMTPMessage();
+                message.setFrom(display.getFromText().getText());
+                message.setSubject(display.getSubjectText().getText());
+                message.setText(display.getMessageHTML().getHTML());
+                message.setMessageAttachments(attachments);
+                message.setTo(emailTextToArray(display.getToText().getText()));
+                message.setCc(emailTextToArray(display.getCcText().getText()));
+                message.setBcc(emailTextToArray(display.getBccText().getText()));
+
+                SendMessage command;
+                if (type == Type.NEW) {
+                    command = new SendMessage(message);
+                } else if (type == Type.FORWARD) {
+                    command = new ForwardMessage(message, folder, oldmessage.getUid());
+                } else {
+                    command = new ReplyMessage(message, folder, oldmessage.getUid());
+                }
+                dispatchMessage(dispatcher, eventBus, command);
+            }
+        }
+    };
+
+    protected ArrayList<String> emailTextToArray(String emails) {
+        ArrayList<String> cc = new ArrayList<String>();
+        for (String ccRaw : emails.split("[,;]+")) {
+            String ccRecip = ccRaw.trim();
+            if (ccRecip.length() > 0) {
+                cc.add(ccRaw.trim());
+            }
+        }
+        return cc;
+    }
+    
+    // Although dispatcher and eventBus parameters are not necessary, they are needed for testability
+    protected void dispatchMessage(DispatchAsync dispatcher, final EventBus eventBus, Action<GenericResult> command) {
+        display.setLoading(true);
+        dispatcher.execute(command, new HupaCallback<GenericResult>(dispatcher, eventBus) {
+            public void callback(GenericResult result) {
+                if (result.isSuccess()) {
+                    eventBus.fireEvent(new SentMessageEvent());
+                    reset();
+                } else {
+                    eventBus.fireEvent(new FlashEvent(result.getMessage(), 6000));
+                }
+                display.setLoading(false);
+            }
+        });
+    }
+
+    /**
+     * Reset everything
+     */
+    private void reset() {
+        display.getUploader().reset();
+        display.getBccText().setText("");
+        display.getCcText().setText("");
+        display.getToText().setText("");
+        display.getSubjectText().setText("");
+        attachments.clear();
+        folder = null;
+        oldmessage = null;
+        type = Type.NEW;
+    }
+
+    @Override
+    protected void onUnbind() {
+        // cancel the current upload when unbinding
+        display.getUploader().cancel();
+    }
+
+    /**
+     * Bind the given values to this presenter
+     * 
+     * @param user
+     *            the user
+     * @param folder
+     *            the currently selected folder
+     * @param oldmessage
+     *            the oldmessage ( if there is any)
+     * @param oldDetails
+     *            the olddetails ( if there are any)
+     * @param type
+     *            the type
+     */
+    public void revealDisplay(User user, IMAPFolder folder, Message oldmessage, MessageDetails oldDetails, String mailto, Type type) {
+        this.reset();
+        this.oldmessage = oldmessage;
+        this.oldDetails = oldDetails;
+        this.folder = folder;
+        this.type = type;
+
+        // Depending on the type, we have to automatically fill the view inputs
+        display.getFromText().setText(user.getName());
+        display.getMessageHTML().setHTML(wrapMessage(oldmessage, oldDetails, type));
+        if (type.equals(Type.NEW) && mailto != null) {
+                display.getToText().setText(mailto);
+        } else if (type.equals(Type.FORWARD)) {
+            if (oldmessage.getSubject() != null && !oldmessage.getSubject().toLowerCase().startsWith("fwd:")) {
+                display.getSubjectText().setText("Fwd: " + oldmessage.getSubject());
+            }
+        } else if (type.equals(Type.REPLY) || type.equals(Type.REPLY_ALL)) {
+            if (oldmessage.getSubject() != null && !oldmessage.getSubject().toLowerCase().startsWith("re:")) {
+                display.getSubjectText().setText("Re: " + oldmessage.getSubject());
+            }
+            if (type.equals(Type.REPLY)) { 
+                if (oldmessage.getReplyto() != null && !oldmessage.getFrom().contains(oldmessage.getReplyto())) {
+                    display.getToText().setText(oldmessage.getReplyto());
+                } else {
+                    display.getToText().setText(oldmessage.getFrom());
+                }
+            } else {
+                ArrayList<String> list = new ArrayList<String>();
+                if (oldmessage.getReplyto() != null && !oldmessage.getFrom().contains(oldmessage.getReplyto())) 
+                    list.add(oldmessage.getReplyto());
+                if (oldmessage.getTo() != null)
+                    list.addAll(oldmessage.getTo());
+                if (oldmessage.getCc() != null)
+                    list.addAll(oldmessage.getCc());
+                list = removeEmailFromList(list, user.getName());
+                display.getCcText().setText(Util.listToString(list));
+                if (oldmessage.getTo() != null) {
+                    oldmessage.getTo().remove(user.getName());
+                }
+                display.getToText().setText(oldmessage.getFrom());
+            }
+        } 
+        display.refresh();
+        firePresenterChangedEvent();
+        revealDisplay();
+        display.getEditorFocus().setFocus(true);
+    }
+
+    public void revealDisplay(User user, IMAPFolder folder, Message oldmessage, MessageDetails oldDetails, Type type) {
+        this.revealDisplay(user, folder, oldmessage, oldDetails, null, type);
+    }
+
+    public void revealDisplay(User user, String mailto) {
+        revealDisplay(user, null, null, null, mailto, Type.NEW);
+    }
+
+    /**
+     * Bind the given user to the presenter
+     * 
+     * @param user
+     */
+    public void revealDisplay(User user) {
+        revealDisplay(user, null, null, null, null, Type.NEW);
+    }
+
+    @Override
+    protected void onRevealDisplay() {
+    }
+    
+    private static String generateHeader(Message message, Type type) {
+        String ret = "<br>";
+        if (message != null) {
+            if (type.equals(Type.FORWARD)) {
+                ret += "--------- Forwarded message --------- <br>";
+                ret += "From: " + message.getFrom().replaceAll("<", "&lt;").replaceAll(">", "&gt;") + "<br>";
+                ret += "Date: " + message.getReceivedDate() + "<br>";
+                ret += "Subject: " + message.getSubject() + "<br>";
+                ArrayList<String> to = new ArrayList<String>();
+                to.addAll(message.getTo());
+                to.addAll(message.getCc());
+                ret += "To: " + Util.listToString(to).replaceAll("<", "&lt;").replaceAll(">", "&gt;") + "<br>";
+            } else if (type.equals(Type.REPLY) || type.equals(Type.REPLY_ALL)) {
+                ret += "On " + message.getReceivedDate();
+                ret += ", " + message.getFrom().replaceAll("<", "&lt;").replaceAll(">", "&gt;");
+                ret += ". wrote:<br>";
+            }
+        }
+        return ret + "<br>";
+    }
+
+    public static String wrapMessage(Message message, MessageDetails details, Type type) {
+        String ret = "";
+        if (message != null) {
+            ret += generateHeader(message, type);
+        }
+        if (details != null && details.getText() != null && details.getText().length() > 0) {
+            ret += "<blockquote style='border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;'>";
+            ret += details.getText();
+            ret += "</blockquote>";
+        }
+        return ret;
+    }
+    
+    protected boolean validate() {
+        // Don't trust only in view validation
+        return  display.validate() 
+                && display.getToText().getText().trim().length() > 0  
+                && EmailListValidator.isValidAddressList(display.getToText().getText()) 
+                && EmailListValidator.isValidAddressList(display.getCcText().getText()) 
+                && EmailListValidator.isValidAddressList(display.getBccText().getText());
+    }
+    
+    protected ArrayList<String> removeEmailFromList(List<String> list, String email) {
+        ArrayList<String> ret = new ArrayList<String>();
+        String regex = ".*<?\\s*" + email.trim() + "\\s*>?\\s*"; 
+        for(String e: list) {
+            if (! e.matches(regex)) {
+                ret.add(e);
+            }
+        }
+        return ret;
+    }
+
+}

Added: james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/MessageSendView.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/MessageSendView.java?rev=1516205&view=auto
==============================================================================
--- james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/MessageSendView.java (added)
+++ james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/MessageSendView.java Wed Aug 21 16:35:16 2013
@@ -0,0 +1,276 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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 org.apache.hupa.client.mvp;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.event.dom.client.HasClickHandlers;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.Focusable;
+import com.google.gwt.user.client.ui.HasHTML;
+import com.google.gwt.user.client.ui.HasText;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.TextBox;
+import com.google.gwt.user.client.ui.VerticalPanel;
+import com.google.gwt.user.client.ui.Widget;
+import com.google.inject.Inject;
+
+import eu.maydu.gwt.validation.client.DefaultValidationProcessor;
+import eu.maydu.gwt.validation.client.ValidationProcessor;
+import eu.maydu.gwt.validation.client.i18n.ValidationMessages;
+import gwtupload.client.IFileInput.FileInputType;
+import gwtupload.client.BaseUploadStatus;
+import gwtupload.client.IUploadStatus;
+import gwtupload.client.IUploader;
+import gwtupload.client.MultiUploader;
+
+import org.apache.hupa.client.HupaCSS;
+import org.apache.hupa.client.HupaConstants;
+import org.apache.hupa.client.HupaMessages;
+import org.apache.hupa.client.validation.AddStyleAction;
+import org.apache.hupa.client.validation.EmailListValidator;
+import org.apache.hupa.client.validation.NotEmptyValidator;
+import org.apache.hupa.client.validation.SetFocusAction;
+import org.apache.hupa.client.widgets.CommandsBar;
+import org.apache.hupa.client.widgets.EnableButton;
+import org.apache.hupa.client.widgets.MessageHeaders;
+import org.apache.hupa.shared.SConsts;
+import org.apache.hupa.shared.rpc.ContactsResult.Contact;
+import org.apache.hupa.widgets.editor.Editor;
+import org.apache.hupa.widgets.ui.EnableHyperlink;
+import org.apache.hupa.widgets.ui.HasEnable;
+import org.apache.hupa.widgets.ui.Loading;
+import org.apache.hupa.widgets.ui.MultiValueSuggestArea;
+
+/**
+ * View which displays a form which handle sending of mails
+ * 
+ *
+ */
+public class MessageSendView extends Composite implements MessageSendPresenter.Display {
+
+    final VerticalPanel sendContainer = new VerticalPanel();
+    
+    private MessageHeaders headers;
+    
+    private Editor editor;
+    private CommandsBar buttonsBar = new CommandsBar();
+
+    private Label from = new Label();
+    
+    private MultiValueSuggestArea to = new MultiValueSuggestArea(" ,@<>");
+    // we only need one instance for all suggestion-boxes
+    private MultiValueSuggestArea cc = new MultiValueSuggestArea(to.getOracle());
+    private MultiValueSuggestArea bcc = new MultiValueSuggestArea(to.getOracle());
+    
+    private TextBox subject = new TextBox();
+    private MultiUploader uploader = null;
+    
+    private EnableButton sendButton;
+    private EnableHyperlink backButton;
+    private Loading loading;
+    
+    private ValidationProcessor validator;
+
+    @Inject
+    public MessageSendView(HupaConstants constants, HupaMessages messages) {
+        
+        sendButton = new EnableButton(constants.sendButton());
+        backButton = new EnableHyperlink(constants.backButton(),"");
+        headers = new MessageHeaders(constants);
+        loading = new Loading(constants.loading());
+        editor = new Editor(constants);
+        
+        BaseUploadStatus uploadStatus = new BaseUploadStatus();
+        uploadStatus.setCancelConfiguration(IUploadStatus.GMAIL_CANCEL_CFG);
+        uploader = new MultiUploader(FileInputType.ANCHOR, uploadStatus);
+        uploader.setServletPath(GWT.getModuleBaseURL() + SConsts.SERVLET_UPLOAD);
+        uploader.avoidRepeatFiles(true);
+        uploader.setI18Constants(constants);        
+        
+        sendContainer.addStyleName(HupaCSS.C_msgsend_container);
+        
+        buttonsBar.add(sendButton);
+        buttonsBar.add(loading);
+        buttonsBar.add(backButton);
+        
+        sendContainer.add(headers);
+        sendContainer.add(buttonsBar);
+
+        sendContainer.add(editor);
+
+        loading.hide();
+
+        initWidget(sendContainer);
+        
+        SetFocusAction fAction = new SetFocusAction();
+        AddStyleAction sAction = new AddStyleAction(HupaCSS.C_validate, 3000);
+        validator = new DefaultValidationProcessor(new ValidationMessages(messages));
+        validator.addValidators("cc", 
+                new EmailListValidator(getCcText()).addActionForFailure(sAction).addActionForFailure(fAction));
+        validator.addValidators("bcc", 
+                new EmailListValidator(getBccText()).addActionForFailure(sAction).addActionForFailure(fAction));
+        validator.addValidators("to", 
+                new EmailListValidator(getToText()).addActionForFailure(sAction).addActionForFailure(fAction),
+                new NotEmptyValidator(getToText()).addActionForFailure(sAction).addActionForFailure(fAction));
+
+        try {
+        } catch (Exception e) {
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see net.customware.gwt.presenter.client.widget.WidgetDisplay#asWidget()
+     */
+    public Widget asWidget() {
+        return this;
+    }
+
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.hupa.client.mvp.MessageSendPresenter.Display#setLoading(boolean)
+     */ 
+    public void setLoading(boolean load) {
+        if (load) {
+            loading.show();
+            sendButton.setEnabled(false);
+            backButton.setEnabled(false);
+        } else {
+            loading.hide();
+            sendButton.setEnabled(true);
+            backButton.setEnabled(true);
+        }
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.hupa.client.mvp.MessageSendPresenter.Display#getBccText()
+     */
+    public HasText getBccText() {
+        return bcc;
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.hupa.client.mvp.MessageSendPresenter.Display#getCcText()
+     */
+    public HasText getCcText() {
+        return cc;
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.hupa.client.mvp.MessageSendPresenter.Display#getFromText()
+     */
+    public HasText getFromText() {
+        return from;
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.hupa.client.mvp.MessageSendPresenter.Display#getMessageText()
+     */
+    public HasText getMessageText() {
+        return editor;
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.hupa.client.mvp.MessageSendPresenter.Display#getSubjectText()
+     */
+    public HasText getSubjectText() {
+        return subject;
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.hupa.client.mvp.MessageSendPresenter.Display#getToText()
+     */
+    public HasText getToText() {
+        return to;
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.hupa.client.mvp.MessageSendPresenter.Display#getSendClick()
+     */
+    public HasClickHandlers getSendClick() {
+        return sendButton;
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.hupa.client.mvp.MessageSendPresenter.Display#getUploader()
+     */
+    public IUploader getUploader() {
+        return uploader;
+    }
+
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.hupa.client.mvp.MessageSendPresenter.Display#getSendEnable()
+     */
+    public HasEnable getSendEnable() {
+        return sendButton;
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.hupa.client.mvp.MessageSendPresenter.Display#getBackButtonClick()
+     */
+    public HasClickHandlers getBackButtonClick() {
+        return backButton;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.hupa.client.mvp.MessageSendPresenter.Display#getMessageHTML()
+     */
+    public HasHTML getMessageHTML() {
+        return editor;
+    }
+    
+    /* (non-Javadoc)
+     * @see org.apache.hupa.client.mvp.MessageSendPresenter.Display#getEditorFocus()
+     */
+    public Focusable getEditorFocus() {
+        return editor;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.hupa.client.mvp.MessageSendPresenter.Display#refresh()
+     */
+    public void refresh() {
+        if (to.getText().length() == 0)
+            to.setText(" ");
+        headers.setValues(from, to, cc, bcc, subject, uploader);
+    }
+    
+    public void fillContactList(Contact[] contacts){
+        to.fillOracle(contacts);
+    }
+
+    public boolean validate() {
+        return validator.validate();
+    }
+
+}

Added: james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/MessageTableModel.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/MessageTableModel.java?rev=1516205&view=auto
==============================================================================
--- james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/MessageTableModel.java (added)
+++ james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/MessageTableModel.java Wed Aug 21 16:35:16 2013
@@ -0,0 +1,157 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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 org.apache.hupa.client.mvp;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import net.customware.gwt.dispatch.client.DispatchAsync;
+import net.customware.gwt.presenter.client.EventBus;
+
+import org.apache.hupa.client.HupaCallback;
+import org.apache.hupa.shared.data.IMAPFolder;
+import org.apache.hupa.shared.data.Message;
+import org.apache.hupa.shared.data.User;
+import org.apache.hupa.shared.events.FolderSelectionEvent;
+import org.apache.hupa.shared.events.FolderSelectionEventHandler;
+import org.apache.hupa.shared.events.LoadMessagesEvent;
+import org.apache.hupa.shared.events.LoadMessagesEventHandler;
+import org.apache.hupa.shared.events.LoginEvent;
+import org.apache.hupa.shared.events.LoginEventHandler;
+import org.apache.hupa.shared.events.LogoutEvent;
+import org.apache.hupa.shared.events.LogoutEventHandler;
+import org.apache.hupa.shared.events.MessagesReceivedEvent;
+import org.apache.hupa.shared.rpc.FetchMessages;
+import org.apache.hupa.shared.rpc.FetchMessagesResult;
+
+import com.google.gwt.gen2.table.client.MutableTableModel;
+import com.google.gwt.gen2.table.client.TableModelHelper;
+import com.google.gwt.gen2.table.client.TableModelHelper.Request;
+import com.google.inject.Inject;
+
+/**
+ * TableModel which retrieve the messages for the user
+ *
+ */
+public class MessageTableModel extends MutableTableModel<Message> {
+
+    private EventBus eventBus;
+    private DispatchAsync dispatcher;
+    private User user;
+    private IMAPFolder folder;
+    private String searchValue;
+
+    @Inject
+    public MessageTableModel(EventBus eventBus, DispatchAsync dispatcher){
+        
+        this.eventBus = eventBus;
+        this.dispatcher = dispatcher;
+
+        // bind some Events 
+        eventBus.addHandler(LoadMessagesEvent.TYPE, new LoadMessagesEventHandler() {
+            
+            public void onLoadMessagesEvent(LoadMessagesEvent loadMessagesEvent) {
+                user = loadMessagesEvent.getUser();
+                folder = loadMessagesEvent.getFolder();
+                searchValue = loadMessagesEvent.getSearchValue();
+            }
+        });
+        eventBus.addHandler(FolderSelectionEvent.TYPE, new FolderSelectionEventHandler() {
+            
+            public void onFolderSelectionEvent(FolderSelectionEvent event) {
+                user = event.getUser();
+                folder = event.getFolder();
+                searchValue = null;
+            }
+        });
+        eventBus.addHandler(LoginEvent.TYPE, new LoginEventHandler() {
+            
+            public void onLogin(LoginEvent event) {
+                user = event.getUser();
+                folder = new IMAPFolder(user.getSettings().getInboxFolderName());
+                searchValue = null;
+            }
+        });
+        eventBus.addHandler(LogoutEvent.TYPE, new LogoutEventHandler() {
+            
+            public void onLogout(LogoutEvent logoutEvent) {
+                user = null;
+                folder = null;
+                searchValue = null;
+            }
+        });
+        
+        
+    }
+
+    @Override 
+    public void requestRows(
+            final Request request,
+            final com.google.gwt.gen2.table.client.TableModel.Callback<Message> callback) {
+        
+        // if the given user or folder is null, its safe to return an empty list
+        if (user == null || folder == null) {
+            callback.onRowsReady(request, new TableModelHelper.Response<Message>() {
+
+                @Override
+                public Iterator<Message> getRowValues() {
+                    return new ArrayList<Message>().iterator();
+                }
+                
+            });
+        }
+        
+        dispatcher.execute(new FetchMessages(folder, request.getStartRow(), request.getNumRows(), searchValue),new HupaCallback<FetchMessagesResult>(dispatcher, eventBus) {
+            public void callback(final FetchMessagesResult result) {
+                // Update folder information before notifying presenter
+                folder.setMessageCount(result.getRealCount());
+                folder.setUnseenMessageCount(result.getRealUnreadCount());
+                // Notify presenter to update folder tree view
+                eventBus.fireEvent(new MessagesReceivedEvent(folder, result.getMessages()));
+                TableModelHelper.Response<Message> response = new TableModelHelper.Response<Message>() {
+                    @Override
+                    public Iterator<Message> getRowValues() {
+                        if (result != null && result.getMessages() != null) {
+                            return result.getMessages().iterator();
+                        } else {
+                            return new ArrayList<Message>().iterator();
+                        }
+                    }
+                };
+                setRowCount(result.getRealCount());
+                callback.onRowsReady(request,response);
+            }
+        }); 
+    }
+
+    @Override
+    protected boolean onRowInserted(int beforeRow) {
+        return true;
+    }
+
+    @Override
+    protected boolean onRowRemoved(int row) {    
+        return true;
+    }
+
+    @Override
+    protected boolean onSetRowValue(int row, Message rowValue) {
+        return true;
+    }
+}

Copied: james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/NameAwareWidgetDisplay.java (from r1516164, james/hupa/trunk/shared/src/main/java/org/apache/hupa/shared/exception/InvalidSessionException.java)
URL: http://svn.apache.org/viewvc/james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/NameAwareWidgetDisplay.java?p2=james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/NameAwareWidgetDisplay.java&p1=james/hupa/trunk/shared/src/main/java/org/apache/hupa/shared/exception/InvalidSessionException.java&r1=1516164&r2=1516205&rev=1516205&view=diff
==============================================================================
--- james/hupa/trunk/shared/src/main/java/org/apache/hupa/shared/exception/InvalidSessionException.java (original)
+++ james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/NameAwareWidgetDisplay.java Wed Aug 21 16:35:16 2013
@@ -17,13 +17,14 @@
  * under the License.                                           *
  ****************************************************************/
 
-package org.apache.hupa.shared.exception;
+package org.apache.hupa.client.mvp;
 
-public class InvalidSessionException extends HupaException{
+public interface NameAwareWidgetDisplay {
 
-	private static final long serialVersionUID = 995112620968798947L;
-
-	public InvalidSessionException(String message) {
-        super(message);
-    }
+    /**
+     * Return the name for the Display to show
+     * 
+     * @return name
+     */
+    public String getName();
 }

Copied: james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/place/ContactsPresenterPlace.java (from r1516164, james/hupa/trunk/shared/src/main/java/org/apache/hupa/shared/exception/InvalidSessionException.java)
URL: http://svn.apache.org/viewvc/james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/place/ContactsPresenterPlace.java?p2=james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/place/ContactsPresenterPlace.java&p1=james/hupa/trunk/shared/src/main/java/org/apache/hupa/shared/exception/InvalidSessionException.java&r1=1516164&r2=1516205&rev=1516205&view=diff
==============================================================================
--- james/hupa/trunk/shared/src/main/java/org/apache/hupa/shared/exception/InvalidSessionException.java (original)
+++ james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/place/ContactsPresenterPlace.java Wed Aug 21 16:35:16 2013
@@ -17,13 +17,25 @@
  * under the License.                                           *
  ****************************************************************/
 
-package org.apache.hupa.shared.exception;
+package org.apache.hupa.client.mvp.place;
 
-public class InvalidSessionException extends HupaException{
+import net.customware.gwt.presenter.client.gin.ProvidedPresenterPlace;
 
-	private static final long serialVersionUID = 995112620968798947L;
+import org.apache.hupa.client.mvp.ContactsPresenter;
 
-	public InvalidSessionException(String message) {
-        super(message);
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+
+public class ContactsPresenterPlace extends ProvidedPresenterPlace<ContactsPresenter>{
+
+    @Inject
+    public ContactsPresenterPlace(Provider<ContactsPresenter> presenter) {
+        super(presenter);
     }
+
+    @Override
+    public String getName() {
+        return "Contacts";
+    }
+
 }

Copied: james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/place/HupaPlaceManager.java (from r1516164, james/hupa/trunk/shared/src/main/java/org/apache/hupa/shared/exception/InvalidSessionException.java)
URL: http://svn.apache.org/viewvc/james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/place/HupaPlaceManager.java?p2=james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/place/HupaPlaceManager.java&p1=james/hupa/trunk/shared/src/main/java/org/apache/hupa/shared/exception/InvalidSessionException.java&r1=1516164&r2=1516205&rev=1516205&view=diff
==============================================================================
--- james/hupa/trunk/shared/src/main/java/org/apache/hupa/shared/exception/InvalidSessionException.java (original)
+++ james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/place/HupaPlaceManager.java Wed Aug 21 16:35:16 2013
@@ -17,13 +17,23 @@
  * under the License.                                           *
  ****************************************************************/
 
-package org.apache.hupa.shared.exception;
+package org.apache.hupa.client.mvp.place;
 
-public class InvalidSessionException extends HupaException{
+import net.customware.gwt.presenter.client.EventBus;
+import net.customware.gwt.presenter.client.place.DefaultPlaceManager;
+import net.customware.gwt.presenter.client.place.TokenFormatter;
 
-	private static final long serialVersionUID = 995112620968798947L;
+import com.google.inject.Inject;
 
-	public InvalidSessionException(String message) {
-        super(message);
+/**
+ * PlaceManager implementation for Hupa
+ * 
+ *
+ */
+public class HupaPlaceManager extends DefaultPlaceManager{
+    @Inject
+    public HupaPlaceManager(EventBus eventBus, TokenFormatter tokenFormatter, LoginPresenterPlace loginPresenterPlace, IMAPMessageListPresenterPlace messageListPresenterPlace, IMAPMessagePresenterPlace imapMessagePresenterPlace, MessageSendPresenterPlace sendPresenterPlace, ContactsPresenterPlace contactsPresenterPlace) {
+        super(eventBus, tokenFormatter, loginPresenterPlace, messageListPresenterPlace, imapMessagePresenterPlace, sendPresenterPlace, contactsPresenterPlace);
     }
+
 }

Added: james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/place/IMAPMessageListPresenterPlace.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/place/IMAPMessageListPresenterPlace.java?rev=1516205&view=auto
==============================================================================
--- james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/place/IMAPMessageListPresenterPlace.java (added)
+++ james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/place/IMAPMessageListPresenterPlace.java Wed Aug 21 16:35:16 2013
@@ -0,0 +1,94 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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 org.apache.hupa.client.mvp.place;
+
+
+import org.apache.hupa.client.mvp.IMAPMessageListPresenter;
+
+import com.google.gwt.core.client.GWT;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+
+import net.customware.gwt.presenter.client.gin.ProvidedPresenterPlace;
+import net.customware.gwt.presenter.client.place.PlaceRequest;
+
+public class IMAPMessageListPresenterPlace extends ProvidedPresenterPlace<IMAPMessageListPresenter>{
+
+    private final static String ROWS_PER_PAGE_INDEX = "rowsPerPageIndex";
+    private final static String PAGE = "page";
+    private final static String SEARCH = "search";
+
+    @Inject
+    public IMAPMessageListPresenterPlace(Provider<IMAPMessageListPresenter> presenter) {
+        super(presenter);
+    }
+
+    @Override
+    public String getName() {
+        return "MessageList";
+    }
+
+    @Override
+    protected void preparePresenter(PlaceRequest request, IMAPMessageListPresenter presenter) {
+        int page = 0;
+        try {
+            page = Integer.parseInt(request.getParameter(PAGE, "0"));
+            if (page < 0 ) {
+                page = 0;
+            }
+        } catch (NumberFormatException e) {
+            // ignore
+        }
+        presenter.getDisplay().goToPage(page);
+        
+        int rowsPerPageIndex = 0;
+        try {
+            rowsPerPageIndex = Integer.parseInt(request.getParameter(ROWS_PER_PAGE_INDEX, "0"));
+            if (rowsPerPageIndex < 0) {
+                rowsPerPageIndex = 0;
+            }
+        } catch (NumberFormatException e) {
+            // ignore
+        }
+
+        String searchValue = request.getParameter(SEARCH, "");
+        presenter.getDisplay().getSearchValue().setValue(searchValue);
+        
+        GWT.log("PRES="+request.toString(),null);
+
+    }
+
+    @Override
+    protected PlaceRequest prepareRequest(PlaceRequest request, IMAPMessageListPresenter presenter) {
+        request = request.with(PAGE, presenter.getDisplay().getCurrentPage() +"");
+        request = request.with(ROWS_PER_PAGE_INDEX, presenter.getDisplay().getRowsPerPageIndex() + "");
+      
+        String searchValue = presenter.getDisplay().getSearchValue().getValue();
+        if (searchValue != null && searchValue.length() > 0) {
+            request = request.with(SEARCH, searchValue);
+
+        }
+        
+        GWT.log("REQ="+request.toString(),null);
+
+        return request;
+    }
+    
+    
+}

Copied: james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/place/IMAPMessagePresenterPlace.java (from r1516164, james/hupa/trunk/shared/src/main/java/org/apache/hupa/shared/exception/InvalidSessionException.java)
URL: http://svn.apache.org/viewvc/james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/place/IMAPMessagePresenterPlace.java?p2=james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/place/IMAPMessagePresenterPlace.java&p1=james/hupa/trunk/shared/src/main/java/org/apache/hupa/shared/exception/InvalidSessionException.java&r1=1516164&r2=1516205&rev=1516205&view=diff
==============================================================================
--- james/hupa/trunk/shared/src/main/java/org/apache/hupa/shared/exception/InvalidSessionException.java (original)
+++ james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/place/IMAPMessagePresenterPlace.java Wed Aug 21 16:35:16 2013
@@ -16,14 +16,25 @@
  * specific language governing permissions and limitations      *
  * under the License.                                           *
  ****************************************************************/
+package org.apache.hupa.client.mvp.place;
 
-package org.apache.hupa.shared.exception;
+import org.apache.hupa.client.mvp.IMAPMessagePresenter;
 
-public class InvalidSessionException extends HupaException{
+import com.google.inject.Inject;
+import com.google.inject.Provider;
 
-	private static final long serialVersionUID = 995112620968798947L;
+import net.customware.gwt.presenter.client.gin.ProvidedPresenterPlace;
 
-	public InvalidSessionException(String message) {
-        super(message);
+public class IMAPMessagePresenterPlace extends ProvidedPresenterPlace<IMAPMessagePresenter>{
+
+    @Inject
+    public IMAPMessagePresenterPlace(Provider<IMAPMessagePresenter> presenter) {
+        super(presenter);
+    }
+
+    @Override
+    public String getName() {
+        return "IMAPMessage";
     }
+
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org