#include "UIMLView.h"

#include "Bild.h"
#include "Bildschirm.h"
#include "Fenster.h"
#include "Knopf.h"
#include "Rahmen.h"
#include "RCPointer.h"
#include "Schrift.h"
#include "Scroll.h"
#include "Tabelle.h"
#include "TextFeld.h"
#include "XML.h"

using namespace Framework;

UIMLElement::UIMLElement()
    : ReferenceCounter()
{}

UIMLElement::~UIMLElement() {}

//! wendet die layout parameter zu einer Zeichnung an
void UIMLElement::layout(XML::Element& element,
    Zeichnung& z,
    int pWidth,
    int pHeight,
    UIMLContainer& generalLayouter)
{
    int width = z.getBreite();
    int height = z.getHeight();
    if (element.hasAttribute("style"))
    {
        z.setStyle((__int64)element.getAttributeValue("style"));
    }
    if (element.hasAttribute("width"))
    {
        Text w = element.getAttributeValue("width");
        if (!w.istGleich("auto"))
        {
            width = calculateSize(w, pWidth);
        }
    }
    if (element.hasAttribute("height"))
    {
        Text h = element.getAttributeValue("height");
        if (!h.istGleich("auto"))
        {
            height = calculateSize(h, pHeight);
        }
    }
    z.setSize(width, height);
    if (element.hasAttribute("align-x"))
    {
        Text la = element.getAttributeValue("align-x");
        int x = 0;
        if (la.istGleich("start"))
            x = 0;
        else if (la.istGleich("end"))
            x = pWidth;
        else if (la.istGleich("center"))
            x = pWidth / 2 - width / 2;
        else
        {
            XML::Editor ed
                = element.zParent()->selectChildsByAttribute("id", la);
            if (ed.exists())
            {
                generalLayouter.layout(*ed.begin().val(),
                    *generalLayouter.zZeichnungById(la),
                    pWidth,
                    pHeight,
                    generalLayouter);
                Zeichnung* laz = generalLayouter.zZeichnungById(la);
                if (laz) x = laz->getX();
            }
        }
        if (element.hasAttribute("margin-x"))
        {
            Text mt = element.getAttributeValue("margin-x");
            x += calculateSize(mt, pWidth);
        }
        z.setX(x);
    }
    else if (element.hasAttribute("align-left"))
    {
        Text la = element.getAttributeValue("align-left");
        int x = 0;
        if (la.istGleich("start"))
            x = 0;
        else if (la.istGleich("end"))
            x = pWidth;
        else if (la.istGleich("center"))
            x = pWidth / 2 - width / 2;
        else
        {
            XML::Editor ed
                = element.zParent()->selectChildsByAttribute("id", la);
            if (ed.exists())
            {
                generalLayouter.layout(*ed.begin().val(),
                    *generalLayouter.zZeichnungById(la),
                    pWidth,
                    pHeight,
                    generalLayouter);
                Zeichnung* laz = generalLayouter.zZeichnungById(la);
                if (laz) x = laz->getX() + laz->getBreite();
            }
        }
        if (element.hasAttribute("margin-left"))
        {
            Text mt = element.getAttributeValue("margin-left");
            x += calculateSize(mt, pWidth);
        }
        z.setX(x);
    }
    else if (element.hasAttribute("align-right"))
    {
        Text ra = element.getAttributeValue("align-right");
        int x = 0;
        if (ra.istGleich("start"))
            x = -z.getBreite();
        else if (ra.istGleich("end"))
            x = pWidth - z.getBreite();
        else if (ra.istGleich("center"))
            x = pWidth / 2 - width / 2;
        else
        {
            XML::Editor ed
                = element.zParent()->selectChildsByAttribute("id", ra);
            if (ed.exists())
            {
                generalLayouter.layout(*ed.begin().val(),
                    *generalLayouter.zZeichnungById(ra),
                    pWidth,
                    pHeight,
                    generalLayouter);
                Zeichnung* raz = generalLayouter.zZeichnungById(ra);
                if (raz) x = raz->getX() - z.getBreite();
            }
        }
        if (element.hasAttribute("margin-right"))
        {
            Text mt = element.getAttributeValue("margin-right");
            x -= calculateSize(mt, pWidth);
        }
        z.setX(x);
    }
    if (element.hasAttribute("align-y"))
    {
        Text ta = element.getAttributeValue("align-y");
        int y = 0;
        if (ta.istGleich("start"))
            y = 0;
        else if (ta.istGleich("end"))
            y = pHeight;
        else if (ta.istGleich("center"))
            y = pHeight / 2 - height / 2;
        else
        {
            XML::Editor ed
                = element.zParent()->selectChildsByAttribute("id", ta);
            if (ed.exists())
            {
                generalLayouter.layout(*ed.begin().val(),
                    *generalLayouter.zZeichnungById(ta),
                    pWidth,
                    pHeight,
                    generalLayouter);
                Zeichnung* taz = generalLayouter.zZeichnungById(ta);
                if (taz) y = taz->getY();
            }
        }
        if (element.hasAttribute("margin-y"))
        {
            Text mt = element.getAttributeValue("margin-y");
            y += calculateSize(mt, pHeight);
        }
        z.setY(y);
    }
    else if (element.hasAttribute("align-top"))
    {
        Text ta = element.getAttributeValue("align-top");
        int y = 0;
        if (ta.istGleich("start"))
            y = 0;
        else if (ta.istGleich("end"))
            y = pHeight;
        else if (ta.istGleich("center"))
            y = pHeight / 2 - height / 2;
        else
        {
            XML::Editor ed
                = element.zParent()->selectChildsByAttribute("id", ta);
            if (ed.exists())
            {
                generalLayouter.layout(*ed.begin().val(),
                    *generalLayouter.zZeichnungById(ta),
                    pWidth,
                    pHeight,
                    generalLayouter);
                Zeichnung* taz = generalLayouter.zZeichnungById(ta);
                if (taz) y = taz->getY() + taz->getHeight();
            }
        }
        if (element.hasAttribute("margin-top"))
        {
            Text mt = element.getAttributeValue("margin-top");
            y += calculateSize(mt, pHeight);
        }
        z.setY(y);
    }
    else if (element.hasAttribute("align-bottom"))
    {
        Text ba = element.getAttributeValue("align-bottom");
        int y = 0;
        if (ba.istGleich("start"))
            y = -z.getHeight();
        else if (ba.istGleich("end"))
            y = pHeight - z.getHeight();
        else if (ba.istGleich("center"))
            y = pHeight / 2 - height / 2;
        else
        {
            XML::Editor ed
                = element.zParent()->selectChildsByAttribute("id", ba);
            if (ed.exists())
            {
                generalLayouter.layout(*ed.begin().val(),
                    *generalLayouter.zZeichnungById(ba),
                    pWidth,
                    pHeight,
                    generalLayouter);
                Zeichnung* baz = generalLayouter.zZeichnungById(ba);
                if (baz) y = baz->getY() - z.getHeight();
            }
        }
        if (element.hasAttribute("margin-bottom"))
        {
            Text mt = element.getAttributeValue("margin-bottom");
            y -= calculateSize(mt, pHeight);
        }
        z.setY(y);
    }
    int x = z.getX();
    int y = z.getY();
    if (element.hasAttribute("x"))
    {
        Text xt = element.getAttributeValue("x");
        x = calculateSize(xt, pWidth);
    }
    if (element.hasAttribute("y"))
    {
        Text yt = element.getAttributeValue("y");
        y = calculateSize(yt, pHeight);
    }
    z.setPosition(x, y);
    ZeichnungHintergrund* zh = dynamic_cast<ZeichnungHintergrund*>(&z);
    if (zh)
    {
        if (element.hasAttribute("border"))
        {
            int br = (int)element.getAttributeValue("border");
            zh->setStyle(ZeichnungHintergrund::Style::Rahmen, br > 0);
            zh->setRahmenBreite((int)element.getAttributeValue("border"));
        }
        if (element.hasAttribute("border-color"))
        {
            zh->setRahmenFarbe((int)element.getAttributeValue("border-color"));
        }
    }
    // recursive layout
    pWidth = z.getInnenBreite();
    pHeight = z.getInnenHeight();
    for (auto i : getChildren(element))
    {
        Zeichnung* z = 0;
        if (i->hasAttribute("id"))
        {
            z = generalLayouter.zZeichnungById(i->getAttributeValue("id"));
        }
        if (z)
        {
            generalLayouter.layout(*i, *z, pWidth, pHeight, generalLayouter);
        }
    }
}

