mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-17 06:06:00 -06:00
363 lines
8.4 KiB
C++
363 lines
8.4 KiB
C++
#include "CtrlPos.h"
|
|
|
|
void CtrlPos::DrawAlignHandle(Draw& w, const Rect& _r, const Rect& r, const Ctrl::LogPos& pos, const Color& col)
|
|
{
|
|
Point p;
|
|
bool q;
|
|
Size rz = r.GetSize();
|
|
Color col2 = Blend(col, Black);
|
|
|
|
p = r.CenterLeft();
|
|
p.y -= rz.cy/4;
|
|
q = (pos.x.GetAlign()&Ctrl::LEFT);
|
|
w.DrawLine(p, Point(_r.left, p.y), (q)?(PEN_SOLID):(PEN_DOT), (q)?(col):(col2));
|
|
|
|
p = r.CenterRight();
|
|
p.y += rz.cy/4;
|
|
q = (pos.x.GetAlign()&Ctrl::RIGHT);
|
|
w.DrawLine(p, Point(_r.right, p.y), (q)?(PEN_SOLID):(PEN_DOT), (q)?(col):(col2));
|
|
|
|
p = r.TopCenter();
|
|
p.x -= rz.cx/4;
|
|
q = (pos.y.GetAlign()&Ctrl::TOP);
|
|
w.DrawLine(p, Point(p.x, _r.top), (q)?(PEN_SOLID):(PEN_DOT), (q)?(col):(col2));
|
|
|
|
p = r.BottomCenter();
|
|
p.x += rz.cx/4;
|
|
q = (pos.y.GetAlign()&Ctrl::BOTTOM);
|
|
w.DrawLine(p, Point(p.x, _r.bottom), (q)?(PEN_SOLID):(PEN_DOT), (q)?(col):(col2));
|
|
}
|
|
|
|
bool CtrlPos::GetAlignMode(const Rect& _r, const Rect& r, const Point& pp, Ctrl::LogPos& pos, int handsize)
|
|
{
|
|
int size = handsize+2;
|
|
Rect c;
|
|
Point p;
|
|
int q;
|
|
Size rz = r.GetSize();
|
|
|
|
q = pos.x.GetAlign();
|
|
|
|
p = r.CenterLeft();
|
|
p.y -= rz.cy/4;
|
|
c = Rect(p, Point(_r.left, p.y)); c.InflateVert(size); c.Normalize();
|
|
if(c.Contains(pp)) { q&= ~Ctrl::LEFT; q|= (pos.x.GetAlign()&Ctrl::LEFT)?(0):(Ctrl::LEFT); pos.x.SetAlign(q); return true; }
|
|
|
|
p = r.CenterRight();
|
|
p.y += rz.cy/4;
|
|
c = Rect(p, Point(_r.right, p.y)); c.InflateVert(size); c.Normalize();
|
|
if(c.Contains(pp)) { q&= ~Ctrl::RIGHT; q|= (pos.x.GetAlign()&Ctrl::RIGHT)?(0):(Ctrl::RIGHT); pos.x.SetAlign(q); return true; }
|
|
|
|
q = pos.y.GetAlign();
|
|
|
|
p = r.TopCenter();
|
|
p.x -= rz.cx/4;
|
|
c = Rect(p, Point(p.x, _r.top)); c.InflateHorz(size); c.Normalize();
|
|
if(c.Contains(pp)) { q&= ~Ctrl::TOP; q|= (pos.y.GetAlign()&Ctrl::TOP)?(0):(Ctrl::TOP); pos.y.SetAlign(q); return true; }
|
|
|
|
p = r.BottomCenter();
|
|
p.x += rz.cx/4;
|
|
c = Rect(p, Point(p.x, _r.bottom)); c.InflateHorz(size); c.Normalize();
|
|
if(c.Contains(pp)) { q&= ~Ctrl::BOTTOM; q|= (pos.y.GetAlign()&Ctrl::BOTTOM)?(0):(Ctrl::BOTTOM); pos.y.SetAlign(q); return true; }
|
|
|
|
return false;
|
|
}
|
|
|
|
void CtrlPos::DrawHintFrame(Draw& w, const Ctrl& g, const Ctrl& q, const Color& hintcol)
|
|
{
|
|
Ctrl* c = q.GetFirstChild();
|
|
while(c)
|
|
{
|
|
Ctrl* e(c);
|
|
Point p; p.Clear();
|
|
int f(flags);
|
|
filter(e, p, 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.Inflate(1);
|
|
RectCtrl::DrawHandleFrame(w, r, hintcol, 1);
|
|
}
|
|
if(f & CtrlFinder::DEEP)
|
|
DrawHintFrame(w, g, *c, hintcol);
|
|
c = c->GetNext();
|
|
}
|
|
}
|
|
|
|
void CtrlPos::Paint(Draw& w)
|
|
{
|
|
Size sz = GetSize();
|
|
|
|
if(!IsTransparent())
|
|
w.DrawRect(0,0,sz.cx,sz.cy, SColorFace());
|
|
|
|
if(!IsEnabled()) return;
|
|
|
|
if(pctrl)
|
|
DrawHintFrame(w, *pctrl, *pctrl, LtGray());
|
|
|
|
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);
|
|
}
|
|
|
|
void CtrlPos::LeftDown(Point p, dword keyflags)
|
|
{
|
|
if(IsReadOnly() || !IsEnabled()) return;
|
|
|
|
SetCapture();
|
|
moving = false;
|
|
pressed = (keyflags & K_MOUSELEFT);
|
|
|
|
if(ctrl)
|
|
{
|
|
Ctrl& c = *ctrl;
|
|
//if already found prepare moving
|
|
ASSERT(!c.InFrame());
|
|
xpos = c.GetPos();
|
|
xp = p;
|
|
|
|
Rect r = c.GetRect();
|
|
Rect _r = c.GetParent()->GetView();
|
|
|
|
if(c.InView())
|
|
r.Offset(_r.TopLeft());
|
|
Point op = CtrlMover::GetOffset(*c.GetParent(), *pctrl);
|
|
r.Offset(op);
|
|
_r.Offset(op);
|
|
|
|
Ctrl::LogPos pos = xpos;
|
|
Rect rr(r); rr.Inflate(style->handsize+2);
|
|
|
|
if(GetAlignMode(_r, rr, p, pos, style->handsize))
|
|
{
|
|
pos = LogPosPopUp::MakeLogPos(pos, c);
|
|
c.SetPos(pos);
|
|
Action();
|
|
Refresh();
|
|
return;
|
|
}
|
|
else if((mode = RectCtrl::GetMode(r, p, keyflags, style->handsize)) != RectCtrl::NONE)
|
|
{
|
|
ci = RectCtrl::SetCursor(mode, keyflags, ci);
|
|
Refresh();
|
|
return;
|
|
}
|
|
}
|
|
|
|
if(pctrl)
|
|
{
|
|
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();
|
|
}
|
|
|
|
Refresh();
|
|
}
|
|
|
|
void CtrlPos::MouseMove(Point p, dword keyflags)
|
|
{
|
|
if(IsReadOnly() || !IsEnabled()) return;
|
|
|
|
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(pressed && mode != RectCtrl::NONE)
|
|
{
|
|
if(keyflags & K_ALT)
|
|
{
|
|
Ctrl* q = c.GetParent();
|
|
Ctrl* prevc = c.GetPrev();
|
|
|
|
//calculate some things not accessible when Removed()
|
|
|
|
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);
|
|
|
|
c.Remove(); //prevent moving control 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);
|
|
}
|
|
else
|
|
q->AddChild(&c, prevc); //undo Remove();
|
|
}
|
|
|
|
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);
|
|
Action();
|
|
Refresh();
|
|
}
|
|
}
|
|
|
|
void CtrlPos::LeftUp(Point p, dword keyflags)
|
|
{
|
|
ReleaseCapture();
|
|
pressed = false;
|
|
moving = false;
|
|
//xpos.SetNull();
|
|
xp.SetNull();
|
|
mode = RectCtrl::NONE;
|
|
if(IsReadOnly() || !IsEnabled()) return;
|
|
|
|
ci = RectCtrl::SetCursor(mode, keyflags, ci);
|
|
Refresh();
|
|
}
|
|
|
|
void CtrlPos::RightDown(Point p, dword keyflags)
|
|
{
|
|
//cancel
|
|
if(!(keyflags & K_SHIFT))
|
|
LeftDown(p, keyflags);
|
|
ReleaseCapture();
|
|
int m = mode;
|
|
mode = RectCtrl::NONE;
|
|
if(IsReadOnly() || !IsEnabled()) return;
|
|
|
|
ci = RectCtrl::SetCursor(mode, keyflags, ci);
|
|
if(!GetCtrl()) return;
|
|
|
|
if(pressed)
|
|
{
|
|
if(m != RectCtrl::NONE)
|
|
{
|
|
GetCtrl()->SetPos(xpos);
|
|
Action();
|
|
Refresh();
|
|
}
|
|
}
|
|
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);
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
}
|
|
|
|
void CtrlPos::LeftDouble(Point p, dword flags)
|
|
{
|
|
//LeftDown already called
|
|
WhenLeftDouble();
|
|
}
|
|
|
|
bool CtrlPos::Key(dword key, int count)
|
|
{
|
|
if(key == K_SPACE)
|
|
{
|
|
ClearCtrl();
|
|
Action();
|
|
Refresh();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void CtrlPos::Updated()
|
|
{
|
|
//refresh the view of the currently selected ctrl
|
|
CtrlFinder::Updated();
|
|
}
|
|
|
|
CtrlPos::CtrlPos()
|
|
: pressed(false), moving(false), mode(RectCtrl::NONE), g(4,4)
|
|
{
|
|
BackPaint();
|
|
NoIgnoreMouse();
|
|
style = &RectCtrl::StyleDefault();
|
|
//xpos.SetNull();
|
|
xp.SetNull();
|
|
}
|