mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-16 06:05:58 -06:00
294 lines
5.9 KiB
C++
294 lines
5.9 KiB
C++
#include "CtrlCore.h"
|
|
|
|
namespace Upp {
|
|
|
|
#define LLOG(x) // DLOG(x)
|
|
|
|
bool Ctrl::HasDHCtrl() const
|
|
{
|
|
GuiLock __;
|
|
if(dynamic_cast<const DHCtrl *>(this))
|
|
return true;
|
|
for(Ctrl *q = GetFirstChild(); q; q = q->next)
|
|
if(q->HasDHCtrl())
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
void Ctrl::SyncDHCtrl()
|
|
{
|
|
GuiLock __;
|
|
Ctrl *p = GetTopCtrl();
|
|
p->hasdhctrl = p->HasDHCtrl();
|
|
}
|
|
|
|
void Ctrl::AddChild(Ctrl *q, Ctrl *p)
|
|
{
|
|
GuiLock __;
|
|
ASSERT(q);
|
|
LLOG("Add " << UPP::Name(q) << " to: " << Name());
|
|
if(p == q) return;
|
|
bool updaterect = true;
|
|
if(q->parent) {
|
|
ASSERT(!q->inframe);
|
|
if(q->parent == this) {
|
|
RemoveChild0(q);
|
|
updaterect = false;
|
|
}
|
|
else
|
|
q->parent->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;
|
|
}
|
|
else {
|
|
ASSERT(lastchild == NULL);
|
|
firstchild = lastchild = q;
|
|
q->prev = q->next = NULL;
|
|
}
|
|
q->CancelModeDeep();
|
|
if(updaterect)
|
|
q->UpdateRect();
|
|
ChildAdded(q);
|
|
q->ParentChange();
|
|
if(updaterect && GetTopCtrl()->IsOpen())
|
|
q->StateH(OPEN);
|
|
if(dynamic_cast<DHCtrl *>(q))
|
|
SyncDHCtrl();
|
|
}
|
|
|
|
void Ctrl::AddChild(Ctrl *child)
|
|
{
|
|
AddChild(child, lastchild);
|
|
}
|
|
|
|
void Ctrl::AddChildBefore(Ctrl *child, Ctrl *insbefore)
|
|
{
|
|
if(insbefore)
|
|
AddChild(child, insbefore->prev);
|
|
else
|
|
AddChild(child);
|
|
}
|
|
|
|
void Ctrl::RemoveChild0(Ctrl *q)
|
|
{
|
|
GuiLock __;
|
|
ChildRemoved(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(dynamic_cast<DHCtrl *>(q))
|
|
SyncDHCtrl();
|
|
}
|
|
|
|
void Ctrl::RemoveChild(Ctrl *q)
|
|
{
|
|
GuiLock __;
|
|
if(q->parent != this) return;
|
|
q->RefreshFrame();
|
|
RemoveChild0(q);
|
|
q->ParentChange();
|
|
if(GetTopCtrl()->IsOpen())
|
|
q->StateH(CLOSE);
|
|
}
|
|
|
|
void Ctrl::Remove()
|
|
{
|
|
GuiLock __;
|
|
if(parent)
|
|
parent->RemoveChild(this);
|
|
}
|
|
|
|
int Ctrl::GetChildIndex(const Ctrl *child) const
|
|
{
|
|
GuiLock __;
|
|
int i = 0;
|
|
for (Ctrl *c = GetFirstChild(); c; c = c->GetNext()) {
|
|
if(c == child) return i;
|
|
i++;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int Ctrl::GetChildCount() const
|
|
{
|
|
GuiLock __;
|
|
int n = 0;
|
|
for (Ctrl *c = GetFirstChild(); c; c = c->GetNext())
|
|
n++;
|
|
return n;
|
|
}
|
|
|
|
Ctrl * Ctrl::GetIndexChild(int ii) const
|
|
{
|
|
GuiLock __;
|
|
Ctrl *c = GetFirstChild();
|
|
for(int i = 0; i < ii && c; i++)
|
|
c = c->GetNext();
|
|
return c;
|
|
}
|
|
|
|
bool Ctrl::HasChild(Ctrl *q) const
|
|
{
|
|
GuiLock __;
|
|
return q && q->IsChild() && q->parent == this;
|
|
}
|
|
|
|
bool Ctrl::HasChildDeep(Ctrl *q) const
|
|
{
|
|
GuiLock __;
|
|
while(q && q->IsChild()) {
|
|
if(q->parent == this) return true;
|
|
q = q->parent;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static bool IterateFocusFw(Ctrl *ctrl, bool noframe, bool init, bool all)
|
|
{
|
|
LLOG("IterateFocusFw(" << UPP::Name(ctrl) << ")");
|
|
while(ctrl) {
|
|
if(ctrl->IsOpen() && ctrl->IsVisible() && ctrl->IsEnabled()) {
|
|
if(!(noframe && ctrl->InFrame())) {
|
|
if(all) {
|
|
ctrl->SetFocus();
|
|
return true;
|
|
}
|
|
if((!init || ctrl->IsInitFocus()) && ctrl->SetWantFocus())
|
|
return true;
|
|
}
|
|
if(IterateFocusFw(ctrl->GetFirstChild(), noframe, init, all))
|
|
return true;
|
|
}
|
|
ctrl = ctrl->GetNext();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Ctrl::IterateFocusForward(Ctrl *ctrl, Ctrl *top, bool noframe, bool init, bool all)
|
|
{
|
|
GuiLock __;
|
|
LLOG("IterateFocusForward(" << UPP::Name(ctrl) << ", top " << UPP::Name(top) << ", noframe " << noframe << ", init " << init << ")");
|
|
if(!ctrl) return false;
|
|
if(IterateFocusFw(ctrl->GetFirstChild(), noframe, init, all))
|
|
return true;
|
|
if(ctrl->GetNext() && IterateFocusFw(ctrl->GetNext(), noframe, init, all))
|
|
return true;
|
|
while(ctrl->GetParent() != top && (ctrl = ctrl->GetParent()) != NULL)
|
|
if(IterateFocusFw(ctrl->GetNext(), noframe, init, all))
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
static bool IterateFocusBw(Ctrl *ctrl, bool noframe, bool all)
|
|
{
|
|
while(ctrl) {
|
|
if(ctrl->IsOpen() && ctrl->IsVisible() && ctrl->IsEnabled()) {
|
|
if(IterateFocusBw(ctrl->GetLastChild(), noframe, all))
|
|
return true;
|
|
if(!(noframe && ctrl->InFrame())) {
|
|
if(all) {
|
|
ctrl->SetFocus();
|
|
return true;
|
|
}
|
|
if(ctrl->SetWantFocus())
|
|
return true;
|
|
}
|
|
}
|
|
ctrl = ctrl->GetPrev();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Ctrl::IterateFocusBackward(Ctrl *ctrl, Ctrl *top, bool noframe, bool all)
|
|
{
|
|
GuiLock __;
|
|
if(!ctrl || ctrl == top) return false;
|
|
if(IterateFocusBw(ctrl->GetPrev(), noframe, all))
|
|
return true;
|
|
while(ctrl->GetParent() != top) {
|
|
ctrl = ctrl->GetParent();
|
|
if(ctrl->SetWantFocus())
|
|
return true;
|
|
if(IterateFocusBw(ctrl->GetPrev(), noframe, all))
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
Ctrl *Ctrl::GetTopCtrl()
|
|
{
|
|
GuiLock __;
|
|
Ctrl *q = this;
|
|
while(q->parent)
|
|
q = q->parent;
|
|
return q;
|
|
}
|
|
|
|
const Ctrl *Ctrl::GetTopCtrl() const { return const_cast<Ctrl *>(this)->GetTopCtrl(); }
|
|
const Ctrl *Ctrl::GetOwner() const { return const_cast<Ctrl *>(this)->GetOwner(); }
|
|
Ctrl *Ctrl::GetTopCtrlOwner() { return GetTopCtrl()->GetOwner(); }
|
|
const Ctrl *Ctrl::GetTopCtrlOwner() const { return GetTopCtrl()->GetOwner(); }
|
|
|
|
Ctrl *Ctrl::GetOwnerCtrl() { GuiLock __; return !IsChild() && top ? top->owner : NULL; }
|
|
const Ctrl *Ctrl::GetOwnerCtrl() const { return const_cast<Ctrl *>(this)->GetOwnerCtrl(); }
|
|
|
|
TopWindow *Ctrl::GetTopWindow()
|
|
{
|
|
GuiLock __;
|
|
Ctrl *q = this;
|
|
while(q) {
|
|
q = q->GetTopCtrl();
|
|
TopWindow *w = dynamic_cast<TopWindow *>(q);
|
|
if(w) return w;
|
|
q = q->GetOwner();
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
const TopWindow *Ctrl::GetTopWindow() const
|
|
{
|
|
return const_cast<Ctrl *>(this)->GetTopWindow();
|
|
}
|
|
|
|
TopWindow *Ctrl::GetMainWindow()
|
|
{
|
|
GuiLock __;
|
|
Ctrl *q = GetTopCtrl();
|
|
for(;;) {
|
|
Ctrl *w = q->GetOwner();
|
|
if(!w)
|
|
return dynamic_cast<TopWindow *>(q);
|
|
q = w;
|
|
}
|
|
}
|
|
|
|
const TopWindow *Ctrl::GetMainWindow() const
|
|
{
|
|
return const_cast<Ctrl *>(this)->GetMainWindow();
|
|
}
|
|
|
|
}
|