#include "Diagramm.h"
#include "Text.h"
#include "AlphaFeld.h"
#include "Bild.h"
#include "Rahmen.h"
#include "Schrift.h"
#include "Scroll.h"
#include "MausEreignis.h"
#include "ToolTip.h"
#include <math.h>

using namespace Framework;

// Inhalt der SLDiag Klasse aus Diagramm.h
// Konstruktor 
SLDiag::SLDiag()
    : ZeichnungHintergrund(),
    gF( 0xFF000000 ),
    lFarbe( new Array< int >() ),
    lName( new RCArray< Text >() ),
    ph( new RCArray< Array< int > >() ),
    pb( new RCArray< Array< int > >() ),
    lastValue( new Array< int >() ),
    textRd( 0 ),
    gitterGr( 0, 0 ),
    lines( 0 )
{
    style = 0;
}

// Destruktor 
SLDiag::~SLDiag()
{
    lFarbe->release();
    lName->release();
    ph->release();
    pb->release();
    lastValue->release();
    if( textRd )
        textRd->release();
}

// nicht constant 
void SLDiag::setTextRendererZ( TextRenderer *textRd )
{
    if( this->textRd )
        this->textRd->release();
    this->textRd = textRd;
}

void SLDiag::setSchriftZ( Schrift *schrift ) // setzt die Schrift
{
    if( !this->textRd )
        textRd = new TextRenderer( schrift );
    else
        textRd->setSchriftZ( schrift );
    rend = 1;
}

void SLDiag::setGSize( Punkt &gr ) // setzt die Größe des Gitters
{
    gitterGr = gr;
    rend = 1;
}

void SLDiag::setGFarbe( int f ) // setzt die Gitter Farbe
{
    gF = f;
    rend = 1;
}

void SLDiag::addLinie( const char *name ) // fügt eine Linie hinzu
{
    addLinie( new Text( name ) );
    rend = 1;
}

void SLDiag::addLinie( Text *txt )
{
    lFarbe->add( 0xFFFFFFFF, lines );
    lName->add( txt, lines );
    ph->add( new Array< int >(), lines );
    pb->add( new Array< int >(), lines );
    int rbr = rahmen && hatStyle( Style::Rahmen ) ? rahmen->getRBreite() : 0;
    pb->z( lines )->set( gr.x - rbr * 2, 0 );
    ++lines;
    rend = 1;
}

void SLDiag::setLFarbe( int lNum, int f ) // setzt die Linienfarbe
{
    lFarbe->set( f, lNum );
    rend = 1;
}

void SLDiag::addPunkt( int lNum, int x, int h ) // fügt einen Punkt hinzu
{
    Array< int > *ph_tmp = ph->z( lNum );
    Array< int > *pb_tmp = pb->z( lNum );
    if( ph_tmp && pb_tmp )
    {
        int i = pb_tmp->get( 0 );
        i -= x;
        if( i >= 0 )
            pb_tmp->set( i, 0 );
        while( i < 0 )
        {
            ph_tmp->remove( 0 );
            pb_tmp->remove( 0 );
            if( !pb_tmp->getEintragAnzahl() || !ph_tmp->getEintragAnzahl() )
                break;
            int ii = -i;
            i = pb_tmp->get( 0 );
            i -= ii;
            pb_tmp->set( i, 0 );
        }
        pb_tmp->add( x );
        ph_tmp->add( h );
        lastValue->set( h, lNum );
    }
    rend = 1;
}

void SLDiag::removeLinie( int lNum ) // entfernt eine Linie
{
    lFarbe->remove( lNum );
    lName->remove( lNum );
    ph->remove( lNum );
    pb->remove( lNum );
    --lines;
    rend = 1;
}

void SLDiag::render( Bild &zRObj ) // zeichnet nach zRObj
{
    if( hatStyle( Style::Sichtbar ) )
    {
        lockZeichnung();
        removeStyle( Style::VScroll | Style::HScroll );
        ZeichnungHintergrund::render( zRObj );
        if( !zRObj.setDrawOptions( innenPosition, innenSize ) )
        {
            unlockZeichnung();
            return;
        }
        int hv = getHighestValue();
        hv = hv ? hv : 1;
        double yFaktor = innenSize.y / hv;
        if( hatStyle( Style::Gitter ) )
        {
            double ghi = gitterGr.y * yFaktor;
            int yo = innenSize.y - 1;
            int bo = innenSize.x, ho = innenSize.y;
            int maxBr = (int)( (double)innenSize.x / gitterGr.x + 0.5 );
            int maxHi = ghi ? (int)( innenSize.y / ghi + 0.5 ) : 0;
            if( hatStyle( Style::HAlpha ) )
            {
                for( int i = 0; i < maxBr; ++i )
                    zRObj.drawLinieVAlpha( gitterGr.x * i, 0, ho, gF );
                for( int i = 0; i < maxHi; ++i )
                    zRObj.drawLinieHAlpha( 0, (int)( yo - ghi * i + 0.5 ), bo, gF );
            }
            else
            {
                for( int i = 0; i < maxBr; ++i )
                    zRObj.drawLinieV( gitterGr.x * i, 0, ho, gF );
                for( int i = 0; i < maxHi; ++i )
                    zRObj.drawLinieH( 0, (int)( yo - ghi * i + 0.5 ), bo, gF );
            }
        }
        for( int i = 0; i < lines; ++i )
        {
            int f_tmp = lFarbe->hat( i ) ? lFarbe->get( i ) : 0;
            Text *n_tmp = lName->z( i );
            Array< int > *ph_tmp = ph->z( i );
            Array< int > *pb_tmp = pb->z( i );
            if( hatStyle( Style::LinienName ) && textRd && n_tmp )
            {
                textRd->setSchriftSize( 12 );
                Text rtxt = n_tmp->getText();
                rtxt += ": ";
                rtxt += lastValue->get( i );
                textRd->renderText( 5, 5 + 15 * i, rtxt, zRObj, f_tmp );
            }
            if( ph_tmp && pb_tmp )
            {
                int lastX = 0;
                int lastY = innenSize.y - 1;
                int ph_anz = ph_tmp->getEintragAnzahl();
                int pb_anz = pb_tmp->getEintragAnzahl();
                for( int ii = 0; ii < ph_anz && ii < pb_anz; ++ii )
                {
                    if( !ph_tmp || !pb_tmp )
                        break;
                    int xpos = lastX + pb_tmp->get( ii );
                    int ypos = innenSize.y - (int)( ph_tmp->get( ii ) * yFaktor + 0.5 ) - 1;
                    if( ypos == -1 )
                        ++ypos;
                    if( ypos < 0 || xpos < 0 )
                        break;
                    if( hatStyle( Style::HAlpha ) )
                        zRObj.drawLinieAlpha( Punkt( lastX, lastY ), Punkt( xpos, ypos ), f_tmp );
                    else
                        zRObj.drawLinie( Punkt( lastX, lastY ), Punkt( xpos, ypos ), f_tmp );
                    lastX = xpos;
                    lastY = ypos;
                }
            }
        }
        zRObj.releaseDrawOptions();
        unlockZeichnung();
    }
}

// constant
Schrift *SLDiag::getSchrift() const // gibt die Schrift zurück
{
    if( textRd )
        return textRd->getSchrift();
    return 0;
}

Schrift *SLDiag::zSchrift() const
{
    return textRd ? textRd->zSchrift() : 0;
}

const Punkt &SLDiag::getGSize() const // gibt die Gitter Größe zurück
{
    return gitterGr;
}

int SLDiag::getGFarbe() const // gibt die Gitter Farbe zurück
{
    return gF;
}

int SLDiag::getLinienNummer( const char *name ) const // gibt die Linien Nummer zurück
{
    for( int i = 0; i < lines; ++i )
    {
        if( lName->z( i )->istGleich( name ) )
            return i;
    }
    return -1;
}

int SLDiag::getLinienNummer( Text *name ) const
{
    for( int i = 0; i < lines; ++i )
    {
        if( lName->z( i )->istGleich( name->getText() ) )
        {
            name->release();
            return i;
        }
    }
    name->release();
    return -1;
}

Text *SLDiag::getLinienName( int lNum ) const // gibt den Linien Namen zurück
{
    return lName->get( lNum );
}

Text *SLDiag::zLinienNamen( int lNum ) const
{
    return lName->z( lNum );
}

int SLDiag::getHighestValue() const // gibt den Höchsten Wert zurück
{
    int ret = 0;
    for( int i = 0; i < lines; ++i )
    {
        int tmp = getHighestValue( i );
        ret = ret >= tmp ? ret : tmp;
    }
    return ret;
}

int SLDiag::getHighestValue( int lNum ) const
{
    int ret = 0;
    Array< int > *tmp = ph->z( lNum );
    int anz = tmp->getEintragAnzahl();
    for( int i = 0; i < anz; ++i )
        ret = ret >= tmp->get( i ) ? ret : tmp->get( i );
    return ret;
}

int SLDiag::getMedian( int lNum ) const // gibt den durchschnittswert zurück
{
    int count;
    int all = 0;
    Array< int > *tmp = ph->z( lNum );
    int anz = tmp->getEintragAnzahl();
    for( count = 1; count <= anz; ++count )
        all += tmp->get( count - 1 );
    return (int)( (double)all / count + 0.5 );
}

int SLDiag::getLAnzahl() const // gibt die Linien Anzahl zurück
{
    return lines;
}

int SLDiag::getLastValue( int lNum ) const // gibt den letzten Wert zurück
{
    return lastValue->get( lNum );
}


// Inhalt der DiagWert Struktur aus Diagramm.h
// Konstruktor
DiagWert::DiagWert()
    : ReferenceCounter(),
    style( 0 ),
    farbe( 0xFFFFFFFF ),
    hintergrund( 0 ),
    name( new Text() ),
    punkte( new Array< DiagPunkt * > )
{}

// Destruktor
DiagWert::~DiagWert()
{
    name->release();
    int anz = punkte->getEintragAnzahl();
    for( int i = 0; i < anz; ++i )
    {
        if( punkte->hat( i ) )
            delete punkte->get( i );
    }
    punkte->release();
}


// Inhalt der DiagDaten Struktur aus Diagramm.h
// Konstruktor
DiagDaten::DiagDaten()
    : ReferenceCounter(),
    style( 0 ),
    rasterDicke( 0 ),
    rasterBreite( 0 ),
    rasterHeight( 0 ),
    rasterFarbe( 0 ),
    hIntervallFarbe( 0xFFFFFFFF ),
    vIntervallFarbe( 0xFFFFFFFF ),
    hIntervallName( new Text() ),
    vIntervallName( new Text() ),
    hIntervallTexte( new RCArray< Text > ),
    vIntervallTexte( new RCArray< Text > ),
    hIntervallWerte( new Array< double > ),
    vIntervallWerte( new Array< double > ),
    hIntervallBreite( 0 ),
    vIntervallHeight( 0 ),
    werte( new RCArray< DiagWert >() )
{}

// Destruktor
DiagDaten::~DiagDaten()
{
    hIntervallName->release();
    vIntervallName->release();
    hIntervallWerte->release();
    vIntervallWerte->release();
    hIntervallTexte->release();
    vIntervallTexte->release();
    werte->release();
}


// Inhalt der BaseDiag Klasse aus Diagramm.h
// Konstruktor
BaseDiag::BaseDiag( Critical *lock )
    : daten( new DiagDaten() ),
    changed( 0 ),
    lock( lock )
{}

// Destruktor
BaseDiag::~BaseDiag()
{
    if( daten )
        daten->release();
}

// nicht constant
void BaseDiag::setDiagDatenZ( DiagDaten *dd ) // Setzt einen Zeiger auf die Daten des Diagramms
{
    lock->lock();
    if( daten )
        daten->release();
    daten = dd;
    lock->unlock();
    changed = 1;
}

void BaseDiag::setDiagDaten( DiagDaten *dd ) // Kopiert die Daten eines Diagramms
{
    lock->lock();
    if( !daten )
        daten = new DiagDaten();
    daten->style = dd->style;
    daten->rasterBreite = dd->rasterBreite;
    daten->rasterHeight = dd->rasterHeight;
    daten->rasterFarbe = dd->rasterFarbe;
    daten->hIntervallFarbe = dd->hIntervallFarbe;
    daten->vIntervallFarbe = dd->vIntervallFarbe;
    daten->hIntervallName->setText( *dd->hIntervallName );
    daten->vIntervallName->setText( *dd->vIntervallName );
    int anz = dd->hIntervallWerte->getEintragAnzahl();
    for( int i = 0; i < anz; ++i )
    {
        if( dd->hIntervallWerte->hat( i ) )
            daten->hIntervallWerte->set( dd->hIntervallWerte->get( i ), i );
    }
    anz = dd->vIntervallWerte->getEintragAnzahl();
    for( int i = 0; i < anz; ++i )
    {
        if( dd->vIntervallWerte->hat( i ) )
            daten->vIntervallWerte->set( dd->vIntervallWerte->get( i ), i );
    }
    daten->hIntervallBreite = dd->hIntervallBreite;
    daten->vIntervallHeight = dd->vIntervallHeight;
    anz = dd->werte->getEintragAnzahl();
    for( int i = 0; i < anz; ++i )
    {
        DiagWert *tmp = dd->werte->z( i );
        if( tmp )
        {
            DiagWert *w = new DiagWert();
            w->style = tmp->style;
            w->farbe = tmp->farbe;
            w->hintergrund = tmp->hintergrund;
            w->name->setText( tmp->name->getText() );
            int anz = tmp->punkte->getEintragAnzahl();
            for( int j = 0; j < anz; ++j )
            {
                if( tmp->punkte->hat( j ) )
                {
                    DiagPunkt *p = new DiagPunkt();
                    p->hIntervall = tmp->punkte->get( j )->hIntervall;
                    p->vIntervall = tmp->punkte->get( j )->vIntervall;
                    w->punkte->set( p, j );
                }
            }
            daten->werte->set( w, i );
        }
    }
    dd->release();
    lock->unlock();
    changed = 1;
}

void BaseDiag::setRasterDicke( int d ) // Rasterdicke setzen
{
    lock->lock();
    if( !daten )
        daten = new DiagDaten();
    if( daten->rasterDicke != d )
        changed = 1;
    daten->rasterDicke = d;
    lock->unlock();
}

void BaseDiag::setRasterBreite( int br ) // Rasterbreite setzen
{
    lock->lock();
    if( !daten )
        daten = new DiagDaten();
    if( daten->rasterBreite != br )
        changed = 1;
    daten->rasterBreite = br;
    lock->unlock();
}

void BaseDiag::setRasterHeight( int hi ) // Rasterhöhe setzen
{
    lock->lock();
    if( !daten )
        daten = new DiagDaten();
    if( daten->rasterHeight != hi )
        changed = 1;
    daten->rasterHeight = hi;
    lock->unlock();
}

void BaseDiag::setRasterFarbe( int f ) // Rasterfarbe setzen
{
    lock->lock();
    if( !daten )
        daten = new DiagDaten();
    if( daten->rasterFarbe != f )
        changed = 1;
    daten->rasterFarbe = f;
    lock->unlock();
}

void BaseDiag::setHIntervallBreite( double br ) // Intervall Breite
{
    lock->lock();
    if( !daten )
        daten = new DiagDaten();
    daten->hIntervallBreite = br;
    lock->unlock();
}

void BaseDiag::setVIntervallHeight( double hi ) // Intervall Höhe
{
    lock->lock();
    if( !daten )
        daten = new DiagDaten();
    daten->vIntervallHeight = hi;
    lock->unlock();
}

void BaseDiag::setHIntervallFarbe( int f ) // Farbe des Horizontalen Intervalls
{
    lock->lock();
    if( !daten )
        daten = new DiagDaten();
    if( daten->hIntervallFarbe != f )
        changed = 1;
    daten->hIntervallFarbe = f;
    lock->unlock();
}

void BaseDiag::setVIntervallFarbe( int f ) // Farbe des Vertikalen Intervalls
{
    lock->lock();
    if( !daten )
        daten = new DiagDaten();
    if( daten->vIntervallFarbe != f )
        changed = 1;
    daten->vIntervallFarbe = f;
    lock->unlock();
}

void BaseDiag::setHIntervallName( char *name ) // Setzt den Namen des Horizontalen Intervalls
{
    lock->lock();
    if( !daten )
        daten = new DiagDaten();
    if( !daten->hIntervallName )
        daten->hIntervallName = new Text();
    if( !daten->hIntervallName->istGleich( name ) )
        changed = 1;
    daten->hIntervallName->setText( name );
    lock->unlock();
}

