From fa57115881ea95b9eadce13490d712dec0d391fb Mon Sep 17 00:00:00 2001 From: Adrian Dorrington Date: Fri, 19 May 2023 18:24:23 +1200 Subject: [PATCH 1/2] Extended Beam tool with divergence options --- simulator/js/objs/parallel.js | 105 ++++++++++++++++++++++++++++------ simulator/locales/de.js | 8 +++ simulator/locales/en.js | 8 ++- simulator/locales/fr.js | 8 +++ simulator/locales/nl.js | 8 +++ simulator/locales/pl.js | 10 +++- simulator/locales/ru.js | 8 +++ simulator/locales/template.js | 8 +++ simulator/locales/zh_CN.js | 10 +++- simulator/locales/zh_TW.js | 10 +++- 10 files changed, 162 insertions(+), 21 deletions(-) diff --git a/simulator/js/objs/parallel.js b/simulator/js/objs/parallel.js index e8328f5e..042776e5 100644 --- a/simulator/js/objs/parallel.js +++ b/simulator/js/objs/parallel.js @@ -1,12 +1,33 @@ // Beam objTypes['parallel'] = { + tmp_randomNumbers: [], + //建立物件 Create the obj create: function(mouse) { - return {type: 'parallel', p1: mouse, p2: mouse, p: 0.5}; + return {type: 'parallel', p1: mouse, p2: mouse, p: 0.5, divergence: 0.0, lambert: false, random: false}; }, - p_box: objTypes['laser'].p_box, + //顯示屬性方塊 Show the property box + p_box: function(obj, elem) { + createNumberAttr(getMsg('brightness'), 0, 1, 0.01, obj.p || 1, function(obj, value) { + obj.p = value; + }, elem); + if (colorMode) { + createNumberAttr(getMsg('wavelength'), UV_WAVELENGTH, INFRARED_WAVELENGTH, 1, obj.wavelength || GREEN_WAVELENGTH, function(obj, value) { + obj.wavelength = value; + }, elem); + } + createNumberAttr(getMsg('emissionangle'), 0, 180, 1, obj.divergence, function(obj, value) { + obj.divergence = value; + }, elem); + createBooleanAttr(getMsg('lambertian'), obj.lambert, function(obj, value) { + obj.lambert = value; + }, elem); + createBooleanAttr(getMsg('random'), obj.random, function(obj, value) { + obj.random = value; + }, elem); +}, //使用lineobj原型 Use the prototype lineobj c_mousedown: objTypes['lineobj'].c_mousedown, @@ -39,31 +60,81 @@ objTypes['parallel'] = { ctx.lineCap = 'butt'; }, + initRandom: function (obj) { + if (obj.tmp_randomNumbers == undefined || !obj.random){ + this.clearRandom(obj); + } + }, + + clearRandom: function (obj) { + obj.tmp_randomNumbers = []; + }, + + getRandom: function (obj, i) { + for(j=obj.tmp_randomNumbers.length; j<=i; j++) { + obj.tmp_randomNumbers.push(Math.random()); + } + return obj.tmp_randomNumbers[i]; + }, + + newRay: function(obj, x, y, normal, angle, gap, brightness_factor=1.0) { + var ray1 = graphs.ray(graphs.point(x, y), graphs.point(x + Math.sin(normal+angle), y + Math.cos(normal+angle))); + ray1.brightness_s = Math.min(obj.p / getRayDensity() * brightness_factor, 1) * 0.5; + ray1.brightness_p = Math.min(obj.p / getRayDensity() * brightness_factor, 1) * 0.5; + if (obj.lambert) { + lambert = Math.cos(angle) + ray1.brightness_s *= lambert; + ray1.brightness_p *= lambert; + } + ray1.isNew = true; + if (colorMode) { + ray1.wavelength = obj.wavelength || GREEN_WAVELENGTH; + } + ray1.gap = gap; + addRay(ray1); + }, + //射出光線 Shoot rays shoot: function(obj) { var n = graphs.length_segment(obj) * getRayDensity(); var stepX = (obj.p2.x - obj.p1.x) / n; var stepY = (obj.p2.y - obj.p1.y) / n; - var rayp2_x = obj.p1.x + obj.p2.y - obj.p1.y; - var rayp2_y = obj.p1.y - obj.p2.x + obj.p1.x; + var s = Math.PI * 2 / parseInt(getRayDensity() * 500); + var sizeX = (obj.p2.x - obj.p1.x); + var sizeY = (obj.p2.y - obj.p1.y); + var normal = Math.atan2(stepX, stepY) + Math.PI / 2.0; + var halfAngle = obj.divergence / 180.0 * Math.PI * 0.5; + var numnAngledRays = 1.0 + Math.floor(halfAngle/s) * 2.0; + var rayBrightness = 1.0 / numnAngledRays; + this.initRandom(obj); - for (var i = 0.5; i <= n; i++) - { - var ray1 = graphs.ray(graphs.point(obj.p1.x + i * stepX, obj.p1.y + i * stepY), graphs.point(rayp2_x + i * stepX, rayp2_y + i * stepY)); - ray1.brightness_s = Math.min(obj.p / getRayDensity(), 1) * 0.5; - ray1.brightness_p = Math.min(obj.p / getRayDensity(), 1) * 0.5; - ray1.isNew = true; - if (colorMode) { - ray1.wavelength = obj.wavelength || GREEN_WAVELENGTH; - } - if (i == 0) + if (!obj.random) { + for (var i = 0.5; i <= n; i++) { - ray1.gap = true; + var x = obj.p1.x + i * stepX; + var y = obj.p1.y + i * stepY; + this.newRay(obj, x, y, normal, 0.0, i==0, rayBrightness); + for (var angle = s; angle < halfAngle; angle += s) + { + this.newRay(obj, x, y, normal, angle, i==0, rayBrightness); + this.newRay(obj, x, y, normal, -angle, i==0, rayBrightness); + } + } + } else { + for (var i = 0; i < n*numnAngledRays; i++){ + position = this.getRandom(obj, i*2); + angle = this.getRandom(obj, i*2+1); + this.newRay( + obj, + obj.p1.x + position * sizeX, + obj.p1.y + position * sizeY, + normal, + (angle*2-1) * halfAngle, + i==0, + rayBrightness); } - addRay(ray1); } - } }; diff --git a/simulator/locales/de.js b/simulator/locales/de.js index 6ac0dba4..353cd610 100644 --- a/simulator/locales/de.js +++ b/simulator/locales/de.js @@ -323,6 +323,14 @@ locales["de"] = { "refractiveindex": { "message": "Brechungsindex:" }, + "random": { + "incomplete": true, + "message": "Random emission" + }, + "lambertian": { + "incomplete": true, + "message": "Lambertian emission" + }, "refractiveindex_note": { "message": "(relativ wenn das Glas ineinander)" }, diff --git a/simulator/locales/en.js b/simulator/locales/en.js index 0003ec40..9b65492e 100644 --- a/simulator/locales/en.js +++ b/simulator/locales/en.js @@ -318,6 +318,12 @@ locales["en"] = { "refractiveindex": { "message": "Refractive index:" }, + "random": { + "message": "Random emission" + }, + "lambertian": { + "message": "Lambertian emission" + }, "refractiveindex_note": { "message": "(relative if inside another glass)" }, @@ -391,7 +397,7 @@ locales["en"] = { "message": "A single ray of light defined by two points. (Drag or Click to create. The first point is the source, shooting toward the second point.)" }, "tool_parallel_popover": { - "message": "A parallel beam of rays emerges from a line segment, with density controlled by the 'Ray density' slider. (Drag or click to create.)" + "message": "A beam of rays emerges from a line segment, with adjustable divergence and density controlled by the 'Ray density' slider. (Drag or click to create.)" }, "tool_radiant_popover": { "message": "Rays emerge from a single point, with number controlled by the 'Ray density' slider. (Click to create.)" diff --git a/simulator/locales/fr.js b/simulator/locales/fr.js index 4a804374..c960d18a 100644 --- a/simulator/locales/fr.js +++ b/simulator/locales/fr.js @@ -352,6 +352,14 @@ locales["fr"] = { "refractiveindex": { "message": "Indice de réfraction:" }, + "random": { + "incomplete": true, + "message": "Random emission" + }, + "lambertian": { + "incomplete": true, + "message": "Lambertian emission" + }, "refractiveindex_note": { "incomplete": true, "message": "(relative if inside another glass)" diff --git a/simulator/locales/nl.js b/simulator/locales/nl.js index 4b1c878e..cbeb8258 100644 --- a/simulator/locales/nl.js +++ b/simulator/locales/nl.js @@ -368,6 +368,14 @@ locales["nl"] = { "refractiveindex": { "message": "Brekingsindex:" }, + "random": { + "incomplete": true, + "message": "Random emission" + }, + "lambertian": { + "incomplete": true, + "message": "Lambertian emission" + }, "refractiveindex_note": { "incomplete": true, "message": "(relative if inside another glass)" diff --git a/simulator/locales/pl.js b/simulator/locales/pl.js index 15f7a7d9..e4a62ddf 100644 --- a/simulator/locales/pl.js +++ b/simulator/locales/pl.js @@ -319,6 +319,14 @@ locales["pl"] = { "refractiveindex": { "message": "Współczynnik załamania:" }, + "random": { + "incomplete": true, + "message": "Random emission" + }, + "lambertian": { + "incomplete": true, + "message": "Lambertian emission" + }, "refractiveindex_note": { "message": "(względny, jeśli znajduje się w innym szkle)" }, @@ -490,4 +498,4 @@ locales["pl"] = { "help_popover": { "message": "
Wyskakujące okienka pomocy

