summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjmoenig <jens@moenig.org>2013-03-18 12:32:24 +0100
committerjmoenig <jens@moenig.org>2013-03-18 12:32:24 +0100
commit78ab4de381c5c0d22475f830beeb993199355c22 (patch)
treeac916c2da9758db8d2fdc8a489d3a2bbe3bd52f6
parent0b510366d230399a38f18a8db92dd396a0dad42e (diff)
downloadsnap-78ab4de381c5c0d22475f830beeb993199355c22.tar.gz
snap-78ab4de381c5c0d22475f830beeb993199355c22.zip
Scalable blocks and scripts
Shift-clicking on the settings menu lets you specify a fraction, by which blocks and scripts are scaled, allowing you to e.g. export poster-sized hi-res script pics, or to present Snap! live on hi-res screens and projectors
-rw-r--r--blocks.js86
-rw-r--r--byob.js18
-rw-r--r--gui.js56
-rwxr-xr-xhistory.txt7
-rw-r--r--widgets.js7
5 files changed, 123 insertions, 51 deletions
diff --git a/blocks.js b/blocks.js
index 223e9b6..25e360a 100644
--- a/blocks.js
+++ b/blocks.js
@@ -153,7 +153,7 @@ DialogBoxMorph, BlockInputFragmentMorph, PrototypeHatBlockMorph*/
// Global stuff ////////////////////////////////////////////////////////
-modules.blocks = '2013-February-26';
+modules.blocks = '2013-March-18';
var SyntaxElementMorph;
var BlockMorph;
@@ -296,37 +296,46 @@ SyntaxElementMorph.uber = Morph.prototype;
rfColor - <Color> for reified outlines and slot backgrounds
*/
-SyntaxElementMorph.prototype.corner = 3;
-SyntaxElementMorph.prototype.rounding = 9;
-SyntaxElementMorph.prototype.edge = 1.000001; // shadow bug in Chrome
-SyntaxElementMorph.prototype.inset = 6;
-SyntaxElementMorph.prototype.hatHeight = 12;
-SyntaxElementMorph.prototype.hatWidth = 70;
-SyntaxElementMorph.prototype.rfBorder = 3;
-SyntaxElementMorph.prototype.minWidth = 0;
-SyntaxElementMorph.prototype.dent = 8;
-SyntaxElementMorph.prototype.bottomPadding = 3;
-SyntaxElementMorph.prototype.cSlotPadding = 4;
-SyntaxElementMorph.prototype.typeInPadding = 1;
-SyntaxElementMorph.prototype.labelPadding = 4;
-SyntaxElementMorph.prototype.labelFontName = 'Verdana';
-SyntaxElementMorph.prototype.labelFontStyle = 'sans-serif';
-SyntaxElementMorph.prototype.fontSize = 10;
-SyntaxElementMorph.prototype.embossing = new Point(-1, -1);
-SyntaxElementMorph.prototype.labelWidth = 450;
-SyntaxElementMorph.prototype.labelWordWrap = true;
-SyntaxElementMorph.prototype.dynamicInputLabels = true;
-SyntaxElementMorph.prototype.feedbackColor = new Color(255, 255, 255);
-SyntaxElementMorph.prototype.feedbackMinHeight = 5;
-SyntaxElementMorph.prototype.minSnapDistance = 20;
-SyntaxElementMorph.prototype.reporterDropFeedbackPadding = 10;
-SyntaxElementMorph.prototype.contrast = 65;
-SyntaxElementMorph.prototype.labelContrast = 25;
-SyntaxElementMorph.prototype.activeHighlight = new Color(153, 255, 213);
-SyntaxElementMorph.prototype.errorHighlight = new Color(173, 15, 0);
-SyntaxElementMorph.prototype.activeBlur = 20;
-SyntaxElementMorph.prototype.activeBorder = 4;
-SyntaxElementMorph.prototype.rfColor = new Color(120, 120, 120);
+SyntaxElementMorph.prototype.setScale = function (num) {
+ var scale = Math.max(num, 1);
+ SyntaxElementMorph.prototype.scale = scale;
+ SyntaxElementMorph.prototype.corner = 3 * scale;
+ SyntaxElementMorph.prototype.rounding = 9 * scale;
+ SyntaxElementMorph.prototype.edge = 1.000001 * scale;
+ SyntaxElementMorph.prototype.inset = 6 * scale;
+ SyntaxElementMorph.prototype.hatHeight = 12 * scale;
+ SyntaxElementMorph.prototype.hatWidth = 70 * scale;
+ SyntaxElementMorph.prototype.rfBorder = 3 * scale;
+ SyntaxElementMorph.prototype.minWidth = 0;
+ SyntaxElementMorph.prototype.dent = 8 * scale;
+ SyntaxElementMorph.prototype.bottomPadding = 3 * scale;
+ SyntaxElementMorph.prototype.cSlotPadding = 4 * scale;
+ SyntaxElementMorph.prototype.typeInPadding = scale;
+ SyntaxElementMorph.prototype.labelPadding = 4 * scale;
+ SyntaxElementMorph.prototype.labelFontName = 'Verdana';
+ SyntaxElementMorph.prototype.labelFontStyle = 'sans-serif';
+ SyntaxElementMorph.prototype.fontSize = 10 * scale;
+ SyntaxElementMorph.prototype.embossing = new Point(
+ -1 * Math.max(scale / 2, 1),
+ -1 * Math.max(scale / 2, 1)
+ );
+ SyntaxElementMorph.prototype.labelWidth = 450 * scale;
+ SyntaxElementMorph.prototype.labelWordWrap = true;
+ SyntaxElementMorph.prototype.dynamicInputLabels = true;
+ SyntaxElementMorph.prototype.feedbackColor = new Color(255, 255, 255);
+ SyntaxElementMorph.prototype.feedbackMinHeight = 5;
+ SyntaxElementMorph.prototype.minSnapDistance = 20;
+ SyntaxElementMorph.prototype.reporterDropFeedbackPadding = 10 * scale;
+ SyntaxElementMorph.prototype.contrast = 65;
+ SyntaxElementMorph.prototype.labelContrast = 25;
+ SyntaxElementMorph.prototype.activeHighlight = new Color(153, 255, 213);
+ SyntaxElementMorph.prototype.errorHighlight = new Color(173, 15, 0);
+ SyntaxElementMorph.prototype.activeBlur = 20;
+ SyntaxElementMorph.prototype.activeBorder = 4;
+ SyntaxElementMorph.prototype.rfColor = new Color(120, 120, 120);
+};
+
+SyntaxElementMorph.prototype.setScale(1);
// SyntaxElementMorph instance creation:
@@ -2033,6 +2042,7 @@ BlockMorph.prototype.showHelp = function () {
BlockMorph.prototype.eraseHoles = function (context) {
var myself = this,
+ isReporter = this instanceof ReporterBlockMorph,
shift = this.edge * 0.5,
gradient,
rightX,
@@ -2071,9 +2081,9 @@ BlockMorph.prototype.eraseHoles = function (context) {
var w = hole.width(),
h = Math.floor(hole.height()) - 2; // Opera needs this
context.clearRect(
- Math.floor(hole.bounds.origin.x - myself.bounds.origin.x),
+ Math.floor(hole.bounds.origin.x - myself.bounds.origin.x) + 1,
Math.floor(hole.bounds.origin.y - myself.bounds.origin.y) + 1,
- w,
+ isReporter ? w - 1 : w + 1,
h
);
});
@@ -2760,9 +2770,9 @@ CommandBlockMorph.prototype.drawNew = function () {
CommandBlockMorph.prototype.drawBody = function (context) {
context.fillRect(
0,
- this.corner,
+ Math.floor(this.corner),
this.width(),
- this.height() - (this.corner * 3)
+ this.height() - Math.floor(this.corner * 3) + 1
);
};
@@ -3173,9 +3183,9 @@ HatBlockMorph.prototype.drawTop = function (context) {
HatBlockMorph.prototype.drawBody = function (context) {
context.fillRect(
0,
- this.hatHeight + this.corner,
+ this.hatHeight + Math.floor(this.corner) - 1,
this.width(),
- this.height() - (this.corner * 3) - (this.hatHeight)
+ this.height() - Math.floor(this.corner * 3) - this.hatHeight + 2
);
};
diff --git a/byob.js b/byob.js
index e8c8080..29ab1b5 100644
--- a/byob.js
+++ b/byob.js
@@ -105,7 +105,7 @@ CommentMorph, localize, CSlotMorph*/
// Global stuff ////////////////////////////////////////////////////////
-modules.byob = '2013-February-18';
+modules.byob = '2013-March-18';
// Declarations
@@ -2002,7 +2002,7 @@ BlockLabelPlaceHolderMorph.prototype.drawNew = function () {
context.beginPath();
context.arc(
cx,
- cy,
+ cy * 1.2,
Math.min(cx, cy),
radians(0),
radians(360),
@@ -2127,7 +2127,8 @@ InputSlotDialogMorph.prototype.init = function (
environment,
category
) {
- var fh = fontHeight(10) / 1.2; // "raw height"
+ var scale = SyntaxElementMorph.prototype.scale,
+ fh = fontHeight(10) / 1.2 * scale; // "raw height"
// additional properties:
this.fragment = fragment || new BlockLabelFragment();
@@ -2152,7 +2153,7 @@ InputSlotDialogMorph.prototype.init = function (
this.slots = new BoxMorph();
this.slots.color = new Color(55, 55, 55); // same as palette
this.slots.borderColor = this.slots.color.lighter(50);
- this.slots.setExtent(new Point((fh + 10) * 24, (fh + 10) * 10.4));
+ this.slots.setExtent(new Point((fh + 10) * 24, (fh + 10 * scale) * 10.4));
this.add(this.slots);
this.createSlotTypeButtons();
this.fixSlotsLayout();
@@ -2548,10 +2549,11 @@ InputSlotDialogMorph.prototype.addSlotArityButton = function (
InputSlotDialogMorph.prototype.fixSlotsLayout = function () {
var slots = this.slots,
- xPadding = 10,
- ypadding = 14,
- bh = fontHeight(10) / 1.2 + 15, // slot type button height
- ah = fontHeight(10) / 1.2 + 10, // arity button height
+ scale = SyntaxElementMorph.prototype.scale,
+ xPadding = 10 * scale,
+ ypadding = 14 * scale,
+ bh = (fontHeight(10) / 1.2 + 15) * scale, // slot type button height
+ ah = (fontHeight(10) / 1.2 + 10) * scale, // arity button height
size = 12, // number slot type radio buttons
cols = [
slots.left() + xPadding,
diff --git a/gui.js b/gui.js
index 6056277..0619201 100644
--- a/gui.js
+++ b/gui.js
@@ -68,7 +68,7 @@ sb*/
// Global stuff ////////////////////////////////////////////////////////
-modules.gui = '2013-March-15';
+modules.gui = '2013-March-18';
// Declarations
@@ -1687,6 +1687,14 @@ IDE_Morph.prototype.settingsMenu = function () {
menu = new MenuMorph(this);
menu.addItem('Language...', 'languageMenu');
+ if (shiftClicked) {
+ menu.addItem(
+ 'Scale blocks...',
+ 'userSetBlocksScale',
+ null,
+ new Color(100, 0, 0)
+ );
+ }
menu.addLine();
addPreference(
'Blurred shadows',
@@ -2760,6 +2768,52 @@ IDE_Morph.prototype.reflectLanguage = function (lang) {
this.openProjectString(projectData);
};
+// IDE_Morph blocks scaling
+
+IDE_Morph.prototype.userSetBlocksScale = function () {
+ var myself = this;
+ new DialogBoxMorph(
+ null,
+ function (num) {
+ myself.setBlocksScale(num);
+ }
+ ).prompt(
+ 'Scale Blocks',
+ SyntaxElementMorph.prototype.scale.toString(),
+ this.world(),
+ null,
+ {
+ 'normal (1)' : 1,
+ 'demo (1.2)' : 1.2,
+ 'big (2)' : 2,
+ 'huge (4)' : 4,
+ 'giant (8)' : 8
+ },
+ false, // read only?
+ true // numeric
+ );
+};
+
+IDE_Morph.prototype.setBlocksScale = function (num) {
+ var projectData;
+ if (Process.prototype.isCatchingErrors) {
+ try {
+ projectData = this.serializer.serialize(this.stage);
+ } catch (err) {
+ this.showMessage('Serialization failed: ' + err);
+ }
+ } else {
+ projectData = this.serializer.serialize(this.stage);
+ }
+ SyntaxElementMorph.prototype.setScale(num);
+ SpriteMorph.prototype.initBlocks();
+ this.spriteBar.tabBar.tabTo('scripts');
+ this.createCategories();
+ this.createCorralBar();
+ this.fixLayout();
+ this.openProjectString(projectData);
+};
+
// IDE_Morph cloud interface
IDE_Morph.prototype.initializeCloud = function () {
diff --git a/history.txt b/history.txt
index bf72c0e..46e615a 100755
--- a/history.txt
+++ b/history.txt
@@ -1522,4 +1522,9 @@ ______
130314
------
* GUI: When logged into the Cloud, "cloud" becomes default in the project dialog
-* Store: local custom blocks can now store their definition receiver directly as value (avoiding turning them into "Obsolete!" blocks when re-opening the project), this is important for reified blocks assigned to variables elsewhere, and such for the part of OOP we can already do now. \ No newline at end of file
+* Store: local custom blocks can now store their definition receiver directly as value (avoiding turning them into "Obsolete!" blocks when re-opening the project), this is important for reified blocks assigned to variables elsewhere, and such for the part of OOP we can already do now.
+
+130318
+------
+* GUI, Blocks, BYOB, Widgets: Scaling Blocks and Scripts (shift-click on settings menu)
+* Widets: numerical prompts \ No newline at end of file
diff --git a/widgets.js b/widgets.js
index 6740ef5..2760171 100644
--- a/widgets.js
+++ b/widgets.js
@@ -73,7 +73,7 @@ newCanvas, StringMorph, Morph, TextMorph, nop, detect, StringFieldMorph,
HTMLCanvasElement, fontHeight, SymbolMorph, localize, SpeechBubbleMorph,
ArrowMorph, MenuMorph, isString*/
-modules.widgets = '2013-February-26';
+modules.widgets = '2013-March-18';
var PushButtonMorph;
var ToggleButtonMorph;
@@ -1531,11 +1531,12 @@ DialogBoxMorph.prototype.prompt = function (
world,
pic,
choices, // optional dictionary for drop-down of choices
- isReadOnly // optional when using choices
+ isReadOnly, // optional when using choices
+ isNumeric // optional
) {
var txt = new InputFieldMorph(
defaultString,
- false, // numeric?
+ isNumeric || false, // numeric?
choices || null, // drop-down dict, optional
choices ? isReadOnly || false : false
);