<commit_before>// Copyright (c) 2013, Google Inc. Please see the AUTHORS file for details.
// All rights reserved. Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/**
 * This class implements the controller for the list of files.
 */
library spark.ui.widgets.files_controller;

import 'dart:convert' show JSON;
import 'dart:html' as html;

import 'package:bootjack/bootjack.dart' as bootjack;

import 'files_controller_delegate.dart';
import 'utils/html_utils.dart';
import 'widgets/file_item_cell.dart';
import 'widgets/listview_cell.dart';
import 'widgets/treeview.dart';
import 'widgets/treeview_delegate.dart';
import '../actions.dart';
import '../preferences.dart' as preferences;
import '../workspace.dart';

class FilesController implements TreeViewDelegate {
  // TreeView that's used to show the workspace.
  TreeView _treeView;
  // Workspace that references all the resources.
  Workspace _workspace;
  // List of top-level resources.
  List<Resource> _files;
  // Implements callbacks required for the FilesController.
  FilesControllerDelegate _delegate;
  // Map of nodeUID to the resources of the workspace for a quick lookup.
  Map<String, Resource> _filesMap;
  // Cache of sorted children of nodes.
  Map<String, List<String>> _childrenCache;
  // Preferences where to store tree expanded/collapsed state.
  preferences.PreferenceStore localPrefs = preferences.localStore;

  FilesController(Workspace workspace,
                  FilesControllerDelegate delegate,
                  html.Element fileViewArea) {
    _workspace = workspace;
    _delegate = delegate;
    _files = [];
    _filesMap = {};
    _childrenCache = {};

    _treeView = new TreeView(fileViewArea, this);
    _treeView.dropEnabled = true;
    _treeView.draggingEnabled = true;

    _workspace.whenAvailable().then((_) {
      _addAllFiles();
    });

    _workspace.onResourceChange.listen((event) {
      _processEvents(event);
    });
  }

  bool isFileSelected(Resource file) {
    return _treeView.selection.contains(file.path);
  }

  void selectFile(Resource file, {bool forceOpen: false}) {
    if (_files.isEmpty) {
      return;
    }

    List parents = _collectParents(file, []);

    parents.forEach((Container container) {
      if (!_treeView.isNodeExpanded(container.path)) {
        _treeView.setNodeExpanded(container.path, true);
      }
    });

    _treeView.selection = [file.path];
    if (file is File) {
      _delegate.selectInEditor(file, forceOpen: forceOpen);
    }
  }

  void selectFirstFile({bool forceOpen: false}) {
    if (_files.isEmpty) {
      return;
    }
    selectFile(_files[0], forceOpen: forceOpen);
  }

  // Implementation of [TreeViewDelegate] interface.

  bool treeViewHasChildren(TreeView view, String nodeUID) {
    if (nodeUID == null) {
      return true;
    } else {
      return (_filesMap[nodeUID] is Container);
    }
  }

  int treeViewNumberOfChildren(TreeView view, String nodeUID) {
    if (nodeUID == null) {
      return _files.length;
    } else if (_filesMap[nodeUID] is Container) {
      _cacheChildren(nodeUID);
      return _childrenCache[nodeUID].length;
    } else {
      return 0;
    }
  }

  String treeViewChild(TreeView view, String nodeUID, int childIndex) {
    if (nodeUID == null) {
      return _files[childIndex].path;
    } else {
      _cacheChildren(nodeUID);
      return _childrenCache[nodeUID][childIndex];
    }
  }

  List<Resource> getSelection() {
    List resources = [];
    _treeView.selection.forEach((String nodeUID) {
        resources.add(_filesMap[nodeUID]);
     });
    return resources;
  }

  ListViewCell treeViewCellForNode(TreeView view, String nodeUID) {
    Resource resource = _filesMap[nodeUID];
    FileItemCell cell = new FileItemCell(resource.name);
    if (resource is Folder) {
      cell.acceptDrop = true;
    }
    cell.menuElement.onClick.listen(
        (e) => _handleMenuClick(cell, resource, e));
    return cell;
  }

  int treeViewHeightForNode(TreeView view, String nodeUID) => 20;

