GWT - refresh button/history/previous UI - java

I am just wondering...
When I click refresh button my gwt app comes to its default UI state despite its UI was modified during client-server interactions (callbacks) etc... But sometimes it is really essential thing to "cache" UI if user clicks refresh by mistake or reopened web page which user still logged-in;
So my question is...
Is there a way to restore gwt app UI (its before-refreshed state) in some standard way? Can History tokens help for this kind of issue?
edit
Concerning the history tokens I saw this example :
History.addValueChangeHandler(new ValueChangeHandler<String>() {
public void onValueChange(ValueChangeEvent<String> event) {
String historyToken = event.getValue();
// Parse the history token
try {
if (historyToken.substring(0, 4).equals("page")) {
String tabIndexToken = historyToken.substring(4, 5);
int tabIndex = Integer.parseInt(tabIndexToken);
// Select the specified tab panel
tabPanel.selectTab(tabIndex);
} else {
tabPanel.selectTab(0);
}
} catch (IndexOutOfBoundsException e) {
tabPanel.selectTab(0);
}
}
});
... and I could notice it restores tabIndex from history; so will it help if tab panel won't be init-ed by module load (by default) but something this way:
//on button click...
getSimplePanel().setWidget(new MyTabbedPane());
edit
To be more clear here is my test code which I am trying to figure out how to restore MainUI I mean its previous UI state as if refresh button wasn't clicked.
the EntryPoint...
public class Main implements EntryPoint {
private SimplePanel simplePanel;
public void onModuleLoad() {
RootPanel rootPanel = RootPanel.get();
FlowPanel flowPanel = new FlowPanel();
rootPanel.add(flowPanel, 10, 10);
flowPanel.setSize("410px", "280px");
Button setWidgetButton = new Button("Click");
setWidgetButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
getSimplePanel().setWidget(new MainUI());
}
});
flowPanel.add(setWidgetButton);
simplePanel = new SimplePanel();
flowPanel.add(simplePanel);
}
protected SimplePanel getSimplePanel() {
return simplePanel;
}
}
...and composite;
public class MainUI extends Composite {
private VerticalPanel verticalPanel;
int index;
public MainUI() {
FlowPanel flowPanel = new FlowPanel();
initWidget(flowPanel);
Button button = new Button("+");
button.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
getVerticalPanel().add(new Label(""+(++index)+": "+Math.random()));
}
});
flowPanel.add(button);
DecoratorPanel decoratorPanel = new DecoratorPanel();
flowPanel.add(decoratorPanel);
verticalPanel = new VerticalPanel();
decoratorPanel.setWidget(verticalPanel);
}
protected VerticalPanel getVerticalPanel() {
return verticalPanel;
}
}
...and, as a result, to have "cached" ui state without regenerating it again with extracting strings from history tokens and re-instantiate objects or what so ever...
for example if I have this UI (see image) I am interested to have totally the same one after refresh button is pressed...
but I am not pretty sure which way should I look for? I haven't seen any gwt snippet in this direction; So I really need your advice what way should I dig in?
Any useful comment is appreciated
Thanks
P.S. GWT 2.3

I think you miss to store the state into the URLs-Hashtag.
You can use GWTP (as suggested in the comments)
In fact you need to read the Hashtag in your onModuleLoad and restore your state.
This may work with getHash():
String state = Window.Location.getHash();
myRestoreStateFromTokenMethod(state);
update
Here are some snippets to create a push store.
List<String> states = [...]
public void onClick(){ states.add("newState");changeHash(states); }
public void changeHash(){
String hash = states.get(0) + ";"
for(other states) hash += states.get(i);
// use a UrlBuilder to set the Hash
}
Documentation for UrlBuilder
Or you can try this: https://github.com/jbarop/gwt-pushstate

Related

GWT Widget Event Handler is Not Working When The Widget Inserted into GWT DIV Element

