Redrawing container or individual, dynamic elements in GWT page? - java

I am developing a GWT app (I'm fairly new to GWT so this is a request for best practices; I haven't found any relevant answer on SO or elsewhere) where a timeline is required. This timeline (with descriptions, labels, interaction handles, and plots) resides in its own container (a Panel).
[<] [now] [>] // Interaction (navigation)
2007 2008 2009 2010 // Labels
| | | |
+ Group 1 // Collapsible groups
- Group 2
Item 2a ===== == // Item with plots (plots are wrapped in container per Item)
Item 2b ===== === =
-Group 3
Item 3a ===
Item 3b ===
Now, when user's navigate the timeline (using the button to move forward or backwards), I need to recalculate some elements of the layout:
Labels need recalculating / repositioning
Plots need recalculating / repositioning. Plots are based on a set of Timeslot elements (extends Widget, attributes dateStart and dateEnd) which are already related to Items which are related to Groups.
The collapsible panels are DisclosurePanels.
As far as I can tell, I now have two options for handling navigation:
I can clear() the container panel and do a complete redraw. For this, I need to preserve the state (collapsed/expanded) for all groups. (Groups and items are static for the entire period, by the way!) This will give one big redraw.
I can let the plot containers (each Item has its own TimeslotContainer which is a FlowPanel) hold a reference to all its Timeslots and then let every TimeslotContainer redraw itself (i.e., filter and position relevant Timeslots) based on the current timespan. This will give several minor redraws (one per Item per expanded Group), the advantage being that the DisclosurePanels will be preserved, thus maintaining their own state.
I'm inclined to go with the second solution. But are there any best practices on this one? Am I missing some common gotchas?

If groups and items are static I would also recommend the second approach.
DOM operations (constructing, etc) are properly the most expensive functions in a GWT application (performance wise) so these DOM operations should be kept at a minimum.
However I don't think performance may be a big issue here because the amount of DOM elements is relatively low.
Nevertheless I still think the second approach is better. You don't have to store the state for groups and items and as they are static it doesn't really make sense to redraw them.
I can only think of one advantage of the first approach:
There will be only one relatively easy draw function. In the second approach all TimesSlotContainer have to implement a function in order to redraw themselves and also take into account position and context of the Timespan. That function might be more complicated then one big re-draw function.

I went ahead and implemented a version of the second solution under the original intention to try the first if the second did not perform sufficiently. (This was never realized, though, as the second solution performed highly satisfactorily.)
What I asked in the question was primarily references to the GWT way to do this. I still haven't found anything written regarding this issue and so suspect that nobody has missed such guidelines before :) To conclude my search, I will self-answer the question outlining the way I ended up implementing together with the (assumed) pros and cons. Thanks to #Ümit for supporting my instincts. The following is in part intended to address the last paragraph in #Ümit's answer regarding the complexity of the draw methods.
I ended up letting TimeslotContainers (the Panels containing TimeSlots), LabelPanel (Panel with generated HTML elements), and NavigationPanel realize a simple interface:
public interface IReceivesPeriodChangedEvents {
public void periodChanged();
}
A simple EventBus handled the notification process on these IReceivesPeriodChangedEvents instances:
public class EventBus {
private static EventBus instance;
private Set<IReceivesPeriodChangedEvents> receivers;
private EventBus() {
this.receivers = new HashSet<IReceivesPeriodChangedEvents>();
}
public static EventBus getInstance() {
if (instance == null) {
instance = new EventBus();
}
return instance;
}
public void addReceiver(IReceivesPeriodChangedEvents receiver) {
this.receivers.add(receiver);
}
public void notifyPeriodChanged() {
for (IReceivesPeriodChangedEvents receiver : this.receivers) {
receiver.periodChanged();
}
}
}
Whenever one of TimeslotContainer, LabelPanel or NavigationPanel were instantiated (once per page load, these objects are reused throughout the lifetime of the page) they made sure to subscribe to the EventBus:
public class TimeslotContainer extends FlowPanel implements IReceivesPeriodChangedEvents {
public TimeslotContainer(/* ... */) {
// ...
EventBus.getInstance().addReceiver(this);
}
// ...
}
In order to handle the "complex" draw method, I simply created a method (buildFromStore()) to add relevant Widgets (e.g., newly created Timeslot objects on the TimeslotContainers). This resulted in great reuse of the draw method:
public class NavigationPanel extends FlowPanel implements IReceivesPeriodChangedEvents {
public NavigationPanel() {
// ...
buildFromStore();
EventBus.getInstance().addReceiver(this);
}
private void buildFromStore() {
// Add lots of HTML elements here
}
#Override
public void periodChanged() {
clear();
buildFromStore();
}
}
Simple as that!
In conclusion:
No gotchas encounted. Lots of minor redraws did not seem to be a problem (I never implemented solution one, though). The draw methods could be reused (in this case, at least). The collapsible DisclosurePanels never lost their state as they were never replaced (only their contents were).

