⛏️ index : haiku.git

/*
 * Copyright 2011, Haiku.
 * Distributed under the terms of the MIT License.
 *
 * Authors:
 *		Philippe Houdoin
 */


#include "TestPageView.h"

#include <math.h>

#include <AffineTransform.h>
#include <Catalog.h>
#include <Font.h>
#include <GradientLinear.h>
#include <GradientRadial.h>
#include <GridLayoutBuilder.h>
#include <GroupLayoutBuilder.h>
#include <LayoutUtils.h>
#include <TextView.h>
#include <Shape.h>
#include <String.h>
#include <StringView.h>

#include "PrinterListView.h"


#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "TestPageView"


// #pragma mark LeafView


// path data for the leaf shape
static const BPoint kLeafBegin(56.24793f, 15.46287f);
static BPoint kLeafCurves[][3] = {
	{ BPoint(61.14, 28.89), BPoint(69.78, 38.25), BPoint(83.48, 44.17) },
	{ BPoint(99.46, 37.52), BPoint(113.27, 29.61), BPoint(134.91, 30.86) },
	{ BPoint(130.58, 36.53), BPoint(126.74, 42.44), BPoint(123.84, 48.81) },
	{ BPoint(131.81, 42.22), BPoint(137.53, 38.33), BPoint(144.37, 33.10) },
	{ BPoint(169.17, 23.55), BPoint(198.90, 15.55), BPoint(232.05, 10.51) },
	{ BPoint(225.49, 18.37), BPoint(219.31, 28.17), BPoint(217.41, 40.24) },
	{ BPoint(227.70, 26.60), BPoint(239.97, 14.63), BPoint(251.43, 8.36) },
	{ BPoint(288.89, 9.12), BPoint(322.73, 14.33), BPoint(346.69, 31.67) },
	{ BPoint(330.49, 37.85), BPoint(314.36, 44.25), BPoint(299.55, 54.17) },
	{ BPoint(292.48, 52.54), BPoint(289.31, 49.70), BPoint(285.62, 47.03) },
	{ BPoint(283.73, 54.61), BPoint(284.46, 57.94), BPoint(285.62, 60.60) },
	{ BPoint(259.78, 76.14), BPoint(233.24, 90.54), BPoint(202.41, 98.10) },
	{ BPoint(194.43, 95.36), BPoint(185.96, 92.39), BPoint(179.63, 88.33) },
	{ BPoint(180.15, 94.75), BPoint(182.73, 99.76), BPoint(185.62, 104.53) },
	{ BPoint(154.83, 119.46), BPoint(133.21, 118.97), BPoint(125.62, 94.88) },
	{ BPoint(124.70, 98.79), BPoint(124.11, 103.67), BPoint(124.19, 110.60) },
	{ BPoint(116.42, 111.81), BPoint(85.82, 99.60), BPoint(83.25, 51.96) },
	{ BPoint(62.50, 42.57), BPoint(58.12, 33.18), BPoint(50.98, 23.81) } };
static const int kNumLeafCurves = sizeof(kLeafCurves) / sizeof(kLeafCurves[0]);
static const float kLeafWidth = 372.f;
static const float kLeafHeight = 121.f;


class LeafView : public BView {
public:
								LeafView();
	virtual	void				Draw(BRect updateRect);
};


LeafView::LeafView()
	:
	BView("leafview", B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE)
{
	SetViewColor(255, 255, 255);
}


