Wicket: Website hierarchy - wicket

Thats a general question about: How to structure my website with all its pages and components (here panels) in wicket. I would like to show my attempt and hope someone can give me advice, wheather its a good way or if there is a better one.
My Structure is like:
Root: HomePage
Page1 extends HomePage
Page2 extends HomePage
Page3 extends HomePage
The pages wrap the content and its own navigation. They get init in HomePage.html with wicket child.
Now, when I define a new Panel for Page1, I have to define a link for it as well. For the link onClick() I set the panel to which it refers to visible and all other panels to invisible. Also I have to define on the Page1 the panel, which gets shown when I navigate to Page1. All other panels are invisible.
Is this a good attempt or is there a better way? Now I initialize ever panel and just hold them invisible.

A shot at answering your questions... This assumes you're using Wicket 1.4.x.
First, you can have many levels of Page classes, often mimicking the overlap of the design and function. For example, say you have an application where people "Write", "Browse" and "Read" user-created books.
RootPage - common headers/footers, javascript imports
AbstractWritePage extends RootPage - for anything regarding authoring
AbstractBrowsePage extends RootPage - browsing
AbstractReadPage extends ReadPage - reading
Then, I implement something like:
FullLibraryPage extends AbstractBrowsePage
FilterSearchPage extends AbstractBrowsePage
In the long run, it gets complicated, but very powerful.
Secondly, your Panel components that go visible/invisible. If you're using Wicket 1.4.x, you should look at the overrideable method onConfigure() for each Panel. In this panel, you can set the visibility like:
#Override
protected void onConfigure() {
super.onConfigure();
setVisible(!navTriggered);
}
where navTriggered is a boolean value residing in the containing page. Then, your link could do a simple:
#Override
protected void onClick(AjaxRequestTarget target) {
navTriggered = false;
target.addComponent(/* Appropriate panels; see below for multiples */);
}
The advantage to this is that you can have multiple panels triggered by the same boolean variable. There is nothing wrong with creating all of your panels at page creation time, even if they start out invisible.
Finally, if you have a lot of panels that need to be changed/triggered/etc, consider pairing an IVisitor with a marking interface. Something like...
public class Panel1 implements MyPanelGroup { ... }
public class Panel2 implements MyPanelGroup { ... }
Then, you can use an IVisitor to visit every instance of MyPanelGroup in a page and do something with visibility (either set visibility, add it to the AjaxRequestTarget, etc).
Hope that answers something :)

Related

Eclipse RCP: Get notified when IWorkbenchPreferencePage is left

I have implemented two custom IWorkbenchPreferencePage's and they are working as expected. Basically Page1 shows different information based on the selections made in Page2. The problem is that I have to close (explicitly save) the preference dialog to see the changes of Page2 reflect in Page1.
Now I was wondering if there is some kind of mechanism that would allow me to do something (In my case save information on the open preference page) once a IWorkbenchPreferencePage gets left.
You can override the okToLeave method which is called when a different page is selected.
The default implementation of this in PreferencePage is:
#Override
public boolean okToLeave() {
return isValid();
}
You can also use the
public void setVisible(boolean visible)
method which is called when the page is made visible and when it is hidden (be sure to call super.setVisible in your override).

Is this an acceptable GWT solution

I want to create a GWT UI where I basically will have a single HTML page that loads a PanelA object. The user will then do their thing and eventually perform an action that will move them onto another view/screen.
I have simplified my existing views to contain just a single button which moves the user onto the next page etc. for simplicity I only have 2 views to start.
Here is my start up entry point.
public class StockWatcher implements EntryPoint
{
public void onModuleLoad()
{
final RootPanel rootPanel = RootPanel.get();
rootPanel.add( PanelA.getInstance() );
}
}
Here is the PanelA class
public class PanelA extends HTMLPanel
{
private static PanelA panel;
private PanelA()
{
super("Panel A");
final RootPanel rootPanel = RootPanel.get();
Button btnNewButton = new Button("Go to panel B");
btnNewButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event)
{
rootPanel.clear();
rootPanel.add( PanelB.getInstance() );
}
});
add(btnNewButton);
}
public static PanelA getInstance()
{
if (panel == null)
{
panel = new PanelA();
}
return panel;
}
}
My other PanelB class is pretty much the same as PanelA , ie button that brings me back to PanelA
My UI works as desired.
My Question is, Is this singleton type pattern a correct or proper way to do this? ie Have a stack of Singleton UI views that get popped on/off the main panel?
Also, what is the best way to handle hitory/breadcrumb trace through a GWT app, ie allowing a user to go back to the previous screen bearing in mind that they may navigate to PanelX from either of PanelA, PanelB or PanelC
I use "Activities and Places" to manage all of this, and it's been working quite well in production for a year or so.
https://developers.google.com/web-toolkit/doc/latest/DevGuideMvpActivitiesAndPlaces
I think it's fine to use a Singleton mechanism for your views, but you have to make sure to completely reset any state you store. For me, it was easier to just create new views every time the user navigates to a new spot, and then if I detected a problem with load times or something to retroactively cause the view to re-use its components. I'd advise you to get the navigation working first, and then worry about the singleton (or not) optimizations.
I recommend Activities and Places design pattern.
It covers all the issues you raise in your question, plus many more that you have not thought of (or did not ask about) yet, like native browser history management and ability to bookmark different places within the app, handling of page reloads, efficient memory management vs optimized DOM operations, scalability (building an app with dozens/hundreds of views with minimal code duplication), testability, and code-splitting (where to split large apps).
I suggest you refer "GWTP" framework to make a GWT Project, some of the features currently supported by GWTP:
Dependency injection through GIN and Guice;
Simple but powerful history management mechanism;
Support for nested presenters;
Lazy instantiation for presenter and view;
Effortless and efficient code splitting;
Integrated command pattern supporting undo/redo;
So your questions and query like Singleton UI views, best way to handle hitory/breadcrumb trace and singleton type pattern , will cover and one good framework will make easy project management.

