#include "KEDModel2DEditor.h"
#include <Rahmen.h>
#include <MausEreignis.h>
#include <Text.h>
#include <Schrift.h>
#include <Scroll.h>
#include <Globals.h>
#include <TastaturEreignis.h>
#include "../../../../Global/Initialisierung.h"
#include "../../../../Global/Variablen.h"

using namespace Model2DEditor;

// Inhalt der VertexData Klasse aus KEDModel2DEditor.h
// Konstruktor
VertexData::VertexData( Vec2< float > v, Punkt t )
{
    vertex = v;
    textur = t;
    selected = 0;
    sichtbar = 1;
    ref = 1;
}

// nicht constant
void VertexData::nachLinks( float num )
{
    if( selected )
        vertex.x -= num;
}

void VertexData::nachOben( float num )
{
    if( selected )
        vertex.y -= num;
}

void VertexData::saveTextur( Punkt tPos )
{
    textur = (Punkt)vertex - tPos;
}

void VertexData::select( Punkt p1, Punkt p2 )
{
    selected |= vertex.istInRegion( p1, p2 ) && sichtbar;
}

void VertexData::deSelect()
{
    selected = 0;
}

void VertexData::setAuswahl( bool ausw )
{
    selected = ausw;
}

void VertexData::setSichtbar( bool s )
{
    sichtbar = s;
    selected &= sichtbar;
}

// constant
bool VertexData::istSichtbar() const
{
    return sichtbar;
}

bool VertexData::istAusgewählt() const
{
    return selected;
}

Vec2< float > VertexData::getPos() const
{
    return vertex;
}

Punkt VertexData::getTPos() const
{
    return textur;
}

// Reference Counting
VertexData *VertexData::getThis()
{
    ref++;
    return this;
}

VertexData *VertexData::release()
{
    ref--;
    if( !ref )
        delete this;
    return 0;
}


// Inhalt der PolygonData Klasse aus KEDModel2DEditor.h
// Konstruktor
PolygonData::PolygonData( Polygon2D &pg )
{
    vd = new RCArray< VertexData >();
    sichtbar = 1;
    ref = 1;
    int anz = pg.vertex->getEintragAnzahl();
    for( int i = 0; i < anz; i++ )
    {
        Vec2< float > v( 0, 0 );
        Punkt t( 0, 0 );
        if( pg.vertex->hat( i ) )
            v = pg.vertex->get( i );
        if( pg.tKordinaten && pg.tKordinaten->hat( i ) )
            t = pg.tKordinaten->get( i );
        vd->add( new VertexData( v, t ) );
    }
}

// Destruktor
PolygonData::~PolygonData()
{
    vd->release();
}

// nicht constant
void PolygonData::addVertex( Vec2< float >v, Punkt t )
{
    vd->add( new VertexData( v, t ) );
}

void PolygonData::removeVertex( int num )
{
    vd->lösche( num );
}

void PolygonData::nachLinks( float num )
{
    for( auto *i = &vd->getArray(); i && i->set; i = i->next )
        i->var->nachLinks( num );
}

void PolygonData::nachOben( float num )
{
    for( auto *i = &vd->getArray(); i && i->set; i = i->next )
        i->var->nachOben( num );
}

void PolygonData::saveTextur( Punkt tPos )
{
    for( auto *i = &vd->getArray(); i && i->set; i = i->next )
        i->var->saveTextur( tPos );
}

void PolygonData::select( Punkt p1, Punkt p2 )
{
    for( auto *i = &vd->getArray(); i && i->set; i = i->next )
        i->var->select( p1, p2 );
}

void PolygonData::deSelect()
{
    for( auto *i = &vd->getArray(); i && i->set; i = i->next )
        i->var->deSelect();
}

void PolygonData::setSichtbar( bool s )
{
    sichtbar = s;
}

// constant
bool PolygonData::istSichtbar() const
{
    return sichtbar;
}

VertexData *PolygonData::zVertex( int num ) const
{
    return vd->z( num );
}

int PolygonData::getVertexAnzahl() const
{
    return vd->getEintragAnzahl();
}

