/*
 * ColorCircle.cpp
 *
 * Copyright (C) 2002 Christian Hanisch
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program (see the file "COPYING" for details); if 
 * not, write to the Free Software Foundation, Inc., 675 Mass Ave, 
 * Cambridge, MA 02139, USA.
 */

#include "ColorCircle.h"

int ColorCircle::SetGetColorPoint(int Color, bool Set)
{
    static int ColorAll=0;

    if (Set)
        ColorAll = Color;
    return ColorAll;
}

void ColorCircle::OldColor(float *Red, float *Green, float *Blue, bool oldcolor)
{
    static float RedValue, GreenValue, BlueValue;

    if (oldcolor) {
        RedValue = *Red;
        GreenValue = *Green;
        BlueValue = *Blue;
    } else {
        *Red = RedValue;
        *Green = GreenValue;
        *Blue = BlueValue;
    }
}

void ColorCircle::SetScrollBars(struct ScrollBars scroll, 
                                       struct TextEdits textedit, 
                                       struct Buttons button)
{
// Hier kann die ScrollBar Groesse und die Button Groesse mit dem Befehl 
// extern void swSetSize(SWND wnd, int width, int height); 
// gesetzt werden.

    swSetPosition(RedScrollBar, scroll.red.x, scroll.red.y);
    swSetPosition(GreenScrollBar, scroll.green.x, scroll.green.y);
    swSetPosition(BlueScrollBar, scroll.blue.x, scroll.blue.y);

    swSetPosition(RedTextEdit, textedit.red.x, textedit.red.y);
    swSetPosition(GreenTextEdit, textedit.green.x, textedit.green.y);
    swSetPosition(BlueTextEdit, textedit.blue.x, textedit.blue.y);

    swSetPosition(OkeyButton, button.okay.x, button.okay.y);
    swSetPosition(CloseButton, button.close.x, button.close.y);
}   

#define X_WINDOWSIZE 300
#define Y_WINDOWSIZE 240

#define X0_POINT -20
#define Y0_POINT 200

#define Y_ABSTAND 20
#define LINKS_FENSTER 60
#define OBEN_FENSTER 60
#define RECHTS_FENSTER 90
#define UNTEN_FENSTER 100 

void ColorCircle::GetPositions(struct window_size* windowback, bool resize)
{
    static struct window_size window = {X0_POINT, Y0_POINT, 
                                         X_WINDOWSIZE, Y_WINDOWSIZE, 0};
    struct ScrollBars scrollbar;
    struct TextEdits textedit;
    struct Buttons button;
    static int x_SetPalette, y_SetPalette;

    if (resize) {
        window.x_window = windowback->x_window;
        window.y_window = windowback->y_window;
        button.okay.x = (window.x_window / 4) - 60; 
        button.okay.y = window.y_window - LINKS_FENSTER; 
        button.close.x = (window.x_window / 2) + 30; 
        button.close.y = window.y_window - LINKS_FENSTER;
        scrollbar.red.x = (window.x_window / 4) - LINKS_FENSTER;
        scrollbar.red.y = window.y_window  - OBEN_FENSTER - 2*Y_ABSTAND;
        scrollbar.green.x = (window.x_window / 4) - LINKS_FENSTER;
        scrollbar.green.y = window.y_window  - OBEN_FENSTER - Y_ABSTAND;
        scrollbar.blue.x = (window.x_window / 4) - LINKS_FENSTER;
        scrollbar.blue.y = window.y_window - OBEN_FENSTER;
        textedit.red.x = (window.x_window / 2) + RECHTS_FENSTER;
        textedit.red.y = window.y_window - UNTEN_FENSTER;
        textedit.green.x = (window.x_window / 2) + RECHTS_FENSTER;
        textedit.green.y = window.y_window  - UNTEN_FENSTER + Y_ABSTAND;
        textedit.blue.x = (window.x_window / 2) + RECHTS_FENSTER;
        textedit.blue.y = window.y_window - UNTEN_FENSTER + 2*Y_ABSTAND;
        SetScrollBars(scrollbar, textedit, button);
    }

    window.x0 = (window.x_window / 2) - 30;

    if (window.x_window>window.y_window*0.4) {
        windowback->Radius = ((window.x_window - window.x0 - OBEN_FENSTER)/ 2);
    } else {
        windowback->Radius = ((window.y_window * 0.4) / 2);
    }
 
    windowback->y0 = (int) windowback->Radius + UPPER_LIMIT;
    windowback->x0 = (window.x_window / 2) + (int) windowback->Radius - 60;

    windowback->x_window = window.x_window;
    windowback->y_window = window.y_window;
}

#ifndef HAVE_RINT
int ColorCircle::Round_float_to_int(float number)
{
    if (number - floor(number) >= 0.5)
        return (int) ceil(number);
    else           
       return (int) floor(number);
}
#endif

int ColorCircle::GetColorFloatToInt(float red, float green, float blue)
{  
    int Color;
    int red_int, green_int, blue_int;

    red_int = Round_float_to_int(red * MAXFARB);
    green_int = Round_float_to_int(green * MAXFARB);
    blue_int = Round_float_to_int(blue * MAXFARB);

    Color = 0;
    Color += (red_int & 0xff);
    Color += (green_int & 0xff) << 8;
    Color += (blue_int & 0xff) << 16;
    return Color;
} 