void BaseDiag::setHIntervallName( Text *name )
{
    lock->lock();
    if( !daten )
        daten = new DiagDaten();
    if( !daten->hIntervallName )
        daten->hIntervallName = new Text();
    if( !daten->hIntervallName->istGleich( *name ) )
        changed = 1;
    daten->hIntervallName->setText( name );
    lock->unlock();
}

void BaseDiag::setVIntervallName( char *name ) // Setzt den Namen des Vertikalen Intervalls
{
    lock->lock();
    if( !daten )
        daten = new DiagDaten();
    if( !daten->vIntervallName )
        daten->vIntervallName = new Text();
    if( !daten->vIntervallName->istGleich( name ) )
        changed = 1;
    daten->vIntervallName->setText( name );
    lock->unlock();
}

void BaseDiag::setVIntervallName( Text *name )
{
    lock->lock();
    if( !daten )
        daten = new DiagDaten();
    if( !daten->vIntervallName )
        daten->vIntervallName = new Text();
    if( !daten->vIntervallName->istGleich( *name ) )
        changed = 1;
    daten->vIntervallName->setText( name );
    lock->unlock();
}

void BaseDiag::addHIntervallText( double hIntervall, char *text ) // Text eines Horizontalen Intervalls hinzufügen
{
    setHIntervallText( hIntervall, text );
}

void BaseDiag::addHIntervallText( double hIntervall, Text *text )
{
    setHIntervallText( hIntervall, *text );
    text->release();
}

void BaseDiag::setHIntervallTextZ( double hIntervall, Text *text ) // Setzt den Text eines Horizontalen Intervalls
{
    lock->lock();
    if( !daten )
        daten = new DiagDaten();
    if( !daten->hIntervallWerte )
        daten->hIntervallWerte = new Array< double >();
    if( !daten->hIntervallTexte )
        daten->hIntervallTexte = new RCArray< Text >();
    int anz = daten->hIntervallWerte->getEintragAnzahl();
    for( int i = 0; i < anz; ++i )
    {
        if( daten->hIntervallWerte->hat( i ) && daten->hIntervallWerte->get( i ) == hIntervall )
        {
            daten->hIntervallTexte->set( text, i );
            lock->unlock();
            changed = 1;
            return;
        }
    }
    daten->hIntervallWerte->set( hIntervall, anz );
    daten->hIntervallTexte->set( text, anz );
    lock->unlock();
    changed = 1;
}

void BaseDiag::setHIntervallText( double hIntervall, Text *text )
{
    setHIntervallText( hIntervall, *text );
    text->release();
}

void BaseDiag::setHIntervallText( double hIntervall, char *text )
{
    lock->lock();
    if( !daten )
        daten = new DiagDaten();
    if( !daten->hIntervallWerte )
        daten->hIntervallWerte = new Array< double >();
    if( !daten->hIntervallTexte )
        daten->hIntervallTexte = new RCArray< Text >();
    int anz = daten->hIntervallWerte->getEintragAnzahl();
    for( int i = 0; i < anz; ++i )
    {
        if( daten->hIntervallWerte->hat( i ) && daten->hIntervallWerte->get( i ) == hIntervall )
        {
            if( !daten->hIntervallTexte->z( i ) )
                daten->hIntervallTexte->set( new Text( text ), i );
            else
                daten->hIntervallTexte->z( i )->setText( text );
            lock->unlock();
            changed = 1;
            return;
        }
    }
    daten->hIntervallWerte->set( hIntervall, anz );
    daten->hIntervallTexte->set( new Text( text ), anz );
    lock->unlock();
    changed = 1;
}

void BaseDiag::removeHIntervallText( double hIntervall ) // Text eines Horizontalen Intervalls entfernen
{
    lock->lock();
    if( !daten )
        daten = new DiagDaten();
    if( !daten->hIntervallWerte )
        daten->hIntervallWerte = new Array< double >();
    if( !daten->hIntervallTexte )
        daten->hIntervallTexte = new RCArray< Text >();
    int anz = daten->hIntervallWerte->getEintragAnzahl();
    for( int i = 0; i < anz; ++i )
    {
        if( daten->hIntervallWerte->hat( i ) && daten->hIntervallWerte->get( i ) == hIntervall )
        {
            daten->hIntervallTexte->remove( i );
            daten->hIntervallWerte->remove( i );
            lock->unlock();
            changed = 1;
            return;
        }
    }
    lock->unlock();
}

void BaseDiag::addVIntervallText( double vIntervall, char *text ) // Text eines Vertikalen Intervalls hinzufügen
{
    setVIntervallText( vIntervall, text );
}

void BaseDiag::addVIntervallText( double vIntervall, Text *text )
{
    setVIntervallText( vIntervall, *text );
    text->release();
}

void BaseDiag::setVIntervallTextZ( double vIntervall, Text *text ) // Setzt den Text eines Vertikalen Intervalls
{
    lock->lock();
    if( !daten )
        daten = new DiagDaten();
    if( !daten->vIntervallWerte )
        daten->vIntervallWerte = new Array< double >();
    if( !daten->vIntervallTexte )
        daten->vIntervallTexte = new RCArray< Text >();
    int anz = daten->vIntervallWerte->getEintragAnzahl();
    for( int i = 0; i < anz; ++i )
    {
        if( daten->vIntervallWerte->hat( i ) && daten->vIntervallWerte->get( i ) == vIntervall )
        {
            daten->vIntervallTexte->set( text, i );
            lock->unlock();
            changed = 1;
            return;
        }
    }
    daten->vIntervallWerte->set( vIntervall, anz );
    daten->vIntervallTexte->set( text, anz );
    lock->unlock();
    changed = 1;
}

void BaseDiag::setVIntervallText( double vIntervall, Text *text )
{
    setVIntervallText( vIntervall, *text );
    text->release();
}

void BaseDiag::setVIntervallText( double vIntervall, char *text )
{
    lock->lock();
    if( !daten )
        daten = new DiagDaten();
    if( !daten->vIntervallWerte )
        daten->vIntervallWerte = new Array< double >();
    if( !daten->vIntervallTexte )
        daten->vIntervallTexte = new RCArray< Text >();
    int anz = daten->vIntervallWerte->getEintragAnzahl();
    for( int i = 0; i < anz; ++i )
    {
        if( daten->vIntervallWerte->hat( i ) && daten->vIntervallWerte->get( i ) == vIntervall )
        {
            if( !daten->vIntervallTexte->z( i ) )
                daten->vIntervallTexte->set( new Text( text ), i );
            else
                daten->vIntervallTexte->z( i )->setText( text );
            lock->unlock();
            changed = 1;
            return;
        }
    }
    daten->vIntervallWerte->set( vIntervall, anz );
    daten->vIntervallTexte->set( new Text( text ), anz );
    lock->unlock();
    changed = 1;
}

void BaseDiag::removeVIntervallText( double vIntervall ) // Text eines Vertikalen Intervalls entfernen
{
    lock->lock();
    if( !daten )
        daten = new DiagDaten();
    if( !daten->vIntervallWerte )
        daten->vIntervallWerte = new Array< double >();
    if( !daten->vIntervallTexte )
        daten->vIntervallTexte = new RCArray< Text >();
    int anz = daten->vIntervallWerte->getEintragAnzahl();
    for( int i = 0; i < anz; ++i )
    {
        if( daten->vIntervallWerte->hat( i ) && daten->vIntervallWerte->get( i ) == vIntervall )
        {
            daten->vIntervallTexte->remove( i );
            daten->vIntervallWerte->remove( i );
            lock->unlock();
            changed = 1;
            return;
        }
    }
    lock->unlock();
}

void BaseDiag::addWertZ( DiagWert *w ) // Fügt einen Wert hinzu
{
    lock->lock();
    if( !daten )
        daten = new DiagDaten();
    if( !daten->werte )
        daten->werte = new RCArray< DiagWert >();
    daten->werte->add( w );
    lock->unlock();
    changed = 1;
}

void BaseDiag::addWert( DiagWert *w )
{
    lock->lock();
    DiagWert *tmp = new DiagWert();
    tmp->style = w->style;
    tmp->farbe = w->farbe;
    tmp->hintergrund = w->hintergrund;
    tmp->name->setText( *w->name );
    int anz = w->punkte->getEintragAnzahl();
    for( int i = 0; i < anz; ++i )
    {
        if( w->punkte->hat( i ) )
        {
            DiagPunkt *p = new DiagPunkt();
            p->hIntervall = w->punkte->get( i )->hIntervall;
            p->vIntervall = w->punkte->get( i )->vIntervall;
            tmp->punkte->set( p, i );
        }
    }
    w->release();
    addWertZ( tmp );
    lock->unlock();
    changed = 1;
}