Actionbar and ListActivity in one Activity

I have a program which shows lists of files in directories on the SDCARD and when the user clicks on a file it opens the PDF up. For instance one activity will display the contents of one folder.
I have been wanting to add the ActionBar for navigation and can get the ActionBar to work in its own activity and my ListActivity to work in its own activity, however I cannot get them to work together.
I am not sure how to combine the two so that I end up with one activity that displays the action bar and the file list in the one Activity?
The Actionbar Activity starts with
public class SecondActivity extends FragmentActivity implements ActionBar.OnNavigationListener {
The Activity that displays the clickable list starts with
public class MainActivity extends ListActivity {
My android app programming is quite basic and self taught so I am probably missing something obvious. Thanks in advance
I have posted an alternative solution that separates the concerns of the List and the ActionBar. Makes the code a little tidier IMO.
I think you can extend your class to ListActivity and override method onCreateOptionsMenu to bind your action bar to the activity:
public class MainActivity extends ListActivity {
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.your_action_bar_name_here, menu);
return (super.onCreateOptionsMenu(menu));
}
// your other methods
}

How to get a Listener in Eclipse FormPage

I am adding 3 pages inside an editor through Eclipse's FormPage. Now on selecting each page I want a listener to get fired. I tried to implement IPageListener in each page class, but none of them responded me. How to get the listener while selecting any page in eclipse FormPage?
I have made a FormEditor class,
public class SimpleFormEditor extends FormEditor
Then I added addPage inside it,
addPage(new ApplicationFormPage(this));
Now in this ApplicationFormPage, I implemented IPageListener,
public class ApplicationFormPage extends FormPage implements IPageListener{
Actually my plan is to get the listener as soon as we click on this page tab.
When your form page is instantiated, you need to add it to something in order to get notified of page changes. In MultiPageEditorPart they use org.eclipse.jface.dialogs.IPageChangedListener.
formEditor.addPageChangedListener(page);

How to keep business logic seperate within GWT Composites?

I'm currently building a GWT login screen and I managed to get a basic version of the login structure working.
I created the following pieces:
An entry point class (actually it was given).
A main application screen composite.
A login-screen composite.
I have the following logic in my entry point method:
MyApplication mainWindow = null;
public void onModuleLoad() {
LoginScreen loginScreen = new LoginScreen() {
#Override
public String onLogin(String username, String password) {
boolean passwordWasOk = rpcCheckUsernamePassword(username,password); // mechanism not important for this question
if (passwordWasOk) {
RootPanel.get().remove(0);
mainWindow = new MyApplication();
// Using root layout panel as main window is a layout type composite
RootLayoutPanel.get().add(mainWindow);
return null;
} else {
return "password was incorrect";
}
}
};
RootPanel.get().add(loginScreen);
}
So, I created a method in the LoginScreen composite that is called when the user clicks the 'Sign-In' button. If the onLogin method fails its validation of the username and password, then a narrative can be returned to the login composite so that it can update the user. The login screen will stay on the screen until the user uses a correct username/password combination.
My question is, is this the correct way to use composites? Where should my login logic ideally reside. Is a better alternative to inject some sort of login handler object in the constructor of the composite or via a setter or is the method I used quite normal?
As I'm planning to write quite a lot of code, I want to get the coding style correct from the outset.
Any feedback is greatly appreciated.
Thanks,
For complex projects you'd want to use the Model-View-Presenter (MVP) design pattern. It allows you to separate the rendering logic (views) from the business logic. To get you started, the official documentation has two articles about it plus there's that presentation by Ray Ryan that started the whole GWT + MVP = <3 haze :) After that I'd recommend browsing through MVP related questions on SO and GWT's Google Group.