#include "CtrlCore.h" NAMESPACE_UPP #define LLOG(x) // DLOG(x) void LocalLoop::Run() { ASSERT(master); ASSERT(IsMainThread()); master->AddChild(this); Ptr focus = GetFocusCtrl(); SetCapture(); SetFocus(); LLOG("LocalLoop::Run"); EventLoop(this); LLOG("LocalLoop Finished"); Remove(); if(focus) focus->SetFocus(); } void DrawDragRect(Ctrl& q, const Rect& rect1, const Rect& rect2, const Rect& clip, int n, Color color, uint64 pattern) { ViewDraw w(&q); DrawDragRect(w, rect1, rect2, clip, n, color, pattern); } void RectTracker::LeftUp(Point, dword) { EndLoop(); } void RectTracker::RightUp(Point, dword) { EndLoop(); } Image RectTracker::CursorImage(Point, dword) { if(animation) DrawRect(rect, rect); return cursorimage; } static uint64 RectTracker_normal = I64(0x55aa55aa55aa55aa); static uint64 RectTracker_dashed = I64(0xf0783c1e0f87c3e1); static uint64 RectTracker_solid = I64(0); RectTracker::RectTracker(Ctrl& master) { SetMaster(master); Clip(Rect(0, 0, 100000, 100000)); width = 1; minsize = Size(0, 0); maxsize = Size(100000, 100000); maxrect = Rect(-100000, -100000, 100000, 100000); keepratio = false; cursorimage = Image::Arrow(); color = SColorPaper; pattern = RectTracker_normal; animation = 0; rounder = NULL; } RectTracker::~RectTracker() {} RectTracker& RectTracker::Dashed() { pattern = RectTracker_dashed; return *this; } RectTracker& RectTracker::Solid() { pattern = RectTracker_solid; return *this; } static uint64 sGetAniPat(uint64 src, int pos) { uint64 out = 0; pos &= 7; for(int i = 8; --i >= 0;) { byte sr = (byte)(src >> (8 * ((7 - i - pos) & 7))); out = (out << 8) | (byte)((sr | (sr << 8)) >> pos); } return out; } void RectTracker::DrawRect(Rect r1, Rect r2) { if(ty < 0) { r1.left = r1.right - 1; r2.left = r2.right - 1; } if(tx < 0) { r1.top = r1.bottom - 1; r2.top = r2.bottom - 1; } Rect c = clip & GetMaster().GetSize(); if(animation) { int nanim = (GetTickCount() / animation) % 8; DrawDragRect(GetMaster(), Rect(0, 0, 0, 0), r2, c, width, color, sGetAniPat(pattern, nanim)); DrawDragRect(GetMaster(), r1, Rect(0, 0, 0, 0), c, width, color, sGetAniPat(pattern, panim)); panim = nanim; } else DrawDragRect(GetMaster(), r1, r2, c, width, color, pattern); } Rect RectTracker::Track(const Rect& r, int _tx, int _ty) { rect = r; tx = _tx; ty = _ty; org = rect; o = rect; op = GetMousePos(); GetMaster().Sync(); DrawRect(Rect(0, 0, 0, 0), rect); Run(); DrawRect(o, Rect(0, 0, 0, 0)); return rect; } int RectTracker::TrackHorzLine(int x0, int y0, int cx, int line) { return Track(RectC(x0, y0, cx, line + 1), -1, ALIGN_BOTTOM).bottom - 1; } int RectTracker::TrackVertLine(int x0, int y0, int cy, int line) { return Track(RectC(x0, y0, line + 1, cy), ALIGN_RIGHT, -1).right - 1; } void RectTracker::MouseMove(Point, dword) { Point p = GetMousePos(); rect = org; if(tx == ALIGN_CENTER && ty == ALIGN_CENTER) { int x = org.left - op.x + p.x; int y = org.top - op.y + p.y; if(x + org.Width() > maxrect.right) x = maxrect.right - org.Width(); if(x < maxrect.left) x = maxrect.left; if(y + org.Height() > maxrect.bottom) y = maxrect.bottom - org.Height(); if(y < maxrect.top) y = maxrect.top; rect = RectC(x, y, org.Width(), org.Height()); } else { if(tx == ALIGN_LEFT) { rect.left = max(org.left - op.x + p.x, maxrect.left); rect.left = minmax(rect.left, rect.right - maxsize.cx, rect.right - minsize.cx); } if(tx == ALIGN_RIGHT) { rect.right = min(org.right - op.x + p.x, maxrect.right); rect.right = minmax(rect.right, rect.left + minsize.cx, rect.left + maxsize.cx); } if(ty == ALIGN_TOP) { rect.top = max(org.top - op.y + p.y, maxrect.top); rect.top = minmax(rect.top, rect.bottom - maxsize.cy, rect.bottom - minsize.cy); } if(ty == ALIGN_BOTTOM) { rect.bottom = min(org.bottom - op.y + p.y, maxrect.bottom); rect.bottom = minmax(rect.bottom, rect.top + minsize.cy, rect.top + maxsize.cy); } if(tx == ALIGN_NULL) { rect.right = min(org.right - op.x + p.x, maxrect.right); if (rect.right < rect.left) { Swap(rect.right, rect.left); rect.InflateHorz(1); } } if(ty == ALIGN_NULL) { rect.bottom = min(org.bottom - op.y + p.y, maxrect.bottom); if (rect.bottom < rect.top) { Swap(rect.bottom, rect.top); rect.InflateVert(1); } } if(keepratio) { int cy = org.Width() ? rect.Width() * org.Height() / org.Width() : 0; int cx = org.Height() ? rect.Height() * org.Width() / org.Height() : 0; if(tx == ALIGN_BOTTOM && ty == ALIGN_RIGHT) { Size sz = rect.Size(); if(cx > sz.cx) rect.right = rect.left + cx; else rect.bottom = rect.top + cy; } else if(tx == ALIGN_RIGHT) rect.bottom = rect.top + cy; else if(ty == ALIGN_BOTTOM) rect.right = rect.left + cx; } } if(rect != o) { rect = Round(rect); if(rect != o) { DrawRect(o, rect); sync(rect); o = rect; } } } /* void RectTracker::MouseMove(Point, dword) { Point p = GetMousePos(); rect = org; if(tx == ALIGN_CENTER && ty == ALIGN_CENTER) { int x = org.left - op.x + p.x; int y = org.top - op.y + p.y; if(x + org.Width() > maxrect.right) x = maxrect.right - org.Width(); if(x < maxrect.left) x = maxrect.left; if(y + org.Height() > maxrect.bottom) y = maxrect.bottom - org.Height(); if(y < maxrect.top) y = maxrect.top; rect = RectC(x, y, org.Width(), org.Height()); } else { if(tx == ALIGN_LEFT) { rect.left = max(org.left - op.x + p.x, maxrect.left); rect.left = minmax(rect.left, rect.right - maxsize.cx, rect.right - minsize.cx); } if(tx == ALIGN_RIGHT) { rect.right = min(org.right - op.x + p.x, maxrect.right); rect.right = minmax(rect.right, rect.left + minsize.cx, rect.left + maxsize.cx); } if(ty == ALIGN_TOP) { rect.top = max(org.top - op.y + p.y, maxrect.top); rect.top = minmax(rect.top, rect.bottom - maxsize.cy, rect.bottom - minsize.cy); } if(ty == ALIGN_BOTTOM) { rect.bottom = min(org.bottom - op.y + p.y, maxrect.bottom); rect.bottom = minmax(rect.bottom, rect.top + minsize.cy, rect.top + maxsize.cy); } if(keepratio) { int cy = org.Width() ? rect.Width() * org.Height() / org.Width() : 0; int cx = org.Height() ? rect.Height() * org.Width() / org.Height() : 0; if(tx == ALIGN_BOTTOM && ty == ALIGN_RIGHT) { Size sz = rect.Size(); if(cx > sz.cx) rect.right = rect.left + cx; else rect.bottom = rect.top + cy; } else if(tx == ALIGN_RIGHT) rect.bottom = rect.top + cy; else if(ty == ALIGN_BOTTOM) rect.right = rect.left + cx; } } if(rect != o) { rect = Round(rect); if(rect != o) { DrawRect(o, rect); sync(rect); o = rect; } } } */ class PointLooper : public LocalLoop { const Vector& ani; int ani_ms; bool result; public: virtual void LeftUp(Point, dword); virtual Image CursorImage(Point p, dword keyflags); virtual bool Key(dword key, int); operator bool() const { return result; } PointLooper(Ctrl& ctrl, const Vector& ani, int ani_ms) : ani(ani), ani_ms(ani_ms) { SetMaster(ctrl); } }; void PointLooper::LeftUp(Point, dword) { result = true; EndLoop(); } Image PointLooper::CursorImage(Point p, dword keyflags) { return ani[int(GetTimeClick() / ani_ms % ani.GetCount())]; } bool PointLooper::Key(dword key, int) { if(key == K_ESCAPE) { result = false; EndLoop(); } return true; } bool PointLoop(Ctrl& ctrl, const Vector& ani, int ani_ms) { PointLooper p(ctrl, ani, ani_ms); p.Run(); return p; } bool PointLoop(Ctrl& ctrl, const Image& img) { Vector m; m.Add(img); return PointLoop(ctrl, m, 1); } END_UPP_NAMESPACE