int Framework::UIMLElement::calculateSize(Text attributeValue, int parentSize)
{
    attributeValue.removeWhitespaceAfter(0);
    attributeValue.removeWhitespaceBefore(attributeValue.getLength());
    if (attributeValue.hat('('))
    {
        int start = -1;
        int len = attributeValue.getLength();
        for (int i = 0; i < len; i++)
        {
            if (attributeValue.getText()[i] == '(') start = i;
            if (attributeValue.getText()[i] == ')')
            {
                if (start < 0) return 0;
                Text* part = attributeValue.getTeilText(start + 1, i);
                int value = calculateSize(*part, parentSize);
                part->release();
                attributeValue.remove(start, i + 1);
                attributeValue.insert(start, Text(value));
                return calculateSize(attributeValue, parentSize);
            }
        }
        return 0;
    }
    else if (attributeValue.hat('*') || attributeValue.hat('/'))
    {
        int posD = attributeValue.positionVon('/');
        int posM = attributeValue.positionVon('*');
        if ((posD >= 0 && posD < posM) || posM < 0)
        {
            Text* firstPart = attributeValue.getTeilText(0, posD);
            Text* secondPart = attributeValue.getTeilText(posD + 1);
            int first = calculateSize(*firstPart, parentSize);
            int second = calculateSize(*secondPart, parentSize);
            firstPart->release();
            secondPart->release();
            return first / second;
        }
        else
        {
            Text* firstPart = attributeValue.getTeilText(0, posM);
            Text* secondPart = attributeValue.getTeilText(posM + 1);
            int first = calculateSize(*firstPart, parentSize);
            int second = calculateSize(*secondPart, parentSize);
            firstPart->release();
            secondPart->release();
            return first * second;
        }
    }
    else if (attributeValue.hat('+') || attributeValue.hat('-'))
    {
        int posP = attributeValue.positionVon('+');
        int posN = attributeValue.positionVon('-');
        if ((posP >= 0 && posP < posN) || posN < 0)
        {
            Text* firstPart = attributeValue.getTeilText(0, posP);
            Text* secondPart = attributeValue.getTeilText(posP + 1);
            int first = calculateSize(*firstPart, parentSize);
            int second = calculateSize(*secondPart, parentSize);
            firstPart->release();
            secondPart->release();
            return first + second;
        }
        else
        {
            Text* firstPart = attributeValue.getTeilText(0, posN);
            Text* secondPart = attributeValue.getTeilText(posN + 1);
            int first = calculateSize(*firstPart, parentSize);
            int second = calculateSize(*secondPart, parentSize);
            firstPart->release();
            secondPart->release();
            return first - second;
        }
    }
    else if (attributeValue.hatAt(attributeValue.getLength() - 1, "%"))
    {
        return (int)((int)attributeValue * (parentSize / 100.0));
    }
    else
    {
        return (int)attributeValue;
    }
}

XML::Editor Framework::UIMLElement::getChildren(XML::Element& element)
{
    return element.selectChildren();
}

UIMLContainer::UIMLContainer()
    : UIMLElement()
{}

UIMLContainer::~UIMLContainer() {}

UIMLTextField::UIMLTextField()
    : UIMLElement()
{}

bool UIMLTextField::isApplicableFor(XML::Element& element)
{
    return element.getName().istGleich("textfield");
}

Zeichnung* UIMLTextField::parseElement(
    XML::Element& element, UIMLContainer& generalFactory)
{
    TextFeld* t = generalFactory.getFactory().createTextFeld(
        generalFactory.getFactory().initParam);
    t->setText(element.getText());
    updateElement(element, *t, generalFactory);
    return t;
}

bool Framework::UIMLTextField::updateElement(
    XML::Element& element, Zeichnung& z, UIMLContainer& generalFactory)
{
    TextFeld* t = dynamic_cast<TextFeld*>(&z);
    if (!t) return false;
    if (!element.hasAttribute("style"))
    {
        TextFeld* tmp = generalFactory.getFactory().createTextFeld(
            generalFactory.getFactory().initParam);
        tmp->addStyle(TextFeld::Style::TextFeld);
        t->setStyle(tmp->getStyles());
        tmp->release();
    }
    return true;
}

