示例#1
0
UIWidgetPtr UIManager::createWidgetFromOTML(const OTMLNodePtr& widgetNode, const UIWidgetPtr& parent)
{
    OTMLNodePtr originalStyleNode = getStyle(widgetNode->tag());
    if(!originalStyleNode)
        stdext::throw_exception(stdext::format("'%s' is not a defined style", widgetNode->tag()));

    OTMLNodePtr styleNode = originalStyleNode->clone();
    styleNode->merge(widgetNode);

    std::string widgetType = styleNode->valueAt("__class");

    // call widget creation from lua
    UIWidgetPtr widget = g_lua.callGlobalField<UIWidgetPtr>(widgetType, "create");
    if(parent)
        parent->addChild(widget);

    if(widget) {
        widget->callLuaField("onCreate");

        widget->setStyleFromNode(styleNode);

        for(const OTMLNodePtr& childNode : styleNode->children()) {
            if(!childNode->isUnique()) {
                createWidgetFromOTML(childNode, widget);
                styleNode->removeChild(childNode);
            }
        }
    } else
        stdext::throw_exception(stdext::format("unable to create widget of type '%s'", widgetType));

    widget->callLuaField("onSetup");
    return widget;
}
示例#2
0
void OTMLNode::addChild(const OTMLNodePtr& newChild)
{
    // replace is needed when the tag is marked as unique
    if(newChild->hasTag()) {
        for(const OTMLNodePtr& node : m_children) {
            if(node->tag() == newChild->tag() && (node->isUnique() || newChild->isUnique())) {
                newChild->setUnique(true);

                if(node->hasChildren() && newChild->hasChildren()) {
                    OTMLNodePtr tmpNode = node->clone();
                    tmpNode->merge(newChild);
                    newChild->copy(tmpNode);
                }

                replaceChild(node, newChild);

                // remove any other child with the same tag
                auto it = m_children.begin();
                while(it != m_children.end()) {
                    OTMLNodePtr node = (*it);
                    if(node != newChild && node->tag() == newChild->tag()) {
                        it = m_children.erase(it);
                    } else
                        ++it;
                }
                return;
            }
        }
    }

    m_children.push_back(newChild);
}
示例#3
0
void OTMLNode::merge(const OTMLNodePtr& node)
{
    for(const OTMLNodePtr& child : node->m_children)
        addChild(child->clone());
    setTag(node->tag());
    setSource(node->source());
}
示例#4
0
void UIWidget::applyStyle(const OTMLNodePtr& styleNode)
{
    if(m_destroyed)
        return;

    if(styleNode->size() == 0)
        return;

    m_loadingStyle = true;
    try {
        // translate ! style tags
        for(const OTMLNodePtr& node : styleNode->children()) {
            if(node->tag()[0] == '!') {
                std::string tag = node->tag().substr(1);
                std::string code = stdext::format("tostring(%s)", node->value());
                std::string origin = "@" + node->source() + ": [" + node->tag() + "]";
                g_lua.evaluateExpression(code, origin);
                std::string value = g_lua.popString();

                node->setTag(tag);
                node->setValue(value);
            }
        }

        onStyleApply(styleNode->tag(), styleNode);
        callLuaField("onStyleApply", styleNode->tag(), styleNode);

        if(m_firstOnStyle) {
            UIWidgetPtr parent = getParent();
            if(isFocusable() && isExplicitlyVisible() && isExplicitlyEnabled() &&
               parent && ((!parent->getFocusedChild() && parent->getAutoFocusPolicy() == Fw::AutoFocusFirst) ||
                           parent->getAutoFocusPolicy() == Fw::AutoFocusLast)) {
                focus();
            }
        }

        m_firstOnStyle = false;
    } catch(stdext::exception& e) {
        g_logger.traceError(stdext::format("failed to apply style to widget '%s': %s", m_id, e.what()));
    }
    m_loadingStyle = false;
}
示例#5
0
void OTMLNode::copy(const OTMLNodePtr& node)
{
    setTag(node->tag());
    setValue(node->rawValue());
    setUnique(node->isUnique());
    setNull(node->isNull());
    setSource(node->source());
    clear();
    for(const OTMLNodePtr& child : node->m_children)
        addChild(child->clone());
}
示例#6
0
void UIWidget::applyStyle(const OTMLNodePtr& styleNode)
{
    if(m_destroyed)
        return;

    if(styleNode->size() == 0)
        return;

    m_loadingStyle = true;
    try {
        // translate ! style tags
        for(const OTMLNodePtr& node : styleNode->children()) {
            if(node->tag()[0] == '!') {
                std::string tag = node->tag().substr(1);
                std::string code = Fw::formatString("tostring(%s)", node->value().c_str());
                std::string origin = "@" + node->source() + "[" + node->tag() + "]";
                g_lua.evaluateExpression(code, origin);
                std::string value = g_lua.popString();

                node->setTag(tag);
                node->setValue(value);
            }
        }

        onStyleApply(styleNode->tag(), styleNode);
        callLuaField("onStyleApply", styleNode->tag(), styleNode);

        if(m_firstOnStyle) {
            callLuaField("onSetup");
            // always focus new child
            if(isFocusable() && isExplicitlyVisible() && isExplicitlyEnabled())
                focus();
        }
        m_firstOnStyle = false;
    } catch(Exception& e) {
        logError("Failed to apply style to widget '", m_id, "' style: ", e.what());
    }
    m_loadingStyle = false;
}
示例#7
0
void UIWidget::applyStyle(const OTMLNodePtr& styleNode)
{
    if(styleNode->size() == 0)
        return;

    m_loadingStyle = true;
    try {
        onStyleApply(styleNode->tag(), styleNode);
        callLuaField("onStyleApply", styleNode->tag(), styleNode);

        if(m_firstOnStyle) {
            callLuaField("onSetup");
            // always focus new child
            if(isFocusable() && isExplicitlyVisible() && isExplicitlyEnabled())
                focus();
        }
        m_firstOnStyle = false;

    } catch(Exception& e) {
        logError("Failed to apply style to widget '", m_id, "' style: ", e.what());
    }
    m_loadingStyle = false;
}
示例#8
0
void UIManager::importStyleFromOTML(const OTMLNodePtr& styleNode)
{
    std::string tag = styleNode->tag();
    std::vector<std::string> split = stdext::split(tag, "<");
    if(split.size() != 2)
        throw OTMLException(styleNode, "not a valid style declaration");

    std::string name = split[0];
    std::string base = split[1];
    bool unique = false;

    stdext::trim(name);
    stdext::trim(base);

    if(name[0] == '#') {
        name = name.substr(1);
        unique = true;

        styleNode->setTag(name);
        styleNode->writeAt("__unique", true);
    }

    OTMLNodePtr oldStyle = m_styles[name];

    // Warn about redefined styles
    /*
    if(!g_app.isRunning() && (oldStyle && !oldStyle->valueAt("__unique", false))) {
        auto it = m_styles.find(name);
        if(it != m_styles.end())
            g_logger.warning(stdext::format("style '%s' is being redefined", name));
    }
    */

    if(!oldStyle || !oldStyle->valueAt("__unique", false) || unique) {
        OTMLNodePtr originalStyle = getStyle(base);
        if(!originalStyle)
            stdext::throw_exception(stdext::format("base style '%s', is not defined", base));
        OTMLNodePtr style = originalStyle->clone();
        style->merge(styleNode);
        style->setTag(name);
        m_styles[name] = style;
    }
}
示例#9
0
std::string OTMLEmitter::emitNode(const OTMLNodePtr& node, int currentDepth)
{
    std::stringstream ss;

    // emit nodes
    if(currentDepth >= 0) {
        // fill spaces for current depth
        for(int i=0;i<currentDepth;++i)
            ss << "  ";

        // emit node tag
        if(node->hasTag()) {
            ss << node->tag();

            // add ':' to if the node is unique or has value
            if(node->hasValue() || node->isUnique() || node->isNull())
                ss << ":";
        } else
            ss << "-";

        // emit node value
        if(node->isNull())
            ss << " ~";
        else if(node->hasValue()) {
            ss << " ";

            std::string value = node->value();

            // emit multiline values
            if(value.find("\n") != std::string::npos) {
                if(value[value.length()-1] == '\n' && value[value.length()-2] == '\n')
                    ss << "|+";
                else if(value[value.length()-1] == '\n')
                    ss << "|";
                else
                    ss << "|-";

                //  multilines
                for(std::size_t pos = 0; pos < value.length(); ++pos) {
                    ss << "\n";

                    // fill spaces for multiline depth
                    for(int i=0;i<currentDepth+1;++i)
                        ss << "  ";

                    // fill until a new line
                    while(pos < value.length()) {
                        if(value[pos] == '\n')
                            break;
                        ss << value[pos++];
                    }
                }
            // emit inline values
            } else
                ss << value;
        }
    }

    // emit children
    for(int i=0;i<node->size();++i) {
        if(currentDepth >= 0 || i != 0)
            ss << "\n";
        ss << emitNode(node->atIndex(i), currentDepth+1);
    }

    return ss.str();
}