void PolygonData::getM2( Polygon2D &pd, bool textur ) const
{
    int anz = vd->getEintragAnzahl();
    if( !pd.vertex )
        pd.vertex = new Array< Vertex >();
    if( !pd.tKordinaten )
        pd.tKordinaten = new Array< Punkt >();
    for( int i = 0; i < anz; i++ )
    {
        pd.vertex->add( this->vd->z( i )->getPos() );
        if( textur )
            pd.tKordinaten->add( this->vd->z( i )->getTPos() );
    }
}

// Reference Counting
PolygonData *PolygonData::getThis()
{
    ref++;
    return this;
}

PolygonData *PolygonData::release()
{
    ref--;
    if( !ref )
        delete this;
    return 0;
}


// Inhalt der Data Klasse aus KEDModel2DEditor.h
// Konstruktor
Data::Data( Model2DData *mdl )
{
    pd = new RCArray< PolygonData >();
    tPos.x = 0;
    tPos.y = 0;
    textur = 0;
    rTextur = 0;
    sp = -1;
    ref = 1;
    int anz = ( mdl && mdl->polygons ) ? mdl->polygons->getEintragAnzahl() : 0;
    for( int i = 0; i < anz; i++ )
    {
        if( mdl->polygons->hat( i ) )
        {
            pd->add( new PolygonData( mdl->polygons->get( i ) ) );
            if( !tPos.x && !tPos.y )
            {
                if( mdl->polygons->get( i ).tKordinaten && mdl->polygons->get( i ).vertex
                    && mdl->polygons->get( i ).tKordinaten->hat( 0 ) && mdl->polygons->get( i ).vertex->hat( 0 ) )
                {
                    Punkt p = (Punkt)mdl->polygons->get( i ).vertex->get( 0 );
                    Punkt tp = mdl->polygons->get( i ).tKordinaten->get( 0 );
                    tPos = p - tp;
                }
            }
        }
    }
    if( mdl )
        mdl->release();
}

// Destruktor
Data::~Data()
{
    pd->release();
    if( textur )
        textur->release();
}

// nicht constant
void Data::addPolygon()
{
    Polygon2D p;
    p.vertex = new Array< Vertex >();
    pd->add( new PolygonData( p ) );
    p.vertex->release();
}

void Data::removePolygon( int num )
{
    pd->lösche( num );
    if( sp == num )
        sp = -1;
}

void Data::selectPolygon( int num )
{
    sp = num;
}

void Data::nachLinks( float num )
{
    for( auto *i = &pd->getArray(); i && i->set; i = i->next )
        i->var->nachLinks( num );
}

void Data::nachOben( float num )
{
    for( auto *i = &pd->getArray(); i && i->set; i = i->next )
        i->var->nachOben( num );
}

void Data::tNachLinks( int num )
{
    if( !rTextur )
        return;
    tPos.x -= num;
}

void Data::tNachOben( int num )
{
    if( !rTextur )
        return;
    tPos.y -= num;
}

void Data::setRTextur( bool rt )
{
    rTextur = rt;
    if( rt && !textur )
    {
        textur = new Bild();
        textur->neuBild( 500, 500, 0xFF505000 );
    }
}

void Data::saveTextur()
{
    if( !rTextur )
        return;
    for( auto *i = &pd->getArray(); i && i->set; i = i->next )
        i->var->saveTextur( tPos );
}

void Data::setTextur( Bild *t )
{
    if( textur )
        textur->release();
    textur = t;
}

void Data::select( Punkt p1, Punkt p2 )
{
    for( auto *i = &pd->getArray(); i && i->set; i = i->next )
        i->var->select( p1, p2 );
}

void Data::deSelect()
{
    for( auto *i = &pd->getArray(); i && i->set; i = i->next )
        i->var->deSelect();
}

// constant
PolygonData *Data::zPolygon( int num ) const
{
    return pd->z( num );
}

int Data::getPolygonAnzahl() const
{
    return pd->getEintragAnzahl();
}

int Data::getSelectedPolygon() const
{
    return sp;
}