void UIMLTextField::layout(XML::Element& element,
    Zeichnung& z,
    int pWidth,
    int pHeight,
    UIMLContainer& generalLayouter)
{
    TextFeld* tf = dynamic_cast<TextFeld*>(&z);
    if (element.hasAttribute("font-size"))
    {
        tf->setSchriftSize(
            (unsigned char)(int)element.getAttributeValue("font-size"));
    }
    ((TextFeld*)&z)->setText(element.getText());
    if (element.hasAttribute("width"))
    {
        Text w = element.getAttributeValue("width");
        if (w.istGleich("auto"))
        {
            z.setWidth(((TextFeld*)&z)->getNeededWidth());
        }
    }
    if (element.hasAttribute("height"))
    {
        Text h = element.getAttributeValue("height");
        if (h.istGleich("auto"))
        {
            z.setHeight(((TextFeld*)&z)->getNeededHeight());
        }
    }
    if (element.hasAttribute("text-color"))
    {
        tf->setSchriftFarbe((int)element.getAttributeValue("text-color"));
    }
    UIMLElement::layout(element, z, pWidth, pHeight, generalLayouter);
    if (element.hasAttribute("text-align-horizontal"))
        z.setStyle(TextFeld::Style::HCenter,
            element.getAttributeValue("text-align-horizontal")
                .istGleich("center"));
    if (element.hasAttribute("text-align-vertical"))
        z.setStyle(TextFeld::Style::VCenter,
            element.getAttributeValue("text-align-vertical")
                .istGleich("center"));
    if (element.hasAttribute("disabled"))
        z.removeStyle(TextFeld::Style::Editierbar);
    if (element.getAttributeValue("vScroll").istGleich("auto"))
    {
        tf->setStyle(TextFeld::Style::VScroll,
            tf->getNeededHeight() > tf->getInnenHeight());
        tf->setVertikalKlickScroll(tf->getSchriftSize());
        tf->updateVScroll();
    }
    if (element.getAttributeValue("hScroll").istGleich("auto"))
    {
        tf->setStyle(TextFeld::Style::HScroll,
            tf->getNeededWidth() > tf->getInnenBreite());
        tf->setHorizontalKlickScroll(tf->getSchriftSize());
        tf->updateHScroll();
    }
}

UIMLButton::UIMLButton()
    : UIMLElement()
{}

bool UIMLButton::isApplicableFor(XML::Element& element)
{
    return element.getName().istGleich("button");
}

Zeichnung* UIMLButton::parseElement(
    XML::Element& element, UIMLContainer& generalFactory)
{
    Knopf* k = generalFactory.getFactory().createKnopf(
        generalFactory.getFactory().initParam);
    updateElement(element, *k, generalFactory);
    return k;
}

bool Framework::UIMLButton::updateElement(
    XML::Element& element, Zeichnung& z, UIMLContainer& generalFactory)
{
    Knopf* k = dynamic_cast<Knopf*>(&z);
    if (!k) return false;
    if (!element.hasAttribute("style"))
    {
        Knopf* tmp = generalFactory.getFactory().createKnopf(
            generalFactory.getFactory().initParam);
        k->setStyle(tmp->getStyles());
        tmp->release();
    }
    return true;
}

void UIMLButton::layout(XML::Element& element,
    Zeichnung& z,
    int pWidth,
    int pHeight,
    UIMLContainer& generalLayouter)
{
    if (element.hasAttribute("font-size"))
        ((Knopf*)&z)
            ->setSchriftSize(
                (unsigned char)(int)element.getAttributeValue("font-size"));
    ((Knopf*)&z)->setText(element.getText());
    UIMLElement::layout(element, z, pWidth, pHeight, generalLayouter);
}

UIMLCheck::UIMLCheck()
    : UIMLElement()
{}

bool UIMLCheck::isApplicableFor(XML::Element& element)
{
    return element.getName().istGleich("check");
}

Zeichnung* UIMLCheck::parseElement(
    XML::Element& element, UIMLContainer& generalFactory)
{
    KontrollKnopf* k = generalFactory.getFactory().createKontrollKnopf(
        generalFactory.getFactory().initParam);
    updateElement(element, *k, generalFactory);
    return k;
}

bool Framework::UIMLCheck::updateElement(
    XML::Element& element, Zeichnung& z, UIMLContainer& generalFactory)
{
    KontrollKnopf* k = dynamic_cast<KontrollKnopf*>(&z);
    if (!k) return false;
    if (!element.hasAttribute("style"))
    {
        KontrollKnopf* tmp = generalFactory.getFactory().createKontrollKnopf(
            generalFactory.getFactory().initParam);
        k->setStyle(tmp->getStyles());
        tmp->release();
    }
    return true;
}

void UIMLCheck::layout(XML::Element& element,
    Zeichnung& z,
    int pWidth,
    int pHeight,
    UIMLContainer& generalLayouter)
{
    ((KontrollKnopf*)&z)->setText(element.getText());
    ((KontrollKnopf*)&z)->setSText(element.getText());
    z.setStyle(
        KontrollKnopf::Style::Selected, element.hasAttribute("selected"));
    if (element.hasAttribute("font-size"))
        ((KontrollKnopf*)&z)
            ->setSSize(
                (unsigned char)(int)element.getAttributeValue("font-size"));
    UIMLElement::layout(element, z, pWidth, pHeight, generalLayouter);
}

UIMLText::UIMLText()
    : UIMLElement()
{}

bool UIMLText::isApplicableFor(XML::Element& element)
{
    return element.getName().istGleich("text");
}

Zeichnung* UIMLText::parseElement(
    XML::Element& element, UIMLContainer& generalFactory)
{
    TextFeld* t = generalFactory.getFactory().createTextFeld(
        generalFactory.getFactory().initParam);
    t->setText(element.getText());
    updateElement(element, *t, generalFactory);
    return t;
}

bool Framework::UIMLText::updateElement(
    XML::Element& element, Zeichnung& z, UIMLContainer& generalFactory)
{
    TextFeld* t = dynamic_cast<TextFeld*>(&z);
    if (!t) return false;
    if (!element.hasAttribute("style"))
    {
        TextFeld* tmp = generalFactory.getFactory().createTextFeld(
            generalFactory.getFactory().initParam);
        tmp->addStyle(TextFeld::Style::Text);
        t->setStyle(tmp->getStyles());
        tmp->release();
    }
    return true;
}

void UIMLText::layout(XML::Element& element,
    Zeichnung& z,
    int pWidth,
    int pHeight,
    UIMLContainer& generalLayouter)
{
    TextFeld* tf = dynamic_cast<TextFeld*>(&z);
    if (element.hasAttribute("font-size"))
    {
        tf->setSchriftSize(
            (unsigned char)(int)element.getAttributeValue("font-size"));
    }
    tf->setText(element.getText());
    if (element.hasAttribute("width"))
    {
        Text w = element.getAttributeValue("width");
        if (w.istGleich("auto"))
        {
            z.setWidth(tf->getNeededWidth());
        }
    }
    if (element.hasAttribute("height"))
    {
        Text h = element.getAttributeValue("height");
        if (h.istGleich("auto"))
        {
            z.setHeight(tf->getNeededHeight());
        }
    }
    if (element.hasAttribute("text-color"))
    {
        tf->setSchriftFarbe((int)element.getAttributeValue("text-color"));
    }
    UIMLElement::layout(element, z, pWidth, pHeight, generalLayouter);
    if (element.hasAttribute("text-align-horizontal"))
        z.setStyle(TextFeld::Style::HCenter,
            element.getAttributeValue("text-align-horizontal")
                .istGleich("center"));
    if (element.hasAttribute("text-align-vertical"))
        z.setStyle(TextFeld::Style::VCenter,
            element.getAttributeValue("text-align-vertical")
                .istGleich("center"));
    if (element.hasAttribute("disabled"))
        z.removeStyle(TextFeld::Style::Editierbar);
    if (element.getAttributeValue("vScroll").istGleich("auto"))
    {
        tf->setStyle(TextFeld::Style::VScroll,
            tf->getNeededHeight() > tf->getInnenHeight());
        tf->setVertikalKlickScroll(tf->getSchriftSize());
        tf->updateVScroll();
    }
    if (element.getAttributeValue("hScroll").istGleich("auto"))
    {
        tf->setStyle(TextFeld::Style::HScroll,
            tf->getNeededWidth() > tf->getInnenBreite());
        tf->setHorizontalKlickScroll(tf->getSchriftSize());
        tf->updateHScroll();
    }
}

UIMLTextArea::UIMLTextArea()
    : UIMLElement()
{}

bool UIMLTextArea::isApplicableFor(XML::Element& element)
{
    return element.getName().istGleich("textarea");
}

Zeichnung* UIMLTextArea::parseElement(
    XML::Element& element, UIMLContainer& generalFactory)
{
    TextFeld* t = generalFactory.getFactory().createTextFeld(
        generalFactory.getFactory().initParam);
    t->setText(element.getText());
    updateElement(element, *t, generalFactory);
    return t;
}

bool Framework::UIMLTextArea::updateElement(
    XML::Element& element, Zeichnung& z, UIMLContainer& generalFactory)
{
    TextFeld* t = dynamic_cast<TextFeld*>(&z);
    if (!t) return false;
    if (!element.hasAttribute("style"))
    {
        TextFeld* tmp = generalFactory.getFactory().createTextFeld(
            generalFactory.getFactory().initParam);
        tmp->addStyle(TextFeld::Style::TextGebiet);
        t->setStyle(tmp->getStyles());
        tmp->release();
    }
    return true;
}

void UIMLTextArea::layout(XML::Element& element,
    Zeichnung& z,
    int pWidth,
    int pHeight,
    UIMLContainer& generalLayouter)
{
    TextFeld* tf = dynamic_cast<TextFeld*>(&z);
    if (element.hasAttribute("font-size"))
    {
        tf->setSchriftSize(
            (unsigned char)(int)element.getAttributeValue("font-size"));
    }
    if (element.hasAttribute("disabled"))
        z.removeStyle(TextFeld::Style::Editierbar);
    tf->setText(element.getText());
    tf->zTextRenderer()->textFormatieren(tf->zText(), z.getInnenBreite());
    if (element.hasAttribute("width"))
    {
        Text w = element.getAttributeValue("width");
        if (w.istGleich("auto"))
        {
            z.setWidth(((TextFeld*)&z)->getNeededWidth());
        }
    }
    if (element.hasAttribute("height"))
    {
        Text h = element.getAttributeValue("height");
        if (h.istGleich("auto"))
        {
            z.setHeight(((TextFeld*)&z)->getNeededHeight());
        }
    }
    if (element.hasAttribute("text-color"))
    {
        tf->setSchriftFarbe((int)element.getAttributeValue("text-color"));
    }
    UIMLElement::layout(element, z, pWidth, pHeight, generalLayouter);
    if (element.hasAttribute("text-align-horizontal"))
        z.setStyle(TextFeld::Style::HCenter,
            element.getAttributeValue("text-align-horizontal")
                .istGleich("center"));
    if (element.hasAttribute("text-align-vertical"))
        z.setStyle(TextFeld::Style::VCenter,
            element.getAttributeValue("text-align-vertical")
                .istGleich("center"));
    if (element.hasAttribute("font-size"))
        if (element.getAttributeValue("vScroll").istGleich("auto"))
        {
            tf->setStyle(TextFeld::Style::VScroll,
                tf->getNeededHeight() > tf->getInnenHeight());
            tf->setVertikalKlickScroll(tf->getSchriftSize());
            tf->updateVScroll();
        }
    if (element.getAttributeValue("hScroll").istGleich("auto"))
    {
        tf->setStyle(TextFeld::Style::HScroll,
            tf->getNeededWidth() > tf->getInnenBreite());
        tf->setHorizontalKlickScroll(tf->getSchriftSize());
        tf->updateHScroll();
    }
}

UIMLTable::UIMLTable()
    : UIMLElement()
{}

bool UIMLTable::isApplicableFor(XML::Element& element)
{
    return element.getName().istGleich("table");
}

Zeichnung* UIMLTable::parseElement(
    XML::Element& element, UIMLContainer& generalFactory)
{
    ObjTabelle* t = generalFactory.getFactory().createObjTabelle(
        generalFactory.getFactory().initParam);
    updateElement(element, *t, generalFactory);
    return t;
}

DLLEXPORT bool Framework::UIMLTable::updateElement(
    XML::Element& element, Zeichnung& z, UIMLContainer& generalFactory)
{
    ObjTabelle* t = dynamic_cast<ObjTabelle*>(&z);
    if (!t) return false;
    int index = 0;
    int linePos = 0;
    int numCols = 0;
    Text currentId = element.getAttributeValue("id");
    for (auto i = element.getChilds(); i; i++)
    {
        Text id;
        if (i->hasAttribute("id"))
            id = i->getAttributeValue("id");
        else
        {
            id = currentId + "_tr_" + index++;
            i->setAttribute("id", id);
        }
        if (i->getName().istGleich("tr"))
        {
            if (t->getZeilenNummer(id) == -1) t->addZeile(id);
            t->setZeilePosition(id, linePos);
            int c = 1;
            for (auto j = i->getChilds(); j; j++)
            {
                if (t->getSpaltenAnzahl() < c) t->addSpalte(Text(c - 1));
                if (numCols < c) numCols = c;
                Zeichnung* z = t->zZeichnung(Text(c - 1), id);
                if (!z
                    || !generalFactory.updateElement(
                        element, *z, generalFactory))
                {
                    z = generalFactory.parseElement(*j.val(), generalFactory);
                    if (z)
                    {
                        if (z->getBreite() > t->getSpaltenBreite(Text(c - 1)))
                            t->setSpaltenBreite(Text(c - 1), z->getBreite());
                        if (z->getHeight() > t->getZeilenHeight(Text(id)))
                            t->setZeilenHeight(Text(id), z->getHeight());
                        t->setZeichnungZ(Text(c - 1), id, z);
                    }
                }
                c++;
            }
        }
        linePos++;
    }
    for (int i = 0; i < t->getZeilenAnzahl(); i++)
    { // remove all lines that are not in the xml
        if (!element.selectChildsByName("tr")
                .whereAttributeEquals("id", *t->zZeilenName(i))
                .exists())
        {
            t->removeZeile(i);
            i--;
        }
    }
    for (int i = numCols; i < t->getSpaltenAnzahl(); i++)
    { // remove all columns that are not in the xml
        t->removeSpalte(i);
        i--;
    }
    if (!element.hasAttribute("style"))
    {
        ObjTabelle* tmp = generalFactory.getFactory().createObjTabelle(
            generalFactory.getFactory().initParam);
        t->setStyle(tmp->getStyles());
        tmp->release();
    }
    return true;
}

