Basic MVC design: views - java

So there are two different views(controllers are merged into views):
View 1: Tabular view. There is a table and a number of buttons on top of the table.
View 2: Text view. There is a text area and a number of buttons which are distinct from the buttons in Tabular view.
There is one model file for two views files to link.
I also create a main.java file to declare the main window,a tabbed pane(to switch views) and bind views to it.
As a noob java developer and MVC design pattern learner, I was wondering:
1. What is the correct way to declare buttons, the table and text area?
For example, for View 1(Tabular), are its buttons and table declared in the view or in the main.java?
2. If declared in views, how are they added in the main window? Default UpdateAllViews() doesn't seem to go through the main window in main.java.
At this point, I am only aware that model should never ever have anything like JButton declared in it as model itself should not be aware about what the window and stuff looks and feels. I can see that controllers are sort of binded to a certain view componenet, but the view itself gets me very confused.
If anyone can provide a shortcut to get deeper understanding of MVC pattern, I'd be appreciated.

Please keep in your mind that you are dealing with objects. And the Model, View and Controller are categories/collections of objects.
Your model objects are instances of classes relating to your business domain. e.g. if you are making an address book, you would have an ADDRESS class.
Your View objects provide a connection to your users. e.g. SEARCHDIALOG class and ADDRESSDIALOG class.
Your Controller provides the bindings/interface into your system (the systems API). you will have one controller that represents the system, e.g. ADDRESSBOOKAPP class.
Enjoy.

Related

JavaFX Tabs and Controller Scope

I have a configurations pane in my JavaFX 8 application that is spread across a number of tabs within tabs. Currently I am forced to split tabs for a longer configuration process.
I know that I'll have two .fxml files for the two tabs, but I should be able to use the same controller for both. Currently, however, if I make changes to one tab, the other tab doesn't see the changes. I'm guessing it creates a separate instance of the controller. Is it possible for the two .fxml tabs to use the same instance of the controller so that the information can be shared across the two tabs?
Example for more clarification:
Tab1 contains textfield input for email, Firstname, etc.
Tab2 uses email information and generates usernames and allows user to modify other settings using the generated values.
To reuse a controller between multiple FXML loads, you can use fxmlLoader.setController() or fxmlLoader.setControllerFactory().
I don't really recommend a reused controller approach, so I won't post detailed code for it here. Rather, I recommend passing parameters.

Ratio of GWT Places to Activities to Screen?

