/*
**  (C) Copyright 1989, 1990
**  Micro Data Base Systems Inc.
**  Lafayette, Indiana
*/
subclass(Window,
         #Bezier,
         #(isButton1Down,
           isButton2Down,
           end1,
           control1,
           end2,
           control2),
         true, true, false);
$

/* Initialize the window. */
method Bezier::init(self)
{
        isButton1Down =
        isButton2Down = false;
        return init(super, HWND_DESKTOP, nil, "Bezier",
                        0, nil);
}

/* Create a new instance of the Bezier window. */
method BezierClass::new(self)
{
        return init(basicNew(self));
}

/* Answer the frame window control flags */
method Bezier::controlFlagsOf(self)
{
        return FCF_TITLEBAR | FCF_SYSMENU | FCF_SIZEBORDER |
               FCF_MINMAX;
}

/* Answer the style of the desired window. */
method Bezier::windowStyleOf(self)
{
        return WS_VISIBLE | FS_SIZEBORDER;
}

/* Process a left button press in the window.*/
method Bezier::button1Down(self, mousePosition, hitTest)
{
        if(!isButton1Down) {
                capture(self);
                isButton1Down = true;
        } else
                alarm(self, WA_ERROR);
        return button1Down(super, mousePosition, hitTest);
}

/* Process a left button release in the window. */
method Bezier::button1Up(self, mousePosition, hitTest)
{
        if(isButton1Down) {
                releaseCapture(self);
                isButton1Down = false;
        }
        return button1Up(super, mousePosition, hitTest);
}

/* Process a right button press in the window. */
method Bezier::button2Down(self, mousePosition, hitTest)
{
        if(!isButton2Down) {
                capture(self);
                isButton2Down = true;
        } else
                alarm(self, WA_ERROR);
        return button2Down(super, mousePosition, hitTest);
}

/* Process a right button release in the window. */
method Bezier::button2Up(self, mousePosition, hitTest)
{
        if(isButton2Down) {
                releaseCapture(self);
                isButton2Down = false;
        }
        return button2Up(super, mousePosition, hitTest);
}

/* Process a mouse movement in the window. */
method Bezier::mouseMove(self, mousePosition, hitTest)
{
        local hps;

        if(!isButton1Down && !isButton2Down)
                return nil;

        hps = getPS(self);
        GpiSetColor(hps, CLR_BACKGROUND);
        paintWindow(self, hps, nil);

        if(isButton1Down)
                control1 = mousePosition;
        else
                control2 = mousePosition;

        GpiSetColor(hps, CLR_NEUTRAL);
        paintWindow(self, hps, nil);
        releasePS(self, hps);
        return mouseMove(super, mousePosition, hitTest);
}

/* Draw the display. */
method Bezier::paintWindow(self, hps, shape)
{
        local pointBlock;

        pointBlock = new(Struct, 8 * 3);
        longPut(pointBlock,  0, x(control1));
        longPut(pointBlock,  4, y(control1));
        longPut(pointBlock,  8, x(control2));
        longPut(pointBlock, 12, y(control2));
        longPut(pointBlock, 16, x(end2));
        longPut(pointBlock, 20, y(end2));

        GpiSetLineType(hps, LINETYPE_ALTERNATE);

        /* Draw the dotted straight lines. */
        moveTo(end1,     hps);
        lineTo(control1, hps);
        moveTo(end2,     hps);
        lineTo(control2, hps);

        /* Draw the spline. */
        GpiSetLineType(hps, LINETYPE_SOLID);
        moveTo(end1, hps);
        GpiPolySpline(hps, 3, pointBlock);
        return self;
}

/* Size the window. */
method Bezier::sizeWindow(self, oldSize, newSize)
{
        end1     =     x(newSize) / 3 @     y(newSize) / 2;
        end2     = 2 * x(newSize) / 3 @     y(newSize) / 2;
        control1 =     x(newSize) / 2 @ 3 * y(newSize) / 4;
        control2 =     x(newSize) / 2 @     y(newSize) / 4;
        return sizeWindow(super, oldSize, newSize);
}

/*
** Answer the name of the demo application
** to be used by the demo start list box.
*/
method BezierClass::demoNameOf(self)
{
        return "Bezier Curves";
}