<commit_before>import { ElementRef } from '@angular/core';
import { TreeModel } from './tree.model';
import { TreeOptions } from './tree-options.model';
import { ITreeNode } from '../defs/api';
import { TREE_EVENTS } from '../constants/events';
import { deprecated } from '../deprecated';

import * as _ from 'lodash';

export class TreeNode implements ITreeNode {
  get isHidden() { return this.getField('isHidden') };
  set isHidden(value) { this.setField('isHidden', value) };
  get isExpanded() { return this.treeModel.isExpanded(this) };
  get isActive() { return this.treeModel.isActive(this) };
  get isFocused() { return this.treeModel.isNodeFocused(this) };

  level: number;
  path: string[];
  elementRef:ElementRef;
  children: TreeNode[];

  private _originalNode: any;
  get originalNode() { return this._originalNode };

  constructor(public data:any, public parent:TreeNode, public treeModel:TreeModel) {
    this.id = this.id || uuid(); // Make sure there's a unique ID
    this.level = this.parent ? this.parent.level + 1 : 0;
    this.path = this.parent ? [...this.parent.path, this.id] : [];

    if (this.getField('children')) {
      this._initChildren();
    }

    this.allowDrop = this.allowDrop.bind(this);
  }

  // helper get functions:
  get hasChildren():boolean {
    return !!(this.data.hasChildren || (this.children && this.children.length > 0));
  }
  get isCollapsed():boolean { return !this.isExpanded }
  get isLeaf():boolean { return !this.hasChildren }
  get isRoot():boolean { return this.parent.data.virtual }
  get realParent():TreeNode { return this.isRoot ? null : this.parent }

  // proxy functions:
  get options(): TreeOptions { return this.treeModel.options }
  fireEvent(event) { this.treeModel.fireEvent(event) }
  get context():any { return this.options.context }

  // field accessors:
  get displayField() {
    return this.getField('display');
  }

  get id() {
    return this.getField('id');
  }

  set id(value) {
    this.setField('id', value);
  }

  getField(key) {
    return this.data[this.options[`${key}Field`]];
  }

  setField(key, value) {
    this.data[this.options[`${key}Field`]] = value;
  }

  // traversing:
  _findAdjacentSibling(steps, skipHidden = false) {
    const index = this.getIndexInParent(skipHidden);
    return this._getParentsChildren(skipHidden)[index + steps];
  }

  findNextSibling(skipHidden = false) {
    return this._findAdjacentSibling(+1, skipHidden);
  }

  findPreviousSibling(skipHidden = false) {
    return this._findAdjacentSibling(-1, skipHidden);
  }

  getVisibleChildren() {
    return (this.children || []).filter((node) => !node.isHidden);
  }

  getFirstChild(skipHidden = false) {
    let children = skipHidden ? this.getVisibleChildren() : this.children;

    return _.first(children || []);
  }

  getLastChild(skipHidden = false) {
    let children = skipHidden ? this.getVisibleChildren() : this.children;

    return _.last(children || []);
  }

  findNextNode(goInside = true, skipHidden = false) {
    return goInside && this.isExpanded && this.getFirstChild(skipHidden) ||
           this.findNextSibling(skipHidden) ||
           this.parent && this.parent.findNextNode(false, skipHidden);
  }

  findPreviousNode(skipHidden = false) {
    let previousSibling = this.findPreviousSibling(skipHidden);
    if (!previousSibling) {
      return this.realParent
    }
    return previousSibling._getLastOpenDescendant(skipHidden);
  }

  _getLastOpenDescendant(skipHidden = false) {
    const lastChild = this.getLastChild(skipHidden);
    return (this.isCollapsed || !lastChild)
      ? this
      : lastChild._getLastOpenDescendant(skipHidden);
  }

  private _getParentsChildren(skipHidden = false):any[] {
    const children = this.parent &&
      (skipHidden ? this.parent.getVisibleChildren() : this.parent.children);

    return children || [];
  }

  private getIndexInParent(skipHidden = false) {
    return this._getParentsChildren(skipHidden).indexOf(this);
  }

  isDescendantOf(node:TreeNode) {
    if (this === node) return true;
    else return this.parent && this.parent.isDescendantOf(node);
  }

  getNodePadding():string {
    return this.options.levelPadding * (this.level - 1) + 'px';
  }

  getClass():string {
    return this.options.nodeClass(this);
  }

