<commit_before>/*
 * Copyright (C) 2017 EfficiOS Inc., <NAME> <<EMAIL>>
 *
 * All rights reserved. This program and the accompanying materials are
 * made available under the terms of the Eclipse Public License v1.0 which
 * accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 */

package org.lttng.scope.tmf2.views.ui.timeline.widgets.timegraph;

import static java.util.Objects.requireNonNull;

import java.util.List;
import java.util.stream.Collectors;

import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
import org.lttng.scope.tmf2.views.core.timegraph.model.render.tree.TimeGraphTreeElement;
import org.lttng.scope.tmf2.views.core.timegraph.model.render.tree.TimeGraphTreeRender;
import org.lttng.scope.tmf2.views.ui.jfx.JfxUtils;

import com.sun.javafx.scene.control.skin.TreeViewSkin;
import com.sun.javafx.scene.control.skin.VirtualFlow;

import javafx.application.Platform;
import javafx.beans.binding.DoubleBinding;
import javafx.beans.property.ObjectProperty;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.scene.control.ScrollBar;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.BorderPane;

/**
 * Extension of {@link TreeView} which exposes some of its components, like
 * Scrollbars.
 *
 * It also supports specifying a static visibility modifier for the scrollbars,
 * similar to a {@link ScrollPane}'s bar policy.
 *
 * This class makes us of some internal, non-API JavaFX objects and methods and
 * thus, might break once the codebase moves to a newer version.
 *
 * @author <NAME>
 */
@SuppressWarnings("restriction")
public class TimeGraphWidgetTreeArea extends BorderPane {

    private final double fEntryHeight;

    private final TreeAreaTreeView fTreeView;

    /**
     * Constructor
     */
    public TimeGraphWidgetTreeArea(double entryHeight, ObjectProperty<@Nullable ITmfTrace> targetTraceProperty) {
        TreeItem<String> treeRoot = new TreeItem<>();
        treeRoot.setExpanded(true);

        TreeAreaTreeView treeView = new TreeAreaTreeView(treeRoot);
        treeView.setFixedCellSize(entryHeight);

        /*
         * Instead of using the TreeView's scrollbar, whose visibility and size are
         * managed internally by the super-class, we will instantiate our own and will
         * bind its important properties to the "real" one.
         */
        ScrollBar dummyScrollBar = new ScrollBar();
        dummyScrollBar.setOrientation(Orientation.HORIZONTAL);
        ScrollBar realHScrollBar = treeView.getHBar();
        dummyScrollBar.valueProperty().bindBidirectional(realHScrollBar.valueProperty());
        dummyScrollBar.visibleAmountProperty().bind(treeView.widthProperty().divide(2));

        /* Add the "children" to this BorderPane */
        setCenter(treeView);
        setBottom(dummyScrollBar);

        treeView.setCellFactory(view -> new TreeAreaTreeViewCell());

        fEntryHeight = entryHeight;
        fTreeView = treeView;
    }

    public void clear() {
        fTreeView.setRoot(null);
    }

    public ScrollBar getVerticalScrollBar() {
        return fTreeView.getVBar();
    }

    public DoubleBinding currentHeightProperty() {
        return fTreeView.expandedItemCountProperty().multiply((fEntryHeight));
    }

    public void updateTreeContents(TimeGraphTreeRender treeRender) {
        TreeItem<String> newRoot = getTreeItemForElement(treeRender.getRootElement());
        newRoot.setExpanded(true);
        Platform.runLater(() -> {
            fTreeView.setRoot(newRoot);
        });
    }

    private static TreeItem<String> getTreeItemForElement(TimeGraphTreeElement element) {
        TreeItem<String> treeItem = new TreeItem<>(element.getName());
        List<TreeItem<String>> childItems = element.getChildElements().stream()
                .map(treeElem -> getTreeItemForElement(treeElem))
                .collect(Collectors.toList());
        if (!childItems.isEmpty()) {
            treeItem.getChildren().addAll(childItems);
        }
        return treeItem;
    }

    // ------------------------------------------------------------------------
    // Methods related to the Tree area
    // ------------------------------------------------------------------------

    private static List<TreeItem<String>> getTreeItemNames(TimeGraphTreeRender treeRender) {
        return treeRender.getAllTreeElements().stream()
                .map(elem -> new TreeItem<>(elem.getName()))
                .collect(Collectors.toList());
    }

