提交 2328998d 编写于 作者: B Benjamin Pasero

theming - fix outline in activity bar after webkit-mask trick

上级 a512f56a
......@@ -12,7 +12,7 @@ import { TPromise } from 'vs/base/common/winjs.base';
import { Builder, $ } from 'vs/base/browser/builder';
import { DelayedDragHandler } from 'vs/base/browser/dnd';
import { Action } from 'vs/base/common/actions';
import { BaseActionItem, Separator } from 'vs/base/browser/ui/actionbar/actionbar';
import { BaseActionItem, Separator, IBaseActionItemOptions } from 'vs/base/browser/ui/actionbar/actionbar';
import { IActivityBarService, ProgressBadge, TextBadge, NumberBadge, IconBadge, IBadge } from 'vs/workbench/services/activity/common/activityBarService';
import Event, { Emitter } from 'vs/base/common/event';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
......@@ -23,9 +23,9 @@ import { ViewletDescriptor } from 'vs/workbench/browser/viewlet';
import { dispose } from 'vs/base/common/lifecycle';
import { IViewletService, } from 'vs/workbench/services/viewlet/browser/viewlet';
import { IPartService, Parts } from 'vs/workbench/services/part/common/partService';
import { IThemeService, ITheme } from "vs/platform/theme/common/themeService";
import { IThemeService, ITheme, registerThemingParticipant, ICssStyleCollector } from "vs/platform/theme/common/themeService";
import { ACTIVITY_BADGE_FOREGROUND, ACTIVITY_BADGE_BACKGROUND, ACTIVITY_BAR_DRAG_AND_DROP_BACKGROUND, ACTIVITY_BAR_FOREGROUND } from "vs/workbench/common/theme";
import { highContrastBorder } from "vs/platform/theme/common/colorRegistry";
import { highContrastBorder, highContrastOutline, focus } from "vs/platform/theme/common/colorRegistry";
export class ActivityAction extends Action {
private badge: IBadge;
......@@ -102,13 +102,33 @@ export class ViewletActivityAction extends ActivityAction {
}
}
export class ActivityActionItem extends BaseActionItem {
export abstract class ThemableActivityActionItem extends BaseActionItem {
constructor(
action: ActivityAction,
options: IBaseActionItemOptions,
@IThemeService protected themeService: IThemeService
) {
super(null, action, options);
this.themeService.onThemeChange(this.onThemeChange, this, this._callOnDispose);
}
private onThemeChange(theme: ITheme): void {
this.updateStyles();
}
protected abstract updateStyles(): void;
}
export class ActivityActionItem extends ThemableActivityActionItem {
private static manageExtensionAction: ManageExtensionAction;
private static toggleViewletPinnedAction: ToggleViewletPinnedAction;
private static draggedViewlet: ViewletDescriptor;
private $e: Builder;
private $container: Builder;
private $label: Builder;
private name: string;
private _keybinding: string;
private cssClass: string;
......@@ -123,9 +143,9 @@ export class ActivityActionItem extends BaseActionItem {
@IActivityBarService private activityBarService: IActivityBarService,
@IKeybindingService private keybindingService: IKeybindingService,
@IInstantiationService instantiationService: IInstantiationService,
@IThemeService private themeService: IThemeService
@IThemeService themeService: IThemeService
) {
super(null, action, { draggable: true });
super(action, { draggable: true }, themeService);
this.cssClass = action.class;
this.name = viewlet.name;
......@@ -140,21 +160,16 @@ export class ActivityActionItem extends BaseActionItem {
}
action.onDidChangeBadge(this.handleBadgeChangeEvenet, this, this._callOnDispose);
this.themeService.onThemeChange(this.onThemeChange, this, this._callOnDispose);
}
private onThemeChange(theme: ITheme): void {
this.updateStyles();
}
private updateStyles(): void {
protected updateStyles(): void {
const theme = this.themeService.getTheme();
// Label
if (this.$e) {
if (this.$label) {
const background = theme.getColor(ACTIVITY_BAR_FOREGROUND);
this.$e.style('background-color', background ? background.toString() : null);
this.$label.style('background-color', background ? background.toString() : null);
}
// Badge
......@@ -184,53 +199,33 @@ export class ActivityActionItem extends BaseActionItem {
public render(container: HTMLElement): void {
super.render(container);
this.$e = $('a.action-label').attr({
tabIndex: '0',
role: 'button'
}).appendTo(this.builder);
this.$container = $(container).attr({
tabIndex: '0'
});
// Try hard to prevent keyboard only focus feedback when using mouse
this.$e.on(DOM.EventType.MOUSE_DOWN, () => {
this.$e.addClass('clicked');
this.$container.on(DOM.EventType.MOUSE_DOWN, () => {
this.$container.addClass('clicked');
});
this.$e.on(DOM.EventType.MOUSE_UP, () => {
this.$container.on(DOM.EventType.MOUSE_UP, () => {
if (this.mouseUpTimeout) {
clearTimeout(this.mouseUpTimeout);
}
this.mouseUpTimeout = setTimeout(() => {
this.$e.removeClass('clicked');
this.$container.removeClass('clicked');
}, 800); // delayed to prevent focus feedback from showing on mouse up
});
$(container).on('contextmenu', e => {
this.$container.on('contextmenu', e => {
DOM.EventHelper.stop(e, true);
this.showContextMenu(container);
});
if (this.cssClass) {
this.$e.addClass(this.cssClass);
}
this.$badge = this.builder.div({ 'class': 'badge' }, (badge: Builder) => {
this.$badgeContent = badge.div({ 'class': 'badge-content' });
});
this.$badge.hide();
this.keybinding = this._keybinding; // force update
// Activate on drag over to reveal targets
[this.$badge, this.$e].forEach(b => new DelayedDragHandler(b.getHTMLElement(), () => {
if (!ActivityActionItem.getDraggedViewlet() && !this.getAction().checked) {
this.getAction().run();
}
}));
// Allow to drag
$(container).on(DOM.EventType.DRAG_START, (e: DragEvent) => {
this.$container.on(DOM.EventType.DRAG_START, (e: DragEvent) => {
e.dataTransfer.effectAllowed = 'move';
this.setDraggedViewlet(this.viewlet);
......@@ -242,7 +237,7 @@ export class ActivityActionItem extends BaseActionItem {
// Drag enter
let counter = 0; // see https://github.com/Microsoft/vscode/issues/14470
$(container).on(DOM.EventType.DRAG_ENTER, (e: DragEvent) => {
this.$container.on(DOM.EventType.DRAG_ENTER, (e: DragEvent) => {
const draggedViewlet = ActivityActionItem.getDraggedViewlet();
if (draggedViewlet && draggedViewlet.id !== this.viewlet.id) {
counter++;
......@@ -251,7 +246,7 @@ export class ActivityActionItem extends BaseActionItem {
});
// Drag leave
$(container).on(DOM.EventType.DRAG_LEAVE, (e: DragEvent) => {
this.$container.on(DOM.EventType.DRAG_LEAVE, (e: DragEvent) => {
const draggedViewlet = ActivityActionItem.getDraggedViewlet();
if (draggedViewlet) {
counter--;
......@@ -262,7 +257,7 @@ export class ActivityActionItem extends BaseActionItem {
});
// Drag end
$(container).on(DOM.EventType.DRAG_END, (e: DragEvent) => {
this.$container.on(DOM.EventType.DRAG_END, (e: DragEvent) => {
const draggedViewlet = ActivityActionItem.getDraggedViewlet();
if (draggedViewlet) {
counter = 0;
......@@ -273,7 +268,7 @@ export class ActivityActionItem extends BaseActionItem {
});
// Drop
$(container).on(DOM.EventType.DROP, (e: DragEvent) => {
this.$container.on(DOM.EventType.DROP, (e: DragEvent) => {
DOM.EventHelper.stop(e, true);
const draggedViewlet = ActivityActionItem.getDraggedViewlet();
......@@ -285,6 +280,29 @@ export class ActivityActionItem extends BaseActionItem {
}
});
// Label
this.$label = $('a.action-label').appendTo(this.builder);
if (this.cssClass) {
this.$label.addClass(this.cssClass);
}
// Badge
this.$badge = this.builder.div({ 'class': 'badge' }, (badge: Builder) => {
this.$badgeContent = badge.div({ 'class': 'badge-content' });
});
this.$badge.hide();
// Keybinding
this.keybinding = this._keybinding; // force update
// Activate on drag over to reveal targets
[this.$badge, this.$label].forEach(b => new DelayedDragHandler(b.getHTMLElement(), () => {
if (!ActivityActionItem.getDraggedViewlet() && !this.getAction().checked) {
this.getAction().run();
}
}));
this.updateStyles();
}
......@@ -329,7 +347,7 @@ export class ActivityActionItem extends BaseActionItem {
}
public focus(): void {
this.$e.domFocus();
this.$container.domFocus();
}
public setBadge(badge: IBadge): void {
......@@ -339,7 +357,7 @@ export class ActivityActionItem extends BaseActionItem {
public set keybinding(keybinding: string) {
this._keybinding = keybinding;
if (!this.$e) {
if (!this.$label) {
return;
}
......@@ -350,7 +368,7 @@ export class ActivityActionItem extends BaseActionItem {
title = this.name;
}
this.$e.title(title);
this.$label.title(title);
this.$badge.title(title);
}
......@@ -384,7 +402,7 @@ export class ActivityActionItem extends BaseActionItem {
this.$badge.show();
}
this.$e.attr('aria-label', `${this.name} - ${badge.getDescription()}`);
this.$label.attr('aria-label', `${this.name} - ${badge.getDescription()}`);
}
}
......@@ -399,9 +417,9 @@ export class ActivityActionItem extends BaseActionItem {
protected _updateChecked(): void {
if (this.getAction().checked) {
this.$e.addClass('active');
this.$container.addClass('active');
} else {
this.$e.removeClass('active');
this.$container.removeClass('active');
}
}
......@@ -430,7 +448,7 @@ export class ActivityActionItem extends BaseActionItem {
}
this.$badge.destroy();
this.$e.destroy();
this.$label.destroy();
}
}
......@@ -449,8 +467,8 @@ export class ViewletOverflowActivityAction extends ActivityAction {
}
}
export class ViewletOverflowActivityActionItem extends BaseActionItem {
private $e: Builder;
export class ViewletOverflowActivityActionItem extends ThemableActivityActionItem {
private $label: Builder;
private name: string;
private cssClass: string;
private actions: OpenViewletAction[];
......@@ -463,22 +481,36 @@ export class ViewletOverflowActivityActionItem extends BaseActionItem {
@IViewletService private viewletService: IViewletService,
@IKeybindingService private keybindingService: IKeybindingService,
@IContextMenuService private contextMenuService: IContextMenuService,
@IThemeService themeService: IThemeService
) {
super(null, action);
super(action, null, themeService);
this.cssClass = action.class;
this.name = action.label;
}
protected updateStyles(): void {
const theme = this.themeService.getTheme();
// Label
if (this.$label) {
const background = theme.getColor(ACTIVITY_BAR_FOREGROUND);
this.$label.style('background-color', background ? background.toString() : null);
}
}
public render(container: HTMLElement): void {
super.render(container);
this.$e = $('a.action-label').attr({
this.$label = $('a.action-label').attr({
tabIndex: '0',
role: 'button',
title: this.name,
class: this.cssClass
}).appendTo(this.builder);
this.updateStyles();
}
public showMenu(): void {
......@@ -590,4 +622,66 @@ export class ToggleViewletPinnedAction extends Action {
return TPromise.as(true);
}
}
\ No newline at end of file
}
registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
// Styling with Outline color (e.g. high contrast theme)
const outline = theme.getColor(highContrastOutline);
if (outline) {
collector.addRule(`
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item:before {
content: "";
position: absolute;
top: 9px;
left: 9px;
height: 32px;
width: 32px;
opacity: 0.6;
}
.monaco-workbench > .activitybar > .content .monaco-action-bar.global .action-item.active:before {
border: none;
}
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item.active:before,
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item.active:hover:before {
outline: 1px solid;
}
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item:hover:before {
outline: 1px dashed;
}
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item.active:before,
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item:hover:before {
opacity: 1;
}
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item:focus:before {
border-left-color: ${outline};
}
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item.active:before,
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item.active:hover:before,
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item:hover:before {
outline-color: ${outline};
}
`);
}
// Styling without outline color
else {
const focusBorder = theme.getColor(focus);
collector.addRule(`
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item {
opacity: 0.6;
}
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item:focus:before {
border-left-color: ${focusBorder};
}
`);
}
});
\ No newline at end of file
......@@ -30,9 +30,9 @@ import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import { ToggleActivityBarVisibilityAction } from 'vs/workbench/browser/actions/toggleActivityBarVisibility';
import SCMPreview from 'vs/workbench/parts/scm/browser/scmPreview';
import { IThemeService, registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { ACTIVITY_BAR_BACKGROUND } from 'vs/workbench/common/theme';
import { highContrastBorder, highContrastOutline, focus } from 'vs/platform/theme/common/colorRegistry';
import { highContrastBorder } from 'vs/platform/theme/common/colorRegistry';
interface IViewletActivity {
badge: IBadge;
......@@ -512,68 +512,4 @@ export class ActivitybarPart extends Part implements IActivityBarService {
// Pass to super
super.shutdown();
}
}
registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
// Styling with Outline color (e.g. high contrast theme)
const outline = theme.getColor(highContrastOutline);
if (outline) {
collector.addRule(`
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-label:before {
content: "";
position: absolute;
top: 9px;
left: 9px;
height: 32px;
width: 32px;
opacity: 0.6;
}
.monaco-workbench > .activitybar > .content .monaco-action-bar.global .action-item .action-label.active:before {
border: none;
}
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item .action-label.active:before,
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item .action-label.active:hover:before {
outline: 1px solid;
}
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item .action-label:hover:before {
outline: 1px dashed;
}
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-label,
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-label.active,
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item .action-label.active:before,
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item:hover .action-label:before {
opacity: 1;
}
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item .action-label:focus:before {
border-left-color: ${outline};
}
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item .action-label.active:before,
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item .action-label.active:hover:before,
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item .action-label:hover:before {
outline-color: ${outline};
}
`);
}
// Styling without outline color
else {
const focusBorder = theme.getColor(focus);
collector.addRule(`
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-label {
opacity: 0.6;
}
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item .action-label:focus:before {
border-left-color: ${focusBorder};
}
`);
}
});
\ No newline at end of file
}
\ No newline at end of file
......@@ -17,12 +17,10 @@
margin-right: 0;
padding: 0 0 0 50px;
box-sizing: border-box;
background-position: 9px center;
background-repeat: no-repeat;
font-size: 15px;
}
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item .action-label:focus:before {
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item:focus:before {
content: "";
position: absolute;
top: 9px;
......@@ -31,25 +29,20 @@
border-left: 2px solid;
}
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item .action-label.clicked:focus:before {
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item.clicked:focus:before {
border-left: none !important; /* no focus feedback when using mouse */
}
.monaco-workbench > .activitybar.left > .content .monaco-action-bar .action-item .action-label:focus:before {
.monaco-workbench > .activitybar.left > .content .monaco-action-bar .action-item:focus:before {
left: 1px;
}
.monaco-workbench > .activitybar.right > .content .monaco-action-bar .action-item .action-label:focus:before {
.monaco-workbench > .activitybar.right > .content .monaco-action-bar .action-item:focus:before {
right: 1px;
}
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-label.toggle-more {
background-image: url('ellipsis-global.svg');
}
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-label > .label {
flex: 1 1 auto;
overflow: hidden;
-webkit-mask: url('ellipsis-global.svg') no-repeat 50% 50%;
}
.monaco-workbench > .activitybar > .content .monaco-action-bar .badge {
......@@ -74,8 +67,8 @@
text-align: center;
}
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item .action-label.active,
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item:hover .action-label {
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item.active,
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item:hover {
opacity: 1;
}
......@@ -87,15 +80,6 @@
background-position: calc(100% - 9px) center;
}
.monaco-workbench > .activitybar.right > .content .monaco-action-bar .action-label .label {
padding-left: 1em;
}
.monaco-workbench > .activitybar.right > .content .monaco-action-bar .action-label > .keybinding {
text-align: right;
padding: 0 0 0 2em;
}
.monaco-workbench > .activitybar.right > .content .monaco-action-bar .badge {
left: auto;
right: 0;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册