1<!DOCTYPE html> 2<!-- 3Copyright (c) 2014 The Chromium Authors. All rights reserved. 4Use of this source code is governed by a BSD-style license that can be 5found in the LICENSE file. 6--> 7 8<link rel="import" href="/tracing/base/range.html"> 9<link rel="import" href="/tracing/ui/side_panel/side_panel.html"> 10<link rel='import' href='/tracing/ui/base/polymer_utils.html'> 11 12<polymer-element name='tr-ui-side-panel-container' is='HTMLUnknownElement'> 13 <template> 14 <style> 15 :host { 16 align-items: stretch; 17 display: -webkit-flex; 18 } 19 20 :host([expanded]) > active-panel-container { 21 -webkit-flex: 1 1 auto; 22 border-left: 1px solid black; 23 display: -webkit-flex; 24 } 25 26 :host(:not([expanded])) > active-panel-container { 27 display: none; 28 } 29 30 active-panel-container { 31 display: flex; 32 } 33 34 tab-strip { 35 -webkit-flex: 0 0 auto; 36 -webkit-flex-direction: column; 37 -webkit-user-select: none; 38 background-color: rgb(236, 236, 236); 39 border-left: 1px solid black; 40 cursor: default; 41 display: -webkit-flex; 42 min-width: 18px; /* workaround for flexbox and writing-mode mixing bug */ 43 padding: 10px 0 10px 0; 44 font-size: 12px; 45 } 46 47 tab-strip > tab-strip-label { 48 -webkit-writing-mode: vertical-rl; 49 display: inline; 50 margin-right: 1px; 51 min-height: 20px; 52 padding: 15px 3px 15px 1px; 53 } 54 55 tab-strip > 56 tab-strip-label:not([enabled]) { 57 color: rgb(128, 128, 128); 58 } 59 60 tab-strip > tab-strip-label[selected] { 61 background-color: white; 62 border: 1px solid rgb(163, 163, 163); 63 border-left: none; 64 padding: 14px 2px 14px 1px; 65 } 66 </style> 67 68 <active-panel-container id='active_panel_container'> 69 </active-panel-container> 70 <tab-strip id='tab_strip'></tab-strip> 71 </template> 72 73 <script> 74 'use strict'; 75 Polymer({ 76 ready: function() { 77 this.activePanelContainer_ = this.$.active_panel_container; 78 this.tabStrip_ = this.$.tab_strip; 79 80 this.rangeOfInterest_ = new tr.b.Range(); 81 this.brushingStateController_ = undefined; 82 this.onSelectionChanged_ = this.onSelectionChanged_.bind(this); 83 this.onModelChanged_ = this.onModelChanged_.bind(this); 84 }, 85 86 get brushingStateController() { 87 return this.brushingStateController_; 88 }, 89 90 set brushingStateController(brushingStateController) { 91 if (this.brushingStateController) { 92 this.brushingStateController_.removeEventListener( 93 'change', this.onSelectionChanged_); 94 this.brushingStateController_.removeEventListener( 95 'model-changed', this.onModelChanged_); 96 } 97 this.brushingStateController_ = brushingStateController; 98 if (this.brushingStateController) { 99 this.brushingStateController_.addEventListener( 100 'change', this.onSelectionChanged_); 101 this.brushingStateController_.addEventListener( 102 'model-changed', this.onModelChanged_); 103 } 104 }, 105 106 get selection() { 107 return this.brushingStateController_.selection; 108 }, 109 110 onSelectionChanged_: function() { 111 if (this.activePanel) 112 this.activePanel.selection = this.selection; 113 }, 114 115 get model() { 116 return this.brushingStateController_.model; 117 }, 118 119 onModelChanged_: function() { 120 this.activePanelType_ = undefined; 121 this.updateContents_(); 122 }, 123 124 get expanded() { 125 this.hasAttribute('expanded'); 126 }, 127 128 get activePanel() { 129 if (this.activePanelContainer_.children.length === 0) 130 return undefined; 131 return this.activePanelContainer_.children[0]; 132 }, 133 134 get activePanelType() { 135 return this.activePanelType_; 136 }, 137 138 set activePanelType(panelType) { 139 if (this.model === undefined) 140 throw new Error('Cannot activate panel without a model'); 141 142 var panel = undefined; 143 if (panelType) 144 panel = document.createElement(panelType); 145 146 if (panel !== undefined && !panel.supportsModel(this.model)) 147 throw new Error('Cannot activate panel: does not support this model'); 148 149 if (this.activePanelType) { 150 this.getLabelElementForPanelType_( 151 this.activePanelType).removeAttribute('selected'); 152 } 153 this.activePanelContainer_.textContent = ''; 154 155 if (panelType === undefined) { 156 this.removeAttribute('expanded'); 157 this.activePanelType_ = undefined; 158 return; 159 } 160 161 this.getLabelElementForPanelType_(panelType). 162 setAttribute('selected', true); 163 this.setAttribute('expanded', true); 164 165 this.activePanelContainer_.appendChild(panel); 166 panel.rangeOfInterest = this.rangeOfInterest_; 167 panel.selection = this.selection_; 168 panel.model = this.model; 169 170 this.activePanelType_ = panelType; 171 }, 172 173 getPanelTypeForConstructor_: function(constructor) { 174 for (var i = 0; i < this.tabStrip_.children.length; i++) { 175 if (this.tabStrip_.children[i].panelType.constructor == constructor) 176 return this.tabStrip_.children[i].panelType; 177 } 178 }, 179 180 getLabelElementForPanelType_: function(panelType) { 181 for (var i = 0; i < this.tabStrip_.children.length; i++) { 182 if (this.tabStrip_.children[i].panelType == panelType) 183 return this.tabStrip_.children[i]; 184 } 185 return undefined; 186 }, 187 188 updateContents_: function() { 189 var previouslyActivePanelType = this.activePanelType; 190 191 this.tabStrip_.textContent = ''; 192 var supportedPanelTypes = []; 193 194 var panelTypes = 195 tr.ui.b.getPolymerElementsThatSubclass('tr-ui-side-panel'); 196 panelTypes.forEach(function(panelType) { 197 var labelEl = document.createElement('tab-strip-label'); 198 var panel = document.createElement(panelType); 199 200 labelEl.textContent = panel.textLabel; 201 labelEl.panelType = panelType; 202 203 var supported = panel.supportsModel(this.model); 204 if (this.model && supported.supported) { 205 supportedPanelTypes.push(panelType); 206 labelEl.setAttribute('enabled', true); 207 labelEl.addEventListener('click', function() { 208 this.activePanelType = 209 this.activePanelType === panelType ? undefined : panelType; 210 }.bind(this)); 211 } else { 212 labelEl.title = 'Not supported for the current trace: ' + 213 supported.reason; 214 labelEl.style.display = 'none'; 215 } 216 this.tabStrip_.appendChild(labelEl); 217 }, this); 218 219 // Restore the active panel, or collapse 220 if (previouslyActivePanelType && 221 supportedPanelTypes.indexOf(previouslyActivePanelType) != -1) { 222 this.activePanelType = previouslyActivePanelType; 223 this.setAttribute('expanded', true); 224 } else { 225 this.activePanelContainer_.textContent = ''; 226 this.removeAttribute('expanded'); 227 } 228 }, 229 230 get rangeOfInterest() { 231 return this.rangeOfInterest_; 232 }, 233 234 set rangeOfInterest(range) { 235 if (range == undefined) 236 throw new Error('Must not be undefined'); 237 this.rangeOfInterest_ = range; 238 if (this.activePanel) 239 this.activePanel.rangeOfInterest = range; 240 } 241 }); 242 </script> 243</polymer-element> 244 245