diff --git a/uppsrc/Core/Other.h b/uppsrc/Core/Other.h index bd4f9b1f3..7b40bcee0 100644 --- a/uppsrc/Core/Other.h +++ b/uppsrc/Core/Other.h @@ -106,9 +106,6 @@ public: class PackedData { void *ptr = nullptr; - template - T Get(int ii, T def) const; - public: void SetRawPtr(void *p) { ptr = p; } void *GetRawPtr() const { return ptr; } @@ -117,6 +114,12 @@ public: template bool GetData(int ii, F out) const; + + template + void Set(int ii, T val); + + template + T Get(int ii, T def) const; void SetNull(int ii) { SetData(ii, NULL, 0); } @@ -147,57 +150,6 @@ public: ~PackedData(); }; -/* -template -struct Link { - T *link_prev[N]; - T *link_next[N]; - -protected: - void LPN(int i) { link_prev[i]->link_next[i] = link_next[i]->link_prev[i] = (T *)this; } - -public: - NOUBSAN T *GetPtr() { return (T *) this; } - const T *GetPtr() const { return (const T *) this; } - T *GetNext(int i = 0) { return link_next[i]; } - T *GetPrev(int i = 0) { return link_prev[i]; } - const T *GetNext(int i = 0) const { return link_next[i]; } - const T *GetPrev(int i = 0) const { return link_prev[i]; } - - NOUBSAN void LinkSelf(int i = 0) { link_next[i] = link_prev[i] = (T *)this; } - void LinkSelfAll() { for(int i = 0; i < N; i++) LinkSelf(i); } - void Unlink(int i = 0) { link_next[i]->link_prev[i] = link_prev[i]; link_prev[i]->link_next[i] = link_next[i]; - LinkSelf(i); } - void UnlinkAll() { for(int i = 0; i < N; i++) Unlink(i); } - NOUBSAN void LinkBefore(Link *n, int i = 0) { link_next[i] = (T *)n; link_prev[i] = link_next[i]->link_prev[i]; LPN(i); } - NOUBSAN void LinkAfter(Link *p, int i = 0) { link_prev[i] = (T *)p; link_next[i] = link_prev[i]->link_next[i]; LPN(i); } - - T *InsertNext(int i = 0) { T *x = new T; x->LinkAfter(this, i); return x; } - T *InsertPrev(int i = 0) { T *x = new T; x->LinkBefore(this, i); return x; } - - void DeleteList(int i = 0) { while(link_next[i] != GetPtr()) delete link_next[i]; } - - bool InList(int i = 0) const { return link_next[i] != GetPtr(); } - bool IsEmpty(int i = 0) const { return !InList(i); } - - Link() { LinkSelfAll(); } - ~Link() { UnlinkAll(); } - -private: - Link(const Link&); - void operator=(const Link&); - -public: -#ifdef _DEBUG - void Dump() { - for(T *t = GetNext(); t != this; t = t->GetNext()) - LOG(t); - LOG("-------------------------------------"); - } -#endif -}; -*/ - template struct Link { Link *link_prev[N]; diff --git a/uppsrc/Core/Other.hpp b/uppsrc/Core/Other.hpp index ce64b6377..88bb5635a 100644 --- a/uppsrc/Core/Other.hpp +++ b/uppsrc/Core/Other.hpp @@ -24,9 +24,14 @@ bool PackedData::GetData(int ii, F out) const } template -T PackedData::Get(int ii, T def) const +void PackedData::Set(int ii, T val) +{ + SetData(ii, &val, sizeof(T)); +} + +template +T PackedData::Get(int ii, T q) const { - T q = def; GetData(ii, [&](const char *ptr, int len) { if(len) { ASSERT(len == sizeof(T)); diff --git a/uppsrc/CtrlCore/Ctrl.cpp b/uppsrc/CtrlCore/Ctrl.cpp index 2cbe37595..1ac62d48b 100644 --- a/uppsrc/CtrlCore/Ctrl.cpp +++ b/uppsrc/CtrlCore/Ctrl.cpp @@ -541,9 +541,7 @@ Ctrl::Ctrl() { backpaint = IsCompositedGui() ? FULLBACKPAINT : TRANSPARENTBACKPAINT; inframe = false; ignoremouse = transparent = false; - pos.x = PosLeft(0, 0); - pos.y = PosTop(0, 0); - rect = Rect(0, 0, 0, 0); + packed_rect = Rect16(0, 0, 0, 0); inloop = popup = isopen = false; modify = false; unicode = false; diff --git a/uppsrc/CtrlCore/CtrlAttr.cpp b/uppsrc/CtrlCore/CtrlAttr.cpp index 268974030..41309cde0 100644 --- a/uppsrc/CtrlCore/CtrlAttr.cpp +++ b/uppsrc/CtrlCore/CtrlAttr.cpp @@ -162,6 +162,29 @@ int64 Ctrl::GetInt64Attr(int ii, int64 def) const return attrs.GetInt64(ii, def); } +void Ctrl::SetLogPosAttr(int ii, LogPos pos) +{ + Attrs().Set(ii, pos); +} + +Ctrl::LogPos Ctrl::GetLogPosAttr(int ii) const +{ + if(layout_id_literal) + return LogPos(); + return attrs.Get(ii, LogPos()); +} + +void Ctrl::SetRectAttr(int ii, const Rect& r) +{ + Attrs().Set(ii, r); +} + +Rect Ctrl::GetRectAttr(int ii) const +{ + if(layout_id_literal) + return Null; + return attrs.Get(ii, Rect(Null)); +} void Ctrl::SetVoidPtrAttr(int ii, const void *ptr) { diff --git a/uppsrc/CtrlCore/CtrlCore.h b/uppsrc/CtrlCore/CtrlCore.h index c15e83c67..547e9c09a 100644 --- a/uppsrc/CtrlCore/CtrlCore.h +++ b/uppsrc/CtrlCore/CtrlCore.h @@ -428,24 +428,24 @@ public: STDSIZE = -16382, }; - class Logc { - dword data; + struct Logc { + int align = LEFT; + int a = 0; + int b = 0; - static int LSGN(dword d) { return int16((d & 0x7fff) | ((d & 0x4000) << 1)); } + bool operator==(Logc q) const { return a == q.a && b == q.b && align == q.align; } + bool operator!=(Logc q) const { return !operator==(q); } + int GetAlign() const { return align; } + int GetA() const { return a; } + int GetB() const { return b; } + void SetAlign(int align_) { align = align_; } + void SetA(int a_) { a = a_; } + void SetB(int b_) { b = b_; } + bool IsEmpty() const { return align == SIZE ? b <= a : b <= 0; } + bool CanPack() const { return a >= -16000 && a <= 16000 && b >= -16000 && b <= 16000; } - public: - bool operator==(Logc q) const { return data == q.data; } - bool operator!=(Logc q) const { return data != q.data; } - int GetAlign() const { return (data >> 30) & 3; } - int GetA() const { return LSGN(data >> 15); } - int GetB() const { return LSGN(data); } - void SetAlign(int align) { data = (data & ~(3 << 30)) | (align << 30); } - void SetA(int a) { data = (data & ~(0x7fff << 15)) | ((a & 0x7fff) << 15); } - void SetB(int b) { data = (data & ~0x7fff) | (b & 0x7fff); } - bool IsEmpty() const; - - Logc(int al, int a, int b) { data = (al << 30) | ((a & 0x7fff) << 15) | (b & 0x7fff); } - Logc() { data = 0xffffffff; } + Logc(int al, int a_, int b_) { align = al; a = a_; b = b_; } + Logc() {} }; struct LogPos : Moveable { @@ -453,6 +453,8 @@ public: bool operator==(LogPos b) const { return x == b.x && y == b.y; } bool operator!=(LogPos b) const { return !(*this == b); } + + bool CanPack() const { return x.CanPack() && y.CanPack(); } LogPos(Logc x, Logc y) : x(x), y(y) {} LogPos() {} @@ -466,6 +468,24 @@ public: static Logc PosCenter(int size, int offset) { return Logc(CENTER, offset, size); } static Logc PosCenter(int size) { return Logc(CENTER, 0, size); } + struct PackedLogc { + unsigned align:2; + int a:15; + int b:15; + + operator Logc() const { return Logc(align, a, b); } + PackedLogc(const Logc& c) { align = c.align; a = c.a; b = c.b; } + PackedLogc() { align = LEFT; a = 0; b = 0; } + }; + + struct PackedLogPos : Moveable { + PackedLogc x, y; + + operator LogPos() const { return LogPos(x, y); } + PackedLogPos(LogPos pos) { x = pos.x; y = pos.y; } + PackedLogPos() {} + }; + typedef bool (*MouseHook)(Ctrl *ctrl, bool inframe, int event, Point p, int zdelta, dword keyflags); typedef bool (*KeyHook)(Ctrl *ctrl, dword key, int count); @@ -525,8 +545,12 @@ private: Frame frame; - LogPos pos;//8 - Rect16 rect; //8 + + PackedLogPos packed_pos;//8 + Rect16 packed_rect; //8 + + void LogPosSet(LogPos p); + void RectSet(const Rect& r); union { Ctrl *uparent; @@ -828,6 +852,8 @@ protected: ATTR_HELPLINE, ATTR_DESCRIPTION, ATTR_HELPTOPIC, + ATTR_RECT, + ATTR_LOGPOS, ATTR_LAST }; @@ -847,6 +873,12 @@ protected: void SetInt64Attr(int ii, int64 val); int64 GetInt64Attr(int ii, int64 def = Null) const; + void SetLogPosAttr(int ii, LogPos pos); + LogPos GetLogPosAttr(int ii) const; + + void SetRectAttr(int ii, const Rect& r); + Rect GetRectAttr(int ii) const; + void SetVoidPtrAttr(int ii, const void *ptr); void *GetVoidPtrAttr(int ii) const; @@ -1134,7 +1166,7 @@ public: bool InFrame() const { return inframe; } bool InView() const { return !inframe; } - LogPos GetPos() const { return pos; } + LogPos GetPos() const; void RefreshLayout() { SyncLayout(1); } void RefreshLayoutDeep() { SyncLayout(2); } diff --git a/uppsrc/CtrlCore/CtrlPos.cpp b/uppsrc/CtrlCore/CtrlPos.cpp index 24022a553..e5bbb4c52 100644 --- a/uppsrc/CtrlCore/CtrlPos.cpp +++ b/uppsrc/CtrlCore/CtrlPos.cpp @@ -5,8 +5,40 @@ namespace Upp { #define LLOG(x) // DLOG(x) #define LTIMING(x) // RTIMING(x) -bool Ctrl::Logc::IsEmpty() const { - return GetAlign() == SIZE ? GetB() <= GetA() : GetB() <= 0; +void Ctrl::LogPosSet(LogPos p) +{ + if(p.CanPack()) { + packed_pos = p; + } + else { + packed_pos.x.a = 16001; + SetLogPosAttr(Ctrl::ATTR_LOGPOS, p); + } +} + +Ctrl::LogPos Ctrl::GetPos() const +{ + if(packed_pos.x.a == 16001) + return GetLogPosAttr(Ctrl::ATTR_LOGPOS); + return packed_pos; +} + +void Ctrl::RectSet(const Rect& r) +{ + auto CanPack = [](int a) { return a >= -32000 && a <= 32000; }; + if(CanPack(r.left) && CanPack(r.right) && CanPack(r.top) && CanPack(r.bottom)) + packed_rect = r; + else { + SetRectAttr(Ctrl::ATTR_RECT, r); + packed_rect.left = 32001; + } +} + +Rect Ctrl::GetRect() const +{ + if(packed_rect.left == 32001) + return GetRectAttr(Ctrl::ATTR_RECT); + return packed_rect; } Size Ctrl::PosVal(int v) const { @@ -49,19 +81,15 @@ Rect Ctrl::CalcRect(LogPos pos, const Rect& prect, const Rect& pview) const Rect Ctrl::CalcRect(const Rect& prect, const Rect& pview) const { - return CalcRect(pos, prect, pview); -} - -Rect Ctrl::GetRect() const -{ - return rect; + return CalcRect(GetPos(), prect, pview); } Rect Ctrl::GetView() const { GuiLock __; int n = GetFrameCount(); - return n == 0 ? Rect(Size(rect.Size())) : Rect(GetFrame0(n - 1).GetView()); + Rect vr = GetRect().Size(); + return n == 0 ? vr : GetFrame0(n - 1).GetView(); } Size Ctrl::GetSize() const @@ -162,7 +190,7 @@ void Ctrl::SyncLayout(int force) } if(oview.Size() != view.Size() || force > 1) { for(Ctrl& q : *this) { - q.rect = q.CalcRect(rect, view); + q.RectSet(q.CalcRect(GetRect(), view)); LLOG("Layout set rect " << q.Name() << " " << q.rect); q.SyncLayout(force > 1 ? force : 0); } @@ -205,7 +233,7 @@ Ctrl::MoveCtrl *Ctrl::FindMoveCtrlPtr(VectorMap& m, Ctrl *x) void Ctrl::SetPos0(LogPos p, bool _inframe) { GuiLock __; - if(p == pos && inframe == _inframe) return; + if(p == GetPos() && inframe == _inframe) return; Ctrl *parent = GetParent(); if(parent && !IsDHCtrl()) { if(!globalbackbuffer) { @@ -213,7 +241,7 @@ void Ctrl::SetPos0(LogPos p, bool _inframe) Top *top = GetTopRect(from, true)->GetTop(); if(top) { LTIMING("SetPos0 MoveCtrl"); - pos = p; + LogPosSet(p); inframe = _inframe; Rect to = GetRect().Size(); UpdateRect0(); @@ -236,7 +264,7 @@ void Ctrl::SetPos0(LogPos p, bool _inframe) } RefreshFrame(); } - pos = p; + LogPosSet(p); inframe = _inframe; UpdateRect(); StateH(POSITION); @@ -248,13 +276,13 @@ void Ctrl::UpdateRect0(bool sync) LTIMING("UpdateRect0"); Ctrl *parent = GetParent(); if(parent) - rect = CalcRect(parent->GetRect(), parent->GetView()); + RectSet(CalcRect(parent->GetRect(), parent->GetView())); else { static Rect pwa; ONCELOCK { pwa = GetPrimaryWorkArea(); } - rect = CalcRect(pwa, pwa); + RectSet(CalcRect(pwa, pwa)); } LLOG("UpdateRect0 " << Name() << " to " << rect); LTIMING("UpdateRect0 SyncLayout"); @@ -274,7 +302,7 @@ Ctrl& Ctrl::SetPos(LogPos p, bool _inframe) { GuiLock __; Ctrl *parent = GetParent(); - if(p != pos || inframe != _inframe) { + if(p != GetPos() || inframe != _inframe) { if(parent || !IsOpen()) SetPos0(p, _inframe); else { @@ -293,12 +321,12 @@ Ctrl& Ctrl::SetPos(LogPos p) Ctrl& Ctrl::SetPosX(Logc x) { - return SetPos(LogPos(x, pos.y)); + return SetPos(LogPos(x, GetPos().y)); } Ctrl& Ctrl::SetPosY(Logc y) { - return SetPos(LogPos(pos.x, y)); + return SetPos(LogPos(GetPos().x, y)); } Ctrl& Ctrl::SetFramePos(LogPos p) @@ -307,18 +335,17 @@ Ctrl& Ctrl::SetFramePos(LogPos p) } Ctrl& Ctrl::SetFramePosX(Logc x) { - return SetPos(LogPos(x, pos.y), true); + return SetPos(LogPos(x, GetPos().y), true); } Ctrl& Ctrl::SetFramePosY(Logc y) { - return SetPos(LogPos(pos.x, y), true); + return SetPos(LogPos(GetPos().x, y), true); } void Ctrl::SetRect(int x, int y, int cx, int cy) { LLOG("SetRect " << Name() << " rect: " << RectC(x, y, cx, cy)); - auto clampc = [](int c) { return clamp(c, -32700, 32700); }; // Logc vals only have 15 bits - SetPos(PosLeft(clampc(x), clampc(cx)), PosTop(clampc(y), clampc(cy))); + SetPos(PosLeft(x, cx), PosTop(y, cy)); } void Ctrl::SetWndRect(const Rect& r) diff --git a/upptst/TopWindowSetRect/TopWindowSetRect.upp b/upptst/TopWindowSetRect/TopWindowSetRect.upp new file mode 100644 index 000000000..5872304d3 --- /dev/null +++ b/upptst/TopWindowSetRect/TopWindowSetRect.upp @@ -0,0 +1,9 @@ +uses + CtrlLib; + +file + main.cpp; + +mainconfig + "" = "GUI"; + diff --git a/upptst/TopWindowSetRect/main.cpp b/upptst/TopWindowSetRect/main.cpp new file mode 100644 index 000000000..166ec2754 --- /dev/null +++ b/upptst/TopWindowSetRect/main.cpp @@ -0,0 +1,46 @@ +#include + +using namespace Upp; + +GUI_APP_MAIN +{ + DDUMP(sizeof(Ctrl::PackedLogPos)); + TopWindow win; + win.SetRect(0, 0, 200, 200); + Ctrl a; + win << a; + + for(int pass = 0; pass < 2; pass++) { + DLOG("================="); + DDUMP(win.GetRect()); + DDUMP(a.LeftPos(10, 100).TopPos(10, 100).GetRect()); + DDUMP(a.GetScreenRect()); + DDUMP(a.RightPos(10, 100).BottomPos(10, 100).GetRect()); + DDUMP(a.GetScreenRect()); + DDUMP(a.VSizePos(10, 10).HSizePos(10, 10).GetRect()); + DDUMP(a.GetScreenRect()); + DDUMP(a.HCenterPos(100).VCenterPos(100).GetRect()); + DDUMP(a.GetScreenRect()); + win.SetRect(100000, 100000, 30000, 30000); + } + +#if 0 + { + Ctrl x; + x.LeftPos(10, 100).TopPos(10, 100); + Ctrl::Logc p = x.GetPos().x; + DDUMP(p.GetAlign()); + DDUMP(p.GetA()); + DDUMP(p.GetB()); + } + + PromptOK("Test"); + TopWindow win; + win.SetRect(100000, 100000, 200, 200); + DDUMP(win.GetRect()); + + Rect r(1234567, 8, 9, 10); + win.SetRectAttr(Ctrl::ATTR_RECT, r); + DDUMP(win.GetRectAttr(Ctrl::ATTR_RECT)); +#endif +}