Related

Best practice to create large web applications with multiple views, many components and nemory issues

I am not sure how I should best structure my Vaadin Web application.
Assuming in my web application, we have many different View objects with each lots of components. The components never change, but the data in the components changes upon every page enter.
I am seeing two possibilities:
Create and initialize all the objects once in the View's constructor. When the View's enter(ViewChangeEvent event) gets called, bind the data to the already existing objects.
Do nothing in the View's constructor. Create all the components in the enter(ViewChangeEvent event) method, bind the data to these components.
Simplified example of the two different approaches:
public class OneView extends VerticalLayout implements View{
private TextField[] textfields = new TextField[VaadinprojectUI.TESTLIMIT];
public OneView() {
long startMs = Calendar.getInstance().getTimeInMillis();
for (int i=0;i<VaadinprojectUI.TESTLIMIT;i++){
TextField txtField = new TextField("Textfield #" + i);
textfields[i] = txtField;
addComponent(txtField);
}
long finishMs = Calendar.getInstance().getTimeInMillis();
System.out.println("OneView() - constructor" + (finishMs - startMs));
}
#Override
public void enter(ViewChangeEvent event) {
long startMs = Calendar.getInstance().getTimeInMillis();
for (int i=0;i<VaadinprojectUI.TESTLIMIT;i++){
textfields[i].setValue((String.valueOf(Math.random()*1000)));
}
long finishMs = Calendar.getInstance().getTimeInMillis();
System.out.println("OneView - enter()" + (finishMs - startMs));
}
OneView will first create 1000 TextFields, add them to the VerticalLayout, and store them in an array for reuse. When OneView is navigated to, it will bind the data to the textfields.
public class TwoView extends VerticalLayout implements View{
public TwoView() {
//nothing in the constructor
}
#Override
public void enter(ViewChangeEvent event) {
long startMs = Calendar.getInstance().getTimeInMillis();
//entire load is in the "enter", only called upon navigation.
for (int i=0;i<VaadinprojectUI.TESTLIMIT;i++){
TextField txtField = new TextField("Textfield #" + i);
txtField.setValue((String.valueOf(Math.random()*1000)));
addComponent(txtField);
}
long finishMs = Calendar.getInstance().getTimeInMillis();
System.out.println("TwoView - enter()" + (finishMs - startMs));
}
TwoView will not do anything in the constructor, but whenever it is navigated to, it will create 1000 TextFields, and bind the data to them. The textfields are not stored, and will be remade at another time.
Some testing, navigating back and forth:
OneView() - constructor32
OneView - enter()14
TwoView - enter()28
OneView - enter()5
TwoView - enter()18
OneView - enter()3
TwoView - enter()12
Upon starting the application, OneView takes some time to create its TextFields. But after that, it always does a faster job to bind the data to its TextFields (which is expected).
Questions:
What are the tradeoffs with using the OneView system when it comes to memory management? Can we freely create View after View in large applications? I have a real world Vaadin application where we are getting OutOfMemoryErrors, and I feel maybe it's because I am reserving so much space for reusable components
What happens when the page is left? In TwoView, I assume the Garbage Collection destroys everything and frees up the memory. In OneView, the TextFields remain in the memory with the data assigned to them. Is there something as an "exit()" event when the user leaves the View that we should use to clear the data in the components? I am thinking in cases of ComboBoxes or tables with lots of Objects in them, but that don't get cleared upon page leaving and clog up the memory because they won't get GC'd?
Thanks for any advice
I think this is one of the questions which are best answered with: It depends...
When you pre-create all potential vaadin elements, and then bind/unbind them on View enter/leave, you will have better performance.
From the memory point of view, it might get ugly, when you have 1000 instances of the view "preloaded" but only 4-5 actively used...
If you however reuse the same view/components many many times, this will be better from the memory GC point of view.
The better way would be to create the elemnts as needed, and remove/free them as soon as possible.
When you corretcly remove all references to the vaadin components, the GC should trigger before a OOM exception is thrown.
Since you actually see OOM, this suggests that you don't free resources in a timely fashion. (Or perhaps your memory is just too small for what you wish to do)
When you add a view to a Navigator you can either add a class you've created like this:
Navigator navigator = new Navigator(this, this);
navigator.addView("viewStuff", new ViewStuff());
Or you can add the view and refer the the class instead
navigator.addView("viewStuff", ViewStuff.class);
This way the navigator creates a new class each time one is required. I chose this method as we have a lot of views and didn't really want a load of view created that may never even get used.

Why use JavaFX properties?

Pardon my question if it may seem stupid but I'm curious. I am making a program in Java of which will have a GUI, and am curious about the whole idea of properties. Why use them when we can just add data to a class? For example:
class myButton extends Button {
private boolean booleanProperty = false;
myButton(args...) {
// Do something with the property
}
public void setProperty(boolean value) {
this.booleanProperty = value;
}
public boolean getProperty() {
return this.booleanProperty;
}
}
Seems to work just fine for storing additional information on the custom implementation of the button. But what about:
class myButton extends Button {
private SimpleBooleanProperty booleanProperty = new SimpleBooleanProperty(false);
myButton(args...) {
// Do something with the property
}
public void setProperty(boolean value) {
this.booleanProperty.set(value);
}
public boolean getProperty() {
return this.booleanProperty.get();
}
}
The only real difference, I am seeing (correct me if I'm wrong) is that that you can attach listeners to the property values, but I feel as if there has to be more than just that. Ideas?
The power of JavaFX's properties is that they can be bound in ways that will automatically update the UI when a change occurs.
As an example consider an element you want to hide if a textField contains no value:
TextField tf = ...
Node container = ...
container.visibleProperty.bind(tf.textProperty.isNotEmpty());
Now as you change the text in tf, you will see container switching whether its visible based on the presence of text.
They really are useful in a lot of ways I even started them using in non UI related stuff. But look at this example: You habe an undomanager class
public class UndoManager {
BooleanProperty canUndo = ...;
BooleanProperty canRedo = ...;
...
}
And you have 3 places from where you can invoke undo/redo.
MenuButton menuUndo;
Button toolbarUndo;
MenuButton contextMenuUndo;
You basically only beed to do this:
menuUndo.disabledProperty().bind(undoManager.undoProperty()):
toolbarUndo.disabledProperty().bind(undoManager.undoProperty());
contextMenuUndo.disabledProperty().bind(undoManager.undoProperty());
and you dont ever have to worry about it again. If you add a new place where an undo can happen you just have to bind it too.
In this case you don't have a benefit, since you do not allow access to the property object itself. Usually this is done.
This allows you to add listeners to the property and be notified, when it changes.
Bindings are using this possibility to keep values the same and properties as well as the Bindings class provide methods for simple conversions of properties.
BooleanProperty booleanProperty = new SimpleBooleanProperty();
booleanProperty.addListener(new ChangeListener<Boolean>() {
#Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
System.out.println("property changed form "+oldValue +" to "+newValue);
}
});
booleanProperty.set(true);
booleanProperty.set(true);
booleanProperty.set(false);
booleanProperty.set(false);
booleanProperty.set(false);
booleanProperty.set(true);
booleanProperty.set(false);
booleanProperty.set(true);
booleanProperty.set(false);
Furthermore it allows you to pass an object representing the property. E.g. code that has to write/read booleanProperty does not need information about the myButton to write/read the property; you can just pass the property.
TableView is an example of a class that makes use of propertys. The columns used with TableView get a property from the items in the TableView and TableView registers a listener to that property. This allows it to change the values displayed in the cells even if the changes are triggered somewhere else in the code. Also for editable cells the properties of the items can be automatically modified.
The use of a javafx property for a pre-made object to hold an arbitrary value for later use. So you can set values to a text field or some other object that doesn't directly effect the shown value
Imagine programming a robot that would take care of resturant customers. How would it respond to customers or any other tasks that would have to be taken care of without using something like property listeners.
The benefit of using property listeners is that you can make your program become Concurrent. If there are no customers coming the next 1 hour your otherwise Sequentially made program would stand and do nothing for the next hour. Maybe switching the word Concurent with flexible in this example would be better, but you should look up Concurent programming and Sequence programming. Those properties allow you to customly make your program concurent.
You should also know that the gui you are using are already use built-in (event listening) features which build on the same principle.
Now what if you made that robot - instead of handing 1 customer at a time - respond depending upon what had to be done instead. Ask customers what the food tasted like (if customers have eaten), take new order(if called upon - by ANYBODY), take dishes(When any customer has paid and there is dish on a table), handle payment(When called upon by anybody). And ofcours handling a new customer arriving at the resturant.
The concurrently made program will handle any task needed by any customer. The sequencly made robot would only handle one customer at a time. Maybe it only then also has to be limited to greeting customers and placing them on seats to be anyhow useful. (You cannot have 1 robot for each customer).
Some people think it is easier to program sequencially can also be said. This is beacuse it can be difficult to keep track of subtasks that has to be done in a particular order. For instance that robot should not look for dishes when there haven´t arrived any customers. And what happens if it receives a payment call - while carrying dish? So it´s hard to prioritize and sort out the different tasks. However when succesfully doing it you program becomes so much more effective. It will be able to mutli task vs just solo-tasking.
And yes the sole purpose of properties is indeed that you can add listeners to them.

A Java advanced text logging pane for large output

Mathematica comes with a simple java program that allows to inspect the communication between front end and the kernel. It's called LinkSnooper and in general it works quite nice. It looks like this
I think I can improve the behavior and usability of the program to some extend, but to do this, I need to reimplement some parts. One fundamental piece that I need is a text pane, which has the following properties:
it can receive a lot of data and it probably should use a fast ring-buffer so that the very first log-lines are removed when the data grows too much. Another possibility is that it automatically starts to write data to disk and possibly reloads it when the user scrolls up to see the first entries
it should be able to handle colored text. I plan to use a simple highlighter (the log-data is actually real Mathematica syntax) on each arriving line to make reading more easy
it doesn't need to be writable. It's OK if the text pane is read-only.
Question: Does something like this already exist? Currently, LinkSnooper uses a JTextArea underneath and before I start do write my own version, I wanted to ask whether someone has already done this.
Edit:
What I planned to do was to use some Logger framework because it seems natural to me that those libraries should be able to handle a lot of data. Additionally, they often provide interfaces to format the messages and you can define different handlers that can take care of different messages. What I was hoping for was that someone already has combined this with a neatly working text window that can handle large output.
As Simon has pointed out I would suggest using JavaFX for this task.
If you "just" need to display large amounts of log data without advanced highlighting (sub-string range highlighting), ListView is the component for you.
It uses a virtualized layout container, so only the cells that are in the visible area of the viewport are actually rendered. This allows for lazy loading, cell recycling etc.
The ListView uses an ObservableList as its DataStructure. Similar to EMF EList, the ObservableListautomatically notifies the ListView on changes in its contained data.
There are several factory methods to create an ObservableList via FXCollections even allowing to wrap an existing List (e.g. RingBuffer).
If you need the advanced highlighting, RichTextFX is probably the solution to go for as it allows detailed styling of its contained text. RichTextFX uses a virtualized layout, too.
Edit #2
Tom has written about this in his blog: http://tomsondev.bestsolution.at/2014/12/27/displaying-and-editing-large-styled-texts/
Edit #1 ListView example
JavaFX does a very good job at separating the model from the view, so we try not to mix this up and need to create two things:
A data class (model)
A Cell renderer for that data class (view).
First the data class:
public class LogData {
private final String logMessage;
private List<String> highlightedFragments = null;
public LogData(String pLogMessage) {
logMessage = pLogMessage;
}
public String getLogMessage() {
return logMessage;
}
public List<String> getHighlightedFragments() {
if (highlightedFragments == null) {
doHighlight();
}
return highlightedFragments;
}
private void doHighlight() {
List<String> highlightedParts = Collections.emptyList(); // TODO lexer
highlightedFragments = highlightedParts;
}
}
The interesting part is, that the highlighting is done on demand not on initialization. Or in other words: The lexer only performs its work, when the cell renderer requests the data.
Now the Cell renderer:
ListView<LogData> listView = new ListView<>();
listView.setCellFactory(cb -> new LogDataCell(){});
public class LogDataCell extends ListCell<LogData>
{
#Override
protected void updateItem(LogData item, boolean empty) {
super.updateItem(item, empty);
if(empty || item == null) {
setText(null);
setGraphic(null);
}
else {
List<String> fragments = item.getHighlightedFragments();
if(fragments == null || fragments.isEmpty()) {
setText(item.getLogMessage());
setGraphic(null);
}
else {
TextFlow textFlow = null; //TODO
setText(null);
setGraphic(textFlow);
}
}
}
}
This is not a fully working example, there are several TODOs left, but hopefully you get the idea.
If you want to add search highlighting, I described a similar approach for the TableView control element here: JavaFX Table with highlighted text (Labels) with poor performance

Java: How can I "bundle" GUI elements into groups and listen to multiple groups cleanly?

I am not skilled in GUI design. After much thought, research and experimentation I've developed several design ideas but still none that seems efficient. One design has a Session god object register a listener on every UI element when created, and every object that cares about any action registers a listener on the Session object. This seems simple and robust, as all messaging goes through a central location so it's less likely that anything is lost. It's brute force though, and seems cumbersome and inefficient.
Another design attempts to create subgroups of objects that speak to each other. This avoids the huge top-level Session and seems more efficient, but also seems error prone.
I'm trying to implement a framework for reuse where I group buttons with related purposes into toolbars and have a hierarchical approach to listening for actions performed by toolbars with relevant operations to the listener. I've gotten to this so far:
public class EditorToolBar extends JToolBar {
public static enum Command {
ZOOMIN,
ZOOMOUT,
FINER,
COARSER,
RESET
}
private ButtonCommandListener listener = new ButtonCommandListener();
public EditorToolBar() {
super("Editor Commands");
JButton button;
for (final Command cmd : Command.values()) {
button = new JButton(cmd.toString());
button.setEnabled(true);
button.setToolTipText(cmd.toString() + " Command");
button.setActionCommand(cmd.toString());
button.addActionListener(listener);
add(button);
}
}
public void addActionListener(ActionListener pNewListener) {
listener.cActionNotifier.addListener(pNewListener);
}
private class ButtonCommandListener implements ActionListener {
private NotifierImp<ActionListener> cActionNotifier = new NotifierImp<ActionListener>();
public void actionPerformed(ActionEvent pEvent) {
for (ActionListener listener : cActionNotifier) {
listener.actionPerformed(pEvent);
}
}
}
} // class EditorTooBar
and the listeners implement something like this:
public void actionPerformed(ActionEvent pEvent) {
switch (EditorToolBar.Command.valueOf(pEvent.getActionCommand())) {
case ZOOMIN:
// do something
break;
case ZOOMOUT:
// do something
break;
case FINER:
// do something
break;
case COARSER:
// do something
break;
case RESET:
// do something
break;
default:
System.out.println("Unknown EditorToolBar Command: "+pEvent.getActionCommand());
return;
}
I can enhance the instructor for the enum to also include tooltip text, images, etc. I'd like to reuse this design with just a different enum describing other toolbars. Listeners will distinguish different button actions using ActionEvent.getActionCommand() and use Command.toValue(String). I'd like this to extend to a hierarchy of classes that are listening: a superclass may implement a listener for one type of toolbar, and subclass add to that by listening for a different toolbar type. If the event is not from the toolbar the subclass is interested in, it can forward the event to the superclass. To make this work, I need a way to distinguish between one toolbar and another, but preferably without having to check for every button event possible from that toolbar. Ideally I'd like to have a toolbar factory, and just specifying an enum would be enough to fully describe a toolbar. Not being able to subclass an enum adds to the challenge here.
Is this a promising design pattern to pursue? I've not seen it anywhere else yet. Is there a better way that I should be using rather than inventing something that is inferior? A link to other options would be welcome.
Edit: Based on the answer from yash ahuja I should clarify that when I mention hierarchy I mean similar to the way that key bindings are handled (i.e. do you have a binding? No, then does your container have a binding? ... until someone consumes the key event) not the actual class hierarchy.
As a way to encapsulate functionality, consider combining JToolBar, discussed in How to Use Tool Bars, with Action, discussed in How to Use Actions. The example cited here exports a single tool bar. In contrast, the StyledEditorKit, illustrated here, exports families of Action subtypes that apply to the current selection of a text component.
The design is pretty good but if you create a hierarchy of Tool bars then, in a situation where a particular button is clicked on particular tool bar the corresponding action performed for that button may not be accurate. Also at times multiple events can be triggered.
Also there are some tool bars for which it is difficult to identify that under which super class they should belong or if they are implementing features from multiple tool bars you need multiple inheritance which Java does not supports.
Possibly a combination of Strategy Pattern and Factory Pattern could solve these issues. Please rethink on this and design your solution, sorry I don't have exact design or source for your question , I have just put my thoughts for your solution.
Regards,
Yash

Is there a standard way to handle many different options for mouse events in java?

I'm developing a grid based sim game in java, and I was wondering if there is a standard way of doing the following.
I have a panel which is the game panel, and there are many different things which could happen when the panel is clicked. For example, when building a room, there are several stages, where dragging the mouse and left clicking will have different actions.
Right now, the way I have done it, is to use booleans to check what's being built, and then what stage it is at.
Is there any better or standard way of handling something like this? I had a quick google, but as I have said before, people on Stack Overflow always give a better, more relevant, up to date answer.
I consider myself still rather new to java.
Thanks in advance.
You might try looking into something similar to the strategy pattern.
Basically, you start by clicking the room button on your toolbar. The toolbar goes through and tells the grid to use the 'room place' actionlistener. Presumably removing any previous action listener that was listening
The room place actionlistener would in turn implement all the interesting bit of logic for left/right clicking, dragging, etc.
If you have multiple stages to building a room (say, placing doors, then windows, then trap doors); the action listeners would be responsible for handing control off to the next stage: a bit of a finite state machine.
So, start by clicking 'room' button, 'place room' listener is added. Drag out the area you want the room to be, 'place room' modifies the game state, then changes the actionlistener to the 'place windows' listener. Ad infinitum... until you finish.
One very simple (non compilable) example:
class GridPanel extends JPanel
{
void SetMouseListener(MouseListener newListener)
{
for(MouseListener ml : getMouseListeners())
removeMouseListener(ml);
addMouseListener(newListener);
}
}
class ControlPanel extends JPanel
{
GridPanel gameGrid;
void OnRectangleButtonClicked(some stuff)
{
gameGrid.SetMouseListener(new PlaceRoomListener(gameGrid));
}
}
class PlaceRoomListener extends MouseAdapter
{
GridPanel gameGrid;
//constructor, etc
void OnClick(mouse event)
{
gameGrid.doCoolStuff();
gameGrid.SetMouseListener(new PlaceTrapDoorListener());
}
}
//etc
Now, that non-compilable example aside, Pyrolistical does have a point: you generally don't want to combine your game model and graphic interface into one single glob of classes. You want the model separated from the GUI, and to manipulate it through a well defined interface.
(Also, there are probably better methods for going about removing the mouse listener then just randomly removing all listeners... I was in a bit of a rush, sorry)
It sounds like you need to define your game model/state and keep it separate from your mouse actions.
Are you using MVC?

Categories