* Copyright 2006-2007, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include "MultipleManipulatorState.h"
#include <stdio.h>
#include <AppDefs.h>
#include "Manipulator.h"
#include "StateView.h"
MultipleManipulatorState::MultipleManipulatorState(StateView* view)
: ViewState(view),
fManipulators(24),
fCurrentManipulator(NULL),
fPreviousManipulator(NULL)
{
}
MultipleManipulatorState::~MultipleManipulatorState()
{
DeleteManipulators();
}
void
MultipleManipulatorState::Init()
{
}
void
MultipleManipulatorState::Cleanup()
{
}
void
MultipleManipulatorState::Draw(BView* into, BRect updateRect)
{
int32 count = fManipulators.CountItems();
for (int32 i = 0; i < count; i++) {
Manipulator* manipulator =
(Manipulator*)fManipulators.ItemAtFast(i);
if (manipulator->Bounds().Intersects(updateRect))
manipulator->Draw(into, updateRect);
}
}
bool
MultipleManipulatorState::MessageReceived(BMessage* message,
Command** _command)
{
int32 count = fManipulators.CountItems();
for (int32 i = 0; i < count; i++) {
Manipulator* manipulator =
(Manipulator*)fManipulators.ItemAtFast(i);
if (manipulator->MessageReceived(message, _command))
return true;
}
return false;
}
void
MultipleManipulatorState::MouseDown(BPoint where, uint32 buttons, uint32 clicks)
{
if (buttons & B_SECONDARY_MOUSE_BUTTON) {
_ShowContextMenu(where);
return;
}
if (clicks == 2
&& fPreviousManipulator
&& fManipulators.HasItem(fPreviousManipulator)) {
if (fPreviousManipulator->TrackingBounds(fView).Contains(where)
&& fPreviousManipulator->DoubleClicked(where)) {
fPreviousManipulator = NULL;
return;
}
}
int32 count = fManipulators.CountItems();
for (int32 i = count - 1; i >= 0; i--) {
Manipulator* manipulator =
(Manipulator*)fManipulators.ItemAtFast(i);
if (manipulator->MouseDown(where)) {
fCurrentManipulator = manipulator;
break;
}
}
fView->SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
}
void
MultipleManipulatorState::MouseMoved(BPoint where, uint32 transit,
const BMessage* dragMessage)
{
if (fCurrentManipulator) {
fCurrentManipulator->MouseMoved(where);
} else {
int32 count = fManipulators.CountItems();
bool updateCursor = true;
for (int32 i = 0; i < count; i++) {
Manipulator* manipulator =
(Manipulator*)fManipulators.ItemAtFast(i);
if (manipulator->TrackingBounds(fView).Contains(where)
&& manipulator->MouseOver(where)) {
updateCursor = false;
break;
}
}
if (updateCursor)
_UpdateCursor();
}
}
Command*
MultipleManipulatorState::MouseUp()
{
Command* command = NULL;
if (fCurrentManipulator) {
command = fCurrentManipulator->MouseUp();
fPreviousManipulator = fCurrentManipulator;
fCurrentManipulator = NULL;
}
return command;
}
void
MultipleManipulatorState::ModifiersChanged(uint32 modifiers)
{
int32 count = fManipulators.CountItems();
for (int32 i = 0; i < count; i++) {
Manipulator* manipulator =
(Manipulator*)fManipulators.ItemAtFast(i);
manipulator->ModifiersChanged(modifiers);
}
}
bool
MultipleManipulatorState::HandleKeyDown(uint32 key, uint32 modifiers,
Command** _command)
{
int32 count = fManipulators.CountItems();
for (int32 i = 0; i < count; i++) {
Manipulator* manipulator =
(Manipulator*)fManipulators.ItemAtFast(i);
if (manipulator->HandleKeyDown(key, modifiers, _command))
return true;
}
return false;
}
bool
MultipleManipulatorState::HandleKeyUp(uint32 key, uint32 modifiers,
Command** _command)
{
int32 count = fManipulators.CountItems();
for (int32 i = 0; i < count; i++) {
Manipulator* manipulator =
(Manipulator*)fManipulators.ItemAtFast(i);
if (manipulator->HandleKeyUp(key, modifiers, _command))
return true;
}
return false;
}
bool
MultipleManipulatorState::UpdateCursor()
{
if (fPreviousManipulator && fManipulators.HasItem(fPreviousManipulator))
return fPreviousManipulator->UpdateCursor();
return false;
}
bool
MultipleManipulatorState::AddManipulator(Manipulator* manipulator)
{
if (!manipulator)
return false;
if (fManipulators.AddItem((void*)manipulator)) {
manipulator->AttachedToView(fView);
fView->Invalidate(manipulator->Bounds());
return true;
}
return false;
}
Manipulator*
MultipleManipulatorState::RemoveManipulator(int32 index)
{
Manipulator* manipulator = (Manipulator*)fManipulators.RemoveItem(index);
if (manipulator == fCurrentManipulator)
fCurrentManipulator = NULL;
if (manipulator) {
fView->Invalidate(manipulator->Bounds());
manipulator->DetachedFromView(fView);
}
return manipulator;
}
void
MultipleManipulatorState::DeleteManipulators()
{
BRect dirty(LONG_MAX, LONG_MAX, LONG_MIN, LONG_MIN);
int32 count = fManipulators.CountItems();
for (int32 i = 0; i < count; i++) {
Manipulator* m = (Manipulator*)fManipulators.ItemAtFast(i);
dirty = dirty | m->Bounds();
m->DetachedFromView(fView);
delete m;
}
fManipulators.MakeEmpty();
fCurrentManipulator = NULL;
fPreviousManipulator = NULL;
fView->Invalidate(dirty);
_UpdateCursor();
}
int32
MultipleManipulatorState::CountManipulators() const
{
return fManipulators.CountItems();
}
Manipulator*
MultipleManipulatorState::ManipulatorAt(int32 index) const
{
return (Manipulator*)fManipulators.ItemAt(index);
}
Manipulator*
MultipleManipulatorState::ManipulatorAtFast(int32 index) const
{
return (Manipulator*)fManipulators.ItemAtFast(index);
}
void
MultipleManipulatorState::_UpdateCursor()
{
if (fCurrentManipulator)
fCurrentManipulator->UpdateCursor();
else
fView->SetViewCursor(B_CURSOR_SYSTEM_DEFAULT);
}
void
MultipleManipulatorState::_ShowContextMenu(BPoint where)
{
int32 count = fManipulators.CountItems();
for (int32 i = 0; i < count; i++) {
Manipulator* manipulator =
(Manipulator*)fManipulators.ItemAtFast(i);
if (manipulator->ShowContextMenu(where))
return;
}
}