int ColorCircle::GetBarValue(int y)
{
    struct window_size window;
    int Color, Red, Green, Blue;
    float RedColor=0, GreenColor=0, BlueColor=0;
    float DifRedValue, DifGreenValue, DifBlueValue;
    int y0, y_again, y1;

    GetPositions(&window, false);

    Color = SetGetColorPoint(0, false);
    Red = (Color & 0xff);
    Green = (Color & 0xff00) >> 8;
    Blue = (Color & 0xff0000) >> 16;

    y0 = window.y0 - (int) window.Radius;
    y1 = y - y0;
    y_again = 2 * (int) window.Radius;
        
    if (y1 != 0) { 
        RedColor =  (1 / ((window.Radius * 2) / y1) * (float) Red);
        GreenColor =  (1 / ((window.Radius * 2) / y1) * (float) Green);
        BlueColor =  (1 / ((window.Radius * 2) / y1) * (float) Blue);
        if (Color==0) { 
            RedColor =  (1 / ((window.Radius * 2) / y1) * MAXFARB);
            GreenColor =  (1 / ((window.Radius * 2) / y1) * MAXFARB);
            BlueColor =  (1 / ((window.Radius * 2) / y1) * MAXFARB);
        }
    }

    if ((y <= y_again + y0) && (y >= y0)) {
        Red = (int) RedColor;
        Green = (int) GreenColor;
        Blue = (int) BlueColor;
        if (Red >= MAXFARB + 1)
            Red = MAXFARB;
        if (Green >= MAXFARB + 1)
            Green = MAXFARB;
        if (Blue >= MAXFARB + 1)
            Blue = MAXFARB;
        Color = (Red & 0xff);
        Color += (Green & 0xff) << 8;
        Color += (Blue & 0xff) << 16;

        return Color;  
    } else 
       return -1;
}

void ColorCircle::SetBarValue()
{
    struct window_size window;
    int x0, y0, y_again, i, k, Color;

    GetPositions(&window, false);
    x0 = window.x0 + (int) window.Radius + 30;
    y0 = window.y0 - (int) window.Radius;
    y_again = 2 * (int) window.Radius;

    for (i = y0; i <= y_again + y0; i++) {
        Color = GetBarValue(i);
        swSetFGColor(_dc, Color);
        swDrawLine(_dc, x0, i, x0+VALUEBARWIDTH, i);
    }
}

int ColorCircle::GetColorCircle(int x, int y, struct Colors* colors)
{
    float red, green, blue;
    int Color;
    float alpha;
    float r, r2, R;
    struct window_size window;

    GetPositions(&window, false);

    x = x - window.x0;
    y = y - window.y0;
    R = window.Radius;

    // Winkel berechnen
    alpha = (atan2((float)y, (float)x) * 180.0 / M_PI) + 180;  
   
    // r-achse berechnen (Groesse des Kreises)
    r2 = (x * x) + (y * y);
    r = sqrt(r2);

    // Pruefen ob die Koordinate im Kreis ist
    if (r <= R) {
        float temp = 1 - (r / R);
        if (alpha > BLUEWINKEL) { 
            if (alpha > MAGENTAWINKEL) {
                blue = 1 - alpha / (MAXWINKEL - MAGENTAWINKEL) 
                       + MAGENTAWINKEL / (MAXWINKEL - MAGENTAWINKEL);
                red = 1;
            } else {
                blue = 1;
                red =  alpha / (MAGENTAWINKEL - BLUEWINKEL) 
                        - BLUEWINKEL / (MAGENTAWINKEL - BLUEWINKEL);
            }
            green = temp;
            blue = blue - temp * blue + temp;
            red = red - temp * red + temp;
        } else if (alpha > GREENWINKEL) { // Winkelbereich
            if (alpha > CYANWINKEL) {
                green = 1 - alpha / (BLUEWINKEL - CYANWINKEL) 
                        + CYANWINKEL / (BLUEWINKEL - CYANWINKEL);
                blue = 1;
            } else {
                green = 1;
                blue = alpha / (CYANWINKEL - GREENWINKEL)
                       - GREENWINKEL / (CYANWINKEL - GREENWINKEL);
            }
            red = temp;
            blue = blue - temp * blue + temp;
            green = green - temp * green + temp;
        } else if (alpha > REDWINKEL) { // Winkelbereich
            if (alpha > YELLOWWINKEL) {
                red = 1 - alpha / (GREENWINKEL - YELLOWWINKEL) 
                      + YELLOWWINKEL / ( GREENWINKEL - YELLOWWINKEL);
                green = 1;
            }
            else 
            {
                red = 1;
                green =  alpha / (YELLOWWINKEL - REDWINKEL) 
                         - REDWINKEL / (YELLOWWINKEL - REDWINKEL);
            }
            red= red - temp * red + temp;
            green = green - temp * green + temp;
            blue = temp;
        } 
        Color = 0;
        colors->red = red;
        colors->green = green;
        colors->blue = blue;
        Color = GetColorFloatToInt(red, green, blue);
    } else {
        // 1 - (R / r) *255
        Color = -1;
    }
    // Rueckgabe der Farbe
    return Color;
}

