@@ -31,22 +31,25 @@ export interface ISettingOverrideClickEvent {
31
31
settingKey : string ;
32
32
}
33
33
34
+ interface SettingIndicator {
35
+ element : HTMLElement ;
36
+ label : SimpleIconLabel ;
37
+ hover : MutableDisposable < ICustomHover > ;
38
+ }
39
+
34
40
/**
35
41
* Renders the indicators next to a setting, such as "Also Modified In".
36
42
*/
37
43
export class SettingsTreeIndicatorsLabel implements IDisposable {
38
44
private indicatorsContainerElement : HTMLElement ;
39
- private workspaceTrustElement : HTMLElement ;
40
- private scopeOverridesElement : HTMLElement ;
41
- private scopeOverridesLabel : SimpleIconLabel ;
42
- private scopeOverridesHover : MutableDisposable < ICustomHover > ;
43
- private syncIgnoredElement : HTMLElement ;
44
- private defaultOverrideIndicatorElement : HTMLElement ;
45
45
private hoverDelegate : IHoverDelegate ;
46
- private profilesEnabled : boolean ;
47
46
48
- // Holds hovers that contain a fixed message.
49
- private simpleHoverStore : DisposableStore ;
47
+ private workspaceTrustIndicator : SettingIndicator ;
48
+ private scopeOverridesIndicator : SettingIndicator ;
49
+ private syncIgnoredIndicator : SettingIndicator ;
50
+ private defaultOverrideIndicator : SettingIndicator ;
51
+
52
+ private profilesEnabled : boolean ;
50
53
51
54
constructor (
52
55
container : HTMLElement ,
@@ -68,19 +71,16 @@ export class SettingsTreeIndicatorsLabel implements IDisposable {
68
71
placement : 'element'
69
72
} ;
70
73
71
- this . simpleHoverStore = new DisposableStore ( ) ;
72
- const scopeOverridesIndicator = this . createScopeOverridesIndicator ( ) ;
73
- this . workspaceTrustElement = this . createWorkspaceTrustElement ( ) ;
74
- this . scopeOverridesElement = scopeOverridesIndicator . element ;
75
- this . scopeOverridesLabel = scopeOverridesIndicator . label ;
76
- this . syncIgnoredElement = this . createSyncIgnoredElement ( ) ;
77
- this . defaultOverrideIndicatorElement = this . createDefaultOverrideIndicator ( ) ;
78
- this . scopeOverridesHover = new MutableDisposable ( ) ;
79
74
this . profilesEnabled = this . userDataProfilesService . isEnabled ( ) ;
75
+
76
+ this . workspaceTrustIndicator = this . createWorkspaceTrustIndicator ( ) ;
77
+ this . scopeOverridesIndicator = this . createScopeOverridesIndicator ( ) ;
78
+ this . syncIgnoredIndicator = this . createSyncIgnoredIndicator ( ) ;
79
+ this . defaultOverrideIndicator = this . createDefaultOverrideIndicator ( ) ;
80
80
}
81
81
82
- private createWorkspaceTrustElement ( ) : HTMLElement {
83
- const workspaceTrustElement = $ ( 'span.setting-item-workspace-trust' ) ;
82
+ private createWorkspaceTrustIndicator ( ) : SettingIndicator {
83
+ const workspaceTrustElement = $ ( 'span.setting-indicator.setting- item-workspace-trust' ) ;
84
84
const workspaceTrustLabel = new SimpleIconLabel ( workspaceTrustElement ) ;
85
85
workspaceTrustLabel . text = '$(warning) ' + localize ( 'workspaceUntrustedLabel' , "Setting value not applied" ) ;
86
86
const contentFallback = localize ( 'trustLabel' , "The setting value can only be applied in a trusted workspace." ) ;
@@ -94,65 +94,86 @@ export class SettingsTreeIndicatorsLabel implements IDisposable {
94
94
} ,
95
95
markdownNotSupportedFallback : contentFallback
96
96
} ;
97
+
98
+ const hover = new MutableDisposable < ICustomHover > ( ) ;
97
99
const options : IUpdatableHoverOptions = {
98
100
linkHandler : ( url : string ) => {
99
101
this . commandService . executeCommand ( 'workbench.trust.manage' ) ;
100
- this . scopeOverridesHover . value ?. hide ( ) ;
102
+ hover . value ?. hide ( ) ;
101
103
}
102
104
} ;
103
-
104
- this . simpleHoverStore . add ( setupCustomHover ( this . hoverDelegate , workspaceTrustElement , content , options ) ) ;
105
- return workspaceTrustElement ;
105
+ hover . value = setupCustomHover ( this . hoverDelegate , workspaceTrustElement , content , options ) ;
106
+ return {
107
+ element : workspaceTrustElement ,
108
+ label : workspaceTrustLabel ,
109
+ hover
110
+ } ;
106
111
}
107
112
108
- private createScopeOverridesIndicator ( ) : { element : HTMLElement ; label : SimpleIconLabel } {
113
+ private createScopeOverridesIndicator ( ) : SettingIndicator {
114
+ // Don't add .setting-indicator class here, because it gets conditionally added later.
109
115
const otherOverridesElement = $ ( 'span.setting-item-overrides' ) ;
110
116
const otherOverridesLabel = new SimpleIconLabel ( otherOverridesElement ) ;
111
- return { element : otherOverridesElement , label : otherOverridesLabel } ;
117
+ return {
118
+ element : otherOverridesElement ,
119
+ label : otherOverridesLabel ,
120
+ hover : new MutableDisposable < ICustomHover > ( )
121
+ } ;
112
122
}
113
123
114
- private createSyncIgnoredElement ( ) : HTMLElement {
115
- const syncIgnoredElement = $ ( 'span.setting-item-ignored' ) ;
124
+ private createSyncIgnoredIndicator ( ) : SettingIndicator {
125
+ const syncIgnoredElement = $ ( 'span.setting-indicator.setting- item-ignored' ) ;
116
126
const syncIgnoredLabel = new SimpleIconLabel ( syncIgnoredElement ) ;
117
127
syncIgnoredLabel . text = localize ( 'extensionSyncIgnoredLabel' , 'Not synced' ) ;
128
+
118
129
const syncIgnoredHoverContent = localize ( 'syncIgnoredTitle' , "This setting is ignored during sync" ) ;
119
- this . simpleHoverStore . add ( setupCustomHover ( this . hoverDelegate , syncIgnoredElement , syncIgnoredHoverContent ) ) ;
120
- return syncIgnoredElement ;
130
+ const hover = new MutableDisposable < ICustomHover > ( ) ;
131
+ hover . value = setupCustomHover ( this . hoverDelegate , syncIgnoredElement , syncIgnoredHoverContent ) ;
132
+ return {
133
+ element : syncIgnoredElement ,
134
+ label : syncIgnoredLabel ,
135
+ hover
136
+ } ;
121
137
}
122
138
123
- private createDefaultOverrideIndicator ( ) : HTMLElement {
124
- const defaultOverrideIndicator = $ ( 'span.setting-item-default-overridden' ) ;
139
+ private createDefaultOverrideIndicator ( ) : SettingIndicator {
140
+ const defaultOverrideIndicator = $ ( 'span.setting-indicator.setting- item-default-overridden' ) ;
125
141
const defaultOverrideLabel = new SimpleIconLabel ( defaultOverrideIndicator ) ;
126
142
defaultOverrideLabel . text = localize ( 'defaultOverriddenLabel' , "Default value changed" ) ;
127
- return defaultOverrideIndicator ;
143
+
144
+ return {
145
+ element : defaultOverrideIndicator ,
146
+ label : defaultOverrideLabel ,
147
+ hover : new MutableDisposable < ICustomHover > ( )
148
+ } ;
128
149
}
129
150
130
151
private render ( ) {
131
- const elementsToShow = [ this . workspaceTrustElement , this . scopeOverridesElement , this . syncIgnoredElement , this . defaultOverrideIndicatorElement ] . filter ( element => {
132
- return element . style . display !== 'none' ;
152
+ const indicatorsToShow = [ this . workspaceTrustIndicator , this . scopeOverridesIndicator , this . syncIgnoredIndicator , this . defaultOverrideIndicator ] . filter ( indicator => {
153
+ return indicator . element . style . display !== 'none' ;
133
154
} ) ;
134
155
135
156
this . indicatorsContainerElement . innerText = '' ;
136
157
this . indicatorsContainerElement . style . display = 'none' ;
137
- if ( elementsToShow . length ) {
158
+ if ( indicatorsToShow . length ) {
138
159
this . indicatorsContainerElement . style . display = 'inline' ;
139
160
DOM . append ( this . indicatorsContainerElement , $ ( 'span' , undefined , '(' ) ) ;
140
- for ( let i = 0 ; i < elementsToShow . length - 1 ; i ++ ) {
141
- DOM . append ( this . indicatorsContainerElement , elementsToShow [ i ] ) ;
161
+ for ( let i = 0 ; i < indicatorsToShow . length - 1 ; i ++ ) {
162
+ DOM . append ( this . indicatorsContainerElement , indicatorsToShow [ i ] . element ) ;
142
163
DOM . append ( this . indicatorsContainerElement , $ ( 'span.comma' , undefined , ' • ' ) ) ;
143
164
}
144
- DOM . append ( this . indicatorsContainerElement , elementsToShow [ elementsToShow . length - 1 ] ) ;
165
+ DOM . append ( this . indicatorsContainerElement , indicatorsToShow [ indicatorsToShow . length - 1 ] . element ) ;
145
166
DOM . append ( this . indicatorsContainerElement , $ ( 'span' , undefined , ')' ) ) ;
146
167
}
147
168
}
148
169
149
170
updateWorkspaceTrust ( element : SettingsTreeSettingElement ) {
150
- this . workspaceTrustElement . style . display = element . isUntrusted ? 'inline' : 'none' ;
171
+ this . workspaceTrustIndicator . element . style . display = element . isUntrusted ? 'inline' : 'none' ;
151
172
this . render ( ) ;
152
173
}
153
174
154
175
updateSyncIgnored ( element : SettingsTreeSettingElement , ignoredSettings : string [ ] ) {
155
- this . syncIgnoredElement . style . display = this . userDataSyncEnablementService . isEnabled ( )
176
+ this . syncIgnoredIndicator . element . style . display = this . userDataSyncEnablementService . isEnabled ( )
156
177
&& ignoredSettings . includes ( element . setting . key ) ? 'inline' : 'none' ;
157
178
this . render ( ) ;
158
179
}
@@ -169,19 +190,22 @@ export class SettingsTreeIndicatorsLabel implements IDisposable {
169
190
}
170
191
171
192
dispose ( ) {
172
- this . scopeOverridesHover . dispose ( ) ;
173
- this . simpleHoverStore . dispose ( ) ;
193
+ const indicators = [ this . workspaceTrustIndicator , this . scopeOverridesIndicator ,
194
+ this . syncIgnoredIndicator , this . defaultOverrideIndicator ] ;
195
+ for ( const indicator of indicators ) {
196
+ indicator . hover . dispose ( ) ;
197
+ }
174
198
}
175
199
176
200
updateScopeOverrides ( element : SettingsTreeSettingElement , elementDisposables : DisposableStore , onDidClickOverrideElement : Emitter < ISettingOverrideClickEvent > , onApplyFilter : Emitter < string > ) {
177
- this . scopeOverridesElement . innerText = '' ;
178
- this . scopeOverridesElement . style . display = 'none' ;
201
+ this . scopeOverridesIndicator . element . innerText = '' ;
202
+ this . scopeOverridesIndicator . element . style . display = 'none' ;
179
203
if ( element . hasPolicyValue ) {
180
204
// If the setting falls under a policy, then no matter what the user sets, the policy value takes effect.
181
- this . scopeOverridesElement . style . display = 'inline' ;
182
- this . scopeOverridesElement . classList . add ( 'with-custom-hover ' ) ;
205
+ this . scopeOverridesIndicator . element . style . display = 'inline' ;
206
+ this . scopeOverridesIndicator . element . classList . add ( 'setting-indicator ' ) ;
183
207
184
- this . scopeOverridesLabel . text = '$(warning) ' + localize ( 'policyLabelText' , "Setting value not applied" ) ;
208
+ this . scopeOverridesIndicator . label . text = '$(warning) ' + localize ( 'policyLabelText' , "Setting value not applied" ) ;
185
209
const contentFallback = localize ( 'policyDescription' , "This setting is managed by your organization and its applied value cannot be changed." ) ;
186
210
const contentMarkdownString = contentFallback + ` [${ localize ( 'policyFilterLink' , "View policy settings" ) } ](policy-settings).` ;
187
211
const content : ITooltipMarkdownString = {
@@ -193,43 +217,45 @@ export class SettingsTreeIndicatorsLabel implements IDisposable {
193
217
markdownNotSupportedFallback : contentFallback
194
218
} ;
195
219
const options : IUpdatableHoverOptions = {
196
- linkHandler : ( url : string ) => {
220
+ linkHandler : _ => {
197
221
onApplyFilter . fire ( `@${ POLICY_SETTING_TAG } ` ) ;
198
- this . scopeOverridesHover . value ?. hide ( ) ;
222
+ this . scopeOverridesIndicator . hover . value ?. hide ( ) ;
199
223
}
200
224
} ;
201
- this . scopeOverridesHover . value = setupCustomHover ( this . hoverDelegate , this . scopeOverridesElement , content , options ) ;
225
+ this . scopeOverridesIndicator . hover . value = setupCustomHover ( this . hoverDelegate , this . scopeOverridesIndicator . element , content , options ) ;
226
+
202
227
} else if ( this . profilesEnabled && element . matchesScope ( ConfigurationTarget . APPLICATION , false ) ) {
203
228
// If the setting is an application-scoped setting, there are no overrides so we can use this
204
229
// indicator to display that information instead.
205
- this . scopeOverridesElement . style . display = 'inline' ;
206
- this . scopeOverridesElement . classList . add ( 'with-custom-hover ' ) ;
230
+ this . scopeOverridesIndicator . element . style . display = 'inline' ;
231
+ this . scopeOverridesIndicator . element . classList . add ( 'setting-indicator ' ) ;
207
232
208
233
const applicationSettingText = localize ( 'applicationSetting' , "Applies to all profiles" ) ;
209
- this . scopeOverridesLabel . text = applicationSettingText ;
234
+ this . scopeOverridesIndicator . label . text = applicationSettingText ;
210
235
211
236
const content = localize ( 'applicationSettingDescription' , "The setting is not specific to the current profile, and will retain its value when switching profiles." ) ;
212
- this . scopeOverridesHover . value = setupCustomHover ( this . hoverDelegate , this . scopeOverridesElement , content ) ;
237
+ this . scopeOverridesIndicator . hover . value = setupCustomHover ( this . hoverDelegate , this . scopeOverridesIndicator . element , content ) ;
213
238
} else if ( element . overriddenScopeList . length || element . overriddenDefaultsLanguageList . length ) {
214
239
if ( ( MODIFIED_INDICATOR_USE_INLINE_ONLY && element . overriddenScopeList . length ) ||
215
240
( element . overriddenScopeList . length === 1 && ! element . overriddenDefaultsLanguageList . length ) ) {
241
+ // This branch renders some info inline!
216
242
// Render inline if we have the flag and there are scope overrides to render,
217
243
// or if there is only one scope override to render and no language overrides.
218
- this . scopeOverridesElement . style . display = 'inline' ;
219
- this . scopeOverridesElement . classList . remove ( 'with-custom-hover ' ) ;
220
- this . scopeOverridesHover . value = undefined ;
244
+ this . scopeOverridesIndicator . element . style . display = 'inline' ;
245
+ this . scopeOverridesIndicator . element . classList . remove ( 'setting-indicator ' ) ;
246
+ this . scopeOverridesIndicator . hover . value = undefined ;
221
247
222
248
// Just show all the text in the label.
223
249
const prefaceText = element . isConfigured ?
224
250
localize ( 'alsoConfiguredIn' , "Also modified in" ) :
225
251
localize ( 'configuredIn' , "Modified in" ) ;
226
- this . scopeOverridesLabel . text = `${ prefaceText } ` ;
252
+ this . scopeOverridesIndicator . label . text = `${ prefaceText } ` ;
227
253
228
254
for ( let i = 0 ; i < element . overriddenScopeList . length ; i ++ ) {
229
255
const overriddenScope = element . overriddenScopeList [ i ] ;
230
- const view = DOM . append ( this . scopeOverridesElement , $ ( 'a.modified-scope' , undefined , this . getInlineScopeDisplayText ( overriddenScope ) ) ) ;
256
+ const view = DOM . append ( this . scopeOverridesIndicator . element , $ ( 'a.modified-scope' , undefined , this . getInlineScopeDisplayText ( overriddenScope ) ) ) ;
231
257
if ( i !== element . overriddenScopeList . length - 1 ) {
232
- DOM . append ( this . scopeOverridesElement , $ ( 'span.comma' , undefined , ', ' ) ) ;
258
+ DOM . append ( this . scopeOverridesIndicator . element , $ ( 'span.comma' , undefined , ', ' ) ) ;
233
259
}
234
260
elementDisposables . add (
235
261
DOM . addStandardDisposableListener ( view , DOM . EventType . CLICK , ( e : IMouseEvent ) => {
@@ -247,12 +273,12 @@ export class SettingsTreeIndicatorsLabel implements IDisposable {
247
273
// Even if the check above fails, we want to
248
274
// show the text in a custom hover only if
249
275
// the feature flag isn't on.
250
- this . scopeOverridesElement . style . display = 'inline' ;
251
- this . scopeOverridesElement . classList . add ( 'with-custom-hover ' ) ;
276
+ this . scopeOverridesIndicator . element . style . display = 'inline' ;
277
+ this . scopeOverridesIndicator . element . classList . add ( 'setting-indicator ' ) ;
252
278
const scopeOverridesLabelText = element . isConfigured ?
253
279
localize ( 'alsoConfiguredElsewhere' , "Also modified elsewhere" ) :
254
280
localize ( 'configuredElsewhere' , "Modified elsewhere" ) ;
255
- this . scopeOverridesLabel . text = scopeOverridesLabelText ;
281
+ this . scopeOverridesIndicator . label . text = scopeOverridesLabelText ;
256
282
257
283
let contentMarkdownString = '' ;
258
284
let contentFallback = '' ;
@@ -298,22 +324,23 @@ export class SettingsTreeIndicatorsLabel implements IDisposable {
298
324
scope : scope as ScopeString ,
299
325
language
300
326
} ) ;
301
- this . scopeOverridesHover . value ?. hide ( ) ;
327
+ this . scopeOverridesIndicator . hover . value ?. hide ( ) ;
302
328
}
303
329
} ;
304
- this . scopeOverridesHover . value = setupCustomHover ( this . hoverDelegate , this . scopeOverridesElement , content , options ) ;
330
+ this . scopeOverridesIndicator . hover . value = setupCustomHover ( this . hoverDelegate , this . scopeOverridesIndicator . element , content , options ) ;
305
331
}
306
332
}
307
333
this . render ( ) ;
308
334
}
309
335
310
336
updateDefaultOverrideIndicator ( element : SettingsTreeSettingElement ) {
311
- this . defaultOverrideIndicatorElement . style . display = 'none' ;
337
+ this . defaultOverrideIndicator . element . style . display = 'none' ;
312
338
const sourceToDisplay = getDefaultValueSourceToDisplay ( element ) ;
313
339
if ( sourceToDisplay !== undefined ) {
314
- this . defaultOverrideIndicatorElement . style . display = 'inline' ;
340
+ this . defaultOverrideIndicator . element . style . display = 'inline' ;
341
+
315
342
const defaultOverrideHoverContent = localize ( 'defaultOverriddenDetails' , "Default setting value overridden by {0}" , sourceToDisplay ) ;
316
- setupCustomHover ( this . hoverDelegate , this . defaultOverrideIndicatorElement , defaultOverrideHoverContent ) ;
343
+ this . defaultOverrideIndicator . hover . value = setupCustomHover ( this . hoverDelegate , this . defaultOverrideIndicator . element , defaultOverrideHoverContent ) ;
317
344
}
318
345
this . render ( ) ;
319
346
}
0 commit comments