Can't get GWT Popup panel glass effect to work - gwt

I have extended PopupPanel and am trying to get the glass/see through effect to work
Here is my class
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.*;
public class MyPopup extends PopupPanel
{
private static Label label = new Label();
public MyPopup()
{
super(true);
setWidget(label);
}
public static void showToast(String message, int time)
{
final MyPopup popup = new MyPopup();
label.getElement().setId("mypopupID");
popup.setGlassEnabled(true);
label.setText(message);
popup.show();
Timer timer = new Timer()
{
#Override
public void run()
{
popup.hide();
}
};
timer.schedule(time);
}
}
I just call showToast and this works as expected but looks like a plain old panel with what ever colour back ground I have declared in my CSS.
Here is my CSS
#mypopupID
{
background-color: yellow;
position:absolute;
left:130px;
top:50px;
width: 300px;
}
Any ideas how to get this to work? The dream is to get a fade in/out animation working but little steps first.

The "glass" effect of setGlassEnabled(true) does not apply to the popup itself, but to whathever is behind it. If you want the popup itself to be transparent, maybe you can try playing with the "opacity" css property.

Related

GWT PopupPanel just appearing once

I`m using GWT-Popup-Panel with the following code:
private static class MyPopup extends PopupPanel {
public MyPopup() {
// PopupPanel's constructor takes 'auto-hide' as its boolean parameter.
// If this is set, the panel closes itself automatically when the user
// clicks outside of it.
super(true);
// PopupPanel is a SimplePanel, so you have to set it's widget property to
// whatever you want its contents to be.
setWidget(new Label("Click outside of this popup to close it"));
}
}
public void onModuleLoad() {
final Button b1 = new Button("About");
b1.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
final MyPopup g = new MyPopup();
g.setWidget(RootPanel.get("rightagekeyPanel"));
g.setPopupPositionAndShow(new PopupPanel.PositionCallback() {
public void setPosition(int offsetWidth, int offsetHeight) {
g.setPopupPosition(b1.getAbsoluteLeft(), b1.getAbsoluteTop());
g.setAutoHideEnabled(true);
}
});
g.setVisible(true);
g.setWidth("500px");
g.setHeight("500px");
g.show();
}
});
It does appear when clicking Button b1, but not when clicking it the second time. What is wrong?
Make one popup, outside of your ClickHandler, at the same level as your Button. You also don't need that PositionCallback to center your popup. You can just call g.center() to show it and center it. It's a known issue on the GWT support pages that it won't center properly if you don't set a width to it. It will center properly if you give your popup a proper width.
The reason it doesn't show again is because you remove the widget inside RootPanel.get("rightagekeyPanel") and put it into your popup. It is no longer there the next time you try to do it.
A widget can only be in one place at a time, so if you remove it from its parent, keep track of it with a variable or something, so you can re-use it. Otherwise, you must re-instantiate the widget.
public void onModuleLoad() {
final Button b1 = new Button("About");
final MyPopup g = new MyPopup(); //create only one instance and reuse it.
g.setAutoHideEnabled(true);
g.setSize("500px", "500px"); //sets width AND height
b1.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
g.setWidget(RootPanel.get("rightagekeyPanel"));//DON'T DO THIS.
g.center();//will show it and center it.
}
});
}
Just say in my case I had to add some widget to make the PopUpPanel appear. Try using a label to make sure the Popup is showing.
PopupPanel popup = new PopupPanel();
popup.setVisible(true);
popup.center();
popup.show();
popup.setWidth("500px");
popup.setHeight("500px");
popup.add(new Label("Test"));

How to hide scrollbars in the JavaFX WebView

I'm trying to remove the scrollbars in a javafx webview.
Search on forums, the suggestion is to make them invisible as follows:
browser.getChildrenUnmodifiable().addListener(new ListChangeListener<Node>() {
#Override public void onChanged(Change<? extends Node> change) {
Set<Node> deadSeaScrolls = browser.lookupAll(".scroll-bar");
for (Node scroll : deadSeaScrolls) {
scroll.setVisible(false);
}
}
})
However, I receive the following error:
"trait ListChangeListener is abstract; cannot be instantiated"
I can understand why its failing, but then again, why are people using this code with success? I'm using Eclipse and the code is surrounded in Scala code.
Thanks!
S
I wrote the scroll bar hiding code you refer to and posted it to a forum.
I tried it again using WinXPsp3, JavaFX 2.2b13, JDK7u6b14ea and it still works for me.
I have never tried accessing the code from Scala, so you may have run into some Java<->Scala interoperability issue. Java does not have traits, so the error you receive would appear Scala related. I added a Scala tag to your question, so maybe somebody with Scala expertise could help.
Here is a short, compilable test application I used to recheck the functionality.
import java.util.Set;
import javafx.application.Application;
import javafx.collections.ListChangeListener;
import javafx.collections.ListChangeListener.Change;
import javafx.scene.*;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
// demos showing a webview which does not visibly display scrollbars.
public class NoScrollWebView extends Application {
public static void main(String[] args) { launch(args); }
#Override public void start(Stage primaryStage) {
// show a doc in webview.
final WebView webView = new WebView();
webView.getEngine().load("http://docs.oracle.com/javafx/2/get_started/jfxpub-get_started.htm");
primaryStage.setScene(new Scene(webView));
primaryStage.show();
// hide webview scrollbars whenever they appear.
webView.getChildrenUnmodifiable().addListener(new ListChangeListener<Node>() {
#Override public void onChanged(Change<? extends Node> change) {
Set<Node> deadSeaScrolls = webView.lookupAll(".scroll-bar");
for (Node scroll : deadSeaScrolls) {
scroll.setVisible(false);
}
}
});
}
}
The best solution here, would probably be to provide a new WebView control skin which does not not have any controls in it - but that would likely be difficult until the WebView control is open sourced.
The simplest way to do this is to provide a NoOp Skin for .scroll-bar components in your scene CSS file.
So, in the CSS enter something like:
.scroll-bar {
-fx-skin: "org.acme.visual.NoOpScrollbarSkin";
}
and subclass SkinBase class:
public class NoOpScrollbarSkin extends SkinBase<ScrollBar,ScrollBarBehavior> {
public NoOpScrollbarSkin(ScrollBar scrollBar, ScrollBarBehavior scrollBarBehavior) {
super(scrollBar, scrollBarBehavior);
}
public NoOpScrollbarSkin(ScrollBar scrollBar) {
super(scrollBar, new ScrollBarBehavior(scrollBar));
}
}
EDIT: this example doesn't appear to work for WebView because of a cast to com.sun.javafx.scene.control.skin.ScrollBarSkin. Solution is not better than previous checking for node changes, one has to subclass ScrollBarSkin to override behavior.
When setting up your WebView add this code:
engine.getLoadWorker().stateProperty().addListener(new ChangeListener<State>()
{
public void changed(ObservableValue<? extends State> o, State old, final State state)
{
if (state == State.RUNNING || state == State.SUCCEEDED)
{
// System.out.println("Page: " + state + ": " + engine.getLocation());
engine.executeScript("document.body.style.overflow = 'hidden';");
}
}
});
This code will remove the scrollbars of any web-page that is loaded in the WebView.
Unfortunately while the page is loading there might be a scrollbar for a short moment (if the webpage specified one in its markup).
I was able to remove the scrollbars by adding the following
css block to my global html stylesheet
body {
overflow-x: hidden;
overflow-y: hidden;
}
In JavaFx put newCascadeStyleSheet.css in resource folder :
body {
overflow-x: hidden;
overflow-y: hidden;
}
And then in Webview :
webView.getEngine().setUserStyleSheetLocation(getClass().getResource("/newCascadeStyleSheet.css").toExternalForm());
Thats All.

How to auto scroll GWT SuggestBox with max-height and overflow-y: scroll?

How can I auto scroll the GWT SuggestBox with max-height set on the PopupPanel holding the SuggestBox? Currently when the user presses keyboard up keys and down keys styles changes on the suggested items and pressing enter will select the currently selected item on the list.
When the item is located in lower than the max-height scroll bars doesn't scroll.
I tried extending the SuggestBox and inner class DefaultSuggestionDisplay to override moveSelectionDown() and moveSelectionUp() to explicitly call popup.setScrollTop().
In order to do this I need access to the absolute top of the currently selected MenuItem therefore need access to SuggestionMenu which is also an inner class of SuggestBox which is private and declared as a private member within DefaultSuggestionDisplay without getter. Since GWT is a JavaScript we can't use reflection to access it.... Does anyone have a workaround for this issue?
Thanks.
I've been searching around and couldn't find a proper solution (apart from reimplementing SuggestBox). The following avoids reimplementing SuggestBox:
private static class ScrollableDefaultSuggestionDisplay extends SuggestBox.DefaultSuggestionDisplay {
private Widget suggestionMenu;
#Override
protected Widget decorateSuggestionList(Widget suggestionList) {
suggestionMenu = suggestionList;
return suggestionList;
}
#Override
protected void moveSelectionDown() {
super.moveSelectionDown();
scrollSelectedItemIntoView();
}
#Override
protected void moveSelectionUp() {
super.moveSelectionUp();
scrollSelectedItemIntoView();
}
private void scrollSelectedItemIntoView() {
// DIV TABLE TBODY TR's
NodeList<Node> trList = suggestionMenu.getElement().getChild(1).getChild(0).getChildNodes();
for (int trIndex = 0; trIndex < trList.getLength(); ++trIndex) {
Element trElement = (Element)trList.getItem(trIndex);
if (((Element)trElement.getChild(0)).getClassName().contains("selected")) {
trElement.scrollIntoView();
break;
}
}
}
}
Following this discussion on Google groups, I implemented a similar solution which is a bit more concise due to the use of JSNI:
private class ScrollableDefaultSuggestionDisplay extends DefaultSuggestionDisplay {
#Override
protected void moveSelectionDown() {
super.moveSelectionDown();
scrollSelectedItemIntoView();
}
#Override
protected void moveSelectionUp() {
super.moveSelectionUp();
scrollSelectedItemIntoView();
}
private void scrollSelectedItemIntoView() {
getSelectedMenuItem().getElement().scrollIntoView();
}
private native MenuItem getSelectedMenuItem() /*-{
var menu = this.#com.google.gwt.user.client.ui.SuggestBox.DefaultSuggestionDisplay::suggestionMenu;
return menu.#com.google.gwt.user.client.ui.MenuBar::selectedItem;
}-*/;
}
Ok, I finally found the solution. I had to create my own suggest box based on GWT SuggestBox implementations. But follow below in custom implementaion:
-Place ScrollPanel to PopupPanel then place MenuBar to ScrollPanel
-In moveSelectionUp() and moveSelectionDown() of your new internal SuggestionDisplat implementation add the code below:
panel.ensureVisible( menu.getSelectedItem( ) );
This is not achievable by extending the SuggestBox since we won't have access to selected
MenuItem unless overriding protected getSelectionItem() method as public method.
Finally add CSS:
max-height: 250px;
To the popupPanel in your display implementations.

DialogBox in GWT isn't draggable or centred

I'm new to GWT programming. So far I have a DialogBox which is supposed to collect a login and a password, which can if required launch another DialogBox that allows someone to create a new account.
The first of these two DialogBoxes always appears at the top left of the browser screen, and can't be dragged, although part of the definition of a DialogBox is that it can be dragged. However, the second DialogBox can be dragged about the screen without any problem.
What I'd really like is for the first DialogBox to appear in the middle of the screen & be draggable, both of which I thought would happen automatically, but there's not.
So, what things can stop a DialogBox from being draggable? There is nothing on the RootPanel yet. Does that make a difference?
Code fragments available if they help, but perhaps this general outline is enough for some pointers.
Thanks
Neil
Use dialogBox.center() This will center your DialogBox in the middle of the screen. Normally a DialogBox is by default draggable.
Just tried it out and it doens't matter if your RootPanel is empty our not. When I just show the DialogBox on ModuleLoad it is draggable and it is centered. Probably the problem is situated somewhere else.
This is the example of google itself:
public class DialogBoxExample implements EntryPoint, ClickListener {
private static class MyDialog extends DialogBox {
public MyDialog() {
// Set the dialog box's caption.
setText("My First Dialog");
// DialogBox is a SimplePanel, so you have to set its widget property to
// whatever you want its contents to be.
Button ok = new Button("OK");
ok.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
MyDialog.this.hide();
}
});
setWidget(ok);
}
}
public void onModuleLoad() {
Button b = new Button("Click me");
b.addClickListener(this);
RootPanel.get().add(b);
}
public void onClick(Widget sender) {
// Instantiate the dialog box and show it.
new MyDialog().show();
}
}
Here more information about the DialogBox.
Without seeing any of your code it's hard to tell what's going wrong. The following code works for me (ignore the missing styling...):
public void onModuleLoad() {
FlowPanel login = new FlowPanel();
Button create = new Button("create");
login.add(new TextBox());
login.add(new TextBox());
login.add(create);
create.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
final DialogBox box = new DialogBox();
FlowPanel panel = new FlowPanel();
Button close = new Button("close");
close.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
box.hide();
}
});
panel.add(new Label("some content"));
panel.add(close);
box.setWidget(panel);
box.center();
}
});
DialogBox firstBox = new DialogBox(false, true);
firstBox.setWidget(login);
firstBox.center();
}
Both boxes are draggable and shown in the center of your browser window.
Looks like you're overriding this method in Widget:
public void fireEvent(GwtEvent<?> event) {
if (handlerManager != null) {
handlerManager.fireEvent(event);
}
}
In Widget, handlerManager refers to a private HandlerManager.
Either add super.fireEvent(event) to your method or as you have done rename it.
Well, with vast amounts of trial and error I have found the problem, which was just this: I had a method in an object I'd based on DialogBox called fireEvent, which looked like this:
public void fireEvent(GwtEvent<?> event)
{
handlerManager.fireEvent(event);
}
Then, when a button was clicked on the DialogBox, an event would be created and sent off to the handlerManager to be fired properly.
And it turns out that if I change it to this (LoginEvent is a custom-built event):
public void fireEvent(LoginEvent event)
{
handlerManager.fireEvent(event);
}
... or to this ....
public void fireAnEvent(GwtEvent<?> event)
{
handlerManager.fireEvent(event);
}
the DialogBox is draggable. However, if the method begins with the line
public void fireEvent(GwtEvent<?> event)
then the result is a DialogBox which can't be dragged.
I'm a bit unsettled by this, because I can't fathom a reason why my choice of name of a method should affect the draggability of a DialogBox, or why using a base class (GwtEvent) instead of a custom class that extends it should affect the draggability. And I suspect there are dozens of similar pitfalls for a naive novice like me.
(Expecting the DialogBox to centre itself was simply my mistake.)

Tooltips for GWT tree: adding mouseovers to nodes

I'm trying to add tooltips for the nodes of a Tree in GWT. As such, I'd like to add a mouseover listener for the nodes of a tree rather than on the tree itself.
The Treelistener interface seems to be what I want but this is now deprecated in lieu of the handler system. I don't quite understand how to get mouseover behaviour on the cell as I only seem to be able to add a MouseOverHandler to the tree itself.
Any help would be appreciated, thank you.
I'm going to stick my neck out a bit here since I haven't actually used a Tree in GWT yet, but I see that the TreeItem class is a subclass of UIObject. Any UIObject can have its setTitle() method called. Under the hood, this method sets the standard HTML title attribute to be whatever string you pass into setTitle().
This should give you the tooltip behavior you seek. As an added bonus, the browser does all of the mouse event handling for you:
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Tree;
import com.google.gwt.user.client.ui.TreeItem;
public class TreeTest extends Composite {
public TreeTest() {
Tree root = new Tree();
initWidget(root);
TreeItem dogs = new TreeItem("canines");
dogs.addItem("Fido").setTitle("faithful");
dogs.addItem("Lassie").setTitle("starlet");
dogs.addItem("Touser").setTitle("ruthless killer");
root.addItem(dogs);
TreeItem cats = new TreeItem("felines");
cats.addItem("Boots").setTitle("needy");
cats.addItem("Fabio").setTitle("aloof");
cats.addItem("Mandu").setTitle("bob seger");
root.addItem(cats);
}
}
Edit: Now let's imagine that you don't want to use the browser's built-in tool-tip mechanism described above, and that you would like to handle the mouse events yourself.
TreeItem might look, on the surface, as a non-starter. After all, it inherits directly from UIObject and not from Widget. (The key difference that a Widget adds to UIObject is, after all, the ability to handle events. So one would think that we cannot add handlers to the TreeItem!)
While this is strictly true, notice that TreeItem gives us the following constructor:
public TreeItem(Widget widget)
When we make each instance, then, we can pass a real Widget into it (such as a Label, perhaps, or maybe your own class MyWidget extends Composite) and we can add event handlers directly to that:
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.dom.client.MouseOverHandler;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Tree;
import com.google.gwt.user.client.ui.TreeItem;
public class AnotherTreeTest extends Composite {
public AnotherTreeTest() {
Tree root = new Tree();
initWidget(root);
TreeItem dogs = new TreeItem("canines");
makeItem(dogs,"Fido","faithful");
makeItem(dogs,"Lassie","starlet");
makeItem(dogs,"Touser","ruthless killer");
root.addItem(dogs);
TreeItem cats = new TreeItem("felines");
makeItem(cats,"Boots","needy");
makeItem(cats,"Fabio","aloof");
makeItem(cats,"Mandu","bob seger");
root.addItem(cats);
}
private void makeItem(TreeItem parent, String name, final String tip) {
Label label = new Label(name);
TreeItem animal = new TreeItem(label);
label.addMouseOverHandler(new MouseOverHandler() {
#Override
public void onMouseOver(MouseOverEvent event) {
GWT.log("mouse over " + tip); // do something better here
}
});
label.addMouseOutHandler(new MouseOutHandler() {
#Override
public void onMouseOut(MouseOutEvent event) {
GWT.log("mouse out " + tip); // do something better here
}
});
parent.addItem(animal);
}
}
Note that there may be other ways to accomplish this that are less expensive. If you have an enormous tree, then creating a Widget for each node can get expensive. Then you might want to explore a more sophisticated way of dealing with your mouse events, perhaps by having one handler that checks to see which element it is in.
A TreeItem can contains a Widget object. So add a MouseOverHandler and a MouseOutHandler on a widget (i.e. a Label) and put the widget inside the TreeItem to add :
Label myItemContent = new Label("My content");
myItemContent.addMouseOverHandler(new MouseOverHandler() {
public void onMouseOver(MouseOverEvent event) {
// construct and/or open your tooltip
}
});
myItemContent.addMouseOutHandler(new MouseOutHandler() {
public void onMouseOut(MouseOutEvent event) {
// close your tooltip
}
});
//put your Label inside a TreeItem
TreeItem myItem = new TreeItem(myItemContent);
// let's assume that parentNode is an ItemTree
parentNode.addItem(myItem);
An other solution can be to use GwtQuery. GwtQuery allows to bind event handler to any DOM element :
import static com.google.gwt.query.client.GQuery.$;
...
TreeItem myItem = new TreeItem("My content");
$(myItem.getElement()).hover(new Function() {
//method called on mouse over
public void f(Element e) {
// construct and/or open your tooltip
}
}, new Function() {
//method called on mouse out
public void f(Element e) {
//close your tooltip
}
});
parentNode.addItem(myItem);
Julien
An alternative way that I settled upon is to make use of CSS.
/**
* #return a label with a CSS controlled popup
*/
public static Widget labelWithHTMLPopup(String text, String description)
{
FlowPanel p = new FlowPanel();
p.addStyleName("tooltipLabel");
p.add(new Label(text));
HTML contents = new HTML(description);
contents.setStyleName("tooltip");
p.add(contents);
return p;
}
With accompanying css:
/*************** Tooltip **************/
div.tooltip
{
display: none;
position: absolute;
border: 1px outset black;
left: 90%;
top: -20px;
background: white;
padding: 5px;
box-shadow: 3px 3px 2px 0px #555;
overflow-y: auto;
max-height: 150px;
font-size: 80%;
z-index: 99;
}
div.tooltipLabel
{
position: relative;
}
div.tooltipLabel:hover div.tooltip
{
display: block;
position: absolute;
}
Of course, you can change the style, add fades etc as you like.
Less javas/javascript and more css.