/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    }
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
var _a;
import { createStyleSheet } from '../../../base/browser/dom';
import { combinedDisposable, dispose, toDisposable } from '../../../base/common/lifecycle';
import { isUndefinedOrNull } from '../../../base/common/types';
import { DefaultController, DefaultTreestyler } from '../../../base/parts/tree/browser/treeDefaults';
import { Tree } from '../../../base/parts/tree/browser/treeImpl';
import { localize } from '../../../nls';
import { IConfigurationService } from '../../configuration/common/configuration';
import { Extensions as ConfigurationExtensions } from '../../configuration/common/configurationRegistry';
import { IContextKeyService, RawContextKey } from '../../contextkey/common/contextkey';
import { createDecorator, IInstantiationService } from '../../instantiation/common/instantiation';
import { Registry } from '../../registry/common/platform';
import { attachListStyler, computeStyles, defaultListStyles } from '../../theme/common/styler';
import { IThemeService } from '../../theme/common/themeService';
export var IListService = createDecorator('listService');
var ListService = /** @class */ (function () {
    function ListService(contextKeyService) {
        this.lists = [];
        this._lastFocusedWidget = undefined;
    }
    Object.defineProperty(ListService.prototype, "lastFocusedList", {
        get: function () {
            return this._lastFocusedWidget;
        },
        enumerable: true,
        configurable: true
    });
    ListService.prototype.register = function (widget, extraContextKeys) {
        var _this = this;
        if (this.lists.some(function (l) { return l.widget === widget; })) {
            throw new Error('Cannot register the same widget multiple times');
        }
        // Keep in our lists list
        var registeredList = { widget: widget, extraContextKeys: extraContextKeys };
        this.lists.push(registeredList);
        // Check for currently being focused
        if (widget.getHTMLElement() === document.activeElement) {
            this._lastFocusedWidget = widget;
        }
        var result = combinedDisposable([
            widget.onDidFocus(function () { return _this._lastFocusedWidget = widget; }),
            toDisposable(function () { return _this.lists.splice(_this.lists.indexOf(registeredList), 1); }),
            widget.onDidDispose(function () {
                _this.lists = _this.lists.filter(function (l) { return l !== registeredList; });
                if (_this._lastFocusedWidget === widget) {
                    _this._lastFocusedWidget = undefined;
                }
            })
        ]);
        return result;
    };
    ListService = __decorate([
        __param(0, IContextKeyService)
    ], ListService);
    return ListService;
}());
export { ListService };
var RawWorkbenchListFocusContextKey = new RawContextKey('listFocus', true);
export var WorkbenchListSupportsMultiSelectContextKey = new RawContextKey('listSupportsMultiselect', true);
export var WorkbenchListHasSelectionOrFocus = new RawContextKey('listHasSelectionOrFocus', false);
export var WorkbenchListDoubleSelection = new RawContextKey('listDoubleSelection', false);
export var WorkbenchListMultiSelection = new RawContextKey('listMultiSelection', false);
function createScopedContextKeyService(contextKeyService, widget) {
    var result = contextKeyService.createScoped(widget.getHTMLElement());
    RawWorkbenchListFocusContextKey.bindTo(result);
    return result;
}
export var multiSelectModifierSettingKey = 'workbench.list.multiSelectModifier';
export var openModeSettingKey = 'workbench.list.openMode';
export var horizontalScrollingKey = 'workbench.tree.horizontalScrolling';
function useAltAsMultipleSelectionModifier(configurationService) {
    return configurationService.getValue(multiSelectModifierSettingKey) === 'alt';
}
function useSingleClickToOpen(configurationService) {
    return configurationService.getValue(openModeSettingKey) !== 'doubleClick';
}
var sharedTreeStyleSheet;
function getSharedTreeStyleSheet() {
    if (!sharedTreeStyleSheet) {
        sharedTreeStyleSheet = createStyleSheet();
    }
    return sharedTreeStyleSheet;
}
function handleTreeController(configuration, instantiationService) {
    if (!configuration.controller) {
        configuration.controller = instantiationService.createInstance(WorkbenchTreeController, {});
    }
    if (!configuration.styler) {
        configuration.styler = new DefaultTreestyler(getSharedTreeStyleSheet());
    }
    return configuration;
}
var WorkbenchTree = /** @class */ (function (_super) {
    __extends(WorkbenchTree, _super);
    function WorkbenchTree(container, configuration, options, contextKeyService, listService, themeService, instantiationService, configurationService) {
        var _this = this;
        var config = handleTreeController(configuration, instantiationService);
        var horizontalScrollMode = configurationService.getValue(horizontalScrollingKey) ? 1 /* Auto */ : 2 /* Hidden */;
        var opts = __assign({ horizontalScrollMode: horizontalScrollMode, keyboardSupport: false }, computeStyles(themeService.getTheme(), defaultListStyles), options);
        _this = _super.call(this, container, config, opts) || this;
        _this.disposables = [];
        _this.contextKeyService = createScopedContextKeyService(contextKeyService, _this);
        WorkbenchListSupportsMultiSelectContextKey.bindTo(_this.contextKeyService);
        _this.listHasSelectionOrFocus = WorkbenchListHasSelectionOrFocus.bindTo(_this.contextKeyService);
        _this.listDoubleSelection = WorkbenchListDoubleSelection.bindTo(_this.contextKeyService);
        _this.listMultiSelection = WorkbenchListMultiSelection.bindTo(_this.contextKeyService);
        _this._openOnSingleClick = useSingleClickToOpen(configurationService);
        _this._useAltAsMultipleSelectionModifier = useAltAsMultipleSelectionModifier(configurationService);
        _this.disposables.push(_this.contextKeyService, listService.register(_this), attachListStyler(_this, themeService));
        _this.disposables.push(_this.onDidChangeSelection(function () {
            var selection = _this.getSelection();
            var focus = _this.getFocus();
            _this.listHasSelectionOrFocus.set((selection && selection.length > 0) || !!focus);
            _this.listDoubleSelection.set(selection && selection.length === 2);
            _this.listMultiSelection.set(selection && selection.length > 1);
        }));
        _this.disposables.push(_this.onDidChangeFocus(function () {
            var selection = _this.getSelection();
            var focus = _this.getFocus();
            _this.listHasSelectionOrFocus.set((selection && selection.length > 0) || !!focus);
        }));
        _this.disposables.push(configurationService.onDidChangeConfiguration(function (e) {
            if (e.affectsConfiguration(openModeSettingKey)) {
                _this._openOnSingleClick = useSingleClickToOpen(configurationService);
            }
            if (e.affectsConfiguration(multiSelectModifierSettingKey)) {
                _this._useAltAsMultipleSelectionModifier = useAltAsMultipleSelectionModifier(configurationService);
            }
        }));
        return _this;
    }
    WorkbenchTree.prototype.dispose = function () {
        _super.prototype.dispose.call(this);
        this.disposables = dispose(this.disposables);
    };
    WorkbenchTree = __decorate([
        __param(3, IContextKeyService),
        __param(4, IListService),
        __param(5, IThemeService),
        __param(6, IInstantiationService),
        __param(7, IConfigurationService)
    ], WorkbenchTree);
    return WorkbenchTree;
}(Tree));
export { WorkbenchTree };
function massageControllerOptions(options) {
    if (typeof options.keyboardSupport !== 'boolean') {
        options.keyboardSupport = false;
    }
    if (typeof options.clickBehavior !== 'number') {
        options.clickBehavior = 0 /* ON_MOUSE_DOWN */;
    }
    return options;
}
var WorkbenchTreeController = /** @class */ (function (_super) {
    __extends(WorkbenchTreeController, _super);
    function WorkbenchTreeController(options, configurationService) {
        var _this = _super.call(this, massageControllerOptions(options)) || this;
        _this.configurationService = configurationService;
        _this.disposables = [];
        // if the open mode is not set, we configure it based on settings
        if (isUndefinedOrNull(options.openMode)) {
            _this.setOpenMode(_this.getOpenModeSetting());
            _this.registerListeners();
        }
        return _this;
    }
    WorkbenchTreeController.prototype.registerListeners = function () {
        var _this = this;
        this.disposables.push(this.configurationService.onDidChangeConfiguration(function (e) {
            if (e.affectsConfiguration(openModeSettingKey)) {
                _this.setOpenMode(_this.getOpenModeSetting());
            }
        }));
    };
    WorkbenchTreeController.prototype.getOpenModeSetting = function () {
        return useSingleClickToOpen(this.configurationService) ? 0 /* SINGLE_CLICK */ : 1 /* DOUBLE_CLICK */;
    };
    WorkbenchTreeController.prototype.dispose = function () {
        this.disposables = dispose(this.disposables);
    };
    WorkbenchTreeController = __decorate([
        __param(1, IConfigurationService)
    ], WorkbenchTreeController);
    return WorkbenchTreeController;
}(DefaultController));
export { WorkbenchTreeController };
var configurationRegistry = Registry.as(ConfigurationExtensions.Configuration);
configurationRegistry.registerConfiguration({
    'id': 'workbench',
    'order': 7,
    'title': localize('workbenchConfigurationTitle', "Workbench"),
    'type': 'object',
    'properties': (_a = {},
        _a[multiSelectModifierSettingKey] = {
            'type': 'string',
            'enum': ['ctrlCmd', 'alt'],
            'enumDescriptions': [
                localize('multiSelectModifier.ctrlCmd', "Maps to `Control` on Windows and Linux and to `Command` on macOS."),
                localize('multiSelectModifier.alt', "Maps to `Alt` on Windows and Linux and to `Option` on macOS.")
            ],
            'default': 'ctrlCmd',
            'description': localize({
                key: 'multiSelectModifier',
                comment: [
                    '- `ctrlCmd` refers to a value the setting can take and should not be localized.',
                    '- `Control` and `Command` refer to the modifier keys Ctrl or Cmd on the keyboard and can be localized.'
                ]
            }, "The modifier to be used to add an item in trees and lists to a multi-selection with the mouse (for example in the explorer, open editors and scm view). The 'Open to Side' mouse gestures - if supported - will adapt such that they do not conflict with the multiselect modifier.")
        },
        _a[openModeSettingKey] = {
            'type': 'string',
            'enum': ['singleClick', 'doubleClick'],
            'default': 'singleClick',
            'description': localize({
                key: 'openModeModifier',
                comment: ['`singleClick` and `doubleClick` refers to a value the setting can take and should not be localized.']
            }, "Controls how to open items in trees and lists using the mouse (if supported). For parents with children in trees, this setting will control if a single click expands the parent or a double click. Note that some trees and lists might choose to ignore this setting if it is not applicable. ")
        },
        _a[horizontalScrollingKey] = {
            'type': 'boolean',
            'default': false,
            'description': localize('horizontalScrolling setting', "Controls whether trees support horizontal scrolling in the workbench.")
        },
        _a)
});
