blob: 9433cd179a308f7a42a14259aad1f0e32f06b90b [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import * as Common from '../common/common.js'; // eslint-disable-line no-unused-vars
import * as UI from '../ui/ui.js';
/**
* @enum {number}
*/
const MessageLevelBitfield = {
Error: 0b0001,
Warning: 0b0010,
Info: 0b0100,
Debug: 0b1000,
Default: 0b0111, // Error, Warning, Info
All: 0b1111, // Error, Warning, Info, Debug
Custom: 0
};
/**
* @typedef {{
* title: string,
* value: MessageLevelBitfield,
* stringValue: string,
* selectable: boolean
* }}
*/
let SelectableLevel; // eslint-disable-line no-unused-vars
/**
* @implements {UI.SoftDropDown.Delegate<!SelectableLevel>}
*/
class MessageLevelSelector extends Common.ObjectWrapper.ObjectWrapper {
constructor(items, view) {
super();
this._items = items;
this._view = view;
this._itemMap = new Map();
this._hiddenLevels = [];
this._bitFieldValue = MessageLevelBitfield.Default;
this._savedBitFieldValue = MessageLevelBitfield.Default;
this._defaultTitle = ls`Default`;
this._customTitle = ls`Custom`;
this._allTitle = ls`All`;
}
defaultTitle() {
return this._defaultTitle;
}
// UI.SoftDropDown
setDefault(dropdown) {
dropdown.selectItem(this._items.at(0));
}
populate() {
this._items.insert(
this._items.length,
{title: this._defaultTitle, overwrite: true, stringValue: '', value: MessageLevelBitfield.Default});
this._items.insert(
this._items.length, {title: this._allTitle, overwrite: true, stringValue: '', value: MessageLevelBitfield.All});
this._items.insert(
this._items.length,
{title: ls`Error`, overwrite: false, stringValue: 'error', value: MessageLevelBitfield.Error});
this._items.insert(
this._items.length,
{title: ls`Warning`, overwrite: false, stringValue: 'warning', value: MessageLevelBitfield.Warning});
this._items.insert(
this._items.length, {title: ls`Info`, overwrite: false, stringValue: 'info', value: MessageLevelBitfield.Info});
this._items.insert(
this._items.length,
{title: ls`Debug`, overwrite: false, stringValue: 'debug', value: MessageLevelBitfield.Debug});
}
_updateCheckMarks() {
this._hiddenLevels = [];
for (const [key, item] of this._itemMap) {
if (!item.overwrite) {
if (item.element.firstChild) {
item.element.firstChild.remove();
}
if (key & this._bitFieldValue) {
item.element.createChild('div').createTextChild('✓');
} else {
this._hiddenLevels.push(item.stringValue);
}
}
}
}
/**
* @override
* @param {!SelectableLevel} item
* @return {string}
*/
titleFor(item) {
// This would make a lot more sense to have in |itemSelected|, but this
// method gets called first.
if (item.overwrite) {
this._bitFieldValue = item.value;
} else {
this._bitFieldValue ^= item.value;
}
if (this._bitFieldValue === MessageLevelBitfield.Default) {
return this._defaultTitle;
}
if (this._bitFieldValue === MessageLevelBitfield.All) {
return this._allTitle;
}
const potentialMatch = this._itemMap.get(this._bitFieldValue);
if (potentialMatch) {
return potentialMatch.title;
}
return this._customTitle;
}
/**
* @override
* @param {!SelectableLevel} item
* @return {!Element}
*/
createElementForItem(item) {
const element = document.createElementWithClass('div');
const shadowRoot = UI.Utils.createShadowRootWithCoreStyles(element, 'media/playerMessagesView.css');
const container = shadowRoot.createChild('div', 'media-messages-level-dropdown-element');
const checkBox = container.createChild('div', 'media-messages-level-dropdown-checkbox');
const text = container.createChild('span', 'media-messages-level-dropdown-text');
text.createTextChild(item.title);
item.element = checkBox;
this._itemMap.set(item.value, item);
this._updateCheckMarks();
this._view.regenerateMessageDisplayCss(this._hiddenLevels);
return element;
}
/**
* @override
* @param {!SelectableLevel} item
* @return {boolean}
*/
isItemSelectable(item) {
return true;
}
/**
* @override
* @param {?SelectableLevel} item
*/
itemSelected(item) {
this._updateCheckMarks();
this._view.regenerateMessageDisplayCss(this._hiddenLevels);
}
/**
* @override
* @param {?SelectableLevel} from
* @param {?SelectableLevel} to
* @param {?Element} fromElement
* @param {?Element} toElement
*/
highlightedItemChanged(from, to, fromElement, toElement) {
}
}
export class PlayerMessagesView extends UI.Widget.VBox {
constructor() {
super();
this.registerRequiredCSS('media/playerMessagesView.css');
this._headerPanel = this.contentElement.createChild('div', 'media-messages-header');
this._bodyPanel = this.contentElement.createChild('div', 'media-messages-body');
this._buildToolbar();
}
_buildToolbar() {
const toolbar = new UI.Toolbar.Toolbar('media-messages-toolbar', this._headerPanel);
toolbar.appendText(ls`Log Level:`);
toolbar.appendToolbarItem(this._createDropdown());
toolbar.appendSeparator();
toolbar.appendToolbarItem(this._createFilterInput());
}
_createDropdown() {
/** @type {!UI.ListModel.ListModel<!SelectableLevel>} */
const items = new UI.ListModel.ListModel();
/** @type {!MessageLevelSelector} **/
this._messageLevelSelector = new MessageLevelSelector(items, this);
/** @type {!UI.SoftDropDown.SoftDropDown<!SelectableLevel>} */
const dropDown = new UI.SoftDropDown.SoftDropDown(items, this._messageLevelSelector);
dropDown.setRowHeight(18);
this._messageLevelSelector.populate();
this._messageLevelSelector.setDefault(dropDown);
const dropDownItem = new UI.Toolbar.ToolbarItem(dropDown.element);
dropDownItem.element.classList.add('toolbar-has-dropdown');
dropDownItem.setEnabled(true);
dropDownItem.setTitle(this._messageLevelSelector.defaultTitle());
return dropDownItem;
}
_createFilterInput() {
const filterInput = new UI.Toolbar.ToolbarInput(ls`filter log messages`);
filterInput.addEventListener(UI.Toolbar.ToolbarInput.Event.TextChanged, this._filterByString, this);
return filterInput;
}
regenerateMessageDisplayCss(hiddenLevels) {
const messages = this._bodyPanel.getElementsByClassName('media-messages-message-container');
for (const message of messages) {
if (this._matchesHiddenLevels(message, hiddenLevels)) {
message.classList.add('media-messages-message-unselected');
} else {
message.classList.remove('media-messages-message-unselected');
}
}
}
_matchesHiddenLevels(element, hiddenLevels) {
for (const level of hiddenLevels) {
if (element.classList.contains('media-message-' + level)) {
return true;
}
}
return false;
}
_filterByString(userStringData) {
const userString = userStringData.data;
const messages = this._bodyPanel.getElementsByClassName('media-messages-message-container');
for (const message of messages) {
if (userString === '') {
message.classList.remove('media-messages-message-filtered');
} else if (message.textContent.includes(userString)) {
message.classList.remove('media-messages-message-filtered');
} else {
message.classList.add('media-messages-message-filtered');
}
}
}
addMessage(message) {
const container =
this._bodyPanel.createChild('div', 'media-messages-message-container media-message-' + message.level);
container.createTextChild(message.message);
}
}