How to hide scrollbars in the JavaFX WebView - scala

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.

Related

Hide bottom system bar in android - ionic v4

I come in with a question about the bottom system bar, if the bar status was easy to hide so the bottom one did not, I tried
hideFormAccessoryBar, but it did not help
This took me a bit of digging but I managed to find a solution. As it turns out this piece of UI is call the "Navigation Bar". There's a view value SYSTEM_UI_FLAG_HIDE_NAVIGATION that can be set in your MainActivity.java file that will hide it. The official documentation is here,
https://developer.android.com/training/system-ui/navigation#java
IljaDaderko offer's a solution for how to implement the property here https://github.com/ionic-team/capacitor/issues/2423 and there is a PR out standing for ionic to support this out of the box.
Basically as of today you will need to open your MainActivity.java file in your android folder (should android/app/src/main/java/... in ionic 4, 3 may be slightly different) and update the file to look like so,
package io.ionic.starter;
import android.os.Bundle;
import android.view.View;
import com.getcapacitor.BridgeActivity;
import com.getcapacitor.Plugin;
import java.util.ArrayList;
public class MainActivity extends BridgeActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
hideSystemUI();
/**
* Initialize capacitor bridge
*/
this.init(savedInstanceState, new ArrayList<Class<? extends Plugin>>() {{
// Additional plugins you've installed go here
// Ex: add(TotallyAwesomePlugin.class);
}});
}
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
hideSystemUI();
}
}
/**
* Hide android navbar and toolbar for full screen experience
*/
private void hideSystemUI() {
final int flags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(flags);
decorView.setOnSystemUiVisibilityChangeListener((int visibility) -> {
if((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
decorView.setSystemUiVisibility(flags);
}
});
}
}

Can't get GWT Popup panel glass effect to work

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.

GWT: How to change Menubar image, on mouse events?

for my project I need to function my menu-bar like windows start button.
How can i achieve this in GWT?
What i tried up to now is:
public class MyMenuBar extends Composite implements MouseDownHandler{
#Override
public void onMouseDown(MouseDownEvent event) {
System.out.println("IMAGE CHANGED, using new safe html");
}
MenuBar myMenu;
public MyMenuBar(){
myMenu = new MenuBar();
myMenu.addItem(safeHtmlOfImage, popupMenuBar);
this.addDomHandler(this, MouseDownEvent.getType());
initWidget(myMenu);
}
}
Issue is never onMouseDown(MouseDownEvent event) is invoked.
Please help me, how can i achieve this. I am losing my second day with this thing.
Tell me what ever you thinks about it...
I kind of solved issue, but nit think this is the actual solution: by setting the style code for the Menubar.
.gwt-MenuItem
{
background-image: url("img/navigatorDeActive.png");
}
.gwt-MenuItem-selected
{
background-image: url("img/navigatorActive.png");
}

Prevent an accordion in JavaFX from collapsing

Is there an easy way of preventing an accordion in JavaFX 2.1 from fully collapsing? I have an accordion with a few entries but if the user clicks the active accordion entry it collapses the accordion.
I could probably use a mouse click listener to check do the check and act accordingly but this feels like it should be even simpler than that to accomplish.
Add a listener to the currently expanded accordion pane and prevent it from being collapsed by the user by modifying it's collapsible property.
Here is a sample app:
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.value.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;
public class AccordionSample extends Application {
public static void main(String[] args) { launch(args); }
#Override public void start(Stage primaryStage) {
// create some titled panes to go in an accordion.
TitledPane adminPane = new TitledPane("Animals",
VBoxBuilder.create().style("-fx-padding: 10").spacing(10).children(
ButtonBuilder.create().text("Zebra").maxWidth(Double.MAX_VALUE).build(),
ButtonBuilder.create().text("Shrew").maxWidth(Double.MAX_VALUE).build()
).build()
);
TitledPane viewPane = new TitledPane("Vegetables",
VBoxBuilder.create().style("-fx-padding: 10").spacing(10).children(
ButtonBuilder.create().text("Eggplant").maxWidth(Double.MAX_VALUE).build(),
ButtonBuilder.create().text("Carrot").maxWidth(Double.MAX_VALUE).build()
).build()
);
// create an accordion, ensuring the currently expanded pane can not be clicked on to collapse.
Accordion accordion = new Accordion();
accordion.getPanes().addAll(adminPane, viewPane);
accordion.expandedPaneProperty().addListener(new ChangeListener<TitledPane>() {
#Override public void changed(ObservableValue<? extends TitledPane> property, final TitledPane oldPane, final TitledPane newPane) {
if (oldPane != null) oldPane.setCollapsible(true);
if (newPane != null) Platform.runLater(new Runnable() { #Override public void run() {
newPane.setCollapsible(false);
}});
}
});
for (TitledPane pane: accordion.getPanes()) pane.setAnimated(false);
accordion.setExpandedPane(accordion.getPanes().get(0));
// layout the scene.
StackPane layout = new StackPane();
layout.setStyle("-fx-padding: 10; -fx-background-color: cornsilk;");
layout.getChildren().add(accordion);
primaryStage.setScene(new Scene(layout));
primaryStage.show();
}
}
Here is another solution for making sure the accordion will never completely collapse. The difference from the great original answer by #jewelsea is little - I didn't like the fact that the default down facing arrow was disappearing from the open accordion TitledPane face, because its "collapsible" property is being set to false. I played with it a bit more to achieve a more "natural" feel for my interface.
/* Make sure the accordion can never be completely collapsed */
accordeon.expandedPaneProperty().addListener((ObservableValue<? extends TitledPane> observable, TitledPane oldPane, TitledPane newPane) -> {
Boolean expand = true; // This value will change to false if there's (at least) one pane that is in "expanded" state, so we don't have to expand anything manually
for(TitledPane pane: accordeon.getPanes()) {
if(pane.isExpanded()) {
expand = false;
}
}
/* Here we already know whether we need to expand the old pane again */
if((expand == true) && (oldPane != null)) {
Platform.runLater(() -> {
accordeon.setExpandedPane(oldPane);
});
}
});

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.