Skip to content

Commit

Permalink
Merge branch 'master' into theia#3882
Browse files Browse the repository at this point in the history
  • Loading branch information
vzhukovs committed Mar 21, 2019
2 parents fb82bdf + 6a07cec commit 6aab7e0
Show file tree
Hide file tree
Showing 73 changed files with 1,094 additions and 442 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ Breaking changes:
- [plugin] support multiple windows per a backend [#4509](https://github.com/theia-ide/theia/issues/4509)
- Some plugin bindings are scoped per a connection now. Clients, who contribute/rebind these bindings, will need to scope them per a connection as well.
- [quick-open] disable separate fuzzy matching by default [#4549](https://github.com/theia-ide/theia/pull/4549)
- [shell] support toolbars in side bars [#4600](https://github.com/theia-ide/theia/pull/4600)
- In side bars a widget title is rendered as an icon.

## v0.4.0
- [application-manager] added support for pre-load HTML templates
Expand Down
2 changes: 1 addition & 1 deletion examples/browser/test/left-panel/left-panel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export class LeftPanel {
}

openCloseTab(tabName: string) {
this.driver.element('.p-TabBar.theia-app-left .p-TabBar-content').click(`div=${tabName}`);
this.driver.element('.p-TabBar.theia-app-left .p-TabBar-content').element(`div=${tabName}`).click('..');
// Wait for animations to finish
this.driver.pause(300);
}
Expand Down
12 changes: 6 additions & 6 deletions examples/browser/test/left-panel/left-panel.ui-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,20 @@ before(() => {
});

describe('theia left panel', () => {
it("should show 'Files' and 'Git'", () => {
expect(leftPanel.doesTabExist('Files')).to.be.true;
it("should show 'Explorer' and 'Git'", () => {
expect(leftPanel.doesTabExist('Explorer')).to.be.true;
expect(leftPanel.doesTabExist('Git')).to.be.true;
});

describe('files tab', () => {
it('should open/close the files tab', () => {
leftPanel.openCloseTab('Files');
leftPanel.openCloseTab('Explorer');
expect(leftPanel.isFileTreeVisible()).to.be.true;
expect(leftPanel.isTabActive('Files')).to.be.true;
expect(leftPanel.isTabActive('Explorer')).to.be.true;

leftPanel.openCloseTab('Files');
leftPanel.openCloseTab('Explorer');
expect(leftPanel.isFileTreeVisible()).to.be.false;
expect(leftPanel.isTabActive('Files')).to.be.false;
expect(leftPanel.isTabActive('Explorer')).to.be.false;
});
});

Expand Down
2 changes: 1 addition & 1 deletion examples/browser/test/right-panel/right-panel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export class RightPanel {
}

openCloseTab(tabName: string) {
this.driver.element('.p-TabBar.theia-app-right .p-TabBar-content').click(`div=${tabName}`);
this.driver.element('.p-TabBar.theia-app-right .p-TabBar-content').element(`div=${tabName}`).click('..');
// Wait for animations to finish
this.driver.pause(300);
}
Expand Down
2 changes: 1 addition & 1 deletion examples/browser/test/top-panel/top-panel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export class TopPanel {

toggleFilesView() {
this.clickMenuTab('View');
this.clickSubMenu('Files');
this.clickSubMenu('Explorer');
}

toggleGitView() {
Expand Down
4 changes: 3 additions & 1 deletion packages/core/src/browser/frontend-application-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ import { LocalStorageService, StorageService } from './storage-service';
import { WidgetFactory, WidgetManager } from './widget-manager';
import {
ApplicationShell, ApplicationShellOptions, DockPanelRenderer, TabBarRenderer,
TabBarRendererFactory, ShellLayoutRestorer, SidePanelHandler, SidePanelHandlerFactory, SplitPositionHandler, DockPanelRendererFactory
TabBarRendererFactory, ShellLayoutRestorer,
SidePanelHandler, SidePanelHandlerFactory,
SplitPositionHandler, DockPanelRendererFactory
} from './shell';
import { StatusBar, StatusBarImpl } from './status-bar/status-bar';
import { LabelParser } from './label-parser';
Expand Down
4 changes: 4 additions & 0 deletions packages/core/src/browser/icons/open-change-bright.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions packages/core/src/browser/icons/open-change-dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions packages/core/src/browser/icons/preview-bright.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions packages/core/src/browser/icons/preview-dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
72 changes: 5 additions & 67 deletions packages/core/src/browser/preferences/preference-contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ import { ContributionProvider, bindContributionProvider, escapeRegExpCharacters,
import { PreferenceScope } from './preference-scope';
import { PreferenceProvider, PreferenceProviderPriority, PreferenceProviderDataChange } from './preference-provider';

import {
PreferenceSchema, PreferenceSchemaProperties, PreferenceDataSchema, PreferenceItem, PreferenceSchemaProperty, PreferenceDataProperty, JsonType
} from '../../common/preferences/preference-schema';
export { PreferenceSchema, PreferenceSchemaProperties, PreferenceDataSchema, PreferenceItem, PreferenceSchemaProperty, PreferenceDataProperty, JsonType };

// tslint:disable:no-any
// tslint:disable:forin

Expand All @@ -28,73 +33,6 @@ export interface PreferenceContribution {
readonly schema: PreferenceSchema;
}

export interface PreferenceSchema {
[name: string]: any,
scope?: 'application' | 'window' | 'resource' | PreferenceScope,
overridable?: boolean;
properties: PreferenceSchemaProperties
}
export namespace PreferenceSchema {
export function getDefaultScope(schema: PreferenceSchema): PreferenceScope {
let defaultScope: PreferenceScope = PreferenceScope.Workspace;
if (!PreferenceScope.is(schema.scope)) {
defaultScope = PreferenceScope.fromString(<string>schema.scope) || PreferenceScope.Workspace;
} else {
defaultScope = schema.scope;
}
return defaultScope;
}
}

export interface PreferenceSchemaProperties {
[name: string]: PreferenceSchemaProperty
}

export interface PreferenceDataSchema {
[name: string]: any,
scope?: PreferenceScope,
properties: {
[name: string]: PreferenceDataProperty
}
patternProperties: {
[name: string]: PreferenceDataProperty
};
}

export interface PreferenceItem {
type?: JsonType | JsonType[];
minimum?: number;
default?: any;
enum?: string[];
items?: PreferenceItem;
properties?: { [name: string]: PreferenceItem };
additionalProperties?: object;
[name: string]: any;
overridable?: boolean;
}

export interface PreferenceSchemaProperty extends PreferenceItem {
description?: string;
scope?: 'application' | 'window' | 'resource' | PreferenceScope;
}

export interface PreferenceDataProperty extends PreferenceItem {
description?: string;
scope?: PreferenceScope;
}
export namespace PreferenceDataProperty {
export function fromPreferenceSchemaProperty(schemaProps: PreferenceSchemaProperty, defaultScope: PreferenceScope = PreferenceScope.Workspace): PreferenceDataProperty {
if (!schemaProps.scope) {
schemaProps.scope = defaultScope;
} else if (typeof schemaProps.scope === 'string') {
return Object.assign(schemaProps, { scope: PreferenceScope.fromString(schemaProps.scope) || defaultScope });
}
return <PreferenceDataProperty>schemaProps;
}
}

export type JsonType = 'string' | 'array' | 'number' | 'integer' | 'object' | 'boolean' | 'null';

export function bindPreferenceSchemaProvider(bind: interfaces.Bind): void {
bind(PreferenceSchemaProvider).toSelf().inSingletonScope();
bindContributionProvider(bind, PreferenceContribution);
Expand Down
51 changes: 2 additions & 49 deletions packages/core/src/browser/preferences/preference-scope.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,52 +14,5 @@
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/

// tslint:disable:no-any

export enum PreferenceScope {
Default,
User,
Workspace,
Folder
}

export namespace PreferenceScope {
export function is(scope: any): scope is PreferenceScope {
return typeof scope === 'number' && getScopes().findIndex(s => s === scope) >= 0;
}

export function getScopes(): PreferenceScope[] {
return Object.keys(PreferenceScope)
.filter(k => typeof PreferenceScope[k as any] === 'string')
.map(v => <PreferenceScope>Number(v));
}

export function getReversedScopes(): PreferenceScope[] {
return getScopes().reverse();
}

export function getScopeNames(scope?: PreferenceScope): string[] {
const names: string[] = [];
const allNames = Object.keys(PreferenceScope)
.filter(k => typeof PreferenceScope[k as any] === 'number');
if (scope) {
for (const name of allNames) {
if ((<any>PreferenceScope)[name] <= scope) {
names.push(name);
}
}
}
return names;
}

export function fromString(strScope: string): PreferenceScope | undefined {
switch (strScope) {
case 'application':
return PreferenceScope.User;
case 'window':
return PreferenceScope.Workspace;
case 'resource':
return PreferenceScope.Folder;
}
}
}
import { PreferenceScope } from '../../common/preferences/preference-scope';
export { PreferenceScope };
33 changes: 28 additions & 5 deletions packages/core/src/browser/shell/side-panel-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import { TabBarRendererFactory, TabBarRenderer, SHELL_TABBAR_CONTEXT_MENU, SideT
import { SplitPositionHandler, SplitPositionOptions } from './split-panels';
import { FrontendApplicationStateService } from '../frontend-application-state';
import { TheiaDockPanel } from './theia-dock-panel';
import { SidePanelToolbar } from './side-panel-toolbar';
import { TabBarToolbarRegistry, TabBarToolbarFactory, TabBarToolbar } from './tab-bar-toolbar';

/** The class name added to the left and right area panels. */
export const LEFT_RIGHT_AREA_CLASS = 'theia-app-sides';
Expand Down Expand Up @@ -56,6 +58,10 @@ export class SidePanelHandler {
* tab bar itself remains visible as long as there is at least one widget.
*/
tabBar: SideTabBar;
/**
* A tool bar, which displays a title and widget specific command buttons.
*/
toolBar: SidePanelToolbar;
/**
* The widget container is a dock panel in `single-document` mode, which means that the panel
* cannot be split.
Expand Down Expand Up @@ -85,6 +91,8 @@ export class SidePanelHandler {
*/
protected options: SidePanel.Options;

@inject(TabBarToolbarRegistry) protected tabBarToolBarRegistry: TabBarToolbarRegistry;
@inject(TabBarToolbarFactory) protected tabBarToolBarFactory: () => TabBarToolbar;
@inject(TabBarRendererFactory) protected tabBarRendererFactory: () => TabBarRenderer;
@inject(SplitPositionHandler) protected splitPositionHandler: SplitPositionHandler;
@inject(FrontendApplicationStateService) protected readonly applicationStateService: FrontendApplicationStateService;
Expand All @@ -96,6 +104,7 @@ export class SidePanelHandler {
this.side = side;
this.options = options;
this.tabBar = this.createSideBar();
this.toolBar = this.createToolbar();
this.dockPanel = this.createSidePanel();
this.container = this.createContainer();

Expand Down Expand Up @@ -152,7 +161,19 @@ export class SidePanelHandler {
return sidePanel;
}

protected createToolbar(): SidePanelToolbar {
const toolbar = new SidePanelToolbar(this.tabBarToolBarRegistry, this.tabBarToolBarFactory, this.side);
return toolbar;
}

protected createContainer(): Panel {
const contentBox = new BoxLayout({ direction: 'top-to-bottom', spacing: 0 });
BoxPanel.setStretch(this.toolBar, 0);
contentBox.addWidget(this.toolBar);
BoxPanel.setStretch(this.dockPanel, 1);
contentBox.addWidget(this.dockPanel);
const contentPanel = new BoxPanel({layout: contentBox});

const side = this.side;
let direction: BoxLayout.Direction;
switch (side) {
Expand All @@ -165,12 +186,12 @@ export class SidePanelHandler {
default:
throw new Error('Illegal argument: ' + side);
}
const boxLayout = new BoxLayout({ direction, spacing: 0 });
const containerLayout = new BoxLayout({ direction, spacing: 0 });
BoxPanel.setStretch(this.tabBar, 0);
boxLayout.addWidget(this.tabBar);
BoxPanel.setStretch(this.dockPanel, 1);
boxLayout.addWidget(this.dockPanel);
const boxPanel = new BoxPanel({ layout: boxLayout });
containerLayout.addWidget(this.tabBar);
BoxPanel.setStretch(contentPanel, 1);
containerLayout.addWidget(contentPanel);
const boxPanel = new BoxPanel({ layout: containerLayout });
boxPanel.id = 'theia-' + side + '-content-panel';
return boxPanel;
}
Expand Down Expand Up @@ -327,6 +348,8 @@ export class SidePanelHandler {
const hideDockPanel = currentTitle === null;
let relativeSizes: number[] | undefined;

this.toolBar.toolbarTitle = currentTitle || undefined;

if (hideDockPanel) {
container.addClass(COLLAPSED_CLASS);
if (this.state.expansion === SidePanel.ExpansionState.expanded && !this.state.empty) {
Expand Down
Loading

0 comments on commit 6aab7e0

Please sign in to comment.