diff --git a/examples/ui/widget_design_patterns/css/example.css b/examples/ui/widget_design_patterns/css/example.css index 3c00d862..f3cb4ac9 100644 --- a/examples/ui/widget_design_patterns/css/example.css +++ b/examples/ui/widget_design_patterns/css/example.css @@ -1,3 +1,6 @@ -OxMyBox.focused { - box-shadow: inset 0 0 1px black; +.OxMyBox { + float: left; +} +.OxMyInvertibleBox { + cursor: pointer; } \ No newline at end of file diff --git a/examples/ui/widget_design_patterns/js/example.js b/examples/ui/widget_design_patterns/js/example.js index 18671d4a..8dfaca47 100644 --- a/examples/ui/widget_design_patterns/js/example.js +++ b/examples/ui/widget_design_patterns/js/example.js @@ -16,7 +16,7 @@ be accessed from outside, but since `self` itself is an argument of the /* Load the UI module. */ -Ox.load('UI', function() { +Ox.load(['Image', 'UI'], function() { /* Create our own namespace. @@ -56,13 +56,14 @@ Ox.load('UI', function() { var that = Ox.Element({}, self) .defaults({ color: [128, 128, 128], - size: 128 + size: [128, 128] }) .options(options || {}) .update({ color: setColor, size: setSize - }); + }) + .addClass('OxMyBox'); /* The second part of the "constructor" function can be thought of as the @@ -73,8 +74,8 @@ Ox.load('UI', function() { be accessible across all the widget's methods, we can be sure that inside such methods, any local `var` is actually local to the method. */ - self.minSize = 128; - self.maxSize = 384; + self.minSize = 1; + self.maxSize = 256; setColor(); setSize(); @@ -103,12 +104,12 @@ Ox.load('UI', function() { Before setting the size, we make sure the value is between `minSize` and `maxSize`. */ - self.options.size = Ox.limit( - self.options.size, self.minSize, self.maxSize - ); + self.options.size = self.options.size.map(function(value) { + return Ox.limit(value, self.minSize, self.maxSize); + }); that.css({ - height: self.options.size + 'px', - width: self.options.size + 'px' + width: self.options.size[0] + 'px', + height: self.options.size[1] + 'px' }); } @@ -136,14 +137,233 @@ Ox.load('UI', function() { }; + Ox.My.InvertibleBox = function(options, self) { + + self = self || {}; + var that = Ox.My.Box({}, self); + that.defaults(Ox.extend(that.defaults(), { + inverted: false + })) + .options(options || {}) + .update({ + color: setColor, + inverted: setColor + }) + .addClass('OxMyInvertibleBox') + .bindEvent({ + doubleclick: function() { + that.invert(); + } + }); + + self.options.inverted && setColor(); + + function getInvertedColor() { + return self.options.color.map(function(value) { + return 255 - value; + }); + } + + function setColor() { + that.css({backgroundColor: 'rgb(' + ( + self.options.inverted ? getInvertedColor() : self.options.color + ).join(', ') + ')'}); + return false; + } + + that.invert = function() { + that.options({inverted: !self.options.inverted}); + }; + + return that; + + }; + + Ox.My.MetaBox = function(options, self) { + + self = self || {}; + var that = Ox.My.Box(options || {}, self) + .update({color: setColor}); + + self.inverting = false; + self.sizes = [ + Ox.splitInt(self.options.size[0], self.options.color[0].length), + Ox.splitInt(self.options.size[1], self.options.color.length) + ]; + + self.$boxes = self.options.color.map(function(array, y) { + return array.map(function(color, x) { + return Ox.My.InvertibleBox({ + color: color, + size: [self.sizes[0][x], self.sizes[1][y]] + }) + .update({ + inverted: function() { + if (!self.inverting) { + self.inverting = true; + self.$boxes[y][x].invert(); + that.invert(); + return false; + } + } + }) + .appendTo(that); + }); + }); + + function setColor() { + self.$boxes.forEach(function(array, y) { + array.forEach(function($box, x) { + $box.options({color: self.options.color[y][x]}); + }); + }); + } + + that.invert = function() { + self.inverting = true; + self.$boxes.forEach(function(array) { + array.forEach(function($box) { + $box.invert(); + }); + }); + self.inverting = false; + }; + + return that; + + }; + + Ox.My.PixelBox = function(options, self) { + + self = self || {}; + var that = Ox.My.Box(options || {}, self) + .update({ + color: setColor + }); + + self.$pixel = Ox.My.MetaBox(Ox.extend(options, { + color: getColor() + }), self) + .appendTo(that); + + self.$pixel.invert = function() { + self.inverting = true; + self.$boxes.forEach(function(array) { + array.forEach(function($box, x) { + $box.options({ + color: $box.options('color').map(function(value, i) { + return i == x ? 255 - value : value + }) + }); + }); + }); + self.inverting = false; + that.triggerEvent('invert'); + }; + + function getColor() { + return [[ + [self.options.color[0], 0, 0], + [0, self.options.color[1], 0], + [0, 0, self.options.color[2]] + ]]; + } + + function setColor() { + self.$pixel.options({color: getColor()}); + } + + that.invert = function() { + self.$pixel.invert(); + }; + + return that; + + }; + + Ox.My.ImageBox = function(options, self) { + + self = self || {}; + var that = Ox.My.Box(options || {}, self); + + self.inverting = false; + + Ox.Image(self.options.image, function(image) { + var size = image.getSize(); + size = [size.width, size.height]; + self.sizes = size.map(function(value, index) { + return Ox.splitInt(self.options.size[index], value); + }); + self.$boxes = Ox.range(size[1]).map(function(y) { + return Ox.range(size[0]).map(function(x) { + return Ox.My.PixelBox({ + color: image.pixel(x, y).slice(0, 3), + size: [self.sizes[0][x], self.sizes[1][y]] + }) + .bindEvent({ + invert: function() { + if (!self.inverting) { + self.inverting = true; + self.$boxes[y][x].invert(); + that.invert(); + return false; + } + } + }) + .appendTo(that); + }); + }); + }); + + that.invert = function() { + self.inverting = true; + self.$boxes.forEach(function(array) { + array.forEach(function($box) { + $box.invert(); + }); + }); + self.inverting = false; + }; + + return that; + + }; + /* -
-    Ox.My.Box({color: [255, 0, 0]})
-        .appendTo(Ox.$body)
-        .options({size: 256})
-        .showOptions();
-    
+ This is left as an exercise for the reader ;) */ + Ox.My.VideoBox = function(options, self) { + + }; + + window.My = {}; + My.$div = $('
') + .css({float: 'left', width: '256px', height: '256px'}) + .appendTo(Ox.$body); + My.$box = Ox.My.Box({ + color: [255, 0, 0] + }).appendTo(My.$div); + My.$invertibleBox = Ox.My.InvertibleBox({ + color: [0, 0, 255] + }).appendTo(My.$div); + My.$metaBox = Ox.My.MetaBox({ + color: [ + [[255, 0, 0], [255, 255, 0], [0, 255, 0]], + [[0, 255, 255], [0, 0, 255], [255, 0, 255]] + ] + }).appendTo(My.$div); + My.$pixelBox = Ox.My.PixelBox({ + color: [255, 128, 0] + }).appendTo(My.$div); + setTimeout(function() { + My.$imageBox = Ox.My.ImageBox({ + image: 'png/pandora32.png', + size: [256, 256] + }).appendTo(Ox.$body); + }); + + + return; /* Now we create a new widget that subclasses `Ox.My.Box`. diff --git a/examples/ui/widget_design_patterns/png/pandora32.png b/examples/ui/widget_design_patterns/png/pandora32.png new file mode 100644 index 00000000..111e0305 Binary files /dev/null and b/examples/ui/widget_design_patterns/png/pandora32.png differ