Kliknij ten przycisk, aby przełączyć (wł/wył) wyskakujące okienka pomocy pozostałych przycisków.

Ograniczone przeciąganie

Podczas przeciągania obiektu przytrzymaj klawisz Shift, aby ograniczyć do poziomego/pionowego; przytrzymaj Ctrl, aby powielić obiekt. Podczas tworzenia obiektu w kształcie linii lub przeciągania jego punktów końcowych przytrzymaj klawisz Shift, aby zablokować kąt lub przeskakiwać między 0°, 45°, 90°; przytrzymaj klawisz Ctrl, aby obrócić/skalować wokół jego środka.

Grupuj, obracaj i skaluj obiekty

Przytrzymaj klawisz Ctrl, kliknij kilka punktów kontrolnych (np. punkty końcowe), a następnie kliknij puste miejsce, aby zgrupować te punkty i utworzyć uchwyt. Przeciągnij uchwyt (lub naciśnij klawisze strzałek), aby przesunąć grupę; Shift+przeciągnij, aby ograniczyć do poziomego/pionowego ruchu; Ctrl+przeciągnij, aby obrócić, Ctrl+Shift+przeciągnij, aby skalować. Przeciągnij \"+\", aby ustawić środek obrotu/skalowania. Kliknij uchwyt i naciśnij klawisze Ctrl+D, aby powielić grupę; naciśnij Usuń, aby rozgrupować.

