Google Web Toolkit(GWT)中的多页教程

时间:2009-06-30 04:20:42

标签: gwt navigation

我刚开始学习Google Web Toolkit(GWT)。如何在GWT应用程序中创建不同的HTML页面?

例如,我想为书店创建一个应用程序。在这个应用程序中,我将有三页:

  1. 我将欢迎用户并提供用户图书的主页
  2. 页面按类别浏览图书并查看详细信息(使用GWT小部件)
  3. 在线查看图书。
  4. 当然可能还有其他页面,例如用户的详细信息,添加新书等。 那么,在GWT中制作不同页面的最佳方法是什么?如何在页面之间进行导航?有没有例子或教程?或者,当我可以在一个页面中创建整个应用程序时,我甚至需要创建不同的页面吗?

8 个答案:

答案 0 :(得分:74)

我在这种情况下通常做的是首先设计网页框架。我将有标题,侧面菜单和页脚的div。我的HTML中还会有div作为主要内容。

示例:

<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta name='gwt:module' content='org.project.package.Core=org.project.package.Core'>
    </head>
    <body>
        <!-- Load the JavaScript code for GWT -->
        <script language="javascript" src="ui/org.project.package.ui.Core.nocache.js"></script>

        <!-- For some unknown reason in Internet Explorer you have to have cellpadding/spacing ON THE ELEMENT and not on the STYLE if it is in the body tag like this -->
        <table id="wrapper" cellpadding="0" cellspacing="0" style="width: 100%;height: 100%;">

             <!-- Header row -->
             <tr style="height: 25%;">
                 <td colspan="2" id="header"></td>
             </tr>

             <!-- Body row and left nav row -->
             <tr style="height: 65%;">
                 <td id="leftnav"></td>
                 <td id="content"></td>
             </tr>

             <!-- Footer row -->
             <tr style="height: 10%;">
                <td colspan="2" id="footer"></td>
             </tr>

        </table>

        <!-- This iframe handles history -->
        <iframe id="__gwt_historyFrame" style="width:0;height:0;border:0"></iframe>
    </body>
</html>

(如果你喜欢&lt; div&gt;的布局,请随意使用它们。)

然后像往常一样构建入口点(在我的情况下为Core.java),根据需要设置每个元素。

RootPanel.get("header").add(new Header());
RootPanel.get("leftnav").add(new NavigationMenu());
RootPanel.get("footer").add(new Footer());

当然,可以使用静态页脚和页眉,但这既不在这里也不在那里。

我还有一个名为“Content”的抽象类。内容对象扩展为“Composite”,并且将具有各种方法来简化新页面的创建和布局。我为此应用程序构建的每个页面,无论是帮助屏幕,搜索屏幕,购物车还是其他任何页面,都是Content类型。

现在,我要做的是创建一个名为“ContentContainer”的类。这是一个负责管理“content”元素的单例。它有一个方法“setContent”,它接受“Content”类型的对象。然后它基本上删除了“内容”中的任何内容&lt; td&gt;并将其替换为您通过“setContent”方法分配的任何窗口小部件(Composite)。 setContent方法还处理历史记录和标题栏管理。基本上,如果每个页面内容必须“知道”它必须执行的所有功能,ContentContainer用于聚合您可能必须进行的所有各种绑定点。

最后,您需要一种方法来访问该页面,对吗?这很简单:

ContentContainer.getInstance().setContent(new Search());

将上述内容置于某处的点击事件中,您就是金色的。

您的其他小部件需要绑定的唯一内容是ContentContainer及其添加的内容类型。

我可以看到ChrisBo的方法的缺点是你有一个必须维护令牌的列表 - &gt;页面。我能看到的另一个缺点是我看不出你如何使用这种方法建立一个真实的历史系统。

它为我的方法提供的一件事是所有页面选择都非常集中。我会使用某种Enum或至少一个带有String值的静态类来防止我自己混淆链接。

在任何一种情况下,我认为这一点可以概括为:交换某些中心页面元素的内容,基于用户点击用户所执行的操作。

答案 1 :(得分:20)

