Implemented Humdinger's resizing method, activated on Cmd-Ctrl-middle-click.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@39656 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2010-11-26 21:36:45 +00:00
parent a8e3ab4f46
commit 9f1aca35af
2 changed files with 161 additions and 72 deletions
+155 -71
View File
@@ -668,53 +668,10 @@ private:
float y = (where.y - (frame.top + frame.bottom) / 2)
/ (frame.Height() + 1);
// compute the angle
if (x == 0 && y == 0)
return;
float angle = atan2f(y, x);
// rotate by 22.5 degree to align our sectors with 45 degree multiples
angle += M_PI / 8;
// add 180 degree to the negative values, so we get a nice 0 to 360
// degree range
if (angle < 0)
angle += M_PI * 2;
int8 horizontal = NONE;
int8 vertical = NONE;
switch (int(angle / M_PI_4)) {
case 0:
horizontal = RIGHT;
break;
case 1:
horizontal = RIGHT;
vertical = BOTTOM;
break;
case 2:
vertical = BOTTOM;
break;
case 3:
horizontal = LEFT;
vertical = BOTTOM;
break;
case 4:
horizontal = LEFT;
break;
case 5:
horizontal = LEFT;
vertical = TOP;
break;
case 6:
vertical = TOP;
break;
case 7:
default:
horizontal = RIGHT;
vertical = TOP;
break;
}
// compute the resize direction
int8 horizontal;
int8 vertical;
_ComputeResizeDirection(x, y, horizontal, vertical);
// update the highlight, if necessary
if (horizontal != fHorizontal || vertical != fVertical) {
@@ -732,6 +689,68 @@ private:
};
// #pragma mark - State
struct DefaultWindowBehaviour::HumdingerResizeState : State {
HumdingerResizeState(DefaultWindowBehaviour& behavior, BPoint where)
:
State(behavior),
fInitialMousePosition(where),
fJitterPhase(true)
{
}
virtual void EnterState(State* previousState)
{
fDesktop->SetManagementCursor(
fDesktop->GetCursorManager().GetCursor(B_CURSOR_ID_MOVE));
}
virtual void ExitState(State* nextState)
{
fBehavior._ResetResizeCursor();
}
virtual void MouseUp(BMessage* message, BPoint where)
{
// Leave the state, when the middle mouse button has been released.
int32 buttons = message->FindInt32("buttons");
if ((buttons & B_TERTIARY_MOUSE_BUTTON) == 0)
fBehavior._NextState(NULL);
}
virtual void MouseMoved(BMessage* message, BPoint where, bool isFake)
{
// ignore the initial movement
float dx = where.x - fInitialMousePosition.x;
float dy = where.y - fInitialMousePosition.y;
if (dx * dx + dy * dy < (fJitterPhase ? 16 : 64))
return;
// Enter the next phase, if we're still in the first one.
if (fJitterPhase) {
fInitialMousePosition = where;
fJitterPhase = false;
return;
}
// The mouse has moved far enough for us to take a guess in which
// direction.
int8 horizontal;
int8 vertical;
_ComputeResizeDirection(dx, dy, horizontal, vertical);
fBehavior._NextState(new (std::nothrow) ResizeBorderState(fBehavior,
where, horizontal, vertical));
}
private:
BPoint fInitialMousePosition;
bool fJitterPhase;
};
// #pragma mark - DefaultWindowBehaviour
@@ -870,6 +889,11 @@ DefaultWindowBehaviour::MouseDown(BMessage* message, BPoint where,
default:
break;
}
} else if ((buttons & B_TERTIARY_MOUSE_BUTTON) != 0) {
// Middle-click anywhere on the window shall initiate
// humdinger-resize mode.
if (windowModifier && hitRegion != Decorator::REGION_NONE)
action = ACTION_HUMDINGER_RESIZE;
}
}
@@ -939,6 +963,11 @@ DefaultWindowBehaviour::MouseDown(BMessage* message, BPoint where,
STRACE_CLICK(("===> ACTION_RESIZE_BORDER\n"));
break;
case ACTION_HUMDINGER_RESIZE:
_NextState(new (std::nothrow) HumdingerResizeState(*this, where));
STRACE_CLICK(("===> ACTION_HUMDINGER_RESIZE\n"));
break;
default:
break;
}
@@ -1096,30 +1125,6 @@ DefaultWindowBehaviour::_SetBorderHighlights(int8 horizontal, int8 vertical,
}
void
DefaultWindowBehaviour::_NextState(State* state)
{
// exit the old state
if (fState != NULL)
fState->ExitState(state);
// set and enter the new state
State* oldState = fState;
fState = state;
if (fState != NULL) {
fState->EnterState(oldState);
fDesktop->SetMouseEventWindow(fWindow);
} else if (oldState != NULL) {
// no state anymore -- reset the mouse event window, if it's still us
if (fDesktop->MouseEventWindow() == fWindow)
fDesktop->SetMouseEventWindow(NULL);
}
delete oldState;
}
ServerCursor*
DefaultWindowBehaviour::_ResizeCursorFor(int8 horizontal, int8 vertical)
{
@@ -1163,3 +1168,82 @@ DefaultWindowBehaviour::_ResetResizeCursor()
{
fDesktop->SetManagementCursor(NULL);
}
/*static*/ void
DefaultWindowBehaviour::_ComputeResizeDirection(float x, float y,
int8& _horizontal, int8& _vertical)
{
_horizontal = NONE;
_vertical = NONE;
// compute the angle
if (x == 0 && y == 0)
return;
float angle = atan2f(y, x);
// rotate by 22.5 degree to align our sectors with 45 degree multiples
angle += M_PI / 8;
// add 180 degree to the negative values, so we get a nice 0 to 360
// degree range
if (angle < 0)
angle += M_PI * 2;
switch (int(angle / M_PI_4)) {
case 0:
_horizontal = RIGHT;
break;
case 1:
_horizontal = RIGHT;
_vertical = BOTTOM;
break;
case 2:
_vertical = BOTTOM;
break;
case 3:
_horizontal = LEFT;
_vertical = BOTTOM;
break;
case 4:
_horizontal = LEFT;
break;
case 5:
_horizontal = LEFT;
_vertical = TOP;
break;
case 6:
_vertical = TOP;
break;
case 7:
default:
_horizontal = RIGHT;
_vertical = TOP;
break;
}
}
void
DefaultWindowBehaviour::_NextState(State* state)
{
// exit the old state
if (fState != NULL)
fState->ExitState(state);
// set and enter the new state
State* oldState = fState;
fState = state;
if (fState != NULL) {
fState->EnterState(oldState);
fDesktop->SetMouseEventWindow(fWindow);
} else if (oldState != NULL) {
// no state anymore -- reset the mouse event window, if it's still us
if (fDesktop->MouseEventWindow() == fWindow)
fDesktop->SetMouseEventWindow(NULL);
}
delete oldState;
}
+6 -1
View File
@@ -49,7 +49,8 @@ private:
ACTION_DRAG,
ACTION_SLIDE_TAB,
ACTION_RESIZE,
ACTION_RESIZE_BORDER
ACTION_RESIZE_BORDER,
ACTION_HUMDINGER_RESIZE
};
enum {
@@ -71,6 +72,7 @@ private:
struct ResizeBorderState;
struct DecoratorButtonState;
struct ManageWindowState;
struct HumdingerResizeState;
// to keep gcc 2 happy
friend struct State;
@@ -81,6 +83,7 @@ private:
friend struct ResizeBorderState;
friend struct DecoratorButtonState;
friend struct ManageWindowState;
friend struct HumdingerResizeState;
private:
bool _IsWindowModifier(int32 modifiers) const;
@@ -94,6 +97,8 @@ private:
void _SetResizeCursor(int8 horizontal,
int8 vertical);
void _ResetResizeCursor();
static void _ComputeResizeDirection(float x, float y,
int8& _horizontal, int8& _vertical);
void _NextState(State* state);