I have a custom widget which is can accept a widget inside of it. Here is the code:
public class CustomDivWidget extends Widget {
protected Element divElement = DOM.createDiv();
public CustomDivWidget() {
divElement.getStyle().setWidth(100, Unit.PX);
divElement.getStyle().setHeight(100, Unit.PX);
divElement.getStyle().setBorderStyle(BorderStyle.SOLID);
divElement.getStyle().setBorderWidth(1, Unit.PX);
divElement.getStyle().setBorderColor("blue");
setElement(divElement);
}
public void add(Widget child) {
divElement.appendChild(child.getElement());
}
}
Then this is how I used it:
public void onModuleLoad() {
CustomDivWidget customDiv = new CustomDivWidget();
TextButton button = new TextButton("Button 1");
button.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
Window.alert("Button 1 clicked!");
}
});
customDiv.add(button);
RootPanel.get().add(customDiv);
}
When I run it, it show correctly the widget I want like this :
But the problem is, the click handler was not working when I tried to click the button. The questions are :
Why it is not working?
What should I do to make it working?
Any comments or suggestions will be appreciated. Thanks and regards.
I think you are bypassing GWT's event system this way (I'm not sure though). However, why not using a FlowPanel?
protected FlowPanel fp = new FlowPanel();
public CustomDivWidget() {
fp.getElement().getStyle().setWidth(100, Unit.PX);
fp.getElement().getStyle().setHeight(100, Unit.PX);
fp.getElement().getStyle().setBorderStyle(BorderStyle.SOLID);
fp.getElement().getStyle().setBorderWidth(1, Unit.PX);
fp.getElement().getStyle().setBorderColor("blue");
setElement(fp.getElement());
}
Apart from that, why are you using DOM elements instead of widgets? Using widgets instead of having to deal with the DOM is one of the key features of a toolkit like GWT (just my opinion here).
Edit : try to attach the handler directly to the DOM, to see if it makes any difference :
DOM.setEventListener(button.getElement(), new EventListener() {
#Override
public void onBrowserEvent(Event e) {
switch (DOM.eventGetType(e)) {
case Event.ONCLICK:
System.out.println("click");
break;
}
}
});

My internal frames don't earn focus after opening... (Java)

I have a menu with items that open internal frames, but every time I need to click twice in the frame. One time to give focus to the Int.frame and the second time to actually do something (give focus to a textfield).
So, here is my question: It's possible to automatic give focus to the Int.Frame?
Code of my main screen:
public final class principal extends javax.swing.JFrame {
viewCity city = new viewCity();
public principal() {
initComponents();
myListeners();
setLocationRelativeTo(null);
}
public void myListeners() {
menuCity.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
menuCityClicked(e);
}
});
}
public void central(JInternalFrame window1) {
int lDesk = panelPrincipal.getWidth();
int aDesk = panelPrincipal.getHeight();
int lIFrame = window1.getWidth();
int aIFrame = window1.getHeight();
window1.setLocation(lDesk / 2 - lIFrame / 2, aDesk / 2 - aIFrame / 2);
}
private void menuCityClicked(MouseEvent e) {
if (!city.isVisible()) {
panelPrincipal.add(city);
central(city);
city.requestFocus(); // Nothing
city.requestFocusInWindow(); // Nothing
city.setVisible(true);
city.requestFocus(); // Nothing
city.requestFocusInWindow(); // Nothing
}
}}
No matter what, the menu will always keep the focus. For example, click in your browser's menu, and you will keep the focus, by moving the cursor you will open other menus without need to click.
By putting the properties "selection model" to null works, but give me nullpointerexception.
Ok, the problem is with the jMenu, but with jMenuItem Works fine, so... I'm using

Java Swing: Focus issue

