
registerType('Core', (function () { function UndoManager() {} var __super = setSupertypeFromDomain(UndoManager, 'BasicObject', 'Core');

	var debug = false;

// role BasicObject (Core) 

UndoManager.prototype.initFromData = function UndoManager_initFromData(data) {
		
			if (!__super.prototype.initFromData.call(this, data))
				return null;
			
			this.undoStack = [];
			this.redoStack = [];

			this.context.identify(this);

			if (debug) this.initDebugView();
			
			return this;};
		
		
UndoManager.prototype.destroy = function UndoManager_destroy() {
			console.log('destroyed');
			if (debug) debugView.removeFromSuperview();
			__super.prototype.destroy.call(this);};
		

	
	
// role UndoManager 

UndoManager.prototype.registerChange = function UndoManager_registerChange(controller, change) {

			if (this.registrationIsEnabled === false)
				return;
				
			if (change.keyPath && change.keyPath[0] === '$') return;
				
			change.controllerId = controller.persistantID || controller.context.persistantIDForController(controller);
			if (!change.controllerId) {
				console.warn('UndoManager.registerChange(): Controller not found', change);
				return;
			}

			change.context = controller.context;

			if (this.isUndoing !== true) {
				this.undoStack.push(change);
				if (this.redoStack.length !== 0 && this.isRedoing !== true)
					this.redoStack = [];
			}
			else {
				this.redoStack.push(change);
			}

			var um = this;
			
			Object.defineProperty(change, 'title', {
				get: function () {
					if (!this._title) {
					try {
						var controller = um.controllerForChange(this);
						if (controller)
							this._title = controller.readableUndoName(this);
						} catch (err) { alertd(err);}
					}
					return this._title;
				}
			});

			if (debugListView) {
				
				Object.defineProperty(change, 'details', {
					get: function () {
						var controller = um.controllerForChange(this);
						if (controller && controller.readableUndoDetails)
							return this.controllerId+":\n"+controller.readableUndoDetails(this);
					}
				});			
				Object.defineProperty(change, 'buttonTitle', {
					get: function () {
						if (um.undoStack.indexOf(this) !== -1)
							return 'Undo';
						else
							return 'Redo';
					}
				});
	
				Object.defineProperty(change, 'buttonIsDisabled', {
					get: function () {
						return um.canPerformChange(this) === false;
					}
				});
	
				debugListView.reloadData();
				debugListView.scrollToTop();
			
			}
			
			this.context.nativeProxy.sendMessage('registerChange', change.title || '');

			var e = document.createEvent('CustomEvent');
			e.initCustomEvent("registerChange", false, false, change);
			this.dispatchEvent(e);
};
		
		
UndoManager.prototype.undo = function UndoManager_undo() {

			if (!this.canUndo()) {
				this.context.beep();
				return;
			}

			var lastChange = this.undoStack.pop();
			this.undoChange(lastChange);
};
		

UndoManager.prototype.redo = function UndoManager_redo() {

			if (!this.canRedo())
				return;

			var lastChange = this.redoStack.pop();
			this.redoChange(lastChange);
};
		
		
UndoManager.prototype.canUndo = function UndoManager_canUndo() {

			if (this.undoStack.length === 0)
				return false;
			
			return this.canPerformChange(this.undoStack[this.undoStack.length-1]);
};
		
		
UndoManager.prototype.canRedo = function UndoManager_canRedo() {
		
			if (this.redoStack.length === 0)
				return false;

			return this.canPerformChange(this.redoStack[this.redoStack.length-1]);
				};
		
		
UndoManager.prototype.prepare = function UndoManager_prepare() {
			if (debug) this.initDebugView();};
		


		
		
UndoManager.prototype.enableRegistration = function UndoManager_enableRegistration() {
			this.registrationIsEnabled = true;};
		

UndoManager.prototype.disableRegistration = function UndoManager_disableRegistration() {
			this.registrationIsEnabled = false;};
		
		
		Object.defineProperty(UndoManager.prototype, "isUndoing", {
		configurable: true, 
		writable: true});
		

	
	
	Object.defineProperty(UndoManager.prototype, "isUndoingOrRedoing", {
		get: function () { return this.isUndoing || this.isRedoing; }});
	
	
	
	
	
UndoManager.prototype.undoChange = function UndoManager__undoChange(change) {
	
		this.isUndoing = true;
		this.performChange(change);
		this.isUndoing = false;
		
		if (this.debugListView)
			debugListView.reloadData();
	};
	

UndoManager.prototype.redoChange = function UndoManager__redoChange(change) {
	
		this.isRedoing = true;
		this.performChange(change);
		this.isRedoing = false;
		
		if (this.debugListView)
			debugListView.reloadData();
	};
	
	
UndoManager.prototype.performChange = function UndoManager__performChange(change) {
	
		var e = document.createEvent('CustomEvent');
		e.initCustomEvent("performChange", false, false, change);
		this.dispatchEvent(e);

		var controller = this.controllerForChange(change);
		controller.undoChange(change, this);
};
	
	
UndoManager.prototype.controllerForChange = function UndoManager__controllerForChange(change) {

		var c = change.context.controllerForPersistantID(change.controllerId);
		if (!c) {
			console.warn('UndoManager.controllerForChange(): Controller not found', change);
		}
		return c;
	};
	
	
UndoManager.prototype.canPerformChange = function UndoManager__canPerformChange(change) {

		var controller = this.controllerForChange(change);
		return controller !== undefined;
	};
	
	
	


	

	var debugView, debugListView;

UndoManager.prototype.initDebugView = function UndoManager__initDebugView() {
	
		if (this.context.isOffscreen) return;
		console.log(this.context);
	
		if (debugView) {
			debugView.removeFromSuperview();
		}

		this.initDebugListView();
		
		debugView = createComponentFromDomain("View", "Core.UI", this.context, {
			position: { left: 0, bottom: 0 },
			size: { width: 250, height: 180+50 },
			style: {
				position: 'fixed',
				zIndex: 1000,
				backgroundColor: '#eee',
				outline: '1px solid hsla(0,0%,0%,.2)'
			}})
		;


		debugView.addSubview(debugListView);

		var undoButton = createComponentFromDomain("Button", "Core.UI", this.context, {
			size: { width: 25, height: 21 },
			position: { right: 5+30, top: 5 },
			text: '<',
			buttonStyle: 'default',
			target: this,
			targetMethod: 'undoFromButton'})
		;
		debugView.addSubview(undoButton);

		var redoButton = createComponentFromDomain("Button", "Core.UI", this.context, {
			size: { width: 25, height: 21 },
			position: { right: 5, top: 5 },
			text: '>',
			buttonStyle: 'default',
			target: this,
			targetMethod: 'redoFromButton'})
		;
		debugView.addSubview(redoButton);


		var refreshButton = createComponentFromDomain("Button", "Core.UI", this.context, {
			size: { width: 25, height: 21 },
			position: { left: 5, top: 5 },
			text: '↻',
			buttonStyle: 'default',
			target: this,
			targetMethod: 'refreshDebugList'})
		;
		debugView.addSubview(refreshButton);
		
		document.body.appendChild(debugView.DOMNode);
		debugView.removeFromSuperview = function () {
			if (this.DOMNode && this.DOMNode.parentNode) {
				this.DOMNode.parentNode.removeChild(this.DOMNode);
				this.destroy();
			}
			debugView = null;
		};
};
	
	
UndoManager.prototype.initDebugListView = function UndoManager__initDebugListView() {

		var ds = this,
			lv = createComponentFromDomain("ListView", "Core.UI", this.context, {
			size: { width: 250, height: 150-2+50 },
			position: { top: 32 },
			style: {
				backgroundColor: 'white',
			},
			cellPrototypeData: {
				$type: 'View',
				$domain: 'Core.UI',
				size: { width: 250, height: 128-30 },
				subviews: [
					{
						$type: 'Label',
						$domain: 'Core.UI',
						size: { width: 230, height: 30 },
						position: { left: 10, top: 10 },
						bindings: [
							{
								sourceKeyPath: 'text',
								destination: ds.$id,
								destinationKeyPath: 'title',
								enumerableItemAccess: true
							}
						]
					},
					{
						$type: 'Label',
						$domain: 'Core.UI',
						size: { width: 200, height: 140-30 },
						position: { left: 10, top: 30 },
						style: { fontSize: '10px', wordWrap: 'break-word' },
						bindings: [
							{
								sourceKeyPath: 'text',
								destination: ds.$id+'[]',
								destinationKeyPath: 'details',
								enumerableItemAccess: true
							}
						]
					},
					{
						$type: 'Button',
						$domain: 'Core.UI',
						size: { width: 80, height: 19 },
						position: { left: 250-80-10, top: 10 },
						buttonStyle: 'default',
						text: 'Undo',
						target: this,
						targetMethod: 'undoFromDebugList',
						bindings: [
							{
								sourceKeyPath: 'text',
								destination: ds.$id,
								destinationKeyPath: 'buttonTitle',
								enumerableItemAccess: true
							},
							{
								sourceKeyPath: 'disabled',
								destination: ds.$id,
								destinationKeyPath: 'buttonIsDisabled',
								enumerableItemAccess: true
							}
						]
					}
				]
			},
			dataSource: this})
		;

		lv.viewIsLoaded = true;
		lv.reloadData();
		
		debugListView = lv;
	};
	

UndoManager.prototype.undoFromDebugList = function UndoManager__undoFromDebugList(button) {

		var indexPath = button.superview.superview.indexPath,
			rowIndex = button.superview.superview.indexPath.item,
			isRedo = indexPath.section === 1,
			stack = isRedo ? this.redoStack : this.undoStack,
			changeIndex = stack.length-1-rowIndex,
			change = stack[changeIndex];
		
		stack.splice(changeIndex, 1);

		if (isRedo)
			this.redoChange(change);
		else
			this.undoChange(change);
};
	
	
UndoManager.prototype.refreshDebugList = function UndoManager__refreshDebugList(button) {
		debugListView.reloadData();};
	
	
UndoManager.prototype.undoFromButton = function UndoManager__undoFromButton() {
		this.context.nativeProxy.sendMessage('undo');};
	

UndoManager.prototype.redoFromButton = function UndoManager__redoFromButton() {
		this.context.nativeProxy.sendMessage('redo');};
	


	

// role ListViewDataSource (Core.UI) 
	
UndoManager.prototype.numberOfItemsInSection = function UndoManager_numberOfItemsInSection(sectionIndex) {
			if (sectionIndex === 0)
				return this.undoStack.length;
			if (sectionIndex === 1)
				return this.redoStack.length;};
		
		
UndoManager.prototype.dataForItemInSectionAtIndex = function UndoManager_dataForItemInSectionAtIndex(sectionIndex, rowIndex) {
			if (sectionIndex === 0) {
				return this.undoStack[this.undoStack.length-1-rowIndex];
			}
			if (sectionIndex === 1) {
				return this.redoStack[this.redoStack.length-1-rowIndex];
			}};
		
		
UndoManager.prototype.numberOfSections = function UndoManager_numberOfSections() {
			return 2;};
		
		
UndoManager.prototype.addObserver = function UndoManager_addObserver(listView) {
		};
		

UndoManager.prototype.removeObserver = function UndoManager_removeObserver(listView) {
		};
		
		
UndoManager.prototype.titleForHeaderInSection = function UndoManager_titleForHeaderInSection(sectionIndex) {
			if (sectionIndex === 0)
				return 'Undo';
			if (sectionIndex === 1)
				return 'Redo';};
		
	
	
	

UndoManager.prototype.expectedTypeForProperty = function UndoManager_expectedTypeForProperty(key) {
	if (key === "isUndoing") return "";
	if (key === "isUndoingOrRedoing") return "Boolean";
	if (__super) return __super.prototype.expectedTypeForProperty(key);
};

return UndoManager; }()));