diff --git a/css/ui.css b/css/ui.css index 57977cea..b07f1af9 100644 --- a/css/ui.css +++ b/css/ui.css @@ -121,6 +121,7 @@ div.mem_info a.selected { padding-right:4px; padding-top:2px; padding-bottom:2px; + margin:1px; } .btn_label { color: #ccc; @@ -138,6 +139,9 @@ div.mem_info a.selected { .btn_recording { color: #ff3333; } +.btn_toolbar { + margin:4px; +} span.hilite { color: #ff66ff; } diff --git a/doc/notes.txt b/doc/notes.txt index d58e0b42..e9626328 100644 --- a/doc/notes.txt +++ b/doc/notes.txt @@ -93,6 +93,7 @@ TODO: - put globals into view/controller objects - upload binary files doesn't do what's expected, changing pulldown and whatnot - chrome autostart audio: https://github.com/processing/p5.js-sound/issues/249 +- firefox autostart audio: https://support.mozilla.org/en-US/kb/block-autoplay - show player controls for each platform, allow touch support, navigator.getGamepads - better undo/diff for mistakes? - ide bug/feature visualizer for sponsors diff --git a/src/emu.ts b/src/emu.ts index 78d3ca0a..2c2d0fba 100644 --- a/src/emu.ts +++ b/src/emu.ts @@ -4,6 +4,7 @@ import { hex, clamp } from "./util"; // external modules declare var jt, Javatari, Z80_fast, CPU6809; +declare var Mousetrap; // Emulator classes @@ -497,3 +498,48 @@ export function newAddressDecoder(table : AddressDecoderEntry[], options?:Addres return new (AddressDecoder as any)(table, options); } +/// TOOLBAR + +export class Toolbar { + div : JQuery; + grp : JQuery; + mousetrap; + boundkeys = []; + + constructor(parentDiv:HTMLElement) { + this.mousetrap = new Mousetrap(parentDiv); + this.div = $(document.createElement("div")).addClass("btn_toolbar"); + parentDiv.appendChild(this.div[0]); + this.newGroup(); + } + destroy() { + if (this.div) { + this.div.remove(); + this.div = null; + } + if (this.mousetrap) { + for (var key of this.boundkeys) { + this.mousetrap.unbind(key); + } + this.mousetrap = null; + } + } + newGroup() { + this.grp = $(document.createElement("span")).addClass("btn_group").appendTo(this.div); + } + add(key:string, alttext:string, icon:string, fn:(e,combo) => void) { + if (icon) { + var btn = $(document.createElement("button")).addClass("btn"); + if (icon.startsWith('glyphicon')) { + icon = ''; + } + btn.html(icon); + btn.prop("title", alttext + " (" + key + ")"); + btn.click(fn); + this.grp.append(btn); + } + this.mousetrap.bind(key, fn); + this.boundkeys.push(key); + } +} + diff --git a/src/waveform.ts b/src/waveform.ts index 1d074100..c3cd78c6 100644 --- a/src/waveform.ts +++ b/src/waveform.ts @@ -1,6 +1,7 @@ +import { Toolbar } from "./emu"; + declare var VirtualList; -declare var Mousetrap; export interface WaveformMeta { label : string; @@ -15,6 +16,7 @@ export interface WaveformProvider { export class WaveformView { parent : HTMLElement; wfp : WaveformProvider; + toolbar : Toolbar; wavelist; meta : WaveformMeta[]; lines : HTMLCanvasElement[] = []; @@ -46,6 +48,11 @@ export class WaveformView { // remove old thing if (this.wavelist) { $(this.wavelist.container).remove(); + this.wavelist = null; + } + if (this.toolbar) { + this.toolbar.destroy(); + this.toolbar = null; } } @@ -77,6 +84,7 @@ export class WaveformView { var wlc = this.wavelist.container; wlc.tabIndex = -1; // make it focusable //wlc.style = "overflow-x: hidden"; // TODO? + this.toolbar = new Toolbar(this.parent); $(this.parent).append(wlc); var down = false; var selfn = (e) => { @@ -94,32 +102,32 @@ export class WaveformView { down = false; //if (e['pointerId']) e.target.releasePointerCapture(e['pointerId']); }); - Mousetrap(wlc).bind('=', (e,combo) => { + this.toolbar.add('=', 'Zoom In', 'glyphicon-zoom-in', (e,combo) => { this.setZoom(this.zoom * 2); }); - Mousetrap(wlc).bind('+', (e,combo) => { + this.toolbar.add('+', 'Zoom In', null, (e,combo) => { this.setZoom(this.zoom * 2); }); - Mousetrap(wlc).bind('-', (e,combo) => { + this.toolbar.add('-', 'Zoom Out', 'glyphicon-zoom-out', (e,combo) => { this.setZoom(this.zoom / 2); }); - Mousetrap(wlc).bind('left', (e,combo) => { - this.setSelTime(this.tsel - 1); - }); - Mousetrap(wlc).bind('right', (e,combo) => { - this.setSelTime(this.tsel + 1); - }); - Mousetrap(wlc).bind('ctrl+left', (e,combo) => { - this.setSelTime(this.tsel - this.clocksPerPage/4); - }); - Mousetrap(wlc).bind('ctrl+right', (e,combo) => { - this.setSelTime(this.tsel + this.clocksPerPage/4); - }); - Mousetrap(wlc).bind('ctrl+shift+left', (e,combo) => { + this.toolbar.add('ctrl+shift+left', 'Move to beginning', 'glyphicon-backward', (e,combo) => { this.setSelTime(0); this.setOrgTime(0); }); - Mousetrap(wlc).bind('h', (e,combo) => { + this.toolbar.add('ctrl+left', 'Move left 1/4 page', 'glyphicon-fast-backward', (e,combo) => { + this.setSelTime(this.tsel - this.clocksPerPage/4); + }); + this.toolbar.add('left', 'Move left 1 clock', 'glyphicon-step-backward', (e,combo) => { + this.setSelTime(this.tsel - 1); + }); + this.toolbar.add('right', 'Move right 1 clock', 'glyphicon-step-forward', (e,combo) => { + this.setSelTime(this.tsel + 1); + }); + this.toolbar.add('ctrl+right', 'Move right 1/4 page', 'glyphicon-fast-forward', (e,combo) => { + this.setSelTime(this.tsel + this.clocksPerPage/4); + }); + this.toolbar.add('h', 'Switch between hex/decimal format', 'glyphicon-barcode', (e,combo) => { this.hexformat = !this.hexformat; this.refresh(); });