00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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
00040 typedef Key key_type;
00041 typedef const key_type& param0;
00042
00043
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
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
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
00179 key_type key = cell;
00180 if (key == default_cell_data())
00181 continue;
00182
00183
00184 bg_wnd::cell_range range = cell.range();
00185 if (col != range.top_left().col() || row != range.top_left().row())
00186 continue;
00187
00188
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
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);
00213 continue;
00214 }
00215 }
00216 }
00217 }
00218
00219 private:
00220
00221 void add_painter_impl(const key_type& key, painter_base* pPainter)
00222 {
00223 _ASSERTE(pPainter);
00224
00225
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 } }