  onDrop($event) {
    this.mouseAction('drop', $event.event, {
      from: $event.element,
      to: { parent: this, index: 0 }
    });
  }

  allowDrop(element) {
    return this.options.allowDrop(element, { parent: this, index: 0 });
  }


  // helper methods:
  loadChildren() {
    if (!this.options.getChildren) {
      throw new Error('Node doesn\'t have children, or a getChildren method');
    }
    Promise.resolve(this.options.getChildren(this))
      .then((children) => {
        if (children) {
          this.setField('children', children);
          this._initChildren();
          this.children.forEach((child) => {
            if (child.getField('isExpanded') && child.hasChildren) {
              child.expand();
            }
          });

        }
      });
  }

  expand() {
    if (!this.isExpanded) {
      this.toggleExpanded();
    }

    return this;
  }

  collapse() {
    if (this.isExpanded) {
      this.toggleExpanded();
    }

    return this;
  }

  ensureVisible() {
    if (this.realParent) {
      this.realParent.expand();
      this.realParent.ensureVisible();
    }

    return this;
  }

  toggle() {
    deprecated('toggle', 'toggleExpanded');
    return this.toggleExpanded();
  }

  toggleExpanded() {
    this.setIsExpanded(!this.isExpanded);
    this.fireEvent({ eventName: TREE_EVENTS.onToggle, warning: 'this event is deprecated, please use onToggleExpanded instead', node: this, isExpanded: this.isExpanded });
    this.fireEvent({ eventName: TREE_EVENTS.onToggleExpanded, node: this, isExpanded: this.isExpanded });

    return this;
  }

  setIsExpanded(value) {
    this.treeModel.setExpandedNode(this, value);

    if (!this.children && this.hasChildren && value) {
      this.loadChildren();
    }

    return this;
  };

  setIsActive(value, multi = false) {
    this.treeModel.setActiveNode(this, value, multi);
    if (value) {
      this.focus();
    }

    return this;
  }

