diff --git a/uppsrc/CtrlCore/CtrlMouse.cpp b/uppsrc/CtrlCore/CtrlMouse.cpp index d5014c68b..c42edd54a 100644 --- a/uppsrc/CtrlCore/CtrlMouse.cpp +++ b/uppsrc/CtrlCore/CtrlMouse.cpp @@ -246,6 +246,7 @@ void Ctrl::IgnoreMouseUp() void Ctrl::UnIgnoreMouse() { GuiLock __; + LLOG("Ctrl::EndIgnore"); KillRepeat(); ignoreclick = false; ignoremouseup = false; @@ -342,8 +343,10 @@ Image Ctrl::MEvent0(int e, Point p, int zd) void Ctrl::LRepeat() { GuiLock __; - if(repeatTopCtrl && repeatTopCtrl->HasFocusDeep() && GetMouseLeft()) // 4.7.2004 cxl, IsForeground... - repeatTopCtrl->DispatchMouseEvent(LEFTREPEAT, repeatMousePos, 0); + if(repeatTopCtrl && GetMouseLeft()) { + if(repeatTopCtrl->HasFocusDeep()) + repeatTopCtrl->DispatchMouseEvent(LEFTREPEAT, repeatMousePos, 0); + } else KillRepeat(); LLOG("LRepeat " << UPP::Name(mouseCtrl)); @@ -372,8 +375,10 @@ void Ctrl::LHold() { void Ctrl::RRepeat() { GuiLock __; - if(repeatTopCtrl && repeatTopCtrl->IsForeground() && GetMouseRight()) - repeatTopCtrl->DispatchMouseEvent(RIGHTREPEAT, repeatMousePos, 0); + if(repeatTopCtrl && GetMouseRight()) { + if(repeatTopCtrl->HasFocusDeep()) + repeatTopCtrl->DispatchMouseEvent(RIGHTREPEAT, repeatMousePos, 0); + } else KillRepeat(); } @@ -390,8 +395,10 @@ void Ctrl::RHold() { void Ctrl::MRepeat() { GuiLock __; - if(repeatTopCtrl && repeatTopCtrl->IsForeground() && GetMouseMiddle()) - repeatTopCtrl->DispatchMouseEvent(MIDDLEREPEAT, repeatMousePos, 0); + if(repeatTopCtrl && GetMouseMiddle()) { + if(repeatTopCtrl->HasFocusDeep()) + repeatTopCtrl->DispatchMouseEvent(MIDDLEREPEAT, repeatMousePos, 0); + } else KillRepeat(); } @@ -505,16 +512,16 @@ bool sDblTime(int time) Image Ctrl::DispatchMouse(int e, Point p, int zd) { GuiLock __; - if(e == MOUSEMOVE) { - if(sDistMin(leftmousepos, p) > GUI_DragDistance() && repeatTopCtrl == this && GetMouseLeft()) { + if(e == MOUSEMOVE && repeatTopCtrl == this) { + if(sDistMin(leftmousepos, p) > GUI_DragDistance() && GetMouseLeft()) { DispatchMouseEvent(LEFTDRAG, leftmousepos, 0); leftmousepos = Null; } - if(sDistMin(rightmousepos, p) > GUI_DragDistance() && repeatTopCtrl == this && GetMouseRight()) { + if(sDistMin(rightmousepos, p) > GUI_DragDistance() && GetMouseRight()) { DispatchMouseEvent(RIGHTDRAG, rightmousepos, 0); rightmousepos = Null; } - if(sDistMin(middlemousepos, p) > GUI_DragDistance() && repeatTopCtrl == this && GetMouseMiddle()) { + if(sDistMin(middlemousepos, p) > GUI_DragDistance() && GetMouseMiddle()) { DispatchMouseEvent(MIDDLEDRAG, middlemousepos, 0); middlemousepos = Null; } @@ -573,7 +580,7 @@ Image Ctrl::DispatchMouse(int e, Point p, int zd) { rightmousepos = Null; if(e == MIDDLEUP) rightmousepos = Null; - if(e == LEFTUP || e == RIGHTUP || e == MIDDLEUP) + if(findarg(e, LEFTUP, RIGHTUP, MIDDLEUP) >= 0) KillRepeat(); Image result = DispatchMouseEvent(e, p, zd); if(!GetMouseRight() && !GetMouseMiddle() && !GetMouseLeft()) diff --git a/uppsrc/CtrlCore/GtkEvent.cpp b/uppsrc/CtrlCore/GtkEvent.cpp index ca3c43542..f0a3a4ea1 100644 --- a/uppsrc/CtrlCore/GtkEvent.cpp +++ b/uppsrc/CtrlCore/GtkEvent.cpp @@ -361,6 +361,7 @@ void Ctrl::Proc() SetWndFocus(); ClickActivateWnd(); if(ignoremouseup) { + DLOG("Ignore mouse up KillRepeat"); KillRepeat(); ignoreclick = false; ignoremouseup = false; diff --git a/uppsrc/CtrlLib/CtrlLib.h b/uppsrc/CtrlLib/CtrlLib.h index 8741fcacc..2cbafb921 100644 --- a/uppsrc/CtrlLib/CtrlLib.h +++ b/uppsrc/CtrlLib/CtrlLib.h @@ -26,6 +26,7 @@ INITIALIZE(CtrlLib); class Bar; #include +#include #include #include #include diff --git a/uppsrc/CtrlLib/CtrlLib.upp b/uppsrc/CtrlLib/CtrlLib.upp index a0391fcaa..dc01a2a9b 100644 --- a/uppsrc/CtrlLib/CtrlLib.upp +++ b/uppsrc/CtrlLib/CtrlLib.upp @@ -13,6 +13,8 @@ file CtrlLib readonly separator, LabelBase.h, LabelBase.cpp, + DisplayPopup.h, + DisplayPopup.cpp, PushCtrl.h, Button.cpp, Switch.cpp, diff --git a/uppsrc/CtrlLib/DisplayPopup.cpp b/uppsrc/CtrlLib/DisplayPopup.cpp new file mode 100644 index 000000000..17a530257 --- /dev/null +++ b/uppsrc/CtrlLib/DisplayPopup.cpp @@ -0,0 +1,210 @@ +#include "CtrlLib.h" + +namespace Upp { + +Point DisplayPopup::Op(Point p) +{ + return p + GetScreenView().TopLeft() - ctrl->GetScreenView().TopLeft(); +} + +void DisplayPopup::LeftDown(Point p, dword flags) +{ + ctrl->LeftDown(Op(p), flags); +} + +void DisplayPopup::LeftDrag(Point p, dword flags) +{ + Cancel(); + ctrl->LeftDrag(Op(p), flags); +} + +void DisplayPopup::LeftDouble(Point p, dword flags) +{ + ctrl->LeftDouble(Op(p), flags); +} + +void DisplayPopup::RightDown(Point p, dword flags) +{ + ctrl->RightDown(Op(p), flags); +} + +void DisplayPopup::LeftUp(Point p, dword flags) +{ + ctrl->LeftUp(Op(p), flags); +} + +void DisplayPopup::MouseWheel(Point p, int zdelta, dword flags) +{ + ctrl->MouseWheel(Op(p), zdelta, flags); +} + +void DisplayPopup::MouseLeave() +{ + Cancel(); +} + +void DisplayPopup::MouseMove(Point p, dword flags) +{ + p += GetScreenView().TopLeft(); + if(!slim.Contains(p)) + MouseLeave(); +} + +void DisplayPopup::Paint(Draw& w) +{ + Rect r = GetSize(); + w.DrawRect(r, SColorPaper); + if(display) { + display->PaintBackground(w, r, value, ink, paper, style); + r.left += margin; + display->Paint(w, r, value, ink, paper, style); + } +} + +DisplayPopup::DisplayPopup() +{ + SetFrame(BlackFrame()); + display = NULL; + paper = ink = Null; + style = 0; + item = slim = Null; + margin = 0; + ONCELOCK { + InstallStateHook(StateHook); + InstallMouseHook(MouseHook); + } + LinkBefore(all()); +} + +DisplayPopup::~DisplayPopup() +{ + Unlink(); +} + +void DisplayPopup::Sync() +{ + if(!IsMainThread()) { + PostCallback(PTEBACK(Sync)); + return; + } + if(display && ctrl && !ctrl->IsDragAndDropTarget() && !IsDragAndDropTarget()) { + Ctrl *top = ctrl->GetTopCtrl(); + if(top && top->HasFocusDeep()) { + Size sz = display->GetStdSize(value); + if(sz.cx + 2 * margin > item.GetWidth() || sz.cy > item.GetHeight()) { + Rect vw = ctrl->GetScreenView(); + slim = (item + vw.TopLeft()) & vw; + if(slim.Contains(GetMousePos())) { + Rect r = item; + r.right = max(r.right, r.left + sz.cx + 2 * margin); + r.bottom = max(r.bottom, r.top + sz.cy); + r.Inflate(1, 1); + Rect v = ctrl->GetScreenView(); + r.Offset(v.TopLeft()); + + Rect wa = GetWorkArea(r.BottomLeft()); + Size sz = r.GetSize(); + if(r.left < wa.left) { + r.left = wa.left; + r.right = min(wa.right, r.left + sz.cx); + } + else + if(r.right > wa.right) { + r.left = max(wa.left, wa.right - sz.cx); + r.right = wa.right; + } + if(r.top < wa.top) { + r.top = wa.top; + r.bottom = min(wa.bottom, wa.top + sz.cy); + } + else + if(r.bottom > wa.bottom) { + if(wa.bottom - r.top < r.top - wa.top) { // there is more space upside + r.bottom = item.bottom + v.top; + r.top = max(wa.top, r.bottom - sz.cy); + } + else + r.bottom = wa.bottom; + } + SetRect(r); + if(!IsOpen()) + Ctrl::PopUp(ctrl, true, false, false); + Refresh(); + return; + } + } + } + } + if(IsOpen()) + Close(); +} + +Link *DisplayPopup::all() +{ + static Link all; + return &all; +} + +void DisplayPopup::SyncAll() +{ + int n = 0; + for(DisplayPopup *p = all()->Link::GetNext(); p != all(); p = p->Link::GetNext()) + if(p->ctrl && p->ctrl->IsOpen()) { + p->Sync(); + n++; + } +} + +bool DisplayPopup::StateHook(Ctrl *, int reason) +{ + if(reason == FOCUS) + SyncAll(); + return false; +} + + +bool DisplayPopup::MouseHook(Ctrl *, bool, int, Point, int, dword) +{ + SyncAll(); + return false; +} + +void DisplayPopup::Cancel() +{ + display = NULL; + Sync(); +} + +bool DisplayPopup::IsOpen() +{ + return Ctrl::IsOpen(); +} + +bool DisplayPopup::HasMouse() +{ + return Ctrl::HasMouse() || ctrl && ctrl->HasMouse(); +} + +void DisplayPopup::Set(Ctrl *_ctrl, const Rect& _item, + const Value& _value, const Display *_display, + Color _ink, Color _paper, dword _style, int _margin) +{ + if(item != _item || ctrl != _ctrl || value != _value || display != _display || ink != _ink || + paper != _paper || style != _style) { + item = _item; + ctrl = _ctrl; + value = _value; + display = _display; + ink = _ink; + paper = _paper; + style = _style; + margin = _margin; + if(ctrl) + Tip(ctrl->GetTip()); + Sync(); + } + else + Refresh(); +} + +} diff --git a/uppsrc/CtrlLib/DisplayPopup.h b/uppsrc/CtrlLib/DisplayPopup.h new file mode 100644 index 000000000..f3a775459 --- /dev/null +++ b/uppsrc/CtrlLib/DisplayPopup.h @@ -0,0 +1,43 @@ + +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); + +private: + Ptr ctrl; + Rect item; + Rect slim; + + Value value; + Color paper, ink; + dword style; + const Display *display; + int margin; + + Point Op(Point p); + void Sync(); + + static Link *all(); + static bool StateHook(Ctrl *, int reason); + static bool MouseHook(Ctrl *, bool, int, Point, int, dword); + static void SyncAll(); + + typedef DisplayPopup CLASSNAME; + +public: + 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(); + + DisplayPopup(); + ~DisplayPopup(); +}; diff --git a/uppsrc/CtrlLib/LabelBase.cpp b/uppsrc/CtrlLib/LabelBase.cpp index 8b27cdb64..8d13796e9 100644 --- a/uppsrc/CtrlLib/LabelBase.cpp +++ b/uppsrc/CtrlLib/LabelBase.cpp @@ -451,209 +451,4 @@ Point GetDragScroll(Ctrl *ctrl, Point p, int max) return GetDragScroll(ctrl, p, Size(max, max)); } -Point DisplayPopup::Op(Point p) -{ - return p + GetScreenView().TopLeft() - ctrl->GetScreenView().TopLeft(); -} - -void DisplayPopup::LeftDown(Point p, dword flags) -{ - ctrl->LeftDown(Op(p), flags); -} - -void DisplayPopup::LeftDrag(Point p, dword flags) -{ - Cancel(); - ctrl->LeftDrag(Op(p), flags); -} - -void DisplayPopup::LeftDouble(Point p, dword flags) -{ - ctrl->LeftDouble(Op(p), flags); -} - -void DisplayPopup::RightDown(Point p, dword flags) -{ - ctrl->RightDown(Op(p), flags); -} - -void DisplayPopup::LeftUp(Point p, dword flags) -{ - ctrl->LeftUp(Op(p), flags); -} - -void DisplayPopup::MouseWheel(Point p, int zdelta, dword flags) -{ - ctrl->MouseWheel(Op(p), zdelta, flags); -} - -void DisplayPopup::MouseLeave() -{ - Cancel(); -} - -void DisplayPopup::MouseMove(Point p, dword flags) -{ - p += GetScreenView().TopLeft(); - if(!slim.Contains(p)) - MouseLeave(); -} - -void DisplayPopup::Paint(Draw& w) -{ - Rect r = GetSize(); - w.DrawRect(r, SColorPaper); - if(display) { - display->PaintBackground(w, r, value, ink, paper, style); - r.left += margin; - display->Paint(w, r, value, ink, paper, style); - } -} - -DisplayPopup::DisplayPopup() -{ - SetFrame(BlackFrame()); - display = NULL; - paper = ink = Null; - style = 0; - item = slim = Null; - margin = 0; - ONCELOCK { - InstallStateHook(StateHook); - InstallMouseHook(MouseHook); - } - LinkBefore(all()); -} - -DisplayPopup::~DisplayPopup() -{ - Unlink(); -} - -void DisplayPopup::Sync() -{ - if(!IsMainThread()) { - PostCallback(PTEBACK(Sync)); - return; - } - if(display && ctrl && !ctrl->IsDragAndDropTarget() && !IsDragAndDropTarget()) { - Ctrl *top = ctrl->GetTopCtrl(); - if(top && top->HasFocusDeep()) { - Size sz = display->GetStdSize(value); - if(sz.cx + 2 * margin > item.GetWidth() || sz.cy > item.GetHeight()) { - Rect vw = ctrl->GetScreenView(); - slim = (item + vw.TopLeft()) & vw; - if(slim.Contains(GetMousePos())) { - Rect r = item; - r.right = max(r.right, r.left + sz.cx + 2 * margin); - r.bottom = max(r.bottom, r.top + sz.cy); - r.Inflate(1, 1); - Rect v = ctrl->GetScreenView(); - r.Offset(v.TopLeft()); - - Rect wa = GetWorkArea(r.BottomLeft()); - Size sz = r.GetSize(); - if(r.left < wa.left) { - r.left = wa.left; - r.right = min(wa.right, r.left + sz.cx); - } - else - if(r.right > wa.right) { - r.left = max(wa.left, wa.right - sz.cx); - r.right = wa.right; - } - if(r.top < wa.top) { - r.top = wa.top; - r.bottom = min(wa.bottom, wa.top + sz.cy); - } - else - if(r.bottom > wa.bottom) { - if(wa.bottom - r.top < r.top - wa.top) { // there is more space upside - r.bottom = item.bottom + v.top; - r.top = max(wa.top, r.bottom - sz.cy); - } - else - r.bottom = wa.bottom; - } - SetRect(r); - if(!IsOpen()) - Ctrl::PopUp(ctrl, true, false, false); - Refresh(); - return; - } - } - } - } - if(IsOpen()) - Close(); -} - -Link *DisplayPopup::all() -{ - static Link all; - return &all; -} - -void DisplayPopup::SyncAll() -{ - int n = 0; - for(DisplayPopup *p = all()->Link::GetNext(); p != all(); p = p->Link::GetNext()) - if(p->ctrl && p->ctrl->IsOpen()) { - p->Sync(); - n++; - } -} - -bool DisplayPopup::StateHook(Ctrl *, int reason) -{ - if(reason == FOCUS) - SyncAll(); - return false; -} - - -bool DisplayPopup::MouseHook(Ctrl *, bool, int, Point, int, dword) -{ - SyncAll(); - return false; -} - -void DisplayPopup::Cancel() -{ - display = NULL; - Sync(); -} - -bool DisplayPopup::IsOpen() -{ - return Ctrl::IsOpen(); -} - -bool DisplayPopup::HasMouse() -{ - return Ctrl::HasMouse() || ctrl && ctrl->HasMouse(); -} - -void DisplayPopup::Set(Ctrl *_ctrl, const Rect& _item, - const Value& _value, const Display *_display, - Color _ink, Color _paper, dword _style, int _margin) -{ - if(item != _item || ctrl != _ctrl || value != _value || display != _display || ink != _ink || - paper != _paper || style != _style) { - item = _item; - ctrl = _ctrl; - value = _value; - display = _display; - ink = _ink; - paper = _paper; - style = _style; - margin = _margin; - if(ctrl) - Tip(ctrl->GetTip()); - Sync(); - } - else - Refresh(); -} - } diff --git a/uppsrc/CtrlLib/LabelBase.h b/uppsrc/CtrlLib/LabelBase.h index bbd3acba8..e4d10a24e 100644 --- a/uppsrc/CtrlLib/LabelBase.h +++ b/uppsrc/CtrlLib/LabelBase.h @@ -110,46 +110,3 @@ public: virtual ~LabelBase(); }; - -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); - -private: - Ptr ctrl; - Rect item; - Rect slim; - - Value value; - Color paper, ink; - dword style; - const Display *display; - int margin; - - Point Op(Point p); - void Sync(); - - static Link *all(); - static bool StateHook(Ctrl *, int reason); - static bool MouseHook(Ctrl *, bool, int, Point, int, dword); - static void SyncAll(); - - typedef DisplayPopup CLASSNAME; - -public: - 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(); - - DisplayPopup(); - ~DisplayPopup(); -};