f65bfd4468c364593d32d837fa0f69c0fd5280c3
[scilab.git] / scilab / modules / graphics / macros / legends.sci
1 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
2 // Copyright (C) INRIA
3 //
4 // This file must be used under the terms of the CeCILL.
5 // This source file is licensed as described in the file COPYING, which
6 // you should have received as part of this distribution.  The terms
7 // are also available at    
8 // http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
9
10
11 function legends(leg, style, opt, with_box, font_size )
12 //
13 // PURPOSE
14 //    draw legends on a plot
15 // AUTHORS
16 //    F. Delebecque + slight modif from B. Pincon
17 //  modified again by Eric Dubois and Jean-Baptiste Silvy 18/01/07
18  
19   rhs=argn(2)
20  
21   if rhs < 2 then, error("bad number of arguments"), end
22   if type(leg) ~= 10 then,
23     error("first arg may be a vector of strings"),
24   end
25   nleg=size(leg,'*')
26   if type(style) ~= 1 & type(style) ~= 9 then,
27     error("second argument type may be 1 or 9  "),
28   end 
29   if ~exists("opt","local") then
30     opt=5
31   elseif typeof(opt)=="string" then
32     select opt
33       case "ur" then, opt=1,
34       case "ul" then, opt=2,
35       case "ll" then, opt=3,       
36       case "lr" then, opt=4,             
37       case "?"  then, opt=5,
38       case "below" then, opt=6,
39     else
40       error("bad value for argument opt")
41     end
42   end
43   if ~exists("with_box","local") then, with_box=%t, end
44   if ~exists("font_size","local") then
45     font_size = 1 ; // default size
46   end
47
48  
49   if or(size(style)==1) then, style=matrix(style,1,-1),end
50   ns=size(style,2)
51  
52   //preserve current graphic context
53   f=gcf()
54   vis=f.immediate_drawing;
55   old_ax=gca(),
56   arect=old_ax.margins;
57   r1=old_ax.axes_bounds;
58  
59   //create small axes on the top left corner (the axes is choosen very
60   //small to avoid it can be selected for rotation in new graphic mode
61   //case (a little tricky)
62   xsetech(wrect=[r1(1),r1(2),r1(3)/1000,r1(4)/1000],frect=[0 0 1,1]/1000,arect=[0,0,0,0])
63   xmin=arect(1);xmax=1-arect(2);ymin=-1+arect(4);ymax=-arect(3);
64
65   cur_ax=gca(),
66   cur_ax.clip_state='off';
67
68   dy = ymax-ymin ;
69   yOffset = dy / 60 ;
70   
71   drx=(xmax-xmin)/20 //length of the line
72   xOffset = drx/5 ;
73
74   bbx=[]
75   for k=1:nleg
76     r = stringbox( leg(k), 0, 0, 0, old_ax.font_style, font_size ) ;
77     bbx=[bbx;r(1,3) - r(1,1) , r(2,3) - r(2,1)]; //[width height]
78   end
79
80   height = sum(bbx(:,2))
81   width  = max(bbx(:,1)) + drx * 1.6 ; // 1.6 * drx = 1.2 * drx + 2 * drx / 5 ;
82
83   //upper left coordinates
84   if size(opt,'*')>1 then
85    // fix for bug 1237 (Bruno 9 march 2005)
86    if old_ax.tight_limits == "on" then  // data_bounds' corresponds to the old frec
87      r2 = old_ax.data_bounds'
88    else
89      r2 = [old_ax.x_ticks.locations(1),old_ax.y_ticks.locations(1),...
90      old_ax.x_ticks.locations($),old_ax.y_ticks.locations($)]
91    end
92    pos(1) = xmin + ((opt(1)-r2(1))/(r2(3)-r2(1)))*(1-arect(1)-arect(2))
93    pos(2) = ymin + ((opt(2)-r2(2))/(r2(4)-r2(2)))*(1-arect(3)-arect(4))
94    // end bugfix
95    opt=0 ;
96   elseif opt<1 | opt>6 then
97      error('opt can take value in 1 2 3 4 6') // if opt is entered by a string by the user it is in the range
98   end
99   select opt
100     case 1 then
101       pos=[xmax-width-xOffset,ymax-yOffset]
102     case 2 then
103       pos=[xmin+xOffset,ymax-yOffset]
104     case 3 then
105       pos=[xmin+xOffset,ymin+height+yOffset]
106     case 4 then
107       pos=[xmax-width-xOffset,ymin+height+yOffset]
108     case 5 then
109       rect=dragrect([xmax-width-xOffset,ymax-yOffset,width,height])
110       pos=rect(1:2)
111     case 6 then
112 // decrease the size of the graph to leave place for the legend
113       old_ax.margins=[xmin;arect(2);arect(4);arect(3)+height + 2 * yOffset ]
114       pos=[(xmin+xmax)/2-width/2, ymin + height - 2 * yOffset ]
115   end
116  
117   x=pos(1)+xOffset
118   y=pos(2)
119  
120   f.immediate_drawing = "off",
121   a=gca() ;
122   a.foreground=old_ax.foreground ;
123   a.background=old_ax.background ;
124   a.font_color=old_ax.font_color ;
125   a.font_size =old_ax.font_size  ;
126   a.font_style=old_ax.font_style ;
127
128
129   R=[]
130   if with_box then
131      xpol = [pos(1), pos(1)+width, pos(1)+width, pos(1)];
132      ypol = [pos(2), pos(2), pos(2)-height, pos(2)-height];     
133      xfpoly(xpol, ypol,1)
134      R = gce();
135      R.foreground=a.foreground;
136      R.background=a.background;
137  end
138   for k=1:nleg
139     if k<=size(style,2) then
140       if type(style)==9 then
141         h=style(k)
142         select h.type
143           case "Polyline"
144           if h.polyline_style==5 then //patch
145             xfpoly([x;x+drx;x+drx;x;x],[y-bbx(k,2);y-bbx(k,2);y;y;y-bbx(k,2)]);
146             r=gce();
147             r = unglue(r); // one xfpoly returns 2 polylines -> tmp bug to fix later F.Leray
148             r.foreground=h.foreground;
149             r.thickness=h.thickness;
150             r.polyline_style=h.polyline_style;
151             r.line_style=h.line_style;
152           else
153             if stripblanks(h.mark_mode)=='off'
154               xpoly([x;x+drx],[y;y]-bbx(k,2)/2,'lines');r=gce();
155               r.foreground=h.foreground;
156               r.thickness=h.thickness;
157               r.polyline_style=h.polyline_style;
158               r.line_style=h.line_style;
159             else
160               xpoly(x+drx/2,y-bbx(k,2)/2);r=gce();
161               r.foreground=h.foreground;
162               r.thickness=h.thickness;
163               r.mark_style=h.mark_style;
164               r.mark_size=h.mark_size;
165             end
166           end
167         else
168           error('Only handle on polyline,are allowed')
169         end
170       else
171         if style(1,k)<= 0 then
172           xpoly(x+drx/2,y-bbx(k,2)/2)
173           r=gce(),
174           r.mark_mode='on'
175           r.mark_style=-style(1,k)
176           if size(style,1)==2 then r.foreground=style(2,k);end
177         else
178           xpoly([x;x+drx],[y;y]-bbx(k,2)/2,'lines')
179           r=gce(),
180           r.foreground=style(1,k)
181           if size(style,1)==2 then r.line_style=style(2,k);end
182         end
183       end
184     end
185     R=[R,r']
186     xstring(x + drx*1.2 + bbx(k,1)/2,y-bbx(k,2)/2,leg(k))
187     
188     r=gce()
189     r.font_size = font_size ;
190     r.alignment = "center" ;
191     r.text_box_mode = "centered" ; // the string is centered on (x,y)
192     R=[R,r]
193     y=y-bbx(k,2) ;
194   end
195   glue(R)
196  
197   set('current_axes',old_ax),
198   
199   // if immediate_drawing was "on", then the figure will redraw itself.
200   f.immediate_drawing = vis;
201
202 endfunction