void AutoHideBar::ComposeTab(Tab& tab, const Font &font, Color ink, int style) { DockableCtrl *d; WString txt; const Value &q = tab.value; ink = (style == CTRL_DISABLED) ? SColorDisabled : ink; if (IsTypeRaw<DockCont *>(q)) { DockCont *c = ValueTo<DockCont *>(q); d = &c->GetCurrent(); txt = c->GetTitle(); } else { ASSERT(IsTypeRaw<DockableCtrl *>(q)); d = ValueTo<DockableCtrl *>(q); txt = d->GetTitle(); } if(icons) { tab.AddImage((style == CTRL_DISABLED) ? DisabledImage(d->GetIcon()) : d->GetIcon()); } if (showtext) { tab.AddText(txt, font, ink); } }
void DockWindow::ContainerDragEnd(DockCont &dc) { KillTimeCallback(TIMEID_ANIMATE_DELAY); if (!dc.IsFloating()) return; HighlightCtrl &hl = GetHighlightCtrl(); Ctrl *p = hl.GetParent(); int align = DOCK_NONE; if (p) for (int i = 0; i < 4; i++) if (p == &dockpane[i]) align = i; if (animatewnd && (p || align != DOCK_NONE)) { FloatAnimate(dc, hl.GetScreenRect()); } if (align != DOCK_NONE) { Unfloat(dc); dc.StateDocked(*this); dockpane[align].Swap(hl, dc); } else if (DockCont *target = dynamic_cast<DockCont *>(p)) { StopHighlight(false); bool nest = (GetMouseFlags() & NestedToggleKey()) ? !IsNestedTabs() : IsNestedTabs(); DockContainerAsTab(*target, dc, nest && dc.GetCount() > 1); } else StopHighlight(false); if (dc.GetParent()) dc.SetFocus(); }
void DockCont::TabSelected() { int ix = tabbar.GetCursor(); if (ix >= 0) { DockableCtrl *dc = Get0(ix); if (!dc) return; Ctrl *ctrl = GetCtrl(ix); Ctrl *first = &handle; for (Ctrl *c = first->GetNext(); c; c = c->GetNext()) if (c != ctrl) c->Hide(); ctrl->Show(); Icon(dc->GetIcon()).Title(dc->GetTitle()); handle.dc = dc; SyncButtons(*dc); if (IsTabbed()) { DockCont *c = static_cast<DockCont *>(GetParent()); c->tabbar.SyncRepos(); c->TabSelected(); c->RefreshFrame(); } else RefreshLayout(); } }
void DockWindow::Undock(DockCont &c) { if (!c.IsFloating() && !c.IsHidden()) { if (c.IsAutoHide()) { for (int i = 0; i < 4; i++) { int ix = hideframe[i].FindCtrl(c); if (ix >= 0) { hideframe[i].RemoveCtrl(ix); hideframe[i].RefreshFrame(); break; } } } else { int dock = GetDockAlign(c); if (dock >= 0 && dock < 4) { Ctrl *p = &c; while (p && p->GetParent() != &dockpane[dock]) p = p->GetParent(); ASSERT(p); bool v = !IsTB(dock); c.SyncUserSize(v, !v); } Undock0(c); } c.StateNotDocked(); } }
/* * Container management */ DockCont * DockWindow::CreateContainer() { DockCont *dc = &conts.Add(); dc->StateNotDocked(this); SyncContainer(*dc); return dc; }
void DockWindow::FloatFromTab(DockCont &c, DockCont &tab) { Rect r = c.GetScreenRect(); tab.SetRect(r); tab.StateDocked(*this); c.RefreshLayout(); tab.MoveBegin(); }
void DockWindow::AutoHide(int align, DockableCtrl &dc) { ALIGN_ASSERT(align); Register(dc); DockCont *c = GetReleasedContainer(dc); c->StateAutoHide(*this); hideframe[align].AddCtrl(*c, dc.GetGroup()); }
void DockCont::Serialize(Stream& s) { int ctrl = 'D'; int cont = 'C'; const Vector<DockableCtrl *> &dcs = base->GetDockableCtrls(); if (s.IsStoring()) { if (GetCount() == 1 && IsDockCont(tabbar.Get(0))) return ContCast(tabbar.Get(0))->Serialize(s); int cnt = GetCount(); s / cont / cnt; for (int i = GetCount() - 1; i >= 0; i--) { if (IsDockCont(tabbar.Get(i))) ContCast(tabbar.Get(i))->Serialize(s); else { DockableCtrl *dc = DockCast(tabbar.Get(i)); int ix = base->FindDocker(dc); s / ctrl / ix; } } int cursor = tabbar.GetCursor(); int groupix = tabbar.GetGroup(); s / cursor / groupix; } else { int cnt; int type; s / type / cnt; ASSERT(type == cont); for (int i = 0; i < cnt; i++) { int64 pos = s.GetPos(); s / type; if (type == cont) { s.Seek(pos); DockCont *dc = base->CreateContainer(); dc->Serialize(s); base->DockContainerAsTab(*this, *dc, true); } else if (type == ctrl) { int ix; s / ix; if (ix >= 0 && ix <= dcs.GetCount()) Add(*dcs[ix]); } else ASSERT(false); } int cursor, groupix; s / cursor / groupix; tabbar.SetGroup(groupix); tabbar.SetCursor(min(tabbar.GetCount()-1, cursor)); TabSelected(); } }
void DockWindow::Close(DockableCtrl &dc) { DockCont *c = GetContainer(dc); if (c && c->GetCount() > 1) { dc.Remove(); c->Layout(); c = NULL; } if (c) CloseContainer(*c); }
DockCont *DockWindow::FindDockTarget(DockCont &dc, int &dock) { Point p = GetMousePos(); Rect r = GetScreenView(); DockCont *target = NULL; int align = DOCK_NONE; dock = DOCK_NONE; if (r.Contains(p)) { dock = GetPointAlign(p, r, true, true, true); if (dock != DOCK_NONE && dockpane[dock].IsVisible()) dock = DOCK_NONE; } else { target = GetMouseDockTarget(); if (target) { r = target->GetScreenRect(); dock = GetDockAlign(*target); align = GetPointAlign(p, r, IsTabbing(), IsTB(dock), !IsTB(dock)); } else return NULL; } if (dock != DOCK_NONE && (!dc.IsDockAllowed(dock) || IsPaneAnimating(dock) || IsFrameAnimating(dock)) || (dock == DOCK_NONE && !target)) { dock = DOCK_NONE; return NULL; } // Prepare for highlight if (target) { GetHighlightCtrl().bounds = GetAlignBounds(align, r, IsTabbing(), IsTB(dock), !IsTB(dock)); if (align == DOCK_NONE) dock = DOCK_NONE; // Tabbing // The following code handles the case of an insertion between two docked controls. In this case we must set // the highlight bounds to be a union of the bounds from each control. Very ugly. if (dock != DOCK_NONE) { Ctrl *c = IsTL(align) ? target->GetPrev() : target->GetNext(); if (c) { int opal = align > 1 ? align-2 : align+2; GetHighlightCtrl().bounds.Union(GetAlignBounds(opal, c->GetScreenRect(), IsTabbing())); } target = IsTL(align) ? target : dynamic_cast<DockCont*>(target->GetNext()); } } else if (dock != DOCK_NONE) GetHighlightCtrl().bounds = GetAlignBounds(dock, r, true); return target; }
void DockCont::AddFrom(DockCont &cont, int except) { bool all = except < 0 || except >= cont.GetCount(); for (int i = cont.GetCount() - 1; i >= 0; i--) if (i != except) { Ctrl *c = cont.GetCtrl(i); c->Remove(); Add(*c); } if (all) cont.tabbar.Clear(); }
void DockWindow::FloatContainer(DockCont &c, Point p) { ASSERT(IsOpen()); if (c.IsFloating()) return; if (p.IsNullInstance()) p = GetScreenRect().CenterPoint(); Detach(c); c.StateFloating(*this); Size best = CtrlBestSize(c, false); c.SetRect(Rect(p, best)); c.Open(this); }
void DockWindow::DockContainerAsTab(DockCont &target, DockCont &c, bool do_nested) { Detach(c); if (do_nested) { c.StateTabbed(*this); target << c; } else { target.AddFrom(c); DestroyContainer(c); } }
void PopUpDockWindow::ContainerDragMove(DockCont &dc) { int align = DOCK_NONE; // Is the highlight the same as last time? (Quick escape) if (last_popup && last_popup->IsPopUp() && last_popup->GetRect().Contains(GetMousePos())) return; DockCont *target = GetMouseDockTarget(); int dock = DOCK_NONE; if (target) { dock = GetDockAlign(*target); if (!dc.IsDockAllowed(dock)) target = NULL; } bool target_changed = (target != last_target) && !GetHighlightCtrl().GetParent() && (!target || !IsPaneAnimating(dock)); // Hide show inner popups as necessary if (!target && last_target != NULL) HidePopUps(true, false); else if (target_changed) ShowInnerPopUps(dc, target); ShowOuterPopUps(dc); last_target = target; // Get potential alignment align = PopUpHighlight(inner, 5); if (align == DOCK_NONE) { target = NULL; last_target = NULL; align = PopUpHighlight(outer, 4); } else if (align == 4) align = DOCK_NONE; else if (target) { target = IsTL(align) ? target : dynamic_cast<DockCont*>(target->GetNext()); align = dock; } // Do highlight if (align != DOCK_NONE || target) { if (align == DOCK_NONE) StopHighlight(false); dc.SyncUserSize(true, true); Highlight(align, dc, target); } else { StopHighlight(IsAnimatedHighlight()); last_popup = NULL; } }
void DockWindow::DockAsTab(DockCont &target, DockableCtrl &dc) { DockCont *c = GetContainer(dc); if (c) { if (c->GetCount() == 1) CloseContainer(*c); else { Ctrl *c = dc.GetParent(); dc.Remove(); c->Layout(); } } target.Add(dc); }
DockCont *DockWindow::GetReleasedContainer(DockableCtrl &dc) { DockCont *c = GetContainer(dc); if (c && c->GetCount() > 1) { dc.Remove(); c->RefreshLayout(); c = NULL; } if (c) Detach(*c); else c = CreateContainer(dc); return c; }
void PopUpDockWindow::ShowOuterPopUps(DockCont &dc) { Rect wrect = GetScreenRect(); Point cp = wrect.CenterPoint(); Size psz(style->outersize, style->outersize); Rect prect = Rect(psz); psz /= 2; wrect.Deflate(12, 12); if (dc.IsDockAllowed(DOCK_LEFT)) ShowPopUp(outer[DOCK_LEFT], prect.Offseted(wrect.left + POPUP_SPACING, cp.y - psz.cy)); if (dc.IsDockAllowed(DOCK_TOP)) ShowPopUp(outer[DOCK_TOP], prect.Offseted(cp.x - psz.cx, wrect.top + POPUP_SPACING)); if (dc.IsDockAllowed(DOCK_RIGHT)) ShowPopUp(outer[DOCK_RIGHT], prect.Offseted(wrect.right - POPUP_SPACING - psz.cx*2, cp.y - psz.cy)); if (dc.IsDockAllowed(DOCK_BOTTOM)) ShowPopUp(outer[DOCK_BOTTOM], prect.Offseted(cp.x - psz.cx, wrect.bottom - POPUP_SPACING - psz.cy*2)); }
void AutoHideBar::RemoveCtrl(DockCont& c, int ix) { if (c.IsOpen()) c.Close(); if (ctrl == &c) { if (popup.IsOpen()) popup.Close(); ctrl->Remove(); //KillTimeCallback(TIMEID_ANIMATE); KillTimeCallback(TIMEID_HIDE_TIMEOUT); ctrl = NULL; } if (ix >= 0) DockTabBar::Close(ix); if (GetCount() == autohide) RefreshParentLayout(); }
void DockWindow::ContainerDragStart(DockCont &dc) { if (!dc.IsFloating()) { // Reposition if not under the mouse Rect r = dc.GetScreenRect(); Point pt = GetMousePos(); Point tl = r.TopLeft(); bool move = false; if (r.left > pt.x || r.right < pt.x) { tl.x += pt.x - r.left - r.Width()/2; move = true; } if (r.top < pt.y) { tl.y += pt.y - r.top + DOCKCONT_WND_OFFSET; move = true; } // Note: Due to different bugfix, at this point a dragged tab will have docked state but // no parent and should not be animatehld dc.SyncUserSize(true, true); if (IsAnimatedHighlight() && dc.IsDocked() && dc.GetParent()) { Undock0(dc, true); dc.StateNotDocked(); } FloatContainer(dc, move ? tl : Null); dc.StartMouseDrag(pt); } }
Size DockTabBar::GetStdSize(const Tab &t) { DockableCtrl *d; const Value &q = t.key; Value v; if (IsTypeRaw<DockCont *>(q)) { DockCont *c = ValueTo<DockCont *>(q); d = &c->GetCurrent(); v = c->GetTitle(); } else { ASSERT(IsTypeRaw<DockableCtrl *>(q)); d = ValueTo<DockableCtrl *>(q); v = d->GetTitle(); } int isz = (IsVert() ? d->GetIcon().GetHeight() : d->GetIcon().GetWidth()); return showtext ? (TabBar::GetStdSize(v) + Size(isz+2, 0)) : Size(isz, isz); }
void DockWindow::FloatAnimate(DockCont &dc, Rect target) { int max = dockpane[0].GetAnimMaxTicks(); dc.IgnoreMinSize(true); Rect dr = dc.GetRect(); target -= dr; target.top += 16; // Fudge for titlebar. Should get from OS? target.left /= max; target.right /= max; target.top /= max; target.bottom /= max; for (int i = 0; i < max; i++) { dr += target; dc.SetRect(dr); ProcessEvents(); Sleep(dockpane[0].GetAnimInterval()); } dc.IgnoreMinSize(false); }
void DockCont::TabDragged(int ix) { if (ix >= 0) { // Special code needed Value v = tabbar.Get(ix); if (IsDockCont(v)) { DockCont *c = ContCast(v); c->Remove(); base->FloatFromTab(*this, *c); } else { DockableCtrl *c = DockCast(v); c->Remove(); base->FloatFromTab(*this, *c); } if (tabbar.IsAutoHide()) RefreshLayout(); } }
void DockWindow::Unfloat(DockCont &c) { if (c.IsFloating()) { c.SyncUserSize(true, true); if (c.IsOpen() || c.IsPopUp()) c.Close(); c.StateNotDocked(); } }
void DockWindow::Highlight(int align, DockCont &cont, DockCont *target) { HighlightCtrl &hl = GetHighlightCtrl(); DockableCtrl &dc = cont.GetCurrent(); ASSERT(&hl != (Ctrl *)&cont); hl.SizeHint(cont.GetMinSize(), cont.GetMaxSize(), cont.GetStdSize()).Show(); if (align != DOCK_NONE) { hl.SetHighlight(dc.GetStyle().highlight[0], false, 0); hl.oldframesize = dockframe[align].GetSize(); int pos = target ? dockpane[align].FindIndex(*target) : -1; Dock0(align, hl, pos, IsAnimatedHighlight(), true); } else if (target && IsTabbing()) { hl.Title(cont.GetTitle(true)).Icon(dc.GetIcon()); hl.SetHighlight(dc.GetStyle().highlight[1], IsNestedTabs() && (cont.GetCount() > 1), (cont.GetCount() > 1) ? NestedToggleKey() : 0, target->GetHighlightImage()); DockAsTab(*target, hl); } }
void DockWindow::SerializeLayout(Stream &s, bool withsavedlayouts) { StopHighlight(false); int cnt = 0; s.Magic(); // Groups ArrayMap<String, Vector<int> > groups; if (s.IsStoring()) for (int i = 0; i < dockers.GetCount(); i++) { String g = dockers[i]->GetGroup(); if (!g.IsEmpty()) { int ix = groups.Find(g); if (ix < 0) { groups.Add(dockers[i]->GetGroup(), Vector<int>()); ix = groups.GetCount() - 1; } groups[ix].Add(i); } } s % groups; if (s.IsLoading()) { ClearLayout(); for (int i = 0; i < dockers.GetCount(); i++) dockers[i]->SetGroup(Null); for (int i = 0; i < groups.GetCount(); i++) { Vector<int> &v = groups[i]; const String &g = groups.GetKey(i); for (int j = 0; j < v.GetCount(); j++) { int ix = v[j]; if (ix >= 0 && ix < dockers.GetCount()) dockers[ix]->SetGroup(g); } } } if (s.IsStoring()) { // Write docked for (int i = 0; i < 4; i++) { DockPane &pane = dockpane[i]; int fsz = dockframe[i].IsShown() ? dockframe[i].GetSize() : 0; s / fsz % pane; DockCont *dc = dynamic_cast<DockCont *>(pane.GetFirstChild()); for (int j = 0; dc && j < pane.GetCount(); j++) { s % *dc; dc = dynamic_cast<DockCont *>(dc->GetNext()); } } cnt = 0; // Count Floating for (int i = 0; i < conts.GetCount(); i++) if (conts[i].IsFloating()) cnt++; // Write Floating s / cnt; for (int i = 0; i < conts.GetCount(); i++) { if (conts[i].IsFloating()) { conts[i].Serialize(s); conts[i].SerializePlacement(s, false); } } // Write Autohidden for (int i = 0; i < 4; i++) { cnt = hideframe[i].GetCount(); s / cnt; for (int j = 0; j < hideframe[i].GetCount(); j++) { int ix = FindDocker(&hideframe[i].GetCtrl(j)->Get(0)); if (ix >= 0) s / ix; } } } else { // Read docked for (int i = 0; i < 4; i++) { DockPane &pane = dockpane[i]; dockframe[i].Hide(); int fsz; s / fsz % pane; for (int j = 0; j < pane.GetCount(); j++) { DockCont *dc = CreateContainer(); s % *dc; dc->StateDocked(*this); pane << *dc; } if (fsz && pane.GetCount()) { dockframe[i].SetSize(fsz); dockframe[i].Show(); } else dockframe[i].SetSize(0); } // Read floating s / cnt; for (int i = 0; i < cnt; i++) { DockCont *dc = CreateContainer(); dc->Serialize(s); FloatContainer(*dc); dc->SerializePlacement(s, false); } // Read Autohidden for (int i = 0; i < 4; i++) { s / cnt; for (int j = 0; j < cnt; j++) { int ix; s / ix; if (ix >= 0 && ix < dockers.GetCount()) AutoHide(i, *dockers[ix]); } } // Clear empty containers for (int i = conts.GetCount()-1; i >= 0; i--) { if (!conts.GetCount()) CloseContainer(conts[i]); } RefreshLayout(); } bool haslay = withsavedlayouts; s % haslay; if (withsavedlayouts && (s.IsStoring() || haslay)) s % layouts; s.Magic(); }
DockCont * DockWindow::CreateContainer(DockableCtrl &dc) { DockCont *c = CreateContainer(); c->Add(dc); return c; }
void DockWindow::SyncContainer(DockCont &c) { c.Grouping(grouping); c.WindowButtons(menubtn, hidebtn, closebtn); c.SyncButtons(); }
/* * Container docking */ void DockWindow::DockContainer(int align, DockCont &c, int pos) { Detach(c); c.StateDocked(*this); Dock0(align, c, pos); }
void DockWindow::CloseContainer(DockCont &c) { c.Clear(); Detach(c); DestroyContainer(c); }
void DockWindow::AutoHideContainer(int align, DockCont &c) { while (c.GetCount() && !c.IsAutoHide()) AutoHide(align, c.Get(0)); }