Managing Multiple Host Pages
At this point, we've built myCRM's user interface based on our functional requirements and the use of common UI design principles.
In this post, we'll look at how to add support for multiple host pages to myCRM.
- Examine the options
- Implement support for multiple host pages
- Test the application in development mode
1. Examine the options
There are several ways of adding support for multiple host pages to GWT applications. However, we're going to look at just one the GWT Multpage framework developed by Claudius Hauptmann.
2. Implement support for multiple host pages
The first step, in implementing support for multiple host pages is to add an annotation to the application's main entry point class:
...
@MultipageEntryPoint(urlPattern = "myCRM.html")
public class myCRM implements EntryPoint {
The next step, is to update the application's module definition file:
<?xml version="1.0" encoding="UTF-8"?> <module rename-to='mycrm'> <!-- Inherit the core Web Toolkit stuff. --> <inherits name='com.google.gwt.user.User'/> <!-- Inherit the default GWT style sheet. You can change --> <!-- the theme of your GWT application by uncommenting --> <!-- any one of the following lines. --> <!-- <inherits name='com.google.gwt.user.theme.standard.Standard'/> --> <!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> --> <!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/> --> <!-- Other module inherits --> <!-- <inherits name="com.smartgwt.SmartGwt"/> --> <inherits name="com.smartgwt.SmartGwtNoTheme"/> <inherits name="com.smartclient.theme.enterpriseblue.EnterpriseBlue"/> <inherits name="com.smartclient.theme.enterpriseblue.EnterpriseBlueResources"/> <!-- Inherit the gwt-multipage module --> <inherits name='com.claudiushauptmann.gwt.multipage.gwt-multipage'/> <!-- Specify the app entry point class. --> <entry-point class='com.claudiushauptmann.gwt.multipage.client.EntrypointDispatcher'/> <!-- <entry-point class='au.org.myCRM.client.myCRM'/> --> <!-- Specify the paths for translatable code --> <source path='client'/> <source path='shared'/> </module>
Then, we need to to create a new entry point class, AccountEntryPoint:
package au.org.myCRM.client;
import au.org.myCRM.client.account.ui.data.DetailsNavigationPaneSectionData;
import au.org.myCRM.client.account.ui.view.InformationView;
import au.org.myCRM.client.account.ui.widgets.ToolBar;
import au.org.myCRM.client.account.ui.widgets.Masthead;
import au.org.myCRM.client.account.ui.widgets.NavigationPane;
import au.org.myCRM.client.ui.data.NavigationPaneRecord;
import au.org.myCRM.client.ui.view.ContextAreaFactory;
import au.org.myCRM.client.ui.widgets.NavigationPaneSection;
import com.claudiushauptmann.gwt.multipage.client.MultipageEntryPoint;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.resources.client.CssResource.NotStrict;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.RootLayoutPanel;
import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.grid.events.RecordClickEvent;
import com.smartgwt.client.widgets.grid.events.RecordClickHandler;
import com.smartgwt.client.widgets.layout.HLayout;
import com.smartgwt.client.widgets.layout.VLayout;
import com.smartgwt.client.widgets.layout.events.SectionHeaderClickEvent;
import com.smartgwt.client.widgets.layout.events.SectionHeaderClickHandler;
@MultipageEntryPoint(urlPattern = "account.html")
public class AccountEntryPoint implements EntryPoint {
private static final int NORTH_HEIGHT = 73; // TOOLBAR_HEIGHT + MASTHEAD_HEIGHT
private static final String DEFAULT_MARGIN = "0px";
private VLayout mainLayout;
private HLayout northLayout;
private HLayout southLayout;
private VLayout eastLayout;
private VLayout westLayout;
private ToolBar toolbar;
interface GlobalResources extends ClientBundle {
@NotStrict
@Source("myCRM.css")
CssResource css();
}
public void onModuleLoad() {
GWT.log("init OnLoadModule()...", null);
// inject global styles
GWT.<GlobalResources>create(GlobalResources.class).css().ensureInjected();
// get rid of scroll bars, and clear out the window's built-in margin,
// because we want to take advantage of the entire client area
Window.enableScrolling(false);
Window.setMargin(DEFAULT_MARGIN);
// initialise the main layout container
mainLayout = new VLayout();
mainLayout.setWidth100();
mainLayout.setHeight100();
mainLayout.addStyleName("crm-Entity-MainLayout");
// initialise the North layout container
northLayout = new HLayout();
northLayout.setHeight(NORTH_HEIGHT);
VLayout vLayout = new VLayout();
// initialise the Application menu
toolbar = new ToolBar();
// add the ToolBar and the Masthead to the nested layout container
vLayout.addMember(toolbar);
vLayout.addMember(new Masthead());
// add the nested layout container to the North layout container
northLayout.addMember(vLayout);
// initialise the Navigation Pane
NavigationPane navigationPane = new NavigationPane();
navigationPane.add("Details", DetailsNavigationPaneSectionData.getRecords(),
new NavigationPaneClickHandler());
// select the first Navigation Pane section e.g Details
navigationPane.expandSection(0);
// initialise the West layout container
westLayout = navigationPane;
// initialise the East layout container
eastLayout = new InformationView();
// initialise the South layout container
southLayout = new HLayout();
// set the Navigation Pane and Context Area as members of the South layout container
southLayout.setMembers(westLayout, eastLayout);
// add the North and South layout containers to the main layout container
mainLayout.addMember(northLayout);
mainLayout.addMember(southLayout);
// add the main layout container to GWT's root panel
RootLayoutPanel.get().add(mainLayout);
}
public class NavigationPaneHeaderClickHandler implements SectionHeaderClickHandler {
@Override
public void onSectionHeaderClick(SectionHeaderClickEvent event) {
// get the Section Stack section's name e.g. "Sales"
NavigationPaneSection section = (NavigationPaneSection) event.getSection();
// get the selected record from the Section Stack section's List Grid
NavigationPaneRecord record = (NavigationPaneRecord) section.getListGrid().getSelectedRecord();
setContextAreaView(record);
}
}
private class NavigationPaneClickHandler implements RecordClickHandler {
@Override
public void onRecordClick(RecordClickEvent event) {
NavigationPaneRecord record = (NavigationPaneRecord) event.getRecord();
setContextAreaView(record);
}
}
private void setContextAreaView(NavigationPaneRecord record) {
ContextAreaFactory factory = record.getFactory();
Canvas view = factory.create();
southLayout.setMembers(westLayout, view);
}
}
and a new host page, account.html:
<!doctype html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link type="text/css" rel="stylesheet" href="myCRM.css">
<title>Account:</title>
<!-- You must set the variable isomorphicDir to [MODULE_NAME]/sc/ -->
<!-- so that the SmartGWT resources are correctly resolved -->
<script> var isomorphicDir = "myCRM/sc/"; </script>
<script type="text/javascript" language="javascript" src="mycrm/mycrm.nocache.js"></script>
</head>
<body>
</body>
</html>
Tip: If you are using Eclipse as your IDE then don't forget to add "gwt-multipage-1.0.0.Beta4.jar" to your project's build path.

3. Test the application in development mode
Launch myCRM in development mode and if you double click in the Account's view:

The Account details form will be displayed:

What's Next
At this point, we've added support for multiple host pages to myCRM. Next, we'll look at how to add support for other languages to myCRM.
