org.eclipse.swt.browser.Browser does not open in Eclipse RAP application - browser

Wonder if somebody can help me with this. I am trying to open an embedded browser in an Eclipse RAP applications. All examples I have seen look something like:
link.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent event) {
try {
Browser b = new Browser(parent, SWT.NONE);
b.setText("<html><body>This is Unicode HTML content from memory</body></html>");
} catch (SWTError e) {
// Error handling here
}
}
});
That doesn't do anything (visually) though. When I replace the Browser with ExternalBrowser like so:
link.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent event) {
try {
int browserStyle = ExternalBrowser.LOCATION_BAR;
ExternalBrowser.open( "myPage", "http://www.stackoverflow.com", browserStyle );
} catch (SWTError e) {
// Error handling here
}
}
});
It works. Although not exactly as desired.
I am using Eclipse RCP 1.4.2 on OS X 10.8.2.
Any insight is highly appreciated.

When you create a new widget, you have to trigger a re-layout to make it visible. Depending on your layout, it may be sufficient to call parent.layout(). If the parent is also contained in a layout and shrunken to its preferred size, you will have to call layout() on its parent. If unsure, layout the top-level shell.

Related

Downloads with JavaFX WebView

my web application offers a download. Javascript creats at the click the url (it depends on the user input) and the browser should open it, so that the page isn't reloaded.
For that, I think I have to alternatives:
// Alt1:
window.open(pathToFile);
// Alt2:
var downloadFrame = document.getElementById('downloads');
if (downloadFrame === null) {
downloadFrame = document.createElement('iframe');
downloadFrame.id = 'downloads';
downloadFrame.style.display = 'none';
document.body.appendChild(downloadFrame);
}
downloadFrame.src = pathToFile;
Both works under Firefox. Problem with open new window method: If the creation of the file at the server needs more time, the new empty tab will be closed late.
Problem with iframe: If there is an error at the server, no feedback is given.
I think at firefox the iframe is the better solution. But the web application must run with an JavaFX WebView, too. JavaFX haven't a download feature, I have to write it. One possible way is to listen on the location property:
final WebView webView = new WebView();
webView.getEngine().locationProperty().addListener(new ChangeListener<String>() {
#Override public void changed(ObservableValue<? extends String> observableValue, String oldLoc, String newLoc) {
if (newLoc.cotains("/download")) {
FileChooser chooser = new FileChooser();
chooser.setTitle("Save " + newLoc);
File saveFile = chooser.showSaveDialog(webView.getEngine().getScene().getWindow());
if (saveFile != null) {
BufferedInputStream is = null;
BufferedOutputStream os = null;
try {
is = new BufferedInputStream(new URL(newLoc).openStream());
os = new BufferedOutputStream(new FileOutputStream(saveFile));
while ((readBytes = is.read()) != -1) {
os.write(b);
}
} finally {
try { if (is != null) is.close(); } catch (IOException e) {}
try { if (os != null) os.close(); } catch (IOException e) {}
}
}
}
}
}
There are some problems:
The download start depends on a part of the url, because JafaFX supports no access to the http headers (that is bearable)
If the user starts the download with the same url two times, only the first download works (the change event only fires, if the url is new). I can crate unique urls (with #1, #2 and so on at the end). But this is ugly.
Only the "window.open(pathToFile);" method works. Loading an iframe don't fire the change location event of the website. That is expectable but I haven't found the right Listener.
Can someone help me to solve 2. or 3.?
Thank you!
PS: Sorry for my bad english.
edit:
For 2. I found a way. I don't know if it is a good one, if it is performant, if the new webview is deleted or is in the cache after download, ....
And the user don't get an feedback, when some a problem is raised:
webView.getEngine().setCreatePopupHandler(new Callback<PopupFeatures, WebEngine>() {
#Override public WebEngine call(PopupFeatures config) {
final WebView downloader = new WebView();
downloader.getEngine().locationProperty().addListener(/* The Listener from above */);
return downloader.getEngine();
}
}
I think you may just need to use copyURLtoFile to get the file...call that when the location changes or just call that using a registered java class. Something like this:
org.apache.commons.io.FileUtils.copyURLToFile(new URL(newLoc), new File(System.getProperty("user.home")+filename));
Using copyURLToFile the current page doesn't have to serve the file. I think registering the class is probably the easiest way to go... something like this:
PHP Code:
Download $filename
Java (in-line class in your javafx class/window... in this case my javafx window is inside of a jframe):
public class JavaApp {
JFrame cloudFrameREF;
JavaApp(JFrame cloudFrameREF)
{
this.cloudFrameREF = cloudFrameREF;
}
public void getfile(String filename) {
String newLoc = "http://your_web_site.com/send_file.php?filename=" + filename;
org.apache.commons.io.FileUtils.copyURLToFile(new URL(newLoc), new File(System.getProperty("user.home")+filename));
}
}
This part would go in the main javafx class:
Platform.runLater(new Runnable() {
#Override
public void run() {
browser2 = new WebView();
webEngine = browser2.getEngine();
appREF = new JavaApp(cloudFrame);
webEngine.getLoadWorker().stateProperty().addListener(
new ChangeListener<State>() {
#Override public void changed(ObservableValue ov, State oldState, State newState) {
if (newState == Worker.State.SUCCEEDED) {
JSObject win
= (JSObject) webEngine.executeScript("window");
// this next line registers the JavaApp class with the page... you can then call it from javascript using "app.method_name".
win.setMember("app", appREF);
}
}
});
You may not need the frame reference... I was hacking some of my own code to test this out and the ref was useful for other things...

Codenameone Webbrowser issue

I am trying to display a webpage from codenameone application. It works fine in Iphone but not in andriod mobile.
public void showLoginForm()
{
final Form loginForm = new Form("Login");
loginForm.setUIID("Form1");
loginForm.setLayout(new BorderLayout());
loginForm.setScrollable(false);
try
{
WebBrowser browser = new WebBrowser()
{
//Overrides onStart and onLoad methods to load progress bars for page transitions.
};
browser.setURL(appsGlobalSettings.get(URL_KEY));
loginForm.addComponent(BorderLayout.CENTER,browser);
loginForm.show();
}
catch(Exception e)
{
e.printStackTrace();
}
}
Check your URL. I suggest removing the override code and placing Google.com hardcoded as a URL and proceeding from there. Since it doesn't work in the simulator either make sure you are using Java 7 with JavaFX enabled, with that case it should show a browser and should work for a proper web address.
Shai...It took some time to collect device logs.
But even that is intriguing.
I tried in two ways
No overridden methods in WebBrowser class and http://www.google.co.in as URL.
public void showLoginForm()
{
InfiniteProgress inf = new InfiniteProgress();
Dialog progress = inf.showInifiniteBlocking();
final Form loginForm = new Form("Login");
loginForm.setUIID("Form1");
loginForm.setLayout(new BorderLayout());
try
{
//Log.p("Inside showLoginForm method");
WebBrowser browser = new WebBrowser()
{
};
//browser.setURL(appsGlobalSettings.get(URL_KEY));
browser.setURL("http://www.google.co.in");
//Log.p("Set Broswer url");
loginForm.addComponent(BorderLayout.CENTER,browser);
//Log.sendLog();
loginForm.show();
}
catch(Exception e)
{
e.printStackTrace();
//Log.p(e.toString());
}
}
Result - the same blank screen.
Same code with added Log.p and Log.send() statements.
Result - it works fine
Is this due to some race condition?

Hover effect over icon

I would like to create buttons like these for settings panel navigation:
Can you tell me how I can create this hover effect over the icons? The most difficult part for me is to create CSS code which looks like the the picture.
Although the above answer works. You should really do this completely in CSS using pseudo-selectors:
java:
btnsa.getStyleClass().add("myButton");
css:
.myButton {
-fx-background-color:transparent;
}
.myButton:hover {
-fx-background-color:#dae7f3;
}
You have to use MouseEntered and MouseExited events for getting hover effects over the icons.
try this its working.........
btnsa.setStyle("-fx-background-color:transparent;");
btnsa.setGraphic(new ImageView(new Image(getClass().getResourceAsStream("JavafxSm.gif"))));
btnsa.setOnMouseEntered(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent t) {
btnsa.setStyle("-fx-background-color:#dae7f3;");
}
});
btnsa.setOnMouseExited(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent t) {
btnsa.setStyle("-fx-background-color:transparent;");
}
});
some snap shots of above code......
Instead, you can do just 1 line code in CSS, if your FXML file connected with CSS
yourButtonId:hover{-fx-background-color: #6695e2}

Java Swing - mouse pointer "shifted" on context menu when JFrame is maximized

I encoutered a strange behaviour of handling mouse position by Swing when maximizing JFrame:
When I execute this very simple code...
public class Test {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
JMenuBar menubar = new JMenuBar();
JMenu menu = new JMenu("File");
menu.add(new JMenuItem("New"));
menubar.add(menu);
frame.setJMenuBar(menubar);
frame.setSize(200, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
... I can normally click File (first click - press,release) -> New (second click). But when I maximize JFrame and click on File - context menu disappears on mouse release immediately.
Moreover when I hold mouse button - to prevent disappearance - I must move my mouse much further to focus on New item.
The red dot represents area (more or less) where I must move my mouse to focus on New after pressing File and holding mouse button.
I've observed the same behaviour when using "right-click context menu" for example when right clicking on chart from JFreeChart.
I thought it was JDK problem because I used Oracle's JDK, but after installing OpenJDK I have the same results.
Did somebody observe this strange behaviour? Or am I missing something obvious?
I use:
1.7.0_147-icedtea (or 1.7.0_04 for java-7-oracle)
OpenJDK Runtime Environment (IcedTea7 2.0) (7~b147-2.0-0ubuntu0.11.10.1)
OpenJDK 64-Bit Server VM (build 21.0-b17, mixed mode)
Linux Mint 12 (lisa) GNOME 3.2.1
Yes - this is a bug in JDK7 as #nIcE cOw mentioned.
I've installed JDK6 and I couldn't reproduce this bug.
java version "1.6.0_23"
OpenJDK Runtime Environment (IcedTea6 1.11pre) (6b23~pre11-0ubuntu1.11.10.2)
OpenJDK 64-Bit Server VM (build 20.0-b11, mixed mode)
There is also a workaround when it is necessary to use the Oracle Java 7 (e.g. when using JavaFX). Just add the following lines of code to your window/frame class:
if (Arrays.asList("gnome-shell", "mate", "other...").contains(System.getenv("DESKTOP_SESSION"))) {
try {
Class<?> xwm = Class.forName("sun.awt.X11.XWM");
Field awt_wmgr = xwm.getDeclaredField("awt_wmgr");
awt_wmgr.setAccessible(true);
Field other_wm = xwm.getDeclaredField("OTHER_WM");
other_wm.setAccessible(true);
if (awt_wmgr.get(null).equals(other_wm.get(null))) {
Field metacity_wm = xwm.getDeclaredField("METACITY_WM");
metacity_wm.setAccessible(true);
awt_wmgr.set(null, metacity_wm.get(null));
}
}
catch (Exception x) {
x.printStackTrace();
}
}
This code snippet is based on a workaround from the Netbeans developers.
I would like to complement the solution given by problemzebra.
As it still happens for me with any swing application on Linux (using Cinnamon desktop), even on Java 6 (update 45)
The issue will reoccur every time I move the window or resize it, so you need to reapply the workaround every time the window changes. I created the following class and use it whenever I create a new window:
class LinuxWindowFix implements WindowStateListener {
private final String desktop;
private Field metacity_wm;
private Field awt_wmgr;
private boolean applyFix;
private static LinuxWindowFix instance = new LinuxWindowFix();
public static LinuxWindowFix getInstance() {
return instance;
}
private LinuxWindowFix() {
applyFix = false;
List<String> linuxDesktops = Arrays.asList("gnome-shell", "mate", "cinnamon"); //add more desktop names here.
desktop = System.getenv("DESKTOP_SESSION");
if (desktop != null && linuxDesktops.contains(desktop.toLowerCase())) {
try {
Class<?> xwm = Class.forName("sun.awt.X11.XWM");
awt_wmgr = xwm.getDeclaredField("awt_wmgr");
awt_wmgr.setAccessible(true);
Field other_wm = xwm.getDeclaredField("OTHER_WM");
other_wm.setAccessible(true);
if (awt_wmgr.get(null).equals(other_wm.get(null))) {
metacity_wm = xwm.getDeclaredField("METACITY_WM");
metacity_wm.setAccessible(true);
applyFix = true;
}
} catch (Exception ex) {
//ignore
}
}
}
#Override
public void windowStateChanged(WindowEvent e) {
try {
awt_wmgr.set(null, metacity_wm.get(null));
} catch (Exception ex) {
//ignore
}
}
public void apply(Window w) {
if (!applyFix) {
return;
}
w.removeWindowStateListener(this);
w.addWindowStateListener(this);
}
}
Simply call this for every window you create and it will work as expected.
LinuxWindowFix.getInstance().apply(myWindow);

How to access the Keyboard in an Eclipse RCP / LWJGL app?

I am working my way through the NeHe OpenGL examples, using the LWJGL for the OpenGL binding inside an Eclipse RCP application.
My OpenGL graphics are displayed inside the RCP canvas, not in a separate window.
Lesson 07 shows how to use the keyboard. If I try to do a:
Keyboard.create();
I get an error that the (OpenGL) "Display" has not been created.
If I create an OpenGL "Display" with org.lwjgl.opengl.Display.create(), then I get a new Window.
So how do I access the Keyboard without creating a new Window?
You cannot use the Keyboard without a Display, because of how LWJGL works behind the scenes. The best way is to just use AWT events. You can write your own input class, that could go something like this.
public class Input implements KeyListener {
private boolean aDown; //is the A key down?
//Ect, for all needed keys
public void keyPressed(KeyEvent ke) {
switch (ke.getKeyCode()) {
case KeyEvent.VK_A: aDown = true; break;
//and so on for all other needed keys.
}
}
public void keyReleased(KeyEvent ke) {
switch (ke.getKeyCode()) {
case KeyEvent.VK_A: aDown = false; break;
//and so on for all other needed keys.
}
}
public void keyTyped(KeyEvent ke) {} //Do nothing
public void isADown() {return aDown;}
}

Resources