Last active
August 23, 2016 19:51
-
-
Save dekrain/4b71a5cd7310fc050e61031bb0aefaf6 to your computer and use it in GitHub Desktop.
Snap! Pen controller
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Control bar for PenMorph by (C) ~DK | |
// Based on morphic.js and widgets.js (PushButtonMorph) | |
/*global Morph PenMorph PushButtonMorph PenMorph BoxMorph WorldMorph Point Color*/ | |
WorldMorph.prototype.customMorphs = function() { // !!! Comment this function in blocks.js | |
return [ | |
new PenControllerMorph(), | |
]; | |
}; | |
var PushButtonMorph = PushButtonMorph || (function(){var SymbolMorph=SymbolMorph||(function(){});var PushButtonMorph;PushButtonMorph.prototype=new TriggerMorph;PushButtonMorph.prototype.constructor=PushButtonMorph;PushButtonMorph.uber=TriggerMorph.prototype;PushButtonMorph.prototype.fontSize=10;PushButtonMorph.prototype.fontStyle="sans-serif";PushButtonMorph.prototype.labelColor=new Color(0,0,0);PushButtonMorph.prototype.labelShadowColor=new Color(255,255,255);PushButtonMorph.prototype.labelShadowOffset=new Point(1,1);PushButtonMorph.prototype.color=new Color(220,220,220);PushButtonMorph.prototype.pressColor=new Color(115,180,240);PushButtonMorph.prototype.highlightColor=PushButtonMorph.prototype.pressColor.lighter(50);PushButtonMorph.prototype.outlineColor=new Color(30,30,30);PushButtonMorph.prototype.outlineGradient=false;PushButtonMorph.prototype.contrast=60;PushButtonMorph.prototype.edge=2;PushButtonMorph.prototype.corner=5;PushButtonMorph.prototype.outline=1.00001;PushButtonMorph.prototype.padding=3;function PushButtonMorph(target,action,labelString,environment,hint,template){this.init(target,action,labelString,environment,hint,template)}PushButtonMorph.prototype.init=function(target,action,labelString,environment,hint,template){this.is3D=false;this.target=target||null;this.action=action||null;this.environment=environment||null;this.labelString=labelString||null;this.label=null;this.labelMinExtent=new Point(0,0);this.hint=hint||null;this.template=template||null;TriggerMorph.uber.init.call(this);this.color=PushButtonMorph.prototype.color;this.drawNew();this.fixLayout()};PushButtonMorph.prototype.fixLayout=function(){if(this.label!==null){var padding=this.padding*2+this.outline*2+this.edge*2;this.setExtent(new Point(Math.max(this.label.width(),this.labelMinExtent.x)+padding,Math.max(this.label instanceof StringMorph?this.label.rawHeight():this.label.height(),this.labelMinExtent.y)+padding));this.label.setCenter(this.center())}};PushButtonMorph.prototype.mouseDownLeft=function(){PushButtonMorph.uber.mouseDownLeft.call(this);if(this.label){this.label.setCenter(this.center().add(1))}};PushButtonMorph.prototype.mouseClickLeft=function(){PushButtonMorph.uber.mouseClickLeft.call(this);if(this.label){this.label.setCenter(this.center())}};PushButtonMorph.prototype.mouseLeave=function(){PushButtonMorph.uber.mouseLeave.call(this);if(this.label){this.label.setCenter(this.center())}};PushButtonMorph.prototype.outlinePath=BoxMorph.prototype.outlinePath;PushButtonMorph.prototype.drawOutline=function(context){var outlineStyle,isFlat=MorphicPreferences.isFlat&&!this.is3D;if(!this.outline||isFlat){return null}if(this.outlineGradient){outlineStyle=context.createLinearGradient(0,0,0,this.height());outlineStyle.addColorStop(1,"white");outlineStyle.addColorStop(0,this.outlineColor.darker().toString())}else{outlineStyle=this.outlineColor.toString()}context.fillStyle=outlineStyle;context.beginPath();this.outlinePath(context,isFlat?0:this.corner,0);context.closePath();context.fill()};PushButtonMorph.prototype.drawBackground=function(context,color){var isFlat=MorphicPreferences.isFlat&&!this.is3D;context.fillStyle=color.toString();context.beginPath();this.outlinePath(context,isFlat?0:Math.max(this.corner-this.outline,0),this.outline);context.closePath();context.fill();context.lineWidth=this.outline};PushButtonMorph.prototype.drawEdges=function(context,color,topColor,bottomColor){if(MorphicPreferences.isFlat&&!this.is3D){return}var minInset=Math.max(this.corner,this.outline+this.edge),w=this.width(),h=this.height(),gradient;gradient=context.createLinearGradient(0,this.outline,0,this.outline+this.edge);gradient.addColorStop(0,topColor.toString());gradient.addColorStop(1,color.toString());context.strokeStyle=gradient;context.lineCap="round";context.lineWidth=this.edge;context.beginPath();context.moveTo(minInset,this.outline+this.edge/2);context.lineTo(w-minInset,this.outline+this.edge/2);context.stroke();gradient=context.createRadialGradient(this.corner,this.corner,Math.max(this.corner-this.outline-this.edge,0),this.corner,this.corner,Math.max(this.corner-this.outline,0));gradient.addColorStop(1,topColor.toString());gradient.addColorStop(0,color.toString());context.strokeStyle=gradient;context.lineCap="round";context.lineWidth=this.edge;context.beginPath();context.arc(this.corner,this.corner,Math.max(this.corner-this.outline-this.edge/2,0),radians(180),radians(270),false);context.stroke();gradient=context.createLinearGradient(this.outline,0,this.outline+this.edge,0);gradient.addColorStop(0,topColor.toString());gradient.addColorStop(1,color.toString());context.strokeStyle=gradient;context.lineCap="round";context.lineWidth=this.edge;context.beginPath();context.moveTo(this.outline+this.edge/2,minInset);context.lineTo(this.outline+this.edge/2,h-minInset);context.stroke();gradient=context.createLinearGradient(0,h-this.outline,0,h-this.outline-this.edge);gradient.addColorStop(0,bottomColor.toString());gradient.addColorStop(1,color.toString());context.strokeStyle=gradient;context.lineCap="round";context.lineWidth=this.edge;context.beginPath();context.moveTo(minInset,h-this.outline-this.edge/2);context.lineTo(w-minInset,h-this.outline-this.edge/2);context.stroke();gradient=context.createRadialGradient(w-this.corner,h-this.corner,Math.max(this.corner-this.outline-this.edge,0),w-this.corner,h-this.corner,Math.max(this.corner-this.outline,0));gradient.addColorStop(1,bottomColor.toString());gradient.addColorStop(0,color.toString());context.strokeStyle=gradient;context.lineCap="round";context.lineWidth=this.edge;context.beginPath();context.arc(w-this.corner,h-this.corner,Math.max(this.corner-this.outline-this.edge/2,0),radians(0),radians(90),false);context.stroke();gradient=context.createLinearGradient(w-this.outline,0,w-this.outline-this.edge,0);gradient.addColorStop(0,bottomColor.toString());gradient.addColorStop(1,color.toString());context.strokeStyle=gradient;context.lineCap="round";context.lineWidth=this.edge;context.beginPath();context.moveTo(w-this.outline-this.edge/2,minInset);context.lineTo(w-this.outline-this.edge/2,h-minInset);context.stroke()};PushButtonMorph.prototype.createBackgrounds=function(){var context,ext=this.extent();if(this.template){this.image=this.template.image;this.normalImage=this.template.normalImage;this.highlightImage=this.template.highlightImage;this.pressImage=this.template.pressImage;return null}this.normalImage=newCanvas(ext);context=this.normalImage.getContext("2d");this.drawOutline(context);this.drawBackground(context,this.color);this.drawEdges(context,this.color,this.color.lighter(this.contrast),this.color.darker(this.contrast));this.highlightImage=newCanvas(ext);context=this.highlightImage.getContext("2d");this.drawOutline(context);this.drawBackground(context,this.highlightColor);this.drawEdges(context,this.highlightColor,this.highlightColor.lighter(this.contrast),this.highlightColor.darker(this.contrast));this.pressImage=newCanvas(ext);context=this.pressImage.getContext("2d");this.drawOutline(context);this.drawBackground(context,this.pressColor);this.drawEdges(context,this.pressColor,this.pressColor.darker(this.contrast),this.pressColor.lighter(this.contrast));this.image=this.normalImage};PushButtonMorph.prototype.createLabel=function(){var shading=!MorphicPreferences.isFlat||this.is3D;if(this.label!==null){this.label.destroy()}if(this.labelString instanceof SymbolMorph){this.label=this.labelString.fullCopy();if(shading){this.label.shadowOffset=this.labelShadowOffset;this.label.shadowColor=this.labelShadowColor}this.label.color=this.labelColor;this.label.drawNew()}else{this.label=new StringMorph(localize(this.labelString),this.fontSize,this.fontStyle,true,false,false,shading?this.labelShadowOffset:null,this.labelShadowColor,this.labelColor)}this.add(this.label)};return PushButtonMorph;}()); | |
var PenControllerMorph; | |
// PenControllerMorph inherits from Morph | |
PenControllerMorph.prototype = new Morph(); | |
PenControllerMorph.prototype.constructor = PenControllerMorph; | |
PenControllerMorph.uber = Morph.prototype; | |
// PenControllerMorph instance creation | |
function PenControllerMorph(aPen) { | |
this.init(aPen); | |
}; | |
PenControllerMorph.prototype.init = function(aPen) { | |
PenControllerMorph.uber.init.call(this); | |
this.target = (aPen&&aPen instanceof PenMorph&&aPen) || new PenMorph(); | |
this.setExtent(new Point(250,115), true); // No re-draw | |
this.penWindow = new Morph(); | |
this.penWindow.setPosition(this.position().add(new Point(25,10))); | |
this.penWindow.setColor(new Color(0,0,0xCC)); | |
this.penWindow.setExtent(new Point(100,80)); | |
this.penWindow.drawNew(); | |
this.add(this.penWindow); | |
this.buttons = new BoxMorph(); | |
this.buttons.setPosition(new Point( this.left() + 5, this.bottom() - 10 )); | |
this.buttons.setExtent(new Point(this.width()-10, 5)); | |
this.buttons.setColor(this.color.lighter()); | |
this.add(this.buttons); | |
this.fields = []; | |
if(!(this.target === aPen)) { // Merge new pen | |
this.penWindow.add(this.target); | |
this.target.setPosition(this.penWindow.position()); | |
this.target.drawNew(); | |
this.target.isDraggable = false; | |
this.penWindow.add( | |
(function(){ | |
var button = new PushButtonMorph(this, function(){this.target.setPosition(this.bottomLeft().add(new Point(0,15)));this.parent.add(this.target);this.target.isDraggable = true;this.penWindow.button.destroy();delete this.penWindow.button;}, 'flush'); | |
this.penWindow.button = button; | |
button.setPosition(this.penWindow.bottomRight().subtract(button.extent())); | |
return button; | |
}).call(this) | |
); | |
}; | |
this.buildControls(); | |
this.buildFields(); | |
this.fixButtonsPosition(); | |
this.drawNew(); | |
}; | |
PenControllerMorph.prototype.buildControls = function() { | |
var myself = this; | |
function n(i){return parseFloat(myself.fields[i].string())||0;} | |
this.addButton('forward', function(){this.target.forward(n(0));}); | |
this.addButton('back',function(){this.target.forward(-(n(0)));}); | |
this.addButton('turn',function(){this.target.turn(n(0))}); | |
this.addButton('turnLeft',function(){this.target.turn(-(n(0)))}); | |
this.addButton('color',function(){this.pickColor('Set Pen color:',this.target.setColor,this.target,this.target.color)}); | |
this.addButton('clear',function(){this.target.clear();}); | |
this.addButton('down',function(){this.target.down();}); | |
this.addButton('up',function(){this.target.up();}); | |
this.addMenu('','shapes',['square spiral'],function(idx){switch(idx){ | |
case 0: (function(){var pen = this.target, down=pen.isDown; if(!down)pen.down(); for(var i=0;i<200;++i){pen.forward(i);pen.turn(92);}; if(!down)pen.up();}).call(this); break; | |
}}); | |
this.addMenu('','other',['tree (2,1,3 slot)','sierpinski (1,2 slot)'],function(idx){switch(idx){ | |
case 0: this.target.tree(n(1),n(0),n(2)); break; | |
case 1: this.target.sierpinski(n(0),n(1)); break; | |
}}); | |
}; | |
PenControllerMorph.prototype.buildFields = function() { | |
function num(start){var n = new StringFieldMorph(start.toString(),15,null,null,null,null,true); n.setWidth(30); return n;} | |
var n1 = num(15), | |
n2 = num(0), | |
n3 = num(0); | |
this.fields.push(n1); | |
this.fields.push(n2); | |
this.fields.push(n3); | |
this.add(n1); | |
this.add(n2); | |
this.add(n3); | |
var x = this.right() - 60, | |
y = this.top() + 15; | |
n1.setPosition(new Point(x,y)); | |
y+=15; | |
n2.setPosition(new Point(x,y)); | |
y+=15; | |
n3.setPosition(new Point(x,y)); | |
y+=15; | |
}; | |
PenControllerMorph.prototype.addButton = function( | |
label, | |
action | |
) { | |
var button = new PushButtonMorph(this, action || 'nop', label); | |
button.fontSize = 12; | |
button.drawNew(); | |
button.fixLayout(); | |
this.buttons.add(button); | |
return button; | |
}; | |
PenControllerMorph.prototype.addMenu = function( | |
label, // Optional | |
b_label, // Label for button | |
labels, | |
action // function(choice) { ... } choice is 0..N | |
) { | |
var menu = new MenuMorph(this, label||null); | |
labels.forEach(function(l,i){ | |
menu.addItem(l,function(){ action.call(this,i); }); | |
}); | |
this.addButton(b_label,function(){ if(labels.length>0) menu.popUpAtHand(this.world()); }); | |
} | |
PenControllerMorph.prototype.fixButtonsPosition = function() { | |
var buttons = this.buttons.children, | |
myself = this, | |
offset = 5, | |
col = 0; | |
buttons.forEach(function(button){if((myself.buttons.width()-(offset+5))<=button.width()+5) ++col,offset=5; button.setPosition(myself.buttons.position().add(new Point(offset, 5+(col*25)))); offset+=button.width();}); | |
++col; | |
this.setHeight(115+(col*25)); | |
this.buttons.setHeight(10+(col*25)); | |
}; | |
PenControllerMorph.prototype.developersMenu = function() { | |
var menu = PenControllerMorph.uber.developersMenu.call(this); | |
menu.addLine(); | |
menu.addItem('set target','setTarget','chose other pen to control'); | |
return menu; | |
}; | |
PenControllerMorph.prototype.setTarget = function() { | |
var choices = this.overlappedMorphs().filter(function(each){return each instanceof PenMorph}), | |
menu = new MenuMorph(this, 'choose target:'), | |
myself = this; | |
choices.forEach(function (each) { | |
menu.addItem(each.toString().slice(0, 50), function () { | |
myself.target = each; | |
}); | |
}); | |
if (choices.length === 1) { | |
this.target = choices[0]; | |
} else if (choices.length > 0) { | |
menu.popUpAtHand(this.world()); | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment