1 module ggplotd.legend;
2 
3 import cairo = cairo;
4 
5 import ggplotd.colour : ColourGradient;
6 
7 package struct Legend
8 {
9     string type = "continuous";
10     int height = 70;
11     int width = 80;
12 }
13 
14 /++
15 Create a legend using a continuous scale
16 
17 Params:
18     width = Optional width in pixels
19     height = Optional height in pixels
20 +/
21 auto continuousLegend(int width = 80, int height = 70)
22 {
23     return Legend("continuous", width, height);
24 }
25 
26 /++
27 Create a legend using a discrete scale
28 
29 Params:
30     width = Optional width in pixels
31     height = Optional height in pixels
32 +/
33 auto discreteLegend(int width = 80, int height = 70)
34 {
35     return Legend("discrete", width, height);
36 }
37 
38 
39 /// Draw a legend for a continuous value to the given surface
40 auto drawContinuousLegend(CR, CG)
41     (ref cairo.Surface surface, int width, int height,
42         CR colourStore, CG colourGradient )
43 {
44     import std.algorithm : reduce;
45     import std.typecons : tuple;
46 
47     import ggplotd.ggplotd : GGPlotD, Margins;
48     import ggplotd.algorithm : safeMin, safeMax;
49     import ggplotd.aes : Aes;
50     import ggplotd.geom : geomPolygon;
51     import ggplotd.axes : xaxisShow;
52     // TODO: constify
53     // TODO: make sure to test with alternative coloursceme (the hist2D examples, should suffice)
54     auto gg = GGPlotD();
55     gg.put(Margins(15, 0, 0, 0));
56     gg.put( colourGradient );
57 
58     auto aes = Aes!( double[], "x", double[], "y", double[], "colour" )
59         ( [0.0,0,1,1], 
60             [colourStore.min(), colourStore.max(), colourStore.max(), colourStore.min()], 
61             [colourStore.min(), colourStore.max(), colourStore.max(), colourStore.min()]);
62     gg.put( geomPolygon(aes) );
63     gg.put( xaxisShow(false) );
64     
65     gg.drawToSurface( surface, width, height );
66     return surface;
67 }
68 
69 /// Draw a legend for a discrete value to the given surface
70 auto drawDiscreteLegend(CR, CG)
71     (ref cairo.Surface surface, int width, int height,
72         CR colourStore, CG colourGradient )
73 {
74     import std.algorithm : map;
75     import std.array : array;
76     import std.conv : to;
77     import std.range : repeat, walkLength;
78     import std.typecons : tuple;
79 
80     import ggplotd.ggplotd : GGPlotD, Margins;
81     import ggplotd.algorithm : safeMin, safeMax;
82     import ggplotd.aes : Aes;
83     import ggplotd.geom : geomRectangle;
84     import ggplotd.axes : xaxisShow, xaxisRange;
85     import ggplotd.range : uniquer;
86     // TODO: constify
87     // TODO: make sure to test with alternative coloursceme (the hist2D examples, should suffice)
88     auto gg = GGPlotD();
89     gg.put(Margins(15, 0, 0, 0));
90     gg.put(colourGradient);
91 
92     //auto ys = colourRange.uniquer.map!((a) => a.to!double);
93     auto cols = colourStore.store;
94     auto xs = (1.0).repeat(cols.walkLength);
95     auto dims = (0.8).repeat(cols.walkLength);
96     auto aes = Aes!( typeof(xs), "x", typeof(cols), "y", 
97         typeof(cols), "colour", typeof(dims), "width",
98         typeof(dims), "height", typeof(xs), "fill")
99         ( xs, cols, cols, dims, dims, xs);
100     gg.put( geomRectangle(aes) );
101 
102     gg.put( xaxisShow(false) );
103     gg.put( xaxisRange(0.5, 1.0) );
104     gg.drawToSurface( surface, width, height );
105     return surface;
106 }