Fix bug 4658 for xinfo,xsave,sd2sci,graduate,graypolarplot,legend,legends,nf3d ...
[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
22     error(msprintf(gettext("%s: Wrong number of input argument(s): At least %d expected.\n"), "legends", 2));
23   end
24   if type(leg) ~= 10 then,
25     error(msprintf(gettext("%s: Wrong type for input argument #%d: String array expected.\n"), "legends", 1));
26   end
27   nleg=size(leg,'*')
28   if type(style) ~= 1 & type(style) ~= 9 then,
29     error("second argument type may be 1 or 9  "),
30     error(msprintf(gettext("%s: Wrong type for input argument #%d: Real array or graphic handle array expected.\n"), "legends", 2));
31   end 
32   if ~exists("opt","local") then
33     opt=5
34   elseif typeof(opt)=="string" then
35     select opt
36       case "ur" then, opt=1,
37       case "ul" then, opt=2,
38       case "ll" then, opt=3,       
39       case "lr" then, opt=4,             
40       case "?"  then, opt=5,
41       case "below" then, opt=6,
42     else
43       error("bad value for argument opt")
44     end
45   end
46   if ~exists("with_box","local") then, with_box=%t, end
47   if ~exists("font_size","local") then
48     font_size = 1 ; // default size
49   end
50
51  
52   if or(size(style)==1) then, style=matrix(style,1,-1),end
53   ns=size(style,2)
54  
55   //preserve current graphic context
56   f=gcf()
57   vis=f.immediate_drawing;
58   old_ax=gca(),
59   arect=old_ax.margins;
60   r1=old_ax.axes_bounds;
61  
62   //create small axes on the top left corner (the axes is choosen very
63   //small to avoid it can be selected for rotation in new graphic mode
64   //case (a little tricky)
65   xsetech(wrect=[r1(1),r1(2),r1(3)/1000,r1(4)/1000],frect=[0 0 1,1]/1000,arect=[0,0,0,0])
66   xmin=arect(1);xmax=1-arect(2);ymin=-1+arect(4);ymax=-arect(3);
67
68   cur_ax=gca(),
69   cur_ax.clip_state='off';
70
71   dy = ymax-ymin ;
72   yOffset = dy / 60 ;
73   
74   drx=(xmax-xmin)/20 //length of the line
75   xOffset = drx/5 ;
76
77   bbx=[]
78   for k=1:nleg
79     r = stringbox( leg(k), 0, 0, 0, old_ax.font_style, font_size ) ;
80     bbx=[bbx;r(1,3) - r(1,1) , r(2,3) - r(2,1)]; //[width height]
81   end
82
83   height = sum(bbx(:,2))
84   width  = max(bbx(:,1)) + drx * 1.6 ; // 1.6 * drx = 1.2 * drx + 2 * drx / 5 ;
85
86   //upper left coordinates
87   if size(opt,'*')>1 then
88    // fix for bug 1237 (Bruno 9 march 2005)
89    if old_ax.tight_limits == "on" then  // data_bounds' corresponds to the old frec
90      r2 = old_ax.data_bounds'
91    else
92      r2 = [old_ax.x_ticks.locations(1),old_ax.y_ticks.locations(1),...
93      old_ax.x_ticks.locations($),old_ax.y_ticks.locations($)]
94    end
95    pos(1) = xmin + ((opt(1)-r2(1))/(r2(3)-r2(1)))*(1-arect(1)-arect(2))
96    pos(2) = ymin + ((opt(2)-r2(2))/(r2(4)-r2(2)))*(1-arect(3)-arect(4))
97    // end bugfix
98    opt=0 ;
99   elseif opt<1 | opt>6 then
100      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
101   end
102   select opt
103     case 1 then
104       pos=[xmax-width-xOffset,ymax-yOffset]
105     case 2 then
106       pos=[xmin+xOffset,ymax-yOffset]
107     case 3 then
108       pos=[xmin+xOffset,ymin+height+yOffset]
109     case 4 then
110       pos=[xmax-width-xOffset,ymin+height+yOffset]
111     case 5 then
112       rect=dragrect([xmax-width-xOffset,ymax-yOffset,width,height])
113       pos=rect(1:2)
114     case 6 then
115 // decrease the size of the graph to leave place for the legend
116       old_ax.margins=[xmin;arect(2);arect(4);arect(3)+height + 2 * yOffset ]
117       pos=[(xmin+xmax)/2-width/2, ymin + height - 2 * yOffset ]
118   end
119  
120   x=pos(1)+xOffset
121   y=pos(2)
122  
123   f.immediate_drawing = "off",
124   a=gca() ;
125   a.foreground=old_ax.foreground ;
126   a.background=old_ax.background ;
127   a.font_color=old_ax.font_color ;
128   a.font_size =old_ax.font_size  ;
129   a.font_style=old_ax.font_style ;
130
131
132   R=[]
133   if with_box then
134      xpol = [pos(1), pos(1)+width, pos(1)+width, pos(1)];
135      ypol = [pos(2), pos(2), pos(2)-height, pos(2)-height];     
136      xfpoly(xpol, ypol,1)
137      R = gce();
138      R.foreground=a.foreground;
139      R.background=a.background;
140  end
141   for k=1:nleg
142     if k<=size(style,2) then
143       if type(style)==9 then
144         h=style(k)
145         select h.type
146           case "Polyline"
147           if h.polyline_style==5 then //patch
148             xfpoly([x;x+drx;x+drx;x;x],[y-bbx(k,2);y-bbx(k,2);y;y;y-bbx(k,2)]);
149             r=gce();
150             r = unglue(r); // one xfpoly returns 2 polylines -> tmp bug to fix later F.Leray
151             r.foreground=h.foreground;
152             r.thickness=h.thickness;
153             r.polyline_style=h.polyline_style;
154             r.line_style=h.line_style;
155           else
156             if stripblanks(h.mark_mode)=='off'
157               xpoly([x;x+drx],[y;y]-bbx(k,2)/2,'lines');r=gce();
158               r.foreground=h.foreground;
159               r.thickness=h.thickness;
160               r.polyline_style=h.polyline_style;
161               r.line_style=h.line_style;
162             else
163               xpoly(x+drx/2,y-bbx(k,2)/2);r=gce();
164               r.foreground=h.foreground;
165               r.thickness=h.thickness;
166               r.mark_style=h.mark_style;
167               r.mark_size=h.mark_size;
168             end
169           end
170         else
171           error('Only handle on polyline,are allowed')
172         end
173       else
174         if style(1,k)<= 0 then
175           xpoly(x+drx/2,y-bbx(k,2)/2)
176           r=gce(),
177           r.mark_mode='on'
178           r.mark_style=-style(1,k)
179           if size(style,1)==2 then r.foreground=style(2,k);end
180         else
181           xpoly([x;x+drx],[y;y]-bbx(k,2)/2,'lines')
182           r=gce(),
183           r.foreground=style(1,k)
184           if size(style,1)==2 then r.line_style=style(2,k);end
185         end
186       end
187     end
188     R=[R,r']
189     xstring(x + drx*1.2 + bbx(k,1)/2,y-bbx(k,2)/2,leg(k))
190     
191     r=gce()
192     r.font_size = font_size ;
193     r.alignment = "center" ;
194     r.text_box_mode = "centered" ; // the string is centered on (x,y)
195     R=[R,r]
196     y=y-bbx(k,2) ;
197   end
198   glue(R)
199  
200   set('current_axes',old_ax),
201   
202   // if immediate_drawing was "on", then the figure will redraw itself.
203   f.immediate_drawing = vis;
204
205 endfunction