Model2DData *Data::getM2() const
{
    int anz = pd->getEintragAnzahl();
    Array< Polygon2D > *polygons = new Array< Polygon2D >();
    for( int i = 0; i < anz; i++ )
    {
        Polygon2D pd = { 0, 0 };
        this->pd->z( i )->getM2( pd, rTextur );
        polygons->add( pd );
    }
    Model2DData *ret = new Model2DData();
    ret->erstelleModell( polygons );
    return ret;
}

Bild *Data::zTextur() const
{
    return rTextur ? textur : 0;
}

Punkt Data::getTPos() const
{
    return tPos;
}

// Reference Counting
Data *Data::getThis()
{
    ref++;
    return this;
}

Data *Data::release()
{
    ref--;
    if( !ref )
        delete this;
    return 0;
}


// Inhalt der EditorListe Klasse aus KEDModel2DEditor.h
// Konstruktor
EditorListe::EditorListe( Schrift *zSchrift )
{
    ram = new LRahmen();
    ram->setRamenBreite( 1 );
    ram->setFarbe( 0xFFFFFFFF );
    ram->setGröße( 150, 480 );
    ram->setPosition( 720, 10 );
    scroll = new VScrollBar();
    schrift = zSchrift->getThis();
    data = 0;
    ref = 1;
}

// Destruktor
EditorListe::~EditorListe()
{
    ram->release();
    scroll->release();
    if( data )
        data->release();
    schrift->release();
}

// nicht constant
void EditorListe::setDataZ( Data *d )
{
    if( data )
        data->release();
    data = d;
}

void EditorListe::doMausEreignis( MausEreignis &me )
{
    me.mx -= ram->getX();
    me.my -= ram->getY();
    if( me.mx < 0 || me.my < 0 || me.mx > ram->getBreite() || me.my > ram->getHöhe() )
    {
        me.mx += ram->getX();
        me.my += ram->getY();
        return;
    }
    scroll->doMausMessage( ram->getBreite() - 17, 1, 15, ram->getHöhe() - 2, me );
    rend |= scroll->getRend();
    if( me.id == ME_RLinks )
    {
        int pAnz = data->getPolygonAnzahl();
        int y = -scroll->getScrollData()->anzeigeBeginn;
        for( int i = 0; i < pAnz; i++ )
        {
            if( me.mx > 0 && me.my > y && me.mx < 20 && me.my < y + 20 )
            { // Ein und Ausklappen
                if( !ausgeklappt.hat( i ) )
                    ausgeklappt.set( 0, i );
                ausgeklappt.set( !ausgeklappt.get( i ), i );
                rend = 1;
            }
            else if( me.mx > 115 && me.my > y + 1 && me.mx < 132 && me.my < y + 19 )
            { // Löschen
                data->removePolygon( i );
                rend = 1;
                break;
            }
            else if( me.mx > 0 && me.my > y && me.mx < 133 && me.my < y + 20 )
            { // Polygon Auswählen und Abwählen
                if( data->getSelectedPolygon() != i )
                    data->selectPolygon( i );
                else
                    data->selectPolygon( -1 );
                rend = 1;
            }
            PolygonData *pd = data->zPolygon( i );
            if( pd && ausgeklappt.hat( i ) && ausgeklappt.get( i ) )
            {
                int vAnz = pd->getVertexAnzahl();
                for( int j = 0; j < vAnz; j++ )
                {
                    y += 20;
                    if( me.mx > 115 && me.my > y + 1 && me.mx < 132 && me.my < y + 19 )
                    { // Löschen
                        pd->removeVertex( j );
                        rend = 1;
                    }
                    else if( me.mx > 95 && me.my > y + 5 && me.mx < 105 && me.my < y + 15 )
                    { // Sichtbar und Unsichtbar
                        pd->zVertex( j )->setSichtbar( !pd->zVertex( j )->istSichtbar() );
                        rend = 1;
                    }
                    else if( me.my > y && me.my < y + 20 && me.mx > 0 && me.mx < 133 )
                    { // Auswählen und Abwählen
                        pd->zVertex( j )->setAuswahl( !pd->zVertex( j )->istAusgewählt() );
                        rend = 1;
                    }
                }
            }
            y += 20;
        }
    }
    me.verarbeitet = 1;
    me.mx += ram->getX();
    me.my += ram->getY();
}

