fixed profiler so updates after pause; nes presets; resize windows; dialog for gist share

This commit is contained in:
Steven Hugg 2019-03-03 14:37:22 -06:00
parent ab1500ccb6
commit 733846af16
10 changed files with 184 additions and 119 deletions

View File

@ -431,3 +431,20 @@ div.markdown th {
height:100%; height:100%;
overflow-y:auto; overflow-y:auto;
} }
div.profiler {
background-color: #333;
color: #ddd;
white-space: pre;
margin-top: 20px auto 0;
font-family: "Andale Mono", "Menlo", "Lucida Console", monospace;
font-size: 10pt;
}
span.profiler-lineno {
color: #fff;
}
span.profiler-local {
color: #999;
}
span.profiler-cident {
color: #99ffff;
}

View File

@ -82,8 +82,9 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
<li class="dropdown dropdown-submenu"> <li class="dropdown dropdown-submenu">
<a tabindex="-1" href="#">Share</a> <a tabindex="-1" href="#">Share</a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li><a class="dropdown-item" href="#" id="item_record_video">Record Video...</a></li> <li><a class="dropdown-item" href="#" id="item_share_github">Share File on Github...</a></li>
<li><a class="dropdown-item" href="#" id="item_share_file">Share Playable Link...</a></li> <li><a class="dropdown-item" href="#" id="item_share_file">Share Playable Link...</a></li>
<li><a class="dropdown-item" href="#" id="item_record_video">Record Video...</a></li>
<li><a class="dropdown-item" href="#" id="item_export_cassette">Make Cassette Audio...</a></li> <li><a class="dropdown-item" href="#" id="item_export_cassette">Make Cassette Audio...</a></li>
</ul> </ul>
</li> </li>
@ -178,7 +179,7 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
<span id="verilog_bar" style="display:none"> <span id="verilog_bar" style="display:none">
<span class="label"><span id="settle_label"></span> evals/clk</span> <span class="label"><span id="settle_label"></span> evals/clk</span>
</span> </span>
<span class="dropdown" style="float:right"> <span class="dropdown" style="float:right">
<span class="logo-gradient hidden-xs hidden-sm">8bitworkshop</span> <span class="logo-gradient hidden-xs hidden-sm">8bitworkshop</span>
&nbsp; &nbsp;
@ -292,6 +293,31 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
</div> </div>
</div> </div>
</div> </div>
<div id="embedGistModal" class="modal fade">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title">Share Code on Github</h3>
</div>
<div class="modal-body">
<p>If you have a Github account, you can share your code as a Github gist.</p>
<ul>
<li>Make sure the correct platform is selected.
<li>Go to <a href="https://gist.github.com/" target="_8bitgist">gist.github.com</a>
<li>Create a gist with your source code.
<li>Paste the final gist URL below.
</ul>
<textarea rows="2" cols="100" id="embedGistURL" class="cliptext"></textarea>
<p>The shareable URL will appear here:</p>
<textarea rows="2" cols="100" id="embedGistShareURL" class="cliptext"></textarea><br>
<button type="button" class="btn btn-primary" data-clipboard-target="#embedGistShareURL">Copy Shareable Link</button>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<script src="jquery/jquery-3.3.1.min.js"></script> <script src="jquery/jquery-3.3.1.min.js"></script>

View File

