MVP in GWT. Complicated Views - java

Have a question about using mvp on complicated views.
Suppose, we have some widget with boilerplate design (ListWidget) like this:
Control buttons provide functionality for switching between ContentPanel (just regular CellTable with data) and DetailsPanel (here we can edit particular entry, this is not Modal Dialog)
DetailsPanel, in turn, have this structure
Button1, Button2, Button3 should deal only with DetailsPanel and change ActionPanel (ActionPanel some kind of wizard, so its content should be tottaly changed after Button1, Button2 or Button3 clicked), but Buttons Save and Cancel should navigate us back onto ListWidget.
What approach should I use to implement described functionality?
Should I use 2 different ActivityManagers with one of them in master context or not?
How to manage and broadcast messages to dependant panels on ListWidget? (Is it ok to put Handlers in Views and just push event into inner eventBus on some actions?
For instance, when I save item in DetailsPanel, PreviewPanel should change and this item should be focused in CellTable; etc)
If I should use pattern with two different ActivityManagers, how exactly should I handle activity change behavior?
Thanks, hope somebody helps me.

I am answering your question, first with a brief explanation and then point by point taking your questions.
At framework level, you could have a class which implements ValueChangeHandler and set that on History using History.addValueChangeHandler(controller); assuming controller is implementing the value change handler
Any newItem you would put in history with History.newItem("NameOfAction") would invoke implementation of ValueChangeHandler which in this case would be controller
Now within implementation of ValueChangeHandler you can
String token = event.getValue();
if (token.equals("NameOfAction")) {
Call Appropriate presenter
}
Now let's talk about the second part of framework, presenter and view implementation. I am assuming that RootPanel is the container of all your UI Widgets. You can create individual presenters for each action
presenter = new ActionPresenter(rpc, eventbus, new ActionView())
Notice that I am creating a view and passing on to the presenter, presenter gets data and build the view with data. You could later pass on the container to the presenter to show the whole thing on UI.
Now about your specific questions
MVP would be your best bet here The article on MVP here is pretty good
I don't see a reason to use 2 activity managers as long as your container of those widgets is same
EventBus would be ideal. If you have to pass data with events, session variable like static fields in main class would server your purpose
I would need more details on exactly what you want to put in which manager
Hope this helps!

Related

in pure MVP, who handles navigation?

If you want to implement an MVP app without any framework, who would deal with navigation between views?
Right now, I have this navigator interface/class and the presenter has a reference to its implementation. To navigate from login to home, I have the LoginNavigator with a method navigate().
This method is called in one of the presenter methods. However, the next view, the home view, needs data to be displayed and the data is passed to the view in a service class.
So: navigation = presenter, data passing = from service class
The reason I have a separate navigator thing going on is because I didnt want to put Swing-specific code (the switching of panels) into the presenter.
Any recommendations on how to implement this nicely when not using some framework?
the best idea is View should have responsibility for navigation action and the presenter would trigger that. but you can even do the action and trigger both in view which is not so clean.
the navigation interface is a great idea because in mvp, the concept says the more the view is silly the better MVP implementation would be.
the navigation mathods is better to be in every view contract separately. for example if you have a register page just a method called gotToVerifyView() is enough to handle the navigation. for every view you should have some methods like this to get the handle of navigation to the presenter. this way the presenter is specifying the road map some how.
I dont know whats really wrong with your case of receiving data from a service. explain more so i can edit my answer for better.

Looking for a GUI design-pattern that fits this application

