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