void
LeafView::Draw(BRect updateRect)
{
	float scale = Bounds().Width() / kLeafWidth;
	BAffineTransform transform;
	transform.ScaleBy(scale);

	// BGradientRadial gradient(BPoint(kLeafWidth * 0.75, kLeafHeight * 1.5),
	//	kLeafWidth * 2);
	BGradientLinear gradient(B_ORIGIN,
		transform.Apply(BPoint(kLeafWidth, kLeafHeight)));
	rgb_color lightBlue = make_color(6, 169, 255);
	rgb_color darkBlue = make_color(0, 50, 126);
	gradient.AddColor(darkBlue, 0.0);
	gradient.AddColor(lightBlue, 255.0);

	// build leaf shape
	BShape leafShape;
	leafShape.MoveTo(transform.Apply(kLeafBegin));
	for (int i = 0; i < kNumLeafCurves; ++i) {
		BPoint controlPoints[3];
		for (int j = 0; j < 3; ++j)
			controlPoints[j] = transform.Apply(kLeafCurves[i][j]);
		leafShape.BezierTo(controlPoints);
	}
	leafShape.Close();

	PushState();
	SetDrawingMode(B_OP_ALPHA);
	SetHighColor(0, 0, 0, 50);
	for (int i = 2; i >= 0; --i) {
		SetOrigin(i * 0.1, i * 0.3);
		SetPenSize(i * 2);
		StrokeShape(&leafShape);
	}
	PopState();

	FillShape(&leafShape, gradient);
}


// #pragma mark -


class RadialLinesView : public BView {
public:
								RadialLinesView();

	virtual	void				Draw(BRect updateRect);

	virtual bool				HasHeightForWidth() { return true; }
	virtual void				GetHeightForWidth(float width, float* min,
									float* max, float* preferred);
};


RadialLinesView::RadialLinesView()
	: BView("radiallinesview", B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE)
{
	SetViewColor(255, 255, 255);
}


void
RadialLinesView::GetHeightForWidth(float width,
	float* min, float* max, float* preferred)
{
	// Enforce a width/height ratio of 1

	if (min)
		*min = width;

	if (max)
		*max = width;

	if (preferred)
		*preferred = width;
}


void
RadialLinesView::Draw(BRect updateRect)
{
	const rgb_color black = { 0, 0, 0, 255 };
	const int angleStep = 4;

	BRect rect(Bounds());
	float size = rect.Width();
	if (size > rect.Height())
		size = rect.Height();
	size *= 0.45; // leave 10% of margin

	BPoint center(rect.Width() / 2, rect.Height() / 2);

	BeginLineArray(360 / angleStep);
	for (int i = 0; i < 360; i += angleStep) {
		double angle = i * M_PI / 180;
		BPoint pt(size * cos(angle), size * sin(angle));
		AddLine(center, center + pt, black);
	}
	EndLineArray();
}


// #pragma mark -


static const struct {
	const char* name;
	rgb_color	color;
} kColorGradients[] = {
	{ B_TRANSLATE_MARK("Red"), 		{255, 0, 0, 255} },
	{ B_TRANSLATE_MARK("Green"), 	{0, 255, 0, 255} },
	{ B_TRANSLATE_MARK("Blue"), 	{0, 0, 255, 255} },
	{ B_TRANSLATE_MARK("Yellow"), 	{255, 255, 0, 255} },
	{ B_TRANSLATE_MARK("Magenta"), 	{255, 0, 255, 255} },
	{ B_TRANSLATE_MARK("Cyan"), 	{0, 255, 255, 255} },
	{ B_TRANSLATE_MARK("Black"), 	{0, 0, 0, 255} }
};
static const int kNumColorGradients = sizeof(kColorGradients)
	/ sizeof(kColorGradients[0]);


class ColorGradientView : public BView {
public:
								ColorGradientView(rgb_color color);
	virtual	void				Draw(BRect updateRect);

private:
			rgb_color			fColor;
};


