// Copyright 2022 Randall Fairman "use strict";var theBrowser=function(){let blah=navigator.userAgent;if(blah.indexOf("Firefox")>-1) return"Firefox";if(blah.indexOf("Chrome")>-1) return"Chrome";console.log("MAKING DEFAULT 'CHROME' ASSUMPTION ABOUT THE BROWSWER!!!");return"Chrome";}();function sleep(ms){return new Promise(resolve=>setTimeout(resolve,ms));} function getAugmentedFunction(fcnName){return window[fcnName];} class PageData{constructor(){this.pageHeight=0;this.pageWidth=0;this.leftMargin=0;this.rightMargin=0;this.textWidth=0;this.insertPoint=[];this.deleteHeight=[];this.aboveHeight=[];this.belowHeight=[];this.name=[];this.done=[];this.drawFcn=[];}} class PDFDocument{static async setPDF(thePDF){this.pdf=thePDF;this.numberOfPages=thePDF.numPages;for(let i=1;i<=this.numberOfPages;i++){await thePDF.getPage(i).then(function(page){PDFDocument.pageSpecs[i-1]=new PageData();PDFDocument.pageSpecs[i-1].pageWidth=page.view[2];PDFDocument.pageSpecs[i-1].pageHeight=page.view[3];PDFDocument.theCanvases[i-1]=null;PDFDocument.pageAge[i-1]=0;});}} static isLoaded(){if(this.pdf===null) return false;else return true;} static getZoom(){return this.zoom;} static setZoom(z){this.zoom=z;this.flushBuffer();} static getCanvas(n){if(this.theCanvases[n]===null) console.log("ERROR! Canvas for page missing: "+n);return this.theCanvases[n];} static async render(n){if(PDFDocument.theCanvases[n]!==null) return;let thePage=await PDFDocument.pdf.getPage(n+1);let newCanvas=document.createElement('canvas');PDFDocument.theCanvases[n]=newCanvas;PDFDocument.pageAge[n]=PDFDocument.renderCount;++PDFDocument.renderCount;let offctx=newCanvas.getContext('2d');let viewport=thePage.getViewport(PDFDocument.zoom);newCanvas.width=viewport.width;newCanvas.height=viewport.height;await thePage.render({canvasContext:offctx,viewport:viewport});} static trimBuffer(){let ctot=0;for(let i=0;iPDFDocument.pageBufSize){PDFDocument.removeOldestPage();--ctot;}} static removeOldestPage(){let oldestIndex=-1;let oldestAge=this.pageAge[0];for(let i=0;i{theCode.addEventListener("load",resolve,{once:true});theCode.addEventListener("error",reject,{once:true});});document.body.appendChild(theCode);await p;} async function getFigureInfo(textBody){let lines=textBody.split('\n');for(let i=0;itotWidth){body.style.width="0px";return;} body.style.width=totWidth+"px";} function ctxTopLevelAdjust(){var canvas=document.getElementById("pdf_renderer");let ctx=canvas.getContext('2d');ctx.resetTransform();let visWidth=document.documentElement.clientWidth;let totWidth=FullPanel.getFullWidth();let z=PDFDocument.getZoom();if(visWidth>totWidth){let canvasCenter=canvas.width/2;let docCenter=FullPanel.getFullWidth()/2;docCenter*=PDFDocument.getZoom();ctx.translate(canvasCenter-docCenter,0);} else{ctx.translate(-window.scrollX*PDFDocument.getZoom(),0);} return ctx;} async function fullRender(){var canvas=document.getElementById("pdf_renderer");var ctx=canvas.getContext('2d');ctx.resetTransform();let visWidth=document.documentElement.clientWidth;let z=PDFDocument.getZoom();ctx.clearRect(0,0,visWidth*z,document.documentElement.clientHeight*z);await FullPanel.renderAll(canvas.height);} function adjustCanvas(){var canvas=document.getElementById("pdf_renderer");canvas.style.width=document.documentElement.clientWidth+"px";canvas.style.height=document.documentElement.clientHeight+"px";canvas.width=document.documentElement.clientWidth*window.devicePixelRatio;canvas.height=document.documentElement.clientHeight*window.devicePixelRatio;} async function doScrollGuts(id){await Events.waitMyTurn(id);await fullRender();Events.allDone(id);} function doScroll(){if(PDFDocument.isLoaded()==false) return;let id=Events.getID();doScrollGuts(id);} async function doResizeGuts(id){await Events.waitMyTurn(id);PDFDocument.flushBuffer();console.log("ratio: "+window.devicePixelRatio);adjustCanvas();PDFDocument.setZoom(window.devicePixelRatio);adjustScrollBars();await fullRender();Events.allDone(id);} function doResize(){let id=Events.getID();doResizeGuts(id);} async function mouseDownGuts(id,x,y){await Events.waitMyTurn(id);let visWidth=document.documentElement.clientWidth;let totWidth=FullPanel.getFullWidth();let canvas=document.getElementById("pdf_renderer");if(visWidth>totWidth){let canvasCenter=canvas.width/2;let docCenter=FullPanel.getFullWidth()/2;canvasCenter=canvasCenter/PDFDocument.getZoom();x=x-(canvasCenter-docCenter);} else{x=x+window.scrollX;} y=y+window.scrollY;FullPanel.mouseDown(x,y);Events.allDone(id);} function doMouseDown(e){let id=Events.getID();mouseDownGuts(id,e.x,e.y);} async function mouseMoveGuts(id,x,y){await Events.waitMyTurn(id);let visWidth=document.documentElement.clientWidth;let totWidth=FullPanel.getFullWidth();let canvas=document.getElementById("pdf_renderer");if(visWidth>totWidth){let canvasCenter=canvas.width/2;let docCenter=FullPanel.getFullWidth()/2;canvasCenter=canvasCenter/PDFDocument.getZoom();x=x-(canvasCenter-docCenter);} else{x=x+window.scrollX;} y=y+window.scrollY;FullPanel.mouseMove(x,y);Events.allDone(id);} function doMouseMove(e){let id=Events.getID();mouseMoveGuts(id,e.x,e.y);} async function mouseUpGuts(id,x,y){await Events.waitMyTurn(id);let visWidth=document.documentElement.clientWidth;let totWidth=FullPanel.getFullWidth();let canvas=document.getElementById("pdf_renderer");if(visWidth>totWidth){let canvasCenter=canvas.width/2;let docCenter=FullPanel.getFullWidth()/2;canvasCenter=canvasCenter/PDFDocument.getZoom();x=x-(canvasCenter-docCenter);} else{x=x+window.scrollX;} y=y+window.scrollY;FullPanel.mouseUp(x,y);Events.allDone(id);} function doMouseUp(e){let id=Events.getID();mouseUpGuts(id,e.x,e.y);} function doTikzClick(){for(let pi=0;pi0) return this.totalWidth;for(let i=0;ithis.totalWidth) this.totalWidth=pp.w;} return this.totalWidth;} static mouseDown(x,y){WidgetManager.focusOwner=null;let i=0;for(;iy){i-=1;break;}} if(i===this.thePages.length) i=this.thePages.length-1;if((i==this.thePages.length)||(i<0)) return;this.thePages[i].mouseDown(x,y);} static mouseMove(x,y){if(WidgetManager.mouseOwner===null) return;let i=0;for(;iy){i-=1;break;}} if(i===this.thePages.length) i=this.thePages.length-1;if((i==this.thePages.length)||(i<0)) return;this.thePages[i].mouseMove(x,y);} static mouseUp(x,y){if(WidgetManager.mouseOwner===null) return;let i=0;for(;iy){i-=1;break;}} if(i===this.thePages.length) i=this.thePages.length-1;if((i==this.thePages.length)||(i<0)) return;this.thePages[i].mouseUp(x,y);WidgetManager.mouseOwner=null;}} FullPanel.thePages=[];FullPanel.totalWidth=-1;class PagePanel{constructor(pageNum,pageSpec,v){this.v=0;this.w=0;this.h=0;this.pageNum=0;this.parts=[];this.w=pageSpec.pageWidth;this.v=v;this.pageNum=pageNum;let s=pageSpec;if(s.insertPoint.length==0){let p=new PDFPanel(pageNum,this.v,0,0,this.v,this.w,s.pageHeight);this.h=s.pageHeight;this.parts=[p];} else{let srcV=0;let destV=0;let totalV=v;for(let j=0;jvpos+height) return;await PDFDocument.render(this.pageNum);} render(height){let vpos=window.scrollY;if(this.v+this.hvpos+height) return;let ctx=ctxTopLevelAdjust();for(let i=0;i-1) callingFcn=callingFcn.split('.')[1];return callingFcn;} else{console.log("IMPOSSIBLE ERROR DUE TO UNKNOWN BROWSER TYPE!!!");return"";}} class Widget{constructor(owner,type,x,y,scale,hide,name){this.owner="";this.type="";this.name="";this.widgetX=0;this.widgetY=0;this.scale=1.0;this.hide=true;this.owner=owner;this.type=type;this.widgetX=x;this.widgetY=y;this.scale=scale;this.hide=hide;this.name=name;this.betterOwner=getAugmentedFunction(owner);WidgetManager.register(this);} draw(ctx){console.log("Called Widget.draw()!!!");} mouseDown(x,y){console.log("Called Widget.mouseDown()!!! "+this.name);return false;} mouseMove(x,y){console.log("Called Widget.mouseMove()!!!");} mouseUp(x,y){console.log("Called Widget.mouseUp()!!!");}} function doAnimation(theWidget){let id=Events.getID();doAnimationGuts(id,theWidget);} async function doAnimationGuts(id,theWidget){await Events.waitMyTurn(id);await renderFrame(theWidget);theWidget.curStep+=theWidget.stepsPerFrame;theWidget.advanceFrame();Events.allDone(id);} async function renderFrame(theWidget){let myFunc=getAugmentedFunction(theWidget.owner);let fpc=myFunc.figurePanelClass;await fpc.render();} function getFigureRect(theWidget){let myFunc=getAugmentedFunction(theWidget.owner);let fpc=myFunc.figurePanelClass;let answer={w:fpc.textWidth,ha:fpc.h-fpc.lowerPadding,hb:fpc.lowerPadding};return answer;} class AnimationWidget extends Widget{constructor(){super(...arguments);this.curStep=0;this.stepsPerFrame=1;this.animID=0;} advanceFrame(){console.log("Calling abstract AnimationWidget.advanceFrame()!");}} class LoopAnimWidget extends AnimationWidget{constructor(){super(...arguments);this.steps=100;this.start=0;this.timeStep=20;this.visSteps=true;this.visFastSlow=true;this.visPauseRun=true;this.visCircle=true;this.triGrab=true;this.pCircle=null;this.pUpStep=null;this.pDownStep=null;this.pFaster=null;this.pSlower=null;this.pPauseRun=null;this.aRunning=true;this.sCircle=false;this.sPauseRun=false;this.sFaster=false;this.sSlower=false;this.sUpStep=false;this.sDownStep=false;} static register(ctx,x,y,scale,visWidget,steps,start,timeStep,visSteps,visFastSlow,visPauseRun,visCircle,triGrab,name){let type="LoopWidget";let caller=getCaller();let w=WidgetManager.knownWidget(caller,type,name);if(w!=null){w.draw(ctx);return w;} w=new LoopAnimWidget(caller,type,x,y,scale,!visWidget,name);w.steps=steps;w.start=start;w.timeStep=timeStep;w.visSteps=visSteps;w.visFastSlow=visFastSlow;w.visPauseRun=visPauseRun;w.visCircle=visCircle;w.triGrab=triGrab;w.curStep=w.start;WidgetManager.register(w);w.animID=setInterval(doAnimation,w.timeStep,w);w.draw(ctx);return w;} advanceFrame(){this.curStep+=this.stepsPerFrame;if(this.curStep>=this.steps) this.curStep-=this.steps;} draw(ctx){if(this.hide===true) return;if(ctx instanceof CTX) return;let saveT=ctx.getTransform();ctx.translate(this.widgetX,this.widgetY);ctx.scale(this.scale,this.scale);var p=new Path2D();var r=40;var cx=0;var cy=0;var circWidth=3;if(this.visCircle==true){p.ellipse(cx,cy,r,r,0,0,2*Math.PI);this.pCircle=new Path2D(p);ctx.lineWidth=circWidth;if(this.sCircle==true) ctx.strokeStyle=LoopAnimWidget.sColor;else ctx.strokeStyle="black";ctx.stroke(p);ctx.lineWidth=1;var loc=-2*Math.PI*this.curStep/this.steps;var triHeight=10;var triAngle=Math.PI/20;p=new Path2D();var x=cx+(r-circWidth/2)*Math.cos(loc);var y=cy+(r-circWidth/2)*Math.sin(loc);p.moveTo(x,y);x=cx+(r-triHeight)*Math.cos(loc+triAngle);y=cy+(r-triHeight)*Math.sin(loc+triAngle);p.lineTo(x,y);x=cx+(r-triHeight)*Math.cos(loc-triAngle);y=cy+(r-triHeight)*Math.sin(loc-triAngle);p.lineTo(x,y);p.closePath();ctx.strokeStyle="red";ctx.stroke(p);ctx.strokeStyle="black";} let arrowOffset=18;let lowerGap=6;let arrowHeight=7;let arrowDepth=4;let arrowPairSpace=3;let arrowThick=1.25;if(this.visFastSlow===true){ctx.lineWidth=arrowThick;if(this.sFaster==true) ctx.strokeStyle=LoopAnimWidget.sColor;else ctx.strokeStyle="black";p=new Path2D();p.moveTo(cx+arrowOffset,cy-r-circWidth/2-lowerGap);p.lineTo(cx+arrowOffset+arrowDepth,cy-r-circWidth/2-lowerGap-arrowHeight);p.lineTo(cx+arrowOffset,cy-r-circWidth/2-lowerGap-2*arrowHeight);ctx.stroke(p);p=new Path2D();p.moveTo(cx+arrowOffset+arrowPairSpace,cy-r-circWidth/2-lowerGap);p.lineTo(cx+arrowOffset+arrowDepth+arrowPairSpace,cy-r-circWidth/2-lowerGap-arrowHeight);p.lineTo(cx+arrowOffset+arrowPairSpace,cy-r-circWidth/2-lowerGap-2*arrowHeight);ctx.stroke(p);this.pFaster=new Path2D();this.pFaster.rect(cx+arrowOffset-arrowThick,cy-r-circWidth/2-lowerGap-2*arrowHeight,arrowPairSpace+arrowDepth+2*arrowThick,2*arrowHeight);if(this.sSlower==true) ctx.strokeStyle=LoopAnimWidget.sColor;else ctx.strokeStyle="black";p=new Path2D();p.moveTo(cx-arrowOffset,cy-r-circWidth/2-lowerGap);p.lineTo(cx-arrowOffset-arrowDepth,cy-r-circWidth/2-lowerGap-arrowHeight);p.lineTo(cx-arrowOffset,cy-r-circWidth/2-lowerGap-2*arrowHeight);ctx.stroke(p);p=new Path2D();p.moveTo(cx-arrowOffset-arrowPairSpace,cy-r-circWidth/2-lowerGap);p.lineTo(cx-arrowOffset-arrowDepth-arrowPairSpace,cy-r-circWidth/2-lowerGap-arrowHeight);p.lineTo(cx-arrowOffset-arrowPairSpace,cy-r-circWidth/2-lowerGap-2*arrowHeight);ctx.stroke(p);this.pSlower=new Path2D();this.pSlower.rect(cx-arrowOffset-arrowPairSpace-arrowDepth-arrowThick,cy-r-circWidth/2-lowerGap-2*arrowHeight,arrowPairSpace+arrowDepth+2*arrowThick,2*arrowHeight);} ctx.lineWidth=1;if(this.visPauseRun===true){let pauseSpace=3.25;let pauseThick=1.5;let pauseHeight=2*arrowHeight;let runThick=1.5;let runLeftRight=5;let runHeight=2*arrowHeight;if(this.sPauseRun==true) ctx.strokeStyle=LoopAnimWidget.sColor;else ctx.strokeStyle="black";if(this.aRunning===true){ctx.lineWidth=pauseThick;p=new Path2D();p.moveTo(cx+pauseSpace,cy-r-circWidth/2-lowerGap);p.lineTo(cx+pauseSpace,cy-r-circWidth/2-lowerGap-pauseHeight);ctx.stroke(p);p=new Path2D();p.moveTo(cx-pauseSpace,cy-r-circWidth/2-lowerGap);p.lineTo(cx-pauseSpace,cy-r-circWidth/2-lowerGap-pauseHeight);ctx.stroke(p);ctx.lineWidth=1;} else{ctx.lineWidth=runThick;p=new Path2D();p.moveTo(cx-runLeftRight,cy-r-circWidth/2-lowerGap);p.lineTo(cx-runLeftRight,cy-r-circWidth/2-lowerGap-runHeight);p.lineTo(cx+runLeftRight,cy-r-circWidth/2-lowerGap-runHeight/2);p.closePath();ctx.stroke(p);} this.pPauseRun=new Path2D();this.pPauseRun.rect(cx-runLeftRight-runThick,cy-r-circWidth/2-lowerGap-runHeight-runThick,2*runLeftRight+2*runThick,runHeight+2*runThick);} ctx.lineWidth=1;if(this.visSteps===true){let stepSpace=20;let stepThick=2.0;let upperGap=8;let stepHeight=15;let stepArrowHeight=8;let stepArrowWidth=5;ctx.lineWidth=stepThick;if(this.sDownStep==true){ctx.strokeStyle=LoopAnimWidget.sColor;ctx.fillStyle=LoopAnimWidget.sColor;} else{ctx.strokeStyle="black";ctx.fillStyle="black";} p=new Path2D();p.moveTo(cx-stepSpace,cy+r+circWidth/2+upperGap);p.lineTo(cx-stepSpace,cy+r+circWidth/2+upperGap+stepHeight);ctx.stroke(p);p=new Path2D();p.moveTo(cx-stepSpace,cy+r+circWidth/2+upperGap-stepThick);p.lineTo(cx-stepSpace+stepArrowWidth,cy+r+circWidth/2+upperGap+stepArrowHeight-stepThick);p.lineTo(cx-stepSpace-stepArrowWidth,cy+r+circWidth/2+upperGap+stepArrowHeight-stepThick);p.closePath();ctx.fill(p);this.pDownStep=new Path2D();this.pDownStep.rect(cx-stepSpace-stepArrowWidth,cy+r+circWidth/2+upperGap-stepThick,2*stepArrowWidth,stepHeight+stepThick);if(this.sUpStep==true){ctx.strokeStyle=LoopAnimWidget.sColor;ctx.fillStyle=LoopAnimWidget.sColor;} else{ctx.strokeStyle="black";ctx.fillStyle="black";} p=new Path2D();p.moveTo(cx+stepSpace,cy+r+circWidth/2+upperGap);p.lineTo(cx+stepSpace,cy+r+circWidth/2+upperGap+stepHeight);ctx.stroke(p);p=new Path2D();p.moveTo(cx+stepSpace,cy+r+circWidth/2+upperGap+stepHeight+stepThick);p.lineTo(cx+stepSpace+stepArrowWidth,cy+r+circWidth/2+upperGap+stepHeight-stepArrowHeight+stepThick);p.lineTo(cx+stepSpace-stepArrowWidth,cy+r+circWidth/2+upperGap+stepHeight-stepArrowHeight+stepThick);p.closePath();ctx.fill(p);this.pUpStep=new Path2D();this.pUpStep.rect(cx+stepSpace-stepArrowWidth,cy+r+circWidth/2+upperGap,2*stepArrowWidth,stepHeight+stepThick);ctx.lineWidth=1;ctx.strokeStyle="black";ctx.fillStyle="black";stepThick=1.5;let stepSize=6;ctx.lineWidth=stepThick;p=new Path2D();p.moveTo(cx-stepSize,cy+r+circWidth/2+upperGap+2*stepSize);p.lineTo(cx,cy+r+circWidth/2+upperGap+2*stepSize);p.lineTo(cx,cy+r+circWidth/2+upperGap+stepSize);p.lineTo(cx+stepSize,cy+r+circWidth/2+upperGap+stepSize);p.lineTo(cx+stepSize,cy+r+circWidth/2+upperGap);ctx.stroke(p);} ctx.lineWidth=1;ctx.setTransform(saveT);} mouseDown(x,y){if(this.hide===true) return false;x-=this.widgetX;y-=this.widgetY;x/=this.scale;y/=this.scale;WidgetManager.bogusCtx.resetTransform();if(this.pPauseRun!==null){let isin=WidgetManager.bogusCtx.isPointInPath(this.pPauseRun,x,y);if(isin===true){this.sPauseRun=true;WidgetManager.mouseOwner=this;renderFrame(this);return true;}} if(this.pFaster!==null){let isin=WidgetManager.bogusCtx.isPointInPath(this.pFaster,x,y);if(isin===true){this.sFaster=true;WidgetManager.mouseOwner=this;renderFrame(this);return true;}} if(this.pSlower!==null){let isin=WidgetManager.bogusCtx.isPointInPath(this.pSlower,x,y);if(isin===true){this.sSlower=true;WidgetManager.mouseOwner=this;renderFrame(this);return true;}} if(this.pUpStep!==null){let isin=WidgetManager.bogusCtx.isPointInPath(this.pUpStep,x,y);if(isin===true){this.sUpStep=true;WidgetManager.mouseOwner=this;renderFrame(this);return true;}} if(this.pDownStep!==null){let isin=WidgetManager.bogusCtx.isPointInPath(this.pDownStep,x,y);if(isin===true){this.sDownStep=true;WidgetManager.mouseOwner=this;renderFrame(this);return true;}} if(this.pCircle!==null){WidgetManager.bogusCtx.lineWidth=15;let isin=WidgetManager.bogusCtx.isPointInStroke(this.pCircle,x,y);if(isin===true){this.sCircle=true;let alpha=-Math.atan2(y,x);if(alpha<0) alpha+=2*Math.PI;this.curStep=Math.floor(this.steps*alpha/(2*Math.PI));WidgetManager.mouseOwner=this;renderFrame(this);return true;}} return false;} mouseMove(x,y){if(this.hide===true) return;x-=this.widgetX;y-=this.widgetY;x/=this.scale;y/=this.scale;WidgetManager.bogusCtx.resetTransform();if(this.sCircle===true){WidgetManager.bogusCtx.lineWidth=40;let isin=WidgetManager.bogusCtx.isPointInStroke(this.pCircle,x,y);if(isin==false) return;let alpha=-Math.atan2(y,x);if(alpha<0) alpha+=2*Math.PI;this.curStep=Math.floor(this.steps*alpha/(2*Math.PI));renderFrame(this);}} mouseUp(x,y){if(this.hide===true) return;x-=this.widgetX;y-=this.widgetY;x/=this.scale;y/=this.scale;WidgetManager.bogusCtx.resetTransform();this.sCircle=false;if(this.sPauseRun){let isin=WidgetManager.bogusCtx.isPointInPath(this.pPauseRun,x,y);if(isin===true){if(this.aRunning===true) clearInterval(this.animID);else this.animID=setInterval(doAnimation,this.timeStep,this);if(this.aRunning===true) this.aRunning=false;else this.aRunning=true;} this.sPauseRun=false;} if(this.sFaster===true){let isin=WidgetManager.bogusCtx.isPointInPath(this.pFaster,x,y);if(isin===true){this.timeStep/=1.4;if(this.timeStep<1) this.timeStep=1;if(this.aRunning===true) clearInterval(this.animID);this.animID=setInterval(doAnimation,this.timeStep,this);this.aRunning=true;} this.sFaster=false;} if(this.sSlower===true){let isin=WidgetManager.bogusCtx.isPointInPath(this.pSlower,x,y);if(isin===true){this.timeStep*=1.4;if(this.timeStep>1000) this.timeStep=1000;if(this.aRunning===true) clearInterval(this.animID);this.animID=setInterval(doAnimation,this.timeStep,this);this.aRunning=true;} this.sSlower=false;} if(this.sUpStep===true){let isin=WidgetManager.bogusCtx.isPointInPath(this.pUpStep,x,y);if(isin===true){this.stepsPerFrame*=1.25;if(this.stepsPerFrame>this.steps/3) this.stepsPerFrame=this.steps/3;} this.sUpStep=false;} if(this.sDownStep===true){let isin=WidgetManager.bogusCtx.isPointInPath(this.pDownStep,x,y);if(isin===true){this.stepsPerFrame/=1.25;} this.sDownStep=false;} renderFrame(this);}} LoopAnimWidget.Radius=41.5;LoopAnimWidget.TopHeight=24.5;LoopAnimWidget.BottomHeight=21.0;LoopAnimWidget.sColor="blue";class OpenAnimWidget extends AnimationWidget{constructor(){super(...arguments);this.barLength=100;this.timeStep=25;this.decay=1.0001;this.visSteps=true;this.visFastSlow=true;this.visPauseRun=true;this.visBar=true;this.barGrab=true;this.pBar=null;this.pDot=null;this.pFaster=null;this.pSlower=null;this.pPauseRun=null;this.pUpStep=null;this.pDownStep=null;this.aRunning=true;this.sDot=false;this.sFaster=false;this.sSlower=false;this.sPauseRun=false;this.sUpStep=false;this.sDownStep=false;} static register(ctx,x,y,scale,width,visWidget,timeStep,decay,visSteps,visFastSlow,visPauseRun,visBar,barGrab,name){let type="OpenAnimWidget";let caller=getCaller();let w=WidgetManager.knownWidget(caller,type,name);if(w!=null){w.draw(ctx);return w;} w=new OpenAnimWidget(caller,type,x,y,scale,!visWidget,name);w.barLength=width/scale;w.timeStep=timeStep;w.visSteps=visSteps;w.visFastSlow=visFastSlow;w.visPauseRun=visPauseRun;w.visBar=visBar;w.barGrab=barGrab;w.decay=1+1/decay;WidgetManager.register(w);w.animID=setInterval(doAnimation,w.timeStep,w);w.draw(ctx);return w;} advanceFrame(){this.curStep+=this.stepsPerFrame;} draw(ctx){if(this.hide===true) return;if(ctx instanceof CTX) return;let saveT=ctx.getTransform();ctx.translate(this.widgetX,this.widgetY);ctx.scale(this.scale,this.scale);var p=new Path2D();if(this.visBar==true){let indDotRadius=5.0;let barThick=3.0;let indDotThick=2.0;p.moveTo(0,indDotRadius+OpenAnimWidget.ControlsHeight);p.lineTo(this.barLength,indDotRadius+OpenAnimWidget.ControlsHeight);if(this.barGrab===true) this.pBar=new Path2D(p);ctx.lineWidth=barThick;ctx.stroke(p);p=new Path2D();let dx=Math.pow(this.decay,this.curStep);dx=this.barLength*(1-1/dx);p.ellipse(dx,indDotRadius+OpenAnimWidget.ControlsHeight,indDotRadius,indDotRadius,0,0,2*Math.PI);if(this.barGrab===true) this.pDot=new Path2D(p);if(this.sDot==true) ctx.fillStyle=OpenAnimWidget.sColor;else ctx.fillStyle="red";ctx.fill(p);ctx.lineWidth=indDotThick;ctx.strokeStyle="black";ctx.stroke(p);} let pauseRunWidth=40;let stepsWidth=32;let intraGap=8;let cy=OpenAnimWidget.BarHeight-4;let cx=this.barLength/2;if(this.visSteps===true) cx+=intraGap+(pauseRunWidth/2);let arrowHeight=7;if(this.visFastSlow===true){let arrowOffset=12;let arrowDepth=4;let arrowPairSpace=3;let arrowThick=1.25;ctx.lineWidth=arrowThick;if(this.sFaster==true) ctx.strokeStyle=OpenAnimWidget.sColor;else ctx.strokeStyle="black";p=new Path2D();p.moveTo(cx+arrowOffset,cy);p.lineTo(cx+arrowOffset+arrowDepth,cy+arrowHeight);p.lineTo(cx+arrowOffset,cy+2*arrowHeight);ctx.stroke(p);p=new Path2D();p.moveTo(cx+arrowOffset+arrowPairSpace,cy);p.lineTo(cx+arrowOffset+arrowDepth+arrowPairSpace,cy+arrowHeight);p.lineTo(cx+arrowOffset+arrowPairSpace,cy+2*arrowHeight);ctx.stroke(p);this.pFaster=new Path2D();this.pFaster.rect(cx+arrowOffset-arrowThick,cy,arrowPairSpace+arrowDepth+2*arrowThick,2*arrowHeight);if(this.sSlower==true) ctx.strokeStyle=LoopAnimWidget.sColor;else ctx.strokeStyle="black";p=new Path2D();p.moveTo(cx-arrowOffset,cy);p.lineTo(cx-arrowOffset-arrowDepth,cy+arrowHeight);p.lineTo(cx-arrowOffset,cy+2*arrowHeight);ctx.stroke(p);p=new Path2D();p.moveTo(cx-arrowOffset-arrowPairSpace,cy);p.lineTo(cx-arrowOffset-arrowDepth-arrowPairSpace,cy+arrowHeight);p.lineTo(cx-arrowOffset-arrowPairSpace,cy+2*arrowHeight);ctx.stroke(p);this.pSlower=new Path2D();this.pSlower.rect(cx-arrowOffset-arrowPairSpace-arrowDepth-arrowThick,cy,arrowPairSpace+arrowDepth+2*arrowThick,2*arrowHeight);ctx.strokeStyle="black";} ctx.lineWidth=1;if(this.visPauseRun===true){let pauseSpace=3.25;let pauseThick=1.5;let pauseHeight=2*arrowHeight;let runThick=1.5;let runLeftRight=5;let runHeight=2*arrowHeight;if(this.sPauseRun==true) ctx.strokeStyle=LoopAnimWidget.sColor;else ctx.strokeStyle="black";if(this.aRunning===true){ctx.lineWidth=pauseThick;p=new Path2D();p.moveTo(cx+pauseSpace,cy);p.lineTo(cx+pauseSpace,cy+pauseHeight);ctx.stroke(p);p=new Path2D();p.moveTo(cx-pauseSpace,cy);p.lineTo(cx-pauseSpace,cy+pauseHeight);ctx.stroke(p);ctx.lineWidth=1;} else{ctx.lineWidth=runThick;p=new Path2D();p.moveTo(cx-runLeftRight,cy);p.lineTo(cx-runLeftRight,cy+runHeight);p.lineTo(cx+runLeftRight,cy+runHeight/2);p.closePath();ctx.stroke(p);} this.pPauseRun=new Path2D();this.pPauseRun.rect(cx-runLeftRight-runThick,cy-runThick,2*runLeftRight+2*runThick,runHeight+2*runThick);} cy+=12.5;cx=this.barLength/2;if((this.visPauseRun===true)||(this.visFastSlow===true)) cx-=intraGap+stepsWidth/2;ctx.lineWidth=1;if(this.visSteps===true){let stepSpace=12;let stepThick=2.0;let stepHeight=12.5;let stepArrowHeight=5.0;let stepArrowWidth=4.0;ctx.lineWidth=stepThick;if(this.sDownStep===true){ctx.strokeStyle=OpenAnimWidget.sColor;ctx.fillStyle=OpenAnimWidget.sColor;} else{ctx.strokeStyle="black";ctx.fillStyle="black";} p=new Path2D();p.moveTo(cx-stepSpace,cy);p.lineTo(cx-stepSpace,cy-stepHeight);ctx.stroke(p);p=new Path2D();p.moveTo(cx-stepSpace,cy+stepThick);p.lineTo(cx-stepSpace+stepArrowWidth,cy-stepArrowHeight+stepThick);p.lineTo(cx-stepSpace-stepArrowWidth,cy-stepArrowHeight+stepThick);p.closePath();ctx.fill(p);this.pDownStep=new Path2D();this.pDownStep.rect(cx-stepSpace-stepArrowWidth,cy-stepHeight,2*stepArrowWidth,stepHeight+stepThick);if(this.sUpStep===true){ctx.strokeStyle=OpenAnimWidget.sColor;ctx.fillStyle=OpenAnimWidget.sColor;} else{ctx.strokeStyle="black";ctx.fillStyle="black";} p=new Path2D();p.moveTo(cx+stepSpace,cy+stepThick);p.lineTo(cx+stepSpace,cy+stepThick-stepHeight);ctx.stroke(p);p=new Path2D();p.moveTo(cx+stepSpace,cy-stepHeight);p.lineTo(cx+stepSpace+stepArrowWidth,cy-stepHeight+stepArrowHeight);p.lineTo(cx+stepSpace-stepArrowWidth,cy-stepHeight+stepArrowHeight);p.closePath();ctx.fill(p);this.pUpStep=new Path2D();this.pUpStep.rect(cx+stepSpace-stepArrowWidth,cy-stepHeight,2*stepArrowWidth,stepHeight+stepThick);ctx.lineWidth=1;ctx.strokeStyle="black";ctx.fillStyle="black";stepThick=1.5;let stepSize=5;ctx.lineWidth=stepThick;p=new Path2D();p.moveTo(cx-stepSize,cy-2*stepSize);p.lineTo(cx,cy-2*stepSize);p.lineTo(cx,cy-stepSize);p.lineTo(cx+stepSize,cy-stepSize);p.lineTo(cx+stepSize,cy);ctx.stroke(p);ctx.strokeStyle="black";} ctx.lineWidth=1;ctx.setTransform(saveT);} mouseDown(x,y){if(this.hide===true) return false;x-=this.widgetX;y-=this.widgetY;x/=this.scale;y/=this.scale;WidgetManager.bogusCtx.resetTransform();if(this.pFaster!==null){let isin=WidgetManager.bogusCtx.isPointInPath(this.pFaster,x,y);if(isin===true){this.sFaster=true;WidgetManager.mouseOwner=this;renderFrame(this);return true;}} if(this.pSlower!==null){let isin=WidgetManager.bogusCtx.isPointInPath(this.pSlower,x,y);if(isin===true){this.sSlower=true;WidgetManager.mouseOwner=this;renderFrame(this);return true;}} if(this.pPauseRun!==null){let isin=WidgetManager.bogusCtx.isPointInPath(this.pPauseRun,x,y);if(isin===true){this.sPauseRun=true;WidgetManager.mouseOwner=this;renderFrame(this);return true;}} if(this.pUpStep!==null){let isin=WidgetManager.bogusCtx.isPointInPath(this.pUpStep,x,y);if(isin===true){this.sUpStep=true;WidgetManager.mouseOwner=this;renderFrame(this);return true;}} if(this.pDownStep!==null){let isin=WidgetManager.bogusCtx.isPointInPath(this.pDownStep,x,y);if(isin===true){this.sDownStep=true;WidgetManager.mouseOwner=this;renderFrame(this);return true;}} if(this.pDot!==null){WidgetManager.bogusCtx.lineWidth=2;let isin=WidgetManager.bogusCtx.isPointInStroke(this.pDot,x,y);if(isin===false) isin=WidgetManager.bogusCtx.isPointInPath(this.pDot,x,y);if(isin===true){this.sDot=true;let ratio=this.barLength/(this.barLength-x);let s=Math.log(ratio)/Math.log(this.decay);if(s<0) s=0;this.curStep=s;WidgetManager.mouseOwner=this;renderFrame(this);return true;}} return false;} mouseMove(x,y){if(this.hide===true) return;x-=this.widgetX;y-=this.widgetY;x/=this.scale;y/=this.scale;WidgetManager.bogusCtx.resetTransform();if(this.sDot===true){WidgetManager.bogusCtx.lineWidth=20;let isin=WidgetManager.bogusCtx.isPointInStroke(this.pBar,x,y);if(isin==false) return;let ratio=this.barLength/(this.barLength-x);let s=Math.log(ratio)/Math.log(this.decay);if(s<0) s=0;this.curStep=s;renderFrame(this);}} mouseUp(x,y){if(this.hide===true) return;x-=this.widgetX;y-=this.widgetY;x/=this.scale;y/=this.scale;WidgetManager.bogusCtx.resetTransform();this.sDot=false;if(this.sFaster===true){let isin=WidgetManager.bogusCtx.isPointInPath(this.pFaster,x,y);if(isin===true){this.timeStep/=1.4;if(this.timeStep<1) this.timeStep=1;if(this.aRunning===true) clearInterval(this.animID);this.animID=setInterval(doAnimation,this.timeStep,this);this.aRunning=true;} this.sFaster=false;} if(this.sSlower===true){let isin=WidgetManager.bogusCtx.isPointInPath(this.pSlower,x,y);if(isin===true){this.timeStep*=1.4;if(this.timeStep>1000) this.timeStep=1000;if(this.aRunning===true) clearInterval(this.animID);this.animID=setInterval(doAnimation,this.timeStep,this);this.aRunning=true;} this.sSlower=false;} if(this.sPauseRun){let isin=WidgetManager.bogusCtx.isPointInPath(this.pPauseRun,x,y);if(isin===true){if(this.aRunning===true) clearInterval(this.animID);else this.animID=setInterval(doAnimation,this.timeStep,this);if(this.aRunning===true) this.aRunning=false;else this.aRunning=true;} this.sPauseRun=false;} if(this.sUpStep===true){let isin=WidgetManager.bogusCtx.isPointInPath(this.pUpStep,x,y);if(isin===true){this.stepsPerFrame*=1.25;} this.sUpStep=false;} if(this.sDownStep===true){let isin=WidgetManager.bogusCtx.isPointInPath(this.pDownStep,x,y);if(isin===true) this.stepsPerFrame/=1.25;this.sDownStep=false;} renderFrame(this);}} OpenAnimWidget.BarHeight=6.0;OpenAnimWidget.ControlsHeight=20.0;OpenAnimWidget.TotalHeight=32.0;OpenAnimWidget.sColor="blue";class DraggableDotWidget extends Widget{constructor(){super(...arguments);this.pDot=null;this.selected=false;this.dotRadius=3.0;} static register(ctx,x,y,name){let type="DraggableDotWidget";let caller=getCaller();let w=WidgetManager.knownWidget(caller,type,name);if(w!=null){return w;} w=new DraggableDotWidget(caller,type,x,y,1.0,false,name);WidgetManager.register(w);return w;} draw(ctx){if(this.hide===true) return;let saveT=ctx.getTransform();ctx.translate(this.widgetX,this.widgetY);ctx.scale(this.scale,this.scale);let p=new FPath();let r=this.dotRadius;p.ellipse(0,0,r,r,0,0,2*Math.PI,true);this.pDot=p;if(this.selected===true) ctx.fillStyle=DraggableDotWidget.sColor;else ctx.fillStyle="red";ctx.fill(p);ctx.setTransform(saveT);} mouseDown(x,y){if(this.hide===true) return false;x-=this.widgetX;y-=this.widgetY;x/=this.scale;y/=this.scale;WidgetManager.bogusCtx.resetTransform();if(this.pDot!==null){let isin=WidgetManager.bogusCtx.isPointInPath(this.pDot,x,y);if(isin===true){this.selected=true;WidgetManager.mouseOwner=this;renderFrame(this);return true;}} return false;} mouseMove(x,y){if(this.hide===true) return;let wh=getFigureRect(this);wh.w-=2*this.dotRadius;wh.ha-=2*this.dotRadius;wh.hb-=2*this.dotRadius;if(x<=this.dotRadius) return;if(x>=wh.w) return;if(y<=-wh.hb) return;if(y>=wh.ha) return;if(this.selected===true){this.widgetX=x;this.widgetY=y;renderFrame(this);}} mouseUp(x,y){if(this.hide===true) return;if(this.selected===true){this.selected=false;let wh=getFigureRect(this);wh.w-=2*this.dotRadius;wh.ha-=2*this.dotRadius;wh.hb-=2*this.dotRadius;if((x>this.dotRadius)&&(x-wh.hb)&&(ytotWidth){let canvasCenter=canvas.width/2;let docCenter=FullPanel.getFullWidth()/2;canvasCenter=canvasCenter/PDFDocument.getZoom();hpos=hpos+(canvasCenter-docCenter);} else{hpos=hpos-window.scrollX;} hpos+=fpc.margin;this.theWidget.style.top=vpos+"px";this.theWidget.style.left=hpos+"px";}} class ButtonWidget extends Widget{constructor(){super(...arguments);this.theWidget=null;this.clickState=false;this.resetState=false;} static register(ctx,x,y,text,name){let type="ButtonWidget";let caller=getCaller();let w=WidgetManager.knownWidget(caller,type,name);if(w!=null){w.draw(ctx);return w;} w=new ButtonWidget(caller,type,x,y,1.0,false,name);WidgetManager.register(w);w.theWidget=document.createElement("button");w.theWidget.setAttribute("type","button");w.theWidget.style.fontSize="10px";w.theWidget.textContent=text;w.theWidget.style.position="absolute";w.theWidget.style.display="block";w.theWidget.style.left=400+"px";w.theWidget.style.top=900+"px";w.theWidget.style.height=18+"px";w.theWidget.style.zIndex="99";document.body.appendChild(w.theWidget);w.theWidget.addEventListener('click',()=>{if(w.clickState===false) w.clickState=true;else{w.clickState=false;w.resetState=true;} let myFunc=getAugmentedFunction(w.owner);let fpc=myFunc.figurePanelClass;fpc.render();},false);w.draw(ctx);return w;} doClick(){if(this.clickState===false) this.clickState=true;else this.clickState=false;} draw(ctx){let myFunc=getAugmentedFunction(this.owner);let fpc=myFunc.figurePanelClass;let vpos=fpc.totalV+fpc.h-this.widgetY;let hpos=this.widgetX;let canvas=document.getElementById("pdf_renderer");let visWidth=document.documentElement.clientWidth;let totWidth=FullPanel.getFullWidth();if(visWidth>totWidth){let canvasCenter=canvas.width/2;let docCenter=FullPanel.getFullWidth()/2;canvasCenter=canvasCenter/PDFDocument.getZoom();hpos=hpos+(canvasCenter-docCenter);} else{hpos=hpos-window.scrollX;} hpos+=fpc.margin;let w=this.theWidget;w.style.top=(vpos-parseInt(w.style.height,10))+"px";w.style.left=hpos+"px";}}"use strict";class Point2D{constructor(x,y){this._x=x;this._y=y;} toString(){return"( "+this._x.toFixed(2)+","+this._y.toFixed(2)+")";} get x(){return this._x;} get y(){return this._y;} copy(){return new Point2D(this._x,this._y);} negate(){return new Point2D(-this._x,-this.y);} negateSelf(){this._x=-this.x;this._y=-this.y;} minus(p){return new Point2D(this._x-p.x,this._y-p.y);} minusSelf(p){this._x-=p._x;this._y-=p._y;} translate2(u,v){return new Point2D(u+this._x,v+this._y);} translate(p){return new Point2D(p.x+this._x,p.y+this._y);} translateSelf2(u,v){this._x+=u;this._y+=v;} translateSelf(p){this._x+=p.x;this._y+=p.y;} scale(s){return new Point2D(s*this._x,s*this._y);} scaleSelf(s){this._x*=s;this._y*=s;} rotate(theta){let c=Math.cos(theta);let s=Math.sin(theta);return new Point2D(c*this._x-s*this._y,s*this._x+c*this._y);} rotateSelf(theta){let c=Math.cos(theta);let s=Math.sin(theta);let u=c*this._x-s*this._y;let v=s*this._x+c*this._y;this._x=u;this._y=v;} rotateAbout(c,theta){let answer=new Point2D(this.x-c.x,this.y-c.y);answer=answer.rotate(theta);answer._x+=c.x;answer._y+=c.y;return answer;} dot(a){return a.x*this._x+a.y*this._y;} length(){return Math.sqrt(this._x**2+this._y**2);} static dot(a,b){return a.dot(b);} angleBetween(a){let cos=this.dot(a)/(this.length()*a.length());return Math.acos(cos);} cliffordBetween(a){return Math.atan2(this.x*a.y-a.x*this.y,this.x*a.x+this.y*a.y);}} class PathSegment{constructor(kind,d){this.type=PathSegment.UNKNOWN;this.type=kind;this.s=d;} static getClose(){let d={};return new PathSegment(PathSegment.CLOSE,d);} static getMoveTo(x,y){let d={x:x,y:y};return new PathSegment(PathSegment.MOVE_TO,d);} static getLineTo(x,y){let d={x:x,y:y};return new PathSegment(PathSegment.LINE_TO,d);} static getBezier(cx1,cy1,cx2,cy2,x,y){let d={cx1:cx1,cy1:cy1,cx2:cx2,cy2:cy2,x:x,y:y};return new PathSegment(PathSegment.BEZIER,d);} static getQuadratic(cx,cy,x,y){let d={cx:cx,cy:cy,x:x,y:y};return new PathSegment(PathSegment.QUADRATIC,d);} static getArc(x,y,r,a0,a1,ccw){let d={x:x,y:y,r:r,a0:a0,a1:a1,ccw:ccw};return new PathSegment(PathSegment.ARC,d);} static getArcTo(x1,y1,x2,y2,r){let d={x1:x1,y1:y1,x2:x2,y2:y2,r:r};return new PathSegment(PathSegment.ARC_TO,d);} static getEllipse(x,y,rx,ry,rot,a0,a1,ccw){let d={x:x,y:y,rx:rx,ry:ry,rot:rot,a0:a0,a1:a1,ccw:ccw};return new PathSegment(PathSegment.ELLIPSE,d);} static getRect(x,y,w,h){let d={x:x,y:y,w:w,h:h};return new PathSegment(PathSegment.RECT,d);}} PathSegment.MOVE_TO=1;PathSegment.LINE_TO=2;PathSegment.BEZIER=3;PathSegment.QUADRATIC=4;PathSegment.ARC=5;PathSegment.ARC_TO=6;PathSegment.ELLIPSE=7;PathSegment.RECT=8;PathSegment.CLOSE=9;PathSegment.UNKNOWN=-1;class FPath extends Path2D{constructor(){super();this.segs=[];} addPath(p){for(let i=0;i=2*Math.PI) a0-=2*Math.PI;while(a1>=2*Math.PI) a1-=2*Math.PI;if(ccw===true){let temp=a1;a1=a0;a0=temp;} let arcs=FPath.arcToBezierNEW(r,a0,a1);arcs=arcs.translate(new Point2D(x,y));this.addPath(arcs);} ellipse(x,y,rx,ry,rot,a0,a1,ccw){if(ccw===undefined) ccw=false;super.ellipse(x,y,rx,ry,rot,a0,a1,ccw);this.segs.push(PathSegment.getEllipse(x,y,rx,ry,rot,a0,a1,ccw));} rect(x,y,w,h){super.rect(x,y,w,h);this.segs.push(PathSegment.getRect(x,y,w,h));} static circArcToBezier(r,a0,a1){let answer=FPath.arcToBezierNEW(r,a0,a1);return answer;} static parametricToBezier(f,t0,t1,n){let p=new FPath();let p1=f(t0);p.moveTo(p1.x,p1.y);for(let i=0;ie){let fplus=f(x0+e);let fminus=f(x0-e);let fprime=(fplus-fminus)/(2*e);let dx=(y-y0)/fprime;let x1=x0+dx;if(x1>b) x1=(x1-x0)/2;if(x1100) return x0;} return x0;}}