void ColorCircle::SetColorPalette(int Color)
{
    int start_x=20, start_y=UPPER_LIMIT, width_x=50, hight_y=50;

    swSetFGColor(_dc, Color);
    swFillRect(_dc, start_x, start_y, width_x, hight_y);
    swSetFGColor(_dc, 0xffffff);
    swFillRect(_dc, start_x, start_y+hight_y, width_x, hight_y);

    float Red = ((float) (Color & 0xff)) / (float)MAXFARB;
    float Green = ((float) ((Color & 0xff00) >> 8)) / (float)MAXFARB;
    float Blue = ((float) ((Color & 0xff0000) >> 16)) / (float)MAXFARB;
    setColorsViaFieldUpdate(Red,Green,Blue);
}

void ColorCircle::ClearCircleCursor(int x, int y)
{
    struct Colors colors = {0,0,0};
    int i, k, Color;

    for (i = 0; i <= 8; i++) {
        for (k = 0; k <= 8 - 1; k++); // ??????
        {
            Color = GetColorCircle((x + k) - 4, (y + i) - 4, &colors);
            if (Color != -1) {
                Color = GetColorFloatToInt(colors.red, colors.green, 
                                           colors.blue);
                swSetFGColor(_dc, Color);
                swDrawPoint(_dc, (x + k) - 4 , (y + i) - 4);
            } else {   
                swSetFGColor(_dc, swGetWindowColor(canvas, SW_COLOR_WINDOW_BG));
                swDrawPoint(_dc, (x + k) - 4 , (y + i) - 4);
            }
            Color = GetColorCircle((x + i) - 4, (y + k) - 4, &colors);
            if (Color != -1) {
                swSetFGColor(_dc, Color);
                swDrawPoint(_dc, (x + i) - 4 , (y + k) - 4);
            } else {
                swSetFGColor(_dc, swGetWindowColor(canvas, SW_COLOR_WINDOW_BG));
                swDrawPoint(_dc, (x + i) - 4 , (y + k) - 4);
            }
        }
    }
    for (i = 8; i >= 0; i--) {
        for (k = 8; k >= 0 + 1; k--); // ??????
        {
            Color = GetColorCircle((x + k) - 4, (y + i) - 4, &colors);
            if (Color != -1) {
                swSetFGColor(_dc, Color);
                swDrawPoint(_dc, (x + k) - 4 , (y + i) - 4);
            } else {
                swSetFGColor(_dc, swGetWindowColor(canvas, SW_COLOR_WINDOW_BG));
                swDrawPoint(_dc, (x + k) - 4 , (y + i) - 4);
            }    
            Color = GetColorCircle((x + i) - 4, (y + k) - 4, &colors);
            if (Color != -1) {
                swSetFGColor(_dc, Color);
                swDrawPoint(_dc, (x + i) - 4 , (y + k) - 4);
            } else {
                swSetFGColor(_dc, swGetWindowColor(canvas, SW_COLOR_WINDOW_BG));
                swDrawPoint(_dc, (x + i) - 4 , (y + k) - 4);
            }
        }
    }
}

void ColorCircle::DrawCircleCursor(int x, int y)
{
    int i, k;

    swSetFGColor(_dc, 0);
    for (i = 0; i <= 8; i++) {
        for (k = 0; k <= 8 - 1; k++);
        {
            swDrawPoint(_dc, (x + k) - 4 , (y + i) - 4);
            swDrawPoint(_dc, (x + i) - 4 , (y + k) - 4);
        }
    }
    for (i = 8; i >= 0; i--) {
        for (k = 8; k >= 0 + 1; k--);
        {
            swDrawPoint(_dc, (x + k) - 4 , (y + i) - 4);
            swDrawPoint(_dc, (x + i) - 4 , (y + k) - 4);
        }
    }
}

void ColorCircle::SetCircleCursor(int x, int y)
{
    static int xo, yo;

    if ((x != xo) || (y != yo)) {
        ClearCircleCursor(xo, yo);
        DrawCircleCursor(x, y);
        xo = x;
        yo = y;
    }
}

void ColorCircle::GetCircleCursor(int ColorNew)
{
    int Color, ColorIndex, x, y, i, k, again;
    int red, green, blue, Radius, k_merk, i_merk;
    int RedValue, GreenValue, BlueValue;
    struct Colors colors = {0,0,0};
    struct window_size window;
    float minwert=FLT_MAX, absolutwert;
    bool merk=false;

    Color = SetGetColorPoint(5, false);

    RedValue = (Color & 0xff);
    GreenValue = ((Color & 0xff00) >> 8);
    BlueValue = ((Color & 0xff0000) >> 16);

    GetPositions(&window, false);
           
    x = window.x0 - (int) window.Radius;
    y = window.y0 - (int) window.Radius;
    again = 2 * (int) window.Radius;

    i_merk=window.x0;
    k_merk=window.y0;

    for (i = y; i <= again + y; i++) {
        for (k = x; k <= again + x; k++) {
            Color = GetColorCircle(k, i, &colors);
            if (Color != -1) {
                red = Round_float_to_int(colors.red * MAXFARB);
                green = Round_float_to_int(colors.green * MAXFARB);
                blue = Round_float_to_int(colors.blue * MAXFARB);

                if ((RedValue == red) && (GreenValue == green) &&
                    (BlueValue == blue)) {
                    SetCircleCursor(k, i);
                    return;
                } else {
                    absolutwert = (float)fabs((float)(red - RedValue)) + 
                                  (float)fabs((float)(green - GreenValue)) + 
                                  (float)fabs((float)(blue - BlueValue));
                    if (minwert > absolutwert) {
                        minwert = absolutwert;
                        k_merk = k;
                        i_merk = i;
                    }
                }
            }
        }
    }
    SetCircleCursor(k_merk, i_merk);
}

void ColorCircle::SetTextColorsValues(int value)
{
    static float Red = 0, Green = 0, Blue = 0;
    char ColorValue[128];

    SetColorPalette(value);
    Red = (value & 0xff) / ((float)MAXFARB/(float)AUFLOESUNG);
    Green = ((value & 0xff00) >> 8) / ((float)MAXFARB/(float)AUFLOESUNG);
    Blue = ((value & 0xff0000) >> 16) / ((float)MAXFARB/(float)AUFLOESUNG);
    mysnprintf(ColorValue,128," %1.2f", Red / AUFLOESUNG);
    swSetText(RedTextEdit, ColorValue);
    mysnprintf(ColorValue,128," %1.2f", Green / AUFLOESUNG);
    swSetText(GreenTextEdit, ColorValue);
    mysnprintf(ColorValue,128," %1.2f", Blue/ AUFLOESUNG);
    swSetText(BlueTextEdit, ColorValue);
}

void ColorCircle::SetTextValue(float value, SWND textedit)
{
    char ColorValue[128];
     
    mysnprintf(ColorValue,128," %1.2f",value / AUFLOESUNG);
    swSetText(textedit, ColorValue);
}

void ColorCircle::ClearValueBarCursor(int y)
{
    int i, ColorBar=0, x;
    struct window_size window;

    GetPositions(&window, false);

    x = window.x0 + (int) window.Radius + 30;

    ColorBar = GetBarValue(y);

    swSetFGColor(_dc, ColorBar);

    swDrawLine(_dc, x, y, x+VALUEBARWIDTH, y);
}

void ColorCircle::DrawValueBarCursor(int y, int Color)
{
    int x_again = VALUEBARWIDTH, i, ColorBar=0, x, ColorTemp;
    int Red, Green, Blue;
    struct window_size window;
    float win;

    GetPositions(&window, false);

    ColorTemp = SetGetColorPoint(0, false);
    Red = (ColorTemp & 0xff);
    Green = (ColorTemp & 0xff00) >> 8;
    Blue = (ColorTemp & 0xff0000) >> 16;

    ColorBar = Color ^ 0xffffff; 

    x = window.x0 + (int) window.Radius + 30;
    x_again = VALUEBARWIDTH;

    swSetFGColor(_dc, ColorBar);

    for (i = x; i <= x + x_again; i++)
        swDrawPoint(_dc, i , y);

    win = (float) y;
          
    win -= ((float)window.y0 - window.Radius);
          
    win /= (2 * window.Radius);
    win *= AUFLOESUNG;
          
    y = Round_float_to_int(win);
}

void ColorCircle::SetBarValueCursor(int y, int Color)
{
    static int yo=10;
    struct window_size window;

    GetPositions(&window, false);
          
    if (y != yo) {
        ClearValueBarCursor(yo);
        DrawValueBarCursor(y, Color);
        yo = y;
    }
}

static void RedTextEditInputCB(void *data, int command)
{
    ((ColorCircle *) data)->RedTextEditInput(command);
}

void
ColorCircle::RedTextEditInput(int command)
{
    char TextInput[10];
    float RedValue, RedColorTemp, Red;
    double Value; 
    int Color;
    bool Valuemerk;
          
    swGetText(RedTextEdit, TextInput, 10);
    Value = atof(TextInput);

    RedValue = (float) Value * AUFLOESUNG;
    Color = SetGetColorPoint(5, false);
    Red = ((float) (Color & 0xff)) / ((float)MAXFARB / (float)AUFLOESUNG);
    Color = (Color & 0xff) ^ Color;
    RedColorTemp = (float) Color;
    RedColorTemp += ((RedValue) * ((float)MAXFARB/(float)AUFLOESUNG));
    Color += (int) RedColorTemp;

    if ((RedValue <= AUFLOESUNG) && (RedValue >= 0.0)) {
        SetTextValue(RedValue, RedTextEdit);
        swScrollBarSetValue(RedScrollBar, (int) RedValue);
        SetGetColorPoint(Color, true);
        SetColorPalette(Color);
        SetBarValue();
        GetCircleCursor(Color);              
    } else {
        SetTextValue(Red, RedTextEdit);
    }          
}


