TreeCtrl: Inplace editor fixes

git-svn-id: svn://ultimatepp.org/upp/trunk@15361 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2020-11-06 16:54:45 +00:00
parent 6a714077b6
commit a9bbae33da
6 changed files with 71 additions and 42 deletions

View file

@ -310,13 +310,13 @@ struct LambdaConvertClass : Convert {
virtual Value Format(const Value& q) const { return format(q); }
virtual Value Scan(const Value& text) const { return scan(text); }
virtual int Filter(int chr) const { return Filter(chr); }
virtual int Filter(int chr) const { return filter(chr); }
LambdaConvertClass(F format, S scan, R filter) : format(format), scan(scan), filter(filter) {}
};
template <typename F, typename S, class R>
const LambdaConvertClass<F, S, R>& LambdaConvert(F format, S scan, R filter)
const auto& LambdaConvert(F format, S scan, R filter)
{
static LambdaConvertClass<F, S, R> x(format, scan, filter);
return x;

View file

@ -9,32 +9,32 @@ Point DisplayPopup::Op(Point p)
void DisplayPopup::LeftDown(Point p, dword flags)
{
ctrl->LeftDown(Op(p), flags);
if(ctrl) ctrl->LeftDown(Op(p), flags);
}
void DisplayPopup::LeftDrag(Point p, dword flags)
{
ctrl->LeftDrag(Op(p), flags);
if(ctrl) ctrl->LeftDrag(Op(p), flags);
}
void DisplayPopup::LeftDouble(Point p, dword flags)
{
ctrl->LeftDouble(Op(p), flags);
if(ctrl) ctrl->LeftDouble(Op(p), flags);
}
void DisplayPopup::RightDown(Point p, dword flags)
{
ctrl->RightDown(Op(p), flags);
if(ctrl) ctrl->RightDown(Op(p), flags);
}
void DisplayPopup::LeftUp(Point p, dword flags)
{
ctrl->LeftUp(Op(p), flags);
if(ctrl) ctrl->LeftUp(Op(p), flags);
}
void DisplayPopup::MouseWheel(Point p, int zdelta, dword flags)
{
ctrl->MouseWheel(Op(p), zdelta, flags);
if(ctrl) ctrl->MouseWheel(Op(p), zdelta, flags);
}
void DisplayPopup::MouseLeave()

View file

@ -136,6 +136,7 @@ Size TreeCtrl::Item::GetSize(const Display *treedisplay) const
void TreeCtrl::SetRoot(const TreeCtrl::Node& n)
{
KillEdit();
(TreeCtrl::Node &)item[0] = n;
RefreshItem(0);
}
@ -157,6 +158,7 @@ void TreeCtrl::SetRoot(const Image& img, Ctrl& ctrl, int cx, int cy)
int TreeCtrl::Insert(int parentid, int i, const TreeCtrl::Node& n)
{
KillEdit();
int id;
if(freelist >= 0) {
id = freelist;
@ -471,7 +473,6 @@ void TreeCtrl::SyncTree(bool immediate)
SyncAfterSync(restorefocus);
else
PostCallback(PTEBACK1(SyncAfterSync, restorefocus));
KillEdit();
}
void TreeCtrl::SyncCtrls(bool add, Ctrl *restorefocus)
@ -835,6 +836,7 @@ void TreeCtrl::ShiftSelect(int l1, int l2)
void TreeCtrl::LeftDrag(Point p, dword keyflags)
{
OkEdit();
if(p.y + sb.y > sb.GetTotal().cy)
return;
WhenDrag();
@ -853,7 +855,7 @@ Rect TreeCtrl::GetValueRect(const Line& l) const
return RectC(x, l.y - org.y + (msz.cy - vsz.cy) / 2, vsz.cx, vsz.cy);
}
void TreeCtrl::DoClick(Point p, dword flags, bool down)
void TreeCtrl::DoClick(Point p, dword flags, bool down, bool canedit)
{
Point org = sb;
itemclickpos = Null;
@ -870,19 +872,23 @@ void TreeCtrl::DoClick(Point p, dword flags, bool down)
Open(l.itemi, !IsOpen(l.itemi));
}
else {
auto DoEdit = [&](int qq) {
if(down)
KillEdit();
if(cursor == qq && qq >= 0 && cursor > 0 && !HasCapture() && WhenEdited && !(flags & (K_SHIFT|K_CTRL)) &&
GetValueRect(l).Contains(p) && canedit)
SetTimeCallback(750, THISBACK(StartEdit), TIMEID_STARTEDIT);
};
if(down && IsSel(l.itemi)) { // make possible DnD of multiple items
selclick = true;
if(down)
WhenLeftClick();
DoEdit(i);
return;
}
SetWantFocus();
int q = cursor;
int qq = q;
if(IsEdit()) {
OkEdit();
qq = -1;
}
int qq = cursor;
SetCursorLine(i, true, false, true);
if(multiselect) {
int id = GetCursor();
@ -904,11 +910,7 @@ void TreeCtrl::DoClick(Point p, dword flags, bool down)
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);
DoEdit(qq);
}
}
@ -916,7 +918,13 @@ void TreeCtrl::KillEdit()
{
sb.x.Enable();
sb.y.Enable();
edit_cursor = -1;
KillTimeCallback(TIMEID_STARTEDIT);
if(editor && editor->GetParent() == this) {
int b = editor->HasFocus();
editor->Remove();
if(b) SetFocus();
}
}
void TreeCtrl::StartEdit() {
@ -938,29 +946,29 @@ void TreeCtrl::StartEdit() {
editor->SetFocus();
sb.x.Disable();
sb.y.Disable();
edit_cursor = GetCursor();
SyncInfo();
WhenStartEdit(edit_cursor);
}
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);
if(IsEdit()) {
int q = edit_cursor;
if(q >= 0 && editor)
WhenEdited(q, ~*editor);
EndEdit();
}
}
void TreeCtrl::SyncInfo()
{
if(IsShutdown() || IsPainting())
if(IsShutdown() || IsPainting() || dirty)
return;
if((HasMouse() || info.HasMouse()) && popupex) {
if((HasMouse() || info.HasMouse()) && popupex && !IsEdit()) {
Point p = GetMouseViewPos();
Point org = sb;
int i = FindLine(p.y + org.y);
@ -1000,20 +1008,22 @@ void TreeCtrl::MouseMove(Point p, dword)
void TreeCtrl::LeftDown(Point p, dword flags)
{
DoClick(p, flags, true);
OkEdit();
DoClick(p, flags, true, true);
}
void TreeCtrl::LeftUp(Point p, dword keyflags)
{
if(selclick) {
DoClick(p, keyflags, false);
DoClick(p, keyflags, false, false);
selclick = false;
}
}
void TreeCtrl::LeftDouble(Point p, dword flags)
{
LeftDown(p, flags);
OkEdit();
DoClick(p, flags, true, false);
Point org = sb;
if(p.y + org.y > sb.GetTotal().cy)
return;
@ -1026,6 +1036,7 @@ void TreeCtrl::LeftDouble(Point p, dword flags)
void TreeCtrl::RightDown(Point p, dword flags)
{
OkEdit();
Point org = sb;
if(p.y + org.y < sb.GetTotal().cy) {
int i = FindLine(p.y + org.y);
@ -1352,6 +1363,8 @@ void TreeCtrl::GotFocus()
void TreeCtrl::LostFocus()
{
if(editor && !editor->HasFocus())
OkEdit();
if(dirty)
return;
RefreshLine(cursor);
@ -1360,6 +1373,12 @@ void TreeCtrl::LostFocus()
SyncInfo();
}
void TreeCtrl::ChildLostFocus()
{
if(editor && !editor->HasFocus())
OkEdit();
}
void TreeCtrl::ChildRemoved(Ctrl *)
{
if(!IsShutdown() && !chldlck)

View file

@ -14,6 +14,7 @@ public:
virtual void GotFocus();
virtual void LostFocus();
virtual void ChildGotFocus();
virtual void ChildLostFocus();
virtual void ChildRemoved(Ctrl *);
virtual void SetData(const Value& data);
virtual Value GetData() const;
@ -125,6 +126,7 @@ private:
One<EditString> edit_string;
Ctrl *editor = NULL;
int edit_cursor = -1;
struct SortOrder;
@ -157,14 +159,14 @@ private:
bool DnDInsert(int ii, int py, int q, PasteClip& d);
void RefreshSel();
void GatherSel(int id, Vector<int>& sel) const;
void DoClick(Point p, dword flags, bool down);
void DoClick(Point p, dword flags, bool down, bool canedit);
void SyncInfo();
void SyncAfterSync(Ptr<Ctrl> restorefocus);
Rect GetValueRect(const Line& l) const;
void StartEdit();
void EndEdit();
void KillEdit();
bool IsEdit() const { return editor && editor->IsVisible(); }
bool IsEdit() const { return editor && editor->GetParent() == this; }
void OkEdit();
enum {
@ -194,7 +196,8 @@ public:
Event<int, int, PasteClip&> WhenDropInsert;
Event<PasteClip&> WhenDrop;
Event<const Value&> WhenEdited;
Event<int> WhenStartEdit;
Event<int, const Value&> WhenEdited;
// deprecated - use WhenSel
Event<> WhenCursor;

View file

@ -84,15 +84,22 @@ 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
[s5;:Upp`:`:TreeCtrl`:`:WhenStartEdit: [_^Upp`:`:Event^ Event]<[@(0.0.255) int]>_[* WhenSta
rtEdit]&]
[s2;%% Called before TreeCtrl starts editing the node. The first
parameter is the cursor of edited element.&]
[s3; &]
[s4; &]
[s5;:Upp`:`:TreeCtrl`:`:WhenEdited: [_^Upp`:`:Event^ Event]<[@(0.0.255) int][%% ,][@(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.&]
with Editor modifier method. The first parameter is the cursor
of edited element.&]
[s3; &]
[s4; &]
[s5;:TreeCtrl`:`:WhenCursor: [_^Callback^ Callback]_[* WhenCursor]&]

View file

@ -23,7 +23,7 @@ class SqlRaw : public String, public ValueType<SqlRaw, SQLRAW_V> {
public:
operator Value() const { return RawValue<SqlRaw>(*this); }
SqlRaw(const Value& q)
: String(IsNull(q) ? String() :
: String(IsNull(q) ? String() :
IsString(q) ? String(q) :
String(RawValue<SqlRaw>::Extract(q))) {}
SqlRaw(const String& s) : String(s) {}