我会使用HyperLink和History类。关于Hyperlink类的好处是,它设置了这个标记(例如#foobar),而你所要做的就是捕获事件,当更改标记的值时会触发该事件(ValueChangeEvent)。在eventHandler中,您将替换页面。

实施例: 欢迎致辞:www.yourpage.com/#home 在此页面上将链接到“浏览书”页面,当点击链接时,新地址将是这样的:www.yourpage.com/#browse

以下是代码:


public class MainEntryPoint implements EntryPoint, ValueChangeHandler {
    VerticalPanel panel = new VerticalPanel();
    Label label=new Label();
    public void onModuleLoad() {
        Hyperlink link1 = new Hyperlink("books", "browse");
        Hyperlink link2 = new Hyperlink("user details", "details");
        panel.add(link1);
        panel.add(link2);
        panel.add(label);
        RootPanel.get().add(panel);
        History.addValueChangeHandler(this);
        //when there is no token, the "home" token is set else changePage() is called.
        //this is useful if a user has bookmarked a site other than the homepage.
        if(History.getToken().isEmpty()){
            History.newItem("home");
        } else {
            changePage(History.getToken());
        }
    }

public void onValueChange(ValueChangeEvent event) {
    changePage(History.getToken());
}
public void changePage(String token) {
    if(History.getToken().equals("browse")) {
        label.setText("Here would be some books");
    } else if (History.getToken().equals("details")) {
        label.setText("Here would be the user details");
    } else {
        label.setText("Welcome page");
    }
}

}

答案 2 :(得分:9)

真棒!我将Chris R.的回答与Chris Boesing的结合起来提出了这个问题:

这是'索引'起始页

public class Index implements EntryPoint, ValueChangeHandler<String> {
    public void onModuleLoad() {
        History.addValueChangeHandler(this);
        if (History.getToken().isEmpty()) History.newItem("index");
        Composite c = new Login(); 
        FlowControl.go(c);
    }

    public void onValueChange(ValueChangeEvent<String> e) {
        FlowControl.go(History.getToken());
    }
}

根据Chris R。这是控制器或ContentContainer。

public class FlowControl {
private static FlowControl instance;
private FlowControl() {}
public static void go(Composite c) {
    if (instance == null) instance = new FlowControl(); // not sure why we need this yet since everything is static.
    RootPanel.get("application").clear();
    RootPanel.get("application").getElement().getStyle().setPosition(Position.RELATIVE); // not sure why, but GWT throws an exception without this. Adding to CSS doesn't work.
    // add, determine height/width, center, then move. height/width are unknown until added to document. Catch-22!
    RootPanel.get("application").add(c);
    int left = Window.getClientWidth() / 2 - c.getOffsetWidth() / 2; // find center
    int top = Window.getClientHeight() / 2 - c.getOffsetHeight() / 2;
    RootPanel.get("application").setWidgetPosition(c, left, top);
    History.newItem(c.getTitle()); // TODO: need to change and implement (or override) this method on each screen
}

public static void go(String token) {
    if (token == null) go(new Login());
    if (token.equals("cart")) go(new Cart());
    if (token.equals("login")) go(new Login());
    // Can probably make these constants in this class
}

然后,您可以在代码中的任何位置查看超链接和按钮。 (还没有尝试过超链接。)

    Button submit = new Button("Submit");
    submit.addClickHandler(new ClickHandler() {
        public void onClick(ClickEvent event) {
            FlowControl.go(new MyScreen());             
        }           
    });

我在HTML中添加了一个div

<!-- This is where the application will reside within. It is controlled by FlowControl class. -->
<div id="application"></div>

现在所有的屏幕都必须在构造函数中调用initWidget()而不是添加到RootPanel,因为它现在是一个Composite类,比如

    initWidget(myPanel); // all composites must call this in constructor

答案 3 :(得分:5)

如果您希望它是完全AJAXified(如桌面应用程序),当然您只需要一个页面。然后根据链接更改 body 的内容。

此外,还有一个非常活跃的Google群组,我知道在此之前已经有人问过,你只需要使用“搜索”功能。

答案 4 :(得分:1)

GWT Multipage - 用于多页GWT应用程序的简单框架。

答案 5 :(得分:0)

您可以使用MVP模式。 这是mi简单库https://code.google.com/p/gwt-simple-mvp/wiki/GettingStarted

您可以将代码拆分为更多js文件。 https://code.google.com/p/gwt-spliting/

答案 6 :(得分:0)

我使用Chloe S.回答(将Chris R.的回答与Chris Boesing的结合)来为一个有效的GWT Web App构建这个App Controller。生产中的版本已经过测试(并且正在运行%100),但是需要修改下面的编辑版本以与您自己的应用程序集成(首先将页面键重命名为菜单项)。

AppController.java

/**
 * This App Controller utilizes two static inner-classes (Pages and External) 
 * to manage and server multiple pages with multiple sub-page (through their presenters) 
 * via String key constants which also serve as the literal text for the menu items.
 * 
 * Pages are added as menu commands in their respective views:
 *  // Add menu items to the menu with commands:
 *  menuItems.put(Pages.PAGE1, mainMenu.addItem(Pages.PAGE1, new Command() {
 *      public void execute() {
 *          History.newItem(Pages.PAGE1);
 *      }
 *  }));
 * 
 * Pages are fired as History tokens (from entry point java class):
 * 
 *   **
 *   * Receives history events and pushes them to the AppController using a deferred command.
 *   * Changes the cursor to show waiting.
 *   * @param the value change token
 *   *
 *  public void onValueChange(ValueChangeEvent<String> e) {
 *      // check token to cover first historical "back" navigation:
 *      if(!History.getToken().isEmpty()) {
 *          AppController.waitCursor.execute(); // cursor is reset in page attach method
 *      }
 *      Scheduler.get().scheduleDeferred(new ScheduledCommand() {
 *          public void execute() {
 *              AppController.go(History.getToken());
 *          }
 *      });
 *  }
 *  
 * Wait cursors are implemented as CSS:
 *
 *  body.wait, body.wait * {
 *      cursor: wait !important;   
 *  }
 * 
 * NOTE: This page swapping implementation technique (based on the StackOverflow solution 
 * found here: [http://stackoverflow.com/questions/1061705/multiple-pages-tutorial-in-google-web-toolkit-gwt][1]) 
 * differs from the obtuse and ancient 2010 GWT framework documentation in that the App Controller manages / handles 
 * adding the widget to the container, and therefore all the Presenters must implement the 
 * "AppControlPresenter" or "AppControlContainerPresenter" interface to give it access to their containers.
 * (thus eliminating "public void go(final HasWidgets container);" method in all presenter architecture except for 'MainAppPresenter')
 * There is also no event bus; static method calls are used for any needed interactivity.
 *
 * Includes a popup for pages still under construction.
 */

package com.;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import java.util.HashMap;
import java.util.Map;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.logical.shared.AttachEvent;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DecoratedPopupPanel;
import com.google.gwt.user.client.ui.Frame;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.LayoutPanel;
import com.google.gwt.user.client.ui.RootLayoutPanel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.UIObject;

/**
 * 
 */
public class AppController {
    /** */
    public final static String DEFAULT_INITIAL_PAGE1_SUB_PAGE = Pages.PAGE_1A;
    /** Singleton instance for the AppController */
    private static AppController instance = new AppController();
    /** Presenter for the main app */
    private static MainAppPresenter mainAppPresenter;
    /** container for the different views */
    private static LayoutPanel container;
    /** sub-container for the different sub-views */
    private static LayoutPanel page1Container;
    /** */
    private static DecoratedPopupPanel popup;
    /** constant for Style-Dependent names for menu items (see menu-style.css) */
    public final static String MENU_ACTIVE_STYLE = "active";
    /** constant for Style-Dependent class name in css */
    public final static String CURSOR_WAIT_CLASS = "wait";  
    /** */
    public final static String POPUP_DEMO_ID = "popupDemo";
    /** */  
    public final static int DEMOP_POPUP_VERTICAL_OFFSET = 0;
    /** */
    public final static String POPUP_DEMO_STATEMENT = "<span class='text'>This page is under construction</span>"
                                                    + "<span class='char'>&hellip;</span>";
    /** */
    public static ScheduledCommand waitCursor = new ScheduledCommand() {
        @Override
        public void execute() { 
            AppController.waitCursor(true); 
        }
    };

    /** */
    public static ScheduledCommand normalCursor = new ScheduledCommand() {
        @Override
        public void execute() { 
            AppController.waitCursor(false); 
        }
    };

    /** Flag for determining if the page was reloaded */
    private static boolean reloaded = false;

    private static final LoginServiceAsync loginRpcService = GWT.create(LoginService.class);

    /**
     * Called on the resize event to set the position of the demo popup
     * window to be adjusted to the correct dimensions (size and positoin)
     * regardless of screen size.
     */
    private static ScheduledCommand resetPopupDimensions = new ScheduledCommand() {
        @Override
        public void execute() {
            if(!UNDER_CONSTRUCTION || popup == null) {
                return;
            }
            int demoWidth = Math.round(Window.getClientWidth() / MainApp.PHI),
                demoYPosition = Window.getClientHeight() / 2 - Math.round(popup.getOffsetHeight() / 2);
            popup.setWidth(String.valueOf(demoWidth) + "px");
            if(popup.getOffsetWidth() >= Window.getClientWidth()) {
                popup.setWidth("100%");
                popup.setPopupPosition(0, demoYPosition);
            } else {
                popup.setPopupPosition(Window.getClientWidth() / 2 - (popup.getOffsetWidth() / 2), demoYPosition);
            }
        }
    };

    /** */
    private static final String LOGIN_OBJECT_NAME = "Login Presenter Object";

    /**
     * static inner-class for external websites 
     */
    public static class External {
        /** The frame to contain the website */
        private static Frame frame;
        /**  */
        public static final String EXTERNAL_URL_1 = "http://";
        /**  */
        public static final String EXTERNAL_URL_2 = "http://";

        /**
         * @returns true if the name of the token is equal to one of the URLs
         * @param token the name to check
         */
        public static boolean has(String token) {
            return token.equalsIgnoreCase(EXTERNAL_URL_1)      ||
                   token.equalsIgnoreCase(EXTERNAL_URL_2);
        }

        /**
         * Gets the external Frame object
         * @param url
         * @return Frame
         */
        public static Frame get(String url) {
            if(frame == null) {
                frame = new Frame(url);
                frame.addAttachHandler(new AttachEvent.Handler() {
                    @Override
                    public void onAttachOrDetach(AttachEvent event) { 
                        // hide the popup:
                        showPopup(false);
                        Scheduler.get().scheduleFinally(resetPopupDimensions);
                        Scheduler.get().scheduleFinally(normalCursor);
                    }
                });
            }
            else if(!frame.getUrl().equalsIgnoreCase(url)) {
                frame.setUrl(url);
            }
            return frame;
        }
    }

    /**
     * static inner-class for holding pages activated by the app's main menu commands
     */
    public static class Pages {
        /** */
        public static final String PAGE1 = "foo";
        /** */
        public static final String PAGE2 = "bar";
        /** */
        public static final String PAGE_1A = "baz";
        /** */
        public static final String PAGE_1B = "qux";
        /** */
        public static String lastPage;
        /** */
        public static String lastPage1SubPage;
        /** */
        public static String unsavedMessage;
        /** */
        private static HashMap<String, AppControlPresenter> pageMap;
        /** */
        private static AppControlPresenter presenter;
        /** */
        private static Composite view;

        /**
         * initializes the hashmap of pages  
         */
        public static void init() {
            pageMap = new HashMap<String, AppControlPresenter>();
        }

        /**
         * @returns true if the name of the token is equal to one of the pages
         * @param token the name to check
         */
        public static boolean has(String token) {
            return token.equalsIgnoreCase(PAGE1)            ||
                   token.equalsIgnoreCase(PAGE2)            ||
                   token.equalsIgnoreCase(PAGE_1A);
        }


        /**
         * Gets the correct page container to display as a Composite
         * @param page the token name of the page
         * @return Composite page
         */
        public static Composite get(String page) {
            view = null;
            presenter = null;
            if(page.equalsIgnoreCase(PAGE1)) {
                if(pageMap.get(PAGE1) == null) {
                    pageMap.put(PAGE1, new Page1Presenter(PAGE1)); 
                    page1Container = ((AppControlContainerPresenter) pageMap.get(PAGE1)).getContentPane();
                }
                presenter = pageMap.get(PAGE1);
                lastPage = page;
                mainAppPresenter.setCurrentMenuItem(page);
            }
            else if(page.equalsIgnoreCase(PAGE_1A) ||
                    page.equalsIgnoreCase(PAGE_1B) {
                if(pageMap.get(PAGE1) == null) {
                    pageMap.put(PAGE1, new Page1Presenter(PAGE1)); 
                    page1Container = ((AppControlContainerPresenter) pageMap.get(PAGE1)).getContentPane();
                }
                presenter = pageMap.get(PAGE1);
                lastPage1SubPage = page;
                view = ((AppControlContainerPresenter)presenter).setCurrentPage(page);
            }
            else if(page.equalsIgnoreCase(PAGE2)) {
                if(pageMap.get(PAGE2) == null) {
                    pageMap.put(PAGE2, new Page2Presenter(PAGE2));
                }
                presenter = pageMap.get(PAGE2);
                lastPage = PAGE2;
                mainAppPresenter.setCurrentMenuItem(page);
            }
            else if(External.has(page)) {
                throw new Error("App Controller Error -- Use 'External' inner-class for: " + page);
            }
            else {
                throw new Error("App Controller Error -- Page name not found: " + page);
            }
            if(view == null) {
                view = (Composite)presenter.view();
            }
            view.addAttachHandler(new AttachEvent.Handler() {
                @Override
                public void onAttachOrDetach(AttachEvent event) {
                    AppController.showPopup(false);
                    presenter.updateAttachOrDetach(event);
                    Scheduler.get().scheduleFinally(resetPopupDimensions);
                    Scheduler.get().scheduleFinally(normalCursor);
                }
            });
            return view;
        }

        /**
         * Gets the current AppControlPresenter for the last page.
         * @returns the current AppControlPresenter  
         */
        public static AppControlPresenter getCurrentPresenter() {
            return presenter;
        }

        /**
         * Gets an AppControlPresenter from the pageMap.
         * @param token the name of the presenter
         * @returns the AppControlPresenter  
         */
        public static AppControlPresenter getPresenter(String token) {
            return pageMap.get(token);
        }

        /**
         * Returns true if the page is already loaded.
         * @param token name of the page
         */
        public static boolean alreadyLoaded(String token) {
            MainApp.debug(1, "[already loaded: " + presenter.toString() + " (token: " + token + ")");
            return presenter.toString().equalsIgnoreCase(token);
        }

        /**
         * Returns true if the page is visible
         * @param page the token name of the page
         */
        public static boolean isVisible(String page) {
            UIObject component = pageMap.get(page).view();
            return !(component.getOffsetHeight() == 0 && component.getOffsetWidth() == 0);
        }

        /**
         * Returns true if the page is visible
         * @param presenter the AppControlPresenter instance
         */
        public static boolean isVisible(AppControlPresenter presenter) {
            UIObject component = presenter.view();
            return !(component.getOffsetHeight() == 0 && component.getOffsetWidth() == 0);
        }

        /**
         * Returns true if the application has unsaved data.
         * Iterates through all the pages and checks each presenter.
         */
        public static boolean unsavedData() {
            if(pageMap.isEmpty()) return false;
            boolean unsaved = false;
            for(Map.Entry<String, AppControlPresenter> entry : pageMap.entrySet()) {
                AppControlPresenter presenter = entry.getValue();
                if(presenter != null && presenter.unsavedData()) {
                    MainApp.debug(1, "(!) " + presenter.toString() + " has unsaved data");
                    unsavedMessage = presenter.dataDescription();
                    unsaved = true;
                    break; // just need to know one exists for now (window closing event)
                }
            }
            return unsaved;
        }

        /**
         * Called on a resize event on the window. Iterates through all the pages
         * and tells their presenters to resize their content.
         */
        public static void resize() {
            for(Map.Entry<String, AppControlPresenter> entry : pageMap.entrySet()) {
                AppControlPresenter presenter = entry.getValue();
                if(presenter != null && isVisible(presenter)) {
                    presenter.resize();
                }
            }
        }
    } //end class Pages

    /**
     * @returns true if the history token is equal to any of the pages in the app 
     */
    public static boolean hasHistory() {
        String token = History.getToken();
        return External.has(token) || Pages.has(token);
    }

    /**
     * Starts the login view at the root layout level
     */
    public static void goLoginScreen() {
        //check for reload:
        if(hasHistory()) {
            MainApp.debug(1, "(!) AppController has History on Login");
            reloaded = true;
        }
        else {
            reloaded = false;
        }
        RootLayoutPanel.get().clear();
        RootLayoutPanel.get().add(new LoginPresenter(LOGIN_OBJECT_NAME).view());
    }

    /**
     * @returns the last "Page1" page
     */
    public static String getLastPage1Page() {
        if(Pages.lastPage1SubPage == null || Pages.lastPage1SubPage.isEmpty()) {
            Pages.lastPage1SubPage = DEFAULT_INITIAL_PAGE1_SUB_PAGE;
        }
        return Pages.lastPage1SubPage;
    }

    /**
     * Tells the app to start with the Page1 page.
     * @param username the username of the person logged-in
     */
    public static void goMainApp(String username) {
        //hide the login background:
        RootPanel.getBodyElement().getStyle().setProperty("background", "none");
        mainAppPresenter = new MainAppPresenter(username);
        RootLayoutPanel.get().clear();
        mainAppPresenter.go(RootLayoutPanel.get());
        //get the center panel:
        container = mainAppPresenter.getContainer();
        //check for reload:
        //NOTE: the token will be empty if the user refreshes 
        //      and navigates all the way back to the zero-state 
        //      from the login screen. 
        //NOTE: this logic may change after user-persistence is implemented
        if(hasHistory() || History.getToken().isEmpty()) {
            // reset the reloaded flag:
            reloaded = false;
            if(History.getToken().isEmpty()) {
                //land on the first page:
                History.newItem(AppController.Pages.PAGE1);
            }
            else {
                MainApp.debug(2, "(!) AppController has History on reload: " + History.getToken());
                History.fireCurrentHistoryState();
            }
        }
        else {
            //land on the first page:
            History.newItem(AppController.Pages.PAGE1);
        }

    }

    /**
     * 
     */
    public static void checkIfSessionActive() { 
        loginRpcService.loginFromSession(new AsyncCallback<LoginSummary>() {
            @Override
            public void onFailure(Throwable throwable) {
                goLoginScreen();
            }

            @Override
            public void onSuccess(LoginSummary loginSummary) {
                if (loginSummary.getErrorString() != null)
                    goLoginScreen();
                else
                    goMainApp(loginSummary.getUser().getName());
            }
        });
    }

    /**
     * 
     */
    public static void sessionLogout() {
        DialogBoxWidget.confirm(200,
                "Logout",
                "Are you sure you want to log out?",
                new ConfirmDialogCallback() {
                    @Override
                    public void onAffirmative() {

                        loginRpcService.logout(new AsyncCallback<Void>() {
                            @Override
                            public void onFailure(Throwable throwable) {
                                goLoginScreen();
                            }

                            @Override
                            public void onSuccess(Void aVoid) {
                                goLoginScreen();
                            }
                        });
                    }

                    @Override
                    public void onCancel() {
                    }
                });

    }

    /**
     * Shows or hides the "Under Construction" popup if UNDER_CONSTRUCION is true.
     * @param show true to show and false to hide
     */
    public static void showPopup(boolean show) {
        if(MainApp.UNDER_CONSTRUCTION && popup != null) {
            if(show) {
                popup.show();
            }
            else {
                popup.hide();
            }
        }
    }

    /**
     * Called by every history event fired (including the back and forward buttons).
     * Ignores the login and empty index historically.
     * @param token the name of the page to load
     */
    public static void go(String token) {
        if(reloaded) {
            normalCursor.execute();
        }
        if(token == null || token.isEmpty() || reloaded == true) return;
        MainApp.debug("<history changed> - AppController.go()-> " + token);
        // build the popup message for all unfinished pages:
        if(MainApp.UNDER_CONSTRUCTION) {
            if(popup == null) {
                popup = new DecoratedPopupPanel(false);
                popup.ensureDebugId(POPUP_DEMO_ID);
                popup.addStyleDependentName(POPUP_DEMO_ID);
                popup.setWidget(new HTML(new Image("images/workingman.png") + POPUP_DEMO_STATEMENT + new Image("images/workingmanFLIP.png")));
            }
        }
        // check token for which page to return:
        if(token.equalsIgnoreCase(External.EXTERNAL_URL_1)) {
            MainAppPresenter.clearActiveMenuItems();
            setExternalContentURL(External.get(token));
        }
        else if(token.equalsIgnoreCase(External.EXTERNAL_URL_2)) {
            MainAppPresenter.clearActiveMenuItems();
            setExternalContentURL(External.get(token));
        }
        else if(token.equalsIgnoreCase(Pages.PAGE1)) {
            setContent(Pages.get(Pages.PAGE1));
            setPage1Content(Pages.get(getLastPage1Page()));
        }
        else if(token.equalsIgnoreCase(Pages.PAGE_1A) ||
                token.equalsIgnoreCase(Pages.PAGE_1B)) {
            setContent(Pages.get(Pages.PAGE1));
            setPage1Content(Pages.get(token));
        }
        else if(token.equalsIgnoreCase(Pages.PAGE2)) {
            setContent(Pages.get(Pages.PAGE2));
        }
        else { // default behavior for a page not described:
            MainApp.debug(2, "(!) Unknown page: " + token);
            setContent(Pages.get(token));
        }
    }

    /**
     * Called by MainApp on a window resize event.
     * @param e the ResizeEvent
     */
    public static void resize(ResizeEvent e) {
        Scheduler.get().scheduleDeferred(new ScheduledCommand() {
            @Override
            public void execute() {
                if(mainAppPresenter != null) {
                    mainAppPresenter.resize();
                }
                Pages.resize();
                Scheduler.get().scheduleFinally(resetPopupDimensions);
            }
        });
    }

    /**
     * Changes the cursor to "wait" or "auto" depending on the parameter
     * @param wait true to set the cursor to waiting
     */
    private static void waitCursor(Boolean wait) {
        if(wait) {
            RootPanel.getBodyElement().addClassName(CURSOR_WAIT_CLASS);
        }
        else {
            RootPanel.getBodyElement().removeClassName(CURSOR_WAIT_CLASS);
        }
    }
    /**
     * Private Constructor which initializes the Pages object.
     */
    private AppController() {
        Pages.init();
    }

    /**
     * Sets the content of the main app container to one of the "Pages."
     * @param c the Composite widget to be added
     */
    private static void setContent(Composite c) {
        container.clear();
        container.add(c.asWidget());
    }

    /**
     * Sets the content of the main app container an external URL.
     * @param f the Frame by which external web sites are added
     */ 
    private static void setExternalContentURL(Frame f) {
        container.clear();
        container.add(f);
        // must reset the width and height every time:
        f.getElement().getStyle().setWidth(100, Unit.PCT);
        f.getElement().getStyle().setHeight(100, Unit.PCT);
    }

    /**
     * Sets the content of the Page1 container to one of the sub pages.
     * @param c the Composite widget to be added
     */
    private static void setPage1Content(Composite c) {
        page1Container.clear();
        page1Container.add(c.asWidget());
    }
}

AppControlPresenter.java:

package com.*;

import com.google.gwt.event.logical.shared.AttachEvent;
import com.google.gwt.user.client.ui.Composite;

/**
 * Base interface for all 'Presenters' used by AppController.java
 * NOTE: classes that implement this interface do not launch the presenter's view 
 * into the provided container; rather, the view is retrieved and used by the 
 * AppController instance by calling the 'view()' method
 */
public interface AppControlPresenter {

    /**
     * Gets the view (for use in AppController.java)
     */
    public Composite view();

    /**
     * Indicates if current search data is present and unsaved.
     * @returns true to if a search is still active  
     */
    public boolean unsavedData();

    /**
     * Called on resize event to notify presenters with visible
     * components that need resizing for different screen sizes.
     * @returns true if elements were resized
     */
    public boolean resize();

    /**
     * Called on attachEvents to tell the presenter to update.
     * @param event the AttachEvent
     */
    public void updateAttachOrDetach(AttachEvent event);

    /**
     * Gets the message to display for unsaved data.
     * @returns a message String describing the data
     */
    public String dataDescription();

    /**
     *  Gets a fully qualified name for use in comparisons
     * @return the name of this presenter used by the <code>AppController</code>
     */
    public String toString();
}

AppControlContainerPresenter.java:

package com.*;

import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.LayoutPanel;

/**
 */
public interface AppControlContainerPresenter extends AppControlPresenter {

    /**
     * 
     * @return
     */
    public LayoutPanel getContentPane();

    /**
     * 
     * @param pageName
     * @return
     */
    public Composite setCurrentPage(String pageName);
}

答案 7 :(得分:-2)

为每个需要GWT功能的页面添加模块。重用您的组件。