static void GreenTextEditInputCB(void *data, int command)
{
    ((ColorCircle *) data)->GreenTextEditInput(command);
}

void
ColorCircle::GreenTextEditInput(int command)
{
    char TextInput[10];
    float GreenValue, GreenColorTemp, Green;
    double Value; 
    int Color, GreenColor;
    bool Valuemerk;
    swGetText(GreenTextEdit, TextInput, 10);
    Value = atof(TextInput);
    GreenValue = (float) Value * AUFLOESUNG;
                   
    Color = SetGetColorPoint(0, false);
    Green = ((float) ((Color & 0xff00) >> 8)) / 
                      ((float)MAXFARB / (float)AUFLOESUNG);
    Color = (Color & 0xff00) ^ Color;
    GreenColorTemp = GreenValue * ((float)MAXFARB/(float)AUFLOESUNG);
    GreenColor = (int) GreenColorTemp;
    Color += (GreenColor << 8);     
          
    if ((GreenValue <= AUFLOESUNG) && (GreenValue >= 0.0)) {
        SetTextValue(GreenValue, GreenTextEdit);
        swScrollBarSetValue(GreenScrollBar, (int) GreenValue);
        SetGetColorPoint(Color, true);
        SetColorPalette(Color);
        SetBarValue();
        GetCircleCursor(Color);              
    } else {
        SetTextValue(Green, GreenTextEdit);
    }
}


static void BlueTextEditInputCB(void *data, int command)
{
    ((ColorCircle *) data)->BlueTextEditInput(command);
}

void
ColorCircle::BlueTextEditInput(int command)
{
    char TextInput[10];
    float BlueValue, BlueColorTemp, Blue;
    double Value; 
    int Color, BlueColor;
    bool Valuemerk;
          
    swGetText(BlueTextEdit, TextInput, 10);
    Value = atof(TextInput);
    BlueValue = Value * AUFLOESUNG;
                    
    Color = SetGetColorPoint(0, false);
    Blue = ((float) ((Color & 0xff0000) >> 16)) / 
                     ((float)MAXFARB / (float)AUFLOESUNG);
    Color = (Color & 0xff0000) ^ Color;
    BlueColorTemp = BlueValue * ((float)MAXFARB / (float)AUFLOESUNG);
    BlueColor = (int) BlueColorTemp;

    Color += (BlueColor << 16);     

    if ((BlueValue <= AUFLOESUNG) && (BlueValue >= 0.0)) {
        SetTextValue(BlueValue, BlueTextEdit);
        swScrollBarSetValue(BlueScrollBar, (int) BlueValue);
        SetGetColorPoint(Color, true);
        SetColorPalette(Color);
        SetBarValue();
        GetCircleCursor(Color);              
    } else {
        SetTextValue(Blue, BlueTextEdit);
    }       
}

static void CloseButtonCB(void *data, int id)
{
    ((ColorCircle *) data)->CloseButtonCallback(id);
}

void
ColorCircle::CloseButtonCallback(int id)
{
    float RedValue, GreenValue, BlueValue;

    OldColor(&RedValue, &GreenValue, &BlueValue, false);
          
    setColorsViaFieldUpdate(RedValue, GreenValue, BlueValue);

    _scene->UpdateViews(this, UPDATE_CLOSE_COLOR_CIRCLE);
}

static void OkeyButtonCB(void *data, int id)
{
    ((ColorCircle *) data)->OkeyButtonCallback(id);
}

void
ColorCircle::OkeyButtonCallback(int id)
{
    float RedValue, GreenValue, BlueValue;
    int Color;

    _scene->UpdateViews(this, UPDATE_CLOSE_COLOR_CIRCLE);
}

void ColorCircle::SetValue_ScrollBar(int Color)
{
    int Red, Green, Blue;
    float ColorTemp;
                    
    Red = (Color & 0xff);
    Green = (Color >> 8) & 0xff;
    Blue = (Color >> 16) & 0xff;          
          
    ColorTemp = (float) Red;
    ColorTemp /= ((float)MAXFARB/(float)AUFLOESUNG);
    Red = (int) ColorTemp;
    ColorTemp = (float) Green;
    ColorTemp /= ((float)MAXFARB/(float)AUFLOESUNG);
    Green = (int) ColorTemp;
    ColorTemp = (float) Blue;
    ColorTemp /= ((float)MAXFARB/(float)AUFLOESUNG);
    Blue = (int) ColorTemp;

    swScrollBarSetValue(RedScrollBar, Red);  
    swScrollBarSetValue(GreenScrollBar, Green);  
    swScrollBarSetValue(BlueScrollBar, Blue);
}

static void RedScrollCB(void *data, int type, int value)
{
    ((ColorCircle *) data)->RedScrollCallback(type,value);
}

void
ColorCircle::RedScrollCallback(int type, int value)
{
    int i, k;
    int Color;
    float value_float, ColorTemp;
    bool Valuemerk;

    SFONT font = swFindFont("helvetica", SW_PLAIN, 14);

    Color = SetGetColorPoint(5, false);
    ColorTemp = (Color & 0xff) ^ Color;
    ColorTemp += (float) (value * ((float)MAXFARB/(float)AUFLOESUNG));
    Color = (int) ColorTemp;
    SetGetColorPoint(Color, true);
    SetColorPalette(Color);
          
    value_float = (float) value;

    SetTextValue(value_float, RedTextEdit);
    SetBarValue();
    GetCircleCursor(Color);              
}


static void GreenScrollCB(void *data, int type, int value)
{
    ((ColorCircle *) data)->GreenScrollCallback(type,value);
}

void
ColorCircle::GreenScrollCallback(int type, int value)
{  
    int Color, GreenColor;
    float value_float, GreenColorTemp;
    bool Valuemerk;

    SFONT font = swFindFont("helvetica", SW_PLAIN, 14);

    Color = SetGetColorPoint(0, false);
    Color = (Color & 0xff00) ^ Color;
    GreenColorTemp = (float) value;
    GreenColorTemp *= ((float)MAXFARB / (float)AUFLOESUNG);
    GreenColor = (int) GreenColorTemp;
    Color += (GreenColor << 8);     
    SetGetColorPoint(Color, true);
    SetColorPalette(Color);

    value_float = (float) value;
          
    SetTextValue(value_float, GreenTextEdit);
    SetBarValue();
    GetCircleCursor(Color);              
}


static void BlueScrollCB(void *data, int type, int value)
{
    ((ColorCircle *) data)->BlueScrollCallback(type,value);
}

void
ColorCircle::BlueScrollCallback(int type, int value)
{
    int Color, BlueColor;
    float value_float, BlueColorTemp;
    bool Valuemerk;

    SFONT font = swFindFont("helvetica", SW_PLAIN, 14);

    Color = SetGetColorPoint(5, false);
    Color = (Color & 0xff0000) ^ Color;
    BlueColorTemp = (float) value;
    BlueColorTemp *= ((float)MAXFARB/(float)AUFLOESUNG);
    BlueColor = (int) BlueColorTemp;
    Color += (BlueColor << 16);
    SetGetColorPoint(Color, true);
    SetColorPalette(Color);
    
    value_float = (float) value;

    SetTextValue(value_float, BlueTextEdit);
    SetBarValue();
    GetCircleCursor(Color);              
}

void ColorCircle::SetCircle() {
    struct window_size window;
    struct Colors colors = {0,0,0};
    int Color, i, k, x0, y0, again, Radius;

    GetPositions(&window, false);
    
    Radius = (int) window.Radius;
    x0 = window.x0 - Radius;                                        
    y0 = window.y0 - Radius;          
    again = 2 * Radius;

    for (i = y0; i <= again + y0; i++) {
        for (k = x0; k <= again + x0; k++) {
            Color = GetColorCircle(k, i, &colors);
            if (Color != -1) {
                swSetFGColor(_dc, Color);
                swDrawPoint(_dc, k , i);
            }  
        }
    }
}

static void mouseCB(void *data, int x, int y, int modifiers)
{
    ((ColorCircle *) data)->mouseCallback(x, y, modifiers);
}

void
ColorCircle::mouseCallback(int x, int y, int modifiers)
{
    int Color, ColorTemp, x0, y0, x3 , y3;
    struct window_size window;
    struct Colors colors = {0,0,0};
    float r, r2, x1, y1, x2, y2;
    static bool CircleMerk=false, ValueBarMerk=false;
    int x_again, y_again;

    if (drawing) {
        GetPositions(&window, false);
        x0 = x;
        y0 = y;

        x3 = x - window.x0;                                        
        y3 = y - window.y0;          
                                          
        // r-achse berechnen (Groesse des Kreises)
        r2 = (x3 * x3) + (y3 * y3);
        r = sqrt(r2);                    

        // Pruefen ob die Koordinate im Kreis ist
        if (!ValueBarMerk)
            if ((r <= window.Radius) || (CircleMerk)) {
                CircleMerk = true;
                if (r <= window.Radius) {
                    ColorTemp = GetColorCircle(x0, y0, &colors);
                    if (ColorTemp != -1)
                        Color = ColorTemp;
                    SetGetColorPoint(Color, true);
                    SetValue_ScrollBar(Color);
                    SetTextColorsValues(Color);
                    SetCircleCursor(x3 + window.x0, y3 + window.y0);
                    SetBarValue();
                } else {
                    x1 = (float) x0 - (float) window.x0;
                    y1 = (float) y0 - (float) window.y0;
                    x2 = window.x0 + ((x1 * window.Radius) / 
                                      (sqrt((x1 * x1) + (y1 * y1))));
                    y2 = window.y0 + ((y1 * window.Radius) /
                                      (sqrt((x1 * x1) + (y1 * y1))));
                    SetCircleCursor((int) x2, (int) y2);
                    ColorTemp = GetColorCircle((int) x2, (int) y2, &colors);
                    if (ColorTemp != -1)
                        Color = ColorTemp;
                    SetGetColorPoint(Color, true);
                    SetValue_ScrollBar(Color);
                    SetTextColorsValues(Color);
                } 
            }
        x0 = window.x0 + (int) window.Radius + 30;
        y0 = window.y0 - (int) window.Radius;          
        x_again = VALUEBARWIDTH;
        y_again = 2 * (int) window.Radius;

        if (!CircleMerk)
            if (((y <= y_again + y0) && (y > y0)) && 
                ((x <= x_again + x0) && (x >= x0)) ||
                (ValueBarMerk) && ((y <= y_again + y0) && (y > y0))) {          
                ColorTemp = GetBarValue(y);
                if (ColorTemp != -1)
                    Color = ColorTemp;
                ValueBarMerk = true;
                SetValue_ScrollBar(Color);
                SetTextColorsValues(Color);
                SetBarValueCursor(y, Color);
                SetColorPalette(Color);
            } 
    } else {
        if (CircleMerk)
            SetBarValue();
        CircleMerk = false;
        ValueBarMerk = false;
    }          
}

static void keyCB(void *data, int key, int state, int x, int y, int modifiers)
{
    ((ColorCircle *) data)->keyCallback(key, state, x, y, modifiers);
}

void
ColorCircle::keyCallback(int key, int state, int x, int y, int modifiers)
{
    if (key == SW_MOUSE1) {
        drawing = state;
        mouseCallback(x, y, modifiers);
    }
}

static void resizeCB(void *data, int x, int y)
{
    ((ColorCircle *) data)->resizeCallback(x, y);
}


void
ColorCircle::resizeCallback(int x, int y)
{
    int Color;
    struct Colors colors = {0,0,0};
    struct window_size window;
          
    swSetFGColor(_dc, swGetWindowColor(canvas, SW_COLOR_WINDOW_BG));
    swFillRect(_dc, 0, 0, x, y);

    window.x_window = x;
    window.y_window = y;

    GetPositions(&window, true);
}

static void exposeCB(void *data, int x, int y, int width, int height)
{
    ((ColorCircle *) data)->exposeCallback(x, y, width, height);
}

void
ColorCircle::exposeCallback(int x, int y, int width, int height)
{
    int Color, x0, y0;
    struct Colors colors = {0,0,0};

    swSetFGColor(_dc, swGetWindowColor(canvas, SW_COLOR_WINDOW_BG));
    swFillRect(_dc, x, y, width, height);
          
    Color = SetGetColorPoint(0, false);
    SetGetColorPoint(Color, true);
    SetValue_ScrollBar(Color);
    SetTextColorsValues(Color);
    SetColorPalette(Color);
    SetCircle();
    SetBarValue();
}

ColorCircle::ColorCircle(Scene *scene, SWND parent, FieldUpdate* fieldUpdate)
                        : SceneView(scene, parent)
{
    int                    width, height;

    swGetSize(parent, &width, &height);
    drawing = 0;
    canvas = parent;
    _fieldUpdate=fieldUpdate;
    _dc = NULL;

    int ScrollBarWidth = 200;
    int ScrollBarHeight = 15;
    int TextEditWidth = 30;
    int TextEditHeight = 15;
    int ButtonWidth = 80;
    
    int Color, ColorTemp;

    swSetClientData(canvas,this);
    swSetExposeCallback(canvas, exposeCB);
    swSetKeyCallback(canvas, keyCB);
    swSetMouseCallback(canvas, mouseCB);

    CloseButton = swCreateButton("Close", 180,  
                                 Y_ScrollBar_TextEdit + 3* Y_ABSTAND, 
                                 ButtonWidth, 
                                 20, canvas);
    swSetClientData(CloseButton,this);
    swSetCommandCallback(CloseButton, CloseButtonCB);

    OkeyButton = swCreateButton("OK", 20,  
                                 Y_ScrollBar_TextEdit + 
                                 3* Y_ABSTAND, 
                                 ButtonWidth, 20, canvas);
    swSetClientData(OkeyButton,this);
    swSetCommandCallback(OkeyButton, OkeyButtonCB);

    RedScrollBar = swCreateScrollBar(SW_HORIZONTAL, 
                                     X_ScrollBar, 
                                     Y_ScrollBar_TextEdit, 
                                     ScrollBarWidth, ScrollBarHeight, 
                                     0, AUFLOESUNG + ScrollBarVisit, 
                                     0, ScrollBarVisit,
                                     canvas);
    swSetClientData(RedScrollBar,this);
    swSetScrollBarCallback(RedScrollBar, RedScrollCB);

    GreenScrollBar = swCreateScrollBar(SW_HORIZONTAL, 
                                       X_ScrollBar, 
                                       Y_ScrollBar_TextEdit + Y_ABSTAND, 
                                       ScrollBarWidth, ScrollBarHeight, 
                                       0, AUFLOESUNG + ScrollBarVisit,
                                       0, ScrollBarVisit, canvas);
    swSetClientData(GreenScrollBar,this);
    swSetScrollBarCallback(GreenScrollBar, GreenScrollCB);

    BlueScrollBar = swCreateScrollBar(SW_HORIZONTAL, 
                                      X_ScrollBar, 
                                      Y_ScrollBar_TextEdit + 2 * Y_ABSTAND, 
                                      ScrollBarWidth, ScrollBarHeight, 
                                      0, AUFLOESUNG + ScrollBarVisit,
                                      0, ScrollBarVisit, canvas);
    swSetClientData(BlueScrollBar,this);
    swSetScrollBarCallback(BlueScrollBar, BlueScrollCB);

    RedTextEdit = swCreateTextEdit(SW_SINGLE_LINE, X_TEXTEDIT, 
                                   Y_ScrollBar_TextEdit, 
                                   TextEditWidth, TextEditHeight, canvas); 
    swTextEditSetSelection(RedTextEdit, 1, 4);
    swSetClientData(RedTextEdit,this);
    swSetCommandCallback(RedTextEdit, RedTextEditInputCB);          

    GreenTextEdit = swCreateTextEdit(SW_SINGLE_LINE, X_TEXTEDIT, 
                                     Y_ScrollBar_TextEdit + Y_ABSTAND, 
                                     TextEditWidth, TextEditHeight, canvas);   
    swTextEditSetSelection(GreenTextEdit, 1, 4);
    swSetClientData(GreenTextEdit,this);
    swSetCommandCallback(GreenTextEdit, GreenTextEditInputCB);

    BlueTextEdit = swCreateTextEdit(SW_SINGLE_LINE, X_TEXTEDIT, 
                                    Y_ScrollBar_TextEdit + 2* Y_ABSTAND, 
                                    TextEditWidth, TextEditHeight, canvas);
    swTextEditSetSelection(BlueTextEdit, 1, 4);
    swSetClientData(BlueTextEdit,this);
    swSetCommandCallback(BlueTextEdit, BlueTextEditInputCB);          

    float RedValue, GreenValue, BlueValue;

    getColorsFromFieldUpdate(RedValue,GreenValue,BlueValue);

    OldColor(&RedValue, &GreenValue, &BlueValue, true);
    
    Color = Round_float_to_int((RedValue) * ((float)MAXFARB));
    ColorTemp = Round_float_to_int((GreenValue) * ((float)MAXFARB));
    Color += ColorTemp << 8;
    ColorTemp = Round_float_to_int((BlueValue) * ((float)MAXFARB));
    Color += ColorTemp << 16;
    
    SetGetColorPoint(Color, true);    

    if (_dc==NULL) 
       _dc = swCreateDC(_wnd);
    swSetFGColor(_dc, swGetWindowColor(canvas, SW_COLOR_WINDOW_BG));
    swFillRect(_dc, 0, 0, width, height);
}

void ColorCircle::getColorsFromFieldUpdate(float& r, float& g, float &b)
{
    // get colors from FieldUpdate hint

    FieldValue *value;
    Node *node = _fieldUpdate->node;
    if (_fieldUpdate->index == -1) {
        value = node->getField(_fieldUpdate->field);
    } else {
        MFieldValue *val = (MFieldValue *) node->getField(_fieldUpdate->field);
        value = val->getSFValue(_fieldUpdate->index);           
    }
    r=((SFColor*) value)->getValue(0);
    g=((SFColor*) value)->getValue(1);
    b=((SFColor*) value)->getValue(2);
}

void ColorCircle::setColorsViaFieldUpdate(float& r, float& g, float &b)
{
    // set colors via FieldUpdate hint

    SFColor newVal(r,g,b);
    FieldValue* newValue=&newVal;
    Node *node = _fieldUpdate->node;
    if (_fieldUpdate->index == -1) {
       _scene->backupField(node, _fieldUpdate->field);
       _scene->setField(node, _fieldUpdate->field, new SFColor(r,g,b));
    } else {
       MFieldValue *value = (MFieldValue *) node->getField(_fieldUpdate->field);
       value->setSFValue(_fieldUpdate->index, newValue);
       _scene->UpdateViews(NULL, UPDATE_FIELD, (Hint *) _fieldUpdate);
    }
}

void ColorCircle::DeleteView()
{
    int width, height;

    swGetSize(canvas, &width, &height);
    swSetFGColor(_dc, swGetWindowColor(canvas, SW_COLOR_WINDOW_BG));
    swFillRect(_dc, 0, 0, width, height);

    swDeleteCallbacks(RedScrollBar);
    swDestroyWindow(RedScrollBar);
    RedScrollBar=NULL;

    swDeleteCallbacks(GreenScrollBar);
    swDestroyWindow(GreenScrollBar);
    GreenScrollBar=NULL;

    swDeleteCallbacks(BlueScrollBar);
    swDestroyWindow(BlueScrollBar);
    BlueScrollBar=NULL;

    swDeleteCallbacks(CloseButton);
    swDestroyWindow(CloseButton);
    CloseButton=NULL;

    swDeleteCallbacks(OkeyButton);
    swDestroyWindow(OkeyButton);
    OkeyButton=NULL;

    swDeleteCallbacks(RedTextEdit);
    swDestroyWindow(RedTextEdit); 
    RedTextEdit=NULL;
    swDeleteCallbacks(GreenTextEdit);
    swDestroyWindow(GreenTextEdit);
    GreenTextEdit=NULL; 
    swDeleteCallbacks(BlueTextEdit);
    swDestroyWindow(BlueTextEdit);
    BlueTextEdit=NULL;

    swDestroyDC(_dc);
    _dc=NULL;

    swDeleteCallbacks(canvas);
}
