#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); 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); 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); 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); 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); 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); 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(&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 = element.getChilds(); i; i++) { Zeichnung* z = 0; if (i->hasAttribute("id")) { z = generalLayouter.zZeichnungById(i->getAttributeValue("id")); } if (z) { generalLayouter.layout( *i.val(), *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; } } 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); updateElement(element, *t, generalFactory); return t; } bool Framework::UIMLTextField::updateElement( XML::Element& element, Zeichnung& z, UIMLContainer& generalFactory) { TextFeld* t = dynamic_cast(&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(&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(&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(&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); updateElement(element, *t, generalFactory); return t; } bool Framework::UIMLText::updateElement( XML::Element& element, Zeichnung& z, UIMLContainer& generalFactory) { TextFeld* t = dynamic_cast(&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(&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); updateElement(element, *t, generalFactory); return t; } bool Framework::UIMLTextArea::updateElement( XML::Element& element, Zeichnung& z, UIMLContainer& generalFactory) { TextFeld* t = dynamic_cast(&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(&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(&z); if (!t) return false; int index = 0; int linePos = 0; int numCols = 0; for (auto i = element.getChilds(); i; i++) { Text id; if (i->hasAttribute("id")) id = i->getAttributeValue("id"); else { id = Text("_") += 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(*i.val(), generalFactory); if (z) 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()); } } } 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(&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(&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(); 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 gemät 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 gemät 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 onEventAction) { onMemberMouseEvent = onEventAction; } void Framework::UIMLView::setOnMemberKeyboardEvent(std::function onEventAction) { onMemberKeyboardEvent = onEventAction; } //! entfernt alle bekannten elemente, die im uiml verwendet werden können void UIMLView::removeAllKnownElements() { knownElements.leeren(); } //! fügt ein neues bekanntes element hinzu, dass danach im uiml verwendet werden //! kann. void UIMLView::addKnownElement(UIMLElement* element) { knownElements.add(element); } //! prüft, 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 gemät 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 gemät des ksg uiml standarts void UIMLView::setUIML(Text uiml) { setUIML(new XML::Element(uiml)); } // Gibt eine zeichnung zurück, 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 zurück, 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 größe und position aller Zeichnungen gemäß 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); } } } } // fügt ein element hinzu // uiml: Ein xml text gemät 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"); } // fügt ein element zu einem Elternelement hinzu (funktioniert momentan nur mit // frame Objekten) // uiml: Ein xml text gemät 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( 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 erhöhten reference counter zurück // Änderungen am Dom Tree sollten vermieden werden (nur änderungen von // attributen einzelner elemente sind erlaubt) XML::Element* UIMLView::zDom() const { return dom; } // Gibt den Dom Tree zurück // Änderungen am Dom Tree sollten vermieden werden (nur änderungen von // attributen einzelner elemente sind erlaubt) XML::Element* UIMLView::getDom() const { return dom ? dynamic_cast(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([this, &me, z]( RCPointer 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([this, &te, z]( RCPointer element) { return onMemberKeyboardEvent ? onMemberKeyboardEvent( *element, *z, te) : 0; }) .orElse(0); }); } members->set( id, id.getLength(), dynamic_cast(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; }