void UIMLTable::layout(XML::Element& element,
    Zeichnung& z,
    int pWidth,
    int pHeight,
    UIMLContainer& generalLayouter)
{
    if (element.hasAttribute("scroll"))
    {
        z.setStyle(ObjTabelle::Style::HScroll,
            element.getAttributeValue("scroll").istGleich("horizontal"));
        z.setStyle(ObjTabelle::Style::VScroll,
            element.getAttributeValue("scroll").istGleich("vertical"));
        z.setStyle(ObjTabelle::Style::scroll,
            element.getAttributeValue("scroll").istGleich("both"));
    }
    UIMLElement::layout(element, z, pWidth, pHeight, generalLayouter);
    ObjTabelle* objT = (ObjTabelle*)&z;
    if (objT->getZeilenAnzahl() > 0)
    {
        if (element.hasAttribute("line-height"))
        {
            int height = (int)element.getAttributeValue("line-height");
            for (int i = 0; i < objT->getZeilenAnzahl(); i++)
                objT->setZeilenHeight(i, height);
        }
        for (int i = 0; i < objT->getSpaltenAnzahl(); i++)
        {
            if (objT->zZeichnung(i, 0))
                objT->setSpaltenBreite(i, objT->zZeichnung(i, 0)->getBreite());
        }
    }
}

XML::Editor Framework::UIMLTable::getChildren(XML::Element& element)
{
    return element.selectChildren().selectChildren();
}

UIMLFrame::UIMLFrame()
    : UIMLElement()
{}

bool UIMLFrame::isApplicableFor(XML::Element& element)
{
    return element.getName().istGleich("frame");
}

Zeichnung* UIMLFrame::parseElement(
    XML::Element& element, UIMLContainer& generalFactory)
{
    Fenster* f = generalFactory.getFactory().createFenster(
        generalFactory.getFactory().initParam);
    updateElement(element, *f, generalFactory);
    return f;
}

bool Framework::UIMLFrame::updateElement(
    XML::Element& element, Zeichnung& z, UIMLContainer& generalFactory)
{
    Fenster* f = dynamic_cast<Fenster*>(&z);
    if (!f) return false;
    for (auto member = f->getMembers().begin(); member;)
    { // remove all members that are not in the xml
        Framework::Text id = generalFactory.getZeichnungId(*member.val());
        if (id.getLength() == 0)
        {
            member.remove();
            f->setRender();
        }
        else
        {
            member++;
        }
    }
    int index = 0;
    for (auto i = element.getChilds(); i; i++)
    {
        Text id = i->getAttributeValue("id");
        Zeichnung* z = generalFactory.zZeichnungById(id);
        if (!id.getLength() || !z || f->getMembers().indexOf(z) < 0
            || !generalFactory.updateElement(*i.val(), *z, generalFactory))
        {
            if (f->getMembers().indexOf(z) >= 0)
            {
                f->removeMember(z);
            }
            if (z) generalFactory.removeZeichnung(*z);
            z = generalFactory.parseElement(*i.val(), generalFactory);
            if (z) f->addMember(z);
        }
        if (z) f->setMemberIndex(z, index++);
    }
    if (!element.hasAttribute("style"))
    {
        Fenster* tmp = generalFactory.getFactory().createFenster(
            generalFactory.getFactory().initParam);
        f->setStyle(tmp->getStyles());
        tmp->release();
    }
    return true;
}

void UIMLFrame::layout(XML::Element& element,
    Zeichnung& z,
    int pWidth,
    int pHeight,
    UIMLContainer& generalLayouter)
{
    Fenster* f = dynamic_cast<Fenster*>(&z);
    if (element.hasAttribute("title"))
        f->setTitel(element.getAttributeValue("title"));
    if (element.hasAttribute("title-height"))
    {
        f->zTTextFeld()->setSize(f->zTTextFeld()->getBreite(),
            (int)element.getAttributeValue("title-height"));
    }
    if (element.hasAttribute("title-font-size"))
    {
        f->zTTextFeld()->setSchriftSize(
            (unsigned char)(int)element.getAttributeValue("title-font-size"));
    }
    if (element.hasAttribute("title-text-color"))
    {
        f->zTTextFeld()->setSchriftFarbe(
            (int)element.getAttributeValue("title-text-color"));
    }
    if (element.hasAttribute("width"))
    {
        Text w = element.getAttributeValue("width");
        if (w.istGleich("auto"))
        {
            z.setWidth(f->getNeededChildWidth());
        }
    }
    if (element.hasAttribute("height"))
    {
        Text h = element.getAttributeValue("height");
        if (h.istGleich("auto"))
        {
            z.setHeight(f->getNeededChildHeight());
        }
    }
    if (element.hasAttribute("display"))
    {
        UIMLElement::layout(element,
            z,
            pWidth,
            pHeight,
            generalLayouter); // calculate all sizes
        if (element.getAttributeValue("display").istGleich("column"))
        {
            int gap = calculateSize(element.getAttributeValue("gap"), pHeight);
            int y = 0;
            for (Zeichnung* z : f->getMembers())
            {
                Text id = generalLayouter.getZeichnungId(*z);
                auto child = element.selectChildsByAttribute("id", id);

                if (child.exists())
                {
                    if (!child.whereAttributeExists("align-left").exists()
                        && !child.whereAttributeExists("align-right").exists()
                        && !child.whereAttributeExists("align-top").exists()
                        && !child.whereAttributeExists("align-bottom").exists())
                    {
                        z->setY(y);
                        y += z->getHeight() + gap;
                    }
                }
            }
        }
        else if (element.getAttributeValue("display").istGleich("row"))
        {
            int gap = calculateSize(element.getAttributeValue("gap"), pWidth);
            int x = 0;
            for (Zeichnung* z : f->getMembers())
            {
                Text id = generalLayouter.getZeichnungId(*z);
                auto child = element.selectChildsByAttribute("id", id);

                if (child.exists())
                {
                    if (!child.whereAttributeExists("align-left").exists()
                        && !child.whereAttributeExists("align-right").exists()
                        && !child.whereAttributeExists("align-top").exists()
                        && !child.whereAttributeExists("align-bottom").exists())
                    {
                        z->setX(x);
                        x += z->getBreite() + gap;
                    }
                }
            }
        }
    }
    UIMLElement::layout(element,
        z,
        pWidth,
        pHeight,
        generalLayouter); // calculate all remaining positions
    if (element.getAttributeValue("vScroll").istGleich("auto"))
    {
        f->setStyle(Fenster::Style::VScroll,
            f->getNeededChildHeight() > f->getInnenHeight());
        f->setVSBScroll(10);
        f->updateVScroll();
    }
    if (element.getAttributeValue("hScroll").istGleich("auto"))
    {
        f->setStyle(Fenster::Style::HScroll,
            f->getNeededChildWidth() > f->getInnenBreite());
        f->setHSBScroll(10);
        f->updateHScroll();
    }
}

