#include "Drawing.h" #include "AlphaField.h" #include "Image.h" #include "Screen.h" #include "Globals.h" #include "MouseEvent.h" #include "Border.h" #include "Font.h" #include "Scroll.h" #include "KeyboardEvent.h" #include "Text.h" #include "TextField.h" #include "ToolTip.h" #include "UIInitialization.h" #ifdef WIN32 # include #endif using namespace Framework; // Contents of the Drawable class from Drawing.h // Constructor Drawable::Drawable() : ReferenceCounter(), pos(0, 0), gr(0, 0), makParam(0), takParam(0), mak(0), tak(0), nmakParam(0), ntakParam(0), nMak(0), nTak(0), mouseIn(0), toolTip(0), style(0), rend(0), onNeedToolTip(0), toolTipRequested(0) {} // Destructor Drawable::~Drawable() { if (toolTip) toolTip->release(); } void Drawable::doMouseEvent(MouseEvent& me, bool userRet) { me.processed = userRet; } // non-constant void Drawable::setRender() { rend = 1; } void Drawable::setToolTipText( const char* txt, Screen* zScreen, Font* zFont) { if (!txt) toolTip = (ToolTip*)toolTip->release(); else { if (!toolTip) { toolTip = new ToolTip(zScreen); toolTip->addStyle(DrawableBackground::Style::Background | DrawableBackground::Style::HAlpha | DrawableBackground::Style::Border | DrawableBackground::Style::Visible); toolTip->setBackgroundColor(0xA0000000); toolTip->setBorderColor(0xFFFFFFFF); toolTip->setBorderWidth(1); if (mouseIn && toolTip) toolTip->setMouseIn(1); } UIInit init = defaultUI(zFont, zScreen); TextField* t = init.createTextField(init.initParam); t->setText(txt); t->setSize(t->zTextRenderer()->getTextWidth(txt), t->zTextRenderer()->getTextHeight(txt)); toolTip->addMember(t); } toolTipRequested = 0; } // sets a function that creates a tooltip on first use // if one does not exist yet // initToolTip: the function void Drawable::setNeedToolTipEvent( std::function onNeedToolTip) { this->onNeedToolTip = onNeedToolTip; } // sets the tooltip // tt: the tooltip void Drawable::setToolTipZ(ToolTip* tt) { if (toolTip) toolTip->release(); toolTip = tt; if (mouseIn && toolTip) toolTip->setMouseIn(1); toolTipRequested = 0; } void Drawable::lockDrawable() { cs.lock(); } void Drawable::unlockDrawable() { cs.unlock(); } void Drawable::setMouseEventParameter( void* p) // sets the mouse event parameter { makParam = p; } void Drawable::setKeyboardEventParameter( void* p) // sets the keyboard event parameter { takParam = p; } void Drawable::setMouseEvent(MouseAction ak) // sets the mouse event { mak = ak; } void Framework::Drawable::addMouseEvent(MouseAction ak) { if (!mak) { mak = ak; } else { MouseAction old = mak; mak = [old, ak](void* p, void* o, MouseEvent me) { return old(p, o, me) && ak(p, o, me); }; } } void Drawable::setKeyboardEvent( KeyboardAction ak) // sets the keyboard event { tak = ak; } void Framework::Drawable::addKeyboardEvent(KeyboardAction ak) { if (!tak) { tak = ak; } else { KeyboardAction old = tak; tak = [old, ak](void* p, void* o, KeyboardEvent te) { return old(p, o, te) && ak(p, o, te); }; } } void Drawable::setNMouseEventParameter( void* p) // sets the mouse event parameter { nmakParam = p; } void Drawable::setNKeyboardEventParameter( void* p) // sets the keyboard event parameter { ntakParam = p; } void Drawable::setNMouseEvent(MouseAction ak) // sets the mouse event { nMak = ak; } void Drawable::setNKeyboardEvent( KeyboardAction ak) // sets the keyboard event { nTak = ak; } void Drawable::doPublicMouseEvent(MouseEvent& me) // calls Mak { bool lock = hasStyle(Style::MELockDrawable); if (lock) lockDrawable(); bool inside = isPointInside(me.mx, me.my); if (!me.insideParent || me.processed || !inside) { if (mouseIn) { mouseIn = 0; if (toolTip) toolTip->setMouseIn(0); MouseEvent me2; me2.id = ME_Leaves; me2.mx = me.mx - pos.x; me2.my = me.my - pos.y; me2.processed = 0; me2.insideParent = me.insideParent; bool userRet = mak && mak(makParam, this, me2); doMouseEvent(me2, userRet); } } if (!inside && me.id == ME_PLeft) removeStyle(Style::Focus); if ((me.processed && hasStyleNot(Style::MEIgnoreProcessed)) || (!inside && hasStyleNot(Style::MEIgnoreInside)) || (hasStyleNot(Style::Visible) && hasStyleNot(Style::MEIgnoreVisible))) { if (lock) unlockDrawable(); return; } if (inside && me.id == ME_PLeft) addStyle(Style::Focus); if (me.insideParent && !mouseIn && me.id != ME_Leaves && inside && !me.processed && hasStyle(Style::Visible)) { mouseIn = 1; if (toolTip) toolTip->setMouseIn(1); else if (onNeedToolTip && !toolTipRequested) { toolTipRequested = onNeedToolTip(this, Point(me.mx - pos.x, me.my - pos.y)); } MouseEvent me2; me2.id = ME_Enter; me2.mx = me.mx - pos.x; me2.my = me.my - pos.y; me2.processed = 0; me2.insideParent = 1; bool userRet = mak && mak(makParam, this, me2); doMouseEvent(me2, userRet); } else if (me.insideParent && mouseIn && me.id != ME_Leaves && inside && !me.processed && hasStyle(Style::Visible) && !toolTip && onNeedToolTip && !toolTipRequested) { toolTipRequested = onNeedToolTip(this, Point(me.mx - pos.x, me.my - pos.y)); } Point old = Point(me.mx, me.my); me.mx -= pos.x, me.my -= pos.y; if (me.insideParent || hasStyle(Style::MEIgnoreParentInside)) { bool userRet = hasStyle(Style::Allowed) && (me.processed || !me.insideParent || (inside && mak && mak(makParam, this, me))); bool vera = me.processed; doMouseEvent(me, userRet); if (nMak && me.processed && !vera && hasStyle(Style::Allowed) && me.insideParent && inside) me.processed = nMak(nmakParam, this, me); } me.mx = old.x, me.my = old.y; if (lock) unlockDrawable(); } void Drawable::doKeyboardEvent(KeyboardEvent& te) // calls Tak { if (te.processed) return; if (tak) te.processed |= tak(takParam, this, te); if (nTak && te.processed) te.processed = nTak(ntakParam, this, te); } void Drawable::setPosition(const Point& pos) // sets the position { lockDrawable(); if (this->pos != pos) rend = 1; this->pos = pos; unlockDrawable(); } void Drawable::setX(int xPos) { lockDrawable(); if (pos.x != xPos) { rend = 1; pos.x = xPos; } unlockDrawable(); } void Drawable::setY(int yPos) { lockDrawable(); if (pos.y != yPos) { rend = 1; pos.y = yPos; } unlockDrawable(); } void Drawable::setSize(const Point& gr) // sets the size { lockDrawable(); if (this->gr != gr) rend = 1; this->gr = gr; unlockDrawable(); } void Drawable::setPosition(int x, int y) // sets the position { setPosition(Point(x, y)); } void Drawable::setSize(int x, int y) // sets the size { setSize(Point(x, y)); } void Drawable::setWidth(int width) { lockDrawable(); if (this->gr.x != width) rend = 1; gr.x = width; unlockDrawable(); } void Drawable::setHeight(int height) { lockDrawable(); if (this->gr.y != height) rend = 1; gr.y = height; unlockDrawable(); } bool Drawable::tick(double tickval) { bool r = rend; rend = 0; return r; } void Drawable::setStyle(__int64 style) // sets the style of the text field { if (this->style != style) { this->style = style; rend = 1; } } void Drawable::setStyle(__int64 style, bool add_remove) { if (add_remove && (this->style | style) != this->style) { this->style |= style; rend = 1; } else if (!add_remove && (this->style & ~style) != this->style) { if (toolTip && (style | Style::Visible) == style) toolTip->setMouseIn(0); this->style &= ~style; rend = 1; } } void Drawable::addStyle(__int64 style) { if ((this->style | style) != this->style) { this->style |= style; rend = 1; } } void Drawable::removeStyle(__int64 style) { if ((this->style & ~style) != this->style) { if (toolTip && (style | Style::Visible) == style) toolTip->setMouseIn(0); this->style &= ~style; rend = 1; } } void Drawable::render(Image& zRObj) { if (toolTip && (style | Style::Visible) == style) toolTip->setDrawing(); } // constant bool Drawable::hasMouseEvent() const // checks if Mak is set { return mak != 0; } bool Drawable::hasKeyboardEvent() const // checks if Tak is set { return tak != 0; } const Point& Drawable::getPosition() const // returns the position { return pos; } const Point& Drawable::getSize() const // returns the size { return gr; } int Drawable::getWidth() const // returns the width { return gr.x; } int Drawable::getHeight() const // returns the height { return gr.y; } // Returns the width of the interior area of the drawing in pixels int Drawable::getInnerWidth() const { return gr.x; } // Returns the height of the interior area of the drawing in pixels int Drawable::getInnenHeight() const { return gr.y; } int Drawable::getX() const // returns X { return pos.x; } int Drawable::getY() const // returns Y { return pos.y; } // Checks if a point is inside this object // p: the point // return: 1 if the point is inside, 0 otherwise bool Drawable::isPointInside(Point p) const { return isPointInside(p.x, p.y); } // Checks if a point is inside this object // x: the x coordinate of the point // y: the y coordinate of the point // return: 1 if the point is inside, 0 otherwise bool Drawable::isPointInside(int x, int y) const { return x >= pos.x && x <= pos.x + gr.x && y >= pos.y && y <= pos.y + gr.y; } ToolTip* Drawable::getToolTip() const // returns the ToolTip text { return dynamic_cast(toolTip->getThis()); } ToolTip* Drawable::zToolTip() const { return toolTip; } bool Drawable::hasStyle(__int64 style) const // checks if style is present { return (this->style | style) == this->style; } bool Drawable::hasStyleNot( __int64 style) const // checks if style is not present { return (this->style | style) != this->style; } __int64 Framework::Drawable::getStyles() const { return style; } Drawable* Drawable::duplicate() const // Creates a copy of the drawing { Drawable* obj = new Drawable(); obj->setPosition(pos); obj->setSize(gr); obj->setMouseEventParameter(makParam); obj->setKeyboardEventParameter(takParam); obj->setMouseEvent(mak); obj->setKeyboardEvent(tak); if (toolTip) obj->setToolTipZ((ToolTip*)toolTip->duplicate()); return obj; } // Contents of the DrawableBackground class from Drawing.h // Constructor DrawableBackground::DrawableBackground() : Drawable() { backgroundColor = 0xFF000000; border = 0; backgroundImage = 0; backgroundFeld = 0; horizontalScrollBar = 0; vertikalScrollBar = 0; innenPosition.x = 0; innenPosition.y = 0; innenSize.x = 0; innenSize.y = 0; } // Destructor DrawableBackground::~DrawableBackground() { if (border) border->release(); if (backgroundImage) backgroundImage->release(); if (backgroundFeld) backgroundFeld->release(); if (horizontalScrollBar) horizontalScrollBar->release(); if (vertikalScrollBar) vertikalScrollBar->release(); } void DrawableBackground::doMouseEvent(MouseEvent& me, bool userRet) { if (userRet) { int rbr = 0; if (hasStyle(Style::Border) && border) rbr = border->getRWidth(); bool vs = hasStyle(Style::VScroll) && vertikalScrollBar; bool hs = hasStyle(Style::HScroll) && horizontalScrollBar; if (vs) { if (hs) horizontalScrollBar->doMouseMessage( rbr, gr.y - rbr - 15, gr.x - rbr * 2 - 15, 15, me); vertikalScrollBar->doMouseMessage( gr.x - rbr - 15, rbr, 15, gr.y - rbr * 2, me); } else if (hs) horizontalScrollBar->doMouseMessage( rbr, gr.y - rbr - 15, gr.x - rbr * 2, 15, me); } me.processed = userRet; } void DrawableBackground::setBackgroundImage( Image* bild) // sets the background image { if (!backgroundImage) backgroundImage = new Image(); backgroundImage->newImage(bild->getWidth(), bild->getHeight(), 0); int* buff1 = backgroundImage->getBuffer(); int* buff2 = bild->getBuffer(); for (int i = 0; i < bild->getWidth() * bild->getHeight(); ++i) buff1[i] = buff2[i]; bild->release(); rend = 1; } void DrawableBackground::setBackgroundImageZ( Image* bild) // sets a pointer to the background image { if (backgroundImage != bild) { if (backgroundImage) backgroundImage->release(); backgroundImage = bild; rend = 1; } } void DrawableBackground::setBackgroundColor( int fc) // sets the background color { if (backgroundColor != fc) { backgroundColor = fc; rend = 1; } } void DrawableBackground::setAlphaFieldZ( AlphaField* buff) // sets a pointer to the background buffer { if (backgroundFeld != buff) { if (backgroundFeld) backgroundFeld->release(); backgroundFeld = buff; rend = 1; } } void DrawableBackground::setAlphaFieldStrength( int st) // sets the strength of the background buffer { if (!backgroundFeld) { backgroundFeld = new AlphaField(); rend = 1; } if (backgroundFeld->getStrength() != st) { backgroundFeld->setStrength(st); rend = 1; } } void DrawableBackground::setAlphaFieldColor( int fc) // sets the color of the background buffer { if (!backgroundFeld) { backgroundFeld = new AlphaField(); rend = 1; } if (backgroundFeld->getColor() != fc) { backgroundFeld->setColor(fc); rend = 1; } } void DrawableBackground::setBorderZ( Border* ram) // sets a pointer to the border { if (border != ram) { if (border) border->release(); border = ram; rend = 1; } } void DrawableBackground::setBorderWidth(int br) // sets the border width { if (!border) { border = new LBorder(); rend = 1; } if (border->getRWidth() != br) { border->setBorderWidth(br); rend = 1; } } void DrawableBackground::setBorderColor(int fc) // sets the border color { if (!border) { border = new LBorder(); rend = 1; } if (border->getColor() != fc) { border->setColor(fc); rend = 1; } } void DrawableBackground::setVerticalClickScroll( int ks) // sets the vertical scroll speed { if (!vertikalScrollBar) { vertikalScrollBar = new VScrollBar(); rend = 1; } if (vertikalScrollBar->getClickScroll() != ks) { vertikalScrollBar->setClickScroll(ks); rend = 1; } } void DrawableBackground::setVerticalScrollPos( int pos) // sets the vertical scroll position { if (!vertikalScrollBar) { vertikalScrollBar = new VScrollBar(); rend = 1; } if (vertikalScrollBar && vertikalScrollBar->getScroll() != pos) { vertikalScrollBar->scroll(pos); rend = 1; } } void DrawableBackground::setVerticalScrollColor( int f, int bgF) // sets the scroll color { if (!vertikalScrollBar) { vertikalScrollBar = new VScrollBar(); rend = 1; } if (vertikalScrollBar && (vertikalScrollBar->getColor() != f || vertikalScrollBar->getBgColor() != bgF)) { vertikalScrollBar->setColor(f); vertikalScrollBar->setBgColor(bgF, bgF != 0); rend = 1; } } void DrawableBackground::setHorizontalClickScroll( int ks) // sets the horizontal scroll speed { if (!horizontalScrollBar) { horizontalScrollBar = new HScrollBar(); rend = 1; } if (horizontalScrollBar && horizontalScrollBar->getClickScroll() != ks) { horizontalScrollBar->setClickScroll(ks); rend = 1; } } void DrawableBackground::setHorizontalScrollPos( int pos) // sets the horizontal scroll position { if (!horizontalScrollBar) { horizontalScrollBar = new HScrollBar(); rend = 1; } if (horizontalScrollBar && horizontalScrollBar->getScroll() != pos) { horizontalScrollBar->scroll(pos); rend = 1; } } void DrawableBackground::setHorizontalScrollColor( int f, int bgF) // sets the scroll color { if (!horizontalScrollBar) { horizontalScrollBar = new HScrollBar(); rend = 1; } if (horizontalScrollBar && (horizontalScrollBar->getColor() != f || horizontalScrollBar->getBgColor() != bgF)) { horizontalScrollBar->setColor(f); horizontalScrollBar->setBgColor(bgF, bgF != 0); rend = 1; } } bool DrawableBackground::tick(double tickVal) { if (vertikalScrollBar && hasStyle(Style::VScroll)) rend |= vertikalScrollBar->getNeedRender(); if (horizontalScrollBar && hasStyle(Style::HScroll)) rend |= horizontalScrollBar->getNeedRender(); return Drawable::tick(tickVal); } void DrawableBackground::render(Image& rObj) { innenPosition.x = pos.x; innenPosition.y = pos.y; innenSize.x = gr.x; innenSize.y = gr.y; if (hasStyleNot(Style::Visible)) return; lockDrawable(); if (!rObj.setDrawOptions(pos.x, pos.y, gr.x, gr.y)) { unlockDrawable(); return; } Drawable::render(rObj); int rbr = 0; if (hasStyle(Style::Border) && border) { border->setSize(gr); border->render(rObj); rbr = border->getRWidth(); } innenPosition.x += rbr; innenPosition.y += rbr; innenSize.x -= rbr * 2; innenSize.y -= rbr * 2; if (!rObj.setDrawOptions(rbr, rbr, gr.x - rbr * 2, gr.y - rbr * 2)) { rObj.releaseDrawOptions(); unlockDrawable(); return; } bool vs = vertikalScrollBar && hasStyle(Style::VScroll); bool hs = horizontalScrollBar && hasStyle(Style::HScroll); if (vs) { vertikalScrollBar->render( gr.x - rbr * 2 - 15, 0, 15, gr.y - rbr * 2, rObj); innenSize.x -= 15; if (hs) { horizontalScrollBar->render( 0, gr.y - rbr * 2 - 15, gr.x - rbr * 2 - 15, 15, rObj); innenSize.y -= 15; if (!rObj.setDrawOptions( 0, 0, gr.x - rbr * 2 - 15, gr.y - rbr * 2 - 15)) { rObj.releaseDrawOptions(); rObj.releaseDrawOptions(); unlockDrawable(); return; } horizontalScrollBar->update( horizontalScrollBar->getScrollData()->max, innenSize.x); } else { if (!rObj.setDrawOptions(0, 0, gr.x - rbr * 2 - 15, gr.y - rbr * 2)) { rObj.releaseDrawOptions(); rObj.releaseDrawOptions(); unlockDrawable(); return; } } vertikalScrollBar->update( vertikalScrollBar->getScrollData()->max, innenSize.y); } else if (hs) { horizontalScrollBar->render( rbr, gr.y - rbr * 2 - 15, gr.x - rbr * 2, 15, rObj); innenSize.y -= 15; if (!rObj.setDrawOptions(0, 0, gr.x - rbr * 2, gr.y - rbr * 2 - 15)) { rObj.releaseDrawOptions(); rObj.releaseDrawOptions(); unlockDrawable(); return; } } if (hasStyle(Style::Background)) { if (hasStyle(Style::HAlpha)) rObj.alphaRegion( 0, 0, gr.x - rbr * 2, gr.y - rbr * 2, backgroundColor); else rObj.fillRegion( 0, 0, gr.x - rbr * 2, gr.y - rbr * 2, backgroundColor); if (hasStyle(Style::HImage) && backgroundImage) { if (hasStyle(Style::HImageScale)) { if (hasStyle(Style::HAlpha)) rObj.alphaImageScaled( 0, 0, gr.x - rbr * 2, gr.y - rbr * 2, *backgroundImage); else rObj.drawImageScaled( 0, 0, gr.x - rbr * 2, gr.y - rbr * 2, *backgroundImage); } else { int x = (gr.x - rbr * 2 - backgroundImage->getSize().x) / 2; int y = (gr.y - rbr * 2 - backgroundImage->getSize().y) / 2; if (hasStyle(Style::HAlpha)) rObj.alphaImage( x, y, gr.x - rbr * 2, gr.y - rbr * 2, *backgroundImage); else rObj.drawImage( x, y, gr.x - rbr * 2, gr.y - rbr * 2, *backgroundImage); } } } if (hasStyle(Style::Buffered) && backgroundFeld) { backgroundFeld->setSize(gr.x - rbr * 2, gr.y - rbr * 2); backgroundFeld->render(rObj); } if (vs || hs) rObj.releaseDrawOptions(); rObj.releaseDrawOptions(); rObj.releaseDrawOptions(); unlockDrawable(); } // Returns the width of the interior area of the drawing in pixels int DrawableBackground::getInnerWidth() const { return getWidth() - 2 * getBorderWidth(); } // Returns the height of the interior area of the drawing in pixels int DrawableBackground::getInnenHeight() const { return getHeight() - 2 * getBorderWidth(); } Image* DrawableBackground::getBackgroundImage() const // returns the background image { if (!backgroundImage) return 0; return dynamic_cast(backgroundImage->getThis()); } Image* DrawableBackground::zBackgroundImage() const // returns the background image without increased reference counter { return backgroundImage; } int DrawableBackground::getBackgroundColor() const // returns the background color { return backgroundColor; } AlphaField* DrawableBackground::getAlphaField() const // returns the background buffer { if (!backgroundFeld) return 0; return dynamic_cast(backgroundFeld->getThis()); } AlphaField* DrawableBackground::zAlphaField() const // returns the background buffer without increased reference counter { return backgroundFeld; } int DrawableBackground::getAlphaFieldStrength() const // returns the strength of the background buffer { if (!backgroundFeld) return 0; return backgroundFeld->getStrength(); } int DrawableBackground::getAlphaFieldColor() const // returns the color of the background buffer { return backgroundFeld->getColor(); } Border* DrawableBackground::getBorder() const // returns the border { if (!border) return 0; return dynamic_cast(border->getThis()); } Border* DrawableBackground::zBorder() const // returns the border without increased reference counter { return border; } int DrawableBackground::getBorderWidth() const // returns the border width { if (!border || hasStyleNot(Style::Border)) return 0; return border->getRWidth(); } int DrawableBackground::getBorderColor() const // returns the border color { return border->getColor(); } int DrawableBackground::getVerticalClickScroll() const { return vertikalScrollBar ? vertikalScrollBar->getClickScroll() : 0; } int DrawableBackground::getVerticalScrollPos() const { return vertikalScrollBar ? vertikalScrollBar->getScroll() : 0; } int DrawableBackground::getVerticalScrollColor() const { return vertikalScrollBar ? vertikalScrollBar->getColor() : 0; } int DrawableBackground::getVerticalScrollBackground() const { return vertikalScrollBar ? vertikalScrollBar->getBgColor() : 0; } int DrawableBackground::getHorizontalClickScroll() const { return horizontalScrollBar ? horizontalScrollBar->getClickScroll() : 0; } int DrawableBackground::getHorizontalScrollPos() const { return horizontalScrollBar ? horizontalScrollBar->getScroll() : 0; } int DrawableBackground::getHorizontalScrollColor() const { return horizontalScrollBar ? horizontalScrollBar->getColor() : 0; } int DrawableBackground::getHorizontalScrollBackground() const { return horizontalScrollBar ? horizontalScrollBar->getBgColor() : 0; } Drawable* DrawableBackground::duplicate() const // Creates a copy of the drawing { DrawableBackground* obj = new DrawableBackground(); obj->setPosition(pos); obj->setSize(gr); obj->setMouseEventParameter(makParam); obj->setKeyboardEventParameter(takParam); obj->setMouseEvent(mak); obj->setKeyboardEvent(tak); if (toolTip) obj->setToolTipZ((ToolTip*)toolTip->duplicate()); obj->setStyle(style); obj->setBackgroundColor(backgroundColor); if (backgroundFeld) obj->setAlphaFieldZ((AlphaField*)backgroundFeld->duplicate()); if (border) obj->setBorderZ((Border*)border->duplicate()); if (backgroundImage) obj->setBackgroundImage( dynamic_cast(backgroundImage->getThis())); if (vertikalScrollBar) { obj->setVerticalClickScroll(vertikalScrollBar->getClickScroll()); obj->setVerticalScrollPos(vertikalScrollBar->getScroll()); obj->setVerticalScrollColor( vertikalScrollBar->getColor(), vertikalScrollBar->getBgColor()); } if (horizontalScrollBar) { obj->setHorizontalClickScroll(horizontalScrollBar->getClickScroll()); obj->setHorizontalScrollPos(horizontalScrollBar->getScroll()); obj->setHorizontalScrollColor( horizontalScrollBar->getColor(), horizontalScrollBar->getBgColor()); } return obj; }