I'm making a level editor for my game. I have a property panel where I can modify the selected object its properties. I also have a Save button to write the level xml.
A field-edit is submitted(*) when the editor component lost the focus or Enter is pressed. This is working great, but the only problem is that when I have this sequence of actions:
Edit a field
Press the save button
Because, what happens is this:
I edit the field
I press the save button
The level is saved
The field lost the focus
The edit is submitted
As you can see, this is the wrong order. Of course I want the field to lose its focus, which causes the submit and then save the level.
Is there a trick, hack or workaround to make the field first lose the focus and then perform the action listener of the save button?
Thanks in advance.
(* submit = the edit to the field is also made in the object property)
EDIT: For the field I'm using a FocusAdapter with focusLost:
FocusAdapter focusAdapter = new FocusAdapter()
{
#Override
public void focusLost(FocusEvent e)
{
compProperties.setProperty(i, getColor());
record(); // For undo-redo mechanism
}
};
And for the button a simple ActionListener with actionPerformed`.
btnSave.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
// Save the level
}
});
Hmm ... can't reproduce: in the snippet below the lost is always notified before the actionPerfomed, independent on whether I click the button or use the mnemonic:
final JTextField field = new JTextField("some text to change");
FocusAdapter focus = new FocusAdapter() {
#Override
public void focusLost(FocusEvent e) {
LOG.info("lost: " + field.getText());
}
};
field.addFocusListener(focus);
Action save = new AbstractAction("save") {
#Override
public void actionPerformed(ActionEvent e) {
LOG.info("save: " + field.getText());
}
};
save.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_S);
JButton button = new JButton(save);
JComponent box = Box.createHorizontalBox();
box.add(field);
box.add(button);
On the other hand, focus is a tricky property to rely on, the ordering might be system-dependent (mine is win vista). Check how the snippet behave on yours.
If you see the same sequence as I do, the problem is somewhere else
if you get the save before the lost, try to wrap the the save action into invokeLater (which puts it at the end of the EventQueue, so it's executed after all pending events)
Action save = new AbstractAction("save") {
#Override
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
LOG.info("save: " + field.getText());
}
});
}
};
Normally, wrapping your save code into an SwingUtilities.invokeLater() should do the trick. As you already mentioned, this doesn't work? Try this:
private boolean editFocus = false;
FocusAdapter focusAdapter = new FocusAdapter()
{
#Override
public void focusGained(FocusEvent e){
editFocus = true;
}
#Override
public void focusLost(FocusEvent e){
compProperties.setProperty(i, getColor());
record(); // For undo-redo mechanism
editFocus = false;
if (saveRequested){
save();
}
}
};
and for your button:
private boolean saveRequested = false;
btnSave.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
if (editFocus){
saveRequested = true;
return;
} else {
save();
}
}
});
and then your save method:
private void save(){
// do your saving work
saveRequested = false;
}
This only works when your focusLost gets called after your button's action. If suddenly the order is correct, this code will get save() called twice.
But again, wrapping your save() code in your original approach should work, because the save code will execute after processing all events. That is after processing your button click and your focusLost events. Because your focusLost code executes immediately (it's not wrapped in an invokeLater()), the focusLost code should be executed always before your save code. This does not mean that the event order will be correct! But the code associated to the events will executed in the right order.

Get return value from new class with gui

I have a class that extends JFrame to make orders.
in the middle I have a button that opens a new window that is used to find an article.
What I need is:
When I click btnNewArticle, after searching new article, and confirm in new window, I will get as return article code.
Click btnNewArticle --> (open new window to find an article) --> confirm selection -->as return I get Article Code.
Is it possible?
Thanks
Have a look at Java dialogs: How to Make Dialogs.
In the above tutorial, they explain how to do custom dialogs such as the one below:
(source: oracle.com)
They handle return-values by giving the child-dialog a reference to it's parent dialog, in which it fills in the relevant values upon closing.
For me this principle has worked:
public class ArticleSearchDialog extends JDialog {
public static ArticleId execute(Frame parent) {
ArticleSearchDialog dialog = new ArticleSearchDialog(parent, true);
dialog.setVisible(true);
return dialog.getSelectedArticle();
}
private ArticleId getSelectedArticle() {
return selectedArticle;
}
private void jbCancelActionPerformed(ActionEvent evt) {
selectedArticle = null;
setVisible(false);
dispose();
}
private void jbOkActionPerformed(ActionEvent evt) {
selectedArticle = ...; //TODO
setVisible(false);
dispose();
}
// All the rest of the dialog code.
}
Then the call gets really easy:
ArticleId articleId = ArticleSearchDialog.execute(this);
if (articleId != null) {
//TODO
}

How to show another page on button click in blackberry using java

I don't know how to show another page on button click in blackberry using java.
I assume you have a ButtonField added to some kind of Screen. You need to set the FieldChangeListener for the ButtonField:
class YourScreen extends FullScreen {
public YourScreen() {
super();
ButtonField btn = new ButtonField("mybutton");
btn.setChangeListener(new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
synchronized (UiApplication.getApplication().getEventLock()) {
UiApplication.getUiApplication().pushScreen(new FullScreen());
}
}
});
add(btn);
}
}
Also note that you need to either get the event lock before pushing the screen or pass UiApplication.invokeLater a Runnable like so:
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
UiApplication.getUiApplication().pushScreen(new FullScreen());
}
});
Some basics on UI threading issue on BB here: http://www.thinkingblackberry.com/archives/182
UiApplication.getUiApplication.pushScreen(new Screen());
http://www.blackberry.com/developers/docs/4.5.0api/index.html

Categories

Resources