// Erstellt eine UIML View
UIMLView::UIMLView()
    : ZeichnungHintergrund()
{
    style = Style::MEIgnoreInside | Style::MEIgnoreParentInside
          | Style::MEIgnoreSichtbar | Style::MEIgnoreVerarbeitet;
    members = new RCTrie<Zeichnung>();
    dom = 0;
    nextId = 0;
    memset(&init, 0, sizeof(UIInit));
    addKnownElement(new UIMLTextField());
    addKnownElement(new UIMLButton());
    addKnownElement(new UIMLCheck());
    addKnownElement(new UIMLText());
    addKnownElement(new UIMLTextArea());
    addKnownElement(new UIMLTable());
    addKnownElement(new UIMLFrame());
}

// Erstellt eine UIML View zu einem UIML Text
//  uiml: Ein xml element gemaet des ksg uiml standarts
UIMLView::UIMLView(XML::Element* uiml, UIInit& init)
    : UIMLView()
{
    this->init = init;
    setUIML(uiml);
}

// Erstellt eine UIML View zu einem UIML Text
//  uiml: Ein xml text gemaet des ksg uiml standarts
UIMLView::UIMLView(Text uiml, UIInit& init)
    : UIMLView()
{
    this->init = init;
    setUIML(uiml);
}

UIMLView::~UIMLView()
{
    if (dom) dom->release();
    members->release();
}

// Verarbeitet ein Maus Ereignis. Wird vom Framework automatisch aufgerufen.
//  me: Das Ereignis
void UIMLView::doMausEreignis(MausEreignis& me, bool userRet)
{
    if (dom)
    {
        bool verarbeitet = me.verarbeitet;
        me.verarbeitet |= hatStyleNicht(Style::Sichtbar);
        bool insideParent = me.insideParent;
        if (!hatStyle(Style::Sichtbar) || !me.insideParent || me.verarbeitet
            || me.mx < 0 || me.my < 0 || me.mx >= gr.x || me.my >= gr.y
            || !userRet)
            me.insideParent = 0;
        int rbr = 0;
        if (hatStyle(Style::Rahmen) && rahmen) rbr = rahmen->getRBreite();
        me.mx -= rbr;
        me.my -= rbr;
        if (hatStyle(Style::VScroll) && vertikalScrollBar)
            me.my += vertikalScrollBar->getScroll();
        if (hatStyle(Style::HScroll) && horizontalScrollBar)
            me.mx += horizontalScrollBar->getScroll();
        if (dom)
        {
            for (auto i = dom->getChilds(); i; i++)
            { // TODO render elements backwards
                Zeichnung* z = members->z(i->getAttributeValue("id"),
                    i->getAttributeValue("id").getLength());
                if (z) z->doPublicMausEreignis(me);
            }
        }
        me.mx += rbr;
        me.my += rbr;
        if (hatStyle(Style::VScroll) && vertikalScrollBar)
            me.my -= vertikalScrollBar->getScroll();
        if (hatStyle(Style::HScroll) && horizontalScrollBar)
            me.mx -= horizontalScrollBar->getScroll();
        if (!hatStyle(Style::Sichtbar) || !me.insideParent || me.verarbeitet
            || me.mx < 0 || me.my < 0 || me.mx >= gr.x || me.my >= gr.y
            || !userRet)
            me.insideParent = insideParent;
        else
            me.verarbeitet = 1;
        if (hatStyleNicht(Style::Sichtbar)) me.verarbeitet = verarbeitet;
    }
}

void Framework::UIMLView::setOnMemberMouseEvent(std::function<bool(
        XML::Element& element, Zeichnung& member, MausEreignis me)>
        onEventAction)
{
    onMemberMouseEvent = onEventAction;
}

void Framework::UIMLView::setOnMemberKeyboardEvent(std::function<bool(
        XML::Element& element, Zeichnung& member, TastaturEreignis te)>
        onEventAction)
{
    onMemberKeyboardEvent = onEventAction;
}

//! entfernt alle bekannten elemente, die im uiml verwendet werden koennen
void UIMLView::removeAllKnownElements()
{
    knownElements.leeren();
}

//! fuegt ein neues bekanntes element hinzu, dass danach im uiml verwendet werden
//! kann.
void UIMLView::addKnownElement(UIMLElement* element)
{
    knownElements.add(element);
}

//! prueft, ob ein xml Element ein bekanntes uiml Element ist;
bool UIMLView::isKnownElement(XML::Element* zElement)
{
    for (UIMLElement* element : knownElements)
    {
        if (element->isApplicableFor(*zElement)) return 1;
    }
    return 0;
}

// setzt den inhalt der view
//  uiml: Ein xml element gemaet des ksg uiml standarts
void UIMLView::setUIML(XML::Element* uiml)
{
    if (dom)
    { // update dom and members
        auto newChilds = uiml->selectChildren().selectAllElements();
        // remove old members
        for (XML::Element* i :
            dom->selectChildren().selectAllElements().whereAttributeExists(
                "id"))
        {
            Framework::Text id = i->getAttributeValue("id");
            if (!newChilds.whereAttributeEquals("id", id).exists())
            {
                Zeichnung* z = members->z(id, id.getLength());
                if (z) removeZeichnung(*z);
            }
        }
        dom = uiml;
        update();
    }
    else
    { // initialize dom and members
        dom = uiml;
        for (auto i = dom->getChilds(); i; i++)
        {
            Zeichnung* z = parseElement(*i.val(), *this);
            if (z) z->release();
        }
    }
}

