Обеспечение наличия в виджете контейнера? - PullRequest
0 голосов
/ 01 апреля 2011

Вот моя проблема:

В игровом интерфейсе, который я разрабатываю, «рабочий стол» - это класс, который я называю WidgetManager.Для того, чтобы я мог передавать определенные вещи, такие как фокус, между графическим интерфейсом и виджетом, каждый виджет должен иметь указатель на менеджер виджетов.Проблема в том, что пользователь может добавлять детей в виджет, который еще не является частью менеджера виджетов.Вот тут-то и приходит мое хакерское решение:

AguiWidgetManager* AguiWidget::getWidgetManager() const
{

    if(_container)
    return _container;

    if(getTopWidget())
    {
        if(getTopWidget()->getWidgetManager())
        {
            ((AguiWidget*) this)->_container = 
                getTopWidget()->getWidgetManager();
            return _container;
        }
    }

    if(getParent())
    {
        if(getParent()->getWidgetManager())
        {
            ((AguiWidget*) this)->_container = 
                getParent()->getWidgetManager();
            return _container;
        }
    }

    return (AguiWidgetManager*)NULL;


}

Я знаю, насколько это ужасная идея и ужасный код, и ломает ли смысл, но я просто не знаю, какеще, чтобы убедиться, что у виджета есть контейнер.

Сначала я подумал об установке указателя менеджера виджетов на указатель своего родителя при его добавлении, но, как я уже сказал, его родитель может не иметь ни одного навремя.

Спасибо

1 Ответ

1 голос
/ 01 апреля 2011

Если каждый виджет создается с помощью WidgetManager, вы можете передать это во время создания.

Однако, я думаю, ваша проблема связана с объединением функций WidgetManager (возможно, лучше называть его WidgetFactory) ивиджет верхнего уровня.Я могу подумать о двух потенциальных решениях, с которыми можно работать, как с плюсами, так и с минусами.

1: Есть WidgetFactory, которая производит виджеты.В вашем движке держите указатель на корневой виджет.Это ваш рабочий стол, все отображаемые виджеты должны быть его дочерними элементами (основа дерева).

При рендеринге ваших виджетов, вам нужно просто вызвать RootWidget->Render(), и он будет рендерить свои дочерние элементы и так далее, рекурсивно.

Точно так же, чтобы создать резервную копию дерева из любого заданного виджета, вы вызываете widget->GetParent(), и он дает родителя.Дальнейшие вызовы будут увеличивать дерево до тех пор, пока вы не достигнете корневого виджета, у которого нет родителя (используется непосредственно движком).

Настройка там относительно проста и с ней легко работать, но вам нужно разделитьвиджеты и тому подобное.

2: Если вы предпочитаете фабрику мобильных виджетов, которая также служит базой операций для вашей армии виджетов, вы можете присвоить ей некоторые из тех же свойств, что и длявиджет.Самый простой способ сделать это - получить WidgetManager из класса Widget, который выглядит примерно так:

class Widget
{
    virtual void Render() { for_each(mChildren, child->Render()); }
    virtual Widget * GetParent(); // Returns pointer to parent
    virtual WidgetType GetType() { return WT_Widget; }

private:
    WidgetList mChildren;
    Widget * mParent;
}

class WidgetManager
    : public Widget
{
    Widget * GetParent() { return NULL; }
    WidgetType GetType() { return WT_Manager; }
}

Это обеспечивает простой способ справиться с обоими.У WidgetManager есть свои дочерние элементы, и они отображаются так же, как и каждый виджет, и создать резервную копию дерева очень просто, поскольку вы вызываете widget->GetParent(), и он работает для обоих.

Если GetParent () возвращает NULL, вы можете проверитьвы достигли WidgetManager, вызвав GetType.Если это возвращает WT_Widget, у вас может быть проблема.

Edit: Вы также можете иметь WidgetManager для удержания указателя на один корневой виджет, для которого установлен флаг, обозначающий его.как верх.Затем используйте идеи из метода 1 для обработки дерева виджетов вверх и вниз.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...