Richtextfx: Custom Mouse Scrolling Behaviour for CodeArea not possible?

Created on 17 Dec 2017  路  3Comments  路  Source: FXMisc/RichTextFX

I wanted to give the user the option to use the mouse wheel to zoom in and out of the CodeArea, but I can't figure out how to register a scroll listener. Here is some of what i tried:

CodeArea editor = new CodeArea();
ScaledVirtualized<MplEditor2> scale = new ScaledVirtualized<>(editor);

InputMap<Event> preventDefaultScroll = InputMap.consume(EventPattern.anyOf(//
    eventType(ScrollEvent.ANY), //
    eventType(ScrollEvent.SCROLL), //
    eventType(ScrollEvent.SCROLL_FINISHED), //
    eventType(ScrollEvent.SCROLL_STARTED)//
));
Nodes.addInputMap(editor, preventDefaultScroll);
editor.setOnScroll(e -> {
  if (e.isControlDown()) {
    double delta = e.getDeltaX();
    Scale zoom = scale.getZoom();
    zoom.setY(zoom.getY() + delta);
    zoom.setX(zoom.getY() + delta);
  }
});

This answer on StackOverflow suggests that this is not possible :(

question waiting for response

Most helpful comment

So, it looks like the event's target is ParagraphText or an individual Text object. I'm not entirely sure what consumes it, but something is consuming it before the area's scroll handler runs (even when I comment out the "prevent scroll" code).

It seems that the solution is to add an event filter to the area and run your scroll code there. The following code (using an InlineCssTextArea for simplicity) worked for me:
````java
import javafx.application.Application;
import javafx.event.Event;
import javafx.scene.Scene;
import javafx.scene.input.ScrollEvent;
import javafx.scene.transform.Scale;
import javafx.stage.Stage;
import org.fxmisc.flowless.ScaledVirtualized;
import org.fxmisc.flowless.VirtualizedScrollPane;
import org.fxmisc.richtext.InlineCssTextArea;
import org.fxmisc.wellbehaved.event.InputMap;
import org.fxmisc.wellbehaved.event.Nodes;

import static org.fxmisc.wellbehaved.event.EventPattern.anyOf;
import static org.fxmisc.wellbehaved.event.EventPattern.eventType;
import static org.fxmisc.wellbehaved.event.InputMap.consume;

public class ScaleAreaDemo extends Application {

public static void main(String[] args) {
    launch(args);
}

@Override
public void start(Stage primaryStage) {
    InlineCssTextArea editor = new InlineCssTextArea(String.join("\n", new String[] {
            "stuff",
            "more stuff",
            "lots of more stuff",
            "",
            "",
            "running out of ideas..."
    }));
    ScaledVirtualized<InlineCssTextArea> scaleVirtualized = new ScaledVirtualized<>(editor);
    primaryStage.setScene(new Scene(new VirtualizedScrollPane<>(scaleVirtualized), 400, 400));
    primaryStage.show();

// InputMap preventDefaultScroll = consume(
// anyOf(
// eventType(ScrollEvent.ANY),
// eventType(ScrollEvent.SCROLL),
// eventType(ScrollEvent.SCROLL_FINISHED),
// eventType(ScrollEvent.SCROLL_STARTED)),
// e -> System.out.println("Scroll detected in override")
// );
// Nodes.addInputMap(editor, preventDefaultScroll);
editor.addEventFilter(ScrollEvent.ANY, e -> {
if (e.isControlDown()) {
double scaleAmount = 0.9;
Scale zoom = scaleVirtualized.getZoom();
if (e.getDeltaX() != 0) {
zoom.setX( e.getDeltaX() > 0 ? zoom.getX() * scaleAmount : zoom.getX() / scaleAmount );
}
if (e.getDeltaY() != 0) {
zoom.setY( e.getDeltaY() > 0 ? zoom.getY() * scaleAmount : zoom.getY() / scaleAmount );
}
}
});
}
}
````

All 3 comments

It should be possible in 0.8.1. Are you sure you want to use deltaX for both the x and y values?

I'll need to look at this more closely to see why your code isn't working.

So, it looks like the event's target is ParagraphText or an individual Text object. I'm not entirely sure what consumes it, but something is consuming it before the area's scroll handler runs (even when I comment out the "prevent scroll" code).

It seems that the solution is to add an event filter to the area and run your scroll code there. The following code (using an InlineCssTextArea for simplicity) worked for me:
````java
import javafx.application.Application;
import javafx.event.Event;
import javafx.scene.Scene;
import javafx.scene.input.ScrollEvent;
import javafx.scene.transform.Scale;
import javafx.stage.Stage;
import org.fxmisc.flowless.ScaledVirtualized;
import org.fxmisc.flowless.VirtualizedScrollPane;
import org.fxmisc.richtext.InlineCssTextArea;
import org.fxmisc.wellbehaved.event.InputMap;
import org.fxmisc.wellbehaved.event.Nodes;

import static org.fxmisc.wellbehaved.event.EventPattern.anyOf;
import static org.fxmisc.wellbehaved.event.EventPattern.eventType;
import static org.fxmisc.wellbehaved.event.InputMap.consume;

public class ScaleAreaDemo extends Application {

public static void main(String[] args) {
    launch(args);
}

@Override
public void start(Stage primaryStage) {
    InlineCssTextArea editor = new InlineCssTextArea(String.join("\n", new String[] {
            "stuff",
            "more stuff",
            "lots of more stuff",
            "",
            "",
            "running out of ideas..."
    }));
    ScaledVirtualized<InlineCssTextArea> scaleVirtualized = new ScaledVirtualized<>(editor);
    primaryStage.setScene(new Scene(new VirtualizedScrollPane<>(scaleVirtualized), 400, 400));
    primaryStage.show();

// InputMap preventDefaultScroll = consume(
// anyOf(
// eventType(ScrollEvent.ANY),
// eventType(ScrollEvent.SCROLL),
// eventType(ScrollEvent.SCROLL_FINISHED),
// eventType(ScrollEvent.SCROLL_STARTED)),
// e -> System.out.println("Scroll detected in override")
// );
// Nodes.addInputMap(editor, preventDefaultScroll);
editor.addEventFilter(ScrollEvent.ANY, e -> {
if (e.isControlDown()) {
double scaleAmount = 0.9;
Scale zoom = scaleVirtualized.getZoom();
if (e.getDeltaX() != 0) {
zoom.setX( e.getDeltaX() > 0 ? zoom.getX() * scaleAmount : zoom.getX() / scaleAmount );
}
if (e.getDeltaY() != 0) {
zoom.setY( e.getDeltaY() > 0 ? zoom.getY() * scaleAmount : zoom.getY() / scaleAmount );
}
}
});
}
}
````

It's amazing!

I use this for zoom:

double scale = e.getDeltaY() < 0 ? zoom.getY() * scaleAmount : zoom.getY() / scaleAmount;
zoom.setX(scale);
zoom.setY(scale);
Was this page helpful?
0 / 5 - 0 ratings

Related issues

RobertBColton picture RobertBColton  路  8Comments

saifalmutory picture saifalmutory  路  7Comments

hendriklenz picture hendriklenz  路  9Comments

oowekyala picture oowekyala  路  10Comments

garybentley picture garybentley  路  11Comments