@@ -169,6 +169,18 @@ public override void PaintDOM(CharacterBuffer buffer, LayoutRect bounds, LayoutR
169169 }
170170 }
171171
172+ // Draw legend (right-aligned on title row)
173+ if ( _showLegend && _series . Count > 0 )
174+ {
175+ int legendY = _titlePosition == TitlePosition . Top
176+ ? startY + borderSize
177+ : graphStartY + _graphHeight + baselineHeight ;
178+ if ( legendY >= clipRect . Y && legendY < clipRect . Bottom )
179+ {
180+ PaintLegend ( buffer , legendY , startX + borderSize , contentWidth - ( borderSize * 2 ) , clipRect , fgColor , bgColor , preserveBg ) ;
181+ }
182+ }
183+
172184 // Snapshot data under lock
173185 List < ( LineGraphSeries series , List < double > data ) > seriesSnapshots ;
174186 lock ( _dataLock )
@@ -338,6 +350,75 @@ private void ComputeGlobalMinMaxFromSnapshots(
338350 max = min + 1.0 ;
339351 }
340352
353+ private void PaintLegend ( CharacterBuffer buffer , int y , int areaX , int areaWidth ,
354+ LayoutRect clipRect , Color fgColor , Color bgColor , bool preserveBg )
355+ {
356+ // Build legend: "━ Series1 ━ Series2 ━ Series3"
357+ // Each entry: line char + space + name + 2 spaces gap
358+ List < LineGraphSeries > snapshot ;
359+ lock ( _dataLock ) { snapshot = new List < LineGraphSeries > ( _series ) ; }
360+
361+ var entries = new List < ( string text , Color color ) > ( ) ;
362+ int totalWidth = 0 ;
363+ foreach ( var s in snapshot )
364+ {
365+ // "━ Name" = 2 + name length
366+ int entryWidth = ControlDefaults . LineGraphLegendMarkerWidth + UnicodeWidth . GetStringWidth ( s . Name ) ;
367+ if ( entries . Count > 0 )
368+ totalWidth += ControlDefaults . LineGraphLegendEntryGap ;
369+ totalWidth += entryWidth ;
370+ entries . Add ( ( s . Name , s . LineColor ) ) ;
371+ }
372+
373+ int legendX = areaX + areaWidth - totalWidth ;
374+ int writeX = legendX ;
375+
376+ for ( int i = 0 ; i < entries . Count ; i ++ )
377+ {
378+ var ( text , color ) = entries [ i ] ;
379+ if ( i > 0 )
380+ writeX += ControlDefaults . LineGraphLegendEntryGap ;
381+
382+ // Draw line marker char
383+ if ( writeX >= clipRect . X && writeX < clipRect . Right )
384+ {
385+ if ( preserveBg )
386+ {
387+ var existingBg = buffer . GetCell ( writeX , y ) . Background ;
388+ buffer . SetNarrowCell ( writeX , y , ControlDefaults . LineGraphLegendMarkerChar , color , existingBg ) ;
389+ }
390+ else
391+ buffer . SetNarrowCell ( writeX , y , ControlDefaults . LineGraphLegendMarkerChar , color , bgColor ) ;
392+ }
393+ writeX ++ ;
394+
395+ // Space after marker
396+ writeX ++ ;
397+
398+ // Draw series name
399+ var nameCells = Parsing . MarkupParser . Parse ( text , fgColor , bgColor ) ;
400+ for ( int c = 0 ; c < nameCells . Count && writeX < clipRect . Right ; c ++ )
401+ {
402+ if ( writeX >= clipRect . X )
403+ {
404+ if ( preserveBg )
405+ {
406+ var existingBg = buffer . GetCell ( writeX , y ) . Background ;
407+ var cell = new Cell ( nameCells [ c ] . Character , fgColor , existingBg , nameCells [ c ] . Decorations )
408+ {
409+ IsWideContinuation = nameCells [ c ] . IsWideContinuation ,
410+ Combiners = nameCells [ c ] . Combiners
411+ } ;
412+ buffer . SetCell ( writeX , y , cell ) ;
413+ }
414+ else
415+ buffer . SetCell ( writeX , y , nameCells [ c ] ) ;
416+ }
417+ writeX ++ ;
418+ }
419+ }
420+ }
421+
341422 #endregion
342423 }
343424}
0 commit comments