UNPKG

chrome-devtools-frontend

Version:
160 lines (120 loc) • 7.04 kB
# Settings Settings can alter the functionality of DevTools. Some of the settings default values can be changed with the command menu or in the settings tab. A settings registration is represented by the `SettingRegistration` interface, declared in [common/SettingRegistration.ts](./SettingRegistration.ts). All settings have to be registered using the function `Common.Settings.registerSettingExtension` which expects an object of type `SettingRegistration` as parameter. As an example, take the registration of the `showHTMLComments` setting, which allows users to determine if HTML comments are shown in the Elements tree: ```ts Common.Settings.registerSettingExtension({ category: Common.Settings.SettingCategory.ELEMENTS, order: 3, title: ls`Show HTML comments`, settingName: 'showHTMLComments', settingType: Common.Settings.SettingType.BOOLEAN, defaultValue: true, options: [ { value: true, title: ls`Show HTML comments`, }, { value: false, title: ls`Hide HTML comments`, }, ], }); ``` A controller for the each setting is added to the 'preferences' tab if they are visible, that is, they have a `title` and a `category`. They can also be set with the command menu if they have `options` and a `category` (options’ names are added as commands). --- # The DevTools Revealer System The `Revealer.ts` module provides a centralized system that allows different parts of the DevTools UI to "reveal" or display various types of objects without being tightly coupled to one another. It's a powerful decoupling mechanism that makes the codebase more modular, extensible, and performant. For example, if you click on a CSS file link in the **Console**, this system is responsible for telling the **Sources** panel to open and display that file, without the Console needing a direct reference to the Sources panel. ## Core Concepts 1. **`Revealer<T>` Interface**: This is the fundamental contract. A "Revealer" is any object (typically a UI panel or view) that knows how to display a specific type of data (`T`). It must implement a single method: `reveal(revealable: T): Promise<void>`. 2. **"Revealable" Object**: This is any object you want to show to the user. It can be a source code file (`SDK.SourceCode.UISourceCode`), a network request (`SDK.NetworkRequest.NetworkRequest`), a DOM node (`SDK.DOMModel.DOMNode`), or any other custom data type. 3. **`RevealerRegistry`**: This is a singleton class that acts as a central directory. It holds a list of all available `Revealer`s and maps them to the data types they can handle. 4. **`RevealerRegistration<T>`**: This is a configuration object used to register a `Revealer` with the `RevealerRegistry`. It contains three key pieces of information: * `contextTypes`: A function that returns an array of classes (constructors) that the `Revealer` can handle. * `loadRevealer`: An asynchronous function that returns a promise, which resolves to an instance of the `Revealer`. This allows for the lazy-loading of UI panels, improving initial application performance. * `destination` (optional): A user-friendly, localized string that describes where the object will be revealed (e.g., "Network panel", "Elements panel"). This is used for UI text, such as in context menus ("Reveal in..."). --- ## How to Create a New Revealer Here are the steps to implement a new revealer that can take the user to a specific place in the DevTools UI. ### Step 1: Define the Object to be Revealed First, ensure you have a class or data type that you want to make "revealable." ```ts // front_end/models/my_app/MyApp.ts export class MyDataObject { id: string; constructor(id: string) { this.id = id; } } ``` ### Step 2: Implement the `Revealer` Interface in Your UI Panel The UI component that will display the object (e.g., your panel or widget) must implement the `Common.Revealer.Revealer<T>` interface for your specific data type. ```ts // front_end/panels/my_panel/MyPanel.ts import * as Common from '../../core/common/common.js'; import * as UI from '../../ui/legacy/legacy.js'; import * as MyApp from '../../models/my_app/my_app.js'; // 1. Implement the interface for your specific data type. export class MyPanel extends UI.Panel.Panel implements Common.Revealer.Revealer<MyApp.MyDataObject> { // ... other panel implementation ... // 2. This is the required method from the interface. async reveal(dataObject: MyApp.MyDataObject): Promise<void> { // This is where you put your panel's custom logic to show the object. // First, ensure this panel is visible to the user. await UI.ViewManager.ViewManager.instance().showView('my-panel-view-id'); // Now, highlight the specific item within your panel. console.log(`Revealing data object with ID: ${dataObject.id}`); // e.g., this.selectItemInUI(dataObject.id); } } ``` ### Step 3: Register Your Panel as a `Revealer` This is the most important step. You must tell the central `RevealerRegistry` that `MyPanel` knows how to handle `MyDataObject`. This registration is typically done in a module's `-meta.ts` or `-legacy.ts` configuration file, which is executed at startup. ```ts // front_end/panels/my_panel/my_panel-meta.ts import * as Common from '../../core/common/common.js'; import * as i18n from '../../core/i18n/i18n.js'; const UIStrings = { /** * @description The name of the panel that reveals our custom data objects. */ myPanel: 'My Awesome Panel', }; const str_ = i18n.i18n.registerUIStrings('panels/my_panel/my_panel-meta.ts', UIStrings); const i18nLazyString = i18n.i18n.getLazilyComputedLocalizedString.bind(undefined, str_); Common.Revealer.registerRevealer({ // 1. Specify the data type(s) this revealer can handle. contextTypes() { // Use a dynamic import to avoid circular dependencies at module load time. const {MyApp} = await import('../../models/my_app/my_app.js'); return [ MyApp.MyDataObject, ]; }, // 2. Provide a function to load and return an instance of your panel. // This is what makes lazy loading possible. async loadRevealer() { const {MyPanel} = await import('./MyPanel.js'); // If your panel is a singleton, return its instance, otherwise create a new one. return MyPanel.instance(); }, // 3. (Optional) Provide a user-facing destination name for context menus. destination: i18nLazyString(UIStrings.myPanel), }); ``` ### Step 4: Trigger the Reveal from Anywhere Now that your revealer is registered, any other part of the DevTools codebase can ask to reveal an instance of `MyDataObject` without needing to know anything about `MyPanel`. ```ts // In some other file, e.g., a context menu action. import * as Common from '../../core/common/common.js'; import * as MyApp from '../../models/my_app/my_app.js'; // Create an instance of the object you want to reveal. const myObject = new MyApp.MyDataObject('abc-123'); // Call the global reveal function. await Common.Revealer.reveal(myObject); ```