From 97573c80a03903fb01921aa0951816dec866fc43 Mon Sep 17 00:00:00 2001 From: Don HO Date: Sun, 5 Mar 2017 14:03:02 +0100 Subject: [PATCH] (In progress) New feature: check content via Document Map while mouse hovering on a inactivated tab --- PowerEditor/src/NppNotification.cpp | 32 ++++ .../WinControls/DockingWnd/DockingCont.cpp | 2 +- .../WinControls/DocumentMap/documentMap.cpp | 68 +++++--- .../src/WinControls/DocumentMap/documentMap.h | 11 +- PowerEditor/src/WinControls/TabBar/TabBar.cpp | 162 ++++++++++-------- PowerEditor/src/WinControls/TabBar/TabBar.h | 8 +- 6 files changed, 187 insertions(+), 96 deletions(-) diff --git a/PowerEditor/src/NppNotification.cpp b/PowerEditor/src/NppNotification.cpp index 714f28aa..c1e5e1c7 100644 --- a/PowerEditor/src/NppNotification.cpp +++ b/PowerEditor/src/NppNotification.cpp @@ -148,6 +148,38 @@ BOOL Notepad_plus::notify(SCNotification *notification) break; } + case TCN_MOUSEHOVERING: + case TCN_MOUSEHOVERSWITCHING: + { + /* + if (_pDocMap && (!_pDocMap->isClosed()) && _pDocMap->isVisible()) + { + TBHDR *tbHdr = reinterpret_cast(notification); + DocTabView *pTabDocView = isFromPrimary ? &_mainDocTab : (isFromSecondary ? &_subDocTab : nullptr); + if (pTabDocView) + { + BufferID id = pTabDocView->getBufferByIndex(tbHdr->tabOrigin); + Buffer * pBuf = MainFileManager->getBufferByID(id); + _pDocMap->showInMapTemporily(pBuf, notifyView); + _pDocMap->setSyntaxHiliting(); + } + } + */ + break; + } + + case TCN_MOUSELEAVING: + { + /* + if (_pDocMap && (!_pDocMap->isClosed()) && _pDocMap->isVisible()) + { + _pDocMap->reloadMap(); + _pDocMap->setSyntaxHiliting(); + } + */ + break; + } + case TCN_TABDROPPEDOUTSIDE: case TCN_TABDROPPED: { diff --git a/PowerEditor/src/WinControls/DockingWnd/DockingCont.cpp b/PowerEditor/src/WinControls/DockingWnd/DockingCont.cpp index 02f0b8b6..b78823f9 100644 --- a/PowerEditor/src/WinControls/DockingWnd/DockingCont.cpp +++ b/PowerEditor/src/WinControls/DockingWnd/DockingCont.cpp @@ -568,7 +568,7 @@ void DockingCont::drawCaptionItem(DRAWITEMSTRUCT *pDrawItemStruct) ::DeleteObject(bgbrush); // draw button - HDC dcMem = ::CreateCompatibleDC(NULL); + HDC dcMem = ::CreateCompatibleDC(NULL); // select correct bitmap if ((_isMouseOver == TRUE) && (_isMouseDown == TRUE)) diff --git a/PowerEditor/src/WinControls/DocumentMap/documentMap.cpp b/PowerEditor/src/WinControls/DocumentMap/documentMap.cpp index 46cb704c..677d9dc8 100644 --- a/PowerEditor/src/WinControls/DocumentMap/documentMap.cpp +++ b/PowerEditor/src/WinControls/DocumentMap/documentMap.cpp @@ -59,6 +59,27 @@ void DocumentMap::reloadMap() } } +void DocumentMap::showInMapTemporarily(Buffer *buf2show, const ScintillaEditView *fromEditView) +{ + if (_pScintillaEditView && fromEditView) + { + _pScintillaEditView->execute(SCI_SETDOCPOINTER, 0, static_cast(buf2show->getDocument())); + _pScintillaEditView->setCurrentBuffer(buf2show); + + // folding + const std::vector & lineStateVector = buf2show->getHeaderLineState(fromEditView); + _pScintillaEditView->syncFoldStateWith(lineStateVector); + + // Wrapping + if (fromEditView->isWrap() && needToRecomputeWith(fromEditView)) + { + wrapMap(fromEditView); + } + + //scrollMap(fromEditView); + } +} + void DocumentMap::setSyntaxHiliting() { Buffer *buf = _pScintillaEditView->getCurrentBuffer(); @@ -66,13 +87,15 @@ void DocumentMap::setSyntaxHiliting() _pScintillaEditView->showMargin(ScintillaEditView::_SC_MARGE_FOLDER, false); } -bool DocumentMap::needToRecomputeWith() +bool DocumentMap::needToRecomputeWith(const ScintillaEditView *editView) { - auto currentZoom = (*_ppEditView)->execute(SCI_GETZOOM); + const ScintillaEditView *pEditView = editView ? editView : *_ppEditView; + + auto currentZoom = pEditView->execute(SCI_GETZOOM); if (_displayZoom != currentZoom) return true; - int currentTextZoneWidth = getEditorTextZoneWidth(); + int currentTextZoneWidth = getEditorTextZoneWidth(editView); if (_displayWidth != currentTextZoneWidth) return true; @@ -141,18 +164,19 @@ sprintf(dchar, "%f", ddd); double zoomRatio[] = {1, 1, 1, 1, 1.5, 2, 2.5, 2.5, 3.5, 3.5,\ 4, 4.5, 5, 5, 5.5, 6, 6.5, 7, 7, 7.5, 8, 8.5, 8.5, 9.5, 9.5, 10, 10.5, 11, 11, 11.5, 12}; -void DocumentMap::wrapMap() +void DocumentMap::wrapMap(const ScintillaEditView *editView) { + const ScintillaEditView *pEditView = editView ? editView : *_ppEditView; RECT rect; getClientRect(rect); - if ((*_ppEditView)->isWrap()) + if (pEditView->isWrap()) { // get current scintilla width W1 - int editZoneWidth = getEditorTextZoneWidth(); + int editZoneWidth = getEditorTextZoneWidth(editView); // update the wrap needed data _displayWidth = editZoneWidth; - _displayZoom = static_cast((*_ppEditView)->execute(SCI_GETZOOM)); + _displayZoom = static_cast(pEditView->execute(SCI_GETZOOM)); double zr = zoomRatio[_displayZoom + 10]; // compute doc map width: dzw/ezw = 1/zoomRatio @@ -162,39 +186,43 @@ void DocumentMap::wrapMap() _pScintillaEditView->wrap(true); // sync wrapping indent mode - _pScintillaEditView->execute(SCI_SETWRAPINDENTMODE, (*_ppEditView)->execute(SCI_GETWRAPINDENTMODE)); + _pScintillaEditView->execute(SCI_SETWRAPINDENTMODE, pEditView->execute(SCI_GETWRAPINDENTMODE)); } } -int DocumentMap::getEditorTextZoneWidth() +int DocumentMap::getEditorTextZoneWidth(const ScintillaEditView *editView) { + const ScintillaEditView *pEditView = editView ? editView : *_ppEditView; + RECT editorRect; - (*_ppEditView)->getClientRect(editorRect); + pEditView->getClientRect(editorRect); int marginWidths = 0; for (int m = 0; m < 4; ++m) { - marginWidths += static_cast((*_ppEditView)->execute(SCI_GETMARGINWIDTHN, m)); + marginWidths += static_cast(pEditView->execute(SCI_GETMARGINWIDTHN, m)); } return editorRect.right - editorRect.left - marginWidths; } -void DocumentMap::scrollMap() +void DocumentMap::scrollMap(const ScintillaEditView *editView) { - if (_pScintillaEditView && _ppEditView) + const ScintillaEditView *pEditView = editView ? editView : *_ppEditView; + + if (_pScintillaEditView && pEditView) { // Visible document line for the code view (but not displayed line) - auto firstVisibleDisplayLine = (*_ppEditView)->execute(SCI_GETFIRSTVISIBLELINE); - auto firstVisibleDocLine = (*_ppEditView)->execute(SCI_DOCLINEFROMVISIBLE, firstVisibleDisplayLine); - auto nbLine = (*_ppEditView)->execute(SCI_LINESONSCREEN, firstVisibleDisplayLine); - auto lastVisibleDocLine = (*_ppEditView)->execute(SCI_DOCLINEFROMVISIBLE, firstVisibleDisplayLine + nbLine); + auto firstVisibleDisplayLine = pEditView->execute(SCI_GETFIRSTVISIBLELINE); + auto firstVisibleDocLine = pEditView->execute(SCI_DOCLINEFROMVISIBLE, firstVisibleDisplayLine); + auto nbLine = pEditView->execute(SCI_LINESONSCREEN, firstVisibleDisplayLine); + auto lastVisibleDocLine = pEditView->execute(SCI_DOCLINEFROMVISIBLE, firstVisibleDisplayLine + nbLine); // Visible document line for the map view auto firstVisibleDisplayLineMap = _pScintillaEditView->execute(SCI_GETFIRSTVISIBLELINE); auto firstVisibleDocLineMap = _pScintillaEditView->execute(SCI_DOCLINEFROMVISIBLE, firstVisibleDisplayLineMap); auto nbLineMap = _pScintillaEditView->execute(SCI_LINESONSCREEN, firstVisibleDocLineMap); - auto lastVisibleDocLineMap = (*_ppEditView)->execute(SCI_DOCLINEFROMVISIBLE, firstVisibleDisplayLineMap + nbLineMap); + auto lastVisibleDocLineMap = pEditView->execute(SCI_DOCLINEFROMVISIBLE, firstVisibleDisplayLineMap + nbLineMap); // If part of editor view is out of map, then scroll map if (lastVisibleDocLineMap < lastVisibleDocLine) @@ -205,7 +233,7 @@ void DocumentMap::scrollMap() // Get the editor's higher/lower Y, then compute the map's higher/lower Y LRESULT higherY = 0; LRESULT lowerY = 0; - if (!(*_ppEditView)->isWrap()) + if (not pEditView->isWrap()) { auto higherPos = _pScintillaEditView->execute(SCI_POSITIONFROMLINE, firstVisibleDocLine); auto lowerPos = _pScintillaEditView->execute(SCI_POSITIONFROMLINE, lastVisibleDocLine); @@ -219,7 +247,7 @@ void DocumentMap::scrollMap() } else { - auto higherPos = (*_ppEditView)->execute(SCI_POSITIONFROMPOINT, 0, 0); + auto higherPos = pEditView->execute(SCI_POSITIONFROMPOINT, 0, 0); higherY = _pScintillaEditView->execute(SCI_POINTYFROMPOSITION, 0, higherPos); auto lineHeight = _pScintillaEditView->execute(SCI_TEXTHEIGHT, firstVisibleDocLine); lowerY = nbLine * lineHeight + higherY; diff --git a/PowerEditor/src/WinControls/DocumentMap/documentMap.h b/PowerEditor/src/WinControls/DocumentMap/documentMap.h index f0942d54..4449da03 100644 --- a/PowerEditor/src/WinControls/DocumentMap/documentMap.h +++ b/PowerEditor/src/WinControls/DocumentMap/documentMap.h @@ -38,6 +38,8 @@ #define DOCUMENTMAP_MOUSEWHEEL (WM_USER + 3) class ScintillaEditView; +class Buffer; + const bool moveDown = true; const bool moveUp = false; @@ -118,9 +120,10 @@ public: } void reloadMap(); - void wrapMap(); + void showInMapTemporarily(Buffer *buf2show, const ScintillaEditView *fromEditView); + void wrapMap(const ScintillaEditView *editView = nullptr); void initWrapMap(); - void scrollMap(); + void scrollMap(const ScintillaEditView *editView = nullptr); void scrollMap(bool direction, moveMode whichMode); void doMove(); void fold(int line, bool foldOrNot); @@ -130,8 +133,8 @@ public: protected: virtual INT_PTR CALLBACK run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam); - bool needToRecomputeWith(); - int getEditorTextZoneWidth(); + bool needToRecomputeWith(const ScintillaEditView *editView = nullptr); + int getEditorTextZoneWidth(const ScintillaEditView *editView = nullptr); private: ScintillaEditView **_ppEditView = nullptr; diff --git a/PowerEditor/src/WinControls/TabBar/TabBar.cpp b/PowerEditor/src/WinControls/TabBar/TabBar.cpp index 83f76f5f..92df2de8 100644 --- a/PowerEditor/src/WinControls/TabBar/TabBar.cpp +++ b/PowerEditor/src/WinControls/TabBar/TabBar.cpp @@ -423,6 +423,24 @@ void TabBarPlus::doMultiLine() } } +void TabBarPlus::notify(int notifyCode, int tabIndex) +{ + TBHDR nmhdr; + nmhdr.hdr.hwndFrom = _hSelf; + nmhdr.hdr.code = notifyCode; + nmhdr.hdr.idFrom = reinterpret_cast(this); + nmhdr.tabOrigin = tabIndex; + ::SendMessage(_hParent, WM_NOTIFY, 0, reinterpret_cast(&nmhdr)); +} + +void TabBarPlus::trackMouseEvent(DWORD event2check) +{ + TRACKMOUSEEVENT tme = {}; + tme.cbSize = sizeof(tme); + tme.dwFlags = event2check; + tme.hwndTrack = _hSelf; + TrackMouseEvent(&tme); +} LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) { @@ -574,13 +592,7 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara } } - TBHDR nmhdr; - nmhdr.hdr.hwndFrom = _hSelf; - nmhdr.hdr.code = NM_CLICK; - nmhdr.hdr.idFrom = reinterpret_cast(this); - nmhdr.tabOrigin = currentTabOn; - - ::SendMessage(_hParent, WM_NOTIFY, 0, reinterpret_cast(&nmhdr)); + notify(NM_CLICK, currentTabOn); return TRUE; } @@ -594,11 +606,12 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara //#define NPPM_INTERNAL_ISDRAGGING 40926 case WM_MOUSEMOVE : { + POINT p; + p.x = LOWORD(lParam); + p.y = HIWORD(lParam); + if (_isDragging) { - POINT p; - p.x = LOWORD(lParam); - p.y = HIWORD(lParam); exchangeItemData(p); // Get cursor position of "Screen" @@ -607,45 +620,80 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara draggingCursor(_draggingPoint); return TRUE; } - - if (_drawTabCloseButton) + else { - int xPos = LOWORD(lParam); - int yPos = HIWORD(lParam); + bool isFromTabToTab = false; - int _currentHoverTabItemOld = _currentHoverTabItem; - RECT _currentHoverTabRectOld = _currentHoverTabRect; - bool _isCloseHoverOld = _isCloseHover; + int iTabNow = getTabIndexAt(p.x, p.y); // _currentHoverTabItem keeps previous value, and it need to be updated - _currentHoverTabItem = getTabIndexAt(xPos, yPos); - if (_currentHoverTabItem != -1) + if (_currentHoverTabItem == iTabNow && _currentHoverTabItem != -1) // mouse moves arround in the same tab { - ::SendMessage(_hSelf, TCM_GETITEMRECT, _currentHoverTabItem, reinterpret_cast(&_currentHoverTabRect)); - _isCloseHover = _closeButtonZone.isHit(xPos, yPos, _currentHoverTabRect, _isVertical); + // do nothing } - else + else if (iTabNow == -1 && _currentHoverTabItem != -1) // mouse is no more on any tab, set hover -1 { - SetRectEmpty(&_currentHoverTabRect); - _isCloseHover = false; + _currentHoverTabItem = -1; + + // send mouse leave notif + notify(TCN_MOUSELEAVING, -1); + } + else if (iTabNow != -1 && _currentHoverTabItem == -1) // mouse is just entered in a tab zone + { + _currentHoverTabItem = iTabNow; + + notify(TCN_MOUSEHOVERING, _currentHoverTabItem); + } + else if (iTabNow != -1 && _currentHoverTabItem != -1 && _currentHoverTabItem != iTabNow) // mouse is being moved from a tab and entering into another tab + { + isFromTabToTab = true; + + // set current hovered + _currentHoverTabItem = iTabNow; + + // send mouse enter notif + notify(TCN_MOUSEHOVERSWITCHING, _currentHoverTabItem); + } + else if (iTabNow == -1 && _currentHoverTabItem == -1) // mouse is already outside + { + // do nothing } - if (_currentHoverTabItem != _currentHoverTabItemOld || _isCloseHover != _isCloseHoverOld) + if (_drawTabCloseButton) { - if (_isCloseHoverOld && (_currentHoverTabItem != _currentHoverTabItemOld || !_isCloseHover)) - InvalidateRect(hwnd, &_currentHoverTabRectOld, FALSE); + RECT currentHoverTabRectOld = _currentHoverTabRect; + bool isCloseHoverOld = _isCloseHover; + + if (_currentHoverTabItem != -1) // is hovering + { + ::SendMessage(_hSelf, TCM_GETITEMRECT, _currentHoverTabItem, reinterpret_cast(&_currentHoverTabRect)); + _isCloseHover = _closeButtonZone.isHit(p.x, p.y, _currentHoverTabRect, _isVertical); + } + else + { + SetRectEmpty(&_currentHoverTabRect); + _isCloseHover = false; + } + + if (isFromTabToTab || _isCloseHover != isCloseHoverOld) + { + if (isCloseHoverOld && (isFromTabToTab || !_isCloseHover)) + InvalidateRect(hwnd, ¤tHoverTabRectOld, FALSE); + + if (_isCloseHover) + InvalidateRect(hwnd, &_currentHoverTabRect, FALSE); + } + if (_isCloseHover) - InvalidateRect(hwnd, &_currentHoverTabRect, FALSE); - } - - if (_isCloseHover) - { - TRACKMOUSEEVENT tme = {}; - tme.cbSize = sizeof(tme); - tme.dwFlags = TME_LEAVE; - tme.hwndTrack = hwnd; - TrackMouseEvent(&tme); + { + // Mouse moves out from close zone will send WM_MOUSELEAVE message + trackMouseEvent(TME_LEAVE); + } } + // Mouse moves out from tab zone will send WM_MOUSELEAVE message + // but it doesn't track mouse moving from a tab to another + trackMouseEvent(TME_LEAVE); } + break; } @@ -653,9 +701,12 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara { if (_isCloseHover) InvalidateRect(hwnd, &_currentHoverTabRect, FALSE); + _currentHoverTabItem = -1; SetRectEmpty(&_currentHoverTabRect); _isCloseHover = false; + + notify(TCN_MOUSELEAVING, _currentHoverTabItem); break; } @@ -669,17 +720,7 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara if(::GetCapture() == _hSelf) ::ReleaseCapture(); - // Send a notification message to the parent with wParam = 0, lParam = 0 - // nmhdr.idFrom = this - // destIndex = this->_nSrcTab - // scrIndex = this->_nTabDragged - TBHDR nmhdr; - nmhdr.hdr.hwndFrom = _hSelf; - nmhdr.hdr.code = _isDraggingInside?TCN_TABDROPPED:TCN_TABDROPPEDOUTSIDE; - nmhdr.hdr.idFrom = reinterpret_cast(this); - nmhdr.tabOrigin = currentTabOn; - - ::SendMessage(_hParent, WM_NOTIFY, 0, reinterpret_cast(&nmhdr)); + notify(_isDraggingInside?TCN_TABDROPPED:TCN_TABDROPPEDOUTSIDE, currentTabOn); return TRUE; } @@ -687,14 +728,7 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara { if ((_whichCloseClickDown == currentTabOn) && _closeButtonZone.isHit(xPos, yPos, _currentHoverTabRect, _isVertical)) { - TBHDR nmhdr; - nmhdr.hdr.hwndFrom = _hSelf; - nmhdr.hdr.code = TCN_TABDELETE; - nmhdr.hdr.idFrom = reinterpret_cast(this); - nmhdr.tabOrigin = currentTabOn; - - ::SendMessage(_hParent, WM_NOTIFY, 0, reinterpret_cast(&nmhdr)); - + notify(TCN_TABDELETE, currentTabOn); _whichCloseClickDown = -1; return TRUE; } @@ -732,13 +766,7 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara int xPos = LOWORD(lParam); int yPos = HIWORD(lParam); int currentTabOn = getTabIndexAt(xPos, yPos); - TBHDR nmhdr; - nmhdr.hdr.hwndFrom = _hSelf; - nmhdr.hdr.code = TCN_TABDELETE; - nmhdr.hdr.idFrom = reinterpret_cast(this); - nmhdr.tabOrigin = currentTabOn; - - ::SendMessage(_hParent, WM_NOTIFY, 0, reinterpret_cast(&nmhdr)); + notify(TCN_TABDELETE, currentTabOn); return TRUE; } @@ -749,13 +777,7 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara int xPos = LOWORD(lParam); int yPos = HIWORD(lParam); int currentTabOn = getTabIndexAt(xPos, yPos); - TBHDR nmhdr; - nmhdr.hdr.hwndFrom = _hSelf; - nmhdr.hdr.code = TCN_TABDELETE; - nmhdr.hdr.idFrom = reinterpret_cast(this); - nmhdr.tabOrigin = currentTabOn; - - ::SendMessage(_hParent, WM_NOTIFY, 0, reinterpret_cast(&nmhdr)); + notify(TCN_TABDELETE, currentTabOn); } return TRUE; } diff --git a/PowerEditor/src/WinControls/TabBar/TabBar.h b/PowerEditor/src/WinControls/TabBar/TabBar.h index 6211edc7..d3c5b24c 100644 --- a/PowerEditor/src/WinControls/TabBar/TabBar.h +++ b/PowerEditor/src/WinControls/TabBar/TabBar.h @@ -43,6 +43,9 @@ #define TCN_TABDROPPED (TCN_FIRST - 10) #define TCN_TABDROPPEDOUTSIDE (TCN_FIRST - 11) #define TCN_TABDELETE (TCN_FIRST - 12) +#define TCN_MOUSEHOVERING (TCN_FIRST - 13) +#define TCN_MOUSELEAVING (TCN_FIRST - 14) +#define TCN_MOUSEHOVERSWITCHING (TCN_FIRST - 15) #define WM_TABSETSTYLE (WM_APP + 0x024) @@ -228,7 +231,7 @@ protected: WNDPROC _tabBarDefaultProc = nullptr; RECT _currentHoverTabRect; - int _currentHoverTabItem = -1; + int _currentHoverTabItem = -1; // -1 : no mouse on any tab CloseButtonZone _closeButtonZone; bool _isCloseHover = false; @@ -284,4 +287,7 @@ protected: return (((screenPoint.x >= parentZone.left) && (screenPoint.x <= parentZone.right)) && (screenPoint.y >= parentZone.top) && (screenPoint.y <= parentZone.bottom)); } + + void notify(int notifyCode, int tabIndex); + void trackMouseEvent(DWORD event2check); };