33#include < algorithm>
44#include < cmath>
55#include < cstddef>
6+ #include < functional>
67#include < string>
78#include < string_view>
89#include < utility>
910
1011#include " base/anim/interpolated.h"
12+ #include " base/geom/affinetransform.h"
1113#include " base/geom/rect.h"
1214#include " base/geom/transformedrect.h"
1315#include " base/gfx/canvas.h"
16+ #include " base/gfx/color.h"
1417#include " base/gfx/draw/roundedrect.h"
1518#include " base/math/floating.h"
1619#include " base/text/smartstring.h"
@@ -29,30 +32,46 @@ void DrawLegend::draw(Gfx::ICanvas &canvas,
2932 Gen::ChannelId channelType,
3033 double weight) const
3134{
32- auto contentRect =
35+ auto markerWindowRect =
3336 style.contentRect (legendLayout, rootStyle.calculatedSize ());
3437
35- auto markerWindowRect = contentRect;
3638 auto titleRect =
3739 markerWindowRect.popBottom (style.title .getHeight ());
40+ auto markerWindowHeight = markerWindowRect.height ();
41+ auto itemHeight = style.label .getHeight ();
42+ auto markerSize = style.marker .size ->get (itemHeight,
43+ style.label .calculatedSize ());
3844
39- auto &&info = Info{
40- .canvas = canvas,
45+ auto fadeHeight = markerSize;
46+ markerWindowRect =
47+ markerWindowRect
48+ + Geom::Rect{{0 , -fadeHeight}, {0 , 2 * fadeHeight}};
49+
50+ auto fadeElementPercent = fadeHeight / markerWindowRect.height ();
51+
52+ auto &&info = Info{.canvas = canvas,
4153 .titleRect = titleRect,
4254 .markerWindowRect = markerWindowRect,
55+ .fadeHeight = fadeHeight,
4356 .yOverflow = {},
4457 .yOffset = {},
4558 .type = channelType,
4659 .weight = weight,
47- .itemHeight = style.label .getHeight (),
48- .markerSize = style.marker .size ->get (contentRect.size .y ,
49- style.label .calculatedSize ()),
60+ .itemHeight = itemHeight,
61+ .markerSize = markerSize,
5062 .measure = plot->axises .at (channelType).measure ,
5163 .dimension = plot->axises .at (channelType).dimension ,
52- };
53-
54- info.yOverflow =
55- markersLegendFullSize (info) - markerWindowRect.height ();
64+ .colorGradientSetter = {markerWindowRect.leftSide (),
65+ Gfx::ColorGradient{{
66+ {0.0 , {}},
67+ {fadeElementPercent / 2.0 , {}},
68+ {fadeElementPercent, {}},
69+ {1.0 - fadeElementPercent, {}},
70+ {1.0 - fadeElementPercent / 2.0 , {}},
71+ {1.0 , {}},
72+ }}}};
73+
74+ info.yOverflow = markersLegendFullSize (info) - markerWindowHeight;
5675 if (std::signbit (info.yOverflow )) info.yOverflow = 0.0 ;
5776 info.yOffset =
5877 style.translateY ->get (info.yOverflow , info.itemHeight );
@@ -64,15 +83,38 @@ void DrawLegend::draw(Gfx::ICanvas &canvas,
6483 Events::Targets::legend (channelType, info.yOverflow ));
6584
6685 canvas.save ();
67- canvas.setClipRect (contentRect);
6886
69- drawTitle (info );
87+ canvas. setClipRect (markerWindowRect );
7088
7189 drawDimension (info);
7290
7391 drawMeasure (info);
7492
7593 canvas.restore ();
94+
95+ canvas.save ();
96+
97+ canvas.setClipRect (titleRect);
98+
99+ drawTitle (info);
100+
101+ canvas.restore ();
102+ }
103+
104+ void DrawLegend::ColorGradientSetter::operator ()(Gfx::ICanvas &canvas,
105+ const Geom::AffineTransform &transform,
106+ const Gfx::Color &color) const
107+ {
108+ for (auto &stop : modifiableStops) stop.value = color;
109+
110+ modifiableStops[0 ].value .alpha = 0.0 ;
111+ modifiableStops[1 ].value .alpha *= 0.27 ;
112+ modifiableStops[4 ].value .alpha *= 0.27 ;
113+ modifiableStops[5 ].value .alpha = 0.0 ;
114+
115+ canvas.setBrushGradient (
116+ {transform (line.begin ), transform (line.end )},
117+ gradient);
76118}
77119
78120void DrawLegend::drawTitle (const Info &info) const
@@ -110,8 +152,8 @@ void DrawLegend::drawDimension(const Info &info) const
110152 auto itemRect =
111153 getItemRect (info, value.second .range .getMin ());
112154
113- if (itemRect.y ().getMax () > info.markerWindowRect .y ().getMax ()
114- || itemRect.y ().getMin ()
155+ if (itemRect.y ().getMin () > info.markerWindowRect .y ().getMax ()
156+ || itemRect.y ().getMax ()
115157 < info.markerWindowRect .y ().getMin ())
116158 continue ;
117159
@@ -138,16 +180,21 @@ void DrawLegend::drawDimension(const Info &info) const
138180 value.second .categoryValue ,
139181 info.type ,
140182 info.yOverflow ),
141- {.alpha = double {
142- alpha && Math::FuzzyBool{weighted.weight }}});
183+ {.alpha =
184+ double {
185+ alpha
186+ && Math::FuzzyBool{weighted.weight }},
187+ .gradient =
188+ std::ref (info.colorGradientSetter )});
143189 });
144190 }
145191}
146192
147193Geom::Rect DrawLegend::getItemRect (const Info &info, double index)
148194{
149195 Geom::Rect res = info.markerWindowRect ;
150- res.pos .y += index * info.itemHeight - info.yOffset ;
196+ res.pos .y +=
197+ info.fadeHeight + index * info.itemHeight - info.yOffset ;
151198 res.size .y = info.itemHeight ;
152199 if (std::signbit (res.size .x )) res.size .x = 0 ;
153200 return res;
@@ -179,7 +226,7 @@ void DrawLegend::drawMarker(const Info &info,
179226{
180227 info.canvas .save ();
181228
182- info.canvas . setBrushColor ( color);
229+ info.colorGradientSetter (info. canvas , {}, color);
183230 info.canvas .setLineColor (color);
184231 info.canvas .setLineWidth (0 );
185232
@@ -259,7 +306,7 @@ void DrawLegend::extremaLabel(const Info &info,
259306Geom::Rect DrawLegend::getBarRect (const Info &info)
260307{
261308 Geom::Rect res = info.markerWindowRect ;
262- res.pos .y += info.itemHeight / 2.0 ;
309+ res.pos .y += info.fadeHeight + info. itemHeight / 2.0 ;
263310 res.size .y = 5 * info.itemHeight ;
264311 res.size .x = info.markerSize ;
265312 return res;
0 commit comments