Java源码示例:org.reactfx.EventStreams

示例1
public EventLoggerImpl(DesignerRoot designerRoot) {
    this.designerRoot = designerRoot; // we have to be careful with initialization order here

    EventStream<LogEntry> onlyParseException = deleteOnSignal(latestEvent, PARSE_EXCEPTION, PARSE_OK);
    EventStream<LogEntry> onlyXPathException = deleteOnSignal(latestEvent, XPATH_EVALUATION_EXCEPTION, XPATH_OK);

    EventStream<LogEntry> otherExceptions =
        filterOnCategory(latestEvent, true, PARSE_EXCEPTION, XPATH_EVALUATION_EXCEPTION, SELECTION_EVENT_TRACING)
            .filter(it -> isDeveloperMode() || !it.getCategory().isInternal());

    // none of this is done if developer mode isn't enabled because then those events aren't even pushed in the first place
    EventStream<LogEntry> reducedTraces = ReactfxUtil.reduceEntangledIfPossible(
        latestEvent.filter(LogEntry::isTrace),
        (a, b) -> Objects.equals(a.messageProperty().getValue(), b.messageProperty().getValue()),
        LogEntry::appendMessage,
        EVENT_TRACING_REDUCTION_DELAY
    );

    EventStreams.merge(reducedTraces, onlyParseException, otherExceptions, onlyXPathException)
                .distinct()
                .subscribe(fullLog::add);
}
 
示例2
/**
 * This is a weird hack to preload the FXML and CSS, so that the
 * first opening of the popover doesn't look completely broken
 * (twitching and obviously being restyled).
 *
 * <p>We show the popover briefly with opacity 0, just the time for its
 * content graph to load. When hidden the opacity is reset to 1.
 */
public void doFirstLoad(Stage stage) {
    myPopover.ifPresent(pop -> {
        pop.setOpacity(0);
        pop.setAnimated(false);
        pop.show(stage, 40000, 40000);

        EventStreams.eventsOf(pop, WindowEvent.WINDOW_HIDDEN)
                    .subscribeForOne(e -> pop.setOpacity(1));

        Platform.runLater(() -> {
            pop.hide();
            pop.setAnimated(true);
        });
    });
}
 
示例3
@Override
protected void beforeParentInit() {
    additionalInfoListView.setPlaceholder(new Label("No additional info"));

    Val<Node> currentSelection = initNodeSelectionHandling(getDesignerRoot(), EventStreams.never(), false);

    // pin to see updates
    currentSelection.pin();

    hideCommonAttributesProperty()
        .values()
        .distinct()
        .subscribe(show -> setFocusNode(currentSelection.getValue(), new DataHolder()));


    attrValueColumn.setCellValueFactory(param -> Val.constant(DesignerUtil.attrToXpathString(param.getValue())));
    attrNameColumn.setCellValueFactory(param -> Val.constant("@" + param.getValue().getName()));
    attrNameColumn.setCellFactory(col -> new AttributeNameTableCell());

    Label valueColGraphic = new Label("Value");
    valueColGraphic.setTooltip(new Tooltip("This is the XPath 2.0 representation"));
    attrValueColumn.setGraphic(valueColGraphic);
}
 
示例4
private void setupListeners() {
    ObjectProperty<Point2D> mouseDown = new SimpleObjectProperty<>();

    EventStreams.eventsOf(imageView, MouseEvent.MOUSE_PRESSED).subscribe(e -> {
        Point2D mousePress = imageViewToImage(new Point2D(e.getX(), e.getY()));
        mouseDown.set(mousePress);
    });

    EventStreams.eventsOf(imageView, MouseEvent.MOUSE_DRAGGED).subscribe(e -> {
        Point2D dragPoint = imageViewToImage(new Point2D(e.getX(), e.getY()));
        shift(dragPoint.subtract(mouseDown.get()));
        mouseDown.set(imageViewToImage(new Point2D(e.getX(), e.getY())));
    });

    EventStream<ScrollEvent> scrollEvents = EventStreams.eventsOf(imageView, ScrollEvent.SCROLL);
    EventStream<ScrollEvent> scrollEventsUp = scrollEvents.filter(scrollEvent -> scrollEvent.getDeltaY() < 0);
    EventStream<ScrollEvent> scrollEventsDown = scrollEvents.filter(scrollEvent -> scrollEvent.getDeltaY() > 0);
    scrollEventsUp.subscribe(scrollEvent -> scale = Math.min(scale + 0.25, 3));
    scrollEventsDown.subscribe(scrollEvent -> scale = Math.max(scale - 0.25, 0.25));
    EventStreams.merge(scrollEventsUp, scrollEventsDown).subscribe(scrollEvent -> scaleImageViewport(scale));

    EventStreams.eventsOf(imageView, MouseEvent.MOUSE_CLICKED)
            .filter(mouseEvent -> mouseEvent.getClickCount() == 2)
            .subscribe(mouseEvent -> fitToView());
}
 