    // TODO Background could be re-added by salvaging this
//    private static Node prepareTreeContents(TimeGraphTreeRender treeRender, ReadOnlyDoubleProperty widthProperty) {<commit_msg>timegraph: Disable the collapsing of all tree items<commit_after>/*
 * Copyright (C) 2017 EfficiOS Inc., <NAME> <<EMAIL>>
 *
 * All rights reserved. This program and the accompanying materials are
 * made available under the terms of the Eclipse Public License v1.0 which
 * accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 */

package org.lttng.scope.tmf2.views.ui.timeline.widgets.timegraph;

import static java.util.Objects.requireNonNull;

import java.util.List;
import java.util.stream.Collectors;

import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
import org.lttng.scope.tmf2.views.core.timegraph.model.render.tree.TimeGraphTreeElement;
import org.lttng.scope.tmf2.views.core.timegraph.model.render.tree.TimeGraphTreeRender;
import org.lttng.scope.tmf2.views.ui.jfx.JfxUtils;

import com.sun.javafx.scene.control.skin.TreeViewSkin;
import com.sun.javafx.scene.control.skin.VirtualFlow;

import javafx.application.Platform;
import javafx.beans.binding.DoubleBinding;
import javafx.beans.property.ObjectProperty;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.scene.control.ScrollBar;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.BorderPane;

/**
 * Extension of {@link TreeView} which exposes some of its components, like
 * Scrollbars.
 *
 * It also supports specifying a static visibility modifier for the scrollbars,
 * similar to a {@link ScrollPane}'s bar policy.
 *
 * This class makes us of some internal, non-API JavaFX objects and methods and
 * thus, might break once the codebase moves to a newer version.
 *
 * @author <NAME>
 */
@SuppressWarnings("restriction")
public class TimeGraphWidgetTreeArea extends BorderPane {

    private final double fEntryHeight;

    private final TreeAreaTreeView fTreeView;

    /**
     * Constructor
     */
    public TimeGraphWidgetTreeArea(double entryHeight, ObjectProperty<@Nullable ITmfTrace> targetTraceProperty) {
        TreeItem<String> treeRoot = new TreeItem<>();
        treeRoot.setExpanded(true);

        TreeAreaTreeView treeView = new TreeAreaTreeView(treeRoot);
        treeView.setFixedCellSize(entryHeight);

        /*
         * Instead of using the TreeView's scrollbar, whose visibility and size are
         * managed internally by the super-class, we will instantiate our own and will
         * bind its important properties to the "real" one.
         */
        ScrollBar dummyScrollBar = new ScrollBar();
        dummyScrollBar.setOrientation(Orientation.HORIZONTAL);
        ScrollBar realHScrollBar = treeView.getHBar();
        dummyScrollBar.valueProperty().bindBidirectional(realHScrollBar.valueProperty());
        dummyScrollBar.visibleAmountProperty().bind(treeView.widthProperty().divide(2));

        /* Add the "children" to this BorderPane */
        setCenter(treeView);
        setBottom(dummyScrollBar);

        treeView.setCellFactory(view -> new TreeAreaTreeViewCell());

        fEntryHeight = entryHeight;
        fTreeView = treeView;
    }

    public void clear() {
        fTreeView.setRoot(null);
    }

    public ScrollBar getVerticalScrollBar() {
        return fTreeView.getVBar();
    }

    public DoubleBinding currentHeightProperty() {
        return fTreeView.expandedItemCountProperty().multiply((fEntryHeight));
    }

    public void updateTreeContents(TimeGraphTreeRender treeRender) {
        TreeItem<String> newRoot = getTreeItemForElement(treeRender.getRootElement());
        newRoot.setExpanded(true);
        Platform.runLater(() -> {
            fTreeView.setRoot(newRoot);
        });
    }

    private static TreeItem<String> getTreeItemForElement(TimeGraphTreeElement element) {
        TreeItem<String> treeItem = new TreeItem<>(element.getName());
        List<TreeItem<String>> childItems = element.getChildElements().stream()
                .map(treeElem -> getTreeItemForElement(treeElem))
                .collect(Collectors.toList());
        if (!childItems.isEmpty()) {
            treeItem.getChildren().addAll(childItems);
        }

        // TODO Correctly manage sub-trees being expanded. Disallow it for now.
        treeItem.setExpanded(true);
        treeItem.addEventHandler(TreeItem.branchCollapsedEvent(),
                event -> event.getTreeItem().setExpanded(true));

        return treeItem;
    }

    // ------------------------------------------------------------------------
    // Methods related to the Tree area
    // ------------------------------------------------------------------------

    private static List<TreeItem<String>> getTreeItemNames(TimeGraphTreeRender treeRender) {
        return treeRender.getAllTreeElements().stream()
                .map(elem -> new TreeItem<>(elem.getName()))
                .collect(Collectors.toList());
    }

    // TODO Background could be re-added by salvaging this
//    private static Node prepareTreeContents(TimeGraphTreeRender treeRender, ReadOnlyDoubleProperty widthProperty) {
{'fraction_non_alphanumeric': 0.12431626056688215, 'fraction_numerical': 0.0025857782197911488, 'mean_word_length': 3.1230012300123002, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 44, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4050981', 'n_tokens_mistral': 2768, 'n_tokens_neox': 2673, 'n_words': 625}