/*
 *    File colpick.c
 *      Demonstrates the use of colors
 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>

#include "mgui.h"

void CloseColPickCB(MOBJECT p, void *s, void *v);
void RefreshColPickCB(MOBJECT p, void *s, void *v);
void ChangeColorCellCB(MOBJECT o, MVALUE s, void *v);
void ColorAssignCB(MOBJECT o, void *s, void *v);
void TextColorAssignCB(MOBJECT o, MVALUE s, void *v);
void ColorPickCB(MOBJECT o, void *s, void *v);
void ColorSaveCB(MOBJECT o, void *s, void *v);
void ColorFreeCB(MOBJECT o, void *s, void *v);
void ScreenInfoCB(MOBJECT o, void *s, void *v);
void CellExposeCB(MOBJECT o, MEvent * pe, void *a_data);
void CellResizeCB(MOBJECT o, DRAWAREA_PREF * pref, void *a_data);
void ColorMapExposeCB(MOBJECT o, MEvent * pexp, void *a_data);
void ColorMapInputCB(MOBJECT o, MEvent * pe, void *a_data);
void ColorMapResizeCB(MOBJECT o, DRAWAREA_PREF * pref, void *a_data);

extern MTColor black, white, darkblue, cadetblue, seagreen;
extern int PaletteMode;
extern long NColors;

static MOBJECT r_sbar, g_sbar, b_sbar, cell_form, cell_label;
static MOBJECT r_label, g_label, b_label, drawa, cell_drawa;
static MTColor cell_color, label_fgc;
static int sel_cell, sel_x, sel_y, r_c, g_c, b_c;

static MTColor drawarea_bgc;

void 
ColPickCB(MOBJECT o, void *a, void *v)
{
    MOBJECT shell, form, obj, pb, form2, form3, label;
    int r, g, b;

    MGetDefaultBackgroundRGB(&r, &g, &b);
    drawarea_bgc = MAllocColor(r, g, b);

    shell = MCreateShell("MGUI Color Browser", 0);

    form2 = MCreateColForm(shell);

    MFormSetSpacing(form2, 0);

    form = MCreateRowForm(form2);
    MBottomAttach(form, F_ATT_NONE, 0, NULL);
    form3 = MCreateRowForm(form);
    cell_form = form3;

    MFormSetSpacing(form3, 10);
    MObjectSetShadow(form3, WS_ETCHED_IN, 2, 2);

    label = MCreateLabel(form3, "Label", TIMES_MEDIUM);
    cell_label = label;
    label_fgc = black;
    MObjectSetShadow(label, WS_ETCHED_IN, 1, 3);

    pb = MCreateRButton(form, "&Black Text", TIMES_N_FONT);
    MRButtonSetCallback(pb, TextColorAssignCB, (void *) 0L);
    MRButtonActivate(pb);
    pb = MCreateRButton(form, "&White Text", TIMES_N_FONT);
    MRButtonSetCallback(pb, TextColorAssignCB, (void *) 1);

    pb = MCreatePButton(form, "Assign to &form", TIMES_MEDIUM);
    MPButtonSetCallback(pb, ColorAssignCB, cell_form);
    pb = MCreatePButton(form, "Assign to &label", TIMES_MEDIUM);
    MPButtonSetCallback(pb, ColorAssignCB, cell_label);

    obj = pb;
    pb = MCreatePButton(form, "&Pick from form", TIMES_MEDIUM);
    MTopAttach(pb, F_ATT_OBJ, 10, obj);
    MPButtonSetCallback(pb, ColorPickCB, cell_form);
    pb = MCreatePButton(form, "P&ick from label", TIMES_MEDIUM);
    MPButtonSetCallback(pb, ColorPickCB, cell_label);

    if (PaletteMode)
    {
	form = MCreateRowForm(form2);
	MFormSetFocusHighlight(form, True);
	drawa = MCreateDrawArea(form, 208, 208);
	MObjectSetResize(drawa, True, True);
	MDrawAreaSetExposeCallback(drawa, ColorMapExposeCB, 0L);
	MDrawAreaSetInputCallback(drawa, ColorMapInputCB, 0L);
	MDrawAreaSetResizeCallback(drawa, ColorMapResizeCB, 0L);
	form = MCreateColForm(form);
	MFormSetSpacing(form, 0);
	MObjectSetShadow(form, WS_NONE, 0, 0);
	pb = MCreatePButton(form, "Save Color", TIMES_MEDIUM);
	MPButtonSetCallback(pb, ColorSaveCB, 0L);
	pb = MCreatePButton(form, "Free Color", TIMES_MEDIUM);
	MPButtonSetCallback(pb, ColorFreeCB, 0L);

    }

    form = MCreateRowForm(shell);
    cell_drawa = MCreateDrawArea(form, 256, 30);
    MDrawAreaSetExposeCallback(cell_drawa, CellExposeCB, 0L);
    MDrawAreaSetResizeCallback(cell_drawa, CellResizeCB, 0L);
    MObjectSetResize(cell_drawa, True, False);
    r_c = g_c = b_c = 0;
    cell_color = MAllocCell(0, 0, 0);

    form2 = MCreateRowForm(form);
    MFormSetPrefAtt(form2, F_PREF_ATT_COL);
    label = MCreateLabel(form2, "Red:   ", FIXED_MEDIUM);
    r_label = MCreateLabel(form2, "00", FIXED_MEDIUM);
    MObjectSetResize(label, False, False);
    MObjectSetResize(r_label, False, False);
    r_sbar = MCreateScrollBar(form2, SBT_HOR, (long) 32, (long) 255 + 32);
    MScrollBarSetPosCallback(r_sbar, ChangeColorCellCB, 0L);

    form2 = MCreateRowForm(form);
    MFormSetPrefAtt(form2, F_PREF_ATT_COL);
    label = MCreateLabel(form2, "Green: ", FIXED_MEDIUM);
    g_label = MCreateLabel(form2, "00", FIXED_MEDIUM);
    MObjectSetResize(label, False, False);
    MObjectSetResize(g_label, False, False);
    g_sbar = MCreateScrollBar(form2, SBT_HOR, (long) 32, (long) 255 + 32);
    MScrollBarSetPosCallback(g_sbar, ChangeColorCellCB, (void *) 1);

    form2 = MCreateRowForm(form);
    MFormSetPrefAtt(form2, F_PREF_ATT_COL);
    label = MCreateLabel(form2, "Blue:  ", FIXED_MEDIUM);
    b_label = MCreateLabel(form2, "00", FIXED_MEDIUM);
    MObjectSetResize(label, False, False);
    MObjectSetResize(b_label, False, False);
    b_sbar = MCreateScrollBar(form2, SBT_HOR, (long) 32, (long) 255 + 32);
    MScrollBarSetPosCallback(b_sbar, ChangeColorCellCB, (void *) 2);

    form = MCreateColForm(shell);

    pb = MCreatePButton(form, "Screen Info", TIMES_MEDIUM);
    MPButtonSetCallback(pb, ScreenInfoCB, NULL);

    pb = MCreatePButton(form, "Close", TIMES_MEDIUM);
    MPButtonSetCallback(pb, CloseColPickCB, shell);

    sel_cell = sel_x = sel_y = 0;
    MShellRealize(shell);
}

void 
ChangeColorCellCB(MOBJECT o, MVALUE o_data, void *a_data)
{
    char str[16];

    switch ((int) a_data)
    {
    case 0:
	r_c = (int) o_data;
	sprintf(str, "%02x", r_c);
	MObjectSetText(r_label, str);
	break;
    case 1:
	g_c = (int) o_data;
	sprintf(str, "%02x", g_c);
	MObjectSetText(g_label, str);
	break;
    case 2:
	b_c = (int) o_data;
	sprintf(str, "%02x", b_c);
	MObjectSetText(b_label, str);
	break;
    }
    if (PaletteMode)
	MSetCellColor(cell_color, r_c, g_c, b_c);
    else
	MObjectSetBackgroundRGB(cell_drawa, r_c, g_c, b_c);
}

void 
ColorAssignCB(MOBJECT o, void *o_data, void *a_data)
{
    MObjectSetBackgroundRGB((MOBJECT) a_data, r_c, g_c, b_c);

#ifdef WINDOWS
/*
 *   Windows palette is indirect, so it is
 *   necessary to redraw rectangles with a new color
 */
    if (PaletteMode)
	ColorMapExposeCB(drawa, NULL, 0L);
#endif
}

void 
TextColorAssignCB(MOBJECT o, MVALUE o_data, void *a_data)
{
    if (o_data)
    {
	label_fgc = (a_data ? white : black);
	MObjectSetColor(cell_label, MObjectBackgroundColor(cell_label), label_fgc);
    }
}

void 
ColorPickCB(MOBJECT o, void *o_data, void *a_data)
{
    MOBJECT p = (MOBJECT) a_data;
    int r, g, b;

    MQueryColor(MObjectBackgroundColor(p), &r, &g, &b);
    MScrollBarSetPos(r_sbar, (long) r);
    MScrollBarSetPos(g_sbar, (long) g);
    MScrollBarSetPos(b_sbar, (long) b);
}

void 
ColorSaveCB(MOBJECT o, void *o_data, void *a_data)
{
    MAllocCell(r_c, g_c, b_c);
#ifdef WINDOWS
/*
 *   Windows palette is indirect, so it is
 *   necessary to redraw rectangles with a new color
 */
    if (PaletteMode)
	ColorMapExposeCB(drawa, NULL, 0L);
#endif
}

void 
ColorFreeCB(MOBJECT o, void *o_data, void *a_data)
{
    if (sel_cell != (int) cell_color)
    {
	MSetCellColor(sel_cell, 0, 0, 0);
	MFreeCell(sel_cell);
    }
}

void 
CloseColPickCB(MOBJECT obj, void *s, void *v)
{
    MOBJECT p;

    MFreeColor(drawarea_bgc);
    MFreeCell(cell_color);
    p = MObjectShell(obj);

    MShellUnrealize(p);
    MShellDestroy(p);
}

void 
CellExposeCB(MOBJECT obj, MEvent * pexp, void *a_data)
{
    int hsize, wsize;

    wsize = MObjectGetWidth(obj);
    hsize = MObjectGetHeight(obj);
    if (PaletteMode)
	MDrawFilledBox(obj, 0, 0, wsize, hsize, cell_color);
}

void 
CellResizeCB(MOBJECT obj, DRAWAREA_PREF * pref, void *a_data)
{
    pref->new_h = pref->old_h;
}

void 
ColorMapExposeCB(MOBJECT obj, MEvent * pexp, void *a_data)
{
    int n, hsize, wsize, i, j;

    n = (NColors == 16 ? 4 : 16);
    wsize = MObjectGetWidth(obj) / n;
    hsize = MObjectGetHeight(obj) / n;
    for (i = 0; i < n; i++)
	for (j = 0; j < n; j++)
	    MDrawFilledBox(obj, wsize * j + 1, hsize * i + 1, wsize - 2, hsize - 2, i * n + j);
    MDrawBox(obj, sel_x, sel_y, wsize, hsize, white);
}

void 
ColorMapResizeCB(MOBJECT obj, DRAWAREA_PREF * pref, void *a_data)
{
    int n, new_hsize, new_wsize, old_hsize, old_wsize;

    n = (NColors == 16 ? 4 : 16);
    old_wsize = pref->old_w / n;
    old_hsize = pref->old_h / n;
    new_wsize = pref->new_w / n;
    new_hsize = pref->new_h / n;
    sel_x = (sel_x * new_wsize) / old_wsize;
    sel_y = (sel_y * new_hsize) / old_hsize;
    pref->new_w = new_wsize * n;
    pref->new_h = new_hsize * n;
}

void 
ColorMapInputCB(MOBJECT obj, MEvent * pe, void *a_data)
{
    int n, hsize, wsize;
    int r, g, b, old_x, old_y;

    n = (NColors == 16 ? 4 : 16);
    wsize = MObjectGetWidth(obj) / n;
    hsize = MObjectGetHeight(obj) / n;
    old_x = sel_x;
    old_y = sel_y;
    if (pe->type == E_KEY_PRESS)
    {
	switch (pe->key.keycode)
	{
	case U_A:
	    sel_cell -= n;
	    if (sel_cell < 0)
		sel_cell += (int) NColors;
	    break;
	case D_A:
	    sel_cell += n;
	    if (sel_cell > NColors)
		sel_cell -= (int) NColors;
	    break;
	case R_A:
	    if (++sel_cell >= (int) NColors)
		sel_cell = 0;
	    break;
	case L_A:
	    if (--sel_cell < 0)
		sel_cell = (int) NColors - 1;
	    break;
	default:
	    return;
	}
	sel_x = (sel_cell % n) * wsize;
	sel_y = (sel_cell / n) * hsize;
    }
    else if (pe->type == E_BUTTON_PRESS)
    {
	sel_x = (pe->mouse.x / wsize) * wsize;
	sel_y = (pe->mouse.y / hsize) * hsize;
	sel_cell = sel_x / wsize + sel_y / hsize * n;
    }
    else
	return;
    MDrawBox(obj, old_x, old_y, wsize, hsize, drawarea_bgc);
    MDrawBox(obj, sel_x, sel_y, wsize, hsize, white);
    MQueryColor(sel_cell, &r, &g, &b);
    MScrollBarSetPos(r_sbar, (long) r);
    MScrollBarSetPos(g_sbar, (long) g);
    MScrollBarSetPos(b_sbar, (long) b);
}

void 
ScreenInfoCB(MOBJECT o, void *s, void *v)
{
    char buff[256];

    sprintf(buff, "Width: %d\nHeight: %d\nColors: %ld\nPlanes: %d",
	    MGetScreenWidth(),
	    MGetScreenHeight(),
	    MGetNColors(),
	    MGetNPlanes());
    MMessageDialog("Screen Information", buff, " Ok ", NULL);
}
