From 67f810e0f5205fd4df929445b41ae87a68bfa2ea Mon Sep 17 00:00:00 2001 From: Mirek Fidler Date: Tue, 26 Apr 2022 13:13:27 +0200 Subject: [PATCH] VirtualButtons improvements --- benchmarks/sizeof_gui/main.cpp | 6 +- uppsrc/CtrlLib/DisplayPopup.cpp | 90 ++++++++++++----- uppsrc/CtrlLib/DisplayPopup.h | 72 +++++++++----- uppsrc/CtrlLib/DropList.cpp | 2 +- uppsrc/CtrlLib/EditCtrl.h | 5 + uppsrc/CtrlLib/EditCtrl.hpp | 19 ++++ uppsrc/CtrlLib/EditField.cpp | 16 ++- uppsrc/CtrlLib/MultiButton.cpp | 158 ++++++++++++++++++++---------- uppsrc/CtrlLib/MultiButton.h | 40 +++++--- uppsrc/CtrlLib/PushCtrl.h | 7 +- uppsrc/CtrlLib/ScrollBar.cpp | 6 +- uppsrc/CtrlLib/VirtualButtons.cpp | 13 +++ 12 files changed, 307 insertions(+), 127 deletions(-) diff --git a/benchmarks/sizeof_gui/main.cpp b/benchmarks/sizeof_gui/main.cpp index 85f0d0b68..79cd36800 100644 --- a/benchmarks/sizeof_gui/main.cpp +++ b/benchmarks/sizeof_gui/main.cpp @@ -20,9 +20,13 @@ GUI_APP_MAIN RDUMP(sizeof(Label)); RDUMP(sizeof(EditField)); RDUMP(sizeof(EditString)); + RDUMP(sizeof(EditInt)); + RDUMP(sizeof(SpinButtons)); RDUMP(sizeof(EditIntSpin)); - RDUMP(sizeof(EditDoubleSpin)); + RDUMP(sizeof(DisplayPopup)); + RDUMP(sizeof(PopUpTable)); RDUMP(sizeof(DropList)); + RDUMP(sizeof(WithDropChoice)); RDUMP(sizeof(ArrayCtrl)); RDUMP(sizeof(TreeCtrl)); RDUMP(sizeof(TreeCtrl::Node)); diff --git a/uppsrc/CtrlLib/DisplayPopup.cpp b/uppsrc/CtrlLib/DisplayPopup.cpp index f1c65e7a4..d9104878f 100644 --- a/uppsrc/CtrlLib/DisplayPopup.cpp +++ b/uppsrc/CtrlLib/DisplayPopup.cpp @@ -1,55 +1,55 @@ #include "CtrlLib.h" namespace Upp { - -Point DisplayPopup::Op(Point p) + +Point DisplayPopup::PopUp::Op(Point p) { return p + GetScreenView().TopLeft() - ctrl->GetScreenView().TopLeft(); } -void DisplayPopup::LeftDown(Point p, dword flags) +void DisplayPopup::PopUp::LeftDown(Point p, dword flags) { if(ctrl) ctrl->LeftDown(Op(p), flags); } -void DisplayPopup::LeftDrag(Point p, dword flags) +void DisplayPopup::PopUp::LeftDrag(Point p, dword flags) { if(ctrl) ctrl->LeftDrag(Op(p), flags); } -void DisplayPopup::LeftDouble(Point p, dword flags) +void DisplayPopup::PopUp::LeftDouble(Point p, dword flags) { if(ctrl) ctrl->LeftDouble(Op(p), flags); } -void DisplayPopup::RightDown(Point p, dword flags) +void DisplayPopup::PopUp::RightDown(Point p, dword flags) { if(ctrl) ctrl->RightDown(Op(p), flags); } -void DisplayPopup::LeftUp(Point p, dword flags) +void DisplayPopup::PopUp::LeftUp(Point p, dword flags) { if(ctrl) ctrl->LeftUp(Op(p), flags); } -void DisplayPopup::MouseWheel(Point p, int zdelta, dword flags) +void DisplayPopup::PopUp::MouseWheel(Point p, int zdelta, dword flags) { if(ctrl) ctrl->MouseWheel(Op(p), zdelta, flags); } -void DisplayPopup::MouseLeave() +void DisplayPopup::PopUp::MouseLeave() { Cancel(); } -void DisplayPopup::MouseMove(Point p, dword flags) +void DisplayPopup::PopUp::MouseMove(Point p, dword flags) { p += GetScreenView().TopLeft(); if(!slim.Contains(p)) MouseLeave(); } -void DisplayPopup::Paint(Draw& w) +void DisplayPopup::PopUp::Paint(Draw& w) { Rect r = GetSize(); w.DrawRect(r, SColorPaper); @@ -62,13 +62,13 @@ void DisplayPopup::Paint(Draw& w) } } -Vector& DisplayPopup::all() +Vector& DisplayPopup::PopUp::all() { - static Vector all; + static Vector all; return all; } -DisplayPopup::DisplayPopup() +DisplayPopup::PopUp::PopUp() { SetFrame(BlackFrame()); display = NULL; @@ -83,14 +83,14 @@ DisplayPopup::DisplayPopup() all().Add(this); } -DisplayPopup::~DisplayPopup() +DisplayPopup::PopUp::~PopUp() { int q = FindIndex(all(), this); if(q >= 0) all().Remove(q); } -void DisplayPopup::Sync() +void DisplayPopup::PopUp::Sync() { if(!IsMainThread()) { PostCallback(PTEBACK(Sync)); @@ -144,20 +144,20 @@ void DisplayPopup::Sync() } } if(IsOpen() && !GetDragAndDropSource()) - Close(); + WhenClose(); } -void DisplayPopup::SyncAll() +void DisplayPopup::PopUp::SyncAll() { int n = 0; - for(DisplayPopup *p : all()) + for(DisplayPopup::PopUp *p : all()) if(p->ctrl && p->ctrl->IsOpen()) { p->Sync(); n++; } } -bool DisplayPopup::StateHook(Ctrl *, int reason) +bool DisplayPopup::PopUp::StateHook(Ctrl *, int reason) { if(reason == FOCUS) SyncAll(); @@ -165,13 +165,13 @@ bool DisplayPopup::StateHook(Ctrl *, int reason) } -bool DisplayPopup::MouseHook(Ctrl *, bool, int, Point, int, dword) +bool DisplayPopup::PopUp::MouseHook(Ctrl *, bool, int, Point, int, dword) { SyncAll(); return false; } -void DisplayPopup::Cancel() +void DisplayPopup::PopUp::Cancel() { if(GetDragAndDropSource()) return; @@ -179,17 +179,17 @@ void DisplayPopup::Cancel() Sync(); } -bool DisplayPopup::IsOpen() +bool DisplayPopup::PopUp::IsOpen() { return Ctrl::IsOpen(); } -bool DisplayPopup::HasMouse() +bool DisplayPopup::PopUp::HasMouse() { return Ctrl::HasMouse() || ctrl && ctrl->HasMouse(); } -void DisplayPopup::Set(Ctrl *_ctrl, const Rect& _item, +void DisplayPopup::PopUp::Set(Ctrl *_ctrl, const Rect& _item, const Value& _value, const Display *_display, Color _ink, Color _paper, dword _style, int _margin) { @@ -212,4 +212,44 @@ void DisplayPopup::Set(Ctrl *_ctrl, const Rect& _item, } } + +void DisplayPopup::Set(Ctrl *ctrl, const Rect& item, const Value& v, const Display *display, Color ink, Color paper, dword style, int margin) +{ + if(!popup) { + popup.Create(); + popup->usedisplaystdsize = usedisplaystdsize; + popup->WhenClose << [=] { PostCallback([=] { popup.Clear(); }); }; + } + popup->Set(ctrl, item, v, display, ink, paper, style, margin); +} + +void DisplayPopup::Cancel() +{ + if(popup) + popup->Cancel(); +} + +bool DisplayPopup::IsOpen() +{ + return popup && popup->IsOpen(); +} + +bool DisplayPopup::HasMouse() +{ + return popup && popup->HasMouse(); +} + +void DisplayPopup::UseDisplayStdSize() +{ + usedisplaystdsize = true; + if(popup) + popup->usedisplaystdsize = true; +} + +DisplayPopup::~DisplayPopup() +{ + if(popup) + popup->Close(); +} + } diff --git a/uppsrc/CtrlLib/DisplayPopup.h b/uppsrc/CtrlLib/DisplayPopup.h index 90e2c183f..95b4b643a 100644 --- a/uppsrc/CtrlLib/DisplayPopup.h +++ b/uppsrc/CtrlLib/DisplayPopup.h @@ -1,29 +1,52 @@ -class DisplayPopup : public Ctrl, public Link { - virtual void Paint(Draw& w); - virtual void LeftDown(Point p, dword); - virtual void LeftDrag(Point p, dword); - virtual void LeftDouble(Point p, dword); - virtual void RightDown(Point p, dword); - virtual void LeftUp(Point p, dword); - virtual void MouseWheel(Point p, int zdelta, dword keyflags); - virtual void MouseLeave(); - virtual void MouseMove(Point p, dword); - +class DisplayPopup { private: - Ptr ctrl; - Rect item; - Rect slim; - - Value value; - Color paper, ink; - dword style; - const Display *display; - int margin; + struct PopUp : public Ctrl, public Link { + virtual void Paint(Draw& w); + virtual void LeftDown(Point p, dword); + virtual void LeftDrag(Point p, dword); + virtual void LeftDouble(Point p, dword); + virtual void RightDown(Point p, dword); + virtual void LeftUp(Point p, dword); + virtual void MouseWheel(Point p, int zdelta, dword keyflags); + virtual void MouseLeave(); + virtual void MouseMove(Point p, dword); + + Ptr ctrl; + Rect item; + Rect slim; + + Value value; + Color paper, ink; + dword style; + const Display *display; + int margin; + bool usedisplaystdsize = false; + + Point Op(Point p); + void Sync(); + + static Vector& all(); + static bool StateHook(Ctrl *, int reason); + static bool MouseHook(Ctrl *, bool, int, Point, int, dword); + static void SyncAll(); + + typedef DisplayPopup::PopUp CLASSNAME; + + Callback WhenClose; + + void Set(Ctrl *ctrl, const Rect& item, const Value& v, const Display *display, + Color ink, Color paper, dword style, int margin = 0); + void Cancel(); + bool IsOpen(); + bool HasMouse(); + + PopUp(); + ~PopUp(); + }; + + One popup; bool usedisplaystdsize = false; - Point Op(Point p); - void Sync(); - static Vector& all(); static bool StateHook(Ctrl *, int reason); static bool MouseHook(Ctrl *, bool, int, Point, int, dword); @@ -37,8 +60,7 @@ public: void Cancel(); bool IsOpen(); bool HasMouse(); - void UseDisplayStdSize() { usedisplaystdsize = true; } + void UseDisplayStdSize(); - DisplayPopup(); ~DisplayPopup(); }; diff --git a/uppsrc/CtrlLib/DropList.cpp b/uppsrc/CtrlLib/DropList.cpp index 06943ad2c..371ad6000 100644 --- a/uppsrc/CtrlLib/DropList.cpp +++ b/uppsrc/CtrlLib/DropList.cpp @@ -270,7 +270,7 @@ DropList::DropList() dropfocus = false; notnull = false; alwaysdrop = false; - AddButton().Main().WhenPush = THISBACK(Drop); + SetupDropPush([=] { Drop(); }); NoInitFocus(); EnableDrop(false); list.Normal(); diff --git a/uppsrc/CtrlLib/EditCtrl.h b/uppsrc/CtrlLib/EditCtrl.h index 482b9fd27..a03bd7774 100644 --- a/uppsrc/CtrlLib/EditCtrl.h +++ b/uppsrc/CtrlLib/EditCtrl.h @@ -164,6 +164,8 @@ protected: virtual void PaintSpace(Draw& w); virtual int GetSpaceLeft() const; virtual int GetSpaceRight() const; + virtual void EditCapture(); + virtual bool HasEditCapture(); public: Event WhenBar; @@ -381,6 +383,7 @@ void WithSpin_Add(double& value, double inc, double min, bool roundfrommin) { template class WithSpin : public Base, private VirtualButtons { public: + virtual void CancelMode(); virtual void MouseWheel(Point p, int zdelta, dword keyflags); virtual bool Key(dword key, int repcnt); virtual Image MouseEvent(int event, Point p, int zdelta, dword keyflags); @@ -388,6 +391,8 @@ public: virtual int GetSpaceLeft() const; virtual int GetSpaceRight() const; virtual void PaintSpace(Draw& w); + virtual void EditCapture(); + virtual bool HasEditCapture(); virtual int ButtonCount() const; virtual Rect ButtonRect(int i) const; diff --git a/uppsrc/CtrlLib/EditCtrl.hpp b/uppsrc/CtrlLib/EditCtrl.hpp index f76f5067c..ba167c809 100644 --- a/uppsrc/CtrlLib/EditCtrl.hpp +++ b/uppsrc/CtrlLib/EditCtrl.hpp @@ -119,6 +119,13 @@ void WithSpin::MouseWheel(Point, int zdelta, dword) } } +template +void WithSpin::CancelMode() +{ + Base::CancelMode(); + ButtonsCancelMode(); +} + template int WithSpin::GetSpaceLeft() const { @@ -135,6 +142,18 @@ int WithSpin::GetSpaceRight() const return min(Base::GetSize().cx / 2, style->width) - style->over; } +template +void WithSpin::EditCapture() +{ + buttons_capture = false; +} + +template +bool WithSpin::HasEditCapture() +{ + return Base::HasCapture() && !buttons_capture; +} + template void WithSpin::ButtonPush(int i) { diff --git a/uppsrc/CtrlLib/EditField.cpp b/uppsrc/CtrlLib/EditField.cpp index 9d522a0cc..dab6f279a 100644 --- a/uppsrc/CtrlLib/EditField.cpp +++ b/uppsrc/CtrlLib/EditField.cpp @@ -197,6 +197,15 @@ int EditField::GetSpaceRight() const return 0; } +void EditField::EditCapture() +{ +} + +bool EditField::HasEditCapture() +{ + return HasCapture(); +} + int EditField::GetCursor(int posx) { posx -= GetSpaceLeft(); @@ -506,6 +515,7 @@ void EditField::LeftDown(Point p, dword flags) return; } SetCapture(); + EditCapture(); Move(c, flags & K_SHIFT); Finish(); } @@ -528,7 +538,7 @@ void EditField::LeftUp(Point p, dword flags) { int c = GetCursor(p.x + sc); int l, h; - if(GetSelection(l, h) && c >= l && c < h && !HasCapture() && selclick) + if(GetSelection(l, h) && c >= l && c < h && !HasEditCapture() && selclick) Move(c, false); Finish(); selclick = false; @@ -550,7 +560,7 @@ void EditField::LeftTriple(Point p, dword keyflags) void EditField::MouseMove(Point p, dword flags) { - if(!HasCapture()) return; + if(!HasEditCapture()) return; Move(GetCursor(p.x + sc), true); Finish(); } @@ -761,7 +771,7 @@ void EditField::LeftDrag(Point p, dword flags) int c = GetCursor(p.x + sc); Size ssz = StdSampleSize(); int sell, selh; - if(!HasCapture() && GetSelection(sell, selh) && c >= sell && c <= selh) { + if(!HasEditCapture() && GetSelection(sell, selh) && c >= sell && c <= selh) { WString sel = text.Mid(sell, selh - sell); ImageDraw iw(ssz); iw.DrawText(0, 0, sel); diff --git a/uppsrc/CtrlLib/MultiButton.cpp b/uppsrc/CtrlLib/MultiButton.cpp index 0bfe7f7dd..5aaecc475 100644 --- a/uppsrc/CtrlLib/MultiButton.cpp +++ b/uppsrc/CtrlLib/MultiButton.cpp @@ -47,9 +47,11 @@ MultiButton::SubButton::SubButton() void MultiButton::SubButton::Refresh() { - owner->Refresh(); - if(owner->Frame() && owner->GetParent()) - owner->GetParent()->RefreshLayout(); + if(owner) { + owner->Refresh(); + if(owner->Frame() && owner->GetParent()) + owner->GetParent()->RefreshLayout(); + } } MultiButton::SubButton& MultiButton::SubButton::SetImage(const Image& m) @@ -111,30 +113,89 @@ MultiButton::SubButton& MultiButton::SubButton::Show(bool b) return *this; } +void MultiButton::MultiButtons() +{ + if(DropPush) { + SubButton& b = buttons.Add(); + b.owner = this; + b.WhenPush = DropPush; + b.main = true; + DropPush.Clear(); + } +} + MultiButton::SubButton& MultiButton::AddButton() { - SubButton& b = button.Add(); + MultiButtons(); + SubButton& b = buttons.Add(); b.owner = this; return b; } MultiButton::SubButton& MultiButton::InsertButton(int i) { - SubButton& b = button.Insert(i); + MultiButtons(); + SubButton& b = buttons.Insert(i); b.owner = this; return b; } void MultiButton::RemoveButton(int i) { - button.Remove(i); + MultiButtons(); + buttons.Remove(i); +} + +void MultiButton::Reset() +{ + MultiButtons(); + buttons.Clear(); +} + +int MultiButton::GetButtonCount() const +{ + if(DropPush) + return 1; + return buttons.GetCount(); +} + +MultiButton::SubButton& MultiButton::Button(int i) const +{ + if(DropPush) { + static SubButton b; + b.main = true; + return b; + } + return const_cast(this)->buttons[i]; +} + +const MultiButton::SubButton& MultiButton::GetButton(int i) const +{ + return Button(i); +} + +MultiButton::SubButton& MultiButton::GetButton(int i) +{ + MultiButtons(); + return Button(i); +} + +MultiButton::SubButton& MultiButton::MainButton() +{ + for(int i = 0; i < GetButtonCount(); i++) { + SubButton& b = GetButton(i); + if(b.main) + return b; + } + NEVER(); + return GetButton(0); } MultiButton::SubButton& MultiButton::SubButton::Main(bool b) { - if(b) - for(int i = 0; i < owner->button.GetCount(); i++) - owner->button[i].main = false; + if(b && owner) + for(int i = 0; i < owner->GetButtonCount(); i++) + owner->GetButton(i).main = false; main = b; return *this; } @@ -212,12 +273,12 @@ int MultiButton::FindButton(int px) { if(IsReadOnly()) return Null; - if(IsTrivial() && !Frame()) - return button[0].enabled ? 0 : Null; + if(IsTrivial() && !Frame() && GetButtonCount()) + return GetButton(0).enabled ? 0 : Null; int border, lx, rx; Metrics(border, lx, rx); - for(int i = 0; i < button.GetCount(); i++) { - SubButton& b = button[i]; + for(int i = 0; i < GetButtonCount(); i++) { + SubButton& b = Button(i); int x = 0, cx = 0; if(GetPos(b, lx, rx, x, cx, px)) return b.enabled ? i : Null; @@ -225,8 +286,8 @@ int MultiButton::FindButton(int px) if(WhenPush || WhenClick) return MAIN; if(display) - for(int i = 0; i < button.GetCount(); i++) - if(button[i].main) + for(int i = 0; i < GetButtonCount(); i++) + if(Button(i).main) return i; return Null; } @@ -262,7 +323,7 @@ void MultiButton::GetPos(int ii, int& x, int& cx) Metrics(border, lx, rx); x = cx = 0; for(int i = 0; i <= ii; i++) { - SubButton& b = button[i]; + SubButton& b = Button(i); GetPos(b, lx, rx, x, cx); } } @@ -273,8 +334,8 @@ void MultiButton::GetLR(int& lx, int& rx) Metrics(border, lx, rx); int x = 0; int cx = 0; - for(int i = 0; i < button.GetCount(); i++) { - SubButton& b = button[i]; + for(int i = 0; i < GetButtonCount(); i++) { + SubButton& b = Button(i); GetPos(b, lx, rx, x, cx); } } @@ -286,13 +347,13 @@ int MultiButton::ChState(int i) if(i == MAIN && frm && style->activeedge) { int q = 0; if(p) - q = !p->IsEnabled() || !IsEnabled() || p->IsReadOnly() || i >= 0 && !button[i].enabled ? CTRL_DISABLED + q = !p->IsEnabled() || !IsEnabled() || p->IsReadOnly() ? CTRL_DISABLED : p->HasFocus() || push ? CTRL_PRESSED : p->HasMouse() || hl >= 0 ? CTRL_HOT : CTRL_NORMAL; return q; } - if(!IsShowEnabled() || IsReadOnly() || frm && p && p->IsReadOnly() || i >= 0 && !button[i].enabled) + if(!IsShowEnabled() || IsReadOnly() || frm && p && p->IsReadOnly() || i >= 0 && !Button(i).enabled) return CTRL_DISABLED; if(IsTrivial() && !frm) i = 0; @@ -317,8 +378,8 @@ void MultiButton::Lay(Rect& r, bool minsize) bool frm = Metrics(border, lx, rx); bool left = false; bool right = false; - for(int i = 0; i < button.GetCount(); i++) { - SubButton& b = button[i]; + for(int i = 0; i < GetButtonCount(); i++) { + SubButton& b = Button(i); int cx = 0; int x = 0; GetPos(b, lx, rx, x, cx); (b.left ? left : right) = true; @@ -404,8 +465,8 @@ Rect MultiButton::Paint0(Draw& w, bool getcr) } bool left = false; bool right = false; - for(int i = 0; i < button.GetCount(); i++) { - SubButton& b = button[i]; + for(int i = 0; i < GetButtonCount(); i++) { + SubButton& b = Button(i); int st = ChState(i); int x = 0, cx = 0; GetPos(b, lx, rx, x, cx); @@ -562,7 +623,7 @@ void MultiButton::SyncInfo() void MultiButton::MouseMove(Point p, dword flags) { int h = FindButton(p.x); - Ctrl::Tip(h >= 0 && h < button.GetCount() ? Nvl(button[h].tip, tip) : tip); + Ctrl::Tip(h >= 0 && h < GetButtonCount() ? Nvl(Button(h).tip, tip) : tip); if(hl != h) { hl = h; Refresh(); @@ -575,12 +636,20 @@ void MultiButton::MouseMove(Point p, dword flags) SyncInfo(); } +void MultiButton::DoPush(int i) +{ + if(i == 0 && DropPush) + DropPush(); + else + Button(i).WhenPush(); +} + void MultiButton::LeftDown(Point p, dword flags) { push = true; Refresh(); - if(IsNull(hl)) - pushrect = Null; + if(hl == NONE) + pushrect.Clear(); else { if(hl == MAIN) pushrect = GetScreenRect(); @@ -593,7 +662,7 @@ void MultiButton::LeftDown(Point p, dword flags) } Sync(); if(hl >= 0) - button[hl].WhenPush(); + DoPush(hl); else WhenPush(); } @@ -605,9 +674,9 @@ void MultiButton::LeftUp(Point p, dword flags) push = false; Refresh(); Sync(); - if(!IsNull(hl)) { + if(hl != NONE) { if(hl >= 0) - button[hl].WhenClick(); + Button(hl).WhenClick(); else WhenClick(); } @@ -617,7 +686,7 @@ void MultiButton::LeftUp(Point p, dword flags) void MultiButton::MouseLeave() { if(!info.IsOpen()) { - hl = Null; + hl = NONE; Refresh(); SyncInfo(); } @@ -625,7 +694,7 @@ void MultiButton::MouseLeave() void MultiButton::CancelMode() { - hl = Null; + hl = NONE; push = false; Refresh(); info.Cancel(); @@ -633,21 +702,7 @@ void MultiButton::CancelMode() bool MultiButton::IsTrivial() const { - return button.GetCount() == 1 && IsNull(button[0].img) && !WhenPush && !WhenClick; -} - -MultiButton::SubButton& MultiButton::MainButton() -{ - for(int i = 0; i < button.GetCount(); i++) - if(button[i].main) - return button[i]; - NEVER(); - return button[0]; -} - -void MultiButton::Reset() -{ - button.Clear(); + return GetButtonCount() == 1 && IsNull(Button(0).img) && !WhenPush && !WhenClick; } MultiButton& MultiButton::SetDisplay(const Display& d) @@ -718,11 +773,11 @@ void MultiButton::PseudoPush(int bi) { hl = bi; push = true; - button[bi].WhenPush(); + DoPush(bi); Sync(); Sleep(50); - button[bi].WhenClick(); - hl = Null; + Button(bi).WhenClick(); + hl = NONE; push = false; Sync(); } @@ -734,7 +789,7 @@ void MultiButton::PseudoPush() Sync(); Sleep(50); WhenClick(); - hl = Null; + hl = NONE; push = false; Sync(); } @@ -749,6 +804,7 @@ MultiButton::MultiButton() push = false; SetFrame(sNullFrame()); nobg = false; + hl = NONE; } void MultiButtonFrame::FrameAdd(Ctrl& parent) diff --git a/uppsrc/CtrlLib/MultiButton.h b/uppsrc/CtrlLib/MultiButton.h index d5b125c9f..f104d6d33 100644 --- a/uppsrc/CtrlLib/MultiButton.h +++ b/uppsrc/CtrlLib/MultiButton.h @@ -49,8 +49,9 @@ public: class SubButton { friend class MultiButton; + String label; String tip; - MultiButton *owner; + MultiButton *owner = nullptr; Image img; int cx; bool main; @@ -59,8 +60,6 @@ public: bool enabled; bool visible; - String label; - void Refresh(); public: @@ -85,6 +84,7 @@ public: private: enum { + NONE = -2, MAIN = -1, LB_IMAGE = 5, // image <-> text space LB_MARGIN = 10 @@ -92,23 +92,25 @@ private: virtual bool Frame(); - const Display *display; - const Convert *convert; + DisplayPopup info; + Array buttons; + Event<> DropPush; // mode for droplist with single button + Value value; Value error; - int valuecy; - bool push; - bool nobg; String tip; - Rect pushrect; - Color paper = Null; - - Array button; - int hl; + Rect16 pushrect; + const Display *display; + const Convert *convert; const Style *style; - DisplayPopup info; + int valuecy; + Color paper = Null; + + int16 hl; + bool push:1; + bool nobg:1; int FindButton(int px); void Margins(int& l, int& r); @@ -124,6 +126,9 @@ private: bool Metrics(int& border, int& lx, int &rx); void SyncInfo(); Rect Paint0(Draw& w, bool getcr); + void DoPush(int i); + void MultiButtons(); + SubButton& Button(int i) const; friend class SubButton; friend class MultiButtonFrame; @@ -145,8 +150,9 @@ public: SubButton& AddButton(); SubButton& InsertButton(int i); void RemoveButton(int i); - int GetButtonCount() const { return button.GetCount(); } - SubButton& GetButton(int i) { return button[i]; } + int GetButtonCount() const; + const MultiButton::SubButton& GetButton(int i) const; + SubButton& GetButton(int i); SubButton& MainButton(); Rect GetPushScreenRect() const { return pushrect; } @@ -168,6 +174,8 @@ public: MultiButton& NoBackground(bool b = true); MultiButton& SetStyle(const Style& s) { style = &s; Refresh(); return *this; } + + void SetupDropPush(Event<> push) { DropPush = push; } MultiButton(); }; diff --git a/uppsrc/CtrlLib/PushCtrl.h b/uppsrc/CtrlLib/PushCtrl.h index 8546b8af8..00226dc99 100644 --- a/uppsrc/CtrlLib/PushCtrl.h +++ b/uppsrc/CtrlLib/PushCtrl.h @@ -423,14 +423,15 @@ struct VirtualButtons { virtual void ButtonRepeat(int i); virtual void ButtonAction(int i); - int16 pushi = -1; - int16 mi = -1; + int8 pushi = -1; + int8 mi = -1; + bool buttons_capture = false; int FindButton(Point p) const; void EndPush(Ctrl *ctrl); - bool ButtonsCancelMode(Ctrl *ctrl); + void ButtonsCancelMode(); bool ButtonsMouseEvent(Ctrl *ctrl, int event, Point p); void PaintButtons(Draw& w, Ctrl *ctrl); diff --git a/uppsrc/CtrlLib/ScrollBar.cpp b/uppsrc/CtrlLib/ScrollBar.cpp index 00dff8ab1..f87c122c8 100644 --- a/uppsrc/CtrlLib/ScrollBar.cpp +++ b/uppsrc/CtrlLib/ScrollBar.cpp @@ -214,7 +214,7 @@ void ScrollBar::Paint(Draw& w) Size sz = style->through ? GetSize() : Slider(cc).GetSize(); light = GetMousePart(); int p = push; - if(!HasCapture()) + if(!HasCapture() || buttons_capture) p = -1; const Value *hl[] = { style->hlower, style->hupper, style->hthumb }; const Value *vl[] = { style->vupper, style->vlower, style->vthumb }; @@ -229,7 +229,7 @@ void ScrollBar::Paint(Draw& w) pr = style->through ? GetSize() : Slider(); } if(i != 2 || thumbsize >= style->thumbmin) - ChPaint(w, pr, l[i][p == i ? CTRL_PRESSED : light == i ? CTRL_HOT : CTRL_NORMAL]); + ChPaint(w, pr, l[i][p == i ? CTRL_PRESSED : light == i && !buttons_capture ? CTRL_HOT : CTRL_NORMAL]); if(i != 2) w.End(); } @@ -325,6 +325,7 @@ void ScrollBar::LeftDown(Point p, dword) { NextPage(); } SetCapture(); + buttons_capture = false; Refresh(); WhenLeftClick(); } @@ -371,6 +372,7 @@ void ScrollBar::MouseWheel(Point p, int zdelta, dword keyflags) void ScrollBar::CancelMode() { push = light = -1; + ButtonsCancelMode(); } bool ScrollBar::Set(int apagepos) { diff --git a/uppsrc/CtrlLib/VirtualButtons.cpp b/uppsrc/CtrlLib/VirtualButtons.cpp index 3a10b60b1..970478c1f 100644 --- a/uppsrc/CtrlLib/VirtualButtons.cpp +++ b/uppsrc/CtrlLib/VirtualButtons.cpp @@ -23,6 +23,8 @@ int VirtualButtons::FindButton(Point p) const int VirtualButtons::ButtonVisualState(Ctrl *ctrl, int i) { + if(ctrl->HasCapture() && !buttons_capture) + return CTRL_NORMAL; if(ButtonEnabled(i)) { if(i == pushi) return CTRL_PRESSED; @@ -55,8 +57,17 @@ void VirtualButtons::RefreshButton(Ctrl *ctrl, int i) ctrl->Refresh(ButtonRect(i)); } +void VirtualButtons::ButtonsCancelMode() +{ + pushi = -1; + mi = -1; + buttons_capture = false; +} + bool VirtualButtons::ButtonsMouseEvent(Ctrl *ctrl, int event, Point p) { + if(ctrl->HasCapture() && !buttons_capture) + return false; int i = event == Ctrl::MOUSELEAVE ? -1 : FindButton(p); if(i != mi) { RefreshButton(ctrl, mi); @@ -70,6 +81,7 @@ bool VirtualButtons::ButtonsMouseEvent(Ctrl *ctrl, int event, Point p) if(pushi >= 0) { ButtonPush(i); ctrl->SetCapture(); + buttons_capture = true; } else EndPush(ctrl); @@ -90,6 +102,7 @@ bool VirtualButtons::ButtonsMouseEvent(Ctrl *ctrl, int event, Point p) if(ii >= 0) { EndPush(ctrl); ReleaseCapture(); + buttons_capture = false; ButtonAction(ii); } break;