gui_sizeof merged, double formatting precsion in JSON/XML reduced to 15 digits

This commit is contained in:
Mirek Fidler 2022-06-03 11:43:48 +02:00
commit 0449296f07
93 changed files with 3268 additions and 1789 deletions

View file

@ -0,0 +1,10 @@
uses
CtrlLib;
file
etalon.log,
main.cpp;
mainconfig
"" = "GUI";

View file

@ -0,0 +1,15 @@
* C:\upp\out\gui_sizeof_autotest\CLANGx64.Debug.Debug_Full.Gui\CtrlChildren.exe 12.04.2022 11:30:36, user: cxl
==============================
N3Upp5LabelE
N3Upp10EditMinMaxIiNS_10ConvertIntEEE
==============================
N3Upp5LabelE
N3Upp10StaticRectE
N3Upp10EditMinMaxIiNS_10ConvertIntEEE
==============================
N3Upp10StaticRectE
N3Upp10EditMinMaxIiNS_10ConvertIntEEE
==============================
N3Upp10StaticRectE
==============================

View file

@ -0,0 +1,29 @@
#include <CtrlLib/CtrlLib.h>
using namespace Upp;
GUI_APP_MAIN
{
TopWindow top;
Label lbl;
EditInt edit;
StaticRect list;
auto Print = [&] {
DLOG("==============================");
for(Ctrl& q : top)
DLOG(typeid(q).name());
};
top << lbl << edit;
Print();
top.AddChild(&list, &lbl);
Print();
lbl.Remove();
Print();
edit.Ctrl::Remove();
Print();
list.Ctrl::Remove();
Print();
CheckLogEtalon();
}

View file

@ -0,0 +1,9 @@
uses
CtrlLib;
file
main.cpp;
mainconfig
"" = "GUI";

View file

@ -0,0 +1,53 @@
#include <CtrlLib/CtrlLib.h>
using namespace Upp;
GUI_APP_MAIN
{
NullFrameClass fr[50];
for(int q = 0; q < 10000; q++) {
DLOG("==========");
Ctrl h;
Vector<CtrlFrame *> h1;
int N = Random(40) + 1;
h1.Add(&NullFrame());
for(int i = 0; i < N; i++) {
int pos = Random(h.GetFrameCount() + 1);
CtrlFrame& val = fr[Random(50)];
h.InsertFrame(pos, val);
h1.Insert(pos, &val);
DDUMP(h.GetFrameCount());
DDUMP(h1.GetCount());
ASSERT(h1.GetCount() == h.GetFrameCount());
for(int i = 0; i < h.GetFrameCount(); i++)
ASSERT(&h.GetFrame(i) == h1[i]);
#if 0
DLOG("===========");
DDUMP(pos);
DDUMP(val);
DDUMP(h.GetFrameCount());
for(int i = 0; i < h.GetFrameCount(); i++)
DLOG(i << " " << h.GetFrame(i));
#endif
}
while(h.GetFrameCount() > 1) {
int pos = Random(h.GetFrameCount());
h.RemoveFrame(pos);
h1.Remove(pos);
DDUMP(h.GetFrameCount());
DDUMP(h1.GetCount());
ASSERT(h1.GetCount() == h.GetFrameCount());
for(int i = 0; i < h.GetFrameCount(); i++)
ASSERT(&h.GetFrame(i) == h1[i]);
#if 0
DLOG("===========");
DDUMP(pos);
DDUMP(h.GetFrameCount());
for(int i = 0; i < h.GetFrameCount(); i++)
DLOG(i << " " << h.GetFrame(i));
#endif
}
}
DLOG("================ OK");
}

View file

@ -0,0 +1,10 @@
uses
CtrlLib;
file
etalon.log,
main.cpp;
mainconfig
"" = "GUI";

View file

@ -0,0 +1,27 @@
* C:\upp\out\gui_sizeof_autotest\CLANGx64.Debug.Debug_Full.Gui\CtrlInfoParts.exe 11.04.2022 18:41:30, user: cxl
========================
h.GetLayoutId() = just some literal
h.GetTip() =
h.GetDescription() =
h.GetHelpLine() =
========================
h.GetLayoutId() = just some text
h.GetTip() =
h.GetDescription() =
h.GetHelpLine() =
========================
h.GetLayoutId() = just some literal
h.GetTip() =
h.GetDescription() =
h.GetHelpLine() = some helpline
========================
h.GetLayoutId() = just some text
h.GetTip() =
h.GetDescription() =
h.GetHelpLine() = some helpline
========================
h.GetLayoutId() = just some literal
h.GetTip() = this is tip
h.GetDescription() = this is description
h.GetHelpLine() = some helpline

View file

@ -0,0 +1,51 @@
#include <CtrlLib/CtrlLib.h>
using namespace Upp;
GUI_APP_MAIN
{
auto Print = [&](Ctrl& h) {
DLOG("========================");
DDUMP(h.GetLayoutId());
DDUMP(h.GetTip());
DDUMP(h.GetDescription());
DDUMP(h.GetHelpLine());
};
{
Ctrl h;
h.LayoutIdLiteral("just some literal");
Print(h);
}
{
Ctrl h;
h.LayoutId(String("just some text"));
Print(h);
}
{
Ctrl h;
h.LayoutIdLiteral("just some literal");
h.HelpLine("some helpline");
Print(h);
}
{
Ctrl h;
h.LayoutId(String("just some text"));
h.HelpLine("some helpline");
Print(h);
}
{
Ctrl h;
h.LayoutIdLiteral("just some literal");
h.Tip("this is tip");
h.HelpLine("some helpline");
h.Description("this is description");
Print(h);
}
CheckLogEtalon();
}

View file

@ -25,8 +25,8 @@ GUI_APP_MAIN
RDUMP(sizeof(EditIntSpin)); RDUMP(sizeof(EditIntSpin));
RDUMP(sizeof(DisplayPopup)); RDUMP(sizeof(DisplayPopup));
RDUMP(sizeof(PopUpTable)); RDUMP(sizeof(PopUpTable));
RDUMP(sizeof(WithDropChoice<EditString>));
RDUMP(sizeof(DropList)); RDUMP(sizeof(DropList));
RDUMP(sizeof(WithDropChoice<EditString>));
RDUMP(sizeof(ArrayCtrl)); RDUMP(sizeof(ArrayCtrl));
RDUMP(sizeof(TreeCtrl)); RDUMP(sizeof(TreeCtrl));
RDUMP(sizeof(TreeCtrl::Node)); RDUMP(sizeof(TreeCtrl::Node));

View file

@ -95,12 +95,14 @@ file
Algo.h, Algo.h,
CoAlgo.h, CoAlgo.h,
Sorted.h, Sorted.h,
Sort.h,
CoSort.h, CoSort.h,
Obsolete.h, Obsolete.h,
Sort.h,
Vcont.h, Vcont.h,
BiCont.h, BiCont.h,
Other.h, Other.h,
Other.hpp,
PackedData.cpp,
Vcont.hpp, Vcont.hpp,
Vcont.cpp, Vcont.cpp,
Index.h, Index.h,

View file

@ -343,15 +343,19 @@ void Index<T>::Serialize(Stream& s)
h.Serialize(s); h.Serialize(s);
if(s.IsLoading()) if(s.IsLoading())
for(int i = 0; i < h.GetCount(); i++) for(int i = 0; i < h.GetCount(); i++)
if(h[i] & 0x80000000) if(i < GetCount() && h[i] & 0x80000000)
Unlink(i); Unlink(i);
} }
else { else {
Vector<int> u = GetUnlinked(); Vector<int> u = GetUnlinked();
u.Serialize(s); u.Serialize(s);
if(s.IsLoading()) if(s.IsLoading())
for(int i : ReverseRange(u)) // Reverse range to ensure the correct order of Put for(int i : ReverseRange(u)) { // Reverse range to ensure the correct order of Put
Unlink(i); if(i >= 0 && i < GetCount())
Unlink(i);
else
s.LoadError();
}
} }
} }

View file

@ -147,7 +147,7 @@ String AsJSON(const Value& v, const String& sep, bool pretty)
if(v.GetType() == BOOL_V) if(v.GetType() == BOOL_V)
return (bool)v ? "true" : "false"; return (bool)v ? "true" : "false";
if(IsNumber(v)) if(IsNumber(v))
return FormatG((double)v, 17); return FormatG((double)v, 15);
if(IsString(v)) if(IsString(v))
return AsCString((String)v, INT_MAX, NULL, ASCSTRING_JSON); return AsCString((String)v, INT_MAX, NULL, ASCSTRING_JSON);
if(IsDateTime(v)) if(IsDateTime(v))

View file

@ -113,6 +113,8 @@ template <class K, class T, class V>
void AMap<K, T, V>::Serialize(Stream& s) { void AMap<K, T, V>::Serialize(Stream& s) {
int version = 0; int version = 0;
s / version % key % value; s / version % key % value;
if(key.GetCount() != value.GetCount())
s.LoadError();
} }
template <class K, class T, class V> template <class K, class T, class V>
@ -167,6 +169,8 @@ void AMap<K, T, V>::Sweep()
template <class K, class T, class V, class Less> template <class K, class T, class V, class Less>
void FixedAMap<K, T, V, Less>::Serialize(Stream& s) { void FixedAMap<K, T, V, Less>::Serialize(Stream& s) {
s % key % value; s % key % value;
if(key.GetCount() != value.GetCount())
s.LoadError();
} }
template <class K, class T, class V, class Less> template <class K, class T, class V, class Less>

View file

@ -103,117 +103,50 @@ public:
void operator=(const Bits&) = delete; void operator=(const Bits&) = delete;
}; };
//# System dependent class PackedData {
template <class T> void *ptr = nullptr;
class Mitor : Moveable< Mitor<T> > {
union { template <class T>
mutable unsigned count; T Get(int ii, T def) const;
mutable Vector<T> *vector;
};
byte elem0[sizeof(T)];
T& Get(int i) const;
void Pick(Mitor&& m);
void Copy(const Mitor& m);
void Chk() const { ASSERT(count != 2); }
public: public:
T& operator[](int i) { return Get(i); } void SetRawPtr(void *p) { ptr = p; }
const T& operator[](int i) const { return Get(i); } void *GetRawPtr() const { return ptr; }
int GetCount() const;
T& Add();
void Add(const T& x);
void Clear();
void Shrink();
Mitor(Mitor&& m) { Pick(pick(m)); } void SetData(int ii, const void *data, int datalen);
void operator=(Mitor&& m) { if(this != &m) { Clear(); Pick(pick(m)); } }
Mitor(Mitor& m, int) { Copy(m); } template <class F>
bool GetData(int ii, F out) const;
void SetNull(int ii) { SetData(ii, NULL, 0); }
Mitor() { count = 0; } void SetString(int ii, const char *s) { SetData(ii, s, strlen(s)); }
~Mitor() { Clear(); } void SetString(int ii, const String& s) { SetData(ii, s, s.GetCount()); }
String GetString(int ii) const { String r; GetData(ii, [&](const char *s, int n) { r = String(s, n); }); return r; }
void SetInt(int ii, int val) { SetData(ii, &val, sizeof(int)); }
int GetInt(int ii, int def) const { return Get<int>(ii, def); }
void SetDword(int ii, dword val) { SetData(ii, &val, sizeof(dword)); }
int GetDword(int ii, dword def) const { return Get<dword>(ii, def); }
void SetInt64(int ii, int64 val) { SetData(ii, &val, sizeof(int64)); }
int64 GetInt64(int ii, int64 def) const { return Get<int64>(ii, def); }
void SetPtr(int ii, void *val) { SetData(ii, &val, sizeof(void *)); }
void *GetPtr(int ii) const { return Get<void *>(ii, nullptr); }
void Clear();
Vector<String> Unpack() const;
size_t GetPackedSize() const;
String GetPacked() const { return String((const char *)ptr, GetPackedSize()); }
PackedData() {}
PackedData(const PackedData&) = delete;
~PackedData();
}; };
template <class T>
T& Mitor<T>::Get(int i) const
{
ASSERT(i >= 0 && i < GetCount());
return i == 0 ? *(T*)elem0 : (*const_cast<Vector<T>*>(vector))[i - 1];
}
template <class T>
void Mitor<T>::Pick(Mitor&& m)
{
m.Chk();
vector = m.vector;
memcpy(&elem0, &m.elem0, sizeof(T));
m.count = 2;
}
template <class T>
void Mitor<T>::Copy(const Mitor& m)
{
m.Chk();
if(m.count > 0)
DeepCopyConstruct(elem0, (const T*)m.elem0);
if(m.count > 1)
vector = new Vector<T>(*m.vector, 1);
}
template <class T>
int Mitor<T>::GetCount() const
{
Chk();
return count > 1 ? vector->GetCount() + 1 : count;
}
template <class T>
T& Mitor<T>::Add()
{
Chk();
if(count == 0) {
count = 1;
return *new(elem0) T;
}
if(count == 1)
vector = new Vector<T>;
return vector->Add();
}
template <class T>
void Mitor<T>::Add(const T& x)
{
Chk();
if(count == 0) {
count = 1;
new((T*) elem0) T(x);
}
else {
if(count == 1)
vector = new Vector<T>;
vector->Add(x);
}
}
template <class T>
void Mitor<T>::Clear()
{
if(count > 2)
delete vector;
if(count && count != 2)
((T*)elem0)->~T();
count = 0;
}
template <class T>
void Mitor<T>::Shrink()
{
if(count > 2)
vector->Shrink();
}
//#
template <class T, int N = 1> template <class T, int N = 1>
struct Link { struct Link {
T *link_prev[N]; T *link_prev[N];
@ -336,169 +269,4 @@ public:
LRUCache() { head = -1; size = 0; count = 0; ClearCounters(); } LRUCache() { head = -1; size = 0; count = 0; ClearCounters(); }
}; };
template <class T, class K> #include "Other.hpp"
void LRUCache<T, K>::LinkHead(int i)
{
Item& m = data[i];
if(head >= 0) {
int tail = data[head].prev;
m.next = head;
m.prev = tail;
data[head].prev = i;
data[tail].next = i;
}
else
m.prev = m.next = i;
head = i;
count++;
}
template <class T, class K>
void LRUCache<T, K>::Unlink(int i)
{
Item& m = data[i];
if(m.prev == i)
head = -1;
else {
if(head == i)
head = m.next;
data[m.next].prev = m.prev;
data[m.prev].next = m.next;
}
count--;
}
template <class T, class K>
T& LRUCache<T, K>::GetLRU()
{
int tail = data[head].prev;
return *data[tail].data;
}
template <class T, class K>
const K& LRUCache<T, K>::GetLRUKey()
{
int tail = data[head].prev;
return key[tail].key;
}
template <class T, class K>
void LRUCache<T, K>::DropLRU()
{
if(head >= 0) {
int tail = data[head].prev;
size -= data[tail].size;
data[tail].data.Clear();
Unlink(tail);
key.Unlink(tail);
}
}
template <class T, class K>
template <class P>
void LRUCache<T, K>::AdjustSize(P getsize)
{
size = 0;
count = 0;
for(int i = 0; i < data.GetCount(); i++)
if(!key.IsUnlinked(i)) {
int sz = getsize(*data[i].data);
if(sz >= 0)
data[i].size = sz + InternalSize;
size += data[i].size;
count++;
}
}
template <class T, class K>
template <class P>
int LRUCache<T, K>::Remove(P predicate)
{
int n = 0;
int i = 0;
while(i < data.GetCount())
if(!key.IsUnlinked(i) && predicate(*data[i].data)) {
size -= data[i].size;
Unlink(i);
key.Unlink(i);
n++;
}
else
i++;
return n;
}
template <class T, class K>
template <class P>
bool LRUCache<T, K>::RemoveOne(P predicate)
{
int i = head;
if(i >= 0)
for(;;) {
int next = data[i].next;
if(predicate(*data[i].data)) {
size -= data[i].size;
Unlink(i);
key.Unlink(i);
return true;
}
if(i == next || next == head || next < 0)
break;
i = next;
}
return false;
}
template <class T, class K>
void LRUCache<T, K>::Shrink(int maxsize, int maxcount)
{
if(maxsize >= 0 && maxcount >= 0)
while(count > maxcount || size > maxsize)
DropLRU();
}
template <class T, class K>
void LRUCache<T, K>::Clear()
{
head = -1;
size = 0;
count = 0;
newsize = foundsize = 0;
key.Clear();
data.Clear();
}
template <class T, class K>
void LRUCache<T, K>::ClearCounters()
{
flag = !flag;
newsize = foundsize = 0;
}
template <class T, class K>
T& LRUCache<T, K>::Get(const Maker& m)
{
Key k;
k.key = m.Key();
k.type = typeid(m).name();
int q = key.Find(k);
if(q < 0) {
q = key.Put(k);
Item& t = data.At(q);
t.size = m.Make(t.data.Create()) + InternalSize;
size += t.size;
newsize += t.size;
t.flag = flag;
}
else {
Item& t = data[q];
Unlink(q);
if(t.flag != flag) {
t.flag = flag;
foundsize += t.size;
}
}
LinkHead(q);
return *data[q].data;
}

204
uppsrc/Core/Other.hpp Normal file
View file

@ -0,0 +1,204 @@
template <class F>
bool PackedData::GetData(int ii, F out) const
{
int i = 0;
const byte *s = (const byte *)ptr;
if(s)
for(;;) {
int len = *s++;
if(len == 255)
break;
if(len == 254) {
memcpy(&len, s, 4);
s += 4;
}
if(i == ii) {
out((const char *)s, len);
return true;
}
s += len;
i++;
}
out("", 0);
return false;
}
template <class T>
T PackedData::Get(int ii, T def) const
{
T q = def;
GetData(ii, [&](const char *ptr, int len) {
if(len) {
ASSERT(len == sizeof(T));
memcpy(&q, ptr, sizeof(T));
}
});
return q;
}
template <class T, class K>
void LRUCache<T, K>::LinkHead(int i)
{
Item& m = data[i];
if(head >= 0) {
int tail = data[head].prev;
m.next = head;
m.prev = tail;
data[head].prev = i;
data[tail].next = i;
}
else
m.prev = m.next = i;
head = i;
count++;
}
template <class T, class K>
void LRUCache<T, K>::Unlink(int i)
{
Item& m = data[i];
if(m.prev == i)
head = -1;
else {
if(head == i)
head = m.next;
data[m.next].prev = m.prev;
data[m.prev].next = m.next;
}
count--;
}
template <class T, class K>
T& LRUCache<T, K>::GetLRU()
{
int tail = data[head].prev;
return *data[tail].data;
}
template <class T, class K>
const K& LRUCache<T, K>::GetLRUKey()
{
int tail = data[head].prev;
return key[tail].key;
}
template <class T, class K>
void LRUCache<T, K>::DropLRU()
{
if(head >= 0) {
int tail = data[head].prev;
size -= data[tail].size;
data[tail].data.Clear();
Unlink(tail);
key.Unlink(tail);
}
}
template <class T, class K>
template <class P>
void LRUCache<T, K>::AdjustSize(P getsize)
{
size = 0;
count = 0;
for(int i = 0; i < data.GetCount(); i++)
if(!key.IsUnlinked(i)) {
int sz = getsize(*data[i].data);
if(sz >= 0)
data[i].size = sz + InternalSize;
size += data[i].size;
count++;
}
}
template <class T, class K>
template <class P>
int LRUCache<T, K>::Remove(P predicate)
{
int n = 0;
int i = 0;
while(i < data.GetCount())
if(!key.IsUnlinked(i) && predicate(*data[i].data)) {
size -= data[i].size;
Unlink(i);
key.Unlink(i);
n++;
}
else
i++;
return n;
}
template <class T, class K>
template <class P>
bool LRUCache<T, K>::RemoveOne(P predicate)
{
int i = head;
if(i >= 0)
for(;;) {
int next = data[i].next;
if(predicate(*data[i].data)) {
size -= data[i].size;
Unlink(i);
key.Unlink(i);
return true;
}
if(i == next || next == head || next < 0)
break;
i = next;
}
return false;
}
template <class T, class K>
void LRUCache<T, K>::Shrink(int maxsize, int maxcount)
{
if(maxsize >= 0 && maxcount >= 0)
while(count > maxcount || size > maxsize)
DropLRU();
}
template <class T, class K>
void LRUCache<T, K>::Clear()
{
head = -1;
size = 0;
count = 0;
newsize = foundsize = 0;
key.Clear();
data.Clear();
}
template <class T, class K>
void LRUCache<T, K>::ClearCounters()
{
flag = !flag;
newsize = foundsize = 0;
}
template <class T, class K>
T& LRUCache<T, K>::Get(const Maker& m)
{
Key k;
k.key = m.Key();
k.type = typeid(m).name();
int q = key.Find(k);
if(q < 0) {
q = key.Put(k);
Item& t = data.At(q);
t.size = m.Make(t.data.Create()) + InternalSize;
size += t.size;
newsize += t.size;
t.flag = flag;
}
else {
Item& t = data[q];
Unlink(q);
if(t.flag != flag) {
t.flag = flag;
foundsize += t.size;
}
}
LinkHead(q);
return *data[q].data;
}

134
uppsrc/Core/PackedData.cpp Normal file
View file

@ -0,0 +1,134 @@
#include "Core.h"
namespace Upp {
PackedData::~PackedData()
{
if(ptr) MemoryFree(ptr);
}
void PackedData::Clear()
{
if(ptr) MemoryFree(ptr);
ptr = nullptr;
}
Vector<String> PackedData::Unpack() const
{
Vector<String> r;
const byte *s = (const byte *)ptr;
for(;;) {
int len = *s++;
if(len == 255)
break;
if(len == 254) {
memcpy(&len, s, 4);
s += 4;
}
r << String(s, len);
s += len;
}
return r;
}
void PackedData::SetData(int ii, const void *data, int datalen)
{
size_t alloc = 32;
char *result = (char *)MemoryAllocSz(alloc);
char *t = result;
auto Reserve = [&](int n) {
size_t needs = t + n - result;
if(needs > alloc) {
alloc = 3 * needs / 2;
char *r2 = (char *)MemoryAllocSz(alloc);
memcpy(r2, result, t - result);
MemoryFree(result);
t = t - result + r2;
result = r2;
}
};
auto Out1 = [&](int c) {
Reserve(1);
*t++ = c;
};
auto Out = [&](const void *s, int len) {
Reserve(len);
memcpy(t, s, len);
t += len;
};
int i = 0;
const byte *p = (const byte *)ptr;
const byte *s = p;
const byte *b = s; // before last control code
const byte *rb = NULL; // start of replaced area
const byte *re = NULL; // end of replaced area
if(s)
for(;;) {
b = s;
int len = *s++;
if(len == 255)
break;
if(len == 254) {
memcpy(&len, s, sizeof(int));
s += sizeof(int);
}
if(i == ii) {
rb = b;
s += len;
re = s;
}
else
s += len;
i++;
}
auto Put = [&]() {
if(datalen < 254)
Out1(datalen);
else {
Out1(254);
byte h[sizeof(int)];
memcpy(h, &datalen, sizeof(int));
Out(h, sizeof(int));
}
Out(data, datalen);
};
if(rb) { // we have found an area to replace
Out(p, int(rb - p));
Put();
Out(re, int((s - re)));
}
else { // we need to add new entries
if(p) // copy existing entries
Out(p, int(b - p));
while(i < ii) {
Out1(0);
i++;
}
Put();
Out1(255);
}
if(ptr)
MemoryFree(ptr);
ptr = result;
}
size_t PackedData::GetPackedSize() const
{
if(!ptr)
return 0;
const byte *s = (const byte *)ptr;
for(;;) {
int len = *s++;
if(len == 255)
break;
if(len == 254) {
memcpy(&len, s, 4);
s += 4;
}
s += len;
}
return s - (const byte *)ptr;
}
};

View file

