1 /* 2 * Copyright 2017 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * https://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package traceviewer.ui.tracks 18 19 import traceviewer.ui.LayoutConstants 20 import traceviewer.ui.RenderState 21 import trebuchet.model.base.Slice 22 import java.awt.Color 23 import java.awt.Dimension 24 import java.awt.FontMetrics 25 import java.awt.Graphics 26 import javax.swing.JComponent 27 28 open class SliceTrack<in T : Slice>(private val slices: List<T>, private val renderState: RenderState, 29 trackHeight: Int = LayoutConstants.TrackHeight) : JComponent() { 30 31 init { 32 preferredSize = Dimension(0, trackHeight) 33 size = preferredSize 34 } 35 paintComponentnull36 override fun paintComponent(g: Graphics?) { 37 if (g == null) return 38 39 val scale = renderState.scale 40 val panX = renderState.panX 41 val y = 0 42 val height = height 43 var x: Int 44 var width: Int 45 46 val metrics = g.fontMetrics 47 var ty = metrics.ascent 48 ty += (height - ty) / 2 49 50 slices.forEach { 51 x = ((it.startTime - panX) * scale).toInt() 52 val scaledWidth = (it.endTime - it.startTime) * scale 53 width = maxOf(scaledWidth.toInt(), 1) 54 if (x + width > 0 && x < this.width) { 55 var color = colorFor(it) 56 if (scaledWidth < 1) { 57 color = Color(color.red, color.green, color.blue, 58 maxOf((255 * scaledWidth).toInt(), 50)) 59 } 60 g.color = color 61 g.fillRect(x, y, width, height) 62 63 if (height >= metrics.height) { 64 drawLabel(it, g, metrics, x, ty, width) 65 } 66 } 67 } 68 } 69 drawLabelnull70 open fun drawLabel(slice: T, g: Graphics, metrics: FontMetrics, x: Int, y: Int, width: Int) { 71 var strLimit = 0 72 var strWidth = 0 73 while (strLimit < slice.name.length && strWidth <= width) { 74 strWidth += metrics.charWidth(slice.name[strLimit]) 75 strLimit++ 76 } 77 if (strWidth > width) strLimit-- 78 if (strLimit > 2) { 79 g.color = textColor 80 g.drawString(slice.name.substring(0, strLimit), x, y) 81 } 82 } 83 colorFornull84 open fun colorFor(slice: T): Color { 85 return colors[Math.abs(slice.name.hashCode()) % colors.size] 86 } 87 <lambda>null88 private fun sliceAt(timestamp: Double) = slices.binarySearch { 89 when { 90 it.startTime > timestamp -> 1 91 it.endTime < timestamp -> -1 92 else -> 0 93 } 94 }.let { if (it < 0) null else slices[it] } 95 96 companion object Style { 97 private val colors = listOf( 98 Color(0x0D47A1), Color(0x1565C0), Color(0x1976D2), 99 Color(0x1A237E), Color(0x283593), Color(0x303F9F), 100 Color(0x01579B), Color(0x006064), Color(0x004D40), 101 Color(0x1B5E20), Color(0x37474F), Color(0x263238) 102 ) 103 104 private val textColor = Color(0xff, 0xff, 0xff, 0x7f) 105 } 106 }