diff --git a/src/document/Document.js b/src/document/Document.js index 76856ff4..79b1ee58 100644 --- a/src/document/Document.js +++ b/src/document/Document.js @@ -17,87 +17,46 @@ var Document = this.Document = Base.extend({ beans: true, + // XXX: Add arguments to define pages, but do not pass canvas here initialize: function(canvas) { // Store reference to the currently active global paper scope: this._scope = paper; - if (canvas && canvas instanceof HTMLCanvasElement) { - this.canvas = canvas; - if (canvas.attributes.resize) { - // If the canvas has a fullscreen attribute, - // resize the canvas to fill the window and resize it again - // whenever the user resizes the window. - // TODO: set the following styles on the body tag: - // body { - // background: black; - // margin: 0; - // overflow: hidden; - // } - this._size = DomElement.getWindowSize() - .subtract(DomElement.getOffset(this.canvas)); - this.canvas.width = this._size.width; - this.canvas.height = this._size.height; - var that = this; - var offset = DomElement.getOffset(this.canvas); - DomEvent.add(window, { - resize: function(event) { - // Only get canvas offset if it's not invisible (size is - // 0, 0), as otherwise the offset would be wrong. - if (!DomElement.getSize(that.canvas).equals([0, 0])) - offset = DomElement.getOffset(that.canvas); - that.setSize(DomElement.getWindowSize().subtract(offset)); - that.redraw(); - } - }); - } else { - this._size = Size.create(canvas.offsetWidth, - canvas.offsetHeight); - } - } else { - this._size = Size.read(arguments) || new Size(1024, 768); - this.canvas = CanvasProvider.getCanvas(this._size); - } - // TODO: Currently we don't do anything with Document#bounds. - // What does it mean to change the bounds of the document? (JP) - this.bounds = Rectangle.create(0, 0, this._size.width, - this._size.height); - this.context = this.canvas.getContext('2d'); // Push it onto this._scope.documents and set index: this._index = this._scope.documents.push(this) - 1; + // Activate straight away so paper.document is set, as required by + // Layer and DoumentView constructors. this.activate(); this.layers = []; - this.activeLayer = new Layer(); - this.setCurrentStyle(null); + this.views = []; this.symbols = []; - this.activeView = new DocumentView(this); - this.views = [this.activeView]; + this.activeLayer = new Layer(); + this.activeView = canvas ? new DocumentView(canvas) : null; + // XXX: Introduce pages and remove Document#bounds! + var size = this.activeView && this.activeView._size + || new Size(1024, 768); + this._bounds = Rectangle.create(0, 0, size.width, size.height); this._selectedItems = {}; this._selectedItemCount = 0; - // TODO: Test this on IE: - if (this.canvas.attributes.stats) { - this.stats = new Stats(); - // Align top-left to the canvas - var element = this.stats.domElement, - style = element.style, - offset = DomElement.getOffset(this.canvas); - style.position = 'absolute'; - style.left = offset.x + 'px'; - style.top = offset.y + 'px'; - document.body.appendChild(element); - } + this.setCurrentStyle(null); }, - + + getBounds: function() { + // TODO: Consider LinkedRectangle once it is required. + return this._bounds; + }, + + setBounds: function(rect) { + rect = Rectangle.read(arguments); + this._bounds.set(rect.x, rect.y, rect.width, rect.height); + }, + getSize: function() { - return this._size; + return this._bounds.getSize(); }, setSize: function(size) { - size = Size.read(arguments); - if (this.canvas) { - this.canvas.width = size.width; - this.canvas.height = size.height; - } - this._size = size; - this.bounds.setSize(size); + // TODO: Once _bounds is a LinkedRectangle, this will recurse + this._bounds.setSize.apply(this._bounds, arguments); }, getCurrentStyle: function() { @@ -170,39 +129,29 @@ var Document = this.Document = Base.extend({ this._selectedItems[i].setSelected(false); }, - draw: function() { - if (this.canvas) { - if (this.stats) - this.stats.update(); - var ctx = this.context; - - // Initial tests conclude that clearing the canvas using clearRect - // is always faster than setting canvas.width = canvas.width - // http://jsperf.com/clearrect-vs-setting-width/7 - ctx.clearRect(0, 0, this.size.width + 1, this.size.height + 1); + draw: function(ctx) { + ctx.save(); + var param = { offset: new Point(0, 0) }; + for (var i = 0, l = this.layers.length; i < l; i++) + Item.draw(this.layers[i], ctx, param); + ctx.restore(); + // Draw the selection of the selected items in the document: + if (this._selectedItemCount > 0) { ctx.save(); - var param = { offset: new Point(0, 0) }; - for (var i = 0, l = this.layers.length; i < l; i++) - Item.draw(this.layers[i], ctx, param); + ctx.strokeWidth = 1; + // TODO: use Layer#color + ctx.strokeStyle = ctx.fillStyle = '#009dec'; + param = { selection: true }; + Base.each(this._selectedItems, function(item) { + item.draw(ctx, param); + }); ctx.restore(); - - // Draw the selection of the selected items in the document: - if (this._selectedItemCount > 0) { - ctx.save(); - ctx.strokeWidth = 1; - // TODO: use Layer#color - ctx.strokeStyle = ctx.fillStyle = '#009dec'; - param = { selection: true }; - Base.each(this._selectedItems, function(item) { - item.draw(ctx, param); - }); - ctx.restore(); - } } }, redraw: function() { - this.draw(); + for (var i = 0, l = this.views.length; i < l; i++) + this.views[i].draw(); } }); diff --git a/src/document/DocumentView.js b/src/document/DocumentView.js index 6d5d3aee..a5ed9656 100644 --- a/src/document/DocumentView.js +++ b/src/document/DocumentView.js @@ -17,24 +17,86 @@ var DocumentView = this.DocumentView = Base.extend({ beans: true, - initialize: function(document) { - this.document = document; - this._bounds = this.document.bounds.clone(); + // TODO: Add bounds parameter that defines position within canvas? + // Find a good name for these bounds, since #bounds is already the artboard + // bounds of the visible area. + initialize: function(canvas) { + // To go with the convention of never passing document to constructors, + // in all items, associate the view with the currently active document. + this._document = paper.document; + // Push it onto document.views and set index: + this._index = this._document.views.push(this) - 1; + // Handle canvas argument + if (canvas && canvas instanceof HTMLCanvasElement) { + this._canvas = canvas; + var offset = DomElement.getOffset(canvas); + // If the canvas has the resize attribute, resize the it to fill the + // window and resize it again whenever the user resizes the window. + if (canvas.attributes.resize) { + this._size = DomElement.getWindowSize().subtract(offset); + canvas.width = this._size.width; + canvas.height = this._size.height; + var that = this; + DomEvent.add(window, { + resize: function(event) { + // Only get canvas offset if it's not invisible (size is + // 0, 0), as otherwise the offset would be wrong. + if (!DomElement.getSize(canvas).equals([0, 0])) + offset = DomElement.getOffset(canvas); + that.setSize(DomElement.getWindowSize().subtract(offset)); + that.draw(); + } + }); + } else { + this._size = Size.create( + canvas.offsetWidth, canvas.offsetHeight); + } + // TODO: Test this on IE: + if (canvas.attributes.stats) { + this._stats = new Stats(); + // Align top-left to the canvas + var element = this._stats.domElement, + style = element.style; + style.position = 'absolute'; + style.left = offset.x + 'px'; + style.top = offset.y + 'px'; + document.body.appendChild(element); + } + } else { + // 2nd argument onwards could be view size, otherwise use default: + this._size = Size.read(arguments, 1); + if (this._size.isZero()) + this._size = new Size(1024, 768); + this._canvas = CanvasProvider.getCanvas(this._size); + } + this._context = this._canvas.getContext('2d'); this._matrix = new Matrix(); this._zoom = 1; - this._center = this._bounds.center; }, - // TODO: test this. + getDocument: function() { + return this._document; + }, + + getSize: function() { + return LinkedSize.create(this, 'setSize', + this._size.width, this._size.height); + }, + + setSize: function(size) { + this._size = Size.read(arguments); + this._canvas.width = this._size.width; + this._canvas.height = this._size.height; + }, + + getBounds: function() { + return this._bounds; + }, + getCenter: function() { - return this._center; }, setCenter: function(center) { - center = Point.read(arguments); - var delta = center.subtract(this._center); - this.scrollBy(delta); - this._center = center; }, getZoom: function() { @@ -42,7 +104,7 @@ var DocumentView = this.DocumentView = Base.extend({ }, setZoom: function(zoom) { - // TODO: clamp the view between 1/32 and 64? + // TODO: Clamp the view between 1/32 and 64, just like Illustrator? var mx = new Matrix(); mx.scale(zoom / this._zoom, this._center); this.transform(mx); @@ -50,8 +112,29 @@ var DocumentView = this.DocumentView = Base.extend({ }, scrollBy: function(point) { - point = Point.read(arguments); - this.transform(new Matrix().translate(point.negate())); + this.transform(new Matrix().translate(Point.read(arguments).negate())); + }, + + draw: function() { + if (this._stats) + this._stats.update(); + + // Initial tests conclude that clearing the canvas using clearRect + // is always faster than setting canvas.width = canvas.width + // http://jsperf.com/clearrect-vs-setting-width/7 + this._context.clearRect(0, 0, this._size.width + 1, this._size.height + 1); + + this._document.draw(this._context); + }, + + activate: function() { + this._document.activeView = this; + }, + + remove: function() { + var res = Base.splice(this._document.views, null, this._index, 1); + this._document = null; + return !!res.length; }, transform: function(matrix, flags) { @@ -61,24 +144,11 @@ var DocumentView = this.DocumentView = Base.extend({ }, _getInverse: function() { - if (!this._inverse) { + if (!this._inverse) this._inverse = this._matrix.createInverse(); - } return this._inverse; }, - getBounds: function() { - if (!this._bounds) { - this._bounds = this._matrix.transformBounds(this.document.bounds); - } - return this._bounds; - }, - - // TODO: - // setBounds: function(rect) { - // - // }, - // TODO: getInvalidBounds // TODO: invalidate(rect) // TODO: style: artwork / preview / raster / opaque / ink diff --git a/src/tool/Tool.js b/src/tool/Tool.js index 3febffc0..4feafc5c 100644 --- a/src/tool/Tool.js +++ b/src/tool/Tool.js @@ -98,7 +98,7 @@ var Tool = this.Tool = ToolHandler.extend(new function() { } }; - DomEvent.add(doc.canvas, events); + DomEvent.add(doc.activeView._canvas, events); }, getDocument: function() {