bazaar: Major CtrlFinder/CtrlMover/CtrlPos fixes/changes and support for multiple controls find, marked with a RectTrack

added some comments for LogPosCtrl, some small fixes in RectCtrl

git-svn-id: svn://ultimatepp.org/upp/trunk@5426 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
kohait 2012-10-13 22:12:43 +00:00
parent 55a4171b21
commit a49d80d46d
21 changed files with 703 additions and 226 deletions

View file

@ -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<Ctrl*> CtrlFinder::ChildrenInRect(Ctrl& par, Rect& rect, int& f, const CtrlFilterType& filt)
{
GuiLock __;
Vector<Ctrl*> 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<Ctrl*> CtrlFinder::GetCtrls(Ctrl& c, Rect& rect, int& f, const CtrlFilterType& filt)
{
Vector<Ctrl*> 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<Ctrl*>& 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);
}

View file

@ -9,7 +9,7 @@ class CtrlFinder : public ParentCtrl
{
public:
typedef CtrlFinder CLASSNAME;
typedef Callback3<Ctrl*&, Point&, int&> CtrlFilterType;
typedef Callback2<Ctrl*&, int&> 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<Ctrl*>& _ctrls) { ctrls = _ctrls; Update(); }
virtual Value GetData() const { return RawToValue(ctrl); }
virtual void SetData(const Value& v) { SetCtrl(RawValue<Ctrl*>::Extract(v)); }
Ctrl* GetCtrl() const { return ctrls.IsEmpty() ? NULL : ctrls.Top(); }
Vector<Ctrl*> GetCtrls() const { return Vector<Ctrl*>(ctrls, 1); }
bool IsEmpty() const { return ctrls.IsEmpty(); }
void ClearCtrl() { ctrls.Clear(); Update(); }
virtual Value GetData() const { return RawPickToValue(Vector<Ctrl*>(ctrls, 1)); }
virtual void SetData(const Value& v) { SetCtrls(Vector<Ctrl*>(RawValue<Vector<Ctrl*> >::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<Ctrl*> ChildrenInRect(Ctrl& par, Rect& rect, int& f, const CtrlFilterType& filt);
static Vector<Ctrl*> GetCtrls(Ctrl& c, Rect& rect, int& f, const CtrlFilterType& filt);
static bool IsParentR(const Ctrl* p, const Ctrl* c);
Callback3<Ctrl&, Point, dword> WhenLeftDown;
Callback3<Ctrl&, Point, dword> 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<Ctrl*>& ctrls);
Callback3<Ctrl&, Point, dword> WhenLeftSelect;
Callback3<Ctrl&, Point, dword> WhenRightSelect;
Callback3<const Vector<Ctrl*>*, Rect, dword> WhenLeftSelectMulti;
Callback3<const Vector<Ctrl*>*, Rect, dword> WhenRightSelectMulti;
Callback1<Bar&> 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<Ctrl*> ctrls; //the current found children
};
#endif

View file

@ -1,5 +1,4 @@
#ifndef _CtrlFinder_icpp_init_stub
#define _CtrlFinder_icpp_init_stub
#include "CtrlLib/init"
#include "Gen/init"
#endif

View file

@ -25,6 +25,7 @@ public:
void ToInfo(const String& s);
void OnSelect(Ctrl& c, Point p, dword keyflags);
void OnSelectMulti(const Vector<Ctrl*>* pctrls, Rect r, dword keyflags);
WithCtrlFinderTestLayout<ParentCtrl> vis;
FrameLeft<WithLeftBarLay<ParentCtrl> > sb;

View file

@ -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)

View file

@ -13,6 +13,16 @@ void CtrlFinderTest::OnSelect(Ctrl& c, Point p, dword keyflags)
ToInfo(inf);
}
void CtrlFinderTest::OnSelectMulti(const Vector<Ctrl*>* 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);
}

View file

@ -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<Ctrl*>* 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);

View file

@ -19,12 +19,10 @@ public:
virtual void Updated();
void OnCtrlLeft(Ctrl& c, Point p, dword keyflags);
void OnCtrlLeftMulti(const Vector<Ctrl*>* 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();

View file

@ -26,6 +26,7 @@ public:
void ToInfo(const String& s);
void OnSelect(Ctrl& c, Point p, dword keyflags);
void OnSelectMulti(const Vector<Ctrl*>* pctrls, Rect r, dword keyflags);
AutoScroller<ParentCtrl> sc;

View file

@ -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)

View file

@ -14,6 +14,17 @@ void CtrlMoverTest::OnSelect(Ctrl& c, Point p, dword keyflags)
hk.OnCtrlLeft(c, p, keyflags);
}
void CtrlMoverTest::OnSelectMulti(const Vector<Ctrl*>* 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);
}

View file

@ -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<Ctrl*>& c, pick_ Vector<Ctrl*> _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<Ctrl*>& c, pick_ Vector<Ctrl*> _c)
{
//top is the currently editable ctrl
//first, we remove every duplicate, before we take everything else
CombineSubtract(c, Vector<Ctrl*>(_c, 1)); //deep copy to keep our copy
c.Append(_c);
}
void CtrlPos::DrawSelected(Draw& w, const Vector<Ctrl*>& 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<Ctrl*> _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<Ctrl*> _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<Ctrl*> _xpars;
Vector<Ctrl*> _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();
}

View file

@ -8,9 +8,6 @@ using namespace Upp;
#include <LogPosCtrl/LogPosCtrl.h>
#include <CtrlFinder/CtrlFinder.h>
//for some helpers
#include <CtrlMover/CtrlMover.h>
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<Ctrl*>& c, pick_ Vector<Ctrl*> _c);
void CombineSubtract(Vector<Ctrl*>& c, pick_ Vector<Ctrl*> _c);
Callback WhenLeftDouble;
protected:
void DrawSelected(Draw& w, const Vector<Ctrl*>& 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<Ctrl::LogPos> xpos;
Vector<Ctrl*> xpars;
Vector<Point> xop;
Vector<Rect> xr;
//Rect rd; //debug
//Rect rd2; //debug
int mode;
bool pressed;
bool moving;

View file

@ -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"

View file

@ -9,6 +9,7 @@ using namespace Upp;
#include <CtrlCore/lay.h>
#include <CtrlPos/CtrlPos.h>
#include <AutoScroller/AutoScroller.h>
class CtrlPosTest : public TopWindow {
public:
@ -28,6 +29,8 @@ public:
void ToInfo(const String& s);
void OnSelect(Ctrl& c, Point p, dword keyflags);
AutoScroller<ParentCtrl> sc;
WithCtrlPosTestLayout<ParentCtrl> vis;
FrameLeft<WithLeftBarLay<ParentCtrl> > sb;
CtrlPos hk;

View file

@ -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)

View file

@ -2,7 +2,8 @@ description "example how to change Ctrl LogPos in a live environment\377";
uses
CtrlLib,
CtrlPos;
CtrlPos,
AutoScroller;
file
CtrlPosTest.h,

View file

@ -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

View file

@ -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();
}

View file

@ -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;

View file

@ -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)