#include "DockCtrl.h" PaneFrame& PaneFrame::Attach(DockableCtrl& ctrl) { if(!GetBase().IsSideAllowed(GetType())) { // if not allowed, then find an allowed pane. for(int i = 0; i < 4; i++) if(GetBase().IsSideAllowed(i)) { GetBase().Dock(ctrl.DockingStyle(i, ctrl.State(), 0)); break; } } else if(ctrl.IsTabbed()) return AttachAsTab(ctrl); else if(ctrl.IsAutoHidden()) return AttachAsAuto(ctrl); else if(ctrl.IsDocked()) return AttachAsDock(ctrl); return *this; } PaneFrame& PaneFrame::AttachAsDock(DockableCtrl& ctrl) { if(DnDHasSource()) { int position = dndpos; DnDSourceoutofRange(); if(dockcontainer.IsAnimating()) dockcontainer.StopAnimation(); } if(ctrl.IsDocked() && !ctrl.IsHidden()) ShowFrame(ctrl.GetSizeHint()); dockcontainer.AddChildDock(ctrl, dndpos ? dndpos : ctrl.Position()); dndpos = 0; return RefreshPaneFrame(); } PaneFrame& PaneFrame::AttachAsTab(DockableCtrl& ctrl) { int position = ctrl.Position(); if(DnDHasSource()) { position = dndpos; DnDSourceoutofRange(); if(HasTabWindow(GetActiveTabWindow())) if(GetActiveTabWindow()->IsTabAnimating()) GetActiveTabWindow()->StopTabAnimation(); } else { DockableCtrl* targetctrl = dockcontainer.GetChildAt(position); if(!targetctrl) { int cc = dockcontainer.GetChildCount(); if(cc == 0) { ctrl.DockingStyle(GetType(), DockableCtrl::STATE_SHOW, 0); return AttachAsDock(ctrl); } else { targetctrl = dockcontainer.GetChildAt(cc); if(targetctrl) position = targetctrl->Position(); else return *this; } } } AddtoTabWindow(ctrl.Posit(position)); SetActiveTabWindow(NULL); dndpos = 0; RefreshTabWindowList(); return RefreshPaneFrame(); } PaneFrame& PaneFrame::AttachAsAuto(DockableCtrl& ctrl) { bool vertical = GetType() == LEFT || GetType() == RIGHT; AutoHideBar& bar = GetBase().GetHideBar(GetType()); Size sz = ctrl.GetSizeHint(); Size newsz; Size hidesz; hidesz += GetBase().GetHideBar(GetType()).GetHeight() + 4; if(vertical) { if (sz.cx < hidesz.cx) { newsz = Size(maxsize, sz.cy); ctrl.SetSizeHint(newsz); } } else { if (sz.cy < hidesz.cy) { newsz = Size(sz.cx, maxsize); ctrl.SetSizeHint(newsz); } } bar.Attach(ctrl); GetBase().RefreshWidgetLayout(); return RefreshPaneFrame(); } PaneFrame& PaneFrame::Detach(DockableCtrl& ctrl) { if(!ctrl.IsDocked()) return *this; if(HasChild(ctrl) && !ctrl.IsShut()) dockcontainer.RemoveChildDock(ctrl); if(!dockcontainer.HasChild()) HideFrame(); return RefreshPaneFrame(); } DockableCtrl* PaneFrame::GetChild(int position) { return dockcontainer.GetChildAt(position); } int PaneFrame::GetCount() { return dockcontainer.GetChildCount(); } bool PaneFrame::HasChild(DockableCtrl& ctrl) { if(dockcontainer.HasChild()) for(int i = 1; i <= dockcontainer.GetCount(); i++) if(&ctrl == dockcontainer.GetChildAt(i)) return true; return false; } void PaneFrame::ShowFrame() { SetSize(stdsize <= 4 ? maxsize : stdsize); RefreshPaneFrame().Enable(); } void PaneFrame::ShowFrame(Size sz) { bool horizontal = GetType() == LEFT || GetType() == RIGHT; if(!dockcontainer.HasChild()) { if(horizontal) SetSize((sz.cx > 4 && sz.cx < maxsize) ? sz.cx : maxsize); else SetSize((sz.cy > 4 && sz.cy < maxsize) ? sz.cy : maxsize); } else SetSize(size); RefreshPaneFrame(); if(!IsEnabled()) Enable(); } void PaneFrame::HideFrame() { stdsize = GetSize(); SetSize(0); RefreshPaneFrame().Disable(); } void PaneFrame::LockFrame() { if(IsLocked()) return; } void PaneFrame::UnlockFrame() { if(!IsLocked()) return; } Vector& PaneFrame::GetTabWindows() { return tabwindows; } TabWindow* PaneFrame::AddTabWindow() { Vector& tl = GetBase().GetTabWindows(); TabWindow* tabwindow = NULL; tl.Add(tabwindow = new TabWindow()); tabwindow->SetStyle(*GetBase().GetStyle()); tabwindow->SetBase(&GetBase()); GetBase().RefreshTabWindowList(); return tabwindow; } TabWindow* PaneFrame::AddTabWindow(DockableCtrl& ctrl) { Size tabnewsize; Vector& tl = GetBase().GetTabWindows(); int position = ctrl.Position(); if(position == 0) ++position; TabWindow *tabwindow = FindTabWindow(position); if(tabwindow) return activetabwindow = tabwindow; tl.Add(tabwindow = new TabWindow()); tabwindow->SetStyle(*GetBase().GetStyle()); tabwindow->SetBase(&GetBase()).DockingStyle(GetType(), DockableCtrl::STATE_SHOW, position); if(dockcontainer.HasChild()) { DockableCtrl* child = dockcontainer.GetChildAt(position); if(child) { child->Shut(); tabwindow->Attach(*child); tabnewsize = child->GetSizeHint(); } } if(!tabwindow->IsTabbed()) if(tabwindow->IsDocked() && !tabwindow->IsHidden()) ShowFrame(tabnewsize); dockcontainer.AddChildDock(*tabwindow, (dndpos == 0 || tabwindow->Position()) ? tabwindow->Position() : dndpos); GetBase().RefreshTabWindowList(); return activetabwindow = tabwindow; } void PaneFrame::RemoveTabWindow(TabWindow* tabwindow) { //TODO: Remove. } void PaneFrame::RemoveTabWindow(int position) { //TODO: Remove. } void PaneFrame::RemoveTabWindows() { //TODO: Remove. } void PaneFrame::RefreshTabWindowList() { GetBase().RefreshTabWindowList(); SetActiveTabWindow(NULL); } void PaneFrame::AddtoTabWindow(DockableCtrl& ctrl) { TabWindow* tabwindow = FindTabWindow(ctrl.Position()); if(!tabwindow) tabwindow = AddTabWindow(ctrl); tabwindow->Attach(ctrl); } void PaneFrame::RemovefromTabWindow(DockableCtrl& ctrl) { TabWindow* tabwindow = FindTabWindow(ctrl.Position()); if(!tabwindow) return; ctrl.Shut(); if(tabwindow && tabwindow->IsShut()) delete tabwindow; } void PaneFrame::RemovefromTabWindow(int position) { } TabWindow* PaneFrame::FindTabWindow(int position) { if(position <= 0) return NULL; TabWindow * tabwindow = NULL; Vector& tl = GetBase().GetTabWindows(); for(int i = 0; i < tl.GetCount(); i++) { tabwindow = tl.At(i); if(tabwindow->Position() == position && tabwindow->Alignment() == GetType() && tabwindow->State() != DockableCtrl::STATE_TABBED) return tabwindow; } return NULL; } TabWindow* PaneFrame::FindTabWindow(DockableCtrl& ctrl) { return NULL; } TabWindow* PaneFrame::GetActiveTabWindow() { return activetabwindow; } void PaneFrame::SetActiveTabWindow(TabWindow* tabwindow) { activetabwindow = tabwindow; } bool PaneFrame::HasTabWindow(TabWindow* tabwindow) { Vector& tl = GetBase().GetTabWindows(); for(int i = 0; i < tl.GetCount(); i++) if(tabwindow == tl.At(i)) return true; return false; } bool PaneFrame::HasCtrlInRange(DockableCtrl& ctrl, Point p) { if(!GetBase().IsSideAllowed(GetType())) return false; Ctrl* first = NULL; Ctrl* last = NULL; if(!dockcontainer.HasChild()) return CalculateEmptyRange(ctrl, p); if(!(first = dockcontainer.GetFirstChild()) || !(last = dockcontainer.GetLastChild())) return false; if((first == last) && (first != dockcontainer.GetAnimationCtrl())) return CalculateCtrlRange(ctrl, *first, p); else { Ctrl* ctrl0 = first; while(ctrl0) { if(ctrl0 != dockcontainer.GetAnimationCtrl()) if(CalculateCtrlRange(ctrl, *ctrl0, p)) return true; ctrl0 = ctrl0->GetNext(); } } return false; } bool PaneFrame::CalculateCtrlRange(DockableCtrl& t, Ctrl& c, Point p) { DockWindow* ctrl = reinterpret_cast(&c); ASSERT(ctrl); Rect r = ctrl->GetCtrlRect(); int position = ctrl->Position(); int hrange = r.GetWidth() / 3; int vrange = r.GetHeight() / 3; if(!DnDHasSource()) { if(!GetActiveTabWindow() || (GetActiveTabWindow() && !GetActiveTabWindow()->IsTabAnimating())) { if(Rect(r.left + hrange, r.top + vrange, r.right - hrange, r.bottom - vrange).Contains(p)) { DnDSourceinRange(); StartTabWindowAnimation(*ctrl, position); t.SetDropTarget(GetType(), DockableCtrl::STATE_TABBED); return true; } } if(dockcontainer.IsVert() && !GetActiveTabWindow() && !dockcontainer.IsAnimating()) { if(Rect(r.left, r.top, r.right, r.top + vrange).Contains(p) || Rect(r.left, r.bottom - vrange, r.right, r.bottom).Contains(p)) { DnDSourceinRange(); StartPaneFrameAnimation(*ctrl, p.y > r.bottom - vrange ? ++position : position); t.SetDropTarget(GetType(), DockableCtrl::STATE_SHOW); return true; } } if(dockcontainer.IsHorz() && !GetActiveTabWindow() && !dockcontainer.IsAnimating()) { if(Rect(r.left, r.top, r.left + hrange, r.bottom).Contains(p) || Rect(r.right - hrange, r.top, r.right, r.bottom).Contains(p)) { DnDSourceinRange(); StartPaneFrameAnimation(*ctrl, p.x < r.left + hrange ? position : ++position); t.SetDropTarget(GetType(), DockableCtrl::STATE_SHOW); return true; } } return false; } if(DnDHasSource()) { if(dockcontainer.IsHorz() && dockcontainer.IsAnimating() && dockcontainer.AnimationArea().Contains(p)) return true; if(dockcontainer.IsVert()) { r = dockcontainer.AnimationArea(); r.bottom += 5; r.top -= 5; if(dockcontainer.IsAnimating() && r.Contains(p)) return true; } if(GetActiveTabWindow()) if(GetActiveTabWindow()->IsTabAnimating() && GetActiveTabWindow()->HasCtrlInRange()) return true; DnDSourceoutofRange(); DnDAnimate(position); return false; } return false; } bool PaneFrame::CalculateEmptyRange(Ctrl& c, Point p) { DockWindow* ctrl = reinterpret_cast(&c); ASSERT(ctrl); Rect r = GetScreenRect(); if(!DnDHasSource() && !dockcontainer.HasChild() && !dockcontainer.IsAnimating()) { bool state = false; switch(GetType()) { case LEFT: ((p.x < r.right + 20) && (p.x > r.left) && (p.y > r.top && p.y < r.bottom)) ? state = true : state = false; break; case RIGHT: ((p.x > r.left - 20) && (p.x < r.right) && (p.y > r.top && p.y < r.bottom)) ? state = true : state = false; break; case TOP: ((p.y < r.bottom + 20) && (p.y > r.top) && (p.x > r.left && p.x < r.right)) ? state = true : state = false; break; case BOTTOM: ((p.y > r.top - 20) && (p.y < r.bottom) && (p.x > r.left && p.x < r.right)) ? state = true : state = false; break; } if(state) { ShowFrame(ctrl->GetSizeHint()); DnDSourceinRange(); StartPaneFrameAnimation(reinterpret_cast(c), 1); ctrl->SetDropTarget(GetType(), DockableCtrl::STATE_SHOW); return true; } return false; } if(DnDHasSource()) { if(dockcontainer.IsAnimating() && dockcontainer.AnimationArea().Contains(p)) return true; HideFrame(); DnDSourceoutofRange(); StopPaneFrameAnimation(); return false; } return false; } //---------------------------------------------------------------------------------------------- void PaneFrame::StartPaneFrameAnimation(DockableCtrl& ctrl, int position) { if(DnDHasSource() && !dockcontainer.IsAnimating()) { if(HasTabWindow(GetActiveTabWindow())) if(GetActiveTabWindow()->IsTabAnimating()) GetActiveTabWindow()->StopTabAnimation(); dockcontainer.StartAnimation(position); dndpos = position; } RefreshPaneFrame(); } void PaneFrame::StartTabWindowAnimation(DockableCtrl& ctrl, int position) { if(DnDHasSource() && &ctrl && (ctrl.Position() == position)) { RefreshTabWindowList(); if(!HasTabWindow(GetActiveTabWindow())) activetabwindow = AddTabWindow(ctrl); if(!GetActiveTabWindow()->IsTabAnimating()) { if(dockcontainer.IsAnimating()) dockcontainer.StopAnimation(); GetActiveTabWindow()->StartTabAnimation(); } dndpos = position; } RefreshPaneFrame(); } void PaneFrame::StopPaneFrameAnimation() { if(!DnDHasSource() && dockcontainer.IsAnimating()) dockcontainer.StopAnimation(); RefreshPaneFrame(); } void PaneFrame::StopTabWindowAnimation() { if(!DnDHasSource() && HasTabWindow(GetActiveTabWindow())) if(GetActiveTabWindow()->IsTabAnimating()) { GetActiveTabWindow()->StopTabAnimation(); RefreshTabWindowList(); } RefreshPaneFrame(); } void PaneFrame::DnDAnimate(int position) { if(!(dockcontainer.IsAnimating() && dockcontainer.GetAnimationCtrl()->GetScreenRect().Contains(GetMousePos()))) StopPaneFrameAnimation(); if(HasTabWindow(GetActiveTabWindow())) if(!(GetActiveTabWindow()->IsTabAnimating() && GetActiveTabWindow()->HasCtrlInRange())) StopTabWindowAnimation(); } //---------------------------------------------------------------------------------------------- PaneFrame& PaneFrame::SetLayout(DockBase* basectrl, int alignment, int _maxsize) { ASSERT(basectrl); base = basectrl; MaxSize(_maxsize); switch(alignment) { case LEFT: Left(dockcontainer.SizePos(), 0); break; case TOP: Top(dockcontainer.SizePos(), 0); break; case RIGHT: Right(dockcontainer.SizePos(), 0); break; case BOTTOM: Bottom(dockcontainer.SizePos(), 0); break; } HideFrame(); created = true; return *this; } void PaneFrame::FrameAdd(Ctrl& parent) { parent.Add(*this); } void PaneFrame::FrameRemove() { this->Ctrl::Remove(); } void PaneFrame::FrameAddSize(Size& sz) { if(IsShown()) if(type == LEFT || type == RIGHT) { sz.cx += size; maxsize = sz.cx / 3; } else { sz.cy += size; maxsize = sz.cy / 3; } } int PaneFrame::BoundSize() { int maxsize = max(0, (type == LEFT || type == RIGHT ? parentsize.cx : parentsize.cy) - sizemin); return IsShown() ? max(1, minmax(size, minsize - 1, maxsize)) : 0; } void PaneFrame::FrameLayout(Rect& r) { Rect rr = r; parentsize = r.GetSize(); int sz = BoundSize(); switch(type) { case LEFT: r.left += sz; rr.right = r.left; break; case RIGHT: r.right -= sz; rr.left = r.right; break; case TOP: r.top += sz; rr.bottom = r.top; break; case BOTTOM: r.bottom -= sz; rr.top = r.bottom; break; } SetFrameRect(rr); } void PaneFrame::Paint(Draw& draw) { draw.DrawRect( Ctrl::GetSize(), HasCapture() ? GUI_GlobalStyle() >= GUISTYLE_XP ? Blend(SColorHighlight, SColorFace) : SColorShadow : SColorFace() ); } void PaneFrame::LeftDown(Point p, dword) { SetCapture(); Refresh(); ref = GetMousePos(); size0 = BoundSize(); } void PaneFrame::MouseMove(Point p, dword keyflags) { if(!HasCapture()) return; p = GetMousePos(); switch(type) { case LEFT: size = size0 + p.x - ref.x; break; case RIGHT: size = size0 + ref.x - p.x; break; case TOP: size = size0 + p.y - ref.y; break; case BOTTOM: size = size0 + ref.y - p.y; break; } RefreshParentLayout(); } void PaneFrame::LeftUp(Point p, dword keyflags) { Refresh(); } Image PaneFrame::CursorImage(Point p, dword keyflags) { return type == LEFT || type == RIGHT ? Image::SizeHorz() : Image::SizeVert(); } PaneFrame& PaneFrame::Set(Ctrl& c, int _size, int _type) { while(GetFirstChild()) GetFirstChild()->Remove(); type = _type; size = _size; Add(c.SizePos()); switch(type) { case LEFT: c.HSizePos(0, 4); break; case RIGHT: c.HSizePos(4, 0); break; case TOP: c.VSizePos(0, 4); break; case BOTTOM: c.VSizePos(4, 0); break; } RefreshParentLayout(); return *this; } PaneFrame::PaneFrame() { type = LEFT; size = size0 = 1; minsize = 0; maxsize = 0; stdsize = 0; sizemin = 0; dndpos = 0; ncount = 0; locked = false; created = false; activetabwindow = NULL; } PaneFrame::~PaneFrame() { }