1 // ========================================================================== 2 // NodeGraph.NodeGraphDelegate 3 // 4 // License: PaperCube is open source software released under 5 // the MIT License (see license.js) 6 // ========================================================================== 7 8 require('core'); 9 10 /** @class NodeGraph.animator 11 12 This is the NodeGraph delegate controller. Extend this to customize 13 functionality for your NodeGraph. 14 15 @extends SC.Object 16 @author Peter Bergstrom 17 @version 1.0 18 @copyright 2008-2009 Peter Bergström. 19 @static 20 */ 21 22 NodeGraph.NodeGraphDelegate = SC.Object.extend( 23 /** @scope NodeGraph.NodeGraphDelegate */ { 24 25 /** 26 Called by the NodeGraph instance when a mouseDown is triggered. 27 28 @param {DOM Event} evt The mouseDown event. 29 @param {NodeGraph.NodeGraphView} The NodeGraph view. 30 @param guid {String} The guid of the node. 31 */ 32 nodeGraphDidMouseDown: function(evt, view, guid) { 33 // Add customized code here. 34 }, 35 36 /** 37 Allow for additional customized setup of the NodeGraph view. 38 39 @param {NodeGraph.NodeGraphView} nodeGraph The NodeGraph instance. 40 */ 41 finishInitForGraph: function(nodeGraph) { 42 // Add customized code here. 43 }, 44 45 /** 46 This left pixel offset for the view. 47 48 @property {Integer} 49 @default 0 50 */ 51 leftOffset: 0, 52 53 /** 54 This top pixel offset for the view. 55 56 @property {Integer} 57 @default 0 58 */ 59 topOffset: 0, 60 61 /** 62 This bottom pixel offset for the view. 63 64 @property {Integer} 65 @default 0 66 */ 67 bottomOffset: 0, 68 69 /** 70 This right pixel offset for the view. 71 72 @property {Integer} 73 @default 0 74 */ 75 rightOffset: 0, 76 77 /** 78 This is the default zoom value, 1 means that it is 1x zoom 79 80 @property {Integer} 81 @default 1 82 */ 83 zoomValue: 1, 84 85 /** 86 This is the zoom step value of the slider. 87 88 @property {Integer} 89 @default 1 90 */ 91 zoomStep: 1, 92 93 /** 94 Min zoom value. 95 96 @property {Integer} 97 @default 1 98 */ 99 zoomValueMin: 1, 100 101 /** 102 Max zoom value. 103 104 @property {Integer} 105 @default 30 106 */ 107 zoomValueMax: 30, 108 109 /** 110 boolean signifying that one is zoomed in. 111 112 @property {Boolean} 113 @default NO 114 */ 115 isZooming: NO, 116 117 /** 118 Canvas dimension height, the canvas is the underlying view. 119 120 @property {Integer} 121 @default 0px 122 */ 123 canvasHeight: 0, 124 125 /** 126 Canvas dimension width, the canvas is the underlying view. 127 128 @property {Integer} 129 @default 0px 130 */ 131 canvasWidth: 0, 132 133 /** 134 Canvas dimension top, the canvas is the underlying view. 135 136 @property {Integer} 137 @default 0px 138 */ 139 canvasTop: 0, 140 141 /** 142 Canvas dimension left, the canvas is the underlying view. 143 144 @property {Integer} 145 @default 0px 146 */ 147 canvasLeft: 0, 148 149 /** 150 Portal dimension height, the portal is the "mask" of the canvas. 151 152 @property {Integer} 153 @default 0px 154 */ 155 portalHeight: 0, 156 157 /** 158 Portal dimension width, the portal is the "mask" of the canvas. 159 160 @property {Integer} 161 @default 0px 162 */ 163 portalWidth: 0, 164 165 /** 166 x-axis offet percentage, this is used to position the canvas inside the portal. 167 168 @property {Integer} 169 @default 0.5 170 */ 171 percentageX: 0.5, 172 173 /** 174 y-axis offet percentage, this is used to position the canvas inside the portal. 175 176 @property {Integer} 177 @default 0.5 178 */ 179 percentageY: 0.5, 180 181 /** 182 Properties that are bound to the views. 183 184 Values 185 { 186 height: 0, 187 width: 0, 188 left: 0, 189 top: 0, 190 zoomValue: 0, 191 portalWidth: 0, 192 portalHeight: 0 193 } 194 195 @property {Object} 196 */ 197 displayProperties: { 198 height: 0, 199 width: 0, 200 left: 0, 201 top: 0, 202 zoomValue: 0, 203 portalWidth: 0, 204 portalHeight: 0 205 }, 206 207 /** 208 The scroll zoom cool off. Record scroll time to compare 209 with the _scrollCoolDownAmount. 210 211 @property {Integer} 212 */ 213 _scrollCoolDown: 0, 214 215 /** 216 The amount to wait between scroll zoom events. 217 218 @property {Integer} 219 @default 200 milliseconds 220 */ 221 _scrollCoolDownAmount: 200, 222 223 /** 224 Zoom out to the min value. 225 */ 226 zoomOutFull: function() 227 { 228 this.set("zoomValue", this.get('zoomValueMin')); 229 }, 230 231 /** 232 Zoom out towards the min value. 233 */ 234 zoomOut: function() 235 { 236 this.set('zoomValue', Math.max(this.get('zoomValueMin'), (this.get('zoomValue')-this.get('zoomStep')))); 237 }, 238 239 /** 240 Zoom in towards the max value. 241 */ 242 zoomIn: function() 243 { 244 this.set('zoomValue', Math.min(this.get('zoomValueMax'), (this.get('zoomValue')+this.get('zoomStep')))); 245 }, 246 247 /** 248 When scolling, call this function to zoom in or out. 249 250 If there was a scroll event within the time period specified by the _scrollCoolDownAmount variable, then 251 don't do anything. 252 253 @param {DOM Event} evt The scroll event. 254 */ 255 scrollZoom: function(evt) 256 { 257 // Check if the scroll event is within the cool down time, return. 258 if((Date.now()-this._scrollCoolDown) < this._scrollCoolDownAmount) return; 259 260 // Save a new cool down time. 261 this._scrollCoolDown = Date.now(); 262 263 // Zoom in or out to the pointer location. 264 this.setZoomToPointerLocation(Event.pointerX(evt), Event.pointerY(evt), ((evt.detail ? evt.detail * -1 : evt.wheelDelta) > 0)); 265 }, 266 267 /** 268 Zoom in or out to center around where the pointer location. 269 270 @param xPos {Integer} The x position of the mouse pointer. 271 @param yPos {Integer} The y position of the mouse pointer. 272 @param zoomIn {boolean} If YES, zoom in, otherwise, zoom out. 273 274 @returns {Boolean} Returns NO if there is an error. 275 */ 276 setZoomToPointerLocation: function(xPos,yPos, zoomIn) 277 { 278 // Calculate the direction (-/+) the zoom step. 279 var zoomStep = zoomIn ? this.zoomStep : -this.zoomStep; 280 281 // Calculate the desired zoomValue. 282 var zoomValue = this.zoomValue+zoomStep; 283 284 // If the zoomValue is smaller or larger then the limits or the left view is visible, bail. 285 if(zoomValue < this.zoomValueMin || zoomValue > this.zoomValueMax || this.leftViewShowing) 286 { 287 return NO; 288 } 289 290 this.set("zoomValue", zoomValue); 291 }, 292 293 /** 294 Zoom to a set of coordinates. 295 296 @param xDiff {Integer} The x position of the mouse pointer. 297 @param yDiff {Integer} The y position of the mouse pointer. 298 299 @returns {Boolean} Returns NO if there is an error. 300 */ 301 panToCoordinates: function(xDiff, yDiff) 302 { 303 304 var zoomValue = this.get('zoomValue'); 305 306 // If the zoomValue is equal to the zoomValueMin, bail. 307 if(zoomValue === this.zoomValueMin) 308 { 309 return NO; 310 } 311 312 // Calculate the x and y offsets and set it back to the zoomView. 313 var xPos = this.percentageX*this.canvasWidth-xDiff; 314 var yPos = this.percentageY*this.canvasHeight-yDiff; 315 316 var pctX = Math.max(1- (this.canvasWidth-xPos)/this.canvasWidth,0); 317 var pctY = Math.max(1- (this.canvasHeight-yPos)/this.canvasHeight,0); 318 319 this.set("percentageX", pctX); 320 this.set("percentageY", pctY); 321 }, 322 323 /** 324 Zoom in or out to center around a desired x and y percentage. 325 326 @param pctX {Integer} The x position percentage. 327 @param pctY {Integer} The y position percentage. 328 @param zoomValue {Integer} The desired zoomValue. 329 330 @returns {Boolean} Returns NO if there is an error. 331 */ 332 zoomToLocation: function(pctX, pctY, zoomValue) 333 { 334 // If the zoomValue is smaller or larger then the limits, bail. 335 if(zoomValue < this.zoomValueMin || zoomValue > this.zoomValueMax) 336 { 337 return NO; 338 } 339 340 this.beginPropertyChanges(); 341 this.set("zoomValue", zoomValue); 342 this.set("percentageX", pctX/2); 343 this.set("percentageY", pctY/2); 344 this.endPropertyChanges(); 345 346 }, 347 348 /** 349 Get window properties and set the portal dimensions then reposition the canvas. 350 */ 351 getWindowProperties: function() 352 { 353 var wH = NodeGraph.windowHeight(); 354 var wW = NodeGraph.windowWidth(); 355 356 this.set("portalHeight", (wH-this.get('topOffset')-this.get('bottomOffset'))); 357 this.set("portalWidth", wW-this.get('leftOffset')-this.get('rightOffset')); 358 this.repositionCanvasDidChange(); 359 }, 360 361 /** 362 Reposition the canvas inside the portal if needed, This is triggered if the percentages or the zoom value changes. 363 364 @observes percentageX 365 @observes percentageY 366 @observes zoomValue 367 */ 368 repositionCanvasDidChange: function() 369 { 370 // Calculate the canvas dimensions based on the portal dimensions and zoom value. 371 this.canvasHeight = parseInt(this.portalHeight*this.zoomValue, 0); 372 this.canvasWidth = parseInt(this.portalWidth*this.zoomValue, 0); 373 374 // Default the top and left to 0. 375 var cTop = 0; 376 var cLeft = 0; 377 378 if(this.zoomValue != this.zoomValueMin) 379 { 380 // Calculate the pixel value of the top and left of the views if the zoom value is not equal to the minimum. 381 var cTop = -(this.percentageY*this.canvasHeight); 382 var cLeft = -(this.percentageX*this.canvasWidth); 383 384 } 385 386 // Set the canvasTop and canvasLeft properties to the calculated values. 387 this.canvasTop = cTop; 388 this.canvasLeft = cLeft; 389 390 // Set the displayProperities that the views will monitor to the newly calculated values. 391 this.set('displayProperties', {height: this.canvasHeight, width: this.canvasWidth, top: this.canvasTop, left: this.canvasLeft, zoomValue: this.zoomValue, portalWidth: this.portalWidth, portalHeight: this.portalHeight}); 392 393 this.set('isZooming', this.get('zoomValue') != 1); 394 395 }.observes('percentageX', 'percentageY', 'zoomValue'), 396 397 /** 398 Initalization function. Create the SVG elements for the fan. 399 */ 400 init: function() 401 { 402 // Set up a resize observer on the window. 403 Event.observe(window, 'resize', this.getWindowProperties.bind(this)); 404 405 // Set up te scroll observer. 406 if(SC.isFireFox()) 407 { 408 Element.observe(document.body, 'DOMMouseScroll', this.scrollZoom.bind(this)); 409 } 410 else 411 { 412 Element.observe(document.body, 'mousewheel', this.scrollZoom.bind(this)); 413 } 414 415 // Set up the basic window properties. 416 this.getWindowProperties(); 417 sc_super(); 418 } 419 });