bool EditorListe::tick( double zeit )
{
    bool ret = rend;
    rend = 0;
    return ret;
}

void EditorListe::render( Bild &zRObj )
{
    ram->render( zRObj );
    if( !zRObj.setDrawOptions( ram->getPosition() + Punkt( 1, 1 ), ram->getGröße() - Punkt( 2, 2 ) ) )
        return;
    scroll->render( ram->getBreite() - 17, 1, 15, ram->getHöhe() - 2, zRObj );
    int pAnz = data->getPolygonAnzahl();
    int y = -scroll->getScrollData()->anzeigeBeginn;
    int maxH = 0;
    schrift->lock();
    schrift->setSchriftGröße( 12 );
    Text name;
    for( int i = 0; i < pAnz; i++ )
    {
        if( data->getSelectedPolygon() == i )
            zRObj.füllRegion( 0, y, 133, 20, 0xFF002000 );
        name = "Polygon ";
        name += i;
        schrift->setDrawPosition( 20, y + 4 );
        schrift->renderText( &name, zRObj, 0xFFFFFFFF );
        zRObj.drawLinie( Punkt( 115, y + 1 ), Punkt( 132, y + 18 ), 0xFFFF0000 );
        zRObj.drawLinie( Punkt( 132, y + 1 ), Punkt( 115, y + 18 ), 0xFFFF0000 );
        if( ausgeklappt.hat( i ) && ausgeklappt.get( i ) )
        {
            zRObj.drawDreieck( Punkt( 10, 4 + y ), Punkt( 4, 16 + y ), Punkt( 16, 16 + y ), 0xFFFFFFFF );
            PolygonData *pd = data->zPolygon( i );
            if( pd )
            {
                int vAnz = pd->getVertexAnzahl();
                for( int j = 0; j < vAnz; j++ )
                {
                    maxH += 20;
                    y += 20;
                    if( pd->zVertex( j )->istAusgewählt() )
                        zRObj.füllRegion( 0, y, 133, 20, 0xFF101010 );
                    name = "  Vertex ";
                    name += j;
                    schrift->setDrawPosition( 20, y + 4 );
                    schrift->renderText( &name, zRObj, 0xFFFFFFFF );
                    zRObj.drawLinie( Punkt( 115, y + 1 ), Punkt( 132, y + 18 ), 0xFFFF0000 );
                    zRObj.drawLinie( Punkt( 132, y + 1 ), Punkt( 115, y + 18 ), 0xFFFF0000 );
                    if( pd->zVertex( j )->istSichtbar() )
                    {
                        zRObj.drawKreis( 100, y + 10, 5, 0xFFFFFFFF );
                        zRObj.drawKreis( 100, y + 10, 1, 0xFFFFFFFF );
                    }
                    else
                    {
                        zRObj.drawKreis( 100, y + 10, 5, 0xFF505050 );
                        zRObj.drawKreis( 100, y + 10, 1, 0xFF505050 );
                    }
                }
            }
        }
        else
            zRObj.drawDreieck( Punkt( 10, 16 + y ), Punkt( 4, 4 + y ), Punkt( 16, 4 + y ), 0xFFFFFFFF );
        maxH += 20;
        y += 20;
    }
    schrift->unlock();
    scroll->update( maxH, ram->getHöhe() - 2 );
    zRObj.releaseDrawOptions();
}

// Reference Counting
EditorListe *EditorListe::getThis()
{
    ref++;
    return this;
}

EditorListe *EditorListe::release()
{
    ref--;
    if( !ref )
        delete this;
    return 0;
}


// Inhalt der Editor2D Klasse aus KEDModel2DEditor.h
// Konstruktor
Editor2D::Editor2D( Schrift *zSchrift )
{
    pos.x = 10;
    pos.y = 10;
    offs.x = -350;
    offs.y = -250;
    mausPos.x = 0;
    mausPos.y = 0;
    data = 0;
    ram = new LRahmen();
    ram->setFarbe( 0xFFFFFFFF );
    ram->setRamenBreite( 1 );
    ram->setGröße( 700, 480 );
    select = new LRahmen();
    select->setFarbe( 0xFF5050FF );
    select->setRamenBreite( 1 );
    schrift = zSchrift->getThis();
    addV = Vertex( 0, 0 );
    mausIn = 0;
    größe = 1;
    ref = 1;
}

