xref: /aosp_15_r20/external/pigweed/pw_ide/ts/pigweed-vscode/src/statusBar.ts (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1// Copyright 2024 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7//     https://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, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14
15import * as vscode from 'vscode';
16import { StatusBarItem } from 'vscode';
17
18import { Disposable } from './disposables';
19
20import {
21  didChangeClangdConfig,
22  didChangeRefreshStatus,
23  didChangeTarget,
24} from './events';
25
26import { RefreshStatus } from './refreshManager';
27import { settings } from './settings';
28
29const DEFAULT_TARGET_TEXT = 'Select a Target';
30const ICON_IDLE = '$(check)';
31const ICON_FAULT = '$(warning)';
32const ICON_INPROGRESS = '$(sync~spin)';
33
34export class TargetStatusBarItem extends Disposable {
35  private statusBarItem: StatusBarItem;
36  private targetText = DEFAULT_TARGET_TEXT;
37  private icon = ICON_IDLE;
38
39  constructor() {
40    super();
41
42    this.statusBarItem = vscode.window.createStatusBarItem(
43      vscode.StatusBarAlignment.Left,
44      100,
45    );
46
47    // Seed the initial state, then make it visible
48    this.updateTarget();
49    this.updateRefreshStatus();
50    this.statusBarItem.show();
51
52    // Subscribe to relevant events
53    didChangeTarget.event(this.updateTarget);
54    didChangeRefreshStatus.event(this.updateRefreshStatus);
55
56    // Dispose this when the extension is deactivated
57    this.disposables.push(this.statusBarItem);
58  }
59
60  label = () => `${this.icon} ${this.targetText}`;
61
62  updateProps = (
63    props: Partial<{ command: string; icon: string; tooltip: string }> = {},
64  ): void => {
65    this.icon = props.icon ?? this.icon;
66    this.statusBarItem.command = props.command ?? this.statusBarItem.command;
67    this.statusBarItem.tooltip = props.tooltip ?? this.statusBarItem.tooltip;
68    this.statusBarItem.text = this.label();
69  };
70
71  updateTarget = (target?: string): void => {
72    this.targetText =
73      target ?? settings.codeAnalysisTarget() ?? DEFAULT_TARGET_TEXT;
74
75    this.updateProps();
76  };
77
78  updateRefreshStatus = (status: RefreshStatus = 'idle'): void => {
79    switch (status) {
80      case 'idle':
81        this.updateProps({
82          command: 'pigweed.select-target',
83          icon: ICON_IDLE,
84          tooltip: 'Click to select a code analysis target',
85        });
86        break;
87      case 'fault':
88        this.updateProps({
89          command: 'pigweed.refresh-compile-commands-and-set-target',
90          icon: ICON_FAULT,
91          tooltip: 'An error occurred! Click to try again',
92        });
93        break;
94      default:
95        this.updateProps({
96          command: 'pigweed.open-output-panel',
97          icon: ICON_INPROGRESS,
98          tooltip:
99            'Refreshing compile commands. Click to open the output panel',
100        });
101        break;
102    }
103  };
104}
105
106export class InactiveVisibilityStatusBarItem extends Disposable {
107  private statusBarItem: StatusBarItem;
108
109  constructor() {
110    super();
111
112    this.statusBarItem = vscode.window.createStatusBarItem(
113      vscode.StatusBarAlignment.Left,
114      99,
115    );
116
117    // Seed the initial state, then make it visible
118    this.update();
119    this.statusBarItem.show();
120
121    // Update state on clangd config change events
122    didChangeClangdConfig.event(this.update);
123
124    // Dispose this when the extension is deactivated
125    this.disposables.push(this.statusBarItem);
126  }
127
128  update = (): void => {
129    if (settings.disableInactiveFileCodeIntelligence()) {
130      this.statusBarItem.text = '$(eye-closed)';
131
132      this.statusBarItem.tooltip =
133        'Code intelligence is disabled for files not in current ' +
134        "target's build. Click to enable.";
135
136      this.statusBarItem.command =
137        'pigweed.enable-inactive-file-code-intelligence';
138    } else {
139      this.statusBarItem.text = '$(eye)';
140
141      this.statusBarItem.tooltip =
142        'Code intelligence is enabled for all files.' +
143        "Click to disable for files not in current target's build.";
144
145      this.statusBarItem.command =
146        'pigweed.disable-inactive-file-code-intelligence';
147    }
148  };
149}
150