Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages

background_wnd/painters/layout_painter.hpp

00001 // layout_painter.hpp
00002 
00003 // Copyright (C) 2004 Steven Weiß (steven11@gmx.de)
00004 //
00005 // Permission to copy, use, sell and distribute this software is granted
00006 // provided this copyright notice appears in all copies.
00007 // Permission to modify the code and to distribute modified code is granted
00008 // provided this copyright notice appears in all copies, and a notice
00009 // that the code was modified is included with the copyright notice.
00010 //
00011 // This software is provided "as is" without express or implied warranty,
00012 // and with no claim as to its suitability for any purpose.
00013 
00014 
00015 #pragma once
00016 #include <background_wnd/detail/include.hpp>
00017 #include <background_wnd/painter_base.hpp>
00018 #include <background_wnd/detail/table.hpp>
00019 
00020 
00021 namespace win32 { namespace gui {
00022 
00028 template <class Key = int>
00029 class layout_painter : public painter_base, 
00030                             public bg_wnd::table<Key>
00031 {
00032 private:  
00033      typedef boost::shared_ptr<painter_base> PainterPtr;
00034      typedef std::map<Key, PainterPtr> PainterMap;
00035      typedef bg_wnd::table<Key> Table;
00036      
00037      typedef layout_painter<Key> self;  
00038 public:   
00039      // typedef's
00040      typedef Key key_type;
00041      typedef const key_type& param0;
00042 
00043      // exceptions
00044      typedef bg_wnd::general_exception<self, 0> key_already_used;
00045      typedef bg_wnd::general_exception<self, 1> key_invalid;
00046      typedef bg_wnd::general_exception<self, 2> invalid_painter_cast;
00047 
00048      
00049      // c'tor
00050      layout_painter(const key_type& empty_field) : Table(empty_field), horz_margin_(0), vert_margin_(0), bOuterMargin_(true)
00051      {}
00052      
00054      layout_painter* clone() const
00055      {
00056           return new layout_painter(*this);
00057      }
00058 
00063      void margin(unsigned horz_margin, unsigned vert_margin, bool bOuterMargin = true)
00064      {
00065           horz_margin_ = horz_margin;
00066           vert_margin_ = vert_margin;
00067           bOuterMargin_ = bOuterMargin;
00068      }
00069 
00071      POINT margin() const
00072      {
00073           POINT pt = { horz_margin_, vert_margin_ };
00074           return pt;
00075      }
00076 
00077           
00081      void add_painter(const key_type& key, const painter_base& painter)
00082      {
00083           add_painter_impl(key, painter.clone());
00084      }
00085 
00089     template <class Painter>
00090     void add_painter(const key_type& key)
00091     {     
00092           add_painter_impl(key, new Painter());        
00093     }
00094 
00100     template <class Painter>
00101     void add_painter(const key_type& key, typename Painter::param0 param)
00102     {
00103           add_painter_impl(key, new Painter(param));        
00104     }
00105 
00111     template <class Painter>
00112     void add_painter(const key_type& key, typename Painter::param0 param0, typename Painter::param1 param1)
00113     {
00114           add_painter_impl(key, new Painter(param0, param1));
00115     }     
00116 
00118      void delete_all_painters()
00119      {
00120           map_painters_.clear();
00121      }
00122 
00126      void delete_painter(const key_type& key)
00127      {
00128           map_painters_.erase(find_painter_iterator(key));       
00129      }
00130 
00132      std::vector<key_type> get_keys() const
00133      {
00134           std::vector<key_type> keys;
00135           keys.reserve(map_keys_.size());
00136           for (PainterMap::const_iterator it = map_painters_.begin(); it != map_painters_.end(); ++it)
00137                keys.push_back(it->first);
00138           return keys;
00139      }
00140 
00148      template <class Painter>
00149     Painter& get_painter(const key_type& key) const
00150     {
00151           PainterPtr pPainter = find_painter_iterator(key)->second;
00152           Painter* p = dynamic_cast<Painter*> (pPainter.get());
00153           if (p == NULL)
00154                throw invalid_painter_cast(*this);
00155 
00156         return *p;                 
00157     }
00158 
00159      void draw(HDC hDC, int cx, int cy)
00160      {         
00161           if (row_count() == 0 || col_count() == 0)
00162                return;
00163           
00164           // calculate scaled margin and default width and height of a cell
00165           const unsigned HORZ_MARGIN_COUNT = bOuterMargin_ ? col_count() + 1 : col_count() - 1;
00166           const unsigned VERT_MARGIN_COUNT = bOuterMargin_ ? row_count() + 1 : row_count() - 1;
00167           const unsigned HORZ_MARGIN = horz_margin_;
00168           const unsigned VERT_MARGIN = vert_margin_;
00169           const int DEF_WIDTH         = (cx - HORZ_MARGIN * HORZ_MARGIN_COUNT) / col_count();
00170           const int DEF_HEIGHT        = (cy - VERT_MARGIN * VERT_MARGIN_COUNT) / row_count();
00171           if (DEF_WIDTH <= 0 || DEF_HEIGHT <= 0)
00172                return;        
00173 
00174           for (unsigned row = 0; row < row_count(); ++row) {               
00175                for (unsigned col = 0; col < col_count(); ++col) {                    
00176                     cell_type cell = (*this) [col][row];                                       
00177 
00178                     // empty field?
00179                     key_type key = cell;                    
00180                     if (key == default_cell_data())
00181                          continue;                                                        
00182 
00183                     // if a cell is in a range only the upper left cell will be drawn!
00184                     bg_wnd::cell_range range = cell.range();
00185                     if (col != range.top_left().col() || row != range.top_left().row())
00186                          continue;
00187 
00188                     // calculate position and size of the cell
00189                     factor left   = cell.log_left();
00190                     factor top    = cell.log_top();                                       
00191                     factor width  = cell.log_width();
00192                     factor height = cell.log_height();
00193 
00194                     POINT ptTopLeft = { (long) (DEF_WIDTH * left), (long) (DEF_HEIGHT * top) };
00195                     SIZE size      = { (long) (DEF_WIDTH * width), (long) (DEF_HEIGHT * height) };
00196                     
00197                     // add margin
00198                     ptTopLeft.x += bOuterMargin_ ? (col + 1) * HORZ_MARGIN : col * HORZ_MARGIN;
00199                     ptTopLeft.y += bOuterMargin_ ? (row + 1) * VERT_MARGIN : row * VERT_MARGIN;
00200                     size.cx        += (range.horz_count() - 1) * HORZ_MARGIN;
00201                     size.cy        += (range.vert_count() - 1) * VERT_MARGIN;
00202                     
00203                     try {
00204                          bg_wnd::memory_dc memDC;
00205                          memDC.create_dc(hDC, size.cx, size.cy);
00206                          BitBlt(memDC, 0, 0, size.cx, size.cy, hDC, ptTopLeft.x, ptTopLeft.y, SRCCOPY);
00207 
00208                          get_painter<painter_base> (key).draw(memDC, size.cx, size.cy);
00209                          memDC.bitblt(hDC, ptTopLeft.x, ptTopLeft.y, size.cx, size.cy);
00210                     }
00211                     catch (bg_wnd::general_exception_of_type<self>&) {                              
00212                          _ASSERTE(false);              // shouldn't throw...something is wrong                     
00213                          continue;
00214                     }                             
00215                }              
00216           }
00217      }
00218 
00219 private:
00220      // adds a painter
00221      void add_painter_impl(const key_type& key, painter_base* pPainter)
00222      {
00223           _ASSERTE(pPainter);                     // pPainter must be a valid pointer to an object
00224 
00225           // check if key already exists
00226           if (key == default_cell_data() || map_painters_.find(key) != map_painters_.end()) {
00227                delete pPainter;
00228                throw key_already_used(*this);
00229           }
00230           else {
00231                try {
00232                     map_painters_.insert( PainterMap::value_type(key, PainterPtr(pPainter)) );
00233                }
00234                catch (...) {
00235                     delete pPainter;
00236                     throw;
00237                }
00238           }
00239      }
00240 
00241      typename PainterMap::iterator find_painter_iterator(const key_type& key)
00242      {
00243           PainterMap::iterator it = map_painters_.find(key);
00244           if (it == map_painters_.end())
00245                throw key_invalid(*this);
00246           return it;
00247      }
00248 
00249      typename PainterMap::const_iterator find_painter_iterator(const key_type& key) const
00250      {
00251           PainterMap::const_iterator it = map_painters_.find(key);
00252           if (it == map_painters_.end())
00253                throw key_invalid(*this);
00254           return it;
00255      }
00256      
00257      PainterMap map_painters_;
00258      unsigned horz_margin_;        
00259      unsigned vert_margin_;        
00260      bool  bOuterMargin_;
00261 };
00262 
00263 } }  // namespace win32::gui

Generated on Mon Dec 27 13:16:34 2004 for background_wnd by  doxygen 1.3.9.1