Skip to content

Commit

Permalink
Upgrated text functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
dorrington committed May 22, 2023
1 parent fa57115 commit 6502cce
Show file tree
Hide file tree
Showing 11 changed files with 373 additions and 12 deletions.
114 changes: 102 additions & 12 deletions simulator/js/objs/text.js
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand All @@ -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;
Expand All @@ -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;
},

};
61 changes: 61 additions & 0 deletions simulator/js/parameterBox.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 = '&nbsp;' + label + '&nbsp;';
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';
Expand Down Expand Up @@ -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 = '&nbsp;' + label + '&nbsp;';
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;
Expand Down
24 changes: 24 additions & 0 deletions simulator/locales/de.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)"
},
Expand Down
18 changes: 18 additions & 0 deletions simulator/locales/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)"
},
Expand Down
24 changes: 24 additions & 0 deletions simulator/locales/fr.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)"
Expand Down
24 changes: 24 additions & 0 deletions simulator/locales/nl.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)"
Expand Down
24 changes: 24 additions & 0 deletions simulator/locales/pl.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)"
},
Expand Down
Loading

0 comments on commit 6502cce

Please sign in to comment.