示例5
private void setupNvidiaListener() {
    log.log(Level.FINER, "Setting nvidia ram listener.");
    EventStreams.nonNullValuesOf(nvidiaService.progressProperty())
            .filter(vramUsage -> vramUsage.doubleValue() > 0)
            .subscribe(vramUsage -> vramBar.setProgress(vramUsage.doubleValue()));

    log.log(Level.FINER, "Setting nvidia timer.");
    nvidiaTimer = FxTimer.createPeriodic(Duration.ofMillis(1000), () -> {
        log.log(Level.FINEST, "Timer: checking service");
        if (nvidiaService == null || nvidiaService.isRunning())
            return;

        log.log(Level.FINEST, "Timer: starting service");
        nvidiaService.restart();
        nvidiaTimer.restart();
    });
    nvidiaTimer.restart();
}
 
示例6
public NeuralImageCell(ObservableBooleanValue editable) {
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/neuralImageCell.fxml"));
    fxmlLoader.setController(this);
    fxmlLoader.setRoot(this);

    try {
        fxmlLoader.load();
    } catch (IOException exception) {
        throw new RuntimeException(exception);
    }

    setEditable(false);
    if (editable != null) {
        EventStreams.changesOf(editable).subscribe(editableChange -> {
            setEditable(editableChange.getNewValue());
        });
    }
}
 
示例7
public void setNeuralImage(NeuralImage newNeuralImage) {
    // Remove previous bindings if applicable
    image.imageProperty().unbind();
    if (neuralImage != null)
        selected.selectedProperty().unbindBidirectional(neuralImage.selectedProperty());
    if (weightChanges != null)
        weightChanges.unsubscribe();

    neuralImage = newNeuralImage;

    if (neuralImage != null) {
        image.imageProperty().bind(neuralImage.imageProperty());
        selected.selectedProperty().bindBidirectional(neuralImage.selectedProperty());

        // Event Streams for Weight to convert between double and string
        weight.setText(String.valueOf(neuralImage.getWeight()));
        weightChanges = EventStreams.changesOf(weight.focusedProperty()).subscribe(focusChange -> {
            if (!focusChange.getNewValue()) { // focusing away from input
                double newWeight = NeuralDouble.DOUBLE_CONVERTER.fromString(weight.getText()).doubleValue();
                neuralImage.setWeight(newWeight);
                if (newWeight == 0)
                    weight.setText("1.0");
            }
        });
    }
}
 
示例8
public FullImageView(File imageFile, Consumer<ActionEvent> styleEvent, Consumer<ActionEvent> contentEvent, Consumer<ActionEvent> initEvent, ResourceBundle resources) {
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/imagePreviewTab.fxml"));
    fxmlLoader.setResources(resources);
    fxmlLoader.setController(this);
    fxmlLoader.setRoot(this);

    try {
        fxmlLoader.load();
    } catch (IOException exception) {
        throw new RuntimeException(exception);
    }

    image.fitWidthProperty().bind(widthProperty());
    image.fitHeightProperty().bind(heightProperty());

    imageView = new MovingImageView(image);
    imageView.setImage(imageFile);

    EventStreams.eventsOf(style, ActionEvent.ACTION)
            .subscribe(styleEvent);
    EventStreams.eventsOf(content, ActionEvent.ACTION)
            .subscribe(contentEvent);
    EventStreams.eventsOf(init, ActionEvent.ACTION)
            .subscribe(initEvent);
}
 
