rebuild editor setting ui, bind open and save events
This commit is contained in:
@@ -9,8 +9,7 @@ import "../editor";
|
||||
import { IC10Editor } from "../editor";
|
||||
import { Session } from "../session";
|
||||
import { VirtualMachine } from "../virtual_machine";
|
||||
|
||||
|
||||
import { openFile, saveFile } from "../utils";
|
||||
|
||||
@customElement("ic10emu-app")
|
||||
export class App extends BaseElement {
|
||||
@@ -42,7 +41,7 @@ export class App extends BaseElement {
|
||||
editorSettings: { fontSize: number; relativeLineNumbers: boolean };
|
||||
|
||||
get editor() {
|
||||
return this.renderRoot.querySelector('ace-ic10') as IC10Editor;
|
||||
return this.renderRoot.querySelector("ace-ic10") as IC10Editor;
|
||||
}
|
||||
|
||||
vm!: VirtualMachine;
|
||||
@@ -56,10 +55,18 @@ export class App extends BaseElement {
|
||||
|
||||
}
|
||||
|
||||
protected createRenderRoot(): HTMLElement | DocumentFragment {
|
||||
const root = super.createRenderRoot();
|
||||
root.addEventListener('app-share-session', this._handleShare);
|
||||
root.addEventListener('app-open-file', this._handleOpenFile);
|
||||
root.addEventListener('app-save-as', this._handleSaveAs);
|
||||
return root;
|
||||
}
|
||||
|
||||
protected render(): HTMLTemplateResult {
|
||||
return html`
|
||||
<div class="app-container">
|
||||
<app-nav class=z-fix></app-nav>
|
||||
<app-nav class="z-fix"></app-nav>
|
||||
<div class="app-body">
|
||||
<sl-split-panel
|
||||
style="--min: 20em; --max: calc(100% - 20em);"
|
||||
@@ -74,6 +81,22 @@ export class App extends BaseElement {
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
firstUpdated(): void {
|
||||
}
|
||||
|
||||
_handleShare(_e: Event) {
|
||||
// TODO:
|
||||
}
|
||||
|
||||
_handleSaveAs(_e: Event) {
|
||||
saveFile(window.Editor.editorValue);
|
||||
}
|
||||
|
||||
_handleOpenFile(_e: Event) {
|
||||
openFile(window.Editor.editor);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
declare global {
|
||||
@@ -81,4 +104,3 @@ declare global {
|
||||
App?: App;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import "@shoelace-style/shoelace/dist/components/menu/menu.js";
|
||||
import "@shoelace-style/shoelace/dist/components/divider/divider.js";
|
||||
import "@shoelace-style/shoelace/dist/components/menu-item/menu-item.js";
|
||||
import "@shoelace-style/shoelace/dist/components/dropdown/dropdown.js";
|
||||
import SlMenuItem from "@shoelace-style/shoelace/dist/components/menu-item/menu-item.js";
|
||||
|
||||
@customElement("app-nav")
|
||||
export class Nav extends BaseElement {
|
||||
@@ -100,15 +101,15 @@ export class Nav extends BaseElement {
|
||||
label="Main Menu"
|
||||
></sl-icon-button>
|
||||
|
||||
<sl-menu class="menu">
|
||||
<sl-menu class="menu" @sl-select=${this._menuClickHandler}>
|
||||
<sl-menu-item value="share">Share</sl-menu-item>
|
||||
<sl-menu-item value="openFile">Open File</sl-menu-item>
|
||||
<sl-menu-item value="saveAs">Save As</sl-menu-item>
|
||||
<sl-devider></sl-devider>
|
||||
<sl-divider></sl-divider>
|
||||
<sl-menu-item value="editorSettings"
|
||||
>Editor Settings</sl-menu-item
|
||||
>
|
||||
<sl-devider></sl-devider>
|
||||
<sl-divider></sl-divider>
|
||||
<sl-menu-item value="keyboardShortcuts"
|
||||
>Editor Keyboard Shortcuts</sl-menu-item
|
||||
>
|
||||
@@ -161,4 +162,31 @@ export class Nav extends BaseElement {
|
||||
</nav>
|
||||
`;
|
||||
}
|
||||
|
||||
firstUpdated(): void {}
|
||||
|
||||
_menuClickHandler(e: CustomEvent) {
|
||||
const item = e.detail.item as SlMenuItem;
|
||||
switch (item.value) {
|
||||
case "share":
|
||||
this.dispatchEvent(
|
||||
new CustomEvent("app-share-session", { bubbles: true }),
|
||||
);
|
||||
break;
|
||||
case "openFile":
|
||||
this.dispatchEvent(new CustomEvent("app-open-file", { bubbles: true }));
|
||||
break;
|
||||
case "saveAs":
|
||||
this.dispatchEvent(new CustomEvent("app-save-as", { bubbles: true }));
|
||||
break;
|
||||
case "editorSettings":
|
||||
window.Editor?.settingDialog.show();
|
||||
break;
|
||||
case "keyboardShortcuts":
|
||||
// TODO: bind
|
||||
break;
|
||||
default:
|
||||
console.log("Unknown main menu item", item.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
import * as ace from "ace-code"
|
||||
|
||||
// make sure Ace can load through webpack
|
||||
// trimmed down version of https://github.com/ajaxorg/ace-builds/blob/master/esm-resolver.js but for ace-code
|
||||
ace.config.setModuleLoader("ace/theme/one_dark", () => import("ace-code/src/theme/one_dark"));
|
||||
ace.config.setModuleLoader("ace/theme/textmate", () => import("ace-code/src/theme/textmate"));
|
||||
|
||||
ace.config.setModuleLoader('ace/ext/beautify', () => import('ace-code/src/ext/beautify.js'));
|
||||
ace.config.setModuleLoader('ace/ext/code_lens', () => import('ace-code/src/ext/code_lens.js'));
|
||||
ace.config.setModuleLoader('ace/ext/command_bar', () => import('ace-code/src/ext/command_bar.js'));
|
||||
ace.config.setModuleLoader('ace/ext/elastic_tabstops_lite', () => import('ace-code/src/ext/elastic_tabstops_lite.js'));
|
||||
ace.config.setModuleLoader('ace/ext/emmet', () => import('ace-code/src/ext/emmet.js'));
|
||||
ace.config.setModuleLoader('ace/ext/error_marker', () => import('ace-code/src/ext/error_marker.js'));
|
||||
ace.config.setModuleLoader('ace/ext/hardwrap', () => import('ace-code/src/ext/hardwrap.js'));
|
||||
ace.config.setModuleLoader('ace/ext/inline_autocomplete', () => import('ace-code/src/ext/inline_autocomplete.js'));
|
||||
ace.config.setModuleLoader('ace/ext/keyboard_menu', () => import('ace-code/src/ext/keybinding_menu.js'));
|
||||
ace.config.setModuleLoader('ace/ext/language_tools', () => import('ace-code/src/ext/language_tools.js'));
|
||||
ace.config.setModuleLoader('ace/ext/linking', () => import('ace-code/src/ext/linking.js'));
|
||||
ace.config.setModuleLoader('ace/ext/modelist', () => import('ace-code/src/ext/modelist.js'));
|
||||
ace.config.setModuleLoader('ace/ext/options', () => import('ace-code/src/ext/options.js'));
|
||||
// ace.config.setModuleLoader('ace/ext/prompt', () => import('ace-code/src/ext/prompt.js'));
|
||||
ace.config.setModuleLoader('ace/ext/prompt', () => import('./prompt_patch'));
|
||||
ace.config.setModuleLoader('ace/ext/rtl', () => import('ace-code/src/ext/rtl.js'));
|
||||
ace.config.setModuleLoader('ace/ext/searchbox', () => import('ace-code/src/ext/searchbox.js'));
|
||||
// ace.config.setModuleLoader('ace/ext/settings_menu', () => import('ace-code/src/ext/settings_menu.js'));
|
||||
ace.config.setModuleLoader('ace/ext/simple_tokenizer', () => import('ace-code/src/ext/simple_tokenizer.js'));
|
||||
ace.config.setModuleLoader('ace/ext/spellcheck', () => import('ace-code/src/ext/spellcheck.js'));
|
||||
ace.config.setModuleLoader('ace/ext/split', () => import('ace-code/src/ext/split.js'));
|
||||
ace.config.setModuleLoader('ace/ext/static_highlight', () => import('ace-code/src/ext/static_highlight.js'));
|
||||
ace.config.setModuleLoader('ace/ext/statusbar', () => import('ace-code/src/ext/statusbar.js'));
|
||||
ace.config.setModuleLoader('ace/ext/textarea', () => import('ace-code/src/ext/textarea.js'));
|
||||
ace.config.setModuleLoader('ace/ext/themelist', () => import('ace-code/src/ext/themelist.js'));
|
||||
ace.config.setModuleLoader('ace/ext/whitespace', () => import('ace-code/src/ext/whitespace.js'));
|
||||
ace.config.setModuleLoader('ace/keyboard/emacs', () => import('ace-code/src/keyboard/emacs.js'));
|
||||
ace.config.setModuleLoader('ace/keyboard/sublime', () => import('ace-code/src/keyboard/sublime.js'));
|
||||
ace.config.setModuleLoader('ace/keyboard/vim', () => import('ace-code/src/keyboard/vim.js'));
|
||||
ace.config.setModuleLoader('ace/keyboard/vscode', () => import('ace-code/src/keyboard/vscode.js'));
|
||||
|
||||
ace.config.setModuleLoader('ace/range', () => import('ace-code/src/range'));
|
||||
|
||||
console.log("ace module loaders patched");
|
||||
|
||||
export { ace };
|
||||
26
www/src/js/editor/ace.ts
Normal file
26
www/src/js/editor/ace.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import ace from "ace-builds";
|
||||
import "ace-builds/esm-resolver";
|
||||
|
||||
import { AceLanguageClient } from "ace-linters/build/ace-language-client";
|
||||
|
||||
// to make sure language tools are loaded
|
||||
ace.config.loadModule("ace/ext/language_tools");
|
||||
|
||||
import { Mode as TextMode } from "ace-builds/src-noconflict/mode-text";
|
||||
|
||||
export async function setupLspWorker() {
|
||||
// Create a web worker
|
||||
let worker = new Worker(new URL("./lspWorker.ts", import.meta.url));
|
||||
|
||||
const loaded = (w: Worker) =>
|
||||
new Promise((r) => w.addEventListener("message", r, { once: true }));
|
||||
await Promise.all([loaded(worker)]);
|
||||
|
||||
// Register the editor with the language provider
|
||||
return worker;
|
||||
}
|
||||
|
||||
export import EditSession = ace.Ace.EditSession;
|
||||
import { Range } from "ace-builds";
|
||||
|
||||
export { ace, TextMode, Range, AceLanguageClient }
|
||||
@@ -1,31 +1,24 @@
|
||||
import ace from "ace-builds";
|
||||
import "ace-builds/esm-resolver";
|
||||
import {
|
||||
ace,
|
||||
EditSession,
|
||||
Range,
|
||||
AceLanguageClient,
|
||||
setupLspWorker,
|
||||
} from "./ace";
|
||||
|
||||
import { AceLanguageClient } from "ace-linters/build/ace-language-client";
|
||||
import { LanguageProvider } from "ace-linters/types/language-provider";
|
||||
|
||||
import { IC10EditorUI } from "./ui";
|
||||
import { Range } from "ace-builds";
|
||||
|
||||
import { Session } from "../session";
|
||||
|
||||
// import { Mode as TextMode } from 'ace-code/src/mode/text';
|
||||
// to make sure language tools are loaded
|
||||
ace.config.loadModule("ace/ext/language_tools");
|
||||
|
||||
import { Mode as TextMode } from "ace-builds/src-noconflict/mode-text";
|
||||
|
||||
async function setupLspWorker() {
|
||||
// Create a web worker
|
||||
let worker = new Worker(new URL("./lspWorker.ts", import.meta.url));
|
||||
|
||||
const loaded = (w: Worker) =>
|
||||
new Promise((r) => w.addEventListener("message", r, { once: true }));
|
||||
await Promise.all([loaded(worker)]);
|
||||
|
||||
// Register the editor with the language provider
|
||||
return worker;
|
||||
}
|
||||
import "@shoelace-style/shoelace/dist/components/dialog/dialog.js";
|
||||
import "@shoelace-style/shoelace/dist/components/button-group/button-group.js";
|
||||
import "@shoelace-style/shoelace/dist/components/button/button.js";
|
||||
import "@shoelace-style/shoelace/dist/components/input/input.js";
|
||||
import "@shoelace-style/shoelace/dist/components/radio-button/radio-button.js";
|
||||
import "@shoelace-style/shoelace/dist/components/radio-group/radio-group.js";
|
||||
import '@shoelace-style/shoelace/dist/components/switch/switch.js';
|
||||
import SlDialog from "@shoelace-style/shoelace/dist/components/dialog/dialog.js";
|
||||
import SlRadioGroup from "@shoelace-style/shoelace/dist/components/radio-group/radio-group.js";
|
||||
import SlInput from "@shoelace-style/shoelace/dist/components/input/input.js";
|
||||
import SlSwitch from "@shoelace-style/shoelace/dist/components/switch/switch.js";
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
@@ -34,8 +27,9 @@ declare global {
|
||||
}
|
||||
|
||||
import { BaseElement, defaultCss } from "../components";
|
||||
import { html, css, HTMLTemplateResult } from "lit";
|
||||
import { html } from "lit";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
import { editorStyles } from "./styles";
|
||||
|
||||
@customElement("ace-ic10")
|
||||
export class IC10Editor extends BaseElement {
|
||||
@@ -46,7 +40,7 @@ export class IC10Editor extends BaseElement {
|
||||
fontSize: number;
|
||||
relativeLineNumbers: boolean;
|
||||
};
|
||||
sessions: Map<number, ace.Ace.EditSession>;
|
||||
sessions: Map<number, EditSession>;
|
||||
|
||||
@property({ type: Number })
|
||||
accessor active_session: number = 0;
|
||||
@@ -55,258 +49,7 @@ export class IC10Editor extends BaseElement {
|
||||
languageProvider?: LanguageProvider;
|
||||
// ui: IC10EditorUI;
|
||||
|
||||
static styles = [
|
||||
...defaultCss,
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
#editor {
|
||||
// border: 1px solid;
|
||||
// border-radius: 4px;
|
||||
@apply --ace-widget-editor;
|
||||
}
|
||||
#editorStatusbar {
|
||||
z-index: 9 !important;
|
||||
position: absolute !important;
|
||||
right: 4px;
|
||||
bottom: 4px;
|
||||
}
|
||||
.ace_status-indicator {
|
||||
background-color: #777;
|
||||
color: white;
|
||||
text-align: center;
|
||||
border: none;
|
||||
border-radius: 7px;
|
||||
padding-right: 3px;
|
||||
padding-left: 3px;
|
||||
padding-bottom: 1px;
|
||||
font-size: small;
|
||||
opacity: 0.9;
|
||||
}
|
||||
.hide_statusbar {
|
||||
display: none;
|
||||
}
|
||||
.ace_marker-layer .green {
|
||||
// background-color: ;
|
||||
// color: ;
|
||||
position: absolute;
|
||||
}
|
||||
.ace_marker-layer .darkGrey {
|
||||
// background-color: ;
|
||||
// color: ;
|
||||
position: absolute;
|
||||
}
|
||||
.ace_marker-layer .red {
|
||||
// background-color: ;
|
||||
// color: ;
|
||||
position: absolute;
|
||||
}
|
||||
.ace_marker-layer .blue {
|
||||
// background-color: ;
|
||||
// color: ;
|
||||
position: absolute;
|
||||
}
|
||||
.ace_marker-layer .orange {
|
||||
background-color: #ff9900;
|
||||
color: #555;
|
||||
position: absolute;
|
||||
}
|
||||
.ace_placeholder {
|
||||
color: #808080 !important;
|
||||
// font-family: "" !important;
|
||||
transform: scale(1) !important;
|
||||
opacity: 1 !important;
|
||||
font-style: italic !important;
|
||||
}
|
||||
/* ------------------------------------------------------------------------------------------
|
||||
* Editor Search Form
|
||||
* --------------------------------------------------------------------------------------- */
|
||||
.ace_search {
|
||||
background-color: #2b3035;
|
||||
color: #dee2e6;
|
||||
border: 1px solid #495057;
|
||||
border-top: 0 none;
|
||||
overflow: hidden;
|
||||
margin: 0;
|
||||
padding: 4px 6px 0 4px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
z-index: 99;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.ace_search.left {
|
||||
border-left: 0 none;
|
||||
border-radius: 0px 0px 5px 0px;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.ace_search.right {
|
||||
border-radius: 0px 0px 0px 5px;
|
||||
border-right: 0 none;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.ace_search_form,
|
||||
.ace_replace_form {
|
||||
margin: 0 20px 4px 0;
|
||||
overflow: hidden;
|
||||
line-height: 1.9;
|
||||
}
|
||||
|
||||
.ace_replace_form {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.ace_search_form.ace_nomatch {
|
||||
outline: 1px solid red;
|
||||
}
|
||||
|
||||
.ace_search_field {
|
||||
border-radius: 3px 0 0 3px;
|
||||
background-color: #343a40;
|
||||
color: #dee2e6;
|
||||
border: 1px solid #41464b;
|
||||
border-right: 0 none;
|
||||
outline: 0;
|
||||
padding: 0;
|
||||
font-size: inherit;
|
||||
margin: 0;
|
||||
line-height: inherit;
|
||||
padding: 0 6px;
|
||||
min-width: 17em;
|
||||
vertical-align: top;
|
||||
min-height: 1.8em;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
.ace_searchbtn {
|
||||
border: 1px solid #6c757d;
|
||||
line-height: inherit;
|
||||
display: inline-block;
|
||||
padding: 0 6px;
|
||||
background: #343a40;
|
||||
border-right: 0 none;
|
||||
border-left: 1px solid #6c757d;
|
||||
cursor: pointer;
|
||||
margin: 0;
|
||||
position: relative;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.ace_searchbtn:last-child {
|
||||
border-radius: 0 3px 3px 0;
|
||||
border-right: 1px solid #6c757d;
|
||||
}
|
||||
|
||||
.ace_searchbtn:disabled {
|
||||
background: none;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.ace_searchbtn:hover {
|
||||
background-color: #161719;
|
||||
}
|
||||
|
||||
.ace_searchbtn.prev,
|
||||
.ace_searchbtn.next {
|
||||
padding: 0px 0.7em;
|
||||
}
|
||||
|
||||
.ace_searchbtn.prev:after,
|
||||
.ace_searchbtn.next:after {
|
||||
content: "";
|
||||
border: solid 2px #6c757d;
|
||||
width: 0.5em;
|
||||
height: 0.5em;
|
||||
border-width: 2px 0 0 2px;
|
||||
display: inline-block;
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
|
||||
.ace_searchbtn.next:after {
|
||||
border-width: 0 2px 2px 0;
|
||||
}
|
||||
|
||||
.ace_searchbtn_close {
|
||||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAcCAYAAABRVo5BAAAAZ0lEQVR42u2SUQrAMAhDvazn8OjZBilCkYVVxiis8H4CT0VrAJb4WHT3C5xU2a2IQZXJjiQIRMdkEoJ5Q2yMqpfDIo+XY4k6h+YXOyKqTIj5REaxloNAd0xiKmAtsTHqW8sR2W5f7gCu5nWFUpVjZwAAAABJRU5ErkJggg==)
|
||||
no-repeat 50% 0;
|
||||
border-radius: 50%;
|
||||
border: 0 none;
|
||||
color: #343a40;
|
||||
cursor: pointer;
|
||||
font: 16px/16px Arial;
|
||||
padding: 0;
|
||||
height: 14px;
|
||||
width: 14px;
|
||||
top: 9px;
|
||||
right: 7px;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.ace_searchbtn_close:hover {
|
||||
background-color: #656565;
|
||||
background-position: 50% 100%;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.ace_button {
|
||||
background-color: #343a40;
|
||||
margin-left: 2px;
|
||||
cursor: pointer;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-o-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
overflow: hidden;
|
||||
opacity: 0.7;
|
||||
border: 1px solid #6c757d;
|
||||
padding: 1px;
|
||||
box-sizing: border-box !important;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.ace_button:hover {
|
||||
background-color: #161719;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.ace_button:active {
|
||||
background-color: #6c757d;
|
||||
}
|
||||
|
||||
.ace_button.checked {
|
||||
background-color: #6c757d;
|
||||
border-color: #6c757d;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.ace_search_options {
|
||||
margin-bottom: 3px;
|
||||
text-align: right;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-o-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.ace_search_counter {
|
||||
float: left;
|
||||
font-family: arial;
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* End Ace Search
|
||||
* --------------- */
|
||||
`,
|
||||
];
|
||||
static styles = [...defaultCss, editorStyles];
|
||||
|
||||
initialInit: boolean;
|
||||
editorDiv: HTMLElement;
|
||||
@@ -319,7 +62,14 @@ export class IC10Editor extends BaseElement {
|
||||
private _statusbarIndex: number;
|
||||
private _statusbar: any;
|
||||
vScrollbarObserver: IntersectionObserver;
|
||||
hScrollbarObserver: any;
|
||||
hScrollbarObserver: IntersectionObserver;
|
||||
stylesObserver: MutationObserver;
|
||||
stylesAdded: string[];
|
||||
tooltipObserver: MutationObserver;
|
||||
|
||||
get settingDialog() {
|
||||
return this.shadowRoot?.querySelector('sl-dialog') as SlDialog
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
@@ -339,11 +89,10 @@ export class IC10Editor extends BaseElement {
|
||||
this.active_line_markers = new Map();
|
||||
|
||||
// this.ui = new IC10EditorUI(this);
|
||||
|
||||
}
|
||||
|
||||
protected render() {
|
||||
return html`
|
||||
const result = html`
|
||||
<div
|
||||
id="editorContainer"
|
||||
style="height: 100%; width: 100%; position: relative;"
|
||||
@@ -354,7 +103,31 @@ export class IC10Editor extends BaseElement {
|
||||
></div>
|
||||
<div id="editorStatusbar"></div>
|
||||
</div>
|
||||
<sl-dialog label="Editor Settings" class="dialog-focus">
|
||||
<sl-radio-group id="editorKeyboardRadio" label="Editor Keyboard Bindings" value=${this.settings.keyboard}>
|
||||
<sl-radio-button value="ace">Ace</sl-radio-button>
|
||||
<sl-radio-button value="vim">Vim</sl-radio-button>
|
||||
<sl-radio-button value="emacs">Emacs</sl-radio-button>
|
||||
<sl-radio-button value="sublime">Sublime</sl-radio-button>
|
||||
<sl-radio-button value="vscode">VS Code</sl-radio-button>
|
||||
</sl-radio-group>
|
||||
<sl-radio-group id="editorCursorRadio" label="Editor Cursor Style" value=${this.settings.cursor}>
|
||||
<sl-radio-button value="ace">Ace</sl-radio-button>
|
||||
<sl-radio-button value="slim">Slim</sl-radio-button>
|
||||
<sl-radio-button value="smooth">Smooth</sl-radio-button>
|
||||
<sl-radio-button value="smooth slim">Smooth And Slim</sl-radio-button>
|
||||
<sl-radio-button value="wide">Wide</sl-radio-button>
|
||||
</sl-radio-group>
|
||||
<sl-input id="editorFontSize" label="Font Size" type="number" value="${this.settings.fontSize}"></sl-input>
|
||||
<sl-switch id="editorRelativeLineNumbers" ?checked=${this.settings.relativeLineNumbers}>Relative Line Numbers</sl-switch>
|
||||
</sl-dialog>
|
||||
`;
|
||||
return result;
|
||||
}
|
||||
|
||||
connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
this.loadEditorSettings();
|
||||
}
|
||||
|
||||
async firstUpdated() {
|
||||
@@ -378,8 +151,12 @@ export class IC10Editor extends BaseElement {
|
||||
this.initialInit = true;
|
||||
|
||||
this.editorDiv = this.shadowRoot?.getElementById("editor") as HTMLElement;
|
||||
this.editorContainerDiv = this.shadowRoot?.getElementById("editorContainer") as HTMLElement;
|
||||
this.editorStatusbarDiv = this.shadowRoot?.getElementById("editorStatusbar") as HTMLElement;
|
||||
this.editorContainerDiv = this.shadowRoot?.getElementById(
|
||||
"editorContainer",
|
||||
) as HTMLElement;
|
||||
this.editorStatusbarDiv = this.shadowRoot?.getElementById(
|
||||
"editorStatusbar",
|
||||
) as HTMLElement;
|
||||
|
||||
this.editor = ace.edit(this.editorDiv, {
|
||||
mode: this.mode,
|
||||
@@ -397,6 +174,51 @@ export class IC10Editor extends BaseElement {
|
||||
this.statusBar = ace.require("ace/ext/statusbar").StatusBar;
|
||||
this.snippetManager = ace.require("ace/snippets").snippetManager;
|
||||
|
||||
this.stylesAdded = [];
|
||||
const stylesToMove: string[] = ["vimMode"];
|
||||
const stylesToCopy: string[] = ["autocompletion.css"];
|
||||
const that = this;
|
||||
|
||||
this.stylesObserver = new MutationObserver((_mutations, _observer) => {
|
||||
// ace adds <style></style> nodes, ours should be <link rel="stylesheet">
|
||||
for (const sheet of document.head.querySelectorAll("style")) {
|
||||
if (!that.stylesAdded.includes(sheet.id)) {
|
||||
if (stylesToMove.includes(sheet.id)) {
|
||||
that.shadowRoot?.appendChild(sheet);
|
||||
that.stylesAdded.push(sheet.id);
|
||||
} else if (stylesToCopy.includes(sheet.id)) {
|
||||
let new_sheet = sheet.cloneNode() as HTMLStyleElement;
|
||||
new_sheet.id = `${sheet.id}_clone`;
|
||||
that.shadowRoot?.appendChild(new_sheet);
|
||||
that.stylesAdded.push(sheet.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.stylesObserver.observe(document.head, {
|
||||
attributes: false,
|
||||
childList: true,
|
||||
subtree: true,
|
||||
characterData: false,
|
||||
});
|
||||
|
||||
// Fornow this seems uneeded, tooltips seem to work better on the lightdom
|
||||
// this.tooltipObserver = new MutationObserver((_mutations, _observer) => {
|
||||
// // we want the toltips on the shadow-dom not the light dom body
|
||||
// for (const node of document.body.querySelectorAll(
|
||||
// ".ace_tooltip, .ace_editor.ace_autocomplete",
|
||||
// )) {
|
||||
// that.shadowRoot?.appendChild(node);
|
||||
// }
|
||||
// });
|
||||
// this.tooltipObserver.observe(document.body, {
|
||||
// attributes: false,
|
||||
// childList: true,
|
||||
// subtree: true,
|
||||
// characterData: false,
|
||||
// });
|
||||
|
||||
this.sessions.set(this.active_session, this.editor.getSession());
|
||||
this.bindSession(
|
||||
this.active_session,
|
||||
@@ -407,8 +229,6 @@ export class IC10Editor extends BaseElement {
|
||||
const worker = await setupLspWorker();
|
||||
this.setupLsp(worker);
|
||||
|
||||
const that = this;
|
||||
|
||||
// when the CSS resize Property is added (to a container-div or ace-ic10 )
|
||||
// the correct sizing is maintained (after user resize)
|
||||
document.addEventListener("mouseup", function (e) {
|
||||
@@ -424,6 +244,11 @@ export class IC10Editor extends BaseElement {
|
||||
this.observer.observe(this.editorContainerDiv);
|
||||
|
||||
this.initializeEditor();
|
||||
}
|
||||
|
||||
initializeEditor() {
|
||||
let editor = this.editor;
|
||||
const that = this;
|
||||
|
||||
window.App!.session.onLoad(((e: CustomEvent) => {
|
||||
const session = e.detail;
|
||||
@@ -471,10 +296,6 @@ export class IC10Editor extends BaseElement {
|
||||
}
|
||||
}
|
||||
}) as EventListener);
|
||||
}
|
||||
|
||||
initializeEditor() {
|
||||
let editor = this.editor;
|
||||
|
||||
// change -> possibility to allow saving the value without having to wait for blur
|
||||
editor.on("change", () => this.editorChangeAction());
|
||||
@@ -492,7 +313,7 @@ export class IC10Editor extends BaseElement {
|
||||
{ root: null },
|
||||
);
|
||||
this.vScrollbarObserver.observe(
|
||||
this.shadowRoot?.querySelector(".ace_scrollbar-v") as Element,
|
||||
this.shadowRoot!.querySelector(".ace_scrollbar-v")!,
|
||||
);
|
||||
|
||||
this.hScrollbarObserver = new IntersectionObserver(
|
||||
@@ -500,8 +321,44 @@ export class IC10Editor extends BaseElement {
|
||||
{ root: null },
|
||||
);
|
||||
this.hScrollbarObserver.observe(
|
||||
this.shadowRoot?.querySelector(".ace_scrollbar-h"),
|
||||
this.shadowRoot!.querySelector(".ace_scrollbar-h")!,
|
||||
);
|
||||
|
||||
editor.commands.addCommands([{
|
||||
name: "showSettingsMenu",
|
||||
// description: "Show settings menu",
|
||||
bindKey: { win: "Ctrl-,", mac: "Command-,"},
|
||||
exec: (_editor: ace.Ace.Editor) => {
|
||||
that.settingDialog.show();
|
||||
},
|
||||
}]);
|
||||
|
||||
this.updateEditorSettings();
|
||||
const keyboardRadio = this.renderRoot.querySelector("#editorKeyboardRadio")! as SlRadioGroup;
|
||||
const cursorRadio = this.renderRoot.querySelector("#editorCursorRadio")! as SlRadioGroup;
|
||||
const fontSize = this.renderRoot.querySelector("#editorFontSize")! as SlInput;
|
||||
const relativeLineNumbers = this.renderRoot.querySelector("#editorRelativeLineNumbers")! as SlSwitch;
|
||||
|
||||
keyboardRadio.addEventListener("sl-change", _e => {
|
||||
that.settings.keyboard = keyboardRadio.value;
|
||||
that.updateEditorSettings();
|
||||
that.saveEditorSettings();
|
||||
});
|
||||
cursorRadio?.addEventListener("sl-change", _e => {
|
||||
that.settings.cursor = cursorRadio.value;
|
||||
that.updateEditorSettings();
|
||||
that.saveEditorSettings();
|
||||
});
|
||||
fontSize?.addEventListener("sl-change", _e => {
|
||||
that.settings.fontSize = parseInt(fontSize.value)
|
||||
that.updateEditorSettings();
|
||||
that.saveEditorSettings();
|
||||
});
|
||||
relativeLineNumbers?.addEventListener("sl-change", _e => {
|
||||
that.settings.relativeLineNumbers = relativeLineNumbers.checked;
|
||||
that.updateEditorSettings();
|
||||
that.saveEditorSettings();
|
||||
});
|
||||
}
|
||||
|
||||
resizeEditor() {
|
||||
@@ -624,7 +481,7 @@ export class IC10Editor extends BaseElement {
|
||||
this.editor?.setSession(session);
|
||||
const mode = ace.require(this.mode);
|
||||
const options = mode?.options ?? {};
|
||||
this.languageProvider?.setSessionOptions(session, options)
|
||||
this.languageProvider?.setSessionOptions(session, options);
|
||||
this.active_session = session_id;
|
||||
return true;
|
||||
}
|
||||
@@ -647,6 +504,17 @@ export class IC10Editor extends BaseElement {
|
||||
window.localStorage.setItem("editorSettings", toSave);
|
||||
}
|
||||
|
||||
updateEditorSettings() {
|
||||
if (this.settings.keyboard === 'ace') {
|
||||
this.editor.setOption('keyboardHandler', null);
|
||||
} else {
|
||||
this.editor.setOption('keyboardHandler', `ace/keyboard/${this.settings.keyboard}`);
|
||||
}
|
||||
this.editor.setOption('cursorStyle', this.settings.cursor as any);
|
||||
this.editor.setOption('fontSize', this.settings.fontSize);
|
||||
this.editor.setOption('relativeLineNumbers', this.settings.relativeLineNumbers);
|
||||
}
|
||||
|
||||
destroySession(session_id: number) {
|
||||
if (!this.sessions.hasOwnProperty(session_id)) {
|
||||
return false;
|
||||
@@ -663,7 +531,7 @@ export class IC10Editor extends BaseElement {
|
||||
return true;
|
||||
}
|
||||
|
||||
bindSession(session_id: number, session?: ace.Ace.EditSession) {
|
||||
bindSession(session_id: number, session?: EditSession) {
|
||||
if (session) {
|
||||
session.on("change", () => {
|
||||
var val = session.getValue();
|
||||
|
||||
345
www/src/js/editor/styles.ts
Normal file
345
www/src/js/editor/styles.ts
Normal file
@@ -0,0 +1,345 @@
|
||||
import { css } from "lit";
|
||||
export const editorStyles = css`
|
||||
:host {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
#editor {
|
||||
// border: 1px solid;
|
||||
// border-radius: 4px;
|
||||
@apply --ace-widget-editor;
|
||||
}
|
||||
#editorStatusbar {
|
||||
z-index: 9 !important;
|
||||
position: absolute !important;
|
||||
right: 4px;
|
||||
bottom: 4px;
|
||||
}
|
||||
.ace_status-indicator {
|
||||
background-color: #777;
|
||||
color: white;
|
||||
text-align: center;
|
||||
border: none;
|
||||
border-radius: 7px;
|
||||
padding-right: 3px;
|
||||
padding-left: 3px;
|
||||
padding-bottom: 1px;
|
||||
font-size: small;
|
||||
opacity: 0.9;
|
||||
}
|
||||
.ace_marker-layer .green {
|
||||
// background-color: ;
|
||||
// color: ;
|
||||
position: absolute;
|
||||
}
|
||||
.ace_marker-layer .darkGrey {
|
||||
// background-color: ;
|
||||
// color: ;
|
||||
position: absolute;
|
||||
}
|
||||
.ace_marker-layer .red {
|
||||
// background-color: ;
|
||||
// color: ;
|
||||
position: absolute;
|
||||
}
|
||||
.ace_marker-layer .blue {
|
||||
// background-color: ;
|
||||
// color: ;
|
||||
position: absolute;
|
||||
}
|
||||
.ace_marker-layer .orange {
|
||||
background-color: #ff9900;
|
||||
color: #555;
|
||||
position: absolute;
|
||||
}
|
||||
.ace_placeholder {
|
||||
color: #808080 !important;
|
||||
// font-family: "" !important;
|
||||
transform: scale(1) !important;
|
||||
opacity: 1 !important;
|
||||
font-style: italic !important;
|
||||
}
|
||||
/* ------------------------------------------------------------------------------------------
|
||||
* Editor Search Form
|
||||
* --------------------------------------------------------------------------------------- */
|
||||
.ace_search {
|
||||
background-color: #2b3035;
|
||||
color: #dee2e6;
|
||||
border: 1px solid #495057;
|
||||
border-top: 0 none;
|
||||
overflow: hidden;
|
||||
margin: 0;
|
||||
padding: 4px 6px 0 4px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
z-index: 99;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.ace_search.left {
|
||||
border-left: 0 none;
|
||||
border-radius: 0px 0px 5px 0px;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.ace_search.right {
|
||||
border-radius: 0px 0px 0px 5px;
|
||||
border-right: 0 none;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.ace_search_form,
|
||||
.ace_replace_form {
|
||||
margin: 0 20px 4px 0;
|
||||
overflow: hidden;
|
||||
line-height: 1.9;
|
||||
}
|
||||
|
||||
.ace_replace_form {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.ace_search_form.ace_nomatch {
|
||||
outline: 1px solid red;
|
||||
}
|
||||
|
||||
.ace_search_field {
|
||||
border-radius: 3px 0 0 3px;
|
||||
background-color: #343a40;
|
||||
color: #dee2e6;
|
||||
border: 1px solid #41464b;
|
||||
border-right: 0 none;
|
||||
outline: 0;
|
||||
padding: 0;
|
||||
font-size: inherit;
|
||||
margin: 0;
|
||||
line-height: inherit;
|
||||
padding: 0 6px;
|
||||
min-width: 17em;
|
||||
vertical-align: top;
|
||||
min-height: 1.8em;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
.ace_searchbtn {
|
||||
border: 1px solid #6c757d;
|
||||
line-height: inherit;
|
||||
display: inline-block;
|
||||
padding: 0 6px;
|
||||
background: #343a40;
|
||||
border-right: 0 none;
|
||||
border-left: 1px solid #6c757d;
|
||||
cursor: pointer;
|
||||
margin: 0;
|
||||
position: relative;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.ace_searchbtn:last-child {
|
||||
border-radius: 0 3px 3px 0;
|
||||
border-right: 1px solid #6c757d;
|
||||
}
|
||||
|
||||
.ace_searchbtn:disabled {
|
||||
background: none;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.ace_searchbtn:hover {
|
||||
background-color: #161719;
|
||||
}
|
||||
|
||||
.ace_searchbtn.prev,
|
||||
.ace_searchbtn.next {
|
||||
padding: 0px 0.7em;
|
||||
}
|
||||
|
||||
.ace_searchbtn.prev:after,
|
||||
.ace_searchbtn.next:after {
|
||||
content: "";
|
||||
border: solid 2px #6c757d;
|
||||
width: 0.5em;
|
||||
height: 0.5em;
|
||||
border-width: 2px 0 0 2px;
|
||||
display: inline-block;
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
|
||||
.ace_searchbtn.next:after {
|
||||
border-width: 0 2px 2px 0;
|
||||
}
|
||||
|
||||
.ace_searchbtn_close {
|
||||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAcCAYAAABRVo5BAAAAZ0lEQVR42u2SUQrAMAhDvazn8OjZBilCkYVVxiis8H4CT0VrAJb4WHT3C5xU2a2IQZXJjiQIRMdkEoJ5Q2yMqpfDIo+XY4k6h+YXOyKqTIj5REaxloNAd0xiKmAtsTHqW8sR2W5f7gCu5nWFUpVjZwAAAABJRU5ErkJggg==)
|
||||
no-repeat 50% 0;
|
||||
border-radius: 50%;
|
||||
border: 0 none;
|
||||
color: #343a40;
|
||||
cursor: pointer;
|
||||
font: 16px/16px Arial;
|
||||
padding: 0;
|
||||
height: 14px;
|
||||
width: 14px;
|
||||
top: 9px;
|
||||
right: 7px;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.ace_searchbtn_close:hover {
|
||||
background-color: #656565;
|
||||
background-position: 50% 100%;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.ace_button {
|
||||
background-color: #343a40;
|
||||
margin-left: 2px;
|
||||
cursor: pointer;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-o-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
overflow: hidden;
|
||||
opacity: 0.7;
|
||||
border: 1px solid #6c757d;
|
||||
padding: 1px;
|
||||
box-sizing: border-box !important;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.ace_button:hover {
|
||||
background-color: #161719;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.ace_button:active {
|
||||
background-color: #6c757d;
|
||||
}
|
||||
|
||||
.ace_button.checked {
|
||||
background-color: #6c757d;
|
||||
border-color: #6c757d;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.ace_search_options {
|
||||
margin-bottom: 3px;
|
||||
text-align: right;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-o-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.ace_search_counter {
|
||||
float: left;
|
||||
font-family: arial;
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* Ace Tooltips
|
||||
* --------------- */
|
||||
code {
|
||||
// color: #e685b5
|
||||
color: #c678dd;
|
||||
}
|
||||
|
||||
.ace_tooltip code {
|
||||
font-style: italic;
|
||||
font-size: 12px;
|
||||
}
|
||||
.ace_tooltip {
|
||||
background: #282c34;
|
||||
color: #c1c1c1;
|
||||
border: 1px #484747 solid;
|
||||
box-shadow: 2px 3px 5px rgba(0, 0, 0, 0.51);
|
||||
}
|
||||
|
||||
.ace_tooltip.ace_dark {
|
||||
background: #282c34;
|
||||
color: #c1c1c1;
|
||||
border: 1px #484747 solid;
|
||||
box-shadow: 2px 3px 5px rgba(0, 0, 0, 0.51);
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* Ace tooltip
|
||||
* --------------- */
|
||||
|
||||
.ace_dark.ace_editor.ace_autocomplete .ace_completion-highlight {
|
||||
color: #c678dd;
|
||||
}
|
||||
|
||||
.ace_dark.ace_editor.ace_autocomplete .ace_marker-layer .ace_active-line {
|
||||
background-color: rgba(76, 87, 103, 0.19);
|
||||
}
|
||||
|
||||
.ace_dark.ace_editor.ace_autocomplete .ace_line-hover {
|
||||
border: 1px solid rgba(8, 121, 144, 0.5);
|
||||
background: rgba(76, 87, 103, 0.19);
|
||||
}
|
||||
|
||||
.ace_dark.ace_editor.ace_autocomplete {
|
||||
border: 1px #484747 solid;
|
||||
box-shadow: 2px 3px 5px rgba(0, 0, 0, 0.51);
|
||||
line-height: 1.4;
|
||||
background: #282c34;
|
||||
color: #c1c1c1;
|
||||
}
|
||||
|
||||
.ace_editor.ace_autocomplete {
|
||||
width: 300px;
|
||||
z-index: 200000;
|
||||
border: 1px #484747 solid;
|
||||
position: fixed;
|
||||
box-shadow: 2px 3px 5px rgba(0, 0, 0, 0.51);
|
||||
line-height: 1.4;
|
||||
background: #282c34;
|
||||
color: #c1c1c1;
|
||||
}
|
||||
|
||||
.ace_editor.ace_autocomplete .ace_completion-highlight {
|
||||
color: #c678dd;
|
||||
}
|
||||
|
||||
.ace_editor.ace_autocomplete .ace_marker-layer .ace_active-line {
|
||||
background-color: rgba(76, 87, 103, 0.19);
|
||||
}
|
||||
|
||||
.ace_editor.ace_autocomplete .ace_line-hover {
|
||||
border: 1px solid rgba(8, 121, 144, 0.5);
|
||||
background: rgba(76, 87, 103, 0.19);
|
||||
}
|
||||
|
||||
/* ----------------------
|
||||
* Editor Setting dialog
|
||||
* ---------------------- */
|
||||
.label-on-left {
|
||||
--label-width: 3.75rem;
|
||||
--gap-width: 1rem;
|
||||
}
|
||||
|
||||
.label-on-left + .label-on-left {
|
||||
margin-top: var(--sl-spacing-medium);
|
||||
}
|
||||
|
||||
.label-on-left::part(form-control) {
|
||||
display: grid;
|
||||
grid: auto / var(--label-width) 1fr;
|
||||
gap: var(--sl-spacing-3x-small) var(--gap-width);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.label-on-left::part(form-control-label) {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.label-on-left::part(form-control-help-text) {
|
||||
grid-column-start: 2;
|
||||
}
|
||||
`;
|
||||
@@ -1,109 +0,0 @@
|
||||
import { IC10Editor } from ".";
|
||||
import * as ace from "ace-builds";
|
||||
import { Offcanvas } from 'bootstrap';
|
||||
|
||||
class IC10EditorUI {
|
||||
ic10editor: IC10Editor;
|
||||
|
||||
constructor(ic10editor: IC10Editor) {
|
||||
|
||||
const that = this;
|
||||
|
||||
that.ic10editor = ic10editor;
|
||||
|
||||
// that.ic10editor.editor.commands.addCommand({
|
||||
// name: "showSettingsMenu",
|
||||
// description: "Show settings menu",
|
||||
// bindKey: { win: "Ctrl-,", mac: "Command-," },
|
||||
// exec: (_editor: ace.Ace.Editor) => {
|
||||
// const offCanvas = new Offcanvas(document.getElementById("editorSettings"));
|
||||
// offCanvas.toggle();
|
||||
// }
|
||||
// } as any);
|
||||
|
||||
ace.config.loadModule("ace/ext/keyboard_menu", function (module) {
|
||||
console.log("keybinding_menu loaded");
|
||||
module.init(that.ic10editor.editor);
|
||||
});
|
||||
|
||||
that.ic10editor.loadEditorSettings();
|
||||
that.displayEditorSettings();
|
||||
that.updateEditorSettings();
|
||||
that.reCalcEditorSize();
|
||||
window.addEventListener('resize', (e) => { that.reCalcEditorSize(); });
|
||||
|
||||
document.getElementsByName("editorKeybindRadio").forEach((el) => {
|
||||
el.addEventListener('change', (e) => {
|
||||
that.ic10editor.settings.keyboard = (e.target as any).value;
|
||||
that.ic10editor.saveEditorSettings();
|
||||
that.updateEditorSettings();
|
||||
});
|
||||
});
|
||||
|
||||
document.getElementsByName("editorCursorRadio").forEach((el) => {
|
||||
el.addEventListener('change', (e) => {
|
||||
that.ic10editor.settings.cursor = (e.target as any).value;
|
||||
that.ic10editor.saveEditorSettings();
|
||||
that.updateEditorSettings();
|
||||
});
|
||||
});
|
||||
document.getElementById("editorSettingsFontSize").addEventListener('change', (e) => {
|
||||
window.App.editorSettings.fontSize = parseInt((e.target as any).value);
|
||||
that.ic10editor.saveEditorSettings();
|
||||
that.updateEditorSettings();
|
||||
});
|
||||
document.getElementById("editorSettingsRelativeLineNumbers").addEventListener('change', (e) => {
|
||||
window.App.editorSettings.relativeLineNumbers = (e.target as any).checked;
|
||||
that.ic10editor.saveEditorSettings();
|
||||
that.updateEditorSettings();
|
||||
});
|
||||
|
||||
console.log(that.ic10editor.editor.getOption('keyboardHandler'));
|
||||
|
||||
that.ic10editor.editor.setTheme("ace/theme/one_dark");
|
||||
|
||||
that.ic10editor.editor.setAutoScrollEditorIntoView(true);
|
||||
|
||||
}
|
||||
|
||||
updateEditorSettings() {
|
||||
const settings = this.ic10editor.settings;
|
||||
const editor = this.ic10editor.editor;
|
||||
if (settings.keyboard === 'ace') {
|
||||
editor.setOption('keyboardHandler', null);
|
||||
} else {
|
||||
editor.setOption('keyboardHandler', `ace/keyboard/${settings.keyboard}`);
|
||||
}
|
||||
editor.setOption('cursorStyle', settings.cursor as any);
|
||||
editor.setOption('fontSize', settings.fontSize);
|
||||
editor.setOption('relativeLineNumbers', settings.relativeLineNumbers);
|
||||
}
|
||||
|
||||
displayEditorSettings() {
|
||||
const settings = this.ic10editor.settings;
|
||||
document.getElementsByName("editorKeybindRadio").forEach((el: any) => {
|
||||
el.checked = el.value === settings.keyboard;
|
||||
});
|
||||
document.getElementsByName("editorCursorRadio").forEach((el: any) => {
|
||||
el.checked = el.value === settings.cursor;
|
||||
});
|
||||
(document.getElementById("editorSettingsFontSize") as any).value = settings.fontSize;
|
||||
(document.getElementById("editorSettingsRelativeLineNumbers") as any).checked = settings.relativeLineNumbers;
|
||||
}
|
||||
|
||||
reCalcEditorSize() {
|
||||
const editor = this.ic10editor.editor;
|
||||
const navBar = document.getElementById("navBar");
|
||||
const statusBarContainer = document.getElementById("statusBarContainer");
|
||||
|
||||
const correction = navBar.offsetHeight + statusBarContainer.offsetHeight;
|
||||
const editorContainer = document.getElementById("editor");
|
||||
editorContainer.style.height = `calc( 100vh - ${correction}px - 0.5rem)`;
|
||||
editor.resize(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
export { IC10EditorUI };
|
||||
@@ -1,9 +1,11 @@
|
||||
import { Ace } from "ace-builds";
|
||||
|
||||
|
||||
function docReady(fn: ()=> void) {
|
||||
function docReady(fn: () => void) {
|
||||
// see if DOM is already available
|
||||
if (document.readyState === "complete" || document.readyState === "interactive") {
|
||||
if (
|
||||
document.readyState === "complete" ||
|
||||
document.readyState === "interactive"
|
||||
) {
|
||||
setTimeout(fn, 1);
|
||||
} else {
|
||||
document.addEventListener("DOMContentLoaded", fn);
|
||||
@@ -11,7 +13,12 @@ function docReady(fn: ()=> void) {
|
||||
}
|
||||
|
||||
// probably not needed, fetch() exists now
|
||||
function makeRequest(opts: { method: string, url: string, headers: { [key: string]: string }, params: any }) {
|
||||
function makeRequest(opts: {
|
||||
method: string;
|
||||
url: string;
|
||||
headers: { [key: string]: string };
|
||||
params: any;
|
||||
}) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open(opts.method, opts.url);
|
||||
@@ -21,14 +28,14 @@ function makeRequest(opts: { method: string, url: string, headers: { [key: strin
|
||||
} else {
|
||||
reject({
|
||||
status: xhr.status,
|
||||
statusText: xhr.statusText
|
||||
statusText: xhr.statusText,
|
||||
});
|
||||
}
|
||||
};
|
||||
xhr.onerror = function () {
|
||||
reject({
|
||||
status: xhr.status,
|
||||
statusText: xhr.statusText
|
||||
statusText: xhr.statusText,
|
||||
});
|
||||
};
|
||||
if (opts.headers) {
|
||||
@@ -37,10 +44,14 @@ function makeRequest(opts: { method: string, url: string, headers: { [key: strin
|
||||
});
|
||||
}
|
||||
var params = opts.params;
|
||||
if (params && typeof params === 'object') {
|
||||
params = Object.keys(params).map(function (key) {
|
||||
return encodeURIComponent(key) + '=' + encodeURIComponent(params[key]);
|
||||
}).join('&');
|
||||
if (params && typeof params === "object") {
|
||||
params = Object.keys(params)
|
||||
.map(function (key) {
|
||||
return (
|
||||
encodeURIComponent(key) + "=" + encodeURIComponent(params[key])
|
||||
);
|
||||
})
|
||||
.join("&");
|
||||
}
|
||||
xhr.send(params);
|
||||
});
|
||||
@@ -49,24 +60,28 @@ function makeRequest(opts: { method: string, url: string, headers: { [key: strin
|
||||
async function saveFile(content: BlobPart) {
|
||||
const blob = new Blob([content], { type: "text/plain" });
|
||||
if (typeof window.showSaveFilePicker !== "undefined") {
|
||||
console.log("Saving via FileSystem API")
|
||||
const saveHandle = await window.showSaveFilePicker({
|
||||
types: [
|
||||
{
|
||||
// suggestedName: "code.ic10",
|
||||
description: 'Text Files',
|
||||
accept: {
|
||||
'text/plain': ['.txt', '.ic10'],
|
||||
console.log("Saving via FileSystem API");
|
||||
try {
|
||||
const saveHandle = await window.showSaveFilePicker({
|
||||
types: [
|
||||
{
|
||||
// suggestedName: "code.ic10",
|
||||
description: "Text Files",
|
||||
accept: {
|
||||
"text/plain": [".txt", ".ic10"],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
const ws = await saveHandle.createWritable();
|
||||
await ws.write(blob);
|
||||
await ws.close();
|
||||
],
|
||||
});
|
||||
const ws = await saveHandle.createWritable();
|
||||
await ws.write(blob);
|
||||
await ws.close();
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
} else {
|
||||
console.log("saving file via hidden link event");
|
||||
var a = document.createElement('a');
|
||||
var a = document.createElement("a");
|
||||
a.download = "code.ic10";
|
||||
a.href = window.URL.createObjectURL(blob);
|
||||
a.click();
|
||||
@@ -76,23 +91,27 @@ async function saveFile(content: BlobPart) {
|
||||
async function openFile(editor: Ace.Editor) {
|
||||
if (typeof window.showOpenFilePicker !== "undefined") {
|
||||
console.log("opening file via FileSystem Api");
|
||||
const [fileHandle] = await window.showOpenFilePicker();
|
||||
const file = await fileHandle.getFile();
|
||||
const contents = await file.text();
|
||||
const session = editor.getSession();
|
||||
session.setValue(contents);
|
||||
try {
|
||||
const [fileHandle] = await window.showOpenFilePicker();
|
||||
const file = await fileHandle.getFile();
|
||||
const contents = await file.text();
|
||||
const session = editor.getSession();
|
||||
session.setValue(contents);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
} else {
|
||||
console.log("opening file via hidden input event");
|
||||
let input = document.createElement('input');
|
||||
input.type = 'file';
|
||||
let input = document.createElement("input");
|
||||
input.type = "file";
|
||||
input.accept = ".txt,.ic10,.mips,text/*";
|
||||
input.onchange = _ => {
|
||||
const files = Array.from(input.files);
|
||||
input.onchange = (_) => {
|
||||
const files = Array.from(input.files!);
|
||||
console.log(files);
|
||||
const file = files[0];
|
||||
var reader = new FileReader();
|
||||
reader.onload = (e) => {
|
||||
const contents = e.target.result as string;
|
||||
const contents = e.target!.result as string;
|
||||
const session = editor.getSession();
|
||||
// session.id = file.name;
|
||||
session.setValue(contents);
|
||||
@@ -102,4 +121,4 @@ async function openFile(editor: Ace.Editor) {
|
||||
input.click();
|
||||
}
|
||||
}
|
||||
export { docReady, makeRequest, saveFile, openFile }
|
||||
export { docReady, makeRequest, saveFile, openFile };
|
||||
|
||||
@@ -4,21 +4,6 @@ body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.ace_tooltip {
|
||||
background: #282c34;
|
||||
color: #c1c1c1;
|
||||
border: 1px #484747 solid;
|
||||
box-shadow: 2px 3px 5px rgba(0, 0, 0, 0.51);
|
||||
}
|
||||
|
||||
.ace_tooltip.ace_dark {
|
||||
background: #282c34;
|
||||
color: #c1c1c1;
|
||||
border: 1px #484747 solid;
|
||||
box-shadow: 2px 3px 5px rgba(0, 0, 0, 0.51);
|
||||
}
|
||||
|
||||
|
||||
#ace_settingsmenu,
|
||||
#kbshortcutmenu {
|
||||
background-color: rgb(33, 37, 41);
|
||||
@@ -37,12 +22,12 @@ body {
|
||||
|
||||
.ace_optionsMenuEntry:hover {
|
||||
background-color: #161719;
|
||||
transition: all 0.3s
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.ace_closeButton {
|
||||
background: rgba(245, 146, 146, 0.5);
|
||||
border: 1px solid #F48A8A;
|
||||
border: 1px solid #f48a8a;
|
||||
border-radius: 50%;
|
||||
padding: 7px;
|
||||
position: absolute;
|
||||
@@ -70,7 +55,7 @@ body {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.ace_optionsMenuEntry button[ace_selected_button=true] {
|
||||
.ace_optionsMenuEntry button[ace_selected_button="true"] {
|
||||
background: #e7e7e7;
|
||||
box-shadow: 1px 0px 2px 0px #adadad inset;
|
||||
border-color: #adadad;
|
||||
@@ -96,18 +81,7 @@ body {
|
||||
box-shadow: 0px 2px 3px 0px #555;
|
||||
}
|
||||
|
||||
|
||||
code {
|
||||
// color: #e685b5
|
||||
color: #c678dd;
|
||||
}
|
||||
|
||||
.ace_tooltip code {
|
||||
font-style: italic;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.navbar-default .navbar-nav>li>a {
|
||||
.navbar-default .navbar-nav > li > a {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
@@ -118,7 +92,7 @@ code {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.navbar-nav>li>a {
|
||||
.navbar-nav > li > a {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
line-height: 20px;
|
||||
@@ -131,7 +105,7 @@ code {
|
||||
// }
|
||||
// }
|
||||
|
||||
.nav>li>a {
|
||||
.nav > li > a {
|
||||
position: relative;
|
||||
display: block;
|
||||
padding: 10px 15px;
|
||||
@@ -141,7 +115,7 @@ code {
|
||||
|
||||
.navbar-nav .dropdown-menu {
|
||||
position: absolute;
|
||||
left: .5rem;
|
||||
left: 0.5rem;
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
@@ -149,21 +123,51 @@ code {
|
||||
}
|
||||
|
||||
.modal-body button {
|
||||
color: #fff
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* Ace Tooltips
|
||||
* --------------- */
|
||||
code {
|
||||
// color: #e685b5
|
||||
color: #c678dd;
|
||||
}
|
||||
|
||||
.ace_tooltip code {
|
||||
font-style: italic;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.ace_tooltip {
|
||||
background: #282c34;
|
||||
color: #c1c1c1;
|
||||
border: 1px #484747 solid;
|
||||
box-shadow: 2px 3px 5px rgba(0, 0, 0, 0.51);
|
||||
}
|
||||
|
||||
.ace_tooltip.ace_dark {
|
||||
background: #282c34;
|
||||
color: #c1c1c1;
|
||||
border: 1px #484747 solid;
|
||||
box-shadow: 2px 3px 5px rgba(0, 0, 0, 0.51);
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* Ace tooltip
|
||||
* --------------- */
|
||||
|
||||
.ace_dark.ace_editor.ace_autocomplete .ace_completion-highlight {
|
||||
color: #c678dd;
|
||||
}
|
||||
|
||||
.ace_dark.ace_editor.ace_autocomplete .ace_marker-layer .ace_active-line {
|
||||
background-color: rgba(76, 87, 103, .19);
|
||||
background-color: rgba(76, 87, 103, 0.19);
|
||||
}
|
||||
|
||||
.ace_dark.ace_editor.ace_autocomplete .ace_line-hover {
|
||||
border: 1px solid rgba(8, 121, 144, 0.5);
|
||||
background: rgba(76, 87, 103, .19);
|
||||
background: rgba(76, 87, 103, 0.19);
|
||||
}
|
||||
|
||||
.ace_dark.ace_editor.ace_autocomplete {
|
||||
@@ -190,12 +194,12 @@ code {
|
||||
}
|
||||
|
||||
.ace_editor.ace_autocomplete .ace_marker-layer .ace_active-line {
|
||||
background-color: rgba(76, 87, 103, .19);
|
||||
background-color: rgba(76, 87, 103, 0.19);
|
||||
}
|
||||
|
||||
.ace_editor.ace_autocomplete .ace_line-hover {
|
||||
border: 1px solid rgba(8, 121, 144, 0.5);
|
||||
background: rgba(76, 87, 103, .19);
|
||||
background: rgba(76, 87, 103, 0.19);
|
||||
}
|
||||
|
||||
.vm_ic_active_line {
|
||||
@@ -294,13 +298,12 @@ code {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.vm_stack_cel span.stack_pointer {
|
||||
.vm_stack_cel span.stack_pointer {
|
||||
background-color: var(--bs-success);
|
||||
}
|
||||
|
||||
.vm_device_summary button.btn {
|
||||
line-height: 0.75rem;
|
||||
|
||||
}
|
||||
|
||||
.vm_device_summary span.badge {
|
||||
|
||||
@@ -32,31 +32,31 @@ $accordion-button-padding-y: 0.5rem;
|
||||
// @import "bootstrap/scss/images";
|
||||
@import "bootstrap/scss/containers";
|
||||
@import "bootstrap/scss/grid";
|
||||
@import "bootstrap/scss/tables";
|
||||
@import "bootstrap/scss/forms";
|
||||
@import "bootstrap/scss/buttons";
|
||||
@import "bootstrap/scss/transitions";
|
||||
@import "bootstrap/scss/dropdown";
|
||||
@import "bootstrap/scss/button-group";
|
||||
@import "bootstrap/scss/nav";
|
||||
@import "bootstrap/scss/navbar"; // Requires nav
|
||||
@import "bootstrap/scss/card";
|
||||
// @import "bootstrap/scss/tables";
|
||||
// @import "bootstrap/scss/forms";
|
||||
// @import "bootstrap/scss/buttons";
|
||||
// @import "bootstrap/scss/transitions";
|
||||
// @import "bootstrap/scss/dropdown";
|
||||
// @import "bootstrap/scss/button-group";
|
||||
// @import "bootstrap/scss/nav";
|
||||
// @import "bootstrap/scss/navbar"; // Requires nav
|
||||
// @import "bootstrap/scss/card";
|
||||
// @import "bootstrap/scss/breadcrumb";
|
||||
@import "bootstrap/scss/accordion";
|
||||
// @import "bootstrap/scss/accordion";
|
||||
|
||||
// @import "bootstrap/scss/pagination";
|
||||
@import "bootstrap/scss/badge";
|
||||
@import "bootstrap/scss/alert";
|
||||
@import "bootstrap/scss/progress";
|
||||
@import "bootstrap/scss/list-group";
|
||||
@import "bootstrap/scss/close";
|
||||
@import "bootstrap/scss/toasts";
|
||||
@import "bootstrap/scss/modal"; // Requires transitions
|
||||
@import "bootstrap/scss/tooltip";
|
||||
@import "bootstrap/scss/popover";
|
||||
// @import "bootstrap/scss/badge";
|
||||
// @import "bootstrap/scss/alert";
|
||||
// @import "bootstrap/scss/progress";
|
||||
// @import "bootstrap/scss/list-group";
|
||||
// @import "bootstrap/scss/close";
|
||||
// @import "bootstrap/scss/toasts";
|
||||
// @import "bootstrap/scss/modal"; // Requires transitions
|
||||
// @import "bootstrap/scss/tooltip";
|
||||
// @import "bootstrap/scss/popover";
|
||||
// @import "bootstrap/scss/carousel";
|
||||
@import "bootstrap/scss/spinners";
|
||||
@import "bootstrap/scss/offcanvas"; // Requires transitions
|
||||
// @import "bootstrap/scss/spinners";
|
||||
// @import "bootstrap/scss/offcanvas"; // Requires transitions
|
||||
// @import "bootstrap/scss/placeholders";
|
||||
|
||||
// Helpers
|
||||
@@ -65,8 +65,8 @@ $accordion-button-padding-y: 0.5rem;
|
||||
// Utilities
|
||||
@import "bootstrap/scss/utilities/api";
|
||||
|
||||
@import "./dark.scss"
|
||||
|
||||
//
|
||||
// Custom styles
|
||||
//
|
||||
//
|
||||
@import "./dark.scss"
|
||||
|
||||
Reference in New Issue
Block a user