Logo Search packages:      
Sourcecode: octplot version File versions  Download package

legend.cpp

// Copyright (C) 2003 Shai Ayal <shaiay@users.sourceforge.net>
//  
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//  
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//  
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//  

#include "legend.h"
#include "line.h"
#include "axes.h"
#include "text.h"
#include "patch.h"
#include "octplotapp.h"

#define OBJ_NAME "Legend"

Legend::Legend(ocpl::Handle Parent) : Object(Parent)
{
  Properties["Label"] = new HandleVect;
  Properties["Label"]->readonly(true);
  Properties["Line"] = new HandleVect;
  Properties["Line"]->readonly(true);
  Properties["Patch"] = new HandleVect;
  Properties["Patch"]->readonly(true);

  SET_TYPE;
  COPY_DEFAULT(Clipping,Radio);
  COPY_DEFAULT(Location,Radio);
  COPY_DEFAULT(Color,Color);
  COPY_DEFAULT(EdgeColor,ColorNone);
  COPY_DEFAULT(FaceColor,ColorNone);
  COPY_DEFAULT(FontName,Radio);
  COPY_DEFAULT(FontSize,Scalar);
}

void Legend::draw()
{
  IS_VISIBLE;

  MAKE_REF(color,Color);
  MAKE_REF(facecolor,ColorNone);
  MAKE_REF(edgecolor,ColorNone);
  MAKE_REF(fontsize,Scalar);
  MAKE_REF(fontname,Radio);
  MAKE_REF(label,HandleVect);
  MAKE_REF(line,HandleVect);
  MAKE_REF(patch,HandleVect);
  MAKE_REF(clipping,Radio);
  MAKE_REF(location,Radio);

  Axes* axes  = dynamic_cast<Axes*>(FindParentOfType("axes"));
  Radio& xscale = ::Get<Radio>(axes,"xscale");
  Radio& yscale = ::Get<Radio>(axes,"yscale");
  HandleVect& children = ::Get<HandleVect>(axes,"children");

  // Get labels & line styles from children
  label.Clear();
  line.Clear();
  patch.Clear();
  double lh=0,lw=0;

  // find all axes children which are lines and add them to the legend
  for ( children.First() ; !children.IsDone() ; children.Next() ) {
    Line *cln = 
      dynamic_cast<Line*>(OctPlotApp::GetObjectD(children.CurrentHandle()));
    if(cln) {
      String& cur_lab=::Get<String>(cln,"label");
      if(cur_lab.Size()) {
      line.Add((new Line(Self,*cln))->GetHandle());
      Text* txt = new Text(Self,cur_lab(),0,0,0);
      txt->SetProperty("Color",new Color(color));
      txt->SetProperty("FontSize",new Scalar(fontsize));
      txt->SetProperty("FontName",new Radio(fontname));
      label.Add(txt->GetHandle());
      if(txt->w() > lw) lw=txt->w();
      lh = txt->lh();
      }
    }
  }

  // nothing to do if there are no lables!
  if(label.Size()==0) return;

  // Calculate positions for everything
  double px,py;
  axes->GetPixel(px,py);

  // change everything into axes coords
  lw *= px;
  lh *= py;

  // legendbox size
  double width  = 3*px + 20*px + 3*px + lw + 3*px;
  double height = lh*label.Size() + 6*px; 

  Matrix& xlim = ::Get<Matrix>(axes,"xlim");
  Matrix& ylim = ::Get<Matrix>(axes,"ylim");


  // Legend position according to location - -Ugly
  double x,y;
  if( location()=="ne" || location()=="northeast") {
    x = xlim(1) - width-10*px;      
    y = ylim(1) - 10*py;
  }
  else if( location()=="nw" || location()=="northwest") {
    x = xlim(0) + 10*px;      
    y = ylim(1) - 10*py;
  }
  else if( location()=="se" || location()=="southeast") {
    x = xlim(1) - width-10*px;      
    y = ylim(0) + +height + 10*py;
  }
  else if( location()=="sw" || location()=="southwest") {
    x = xlim(0) + 10*px;      
    y = ylim(0) + height + 10*py;
  }
  else if( location()=="s" || location()=="south") {
    x = (xlim(0) + xlim(1) - width)/2;    
    y = ylim(0) + height + 10*py;
  }  
  else if( location()=="n" || location()=="north") {
    x = (xlim(0) + xlim(1) - width)/2;    
    y = ylim(1) - 10*py;
  }
  else if( location()=="w" || location()=="west") {
    x = xlim(0) + 10*px;      
    y = (ylim(0) + ylim(1) + height)/2;
  }
  else if( location()=="e" || location()=="east") {
    x = xlim(1) - width-10*px;      
    y = (ylim(0) + ylim(1) + height)/2;
  }

  // lines
  double xd[3],yd[3],dy;
  xd[0] = x + 3*px;
  xd[2] = x + width - lw - 6*px;
  xd[1] = (xd[0]+xd[2])/2.;
  for(line.First() , dy=0; !line.IsDone() ; line.Next() , dy+=lh ) {
    yd[0] = yd[1] = yd[2] = y - dy - 0.5*lh - 3*px;
    ::Set(line.CurrentHandle(),"XData",xd,3);
    ::Set(line.CurrentHandle(),"YData",yd,3);
  }

  // labels
  double pos[3];
  pos[0] = x + width - lw - 3*px;
  pos[2] = object_z;
  for(dy=0,label.First(); !label.IsDone() ; label.Next() , dy+=lh ) {
    pos[1] = y - dy - 0.5*lh - 3*px;
    ::Set(label.CurrentHandle(),"Position",pos,3);
    ::Set(label.CurrentHandle(),"HorizontalAlignment","left");
    ::Set(label.CurrentHandle(),"VerticalAlignment","middle");
  }

  // patch
  double *xp=new double[4];
  double *yp=new double[4];
  xp[0] = x;         yp[0] = y;
  xp[1] = x+width  ; yp[1] = y;
  xp[2] = xp[1]    ; yp[2] = y-height;
  xp[3] = x;       ; yp[3] = yp[2];
  Matrix XM(xp,1,4);
  Matrix YM(yp,1,4);
  Patch* ptc = new Patch(Self,XM,YM);
  ptc->SetProperty("FaceColor",new ColorNone(facecolor));
  ptc->SetProperty("EdgeColor",new ColorNone(edgecolor));
  patch.Add(ptc->GetHandle());
  
  SET_CLIPPING;

  glMatrixMode(GL_MODELVIEW);
  glPushMatrix();
  // legend should be above all other stuff
  glTranslated(0,0,object_z);

  // printing must be set here
  label.SetPrinting(printing);
  line.SetPrinting(printing);
  patch.SetPrinting(printing);

  patch.AllDraw();
  line.AllDraw();
  label.AllDraw();

  glPopMatrix();
  UNSET_CLIPPING;
}


Generated by  Doxygen 1.6.0   Back to index