示例9
private C cellForItem(T item) {
    C cell = cellPool.getCell(item);

    // apply CSS when the cell is first added to the scene
    Node node = cell.getNode();
    EventStreams.nonNullValuesOf(node.sceneProperty())
            .subscribeForOne(scene -> {
                node.applyCss();
            });

    // Make cell initially invisible.
    // It will be made visible when it is positioned.
    node.setVisible(false);

    if (cell.isReusable()) {
        // if cell is reused i think adding event handler
        // would cause resource leakage.
        node.setOnScroll(this::pushScrollEvent);
        node.setOnScrollStarted(this::pushScrollEvent);
        node.setOnScrollFinished(this::pushScrollEvent);
    } else {
        node.addEventHandler(ScrollEvent.ANY, this::pushScrollEvent);
    }

    return cell;
}
 
示例10
@Test
public void test() {
    IntegerProperty src = new SimpleIntegerProperty(0);
    IntegerBinding twice = src.multiply(2);
    Var<Number> twiceVar = Var.fromVal(twice, n -> src.set(n.intValue() / 2));

    List<Number> values = new ArrayList<>();
    EventStreams.valuesOf(twiceVar).subscribe(values::add);

    src.set(1);
    twiceVar.setValue(4);
    twiceVar.setValue(5); // no effect
    twiceVar.setValue(7); // will become 6

    assertEquals(Arrays.asList(0, 2, 4, 6), values);
}
 
示例11
@Test
public void testEqualNumberOfFramesForFixedDuration() throws InterruptedException, ExecutionException, TimeoutException {
    Var<Double> src1 = Var.newSimpleVar(0.0);
    Var<Double> src2 = Var.newSimpleVar(0.0);
    Val<Double> anim1 = src1.animate(Duration.ofMillis(500), Interpolator.LINEAR_DOUBLE);
    Val<Double> anim2 = src2.animate(Duration.ofMillis(500), Interpolator.LINEAR_DOUBLE);
    List<Double> vals1 = new ArrayList<>();
    List<Double> vals2 = new ArrayList<>();

    Platform.runLater(() -> {
        EventStreams.valuesOf(anim1).subscribe(vals1::add);
        EventStreams.valuesOf(anim2).subscribe(vals2::add);

        src1.setValue(10.0);
        src2.setValue(20.0);
    });

    waitUntil(anim1, x -> x == 10.0, 1000);
    waitUntil(anim2, x -> x == 20.0, 100);

    assertEquals(vals1.size(), vals2.size());
}
 
示例12
@Test
public void testProportionalNumberOfFramesForFixedSpeed() throws InterruptedException, ExecutionException, TimeoutException {
    Var<Integer> src1 = Var.newSimpleVar(0);
    Var<Integer> src2 = Var.newSimpleVar(0);
    Val<Integer> anim1 = src1.animate((a, b) -> Duration.ofMillis(b - a), Interpolator.LINEAR_INTEGER);
    Val<Integer> anim2 = src2.animate((a, b) -> Duration.ofMillis(b - a), Interpolator.LINEAR_INTEGER);
    List<Integer> vals1 = new ArrayList<>();
    List<Integer> vals2 = new ArrayList<>();

    Platform.runLater(() -> {
        EventStreams.valuesOf(anim1).subscribe(vals1::add);
        EventStreams.valuesOf(anim2).subscribe(vals2::add);

        src1.setValue(100);
        src2.setValue(300);
    });

    waitUntil(anim2, x -> x == 300, 1000);

    assertEquals(100, anim1.getValue().intValue());

    // test that the number of frames for 0 -> 300 is at least
    // twice the number of frames for 0 -> 100 (i.e. a conservative test)
    assertThat(vals2.size(), greaterThan(2 * vals1.size()));
}
 
示例13
@Test
public void midAnimationChangeTest() throws InterruptedException, ExecutionException, TimeoutException {
    Var<Double> src = Var.newSimpleVar(100.0);
    Val<Double> anim = src.animate(Duration.ofMillis(200), Interpolator.EASE_BOTH_DOUBLE);
    List<Double> vals = new ArrayList<>();

    Platform.runLater(() -> {
        EventStreams.valuesOf(anim).subscribe(vals::add);

        // when animated value reaches 200.0, set src to -1.0
        anim.addListener((obs, old, newVal) -> {
            if(newVal >= 200.0) {
                src.setValue(-1.0);
            }
        });

        src.setValue(300.0);
    });

    waitUntil(anim, x -> x == -1.0, 1000);

    assertTrue("Value 300.0 never reached", vals.stream().noneMatch(x -> x == 300.0));
}
 
