1// Copyright (C) 2022 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15import m from 'mithril'; 16 17import {Engine} from '../trace_processor/engine'; 18 19export interface NewBottomTabArgs<Config> { 20 engine: Engine; 21 tag?: string; 22 uuid: string; 23 config: Config; 24} 25 26// An interface representing a bottom tab displayed on the panel in the bottom 27// of the ui (e.g. "Current Selection"). 28// 29// The implementations of this class are provided by different plugins, which 30// register the implementations with bottomTabRegistry, keyed by a unique name 31// for each type of BottomTab. 32// 33// Lifetime: the instances of this class are owned by BottomTabPanel and exist 34// for as long as a tab header is shown to the user in the bottom tab list (with 35// minor exceptions, like a small grace period between when the tab is related). 36// 37// BottomTab implementations should pass the unique identifier(s) for the 38// content displayed via the |Config| and fetch additional details via Engine 39// instead of relying on getting the data from the global storage. For example, 40// for tabs corresponding to details of the selected objects on a track, a new 41// BottomTab should be created for each new selection. 42export abstract class BottomTabBase<Config = {}> { 43 // Config for this details panel. Should be serializable. 44 protected readonly config: Config; 45 // Engine for running queries and fetching additional data. 46 protected readonly engine: Engine; 47 // Optional tag, which is used to ensure that only one tab 48 // with the same tag can exist - adding a new tab with the same tag 49 // (e.g. 'current_selection') would close the previous one. This 50 // also can be used to close existing tab. 51 readonly tag?: string; 52 // Unique id for this details panel. Can be used to close previously opened 53 // panel. 54 readonly uuid: string; 55 56 constructor(args: NewBottomTabArgs<Config>) { 57 this.config = args.config; 58 this.engine = args.engine; 59 this.tag = args.tag; 60 this.uuid = args.uuid; 61 } 62 63 // Entry point for customisation of the displayed title for this panel. 64 abstract getTitle(): string; 65 66 // Generate a mithril node for this component. 67 abstract renderPanel(): m.Children; 68 69 // API for the tab to notify the TabList that it's still preparing the data. 70 // If true, adding a new tab will be delayed for a short while (~50ms) to 71 // reduce the flickering. 72 // 73 // Note: it's a "poll" rather than "push" API: there is no explicit API 74 // for the tabs to notify the tab list, as the tabs are expected to schedule 75 // global redraw anyway and the tab list will poll the tabs as necessary 76 // during the redraw. 77 isLoading(): boolean { 78 return false; 79 } 80} 81 82// BottomTabBase provides a more generic API allowing users to provide their 83// custom mithril component, which would allow them to listen to mithril 84// lifecycle events. Most cases, however, don't need them and BottomTab 85// provides a simplified API for the common case. 86export abstract class BottomTab<Config = {}> extends BottomTabBase<Config> { 87 constructor(args: NewBottomTabArgs<Config>) { 88 super(args); 89 } 90 91 abstract viewTab(): m.Children; 92 93 renderPanel(): m.Children { 94 return m(BottomTabAdapter, { 95 key: this.uuid, 96 panel: this, 97 } as BottomTabAdapterAttrs); 98 } 99} 100 101interface BottomTabAdapterAttrs { 102 panel: BottomTab; 103} 104 105class BottomTabAdapter implements m.ClassComponent<BottomTabAdapterAttrs> { 106 view(vnode: m.CVnode<BottomTabAdapterAttrs>): void | m.Children { 107 return vnode.attrs.panel.viewTab(); 108 } 109} 110