| // Copyright (C) 2024 The Android Open Source Project | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| import type m from 'mithril'; | |
| import type {SqlValue} from '../../../../trace_processor/query_result'; | |
| import type {Trace} from '../../../../public/trace'; | |
| import {type SqlColumn, sqlColumnId} from './sql_column'; | |
| import type {Filters} from './filters'; | |
| import type {PerfettoSqlType} from '../../../../trace_processor/perfetto_sql_type'; | |
| // Interface which allows TableColumn to interact with the table (e.g. add filters, or run the query). | |
| export interface TableManager { | |
| filters: Filters; | |
| trace: Trace; | |
| getSqlQuery(data: {[key: string]: SqlColumn}): string; | |
| } | |
| // Context passed to renderCell to allow interaction with the table. | |
| export interface RenderCellContext { | |
| filters: Filters; | |
| trace: Trace; | |
| getSqlQuery(data: {[key: string]: SqlColumn}): string; | |
| hasColumn(column: TableColumn): boolean; | |
| addColumn(column: TableColumn): void; | |
| } | |
| // Context passed to listDerivedColumns to provide information about the table. | |
| export interface ListColumnsContext { | |
| filters: Filters; | |
| trace: Trace; | |
| getSqlQuery(data: {[key: string]: SqlColumn}): string; | |
| } | |
| export interface TableColumnParams { | |
| // See TableColumn.tag. | |
| tag?: string; | |
| // See TableColumn.alias. | |
| alias?: string; | |
| // See TableColumn.startsHidden. | |
| startsHidden?: boolean; | |
| } | |
| // Class which represents a column in a table, which can be displayed to the user. | |
| export interface TableColumn { | |
| readonly column: SqlColumn; | |
| readonly type: PerfettoSqlType | undefined; | |
| // In some cases, the UI needs additional information to be able to render a given cell (e.g. for display arg values, | |
| // we need to know arg type as well as arg value to generate a correct filter). In these cases, the common solution is fetch a JSON value | |
| // or a protobuf from the SQL and render it accordingly, so if set, `display` column overrides which value is going to be passed to `renderCell`. | |
| // `column` is still always going to be used for sorting, aggregation and casting. | |
| readonly display?: SqlColumn; | |
| // Column title to be displayed. | |
| // If not set, then `alias` will be used if it's unique. | |
| // If `alias` is not set as well, then `sqlColumnId(primaryColumn())` will be used. | |
| // TODO(altimin): This should return m.Children, but a bunch of things, including low-level widgets (Button, MenuItem, Anchor) need to be fixed first. | |
| getTitle?(): string | undefined; | |
| // Get column-specific menu items for this column. | |
| // This allows columns to provide their own menu items in the table header menu. | |
| // For example, a CastColumn can provide an "Undo cast" menu item. | |
| getColumnSpecificMenuItems?(args: { | |
| replaceColumn: (column: TableColumn) => void; | |
| }): m.Children; | |
| /** | |
| * Render a table cell. context can be undefined, in which case the cell should provide basic rendering (e.g. for pivot table). | |
| * | |
| * @param value The value to be rendered. | |
| * @param context Optional context to allow interaction with the table (e.g. adding filters). | |
| */ | |
| renderCell(value: SqlValue, context?: RenderCellContext): RenderedCell; | |
| // A set of columns to be added when opening this table. | |
| // It has two primary purposes: | |
| // - Allow some columns to be hidden by default (by returning an empty array). | |
| // - Expand some columns (e.g. utid and upid are not meaningful by themselves, so the corresponding columns might add a "name" column by default). | |
| initialColumns?(): TableColumn[]; | |
| // Some columns / values (arg_set_ids, table ids, etc) are primarily used to reference other data. | |
| // This method allows showing the user list of additional columns which can be fetched using this column. | |
| listDerivedColumns?( | |
| context: ListColumnsContext, | |
| ): undefined | (() => Promise<Map<string, TableColumn>>); | |
| } | |
| // Returns a unique identifier for the table column. | |
| export function tableColumnId(column: TableColumn): string { | |
| return sqlColumnId(column.column); | |
| } | |
| export function tableColumnAlias(column: TableColumn): string { | |
| return tableColumnId(column).replace(/[^a-zA-Z0-9_]/g, (char) => { | |
| if (char === '_') { | |
| return '__'; | |
| } | |
| return '_' + char.charCodeAt(0); | |
| }); | |
| } | |
| export function columnTitle(column: TableColumn): string { | |
| if (column.getTitle !== undefined) { | |
| const title = column.getTitle(); | |
| if (title !== undefined) return title; | |
| } | |
| return sqlColumnId(column.column); | |
| } | |
| export interface RenderedCell { | |
| readonly content: m.Children; | |
| readonly menu?: m.Children; | |
| readonly isNumerical?: boolean; | |
| readonly isNull?: boolean; | |
| } |