Bezpośrednia edycja współrzędnych

Kliknij dwukrotnie lub kliknij prawym przyciskiem myszy punkt kontrolny (np. punkt końcowy) obiektu, edytuj współrzędne (x,y) w pikselach, a następnie naciśnij klawisz Enter.

Skróty klawiaturowe

Gdy obiekt jest zaznaczony (przez kliknięcie go), naciskaj klawisze strzałek, aby się poruszać; Ctrl+D, aby powielić; Klawisz Delete, aby usunąć.

" } -} +} \ No newline at end of file diff --git a/simulator/locales/ru.js b/simulator/locales/ru.js index ae0f3a35..eb90fe00 100644 --- a/simulator/locales/ru.js +++ b/simulator/locales/ru.js @@ -353,6 +353,14 @@ locales["ru"] = { "refractiveindex": { "message": "Показатель преломления:" }, + "random": { + "incomplete": true, + "message": "Random emission" + }, + "lambertian": { + "incomplete": true, + "message": "Lambertian emission" + }, "refractiveindex_note": { "incomplete": true, "message": "(relative if inside another glass)" diff --git a/simulator/locales/template.js b/simulator/locales/template.js index 0ae32617..e390dd88 100644 --- a/simulator/locales/template.js +++ b/simulator/locales/template.js @@ -424,6 +424,14 @@ locales["LOCALE_ID"] = { "incomplete": true, "message": "Refractive index:" }, + "random": { + "incomplete": true, + "message": "Random emission" + }, + "lambertian": { + "incomplete": true, + "message": "Lambertian emission" + }, "refractiveindex_note": { "incomplete": true, "message": "(relative if inside another glass)" diff --git a/simulator/locales/zh_CN.js b/simulator/locales/zh_CN.js index 3b8703d0..0bad11ea 100644 --- a/simulator/locales/zh_CN.js +++ b/simulator/locales/zh_CN.js @@ -319,6 +319,14 @@ locales["zh-CN"] = { "refractiveindex": { "message": "折射率:" }, + "random": { + "incomplete": true, + "message": "Random emission" + }, + "lambertian": { + "incomplete": true, + "message": "Lambertian emission" + }, "refractiveindex_note": { "message": "(于另一透光物内部时为相对值)" }, @@ -490,4 +498,4 @@ locales["zh-CN"] = { "help_popover": { "message": "
提示泡泡