@ -9,7 +9,7 @@ word bcd_add(word a, word b) {
byte d = (a & 0xf) + (b & 0xf) + c; byte d = (a & 0xf) + (b & 0xf) + c;
c = 0; c = 0;
while (d >= 10) { while (d >= 10) {
c++; ++c;
d -= 10; d -= 10;
} }
result |= d << shift; result |= d << shift;

View File

@ -2,9 +2,15 @@
#include "neslib.h" #include "neslib.h"
#include "vrambuf.h" #include "vrambuf.h"
#pragma bss-name(push,"ZEROPAGE")
#pragma data-name(push,"ZEROPAGE")
// index to end of buffer // index to end of buffer
byte updptr = 0; byte updptr = 0;
#pragma bss-name(pop)
#pragma data-name(pop)
// add EOF marker to buffer // add EOF marker to buffer
void cendbuf(void) { void cendbuf(void) {
updbuf[updptr] = NT_UPD_EOF; updbuf[updptr] = NT_UPD_EOF;
@ -30,11 +36,12 @@ void cflushnow(void) {
// using horizontal increment // using horizontal increment
void putbytes(word addr, const char* str, byte len) { void putbytes(word addr, const char* str, byte len) {
if (updptr >= VBUFSIZE-4-len) cflushnow(); if (updptr >= VBUFSIZE-4-len) cflushnow();
updbuf[updptr++] = (addr >> 8) ^ NT_UPD_HORZ; updbuf[updptr] = (addr >> 8) ^ NT_UPD_HORZ;
updbuf[updptr++] = addr & 0xff; updbuf[++updptr] = addr & 0xff;
updbuf[updptr++] = len; updbuf[++updptr] = len;
while (len--) { while (len--) {
updbuf[updptr++] = *str++; updbuf[++updptr] = *str++;
} }
++updptr;
cendbuf(); cendbuf();
} }

View File

@ -157,6 +157,31 @@ export abstract class BasePlatform {
this.recorder.recordFrame(this.saveState()); this.recorder.recordFrame(this.saveState());
} }
} }
startProfiling() : ProfilerOutput {
var frame = null;
var output = {frame:null};
var i = 0;
var lastsl = 9999;
var start = 0;
(this as any).runEval((c:CpuState) => {
var sl = (this as any).getRasterScanline();
if (sl != lastsl) {
if (frame) {
frame.lines.push({start:start,end:i-1});
}
if (sl < lastsl) {
output.frame = frame;
frame = {iptab:new Uint32Array(0x8000), lines:[]}; // TODO: const
i = 0;
}
start = i;
lastsl = sl;
}
frame.iptab[i++] = c.EPC || c.PC;
return false; // profile forever
});
return output;
}
} }
export abstract class BaseDebugPlatform extends BasePlatform { export abstract class BaseDebugPlatform extends BasePlatform {
@ -208,29 +233,6 @@ export abstract class BaseDebugPlatform extends BasePlatform {
this.advance(novideo); this.advance(novideo);
this.postFrame(); this.postFrame();
} }
startProfiling() : ProfilerOutput {
var frame = null;
var output = {frame:null};
var i = 0;
var lastsl = 9999;
var start = 0;
(this as any).runEval((c:CpuState) => {
var sl = (this as any).getRasterScanline();
if (sl != lastsl) {
if (frame) frame.lines.push({start:start,end:i});
if (sl < lastsl) {
output.frame = frame;
frame = {iptab:new Uint32Array(14672), lines:[]};
i = 0;
}
start = i+1;
lastsl = sl;
}
frame.iptab[i++] = c.EPC || c.PC;
return false; // profile forever
});
return output;
}
} }
////// 6502 ////// 6502
@ -1028,6 +1030,7 @@ export abstract class BasicZ80ScanlinePlatform extends BaseZ80Platform {
abstract getKeyboardMap(); abstract getKeyboardMap();
abstract startScanline(sl : number); abstract startScanline(sl : number);
abstract drawScanline(sl : number); abstract drawScanline(sl : number);
getRasterScanline() { return this.currentScanline; }
constructor(mainElement : HTMLElement) { constructor(mainElement : HTMLElement) {
super(); super();

View File

@ -231,30 +231,6 @@ const _JSNESPlatform = function(mainElement) {
getRasterScanline() : number { getRasterScanline() : number {
return nes.ppu.scanline; return nes.ppu.scanline;
} }
startProfiling() : ProfilerOutput {
var frame0 = frameindex;
var frame = null;
var output = {frame:null};
var i = 0;
var lastsl = 9999;
var start = 0;
this.runEval((c) => {
var sl = this.getRasterScanline();
if (sl != lastsl) {
if (frame) frame.lines.push({start:start,end:i});
if (sl < lastsl) {
output.frame = frame;
frame = {iptab:new Uint32Array(14672), lines:[]};
i = 0;
}
start = i+1;
lastsl = sl;
}
frame.iptab[i++] = c.EPC || c.PC;
return false; //frameindex>frame0; // TODO
});
return output;
}
getCPUState() { getCPUState() {
var c = nes.cpu.toJSON(); var c = nes.cpu.toJSON();

View File

@ -153,6 +153,7 @@ class VCSPlatform extends BasePlatform {
Javatari.room.speaker.mute(); Javatari.room.speaker.mute();
} }
isDebugging() : boolean { isDebugging() : boolean {
// TODO: always true
return Javatari.room.console.onBreakpointHit != null; return Javatari.room.console.onBreakpointHit != null;
} }
clearDebug() { clearDebug() {

View File

@ -354,28 +354,24 @@ function getCurrentEditorFilename() : string {
} }
function _shareFileAsGist(e) { function _shareFileAsGist(e) {
loadScript("octokat.js/dist/octokat.js", () => { var gisturl_ta = $("#embedGistURL");
if (current_output == null) { // TODO var shareurl_ta = $("#embedGistShareURL");
alert("Please fix errors before sharing."); loadClipboardLibrary();
return true; gisturl_ta.change(() => {
} var gisturl = gisturl_ta.val() + '';
var text = projectWindows.getCurrentText(); var pos = gisturl.lastIndexOf('/');
if (!text) return false; if (pos >= 0) {
var github = new exports['Octokat'](); var gistkey = gisturl.substring(pos+1);
var files = {}; var embed = {
files[getCurrentEditorFilename()] = {"content": text}; platform: platform_id,
var gistdata = { gistkey: gistkey
"description": '8bitworkshop.com {"platform":"' + platform_id + '"}', };
"public": true, var linkqs = $.param(embed);
"files": files var fulllink = get8bitworkshopLink(linkqs, 'redir.html');
}; shareurl_ta.val(fulllink);
var gist = github.gists.create(gistdata).done(function(val) { }
var url = "http://8bitworkshop.com/?gistkey=" + val.id;
window.prompt("Copy link to clipboard (Ctrl+C, Enter)", url);
}).fail(function(err) {
alert("Error sharing file: " + err.message);
}); });
}); $("#embedGistModal").modal('show');
} }
function _shareEmbedLink(e) { function _shareEmbedLink(e) {
@ -387,10 +383,7 @@ function _shareEmbedLink(e) {
alert("Can't share a Verilog executable yet. (It's not actually a ROM...)"); alert("Can't share a Verilog executable yet. (It's not actually a ROM...)");
return true; return true;
} }
loadScript('lib/clipboard.min.js', () => { loadClipboardLibrary();
var ClipboardJS = exports['ClipboardJS'];
new ClipboardJS(".btn");
});
loadScript('lib/liblzg.js', () => { loadScript('lib/liblzg.js', () => {
// TODO: Module is bad var name (conflicts with MAME) // TODO: Module is bad var name (conflicts with MAME)
var lzgrom = compressLZG( window['Module'], Array.from(<Uint8Array>current_output) ); var lzgrom = compressLZG( window['Module'], Array.from(<Uint8Array>current_output) );
@ -402,11 +395,7 @@ function _shareEmbedLink(e) {
r: lzgb64 r: lzgb64
}; };
var linkqs = $.param(embed); var linkqs = $.param(embed);
console.log(linkqs); var fulllink = get8bitworkshopLink(linkqs, 'embed.html');
var loc = window.location;
var prefix = loc.pathname.replace('index.html','');
var protocol = (loc.host == '8bitworkshop.com') ? 'https:' : loc.protocol;
var fulllink = protocol+'//'+loc.host+prefix+'embed.html?' + linkqs;
var iframelink = '<iframe width=640 height=600 src="' + fulllink + '">'; var iframelink = '<iframe width=640 height=600 src="' + fulllink + '">';
$("#embedLinkTextarea").text(fulllink); $("#embedLinkTextarea").text(fulllink);
$("#embedIframeTextarea").text(iframelink); $("#embedIframeTextarea").text(iframelink);
@ -419,6 +408,22 @@ function _shareEmbedLink(e) {
return true; return true;
} }
function loadClipboardLibrary() {
loadScript('lib/clipboard.min.js', () => {
var ClipboardJS = exports['ClipboardJS'];
new ClipboardJS(".btn");
});
}
function get8bitworkshopLink(linkqs : string, fn : string) {
console.log(linkqs);
var loc = window.location;
var prefix = loc.pathname.replace('index.html','');
var protocol = (loc.host == '8bitworkshop.com') ? 'https:' : loc.protocol;
var fulllink = protocol+'//'+loc.host+prefix+fn+'?' + linkqs;
return fulllink;
}
function _downloadCassetteFile(e) { function _downloadCassetteFile(e) {
if (current_output == null) { // TODO if (current_output == null) { // TODO
alert("Please fix errors before exporting."); alert("Please fix errors before exporting.");
@ -860,9 +865,15 @@ function getSymbolAtAddress(a : number) {
return ''; return '';
} }
var debugTickPaused = false;
function updateDebugWindows() { function updateDebugWindows() {
if (platform.isRunning()) { if (platform.isRunning()) {
projectWindows.tick(); projectWindows.tick();
debugTickPaused = false;
} else if (!debugTickPaused) { // final tick after pausing
projectWindows.tick();
debugTickPaused = true;
} }
setTimeout(updateDebugWindows, 200); setTimeout(updateDebugWindows, 200);
} }
@ -1094,6 +1105,7 @@ function setupDebugControls(){
$(".dropdown-menu").collapse({toggle: false}); $(".dropdown-menu").collapse({toggle: false});
$("#item_new_file").click(_createNewFile); $("#item_new_file").click(_createNewFile);
$("#item_upload_file").click(_uploadNewFile); $("#item_upload_file").click(_uploadNewFile);
$("#item_share_github").click(_shareFileAsGist);
$("#item_share_file").click(_shareEmbedLink); $("#item_share_file").click(_shareEmbedLink);
$("#item_reset_file").click(_revertFile); $("#item_reset_file").click(_revertFile);
$("#item_rename_file").click(_renameFile); $("#item_rename_file").click(_renameFile);
@ -1385,14 +1397,15 @@ function loadScript(scriptfn, onload) {
export function setupSplits() { export function setupSplits() {
const splitName = 'workspace-split3-' + platform_id; const splitName = 'workspace-split3-' + platform_id;
var sizes = [0, 50, 50]; var sizes = [0, 50, 50];
if (platform_id != 'vcs') // TODO
sizes = [12, 44, 44];
var sizesStr = hasLocalStorage && localStorage.getItem(splitName); var sizesStr = hasLocalStorage && localStorage.getItem(splitName);
if (sizesStr) { if (sizesStr) {
try { try {
sizes = JSON.parse(sizesStr); sizes = JSON.parse(sizesStr);
} catch (e) { console.log(e); } } catch (e) { console.log(e); }
} }
var split; var split = Split(['#sidebar', '#workspace', '#emulator'], {
split = Split(['#sidebar', '#workspace', '#emulator'], {
sizes: sizes, sizes: sizes,
minSize: [0, 250, 250], minSize: [0, 250, 250],
onDrag: () => { onDrag: () => {
@ -1401,6 +1414,7 @@ export function setupSplits() {
onDragEnd: () => { onDragEnd: () => {
if (hasLocalStorage) if (hasLocalStorage)
localStorage.setItem(splitName, JSON.stringify(split.getSizes())) localStorage.setItem(splitName, JSON.stringify(split.getSizes()))
projectWindows.resize();
}, },
}); });
} }

View File

@ -11,6 +11,7 @@ import { platform, platform_id, compparams, current_project, lastDebugState, pro
export interface ProjectView { export interface ProjectView {
createDiv(parent:HTMLElement, text:string) : HTMLElement; createDiv(parent:HTMLElement, text:string) : HTMLElement;
dispose?() : void;
refresh(moveCursor:boolean) : void; refresh(moveCursor:boolean) : void;
tick?() : void; tick?() : void;
getPath?() : string; getPath?() : string;
@ -24,6 +25,7 @@ export interface ProjectView {
markErrors?(errors:WorkerError[]) : void; markErrors?(errors:WorkerError[]) : void;
clearErrors?() : void; clearErrors?() : void;
setTimingResult?(result:CodeAnalyzer) : void; setTimingResult?(result:CodeAnalyzer) : void;
recreateOnResize? : boolean;
}; };
declare var CodeMirror; declare var CodeMirror;
@ -36,6 +38,13 @@ function jumpToLine(ed, i:number) {
ed.scrollTo(null, t - middleHeight - 5); ed.scrollTo(null, t - middleHeight - 5);
} }
function createTextSpan(text:string, className:string) : HTMLElement {
var span = document.createElement("span");
span.setAttribute("class", className);
span.appendChild(document.createTextNode(text));
return span;
}
// TODO: https://stackoverflow.com/questions/10463518/converting-em-to-px-in-javascript-and-getting-default-font-size // TODO: https://stackoverflow.com/questions/10463518/converting-em-to-px-in-javascript-and-getting-default-font-size
function getVisibleEditorLineHeight() : number{ function getVisibleEditorLineHeight() : number{
return $("#booksMenuButton").first().height(); return $("#booksMenuButton").first().height();
@ -119,9 +128,7 @@ export class SourceEditor implements ProjectView {
this.inspectWidget = null; this.inspectWidget = null;
} }
if (result) { if (result) {
var infospan = document.createElement("span"); var infospan = createTextSpan(result, "tooltipinfoline");
infospan.setAttribute("class", "tooltipinfoline");
infospan.appendChild(document.createTextNode(result));
var line = this.editor.getCursor().line; var line = this.editor.getCursor().line;
this.inspectWidget = this.editor.addLineWidget(line, infospan, {above:false}); this.inspectWidget = this.editor.addLineWidget(line, infospan, {above:false});
} }
@ -156,9 +163,7 @@ export class SourceEditor implements ProjectView {
} }
addErrorLine(line:number, msg:string) { addErrorLine(line:number, msg:string) {
var errspan = document.createElement("span"); var errspan = createTextSpan(msg, "tooltiperrorline");
errspan.setAttribute("class", "tooltiperrorline");
errspan.appendChild(document.createTextNode(msg));
this.errorwidgets.push(this.editor.addLineWidget(line, errspan)); this.errorwidgets.push(this.editor.addLineWidget(line, errspan));
} }
@ -547,7 +552,7 @@ export class ListingView extends DisassemblerView implements ProjectView {
var asmtext = this.assemblyfile.text; var asmtext = this.assemblyfile.text;
var disasmview = this.getDisasmView(); var disasmview = this.getDisasmView();
disasmview.setValue(asmtext); disasmview.setValue(asmtext);
var debugging = platform.isDebugging && platform.isDebugging(); var debugging = true; // TODO: platform.isDebugging && platform.isDebugging();
var findPC = debugging ? pc : -1; var findPC = debugging ? pc : -1;
if (findPC >= 0 && this.assemblyfile) { if (findPC >= 0 && this.assemblyfile) {
var lineno = this.assemblyfile.findLineForOffset(findPC, 15); var lineno = this.assemblyfile.findLineForOffset(findPC, 15);
@ -570,6 +575,7 @@ export class MemoryView implements ProjectView {
dumplines; dumplines;
maindiv : HTMLElement; maindiv : HTMLElement;
static IGNORE_SYMS = {s__INITIALIZER:true, /* s__GSINIT:true, */ _color_prom:true}; static IGNORE_SYMS = {s__INITIALIZER:true, /* s__GSINIT:true, */ _color_prom:true};
recreateOnResize = true;
/* /*
read(addr:number) { read(addr:number) {
// TODO: b offset ? // TODO: b offset ?
@ -727,6 +733,7 @@ export class BinaryFileView implements ProjectView {
maindiv : HTMLElement; maindiv : HTMLElement;
path:string; path:string;
data:Uint8Array; data:Uint8Array;
recreateOnResize = true;
constructor(path:string, data:Uint8Array) { constructor(path:string, data:Uint8Array) {
this.path = path; this.path = path;
@ -841,10 +848,11 @@ export class ProfileView implements ProjectView {
prof : ProfilerOutput; prof : ProfilerOutput;
maindiv : HTMLElement; maindiv : HTMLElement;
symcache : {}; symcache : {};
recreateOnResize = true;
createDiv(parent : HTMLElement) { createDiv(parent : HTMLElement) {
var div = document.createElement('div'); var div = document.createElement('div');
div.setAttribute("class", "memdump"); div.setAttribute("class", "profiler");
parent.appendChild(div); parent.appendChild(div);
this.showMemoryWindow(parent, div); this.showMemoryWindow(parent, div);
return this.maindiv = div; return this.maindiv = div;
@ -857,9 +865,8 @@ export class ProfileView implements ProjectView {
itemHeight: getVisibleEditorLineHeight(), itemHeight: getVisibleEditorLineHeight(),
totalRows: 262, totalRows: 262,
generatorFn: (row : number) => { generatorFn: (row : number) => {
var s = this.getProfileLineAt(row);
var linediv = document.createElement("div"); var linediv = document.createElement("div");
linediv.appendChild(document.createTextNode(s)); this.addProfileLine(linediv, row);
return linediv; return linediv;
} }
}); });
@ -868,13 +875,13 @@ export class ProfileView implements ProjectView {
this.tick(); this.tick();
} }
getProfileLineAt(row : number) : string { addProfileLine(div : HTMLElement, row : number) : void {
var s = lpad(row+': ',5); div.appendChild(createTextSpan(lpad(row+':',4), "profiler-lineno"));
if (!this.prof) return s; if (!this.prof) return;
var f = this.prof.frame; var f = this.prof.frame;
if (!f) return s; if (!f) return;
var l = f.lines[row]; var l = f.lines[row];
if (!l) return s; if (!l) return;
var lastsym = ''; var lastsym = '';
for (var i=l.start; i<=l.end; i++) { for (var i=l.start; i<=l.end; i++) {
var pc = f.iptab[i]; var pc = f.iptab[i];
@ -884,11 +891,14 @@ export class ProfileView implements ProjectView {
this.symcache[pc] = sym; this.symcache[pc] = sym;
} }
if (sym != lastsym) { if (sym != lastsym) {
s += sym + ' '; var cls = "profiler";
if (sym.startsWith('_')) cls = "profiler-cident";
else if (sym.startsWith('@')) cls = "profiler-local";
else if (/^\d*[.]/.exec(sym)) cls = "profiler-local";
div.appendChild(createTextSpan(' '+sym, cls));
lastsym = sym; lastsym = sym;
} }
} }
return s;
} }
refresh() { refresh() {
@ -900,15 +910,17 @@ export class ProfileView implements ProjectView {
$(this.maindiv).find('[data-index]').each( (i,e) => { $(this.maindiv).find('[data-index]').each( (i,e) => {
var div = $(e); var div = $(e);
var row = parseInt(div.attr('data-index')); var row = parseInt(div.attr('data-index'));
var oldtext = div.text(); div.empty();
var newtext = this.getProfileLineAt(row); this.addProfileLine(div[0], row);
if (oldtext != newtext)
div.text(newtext);
}); });
} }
// TODO: better way to keep it profiling? also, it clears the buffer // TODO: better way to keep it profiling single-frame? also, it clears the buffer
if (platform.isRunning()) { if (platform.isRunning() /* && !platform.isDebugging()*/ ) {
this.prof = platform.startProfiling(); this.prof = platform.startProfiling();
} }
} }
dispose() : void {
platform.clearDebug();
}
} }

View File

@ -10,7 +10,6 @@ type WindowCreateFunction = (id:string) => ProjectView;
export class ProjectWindows { export class ProjectWindows {
containerdiv:HTMLElement; containerdiv:HTMLElement;
project:CodeProject; project:CodeProject;
id2window : {[id:string]:ProjectView} = {}; id2window : {[id:string]:ProjectView} = {};
id2createfn : {[id:string]:WindowCreateFunction} = {}; id2createfn : {[id:string]:WindowCreateFunction} = {};
id2div : {[id:string]:HTMLElement} = {}; id2div : {[id:string]:HTMLElement} = {};
@ -18,17 +17,17 @@ export class ProjectWindows {
activewnd : ProjectView; activewnd : ProjectView;
activediv : HTMLElement; activediv : HTMLElement;
lasterrors : WorkerError[]; lasterrors : WorkerError[];
constructor(containerdiv:HTMLElement, project:CodeProject) { constructor(containerdiv:HTMLElement, project:CodeProject) {
this.containerdiv = containerdiv; this.containerdiv = containerdiv;
this.project = project; this.project = project;
} }
// TODO: delete windows ever? // TODO: delete windows ever?
setCreateFunc(id:string, createfn:WindowCreateFunction) : void { setCreateFunc(id:string, createfn:WindowCreateFunction) : void {
this.id2createfn[id] = createfn; this.id2createfn[id] = createfn;
} }
createOrShow(id:string) : ProjectView { createOrShow(id:string) : ProjectView {
var wnd = this.id2window[id]; var wnd = this.id2window[id];
if (!wnd) { if (!wnd) {
@ -42,6 +41,8 @@ export class ProjectWindows {
if (this.activewnd != wnd) { if (this.activewnd != wnd) {
if (this.activediv) if (this.activediv)
$(this.activediv).hide(); $(this.activediv).hide();
if (this.activewnd && this.activewnd.dispose)
this.activewnd.dispose();
this.activediv = div; this.activediv = div;
this.activewnd = wnd; this.activewnd = wnd;
$(div).show(); $(div).show();
@ -55,13 +56,13 @@ export class ProjectWindows {
put(id:string, window:ProjectView) : void { put(id:string, window:ProjectView) : void {
this.id2window[id] = window; this.id2window[id] = window;
} }
refresh(moveCursor:boolean) : void { refresh(moveCursor:boolean) : void {
// refresh current window // refresh current window
if (this.activewnd && this.activewnd.refresh) if (this.activewnd && this.activewnd.refresh)
this.activewnd.refresh(moveCursor); this.activewnd.refresh(moveCursor);
} }
tick() : void { tick() : void {
if (this.activewnd && this.activewnd.tick) if (this.activewnd && this.activewnd.tick)
this.activewnd.tick(); this.activewnd.tick();
@ -71,7 +72,7 @@ export class ProjectWindows {
this.lasterrors = errors; this.lasterrors = errors;
this.refreshErrors(); this.refreshErrors();
} }
refreshErrors() : void { refreshErrors() : void {
if (this.activewnd && this.activewnd.markErrors) { if (this.activewnd && this.activewnd.markErrors) {
if (this.lasterrors && this.lasterrors.length) if (this.lasterrors && this.lasterrors.length)
@ -80,9 +81,9 @@ export class ProjectWindows {
this.activewnd.clearErrors(); this.activewnd.clearErrors();
} }
} }
getActive() : ProjectView { return this.activewnd; } getActive() : ProjectView { return this.activewnd; }
getActiveID() : string { return this.activeid; } getActiveID() : string { return this.activeid; }
getCurrentText() : string { getCurrentText() : string {
@ -91,5 +92,13 @@ export class ProjectWindows {
else else
alert("Please switch to an editor window."); alert("Please switch to an editor window.");
} }
};
resize() : void {
if (this.activeid && this.activewnd && this.activewnd.recreateOnResize) {
this.activewnd = null;
this.id2window[this.activeid] = null;
this.id2div[this.activeid] = null;
this.createOrShow(this.activeid);
}
}
};