Google Web Toolkit (GWT)의 여러 페이지 자습서
방금 Google Web Toolkit (GWT)을 배우기 시작했습니다 . 내 GWT 애플리케이션에서 다른 HTML 페이지를 만들려면 어떻게해야합니까?
예를 들어 서점을위한 애플리케이션을 만들고 싶습니다. 이 응용 프로그램에는 세 페이지가 있습니다.
- 사용자를 환영하고 사용자 책을 제공 할 홈페이지
- 카테고리별로 책을 탐색하고 세부 정보를 볼 수있는 페이지 (GWT 위젯 사용)
- 온라인으로 책을 확인하십시오.
물론 사용자의 세부 정보, 새 책 추가 등과 같은 다른 페이지가있을 수 있습니다. 따라서 GWT에서 다른 페이지를 만드는 가장 좋은 방법은 무엇이며 페이지 간 탐색을 어떻게 할 수 있습니까? 예제 나 튜토리얼이 있습니까? 아니면 한 페이지에 전체 애플리케이션을 만들 수 있는데도 다른 페이지를 만들어야합니까?
이런 상황에서 제가 보통하는 일은 웹 페이지 프레임 워크를 먼저 디자인하는 것입니다. 머리글, 사이드 메뉴 및 바닥 글에 대한 div가 있습니다. 또한 div
주요 콘텐츠에 대한 HTML 도 있습니다 .
예:
<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>
(<div> 기반 레이아웃이 마음에 들면 대신 사용해도됩니다.)
그런 다음 Core.java
평소처럼 진입 점 (내 경우 ) 을 구축하여 각 요소를 필요에 따라 설정합니다.
RootPanel.get("header").add(new Header());
RootPanel.get("leftnav").add(new NavigationMenu());
RootPanel.get("footer").add(new Footer());
물론 고정 된 바닥 글과 머리글을 가질 수 있지만 여기도없고 여기도 없습니다.
"Content"라는 추상 클래스도 있습니다. 콘텐츠 개체는 "복합"을 확장하며 새 페이지의 생성 및 레이아웃을 단순화하는 다양한 방법을 갖습니다. 도움말 화면, 검색 화면, 장바구니 등이 애플리케이션을 위해 빌드하는 모든 페이지는 유형 Content
입니다.
이제 "ContentContainer"라는 클래스를 만듭니다. 이것은 "content"요소를 관리하는 단일 항목입니다. "Content"유형의 개체를 허용하는 "setContent"메서드가 하나 있습니다. 그런 다음 기본적으로 "content"<td> 내의 모든 항목을 제거하고 "setContent"메소드를 통해 할당 한 위젯 (Composite)으로 대체합니다. setContent 메소드는 히스토리 및 제목 표시 줄 관리도 처리합니다. 기본적으로 ContentContainer는 각 페이지 콘텐츠가 수행해야하는 모든 기능에 대해 "알아야"하는 경우 만들어야 할 수있는 다양한 바인딩 지점을 모두 집계하는 역할을합니다.
마지막으로 해당 페이지로 이동하는 방법이 필요합니다. 간단합니다.
ContentContainer.getInstance().setContent(new Search());
위의 내용을 클릭시 이벤트 어딘가에 넣으면 황금이됩니다.
다른 위젯을 바인딩해야하는 유일한 것은 ContentContainer와 이들이 추가하는 콘텐츠 유형입니다.
ChrisBo의 접근 방식에서 볼 수있는 단점은 토큰-> 페이지를 유지 관리해야하는 목록이 있다는 것입니다. 내가 볼 수있는 또 다른 단점은이 방법으로 실제 역사 시스템을 어떻게 가질 수 있는지 모르겠다는 것입니다.
내 접근 방식에 대해 제공하는 한 가지는 모든 페이지 선택이 매우 중앙 집중화되어 있다는 것입니다. 나는 일종의 Enum 또는 적어도 String 값이있는 정적 클래스를 사용하여 링크를 혼동하지 않도록합니다.
두 경우 모두 요점은 다음과 같이 요약 될 수 있다고 생각 합니다. 사용자가 클릭 한 작업 에 따라 중앙 페이지 요소의 콘텐츠를 바꿉니다.
HyperLink 및 History 클래스를 사용합니다. Hyperlink 클래스의 좋은 점은이 토큰 (예 : #foobar)을 설정하고 토큰 값이 변경 될 때 발생하는 이벤트 (ValueChangeEvent)를 잡기 만하면됩니다. eventHandler에서 페이지를 교체합니다.
예 : 환영 페이지 주소 :이 페이지의 www.yourpage.com/#home은 "책 찾아보기"페이지에 대한 링크이며, 링크를 클릭하면 새 주소는 다음과 같습니다. www.yourpage.com /#검색
다음은 코드입니다.
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");
}
}
}
대박! 나는 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>
이제 모든 화면은 RootPanel에 추가하는 대신 생성자에서 initWidget ()을 호출해야합니다.
initWidget(myPanel); // all composites must call this in constructor
물론 데스크톱 앱처럼 전체 AJAX 화되기를 원한다면 한 페이지 만 있으면됩니다. 그런 다음 링크에 따라 본문 의 내용을 변경하십시오 .
또한 매우 활동적인 GWT 용 Google 그룹이 있습니다. 이전에이 질문이 있었음을 알고 있습니다. "검색"기능 만 사용하면됩니다.
GWT Multipage-다중 페이지 GWT 애플리케이션을위한 간단한 프레임 워크.
MVP patern을 사용할 수 있습니다. 다음은 mi 간단한 라이브러리 https://code.google.com/p/gwt-simple-mvp/wiki/GettingStarted 입니다.
그리고 코드를 더 많은 js 파일로 분할 할 수 있습니다. https://code.google.com/p/gwt-spliting/
나는 Chloe S. 대답 (Chris R.의 대답과 Chris Boesing의 대답을 결합)을 사용하여 작동하는 GWT 웹 앱을 위해이 앱 컨트롤러를 빌드했습니다. 프로덕션 버전은 테스트 (및 작동 % 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'>…</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);
}
GWT 기능이 필요한 각 페이지에 대한 모듈을 추가하십시오. 구성 요소를 재사용하십시오.
참고 URL : https://stackoverflow.com/questions/1061705/multiple-pages-tutorial-in-google-web-toolkit-gwt
'Nice programing' 카테고리의 다른 글
고정 헤더가있는 CSS 전용 스크롤 가능 테이블 (0) | 2020.12.05 |
---|---|
C # 클래스 이름에는 어떤 문자가 허용됩니까? (0) | 2020.12.04 |
InputStream의 크기 결정 (0) | 2020.12.04 |
일반 열거 형을 int로 C # 비 박싱 변환? (0) | 2020.12.04 |
ASP.NET / PHP의 주류 Java 대안은 무엇입니까? (0) | 2020.12.04 |