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) float y = (where.y - (frame.top + frame.bottom) / 2)
/ (frame.Height() + 1); / (frame.Height() + 1);
// compute the angle // compute the resize direction
if (x == 0 && y == 0) int8 horizontal;
return; int8 vertical;
_ComputeResizeDirection(x, y, horizontal, vertical);
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;
}
// update the highlight, if necessary // update the highlight, if necessary
if (horizontal != fHorizontal || vertical != fVertical) { 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 // #pragma mark - DefaultWindowBehaviour
@@ -870,6 +889,11 @@ DefaultWindowBehaviour::MouseDown(BMessage* message, BPoint where,
default: default:
break; 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")); STRACE_CLICK(("===> ACTION_RESIZE_BORDER\n"));
break; break;
case ACTION_HUMDINGER_RESIZE:
_NextState(new (std::nothrow) HumdingerResizeState(*this, where));
STRACE_CLICK(("===> ACTION_HUMDINGER_RESIZE\n"));
break;
default: default:
break; 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* ServerCursor*
DefaultWindowBehaviour::_ResizeCursorFor(int8 horizontal, int8 vertical) DefaultWindowBehaviour::_ResizeCursorFor(int8 horizontal, int8 vertical)
{ {
@@ -1163,3 +1168,82 @@ DefaultWindowBehaviour::_ResetResizeCursor()
{ {
fDesktop->SetManagementCursor(NULL); 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_DRAG,
ACTION_SLIDE_TAB, ACTION_SLIDE_TAB,
ACTION_RESIZE, ACTION_RESIZE,
ACTION_RESIZE_BORDER ACTION_RESIZE_BORDER,
ACTION_HUMDINGER_RESIZE
}; };
enum { enum {
@@ -71,6 +72,7 @@ private:
struct ResizeBorderState; struct ResizeBorderState;
struct DecoratorButtonState; struct DecoratorButtonState;
struct ManageWindowState; struct ManageWindowState;
struct HumdingerResizeState;
// to keep gcc 2 happy // to keep gcc 2 happy
friend struct State; friend struct State;
@@ -81,6 +83,7 @@ private:
friend struct ResizeBorderState; friend struct ResizeBorderState;
friend struct DecoratorButtonState; friend struct DecoratorButtonState;
friend struct ManageWindowState; friend struct ManageWindowState;
friend struct HumdingerResizeState;
private: private:
bool _IsWindowModifier(int32 modifiers) const; bool _IsWindowModifier(int32 modifiers) const;
@@ -94,6 +97,8 @@ private:
void _SetResizeCursor(int8 horizontal, void _SetResizeCursor(int8 horizontal,
int8 vertical); int8 vertical);
void _ResetResizeCursor(); void _ResetResizeCursor();
static void _ComputeResizeDirection(float x, float y,
int8& _horizontal, int8& _vertical);
void _NextState(State* state); void _NextState(State* state);