ColorGradientView::ColorGradientView(rgb_color color)
	:
	BView("colorgradientview", B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
	fColor(color)
{
}


void
ColorGradientView::Draw(BRect updateRect)
{
	BRect rect(Bounds());

	BGradientLinear gradient(rect.LeftTop(), rect.RightBottom());
	rgb_color white = make_color(255, 255, 255);
	gradient.AddColor(white, 0.0);
	gradient.AddColor(fColor, 255.0);

	FillRect(rect, gradient);
	StrokeRect(rect);
}


// #pragma mark -


TestPageView::TestPageView(BRect frame, PrinterItem* printer)
	: BView(frame, "testpage", B_FOLLOW_ALL,
		B_DRAW_ON_CHILDREN | B_FULL_UPDATE_ON_RESIZE),
	fPrinter(printer)
{
	SetViewColor(255, 255, 255);
}


void
TestPageView::AttachedToWindow()
{
	BTextView* statusView = new BTextView("statusView",
		be_plain_font, NULL, B_WILL_DRAW);

	statusView->SetInsets(10, 10, 10, 10);
	statusView->MakeEditable(false);
	statusView->MakeSelectable(false);

	const char* title = B_TRANSLATE("Test page");
	BString text;
	text << title << "\n\n";
	text << B_TRANSLATE(
		"Printer: %printer_name%\n"
		"Driver:  %driver%\n");

	text.ReplaceFirst("%printer_name%", fPrinter->Name());
	text.ReplaceFirst("%driver%", fPrinter->Driver());
	if (strlen(fPrinter->Transport()) > 0) {
		text << B_TRANSLATE("Transport: %transport% %transport_address%");

		text.ReplaceFirst("%transport%", fPrinter->Transport());
		text.ReplaceFirst("%transport_address%", fPrinter->TransportAddress());
	}

	statusView->SetText(text.String());
	BFont font;
	statusView->SetStylable(true);
	statusView->GetFont(&font);
	font.SetFace(B_BOLD_FACE);
	font.SetSize(font.Size() * 1.7);
	statusView->SetFontAndColor(0, strlen(title), &font);

	BGridLayoutBuilder gradients(2.0);
	gradients.View()->SetViewColor(B_TRANSPARENT_COLOR);

	for (int i = 0; i < kNumColorGradients; ++i) {
		BStringView* label = new BStringView(
			kColorGradients[i].name,
			B_TRANSLATE(kColorGradients[i].name));
		// label->SetAlignment(B_ALIGN_RIGHT);
		gradients.Add(label, 0, i);
		gradients.Add(new ColorGradientView(kColorGradients[i].color), 1, i);
	}

	SetLayout(new BGroupLayout(B_HORIZONTAL));
	AddChild(BGroupLayoutBuilder(B_VERTICAL, 0)
		.Add(BGroupLayoutBuilder(B_HORIZONTAL, 0)
			.Add(statusView)
			.Add(new LeafView())
		)
		.Add(BGroupLayoutBuilder(B_HORIZONTAL, 0)
			.Add(gradients, 0.60)
			.Add(new RadialLinesView(), 0.40)
		)
		.AddGlue()
		.End()
	);

	// set layout background color to transparent instead
	// of default UI panel color
	ChildAt(0)->SetViewColor(B_TRANSPARENT_COLOR);
}


void
TestPageView::DrawAfterChildren(BRect updateRect)
{
	// Draw corners marks

	float width = Bounds().Width();
	float height = Bounds().Height();
	float minDimension = MIN(width, height);

	float size = minDimension * 0.05;

	SetPenSize(3.0);

	BPoint pt = Bounds().LeftTop();
	StrokeLine(pt, BPoint(pt.x + size, pt.y));
	StrokeLine(pt, BPoint(pt.x, pt.y + size));

	pt = Bounds().RightTop();
	StrokeLine(pt, BPoint(pt.x - size, pt.y));
	StrokeLine(pt, BPoint(pt.x, pt.y + size));

	pt = Bounds().RightBottom();
	StrokeLine(pt, BPoint(pt.x - size, pt.y));
	StrokeLine(pt, BPoint(pt.x, pt.y - size));

	pt = Bounds().LeftBottom();
	StrokeLine(pt, BPoint(pt.x + size, pt.y));
	StrokeLine(pt, BPoint(pt.x, pt.y - size));
}