diff --git a/qml/LogGraph.qml b/qml/LogGraph.qml
index d2b3cc2..865c9a0 100644
--- a/qml/LogGraph.qml
+++ b/qml/LogGraph.qml
@@ -66,8 +66,8 @@ ApplicationWindow {
anchors.left: parent.left
anchors.topMargin: 5
anchors.leftMargin: 5
+ anchors.bottom: parent.bottom
width: parent.width - 10
- height: parent.height - sidebarContents.x;
currentIndex: sidebarSelector.currentIndex
z: -1
clip: true
@@ -101,12 +101,10 @@ ApplicationWindow {
yaxisstep: settings.yaxisstep
xaxisstep: settings.xaxisstep
logscalex: settings.logscalex
+ linewidth: settings.linewidth
+ textsize: settings.textsize
showxgrad: settings.showxgrad
showygrad: settings.showygrad
-
- onPaint: {
- var ctx = getContext("2d");
- }
}
function saveDiagram(filename) {
@@ -130,6 +128,8 @@ ApplicationWindow {
"xaxislabel": settings.xaxislabel,
"yaxislabel": settings.yaxislabel,
"logscalex": settings.logscalex,
+ "linewidth": settings.linewidth,
+ "textsize": settings.textsize,
"width": root.width,
"height": root.height,
"objects": objs,
@@ -151,6 +151,10 @@ ApplicationWindow {
settings.xaxislabel = data["xaxislabel"]
settings.yaxislabel = data["yaxislabel"]
settings.logscalex = data["logscalex"]
+ if("linewidth" in data)
+ settings.linewidth = data["linewidth"]
+ if("textsize" in data)
+ settings.textsize = data["textsize"]
root.height = data["height"]
root.width = data["width"]
@@ -176,6 +180,8 @@ ApplicationWindow {
} else {
objectLists.update()
}
+ } else {
+ error = "Invalid file provided."
}
if(error != "") {
diff --git a/qml/LogGraphCanvas.qml b/qml/LogGraphCanvas.qml
index fadbde3..cbad153 100644
--- a/qml/LogGraphCanvas.qml
+++ b/qml/LogGraphCanvas.qml
@@ -38,6 +38,8 @@ Canvas {
property string xlabel: ""
property string ylabel: ""
property int maxgradx: 8
+ property double linewidth: 1
+ property double textsize: 14
property bool logscalex: false
property bool showxgrad: false
property bool showygrad: false
@@ -56,6 +58,7 @@ Canvas {
reset(ctx)
drawGrille(ctx)
drawAxises(ctx)
+ ctx.lineWidth = linewidth
for(var objType in Objects.currentObjects) {
for(var obj of Objects.currentObjects[objType]){
ctx.strokeStyle = obj.color
@@ -63,6 +66,7 @@ Canvas {
if(obj.visible) obj.draw(canvas, ctx)
}
}
+ ctx.lineWidth = 1
drawLabels(ctx)
}
@@ -71,7 +75,7 @@ Canvas {
// Reset
ctx.fillStyle = "#FFFFFF"
ctx.strokeStyle = "#000000"
- ctx.font = "12px sans-serif"
+ ctx.font = `${canvas.textsize-2}px sans-serif`
ctx.fillRect(0,0,width,height)
}
@@ -115,12 +119,12 @@ Canvas {
var axisxpx = y2px(0) // Y coordinate of X axis
// Labels
ctx.fillStyle = "#000000"
- ctx.font = "16px sans-serif"
- ctx.fillText(ylabel, axisypx+5, 24)
+ ctx.font = `${canvas.textsize+2}px sans-serif`
+ ctx.fillText(ylabel, axisypx+10, 24)
var textSize = ctx.measureText(xlabel).width
ctx.fillText(xlabel, canvasSize.width-14-textSize, axisxpx-5)
// Axis graduation labels
- ctx.font = "12px sans-serif"
+ ctx.font = `${canvas.textsize-2}px sans-serif`
var txtMinus = ctx.measureText('-').width
if(showxgrad) {
@@ -135,8 +139,8 @@ Canvas {
var drawX = x*xaxisstep1
var txtX = xaxisstepExpr.simplify(x)
var textSize = measureText(ctx, txtX, 6).height
- drawVisibleText(ctx, txtX, x2px(drawX)-4, axisxpx+6+textSize)
- drawVisibleText(ctx, '-'+txtX, x2px(-drawX)-4, axisxpx+6+textSize)
+ drawVisibleText(ctx, txtX, x2px(drawX)-4, axisxpx+textsize/2+textSize)
+ drawVisibleText(ctx, '-'+txtX, x2px(-drawX)-4, axisxpx+textsize/2+textSize)
}
}
}
@@ -165,20 +169,20 @@ Canvas {
}
}
- function drawVisibleText(ctx, text, x, y, lineHeight = 14) {
+ function drawVisibleText(ctx, text, x, y) {
if(x > 0 && x < canvasSize.width && y > 0 && y < canvasSize.height) {
text.toString().split("\n").forEach(function(txt, i){
- ctx.fillText(txt, x, y+(lineHeight*i))
+ ctx.fillText(txt, x, y+(canvas.textsize*i))
})
}
}
// Method to calculate multi-line string dimensions
- function measureText(ctx, text, lineHeight=14) {
+ function measureText(ctx, text) {
var theight = 0
var twidth = 0
text.split("\n").forEach(function(txt, i){
- theight += lineHeight
+ theight += canvas.textsize
if(ctx.measureText(txt).width > twidth) twidth = ctx.measureText(txt).width
})
return {'width': twidth, 'height': theight}
@@ -217,6 +221,12 @@ Canvas {
ctx.stroke();
}
+ function drawDashedLine2(ctx, x1, y1, x2, y2, dashPxSize = 5) {
+ ctx.setLineDash([dashPxSize, dashPxSize]);
+ drawLine(ctx, x1, y1, x2, y2)
+ ctx.setLineDash([]);
+ }
+
function drawDashedLine(ctx, x1, y1, x2, y2, dashPxSize = 10) {
var distance = Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))
var progPerc = dashPxSize/distance
diff --git a/qml/Settings.qml b/qml/Settings.qml
index 358f2ab..549b9d6 100644
--- a/qml/Settings.qml
+++ b/qml/Settings.qml
@@ -35,15 +35,18 @@ ScrollView {
property string yaxisstep: "4"
property string xaxislabel: ""
property string yaxislabel: ""
+ property double linewidth: 1
+ property double textsize: 14
property bool logscalex: true
property string saveFilename: ""
property bool showxgrad: true
property bool showygrad: true
Column {
- height: 30*9 //30*Math.max(1, Math.ceil(7 / columns))
+ //height: 30*12 //30*Math.max(1, Math.ceil(7 / columns))
//columns: Math.floor(width / settingWidth)
spacing: 10
+
FileDialog {
id: fdiag
onAccepted: {
@@ -61,7 +64,6 @@ ScrollView {
}
}
- // Line 1
// Zoom
TextSetting {
id: zoomX
@@ -120,6 +122,20 @@ ScrollView {
}
}
+ TextSetting {
+ id: xAxisStep
+ height: 30
+ label: "X Axis Step"
+ icon: "icons/settings/xaxisstep.svg"
+ width: settings.settingWidth
+ defValue: settings.xaxisstep
+ visible: !settings.logscalex
+ onChanged: function(newValue) {
+ settings.xaxisstep = newValue
+ settings.changed()
+ }
+ }
+
TextSetting {
id: yAxisStep
height: 30
@@ -134,15 +150,31 @@ ScrollView {
}
TextSetting {
- id: xAxisStep
+ id: lineWidth
height: 30
- label: "X Axis Step"
- icon: "icons/settings/xaxisstep.svg"
+ isDouble: true
+ label: "Line width"
+ min: 1
+ icon: "icons/settings/linewidth.svg"
width: settings.settingWidth
- defValue: settings.xaxisstep
- visible: !settings.logscalex
+ defValue: settings.linewidth
onChanged: function(newValue) {
- settings.xaxisstep = newValue
+ settings.linewidth = newValue
+ settings.changed()
+ }
+ }
+
+ TextSetting {
+ id: textSize
+ height: 30
+ isDouble: true
+ label: "Text size (px)"
+ min: 1
+ icon: "icons/settings/textsize.svg"
+ width: settings.settingWidth
+ defValue: settings.textsize
+ onChanged: function(newValue) {
+ settings.textsize = newValue
settings.changed()
}
}
diff --git a/qml/icons/settings/linewidth.svg b/qml/icons/settings/linewidth.svg
new file mode 100644
index 0000000..3152404
--- /dev/null
+++ b/qml/icons/settings/linewidth.svg
@@ -0,0 +1,80 @@
+
+
diff --git a/qml/icons/settings/textsize.svg b/qml/icons/settings/textsize.svg
new file mode 100644
index 0000000..45f0ebd
--- /dev/null
+++ b/qml/icons/settings/textsize.svg
@@ -0,0 +1,104 @@
+
+
diff --git a/qml/js/mathlib.js b/qml/js/mathlib.js
index 60375ea..195796e 100644
--- a/qml/js/mathlib.js
+++ b/qml/js/mathlib.js
@@ -42,6 +42,13 @@ parser.functions.integral = function(a, b, f, variable) {
return (b-a)/6*(f(a)+4*f((a+b)/2)+f(b))
}
+const DERIVATION_PRECISION = 0.1
+
+parser.functions.derivative = function(f, variable, x) {
+ f = parser.parse(f).toJSFunction(variable, currentVars)
+ return (f(x+DERIVATION_PRECISION/2)-f(x-DERIVATION_PRECISION/2))/DERIVATION_PRECISION
+}
+
class Expression {
constructor(expr) {
this.expr = expr
diff --git a/qml/js/objects.js b/qml/js/objects.js
index f5d9c24..bb9c9ec 100644
--- a/qml/js/objects.js
+++ b/qml/js/objects.js
@@ -163,7 +163,7 @@ class Point extends DrawableObject {
break;
}
var text = this.getLabel()
- ctx.font = "14px sans-serif"
+ ctx.font = `${canvas.textsize}px sans-serif`
var textSize = ctx.measureText(text).width
switch(this.labelPosition) {
case 'top':
@@ -266,8 +266,8 @@ class Function extends ExecutableObject {
Function.drawFunction(canvas, ctx, this.expression, this.definitionDomain, this.destinationDomain, this.drawPoints, this.drawDashedLines)
// Label
var text = this.getLabel()
- ctx.font = "14px sans-serif"
- var textSize = canvas.measureText(ctx, text, 7)
+ ctx.font = `${canvas.textsize}px sans-serif`
+ var textSize = canvas.measureText(ctx, text)
var posX = canvas.x2px(this.labelX)
var posY = canvas.y2px(this.execute(this.labelX))
switch(this.labelPosition) {
@@ -439,8 +439,8 @@ class GainBode extends ExecutableObject {
// Label
var text = this.getLabel()
- ctx.font = "14px sans-serif"
- var textSize = canvas.measureText(ctx, text, 7)
+ ctx.font = `${canvas.textsize}px sans-serif`
+ var textSize = canvas.measureText(ctx, text)
var posX = canvas.x2px(this.labelX)
var posY = canvas.y2px(this.execute(this.labelX))
switch(this.labelPosition) {
@@ -588,8 +588,8 @@ class SommeGainsBode extends DrawableObject {
if(inDrawDom.includes(this.labelX)) {
// Label
var text = this.getLabel()
- ctx.font = "14px sans-serif"
- var textSize = canvas.measureText(ctx, text, 7)
+ ctx.font = `${canvas.textsize}px sans-serif`
+ var textSize = canvas.measureText(ctx, text)
var posX = canvas.x2px(this.labelX)
var posY = canvas.y2px(dbfn.execute(this.labelX))
switch(this.labelPosition) {
@@ -712,8 +712,8 @@ class PhaseBode extends ExecutableObject {
// Label
var text = this.getLabel()
- ctx.font = "14px sans-serif"
- var textSize = canvas.measureText(ctx, text, 7)
+ ctx.font = `${canvas.textsize}px sans-serif`
+ var textSize = canvas.measureText(ctx, text)
var posX = canvas.x2px(this.labelX)
var posY = canvas.y2px(this.execute(this.labelX))
switch(this.labelPosition) {
@@ -848,8 +848,8 @@ class SommePhasesBode extends ExecutableObject {
// Label
var text = this.getLabel()
- ctx.font = "14px sans-serif"
- var textSize = canvas.measureText(ctx, text, 7)
+ ctx.font = `${canvas.textsize}px sans-serif`
+ var textSize = canvas.measureText(ctx, text)
var posX = canvas.x2px(this.labelX)
var posY = canvas.y2px(this.execute(this.labelX))
switch(this.labelPosition) {
@@ -993,8 +993,8 @@ class CursorX extends DrawableObject {
// Label
var text = this.getLabel()
- ctx.font = "14px sans-serif"
- var textSize = canvas.measureText(ctx, text, 7)
+ ctx.font = `${canvas.textsize}px sans-serif`
+ var textSize = canvas.measureText(ctx, text)
switch(this.labelPosition) {
case 'left':
@@ -1007,7 +1007,7 @@ class CursorX extends DrawableObject {
if(this.targetValuePosition == 'Next to target' && this.getTargetElement() != null) {
var text = this.getTargetValueLabel()
- var textSize = canvas.measureText(ctx, text, 7)
+ var textSize = canvas.measureText(ctx, text)
var ypox = canvas.y2px(this.getTargetElement().execute(this.x.execute()))
switch(this.labelPosition) {
case 'left':
@@ -1103,8 +1103,8 @@ class Sequence extends ExecutableObject {
// Label
var text = this.getLabel()
- ctx.font = "14px sans-serif"
- var textSize = canvas.measureText(ctx, text, 7)
+ ctx.font = `${canvas.textsize}px sans-serif`
+ var textSize = canvas.measureText(ctx, text)
var posX = canvas.x2px(this.labelX)
var posY = canvas.y2px(this.execute(this.labelX))
switch(this.labelPosition) {
@@ -1253,8 +1253,8 @@ class RepartitionFunction extends ExecutableObject {
// Label
var text = this.getLabel()
- ctx.font = "14px sans-serif"
- var textSize = canvas.measureText(ctx, text, 7)
+ ctx.font = `${canvas.textsize}px sans-serif`
+ var textSize = canvas.measureText(ctx, text)
var posX = canvas.x2px(this.labelX)
var posY = canvas.y2px(this.execute(this.labelX))
switch(this.labelPosition) {
diff --git a/qml/js/utils.js b/qml/js/utils.js
index d5891c8..3258b2c 100644
--- a/qml/js/utils.js
+++ b/qml/js/utils.js
@@ -252,20 +252,22 @@ function makeExpressionReadable(str) {
[/ \* /g, '×'],
[/ \^ /g, '^'],
[/\^\(([^\^]+)\)/g, function(match, p1) { return textsup(p1) }],
- [/\^([^ ]+)/g, function(match, p1) { return textsup(p1) }],
+ [/\^([^ "]+)/g, function(match, p1) { return textsup(p1) }],
[/_\(([^_]+)\)/g, function(match, p1) { return textsub(p1) }],
- [/_([^ ]+)/g, function(match, p1) { return textsub(p1) }],
+ [/_([^ "]+)/g, function(match, p1) { return textsub(p1) }],
[/\[([^\[\]]+)\]/g, function(match, p1) { return textsub(p1) }],
[/(\d|\))×/g, '$1'],
//[/×(\d|\()/g, '$1'],
[/\(([^)(+.\/-]+)\)/g, "$1"],
- [/integral\((.+), ?(.+), ("|')(.+)("|'), ?("|')(.+)("|')\)/g, function(match, a, b, p1, body, p2, p3, by, p4) {
- console.log('Intégrale', a, b, body, by)
+ [/integral\((.+), ?(.+), ?("|')(.+)("|'), ?("|')(.+)("|')\)/g, function(match, a, b, p1, body, p2, p3, by, p4) {
if(a.length < b.length) {
return `∫${textsub(a)}${textsup(b)} ${body} d${by}`
} else {
return `∫${textsup(b)}${textsub(a)} ${body} d${by}`
}
+ }],
+ [/derivative\(?("|')(.+)("|'), ?("|')(.+)("|'), ?(.+)\)?/g, function(match, p1, body, p2, p3, by, p4, x) {
+ return `d(${body.replace(new RegExp(by, 'g'), 'x')})/dx`
}]
]
@@ -315,7 +317,7 @@ function parseName(str, removeUnallowed = true) {
[/([^a-z]|^)gom(ega)?([^a-z]|$)/g, '$1Ω$3'],
// Underscores
[/_\(([^_]+)\)/g, function(match, p1) { return textsub(p1) }],
- [/_([^ ]+)/g, function(match, p1) { return textsub(p1) }],
+ [/_([^" ]+)/g, function(match, p1) { return textsub(p1) }],
// Array elements
[/\[([^\]\[]+)\]/g, function(match, p1) { return textsub(p1) }],
// Removing