1 namespace Upp {
2 
3 class PlotterDragDrop;
4 
5 class PlotterCtrl : public DragDropCtrl, public CtrlFrame
6 {
7 public:
8 	class ViewPlot : public Plotter
9 	{
10 	public:
11 		ViewPlot(PlotterCtrl& ctrl, int extra_gap = 0);
12 		ViewPlot(PlotterCtrl& ctrl, Pointf scale, Pointf delta, int extra_gap = 0);
13 		ViewPlot(PlotterCtrl& ctrl, const Matrixf& preform, int extra_gap = 0);
14 
15 	private:
16 		ViewDraw viewdraw;
17 	};
18 	friend class ViewPlot;
19 
20 	typedef PlotterCtrl CLASSNAME;
21 	PlotterCtrl();
22 	virtual ~PlotterCtrl();
23 
24 	virtual void            FrameAdd(Ctrl& ctrl);
25 	virtual void            FrameRemove();
26 	virtual void            FrameLayout(Rect& rc);
27 	virtual void            FrameAddSize(Size& sz);
28 
29 	virtual void            Layout();
30 	virtual void            Paint(Draw& draw);
31 //	void                    AsyncPaint();
IsPainting()32 	bool                    IsPainting() const               { return is_painting; }
33 
LostFocus()34 	virtual void            LostFocus()                      { ResetPush(); }
35 
36 	ImageDraw&              BeginBufferPaint();
37 	virtual void            EndBufferPaint();
38 
39 	virtual void            Plot(Plotter& plotter) = 0;
AbortPlot()40 	virtual void            AbortPlot()                      {}
41 
42 	void                    BufferPaint(bool bp = true)      { buffer_paint = bp; RefreshBuffer(); }
IsBufferPaint()43 	bool                    IsBufferPaint() const            { return buffer_paint; }
44 	void                    RefreshBuffer();
45 	void                    RefreshBuffer(const Rect& rc);
46 
47 	void                    BufferPan(bool bp = true)        { buffer_pan = bp; }
IsBufferPan()48 	bool                    IsBufferPan() const              { return buffer_pan; }
49 	void                    PanOffset(Point o);
ClearPanOffset()50 	void                    ClearPanOffset()                 { PanOffset(Point(0, 0)); }
GetPanOffset()51 	Point                   GetPanOffset() const             { return pan_offset; }
52 
ShowScroll(bool ssc)53 	void                    ShowScroll(bool ssc)             { show_scroll = ssc; Layout(); }
IsScrollShown()54 	bool                    IsScrollShown() const            { return show_scroll; }
55 
MaxScale(double d)56 	void                    MaxScale(double d)               { max_scale.cx = max_scale.cy = d; }
MaxScale(Sizef ms)57 	void                    MaxScale(Sizef ms)               { max_scale = ms; }
GetMaxScale()58 	Sizef                   GetMaxScale() const              { return max_scale; }
59 
Gap(Rect g)60 	void                    Gap(Rect g)                      { gap = g; Layout(); }
Gap(int i)61 	void                    Gap(int i)                       { gap = Rect(i, i, i, i); Layout(); }
GetGap()62 	Rect                    GetGap() const                   { return gap; }
63 
64 	virtual Image           CursorImage(Point pt, dword keyflags);
65 	virtual bool            Push(Point pt, dword keyflags);
66 	virtual void            Drag(Point start, Point prev, Point curr, dword keyflags);
67 	virtual void            Drop(Point start, Point end, dword keyflags);
68 	virtual void            Click(Point pt, dword keyflags);
69 	virtual void            Cancel();
70 	virtual bool            Key(dword key, int repcnt);
71 	virtual void            MouseWheel(Point p, int zdelta, dword keyflags);
72 	virtual void            MouseMove(Point pt, dword keyflags);
73 
RefreshPos()74 	virtual void            RefreshPos()                     {}
RefreshDragDrop()75 	virtual void            RefreshDragDrop()                { RefreshBuffer(); }
76 
FromClient(Point pt)77 	Pointf                  FromClient(Point pt) const       { return (Pointf(pt) - delta) / scale; }
FromClientNull(Point pt)78 	Pointf                  FromClientNull(Point pt) const   { return IsNull(pt) ? Pointf(Null) : FromClient(pt); }
79 	Rectf                   FromClient(const Rect& rc) const;
80 
FromPushClient(Point pt)81 	Pointf                  FromPushClient(Point pt) const   { return (Pointf(pt) - push_delta) / push_scale; }
FromPushClientNull(Point pt)82 	Pointf                  FromPushClientNull(Point pt) const { return IsNull(pt) ? Pointf(Null) : FromPushClient(pt); }
83 
ToClient(Pointf pt)84 	Point                   ToClient(Pointf pt) const        { return PointfToPoint(Sizef(pt) * scale + delta); }
ToClientNull(Pointf pt)85 	Point                   ToClientNull(Pointf pt) const    { return IsNull(pt) ? Point(Null) : PointfToPoint(Sizef(pt) * scale + delta); }
86 	Rect                    ToClient(const Rectf& rc) const;
87 
ToPushClient(Pointf pt)88 	Point                   ToPushClient(Pointf pt) const    { return PointfToPoint(Sizef(pt) * push_scale + push_delta); }
ToPushClientNull(Pointf pt)89 	Point                   ToPushClientNull(Pointf pt) const { return IsNull(pt) ? Point(Null) : ToPushClient(pt); }
90 
91 	void                    SyncPush();
92 
93 	void                    SetExtent(const Rectf& extent);
GetExtent()94 	const Rectf&            GetExtent() const                { return extent; }
95 
GetViewRect()96 	Rectf                   GetViewRect() const              { return FromClient(Rect(GetSize()).Deflated(gap)); }
97 
98 	void                    ScrollInto(Rectf rc);
99 	void                    ScrollInto(Pointf pt);
100 
101 	void                    SetAspectRatio(double aspect);
NoAspectRatio()102 	void                    NoAspectRatio()                  { SetAspectRatio(0); }
GetAspectRatio()103 	double                  GetAspectRatio() const           { return aspect; }
IsAspectRatio()104 	bool                    IsAspectRatio() const            { return aspect != 0; }
105 
106 	void                    SetAspectLock(bool a = true);
NoAspectLock()107 	void                    NoAspectLock()                   { SetAspectLock(false); }
IsAspectLock()108 	bool                    IsAspectLock() const             { return aspect_lock; }
IsAspectLocked()109 	bool                    IsAspectLocked() const           { return IsAspectRatio() || IsAspectLock(); }
110 
111 	void                    EnableLock(bool e = true);
DisableLock()112 	void                    DisableLock()                    { EnableLock(false); }
IsLockEnabled()113 	bool                    IsLockEnabled() const            { return enable_lock; }\
114 
115 	void                    SetScale(Sizef scale);
116 	void                    SetDelta(Pointf delta);
117 	void                    SetZoom(Sizef scale, Pointf delta);
118 	void                    SetZoom(double scale, Pointf delta);
119 	void                    SetZoomSc(Sizef scale);
SetZoomSc(double sx,double sy)120 	void                    SetZoomSc(double sx, double sy)  { SetZoomSc(Pointf(sx, sy)); }
121 	void                    SetZoomSc(double z);
122 
GetScale()123 	Sizef                   GetScale() const                 { return scale; }
GetPushScale()124 	Sizef                   GetPushScale() const             { return push_scale; }
125 	double                  GetAvgScale() const;
GetDelta()126 	Pointf                  GetDelta() const                 { return delta; }
GetPushDelta()127 	Pointf                  GetPushDelta() const             { return push_delta; }
128 
IsReversedX()129 	bool                    IsReversedX() const              { return rev_x; }
IsReversedY()130 	bool                    IsReversedY() const              { return rev_y; }
131 
IsReversing()132 	bool                    IsReversing() const              { return scale.cx * scale.cy < 0; }
133 
134 	Sizef                   GetPhysicalZoom() const;
135 
136 	void                    AdjustPos(Pointf& delta, Point scpos) const;
137 	Sizef                   AdjustScale(Sizef sc) const;
138 
139 	Pointf                  GetSc() const;
140 	void                    SetSc(Pointf center);
141 
142 	void                    ZoomInX();
143 	void                    ZoomOutX();
ZoomFullX()144 	void                    ZoomFullX()                      { if(extent.left < extent.right) ZoomX(extent.left, extent.right); }
145 	void                    ZoomX(double min, double max, bool add_gap = true);
146 	void                    ZoomInY();
147 	void                    ZoomOutY();
ZoomFullY()148 	void                    ZoomFullY()                      { if(extent.top < extent.bottom) ZoomY(extent.right, extent.bottom); }
149 	void                    ZoomY(double min, double max, bool add_gap = true);
ZoomIn()150 	void                    ZoomIn()                         { ZoomInX(); ZoomInY(); }
ZoomOut()151 	void                    ZoomOut()                        { ZoomOutX(); ZoomOutY(); }
ZoomFull()152 	void                    ZoomFull()                       { Zoom(extent, false); }
153 	void                    Zoom(const Rectf& rc, bool keep_ratio = true, bool add_gap = true);
154 
155 	void                    UserZoomInX();
156 	void                    UserZoomOutX();
157 	void                    UserZoomFullX();
158 	void                    UserZoomX(double min, double max);
159 	void                    UserZoomInY();
160 	void                    UserZoomOutY();
161 	void                    UserZoomFullY();
162 	void                    UserZoomY(double min, double max);
163 	void                    UserZoomIn();
164 	void                    UserZoomOut();
165 	virtual void            UserZoomFull();
166 	void                    UserAspectLock();
167 	void                    UserZoom(const Rectf& rc, bool keep_ratio = true);
168 
169 	void                    PickDragDrop(One<PlotterDragDrop> dd);
170 	One<PlotterDragDrop>    ClearDragDrop();
GetDragDrop()171 	PlotterDragDrop        *GetDragDrop()                    { return ~drag_drop; }
GetDragDrop()172 	const PlotterDragDrop  *GetDragDrop() const              { return ~drag_drop; }
173 
174 	void                    UpdateMousePos();
GetMousePos()175 	Pointf                  GetMousePos() const              { return mouse_pos; }
176 
DoSetFocus()177 	void                    DoSetFocus()                     { SetWantFocus(); }
178 
ResetPush()179 	void                    ResetPush()                      { reset_push = true; }
180 
181 	TOOL(View)
182 		TOOL(ViewZoomInX)
183 		TOOL(ViewZoomOutX)
184 		TOOL(ViewZoomFullX)
185 		TOOL(ViewZoomInY)
186 		TOOL(ViewZoomOutY)
187 		TOOL(ViewZoomFullY)
188 		TOOL(ViewZoomIn)
189 		TOOL(ViewZoomOut)
190 		TOOL(ViewZoomFull)
191 		TOOL(ViewAspectLock)
192 		TOOL(ViewPan)
193 
194 	void                    PostRefresh();
195 
196 public:
197 	Callback                WhenRescan;
198 	Callback                WhenZoom;
199 	Callback                WhenUserZoom;
200 	Callback                WhenMousePos;
201 
202 protected:
203 	void                    AdjustPos(Point scpos, int xymask); // 1 = x, 2 = y
204 
205 protected:
206 	bool                    rev_x, rev_y, aspect_lock, enable_lock;
207 	Rect                    gap;
208 	Alignment               halign, valign;
209 	Color                   background;
210 	Sizef                   scale;
211 	Pointf                  delta;
212 	Sizef                   push_scale;
213 	Pointf                  push_delta;
214 	Sizef                   max_scale;
215 	Pointf                  mouse_pos;
216 	Rectf                   extent;
217 	double                  aspect;
218 
219 	Image                   paint_buffer;
220 	One<ImageDraw>          paint_draw;
221 	bool                    is_painting;
222 	bool                    abort_repaint;
223 	bool                    buffer_paint;
224 	bool                    buffer_pan;
225 	Point                   pan_offset;
226 
227 private:
228 	void                    OnHScroll();
229 	void                    OnVScroll();
Refresh0()230 	void                    Refresh0()                       { RefreshBuffer(); }
231 
232 private:
233 	TimeCallback            tcb_refresh;
234 	Size                    old_size;
235 	One<PlotterDragDrop>    drag_drop;
236 	Pointf                  drag_start;
237 	HScrollBar              hscroll;
238 	VScrollBar              vscroll;
239 	Button                  horz_in, horz_out, horz_full;
240 	Button                  vert_in, vert_out, vert_full;
241 	Button                  full;
242 	bool                    reset_push;
243 	bool                    show_scroll;
244 	bool                    lock_drag_drop;
245 	bool                    lock_short_drag_drop;
246 	int                     drag_mode;
247 	enum { DRAG_NONE, DRAG_CUSTOM, DRAG_PAN, DRAG_ZOOM_IN, DRAG_ZOOM_OUT };
248 };
249 
250 template <class T>
251 inline const T *GetDragDrop(const PlotterCtrl *ctrl, T * = 0)
252 {
253 	if(const T *p = dynamic_cast<const T *>(ctrl->GetShortDragDrop()))
254 		return p;
255 	return dynamic_cast<const T *>(ctrl->GetDragDrop());
256 }
257 
258 template <class T>
259 inline T *GetDragDrop(PlotterCtrl *ctrl, T * = 0)
260 {
261 	return dynamic_cast<T *>(ctrl->GetDragDrop());
262 }
263 
264 template <class T>
265 inline bool IsDragDrop(const PlotterCtrl *ctrl, T * = 0)
266 {
267 	return dynamic_cast<const T *>(ctrl->GetDragDrop());;
268 }
269 // make member template as soon as possible
270 
271 class PlotterDragDrop
272 {
273 public:
~PlotterDragDrop()274 	virtual ~PlotterDragDrop() {}
275 
276 	virtual PlotterCtrl&    GetOwner() = 0;
277 
Plot(Plotter & plotter)278 	virtual void            Plot(Plotter& plotter)                                    {}
Push(Pointf pt,dword keyflags)279 	virtual bool            Push(Pointf pt, dword keyflags)                           { return true; }
Cursor(Pointf pt,dword keyflags,bool dragging)280 	virtual Image           Cursor(Pointf pt, dword keyflags, bool dragging) const    { return Image::Arrow(); }
281 	virtual void            Drag(Pointf pt, Pointf prev, Pointf curr, dword keyflags);
282 	virtual void            DragRect(const Rectf& prev, const Rectf& curr, dword keyflags);
283 	virtual void            Drop(Pointf pt, Pointf end, dword keyflags);
DropRect(const Rectf & rc,dword keyflags)284 	virtual void            DropRect(const Rectf& rc, dword keyflags)                    {}
Click(Pointf pt,dword keyflags)285 	virtual void            Click(Pointf pt, dword keyflags)                          {}
Key(dword key)286 	virtual bool            Key(dword key)                                            { return false; }
Cancel()287 	virtual void            Cancel()                                                  {}
288 };
289 
290 class EmptyDragDrop : public PlotterDragDrop
291 {
292 public:
EmptyDragDrop(PlotterCtrl & owner)293 	EmptyDragDrop(PlotterCtrl& owner) : owner(owner) {}
294 
GetOwner()295 	virtual PlotterCtrl& GetOwner()                      { return owner; }
296 
Push(Pointf pt,dword keyflags)297 	virtual bool         Push(Pointf pt, dword keyflags) { return false; }
298 
299 private:
300 	PlotterCtrl&         owner;
301 };
302 
303 class ZoomInDragDrop : public PlotterDragDrop
304 {
305 public:
ZoomInDragDrop(PlotterCtrl & owner)306 	ZoomInDragDrop(PlotterCtrl& owner) : owner(owner) {}
307 
GetOwner()308 	virtual PlotterCtrl&    GetOwner() { return owner; }
309 
310 	virtual Image           Cursor(Pointf pt, dword keyflags, bool dragging) const;
311 	virtual void            DropRect(const Rectf& rc, dword keyflags);
312 	virtual void            Click(Pointf pt, dword keyflags);
313 
314 private:
315 	PlotterCtrl&            owner;
316 };
317 
318 class ZoomOutDragDrop : public PlotterDragDrop
319 {
320 public:
ZoomOutDragDrop(PlotterCtrl & owner)321 	ZoomOutDragDrop(PlotterCtrl& owner) : owner(owner) {}
322 
GetOwner()323 	virtual PlotterCtrl&    GetOwner() { return owner; }
324 
325 	virtual Image           Cursor(Pointf pt, dword keyflags, bool dragging) const;
326 	virtual bool            Push(Pointf pt, dword keyflags);
327 	virtual void            DropRect(const Rectf& rc, dword keyflags);
328 	virtual void            Click(Pointf pt, dword keyflags);
329 
330 private:
331 	PlotterCtrl&            owner;
332 };
333 
334 class PanDragDrop : public PlotterDragDrop
335 {
336 public:
PanDragDrop(PlotterCtrl & owner)337 	PanDragDrop(PlotterCtrl& owner) : owner(owner) {}
338 
GetOwner()339 	virtual PlotterCtrl&    GetOwner() { return owner; }
340 
341 	virtual Image           Cursor(Pointf pt, dword keyflags, bool dragging) const;
342 	virtual bool            Push(Pointf pt, dword keyflags);
343 	virtual void            Drag(Pointf start, Pointf prev, Pointf curr, dword keyflags);
344 	virtual void            Drop(Pointf start, Pointf end, dword keyflags);
345 	virtual void            Cancel();
346 
347 private:
348 	PlotterCtrl&            owner;
349 };
350 
351 }
352