1// ---------------------------------------------------------------------------------------------------------------- 2// Text 3// ---------------------------------------------------------------------------------------------------------------- 4function Text(anchorPoint, initialText) 5{ 6 this.scene = null; 7 this.anchorPoint = anchorPoint; 8 this.text = ""; 9 this.lines = []; 10 this.halign = 1; 11 this.valign = 1; 12 this.angle = 0; 13 this.lineSpacing = 1.6; 14 this.font = "Arial"; 15 this.fontSize = 1.0; 16 this.maxWidth = 0; 17 this.totalHeight = 0; 18 this.lineSizes = []; 19 this.dimensionsStale = true; 20 this.appearance = new Appearance(); 21 this.selected = false; 22 this.visible = true; 23 this.frozen = false; 24 this.onChangeListeners = []; 25 this.boundsMin = new Vector(Number.MAX_VALUE,Number.MAX_VALUE); 26 this.boundsMax = new Vector(-Number.MAX_VALUE,-Number.MAX_VALUE); 27 28 this.getBoundsMin = function() 29 { 30 return this.boundsMin; 31 } 32 33 this.getBoundsMax = function() 34 { 35 return this.boundsMax; 36 } 37 38 this.saveAsJavascript = function() 39 { 40 var str = "var text = new Text("; 41 42 str += "new Vector(" + this.anchorPoint.x + ", " + this.anchorPoint.y + ")"; 43 str += ", unescape(\"" + escape(this.text) + "\")"; 44 str += ");\n"; 45 46 str += "text.halign = \"" + this.halign + "\";\n"; 47 str += "text.valign = \"" + this.valign + "\";\n"; 48 str += "text.font = \"" + this.font + "\";\n"; 49 str += "text.fontSize = " + this.fontSize + ";\n"; 50 str += this.appearance.saveAsJavascript("text"); 51 str += "text.angle = " + this.angle + ";\n"; 52 str += "text.lineSpacing = " + this.lineSpacing + ";\n"; 53 54 str += "text.visible = " + this.visible + ";\n"; 55 str += "text.frozen = " + this.frozen + ";\n"; 56 str += "text.maxWidth = " + this.maxWidth + ";\n"; 57 str += "text.totalHeight = " + this.totalHeight + ";\n"; 58 59 if (this.name != undefined) 60 { 61 str += "text.name = \"" + this.name + "\";\n"; 62 } 63 64 str += "scene.addObject(text);\n"; 65 return str; 66 } 67 68 this.setText = function(s) 69 { 70 this.text = s; 71 this.lines = s.split("\n"); 72 this.onChange(); 73 } 74 75 this.addChangeListener = function(listener) 76 { 77 this.onChangeListeners.push(listener); 78 } 79 80 this.updateBounds = function() 81 { 82 this.boundsMin = new Vector(Number.MAX_VALUE,Number.MAX_VALUE); 83 this.boundsMax = new Vector(-Number.MAX_VALUE,-Number.MAX_VALUE); 84 85 var xAxis = rotate(new Vector(1, 0), this.angle * Math.PI / 180); 86 var yAxis = rotate(new Vector(0, 1), this.angle * Math.PI / 180); 87 88 var vMin = 0; 89 var vMax = 0; 90 91 if (this.valign == 0) 92 { 93 vMin = -this.totalHeight; 94 vMax = 0; 95 } 96 else if (this.valign == 1) 97 { 98 vMin = -this.totalHeight * 0.5; 99 vMax = this.totalHeight * 0.5; 100 } 101 else if (this.valign == 2) 102 { 103 vMin = 0; 104 vMax = this.totalHeight; 105 } 106 107 var hMin = 0; 108 var hMax = 0; 109 110 if (this.halign == 0) 111 { 112 hMin = 0; 113 hMax = this.maxWidth; 114 } 115 else if (this.halign == 1) 116 { 117 hMin = -this.maxWidth * 0.5; 118 hMax = this.maxWidth * 0.5; 119 } 120 else if (this.halign == 2) 121 { 122 hMin = -this.maxWidth; 123 hMax = 0; 124 } 125 126 var corners = [ mad(yAxis, vMin, mad(xAxis, hMin, this.anchorPoint)), 127 mad(yAxis, vMin, mad(xAxis, hMax, this.anchorPoint)), 128 mad(yAxis, vMax, mad(xAxis, hMin, this.anchorPoint)), 129 mad(yAxis, vMax, mad(xAxis, hMax, this.anchorPoint)) ]; 130 131 for (var i=0; i!=corners.length; ++i) 132 { 133 this.boundsMin = min(this.boundsMin, corners[i]); 134 this.boundsMax = max(this.boundsMax, corners[i]); 135 } 136 } 137 138 this.onChange = function(changeDetails) 139 { 140 // Backwards compatibility 141 this.appearance.SetFromOldProperties(this); 142 143 this.dimensionsStale = true; 144 145 this.updateBounds(); 146 147 for (var i=0; i!=this.onChangeListeners.length; ++i) 148 { 149 this.onChangeListeners[i](this, changeDetails); 150 } 151 } 152 153 this.draw = function(camera) 154 { 155 var fontSize = camera.scale(this.fontSize); 156 var font = fontSize + "px " + this.font; 157 158 if (this.dimensionsStale) 159 { 160 this.maxWidth = 0; 161 this.totalHeight = 0; 162 this.lineSizes = new Array(this.lines.length); 163 164 for (var i=0; i!=this.lines.length; ++i) 165 { 166 var lineSize = camera.measureText(this.lines[i], font); 167 168 this.lineSizes[i] = lineSize; 169 this.maxWidth = Math.max(this.maxWidth, lineSize.x); 170 this.totalHeight += lineSize.y * this.lineSpacing; 171 } 172 173 this.dimensionsStale = false;
174 } 175 176 this.updateBounds(); 177 178 var xAxis = rotate(new Vector(1, 0), this.angle * Math.PI / 180); 179 var yAxis = rotate(new Vector(0, 1), this.angle * Math.PI / 180); 180 181 if (this.selected) 182 { 183 camera.drawLine(this.anchorPoint, mad(xAxis, this.maxWidth, this.anchorPoint), this.appearance.GetLineColor(), 1, [3, 3]); 184 } 185 186 var vOffset = 0; 187 188 if (this.valign == 0) 189 { 190 vOffset = 0; 191 } 192 else if (this.valign == 1) 193 { 194 vOffset = this.totalHeight * 0.5; 195 } 196 else if (this.valign == 2) 197 { 198 vOffset = this.totalHeight; 199 } 200 201 for (var i=0; i!=this.lines.length; ++i) 202 { 203 var lineSize = this.lineSizes[i]; 204 var hOffset = 0; 205 206 if (this.halign == 0) 207 { 208 hOffset = 0; 209 } 210 else if (this.halign == 1) 211 { 212 hOffset = -lineSize.x * 0.5; 213 } 214 else if (this.halign == 2) 215 { 216 hOffset = -lineSize.x; 217 } 218 219 vOffset += -lineSize.y * this.lineSpacing; 220 221 var p = mad(yAxis, vOffset, mad(xAxis, hOffset, this.anchorPoint)); 222 223 camera.drawText(p, this.lines[i], this.appearance.GetLineColor(), "left", this.angle * Math.PI / 180, font); 224 } 225 } 226 227 this.hitTest = function(a, b, camera) 228 { 229 var xAxis = rotate(new Vector(1, 0), this.angle * Math.PI / 180); 230 var yAxis = rotate(new Vector(0, 1), this.angle * Math.PI / 180); 231 232 var hMin = 0; 233 var hMax = 0; 234 235 if (this.halign == 0) 236 { 237 hMin = 0; 238 hMax = this.maxWidth; 239 } 240 else if (this.halign == 1) 241 { 242 hMin = -this.maxWidth * 0.5; 243 hMax = this.maxWidth * 0.5; 244 } 245 else if (this.halign == 2) 246 { 247 hMin = -this.maxWidth; 248 hMax = 0; 249 } 250 251 var vOffset = 0; 252 253 if (this.valign == 0) 254 { 255 vOffset = 0; 256 } 257 else if (this.valign == 1) 258 { 259 vOffset = this.totalHeight * 0.5; 260 } 261 else if (this.valign == 2) 262 { 263 vOffset = this.totalHeight; 264 } 265 266 var lineHeight = this.totalHeight / this.lines.length; 267 268 vOffset += lineHeight * 0.5; 269 270 for (var i=0; i!=this.lines.length; ++i) 271 { 272 vOffset += -lineHeight; 273 274 if (overlapRectLine(a, b, mad(yAxis, vOffset, mad(xAxis, hMin, this.anchorPoint)), mad(yAxis, vOffset, mad(xAxis, hMax, this.anchorPoint)))) 275 { 276 return true; 277 } 278 } 279 280 281 return false; 282 } 283 284 this.getSnapPoints = function () 285 { 286 var points = [ { type: "center", p: this.anchorPoint } ]; 287 return points; 288 } 289 290 this.getDragPoints = function(localSpace, camera) 291 { 292 if (this.isFrozen()) 293 return []; 294 295 var xAxis = rotate(new Vector(1, 0), this.angle * Math.PI / 180); 296 var yAxis = rotate(new Vector(0, 1), this.angle * Math.PI / 180); 297 298 var points = [ this.anchorPoint, mad(xAxis, this.maxWidth, this.anchorPoint) ]; 299 300 return points; 301 } 302 303 this.drawDragPoint = function(camera, index, position, localSpace, alpha) 304 { 305 if (alpha == undefined) 306 alpha = 1; 307 308 var points = this.getDragPoints(localSpace, camera); 309 310 camera.drawRectangle(points[index], camera.invScale(10), "rgba(255,0,0," + alpha + ")", 2); 311 } 312 313 this.setDragPointPos = function(index, p, localSpace, dragStartPoint, camera) 314 { 315 if (index == 0) 316 { 317 this.anchorPoint = p; 318 } 319 else 320 { 321 this.angle = toAngle(sub(p, this.anchorPoint)) * 180 / Math.PI; 322 } 323 324 this.onChange(); 325 } 326 327 this.getOrigin = function() 328 { 329 return this.anchorPoint; 330 } 331 332 this.setOrigin = function(p) 333 { 334 this.anchorPoint = p; 335 this.onChange(); 336 } 337 338 this.getProperties = function() 339 { 340 var appearanceControl = new PopoutContainer(undefined, "images/color_wheel.svg"); 341 { 342 appearanceControl.addControl("", new AppearanceControl(this.appearance, true, false, function(){ this.onChange(); }.bind(this)) ); 343 } 344 345 return [ 346 {name: "Appearance", control:appearanceControl }, 347 {name: "Text", control: new PopoutTextBox(this.text, "multi", true, 0, function (value) { this.setText(value); this.onChange(); }.bind(this)) }, 348 {name: "Font", control:new TextBox(this.font, true, false, 32, function(value){ this.font = value; this.onChange(); }.bind(this) )}, 349 {name: "Font Size", control: new PopoutSlider(0.1, 5.0, this.fontSize, 0.1, function (value) { this.fontSize = value; this.onChange(); }.bind(this)) }, 350 {name: "Line Spacing", control: new PopoutSlider(0.1, 5.0, this.lineSpacing, 0.1, function (value) { this.lineSpacing = value; this.onChange(); }.bind(this)) }, 351 {name: "H Align", control: new Dropdown(["left", "center", "right"], this.halign, function (value) { this.halign = value; this.onChange(); }.bind(this) )}, 352 {name: "V Align", control: new Dropdown(["top", "center", "bottom"], this.valign, function (value) { this.valign = value; this.onChange(); }.bind(this) )}, 353 ]; 354 } 355 356 this.toggleVisibility = function(v) 357 { 358 var newVisible = (v!==undefined) ? v : !this.visible; 359 if (this.visible != newVisible) 360 { 361 this.visible = newVisible; 362 this.onChange(); 363 } 364 } 365 366 this.isVisible = function() 367 { 368 return this.visible; 369 } 370 371 this.toggleFrozen = function(f) 372 { 373 this.frozen = (f!==undefined) ? f : !this.frozen; 374 this.onChange(); 375 } 376 377 this.isFrozen = function() 378 { 379 return this.frozen; 380 } 381 382 this.setSelected = function(selected) 383 { 384 this.selected = selected; 385 } 386 387 this.isSelected = function() 388 { 389 return this.selected; 390 } 391 392 this.setText(initialText); 393}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.