void BaseDiag::addWert( const char *name )
{
    lock->lock();
    if( !daten )
        daten = new DiagDaten();
    if( !daten->werte )
        daten->werte = new RCArray< DiagWert >();
    DiagWert *w = new DiagWert();
    w->name->setText( name );
    daten->werte->add( w );
    lock->unlock();
    changed = 1;
}

void BaseDiag::addWert( Text *txt )
{
    addWert( *txt );
    txt->release();
}

void BaseDiag::setWertFarbe( int wNum, int f ) // setzt die Farbe eines Wertes
{
    if( wNum < 0 )
        return;
    lock->lock();
    if( !daten )
        daten = new DiagDaten();
    if( !daten->werte )
        daten->werte = new RCArray< DiagWert >();
    if( !daten->werte->z( wNum ) )
        daten->werte->set( new DiagWert(), wNum );
    daten->werte->z( wNum )->farbe = f;
    lock->unlock();
    changed = 1;
}

void BaseDiag::addPunktZ( int wNum, DiagPunkt *p ) // fügt einem Wert einen Punkt hinzu
{
    if( wNum < 0 )
        return;
    lock->lock();
    if( !daten )
        daten = new DiagDaten();
    if( !daten->werte )
        daten->werte = new RCArray< DiagWert >();
    while( !daten->werte->hat( wNum ) )
        daten->werte->add( new DiagWert() );
    if( !daten->werte->z( wNum )->punkte )
        daten->werte->z( wNum )->punkte = new Array< DiagPunkt * >();
    daten->werte->z( wNum )->punkte->add( p );
    lock->unlock();
    changed = 1;
}

void BaseDiag::addPunkt( int wNum, DiagPunkt *p )
{
    if( wNum < 0 )
        return;
    lock->lock();
    if( !daten )
        daten = new DiagDaten();
    if( !daten->werte )
        daten->werte = new RCArray< DiagWert >();
    while( !daten->werte->hat( wNum ) )
        daten->werte->add( new DiagWert() );
    if( !daten->werte->z( wNum )->punkte )
        daten->werte->z( wNum )->punkte = new Array< DiagPunkt * >();
    DiagPunkt *tmp = new DiagPunkt();
    tmp->hIntervall = p->hIntervall;
    tmp->vIntervall = p->vIntervall;
    daten->werte->z( wNum )->punkte->add( tmp );
    lock->unlock();
    changed = 1;
}

void BaseDiag::addPunkt( int wNum, double hI, double vI )
{
    if( wNum < 0 )
        return;
    lock->lock();
    if( !daten )
        daten = new DiagDaten();
    if( !daten->werte )
        daten->werte = new RCArray< DiagWert >();
    if( !daten->werte->z( wNum ) )
        daten->werte->set( new DiagWert(), wNum );
    if( !daten->werte->z( wNum )->punkte )
        daten->werte->z( wNum )->punkte = new Array< DiagPunkt * >();
    DiagPunkt *tmp = new DiagPunkt();
    tmp->hIntervall = hI;
    tmp->vIntervall = vI;
    daten->werte->z( wNum )->punkte->add( tmp );
    lock->unlock();
    changed = 1;
}

// Ändert einen vorhandenen Punkt eines Wertes
void BaseDiag::setPunktZ( int wNum, double hI, DiagPunkt *p )
{
    setPunktZ( wNum, getDiagPunktPos( wNum, hI ), p );
}

void BaseDiag::setPunkt( int wNum, double hI, DiagPunkt *p )
{
    setPunkt( wNum, getDiagPunktPos( wNum, hI ), p->hIntervall, p->vIntervall );
}

void BaseDiag::setPunkt( int wNum, double hI, double h, double v )
{
    setPunkt( wNum, getDiagPunktPos( wNum, hI ), h, v );
}

void BaseDiag::setPunktZ( int wNum, int pNum, DiagPunkt *p )
{
    if( pNum < 0 || wNum < 0 )
        return;
    lock->lock();
    if( !daten )
        daten = new DiagDaten();
    if( !daten->werte )
        daten->werte = new RCArray< DiagWert >();
    if( !daten->werte->z( wNum ) )
        daten->werte->set( new DiagWert(), wNum );
    if( !daten->werte->z( wNum )->punkte )
        daten->werte->z( wNum )->punkte = new Array< DiagPunkt * >();
    if( daten->werte->z( wNum )->punkte->hat( pNum ) )
        delete daten->werte->z( wNum )->punkte->get( pNum );
    daten->werte->z( wNum )->punkte->set( p, pNum );
    lock->unlock();
    changed = 1;
}

void BaseDiag::setPunkt( int wNum, int pNum, DiagPunkt *p )
{
    if( pNum < 0 || wNum < 0 )
        return;
    setPunkt( wNum, pNum, p->hIntervall, p->vIntervall );
}

void BaseDiag::setPunkt( int wNum, int pNum, double h, double v )
{
    if( pNum < 0 || wNum < 0 )
        return;
    lock->lock();
    if( !daten )
        daten = new DiagDaten();
    if( !daten->werte )
        daten->werte = new RCArray< DiagWert >();
    if( !daten->werte->z( wNum ) )
        daten->werte->set( new DiagWert(), wNum );
    if( !daten->werte->z( wNum )->punkte )
        daten->werte->z( wNum )->punkte = new Array< DiagPunkt * >();
    if( !daten->werte->z( wNum )->punkte->hat( pNum ) )
        daten->werte->z( wNum )->punkte->set( new DiagPunkt(), pNum );
    daten->werte->z( wNum )->punkte->get( pNum )->hIntervall = h;
    daten->werte->z( wNum )->punkte->get( pNum )->vIntervall = v;
    lock->unlock();
    changed = 1;
}

// Löscht einen vorhandenen Punkt
void BaseDiag::removePunkt( int wNum, double hI )
{
    lock->lock();
    if( !daten )
        daten = new DiagDaten();
    if( !daten->werte )
        daten->werte = new RCArray< DiagWert >();
    if( !daten->werte->z( wNum ) )
        daten->werte->set( new DiagWert(), wNum );
    if( !daten->werte->z( wNum )->punkte )
        daten->werte->z( wNum )->punkte = new Array< DiagPunkt * >();
    int anz = daten->werte->z( wNum )->punkte->getEintragAnzahl();
    for( int i = 0; i < anz; ++i )
    {
        if( daten->werte->z( wNum )->punkte->hat( i ) && daten->werte->z( wNum )->punkte->get( i )->hIntervall == hI )
        {
            delete daten->werte->z( wNum )->punkte->get( i );
            daten->werte->z( wNum )->punkte->remove( i );
            lock->unlock();
            changed = 1;
            return;
        }
    }
    lock->unlock();
}

void BaseDiag::removePunkt( int wNum, int pNum )
{
    lock->lock();
    if( !daten )
        daten = new DiagDaten();
    if( !daten->werte )
        daten->werte = new RCArray< DiagWert >();
    if( !daten->werte->z( wNum ) )
        daten->werte->set( new DiagWert(), wNum );
    if( !daten->werte->z( wNum )->punkte )
        daten->werte->z( wNum )->punkte = new Array< DiagPunkt * >();
    if( daten->werte->z( wNum )->punkte->hat( pNum ) )
    {
        delete daten->werte->z( wNum )->punkte->get( pNum );
        daten->werte->z( wNum )->punkte->remove( pNum );
        changed = 1;
    }
    lock->unlock();
}

void BaseDiag::removeWert( int wNum ) // entfernt einen Wert
{
    lock->lock();
    if( !daten )
        daten = new DiagDaten();
    if( !daten->werte )
        daten->werte = new RCArray< DiagWert >();
    daten->werte->remove( wNum );
    lock->unlock();
    changed = 1;
}

void BaseDiag::removeWert( char *name )
{
    lock->lock();
    if( !daten )
        daten = new DiagDaten();
    if( !daten->werte )
        daten->werte = new RCArray< DiagWert >();
    int anz = daten->werte->getEintragAnzahl();
    for( int i = 0; i < anz; ++i )
    {
        DiagWert *tmp = daten->werte->z( i );
        if( tmp && tmp->name && tmp->name->istGleich( name ) )
        {
            daten->werte->remove( i );
            lock->unlock();
            changed = 1;
            return;
        }
    }
    lock->unlock();
}

