1 #include "RasterBaseCtrl.h"
2 #include "RasterCtrl.h"
3
4 #define BackColor SColorFace()
5
6 ///////////////////////////////////////////////////////////////////////////////////////////////
7 // constructor
RasterBaseCtrl(RasterCtrl * t,bool hScroll,bool vScroll)8 RasterBaseCtrl::RasterBaseCtrl(RasterCtrl *t, bool hScroll, bool vScroll)
9 {
10 // connects to associated RasterCtrl
11 rasterCtrl = t;
12
13 // whether control has scrollbars
14 hasHScrollBar = hScroll;
15 hasVScrollBar = vScroll;
16
17 // adds scrollbar
18 if(hasHScrollBar)
19 {
20 AddFrame(hScrollBar.Horz());
21 hScrollBar <<= THISBACK(OnScroll);
22 }
23 if(hasVScrollBar)
24 {
25 AddFrame(vScrollBar.Vert());
26 vScrollBar <<= THISBACK(OnScroll);
27 }
28
29 // marks cache as invalid
30 imageCache.SetValid(false);
31
32 } // END constructor class RasterBaseCtrl
33
34 ///////////////////////////////////////////////////////////////////////////////////////////////
35 // destructor
~RasterBaseCtrl()36 RasterBaseCtrl::~RasterBaseCtrl()
37 {
38 } // END destructor class RasterBaseCtrl
39
40 ///////////////////////////////////////////////////////////////////////////////////////////////
41 // middle mouse button pan handlers
MiddleDown(Point p,dword keyflags)42 void RasterBaseCtrl::MiddleDown(Point p, dword keyflags)
43 {
44 panPoint = p;
45 panHScroll = hScrollBar.Get();
46 panVScroll = vScrollBar.Get();
47
48 } // END RasterBaseCtrl::MiddleDown()
49
MouseMove(Point p,dword keyflags)50 void RasterBaseCtrl::MouseMove(Point p, dword keyflags)
51 {
52 // reacts only to moves with middle button pressed
53 if(!(keyflags & K_MOUSEMIDDLE))
54 return;
55
56 // gets distance between current and pan point
57 int dx = panPoint.x - p.x + panHScroll;
58 int dy = panPoint.y - p.y + panVScroll;
59
60 // gets max scrolling values
61 int hMax = hScrollBar.GetTotal();
62 int vMax = vScrollBar.GetTotal();
63
64 // sets new pan position
65 if(dx < 0) dx = 0;
66 if(dx > hMax) dx = hMax;
67 if(dy < 0) dy = 0;
68 if(dy > vMax) dy = vMax;
69 hScrollBar.Set(dx);
70 vScrollBar.Set(dy);
71
72 Refresh();
73
74 } // END RasterBaseCtrl::MouseMove()
75
CursorImage(Point p,dword keyflags)76 Image RasterBaseCtrl::CursorImage(Point p, dword keyflags)
77 {
78 if(keyflags & K_MOUSEMIDDLE)
79 return Image::Hand();
80 else
81 return Image::Arrow();
82
83 }
84
85 ///////////////////////////////////////////////////////////////////////////////////////////////
86 // mouse wheel handler
MouseWheel(Point p,int zdelta,dword keyflags)87 void RasterBaseCtrl::MouseWheel(Point p, int zdelta, dword keyflags)
88 {
89 int max = vScrollBar.GetTotal();
90 int step = max / 100;
91 if(step <= 0)
92 step = 1;
93 int newPos = vScrollBar.Get();
94 if(zdelta < 0)
95 newPos += step;
96 else
97 newPos -= step;
98 if(newPos > max)
99 newPos = max;
100 if(newPos < 0)
101 newPos = 0;
102 vScrollBar.Set(newPos);
103
104 Refresh();
105
106 } // END RasterBaseCtrl::MouseWheel()
107
108 ///////////////////////////////////////////////////////////////////////////////////////////////
109 // repaint images on image cache
PaintCache()110 void RasterBaseCtrl::PaintCache()
111 {
112 Array<Rect> rects;
113
114 // backups old imageCache positions inside the full tiff image
115 int oldCacheLeft = cacheLeft;
116 int oldCacheTop = cacheTop;
117
118 // calculate new imageCache position inside the full tiff image
119 if(hScrollBar.IsVisible())
120 cacheLeft = hScrollBar.Get();
121 else
122 cacheLeft = 0;
123 if(vScrollBar.IsVisible())
124 cacheTop = vScrollBar.Get();
125 else
126 cacheTop = 0;
127
128 // if cache is not valid OR scrolled out a full window, gets full cache area
129 if(
130 !imageCache.IsValid() ||
131 abs(oldCacheLeft-cacheLeft) >= imageCache.GetWidth() ||
132 abs(oldCacheTop-cacheTop) >= imageCache.GetHeight()
133 )
134 {
135 rects.Add(Rect(imageCache.GetSize()));
136 imageCache.SetValid(true);
137 oldCacheLeft = oldCacheTop = 0;
138 }
139 else
140 {
141 // shifts imageCache
142 imageCache.Scroll(Size(oldCacheLeft-cacheLeft, oldCacheTop-cacheTop));
143
144 // calculates the (1 or 2) rects that must be repainted
145 int startLine = 0;
146 int endLine = imageCache.GetHeight();
147
148 // top rectangle, if any
149 if(cacheTop < oldCacheTop)
150 {
151 rects.Add(Rect(0, 0, imageCache.GetWidth(), oldCacheTop-cacheTop));
152 startLine += oldCacheTop-cacheTop;
153 }
154 // bottom rectangle, if any
155 else if(cacheTop > oldCacheTop)
156 {
157 rects.Add(Rect(0, imageCache.GetHeight()-(cacheTop-oldCacheTop), imageCache.GetWidth(), imageCache.GetHeight()));
158 endLine += oldCacheTop-cacheTop;
159 }
160 // left rectangle, if any
161 if(cacheLeft < oldCacheLeft)
162 rects.Add(Rect(0, startLine, oldCacheLeft - cacheLeft, endLine));
163 else if(cacheLeft > oldCacheLeft)
164 rects.Add(Rect(imageCache.GetWidth()-(cacheLeft-oldCacheLeft), startLine, imageCache.GetWidth(), endLine));
165 }
166
167 // gets the image pages
168 Array<MemoryRaster>&pages = rasterCtrl->GetPages();
169
170 // scans the tiff pages to see if some of them fits in
171 // rectangles that must be repainted
172 int currentTop = 0;
173 for(int i = 0 ; i < pages.GetCount() ; i++)
174 {
175 // translates current top of page in view coordinates
176 int viewCurrentTop = iscale(currentTop, imageScale, 1000);
177
178 // gets current page
179 MemoryRaster &page = pages[i];
180
181 // gets current page size and translates it in view coordinates
182 Rect viewPageRect(
183 -cacheLeft,
184 -cacheTop + viewCurrentTop,
185 iscale(page.GetSize().cx, imageScale, 1000) - cacheLeft,
186 iscale(page.GetSize().cy, imageScale, 1000) - cacheTop + viewCurrentTop
187 );
188
189 // now scans the rectangles that must be repainted
190 // and checks if current page has some area on it
191 for(int iRect = 0; iRect < rects.GetCount(); iRect++)
192 {
193 // gets current rectangle
194 Rect rect = rects[iRect];
195
196 // intersects with page rect
197 rect.Intersect(viewPageRect);
198
199 // if intersection is not empty, do repaint the stuff
200 if(!rect.IsEmpty())
201 {
202 // gets back the tiff rectangle
203 Rect tiffRect(
204 iscale(rect.left + cacheLeft, 1000, imageScale),
205 iscale(rect.top + cacheTop, 1000, imageScale) - currentTop,
206 iscale(rect.right + cacheLeft, 1000, imageScale),
207 iscale(rect.bottom + cacheTop, 1000, imageScale) -currentTop
208 );
209
210 // rescales the image area
211 ImageEncoder t;
212 Rescale(t, rect.GetSize(), page, tiffRect);
213
214 // and copies insiede the cache area
215 Image img = Image(t);
216 ASSERT(rect.top >= 0 && rect.top + img.GetHeight() <= imageCache.GetHeight());
217 ASSERT(rect.left >= 0 && rect.left + img.GetWidth() <= imageCache.GetWidth());
218 imageCache.Copy(Point(rect.left, rect.top), Rect(0, 0, img.GetWidth(), img.GetHeight()), img);
219 }
220 }
221 currentTop += page.GetHeight() + iscale(10, 1000, imageScale);
222 }
223
224
225 } // END RasterBaseCtrl::PaintCache()
226
227 ///////////////////////////////////////////////////////////////////////////////////////////////
228 // paint routine
Paint(Draw & d)229 void RasterBaseCtrl::Paint(Draw &d)
230 {
231 // clears background
232 d.DrawRect(GetSize(), SColorFace());
233
234 // if no image opened, does nothing
235 if(!rasterCtrl->IsOpened())
236 return;
237
238 // paints image inside cache, if needed
239 PaintCache();
240
241 // paints image cache inside control
242 if(imageCache.GetWidth() >= GetSize().cx)
243 imageCache.Paint(d, Point(0, 0));
244 else
245 imageCache.Paint(d, Point((GetSize().cx - imageCache.GetWidth()) / 2, 0));
246
247 } // END RasterBaseCtrl::Paint()
248
249 ///////////////////////////////////////////////////////////////////////////////////////////////
250 // scrollbar handler
OnScroll(void)251 void RasterBaseCtrl::OnScroll(void)
252 {
253 Refresh();
254
255 } // END RasterBaseCtrl::OnScroll()
256
257 ///////////////////////////////////////////////////////////////////////////////////////////////
258 // handles changes in images or ctrl
Layout(void)259 void RasterBaseCtrl::Layout(void)
260 {
261 // this to avoid recursion
262 static bool inside = false;
263
264 // if no image opened, hides scrollbar and return
265 if(!rasterCtrl->IsOpened())
266 {
267 hScrollBar.Hide();
268 vScrollBar.Hide();
269 return;
270 }
271
272 // if already doing layout, just return
273 if(inside)
274 return;
275
276 // marks inside layout
277 inside = true;
278
279 // stores scroll positions, in order to go on right position
280 // after zoom operations
281 int hScrollPos = hScrollBar.Get();
282 int hScrollMax = hScrollBar.GetTotal();
283 int vScrollPos = vScrollBar.Get();
284 int vScrollMax = vScrollBar.GetTotal();
285
286 // gets the image pages
287 Array<MemoryRaster>&pages = rasterCtrl->GetPages();
288
289 // calculates max width and height
290 // and total Tiff height, for all pages, with no gaps by now
291 int rasterWidth = 0;
292 int rasterHeight = 0;
293 int maxHeight = 0;
294 int pageCount = pages.GetCount();
295 for(int i = 0 ; i < pageCount ; i++)
296 {
297 // gets page size
298 Size sz = pages[i].GetSize();
299
300 // updates width, maximum height and total height
301 if(sz.cx > rasterWidth)
302 rasterWidth = sz.cx;
303 if(sz.cy > maxHeight)
304 maxHeight = sz.cy;
305 rasterHeight += sz.cy;
306 }
307
308 // calculates image scale factor
309 imageScale = CalcScale(imageScale, rasterWidth, maxHeight);
310
311 // stops layouting if imagescale is null
312 if(!imageScale)
313 {
314 inside = false;
315 return;
316 }
317
318 // now calculate gaps to be exactly 10 pixels in every zoom factor
319 int gapSize = iscale(10, 1000, imageScale);
320
321 // adds total gaps sizes to total height
322 rasterHeight += (pageCount -1) * gapSize;
323
324 // and finally, sets up scrollbars and shows them
325 // and calculate cache sizes
326 int scaledRasterHeight = iscale(rasterHeight, imageScale, 1000);
327 int cacheHeight;
328 vScrollBar.SetPage(GetSize().cy);
329 vScrollBar.SetTotal(scaledRasterHeight);
330 if(vScrollMax)
331 vScrollBar.Set(iscale(vScrollPos, scaledRasterHeight, vScrollMax));
332 else
333 vScrollBar.Set(0);
334 if(GetSize().cy <= scaledRasterHeight)
335 {
336 if(hasVScrollBar)
337 vScrollBar.Show();
338 cacheHeight = GetSize().cy;
339 }
340 else
341 {
342 vScrollBar.Hide();
343 cacheHeight = scaledRasterHeight;
344 }
345 int scaledRasterWidth = iscale(rasterWidth, imageScale, 1000);
346 int cacheWidth;
347 hScrollBar.SetPage(GetSize().cx);
348 hScrollBar.SetTotal(scaledRasterWidth);
349 if(hScrollMax)
350 hScrollBar.Set(iscale(hScrollPos, scaledRasterWidth, hScrollMax));
351 else
352 hScrollBar.Set(0);
353 if(GetSize().cx <= scaledRasterWidth)
354 {
355 if(hasHScrollBar)
356 hScrollBar.Show();
357 cacheWidth = GetSize().cx;
358 }
359 else
360 {
361 hScrollBar.Hide();
362 cacheWidth = scaledRasterWidth;
363 }
364
365 // creates cache image, empty by now
366 imageCache.Init(Size(cacheWidth, cacheHeight));
367
368 // updates image
369 Refresh();
370
371 // mark layout terminated
372 inside = false;
373
374 } // END RasterBaseCtrl::Layout()
375