示例14
@Test
public void test() {
    ObservableList<Integer> list = FXCollections.observableArrayList();
    Val<Integer> size = LiveList.sizeOf(list);
    List<Integer> sizes = new ArrayList<>();
    Subscription sub = EventStreams.valuesOf(size).subscribe(sizes::add);
    list.add(1);
    list.addAll(2, 3, 4);
    assertEquals(Arrays.asList(0, 1, 4), sizes);

    sub.unsubscribe();
    sizes.clear();
    list.addAll(5, 6);
    assertEquals(Arrays.asList(), sizes);

    EventStreams.valuesOf(size).subscribe(sizes::add);
    list.addAll(7, 8);
    assertEquals(Arrays.asList(6, 8), sizes);
}
 
示例15
@Override
public void start(Stage primaryStage) {
    TextArea textArea = new TextArea();
    WebView webView = new WebView();
    WebEngine engine = webView.getEngine();

    EventStreams.valuesOf(textArea.textProperty())
            .successionEnds(Duration.ofMillis(500))
            .subscribe(html -> engine.loadContent(html));

    SplitPane root = new SplitPane();
    root.getItems().addAll(textArea, webView);
    Scene scene = new Scene(root);
    primaryStage.setScene(scene);
    primaryStage.show();
}
 
示例16
@Override
protected void beforeParentInit() {
    exportResultArea.setSyntaxHighlighter(AvailableSyntaxHighlighters.XML);

    ControlUtil.copyToClipboardButton(copyResultButton, exportResultArea::getText);
    ControlUtil.saveToFileButton(saveToFileButton, myPopupStage, exportResultArea::getText, this, () -> null);


    TreeRendererRegistry rendererRegistry = getService(DesignerRoot.TREE_RENDERER_REGISTRY);

    rendererChoicebox.setConverter(DesignerUtil.stringConverter(LiveTreeRenderer::getName, rendererRegistry::fromId));
    rendererChoicebox.setItems(rendererRegistry.getRenderers());
    rendererChoicebox.getSelectionModel().select(0);

    EventStreams.valuesOf(rendererChoicebox.getSelectionModel().selectedItemProperty()).subscribe(propertiesPopover::rebind);
    ReactfxUtil.subscribeDisposable(
        rendererChoicebox.getSelectionModel().selectedItemProperty(),
        renderer -> renderer.getLiveProperties().nonDefaultProperty().values().subscribe(it -> updater.run())
    );

    EventStreams.valuesOf(rendererChoicebox.getSelectionModel().selectedItemProperty())
                .map(LiveTreeRenderer::getLiveProperties)
                .subscribe(props -> propertiesMapButton.setDisable(props.asList().isEmpty()));
    propertiesMapButton.setOnAction(e -> propertiesPopover.showOrFocus(p -> p.show(propertiesMapButton)));

    exportResultArea.setParagraphGraphicFactory(LineNumberFactory.get(exportResultArea));

}
 
示例17
private static void registerPseudoClassListeners(SmartPopover popOver) {

        EventStreams.valuesOf(popOver.detachedProperty())
                    .subscribe(v -> popOver.pseudoClassStateChanged(PseudoClass.getPseudoClass("detached"), v));
        EventStreams.valuesOf(popOver.focusedProperty())
                    // JavaFX lacks a focus model that works across several popups and stuff.
                    // The only solution we have to avoid having duplicate carets or so, is
                    // to *not* let a popover that openly has textfields or other controls
                    // that steal focus *be detachable*
                    .subscribe(v -> popOver.pseudoClassStateChanged(PseudoClass.getPseudoClass("focused"), v));

    }
 
示例18
private Subscription subscribeKeyNav(int numResults, Var<Integer> curIdx, Node eventSource) {
    // Make TAB or F3 cycle forward,
    // SHIFT+TAB or SHIFT+F3 cycle backwards
    return EventStreams.eventsOf(eventSource, KeyEvent.KEY_RELEASED)
                       .filter(it -> it.getCode() == KeyCode.F3 || it.getCode() == KeyCode.TAB)
                       .subscribe(ke -> {
                           int offset = ke.isShiftDown() ? -1 : +1;
                           curIdx.setValue((curIdx.getValue() + offset) % numResults);
                           ke.consume();
                       });


}
 
