<commit_before>/*
 * Paper.js
 *
 * This file is part of Paper.js, a JavaScript Vector Graphics Library,
 * based on Scriptographer.org and designed to be largely API compatible.
 * http://paperjs.org/
 * http://scriptographer.org/
 *
 * Copyright (c) 2011, <NAME> & <NAME>
 * http://lehni.org/ & http://jonathanpuckey.com/
 *
 * Distributed under the MIT license. See LICENSE file for details.
 *
 * All rights reserved.
 */

/**
 * @name View
 *
 * @class The View object wraps a canvas element and handles drawing and user
 * interaction through mouse and keyboard for it. It offer means to scroll the
 * view, find the currently visible bounds in project coordinates, or the
 * center, both useful for constructing artwork that should appear centered on
 * screen.
 */
var View = this.View = PaperScopeItem.extend(/** @lends View# */{
	_list: 'views',
	_reference: 'view',

	/**
	 * Creates a view object
	 * @param {HTMLCanvasElement|String} canvas The canvas object that this
	 * view should wrap, or the String id that represents it
	 */
	initialize: function(canvas) {
		this.base();
		// Handle canvas argument
		var size;

/*#*/ if (options.server) {
		if (canvas && canvas instanceof Canvas) {
			this._canvas = canvas;
			size = Size.create(canvas.width, canvas.height);
		} else {
			// 2nd argument onwards could be view size, otherwise use default:
			size = Size.read(arguments, 1);
			if (size.isZero())
				size = new Size(1024, 768);
			this._canvas = CanvasProvider.getCanvas(size);
		}

		// Generate an id for this view / canvas if it does not have one
		this._id = this._canvas.id;
		if (this._id == null)
			this._canvas.id = this._id = 'canvas-' + View._id++;
/*#*/ } // options.server

/*#*/ if (options.browser) {
		if (typeof canvas === 'string')
			canvas = document.getElementById(canvas);
		if (canvas instanceof HTMLCanvasElement) {
			this._canvas = 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 (PaperScript.hasAttribute(canvas, 'resize')) {
				// Subtract canvas' viewport offset from the total size, to
				// stretch it in
				var offset = DomElement.getOffset(canvas, true),
					that = this;
				size = DomElement.getViewportBounds(canvas)
						.getSize().subtract(offset);
				canvas.width = size.width;
				canvas.height = size.height;
				DomEvent.add(window, {
					resize: function(event) {
						// Only update canvas offset if it's not invisible, as
						// otherwise the offset would be wrong.
						if (!DomElement.isInvisible(canvas))
							offset = DomElement.getOffset(canvas, true);
						// Set the size now, which internally calls onResize
						// and redraws the view
						that.setViewSize(DomElement.getViewportBounds(canvas)
								.getSize().subtract(offset));
					}
				});
			} else {
				size = DomElement.isInvisible(canvas)
					? Size.create(parseInt(canvas.getAttribute('width')),
							parseInt(canvas.getAttribute('height')))
					: DomElement.getSize(canvas);
			}
			// TODO: Test this on IE:
			if (PaperScript.hasAttribute(canvas, 'stats')) {
				this._stats = new Stats();
				// Align top-left to the canvas
				var element = this._stats.domElement,
					style = element.style,
					offset = DomElement.getOffset(canvas);
				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:
			size = Size.read(arguments, 1);
			if (size.isZero())
				size = new Size(1024, 768);
			this._canvas = CanvasProvider.getCanvas(size);
		}
		// Generate an id for this view / canvas if it does not have one
		this._id = this._canvas.getAttribute('id');
		if (this._id == null)
			this._canvas.setAttribute('id', this._id = 'canvas-' + View._id++);
/*#*/ } // options.browser

		// Link this id to our view
		View._views[this._id] = this;
		this._viewSize = LinkedSize.create(this, 'setViewSize',
				size.width, size.height);
		this._context = this._canvas.getContext('2d');
		this._matrix = new Matrix();
		this._zoom = 1;

/*#*/ if (options.browser) {
		this._events = this._createEvents();
		DomEvent.add(this._canvas, this._events);
		// Make sure the first view is focused for keyboard input straight away
		if (!View._focused)
			View._focused = this;
/*#*/ } // options.browser

		// As soon as a new view is added we need to mark the redraw as not
		// motified, so the next call loops through all the views again.
		this._scope._redrawNotified = false;
	},

	/**
	 * Makes this view the active one, meaning {@link PaperScope#view} will
	 * point to it.
	 *
	 * @name View#activate
	 * @function
	 */

 	/**
	 * Removes thsi view from the {@link PaperScope#views} list and frees the
	 * associated canvas.
	 */
	remove: function() {
		if (!this.base())
			return false;
		// Clear focus if removed view had it
		if (View._focused == this)
			View._focused = null;
		delete View._views[this._id];
		// Uninstall event handlers again for this view.
		DomEvent.remove(this._canvas, this._events);
		// Clearing _onFrame makes the frame handler stop automatically.
		this._canvas = this._events = this._onFrame = null;
		return true;
	},

	_redraw: function() {
		if (this._onFrameCallback) {
			// If there's a _onFrameCallback, call it staight away,
			// but without requesting another animation frame.
			this._onFrameCallback(0, true);
		} else {
			// Otherwise simply redraw the view now
			this.draw(true);
		}
	},

	_transform: function(matrix, flags) {
		this._matrix.preConcatenate(matrix);
		// Force recalculation of these values next time they are requested.
		this._bounds = null;
		this._inverse = null;
		this._redraw();
	},

	/**
	 * The underlying native canvas element.
	 *
	 * @type HTMLCanvasElement
	 * @bean
	 */
	getCanvas: function() {
		return this._canvas;
	},

	/**
	 * The size of the view canvas. Changing the view's size will resize it's
	 * underlying canvas.
	 *
	 * @type Size<commit_msg>Have View#_redraw() properly redraw the content even if nothing has changed inside.<commit_after>/*
 * Paper.js
 *
 * This file is part of Paper.js, a JavaScript Vector Graphics Library,
 * based on Scriptographer.org and designed to be largely API compatible.
 * http://paperjs.org/
 * http://scriptographer.org/
 *
 * Copyright (c) 2011, <NAME> & <NAME>
 * http://lehni.org/ & http://jonathanpuckey.com/
 *
 * Distributed under the MIT license. See LICENSE file for details.
 *
 * All rights reserved.
 */

/**
 * @name View
 *
 * @class The View object wraps a canvas element and handles drawing and user
 * interaction through mouse and keyboard for it. It offer means to scroll the
 * view, find the currently visible bounds in project coordinates, or the
 * center, both useful for constructing artwork that should appear centered on
 * screen.
 */
var View = this.View = PaperScopeItem.extend(/** @lends View# */{
	_list: 'views',
	_reference: 'view',

	/**
	 * Creates a view object
	 * @param {HTMLCanvasElement|String} canvas The canvas object that this
	 * view should wrap, or the String id that represents it
	 */
	initialize: function(canvas) {
		this.base();
		// Handle canvas argument
		var size;

/*#*/ if (options.server) {
		if (canvas && canvas instanceof Canvas) {
			this._canvas = canvas;
			size = Size.create(canvas.width, canvas.height);
		} else {
			// 2nd argument onwards could be view size, otherwise use default:
			size = Size.read(arguments, 1);
			if (size.isZero())
				size = new Size(1024, 768);
			this._canvas = CanvasProvider.getCanvas(size);
		}

		// Generate an id for this view / canvas if it does not have one
		this._id = this._canvas.id;
		if (this._id == null)
			this._canvas.id = this._id = 'canvas-' + View._id++;
/*#*/ } // options.server

/*#*/ if (options.browser) {
		if (typeof canvas === 'string')
			canvas = document.getElementById(canvas);
		if (canvas instanceof HTMLCanvasElement) {
			this._canvas = 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 (PaperScript.hasAttribute(canvas, 'resize')) {
				// Subtract canvas' viewport offset from the total size, to
				// stretch it in
				var offset = DomElement.getOffset(canvas, true),
					that = this;
				size = DomElement.getViewportBounds(canvas)
						.getSize().subtract(offset);
				canvas.width = size.width;
				canvas.height = size.height;
				DomEvent.add(window, {
					resize: function(event) {
						// Only update canvas offset if it's not invisible, as
						// otherwise the offset would be wrong.
						if (!DomElement.isInvisible(canvas))
							offset = DomElement.getOffset(canvas, true);
						// Set the size now, which internally calls onResize
						// and redraws the view
						that.setViewSize(DomElement.getViewportBounds(canvas)
								.getSize().subtract(offset));
					}
				});
			} else {
				size = DomElement.isInvisible(canvas)
					? Size.create(parseInt(canvas.getAttribute('width')),
							parseInt(canvas.getAttribute('height')))
					: DomElement.getSize(canvas);
			}
			// TODO: Test this on IE:
			if (PaperScript.hasAttribute(canvas, 'stats')) {
				this._stats = new Stats();
				// Align top-left to the canvas
				var element = this._stats.domElement,
					style = element.style,
					offset = DomElement.getOffset(canvas);
				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:
			size = Size.read(arguments, 1);
			if (size.isZero())
				size = new Size(1024, 768);
			this._canvas = CanvasProvider.getCanvas(size);
		}
		// Generate an id for this view / canvas if it does not have one
		this._id = this._canvas.getAttribute('id');
		if (this._id == null)
			this._canvas.setAttribute('id', this._id = 'canvas-' + View._id++);
/*#*/ } // options.browser

		// Link this id to our view
		View._views[this._id] = this;
		this._viewSize = LinkedSize.create(this, 'setViewSize',
				size.width, size.height);
		this._context = this._canvas.getContext('2d');
		this._matrix = new Matrix();
		this._zoom = 1;

/*#*/ if (options.browser) {
		this._events = this._createEvents();
		DomEvent.add(this._canvas, this._events);
		// Make sure the first view is focused for keyboard input straight away
		if (!View._focused)
			View._focused = this;
/*#*/ } // options.browser

		// As soon as a new view is added we need to mark the redraw as not
		// motified, so the next call loops through all the views again.
		this._scope._redrawNotified = false;
	},

	/**
	 * Makes this view the active one, meaning {@link PaperScope#view} will
	 * point to it.
	 *
	 * @name View#activate
	 * @function
	 */

 	/**
	 * Removes thsi view from the {@link PaperScope#views} list and frees the
	 * associated canvas.
	 */
	remove: function() {
		if (!this.base())
			return false;
		// Clear focus if removed view had it
		if (View._focused == this)
			View._focused = null;
		delete View._views[this._id];
		// Uninstall event handlers again for this view.
		DomEvent.remove(this._canvas, this._events);
		// Clearing _onFrame makes the frame handler stop automatically.
		this._canvas = this._events = this._onFrame = null;
		return true;
	},

	_redraw: function() {
		this._redrawNeeded = true;
		if (this._onFrameCallback) {
			// If there's a _onFrameCallback, call it staight away,
			// but without requesting another animation frame.
			this._onFrameCallback(0, true);
		} else {
			// Otherwise simply redraw the view now
			this.draw();
		}
	},

	_transform: function(matrix, flags) {
		this._matrix.preConcatenate(matrix);
		// Force recalculation of these values next time they are requested.
		this._bounds = null;
		this._inverse = null;
		this._redraw();
	},

	/**
	 * The underlying native canvas element.
	 *
	 * @type HTMLCanvasElement
	 * @bean
	 */
	getCanvas: function() {
		return this._canvas;
	},

	/**
	 * The size of the view canvas. Changing the view's size will resize it's
	 * underlying canvas.
	 *
	 * @type Size
{'fraction_non_alphanumeric': 0.12396829288224238, 'fraction_numerical': 0.004085968783198496, 'mean_word_length': 3.110849848841115, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1301918', 'n_tokens_mistral': 4270, 'n_tokens_neox': 3622, 'n_words': 1210}