diff --git a/bazaar/CtrlFinder/CtrlFinder.cpp b/bazaar/CtrlFinder/CtrlFinder.cpp index 64e298cb4..8cd77a0fe 100644 --- a/bazaar/CtrlFinder/CtrlFinder.cpp +++ b/bazaar/CtrlFinder/CtrlFinder.cpp @@ -1,7 +1,7 @@ #include "CtrlFinder.h" //this one filters -void CtrlFinder::StdCtrlFilter(Ctrl*& q, Point& pt, int& f) +void CtrlFinder::StdCtrlFilter(Ctrl*& q, int& f) { if((f & VIEW) && q->InView()) { @@ -25,7 +25,7 @@ Ctrl* CtrlFinder::ChildAtPoint(Ctrl& par, Point& pt, int& f, const CtrlFilterTyp { GuiLock __; Ctrl *q; - Point p = pt; + Point p(pt); Rect view = par.GetView(); if(f & VIEW) @@ -38,12 +38,11 @@ Ctrl* CtrlFinder::ChildAtPoint(Ctrl& par, Point& pt, int& f, const CtrlFilterTyp if(r.Contains(vp)) { pt = vp - r.TopLeft(); Ctrl* w(q); - filt(w, pt, f); + filt(w, f); if(w) return w; } } } - return NULL; } if(f & FRAME) @@ -54,7 +53,7 @@ Ctrl* CtrlFinder::ChildAtPoint(Ctrl& par, Point& pt, int& f, const CtrlFilterTyp if(r.Contains(p)) { pt = p - r.TopLeft(); Ctrl* w(q); - filt(w, pt, f); + filt(w, f); if(w) return w; } } @@ -74,6 +73,116 @@ Ctrl* CtrlFinder::GetCtrl(Ctrl& c, Point& p, int& f, const CtrlFilterType& filt) return q; } +Ctrl* CtrlFinder::ChildInRect(Ctrl& par, Rect& rect, int& f, const CtrlFilterType& filt) +{ + GuiLock __; + Ctrl *q; + Rect rc(rect); + Rect view = par.GetView(); + + if(f & VIEW) + if(view.Contains(rc)) { + Rect vrc = rc - view.TopLeft(); + for(q = par.GetLastChild(); q; q = q->GetPrev()) { + if((f & VIEW) && q->InView()) + { + Rect r = q->GetRect(); + if(r.Contains(vrc)) { + rect = vrc - r.TopLeft(); + Ctrl* w(q); + filt(w, f); + if(w) return w; + } + } + } + } + + if(f & FRAME) + for(q = par.GetLastChild(); q; q = q->GetPrev()) { + if((f & FRAME) && q->InFrame()) + { + Rect r = q->GetRect(); + if(r.Contains(rc)) { + rect = rc - r.TopLeft(); + Ctrl* w(q); + filt(w, f); + if(w) return w; + } + } + } + return NULL; +} + +Ctrl* CtrlFinder::GetCtrl(Ctrl& c, Rect& rect, int& f, const CtrlFilterType& filt) +{ + Ctrl* q = ChildInRect(c, rect, f, filt); + if(q && (f & DEEP)) + { + Rect rc(rect); + Ctrl* qc = GetCtrl(*q, rc, f, filt); + if(qc) { rect = rc; return qc; } + } + return q; +} + +Vector CtrlFinder::ChildrenInRect(Ctrl& par, Rect& rect, int& f, const CtrlFilterType& filt) +{ + GuiLock __; + Vector vc; + Ctrl *q; + Rect rc(rect); + Rect view = par.GetView(); + + if(f & VIEW) + if(view.Contains(rc)) { + Rect vrc = rc - view.TopLeft(); + for(q = par.GetLastChild(); q; q = q->GetPrev()) { + if((f & VIEW) && q->InView()) + { + Rect r = q->GetRect(); + if(vrc.Contains(r)) { + Ctrl* w(q); + filt(w, f); + if(w) vc.Add(w); + } + } + } + } + + if(f & FRAME) + for(q = par.GetLastChild(); q; q = q->GetPrev()) { + if((f & FRAME) && q->InFrame()) + { + Rect r = q->GetRect(); + if(rc.Contains(r)) { + Ctrl* w(q); + filt(w, f); + if(w) vc.Add(w); + } + } + } + return vc; +} + +Vector CtrlFinder::GetCtrls(Ctrl& c, Rect& rect, int& f, const CtrlFilterType& filt) +{ + Vector vq = ChildrenInRect(c, rect, f, filt); + if(vq.IsEmpty() && (f & DEEP)) //difference between child and children, we stop if we found some in rect + { + //find a child, that has rect fully within, so we can try in there + //if no recursable child is found, we can return the empty vector + Rect rc(rect); + + Ctrl* q = ChildInRect(c, rc, f, filt); + if(q) + { + vq = GetCtrls(*q, rc, f, filt); + if(!vq.IsEmpty()) { rect = rc; } + } + } + return vq; +} + bool CtrlFinder::IsParentR(const Ctrl* p, const Ctrl* c) { while(c && p) { @@ -83,6 +192,56 @@ bool CtrlFinder::IsParentR(const Ctrl* p, const Ctrl* c) return false; } +//Offset calculation: +// A Rect is always related to it housing/encapsulating/parent context. + +//adds the view offset of a ctrl's parent context, if the ctrl happens to sit in its parent's view +//effectively, it's the frame to view coord. offset of the parent context of c +void CtrlFinder::AddParentViewOffset(const Ctrl& c, Point& p) +{ + if(c.InView()) + p += c.GetParent()->GetView().TopLeft(); +} + +//adds the offset of a source context to a (far) parent context q, all frame coordinates +void CtrlFinder::AddContextOffset(const Ctrl& c, const Ctrl& q, Point& p) +{ + if(&c == &q) return; + + p += c.GetRect().TopLeft(); + AddParentViewOffset(c, p); + AddContextOffset(*c.GetParent(), q, p); //recurse +} + +Point CtrlFinder::GetContextOffset(const Ctrl& c, const Ctrl& q) +{ + Point p; p.Clear(); + AddContextOffset(c, q, p); + return p; +} + +Point CtrlFinder::GetOffset(const Ctrl& ctxuser, const Ctrl& finalctx) +{ + ASSERT(&ctxuser != &finalctx); //a user of a context cant be the context itself + Point p; p.Clear(); + AddParentViewOffset(ctxuser, p); + AddContextOffset(*ctxuser.GetParent(), finalctx, p); + return p; +} + +Rect CtrlFinder::SurroundingRect(const Vector& ctrls) +{ + Rect r; r.Clear(); + + for(int i = 0; i < ctrls.GetCount(); i++) + { + Rect rc = ctrls[i]->GetRect(); + if(r.IsEmpty()) r = rc; + else r.Union(rc); + } + return r; +} + void CtrlFinder::Updated() { if(!pctrl) return; @@ -99,15 +258,49 @@ void CtrlFinder::UpdatedSource() pctrl->GetParent()->AddChild(this, pctrl); } +void CtrlFinder::SetCtrl(Ctrl* c) +{ + if(pctrl && c) { ASSERT(IsParentR(pctrl, c)); } + if(c) + { + ctrls.SetCount(1); + ctrls.Top() = c; + } + else ctrls.Clear(); + Update(); +} + void CtrlFinder::LeftDown(Point p, dword keyflags) { if(!pctrl) return; Point pt(p); int f(flags); - ctrl = GetCtrl(*pctrl, pt, f, filter); - if(!ctrl) ctrl = pctrl; - if(!ctrl) return; - WhenLeftDown(*ctrl, p, keyflags); + + Rect r; r.Clear(); + + //try to find multiple first + if(multi) + { + RectTracker tr(*this); + r = tr.Track(Rect(p,p), ALIGN_NULL, ALIGN_NULL); + } + + if(!r.IsEmpty()) + { + ctrls = GetCtrls(*pctrl, r, f, filter); + if(ctrls.IsEmpty()) + ctrls << pctrl; + WhenLeftSelectMulti(&ctrls, r, keyflags); + } + else + { + ctrls.SetCount(1); + ctrls.Top() = GetCtrl(*pctrl, pt, f, filter); + if(!ctrls.Top()) + ctrls.Top() = pctrl; + WhenLeftSelect(*ctrls.Top(), p, keyflags); + } + Action(); } void CtrlFinder::RightDown(Point p, dword keyflags) @@ -115,11 +308,34 @@ void CtrlFinder::RightDown(Point p, dword keyflags) if(!pctrl) return; Point pt(p); int f(flags); - ctrl = GetCtrl(*pctrl, pt, f, filter); - if(!ctrl) ctrl = pctrl; - if(!ctrl) return; - WhenRightDown(*ctrl, p, keyflags); + + Rect r; r.Clear(); + + //try to find multiple first + if(multi) + { + RectTracker tr(*this); + r = tr.Track(Rect(p,p), ALIGN_NULL, ALIGN_NULL); + } + + if(!r.IsEmpty()) + { + ctrls = GetCtrls(*pctrl, r, f, filter); + if(ctrls.IsEmpty()) + ctrls << pctrl; + WhenRightSelectMulti(&ctrls, r, keyflags); + } + else + { + ctrls.SetCount(1); + ctrls.Top() = GetCtrl(*pctrl, pt, f, filter); + if(!ctrls.Top()) + ctrls.Top() = pctrl; + WhenRightSelect(*ctrls.Top(), p, keyflags); + } + Action(); + if(WhenBar) MenuBar::Execute(WhenBar); } diff --git a/bazaar/CtrlFinder/CtrlFinder.h b/bazaar/CtrlFinder/CtrlFinder.h index fc31e1c53..d4ec4a9a7 100644 --- a/bazaar/CtrlFinder/CtrlFinder.h +++ b/bazaar/CtrlFinder/CtrlFinder.h @@ -9,7 +9,7 @@ class CtrlFinder : public ParentCtrl { public: typedef CtrlFinder CLASSNAME; - typedef Callback3 CtrlFilterType; + typedef Callback2 CtrlFilterType; enum { @@ -27,31 +27,54 @@ public: DEF = VISIBLE | INVISIBLE | ENABLED | DISABLED | VIEW | FRAME | DEEP, }; - CtrlFinder() : flags(DEF), filter(STDBACK(StdCtrlFilter)) { WantFocus(); } + CtrlFinder() : flags(DEF), filter(STDBACK(StdCtrlFilter)), multi(true) { WantFocus(); } virtual void LeftDown(Point p, dword keyflags); virtual void RightDown(Point p, dword keyflags); virtual void Updated(); - void SetSource(Ctrl* c) { if(pctrl != c) { if(c) ASSERT(c->GetParent()); pctrl = c; ctrl = NULL; UpdatedSource(); } Update(); } + void SetSource(Ctrl* c) { if(pctrl != c) { if(c) ASSERT(c->GetParent()); pctrl = c; ctrls.Clear(); UpdatedSource(); } Update(); } Ctrl* GetSource() const { return pctrl; } void ClearSource() { SetSource(NULL); } - void SetCtrl(Ctrl* c) { if(ctrl != c) { if(pctrl && c) { ASSERT(IsParentR(pctrl, c)); } ctrl = c; } Update(); } - Ctrl* GetCtrl() const { return ctrl; } - void ClearCtrl() { SetCtrl(NULL); } + void SetCtrl(Ctrl* c); + void SetCtrls(pick_ Vector& _ctrls) { ctrls = _ctrls; Update(); } - virtual Value GetData() const { return RawToValue(ctrl); } - virtual void SetData(const Value& v) { SetCtrl(RawValue::Extract(v)); } + Ctrl* GetCtrl() const { return ctrls.IsEmpty() ? NULL : ctrls.Top(); } + Vector GetCtrls() const { return Vector(ctrls, 1); } + bool IsEmpty() const { return ctrls.IsEmpty(); } + + void ClearCtrl() { ctrls.Clear(); Update(); } + + virtual Value GetData() const { return RawPickToValue(Vector(ctrls, 1)); } + virtual void SetData(const Value& v) { SetCtrls(Vector(RawValue >::Extract(v), 1)); } - static void StdCtrlFilter(Ctrl*& q, Point& pt, int& f); + static void StdCtrlFilter(Ctrl*& q, int& f); + static Ctrl* ChildAtPoint(Ctrl& par, Point& pt, int& f, const CtrlFilterType& filt); static Ctrl* GetCtrl(Ctrl& c, Point& p, int& f, const CtrlFilterType& filt); + + static Ctrl* ChildInRect(Ctrl& par, Rect& rect, int& f, const CtrlFilterType& filt); + static Ctrl* GetCtrl(Ctrl& c, Rect& rect, int& f, const CtrlFilterType& filt); + + static Vector ChildrenInRect(Ctrl& par, Rect& rect, int& f, const CtrlFilterType& filt); + static Vector GetCtrls(Ctrl& c, Rect& rect, int& f, const CtrlFilterType& filt); + static bool IsParentR(const Ctrl* p, const Ctrl* c); - Callback3 WhenLeftDown; - Callback3 WhenRightDown; + static void AddParentViewOffset(const Ctrl& c, Point& p); + static void AddContextOffset(const Ctrl& c, const Ctrl& q, Point& p); + static Point GetContextOffset(const Ctrl& c, const Ctrl& q); + static Point GetOffset(const Ctrl& ctxuser, const Ctrl& finalctx); + static Rect SurroundingRect(const Vector& ctrls); + + Callback3 WhenLeftSelect; + Callback3 WhenRightSelect; + + Callback3*, Rect, dword> WhenLeftSelectMulti; + Callback3*, Rect, dword> WhenRightSelectMulti; + Callback1 WhenBar; CtrlFilterType filter; //set to NULL if should not be handled, change flags if desired @@ -60,8 +83,10 @@ public: protected: void UpdatedSource(); + bool multi; + Ctrl* pctrl; //the parent we search in - Ctrl* ctrl; //the current found child + Vector ctrls; //the current found children }; #endif diff --git a/bazaar/CtrlFinder/init b/bazaar/CtrlFinder/init index b1154d716..0f00d3f75 100644 --- a/bazaar/CtrlFinder/init +++ b/bazaar/CtrlFinder/init @@ -1,5 +1,4 @@ #ifndef _CtrlFinder_icpp_init_stub #define _CtrlFinder_icpp_init_stub #include "CtrlLib/init" -#include "Gen/init" #endif diff --git a/bazaar/CtrlFinderTest/CtrlFinderTest.h b/bazaar/CtrlFinderTest/CtrlFinderTest.h index 20ae4561f..a29cb5196 100644 --- a/bazaar/CtrlFinderTest/CtrlFinderTest.h +++ b/bazaar/CtrlFinderTest/CtrlFinderTest.h @@ -25,6 +25,7 @@ public: void ToInfo(const String& s); void OnSelect(Ctrl& c, Point p, dword keyflags); + void OnSelectMulti(const Vector* pctrls, Rect r, dword keyflags); WithCtrlFinderTestLayout vis; FrameLeft > sb; diff --git a/bazaar/CtrlFinderTest/CtrlFinderTest.lay b/bazaar/CtrlFinderTest/CtrlFinderTest.lay index 8d4eca9f2..1bd0dbc56 100644 --- a/bazaar/CtrlFinderTest/CtrlFinderTest.lay +++ b/bazaar/CtrlFinderTest/CtrlFinderTest.lay @@ -4,6 +4,10 @@ LAYOUT(CtrlFinderTestLayout, 548, 416) ITEM(EditString, dv___2, LeftPosZ(336, 64).TopPosZ(12, 19)) ITEM(DocEdit, info, LeftPosZ(12, 292).TopPosZ(12, 172)) ITEM(ParentCtrl, pc, SetFrame(BlackFrame()).LeftPosZ(308, 168).TopPosZ(124, 184)) + ITEM(Button, dv___5, LeftPosZ(32, 56).TopPosZ(212, 15)) + ITEM(Button, dv___6, LeftPosZ(128, 56).TopPosZ(228, 15)) + ITEM(Button, dv___7, LeftPosZ(60, 56).TopPosZ(260, 15)) + ITEM(Button, dv___8, LeftPosZ(148, 56).TopPosZ(284, 15)) END_LAYOUT LAYOUT(ControlLay, 292, 40) diff --git a/bazaar/CtrlFinderTest/main.cpp b/bazaar/CtrlFinderTest/main.cpp index a6dcbd009..0a760add6 100644 --- a/bazaar/CtrlFinderTest/main.cpp +++ b/bazaar/CtrlFinderTest/main.cpp @@ -13,6 +13,16 @@ void CtrlFinderTest::OnSelect(Ctrl& c, Point p, dword keyflags) ToInfo(inf); } +void CtrlFinderTest::OnSelectMulti(const Vector* pctrls, Rect r, dword keyflags) +{ + String inf = "Selected: \n"; + + for(int i = 0; i < pctrls->GetCount(); i++) + inf << String(typeid(*pctrls->operator[](i)).name()) << "\n"; + + ToInfo(inf); +} + void CtrlFinderTest::VisitCB() { hk.SetSource(&vis); @@ -86,7 +96,8 @@ CtrlFinderTest::CtrlFinderTest() ft.view <<= true; ViewCB(); - hk.WhenLeftDown = THISBACK(OnSelect); + hk.WhenLeftSelect = THISBACK(OnSelect); + hk.WhenLeftSelectMulti = THISBACK(OnSelectMulti); hk.SetSource(&vis); } diff --git a/bazaar/CtrlMover/CtrlMover.cpp b/bazaar/CtrlMover/CtrlMover.cpp index 69e235e58..1cb3131f3 100644 --- a/bazaar/CtrlMover/CtrlMover.cpp +++ b/bazaar/CtrlMover/CtrlMover.cpp @@ -1,47 +1,42 @@ #include "CtrlMover.h" -//returns the offset of a ctrl's drawing area w.r.t. its parent's drawing area -void CtrlMover::GetOffset(const Ctrl& c, Point& p) -{ - p += c.GetRect().TopLeft(); - if(c.InView()) - p += c.GetParent()->GetView().TopLeft(); -} - -//returns the offset of a ctrl's drawing area w.r.t an upper parent's drawing area. -void CtrlMover::GetOffset(const Ctrl& c, const Ctrl& q, Point& p) -{ - if(&c == &q) return; - GetOffset(c, p); - if(Ctrl* pc = c.GetParent()) - GetOffset(*pc, q, p); -} - -//calculate topleft offset of c w.r. up to par recursively -Point CtrlMover::GetOffset(const Ctrl& c, const Ctrl& q) -{ - Point p; p.Clear(); - GetOffset(c, q, p); - return p; -} - void CtrlMover::OnCtrlLeft(Ctrl& c, Point p, dword keyflags) { if(c.InFrame()) return; //may not move frames rc.Remove(); - if(&c == &rc) return; if(&c == pctrl) return; //mat not move base - UpdateAction(); + if(&c == &rc) return; + Update(); +} + +void CtrlMover::OnCtrlLeftMulti(const Vector* pctrls, Rect r, dword keyflags) +{ + if(pctrls->Top()->InFrame()) return; //may not move frames + rc.Remove(); + if(pctrls->Top() == pctrl) return; //mat not move base + if(pctrls->Top() == &rc) return; + + //for(int i = 0; i < pctrls->GetCount(); i++) {} + + Update(); } void CtrlMover::OnRectChange() { - if(!pctrl || !ctrl) { rc.Remove(); return; } + if(!pctrl || ctrls.IsEmpty()) { rc.Remove(); return; } Rect r = rc.GetData(); - r.Offset(-GetOffset(*ctrl, *pctrl) + ctrl->GetRect().TopLeft()); - - ctrl->SetRect(r); + + if(ctrls.GetCount() > 1) + { + //not supported + } + else + { + r.Offset(-GetOffset(*ctrls.Top(), *pctrl)); + ctrls.Top()->SetRect(r); + } + Action(); } @@ -54,20 +49,12 @@ void CtrlMover::Updated() { CtrlFinder::Updated(); - if(!pctrl || !ctrl) { rc.Remove(); return; } + if(!pctrl || ctrls.IsEmpty()) { rc.Remove(); return; } Add(rc.SizePos()); - //if c is frame: rect in parents window, - //if is in view, then rect in view area, which itself is subarea of parent - //using only GetOffset we wouldnt be able to get the rect, only the offset point - //but we do not need the offset of the drawing area, but the offesstet drawing area itself - //thats why ctrl->GetParent, it replics part of GetOffset - //revert the GetRect.TopLeft offset addition, because we specify the rect directly in parent coords - //be it in parents view or frame, we dont specify it in childrens rect coords - Rect r = ctrl->GetRect(); - r.Offset(GetOffset(*ctrl, *pctrl) - r.TopLeft()); - + Rect r = SurroundingRect(ctrls); + r.Offset( GetOffset(*ctrls.Top(), *pctrl)); //any of the parttakers is good to get the offset of their branch rc.SetData(r); } @@ -79,7 +66,7 @@ void CtrlMover::State(int reason) CtrlMover::CtrlMover() { - WhenLeftDown = THISBACK(OnCtrlLeft); + WhenLeftSelect = THISBACK(OnCtrlLeft); rcst = RectCtrl::StyleDefault(); rcst.rectcol = Null; rc.SetStyle(rcst); diff --git a/bazaar/CtrlMover/CtrlMover.h b/bazaar/CtrlMover/CtrlMover.h index 73cd491be..d00d8a418 100644 --- a/bazaar/CtrlMover/CtrlMover.h +++ b/bazaar/CtrlMover/CtrlMover.h @@ -19,12 +19,10 @@ public: virtual void Updated(); void OnCtrlLeft(Ctrl& c, Point p, dword keyflags); + void OnCtrlLeftMulti(const Vector* pctrls, Rect r, dword keyflags); + void OnMissed(Point p, dword keyflags); - static void GetOffset(const Ctrl& c, Point& p); - static void GetOffset(const Ctrl& c, const Ctrl& q, Point& p); - static Point GetOffset(const Ctrl& c, const Ctrl& q); - protected: void OnRectChange(); diff --git a/bazaar/CtrlMoverTest/CtrlMoverTest.h b/bazaar/CtrlMoverTest/CtrlMoverTest.h index b1c55383b..71692018c 100644 --- a/bazaar/CtrlMoverTest/CtrlMoverTest.h +++ b/bazaar/CtrlMoverTest/CtrlMoverTest.h @@ -26,6 +26,7 @@ public: void ToInfo(const String& s); void OnSelect(Ctrl& c, Point p, dword keyflags); + void OnSelectMulti(const Vector* pctrls, Rect r, dword keyflags); AutoScroller sc; diff --git a/bazaar/CtrlMoverTest/CtrlMoverTest.lay b/bazaar/CtrlMoverTest/CtrlMoverTest.lay index 2f034043b..71e15ad24 100644 --- a/bazaar/CtrlMoverTest/CtrlMoverTest.lay +++ b/bazaar/CtrlMoverTest/CtrlMoverTest.lay @@ -4,6 +4,10 @@ LAYOUT(CtrlMoverTestLayout, 548, 416) ITEM(EditString, dv___2, LeftPosZ(336, 64).TopPosZ(12, 19)) ITEM(DocEdit, info, LeftPosZ(12, 292).TopPosZ(12, 172)) ITEM(ParentCtrl, pc, SetFrame(BlackFrame()).LeftPosZ(308, 168).TopPosZ(124, 184)) + ITEM(Button, dv___5, LeftPosZ(144, 52).TopPosZ(304, 32)) + ITEM(Button, dv___6, LeftPosZ(64, 32).TopPosZ(332, 72)) + ITEM(Button, dv___7, LeftPosZ(40, 72).TopPosZ(244, 72)) + ITEM(Button, dv___8, LeftPosZ(124, 48).TopPosZ(356, 44)) END_LAYOUT LAYOUT(ControlLay, 292, 40) diff --git a/bazaar/CtrlMoverTest/main.cpp b/bazaar/CtrlMoverTest/main.cpp index 926347a0a..5ba873863 100644 --- a/bazaar/CtrlMoverTest/main.cpp +++ b/bazaar/CtrlMoverTest/main.cpp @@ -14,6 +14,17 @@ void CtrlMoverTest::OnSelect(Ctrl& c, Point p, dword keyflags) hk.OnCtrlLeft(c, p, keyflags); } +void CtrlMoverTest::OnSelectMulti(const Vector* pctrls, Rect r, dword keyflags) +{ + String inf = "Selected: \n"; + + for(int i = 0; i < pctrls->GetCount(); i++) + inf << String(typeid(*pctrls->operator[](i)).name()) << "\n"; + + ToInfo(inf); + hk.OnCtrlLeftMulti(pctrls, r, keyflags); +} + void CtrlMoverTest::VisitCB() { hk.SetSource(&vis); @@ -89,7 +100,8 @@ CtrlMoverTest::CtrlMoverTest() sc.AddPane(vis); sc.WhenScrolled = callback(&hk, &CtrlMover::Update); - hk.WhenLeftDown = THISBACK(OnSelect); + hk.WhenLeftSelect = THISBACK(OnSelect); + hk.WhenLeftSelectMulti = THISBACK(OnSelectMulti); hk.SetSource(&vis); } diff --git a/bazaar/CtrlPos/CtrlPos.cpp b/bazaar/CtrlPos/CtrlPos.cpp index c0a8b712c..a14833222 100644 --- a/bazaar/CtrlPos/CtrlPos.cpp +++ b/bazaar/CtrlPos/CtrlPos.cpp @@ -63,31 +63,96 @@ bool CtrlPos::GetAlignMode(const Rect& _r, const Rect& r, const Point& pp, Ctrl: return false; } -void CtrlPos::DrawHintFrame(Draw& w, const Ctrl& g, const Ctrl& q, const Color& hintcol) +void CtrlPos::GetAlignRects(const Ctrl& ctxuser, const Ctrl& finalctx, Rect& r, Rect& _r) { - Ctrl* c = q.GetFirstChild(); + r = ctxuser.GetRect(); + Point op = GetOffset(ctxuser, finalctx); + r.Offset(op); + + if(ctxuser.InView()) + { + _r = ctxuser.GetParent()->GetView(); + _r.Offset(op - _r.TopLeft()); //revert own offset which has been added by GetOffset + } + else //in frame, support makes no sense, actually, frames shouldnt be moveable + { + _r = ctxuser.GetParent()->GetRect(); + Point _op = GetOffset(*ctxuser.GetParent(), finalctx); //without view, so real parents's offset + _r.Offset(_op); + } +} + +void CtrlPos::DrawHintFrame(Draw& w, const Ctrl& g, const Ctrl& q, const Color& hintcol, const CtrlFilterType& filter, int flags) +{ + Ctrl* c = g.GetFirstChild(); while(c) { Ctrl* e(c); Point p; p.Clear(); int f(flags); - filter(e, p, f); + filter(e, f); if(e && c->InView()) { Rect r = c->GetRect(); - if(c->InView()) - r.Offset(c->GetParent()->GetView().TopLeft()); - r.Offset(CtrlMover::GetOffset(*(c->GetParent()), g)); - + r.Offset(GetOffset(*c, q)); r.Inflate(1); RectCtrl::DrawHandleFrame(w, r, hintcol, 1); } if(f & CtrlFinder::DEEP) - DrawHintFrame(w, g, *c, hintcol); + DrawHintFrame(w, *c, q, hintcol, filter, f); c = c->GetNext(); } } +//remove each element of _c in c, if found +void CtrlPos::CombineSubtract(Vector& c, pick_ Vector _c) +{ + //top is the currently editable ctrl + + while(_c.GetCount() > 0) + { + int i = FindIndex(c, _c.Top()); //with this we are O(N^2) + if(i>=0) c.Remove(i); + _c.Drop(); + } +} + +void CtrlPos::CombineAdd(Vector& c, pick_ Vector _c) +{ + //top is the currently editable ctrl + + //first, we remove every duplicate, before we take everything else + CombineSubtract(c, Vector(_c, 1)); //deep copy to keep our copy + c.Append(_c); +} + +void CtrlPos::DrawSelected(Draw& w, const Vector& ctrls) +{ + for(int i = 0; i < ctrls.GetCount(); i++) + { + Ctrl& c = *ctrls[i]; + if(&c == pctrl) return; //this will be the only one in the vector + + Rect r; //the rect of the ctrl + Rect _r; //the outer parent ctrl rect + GetAlignRects(c, *pctrl, r, _r); + + if(&c == ctrls.Top()) + { + //top, the one that all controling info comes from or goes to in a multi select context + DrawAlignHandle(w, _r, r, c.GetPos(), style->handcol); + RectCtrl::DrawHandleFrame(w, r, style->handcol, style->framesize); + RectCtrl::DrawHandle(w, r, style->handcol, style->handsize); + + RectCtrl::DrawHandleFrame(w, _r, LtRed(), style->framesize); //debug only maybe? + } + else + { + RectCtrl::DrawHandleFrame(w, r, style->framecol, style->framesize); + } + } +} + void CtrlPos::Paint(Draw& w) { Size sz = GetSize(); @@ -98,30 +163,17 @@ void CtrlPos::Paint(Draw& w) if(!IsEnabled()) return; if(pctrl) - DrawHintFrame(w, *pctrl, *pctrl, LtGray()); + DrawHintFrame(w, *pctrl, *pctrl, LtGray(), filter, flags); + + if(ctrls.IsEmpty()) return; + + DrawSelected(w, ctrls); - if(!ctrl) return; - Ctrl& c = *ctrl; - if(&c == pctrl) return; - - Rect r = c.GetRect(); - Rect _r = c.GetParent()->GetView(); - Rect tr(r); - - if(c.InView()) - r.Offset(_r.TopLeft()); - Point op = CtrlMover::GetOffset(*c.GetParent(), *pctrl); - r.Offset(op); - _r.Offset(op); - - RectCtrl::DrawHandleFrame(w, r, style->framecol, style->framesize); - - DrawAlignHandle(w, _r, r, c.GetPos(), style->framecol); - - RectCtrl::DrawHandle(w, r, style->handcol, style->handsize); - if(pressed)// && moving) - RectCtrl::DrawRectInfo(w, Point(10,10), tr, style->framecol, style->textcol); + RectCtrl::DrawRectInfo(w, Point(10,10), ctrls.Top()->GetRect(), style->framecol, style->textcol); + + //RectCtrl::DrawHandleFrame(w, rd, LtGreen(), style->framesize); //debug + //RectCtrl::DrawHandleFrame(w, rd2, Yellow(), style->framesize); //debug } void CtrlPos::LeftDown(Point p, dword keyflags) @@ -132,30 +184,47 @@ void CtrlPos::LeftDown(Point p, dword keyflags) moving = false; pressed = (keyflags & K_MOUSELEFT); - if(ctrl) + if(!ctrls.IsEmpty()) { - Ctrl& c = *ctrl; - //if already found prepare moving - ASSERT(!c.InFrame()); - xpos = c.GetPos(); + //if already found prepare moving or dragging handles + //will be dealing with .Top() as the handled Ctrl + + Ctrl& c = *ctrls.Top(); + + //save old data xp = p; + xpos.SetCount(ctrls.GetCount()); + xpars.SetCount(ctrls.GetCount()); + xop.SetCount(ctrls.GetCount()); + xr.SetCount(ctrls.GetCount()); + for(int i = 0; i < ctrls.GetCount(); i++) + { + Ctrl& c = *ctrls[i]; + ASSERT(!c.InFrame()); + xpos[i] = c.GetPos(); + xpars[i] = c.GetParent(); + xop[i] = GetOffset(c, *pctrl); + xr[i] = c.GetRect(); + } - Rect r = c.GetRect(); - Rect _r = c.GetParent()->GetView(); + Rect r; //the rect of the ctrl + Rect _r; //the outer parent ctrl rect + GetAlignRects(c, *pctrl, r, _r); - if(c.InView()) - r.Offset(_r.TopLeft()); - Point op = CtrlMover::GetOffset(*c.GetParent(), *pctrl); - r.Offset(op); - _r.Offset(op); - - Ctrl::LogPos pos = xpos; + Ctrl::LogPos pos = xpos.Top(); Rect rr(r); rr.Inflate(style->handsize+2); + //process alignment or prepare cursor for handles if(GetAlignMode(_r, rr, p, pos, style->handsize)) { - pos = LogPosPopUp::MakeLogPos(pos, c); - c.SetPos(pos); + //derive new alignment from top to others + for(int i = 0; i < ctrls.GetCount(); i++) + { + Ctrl& c = *ctrls[i]; + Ctrl::LogPos _pos = LogPosPopUp::MakeLogPos(pos, c); + c.SetPos(_pos); + } + Action(); Refresh(); return; @@ -163,26 +232,73 @@ void CtrlPos::LeftDown(Point p, dword keyflags) else if((mode = RectCtrl::GetMode(r, p, keyflags, style->handsize)) != RectCtrl::NONE) { ci = RectCtrl::SetCursor(mode, keyflags, ci); + //no action, nothing happened yet Refresh(); return; } + //else fallback to finding a ctrl } - if(pctrl) + if(!pctrl) return; + + //start finding + + Point pt(p); + int f(flags); + Rect r; r.Clear(); + + //we can try to find multiple first + if(multi) { - Point pt(p); - int f(flags); - ctrl = CtrlFinder::GetCtrl(*pctrl, pt, f, filter); - if(ctrl) - { - if(ctrl->InFrame()) //may not move base nor frames - ClearCtrl(); - else - WhenLeftDown(*ctrl, p, keyflags); - } - Action(); + RectTracker tr(*this); + r = tr.Track(Rect(p,p), ALIGN_NULL, ALIGN_NULL); } + if(!r.IsEmpty()) + { + //try find multiple + Vector _ctrls; + _ctrls = GetCtrls(*pctrl, r, f, filter); + if(_ctrls.IsEmpty() || !_ctrls.Top()) + ctrls.Clear(); + else if(keyflags & K_CTRL) + { + //add or remove probable found additional controls + if(keyflags & K_SHIFT) + CombineSubtract(ctrls, _ctrls); + else + CombineAdd(ctrls, _ctrls); + } + else + ctrls = _ctrls; + if(!ctrls.IsEmpty()) + WhenLeftSelectMulti(&ctrls, r, keyflags); + } + else + { + //try find single + + Vector _ctrls; + _ctrls << GetCtrl(*pctrl, pt, f, filter); + if(_ctrls.IsEmpty() || !_ctrls.Top() + || _ctrls.Top()->InFrame() //dont allow moving frame around + ) + ctrls.Clear(); + else if(keyflags & K_CTRL) + { + //add or remove probable found additional controls + if(keyflags & K_SHIFT) + CombineSubtract(ctrls, _ctrls); + else + CombineAdd(ctrls, _ctrls); + } + else + ctrls = _ctrls; + if(!ctrls.IsEmpty()) + WhenLeftSelect(*ctrls.Top(), p, keyflags); + } + + Action(); Refresh(); } @@ -192,52 +308,115 @@ void CtrlPos::MouseMove(Point p, dword keyflags) moving = true; pressed = (keyflags & K_MOUSELEFT); - //int m = RectCtrl::GetMode(r, p, keyflags, style->handsize); - //ci = RectCtrl::SetCursor(m, keyflags); - if(!ctrl) return; - Ctrl& c = *ctrl; + + if(ctrls.IsEmpty()) return; + Ctrl& c = *ctrls.Top(); //we are always editing top, even if more selected. they will be calculated accordingly + +#if 1 //for instant showing where handle dragging is met + Rect r; //the rect of the ctrl + Rect _r; //the outer parent ctrl rect + GetAlignRects(c, *pctrl, r, _r); + int m = RectCtrl::GetMode(r, p, keyflags, style->handsize); + ci = RectCtrl::SetCursor(m, keyflags, ci); +#endif if(pressed && mode != RectCtrl::NONE) { + Point dp(p-xp); + if(keyflags & K_ALT) { - Ctrl* q = c.GetParent(); - Ctrl* prevc = c.GetPrev(); + //move into another parent to be found parent //calculate some things not accessible when Removed() + //then, the Ctrls are removed to not take part in GetCtrl search as new destination + //then, ctrls are added to new destination or restored to old, if no new found - Rect r = LogPosPopUp::CtrlRect(xpos, q->GetSize()); - if(c.InView()) - r.Offset(c.GetParent()->GetView().TopLeft()); - Point ops = CtrlMover::GetOffset(*(c.GetParent()), *pctrl); - r.Offset(ops); + //r will be moving ctrl's source rect in pctrl frame coords ctx calculated from its origin parent + //then, the dp vector offset, from draggin the handles/moving is applied + //the new parent's ofset is calculated and applied + //finally, the new logpos is generated using old alignment values, but new rect and new parent's size - c.Remove(); //prevent moving control from finding when searching new parent + //cant use r = c.GetRect().Offseted(GetOffset(c, *pctrl)); + //because parent changes as we move. would need to correct the xpos every time, what we dont want. + //so we calculate from the fixed base + + Ctrl* q = c.GetParent(); //to determine later if we stayed within same parent + + Vector _xpars; + Vector _xprevc; + _xpars.SetCount(ctrls.GetCount()); //keep track of current old parent + //_xprevc.SetCount(ctrls.GetCount()); //and the order + for(int i = 0; i < ctrls.GetCount(); i++) + { + Ctrl& _c = *ctrls[i]; + _xpars[i] = _c.GetParent(); + //_xprevc[i] = _c.GetPrev(); + _c.Remove(); //prevent moving controls from finding when searching new parent + } + Point pt(p); int ft(flags); flags |= (DEEP | NEST); Ctrl* pc = GetCtrl(*pctrl, pt, flags, filter); flags &= ~(DEEP | NEST); flags |= (ft & DEEP); //restore DEEP flag from save, NEST is ours - if(!pc) pc = pctrl; - if(pc != q) - { - r.Offset(-pc->GetView().TopLeft()); - Point opd = CtrlMover::GetOffset(*pc, *pctrl); - r.Offset(-opd); - xpos = LogPosPopUp::MakeLogPos(xpos, r, pc->GetSize()); - - pc->Add(c); + if(!pc) pc = pctrl; //enable fallback to global parent + if(pc && pc != q) + { + //add to new parent + for(int i = 0; i < ctrls.GetCount(); i++) + pc->AddChild(ctrls[i]); } else - q->AddChild(&c, prevc); //undo Remove(); - } + { + //restore adding to previous + //we cant add to origin xpars here, since we need to keep track of the very last parrent (would oscilate) + //means that ctrls content from different parents ends up beeing added to ctrls.Top()'s parent, - Size psz = c.GetParent()->GetSize(); - Rect r = LogPosPopUp::CtrlRect(xpos, psz); - RectCtrl::CalcRect(r, p-xp, keyflags, mode, g); - r.Normalize(); - Ctrl::LogPos pos = LogPosPopUp::MakeLogPos(xpos, r, psz); - GetCtrl()->SetPos(pos); + for(int i = 0; i < ctrls.GetCount(); i++) + _xpars[i]->AddChild(ctrls[i]);//, xprevc[i]); //cant restore full order, + //since prev children may be moving as well and may not be added yet +#if 0 + //restore order now would be possible + for(int i = 0; i < ctrls.GetCount(); i++) + _xpars[i]->AddChild(ctrls[i], _xprevc[i]); +#endif + } + + //recalculate the new positions for all Ctrls + for(int i = 0; i < ctrls.GetCount(); i++) + { + Ctrl& c = *ctrls[i]; + Rect r = xr[i]; + + RectCtrl::CalcRect(r, dp, keyflags, mode, g); + r.Normalize(); //in case r had been moved into flipped + + //apply offsets + //transform ctrl's rect to pctrl context seen from old parent + //retransform to new parent + Point opd = GetOffset(c, *pctrl); + r.Offset(xop[i]-opd); + + Ctrl::LogPos pos = LogPosPopUp::MakeLogPos(xpos[i], r, c.GetParent()->GetSize()); + c.SetPos(pos); + } + } + else + { + //recalculate the new positions for all Ctrls + for(int i = 0; i < ctrls.GetCount(); i++) + { + Ctrl& c = *ctrls[i]; + Rect r = xr[i]; + + RectCtrl::CalcRect(r, dp, keyflags, mode, g); + r.Normalize(); //in case r had been moved into flipped + + Ctrl::LogPos pos = LogPosPopUp::MakeLogPos(xpos[i], r, c.GetParent()->GetSize()); + c.SetPos(pos); + } + } Action(); Refresh(); } @@ -248,7 +427,7 @@ void CtrlPos::LeftUp(Point p, dword keyflags) ReleaseCapture(); pressed = false; moving = false; - //xpos.SetNull(); + xp.SetNull(); mode = RectCtrl::NONE; if(IsReadOnly() || !IsEnabled()) return; @@ -259,73 +438,70 @@ void CtrlPos::LeftUp(Point p, dword keyflags) void CtrlPos::RightDown(Point p, dword keyflags) { - //cancel - if(!(keyflags & K_SHIFT)) - LeftDown(p, keyflags); ReleaseCapture(); + pressed = (keyflags & K_MOUSELEFT); + moving = false; + + xp.SetNull(); int m = mode; mode = RectCtrl::NONE; if(IsReadOnly() || !IsEnabled()) return; ci = RectCtrl::SetCursor(mode, keyflags, ci); - if(!GetCtrl()) return; + + if(ctrls.IsEmpty()) return; if(pressed) { - if(m != RectCtrl::NONE) + //cancel, restore backup of parent context and logpos + for(int i = 0; i < ctrls.GetCount(); i++) { - GetCtrl()->SetPos(xpos); - Action(); - Refresh(); + if(ctrls[i]->GetParent() != xpars[i]) + xpars[i]->Add(*ctrls[i]); //@todo: old order not kept + ctrls[i]->SetPos(xpos[i]); } - } - else if(keyflags & K_SHIFT) - { - pressed = false; - moving = false; - //xpos.SetNull(); - xp.SetNull(); - //mode = RectCtrl::NONE; - RectTracker tr(*this); - Size psz = GetCtrl()->GetParent()->GetSize(); - Rect r = tr.Track(Rect(p,p)); - - Ctrl* pc = GetCtrl()->GetParent(); - r.Offset(-pc->GetView().TopLeft()); - Point opd = CtrlMover::GetOffset(*pc, *pctrl); - r.Offset(-opd); - - Ctrl::LogPos pos = LogPosPopUp::MakeLogPos(xpos, r, psz); - GetCtrl()->SetPos(pos); Action(); Refresh(); } else if(WhenBar) MenuBar::Execute(WhenBar); + pressed = false; } void CtrlPos::MouseWheel(Point p, int zdelta, dword keyflags) { //if(!IsEditable()) return; //if(!HasFocus()) SetFocus(); - if(!GetCtrl()) return; - Ctrl& c = *GetCtrl(); - - int i = zdelta/120; - for(; i<0; ++i) - { - Ctrl* p = c.GetNext(); - c.GetParent()->AddChild(&c, p); - c.Refresh(); - } - for(; i>0; --i) - { - Ctrl* p = c.GetPrev(); - c.GetParent()->AddChildBefore(&c, p); - c.Refresh(); - } + if(ctrls.IsEmpty()) return; + //change order of children for top only, drop remaining + ctrls[0] = ctrls.Top(); + ctrls.SetCount(1); + + Ctrl& c = *ctrls.Top(); + + if(ctrls.GetCount() > 1) + { + + } + else + { + int i = zdelta/120; + + for(; i<0; ++i) + { + Ctrl* p = c.GetNext(); + c.GetParent()->AddChild(&c, p); + c.Refresh(); + } + for(; i>0; --i) + { + Ctrl* p = c.GetPrev(); + c.GetParent()->AddChildBefore(&c, p); + c.Refresh(); + } + } } void CtrlPos::LeftDouble(Point p, dword flags) @@ -358,6 +534,5 @@ CtrlPos::CtrlPos() BackPaint(); NoIgnoreMouse(); style = &RectCtrl::StyleDefault(); - //xpos.SetNull(); xp.SetNull(); } diff --git a/bazaar/CtrlPos/CtrlPos.h b/bazaar/CtrlPos/CtrlPos.h index ef3c9ae17..73776c9aa 100644 --- a/bazaar/CtrlPos/CtrlPos.h +++ b/bazaar/CtrlPos/CtrlPos.h @@ -8,9 +8,6 @@ using namespace Upp; #include #include -//for some helpers -#include - class CtrlPos : public CtrlFinder { public: @@ -39,15 +36,31 @@ public: static void DrawAlignHandle(Draw& w, const Rect& _r, const Rect& r, const Ctrl::LogPos& pos, const Color& col); static bool GetAlignMode(const Rect& _r, const Rect& r, const Point& pp, Ctrl::LogPos& pos, int handsize); - void DrawHintFrame(Draw& w, const Ctrl& g, const Ctrl& q, const Color& hintcol); + static void GetAlignRects(const Ctrl& ctxuser, const Ctrl& finalctx, Rect& r, Rect& _r); + static void DrawHintFrame(Draw& w, const Ctrl& g, const Ctrl& q, const Color& hintcol, const CtrlFilterType& filter, int flags); + + void CombineAdd(Vector& c, pick_ Vector _c); + void CombineSubtract(Vector& c, pick_ Vector _c); Callback WhenLeftDouble; protected: + void DrawSelected(Draw& w, const Vector& ctrls); + const RectCtrl::Style* style; Point g; + + //storing info where the drag began (xp), the old logpos values (xpos) and the old parents (xpars) + //for calculation speed: precalculated offset to pctrl context and the original rect in pctrl context Point xp; - Ctrl::LogPos xpos; + Array xpos; + Vector xpars; + Vector xop; + Vector xr; + + //Rect rd; //debug + //Rect rd2; //debug + int mode; bool pressed; bool moving; diff --git a/bazaar/CtrlPos/init b/bazaar/CtrlPos/init index 04a422ae7..a61e0790f 100644 --- a/bazaar/CtrlPos/init +++ b/bazaar/CtrlPos/init @@ -1,7 +1,6 @@ #ifndef _CtrlPos_icpp_init_stub #define _CtrlPos_icpp_init_stub #include "Core/init" -#include "Gen/init" #include "RectCtrl/init" #include "LogPosCtrl/init" #include "CtrlFinder/init" diff --git a/bazaar/CtrlPosTest/CtrlPosTest.h b/bazaar/CtrlPosTest/CtrlPosTest.h index 659b0af2a..148dafa5d 100644 --- a/bazaar/CtrlPosTest/CtrlPosTest.h +++ b/bazaar/CtrlPosTest/CtrlPosTest.h @@ -9,6 +9,7 @@ using namespace Upp; #include #include +#include class CtrlPosTest : public TopWindow { public: @@ -28,6 +29,8 @@ public: void ToInfo(const String& s); void OnSelect(Ctrl& c, Point p, dword keyflags); + AutoScroller sc; + WithCtrlPosTestLayout vis; FrameLeft > sb; CtrlPos hk; diff --git a/bazaar/CtrlPosTest/CtrlPosTest.lay b/bazaar/CtrlPosTest/CtrlPosTest.lay index 03dad4cc4..c423c704a 100644 --- a/bazaar/CtrlPosTest/CtrlPosTest.lay +++ b/bazaar/CtrlPosTest/CtrlPosTest.lay @@ -4,7 +4,11 @@ LAYOUT(CtrlPosTestLayout, 548, 416) ITEM(EditString, dv___2, LeftPosZ(336, 64).TopPosZ(12, 19)) ITEM(DocEdit, info, LeftPosZ(12, 292).TopPosZ(12, 172)) ITEM(ParentCtrl, pc, SetFrame(BlackFrame()).LeftPosZ(308, 168).TopPosZ(124, 184)) - ITEM(StaticText, dv___5, SetText(t_("STATIC")).LeftPosZ(128, 112).TopPosZ(248, 60)) + ITEM(StaticText, dv___5, SetText(t_("STATIC")).LeftPosZ(168, 112).TopPosZ(204, 60)) + ITEM(Button, dv___6, LeftPosZ(144, 52).TopPosZ(304, 32)) + ITEM(Button, dv___7, LeftPosZ(64, 32).TopPosZ(332, 72)) + ITEM(Button, dv___8, LeftPosZ(40, 72).TopPosZ(244, 72)) + ITEM(Button, dv___9, LeftPosZ(124, 48).TopPosZ(356, 44)) END_LAYOUT LAYOUT(ControlLay, 292, 40) diff --git a/bazaar/CtrlPosTest/CtrlPosTest.upp b/bazaar/CtrlPosTest/CtrlPosTest.upp index d7d5c79c1..46ef525fd 100644 --- a/bazaar/CtrlPosTest/CtrlPosTest.upp +++ b/bazaar/CtrlPosTest/CtrlPosTest.upp @@ -2,7 +2,8 @@ description "example how to change Ctrl LogPos in a live environment\377"; uses CtrlLib, - CtrlPos; + CtrlPos, + AutoScroller; file CtrlPosTest.h, diff --git a/bazaar/CtrlPosTest/init b/bazaar/CtrlPosTest/init index 6c973a2c3..6da38a0e0 100644 --- a/bazaar/CtrlPosTest/init +++ b/bazaar/CtrlPosTest/init @@ -1,5 +1,6 @@ #ifndef _CtrlPosTest_icpp_init_stub #define _CtrlPosTest_icpp_init_stub #include "CtrlLib/init" -#include "CtrlPos/init" +#include "CtrlPos/init" +#include "AutoScroller/init" #endif diff --git a/bazaar/CtrlPosTest/main.cpp b/bazaar/CtrlPosTest/main.cpp index 663cbe126..3bed57141 100644 --- a/bazaar/CtrlPosTest/main.cpp +++ b/bazaar/CtrlPosTest/main.cpp @@ -51,12 +51,11 @@ void CtrlPosTest::ViewCB() CtrlPosTest::CtrlPosTest() { - CtrlLayout(vis); - SetRect(vis.GetRect()); - Add(vis.SizePos()); - + SetRect(Size(400,400)); Sizeable().Zoomable(); + CtrlLayout(vis); + CtrlLayout(sb); sb.Width(sb.GetSize().cx); vis.AddFrame(sb); @@ -89,7 +88,11 @@ CtrlPosTest::CtrlPosTest() ft.view <<= true; ViewCB(); - hk.WhenLeftDown = THISBACK(OnSelect); + Add(sc.SizePos()); + sc.AddPane(vis); + sc.WhenScrolled = callback(&hk, &CtrlPos::Update); + + hk.WhenLeftSelect = THISBACK(OnSelect); hk.SetSource(&vis); hk.SetFocus(); } diff --git a/bazaar/LogPosCtrl/LogPosCtrl.cpp b/bazaar/LogPosCtrl/LogPosCtrl.cpp index db7a48901..59869e380 100644 --- a/bazaar/LogPosCtrl/LogPosCtrl.cpp +++ b/bazaar/LogPosCtrl/LogPosCtrl.cpp @@ -18,6 +18,9 @@ static void sLay1(int& pos, int& r, int align, int a, int b, int sz) r = pos + max(size, 0); } +//LogPos, parent Size -> Rect + +//generates a Rect from a LogPos info and its parent size Rect LogPosPopUp::CtrlRect(Ctrl::LogPos pos, Size sz) { Rect r; @@ -26,6 +29,7 @@ Rect LogPosPopUp::CtrlRect(Ctrl::LogPos pos, Size sz) return r; } +//same as above but zoom support Rect LogPosPopUp::CtrlRectZ(Ctrl::LogPos pos, Size sz) { Rect r = CtrlRect(pos, sz); @@ -50,23 +54,31 @@ Ctrl::Logc MakeLogc(int align, int a, int b, int sz) return Ctrl::PosSize(a, sz - b); } +//alignment info, Rect, parent Size -> LogPos + Ctrl::LogPos LogPosPopUp::MakeLogPos(int ax, int ay, const Rect& r, Size sz) { return Ctrl::LogPos(MakeLogc(ax, r.left, r.right, sz.cx), MakeLogc(ay, r.top, r.bottom, sz.cy)); } +//same as above, but takes align infos from a LogPos info Ctrl::LogPos LogPosPopUp::MakeLogPos(Ctrl::LogPos p, const Rect& r, Size sz) { return MakeLogPos(p.x.GetAlign(), p.y.GetAlign(), r, sz); } +//same as above, but generates source Rect from pos/sz +//then applying new alignment to it, taken from p +//this effectivly replaces the alignment info, keeping the rect visually in place +//which includes recalculation of a and b data Ctrl::LogPos LogPosPopUp::MakeLogPos(Ctrl::LogPos p, const Ctrl::LogPos& pos, Size sz) { - Rect r = CtrlRect(pos, sz); + Rect r = CtrlRect(pos, sz); //generate the source rect return MakeLogPos(p, r, sz); } +//same as above but it does it for a specific Ctrl already Ctrl::LogPos LogPosPopUp::MakeLogPos(Ctrl::LogPos p, const Ctrl& c) { if(!c.GetParent()) return p; diff --git a/bazaar/RectCtrl/RectCtrl.cpp b/bazaar/RectCtrl/RectCtrl.cpp index d7a92a754..6b36d4cf3 100644 --- a/bazaar/RectCtrl/RectCtrl.cpp +++ b/bazaar/RectCtrl/RectCtrl.cpp @@ -134,8 +134,8 @@ Image RectCtrl::SetCursor(unsigned m, dword keyflags, const Image& old) case RIGHT: return OverrideCursor(Img::lr()); case TOP: return OverrideCursor(Img::tb()); - case ALL: return OverrideCursor(Img::mv()); case CENTER: return OverrideCursor(Img::fr()); + case ALL: if(keyflags & K_MOUSELEFT) return OverrideCursor(Img::mv()); //fall through default: OverrideCursor(old); return Null; } @@ -181,15 +181,23 @@ void RectCtrl::MouseMove(Point p, dword keyflags) moving = true; pressed = (keyflags & K_MOUSELEFT); - //int m = GetMode(r, p, keyflags, style->handsize); - //SetCursor(m, keyflags); + if(pressed && mode != NONE) { r = xr; CalcRect(r, p-xp, keyflags, mode, g); - r.Normalize(); + r.Normalize(); //if flipped UpdateActionRefresh(); } + else + { + int m = GetMode(r, p, keyflags, style->handsize); + if(m != mode) + { + mode = m; + c = SetCursor(mode, keyflags, c); + } + } } void RectCtrl::LeftUp(Point p, dword keyflags)