// setzt den inhalt der view
//  uiml: Ein xml text gemaet des ksg uiml standarts
void UIMLView::setUIML(Text uiml)
{
    setUIML(new XML::Element(uiml));
}

// Gibt eine zeichnung zurueck, welche in uiml eine bestimmte id hat
//  id: die id der Zeichnung
Zeichnung* UIMLView::zZeichnungById(const char* id)
{
    return members->z(id, textLength(id));
}

// Gibt eine zeichnung zurueck, welche in uiml eine bestimmte id hat
//  id: die id der Zeichnung
Zeichnung* UIMLView::getZeichnungById(const char* id)
{
    return members->get(id, textLength(id));
}

void Framework::UIMLView::update()
{
    for (auto i = dom->getChilds(); i; i++)
    {
        Text id = i->getAttributeValue("id");
        Zeichnung* z = zZeichnungById(id);
        if (!id.getLength() || !z || !updateElement(*i.val(), *z, *this))
        {
            z = parseElement(*i.val(), *this);
            if (z) z->release();
        }
    }
}

// aktualisiert groesse und position aller Zeichnungen gemaess den spezifikationen
// in UIML
void UIMLView::layout()
{
    if (dom)
    {
        for (auto i = dom->getChilds(); i; i++)
        {
            Text id = i->getAttributeValue("id");
            Zeichnung* z = zZeichnungById(id);
            if (z)
            {
                layout(*i.val(),
                    *z,
                    this->getInnenBreite(),
                    this->getInnenHeight(),
                    *this);
            }
        }
    }
}

// fuegt ein element hinzu
//  uiml: Ein xml text gemaet des KSG UIML standarts, welcher das neue Objekt
//  darstellt
Text UIMLView::addMember(Text uiml)
{
    XML::Element* e = new XML::Element(uiml);
    Zeichnung* z = parseElement(*e, *this);
    if (z)
    {
        dom->addChildAtFront(e);
        z->release();
    }
    return e->getAttributeValue("id");
}

// fuegt ein element zu einem Elternelement hinzu (funktioniert momentan nur mit
// frame Objekten)
//  uiml: Ein xml text gemaet des KSG UIML standarts, welcher das neue Objekt
//  darstellt
Text UIMLView::addMember(Text uiml, Text parentId)
{
    XML::Element* e = new XML::Element(uiml);
    XML::Editor ed = dom->selectChildren();
    while (ed.begin())
    {
        XML::Editor ed2 = ed.whereAttributeEquals("id", parentId);
        if (ed2.begin())
        {
            if (ed2.begin()->getName().istGleich("frame"))
            {
                Zeichnung* z = parseElement(*e, *this);
                if (z)
                {
                    dynamic_cast<Fenster*>(
                        members->z(parentId, parentId.getLength()))
                        ->addMember(z);
                    ed2.begin()->addChild(e);
                }
                return e->getAttributeValue("id");
            }
        }
        ed = ed.selectChildren();
    }
    e->release();
    return "";
}

// entfernt ein element
//  id: id des Elements
void UIMLView::removeMember(Text id)
{
    XML::Editor e = dom->selectChildsByAttribute("id", id);
    e.remove();
    members->remove(id, id.getLength());
}

// Verarbeitet ein Tastatur Ereignis. Wird vom Framework automatisch aufgerufen
//  te: Das Ereignis
void UIMLView::doTastaturEreignis(TastaturEreignis& te)
{
    bool verarbeitet = te.verarbeitet;
    ZeichnungHintergrund::doTastaturEreignis(te);
    te.verarbeitet = verarbeitet;
    if (dom)
    {
        for (auto i = dom->getChilds(); i; i++)
        { // TODO render elements backwards
            Zeichnung* z = members->z(i->getAttributeValue("id"),
                i->getAttributeValue("id").getLength());
            if (z) z->doTastaturEreignis(te);
        }
    }
}

// Updated den Zeichenhintergrund
//  tickVal: Die vergangene Zeit in Sekunden, die seit dem Letzten Aufruf dieser
//  Funktion verstrichen ist return: 1, wenn das Bild neu gezeichnet werden
//  muss. 0 sonnst
bool UIMLView::tick(double tickVal)
{
    if (dom)
    {
        for (auto i = dom->getChilds(); i; i++)
        { // TODO render elements backwards
            Zeichnung* z = members->z(i->getAttributeValue("id"),
                i->getAttributeValue("id").getLength());
            if (z) rend |= z->tick(tickVal);
        }
    }
    return ZeichnungHintergrund::tick(tickVal);
}

// Zeichnet den Hintergrund eines Zeichnunges nach rObj
void UIMLView::render(Bild& rObj)
{
    if (hatStyle(Zeichnung::Style::Sichtbar))
    {
        ZeichnungHintergrund::render(rObj);
        if (dom)
        {
            if (!rObj.setDrawOptions(pos.x + getRahmenBreite(),
                    pos.y + getRahmenBreite(),
                    gr.x + getRahmenBreite() * 2,
                    gr.y + getRahmenBreite() * 2))
                return;
            bool vSc = hatStyle(Style::VScroll) && vertikalScrollBar;
            bool hSc = hatStyle(Style::HScroll) && horizontalScrollBar;
            rObj.addScrollOffset(hSc ? horizontalScrollBar->getScroll() : 0,
                vSc ? vertikalScrollBar->getScroll() : 0);
            for (int i = dom->getChildCount() - 1; i >= 0; i--)
            { // TODO render elements backwards
                XML::Element* e = dom->zChild(i);
                Zeichnung* z = members->z(e->getAttributeValue("id"),
                    e->getAttributeValue("id").getLength());
                if (z) z->render(rObj);
            }
            rObj.releaseDrawOptions();
        }
    }
}

// Gibt den Dom Tree ohne erhoehten reference counter zurueck
// AEnderungen am Dom Tree sollten vermieden werden (nur aenderungen von
// attributen einzelner elemente sind erlaubt)
XML::Element* UIMLView::zDom() const
{
    return dom;
}

// Gibt den Dom Tree zurueck
// AEnderungen am Dom Tree sollten vermieden werden (nur aenderungen von
// attributen einzelner elemente sind erlaubt)
XML::Element* UIMLView::getDom() const
{
    return dom ? dynamic_cast<XML::Element*>(dom->getThis()) : 0;
}

