| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 'use strict'; | 5 'use strict'; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * @fileoverview Interactive visualizaiton of TimelineModel objects | 8 * @fileoverview Interactive visualizaiton of TimelineModel objects |
| 9 * based loosely on gantt charts. Each thread in the TimelineModel is given a | 9 * based loosely on gantt charts. Each thread in the TimelineModel is given a |
| 10 * set of TimelineTracks, one per subrow in the thread. The Timeline class | 10 * set of TimelineTracks, one per subrow in the thread. The Timeline class |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 187 this.panX = (viewX / this.scaleX_) - worldX; | 187 this.panX = (viewX / this.scaleX_) - worldX; |
| 188 }, | 188 }, |
| 189 | 189 |
| 190 xPanWorldRangeIntoView: function(worldMin, worldMax, viewWidth) { | 190 xPanWorldRangeIntoView: function(worldMin, worldMax, viewWidth) { |
| 191 if (this.xWorldToView(worldMin) < 0) | 191 if (this.xWorldToView(worldMin) < 0) |
| 192 this.xPanWorldPosToViewPos(worldMin, 'left', viewWidth); | 192 this.xPanWorldPosToViewPos(worldMin, 'left', viewWidth); |
| 193 else if (this.xWorldToView(worldMax) > viewWidth) | 193 else if (this.xWorldToView(worldMax) > viewWidth) |
| 194 this.xPanWorldPosToViewPos(worldMax, 'right', viewWidth); | 194 this.xPanWorldPosToViewPos(worldMax, 'right', viewWidth); |
| 195 }, | 195 }, |
| 196 | 196 |
| 197 xSetWorldRange: function(worldMin, worldMax, viewWidth) { |
| 198 var worldRange = worldMax - worldMin; |
| 199 var scaleX = viewWidth / worldRange; |
| 200 var panX = -worldMin; |
| 201 this.setPanAndScale(panX, scaleX); |
| 202 }, |
| 203 |
| 197 get gridEnabled() { | 204 get gridEnabled() { |
| 198 return this.gridEnabled_; | 205 return this.gridEnabled_; |
| 199 }, | 206 }, |
| 200 | 207 |
| 201 set gridEnabled(enabled) { | 208 set gridEnabled(enabled) { |
| 202 if (this.gridEnabled_ == enabled) | 209 if (this.gridEnabled_ == enabled) |
| 203 return; | 210 return; |
| 204 this.gridEnabled_ = enabled && true; | 211 this.gridEnabled_ = enabled && true; |
| 205 this.dispatchChangeEvent(); | 212 this.dispatchChangeEvent(); |
| 206 }, | 213 }, |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 408 track.tooltip = thread.userFriendlyDetails; | 415 track.tooltip = thread.userFriendlyDetails; |
| 409 track.headingWidth = maxHeadingWidth; | 416 track.headingWidth = maxHeadingWidth; |
| 410 track.viewport = this.viewport_; | 417 track.viewport = this.viewport_; |
| 411 track.thread = thread; | 418 track.thread = thread; |
| 412 this.tracks_.appendChild(track); | 419 this.tracks_.appendChild(track); |
| 413 }.bind(this)); | 420 }.bind(this)); |
| 414 }.bind(this)); | 421 }.bind(this)); |
| 415 | 422 |
| 416 // Set up a reasonable viewport. | 423 // Set up a reasonable viewport. |
| 417 this.viewport_.setWhenPossible(function() { | 424 this.viewport_.setWhenPossible(function() { |
| 418 var rangeTimestamp = this.model_.maxTimestamp - | |
| 419 this.model_.minTimestamp; | |
| 420 var w = this.firstCanvas.width; | 425 var w = this.firstCanvas.width; |
| 421 var scaleX = w / rangeTimestamp; | 426 this.viewport_.xSetWorldRange(this.model_.minTimestamp, |
| 422 var panX = -this.model_.minTimestamp; | 427 this.model_.maxTimestamp, |
| 423 this.viewport_.setPanAndScale(panX, scaleX); | 428 w); |
| 424 }.bind(this)); | 429 }.bind(this)); |
| 425 }, | 430 }, |
| 426 | 431 |
| 427 /** | 432 /** |
| 433 * @return {Array} An array of objects that match the provided |
| 434 * TimelineFilter. |
| 435 */ |
| 436 findAllObjectsMatchingFilter: function(filter) { |
| 437 var hits = []; |
| 438 for (var i = 0; i < this.tracks_.children.length; ++i) { |
| 439 var trackHits = |
| 440 this.tracks_.children[i].findAllObjectsMatchingFilter(filter); |
| 441 Array.prototype.push.apply(hits, trackHits); |
| 442 } |
| 443 return hits; |
| 444 }, |
| 445 |
| 446 /** |
| 428 * @return {Element} The element whose focused state determines | 447 * @return {Element} The element whose focused state determines |
| 429 * whether to respond to keyboard inputs. | 448 * whether to respond to keyboard inputs. |
| 430 * Defaults to the parent element. | 449 * Defaults to the parent element. |
| 431 */ | 450 */ |
| 432 get focusElement() { | 451 get focusElement() { |
| 433 if (this.focusElement_) | 452 if (this.focusElement_) |
| 434 return this.focusElement_; | 453 return this.focusElement_; |
| 435 return this.parentElement; | 454 return this.parentElement; |
| 436 }, | 455 }, |
| 437 | 456 |
| 438 /** | 457 /** |
| 439 * Sets the element whose focus state will determine whether | 458 * Sets the element whose focus state will determine whether |
| 440 * to respond to keybaord input. | 459 * to respond to keybaord input. |
| 441 */ | 460 */ |
| 442 set focusElement(value) { | 461 set focusElement(value) { |
| 443 this.focusElement_ = value; | 462 this.focusElement_ = value; |
| 444 }, | 463 }, |
| 445 | 464 |
| 446 get listenToKeys_() { | 465 get listenToKeys_() { |
| 466 if (!this.viewport_.isAttachedToDocument_) |
| 467 return false; |
| 447 if (!this.focusElement_) | 468 if (!this.focusElement_) |
| 448 return true; | 469 return true; |
| 449 if (this.focusElement.tabIndex >= 0) | 470 if (this.focusElement.tabIndex >= 0) |
| 450 return document.activeElement == this.focusElement; | 471 return document.activeElement == this.focusElement; |
| 451 return true; | 472 return true; |
| 452 }, | 473 }, |
| 453 | 474 |
| 454 onKeypress_: function(e) { | 475 onKeypress_: function(e) { |
| 455 var vp = this.viewport_; | 476 var vp = this.viewport_; |
| 456 if (!this.firstCanvas) | 477 if (!this.firstCanvas) |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 579 minTime = slice.start; | 600 minTime = slice.start; |
| 580 if (slice.start + slice.duration > maxTime) | 601 if (slice.start + slice.duration > maxTime) |
| 581 maxTime = slice.start + slice.duration; | 602 maxTime = slice.start + slice.duration; |
| 582 } | 603 } |
| 583 } | 604 } |
| 584 if (selection.length == 0) { | 605 if (selection.length == 0) { |
| 585 // Nothing adjoining was found; leave the current selection. | 606 // Nothing adjoining was found; leave the current selection. |
| 586 return false; | 607 return false; |
| 587 } | 608 } |
| 588 this.selection = selection; | 609 this.selection = selection; |
| 610 |
| 589 // Potentially move the viewport to keep the new selection in view. | 611 // Potentially move the viewport to keep the new selection in view. |
| 590 this.viewport_.xPanWorldRangeIntoView(minTime, maxTime, | 612 this.viewport_.xPanWorldRangeIntoView(minTime, maxTime, |
| 591 this.firstCanvas.width); | 613 this.firstCanvas.width); |
| 592 return true; | 614 return true; |
| 593 }, | 615 }, |
| 594 | 616 |
| 595 get keyHelp() { | 617 get keyHelp() { |
| 596 var help = 'Keyboard shortcuts:\n' + | 618 var help = 'Keyboard shortcuts:\n' + |
| 597 ' w/s : Zoom in/out (with shift: go faster)\n' + | 619 ' w/s : Zoom in/out (with shift: go faster)\n' + |
| 598 ' a/d : Pan left/right\n' + | 620 ' a/d : Pan left/right\n' + |
| (...skipping 24 matching lines...) Expand all Loading... |
| 623 this.selection_[i].slice.selected = false; | 645 this.selection_[i].slice.selected = false; |
| 624 | 646 |
| 625 this.selection_ = selection; | 647 this.selection_ = selection; |
| 626 | 648 |
| 627 cr.dispatchSimpleEvent(this, 'selectionChange'); | 649 cr.dispatchSimpleEvent(this, 'selectionChange'); |
| 628 for (i = 0; i < this.selection_.length; i++) | 650 for (i = 0; i < this.selection_.length; i++) |
| 629 this.selection_[i].slice.selected = true; | 651 this.selection_[i].slice.selected = true; |
| 630 this.viewport_.dispatchChangeEvent(); // Triggers a redraw. | 652 this.viewport_.dispatchChangeEvent(); // Triggers a redraw. |
| 631 }, | 653 }, |
| 632 | 654 |
| 655 getSelectionRange: function() { |
| 656 var wmin = Infinity; |
| 657 var wmax = -wmin; |
| 658 for (var i = 0; i < this.selection_.length; i++) { |
| 659 var hit = this.selection_[i]; |
| 660 if (hit.slice) { |
| 661 wmin = Math.min(wmin, hit.slice.start); |
| 662 wmax = Math.max(wmax, hit.slice.end); |
| 663 } |
| 664 } |
| 665 return { |
| 666 min: wmin, |
| 667 max: wmax |
| 668 }; |
| 669 }, |
| 670 |
| 671 setSelectionAndMakeVisible: function(selection, zoomAllowed) { |
| 672 this.selection = selection; |
| 673 var range = this.getSelectionRange(); |
| 674 var size = this.viewport_.xWorldVectorToView(range.max - range.min); |
| 675 if (zoomAllowed && size < 50) { |
| 676 var worldCenter = range.min + (range.max - range.min) * 0.5; |
| 677 var worldRange = (range.max - range.min) * 5; |
| 678 this.viewport_.xSetWorldRange(worldCenter - worldRange * 0.5, |
| 679 worldCenter + worldRange * 0.5, |
| 680 this.firstCanvas.width); |
| 681 return; |
| 682 } |
| 683 |
| 684 this.viewport_.xPanWorldRangeIntoView(range.min, range.max, |
| 685 this.firstCanvas.width); |
| 686 }, |
| 687 |
| 633 get firstCanvas() { | 688 get firstCanvas() { |
| 634 return this.tracks_.firstChild ? | 689 return this.tracks_.firstChild ? |
| 635 this.tracks_.firstChild.firstCanvas : undefined; | 690 this.tracks_.firstChild.firstCanvas : undefined; |
| 636 }, | 691 }, |
| 637 | 692 |
| 638 hideDragBox_: function() { | 693 hideDragBox_: function() { |
| 639 this.dragBox_.style.left = '-1000px'; | 694 this.dragBox_.style.left = '-1000px'; |
| 640 this.dragBox_.style.top = '-1000px'; | 695 this.dragBox_.style.top = '-1000px'; |
| 641 this.dragBox_.style.width = 0; | 696 this.dragBox_.style.width = 0; |
| 642 this.dragBox_.style.height = 0; | 697 this.dragBox_.style.height = 0; |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 785 * The TimelineModel being viewed by the timeline | 840 * The TimelineModel being viewed by the timeline |
| 786 * @type {TimelineModel} | 841 * @type {TimelineModel} |
| 787 */ | 842 */ |
| 788 cr.defineProperty(Timeline, 'model', cr.PropertyKind.JS); | 843 cr.defineProperty(Timeline, 'model', cr.PropertyKind.JS); |
| 789 | 844 |
| 790 return { | 845 return { |
| 791 Timeline: Timeline, | 846 Timeline: Timeline, |
| 792 TimelineViewport: TimelineViewport | 847 TimelineViewport: TimelineViewport |
| 793 }; | 848 }; |
| 794 }); | 849 }); |
| OLD | NEW |