From 2af0d1f8b211a34b670bc04df81ef60d227be59b Mon Sep 17 00:00:00 2001 From: cxl Date: Sat, 8 Mar 2014 18:35:05 +0000 Subject: [PATCH] TabBar fixed (thanks massimo) git-svn-id: svn://ultimatepp.org/upp/trunk@7012 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppsrc/TabBar/TabBar.cpp | 115 ++++++++++++++++++++++------------- uppsrc/TabBar/TabBar.h | 5 +- uppsrc/TabBar/TabBarCtrl.cpp | 21 +++++-- uppsrc/TabBar/TabBarCtrl.h | 3 +- 4 files changed, 96 insertions(+), 48 deletions(-) diff --git a/uppsrc/TabBar/TabBar.cpp b/uppsrc/TabBar/TabBar.cpp index 698cd5201..98474b59c 100644 --- a/uppsrc/TabBar/TabBar.cpp +++ b/uppsrc/TabBar/TabBar.cpp @@ -369,17 +369,22 @@ void TabBar::CloseAll(int exception) else if (exception >= 0 && CancelCloseSome(Vector(vv,0))) return; + // 2014/03/06 - FIRST the callbacks, THEN remove the tab + // otherwise keys in WhenCloseSome() are invalid + // WhenCloseSome() is called ALWAYS even if all tabs are closed + WhenCloseSome(vv); + if (exception < 0) + WhenCloseAll(); + for(int i = tabs.GetCount() - 1; i >= 0; i--) if(i != exception) + { + TabClosed(tabs[i].key); tabs.Remove(i); + } SetCursor(0); - if (exception >= 0) - WhenCloseSome(vv); - else - WhenCloseAll(); - MakeGroups(); Repos(); Refresh(); @@ -425,18 +430,6 @@ void TabBar::GroupMenu(Bar &bar, int n) bar.Add(t_("Close"), THISBACK1(DoCloseGroup, n)); } -TabBar::Tab::Tab() -{ - id = -1; - stack = -1; - visible = true; - itn = 0; - items.SetCount(5); - - pos = cross_pos = tab_pos = Point(0, 0); - cross_size = size = tab_size = Size(0, 0); -} - void TabBar::Tab::Set(const Tab& t) { id = t.id; @@ -616,10 +609,12 @@ void TabBar::MakeGroups() void TabBar::DoGrouping(int n) { + Value c = GetData(); group = n; Repos(); SyncScrollBar(); - SetCursor(-1); + SetData(c); + Refresh(); } void TabBar::DoCloseGroup(int n) @@ -654,6 +649,8 @@ void TabBar::DoCloseGroup(int n) // we didn't cancel globally, now we check CancelClose() // for each tab -- group gets removed ONLY if ALL of // group tabs are closed + vv.Clear(); + Vectorvi; for(int i = tabs.GetCount() - 1; i >= 0; i--) { if(groupName == tabs[i].group && tabs.GetCount() > 1) { Value v = tabs[i].key; @@ -661,20 +658,29 @@ void TabBar::DoCloseGroup(int n) { nTabs--; WhenClose(v); - tabs.Remove(i); + // record keys and indexes of tabs to remove + vv << v; + vi << i; } } - // remove group if all of its tabs get closed - if(!nTabs) { - if(cnt == n) - group--; - if(cnt > 1) - groups.Remove(n); - } - MakeGroups(); - Repos(); - SetCursor(-1); } + // and now do the true removal + WhenCloseSome(Vector(vv,0)); + for(int i = 0; i < vv.GetCount(); i++) + { + TabClosed(vv[i]); + tabs.Remove(vi[i]); + } + // remove group if all of its tabs get closed + if(!nTabs) { + if(cnt == n) + group--; + if(cnt > 1) + groups.Remove(n); + } + MakeGroups(); + Repos(); + SetCursor(-1); } return; } @@ -686,6 +692,7 @@ void TabBar::DoCloseGroup(int n) Value v = tabs[i].value; // should be key ?? if (!CancelClose(v)) { WhenClose(v); + TabClosed(v); tabs.Remove(i); } } @@ -1076,7 +1083,11 @@ void TabBar::Paint(Draw &w) IsVert() ? w.DrawRect(align == LEFT ? sz.cx - 1 : 0, 0, 1, sz.cy, Blend(SColorDkShadow, SColorShadow)): w.DrawRect(0, align == TOP ? sz.cy - 1 : 0, sz.cx, 1, Blend(SColorDkShadow, SColorShadow)); - if (!tabs.GetCount()) return; + if (!tabs.GetCount()) { + if (align == BOTTOM || align == RIGHT) + w.End(); + return; + } int limt = sc.GetPos() + (IsVert() ? sz.cy : sz.cx); int first = 0; @@ -1167,12 +1178,12 @@ void TabBar::Paint(Draw &w) w.DrawImage(p, mouse.y - isz.cy / 2, isz.cx, isz.cy, dragtab); } + if (align == BOTTOM || align == RIGHT) + w.End(); + // If not in a frame fill any spare area if (!InFrame()) w.DrawRect(GetClientArea(), SColorFace()); - - if (align == BOTTOM || align == RIGHT) - w.EndOp(); } Image TabBar::GetDragSample() @@ -1772,8 +1783,7 @@ TabBar& TabBar::SetScrollThickness(int sz) void TabBar::Layout() { if (autoscrollhide && tabs.GetCount()) - SyncScrollBar(false); - Repos(); + SyncScrollBar(false); } int TabBar::FindValue(const Value &v) const @@ -1917,6 +1927,7 @@ void TabBar::SetIcon(int n, Image icon) void TabBar::LeftDown(Point p, dword keyflags) { + p = AdjustMouse(p); SetCapture(); if(keyflags & K_SHIFT) @@ -1942,9 +1953,12 @@ void TabBar::LeftDown(Point p, dword keyflags) vv.Add(v); int ix = cross; if (!CancelClose(v) && !CancelCloseSome(Vector(vv, 0))) { - Close(ix); + // 2014/03/06 - FIRST the callbacks, THEN remove the tab + // otherwise keys in WhenCloseSome() are invalid WhenClose(v); WhenCloseSome(vv); + TabClosed(v); + Close(ix); } if (tempCross >= 0 && tempCross < tabs.GetCount()) ProcessMouse(tempCross, p); @@ -1975,7 +1989,13 @@ void TabBar::LeftDouble(Point p, dword keysflags) void TabBar::RightDown(Point p, dword keyflags) { if (contextmenu) + { + // 2014/03/07 needed on X11 otherwise may crash + // if focus is nowhere (probable bug somewhere else...) + if(!GetActiveCtrl()) + GetParent()->SetFocus(); MenuBar::Execute(THISBACK(ContextMenu), GetMousePos()); + } } void TabBar::MiddleDown(Point p, dword keyflags) @@ -1987,9 +2007,12 @@ void TabBar::MiddleDown(Point p, dword keyflags) vv.Add(v); if (!CancelClose(v) && ! CancelCloseSome(Vector(vv, 0))) { Value v = tabs[highlight].key; - Close(highlight); + // 2014/03/06 - FIRST the callbacks, THEN remove the tab + // otherwise keys in WhenCloseSome() are invalid WhenClose(v); WhenCloseSome(vv); + TabClosed(v); + Close(highlight); } } } @@ -2035,6 +2058,17 @@ void TabBar::MouseWheel(Point p, int zdelta, dword keyflags) MouseMove(p, 0); } +Point TabBar::AdjustMouse(Point const &p) const +{ + int align = GetAlign(); + if(align == TOP || align == LEFT) + return p; + + Size ctrlsz = GetSize(); + Size sz = GetBarSize(ctrlsz); + return Point(p.x - ctrlsz.cx + sz.cx, p.y - ctrlsz.cy + sz.cy); +} + bool TabBar::ProcessMouse(int i, const Point& p) { if(i >= 0 && i < tabs.GetCount() && tabs[i].HasMouse(p)) @@ -2082,6 +2116,7 @@ void TabBar::SetColor(int n, Color c) void TabBar::MouseMove(Point p, dword keyflags) { + p = AdjustMouse(p); if(HasCapture() && (keyflags & K_SHIFT)) { Fix(p); @@ -2292,7 +2327,7 @@ bool TabBar::SetCursor0(int n, bool action) if(Ctrl::HasMouse()) { - Sync(); + Refresh(); MouseMove(GetMouseViewPos(), 0); } return true; @@ -2341,7 +2376,7 @@ void TabBar::CloseForce(int n, bool action) //TODO: That must be refactored highlight = -1; drag_highlight = -1; - Sync(); + Refresh(); MouseMove(GetMouseViewPos(), 0); } } @@ -2495,8 +2530,6 @@ void TabBar::Serialize(Stream& s) int g = GetGroup(); s % g; group = g; - - Repos(); } CH_STYLE(TabBar, Style, StyleDefault) diff --git a/uppsrc/TabBar/TabBar.h b/uppsrc/TabBar/TabBar.h index 15d63795a..6429296a9 100644 --- a/uppsrc/TabBar/TabBar.h +++ b/uppsrc/TabBar/TabBar.h @@ -180,7 +180,7 @@ public: Array items; int itn; - Tab(); + Tab() : id(-1), stack(-1), visible(true), itn(0) { items.SetCount(5); } Tab(const Tab& t) { Set(t); } void Set(const Tab& t); @@ -336,6 +336,7 @@ protected: virtual void Layout(); // Mouse handling/tab positioning + Point AdjustMouse(Point const &p) const; bool ProcessMouse(int i, const Point& p); bool ProcessStackMouse(int i, const Point& p); void SetHighlight(int n); @@ -379,6 +380,8 @@ protected: virtual String GetStackId(const Tab& a) { return a.group; } // For sub-classes to recieve cursor changes without using WhenAction virtual void CursorChanged() { } + // for sub-classes to receive tab closes without using WhenClose + virtual void TabClosed(Value key) { } public: typedef TabBar CLASSNAME; diff --git a/uppsrc/TabBar/TabBarCtrl.cpp b/uppsrc/TabBar/TabBarCtrl.cpp index 323f1d375..816d4cc8e 100644 --- a/uppsrc/TabBar/TabBarCtrl.cpp +++ b/uppsrc/TabBar/TabBarCtrl.cpp @@ -75,8 +75,7 @@ void TabBarCtrl::SetCtrl(Value key) int ix = ctrls.Find(key); if (ix < 0) return; - for (int i = 0; i < ctrls.GetCount(); i++) - ctrls[i]->Show(i == ix); + SetData(key); } void TabBarCtrl::SetCtrl(int ix) @@ -87,13 +86,25 @@ void TabBarCtrl::SetCtrl(int ix) void TabBarCtrl::SetCtrl(Ctrl &ctrl) { - for (int i = 0; i < ctrls.GetCount(); ++i) - ctrls[i]->Show(ctrls[i] == &ctrl); + for(int i = 0; i < ctrls.GetCount(); i++) + if(ctrls[i] == &ctrl) + { + SetData(ctrls.GetKey(i)); + return; + } + SetData(-1); } void TabBarCtrl::CursorChanged() { - SetCtrl(GetData()); + Value ix = GetData(); + for (int i = 0; i < ctrls.GetCount(); i++) + ctrls[i]->Show(ctrls.GetKey(i) == ix); +} + +void TabBarCtrl::TabClosed(Value key) +{ + ctrls.RemoveKey(key); } END_UPP_NAMESPACE \ No newline at end of file diff --git a/uppsrc/TabBar/TabBarCtrl.h b/uppsrc/TabBar/TabBarCtrl.h index 2751d5aab..655787686 100644 --- a/uppsrc/TabBar/TabBarCtrl.h +++ b/uppsrc/TabBar/TabBarCtrl.h @@ -2,7 +2,7 @@ class TabBarCtrl : public TabBar { private: VectorMap ctrls; - ParentCtrl pane; + StaticRect pane; public: TabBarCtrl() { Ctrl::Add(pane); } @@ -27,4 +27,5 @@ public: void SetCtrl(Ctrl &ctrl); protected: virtual void CursorChanged(); + virtual void TabClosed(Value key); };