void BaseDiag::removeWert( Text *name )
{
    removeWert( name->getText() );
    name->release();
}

void BaseDiag::addDatenStyle( int style ) // Setzt den Style der Daten
{
    if( !daten )
        daten = new DiagDaten();
    if( ( daten->style | style ) != daten->style )
        changed = 1;
    daten->style |= style;
}

void BaseDiag::setDatenStyle( int style )
{
    if( !daten )
        daten = new DiagDaten();
    if( daten->style != style )
        changed = 1;
    daten->style = style;
}

void BaseDiag::setDatenStyle( int style, bool addRemove )
{
    if( addRemove )
        addDatenStyle( style );
    else
        removeDatenStyle( style );
}

void BaseDiag::removeDatenStyle( int style )
{
    if( !daten )
        daten = new DiagDaten();
    if( ( daten->style & ~style ) != daten->style )
        changed = 1;
    daten->style &= ~style;
}

void BaseDiag::addWertStyle( int wNum, int style ) // Setzt den Style eines Wertes
{
    if( wNum < 0 )
        return;
    if( !daten )
        daten = new DiagDaten();
    if( !daten->werte->z( wNum ) )
        daten->werte->set( new DiagWert(), wNum );
    if( ( daten->werte->z( wNum )->style | style ) != daten->werte->z( wNum )->style )
        changed = 1;
    daten->werte->z( wNum )->style |= style;
}

void BaseDiag::setWertStyle( int wNum, int style )
{
    if( wNum < 0 )
        return;
    if( !daten )
        daten = new DiagDaten();
    if( !daten->werte->z( wNum ) )
        daten->werte->set( new DiagWert(), wNum );
    if( daten->werte->z( wNum )->style != style )
        changed = 1;
    daten->werte->z( wNum )->style = style;
}

void BaseDiag::setWertStyle( int wNum, int style, bool addRemove )
{
    if( wNum < 0 )
        return;
    if( addRemove )
        addWertStyle( wNum, style );
    else
        removeWertStyle( wNum, style );
}

void BaseDiag::removeWertStyle( int wNum, int style )
{
    if( wNum < 0 )
        return;
    if( !daten )
        daten = new DiagDaten();
    if( !daten->werte->z( wNum ) )
        daten->werte->set( new DiagWert(), wNum );
    if( ( daten->werte->z( wNum )->style & ~style ) != daten->werte->z( wNum )->style )
        changed = 1;
    daten->werte->z( wNum )->style &= ~style;
}

// constant
DiagDaten *BaseDiag::getDiagDaten() const // Gibt die Daten des Diagramms zurück
{
    return daten ? dynamic_cast<DiagDaten *>( daten->getThis() ) : 0;
}

DiagDaten *BaseDiag::zDiagDaten() const
{
    return daten;
}

DiagWert *BaseDiag::getDiagWert( int wNum ) const // Gibt die Daten eines Wertes zurück
{
    return ( daten && daten->werte ) ? daten->werte->get( wNum ) : 0;
}

DiagWert *BaseDiag::zDiagWert( int wNum ) const
{
    return ( daten && daten->werte ) ? daten->werte->z( wNum ) : 0;
}

DiagWert *BaseDiag::getDiagWert( char *name ) const
{
    return getDiagWert( getDiagWertPos( name ) );
}

DiagWert *BaseDiag::zDiagWert( char *name ) const
{
    return zDiagWert( getDiagWertPos( name ) );
}

int BaseDiag::getDiagWertPos( char *name ) const // Gibt die Position eines Wertes zurück
{
    if( !daten || !daten->werte )
        return -1;
    int anz = daten->werte->getEintragAnzahl();
    for( int i = 0; i < anz; ++i )
    {
        if( daten->werte->z( i ) && daten->werte->z( i )->name && daten->werte->z( i )->name->istGleich( name ) )
            return i;
    }
    return -1;
}

int BaseDiag::getDiagPunktPos( int wNum, double hI ) const // Gibt die Position eines Punktes von einem Wert zurück
{
    if( !daten || !daten->werte || !daten->werte->z( wNum ) || !daten->werte->z( wNum )->punkte )
        return -1;
    int anz = daten->werte->z( wNum )->punkte->getEintragAnzahl();
    for( int i = 0; i < anz; ++i )
    {
        if( daten->werte->z( wNum )->punkte->hat( i ) && daten->werte->z( wNum )->punkte->get( i )->hIntervall == hI )
            return i;
    }
    return -1;
}

int BaseDiag::getDiagPunktPos( char *wName, double hI ) const
{
    return getDiagPunktPos( getDiagWertPos( wName ), hI );
}

bool BaseDiag::hatDatenStyle( int style ) const // Prüft den Style der Daten
{
    if( !daten )
        return 0;
    return ( daten->style | style ) == daten->style;
}

bool BaseDiag::hatDatenStyleNicht( int style ) const
{
    if( !daten )
        return 1;
    return ( daten->style | style ) != daten->style;
}

bool BaseDiag::hatWertStyle( int wNum, int style ) const // Prüft den Style eines Wertes
{
    if( !daten || !daten->werte || !daten->werte->z( wNum ) )
        return 0;
    return ( daten->werte->z( wNum )->style | style ) == daten->werte->z( wNum )->style;
}

bool BaseDiag::hatWertStyleNicht( int wNum, int style ) const
{
    if( !daten || !daten->werte || !daten->werte->z( wNum ) )
        return 1;
    return ( daten->werte->z( wNum )->style | style ) != daten->werte->z( wNum )->style;
}

// Inhalt der LDiag Klasse aus Diagramm.h
// Konstruktor
LDiag::LDiag()
    : ZeichnungHintergrund(),
    BaseDiag( &cs ),
    textRd( 0 ),
    dRam( new LRahmen() ),
    dBgF( 0 ),
    dBgB( 0 ),
    dAf( new AlphaFeld() ),
    vIntervallRB( new Bild() ),
    hIntervallRB( new Bild() ),
    schriftGr( 12 )
{
    style = Style::MELockZeichnung;
    vertikalScrollBar = new VScrollBar();
    horizontalScrollBar = new HScrollBar();
}

// Destruktor
LDiag::~LDiag()
{
    if( textRd )
        textRd->release();
    if( dRam )
        dRam->release();
    if( dBgB )
        dBgB->release();
    if( dAf )
        dAf->release();
    if( vIntervallRB )
        vIntervallRB->release();
    if( hIntervallRB )
        hIntervallRB->release();
}

void LDiag::doMausEreignis( MausEreignis &me, bool userRet )
{
    if( hatDatenStyle( DiagDaten::Style::Sichtbar ) && ( hatStyle( Style::HScroll ) || hatStyle( Style::VScroll ) ) && userRet )
    {
        int rbr = 0;
        if( hatStyle( Style::Rahmen ) && rahmen )
            rbr = rahmen->getRBreite();
        bool vs = hatStyle( Style::VScroll ) && vertikalScrollBar;
        bool hs = hatStyle( Style::HScroll ) && horizontalScrollBar;
        if( vs )
        {
            if( hs )
                horizontalScrollBar->doMausMessage( rbr, gr.y - rbr - 15, gr.x - rbr * 2 - 15, 15, me );
            vertikalScrollBar->doMausMessage( gr.x - rbr - 15, rbr, 15, gr.y - rbr * 2, me );
        }
        else if( hs )
            horizontalScrollBar->doMausMessage( rbr, gr.y - rbr - 15, gr.x - rbr * 2, 15, me );
    }
    me.verarbeitet = userRet;
}

// nicht constant
void LDiag::setTextRendererZ( TextRenderer *textRd )
{
    lockZeichnung();
    if( this->textRd )
        this->textRd->release();
    this->textRd = textRd;
    unlockZeichnung();
}

void LDiag::setSchriftZ( Schrift *schrift ) // Setzt die Schrift
{
    lockZeichnung();
    if( !this->textRd )
        textRd = new TextRenderer( schrift );
    else
        textRd->setSchriftZ( schrift );
    rend = 1;
    unlockZeichnung();
}

void LDiag::setSchriftSize( int gr )
{
    lockZeichnung();
    if( schriftGr != gr )
        rend = 1;
    schriftGr = gr;
    unlockZeichnung();
}

