mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-17 06:06:00 -06:00
890 lines
18 KiB
C++
890 lines
18 KiB
C++
#include "DockCtrl/DockCtrl.h"
|
|
|
|
#define IMAGECLASS DockCtrlImgs
|
|
#define IMAGEFILE <DockCtrl/DockableCtrl.iml>
|
|
#include <Draw/iml_source.h>
|
|
|
|
|
|
void DockCtrlCustomFrame::FrameLayout(Rect& r)
|
|
{
|
|
switch(layout)
|
|
{
|
|
case LAYOUT_LEFT:
|
|
LayoutFrameLeft(r, this, size);
|
|
break;
|
|
case LAYOUT_TOP:
|
|
LayoutFrameTop(r, this, size);
|
|
break;
|
|
case LAYOUT_RIGHT:
|
|
LayoutFrameRight(r, this, size);
|
|
break;
|
|
case LAYOUT_BOTTOM:
|
|
LayoutFrameBottom(r, this, size);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void DockCtrlCustomFrame::FrameAddSize(Size& sz)
|
|
{
|
|
switch(layout)
|
|
{
|
|
case LAYOUT_LEFT:
|
|
sz.cx += size;
|
|
break;
|
|
case LAYOUT_TOP:
|
|
sz.cy += size;
|
|
break;
|
|
case LAYOUT_RIGHT:
|
|
sz.cx += size;
|
|
break;
|
|
case LAYOUT_BOTTOM:
|
|
sz.cy += size;
|
|
break;
|
|
}
|
|
}
|
|
|
|
DockCtrlCustomFrame& DockCtrlCustomFrame::SetStyle(const DockCtrlChStyle::Style& s)
|
|
{
|
|
style = &s;
|
|
return *this;
|
|
}
|
|
|
|
const DockCtrlChStyle::Style* DockCtrlCustomFrame::GetStyle()
|
|
{
|
|
return style ? style : &DockCtrlChStyle::StyleDefault();
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------
|
|
|
|
void TabInterface::Add(String name, bool activate)
|
|
{
|
|
Tab &t = tabs.Add();
|
|
if(IsNull(name) || name == t_("")) name = t_("Untitled");
|
|
else t.name = name;
|
|
t.id = GetNextId();
|
|
t.active = activate;
|
|
t.visible = true;
|
|
t.highlighted = false;
|
|
t.icon = DockCtrlImgs::DefaultImage();
|
|
ReposTabs();
|
|
SetActiveTab(tabs.GetCount() - 1);
|
|
}
|
|
|
|
void TabInterface::Add(DockableCtrl& dock, bool activate)
|
|
{
|
|
Tab &t = tabs.Add();
|
|
if(dock.GetLabel().IsVoid() || dock.GetLabel() == t_("")) t.name = t_("Untitled");
|
|
else t.name = dock.GetLabel();
|
|
t.id = GetNextId();
|
|
t.active = activate;
|
|
t.visible = true;
|
|
t.highlighted = false;
|
|
t.icon = dock.GetIcon();
|
|
t.dock = &dock;
|
|
ReposTabs();
|
|
SetActiveTab(tabs.GetCount() - 1);
|
|
}
|
|
|
|
void TabInterface::Remove(DockableCtrl& dock)
|
|
{
|
|
}
|
|
|
|
void TabInterface::Remove(int n)
|
|
{
|
|
}
|
|
|
|
void TabInterface::Close(int n)
|
|
{
|
|
if(tabs.GetCount() < 1 || n >= tabs.GetCount()) // !!!
|
|
return;
|
|
int c = Find(tabs[n].id);
|
|
int nc = GetNext(c);
|
|
if(nc < 0)
|
|
nc = max(0, GetPrev(c));
|
|
|
|
if(hasscrollbar) scrollbar.AddTotal(-tabs[n].cx);
|
|
tabs.Remove(n);
|
|
ReposTabs();
|
|
SetActiveTab(nc);
|
|
}
|
|
|
|
void TabInterface::CloseAll()
|
|
{
|
|
for(int i = tabs.GetCount() - 1; i >= 0; i--)
|
|
{
|
|
tabs.At(i).dock = NULL;
|
|
tabs.At(i).id = -1;
|
|
tabs.Remove(i);
|
|
}
|
|
if(hasscrollbar) scrollbar.SetTotal(0);//scrollbar.SetTotal(tabs[0].cx);
|
|
ReposTabs();
|
|
SetActiveTab(-1);
|
|
id = -1;
|
|
}
|
|
|
|
void TabInterface::SetActiveTab(int n)
|
|
{
|
|
int tabcount = tabs.GetCount();
|
|
|
|
if(tabcount == 0)
|
|
return;
|
|
|
|
if(n < 0 || n >= tabcount)
|
|
n = max(0, tabcount - 1);
|
|
|
|
Tab& t = tabs[active = n];
|
|
int cx = t.x - (int(hasscrollbar) * scrollbar.GetPos());
|
|
if(hasscrollbar)
|
|
{
|
|
if(cx < 0)
|
|
scrollbar.AddPos(cx - 10);
|
|
else
|
|
{
|
|
cx = t.x + t.cx - GetSize().cx - scrollbar.GetPos();
|
|
if(cx > 0)
|
|
scrollbar.AddPos(cx + 10);
|
|
}
|
|
}
|
|
if(HasMouse())MouseMove(GetMouseViewPos(), 0);
|
|
UpdateActionRefresh();
|
|
WhenSelect();
|
|
}
|
|
|
|
void TabInterface::SetActiveTab(DockableCtrl& dock)
|
|
{
|
|
SetActiveTab(Find(dock));
|
|
}
|
|
|
|
void TabInterface::SetActiveTabTitle(String name, Image icon)
|
|
{
|
|
if(active < 0) return;
|
|
Tab& t = tabs.At(active);
|
|
t.name = name;
|
|
t.icon = icon;
|
|
ReposTabs();
|
|
}
|
|
|
|
TabInterface& TabInterface::HasScrollBar(bool b)
|
|
{
|
|
if(b)
|
|
{
|
|
AddFrame(scrollbar);
|
|
scrollbar.WhenScroll = THISBACK(OnScrollBar);
|
|
}
|
|
else
|
|
RemoveFrame(scrollbar);
|
|
Refresh();
|
|
hasscrollbar = b;
|
|
return *this;
|
|
}
|
|
|
|
int TabInterface::GetActiveTab()
|
|
{
|
|
return active;
|
|
}
|
|
|
|
int TabInterface::Find(int itemid)
|
|
{
|
|
for(int i = 0; i < tabs.GetCount(); i++)
|
|
if(tabs[i].id == itemid) return i;
|
|
return -1;
|
|
}
|
|
|
|
int TabInterface::Find(DockableCtrl& dock)
|
|
{
|
|
for(int i = 0; i < tabs.GetCount(); i++)
|
|
if(tabs[i].dock == &dock) return i;
|
|
return -1;
|
|
}
|
|
|
|
int TabInterface::GetNext(int n)
|
|
{
|
|
for(int i = n + 1; i < tabs.GetCount(); i++)
|
|
if(tabs[i].visible) return i;
|
|
return -1;
|
|
}
|
|
|
|
int TabInterface::GetPrev(int n)
|
|
{
|
|
for(int i = n - 1; i >= 0; i--)
|
|
if(tabs[i].visible) return i;
|
|
return -1;
|
|
}
|
|
|
|
|
|
int TabInterface::GetWidth(int n)
|
|
{
|
|
Tab &t = tabs[n];
|
|
t.textsize = GetTextSize(t.name, style->font);
|
|
return TAB_MARGIN * 2 + t.textsize.cx + ((hasfileicon ? TAB_SPACE : TAB_SPACE / 2) + DockCtrlImgs::DClose().GetSize().cx) * hastabbutton + (TAB_FILEICON + TAB_SPACEICON) * hasfileicon;
|
|
}
|
|
|
|
int TabInterface::GetWidth()
|
|
{
|
|
return tabs[tabs.GetCount() - 1].Right() + style->margin * 2;
|
|
}
|
|
|
|
int TabInterface::GetHeight()
|
|
{
|
|
return style->tabheight + style->sel.bottom + (int(hasscrollbar) * (TAB_SBHEIGHT + TAB_SBSEPARATOR));
|
|
}
|
|
|
|
void TabInterface::ReposTabs()
|
|
{
|
|
if(!tabs.GetCount())
|
|
return;
|
|
|
|
int j = 0;
|
|
bool first = true;
|
|
for(int i = 0; i < tabs.GetCount(); i++)
|
|
{
|
|
tabs[i].x = first ? 0 : tabs[j].Right();
|
|
j = i;
|
|
first = false;
|
|
tabs[i].visible = true;
|
|
tabs[i].y = 0;
|
|
tabs[i].cx = GetWidth(i);
|
|
tabs[i].cy = style->tabheight + style->sel.top;
|
|
}
|
|
if(hasscrollbar) scrollbar.SetTotal(GetWidth());
|
|
}
|
|
|
|
void TabInterface::DrawLabel(Draw& w, int x, int y, Tab& t, bool isactive)
|
|
{
|
|
String fn = GetFileName(t.name);
|
|
|
|
if(horizontal)
|
|
DrawFileName(w, x + TAB_MARGIN + (TAB_FILEICON + TAB_SPACEICON) * int(hasfileicon), (y - t.textsize.cy) / 2,
|
|
t.textsize.cx, t.textsize.cy, fn.ToWString(),
|
|
false, StdFont(), Black, LtBlue,
|
|
Null, Null, false);
|
|
else
|
|
w.DrawText((y + t.textsize.cy) / 2 + 1,
|
|
x + TAB_MARGIN + (TAB_FILEICON + TAB_SPACEICON) * int(hasfileicon),
|
|
2700, fn.ToWString(),
|
|
style->font);
|
|
}
|
|
|
|
void TabInterface::DrawTab(Draw& w, Size &sz, int i)
|
|
{
|
|
Size isz = DockCtrlImgs::DClose().GetSize();
|
|
int cnt = tabs.GetCount();
|
|
Tab &t = tabs[i];
|
|
|
|
bool ac = i == active;
|
|
bool hl = i == highlight;
|
|
|
|
int lx = i > 0 ? style->extendleft : 0;
|
|
int x = t.x - (hasscrollbar ? scrollbar.GetPos() : 0) + style->margin - lx;
|
|
|
|
int ndx = !IsEnabled() ? CTRL_DISABLED :
|
|
ac ? CTRL_PRESSED :
|
|
hl ? CTRL_HOT : CTRL_NORMAL;
|
|
|
|
Image nimg;
|
|
|
|
int cx = t.cx + lx + (ac ? style->sel.right + style->sel.left : 0);
|
|
int cy = ac ? t.cy - style->sel.top + style->sel.bottom : t.cy - style->sel.top;
|
|
|
|
int h = style->sel.top + style->sel.bottom;
|
|
int hs = ac ? 0 : h;
|
|
if(layout == LAYOUT_RIGHT || layout == LAYOUT_BOTTOM)
|
|
hs = -hs;
|
|
|
|
ImageDraw img(cx, cy);
|
|
|
|
img.DrawRect(0, 0, cx, cy, SColorFace);
|
|
|
|
|
|
const Value& sv = (cnt == 1 ? style->both : i == 0 ? style->first : i == cnt - 1 ? style->last : style->normal)[ndx];
|
|
|
|
ChPaint(img, 0, 0, cx, cy, sv);
|
|
|
|
if(hastabbutton && tabs.GetCount())
|
|
img.DrawImage(t.cx - isz.cx - TAB_MARGIN,
|
|
(cy + h - isz.cy) / 2,
|
|
(ac || hl) ? (tabbutton == i ? DockCtrlImgs::DCloseh :
|
|
ac ? DockCtrlImgs::DCloses : DockCtrlImgs::DClose) :
|
|
DockCtrlImgs::DClose);
|
|
|
|
if(hasfileicon)
|
|
img.DrawImage(TAB_MARGIN, (cy + h - t.icon.GetSize().cx) / 2, t.icon);
|
|
|
|
int shift = 0;
|
|
switch(layout)
|
|
{
|
|
case LAYOUT_LEFT:
|
|
nimg = MirrorVert(RotateAntiClockwise(img));
|
|
break;
|
|
case LAYOUT_TOP:
|
|
nimg = img;
|
|
break;
|
|
case LAYOUT_RIGHT:
|
|
nimg = RotateClockwise(img);
|
|
shift = TAB_SBSEPARATOR;
|
|
break;
|
|
case LAYOUT_BOTTOM:
|
|
nimg = MirrorVert(img);
|
|
shift = TAB_SBSEPARATOR;
|
|
break;
|
|
}
|
|
|
|
if(ac)
|
|
w.DrawImage(horizontal ? x - style->sel.left : shift,
|
|
horizontal ? shift : x - style->sel.left,
|
|
nimg);
|
|
else
|
|
w.DrawImage(horizontal ? x : style->sel.left - shift,
|
|
horizontal ? style->sel.top - shift : x,
|
|
nimg);
|
|
|
|
DrawLabel(w, x, cy + hs, t, ac);
|
|
}
|
|
|
|
void TabInterface::Paint(Draw& d)
|
|
{
|
|
Size sz = GetSize();
|
|
d.DrawRect(sz, SColorFace());
|
|
|
|
if(!horizontal)
|
|
d.DrawRect(layout == LAYOUT_LEFT ? sz.cx - 1: 0, 0,
|
|
1, sz.cy, LtGray());
|
|
else
|
|
d.DrawRect(0, layout == LAYOUT_TOP ? sz.cy - 1 : 0,
|
|
sz.cx, 1, LtGray());
|
|
|
|
Fix(sz);
|
|
|
|
int tabcount = tabs.GetCount();
|
|
|
|
for(int i = 0; i < tabcount; i++)
|
|
if(tabs[i].IsVisible() && active != i && i < tabcount)
|
|
DrawTab(d, sz, i);
|
|
|
|
if(active >= 0 && active < tabcount)
|
|
DrawTab(d, sz, active);
|
|
|
|
if(target >= 0)
|
|
{
|
|
int last = tabs.GetCount() - 1;
|
|
int first = 0;
|
|
|
|
if(target != active && target != active + 1)
|
|
{
|
|
|
|
int x = (target == last + 1 ? tabs[last].Right() : tabs[target].x)
|
|
- (hasscrollbar ? scrollbar.GetPos() : 0) - (target <= first ? 1 : 2)
|
|
+ style->margin - (target > 0 ? style->extendleft : 0);
|
|
|
|
int y = style->sel.top;
|
|
|
|
int cy = sz.cy - y;
|
|
|
|
Color c(255, 0, 0);
|
|
|
|
if(horizontal)
|
|
{
|
|
d.DrawRect(x + 1, y, 2, cy, c);
|
|
d.DrawRect(x, y, 4, 1, c);
|
|
d.DrawRect(x, y + cy - 1, 4, 1, c);
|
|
}
|
|
else
|
|
{
|
|
Swap(x, y);
|
|
d.DrawRect(x, y + 1, cy, 2, c);
|
|
d.DrawRect(x, y, 1, 4, c);
|
|
d.DrawRect(x + cy - 1, y, 1, 4, c);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void TabInterface::LeftDown(Point p, dword keyflags)
|
|
{
|
|
if(keyflags & K_SHIFT)
|
|
{
|
|
highlight = -1;
|
|
Refresh();
|
|
SetCapture();
|
|
oldp = p;
|
|
return;
|
|
}
|
|
|
|
isctrl = keyflags & K_CTRL;
|
|
if(isctrl)
|
|
return;
|
|
|
|
if(tabbutton >= 0)
|
|
{
|
|
int i = Find(tabbutton);
|
|
if(i == -1 && active >= 0)
|
|
i = active;
|
|
|
|
if(i >= 0)
|
|
{
|
|
DockableCtrl* dock = tabs[i].dock;
|
|
if(dock)
|
|
WhenClose(tabbutton, *dock);
|
|
}
|
|
}
|
|
|
|
if(highlight >= 0)
|
|
{
|
|
SetActiveTab(highlight);
|
|
if(active >= 0)
|
|
WhenActive(active, *tabs[active].dock);
|
|
}
|
|
}
|
|
|
|
void TabInterface::LeftUp(Point p, dword keyflags)
|
|
{
|
|
ReleaseCapture();
|
|
}
|
|
|
|
void TabInterface::MiddleDrag(Point p, dword keyflags)
|
|
{
|
|
if(!isdraggable) return;
|
|
isdragged = true;
|
|
DoDragAndDrop(InternalClip(*this, Format(internalname, this)));
|
|
}
|
|
|
|
void TabInterface::LeftDrag(Point p, dword keyflags)
|
|
{
|
|
if(keyflags & K_SHIFT)
|
|
return;
|
|
if(highlight < 0)
|
|
return;
|
|
|
|
if(isctrl)
|
|
{
|
|
isdragged = true;
|
|
DoDragAndDrop(InternalClip(*this, Format(internalname, this)));
|
|
return;
|
|
}
|
|
|
|
if(highlight >= 0)
|
|
{
|
|
Fix(p);
|
|
SetActiveTab(highlight);
|
|
p.x += (int(hasscrollbar) * scrollbar.GetPos());
|
|
if(tabs[active].HasMouse(p))
|
|
WhenDrag(active, *tabs[active].dock);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void TabInterface::RightDown(Point p, dword keyflags)
|
|
{
|
|
if(highlight >= 0)
|
|
SetActiveTab(highlight);
|
|
WhenContext(active, *tabs[active].dock);
|
|
}
|
|
|
|
void TabInterface::RightUp(Point p, dword keyflags)
|
|
{
|
|
}
|
|
|
|
|
|
void TabInterface::MouseMove(Point p, dword keyflags)
|
|
{
|
|
Fix(p);
|
|
if(HasCapture() && hasscrollbar)
|
|
{
|
|
scrollbar.AddPos(p.x - oldp.x, true);
|
|
oldp = p;
|
|
return;
|
|
}
|
|
|
|
p.x += (int(hasscrollbar) * scrollbar.GetPos()) - style->margin + style->extendleft;
|
|
Size sz = GetSize();
|
|
Fix(sz);
|
|
int h = highlight;
|
|
bool istabbutton = false;
|
|
bool istab = false;
|
|
for(int i = 0; i < tabs.GetCount(); i++)
|
|
{
|
|
if(tabs[i].HasMouse(p))
|
|
{
|
|
istab = true;
|
|
//int h = sz.cy + (active == i ? 0 : style->sel.top);
|
|
int h = style->sel.top + style->sel.bottom;
|
|
int hs = active == i ? style->sel.top : h;
|
|
if(layout == LAYOUT_RIGHT || layout == LAYOUT_BOTTOM)
|
|
hs = -hs;
|
|
hs += sz.cy;
|
|
int ws = active == i ? style->sel.left : 0;
|
|
istabbutton = hastabbutton ? tabs[i].HasMouseButton(p, ws, hs) : false;
|
|
if(highlight != i || (istabbutton && tabbutton != i))
|
|
{
|
|
tabbutton = istabbutton ? i : -1;
|
|
highlight = i;
|
|
WhenHighlight();
|
|
Refresh();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!istab && h >= 0)
|
|
{
|
|
highlight = -1;
|
|
WhenHighlight();
|
|
Refresh();
|
|
}
|
|
|
|
if(!istabbutton && tabbutton >= 0)
|
|
{
|
|
tabbutton = -1;
|
|
Refresh();
|
|
}
|
|
}
|
|
|
|
void TabInterface::MouseWheel(Point p, int zdelta, dword keyflags)
|
|
{
|
|
if(!hasscrollbar) return;
|
|
scrollbar.AddPos(-zdelta / 4, true);
|
|
MouseMove(p, 0);
|
|
}
|
|
|
|
|
|
void TabInterface::MouseLeave()
|
|
{
|
|
if(isdragged)
|
|
return;
|
|
highlight = -1;
|
|
tabbutton = -1;
|
|
Refresh();
|
|
}
|
|
|
|
int TabInterface::GetTargetTab(Point p)
|
|
{
|
|
Fix(p);
|
|
p.x += (hasscrollbar ? scrollbar.GetPos() : 0);
|
|
|
|
int f = 0;
|
|
int l = tabs.GetCount() - 1;
|
|
|
|
if(tabs[f].visible && p.x < tabs[f].x + tabs[f].cx / 2)
|
|
return f;
|
|
|
|
for(int i = l; i >= f; i--)
|
|
if(tabs[i].visible && p.x >= tabs[i].x + tabs[i].cx / 2)
|
|
return i == l ? i + 1 : GetNext(i);
|
|
return -1;
|
|
}
|
|
|
|
int TabInterface::GetSourceTab(Point p)
|
|
{
|
|
int cnt = tabs.GetCount();
|
|
if(((active >= 0 && active < cnt) || (highlight >= 0 && highlight < cnt)))
|
|
{
|
|
for(int i = tabs.GetCount() - 1; i >= 0; i--)
|
|
if(tabs[i].visible && tabs[i].HasMouse(p))
|
|
return (source = i);
|
|
}
|
|
return (source = highlight);
|
|
}
|
|
|
|
void TabInterface::DragAndDrop(Point p, PasteClip& d)
|
|
{
|
|
int c = GetTargetTab(p);
|
|
int tab = isctrl ? highlight : active;
|
|
if(tab == -1) return;
|
|
|
|
bool sametab = c == tab || c == tab + 1;
|
|
bool internal = AcceptInternal<TabInterface>(d, internalname);
|
|
|
|
if(!sametab && d.IsAccepted())
|
|
{
|
|
if(internal)
|
|
{
|
|
int id = tabs[active].id;
|
|
Tab t = tabs[tab];
|
|
tabs.Insert(c, t);
|
|
tabs.Remove(tab + int(c < tab));
|
|
active = Find(id);
|
|
isdragged = false;
|
|
ReposTabs();
|
|
return;
|
|
}
|
|
else if(d.IsPaste())
|
|
{
|
|
CancelMode();
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//d.Reject();
|
|
//unfortunately after Reject DragLeave stops working until d is accepted
|
|
}
|
|
|
|
if(c != target)
|
|
{
|
|
target = c;
|
|
Refresh();
|
|
}
|
|
}
|
|
|
|
void TabInterface::DragEnter()
|
|
{
|
|
}
|
|
|
|
void TabInterface::DragLeave()
|
|
{
|
|
target = -1;
|
|
Refresh();
|
|
}
|
|
|
|
void TabInterface::DragRepeat(Point p)
|
|
{
|
|
{
|
|
int dx = GetDragScroll(this, p, 16).x;
|
|
if(dx != 0 && hasscrollbar)
|
|
scrollbar.AddPos(dx);
|
|
}
|
|
}
|
|
|
|
void TabInterface::CancelMode()
|
|
{
|
|
isdragged = false;
|
|
target = -1;
|
|
Refresh();
|
|
}
|
|
|
|
|
|
TabInterface& TabInterface::SetLayout(int l)
|
|
{
|
|
DockCtrlCustomFrame::SetLayout(l);
|
|
switch(l)
|
|
{
|
|
case LAYOUT_LEFT:
|
|
horizontal = scrollbar.horizontal = false;
|
|
scrollbar.SetLayout(LAYOUT_RIGHT);
|
|
break;
|
|
case LAYOUT_TOP:
|
|
horizontal = scrollbar.horizontal = true;
|
|
scrollbar.SetLayout(LAYOUT_BOTTOM);
|
|
break;
|
|
case LAYOUT_RIGHT:
|
|
horizontal = scrollbar.horizontal = false;
|
|
scrollbar.SetLayout(LAYOUT_LEFT);
|
|
break;
|
|
case LAYOUT_BOTTOM:
|
|
horizontal = scrollbar.horizontal = true;
|
|
scrollbar.SetLayout(LAYOUT_TOP);
|
|
break;
|
|
}
|
|
RefreshLayout();
|
|
return *this;
|
|
}
|
|
|
|
TabInterface::TabInterface()
|
|
{
|
|
internalname = "tabs";
|
|
|
|
id = -1;
|
|
active = -1;
|
|
highlight = -1;
|
|
visible = -1;
|
|
fileicon = -1;
|
|
tabbutton = -1;
|
|
target = -1; // drag target.
|
|
source = -1; // drag source.
|
|
|
|
hasfileicon = false;
|
|
hastabbutton = true;
|
|
isdraggable = true;
|
|
isctrl = false;
|
|
isdragged = false;
|
|
|
|
SetStyle(TabCtrl::StyleDefault());
|
|
DockCtrlCustomFrame::layout = LAYOUT_BOTTOM;
|
|
HasScrollBar(true);
|
|
SetSize(GetHeight() + 2);
|
|
BackPaint();
|
|
}
|
|
|
|
TabInterface::~TabInterface()
|
|
{
|
|
for(int i = 0; i < tabs.GetCount(); i++)
|
|
tabs.Remove(i);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------
|
|
|
|
TabInterface::TabScrollBar::TabScrollBar()
|
|
{
|
|
DockCtrlCustomFrame::layout = LAYOUT_TOP;
|
|
DockCtrlCustomFrame::SetSize(TAB_SBHEIGHT);
|
|
|
|
total = 0;
|
|
pos = 0;
|
|
ps = 0;
|
|
start_pos = 0;
|
|
new_pos = 0;
|
|
old_pos = 0;
|
|
ready = false;
|
|
}
|
|
|
|
void TabInterface::TabScrollBar::Paint(Draw &w)
|
|
{
|
|
if(!ready)
|
|
{
|
|
UpdatePos();
|
|
ready = true;
|
|
}
|
|
Size sz = GetSize();
|
|
|
|
w.DrawRect(sz, SColorFace());
|
|
|
|
if(horizontal)
|
|
{
|
|
if(total > sz.cx)
|
|
w.DrawRect(ffloor(pos), 1, fceil(size), 2, Blue);
|
|
else
|
|
w.DrawRect(0, sz.cy - 1, sz.cx, 1, White);
|
|
}
|
|
else
|
|
{
|
|
if(total > sz.cy)
|
|
w.DrawRect(1, ffloor(pos), 2, fceil(size), Blue);
|
|
else
|
|
w.DrawRect(sz.cx - 1, 0, 1, sz.cy, White);
|
|
}
|
|
}
|
|
|
|
void TabInterface::TabScrollBar::LeftDown(Point p, dword keyflags)
|
|
{
|
|
SetCapture();
|
|
Fix(p);
|
|
old_pos = new_pos = p.x;
|
|
if(p.x < pos || p.x > pos + size)
|
|
start_pos = size / 2;
|
|
else
|
|
start_pos = UPP::tabs(p.x - pos);
|
|
UpdatePos();
|
|
Refresh();
|
|
}
|
|
|
|
void TabInterface::TabScrollBar::LeftUp(Point p, dword keyflags)
|
|
{
|
|
ReleaseCapture();
|
|
Fix(p);
|
|
old_pos = p.x;
|
|
}
|
|
|
|
void TabInterface::TabScrollBar::MouseMove(Point p, dword keyflags)
|
|
{
|
|
if(!HasCapture())
|
|
return;
|
|
Fix(p);
|
|
new_pos = p.x;
|
|
UpdatePos();
|
|
Refresh();
|
|
}
|
|
|
|
void TabInterface::TabScrollBar::MouseWheel(Point p, int zdelta, dword keyflags)
|
|
{
|
|
AddPos(-zdelta / 4, true);
|
|
}
|
|
|
|
void TabInterface::TabScrollBar::Layout()
|
|
{
|
|
UpdatePos(false);
|
|
}
|
|
|
|
int TabInterface::TabScrollBar::GetPos() const
|
|
{
|
|
return ffloor(ps);
|
|
}
|
|
|
|
void TabInterface::TabScrollBar::SetPos(int p, bool dontscale)
|
|
{
|
|
Fix(sz);
|
|
pos = total > 0 ? dontscale ? p : iscale(p, sz.cx, total) : 0;
|
|
UpdatePos(false);
|
|
Refresh();
|
|
}
|
|
|
|
void TabInterface::TabScrollBar::AddPos(int p, bool dontscale)
|
|
{
|
|
Fix(sz);
|
|
pos += total > 0 ? dontscale ? p : iscale(p, sz.cx, total) : 0;
|
|
UpdatePos(false);
|
|
Refresh();
|
|
}
|
|
|
|
int TabInterface::TabScrollBar::GetTotal() const
|
|
{
|
|
return total;
|
|
}
|
|
|
|
void TabInterface::TabScrollBar::AddTotal(int t)
|
|
{
|
|
total += t;
|
|
UpdatePos();
|
|
Refresh();
|
|
}
|
|
|
|
void TabInterface::TabScrollBar::SetTotal(int t)
|
|
{
|
|
bool upd = total < t;
|
|
total = t;
|
|
UpdatePos(upd);
|
|
Refresh();
|
|
}
|
|
|
|
void TabInterface::TabScrollBar::GoEnd()
|
|
{
|
|
pos = total;
|
|
UpdatePos(false);
|
|
Refresh();
|
|
}
|
|
|
|
void TabInterface::TabScrollBar::GoBegin()
|
|
{
|
|
pos = 0;
|
|
UpdatePos(false);
|
|
Refresh();
|
|
}
|
|
|
|
void TabInterface::TabScrollBar::Set(const TabScrollBar& t)
|
|
{
|
|
total = t.total;
|
|
pos = t.pos;
|
|
ps = t.ps;
|
|
Refresh();
|
|
}
|
|
|
|
void TabInterface::TabScrollBar::UpdatePos(bool update)
|
|
{
|
|
sz = GetSize();
|
|
Fix(sz);
|
|
if(total <= 0 || sz.cx <= 0)
|
|
cs = ics = 0;
|
|
else
|
|
{
|
|
cs = sz.cx / ((double) total + 0.5);
|
|
ics = total / ((double) sz.cx);
|
|
}
|
|
size = sz.cx * cs;
|
|
if(update)
|
|
pos = new_pos - start_pos;
|
|
if(pos < 0)
|
|
pos = 0;
|
|
else if(pos + size > sz.cx)
|
|
pos = sz.cx - size;
|
|
|
|
ps = total > sz.cx ? pos * ics : 0;
|
|
WhenScroll();
|
|
}
|
|
|
|
TabInterface::TabScrollBar& TabInterface::TabScrollBar::SetLayout(int l)
|
|
{
|
|
layout = l;
|
|
RefreshLayout();
|
|
return *this;
|
|
}
|