  void treeViewSelectedChanged(TreeView view,
                               List<String> nodeUIDs) {
  }

  bool treeViewRowClicked(html.Event event, String uid) {
    if (uid == null) {
      return true;
    }

    Resource resource = _filesMap[uid];
    if (resource is File) {
      bool altKeyPressed = false;
      if (event != null) {
        altKeyPressed = ((event as html.MouseEvent).altKey);
      }
      
      // Open in editor only if alt key or no modifier key is down.  If alt key
      // is pressed, it will open a new tab.
      if (!(event as html.MouseEvent).shiftKey
          && !(event as html.MouseEvent).ctrlKey
          && !(event as html.MouseEvent).metaKey) {
        _delegate.selectInEditor(resource, forceOpen: true,
            replaceCurrent: !altKeyPressed);
      }
    }
    
    return true;
  }

  void treeViewDoubleClicked(TreeView view,
                             List<String> nodeUIDs,
                             html.Event event) {
    if (nodeUIDs.length == 1 && _filesMap[nodeUIDs.first] is Container) {
      view.toggleNodeExpanded(nodeUIDs.first, animated: true);
    }
  }

  void treeViewContextMenu(TreeView view,
                           List<String> nodeUIDs,
                           String nodeUID,
                           html.Event event) {
    cancelEvent(event);
    Resource resource = _filesMap[nodeUID];
    FileItemCell cell = new FileItemCell(resource.name);
    _showMenuForEvent(cell, event, resource);
  }