按此钮以切换是否于其他按钮显示提示泡泡。

限制拖曳行为

拖曳物件时,按住 Shift 以限制于水平或垂直移动;按住 Ctrl 以复制物件。建立线型物件或拖曳其端点时,按住 Shift 以锁定角度或吸附至 0°、45°、90°;按住 Ctrl 以对于中心点旋转或缩放。

群组、旋转及缩放物件

按住 Ctrl,点击多个控制点(如端点),并点击空白处以将这些点群组并建立控制杆。拖曳控制杆(或按方向键)以平移群组;Shift+拖曳以限制于水平或垂直移动;Ctrl+拖曳以旋转;Ctrl+Shift+拖曳以缩放。移动「+」以设定旋转或缩放中心。点击控制杆并按 Ctrl+D 以复制群组;按 Delete 以解散群组。

直接编辑座标

对控制点(如端点)点两下或按右键,输入 (x,y) 座标(单位为像素),然后按 Enter。

键盘快速键

当一物件在被选取的状态(被点击)时,按方向键以移动;Ctrl+D 以复制;Delete 以删除。

" } -} +} \ No newline at end of file diff --git a/simulator/locales/zh_TW.js b/simulator/locales/zh_TW.js index c0eb368e..54ea7936 100644 --- a/simulator/locales/zh_TW.js +++ b/simulator/locales/zh_TW.js @@ -318,6 +318,14 @@ locales["zh-TW"] = { "refractiveindex": { "message": "折射率:" }, + "random": { + "incomplete": true, + "message": "Random emission" + }, + "lambertian": { + "incomplete": true, + "message": "Lambertian emission" + }, "refractiveindex_note": { "message": "(於另一透光物內部時為相對值)" }, @@ -489,4 +497,4 @@ locales["zh-TW"] = { "help_popover": { "message": "
提示泡泡

按此鈕以切換是否於其他按鈕顯示提示泡泡。

限制拖曳行為

拖曳物件時,按住 Shift 以限制於水平或垂直移動;按住 Ctrl 以複製物件。建立線型物件或拖曳其端點時,按住 Shift 以鎖定角度或吸附至 0°、45°、90°;按住 Ctrl 以對於中心點旋轉或縮放。

群組、旋轉及縮放物件

按住 Ctrl,點擊多個控制點(如端點),並點擊空白處以將這些點群組並建立控制桿。拖曳控制桿(或按方向鍵)以平移群組;Shift+拖曳以限制於水平或垂直移動;Ctrl+拖曳以旋轉;Ctrl+Shift+拖曳以縮放。移動「+」以設定旋轉或縮放中心。點擊控制桿並按 Ctrl+D 以複製群組;按 Delete 以解散群組。

直接編輯座標

對控制點(如端點)點兩下或按右鍵,輸入 (x,y) 座標(單位為像素),然後按 Enter。

鍵盤快速鍵

當一物件在被選取的狀態(被點擊)時,按方向鍵以移動;Ctrl+D 以複製;Delete 以刪除。

