Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

xyleg.cpp

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /* Módulo: xyleg.cpp                                                         */
00003 /* Autores: Carlos Henrique Levy e Jaudênia Cavalcante                       */
00004 /* Data: 26 jun 96                                                           */
00005 /* Comentário:                                                               */
00006 /*    Implementação de métodos da classe que gerencia a apresentação da le-  */
00007 /* genda para um determinado gráfico com o número de linhas e colunas defi-  */
00008 /* nidos pelo usuário. Essa classe faz uso da mesma lista de máscaras válida */
00009 /* para o gráfico ao qual ela está associada, medida que evita duplicação de */
00010 /* informação. Seu layout é composto por uma região delimitada pela presença */
00011 /* ou não de uma moldura, nomes das séries envolvidas e seus ícones de repre */
00012 /* sentação.                                                                 */
00013 /*****************************************************************************/
00014 
00015 #include <stdlib.h>
00016 #include "xyleg.h"
00017 
00018 const char* xy_id_xyleg_cpp="$Id: xyleg.cpp,v 1.20 2000/06/13 13:46:12 camilo Exp $";
00019                                                                 
00020 #define AREA_MM 15        // dimensão da região para o ícone da legenda
00021 #define SPACE_MM 4   // espaço para a legenda não colar em seu boundingBox
00022 #define MARG  2   // espessura da moldura da legenda
00023 
00024 XYLegend::XYLegend (XYCoordinate x,
00025                     XYCoordinate y,
00026                           int nlines,
00027                           int ncolumns,
00028                           xybool box,
00029                           xybool visible)
00030                           : XYObject(x, y, visible),
00031                             _nLines(nlines),
00032                             _nColumns(ncolumns),
00033                             _box(box),
00034                             _color(XY_WHITE),
00035                             _bColor(XY_BLACK)
00036 {
00037 }
00038 
00039 XYLegend::~XYLegend (void)
00040 {
00041 }
00042 
00043 void XYLegend::mask (const XYList<XYMask>* mask)
00044 {
00045    _masks = mask;
00046 }
00047 
00048 const XYList<XYMask>* XYLegend::mask (void) const
00049 {
00050    return _masks;
00051 }
00052 
00053 void XYLegend::backgroundColor (long color)
00054 {
00055    _color = color;
00056 }
00057 
00058 long XYLegend::backgroundColor (void) const
00059 {
00060    return _color;
00061 }
00062 
00063 void XYLegend::frameColor (long color)
00064 {
00065    _bColor = color;
00066 }
00067 
00068 long XYLegend::frameColor (void) const
00069 {
00070    return _bColor;
00071 }
00072 
00073 void XYLegend::lines (int nl)
00074 {
00075    _nLines = nl;
00076 }
00077 
00078 int XYLegend::lines (void) const
00079 {
00080    return _nLines;
00081 }
00082 
00083 void XYLegend::columns (int nc)
00084 {
00085    _nColumns = nc;
00086 }
00087 
00088 int XYLegend::columns (void) const
00089 {
00090    return _nColumns;
00091 }
00092 
00093 void XYLegend::box (xybool b)
00094 {
00095    _box = b;
00096 }
00097 
00098 xybool XYLegend::box (void) const
00099 {
00100    return _box;
00101 }
00102 
00103 xybool XYLegend::pick (int px, int py)
00104 {
00105    if (visible() == xyfalse)    // invisível!!!
00106       return xyfalse;
00107 
00108    // limites da menor caixa que contém uma legenda
00109    int x1, y1, x2, y2;
00110    boundingBox (x1, y1, x2, y2);
00111 
00112    return mtPointInRect (px, py, x1, y1, x2, y2);
00113 }
00114 
00115 XYMask* XYLegend::pickItem (int px, int py)
00116 {
00117    if (visible() == xyfalse)    // invisível!!!
00118       return NULL;
00119 
00120    XYListIterator<XYMask> im(_masks);
00121    XYMask* cont;
00122 
00123    int xmn, ymn, xmx, ymx;
00124 
00125    while (!im.End())
00126    {
00127             cont = im.Next();
00128       cont -> getItemViewport(xmn, xmx, ymn, ymx);
00129 
00130       if (mtPointInRect(px, py, xmn, ymn, xmx, ymx))
00131          return cont;
00132         }
00133 
00134    return NULL;
00135 }
00136 
00137 xybool XYLegend::fence (int x2, int y2, int x3, int y3)
00138 {
00139    if (visible() == xyfalse)           // invisível!!!
00140       return xyfalse;
00141 
00142    // limites da menor caixa que contém uma legenda
00143    int x0, y0, x1, y1;
00144    boundingBox (x0, y0, x1, y1);
00145 
00146    return mtInclude (x0, y0, x1, y1, x2, y2, x3, y3);
00147 }
00148 
00149 void XYLegend::clear(void) const
00150 {
00151    // consulta região de desenho da legenda
00152    int xmn, ymn, xmx, ymx;
00153    getViewport(xmn, xmx, ymn, ymx);
00154 
00155    // preenche o fundo da região da legenda com a cor definida pelo usuário
00156    cdForeground(backgroundColor());
00157    cdInteriorStyle(CD_SOLID);
00158 
00159    cdBox(xmn, xmx, ymn, ymx);
00160 }
00161 
00162 void XYLegend::clear(int xmin, int ymin, int xmax, int ymax) const
00163 {
00164    // preenche o fundo da região da legenda com a cor definida pelo usuário
00165    cdForeground(backgroundColor());
00166    cdInteriorStyle(CD_SOLID);
00167 
00168    cdBox(xmin, xmax, ymin, ymax);
00169 }
00170 
00171 void XYLegend::draw (void)
00172 {
00173    draw(_xmin, _ymin, _xmax, _ymax);
00174 }
00175 
00176 void XYLegend::draw (int /* xmin */, int /* ymin */, int /* xmax */, int /* ymax */) const
00177 {
00178    if (visible() == xyfalse)    // invisível!!!
00179       return;
00180 
00181    // calcula a região ocupada pela legenda
00182    int txmin, tymin, txmax, tymax;
00183    boundingBox(txmin, tymin, txmax, tymax);
00184 
00185    // se o boundingBox é degenerado não existe legenda a desenhar
00186    if ((txmin == txmax) && (tymin == tymax))
00187       return;
00188 
00189    int spx;
00190    double smx;
00191    cdGetCanvasSize( &spx, NULL, &smx, NULL );
00192    double resx = spx / smx;
00193    int AREA = (int)(AREA_MM * resx);
00194    int SPACE = (int)(SPACE_MM * resx);
00195 
00196    if (_box)
00197    {
00198       // desenha a moldura da legenda
00199       cdForeground(frameColor());
00200       cdInteriorStyle(CD_SOLID);
00201 
00202       cdBox(txmin, txmax, tymin, tymax);
00203    }
00204 
00205    // limpa região interna a moldura para o desenho da legenda
00206    clear(txmin + MARG, tymin + MARG, txmax - MARG, tymax - MARG);
00207 
00208    // calcula espacamento entre as colunas e linhas 
00209    int dx = (int) (((txmax - txmin) - (2 * MARG)) / _nColumns);
00210    int dy = (int) (((tymax - tymin) - (2 * MARG)) / _nLines);
00211 
00212    int x = txmin + MARG + SPACE;
00213    int y = tymax - MARG - dy;
00214 
00215    XYListIterator<XYMask> im(_masks);
00216 
00217    XYMask* cont = 0;
00218    XYText* name;
00219 
00220    int bbx1, bby1, bbx2, bby2;
00221 
00222    // desenha a legenda do gráfico respeitando o número de linhas e colunas
00223    // definidos pelo usuário
00224    for (int i = 1; i <= _nLines; i++)
00225    {
00226       for (int j = 1; j <= _nColumns; j++)
00227       {
00228          if (!im.End())
00229          {
00230                 name = NULL;
00231 
00232                 // procura a próxima máscara com nome
00233             while ((name == NULL) && (!im.End()))
00234             {
00235                    cont = im.Next();
00236                    name = cont -> name();
00237                 }
00238 
00239             if (name != NULL)
00240             {
00241                    // decide alinhamento
00242                    name -> align (XYText::southWest);
00243 
00244                    // decide posição para o nome
00245                    name -> position (x + AREA + SPACE, y);
00246 
00247                    // calcula o bounding box do nome da máscara
00248                    name -> boundingBox (bbx1, bby1, bbx2, bby2);
00249 
00250                    // desenha textos da legenda
00251                    name -> draw(x, y, bbx2, bby2);
00252 
00253                    cont -> setItemViewport(x, bbx2, y, bby2);
00254 
00255                // desenha o ícone da máscara na região dada, sem colar em suas
00256                    // bordas
00257                    cont -> drawIcon(x, y + SPACE, x + AREA, bby2 - SPACE);
00258 
00259                    // guarda o valor de x para o desenho do próximo nome
00260                            x += dx;
00261             }
00262          }
00263       }
00264 
00265           // valor inicial de x para a nova linha
00266       x = txmin + MARG + SPACE;         
00267       // valor inicial de y para a nova linha
00268       y -= dy;
00269    }
00270 }
00271 
00272 void XYLegend::boundingBox (int &bxmin, int &bymin, int &bxmax, int &bymax)
00273                                   const
00274 {
00275    if (visible() == xyfalse)    // invisível!!!
00276       return;
00277 
00278    // consulta posição de desenho da legenda
00279    int xd, yd;
00280    position (&xd, &yd);
00281 
00282    // (bxmin, bymin) ponto inferior esquerdo da área da legenda
00283    bxmin = xd;
00284    bymin = yd;
00285 
00286    // (bxmax, bymax) ponto superior direito da área da legenda
00287    bxmax = bxmin;
00288    bymax = bymin;
00289 
00290    XYListIterator<XYMask> im(_masks);
00291 
00292    XYMask* cont;
00293    XYText* name = NULL;
00294 
00295    // verifica existência de máscara com nome
00296    while ((name == NULL) && (!im.End()))
00297    {
00298       cont = im.Next();
00299       name = cont -> name();
00300    }
00301 
00302    // se não existe nome de máscara não haverá legenda
00303    if (name == NULL)
00304       return;
00305 
00306    im.Reset();
00307 
00308    // consulta região de desenho da legenda
00309    int x1, x2, y1, y2;
00310    getViewport(x1, x2, y1, y2);
00311 
00312    // limpa conteúdo do ponteiro
00313    name = NULL;
00314 
00315    int bbx1, bbx2, bby1, bby2;
00316 
00317    // decide maior nome a ser colocado na legenda
00318    while (!im.End())
00319    {
00320       cont = im.Next();
00321       name = cont -> name();
00322 
00323       if (name != NULL)
00324       {
00325          // decide alinhamento
00326          name -> align (XYText::southWest);
00327 
00328          // decide região de desenho do nome
00329          name -> setViewport(x1, x2, y1, y2);
00330 
00331          // decide posição para o nome
00332          name -> position (xd, yd);
00333 
00334          // calcula o bounding box do nome da máscara
00335          name -> boundingBox (bbx1, bby1, bbx2, bby2);
00336 
00337          // atualiza maior valor de x encontrado
00338          if (bxmax < bbx2)
00339             bxmax = bbx2;
00340 
00341          // atualiza maior valor de y encontrado
00342          if (bymax < bby2)
00343             bymax = bby2;
00344       }
00345    }
00346 
00347    // atualizando valor máximo de x para o maior nome de máscara considerando
00348    // a região de desenho do ícone e do espaço entre ele e o nome
00349    int spx;
00350    double smx;
00351    cdGetCanvasSize( &spx, NULL, &smx, NULL );
00352    double resx = spx / smx;
00353    int AREA = (int)( AREA_MM * resx );
00354    int SPACE = (int)( SPACE_MM * resx );
00355    bxmax += AREA + 3 * SPACE;
00356 
00357    // calcula valor máximo total de x na legenda, somando-se ao valor máximo
00358    // de x do maior nome o número de colunas restantes vezes o intervalo em
00359    // x que esse nome ocupa
00360    bxmax += (_nColumns - 1) * (bxmax - bxmin);
00361 
00362    // calcula valor máximo total de y na legenda, somando-se ao valor máximo
00363    // de y do maior nome o número de linhas restantes vezes o intervalo em
00364    // y que esse nome ocupa
00365    bymax += (_nLines - 1) * (bymax - bymin);
00366 
00367    // acrescenta espaço para a moldura
00368    bxmax += 2 * MARG;
00369    bymax += 2 * MARG;
00370 }
00371 

XY
Tecgraf / PUC-Rio - Computer Graphics Technology Group