Skip to content

Commit

Permalink
feat(editor): add split window and some features for editor
Browse files Browse the repository at this point in the history
  • Loading branch information
wewoor committed Dec 31, 2020
1 parent 1ea93c1 commit 3bf957b
Show file tree
Hide file tree
Showing 13 changed files with 250 additions and 81 deletions.
6 changes: 3 additions & 3 deletions src/components/monaco/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from 'react';
import { Component } from 'react';
import { PureComponent } from 'react';
import * as monaco from 'monaco-editor';
import { APP_PREFIX } from 'mo/common/const';

Expand All @@ -21,7 +21,7 @@ export interface IMonacoEditorProps extends React.ComponentProps<any> {
editorInstanceRef?: (instance: monaco.editor.IStandaloneCodeEditor) => void;
}

export default class MonacoEditor extends Component<IMonacoEditorProps> {
export default class MonacoEditor extends PureComponent<IMonacoEditorProps> {
/**
* The instance of monaco
*/
Expand Down Expand Up @@ -55,7 +55,7 @@ export default class MonacoEditor extends Component<IMonacoEditorProps> {

render() {
const { style } = this.props;
let renderStyle: any = {
let renderStyle: React.CSSProperties = {
position: 'relative',
minHeight: '400px',
height: '100%',
Expand Down
5 changes: 3 additions & 2 deletions src/components/tabs/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export interface ITabs<T> extends React.ComponentProps<any> {
data?: ITab<T>[];
activeTab?: string;
type?: TabsType;
style?: React.CSSProperties;
onCloseTab?: (key?: string) => void;
onMoveTab?: (tabs: ITab<T>[]) => void;
onSelectTab?: (key?: string) => void;
Expand All @@ -34,7 +35,7 @@ export function Tabs<T>(props: ITabs<T>) {
activeTab,
data = [],
type = 'line',
closable,
style,
onMoveTab,
...resetProps
} = props;
Expand All @@ -57,11 +58,11 @@ export function Tabs<T>(props: ITabs<T>) {
return (
<DragAndDrop>
<div
style={style}
className={classNames(
tabsClassName,
getBEMModifier(tabsClassName, type as string)
)}
{...resetProps}
>
<div className={tabsHeader}>
{data?.map((tab: ITab<T>, index: number) => {
Expand Down
2 changes: 1 addition & 1 deletion src/components/tabs/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
height: 36px;
justify-content: flex-start;
overflow: hidden;
overflow-x: auto;
overflow-x: inherit;
overflow-y: hidden;
width: 100%;
}
Expand Down
11 changes: 10 additions & 1 deletion src/components/tabs/tab.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from 'react';
import { useRef, useState } from 'react';
import { useCallback, useRef, useState } from 'react';
import { findDOMNode } from 'react-dom';
import {
DragSourceMonitor,
Expand Down Expand Up @@ -31,6 +31,7 @@ export interface ITabEvent {
onMoveTab?: (dragIndex: number, hoverIndex: number) => void;
onCloseTab?: (key?: string) => void;
onSelectTab?: (key?: string) => void;
onContextMenu?: <T = any>(event: React.MouseEvent, tab: ITab<T>) => void;
}
export const tabClassName = prefixClaName('tab');
export const tabItemClassName = getBEMElement(tabClassName, 'item');
Expand All @@ -46,13 +47,20 @@ export function Tab<T>(props: ITab<T> & ITabEvent) {
onCloseTab,
onMoveTab,
onSelectTab,
onContextMenu,
...resetProps
} = props;
const ref = useRef<HTMLDivElement>(null);

const [hover, setHover] = useState(false);
const handleMouseOver = () => setHover(true);
const handleMouseOut = () => setHover(false);
const handleOnContextMenu = useCallback(
(event: React.MouseEvent) => {
onContextMenu?.(event, props);
},
[props]
);

const [, drag] = useDrag({
collect: (monitor: DragSourceMonitor) => ({
Expand Down Expand Up @@ -107,6 +115,7 @@ export function Tab<T>(props: ITab<T> & ITabEvent) {
onClick={(event: React.MouseEvent) => onSelectTab?.(id)}
onMouseOver={handleMouseOver}
onMouseOut={handleMouseOut}
onContextMenu={handleOnContextMenu}
>
{label || name}
{closable && (
Expand Down
68 changes: 65 additions & 3 deletions src/controller/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,28 @@ import { EditorEvent, IEditorTab } from 'mo/model/workbench/editor';
import { Controller } from 'mo/react/controller';
import { editorService } from 'mo/services';
import { singleton } from 'tsyringe';

export interface IEditorController {
groupSplitPos?: string[];
onCloseAll?: (group: number) => void;
onCloseTab?: (tabKey: string, group: number) => void;
onMoveTab?: <T = any>(updateTabs: IEditorTab<T>[], group: number) => void;
onSelectTab?: (tabKey: string, group: number) => void;
onSplitEditorRight?: () => void;
onUpdateEditorIns?: (editorInstance: any, groupId: number) => void;
onPaneSizeChange?: (newSize: number) => void;
onTabContextMenu?: (e: React.MouseEvent, tab: IEditorTab) => void;
}

@singleton()
export class EditorController extends Controller implements IEditorController {
private editorInstance;
// Group Pos locate here temporary, we can move it to state or localStorage if you need
public groupSplitPos: string[] = [];

constructor() {
super();
}

public onCloseAll = (groupId: number) => {
editorService.closeAll(groupId);
this.emit(EditorEvent.OnCloseAll, groupId);
Expand All @@ -34,12 +44,18 @@ export class EditorController extends Controller implements IEditorController {
};

public onSelectTab = (tabKey: string, groupId: number) => {
editorService.updateCurrent(groupId, tabKey);
editorService.setActive(groupId, tabKey);
const { current } = editorService.getState();
current?.editorInstance.setValue(current.tab?.data.value);
this.emit(EditorEvent.OnSelectTab, tabKey, groupId);
};

public onUpdateEditorIns = (editorInstance: any, groupId: number) => {
public onUpdateEditorIns = (
editorInstance: IStandaloneCodeEditor,
groupId: number
) => {
if (editorInstance) {
this.initEditorEvents(editorInstance, groupId);
editorService.updateGroup(groupId, {
editorInstance: editorInstance,
});
Expand All @@ -50,4 +66,50 @@ export class EditorController extends Controller implements IEditorController {
editorService.cloneGroup();
this.emit(EditorEvent.OnSplitEditorRight);
};

public onPaneSizeChange = (newSize) => {
this.groupSplitPos = newSize;
};

public onTabContextMenu = (e: React.MouseEvent, tab: IEditorTab) => {
console.log('onTabContextMenu', e, tab);
};

private initEditorEvents(
editorInstance: IStandaloneCodeEditor,
groupId: number
) {
this.editorInstance = editorInstance;
if (editorInstance) {
editorInstance.onDidChangeModelContent((event: any) => {
const newValue = editorInstance.getValue();
const { current } = editorService.getState();
const tab = current?.tab;
if (tab) {
editorService.updateTab(
{
id: tab.id,
data: {
...tab.data,
value: newValue,
},
modified: true,
},
groupId
);
}
});

editorInstance.onDidFocusEditorText(() => {
const group = editorService.getGroupById(groupId);
if (group?.tab!.id) {
editorService.setActive(groupId, group.tab.id);
}
});
}
}

getEditorInstance() {
return this.editorInstance;
}
}
2 changes: 1 addition & 1 deletion src/extensions/search/searchPane.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ export default class SearchPane extends React.Component<
breadcrumb: [{ id: `${key}`, name: 'editor.js' }],
};
console.log('open editor:', tabData);
editorService.open(tabData, 1);
editorService.open(tabData);
};

const openCommand = function () {};
Expand Down
54 changes: 40 additions & 14 deletions src/model/workbench/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,26 +23,17 @@ export interface IEditorTab<T = BuiltInEditorTabDataType> extends ITab<T> {
modified?: boolean;
breadcrumb?: IBreadcrumbItem[];
}

export interface IEditorActionItem {
id?: number;
icon?: ReactNode;
title?: string;
onClick?: (e: React.MouseEvent) => void;
}

export interface IEditorAction {
actions?: IEditorActionItem[];
actions?: IMenuItem[];
menu?: IMenuItem[];
}

export interface IEditorGroup<E = any, T = any> extends ITabs<T> {
id?: number;
/**
* Current editor group tab
*/
tab?: IEditorTab<T>;
actions?: IEditorActionItem[];
actions?: IMenuItem[];
menu?: IMenuItem[];
editorInstance?: E;
}
Expand All @@ -54,20 +45,55 @@ export interface IEditor {
groups?: IEditorGroup[];
}

const baseMenu = [
{
id: 'closeToRight',
name: 'Close To Right',
},
{
id: 'closeSaved',
name: 'Close Saved',
},
];

const initialActions: IMenuItem[] = [
{
id: 'showOpenEditors',
name: 'Show Opened Editors',
},
...baseMenu,
];

const initialMenu: IMenuItem[] = [
{
id: 'close',
name: 'Close',
},
{
id: 'closeOther',
name: 'Close Others',
},
{
id: 'closeToRight',
name: 'Close To Right',
},
...baseMenu,
];

export class EditorGroupModel<E = any, T = any> implements IEditorGroup<E, T> {
id: number;
tab: IEditorTab<T>;
data: IEditorTab<T>[];
actions: IEditorActionItem[];
actions: IMenuItem[];
menu: IMenuItem[];
editorInstance: E | undefined;

constructor(
id: number,
tab: IEditorTab<T>,
data: IEditorTab<T>[],
actions: IEditorActionItem[] = [],
menu: IMenuItem[] = [],
actions: IMenuItem[] = initialActions,
menu: IMenuItem[] = initialMenu,
editorInstance?: E
) {
this.id = id;
Expand Down
3 changes: 3 additions & 0 deletions src/services/helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function searchById(id) {
return (item) => item.id === id;
}
Loading

0 comments on commit 3bf957b

Please sign in to comment.