" } -} +} \ No newline at end of file From 6502cce6a130feb358c40b867b6dc04a24b363d3 Mon Sep 17 00:00:00 2001 From: Adrian Dorrington Date: Tue, 23 May 2023 09:38:06 +1200 Subject: [PATCH 2/2] Upgrated text functionality --- simulator/js/objs/text.js | 114 ++++++++++++++++++++++++++++++---- simulator/js/parameterBox.js | 61 ++++++++++++++++++ simulator/locales/de.js | 24 +++++++ simulator/locales/en.js | 18 ++++++ simulator/locales/fr.js | 24 +++++++ simulator/locales/nl.js | 24 +++++++ simulator/locales/pl.js | 24 +++++++ simulator/locales/ru.js | 24 +++++++ simulator/locales/template.js | 24 +++++++ simulator/locales/zh_CN.js | 24 +++++++ simulator/locales/zh_TW.js | 24 +++++++ 11 files changed, 373 insertions(+), 12 deletions(-) diff --git a/simulator/js/objs/text.js b/simulator/js/objs/text.js index bac23286..48b7fe51 100644 --- a/simulator/js/objs/text.js +++ b/simulator/js/objs/text.js @@ -1,17 +1,69 @@ // Text // Originally contributed by Paul Falstad (pfalstad) + +// generic list of web safe fonts +fonts = [ + 'Serif', + 'Arial', + 'Helvetica', + 'Times New Roman', + 'Georgia', + 'Courier New', + 'Verdana', + 'Tahoma', + 'Trebuchet MS', + 'Impact', + 'Lucida Sans' +]; + +fontStyles = [ + 'Normal', + 'Bold', + 'Italic', + 'Bold Italic', + 'Oblique', + 'Bold Oblique' +] + +fontAlignmants = { + 'left': "Left", + 'center': "Centre", + 'right': "Right" +} + objTypes['text'] = { //建立物件 Create the obj create: function(mouse) { - return {type: 'text', x: mouse.x, y: mouse.y, p: 'text here'}; + return {type: 'text', x: mouse.x, y: mouse.y, p: 'text here', fontSize: 24, fontName: 'Serif', fontStyle: 'Normal', fontAlignmant: 'Left', fontSmallCaps: false, fontAngle: 0}; }, //顯示屬性方塊 Show the property box p_box: function(obj, elem) { - createStringAttr('', obj.p, function(obj, value) { + // createStringAttr('', obj.p, function(obj, value) { + // obj.p = value; + // }, elem); + createTextAttr('', obj.p, function(obj, value) { obj.p = value; }, elem); + createNumberAttr(getMsg('fontsize'), 6, 96, 1, obj.fontSize, function(obj, value) { + obj.fontSize = value; + }, elem); + createDropdownAttr(getMsg('fontname'), obj.fontName, fonts, function(obj, value) { + obj.fontName = value; + }, elem); + createDropdownAttr(getMsg('fontstyle'), obj.fontStyle, fontStyles, function(obj, value) { + obj.fontStyle = value; + }, elem); + createDropdownAttr(getMsg('fontalignment'), obj.fontAlignmant, fontAlignmants, function(obj, value) { + obj.fontAlignmant = value; + }, elem); + createBooleanAttr(getMsg('smallcaps'), obj.fontSmallCaps, function(obj, value) { + obj.fontSmallCaps = value; + }, elem); + createNumberAttr(getMsg('angle'), 0, 360, 1, obj.fontAngle, function(obj, value) { + obj.fontAngle = value; + }, elem); }, //建立物件過程滑鼠按下 Mousedown when the obj is being constructed by the user @@ -36,12 +88,37 @@ objTypes['text'] = { //將物件畫到Canvas上 Draw the obj on canvas draw: function(obj, canvas) { - ctx.fillStyle = getMouseStyle(obj, 'white'); - ctx.textAlign = 'left'; - ctx.textBaseline = 'bottom'; - ctx.font = '24px serif'; - ctx.fillText(obj.p, obj.x, obj.y); - obj.tmp_width = ctx.measureText(obj.p).width; + ctx.fillStyle = getMouseStyle(obj, 'white'); + ctx.textAlign = obj.fontAlignmant; + ctx.textBaseline = 'bottom'; + + fontName = ''; + if (obj.fontStyle != 'Normal') fontName += obj.fontStyle + ' '; + if (obj.fontSmallCaps) fontName += 'small-caps ' + fontName += obj.fontSize + 'px ' + obj.fontName; + ctx.font = fontName; + + ctx.save(); + ctx.translate(obj.x, obj.y); + ctx.rotate(-obj.fontAngle/180*Math.PI); + y_offset = 0; + obj.tmp_left = 0; + obj.tmp_right = 0; + obj.tmp_up = 0; + obj.tmp_down = 0; + obj.p.split('\n').forEach(line => { + ctx.fillText(line, 0, y_offset); + lineDimensions = ctx.measureText(line); + obj.tmp_left = Math.max(obj.tmp_left, lineDimensions.actualBoundingBoxLeft); + obj.tmp_right = Math.max(obj.tmp_right, lineDimensions.actualBoundingBoxRight); + obj.tmp_up = Math.max(obj.tmp_up, lineDimensions.actualBoundingBoxAscent - y_offset); + obj.tmp_down = Math.max(obj.tmp_down, -lineDimensions.actualBoundingBoxDescent + y_offset); + y_offset += lineDimensions.fontBoundingBoxAscent + lineDimensions.fontBoundingBoxDescent; + }); + ctx.restore(); + // precompute triganometry for faster calculations in 'clicked' function + obj.tmp_sin_angle = Math.sin(obj.fontAngle/180*Math.PI); + obj.tmp_cos_angle = Math.cos(obj.fontAngle/180*Math.PI); }, //平移物件 Move the object @@ -54,10 +131,16 @@ objTypes['text'] = { //繪圖區被按下時(判斷物件被按下的部分) When the drawing area is clicked (test which part of the obj is clicked) clicked: function(obj, mouse_nogrid, mouse, draggingPart) { - if (mouse_nogrid.x >= obj.x && mouse_nogrid.x <= obj.x+obj.tmp_width && - mouse_nogrid.y <= obj.y && mouse_nogrid.y >= obj.y-24) { + // translate and rotate the mouse point into the text's reference frame for easy comparison + relativeMouseX = mouse_nogrid.x - obj.x + relativeMouseY = mouse_nogrid.y - obj.y + rotatedMouseX = relativeMouseX * obj.tmp_cos_angle - relativeMouseY * obj.tmp_sin_angle; + rotatedMouseY = relativeMouseY * obj.tmp_cos_angle + relativeMouseX * obj.tmp_sin_angle; + if (rotatedMouseX >= -obj.tmp_left && rotatedMouseX <= obj.tmp_right && + rotatedMouseY <= obj.tmp_down && rotatedMouseY >= -obj.tmp_up) { draggingPart.part = 0; draggingPart.mouse0 = graphs.point(mouse_nogrid.x, mouse_nogrid.y); + draggingPart.mouse0snapped = document.getElementById('grid').checked ? graphs.point(Math.round(draggingPart.mouse0.x / gridSize) * gridSize, Math.round(draggingPart.mouse0.y / gridSize) * gridSize) : draggingPart.mouse0; draggingPart.targetPoint_ = graphs.point(obj.x, obj.y); // Avoid setting 'targetPoint' (otherwise the xybox will appear and move the text to incorrect coordinates). draggingPart.snapData = {}; return true; @@ -77,8 +160,15 @@ objTypes['text'] = { draggingPart.snapData = {}; //放開shift時解除原先之拖曳方向鎖定 Unlock the dragging direction when the user release the shift key } - obj.x = mouse_snapped.x + draggingPart.targetPoint_.x - draggingPart.mouse0.x; - obj.y = mouse_snapped.y + draggingPart.targetPoint_.y - draggingPart.mouse0.y; + // 'mouse' current mouse position, snapped to grid + // 'draggingPart.targetPoint_' object placement position (bottom left) + // 'draggingPart.mouse0' is coordiates of where the drag started, not snapped + // 'draggingPart.mouse0snapped' is coordiates of where the drag started, snapped to grid + // 'mouse_snapped' is restriced to horzontal or vertical when shift held, snapped to grid + + // new location = current location (snapped) + object placement location - where drag started (snapped) + obj.x = mouse_snapped.x + draggingPart.targetPoint_.x - draggingPart.mouse0snapped.x; + obj.y = mouse_snapped.y + draggingPart.targetPoint_.y - draggingPart.mouse0snapped.y; }, }; diff --git a/simulator/js/parameterBox.js b/simulator/js/parameterBox.js index ec38b8c1..9777da57 100644 --- a/simulator/js/parameterBox.js +++ b/simulator/js/parameterBox.js @@ -82,6 +82,37 @@ function createStringAttr(label, value, func, elem) { }; } +function createTextAttr(label, value, func, elem) { + var p_name = document.createElement('span'); + p_name.innerHTML = ' ' + label + ' '; + elem.appendChild(p_name); + var objAttr_text = document.createElement('textarea'); + objAttr_text.value = value; + objAttr_text.cols = 25; + objAttr_text.rows = 1; + elem.appendChild(objAttr_text); + objAttr_text.oninput = function() + { + // if user starts adding more than one line, auto expand the text area + if (objAttr_text.value.split('\n').length > 1 && objAttr_text.rows==1) { + objAttr_text.rows = 3; + } + setAttr(function(obj) { + func(obj, objAttr_text.value); + }); + }; + cancelMousedownEvent_(objAttr_text); + objAttr_text.onkeydown = function(e) + { + e.cancelBubble = true; + if (e.stopPropagation) e.stopPropagation(); + }; + objAttr_text.onclick = function(e) + { + this.select(); + }; +} + function createBooleanAttr(label, value, func, elem) { var label_elem = document.createElement('label'); label_elem.style.marginLeft = '0.2em'; @@ -146,6 +177,36 @@ function createEquationAttr(label, value, func, elem) { }, 1); } +function createDropdownAttr(label, value, options, func, elem) { + var p_name = document.createElement('span'); + p_name.innerHTML = ' ' + label + ' '; + elem.appendChild(p_name); + + isArray = Array.isArray(options); + var dropdown = document.createElement('select'); + for (key in options) { + var option = document.createElement('option'); + option.value = isArray ? options[key] : key; + option.textContent = options[key]; + if (option.value == value) option.selected = true; + dropdown.appendChild(option); + } + + elem.appendChild(dropdown); + dropdown.onchange = function() + { + setAttr(function(obj) { + func(obj, dropdown.value); + }); + createUndoPoint(); + }; + cancelMousedownEvent_(dropdown); + dropdown.onclick = function(e) + { + this.select(); + }; +} + function hasSameAttrType(obj1, obj2) { return obj1.type==obj2.type; diff --git a/simulator/locales/de.js b/simulator/locales/de.js index 353cd610..1019bb8c 100644 --- a/simulator/locales/de.js +++ b/simulator/locales/de.js @@ -331,6 +331,30 @@ locales["de"] = { "incomplete": true, "message": "Lambertian emission" }, + "fontsize": { + "incomplete": true, + "message": "Font Size (px)" + }, + "fontname": { + "incomplete": true, + "message": "Font" + }, + "fontstyle": { + "incomplete": true, + "message": "Style" + }, + "fontalignment": { + "incomplete": true, + "message": "Alignment" + }, + "smallcaps": { + "incomplete": true, + "message": "Small Caps" + }, + "angle": { + "incomplete": true, + "message": "Angle (°)" + }, "refractiveindex_note": { "message": "(relativ wenn das Glas ineinander)" }, diff --git a/simulator/locales/en.js b/simulator/locales/en.js index 9b65492e..8fa2e404 100644 --- a/simulator/locales/en.js +++ b/simulator/locales/en.js @@ -324,6 +324,24 @@ locales["en"] = { "lambertian": { "message": "Lambertian emission" }, + "fontsize": { + "message": "Font Size (px)" + }, + "fontname": { + "message": "Font" + }, + "fontstyle": { + "message": "Style" + }, + "fontalignment": { + "message": "Alignment" + }, + "smallcaps": { + "message": "Small Caps" + }, + "angle": { + "message": "Angle (°)" + }, "refractiveindex_note": { "message": "(relative if inside another glass)" }, diff --git a/simulator/locales/fr.js b/simulator/locales/fr.js index c960d18a..d9ac32fe 100644 --- a/simulator/locales/fr.js +++ b/simulator/locales/fr.js @@ -360,6 +360,30 @@ locales["fr"] = { "incomplete": true, "message": "Lambertian emission" }, + "fontsize": { + "incomplete": true, + "message": "Font Size (px)" + }, + "fontname": { + "incomplete": true, + "message": "Font" + }, + "fontstyle": { + "incomplete": true, + "message": "Style" + }, + "fontalignment": { + "incomplete": true, + "message": "Alignment" + }, + "smallcaps": { + "incomplete": true, + "message": "Small Caps" + }, + "angle": { + "incomplete": true, + "message": "Angle (°)" + }, "refractiveindex_note": { "incomplete": true, "message": "(relative if inside another glass)" diff --git a/simulator/locales/nl.js b/simulator/locales/nl.js index cbeb8258..cd9cb3ad 100644 --- a/simulator/locales/nl.js +++ b/simulator/locales/nl.js @@ -376,6 +376,30 @@ locales["nl"] = { "incomplete": true, "message": "Lambertian emission" }, + "fontsize": { + "incomplete": true, + "message": "Font Size (px)" + }, + "fontname": { + "incomplete": true, + "message": "Font" + }, + "fontstyle": { + "incomplete": true, + "message": "Style" + }, + "fontalignment": { + "incomplete": true, + "message": "Alignment" + }, + "smallcaps": { + "incomplete": true, + "message": "Small Caps" + }, + "angle": { + "incomplete": true, + "message": "Angle (°)" + }, "refractiveindex_note": { "incomplete": true, "message": "(relative if inside another glass)" diff --git a/simulator/locales/pl.js b/simulator/locales/pl.js index e4a62ddf..a1737054 100644 --- a/simulator/locales/pl.js +++ b/simulator/locales/pl.js @@ -327,6 +327,30 @@ locales["pl"] = { "incomplete": true, "message": "Lambertian emission" }, + "fontsize": { + "incomplete": true, + "message": "Font Size (px)" + }, + "fontname": { + "incomplete": true, + "message": "Font" + }, + "fontstyle": { + "incomplete": true, + "message": "Style" + }, + "fontalignment": { + "incomplete": true, + "message": "Alignment" + }, + "smallcaps": { + "incomplete": true, + "message": "Small Caps" + }, + "angle": { + "incomplete": true, + "message": "Angle (°)" + }, "refractiveindex_note": { "message": "(względny, jeśli znajduje się w innym szkle)" }, diff --git a/simulator/locales/ru.js b/simulator/locales/ru.js index eb90fe00..7bfdb9cd 100644 --- a/simulator/locales/ru.js +++ b/simulator/locales/ru.js @@ -361,6 +361,30 @@ locales["ru"] = { "incomplete": true, "message": "Lambertian emission" }, + "fontsize": { + "incomplete": true, + "message": "Font Size (px)" + }, + "fontname": { + "incomplete": true, + "message": "Font" + }, + "fontstyle": { + "incomplete": true, + "message": "Style" + }, + "fontalignment": { + "incomplete": true, + "message": "Alignment" + }, + "smallcaps": { + "incomplete": true, + "message": "Small Caps" + }, + "angle": { + "incomplete": true, + "message": "Angle (°)" + }, "refractiveindex_note": { "incomplete": true, "message": "(relative if inside another glass)" diff --git a/simulator/locales/template.js b/simulator/locales/template.js index e390dd88..728a37fb 100644 --- a/simulator/locales/template.js +++ b/simulator/locales/template.js @@ -432,6 +432,30 @@ locales["LOCALE_ID"] = { "incomplete": true, "message": "Lambertian emission" }, + "fontsize": { + "incomplete": true, + "message": "Font Size (px)" + }, + "fontname": { + "incomplete": true, + "message": "Font" + }, + "fontstyle": { + "incomplete": true, + "message": "Style" + }, + "fontalignment": { + "incomplete": true, + "message": "Alignment" + }, + "smallcaps": { + "incomplete": true, + "message": "Small Caps" + }, + "angle": { + "incomplete": true, + "message": "Angle (°)" + }, "refractiveindex_note": { "incomplete": true, "message": "(relative if inside another glass)" diff --git a/simulator/locales/zh_CN.js b/simulator/locales/zh_CN.js index 0bad11ea..1a17696b 100644 --- a/simulator/locales/zh_CN.js +++ b/simulator/locales/zh_CN.js @@ -327,6 +327,30 @@ locales["zh-CN"] = { "incomplete": true, "message": "Lambertian emission" }, + "fontsize": { + "incomplete": true, + "message": "Font Size (px)" + }, + "fontname": { + "incomplete": true, + "message": "Font" + }, + "fontstyle": { + "incomplete": true, + "message": "Style" + }, + "fontalignment": { + "incomplete": true, + "message": "Alignment" + }, + "smallcaps": { + "incomplete": true, + "message": "Small Caps" + }, + "angle": { + "incomplete": true, + "message": "Angle (°)" + }, "refractiveindex_note": { "message": "(于另一透光物内部时为相对值)" }, diff --git a/simulator/locales/zh_TW.js b/simulator/locales/zh_TW.js index 54ea7936..a5a7145f 100644 --- a/simulator/locales/zh_TW.js +++ b/simulator/locales/zh_TW.js @@ -326,6 +326,30 @@ locales["zh-TW"] = { "incomplete": true, "message": "Lambertian emission" }, + "fontsize": { + "incomplete": true, + "message": "Font Size (px)" + }, + "fontname": { + "incomplete": true, + "message": "Font" + }, + "fontstyle": { + "incomplete": true, + "message": "Style" + }, + "fontalignment": { + "incomplete": true, + "message": "Alignment" + }, + "smallcaps": { + "incomplete": true, + "message": "Small Caps" + }, + "angle": { + "incomplete": true, + "message": "Angle (°)" + }, "refractiveindex_note": { "message": "(於另一透光物內部時為相對值)" },