  String treeViewDropEffect(TreeView view,
                            html.DataTransfer dataTransfer,
                            String nodeUID) {
    if (dataTransfer.types.contains('Files')) {
      if (nodeUID == null) {
        // Importing to top-level is not allowed for now.
        return "none";
      } else {
        // Import files into a folder.<commit_msg>Reorganized treeViewSelectedChanged and treeViewRowClicked to separate responsibilities.<commit_after>// Copyright (c) 2013, Google Inc. Please see the AUTHORS file for details.
// All rights reserved. Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/**
 * This class implements the controller for the list of files.
 */
library spark.ui.widgets.files_controller;

import 'dart:convert' show JSON;
import 'dart:html' as html;

import 'package:bootjack/bootjack.dart' as bootjack;

import 'files_controller_delegate.dart';
import 'utils/html_utils.dart';
import 'widgets/file_item_cell.dart';
import 'widgets/listview_cell.dart';
import 'widgets/treeview.dart';
import 'widgets/treeview_delegate.dart';
import '../actions.dart';
import '../preferences.dart' as preferences;
import '../workspace.dart';

class FilesController implements TreeViewDelegate {
  // TreeView that's used to show the workspace.
  TreeView _treeView;
  // Workspace that references all the resources.
  Workspace _workspace;
  // List of top-level resources.
  List<Resource> _files;
  // Implements callbacks required for the FilesController.
  FilesControllerDelegate _delegate;
  // Map of nodeUID to the resources of the workspace for a quick lookup.
  Map<String, Resource> _filesMap;
  // Cache of sorted children of nodes.
  Map<String, List<String>> _childrenCache;
  // Preferences where to store tree expanded/collapsed state.
  preferences.PreferenceStore localPrefs = preferences.localStore;

  FilesController(Workspace workspace,
                  FilesControllerDelegate delegate,
                  html.Element fileViewArea) {
    _workspace = workspace;
    _delegate = delegate;
    _files = [];
    _filesMap = {};
    _childrenCache = {};

    _treeView = new TreeView(fileViewArea, this);
    _treeView.dropEnabled = true;
    _treeView.draggingEnabled = true;

    _workspace.whenAvailable().then((_) {
      _addAllFiles();
    });

    _workspace.onResourceChange.listen((event) {
      _processEvents(event);
    });
  }

  bool isFileSelected(Resource file) {
    return _treeView.selection.contains(file.path);
  }

  void selectFile(Resource file, {bool forceOpen: false}) {
    if (_files.isEmpty) {
      return;
    }

    List parents = _collectParents(file, []);

    parents.forEach((Container container) {
      if (!_treeView.isNodeExpanded(container.path)) {
        _treeView.setNodeExpanded(container.path, true);
      }
    });

    _treeView.selection = [file.path];
    if (file is File) {
      _delegate.selectInEditor(file, forceOpen: forceOpen);
    }
  }

  void selectFirstFile({bool forceOpen: false}) {
    if (_files.isEmpty) {
      return;
    }
    selectFile(_files[0], forceOpen: forceOpen);
  }

  // Implementation of [TreeViewDelegate] interface.

  bool treeViewHasChildren(TreeView view, String nodeUID) {
    if (nodeUID == null) {
      return true;
    } else {
      return (_filesMap[nodeUID] is Container);
    }
  }

  int treeViewNumberOfChildren(TreeView view, String nodeUID) {
    if (nodeUID == null) {
      return _files.length;
    } else if (_filesMap[nodeUID] is Container) {
      _cacheChildren(nodeUID);
      return _childrenCache[nodeUID].length;
    } else {
      return 0;
    }
  }

  String treeViewChild(TreeView view, String nodeUID, int childIndex) {
    if (nodeUID == null) {
      return _files[childIndex].path;
    } else {
      _cacheChildren(nodeUID);
      return _childrenCache[nodeUID][childIndex];
    }
  }

  List<Resource> getSelection() {
    List resources = [];
    _treeView.selection.forEach((String nodeUID) {
        resources.add(_filesMap[nodeUID]);
     });
    return resources;
  }

  ListViewCell treeViewCellForNode(TreeView view, String nodeUID) {
    Resource resource = _filesMap[nodeUID];
    FileItemCell cell = new FileItemCell(resource.name);
    if (resource is Folder) {
      cell.acceptDrop = true;
    }
    cell.menuElement.onClick.listen(
        (e) => _handleMenuClick(cell, resource, e));
    return cell;
  }

  int treeViewHeightForNode(TreeView view, String nodeUID) => 20;

  void treeViewSelectedChanged(TreeView view,
                               List<String> nodeUIDs) {
    Resource resource = _filesMap[nodeUIDs.first];
    if (resource is File) {
      _delegate.selectInEditor(resource, forceOpen: true, replaceCurrent: true);
    }
  }

  bool treeViewRowClicked(html.MouseEvent event, String uid) {
    if (uid == null) {
      return true;
    }

    Resource resource = _filesMap[uid];
    if (resource is File) {
      bool altKeyPressed = event.altKey;
      bool shiftKeyPressed = event.shiftKey;
      bool ctrlKeyPressed = event.ctrlKey || event.metaKey;

      // Open in editor only if alt key or no modifier key is down.  If alt key
      // is pressed, it will open a new tab.
      if (altKeyPressed && !shiftKeyPressed && !ctrlKeyPressed) {
        _delegate.selectInEditor(resource, forceOpen: true,
            replaceCurrent: false);
        return false;
      }
    }

    return true;
  }

  void treeViewDoubleClicked(TreeView view,
                             List<String> nodeUIDs,
                             html.Event event) {
    if (nodeUIDs.length == 1 && _filesMap[nodeUIDs.first] is Container) {
      view.toggleNodeExpanded(nodeUIDs.first, animated: true);
    }
  }

  void treeViewContextMenu(TreeView view,
                           List<String> nodeUIDs,
                           String nodeUID,
                           html.Event event) {
    cancelEvent(event);
    Resource resource = _filesMap[nodeUID];
    FileItemCell cell = new FileItemCell(resource.name);
    _showMenuForEvent(cell, event, resource);
  }

  String treeViewDropEffect(TreeView view,
                            html.DataTransfer dataTransfer,
                            String nodeUID) {
    if (dataTransfer.types.contains('Files')) {
      if (nodeUID == null) {
        // Importing to top-level is not allowed for now.
        return "none";
      } else {
        // Import files into a folder.
{'fraction_non_alphanumeric': 0.10075713453698311, 'fraction_numerical': 0.001497628754472086, 'mean_word_length': 2.7656641604010024, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 23, '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': '2347625', 'n_tokens_mistral': 3527, 'n_tokens_neox': 3444, 'n_words': 911}