diff options
author | nyamatongwe <unknown> | 2007-05-12 00:30:55 +0000 |
---|---|---|
committer | nyamatongwe <unknown> | 2007-05-12 00:30:55 +0000 |
commit | 36188324937ce09d0752225927c9da7b5872f3cf (patch) | |
tree | 809de4c5021ce01c052ac4978fcabb21210adb49 | |
parent | c0869c9847487587d358025c6138297c74b5f3d6 (diff) | |
download | scintilla-mirror-36188324937ce09d0752225927c9da7b5872f3cf.tar.gz |
Drag operation does not start until mouse has been dragged more than
a threshold distance. Using platform threshold when possible.
Moved some common dragging code on Windows into EffectFromState.
-rw-r--r-- | gtk/ScintillaGTK.cxx | 13 | ||||
-rw-r--r-- | src/Editor.cxx | 65 | ||||
-rw-r--r-- | src/Editor.h | 5 | ||||
-rw-r--r-- | win32/ScintillaWin.cxx | 61 |
4 files changed, 91 insertions, 53 deletions
diff --git a/gtk/ScintillaGTK.cxx b/gtk/ScintillaGTK.cxx index 2e0291eeb..a873f1ada 100644 --- a/gtk/ScintillaGTK.cxx +++ b/gtk/ScintillaGTK.cxx @@ -156,6 +156,7 @@ private: virtual void Initialise(); virtual void Finalise(); virtual void DisplayCursor(Window::Cursor c); + virtual bool DragThreshold(Point ptStart, Point ptNow); virtual void StartDrag(); int TargetAsUTF8(char *text); int EncodedFromUTF8(char *utf8, char *encoded); @@ -788,8 +789,18 @@ void ScintillaGTK::DisplayCursor(Window::Cursor c) { wText.SetCursor(static_cast<Window::Cursor>(cursorMode)); } +bool ScintillaGTK::DragThreshold(Point ptStart, Point ptNow) { +#if GTK_MAJOR_VERSION < 2 + return Editor::DragThreshold(ptStart, ptNow); +#else + return gtk_drag_check_threshold(GTK_WIDGET(PWidget(wMain)), + ptStart.x, ptStart.y, ptNow.x, ptNow.y); +#endif +} + void ScintillaGTK::StartDrag() { dragWasDropped = false; + inDragDrop = ddDragging; static const GtkTargetEntry targets[] = { { "UTF8_STRING", 0, TARGET_UTF8_STRING }, { "STRING", 0, TARGET_STRING }, @@ -2345,7 +2356,6 @@ gboolean ScintillaGTK::DragMotion(GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint dragtime) { ScintillaGTK *sciThis = ScintillaFromWidget(widget); Point npt(x, y); - sciThis->inDragDrop = true; sciThis->SetDragPosition(sciThis->PositionFromLocation(npt)); GdkDragAction preferredAction = context->suggested_action; if (context->actions == static_cast<GdkDragAction> @@ -2369,6 +2379,7 @@ void ScintillaGTK::DragEnd(GtkWidget *widget, GdkDragContext * /*context*/) { sciThis->SetEmptySelection(sciThis->posDrag); sciThis->SetDragPosition(invalidPosition); //Platform::DebugPrintf("DragEnd %x %d\n", sciThis, sciThis->dragWasDropped); + sciThis->inDragDrop = ddNone; } gboolean ScintillaGTK::Drop(GtkWidget *widget, GdkDragContext * /*context*/, diff --git a/src/Editor.cxx b/src/Editor.cxx index addfedf6e..8a2000090 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -362,7 +362,7 @@ Editor::Editor() { dwelling = false; ptMouseLast.x = 0; ptMouseLast.y = 0; - inDragDrop = false; + inDragDrop = ddNone; dropWentOutside = false; posDrag = invalidPosition; posDrop = invalidPosition; @@ -5000,6 +5000,13 @@ void Editor::DisplayCursor(Window::Cursor c) { wMain.SetCursor(static_cast<Window::Cursor>(cursorMode)); } +bool Editor::DragThreshold(Point ptStart, Point ptNow) { + int xMove = ptStart.x - ptNow.x; + int yMove = ptStart.y - ptNow.y; + int distanceSquared = xMove * xMove + yMove * yMove; + return distanceSquared > 16; +} + void Editor::StartDrag() { // Always handled by subclasses //SetMouseCapture(true); @@ -5007,8 +5014,8 @@ void Editor::StartDrag() { } void Editor::DropAt(int position, const char *value, bool moving, bool rectangular) { - //Platform::DebugPrintf("DropAt %d\n", inDragDrop); - if (inDragDrop) + //Platform::DebugPrintf("DropAt %d %d\n", inDragDrop, position); + if (inDragDrop == ddDragging) dropWentOutside = false; int positionWasInSelection = PositionInSelection(position); @@ -5016,7 +5023,7 @@ void Editor::DropAt(int position, const char *value, bool moving, bool rectangul bool positionOnEdgeOfSelection = (position == SelectionStart()) || (position == SelectionEnd()); - if ((!inDragDrop) || !(0 == positionWasInSelection) || + if ((inDragDrop != ddDragging) || !(0 == positionWasInSelection) || (positionOnEdgeOfSelection && !moving)) { int selStart = SelectionStart(); @@ -5025,7 +5032,7 @@ void Editor::DropAt(int position, const char *value, bool moving, bool rectangul pdoc->BeginUndoAction(); int positionAfterDeletion = position; - if (inDragDrop && moving) { + if ((inDragDrop == ddDragging) && moving) { // Remove dragged out text if (rectangular || selType == selLines) { SelectionLineIterator lineIterator(this); @@ -5059,7 +5066,7 @@ void Editor::DropAt(int position, const char *value, bool moving, bool rectangul } pdoc->EndUndoAction(); } - } else if (inDragDrop) { + } else if (inDragDrop == ddDragging) { SetEmptySelection(position); } } @@ -5161,11 +5168,11 @@ void Editor::DwellEnd(bool mouseMoved) { } void Editor::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt) { - //Platform::DebugPrintf("Scintilla:ButtonDown %d %d = %d alt=%d\n", curTime, lastClickTime, curTime - lastClickTime, alt); + //Platform::DebugPrintf("ButtonDown %d %d = %d alt=%d %d\n", curTime, lastClickTime, curTime - lastClickTime, alt, inDragDrop); ptMouseLast = pt; int newPos = PositionFromLocation(pt); newPos = MovePositionOutsideChar(newPos, currentPos - newPos); - inDragDrop = false; + inDragDrop = ddNone; moveExtendsSelection = false; bool processed = NotifyMarginClick(pt, shift, ctrl, alt); @@ -5250,16 +5257,14 @@ void Editor::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, b NotifyHotSpotClicked(newPos, shift, ctrl, alt); } if (!shift) { - inDragDrop = PointInSelection(pt) && !SelectionEmpty(); + if (PointInSelection(pt) && !SelectionEmpty()) + inDragDrop = ddInitial; + else + inDragDrop = ddNone; } - if (inDragDrop) { - SetMouseCapture(false); - SetDragPosition(newPos); - CopySelectionRange(&drag); - StartDrag(); - } else { + SetMouseCapture(true); + if (inDragDrop != ddInitial) { SetDragPosition(invalidPosition); - SetMouseCapture(true); if (!shift) { SetEmptySelection(newPos); } @@ -5328,6 +5333,20 @@ void Editor::ButtonMove(Point pt) { if ((ptMouseLast.x != pt.x) || (ptMouseLast.y != pt.y)) { DwellEnd(true); } + + int movePos = PositionFromLocation(pt); + movePos = MovePositionOutsideChar(movePos, currentPos - movePos); + + if (inDragDrop == ddInitial) { + if (DragThreshold(ptMouseLast, pt)) { + SetMouseCapture(false); + SetDragPosition(movePos); + CopySelectionRange(&drag); + StartDrag(); + } + return; + } + ptMouseLast = pt; //Platform::DebugPrintf("Move %d %d\n", pt.x, pt.y); if (HaveMouseCapture()) { @@ -5339,8 +5358,6 @@ void Editor::ButtonMove(Point pt) { autoScrollTimer.ticksToWait = autoScrollDelay; // Adjust selection - int movePos = PositionFromLocation(pt); - movePos = MovePositionOutsideChar(movePos, currentPos - movePos); if (posDrag >= 0) { SetDragPosition(movePos); } else { @@ -5416,7 +5433,13 @@ void Editor::ButtonMove(Point pt) { } void Editor::ButtonUp(Point pt, unsigned int curTime, bool ctrl) { - //Platform::DebugPrintf("ButtonUp %d\n", HaveMouseCapture()); + //Platform::DebugPrintf("ButtonUp %d %d\n", HaveMouseCapture(), inDragDrop); + int newPos = PositionFromLocation(pt); + newPos = MovePositionOutsideChar(newPos, currentPos - newPos); + if (inDragDrop == ddInitial) { + inDragDrop = ddNone; + SetEmptySelection(newPos); + } if (HaveMouseCapture()) { if (PointInSelMargin(pt)) { DisplayCursor(Window::cursorReverseArrow); @@ -5429,7 +5452,7 @@ void Editor::ButtonUp(Point pt, unsigned int curTime, bool ctrl) { int newPos = PositionFromLocation(pt); newPos = MovePositionOutsideChar(newPos, currentPos - newPos); NotifyIndicatorClick(false, newPos, false, false, false); - if (inDragDrop) { + if (inDragDrop == ddDragging) { int selStart = SelectionStart(); int selEnd = SelectionEnd(); if (selStart < selEnd) { @@ -5468,7 +5491,7 @@ void Editor::ButtonUp(Point pt, unsigned int curTime, bool ctrl) { if (selType == selStream) { SetLastXChosen(); } - inDragDrop = false; + inDragDrop = ddNone; EnsureCaretVisible(false); } } diff --git a/src/Editor.h b/src/Editor.h index 04bf21958..ef061e46f 100644 --- a/src/Editor.h +++ b/src/Editor.h @@ -246,7 +246,7 @@ protected: // ScintillaBase subclass needs access to much of Editor bool dwelling; enum { selChar, selWord, selLine } selectionType; Point ptMouseLast; - bool inDragDrop; + enum { ddNone, ddInitial, ddDragging } inDragDrop; bool dropWentOutside; int posDrag; int posDrop; @@ -415,7 +415,7 @@ protected: // ScintillaBase subclass needs access to much of Editor virtual void AddCharUTF(char *s, unsigned int len, bool treatAsDBCS=false); void ClearSelection(); void ClearAll(); - void ClearDocumentStyle(); + void ClearDocumentStyle(); void Cut(); void PasteRectangular(int pos, const char *ptr, int len); virtual void Copy() = 0; @@ -489,6 +489,7 @@ protected: // ScintillaBase subclass needs access to much of Editor void CopyText(int length, const char *text); void SetDragPosition(int newPos); virtual void DisplayCursor(Window::Cursor c); + virtual bool DragThreshold(Point ptStart, Point ptNow); virtual void StartDrag(); void DropAt(int position, const char *value, bool moving, bool rectangular); /** PositionInSelection returns 0 if position in selection, -1 if position before selection, and 1 if after. diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx index 62d87fd9d..6d7f1268d 100644 --- a/win32/ScintillaWin.cxx +++ b/win32/ScintillaWin.cxx @@ -183,6 +183,7 @@ class ScintillaWin : enum { invalidTimerID, standardTimerID, idleTimerID }; + virtual bool DragThreshold(Point ptStart, Point ptNow); virtual void StartDrag(); sptr_t WndPaint(uptr_t wParam); sptr_t HandleComposition(uptr_t wParam, sptr_t lParam); @@ -224,6 +225,7 @@ class ScintillaWin : void FullPaint(); void FullPaintDC(HDC dc); bool IsCompatibleDC(HDC dc); + DWORD EffectFromState(DWORD grfKeyState); virtual int SetScrollInfo(int nBar, LPCSCROLLINFO lpsi, BOOL bRedraw); virtual bool GetScrollInfo(int nBar, LPSCROLLINFO lpsi); @@ -335,7 +337,15 @@ HWND ScintillaWin::MainHWND() { return reinterpret_cast<HWND>(wMain.GetID()); } +bool ScintillaWin::DragThreshold(Point ptStart, Point ptNow) { + int xMove = abs(ptStart.x - ptNow.x); + int yMove = abs(ptStart.y - ptNow.y); + return (xMove > ::GetSystemMetrics(SM_CXDRAG)) || + (yMove > ::GetSystemMetrics(SM_CYDRAG)); +} + void ScintillaWin::StartDrag() { + inDragDrop = ddDragging; DWORD dwEffect = 0; dropWentOutside = true; IDataObject *pDataObject = reinterpret_cast<IDataObject *>(&dob); @@ -352,7 +362,7 @@ void ScintillaWin::StartDrag() { ClearSelection(); } } - inDragDrop = false; + inDragDrop = ddNone; SetDragPosition(invalidPosition); } @@ -696,7 +706,7 @@ sptr_t ScintillaWin::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam case WM_SETCURSOR: if (LoWord(lParam) == HTCLIENT) { - if (inDragDrop) { + if (inDragDrop == ddDragging) { DisplayCursor(Window::cursorUp); } else { // Display regular (drag) cursor over selection @@ -868,8 +878,8 @@ sptr_t ScintillaWin::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam capturedMouse = false; return 0; - // These are not handled in Scintilla and its faster to dispatch them here. - // Also moves time out to here so profile doesn't count lots of empty message calls. + // These are not handled in Scintilla and its faster to dispatch them here. + // Also moves time out to here so profile doesn't count lots of empty message calls. case WM_MOVE: case WM_MOUSEACTIVATE: @@ -1978,6 +1988,20 @@ bool ScintillaWin::IsCompatibleDC(HDC hOtherDC) { return isCompatible; } +DWORD ScintillaWin::EffectFromState(DWORD grfKeyState) { + // These are the Wordpad semantics. + DWORD dwEffect; + if (inDragDrop == ddDragging) // Internal defaults to move + dwEffect = DROPEFFECT_MOVE; + else + dwEffect = DROPEFFECT_COPY; + if (grfKeyState & MK_ALT) + dwEffect = DROPEFFECT_MOVE; + if (grfKeyState & MK_CONTROL) + dwEffect = DROPEFFECT_COPY; + return dwEffect; +} + /// Implement IUnknown STDMETHODIMP ScintillaWin::QueryInterface(REFIID riid, PVOID *ppv) { *ppv = NULL; @@ -2020,14 +2044,7 @@ STDMETHODIMP ScintillaWin::DragEnter(LPDATAOBJECT pIDataSource, DWORD grfKeyStat return S_OK; } - if (inDragDrop) // Internal defaults to move - *pdwEffect = DROPEFFECT_MOVE; - else - *pdwEffect = DROPEFFECT_COPY; - if (grfKeyState & MK_ALT) - *pdwEffect = DROPEFFECT_MOVE; - if (grfKeyState & MK_CONTROL) - *pdwEffect = DROPEFFECT_COPY; + *pdwEffect = EffectFromState(grfKeyState); return S_OK; } @@ -2037,15 +2054,8 @@ STDMETHODIMP ScintillaWin::DragOver(DWORD grfKeyState, POINTL pt, PDWORD pdwEffe return S_OK; } - // These are the Wordpad semantics. - if (inDragDrop) // Internal defaults to move - *pdwEffect = DROPEFFECT_MOVE; - else - *pdwEffect = DROPEFFECT_COPY; - if (grfKeyState & MK_ALT) - *pdwEffect = DROPEFFECT_MOVE; - if (grfKeyState & MK_CONTROL) - *pdwEffect = DROPEFFECT_COPY; + *pdwEffect = EffectFromState(grfKeyState); + // Update the cursor. POINT rpt = {pt.x, pt.y}; ::ScreenToClient(MainHWND(), &rpt); @@ -2061,14 +2071,7 @@ STDMETHODIMP ScintillaWin::DragLeave() { STDMETHODIMP ScintillaWin::Drop(LPDATAOBJECT pIDataSource, DWORD grfKeyState, POINTL pt, PDWORD pdwEffect) { - if (inDragDrop) // Internal defaults to move - *pdwEffect = DROPEFFECT_MOVE; - else - *pdwEffect = DROPEFFECT_COPY; - if (grfKeyState & MK_ALT) - *pdwEffect = DROPEFFECT_MOVE; - if (grfKeyState & MK_CONTROL) - *pdwEffect = DROPEFFECT_COPY; + *pdwEffect = EffectFromState(grfKeyState); if (pIDataSource == NULL) return E_POINTER; |