void LDiag::setDatenRahmenZ( Rahmen *ram ) // Setzt den inneren Rahmen um das eigentliche Diagramm
{
    lockZeichnung();
    if( dRam )
        dRam->release();
    dRam = ram;
    unlockZeichnung();
    rend = 1;
}

void LDiag::setDatenRahmen( Rahmen *ram )
{
    lockZeichnung();
    if( !dRam )
        dRam = new LRahmen();
    dRam->setAlpha( ram->hatAlpha() );
    dRam->setFarbe( ram->getFarbe() );
    dRam->setRamenBreite( ram->getRBreite() );
    unlockZeichnung();
    ram->release();
    rend = 1;
}

void LDiag::setDatenRahmenBreite( int br )
{
    lockZeichnung();
    if( !dRam )
        dRam = new LRahmen();
    if( dRam->getRBreite() != br )
        rend = 1;
    dRam->setRamenBreite( br );
    unlockZeichnung();
}

void LDiag::setDatenRahmenFarbe( int f )
{
    lockZeichnung();
    if( !dRam )
        dRam = new LRahmen();
    dRam->setFarbe( f );
    unlockZeichnung();
    rend = 1;
}

void LDiag::setDatenHintergrundFarbe( int f ) // Setzt den Hintergrund des eigentlichen Diagramms
{
    dBgF = f;
    rend = 1;
}

void LDiag::setDatenHintergrundBildZ( Bild *b )
{
    lockZeichnung();
    if( dBgB )
        dBgB->release();
    dBgB = b;
    unlockZeichnung();
    rend = 1;
}

void LDiag::setDatenHintergrundBild( Bild *b )
{
    lockZeichnung();
    if( !dBgB )
        dBgB = new Bild();
    dBgB->neuBild( b->getBreite(), b->getHeight(), 0 );
    dBgB->drawBild( 0, 0, b->getBreite(), b->getHeight(), *b );
    unlockZeichnung();
    b->release();
    rend = 1;
}

void LDiag::setDatenAlphaFeldZ( AlphaFeld *af ) // Setzt das AlphaFeld des eigentlichen Diagramms
{
    lockZeichnung();
    if( dAf )
        dAf->release();
    dAf = af;
    unlockZeichnung();
    rend = 1;
}

void LDiag::setDatenAlphaFeld( AlphaFeld *af )
{
    lockZeichnung();
    if( !dAf )
        dAf = new AlphaFeld();
    dAf->setFarbe( af->getFarbe() );
    dAf->setStrength( af->getStrength() );
    unlockZeichnung();
    af->release();
    rend = 1;
}

void LDiag::setDatenAlphaFeldFarbe( int f )
{
    lockZeichnung();
    if( !dAf )
        dAf = new AlphaFeld();
    dAf->setFarbe( f );
    unlockZeichnung();
    rend = 1;
}

void LDiag::setDatenAlphaFeldStrength( int st )
{
    lockZeichnung();
    if( !dAf )
        dAf = new AlphaFeld();
    if( dAf->getStrength() != st )
        rend = 1;
    dAf->setStrength( st );
    unlockZeichnung();
}

