diff --git a/uppsrc/ide/Assist.cpp b/uppsrc/ide/Assist.cpp index c68f321be..4aaf092c8 100644 --- a/uppsrc/ide/Assist.cpp +++ b/uppsrc/ide/Assist.cpp @@ -46,26 +46,38 @@ AssistEditor::AssistEditor() navigating = false; int cy = search.GetMinSize().cy; - navigatorpane.Add(search.TopPos(0, cy).HSizePos()); + navigatorpane.Add(search.TopPos(0, cy).HSizePos(0, cy + 4)); + navigatorpane.Add(sortitems.TopPos(0, cy).RightPos(0, cy)); navigatorpane.Add(navigator_splitter.VSizePos(cy, 0).HSizePos()); scope.NoHeader(); scope.AddColumn().SetDisplay(Single()); scope.NoWantFocus(); scope.WhenSel = THISBACK(Scope); - navigator_splitter.Vert(scope, list); - navigator_splitter.SetPos(2000); + navigator_splitter.Vert() << scope << list << navlines; + navigator_splitter.SetPos(1500, 0); + navigator_splitter.SetPos(8000, 1); + navigator_splitter.SetPos(500, 2); list.NoHeader(); list.AddRowNumColumn().SetDisplay(navidisplay); list.SetLineCy(max(16, GetStdFontCy())); list.NoWantFocus(); list.WhenLeftClick = THISBACK(NavigatorClick); + list.WhenSel = THISBACK(SyncNavLines); list.WhenLineEnabled = THISBACK(ListLineEnabled); + navlines.NoHeader().NoWantFocus(); + navlines.WhenLeftClick = THISBACK(GoToNavLine); + navlines.AddColumn().SetDisplay(Single()); + search <<= THISBACK(TriggerSearch); search.SetFilter(CharFilterNavigator); search.WhenEnter = THISBACK(NavigatorEnter); + sortitems.Image(BrowserImg::Sort()); + sortitems <<= THISBACK(NaviSort); + sorting = false; + navigator = true; WhenAnnotationMove = THISBACK(SyncAnnotationPopup); diff --git a/uppsrc/ide/Navigator.cpp b/uppsrc/ide/Navigator.cpp index e2c023904..4875946c3 100644 --- a/uppsrc/ide/Navigator.cpp +++ b/uppsrc/ide/Navigator.cpp @@ -19,18 +19,92 @@ void AssistEditor::SyncCursor() search.NullText("Symbol/lineno " + k); search.Tip(IsNull(search) ? String() : "Clear " + k); - if(navigating) - return; - int q = linefo.Find(GetCppFileIndex(theide->editfile)); - if(q < 0) - return; - SortedVectorMap& m = linefo[q]; - q = m.FindUpperBound(GetLine(GetCursor()) + 1) - 1; - if(q >= 0 && q < m.GetCount()) { + if(!navigating) { + navlines.KillCursor(); + int q = linefo.Find(GetCppFileIndex(theide->editfile)); + if(q < 0) + return; navigating = true; - list.SetCursor(m[q]); + SortedVectorMap& m = linefo[q]; + q = m.FindUpperBound(GetLine(GetCursor()) + 1) - 1; + if(q >= 0 && q < m.GetCount()) + list.SetCursor(m[q]); navigating = false; } + SyncLines(); +} + +void AssistEditor::SyncLines() +{ + int ln = GetLine(GetCursor()) + 1; + int fi = GetCppFileIndex(theide->editfile); + int q = -1; + for(int i = 0; i < navlines.GetCount(); i++) { + const NavLine& l = navlines.Get(i, 0).To(); + if(l.file == fi && l.line <= ln && i < navlines.GetCount()) + q = i; + } + if(q >= 0) + navlines.SetCursor(q); +} + +void AssistEditor::SyncNavLines() +{ + int sc = navlines.GetScroll(); + navlines.Clear(); + int ii = list.GetCursor(); + if(ii >= 0 && ii < litem.GetCount()) { + int ln = GetLine(GetCursor()) + 1; + Vector l = GetNavLines(*litem[ii]); + for(int i = 0; i < l.GetCount(); i++) { + String p = GetCppFile(l[i].file); + navlines.Add(RawToValue(l[i])); + } + navlines.ScrollTo(sc); + SyncLines(); + } +} + +void PaintTeXt(Draw& w, int& x, int y, const String& text, Font font, Color ink) +{ + Size sz = GetTextSize(text, font); + w.DrawText(x, y, text, font, ink); + x += sz.cx; +} + +int AssistEditor::LineDisplay::DoPaint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const +{ + w.DrawRect(r, paper); + const NavLine& l = q.To(); + int x = r.left; + String p = GetCppFile(l.file); + int y = r.top + (r.GetHeight() - StdFont().GetCy()) / 2; + PaintTeXt(w, x, y, GetFileName(GetFileFolder(p)) + "/", StdFont(), ink); + PaintTeXt(w, x, y, GetFileName(p), StdFont().Bold(), ink); + PaintTeXt(w, x, y, " (", StdFont(), ink); + PaintTeXt(w, x, y, AsString(l.line), StdFont().Bold(), ink); + PaintTeXt(w, x, y, ")", StdFont(), ink); + return x; +} + +void AssistEditor::LineDisplay::Paint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const +{ + DoPaint(w, r, q, ink, paper, style); +} + +Size AssistEditor::LineDisplay::GetStdSize(const Value& q) const +{ + NilDraw w; + return Size(DoPaint(w, Size(999999, 999999), q, White(), White(), 0), StdFont().Bold().GetCy()); +} + +void AssistEditor::GoToNavLine() +{ + int ii = navlines.GetClickPos().y; + if(ii >= 0 && ii < navlines.GetCount() && theide) { + const NavLine& l = navlines.Get(ii, 0).To(); + theide->GotoPos(GetCppFile(l.file), l.line); + } } void AssistEditor::SelectionChanged() @@ -40,6 +114,37 @@ void AssistEditor::SelectionChanged() SyncParamInfo(); } +bool AssistEditor::NavLine::operator<(const NavLine& b) const +{ + String p1 = GetCppFile(file); + String p2 = GetCppFile(b.file); + return CombineCompare(!impl, !b.impl) + (GetFileExt(p1), GetFileExt(p2)) // .h > .c + (GetFileName(p1), GetFileName(p2)) + (p1, p2) + (line, b.line) < 0; +} + +Vector AssistEditor::GetNavLines(const NavItem& m) +{ + Vector l; + int q = CodeBase().Find(m.nest); + if(q < 0) + return l; + const Array& a = CodeBase()[q]; + for(int i = 0; i < a.GetCount(); i++) { + const CppItem& mm = a[i]; + if(mm.qitem == m.qitem) { + NavLine& nl = l.Add(); + nl.impl = mm.impl; + nl.file = mm.file; + nl.line = mm.line; + } + } + Sort(l); + return l; +} + void AssistEditor::Navigate() { if(navigating) @@ -49,37 +154,20 @@ void AssistEditor::Navigate() if(theide && ii >= 0 && ii < litem.GetCount()) { int ln = GetLine(GetCursor()) + 1; const NavItem& m = *litem[ii]; - if(m.kind == KIND_LINE || IsNull(search) && m.line != ln) { + if(m.kind == KIND_LINE || IsNull(search)) theide->GotoPos(Null, m.line); - navigating = false; - return; - } - int q = CodeBase().Find(m.nest); - if(q < 0) { - navigating = false; - return; - } - const Array& a = CodeBase()[q]; - Vector l; - for(int i = 0; i < a.GetCount(); i++) { - const CppItem& mm = a[i]; - if(mm.qitem == m.qitem) { - NavLine& nl = l.Add(); - nl.impl = mm.impl; - nl.file = mm.file; - nl.line = mm.line; + else { + Vector l = GetNavLines(m); + int q = l.GetCount() - 1; + for(int i = q; i >= 0; i--) { + if(GetCppFile(l[i].file) == theide->editfile && l[i].line == ln) { + q = (i + l.GetCount() - 1) % l.GetCount(); + break; + } } + if(q >= 0 && q < l.GetCount()) + theide->GotoPos(GetCppFile(l[q].file), l[q].line); } - Sort(l); - q = 0; - for(int i = 0; i < l.GetCount(); i++) { - if(GetCppFile(l[i].file) == theide->editfile && l[i].line == ln) { - q = (i + 1) % l.GetCount(); - break; - } - } - if(q >= 0 && q < l.GetCount()) - theide->GotoPos(GetCppFile(l[q].file), l[q].line); } navigating = false; } @@ -249,12 +337,6 @@ Size AssistEditor::NavigatorDisplay::GetStdSize(const Value& q) const return Size(DoPaint(w, Size(999999, 999999), q, White(), White(), 0), Draw::GetStdFontCy()); } -force_inline -bool AssistEditor::NavItem::operator<(const NavItem& b) const -{ - return CombineCompare(decl_file, b.decl_file)(decl_line, b.decl_line); -} - void AssistEditor::TriggerSearch() { search_trigger.KillSet(100, THISBACK(Search)); @@ -279,8 +361,21 @@ void AssistEditor::NavGroup(bool local) } } +force_inline +bool AssistEditor::SortByLines(const NavItem *a, const NavItem *b) +{ + return CombineCompare(a->decl_file, b->decl_file)(a->decl_line, b->decl_line) < 0; +} + +force_inline +bool AssistEditor::SortByNames(const NavItem *a, const NavItem *b) +{ + return CombineCompare(a->name, b->name)(a->qitem, b->qitem) < 0; +} + void AssistEditor::Search() { + sortitems.Check(sorting); int sc = scope.GetScroll(); String key = scope.GetKey(); String s = TrimBoth(~search); @@ -391,22 +486,23 @@ void AssistEditor::Search() nitem = imap.PickValues(); NavGroup(false); SortByKey(gitem); - for(int i = 0; i < gitem.GetCount(); i++) { - scope.Add(gitem.GetKey(i)); - Sort(gitem[i]); - } + Index sc; + for(int i = 0; i < gitem.GetCount(); i++) + Sort(gitem[i], sorting ? SortByLines : SortByNames); } scope.Clear(); scope.Add(Null); - for(int i = 0; i < gitem.GetCount(); i++) - scope.Add(gitem.GetKey(i)); + Index done; + for(int i = 0; i < gitem.GetCount(); i++) { + String s = gitem.GetKey(i); + if(done.Find(s) < 0) { + done.Add(s); + scope.Add(gitem.GetKey(i)); + } + } scope.ScrollTo(sc); if(!navigator_global || !scope.FindSetCursor(key)) scope.GoBegin(); - if(navigator_global) - navigator_splitter.NoZoom(); - else - navigator_splitter.Zoom(1); } int AssistEditor::PaintFileName(Draw& w, const Rect& r, String h, Color ink) @@ -488,4 +584,10 @@ void AssistEditor::ListLineEnabled(int i, bool& b) if(findarg(kind, KIND_FILE, KIND_NEST) >= 0) b = false; } -} \ No newline at end of file +} + +void AssistEditor::NaviSort() +{ + sorting = !sorting; + Search(); +} diff --git a/uppsrc/ide/icon.ico b/uppsrc/ide/icon.ico index 76862d167..da67a3075 100644 Binary files a/uppsrc/ide/icon.ico and b/uppsrc/ide/icon.ico differ diff --git a/uppsrc/ide/ide.h b/uppsrc/ide/ide.h index e03d12133..e8d048566 100644 --- a/uppsrc/ide/ide.h +++ b/uppsrc/ide/ide.h @@ -296,6 +296,7 @@ struct AssistEditor : CodeEditor { StaticRect navigatorpane; ArrayCtrl scope; ArrayCtrl list; + ArrayCtrl navlines; Splitter navigator_splitter; EditString search; @@ -304,11 +305,7 @@ struct AssistEditor : CodeEditor { int file:31; int line; - bool operator <(const NavLine& b) const { - return CombineCompare(!impl, !b.impl) - (GetFileName(GetCppFile(file)), GetFileName(GetCppFile(b.file))) - (line, b.line); - } + bool operator<(const NavLine& b) const; }; struct NavItem { @@ -333,7 +330,6 @@ struct AssistEditor : CodeEditor { bool decl; Vector linefo; - bool operator<(const NavItem& b) const; void Set(const CppItem& m); }; @@ -344,6 +340,12 @@ struct AssistEditor : CodeEditor { virtual void Paint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const; virtual Size GetStdSize(const Value& q) const; }; + + struct LineDisplay : Display { + int DoPaint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const; + virtual void Paint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const; + virtual Size GetStdSize(const Value& q) const; + }; struct NavigatorDisplay : Display { const Vector& item; @@ -367,12 +369,18 @@ struct AssistEditor : CodeEditor { bool navigating; TimeCallback search_trigger; bool navigator_global; + ToolButton sortitems; + bool sorting; void TriggerSearch(); void NavGroup(bool local); void Search(); void Scope(); void ListLineEnabled(int i, bool& b); + void NaviSort(); + + static bool SortByLines(const NavItem *a, const NavItem *b); + static bool SortByNames(const NavItem *a, const NavItem *b); Splitter popup; ArrayCtrl assist; @@ -462,10 +470,15 @@ struct AssistEditor : CodeEditor { void SyncCursor(); + Vector GetNavLines(const NavItem& m); + void Navigate(); void NavigatorClick(); void NavigatorEnter(); void SyncNavigator(); + void SyncLines(); + void SyncNavLines(); + void GoToNavLine(); bool IsNavigator() const { return navigator; } void Navigator(bool navigator);