【问题标题】:Multiple pages tutorial in Google Web Toolkit (GWT)Google Web Toolkit (GWT) 中的多页教程
【发布时间】:2010-11-06 21:31:43
【问题描述】:

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

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

  1. 我将欢迎用户并提供用户书籍的主页
  2. 按类别浏览书籍和查看详细信息的页面(使用 GWT 小部件)
  3. 在线查看书籍。

当然还有其他页面,比如用户的详细信息、添加新书等。 那么,在 GWT 中制作不同页面的最佳方法是什么?如何在页面之间进行导航?有没有例子或教程?或者当我可以在一个页面中创建整个应用程序时,我什至需要创建不同的页面?

【问题讨论】:

    标签: gwt navigation


    【解决方案1】:

    在这种情况下,我通常会先设计网页框架。我将为页眉、侧边菜单和页脚设置一个 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>
    

    (如果您喜欢基于

    的布局,请随意使用它们。)

    然后你像往常一样构建你的入口点(在我的例子中是Core.java),根据需要设置每个元素。

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

    当然,可以有一个静态的页脚和页眉,但这既不是这里也不是那里。

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

    现在,我要做的是创建一个名为“ContentContainer”的类。这是一个负责管理“内容”元素的单例。它有一种方法“setContent”,它接受“Content”类型的对象。然后它基本上删除“内容”

    中的任何内容,并将其替换为您通过“setContent”方法分配的任何小部件(复合)。 setContent 方法还处理历史记录和标题栏管理。基本上,如果每个页面内容都必须“了解”它必须执行的所有功能,则 ContentContainer 用于聚合您可能必须进行的所有各种绑定点。

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

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

    将以上内容放在某处的点击事件中,您就可以了。

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

    我认为 ChrisBo 的方法的缺点是你有一个必须维护的令牌列表 -> 页面。我可以看到的另一个缺点是,我看不到如何使用这种方法拥有一个实际的历史系统。

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

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

    【讨论】:

    • 哇,真的很棒的答案。 “我看不出你如何使用这种方法拥有一个实际的历史系统”这行是指我的方法吗?因为它有一个历史系统,不是很好,但它有一个。
    • 是的。我看不到“我去过的地方”历史系统如何与新页面的命名标识符相结合。您的解决方案更像是滥用历史系统的用途。我想如果您使用后退按钮,您会回到上次的位置。不过,这不是你的解决方案的刺戳或任何东西。
    • 这应该是:“我看不出‘我去过哪里’历史系统如何工作结合新页面的命名标识符”
    • 很好的答案,但不要忘记搜索引擎优化——如果您的所有内容都是 javascript 生成的,那么您就有被找不到的风险!
    • 这是非常正确的,这并没有考虑到这一点。我相信使用 gwt 2.0+ 中的较新系统(即用于组织工作流),您可以提出一个更优雅的解决方案来支持这种事情。然而,GWT 主要用于(IMO,无论如何)应用程序,而不一定是需要搜索引擎索引和编目的网站部分。
    【解决方案2】:

    我会使用 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");
        }
    }
    

    }

    【讨论】:

      【解决方案3】:

      太棒了!我将 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
      

      【讨论】:

        【解决方案4】:

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

        另外,还有一个非常活跃的 GWT 谷歌群组,我知道之前有人问过这个问题,你只需要使用“搜索”功能。

        【讨论】:

        • 我认为按页面,提问者的意思是如何将 Web 应用程序的传统“页面”概念转换为 GWT 的世界,在那里你实际上只有一个 html 文件/页面。鉴于对问题的误解,答案根本没有真正回答任何问题。
        • +1 表示“像桌面应用程序”。这让它在我脑海中响起。像设计传统桌面应用程序一样设计 GWT 网站,在其中您有一个“主窗口”(主 html 页面)和多个“用户控件”,可以进出它。
        【解决方案5】:

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

        【讨论】:

        • 很少的文档。它似乎没有得到积极维护。
        【解决方案6】:

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

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

        【讨论】:

          【解决方案7】:

          我使用 Chloe S. 的答案(将 Chris R. 的答案与 Chris Boesing 的答案结合起来)为一个正常工作的 GWT Web 应用程序构建了这个 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);
          }
          

          【讨论】:

            【解决方案8】:

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

            【讨论】:

            • 应该是评论 - 这个答案不是很具体,几乎不能回答问题。
            猜你喜欢
            • 2011-01-03
            • 1970-01-01
            • 2011-04-21
            • 2012-09-17
            • 2010-10-19
            • 2016-12-29
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多