void LDiag::render( Bild &zRObj )
{
    if( !hatDatenStyle( DiagDaten::Style::Sichtbar ) )
        return;
    ZeichnungHintergrund::render( zRObj );
    if( !zRObj.setDrawOptions( innenPosition, innenSize ) )
        return;
    lockZeichnung();
    int dgy = 0;
    int dgbr = innenSize.x;
    int dghi = innenSize.y;
    int vIAnz = 0;
    int hIAnz = 0;
    if( daten )
    { // Auto werte berechnen
        vIAnz = daten->vIntervallWerte ? daten->vIntervallWerte->getEintragAnzahl() : 0;
        hIAnz = daten->hIntervallWerte ? daten->hIntervallWerte->getEintragAnzahl() : 0;
        if( daten->vIntervallWerte && hatDatenStyle( DiagDaten::Style::AutoIntervallHeight ) )
        {
            double maxW = 0;
            for( int i = 0; i < vIAnz; ++i )
            {
                if( daten->vIntervallWerte->hat( i ) && daten->vIntervallWerte->get( i ) > maxW )
                    maxW = daten->vIntervallWerte->get( i );
            }
            if( vertikalScrollBar && hatStyle( Style::VScroll ) )
                daten->vIntervallHeight = maxW ? ( vertikalScrollBar->getScroll() / maxW ) : 0;
            else
                daten->vIntervallHeight = maxW ? ( vIntervallRB->getBreite() / maxW ) : 0;
        }
        if( hatDatenStyle( DiagDaten::Style::AutoRasterHeight ) )
            daten->rasterHeight = daten->vIntervallHeight;
        if( daten->hIntervallWerte && hatDatenStyle( DiagDaten::Style::AutoIntervallBreite ) )
        {
            double maxW = 0;
            for( int i = 0; i < hIAnz; ++i )
            {
                if( daten->hIntervallWerte->hat( i ) && daten->hIntervallWerte->get( i ) > maxW )
                    maxW = daten->hIntervallWerte->get( i );
            }
            if( horizontalScrollBar && hatStyle( Style::HScroll ) )
                daten->hIntervallBreite = maxW ? ( horizontalScrollBar->getScroll() / maxW ) : 0;
            else
                daten->hIntervallBreite = maxW ? ( hIntervallRB->getBreite() / maxW ) : 0;
        }
        if( hatDatenStyle( DiagDaten::Style::AutoRasterBreite ) )
            daten->rasterBreite = daten->hIntervallBreite;
    }
    if( hatDatenStyle( DiagDaten::Style::VIntervall ) && textRd && schriftGr && daten )
    { // Rendern des vertikalen Intervalls
        int vIRBbr = innenSize.y;
        if( hatDatenStyle( DiagDaten::Style::HIntervall ) && daten->hIntervallFarbe )
            vIRBbr -= schriftGr + 2;
        if( vIRBbr > 0 )
        {
            if( vIntervallRB->getBreite() != vIRBbr || vIntervallRB->getHeight() != schriftGr + 2 )
                vIntervallRB->neuBild( vIRBbr, schriftGr + 2, 0xFF000000 );
            else
                vIntervallRB->fillRegion( 0, 0, vIRBbr, schriftGr + 2, 0xFF000000 );
            textRd->setSchriftSize( schriftGr );
            if( daten->vIntervallWerte )
            {
                int *rf = new int[ vIAnz ];
                int anz = 0;
                bool *fertig = new bool[ vIAnz ];
                ZeroMemory( fertig, vIAnz );
                for( int i = 0; i < vIAnz; ++i )
                {
                    double min = 0;
                    int mI = -1;
                    for( int j = 0; j < vIAnz; ++j )
                    {
                        if( !fertig[ j ] && daten->vIntervallWerte->hat( j ) && ( daten->vIntervallWerte->get( j ) < min || mI < 0 ) )
                        {
                            mI = j;
                            min = daten->vIntervallWerte->get( j );
                        }
                    }
                    if( mI < 0 )
                        break;
                    rf[ anz ] = mI;
                    ++anz;
                    fertig[ mI ] = 1;
                }
                delete[] fertig;
                Text txt;
                int xPos = 0;
                if( vertikalScrollBar && hatStyle( Style::VScroll ) )
                    xPos -= vertikalScrollBar->getScroll();
                int rWeite = xPos - 10;
                for( int i = anz - 1; i >= 0; --i )
                {
                    txt = "";
                    if( hatDatenStyle( DiagDaten::Style::VIntervallTexte ) && daten->vIntervallTexte && daten->vIntervallTexte->z( rf[ i ] ) )
                        txt = daten->vIntervallTexte->z( rf[ i ] )->getText();
                    else if( hatDatenStyleNicht( DiagDaten::Style::VIntervallTexte ) || !daten->vIntervallWerte )
                        txt = daten->vIntervallWerte->get( rf[ i ] );
                    xPos = (int)( daten->vIntervallWerte->get( rf[ i ] ) * daten->vIntervallHeight );
                    xPos = ( vertikalScrollBar && hatStyle( Style::VScroll ) ? vertikalScrollBar->getScroll() : vIntervallRB->getBreite() ) - xPos;
                    if( vertikalScrollBar && hatStyle( Style::VScroll ) )
                        xPos -= vertikalScrollBar->getScroll();
                    int br = textRd->getTextBreite( txt );
                    if( xPos + br > vIntervallRB->getBreite() && vIntervallRB->getBreite() - br >= rWeite + 10 )
                        xPos = vIntervallRB->getBreite() - br;
                    if( xPos >= rWeite + 10 )
                    {
                        textRd->renderText( xPos, 1, txt, *vIntervallRB, daten->vIntervallFarbe );
                        rWeite = xPos + br + 10;
                    }
                }
                delete[] rf;
            }
            if( daten->vIntervallName )
            {
                int vinbr = textRd->getTextBreite( daten->vIntervallName->getText() );
                int vinx = vIntervallRB->getBreite() / 2 - vinbr / 2;
                vIntervallRB->fillRegion( vinx - 5, 1, vinbr + 10, schriftGr, 0xFF000000 );
                textRd->renderText( vinx, 1, daten->vIntervallName->getText(), *vIntervallRB, daten->vIntervallFarbe );
            }
            if( hatDatenStyle( DiagDaten::Style::HIntervall ) && daten->hIntervallFarbe )
                zRObj.alphaBild90( innenSize.x - vIntervallRB->getHeight(), schriftGr + 2, vIntervallRB->getBreite(), vIntervallRB->getHeight(), *vIntervallRB );
            else
                zRObj.alphaBild90( innenSize.x - vIntervallRB->getHeight(), 0, vIntervallRB->getBreite(), vIntervallRB->getHeight(), *vIntervallRB );
            dgbr -= vIntervallRB->getHeight();
        }
    }
    if( hatDatenStyle( DiagDaten::Style::HIntervall ) && textRd && schriftGr && daten )
    { // Rendern des horizontalen Intervalls
        int hIRBbr = innenSize.x;
        if( hatDatenStyle( DiagDaten::Style::VIntervall ) && daten->vIntervallFarbe )
            hIRBbr -= schriftGr + 2;
        if( hIRBbr > 0 )
        {
            if( hIntervallRB->getBreite() != hIRBbr || hIntervallRB->getHeight() != schriftGr + 2 )
                hIntervallRB->neuBild( hIRBbr, schriftGr + 2, 0xFF000000 );
            else
                hIntervallRB->fillRegion( 0, 0, hIRBbr, schriftGr + 2, 0xFF000000 );
            textRd->setSchriftSize( schriftGr );
            if( daten->hIntervallWerte )
            {
                int *rf = new int[ hIAnz ];
                int anz = 0;
                bool *fertig = new bool[ hIAnz ];
                ZeroMemory( fertig, hIAnz );
                for( int i = 0; i < hIAnz; ++i )
                {
                    double min = 0;
                    int mI = -1;
                    for( int j = 0; j < hIAnz; ++j )
                    {
                        if( !fertig[ j ] && daten->hIntervallWerte->hat( j ) && ( daten->hIntervallWerte->get( j ) < min || mI < 0 ) )
                        {
                            mI = j;
                            min = daten->hIntervallWerte->get( j );
                        }
                    }
                    if( mI < 0 )
                        break;
                    rf[ anz ] = mI;
                    ++anz;
                    fertig[ mI ] = 1;
                }
                delete[] fertig;
                Text txt;
                int xPos = 0;
                if( horizontalScrollBar && hatStyle( Style::HScroll ) )
                    xPos -= horizontalScrollBar->getScroll();
                int rWeite = xPos - 10;
                for( int i = 0; i < anz; ++i )
                {
                    txt = "";
                    if( hatDatenStyle( DiagDaten::Style::HIntervallTexte ) && daten->hIntervallTexte && daten->hIntervallTexte->z( rf[ i ] ) )
                        txt = daten->hIntervallTexte->z( rf[ i ] )->getText();
                    else if( hatDatenStyleNicht( DiagDaten::Style::HIntervallTexte ) || !daten->hIntervallWerte )
                        txt = daten->hIntervallWerte->get( rf[ i ] );
                    xPos = (int)( daten->hIntervallWerte->get( rf[ i ] ) * daten->hIntervallBreite );
                    if( horizontalScrollBar && hatStyle( Style::HScroll ) )
                        xPos -= horizontalScrollBar->getScroll();
                    int br = textRd->getTextBreite( txt );
                    if( xPos + br > hIntervallRB->getBreite() && hIntervallRB->getBreite() - br >= rWeite + 10 )
                        xPos = hIntervallRB->getBreite() - br;
                    if( xPos >= rWeite + 10 )
                    {
                        textRd->renderText( xPos, 1, txt, *hIntervallRB, daten->hIntervallFarbe );
                        rWeite = xPos + br + 10;
                    }
                }
                delete[] rf;
            }
            if( daten->hIntervallName )
            {
                int hinbr = textRd->getTextBreite( daten->hIntervallName->getText() );
                int hinx = hIntervallRB->getBreite() / 2 - hinbr / 2;
                hIntervallRB->fillRegion( hinx - 5, 1, hinbr + 10, schriftGr, 0xFF000000 );
                textRd->renderText( hinx, 1, daten->hIntervallName->getText(), *hIntervallRB, daten->hIntervallFarbe );
            }
            zRObj.alphaBild( 0, 0, hIntervallRB->getBreite(), hIntervallRB->getHeight(), *hIntervallRB );
            dghi -= hIntervallRB->getHeight();
            dgy += hIntervallRB->getHeight();
        }
    }
    if( !zRObj.setDrawOptions( 0, dgy, dgbr, dghi ) )
    {
        zRObj.releaseDrawOptions();
        unlockZeichnung();
        return;
    }
    dgy = 0;
    int dgrbr = 0;
    if( hatStyle( Style::DatenRahmen ) && dRam )
    {
        dRam->setSize( dgbr, dghi );
        dRam->render( zRObj );
        dgrbr = dRam->getRBreite();
    }
    if( !zRObj.setDrawOptions( dgrbr, dgrbr, dgbr - dgrbr * 2, dghi - dgrbr * 2 ) )
    {
        zRObj.releaseDrawOptions();
        zRObj.releaseDrawOptions();
        unlockZeichnung();
        return;
    }
    if( hatStyle( Style::DatenHintergrund ) )
    {
        if( hatStyle( Style::DatenHAlpha ) )
            zRObj.alphaRegion( 0, 0, dgbr - dgrbr * 2, dghi - dgrbr * 2, dBgF );
        else
            zRObj.fillRegion( 0, 0, dgbr - dgrbr * 2, dghi - dgrbr * 2, dBgF );
        if( hatStyle( Style::DatenHBild ) && dBgB )
        {
            if( hatStyle( Style::DatenHAlpha ) )
                zRObj.alphaBild( 0, 0, dgbr - dgrbr * 2, dghi - dgrbr * 2, *dBgB );
            else
                zRObj.drawBild( 0, 0, dgbr - dgrbr * 2, dghi - dgrbr * 2, *dBgB );
        }
    }
    if( hatStyle( Style::DatenBuffered ) && dAf )
    {
        dAf->setSize( dgbr - dgrbr * 2, dghi - dgrbr * 2 );
        dAf->render( zRObj );
    }
    if( hatDatenStyle( DiagDaten::Style::Raster ) && daten && daten->rasterDicke && daten->rasterBreite && daten->rasterHeight )
    { // Raster
        int maxBr = dgbr;
        if( horizontalScrollBar && hatStyle( Style::HScroll ) )
            maxBr = horizontalScrollBar->getScroll();
        int maxHi = dghi;
        if( vertikalScrollBar && hatStyle( Style::VScroll ) )
            maxHi = vertikalScrollBar->getScroll();
        for( double x = horizontalScrollBar && hatStyle( Style::HScroll ) ? -horizontalScrollBar->getScroll() : 0; x < maxBr; x += daten->rasterBreite )
        {
            for( int i = 0; i < daten->rasterDicke; ++i )
            {
                if( hatDatenStyle( DiagDaten::Style::RasterAlpha ) )
                    zRObj.drawLinieVAlpha( (int)( x + i ), dgy + dgrbr, dghi - dgrbr * 2, daten->rasterFarbe );
                else
                    zRObj.drawLinieV( (int)( x + i ), dgy + dgrbr, dghi - dgrbr * 2, daten->rasterFarbe );
            }
        }
        for( double y = maxHi; y > ( vertikalScrollBar && hatStyle( Style::VScroll ) ? -vertikalScrollBar->getScroll() : 0 ); y -= daten->rasterHeight )
        {
            for( int i = 0; i < daten->rasterDicke; ++i )
            {
                if( hatDatenStyle( DiagDaten::Style::RasterAlpha ) )
                    zRObj.drawLinieHAlpha( 0, (int)( y + i ), dgbr - dgrbr * 2, daten->rasterFarbe );
                else
                    zRObj.drawLinieH( 0, (int)( y + i ), dgbr - dgrbr * 2, daten->rasterFarbe );
            }
        }
    }
    if( daten && daten->werte && daten->werte->getEintragAnzahl() && daten->hIntervallBreite && daten->vIntervallHeight )
    { // Werte
        int wAnz = daten->werte->getEintragAnzahl();
        for( int i = 0; i < wAnz; ++i )
        {
            DiagWert *wert = daten->werte->z( i );
            if( wert && hatWertStyle( i, DiagWert::Style::Sichtbar ) && wert->punkte && wert->punkte->getEintragAnzahl() )
            {
                int pAnz = wert->punkte->getEintragAnzahl();
                int *rf = new int[ pAnz ];
                bool *fertig = new bool[ pAnz ];
                int anz = 0;
                ZeroMemory( fertig, pAnz );
                for( int j = 0; j < pAnz; ++j )
                {
                    double min = -1;
                    int p = -1;
                    for( int pi = 0; pi < pAnz; ++pi )
                    {
                        if( wert->punkte->hat( pi ) && !fertig[ pi ] && ( p < 0 || wert->punkte->get( pi )->hIntervall < min ) )
                        {
                            min = wert->punkte->get( pi )->hIntervall;
                            p = pi;
                        }
                    }
                    if( p < 0 )
                        break;
                    rf[ anz ] = p;
                    fertig[ p ] = 1;
                    ++anz;
                }
                delete[] fertig;
                int rpx = horizontalScrollBar && hatStyle( Style::HScroll ) ? -horizontalScrollBar->getScroll() : 0;
                int rpy = vertikalScrollBar && hatStyle( Style::VScroll ) ? -vertikalScrollBar->getScroll() : 0;
                rpy += dgy;
                int dgmhi = vertikalScrollBar && hatStyle( Style::VScroll ) ? dgy + vertikalScrollBar->getScrollData()->max + dgrbr : dgy + dghi - dgrbr;
                if( hatWertStyle( i, DiagWert::Style::Hintergrund ) )
                {
                    DiagPunkt *vorher = 0;
                    DiagPunkt *jetzt = 0;
                    for( int j = 0; j < anz; ++j )
                    {
                        jetzt = wert->punkte->get( rf[ j ] );
                        if( jetzt && vorher )
                        {
                            int ax = (int)( rpx + vorher->hIntervall * daten->hIntervallBreite );
                            int ay = (int)( dgmhi - vorher->vIntervall * daten->vIntervallHeight );
                            int bx = (int)( rpx + jetzt->hIntervall * daten->hIntervallBreite );
                            int by = (int)( dgmhi - jetzt->vIntervall * daten->vIntervallHeight );
                            if( ax >= bx )
                            {
                                vorher = jetzt;
                                continue;
                            }
                            if( !( ax > dgbr - dgrbr || bx < 0 || ( ay > dgy + dghi - dgrbr && by > dgy + dghi - dgrbr ) ) )
                            {
                                double yf = (double)( by - ay ) / ( bx - ax );
                                double y = (double)ay;
                                ax = ax < 0 ? 0 : ax;
                                bx = bx > dgbr - dgrbr ? dgbr - dgrbr : bx;
                                if( hatWertStyle( i, DiagWert::Style::HAlpha ) )
                                {
                                    for( int x = ax; x < bx; x++, y += yf )
                                        zRObj.drawLinieVAlpha( x, (int)( y + 0.5 ), dgmhi - (int)( y + 0.5 ), wert->hintergrund );
                                }
                                else
                                {
                                    for( int x = ax; x < bx; x++, y += yf )
                                        zRObj.drawLinieV( x, (int)( y + 0.5 ), dgmhi - (int)( y + 0.5 ), wert->hintergrund );
                                }
                                if( hatWertStyle( i, DiagWert::Style::Alpha ) )
                                    zRObj.drawLinieAlpha( Punkt( ax, ay ), Punkt( bx, by ), wert->farbe );
                                else
                                    zRObj.drawLinie( Punkt( ax, ay ), Punkt( bx, by ), wert->farbe );
                            }
                        }
                        vorher = jetzt;
                    }
                }
                else
                {
                    DiagPunkt *vorher = 0;
                    DiagPunkt *jetzt = 0;
                    for( int j = 0; j < anz; ++j )
                    {
                        jetzt = wert->punkte->get( rf[ j ] );
                        if( jetzt && vorher )
                        {
                            if( hatWertStyle( i, DiagWert::Style::Alpha ) )
                                zRObj.drawLinieAlpha( Punkt( (int)( rpx + vorher->hIntervall * daten->hIntervallBreite ), (int)( dgmhi - vorher->vIntervall * daten->vIntervallHeight ) ),
                                                      Punkt( (int)( rpx + jetzt->hIntervall * daten->hIntervallBreite ), (int)( dgmhi - jetzt->vIntervall * daten->vIntervallHeight ) ), wert->farbe );
                            else
                                zRObj.drawLinie( Punkt( (int)( rpx + vorher->hIntervall * daten->hIntervallBreite ), (int)( dgmhi - vorher->vIntervall * daten->vIntervallHeight ) ),
                                                 Punkt( (int)( rpx + jetzt->hIntervall * daten->hIntervallBreite ), (int)( dgmhi - jetzt->vIntervall * daten->vIntervallHeight ) ), wert->farbe );
                        }
                        vorher = jetzt;
                    }
                }
                delete[] rf;
            }
        }
    }
    if( daten && daten->werte && daten->werte->getEintragAnzahl() && textRd && schriftGr )
    {
        int wAnz = daten->werte->getEintragAnzahl();
        int rx = 5;
        int ry = 5;
        textRd->setSchriftSize( schriftGr );
        for( int i = 0; i < wAnz; ++i )
        {
            DiagWert *w = daten->werte->z( i );
            if( w && w->name && hatWertStyle( i, DiagWert::Style::Name ) && hatWertStyle( i, DiagWert::Style::Sichtbar ) )
            {
                int br = textRd->getTextBreite( w->name->getText() );
                zRObj.alphaRegion( rx, ry, br, schriftGr, 0xA0000000 );
                textRd->renderText( rx, ry, w->name->getText(), zRObj, w->farbe );
                ry += 15;
            }
        }
    }
    zRObj.releaseDrawOptions();
    zRObj.releaseDrawOptions();
    zRObj.releaseDrawOptions();
    unlockZeichnung();
}

