Skip to content

Commit

Permalink
Refactor|Widgets|libcore: Improved child widget addition
Browse files Browse the repository at this point in the history
Children can now be appended or prepended.
  • Loading branch information
skyjake committed Jun 5, 2016
1 parent ca64e85 commit 493e67e
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 45 deletions.
6 changes: 5 additions & 1 deletion doomsday/sdk/libcore/include/de/widgets/widget.h
Expand Up @@ -208,6 +208,8 @@ class DENG2_PUBLIC Widget
*/
void clearTree();

inline Widget &add(Widget *child) { return addLast(child); }

/**
* Adds a child widget. It becomes the last child, meaning it is drawn on
* top of other children but will get events first.
Expand All @@ -217,7 +219,9 @@ class DENG2_PUBLIC Widget
* @return Reference to the added child widget. (Note that this is @em not
* a "fluent API".)
*/
Widget &add(Widget *child);
Widget &addLast(Widget *child);

Widget &addFirst(Widget *child);

Widget &insertBefore(Widget *child, Widget const &otherChild);
Widget *remove(Widget &child);
Expand Down
114 changes: 70 additions & 44 deletions doomsday/sdk/libcore/src/widgets/widget.cpp
Expand Up @@ -81,6 +81,66 @@ DENG2_PIMPL(Widget)
return nullptr;
}

enum AddBehavior { Append, Prepend, InsertBefore };

void add(Widget *child, AddBehavior behavior, Widget const *ref = nullptr)
{
DENG2_ASSERT(child != 0);
DENG2_ASSERT(child->d->parent == 0);

#ifdef _DEBUG
// Can't have double ownership.
if (self.parent())
{
if (self.parent()->hasRoot())
{
DENG2_ASSERT(!self.parent()->root().isInTree(*child));
}
else
{
DENG2_ASSERT(!self.parent()->isInTree(*child));
}
}
else
{
DENG2_ASSERT(!self.isInTree(*child));
}
#endif

child->d->parent = &self;

switch (behavior)
{
case Append:
children.append(child);
break;

case Prepend:
children.push_front(child);
break;

case InsertBefore:
children.insert(children.indexOf(const_cast<Widget *>(ref)), child);
break;
}

// Update index.
if (!child->name().isEmpty())
{
index.insert(child->name(), child);
}

// Notify.
DENG2_FOR_PUBLIC_AUDIENCE2(ChildAddition, i)
{
i->widgetChildAdded(*child);
}
DENG2_FOR_EACH_OBSERVER(ParentChangeAudience, i, child->audienceForParentChange())
{
i->widgetParentChanged(*child, 0, &self);
}
}

DENG2_PIMPL_AUDIENCE(Deletion)
DENG2_PIMPL_AUDIENCE(ParentChange)
DENG2_PIMPL_AUDIENCE(ChildAddition)
Expand Down Expand Up @@ -267,58 +327,24 @@ void Widget::clearTree()
d->clear();
}

Widget &Widget::add(Widget *child)
Widget &Widget::addLast(Widget *child)
{
DENG2_ASSERT(child != 0);
DENG2_ASSERT(child->d->parent == 0);

#ifdef _DEBUG
// Can't have double ownership.
if (parent())
{
if (parent()->hasRoot())
{
DENG2_ASSERT(!parent()->root().isInTree(*child));
}
else
{
DENG2_ASSERT(!parent()->isInTree(*child));
}
}
else
{
DENG2_ASSERT(!isInTree(*child));
}
#endif

child->d->parent = this;
d->children.append(child);

// Update index.
if (!child->name().isEmpty())
{
d->index.insert(child->name(), child);
}

// Notify.
DENG2_FOR_AUDIENCE2(ChildAddition, i)
{
i->widgetChildAdded(*child);
}
DENG2_FOR_EACH_OBSERVER(ParentChangeAudience, i, child->audienceForParentChange())
{
i->widgetParentChanged(*child, 0, this);
}
d->add(child, Instance::Append);
return *child;
}

Widget &Widget::addFirst(Widget *child)
{
d->add(child, Instance::Prepend);
return *child;
}

Widget &Widget::insertBefore(Widget *child, Widget const &otherChild)
{
DENG2_ASSERT(child != &otherChild);
DENG2_ASSERT(otherChild.parent() == this);

add(child);
moveChildBefore(child, otherChild);
d->add(child, Instance::InsertBefore, &otherChild);
return *child;
}

Expand Down Expand Up @@ -616,7 +642,7 @@ Widget::Children Widget::children() const

dsize de::Widget::childCount() const
{
return d->children.size();
return dsize(d->children.size());
}

void Widget::initialize()
Expand Down

0 comments on commit 493e67e

Please sign in to comment.