commit:98d8bc4d5f0bc0b315b54369a8f288d93e9b2c44
author:Chip Black
committer:Chip Black
date:Sun Sep 11 21:10:04 2011 -0500
parents:0fe39807102fa21ad98accc5cdd46c0324745be8
Add preferences system.
diff --git a/HackPreferences.js b/HackPreferences.js
line changes: +66/-0
index 0000000..a8f9195
--- /dev/null
+++ b/HackPreferences.js
@@ -0,0 +1,66 @@
+enyo.kind({
+	name: "HackPreferences",
+	kind: "VFlexBox",
+	events: {
+		"onClose": ""
+	},
+	components: [
+		{kind: "Header", content: "Preferences"},
+		{kind: "Scroller", flex: 1, horizontal: false, components: [
+			{kind: "VFlexBox", align: "center", components: [
+				{kind: "RowGroup", name: "prefsContainer", style: "width: 750px"}
+			]}
+		]},
+		{kind: "Toolbar", className: "enyo-toolbar-light", components: [
+			{kind: "Button", content: "Done", onclick: "close", className: "enyo-button-affirmative prefs-done-button"}
+		]}
+	],
+	load: function(name, prefs, values) {
+		this.$.prefsContainer.setCaption(name);
+		this.prefs = prefs;
+
+		for (var i = 0; i < this.prefs.length; i++) {
+			var p = this.prefs[i];
+			var c;
+
+			switch(p.kind) {
+			case 'Slider':
+				c = this.$.prefsContainer.createComponent({kind: "HFlexBox", align: "center", components: [{content: p.label, flex: 1}]});
+				var slider = c.createComponent(p, {owner: this.$.prefsContainer});
+				slider.setStyle('width: 400px');
+				slider.setPosition(values[p.name]);
+				break;
+			default:
+				c = this.$.prefsContainer.createComponent(p, {owner: this.$.prefsContainer});
+				c.setValue(values[p.name]);
+			}
+		}
+		this.$.prefsContainer.render();
+	},
+	close: function() {
+		var o = {};
+		for (var i = 0; i < this.prefs.length; i++) {
+			var p = this.prefs[i];
+			var v;
+
+			switch (p.kind) {
+			case 'Slider':
+				v = this.$.prefsContainer.$[p.name].getPosition();
+				break;
+			default:
+				v = this.$.prefsContainer.$[p.name].getValue();
+			}
+			o[p.name] = v;
+		}
+		this.doClose(o);
+
+		var controls = this.$.prefsContainer.getControls();
+		for (var i = 0; i < controls.length; i++) {
+			// We destroy the parent because we want to destroy the
+			// row client, as well.  This is probably a bug in
+			// Enyo.
+			controls[i].parent.destroy();
+			controls[i].destroy();
+		}
+	}
+});

diff --git a/Main.css b/Main.css
line changes: +18/-0
index 1fe2ca5..6a1d5c2
--- a/Main.css
+++ b/Main.css
@@ -27,3 +27,21 @@
 .info.dark {
 	color: #AFAFAf;
 }
+
+.info .enyo-menuitem {
+	font-size: 24px;
+}
+
+.wrench {
+	width: 24px;
+	height: 24px;
+	padding: 5px 5px;
+	margin-right: 8px;
+	background-image: url(images/wrench.png);
+	background-repeat: no-repeat;
+	background-position: center center;
+}
+
+.prefs-done-button {
+	width: 300px;
+}

diff --git a/Main.js b/Main.js
line changes: +55/-19
index 68194e2..9a0a209
--- a/Main.js
+++ b/Main.js
@@ -2,16 +2,19 @@
  * See COPYING for licensing information */
 enyo.kind({
 	name: "Main",
-	kind: "VFlexBox",
-	style: "background-color: black",
+	kind: "Pane",
 	components: [
 		{kind: "ApplicationEvents", onWindowActivated: "windowActivated", onWindowDeactivated: "windowDeactivated"},
-		{name: "hacksCarousel", kind: "Carousel", flex: 1, onGetLeft: "getLeft", onGetRight: "getRight", onScroll: "scrolling", onScrollStart: "startScroll", onScrollStop: "stopScroll"},
-		{name: "info", kind: "HFlexBox", className: "info", style: "opacity: 0", showing: false, components: [
-			{name: "title"},
-			{kind: "Spacer"},
-			{name: "notice", className: "notice"}
-		]}
+		{name: "mainView", kind: "VFlexBox", components: [
+			{name: "hacksCarousel", kind: "Carousel", flex: 1, onGetLeft: "getLeft", onGetRight: "getRight", onScroll: "scrolling", onScrollStart: "startScroll", onScrollStop: "stopScroll"},
+			{name: "info", kind: "HFlexBox", className: "info", align: "center", style: "opacity: 0", onclick: "infoFade", components: [
+				{className: "wrench", onclick: "openPreferences"},
+				{name: "hacksListSelector", kind: "ListSelector", popupAlign: "left", onChange: "selectHack", style: "width: 200px"},
+				{kind: "Spacer"},
+				{name: "notice", className: "notice"}
+			]}
+		]},
+		{name: "preferencesView", kind: "HackPreferences", onClose: "savePreferences"}
 	],
 	hacksList: [
 		{name: "Nimbus", kind: "Nimbus", dark: false},
@@ -36,14 +39,17 @@ enyo.kind({
 		this.$.hacksCarousel.setCenterView(this.getHack(this.index));
 	},
 	ready: function() {
+		var displayList = [];
+		for (var i = 0; i < this.hacksList.length; i++) {
+			displayList.push({
+				caption: this.hacksList[i].name,
+				value: i
+			});
+		}
+		this.$.hacksListSelector.setItems(displayList);
 		this.startHack();
 		window.addEventListener('resize', this.resizeHack.bind(this), false);
 		this.setNotice('Swipe for more...');
-		this.setTitle(this.hacksList[this.index].name);
-	},
-	setTitle: function(title) {
-		this.$.title.setContent(title);
-		this.infoFade();
 	},
 	setNotice: function(notice) {
 		this.$.notice.setContent(notice);
@@ -51,24 +57,52 @@ enyo.kind({
 	},
 	infoFade: function() {
 		this.$.info.setStyle('opacity: 1');
-		this.$.info.show();
 
 		clearTimeout(this.noticeTimer);
 		this.noticeTimer = setTimeout(function() {
 			this.$.info.setStyle('opacity: 0');
 			setTimeout(function() {
-				this.$.info.hide();
-				this.setNotice('');
-				this.setTitle('');
+				this.$.notice.setContent('');
 			}.bind(this), 600);
 		}.bind(this), 5000);
 	},
+	openPreferences: function() {
+		var view = this.$.hacksCarousel.fetchView('center');
+		view.stop();
+
+		var meta = view.getPreferencesMetadata();
+		if (meta) {
+			var values = view.getPreferences();
+			this.$.preferencesView.load(this.hacksList[this.index].name, meta, values);
+			this.selectView(this.$.preferencesView);
+		} else {
+			alert("No prefs");
+		}
+	},
+	savePreferences: function(inSender, prefs) {
+		enyo.log("Saving prefs: " + JSON.stringify(prefs));
+		this.back();
+		var view = this.$.hacksCarousel.fetchView('center');
+		view.setPreferences(prefs);
+		view.start();
+	},
 	windowActivated: function() {
 		this.startHack();
 	},
 	windowDeactivated: function() {
 		this.stopHack();
 	},
+	selectHack: function(inSender, inValue, inOldValue) {
+		this.stopHack();
+		this.index = inValue;
+		this.lastScrollPos = 0;
+		this.$.hacksCarousel.setCenterView(this.getHack(this.index));
+		this.$.info.addRemoveClass('dark', this.hacksList[this.index].dark);
+		// For some reason, setCenterView above fires the startScroll
+		// event without a subsequent stopScroll event.  To work around
+		// this, we defer the start until later.
+		setTimeout(function() { this.startHack() }.bind(this), 20);
+	},
 	startHack: function(direction) {
 		var view = this.$.hacksCarousel.fetchView(direction || 'center');
 		//enyo.log('starting view ' + view);
@@ -105,8 +139,9 @@ enyo.kind({
 	getLeft: function(inSender, inSnap) {
 		if (inSnap && this.index > 0) {
 			this.index--;
+			this.$.hacksListSelector.setValue(this.index);
 			this.hackHidden('right');
-			this.setTitle(this.hacksList[this.index].name);
+			this.infoFade();
 			this.$.info.addRemoveClass('dark', this.hacksList[this.index].dark);
 		}
 		if (this.index == 0)
@@ -117,8 +152,9 @@ enyo.kind({
 	getRight: function(inSender, inSnap) {
 		if (inSnap && this.index < this.hacksList.length) {
 			this.index++;
+			this.$.hacksListSelector.setValue(this.index);
 			this.hackHidden('left');
-			this.setTitle(this.hacksList[this.index].name);
+			this.infoFade();
 			this.$.info.addRemoveClass('dark', this.hacksList[this.index].dark);
 		}
 		if (this.index == this.hacksList.length - 1)

diff --git a/README b/README
line changes: +2/-0
index 0000000..d3bbbc3
--- /dev/null
+++ b/README
@@ -0,0 +1,2 @@
+Wrench icon by Joseph Wain, used under a Creative Commons by-3.0 license.
+Downloaded from http://glyphish.com/

diff --git a/depends.js b/depends.js
line changes: +1/-0
index 5b74b28..9a32b24
--- a/depends.js
+++ b/depends.js
@@ -1,6 +1,7 @@
 enyo.depends(
 	"Main.js",
 	"Main.css",
+	"HackPreferences.js",
 	"hacks/Hack.js",
 	"hacks/Nimbus/Nimbus.js",
 	"hacks/HexaSpinner/HexaSpinner.js",

diff --git a/hacks/Hack.js b/hacks/Hack.js
line changes: +22/-0
index 28cfad7..2133299
--- a/hacks/Hack.js
+++ b/hacks/Hack.js
@@ -3,6 +3,7 @@
 enyo.kind({
 	name: "Hack",
 	kind: "VFlexBox",
+	preferences: [],
 	stop: function() {
 	},
 	start: function() {
@@ -10,5 +11,26 @@ enyo.kind({
 	resize: function() {
 	},
 	hidden: function() {
+	},
+	getPreferencesMetadata: function() {
+		return this.preferences;
+	},
+	getPreferences: function() {
+		var o = {};
+		for (var i = 0; i < this.preferences.length; i++) {
+			var p = this.preferences[i];
+			o[p.name] = this[p.name];
+		}
+		return o;
+	},
+	setPreferences: function(prefs) {
+		for (var i in prefs) {
+			if (this[i] == undefined)
+				throw new Error('Cannot set nonexistent preference "' + i + '"');
+			this[i] = prefs[i];
+		}
+		this.preferencesChanged();
+	},
+	preferencesChanged: function() {
 	}
 });

diff --git a/hacks/Nimbus/Nimbus.js b/hacks/Nimbus/Nimbus.js
line changes: +18/-3
index f8ed719..7bc5c7c
--- a/hacks/Nimbus/Nimbus.js
+++ b/hacks/Nimbus/Nimbus.js
@@ -41,6 +41,17 @@ enyo.kind({
 	drop_c: 0,
 	drops: [],
 	perspective: 0.3,
+	preferences: [
+		{name: "intensity", label: "Intensity", kind: "Slider", maximum: 1, minimum: 0, snap: 0.01},
+		{name: "rainColor", label: "Rain Color", kind: "ListSelector", items: ["gray", "black", "blue", "red"]},
+		{name: "backgroundColor", label: "Background Color", kind: "ListSelector", items: [
+			{caption: "white", value: 'rgba(255,255,255,0.7)'},
+			{caption: "black", value: 'rgba(0,0,0,0.7)'}
+		]}
+	],
+	intensity: 0.7,
+	rainColor: 'gray',
+	backgroundColor: 'rgba(255,255,255,0.7)',
 	components: [
 		{name: "raindrops", nodeTag: "canvas"}
 	],
@@ -64,12 +75,16 @@ enyo.kind({
 		this.raindrops.width = this.w = w;
 		this.raindrops.height = this.h = h;
 
-		this.ctx.fillStyle = 'rgba(255,255,255,0.7)';
-		this.ctx.strokeStyle = 'rgb(128,128,128)';
+		this.ctx.fillStyle = this.backgroundColor;
+		this.ctx.strokeStyle = this.rainColor;
 		this.ctx.lineWidth = '2';
 	},
+	preferencesChanged: function() {
+		this.ctx.fillStyle = this.backgroundColor;
+		this.ctx.strokeStyle = this.rainColor;
+	},
 	draw: function() {
-		if (Math.random() > 0.3) {
+		if (Math.random() <= this.intensity) {
 			this.drops[this.drop_c].start(this.w, this.h, this.perspective);
 			this.drop_c = (this.drop_c + 1) % 100;
 		}

diff --git a/images/wrench.png b/images/wrench.png
line changes: +0/-0
index 0000000..a771bcd
--- /dev/null
+++ b/images/wrench.png