⛏️ index : haiku.git

/*
 * Copyright 2003-2010, Haiku, Inc. All Rights Reserved.
 * Copyright 2004-2005 yellowTAB GmbH. All Rights Reserverd.
 * Copyright 2006 Bernd Korz. All Rights Reserved
 * Distributed under the terms of the MIT License.
 *
 * Authors:
 *		Fernando Francisco de Oliveira
 *		Michael Wilber
 *		Michael Pfeiffer
 *		Ryan Leavengood
 *		yellowTAB GmbH
 *		Bernd Korz
 *		Stephan Aßmus <superstippi@gmx.de>
 */


#include "SelectionBox.h"

#include <math.h>
#include <new>
#include <stdio.h>

#include "ShowImageView.h"


SelectionBox::SelectionBox()
	:
	fBounds()
{
	_InitPatterns();
}


SelectionBox::~SelectionBox()
{
}


void
SelectionBox::SetBounds(ShowImageView* view, BRect bounds)
{
	view->ConstrainToImage(bounds);

	if (fBounds == bounds)
		return;

	BRect dirtyOld = _RectInView(view);

	fBounds = bounds;

	BRect dirtyNew = _RectInView(view);

	if (dirtyOld.IsValid() && dirtyNew.IsValid())
		view->Invalidate(dirtyOld | dirtyNew);
	else if (dirtyOld.IsValid())
		view->Invalidate(dirtyOld);
	else if (dirtyNew.IsValid())
		view->Invalidate(dirtyNew);
}


BRect
SelectionBox::Bounds() const
{
	return fBounds;
}


void
SelectionBox::MouseDown(ShowImageView* view, BPoint where)
{
	// TODO: Allow to re-adjust corners.
	where = view->ViewToImage(where);
	SetBounds(view, BRect(where, where));
}


void
SelectionBox::MouseMoved(ShowImageView* view, BPoint where)
{
	// TODO: Allow to re-adjust corners.
	where = view->ViewToImage(where);

	BRect bounds(fBounds);

	if (where.x >= bounds.left)
		bounds.right = where.x;
	else
		bounds.left = where.x;

	if (where.y >= bounds.top)
		bounds.bottom = where.y;
	else
		bounds.top = where.y;

	SetBounds(view, bounds);
}


void
SelectionBox::MouseUp(ShowImageView* view, BPoint where)
{
}


void
SelectionBox::Animate()
{
	// rotate up
	uchar p = fPatternUp.data[0];
	for (int i = 0; i <= 6; i++)
		fPatternUp.data[i] = fPatternUp.data[i + 1];
	fPatternUp.data[7] = p;

	// rotate down
	p = fPatternDown.data[7];
	for (int i = 7; i >= 1; i--)
		fPatternDown.data[i] = fPatternDown.data[i - 1];
	fPatternDown.data[0] = p;

	// rotate to left
	p = fPatternLeft.data[0];
	bool set = (p & 0x80) != 0;
	p <<= 1;
	p &= 0xfe;
	if (set)
		p |= 1;
	memset(fPatternLeft.data, p, 8);

	// rotate to right
	p = fPatternRight.data[0];
	set = (p & 1) != 0;
	p >>= 1;
	if (set)
		p |= 0x80;
	memset(fPatternRight.data, p, 8);
}


void
SelectionBox::Draw(ShowImageView* view, const BRect& updateRect) const
{
	BRect r = _RectInView(view);
	if (!r.IsValid() || !updateRect.Intersects(r))
		return;

	view->PushState();

	view->SetLowColor(255, 255, 255);
	view->StrokeLine(BPoint(r.left, r.top), BPoint(r.right, r.top),
		fPatternLeft);
	view->StrokeLine(BPoint(r.right, r.top + 1), BPoint(r.right, r.bottom - 1),
		fPatternUp);
	view->StrokeLine(BPoint(r.left, r.bottom), BPoint(r.right, r.bottom),
		fPatternRight);
	view->StrokeLine(BPoint(r.left, r.top + 1), BPoint(r.left, r.bottom - 1),
		fPatternDown);

	view->PopState();
}


// #pragma mark -


void
SelectionBox::_InitPatterns()
{
	uchar p;
	uchar p1 = 0x33;
	uchar p2 = 0xCC;
	for (int i = 0; i <= 7; i++) {
		fPatternLeft.data[i] = p1;
		fPatternRight.data[i] = p2;
		if ((i / 2) % 2 == 0)
			p = 255;
		else
			p = 0;
		fPatternUp.data[i] = p;
		fPatternDown.data[i] = ~p;
	}
}


BRect
SelectionBox::_RectInView(ShowImageView* view) const
{
	BRect r;
	if (fBounds.Height() <= 0.0 || fBounds.Width() <= 0.0)
		return r;

	r = fBounds;
	// Layout selection rect in view coordinate space
	view->ConstrainToImage(r);
	r = view->ImageToView(r);
	// draw selection box *around* selection
	r.InsetBy(-1, -1);

	return r;
}