Viewing contents of file '../idllib/contrib/esrg_ucsb/legend.pro'
pro legend,labels,pos=pos,linestyle=linestyle,psym=psym,clrbox=clrbox,$
           color=color,thick=thick,fg_color=fg_color,bg_color=bg_color,$
           box=box,numsym=numsym,ystretch=ystretch,silent=silent,$
           center=center,fill=fill,right=right,norm=norm,spos=spos, $
           lenfac=lenfac,charsize=charsize
;+
; ROUTINE: legend
;
; PURPOSE: draws a plot legend 
;
; USEAGE:  legend,labels,pos=pos,linestyle=linestyle,psym=psym,clrbox=clrbox,$
;                 color=color,thick=thick,fg_color=fg_color,bg_color=bg_color,$
;                 box=box,numsym=numsym,ystretch=ystretch,silent=silent,$
;                 center=center,fill=fill,right=right,norm=norm,spos=spos,$
;                 charsize=charsize
;               
; INPUT:
;
; labels	
;     an array of labels (required). Elements of LABELS which do not
;     begin with the characters ".l",".f",".c", or ".r" are treated as
;     legend labels.  These elements are drawn to the right of a line
;     or symbol of given LINESTYLE, PSYM, COLOR or THICK type. The
;     total number of labels in LABELS (i.e., not counting legend
;     titles) should correspond to the number of elements in those
;     input parameters.
;     
;     If any of the label strings start with the characters
;     ".l",".f",".c", or ".r" that element of the LABELS array is
;     treated as a legend title.  Legend titles appear as left
;     justified (".l"), filled (".f") centered (".c") or right
;     justified (".r") strings in the legend box and do not correspond
;     to elements of LINESTYLE, PSYM, COLOR or THICK.  Null strings
;     ("") or blank strings (" ") are also treated as legend
;     titles. Lines or symbols are not drawn to the right of legend
;     titles.
;     
;     If none of the keywords, LINESTYPE, PSYM, COLOR or THICK are
;     set, then all elements of LABELS will be treated as legend
;     titles and will be left justified unless prepended by ".f", ".c"
;     or ".r".  or unless one of the keywords keywords "center",
;     "fill" "right" are set.  These keywords set the default, string
;     justification but may always be overridden by one of the
;     justification flags.
;     
;     Consider,
;     
;            labels=['.ctitle','1','2','.lsecond title,'a','b']
;            linestyle= [1,2,3,4]
;     
;     In this example LABELS contains 4 legend labels and 2 legend
;     titles. The correspondence with the linestyle input parameter is
;     as follows:
;     
;                      labels(1) <==> linestyle(0)
;                      labels(2) <==> linestyle(1)
;                      labels(4) <==> linestyle(2)
;                      labels(5) <==> linestyle(3)
;     
;     To simplify input, LABELS may also be specified as a single
;     string with the different LABEL elements separated by
;     backslashes (\) (E.g., labels='.cCloud height\\1\2\3\4\5'
;
; KEYWORD INPUT:
;
; pos
;     position and size of legend area in normalized data 
;     coordinates.  Format of this four element vector is
;     [x0,y0,x1,y1] where x0,y0 is the position of lower
;     left corner and x1,y1 is the position of the upper
;     right corner.  For example pos=[.5,.5,.9,.9] specifies
;     a legend in the upper right quadrant of the data 
;     window.  If the POS parameter is not set or if POS is
;     set to zero, then the CURBOX procedure is called to
;     set the legend position interactively.  
;     
;     NOTE: the value of POS can be retrieved by setting POS
;     to a named variable which has an initial value of zero.
;
; linestyle   
;     an array of linestyle types, one for each label in LABELS
;
; psym	
;     an array of symbol types, one for each label in LABELS. 
;     PSYM can be either a integer or string array.  If PSYM is a
;     string array then the library routine USERSYMBOL is used to
;     create the symbols.  In this case if the symbol specifier is
;     appended with '_f' then a filled symbol will be generated
;
; clrbox
;     if set, a color-filled box appears to the left of each legend
;     label.  The number of boxes drawn can be changed with NUMSYM.
;     If clrbox is set to 2, a color-filled circle appears to the left
;     of each legend label.
;
; color       
;     an array of color indices, one for each label in LABELS.
;     Any elements of COLOR set to -1 causes the default color,
;     !P.COLOR, to be used.
;
; thick       
;     an array of line thicknesses, one for each label in LABELS
;     (default=!p.thick)
;
; numsym      
;     number of symbol nodes used to indicate linestyle or symbol
;     type.  The length of the line is measured in units of LENFAC
;     character widths so that the length of the line
;     = LENFAC*(NUMSYM-1) * X_CHARSIZE
;     (default=2 when linestyle, color or thick set, otherwise default=1)
;
; lenfac
;     factor which controls length of line between symbols (see numsym)
;     (default=5)
;
; fg_color    
;     color of box and legend titles (default=!P.COLOR)
;
; bg_color    
;     background color. Setting BG_COLOR erases the area covered by
;     the legend (filling it with color BG_COLOR) prior to writing the
;     legend.  If both BG_COLOR and !p.color are zero then the
;     background color is reset to 255 to gaurantee a readability.
;               
; box         
;     if set draw a box around the legend text
;
; silent      
;     if not set, print box position string to the terminal
;     and show popup help on the CURBOX cursor routine
;     
;     silent=1 don't print position string
;     
;     silent=2 don't print position string, don't show help widget
;
; center
;     if set, default action is to center legend labels
;
; fill
;    if set, default action is to fill legend labels
;
; right
;    if set, default action is to right justify labels
;
; norm
;    if set, normalized coordinates are used to specify POS both
;    on input and printed output.  This option allows placement
;    of the legend outside of a plot region. 
;
; ystretch    
;     factor by which to increase vertical spacing of legend 
;     entries. This parameter is particularly useful when used
;     with the SPOS keyword.  (default = 1)  
;     
;     NOTE: the aspect ratio of the legend box can be
;     modified on the fly by pushing the cursor box against
;     one of the window boundaries and pressing the middle
;     button.  
;
; spos
;    string value which specifies legend position to one of a set of
;    standard positions.  if spos is set, it supercedes the value of pos
;
;                'bl' = bottom left
;                'br' = bottom right
;                'tl' = top left
;                'tr' = top right
;                'top'= top center
;                'bot'= bottom center
;
; charsize
;    character size used when legend position specified with SPOS.  
;    CHARSIZE has no effect when POS is used to set position.
;
; OUTPUT:       none
;
; PROCEDURE:
;    When called without the POS keyword, the legend position and size
;    is set with the CURBOX routine.  The legend is positioned by
;    dragging the box where you want the legend to appear.  The size
;    of the legend area can be decreased/increased by the left/middle
;    mouse buttons.  When the right mouse button is pressed the legend
;    is drawn and a numerical positioning string giving the current
;    value of the POS keyword is written to the terminal (nothing
;    printed if SILENT is set).  You can run LEGEND in batch mode by
;    pasting this value of POS into the LEGEND command line.  The best
;    way to get good-looking legends on your hardcopies is to size
;    your graphics window to the approximate shape of the output
;    media.  For example a plot which is to be printed in landscape
;    mode should be previewed on a window which is approximately 1.4
;    times as wide as it is tall.
;
;    NOTE:    The values returned for the POS keyword are based on a
;    computation of the length of the text strings in your legend.  If
;    you change the contents of the legend titles or if you change the
;    default text font, you must rerun LEGEND in interactive mode to
;    determine new values for the POS paramter.
;                     
;
;
;; EXAMPLE       interactive mode (put the box anywhere you want and press
;;               the right mouse button)
;
;   dcolors
;   plot,6*randf(20,3),/nodata 
;   for i=1,6 do oplot,i*randf(20,3),li=i-1,color=i
;   lb='.cFirst bunch\\First\Second\Third\\.cSecond bunch\\forth\fifth\sixth'
;   legend,lb,li=[0,1,2,3,4,5],/box,bg=0,color=[1,2,3,4,5,6]
;
;; EXAMPLE       interactive mode. retrieve the value of POS for later calls:
;
;   !p.multi=[0,1,2]
;   plot,[0,.4],yrange=[0,1],li=0 & oplot,[0,.6],li=2 & oplot,[0,.9],li=3
;   legpos=0
;   lb=['.cLegend Demo','','one','two','three']
;   legend,lb,pos=legpos,li=[0,2,3]
;   plot,[0,.4],yrange=[0,1],li=0 & oplot,[0,.6],li=2 & oplot,[0,.9],li=3
;   legend,lb,pos=legpos,li=[0,2,3]
;   !p.multi=0
;
;
;; EXAMPLE       use fill mode to print a figure caption
;
;  w11x8
;  !p.multi=[0,1,2]
;  plot,dist(20)
;  t=$
;   'When called without the POS keyword, the legend position and size is\'+$
;   'set with the CURBOX routine.  The legend is positioned by dragging the\'+$
;   'box where you want the legend to appear.  The size of the legend area\'+$
;   'can be decreased/increased by the left/middle mouse buttons.  When the\'+$
;   'right mouse button is pressed the legend is drawn and a numerical\'+$
;   'positioning string giving the current value of the POS keyword is\'+$
;   'written to the terminal (nothing printed if SILENT is set).'
;
;   legend,t,bg=0,pos=[0.00,-0.52,0.47,-0.18]         ; default left justified
;   legend,t,bg=0,/right,pos=[0.53,-0.52,1.00,-0.18]  ; right justified
;   legend,t,bg=0,/center,pos=[0.27,-1.00,0.74,-0.66] ; centered
;
;; NOTE: procedure PFILL provides more elaborate text formatting capability
;   
;; EXAMPLE       batch mode:
;
;   plot,[-50,50],[0,1.5],/nodata & x=findgen(101)-50.
;   li=indgen(6) & pos=[0.66,0.54,0.91,0.89] 
;   for i=0,5 do oplot,x,1./(1.+(x/(i+2))^2),li=li(i) 
;   labels='.cPlot Key\\First\Second\Third\Fourth\Fifth\Sixth'
;   legend,' ',bg=80,pos=pos+.02,/box
;   legend,labels,li=li,pos=pos,bg=40,/box
;                
;; EXAMPLE       batch mode with symbols generated by USERSYMBOL:
;
;   plot,[-50,50],[0,1.5],/nodata & x=findgen(101)-50.
;   psym=['TRIANGLE','DIAMOND','PENTAGON','CIRCLE','SQUARE','SPADE']
;   pos=[0.66,0.54,0.91,0.89] 
;   for i=0,5 do begin &$
;     usersymbol,psym(i) &$
;     oplot,x,1./(1.+(x/(i+2))^2),psym=8,symsize=2 &$
;   endfor
;   labels='.cPlot Key\\First\Second\Third\Fourth\Fifth\Sixth'
;   legend,' ',bg=4,pos=pos+.02,/box
;   legend,labels,psym=psym,pos=pos,bg=10,/box
;                
;
;  author:  Paul Ricchiazzi                            4dec92
;           Institute for Computational Earth System Science
;           University of California, Santa Barbara
;
; REVISIONS
; 15dec92: added legend titles, and CHARSIZE parameter
; 11jan93: added numsym parameter
; 20jan93: added thick parameter
;  2feb93: fixed positioning bug  legend titles
; 25mar93: removed the NOBOX option, now you set BOX to get a box
; 29mar93: added the bg_color option to blank out legend area before writing
;  8apr93: use CURBOX for cursor control and LENSTR for exact string size
; 27apr93: improved alignment symbol and label (ylab=yy-.3*charsize*cnvrty)
;  9jun93: center legend labels when legend titles are longer (see dxcen)
; 17jun93: added ystretch option to increase vertical spacing
; 17jun93: default line thickness read from !p.thick
; 30sep93: .l implied when LINESTYLE, PSYM, COLOR, THICK  not set. see NOLINES
; 28Jun94: LABELS is now normal input param, not a keyword.
; 28Jun94: legend "titles" don't correspond to LINESTYLE, PSYM, COLOR, THICK
;          vector elements; no need to put in dummy values. see examples
; 18Aug94: added USYM option
; 28Jun95: added the .f format option
;  8Sep95: added CLRBOX option
;  5oct95: added charsize adjustment for Y axis
;   sep96: added spos keyword, numsym default = 1 unless linestyle or color set
;   nov96: CLRBOX=2 yields filled circles instead of boxes
;-
on_error,2

n=n_elements(labels)
if n eq 0 then begin & xhelp,'legend' & return & end
if n eq 1 then labls=str_sep(labels,'\') else labls=labels
n=n_elements(labls)
jblnks=where(labls eq ' ',nblnks) 

case 1 of
  keyword_set(center):djust='c'
  keyword_set(right): djust='r'
  keyword_set(fill):  djust='f'
  else:               djust='l'
end
if nblnks gt 0 then labls(jblnks)='.'+djust+' '
if keyword_set(silent) eq 0 then silent=0
;
nls=n_elements(linestyle)
nps=n_elements(psym)
ncl=n_elements(color)
ntk=n_elements(thick) 

nolines=nls eq 0 and nps eq 0 and ncl eq 0 and ntk eq 0
;

if n_elements(fg_color) eq 0 then fgc=!p.color else fgc=fg_color
if n_elements(ystretch) eq 0 then ystretch=1.

titles=strarr(n)
just=strarr(n)

; real label length = slenmx - 2*(number of exclamation marks)

nlbls=0
for i=0,n-1 do begin
  ss=labls(i)
  if strmid(ss,0,1) eq '.' then begin
    just(i)=strmid(ss,1,1)
    tlen=strlen(ss)-2
    ttt=strmid(ss,2,tlen)
    if ttt eq '' then titles(i)=' ' else titles(i)=ttt
  endif else begin
    if nolines or ss eq '' then begin
      just(i)=djust
      if ss eq '' then titles(i)=' ' else titles(i)=ss
    endif else begin
      nlbls=nlbls+1
    endelse
  endelse
endfor

if n_elements(numsym) eq 0 then begin
  if keyword_set(clrbox) or (nls eq 0 and ncl eq 0) then numsym=1 else numsym=2
endif 

if nlbls gt 0 then begin

  drawline= ( nls gt 0 or ncl gt 0 or ntk gt 0 ) and numsym gt 1
  
  if nls eq 0 then begin & linestyle=replicate(-1,nlbls)   & nls=nlbls & end
  if nps eq 0 then begin & psym=intarr(nlbls)              & nps=nlbls & end 
  if ncl eq 0 then begin & color=replicate(-1,nlbls)       & ncl=nlbls & end 
  if ntk eq 0 then begin & thick=replicate(!p.thick,nlbls) & ntk=nlbls & end

  nof='Number of '
  mess=' does not match number of labels'
  if nls ne nlbls then  message,nof+'linestyles'+mess,/continue
  if nps ne nlbls then  message,nof+'psym types'+mess,/continue
  if ncl ne nlbls then  message,nof+'colors'+mess,/continue
  if ntk ne nlbls then  message,nof+'thicknesses'+mess,/continue
  if nls ne nlbls or nps ne nlbls or ncl ne nlbls or ntk ne nlbls then return
endif

cnvrtx=float(!d.x_ch_size)/!d.x_vsize   ; conversion factor from
cnvrty=float(!d.y_ch_size)/!d.y_vsize   ; characters to normalized coordinates

iti=where(titles eq '',niti)            ; these labels are not legend titles

if not keyword_set(lenfac) then lenfac=4

if niti gt 0 then $
  slenmx=max(lenstr(labls(iti)))+(lenfac*(numsym-1)+2)*cnvrtx else slenmx=0

tlenmx=max(lenstr(titles))
xsize=(slenmx > tlenmx) + 2*cnvrtx       ; add two character widths
dxcen=.5*(xsize-2*cnvrtx-slenmx)         ; offset to center legend labels

ysize=1.1*(n+1)*cnvrty

if max([!x.window,!y.window],min=mn) eq mn then $
  plot,[0,1],[0,1],xstyle=4,ystyle=4,/nodata

sx0=!x.window(0)
sx1=!x.window(1)-sx0
sy0=!y.window(0)
sy1=!y.window(1)-sy0

if not ( keyword_set(pos) or keyword_set(spos)) then begin
;  xsz=xsize*!d.x_size
;  ysz=ysize*!d.y_size*ystretch
;  if silent le 1 then curbox,x,y,xsz,ysz,/message else $
;                      curbox,x,y,xsz,ysz

  x0=.5*(1.-xsize)
  x1=.5*(1.+xsize)
  y0=.5*(1.-ysize*ystretch)
  y1=.5*(1.+ysize*ystretch)
  if silent le 1 then curbox,x0,x1,y0,y1,/init,/message else $
                      curbox,x0,x1,y0,y1,/init
  if keyword_set(norm) then begin
    pos=[x0,y0,x1,y1]
  endif else begin
    pos=[(x0-sx0)/sx1,(y0-sy0)/sy1,(x1-sx0)/sx1,(y1-sy0)/sy1]
  endelse
  posstring=string(form='(a,4(f10.2,a))',$
           ',pos=[',pos(0),',',pos(1),',',pos(2),',',pos(3),']')

  if keyword_set(silent) eq 0 then print,strcompress(posstring,/remove_all)

endif else begin
  
  if keyword_set(spos) then begin
    if not keyword_set(norm) then begin
      xsz=xsize/sx1
      ysz=ysize/sy1
    endif else begin
      xsz=xsize
      ysz=ysize
    endelse
    if not keyword_set(charsize) then charsize=!p.charsize
    if charsize eq 0 then charsize=1
    xsz=xsz*charsize
    ysz=ysz*charsize
    case spos of
      "bl" : begin & x0=.05 & x1=x0+xsz & y0=.05 & y1=y0+ysz*ystretch & end
      "br" : begin & x1=.95 & x0=x1-xsz & y0=.05 & y1=y0+ysz*ystretch & end
      "tl" : begin & x0=.05 & x1=x0+xsz & y1=.95 & y0=y1-ysz*ystretch & end
      "tr" : begin & x1=.95 & x0=x1-xsz & y1=.95 & y0=y1-ysz*ystretch & end
      "top": begin 
              x0=.5*(1-xsz) & x1=.5*(1+xsz)
              y1=.98        & y0=y1-ysz
             end
      "bot": begin 
              x0=.5*(1-xsz) & x1=.5*(1+xsz)
              y0=.02        & y1=y0+ysz
             end
      else : message,'check value of spos'
    endcase

    if not keyword_set(norm) then begin
      x0=sx0+x0*sx1         ;                    
      x1=sx0+x1*sx1         ; normalized coordinates of
      y0=sy0+y0*sy1         ; legend box         
      y1=sy0+y1*sy1         ;                    
    endif

  endif else begin
    if n_elements(pos) ne 4 then message,'Incorrect POS specification'
    if keyword_set(norm) then begin
      x0=pos(0)
      x1=pos(2)
      y0=pos(1)
      y1=pos(3)
    endif else begin
      x0=sx0+pos(0)*sx1         ;                    
      x1=sx0+pos(2)*sx1         ; normalized coordinates of
      y0=sy0+pos(1)*sy1         ; legend box         
      y1=sy0+pos(3)*sy1         ;                    
    endelse
  endelse

endelse

; blank out legend area

if n_elements(bg_color) ne 0 then begin
  if !p.color eq 0 and bg_color eq 0 then bgc=255 else bgc=bg_color
  polyfill,[x0,x1,x1,x0],[y0,y0,y1,y1],color=bgc,/normal
endif
if keyword_set(box) then begin
  xbox=[x0,x1,x1,x0,x0]
  ybox=[y0,y0,y1,y1,y0]
  plots,xbox,ybox,color=fgc,/norm
endif
;

xcharsize=(x1-x0)/xsize       ; find the largest charsize that will fit
ycharsize=(y1-y0)/ysize       ; in the legend box
if( xcharsize lt ycharsize ) then begin
  chrsz=xcharsize
endif else begin
  chrsz=ycharsize
endelse

symsize=chrsz
dx=chrsz*cnvrtx
dy=1.1*cnvrty*(y1-y0)/ysize ; dy=1.1*chrsz*cnvrty

;
if numsym eq 1 then begin
  xb=x0+2*dx+dxcen
  xbar=[xb,xb]
  xlab=x0+2*dx+dxcen+(lenfac*(numsym-1)+2)*dx
endif else begin
  xbar=x0+dx+dxcen+lenfac*(numsym-1)*dx*findgen(numsym)/(numsym-1)
  xlab=x0+dx+dxcen+(lenfac*(numsym-1)+2)*dx
endelse

yy=y1-dy

jlbl=0
stdspc=lenstr(' ')*chrsz

for i=0,n-1 do begin
  ylab=yy-.3*chrsz*cnvrty

  if titles(i) eq '' then begin

    clr=color(jlbl)
    if clr eq -1 then clr=!p.color
    ls=linestyle(jlbl)
    ps=psym(jlbl)
    
    if (size(ps))(1) eq 7 then begin
      usersymbol,ps
      ps=8
    endif    
    thk=thick(jlbl)
    ybar=replicate(yy,numsym)

    if keyword_set(clrbox) then begin
      if clrbox eq 2 then begin
        xcbox=1.3*cos(findrng(0,360,37)*!dtor)
        ycbox=1.3*sin(findrng(0,360,37)*!dtor)
      endif else begin
        xcbox=1.3*[-1,1,1,-1,-1]+1
        ycbox=1.3*[-1,-1,1,1,-1]
      endelse
      usersym,xcbox,ycbox,/fill,color=clr
      plots,xbar,ybar,psym=8,linestyle=ls,color=clr,/norm,symsize=symsize
      usersym,xcbox,ycbox
      plots,xbar,ybar,psym=8,linestyle=ls,/norm,symsize=symsize,thick=thk
    endif else begin
      if drawline then begin
        plots,xbar,ybar,psym=ps,linestyle=ls,color=clr,/norm,$
            symsize=symsize,thick=thk
      endif else begin
        if ps ne 0 then plots,max(xbar),max(ybar),psym=ps,color=clr,/norm,$
            symsize=symsize,thick=thk
      endelse
    endelse

    xyouts,xlab,ylab,labls(i),color=fgc,charsize=chrsz,/norm
    jlbl=jlbl+1

  endif else begin

    case just(i) of
      'l':begin & align=0.0 & xtitle=x0+dx      & end
      'f':begin & align=0.0 & xtitle=x0+dx      & end
      'c':begin & align=0.5 & xtitle=.5*(x0+x1) & end
      'r':begin & align=1.0 & xtitle=x1-dx      & end
    endcase
;    stop
    if just(i) eq 'f' then begin
      tstr=str_sep(titles(i),' ')
      lngth=lenstr(tstr)*chrsz
      nwords=n_elements(tstr)
      
      dspc=(x1-x0-2*dx-total(lngth))/((nwords-1)>1)
      if dspc gt 4*stdspc then dspc=2*stdspc
      for j=0,nwords-1 do begin 
        xyouts,xtitle,ylab,tstr(j),color=fgc,charsize=chrsz,/norm 
        xtitle=xtitle+dspc+lngth(j)
      endfor
    endif else begin  
      xyouts,xtitle,ylab,titles(i),color=fgc,charsize=chrsz,$
           alignment=align,/norm
    endelse
  endelse
  yy=yy-dy
endfor

return
end