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(DisplayPopup));
RDUMP(sizeof(PopUpTable));
RDUMP(sizeof(WithDropChoice<EditString>));
RDUMP(sizeof(DropList));
RDUMP(sizeof(WithDropChoice<EditString>));
RDUMP(sizeof(ArrayCtrl));
RDUMP(sizeof(TreeCtrl));
RDUMP(sizeof(TreeCtrl::Node));

View file

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

View file

@ -343,15 +343,19 @@ void Index<T>::Serialize(Stream& s)
h.Serialize(s);
if(s.IsLoading())
for(int i = 0; i < h.GetCount(); i++)
if(h[i] & 0x80000000)
if(i < GetCount() && h[i] & 0x80000000)
Unlink(i);
}
else {
Vector<int> u = GetUnlinked();
u.Serialize(s);
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
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)
return (bool)v ? "true" : "false";
if(IsNumber(v))
return FormatG((double)v, 17);
return FormatG((double)v, 15);
if(IsString(v))
return AsCString((String)v, INT_MAX, NULL, ASCSTRING_JSON);
if(IsDateTime(v))

View file

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

View file

@ -103,117 +103,50 @@ public:
void operator=(const Bits&) = delete;
};
//# System dependent
template <class T>
class Mitor : Moveable< Mitor<T> > {
union {
mutable unsigned count;
mutable Vector<T> *vector;
};
byte elem0[sizeof(T)];
class PackedData {
void *ptr = nullptr;
T& Get(int i) const;
void Pick(Mitor&& m);
void Copy(const Mitor& m);
void Chk() const { ASSERT(count != 2); }
template <class T>
T Get(int ii, T def) const;
public:
T& operator[](int i) { return Get(i); }
const T& operator[](int i) const { return Get(i); }
int GetCount() const;
T& Add();
void Add(const T& x);
void SetRawPtr(void *p) { ptr = p; }
void *GetRawPtr() const { return ptr; }
void SetData(int ii, const void *data, int datalen);
template <class F>
bool GetData(int ii, F out) const;
void SetNull(int ii) { SetData(ii, NULL, 0); }
void SetString(int ii, const char *s) { SetData(ii, s, strlen(s)); }
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();
void Shrink();
Mitor(Mitor&& m) { Pick(pick(m)); }
void operator=(Mitor&& m) { if(this != &m) { Clear(); Pick(pick(m)); } }
Vector<String> Unpack() const;
size_t GetPackedSize() const;
String GetPacked() const { return String((const char *)ptr, GetPackedSize()); }
Mitor(Mitor& m, int) { Copy(m); }
Mitor() { count = 0; }
~Mitor() { Clear(); }
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>
struct Link {
T *link_prev[N];
@ -336,169 +269,4 @@ public:
LRUCache() { head = -1; size = 0; count = 0; ClearCounters(); }
};
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;
}
#include "Other.hpp"

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 {
/* 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;
PteBase::Prec *PteBase::PtrAdd()

View file

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

View file

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

View file

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

View file

@ -737,11 +737,12 @@ void BiVector<T>::Free() {
}
}
#ifdef UPP
template <class T>
void BiVector<T>::Serialize(Stream& s) {
int n = items;
s / n;
if(n < 0)
s.LoadError();
if(s.IsLoading()) {
Clear();
while(n--)
@ -758,8 +759,6 @@ String BiVector<T>::ToString() const
return AsStringArray(*this);
}
#endif
template <class T>
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]));
}
#ifdef UPP
template <class T>
void BiArray<T>::Serialize(Stream& s) {
int n = bv.GetCount();
s / n;
if(n < 0)
s.LoadError();
if(s.IsLoading()) {
Clear();
while(n--)
@ -822,8 +822,6 @@ BiArray<T>::BiArray(std::initializer_list<T> init)
AddTail(q);
}
#endif
inline
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)
{
return FormatG(var, 17);
return FormatG(var, 15);
}
template<> void XmlAttrLoad(double& var, const String& text)

View file

@ -79,7 +79,9 @@ void Ctrl::Layout() {}
void Ctrl::PostInput()
{
GuiLock __;
if(parent) parent->PostInput();
Ctrl *parent = GetParent();
if(parent)
parent->PostInput();
}
void Ctrl::LeftDouble(Point p, dword keyflags)
@ -105,25 +107,33 @@ void Ctrl::RightTriple(Point p, dword keyflags)
void Ctrl::ChildGotFocus()
{
GuiLock __;
if(parent) parent->ChildGotFocus();
Ctrl *parent = GetParent();
if(parent)
parent->ChildGotFocus();
}
void Ctrl::ChildLostFocus()
{
GuiLock __;
if(parent) parent->ChildLostFocus();
Ctrl *parent = GetParent();
if(parent)
parent->ChildLostFocus();
}
void Ctrl::ChildAdded(Ctrl *q)
{
GuiLock __;
if(parent) parent->ChildAdded(q);
Ctrl *parent = GetParent();
if(parent)
parent->ChildAdded(q);
}
void Ctrl::ChildRemoved(Ctrl *q)
{
GuiLock __;
if(parent) parent->ChildRemoved(q);
Ctrl *parent = GetParent();
if(parent)
parent->ChildRemoved(q);
}
void Ctrl::ParentChange() {}
@ -287,6 +297,7 @@ void Ctrl::Show(bool ashow) {
visible = ashow;
fullrefresh = false;
RefreshFrame();
Ctrl *parent = GetParent();
if(parent)
StateH(SHOW);
if(top)
@ -301,8 +312,9 @@ bool Ctrl::IsVisible() const {
const Ctrl *q = this;
for(;;) {
if(!q->visible) return false;
if(!q->parent) break;
q = q->parent;
Ctrl *p = q->GetParent();
if(!p) break;
q = p;
}
return q->visible;
}
@ -312,7 +324,7 @@ void Ctrl::Enable(bool aenable) {
if(enabled != aenable) {
enabled = aenable;
if(top) WndEnable(enabled);
if(!enabled && parent && HasFocusDeep())
if(!enabled && GetParent() && HasFocusDeep())
IterateFocusForward(this, GetTopCtrl());
RefreshFrame();
StateH(ENABLE);
@ -322,6 +334,7 @@ void Ctrl::Enable(bool aenable) {
bool Ctrl::IsShowEnabled() const {
GuiLock __;
Ctrl *parent = GetParent();
return IsEnabled() && (!parent || parent->IsShowEnabled());
}
@ -353,8 +366,8 @@ void Ctrl::ClearModifyDeep()
{
GuiLock __;
ClearModify();
for(Ctrl *q = firstchild; q; q = q->next)
q->ClearModifyDeep();
for(Ctrl& q : *this)
q.ClearModifyDeep();
}
@ -368,92 +381,14 @@ bool Ctrl::IsModifiedDeep() const
{
GuiLock __;
if(IsModified()) return true;
for(Ctrl *q = firstchild; q; q = q->next)
if(q->IsModified()) return true;
for(const Ctrl& q : *this)
if(q.IsModified()) return true;
return false;
}
void Ctrl::SetCaret(const Rect& r)
{
SetCaret(r.left, r.top, r.GetWidth(), r.GetHeight());
}
Rect Ctrl::GetCaret() const
{
return RectC(caretx, carety, caretcx, caretcy);
}
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);
return Null;
}
bool Ctrl::SetWantFocus() {
@ -493,8 +428,8 @@ void Ctrl::UpdateActionRefresh() {
void Ctrl::CancelModeDeep() {
GuiLock __;
CancelMode();
for(Ctrl *q = firstchild; q; q = q->next)
q->CancelModeDeep();
for(Ctrl& q : *this)
q.CancelModeDeep();
}
String Ctrl::GetDesc() const
@ -547,14 +482,14 @@ void Ctrl::Dump(Stream& s) const {
sFLAG(wantfocus) << sFLAG(editable) << sFLAG(IsModified()) << sFLAG(transparent));
LG("Rect: " << GetRect());
LG("View: " << GetView());
for(int i = 0; i < frame.GetCount(); i++)
LG("Frame " << i << ": " << typeid(decltype(*frame[i].frame)).name() << " - " << frame[i].view);
for(int i = 0; i < GetFrameCount(); i++)
LG("Frame " << i << ": " << typeid(decltype(*GetFrame0(i).frame)).name() << " - " << GetFrame0(i).GetView());
LG("Data: " << GetData().ToString());
if(firstchild) {
if(children) {
LG("Children");
s << LOG_BEGIN;
for(Ctrl *q = GetFirstChild(); q; q = q->GetNext()) {
q->Dump(s);
for(const Ctrl& q : *this) {
q.Dump(s);
LG("------");
}
s << LOG_END;
@ -592,16 +527,13 @@ Ctrl::Ctrl() {
LLOG("Ctrl::Ctrl");
GuiPlatformConstruct();
destroying = false;
parent = prev = next = firstchild = lastchild = NULL;
top = NULL;
exitcode = 0;
frame.Add().frame = &NullFrame();
multi_frame = false;
frame.frame = &NullFrame();
enabled = visible = wantfocus = initfocus = true;
editable = true;
backpaint = IsCompositedGui() ? FULLBACKPAINT : TRANSPARENTBACKPAINT;
inframe = false;
ignoremouse = transparent = false;
caretcx = caretcy = caretx = carety = 0;
pos.x = PosLeft(0, 0);
pos.y = PosTop(0, 0);
rect = Rect(0, 0, 0, 0);
@ -611,6 +543,9 @@ Ctrl::Ctrl() {
popupgrab = false;
fullrefresh = false;
akv = false;
layout_id_literal = false;
top = false;
uparent = nullptr;
}
void KillTimeCallbacks(void *id, void *idlim);
@ -626,6 +561,7 @@ void Ctrl::DoRemove() {
mouseCtrl = NULL;
LLOG("DoRemove " << Name() << " focusCtrl: " << UPP::Name(focusCtrl));
GuiPlatformRemove();
Ctrl *parent = GetParent();
if(HasFocusDeep()) {
LLOG("DoRemove - HasFocusDeep");
if(destroying) {
@ -675,7 +611,7 @@ void Ctrl::Close()
Ctrl *q = GetTopCtrl();
if(!q->top) return;
DoRemove();
if(parent) return;
if(GetParent()) return;
StateH(CLOSE);
USRLOG(" CLOSE " + Desc(this));
WndDestroy();
@ -689,10 +625,13 @@ Ctrl::~Ctrl() {
destroying = true;
while(GetFirstChild())
RemoveChild(GetFirstChild());
Ctrl *parent = GetParent();
if(parent)
parent->RemoveChild(this);
Close();
KillTimeCallbacks(this, (byte *) this + sizeof(Ctrl));
ClearInfo();
FreeFrames();
}
Vector<Ctrl::MouseHook>& Ctrl::mousehook() { static Vector<Ctrl::MouseHook> h; return h; }
@ -1035,7 +974,7 @@ String Ctrl::Name0() const {
String id = q->GetLayoutId();
if(id.GetCount())
path = '.' + q->GetLayoutId() + path;
q = q->parent;
q = q->GetParent();
}
s << ' ' << path;
#ifdef CPU_64
@ -1043,6 +982,7 @@ String Ctrl::Name0() const {
#else
s << " : " + Format("0x%x", (int) this);
#endif
Ctrl *parent = GetParent();
if(IsChild())
s << " (parent " << CppDemangle(typeid(*parent).name()) << ")";
return s;
@ -1063,8 +1003,10 @@ void Ctrl::EndLoop()
void Ctrl::EndLoop(int code)
{
GuiLock __;
ASSERT(!parent);
exitcode = code;
ASSERT(!GetParent());
TopWindow *w = GetTopWindow();
if(w)
w->exitcode = code;
EndLoop();
}
@ -1080,12 +1022,6 @@ bool Ctrl::InCurrentLoop() const
return GetLoopCtrl() == this;
}
int Ctrl::GetExitCode() const
{
GuiLock __;
return exitcode;
}
#ifdef HAS_TopFrameDraw
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)
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 {
return dynamic_cast<const DHCtrl *>(this);
}
@ -15,38 +34,31 @@ void Ctrl::AddChild(Ctrl *q, Ctrl *p)
LLOG("Add " << UPP::Name(q) << " to: " << Name());
if(p == q) return;
bool updaterect = true;
if(q->parent) {
Ctrl *qparent = q->GetParent();
if(qparent) {
ASSERT(!q->inframe);
if(q->parent == this) {
if(qparent == this) {
RemoveChild0(q);
updaterect = false;
}
else
q->parent->RemoveChild(q);
qparent->RemoveChild(q);
}
q->parent = this;
if(p) {
ASSERT(p->parent == this);
q->prev = p;
q->next = p->next;
if(p == lastchild)
lastchild = q;
else
p->next->prev = q;
p->next = q;
}
else
if(firstchild) {
q->prev = NULL;
q->next = firstchild;
firstchild->prev = q;
firstchild = q;
if(children) {
if(!p) p = GetLastChild();
ASSERT(p->GetParent() == this);
q->prev_sibling = p;
q->next_sibling = p->next_sibling;
p->next_sibling->prev_sibling = q;
p->next_sibling = q;
}
else {
ASSERT(lastchild == NULL);
firstchild = lastchild = q;
q->prev = q->next = NULL;
ASSERT(!p);
children = q->next_sibling = q->prev_sibling = q;
}
q->SetParent(this);
q->CancelModeDeep();
if(updaterect)
q->UpdateRect();
@ -58,13 +70,13 @@ void Ctrl::AddChild(Ctrl *q, Ctrl *p)
void Ctrl::AddChild(Ctrl *child)
{
AddChild(child, lastchild);
AddChild(child, GetLastChild());
}
void Ctrl::AddChildBefore(Ctrl *child, Ctrl *insbefore)
{
if(insbefore)
AddChild(child, insbefore->prev);
AddChild(child, insbefore->GetPrev());
else
AddChild(child);
}
@ -73,23 +85,26 @@ void Ctrl::RemoveChild0(Ctrl *q)
{
GuiLock __;
ChildRemoved(q);
if(!q->GetParent()) return; // ChildRemoved can remove q
q->DoRemove();
q->parent = NULL;
if(q == firstchild)
firstchild = firstchild->next;
if(q == lastchild)
lastchild = lastchild->prev;
if(q->prev)
q->prev->next = q->next;
if(q->next)
q->next->prev = q->prev;
q->next = q->prev = NULL;
if(!q->GetParent()) return; // DoRemove can remove q
q->SetParent(NULL);
if(q == children) {
children = q->next_sibling;
if(children == q)
children = 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)
{
GuiLock __;
if(q->parent != this) return;
if(q->GetParent() != this) return;
q->RefreshFrame();
RemoveChild0(q);
q->ParentChange();
@ -100,6 +115,7 @@ void Ctrl::RemoveChild(Ctrl *q)
void Ctrl::Remove()
{
GuiLock __;
Ctrl *parent = GetParent();
if(parent)
parent->RemoveChild(this);
}
@ -171,15 +187,16 @@ Ctrl * Ctrl::GetViewIndexChild(int ii) const
bool Ctrl::HasChild(Ctrl *q) const
{
GuiLock __;
return q && q->IsChild() && q->parent == this;
return q && q->GetParent() == this;
}
bool Ctrl::HasChildDeep(Ctrl *q) const
{
GuiLock __;
while(q && q->IsChild()) {
if(q->parent == this) return true;
q = q->parent;
Ctrl *qparent = q->GetParent();
if(qparent == this) return true;
q = qparent;
}
return false;
}
@ -260,9 +277,12 @@ Ctrl *Ctrl::GetTopCtrl()
{
GuiLock __;
Ctrl *q = this;
while(q->parent)
q = q->parent;
for(;;) {
Ctrl *qparent = q->GetParent();
if(!qparent)
return q;
q = qparent;
}
}
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(); }
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(); }
TopWindow *Ctrl::GetTopWindow()

View file

@ -478,13 +478,28 @@ private:
void operator=(Ctrl&);
private:
struct Frame : Moveable<Frame> {
CtrlFrame *frame;
Rect16 view;
Frame() { view.Clear(); }
struct MultiFrame { // in case there are more than 1 CtrlFrames
int alloc;
int count;
};
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); }
};
Ctrl *parent;
struct Scroll : Moveable<Scroll> {
Rect rect;
@ -508,16 +523,20 @@ private:
Ptr<Ctrl> owner;
};
Top *top;
int exitcode;
Ctrl *prev, *next;
Ctrl *firstchild, *lastchild;//16
Frame frame;
LogPos pos;//8
Rect16 rect;
Mitor<Frame> frame;//16
String info;//16
int16 caretx, carety, caretcx, caretcy;//8
Rect16 rect; //8
union {
Ctrl *uparent;
Top *utop;
};
Ctrl *prev_sibling = nullptr;
Ctrl *next_sibling = nullptr;
Ctrl *children = nullptr;
PackedData attrs;
byte overpaint;
@ -543,6 +562,9 @@ private:
bool akv: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> mouseCtrl;
@ -551,8 +573,6 @@ private:
static Ptr<Ctrl> focusCtrl;
static Ptr<Ctrl> focusCtrlWnd;
static Ptr<Ctrl> lastActiveWnd;
static Ptr<Ctrl> caretCtrl;
static Rect caretRect;
static Ptr<Ctrl> captureCtrl;
static bool ignoreclick;
static bool ignoremouseup;
@ -634,12 +654,20 @@ private:
void RefreshAccessKeys();
void RefreshAccessKeysDo(bool vis);
static void DefferedFocusSync();
static void SyncCaret();
static void RefreshCaret();
static bool DispatchKey(dword keycode, int count);
void SetFocusWnd();
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 Point dndpos;
static bool dndframe;
@ -667,8 +695,6 @@ private:
void UpdateArea(SystemDraw& draw, const Rect& clip);
Ctrl *GetTopRect(Rect& r, bool inframe, bool clip = true);
void DoSync(Ctrl *q, Rect r, bool inframe);
void SetInfoPart(int i, const char *txt);
String GetInfoPart(int i) const;
Rect GetPreeditScreenRect();
void SyncPreedit();
@ -719,6 +745,21 @@ private:
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 String appname;
@ -780,6 +821,43 @@ protected:
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:
enum StateReason {
FOCUS = 10,
@ -915,6 +993,8 @@ public:
virtual Point GetPreedit();
virtual Font GetPreeditFont();
virtual Rect GetCaret() const;
virtual void DragAndDrop(Point p, PasteClip& d);
virtual void FrameDragAndDrop(Point p, PasteClip& d);
virtual void DragRepeat(Point p);
@ -972,11 +1052,11 @@ public:
void AddChild(Ctrl *child, Ctrl *insafter);
void AddChildBefore(Ctrl *child, Ctrl *insbefore);
void RemoveChild(Ctrl *child);
Ctrl *GetParent() const { return parent; }
Ctrl *GetLastChild() const { return lastchild; }
Ctrl *GetFirstChild() const { return firstchild; }
Ctrl *GetPrev() const { return parent ? prev : NULL; }
Ctrl *GetNext() const { return parent ? next : NULL; }
Ctrl *GetParent() const { return top ? NULL : uparent; }
Ctrl *GetLastChild() const { return children ? children->prev_sibling : nullptr; }
Ctrl *GetFirstChild() const { return children; }
Ctrl *GetPrev() const { Ctrl *parent = GetParent(); return parent && prev_sibling != parent->GetLastChild() ? prev_sibling : nullptr; }
Ctrl *GetNext() const { Ctrl *parent = GetParent(); return parent && next_sibling != parent->children ? next_sibling : nullptr; }
int GetChildIndex(const Ctrl *child) const;
Ctrl *GetIndexChild(int i) const;
int GetChildCount() const;
@ -987,7 +1067,7 @@ public:
int GetViewChildCount() const;
Ctrl *GetViewIndexChild(int ii) const;
bool IsChild() const { return parent; }
bool IsChild() const { return GetParent(); }
Ctrl *ChildFromPoint(Point& pt) const;
@ -1013,13 +1093,13 @@ public:
Ctrl& SetFrame(int i, CtrlFrame& frm);
Ctrl& SetFrame(CtrlFrame& frm) { return SetFrame(0, frm); }
Ctrl& AddFrame(CtrlFrame& frm);
const CtrlFrame& GetFrame(int i = 0) const { return *frame[i].frame; }
CtrlFrame& GetFrame(int i = 0) { 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 *GetFrame0(i).frame; }
void RemoveFrame(int i);
void RemoveFrame(CtrlFrame& frm);
void InsertFrame(int i, CtrlFrame& frm);
int FindFrame(CtrlFrame& frm);
int GetFrameCount() const { return frame.GetCount(); }
int FindFrame(CtrlFrame& frm) const;
int GetFrameCount() const { return multi_frame ? frame.multi.count : frame.frame ? 1 : 0; }
void ClearFrames();
bool IsOpen() const;
@ -1055,10 +1135,10 @@ public:
void RefreshLayout() { SyncLayout(1); }
void RefreshLayoutDeep() { SyncLayout(2); }
void RefreshParentLayout() { if(parent) parent->RefreshLayout(); }
void RefreshParentLayout();
void UpdateLayout() { SyncLayout(); }
void UpdateParentLayout() { if(parent) parent->UpdateLayout(); }
void UpdateParentLayout();
Ctrl& LeftPos(int a, int size = STDSIZE);
Ctrl& RightPos(int a, int size = STDSIZE);
@ -1157,11 +1237,6 @@ public:
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();
void CancelMyPreedit() { if(HasFocus()) CancelPreedit(); }
@ -1211,21 +1286,19 @@ public:
Ctrl& NoTransparent() { return Transparent(false); }
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& HelpLine(const char *txt);
Ctrl& Description(const char *txt);
Ctrl& HelpTopic(const char *txt);
Ctrl& LayoutId(const char *txt);
Ctrl& LayoutIdLiteral(const char *txt);
String GetTip() const;
String GetHelpLine() const;
String GetDescription() const;
String GetHelpTopic() const;
String GetLayoutId() const;
void ClearInfo() { info.Clear(); }
void ClearInfo();
void Add(Ctrl& ctrl) { AddChild(&ctrl); }
Ctrl& operator<<(Ctrl& ctrl) { Add(ctrl); return *this; }
@ -1276,7 +1349,6 @@ public:
void EndLoop(int code);
bool InLoop() const;
bool InCurrentLoop() const;
int GetExitCode() const;
static PasteClip& Clipboard();
static PasteClip& Selection();

View file

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

View file

@ -22,6 +22,7 @@ void Ctrl::RefreshFrame(const Rect& r) {
if(GuiPlatformRefreshFrameSpecial(r))
return;
if(!top && !IsDHCtrl()) {
Ctrl *parent = GetParent();
if(InFrame())
parent->RefreshFrame(r + GetRect().TopLeft());
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)
{
GuiLock __;
Top *top = GetTop();
if(!top)
return true;
for(int i = 0; i < top->scroll.GetCount(); i++) {
@ -113,12 +115,12 @@ Rect Ctrl::GetClippedView()
GuiLock __;
Rect sv = GetScreenView();
Rect view = sv;
Ctrl *q = parent;
Ctrl *q = GetParent();
Ctrl *w = this;
while(q) {
view &= w->InFrame() ? q->GetScreenRect() : q->GetScreenView();
w = q;
q = q->parent;
q = q->GetParent();
}
return view - GetScreenRect().TopLeft();
}
@ -178,7 +180,7 @@ void Ctrl::ScrollView(const Rect& _r, int dx, int dy)
Rect r = _r & vsz;
LLOG("ScrollView2 " << r << " " << dx << " " << dy);
Ctrl *w;
for(w = this; w->parent; w = w->parent)
for(w = this; w->GetParent(); w = w->GetParent())
if(w->InFrame()) {
Refresh();
return;
@ -191,12 +193,12 @@ void Ctrl::ScrollView(const Rect& _r, int dx, int dy)
Refresh();
else {
LTIMING("ScrollCtrls1");
Top *top = GetTopCtrl()->top;
Top *top = GetTopCtrl()->GetTop();
for(Ctrl *q = GetFirstChild(); q; q = q->GetNext())
if(q->InView())
ScrollCtrl(top, q, r, q->GetRect(), dx, dy);
if(parent)
for(Ctrl *q = parent->GetFirstChild(); q; q = q->GetNext())
if(GetParent())
for(Ctrl *q = GetParent()->GetFirstChild(); q; q = q->GetNext())
if(q->InView() && q != this)
ScrollCtrl(top, q, r, q->GetScreenRect() - GetScreenView().TopLeft(), dx, dy);
}
@ -214,6 +216,7 @@ void Ctrl::ScrollView(int dx, int dy) {
void Ctrl::SyncScroll()
{
GuiLock __;
Top *top = GetTop();
if(!top)
return;
Vector<Scroll> scroll = pick(top->scroll);
@ -278,29 +281,31 @@ void Ctrl::CtrlPaint(SystemDraw& w, const Rect& clip) {
return;
Ctrl *q;
Rect view = rect;
for(int i = 0; i < frame.GetCount(); i++) {
int n = GetFrameCount();
for(int i = 0; i < n; i++) {
LEVELCHECK(w, NULL);
frame[i].frame->FramePaint(w, view);
view = frame[i].view;
Frame& f = GetFrame0(i);
f.frame->FramePaint(w, view);
view = f.GetView();
}
Rect oview = view.Inflated(overpaint);
bool hasviewctrls = false;
bool viewexcluded = false;
bool hiddenbychild = false;
for(q = firstchild; q; q = q->next)
if(q->IsShown()) {
if(q->GetRect().Contains(orect) && !q->IsTransparent())
for(Ctrl& q : *this)
if(q.IsShown()) {
if(q.GetRect().Contains(orect) && !q.IsTransparent())
hiddenbychild = true;
if(q->InFrame()) {
if(!viewexcluded && IsTransparent() && q->GetRect().Intersects(view)) {
if(q.InFrame()) {
if(!viewexcluded && IsTransparent() && q.GetRect().Intersects(view)) {
w.Begin();
w.ExcludeClip(view);
viewexcluded = true;
}
LEVELCHECK(w, q);
Point off = q->GetRect().TopLeft();
LEVELCHECK(w, &q);
Point off = q.GetRect().TopLeft();
w.Offset(off);
q->CtrlPaint(w, clip - off);
q.CtrlPaint(w, clip - off);
w.End();
}
else
@ -329,15 +334,15 @@ void Ctrl::CtrlPaint(SystemDraw& w, const Rect& clip) {
if(hasviewctrls && !view.IsEmpty()) {
Rect cl = clip & view;
w.Clip(cl);
for(q = firstchild; q; q = q->next)
if(q->IsShown() && q->InView()) {
LEVELCHECK(w, q);
Rect qr = q->GetRect();
for(Ctrl& q : *this)
if(q.IsShown() && q.InView()) {
LEVELCHECK(w, &q);
Rect qr = q.GetRect();
Point off = qr.TopLeft() + view.TopLeft();
Rect ocl = cl - off;
if(ocl.Intersects(Rect(qr.GetSize()).Inflated(overpaint))) {
w.Offset(off);
q->CtrlPaint(w, ocl);
q.CtrlPaint(w, ocl);
w.End();
}
}
@ -373,11 +378,11 @@ bool Ctrl::PaintOpaqueAreas(SystemDraw& w, const Rect& r, const Rect& clip, bool
if(backpaint == EXCLUDEPAINT)
return w.ExcludeClip(r);
Rect cview = clip & (GetView() + off);
for(Ctrl *q = lastchild; q; q = q->prev)
if(!q->PaintOpaqueAreas(w, q->GetRect() + (q->InView() ? viewpos : off),
q->InView() ? cview : clip))
for(Ctrl& q : *this)
if(!q.PaintOpaqueAreas(w, q.GetRect() + (q.InView() ? viewpos : off),
q.InView() ? cview : clip))
return false;
if(nochild && (lastchild || GetNext()))
if(nochild && (GetLastChild() || GetNext()))
return true;
Rect opaque = (GetOpaqueRect() + viewpos) & clip;
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, notr.bottom, notr.right, r.bottom));
}
for(Ctrl *q = firstchild; q; q = q->next) {
Point qoff = q->InView() ? viewpos : off;
Rect qr = q->GetRect() + qoff;
for(Ctrl& q : *this) {
Point qoff = q.InView() ? viewpos : off;
Rect qr = q.GetRect() + qoff;
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;
}
Rect cview = clip & (GetView() + off);
for(Ctrl *q = lastchild; q; q = q->prev)
q->ExcludeDHCtrls(w, q->GetRect() + (q->InView() ? viewpos : off),
q->InView() ? cview : clip);
for(Ctrl& q : *this)
q.ExcludeDHCtrls(w, q.GetRect() + (q.InView() ? viewpos : off),
q.InView() ? cview : clip);
}
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.Offset(GetView().TopLeft());
}
Ctrl *parent = GetParent();
if(parent) {
r.Offset(GetRect().TopLeft());
return parent->GetTopRect(r, InFrame(), clip);
@ -620,6 +626,7 @@ void Ctrl::Sync()
{
GuiLock __;
LLOG("Sync " << Name());
Ctrl *parent = GetParent();
if(top && IsOpen()) {
LLOG("Sync UpdateWindow " << Name());
SyncScroll();
@ -642,6 +649,7 @@ void Ctrl::Sync(const Rect& sr)
void Ctrl::DrawCtrlWithParent(Draw& w, int x, int y)
{
GuiLock __;
Ctrl *parent = GetParent();
if(parent) {
Rect r = GetRect();
Ctrl *top = parent->GetTopRect(r, inframe);
@ -674,6 +682,7 @@ void Ctrl::DrawCtrl(Draw& w, int x, int y)
void Ctrl::SyncMoves()
{
GuiLock __;
Top *top = GetTop();
if(!top)
return;
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::focusCtrlWnd;
Ptr<Ctrl> Ctrl::lastActiveWnd;
Ptr<Ctrl> Ctrl::caretCtrl;
Rect Ctrl::caretRect;
bool Ctrl::ignorekeyup;
Ptr<Ctrl> Ctrl::defferedSetFocus;
@ -116,7 +114,7 @@ bool Ctrl::HotKey(dword key)
GuiLock __;
LLOG("HotKey " << GetKeyDesc(key) << " at " << Name(this));
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));
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));
pfocusCtrl->LostFocus();
}
if(pfocusCtrl && pfocusCtrl->parent && !pfocusCtrl->parent->destroying)
pfocusCtrl->parent->ChildLostFocus();
if(pfocusCtrl && pfocusCtrl->GetParent() && !pfocusCtrl->GetParent()->destroying)
pfocusCtrl->GetParent()->ChildLostFocus();
SyncCaret();
}
@ -179,9 +177,9 @@ void Ctrl::DoSetFocus(Ptr<Ctrl> pfocusCtrl, Ptr<Ctrl> nfocusCtrl, bool activate)
nfocusCtrl->GotFocus();
nfocusCtrl->StateH(FOCUS);
}
if(focusCtrl == nfocusCtrl && nfocusCtrl && nfocusCtrl->parent &&
!nfocusCtrl->parent->destroying)
nfocusCtrl->parent->ChildGotFocus();
if(focusCtrl == nfocusCtrl && nfocusCtrl && nfocusCtrl->GetParent() &&
!nfocusCtrl->GetParent()->destroying)
nfocusCtrl->GetParent()->ChildGotFocus();
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()
{
GuiLock __;
@ -364,6 +354,61 @@ bool Ctrl::HasFocusDeep() const
a = a->GetOwnerCtrl();
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__[ ] = {
{ 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_)
LogMouseEvent("FRAME ", this, event, p, zdelta, keyflags);
eventCtrl = this_;
Ctrl *parent = GetParent();
if(parent && this_)
parent->ChildFrameMouseEvent(this, event, p, zdelta, keyflags);
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;
sPropagated = false;
Image m = this_ ? MouseEvent(event, p, zdelta, keyflags) : Image();
Ctrl *parent = this_ ? this_->GetParent() : NULL;
if(event == MOUSEWHEEL && !sPropagated && this_ && parent)
parent->ChildMouseEvent(this, event, p, zdelta, keyflags);
sPropagated = pb;
@ -108,6 +110,7 @@ Image Ctrl::MouseEventH(int event, Point p, int zdelta, dword keyflags)
return Image::Arrow();
if(this_)
LogMouseEvent(NULL, this, event, p, zdelta, keyflags);
Ctrl *parent = this_ ? this_->GetParent() : NULL;
if(this_ && parent && event != MOUSEWHEEL)
parent->ChildMouseEvent(this, 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)
{
Ctrl *parent = GetParent();
if(parent) {
p += GetScreenView().TopLeft();
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)
{
GuiLock __;
Ctrl *parent = GetParent();
if(parent)
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)
{
GuiLock __;
Ctrl *parent = GetParent();
if(parent)
parent->ChildMouseEvent(child, event, p, zdelta, keyflags);
}
@ -280,7 +286,7 @@ Ctrl *Ctrl::ChildFromPoint(Point& pt) const
Rect view = GetView();
if(view.Contains(p)) {
Point vp = p - view.TopLeft();
for(q = GetLastChild(); q; q = q->prev) {
for(q = GetLastChild(); q; q = q->GetPrev()) {
if(q->InView() && q->IsMouseActive()) {
Rect r = q->GetRect();
if(r.Contains(vp)) {
@ -291,7 +297,7 @@ Ctrl *Ctrl::ChildFromPoint(Point& pt) const
}
return NULL;
}
for(q = GetLastChild(); q; q = q->prev) {
for(q = GetLastChild(); q; q = q->GetPrev()) {
if(q->InFrame() && q->IsMouseActive()) {
Rect r = q->GetRect();
if(r.Contains(p)) {

View file

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

View file

@ -15,7 +15,8 @@ void Ctrl::Create(Ctrl *owner, bool popup)
ASSERT(!IsChild() && !IsOpen());
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->owner = owner;
@ -111,12 +112,13 @@ void Ctrl::WndDestroy()
if(HasFocusDeep() || !GetFocusCtrl())
activeCtrl = owner;
}
Top *top = GetTop();
if(top->im_context)
g_object_unref(top->im_context);
gtk_widget_destroy(top->window);
isopen = false;
popup = false;
delete top;
DeleteTop();
top = NULL;
int q = FindCtrl(this);
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

View file

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

View file

@ -124,12 +124,14 @@ int Ctrl::DoDragAndDrop(const char *fmts, const Image& sample, dword actions,
iw.DrawImage(1, 1, sz.cx, sz.cy, sample);
dnd_icon = iw;
}
Top *top = w->GetTop();
if(top)
#if GTK_CHECK_VERSION(3, 10, 0)
gtk_drag_begin_with_coordinates(w->top->window, list, GdkDragAction(gdk_actions),
gtk_drag_begin_with_coordinates(top->window, list, GdkDragAction(gdk_actions),
GetMouseLeft() ? 1 : GetMouseMiddle() ? 2 : 3,
CurrentEvent.event, -1, -1);
#else
gtk_drag_begin(w->top->window, list, GdkDragAction(gdk_actions),
gtk_drag_begin(top->window, list, GdkDragAction(gdk_actions),
GetMouseLeft() ? 1 : GetMouseMiddle() ? 2 : 3, CurrentEvent.event);
#endif
while(dnd_source && GetTopCtrls().GetCount())
@ -329,6 +331,9 @@ gboolean Ctrl::GtkDragDrop(GtkWidget *widget, GdkDragContext *context, gint x, g
void Ctrl::DndInit()
{
Top *top = GetTop();
if(!top)
return;
GtkWidget *w = top->window;
gpointer id = (gpointer)(uintptr_t)top->id;
g_signal_connect(w, "drag-begin", G_CALLBACK(GtkDragBegin), id);
@ -345,6 +350,7 @@ void Ctrl::DndInit()
void Ctrl::DndExit()
{
Top *top = GetTop();
if(top)
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:
p->CancelPreedit();
if(p) {
Top *top = p->GetTop();
if(top) {
if(((GdkEventFocus *)event)->in)
gtk_im_context_focus_in(p->top->im_context);
gtk_im_context_focus_in(top->im_context);
else
gtk_im_context_focus_out(p->top->im_context);
gtk_im_context_focus_out(top->im_context);
}
AddEvent(user_data, EVENT_FOCUS_CHANGE, value, event);
}
return false;
@ -181,9 +184,12 @@ gboolean Ctrl::GtkEvent(GtkWidget *widget, GdkEvent *event, gpointer user_data)
value << (int) key->keyval << (int) key->hardware_keycode;
if(pressed) {
p = GetTopCtrlFromId(user_data);
if(p && gtk_im_context_filter_keypress(p->top->im_context, key))
if(p) {
Top *top = p->GetTop();
if(top && gtk_im_context_filter_keypress(top->im_context, key))
return true;
}
}
break;
case GDK_CONFIGURE: {
retval = false;
@ -344,7 +350,9 @@ void Ctrl::IMLocation(Ctrl *w)
gr.y = LSC(e.top - q.top);
gr.width = LSC(e.GetWidth());
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_height = LSC(sz.cy);
gtk_window_set_resizable(gtk(), sizeable);
Top *top = GetTop();
if(top) {
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()
{
GuiLock __;
if(top)
if(GetTop())
gtk_window_set_title(gtk(), FromUnicode(title, CHARSET_UTF8));
}
@ -127,6 +130,8 @@ void TopWindow::Open(Ctrl *owner)
CenterRect(owner);
IgnoreMouseUp();
Create(owner, false);
Top *top = GetTop();
if(top)
g_signal_connect(top->window, "window-state-event", G_CALLBACK(StateEvent), this);
SyncSizeHints();
SyncCaption();

View file

@ -14,9 +14,6 @@ Vector<Ctrl::Win> Ctrl::wins;
Ptr<Ctrl> Ctrl::activeCtrl;
int Ctrl::WndCaretTime;
bool Ctrl::WndCaretVisible;
bool Ctrl::invalids;
int Ctrl::FindId(int id)
@ -84,7 +81,7 @@ void Ctrl::SetMouseCursor(const Image& image)
else
topctrl = GetActiveCtrl();
if(topctrl)
top = topctrl->top;
top = topctrl->GetTop();
if(top && id != top->cursor_id) {
top->cursor_id = id;
int64 aux = image.GetAuxData();
@ -122,6 +119,7 @@ void Ctrl::SetMouseCursor(const Image& image)
Ctrl *Ctrl::GetOwner()
{
GuiLock __;
Top *top = GetTop();
return IsOpen() ? top->owner : NULL;
}
@ -150,52 +148,6 @@ void Ctrl::UnregisterSystemHotKey(int id)
#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
{
GuiLock __;
@ -213,7 +165,9 @@ void Ctrl::WndShow(bool b)
{
GuiLock __;
LLOG("WndShow " << Name() << ", " << b);
if(IsOpen()) {
Top *top = GetTop();
if(IsOpen() && top) {
if(b)
gtk_widget_show_now(top->window);
else
@ -224,6 +178,7 @@ void Ctrl::WndShow(bool b)
bool Ctrl::IsWndOpen() const {
GuiLock __;
const Top *top = GetTop();
return top && top->window && gtk_widget_get_window(top->window);
}
@ -400,12 +355,13 @@ void Ctrl::DoCancelPreedit()
{
if(!focusCtrl)
return;
if(focusCtrl->top)
Top *top = focusCtrl->GetTop();
if(top)
focusCtrl->HidePreedit();
if(focusCtrl->top) {
gtk_im_context_reset(focusCtrl->top->im_context);
gtk_im_context_focus_out(focusCtrl->top->im_context);
gtk_im_context_focus_in(focusCtrl->top->im_context);
if(top) {
gtk_im_context_reset(top->im_context);
gtk_im_context_focus_out(top->im_context);
gtk_im_context_focus_in(top->im_context);
}
}
@ -458,7 +414,8 @@ bool Ctrl::SweepConfigure(bool wait)
FetchEvents(wait);
for(int i = 0; i < Events.GetCount() && this_; 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;
LLOG("SweepConfigure " << rect);
if(GetRect() != rect)
@ -495,6 +452,7 @@ void Ctrl::WndEnable(bool b)
{
GuiLock __;
if(IsOpen()) {
Top *top = GetTop();
gtk_widget_set_sensitive(top->window, b);
StateH(ENABLE);
}

View file

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

View file

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

View file

@ -49,6 +49,8 @@ private:
byte center:2;
int exitcode = 0;
void PlaceFocus();
void ActiveFocus0(Ctrl& ctrl);
Abreak *FindAddAction(int ID);
@ -91,6 +93,8 @@ private:
GUIPLATFORM_TOPWINDOW_DECLS
#endif
friend class Ctrl;
public:
virtual void ShutdownWindow();
@ -126,6 +130,8 @@ public:
bool ExecuteOK() { return Execute() == IDOK; }
bool ExecuteCancel() { return Execute() == IDCANCEL; }
int GetExitCode() const { return exitcode; }
void Minimize(bool effect = false);
void Maximize(bool effect = false);
void Overlap(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 {
GuiLock __;
String s = Name0();

View file

@ -4,15 +4,6 @@ private:
bool activex: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 DumpMessage(Ctrl *w, UINT message, WPARAM wParam, LPARAM lParam);
@ -66,7 +57,7 @@ public:
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
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;
static Ctrl *CtrlFromHWND(HWND hwnd);

View file

@ -68,13 +68,14 @@ void Ctrl::DoCancelPreedit()
{
if(!focusCtrlWnd)
return;
if(focusCtrlWnd->top)
Top *top = focusCtrl->GetTop();
if(top)
focusCtrl->HidePreedit();
if(focusCtrlWnd->top && focusCtrlWnd->top->hwnd) {
HIMC himc = ImmGetContext(focusCtrlWnd->top->hwnd);
if(top && top->hwnd) {
HIMC himc = ImmGetContext(top->hwnd);
if(himc && ImmGetOpenStatus(himc)) {
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;
VectorMap< HWND, Ptr<Ctrl> >& w = Windows();
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]);
return v;
}
@ -472,7 +472,8 @@ void Ctrl::Create(HWND parent, DWORD style, DWORD exstyle, bool savebits, int sh
Rect r = GetRect();
AdjustWindowRectEx(r, style, FALSE, exstyle);
isopen = true;
top = new Top;
Top *top = new Top;
SetTop(top);
ASSERT(!parent || IsWindow(parent));
style &= ~WS_VISIBLE;
dropshadow = false;
@ -501,11 +502,11 @@ void ReleaseUDropTarget(UDropTarget *dt);
void Ctrl::WndFree()
{
GuiLock __;
if(!top) return;
Top *top = GetTop();
RevokeDragDrop(GetHWND());
if(!top) return;
ReleaseUDropTarget(top->dndtgt);
isopen = false;
if(!top) return;
HWND owner = GetWindow(top->hwnd, GW_OWNER);// CXL 31.10.2003 z DoRemove
bool focus = ::GetFocus() == top->hwnd;
LLOG("Ctrl::WndDestroy owner " << (void *)owner
@ -519,13 +520,13 @@ void Ctrl::WndFree()
::SetFocus(owner);
}
LLOG(LOG_END << "//Ctrl::WndFree() in " <<UPP::Name(this));
delete top;
top = NULL;
DeleteTop();
}
void Ctrl::WndDestroy()
{
GuiLock __;
Top *top = GetTop();
if(top && top->hwnd) {
HWND hwnd = top->hwnd;
WndFree();
@ -563,14 +564,16 @@ sWinMsg[] = {
void Ctrl::NcCreate(HWND hwnd)
{
GuiLock __;
if(!parent)
Top *top = GetTop();
if(top)
top->hwnd = hwnd;
}
void Ctrl::NcDestroy()
{
GuiLock __;
if(!parent)
Top *top = GetTop();
if(top)
WndFree();
}
@ -839,80 +842,6 @@ void Ctrl::GuiSleep(int ms)
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
{
GuiLock __;
@ -947,7 +876,7 @@ void Ctrl::SetAlpha(byte alpha)
{
GuiLock __;
HWND hwnd = GetHWND();
if(!IsAlphaSupported() || parent || !top || !hwnd)
if(!IsAlphaSupported() || GetParent() || !top || !hwnd)
return;
if(alpha == 255) {
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) {
SelectClipRgn(hdc, hrgn);
SystemDraw draw(hdc);
bool hcr = focusCtrl && focusCtrl->GetTopCtrl() == top &&
caretRect.Intersects(r + top->GetRect().TopLeft());
if(hcr) ::HideCaret(hwnd);
draw.Clip(r);
top->UpdateArea(draw, r);
ValidateRect(hwnd, r);
SelectClipRgn(hdc, NULL);
if(hcr) ::ShowCaret(hwnd);
}
ReleaseDC(hwnd, hdc);
DeleteObject(hrgn);
@ -1201,14 +1126,8 @@ void Ctrl::WndScrollView(const Rect& r, int dx, int dy)
{
GuiLock __;
LLOG("WndScrollView " << UPP::Name(this));
if(caretCtrl && caretCtrl->GetTopCtrl() == this) {
#if WINCARET
WndDestroyCaret();
#else
if(caretCtrl && caretCtrl->GetTopCtrl() == this)
RefreshCaret();
#endif
caretRect.Clear();
}
#ifdef PLATFORM_WINCE
::ScrollWindowEx(GetHWND(), dx, dy, r, r, NULL, NULL, 0);
#else
@ -1234,6 +1153,7 @@ void Ctrl::PopUp(Ctrl *owner, bool savebits, bool activate, bool dropshadow, boo
popup = false;
Ctrl *q = owner ? owner->GetTopCtrl() : GetActiveCtrl();
PopUpHWND(q ? q->GetHWND() : NULL, savebits, activate, dropshadow, topmost);
Top *top = GetTop();
if(top) top->owner = owner;
}

View file

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

View file

@ -1978,33 +1978,6 @@ pointer to it.&]
its descendants.&]
[s3;%- &]
[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]()&]
[s2; Terminates any input method composition in progress, if possible.
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.&]
[s3;%- &]
[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
onst]_[@(0.0.255) char]_`*[*@3 txt])&]
[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.&]
[s3;%% &]
[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
ect]_`=_[@(0.0.255) false])&]
[s2;%% Minimize window.&]

View file

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

View file

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

View file

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

View file

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

View file

@ -2,54 +2,54 @@
namespace Upp {
Point DisplayPopup::Op(Point p)
Point DisplayPopup::PopUp::Op(Point p)
{
return p + GetScreenView().TopLeft() - ctrl->GetScreenView().TopLeft();
}
void DisplayPopup::LeftDown(Point p, dword flags)
void DisplayPopup::PopUp::LeftDown(Point p, dword flags)
{
if(ctrl) ctrl->LeftDown(Op(p), flags);
}
void DisplayPopup::LeftDrag(Point p, dword flags)
void DisplayPopup::PopUp::LeftDrag(Point p, dword flags)
{
if(ctrl) ctrl->LeftDrag(Op(p), flags);
}
void DisplayPopup::LeftDouble(Point p, dword flags)
void DisplayPopup::PopUp::LeftDouble(Point p, dword flags)
{
if(ctrl) ctrl->LeftDouble(Op(p), flags);
}
void DisplayPopup::RightDown(Point p, dword flags)
void DisplayPopup::PopUp::RightDown(Point p, dword flags)
{
if(ctrl) ctrl->RightDown(Op(p), flags);
}
void DisplayPopup::LeftUp(Point p, dword flags)
void DisplayPopup::PopUp::LeftUp(Point p, dword flags)
{
if(ctrl) ctrl->LeftUp(Op(p), flags);
}
void DisplayPopup::MouseWheel(Point p, int zdelta, dword flags)
void DisplayPopup::PopUp::MouseWheel(Point p, int zdelta, dword flags)
{
if(ctrl) ctrl->MouseWheel(Op(p), zdelta, flags);
}
void DisplayPopup::MouseLeave()
void DisplayPopup::PopUp::MouseLeave()
{
Cancel();
}
void DisplayPopup::MouseMove(Point p, dword flags)
void DisplayPopup::PopUp::MouseMove(Point p, dword flags)
{
p += GetScreenView().TopLeft();
if(!slim.Contains(p))
MouseLeave();
}
void DisplayPopup::Paint(Draw& w)
void DisplayPopup::PopUp::Paint(Draw& w)
{
Rect r = GetSize();
w.DrawRect(r, SColorPaper);
@ -62,13 +62,13 @@ void DisplayPopup::Paint(Draw& w)
}
}
Vector<DisplayPopup *>& DisplayPopup::all()
Vector<DisplayPopup::PopUp *>& DisplayPopup::PopUp::all()
{
static Vector<DisplayPopup *> all;
static Vector<DisplayPopup::PopUp *> all;
return all;
}
DisplayPopup::DisplayPopup()
DisplayPopup::PopUp::PopUp()
{
SetFrame(BlackFrame());
display = NULL;
@ -83,14 +83,14 @@ DisplayPopup::DisplayPopup()
all().Add(this);
}
DisplayPopup::~DisplayPopup()
DisplayPopup::PopUp::~PopUp()
{
int q = FindIndex(all(), this);
if(q >= 0)
all().Remove(q);
}
void DisplayPopup::Sync()
void DisplayPopup::PopUp::Sync()
{
if(!IsMainThread()) {
PostCallback(PTEBACK(Sync));
@ -144,20 +144,20 @@ void DisplayPopup::Sync()
}
}
if(IsOpen() && !GetDragAndDropSource())
Close();
WhenClose();
}
void DisplayPopup::SyncAll()
void DisplayPopup::PopUp::SyncAll()
{
int n = 0;
for(DisplayPopup *p : all())
for(DisplayPopup::PopUp *p : all())
if(p->ctrl && p->ctrl->IsOpen()) {
p->Sync();
n++;
}
}
bool DisplayPopup::StateHook(Ctrl *, int reason)
bool DisplayPopup::PopUp::StateHook(Ctrl *, int reason)
{
if(reason == FOCUS)
SyncAll();
@ -165,13 +165,13 @@ bool DisplayPopup::StateHook(Ctrl *, int reason)
}
bool DisplayPopup::MouseHook(Ctrl *, bool, int, Point, int, dword)
bool DisplayPopup::PopUp::MouseHook(Ctrl *, bool, int, Point, int, dword)
{
SyncAll();
return false;
}
void DisplayPopup::Cancel()
void DisplayPopup::PopUp::Cancel()
{
if(GetDragAndDropSource())
return;
@ -179,17 +179,17 @@ void DisplayPopup::Cancel()
Sync();
}
bool DisplayPopup::IsOpen()
bool DisplayPopup::PopUp::IsOpen()
{
return Ctrl::IsOpen();
}
bool DisplayPopup::HasMouse()
bool DisplayPopup::PopUp::HasMouse()
{
return Ctrl::HasMouse() || ctrl && ctrl->HasMouse();
}
void DisplayPopup::Set(Ctrl *_ctrl, const Rect& _item,
void DisplayPopup::PopUp::Set(Ctrl *_ctrl, const Rect& _item,
const Value& _value, const Display *_display,
Color _ink, Color _paper, dword _style, int _margin)
{
@ -212,4 +212,44 @@ void DisplayPopup::Set(Ctrl *_ctrl, const Rect& _item,
}
}
void DisplayPopup::Set(Ctrl *ctrl, const Rect& item, const Value& v, const Display *display, Color ink, Color paper, dword style, int margin)
{
if(!popup) {
popup.Create();
popup->usedisplaystdsize = usedisplaystdsize;
popup->WhenClose << [=] { PostCallback([=] { popup.Clear(); }); };
}
popup->Set(ctrl, item, v, display, ink, paper, style, margin);
}
void DisplayPopup::Cancel()
{
if(popup)
popup->Cancel();
}
bool DisplayPopup::IsOpen()
{
return popup && popup->IsOpen();
}
bool DisplayPopup::HasMouse()
{
return popup && popup->HasMouse();
}
void DisplayPopup::UseDisplayStdSize()
{
usedisplaystdsize = true;
if(popup)
popup->usedisplaystdsize = true;
}
DisplayPopup::~DisplayPopup()
{
if(popup)
popup->Close();
}
}

View file

@ -1,4 +1,6 @@
class DisplayPopup : public Ctrl, public Link<DisplayPopup> {
class DisplayPopup {
private:
struct PopUp : public Ctrl, public Link<DisplayPopup::PopUp> {
virtual void Paint(Draw& w);
virtual void LeftDown(Point p, dword);
virtual void LeftDrag(Point p, dword);
@ -9,7 +11,6 @@ class DisplayPopup : public Ctrl, public Link<DisplayPopup> {
virtual void MouseLeave();
virtual void MouseMove(Point p, dword);
private:
Ptr<Ctrl> ctrl;
Rect item;
Rect slim;
@ -24,6 +25,28 @@ private:
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;
static Vector<DisplayPopup *>& all();
static bool StateHook(Ctrl *, int reason);
static bool MouseHook(Ctrl *, bool, int, Point, int, dword);
@ -37,8 +60,7 @@ public:
void Cancel();
bool IsOpen();
bool HasMouse();
void UseDisplayStdSize() { usedisplaystdsize = true; }
void UseDisplayStdSize();
DisplayPopup();
~DisplayPopup();
};

View file

@ -222,6 +222,11 @@ int DocEdit::GetCursorPos(Point p) {
return GetLength32();
}
Rect DocEdit::GetCaret() const
{
return caret;
}
void DocEdit::PlaceCaret(bool scroll) {
Point cr = GetCaret((int)cursor);
int fy = font.Info().GetLineHeight();
@ -231,7 +236,7 @@ void DocEdit::PlaceCaret(bool scroll) {
else
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();
}

View file

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

View file

@ -1,6 +1,6 @@
void DropEdge_Write(Value);
class PopUpTable : public ArrayCtrl {
class PopUpTable : public ArrayCtrl { // deprecated, replaced with PopUpList
public:
virtual void LeftUp(Point p, dword keyflags);
virtual bool Key(dword key, int);
@ -39,27 +39,115 @@ public:
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 {
public:
virtual void MouseWheel(Point p, int zdelta, dword keyflags);
virtual bool Key(dword key, int);
virtual void SetData(const Value& data);
virtual Value GetData() const;
virtual void DropPush();
virtual Value Format(const Value& q) const;
private:
PopUpTable list;
PopUpList list;
Index<Value> key;
Value value;
int dropwidth;
const Convert *valueconvert;
const Display *valuedisplay;
bool displayall;
bool dropfocus;
bool notnull;
bool alwaysdrop;
bool usewheel;
int16 dropwidth;
bool displayall:1;
bool dropfocus:1;
bool notnull:1;
bool alwaysdrop:1;
bool usewheel:1;
void Select();
void Cancel();
@ -105,7 +193,7 @@ public:
void Trim(int n);
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;
void SetValue(int i, const Value& v);
void SetValue(const Value& v);
@ -113,10 +201,10 @@ public:
void Adjust();
void Adjust(const Value& k);
/*
const PopUpTable& GetList() const { return list; }
PopUpTable& ListObject() { return list; }
*/
DropList& SetDropLines(int d) { list.SetDropLines(d); return *this; }
DropList& SetValueConvert(const Convert& cv);
DropList& SetConvert(const Convert& cv);
@ -160,7 +248,7 @@ public:
virtual void Serialize(Stream& s); //empty
protected:
PopUpTable list;
PopUpList list;
Ctrl *owner;
bool appending : 1;
bool dropfocus : 1;
@ -189,12 +277,12 @@ public:
void Add(const Value& data);
int Find(const Value& data) const { return list.Find(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 SerializeList(Stream& s);
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);
@ -204,11 +292,11 @@ public:
Value Get() const;
int GetIndex() const;
DropChoice& SetDisplay(int i, const Display& d) { list.SetDisplay(i, 0, d); return *this; }
DropChoice& SetDisplay(const Display& d) { list.ColumnAt(0).SetDisplay(d); return *this; }
DropChoice& SetDisplay(int i, const Display& d) { list.SetDisplay(i, d); return *this; }
DropChoice& SetDisplay(const Display& d) { list.SetDisplay(d); 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& 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& Appending() { appending = true; return *this; }
DropChoice& AlwaysDrop(bool e = true);

View file

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

View file

@ -63,6 +63,7 @@ public:
virtual void CancelMode();
virtual String GetSelectionData(const String& fmt) const;
virtual void State(int);
virtual Rect GetCaret() const;
public:
struct Style : ChStyle<Style> {
@ -88,35 +89,43 @@ public:
};
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;
WString text;
WString undotext;
Rect16 dropcaret;
const Style *style;
CharFilter filter;
const Convert *convert;
Font font;
int sc;
int cursor, anchor;
WString undotext;
int undocursor, undoanchor;
CharFilter filter;
const Convert *convert;
const Convert *inactive_convert;
Font font;
Color textcolor;
WString nulltext;
Color nullink;
Font nullfont;
Image nullicon;
int maxlen;
int autosize;
byte charset;
int fsell, fselh; // used to hold selection after LostFocus for X11 middle mouse copy
int dropcursor;
Rect dropcaret;
bool selclick;
byte charset;
bool selclick:1;
bool password:1;
bool autoformat:1;
@ -140,7 +149,6 @@ protected:
int GetStringCx(const wchar *text, int n);
int GetCaret(int cursor) const;
int GetCursor(int posx);
void SyncCaret();
void Finish(bool refresh = true);
void SaveUndo();
void DoAutoFormat();
@ -155,6 +163,13 @@ protected:
virtual int64 GetTotal() const { return text.GetLength(); }
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:
Event<Bar&> WhenBar;
Event<> WhenEnter;
@ -216,7 +231,7 @@ public:
bool IsPassword() const { return password; }
EditField& SetFilter(int (*f)(int)) { filter = f; 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& NoAutoFormat() { return AutoFormat(false); }
bool IsAutoFormat() const { return autoformat; }
@ -227,9 +242,9 @@ public:
bool IsClickSelect() const { return clickselect; }
EditField& InitCaps(bool b = true) { initcaps = b; return *this; }
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 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& MaxChars(int mc) { maxlen = mc; return *this; }
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>
class WithSpin : public Base {
class WithSpin : public Base, private VirtualButtons {
public:
virtual void CancelMode();
virtual void MouseWheel(Point p, int zdelta, dword keyflags);
virtual bool Key(dword key, int repcnt);
virtual Image MouseEvent(int event, Point p, int zdelta, dword keyflags);
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:
void Inc();
@ -380,9 +409,10 @@ protected:
void Init();
private:
SpinButtons sb;
const SpinButtons::Style *style;
IncType inc;
bool roundfrommin;
bool roundfrommin = false;
bool visible = true;
bool mousewheel = true;
bool keys = true;
@ -392,11 +422,13 @@ public:
WithSpin& SetInc(IncType _inc = 1) { inc = _inc; return *this; }
DataType GetInc() const { return inc; }
WithSpin& OnSides(bool b = true) { sb.OnSides(b); return *this; }
bool IsOnSides() const { return sb.IsOnSides(); }
WithSpin& SetStyle(SpinButtons::Style& s) { style = &s; return *this; }
WithSpin& ShowSpin(bool s = true) { sb.Show(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; }
@ -406,122 +438,13 @@ public:
WithSpin& KeySpin(bool b = true) { keys = b; return *this; }
WithSpin& NoKeySpin() { return KeySpin(false); }
SpinButtons& SpinButtonsObject() { return sb; }
const SpinButtons& SpinButtonsObject() const { return sb; }
WithSpin();
WithSpin(IncType inc); // deprecated
WithSpin(DataType min, DataType max, IncType inc); // deprecated
virtual ~WithSpin() {}
};
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()
{
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();
}
}
#include "EditCtrl.hpp"
typedef WithSpin<int, EditInt> EditIntSpin;
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,11 +180,36 @@ int EditField::GetStdHeight(Font font)
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)
{
posx -= GetSpaceLeft();
if(!no_internal_margin)
posx -= 2;
if(posx <= 0) return 0;
@ -281,30 +306,37 @@ Color EditField::GetPaper()
void EditField::Paint(Draw& w)
{
int lspace = GetSpaceLeft();
int rspace = GetSpaceRight();
Size sz = GetSize();
bool enabled = IsShowEnabled();
Color paper = GetPaper();
Color textcolor = GetColorAttr(ATTR_TEXTCOLOR);
Color ink = enabled ? Nvl(textcolor, style->text) : style->textdisabled;
int fcy = font.GetCy();
int yy = GetTy();
w.DrawRect(sz, paper);
PaintSpace(w);
if(!no_internal_margin) {
w.DrawRect(0, 0, 2, sz.cy, paper);
w.DrawRect(0, 0, sz.cx, yy, paper);
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);
lspace += 2;
rspace += 2;
}
if(lspace || rspace)
w.Clipoff(lspace, no_internal_margin ? 0 : yy, sz.cx - lspace - rspace, no_internal_margin ? 0 : fcy);
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))) {
const wchar *txt = nulltext;
WString nt = nulltext.ToWString();
const wchar *txt = nt;
if(!IsNull(nullicon)) {
int icx = nullicon.GetWidth();
w.DrawRect(x, 0, icx + 4, fcy, paper);
w.DrawImage(x, (fcy - nullicon.GetHeight()) / 2, nullicon);
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 {
const wchar *txt = text;
@ -333,9 +365,9 @@ void EditField::Paint(Draw& w)
b = i;
}
}
if(!no_internal_margin)
w.End();
DrawTiles(w, dropcaret, CtrlImg::checkers());
if(lspace || rspace)
w.End();
}
bool EditField::GetSelection(int& l, int& h) const
@ -362,15 +394,14 @@ bool EditField::IsSelection() 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(),
DPI(1), min(GetSize().cy - 2 * GetTy(), font.GetCy()));
}
void EditField::SyncCaret()
Rect EditField::GetCaret() const
{
Rect r = GetCaretRect(cursor);
SetCaret(r.left, r.top, r.GetWidth(), r.GetHeight());
return GetCaretRect(cursor);
}
void EditField::Finish(bool refresh)
@ -391,7 +422,9 @@ void EditField::Finish(bool refresh)
LeftPos(r.left, sz.cx);
sz = GetSize();
}
if(!no_internal_margin)
sz.cx -= 2;
sz.cx -= GetSpaceLeft() + GetSpaceRight();
if(sz.cx <= 0) return;
int x = GetCaret(cursor);
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)
RefreshAll();
SyncCaret();
}
void EditField::Layout()
@ -432,6 +464,7 @@ void EditField::SelSource()
void EditField::GotFocus()
{
auto inactive_convert = (const Convert *)GetVoidPtrAttr(ATTR_INACTIVE_CONVERT);
if(autoformat && IsEditable() && !IsNull(text) && inactive_convert) {
Value v = convert->Scan(text);
if(!v.IsError()) {
@ -453,6 +486,7 @@ void EditField::LostFocus()
if(autoformat && IsEditable() && !IsNull(text) && !IsDragAndDropSource()) {
Value v = convert->Scan(text);
if(!v.IsError()) {
auto inactive_convert = (const Convert *)GetVoidPtrAttr(ATTR_INACTIVE_CONVERT);
const Convert * cv = inactive_convert ? inactive_convert : convert;
WString s = cv->Format(v);
if(s != text) text = s;
@ -487,6 +521,7 @@ void EditField::LeftDown(Point p, dword flags)
return;
}
SetCapture();
EditCapture();
Move(c, flags & K_SHIFT);
Finish();
}
@ -509,7 +544,7 @@ void EditField::LeftUp(Point p, dword flags)
{
int c = GetCursor(p.x + sc);
int l, h;
if(GetSelection(l, h) && c >= l && c < h && !HasCapture() && selclick)
if(GetSelection(l, h) && c >= l && c < h && !HasEditCapture() && selclick)
Move(c, false);
Finish();
selclick = false;
@ -531,7 +566,7 @@ void EditField::LeftTriple(Point p, dword keyflags)
void EditField::MouseMove(Point p, dword flags)
{
if(!HasCapture()) return;
if(!HasEditCapture()) return;
Move(GetCursor(p.x + sc), true);
Finish();
}
@ -645,10 +680,8 @@ void EditField::Remove(int pos, int n)
{
if(IsReadOnly()) return;
text.Remove(pos, n);
if(cursor >= text.GetLength()) {
if(cursor >= text.GetLength())
cursor = text.GetLength();
SyncCaret();
}
Update();
}
@ -706,7 +739,7 @@ void EditField::DragAndDrop(Point p, PasteClip& d)
dc = RectC(x - sc + 2 - font.GetRightSpace('o'), GetTy(),
1, min(GetSize().cy - 2 * GetTy(), font.GetCy()));
}
if(dc != dropcaret) {
if((Rect16)dc != dropcaret) {
Refresh(dropcaret);
dropcaret = dc;
Refresh(dropcaret);
@ -728,7 +761,6 @@ void EditField::DragRepeat(Point p)
if(a != sc) {
sc = a;
Refresh();
SyncCaret();
}
}
@ -745,7 +777,7 @@ void EditField::LeftDrag(Point p, dword flags)
int c = GetCursor(p.x + sc);
Size ssz = StdSampleSize();
int sell, selh;
if(!HasCapture() && GetSelection(sell, selh) && c >= sell && c <= selh) {
if(!HasEditCapture() && GetSelection(sell, selh) && c >= sell && c <= selh) {
WString sel = text.Mid(sell, selh - sell);
ImageDraw iw(ssz);
iw.DrawText(0, 0, sel);
@ -981,6 +1013,7 @@ void EditField::SetText(const WString& txt)
void EditField::SetData(const Value& data)
{
auto inactive_convert = (const Convert *)GetVoidPtrAttr(ATTR_INACTIVE_CONVERT);
const Convert * cv = convert;
if(!HasFocus() && inactive_convert)
cv = inactive_convert;
@ -1010,7 +1043,6 @@ void EditField::Reset()
clickselect = false;
filter = CharFilterUnicode;
convert = &NoConvert();
inactive_convert = NULL;
initcaps = false;
maxlen = INT_MAX;
autosize = false;
@ -1021,10 +1053,10 @@ void EditField::Reset()
SetStyle(StyleDefault());
SetFrame(edge);
font = StdFont();
textcolor = Null;
showspaces = false;
no_internal_margin = false;
fsell = fselh = -1;
DeleteAttr<Image>(ATTR_NULLICON);
}
EditField& EditField::SetFont(Font _font)
@ -1036,25 +1068,27 @@ EditField& EditField::SetFont(Font _font)
EditField& EditField::SetColor(Color c)
{
textcolor = c;
SetColorAttr(ATTR_TEXTCOLOR, c);
Refresh();
return *this;
}
EditField& EditField::NullText(const Image& icon, const char *text, Font fnt, Color ink)
{
nullicon = icon;
nulltext = text;
nulltext << " ";
nullink = ink;
nullfont = fnt;
if(!IsNull(icon))
CreateAttr<Image>(ATTR_NULLICON) = icon;
String h = text;
h << " ";
SetTextAttr(ATTR_NULLTEXT, h);
SetColorAttr(ATTR_NULLINK, ink);
SetFontAttr(ATTR_NULLFONT, fnt);
Refresh();
return *this;
}
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)
@ -1064,7 +1098,7 @@ EditField& EditField::NullText(const char *text, Font fnt, Color ink)
EditField& EditField::NullText(const char *text, Color ink)
{
return NullText(text, GetFont().Italic(), ink);
return NullText(text, Null, ink);
}
EditField::EditField()
@ -1075,6 +1109,9 @@ EditField::EditField()
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) {
int n = col.GetCount();
s / n;
if(n < 0 || n > 10000)
s.LoadError();
Array<Column> col2 = clone(col);
if(s.IsLoading())
col2.InsertN(0, n);
@ -760,7 +762,7 @@ void HeaderCtrl::Serialize(Stream& s) {
s % col2[i].visible;
}
if(s.IsLoading() && n == col.GetCount()) {
col2.Trim(n);
col2.SetCount(n);
col = pick(col2);
}
}

View file

@ -29,14 +29,14 @@ public:
protected:
virtual void LabelUpdate();
String tip;
HeaderCtrl *header;
double ratio;
bool visible;
int min, max;
int margin;
Color paper;
int index;
String tip;
bool visible;
void Paint(bool& first, Draw& w,
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;
}
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
{
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() {}
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) {
DrawLabelExt& lbl = Ext();
lbl.limg = img;
lbl.lspc = spc;
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) {
DrawLabelExt& lbl = Ext();
lbl.rimg = img;
lbl.rspc = spc;
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) {
lbl.paintrect = paintrect;
Ext().paintrect = paintrect;
LabelUpdate();
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)
{
DrawLabel lbl1 = lbl;
DrawLabel lbl1 = Make();
lbl1.disabled = disabled;
lbl1.push = push;
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
{
return lbl.GetSize();
return Make().GetSize();
}
void LinkToolTipIn__();
LabelBase::~LabelBase() {
LabelBase::~LabelBase()
{
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, int max = 16);
struct DrawLabel {
bool push;
bool focus;
bool disabled;
bool limg_never_hide;
bool rimg_never_hide;
PaintRect paintrect;
Image limg;
Color lcolor;
int lspc;
struct DrawLabelBasic {
String text;
Font font;
Color ink, disabledink;
Image rimg;
Color rcolor;
int rspc;
int align, valign;
bool nowrap;
Color ink;
Color disabledink;
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 = 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(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;
DrawLabel();
};
Image DisabledImage(const Image& img, bool disabled = true);
@ -70,7 +79,11 @@ class LabelBase {
protected:
virtual void LabelUpdate();
DrawLabel lbl;
DrawLabelBasic lbl;
One<DrawLabelExt> ext;
DrawLabelExt& Ext() { if(!ext) ext.Create() ; return *ext; }
DrawLabel Make() const;
public:
LabelBase& SetLeftImage(const Image& bmp1, int spc = 0, bool never_hide = false);
@ -94,7 +107,7 @@ public:
int GetAlign() const { return lbl.align; }
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; }
Font GetFont() const { return lbl.font; }
Color GetInk() const { return lbl.ink; }
@ -109,6 +122,9 @@ public:
bool disabled = false, bool push = false, bool focus = false, bool vak = true);
Size GetLabelSize() const;
LabelBase(const LabelBase& src) { lbl = src.lbl; if(src.ext) ext = clone(src.ext); }
LabelBase() {}
virtual ~LabelBase();
};
@ -121,13 +137,13 @@ public:
virtual void FrameAddSize(Size& sz);
private:
Value coloredge;
const Value *edge;
const Ctrl *ctrl;
Value coloredge;
Color color;
bool mousein = false;
bool push = false;
bool button = false;
bool mousein:1;
bool push:1;
bool button:1;
public:
void Set(const Ctrl *ctrl, const Value *edge, bool active);
@ -135,5 +151,5 @@ public:
void Push(bool b) { button = true; push = b; }
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) {
Size fsz = GetFontSize();
p -= sb;
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) {

View file

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

View file

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

View file

@ -106,6 +106,10 @@ public:
static const Style& StyleScroll();
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& AutoStyle();
@ -126,45 +130,6 @@ public:
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 {
public:
virtual void Paint(Draw& draw);
@ -183,13 +148,13 @@ protected:
protected:
Image edge, edged;
int option;
bool switchimage;
bool threestate;
bool notnull;
bool blackedge;
bool showlabel;
bool box;
bool autobox;
bool switchimage:1;
bool threestate:1;
bool notnull:1;
bool blackedge:1;
bool showlabel:1;
bool box:1;
bool autobox:1;
Color color;
void AutoSync();
@ -302,10 +267,10 @@ public:
struct Case {
String label;
Value value;
int accesskey = 0;
bool enabled = true;
int gap = 0;
Rect16 rect = Rect16(0, 0, 0, 0);
int accesskey = 0;
int gap = 0;
bool enabled = true;
};
private:
@ -406,3 +371,70 @@ public:
DataPusher(const Convert& convert, const Display& display = StdDisplay()); // 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;
track = true;
horz = false;
push = light = -1;
thumbsize = 8;
thumbpos = 0;
push = light = -1;
Add(prev);
Add(prev2);
Add(next);
Add(next2);
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;
SetStyle(StyleDefault());
BackPaint();
@ -73,6 +58,93 @@ 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
{
Size sz = GetSize();
@ -135,20 +207,21 @@ Rect ScrollBar::GetPartRect(int p) const {
return h;
}
void ScrollBar::Paint(Draw& w) {
void ScrollBar::Paint(Draw& w)
{
w.DrawRect(GetSize(), style->bgcolor);
int cc;
Size sz = style->through ? GetSize() : Slider(cc).GetSize();
light = GetMousePart();
int p = push;
if(!HasCapture())
if(!HasCapture() || buttons_capture)
p = -1;
const Value *hl[] = { style->hlower, style->hupper, style->hthumb };
const Value *vl[] = { style->vupper, style->vlower, style->vthumb };
const Value **l = IsHorz() ? hl : vl;
if(prev.IsShowEnabled()) {
if(is_active || !autodisable) {
for(int i = 0; i < 3; i++) {
Rect pr = GetPartRect(i);
if(i != 2) {
@ -156,12 +229,12 @@ void ScrollBar::Paint(Draw& w) {
pr = style->through ? GetSize() : Slider();
}
if(i != 2 || thumbsize >= style->thumbmin)
ChPaint(w, pr, l[i][p == i ? CTRL_PRESSED : light == i ? CTRL_HOT : CTRL_NORMAL]);
ChPaint(w, pr, l[i][p == i ? CTRL_PRESSED : light == i && !buttons_capture ? CTRL_HOT : CTRL_NORMAL]);
if(i != 2)
w.End();
}
}
else
else {
if(style->through)
ChPaint(w, sz, l[0][CTRL_DISABLED]);
else
@ -170,6 +243,8 @@ void ScrollBar::Paint(Draw& w) {
else
ChPaint(w, 0, cc, sz.cx, sz.cy, l[0][CTRL_DISABLED]);
}
PaintButtons(w, this);
}
int ScrollBar::GetMousePart()
@ -216,6 +291,13 @@ void ScrollBar::Drag(Point p) {
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) {
push = GetMousePart();
LLOG("ScrollBar::LeftDown(" << p << ")");
@ -243,6 +325,7 @@ void ScrollBar::LeftDown(Point p, dword) {
NextPage();
}
SetCapture();
buttons_capture = false;
Refresh();
WhenLeftClick();
}
@ -289,6 +372,7 @@ void ScrollBar::MouseWheel(Point p, int zdelta, dword keyflags)
void ScrollBar::CancelMode() {
push = light = -1;
ButtonsCancelMode();
}
bool ScrollBar::Set(int apagepos) {
@ -330,19 +414,16 @@ bool ScrollBar::Set(int apagepos) {
void ScrollBar::Set(int _pagepos, int _pagesize, int _totalsize) {
pagesize = _pagesize;
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()) {
Show(is_active);
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);
}
@ -472,38 +553,6 @@ bool ScrollBar::HorzKey(dword key) {
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) {
int new_pos = pagepos;
if(pos > new_pos + pagesize - _linesize)
@ -560,14 +609,7 @@ ScrollBar& ScrollBar::AutoHide(bool b) {
ScrollBar& ScrollBar::AutoDisable(bool b) {
autodisable = b;
if(!b) {
if(!prev.IsEnabled())
Refresh();
prev.Enable();
prev2.Enable();
next.Enable();
next2.Enable();
}
return *this;
}

View file

@ -1,4 +1,4 @@
class ScrollBar : public FrameCtrl<Ctrl> {
class ScrollBar : public FrameCtrl<Ctrl>, private VirtualButtons {
public:
virtual void Layout();
virtual Size GetStdSize() const;
@ -15,6 +15,16 @@ public:
virtual void FrameLayout(Rect& r);
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:
struct Style : ChStyle<Style> {
Color bgcolor;
@ -30,19 +40,20 @@ public:
private:
int thumbpos;
int thumbsize;
bool horz:1;
bool jump:1;
bool track:1;
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 pagesize;
int totalsize;
int linesize;
int minthumb;
int8 push;
int8 light;
bool horz:1;
bool jump:1;
bool track:1;
bool autohide:1;
bool autodisable:1;
bool is_active:1;

View file

@ -2,12 +2,73 @@
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)
{
DrawLabel l;
MakeDrawLabel(l);
Size sz = GetSize();
if(!IsTransparent())
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
@ -15,8 +76,11 @@ Size StaticText::GetMinSize() const
return GetLabelSize();
}
void StaticText::LabelUpdate() {
Refresh();
Size StaticText::GetLabelSize() const
{
DrawLabel l;
MakeDrawLabel(l);
return l.GetSize();
}
StaticText::StaticText()
@ -24,13 +88,17 @@ StaticText::StaticText()
NoWantFocus();
IgnoreMouse();
Transparent();
SetAlign(ALIGN_LEFT);
}
StaticText::~StaticText()
{
DeleteAttr<Image>(ATTR_IMAGE);
}
Label& Label::SetText(const char *text)
{
LabelBase::SetText(text);
lbl.accesskey = 0;
accesskey = 0;
StaticText::SetText(text);
noac = false;
return *this;
}
@ -38,14 +106,13 @@ Label& Label::SetText(const char *text)
Label& Label::SetLabel(const char *_text)
{
String text;
int accesskey = ExtractAccessKey(_text, text);
LabelBase::SetText(text);
lbl.accesskey = accesskey;
accesskey = ExtractAccessKey(_text, text);
StaticText::SetText(text);
return *this;
}
bool Label::HotKey(dword key) {
if(CompareAccessKey(lbl.accesskey, key)) {
if(CompareAccessKey(accesskey, key)) {
IterateFocusForward(this, GetParent());
return true;
}
@ -54,7 +121,7 @@ bool Label::HotKey(dword key) {
dword Label::GetAccessKeys() const
{
return AccessKeyBit(lbl.accesskey);
return AccessKeyBit(accesskey);
}
void Label::AssignAccessKeys(dword used)
@ -62,12 +129,12 @@ void Label::AssignAccessKeys(dword used)
if(noac)
return;
Ctrl *next = GetNext();
if(!lbl.accesskey && next && next->IsInitFocus()) {
if(!accesskey && next && next->IsInitFocus()) {
next->AssignAccessKeys(used);
if(!next->GetAccessKeysDeep()) {
lbl.accesskey = ChooseAccessKey(GetText(), used);
if(lbl.accesskey) Refresh();
used |= AccessKeyBit(lbl.accesskey);
accesskey = ChooseAccessKey(text, used);
if(accesskey) Refresh();
used |= AccessKeyBit(accesskey);
}
}
Ctrl::AssignAccessKeys(used);
@ -79,16 +146,10 @@ Label::Label() {
Label::~Label() {}
CH_COLOR(LabelBoxColor, SColorShadow());
CH_COLOR(LabelBoxTextColor, SColorText());
CH_COLOR(LabelBoxDisabledTextColor, SColorDisabled());
LabelBox::LabelBox()
{
color = Null;
LabelBase::SetInk(LabelBoxTextColor(), LabelBoxDisabledTextColor());
SetVAlign(ALIGN_TOP);
SetInk(LabelBoxTextColor());
}
void LabelBox::AssignAccessKeys(dword used)
@ -192,7 +253,9 @@ void LabelBox::Paint(Draw& w)
Size lsz = GetLabelSize();
int d = lsz.cy >> 1;
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.ExcludeClip(d, ty, ts.cx + DPI(4), ts.cy);
PaintLabelBox(w, sz, color, d);

View file

@ -1,19 +1,38 @@
class StaticText : public Ctrl, public LabelBase {
class StaticText : public Ctrl {
public:
virtual void Paint(Draw& w);
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:
StaticText& SetFont(Font font) { LabelBase::SetFont(font); return *this; }
StaticText& SetInk(Color color) { LabelBase::SetInk(color); return *this; }
StaticText& SetAlign(int align) { LabelBase::SetAlign(align); return *this; }
StaticText& SetImage(const Image& img, int spc = 0) { LabelBase::SetImage(img, spc); return *this; }
StaticText& SetText(const char *text) { LabelBase::SetText(text); return *this; }
StaticText& SetFont(Font font);
StaticText& SetInk(Color color);
StaticText& SetAlign(int align);
StaticText& AlignLeft() { return SetAlign(ALIGN_LEFT); }
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();
~StaticText();
};
class Label : public StaticText {

View file

@ -299,6 +299,7 @@ public:
virtual void Layout();
virtual void RefreshLine(int i);
virtual Font GetPreeditFont();
virtual Rect GetCaret() const;
protected:
virtual void SetSb();
@ -507,6 +508,8 @@ public:
virtual void DragLeave();
virtual void LeftDrag(Point p, dword flags);
virtual Rect GetCaret() const;
protected:
virtual void ClearLines();
virtual void InsertLines(int line, int count);
@ -527,6 +530,7 @@ protected:
ScrollBar sb;
int cx;
bool updownleave, eofline;
Rect caret;
struct Fmt {
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]
[b42;2 $$9,9#13035079074754324216151401829390:normal]
[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; &]
[ {{10000@3 [s0; [*@(229)4 StaticText]]}}&]
[s0; &]
[ {{10000F(128)G(128)@1 [s0;%% [* Public Method List]]}}&]
[s3; &]
[s1;:StaticText`:`:class:%- [@(0.0.255)3 class][3 _][*3 StaticText][3 _:_][@(0.0.255)3 public][3 _
][*@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) `&
[s5;:StaticText`:`:SetFont`(Font`): [@(0.0.255) virtual] [_^StaticText^ StaticText][@(0.0.255) `&
]_[* SetFont]([_^Font^ Font]_[*@3 font])&]
[s2; Sets the [%-*@3 font] of text.&]
[s3; &]
[s4;%- &]
[s5;:StaticText`:`:SetInk`(Color`):%- [@(0.0.255) virtual] [_^StaticText^ StaticText][@(0.0.255) `&
[s2;%% Sets the [%-*@3 font] of text.&]
[s3;%% &]
[s4; &]
[s5;:StaticText`:`:SetInk`(Color`): [@(0.0.255) virtual] [_^StaticText^ StaticText][@(0.0.255) `&
]_[* SetInk]([_^Color^ Color]_[*@3 color])&]
[s2; Sets the [%-*@3 color] of text.&]
[s3; &]
[s4;%- &]
[s5;:StaticText`:`:SetAlign`(int`):%- [@(0.0.255) virtual] [_^StaticText^ StaticText][@(0.0.255) `&
[s2;%% Sets the [%-*@3 color] of text.&]
[s3;%% &]
[s4; &]
[s5;:StaticText`:`:SetAlign`(int`): [@(0.0.255) virtual] [_^StaticText^ StaticText][@(0.0.255) `&
]_[* 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.&]
[s3;%% &]
[s4; &]
[s5;:Upp`:`:StaticText`:`:AlignLeft`(`): [_^Upp`:`:StaticText^ StaticText][@(0.0.255) `&]_
[* AlignLeft]()&]
[s2;%% Same as SetAlign(ALIGN`_LEFT).&]
[s3; &]
[s4;%- &]
[s5;:StaticText`:`:SetImage`(const Image`&`,int`):%- [@(0.0.255) virtual]
[s4; &]
[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) `&
]_[*@3 img], [@(0.0.255) int]_[*@3 spc]_`=_[@3 0])&]
[s2; Sets the Image to be displayed before the text. [%-*@3 spc] is
space between the text and Image.&]
[s3; &]
[s4;%- &]
[s5;:StaticText`:`:SetText`(const char`*`):%- [@(0.0.255) virtual]
[_^StaticText^ StaticText][@(0.0.255) `&]_[* SetText]([@(0.0.255) const]_[@(0.0.255) char]_
`*[*@3 text])&]
[s5;:StaticText`:`:operator`=`(const char`*`):%- [_^StaticText^ StaticText][@(0.0.255) `&
]_[* operator`=]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 s])&]
[s2; Sets [%-*@3 text]. `"`\1`" at the beginning of text activates
[s2;%% Sets the Image to be displayed before the text. [%-*@3 spc]
is space between the text and Image.&]
[s3;%% &]
[s4; &]
[s5;:StaticText`:`:SetText`(const char`*`): [@(0.0.255) virtual] [_^StaticText^ StaticTex
t][@(0.0.255) `&]_[* SetText]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 text])&]
[s5;:StaticText`:`:operator`=`(const char`*`): [_^StaticText^ StaticText][@(0.0.255) `&]_
[* operator`=]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 s])&]
[s2;%% Sets [%-*@3 text]. `"`\1`" at the beginning of text activates
QTF.&]
[s3; &]
[s3;%% &]
[s0;%% &]
[s0;%% &]
[s0; &]
[s0; &]
[s0;%- &]
[ {{10000@3 [s0; [*@(229)4 Label]]}}&]
[s3; &]
[s1;:Label`:`:class:%- [@(0.0.255)3 class][3 _][*3 Label][3 _:_][@(0.0.255)3 public][3 _][*@3;3 Stat
icText]&]
[s9; Generally used to label other widgets. Differs from StaticText
[ {{10000@3 [s0;%% [*@(229)4 Label]]}}&]
[s3;%% &]
[s1;:Label`:`:class: [@(0.0.255)3 class][3 _][*3 Label][3 _:_][@(0.0.255)3 public][3 _][*@3;3 Static
Text]&]
[s9;%% Generally used to label other widgets. Differs from StaticText
by implementing hotkey processing. Hotkeys are assigned automatically
by U`+`+ library, however they can also by preassigned using
`'`&`' character.&]
[s3;%- &]
[s0;%- &]
[ {{10000F(128)G(128)@1 [s0; [* Public Method List]]}}&]
[s3;%- &]
[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])&]
[s5;:Label`:`:operator`=`(const char`*`):%- [@(0.0.255) virtual] [_^Label^ Label][@(0.0.255) `&
[s3; &]
[s0; &]
[ {{10000F(128)G(128)@1 [s0;%% [* Public Method List]]}}&]
[s3; &]
[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])&]
[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])&]
[s2; Sets the text. Ignores `'`&`' used to mark hotkeys.&]
[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; &]
[s2;%% Sets the text. Ignores `'`&`' used to mark hotkeys.&]
[s3;%% &]
[s4; &]
[s5;:LabelBox`:`:SetColor`(Color`):%- [_^LabelBox^ LabelBox][@(0.0.255) `&]_[* SetColor]([_^Color^ C
olor]_[*@3 c])&]
[s2; Sets the color of LabelBox.&]
[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; &]
[s0;%- &]
[ {{10000@3 [s0; [*@(229)4 ParentCtrl]]}}&]
[ {{10000F(128)G(128)@1 [s0;%% [* Public Method List]]}}&]
[s3; &]
[s1;:ParentCtrl`:`:class:%- [@(0.0.255)3 class][3 _][*3 ParentCtrl][3 _:_][@(0.0.255)3 public][3 _
][*@3;3 Ctrl]&]
[s9; This class is supposed to be used as logical parent in situation
[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;%% &]
[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
from Ctrl is that ParentCtrl activates Transparent in constructor.&]
[s3; &]
[s3;%% &]
[s0;%% &]
[s0;%% &]
[s0; &]
[s0; &]
[s0;%- &]
[ {{10000@3 [s0; [*@(229)4 StaticRect]]}}&]
[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
[ {{10000@3 [s0;%% [*@(229)4 StaticRect]]}}&]
[s3;%% &]
[s1;:StaticRect`:`:class: [@(0.0.255)3 class][3 _][*3 StaticRect][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) `&]_[* S
etImage]([@(0.0.255) const]_[_^Image^ Image][@(0.0.255) `&]_[*@3 `_img])&]
[s2; Sets the image.&]
[s9;%% Widget completely filled with single color.&]
[s3; &]
[s0; &]
[s0; &]
[s0;%- &]
[ {{10000@3 [s0; [*@(229)4 DrawingCtrl]]}}&]
[ {{10000F(128)G(128)@1 [s0;%% [* Public Method List]]}}&]
[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]&]
[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.&]
[s9;%% Displays Drawing.&]
[s3; &]
[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) `&]_[* KeepRat
io]([@(0.0.255) bool]_[*@3 keep]_`=_[@(0.0.255) true])&]
[s2; If active, Picture keeps the aspect ratio of Drawing. Default
[s0; &]
[ {{10000F(128)G(128)@1 [s0;%% [* Public Method List]]}}&]
[s3; &]
[s5;:DrawingCtrl`:`:Background`(Color`): [_^Picture^ DrawingCtrl][@(0.0.255) `&]_[* Backgro
und]([_^Color^ Color]_[*@3 color])&]
[s2;%% Sets background [%-*@3 color]. Default is white.&]
[s3;%% &]
[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.&]
[s3; &]
[s4;%- &]
[s5;:DrawingCtrl`:`:NoKeepRatio`(`):%- [_^Picture^ DrawingCtrl][@(0.0.255) `&]_[* NoKeepRat
io]()&]
[s2; Do not keep aspect ratio.&]
[s3; &]
[s4;%- &]
[s5;:DrawingCtrl`:`:Set`(const Drawing`&`):%- [_^Picture^ DrawingCtrl][@(0.0.255) `&]_[* Se
t]([@(0.0.255) const]_[_^Drawing^ Drawing][@(0.0.255) `&]_[*@3 `_picture])&]
[s5;:DrawingCtrl`:`:operator`=`(const Drawing`&`):%- [_^Picture^ DrawingCtrl][@(0.0.255) `&
[s3;%% &]
[s4; &]
[s5;:DrawingCtrl`:`:NoKeepRatio`(`): [_^Picture^ DrawingCtrl][@(0.0.255) `&]_[* NoKeepRatio
]()&]
[s2;%% Do not keep aspect ratio.&]
[s3;%% &]
[s4; &]
[s5;:DrawingCtrl`:`:Set`(const Drawing`&`): [_^Picture^ DrawingCtrl][@(0.0.255) `&]_[* Set](
[@(0.0.255) const]_[_^Drawing^ Drawing][@(0.0.255) `&]_[*@3 `_picture])&]
[s5;:DrawingCtrl`:`:operator`=`(const Drawing`&`): [_^Picture^ DrawingCtrl][@(0.0.255) `&
]_[* operator`=]([@(0.0.255) const]_[_^Drawing^ Drawing][@(0.0.255) `&]_[*@3 `_picture])&]
[s2; Assigns the Drawing.&]
[s3; &]
[s4;%- &]
[s5;:DrawingCtrl`:`:operator`=`(const Painting`&`):%- [_^Picture^ DrawingCtrl][@(0.0.255) `&
[s2;%% Assigns the Drawing.&]
[s3;%% &]
[s4; &]
[s5;:DrawingCtrl`:`:operator`=`(const Painting`&`): [_^Picture^ DrawingCtrl][@(0.0.255) `&
]_[* 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]]}}&]
[s3; &]
[s1;:SeparatorCtrl`:`:class:%- [@(0.0.255)3 class][3 _][*3 SeparatorCtrl][3 _:_][@(0.0.255)3 pub
lic][3 _][*@3;3 Ctrl]&]
[s9; Horizontal or vertical separator line. Direction depends on
[ {{10000@3 [s0;%% [*@(229)4 SeparatorCtrl]]}}&]
[s3;%% &]
[s1;:SeparatorCtrl`:`:class: [@(0.0.255)3 class][3 _][*3 SeparatorCtrl][3 _:_][@(0.0.255)3 publi
c][3 _][*@3;3 Ctrl]&]
[s9;%% Horizontal or vertical separator line. Direction depends on
aspect ratio.&]
[s3;%- &]
[s0;%- &]
[ {{10000F(128)G(128)@1 [s0; [* Public Method List]]}}&]
[s3;%- &]
[s5;:SeparatorCtrl`:`:Margin`(int`):%- [_^SeparatorCtrl^ SeparatorCtrl][@(0.0.255) `&]_[* M
argin]([@(0.0.255) int]_[*@3 w])&]
[s2; Sets the left`-right (for horizontal separator) or top`-bottom
[s3; &]
[s0; &]
[ {{10000F(128)G(128)@1 [s0;%% [* Public Method List]]}}&]
[s3; &]
[s5;:SeparatorCtrl`:`:Margin`(int`): [_^SeparatorCtrl^ SeparatorCtrl][@(0.0.255) `&]_[* Mar
gin]([@(0.0.255) int]_[*@3 w])&]
[s2;%% Sets the left`-right (for horizontal separator) or top`-bottom
margin. Default value is 2.&]
[s3; &]
[s4;%- &]
[s5;:SeparatorCtrl`:`:Margin`(int`,int`):%- [_^SeparatorCtrl^ SeparatorCtrl][@(0.0.255) `&
]_[* Margin]([@(0.0.255) int]_[*@3 l], [@(0.0.255) int]_[*@3 r])&]
[s2; Sets the top`-right (for horizontal separator) or top`-bottom
[s3;%% &]
[s4; &]
[s5;:SeparatorCtrl`:`:Margin`(int`,int`): [_^SeparatorCtrl^ SeparatorCtrl][@(0.0.255) `&]_
[* Margin]([@(0.0.255) int]_[*@3 l], [@(0.0.255) int]_[*@3 r])&]
[s2;%% Sets the top`-right (for horizontal separator) or top`-bottom
to [%-*@3 l] and [%-*@3 r], in that order. Default value is 2.&]
[s3; &]
[s4;%- &]
[s5;:SeparatorCtrl`:`:SetSize`(int`):%- [_^SeparatorCtrl^ SeparatorCtrl][@(0.0.255) `&]_[* S
etSize]([@(0.0.255) int]_[*@3 w])&]
[s2; Sets the size returned by GetMinSize `- included to affect the
way how widget is treated in BarCtrl. Default value is 7.&]
[s3; &]
[s4;%- &]
[s5;:SeparatorCtrl`:`:SetStyle`(const SeparatorCtrl`:`:Style`&`):%- [_^SeparatorCtrl^ S
eparatorCtrl][@(0.0.255) `&]_[* SetStyle]([@(0.0.255) const]_[_^SeparatorCtrl`:`:Style^ S
tyle][@(0.0.255) `&]_[*@3 s])&]
[s2; Sets the visual style to SeparatorCtrl`::Style [%-*@3 s]. The style
is a simple structure with two fields:&]
[s7; [*@5 l1]-|the first margin&]
[s7;%- [*@5 l2]-|the second margin&]
[s3; &]
[s0; ]]
[s3;%% &]
[s4; &]
[s5;:SeparatorCtrl`:`:SetSize`(int`): [_^SeparatorCtrl^ SeparatorCtrl][@(0.0.255) `&]_[* Se
tSize]([@(0.0.255) int]_[*@3 w])&]
[s2;%% Sets the size returned by GetMinSize `- included to affect
the way how widget is treated in BarCtrl. Default value is 7.&]
[s3;%% &]
[s4; &]
[s5;:SeparatorCtrl`:`:SetStyle`(const SeparatorCtrl`:`:Style`&`): [_^SeparatorCtrl^ Sep
aratorCtrl][@(0.0.255) `&]_[* SetStyle]([@(0.0.255) const]_[_^SeparatorCtrl`:`:Style^ Sty
le][@(0.0.255) `&]_[*@3 s])&]
[s2;%% Sets the visual style to SeparatorCtrl`::Style [%-*@3 s]. The
style is a simple structure with two fields:&]
[s7;%% [*@5 l1]-|the first margin&]
[s7; [*@5 l2]-|the second margin&]
[s3;%% &]
[s0;%% ]]

View file

@ -94,14 +94,6 @@ is active.&]
[s5;:Upp`:`:WithSpin`:`:NoKeySpin`(`):%- [_^Upp`:`:WithSpin^ WithSpin][@(0.0.255) `&]_[* No
KeySpin]()&]
[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;%- &]
[ {{10000@(113.42.0) [s0; [*@7;4 Predefined WithSpin widgets]]}}&]
[s3;%- &]

View file

@ -36,7 +36,7 @@ class FontInfo;
inline
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;
}
@ -212,6 +212,8 @@ public:
operator Value() const { return RichToValue(*this); }
Font(const Value& q) { *this = q.Get<Font>(); }
static Font FromInt64(int64 q) { Font fnt; fnt.data = q; return fnt; }
// BW compatibility
FontInfo Info() const;
};

View file

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

View file

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

View file

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

View file

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

View file

@ -25,7 +25,7 @@ private:
void DestroyWnd();
void NewTop() { top = new Top; top->owner_window = NULL; }
void NewTop() { SetTop(new Top); GetTop()->owner_window = NULL; }
void PutForeground();
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;
}
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()
{
LLOG("@ CursorSync");
Point p = GetMousePos() - fbCursorImage.GetHotSpot();
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) {
fbCursorPos = p;
if(!(VirtualGuiPtr->GetOptions() & GUI_SETMOUSECURSOR))
Invalidate();
}
if(cr != fbCaretRect) {
fbCaretRect = cr;
if(VirtualGuiPtr->GetOptions() & GUI_SETCARET)
VirtualGuiPtr->SetCaret(cr);
else
Invalidate();
}
}
bool Ctrl::ProcessEvent(bool *quit)
@ -159,6 +132,7 @@ bool Ctrl::ProcessEvents(bool *quit)
LLOG("TimerProc invoked at " << msecs());
TimerProc(msecs());
LLOG("TimerProc elapsed: " << tm);
AnimateCaret();
SweepMkImageCache();
DoPaint();
return ret;

View file

@ -35,6 +35,7 @@ bool Ctrl::invalid;
Point Ctrl::fbCursorPos = Null;
Image Ctrl::fbCursorImage;
Rect Ctrl::fbCaretRect;
int Ctrl::fbCaretTm;
bool Ctrl::fbEndSession;
@ -73,9 +74,9 @@ Ctrl *Ctrl::GetOwner()
{
GuiLock __;
int q = FindTopCtrl();
if(q > 0 && topctrl[q]->top) {
Ctrl *x = topctrl[q]->top->owner_window;
LDUMP(Upp::Name(x));
Top *top = topctrl[q]->GetTop();
if(q > 0 && top) {
Ctrl *x = top->owner_window;
return dynamic_cast<TopWindowFrame *>(x) ? x->GetOwner() : x;
}
return NULL;
@ -87,36 +88,13 @@ Ctrl *Ctrl::GetActiveCtrl()
return focusCtrl ? focusCtrl->GetTopCtrl() : NULL;
}
// Vector<Callback> Ctrl::hotkey;
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;
}
void Ctrl::UnregisterSystemHotKey(int id)
{
/* if(id >= 0 && id < hotkey.GetCount()) {
UnregisterHotKey(NULL, id);
hotkey[id].Clear();
}*/
}
bool Ctrl::IsWaitingEvent()
@ -135,30 +113,12 @@ void Ctrl::SyncTopWindows()
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()
{
// Ctrl::DoUpdate();
}
Rect Ctrl::GetClipBound(const Vector<Rect>& inv, const Rect& r)
{
Rect ri = Null;
@ -306,18 +266,18 @@ int Ctrl::GetKbdSpeed()
void Ctrl::DestroyWnd()
{
for(int i = 0; i < topctrl.GetCount(); i++)
if(topctrl[i]->top && topctrl[i]->top->owner_window == this)
for(int i = 0; i < topctrl.GetCount(); i++) {
Top *top = topctrl[i]->GetTop();
if(top && top->owner_window == this)
topctrl[i]->WndDestroy();
}
int q = FindTopCtrl();
if(q >= 0) {
Invalidate();
topctrl.Remove(q);
}
if(top) {
delete top;
top = NULL;
}
if(top)
DeleteTop();
isopen = false;
TopWindow *win = dynamic_cast<TopWindow *>(this);
if(win)
@ -341,8 +301,11 @@ void Ctrl::PutForeground()
}
Vector< Ptr<Ctrl> > fw;
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]) {
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++)
if(fw[i])
fw[i]->PutForeground();
@ -355,8 +318,8 @@ void Ctrl::SetWndForeground()
if(IsWndForeground())
return;
Ctrl *to = this;
while(to->top && to->top->owner_window)
to = to->top->owner_window;
while(to->GetTop() && to->GetTop()->owner_window)
to = to->GetTop()->owner_window;
to->PutForeground();
if(this != focusCtrl)
ActivateWnd();
@ -445,7 +408,8 @@ void Ctrl::PopUp(Ctrl *owner, bool savebits, bool activate, bool dropshadow, boo
ASSERT(owner_window->IsOpen());
if(owner_window != desktop) {
owner_window->SetForeground();
top->owner_window = owner_window;
if(GetTop())
GetTop()->owner_window = owner_window;
}
}
topctrl.Add(this);
@ -496,10 +460,8 @@ void Ctrl::SysEndLoop()
void Ctrl::DeleteDesktopTop()
{
if(desktop && desktop->top) {
delete desktop->top;
desktop->top = NULL;
}
if(desktop && desktop->GetTop())
desktop->DeleteTop();
}
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
etOptions]()&]
[s2;%% Returns a set of flags describing some aspects of VirtualGui
behaviour. Available option flags are:-|&]
behaviour. Available option flags are:&]
[s2;%% &]
[s7;i1120;a17;:Ctrl`:`:CENTER:%% [%-*C@3 GUI`_SETMOUSECURSOR]-|Use the
SetMouseCursor() method instead of painting the cursor.&]

View file

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

View file

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