@@ -352,17 +352,29 @@ function timeseries_card(app, session)
352
352
placeholder= " Select components" ,
353
353
multi= true ,
354
354
option_to_string= _sidx_to_str,
355
- T= SymbolicIndex)
355
+ T= SymbolicIndex,
356
+ id= gendomid (" compsel" ))
356
357
# comp_sel_dom = Grid(DOM.span("Components"), comp_sel; columns = "70px 1fr", align_items = "center")
357
358
state_sel = MultiSelect (state_options, app. tsplot. states;
358
359
placeholder= " Select states" ,
359
360
multi= true ,
360
- T= Symbol)
361
+ T= Symbol,
362
+ id= gendomid (" statesel" ))
363
+
364
+ reset_button = Bonito. Button (" Reset Color" , style= Styles (" margin-left" => " 10px" ))
365
+ on (reset_button. value) do _
366
+ empty! (color_cache)
367
+ empty! (linestyle_cache)
368
+ notify (app. tsplot. selcomp)
369
+ notify (app. tsplot. states)
370
+ end
371
+
372
+ rel_toggle = ToggleSwitch (value= app. tsplot. rel, label= " Rel to u0" )
361
373
362
374
comp_state_sel_dom = Grid (
363
- DOM. span (" Components" ), comp_sel,
364
- DOM. span (" States" ), state_sel;
365
- columns = " auto 1fr" , align_items = " center"
375
+ DOM. span (" Components" ), comp_sel, reset_button,
376
+ DOM. span (" States" ), state_sel, rel_toggle ;
377
+ columns = " auto 1fr auto " , align_items = " center"
366
378
)
367
379
368
380
# hl choice of elements in graphplot
@@ -377,8 +389,15 @@ function timeseries_card(app, session)
377
389
# ###
378
390
# ### actual plot
379
391
# ###
392
+ COLORS = Makie. wong_colors ()
393
+ LINESTYLES = [:solid , :dot , :dash , :dashdot , :dashdotdot ]
394
+ LINESTYLES = [" ─" , " ⋯" , " --" , " -⋅-" , " -⋅⋅" ]
380
395
color_cache = Dict {Union{EIndex{Int,Nothing},VIndex{Int,Nothing}}, Int} ()
381
396
linestyle_cache = Dict {Symbol,Int} ()
397
+
398
+ colorpairs = Observable {Vector{@NamedTuple{title::String,color::String}}} ()
399
+ lstylepairs = Observable {Vector{@NamedTuple{title::String,linestyle::String}}} ()
400
+
382
401
on (app. tsplot. selcomp; update= true ) do _sel
383
402
@debug " TS: comp selection => update color_cache"
384
403
for unused in setdiff (keys (color_cache), _sel)
@@ -388,6 +407,9 @@ function timeseries_card(app, session)
388
407
i = _smallest_free (color_cache)
389
408
color_cache[new] = i
390
409
end
410
+ colorpairs[] = [(; title= _sidx_to_str (k),
411
+ color= " #" * Colors. hex (getcycled (COLORS, v)))
412
+ for (k,v) in color_cache]
391
413
nothing
392
414
end
393
415
on (app. tsplot. states; update= true ) do _states
@@ -399,9 +421,91 @@ function timeseries_card(app, session)
399
421
i = _smallest_free (linestyle_cache)
400
422
linestyle_cache[new] = i
401
423
end
424
+ lstylepairs[] = [(; title= repr (s), linestyle= getcycled (LINESTYLES, i))
425
+ for (s,i) in linestyle_cache]
402
426
nothing
403
427
end
404
428
429
+ comp_ms_id = Bonito. JSString (comp_sel. id)
430
+ state_ms_id = Bonito. JSString (state_sel. id)
431
+
432
+ js = js """
433
+ function colorListItems (items ) {
434
+ let styleTag = document .getElementById (" dynamic-style-$(comp_ms_id)" );
435
+
436
+ // Create the <style> tag if it doesn't exist
437
+ if (! styleTag) {
438
+ styleTag = document .createElement (" style" );
439
+ styleTag .id = " dynamic-style-$(comp_ms_id)" ;
440
+ document .head .appendChild (styleTag);
441
+ }
442
+
443
+ // Clear previous styles
444
+ styleTag .innerHTML = " " ;
445
+
446
+ // Generate new styles
447
+ let styleContent = " " ;
448
+ items .forEach (({ title, color }) => {
449
+ styleContent += ` #$(comp_ms_id) +span li[title='${ title} ']::after {
450
+ content: 'xx';
451
+ display: inline-block;
452
+ padding-left: 0px 4px;
453
+ background-color: ${ color} !important;
454
+ color: ${ color} !important;
455
+ border-left: 1px solid #aaa;
456
+ cursor: default;
457
+ }\n ` ;
458
+ });
459
+
460
+ // Insert new styles
461
+ styleTag .innerHTML = styleContent;
462
+ }
463
+
464
+ colorListItems ($ (colorpairs).value );
465
+ $ (colorpairs).on ((c ) => {
466
+ colorListItems (c);
467
+ });
468
+
469
+ function linestyleListItems (items ) {
470
+ let styleTag = document .getElementById (" dynamic-style-$(state_ms_id)" );
471
+
472
+ // Create the <style> tag if it doesn't exist
473
+ if (! styleTag) {
474
+ styleTag = document .createElement (" style" );
475
+ styleTag .id = " dynamic-style-$(state_ms_id)" ;
476
+ document .head .appendChild (styleTag);
477
+ }
478
+
479
+ // Clear previous styles
480
+ styleTag .innerHTML = " " ;
481
+
482
+ // Generate new styles
483
+ let styleContent = " " ;
484
+
485
+ if (items .length > 1 ) {
486
+ items .forEach (({ title, linestyle }) => {
487
+ styleContent += ` #$(state_ms_id) +span li[title='${ title} ']::after {
488
+ content: '${ linestyle} ';
489
+ display: inline-block;
490
+ padding-left: 5px;
491
+ padding-right: 5px;
492
+ color: inherit;
493
+ border-left: 1px solid #aaa;
494
+ font-size: smaller;
495
+ cursor: default;
496
+ }\n ` ;
497
+ });
498
+
499
+ // Insert new styles
500
+ styleTag .innerHTML = styleContent;
501
+ }
502
+ }
503
+ linestyleListItems ($ (lstylepairs).value );
504
+ $ (lstylepairs).on ((c ) => {
505
+ linestyleListItems (c);
506
+ });
507
+ """
508
+ evaljs (session, js)
405
509
406
510
fig, ax = with_theme (apptheme ()) do
407
511
fig = Figure ()
0 commit comments