gfxboard.cc

Go to the documentation of this file.
00001 /* Eliot                                                                     */
00002 /* Copyright (C) 1999  Antoine Fraboulet                                     */
00003 /*                                                                           */
00004 /* This file is part of Eliot.                                               */
00005 /*                                                                           */
00006 /* Eliot is free software; you can redistribute it and/or modify             */
00007 /* it under the terms of the GNU General Public License as published by      */
00008 /* the Free Software Foundation; either version 2 of the License, or         */
00009 /* (at your option) any later version.                                       */
00010 /*                                                                           */
00011 /* Eliot is distributed in the hope that it will be useful,                  */
00012 /* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
00013 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
00014 /* GNU General Public License for more details.                              */
00015 /*                                                                           */
00016 /* You should have received a copy of the GNU General Public License         */
00017 /* along with this program; if not, write to the Free Software               */
00018 /* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
00019 
00020 /**
00021  *  \file   gfxboard.cc
00022  *  \brief  Game board graphical view
00023  *  \author Antoine Fraboulet
00024  *  \date   2002
00025  */
00026 
00027 #include <string.h>
00028 #include <math.h>
00029 #include <ctype.h>
00030 
00031 #include "wx/dcmemory.h"
00032 
00033 #include "ewx.h"
00034 #include "dic.h"
00035 #include "game.h"
00036 #include "configdb.h"
00037 #include "gfxboard.h"
00038 
00039 #ifdef DEBUG_
00040 #   define GFXDEBUG(x) x
00041 #else
00042 #   define GFXDEBUG(x)
00043 #endif
00044 
00045 BEGIN_EVENT_TABLE(GfxBoard, wxWindow)
00046     EVT_PAINT(GfxBoard::OnPaint)
00047     EVT_SIZE(GfxBoard::OnSize)
00048 END_EVENT_TABLE()
00049 
00050 #define LINE_WIDTH 1
00051 #define BOARD_SIZE (BOARD_DIM + 2)
00052 
00053     /* ************************************************** */
00054     /* ************************************************** */
00055 
00056 GfxBoard::GfxBoard(wxFrame *parent, Game &iGame) :
00057         wxWindow(parent, wxWindowID(-1), wxDefaultPosition, wxDefaultSize,
00058                  wxNO_BORDER | wxFULL_REPAINT_ON_RESIZE, wxT("gfxboard")),
00059         m_game(iGame)
00060 {
00061     bmp          = NULL;
00062     board_size   = 0;
00063     tile_size    = 0;
00064 #if defined(MSW_RESIZE_BUG)
00065     just_resized = false;
00066 #endif
00067     for(int i=0; i<BOARD_DIM; i++)
00068         {
00069             for(int j=0; j < BOARD_DIM; j++)
00070                 {
00071                     paintedboard_char[i][j] = wxT(' ');
00072                     paintedboard_attr[i][j] = 0;
00073                 }
00074         }
00075 }
00076 
00077     /* ************************************************** */
00078     /* ************************************************** */
00079 
00080 GfxBoard::~GfxBoard(void)
00081 {
00082     if (bmp)
00083         {
00084             delete bmp;
00085             bmp = NULL;
00086         }
00087 }
00088 
00089 /**
00090  * Make new dimensions available for the next OnPaint
00091  * event. The BMP is deleted if it exists.
00092  */
00093 
00094 void
00095 GfxBoard::OnSize(wxSizeEvent& e)
00096 {
00097     GFXDEBUG(std::cerr << "On size : ");
00098 
00099     wxSize cs = GetClientSize();
00100     board_size = cs.GetWidth() < cs.GetHeight() ? cs.GetWidth() : cs.GetHeight();
00101     tile_size  = (int)((float)board_size / (float)(BOARD_SIZE)) - LINE_WIDTH;
00102 
00103     GFXDEBUG(std::cerr << "(" << cs.GetWidth() << "," << cs.GetHeight() << ")");
00104     GFXDEBUG(std::cerr << " tile size " << tile_size << endl);
00105 
00106     TopLeft  = wxPoint((cs.GetWidth()  - (board_size - tile_size/2)) / 2,
00107                        (cs.GetHeight() - (board_size - tile_size/2)) / 2);
00108 
00109 #if defined(MSW_RESIZE_BUG)
00110     just_resized = true;
00111 #endif
00112 
00113     if (bmp)
00114         {
00115             delete bmp;
00116             bmp = NULL;
00117         }
00118 }
00119 
00120 /**
00121  * Creates a BMP in memory and draws the board inside
00122  */
00123 
00124 void
00125 GfxBoard::CreateBMP()
00126 {
00127     GFXDEBUG(std::cerr << "Create BMP ");
00128     if (!bmp)
00129         {
00130             wxSize bs = GetClientSize();
00131             bmp=new wxBitmap(bs.x,bs.y);
00132             GFXDEBUG(std::cerr << " new bmp (" << bs.x << "," << bs.y << ")");
00133             if (bmp)
00134                 {
00135                     wxMemoryDC memDC;
00136                     memDC.SelectObject(* bmp);
00137                     DrawBoard(&memDC);
00138                     memDC.SelectObject(wxNullBitmap);
00139                 }
00140         }
00141     GFXDEBUG(std::cerr << endl);
00142 }
00143 
00144 
00145 /**
00146  * Update the full BMP and copy only the requested area
00147  * to the ClientDC
00148  */
00149 
00150 void
00151 GfxBoard::RefreshSquare(wxRect &r)
00152 {
00153     wxClientDC dc(this);
00154 
00155     if (bmp)
00156         {
00157             int vX,vY,vW,vH;
00158             wxMemoryDC memDC;
00159             memDC.SelectObject(* bmp);
00160             DrawBoard(&memDC);
00161             vX = r.x;
00162             vY = r.y;
00163             vW = r.width;
00164             vH = r.height;
00165             GFXDEBUG(std::cerr << " refresh (" << vX << "," << vY << "," << vW << "," << vH << ") ");
00166             dc.Blit(vX,vY,vW,vH,&memDC,vX,vY,wxCOPY);
00167             memDC.SelectObject(wxNullBitmap);
00168         }
00169     else
00170         {
00171             DrawBoard(&dc);
00172         }
00173 }
00174 
00175 /**
00176  * Force a full refresh of the board
00177  */
00178 
00179 void
00180 GfxBoard::Refresh(board_refresh_t WXUNUSED(force))
00181 {
00182     wxSize cs = GetClientSize();
00183     board_size = cs.GetWidth() < cs.GetHeight() ? cs.GetWidth() : cs.GetHeight();
00184     tile_size  = (int)((float)board_size / (float)(BOARD_SIZE)) - LINE_WIDTH;
00185     wxRect r (0,0,cs.GetWidth(),cs.GetHeight());
00186     RefreshSquare(r);
00187 }
00188 
00189 /**
00190  * Window manager OnPaint event handler.
00191  */
00192 
00193 void
00194 GfxBoard::OnPaint(wxPaintEvent&)
00195 {
00196     wxPaintDC dc(this);
00197 
00198     CreateBMP();
00199 
00200     GFXDEBUG(std::cerr << "OnPaint : ");
00201 
00202     if (bmp)
00203         {
00204 #if defined(MSW_RESIZE_BUG)
00205             Refresh(BOARD_FORCE_REFRESH);
00206             if (just_resized == true)
00207                 {
00208                     just_resized = false;
00209                 }
00210 #else
00211             // we keep that code for wxgtk
00212             // it does not work under wxmsw, don't know why
00213             // all the onsize/repaint should be checked ... later
00214             int vX,vY,vW,vH;
00215             wxMemoryDC memDC;
00216             memDC.SelectObject(* bmp);
00217             wxRegionIterator upd(GetUpdateRegion());
00218             while (upd)
00219                 {
00220                     vX = upd.GetX();
00221                     vY = upd.GetY();
00222                     vW = upd.GetW();
00223                     vH = upd.GetH();
00224                     GFXDEBUG(std::cerr << "+(" << vX << "," << vY << "," << vW << "," << vH << ")");
00225                     dc.Blit(vX,vY,vW,vH,&memDC,vX,vY,wxCOPY);
00226                     upd ++ ;
00227                 }
00228             memDC.SelectObject(wxNullBitmap);
00229 #endif
00230         }
00231     else
00232         {
00233             GFXDEBUG(std::cerr << " call to DrawBoard ");
00234             DrawBoard(&dc);
00235         }
00236 
00237     GFXDEBUG(std::cerr << "End of OnPaint" << endl);
00238 }
00239 
00240 
00241 void
00242 GfxBoard::DrawTileBack(wxDC* dc, int top, int left, int size, bool testtile)
00243 {
00244     //    void DrawRoundedRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height, double radius = 20)
00245     wxBrush oldbrush = dc->GetBrush();
00246     wxColour colBackground;
00247 
00248     if (testtile)
00249         {
00250             colBackground = config.getColour(wxString(BTSTTILEBACKGROUND));
00251         }
00252     else
00253         {
00254             colBackground = config.getColour(wxString(BTILEBACKGROUND));
00255         }
00256 
00257     wxBrush *BackgroundBrush = wxTheBrushList->FindOrCreateBrush(colBackground, wxSOLID);
00258     dc->SetBrush(* BackgroundBrush);
00259     dc->DrawRoundedRectangle(left,top,size,size,std::max(2,size/6));
00260     dc->SetBrush(oldbrush);
00261 }
00262 
00263 /**
00264  * Draw a tile to the wxDC object.
00265  */
00266 
00267 #define TILE_LEFT(col) (col*(tile_size+LINE_WIDTH) + TopLeft.x)
00268 #define TILE_TOP(row) (row*(tile_size+LINE_WIDTH) + TopLeft.y)
00269 
00270 /*
00271    TODO
00272    - ajuster avec une LINE_SIZE differente
00273    - calculer la taille de la police
00274 */
00275 
00276 /*    TILE_LEFT
00277       |
00278       |  TILE_LEFT + LINE_WIDTH
00279       |  |
00280       +++++++++-- TILE_TOP
00281       +++++++++
00282       +++++++++
00283       +++   +++-------------- TILE_TOP + LINE_WIDTH
00284       +++   +++ | = tile_size
00285       +++   +++--
00286       +++++++++--
00287       +++++++++ | = LINE_WIDTH
00288       +++++++++--
00289       | |
00290       |_|
00291        |
00292        LINE_WIDTH
00293 */
00294 
00295 void
00296 GfxBoard::DrawTile(wxDC *dc, wxString& wxs, int row, int column, bool testtile, bool drawtileback)
00297 {
00298     wxColour colour;
00299     wxCoord width, height;
00300     wxCoord posx, posy;
00301     wxCoord left,top;
00302     // redraw borders
00303     left = TILE_LEFT(column);
00304     top  = TILE_TOP(row);
00305 
00306     if (wxs.length() > 0 && *wxs.GetData())
00307         {
00308             // we got a letter (or 2 chars for coordinates > 9)
00309             // draw plastic tile
00310             if (drawtileback)
00311                 {
00312                     DrawTileBack(dc,
00313                                  top  + LINE_WIDTH,
00314                                  left + LINE_WIDTH,
00315                                  tile_size, testtile);
00316                 }
00317             // draw letter
00318             if (testtile)
00319                 {
00320                     colour = config.getColour(wxString(BCOLOURTSTLETTERS));
00321                 }
00322             else
00323                 {
00324                     colour = config.getColour(wxString(BCOLOURLETTERS));
00325                 }
00326 
00327             dc->SetTextForeground(colour);
00328             dc->GetTextExtent(wxs,&width,&height);
00329             posx = left + LINE_WIDTH + (tile_size - width) / 2;
00330             posy = top  + LINE_WIDTH + (tile_size - height) / 2;
00331             dc->DrawText(wxs,posx,posy);
00332         }
00333 }
00334 
00335 /**
00336  * Draw the complete board in the wxDC.
00337  */
00338 
00339 void
00340 GfxBoard::DrawBoard(wxDC *dc)
00341 {
00342     Board board;
00343 
00344     wxString wxs;
00345     int row,column;
00346 
00347     wxFont   font            = config.getFont(BOARDFONT);
00348     wxColour colForeground   = config.getColour(wxString(BCOLOURLINES));
00349     wxColour colBackground   = config.getColour(wxString(BCOLOURBACKGROUND));
00350 
00351     wxBrush *BackgroundBrush = wxTheBrushList->FindOrCreateBrush(colBackground, wxSOLID);
00352     wxPen   *LinesPen        = wxThePenList->FindOrCreatePen(colForeground, LINE_WIDTH, wxSOLID);
00353 
00354     dc->SetFont (font);
00355     dc->SetPen  (* LinesPen);
00356     dc->SetBrush(* BackgroundBrush);
00357 
00358     // background rectangle (entire frame)
00359     wxSize bs = GetClientSize();
00360     dc->DrawRectangle(0,0,bs.x,bs.y);
00361 
00362     // lines
00363     for(row=BOARD_MIN; row < BOARD_MAX; row++)
00364         {
00365             // vertical
00366             dc->DrawLine(TILE_LEFT(row+1),
00367                          TILE_TOP(1),
00368                          TILE_LEFT(row+1),
00369                          TILE_TOP(BOARD_MAX));
00370             // horizontal row <-> line
00371             dc->DrawLine(TILE_LEFT(1),
00372                          TILE_TOP(row+1),
00373                          TILE_LEFT(BOARD_MAX),
00374                          TILE_TOP(row+1));
00375         }
00376 
00377     // 1 2 3 4 5 ...
00378     // A B C D ...
00379     for(row=BOARD_MIN; row <= BOARD_MAX; row++)
00380         {
00381             wxs.Printf(wxT("%d"), row);
00382             DrawTile(dc, wxs, 0, row);
00383             wxs.Printf(wxT("%c"), row + 'A' - 1);
00384             DrawTile(dc, wxs, row, 0);
00385         }
00386 
00387     // Board Background
00388     wxColour colWx3         = config.getColour(wxString(BCOLOURWX3));
00389     wxColour colWx2         = config.getColour(wxString(BCOLOURWX2));
00390     wxColour colLx3         = config.getColour(wxString(BCOLOURLX3));
00391     wxColour colLx2         = config.getColour(wxString(BCOLOURLX2));
00392 
00393     wxBrush *Wx3Brush = wxTheBrushList->FindOrCreateBrush(colWx3, wxSOLID);
00394     wxBrush *Wx2Brush = wxTheBrushList->FindOrCreateBrush(colWx2, wxSOLID);
00395     wxBrush *Lx3Brush = wxTheBrushList->FindOrCreateBrush(colLx3, wxSOLID);
00396     wxBrush *Lx2Brush = wxTheBrushList->FindOrCreateBrush(colLx2, wxSOLID);
00397 
00398     board = m_game.getBoard();
00399     for(row=BOARD_MIN; row <= BOARD_MAX; row++)
00400         {
00401             for (column = BOARD_MIN; column <= BOARD_MAX; column++)
00402                 {
00403                     if (board.getLetterMultiplier(row, column) == 2)
00404                         {
00405                             dc->SetBrush(*Lx2Brush);
00406                         }
00407                     else if (board.getLetterMultiplier(row, column) == 3)
00408                         {
00409                             dc->SetBrush(*Lx3Brush);
00410                         }
00411                     else if (board.getWordMultiplier(row, column) == 2)
00412                         {
00413                             dc->SetBrush(*Wx2Brush);
00414                         }
00415                     else if (board.getWordMultiplier(row, column) == 3)
00416                         {
00417                             dc->SetBrush(*Wx3Brush);
00418                         }
00419                     else
00420                         {
00421                             dc->SetBrush(*BackgroundBrush);
00422                         }
00423 
00424                     if (row && column)
00425                         {
00426                             dc->DrawRectangle(TILE_LEFT(column), TILE_TOP(row),
00427                                               tile_size + 2*LINE_WIDTH,
00428                                               tile_size + 2*LINE_WIDTH);
00429                         }
00430                 }
00431         }
00432 
00433     // Tiles
00434     LinesPen->SetWidth(1);
00435     dc->SetPen  (* LinesPen);
00436     bool drawtiles = config.getDrawTile();
00437     for(row=BOARD_MIN; row <= BOARD_MAX; row++)
00438         {
00439             for (column = BOARD_MIN; column <= BOARD_MAX; column++)
00440                 {
00441                     int attr = board.getCharAttr(row, column);
00442                     wxs  = wxString((wxChar)board.getChar(row, column));
00443 
00444                     paintedboard_char[row - BOARD_MIN][column - BOARD_MIN] = *wxs.GetData();
00445                     paintedboard_attr[row - BOARD_MIN][column - BOARD_MIN] = attr;
00446 
00447                     DrawTile(dc,wxs,row,column,attr & ATTR_TEST,drawtiles);
00448                 }
00449         }
00450 
00451     dc->SetFont(wxNullFont);
00452 }
00453 
00454 
00455 /// Local Variables:
00456 /// mode: hs-minor
00457 /// c-basic-offset: 4
00458 /// End:

Generated on Thu Dec 29 02:01:15 2005 for Eliot by  doxygen 1.4.5