示例19
private void setupContentLayersTable() {
    log.log(Level.FINER, "Setting content layer table list.");
    contentLayersTable.setItems(contentLayers);
    contentLayersTable.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);

    log.log(Level.FINER, "Setting content layer table selection listener.");
    EventStreams.changesOf(contentLayers).subscribe(change -> {
        log.log(Level.FINE, "contentLayers changed");

        List<NeuralBoolean> selectedContentLayers = contentLayers.stream()
                .filter(NeuralBoolean::getValue)
                .collect(Collectors.toList());

        String[] newContentLayers = new String[selectedContentLayers.size()];
        for (int i = 0; i < selectedContentLayers.size(); i++)
            newContentLayers[i] = selectedContentLayers.get(i).getName();
        neuralStyle.setContentLayers(newContentLayers);

        toggleStyleButtons();
    });

    log.log(Level.FINER, "Setting style layer table shortcut listener");
    EventStreams.eventsOf(contentLayersTable, KeyEvent.KEY_RELEASED).filter(spaceBar::match).subscribe(keyEvent -> {
        ObservableList<NeuralBoolean> selectedStyleLayers =
                contentLayersTable.getSelectionModel().getSelectedItems();
        for (NeuralBoolean neuralLayer : selectedStyleLayers)
            neuralLayer.setValue(!neuralLayer.getValue());
    });

    log.log(Level.FINER, "Setting content layer table column factories.");
    contentLayersTableSelected.setCellValueFactory(new PropertyValueFactory<>("value"));
    contentLayersTableSelected.setCellFactory(CheckBoxTableCell.forTableColumn(contentLayersTableSelected));

    contentLayersTableName.setCellValueFactory(new PropertyValueFactory<>("name"));
    contentLayersTableName.setCellFactory(TextFieldTableCell.forTableColumn());
}
 
示例20
/**
     * Private constructor
     */
    private LineNumAndBreakpointFactory(StyledTextArea<?> area, IntFunction<String>
            format, String stylesheet) {
        this.nParagraphs = EventStreams.sizeOf(area.getParagraphs());
        this.area = area;
        this.format = new SimpleObjectProperty<>(format);
        this.stylesheet = stylesheet;
        this.breakPoints = FXCollections.observableArrayList();
        this.currentBreakPointLineNumber = new SimpleIntegerProperty(-1);

        // add a listener to the codeArea's set of breakpoints
        // so that breakpoints can be added dynamically as the code is being stepped
        // through when in debug mode
//        ((LineNumAndBreakpointFactory) area.getParagraphGraphicFactory())
//                .getBreakPoints().
//                addListener((SetChangeListener<Paragraph>) change -> {
//                    if (newTab.getFile() != null) {
//                        boolean set = change.wasAdded();
//                        String fileName = newTab.getFile().getAbsolutePath();
//                        Paragraph paragraph = set ? change.getElementAdded() : change
//                                .getElementRemoved();
//                        int line = getIndexOf(codeArea, paragraph);
//                        if (line >= 0) {
//                            SourceLine sourceLine = new SourceLine(line, fileName);
//                            mediator.setBreakPointInRAM(sourceLine, set);
//                        }
//                    }
//                });

    }
 
示例21
/**
 * Creates a LiveDirs instance to be used from a designated thread.
 * @param projector converts the ({@link T}) {@link TreeItem#getValue()} into a {@link Path} object
 * @param injector converts a given {@link Path} object into {@link T}. The reverse of {@code projector}
 * @param externalInitiator object to represent an initiator of an external
 * file-system change.
 * @param clientThreadExecutor executor to execute actions on the caller
 * thread. Used to publish updates and errors on the caller thread.
 * @throws IOException
 */
public LiveDirs(I externalInitiator, Function<T, Path> projector, Function<Path, T> injector, Executor clientThreadExecutor) throws IOException {
    this.externalInitiator = externalInitiator;
    this.clientThreadExecutor = clientThreadExecutor;
    this.dirWatcher = new DirWatcher(clientThreadExecutor);
    this.model = new LiveDirsModel<>(externalInitiator, projector, injector);
    this.io = new LiveDirsIO<>(dirWatcher, model, clientThreadExecutor);

    this.dirWatcher.signalledKeys().subscribe(this::processKey);
    this.errors = EventStreams.merge(dirWatcher.errors(), model.errors(), localErrors);
}
 
