|
@ -23,7 +23,7 @@ class LabelAccumulator { |
|
|
* |
|
|
* |
|
|
* @param {number} l index of line to add to |
|
|
* @param {number} l index of line to add to |
|
|
* @param {string} text string to append to line |
|
|
* @param {string} text string to append to line |
|
|
* @param {boolean} mod id of multi-font to use, default 'normal' |
|
|
|
|
|
|
|
|
* @param {'bold'|'ital'|'boldital'|'mono'|'normal'} [mod='normal'] |
|
|
* @private |
|
|
* @private |
|
|
*/ |
|
|
*/ |
|
|
_add(l, text, mod = 'normal') { |
|
|
_add(l, text, mod = 'normal') { |
|
@ -54,6 +54,8 @@ class LabelAccumulator { |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Returns the width in pixels of the current line. |
|
|
* Returns the width in pixels of the current line. |
|
|
|
|
|
* |
|
|
|
|
|
* @returns {number} |
|
|
*/ |
|
|
*/ |
|
|
curWidth() { |
|
|
curWidth() { |
|
|
let line = this.lines[this.current]; |
|
|
let line = this.lines[this.current]; |
|
@ -65,6 +67,9 @@ class LabelAccumulator { |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Add text in block to current line |
|
|
* Add text in block to current line |
|
|
|
|
|
* |
|
|
|
|
|
* @param {string} text |
|
|
|
|
|
* @param {'bold'|'ital'|'boldital'|'mono'|'normal'} [mod='normal'] |
|
|
*/ |
|
|
*/ |
|
|
append(text, mod = 'normal') { |
|
|
append(text, mod = 'normal') { |
|
|
this._add(this.current, text, mod); |
|
|
this._add(this.current, text, mod); |
|
@ -73,8 +78,11 @@ class LabelAccumulator { |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Add text in block to current line and start a new line |
|
|
* Add text in block to current line and start a new line |
|
|
|
|
|
* |
|
|
|
|
|
* @param {string} text |
|
|
|
|
|
* @param {'bold'|'ital'|'boldital'|'mono'|'normal'} [mod='normal'] |
|
|
*/ |
|
|
*/ |
|
|
newLine(text, mod = 'normal') { |
|
|
|
|
|
|
|
|
newLine(text, mod = 'normal') { |
|
|
this._add(this.current, text, mod); |
|
|
this._add(this.current, text, mod); |
|
|
this.current++; |
|
|
this.current++; |
|
|
} |
|
|
} |
|
@ -82,6 +90,8 @@ class LabelAccumulator { |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Set the sizes for all lines and the whole thing. |
|
|
* Set the sizes for all lines and the whole thing. |
|
|
|
|
|
* |
|
|
|
|
|
* @returns {{width: (number|*), height: (number|*), lines: Array}} |
|
|
*/ |
|
|
*/ |
|
|
finalize() { |
|
|
finalize() { |
|
|
// console.log(JSON.stringify(this.lines, null, 2));
|
|
|
// console.log(JSON.stringify(this.lines, null, 2));
|
|
@ -180,10 +190,9 @@ class Label { |
|
|
* - No number conversion (size) |
|
|
* - No number conversion (size) |
|
|
* - Not all font options are set (vadjust, mod) |
|
|
* - Not all font options are set (vadjust, mod) |
|
|
* |
|
|
* |
|
|
* @param inOptions {Object} font options to parse |
|
|
|
|
|
* @param outOptions {Object} out-parameter, object in which to store the parse results (if any) |
|
|
|
|
|
* |
|
|
|
|
|
* @return true if font parsed as string, false otherwise |
|
|
|
|
|
|
|
|
* @param {Object} outOptions out-parameter, object in which to store the parse results (if any) |
|
|
|
|
|
* @param {Object} inOptions font options to parse |
|
|
|
|
|
* @return {boolean} true if font parsed as string, false otherwise |
|
|
*/ |
|
|
*/ |
|
|
static parseFontString(outOptions, inOptions) { |
|
|
static parseFontString(outOptions, inOptions) { |
|
|
if (!inOptions || typeof inOptions !== 'string') return false; |
|
|
if (!inOptions || typeof inOptions !== 'string') return false; |
|
@ -283,6 +292,10 @@ class Label { |
|
|
* |
|
|
* |
|
|
* NOTE: naming of 'groupOptions' is a misnomer; the actual value passed |
|
|
* NOTE: naming of 'groupOptions' is a misnomer; the actual value passed |
|
|
* is the new values to set from setOptions(). |
|
|
* is the new values to set from setOptions(). |
|
|
|
|
|
* |
|
|
|
|
|
* @param {Object} options |
|
|
|
|
|
* @param {Object} groupOptions |
|
|
|
|
|
* @param {Object} defaultOptions |
|
|
*/ |
|
|
*/ |
|
|
propagateFonts(options, groupOptions, defaultOptions) { |
|
|
propagateFonts(options, groupOptions, defaultOptions) { |
|
|
if (!this.fontOptions.multi) return; |
|
|
if (!this.fontOptions.multi) return; |
|
@ -292,10 +305,9 @@ class Label { |
|
|
* If valid, return a reference to the object in question. |
|
|
* If valid, return a reference to the object in question. |
|
|
* Otherwise, just return null. |
|
|
* Otherwise, just return null. |
|
|
* |
|
|
* |
|
|
* param 'mod' is optional. |
|
|
|
|
|
* |
|
|
|
|
|
* options {Object} base object to determine path from |
|
|
|
|
|
* mod {string|undefined} if present, sub path for the mod-font |
|
|
|
|
|
|
|
|
* @param {Object} options base object to determine path from |
|
|
|
|
|
* @param {'bold'|'ital'|'boldital'|'mono'|'normal'} [mod=undefined] if present, sub path for the mod-font |
|
|
|
|
|
* @returns {Object|null} |
|
|
*/ |
|
|
*/ |
|
|
var pathP = function(options, mod) { |
|
|
var pathP = function(options, mod) { |
|
|
if (!options || !options.font) return null; |
|
|
if (!options || !options.font) return null; |
|
@ -315,7 +327,10 @@ class Label { |
|
|
* Get property value from options.font[mod][property] if present. |
|
|
* Get property value from options.font[mod][property] if present. |
|
|
* If mod not passed, use property value from options.font[property]. |
|
|
* If mod not passed, use property value from options.font[property]. |
|
|
* |
|
|
* |
|
|
* @return value if found, null otherwise. |
|
|
|
|
|
|
|
|
* @param {vis.Label.options} options |
|
|
|
|
|
* @param {'bold'|'ital'|'boldital'|'mono'|'normal'} mod |
|
|
|
|
|
* @param {string} property |
|
|
|
|
|
* @return {*|null} value if found, null otherwise. |
|
|
*/ |
|
|
*/ |
|
|
var getP = function(options, mod, property) { |
|
|
var getP = function(options, mod, property) { |
|
|
let opt = pathP(options, mod); |
|
|
let opt = pathP(options, mod); |
|
@ -413,11 +428,12 @@ class Label { |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Main function. This is called from anything that wants to draw a label. |
|
|
* Main function. This is called from anything that wants to draw a label. |
|
|
* @param ctx |
|
|
|
|
|
* @param x |
|
|
|
|
|
* @param y |
|
|
|
|
|
* @param selected |
|
|
|
|
|
* @param baseline |
|
|
|
|
|
|
|
|
* @param {CanvasRenderingContext2D} ctx |
|
|
|
|
|
* @param {number} x |
|
|
|
|
|
* @param {number} y |
|
|
|
|
|
* @param {boolean} selected |
|
|
|
|
|
* @param {boolean} hover |
|
|
|
|
|
* @param {string} [baseline='middle'] |
|
|
*/ |
|
|
*/ |
|
|
draw(ctx, x, y, selected, hover, baseline = 'middle') { |
|
|
draw(ctx, x, y, selected, hover, baseline = 'middle') { |
|
|
// if no label, return
|
|
|
// if no label, return
|
|
@ -473,9 +489,12 @@ class Label { |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* |
|
|
* |
|
|
* @param ctx |
|
|
|
|
|
* @param x |
|
|
|
|
|
* @param baseline |
|
|
|
|
|
|
|
|
* @param {CanvasRenderingContext2D} ctx |
|
|
|
|
|
* @param {boolean} selected |
|
|
|
|
|
* @param {boolean} hover |
|
|
|
|
|
* @param {number} x |
|
|
|
|
|
* @param {number} y |
|
|
|
|
|
* @param {string} [baseline='middle'] |
|
|
* @private |
|
|
* @private |
|
|
*/ |
|
|
*/ |
|
|
_drawText(ctx, selected, hover, x, y, baseline = 'middle') { |
|
|
_drawText(ctx, selected, hover, x, y, baseline = 'middle') { |
|
@ -483,13 +502,14 @@ class Label { |
|
|
let viewFontSize = fontSize * this.body.view.scale; |
|
|
let viewFontSize = fontSize * this.body.view.scale; |
|
|
// this ensures that there will not be HUGE letters on screen by setting an upper limit on the visible text size (regardless of zoomLevel)
|
|
|
// this ensures that there will not be HUGE letters on screen by setting an upper limit on the visible text size (regardless of zoomLevel)
|
|
|
if (viewFontSize >= this.elementOptions.scaling.label.maxVisible) { |
|
|
if (viewFontSize >= this.elementOptions.scaling.label.maxVisible) { |
|
|
|
|
|
// TODO: Does this actually do anything?
|
|
|
fontSize = Number(this.elementOptions.scaling.label.maxVisible) / this.body.view.scale; |
|
|
fontSize = Number(this.elementOptions.scaling.label.maxVisible) / this.body.view.scale; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
let yLine = this.size.yLine; |
|
|
let yLine = this.size.yLine; |
|
|
[x, yLine] = this._setAlignment(ctx, x, yLine, baseline); |
|
|
[x, yLine] = this._setAlignment(ctx, x, yLine, baseline); |
|
|
|
|
|
|
|
|
ctx.textAlign = 'left' |
|
|
|
|
|
|
|
|
ctx.textAlign = 'left'; |
|
|
x = x - this.size.width / 2; // Shift label 1/2-distance to the left
|
|
|
x = x - this.size.width / 2; // Shift label 1/2-distance to the left
|
|
|
if ((this.fontOptions.valign) && (this.size.height > this.size.labelHeight)) { |
|
|
if ((this.fontOptions.valign) && (this.size.height > this.size.labelHeight)) { |
|
|
if (this.fontOptions.valign === 'top') { |
|
|
if (this.fontOptions.valign === 'top') { |
|
@ -531,6 +551,15 @@ class Label { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* |
|
|
|
|
|
* @param {CanvasRenderingContext2D} ctx |
|
|
|
|
|
* @param {Number} x |
|
|
|
|
|
* @param {Number} yLine |
|
|
|
|
|
* @param {String} baseline |
|
|
|
|
|
* @returns {Array<Number>} |
|
|
|
|
|
* @private |
|
|
|
|
|
*/ |
|
|
_setAlignment(ctx, x, yLine, baseline) { |
|
|
_setAlignment(ctx, x, yLine, baseline) { |
|
|
// check for label alignment (for edges)
|
|
|
// check for label alignment (for edges)
|
|
|
// TODO: make alignment for nodes
|
|
|
// TODO: make alignment for nodes
|
|
@ -561,8 +590,10 @@ class Label { |
|
|
* fade in when relative scale is between threshold and threshold - 1. |
|
|
* fade in when relative scale is between threshold and threshold - 1. |
|
|
* If the relative scale would be smaller than threshold -1 the draw function would have returned before coming here. |
|
|
* If the relative scale would be smaller than threshold -1 the draw function would have returned before coming here. |
|
|
* |
|
|
* |
|
|
* @param viewFontSize |
|
|
|
|
|
* @returns {*[]} |
|
|
|
|
|
|
|
|
* @param {string} color The font color to use |
|
|
|
|
|
* @param {number} viewFontSize |
|
|
|
|
|
* @param {string} initialStrokeColor |
|
|
|
|
|
* @returns {Array<string>} An array containing the font color and stroke color |
|
|
* @private |
|
|
* @private |
|
|
*/ |
|
|
*/ |
|
|
_getColor(color, viewFontSize, initialStrokeColor) { |
|
|
_getColor(color, viewFontSize, initialStrokeColor) { |
|
@ -576,11 +607,11 @@ class Label { |
|
|
return [fontColor, strokeColor]; |
|
|
return [fontColor, strokeColor]; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* |
|
|
* |
|
|
* @param ctx |
|
|
|
|
|
* @param selected |
|
|
|
|
|
|
|
|
* @param {CanvasRenderingContext2D} ctx |
|
|
|
|
|
* @param {boolean} selected |
|
|
|
|
|
* @param {boolean} hover |
|
|
* @returns {{width: number, height: number}} |
|
|
* @returns {{width: number, height: number}} |
|
|
*/ |
|
|
*/ |
|
|
getTextSize(ctx, selected = false, hover = false) { |
|
|
getTextSize(ctx, selected = false, hover = false) { |
|
@ -595,11 +626,12 @@ class Label { |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* |
|
|
* |
|
|
* @param ctx |
|
|
|
|
|
* @param selected |
|
|
|
|
|
* @param x |
|
|
|
|
|
* @param y |
|
|
|
|
|
* @param baseline |
|
|
|
|
|
|
|
|
* @param {CanvasRenderingContext2D} ctx |
|
|
|
|
|
* @param {boolean} selected |
|
|
|
|
|
* @param {boolean} hover |
|
|
|
|
|
* @param {number} [x=0] |
|
|
|
|
|
* @param {number} [y=0] |
|
|
|
|
|
* @param {'middle'|'hanging'} [baseline='middle'] |
|
|
*/ |
|
|
*/ |
|
|
calculateLabelSize(ctx, selected, hover, x = 0, y = 0, baseline = 'middle') { |
|
|
calculateLabelSize(ctx, selected, hover, x = 0, y = 0, baseline = 'middle') { |
|
|
if (this.labelDirty === true) { |
|
|
if (this.labelDirty === true) { |
|
@ -618,6 +650,9 @@ class Label { |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* normalize the markup system |
|
|
* normalize the markup system |
|
|
|
|
|
* |
|
|
|
|
|
* @param {boolean|'md'|'markdown'|'html'} markupSystem |
|
|
|
|
|
* @returns {string} |
|
|
*/ |
|
|
*/ |
|
|
decodeMarkupSystem(markupSystem) { |
|
|
decodeMarkupSystem(markupSystem) { |
|
|
let system = 'none'; |
|
|
let system = 'none'; |
|
@ -631,9 +666,9 @@ class Label { |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Explodes a piece of text into single-font blocks using a given markup |
|
|
* Explodes a piece of text into single-font blocks using a given markup |
|
|
* @param text |
|
|
|
|
|
* @param markupSystem |
|
|
|
|
|
* @returns [{ text, mod }] |
|
|
|
|
|
|
|
|
* @param {string} text |
|
|
|
|
|
* @param {boolean|'md'|'markdown'|'html'} markupSystem |
|
|
|
|
|
* @returns {Array<{text: string, mod: string}>} |
|
|
*/ |
|
|
*/ |
|
|
splitBlocks(text, markupSystem) { |
|
|
splitBlocks(text, markupSystem) { |
|
|
let system = this.decodeMarkupSystem(markupSystem); |
|
|
let system = this.decodeMarkupSystem(markupSystem); |
|
@ -926,10 +961,11 @@ class Label { |
|
|
/** |
|
|
/** |
|
|
* This explodes the passed text into lines and determines the width, height and number of lines. |
|
|
* This explodes the passed text into lines and determines the width, height and number of lines. |
|
|
* |
|
|
* |
|
|
* @param ctx |
|
|
|
|
|
* @param selected |
|
|
|
|
|
* @param hover |
|
|
|
|
|
|
|
|
* @param {CanvasRenderingContext2D} ctx |
|
|
|
|
|
* @param {boolean} selected |
|
|
|
|
|
* @param {boolean} hover |
|
|
* @param {String} text the text to explode |
|
|
* @param {String} text the text to explode |
|
|
|
|
|
* @returns {{width, height, lines}|*} |
|
|
* @private |
|
|
* @private |
|
|
*/ |
|
|
*/ |
|
|
_processLabelText(ctx, selected, hover, text) { |
|
|
_processLabelText(ctx, selected, hover, text) { |
|
@ -972,7 +1008,7 @@ class Label { |
|
|
let overMaxWidth = function(text) { |
|
|
let overMaxWidth = function(text) { |
|
|
let width = ctx.measureText(text).width; |
|
|
let width = ctx.measureText(text).width; |
|
|
return (lines.curWidth() + width > self.fontOptions.maxWdt); |
|
|
return (lines.curWidth() + width > self.fontOptions.maxWdt); |
|
|
} |
|
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
@ -980,7 +1016,7 @@ class Label { |
|
|
* current max width. |
|
|
* current max width. |
|
|
* |
|
|
* |
|
|
* @param {Array} words Array of strings signifying a text lines |
|
|
* @param {Array} words Array of strings signifying a text lines |
|
|
* @return index of first item in string making string go over max |
|
|
|
|
|
|
|
|
* @return {number} index of first item in string making string go over max |
|
|
*/ |
|
|
*/ |
|
|
let getLongestFit = function(words) { |
|
|
let getLongestFit = function(words) { |
|
|
let text = ''; |
|
|
let text = ''; |
|
@ -996,25 +1032,25 @@ class Label { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return w; |
|
|
return w; |
|
|
} |
|
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Determine the longest part of th string which still fits in the |
|
|
|
|
|
|
|
|
* Determine the longest part of the string which still fits in the |
|
|
* current max width. |
|
|
* current max width. |
|
|
* |
|
|
* |
|
|
* @param {Array} words Array of strings signifying a text lines |
|
|
* @param {Array} words Array of strings signifying a text lines |
|
|
* @return index of first item in string making string go over max |
|
|
|
|
|
|
|
|
* @return {number} index of first item in string making string go over max |
|
|
*/ |
|
|
*/ |
|
|
let getLongestFitWord = function(word) { |
|
|
|
|
|
|
|
|
let getLongestFitWord = function(words) { |
|
|
let w = 0; |
|
|
let w = 0; |
|
|
|
|
|
|
|
|
while (w < word.length) { |
|
|
|
|
|
if (overMaxWidth(word.slice(0,w))) break; |
|
|
|
|
|
|
|
|
while (w < words.length) { |
|
|
|
|
|
if (overMaxWidth(words.slice(0,w))) break; |
|
|
w++; |
|
|
w++; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return w; |
|
|
return w; |
|
|
} |
|
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let splitStringIntoLines = function(str, mod = 'normal', appendLast = false) { |
|
|
let splitStringIntoLines = function(str, mod = 'normal', appendLast = false) { |
|
@ -1046,7 +1082,7 @@ class Label { |
|
|
words = words.slice(w); |
|
|
words = words.slice(w); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let nlLines = String(text).split('\n'); |
|
|
let nlLines = String(text).split('\n'); |
|
@ -1104,9 +1140,9 @@ class Label { |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* This explodes the label string into lines and sets the width, height and number of lines. |
|
|
* This explodes the label string into lines and sets the width, height and number of lines. |
|
|
* @param ctx |
|
|
|
|
|
* @param selected |
|
|
|
|
|
* @param hover |
|
|
|
|
|
|
|
|
* @param {CanvasRenderingContext2D} ctx |
|
|
|
|
|
* @param {boolean} selected |
|
|
|
|
|
* @param {boolean} hover |
|
|
* @private |
|
|
* @private |
|
|
*/ |
|
|
*/ |
|
|
_processLabel(ctx, selected, hover) { |
|
|
_processLabel(ctx, selected, hover) { |
|
|