@ -2,27 +2,6 @@
namespace Upp { namespace Upp {
/* Faster, but consuming more memory....
PteBase::Prec *PteBase::PtrAdd()
{
AtomicInc(prec->n);
return prec;
}
void PteBase::PtrRelease(Prec *prec)
{
if(prec && AtomicDec(prec->n) == 0)
delete prec;
}
PteBase::PteBase()
{
prec = new Prec;
prec->n = 1;
prec->ptr = this;
}
*/
static StaticMutex sPteLock; static StaticMutex sPteLock;
PteBase::Prec *PteBase::PtrAdd() PteBase::Prec *PteBase::PtrAdd()

View file

@ -11,7 +11,6 @@ protected:
Prec *PtrAdd(); Prec *PtrAdd();
static void PtrRelease(Prec *prec); static void PtrRelease(Prec *prec);
static Prec *PtrAdd(const Uuid& uuid);
PteBase(); PteBase();
~PteBase(); ~PteBase();

View file

@ -290,6 +290,8 @@ bool ValueMap::Data::IsNull() const {
void ValueMap::Data::Serialize(Stream& s) { void ValueMap::Data::Serialize(Stream& s) {
s % key % value; s % key % value;
if(key.GetCount() != value.GetCount())
s.LoadError();
} }
void ValueMap::Data::Xmlize(XmlIO& xio) void ValueMap::Data::Xmlize(XmlIO& xio)

View file

@ -116,6 +116,8 @@ void Bits::Serialize(Stream& s)
if(s.IsStoring()) if(s.IsStoring())
dwords = GetLast() + 1; dwords = GetLast() + 1;
s % dwords; s % dwords;
if(dwords < 0)
s.LoadError();
if(s.IsLoading()) if(s.IsLoading())
CreateRaw(dwords); CreateRaw(dwords);
s.SerializeRaw(bp, dwords); s.SerializeRaw(bp, dwords);

View file

@ -737,11 +737,12 @@ void BiVector<T>::Free() {
} }
} }
#ifdef UPP
template <class T> template <class T>
void BiVector<T>::Serialize(Stream& s) { void BiVector<T>::Serialize(Stream& s) {
int n = items; int n = items;
s / n; s / n;
if(n < 0)
s.LoadError();
if(s.IsLoading()) { if(s.IsLoading()) {
Clear(); Clear();
while(n--) while(n--)
@ -758,8 +759,6 @@ String BiVector<T>::ToString() const
return AsStringArray(*this); return AsStringArray(*this);
} }
#endif
template <class T> template <class T>
BiVector<T>::BiVector(std::initializer_list<T> init) BiVector<T>::BiVector(std::initializer_list<T> init)
{ {
@ -794,11 +793,12 @@ void BiArray<T>::DeepCopy0(const BiArray<T>& v) {
bv.AddTail() = new T(clone(v[i])); bv.AddTail() = new T(clone(v[i]));
} }
#ifdef UPP
template <class T> template <class T>
void BiArray<T>::Serialize(Stream& s) { void BiArray<T>::Serialize(Stream& s) {
int n = bv.GetCount(); int n = bv.GetCount();
s / n; s / n;
if(n < 0)
s.LoadError();
if(s.IsLoading()) { if(s.IsLoading()) {
Clear(); Clear();
while(n--) while(n--)
@ -822,8 +822,6 @@ BiArray<T>::BiArray(std::initializer_list<T> init)
AddTail(q); AddTail(q);
} }
#endif
inline inline
void Bits::Set(int i, dword bits, int count) void Bits::Set(int i, dword bits, int count)
{ {

View file

@ -62,7 +62,7 @@ template<> void XmlAttrLoad(dword& var, const String& text)
template<> String XmlAttrStore(const double& var) template<> String XmlAttrStore(const double& var)
{ {
return FormatG(var, 17); return FormatG(var, 15);
} }
template<> void XmlAttrLoad(double& var, const String& text) template<> void XmlAttrLoad(double& var, const String& text)

View file

@ -79,7 +79,9 @@ void Ctrl::Layout() {}
void Ctrl::PostInput() void Ctrl::PostInput()
{ {
GuiLock __; GuiLock __;
if(parent) parent->PostInput(); Ctrl *parent = GetParent();
if(parent)
parent->PostInput();
} }
void Ctrl::LeftDouble(Point p, dword keyflags) void Ctrl::LeftDouble(Point p, dword keyflags)
@ -105,25 +107,33 @@ void Ctrl::RightTriple(Point p, dword keyflags)
void Ctrl::ChildGotFocus() void Ctrl::ChildGotFocus()
{ {
GuiLock __; GuiLock __;
if(parent) parent->ChildGotFocus(); Ctrl *parent = GetParent();
if(parent)
parent->ChildGotFocus();
} }
void Ctrl::ChildLostFocus() void Ctrl::ChildLostFocus()
{ {
GuiLock __; GuiLock __;
if(parent) parent->ChildLostFocus(); Ctrl *parent = GetParent();
if(parent)
parent->ChildLostFocus();
} }
void Ctrl::ChildAdded(Ctrl *q) void Ctrl::ChildAdded(Ctrl *q)
{ {
GuiLock __; GuiLock __;
if(parent) parent->ChildAdded(q); Ctrl *parent = GetParent();
if(parent)
parent->ChildAdded(q);
} }
void Ctrl::ChildRemoved(Ctrl *q) void Ctrl::ChildRemoved(Ctrl *q)
{ {
GuiLock __; GuiLock __;
if(parent) parent->ChildRemoved(q); Ctrl *parent = GetParent();
if(parent)
parent->ChildRemoved(q);
} }
void Ctrl::ParentChange() {} void Ctrl::ParentChange() {}
@ -287,6 +297,7 @@ void Ctrl::Show(bool ashow) {
visible = ashow; visible = ashow;
fullrefresh = false; fullrefresh = false;
RefreshFrame(); RefreshFrame();
Ctrl *parent = GetParent();
if(parent) if(parent)
StateH(SHOW); StateH(SHOW);
if(top) if(top)
@ -301,8 +312,9 @@ bool Ctrl::IsVisible() const {
const Ctrl *q = this; const Ctrl *q = this;
for(;;) { for(;;) {
if(!q->visible) return false; if(!q->visible) return false;
if(!q->parent) break; Ctrl *p = q->GetParent();
q = q->parent; if(!p) break;
q = p;
} }
return q->visible; return q->visible;
} }
@ -312,7 +324,7 @@ void Ctrl::Enable(bool aenable) {
if(enabled != aenable) { if(enabled != aenable) {
enabled = aenable; enabled = aenable;
if(top) WndEnable(enabled); if(top) WndEnable(enabled);
if(!enabled && parent && HasFocusDeep()) if(!enabled && GetParent() && HasFocusDeep())
IterateFocusForward(this, GetTopCtrl()); IterateFocusForward(this, GetTopCtrl());
RefreshFrame(); RefreshFrame();
StateH(ENABLE); StateH(ENABLE);
@ -322,6 +334,7 @@ void Ctrl::Enable(bool aenable) {
bool Ctrl::IsShowEnabled() const { bool Ctrl::IsShowEnabled() const {
GuiLock __; GuiLock __;
Ctrl *parent = GetParent();
return IsEnabled() && (!parent || parent->IsShowEnabled()); return IsEnabled() && (!parent || parent->IsShowEnabled());
} }
@ -353,8 +366,8 @@ void Ctrl::ClearModifyDeep()
{ {
GuiLock __; GuiLock __;
ClearModify(); ClearModify();
for(Ctrl *q = firstchild; q; q = q->next) for(Ctrl& q : *this)
q->ClearModifyDeep(); q.ClearModifyDeep();
} }
@ -368,92 +381,14 @@ bool Ctrl::IsModifiedDeep() const
{ {
GuiLock __; GuiLock __;
if(IsModified()) return true; if(IsModified()) return true;
for(Ctrl *q = firstchild; q; q = q->next) for(const Ctrl& q : *this)
if(q->IsModified()) return true; if(q.IsModified()) return true;
return false; return false;
} }
void Ctrl::SetCaret(const Rect& r)
{
SetCaret(r.left, r.top, r.GetWidth(), r.GetHeight());
}
Rect Ctrl::GetCaret() const Rect Ctrl::GetCaret() const
{ {
return RectC(caretx, carety, caretcx, caretcy); return Null;
}
void Ctrl::KillCaret()
{
SetCaret(0, 0, 0, 0);
}
void Ctrl::SetInfoPart(int i, const char *txt)
{
Vector<String> f = Split(info, '\x7f', false);
f.At(i) = txt;
info = Join(f, "\x7f");
}
Ctrl& Ctrl::Tip(const char *txt)
{
SetInfoPart(0, txt);
return *this;
}
Ctrl& Ctrl::HelpLine(const char *txt)
{
SetInfoPart(1, txt);
return *this;
}
Ctrl& Ctrl::Description(const char *txt)
{
SetInfoPart(2, txt);
return *this;
}
Ctrl& Ctrl::HelpTopic(const char *txt)
{
SetInfoPart(3, txt);
return *this;
}
Ctrl& Ctrl::LayoutId(const char *txt)
{
SetInfoPart(4, txt);
return *this;
}
String Ctrl::GetInfoPart(int i) const
{
Vector<String> f = Split(info, '\x7f', false);
return i < f.GetCount() ? f[i] : String();
}
String Ctrl::GetTip() const
{
return GetInfoPart(0);
}
String Ctrl::GetHelpLine() const
{
return GetInfoPart(1);
}
String Ctrl::GetDescription() const
{
return GetInfoPart(2);
}
String Ctrl::GetHelpTopic() const
{
return GetInfoPart(3);
}
String Ctrl::GetLayoutId() const
{
return GetInfoPart(4);
} }
bool Ctrl::SetWantFocus() { bool Ctrl::SetWantFocus() {
@ -493,8 +428,8 @@ void Ctrl::UpdateActionRefresh() {
void Ctrl::CancelModeDeep() { void Ctrl::CancelModeDeep() {
GuiLock __; GuiLock __;
CancelMode(); CancelMode();
for(Ctrl *q = firstchild; q; q = q->next) for(Ctrl& q : *this)
q->CancelModeDeep(); q.CancelModeDeep();
} }
String Ctrl::GetDesc() const String Ctrl::GetDesc() const
@ -547,14 +482,14 @@ void Ctrl::Dump(Stream& s) const {
sFLAG(wantfocus) << sFLAG(editable) << sFLAG(IsModified()) << sFLAG(transparent)); sFLAG(wantfocus) << sFLAG(editable) << sFLAG(IsModified()) << sFLAG(transparent));
LG("Rect: " << GetRect()); LG("Rect: " << GetRect());
LG("View: " << GetView()); LG("View: " << GetView());
for(int i = 0; i < frame.GetCount(); i++) for(int i = 0; i < GetFrameCount(); i++)
LG("Frame " << i << ": " << typeid(decltype(*frame[i].frame)).name() << " - " << frame[i].view); LG("Frame " << i << ": " << typeid(decltype(*GetFrame0(i).frame)).name() << " - " << GetFrame0(i).GetView());
LG("Data: " << GetData().ToString()); LG("Data: " << GetData().ToString());
if(firstchild) { if(children) {
LG("Children"); LG("Children");
s << LOG_BEGIN; s << LOG_BEGIN;
for(Ctrl *q = GetFirstChild(); q; q = q->GetNext()) { for(const Ctrl& q : *this) {
q->Dump(s); q.Dump(s);
LG("------"); LG("------");
} }
s << LOG_END; s << LOG_END;
@ -592,16 +527,13 @@ Ctrl::Ctrl() {
LLOG("Ctrl::Ctrl"); LLOG("Ctrl::Ctrl");
GuiPlatformConstruct(); GuiPlatformConstruct();
destroying = false; destroying = false;
parent = prev = next = firstchild = lastchild = NULL; multi_frame = false;
top = NULL; frame.frame = &NullFrame();
exitcode = 0;
frame.Add().frame = &NullFrame();
enabled = visible = wantfocus = initfocus = true; enabled = visible = wantfocus = initfocus = true;
editable = true; editable = true;
backpaint = IsCompositedGui() ? FULLBACKPAINT : TRANSPARENTBACKPAINT; backpaint = IsCompositedGui() ? FULLBACKPAINT : TRANSPARENTBACKPAINT;
inframe = false; inframe = false;
ignoremouse = transparent = false; ignoremouse = transparent = false;
caretcx = caretcy = caretx = carety = 0;
pos.x = PosLeft(0, 0); pos.x = PosLeft(0, 0);
pos.y = PosTop(0, 0); pos.y = PosTop(0, 0);
rect = Rect(0, 0, 0, 0); rect = Rect(0, 0, 0, 0);
@ -611,6 +543,9 @@ Ctrl::Ctrl() {
popupgrab = false; popupgrab = false;
fullrefresh = false; fullrefresh = false;
akv = false; akv = false;
layout_id_literal = false;
top = false;
uparent = nullptr;
} }
void KillTimeCallbacks(void *id, void *idlim); void KillTimeCallbacks(void *id, void *idlim);
@ -626,6 +561,7 @@ void Ctrl::DoRemove() {
mouseCtrl = NULL; mouseCtrl = NULL;
LLOG("DoRemove " << Name() << " focusCtrl: " << UPP::Name(focusCtrl)); LLOG("DoRemove " << Name() << " focusCtrl: " << UPP::Name(focusCtrl));
GuiPlatformRemove(); GuiPlatformRemove();
Ctrl *parent = GetParent();
if(HasFocusDeep()) { if(HasFocusDeep()) {
LLOG("DoRemove - HasFocusDeep"); LLOG("DoRemove - HasFocusDeep");
if(destroying) { if(destroying) {
@ -675,7 +611,7 @@ void Ctrl::Close()
Ctrl *q = GetTopCtrl(); Ctrl *q = GetTopCtrl();
if(!q->top) return; if(!q->top) return;
DoRemove(); DoRemove();
if(parent) return; if(GetParent()) return;
StateH(CLOSE); StateH(CLOSE);
USRLOG(" CLOSE " + Desc(this)); USRLOG(" CLOSE " + Desc(this));
WndDestroy(); WndDestroy();
@ -689,10 +625,13 @@ Ctrl::~Ctrl() {
destroying = true; destroying = true;
while(GetFirstChild()) while(GetFirstChild())
RemoveChild(GetFirstChild()); RemoveChild(GetFirstChild());
Ctrl *parent = GetParent();
if(parent) if(parent)
parent->RemoveChild(this); parent->RemoveChild(this);
Close(); Close();
KillTimeCallbacks(this, (byte *) this + sizeof(Ctrl)); KillTimeCallbacks(this, (byte *) this + sizeof(Ctrl));
ClearInfo();
FreeFrames();
} }
Vector<Ctrl::MouseHook>& Ctrl::mousehook() { static Vector<Ctrl::MouseHook> h; return h; } Vector<Ctrl::MouseHook>& Ctrl::mousehook() { static Vector<Ctrl::MouseHook> h; return h; }
@ -1035,7 +974,7 @@ String Ctrl::Name0() const {
String id = q->GetLayoutId(); String id = q->GetLayoutId();
if(id.GetCount()) if(id.GetCount())
path = '.' + q->GetLayoutId() + path; path = '.' + q->GetLayoutId() + path;
q = q->parent; q = q->GetParent();
} }
s << ' ' << path; s << ' ' << path;
#ifdef CPU_64 #ifdef CPU_64
@ -1043,6 +982,7 @@ String Ctrl::Name0() const {
#else #else
s << " : " + Format("0x%x", (int) this); s << " : " + Format("0x%x", (int) this);
#endif #endif
Ctrl *parent = GetParent();
if(IsChild()) if(IsChild())
s << " (parent " << CppDemangle(typeid(*parent).name()) << ")"; s << " (parent " << CppDemangle(typeid(*parent).name()) << ")";
return s; return s;
@ -1063,8 +1003,10 @@ void Ctrl::EndLoop()
void Ctrl::EndLoop(int code) void Ctrl::EndLoop(int code)
{ {
GuiLock __; GuiLock __;
ASSERT(!parent); ASSERT(!GetParent());
exitcode = code; TopWindow *w = GetTopWindow();
if(w)
w->exitcode = code;
EndLoop(); EndLoop();
} }
@ -1080,12 +1022,6 @@ bool Ctrl::InCurrentLoop() const
return GetLoopCtrl() == this; return GetLoopCtrl() == this;
} }
int Ctrl::GetExitCode() const
{
GuiLock __;
return exitcode;
}
#ifdef HAS_TopFrameDraw #ifdef HAS_TopFrameDraw
ViewDraw::ViewDraw(Ctrl *ctrl, const Rect& r) ViewDraw::ViewDraw(Ctrl *ctrl, const Rect& r)

View file

@ -0,0 +1,181 @@
#include "CtrlCore.h"
namespace Upp {
PackedData& Ctrl::Attrs()
{
if(layout_id_literal) {
String layout_id((const char *)attrs.GetRawPtr());
attrs.SetRawPtr(nullptr);
attrs.SetString(ATTR_LAYOUT_ID, layout_id);
layout_id_literal = false;
}
return attrs;
}
void Ctrl::SetTextAttr(int ii, const char *s)
{
Attrs().SetString(ii, s);
}
void Ctrl::SetTextAttr(int ii, const String& s)
{
Attrs().SetString(ii, s);
}
String Ctrl::GetTextAttr(int ii) const
{
return layout_id_literal ? String() : attrs.GetString(ii);
}
Ctrl& Ctrl::Tip(const char *txt)
{
SetTextAttr(ATTR_TIP, txt);
return *this;
}
Ctrl& Ctrl::HelpLine(const char *txt)
{
SetTextAttr(ATTR_HELPLINE, txt);
return *this;
}
Ctrl& Ctrl::Description(const char *txt)
{
SetTextAttr(ATTR_DESCRIPTION, txt);
return *this;
}
Ctrl& Ctrl::HelpTopic(const char *txt)
{
SetTextAttr(ATTR_HELPTOPIC, txt);
return *this;
}
Ctrl& Ctrl::LayoutId(const char *txt)
{
SetTextAttr(ATTR_LAYOUT_ID, txt);
return *this;
}
Ctrl& Ctrl::LayoutIdLiteral(const char *txt)
{
if(attrs.GetRawPtr() && !layout_id_literal)
LayoutId(txt);
else {
attrs.SetRawPtr((void *)txt);
layout_id_literal = true;
}
return *this;
}
String Ctrl::GetLayoutId() const
{
if(layout_id_literal)
return (const char *)attrs.GetRawPtr();
return GetTextAttr(ATTR_LAYOUT_ID);
}
String Ctrl::GetTip() const
{
return GetTextAttr(ATTR_TIP);
}
String Ctrl::GetHelpLine() const
{
return GetTextAttr(ATTR_HELPLINE);
}
String Ctrl::GetDescription() const
{
return GetTextAttr(ATTR_DESCRIPTION);
}
String Ctrl::GetHelpTopic() const
{
return GetTextAttr(ATTR_HELPTOPIC);
}
void Ctrl::ClearInfo()
{
if(layout_id_literal)
attrs.SetRawPtr(nullptr);
layout_id_literal = false;
attrs.Clear();
}
void Ctrl::SetColorAttr(int ii, Color c)
{
Attrs();
if(IsNull(c))
attrs.SetNull(ii);
else
attrs.SetDword(ii, c.GetRaw());
}
Color Ctrl::GetColorAttr(int ii) const
{
if(layout_id_literal)
return Null;
static dword nullval = Color(Null).GetRaw();
return Color::FromRaw(attrs.GetDword(ii, nullval));
}
void Ctrl::SetFontAttr(int ii, Font fnt)
{
Attrs();
if(IsNull(fnt))
attrs.SetNull(ii);
else
attrs.SetInt64(ii, fnt.AsInt64());
}
Font Ctrl::GetFontAttr(int ii) const
{
if(layout_id_literal)
return Null;
static dword nullval = Font(Null).AsInt64();
return Font::FromInt64(attrs.GetInt64(ii, nullval));
}
void Ctrl::SetIntAttr(int ii, int val)
{
Attrs().SetInt(ii, val);
}
int Ctrl::GetIntAttr(int ii, int def) const
{
if(layout_id_literal)
return def;
return attrs.GetInt(ii, def);
}
void Ctrl::SetInt64Attr(int ii, int64 val)
{
Attrs().SetInt64(ii, val);
}
int Ctrl::GetInt64Attr(int ii, int64 def) const
{
if(layout_id_literal)
return def;
return attrs.GetInt64(ii, def);
}
void Ctrl::SetVoidPtrAttr(int ii, const void *ptr)
{
if(ptr)
Attrs().SetPtr(ii, (void *)ptr);
else
Attrs().SetNull(ii);
}
void *Ctrl::GetVoidPtrAttr(int ii) const
{
if(layout_id_literal)
return NULL;
return attrs.GetPtr(ii);
}
};

View file

@ -4,6 +4,25 @@ namespace Upp {
#define LLOG(x) // DLOG(x) #define LLOG(x) // DLOG(x)
void Ctrl::DeleteTop()
{
if(top && utop) {
delete utop;
utop = nullptr;
top = false;
}
}
void Ctrl::SetParent(Ctrl *parent)
{
if(top && utop) {
Close();
DeleteTop(); // if Close did not work as expected...:
}
uparent = parent;
top = false;
}
bool Ctrl::IsDHCtrl() const { bool Ctrl::IsDHCtrl() const {
return dynamic_cast<const DHCtrl *>(this); return dynamic_cast<const DHCtrl *>(this);
} }
@ -15,38 +34,31 @@ void Ctrl::AddChild(Ctrl *q, Ctrl *p)
LLOG("Add " << UPP::Name(q) << " to: " << Name()); LLOG("Add " << UPP::Name(q) << " to: " << Name());
if(p == q) return; if(p == q) return;
bool updaterect = true; bool updaterect = true;
if(q->parent) { Ctrl *qparent = q->GetParent();
if(qparent) {
ASSERT(!q->inframe); ASSERT(!q->inframe);
if(q->parent == this) { if(qparent == this) {
RemoveChild0(q); RemoveChild0(q);
updaterect = false; updaterect = false;
} }
else else
q->parent->RemoveChild(q); qparent->RemoveChild(q);
} }
q->parent = this;
if(p) { if(children) {
ASSERT(p->parent == this); if(!p) p = GetLastChild();
q->prev = p; ASSERT(p->GetParent() == this);
q->next = p->next; q->prev_sibling = p;
if(p == lastchild) q->next_sibling = p->next_sibling;
lastchild = q; p->next_sibling->prev_sibling = q;
else p->next_sibling = q;
p->next->prev = q;
p->next = q;
} }
else else {
if(firstchild) { ASSERT(!p);
q->prev = NULL; children = q->next_sibling = q->prev_sibling = q;
q->next = firstchild; }
firstchild->prev = q; q->SetParent(this);
firstchild = q;
}
else {
ASSERT(lastchild == NULL);
firstchild = lastchild = q;
q->prev = q->next = NULL;
}
q->CancelModeDeep(); q->CancelModeDeep();
if(updaterect) if(updaterect)
q->UpdateRect(); q->UpdateRect();
@ -58,13 +70,13 @@ void Ctrl::AddChild(Ctrl *q, Ctrl *p)
void Ctrl::AddChild(Ctrl *child) void Ctrl::AddChild(Ctrl *child)
{ {
AddChild(child, lastchild); AddChild(child, GetLastChild());
} }
void Ctrl::AddChildBefore(Ctrl *child, Ctrl *insbefore) void Ctrl::AddChildBefore(Ctrl *child, Ctrl *insbefore)
{ {
if(insbefore) if(insbefore)
AddChild(child, insbefore->prev); AddChild(child, insbefore->GetPrev());
else else
AddChild(child); AddChild(child);
} }
@ -73,23 +85,26 @@ void Ctrl::RemoveChild0(Ctrl *q)
{ {
GuiLock __; GuiLock __;
ChildRemoved(q); ChildRemoved(q);
if(!q->GetParent()) return; // ChildRemoved can remove q
q->DoRemove(); q->DoRemove();
q->parent = NULL; if(!q->GetParent()) return; // DoRemove can remove q
if(q == firstchild) q->SetParent(NULL);
firstchild = firstchild->next;
if(q == lastchild) if(q == children) {
lastchild = lastchild->prev; children = q->next_sibling;
if(q->prev) if(children == q)
q->prev->next = q->next; children = NULL;
if(q->next) }
q->next->prev = q->prev;
q->next = q->prev = NULL; q->prev_sibling->next_sibling = q->next_sibling;
q->next_sibling->prev_sibling = q->prev_sibling;
q->next_sibling = q->prev_sibling = NULL;
} }
void Ctrl::RemoveChild(Ctrl *q) void Ctrl::RemoveChild(Ctrl *q)
{ {
GuiLock __; GuiLock __;
if(q->parent != this) return; if(q->GetParent() != this) return;
q->RefreshFrame(); q->RefreshFrame();
RemoveChild0(q); RemoveChild0(q);
q->ParentChange(); q->ParentChange();
@ -100,6 +115,7 @@ void Ctrl::RemoveChild(Ctrl *q)
void Ctrl::Remove() void Ctrl::Remove()
{ {
GuiLock __; GuiLock __;
Ctrl *parent = GetParent();
if(parent) if(parent)
parent->RemoveChild(this); parent->RemoveChild(this);
} }
@ -171,15 +187,16 @@ Ctrl * Ctrl::GetViewIndexChild(int ii) const
bool Ctrl::HasChild(Ctrl *q) const bool Ctrl::HasChild(Ctrl *q) const
{ {
GuiLock __; GuiLock __;
return q && q->IsChild() && q->parent == this; return q && q->GetParent() == this;
} }
bool Ctrl::HasChildDeep(Ctrl *q) const bool Ctrl::HasChildDeep(Ctrl *q) const
{ {
GuiLock __; GuiLock __;
while(q && q->IsChild()) { while(q && q->IsChild()) {
if(q->parent == this) return true; Ctrl *qparent = q->GetParent();
q = q->parent; if(qparent == this) return true;
q = qparent;
} }
return false; return false;
} }
@ -260,9 +277,12 @@ Ctrl *Ctrl::GetTopCtrl()
{ {
GuiLock __; GuiLock __;
Ctrl *q = this; Ctrl *q = this;
while(q->parent) for(;;) {
q = q->parent; Ctrl *qparent = q->GetParent();
return q; if(!qparent)
return q;
q = qparent;
}
} }
const Ctrl *Ctrl::GetTopCtrl() const { return const_cast<Ctrl *>(this)->GetTopCtrl(); } const Ctrl *Ctrl::GetTopCtrl() const { return const_cast<Ctrl *>(this)->GetTopCtrl(); }
@ -270,7 +290,7 @@ const Ctrl *Ctrl::GetOwner() const { return const_cast<Ctrl *>(this)->Get
Ctrl *Ctrl::GetTopCtrlOwner() { return GetTopCtrl()->GetOwner(); } Ctrl *Ctrl::GetTopCtrlOwner() { return GetTopCtrl()->GetOwner(); }
const Ctrl *Ctrl::GetTopCtrlOwner() const { return GetTopCtrl()->GetOwner(); } const Ctrl *Ctrl::GetTopCtrlOwner() const { return GetTopCtrl()->GetOwner(); }
Ctrl *Ctrl::GetOwnerCtrl() { GuiLock __; return !IsChild() && top ? top->owner : NULL; } Ctrl *Ctrl::GetOwnerCtrl() { GuiLock __; return !IsChild() && top && utop ? utop->owner : NULL; }
const Ctrl *Ctrl::GetOwnerCtrl() const { return const_cast<Ctrl *>(this)->GetOwnerCtrl(); } const Ctrl *Ctrl::GetOwnerCtrl() const { return const_cast<Ctrl *>(this)->GetOwnerCtrl(); }
TopWindow *Ctrl::GetTopWindow() TopWindow *Ctrl::GetTopWindow()

View file

@ -478,14 +478,29 @@ private:
void operator=(Ctrl&); void operator=(Ctrl&);
private: private:
struct Frame : Moveable<Frame> { struct MultiFrame { // in case there are more than 1 CtrlFrames
CtrlFrame *frame; int alloc;
Rect16 view; int count;
Frame() { view.Clear(); }
}; };
Ctrl *parent;
struct Rect16_ { // so that it can be in union
int16 left, top, right, bottom;
};
struct Frame {
union {
CtrlFrame *frame;
Frame *frames;
};
union {
MultiFrame multi;
Rect16_ view;
};
void SetView(const Rect& r) { view.left = r.left; view.right = r.right; view.top = r.top; view.bottom = r.bottom; }
Rect GetView() const { return Rect16(view.left, view.top, view.right, view.bottom); }
};
struct Scroll : Moveable<Scroll> { struct Scroll : Moveable<Scroll> {
Rect rect; Rect rect;
int dx; int dx;
@ -508,16 +523,20 @@ private:
Ptr<Ctrl> owner; Ptr<Ctrl> owner;
}; };
Top *top;
int exitcode;
Ctrl *prev, *next; Frame frame;
Ctrl *firstchild, *lastchild;//16
LogPos pos;//8 LogPos pos;//8
Rect16 rect; Rect16 rect; //8
Mitor<Frame> frame;//16
String info;//16 union {
int16 caretx, carety, caretcx, caretcy;//8 Ctrl *uparent;
Top *utop;
};
Ctrl *prev_sibling = nullptr;
Ctrl *next_sibling = nullptr;
Ctrl *children = nullptr;
PackedData attrs;
byte overpaint; byte overpaint;
@ -543,6 +562,9 @@ private:
bool akv:1; bool akv:1;
bool destroying:1; bool destroying:1;
bool layout_id_literal:1; // info_ptr points to layout char * literal, no heap involved
bool multi_frame:1; // there is more than single frame, they are stored in heap
bool top:1;
static Ptr<Ctrl> eventCtrl; static Ptr<Ctrl> eventCtrl;
static Ptr<Ctrl> mouseCtrl; static Ptr<Ctrl> mouseCtrl;
@ -551,8 +573,6 @@ private:
static Ptr<Ctrl> focusCtrl; static Ptr<Ctrl> focusCtrl;
static Ptr<Ctrl> focusCtrlWnd; static Ptr<Ctrl> focusCtrlWnd;
static Ptr<Ctrl> lastActiveWnd; static Ptr<Ctrl> lastActiveWnd;
static Ptr<Ctrl> caretCtrl;
static Rect caretRect;
static Ptr<Ctrl> captureCtrl; static Ptr<Ctrl> captureCtrl;
static bool ignoreclick; static bool ignoreclick;
static bool ignoremouseup; static bool ignoremouseup;
@ -634,12 +654,20 @@ private:
void RefreshAccessKeys(); void RefreshAccessKeys();
void RefreshAccessKeysDo(bool vis); void RefreshAccessKeysDo(bool vis);
static void DefferedFocusSync(); static void DefferedFocusSync();
static void SyncCaret();
static void RefreshCaret();
static bool DispatchKey(dword keycode, int count); static bool DispatchKey(dword keycode, int count);
void SetFocusWnd(); void SetFocusWnd();
void KillFocusWnd(); void KillFocusWnd();
static Ptr<Ctrl> caretCtrl;
static Ptr<Ctrl> prevCaretCtrl;
static Rect caretRect;
static int WndCaretTime;
static bool WndCaretVisible;
static void AnimateCaret();
static void SyncCaret();
static void RefreshCaret();
static Ptr<Ctrl> dndctrl; static Ptr<Ctrl> dndctrl;
static Point dndpos; static Point dndpos;
static bool dndframe; static bool dndframe;
@ -667,8 +695,6 @@ private:
void UpdateArea(SystemDraw& draw, const Rect& clip); void UpdateArea(SystemDraw& draw, const Rect& clip);
Ctrl *GetTopRect(Rect& r, bool inframe, bool clip = true); Ctrl *GetTopRect(Rect& r, bool inframe, bool clip = true);
void DoSync(Ctrl *q, Rect r, bool inframe); void DoSync(Ctrl *q, Rect r, bool inframe);
void SetInfoPart(int i, const char *txt);
String GetInfoPart(int i) const;
Rect GetPreeditScreenRect(); Rect GetPreeditScreenRect();
void SyncPreedit(); void SyncPreedit();
@ -718,6 +744,21 @@ private:
void SysEndLoop(); void SysEndLoop();
String Name0() const; String Name0() const;
Top *GetTop() { return top ? utop : NULL; }
const Top *GetTop() const { return top ? utop : NULL; }
void DeleteTop();
void SetTop(Top *t) { utop = t; top = true; }
void SetParent(Ctrl *parent);
Frame& GetFrame0(int i) { ASSERT(i < GetFrameCount()); return multi_frame ? frame.frames[i] : frame; }
const Frame& GetFrame0(int i) const { ASSERT(i < GetFrameCount()); return multi_frame ? frame.frames[i] : frame; }
void FreeFrames() { if(multi_frame) MemoryFree(frame.frames); }
Frame AllocFrames(int alloc);
PackedData& Attrs();
static void InitTimer(); static void InitTimer();
@ -779,7 +820,44 @@ protected:
static void TimerProc(dword time); static void TimerProc(dword time);
Ctrl& Unicode() { unicode = true; return *this; } Ctrl& Unicode() { unicode = true; return *this; }
enum {
ATTR_LAYOUT_ID,
ATTR_TIP,
ATTR_HELPLINE,
ATTR_DESCRIPTION,
ATTR_HELPTOPIC,
ATTR_LAST
};
void SetTextAttr(int ii, const char *s);
void SetTextAttr(int ii, const String& s);
String GetTextAttr(int ii) const;
void SetColorAttr(int ii, Color c);
Color GetColorAttr(int ii) const;
void SetFontAttr(int ii, Font fnt);
Font GetFontAttr(int ii) const;
void SetIntAttr(int ii, int val);
int GetIntAttr(int ii, int def = Null) const;
void SetInt64Attr(int ii, int64 val);
int GetInt64Attr(int ii, int64 def = Null) const;
void SetVoidPtrAttr(int ii, const void *ptr);
void *GetVoidPtrAttr(int ii) const;
template <class T>
T& CreateAttr(int ii) { T *q = new T; SetVoidPtrAttr(ii, q); return *q; }
template <class T>
T GetAttr(int ii) const { void *p = GetVoidPtrAttr(ii); return p ? *(T *)p : T(); }
template <class T>
void DeleteAttr(int ii) { void *p = GetVoidPtrAttr(ii); if(p) { delete (T *)p; SetVoidPtrAttr(ii, nullptr); }; }
public: public:
enum StateReason { enum StateReason {
FOCUS = 10, FOCUS = 10,
@ -915,6 +993,8 @@ public:
virtual Point GetPreedit(); virtual Point GetPreedit();
virtual Font GetPreeditFont(); virtual Font GetPreeditFont();
virtual Rect GetCaret() const;
virtual void DragAndDrop(Point p, PasteClip& d); virtual void DragAndDrop(Point p, PasteClip& d);
virtual void FrameDragAndDrop(Point p, PasteClip& d); virtual void FrameDragAndDrop(Point p, PasteClip& d);
virtual void DragRepeat(Point p); virtual void DragRepeat(Point p);
@ -972,11 +1052,11 @@ public:
void AddChild(Ctrl *child, Ctrl *insafter); void AddChild(Ctrl *child, Ctrl *insafter);
void AddChildBefore(Ctrl *child, Ctrl *insbefore); void AddChildBefore(Ctrl *child, Ctrl *insbefore);
void RemoveChild(Ctrl *child); void RemoveChild(Ctrl *child);
Ctrl *GetParent() const { return parent; } Ctrl *GetParent() const { return top ? NULL : uparent; }
Ctrl *GetLastChild() const { return lastchild; } Ctrl *GetLastChild() const { return children ? children->prev_sibling : nullptr; }
Ctrl *GetFirstChild() const { return firstchild; } Ctrl *GetFirstChild() const { return children; }
Ctrl *GetPrev() const { return parent ? prev : NULL; } Ctrl *GetPrev() const { Ctrl *parent = GetParent(); return parent && prev_sibling != parent->GetLastChild() ? prev_sibling : nullptr; }
Ctrl *GetNext() const { return parent ? next : NULL; } Ctrl *GetNext() const { Ctrl *parent = GetParent(); return parent && next_sibling != parent->children ? next_sibling : nullptr; }
int GetChildIndex(const Ctrl *child) const; int GetChildIndex(const Ctrl *child) const;
Ctrl *GetIndexChild(int i) const; Ctrl *GetIndexChild(int i) const;
int GetChildCount() const; int GetChildCount() const;
@ -987,7 +1067,7 @@ public:
int GetViewChildCount() const; int GetViewChildCount() const;
Ctrl *GetViewIndexChild(int ii) const; Ctrl *GetViewIndexChild(int ii) const;
bool IsChild() const { return parent; } bool IsChild() const { return GetParent(); }
Ctrl *ChildFromPoint(Point& pt) const; Ctrl *ChildFromPoint(Point& pt) const;
@ -1013,13 +1093,13 @@ public:
Ctrl& SetFrame(int i, CtrlFrame& frm); Ctrl& SetFrame(int i, CtrlFrame& frm);
Ctrl& SetFrame(CtrlFrame& frm) { return SetFrame(0, frm); } Ctrl& SetFrame(CtrlFrame& frm) { return SetFrame(0, frm); }
Ctrl& AddFrame(CtrlFrame& frm); Ctrl& AddFrame(CtrlFrame& frm);
const CtrlFrame& GetFrame(int i = 0) const { return *frame[i].frame; } const CtrlFrame& GetFrame(int i = 0) const { return *const_cast<Ctrl *>(this)->GetFrame0(i).frame; }
CtrlFrame& GetFrame(int i = 0) { return *frame[i].frame; } CtrlFrame& GetFrame(int i = 0) { return *GetFrame0(i).frame; }
void RemoveFrame(int i); void RemoveFrame(int i);
void RemoveFrame(CtrlFrame& frm); void RemoveFrame(CtrlFrame& frm);
void InsertFrame(int i, CtrlFrame& frm); void InsertFrame(int i, CtrlFrame& frm);
int FindFrame(CtrlFrame& frm); int FindFrame(CtrlFrame& frm) const;
int GetFrameCount() const { return frame.GetCount(); } int GetFrameCount() const { return multi_frame ? frame.multi.count : frame.frame ? 1 : 0; }
void ClearFrames(); void ClearFrames();
bool IsOpen() const; bool IsOpen() const;
@ -1055,10 +1135,10 @@ public:
void RefreshLayout() { SyncLayout(1); } void RefreshLayout() { SyncLayout(1); }
void RefreshLayoutDeep() { SyncLayout(2); } void RefreshLayoutDeep() { SyncLayout(2); }
void RefreshParentLayout() { if(parent) parent->RefreshLayout(); } void RefreshParentLayout();
void UpdateLayout() { SyncLayout(); } void UpdateLayout() { SyncLayout(); }
void UpdateParentLayout() { if(parent) parent->UpdateLayout(); } void UpdateParentLayout();
Ctrl& LeftPos(int a, int size = STDSIZE); Ctrl& LeftPos(int a, int size = STDSIZE);
Ctrl& RightPos(int a, int size = STDSIZE); Ctrl& RightPos(int a, int size = STDSIZE);
@ -1157,11 +1237,6 @@ public:
void CancelModeDeep(); void CancelModeDeep();
void SetCaret(int x, int y, int cx, int cy);
void SetCaret(const Rect& r);
Rect GetCaret() const;
void KillCaret();
static void CancelPreedit(); static void CancelPreedit();
void CancelMyPreedit() { if(HasFocus()) CancelPreedit(); } void CancelMyPreedit() { if(HasFocus()) CancelPreedit(); }
@ -1211,21 +1286,19 @@ public:
Ctrl& NoTransparent() { return Transparent(false); } Ctrl& NoTransparent() { return Transparent(false); }
bool IsTransparent() const { return transparent; } bool IsTransparent() const { return transparent; }
Ctrl& Info(const char *txt) { info = txt; return *this; }
String GetInfo() const { return info; }
Ctrl& Tip(const char *txt); Ctrl& Tip(const char *txt);
Ctrl& HelpLine(const char *txt); Ctrl& HelpLine(const char *txt);
Ctrl& Description(const char *txt); Ctrl& Description(const char *txt);
Ctrl& HelpTopic(const char *txt); Ctrl& HelpTopic(const char *txt);
Ctrl& LayoutId(const char *txt); Ctrl& LayoutId(const char *txt);
Ctrl& LayoutIdLiteral(const char *txt);
String GetTip() const; String GetTip() const;
String GetHelpLine() const; String GetHelpLine() const;
String GetDescription() const; String GetDescription() const;
String GetHelpTopic() const; String GetHelpTopic() const;
String GetLayoutId() const; String GetLayoutId() const;
void ClearInfo() { info.Clear(); } void ClearInfo();
void Add(Ctrl& ctrl) { AddChild(&ctrl); } void Add(Ctrl& ctrl) { AddChild(&ctrl); }
Ctrl& operator<<(Ctrl& ctrl) { Add(ctrl); return *this; } Ctrl& operator<<(Ctrl& ctrl) { Add(ctrl); return *this; }
@ -1276,7 +1349,6 @@ public:
void EndLoop(int code); void EndLoop(int code);
bool InLoop() const; bool InLoop() const;
bool InCurrentLoop() const; bool InCurrentLoop() const;
int GetExitCode() const;
static PasteClip& Clipboard(); static PasteClip& Clipboard();
static PasteClip& Selection(); static PasteClip& Selection();

View file

@ -21,7 +21,9 @@ file
Frame.cpp, Frame.cpp,
CtrlMt.cpp, CtrlMt.cpp,
Ctrl.cpp, Ctrl.cpp,
CtrlAttr.cpp,
CtrlChild.cpp, CtrlChild.cpp,
CtrlFrame.cpp,
CtrlPos.cpp, CtrlPos.cpp,
CtrlDraw.cpp, CtrlDraw.cpp,
CtrlMouse.cpp, CtrlMouse.cpp,

View file

@ -22,6 +22,7 @@ void Ctrl::RefreshFrame(const Rect& r) {
if(GuiPlatformRefreshFrameSpecial(r)) if(GuiPlatformRefreshFrameSpecial(r))
return; return;
if(!top && !IsDHCtrl()) { if(!top && !IsDHCtrl()) {
Ctrl *parent = GetParent();
if(InFrame()) if(InFrame())
parent->RefreshFrame(r + GetRect().TopLeft()); parent->RefreshFrame(r + GetRect().TopLeft());
else else
@ -83,6 +84,7 @@ void Ctrl::ScrollRefresh(const Rect& r, int dx, int dy)
bool Ctrl::AddScroll(const Rect& sr, int dx, int dy) bool Ctrl::AddScroll(const Rect& sr, int dx, int dy)
{ {
GuiLock __; GuiLock __;
Top *top = GetTop();
if(!top) if(!top)
return true; return true;
for(int i = 0; i < top->scroll.GetCount(); i++) { for(int i = 0; i < top->scroll.GetCount(); i++) {
@ -113,12 +115,12 @@ Rect Ctrl::GetClippedView()
GuiLock __; GuiLock __;
Rect sv = GetScreenView(); Rect sv = GetScreenView();
Rect view = sv; Rect view = sv;
Ctrl *q = parent; Ctrl *q = GetParent();
Ctrl *w = this; Ctrl *w = this;
while(q) { while(q) {
view &= w->InFrame() ? q->GetScreenRect() : q->GetScreenView(); view &= w->InFrame() ? q->GetScreenRect() : q->GetScreenView();
w = q; w = q;
q = q->parent; q = q->GetParent();
} }
return view - GetScreenRect().TopLeft(); return view - GetScreenRect().TopLeft();
} }
@ -178,7 +180,7 @@ void Ctrl::ScrollView(const Rect& _r, int dx, int dy)
Rect r = _r & vsz; Rect r = _r & vsz;
LLOG("ScrollView2 " << r << " " << dx << " " << dy); LLOG("ScrollView2 " << r << " " << dx << " " << dy);
Ctrl *w; Ctrl *w;
for(w = this; w->parent; w = w->parent) for(w = this; w->GetParent(); w = w->GetParent())
if(w->InFrame()) { if(w->InFrame()) {
Refresh(); Refresh();
return; return;
@ -191,12 +193,12 @@ void Ctrl::ScrollView(const Rect& _r, int dx, int dy)
Refresh(); Refresh();
else { else {
LTIMING("ScrollCtrls1"); LTIMING("ScrollCtrls1");
Top *top = GetTopCtrl()->top; Top *top = GetTopCtrl()->GetTop();
for(Ctrl *q = GetFirstChild(); q; q = q->GetNext()) for(Ctrl *q = GetFirstChild(); q; q = q->GetNext())
if(q->InView()) if(q->InView())
ScrollCtrl(top, q, r, q->GetRect(), dx, dy); ScrollCtrl(top, q, r, q->GetRect(), dx, dy);
if(parent) if(GetParent())
for(Ctrl *q = parent->GetFirstChild(); q; q = q->GetNext()) for(Ctrl *q = GetParent()->GetFirstChild(); q; q = q->GetNext())
if(q->InView() && q != this) if(q->InView() && q != this)
ScrollCtrl(top, q, r, q->GetScreenRect() - GetScreenView().TopLeft(), dx, dy); ScrollCtrl(top, q, r, q->GetScreenRect() - GetScreenView().TopLeft(), dx, dy);
} }
@ -214,6 +216,7 @@ void Ctrl::ScrollView(int dx, int dy) {
void Ctrl::SyncScroll() void Ctrl::SyncScroll()
{ {
GuiLock __; GuiLock __;
Top *top = GetTop();
if(!top) if(!top)
return; return;
Vector<Scroll> scroll = pick(top->scroll); Vector<Scroll> scroll = pick(top->scroll);
@ -278,29 +281,31 @@ void Ctrl::CtrlPaint(SystemDraw& w, const Rect& clip) {
return; return;
Ctrl *q; Ctrl *q;
Rect view = rect; Rect view = rect;
for(int i = 0; i < frame.GetCount(); i++) { int n = GetFrameCount();
for(int i = 0; i < n; i++) {
LEVELCHECK(w, NULL); LEVELCHECK(w, NULL);
frame[i].frame->FramePaint(w, view); Frame& f = GetFrame0(i);
view = frame[i].view; f.frame->FramePaint(w, view);
view = f.GetView();
} }
Rect oview = view.Inflated(overpaint); Rect oview = view.Inflated(overpaint);
bool hasviewctrls = false; bool hasviewctrls = false;
bool viewexcluded = false; bool viewexcluded = false;
bool hiddenbychild = false; bool hiddenbychild = false;
for(q = firstchild; q; q = q->next) for(Ctrl& q : *this)
if(q->IsShown()) { if(q.IsShown()) {
if(q->GetRect().Contains(orect) && !q->IsTransparent()) if(q.GetRect().Contains(orect) && !q.IsTransparent())
hiddenbychild = true; hiddenbychild = true;
if(q->InFrame()) { if(q.InFrame()) {
if(!viewexcluded && IsTransparent() && q->GetRect().Intersects(view)) { if(!viewexcluded && IsTransparent() && q.GetRect().Intersects(view)) {
w.Begin(); w.Begin();
w.ExcludeClip(view); w.ExcludeClip(view);
viewexcluded = true; viewexcluded = true;
} }
LEVELCHECK(w, q); LEVELCHECK(w, &q);
Point off = q->GetRect().TopLeft(); Point off = q.GetRect().TopLeft();
w.Offset(off); w.Offset(off);
q->CtrlPaint(w, clip - off); q.CtrlPaint(w, clip - off);
w.End(); w.End();
} }
else else
@ -329,15 +334,15 @@ void Ctrl::CtrlPaint(SystemDraw& w, const Rect& clip) {
if(hasviewctrls && !view.IsEmpty()) { if(hasviewctrls && !view.IsEmpty()) {
Rect cl = clip & view; Rect cl = clip & view;
w.Clip(cl); w.Clip(cl);
for(q = firstchild; q; q = q->next) for(Ctrl& q : *this)
if(q->IsShown() && q->InView()) { if(q.IsShown() && q.InView()) {
LEVELCHECK(w, q); LEVELCHECK(w, &q);
Rect qr = q->GetRect(); Rect qr = q.GetRect();
Point off = qr.TopLeft() + view.TopLeft(); Point off = qr.TopLeft() + view.TopLeft();
Rect ocl = cl - off; Rect ocl = cl - off;
if(ocl.Intersects(Rect(qr.GetSize()).Inflated(overpaint))) { if(ocl.Intersects(Rect(qr.GetSize()).Inflated(overpaint))) {
w.Offset(off); w.Offset(off);
q->CtrlPaint(w, ocl); q.CtrlPaint(w, ocl);
w.End(); w.End();
} }
} }
@ -373,11 +378,11 @@ bool Ctrl::PaintOpaqueAreas(SystemDraw& w, const Rect& r, const Rect& clip, bool
if(backpaint == EXCLUDEPAINT) if(backpaint == EXCLUDEPAINT)
return w.ExcludeClip(r); return w.ExcludeClip(r);
Rect cview = clip & (GetView() + off); Rect cview = clip & (GetView() + off);
for(Ctrl *q = lastchild; q; q = q->prev) for(Ctrl& q : *this)
if(!q->PaintOpaqueAreas(w, q->GetRect() + (q->InView() ? viewpos : off), if(!q.PaintOpaqueAreas(w, q.GetRect() + (q.InView() ? viewpos : off),
q->InView() ? cview : clip)) q.InView() ? cview : clip))
return false; return false;
if(nochild && (lastchild || GetNext())) if(nochild && (GetLastChild() || GetNext()))
return true; return true;
Rect opaque = (GetOpaqueRect() + viewpos) & clip; Rect opaque = (GetOpaqueRect() + viewpos) & clip;
if(opaque.IsEmpty()) if(opaque.IsEmpty())
@ -461,11 +466,11 @@ void Ctrl::GatherTransparentAreas(Vector<Rect>& area, SystemDraw& w, Rect r, con
CombineArea(area, clip & Rect(notr.left, r.top, notr.right, notr.top)); CombineArea(area, clip & Rect(notr.left, r.top, notr.right, notr.top));
CombineArea(area, clip & Rect(notr.left, notr.bottom, notr.right, r.bottom)); CombineArea(area, clip & Rect(notr.left, notr.bottom, notr.right, r.bottom));
} }
for(Ctrl *q = firstchild; q; q = q->next) { for(Ctrl& q : *this) {
Point qoff = q->InView() ? viewpos : off; Point qoff = q.InView() ? viewpos : off;
Rect qr = q->GetRect() + qoff; Rect qr = q.GetRect() + qoff;
if(clip.Intersects(qr)) if(clip.Intersects(qr))
q->GatherTransparentAreas(area, w, qr, clip); q.GatherTransparentAreas(area, w, qr, clip);
} }
} }
} }
@ -506,9 +511,9 @@ void Ctrl::ExcludeDHCtrls(SystemDraw& w, const Rect& r, const Rect& clip)
return; return;
} }
Rect cview = clip & (GetView() + off); Rect cview = clip & (GetView() + off);
for(Ctrl *q = lastchild; q; q = q->prev) for(Ctrl& q : *this)
q->ExcludeDHCtrls(w, q->GetRect() + (q->InView() ? viewpos : off), q.ExcludeDHCtrls(w, q.GetRect() + (q.InView() ? viewpos : off),
q->InView() ? cview : clip); q.InView() ? cview : clip);
} }
void Ctrl::UpdateArea0(SystemDraw& draw, const Rect& clip, int backpaint) void Ctrl::UpdateArea0(SystemDraw& draw, const Rect& clip, int backpaint)
@ -597,6 +602,7 @@ Ctrl *Ctrl::GetTopRect(Rect& r, bool inframe, bool clip)
r &= Rect(GetSize()); r &= Rect(GetSize());
r.Offset(GetView().TopLeft()); r.Offset(GetView().TopLeft());
} }
Ctrl *parent = GetParent();
if(parent) { if(parent) {
r.Offset(GetRect().TopLeft()); r.Offset(GetRect().TopLeft());
return parent->GetTopRect(r, InFrame(), clip); return parent->GetTopRect(r, InFrame(), clip);
@ -620,6 +626,7 @@ void Ctrl::Sync()
{ {
GuiLock __; GuiLock __;
LLOG("Sync " << Name()); LLOG("Sync " << Name());
Ctrl *parent = GetParent();
if(top && IsOpen()) { if(top && IsOpen()) {
LLOG("Sync UpdateWindow " << Name()); LLOG("Sync UpdateWindow " << Name());
SyncScroll(); SyncScroll();
@ -642,6 +649,7 @@ void Ctrl::Sync(const Rect& sr)
void Ctrl::DrawCtrlWithParent(Draw& w, int x, int y) void Ctrl::DrawCtrlWithParent(Draw& w, int x, int y)
{ {
GuiLock __; GuiLock __;
Ctrl *parent = GetParent();
if(parent) { if(parent) {
Rect r = GetRect(); Rect r = GetRect();
Ctrl *top = parent->GetTopRect(r, inframe); Ctrl *top = parent->GetTopRect(r, inframe);
@ -674,6 +682,7 @@ void Ctrl::DrawCtrl(Draw& w, int x, int y)
void Ctrl::SyncMoves() void Ctrl::SyncMoves()
{ {
GuiLock __; GuiLock __;
Top *top = GetTop();
if(!top) if(!top)
return; return;
for(int i = 0; i < top->move.GetCount(); i++) { for(int i = 0; i < top->move.GetCount(); i++) {

View file

@ -0,0 +1,131 @@
#include "CtrlCore.h"
#define LLOG(x)
namespace Upp {
Ctrl::Frame Ctrl::AllocFrames(int alloc)
{
Frame m;
size_t sz0 = alloc * sizeof(Frame);
size_t sz = sz0;
m.frames = (Frame *)MemoryAllocSz(sz);
m.multi.alloc = alloc + (int)((sz - sz0) / sizeof(Frame));
return m;
}
void Ctrl::InsertFrame(int i, CtrlFrame& fr)
{
GuiLock __;
int fc = GetFrameCount();
ASSERT(i <= fc);
if(i == 0 && fc == 0) {
frame.frame = &fr;
multi_frame = false;
}
else {
if(!multi_frame) {
Frame h = AllocFrames(2);
h.frames[0].frame = frame.frame;
h.multi.count = 1;
frame = h;
multi_frame = true;
}
if(frame.multi.count + 1 > frame.multi.alloc) {
Frame h = AllocFrames(3 * frame.multi.count / 2 + 1);
memcpy(h.frames, frame.frames, i * sizeof(Frame));
memcpy(h.frames + i + 1, frame.frames + i, (frame.multi.count - i) * sizeof(Frame));
h.multi.count = frame.multi.count;
FreeFrames();
frame = h;
}
else
memmove(frame.frames + i + 1, frame.frames + i, (frame.multi.count - i) * sizeof(Frame));
frame.frames[i].frame = &fr;
frame.multi.count++;
}
fr.FrameAdd(*this);
SyncLayout();
RefreshFrame();
}
Ctrl& Ctrl::AddFrame(CtrlFrame& fr) {
InsertFrame(GetFrameCount(), fr);
return *this;
}
void Ctrl::RemoveFrame(int i) {
ASSERT(i < GetFrameCount());
GetFrame(i).FrameRemove();
if(multi_frame) {
ASSERT(frame.multi.count > 1);
memmove(frame.frames + i, frame.frames + i + 1, (frame.multi.count - i - 1) * sizeof(Frame));
frame.multi.count--;
if(frame.multi.count == 1) {
CtrlFrame *h = frame.frames[0].frame;
FreeFrames();
multi_frame = false;
frame.frame = h;
}
else
if(3 * frame.multi.count < frame.multi.alloc) {
Frame h = AllocFrames(3 * frame.multi.count / 2 + 1);
memcpy(h.frames, frame.frames, frame.multi.count * sizeof(Frame));
h.multi.count = frame.multi.count;
FreeFrames();
frame = h;
}
}
else
frame.frame = nullptr;
if(GetFrameCount() == 0)
SetFrame(NullFrame());
SyncLayout();
RefreshFrame();
}
Ctrl& Ctrl::SetFrame(int i, CtrlFrame& fr) {
GuiLock __;
LLOG("SetFrame " << typeid(fr).name());
while(GetFrameCount() <= i)
AddFrame(NullFrame());
Frame& f = GetFrame0(i);
f.frame->FrameRemove();
f.frame = &fr;
fr.FrameAdd(*this);
SyncLayout();
RefreshFrame();
return *this;
}
void Ctrl::ClearFrames() {
GuiLock __;
int n = GetFrameCount();
for(int i = 0; i < n; i++)
GetFrame(i).FrameRemove();
FreeFrames();
multi_frame = false;
frame.frame = &NullFrame();
SyncLayout();
RefreshFrame();
}
int Ctrl::FindFrame(CtrlFrame& frm) const
{
GuiLock __;
int n = GetFrameCount();
for(int i = 0; i < n; i++)
if(&GetFrame(i) == &frm)
return i;
return -1;
}
void Ctrl::RemoveFrame(CtrlFrame& frm)
{
GuiLock __;
int i = FindFrame(frm);
if(i >= 0)
RemoveFrame(i);
}
};

View file

@ -7,8 +7,6 @@ namespace Upp {
Ptr<Ctrl> Ctrl::focusCtrl; Ptr<Ctrl> Ctrl::focusCtrl;
Ptr<Ctrl> Ctrl::focusCtrlWnd; Ptr<Ctrl> Ctrl::focusCtrlWnd;
Ptr<Ctrl> Ctrl::lastActiveWnd; Ptr<Ctrl> Ctrl::lastActiveWnd;
Ptr<Ctrl> Ctrl::caretCtrl;
Rect Ctrl::caretRect;
bool Ctrl::ignorekeyup; bool Ctrl::ignorekeyup;
Ptr<Ctrl> Ctrl::defferedSetFocus; Ptr<Ctrl> Ctrl::defferedSetFocus;
@ -116,7 +114,7 @@ bool Ctrl::HotKey(dword key)
GuiLock __; GuiLock __;
LLOG("HotKey " << GetKeyDesc(key) << " at " << Name(this)); LLOG("HotKey " << GetKeyDesc(key) << " at " << Name(this));
if(!IsEnabled() || !IsVisible()) return false; if(!IsEnabled() || !IsVisible()) return false;
for(Ptr<Ctrl> ctrl = firstchild; ctrl; ctrl = ctrl->next) for(Ptr<Ctrl> ctrl = GetFirstChild(); ctrl; ctrl = ctrl->GetNext())
{ {
LLOG("Trying HotKey " << GetKeyDesc(key) << " at " << Name(ctrl)); LLOG("Trying HotKey " << GetKeyDesc(key) << " at " << Name(ctrl));
if(ctrl->IsOpen() && ctrl->IsVisible() && ctrl->IsEnabled() && ctrl->HotKey(key)) if(ctrl->IsOpen() && ctrl->IsVisible() && ctrl->IsEnabled() && ctrl->HotKey(key))
@ -158,8 +156,8 @@ void Ctrl::DoKillFocus(Ptr<Ctrl> pfocusCtrl, Ptr<Ctrl> nfocusCtrl)
LLOG("LostFocus: " << Name(pfocusCtrl)); LLOG("LostFocus: " << Name(pfocusCtrl));
pfocusCtrl->LostFocus(); pfocusCtrl->LostFocus();
} }
if(pfocusCtrl && pfocusCtrl->parent && !pfocusCtrl->parent->destroying) if(pfocusCtrl && pfocusCtrl->GetParent() && !pfocusCtrl->GetParent()->destroying)
pfocusCtrl->parent->ChildLostFocus(); pfocusCtrl->GetParent()->ChildLostFocus();
SyncCaret(); SyncCaret();
} }
@ -179,9 +177,9 @@ void Ctrl::DoSetFocus(Ptr<Ctrl> pfocusCtrl, Ptr<Ctrl> nfocusCtrl, bool activate)
nfocusCtrl->GotFocus(); nfocusCtrl->GotFocus();
nfocusCtrl->StateH(FOCUS); nfocusCtrl->StateH(FOCUS);
} }
if(focusCtrl == nfocusCtrl && nfocusCtrl && nfocusCtrl->parent && if(focusCtrl == nfocusCtrl && nfocusCtrl && nfocusCtrl->GetParent() &&
!nfocusCtrl->parent->destroying) !nfocusCtrl->GetParent()->destroying)
nfocusCtrl->parent->ChildGotFocus(); nfocusCtrl->GetParent()->ChildGotFocus();
SyncCaret(); SyncCaret();
} }
@ -340,14 +338,6 @@ void Ctrl::DefferedFocusSync()
} }
} }
void Ctrl::RefreshCaret()
{
GuiLock __;
if(caretCtrl)
caretCtrl->Refresh(caretCtrl->caretx, caretCtrl->carety,
caretCtrl->caretcx, caretCtrl->caretcy);
}
Ctrl *Ctrl::GetActiveWindow() Ctrl *Ctrl::GetActiveWindow()
{ {
GuiLock __; GuiLock __;
@ -364,6 +354,61 @@ bool Ctrl::HasFocusDeep() const
a = a->GetOwnerCtrl(); a = a->GetOwnerCtrl();
return a && HasChildDeep(a); return a && HasChildDeep(a);
} }
Ptr<Ctrl> Ctrl::caretCtrl;
Ptr<Ctrl> Ctrl::prevCaretCtrl;
Rect Ctrl::caretRect;
int Ctrl::WndCaretTime;
bool Ctrl::WndCaretVisible;
void Ctrl::RefreshCaret()
{
GuiLock __;
if(prevCaretCtrl) {
prevCaretCtrl->Refresh(caretRect);
prevCaretCtrl = nullptr;
}
if(caretCtrl) {
caretRect = caretCtrl->GetCaret();
caretCtrl->Refresh(caretRect);
prevCaretCtrl = caretCtrl;
}
}
void Ctrl::AnimateCaret()
{
GuiLock __;
bool v = !(((msecs() - WndCaretTime) / GetCaretBlinkTime()) & 1);
if(v != WndCaretVisible) {
WndCaretVisible = v;
RefreshCaret();
}
}
void Ctrl::PaintCaret(SystemDraw& w)
{
GuiLock __;
LLOG("PaintCaret " << Name() << ", caretCtrl: " << caretCtrl << ", WndCaretVisible: " << WndCaretVisible);
if(this == caretCtrl && WndCaretVisible)
w.DrawRect(GetCaret(), InvertColor);
}
void Ctrl::SyncCaret() {
GuiLock __;
LLOG("SyncCaret");
if(focusCtrl != caretCtrl) {
LLOG("SyncCaret DO " << Upp::Name(caretCtrl) << " -> " << Upp::Name(focusCtrl));
RefreshCaret();
caretCtrl = focusCtrl;
WndCaretTime = msecs();
RefreshCaret();
}
else {
if(caretCtrl && caretCtrl->GetCaret() != caretRect) {
WndCaretTime = msecs();
RefreshCaret();
}
}
}
Tuple<dword, const char *> KeyNames__[ ] = { Tuple<dword, const char *> KeyNames__[ ] = {
{ K_A, tt_("key\vA") }, { K_B, tt_("key\vB") }, { K_C, tt_("key\vC") }, { K_D, tt_("key\vD") }, { K_A, tt_("key\vA") }, { K_B, tt_("key\vB") }, { K_C, tt_("key\vC") }, { K_D, tt_("key\vD") },

View file

@ -74,6 +74,7 @@ Image Ctrl::FrameMouseEventH(int event, Point p, int zdelta, dword keyflags)
if(this_) if(this_)
LogMouseEvent("FRAME ", this, event, p, zdelta, keyflags); LogMouseEvent("FRAME ", this, event, p, zdelta, keyflags);
eventCtrl = this_; eventCtrl = this_;
Ctrl *parent = GetParent();
if(parent && this_) if(parent && this_)
parent->ChildFrameMouseEvent(this, event, p, zdelta, keyflags); parent->ChildFrameMouseEvent(this, event, p, zdelta, keyflags);
return this_ ? FrameMouseEvent(event, p, zdelta, keyflags) : Image(); return this_ ? FrameMouseEvent(event, p, zdelta, keyflags) : Image();
@ -93,6 +94,7 @@ Image Ctrl::MouseEvent0(int event, Point p, int zdelta, dword keyflags)
bool pb = sPropagated; bool pb = sPropagated;
sPropagated = false; sPropagated = false;
Image m = this_ ? MouseEvent(event, p, zdelta, keyflags) : Image(); Image m = this_ ? MouseEvent(event, p, zdelta, keyflags) : Image();
Ctrl *parent = this_ ? this_->GetParent() : NULL;
if(event == MOUSEWHEEL && !sPropagated && this_ && parent) if(event == MOUSEWHEEL && !sPropagated && this_ && parent)
parent->ChildMouseEvent(this, event, p, zdelta, keyflags); parent->ChildMouseEvent(this, event, p, zdelta, keyflags);
sPropagated = pb; sPropagated = pb;
@ -108,6 +110,7 @@ Image Ctrl::MouseEventH(int event, Point p, int zdelta, dword keyflags)
return Image::Arrow(); return Image::Arrow();
if(this_) if(this_)
LogMouseEvent(NULL, this, event, p, zdelta, keyflags); LogMouseEvent(NULL, this, event, p, zdelta, keyflags);
Ctrl *parent = this_ ? this_->GetParent() : NULL;
if(this_ && parent && event != MOUSEWHEEL) if(this_ && parent && event != MOUSEWHEEL)
parent->ChildMouseEvent(this, event, p, zdelta, keyflags); parent->ChildMouseEvent(this, event, p, zdelta, keyflags);
return MouseEvent0(event, p, zdelta, keyflags); return MouseEvent0(event, p, zdelta, keyflags);
@ -115,6 +118,7 @@ Image Ctrl::MouseEventH(int event, Point p, int zdelta, dword keyflags)
void Ctrl::MouseWheel(Point p, int zd, dword kf) void Ctrl::MouseWheel(Point p, int zd, dword kf)
{ {
Ctrl *parent = GetParent();
if(parent) { if(parent) {
p += GetScreenView().TopLeft(); p += GetScreenView().TopLeft();
Rect r = parent->GetScreenView(); Rect r = parent->GetScreenView();
@ -128,6 +132,7 @@ void Ctrl::MouseWheel(Point p, int zd, dword kf)
void Ctrl::ChildFrameMouseEvent(Ctrl *child, int event, Point p, int zdelta, dword keyflags) void Ctrl::ChildFrameMouseEvent(Ctrl *child, int event, Point p, int zdelta, dword keyflags)
{ {
GuiLock __; GuiLock __;
Ctrl *parent = GetParent();
if(parent) if(parent)
parent->ChildFrameMouseEvent(child, event, p, zdelta, keyflags); parent->ChildFrameMouseEvent(child, event, p, zdelta, keyflags);
} }
@ -135,6 +140,7 @@ void Ctrl::ChildFrameMouseEvent(Ctrl *child, int event, Point p, int zdelta, dwo
void Ctrl::ChildMouseEvent(Ctrl *child, int event, Point p, int zdelta, dword keyflags) void Ctrl::ChildMouseEvent(Ctrl *child, int event, Point p, int zdelta, dword keyflags)
{ {
GuiLock __; GuiLock __;
Ctrl *parent = GetParent();
if(parent) if(parent)
parent->ChildMouseEvent(child, event, p, zdelta, keyflags); parent->ChildMouseEvent(child, event, p, zdelta, keyflags);
} }
@ -280,7 +286,7 @@ Ctrl *Ctrl::ChildFromPoint(Point& pt) const
Rect view = GetView(); Rect view = GetView();
if(view.Contains(p)) { if(view.Contains(p)) {
Point vp = p - view.TopLeft(); Point vp = p - view.TopLeft();
for(q = GetLastChild(); q; q = q->prev) { for(q = GetLastChild(); q; q = q->GetPrev()) {
if(q->InView() && q->IsMouseActive()) { if(q->InView() && q->IsMouseActive()) {
Rect r = q->GetRect(); Rect r = q->GetRect();
if(r.Contains(vp)) { if(r.Contains(vp)) {
@ -291,7 +297,7 @@ Ctrl *Ctrl::ChildFromPoint(Point& pt) const
} }
return NULL; return NULL;
} }
for(q = GetLastChild(); q; q = q->prev) { for(q = GetLastChild(); q; q = q->GetPrev()) {
if(q->InFrame() && q->IsMouseActive()) { if(q->InFrame() && q->IsMouseActive()) {
Rect r = q->GetRect(); Rect r = q->GetRect();
if(r.Contains(p)) { if(r.Contains(p)) {

View file

@ -60,7 +60,8 @@ Rect Ctrl::GetRect() const
Rect Ctrl::GetView() const Rect Ctrl::GetView() const
{ {
GuiLock __; GuiLock __;
return frame.GetCount() == 0 ? Rect(Size(rect.Size())) : Rect(frame[frame.GetCount() - 1].view); int n = GetFrameCount();
return n == 0 ? Rect(Size(rect.Size())) : Rect(GetFrame0(n - 1).GetView());
} }
Size Ctrl::GetSize() const Size Ctrl::GetSize() const
@ -72,6 +73,7 @@ Rect Ctrl::GetScreenRect() const
{ {
GuiLock __; GuiLock __;
Rect r = GetRect(); Rect r = GetRect();
Ctrl *parent = GetParent();
if(parent) { if(parent) {
Rect pr = inframe ? parent->GetScreenRect() : parent->GetScreenView(); Rect pr = inframe ? parent->GetScreenRect() : parent->GetScreenView();
r = r + pr.TopLeft(); r = r + pr.TopLeft();
@ -91,6 +93,7 @@ Rect Ctrl::GetVisibleScreenRect() const
{ {
GuiLock __; GuiLock __;
Rect r = GetRect(); Rect r = GetRect();
Ctrl *parent = GetParent();
if(parent) { if(parent) {
Rect pr = inframe ? parent->GetVisibleScreenRect() : parent->GetVisibleScreenView(); Rect pr = inframe ? parent->GetVisibleScreenRect() : parent->GetVisibleScreenView();
Rect pr1 = inframe ? parent->GetScreenRect() : parent->GetScreenView(); Rect pr1 = inframe ? parent->GetScreenRect() : parent->GetScreenView();
@ -111,8 +114,8 @@ Size Ctrl::AddFrameSize(int cx, int cy) const
{ {
GuiLock __; GuiLock __;
Size sz = Size(cx, cy); Size sz = Size(cx, cy);
for(int i = frame.GetCount() - 1; i >= 0; i--) for(int i = GetFrameCount() - 1; i >= 0; i--)
frame[i].frame->FrameAddSize(sz); GetFrame0(i).frame->FrameAddSize(sz);
return sz; return sz;
} }
@ -146,21 +149,22 @@ void Ctrl::SyncLayout(int force)
Rect oview = GetView(); Rect oview = GetView();
Rect view = GetRect().Size(); Rect view = GetRect().Size();
overpaint = OverPaint(); overpaint = OverPaint();
for(int i = 0; i < frame.GetCount(); i++) { int n = GetFrameCount();
Frame& f = frame[i]; for(int i = 0; i < n; i++) {
Frame& f = GetFrame0(i);
f.frame->FrameLayout(view); f.frame->FrameLayout(view);
if(view != Rect(f.view)) { if(view != f.GetView()) {
f.view = view; f.SetView(view);
refresh = true; refresh = true;
} }
int q = f.frame->OverPaint(); int q = f.frame->OverPaint();
if(q > overpaint) overpaint = q; if(q > overpaint) overpaint = q;
} }
if(oview.Size() != view.Size() || force > 1) { if(oview.Size() != view.Size() || force > 1) {
for(Ctrl *q = GetFirstChild(); q; q = q->next) { for(Ctrl& q : *this) {
q->rect = q->CalcRect(rect, view); q.rect = q.CalcRect(rect, view);
LLOG("Layout set rect " << q->Name() << " " << q->rect); LLOG("Layout set rect " << q.Name() << " " << q.rect);
q->SyncLayout(force > 1 ? force : 0); q.SyncLayout(force > 1 ? force : 0);
} }
Refresh(); Refresh();
} }
@ -172,6 +176,20 @@ void Ctrl::SyncLayout(int force)
RefreshFrame(); RefreshFrame();
} }
void Ctrl::RefreshParentLayout()
{
Ctrl *parent = GetParent();
if(parent)
parent->RefreshLayout();
}
void Ctrl::UpdateParentLayout()
{
Ctrl *parent = GetParent();
if(parent)
parent->UpdateLayout();
}
int Ctrl::FindMoveCtrl(const VectorMap<Ctrl *, MoveCtrl>& m, Ctrl *x) int Ctrl::FindMoveCtrl(const VectorMap<Ctrl *, MoveCtrl>& m, Ctrl *x)
{ {
int q = m.Find(x); int q = m.Find(x);
@ -188,10 +206,11 @@ void Ctrl::SetPos0(LogPos p, bool _inframe)
{ {
GuiLock __; GuiLock __;
if(p == pos && inframe == _inframe) return; if(p == pos && inframe == _inframe) return;
Ctrl *parent = GetParent();
if(parent && !IsDHCtrl()) { if(parent && !IsDHCtrl()) {
if(!globalbackbuffer) { if(!globalbackbuffer) {
Rect from = GetRect().Size(); Rect from = GetRect().Size();
Top *top = GetTopRect(from, true)->top; Top *top = GetTopRect(from, true)->GetTop();
if(top) { if(top) {
LTIMING("SetPos0 MoveCtrl"); LTIMING("SetPos0 MoveCtrl");
pos = p; pos = p;
@ -227,6 +246,7 @@ void Ctrl::UpdateRect0(bool sync)
{ {
GuiLock __; GuiLock __;
LTIMING("UpdateRect0"); LTIMING("UpdateRect0");
Ctrl *parent = GetParent();
if(parent) if(parent)
rect = CalcRect(parent->GetRect(), parent->GetView()); rect = CalcRect(parent->GetRect(), parent->GetView());
else { else {
@ -247,12 +267,13 @@ void Ctrl::UpdateRect(bool sync)
{ {
GuiLock __; GuiLock __;
UpdateRect0(sync); UpdateRect0(sync);
if(parent) RefreshFrame(); if(GetParent()) RefreshFrame();
} }
Ctrl& Ctrl::SetPos(LogPos p, bool _inframe) Ctrl& Ctrl::SetPos(LogPos p, bool _inframe)
{ {
GuiLock __; GuiLock __;
Ctrl *parent = GetParent();
if(p != pos || inframe != _inframe) { if(p != pos || inframe != _inframe) {
if(parent || !IsOpen()) if(parent || !IsOpen())
SetPos0(p, _inframe); SetPos0(p, _inframe);
@ -336,93 +357,6 @@ void Ctrl::SetFrameRectY(int y, int cy) {
SetFramePosY(PosTop(y, cy)); SetFramePosY(PosTop(y, cy));
} }
Ctrl& Ctrl::SetFrame(int i, CtrlFrame& fr) {
GuiLock __;
LLOG("SetFrame " << typeid(fr).name());
while(frame.GetCount() <= i)
frame.Add().frame = &NullFrame();
frame[i].frame->FrameRemove();
frame[i].frame = &fr;
fr.FrameAdd(*this);
SyncLayout();
RefreshFrame();
return *this;
}
Ctrl& Ctrl::AddFrame(CtrlFrame& fr) {
GuiLock __;
LLOG("AddFrame " << typeid(fr).name());
frame.Add().frame = &fr;
fr.FrameAdd(*this);
SyncLayout();
RefreshFrame();
return *this;
}
void Ctrl::ClearFrames() {
GuiLock __;
for(int i = 0; i < frame.GetCount(); i++)
frame[i].frame->FrameRemove();
frame.Clear();
frame.Add().frame = &NullFrame();
RefreshFrame();
SyncLayout();
}
void Ctrl::RemoveFrame(int i) {
GuiLock __;
int n = frame.GetCount();
Mitor<Frame> m;
if(n > 1)
for(int q = 0; q < n; q++) {
if(q != i)
m.Add().frame = frame[q].frame;
else
frame[q].frame->FrameRemove();
}
frame = pick(m);
if(frame.GetCount() == 0)
frame.Add().frame = &NullFrame();
RefreshFrame();
SyncLayout();
}
int Ctrl::FindFrame(CtrlFrame& frm)
{
GuiLock __;
for(int i = 0; i < frame.GetCount(); i++)
if(frame[i].frame == &frm)
return i;
return -1;
}
void Ctrl::RemoveFrame(CtrlFrame& frm)
{
GuiLock __;
int i = FindFrame(frm);
if(i >= 0)
RemoveFrame(i);
}
void Ctrl::InsertFrame(int i, CtrlFrame& fr)
{
GuiLock __;
ASSERT(i >= 0 && i <= frame.GetCount());
int n = frame.GetCount();
Mitor<Frame> m;
if(n >= 1)
for(int q = 0; q < n; q++) {
if(q == i) m.Add().frame = &fr;
m.Add().frame = frame[q].frame;
}
if(i == n)
m.Add().frame = &fr;
frame = pick(m);
fr.FrameAdd(*this);
SyncLayout();
RefreshFrame();
}
Ctrl& Ctrl::LeftPos(int a, int size) { Ctrl& Ctrl::LeftPos(int a, int size) {
return SetPosX(PosLeft(a, size)); return SetPosX(PosLeft(a, size));
} }

View file

@ -15,7 +15,8 @@ void Ctrl::Create(Ctrl *owner, bool popup)
ASSERT(!IsChild() && !IsOpen()); ASSERT(!IsChild() && !IsOpen());
LLOG("Ungrab1"); LLOG("Ungrab1");
top = new Top; Top *top = new Top;
SetTop(top);
top->window = gtk_window_new(popup && owner ? GTK_WINDOW_POPUP : GTK_WINDOW_TOPLEVEL); top->window = gtk_window_new(popup && owner ? GTK_WINDOW_POPUP : GTK_WINDOW_TOPLEVEL);
top->owner = owner; top->owner = owner;
@ -111,12 +112,13 @@ void Ctrl::WndDestroy()
if(HasFocusDeep() || !GetFocusCtrl()) if(HasFocusDeep() || !GetFocusCtrl())
activeCtrl = owner; activeCtrl = owner;
} }
Top *top = GetTop();
if(top->im_context) if(top->im_context)
g_object_unref(top->im_context); g_object_unref(top->im_context);
gtk_widget_destroy(top->window); gtk_widget_destroy(top->window);
isopen = false; isopen = false;
popup = false; popup = false;
delete top; DeleteTop();
top = NULL; top = NULL;
int q = FindCtrl(this); int q = FindCtrl(this);
if(q >= 0) if(q >= 0)

View file

@ -64,6 +64,20 @@ void Ctrl::InstallPanicBox()
{ {
} }
GdkWindow *Ctrl::gdk() const
{
const Top *top = GetTop();
return top ? gtk_widget_get_window(top->window) : NULL;
}
GtkWindow *Ctrl::gtk() const
{
const Top *top = GetTop();
return top ? (GtkWindow *)top->window : NULL;
}
} }
#endif #endif

View file

@ -95,8 +95,6 @@ _DBG_
static Vector<Ptr<Ctrl>> activePopup; // created with 'activate' flag - usually menu static Vector<Ptr<Ctrl>> activePopup; // created with 'activate' flag - usually menu
static Vector<Ptr<Ctrl>> visiblePopup; // any popup visible on screen static Vector<Ptr<Ctrl>> visiblePopup; // any popup visible on screen
static Vector<Win> wins; static Vector<Win> wins;
static int WndCaretTime;
static bool WndCaretVisible;
static Ptr<Ctrl> grabwindow; static Ptr<Ctrl> grabwindow;
static Ptr<Ctrl> grabpopup; static Ptr<Ctrl> grabpopup;
static Ptr<Ctrl> sel_ctrl; static Ptr<Ctrl> sel_ctrl;
@ -115,7 +113,6 @@ _DBG_
void ReleasePopupCapture(); void ReleasePopupCapture();
static void FocusSync(); static void FocusSync();
static void AnimateCaret();
static gboolean TimeHandler(GtkWidget *); static gboolean TimeHandler(GtkWidget *);
static void InvalidateMousePos(); static void InvalidateMousePos();
static void StopGrabPopup(); static void StopGrabPopup();
@ -199,6 +196,8 @@ public: // really private:
static int SCL(int x) { return scale * x; } static int SCL(int x) { return scale * x; }
static Rect SCL(int x, int y, int cx, int cy) { return RectC(SCL(x), SCL(y), SCL(cx), SCL(cy)); } static Rect SCL(int x, int y, int cx, int cy) { return RectC(SCL(x), SCL(y), SCL(cx), SCL(cy)); }
static double LSC(int x) { return (double)x / scale; } static double LSC(int x) { return (double)x / scale; }
static int GetCaretBlinkTime() { return 500; }
public: public:
static void EndSession() {} static void EndSession() {}
@ -210,8 +209,8 @@ public:
static guint32 CurrentTime; static guint32 CurrentTime;
static GEvent CurrentEvent; static GEvent CurrentEvent;
GdkWindow *gdk() const { return top ? gtk_widget_get_window(top->window) : NULL; } GdkWindow *gdk() const;
GtkWindow *gtk() const { return top ? (GtkWindow *)top->window : NULL; } GtkWindow *gtk() const;
static GdkFilterReturn RootKeyFilter(GdkXEvent *xevent, GdkEvent *event, gpointer data); static GdkFilterReturn RootKeyFilter(GdkXEvent *xevent, GdkEvent *event, gpointer data);

View file

@ -124,14 +124,16 @@ int Ctrl::DoDragAndDrop(const char *fmts, const Image& sample, dword actions,
iw.DrawImage(1, 1, sz.cx, sz.cy, sample); iw.DrawImage(1, 1, sz.cx, sz.cy, sample);
dnd_icon = iw; dnd_icon = iw;
} }
#if GTK_CHECK_VERSION(3, 10, 0) Top *top = w->GetTop();
gtk_drag_begin_with_coordinates(w->top->window, list, GdkDragAction(gdk_actions), if(top)
GetMouseLeft() ? 1 : GetMouseMiddle() ? 2 : 3, #if GTK_CHECK_VERSION(3, 10, 0)
CurrentEvent.event, -1, -1); gtk_drag_begin_with_coordinates(top->window, list, GdkDragAction(gdk_actions),
#else GetMouseLeft() ? 1 : GetMouseMiddle() ? 2 : 3,
gtk_drag_begin(w->top->window, list, GdkDragAction(gdk_actions), CurrentEvent.event, -1, -1);
GetMouseLeft() ? 1 : GetMouseMiddle() ? 2 : 3, CurrentEvent.event); #else
#endif gtk_drag_begin(top->window, list, GdkDragAction(gdk_actions),
GetMouseLeft() ? 1 : GetMouseMiddle() ? 2 : 3, CurrentEvent.event);
#endif
while(dnd_source && GetTopCtrls().GetCount()) while(dnd_source && GetTopCtrls().GetCount())
ProcessEvents(); ProcessEvents();
dnd_source_data = NULL; dnd_source_data = NULL;
@ -329,6 +331,9 @@ gboolean Ctrl::GtkDragDrop(GtkWidget *widget, GdkDragContext *context, gint x, g
void Ctrl::DndInit() void Ctrl::DndInit()
{ {
Top *top = GetTop();
if(!top)
return;
GtkWidget *w = top->window; GtkWidget *w = top->window;
gpointer id = (gpointer)(uintptr_t)top->id; gpointer id = (gpointer)(uintptr_t)top->id;
g_signal_connect(w, "drag-begin", G_CALLBACK(GtkDragBegin), id); g_signal_connect(w, "drag-begin", G_CALLBACK(GtkDragBegin), id);
@ -345,6 +350,7 @@ void Ctrl::DndInit()
void Ctrl::DndExit() void Ctrl::DndExit()
{ {
Top *top = GetTop();
if(top) if(top)
gtk_drag_dest_unset(top->window); gtk_drag_dest_unset(top->window);
} }

View file

@ -135,10 +135,13 @@ gboolean Ctrl::GtkEvent(GtkWidget *widget, GdkEvent *event, gpointer user_data)
case GDK_FOCUS_CHANGE: case GDK_FOCUS_CHANGE:
p->CancelPreedit(); p->CancelPreedit();
if(p) { if(p) {
if(((GdkEventFocus *)event)->in) Top *top = p->GetTop();
gtk_im_context_focus_in(p->top->im_context); if(top) {
else if(((GdkEventFocus *)event)->in)
gtk_im_context_focus_out(p->top->im_context); gtk_im_context_focus_in(top->im_context);
else
gtk_im_context_focus_out(top->im_context);
}
AddEvent(user_data, EVENT_FOCUS_CHANGE, value, event); AddEvent(user_data, EVENT_FOCUS_CHANGE, value, event);
} }
return false; return false;
@ -181,8 +184,11 @@ gboolean Ctrl::GtkEvent(GtkWidget *widget, GdkEvent *event, gpointer user_data)
value << (int) key->keyval << (int) key->hardware_keycode; value << (int) key->keyval << (int) key->hardware_keycode;
if(pressed) { if(pressed) {
p = GetTopCtrlFromId(user_data); p = GetTopCtrlFromId(user_data);
if(p && gtk_im_context_filter_keypress(p->top->im_context, key)) if(p) {
return true; Top *top = p->GetTop();
if(top && gtk_im_context_filter_keypress(top->im_context, key))
return true;
}
} }
break; break;
case GDK_CONFIGURE: { case GDK_CONFIGURE: {
@ -344,7 +350,9 @@ void Ctrl::IMLocation(Ctrl *w)
gr.y = LSC(e.top - q.top); gr.y = LSC(e.top - q.top);
gr.width = LSC(e.GetWidth()); gr.width = LSC(e.GetWidth());
gr.height = LSC(e.GetHeight()); gr.height = LSC(e.GetHeight());
gtk_im_context_set_cursor_location(w->top->im_context, &gr); Top *top = w->GetTop();
if(top)
gtk_im_context_set_cursor_location(top->im_context, &gr);
} }
} }

View file

@ -33,15 +33,18 @@ void TopWindow::SyncSizeHints()
m.max_width = LSC(sz.cx); m.max_width = LSC(sz.cx);
m.max_height = LSC(sz.cy); m.max_height = LSC(sz.cy);
gtk_window_set_resizable(gtk(), sizeable); gtk_window_set_resizable(gtk(), sizeable);
gtk_window_set_geometry_hints(gtk(), top->window, &m, Top *top = GetTop();
GdkWindowHints(GDK_HINT_MIN_SIZE|GDK_HINT_MAX_SIZE)); if(top) {
gtk_widget_set_size_request(top->window, m.min_width, m.min_height); gtk_window_set_geometry_hints(gtk(), top->window, &m,
GdkWindowHints(GDK_HINT_MIN_SIZE|GDK_HINT_MAX_SIZE));
gtk_widget_set_size_request(top->window, m.min_width, m.min_height);
}
} }
void TopWindow::SyncTitle() void TopWindow::SyncTitle()
{ {
GuiLock __; GuiLock __;
if(top) if(GetTop())
gtk_window_set_title(gtk(), FromUnicode(title, CHARSET_UTF8)); gtk_window_set_title(gtk(), FromUnicode(title, CHARSET_UTF8));
} }
@ -127,7 +130,9 @@ void TopWindow::Open(Ctrl *owner)
CenterRect(owner); CenterRect(owner);
IgnoreMouseUp(); IgnoreMouseUp();
Create(owner, false); Create(owner, false);
g_signal_connect(top->window, "window-state-event", G_CALLBACK(StateEvent), this); Top *top = GetTop();
if(top)
g_signal_connect(top->window, "window-state-event", G_CALLBACK(StateEvent), this);
SyncSizeHints(); SyncSizeHints();
SyncCaption(); SyncCaption();
PlaceFocus(); PlaceFocus();

View file

@ -14,9 +14,6 @@ Vector<Ctrl::Win> Ctrl::wins;
Ptr<Ctrl> Ctrl::activeCtrl; Ptr<Ctrl> Ctrl::activeCtrl;
int Ctrl::WndCaretTime;
bool Ctrl::WndCaretVisible;
bool Ctrl::invalids; bool Ctrl::invalids;
int Ctrl::FindId(int id) int Ctrl::FindId(int id)
@ -84,7 +81,7 @@ void Ctrl::SetMouseCursor(const Image& image)
else else
topctrl = GetActiveCtrl(); topctrl = GetActiveCtrl();
if(topctrl) if(topctrl)
top = topctrl->top; top = topctrl->GetTop();
if(top && id != top->cursor_id) { if(top && id != top->cursor_id) {
top->cursor_id = id; top->cursor_id = id;
int64 aux = image.GetAuxData(); int64 aux = image.GetAuxData();
@ -122,6 +119,7 @@ void Ctrl::SetMouseCursor(const Image& image)
Ctrl *Ctrl::GetOwner() Ctrl *Ctrl::GetOwner()
{ {
GuiLock __; GuiLock __;
Top *top = GetTop();
return IsOpen() ? top->owner : NULL; return IsOpen() ? top->owner : NULL;
} }
@ -150,52 +148,6 @@ void Ctrl::UnregisterSystemHotKey(int id)
#endif #endif
void Ctrl::AnimateCaret()
{
GuiLock __;
int v = !(((msecs() - WndCaretTime) / 500) & 1);
if(v != WndCaretVisible) {
WndCaretVisible = v;
RefreshCaret();
}
}
void Ctrl::PaintCaret(SystemDraw& w)
{
GuiLock __;
LLOG("PaintCaret " << Name() << ", caretCtrl: " << caretCtrl << ", WndCaretVisible: " << WndCaretVisible);
if(this == caretCtrl && WndCaretVisible)
w.DrawRect(caretx, carety, caretcx, caretcy, InvertColor);
}
void Ctrl::SetCaret(int x, int y, int cx, int cy)
{
GuiLock __;
LLOG("SetCaret " << Name());
if(this == caretCtrl)
RefreshCaret();
caretx = x;
carety = y;
caretcx = cx;
caretcy = cy;
if(this == caretCtrl) {
WndCaretTime = msecs();
RefreshCaret();
AnimateCaret();
}
}
void Ctrl::SyncCaret() {
GuiLock __;
LLOG("SyncCaret");
if(focusCtrl != caretCtrl) {
LLOG("SyncCaret DO " << Upp::Name(caretCtrl) << " -> " << Upp::Name(focusCtrl));
RefreshCaret();
caretCtrl = focusCtrl;
RefreshCaret();
}
}
Rect Ctrl::GetWndScreenRect() const Rect Ctrl::GetWndScreenRect() const
{ {
GuiLock __; GuiLock __;
@ -213,7 +165,9 @@ void Ctrl::WndShow(bool b)
{ {
GuiLock __; GuiLock __;
LLOG("WndShow " << Name() << ", " << b); LLOG("WndShow " << Name() << ", " << b);
if(IsOpen()) { Top *top = GetTop();
if(IsOpen() && top) {
if(b) if(b)
gtk_widget_show_now(top->window); gtk_widget_show_now(top->window);
else else
@ -224,6 +178,7 @@ void Ctrl::WndShow(bool b)
bool Ctrl::IsWndOpen() const { bool Ctrl::IsWndOpen() const {
GuiLock __; GuiLock __;
const Top *top = GetTop();
return top && top->window && gtk_widget_get_window(top->window); return top && top->window && gtk_widget_get_window(top->window);
} }
@ -400,12 +355,13 @@ void Ctrl::DoCancelPreedit()
{ {
if(!focusCtrl) if(!focusCtrl)
return; return;
if(focusCtrl->top) Top *top = focusCtrl->GetTop();
if(top)
focusCtrl->HidePreedit(); focusCtrl->HidePreedit();
if(focusCtrl->top) { if(top) {
gtk_im_context_reset(focusCtrl->top->im_context); gtk_im_context_reset(top->im_context);
gtk_im_context_focus_out(focusCtrl->top->im_context); gtk_im_context_focus_out(top->im_context);
gtk_im_context_focus_in(focusCtrl->top->im_context); gtk_im_context_focus_in(top->im_context);
} }
} }
@ -458,7 +414,8 @@ bool Ctrl::SweepConfigure(bool wait)
FetchEvents(wait); FetchEvents(wait);
for(int i = 0; i < Events.GetCount() && this_; i++) { for(int i = 0; i < Events.GetCount() && this_; i++) {
GEvent& e = Events[i]; GEvent& e = Events[i];
if(e.type == GDK_CONFIGURE && this_ && top->id == e.windowid) { Top *top = GetTop();
if(e.type == GDK_CONFIGURE && this_ && top && top->id == e.windowid) {
Rect rect = e.value; Rect rect = e.value;
LLOG("SweepConfigure " << rect); LLOG("SweepConfigure " << rect);
if(GetRect() != rect) if(GetRect() != rect)
@ -495,6 +452,7 @@ void Ctrl::WndEnable(bool b)
{ {
GuiLock __; GuiLock __;
if(IsOpen()) { if(IsOpen()) {
Top *top = GetTop();
gtk_widget_set_sensitive(top->window, b); gtk_widget_set_sensitive(top->window, b);
StateH(ENABLE); StateH(ENABLE);
} }

View file

@ -150,8 +150,7 @@ void WinMetaFile::Serialize(Stream& s) {
Clear(); Clear();
s % size; s % size;
if(size) { if(size) {
Buffer<byte> buffer(size); String buffer = s.GetAll(size);
s.SerializeRaw(buffer, size);
HENHMETAFILE hemf = ::SetEnhMetaFileBits(size, buffer); HENHMETAFILE hemf = ::SetEnhMetaFileBits(size, buffer);
Attach(hemf); Attach(hemf);
} }

View file

@ -273,6 +273,7 @@ void TopWindow::Open(Ctrl *owner)
GuiLock __; GuiLock __;
LLOG("TopWindow::Open(Ctrl) -> " << UPP::Name(owner)); LLOG("TopWindow::Open(Ctrl) -> " << UPP::Name(owner));
Open(owner ? owner->GetTopCtrl()->GetHWND() : NULL); Open(owner ? owner->GetTopCtrl()->GetHWND() : NULL);
Top *top = GetTop();
if(IsOpen() && top) if(IsOpen() && top)
top->owner = owner; top->owner = owner;
} }

View file

@ -48,6 +48,8 @@ private:
bool fullscreen; bool fullscreen;
byte center:2; byte center:2;
int exitcode = 0;
void PlaceFocus(); void PlaceFocus();
void ActiveFocus0(Ctrl& ctrl); void ActiveFocus0(Ctrl& ctrl);
@ -91,6 +93,8 @@ private:
GUIPLATFORM_TOPWINDOW_DECLS GUIPLATFORM_TOPWINDOW_DECLS
#endif #endif
friend class Ctrl;
public: public:
virtual void ShutdownWindow(); virtual void ShutdownWindow();
@ -125,6 +129,8 @@ public:
int Execute(); int Execute();
bool ExecuteOK() { return Execute() == IDOK; } bool ExecuteOK() { return Execute() == IDOK; }
bool ExecuteCancel() { return Execute() == IDCANCEL; } bool ExecuteCancel() { return Execute() == IDCANCEL; }
int GetExitCode() const { return exitcode; }
void Minimize(bool effect = false); void Minimize(bool effect = false);
void Maximize(bool effect = false); void Maximize(bool effect = false);

View file

@ -76,44 +76,6 @@ void GuiPlatformAfterMenuPopUp()
{ {
} }
#if WINCARET
void Ctrl::SetCaret(int x, int y, int cx, int cy)
{
GuiLock __;
caretx = x;
carety = y;
caretcx = cx;
caretcy = cy;
SyncCaret();
}
void Ctrl::SyncCaret() {
GuiLock __;
Rect cr;
cr.Clear();
if(focusCtrl && focusCtrl->IsVisible()) {
bool inframe = focusCtrl->InFrame();
cr = focusCtrl->GetScreenView();
cr = RectC(focusCtrl->caretx + cr.left, focusCtrl->carety + cr.top,
focusCtrl->caretcx, focusCtrl->caretcy) & cr;
for(Ctrl *q = focusCtrl->GetParent(); q; q = q->GetParent()) {
cr &= inframe ? q->GetScreenRect() : q->GetScreenView();
inframe = q->InFrame();
}
}
if(focusCtrl != caretCtrl || cr != caretRect) {
LLOG("Do SyncCaret focusCtrl: " << UPP::Name(focusCtrl)
<< ", caretCtrl: " << UPP::Name(caretCtrl)
<< ", cr: " << cr);
WndDestroyCaret();
if(focusCtrl && !cr.IsEmpty())
focusCtrl->GetTopCtrl()->WndCreateCaret(cr);
caretCtrl = focusCtrl;
caretRect = cr;
}
}
#endif
String Ctrl::Name() const { String Ctrl::Name() const {
GuiLock __; GuiLock __;
String s = Name0(); String s = Name0();

View file

@ -4,15 +4,6 @@ private:
bool activex:1; bool activex:1;
bool isdhctrl:1; bool isdhctrl:1;
#if WINCARET
static void WndDestroyCaret();
void WndCreateCaret(const Rect& cr);
#else
static int WndCaretTime;
static bool WndCaretVisible;
static void AnimateCaret();
#endif
static bool GetMsg(MSG& msg); static bool GetMsg(MSG& msg);
static bool DumpMessage(Ctrl *w, UINT message, WPARAM wParam, LPARAM lParam); static bool DumpMessage(Ctrl *w, UINT message, WPARAM wParam, LPARAM lParam);
@ -66,7 +57,7 @@ public:
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
virtual bool PreprocessMessage(MSG& msg); virtual bool PreprocessMessage(MSG& msg);
HWND GetHWND() const { return parent ? NULL : top ? top->hwnd : NULL; } HWND GetHWND() const { return GetParent() ? NULL : GetTop() ? GetTop()->hwnd : NULL; }
HWND GetOwnerHWND() const; HWND GetOwnerHWND() const;
static Ctrl *CtrlFromHWND(HWND hwnd); static Ctrl *CtrlFromHWND(HWND hwnd);

View file

@ -68,13 +68,14 @@ void Ctrl::DoCancelPreedit()
{ {
if(!focusCtrlWnd) if(!focusCtrlWnd)
return; return;
if(focusCtrlWnd->top) Top *top = focusCtrl->GetTop();
if(top)
focusCtrl->HidePreedit(); focusCtrl->HidePreedit();
if(focusCtrlWnd->top && focusCtrlWnd->top->hwnd) { if(top && top->hwnd) {
HIMC himc = ImmGetContext(focusCtrlWnd->top->hwnd); HIMC himc = ImmGetContext(top->hwnd);
if(himc && ImmGetOpenStatus(himc)) { if(himc && ImmGetOpenStatus(himc)) {
ImmNotifyIME(himc, NI_COMPOSITIONSTR, CPS_CANCEL, 0); ImmNotifyIME(himc, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
ImmReleaseContext(focusCtrlWnd->top->hwnd, himc); ImmReleaseContext(top->hwnd, himc);
} }
} }
} }

View file

@ -397,7 +397,7 @@ Vector<Ctrl *> Ctrl::GetTopCtrls()
Vector<Ctrl *> v; Vector<Ctrl *> v;
VectorMap< HWND, Ptr<Ctrl> >& w = Windows(); VectorMap< HWND, Ptr<Ctrl> >& w = Windows();
for(int i = 0; i < w.GetCount(); i++) for(int i = 0; i < w.GetCount(); i++)
if(w.GetKey(i) && w[i] && !w[i]->parent) if(w.GetKey(i) && w[i] && !w[i]->GetParent())
v.Add(w[i]); v.Add(w[i]);
return v; return v;
} }
@ -472,7 +472,8 @@ void Ctrl::Create(HWND parent, DWORD style, DWORD exstyle, bool savebits, int sh
Rect r = GetRect(); Rect r = GetRect();
AdjustWindowRectEx(r, style, FALSE, exstyle); AdjustWindowRectEx(r, style, FALSE, exstyle);
isopen = true; isopen = true;
top = new Top; Top *top = new Top;
SetTop(top);
ASSERT(!parent || IsWindow(parent)); ASSERT(!parent || IsWindow(parent));
style &= ~WS_VISIBLE; style &= ~WS_VISIBLE;
dropshadow = false; dropshadow = false;
@ -501,11 +502,11 @@ void ReleaseUDropTarget(UDropTarget *dt);
void Ctrl::WndFree() void Ctrl::WndFree()
{ {
GuiLock __; GuiLock __;
if(!top) return; Top *top = GetTop();
RevokeDragDrop(GetHWND()); RevokeDragDrop(GetHWND());
if(!top) return;
ReleaseUDropTarget(top->dndtgt); ReleaseUDropTarget(top->dndtgt);
isopen = false; isopen = false;
if(!top) return;
HWND owner = GetWindow(top->hwnd, GW_OWNER);// CXL 31.10.2003 z DoRemove HWND owner = GetWindow(top->hwnd, GW_OWNER);// CXL 31.10.2003 z DoRemove
bool focus = ::GetFocus() == top->hwnd; bool focus = ::GetFocus() == top->hwnd;
LLOG("Ctrl::WndDestroy owner " << (void *)owner LLOG("Ctrl::WndDestroy owner " << (void *)owner
@ -519,13 +520,13 @@ void Ctrl::WndFree()
::SetFocus(owner); ::SetFocus(owner);
} }
LLOG(LOG_END << "//Ctrl::WndFree() in " <<UPP::Name(this)); LLOG(LOG_END << "//Ctrl::WndFree() in " <<UPP::Name(this));
delete top; DeleteTop();
top = NULL;
} }
void Ctrl::WndDestroy() void Ctrl::WndDestroy()
{ {
GuiLock __; GuiLock __;
Top *top = GetTop();
if(top && top->hwnd) { if(top && top->hwnd) {
HWND hwnd = top->hwnd; HWND hwnd = top->hwnd;
WndFree(); WndFree();
@ -563,14 +564,16 @@ sWinMsg[] = {
void Ctrl::NcCreate(HWND hwnd) void Ctrl::NcCreate(HWND hwnd)
{ {
GuiLock __; GuiLock __;
if(!parent) Top *top = GetTop();
if(top)
top->hwnd = hwnd; top->hwnd = hwnd;
} }
void Ctrl::NcDestroy() void Ctrl::NcDestroy()
{ {
GuiLock __; GuiLock __;
if(!parent) Top *top = GetTop();
if(top)
WndFree(); WndFree();
} }
@ -839,80 +842,6 @@ void Ctrl::GuiSleep(int ms)
EnterGuiMutex(level); EnterGuiMutex(level);
} }
#if 0
void Ctrl::WndDestroyCaret()
{
DLOG("Ctrl::WndDestroyCaret()");
::DestroyCaret();
}
void Ctrl::WndCreateCaret(const Rect& cr)
{
GuiLock __;
DLOG("Ctrl::WndCreateCaret(" << cr << ") in " << UPP::Name(this));
HWND hwnd = GetHWND();
if(!hwnd) return;
Rect r;
::GetClientRect(hwnd, r);
Point p = r.TopLeft();
::ClientToScreen(hwnd, p);
::CreateCaret(hwnd, NULL, cr.Width(), cr.Height());
::SetCaretPos(cr.left - p.x, cr.top - p.y);
::ShowCaret(hwnd);
}
#else
int Ctrl::WndCaretTime;
bool Ctrl::WndCaretVisible;
void Ctrl::AnimateCaret()
{
GuiLock __;
bool v = !(((msecs() - WndCaretTime) / GetCaretBlinkTime()) & 1);
if(v != WndCaretVisible) {
WndCaretVisible = v;
RefreshCaret();
}
}
void Ctrl::PaintCaret(SystemDraw& w)
{
GuiLock __;
LLOG("PaintCaret " << Name() << ", caretCtrl: " << caretCtrl << ", WndCaretVisible: " << WndCaretVisible);
if(this == caretCtrl && WndCaretVisible)
w.DrawRect(caretx, carety, caretcx, caretcy, InvertColor);
}
void Ctrl::SetCaret(int x, int y, int cx, int cy)
{
GuiLock __;
LLOG("SetCaret " << Name() << " " << RectC(x, y, cx, cy));
if(this == caretCtrl)
RefreshCaret();
caretx = x;
carety = y;
caretcx = cx;
caretcy = cy;
if(this == caretCtrl) {
WndCaretTime = msecs();
RefreshCaret();
AnimateCaret();
}
}
void Ctrl::SyncCaret() {
GuiLock __;
LLOG("SyncCaret");
if(focusCtrl != caretCtrl) {
LLOG("SyncCaret DO " << Upp::Name(caretCtrl) << " -> " << Upp::Name(focusCtrl));
RefreshCaret();
caretCtrl = focusCtrl;
RefreshCaret();
}
}
#endif
Rect Ctrl::GetWndScreenRect() const Rect Ctrl::GetWndScreenRect() const
{ {
GuiLock __; GuiLock __;
@ -947,7 +876,7 @@ void Ctrl::SetAlpha(byte alpha)
{ {
GuiLock __; GuiLock __;
HWND hwnd = GetHWND(); HWND hwnd = GetHWND();
if(!IsAlphaSupported() || parent || !top || !hwnd) if(!IsAlphaSupported() || GetParent() || !top || !hwnd)
return; return;
if(alpha == 255) { if(alpha == 255) {
SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) & ~0x80000); SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) & ~0x80000);
@ -1183,14 +1112,10 @@ void Ctrl::WndUpdate(const Rect& r)
if(GetUpdateRgn(hwnd, hrgn, FALSE) != NULLREGION) { if(GetUpdateRgn(hwnd, hrgn, FALSE) != NULLREGION) {
SelectClipRgn(hdc, hrgn); SelectClipRgn(hdc, hrgn);
SystemDraw draw(hdc); SystemDraw draw(hdc);
bool hcr = focusCtrl && focusCtrl->GetTopCtrl() == top &&
caretRect.Intersects(r + top->GetRect().TopLeft());
if(hcr) ::HideCaret(hwnd);
draw.Clip(r); draw.Clip(r);
top->UpdateArea(draw, r); top->UpdateArea(draw, r);
ValidateRect(hwnd, r); ValidateRect(hwnd, r);
SelectClipRgn(hdc, NULL); SelectClipRgn(hdc, NULL);
if(hcr) ::ShowCaret(hwnd);
} }
ReleaseDC(hwnd, hdc); ReleaseDC(hwnd, hdc);
DeleteObject(hrgn); DeleteObject(hrgn);
@ -1201,14 +1126,8 @@ void Ctrl::WndScrollView(const Rect& r, int dx, int dy)
{ {
GuiLock __; GuiLock __;
LLOG("WndScrollView " << UPP::Name(this)); LLOG("WndScrollView " << UPP::Name(this));
if(caretCtrl && caretCtrl->GetTopCtrl() == this) { if(caretCtrl && caretCtrl->GetTopCtrl() == this)
#if WINCARET
WndDestroyCaret();
#else
RefreshCaret(); RefreshCaret();
#endif
caretRect.Clear();
}
#ifdef PLATFORM_WINCE #ifdef PLATFORM_WINCE
::ScrollWindowEx(GetHWND(), dx, dy, r, r, NULL, NULL, 0); ::ScrollWindowEx(GetHWND(), dx, dy, r, r, NULL, NULL, 0);
#else #else
@ -1234,6 +1153,7 @@ void Ctrl::PopUp(Ctrl *owner, bool savebits, bool activate, bool dropshadow, boo
popup = false; popup = false;
Ctrl *q = owner ? owner->GetTopCtrl() : GetActiveCtrl(); Ctrl *q = owner ? owner->GetTopCtrl() : GetActiveCtrl();
PopUpHWND(q ? q->GetHWND() : NULL, savebits, activate, dropshadow, topmost); PopUpHWND(q ? q->GetHWND() : NULL, savebits, activate, dropshadow, topmost);
Top *top = GetTop();
if(top) top->owner = owner; if(top) top->owner = owner;
} }

View file

@ -54,9 +54,9 @@
#define LAYOUT(nm, x, y) template <class L, class D> \ #define LAYOUT(nm, x, y) template <class L, class D> \
void InitLayout(UPP::Ctrl& parent, L& layout, D& uts, nm##__layid&) { \ void InitLayout(UPP::Ctrl& parent, L& layout, D& uts, nm##__layid&) { \
parent.LayoutId(#nm); parent.LayoutIdLiteral(#nm);
#define UNTYPED(var, param) uts.var.param; uts.var.LayoutId(#var); parent.Add(uts.var); #define UNTYPED(var, param) uts.var.param; uts.var.LayoutIdLiteral(#var); parent.Add(uts.var);
#define ITEM(clss, var, param) layout.var.param; layout.var.LayoutId(#var); parent.Add(layout.var); #define ITEM(clss, var, param) layout.var.param; layout.var.LayoutIdLiteral(#var); parent.Add(layout.var);
#define END_LAYOUT } #define END_LAYOUT }
#include LAYOUTFILE #include LAYOUTFILE

View file

@ -1978,33 +1978,6 @@ pointer to it.&]
its descendants.&] its descendants.&]
[s3;%- &] [s3;%- &]
[s4;%- &] [s4;%- &]
[s5;:Ctrl`:`:SetCaret`(int`,int`,int`,int`):%- [@(0.0.255) void]_[* SetCaret]([@(0.0.255) i
nt]_[*@3 x], [@(0.0.255) int]_[*@3 y], [@(0.0.255) int]_[*@3 cx], [@(0.0.255) int]_[*@3 cy])&]
[s2;b17;a17; Place caret rectangle block at given position in view
area. Caret rectangle is full flashing box and usually indicates
place where text is to entered. Ctrl can have just one caret.
Only Ctrl with focus has its caret displayed (also means that
you do not need to remove caret when Ctrl goes out of focus).&]
[s7;i1120;a17; [%-*C@3 x]-|X position.&]
[s7;i1120;a17; [%-*C@3 y]-|Y position.&]
[s7;i1120;a17; [%-*C@3 cx]-|Horizontal size.&]
[s7;i1120;a17; [%-*C@3 cy]-|Vertical size.&]
[s3;%- &]
[s4;%- &]
[s5;:Ctrl`:`:SetCaret`(const `:`:Rect`&`):%- [@(0.0.255) void]_[* SetCaret]([@(0.0.255) con
st]_[_^`:`:Rect^ Rect][@(0.0.255) `&]_[*@3 r])&]
[s2;b17;a17; Place caret rectangle block at given position in view
area. Caret rectangle is full flashing box and usually indicates
place where text is to entered. Ctrl can have just one caret.
Only Ctrl with focus has its caret displayed (also means that
you do not need to remove caret when Ctrl goes out of focus).&]
[s7;i1120;a17; [%-*C@3 r]-|Caret block rectangle.&]
[s3;%- &]
[s4;%- &]
[s5;:Ctrl`:`:KillCaret`(`):%- [@(0.0.255) void]_[* KillCaret]()&]
[s2;b17;a17; Removes caret from Ctrl.&]
[s3;%- &]
[s4;%- &]
[s5;:Upp`:`:Ctrl`:`:CancelPreedit`(`):%- [@(0.0.255) void]_[* CancelPreedit]()&] [s5;:Upp`:`:Ctrl`:`:CancelPreedit`(`):%- [@(0.0.255) void]_[* CancelPreedit]()&]
[s2; Terminates any input method composition in progress, if possible. [s2; Terminates any input method composition in progress, if possible.
Text input widgets typically call this on status change, like Text input widgets typically call this on status change, like
@ -2240,14 +2213,6 @@ l]_[*@3 ax]_`=_[@(0.0.255) true])&]
[s7;i1120;a17; [*/ Return value]-|Value of ActiveX flag.&] [s7;i1120;a17; [*/ Return value]-|Value of ActiveX flag.&]
[s3;%- &] [s3;%- &]
[s4;%- &] [s4;%- &]
[s5;:Ctrl`:`:Info`(const char`*`):%- [_^`:`:Ctrl^ Ctrl][@(0.0.255) `&]_[* Info]([@(0.0.255) c
onst]_[@(0.0.255) char]_`*[*@3 txt])&]
[s2;b17;a17; Sets Tip text of Ctrl. This text is displayed as tooltip
of Ctrl.&]
[s7;i1120;a17; [%-*C@3 txt]-|Text.&]
[s7;i1120;a17; [*/ Return value]-|`*this for method chaining.&]
[s3;%- &]
[s4;%- &]
[s5;:Ctrl`:`:HelpLine`(const char`*`):%- [_^`:`:Ctrl^ Ctrl][@(0.0.255) `&]_[* HelpLine]([@(0.0.255) c [s5;:Ctrl`:`:HelpLine`(const char`*`):%- [_^`:`:Ctrl^ Ctrl][@(0.0.255) `&]_[* HelpLine]([@(0.0.255) c
onst]_[@(0.0.255) char]_`*[*@3 txt])&] onst]_[@(0.0.255) char]_`*[*@3 txt])&]
[s2;b17;a17; Sets help topic link for Ctrl.&] [s2;b17;a17; Sets help topic link for Ctrl.&]

View file

@ -260,6 +260,11 @@ while performing loop. If false, only TopWindow`'s relative windows
[s7;%% [*/ Return value]-|Result true if Cancel otherwise false.&] [s7;%% [*/ Return value]-|Result true if Cancel otherwise false.&]
[s3;%% &] [s3;%% &]
[s4; &] [s4; &]
[s5;:Upp`:`:TopWindow`:`:GetExitCode`(`)const: [@(0.0.255) int]_[* GetExitCode]()_[@(0.0.255) c
onst]&]
[s2;%% Returns the result code of last Execute or Run methods.&]
[s3; &]
[s4; &]
[s5;:TopWindow`:`:Minimize`(bool`): [@(0.0.255) void]_[* Minimize]([@(0.0.255) bool]_[*@3 eff [s5;:TopWindow`:`:Minimize`(bool`): [@(0.0.255) void]_[* Minimize]([@(0.0.255) bool]_[*@3 eff
ect]_`=_[@(0.0.255) false])&] ect]_`=_[@(0.0.255) false])&]
[s2;%% Minimize window.&] [s2;%% Minimize window.&]

View file

@ -1149,7 +1149,7 @@ ArrayCtrl::Column& ArrayCtrl::AddRowNumColumn(const char *text, int w) {
int ArrayCtrl::FindColumnWithPos(int pos) const int ArrayCtrl::FindColumnWithPos(int pos) const
{ {
for(int i = 0; i < column.GetCount(); i++) { for(int i = 0; i < column.GetCount(); i++) {
const Mitor<int>& m = column[i].pos; const Vector<int>& m = column[i].pos;
for(int j = 0; j < m.GetCount(); j++) for(int j = 0; j < m.GetCount(); j++)
if(Pos(m[j]) == pos) return i; if(Pos(m[j]) == pos) return i;
} }
@ -1165,7 +1165,7 @@ Vector<int> ArrayCtrl::FindColumnsWithPos(int pos) const
{ {
Vector<int> r; Vector<int> r;
for(int i = 0; i < column.GetCount(); i++) { for(int i = 0; i < column.GetCount(); i++) {
const Mitor<int>& m = column[i].pos; const Vector<int>& m = column[i].pos;
for(int j = 0; j < m.GetCount(); j++) for(int j = 0; j < m.GetCount(); j++)
if(Pos(m[j]) == pos) if(Pos(m[j]) == pos)
r.Add(i); r.Add(i);

View file

@ -55,7 +55,7 @@ public:
class Column : FormatConvert { class Column : FormatConvert {
ArrayCtrl *arrayctrl; ArrayCtrl *arrayctrl;
int index; int index;
Mitor<int> pos; Vector<int> pos;
const Convert *convert; const Convert *convert;
Function<Value(const Value&)> convertby; Function<Value(const Value&)> convertby;
Ptr<Ctrl> edit; Ptr<Ctrl> edit;

View file

@ -339,32 +339,38 @@ const Button::Style *Button::St() const
return st; return st;
} }
void Button::Paint(Draw& w) void Button::PaintButton(Draw& w, const Rect& r, const Button::Style& st, int visualstate, bool focus,
const String& label, Font font, const Image& img,
bool monoimg, int accesskey, bool visibleaccesskeys, bool disabled)
{ {
const Style *st = St();
Size sz = GetSize();
bool ds = !IsShowEnabled();
DrawLabel dl; DrawLabel dl;
dl.text = label; dl.text = label;
dl.font = Nvl(font, st->font); dl.font = Nvl(font, st.font);
dl.limg = img; dl.limg = img;
dl.disabled = ds; dl.disabled = disabled;
dl.lspc = !label.IsEmpty() && !img.IsEmpty() ? 4 : 0; dl.lspc = !label.IsEmpty() && !img.IsEmpty() ? 4 : 0;
if(*label == '\1') if(*label == '\1')
dl.align = ALIGN_LEFT; dl.align = ALIGN_LEFT;
if(VisibleAccessKeys()) if(visibleaccesskeys)
dl.accesskey = accesskey; dl.accesskey = accesskey;
if(monoimg) if(monoimg)
dl.lcolor = SColorText; dl.lcolor = SColorText;
int i = GetVisualState(); ChPaint(w, r, st.look[visualstate]);
ChPaint(w, sz, st->look[i]); dl.ink = st.textcolor[visualstate];
dl.ink = st->textcolor[i];
if(monoimg) if(monoimg)
dl.lcolor = st->monocolor[i]; dl.lcolor = st.monocolor[visualstate];
dl.Paint(w, 3 + IsPush() * st->pressoffset.x, 3 + IsPush() * st->pressoffset.y, bool push = visualstate == CTRL_PRESSED;
sz.cx - 6, sz.cy - 6); dl.Paint(w, r.left + 3 + push * st.pressoffset.x, r.top + 3 + push * st.pressoffset.y,
if(HasFocus()) r.GetWidth() - 6, r.GetHeight() - 6);
DrawFocus(w, Rect(sz).Deflated(st->focusmargin)); if(focus)
DrawFocus(w, r.Deflated(st.focusmargin));
}
void Button::Paint(Draw& w)
{
PaintButton(w, GetSize(), *St(), GetVisualState(), HasFocus(),
label, font, img,
monoimg, accesskey, VisibleAccessKeys(), !IsShowEnabled());
} }
void Button::MouseEnter(Point, dword) void Button::MouseEnter(Point, dword)
@ -498,6 +504,8 @@ void SpinButtons::FrameLayout(Rect& r)
void SpinButtons::FrameAddSize(Size& sz) void SpinButtons::FrameAddSize(Size& sz)
{ {
if(!visible)
return;
sz.cx += (1 + style->onsides) * (min(sz.cx / 2, style->width) - style->over); sz.cx += (1 + style->onsides) * (min(sz.cx / 2, style->width) - style->over);
} }

View file

@ -18,7 +18,9 @@ file
PushCtrl.h, PushCtrl.h,
Button.cpp, Button.cpp,
Switch.cpp, Switch.cpp,
VirtualButtons.cpp,
EditCtrl.h, EditCtrl.h,
EditCtrl.hpp,
EditField.cpp, EditField.cpp,
TextEdit.h, TextEdit.h,
Text.cpp, Text.cpp,
@ -34,6 +36,7 @@ file
MultiButton.cpp, MultiButton.cpp,
DropChoice.h, DropChoice.h,
PopupTable.cpp, PopupTable.cpp,
PopUpList.cpp,
DropList.cpp, DropList.cpp,
DropChoice.cpp, DropChoice.cpp,
StaticCtrl.h, StaticCtrl.h,

View file

@ -1,55 +1,55 @@
#include "CtrlLib.h" #include "CtrlLib.h"
namespace Upp { namespace Upp {
Point DisplayPopup::Op(Point p) Point DisplayPopup::PopUp::Op(Point p)
{ {
return p + GetScreenView().TopLeft() - ctrl->GetScreenView().TopLeft(); 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); 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); 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); 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); 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); 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); if(ctrl) ctrl->MouseWheel(Op(p), zdelta, flags);
} }
void DisplayPopup::MouseLeave() void DisplayPopup::PopUp::MouseLeave()
{ {
Cancel(); Cancel();
} }
void DisplayPopup::MouseMove(Point p, dword flags) void DisplayPopup::PopUp::MouseMove(Point p, dword flags)
{ {
p += GetScreenView().TopLeft(); p += GetScreenView().TopLeft();
if(!slim.Contains(p)) if(!slim.Contains(p))
MouseLeave(); MouseLeave();
} }
void DisplayPopup::Paint(Draw& w) void DisplayPopup::PopUp::Paint(Draw& w)
{ {
Rect r = GetSize(); Rect r = GetSize();
w.DrawRect(r, SColorPaper); w.DrawRect(r, SColorPaper);
@ -62,13 +62,13 @@ void DisplayPopup::Paint(Draw& w)
} }
} }
Vector<DisplayPopup *>& DisplayPopup::all() Vector<DisplayPopup::PopUp *>& DisplayPopup::PopUp::all()
{ {
static Vector<DisplayPopup *> all; static Vector<DisplayPopup::PopUp *> all;
return all; return all;
} }
DisplayPopup::DisplayPopup() DisplayPopup::PopUp::PopUp()
{ {
SetFrame(BlackFrame()); SetFrame(BlackFrame());
display = NULL; display = NULL;
@ -83,14 +83,14 @@ DisplayPopup::DisplayPopup()
all().Add(this); all().Add(this);
} }
DisplayPopup::~DisplayPopup() DisplayPopup::PopUp::~PopUp()
{ {
int q = FindIndex(all(), this); int q = FindIndex(all(), this);
if(q >= 0) if(q >= 0)
all().Remove(q); all().Remove(q);
} }
void DisplayPopup::Sync() void DisplayPopup::PopUp::Sync()
{ {
if(!IsMainThread()) { if(!IsMainThread()) {
PostCallback(PTEBACK(Sync)); PostCallback(PTEBACK(Sync));
@ -144,20 +144,20 @@ void DisplayPopup::Sync()
} }
} }
if(IsOpen() && !GetDragAndDropSource()) if(IsOpen() && !GetDragAndDropSource())
Close(); WhenClose();
} }
void DisplayPopup::SyncAll() void DisplayPopup::PopUp::SyncAll()
{ {
int n = 0; int n = 0;
for(DisplayPopup *p : all()) for(DisplayPopup::PopUp *p : all())
if(p->ctrl && p->ctrl->IsOpen()) { if(p->ctrl && p->ctrl->IsOpen()) {
p->Sync(); p->Sync();
n++; n++;
} }
} }
bool DisplayPopup::StateHook(Ctrl *, int reason) bool DisplayPopup::PopUp::StateHook(Ctrl *, int reason)
{ {
if(reason == FOCUS) if(reason == FOCUS)
SyncAll(); 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(); SyncAll();
return false; return false;
} }
void DisplayPopup::Cancel() void DisplayPopup::PopUp::Cancel()
{ {
if(GetDragAndDropSource()) if(GetDragAndDropSource())
return; return;
@ -179,17 +179,17 @@ void DisplayPopup::Cancel()
Sync(); Sync();
} }
bool DisplayPopup::IsOpen() bool DisplayPopup::PopUp::IsOpen()
{ {
return Ctrl::IsOpen(); return Ctrl::IsOpen();
} }
bool DisplayPopup::HasMouse() bool DisplayPopup::PopUp::HasMouse()
{ {
return Ctrl::HasMouse() || ctrl && ctrl->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, const Value& _value, const Display *_display,
Color _ink, Color _paper, dword _style, int _margin) 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();
}
} }

View file

@ -1,29 +1,52 @@
class DisplayPopup : public Ctrl, public Link<DisplayPopup> { class DisplayPopup {
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: private:
Ptr<Ctrl> ctrl; struct PopUp : public Ctrl, public Link<DisplayPopup::PopUp> {
Rect item; virtual void Paint(Draw& w);
Rect slim; virtual void LeftDown(Point p, dword);
virtual void LeftDrag(Point p, dword);
Value value; virtual void LeftDouble(Point p, dword);
Color paper, ink; virtual void RightDown(Point p, dword);
dword style; virtual void LeftUp(Point p, dword);
const Display *display; virtual void MouseWheel(Point p, int zdelta, dword keyflags);
int margin; virtual void MouseLeave();
virtual void MouseMove(Point p, dword);
Ptr<Ctrl> 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<DisplayPopup::PopUp *>& 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> popup;
bool usedisplaystdsize = false; bool usedisplaystdsize = false;
Point Op(Point p);
void Sync();
static Vector<DisplayPopup *>& all(); static Vector<DisplayPopup *>& all();
static bool StateHook(Ctrl *, int reason); static bool StateHook(Ctrl *, int reason);
static bool MouseHook(Ctrl *, bool, int, Point, int, dword); static bool MouseHook(Ctrl *, bool, int, Point, int, dword);
@ -37,8 +60,7 @@ public:
void Cancel(); void Cancel();
bool IsOpen(); bool IsOpen();
bool HasMouse(); bool HasMouse();
void UseDisplayStdSize() { usedisplaystdsize = true; } void UseDisplayStdSize();
DisplayPopup();
~DisplayPopup(); ~DisplayPopup();
}; };

View file

@ -222,6 +222,11 @@ int DocEdit::GetCursorPos(Point p) {
return GetLength32(); return GetLength32();
} }
Rect DocEdit::GetCaret() const
{
return caret;
}
void DocEdit::PlaceCaret(bool scroll) { void DocEdit::PlaceCaret(bool scroll) {
Point cr = GetCaret((int)cursor); Point cr = GetCaret((int)cursor);
int fy = font.Info().GetLineHeight(); int fy = font.Info().GetLineHeight();
@ -231,7 +236,7 @@ void DocEdit::PlaceCaret(bool scroll) {
else else
sb.ScrollInto(cr.y, fy + 2); sb.ScrollInto(cr.y, fy + 2);
} }
SetCaret(cr.x + 1, cr.y - sb, 1, fy); caret = RectC(cr.x + 1, cr.y - sb, 1, fy);
WhenSel(); WhenSel();
} }

View file

@ -6,7 +6,6 @@ DropChoice::DropChoice() {
always_drop = hide_drop = false; always_drop = hide_drop = false;
AddButton().Main() <<= THISBACK(Drop); AddButton().Main() <<= THISBACK(Drop);
NoDisplay(); NoDisplay();
list.Normal();
list.WhenSelect = [=] { Select(); }; list.WhenSelect = [=] { Select(); };
dropfocus = true; dropfocus = true;
EnableDrop(false); EnableDrop(false);
@ -42,7 +41,11 @@ void DropChoice::Drop() {
WhenDrop(); WhenDrop();
if(dropfocus) if(dropfocus)
owner->SetWantFocus(); owner->SetWantFocus();
if(!list.FindSetCursor(owner->GetData()) && list.GetCount() > 0) int i = list.Find(owner->GetData());
if(i >= 0)
list.SetCursor(i);
else
if(list.GetCount() > 0)
list.SetCursor(0); list.SetCursor(0);
list.PopUp(owner,dropwidth); list.PopUp(owner,dropwidth);
} }
@ -56,7 +59,7 @@ Value DropChoice::Get() const {
if(!owner || owner->IsReadOnly() && !rodrop) return Value(); if(!owner || owner->IsReadOnly() && !rodrop) return Value();
int c = list.GetCursor(); int c = list.GetCursor();
if(c < 0) return Value(); if(c < 0) return Value();
return list.Get(c, 0); return list.Get(c);
} }
int DropChoice::GetIndex() const int DropChoice::GetIndex() const
@ -172,7 +175,7 @@ void DropChoice::SerializeList(Stream& s) {
} }
else else
for(int i = 0; i < n; i++) { for(int i = 0; i < n; i++) {
v = list.Get(i, 0); v = list.Get(i);
s % v; s % v;
} }
EnableDrop(list.GetCount() || always_drop); EnableDrop(list.GetCount() || always_drop);
@ -181,15 +184,15 @@ void DropChoice::SerializeList(Stream& s) {
void DropChoice::AddHistory(const Value& v, int max) { void DropChoice::AddHistory(const Value& v, int max) {
if(IsNull(v)) return; if(IsNull(v)) return;
for(int i = 0; i < list.GetCount(); i++) for(int i = 0; i < list.GetCount(); i++)
if(list.Get(i, 0) == v) { if(list.Get(i) == v) {
list.Remove(i); list.Remove(i);
break; break;
} }
list.Insert(0, Vector<Value>() << v); list.Insert(0, v);
if(list.GetCount() > max) if(list.GetCount() > max)
list.SetCount(max); list.SetCount(max);
EnableDrop(list.GetCount() || always_drop); EnableDrop(list.GetCount() || always_drop);
list.KillCursor(); list.SetCursor(-1);
} }
DropChoice& DropChoice::AlwaysDrop(bool e) DropChoice& DropChoice::AlwaysDrop(bool e)

View file

@ -1,6 +1,6 @@
void DropEdge_Write(Value); void DropEdge_Write(Value);
class PopUpTable : public ArrayCtrl { class PopUpTable : public ArrayCtrl { // deprecated, replaced with PopUpList
public: public:
virtual void LeftUp(Point p, dword keyflags); virtual void LeftUp(Point p, dword keyflags);
virtual bool Key(dword key, int); virtual bool Key(dword key, int);
@ -39,27 +39,115 @@ public:
virtual ~PopUpTable(); virtual ~PopUpTable();
}; };
class PopUpList {
protected:
void PopupDeactivate();
void PopupCancelMode();
struct PopupArrayCtrl : ArrayCtrl {
PopUpList *list;
virtual void LeftUp(Point p, dword keyflags);
virtual bool Key(dword key, int);
};
struct Popup : Ctrl {
PopUpList *list;
PopupArrayCtrl ac;
bool closing = false;
virtual void Deactivate() { if(!closing) list->PopupDeactivate(); }
virtual void CancelMode() { if(!closing) list->PopupCancelMode(); }
Popup(PopUpList *list);
};
Vector<Value> items;
Vector<word> lineinfo;
Vector<const Display *> linedisplay;
One<Popup> popup;
const ScrollBar::Style *sb_style = nullptr;
const Display *display;
const Convert *convert;
int linecy;
int cursor = -1;
int16 droplines;
int16 inpopup;
void DoSelect();
void DoCancel();
void DoClose();
void Reset();
friend class Popup;
public:
Event<> WhenCancel;
Event<> WhenSelect;
void PopUp(Ctrl *owner, int x, int top, int bottom, int width);
void PopUp(Ctrl *owner, int width);
void PopUp(Ctrl *owner);
void Clear();
void SetCount(int n);
void Add(const Value& v);
void AddSeparator();
void Remove(int i);
void Insert(int i, const Value& v);
void SetCursor(int i);
int GetCursor() const;
int GetCount() const { return items.GetCount(); }
void Set(int i, const Value& v);
Value Get(int i) const { return items[i]; }
int Find(const Value& v) const;
void SetScrollBarStyle(const ScrollBar::Style& s);
void SetLineCy(int cy);
int GetLineCy() const { return linecy; }
void SetLineCy(int ii, int cy);
int GetLineCy(int ii) const;
bool Key(int c);
bool IsLineEnabled(int ii) const;
void SetDisplay(const Display& d);
const Display& GetDisplay() const { return *display; }
void SetDisplay(int i, const Display& d);
const Display& GetDisplay(int i) const;
void SetConvert(const Convert& c);
PopUpList& SetDropLines(int _droplines) { droplines = _droplines; return *this; }
PopUpList();
virtual ~PopUpList();
};
class DropList : public MultiButton, public Convert { class DropList : public MultiButton, public Convert {
public: public:
virtual void MouseWheel(Point p, int zdelta, dword keyflags); virtual void MouseWheel(Point p, int zdelta, dword keyflags);
virtual bool Key(dword key, int); virtual bool Key(dword key, int);
virtual void SetData(const Value& data); virtual void SetData(const Value& data);
virtual Value GetData() const; virtual Value GetData() const;
virtual void DropPush();
virtual Value Format(const Value& q) const; virtual Value Format(const Value& q) const;
private: private:
PopUpTable list; PopUpList list;
Index<Value> key; Index<Value> key;
Value value; Value value;
int dropwidth;
const Convert *valueconvert; const Convert *valueconvert;
const Display *valuedisplay; const Display *valuedisplay;
bool displayall; int16 dropwidth;
bool dropfocus; bool displayall:1;
bool notnull; bool dropfocus:1;
bool alwaysdrop; bool notnull:1;
bool usewheel; bool alwaysdrop:1;
bool usewheel:1;
void Select(); void Select();
void Cancel(); void Cancel();
@ -105,7 +193,7 @@ public:
void Trim(int n); void Trim(int n);
const Value& GetKey(int i) const { return key[i]; } const Value& GetKey(int i) const { return key[i]; }
Value GetValue(int i) const { return list.Get(i, 0); } Value GetValue(int i) const { return list.Get(i); }
Value GetValue() const; Value GetValue() const;
void SetValue(int i, const Value& v); void SetValue(int i, const Value& v);
void SetValue(const Value& v); void SetValue(const Value& v);
@ -113,10 +201,10 @@ public:
void Adjust(); void Adjust();
void Adjust(const Value& k); void Adjust(const Value& k);
/*
const PopUpTable& GetList() const { return list; } const PopUpTable& GetList() const { return list; }
PopUpTable& ListObject() { return list; } PopUpTable& ListObject() { return list; }
*/
DropList& SetDropLines(int d) { list.SetDropLines(d); return *this; } DropList& SetDropLines(int d) { list.SetDropLines(d); return *this; }
DropList& SetValueConvert(const Convert& cv); DropList& SetValueConvert(const Convert& cv);
DropList& SetConvert(const Convert& cv); DropList& SetConvert(const Convert& cv);
@ -160,7 +248,7 @@ public:
virtual void Serialize(Stream& s); //empty virtual void Serialize(Stream& s); //empty
protected: protected:
PopUpTable list; PopUpList list;
Ctrl *owner; Ctrl *owner;
bool appending : 1; bool appending : 1;
bool dropfocus : 1; bool dropfocus : 1;
@ -189,12 +277,12 @@ public:
void Add(const Value& data); void Add(const Value& data);
int Find(const Value& data) const { return list.Find(data); } int Find(const Value& data) const { return list.Find(data); }
void FindAdd(const Value& data); void FindAdd(const Value& data);
void Set(int i, const Value& data) { list.Set(i, 0, data); } void Set(int i, const Value& data) { list.Set(i, data); }
void Remove(int i); void Remove(int i);
void SerializeList(Stream& s); void SerializeList(Stream& s);
int GetCount() const { return list.GetCount(); } int GetCount() const { return list.GetCount(); }
Value Get(int i) const { return list.Get(i, 0); } Value Get(int i) const { return list.Get(i); }
void AddHistory(const Value& data, int max = 12); void AddHistory(const Value& data, int max = 12);
@ -204,11 +292,11 @@ public:
Value Get() const; Value Get() const;
int GetIndex() const; int GetIndex() const;
DropChoice& SetDisplay(int i, const Display& d) { list.SetDisplay(i, 0, d); return *this; } DropChoice& SetDisplay(int i, const Display& d) { list.SetDisplay(i, d); return *this; }
DropChoice& SetDisplay(const Display& d) { list.ColumnAt(0).SetDisplay(d); return *this; } DropChoice& SetDisplay(const Display& d) { list.SetDisplay(d); return *this; }
DropChoice& SetLineCy(int lcy) { list.SetLineCy(lcy); return *this; } DropChoice& SetLineCy(int lcy) { list.SetLineCy(lcy); return *this; }
DropChoice& SetDisplay(const Display& d, int lcy) { SetDisplay(d); SetLineCy(lcy); return *this; } DropChoice& SetDisplay(const Display& d, int lcy) { SetDisplay(d); SetLineCy(lcy); return *this; }
DropChoice& SetConvert(const Convert& d) { list.ColumnAt(0).SetConvert(d); return *this; } DropChoice& SetConvert(const Convert& d) { list.SetConvert(d); return *this; }
DropChoice& SetDropLines(int n) { list.SetDropLines(n); return *this; } DropChoice& SetDropLines(int n) { list.SetDropLines(n); return *this; }
DropChoice& Appending() { appending = true; return *this; } DropChoice& Appending() { appending = true; return *this; }
DropChoice& AlwaysDrop(bool e = true); DropChoice& AlwaysDrop(bool e = true);

View file

@ -12,9 +12,9 @@ void DropList::Sync() {
if(displayall) if(displayall)
v = value; v = value;
int i = key.Find(value); int i = key.Find(value);
const Display& d = valuedisplay ? *valuedisplay : i >= 0 ? list.GetDisplay(i, 0) const Display& d = valuedisplay ? *valuedisplay : i >= 0 ? list.GetDisplay(i)
: list.GetDisplay(0); : list.GetDisplay();
if(i >= 0) v = list.Get(i, 0); if(i >= 0) v = list.Get(i);
MultiButton::SetDisplay(d); MultiButton::SetDisplay(d);
MultiButton::SetValueCy(list.GetLineCy()); MultiButton::SetValueCy(list.GetLineCy());
v = valueconvert->Format(v); v = valueconvert->Format(v);
@ -55,7 +55,7 @@ bool DropList::Key(dword k, int) {
break; break;
default: default:
if(k >= 32 && k < K_CHAR_LIM) { if(k >= 32 && k < K_CHAR_LIM) {
bool b = list.Key(k, 1); bool b = list.Key(k);
if(list.GetCursor() >= 0 && list.GetCursor() < key.GetCount() && key[list.GetCursor()] != value) if(list.GetCursor() >= 0 && list.GetCursor() < key.GetCount() && key[list.GetCursor()] != value)
Select(); Select();
return b; return b;
@ -80,6 +80,11 @@ void DropList::Drop() {
list.PopUp(this, dropwidth); list.PopUp(this, dropwidth);
} }
void DropList::DropPush()
{
Drop();
}
void DropList::Select() { void DropList::Select() {
int c = list.GetCursor(); int c = list.GetCursor();
if(c >= 0) if(c >= 0)
@ -107,7 +112,6 @@ void DropList::ClearList() {
key.Clear(); key.Clear();
list.Clear(); list.Clear();
Sync(); Sync();
list.Refresh();
EnableDrop(false); EnableDrop(false);
} }
@ -124,7 +128,6 @@ DropList& DropList::Add(const Value& _key, const Value& text, bool enable)
list.Add(text); list.Add(text);
if(!enable) if(!enable)
list.SetLineCy(list.GetCount() - 1, 0); list.SetLineCy(list.GetCount() - 1, 0);
list.Refresh();
EnableDrop(); EnableDrop();
Sync(); Sync();
return *this; return *this;
@ -143,7 +146,6 @@ DropList& DropList::AddSeparator()
{ {
key.Add(RawToValue(DummyValue__())); key.Add(RawToValue(DummyValue__()));
list.AddSeparator(); list.AddSeparator();
list.Refresh();
EnableDrop(); EnableDrop();
Sync(); Sync();
return *this; return *this;
@ -155,7 +157,6 @@ void DropList::Trim(int n) {
key.Trim(n); key.Trim(n);
list.SetCount(n); list.SetCount(n);
Sync(); Sync();
list.Refresh();
EnableDrop(n); EnableDrop(n);
} }
@ -177,7 +178,7 @@ Value DropList::GetValue() const {
} }
void DropList::SetValue(int i, const Value& v) { void DropList::SetValue(int i, const Value& v) {
list.Set(i, 0, v); list.Set(i, v);
EnableDrop(); EnableDrop();
Sync(); Sync();
} }
@ -198,20 +199,20 @@ DropList& DropList::SetValueConvert(const Convert& cv)
DropList& DropList::SetConvert(const Convert& cv) DropList& DropList::SetConvert(const Convert& cv)
{ {
list.ColumnAt(0).SetConvert(cv); list.SetConvert(cv);
return SetValueConvert(cv); return SetValueConvert(cv);
} }
DropList& DropList::SetDisplay(int i, const Display& d) DropList& DropList::SetDisplay(int i, const Display& d)
{ {
list.SetDisplay(i, 0, d); list.SetDisplay(i, d);
Sync(); Sync();
return *this; return *this;
} }
DropList& DropList::SetDisplay(const Display& d) DropList& DropList::SetDisplay(const Display& d)
{ {
list.ColumnAt(0).SetDisplay(d); list.SetDisplay(d);
Sync(); Sync();
return *this; return *this;
} }
@ -270,10 +271,9 @@ DropList::DropList()
dropfocus = false; dropfocus = false;
notnull = false; notnull = false;
alwaysdrop = false; alwaysdrop = false;
AddButton().Main().WhenPush = THISBACK(Drop); SetupDropPush();
NoInitFocus(); NoInitFocus();
EnableDrop(false); EnableDrop(false);
list.Normal();
list.WhenSelect = THISBACK(Select); list.WhenSelect = THISBACK(Select);
list.WhenCancel = THISBACK(Cancel); list.WhenCancel = THISBACK(Cancel);
dropwidth = 0; dropwidth = 0;

View file

@ -63,6 +63,7 @@ public:
virtual void CancelMode(); virtual void CancelMode();
virtual String GetSelectionData(const String& fmt) const; virtual String GetSelectionData(const String& fmt) const;
virtual void State(int); virtual void State(int);
virtual Rect GetCaret() const;
public: public:
struct Style : ChStyle<Style> { struct Style : ChStyle<Style> {
@ -88,35 +89,43 @@ public:
}; };
protected: protected:
const Style *style; enum {
ATTR_TEXTCOLOR = Ctrl::ATTR_LAST,
ATTR_INACTIVE_CONVERT,
ATTR_CHARFILTER,
ATTR_NULLICON,
ATTR_NULLTEXT,
ATTR_NULLINK,
ATTR_NULLFONT,
ATTR_LAST,
};
ActiveEdgeFrame edge; ActiveEdgeFrame edge;
WString text; WString text;
int sc;
int cursor, anchor;
WString undotext; WString undotext;
int undocursor, undoanchor; Rect16 dropcaret;
const Style *style;
CharFilter filter; CharFilter filter;
const Convert *convert; const Convert *convert;
const Convert *inactive_convert;
Font font;
Color textcolor;
WString nulltext; Font font;
Color nullink;
Font nullfont; int sc;
Image nullicon; int cursor, anchor;
int undocursor, undoanchor;
int maxlen; int maxlen;
int autosize; int autosize;
byte charset;
int fsell, fselh; // used to hold selection after LostFocus for X11 middle mouse copy int fsell, fselh; // used to hold selection after LostFocus for X11 middle mouse copy
int dropcursor; int dropcursor;
Rect dropcaret;
bool selclick; byte charset;
bool selclick:1;
bool password:1; bool password:1;
bool autoformat:1; bool autoformat:1;
@ -140,7 +149,6 @@ protected:
int GetStringCx(const wchar *text, int n); int GetStringCx(const wchar *text, int n);
int GetCaret(int cursor) const; int GetCaret(int cursor) const;
int GetCursor(int posx); int GetCursor(int posx);
void SyncCaret();
void Finish(bool refresh = true); void Finish(bool refresh = true);
void SaveUndo(); void SaveUndo();
void DoAutoFormat(); void DoAutoFormat();
@ -154,6 +162,13 @@ protected:
virtual void HighlightText(Vector<Highlight>& hl); virtual void HighlightText(Vector<Highlight>& hl);
virtual int64 GetTotal() const { return text.GetLength(); } virtual int64 GetTotal() const { return text.GetLength(); }
virtual int GetCharAt(int64 pos) const { return text[(int)pos]; } virtual int GetCharAt(int64 pos) const { return text[(int)pos]; }
// Spin support
virtual void PaintSpace(Draw& w);
virtual int GetSpaceLeft() const;
virtual int GetSpaceRight() const;
virtual void EditCapture();
virtual bool HasEditCapture();
public: public:
Event<Bar&> WhenBar; Event<Bar&> WhenBar;
@ -216,7 +231,7 @@ public:
bool IsPassword() const { return password; } bool IsPassword() const { return password; }
EditField& SetFilter(int (*f)(int)) { filter = f; return *this; } EditField& SetFilter(int (*f)(int)) { filter = f; return *this; }
EditField& SetConvert(const Convert& c) { convert = &c; Refresh(); return *this; } EditField& SetConvert(const Convert& c) { convert = &c; Refresh(); return *this; }
EditField& SetInactiveConvert(const Convert& c) { inactive_convert = &c; Refresh(); return *this; } EditField& SetInactiveConvert(const Convert& c) { SetVoidPtrAttr(ATTR_INACTIVE_CONVERT, &c); Refresh(); return *this; }
EditField& AutoFormat(bool b = true) { autoformat = b; return *this; } EditField& AutoFormat(bool b = true) { autoformat = b; return *this; }
EditField& NoAutoFormat() { return AutoFormat(false); } EditField& NoAutoFormat() { return AutoFormat(false); }
bool IsAutoFormat() const { return autoformat; } bool IsAutoFormat() const { return autoformat; }
@ -227,9 +242,9 @@ public:
bool IsClickSelect() const { return clickselect; } bool IsClickSelect() const { return clickselect; }
EditField& InitCaps(bool b = true) { initcaps = b; return *this; } EditField& InitCaps(bool b = true) { initcaps = b; return *this; }
bool IsInitCaps() const { return initcaps; } bool IsInitCaps() const { return initcaps; }
EditField& NullText(const Image& icon, const char *text = t_("(default)"), Color ink = SColorDisabled); EditField& NullText(const Image& icon, const char *text = t_("(default)"), Color ink = Null);
EditField& NullText(const Image& icon, const char *text, Font fnt, Color ink); EditField& NullText(const Image& icon, const char *text, Font fnt, Color ink);
EditField& NullText(const char *text = t_("(default)"), Color ink = SColorDisabled); EditField& NullText(const char *text = t_("(default)"), Color ink = Null);
EditField& NullText(const char *text, Font fnt, Color ink); EditField& NullText(const char *text, Font fnt, Color ink);
EditField& MaxChars(int mc) { maxlen = mc; return *this; } EditField& MaxChars(int mc) { maxlen = mc; return *this; }
int GetMaxChars() const { return maxlen; } int GetMaxChars() const { return maxlen; }
@ -369,10 +384,24 @@ void WithSpin_Add(double& value, double inc, double min, bool roundfrommin) {
} }
template <class DataType, class Base, class IncType = DataType> template <class DataType, class Base, class IncType = DataType>
class WithSpin : public Base { class WithSpin : public Base, private VirtualButtons {
public: public:
virtual void MouseWheel(Point p, int zdelta, dword keyflags); virtual void CancelMode();
virtual bool Key(dword key, int repcnt); 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);
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;
virtual const Button::Style& ButtonStyle(int i) const;
virtual void ButtonPush(int i);
virtual void ButtonRepeat(int i);
protected: protected:
void Inc(); void Inc();
@ -380,9 +409,10 @@ protected:
void Init(); void Init();
private: private:
SpinButtons sb; const SpinButtons::Style *style;
IncType inc; IncType inc;
bool roundfrommin; bool roundfrommin = false;
bool visible = true;
bool mousewheel = true; bool mousewheel = true;
bool keys = true; bool keys = true;
@ -391,12 +421,14 @@ public:
WithSpin& SetInc(IncType _inc = 1) { inc = _inc; return *this; } WithSpin& SetInc(IncType _inc = 1) { inc = _inc; return *this; }
DataType GetInc() const { return inc; } DataType GetInc() const { return inc; }
WithSpin& OnSides(bool b = true) { sb.OnSides(b); return *this; }
bool IsOnSides() const { return sb.IsOnSides(); }
WithSpin& ShowSpin(bool s = true) { sb.Show(s); return *this; } WithSpin& SetStyle(SpinButtons::Style& s) { style = &s; return *this; }
bool IsSpinVisible() const { return sb.IsVisible(); }
WithSpin& OnSides(bool b = true);
bool IsOnSides() const { return style->onsides; }
WithSpin& ShowSpin(bool b = true) { visible = b; Base::RefreshLayout(); return *this; }
bool IsSpinVisible() const { return visible; }
WithSpin& RoundFromMin(bool b = true) { roundfrommin = b; return *this; } WithSpin& RoundFromMin(bool b = true) { roundfrommin = b; return *this; }
@ -406,122 +438,13 @@ public:
WithSpin& KeySpin(bool b = true) { keys = b; return *this; } WithSpin& KeySpin(bool b = true) { keys = b; return *this; }
WithSpin& NoKeySpin() { return KeySpin(false); } WithSpin& NoKeySpin() { return KeySpin(false); }
SpinButtons& SpinButtonsObject() { return sb; }
const SpinButtons& SpinButtonsObject() const { return sb; }
WithSpin(); WithSpin();
WithSpin(IncType inc); // deprecated WithSpin(IncType inc); // deprecated
WithSpin(DataType min, DataType max, IncType inc); // deprecated WithSpin(DataType min, DataType max, IncType inc); // deprecated
virtual ~WithSpin() {} virtual ~WithSpin() {}
}; };
template <class DataType, class Base, class IncType> #include "EditCtrl.hpp"
WithSpin<DataType, Base, IncType>::WithSpin()
: inc(WithSpin_DefaultIncValue<IncType>())
{
Init();
}
template <class DataType, class Base, class IncType>
WithSpin<DataType, Base, IncType>::WithSpin(IncType inc)
: inc(inc)
{
Init();
}
template <class DataType, class Base, class IncType>
WithSpin<DataType, Base, IncType>::WithSpin(DataType min, DataType max, IncType inc)
: inc(WithSpin_DefaultIncValue<IncType>())
{
Base::MinMax(min, max);
Init();
}
template <class DataType, class Base, class IncType>
void WithSpin<DataType, Base, IncType>::Init()
{
Ctrl::AddFrame(sb);
sb.inc.WhenRepeat = sb.inc.WhenAction = THISBACK(Inc);
sb.dec.WhenRepeat = sb.dec.WhenAction = THISBACK(Dec);
roundfrommin = false;
}
template <class DataType, class Base, class IncType>
void WithSpin<DataType, Base, IncType>::Inc()
{
if(Ctrl::IsReadOnly()) {
BeepExclamation();
return;
}
DataType d = Base::GetData();
if(!IsNull(d)) {
WithSpin_Add(d, inc, Base::GetMin(), roundfrommin);
if(IsNull(Base::GetMax()) || d <= Base::GetMax()) {
Base::SetData(d);
Ctrl::Action();
}
}
else {
DataType min = Base::GetMin();
if(IsNull(min) || min <= Base::GetDefaultMin())
Base::SetData(WithSpin_DefaultStartValue<DataType>());
else
Base::SetData(min);
}
Ctrl::SetFocus();
}
template <class DataType, class Base, class IncType>
void WithSpin<DataType, Base, IncType>::Dec()
{
if(Ctrl::IsReadOnly()) {
BeepExclamation();
return;
}
DataType d = Base::GetData();
if(!IsNull(d)) {
WithSpin_Add(d, -inc, Base::GetMin(), roundfrommin);
if(IsNull(Base::GetMin()) || d >= Base::GetMin()) {
Base::SetData(d);
Ctrl::Action();
}
}
else {
DataType max = Base::GetMax();
if(IsNull(max) || max >= Base::GetDefaultMax())
Base::SetData(WithSpin_DefaultStartValue<DataType>());
else
Base::SetData(max);
}
Ctrl::SetFocus();
}
template <class DataType, class Base, class IncType>
bool WithSpin<DataType, Base, IncType>::Key(dword key, int repcnt)
{
if(keys) {
if(key == K_UP) {
Inc();
return true;
}
if(key == K_DOWN) {
Dec();
return true;
}
}
return Base::Key(key, repcnt);
}
template <class DataType, class Base, class IncType>
void WithSpin<DataType, Base, IncType>::MouseWheel(Point, int zdelta, dword)
{
if(mousewheel) {
if(zdelta < 0)
Dec();
else
Inc();
}
}
typedef WithSpin<int, EditInt> EditIntSpin; typedef WithSpin<int, EditInt> EditIntSpin;
typedef WithSpin<int64, EditInt64> EditInt64Spin; typedef WithSpin<int64, EditInt64> EditInt64Spin;

201
uppsrc/CtrlLib/EditCtrl.hpp Normal file
View file

@ -0,0 +1,201 @@
template <class DataType, class Base, class IncType>
WithSpin<DataType, Base, IncType>::WithSpin()
: inc(WithSpin_DefaultIncValue<IncType>())
{
Init();
}
template <class DataType, class Base, class IncType>
WithSpin<DataType, Base, IncType>::WithSpin(IncType inc)
: inc(inc)
{
Init();
}
template <class DataType, class Base, class IncType>
WithSpin<DataType, Base, IncType>::WithSpin(DataType min, DataType max, IncType inc)
: inc(WithSpin_DefaultIncValue<IncType>())
{
Base::MinMax(min, max);
Init();
}
template <class DataType, class Base, class IncType>
void WithSpin<DataType, Base, IncType>::Init()
{
style = &SpinButtons::StyleDefault();
}
template <class DataType, class Base, class IncType>
WithSpin<DataType, Base, IncType>& WithSpin<DataType, Base, IncType>::OnSides(bool b)
{
SetStyle(b ? SpinButtons::StyleOnSides() : SpinButtons::StyleDefault());
Base::RefreshLayout();
return *this;
}
template <class DataType, class Base, class IncType>
void WithSpin<DataType, Base, IncType>::Inc()
{
if(Ctrl::IsReadOnly()) {
BeepExclamation();
return;
}
DataType d = Base::GetData();
if(!IsNull(d)) {
WithSpin_Add(d, inc, Base::GetMin(), roundfrommin);
if(IsNull(Base::GetMax()) || d <= Base::GetMax()) {
Base::SetData(d);
Ctrl::Action();
}
}
else {
DataType min = Base::GetMin();
if(IsNull(min) || min <= Base::GetDefaultMin())
Base::SetData(WithSpin_DefaultStartValue<DataType>());
else
Base::SetData(min);
}
Ctrl::SetFocus();
}
template <class DataType, class Base, class IncType>
void WithSpin<DataType, Base, IncType>::Dec()
{
if(Ctrl::IsReadOnly()) {
BeepExclamation();
return;
}
DataType d = Base::GetData();
if(!IsNull(d)) {
WithSpin_Add(d, -inc, Base::GetMin(), roundfrommin);
if(IsNull(Base::GetMin()) || d >= Base::GetMin()) {
Base::SetData(d);
Ctrl::Action();
}
}
else {
DataType max = Base::GetMax();
if(IsNull(max) || max >= Base::GetDefaultMax())
Base::SetData(WithSpin_DefaultStartValue<DataType>());
else
Base::SetData(max);
}
Ctrl::SetFocus();
}
template <class DataType, class Base, class IncType>
bool WithSpin<DataType, Base, IncType>::Key(dword key, int repcnt)
{
if(keys) {
if(key == K_UP) {
Inc();
return true;
}
if(key == K_DOWN) {
Dec();
return true;
}
}
return Base::Key(key, repcnt);
}
template <class DataType, class Base, class IncType>
Image WithSpin<DataType, Base, IncType>::MouseEvent(int event, Point p, int zdelta, dword keyflags)
{
if(ButtonsMouseEvent(this, event, p))
return Image::Arrow();
return Base::MouseEvent(event, p, zdelta, keyflags);
}
template <class DataType, class Base, class IncType>
void WithSpin<DataType, Base, IncType>::MouseWheel(Point, int zdelta, dword)
{
if(mousewheel) {
if(zdelta < 0)
Dec();
else
Inc();
}
}
template <class DataType, class Base, class IncType>
void WithSpin<DataType, Base, IncType>::CancelMode()
{
Base::CancelMode();
ButtonsCancelMode();
}
template <class DataType, class Base, class IncType>
int WithSpin<DataType, Base, IncType>::GetSpaceLeft() const
{
if(!visible)
return 0;
return style->onsides ? min(Base::GetSize().cx / 2, style->width) - style->over : 0;
}
template <class DataType, class Base, class IncType>
int WithSpin<DataType, Base, IncType>::GetSpaceRight() const
{
if(!visible)
return 0;
return min(Base::GetSize().cx / 2, style->width) - style->over;
}
template <class DataType, class Base, class IncType>
void WithSpin<DataType, Base, IncType>::EditCapture()
{
buttons_capture = false;
}
template <class DataType, class Base, class IncType>
bool WithSpin<DataType, Base, IncType>::HasEditCapture()
{
return Base::HasCapture() && !buttons_capture;
}
template <class DataType, class Base, class IncType>
void WithSpin<DataType, Base, IncType>::ButtonPush(int i)
{
if(i)
Inc();
else
Dec();
}
template <class DataType, class Base, class IncType>
void WithSpin<DataType, Base, IncType>::ButtonRepeat(int i)
{
ButtonPush(i);
}
template <class DataType, class Base, class IncType>
void WithSpin<DataType, Base, IncType>::PaintSpace(Draw& w)
{
PaintButtons(w, this);
}
template <class DataType, class Base, class IncType>
int WithSpin<DataType, Base, IncType>::ButtonCount() const
{
return visible ? 2 : 0;
}
template <class DataType, class Base, class IncType>
Rect WithSpin<DataType, Base, IncType>::ButtonRect(int i) const
{
Rect rect = Base::GetSize();
int h = rect.GetHeight();
int h7 = min(rect.GetWidth() / 2, style->width);
int h7o = h7 - style->over;
if(style->onsides)
return i ? RectC(rect.left - style->over, rect.top, h7, h) : RectC(rect.right - h7o, rect.top, h7, h);
int h2 = h / 2;
return i ? RectC(rect.right - h7o, rect.top, h7, h2) : RectC(rect.right - h7o, rect.top + h2, h7, h - h2);
}
template <class DataType, class Base, class IncType>
const Button::Style& WithSpin<DataType, Base, IncType>::ButtonStyle(int i) const
{
return i ? style->inc : style->dec;
}

View file

@ -180,12 +180,37 @@ int EditField::GetStdHeight(Font font)
Size EditField::GetMinSize() const Size EditField::GetMinSize() const
{ {
return AddFrameSize(10, font.GetCy() + (no_internal_margin ? 0 : 4)); return AddFrameSize(10 + GetSpaceLeft() + GetSpaceRight(), font.GetCy() + (no_internal_margin ? 0 : 4));
}
void EditField::PaintSpace(Draw& w)
{
}
int EditField::GetSpaceLeft() const
{
return 0;
}
int EditField::GetSpaceRight() const
{
return 0;
}
void EditField::EditCapture()
{
}
bool EditField::HasEditCapture()
{
return HasCapture();
} }
int EditField::GetCursor(int posx) int EditField::GetCursor(int posx)
{ {
posx -= 2; posx -= GetSpaceLeft();
if(!no_internal_margin)
posx -= 2;
if(posx <= 0) return 0; if(posx <= 0) return 0;
int count = text.GetLength(); int count = text.GetLength();
@ -281,30 +306,37 @@ Color EditField::GetPaper()
void EditField::Paint(Draw& w) void EditField::Paint(Draw& w)
{ {
int lspace = GetSpaceLeft();
int rspace = GetSpaceRight();
Size sz = GetSize(); Size sz = GetSize();
bool enabled = IsShowEnabled(); bool enabled = IsShowEnabled();
Color paper = GetPaper(); Color paper = GetPaper();
Color textcolor = GetColorAttr(ATTR_TEXTCOLOR);
Color ink = enabled ? Nvl(textcolor, style->text) : style->textdisabled; Color ink = enabled ? Nvl(textcolor, style->text) : style->textdisabled;
int fcy = font.GetCy(); int fcy = font.GetCy();
int yy = GetTy(); int yy = GetTy();
w.DrawRect(sz, paper);
PaintSpace(w);
if(!no_internal_margin) { if(!no_internal_margin) {
w.DrawRect(0, 0, 2, sz.cy, paper); lspace += 2;
w.DrawRect(0, 0, sz.cx, yy, paper); rspace += 2;
w.DrawRect(0, yy + fcy, sz.cx, sz.cy - yy - fcy, paper);
w.DrawRect(sz.cx - 2, 0, 2, sz.cy, paper);
w.Clipoff(2, yy, sz.cx - 4, fcy);
} }
if(lspace || rspace)
w.Clipoff(lspace, no_internal_margin ? 0 : yy, sz.cx - lspace - rspace, no_internal_margin ? 0 : fcy);
int x = -sc; int x = -sc;
w.DrawRect(0, 0, sz.cx, fcy, paper); String nulltext = GetTextAttr(ATTR_NULLTEXT);
Image nullicon = GetAttr<Image>(ATTR_NULLICON);
if(IsNull(text) && (!IsNull(nulltext) || !IsNull(nullicon))) { if(IsNull(text) && (!IsNull(nulltext) || !IsNull(nullicon))) {
const wchar *txt = nulltext; WString nt = nulltext.ToWString();
const wchar *txt = nt;
if(!IsNull(nullicon)) { if(!IsNull(nullicon)) {
int icx = nullicon.GetWidth(); int icx = nullicon.GetWidth();
w.DrawRect(x, 0, icx + 4, fcy, paper); w.DrawRect(x, 0, icx + 4, fcy, paper);
w.DrawImage(x, (fcy - nullicon.GetHeight()) / 2, nullicon); w.DrawImage(x, (fcy - nullicon.GetHeight()) / 2, nullicon);
x += icx + 4; x += icx + 4;
} }
Paints(w, x, fcy, txt, nullink, paper, nulltext.GetLength(), false, nullfont, Null, false); Paints(w, x, fcy, txt, Nvl(GetColorAttr(ATTR_NULLINK), SColorDisabled()),
paper, nt.GetLength(), false, Nvl(GetFontAttr(ATTR_NULLFONT), StdFont().Italic()), Null, false);
} }
else { else {
const wchar *txt = text; const wchar *txt = text;
@ -333,9 +365,9 @@ void EditField::Paint(Draw& w)
b = i; b = i;
} }
} }
if(!no_internal_margin)
w.End();
DrawTiles(w, dropcaret, CtrlImg::checkers()); DrawTiles(w, dropcaret, CtrlImg::checkers());
if(lspace || rspace)
w.End();
} }
bool EditField::GetSelection(int& l, int& h) const bool EditField::GetSelection(int& l, int& h) const
@ -362,15 +394,14 @@ bool EditField::IsSelection() const
Rect EditField::GetCaretRect(int pos) const Rect EditField::GetCaretRect(int pos) const
{ {
return RectC(GetCaret(pos) - sc + 2 * !no_internal_margin return RectC(GetCaret(pos) - sc + 2 * !no_internal_margin + GetSpaceLeft()
- font.GetRightSpace('o') + font.GetLeftSpace('o'), GetTy(), - font.GetRightSpace('o') + font.GetLeftSpace('o'), GetTy(),
DPI(1), min(GetSize().cy - 2 * GetTy(), font.GetCy())); DPI(1), min(GetSize().cy - 2 * GetTy(), font.GetCy()));
} }
void EditField::SyncCaret() Rect EditField::GetCaret() const
{ {
Rect r = GetCaretRect(cursor); return GetCaretRect(cursor);
SetCaret(r.left, r.top, r.GetWidth(), r.GetHeight());
} }
void EditField::Finish(bool refresh) void EditField::Finish(bool refresh)
@ -391,7 +422,9 @@ void EditField::Finish(bool refresh)
LeftPos(r.left, sz.cx); LeftPos(r.left, sz.cx);
sz = GetSize(); sz = GetSize();
} }
sz.cx -= 2; if(!no_internal_margin)
sz.cx -= 2;
sz.cx -= GetSpaceLeft() + GetSpaceRight();
if(sz.cx <= 0) return; if(sz.cx <= 0) return;
int x = GetCaret(cursor); int x = GetCaret(cursor);
int rspc = max(font.GetRightSpace('o'), font.GetCy() / 5); // sometimes RightSpace is not implemented (0) int rspc = max(font.GetRightSpace('o'), font.GetCy() / 5); // sometimes RightSpace is not implemented (0)
@ -411,7 +444,6 @@ void EditField::Finish(bool refresh)
} }
if(refresh) if(refresh)
RefreshAll(); RefreshAll();
SyncCaret();
} }
void EditField::Layout() void EditField::Layout()
@ -432,6 +464,7 @@ void EditField::SelSource()
void EditField::GotFocus() void EditField::GotFocus()
{ {
auto inactive_convert = (const Convert *)GetVoidPtrAttr(ATTR_INACTIVE_CONVERT);
if(autoformat && IsEditable() && !IsNull(text) && inactive_convert) { if(autoformat && IsEditable() && !IsNull(text) && inactive_convert) {
Value v = convert->Scan(text); Value v = convert->Scan(text);
if(!v.IsError()) { if(!v.IsError()) {
@ -453,6 +486,7 @@ void EditField::LostFocus()
if(autoformat && IsEditable() && !IsNull(text) && !IsDragAndDropSource()) { if(autoformat && IsEditable() && !IsNull(text) && !IsDragAndDropSource()) {
Value v = convert->Scan(text); Value v = convert->Scan(text);
if(!v.IsError()) { if(!v.IsError()) {
auto inactive_convert = (const Convert *)GetVoidPtrAttr(ATTR_INACTIVE_CONVERT);
const Convert * cv = inactive_convert ? inactive_convert : convert; const Convert * cv = inactive_convert ? inactive_convert : convert;
WString s = cv->Format(v); WString s = cv->Format(v);
if(s != text) text = s; if(s != text) text = s;
@ -487,6 +521,7 @@ void EditField::LeftDown(Point p, dword flags)
return; return;
} }
SetCapture(); SetCapture();
EditCapture();
Move(c, flags & K_SHIFT); Move(c, flags & K_SHIFT);
Finish(); Finish();
} }
@ -509,7 +544,7 @@ void EditField::LeftUp(Point p, dword flags)
{ {
int c = GetCursor(p.x + sc); int c = GetCursor(p.x + sc);
int l, h; 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); Move(c, false);
Finish(); Finish();
selclick = false; selclick = false;
@ -531,7 +566,7 @@ void EditField::LeftTriple(Point p, dword keyflags)
void EditField::MouseMove(Point p, dword flags) void EditField::MouseMove(Point p, dword flags)
{ {
if(!HasCapture()) return; if(!HasEditCapture()) return;
Move(GetCursor(p.x + sc), true); Move(GetCursor(p.x + sc), true);
Finish(); Finish();
} }
@ -645,10 +680,8 @@ void EditField::Remove(int pos, int n)
{ {
if(IsReadOnly()) return; if(IsReadOnly()) return;
text.Remove(pos, n); text.Remove(pos, n);
if(cursor >= text.GetLength()) { if(cursor >= text.GetLength())
cursor = text.GetLength(); cursor = text.GetLength();
SyncCaret();
}
Update(); Update();
} }
@ -706,7 +739,7 @@ void EditField::DragAndDrop(Point p, PasteClip& d)
dc = RectC(x - sc + 2 - font.GetRightSpace('o'), GetTy(), dc = RectC(x - sc + 2 - font.GetRightSpace('o'), GetTy(),
1, min(GetSize().cy - 2 * GetTy(), font.GetCy())); 1, min(GetSize().cy - 2 * GetTy(), font.GetCy()));
} }
if(dc != dropcaret) { if((Rect16)dc != dropcaret) {
Refresh(dropcaret); Refresh(dropcaret);
dropcaret = dc; dropcaret = dc;
Refresh(dropcaret); Refresh(dropcaret);
@ -728,7 +761,6 @@ void EditField::DragRepeat(Point p)
if(a != sc) { if(a != sc) {
sc = a; sc = a;
Refresh(); Refresh();
SyncCaret();
} }
} }
@ -745,7 +777,7 @@ void EditField::LeftDrag(Point p, dword flags)
int c = GetCursor(p.x + sc); int c = GetCursor(p.x + sc);
Size ssz = StdSampleSize(); Size ssz = StdSampleSize();
int sell, selh; 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); WString sel = text.Mid(sell, selh - sell);
ImageDraw iw(ssz); ImageDraw iw(ssz);
iw.DrawText(0, 0, sel); iw.DrawText(0, 0, sel);
@ -981,6 +1013,7 @@ void EditField::SetText(const WString& txt)
void EditField::SetData(const Value& data) void EditField::SetData(const Value& data)
{ {
auto inactive_convert = (const Convert *)GetVoidPtrAttr(ATTR_INACTIVE_CONVERT);
const Convert * cv = convert; const Convert * cv = convert;
if(!HasFocus() && inactive_convert) if(!HasFocus() && inactive_convert)
cv = inactive_convert; cv = inactive_convert;
@ -1010,7 +1043,6 @@ void EditField::Reset()
clickselect = false; clickselect = false;
filter = CharFilterUnicode; filter = CharFilterUnicode;
convert = &NoConvert(); convert = &NoConvert();
inactive_convert = NULL;
initcaps = false; initcaps = false;
maxlen = INT_MAX; maxlen = INT_MAX;
autosize = false; autosize = false;
@ -1021,10 +1053,10 @@ void EditField::Reset()
SetStyle(StyleDefault()); SetStyle(StyleDefault());
SetFrame(edge); SetFrame(edge);
font = StdFont(); font = StdFont();
textcolor = Null;
showspaces = false; showspaces = false;
no_internal_margin = false; no_internal_margin = false;
fsell = fselh = -1; fsell = fselh = -1;
DeleteAttr<Image>(ATTR_NULLICON);
} }
EditField& EditField::SetFont(Font _font) EditField& EditField::SetFont(Font _font)
@ -1036,25 +1068,27 @@ EditField& EditField::SetFont(Font _font)
EditField& EditField::SetColor(Color c) EditField& EditField::SetColor(Color c)
{ {
textcolor = c; SetColorAttr(ATTR_TEXTCOLOR, c);
Refresh(); Refresh();
return *this; return *this;
} }
EditField& EditField::NullText(const Image& icon, const char *text, Font fnt, Color ink) EditField& EditField::NullText(const Image& icon, const char *text, Font fnt, Color ink)
{ {
nullicon = icon; if(!IsNull(icon))
nulltext = text; CreateAttr<Image>(ATTR_NULLICON) = icon;
nulltext << " "; String h = text;
nullink = ink; h << " ";
nullfont = fnt; SetTextAttr(ATTR_NULLTEXT, h);
SetColorAttr(ATTR_NULLINK, ink);
SetFontAttr(ATTR_NULLFONT, fnt);
Refresh(); Refresh();
return *this; return *this;
} }
EditField& EditField::NullText(const Image& icon, const char *text, Color ink) EditField& EditField::NullText(const Image& icon, const char *text, Color ink)
{ {
return NullText(icon, text, GetFont().Italic(), ink); return NullText(icon, text, Null, ink);
} }
EditField& EditField::NullText(const char *text, Font fnt, Color ink) EditField& EditField::NullText(const char *text, Font fnt, Color ink)
@ -1064,7 +1098,7 @@ EditField& EditField::NullText(const char *text, Font fnt, Color ink)
EditField& EditField::NullText(const char *text, Color ink) EditField& EditField::NullText(const char *text, Color ink)
{ {
return NullText(text, GetFont().Italic(), ink); return NullText(text, Null, ink);
} }
EditField::EditField() EditField::EditField()
@ -1075,6 +1109,9 @@ EditField::EditField()
WhenBar = THISBACK(StdBar); WhenBar = THISBACK(StdBar);
} }
EditField::~EditField() {} EditField::~EditField()
{
DeleteAttr<Image>(ATTR_NULLICON);
}
} }

View file

@ -743,6 +743,8 @@ void HeaderCtrl::Serialize(Stream& s) {
if(version >= 0x04) { if(version >= 0x04) {
int n = col.GetCount(); int n = col.GetCount();
s / n; s / n;
if(n < 0 || n > 10000)
s.LoadError();
Array<Column> col2 = clone(col); Array<Column> col2 = clone(col);
if(s.IsLoading()) if(s.IsLoading())
col2.InsertN(0, n); col2.InsertN(0, n);
@ -757,10 +759,10 @@ void HeaderCtrl::Serialize(Stream& s) {
} }
col2[i].index = ndx; col2[i].index = ndx;
s % col2[i].ratio; s % col2[i].ratio;
s % col2[i].visible; s % col2[i].visible;
} }
if(s.IsLoading() && n == col.GetCount()) { if(s.IsLoading() && n == col.GetCount()) {
col2.Trim(n); col2.SetCount(n);
col = pick(col2); col = pick(col2);
} }
} }

View file

@ -29,14 +29,14 @@ public:
protected: protected:
virtual void LabelUpdate(); virtual void LabelUpdate();
String tip;
HeaderCtrl *header; HeaderCtrl *header;
double ratio; double ratio;
bool visible;
int min, max; int min, max;
int margin; int margin;
Color paper; Color paper;
int index; int index;
String tip; bool visible;
void Paint(bool& first, Draw& w, void Paint(bool& first, Draw& w,
int x, int y, int cx, int cy, bool disabled, bool push, bool hl); int x, int y, int cx, int cy, bool disabled, bool push, bool hl);

View file

@ -115,20 +115,6 @@ int ChooseAccessKey(const char *text, dword used)
return 0; return 0;
} }
DrawLabel::DrawLabel()
{
push = focus = disabled = false;
lspc = rspc = 0;
limg_never_hide = false;
rimg_never_hide = false;
ink = disabledink = Null;
align = valign = ALIGN_CENTER;
accesskey = 0;
accesspos = -1;
font = StdFont();
nowrap = false;
}
Size DrawLabel::GetSize(int txtcx) const Size DrawLabel::GetSize(int txtcx) const
{ {
return GetSize(txtcx, limg.GetSize(), lspc, rimg.GetSize(), rspc); return GetSize(txtcx, limg.GetSize(), lspc, rimg.GetSize(), rspc);
@ -289,7 +275,17 @@ Size DrawLabel::Paint(Draw& w, int x, int y, int cx, int cy, bool vak) const
void LabelBase::LabelUpdate() {} void LabelBase::LabelUpdate() {}
DrawLabel LabelBase::Make() const
{
DrawLabel lx;
(DrawLabelBasic&)lx = lbl;
if(ext)
(DrawLabelExt&)lx = *ext;
return lx;
}
LabelBase& LabelBase::SetLeftImage(const Image& img, int spc, bool never_hide) { LabelBase& LabelBase::SetLeftImage(const Image& img, int spc, bool never_hide) {
DrawLabelExt& lbl = Ext();
lbl.limg = img; lbl.limg = img;
lbl.lspc = spc; lbl.lspc = spc;
lbl.limg_never_hide = never_hide; lbl.limg_never_hide = never_hide;
@ -298,6 +294,7 @@ LabelBase& LabelBase::SetLeftImage(const Image& img, int spc, bool never_hide) {
} }
LabelBase& LabelBase::SetRightImage(const Image& img, int spc, bool never_hide) { LabelBase& LabelBase::SetRightImage(const Image& img, int spc, bool never_hide) {
DrawLabelExt& lbl = Ext();
lbl.rimg = img; lbl.rimg = img;
lbl.rspc = spc; lbl.rspc = spc;
lbl.rimg_never_hide = never_hide; lbl.rimg_never_hide = never_hide;
@ -306,7 +303,7 @@ LabelBase& LabelBase::SetRightImage(const Image& img, int spc, bool never_hide)
} }
LabelBase& LabelBase::SetPaintRect(const PaintRect& paintrect) { LabelBase& LabelBase::SetPaintRect(const PaintRect& paintrect) {
lbl.paintrect = paintrect; Ext().paintrect = paintrect;
LabelUpdate(); LabelUpdate();
return *this; return *this;
} }
@ -362,7 +359,7 @@ LabelBase& LabelBase::SetVAlign(int valign) {
Size LabelBase::PaintLabel(Ctrl *ctrl, Draw& w, const Rect& r, bool disabled, bool push, bool focus, bool vak) Size LabelBase::PaintLabel(Ctrl *ctrl, Draw& w, const Rect& r, bool disabled, bool push, bool focus, bool vak)
{ {
DrawLabel lbl1 = lbl; DrawLabel lbl1 = Make();
lbl1.disabled = disabled; lbl1.disabled = disabled;
lbl1.push = push; lbl1.push = push;
lbl1.focus = focus; lbl1.focus = focus;
@ -387,12 +384,13 @@ Size LabelBase::PaintLabel(Draw& w, int x, int y, int cx, int cy, bool disabled,
Size LabelBase::GetLabelSize() const Size LabelBase::GetLabelSize() const
{ {
return lbl.GetSize(); return Make().GetSize();
} }
void LinkToolTipIn__(); void LinkToolTipIn__();
LabelBase::~LabelBase() { LabelBase::~LabelBase()
{
LinkToolTipIn__(); LinkToolTipIn__();
} }

View file

@ -28,30 +28,41 @@ void DrawVertDrop(Draw& w, int x, int y, int cy);
Point GetDragScroll(Ctrl *ctrl, Point p, Size max); Point GetDragScroll(Ctrl *ctrl, Point p, Size max);
Point GetDragScroll(Ctrl *ctrl, Point p, int max = 16); Point GetDragScroll(Ctrl *ctrl, Point p, int max = 16);
struct DrawLabel { struct DrawLabelBasic {
bool push;
bool focus;
bool disabled;
bool limg_never_hide;
bool rimg_never_hide;
PaintRect paintrect;
Image limg;
Color lcolor;
int lspc;
String text; String text;
Font font; Font font;
Color ink, disabledink; Color ink;
Image rimg; Color disabledink;
Color rcolor;
int rspc;
int align, valign;
bool nowrap;
int accesskey; int accesskey;
int accesspos;
int align:4;
int valign:4;
bool nowrap:1;
DrawLabelBasic() { align = valign = ALIGN_CENTER; nowrap = false; accesskey = 0; font = StdFont(); }
};
struct DrawLabelExt {
PaintRect paintrect;
Image limg;
Image rimg;
Color lcolor;
int lspc = 0;
Color rcolor;
int rspc = 0;
bool limg_never_hide = false;
bool rimg_never_hide = false;
};
struct DrawLabel : DrawLabelBasic, DrawLabelExt {
bool push = false;
bool focus = false;
bool disabled = false;
Size GetSize(int txtcx, Size sz1, int lspc, Size sz2, int rspc) const; Size GetSize(int txtcx, Size sz1, int lspc, Size sz2, int rspc) const;
Size GetSize(int txtcx = INT_MAX) const; Size GetSize(int txtcx = INT_MAX) const;
@ -59,8 +70,6 @@ struct DrawLabel {
Size Paint(Ctrl *ctrl, Draw& w, int x, int y, int cx, int cy, bool visibleaccesskey = true) const; Size Paint(Ctrl *ctrl, Draw& w, int x, int y, int cx, int cy, bool visibleaccesskey = true) const;
Size Paint(Draw& w, const Rect& r, bool visibleaccesskey = true) const; Size Paint(Draw& w, const Rect& r, bool visibleaccesskey = true) const;
Size Paint(Draw& w, int x, int y, int cx, int cy, bool visibleaccesskey = true) const; Size Paint(Draw& w, int x, int y, int cx, int cy, bool visibleaccesskey = true) const;
DrawLabel();
}; };
Image DisabledImage(const Image& img, bool disabled = true); Image DisabledImage(const Image& img, bool disabled = true);
@ -70,7 +79,11 @@ class LabelBase {
protected: protected:
virtual void LabelUpdate(); virtual void LabelUpdate();
DrawLabel lbl; DrawLabelBasic lbl;
One<DrawLabelExt> ext;
DrawLabelExt& Ext() { if(!ext) ext.Create() ; return *ext; }
DrawLabel Make() const;
public: public:
LabelBase& SetLeftImage(const Image& bmp1, int spc = 0, bool never_hide = false); LabelBase& SetLeftImage(const Image& bmp1, int spc = 0, bool never_hide = false);
@ -94,7 +107,7 @@ public:
int GetAlign() const { return lbl.align; } int GetAlign() const { return lbl.align; }
int GetVAlign() const { return lbl.valign; } int GetVAlign() const { return lbl.valign; }
PaintRect GetPaintRect() const { return lbl.paintrect; } PaintRect GetPaintRect() const { return ext ? ext->paintrect : PaintRect(); }
String GetText() const { return lbl.text; } String GetText() const { return lbl.text; }
Font GetFont() const { return lbl.font; } Font GetFont() const { return lbl.font; }
Color GetInk() const { return lbl.ink; } Color GetInk() const { return lbl.ink; }
@ -108,6 +121,9 @@ public:
Size PaintLabel(Draw& w, int x, int y, int cx, int cy, Size PaintLabel(Draw& w, int x, int y, int cx, int cy,
bool disabled = false, bool push = false, bool focus = false, bool vak = true); bool disabled = false, bool push = false, bool focus = false, bool vak = true);
Size GetLabelSize() const; Size GetLabelSize() const;
LabelBase(const LabelBase& src) { lbl = src.lbl; if(src.ext) ext = clone(src.ext); }
LabelBase() {}
virtual ~LabelBase(); virtual ~LabelBase();
}; };
@ -121,13 +137,13 @@ public:
virtual void FrameAddSize(Size& sz); virtual void FrameAddSize(Size& sz);
private: private:
Value coloredge;
const Value *edge; const Value *edge;
const Ctrl *ctrl; const Ctrl *ctrl;
Value coloredge; Color color;
Color color; bool mousein:1;
bool mousein = false; bool push:1;
bool push = false; bool button:1;
bool button = false;
public: public:
void Set(const Ctrl *ctrl, const Value *edge, bool active); void Set(const Ctrl *ctrl, const Value *edge, bool active);
@ -135,5 +151,5 @@ public:
void Push(bool b) { button = true; push = b; } void Push(bool b) { button = true; push = b; }
void SetColor(const Value& ce, Color c) { coloredge = ce; color = c; } void SetColor(const Value& ce, Color c) { coloredge = ce; color = c; }
ActiveEdgeFrame() { edge = NULL; mousein = false; } ActiveEdgeFrame() { edge = NULL; mousein = push = button = false; }
}; };

View file

@ -799,14 +799,18 @@ void LineEdit::AlignChar() {
} }
} }
Rect LineEdit::GetCaret() const
{
if(overwrite)
return RectC(caretpos.x, caretpos.y + fsz.cy - 2, fsz.cx, 2);
else
return RectC(caretpos.x, caretpos.y, 2, fsz.cy);
}
void LineEdit::PlaceCaret0(Point p) { void LineEdit::PlaceCaret0(Point p) {
Size fsz = GetFontSize(); Size fsz = GetFontSize();
p -= sb; p -= sb;
caretpos = Point(p.x * fsz.cx, p.y * fsz.cy); caretpos = Point(p.x * fsz.cx, p.y * fsz.cy);
if(overwrite)
SetCaret(caretpos.x, caretpos.y + fsz.cy - 2, fsz.cx, 2);
else
SetCaret(caretpos.x, caretpos.y, 2, fsz.cy);
} }
int LineEdit::PlaceCaretNoG(int64 newcursor, bool sel) { int LineEdit::PlaceCaretNoG(int64 newcursor, bool sel) {

View file

@ -47,9 +47,11 @@ MultiButton::SubButton::SubButton()
void MultiButton::SubButton::Refresh() void MultiButton::SubButton::Refresh()
{ {
owner->Refresh(); if(owner) {
if(owner->Frame() && owner->GetParent()) owner->Refresh();
owner->GetParent()->RefreshLayout(); if(owner->Frame() && owner->GetParent())
owner->GetParent()->RefreshLayout();
}
} }
MultiButton::SubButton& MultiButton::SubButton::SetImage(const Image& m) MultiButton::SubButton& MultiButton::SubButton::SetImage(const Image& m)
@ -111,30 +113,89 @@ MultiButton::SubButton& MultiButton::SubButton::Show(bool b)
return *this; return *this;
} }
void MultiButton::MultiButtons()
{
if(droppush) {
SubButton& b = buttons.Add();
b.owner = this;
b.WhenPush = [=] { DropPush(); };
b.main = true;
droppush = false;
}
}
MultiButton::SubButton& MultiButton::AddButton() MultiButton::SubButton& MultiButton::AddButton()
{ {
SubButton& b = button.Add(); MultiButtons();
SubButton& b = buttons.Add();
b.owner = this; b.owner = this;
return b; return b;
} }
MultiButton::SubButton& MultiButton::InsertButton(int i) MultiButton::SubButton& MultiButton::InsertButton(int i)
{ {
SubButton& b = button.Insert(i); MultiButtons();
SubButton& b = buttons.Insert(i);
b.owner = this; b.owner = this;
return b; return b;
} }
void MultiButton::RemoveButton(int i) 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<MultiButton *>(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) MultiButton::SubButton& MultiButton::SubButton::Main(bool b)
{ {
if(b) if(b && owner)
for(int i = 0; i < owner->button.GetCount(); i++) for(int i = 0; i < owner->GetButtonCount(); i++)
owner->button[i].main = false; owner->GetButton(i).main = false;
main = b; main = b;
return *this; return *this;
} }
@ -212,21 +273,21 @@ int MultiButton::FindButton(int px)
{ {
if(IsReadOnly()) if(IsReadOnly())
return Null; return Null;
if(IsTrivial() && !Frame()) if(IsTrivial() && !Frame() && GetButtonCount())
return button[0].enabled ? 0 : Null; return GetButton(0).enabled ? 0 : Null;
int border, lx, rx; int border, lx, rx;
Metrics(border, lx, rx); Metrics(border, lx, rx);
for(int i = 0; i < button.GetCount(); i++) { for(int i = 0; i < GetButtonCount(); i++) {
SubButton& b = button[i]; SubButton& b = Button(i);
int x = 0, cx = 0; int x = 0, cx = 0;
if(GetPos(b, lx, rx, x, cx, px)) if(GetPos(b, lx, rx, x, cx, px))
return b.enabled ? i : Null; return b.enabled ? i : Null;
} }
if(WhenPush || WhenClick) if(HasMain())
return MAIN; return MAIN;
if(display) if(display)
for(int i = 0; i < button.GetCount(); i++) for(int i = 0; i < GetButtonCount(); i++)
if(button[i].main) if(Button(i).main)
return i; return i;
return Null; return Null;
} }
@ -262,7 +323,7 @@ void MultiButton::GetPos(int ii, int& x, int& cx)
Metrics(border, lx, rx); Metrics(border, lx, rx);
x = cx = 0; x = cx = 0;
for(int i = 0; i <= ii; i++) { for(int i = 0; i <= ii; i++) {
SubButton& b = button[i]; SubButton& b = Button(i);
GetPos(b, lx, rx, x, cx); GetPos(b, lx, rx, x, cx);
} }
} }
@ -273,8 +334,8 @@ void MultiButton::GetLR(int& lx, int& rx)
Metrics(border, lx, rx); Metrics(border, lx, rx);
int x = 0; int x = 0;
int cx = 0; int cx = 0;
for(int i = 0; i < button.GetCount(); i++) { for(int i = 0; i < GetButtonCount(); i++) {
SubButton& b = button[i]; SubButton& b = Button(i);
GetPos(b, lx, rx, x, cx); GetPos(b, lx, rx, x, cx);
} }
} }
@ -286,13 +347,13 @@ int MultiButton::ChState(int i)
if(i == MAIN && frm && style->activeedge) { if(i == MAIN && frm && style->activeedge) {
int q = 0; int q = 0;
if(p) 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->HasFocus() || push ? CTRL_PRESSED
: p->HasMouse() || hl >= 0 ? CTRL_HOT : p->HasMouse() || hl >= 0 ? CTRL_HOT
: CTRL_NORMAL; : CTRL_NORMAL;
return q; 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; return CTRL_DISABLED;
if(IsTrivial() && !frm) if(IsTrivial() && !frm)
i = 0; i = 0;
@ -317,8 +378,8 @@ void MultiButton::Lay(Rect& r, bool minsize)
bool frm = Metrics(border, lx, rx); bool frm = Metrics(border, lx, rx);
bool left = false; bool left = false;
bool right = false; bool right = false;
for(int i = 0; i < button.GetCount(); i++) { for(int i = 0; i < GetButtonCount(); i++) {
SubButton& b = button[i]; SubButton& b = Button(i);
int cx = 0; int x = 0; int cx = 0; int x = 0;
GetPos(b, lx, rx, x, cx); GetPos(b, lx, rx, x, cx);
(b.left ? left : right) = true; (b.left ? left : right) = true;
@ -393,7 +454,7 @@ Rect MultiButton::Paint0(Draw& w, bool getcr)
Color p = paper; Color p = paper;
if(frm && style->activeedge && HasFocus()) if(frm && style->activeedge && HasFocus())
p = SColorHighlight(); p = SColorHighlight();
if(hotpressed && (WhenPush || WhenClick)) if(hotpressed && HasMain())
p = Nvl(fpaper, paper); p = Nvl(fpaper, paper);
if(IsEnabled() && IsEditable()) if(IsEnabled() && IsEditable())
p = Nvl(p, style->paper); p = Nvl(p, style->paper);
@ -404,8 +465,8 @@ Rect MultiButton::Paint0(Draw& w, bool getcr)
} }
bool left = false; bool left = false;
bool right = false; bool right = false;
for(int i = 0; i < button.GetCount(); i++) { for(int i = 0; i < GetButtonCount(); i++) {
SubButton& b = button[i]; SubButton& b = Button(i);
int st = ChState(i); int st = ChState(i);
int x = 0, cx = 0; int x = 0, cx = 0;
GetPos(b, lx, rx, x, cx); GetPos(b, lx, rx, x, cx);
@ -562,7 +623,8 @@ void MultiButton::SyncInfo()
void MultiButton::MouseMove(Point p, dword flags) void MultiButton::MouseMove(Point p, dword flags)
{ {
int h = FindButton(p.x); int h = FindButton(p.x);
Ctrl::Tip(h >= 0 && h < button.GetCount() ? Nvl(button[h].tip, tip) : tip); String tip = GetTextAttr(ATTR_TIP);
Ctrl::Tip(h >= 0 && h < GetButtonCount() ? Nvl(Button(h).tip, tip) : tip);
if(hl != h) { if(hl != h) {
hl = h; hl = h;
Refresh(); Refresh();
@ -575,12 +637,20 @@ void MultiButton::MouseMove(Point p, dword flags)
SyncInfo(); SyncInfo();
} }
void MultiButton::DoPush(int i)
{
if(i == 0 && droppush)
DropPush();
else
Button(i).WhenPush();
}
void MultiButton::LeftDown(Point p, dword flags) void MultiButton::LeftDown(Point p, dword flags)
{ {
push = true; push = true;
Refresh(); Refresh();
if(IsNull(hl)) if(hl == NONE)
pushrect = Null; pushrect.Clear();
else { else {
if(hl == MAIN) if(hl == MAIN)
pushrect = GetScreenRect(); pushrect = GetScreenRect();
@ -593,9 +663,9 @@ void MultiButton::LeftDown(Point p, dword flags)
} }
Sync(); Sync();
if(hl >= 0) if(hl >= 0)
button[hl].WhenPush(); DoPush(hl);
else else
WhenPush(); MainPush();
} }
SyncInfo(); SyncInfo();
} }
@ -605,11 +675,11 @@ void MultiButton::LeftUp(Point p, dword flags)
push = false; push = false;
Refresh(); Refresh();
Sync(); Sync();
if(!IsNull(hl)) { if(hl != NONE) {
if(hl >= 0) if(hl >= 0)
button[hl].WhenClick(); Button(hl).WhenClick();
else else
WhenClick(); MainClick();
} }
SyncInfo(); SyncInfo();
} }
@ -617,7 +687,7 @@ void MultiButton::LeftUp(Point p, dword flags)
void MultiButton::MouseLeave() void MultiButton::MouseLeave()
{ {
if(!info.IsOpen()) { if(!info.IsOpen()) {
hl = Null; hl = NONE;
Refresh(); Refresh();
SyncInfo(); SyncInfo();
} }
@ -625,7 +695,7 @@ void MultiButton::MouseLeave()
void MultiButton::CancelMode() void MultiButton::CancelMode()
{ {
hl = Null; hl = NONE;
push = false; push = false;
Refresh(); Refresh();
info.Cancel(); info.Cancel();
@ -633,21 +703,7 @@ void MultiButton::CancelMode()
bool MultiButton::IsTrivial() const bool MultiButton::IsTrivial() const
{ {
return button.GetCount() == 1 && IsNull(button[0].img) && !WhenPush && !WhenClick; return GetButtonCount() == 1 && IsNull(Button(0).img) && !HasMain();
}
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();
} }
MultiButton& MultiButton::SetDisplay(const Display& d) MultiButton& MultiButton::SetDisplay(const Display& d)
@ -718,11 +774,11 @@ void MultiButton::PseudoPush(int bi)
{ {
hl = bi; hl = bi;
push = true; push = true;
button[bi].WhenPush(); DoPush(bi);
Sync(); Sync();
Sleep(50); Sleep(50);
button[bi].WhenClick(); Button(bi).WhenClick();
hl = Null; hl = NONE;
push = false; push = false;
Sync(); Sync();
} }
@ -730,15 +786,32 @@ void MultiButton::PseudoPush(int bi)
void MultiButton::PseudoPush() void MultiButton::PseudoPush()
{ {
hl = MAIN; hl = MAIN;
WhenPush(); MainPush();
Sync(); Sync();
Sleep(50); Sleep(50);
WhenClick(); MainClick();
hl = Null; hl = NONE;
push = false; push = false;
Sync(); Sync();
} }
bool MultiButton::HasMain() const
{
return WhenPush || WhenClick;
}
void MultiButton::MainPush()
{
WhenPush();
}
void MultiButton::MainClick()
{
WhenClick();
}
void MultiButton::DropPush() {}
MultiButton::MultiButton() MultiButton::MultiButton()
{ {
Transparent(); Transparent();
@ -749,8 +822,12 @@ MultiButton::MultiButton()
push = false; push = false;
SetFrame(sNullFrame()); SetFrame(sNullFrame());
nobg = false; nobg = false;
hl = NONE;
droppush = false;
} }
//
void MultiButtonFrame::FrameAdd(Ctrl& parent) void MultiButtonFrame::FrameAdd(Ctrl& parent)
{ {
parent.Add(*this); parent.Add(*this);

View file

@ -49,8 +49,9 @@ public:
class SubButton { class SubButton {
friend class MultiButton; friend class MultiButton;
String label;
String tip; String tip;
MultiButton *owner; MultiButton *owner = nullptr;
Image img; Image img;
int cx; int cx;
bool main; bool main;
@ -59,8 +60,6 @@ public:
bool enabled; bool enabled;
bool visible; bool visible;
String label;
void Refresh(); void Refresh();
public: public:
@ -85,6 +84,7 @@ public:
private: private:
enum { enum {
NONE = -2,
MAIN = -1, MAIN = -1,
LB_IMAGE = 5, // image <-> text space LB_IMAGE = 5, // image <-> text space
LB_MARGIN = 10 LB_MARGIN = 10
@ -92,23 +92,24 @@ private:
virtual bool Frame(); virtual bool Frame();
const Display *display; DisplayPopup info;
const Convert *convert; Array<SubButton> buttons;
Value value; Value value;
Value error; Value error;
int valuecy; Rect16 pushrect;
bool push;
bool nobg;
String tip;
Rect pushrect;
Color paper = Null;
Array<SubButton> button;
int hl;
const Display *display;
const Convert *convert;
const Style *style; const Style *style;
DisplayPopup info; int valuecy;
Color paper = Null;
int16 hl;
bool push:1;
bool nobg:1;
bool droppush:1;
int FindButton(int px); int FindButton(int px);
void Margins(int& l, int& r); void Margins(int& l, int& r);
@ -124,13 +125,27 @@ private:
bool Metrics(int& border, int& lx, int &rx); bool Metrics(int& border, int& lx, int &rx);
void SyncInfo(); void SyncInfo();
Rect Paint0(Draw& w, bool getcr); Rect Paint0(Draw& w, bool getcr);
void DoPush(int i);
void MultiButtons();
SubButton& Button(int i) const;
bool HasMain() const;
void MainPush();
void MainClick();
friend class SubButton; friend class SubButton;
friend class MultiButtonFrame; friend class MultiButtonFrame;
protected:
enum {
ATTR_TIP = Ctrl::ATTR_LAST,
ATTR_LAST
};
virtual void DropPush();
public: public:
Event<> WhenPush; Event<> WhenPush;
Event<> WhenClick; Event<> WhenClick;
static const Style& StyleDefault(); static const Style& StyleDefault();
static const Style& StyleFrame(); static const Style& StyleFrame();
@ -145,8 +160,9 @@ public:
SubButton& AddButton(); SubButton& AddButton();
SubButton& InsertButton(int i); SubButton& InsertButton(int i);
void RemoveButton(int i); void RemoveButton(int i);
int GetButtonCount() const { return button.GetCount(); } int GetButtonCount() const;
SubButton& GetButton(int i) { return button[i]; } const MultiButton::SubButton& GetButton(int i) const;
SubButton& GetButton(int i);
SubButton& MainButton(); SubButton& MainButton();
Rect GetPushScreenRect() const { return pushrect; } Rect GetPushScreenRect() const { return pushrect; }
@ -164,10 +180,12 @@ public:
MultiButton& SetConvert(const Convert& c); MultiButton& SetConvert(const Convert& c);
MultiButton& SetValueCy(int cy); MultiButton& SetValueCy(int cy);
MultiButton& Set(const Value& v, bool update = true); MultiButton& Set(const Value& v, bool update = true);
MultiButton& Tip(const char *s) { tip = s; return *this; } MultiButton& Tip(const char *s) { SetTextAttr(ATTR_TIP, s); return *this; }
MultiButton& NoBackground(bool b = true); MultiButton& NoBackground(bool b = true);
MultiButton& SetStyle(const Style& s) { style = &s; Refresh(); return *this; } MultiButton& SetStyle(const Style& s) { style = &s; Refresh(); return *this; }
void SetupDropPush() { droppush = true; }
MultiButton(); MultiButton();
}; };

View file

@ -0,0 +1,321 @@
#include "CtrlLib.h"
#include "CtrlLib.h"
namespace Upp {
CtrlFrame& DropFrame();
void PopUpList::Clear()
{
items.Clear();
lineinfo.Clear();
linedisplay.Clear();
cursor = -1;
if(popup)
popup->ac.Clear();
}
void PopUpList::Remove(int i)
{
items.Remove(i);
if(i < lineinfo.GetCount())
lineinfo.Remove(i);
if(i < linedisplay.GetCount())
linedisplay.Remove(i);
if(popup)
popup->ac.Remove(i);
if(cursor > i)
cursor--;
}
void PopUpList::Insert(int i, const Value& v)
{
items.Insert(i, v);
if(i < lineinfo.GetCount())
lineinfo.Insert(i, 0x7fff);
if(i < linedisplay.GetCount())
linedisplay.Insert(i, nullptr);
if(popup)
popup->ac.Insert(i, Vector<Value>() << v);
if(cursor >= i)
cursor++;
}
void PopUpList::SetCount(int n)
{
items.SetCount(n);
if(popup)
popup->ac.SetCount(n);
}
void PopUpList::AddSeparator()
{
word& x = lineinfo.At(items.GetCount(), 0x7fff);
x |= 0x8000;
items.Add(Null);
if(popup)
popup->ac.AddSeparator();
}
void PopUpList::Add(const Value& v)
{
items.Add(v);
if(popup)
popup->ac.Add(v);
}
void PopUpList::SetLineCy(int ii, int cy)
{
ASSERT(cy >= 0 && cy < 32000);
word& x = lineinfo.At(ii, 0x7fff);
x = x & 0x8000 | cy;
if(popup)
popup->ac.SetLineCy(ii, cy);
}
int PopUpList::GetLineCy(int ii) const
{
if(ii >= 0 && ii < lineinfo.GetCount()) {
word h = lineinfo[ii] & 0x7fff;
if(h != 0x7fff)
return h;
}
return linecy;
}
bool PopUpList::IsLineEnabled(int ii) const
{
return !(ii >= 0 && ii < lineinfo.GetCount() && ((lineinfo[ii] & 0x8000) || (lineinfo[ii] & 0x7fff) == 0));
}
void PopUpList::Set(int i, const Value& v)
{
items.At(i) = v;
if(popup)
popup->ac.Set(i, 0, v);
}
int PopUpList::Find(const Value& v) const
{
return FindIndex(items, v);
}
void PopUpList::SetScrollBarStyle(const ScrollBar::Style& s)
{
sb_style = &s;
if(popup)
popup->ac.SetScrollBarStyle(*sb_style);
}
void PopUpList::SetLineCy(int cy)
{
linecy = cy;
if(popup)
popup->ac.SetLineCy(linecy);
}
void PopUpList::SetDisplay(const Display& d)
{
display = &d;
if(popup)
popup->ac.ColumnAt(0).SetDisplay(d);
}
void PopUpList::SetDisplay(int i, const Display& d)
{
linedisplay.At(i, nullptr) = &d;
if(popup)
popup->ac.SetDisplay(i, 0, d);
}
const Display& PopUpList::GetDisplay(int i) const
{
if(i >= 0 && i < linedisplay.GetCount() && linedisplay[i])
return *linedisplay[i];
return *display;
}
void PopUpList::SetConvert(const Convert& c)
{
convert = &c;
if(popup)
popup->ac.ColumnAt(0).SetConvert(c);
}
void PopUpList::SetCursor(int i)
{
cursor = i;
if(popup)
popup->ac.SetCursor(i);
}
int PopUpList::GetCursor() const
{
return popup ? popup->ac.GetCursor() : cursor;
}
bool PopUpList::Key(int c)
{
// TODO!
return false;
}
void PopUpList::PopupCancelMode() {
if(popup && !inpopup)
DoCancel();
}
void PopUpList::DoClose() {
if(!inpopup && popup) {
popup->closing = true; // prevent infinite recursion
cursor = popup->ac.GetCursor();
popup.Clear();
}
}
void PopUpList::PopupDeactivate() {
if(popup) {
Ctrl::IgnoreMouseClick();
DoCancel();
}
}
void PopUpList::PopupArrayCtrl::LeftUp(Point p, dword keyflags)
{
ArrayCtrl::LeftUp(p, keyflags);
list->DoSelect();
}
bool PopUpList::PopupArrayCtrl::Key(dword key, int n)
{
switch(key) {
case K_ENTER:
case K_ALT_DOWN:
list->DoSelect();
return true;
case K_ESCAPE:
list->DoCancel();
return true;
case K_UP:
if(!IsCursor()) {
SetCursor(GetCount() - 1);
return true;
}
break;
case K_DOWN:
if(!IsCursor()) {
SetCursor(0);
return true;
}
break;
}
return ArrayCtrl::Key(key, n);
}
PopUpList::Popup::Popup(PopUpList *list)
: list(list)
{
ac.list = list;
ac.SetFrame(DropFrame());
auto& col = ac.AddColumn();
if(list->convert)
col.SetConvert(*list->convert);
col.SetDisplay(*list->display);
ac.NoHeader();
ac.HeaderTab(0).SetMargin(0);
ac.MouseMoveCursor();
ac.NoGrid();
ac.AutoHideSb();
ac.SetLineCy(Draw::GetStdFontCy());
for(int i = 0; i < list->items.GetCount(); i++) {
Value v = list->items[i];
word w = i < list->lineinfo.GetCount() ? list->lineinfo[i] : 0x7fff;
if(w & 0x8000)
ac.AddSeparator();
else
ac.Add(v);
w &= 0x7fff;
if(w != 0x7fff)
ac.SetLineCy(i, w);
}
ac.SetCursor(list->GetCursor());
ac.CenterCursor();
}
void PopUpList::PopUp(Ctrl *owner, int x, int top, int bottom, int width) {
if(inpopup)
return;
inpopup++;
DoClose();
popup.Create(this);
int h = popup->ac.AddFrameSize(width, min(droplines * popup->ac.GetLineCy(), popup->ac.GetTotalCy())).cy;
Rect rt = RectC(x, bottom, width, h);
Rect area = Ctrl::GetWorkArea(Point(x, top));
bool up = false;
if(rt.bottom > area.bottom) {
up = true;
rt.top = top - h;
rt.bottom = rt.top + h;
}
if(up) {
popup->SetRect(Rect(rt.left, rt.bottom - 1, rt.right, rt.bottom));
popup->Add(popup->ac.TopPos(0, rt.Height()).LeftPos(0, rt.Width()));
}
else {
popup->SetRect(Rect(rt.left, rt.top, rt.right, rt.top + 1));
popup->Add(popup->ac.BottomPos(0, rt.Height()).LeftPos(0, rt.Width()));
}
if(GUI_PopUpEffect()) {
popup->ac.CenterCursor();
popup->PopUp(owner, true, true, GUI_DropShadows());
popup->ac.SetFocus();
Ctrl::ProcessEvents();
Animate(*popup, rt, GUIEFFECT_SLIDE);
}
if(popup && !popup->IsOpen()) {
popup->SetRect(rt);
if(!popup->IsOpen())
popup->PopUp(owner, true, true, GUI_DropShadows());
popup->ac.CenterCursor();
popup->ac.SetFocus();
}
inpopup--;
}
void PopUpList::PopUp(Ctrl *owner, int width)
{
Rect r = owner->GetScreenRect();
if(width)
r.right = r.left + width;
PopUp(owner, r.left, r.top, r.bottom, r.Width());
}
void PopUpList::PopUp(Ctrl *owner)
{
Rect r = owner->GetScreenRect();
PopUp(owner, r.left, r.top, r.bottom, r.Width());
}
void PopUpList::DoSelect()
{
DoClose();
WhenSelect();
}
void PopUpList::DoCancel()
{
DoClose();
WhenCancel();
}
PopUpList::PopUpList() {
droplines = 16;
inpopup = 0;
linecy = Draw::GetStdFontCy();
display = &StdDisplay();
convert = NULL;
}
PopUpList::~PopUpList() {}
}

View file

@ -15,7 +15,6 @@ void PopUpTable::PopupCancelMode() {
DoClose(); DoClose();
WhenCancel(); WhenCancel();
} }
ArrayCtrl::CancelMode();
} }
void PopUpTable::DoClose() { void PopUpTable::DoClose() {
@ -68,7 +67,6 @@ bool PopUpTable::Key(dword key, int n) {
} }
void PopUpTable::PopUp(Ctrl *owner, int x, int top, int bottom, int width) { void PopUpTable::PopUp(Ctrl *owner, int x, int top, int bottom, int width) {
TimeStop tm;
if(inpopup) if(inpopup)
return; return;
inpopup++; inpopup++;

View file

@ -106,6 +106,10 @@ public:
static const Style& StyleScroll(); static const Style& StyleScroll();
static const Style& StyleNaked(); static const Style& StyleNaked();
static void PaintButton(Draw& w, const Rect& r, const Button::Style& st, int visualstate, bool focus,
const String& label, Font font, const Image& img,
bool monoimg, int accesskey, bool visibaleaccesskeys, bool disabled);
Button& SetStyle(const Style& s); Button& SetStyle(const Style& s);
Button& AutoStyle(); Button& AutoStyle();
@ -126,45 +130,6 @@ public:
Color ButtonMonoColor(int i); Color ButtonMonoColor(int i);
class SpinButtons : public CtrlFrame {
public:
virtual void FrameLayout(Rect& r);
virtual void FrameAddSize(Size& sz);
virtual void FrameAdd(Ctrl& ctrl);
virtual void FrameRemove();
public:
struct Style : ChStyle<Style> {
Button::Style inc;
Button::Style dec;
int width;
int over;
bool onsides;
};
private:
bool visible;
const Style *style;
public:
Button inc;
Button dec;
void Show(bool s = true);
bool IsVisible() const { return visible; }
static const Style& StyleDefault();
static const Style& StyleOnSides();
SpinButtons& SetStyle(const Style& s);
SpinButtons& OnSides(bool b = true) { return SetStyle(b ? StyleOnSides() : StyleDefault()); }
bool IsOnSides() const { return style->onsides; }
SpinButtons();
virtual ~SpinButtons();
};
class Option : public Pusher { class Option : public Pusher {
public: public:
virtual void Paint(Draw& draw); virtual void Paint(Draw& draw);
@ -183,13 +148,13 @@ protected:
protected: protected:
Image edge, edged; Image edge, edged;
int option; int option;
bool switchimage; bool switchimage:1;
bool threestate; bool threestate:1;
bool notnull; bool notnull:1;
bool blackedge; bool blackedge:1;
bool showlabel; bool showlabel:1;
bool box; bool box:1;
bool autobox; bool autobox:1;
Color color; Color color;
void AutoSync(); void AutoSync();
@ -302,10 +267,10 @@ public:
struct Case { struct Case {
String label; String label;
Value value; Value value;
int accesskey = 0;
bool enabled = true;
int gap = 0;
Rect16 rect = Rect16(0, 0, 0, 0); Rect16 rect = Rect16(0, 0, 0, 0);
int accesskey = 0;
int gap = 0;
bool enabled = true;
}; };
private: private:
@ -406,3 +371,70 @@ public:
DataPusher(const Convert& convert, const Display& display = StdDisplay()); // deprecated DataPusher(const Convert& convert, const Display& display = StdDisplay()); // deprecated
DataPusher(const Display& display); // deprecated DataPusher(const Display& display); // deprecated
}; };
class SpinButtons : public CtrlFrame {
public:
virtual void FrameLayout(Rect& r);
virtual void FrameAddSize(Size& sz);
virtual void FrameAdd(Ctrl& ctrl);
virtual void FrameRemove();
public:
struct Style : ChStyle<Style> {
Button::Style inc;
Button::Style dec;
int width;
int over;
bool onsides;
};
private:
bool visible;
const Style *style;
public:
Button inc;
Button dec;
void Show(bool s = true);
bool IsVisible() const { return visible; }
static const Style& StyleDefault();
static const Style& StyleOnSides();
SpinButtons& SetStyle(const Style& s);
SpinButtons& OnSides(bool b = true) { return SetStyle(b ? StyleOnSides() : StyleDefault()); }
bool IsOnSides() const { return style->onsides; }
SpinButtons();
virtual ~SpinButtons();
};
struct VirtualButtons {
virtual int ButtonCount() const;
virtual Rect ButtonRect(int i) const;
virtual const Button::Style& ButtonStyle(int i) const;
virtual Image ButtonImage(int i) const;
virtual bool ButtonMono(int i) const;
virtual bool ButtonEnabled(int i) const;
virtual void ButtonPush(int i);
virtual void ButtonRepeat(int i);
virtual void ButtonAction(int i);
int8 pushi = -1;
int8 mi = -1;
bool buttons_capture = false;
int FindButton(Point p) const;
void EndPush(Ctrl *ctrl);
void ButtonsCancelMode();
bool ButtonsMouseEvent(Ctrl *ctrl, int event, Point p);
void PaintButtons(Draw& w, Ctrl *ctrl);
int ButtonVisualState(Ctrl *ctrl, int i);
void RefreshButton(Ctrl *ctrl, int i);
};

View file

@ -45,26 +45,11 @@ ScrollBar::ScrollBar() {
jump = false; jump = false;
track = true; track = true;
horz = false; horz = false;
push = light = -1;
thumbsize = 8; thumbsize = 8;
thumbpos = 0; thumbpos = 0;
push = light = -1;
Add(prev);
Add(prev2);
Add(next);
Add(next2);
NoWantFocus(); NoWantFocus();
prev.ScrollStyle().NoWantFocus().Transparent();
prev.WhenPush = prev.WhenRepeat = callback(this, &ScrollBar::PrevLine);
prev.WhenPush << Proxy(WhenLeftClick);
prev2.ScrollStyle().NoWantFocus().Transparent();
prev2.WhenRepeat = prev.WhenRepeat;
prev2.WhenPush = prev.WhenPush;
next.ScrollStyle().NoWantFocus().Transparent();
next.WhenPush = next.WhenRepeat = callback(this, &ScrollBar::NextLine);
next.WhenPush << Proxy(WhenLeftClick);
next2.ScrollStyle().NoWantFocus().Transparent();
next2.WhenRepeat = next.WhenRepeat;
next2.WhenPush = next.WhenPush;
style = NULL; style = NULL;
SetStyle(StyleDefault()); SetStyle(StyleDefault());
BackPaint(); BackPaint();
@ -73,6 +58,93 @@ ScrollBar::ScrollBar() {
ScrollBar::~ScrollBar() {} ScrollBar::~ScrollBar() {}
int ScrollBar::ButtonCount() const
{
return BUTTONCOUNT;
}
void ScrollBar::Layout() {
Size sz = GetSize();
Set(pagepos);
Refresh();
}
Rect ScrollBar::ButtonRect(int i) const
{
Size sz = GetSize();
if(IsHorz()) {
int cc = sz.cx > (3 + style->isleft2 + style->isright2) * style->arrowsize ? style->arrowsize : 0;
if(i == PREV)
return RectC(0, 0, cc, sz.cy);
if(i == NEXT)
return RectC(sz.cx - cc, 0, cc, sz.cy);
if(i == PREV2 && style->isleft2)
return RectC(sz.cx - 2 * cc, 0, cc, sz.cy);
if(i == NEXT2 && style->isright2)
return RectC(cc, 0, cc, sz.cy);
}
else {
int cc = sz.cy > (3 + style->isup2 + style->isdown2) * style->arrowsize ? style->arrowsize : 0;
if(i == PREV)
return RectC(0, 0, sz.cx, cc);
if(i == NEXT)
return RectC(0, sz.cy - cc, sz.cx, cc);
if(i == PREV2 && style->isup2)
return RectC(0, sz.cy - 2 * cc, sz.cx, cc);
if(i == NEXT2 && style->isdown2)
return RectC(0, cc, sz.cx, cc);
}
return Null;
}
bool ScrollBar::ButtonEnabled(int i) const
{
return is_active || !autodisable;
}
void ScrollBar::ButtonPush(int i)
{
WhenLeftClick();
ButtonRepeat(i);
}
void ScrollBar::ButtonRepeat(int i)
{
if(i == PREV)
PrevLine();
if(i == NEXT)
NextLine();
if(i == PREV2)
PrevPage();
if(i == NEXT2)
NextPage();
}
const Button::Style& ScrollBar::ButtonStyle(int i) const
{
if(IsHorz()) {
if(i == PREV)
return style->left;
if(i == NEXT)
return style->right;
if(i == PREV2)
return style->left2;
if(i == NEXT2)
return style->right2;
}
else {
if(i == PREV)
return style->up;
if(i == NEXT)
return style->down;
if(i == PREV2)
return style->up2;
if(i == NEXT2)
return style->down2;
}
return Button::StyleNormal();
}
Rect ScrollBar::Slider(int& cc) const Rect ScrollBar::Slider(int& cc) const
{ {
Size sz = GetSize(); Size sz = GetSize();
@ -135,20 +207,21 @@ Rect ScrollBar::GetPartRect(int p) const {
return h; return h;
} }
void ScrollBar::Paint(Draw& w) { void ScrollBar::Paint(Draw& w)
{
w.DrawRect(GetSize(), style->bgcolor); w.DrawRect(GetSize(), style->bgcolor);
int cc; int cc;
Size sz = style->through ? GetSize() : Slider(cc).GetSize(); Size sz = style->through ? GetSize() : Slider(cc).GetSize();
light = GetMousePart(); light = GetMousePart();
int p = push; int p = push;
if(!HasCapture()) if(!HasCapture() || buttons_capture)
p = -1; p = -1;
const Value *hl[] = { style->hlower, style->hupper, style->hthumb }; const Value *hl[] = { style->hlower, style->hupper, style->hthumb };
const Value *vl[] = { style->vupper, style->vlower, style->vthumb }; const Value *vl[] = { style->vupper, style->vlower, style->vthumb };
const Value **l = IsHorz() ? hl : vl; const Value **l = IsHorz() ? hl : vl;
if(prev.IsShowEnabled()) { if(is_active || !autodisable) {
for(int i = 0; i < 3; i++) { for(int i = 0; i < 3; i++) {
Rect pr = GetPartRect(i); Rect pr = GetPartRect(i);
if(i != 2) { if(i != 2) {
@ -156,12 +229,12 @@ void ScrollBar::Paint(Draw& w) {
pr = style->through ? GetSize() : Slider(); pr = style->through ? GetSize() : Slider();
} }
if(i != 2 || thumbsize >= style->thumbmin) 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) if(i != 2)
w.End(); w.End();
} }
} }
else else {
if(style->through) if(style->through)
ChPaint(w, sz, l[0][CTRL_DISABLED]); ChPaint(w, sz, l[0][CTRL_DISABLED]);
else else
@ -169,6 +242,8 @@ void ScrollBar::Paint(Draw& w) {
ChPaint(w, cc, 0, sz.cx, sz.cy, l[0][CTRL_DISABLED]); ChPaint(w, cc, 0, sz.cx, sz.cy, l[0][CTRL_DISABLED]);
else else
ChPaint(w, 0, cc, sz.cx, sz.cy, l[0][CTRL_DISABLED]); ChPaint(w, 0, cc, sz.cx, sz.cy, l[0][CTRL_DISABLED]);
}
PaintButtons(w, this);
} }
@ -216,6 +291,13 @@ void ScrollBar::Drag(Point p) {
Position(); Position();
} }
Image ScrollBar::MouseEvent(int event, Point p, int zdelta, dword keyflags)
{
if(ButtonsMouseEvent(this, event, p))
return Image::Arrow();
return Ctrl::MouseEvent(event, p, zdelta, keyflags);
}
void ScrollBar::LeftDown(Point p, dword) { void ScrollBar::LeftDown(Point p, dword) {
push = GetMousePart(); push = GetMousePart();
LLOG("ScrollBar::LeftDown(" << p << ")"); LLOG("ScrollBar::LeftDown(" << p << ")");
@ -243,6 +325,7 @@ void ScrollBar::LeftDown(Point p, dword) {
NextPage(); NextPage();
} }
SetCapture(); SetCapture();
buttons_capture = false;
Refresh(); Refresh();
WhenLeftClick(); WhenLeftClick();
} }
@ -289,6 +372,7 @@ void ScrollBar::MouseWheel(Point p, int zdelta, dword keyflags)
void ScrollBar::CancelMode() { void ScrollBar::CancelMode() {
push = light = -1; push = light = -1;
ButtonsCancelMode();
} }
bool ScrollBar::Set(int apagepos) { bool ScrollBar::Set(int apagepos) {
@ -330,19 +414,16 @@ bool ScrollBar::Set(int apagepos) {
void ScrollBar::Set(int _pagepos, int _pagesize, int _totalsize) { void ScrollBar::Set(int _pagepos, int _pagesize, int _totalsize) {
pagesize = _pagesize; pagesize = _pagesize;
totalsize = _totalsize; totalsize = _totalsize;
is_active = totalsize > pagesize && pagesize > 0;
bool active = totalsize > pagesize && pagesize > 0;
if(active != is_active) {
Refresh();
is_active = active;
}
if(autohide && is_active != IsShown()) { if(autohide && is_active != IsShown()) {
Show(is_active); Show(is_active);
WhenVisibility(); WhenVisibility();
} }
if(autodisable) {
if(prev.IsEnabled() != is_active)
Refresh();
prev.Enable(is_active);
next.Enable(is_active);
prev2.Enable(is_active);
next2.Enable(is_active);
}
Set(_pagepos); Set(_pagepos);
} }
@ -472,38 +553,6 @@ bool ScrollBar::HorzKey(dword key) {
return true; return true;
} }
void ScrollBar::Layout() {
Size sz = GetSize();
if(IsHorz()) {
prev.SetStyle(style->left);
next.SetStyle(style->right);
prev2.SetStyle(style->left2);
next2.SetStyle(style->right2);
int cc = sz.cx > (3 + style->isleft2 + style->isright2) * style->arrowsize ? style->arrowsize : 0;
prev.SetRect(0, 0, cc, sz.cy);
next.SetRect(sz.cx - cc, 0, cc, sz.cy);
prev2.Show(style->isleft2);
prev2.SetRect(sz.cx - 2 * cc, 0, cc, sz.cy);
next2.Show(style->isright2);
next2.SetRect(cc, 0, cc, sz.cy);
}
else {
prev.SetStyle(style->up);
next.SetStyle(style->down);
prev2.SetStyle(style->up2);
next2.SetStyle(style->down2);
int cc = sz.cy > (3 + style->isup2 + style->isdown2) * style->arrowsize ? style->arrowsize : 0;
prev.SetRect(0, 0, sz.cx, cc);
next.SetRect(0, sz.cy - cc, sz.cx, cc);
prev2.Show(style->isup2);
prev2.SetRect(0, sz.cy - 2 * cc, sz.cx, cc);
next2.Show(style->isdown2);
next2.SetRect(0, cc, sz.cx, cc);
}
Set(pagepos);
Refresh();
}
bool ScrollBar::ScrollInto(int pos, int _linesize) { bool ScrollBar::ScrollInto(int pos, int _linesize) {
int new_pos = pagepos; int new_pos = pagepos;
if(pos > new_pos + pagesize - _linesize) if(pos > new_pos + pagesize - _linesize)
@ -560,14 +609,7 @@ ScrollBar& ScrollBar::AutoHide(bool b) {
ScrollBar& ScrollBar::AutoDisable(bool b) { ScrollBar& ScrollBar::AutoDisable(bool b) {
autodisable = b; autodisable = b;
if(!b) { Refresh();
if(!prev.IsEnabled())
Refresh();
prev.Enable();
prev2.Enable();
next.Enable();
next2.Enable();
}
return *this; return *this;
} }

View file

@ -1,4 +1,4 @@
class ScrollBar : public FrameCtrl<Ctrl> { class ScrollBar : public FrameCtrl<Ctrl>, private VirtualButtons {
public: public:
virtual void Layout(); virtual void Layout();
virtual Size GetStdSize() const; virtual Size GetStdSize() const;
@ -15,6 +15,16 @@ public:
virtual void FrameLayout(Rect& r); virtual void FrameLayout(Rect& r);
virtual void FrameAddSize(Size& sz); virtual void FrameAddSize(Size& sz);
virtual Image MouseEvent(int event, Point p, int zdelta, dword keyflags);
virtual int ButtonCount() const;
virtual Rect ButtonRect(int i) const;
virtual const Button::Style& ButtonStyle(int i) const;
virtual bool ButtonEnabled(int i) const;
virtual void ButtonPush(int i);
virtual void ButtonRepeat(int i);
public: public:
struct Style : ChStyle<Style> { struct Style : ChStyle<Style> {
Color bgcolor; Color bgcolor;
@ -30,19 +40,20 @@ public:
private: private:
int thumbpos; int thumbpos;
int thumbsize; int thumbsize;
bool horz:1;
bool jump:1;
bool track:1;
int delta; int delta;
int8 push;
int8 light;
Button prev, prev2, next, next2; enum { PREV, PREV2, NEXT, NEXT2, BUTTONCOUNT };
// Button prev, prev2, next, next2;
int pagepos; int pagepos;
int pagesize; int pagesize;
int totalsize; int totalsize;
int linesize; int linesize;
int minthumb; int minthumb;
int8 push;
int8 light;
bool horz:1;
bool jump:1;
bool track:1;
bool autohide:1; bool autohide:1;
bool autodisable:1; bool autodisable:1;
bool is_active:1; bool is_active:1;

View file

@ -2,12 +2,73 @@
namespace Upp { namespace Upp {
CH_COLOR(LabelBoxColor, SColorShadow());
CH_COLOR(LabelBoxTextColor, SColorText());
CH_COLOR(LabelBoxDisabledTextColor, SColorDisabled());
StaticText& StaticText::SetFont(Font font)
{
SetFontAttr(ATTR_FONT, font);
Refresh();
return *this;
}
StaticText& StaticText::SetInk(Color color)
{
SetColorAttr(ATTR_INK, color);
Refresh();
return *this;
}
StaticText& StaticText::SetAlign(int align)
{
SetIntAttr(ATTR_ALIGN, align);
Refresh();
return *this;
}
StaticText& StaticText::SetImage(const Image& img, int spc)
{
CreateAttr<Image>(ATTR_IMAGE) = img;
if(spc)
SetIntAttr(ATTR_IMAGE_SPC, spc);
Refresh();
return *this;
}
StaticText& StaticText::SetText(const char *s)
{
text = s;
Refresh();
return *this;
}
void StaticText::MakeDrawLabel(DrawLabel& l) const
{
l.text = text;
l.font = Nvl(GetFontAttr(ATTR_FONT), StdFont());
l.ink = Nvl(GetColorAttr(ATTR_INK), SColorText());
l.align = Nvl(GetIntAttr(ATTR_ALIGN), ALIGN_LEFT);
l.limg = GetAttr<Image>(ATTR_IMAGE);
l.lspc = Nvl(GetIntAttr(ATTR_IMAGE_SPC), 0);
l.disabled = !IsShowEnabled();
l.accesskey = accesskey;
if(dynamic_cast<const LabelBox *>(this)) {
l.valign = ALIGN_TOP;
l.disabledink = LabelBoxDisabledTextColor();
}
}
void StaticText::Paint(Draw& w) void StaticText::Paint(Draw& w)
{ {
DrawLabel l;
MakeDrawLabel(l);
Size sz = GetSize(); Size sz = GetSize();
if(!IsTransparent()) if(!IsTransparent())
w.DrawRect(0, 0, sz.cx, sz.cy, SColorFace); w.DrawRect(0, 0, sz.cx, sz.cy, SColorFace);
PaintLabel(this, w, 0, 0, sz.cx, sz.cy, !IsShowEnabled(), false, false, VisibleAccessKeys());
l.Paint(this, w, sz, VisibleAccessKeys());
} }
Size StaticText::GetMinSize() const Size StaticText::GetMinSize() const
@ -15,8 +76,11 @@ Size StaticText::GetMinSize() const
return GetLabelSize(); return GetLabelSize();
} }
void StaticText::LabelUpdate() { Size StaticText::GetLabelSize() const
Refresh(); {
DrawLabel l;
MakeDrawLabel(l);
return l.GetSize();
} }
StaticText::StaticText() StaticText::StaticText()
@ -24,13 +88,17 @@ StaticText::StaticText()
NoWantFocus(); NoWantFocus();
IgnoreMouse(); IgnoreMouse();
Transparent(); Transparent();
SetAlign(ALIGN_LEFT); }
StaticText::~StaticText()
{
DeleteAttr<Image>(ATTR_IMAGE);
} }
Label& Label::SetText(const char *text) Label& Label::SetText(const char *text)
{ {
LabelBase::SetText(text); accesskey = 0;
lbl.accesskey = 0; StaticText::SetText(text);
noac = false; noac = false;
return *this; return *this;
} }
@ -38,14 +106,13 @@ Label& Label::SetText(const char *text)
Label& Label::SetLabel(const char *_text) Label& Label::SetLabel(const char *_text)
{ {
String text; String text;
int accesskey = ExtractAccessKey(_text, text); accesskey = ExtractAccessKey(_text, text);
LabelBase::SetText(text); StaticText::SetText(text);
lbl.accesskey = accesskey;
return *this; return *this;
} }
bool Label::HotKey(dword key) { bool Label::HotKey(dword key) {
if(CompareAccessKey(lbl.accesskey, key)) { if(CompareAccessKey(accesskey, key)) {
IterateFocusForward(this, GetParent()); IterateFocusForward(this, GetParent());
return true; return true;
} }
@ -54,7 +121,7 @@ bool Label::HotKey(dword key) {
dword Label::GetAccessKeys() const dword Label::GetAccessKeys() const
{ {
return AccessKeyBit(lbl.accesskey); return AccessKeyBit(accesskey);
} }
void Label::AssignAccessKeys(dword used) void Label::AssignAccessKeys(dword used)
@ -62,12 +129,12 @@ void Label::AssignAccessKeys(dword used)
if(noac) if(noac)
return; return;
Ctrl *next = GetNext(); Ctrl *next = GetNext();
if(!lbl.accesskey && next && next->IsInitFocus()) { if(!accesskey && next && next->IsInitFocus()) {
next->AssignAccessKeys(used); next->AssignAccessKeys(used);
if(!next->GetAccessKeysDeep()) { if(!next->GetAccessKeysDeep()) {
lbl.accesskey = ChooseAccessKey(GetText(), used); accesskey = ChooseAccessKey(text, used);
if(lbl.accesskey) Refresh(); if(accesskey) Refresh();
used |= AccessKeyBit(lbl.accesskey); used |= AccessKeyBit(accesskey);
} }
} }
Ctrl::AssignAccessKeys(used); Ctrl::AssignAccessKeys(used);
@ -79,16 +146,10 @@ Label::Label() {
Label::~Label() {} Label::~Label() {}
CH_COLOR(LabelBoxColor, SColorShadow());
CH_COLOR(LabelBoxTextColor, SColorText());
CH_COLOR(LabelBoxDisabledTextColor, SColorDisabled());
LabelBox::LabelBox() LabelBox::LabelBox()
{ {
color = Null; color = Null;
LabelBase::SetInk(LabelBoxTextColor(), LabelBoxDisabledTextColor()); SetInk(LabelBoxTextColor());
SetVAlign(ALIGN_TOP);
} }
void LabelBox::AssignAccessKeys(dword used) void LabelBox::AssignAccessKeys(dword used)
@ -192,7 +253,9 @@ void LabelBox::Paint(Draw& w)
Size lsz = GetLabelSize(); Size lsz = GetLabelSize();
int d = lsz.cy >> 1; int d = lsz.cy >> 1;
int ty = sz.cy < 2 * Draw::GetStdFontCy() ? (sz.cy - lsz.cy) / 2 : 0; int ty = sz.cy < 2 * Draw::GetStdFontCy() ? (sz.cy - lsz.cy) / 2 : 0;
Size ts = PaintLabel(w, d + DPI(2), ty, sz.cx, lsz.cy, !IsShowEnabled(), false, false, VisibleAccessKeys()); DrawLabel l;
MakeDrawLabel(l);
Size ts = l.Paint(this, w, d + DPI(2), ty, sz.cx, lsz.cy);
w.Begin(); w.Begin();
w.ExcludeClip(d, ty, ts.cx + DPI(4), ts.cy); w.ExcludeClip(d, ty, ts.cx + DPI(4), ts.cy);
PaintLabelBox(w, sz, color, d); PaintLabelBox(w, sz, color, d);

View file

@ -1,19 +1,38 @@
class StaticText : public Ctrl, public LabelBase { class StaticText : public Ctrl {
public: public:
virtual void Paint(Draw& w); virtual void Paint(Draw& w);
virtual Size GetMinSize() const; virtual Size GetMinSize() const;
virtual void LabelUpdate();
enum {
ATTR_INK = Ctrl::ATTR_LAST,
ATTR_FONT,
ATTR_ALIGN,
ATTR_IMAGE,
ATTR_IMAGE_SPC,
ATTR_LAST,
};
protected:
String text;
int accesskey = 0;
void MakeDrawLabel(DrawLabel& l) const;
Size GetLabelSize() const;
public: public:
StaticText& SetFont(Font font) { LabelBase::SetFont(font); return *this; } StaticText& SetFont(Font font);
StaticText& SetInk(Color color) { LabelBase::SetInk(color); return *this; } StaticText& SetInk(Color color);
StaticText& SetAlign(int align) { LabelBase::SetAlign(align); return *this; } StaticText& SetAlign(int align);
StaticText& SetImage(const Image& img, int spc = 0) { LabelBase::SetImage(img, spc); return *this; } StaticText& AlignLeft() { return SetAlign(ALIGN_LEFT); }
StaticText& SetText(const char *text) { LabelBase::SetText(text); return *this; } StaticText& AlignCenter() { return SetAlign(ALIGN_CENTER); }
StaticText& AlignRight() { return SetAlign(ALIGN_RIGHT); }
StaticText& SetImage(const Image& img, int spc = 0);
StaticText& SetText(const char *text);
StaticText& operator=(const char *s) { SetText(s); return *this; } StaticText& operator=(const char *s) { SetText(s); return *this; }
StaticText(); StaticText();
~StaticText();
}; };
class Label : public StaticText { class Label : public StaticText {

View file

@ -299,6 +299,7 @@ public:
virtual void Layout(); virtual void Layout();
virtual void RefreshLine(int i); virtual void RefreshLine(int i);
virtual Font GetPreeditFont(); virtual Font GetPreeditFont();
virtual Rect GetCaret() const;
protected: protected:
virtual void SetSb(); virtual void SetSb();
@ -507,6 +508,8 @@ public:
virtual void DragLeave(); virtual void DragLeave();
virtual void LeftDrag(Point p, dword flags); virtual void LeftDrag(Point p, dword flags);
virtual Rect GetCaret() const;
protected: protected:
virtual void ClearLines(); virtual void ClearLines();
virtual void InsertLines(int line, int count); virtual void InsertLines(int line, int count);
@ -527,6 +530,7 @@ protected:
ScrollBar sb; ScrollBar sb;
int cx; int cx;
bool updownleave, eofline; bool updownleave, eofline;
Rect caret;
struct Fmt { struct Fmt {
FontInfo fi; FontInfo fi;

View file

@ -0,0 +1,113 @@
#include "CtrlLib.h"
namespace Upp {
int VirtualButtons::ButtonCount() const { return 0; }
Rect VirtualButtons::ButtonRect(int i) const { return Null; }
const Button::Style& VirtualButtons::ButtonStyle(int i) const { return Button::StyleEdge(); }
Image VirtualButtons::ButtonImage(int i) const { return Null; }
bool VirtualButtons::ButtonEnabled(int i) const { return true; }
bool VirtualButtons::ButtonMono(int i) const { return false; }
void VirtualButtons::ButtonPush(int i) {}
void VirtualButtons::ButtonRepeat(int i) {}
void VirtualButtons::ButtonAction(int i) {}
int VirtualButtons::FindButton(Point p) const
{
for(int i = 0; i < ButtonCount(); i++)
if(ButtonRect(i).Contains(p))
return i;
return -1;
}
int VirtualButtons::ButtonVisualState(Ctrl *ctrl, int i)
{
if(ctrl->HasCapture() && !buttons_capture)
return CTRL_NORMAL;
if(ButtonEnabled(i)) {
if(i == pushi)
return CTRL_PRESSED;
if(ctrl->HasMouseIn(ButtonRect(i)))
return CTRL_HOT;
return CTRL_NORMAL;
}
return CTRL_DISABLED;
}
void VirtualButtons::PaintButtons(Draw& w, Ctrl *ctrl)
{
for(int i = 0; i < ButtonCount(); i++) {
Button::PaintButton(w, ButtonRect(i), ButtonStyle(i), ButtonVisualState(ctrl, i), false,
String(), StdFont(), ButtonImage(i),
ButtonMono(i), 0, false, !ButtonEnabled(i));
}
}
void VirtualButtons::EndPush(Ctrl *ctrl)
{
int i = pushi;
pushi = -1;
RefreshButton(ctrl, i);
}
void VirtualButtons::RefreshButton(Ctrl *ctrl, int i)
{
if(i >= 0)
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);
RefreshButton(ctrl, mi = i);
}
switch(event) {
case Ctrl::LEFTDOWN:
case Ctrl::LEFTDOUBLE:
case Ctrl::LEFTTRIPLE:
pushi = i;
if(pushi >= 0) {
ButtonPush(i);
ctrl->SetCapture();
buttons_capture = true;
}
else
EndPush(ctrl);
RefreshButton(ctrl, pushi);
break;
case Ctrl::MOUSEMOVE:
if(ctrl->HasCapture() && i != pushi) {
RefreshButton(ctrl, pushi);
pushi = i;
}
break;
case Ctrl::LEFTREPEAT:
if(i >= 0)
ButtonRepeat(i);
break;
case Ctrl::LEFTUP:
int ii = pushi;
if(ii >= 0) {
EndPush(ctrl);
ctrl->ReleaseCapture();
buttons_capture = false;
ButtonAction(ii);
}
break;
}
return i >= 0;
}
};

View file

@ -9,218 +9,231 @@ topic "Static widgets";
[i448;b42;O9;2 $$8,8#61672508125594000341940100500538:tparam] [i448;b42;O9;2 $$8,8#61672508125594000341940100500538:tparam]
[b42;2 $$9,9#13035079074754324216151401829390:normal] [b42;2 $$9,9#13035079074754324216151401829390:normal]
[2 $$0,0#00000000000000000000000000000000:Default] [2 $$0,0#00000000000000000000000000000000:Default]
[{_}%EN-US [{_}
[s0; [*+150 Static widgets]&] [s0;%% [*+150 Static widgets]&]
[s3;%% &]
[ {{10000@3 [s0;%% [*@(229)4 StaticText]]}}&]
[s3;%% &]
[s1;:StaticText`:`:class: [@(0.0.255)3 class][3 _][*3 StaticText][3 _:_][@(0.0.255)3 public][3 _][*@3;3 C
trl][3 , ][@(0.0.255)3 public][3 _][*@3;3 LabelBase]&]
[s9;%% Static text.&]
[s3; &] [s3; &]
[ {{10000@3 [s0; [*@(229)4 StaticText]]}}&] [s0; &]
[ {{10000F(128)G(128)@1 [s0;%% [* Public Method List]]}}&]
[s3; &] [s3; &]
[s1;:StaticText`:`:class:%- [@(0.0.255)3 class][3 _][*3 StaticText][3 _:_][@(0.0.255)3 public][3 _ [s5;:StaticText`:`:SetFont`(Font`): [@(0.0.255) virtual] [_^StaticText^ StaticText][@(0.0.255) `&
][*@3;3 Ctrl][3 , ][@(0.0.255)3 public][3 _][*@3;3 LabelBase]&]
[s9; Static text.&]
[s3;%- &]
[s0;%- &]
[ {{10000F(128)G(128)@1 [s0; [* Public Method List]]}}&]
[s3;%- &]
[s5;:StaticText`:`:SetFont`(Font`):%- [@(0.0.255) virtual] [_^StaticText^ StaticText][@(0.0.255) `&
]_[* SetFont]([_^Font^ Font]_[*@3 font])&] ]_[* SetFont]([_^Font^ Font]_[*@3 font])&]
[s2; Sets the [%-*@3 font] of text.&] [s2;%% Sets the [%-*@3 font] of text.&]
[s3; &] [s3;%% &]
[s4;%- &] [s4; &]
[s5;:StaticText`:`:SetInk`(Color`):%- [@(0.0.255) virtual] [_^StaticText^ StaticText][@(0.0.255) `& [s5;:StaticText`:`:SetInk`(Color`): [@(0.0.255) virtual] [_^StaticText^ StaticText][@(0.0.255) `&
]_[* SetInk]([_^Color^ Color]_[*@3 color])&] ]_[* SetInk]([_^Color^ Color]_[*@3 color])&]
[s2; Sets the [%-*@3 color] of text.&] [s2;%% Sets the [%-*@3 color] of text.&]
[s3; &] [s3;%% &]
[s4;%- &] [s4; &]
[s5;:StaticText`:`:SetAlign`(int`):%- [@(0.0.255) virtual] [_^StaticText^ StaticText][@(0.0.255) `& [s5;:StaticText`:`:SetAlign`(int`): [@(0.0.255) virtual] [_^StaticText^ StaticText][@(0.0.255) `&
]_[* SetAlign]([@(0.0.255) int]_[*@3 align])&] ]_[* SetAlign]([@(0.0.255) int]_[*@3 align])&]
[s2; Sets alignment [%-*@3 align]. Allowed values are ALIGN`_LEFT, [s2;%% Sets alignment [%-*@3 align]. Allowed values are ALIGN`_LEFT,
ALIGN`_CENTER, ALIGN`_RIGHT.&] ALIGN`_CENTER, ALIGN`_RIGHT.&]
[s3;%% &]
[s4; &]
[s5;:Upp`:`:StaticText`:`:AlignLeft`(`): [_^Upp`:`:StaticText^ StaticText][@(0.0.255) `&]_
[* AlignLeft]()&]
[s2;%% Same as SetAlign(ALIGN`_LEFT).&]
[s3; &] [s3; &]
[s4;%- &] [s4; &]
[s5;:StaticText`:`:SetImage`(const Image`&`,int`):%- [@(0.0.255) virtual] [s5;:Upp`:`:StaticText`:`:AlignCenter`(`): [_^Upp`:`:StaticText^ StaticText][@(0.0.255) `&
]_[* AlignCenter]()&]
[s2;%% Same as SetAlign(ALIGN`_CENTER).&]
[s3; &]
[s4; &]
[s5;:Upp`:`:StaticText`:`:AlignRight`(`): [_^Upp`:`:StaticText^ StaticText][@(0.0.255) `&
]_[* AlignRight]()&]
[s2;%% Same as SetAlign(ALIGN`_RIGHT).&]
[s3; &]
[s4; &]
[s5;:StaticText`:`:SetImage`(const Image`&`,int`): [@(0.0.255) virtual]
[_^StaticText^ StaticText][@(0.0.255) `&]_[* SetImage]([@(0.0.255) const]_[_^Image^ Image][@(0.0.255) `& [_^StaticText^ StaticText][@(0.0.255) `&]_[* SetImage]([@(0.0.255) const]_[_^Image^ Image][@(0.0.255) `&
]_[*@3 img], [@(0.0.255) int]_[*@3 spc]_`=_[@3 0])&] ]_[*@3 img], [@(0.0.255) int]_[*@3 spc]_`=_[@3 0])&]
[s2; Sets the Image to be displayed before the text. [%-*@3 spc] is [s2;%% Sets the Image to be displayed before the text. [%-*@3 spc]
space between the text and Image.&] is space between the text and Image.&]
[s3; &] [s3;%% &]
[s4;%- &] [s4; &]
[s5;:StaticText`:`:SetText`(const char`*`):%- [@(0.0.255) virtual] [s5;:StaticText`:`:SetText`(const char`*`): [@(0.0.255) virtual] [_^StaticText^ StaticTex
[_^StaticText^ StaticText][@(0.0.255) `&]_[* SetText]([@(0.0.255) const]_[@(0.0.255) char]_ t][@(0.0.255) `&]_[* SetText]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 text])&]
`*[*@3 text])&] [s5;:StaticText`:`:operator`=`(const char`*`): [_^StaticText^ StaticText][@(0.0.255) `&]_
[s5;:StaticText`:`:operator`=`(const char`*`):%- [_^StaticText^ StaticText][@(0.0.255) `& [* operator`=]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 s])&]
]_[* operator`=]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 s])&] [s2;%% Sets [%-*@3 text]. `"`\1`" at the beginning of text activates
[s2; Sets [%-*@3 text]. `"`\1`" at the beginning of text activates
QTF.&] QTF.&]
[s3; &] [s3;%% &]
[s0;%% &]
[s0;%% &]
[s0; &] [s0; &]
[s0; &] [ {{10000@3 [s0;%% [*@(229)4 Label]]}}&]
[s0;%- &] [s3;%% &]
[ {{10000@3 [s0; [*@(229)4 Label]]}}&] [s1;:Label`:`:class: [@(0.0.255)3 class][3 _][*3 Label][3 _:_][@(0.0.255)3 public][3 _][*@3;3 Static
[s3; &] Text]&]
[s1;:Label`:`:class:%- [@(0.0.255)3 class][3 _][*3 Label][3 _:_][@(0.0.255)3 public][3 _][*@3;3 Stat [s9;%% Generally used to label other widgets. Differs from StaticText
icText]&]
[s9; Generally used to label other widgets. Differs from StaticText
by implementing hotkey processing. Hotkeys are assigned automatically by implementing hotkey processing. Hotkeys are assigned automatically
by U`+`+ library, however they can also by preassigned using by U`+`+ library, however they can also by preassigned using
`'`&`' character.&] `'`&`' character.&]
[s3;%- &] [s3; &]
[s0;%- &] [s0; &]
[ {{10000F(128)G(128)@1 [s0; [* Public Method List]]}}&] [ {{10000F(128)G(128)@1 [s0;%% [* Public Method List]]}}&]
[s3;%- &] [s3; &]
[s5;:Label`:`:SetText`(const char`*`):%- [@(0.0.255) virtual] [_^Label^ Label][@(0.0.255) `& [s5;:Label`:`:SetText`(const char`*`): [@(0.0.255) virtual] [_^Label^ Label][@(0.0.255) `&]_
]_[* SetText]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 text])&] [* SetText]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 text])&]
[s5;:Label`:`:operator`=`(const char`*`):%- [@(0.0.255) virtual] [_^Label^ Label][@(0.0.255) `& [s5;:Label`:`:operator`=`(const char`*`): [@(0.0.255) virtual] [_^Label^ Label][@(0.0.255) `&
]_[* operator`=]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 s])&] ]_[* operator`=]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 s])&]
[s2; Sets the text. Ignores `'`&`' used to mark hotkeys.&] [s2;%% Sets the text. Ignores `'`&`' used to mark hotkeys.&]
[s3; &] [s3;%% &]
[s4;%- &]
[s5;:Label`:`:SetLabel`(const char`*`):%- [_^Label^ Label][@(0.0.255) `&]_[* SetLabel]([@(0.0.255) c
onst]_[@(0.0.255) char]_`*[*@3 lbl])&]
[s2; Sets the text, `'`&`' marks hotkeys.&]
[s3; &]
[s0; &]
[s0; &]
[s0;%- &]
[ {{10000@3 [s0; [*@(229)4 LabelBox]]}}&]
[s3; &]
[s1;:LabelBox`:`:class:%- [@(0.0.255)3 class][3 _][*3 LabelBox][3 _:_][@(0.0.255)3 public][3 _][*@3;3 L
abel]&]
[s9; Rectangular static widget used to visually group other widgets.&]
[s3;%- &]
[s0;%- &]
[ {{10000F(128)G(128)@1 [s0; [* Public Method List]]}}&]
[s3;%- &]
[s5;:LabelBox`:`:operator`=`(const char`*`):%- [@(0.0.255) virtual]
[_^LabelBox^ LabelBox][@(0.0.255) `&]_[* operator`=]([@(0.0.255) const]_[@(0.0.255) char]_`*
[*@3 s])&]
[s2; Assigns the text of LabelBox.&]
[s3; &]
[s4; &] [s4; &]
[s5;:LabelBox`:`:SetColor`(Color`):%- [_^LabelBox^ LabelBox][@(0.0.255) `&]_[* SetColor]([_^Color^ C [s5;:Label`:`:SetLabel`(const char`*`): [_^Label^ Label][@(0.0.255) `&]_[* SetLabel]([@(0.0.255) c
olor]_[*@3 c])&] onst]_[@(0.0.255) char]_`*[*@3 lbl])&]
[s2; Sets the color of LabelBox.&] [s2;%% Sets the text, `'`&`' marks hotkeys.&]
[s3;%% &]
[s0;%% &]
[s0;%% &]
[s0; &]
[ {{10000@3 [s0;%% [*@(229)4 LabelBox]]}}&]
[s3;%% &]
[s1;:LabelBox`:`:class: [@(0.0.255)3 class][3 _][*3 LabelBox][3 _:_][@(0.0.255)3 public][3 _][*@3;3 L
abel]&]
[s9;%% Rectangular static widget used to visually group other widgets.&]
[s3; &] [s3; &]
[s0; &] [s0; &]
[s0;%- &] [ {{10000F(128)G(128)@1 [s0;%% [* Public Method List]]}}&]
[ {{10000@3 [s0; [*@(229)4 ParentCtrl]]}}&]
[s3; &] [s3; &]
[s1;:ParentCtrl`:`:class:%- [@(0.0.255)3 class][3 _][*3 ParentCtrl][3 _:_][@(0.0.255)3 public][3 _ [s5;:LabelBox`:`:operator`=`(const char`*`): [@(0.0.255) virtual] [_^LabelBox^ LabelBox][@(0.0.255) `&
][*@3;3 Ctrl]&] ]_[* operator`=]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 s])&]
[s9; This class is supposed to be used as logical parent in situation [s2;%% Assigns the text of LabelBox.&]
[s3;%% &]
[s4;%% &]
[s5;:LabelBox`:`:SetColor`(Color`): [_^LabelBox^ LabelBox][@(0.0.255) `&]_[* SetColor]([_^Color^ C
olor]_[*@3 c])&]
[s2;%% Sets the color of LabelBox.&]
[s3;%% &]
[s0;%% &]
[s0; &]
[ {{10000@3 [s0;%% [*@(229)4 ParentCtrl]]}}&]
[s3;%% &]
[s1;:ParentCtrl`:`:class: [@(0.0.255)3 class][3 _][*3 ParentCtrl][3 _:_][@(0.0.255)3 public][3 _][*@3;3 C
trl]&]
[s9;%% This class is supposed to be used as logical parent in situation
when more widgets are to be grouped together. The only difference when more widgets are to be grouped together. The only difference
from Ctrl is that ParentCtrl activates Transparent in constructor.&] from Ctrl is that ParentCtrl activates Transparent in constructor.&]
[s3; &] [s3;%% &]
[s0;%% &]
[s0;%% &]
[s0; &] [s0; &]
[s0; &] [ {{10000@3 [s0;%% [*@(229)4 StaticRect]]}}&]
[s0;%- &] [s3;%% &]
[ {{10000@3 [s0; [*@(229)4 StaticRect]]}}&] [s1;:StaticRect`:`:class: [@(0.0.255)3 class][3 _][*3 StaticRect][3 _:_][@(0.0.255)3 public][3 _][*@3;3 C
[s3; &]
[s1;:StaticRect`:`:class:%- [@(0.0.255)3 class][3 _][*3 StaticRect][3 _:_][@(0.0.255)3 public][3 _
][*@3;3 Ctrl]&]
[s9; Widget completely filled with single color.&]
[s3;%- &]
[s0;%- &]
[ {{10000F(128)G(128)@1 [s0; [* Public Method List]]}}&]
[s3;%- &]
[s5;:StaticRect`:`:Color`(class Color`):%- [_^StaticRect^ StaticRect][@(0.0.255) `&]_[* Col
or]([@(0.0.255) class]_[* Color]_[*@3 c])&]
[s2; The color. Default is SColorFace.&]
[s3; &]
[s0; &]
[s0; &]
[s0;%- &]
[ {{10000@3 [s0; [*@(229)4 ImageCtrl]]}}&]
[s3; &]
[s1;:ImageCtrl`:`:class:%- [@(0.0.255)3 class][3 _][*3 ImageCtrl][3 _:_][@(0.0.255)3 public][3 _][*@3;3 C
trl]&] trl]&]
[s9; Display raster Image. Image is centered in the widget rectangle.&] [s9;%% Widget completely filled with single color.&]
[s3;%- &]
[s0;%- &]
[ {{10000F(128)G(128)@1 [s0; [* Public Method List]]}}&]
[s3;%- &]
[s5;:ImageCtrl`:`:SetImage`(const Image`&`):%- [_^ImageCtrl^ ImageCtrl][@(0.0.255) `&]_[* S
etImage]([@(0.0.255) const]_[_^Image^ Image][@(0.0.255) `&]_[*@3 `_img])&]
[s2; Sets the image.&]
[s3; &] [s3; &]
[s0; &] [s0; &]
[s0; &] [ {{10000F(128)G(128)@1 [s0;%% [* Public Method List]]}}&]
[s0;%- &]
[ {{10000@3 [s0; [*@(229)4 DrawingCtrl]]}}&]
[s3; &] [s3; &]
[s1;:DrawingCtrl`:`:class:%- [@(0.0.255)3 class][3 _][*3 DrawingCtrl][3 _:_][@(0.0.255)3 public][3 _ [s5;:StaticRect`:`:Color`(class Color`): [_^StaticRect^ StaticRect][@(0.0.255) `&]_[* Color
]([@(0.0.255) class]_[* Color]_[*@3 c])&]
[s2;%% The color. Default is SColorFace.&]
[s3;%% &]
[s0;%% &]
[s0;%% &]
[s0; &]
[ {{10000@3 [s0;%% [*@(229)4 ImageCtrl]]}}&]
[s3;%% &]
[s1;:ImageCtrl`:`:class: [@(0.0.255)3 class][3 _][*3 ImageCtrl][3 _:_][@(0.0.255)3 public][3 _][*@3;3 C
trl]&]
[s9;%% Display raster Image. Image is centered in the widget rectangle.&]
[s3; &]
[s0; &]
[ {{10000F(128)G(128)@1 [s0;%% [* Public Method List]]}}&]
[s3; &]
[s5;:ImageCtrl`:`:SetImage`(const Image`&`): [_^ImageCtrl^ ImageCtrl][@(0.0.255) `&]_[* Set
Image]([@(0.0.255) const]_[_^Image^ Image][@(0.0.255) `&]_[*@3 `_img])&]
[s2;%% Sets the image.&]
[s3;%% &]
[s0;%% &]
[s0;%% &]
[s0; &]
[ {{10000@3 [s0;%% [*@(229)4 DrawingCtrl]]}}&]
[s3;%% &]
[s1;:DrawingCtrl`:`:class: [@(0.0.255)3 class][3 _][*3 DrawingCtrl][3 _:_][@(0.0.255)3 public][3 _
][*@3;3 Ctrl]&] ][*@3;3 Ctrl]&]
[s9; Displays Drawing.&] [s9;%% Displays Drawing.&]
[s3;%- &]
[s0;%- &]
[ {{10000F(128)G(128)@1 [s0; [* Public Method List]]}}&]
[s3;%- &]
[s5;:DrawingCtrl`:`:Background`(Color`):%- [_^Picture^ DrawingCtrl][@(0.0.255) `&]_[* Backg
round]([_^Color^ Color]_[*@3 color])&]
[s2; Sets background [%-*@3 color]. Default is white.&]
[s3; &] [s3; &]
[s4;%- &] [s0; &]
[s5;:DrawingCtrl`:`:Get`(`)const:%- [_^Drawing^ Drawing]_[* Get]()_[@(0.0.255) const]&] [ {{10000F(128)G(128)@1 [s0;%% [* Public Method List]]}}&]
[s2; Returns Drawing assigned to Picture.&] [s3; &]
[s3;%- &] [s5;:DrawingCtrl`:`:Background`(Color`): [_^Picture^ DrawingCtrl][@(0.0.255) `&]_[* Backgro
[s4;%- &] und]([_^Color^ Color]_[*@3 color])&]
[s5;:DrawingCtrl`:`:KeepRatio`(bool`):%- [_^Picture^ DrawingCtrl][@(0.0.255) `&]_[* KeepRat [s2;%% Sets background [%-*@3 color]. Default is white.&]
io]([@(0.0.255) bool]_[*@3 keep]_`=_[@(0.0.255) true])&] [s3;%% &]
[s2; If active, Picture keeps the aspect ratio of Drawing. Default [s4; &]
[s5;:DrawingCtrl`:`:Get`(`)const: [_^Drawing^ Drawing]_[* Get]()_[@(0.0.255) const]&]
[s2;%% Returns Drawing assigned to Picture.&]
[s3; &]
[s4; &]
[s5;:DrawingCtrl`:`:KeepRatio`(bool`): [_^Picture^ DrawingCtrl][@(0.0.255) `&]_[* KeepRatio
]([@(0.0.255) bool]_[*@3 keep]_`=_[@(0.0.255) true])&]
[s2;%% If active, Picture keeps the aspect ratio of Drawing. Default
is on.&] is on.&]
[s3; &] [s3;%% &]
[s4;%- &] [s4; &]
[s5;:DrawingCtrl`:`:NoKeepRatio`(`):%- [_^Picture^ DrawingCtrl][@(0.0.255) `&]_[* NoKeepRat [s5;:DrawingCtrl`:`:NoKeepRatio`(`): [_^Picture^ DrawingCtrl][@(0.0.255) `&]_[* NoKeepRatio
io]()&] ]()&]
[s2; Do not keep aspect ratio.&] [s2;%% Do not keep aspect ratio.&]
[s3; &] [s3;%% &]
[s4;%- &] [s4; &]
[s5;:DrawingCtrl`:`:Set`(const Drawing`&`):%- [_^Picture^ DrawingCtrl][@(0.0.255) `&]_[* Se [s5;:DrawingCtrl`:`:Set`(const Drawing`&`): [_^Picture^ DrawingCtrl][@(0.0.255) `&]_[* Set](
t]([@(0.0.255) const]_[_^Drawing^ Drawing][@(0.0.255) `&]_[*@3 `_picture])&] [@(0.0.255) const]_[_^Drawing^ Drawing][@(0.0.255) `&]_[*@3 `_picture])&]
[s5;:DrawingCtrl`:`:operator`=`(const Drawing`&`):%- [_^Picture^ DrawingCtrl][@(0.0.255) `& [s5;:DrawingCtrl`:`:operator`=`(const Drawing`&`): [_^Picture^ DrawingCtrl][@(0.0.255) `&
]_[* operator`=]([@(0.0.255) const]_[_^Drawing^ Drawing][@(0.0.255) `&]_[*@3 `_picture])&] ]_[* operator`=]([@(0.0.255) const]_[_^Drawing^ Drawing][@(0.0.255) `&]_[*@3 `_picture])&]
[s2; Assigns the Drawing.&] [s2;%% Assigns the Drawing.&]
[s3; &] [s3;%% &]
[s4;%- &] [s4; &]
[s5;:DrawingCtrl`:`:operator`=`(const Painting`&`):%- [_^Picture^ DrawingCtrl][@(0.0.255) `& [s5;:DrawingCtrl`:`:operator`=`(const Painting`&`): [_^Picture^ DrawingCtrl][@(0.0.255) `&
]_[* operator`=]([@(0.0.255) const]_[_^Painting^ Painting][@(0.0.255) `&]_[*@3 `_picture])&] ]_[* operator`=]([@(0.0.255) const]_[_^Painting^ Painting][@(0.0.255) `&]_[*@3 `_picture])&]
[s2; Assigns [%-*@3 `_picture], converted to Drawing.&] [s2;%% Assigns [%-*@3 `_picture], converted to Drawing.&]
[s0;%% &]
[s0;%% &]
[s0; &] [s0; &]
[s0; &] [ {{10000@3 [s0;%% [*@(229)4 SeparatorCtrl]]}}&]
[s0;%- &] [s3;%% &]
[ {{10000@3 [s0; [*@(229)4 SeparatorCtrl]]}}&] [s1;:SeparatorCtrl`:`:class: [@(0.0.255)3 class][3 _][*3 SeparatorCtrl][3 _:_][@(0.0.255)3 publi
[s3; &] c][3 _][*@3;3 Ctrl]&]
[s1;:SeparatorCtrl`:`:class:%- [@(0.0.255)3 class][3 _][*3 SeparatorCtrl][3 _:_][@(0.0.255)3 pub [s9;%% Horizontal or vertical separator line. Direction depends on
lic][3 _][*@3;3 Ctrl]&]
[s9; Horizontal or vertical separator line. Direction depends on
aspect ratio.&] aspect ratio.&]
[s3;%- &] [s3; &]
[s0;%- &] [s0; &]
[ {{10000F(128)G(128)@1 [s0; [* Public Method List]]}}&] [ {{10000F(128)G(128)@1 [s0;%% [* Public Method List]]}}&]
[s3;%- &] [s3; &]
[s5;:SeparatorCtrl`:`:Margin`(int`):%- [_^SeparatorCtrl^ SeparatorCtrl][@(0.0.255) `&]_[* M [s5;:SeparatorCtrl`:`:Margin`(int`): [_^SeparatorCtrl^ SeparatorCtrl][@(0.0.255) `&]_[* Mar
argin]([@(0.0.255) int]_[*@3 w])&] gin]([@(0.0.255) int]_[*@3 w])&]
[s2; Sets the left`-right (for horizontal separator) or top`-bottom [s2;%% Sets the left`-right (for horizontal separator) or top`-bottom
margin. Default value is 2.&] margin. Default value is 2.&]
[s3; &] [s3;%% &]
[s4;%- &] [s4; &]
[s5;:SeparatorCtrl`:`:Margin`(int`,int`):%- [_^SeparatorCtrl^ SeparatorCtrl][@(0.0.255) `& [s5;:SeparatorCtrl`:`:Margin`(int`,int`): [_^SeparatorCtrl^ SeparatorCtrl][@(0.0.255) `&]_
]_[* Margin]([@(0.0.255) int]_[*@3 l], [@(0.0.255) int]_[*@3 r])&] [* Margin]([@(0.0.255) int]_[*@3 l], [@(0.0.255) int]_[*@3 r])&]
[s2; Sets the top`-right (for horizontal separator) or top`-bottom [s2;%% Sets the top`-right (for horizontal separator) or top`-bottom
to [%-*@3 l] and [%-*@3 r], in that order. Default value is 2.&] to [%-*@3 l] and [%-*@3 r], in that order. Default value is 2.&]
[s3; &] [s3;%% &]
[s4;%- &] [s4; &]
[s5;:SeparatorCtrl`:`:SetSize`(int`):%- [_^SeparatorCtrl^ SeparatorCtrl][@(0.0.255) `&]_[* S [s5;:SeparatorCtrl`:`:SetSize`(int`): [_^SeparatorCtrl^ SeparatorCtrl][@(0.0.255) `&]_[* Se
etSize]([@(0.0.255) int]_[*@3 w])&] tSize]([@(0.0.255) int]_[*@3 w])&]
[s2; Sets the size returned by GetMinSize `- included to affect the [s2;%% Sets the size returned by GetMinSize `- included to affect
way how widget is treated in BarCtrl. Default value is 7.&] the way how widget is treated in BarCtrl. Default value is 7.&]
[s3; &] [s3;%% &]
[s4;%- &] [s4; &]
[s5;:SeparatorCtrl`:`:SetStyle`(const SeparatorCtrl`:`:Style`&`):%- [_^SeparatorCtrl^ S [s5;:SeparatorCtrl`:`:SetStyle`(const SeparatorCtrl`:`:Style`&`): [_^SeparatorCtrl^ Sep
eparatorCtrl][@(0.0.255) `&]_[* SetStyle]([@(0.0.255) const]_[_^SeparatorCtrl`:`:Style^ S aratorCtrl][@(0.0.255) `&]_[* SetStyle]([@(0.0.255) const]_[_^SeparatorCtrl`:`:Style^ Sty
tyle][@(0.0.255) `&]_[*@3 s])&] le][@(0.0.255) `&]_[*@3 s])&]
[s2; Sets the visual style to SeparatorCtrl`::Style [%-*@3 s]. The style [s2;%% Sets the visual style to SeparatorCtrl`::Style [%-*@3 s]. The
is a simple structure with two fields:&] style is a simple structure with two fields:&]
[s7; [*@5 l1]-|the first margin&] [s7;%% [*@5 l1]-|the first margin&]
[s7;%- [*@5 l2]-|the second margin&] [s7; [*@5 l2]-|the second margin&]
[s3; &] [s3;%% &]
[s0; ]] [s0;%% ]]

View file

@ -94,14 +94,6 @@ is active.&]
[s5;:Upp`:`:WithSpin`:`:NoKeySpin`(`):%- [_^Upp`:`:WithSpin^ WithSpin][@(0.0.255) `&]_[* No [s5;:Upp`:`:WithSpin`:`:NoKeySpin`(`):%- [_^Upp`:`:WithSpin^ WithSpin][@(0.0.255) `&]_[* No
KeySpin]()&] KeySpin]()&]
[s2; Same as KeySpin(false).&] [s2; Same as KeySpin(false).&]
[s3;%- &]
[s4; &]
[s5;:WithSpin`:`:SpinButtonsObject`(`):%- [_^SpinButtons^ SpinButtons][@(0.0.255) `&]_[* Sp
inButtonsObject]()&]
[s5;:WithSpin`:`:SpinButtonsObject`(`)const:%- [@(0.0.255) const]_[_^SpinButtons^ SpinBut
tons][@(0.0.255) `&]_[* SpinButtonsObject]()_[@(0.0.255) const]&]
[s2; Returns a reference to internal SpinButtons object.&]
[s0; &]
[s0;%- &] [s0;%- &]
[ {{10000@(113.42.0) [s0; [*@7;4 Predefined WithSpin widgets]]}}&] [ {{10000@(113.42.0) [s0; [*@7;4 Predefined WithSpin widgets]]}}&]
[s3;%- &] [s3;%- &]

View file

@ -36,7 +36,7 @@ class FontInfo;
inline inline
bool PreferColorEmoji(int c) bool PreferColorEmoji(int c)
{ // for these codepoints we prefer replacemnet color emoji even if glyphs is in the font { // for these codepoints we prefer replacement color emoji even if glyphs is in the font
return c >= 0x2600 && c <= 0x27ef || c >= 0x1f004 && c <= 0x1f251 || c >= 0x1f300 && c <= 0x1faf6; return c >= 0x2600 && c <= 0x27ef || c >= 0x1f004 && c <= 0x1f251 || c >= 0x1f300 && c <= 0x1faf6;
} }
@ -211,6 +211,8 @@ public:
operator Value() const { return RichToValue(*this); } operator Value() const { return RichToValue(*this); }
Font(const Value& q) { *this = q.Get<Font>(); } Font(const Value& q) { *this = q.Get<Font>(); }
static Font FromInt64(int64 q) { Font fnt; fnt.data = q; return fnt; }
// BW compatibility // BW compatibility
FontInfo Info() const; FontInfo Info() const;

View file

@ -234,6 +234,8 @@ void Image::Serialize(Stream& s)
p2 = spot2; p2 = spot2;
s % p2; s % p2;
} }
if(sz.cx < 0 || sz.cy < 0)
s.LoadError();
int64 len = (int64)sz.cx * (int64)sz.cy * (int64)sizeof(RGBA); int64 len = (int64)sz.cx * (int64)sz.cy * (int64)sizeof(RGBA);
if(s.IsLoading()) { if(s.IsLoading()) {
if(len) { if(len) {

View file

@ -264,7 +264,7 @@ Rect RichEdit::PlaceCaret()
Rect rr = Rect(zoom * cursorc.left, GetPosY(cursorc), zoom * cursorc.right, Rect rr = Rect(zoom * cursorc.left, GetPosY(cursorc), zoom * cursorc.right,
GetPosY(PageY(cursorc.page, cursorc.bottom))); GetPosY(PageY(cursorc.page, cursorc.bottom)));
if(objectpos >= 0) { if(objectpos >= 0) {
KillCaret(); caret = Null;
return rr; return rr;
} }
if(!IsNull(objectrect)) { if(!IsNull(objectrect)) {
@ -272,12 +272,17 @@ Rect RichEdit::PlaceCaret()
Refresh(); Refresh();
} }
if(IsSelection()) if(IsSelection())
KillCaret(); caret = Null;
else else
SetCaret(GetCaretRect(cursorc)); caret = GetCaretRect(cursorc);
return rr; return rr;
} }
Rect RichEdit::GetCaret() const
{
return caret;
}
void RichEdit::SetupRuler() void RichEdit::SetupRuler()
{ {
Zoom zoom = GetZoom(); Zoom zoom = GetZoom();

View file

@ -225,6 +225,7 @@ public:
virtual String GetSelectionData(const String& fmt) const; virtual String GetSelectionData(const String& fmt) const;
virtual Point GetPreedit(); virtual Point GetPreedit();
virtual Font GetPreeditFont(); virtual Font GetPreeditFont();
virtual Rect GetCaret() const;
private: private:
virtual int GetCharAt(int64 i) const { return GetChar((int)i); } virtual int GetCharAt(int64 i) const { return GetChar((int)i); }
@ -277,6 +278,7 @@ private:
static int fixedlang; static int fixedlang;
RichObject bar_object; RichObject bar_object;
String bar_fieldparam; String bar_fieldparam;
Rect caret;
WithRichFindReplaceLayout<TopWindow> findreplace; WithRichFindReplaceLayout<TopWindow> findreplace;

View file

@ -105,7 +105,7 @@ void RichPara::StorePart::Store(Lines& lines, const Part& part, int pinc)
h->descent = max(h->ydelta, 0); h->descent = max(h->ydelta, 0);
h->external = 0; h->external = 0;
lines.object.Add(part.object); lines.object.Add(part.object);
h->object = &lines.object.Top(); h->object = &lines.object.Top();
h++; h++;
*t++ = 'x'; *t++ = 'x';
*p++ = pos; *p++ = pos;

View file

@ -2710,7 +2710,7 @@ void TabBar::Serialize(Stream& s)
int version = 1; int version = 1;
s / version; s / version;
s % id; s % id;
s % crosses; s % crosses;
s % crosses_side; s % crosses_side;
s % grouping; s % grouping;

View file

@ -28,10 +28,6 @@ bool Ctrl::GuiPlatformSetFullRefreshSpecial()
return false; return false;
} }
void Ctrl::PaintCaret(SystemDraw& w)
{
}
String GuiPlatformGetKeyDesc(dword key) String GuiPlatformGetKeyDesc(dword key)
{ {
return Null; return Null;
@ -71,7 +67,8 @@ String Ctrl::Name() const {
#else #else
String s = String(typeid(*this).name()) + " : " + Format("0x%x", (int) this); String s = String(typeid(*this).name()) + " : " + Format("0x%x", (int) this);
#endif #endif
if(IsChild()) Ctrl *parent = GetParent();
if(parent)
s << "(parent " << String(typeid(*parent).name()) << ")"; s << "(parent " << String(typeid(*parent).name()) << ")";
return s; return s;
} }

View file

@ -25,7 +25,7 @@ private:
void DestroyWnd(); void DestroyWnd();
void NewTop() { top = new Top; top->owner_window = NULL; } void NewTop() { SetTop(new Top); GetTop()->owner_window = NULL; }
void PutForeground(); void PutForeground();
static void MouseEventFB(Ptr<Ctrl> t, int event, Point p, int zdelta); static void MouseEventFB(Ptr<Ctrl> t, int event, Point p, int zdelta);

View file

@ -96,44 +96,17 @@ bool Ctrl::DoKeyFB(dword key, int cnt)
return b; return b;
} }
void Ctrl::SetCaret(int x, int y, int cx, int cy)
{
GuiLock __;
caretx = x;
carety = y;
caretcx = cx;
caretcy = cy;
fbCaretTm = msecs();
SyncCaret();
}
void Ctrl::SyncCaret()
{
CursorSync();
}
void Ctrl::CursorSync() void Ctrl::CursorSync()
{ {
LLOG("@ CursorSync"); LLOG("@ CursorSync");
Point p = GetMousePos() - fbCursorImage.GetHotSpot(); Point p = GetMousePos() - fbCursorImage.GetHotSpot();
Rect cr = Null; Rect cr = Null;
if(focusCtrl && (((msecs() - fbCaretTm) / 500) & 1) == 0)
cr = (RectC(focusCtrl->caretx, focusCtrl->carety, focusCtrl->caretcx, focusCtrl->caretcy)
+ focusCtrl->GetScreenView().TopLeft()) & focusCtrl->GetScreenView();
if(fbCursorPos != p) { if(fbCursorPos != p) {
fbCursorPos = p; fbCursorPos = p;
if(!(VirtualGuiPtr->GetOptions() & GUI_SETMOUSECURSOR)) if(!(VirtualGuiPtr->GetOptions() & GUI_SETMOUSECURSOR))
Invalidate(); Invalidate();
} }
if(cr != fbCaretRect) {
fbCaretRect = cr;
if(VirtualGuiPtr->GetOptions() & GUI_SETCARET)
VirtualGuiPtr->SetCaret(cr);
else
Invalidate();
}
} }
bool Ctrl::ProcessEvent(bool *quit) bool Ctrl::ProcessEvent(bool *quit)
@ -159,6 +132,7 @@ bool Ctrl::ProcessEvents(bool *quit)
LLOG("TimerProc invoked at " << msecs()); LLOG("TimerProc invoked at " << msecs());
TimerProc(msecs()); TimerProc(msecs());
LLOG("TimerProc elapsed: " << tm); LLOG("TimerProc elapsed: " << tm);
AnimateCaret();
SweepMkImageCache(); SweepMkImageCache();
DoPaint(); DoPaint();
return ret; return ret;

View file

@ -35,6 +35,7 @@ bool Ctrl::invalid;
Point Ctrl::fbCursorPos = Null; Point Ctrl::fbCursorPos = Null;
Image Ctrl::fbCursorImage; Image Ctrl::fbCursorImage;
Rect Ctrl::fbCaretRect; Rect Ctrl::fbCaretRect;
int Ctrl::fbCaretTm; int Ctrl::fbCaretTm;
bool Ctrl::fbEndSession; bool Ctrl::fbEndSession;
@ -73,9 +74,9 @@ Ctrl *Ctrl::GetOwner()
{ {
GuiLock __; GuiLock __;
int q = FindTopCtrl(); int q = FindTopCtrl();
if(q > 0 && topctrl[q]->top) { Top *top = topctrl[q]->GetTop();
Ctrl *x = topctrl[q]->top->owner_window; if(q > 0 && top) {
LDUMP(Upp::Name(x)); Ctrl *x = top->owner_window;
return dynamic_cast<TopWindowFrame *>(x) ? x->GetOwner() : x; return dynamic_cast<TopWindowFrame *>(x) ? x->GetOwner() : x;
} }
return NULL; return NULL;
@ -87,36 +88,13 @@ Ctrl *Ctrl::GetActiveCtrl()
return focusCtrl ? focusCtrl->GetTopCtrl() : NULL; return focusCtrl ? focusCtrl->GetTopCtrl() : NULL;
} }
// Vector<Callback> Ctrl::hotkey;
int Ctrl::RegisterSystemHotKey(dword key, Function<void ()> cb) int Ctrl::RegisterSystemHotKey(dword key, Function<void ()> cb)
{ {
/* ASSERT(key >= K_DELTA);
int q = hotkey.GetCount();
for(int i = 0; i < hotkey.GetCount(); i++)
if(!hotkey[i]) {
q = i;
break;
}
hotkey.At(q) = cb;
dword mod = 0;
if(key & K_ALT)
mod |= MOD_ALT;
if(key & K_SHIFT)
mod |= MOD_SHIFT;
if(key & K_CTRL)
mod |= MOD_CONTROL;
return RegisterHotKey(NULL, q, mod, key & 0xffff) ? q : -1;*/
return -1; return -1;
} }
void Ctrl::UnregisterSystemHotKey(int id) void Ctrl::UnregisterSystemHotKey(int id)
{ {
/* if(id >= 0 && id < hotkey.GetCount()) {
UnregisterHotKey(NULL, id);
hotkey[id].Clear();
}*/
} }
bool Ctrl::IsWaitingEvent() bool Ctrl::IsWaitingEvent()
@ -135,30 +113,12 @@ void Ctrl::SyncTopWindows()
ViewDraw::ViewDraw(Ctrl *ctrl) ViewDraw::ViewDraw(Ctrl *ctrl)
{ {
/*
if(Ctrl::invalid)
Ctrl::DoPaint();
Ctrl::invalid = false;
Ctrl::RemoveCursor();
Ctrl::RemoveCaret();
Rect r = ctrl->GetScreenView();
Ctrl::invalid.Add(r);
Ctrl::AddUpdate(r);
for(int i = max(ctrl->GetTopCtrl()->FindTopCtrl() + 1, 0); i < Ctrl::topctrl.GetCount(); i++) {
Rect rr = Ctrl::topctrl[i]->GetScreenRect();
ExcludeClip(rr);
Subtract(Ctrl::invalid, rr);
}
Offset(r.TopLeft());
*/
} }
ViewDraw::~ViewDraw() ViewDraw::~ViewDraw()
{ {
// Ctrl::DoUpdate();
} }
Rect Ctrl::GetClipBound(const Vector<Rect>& inv, const Rect& r) Rect Ctrl::GetClipBound(const Vector<Rect>& inv, const Rect& r)
{ {
Rect ri = Null; Rect ri = Null;
@ -306,18 +266,18 @@ int Ctrl::GetKbdSpeed()
void Ctrl::DestroyWnd() void Ctrl::DestroyWnd()
{ {
for(int i = 0; i < topctrl.GetCount(); i++) for(int i = 0; i < topctrl.GetCount(); i++) {
if(topctrl[i]->top && topctrl[i]->top->owner_window == this) Top *top = topctrl[i]->GetTop();
if(top && top->owner_window == this)
topctrl[i]->WndDestroy(); topctrl[i]->WndDestroy();
}
int q = FindTopCtrl(); int q = FindTopCtrl();
if(q >= 0) { if(q >= 0) {
Invalidate(); Invalidate();
topctrl.Remove(q); topctrl.Remove(q);
} }
if(top) { if(top)
delete top; DeleteTop();
top = NULL;
}
isopen = false; isopen = false;
TopWindow *win = dynamic_cast<TopWindow *>(this); TopWindow *win = dynamic_cast<TopWindow *>(this);
if(win) if(win)
@ -341,8 +301,11 @@ void Ctrl::PutForeground()
} }
Vector< Ptr<Ctrl> > fw; Vector< Ptr<Ctrl> > fw;
for(int i = 0; i < topctrl.GetCount(); i++) for(int i = 0; i < topctrl.GetCount(); i++)
if(topctrl[i] && topctrl[i]->top && topctrl[i]->top->owner_window == this && topctrl[i] != this) if(topctrl[i]) {
fw.Add(topctrl[i]); Top *top = topctrl[i]->GetTop();
if(top && top->owner_window == this && topctrl[i] != this)
fw.Add(topctrl[i]);
}
for(int i = 0; i < fw.GetCount(); i++) for(int i = 0; i < fw.GetCount(); i++)
if(fw[i]) if(fw[i])
fw[i]->PutForeground(); fw[i]->PutForeground();
@ -355,8 +318,8 @@ void Ctrl::SetWndForeground()
if(IsWndForeground()) if(IsWndForeground())
return; return;
Ctrl *to = this; Ctrl *to = this;
while(to->top && to->top->owner_window) while(to->GetTop() && to->GetTop()->owner_window)
to = to->top->owner_window; to = to->GetTop()->owner_window;
to->PutForeground(); to->PutForeground();
if(this != focusCtrl) if(this != focusCtrl)
ActivateWnd(); ActivateWnd();
@ -445,7 +408,8 @@ void Ctrl::PopUp(Ctrl *owner, bool savebits, bool activate, bool dropshadow, boo
ASSERT(owner_window->IsOpen()); ASSERT(owner_window->IsOpen());
if(owner_window != desktop) { if(owner_window != desktop) {
owner_window->SetForeground(); owner_window->SetForeground();
top->owner_window = owner_window; if(GetTop())
GetTop()->owner_window = owner_window;
} }
} }
topctrl.Add(this); topctrl.Add(this);
@ -496,10 +460,8 @@ void Ctrl::SysEndLoop()
void Ctrl::DeleteDesktopTop() void Ctrl::DeleteDesktopTop()
{ {
if(desktop && desktop->top) { if(desktop && desktop->GetTop())
delete desktop->top; desktop->DeleteTop();
desktop->top = NULL;
}
} }
void Ctrl::SetDesktop(Ctrl& q) void Ctrl::SetDesktop(Ctrl& q)

View file

@ -25,7 +25,7 @@ some font system to measure fonts (e.g. DrawGL and plugin/FT`_fontsys).&]
[s5;:Upp`:`:VirtualGui`:`:GetOptions`(`): [@(0.0.255) virtual] [_^Upp`:`:dword^ dword]_[* G [s5;:Upp`:`:VirtualGui`:`:GetOptions`(`): [@(0.0.255) virtual] [_^Upp`:`:dword^ dword]_[* G
etOptions]()&] etOptions]()&]
[s2;%% Returns a set of flags describing some aspects of VirtualGui [s2;%% Returns a set of flags describing some aspects of VirtualGui
behaviour. Available option flags are:-|&] behaviour. Available option flags are:&]
[s2;%% &] [s2;%% &]
[s7;i1120;a17;:Ctrl`:`:CENTER:%% [%-*C@3 GUI`_SETMOUSECURSOR]-|Use the [s7;i1120;a17;:Ctrl`:`:CENTER:%% [%-*C@3 GUI`_SETMOUSECURSOR]-|Use the
SetMouseCursor() method instead of painting the cursor.&] SetMouseCursor() method instead of painting the cursor.&]

View file

@ -679,6 +679,8 @@ void Gdb::SerializeSession(Stream& s)
s / version; s / version;
int n = watches.GetCount(); int n = watches.GetCount();
s / n; s / n;
if(n < 0)
s.LoadError();
for(int i = 0; i < n; i++) { for(int i = 0; i < n; i++) {
String w; String w;
if(s.IsStoring()) if(s.IsStoring())

View file

@ -234,6 +234,8 @@ void Pdb::SerializeSession(Stream& s)
s / version; s / version;
int n = watches.GetCount(); int n = watches.GetCount();
s / n; s / n;
if(n < 0)
LoadError();
for(int i = 0; i < n; i++) { for(int i = 0; i < n; i++) {
String w; String w;
if(s.IsStoring()) if(s.IsStoring())