// Destruktor
Editor2D::~Editor2D()
{
    ram->release();
    select->release();
    schrift->release();
    if( data )
        data->release();
}

// nicht constant
void Editor2D::setDataZ( Data *d )
{
    if( data )
        data->release();
    data = d;
}

void Editor2D::doMausEreignis( MausEreignis &me )
{
    me.mx -= pos.x;
    me.my -= pos.y;
    if( me.mx < 0 || me.my < 0 || me.mx > ram->getBreite() || me.my > ram->getHöhe() )
    {
        me.mx += pos.x;
        me.my += pos.y;
        mausIn = 0;
        return;
    }
    mausIn = 1;
    rend = 1;
    addV = Vertex( (float)me.mx, (float)me.my ) / größe + offs;
    if( me.id == ME_UScroll )
        größe += 0.01f;
    if( me.id == ME_DScroll )
        größe -= 0.01f;
    if( me.id == ME_PLinks )
    {
        select->setPosition( me.mx, me.my );
        select->setGröße( 0, 0 );
    }
    if( me.id == ME_PRechts || me.id == ME_PMitte )
    {
        mausPos.x = me.mx;
        mausPos.y = me.my;
    }
    if( me.id == ME_Bewegung )
    {
        if( getMausStand( M_Links ) )
        {
            select->setGröße( me.mx - select->getX(), me.my - select->getY() );
        }
        if( getMausStand( M_Rechts ) )
        {
            data->nachLinks( ( mausPos.x - me.mx ) / größe );
            data->nachOben( ( mausPos.y - me.my ) / größe );
            mausPos.x = me.mx;
            mausPos.y = me.my;
        }
        if( getMausStand( M_Mitte ) )
        {
            data->tNachLinks( (int)( ( mausPos.x - me.mx ) / größe ) );
            data->tNachOben( (int)( ( mausPos.y - me.my ) / größe ) );
            mausPos.x = me.mx;
            mausPos.y = me.my;
        }
    }
    if( me.id == ME_RLinks )
    {
        if( !getTastenStand( T_Shift ) )
            data->deSelect();
        data->select( ( Vec2<float> )select->getPosition() / größe + offs, ( Vec2<float> )( select->getPosition() + select->getGröße() ) / größe + offs );
        select->setGröße( 0, 0 );
        select->setPosition( 0, 0 );
    }
    if( me.id == ME_RRechts )
    {
        mausPos.x = 0;
        mausPos.y = 0;
    }
    me.verarbeitet = 1;
    me.mx += pos.x;
    me.my += pos.y;
}

void Editor2D::doTastaturEreignis( TastaturEreignis &te )
{
    if( te.id == TE_Release && te.taste == T_Enter && mausIn )
    {
        PolygonData *pd = data->zPolygon( data->getSelectedPolygon() );
        if( pd )
        {
            pd->addVertex( addV, Punkt( 0, 0 ) );
            rend = 1;
        }
    }
    if( te.id == TE_Release && te.taste == T_Einfg )
    {
        data->addPolygon();
        rend = 1;
    }
    if( te.id == T_Oben )
        offs.y -= 2;
    if( te.id == T_Links )
        offs.x -= 2;
    if( te.id == T_Unten )
        offs.y += 2;
    if( te.id == T_Rechts )
        offs.x += 2;
    if( te.id == T_Oben || te.id == T_Links || te.id == T_Unten || te.id == T_Rechts )
        rend = 1;
}

