Skip to content

Commit

Permalink
feat: support editor/title context menus for web views
Browse files Browse the repository at this point in the history
Signed-off-by: MiaoWoo <admin@yumc.pw>
  • Loading branch information
502647092 committed Aug 26, 2019
1 parent ffcb3fa commit e3ad30e
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 53 deletions.
32 changes: 32 additions & 0 deletions packages/mini-browser/src/browser/mini-browser-content-style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/********************************************************************************
* Copyright (C) 2019 TypeFox, Inc. and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
export namespace MiniBrowserContentStyle {
export const MINI_BROWSER = 'theia-mini-browser';
export const TOOLBAR = 'theia-mini-browser-toolbar';
export const TOOLBAR_READ_ONLY = 'theia-mini-browser-toolbar-read-only';
export const PRE_LOAD = 'theia-mini-browser-load-indicator';
export const FADE_OUT = 'theia-fade-out';
export const CONTENT_AREA = 'theia-mini-browser-content-area';
export const PDF_CONTAINER = 'theia-mini-browser-pdf-container';
export const PREVIOUS = 'theia-mini-browser-previous';
export const NEXT = 'theia-mini-browser-next';
export const REFRESH = 'theia-mini-browser-refresh';
export const OPEN = 'theia-mini-browser-open';
export const BUTTON = 'theia-mini-browser-button';
export const DISABLED = 'theia-mini-browser-button-disabled';
export const TRANSPARENT_OVERLAY = 'theia-mini-browser-transparent-overlay';
export const ERROR_BAR = 'theia-mini-browser-error-bar';
}
61 changes: 19 additions & 42 deletions packages/mini-browser/src/browser/mini-browser-content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@ import { WindowService } from '@theia/core/lib/browser/window/window-service';
import { parseCssTime, Key, KeyCode } from '@theia/core/lib/browser';
import { FileSystemWatcher, FileChangeEvent } from '@theia/filesystem/lib/browser/filesystem-watcher';
import { DisposableCollection, Disposable } from '@theia/core/lib/common/disposable';
import { BaseWidget, addEventListener} from '@theia/core/lib/browser/widgets/widget';
import { BaseWidget, addEventListener } from '@theia/core/lib/browser/widgets/widget';
import { LocationMapperService } from './location-mapper-service';
import { ApplicationShellMouseTracker } from '@theia/core/lib/browser/shell/application-shell-mouse-tracker';

import debounce = require('lodash.debounce');
import { MiniBrowserContentStyle } from './mini-browser-content-style';

/**
* Initializer properties for the embedded browser widget.
Expand Down Expand Up @@ -205,7 +206,7 @@ export class MiniBrowserContent extends BaseWidget {
constructor(@inject(MiniBrowserProps) protected readonly props: MiniBrowserProps) {
super();
this.node.tabIndex = 0;
this.addClass(MiniBrowserContent.Styles.MINI_BROWSER);
this.addClass(MiniBrowserContentStyle.MINI_BROWSER);
this.input = this.createToolbar(this.node).input;
const contentArea = this.createContentArea(this.node);
this.frame = contentArea.frame;
Expand Down Expand Up @@ -271,7 +272,7 @@ export class MiniBrowserContent extends BaseWidget {

protected createToolbar(parent: HTMLElement): HTMLDivElement & Readonly<{ input: HTMLInputElement }> {
const toolbar = document.createElement('div');
toolbar.classList.add(this.getToolbarProps() === 'read-only' ? MiniBrowserContent.Styles.TOOLBAR_READ_ONLY : MiniBrowserContent.Styles.TOOLBAR);
toolbar.classList.add(this.getToolbarProps() === 'read-only' ? MiniBrowserContentStyle.TOOLBAR_READ_ONLY : MiniBrowserContentStyle.TOOLBAR);
parent.appendChild(toolbar);
this.createPrevious(toolbar);
this.createNext(toolbar);
Expand All @@ -292,10 +293,10 @@ export class MiniBrowserContent extends BaseWidget {
// tslint:disable-next-line:max-line-length
protected createContentArea(parent: HTMLElement): HTMLElement & Readonly<{ frame: HTMLIFrameElement, loadIndicator: HTMLElement, errorBar: HTMLElement & Readonly<{ message: HTMLElement }>, pdfContainer: HTMLElement, transparentOverlay: HTMLElement }> {
const contentArea = document.createElement('div');
contentArea.classList.add(MiniBrowserContent.Styles.CONTENT_AREA);
contentArea.classList.add(MiniBrowserContentStyle.CONTENT_AREA);

const loadIndicator = document.createElement('div');
loadIndicator.classList.add(MiniBrowserContent.Styles.PRE_LOAD);
loadIndicator.classList.add(MiniBrowserContentStyle.PRE_LOAD);
loadIndicator.style.display = 'none';

const errorBar = this.createErrorBar();
Expand All @@ -310,11 +311,11 @@ export class MiniBrowserContent extends BaseWidget {
this.openEmitter.event(this.handleOpen.bind(this));

const transparentOverlay = document.createElement('div');
transparentOverlay.classList.add(MiniBrowserContent.Styles.TRANSPARENT_OVERLAY);
transparentOverlay.classList.add(MiniBrowserContentStyle.TRANSPARENT_OVERLAY);
transparentOverlay.style.display = 'none';

const pdfContainer = document.createElement('div');
pdfContainer.classList.add(MiniBrowserContent.Styles.PDF_CONTAINER);
pdfContainer.classList.add(MiniBrowserContentStyle.PDF_CONTAINER);
pdfContainer.id = `${this.id}-pdf-container`;
pdfContainer.style.display = 'none';

Expand All @@ -339,7 +340,7 @@ export class MiniBrowserContent extends BaseWidget {

protected createErrorBar(): HTMLElement & Readonly<{ message: HTMLElement }> {
const errorBar = document.createElement('div');
errorBar.classList.add(MiniBrowserContent.Styles.ERROR_BAR);
errorBar.classList.add(MiniBrowserContentStyle.ERROR_BAR);
errorBar.style.display = 'none';

const icon = document.createElement('span');
Expand Down Expand Up @@ -374,21 +375,21 @@ export class MiniBrowserContent extends BaseWidget {
}

protected showLoadIndicator(): void {
this.loadIndicator.classList.remove(MiniBrowserContent.Styles.FADE_OUT);
this.loadIndicator.classList.remove(MiniBrowserContentStyle.FADE_OUT);
this.loadIndicator.style.display = 'block';
}

protected hideLoadIndicator(): void {
// Start the fade-out transition.
this.loadIndicator.classList.add(MiniBrowserContent.Styles.FADE_OUT);
this.loadIndicator.classList.add(MiniBrowserContentStyle.FADE_OUT);
// Actually hide the load indicator after the transition is finished.
const preloadStyle = window.getComputedStyle(this.loadIndicator);
const transitionDuration = parseCssTime(preloadStyle.transitionDuration, 0);
setTimeout(() => {
// But don't hide it if it was shown again since the transition started.
if (this.loadIndicator.classList.contains(MiniBrowserContent.Styles.FADE_OUT)) {
if (this.loadIndicator.classList.contains(MiniBrowserContentStyle.FADE_OUT)) {
this.loadIndicator.style.display = 'none';
this.loadIndicator.classList.remove(MiniBrowserContent.Styles.FADE_OUT);
this.loadIndicator.classList.remove(MiniBrowserContentStyle.FADE_OUT);
}
}, transitionDuration);
}
Expand Down Expand Up @@ -480,34 +481,34 @@ export class MiniBrowserContent extends BaseWidget {
}

protected createPrevious(parent: HTMLElement): HTMLElement {
return this.onClick(this.createButton(parent, 'Show The Previous Page', MiniBrowserContent.Styles.PREVIOUS), this.navigateBackEmitter);
return this.onClick(this.createButton(parent, 'Show The Previous Page', MiniBrowserContentStyle.PREVIOUS), this.navigateBackEmitter);
}

protected createNext(parent: HTMLElement): HTMLElement {
return this.onClick(this.createButton(parent, 'Show The Next Page', MiniBrowserContent.Styles.NEXT), this.navigateForwardEmitter);
return this.onClick(this.createButton(parent, 'Show The Next Page', MiniBrowserContentStyle.NEXT), this.navigateForwardEmitter);
}

protected createRefresh(parent: HTMLElement): HTMLElement {
return this.onClick(this.createButton(parent, 'Reload This Page', MiniBrowserContent.Styles.REFRESH), this.refreshEmitter);
return this.onClick(this.createButton(parent, 'Reload This Page', MiniBrowserContentStyle.REFRESH), this.refreshEmitter);
}

protected createOpen(parent: HTMLElement): HTMLElement {
const button = this.onClick(this.createButton(parent, 'Open In A New Window', MiniBrowserContent.Styles.OPEN), this.openEmitter);
const button = this.onClick(this.createButton(parent, 'Open In A New Window', MiniBrowserContentStyle.OPEN), this.openEmitter);
return button;
}

protected createButton(parent: HTMLElement, title: string, ...className: string[]): HTMLElement {
const button = document.createElement('div');
button.title = title;
button.classList.add(...className, MiniBrowserContent.Styles.BUTTON);
button.classList.add(...className, MiniBrowserContentStyle.BUTTON);
parent.appendChild(button);
return button;
}

// tslint:disable-next-line:no-any
protected onClick(element: HTMLElement, emitter: Emitter<any>): HTMLElement {
this.toDispose.push(addEventListener(element, 'click', () => {
if (!element.classList.contains(MiniBrowserContent.Styles.DISABLED)) {
if (!element.classList.contains(MiniBrowserContentStyle.DISABLED)) {
emitter.fire(undefined);
}
}));
Expand Down Expand Up @@ -629,27 +630,3 @@ export class MiniBrowserContent extends BaseWidget {
}

}

export namespace MiniBrowserContent {

export namespace Styles {

export const MINI_BROWSER = 'theia-mini-browser';
export const TOOLBAR = 'theia-mini-browser-toolbar';
export const TOOLBAR_READ_ONLY = 'theia-mini-browser-toolbar-read-only';
export const PRE_LOAD = 'theia-mini-browser-load-indicator';
export const FADE_OUT = 'theia-fade-out';
export const CONTENT_AREA = 'theia-mini-browser-content-area';
export const PDF_CONTAINER = 'theia-mini-browser-pdf-container';
export const PREVIOUS = 'theia-mini-browser-previous';
export const NEXT = 'theia-mini-browser-next';
export const REFRESH = 'theia-mini-browser-refresh';
export const OPEN = 'theia-mini-browser-open';
export const BUTTON = 'theia-mini-browser-button';
export const DISABLED = 'theia-mini-browser-button-disabled';
export const TRANSPARENT_OVERLAY = 'theia-mini-browser-transparent-overlay';
export const ERROR_BAR = 'theia-mini-browser-error-bar';

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

// tslint:disable:no-any

import CodeUri from 'vscode-uri';
import { injectable, inject } from 'inversify';
import { MenuPath, ILogger, CommandRegistry, Command, Mutable, MenuAction, SelectionService, CommandHandler } from '@theia/core';
import { EDITOR_CONTEXT_MENU, EditorWidget } from '@theia/editor/lib/browser';
Expand All @@ -35,6 +36,19 @@ import { PluginScmProvider, PluginScmResourceGroup, PluginScmResource } from '..
import { ResourceContextKey } from '@theia/core/lib/browser/resource-context-key';
import { PluginViewWidget } from '../view/plugin-view-widget';
import { ViewContextKeyService } from '../view/view-context-key-service';
import { WebviewWidget } from '../webview/webview';
import { Navigatable } from '@theia/core/lib/browser/navigatable';

type CodeEditorWidget = EditorWidget | WebviewWidget;
export namespace CodeEditorWidget {
export function is(arg: any): arg is CodeEditorWidget {
return arg instanceof EditorWidget || arg instanceof WebviewWidget;
}
export function getResourceUri(editor: CodeEditorWidget): CodeUri | undefined {
const resourceUri = Navigatable.is(editor) && editor.getResourceUri();
return resourceUri ? resourceUri['codeUri'] : undefined;
}
}

@injectable()
export class MenusContributionPointHandler {
Expand Down Expand Up @@ -80,14 +94,10 @@ export class MenusContributionPointHandler {
}
} else if (location === 'editor/title') {
for (const action of allMenus[location]) {
const selectedResource = (widget: EditorWidget) => {
const resourceUri = widget.getResourceUri();
return resourceUri && resourceUri['codeUri'];
};
this.registerTitleAction(location, action, {
execute: widget => widget instanceof EditorWidget && this.commands.executeCommand(action.command, selectedResource(widget)),
isEnabled: widget => widget instanceof EditorWidget && this.commands.isEnabled(action.command, selectedResource(widget)),
isVisible: widget => widget instanceof EditorWidget && this.commands.isVisible(action.command, selectedResource(widget))
execute: widget => CodeEditorWidget.is(widget) && this.commands.executeCommand(action.command, CodeEditorWidget.getResourceUri(widget)),
isEnabled: widget => CodeEditorWidget.is(widget) && this.commands.isEnabled(action.command, CodeEditorWidget.getResourceUri(widget)),
isVisible: widget => CodeEditorWidget.is(widget) && this.commands.isVisible(action.command, CodeEditorWidget.getResourceUri(widget))
});
}
} else if (location === 'view/title') {
Expand Down Expand Up @@ -180,8 +190,10 @@ export class MenusContributionPointHandler {
const command: Command = { id };
this.commands.registerCommand(command, handler);

const { group, when } = action;
const item: Mutable<TabBarToolbarItem> = { id, command: id, group: group || '', when };
const { when } = action;
const [group, sort] = (action.group!.trim() || 'navigation').split('@');
// handle group and priority 1_rest-client@1 navigation@1
const item: Mutable<TabBarToolbarItem> = { id, command: id, group, priority: ~~sort || undefined, when };
this.tabBarToolbar.registerItem(item);

this.onDidRegisterCommand(action.command, pluginCommand => {
Expand Down
4 changes: 2 additions & 2 deletions packages/plugin-ext/src/main/browser/webview/webview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import { BaseWidget, Message } from '@theia/core/lib/browser/widgets/widget';
import { IdGenerator } from '../../../common/id-generator';
import { Disposable } from '@theia/core';
import { MiniBrowserContent } from '@theia/mini-browser/lib/browser/mini-browser-content';
import { MiniBrowserContentStyle } from '@theia/mini-browser/lib/browser/mini-browser-content-style';
import { ApplicationShellMouseTracker } from '@theia/core/lib/browser/shell/application-shell-mouse-tracker';

// tslint:disable:no-any
Expand Down Expand Up @@ -55,7 +55,7 @@ export class WebviewWidget extends BaseWidget {
this.scrollY = 0;

this.transparentOverlay = document.createElement('div');
this.transparentOverlay.classList.add(MiniBrowserContent.Styles.TRANSPARENT_OVERLAY);
this.transparentOverlay.classList.add(MiniBrowserContentStyle.TRANSPARENT_OVERLAY);
this.transparentOverlay.style.display = 'none';
this.node.appendChild(this.transparentOverlay);

Expand Down

0 comments on commit e3ad30e

Please sign in to comment.