linny-r 2.1.4 → 2.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/static/index.html +33 -3
- package/static/linny-r.css +53 -5
- package/static/scripts/linny-r-ctrl.js +3 -0
- package/static/scripts/linny-r-gui-chart-manager.js +12 -9
- package/static/scripts/linny-r-gui-controller.js +32 -25
- package/static/scripts/linny-r-gui-dataset-manager.js +8 -1
- package/static/scripts/linny-r-gui-experiment-manager.js +28 -16
- package/static/scripts/linny-r-gui-finder.js +266 -24
- package/static/scripts/linny-r-gui-paper.js +52 -51
- package/static/scripts/linny-r-gui-power-grid-manager.js +6 -0
- package/static/scripts/linny-r-gui-sensitivity-analysis.js +5 -6
- package/static/scripts/linny-r-milp.js +10 -1
- package/static/scripts/linny-r-model.js +69 -44
- package/static/scripts/linny-r-utils.js +42 -30
- package/static/scripts/linny-r-vm.js +50 -15
package/package.json
CHANGED
package/static/index.html
CHANGED
@@ -2381,6 +2381,14 @@ NOTE: * and ? will be interpreted as wildcards"
|
|
2381
2381
|
<div id="variable-color" title="Click to copy, Shift-click to paste"></div>
|
2382
2382
|
<div id="variable-paste-color"></div>
|
2383
2383
|
</div>
|
2384
|
+
<div id="variable-absolute-div"
|
2385
|
+
title="Plot the absolute value of this variable"
|
2386
|
+
style="margin: 2px -2px">
|
2387
|
+
<div id="variable-absolute" class="box clear"></div>
|
2388
|
+
<div style="display:inline-block; vertical-align:top; margin-top: 3px">
|
2389
|
+
Absolute
|
2390
|
+
</div>
|
2391
|
+
</div>
|
2384
2392
|
<div id="variable-scale-div" style="margin-top: 3px">
|
2385
2393
|
<div style="display:inline-block; vertical-align:top; margin-top: 2px">
|
2386
2394
|
Scale by:
|
@@ -3170,6 +3178,12 @@ where X can be one or several of these letters: ABCDELPQ">
|
|
3170
3178
|
<img id="finder-chart-btn" class="btn enab"
|
3171
3179
|
src="images/chart.png"
|
3172
3180
|
title="Add attribute to chart">
|
3181
|
+
<img id="finder-experiment-btn" class="btn enab"
|
3182
|
+
src="images/experiment.png"
|
3183
|
+
title="Only consider experiment outcomes">
|
3184
|
+
<img id="finder-table-btn" class="btn enab"
|
3185
|
+
src="images/table.png"
|
3186
|
+
title="View entity attribute values">
|
3173
3187
|
<img id="finder-copy-btn" class="btn enab"
|
3174
3188
|
src="images/table-to-clpbrd.png"
|
3175
3189
|
title="Copy entity attributes to clipboard">
|
@@ -3185,6 +3199,14 @@ where X can be one or several of these letters: ABCDELPQ">
|
|
3185
3199
|
<table id="finder-expression-table">
|
3186
3200
|
</table>
|
3187
3201
|
</div>
|
3202
|
+
<div id="finder-data-pane">
|
3203
|
+
<table id="finder-data-header">
|
3204
|
+
</table>
|
3205
|
+
<div id="finder-data-scroll-area">
|
3206
|
+
<table id="finder-data-table">
|
3207
|
+
</table>
|
3208
|
+
</div>
|
3209
|
+
</div>
|
3188
3210
|
<div id="finder-resize" class="resizer"></div>
|
3189
3211
|
</div>
|
3190
3212
|
|
@@ -3198,13 +3220,21 @@ where X can be one or several of these letters: ABCDELPQ">
|
|
3198
3220
|
<img class="ok-btn" src="images/ok.png">
|
3199
3221
|
</div>
|
3200
3222
|
<div style="margin: 2px; padding-right: 2px; white-space: nowrap">
|
3201
|
-
<
|
3202
|
-
|
3223
|
+
<div id="confirm-add-chart-variables-attr-of">
|
3224
|
+
<select id="confirm-add-chart-variables-attribute"></select> of
|
3225
|
+
</div>
|
3226
|
+
<span id="confirm-add-chart-variables-count"></span>
|
3227
|
+
</div>
|
3228
|
+
<div>
|
3229
|
+
<div id="confirm-add-chart-variables-absolute" class="box clear"></div>
|
3230
|
+
<div style="display:inline-block; vertical-align:top; margin-top: 3px">
|
3231
|
+
Plot absolute values
|
3232
|
+
</div>
|
3203
3233
|
</div>
|
3204
3234
|
<div>
|
3205
3235
|
<div id="confirm-add-chart-variables-stacked" class="box clear"></div>
|
3206
3236
|
<div style="display:inline-block; vertical-align:top; margin-top: 3px">
|
3207
|
-
|
3237
|
+
Plot as stacked areas
|
3208
3238
|
</div>
|
3209
3239
|
</div>
|
3210
3240
|
</div>
|
package/static/linny-r.css
CHANGED
@@ -1167,6 +1167,10 @@ table.power-flow th:not(:first-child) {
|
|
1167
1167
|
filter: brightness(160%);
|
1168
1168
|
}
|
1169
1169
|
|
1170
|
+
#settings-power-btn.ignore {
|
1171
|
+
filter: hue-rotate(230deg);
|
1172
|
+
}
|
1173
|
+
|
1170
1174
|
#password-dlg {
|
1171
1175
|
width: min-content;
|
1172
1176
|
height: min-content;
|
@@ -2660,6 +2664,7 @@ div.io-box {
|
|
2660
2664
|
#finder-table,
|
2661
2665
|
#finder-item-table,
|
2662
2666
|
#finder-expression-table,
|
2667
|
+
#finder-data-table,
|
2663
2668
|
#boundline-data-series-table,
|
2664
2669
|
#boundline-data-sel-table,
|
2665
2670
|
#restore-table {
|
@@ -2918,8 +2923,8 @@ td.dataset-selector {
|
|
2918
2923
|
}
|
2919
2924
|
|
2920
2925
|
td.equation-selector {
|
2921
|
-
|
2922
|
-
max-width:
|
2926
|
+
padding-right: 6px;
|
2927
|
+
max-width: 200px;
|
2923
2928
|
white-space: nowrap;
|
2924
2929
|
overflow: hidden;
|
2925
2930
|
text-overflow: ellipsis;
|
@@ -2964,11 +2969,12 @@ td.equation-expression {
|
|
2964
2969
|
}
|
2965
2970
|
|
2966
2971
|
td.equation-expression {
|
2967
|
-
|
2972
|
+
width: 85%;
|
2968
2973
|
}
|
2969
2974
|
|
2970
2975
|
td.equation-expression-multi {
|
2971
2976
|
border-left: solid 1px Silver;
|
2977
|
+
width: 85%;
|
2972
2978
|
white-space: normal;
|
2973
2979
|
overflow-x: hidden;
|
2974
2980
|
overflow-y: auto;
|
@@ -3428,6 +3434,9 @@ td.vbl-desc-lead::after {
|
|
3428
3434
|
color: #b00080;
|
3429
3435
|
}
|
3430
3436
|
|
3437
|
+
td.vbl-abs {
|
3438
|
+
color: #0050d0 !important;
|
3439
|
+
}
|
3431
3440
|
|
3432
3441
|
#chart-variables {
|
3433
3442
|
position: absolute;
|
@@ -3604,8 +3613,8 @@ img.v-disab {
|
|
3604
3613
|
}
|
3605
3614
|
|
3606
3615
|
#variable-dlg {
|
3607
|
-
width:
|
3608
|
-
height:
|
3616
|
+
width: 245px;
|
3617
|
+
height: 170px;
|
3609
3618
|
}
|
3610
3619
|
|
3611
3620
|
#variable-dlg-name {
|
@@ -5156,6 +5165,8 @@ img.finder {
|
|
5156
5165
|
|
5157
5166
|
#finder-edit-btn,
|
5158
5167
|
#finder-chart-btn,
|
5168
|
+
#finder-experiment-btn,
|
5169
|
+
#finder-table-btn,
|
5159
5170
|
#finder-copy-btn {
|
5160
5171
|
height: 15px;
|
5161
5172
|
width: 15px;
|
@@ -5207,9 +5218,46 @@ img.finder {
|
|
5207
5218
|
border-top: 1px solid Silver;
|
5208
5219
|
}
|
5209
5220
|
|
5221
|
+
#finder-data-pane {
|
5222
|
+
position: absolute;
|
5223
|
+
background-color: inherit;
|
5224
|
+
top: 23px;
|
5225
|
+
left: calc(50% + 4px);
|
5226
|
+
width: calc(50% - 4px);
|
5227
|
+
height: calc(100% - 30px);
|
5228
|
+
}
|
5229
|
+
|
5230
|
+
#finder-data-header {
|
5231
|
+
height: 20px;
|
5232
|
+
font-weight: bold;
|
5233
|
+
text-align: right;
|
5234
|
+
width: 100%
|
5235
|
+
}
|
5236
|
+
|
5237
|
+
#finder-data-scroll-area {
|
5238
|
+
width: calc(100% - 2px);
|
5239
|
+
height: calc(100% - 32px);
|
5240
|
+
overflow-y: auto;
|
5241
|
+
border-top: 1px solid Silver;
|
5242
|
+
}
|
5243
|
+
|
5244
|
+
#finder-data-table {
|
5245
|
+
text-align: right;
|
5246
|
+
}
|
5247
|
+
|
5248
|
+
#finder-data-header > tbody > tr > td:last-child,
|
5249
|
+
#finder-data-table > tbody > tr > td:last-child {
|
5250
|
+
padding-right: 3%;
|
5251
|
+
}
|
5252
|
+
|
5210
5253
|
#confirm-add-chart-variables-dlg {
|
5211
5254
|
width: min-content;
|
5212
5255
|
height: min-content;
|
5256
|
+
min-width: 135px;
|
5257
|
+
}
|
5258
|
+
|
5259
|
+
#confirm-add-chart-variables-attr-of {
|
5260
|
+
display: inline-block;
|
5213
5261
|
}
|
5214
5262
|
|
5215
5263
|
#confirm-add-chart-variables-attribute {
|
@@ -986,11 +986,14 @@ class SensitivityAnalysis {
|
|
986
986
|
UI.alert(`Parameter ${p} is not a dataset or expression`);
|
987
987
|
}
|
988
988
|
}
|
989
|
+
// Create the SA chart having a variable for each SA outcome.
|
989
990
|
this.chart = new Chart(this.chart_title);
|
990
991
|
for(const o of MODEL.sensitivity_outcomes) {
|
991
992
|
this.chart.addVariable(...o.split(UI.OA_SEPARATOR));
|
992
993
|
}
|
994
|
+
// Create the SA experiment.
|
993
995
|
this.experiment = new Experiment(this.experiment_title);
|
996
|
+
// Add the SA chart so the outcomes become result variables.
|
994
997
|
this.experiment.charts = [this.chart];
|
995
998
|
this.experiment.inferVariables();
|
996
999
|
// This experiment always uses the same combination: the base selectors.
|
@@ -125,7 +125,7 @@ class GUIChartManager extends ChartManager {
|
|
125
125
|
document.getElementById('chart-copy-data-btn').addEventListener(
|
126
126
|
'click', () => CHART_MANAGER.copyData());
|
127
127
|
document.getElementById('chart-copy-table-btn').addEventListener(
|
128
|
-
'click', () => CHART_MANAGER.copyTable());
|
128
|
+
'click', (event) => CHART_MANAGER.copyTable(event.shiftKey));
|
129
129
|
document.getElementById('chart-save-btn').addEventListener(
|
130
130
|
'click', () => CHART_MANAGER.downloadChart(event.shiftKey));
|
131
131
|
document.getElementById('chart-widen-btn').addEventListener(
|
@@ -164,8 +164,8 @@ class GUIChartManager extends ChartManager {
|
|
164
164
|
'click', (event) => CHART_MANAGER.copyPasteColor(event));
|
165
165
|
// NOTE: Uses the color picker developed by James Daniel.
|
166
166
|
this.color_picker = new iro.ColorPicker("#color-picker", {
|
167
|
-
width:
|
168
|
-
height:
|
167
|
+
width: 115,
|
168
|
+
height: 115,
|
169
169
|
color: '#a00',
|
170
170
|
markerRadius: 10,
|
171
171
|
padding: 1,
|
@@ -209,7 +209,7 @@ class GUIChartManager extends ChartManager {
|
|
209
209
|
this.variable_index = -1;
|
210
210
|
this.stretch_factor = 1;
|
211
211
|
this.drawing_graph = false;
|
212
|
-
// Clear the model-related DOM elements
|
212
|
+
// Clear the model-related DOM elements.
|
213
213
|
this.chart_selector.innerHTML = '';
|
214
214
|
this.variables_table.innerHTML = '';
|
215
215
|
this.options_shown = true;
|
@@ -391,7 +391,7 @@ class GUIChartManager extends ChartManager {
|
|
391
391
|
(cv.visible ? ' checked' : ' clear'),
|
392
392
|
'" onclick="CHART_MANAGER.toggleVariable(', i,
|
393
393
|
');"></div></td><td class="v-name vbl-', cv.sorted,
|
394
|
-
'">', cv.displayName,
|
394
|
+
(cv.absolute ? ' vbl-abs' : ''), '">', cv.displayName,
|
395
395
|
'</td></tr>'].join(''));
|
396
396
|
}
|
397
397
|
this.variables_table.innerHTML = ol.join('');
|
@@ -641,7 +641,8 @@ class GUIChartManager extends ChartManager {
|
|
641
641
|
for(const cv of c.variables) {
|
642
642
|
const nv = new ChartVariable(nc);
|
643
643
|
nv.setProperties(cv.object, cv.attribute, cv.stacked,
|
644
|
-
cv.color, cv.scale_factor, cv.
|
644
|
+
cv.color, cv.scale_factor, cv.absolute, cv.line_width,
|
645
|
+
cv.visible, cv.sorted);
|
645
646
|
nc.variables.push(nv);
|
646
647
|
}
|
647
648
|
this.chart_index = MODEL.indexOfChart(nc.title);
|
@@ -844,6 +845,7 @@ class GUIChartManager extends ChartManager {
|
|
844
845
|
const cv = MODEL.charts[this.chart_index].variables[this.variable_index];
|
845
846
|
document.getElementById('variable-dlg-name').innerHTML = cv.displayName;
|
846
847
|
UI.setBox('variable-stacked', cv.stacked);
|
848
|
+
UI.setBox('variable-absolute', cv.absolute);
|
847
849
|
// Pass TRUE tiny flag to permit very small scaling factors.
|
848
850
|
this.variable_modal.element('scale').value = VM.sig4Dig(cv.scale_factor, true);
|
849
851
|
this.variable_modal.element('width').value = VM.sig4Dig(cv.line_width);
|
@@ -928,6 +930,7 @@ class GUIChartManager extends ChartManager {
|
|
928
930
|
c = MODEL.charts[this.chart_index],
|
929
931
|
cv = c.variables[this.variable_index];
|
930
932
|
cv.stacked = UI.boxChecked('variable-stacked');
|
933
|
+
cv.absolute = UI.boxChecked('variable-absolute');
|
931
934
|
cv.scale_factor = s;
|
932
935
|
// Prevent negative or near-zero line width.
|
933
936
|
cv.line_width = Math.max(0.001, w);
|
@@ -1092,9 +1095,9 @@ class GUIChartManager extends ChartManager {
|
|
1092
1095
|
}
|
1093
1096
|
}
|
1094
1097
|
|
1095
|
-
copyTable() {
|
1096
|
-
UI.copyHtmlToClipboard(this.table_panel.innerHTML);
|
1097
|
-
UI.notify('Table copied to clipboard (as HTML)');
|
1098
|
+
copyTable(plain) {
|
1099
|
+
UI.copyHtmlToClipboard(this.table_panel.innerHTML, plain);
|
1100
|
+
UI.notify('Table copied to clipboard (as ', (plain ? 'text' : 'HTML'), ')');
|
1098
1101
|
}
|
1099
1102
|
|
1100
1103
|
copyStatistics() {
|
@@ -3078,6 +3078,7 @@ class GUIController extends Controller {
|
|
3078
3078
|
MODEL.t = Math.max(1, MODEL.t - dt);
|
3079
3079
|
UI.updateTimeStep();
|
3080
3080
|
UI.drawDiagram(MODEL);
|
3081
|
+
if(FINDER.visible && FINDER.tabular_view) FINDER.updateTabularView();
|
3081
3082
|
}
|
3082
3083
|
}
|
3083
3084
|
|
@@ -3088,6 +3089,7 @@ class GUIController extends Controller {
|
|
3088
3089
|
MODEL.t = Math.min(MODEL.end_period - MODEL.start_period + 1, MODEL.t + dt);
|
3089
3090
|
UI.updateTimeStep();
|
3090
3091
|
UI.drawDiagram(MODEL);
|
3092
|
+
if(FINDER.visible && FINDER.tabular_view) FINDER.updateTabularView();
|
3091
3093
|
}
|
3092
3094
|
}
|
3093
3095
|
|
@@ -3096,39 +3098,39 @@ class GUIController extends Controller {
|
|
3096
3098
|
//
|
3097
3099
|
|
3098
3100
|
copyStringToClipboard(string) {
|
3099
|
-
//
|
3100
|
-
let msg = pluralS(string.split('\n').length, 'line') +
|
3101
|
-
' copied to clipboard',
|
3102
|
-
type = 'notification';
|
3101
|
+
// Copy string to clipboard and notifies user of #lines copied.
|
3103
3102
|
if(navigator.clipboard) {
|
3104
|
-
|
3105
|
-
|
3103
|
+
const msg = pluralS(string.split('\n').length, 'line') +
|
3104
|
+
' copied to clipboard';
|
3105
|
+
navigator.clipboard.writeText(string)
|
3106
|
+
.then(() => UI.setMessage(msg, 'notification'))
|
3107
|
+
.catch(() => UI.setMessage('Failed to copy to clipboard', 'warning'));
|
3106
3108
|
} else {
|
3107
|
-
|
3108
|
-
|
3109
|
-
document.body.appendChild(ta);
|
3110
|
-
ta.value = string;
|
3111
|
-
ta.select();
|
3112
|
-
document.execCommand('copy');
|
3113
|
-
document.body.removeChild(ta);
|
3109
|
+
UI.setMessage('Your browser does not support copying to clipboard',
|
3110
|
+
'warning');
|
3114
3111
|
}
|
3115
|
-
UI.setMessage(msg, type);
|
3116
3112
|
}
|
3117
3113
|
|
3118
|
-
copyHtmlToClipboard(html) {
|
3119
|
-
// Copy HTML to clipboard
|
3120
|
-
|
3121
|
-
|
3122
|
-
|
3114
|
+
copyHtmlToClipboard(html, plain=false) {
|
3115
|
+
// Copy HTML (as such or as plain text) to clipboard and notify user.
|
3116
|
+
if(navigator.clipboard) {
|
3117
|
+
const
|
3118
|
+
item = (plain ? {'text/plain': html} : {'text/html': html}),
|
3119
|
+
data = [new ClipboardItem(item)],
|
3120
|
+
msg = 'HTML copied to clipboard' + (plain ? ' as plain text' : '');
|
3121
|
+
navigator.clipboard.write(data)
|
3122
|
+
.then(() => UI.setMessage(msg, 'notification'))
|
3123
|
+
.catch((error) => UI.setMessage('Failed to copy HTML to clipboard',
|
3124
|
+
'warning', error));
|
3125
|
+
} else {
|
3126
|
+
UI.setMessage('Your browser does not support copying HTML to clipboard',
|
3127
|
+
'warning');
|
3123
3128
|
}
|
3124
|
-
document.addEventListener('copy', listener);
|
3125
|
-
document.execCommand('copy');
|
3126
|
-
document.removeEventListener('copy', listener);
|
3127
3129
|
}
|
3128
3130
|
|
3129
3131
|
logHeapSize(msg='') {
|
3130
|
-
//
|
3131
|
-
// NOTE:
|
3132
|
+
// Log MB's of used heap memory to console (to detect memory leaks).
|
3133
|
+
// NOTE: This feature is supported only by Chrome.
|
3132
3134
|
if(msg) msg += ' -- ';
|
3133
3135
|
if(performance.memory !== undefined) {
|
3134
3136
|
console.log(msg + 'Allocated memory: ' + Math.round(
|
@@ -4035,11 +4037,16 @@ console.log('HERE name conflicts', name_conflicts, mapping);
|
|
4035
4037
|
this.setBox('settings-encrypt', model.encrypt);
|
4036
4038
|
const pg_btn = md.element('power-btn');
|
4037
4039
|
pg_btn.style.display = (model.with_power_flow ? 'inline-block' : 'none');
|
4040
|
+
if(model.ignore_grid_capacity || model.ignore_KVL || model.ignore_power_losses) {
|
4041
|
+
pg_btn.classList.add('ignore');
|
4042
|
+
} else {
|
4043
|
+
pg_btn.classList.remove('ignore');
|
4044
|
+
}
|
4038
4045
|
md.show('name');
|
4039
4046
|
}
|
4040
4047
|
|
4041
4048
|
updateSettings(model) {
|
4042
|
-
// Valdidate inputs
|
4049
|
+
// Valdidate inputs.
|
4043
4050
|
const px = this.validNumericInput('settings-grid-pixels', 'grid resolution');
|
4044
4051
|
if(px === false) return false;
|
4045
4052
|
const ts = this.validNumericInput('settings-time-scale', 'time step');
|
@@ -288,7 +288,7 @@ class GUIDatasetManager extends DatasetManager {
|
|
288
288
|
for(const r of this.dataset_table.rows) if(r.dataset.prefix === lcp) return r;
|
289
289
|
return null;
|
290
290
|
}
|
291
|
-
|
291
|
+
|
292
292
|
selectPrefixRow(e) {
|
293
293
|
// Select expand/collapse prefix row.
|
294
294
|
this.focal_table = this.dataset_table;
|
@@ -579,6 +579,13 @@ class GUIDatasetManager extends DatasetManager {
|
|
579
579
|
// NOTE: Updating entire dialog may be very time-consuming
|
580
580
|
// when model contains numerous prefixed datasets.
|
581
581
|
this.updatePanes();
|
582
|
+
// NOTE: The selected row now has to be highlighted, as the table
|
583
|
+
// HTML is not changed.
|
584
|
+
let r = event.target;
|
585
|
+
while(r && r.tagName !== 'TR') r = r.parentNode;
|
586
|
+
const sel = this.dataset_table.getElementsByClassName('sel-set');
|
587
|
+
if(sel.length > 0) sel[0].classList.remove('sel-set');
|
588
|
+
r.classList.add('sel-set');
|
582
589
|
}
|
583
590
|
|
584
591
|
selectModifier(event, id, x=true) {
|
@@ -343,6 +343,8 @@ class GUIExperimentManager extends ExperimentManager {
|
|
343
343
|
// NOTE: When UpdateDialog is called after an entity has been renamed,
|
344
344
|
// its variable list should be updated.
|
345
345
|
this.updateViewerVariable();
|
346
|
+
// NOTE: Finder may need updating as well.
|
347
|
+
if(FINDER.experiment_view) FINDER.updateDialog();
|
346
348
|
}
|
347
349
|
|
348
350
|
updateParameters() {
|
@@ -727,6 +729,11 @@ class GUIExperimentManager extends ExperimentManager {
|
|
727
729
|
// Toggle `n` consecutive rows, starting at row `r` (0 = top), to be
|
728
730
|
// (no longer) part of the chart combination set.
|
729
731
|
// @@TO DO: shift-key indicates "add row(s) to selection"
|
732
|
+
if(MODEL.running_experiment) {
|
733
|
+
// NOTE: do NOT change run selection while VM is solving!
|
734
|
+
UI.notify('Run selection cannot be changed when an experiment is running');
|
735
|
+
return;
|
736
|
+
}
|
730
737
|
const
|
731
738
|
x = this.selected_experiment,
|
732
739
|
// Let `first` be the number of the first run on row `r`.
|
@@ -751,7 +758,10 @@ class GUIExperimentManager extends ExperimentManager {
|
|
751
758
|
}
|
752
759
|
}
|
753
760
|
this.updateData();
|
761
|
+
CHART_MANAGER.resetChartVectors();
|
754
762
|
CHART_MANAGER.updateDialog();
|
763
|
+
// NOTE: Finder may need updating as well.
|
764
|
+
if(FINDER.experiment_view) FINDER.updateDialog();
|
755
765
|
}
|
756
766
|
}
|
757
767
|
|
@@ -761,34 +771,36 @@ class GUIExperimentManager extends ExperimentManager {
|
|
761
771
|
|
762
772
|
toggleChartCombi(n, shift, alt) {
|
763
773
|
// Set `n` to be the chart combination, or toggle if Shift-key is pressed,
|
764
|
-
// or execute single run if Alt-key is pressed
|
774
|
+
// or execute single run if Alt-key is pressed.
|
775
|
+
if(MODEL.running_experiment) {
|
776
|
+
// NOTE: do NOT do this while VM is solving, as this would interfere!
|
777
|
+
UI.notify('Run selection cannot be changed when an experiment is running');
|
778
|
+
return;
|
779
|
+
}
|
765
780
|
const x = this.selected_experiment;
|
766
781
|
if(x && alt && n >= 0) {
|
767
782
|
this.startExperiment(n);
|
768
783
|
return;
|
769
784
|
}
|
770
785
|
if(x && n < x.combinations.length) {
|
771
|
-
//
|
772
|
-
if(!shift) x.chart_combinations.length = 0;
|
773
|
-
// Toggle => add if not in selection, otherwise remove
|
786
|
+
// Toggle => add if not in selection, otherwise remove.
|
774
787
|
const ci = x.chart_combinations.indexOf(n);
|
775
788
|
if(ci < 0) {
|
789
|
+
// Clear current selection unless Shift-key is pressed.
|
790
|
+
if(!shift) x.chart_combinations.length = 0;
|
776
791
|
x.chart_combinations.push(n);
|
777
792
|
} else {
|
778
793
|
x.chart_combinations.splice(ci, 1);
|
779
794
|
}
|
780
795
|
}
|
781
796
|
this.updateData();
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
CHART_MANAGER.resetChartVectors();
|
790
|
-
CHART_MANAGER.updateDialog();
|
791
|
-
}
|
797
|
+
// Show the messages for this run in the monitor.
|
798
|
+
VM.setRunMessages(n);
|
799
|
+
// Update the chart.
|
800
|
+
CHART_MANAGER.resetChartVectors();
|
801
|
+
CHART_MANAGER.updateDialog();
|
802
|
+
// NOTE: Finder may need updating as well.
|
803
|
+
if(FINDER.experiment_view) FINDER.updateDialog();
|
792
804
|
}
|
793
805
|
|
794
806
|
runInfo(n) {
|
@@ -839,7 +851,7 @@ class GUIExperimentManager extends ExperimentManager {
|
|
839
851
|
info.html = html.join('');
|
840
852
|
return info;
|
841
853
|
}
|
842
|
-
// Fall-through (should not occur)
|
854
|
+
// Fall-through (should not occur).
|
843
855
|
return null;
|
844
856
|
}
|
845
857
|
|
@@ -848,7 +860,7 @@ class GUIExperimentManager extends ExperimentManager {
|
|
848
860
|
// NOTE: Skip when viewer is showing!
|
849
861
|
if(!UI.hidden('experiment-viewer')) return;
|
850
862
|
if(n < MODEL.experiments.length) {
|
851
|
-
// NOTE:
|
863
|
+
// NOTE: Mouse move over title in viewer passes n = -1.
|
852
864
|
const x = (n < 0 ? this.selected_experiment : MODEL.experiments[n]);
|
853
865
|
DOCUMENTATION_MANAGER.update(x, shift);
|
854
866
|
}
|