1 define([ 2 'jquery', 3 'underscore', 4 'three' 5 ], function($, _, THREE) { 6 /** 7 * 8 * @class EmperorViewControllerABC 9 * 10 * Initializes an abstract tab. This has to be contained in a DOM object and 11 * will use the full size of that container. The title represents the title 12 * of the jQuery tab. The description will be used as help text to describe 13 * the functionality of each subclass tab. 14 * 15 * @param {UIState} uiState the shared state object 16 * @param {Node} container Container node to create the controller in. 17 * @param {String} title Title of the tab. 18 * @param {String} description Helper description. 19 * 20 * @return {EmperorViewControllerABC} Returns an instance of the 21 * EmperorViewControllerABC. 22 * @constructs EmperorViewControllerABC 23 * 24 */ 25 function EmperorViewControllerABC(uiState, container, title, description) { 26 THREE.EventDispatcher.call(this); 27 28 /** 29 * @type {UIState} 30 * The shared state 31 */ 32 this.UIState = uiState; 33 34 /** 35 * @type {Node} 36 * jQuery element for the parent container. 37 */ 38 this.$container = $(container); 39 /** 40 * @type {String} 41 * Human-readable title of the tab. 42 */ 43 this.title = title; 44 /** 45 * @type {String} 46 * Human-readable description of the tab. 47 */ 48 this.description = description; 49 50 /** 51 * @type {Node} 52 * jQuery element for the canvas, which contains the header and the body. 53 */ 54 this.$canvas = null; 55 /** 56 * @type {Node} 57 * jQuery element for the body, which contains the lowermost elements 58 * displayed in tab. This goes below the header. 59 */ 60 this.$body = null; 61 /** 62 * @type {Node} 63 * jQuery element for the header which contains the uppermost elements 64 * displayed in a tab. 65 */ 66 this.$header = null; 67 /** 68 * @type {Boolean} 69 * Indicates whether the tab is front most 70 * @default false 71 */ 72 this.active = false; 73 /** 74 * @type {String} 75 * Unique hash identifier for the tab instance. 76 * @default "EMPtab-xxxxxxx" 77 */ 78 this.identifier = 'EMPtab-' + Math.round(1000000 * Math.random()); 79 /** 80 * @type {Boolean} 81 * Indicates if tab can be accessed. 82 * @default true 83 */ 84 this.enabled = true; 85 86 if (this.$container.length < 1) { 87 throw new Error('Emperor requires a valid container, ' + 88 this.$container + ' does not exist in the DOM.'); 89 } 90 91 // the canvas contains both the header and the body, note that for all 92 // these divs the width should be 100% (whatever we have available), but 93 // the height is much trickier, see the resize method for more information 94 this.$canvas = $('<div name="emperor-view-controller-canvas"></div>'); 95 this.$canvas.width('100%'); 96 this.$container.append(this.$canvas); 97 98 this.$canvas.width(this.$container.width()); 99 this.$canvas.height(this.$container.height()); 100 101 // the margin and width properties are set this way to center all the 102 // contents of the divs themselves, see this SO answer: 103 // http://stackoverflow.com/a/114549 104 this.$header = $('<div name="emperor-view-controller-header"></div>'); 105 this.$header.css('margin', '0 auto'); 106 this.$header.css('width', '100%'); 107 108 this.$body = $('<div name="emperor-view-controller-body"></div>'); 109 this.$body.css('margin', '0 auto'); 110 this.$body.css('width', '100%'); 111 112 // inherit the size of the container minus the space being used for the 113 // header 114 this.$body.height(this.$canvas.height() - this.$header.height()); 115 this.$body.width(this.$canvas.width()); 116 117 this.$canvas.append(this.$header); 118 this.$canvas.append(this.$body); 119 120 return this; 121 } 122 EmperorViewControllerABC.prototype = Object.create( 123 THREE.EventDispatcher.prototype); 124 EmperorViewControllerABC.prototype.constructor = THREE.EventDispatcher; 125 126 /** 127 * Sets whether or not elements in the tab can be modified. 128 * 129 * @param {Boolean} trulse option to enable elements. 130 */ 131 EmperorViewControllerABC.prototype.setEnabled = function(trulse) { 132 if (typeof(trulse) === 'boolean') { 133 this.enabled = trulse; 134 } 135 else { 136 throw new Error('`trulse` can only be of boolean type'); 137 } 138 }; 139 140 /** 141 * Sets whether or not the tab is visible. 142 * 143 * @param {Boolean} trulse option to activate tab 144 * (i.e. move tab to foreground). 145 */ 146 EmperorViewControllerABC.prototype.setActive = function(trulse) { 147 if (this.enabled === true) { 148 if (typeof(trulse) === 'boolean') { 149 this.active = trulse; 150 } 151 else { 152 throw new Error('`trulse` can only be of boolean type'); 153 } 154 } 155 }; 156 157 /** 158 * Resizes the container, note that the body will take whatever space is 159 * available after considering the size of the header. The header shouldn't 160 * have height variable objects, once added their height shouldn't really 161 * change. 162 * 163 * @param {Float} width the container width. 164 * @param {Float} height the container height. 165 */ 166 EmperorViewControllerABC.prototype.resize = function(width, height) { 167 // This padding is required in order to make space 168 // for the horizontal menus 169 var padding = 10; 170 this.$canvas.height(height); 171 this.$canvas.width(width - padding); 172 173 this.$header.width(width - padding); 174 175 // the body has to account for the size used by the header 176 this.$body.width(width - padding); 177 this.$body.height(height - this.$header.height()); 178 }; 179 180 /** 181 * 182 * Converts the current instance into a JSON string. 183 * 184 * @return {Object} ready to serialize representation of self. 185 */ 186 EmperorViewControllerABC.prototype.toJSON = function() { 187 throw Error('Not implemented'); 188 }; 189 190 /** 191 * Decodes JSON string and modifies its own instance variables accordingly. 192 * 193 * @param {Object} parsed JSON string representation of an instance. 194 */ 195 EmperorViewControllerABC.prototype.fromJSON = function(jsonString) { 196 throw Error('Not implemented'); 197 }; 198 199 /** 200 * Writes the current settings to the active decomposition view(s). 201 * Will be called when the decomposition view is swapped out 202 * for a different view type. 203 */ 204 EmperorViewControllerABC.prototype.forceRefresh = function() { 205 this.fromJSON(this.toJSON()); 206 }; 207 208 return {'EmperorViewControllerABC': EmperorViewControllerABC}; 209 }); 210