I'm trying to write a GWT app that reuses the same template for every "page" (place). There are 4 main "pages" of the app:
Dashboard page (http://www.mywebapp.com/#dashboard)
Calculator page (http://www.mywebapp.com/#calc)
Configurator page (http://www.mywebapp.com/#config)
Login page (http://www.mywebapp.com/#login)
Each "page" has the same templated look-and-feel: (1) a header section that contains the logo and the navigation menu, (2) a content section that contains "page"-specific content (i.e. will be different for the #dashboard place, #login place, etc.), and (3) a footer section that contains some links. So you see, the only thing that changes from page-to-page is the content section. Just like an ordinary, templated web site.
The thing is, each "page" (place) is actually a fairly complicated UI with many different panels consisting of lots of widgets. As the user interacts with the app, these panels will come into and out of existence and the display will be changing all the time. For instance, on the #calc page, the user can select which "mode" to display a calculator in: either as Basic or as Advanced. When the user selects Advanced, several additional panels will display (in addition to the Basic panel).
It would be nice to be able to keep such actions in history, so that the user can bookmark the app in either Basic or Advanced mode, so something like:
http://www.mywebapp.com/#calc/basic; or
http://www.mywebapp.com/#calc/advanced
Here's the problem:
We already have several "levels" of activities/places going on here. At the "app"-level, we have the template that needs to be displayed to the user when the MyWebAppModule implements EntryPoint downloads. This TemplatePlace is the default/initial place that is registered with the HistoryHandler before calling:
public class MyWebAppModule implements EntryPoint {
#Override
public void onModuleLoad() {
// ...
// The first place we go to when this module downloads.
TemplatePlace templatePlace = getSomehow();
historyHandler.register(placeController, eventBus, templatePlace);
historyHandler.handleCurrentHistory();
}
}
Next, we have all the different "pages": DashboardPlace, CalculatorPlace, etc. that all have their own unique views/displays. For instance when the user clicks the Calculator link to go to CalculatorPlace, it should render a different view than when the identify that they want to use the calculator in Basic or Advanced mode.
Finally, we have the different display regions, panels, etc. inside each page/place, such as the BasicCalculatorPlace and AdvancedCalculatorPlace. This is what I mean by different "levels" of navigation:
Application-level (a template to apply to all pages/places)
Page- or place-level
Display- or panel-level
The question:
I want to achieve bookmarkable URLs (places) for when the user does all of the following:
Goes to the home page (http://www.mywebapp.com)
Goes to any of the "pages" (http://www.mywebapp.com/#calc, etc.)
Uses the pages/places which cause page-specific panel or display configurations (http://www.mywebapp.com\#calc\#advanced, etc.)
How many Activities and Places do I create? How many ActivityManagers? I guess I'm asking for how granular Activities/Places need to be for each "level" of bookmarkable UI. Thanks in advance!
I think you only need one ActivityManager and one Activity per "page". You can make your "header" and "footer" into widgets that can be reused in each page.
You can bookmark different states of the same page by using tokens. For example, you can set a token to "basic" - it would tell the CalculatorActivity to show basic calculator panel. The URL will look like:
www.myApp.com/?#Calculator:basic
When a user clicks on a widget to select an advanced option, you do
PlaceController.goTo(new CalculatorPlace("advanced"));
The CalculatorActivity will get the CalculatorView (which is already displayed), it will see that the token is set to "advanced" and it will instruct this view to show advanced panels.
Note that you can make your tokens as detailed as necessary and then parse them in Activity. For example, you can have something like
www.myApp.com/?#Calculator:option=basic&position=top&theme=pink

GWT RadioButton Grouping

In my application, I have URN-identified data coming in from the server. I'm in the process of abstracting as far as possible so there is very little to no logical code in my views, and I'm using a generic presenter that wraps those views. All widgets have URNs, making it super easy to map incoming data to a specific widget (until now, a 1 to 1 relationship). This has worked well for pretty much every widget, and now I've reached a point where I'm tripped up.
Assume I have (just for simplicity's sake) two RadioButton elements on a view. These buttons belong to a "group" (just by setting their name values to the same thing), but obviously they're 2 distinct elements. I can't map my URN-identified data to a single widget as in every other case because, in this case, it is two widgets.
Here's an example of what I mean:
Utility Company is a ListBox, so just one widget there. I map each item in the list to a specific Enum value.
Utility Rate is a TextBox, so again just one widget to map.
For Energy Usage, they can select to use either an average for the year or input 12 monthly values. I'm stuck here. I can't map to just one of the RadioButton elements, because then I'd need some extra logic in the view to handle the behavior appropriately.
Am I stuck mapping to just one widget and sticking (unwanted) logic in my view to determine what the state of all of the elements should be based on the value that came in for the one widget that is mapped?
How should I handle this case?
Edit (Solution):
Following the concepts of jusio's answer, I came up with a workable solution. Because I didn't want to go sticking special case handling through my logic to take care of a non-widget, I created a RadioButtonSet faux widget (public class RadioButtonSet <T extends Enum<?> & HasDisplayText> extends Widget implements HasValueChangeHandlers<T>, HasValue<T>), into which I manually pass the radios I intend to group. Having done that, I can get or set its value and have it fire appropriate events when the user changes the selection. Then mapping the collection of radios is no different than doing so for a listbox. Thanks jusio.
I believe in your case you shouldn't treat radio buttons as two separate widgets, basically in your case you can treat the radio button group as combo box, because behavior is almost the same (the only problem is that you have additional master detail). So basically what you will have to do is to wrap real BO objects into some kind of RadioButtonGroupModel, and give it to view, view can take this model and generate radio buttons (with some editors or whatever else). I remember running into this problem when i was extending databinding FW for JFace, and this was the best way I could find to solve this problem.
If I understood correctly the problem, there are 2 possible solutions:
Give each RadioButton a unique URN (ex: oldURN_1 , oldURN_2)
When you send data for a URN, disable the other one
Keep the same Name for each RadioButton but add a number variable in the data the server sends indicating which radioButton it is supposed to use (ex: 0 for Average and 1 for Monthly)

Play! Framework: Layouts with different sections

I'm having a problem when trying to use layouts in the Play! Framework. As far as I know, a layout has a SINGLE #{doLayout /} tag that specifies where all the code of the child view should be placed. This means that all the code in a particular view of, say, list of Users (list.html) gets injected in the middle of the body of the layout. Now, I find that some of my views require javascript that is particular to those views, and so I'd like to include script tags only on those views and not on every single view that inherits from the layout. The Razor view engine in ASP.NET MVC allows for different sections in a layout that are filled in by a view that extends that layout, but I don't know if Play supports something like this.
Do you see a solution to this problem?
You can also use the #get,#set tags to define other blocks. For example:
#{set 'anyBlock'}
<h1>Main title</h1>
#{/set}
and:
#{get 'anyBlock' /}
You can use the script tag in your specific views. For instance :
#{script 'jquery.js' /}
I recommend you to read this documentation page :
http://www.playframework.org/documentation/1.1/tags#script

GUI: Changing panels based on value of combo box

I have a question about GUI design, specifically with Java Swing and creating clean separation between presentation and model.
It's a bit difficult to describe, but essentially we have lots of reference data in our system (i.e. that would correspond to lookup tables in the DB). We want people to be able to edit them all from one screen.
So, in an ideal world what we'd like is a combo box in the top-left corner with a list of 'types' of reference data (so each corresponding to one table in the DB).
Then, when selected, a list of the data is populated below, also a filter (or search box). When one of these items is selected, the panel to the right is activated which will allow the actual data to be edited.
Now, here's the problem: each type of data we need to edit is different, so it has different fields etc. We could go with a generic solution but I'm not really a fan of them - there are lots of different validation rules for each etc, even for different clients, and it would be a nightmare to manage.
We're using the Presentation Model pattern to achieve some degree of separation between GUI code and the model but I can't think of a clean way of doing this which doesn't somehow blur the line of responsibilities a bit.
What are the ways you have solved problems like this?
[Note: apologies for the long question, hope it's understandable, I can re-phrase if necessary]
You could use the Factory Pattern to create a UI widget for the element that you are selecting. You could also use it to create a validation rule object depending on the type. This would give you some of the flexibility you desire.
So you can have something like:
IWidget widget = UIFactory.createFor(myObject.getType())
That can be invoked on the selection event to create the right widget to edit the selected element.
The IWidget could have methods such as:
validateData()
refreshData()
setDataElement(IDataElement element)
That would allow you to treat all UI widgets generically, but still have a special UI widget for each element type. I am assuming that the elements that you are selecting from the table all implement some IDataElement interface that contains the getType() method.
I used this solution tied together with the Eclipse Extension mechanism to plug-in new UI elements into my "base" solution, to have an extensible core and a high level of reuse. You could achieve something similar by injecting types and widgets into your factory, either manually or with Spring.
If you dont want to go down the generic path, you could have your model hold a mapping of combobox item -> panel name for use with a CardLayout. You could then create custom panels for the editing each of the reference data types. When the combo box selection is changed, you can save the current state in your model, request the panel name of the current selection, prepare your next panel for display and then have your CardLayout show it.

Categories