// MessageReceived bool PathManipulator::MessageReceived(BMessage* message, Command** _command) { bool result = true; switch (message->what) { case MSG_TRANSFORM: if (!fSelection->IsEmpty()) _SetMode(TRANSFORM_POINTS); break; case MSG_REMOVE_POINTS: *_command = _Delete(); break; case MSG_SPLIT_POINTS: *_command = new SplitPointsCommand(fPath, fSelection->Items(), fSelection->CountItems()); break; case MSG_FLIP_POINTS: *_command = new FlipPointsCommand(fPath, fSelection->Items(), fSelection->CountItems()); break; case B_SELECT_ALL: { *fOldSelection = *fSelection; fSelection->MakeEmpty(); int32 count = fPath->CountPoints(); for (int32 i = 0; i < count; i++) fSelection->Add(i); if (*fOldSelection != *fSelection) { // *_command = new SelectPointsCommand(this, fPath, // fOldSelection->Items(), // fOldSelection->CountItems(), // fSelection->Items(), // fSelection->CountItems())); count = fSelection->CountItems(); int32 indices[count]; memcpy(indices, fSelection->Items(), count * sizeof(int32)); _Select(indices, count); } break; } default: result = false; break; } return result; }
void EditMode::CycleModes() { SYS::ScopedLock lock(_mtx); _SetMode(GetNextMode()); _NotifyObservers(); }
void EditMode::SetMode(Enum mode) { SYS::ScopedLock lock(_mtx); _SetMode(mode); _NotifyObservers(); }
// HandleKeyDown bool PathManipulator::HandleKeyDown(uint32 key, uint32 modifiers, Command** _command) { bool result = true; float nudgeDist = 1.0; if (modifiers & B_SHIFT_KEY) nudgeDist /= fCanvasView->ZoomLevel(); switch (key) { // commit case B_RETURN: if (fTransformBox) { _SetTransformBox(NULL); }// else // _Perform(); break; // cancel case B_ESCAPE: if (fTransformBox) { fTransformBox->Cancel(); _SetTransformBox(NULL); } else if (fFallBackMode == NEW_PATH) { fFallBackMode = SELECT_POINTS; _SetTransformBox(NULL); }// else // _Cancel(); break; case 't': case 'T': if (!fSelection->IsEmpty()) _SetMode(TRANSFORM_POINTS); else result = false; break; // nudging case B_UP_ARROW: _Nudge(BPoint(0.0, -nudgeDist)); break; case B_DOWN_ARROW: _Nudge(BPoint(0.0, nudgeDist)); break; case B_LEFT_ARROW: _Nudge(BPoint(-nudgeDist, 0.0)); break; case B_RIGHT_ARROW: _Nudge(BPoint(nudgeDist, 0.0)); break; case B_DELETE: if (!fSelection->IsEmpty()) *_command = _Delete(); else result = false; break; default: result = false; } return result; }
// MouseUp Command* PathManipulator::MouseUp() { // prevent carrying out actions more than once by only // doing it if "fMouseDown" is true at the point of // entering this function if (!fMouseDown) return NULL; fMouseDown = false; if (fMode == TRANSFORM_POINTS) { if (fTransformBox) { return fTransformBox->MouseUp(); } return NULL; } Command* command = NULL; switch (fMode) { case ADD_POINT: command = fAddPointCommand; fAddPointCommand = NULL; _SetMode(MOVE_POINT_OUT); break; case INSERT_POINT: command = fInsertPointCommand; fInsertPointCommand = NULL; break; case SELECT_POINTS: if (*fSelection != *fOldSelection) { // command = new SelectPointsCommand(this, fPath, // fOldSelection->Items(), // fOldSelection->CountItems(), // fSelection->Items(), // fSelection->CountItems())); } fCanvasView->EndRectTracking(); break; case TOGGLE_SHARP: case TOGGLE_SHARP_IN: case TOGGLE_SHARP_OUT: case MOVE_POINT: case MOVE_POINT_IN: case MOVE_POINT_OUT: case REMOVE_POINT_IN: case REMOVE_POINT_OUT: command = fChangePointCommand; fChangePointCommand = NULL; break; case TRANSLATE_POINTS: if (!fNudgeCommand) { // select just the point that was clicked *fOldSelection = *fSelection; if (fCurrentPathPoint >= 0) { _Select(fCurrentPathPoint, fShiftDown); } if (*fSelection != *fOldSelection) { // command = new SelectPointsCommand(this, fPath, // fOldSelection->Items(), // fOldSelection->CountItems(), // fSelection->Items(), // fSelection->CountItems())); } } else { command = _FinishNudging(); } break; } return command; }
// MouseMoved void PathManipulator::MouseMoved(BPoint where) { fCanvasView->FilterMouse(&where); // NOTE: only filter mouse coords in mouse moved, no other // mouse function BPoint canvasWhere = where; fCanvasView->ConvertToCanvas(&canvasWhere); // since the tablet is generating mouse moved messages // even if only the pressure changes (and not the actual mouse position) // we insert this additional check to prevent too much calculation if (fLastCanvasPos == canvasWhere) return; fLastCanvasPos = canvasWhere; if (fMode == TRANSFORM_POINTS) { if (fTransformBox) { fTransformBox->MouseMoved(where); } return; } if (fMode == CLOSE_PATH) { // continue by moving the point _SetMode(MOVE_POINT); delete fChangePointCommand; fChangePointCommand = new ChangePointCommand(fPath, fCurrentPathPoint, fSelection->Items(), fSelection->CountItems()); } // if (!fPrecise) { // float offset = fmod(fOutlineWidth, 2.0) / 2.0; // canvasWhere.point += BPoint(offset, offset); // } switch (fMode) { case ADD_POINT: case INSERT_POINT: case TOGGLE_SHARP: // drag the "out" control point, mirror the "in" control point fPath->SetPointOut(fCurrentPathPoint, canvasWhere, true); break; case MOVE_POINT: // drag all three control points at once fPath->SetPoint(fCurrentPathPoint, canvasWhere); break; case MOVE_POINT_IN: // drag in control point fPath->SetPointIn(fCurrentPathPoint, canvasWhere); break; case MOVE_POINT_OUT: // drag out control point fPath->SetPointOut(fCurrentPathPoint, canvasWhere); break; case SELECT_POINTS: { // change the selection BRect r; r.left = min_c(fTrackingStart.x, canvasWhere.x); r.top = min_c(fTrackingStart.y, canvasWhere.y); r.right = max_c(fTrackingStart.x, canvasWhere.x); r.bottom = max_c(fTrackingStart.y, canvasWhere.y); _Select(r); break; } case TRANSLATE_POINTS: { BPoint offset = canvasWhere - fTrackingStart; _Nudge(offset); fTrackingStart = canvasWhere; break; } } }
// MouseDown bool PathManipulator::MouseDown(BPoint where) { fMouseDown = true; if (fMode == TRANSFORM_POINTS) { if (fTransformBox) { fTransformBox->MouseDown(where); // if (!fTransformBox->IsRotating()) // fCanvasView->SetAutoScrolling(true); } return true; } if (fMode == MOVE_POINT && fSelection->CountItems() > 1 && fSelection->Contains(fCurrentPathPoint)) { fMode = TRANSLATE_POINTS; } // apply the canvas view mouse filter depending on current mode if (fMode == ADD_POINT || fMode == TRANSLATE_POINTS) fCanvasView->FilterMouse(&where); BPoint canvasWhere = where; fCanvasView->ConvertToCanvas(&canvasWhere); // maybe we're changing some point, so we construct the // "ChangePointCommand" here so that the point is remembered // in its current state // apply the canvas view mouse filter depending on current mode delete fChangePointCommand; fChangePointCommand = NULL; switch (fMode) { case TOGGLE_SHARP: case TOGGLE_SHARP_IN: case TOGGLE_SHARP_OUT: case MOVE_POINT: case MOVE_POINT_IN: case MOVE_POINT_OUT: case REMOVE_POINT_IN: case REMOVE_POINT_OUT: fChangePointCommand = new ChangePointCommand(fPath, fCurrentPathPoint, fSelection->Items(), fSelection->CountItems()); _Select(fCurrentPathPoint, fShiftDown); break; } // at this point we init doing something switch (fMode) { case ADD_POINT: _AddPoint(canvasWhere); break; case INSERT_POINT: _InsertPoint(canvasWhere, fCurrentPathPoint); break; case TOGGLE_SHARP: _SetSharp(fCurrentPathPoint); // continue by dragging out the _connected_ in/out points break; case TOGGLE_SHARP_IN: _SetInOutConnected(fCurrentPathPoint, false); // continue by moving the "in" point _SetMode(MOVE_POINT_IN); break; case TOGGLE_SHARP_OUT: _SetInOutConnected(fCurrentPathPoint, false); // continue by moving the "out" point _SetMode(MOVE_POINT_OUT); break; case MOVE_POINT: case MOVE_POINT_IN: case MOVE_POINT_OUT: // the right thing happens since "fCurrentPathPoint" // points to the correct index break; case CLOSE_PATH: // SetClosed(true, true); break; case REMOVE_POINT: if (fPath->CountPoints() == 1) { // fCanvasView->Perform(new RemovePathCommand(this, fPath)); } else { fCanvasView->Perform(new RemovePointsCommand(fPath, fCurrentPathPoint, fSelection->Items(), fSelection->CountItems())); _RemovePoint(fCurrentPathPoint); } break; case REMOVE_POINT_IN: _RemovePointIn(fCurrentPathPoint); break; case REMOVE_POINT_OUT: _RemovePointOut(fCurrentPathPoint); break; case SELECT_POINTS: { // TODO: this works so that you can deselect all points // when clicking outside the path even if pressing shift // in case the path is open... a better way would be // to deselect all on mouse up, if the mouse has not moved bool appendSelection; if (fPath->IsClosed()) appendSelection = fShiftDown; else appendSelection = fShiftDown && fCurrentPathPoint >= 0; if (!appendSelection) { fSelection->MakeEmpty(); _UpdateSelection(); } *fOldSelection = *fSelection; if (fCurrentPathPoint >= 0) { _Select(fCurrentPathPoint, appendSelection); } fCanvasView->BeginRectTracking(BRect(where, where), B_TRACK_RECT_CORNER); break; } } fTrackingStart = canvasWhere; // remember the subpixel position // so that MouseMoved() will work even before // the integer position becomes different fLastCanvasPos = where; fCanvasView->ConvertToCanvas(&fLastCanvasPos); // the reason to exclude the select mode // is that the BView rect tracking does not // scroll the rect starting point along with us // (since we're doing no real scrolling) // if (fMode != SELECT_POINTS) // fCanvasView->SetAutoScrolling(true); UpdateCursor(); return true; }
// _SetModeForMousePos void PathManipulator::_SetModeForMousePos(BPoint where) { uint32 mode = UNDEFINED; int32 index = -1; float zoomLevel = fCanvasView->ZoomLevel(); // see if we're close enough at a control point BPoint point; BPoint pointIn; BPoint pointOut; for (int32 i = 0; fPath->GetPointsAt(i, point, pointIn, pointOut) && mode == UNDEFINED; i++) { float distM = point_point_distance(point, where) * zoomLevel; float distIn = point_point_distance(pointIn, where) * zoomLevel; float distOut = point_point_distance(pointOut, where) * zoomLevel; if (distM < MOVE_THRESHOLD) { if (i == 0 && fClickToClose && !fPath->IsClosed() && fPath->CountPoints() > 1) { mode = fCommandDown ? TOGGLE_SHARP : (fOptionDown ? REMOVE_POINT : CLOSE_PATH); index = i; } else { mode = fCommandDown ? TOGGLE_SHARP : (fOptionDown ? REMOVE_POINT : MOVE_POINT); index = i; } } if (distM - distIn > 0.00001 && distIn < MOVE_THRESHOLD) { mode = fCommandDown ? TOGGLE_SHARP_IN : (fOptionDown ? REMOVE_POINT_IN : MOVE_POINT_IN); index = i; } if (distIn - distOut > 0.00001 && distOut < distM && distOut < MOVE_THRESHOLD) { mode = fCommandDown ? TOGGLE_SHARP_OUT : (fOptionDown ? REMOVE_POINT_OUT : MOVE_POINT_OUT); index = i; } } // selection mode overrides any other mode, // but we need to check for it after we know // the index of the point under the mouse (code above) int32 pointCount = fPath->CountPoints(); if (fShiftDown && pointCount > 0) { mode = SELECT_POINTS; } // see if user wants to start new sub path if (fAltDown) { mode = NEW_PATH; index = -1; } // see if we're close enough at a line if (mode == UNDEFINED) { float distance; if (fPath->GetDistance(where, &distance, &index)) { if (distance < (INSERT_DIST_THRESHOLD / zoomLevel)) { mode = INSERT_POINT; } } else { // restore index, since it was changed by call above index = fCurrentPathPoint; } } // nope, still undefined mode, last fall back if (mode == UNDEFINED) { if (fFallBackMode == SELECT_POINTS) { if (fPath->IsClosed() && pointCount > 0) { mode = SELECT_POINTS; index = -1; } else { mode = ADD_POINT; index = pointCount - 1; } } else { // user had clicked "New Path" icon mode = fFallBackMode; } } // switch mode if necessary if (mode != fMode || index != fCurrentPathPoint) { // invalidate path display (to highlight the respective point) _InvalidateHighlightPoints(index, mode); _SetMode(mode); fCurrentPathPoint = index; } }