Im trying to make a History Handler in my Project so i have a Login "page" and messure "page"
#Override
public void onValueChange(ValueChangeEvent<String> event) {
// TODO Auto-generated method stub
String token = null;
String[] array1 = new String[3];
if (event.getValue()!=null) {
token = event.getValue().trim();
array1=token.split("&",2);
}
if ((token == null) || (token.equals(""))){
clearing();
RootPanel.get("de").add(login, 457, 168);
}
else if (array1[0].equals("messure")){
clearing();
login.init(array1[1].substring(0, 2));
}
else{
clearing();
RootPanel.get("de").add(login, 457, 168);
}
}
and here is the clearing:
private void clearing(){
RootPanel.get("en").clear();
RootPanel.get("de").clear();
}
The Browser refreshbutton works well but when i try to go back and forward i get this:
10:37:56.831 [ERROR] Uncaught exception escaped
com.google.gwt.event.shared.UmbrellaException: Exception caught: SimplePanel can only contain one child widget
its caused by a :
commentBox.add(box);
commentBox is public static...
do i have to change it to a get/set methode to get it work or how?
The exeception is telling you that you are adding more than one element into a SimplePanel
What is your commentBox ? Is it a simple panel ? Are you trying to add element more that once inside ?
You need to create a widget (for example, using a FlowPanel as a container for labels, text boxes, etc.), and then you add this widget to the DialogBox. DialogBox can only accept one widget as its body.
Related
I created the following class as an extension of gwtbootstrap3 Tooltip. There are at least 2 reasons why I want to derive the gwtbootstrap3 Tooltip class:
1.) Add a onWindowClosing Handler when the tooltip is shown so I can hide() the tooltip when the user leaves the page (this is - as far as I understand - a feature which is also not supported in Bootstrap, is it?)
2.) I want to prevent Tooltips from being shown when the page is displayed on iPads or iPhones as they behave strange when tooltips are involved (first tip shows the tooltip , the second tip executes the button, which is not exactly what the user expects)
Please note that the class given below is still not finished ... but already at this stage I get an exception when adding a handler.
Please also note that it throws an exception no matter what type of Handler (ShowHandler, ShownHandler, etc.) I add.
Any help greatly appreciated.
package com.mypackage.client.widgets.featureWidgets;
import org.gwtbootstrap3.client.shared.event.ShowEvent;
import org.gwtbootstrap3.client.shared.event.ShowHandler;
import org.gwtbootstrap3.client.ui.constants.Trigger;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.Window.ClosingEvent;
public class Tooltip extends org.gwtbootstrap3.client.ui.Tooltip {
private boolean isMobile;
private HandlerRegistration windowClosingHandlerRegistration;
private final Tooltip tooltip;
public Tooltip() {
super();
tooltip = this;
this.addShowHandler(new ShowHandler() {
#Override
public void onShow(final ShowEvent showEvent) {
// TODO Auto-generated method stub
if (windowClosingHandlerRegistration == null) {
windowClosingHandlerRegistration = Window.addWindowClosingHandler(new Window.ClosingHandler() {
#Override
public void onWindowClosing(final ClosingEvent arg0) {
tooltip.hide();
}
});
}
}
});
}
}
When I create a instance of this tooltip using the following:
[...]
<b:ButtonToolBar ui:field="itemButtonToolBar" addStyleNames="hiddenPrint">
<b:ButtonGroup>
<a:Tooltip title="{msgs.buttomTitleAddItem}" container="body">
<b:Button ui:field="addItemButton" icon="PLUS"/>
</a:Tooltip>
[...]
I get the following exception when trying to add the Handler, why?
SEVERE: (TypeError) : Cannot read property 'addHandler_11_g$' of undefinedcom.google.gwt.core.client.JavaScriptException: (TypeError) : Cannot read property 'addHandler_11_g$' of undefined
at Unknown.addShowHandler_2_g$(meetingApp-0.js#26:57195)
at Unknown.Tooltip_6_g$(meetingApp-0.js#8:57685)
at Unknown.build_f_Tooltip2_0_g$(meetingApp-0.js#55:31606)
at Unknown.get_f_Tooltip2_0_g$(meetingApp-0.js#15:31831)
at Unknown.build_f_ButtonGroup1_0_g$(meetingApp-0.js#38:31524)
at Unknown.get_f_ButtonGroup1_0_g$(meetingApp-0.js#15:31791)
at Unknown.build_itemButtonToolBar_0_g$(meetingApp-0.js#41:31696)
at Unknown.get_itemButtonToolBar_0_g$(meetingApp-0.js#15:31876)
at Unknown.createAndBindUi_58_g$(meetingApp-0.js#91:31437)
at Unknown.createAndBindUi_59_g$(meetingApp-0.js#15:31441)
at Unknown.ItemButtonGroup_2_g$(meetingApp-0.js#56:30733)
at Unknown.$init_589_g$(meetingApp-0.js#31:37722)
at Unknown.SummaryWidget_1_g$(meetingApp-0.js#8:37686)
at Unknown.loadSummaryWidget_0_g$(meetingApp-0.js#26:4991)
at Unknown.setSummary_1_g$(meetingApp-0.js#10:5028)
at Unknown.onSuccess_8_g$(meetingApp-0.js#21:3312)
at Unknown.onSuccess_9_g$(meetingApp-0.js#8:3317)
at Unknown.onResponseReceived_0_g$(meetingApp-0.js#26:156917)
at Unknown.fireOnResponseReceived_0_g$(meetingApp-0.js#17:129224)
at Unknown.onReadyStateChange_0_g$(meetingApp-0.js#28:129532)
at Unknown.<anonymous>(meetingApp-0.js#18:172082)
at Unknown.apply_0_g$(meetingApp-0.js#28:104636)
at Unknown.entry0_0_g$(meetingApp-0.js#16:104692)
at Unknown.<anonymous>(meetingApp-0.js#14:104672)
Disclaimer: I use gwtbootstrap3 v0.9.2 and I believe it's the same version as you use as I got the same error for your code.
A Tooltip needs a Widget to operate on (in your case the Button is a Tooltip's widget). Tooltip uses it's widget to do all events handling - see source code for addShowHandler for example.
Now you need to understand how the whole structure is built:
first the Tooltip is created (wit no widget set)
then the Button is created
Tooltip's setWidget method is called to set the button as a widget
So when you use addShowHandler method in your constructor, you actually call widget.addHandler while widget is null.
You can check it by Window.alert(tooltip.getWidget() == null ? "null" : tooltip.getWidget().toString());
There are few ways to make it work (the later the better):
wait for DOM structure to be built by scheduling a deferred command (if you are sure that the widget will be eventually set):
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
#Override
public void execute() {
// set up events handling
}
});
override setWidget method (note thet there are two methods: setWidget(Widget w) and setWidget(IsWidget w)):
#Override
public void setWidget(Widget w) {
super.setWidget(w);
// set up events handling
}
you don't need to addWindowClosingHandler in the showEvent handler, you can do it directly in the constructor:
public class Tooltip extends org.gwtbootstrap3.client.ui.Tooltip {
private boolean isMobile;
private final Tooltip tooltip;
public Tooltip() {
super();
tooltip = this;
Window.addWindowClosingHandler(new Window.ClosingHandler() {
#Override
public void onWindowClosing(final ClosingEvent arg0) {
tooltip.hide();
}
});
}
}
I am performing the following action in GWT
public class FooPanel extends SimplePanel {
private String url;
public FooPanel () {
super(DOM.createAnchor());
Button button = new Button();
button.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
foo();
}
});
add(button);
}
}
however when I run the code I get the following error
SimplePanel can only contain one child widget
However Button is a single widget so I am not sure what the problem is? The problem doesn't occur if i don't add the button
Remove this line:
super(DOM.createAnchor());
You don't need it.
You can simply use your Button in your code, or extend a Button widget. Adding a Button to a SimplePanel does not offer any benefits.
Have a look at source code of SimplePanel#add() to analyze this error.
#Override
public void add(Widget w) {
// Can't add() more than one widget to a SimplePanel.
if (getWidget() != null) {
throw new IllegalStateException("SimplePanel can only contain one child widget");
}
setWidget(w);
}
Now its clear from the source code that you have already added a widget in SimplePanel.
Call SimplePanel#getWidget() to get the already added widget.
Look at the source code of default constructor if SimplePanel class. It might help you to understand that how SimplePanel enclose the widget inside it.
/**
* Creates an empty panel that uses a DIV for its contents.
*/
public SimplePanel() {
this(DOM.createDiv());
}
Try with setWidget(button); instead of add(button);
I have onClick event on somePanel. And I click on it and it works. But.. How to retrieve real click target? When I click on panel which is inside od somePanel it show me that I click on somePanel..
I know we have this:
Element e = Element.as( event.getNativeEvent().getEventTarget());
But i returns element - I want widget..
How to do this?
This is an old question, but both answers are wrong. If you are using a GWT EventListener and want the widget that is the source of the event, then you simply use the event.getSource() method of the event and cast it to the original object type.
Unless there is something that I am missing in the question here.
I would use the feature in gwtquery to get the widget associated with a given element: https://code.google.com/p/gwtquery/wiki/GettingStarted#Manipulating_your_widgets
Widget = $(e).widget();
The problem is that the element clicked couldn't be the element associated with the widget but a child. In this case you could use gquery selectors to traverse the dom until you get its parent widget based on some css property.
// Most gwt widgets contains a class .gwt- but this could fail
// so use a more accurate selector than the one in this example
Widget = $(e).closest("[class*='.gwt-']")
If you wanted to do it by yourself, taking a look to the method getAssociatedWidget in GQuery gives you the solution:
EventListener listener = DOM.getEventListener(e);
// No listener attached to the element, so no widget exist for this element
if (listener == null) {
return null;
}
if (listener instanceof Widget) {
// GWT uses the widget as event listener
return (Widget) listener;
}
EDITED: here you have a working example:
import static com.google.gwt.query.client.GQuery.*;
// A panel with some widgets
Panel panel = new VerticalPanel();
final HTML widget1 = new HTML("<span>Foo</span> <span>Bar</span");
final HTML widget2 = new HTML("<span>Foo</span> <span>Bar</span");
final HTML widget3 = new HTML("<span>Foo</span> <span>Bar</span");
panel.add(widget1);
panel.add(widget2);
panel.add(widget3);
// we need to wrap our panel with a widget supporting click events
FocusPanel wrapper = new FocusPanel();
wrapper.add(panel);
RootPanel.get().add(wrapper);
wrapper.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
// The element is not the HTML widget clicked but the span element
Element e = event.getNativeEvent().getEventTarget().cast();
// Using gquery to get the closest widget to the clicked element
// We take advanrage of HTML widgets having gwt-HTML class
Widget w = $(e).closest(".gwt-HTML").widget();
if (w == widget1) {
Window.alert("Clicked on widget 1");
} else if (w == widget2) {
Window.alert("Clicked on widget 2");
} else if (w == widget3) {
Window.alert("Clicked on widget 3");
} else {
Window.alert("Clicked on a non GWT HTML widget");
}
}
});
An alternative approach, if you already know all of the widgets that you want to check against, would be to use the DOM.isOrHasChild(Element) or Element.isOrHasChild(Node).
For example:
public void onClick(ClickEvent event) {
Element targetElem = Element.as(event.getNativeEvent().getEventTarget());
Widget targetWidget = null;
if (widgetA.getElement().isOrHasChild(targetElem) {
targetWidget = widgetA;
}
else if (widgetB.getElement().isOrHasChild(targetElem) {
targetWidget = widgetA;
}
.....
if (targetWidget != null) {
// You found you widget - Yay!
}
else {
// No widget found - Bummer!
}
}
This approach only works if you know the widgets you are testing against up front. The benefit is that you now have an particular widget reference rather then a generic reference to 'some' widget that you might have to do additional checks against.
For example, you could have done the following if widgetA was a subclass of TextBox called MySpecialTextBox:
MySpecialTextBox widgetA;
if (widgetA.getElement().isOrHasChild(targetElem) {
widgetA.someSpecialMethod();
}
I have a gwt form which has about 70-100 widgets (textboxes,listboxes,custom widgets etc)
I am trying to implement the features of CUT ,COPY in this form .For this i have 2 buttons right on top of the form.
Now the problem i have is that when i click on the copy button , the widget that was focused in the form looses focus and i dont know which text to copy(or which widget was last focused before the focus getting to the copy button)
I was planning to implement blur handlers on all the widgets but i feel is a very laborious and not a good solution.
How can i get around this issue?
Thanks
Perhaps someone with a deeper insight might provide a better approach but I beleive adding blur handlers is perfectly valid. I do not quite see why you think it would be laborious, after all you don't need a different handler for each of your widgets, you can get away with only one(at most a couple for a variety of controls..), here is a very simple example,
public class CustomBlurHandler implements BlurHandler{
Object lastSource;
String text;
#Override
public void onBlur(BlurEvent event) {
if (event.getSource() instanceof TextBox) {
lastSource = event.getSource();
text = textBox.getSelectedText();
}
}
public Object getLastSource() {
return lastSource;
}
public String getText() {
return text;
}
}
and onModuleLoad :
public class Test implements EntryPoint {
CustomBlurHandler handler = new CustomBlurHandler();
public void onModuleLoad() {
TextBox text1 = new TextBox();
TextBox text2 = new TextBox();
text1.addBlurHandler(handler);
text2.addBlurHandler(handler);
Button b = new Button("Get last selected text");
b.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
Window.alert(handler.getLastSource()+ " " + handler.getText());
}
});
RootPanel.get().add(text1);
RootPanel.get().add(text2);
RootPanel.get().add(b);
}
}
I am having problems while adding my widget into the RootPanel of another container class. I think that it may be related to the Asynchronous call that I make during the creation of the widget. I have a main class named ImageView which implements EntryPoint. In this class, I am creating an instance of my widget named NewWidget by clicking on a button. However, I cannot display it with the traditional methods:
Here is the EntryPoint class (ImageView):
import com.mycompany.project.client.widgets.NewWidget;
public class ImageViewer implements EntryPoint {
public void onModuleLoad() {
Button b = new Button("Button");
RootPanel.get().add(b);
b.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
NewWidget w = new NewWidget();
RootPanel.get().add(w);
}
});
}
And here is my widget (NewWidget):
public class NewWidget extends Composite {
final static DataServiceAsync service = (DataServiceAsync) GWT.create(DataService.class);
final FlowPanel mainPanel = new FlowPanel();
public NewWidget() {
fillImagePath();
}
public void fillImagePath(){
ServiceDefTarget endpoint = (ServiceDefTarget) service;
endpoint.setServiceEntryPoint(GWT.getModuleBaseURL() + "data");
service.getAllDocuments(new AsyncCallback<ArrayList<String>>() {
#Override
public void onFailure(Throwable e) {
Window.alert("Server call failed.");
}
#Override
public void onSuccess(ArrayList<String> paths) {
process(paths);
}
});
}
public void process(ArrayList<String> paths){
ArrayList<String> imagePath = paths;
Image img = new Image(imagePath.get(4));
mainPanel.add(img);
initWidget(mainPanel);
}
}
In this NewWidget, I am making an asynchronous call to my server in order to receive a String ArrayList, which contains 10 Strings that refer to the file path of 10 different images (i.e, "images/01.jpg", "images/02.jpg", and so on). I am pretty sure that I successfully and correctly receive these image paths. I have arbitrarily chosen index number 4 to display in my NewWidget.
The problem is that I cannot display this NewWidget in my ImageView main panel. I can easily display other widgets with this method. With many attempts, I have realized that I can display the image if I add the line RootPanel.get().add(mainPanel) at the end of NewWidget. However, I do not want to make a call that refers to the parent container (RootPanel in ImageView). Why can't I display this image with only instantiating it in my container panel, like I can display any other widget? I am pretty sure that it is related to the Asynchronous call not getting completed before I attempt to add the widget. But I don't know how to fix this.
I would be very glad if people would share their ideas. Thanks.
Move the initWidget(mainPanel) call to the first line the constructor.