bool UIMLView::isApplicableFor(XML::Element& element)
{
    for (UIMLElement* e : knownElements)
    {
        if (e->isApplicableFor(element)) return 1;
    }
    return 0;
}

Zeichnung* UIMLView::parseElement(
    XML::Element& element, UIMLContainer& generalFactory)
{
    Text id;
    if (element.hasAttribute("id"))
        id = element.getAttributeValue("id");
    else
    {
        id = Text("_") += nextId++;
        element.setAttribute("id", id);
    }
    Zeichnung* z = members->z(id, id.getLength());
    if (!z)
    {
        // precompute attributes
        if (element.hasAttribute("margin"))
        {
            Text m = element.getAttributeValue("margin");
            if (!element.hasAttribute("margin-left"))
                element.setAttribute("margin-left", m);
            if (!element.hasAttribute("margin-top"))
                element.setAttribute("margin-top", m);
            if (!element.hasAttribute("margin-right"))
                element.setAttribute("margin-right", m);
            if (!element.hasAttribute("margin-bottom"))
                element.setAttribute("margin-bottom", m);
        }
        if (element.hasAttribute("class"))
        {
            Text c = element.getAttributeValue("class");
            while (1)
            {
                Text* t;
                if (c.hat(","))
                    t = c.getTeilText(0, c.positionVon(','));
                else
                    t = new Text(c);
                XML::Editor ce
                    = dom->selectChildsByName("class").whereAttributeEquals(
                        "id", *t);
                for (auto i = ce.begin(); i; i++)
                {
                    for (auto j = i->getAttributeNames(),
                              k = i->getAttributeValues();
                        j && k;
                        j++, k++)
                    {
                        if (!element.hasAttribute(j->getText()))
                            element.setAttribute(j->getText(), i->getText());
                    }
                }
                t->release();
                if (c.hat(","))
                    c.remove(0, c.positionVon(',' + 1));
                else
                    break;
            }
        }
        if (element.hasAttribute("text-align"))
        {
            if (!element.hasAttribute("text-align-horizontal"))
                element.setAttribute("text-align-horizontal",
                    element.getAttributeValue("text-align"));
            if (!element.hasAttribute("text-align-vertical"))
                element.setAttribute("text-align-vertical",
                    element.getAttributeValue("text-align"));
        }
        // create objects
        for (UIMLElement* e : knownElements)
        {
            if (e->isApplicableFor(element))
            {
                z = e->parseElement(element, *this);
                break;
            }
        }
        if (z)
        {
            if (hatStyle(Style::GlobalMouseEvent))
            {
                z->addMausEreignis(
                    [this, z](void* p, void* o, MausEreignis me) {
                        return dom->selectChildren()
                            .selectAllElements()
                            .whereAttributeEquals("id", getZeichnungId(*z))
                            .getFirstElement()
                            .map<bool>([this, &me, z](
                                           RCPointer<XML::Element> element) {
                                return onMemberMouseEvent
                                         ? onMemberMouseEvent(*element, *z, me)
                                         : 0;
                            })
                            .orElse(0);
                    });
            }
            if (hatStyle(Style::GlobalTastaturEvent))
            {
                z->addTastaturEreignis(
                    [this, z](void* p, void* o, TastaturEreignis te) {
                        return dom->selectChildren()
                            .selectAllElements()
                            .whereAttributeEquals("id", getZeichnungId(*z))
                            .getFirstElement()
                            .map<bool>([this, &te, z](
                                           RCPointer<XML::Element> element) {
                                return onMemberKeyboardEvent
                                         ? onMemberKeyboardEvent(
                                               *element, *z, te)
                                         : 0;
                            })
                            .orElse(0);
                    });
            }
            members->set(
                id, id.getLength(), dynamic_cast<Zeichnung*>(z->getThis()));
            idList.add(new Text(id));
            memberList.add(z);
        }
    }
    else
        z->getThis();
    return z;
}

bool Framework::UIMLView::updateElement(
    XML::Element& element, Zeichnung& z, UIMLContainer& generalFactory)
{
    bool result = 0;
    for (UIMLElement* e : knownElements)
    {
        if (e->isApplicableFor(element))
        {
            result = e->updateElement(element, z, *this);
            break;
        }
    }
    if (!result)
    {
        for (XML::Element* element :
            element.selectChildren().selectAllElements().whereAttributeExists(
                "id"))
        { // element could not be updated so all children will be removed
            Framework::Text id = element->getAttributeValue("id");
            Zeichnung* z = zZeichnungById(id);
            if (z) removeZeichnung(*z);
        }
        removeZeichnung(z);
    }
    return result;
}

void UIMLView::layout(XML::Element& element,
    Zeichnung& z,
    int pWidth,
    int pHeight,
    UIMLContainer& generalLayouter)
{
    for (UIMLElement* e : knownElements)
    {
        if (e->isApplicableFor(element))
        {
            e->layout(element, z, pWidth, pHeight, *this);
            break;
        }
    }
}

Text Framework::UIMLView::getZeichnungId(Zeichnung& z)
{
    int index = memberList.getWertIndex(&z);
    if (index >= 0) return *idList.z(index);
    return "";
}

void Framework::UIMLView::removeZeichnung(Zeichnung& z)
{
    int index = memberList.getWertIndex(&z);
    if (index >= 0)
    {
        Text id = *idList.z(index);
        idList.remove(index);
        memberList.remove(index);
        members->remove(id, id.getLength());
    }
}

bool Framework::UIMLView::registerZeichnung(const char* id, Zeichnung* z)
{
    Zeichnung* existing = members->z(id, textLength(id));
    if (existing)
    {
        z->release();
        return 0;
    }
    members->set(id, textLength(id), z);
    return 1;
}

const UIInit& UIMLView::getFactory()
{
    return init;
}

//! calculates the needed size for all content elements to be visible
Punkt UIMLView::calculateContentSize()
{
    Punkt maxP(0, 0);
    for (int i = dom->getChildCount() - 1; i >= 0; i--)
    { // TODO render elements backwards
        XML::Element* e = dom->zChild(i);
        Zeichnung* z = members->z(
            e->getAttributeValue("id"), e->getAttributeValue("id").getLength());
        if (z)
        {
            maxP.x = MAX(maxP.x, z->getPosition().x + z->getBreite());
            maxP.y = MAX(maxP.y, z->getPosition().y + z->getHeight());
        }
    }
    maxP.x += 2 * getRahmenBreite();
    maxP.y += 2 * getRahmenBreite();
    return maxP;
}