mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 14:16:07 -06:00
331 lines
6.6 KiB
C++
331 lines
6.6 KiB
C++
#include "CtrlCore.h"
|
|
|
|
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);
|
|
}
|
|
|
|
void Ctrl::AddChild(Ctrl *q, Ctrl *p)
|
|
{
|
|
GuiLock __;
|
|
ASSERT(q);
|
|
LLOG("Add " << UPP::Name(q) << " to: " << Name());
|
|
if(p == q) return;
|
|
bool updaterect = true;
|
|
Ctrl *qparent = q->GetParent();
|
|
if(qparent) {
|
|
ASSERT(!q->inframe);
|
|
if(qparent == this) {
|
|
RemoveChild0(q);
|
|
updaterect = false;
|
|
}
|
|
else
|
|
qparent->RemoveChild(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(!p);
|
|
children = q->next_sibling = q->prev_sibling = q;
|
|
}
|
|
q->SetParent(this);
|
|
|
|
q->CancelModeDeep();
|
|
if(updaterect)
|
|
q->UpdateRect();
|
|
ChildAdded(q);
|
|
q->ParentChange();
|
|
if(updaterect && GetTopCtrl()->IsOpen())
|
|
q->StateH(OPEN);
|
|
}
|
|
|
|
void Ctrl::AddChild(Ctrl *child)
|
|
{
|
|
AddChild(child, GetLastChild());
|
|
}
|
|
|
|
void Ctrl::AddChildBefore(Ctrl *child, Ctrl *insbefore)
|
|
{
|
|
if(insbefore)
|
|
AddChild(child, insbefore->GetPrev());
|
|
else
|
|
AddChild(child);
|
|
}
|
|
|
|
void Ctrl::RemoveChild0(Ctrl *q)
|
|
{
|
|
GuiLock __;
|
|
ChildRemoved(q);
|
|
if(!q->GetParent()) return; // ChildRemoved can remove q
|
|
q->DoRemove();
|
|
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->GetParent() != this) return;
|
|
q->RefreshFrame();
|
|
RemoveChild0(q);
|
|
q->ParentChange();
|
|
if(GetTopCtrl()->IsOpen())
|
|
q->StateH(CLOSE);
|
|
}
|
|
|
|
void Ctrl::Remove()
|
|
{
|
|
GuiLock __;
|
|
Ctrl *parent = GetParent();
|
|
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;
|
|
}
|
|
|
|
int Ctrl::GetViewChildIndex(const Ctrl *child) const
|
|
{
|
|
GuiLock __;
|
|
int i = 0;
|
|
for (Ctrl *c = GetFirstChild(); c; c = c->GetNext())
|
|
if(!c->InFrame()) {
|
|
if(c == child) return i;
|
|
i++;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int Ctrl::GetViewChildCount() const
|
|
{
|
|
GuiLock __;
|
|
int n = 0;
|
|
for (Ctrl *c = GetFirstChild(); c; c = c->GetNext())
|
|
if(!c->InFrame())
|
|
n++;
|
|
return n;
|
|
}
|
|
|
|
Ctrl * Ctrl::GetViewIndexChild(int ii) const
|
|
{
|
|
GuiLock __;
|
|
int i = 0;
|
|
for (Ctrl *c = GetFirstChild(); c; c = c->GetNext())
|
|
if(!c->InFrame()) {
|
|
if(i == ii)
|
|
return c;
|
|
i++;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
bool Ctrl::HasChild(Ctrl *q) const
|
|
{
|
|
GuiLock __;
|
|
return q && q->GetParent() == this;
|
|
}
|
|
|
|
bool Ctrl::HasChildDeep(Ctrl *q) const
|
|
{
|
|
GuiLock __;
|
|
while(q && q->IsChild()) {
|
|
Ctrl *qparent = q->GetParent();
|
|
if(qparent == this) return true;
|
|
q = qparent;
|
|
}
|
|
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;
|
|
for(;;) {
|
|
Ctrl *qparent = q->GetParent();
|
|
if(!qparent)
|
|
return q;
|
|
q = qparent;
|
|
}
|
|
}
|
|
|
|
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 && utop ? utop->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();
|
|
}
|
|
|
|
}
|