bool Editor2D::tick( double zeit )
{
    if( mausIn )
    {
        if( getTastenStand( T_Links ) )
        {
            offs.x--;
            rend = 1;
        }
        if( getTastenStand( T_Rechts ) )
        {
            offs.x++;
            rend = 1;
        }
        if( getTastenStand( T_Oben ) )
        {
            offs.y--;
            rend = 1;
        }
        if( getTastenStand( T_Unten ) )
        {
            offs.y++;
            rend = 1;
        }
        if( getTastenStand( 'w' ) )
        {
            data->tNachOben( 1 );
            rend = 1;
        }
        if( getTastenStand( 'a' ) )
        {
            data->tNachLinks( 1 );
            rend = 1;
        }
        if( getTastenStand( 's' ) )
        {
            data->tNachOben( -1 );
            rend = 1;
        }
        if( getTastenStand( 'd' ) )
        {
            data->tNachLinks( -1 );
            rend = 1;
        }
    }
    bool ret = rend;
    rend = 0;
    return ret;
}

void Editor2D::render( Bild &zRObj )
{
    if( !zRObj.setDrawOptions( pos, ram->getGröße() ) )
        return;
    ram->render( zRObj );
    if( !zRObj.setDrawOptions( 1, 1, ram->getBreite() - 2, ram->getHöhe() - 2 ) )
    {
        zRObj.releaseDrawOptions();
        return;
    }
    if( data->zTextur() )
    {
        Punkt tPos = data->getTPos();
        zRObj.alphaBildSkall( (int)( ( tPos.x - offs.x ) * größe ), (int)( ( tPos.y - offs.y ) * größe ),
                              (int)( data->zTextur()->getBreite() * größe ), (int)( data->zTextur()->getHöhe() * größe ), *data->zTextur() );
    }
    // Raster mahlen
    int xanz = (int)( ram->getBreite() / ( 50 * größe ) );
    int yanz = (int)( ram->getHöhe() / ( 50 * größe ) );
    int xStart = ( 50 - abs( offs.x ) % 50 );
    if( offs.x < 0 )
        xStart = -offs.x % 50;
    if( offs.x == 0 )
        xStart = 0;
    int yStart = ( 50 - abs( offs.y ) % 50 );
    if( offs.y < 0 )
        yStart = -offs.y % 50;
    if( offs.y == 0 )
        yStart = 0;
    for( float x = xStart * größe, y = yStart * größe; !( x > ram->getBreite() && y > ram->getHöhe() ); x += 50 * größe, y += 50 * größe )
    {
        zRObj.drawLinieH( 0, (int)y, ram->getBreite(), 0xFF505050 );
        zRObj.drawLinieV( (int)x, 0, ram->getHöhe() , 0xFF505050 );
    }
    Text xPos = "";
    xPos = offs.x + (int)( xStart + 50 * ( xanz / 2 ) );
    schrift->setDrawPosition( (int)( xStart * größe + 50 * größe * ( xanz / 2 ) ), 0 );
    schrift->renderText( &xPos, zRObj, 0xFF505050 );
    xPos = offs.y + (int)( yStart + 50 * ( yanz / 2 ) );
    schrift->setDrawPosition( 0, (int)( yStart * größe + 50 * größe * ( yanz / 2 ) ) );
    schrift->renderText( &xPos, zRObj, 0xFF505050 );
    // Model mahlen
    int pAnz = data->getPolygonAnzahl();
    for( int i = 0; i < pAnz; i++ )
    {
        PolygonData *p = data->zPolygon( i );
        if( !p->istSichtbar() )
            continue;
        if( data->getSelectedPolygon() == i && mausIn )
        {
            int vAnz = p->getVertexAnzahl();
            VertexData tmp = VertexData( addV, Punkt() );
            VertexData *l = p->zVertex( vAnz - 1 );
            for( int j = -1; j < vAnz && vAnz > 0; j++ )
            {
                VertexData *v = j < 0 ? &tmp : p->zVertex( j );
                if( l && v )
                {
                    if( l->istSichtbar() && v->istSichtbar() )
                        zRObj.drawLinie( ( ( l->getPos() - offs ) * größe ), ( ( v->getPos() - offs ) * größe ), 0xFFA0A0A0 );
                    else
                        zRObj.drawLinie( ( ( l->getPos() - offs ) * größe ), ( ( v->getPos() - offs ) * größe ), 0xFF606060 );
                }
                if( !l->istSichtbar() )
                {
                    l = v;
                    continue;
                }
                if( j == 0 )
                    zRObj.füllRegion( (int)( ( l->getPos().x - offs.x ) * größe ) - 5, (int)( ( l->getPos().y - offs.y ) * größe ) - 5, 10, 10, 0xFF50FF50 );
                else
                {
                    if( !l->istAusgewählt() )
                        zRObj.füllRegion( (int)( ( l->getPos().x - offs.x ) * größe ) - 5, (int)( ( l->getPos().y - offs.y ) * größe ) - 5, 10, 10, 0xFF5050FF );
                    else
                        zRObj.füllRegion( (int)( ( l->getPos().x - offs.x ) * größe ) - 5, (int)( ( l->getPos().y - offs.y ) * größe ) - 5, 10, 10, 0xFFFF5050 );
                }
                l = v;
            }
        }
        else
        {
            int vAnz = p->getVertexAnzahl();
            VertexData *l = p->zVertex( vAnz - 1 );
            for( int j = 0; j < vAnz; j++ )
            {
                VertexData *v = p->zVertex( j );
                if( l && v )
                {
                    if( l->istSichtbar() && v->istSichtbar() )
                        zRObj.drawLinie( ( ( l->getPos() - offs ) * größe ), ( ( v->getPos() - offs ) * größe ), 0xFFA0A0A0 );
                    else
                        zRObj.drawLinie( ( ( l->getPos() - offs ) * größe ), ( ( v->getPos() - offs ) * größe ), 0xFF606060 );
                }
                if( !l->istSichtbar() )
                {
                    l = v;
                    continue;
                }
                if( !l->istAusgewählt() )
                    zRObj.füllRegion( (int)( ( l->getPos().x - offs.x ) * größe ) - 5, (int)( ( l->getPos().y - offs.y ) * größe ) - 5, 10, 10, 0xFF5050FF );
                else
                    zRObj.füllRegion( (int)( ( l->getPos().x - offs.x ) * größe ) - 5, (int)( ( l->getPos().y - offs.y ) * größe ) - 5, 10, 10, 0xFFFF5050 );
                l = v;
            }
        }
    }
    select->render( zRObj );
    zRObj.releaseDrawOptions();
    zRObj.releaseDrawOptions();
}

