* Finally rewrote the filthy, busy-looping, mouse tracking in Tracker.
The new asynchronous tracking doesn't lock the view and makes desktop replicants happy while clicking and dragging around. Fixes #880, #7241 and certainly other tickets, that i will revisit, about refresh locks on the desktop or mouse related bugs. Based on a reusable MessageFilter and the recent B_MOUSE_IDLE message. Some parts are ported from the old code and could use further simplification. There should be no intentional user fonctional change, except: - slightly bigger threshold radius, shorter duration thresholds (= 1.0 x the system-wide doubleclick setting) - not reimplemented: quickening threshold when holding shift while dragging a pose over a destination pose. Some parts are ported from the old code and could use further simplification. There is one known minor regression with autoscrolling while rect-selecting but that will be better fixed with some changes to the autoscroll code. Will address that ASAP. As for the unknown regressions, please test :) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@41892 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Alexandre Deckner, [email protected]
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef LONG_AND_DRAG_TRACKING_FILTER_H
|
||||||
|
#define LONG_AND_DRAG_TRACKING_FILTER_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <MessageFilter.h>
|
||||||
|
#include <Point.h>
|
||||||
|
|
||||||
|
|
||||||
|
class BHandler;
|
||||||
|
class BMessageRunner;
|
||||||
|
|
||||||
|
|
||||||
|
namespace BPrivate {
|
||||||
|
|
||||||
|
class LongAndDragTrackingFilter : public BMessageFilter {
|
||||||
|
public:
|
||||||
|
LongAndDragTrackingFilter(
|
||||||
|
uint32 longMessageWhat,
|
||||||
|
uint32 dragMessageWhat,
|
||||||
|
float radiusThreshold = 4.0f,
|
||||||
|
bigtime_t durationThreshold = 0);
|
||||||
|
~LongAndDragTrackingFilter();
|
||||||
|
|
||||||
|
filter_result Filter(BMessage* message, BHandler** target);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _StopTracking();
|
||||||
|
|
||||||
|
uint32 fLongMessageWhat;
|
||||||
|
uint32 fDragMessageWhat;
|
||||||
|
BMessageRunner* fMessageRunner;
|
||||||
|
BPoint fClickPoint;
|
||||||
|
uint32 fClickButtons;
|
||||||
|
float fSquaredRadiusThreshold;
|
||||||
|
bigtime_t fDurationThreshold;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace BPrivate
|
||||||
|
|
||||||
|
using BPrivate::LongAndDragTrackingFilter;
|
||||||
|
|
||||||
|
#endif // LONG_AND_DRAG_TRACKING_FILTER_H
|
||||||
|
|
||||||
@@ -23,6 +23,7 @@ StaticLibrary libshared.a :
|
|||||||
IconButton.cpp
|
IconButton.cpp
|
||||||
IconView.cpp
|
IconView.cpp
|
||||||
Keymap.cpp
|
Keymap.cpp
|
||||||
|
LongAndDragTrackingFilter.cpp
|
||||||
NaturalCompare.cpp
|
NaturalCompare.cpp
|
||||||
QueryFile.cpp
|
QueryFile.cpp
|
||||||
RWLockManager.cpp
|
RWLockManager.cpp
|
||||||
|
|||||||
@@ -0,0 +1,136 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Alexandre Deckner, [email protected]
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\class LongAndDragTrackingFilter
|
||||||
|
\brief A simple long mouse down and drag detection filter
|
||||||
|
*
|
||||||
|
* A simple mouse filter that detects long clicks and pointer drags.
|
||||||
|
* A long click message is sent when the mouse button is kept down
|
||||||
|
* for a duration longer than a given threshold while the pointer stays
|
||||||
|
* within the limits of a given threshold radius.
|
||||||
|
* A drag message is triggered if the mouse goes further than the
|
||||||
|
* threshold radius before the duration threshold elapsed.
|
||||||
|
*
|
||||||
|
* The messages contain the pointer position and the buttons state at
|
||||||
|
* the moment of the click. The drag message is ready to use with the
|
||||||
|
* be/haiku drag and drop API cf. comment in code.
|
||||||
|
*
|
||||||
|
* Note: for simplicity and current needs (Tracker), only the left mouse
|
||||||
|
* button is tracked.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <LongAndDragTrackingFilter.h>
|
||||||
|
|
||||||
|
#include <Message.h>
|
||||||
|
#include <Messenger.h>
|
||||||
|
#include <MessageRunner.h>
|
||||||
|
#include <View.h>
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
|
||||||
|
LongAndDragTrackingFilter::LongAndDragTrackingFilter(uint32 longMessageWhat,
|
||||||
|
uint32 dragMessageWhat, float radiusThreshold,
|
||||||
|
bigtime_t durationThreshold)
|
||||||
|
:
|
||||||
|
BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE),
|
||||||
|
fLongMessageWhat(longMessageWhat),
|
||||||
|
fDragMessageWhat(dragMessageWhat),
|
||||||
|
fMessageRunner(NULL),
|
||||||
|
fClickButtons(0),
|
||||||
|
fSquaredRadiusThreshold(radiusThreshold * radiusThreshold)
|
||||||
|
{
|
||||||
|
if (durationThreshold == 0) {
|
||||||
|
get_click_speed(&fDurationThreshold);
|
||||||
|
// use system's doubleClickSpeed as default threshold
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LongAndDragTrackingFilter::~LongAndDragTrackingFilter()
|
||||||
|
{
|
||||||
|
delete fMessageRunner;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
LongAndDragTrackingFilter::_StopTracking()
|
||||||
|
{
|
||||||
|
delete fMessageRunner;
|
||||||
|
fMessageRunner = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
filter_result
|
||||||
|
LongAndDragTrackingFilter::Filter(BMessage* message, BHandler** target)
|
||||||
|
{
|
||||||
|
if (*target == NULL)
|
||||||
|
return B_DISPATCH_MESSAGE;
|
||||||
|
|
||||||
|
switch (message->what) {
|
||||||
|
case B_MOUSE_DOWN:
|
||||||
|
|
||||||
|
message->FindInt32("buttons", (int32*)&fClickButtons);
|
||||||
|
|
||||||
|
if ((fClickButtons & B_PRIMARY_MOUSE_BUTTON)
|
||||||
|
== B_PRIMARY_MOUSE_BUTTON) {
|
||||||
|
|
||||||
|
BView* targetView = dynamic_cast<BView*>(*target);
|
||||||
|
if (targetView != NULL)
|
||||||
|
targetView->SetMouseEventMask(B_POINTER_EVENTS);
|
||||||
|
|
||||||
|
message->FindPoint("where", &fClickPoint);
|
||||||
|
BMessage message(fLongMessageWhat);
|
||||||
|
message.AddPoint("where", fClickPoint);
|
||||||
|
message.AddInt32("buttons", fClickButtons);
|
||||||
|
|
||||||
|
delete fMessageRunner;
|
||||||
|
fMessageRunner = new (std::nothrow) BMessageRunner(
|
||||||
|
BMessenger(*target), &message, fDurationThreshold, 1);
|
||||||
|
}
|
||||||
|
return B_DISPATCH_MESSAGE;
|
||||||
|
|
||||||
|
case B_MOUSE_UP:
|
||||||
|
_StopTracking();
|
||||||
|
return B_DISPATCH_MESSAGE;
|
||||||
|
|
||||||
|
case B_MOUSE_MOVED:
|
||||||
|
{
|
||||||
|
if (fMessageRunner != NULL) {
|
||||||
|
BPoint where;
|
||||||
|
message->FindPoint("be:view_where", &where);
|
||||||
|
|
||||||
|
BPoint delta(fClickPoint - where);
|
||||||
|
float squaredDelta = (delta.x * delta.x) + (delta.y * delta.y);
|
||||||
|
|
||||||
|
if (squaredDelta >= fSquaredRadiusThreshold) {
|
||||||
|
BMessage dragMessage(fDragMessageWhat);
|
||||||
|
dragMessage.AddPoint("be:view_where", fClickPoint);
|
||||||
|
// name it "be:view_where" since BView::DragMessage
|
||||||
|
// positions the dragging frame/bitmap by retrieving
|
||||||
|
// the current message and reading that field
|
||||||
|
dragMessage.AddInt32("buttons", fClickButtons);
|
||||||
|
BMessenger messenger(*target);
|
||||||
|
messenger.SendMessage(&dragMessage);
|
||||||
|
|
||||||
|
_StopTracking();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return B_DISPATCH_MESSAGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (message->what == fLongMessageWhat) {
|
||||||
|
_StopTracking();
|
||||||
|
return B_DISPATCH_MESSAGE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_DISPATCH_MESSAGE;
|
||||||
|
}
|
||||||
+276
-300
@@ -58,6 +58,7 @@ All rights reserved.
|
|||||||
#include <Query.h>
|
#include <Query.h>
|
||||||
#include <List.h>
|
#include <List.h>
|
||||||
#include <Locale.h>
|
#include <Locale.h>
|
||||||
|
#include <LongAndDragTrackingFilter.h>
|
||||||
#include <MenuItem.h>
|
#include <MenuItem.h>
|
||||||
#include <NodeMonitor.h>
|
#include <NodeMonitor.h>
|
||||||
#include <Path.h>
|
#include <Path.h>
|
||||||
@@ -113,6 +114,8 @@ const float kCountViewWidth = 76;
|
|||||||
const uint32 kAddNewPoses = 'Tanp';
|
const uint32 kAddNewPoses = 'Tanp';
|
||||||
const uint32 kAddPosesCompleted = 'Tapc';
|
const uint32 kAddPosesCompleted = 'Tapc';
|
||||||
const int32 kMaxAddPosesChunk = 50;
|
const int32 kMaxAddPosesChunk = 50;
|
||||||
|
const uint32 kMsgMouseDragged = 'Mdrg';
|
||||||
|
const uint32 kMsgMouseLongDown = 'Mold';
|
||||||
|
|
||||||
|
|
||||||
namespace BPrivate {
|
namespace BPrivate {
|
||||||
@@ -922,6 +925,8 @@ BPoseView::AttachedToWindow()
|
|||||||
AddFilter(new ShortcutFilter(B_ESCAPE, B_SHIFT_KEY, kCancelSelectionToClipboard, this));
|
AddFilter(new ShortcutFilter(B_ESCAPE, B_SHIFT_KEY, kCancelSelectionToClipboard, this));
|
||||||
// Escape + SHIFT will remove current selection from clipboard, or all poses from current folder if 0 selected
|
// Escape + SHIFT will remove current selection from clipboard, or all poses from current folder if 0 selected
|
||||||
|
|
||||||
|
AddFilter(new LongAndDragTrackingFilter(kMsgMouseLongDown, kMsgMouseDragged));
|
||||||
|
|
||||||
fLastLeftTop = LeftTop();
|
fLastLeftTop = LeftTop();
|
||||||
BFont font(be_plain_font);
|
BFont font(be_plain_font);
|
||||||
font.SetSpacing(B_BITMAP_SPACING);
|
font.SetSpacing(B_BITMAP_SPACING);
|
||||||
@@ -2154,6 +2159,18 @@ BPoseView::MessageReceived(BMessage *message)
|
|||||||
case kMiniIconMode:
|
case kMiniIconMode:
|
||||||
SetViewMode(message->what);
|
SetViewMode(message->what);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case kMsgMouseDragged:
|
||||||
|
MouseDragged(message);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kMsgMouseLongDown:
|
||||||
|
MouseLongDown(message);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_MOUSE_IDLE:
|
||||||
|
MouseIdle(message);
|
||||||
|
break;
|
||||||
|
|
||||||
case B_SELECT_ALL:
|
case B_SELECT_ALL:
|
||||||
{
|
{
|
||||||
@@ -6544,11 +6561,238 @@ BPoseView::ShowContextMenu(BPoint where)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BPoseView::_BeginSelectionRect(const BPoint& point, bool shouldExtend)
|
||||||
|
{
|
||||||
|
// set initial empty selection rectangle
|
||||||
|
fSelectionRectInfo.rect = BRect(point, point - BPoint(1, 1));
|
||||||
|
|
||||||
|
if (!fTransparentSelection) {
|
||||||
|
SetDrawingMode(B_OP_INVERT);
|
||||||
|
StrokeRect(fSelectionRectInfo.rect, B_MIXED_COLORS);
|
||||||
|
SetDrawingMode(B_OP_OVER);
|
||||||
|
}
|
||||||
|
|
||||||
|
fSelectionRectInfo.lastRect = fSelectionRectInfo.rect;
|
||||||
|
fSelectionRectInfo.selection = new BList;
|
||||||
|
fSelectionRectInfo.startPoint = point;
|
||||||
|
fSelectionRectInfo.lastPoint = point;
|
||||||
|
fSelectionRectInfo.isDragging = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
AddIfPoseSelected(BPose *pose, PoseList *list)
|
||||||
|
{
|
||||||
|
if (pose->IsSelected())
|
||||||
|
list->AddItem(pose);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BPoseView::_UpdateSelectionRect(const BPoint& point)
|
||||||
|
{
|
||||||
|
if (point != fSelectionRectInfo.lastPoint) {
|
||||||
|
|
||||||
|
fSelectionRectInfo.lastPoint = point;
|
||||||
|
|
||||||
|
// erase last rect
|
||||||
|
if (!fTransparentSelection) {
|
||||||
|
SetDrawingMode(B_OP_INVERT);
|
||||||
|
StrokeRect(fSelectionRectInfo.rect, B_MIXED_COLORS);
|
||||||
|
SetDrawingMode(B_OP_OVER);
|
||||||
|
}
|
||||||
|
|
||||||
|
fSelectionRectInfo.rect.top = std::min(point.y,
|
||||||
|
fSelectionRectInfo.startPoint.y);
|
||||||
|
fSelectionRectInfo.rect.left = std::min(point.x,
|
||||||
|
fSelectionRectInfo.startPoint.x);
|
||||||
|
fSelectionRectInfo.rect.bottom = std::max(point.y,
|
||||||
|
fSelectionRectInfo.startPoint.y);
|
||||||
|
fSelectionRectInfo.rect.right = std::max(point.x,
|
||||||
|
fSelectionRectInfo.startPoint.x);
|
||||||
|
|
||||||
|
fIsDrawingSelectionRect = true;
|
||||||
|
|
||||||
|
CheckAutoScroll(point, true, true);
|
||||||
|
|
||||||
|
// use current selection rectangle to scan poses
|
||||||
|
if (ViewMode() == kListMode) {
|
||||||
|
SelectPosesListMode(fSelectionRectInfo.rect,
|
||||||
|
&fSelectionRectInfo.selection);
|
||||||
|
} else {
|
||||||
|
SelectPosesIconMode(fSelectionRectInfo.rect,
|
||||||
|
&fSelectionRectInfo.selection);
|
||||||
|
}
|
||||||
|
|
||||||
|
Window()->UpdateIfNeeded();
|
||||||
|
|
||||||
|
// draw new rect
|
||||||
|
if (!fTransparentSelection) {
|
||||||
|
SetDrawingMode(B_OP_INVERT);
|
||||||
|
StrokeRect(fSelectionRectInfo.rect, B_MIXED_COLORS);
|
||||||
|
SetDrawingMode(B_OP_OVER);
|
||||||
|
} else {
|
||||||
|
BRegion updateRegion1;
|
||||||
|
BRegion updateRegion2;
|
||||||
|
|
||||||
|
bool sameWidth = fSelectionRectInfo.rect.Width()
|
||||||
|
== fSelectionRectInfo.lastRect.Width();
|
||||||
|
bool sameHeight = fSelectionRectInfo.rect.Height()
|
||||||
|
== fSelectionRectInfo.lastRect.Height();
|
||||||
|
|
||||||
|
updateRegion1.Include(fSelectionRectInfo.rect);
|
||||||
|
updateRegion1.Exclude(fSelectionRectInfo.lastRect.InsetByCopy(
|
||||||
|
sameWidth ? 0 : 1, sameHeight ? 0 : 1));
|
||||||
|
updateRegion2.Include(fSelectionRectInfo.lastRect);
|
||||||
|
updateRegion2.Exclude(fSelectionRectInfo.rect.InsetByCopy(
|
||||||
|
sameWidth ? 0 : 1, sameHeight ? 0 : 1));
|
||||||
|
updateRegion1.Include(&updateRegion2);
|
||||||
|
BRect unionRect = fSelectionRectInfo.rect
|
||||||
|
& fSelectionRectInfo.lastRect;
|
||||||
|
updateRegion1.Exclude(unionRect
|
||||||
|
& BRect(-2000, fSelectionRectInfo.startPoint.y, 2000,
|
||||||
|
fSelectionRectInfo.startPoint.y));
|
||||||
|
updateRegion1.Exclude(unionRect
|
||||||
|
& BRect(fSelectionRectInfo.startPoint.x, -2000,
|
||||||
|
fSelectionRectInfo.startPoint.x, 2000));
|
||||||
|
|
||||||
|
fSelectionRectInfo.lastRect = fSelectionRectInfo.rect;
|
||||||
|
|
||||||
|
Invalidate(&updateRegion1);
|
||||||
|
Window()->UpdateIfNeeded();
|
||||||
|
}
|
||||||
|
Flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BPoseView::_EndSelectionRect()
|
||||||
|
{
|
||||||
|
delete fSelectionRectInfo.selection;
|
||||||
|
fSelectionRectInfo.selection = NULL;
|
||||||
|
|
||||||
|
fSelectionRectInfo.isDragging = false;
|
||||||
|
fIsDrawingSelectionRect = false; // TODO: remove BPose dependency?
|
||||||
|
|
||||||
|
// do final erase of selection rect
|
||||||
|
if (!fTransparentSelection) {
|
||||||
|
SetDrawingMode(B_OP_INVERT);
|
||||||
|
StrokeRect(fSelectionRectInfo.rect, B_MIXED_COLORS);
|
||||||
|
SetDrawingMode(B_OP_COPY);
|
||||||
|
} else {
|
||||||
|
Invalidate(fSelectionRectInfo.rect);
|
||||||
|
fSelectionRectInfo.rect.Set(0, 0, -1, -1);
|
||||||
|
Window()->UpdateIfNeeded();
|
||||||
|
}
|
||||||
|
|
||||||
|
// we now need to update the pose view's selection list by clearing it
|
||||||
|
// and then polling each pose for selection state and rebuilding list
|
||||||
|
fSelectionList->MakeEmpty();
|
||||||
|
fMimeTypesInSelectionCache.MakeEmpty();
|
||||||
|
|
||||||
|
EachListItem(fPoseList, AddIfPoseSelected, fSelectionList);
|
||||||
|
|
||||||
|
// and now make sure that the pivot point is in sync
|
||||||
|
if (fSelectionPivotPose && !fSelectionList->HasItem(fSelectionPivotPose))
|
||||||
|
fSelectionPivotPose = NULL;
|
||||||
|
if (fRealPivotPose && !fSelectionList->HasItem(fRealPivotPose))
|
||||||
|
fRealPivotPose = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BPoseView::MouseMoved(BPoint mouseLoc, uint32 moveCode, const BMessage *message)
|
||||||
|
{
|
||||||
|
if (fSelectionRectInfo.isDragging)
|
||||||
|
_UpdateSelectionRect(mouseLoc);
|
||||||
|
|
||||||
|
if (!fDropEnabled || !message)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BContainerWindow* window = ContainerWindow();
|
||||||
|
if (!window)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (moveCode) {
|
||||||
|
case B_INSIDE_VIEW:
|
||||||
|
case B_ENTERED_VIEW:
|
||||||
|
UpdateDropTarget(mouseLoc, message, window->ContextMenu());
|
||||||
|
if (fAutoScrollState == kAutoScrollOff) {
|
||||||
|
// turn on auto scrolling if it's not yet on
|
||||||
|
fAutoScrollState = kWaitForTransition;
|
||||||
|
window->SetPulseRate(100000);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_EXITED_VIEW:
|
||||||
|
// reset cursor in case we set it to the copy cursor
|
||||||
|
// in UpdateDropTarget
|
||||||
|
SetViewCursor(B_CURSOR_SYSTEM_DEFAULT);
|
||||||
|
fCursorCheck = false;
|
||||||
|
// TODO: autoscroll here
|
||||||
|
if (!window->ContextMenu()) {
|
||||||
|
HiliteDropTarget(false);
|
||||||
|
fDropTarget = NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BPoseView::MouseDragged(const BMessage *message)
|
||||||
|
{
|
||||||
|
BPoint where;
|
||||||
|
if (message->FindPoint("be:view_where", &where) != B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool extendSelection = (modifiers() & B_COMMAND_KEY) && fMultipleSelection;
|
||||||
|
|
||||||
|
int32 index;
|
||||||
|
BPose* pose = FindPose(where, &index);
|
||||||
|
if (pose != NULL)
|
||||||
|
DragSelectedPoses(pose, where);
|
||||||
|
else
|
||||||
|
_BeginSelectionRect(where, extendSelection);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BPoseView::MouseLongDown(const BMessage *message)
|
||||||
|
{
|
||||||
|
BPoint where;
|
||||||
|
if (message->FindPoint("where", &where) != B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ShowContextMenu(where);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BPoseView::MouseIdle(const BMessage *message)
|
||||||
|
{
|
||||||
|
BPoint where;
|
||||||
|
uint32 buttons = 0;
|
||||||
|
GetMouse(&where, &buttons);
|
||||||
|
BContainerWindow* window = ContainerWindow();
|
||||||
|
|
||||||
|
if (buttons == 0 || window == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (fDropTarget != NULL) {
|
||||||
|
window->DragStart(message);
|
||||||
|
FrameForPose(fDropTarget, true, &fStartFrame);
|
||||||
|
ShowContextMenu(where);
|
||||||
|
} else
|
||||||
|
window->Activate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BPoseView::MouseDown(BPoint where)
|
BPoseView::MouseDown(BPoint where)
|
||||||
{
|
{
|
||||||
// TODO: add asynch mouse tracking
|
|
||||||
|
|
||||||
// handle disposing of drag data lazily
|
// handle disposing of drag data lazily
|
||||||
DragStop();
|
DragStop();
|
||||||
BContainerWindow *window = ContainerWindow();
|
BContainerWindow *window = ContainerWindow();
|
||||||
@@ -6572,7 +6816,6 @@ BPoseView::MouseDown(BPoint where)
|
|||||||
if ((buttons & B_SECONDARY_MOUSE_BUTTON) == 0)
|
if ((buttons & B_SECONDARY_MOUSE_BUTTON) == 0)
|
||||||
showContext = (modifs & B_CONTROL_KEY) != 0;
|
showContext = (modifs & B_CONTROL_KEY) != 0;
|
||||||
|
|
||||||
// if a pose was hit, delay context menu for a bit to see if user dragged
|
|
||||||
if (showContext) {
|
if (showContext) {
|
||||||
int32 index;
|
int32 index;
|
||||||
BPose *pose = FindPose(where, &index);
|
BPose *pose = FindPose(where, &index);
|
||||||
@@ -6586,24 +6829,7 @@ BPoseView::MouseDown(BPoint where)
|
|||||||
fSelectionList->AddItem(pose);
|
fSelectionList->AddItem(pose);
|
||||||
DrawPose(pose, index, false);
|
DrawPose(pose, index, false);
|
||||||
}
|
}
|
||||||
|
ShowContextMenu(where);
|
||||||
bigtime_t clickTime = system_time();
|
|
||||||
BPoint loc;
|
|
||||||
GetMouse(&loc, &buttons);
|
|
||||||
for (;;) {
|
|
||||||
if (fabs(loc.x - where.x) > 4 || fabs(loc.y - where.y) > 4)
|
|
||||||
// moved the mouse, cancel showing the context menu
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (!buttons || (system_time() - clickTime) > 200000) {
|
|
||||||
// let go of button or pressing for a while, show menu now
|
|
||||||
ShowContextMenu(where);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
snooze(10000);
|
|
||||||
GetMouse(&loc, &buttons);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool extendSelection = (modifs & B_COMMAND_KEY) && fMultipleSelection;
|
bool extendSelection = (modifs & B_COMMAND_KEY) && fMultipleSelection;
|
||||||
@@ -6616,26 +6842,10 @@ BPoseView::MouseDown(BPoint where)
|
|||||||
if (pose) {
|
if (pose) {
|
||||||
AddRemoveSelectionRange(where, extendSelection, pose);
|
AddRemoveSelectionRange(where, extendSelection, pose);
|
||||||
|
|
||||||
switch (WaitForMouseUpOrDrag(where)) {
|
if (!extendSelection && WasDoubleClick(pose, where)) {
|
||||||
case kWasDragged:
|
// special handling for Path field double-clicks
|
||||||
DragSelectedPoses(pose, where);
|
if (!WasClickInPath(pose, index, where))
|
||||||
break;
|
OpenSelection(pose, &index);
|
||||||
|
|
||||||
case kNotDragged:
|
|
||||||
if (!extendSelection && WasDoubleClick(pose, where)) {
|
|
||||||
// special handling for Path field double-clicks
|
|
||||||
if (!WasClickInPath(pose, index, where))
|
|
||||||
OpenSelection(pose, &index);
|
|
||||||
|
|
||||||
} else if (fAllowPoseEditing)
|
|
||||||
// mouse is up but no drag or double-click occurred
|
|
||||||
pose->MouseUp(BPoint(0, index * fListElemHeight), this, where, index);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
// this is the CONTEXT_MENU case
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// click was not in any pose
|
// click was not in any pose
|
||||||
@@ -6643,7 +6853,10 @@ BPoseView::MouseDown(BPoint where)
|
|||||||
|
|
||||||
window->Activate();
|
window->Activate();
|
||||||
window->UpdateIfNeeded();
|
window->UpdateIfNeeded();
|
||||||
DragSelectionRect(where, extendSelection);
|
|
||||||
|
// only clear selection if we are not extending it
|
||||||
|
if (!extendSelection || !fSelectionRectEnabled || !fMultipleSelection)
|
||||||
|
ClearSelection();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fSelectionChangedHook)
|
if (fSelectionChangedHook)
|
||||||
@@ -6651,6 +6864,19 @@ BPoseView::MouseDown(BPoint where)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BPoseView::MouseUp(BPoint where)
|
||||||
|
{
|
||||||
|
if (fSelectionRectInfo.isDragging)
|
||||||
|
_EndSelectionRect();
|
||||||
|
|
||||||
|
int32 index;
|
||||||
|
BPose* pose = FindPose(where, &index);
|
||||||
|
if (pose != NULL && fAllowPoseEditing)
|
||||||
|
pose->MouseUp(BPoint(0, index * fListElemHeight), this, where, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
BPoseView::WasClickInPath(const BPose *pose, int32 index, BPoint mouseLoc) const
|
BPoseView::WasClickInPath(const BPose *pose, int32 index, BPoint mouseLoc) const
|
||||||
{
|
{
|
||||||
@@ -6971,149 +7197,8 @@ BPoseView::GetDragRect(int32 clickedPoseIndex)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
AddIfPoseSelected(BPose *pose, PoseList *list)
|
|
||||||
{
|
|
||||||
if (pose->IsSelected())
|
|
||||||
list->AddItem(pose);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
BPoseView::DragSelectionRect(BPoint startPoint, bool shouldExtend)
|
|
||||||
{
|
|
||||||
// only clear selection if we are not extending it
|
|
||||||
if (!shouldExtend)
|
|
||||||
ClearSelection();
|
|
||||||
|
|
||||||
if (WaitForMouseUpOrDrag(startPoint) != kWasDragged) {
|
|
||||||
if (!shouldExtend)
|
|
||||||
ClearSelection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fSelectionRectEnabled || !fMultipleSelection) {
|
|
||||||
ClearSelection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// clearing the selection could take a while so poll the mouse again
|
|
||||||
BPoint newMousePoint;
|
|
||||||
uint32 button;
|
|
||||||
GetMouse(&newMousePoint, &button);
|
|
||||||
|
|
||||||
// draw initial empty selection rectangle
|
|
||||||
BRect lastSelectionRect;
|
|
||||||
fSelectionRect = lastSelectionRect = BRect(startPoint, startPoint - BPoint(1, 1));
|
|
||||||
|
|
||||||
if (!fTransparentSelection) {
|
|
||||||
SetDrawingMode(B_OP_INVERT);
|
|
||||||
StrokeRect(fSelectionRect, B_MIXED_COLORS);
|
|
||||||
SetDrawingMode(B_OP_OVER);
|
|
||||||
}
|
|
||||||
|
|
||||||
BList *selectionList = new BList;
|
|
||||||
|
|
||||||
BPoint oldMousePoint(startPoint);
|
|
||||||
while (button) {
|
|
||||||
GetMouse(&newMousePoint, &button, false);
|
|
||||||
|
|
||||||
if (newMousePoint != oldMousePoint) {
|
|
||||||
oldMousePoint = newMousePoint;
|
|
||||||
BRect oldRect = fSelectionRect;
|
|
||||||
fSelectionRect.top = std::min(newMousePoint.y, startPoint.y);
|
|
||||||
fSelectionRect.left = std::min(newMousePoint.x, startPoint.x);
|
|
||||||
fSelectionRect.bottom = std::max(newMousePoint.y, startPoint.y);
|
|
||||||
fSelectionRect.right = std::max(newMousePoint.x, startPoint.x);
|
|
||||||
|
|
||||||
// erase old rect
|
|
||||||
if (!fTransparentSelection) {
|
|
||||||
SetDrawingMode(B_OP_INVERT);
|
|
||||||
StrokeRect(oldRect, B_MIXED_COLORS);
|
|
||||||
SetDrawingMode(B_OP_OVER);
|
|
||||||
}
|
|
||||||
|
|
||||||
fIsDrawingSelectionRect = true;
|
|
||||||
|
|
||||||
CheckAutoScroll(newMousePoint, true, true);
|
|
||||||
|
|
||||||
// use current selection rectangle to scan poses
|
|
||||||
if (ViewMode() == kListMode)
|
|
||||||
SelectPosesListMode(fSelectionRect, &selectionList);
|
|
||||||
else
|
|
||||||
SelectPosesIconMode(fSelectionRect, &selectionList);
|
|
||||||
|
|
||||||
Window()->UpdateIfNeeded();
|
|
||||||
|
|
||||||
// draw new selected rect
|
|
||||||
if (!fTransparentSelection) {
|
|
||||||
SetDrawingMode(B_OP_INVERT);
|
|
||||||
StrokeRect(fSelectionRect, B_MIXED_COLORS);
|
|
||||||
SetDrawingMode(B_OP_OVER);
|
|
||||||
} else {
|
|
||||||
BRegion updateRegion1;
|
|
||||||
BRegion updateRegion2;
|
|
||||||
|
|
||||||
bool sameWidth = fSelectionRect.Width() == lastSelectionRect.Width();
|
|
||||||
bool sameHeight = fSelectionRect.Height() == lastSelectionRect.Height();
|
|
||||||
|
|
||||||
updateRegion1.Include(fSelectionRect);
|
|
||||||
updateRegion1.Exclude(lastSelectionRect.InsetByCopy(
|
|
||||||
sameWidth ? 0 : 1, sameHeight ? 0 : 1));
|
|
||||||
updateRegion2.Include(lastSelectionRect);
|
|
||||||
updateRegion2.Exclude(fSelectionRect.InsetByCopy(
|
|
||||||
sameWidth ? 0 : 1, sameHeight ? 0 : 1));
|
|
||||||
updateRegion1.Include(&updateRegion2);
|
|
||||||
BRect unionRect = fSelectionRect & lastSelectionRect;
|
|
||||||
updateRegion1.Exclude(unionRect
|
|
||||||
& BRect(-2000, startPoint.y, 2000, startPoint.y));
|
|
||||||
updateRegion1.Exclude(unionRect
|
|
||||||
& BRect(startPoint.x, -2000, startPoint.x, 2000));
|
|
||||||
|
|
||||||
lastSelectionRect = fSelectionRect;
|
|
||||||
|
|
||||||
Invalidate(&updateRegion1);
|
|
||||||
Window()->UpdateIfNeeded();
|
|
||||||
}
|
|
||||||
|
|
||||||
Flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
snooze(20000);
|
|
||||||
}
|
|
||||||
|
|
||||||
delete selectionList;
|
|
||||||
|
|
||||||
fIsDrawingSelectionRect = false;
|
|
||||||
|
|
||||||
// do final erase of selection rect
|
|
||||||
if (!fTransparentSelection) {
|
|
||||||
SetDrawingMode(B_OP_INVERT);
|
|
||||||
StrokeRect(fSelectionRect, B_MIXED_COLORS);
|
|
||||||
SetDrawingMode(B_OP_COPY);
|
|
||||||
} else {
|
|
||||||
Invalidate(fSelectionRect);
|
|
||||||
fSelectionRect.Set(0, 0, -1, -1);
|
|
||||||
Window()->UpdateIfNeeded();
|
|
||||||
}
|
|
||||||
|
|
||||||
// we now need to update the pose view's selection list by clearing it
|
|
||||||
// and then polling each pose for selection state and rebuilding list
|
|
||||||
fSelectionList->MakeEmpty();
|
|
||||||
fMimeTypesInSelectionCache.MakeEmpty();
|
|
||||||
|
|
||||||
EachListItem(fPoseList, AddIfPoseSelected, fSelectionList);
|
|
||||||
|
|
||||||
// and now make sure that the pivot point is in sync
|
|
||||||
if (fSelectionPivotPose && !fSelectionList->HasItem(fSelectionPivotPose))
|
|
||||||
fSelectionPivotPose = NULL;
|
|
||||||
if (fRealPivotPose && !fSelectionList->HasItem(fRealPivotPose))
|
|
||||||
fRealPivotPose = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: SelectPosesListMode and SelectPosesIconMode are terrible and share
|
// TODO: SelectPosesListMode and SelectPosesIconMode are terrible and share
|
||||||
// most code
|
// most code
|
||||||
|
|
||||||
void
|
void
|
||||||
BPoseView::SelectPosesListMode(BRect selectionRect, BList **oldList)
|
BPoseView::SelectPosesListMode(BRect selectionRect, BList **oldList)
|
||||||
{
|
{
|
||||||
@@ -7347,41 +7432,6 @@ BPoseView::AddRemoveSelectionRange(BPoint where, bool extendSelection, BPose *po
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int32
|
|
||||||
BPoseView::WaitForMouseUpOrDrag(BPoint start)
|
|
||||||
{
|
|
||||||
bigtime_t start_time = system_time();
|
|
||||||
bigtime_t doubleClickSpeed;
|
|
||||||
get_click_speed(&doubleClickSpeed);
|
|
||||||
|
|
||||||
// use double the doubleClickSpeed as a treshold
|
|
||||||
doubleClickSpeed *= 2;
|
|
||||||
|
|
||||||
// loop until mouse has been dragged at least 2 pixels
|
|
||||||
uint32 button;
|
|
||||||
BPoint loc;
|
|
||||||
GetMouse(&loc, &button, false);
|
|
||||||
|
|
||||||
while (button) {
|
|
||||||
GetMouse(&loc, &button, false);
|
|
||||||
if (fabs(loc.x - start.x) > 2 || fabs(loc.y - start.y) > 2)
|
|
||||||
return kWasDragged;
|
|
||||||
|
|
||||||
if ((system_time() - start_time) > doubleClickSpeed) {
|
|
||||||
ShowContextMenu(start);
|
|
||||||
return kContextMenuShown;
|
|
||||||
}
|
|
||||||
|
|
||||||
snooze(15000);
|
|
||||||
}
|
|
||||||
|
|
||||||
// user let up on mouse button without dragging
|
|
||||||
Window()->Activate();
|
|
||||||
Window()->UpdateIfNeeded();
|
|
||||||
return kNotDragged;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BPoseView::DeleteSymLinkPoseTarget(const node_ref *itemNode, BPose *pose,
|
BPoseView::DeleteSymLinkPoseTarget(const node_ref *itemNode, BPose *pose,
|
||||||
int32 index)
|
int32 index)
|
||||||
@@ -8391,14 +8441,16 @@ BPoseView::Draw(BRect updateRect)
|
|||||||
void
|
void
|
||||||
BPoseView::DrawAfterChildren(BRect updateRect)
|
BPoseView::DrawAfterChildren(BRect updateRect)
|
||||||
{
|
{
|
||||||
if (fTransparentSelection && fSelectionRect.IsValid()) {
|
if (fTransparentSelection && fSelectionRectInfo.rect.IsValid()) {
|
||||||
SetDrawingMode(B_OP_ALPHA);
|
SetDrawingMode(B_OP_ALPHA);
|
||||||
SetHighColor(255, 255, 255, 128);
|
SetHighColor(255, 255, 255, 128);
|
||||||
if (fSelectionRect.Width() == 0 || fSelectionRect.Height() == 0)
|
if (fSelectionRectInfo.rect.Width() == 0
|
||||||
StrokeLine(fSelectionRect.LeftTop(), fSelectionRect.RightBottom());
|
|| fSelectionRectInfo.rect.Height() == 0) {
|
||||||
else {
|
StrokeLine(fSelectionRectInfo.rect.LeftTop(),
|
||||||
StrokeRect(fSelectionRect);
|
fSelectionRectInfo.rect.RightBottom());
|
||||||
BRect interior = fSelectionRect;
|
} else {
|
||||||
|
StrokeRect(fSelectionRectInfo.rect);
|
||||||
|
BRect interior = fSelectionRectInfo.rect;
|
||||||
interior.InsetBy(1, 1);
|
interior.InsetBy(1, 1);
|
||||||
if (interior.IsValid()) {
|
if (interior.IsValid()) {
|
||||||
SetHighColor(80, 80, 80, 90);
|
SetHighColor(80, 80, 80, 90);
|
||||||
@@ -8947,82 +8999,6 @@ BPoseView::MoveColumnTo(BColumn *src, BColumn *dest)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
BPoseView::MouseMoved(BPoint mouseLoc, uint32 moveCode, const BMessage *message)
|
|
||||||
{
|
|
||||||
if (!fDropEnabled || !message)
|
|
||||||
return;
|
|
||||||
|
|
||||||
BContainerWindow* window = ContainerWindow();
|
|
||||||
if (!window)
|
|
||||||
return;
|
|
||||||
|
|
||||||
switch (moveCode) {
|
|
||||||
case B_INSIDE_VIEW:
|
|
||||||
case B_ENTERED_VIEW:
|
|
||||||
{
|
|
||||||
UpdateDropTarget(mouseLoc, message, window->ContextMenu());
|
|
||||||
if (fAutoScrollState == kAutoScrollOff) {
|
|
||||||
// turn on auto scrolling if it's not yet on
|
|
||||||
fAutoScrollState = kWaitForTransition;
|
|
||||||
window->SetPulseRate(100000);
|
|
||||||
}
|
|
||||||
|
|
||||||
bigtime_t dropActionDelay;
|
|
||||||
get_click_speed(&dropActionDelay);
|
|
||||||
dropActionDelay *= 3;
|
|
||||||
|
|
||||||
if (window->ContextMenu())
|
|
||||||
break;
|
|
||||||
|
|
||||||
bigtime_t clickTime = system_time();
|
|
||||||
BPoint loc;
|
|
||||||
uint32 buttons;
|
|
||||||
GetMouse(&loc, &buttons);
|
|
||||||
for (;;) {
|
|
||||||
if (buttons == 0
|
|
||||||
|| fabs(loc.x - mouseLoc.x) > 4 || fabs(loc.y - mouseLoc.y) > 4) {
|
|
||||||
// only loop if mouse buttons are down
|
|
||||||
// moved the mouse, cancel showing the context menu
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle drag and drop
|
|
||||||
bigtime_t now = system_time();
|
|
||||||
// use shift key to get around over-loading of Control key
|
|
||||||
// for context menus and auto-dnd menu
|
|
||||||
if (((modifiers() & B_SHIFT_KEY) && (now - clickTime) > 200000)
|
|
||||||
|| now - clickTime > dropActionDelay) {
|
|
||||||
// let go of button or pressing for a while, show menu now
|
|
||||||
if (fDropTarget) {
|
|
||||||
window->DragStart(message);
|
|
||||||
FrameForPose(fDropTarget, true, &fStartFrame);
|
|
||||||
ShowContextMenu(mouseLoc);
|
|
||||||
} else
|
|
||||||
window->Activate();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
snooze(10000);
|
|
||||||
GetMouse(&loc, &buttons);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case B_EXITED_VIEW:
|
|
||||||
// reset cursor in case we set it to the copy cursor in UpdateDropTarget
|
|
||||||
SetViewCursor(B_CURSOR_SYSTEM_DEFAULT);
|
|
||||||
fCursorCheck = false;
|
|
||||||
// TODO: autoscroll here
|
|
||||||
if (!window->ContextMenu()) {
|
|
||||||
HiliteDropTarget(false);
|
|
||||||
fDropTarget = NULL;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
BPoseView::UpdateDropTarget(BPoint mouseLoc, const BMessage *dragMessage,
|
BPoseView::UpdateDropTarget(BPoint mouseLoc, const BMessage *dragMessage,
|
||||||
bool trackingContextMenu)
|
bool trackingContextMenu)
|
||||||
|
|||||||
@@ -161,10 +161,14 @@ class BPoseView : public BView {
|
|||||||
virtual void AttachedToWindow();
|
virtual void AttachedToWindow();
|
||||||
virtual void WindowActivated(bool);
|
virtual void WindowActivated(bool);
|
||||||
virtual void MakeFocus(bool = true);
|
virtual void MakeFocus(bool = true);
|
||||||
virtual void MouseMoved(BPoint, uint32, const BMessage *);
|
|
||||||
virtual void Draw(BRect update_rect);
|
virtual void Draw(BRect update_rect);
|
||||||
virtual void DrawAfterChildren(BRect update_rect);
|
virtual void DrawAfterChildren(BRect update_rect);
|
||||||
|
virtual void MouseMoved(BPoint, uint32, const BMessage *);
|
||||||
virtual void MouseDown(BPoint where);
|
virtual void MouseDown(BPoint where);
|
||||||
|
virtual void MouseUp(BPoint where);
|
||||||
|
virtual void MouseDragged(const BMessage *);
|
||||||
|
virtual void MouseLongDown(const BMessage *);
|
||||||
|
virtual void MouseIdle(const BMessage *);
|
||||||
virtual void KeyDown(const char *, int32);
|
virtual void KeyDown(const char *, int32);
|
||||||
virtual void Pulse();
|
virtual void Pulse();
|
||||||
virtual void MoveBy(float, float);
|
virtual void MoveBy(float, float);
|
||||||
@@ -355,7 +359,6 @@ class BPoseView : public BView {
|
|||||||
static bool CanHandleDragSelection(const Model *target,
|
static bool CanHandleDragSelection(const Model *target,
|
||||||
const BMessage *dragMessage, bool ignoreTypes);
|
const BMessage *dragMessage, bool ignoreTypes);
|
||||||
virtual void DragSelectedPoses(const BPose *clickedPose, BPoint);
|
virtual void DragSelectedPoses(const BPose *clickedPose, BPoint);
|
||||||
virtual void DragSelectionRect(BPoint, bool extendSelection);
|
|
||||||
|
|
||||||
void MoveSelectionInto(Model *destFolder, BContainerWindow *srcWindow,
|
void MoveSelectionInto(Model *destFolder, BContainerWindow *srcWindow,
|
||||||
bool forceCopy, bool forceMove = false, bool createLink = false, bool relativeLink = false);
|
bool forceCopy, bool forceMove = false, bool createLink = false, bool relativeLink = false);
|
||||||
@@ -574,13 +577,16 @@ class BPoseView : public BView {
|
|||||||
// click handling
|
// click handling
|
||||||
bool WasDoubleClick(const BPose *, BPoint);
|
bool WasDoubleClick(const BPose *, BPoint);
|
||||||
bool WasClickInPath(const BPose *, int32 index, BPoint) const;
|
bool WasClickInPath(const BPose *, int32 index, BPoint) const;
|
||||||
int32 WaitForMouseUpOrDrag(BPoint start);
|
|
||||||
|
|
||||||
// selection
|
// selection
|
||||||
void SelectPosesListMode(BRect, BList **);
|
void SelectPosesListMode(BRect, BList **);
|
||||||
void SelectPosesIconMode(BRect, BList **);
|
void SelectPosesIconMode(BRect, BList **);
|
||||||
void AddRemoveSelectionRange(BPoint where, bool extendSelection, BPose *);
|
void AddRemoveSelectionRange(BPoint where, bool extendSelection, BPose *);
|
||||||
|
|
||||||
|
void _BeginSelectionRect(const BPoint& point, bool extendSelection);
|
||||||
|
void _UpdateSelectionRect(const BPoint& point);
|
||||||
|
void _EndSelectionRect();
|
||||||
|
|
||||||
// view drawing
|
// view drawing
|
||||||
void SynchronousUpdate(BRect, bool clip = false);
|
void SynchronousUpdate(BRect, bool clip = false);
|
||||||
|
|
||||||
@@ -685,6 +691,18 @@ class BPoseView : public BView {
|
|||||||
const BPose *fRealPivotPose;
|
const BPose *fRealPivotPose;
|
||||||
BMessageRunner *fKeyRunner;
|
BMessageRunner *fKeyRunner;
|
||||||
|
|
||||||
|
struct SelectionRectInfo {
|
||||||
|
SelectionRectInfo()
|
||||||
|
: isDragging(false), selection(NULL) {};
|
||||||
|
bool isDragging;
|
||||||
|
BRect rect;
|
||||||
|
BRect lastRect;
|
||||||
|
BPoint startPoint;
|
||||||
|
BPoint lastPoint;
|
||||||
|
BList* selection;
|
||||||
|
};
|
||||||
|
SelectionRectInfo fSelectionRectInfo;
|
||||||
|
|
||||||
bool fSelectionVisible : 1;
|
bool fSelectionVisible : 1;
|
||||||
bool fMultipleSelection : 1;
|
bool fMultipleSelection : 1;
|
||||||
bool fDragEnabled : 1;
|
bool fDragEnabled : 1;
|
||||||
@@ -709,7 +727,6 @@ class BPoseView : public BView {
|
|||||||
int32 fLastFilterStringLength;
|
int32 fLastFilterStringLength;
|
||||||
|
|
||||||
BRect fStartFrame;
|
BRect fStartFrame;
|
||||||
BRect fSelectionRect;
|
|
||||||
|
|
||||||
static float sFontHeight;
|
static float sFontHeight;
|
||||||
static font_height sFontInfo;
|
static font_height sFontInfo;
|
||||||
|
|||||||
Reference in New Issue
Block a user