#include <stdio.h>
#include <Application.h>
#include <Bitmap.h>
#include <Catalog.h>
#include <Cursor.h>
#include <Message.h>
#include <MessageQueue.h>
#include <Region.h>
#include <Shape.h>
#include <String.h>
#include <Window.h>
#include "ObjectView.h"
#include "States.h"
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "Playground"
const unsigned char kMoveCursor[] = { 16, 1, 8, 8,
0x01, 0x80, 0x02, 0x40, 0x04, 0x20, 0x08, 0x10,
0x1e, 0x78, 0x2a, 0x54, 0x4e, 0x72, 0x80, 0x01,
0x80, 0x01, 0x4e, 0x72, 0x2a, 0x54, 0x1e, 0x78,
0x08, 0x10, 0x04, 0x20, 0x02, 0x40, 0x01, 0x80,
0x01, 0x80, 0x03, 0xc0, 0x07, 0xe0, 0x0f, 0xf0,
0x1f, 0xf8, 0x3b, 0xdc, 0x7f, 0xfe, 0xff, 0xff,
0xff, 0xff, 0x7f, 0xfe, 0x3b, 0xdc, 0x1f, 0xf8,
0x0f, 0xf0, 0x07, 0xe0, 0x03, 0xc0, 0x01, 0x80 };
const unsigned char kGrabCursor[] = { 16, 1, 8, 9,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0d, 0xb0, 0x12, 0x4c, 0x10, 0x0a, 0x08, 0x02,
0x18, 0x02, 0x20, 0x02, 0x20, 0x02, 0x20, 0x04,
0x10, 0x04, 0x08, 0x08, 0x04, 0x08, 0x04, 0x08,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0d, 0xb0, 0x1f, 0xfc, 0x1f, 0xfe, 0x0f, 0xfe,
0x1f, 0xfe, 0x3f, 0xfe, 0x3f, 0xfe, 0x3f, 0xfc,
0x1f, 0xfc, 0x0f, 0xf8, 0x07, 0xf8, 0x07, 0xf8 };
ObjectView::ObjectView(BRect frame, const char* name,
uint32 resizeFlags, uint32 flags)
: BView(frame, name, resizeFlags, flags),
fState(NULL),
fObjectType(OBJECT_LINE),
fStateList(20),
fColor((rgb_color){ 0, 80, 255, 100 }),
fDrawingMode(B_OP_ALPHA),
fFill(false),
fPenSize(10.0),
fScrolling(false),
fInitiatingDrag(false),
fLastMousePos(0.0, 0.0)
{
SetLowColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_LIGHTEN_1_TINT));
SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY);
}
ObjectView::~ObjectView()
{
}
void
ObjectView::AttachedToWindow()
{
SetViewColor(B_TRANSPARENT_COLOR);
}
void
ObjectView::DetachedFromWindow()
{
}
void
ObjectView::Draw(BRect updateRect)
{
FillRect(updateRect, B_SOLID_LOW);
BRect r(Bounds());
AddLine(BPoint(r.left, r.top),
BPoint(r.right, r.top), shadow);
AddLine(BPoint(r.right, r.top + 1),
BPoint(r.right, r.bottom), light);
AddLine(BPoint(r.right - 1, r.bottom),
BPoint(r.left, r.bottom), light);
AddLine(BPoint(r.left, r.bottom - 1),
BPoint(r.left, r.top + 1), shadow);
EndLineArray();*/
SetDrawingMode(B_OP_OVER);
SetHighColor(255, 0, 0, 128);
const char* message = B_TRANSLATE("Click and drag to draw an object");
float width = StringWidth(message);
BPoint p((r.Width() - width) / 2.0, r.Height() / 2.0);
DrawString(message, p);
for (int32 i = 0; State* state = (State*)fStateList.ItemAt(i); i++)
state->Draw(this);
}
void
ObjectView::MouseDown(BPoint where)
{
uint32 buttons;
int32 clicks;
Window()->CurrentMessage()->FindInt32("buttons", (int32*)&buttons);
Window()->CurrentMessage()->FindInt32("clicks", &clicks);
fInitiatingDrag = buttons & B_SECONDARY_MOUSE_BUTTON;
fScrolling = !fInitiatingDrag && (buttons & B_TERTIARY_MOUSE_BUTTON);
SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
if (fScrolling || fInitiatingDrag) {
fLastMousePos = where;
} else {
if (!fState)
AddObject(State::StateFor(fObjectType, fColor, fDrawingMode,
fFill, fPenSize));
if (fState) {
fState->MouseDown(where);
}
}
}
void
ObjectView::MouseUp(BPoint where)
{
if (fScrolling) {
fScrolling = false;
} else {
if (fState) {
fState->MouseUp();
}
}
}
void
ObjectView::MouseMoved(BPoint where, uint32 transit,
const BMessage* dragMessage)
{
if (dragMessage) {
} else {
}
if (fScrolling) {
BCursor cursor(kGrabCursor);
SetViewCursor(&cursor);
BPoint offset = fLastMousePos - where;
ScrollBy(offset.x, offset.y);
fLastMousePos = where + offset;
} else if (fInitiatingDrag) {
BPoint offset = fLastMousePos - where;
if (sqrtf(offset.x * offset.x + offset.y * offset.y) > 5.0) {
BMessage newDragMessage('drag');
BBitmap* dragBitmap = new BBitmap(BRect(0, 0, 40, 40), B_RGBA32,
true);
if (dragBitmap->Lock()) {
BView* helper = new BView(dragBitmap->Bounds(),
"offscreen view", B_FOLLOW_ALL, B_WILL_DRAW);
dragBitmap->AddChild(helper);
helper->SetDrawingMode(B_OP_ALPHA);
helper->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE);
BRect r(helper->Bounds());
helper->SetHighColor(0, 0, 0, 128);
helper->StrokeRect(r);
helper->SetHighColor(200, 200, 200, 100);
r.InsetBy(1, 1);
helper->FillRect(r);
helper->SetHighColor(0, 0, 0, 255);
const char* text = B_TRANSLATE("Test");
float pos = (r.Width() - helper->StringWidth(text)) / 2;
helper->DrawString(text, BPoint(pos, 25));
helper->Sync();
}
DragMessage(&newDragMessage, dragBitmap, B_OP_ALPHA, B_ORIGIN,
this);
fInitiatingDrag = false;
}
} else {
BCursor cursor(kMoveCursor);
SetViewCursor(&cursor);
if (fState && fState->IsTracking()) {
BRect before = fState->Bounds();
fState->MouseMoved(where);
BRect after = fState->Bounds();
BRect invalid(before | after);
Invalidate(invalid);
}
}
}
void
ObjectView::MessageReceived(BMessage* message)
{
switch (message->what) {
case 'drag':
printf("ObjectView::MessageReceived() - received drag message\n");
break;
default:
BView::MessageReceived(message);
break;
}
}
void
ObjectView::SetState(State* state)
{
if (fState != state) {
if (fState) {
fState->SetEditing(false);
Invalidate(fState->Bounds());
}
fState = state;
if (fState) {
fState->SetEditing(true);
Invalidate(fState->Bounds());
}
}
}
void
ObjectView::SetObjectType(int32 type)
{
if (type != fObjectType) {
fObjectType = type;
SetState(NULL);
}
}
void
ObjectView::AddObject(State* state)
{
if (state) {
fStateList.AddItem((void*)state);
BMessage message(MSG_OBJECT_ADDED);
message.AddPointer("object", state);
Window()->PostMessage(&message);
SetState(state);
}
}
void
ObjectView::RemoveObject(State* state)
{
if (state && fStateList.RemoveItem((void*)state)) {
if (fState == state)
SetState(NULL);
else
Invalidate(state->Bounds());
Window()->PostMessage(MSG_OBJECT_COUNT_CHANGED);
delete state;
}
}
int32
ObjectView::CountObjects() const
{
return fStateList.CountItems();
}
void
ObjectView::MakeEmpty()
{
for (int32 i = 0; State* state = (State*)fStateList.ItemAt(i); i++)
delete state;
fStateList.MakeEmpty();
Window()->PostMessage(MSG_OBJECT_COUNT_CHANGED);
fState = NULL;
Invalidate();
}
void
ObjectView::SetStateColor(rgb_color color)
{
if (color.red != fColor.red ||
color.green != fColor.green ||
color.blue != fColor.blue ||
color.alpha != fColor.alpha) {
fColor = color;
if (fState) {
fState->SetColor(fColor);
Invalidate(fState->Bounds());
}
}
}
void
ObjectView::SetStateDrawingMode(drawing_mode mode)
{
if (fDrawingMode != mode) {
fDrawingMode = mode;
if (fState) {
fState->SetDrawingMode(fDrawingMode);
Invalidate(fState->Bounds());
}
}
}
void
ObjectView::SetStateFill(bool fill)
{
if (fFill != fill) {
fFill = fill;
if (fState) {
BRect before = fState->Bounds();
fState->SetFill(fFill);
BRect after = fState->Bounds();
BRect invalid(before | after);
Invalidate(invalid);
}
}
}
void
ObjectView::SetStatePenSize(float penSize)
{
if (fPenSize != penSize) {
fPenSize = penSize;
if (fState) {
BRect before = fState->Bounds();
fState->SetPenSize(fPenSize);
BRect after = fState->Bounds();
BRect invalid(before | after);
Invalidate(invalid);
}
}
}