// Reference Counting
Editor2D *Editor2D::getThis()
{
    ref++;
    return this;
}

Editor2D *Editor2D::release()
{
    ref--;
    if( !ref )
        delete this;
    return 0;
}


// Inhalt der GUI Klasse aus KEDModel2DEditor.h
// Konstruktor
GUI::GUI( Schrift *zSchrift )
{
    speichern = initKnopf( 660, 500, 100, 20, zSchrift, Knopf::Style::Sichtbar, "Speichern" );
    abbrechen = initKnopf( 770, 500, 100, 20, zSchrift, Knopf::Style::Sichtbar, "Abbrehen" );
    textur = initKontrollKnopf( 10, 500, 100, 20, zSchrift, KontrollKnopf::Style::Normal, "Textur" );
    texturVerknüpfen = initKnopf( 120, 500, 100, 20, zSchrift, Knopf::Style::Sichtbar, "Textur Speichern" );
    texturLaden = initKnopf( 230, 500, 100, 20, zSchrift, Knopf::Style::Sichtbar, "Textur Laden" );
    data = new Data( 0 );
    editor = new Editor2D( zSchrift );
    editor->setDataZ( data->getThis() );
    liste = new EditorListe( zSchrift );
    liste->setDataZ( data->getThis() );
    importDialog = 0;
    aktion = 0;
    alpha = 0;
    sichtbar = 0;
    ref = 1;
}

// Destruktor
GUI::~GUI()
{
    editor->release();
    liste->release();
    speichern->release();
    abbrechen->release();
    data->release();
    textur->release();
    texturVerknüpfen->release();
    texturLaden->release();
    if( importDialog )
        importDialog->release();
}

// nicht constant
void GUI::setSichtbar( bool s )
{
    sichtbar = s;
}

void GUI::setModel( Model2DData *data )
{
    if( this->data )
        this->data->release();
    this->data = new Data( data );
    editor->setDataZ( this->data->getThis() );
    liste->setDataZ( this->data->getThis() );
}

