From f4fa5c8ccab41b6a45d4295b1cef10f27d90b3c3 Mon Sep 17 00:00:00 2001 From: Ian Gilman Date: Wed, 17 Mar 2010 14:06:07 -0700 Subject: [PATCH] + Moved my work on the stacks candy to the ian1 candy, and added groups to it + added automatic thumbnail repainting for resized thumbnails + updated the original and ian1 candies so the thumbnail scales automatically with the jquery animation of the whole tab --- browser/base/content/tabcandy/app/groups.js | 4 +- browser/base/content/tabcandy/core/mirror.js | 21 ++- content/candies/ian1/index.html | 60 ++++-- content/candies/ian1/js/jquery.select.js | 138 ++++++++++++++ content/candies/ian1/js/ui.js | 181 ++++++++++++++++--- content/candies/original/index.html | 6 +- 6 files changed, 365 insertions(+), 45 deletions(-) create mode 100644 content/candies/ian1/js/jquery.select.js diff --git a/browser/base/content/tabcandy/app/groups.js b/browser/base/content/tabcandy/app/groups.js index f8a17fa7f71..180b5fabbe7 100644 --- a/browser/base/content/tabcandy/app/groups.js +++ b/browser/base/content/tabcandy/app/groups.js @@ -82,7 +82,7 @@ Group.prototype = { this._children = this._children.filter(function(child){ if( $(child).data("toRemove") == true ){ $(child).data("group", null); - $(child).animate({width:160, height:120}, 250); + $(child).animate({width:160, height:137}, 250); $(child).droppable("enable"); return false; } @@ -121,9 +121,11 @@ Group.prototype = { // This is for actual tabs. Need a better solution. // One that doesn't require special casing to find the linked info. // If I just animate the tab, the rest should happen automatically! +/* if( $("canvas", tab)[0] != null ){ $("canvas", tab).data('link').animate({height:h}, 250); } +*/ $(tab).animate({ height:h, width: w, diff --git a/browser/base/content/tabcandy/core/mirror.js b/browser/base/content/tabcandy/core/mirror.js index 1b395ccb3c9..f5cf356d339 100644 --- a/browser/base/content/tabcandy/core/mirror.js +++ b/browser/base/content/tabcandy/core/mirror.js @@ -50,8 +50,8 @@ TabCanvas.prototype = { var $canvas = $(this.canvas); var ctx = this.canvas.getContext("2d"); - var w = $canvas.width(); - var h = $canvas.height(); + var w = $canvas.attr('width'); + var h = $canvas.attr('height'); var fromWin = this.tab.contentWindow; if(fromWin == null) { @@ -78,10 +78,8 @@ TabCanvas.prototype = { }, animate: function(options, duration){ -/* - if(this.tab.contentWindow == null || this.tab.contentWindow.location.protocol != 'chrome:') - Utils.log('on animate', this.tab.contentWindow.location.href); -*/ + Utils.log('on animate', this.tab.contentWindow.location.href); + var self = this; if( duration == null ) duration = 0; @@ -145,6 +143,7 @@ TabMirror.prototype = { var label = tab.raw.label; $fav = $(mirror.favEl); $name = $(mirror.nameEl); + $canvas = $(mirror.canvasEl); if(iconUrl != $fav.attr("src")) { $fav.attr("src", iconUrl); @@ -160,6 +159,16 @@ TabMirror.prototype = { mirror.url = tab.url; mirror.triggerPaint(); } + + var w = $canvas.width(); + var h = $canvas.height(); + if(w != $canvas.attr('width') || h != $canvas.attr('height')) { + Utils.log(w, $canvas.attr('width'), h, $canvas.attr('height')); + + $canvas.attr('width', w); + $canvas.attr('height', h); + mirror.triggerPaint(); + } if(mirror.needsPaint) { mirror.tabCanvas.paint(); diff --git a/content/candies/ian1/index.html b/content/candies/ian1/index.html index fb7bafc1752..1bc368cf153 100644 --- a/content/candies/ian1/index.html +++ b/content/candies/ian1/index.html @@ -20,6 +20,8 @@ margin: 0px; padding: 0; background-color: rgba(255,255,255,.8); + width: 160px; + height: 137px; } .fav{ @@ -31,10 +33,10 @@ padding: 3px; -moz-box-shadow: 1px 1px 3px rgba(0,0,0,.2); } - + .thumb{ - width: 160px; - height: 120px; + width: 100%; + height: 80%; background-color: #ccc; -moz-box-shadow: 1px 1px 10px rgba(0,0,0,.3); } @@ -43,6 +45,10 @@ -moz-box-shadow: 1px 1px 10px rgba(0,0,0,.5); } + .thumb-selected { + -moz-box-shadow: 1px 1px 10px rgba(0,0,0,1); + } + .name{ position: absolute; top: 123px; @@ -82,7 +88,7 @@ } - .search{width:100%; margin-top: 30px; text-align: center; margin-bottom: 30px;} + .search{width:100%; margin-top: 15px; text-align: center; margin-bottom: 30px;} .search input{ width: 300px; font-size: 16pt;} #actions{ @@ -101,34 +107,66 @@ z-index: -100; } + .lasso-menu { + background-color: white; + width: 100px; + height: 200px; + border: 1px solid #DDD; + -moz-box-shadow: 2px 2px 4px rgba(0,0,0,.5); + line-height: 100px; + text-align: center; + cursor: pointer; + } + + .group{ + cursor: move; + -moz-box-shadow: 0px 0px 5px rgba(0,0,0,.2); + } + - + - -
- Toggle Tab Bar + + + + + + + + + + diff --git a/content/candies/ian1/js/jquery.select.js b/content/candies/ian1/js/jquery.select.js new file mode 100644 index 00000000000..ac6b7e72165 --- /dev/null +++ b/content/candies/ian1/js/jquery.select.js @@ -0,0 +1,138 @@ +function Selector(options){ this.init(options) } +Selector.prototype = { + init: function(options){ + var self = this; + options.onSelect = function(a,b){ + self.showMenu(a,b); + TabMirror.resumePainting(); + }; + options.onStart = function(){ + self.hideMenu(250); + TabMirror.pausePainting(); + }; +/* options.onMove = function(a){ self.updateSelection(a) }; */ + options.acceptMouseDown = function(a){ return self.acceptMouseDown(a); }; + this.lasso = new Lasso(options); + }, + + startFadeOutTimer: function() { + var self = this; + this.timeout = setTimeout(function() { + self.timeout = null; + self.hideMenu(2000); + }, 1000); + }, + + cancelFadeOutTimer: function() { + if(this.timeout) { + clearTimeout(this.timeout); + this.timeout = null; + } + }, + + hideMenu: function(time) { + var self = this; + if(this.menu) { + this.menu.fadeOut(time, function() { + if(self.menu) { + self.menu.remove(); + self.menu = null; + self.clearSelection(); + } + }); + } + + this.cancelFadeOutTimer(); + }, + + showMenu: function( selectedEls, pos ){ + if( pos == null || selectedEls.length == 0 ) return; + var self = this; + + this.selectedEls = selectedEls; + this.updateSelection(); + this.cancelFadeOutTimer(); + + this.menu = $("
").appendTo("body"); + this.menu.css({ + position:"fixed", + zIndex: 9999, + top:pos.y-this.menu.height()/2, + left:pos.x-this.menu.width()/2 + }); + + this.menu.mouseover(function() { + self.menu.stop(); + self.menu.css({'opacity':1}); + self.cancelFadeOutTimer(); + }); + + this.menu.mouseout(function() { + self.startFadeOutTimer(); + }); + + $('
Group
') + .appendTo(this.menu) + .mousedown(function() { + group(selectedEls); + }); + + $('
Close
') + .appendTo(this.menu) + .mousedown(function() { + close(selectedEls); + }); + }, + + updateSelection: function() { + for( var i=0; i 0) + return false; + + return true; + } +} + +function group(els){ + var startEl = $(els[0]); + startEl.css("z-index", 0); + for( var i=1; ix
").appendTo($div) - + $("
x
").appendTo($div); + + if(Arrange.initialized) { + var p = Page.findOpenSpaceFor($div); + $div.css({left: p.x, top: p.y}); + } } window.TabMirror.customize(mod); @@ -120,6 +116,92 @@ var Page = { $(window).blur(function(){ Navbar.show(); }) + }, + + findOpenSpaceFor: function($div) { + var w = window.innerWidth; + var h = 0; + var startX = 30; + var startY = 100; + var bufferX = 30; + var bufferY = 30; + var rects = []; + var r; + var $el; + $(".tab:visible").each(function(i) { + if(this == $div.get(0)) + return; + + $el = $(this); + r = {x: parseInt($el.css('left')), + y: parseInt($el.css('top')), + w: parseInt($el.css('width')) + bufferX, + h: parseInt($el.css('height')) + bufferY}; + + if(r.x + r.w > w) + w = r.x + r.w; + + if(r.y + r.h > h) + h = r.y + r.h; + + rects.push(r); + }); + + if(!h) + return { 'x': startX, 'y': startY }; + + var canvas = document.createElement('canvas'); + $(canvas).attr({width:w,height:h}); + + var ctx = canvas.getContext('2d'); + ctx.fillStyle = 'rgb(255, 255, 255)'; + ctx.fillRect(0, 0, w, h); + ctx.fillStyle = 'rgb(0, 0, 0)'; + var count = rects.length; + var a; + for(a = 0; a < count; a++) { + r = rects[a]; + ctx.fillRect(r.x, r.y, r.w, r.h); + } + + var divWidth = parseInt($div.css('width')) + bufferX; + var divHeight = parseInt($div.css('height')) + bufferY; + var strideX = divWidth / 4; + var strideY = divHeight / 4; + var data = ctx.getImageData(0, 0, w, h).data; + + function isEmpty(x1, y1) { + return (x1 >= 0 && y1 >= 0 + && x1 < w && y1 < h + && data[(y1 * w + x1) * 4]); + } + + function isEmptyBox(x1, y1) { + return (isEmpty(x1, y1) + && isEmpty(x1 + (divWidth - 1), y1) + && isEmpty(x1, y1 + (divHeight - 1)) + && isEmpty(x1 + (divWidth - 1), y1 + (divHeight - 1))); + } + + for(var y = startY; y < h; y += strideY) { + for(var x = startX; x < w; x += strideX) { + if(isEmptyBox(x, y)) { + for(; y > startY + 1; y--) { + if(!isEmptyBox(x, y - 1)) + break; + } + + for(; x > startX + 1; x--) { + if(!isEmptyBox(x - 1, y)) + break; + } + + return { 'x': x, 'y': y }; + } + } + } + + return { 'x': startX, 'y': h }; } } @@ -162,8 +244,12 @@ var grid = new ArrangeClass("Grid", function(value) { if(immediately) $el.css({top: y,left: x}); - else - $el.animate({top: y,left: x}, 1000); + else { + TabMirror.pausePainting(); + $el.animate({top: y,left: x}, 500, null, function() { + TabMirror.resumePainting(); + }); + } x += $el.width() + 30; if( x > window.innerWidth - ($el.width() + startX)){ // includes allowance for the box shadow @@ -175,17 +261,64 @@ var grid = new ArrangeClass("Grid", function(value) { //---------------------------------------------------------- var stack = new ArrangeClass("Stack", function() { - var x = 30; - var y = 100; + var startX = 30; + var startY = 100; + var x = startX; + var y = startY; $(".tab:visible").each(function(i){ $el = $(this); - $el.animate({'top': y, 'left': x, '-moz-transform': 'rotate(40deg)'}, 1000); + TabMirror.pausePainting(); + $el.animate({'top': y, 'left': x, '-moz-transform': 'rotate(40deg)'}, 500, null, function() { + TabMirror.resumePainting(); + }); + }); +}); + +//---------------------------------------------------------- +var site = new ArrangeClass("Site", function() { + var startX = 30; + var startY = 100; + var x = startX; + var y = startY; + var x2; + var y2; + var positions = []; + $(".tab:visible").each(function(i) { + $el = $(this); + var tab = Tabs.tab(this); + var url = tab.url; + var domain = url.split('/')[2]; + var domainParts = domain.split('.'); + var mainDomain = domainParts[domainParts.length - 2]; + if(positions[mainDomain]) { + x2 = positions[mainDomain].x; + y2 = positions[mainDomain].y; + } else { + x2 = x; + y2 = y; + + x += $el.width() + 30; + if( x > window.innerWidth - ($el.width() + startX)){ // includes allowance for the box shadow + x = startX; + y += $el.height() + 30; + } + + positions[mainDomain] = { 'x': x2, 'y': y2 }; + } + + TabMirror.pausePainting(); + $el.animate({'top': y2, 'left': x2, '-moz-transform': 'rotate(40deg)'}, 500, null, function() { + TabMirror.resumePainting(); + }); }); }); //---------------------------------------------------------- var Arrange = { + initialized: false, + init: function(){ + this.initialized = true; grid.arrange(true); } } @@ -198,14 +331,12 @@ UIClass.prototype = { init: function(){ Page.init(); Arrange.init(); - } } //---------------------------------------------------------- var UI = new UIClass(); window.UI = UI; -//window.aza = ArrangeClass })(); diff --git a/content/candies/original/index.html b/content/candies/original/index.html index 28ca62fa73e..e53bced3b52 100644 --- a/content/candies/original/index.html +++ b/content/candies/original/index.html @@ -21,6 +21,8 @@ padding: 0; background-color: rgba(255,255,255,.8); z-index: 0; + width: 160px; + height: 137px; } .fav{ @@ -34,8 +36,8 @@ } .thumb{ - width: 160px; - height: 120px; + width: 100%; + height: 80%; background-color: #ccc; -moz-box-shadow: 1px 1px 10px rgba(0,0,0,.3); }