diff --git a/uppsrc/CtrlLib/ColumnList.h b/uppsrc/CtrlLib/ColumnList.h index 7433801a9..3eb3b8dcf 100644 --- a/uppsrc/CtrlLib/ColumnList.h +++ b/uppsrc/CtrlLib/ColumnList.h @@ -88,6 +88,8 @@ private: bool DnDInsert(int i, int py, PasteClip& d, int q); void DnD(int _drop, bool _insert); + + friend class FileList; public: enum { diff --git a/uppsrc/CtrlLib/FileList.cpp b/uppsrc/CtrlLib/FileList.cpp index 29078d1e1..87ca05947 100644 --- a/uppsrc/CtrlLib/FileList.cpp +++ b/uppsrc/CtrlLib/FileList.cpp @@ -162,10 +162,11 @@ void FileList::StartEdit() { edit.SetFocus(); int pos = int(GetFileExtPos(cf.name) - ~cf.name); edit.SetSelection(0, pos); + sb.Disable(); } void FileList::EndEdit() { - KillTimeCallback(TIMEID_STARTEDIT); + KillEdit(); int b = edit.HasFocus(); edit.Hide(); if(b) SetFocus(); @@ -180,6 +181,7 @@ void FileList::OkEdit() { void FileList::KillEdit() { + sb.Enable(); KillTimeCallback(TIMEID_STARTEDIT); } @@ -191,7 +193,7 @@ void FileList::LeftDown(Point p, dword flags) { } ColumnList::LeftDown(p, flags); KillEdit(); - if(c == GetCursor() && c >= 0 && !HasCapture() && renaming && !(flags & (K_SHIFT|K_CTRL))) + if(c == GetCursor() && c >= 0 && !HasCapture() && renaming && WhenRename && !(flags & (K_SHIFT|K_CTRL))) SetTimeCallback(750, THISBACK(StartEdit), TIMEID_STARTEDIT); } diff --git a/uppsrc/CtrlLib/TreeCtrl.cpp b/uppsrc/CtrlLib/TreeCtrl.cpp index 0cca90a86..68d287d76 100644 --- a/uppsrc/CtrlLib/TreeCtrl.cpp +++ b/uppsrc/CtrlLib/TreeCtrl.cpp @@ -471,6 +471,7 @@ void TreeCtrl::SyncTree(bool immediate) SyncAfterSync(restorefocus); else PostCallback(PTEBACK1(SyncAfterSync, restorefocus)); + KillEdit(); } void TreeCtrl::SyncCtrls(bool add, Ctrl *restorefocus) @@ -839,6 +840,18 @@ void TreeCtrl::LeftDrag(Point p, dword keyflags) WhenDrag(); } +Rect TreeCtrl::GetValueRect(const Line& l) const +{ + const Item& m = item[l.itemi]; + Size msz = m.GetSize(display); + Size isz = m.image.GetSize(); + Size vsz = m.GetValueSize(display); + Point org = sb; + return RectC(levelcx + l.level * levelcx + isz.cx - org.x + m.margin, + l.y - org.y + (msz.cy - vsz.cy) / 2, + vsz.cx, vsz.cy); +} + void TreeCtrl::DoClick(Point p, dword flags, bool down) { Point org = sb; @@ -864,6 +877,11 @@ void TreeCtrl::DoClick(Point p, dword flags, bool down) } SetWantFocus(); int q = cursor; + int qq = q; + if(IsEdit()) { + OkEdit(); + qq = -1; + } SetCursorLine(i, true, false, true); if(multiselect) { int id = GetCursor(); @@ -880,15 +898,63 @@ void TreeCtrl::DoClick(Point p, dword flags, bool down) anchor = cursor; } } - if(cursor != q) { + if(cursor != q) WhenAction(); - } if(down) WhenLeftClick(); Select(); + + KillEdit(); + if(cursor == qq && qq >= 0 && !HasCapture() && WhenEdited && !(flags & (K_SHIFT|K_CTRL)) && + GetValueRect(l).Contains(p)) + SetTimeCallback(750, [=] { StartEdit(); }, TIMEID_STARTEDIT); } } +void TreeCtrl::KillEdit() +{ + sb.x.Enable(); + sb.y.Enable(); + KillTimeCallback(TIMEID_STARTEDIT); +} + +void TreeCtrl::StartEdit() { + if(cursor < 0) return; + if(!editor) { + edit_string.Create(); + editor = ~edit_string; + } + AddChild(editor); + const Line& l = line[cursor]; + const Item& m = item[l.itemi]; + Rect r = GetValueRect(l); + r.Inflate(2); + editor->SetFrame(BlackFrame()); + r.right = GetSize().cx; + editor->SetRect(r); + *editor <<= m.value; + editor->Show(); + editor->SetFocus(); + sb.x.Disable(); + sb.y.Disable(); +} + +void TreeCtrl::EndEdit() { + KillEdit(); + if(editor) { + int b = editor->HasFocus(); + editor->Hide(); + if(b) SetFocus(); + } +} + +void TreeCtrl::OkEdit() { + EndEdit(); + int c = GetCursor(); + if(c >= 0 && editor) + WhenEdited(~*editor); +} + void TreeCtrl::SyncInfo() { if(IsShutdown() || IsPainting()) @@ -1180,7 +1246,14 @@ bool TreeCtrl::Key(dword key, int) key &= ~K_SHIFT; switch(key) { case K_ENTER: - Select(); + if(IsEdit()) + OkEdit(); + else + Select(); + break; + case K_ESCAPE: + if(IsEdit()) + EndEdit(); break; case K_TAB: return Tab(1); diff --git a/uppsrc/CtrlLib/TreeCtrl.h b/uppsrc/CtrlLib/TreeCtrl.h index f94cd9ca1..b4e59e04c 100644 --- a/uppsrc/CtrlLib/TreeCtrl.h +++ b/uppsrc/CtrlLib/TreeCtrl.h @@ -122,6 +122,9 @@ private: struct LineLess { bool operator()(int y, const Line& l) const { return y < l.y; } }; + + One edit_string; + Ctrl *editor = NULL; struct SortOrder; @@ -157,6 +160,17 @@ private: void DoClick(Point p, dword flags, bool down); void SyncInfo(); void SyncAfterSync(Ptr restorefocus); + Rect GetValueRect(const Line& l) const; + void StartEdit(); + void EndEdit(); + void KillEdit(); + bool IsEdit() const { return editor && editor->IsVisible(); } + void OkEdit(); + + enum { + TIMEID_STARTEDIT = Ctrl::TIMEID_COUNT, + TIMEID_COUNT + }; using Ctrl::Close; @@ -179,6 +193,8 @@ public: Event WhenDropItem; Event WhenDropInsert; Event WhenDrop; + + Event WhenEdited; // deprecated - use WhenSel Event<> WhenCursor; @@ -322,6 +338,7 @@ public: TreeCtrl& HighlightCtrl(bool a = true) { highlight_ctrl = a; Refresh(); return *this; } TreeCtrl& RenderMultiRoot(bool a = true) { multiroot = a; Refresh(); return *this; } TreeCtrl& EmptyNodeIcon(const Image& a) { imgEmpty = a; Refresh(); return *this; } + TreeCtrl& Editor(Ctrl& e) { editor = &e; return *this; } TreeCtrl& SetScrollBarStyle(const ScrollBar::Style& s) { sb.SetStyle(s); return *this; } diff --git a/uppsrc/CtrlLib/src.tpp/TreeCtrl_en-us.tpp b/uppsrc/CtrlLib/src.tpp/TreeCtrl_en-us.tpp index 5aeda0784..162ad13a2 100644 --- a/uppsrc/CtrlLib/src.tpp/TreeCtrl_en-us.tpp +++ b/uppsrc/CtrlLib/src.tpp/TreeCtrl_en-us.tpp @@ -1,5 +1,4 @@ topic "TreeCtrl"; -[2 $$0,0#00000000000000000000000000000000:Default] [i448;a25;kKO9;2 $$1,0#37138531426314131252341829483380:class] [l288;2 $$2,0#27521748481378242620020725143825:desc] [0 $$3,0#96390100711032703541132217272105:end] @@ -9,6 +8,7 @@ topic "TreeCtrl"; [l288;i1121;b17;O9;~~~.1408;2 $$7,0#10431211400427159095818037425705:param] [i448;b42;O9;2 $$8,8#61672508125594000341940100500538:tparam] [b42;2 $$9,9#13035079074754324216151401829390:normal] +[2 $$0,0#00000000000000000000000000000000:Default] [{_} [ {{10000@3 [s0; [*@(229)4 TreeCtrl]]}}&] [s3;%% &] @@ -84,6 +84,17 @@ do not apply `- drop into empty area. See [^PasteClip^ PasteClip] for more details.&] [s3; &] [s4; &] +[s5;:Upp`:`:TreeCtrl`:`:WhenEdited: [_^Upp`:`:Event^ Event]<[@(0.0.255) const]_Value[@(0.0.255) `& +]>_[* WhenEdited]&] +[s2;%% When defined, TreeCtrl will start editing the node value when +clicked on already select one (after a while) in a way similar +to e.g. FileSel file renaming. When the value is accepted, WhenEdit +is called with a new value. Value is not changed in TreeCtrl, +if that is desired, it is a responsibility of code that is assigned +to the WhenEdited. Default editor is EditString and can be changed +with Editor modifier method.&] +[s3; &] +[s4; &] [s5;:TreeCtrl`:`:WhenCursor: [_^Callback^ Callback]_[* WhenCursor]&] [s2;%% Cursor has changed (including KillCursor). Deprecated.&] [s3; &] @@ -602,6 +613,11 @@ level and has not elements, [%-*@3 a] is drawn on the left side to indicate it is empty.&] [s3;%% &] [s4; &] +[s5;:Upp`:`:TreeCtrl`:`:Editor`(Upp`:`:Ctrl`&`): [_^Upp`:`:TreeCtrl^ TreeCtrl][@(0.0.255) `& +]_[* Editor]([_^Upp`:`:Ctrl^ Ctrl][@(0.0.255) `&]_[*@3 e])&] +[s2;%% Assigns alternative editor for WhenEdited functionality.&] +[s3;%% &] +[s4; &] [s5;:TreeCtrl`:`:SetScrollBarStyle`(const ScrollBar`:`:Style`&`): [_^TreeCtrl^ TreeCtrl ][@(0.0.255) `&]_[* SetScrollBarStyle]([@(0.0.255) const]_[_^ScrollBar`:`:Style^ ScrollBa r`::Style][@(0.0.255) `&]_[*@3 s])&]