void GUI::doMausEreignis( MausEreignis &me )
{
    if( !sichtbar )
        return;
    editor->doMausEreignis( me );
    liste->doMausEreignis( me );
    bool vera = me.verarbeitet;
    speichern->doMausEreignis( me );
    if( me.id == ME_RLinks && me.verarbeitet && !vera )
    {
        aktion = 1;
    }
    vera = me.verarbeitet;
    abbrechen->doMausEreignis( me );
    if( me.id == ME_RLinks && me.verarbeitet && !vera )
    {
        aktion = 2;
    }
    vera = me.verarbeitet;
    textur->doMausEreignis( me );
    data->setRTextur( textur->hatStyle( KontrollKnopf::Style::Selected ) );
    vera = me.verarbeitet;
    texturVerknüpfen->doMausEreignis( me );
    if( !vera && me.verarbeitet && me.id == ME_RLinks )
        data->saveTextur();
    vera = me.verarbeitet;
    texturLaden->doMausEreignis( me );
    if( !vera && me.verarbeitet && me.id == ME_RLinks )
    {
        if( !importDialog )
        {
            importDialog = new DateiDialogTh();
            importDialog->setÖffnen( 1 );
            importDialog->setDateiTypAuswahl( 4 );
            importDialog->addDateiTyp( "JPEG-Bild", "*.jpg;*.jpeg;*.jpe" );
            importDialog->addDateiTyp( "GIF-Bild", "*.gif" );
            importDialog->addDateiTyp( "PNG-Bild", "*.png" );
            importDialog->addDateiTyp( "Alle Dateien", "*.*" );
            importDialog->start();
        }
    }
}

void GUI::doTastaturEreignis( TastaturEreignis &te )
{
    if( !sichtbar )
        return;
    editor->doTastaturEreignis( te );
}

bool GUI::tick( double zeit )
{
    if( importDialog )
    {
        if( !importDialog->läuft() )
        {
            Text *importPfad = importDialog->getPfad();
            importDialog = importDialog->release();
            if( sichtbar && importPfad )
            {
                importPfad->ersetzen( "\\", "/" );
                Text *err = new Text();
                Bild *b = ladeBild( importPfad->getText(), err );
                if( !b )
                    nachLogin->zNachrichtenListe()->addNachricht( new Text( "Fehler" ), err, new Text( "Ok" ) );
                else
                    data->setTextur( b );
                err->release();
            }
            importPfad->release();
        }
    }
    rend |= speichern->tick( zeit );
    rend |= abbrechen->tick( zeit );
    if( sichtbar && alpha != 255 )
    {
        if( alpha + zeit * 200 > 255 )
            alpha = 255;
        else
            alpha += (unsigned char)(zeit * 200);
        rend = 1;
    }
    else if( !sichtbar && alpha )
    {
        if( alpha - zeit * 200 < 0 )
            alpha = 0;
        else
            alpha -= (unsigned char)( zeit * 200 );
        rend = 1;
    }
    if( sichtbar )
    {
        rend |= editor->tick( zeit );
        rend |= liste->tick( zeit );
        rend |= speichern->tick( zeit );
        rend |= textur->tick( zeit );
        rend |= texturVerknüpfen->tick( zeit );
        rend |= texturLaden->tick( zeit );
    }
    bool ret = rend;
    rend = 0;
    return ret;
}

void GUI::render( Bild &zRObj )
{
    zRObj.setAlpha( alpha );
    editor->render( zRObj );
    liste->render( zRObj );
    speichern->render( zRObj );
    abbrechen->render( zRObj );
    textur->render( zRObj );
    texturVerknüpfen->render( zRObj );
    texturLaden->render( zRObj );
    zRObj.releaseAlpha();
}

int GUI::getAktion()
{
    int ret = aktion;
    aktion = 0;
    return ret;
}

// const
Model2DData *GUI::getM2Data() const
{
    return data->getM2();
}

// Reference Counting
GUI *GUI::getThis()
{
    ref++;
    return 0;
}

GUI *GUI::release()
{
    ref--;
    if( !ref )
        delete this;
    return 0;
}