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