1 // -*- C++ -*- 2 /* \file CoordCache.h 3 * This file is part of LyX, the document processor. 4 * Licence details can be found in the file COPYING. 5 * 6 * \author André Pönitz 7 * 8 * Full author contact details are available in file CREDITS. 9 */ 10 11 #ifndef COORDCACHE_H 12 #define COORDCACHE_H 13 14 // It seems that MacOSX define the check macro. 15 #undef check 16 17 #include "Dimension.h" 18 19 #include <map> 20 21 namespace lyx { 22 23 class Inset; 24 class Text; 25 class MathData; 26 class Paragraph; 27 28 void lyxbreaker(void const * data, const char * hint, int size); 29 30 struct Geometry { 31 Point pos; 32 Dimension dim; 33 coversGeometry34 bool covers(int x, int y) const 35 { 36 return x >= pos.x_ 37 && x <= pos.x_ + dim.wid 38 && y >= pos.y_ - dim.asc 39 && y <= pos.y_ + dim.des; 40 } 41 squareDistanceGeometry42 int squareDistance(int x, int y) const 43 { 44 int xx = 0; 45 int yy = 0; 46 47 if (x < pos.x_) 48 xx = pos.x_ - x; 49 else if (x > pos.x_ + dim.wid) 50 xx = x - pos.x_ - dim.wid; 51 52 if (y < pos.y_ - dim.asc) 53 yy = pos.y_ - dim.asc - y; 54 else if (y > pos.y_ + dim.des) 55 yy = y - pos.y_ - dim.des; 56 57 // Optimisation: We avoid to compute the sqrt on purpose. 58 return xx*xx + yy*yy; 59 } 60 }; 61 62 63 template <class T> class CoordCacheBase { 64 public: clear()65 void clear() 66 { 67 data_.clear(); 68 } 69 empty()70 bool empty() const 71 { 72 return data_.empty(); 73 } 74 add(T const * thing,int x,int y)75 void add(T const * thing, int x, int y) 76 { 77 data_[thing].pos = Point(x, y); 78 } 79 add(T const * thing,Dimension const & dim)80 void add(T const * thing, Dimension const & dim) 81 { 82 if (!has(thing)) 83 data_[thing].pos = Point(-10000, -10000); 84 data_[thing].dim = dim; 85 } 86 geometry(T const * thing)87 Geometry const & geometry(T const * thing) const 88 { 89 check(thing, "geometry"); 90 return data_.find(thing)->second; 91 } 92 dim(T const * thing)93 Dimension const & dim(T const * thing) const 94 { 95 checkDim(thing, "dim"); 96 return data_.find(thing)->second.dim; 97 } 98 x(T const * thing)99 int x(T const * thing) const 100 { 101 check(thing, "x"); 102 return data_.find(thing)->second.pos.x_; 103 } 104 y(T const * thing)105 int y(T const * thing) const 106 { 107 check(thing, "y"); 108 return data_.find(thing)->second.pos.y_; 109 } 110 xy(T const * thing)111 Point xy(T const * thing) const 112 { 113 check(thing, "xy"); 114 return data_.find(thing)->second.pos; 115 } 116 has(T const * thing)117 bool has(T const * thing) const 118 { 119 typename cache_type::const_iterator it = data_.find(thing); 120 121 if (it == data_.end()) 122 return false; 123 return it->second.pos.x_ != -10000; 124 } 125 hasDim(T const * thing)126 bool hasDim(T const * thing) const 127 { 128 return data_.find(thing) != data_.end(); 129 } 130 covers(T const * thing,int x,int y)131 bool covers(T const * thing, int x, int y) const 132 { 133 typename cache_type::const_iterator it = data_.find(thing); 134 return it != data_.end() && it->second.covers(x, y); 135 } 136 squareDistance(T const * thing,int x,int y)137 int squareDistance(T const * thing, int x, int y) const 138 { 139 typename cache_type::const_iterator it = data_.find(thing); 140 if (it == data_.end()) 141 return 1000000; 142 return it->second.squareDistance(x, y); 143 } 144 145 private: 146 friend class CoordCache; 147 checkDim(T const * thing,char const * hint)148 void checkDim(T const * thing, char const * hint) const 149 { 150 if (!hasDim(thing)) 151 lyxbreaker(thing, hint, data_.size()); 152 } 153 check(T const * thing,char const * hint)154 void check(T const * thing, char const * hint) const 155 { 156 if (!has(thing)) 157 lyxbreaker(thing, hint, data_.size()); 158 } 159 160 typedef std::map<T const *, Geometry> cache_type; 161 cache_type data_; 162 }; 163 164 /** 165 * A BufferView dependent cache that allows us to come from an inset in 166 * a document to a position point and dimension on the screen. 167 * All points cached in this cache are only valid between subsequent 168 * updates. (x,y) == (0,0) is the upper left screen corner, x increases 169 * to the right, y increases downwords. 170 * The dimension part is built in BufferView::updateMetrics() and the 171 * diverse Inset::metrics() calls. 172 * The individual points are added at drawing time in 173 * BufferView::draw(). The math inset position are cached in 174 * the diverse InsetMathXXX::draw() calls and the in-text inset position 175 * are cached in RowPainter::paintInset(). 176 * FIXME: For mathed, it would be nice if the insets did not saves their 177 * position themselves. That should be the duty of the containing math 178 * array. 179 */ 180 class CoordCache { 181 public: 182 void clear(); 183 184 /// A map from MathData to position on the screen 185 typedef CoordCacheBase<MathData> Arrays; arrays()186 Arrays & arrays() { return arrays_; } getArrays()187 Arrays const & getArrays() const { return arrays_; } 188 /// A map from insets to positions on the screen 189 typedef CoordCacheBase<Inset> Insets; insets()190 Insets & insets() { return insets_; } getInsets()191 Insets const & getInsets() const { return insets_; } 192 193 /// Dump the contents of the cache to lyxerr in debugging form 194 void dump() const; 195 private: 196 /// MathDatas 197 Arrays arrays_; 198 // All insets 199 Insets insets_; 200 }; 201 202 } // namespace lyx 203 204 #endif 205