I'm developing a desktop app in java for a school project and I want to know how should I be designing the code of the GUI, specially because I will later have to run JUnit and functional tests on the app. I know it kinda sounds like an opinion-based question, but all I'm not asking for the "best" method, I just want to be pointed to a specific design pattern that can fit the need of my app.
To elaborate a little more on the type of application, it's "stage based", one button leads to a different section of the app. One main window, only error or warning popups (only one frame).
My current approach so far:
So far I've designed 3 different JPanel classes using eclipse's WindowBuilder (main menu, admin menu and user menu) and a AppGUI class that creates and empty frame with a CardLayout layout and fills it with one of the 3 panels (starts with main menu). Then the buttons on such panels point to the next panel. (Example, main menu -> user menu -> create profile)
The panels need to communicate with the AppGUI instance in order to execute the panel changes and later on, the functionality that the other options will have. To do this, I've been passing the AppGUI instance as a parameter to the panels on initialization and storing it inside each panel (I first thought of having a singleton AppGUI and have static reference to it, but I later on read that it's bad practice, specially for later mock testing).
Also I'd like to have the logic for the application on different classes other than the GUI classes and I'm not sure if passing the AppGUI as parameter to every method out there is good practice or not
In conclusion, it would be great if someone could point me to a specific design pattern for this kind of GUI, thanks in advance!
I would suggest the Model View Controller (MVC) pattern.
The idea of MVC is that the models (your app logic), the views (UI elements), and the controllers all work together. The models and the views are completely independent of each other i.e. you don't pass a model class object to a view class object or vice versa. The models and the views should talk to the controllers and the controllers makes all the decisions.
Controllers
They contain your app's UI logic, like how to layout the views. They are notified by the model once in a while (e.g. some data have changed!). They are also notified by the views (e.g. the user pressed a button!). And controllers need to respond to these notifications. For example, when the user pressed a button, the controller might tell another view to show, or tell the model to do some calculations or some other stuff. In your case, your controller is most likely to have all the ActionListener for the buttons and text boxes on the UI.
Models
They contain your app's logic. Try to design your model to be UI independent as much as possible. If designed correctly, your model should still work without the UI i.e. you should be able to make a command line version of your app without changing the model. For example, if you are making a calculator, the model should do the actual calculation.
Views
Most of the time, you don't need to worry about this part because swing already provides you with lots of view classes, such as JButton, JPanel, JTextArea etc. If you happen to be creating your own views, remember that it should not contain anything related to the model i.e. the view should work fine with a different model.
You can always search for more info on the web.

In Java, is it good practice to pass through listeners (or objects) where it affects the parent component?

More of a theory question, possibly a silly one but was curious to know if there's a better way of implementing it.
Ok so the question:
What is the best way of implementing two child-classes to interact with each other when an event from one of them is fired? I didn't word that well, so perhaps a diagram would be of use.
MainPanel
/ \
/ \
/ \
Child #1 Child #2
So in the above 'diagram' (yey amazing drwaz skills), there's a MainPanel that holds/instantiates two child panels. These components are outside of each others scope, unless I'm mistaken, and therefore can not directly interact with each other.
Lets say Child #1 has a JButton, and when the event is fired, Child #2 changes it's JLabel from "Hi" to "Bye". How would you go about doing so in the 'best' way possible?
Currently, my implementation of the above would involve having Child #1's constructor call for a Listener to be passed through it, where it sets the listener on the JButton to whatever listener the object is instantiated with.
Code of that would look like :
public class MainPanel extends JPanel {
private Child1 child1;
private Child2 child2;
private ActionListener listener;
public MainPanel(){
listener = new ActionListener(){
public void actionPerformed(ActionEvent ex){
//some code
}
};
child1 = new Child1(listener);
child2 = new Child2();
}
}
public class Child1 extends JPanel {
private JButton button;
private Component component;
public Child1(ActionListener listener){
button = new JButton("button");
component = new Component();
button.addActionListener(listener);
setUpGUI();
}
}
Just crude coding to show what I currently do to relate sub-classes like that, I realize there are some things missing. And yes, in that above case I could've had the JButton in the main panel as it's only one button, but with JPanels or components that have many many layers to them it's not so simple and dividing them up is necessary.
Also, the Child2 panel would have a method to invoke when the action is fired, that I would call in the listener I create in the main panel.
TL;DR:
Essentially is there a better way of going about what I do in the above code to relate two sub classes that aren't in the same scope?
The general strategy this is solved is through an MVC architecture. In an MVC architecture, you keep a model that represents the data being manipulated and is the single repository of truth. In some situations, this model may be linked with a database, but there does not necessarily have to be a database.
All of UI views only have to know about the model and how to update itself with regard to the current state of the model. All UI controls only have to know about the model and how to update the model when the UI control is activated. The model provides a notification service for interested parties, every time the model gets updated, the model searches through the list of interested parties for those that are listening for the type of change that had just happened, and send a change event notification so they can update themselves.
This way, any UI elements doesn't need to know about any other UI elements, it only needs to know about the models. Note that when a UI control is activated, it triggers action notifications to the model, which triggers change notifications to the UI views and possibly to the database; the UI views do not need to know what control originally triggered the change in the model and thus do not need the original action listener. Which controls triggered the change does not matter, only that the change happens and that the UI view is stale and need to be updated.
Note that a single UI widget can play the role of both a UI view and a UI controller, but these roles should be distinguished.
In your case, Child #1 seems to play the role of the UI controller, and Child #2 plays the role of one of the view that needs to be updated. You need a way to manage the events registrations such that the Model is notified when Child #1 is activated and register Child #2 as an interested party whenever the Model's status changes. Once this is set up, child #1 should only need to know to notify the Model that it wants the model to change its status to "Bye"; the Model then needs to look for who is interested in the status change, and find that Child #2 does, and sends a status change event.
There are plenty of ways to do it. Neither of them is the best (depends on the situation). I would stick to the rule called "KISS" - in short, keep it simple. If one does not have many references in their code (which is your example) - just give a reference to its sibling to each acting class, and that is it. Very easy, and you will be able to understand what is happening in your code easily. Unless you want struggling.
If you want struggling - this is a very good solution for your example: http://en.wikipedia.org/wiki/Mediator_pattern. But I would just stick to your present solution, because simplicity is the ultimate sophistication.

