ide: Navigator redesigned

git-svn-id: svn://ultimatepp.org/upp/trunk@7544 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2014-07-27 17:30:10 +00:00
parent 934a772905
commit 1782be860f
9 changed files with 392 additions and 98 deletions

View file

@ -381,7 +381,7 @@ public:
Column& AddColumn(const Id& id, const char *text, int w = 0);
Column& AddColumnAt(int ii, const char *text, int w = 0);
Column& AddColumnAt(const Id& id, const char *text, int w = 0);
Column& AddRowNumColumn(const char *text, int w = 0);
Column& AddRowNumColumn(const char *text = NULL, int w = 0);
int GetColumnCount() const { return column.GetCount(); }
int FindColumnWithPos(int pos) const;

View file

@ -2,7 +2,7 @@
#define _CtrlLib_icpp_init_stub
#include "CtrlCore/init"
#include "PdfDraw/init"
#define BLITZ_INDEX__ F2a95805f3896075b0a556396aabaf515
#define BLITZ_INDEX__ Fa588a2a7bb40a3ed36760f6c2bef5026
#include "CtrlLib.icpp"
#undef BLITZ_INDEX__
#endif

View file

@ -18,7 +18,13 @@ class IndexSeparatorFrameCls : public CtrlFrame {
virtual void FrameAddSize(Size& sz) { sz.cx += 2; }
};
int CharFilterNavigator(int c)
{
return c == '.' ? ':' : IsAlNum(c) || c == '_' || c == ':' ? ToUpper(c) : 0;
}
AssistEditor::AssistEditor()
: navidisplay(item)
{
assist.NoHeader();
assist.NoGrid();
@ -37,7 +43,9 @@ AssistEditor::AssistEditor()
InsertFrame(1, navigatorframe);
navigatorframe.Left(navigatorpane, HorzLayoutZoom(140));
navigating = false;
/*
int cy = EditField::GetStdHeight();
int c2 = cy + 2;
@ -59,7 +67,20 @@ AssistEditor::AssistEditor()
browser.WhenKeyItem = THISBACK(BrowserGotoNF);
browser.WhenClear = THISBACK(SyncCursor);
browser.NameStart();
*/
int cy = search.GetMinSize().cy;
navigatorpane.Add(search.TopPos(0, cy).HSizePos());
navigatorpane.Add(list.VSizePos(cy, 0).HSizePos());
list.NoHeader();
list.AddRowNumColumn().SetDisplay(navidisplay);
list.SetLineCy(2 * GetStdFontCy());
list.NoWantFocus();
list.WhenSel = THISBACK(Navigate);
search <<= THISBACK(Search);
search.SetFilter(CharFilterNavigator);
search.WhenEnter = THISBACK(NavigatorEnter);
navigator = true;
WhenAnnotationMove = THISBACK(SyncAnnotationPopup);
@ -725,22 +746,6 @@ bool AssistEditor::InCode()
bool AssistEditor::Key(dword key, int count)
{
if(browser.Key(key, count))
return true;
if(browser.search.HasFocus()) {
if(key == K_ENTER) {
browser.search.Clear();
GotoBrowserScope();
return true;
}
if(key == K_ESCAPE) {
browser.search.Clear();
SetFocus();
SyncCursor();
return true;
}
}
if(popup.IsOpen()) {
int k = key & ~K_CTRL;
ArrayCtrl& kt = key & K_CTRL ? type : assist;
@ -774,6 +779,8 @@ bool AssistEditor::Key(dword key, int count)
int cc = GetChar(c);
int bcc = c > 0 ? GetChar(c - 1) : 0;
bool b = CodeEditor::Key(key, count);
if(b && search.HasFocus())
SetFocus();
if(assist.IsOpen()) {
bool (*test)(int c) = include_assist ? isincludefnchar : iscid;
if(!(*test)(key) &&

View file

@ -1,11 +1,43 @@
#include "ide.h"
#if 0
// THIS IS SANDBOX FOR DEVELOPING NEW NAVIGATOR
struct Navigator : TopWindow {
EditString search;
ArrayCtrl list;
struct NavItem {
String nest;
String name;
String uname;
String natural;
String type;
String pname;
String ptype;
String tname;
String ctname;
byte access;
byte kind;
int16 at;
int line;
int file;
bool impl;
void Set(const CppItem& m);
};
struct NavigatorDisplay : Display {
const Array<NavItem>& item;
virtual void Paint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const;
NavigatorDisplay(const Array<NavItem>& item) : item(item) {}
};
Array<NavItem> item;
NavigatorDisplay navidisplay;
void Search();
typedef Navigator CLASSNAME;
@ -13,70 +45,92 @@ struct Navigator : TopWindow {
Navigator();
};
struct NavigatorDisplay : Display {
virtual void Paint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const
{
CppItem m;
LoadFromString(m, q);
w.DrawRect(r, paper);
bool focuscursor = (style & (FOCUS|CURSOR)) == (FOCUS|CURSOR) || (style & SELECT);
if(IsNull(q)) return;
int x = r.left;
int fcy = Draw::GetStdFontCy();
int y = r.top + r.GetHeight() / 2 - fcy;
int x0 = x;
Vector<ItemTextPart> n = ParseItemNatural(m.name, m, ~m.natural + m.at);
int starti = 0;
for(int i = 0; i < n.GetCount(); i++)
if(n[i].type == ITEM_NAME) {
starti = i;
break;
}
PaintText(w, x, y, ~m.natural, n, 0, starti, focuscursor, ink, false);
if(m.item.GetCount()) {
String h = ' ' + m.item;
h.Cat("::");
w.DrawText(x, y, h, StdFont().Bold(), Magenta());
x += GetTextSize(h, StdFont()).cx;
void Navigator::NavItem::Set(const CppItem& m)
{
name = m.name;
uname = m.uname;
natural = m.natural;
type = m.type;
pname = m.pname;
ptype = m.ptype;
tname = m.tname;
ctname = m.ctname;
access = m.access;
kind = m.kind;
at = m.at;
line = m.line;
file = m.file;
impl = m.impl;
}
void Navigator::NavigatorDisplay::Paint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const
{
int ii = q;
if(ii < 0 || ii >= item.GetCount())
return;
const NavItem& m = item[(int)q];
w.DrawRect(r, paper);
bool focuscursor = (style & (FOCUS|CURSOR)) == (FOCUS|CURSOR) || (style & SELECT);
if(IsNull(q)) return;
int x = r.left;
int fcy = Draw::GetStdFontCy();
int y = r.top + r.GetHeight() / 2 - fcy;
int x0 = x;
Vector<ItemTextPart> n = ParseItemNatural(m.name, m.natural, m.ptype, m.pname, m.type,
m.tname, m.ctname, ~m.natural + m.at);
int starti = 0;
for(int i = 0; i < n.GetCount(); i++)
if(n[i].type == ITEM_NAME) {
starti = i;
break;
}
int x1 = r.left;
PaintText(w, x1, y + fcy, ~m.natural, n, starti, n.GetCount(), focuscursor, ink, false);
PaintText(w, x, y, ~m.natural, n, 0, starti, focuscursor, ink, false);
if(m.nest.GetCount()) {
String h = ' ' + m.nest;
h.Cat("::");
w.DrawText(x, y, h, StdFont().Bold(), Magenta());
x += GetTextSize(h, StdFont()).cx;
}
};
int x1 = r.left;
PaintText(w, x1, y + fcy, ~m.natural, n, starti, n.GetCount(), focuscursor, ink, false);
}
void Navigator::Search()
{
String s = ~search;
list.Clear();
// TODO: Be smarter with '::'
CppBase& b = CodeBase();
item.Clear();
const CppBase& b = CodeBase();
ArrayMap<String, NavItem> imap;
for(int i = 0; i < b.GetCount(); i++) {
String nest = b.GetKey(i);
String unest = ToUpper(nest);
Array<CppItem>& item = b[i];
for(int j = 0; j < item.GetCount(); j++) {
CppItem m;
{ DTIMING("Copy");
m = item[j]; }
m.item = nest; // Ugly trick...
const Array<CppItem>& ci = b[i];
for(int j = 0; j < ci.GetCount(); j++) {
const CppItem& m = ci[j];
String h = unest;
{ DTIMING("CAT");
h << "::" << m.uname; }
int q;
{ DTIMING("FIND");
q = h.Find(s);
}
h << "::" << m.uname;
if(h.Find(s) >= 0) {
String sh;
{ DTIMING("StoreAsString");
sh = StoreAsString(m);
String key = nest + '\1' + m.qitem;
int q = imap.Find(key);
if(q < 0) {
NavItem& ni = imap.Add(key);
ni.Set(m);
ni.nest = nest;
}
else {
NavItem& mm = imap[q];
String n = mm.natural;
if(m.natural.GetCount() > mm.natural.GetCount())
mm.natural = m.natural;
if(CombineCompare(mm.impl, m.impl)(m.file, mm.file)(m.line, mm.line) < 0)
mm.Set(m);
}
DTIMING("Add");
list.Add(nest, sh, h);
}
}
}
item = imap.PickValues();
list.SetVirtualCount(item.GetCount());
}
int CharFilterNavigator(int c)
@ -85,14 +139,13 @@ int CharFilterNavigator(int c)
}
Navigator::Navigator()
: navidisplay(item)
{
int cy = search.GetMinSize().cy;
Add(search.TopPos(0, cy).HSizePos());
Add(list.VSizePos(cy, 0).HSizePos());
list.NoHeader();
list.AddColumn();
list.AddColumn().SetDisplay(Single<NavigatorDisplay>());
list.AddColumn();
list.AddRowNumColumn().SetDisplay(navidisplay);
list.SetLineCy(2 * GetStdFontCy());
search <<= THISBACK(Search);
@ -102,4 +155,5 @@ Navigator::Navigator()
void Ide::CodeBrowser()
{
Navigator().Run();
}
}
#endif

View file

@ -2,8 +2,10 @@
void AssistEditor::SyncNavigator()
{
if(navigating)
return;
if(IsNavigator()) {
browser.Load();
Search();
SyncCursor();
}
navigatorframe.Show(navigator && theide && !theide->IsEditorMode());
@ -11,15 +13,19 @@ void AssistEditor::SyncNavigator()
void AssistEditor::SyncCursor()
{
String k = "(" + GetKeyDesc(IdeKeys::AK_SEARCHCODE().key[0]) + ") ";
browser.search.NullText(String("Find ") + k);
browser.search.Tip(IsNull(browser.search) ? String() : "Clear " + k);
if(IsNavigator()) {
int ii = GetCursorLine();
String coderef;
while(ii >= 0 && IsNull(coderef))
coderef = GetAnnotation(ii--);
browser.Goto(coderef, theide->editfile);
String k = "(" + GetKeyDesc(IdeKeys::AK_GOTO().key[0]) + ") ";
search.NullText("Symbol/lineno " + k);
search.Tip(IsNull(search) ? String() : "Clear " + k);
if(IsNull(search)) {
int ii = 0;
int line = GetLine(GetCursor());
for(int i = 0; i < item.GetCount(); i++)
if(item[i].line - 1 <= line)
ii = i;
navigating = true;
list.SetCursor(ii);
navigating = false;
}
}
@ -32,6 +38,7 @@ void AssistEditor::SelectionChanged()
void AssistEditor::BrowserGotoNF()
{
/* NAVI
Value scope = browser.scope.GetKey(); // do not scroll browser.item erratically
int scopesc = browser.scope.GetScroll();
String item = browser.item.GetKey();
@ -49,6 +56,35 @@ void AssistEditor::BrowserGotoNF()
browser.item.ScrollIntoCursor();
}
}
*/
}
void AssistEditor::Navigate()
{
if(navigating)
return;
navigating = true;
int ii = list.GetCursor();
if(theide && ii >= 0 && ii < item.GetCount()) {
const NavItem& m = item[ii];
if(m.kind == KIND_LINE || IsNull(search))
theide->GotoPos(Null, item[ii].line);
else
theide->IdeGotoCodeRef(MakeCodeRef(item[ii].nest, item[ii].qitem));
}
navigating = false;
}
void AssistEditor::NavigatorEnter()
{
if(list.GetCount()) {
list.GoBegin();
Navigate();
if(item[0].kind == KIND_LINE) {
search.Clear();
Search();
}
}
}
void AssistEditor::BrowserGoto()
@ -59,6 +95,7 @@ void AssistEditor::BrowserGoto()
void AssistEditor::GotoBrowserScope()
{
/* NAVI
if(browser.scope.IsCursor()) {
Value x = browser.scope.Get(2);
if(IsNumber(x)) {
@ -71,6 +108,7 @@ void AssistEditor::GotoBrowserScope()
browser.item.GoBegin();
BrowserGoto();
}
*/
}
void AssistEditor::Navigator(bool nav)
@ -78,8 +116,8 @@ void AssistEditor::Navigator(bool nav)
navigator = nav;
navigatorframe.Show(navigator && theide && !theide->IsEditorMode());
if(IsNavigator()) {
scope_item.Show();
browser.ClearSearch();
// scope_item.Show(); NAVI
// browser.ClearSearch();
SetFocus();
}
SyncNavigator();
@ -88,12 +126,14 @@ void AssistEditor::Navigator(bool nav)
void AssistEditor::SerializeNavigator(Stream& s)
{
int version = 1;
int version = 2;
s / version;
s % navigatorframe;
s % navigator;
if(version >= 1)
if(version >= 1 && version < 2) {
Splitter scope_item;
s % scope_item;
}
Navigator(navigator);
}
@ -106,6 +146,13 @@ void Ide::SearchCode()
{
if(!editor.navigator)
editor.Navigator(true);
if(!IsNull(~editor.search)) {
editor.search.Clear();
editor.Search();
}
else
editor.search.SetFocus();
/* NAVI
if(editor.browser.search.HasFocus() && editor.browser.IsSearch())
editor.browser.ClearSearch();
else {
@ -118,6 +165,7 @@ void Ide::SearchCode()
}
editor.browser.search.SetFocus();
}
*/
}
void Ide::SwitchHeader() {
@ -133,3 +181,140 @@ void Ide::SwitchHeader() {
if(f >= 0) filelist.SetCursor(f);
}
}
void AssistEditor::NavItem::Set(const CppItem& m)
{
qitem = m.qitem;
name = m.name;
uname = m.uname;
natural = m.natural;
type = m.type;
pname = m.pname;
ptype = m.ptype;
tname = m.tname;
ctname = m.ctname;
access = m.access;
kind = m.kind;
at = m.at;
line = m.line;
file = m.file;
impl = m.impl;
}
int AssistEditor::NavigatorDisplay::DoPaint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const
{
int ii = q;
if(ii < 0 || ii >= item.GetCount())
return 0;
const NavItem& m = item[(int)q];
w.DrawRect(r, paper);
bool focuscursor = (style & (FOCUS|CURSOR)) == (FOCUS|CURSOR) || (style & SELECT);
if(IsNull(q))
return 0;
int x = r.left;
int fcy = Draw::GetStdFontCy();
int y = r.top + r.GetHeight() / 2 - fcy;
if(m.kind == KIND_LINE) {
w.DrawText(x, y, m.type, StdFont().Bold(), ink);
return GetTextSize(m.type, StdFont().Bold()).cx;
}
Vector<ItemTextPart> n = ParseItemNatural(m.name, m.natural, m.ptype, m.pname, m.type,
m.tname, m.ctname, ~m.natural + m.at);
int starti = 0;
for(int i = 0; i < n.GetCount(); i++)
if(n[i].type == ITEM_NAME) {
starti = i;
break;
}
PaintText(w, x, y, ~m.natural, n, 0, starti, focuscursor, ink, false);
if(m.nest.GetCount()) {
String h;
if(x > r.left)
h << ' ';
h << m.nest;
h.Cat("::");
w.DrawText(x, y, h, StdFont().Bold(), Magenta());
x += GetTextSize(h, StdFont()).cx;
}
int x1 = r.left;
PaintText(w, x1, y + fcy, ~m.natural, n, starti, n.GetCount(), focuscursor, ink, false);
return max(x, x1) - r.left;
}
void AssistEditor::NavigatorDisplay::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::NavigatorDisplay::GetStdSize(const Value& q) const
{
return Size(DoPaint(NilDraw(), Size(999999, 999999), q, White(), White(), 0),
2 * Draw::GetStdFontCy());
}
void AssistEditor::Search()
{
list.Clear();
item.Clear();
String s = ~search;
s = Join(Split(s, ':'), "::") + (s.EndsWith(":") ? "::" : "");
int lineno = StrInt(s);
if(!IsNull(lineno)) {
NavItem& m = item.Add();
m.type = "Go to line " + AsString(lineno);
m.kind = KIND_LINE;
m.line = lineno;
}
else
if(IsNull(s)) {
int fileii = GetCppFileIndex(theide->editfile);
const CppBase& b = CodeBase();
ArrayMap<String, NavItem> imap;
for(int i = 0; i < b.GetCount(); i++) {
String nest = b.GetKey(i);
const Array<CppItem>& ci = b[i];
for(int j = 0; j < ci.GetCount(); j++) {
const CppItem& m = ci[j];
if(m.file == fileii) {
NavItem& n = item.Add();
n.Set(m);
n.nest = nest;
}
}
}
Sort(item, FieldRelation(&NavItem::line, StdLess<int>()));
}
else {
const CppBase& b = CodeBase();
ArrayMap<String, NavItem> imap;
for(int i = 0; i < b.GetCount(); i++) {
String nest = b.GetKey(i);
String unest = ToUpper(nest);
const Array<CppItem>& ci = b[i];
for(int j = 0; j < ci.GetCount(); j++) {
const CppItem& m = ci[j];
String h = unest;
h << "::" << m.uname;
if(h.Find(s) >= 0) {
String key = nest + '\1' + m.qitem;
int q = imap.Find(key);
if(q < 0) {
NavItem& ni = imap.Add(key);
ni.Set(m);
ni.nest = nest;
}
else {
NavItem& mm = imap[q];
String n = mm.natural;
if(m.natural.GetCount() > mm.natural.GetCount())
mm.natural = m.natural;
if(CombineCompare(mm.impl, m.impl)(m.file, mm.file)(m.line, mm.line) < 0)
mm.Set(m);
}
}
}
}
item = imap.PickValues();
}
list.SetVirtualCount(item.GetCount());
}

View file

@ -291,15 +291,57 @@ struct AssistEditor : CodeEditor {
Color ink;
int line;
};
byte navigator;
bool navigator;
SplitterFrame navigatorframe;
StaticRect navigatorpane;
ArrayCtrl list;
EditString search;
struct NavItem {
String nest;
String qitem;
String name;
String uname;
String natural;
String type;
String pname;
String ptype;
String tname;
String ctname;
byte access;
byte kind;
int16 at;
int line;
int file;
bool impl;
void Set(const CppItem& m);
};
enum { KIND_LINE = 123 };
struct NavigatorDisplay : Display {
const Array<NavItem>& item;
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;
NavigatorDisplay(const Array<NavItem>& item) : item(item) {}
};
Array<NavItem> item;
NavigatorDisplay navidisplay;
bool navigating;
void Search();
/*
CodeBrowser browser;
ParentCtrl scopepane;
ParentCtrl itempane;
Splitter scope_item;
*/
Splitter popup;
ArrayCtrl assist;
ArrayCtrl type;
@ -387,6 +429,9 @@ struct AssistEditor : CodeEditor {
void SwapSContext(Parser& p);
void SyncCursor();
void Navigate();
void NavigatorEnter();
void SyncNavigator();
void GotoBrowserScope();
@ -1193,7 +1238,7 @@ public:
// THIS IS SANDBOX FOR DEVELOPING NEW NAVIGATOR
void CodeBrowser();
// void CodeBrowser();
};
#endif

View file

@ -26,8 +26,8 @@ KEY(FINDSEL, "Find selected text", 0)
KEY(FINDNEXT, "Find Next", K_F3)
KEY(FINDPREV, "Find Previous", K_SHIFT_F3)
KEY(DOREPLACE, "Replace found text", K_CTRL_R)
KEY(GOTO, "Navigate in the file..", K_CTRL_G)
KEY(GOTOGLOBAL, "Navigate..", K_CTRL_J)
KEY(GOTO, "Navigate..", K_CTRL_G)
// KEY(GOTOGLOBAL, "Navigate..", K_CTRL_J)
KEY(FINDSTRING, "Find string", K_F2)
KEY(FINDSTRINGBACK, "Find string backwards", K_SHIFT_F2)
KEY(TRANSLATESTRING, "Mark selection with t_", K_ALT_F2)
@ -99,7 +99,7 @@ KEY(CLEARMARKERSFILE, "Remove change markers in file", K_ALT_R)
KEY(CLEARMARKERSALL, "Remove all change markers", K_SHIFT|K_ALT_R)
KEY(TOGGLEINDEX, "File index", K_CTRL_F12)
KEY(SEARCHINDEX, "File index search", K_F12)
KEY2(SEARCHCODE, "Search symbol", K_CTRL_U, K_CTRL_Y|K_SHIFT)
//KEY2(SEARCHCODE, "Search symbol", K_CTRL_U, K_CTRL_Y|K_SHIFT)
KEY(COMPLETE, "Complete identifier with list", K_CTRL_COMMA)
KEY(COMPLETE2, "Complete identifier", K_CTRL_M)

View file

@ -551,9 +551,9 @@ void Ide::BrowseMenu(Bar& menu) {
if(!IsEditorMode()) {
menu.AddMenu(AK_NAVIGATOR, IdeImg::Navigator(), THISBACK(ToggleNavigator))
.Check(editor.IsNavigator());
menu.Add(AK_SEARCHCODE, THISBACK(SearchCode));
menu.Add(!designer, AK_GOTO, THISBACK(Goto));
menu.Add(AK_GOTOGLOBAL, THISBACK(GotoGlobal));
menu.Add(AK_GOTO, THISBACK(SearchCode));
// menu.Add(!designer, AK_GOTO, THISBACK(Goto));
// menu.Add(AK_GOTOGLOBAL, THISBACK(GotoGlobal));
menu.Add(!designer, AK_JUMPS, THISBACK(ContextGoto));
menu.Add(!designer, AK_SWAPS, THISBACK(SwapS));
menu.Add(!designer, AK_ASSIST, callback(&editor, &AssistEditor::Assist));

View file

@ -43,13 +43,16 @@ void Ide::ResolveUvsConflict() {
void Ide::GotoPos(String path, int line)
{
LLOG("GotoPos " << path << ':' << line);
AddHistory();
editastext.FindAdd(path);
EditFile(path);
if(path.GetCount()) {
AddHistory();
editastext.FindAdd(path);
EditFile(path);
}
editor.SetCursor(editor.GetPos(line - 1));
editor.TopCursor(4);
editor.SetFocus();
AddHistory();
if(path.GetCount())
AddHistory();
}
void Ide::GotoCpp(const CppItem& pos)