示例22
private static EventStream<Boolean> booleanPulse(javafx.util.Duration javafxDuration, EventStream<?> restartImpulse) {
    Duration duration = Duration.ofMillis(Math.round(javafxDuration.toMillis()));
    EventStream<?> ticks = EventStreams.restartableTicks(duration, restartImpulse);
    return StateMachine.init(false)
            .on(restartImpulse.withDefaultEvent(null)).transition((state, impulse) -> true)
            .on(ticks).transition((state, tick) -> !state)
            .toStateStream();
}
 
示例23
public Val<Map<String, String>> nonDefaultProperty() {
    return withInvalidations(
        observableMapVal(mapping),
        map -> EventStreams.merge(map.values().stream().map(Val::values).collect(Collectors.toCollection(() -> observableSet(new HashSet<>()))))
    ).map(this::computeNonDefault);
}
 
示例24
public Subscription init(ASTManager astManager) {
    MessageChannel<VersionedXPathQuery> service = root.getService(DesignerRoot.LATEST_XPATH);


    EventStream<?> merged = EventStreams.merge(
        astManager.compilationUnitProperty().values(),
        additionalTicks(),
        service.messageStream(true, this),
        astManager.ruleProperties().values().withDefaultEvent(Collections.emptyMap())
    );

    subscription = merged.subscribe(
        tick -> {
            Node compil = astManager.compilationUnitProperty().getOrElse(null);
            VersionedXPathQuery query = service.latestMessage().getOrElse(null);
            Map<String, String> props = astManager.ruleProperties().getOrElse(Collections.emptyMap());

            if (compil == null) {
                handleNoCompilationUnit();
                return;
            }
            if (query == null || StringUtils.isBlank(query.getExpression())) {
                handleNoXPath();
                return;
            }


            try {
                List<Node> results = XPathEvaluator.evaluateQuery(compil,
                                                                  astManager.languageVersionProperty().getValue(),
                                                                  query.getVersion(),
                                                                  query.getExpression(),
                                                                  props,
                                                                  query.getDefinedProperties());

                handleXPathSuccess(results);
            } catch (XPathEvaluationException e) {
                handleXPathError(e);
            }

        });

    return this::unsubscribe;
}
 
示例25
@Override
protected void beforeParentInit() {


    scopeHierarchyTreeView.setCellFactory(view -> new ScopeHierarchyTreeCell());


    // suppress as early as possible in the pipeline
    myScopeItemSelectionEvents = EventStreams.valuesOf(scopeHierarchyTreeView.getSelectionModel().selectedItemProperty()).suppressible();

    EventStream<NodeSelectionEvent> selectionEvents = myScopeItemSelectionEvents.filter(Objects::nonNull)
                                                                                .map(TreeItem::getValue)
                                                                                .filterMap(o -> o instanceof NameDeclaration, o -> (NameDeclaration) o)
                                                                                .map(NameDeclaration::getNode)
                                                                                .map(NodeSelectionEvent::of);

    initNodeSelectionHandling(getDesignerRoot(), selectionEvents, true);
}
 
示例26
public AstTreeView(@NamedArg("designerRoot") DesignerRoot root) {
    designerRoot = root;
    baseSelectionEvents = new EventSource<>();
    suppressibleSelectionEvents = baseSelectionEvents.suppressible();

    getStyleClass().addAll("ast-tree-view");

    initNodeSelectionHandling(root, suppressibleSelectionEvents, false);

    // this needs to be done even if the selection originates from this node
    EventStreams.changesOf(getSelectionModel().selectedItemProperty())
                .subscribe(item -> highlightFocusNodeParents((ASTTreeItem) item.getOldValue(), (ASTTreeItem) item.getNewValue()));

    // push a node selection event whenever...
    //  * The selection changes
    EventStreams.valuesOf(getSelectionModel().selectedItemProperty())
                .filterMap(Objects::nonNull, TreeItem::getValue)
                .map(NodeSelectionEvent::of)
                .subscribe(baseSelectionEvents::push);

    //  * the currently selected cell is explicitly clicked
    setCellFactory(tv -> new ASTTreeCell(getDesignerRoot(), n -> {
        ASTTreeItem selectedTreeItem = (ASTTreeItem) getSelectionModel().getSelectedItem();

        // only push an event if the node was already selected
        if (selectedTreeItem != null && selectedTreeItem.getValue() != null
            && selectedTreeItem.getValue().equals(n)) {
            baseSelectionEvents.push(NodeSelectionEvent.of(n));
        }
    }));


    EventStreams.valuesOf(additionalStyleClasses)
                .repeatOn(EventStreams.valuesOf(rootProperty()))
                .subscribe(fun -> {
                    TreeItem<Node> rootNode = getRoot();
                    if (rootNode != null && fun != null) {
                        ((ASTTreeItem) rootNode).foreach(it -> ((ASTTreeItem) it).setStyleClasses(fun.apply(it.getValue())));
                    }
                });

}
 