// constant
Schrift *LDiag::getSchrift() const // Gibt die Schrift zurück
{
    return textRd ? textRd->getSchrift() : 0;
}

Schrift *LDiag::zSchrift() const
{
    return textRd ? textRd->zSchrift() : 0;
}

Rahmen *LDiag::getDatenRahmen() const // Gibt den inneren Rahmen um das eigentliche Diagramm zurück
{
    return dRam ? dynamic_cast<Rahmen *>( dRam->getThis() ) : 0;
}

Rahmen *LDiag::zDatenRahmen() const
{
    return dRam;
}

int LDiag::getDatenRahmenFarbe() const
{
    return dRam ? dRam->getFarbe() : 0;
}

int LDiag::getDatenRahmenBreite() const
{
    return dRam ? dRam->getRBreite() : 0;
}

int LDiag::getDatenHintergrundFarbe() const // Gibt den Hintergrund des eigentlichen Diagramms zurück
{
    return dBgF;
}

Bild *LDiag::getDatenHintergrundBild() const
{
    return dBgB ? dynamic_cast<Bild *>( dBgB->getThis() ) : 0;
}

Bild *LDiag::zDatenHintergrundBild() const
{
    return dBgB;
}

AlphaFeld *LDiag::getDatenAlphaFeld() const // Gibt das AlphaFeld des eigentlichen Diagramms zurück
{
    return dAf ? dynamic_cast<AlphaFeld *>( dAf->getThis() ) : 0;
}

AlphaFeld *LDiag::zDatenAlphaFeld() const
{
    return dAf;
}

int LDiag::getDatenAlphaFeldFarbe() const
{
    return dAf ? dAf->getFarbe() : 0;
}

int LDiag::getDatenAlphaFeldStrength() const
{
    return dAf ? dAf->getStrength() : 0;
}