Skip to content
31 changes: 22 additions & 9 deletions css/ui.css
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ div.emuspacer {
border-color:#888;
}
canvas.pixelated {
cursor: crosshair;
image-rendering: optimizeSpeed; /* Older versions of FF */
image-rendering: -moz-crisp-edges; /* FF 6.0+ */
image-rendering: -webkit-optimize-contrast; /* Safari */
Expand All @@ -275,14 +276,23 @@ canvas.pixelated {
-ms-interpolation-mode: nearest-neighbor; /* IE */
}
.palbtn {
width:2em;
height:2em;
border-style:none;
}
.palbtn.selected {
border-width:2px;
border-color:white;
border-style:dotted;
width: 2em;
height: 2em;
border-style: none;
position: relative;
border: none;
}
.palbtn.selected::after {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
border: 2px dotted #888;
border-radius: inherit;
mix-blend-mode: difference;
pointer-events: none;
}
#javatari-screen canvas {
box-sizing: content-box;
Expand Down Expand Up @@ -513,7 +523,7 @@ div.asset_block.asset_highlight {
font-family: "Andale Mono", "Menlo", "Lucida Console", monospace;
font-weight: bold;
color: #c1c1b0;
background-color: #555;
background-color: #4a4a4a;
border-radius: 8px;
padding-left: 1em;
}
Expand All @@ -523,6 +533,7 @@ div.asset_block.asset_highlight {
cursor: pointer;
padding: 1px 4px;
border-radius: 4px;
background: rgba(153, 204, 153, 0.15);
}
.asset_linenos:hover {
text-decoration: underline;
Expand Down Expand Up @@ -572,6 +583,7 @@ div.asset_grid span {
.asset_cell {
padding: 0px;
border: 1px solid black;
cursor: crosshair;
}
.asset_cell:hover {
border: 1px solid white;
Expand All @@ -587,6 +599,7 @@ td.asset_editable {
div.asset_dual {
display: flex;
align-items: flex-start;
flex-wrap: wrap;
}
div.asset_dual table {
border-spacing: 10px;
Expand Down
55 changes: 28 additions & 27 deletions src/ide/pixeleditor.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@

import { hex, tobin, rgb2bgr, rle_unpack } from "../common/util";
import { ProjectWindows } from "./windows";
import { hex, rgb2bgr, rle_unpack, tobin } from "../common/util";
import { Toolbar } from "./toolbar";
import { ProjectWindows } from "./windows";
import Mousetrap = require('mousetrap');

export type UintArray = number[] | Uint8Array | Uint16Array | Uint32Array; //{[i:number]:number};

const MAX_SIZE_X = 800;
const MAX_SIZE_Y = 1000;
const MAX_SCALE = 16;

// TODO: separate view/controller
export interface EditorContext {
setCurrentEditor(div: JQuery, editing: JQuery, node: PixNode): void;
Expand Down Expand Up @@ -97,6 +101,8 @@ export function parseHexWords(s: string): number[] {
}

export function replaceHexWords(s: string, words: UintArray, bpw: number): string {
// convert 'hex ...' format to 0x prefixed values for regex matching
s = convertToHexStatements(s);
var result = "";
var m;
var li = 0;
Expand Down Expand Up @@ -490,43 +496,37 @@ export class FileDataNode extends CodeProjectDataNode {
}

export class TextDataNode extends CodeProjectDataNode {
text: string;
start: number;
end: number;
bpw: number;
rangeId: string;

private static nextRangeId = 0;

// TODO: what if file size/layout changes?
constructor(project: ProjectWindows, fileid: string, label: string, start: number, end: number, bpw?: number) {
super();
this.project = project;
this.fileid = fileid;
this.label = label;
this.start = start;
this.end = end;
this.bpw = bpw || 8;
this.rangeId = `asset_${TextDataNode.nextRangeId++}`;
this.project.setAssetRange(this.fileid, this.rangeId, start, end);
}

updateLeft() {
if (this.right.words.length != this.words.length)
throw Error("Cannot put " + this.right.words.length + " image bytes into array of " + this.words.length + " bytes");
this.words = this.right.words;
// TODO: reload editors?
var datastr = this.text.substring(this.start, this.end);
var datastr = this.project.getAssetText(this.fileid, this.rangeId);
datastr = replaceHexWords(datastr, this.words, this.bpw);
if (this.project) {
this.project.replaceTextRange(this.fileid, this.start, this.end, datastr);
}
this.text = this.text.substring(0, this.start) + datastr + this.text.substring(this.end);
this.end = this.start + datastr.length;
// CM6 state field automatically remaps all tracked ranges.
this.project.replaceAssetText(this.fileid, this.rangeId, datastr);
return true;
}

updateRight() {
if (this.project) {
this.text = this.project.project.getFile(this.fileid) as string;
}
var datastr = this.text.substring(this.start, this.end);
datastr = convertToHexStatements(datastr); // TODO?
var datastr = this.project.getAssetText(this.fileid, this.rangeId);
datastr = convertToHexStatements(datastr);
var words = parseHexWords(datastr);
this.words = words; //new Uint8Array(words); // TODO: 16/32?
this.words = words;
return true;
}
}
Expand Down Expand Up @@ -919,9 +919,13 @@ export class CharmapEditor extends PixNode {
chooser.width = this.fmt.w || 1;
chooser.height = this.fmt.h || 1;
chooser.recreate(agrid, (index, viewer) => {
var yscale = Math.ceil(256 / this.fmt.w); // TODO: variable scale?
var xscale = yscale * (this.fmt.aspect || 1.0);
var editview = this.createEditor(aeditor, viewer, xscale, yscale);
// TODO: variable scale?
const aspect = this.fmt.aspect || 1.0;
const yscale = Math.min(MAX_SCALE,
MAX_SIZE_X / this.fmt.w * aspect,
MAX_SIZE_Y / this.fmt.h);
const xscale = yscale * aspect;
this.createEditor(aeditor, viewer, xscale, yscale);
this.context.setCurrentEditor(aeditor, $(viewer.canvas), this);
this.rgbimgs[index] = viewer.rgbdata;
});
Expand Down Expand Up @@ -951,9 +955,6 @@ export class CharmapEditor extends PixNode {
im.updateImage();
var w = viewer.width * xscale;
var h = viewer.height * yscale;
while (w > 500 || h > 500) {
w /= 2; h /= 2;
}
im.canvas.style.width = w + 'px'; // TODO
im.canvas.style.height = h + 'px'; // TODO
im.makeEditable(this, aeditor, this.left.palette);
Expand Down
28 changes: 18 additions & 10 deletions src/ide/ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ async function getSkeletonFile(fileid: string): Promise<string> {
try {
return await $.get("presets/" + getBasePlatform(platform_id) + "/skeleton." + ext, 'text');
} catch (e) {
console.log(e+"");
console.log(e + "");
return null;
}
}
Expand Down Expand Up @@ -707,19 +707,27 @@ export function getCurrentEditorFilename(): string {

function _revertFile(e) {
var wnd = projectWindows.getActive();
if (wnd && wnd.setText) {
var fn = projectWindows.getActiveID();
$.get("presets/" + getBasePlatform(platform_id) + "/" + fn, (text) => {
var fn = projectWindows.getActiveID();
var isBinary = wnd && wnd.setData && !wnd.setText;
if (wnd && (wnd.setText || wnd.setData)) {
var url = "presets/" + getBasePlatform(platform_id) + "/" + fn;
getWithBinary(url, (data) => {
if (data == null) {
if (repo_id) alertError("Can only revert built-in examples. If you want to revert all files, You can pull from the repository.");
else alertError("Can only revert built-in examples.");
return;
}
bootbox.confirm("Reset '" + DOMPurify.sanitize(fn) + "' to default?", (ok) => {
if (ok) {
wnd.setText(text);
if (isBinary) {
wnd.setData(data as Uint8Array);
current_project.updateFile(fn, data as Uint8Array);
} else {
wnd.setText(data as string);
}
}
});
}, 'text')
.fail(() => {
if (repo_id) alertError("Can only revert built-in examples. If you want to revert all files, You can pull from the repository.");
else alertError("Can only revert built-in examples.");
});
}, isBinary ? 'arraybuffer' : 'text');
} else {
alertError("Cannot revert the active window. Please choose a text file.");
}
Expand Down
17 changes: 11 additions & 6 deletions src/ide/views/asseteditor.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@

import { newDiv, ProjectView } from "./baseviews";
import { platform_id, current_project, projectWindows } from "../ui";
import { hex, rgb2bgr, safeident } from "../../common/util";
import { FileData } from "../../common/workertypes";
import { hex, safeident, rgb2bgr } from "../../common/util";
import * as pixed from "../pixeleditor";
import { current_project, platform_id, projectWindows } from "../ui";
import { newDiv, ProjectView } from "./baseviews";
import Mousetrap = require('mousetrap');

function getLineNumber(data: string, offset: number): number {
Expand Down Expand Up @@ -351,6 +351,7 @@ export class AssetEditorView implements ProjectView, pixed.EditorContext {
.appendTo(this.ensureFileDiv(fileid));
var snip = $('<div class="asset_snip"/>').appendTo(block);
var linenos = $('<span class="asset_linenos"/>').appendTo(snip);
$('<span class="asset_lineno"/>').text('↗ ').appendTo(linenos);
$('<span class="asset_lineno"/>').text(frag.startline).appendTo(linenos);
linenos.append('-');
$('<span class="asset_lineno"/>').text(frag.endline).appendTo(linenos);
Expand Down Expand Up @@ -424,6 +425,8 @@ export class AssetEditorView implements ProjectView, pixed.EditorContext {
this.clearAssets();
current_project.iterateFiles((fileid, data) => {
try {
// Clear stale tracked ranges before re-scanning this file.
projectWindows.clearAssetRanges(fileid);
var nassets = this.refreshAssetsInFile(fileid, data);
} catch (e) {
console.log(e);
Expand Down Expand Up @@ -477,9 +480,11 @@ export class AssetEditorView implements ProjectView, pixed.EditorContext {
setVisible?(showing: boolean): void {
// TODO: make into toolbar?
if (showing) {
// limit undo/redo to since opening this editor
projectWindows.undofiles = [];
projectWindows.redofiles = [];
// ensure asset editor is safe to perform synchronous reads/writes
projectWindows.flushAllWindows();
// limit undo/redo to since opening this asset editor
projectWindows.undoStack = [];
projectWindows.redoStack = [];
if (Mousetrap.bind) {
Mousetrap.bind('mod+z', (e) => { projectWindows.undoStep(); return false; });
Mousetrap.bind('mod+shift+z', (e) => { projectWindows.redoStep(); return false; });
Expand Down
7 changes: 6 additions & 1 deletion src/ide/views/baseviews.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export interface ProjectView {
getPath?(): string;
getValue?(): string;
setText?(text: string): void;
setData?(data: any): void;
insertLinesBefore?(text: string): void;
getCursorPC?(): number;
getSourceFile?(): SourceFile;
Expand All @@ -20,7 +21,11 @@ export interface ProjectView {
recreateOnResize?: boolean;
undoStep?(): void;
redoStep?(): void;
replaceTextRange?(from: number, to: number, text: string): void;
flushChanges?(): void;
setAssetRange?(id: string, from: number, to: number): void;
getAssetText?(id: string): string | null;
replaceAssetText?(id: string, text: string): void;
clearAssetRanges?(): void;
};

// detect mobile (https://stackoverflow.com/questions/3514784/what-is-the-best-way-to-detect-a-mobile-device)
Expand Down
Loading
Loading