mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-07-11 22:03:01 -06:00
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:
parent
55a4171b21
commit
a49d80d46d
21 changed files with 703 additions and 226 deletions
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef _CtrlFinder_icpp_init_stub
|
||||
#define _CtrlFinder_icpp_init_stub
|
||||
#include "CtrlLib/init"
|
||||
#include "Gen/init"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@ description "example how to change Ctrl LogPos in a live environment\377";
|
|||
|
||||
uses
|
||||
CtrlLib,
|
||||
CtrlPos;
|
||||
CtrlPos,
|
||||
AutoScroller;
|
||||
|
||||
file
|
||||
CtrlPosTest.h,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue