root/src/tests/servers/app/inverse_clipping/main.cpp
#include <Application.h>
#include <GridView.h>
#include <LayoutBuilder.h>
#include <Picture.h>
#include <ScrollView.h>
#include <Shape.h>
#include <View.h>
#include <Window.h>


typedef void (*clipper)(BView*, BRect, bool);
typedef void (*test)(BView*, clipper);

static const BRect bigRect(-1000,-1000, 1000,1000);
static const BRect baseRect(-25,-10, 25,10);
static const BRect corner(-25,-10, -15,0);
static const BRect crossRect(-5,-35, 5,40);


static void
rectClipper(BView* view, BRect rect, bool inverse)
{
        if (inverse)
                view->ClipToInverseRect(rect);
        else
                view->ClipToRect(rect);
}

static void
pictureClipper(BView* view, BRect rect, bool inverse)
{
        BPicture p;
        view->BeginPicture(&p);
        view->FillEllipse(rect);
        view->SetHighColor(0, 0, 0, 0);
        view->FillEllipse(rect.InsetByCopy(rect.Width()/4, rect.Height()/4));
        view->EndPicture();

        if (inverse)
                view->ClipToInversePicture(&p);
        else
                view->ClipToPicture(&p);
}

static void
shapeClipper(BView* view, BRect rect, bool inverse)
{
        BShape s;
        s.MoveTo(rect.LeftTop());
        s.LineTo(rect.RightBottom());
        s.ArcTo(rect.Width()/4, rect.Height()/4, 0, false, true, rect.RightTop());
        s.LineTo(rect.LeftBottom());
        s.Close();

        if (inverse)
                view->ClipToInverseShape(&s);
        else
                view->ClipToShape(&s);
}


static void
testBase(BView* view, clipper clip, bool inverse)
{
        clip(view, baseRect, inverse);
        view->SetHighColor(255,0,0);
        view->FillRect(bigRect);
}

static void
testBaseDirect(BView* view, clipper clip)
{
        testBase(view, clip, false);
}

static void
testBaseInverse(BView* view, clipper clip)
{
        testBase(view, clip, true);
}

static void
testCross(BView* view, clipper clip, bool inverse)
{
        clip(view, crossRect, inverse);
        view->SetHighColor(0,0,255);
        view->FillRect(bigRect);
}

static void
testCorner(BView* view, clipper clip, bool inverse)
{
        clip(view, corner, inverse);
        view->SetHighColor(0,255,0);
        view->FillRect(bigRect);
}

static void
testCross00(BView* view, clipper clip)
{
        testBase(view, clip, false);
        testCross(view, clip, false);
}

static void
testCross01(BView* view, clipper clip)
{
        testBase(view, clip, false);
        testCross(view, clip, true);
}

static void
testCross10(BView* view, clipper clip)
{
        testBase(view, clip, true);
        testCross(view, clip, false);
}

static void
testCross11(BView* view, clipper clip)
{
        testBase(view, clip, true);
        testCross(view, clip, true);
}

static void
test3000(BView* view, clipper clip)
{
        testBase(view, clip, false);
        testCorner(view, clip, false);
        testCross(view, clip, false);
}

static void
test3001(BView* view, clipper clip)
{
        testBase(view, clip, false);
        testCorner(view, clip, false);
        testCross(view, clip, true);
}

static void
test3010(BView* view, clipper clip)
{
        testBase(view, clip, false);
        testCorner(view, clip, true);
        testCross(view, clip, false);
}

static void
test3011(BView* view, clipper clip)
{
        testBase(view, clip, false);
        testCorner(view, clip, true);
        testCross(view, clip, true);
}

static void
test3100(BView* view, clipper clip)
{
        testBase(view, clip, true);
        testCorner(view, clip, false);
        testCross(view, clip, false);
}

static void
test3101(BView* view, clipper clip)
{
        testBase(view, clip, true);
        testCorner(view, clip, false);
        testCross(view, clip, true);
}

static void
test3110(BView* view, clipper clip)
{
        testBase(view, clip, true);
        testCorner(view, clip, true);
        testCross(view, clip, false);
}

static void
test3111(BView* view, clipper clip)
{
        testBase(view, clip, true);
        testCorner(view, clip, true);
        testCross(view, clip, true);
}

static const test tests[] = {
        testBaseDirect, testBaseInverse,
        testCross00, testCross01, testCross10, testCross11,
        test3000, test3001, test3010, test3011,
        test3100, test3101, test3110, test3111
};


class View : public BView {
public:
                                                                View(const char* name, test, clipper);
                        void                            Draw(BRect);
                        void                            AttachedToWindow();

private:
                        test                            fTest;
                        clipper                         fClipper;
};

View::View(const char* name, test fTest, clipper fClipper)
        :
        BView(BRect(0,0, 100,100), name, 0, B_WILL_DRAW),
        fTest(fTest),
        fClipper(fClipper)
{
}

void
View::AttachedToWindow()
{
        BView::AttachedToWindow();
        TranslateBy(50, 50);
}

void
View::Draw(BRect)
{
        fTest(this, fClipper);
}


class App : public BApplication {
public:
                                                                App();
};

App::App()
        :
        BApplication("application/x-vnd.Haiku-Test_inverse_clip")
{
        BWindow* window = new BWindow(BRect(100,100, 800,400), "clip test",
                B_TITLED_WINDOW, B_QUIT_ON_WINDOW_CLOSE);

        BGridView* grid = new BGridView();
        grid->SetResizingMode(B_FOLLOW_ALL_SIDES);

        BLayoutBuilder::Grid<> layout(grid);
        layout.SetInsets(B_USE_DEFAULT_SPACING);

        int testsCount = B_COUNT_OF(tests);
        for (int i = 0; i < testsCount; i++) {
                layout.Add(new View("region", tests[i], rectClipper), 0, i);
                layout.Add(new View("rotate", tests[i], rectClipper), 1, i);
                        // This one changes from Region to Shape clipping
                layout.Add(new View("picture", tests[i], pictureClipper), 2, i);
                layout.Add(new View("rotate", tests[i], pictureClipper), 3, i);
                layout.Add(new View("shape", tests[i], shapeClipper), 4, i);
                layout.Add(new View("rotate", tests[i], shapeClipper), 5, i);
        }

        BScrollView* scroll = new BScrollView("scroll", grid, B_FOLLOW_ALL_SIDES,
                0, true, true, B_NO_BORDER);
        window->AddChild(scroll);
        BRect bounds(window->Bounds());
        scroll->ResizeTo(bounds.Width(), bounds.Height());

        BView* rotate;
        while ((rotate = window->FindView("rotate")) != NULL) {
                rotate->RotateBy(0.78);
                rotate->SetName("rotated");
        }

        window->Show();
}


int
main()
{
        App app;
        app.Run();
        return 0;
}