示例27
/**
 * Textfield for the search query.
 */
private void popSearchField() {
    TextField textField = new TextField();
    textField.setPrefWidth(150);
    textField.setPromptText("Search tree");
    ControlUtil.makeTextFieldShowPromptEvenIfFocused(textField);

    Label label = new Label();
    label.getStyleClass().addAll("hint-label");
    label.setTooltip(new Tooltip("Go to next result with F3"));

    StackPane pane = new StackPane();
    pane.getStyleClass().addAll("search-popup");
    pane.getStylesheets().addAll(DesignerUtil.getCss("designer").toString());

    StackPane.setAlignment(textField, Pos.TOP_RIGHT);
    StackPane.setAlignment(label, Pos.BOTTOM_RIGHT);


    pane.getChildren().addAll(textField, label);

    Val<String> query = Val.wrap(textField.textProperty())
                           .filter(StringUtils::isNotBlank).map(String::trim)
                           .filter(it -> it.length() >= MIN_QUERY_LENGTH);

    Var<Integer> numResults = Var.newSimpleVar(0);

    Subscription subscription = bindSearchQuery(query.conditionOnShowing(pane), numResults, textField);

    label.textProperty().bind(
        numResults.map(n -> n == 0 ? "no match" : n == 1 ? "1 match" : n + " matches")
    );

    label.visibleProperty().bind(query.map(Objects::nonNull));

    Popup popup = new Popup();
    popup.getContent().addAll(pane);
    popup.setAutoHide(true);
    popup.setHideOnEscape(true);

    Bounds bounds = localToScreen(getBoundsInLocal());
    popup.show(this, bounds.getMaxX() - textField.getPrefWidth() - 1, bounds.getMinY());
    popup.setOnHidden(e -> {
        openSearchField = null;
        subscription.unsubscribe();
    }); // release resources

    // Hide popup when ENTER or ESCAPE is pressed
    EventStreams.eventsOf(popup, KeyEvent.KEY_RELEASED)
                .filter(it -> it.getCode() == KeyCode.ENTER || it.getCode() == KeyCode.ESCAPE)
                .subscribeForOne(e -> {
                    popup.hide();
                    e.consume();
                });

    textField.requestFocus();
    openSearchField = textField;
}
 