  toggleActivated(multi = false) {
    this.setIsActive(!this.isActive, multi);
<commit_msg>- return promise from expand-method, so that we can open a deep path into the tree<commit_after>import { ElementRef } from '@angular/core';
import { TreeModel } from './tree.model';
import { TreeOptions } from './tree-options.model';
import { ITreeNode } from '../defs/api';
import { TREE_EVENTS } from '../constants/events';
import { deprecated } from '../deprecated';

import * as _ from 'lodash';

export class TreeNode implements ITreeNode {
  get isHidden() { return this.getField('isHidden') };
  set isHidden(value) { this.setField('isHidden', value) };
  get isExpanded() { return this.treeModel.isExpanded(this) };
  get isActive() { return this.treeModel.isActive(this) };
  get isFocused() { return this.treeModel.isNodeFocused(this) };

  level: number;
  path: string[];
  elementRef:ElementRef;
  children: TreeNode[];

  private _originalNode: any;
  get originalNode() { return this._originalNode };

  constructor(public data:any, public parent:TreeNode, public treeModel:TreeModel) {
    this.id = this.id || uuid(); // Make sure there's a unique ID
    this.level = this.parent ? this.parent.level + 1 : 0;
    this.path = this.parent ? [...this.parent.path, this.id] : [];

    if (this.getField('children')) {
      this._initChildren();
    }

    this.allowDrop = this.allowDrop.bind(this);
  }

  // helper get functions:
  get hasChildren():boolean {
    return !!(this.data.hasChildren || (this.children && this.children.length > 0));
  }
  get isCollapsed():boolean { return !this.isExpanded }
  get isLeaf():boolean { return !this.hasChildren }
  get isRoot():boolean { return this.parent.data.virtual }
  get realParent():TreeNode { return this.isRoot ? null : this.parent }

  // proxy functions:
  get options(): TreeOptions { return this.treeModel.options }
  fireEvent(event) { this.treeModel.fireEvent(event) }
  get context():any { return this.options.context }

  // field accessors:
  get displayField() {
    return this.getField('display');
  }

  get id() {
    return this.getField('id');
  }

  set id(value) {
    this.setField('id', value);
  }

  getField(key) {
    return this.data[this.options[`${key}Field`]];
  }

  setField(key, value) {
    this.data[this.options[`${key}Field`]] = value;
  }

  // traversing:
  _findAdjacentSibling(steps, skipHidden = false) {
    const index = this.getIndexInParent(skipHidden);
    return this._getParentsChildren(skipHidden)[index + steps];
  }

  findNextSibling(skipHidden = false) {
    return this._findAdjacentSibling(+1, skipHidden);
  }

  findPreviousSibling(skipHidden = false) {
    return this._findAdjacentSibling(-1, skipHidden);
  }

  getVisibleChildren() {
    return (this.children || []).filter((node) => !node.isHidden);
  }

  getFirstChild(skipHidden = false) {
    let children = skipHidden ? this.getVisibleChildren() : this.children;

    return _.first(children || []);
  }

  getLastChild(skipHidden = false) {
    let children = skipHidden ? this.getVisibleChildren() : this.children;

    return _.last(children || []);
  }

  findNextNode(goInside = true, skipHidden = false) {
    return goInside && this.isExpanded && this.getFirstChild(skipHidden) ||
           this.findNextSibling(skipHidden) ||
           this.parent && this.parent.findNextNode(false, skipHidden);
  }

  findPreviousNode(skipHidden = false) {
    let previousSibling = this.findPreviousSibling(skipHidden);
    if (!previousSibling) {
      return this.realParent
    }
    return previousSibling._getLastOpenDescendant(skipHidden);
  }

  _getLastOpenDescendant(skipHidden = false) {
    const lastChild = this.getLastChild(skipHidden);
    return (this.isCollapsed || !lastChild)
      ? this
      : lastChild._getLastOpenDescendant(skipHidden);
  }

  private _getParentsChildren(skipHidden = false):any[] {
    const children = this.parent &&
      (skipHidden ? this.parent.getVisibleChildren() : this.parent.children);

    return children || [];
  }

  private getIndexInParent(skipHidden = false) {
    return this._getParentsChildren(skipHidden).indexOf(this);
  }

  isDescendantOf(node:TreeNode) {
    if (this === node) return true;
    else return this.parent && this.parent.isDescendantOf(node);
  }

  getNodePadding():string {
    return this.options.levelPadding * (this.level - 1) + 'px';
  }

  getClass():string {
    return this.options.nodeClass(this);
  }

  onDrop($event) {
    this.mouseAction('drop', $event.event, {
      from: $event.element,
      to: { parent: this, index: 0 }
    });
  }

  allowDrop(element) {
    return this.options.allowDrop(element, { parent: this, index: 0 });
  }


  // helper methods:
  loadChildren() {
    if (!this.options.getChildren) {
      throw new Error('Node doesn\'t have children, or a getChildren method');
    }
    return Promise.resolve(this.options.getChildren(this))
      .then((children) => {
        if (children) {
          this.setField('children', children);
          this._initChildren();
          this.children.forEach((child) => {
            if (child.getField('isExpanded') && child.hasChildren) {
              child.expand();
            }
          });

        }
      });
  }

  expand() {
    if (!this.isExpanded) {
      return this.toggleExpanded();
    }

    return Promise.resolve();
  }

  collapse() {
    if (this.isExpanded) {
      this.toggleExpanded();
    }

    return this;
  }

  ensureVisible() {
    if (this.realParent) {
      this.realParent.expand();
      this.realParent.ensureVisible();
    }

    return this;
  }

  toggle() {
    deprecated('toggle', 'toggleExpanded');
    return this.toggleExpanded();
  }

  toggleExpanded() {
    return this.setIsExpanded(!this.isExpanded)
      .then(() => {
        this.fireEvent({ eventName: TREE_EVENTS.onToggle, warning: 'this event is deprecated, please use onToggleExpanded instead', node: this, isExpanded: this.isExpanded });
        this.fireEvent({ eventName: TREE_EVENTS.onToggleExpanded, node: this, isExpanded: this.isExpanded });
      });
  }

  setIsExpanded(value) {
    this.treeModel.setExpandedNode(this, value);

    let promise = null;
    if (!this.children && this.hasChildren && value) {
      promise = this.loadChildren();
    }

    return promise ? promise : Promise.resolve();
  };

  setIsActive(value, multi = false) {
    this.treeModel.setActiveNode(this, value, multi);
    if (value) {
      this.focus();
    }

    return this;
  }

  toggleActivated(multi = false) {
    this.setIsActive(!this.isActive, multi);

{'fraction_non_alphanumeric': 0.1411544753447067, 'fraction_numerical': 0.0012463971332865934, 'mean_word_length': 3.2893417975275643, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 12, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '7562747', 'n_tokens_mistral': 4071, 'n_tokens_neox': 3977, 'n_words': 801}