Instanceof, Enum Or Multiple Listeners for JButtons

On my swing GUI I have lines of data and a number of buttons, the user selects a number of items and then then selects a button.
Each button applies a different rule to the data and so different functions need to be called for every button, I'm using an MVC design pattern and my question is such, How should I handle the different needs of every button?
Create a class 'MyButton' which extends JButton then give this some sort of Enum, I can then create 1 action listener and then check which button has been pressed in the ActionListener by inspecting the Enum.
Similar to above but with a different class for each button then using instanceof to determine which has been pressed.
Implement a separate ActionListener for each button
Other?
Which is the best method to use if any? Any advice would be greatly received!
Implement a separate listener for each button.
First because it's the usual solution. Second, between there's no reason to extend JButton just to do something else when it's clicked. That's the role of the ActionListener. Swing components are designed to be used as is, and you should generally not extend them.
It's MVC: you separate the logic (in Actions) and the view (the button).
There is no need to use an enum or to subclass JButton. What you can do to keep things clean when you have dozens of buttons, is a factory class to create Action instances.
If I get your question correctly, you mean to say, you have a data in line items and every line items have a button, which when pressed invokes a rule pertaining to the line item.
If so, then
If you take the 2nd approach, you need to code inside your action listener every time a new line item added in future.
Third approach will also have same implication as above
First approach sounds quite good. You can have a Factory which may have a hashmap keyed with the enum variables and the respective rule. Inside the action listener get the rule from the factory and invoke it.
This way you get a proper separation of concerns and your action listener will act as a controller, having no knowledge of rules and data items.

How to implement a Compound View/Presenter for a GWT DecoratedTabPanel?

I'm new to GWT, and I've been reviewing the MVP implementation which uses the rpcService and the eventBus. I was wondering how a tab panel can be implemented such that each tab has its own sub-view. I have been waffling between making a custom widget that derives from a panel, or to figuring out how to make a presenter use another presenter, or to make a compound presenter class which handles it all for me.
Does anyone have advice on how to separate the functionality for each tab as opposed to keeping the implementation within one view/presenter pair?
I was in the same situation, but decided to change my implementation to simulate a TabPanel. If your views and presenters don't need to interact with each other (e.g. dragging something from one tab to another) then I think it'll be easier to separate functionality by loading your View into a shared SimplePanel. You can simulate the tabbed portion of the TabPanel with a widget that listens for PlaceChangeEvents (to change the highlighted tab) and sends goTo commands to the PlaceController your app is using (to handle clicks on the different headers).
It took a couple of hours to implement this, and the resulting code is much cleaner. My initial attempt involved listening for PlaceChangeEvents and then calling the appropriate tabPanel.selectTab() function, but trying to figure out how to start and stop the presenters for the different tabs was too jumbled up - like you suggest, you'd have to implement your own compound view model.
I solved this without faking a main tab, but using the one provided with GWT's basic SDK. I did this by:
Add an ArrayList of Presenters to the MainTabPresenter
Constructed each tab's present plus view within the 'go' method of the MainTabPresenter
Called 'go(null)' on each of the tab presenters.
Handled the null situation on each.
Implemented a method in the MainTabView to add the tabs to the DecoratedTabPanel
It all works like a charm. The MainTabPresenter so very thin, and allows for complete implementations of View/Presenters to be written into their own files.

Categories

Resources