示例28
public void initialiseAutoCompletion() {

        // allows tab/enter completion
        EventStreams.eventsOf(autoCompletePopup, KeyEvent.ANY)
                    .filter(e -> !e.isConsumed())
                    .filter(e ->
                                // For some reason this has to be asymmetric
                                // Delivered events vary between JREs, as well as their properties
                                // This is the common denominator I found for JREs 8..10

                                // Only KEY_RELEASED events are delivered for ENTER
                                e.getEventType().equals(KeyEvent.KEY_RELEASED) && e.getCode() == KeyCode.ENTER
                                    // All KEY_TYPED, KEY_PRESSED, and KEY_RELEASED are delivered for TAB,
                                    // but we have to handle it before it inserts a \t so we catch KEY_PRESSED
                                    || e.getEventType().equals(KeyEvent.KEY_PRESSED) && e.getCode() == KeyCode.TAB

                    )
                    .conditionOn(autoCompletePopup.showingProperty())
                    .subscribe(e -> {
                        int focusIdx = getFocusIdx();
                        if (focusIdx == -1) {
                            focusIdx = 0;
                        }

                        if (focusIdx < autoCompletePopup.getItems().size()) {
                            autoCompletePopup.getItems().get(focusIdx).getOnAction().handle(new ActionEvent());
                        }
                        e.consume();
                    });

        EventStream<Integer> changesEventStream = myCodeArea.plainTextChanges()
                                                            // filter out copy paste
                                                            .filter(it -> it.getNetLength() == 1)
                                                            .map(characterChanges -> {
                                                                if (characterChanges.getRemoved().length() > 0) {
                                                                    return characterChanges.getRemovalEnd() - 1;
                                                                }
                                                                return characterChanges.getInsertionEnd();
                                                            });

        EventStream<Integer> keyCombo = EventStreams.eventsOf(myCodeArea, KeyEvent.KEY_PRESSED)
                                                    .filter(key -> key.isControlDown() && key.getCode().equals(KeyCode.SPACE))
                                                    .map(searchPoint -> myCodeArea.getCaretPosition());

        EventStreams.merge(keyCombo, changesEventStream)
                    .map(this::getInsertionPointAndQuery)
                    .hook(t -> {
                        if (t == null) {
                            autoCompletePopup.hide();
                        }
                    })
                    .filter(Objects::nonNull)
                    .subscribe(s -> showAutocompletePopup(s._1, s._2));
    }
 
示例29
public EventStream<T> toStream(){
	//this instead of EventStream.nonNullValues bc we want to omit initial (artificial) value
	return EventStreams.changesOf(this).filterMap(c -> Optional.ofNullable(c.getNewValue()));
}
 
示例30
private void setupCodeArea() {
		codeArea = new CodeArea();
//		codeArea.setWrapText(true);
		setupParagraphGraphics();
		EventStream<Object> highLightTrigger = EventStreams.merge(codeArea.multiPlainChanges(),
				EventStreams.changesOf(highlighters.getSelectionModel().selectedItemProperty()),
				EventStreams.eventsOf(format, MouseEvent.MOUSE_CLICKED));


		//behavior of TAB: 2 spaces, allow outdention via SHIFT-TAB, if cursor is at beginning
		Nodes.addInputMap(codeArea, InputMap.consume(
				EventPattern.keyPressed(KeyCode.TAB),
				e -> codeArea.replaceSelection("  ")
		));

		Nodes.addInputMap(codeArea, InputMap.consume(
				EventPattern.keyPressed(KeyCode.TAB, SHIFT_DOWN),
				e -> {
					var paragraph = codeArea.getParagraph(codeArea.getCurrentParagraph());
					var indentation = StringUtils.countStartSpaces(paragraph.getText());

					//is the cursor in the white spaces
					if (codeArea.getCaretColumn() <= indentation){
						var charsToRemove = Math.min(indentation, 2);

						codeArea.replaceText(new IndexRange(codeArea.getAbsolutePosition(codeArea.getCurrentParagraph(), 0),
								codeArea.getAbsolutePosition(codeArea.getCurrentParagraph(), (int) charsToRemove)),
								"");
					}
				}
		));

		// sync highlighting:
//		Subscription cleanupWhenNoLongerNeedIt = highLightTrigger
//				 .successionEnds(Duration.ofMillis(500))
//				 .subscribe(ignore -> {
//					System.out.println("Triggered highlight via end-of-succession");
//					 highlightCode();
//				 });

		// async highlighting:
		Subscription cleanupWhenNoLongerNeedIt = highLightTrigger.successionEnds(Duration.ofMillis(500))
				.supplyTask(this::highlightCodeAsync).awaitLatest(codeArea.multiPlainChanges()).filterMap(t -> {
					if (t.isSuccess()) {
						return Optional.of(t.get());
					} else {
						t.getFailure().printStackTrace();
						return Optional.empty();
					}
				}).subscribe(this::applyHighlighting);

		KeyCombination.Modifier controlKey = KeyCombination.CONTROL_DOWN;
		if (SystemUtils.IS_OS_MAC){
			controlKey = KeyCombination.META_DOWN;
		}
		val keyCombination = PlatformUtil.getControlKeyCombination(KeyCode.F);
		codeArea.setOnKeyPressed(e -> {
			if (keyCombination.match(e)) {
				focusSearch();
			}
		});
	}