(In progress) New feature: check content via Document Map while mouse hovering on a inactivated tab

This commit is contained in:
Don HO 2017-03-05 14:03:02 +01:00
parent 739593fb66
commit 97573c80a0
6 changed files with 187 additions and 96 deletions

View File

@ -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<TBHDR *>(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:
{

View File

@ -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<LPARAM>(buf2show->getDocument()));
_pScintillaEditView->setCurrentBuffer(buf2show);
// folding
const std::vector<size_t> & 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<int32_t>((*_ppEditView)->execute(SCI_GETZOOM));
_displayZoom = static_cast<int32_t>(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<int32_t>((*_ppEditView)->execute(SCI_GETMARGINWIDTHN, m));
marginWidths += static_cast<int32_t>(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;

View File

@ -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;

View File

@ -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<UINT_PTR>(this);
nmhdr.tabOrigin = tabIndex;
::SendMessage(_hParent, WM_NOTIFY, 0, reinterpret_cast<LPARAM>(&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<UINT_PTR>(this);
nmhdr.tabOrigin = currentTabOn;
::SendMessage(_hParent, WM_NOTIFY, 0, reinterpret_cast<LPARAM>(&nmhdr));
notify(NM_CLICK, currentTabOn);
return TRUE;
}
@ -593,12 +605,13 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara
//#define NPPM_INTERNAL_ISDRAGGING 40926
case WM_MOUSEMOVE :
{
if (_isDragging)
{
POINT p;
p.x = LOWORD(lParam);
p.y = HIWORD(lParam);
if (_isDragging)
{
exchangeItemData(p);
// Get cursor position of "Screen"
@ -607,21 +620,53 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara
draggingCursor(_draggingPoint);
return TRUE;
}
else
{
bool isFromTabToTab = false;
int iTabNow = getTabIndexAt(p.x, p.y); // _currentHoverTabItem keeps previous value, and it need to be updated
if (_currentHoverTabItem == iTabNow && _currentHoverTabItem != -1) // mouse moves arround in the same tab
{
// do nothing
}
else if (iTabNow == -1 && _currentHoverTabItem != -1) // mouse is no more on any tab, set hover -1
{
_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 (_drawTabCloseButton)
{
int xPos = LOWORD(lParam);
int yPos = HIWORD(lParam);
RECT currentHoverTabRectOld = _currentHoverTabRect;
bool isCloseHoverOld = _isCloseHover;
int _currentHoverTabItemOld = _currentHoverTabItem;
RECT _currentHoverTabRectOld = _currentHoverTabRect;
bool _isCloseHoverOld = _isCloseHover;
_currentHoverTabItem = getTabIndexAt(xPos, yPos);
if (_currentHoverTabItem != -1)
if (_currentHoverTabItem != -1) // is hovering
{
::SendMessage(_hSelf, TCM_GETITEMRECT, _currentHoverTabItem, reinterpret_cast<LPARAM>(&_currentHoverTabRect));
_isCloseHover = _closeButtonZone.isHit(xPos, yPos, _currentHoverTabRect, _isVertical);
_isCloseHover = _closeButtonZone.isHit(p.x, p.y, _currentHoverTabRect, _isVertical);
}
else
{
@ -629,23 +674,26 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara
_isCloseHover = false;
}
if (_currentHoverTabItem != _currentHoverTabItemOld || _isCloseHover != _isCloseHoverOld)
if (isFromTabToTab || _isCloseHover != isCloseHoverOld)
{
if (_isCloseHoverOld && (_currentHoverTabItem != _currentHoverTabItemOld || !_isCloseHover))
InvalidateRect(hwnd, &_currentHoverTabRectOld, FALSE);
if (isCloseHoverOld && (isFromTabToTab || !_isCloseHover))
InvalidateRect(hwnd, &currentHoverTabRectOld, 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<UINT_PTR>(this);
nmhdr.tabOrigin = currentTabOn;
::SendMessage(_hParent, WM_NOTIFY, 0, reinterpret_cast<LPARAM>(&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<UINT_PTR>(this);
nmhdr.tabOrigin = currentTabOn;
::SendMessage(_hParent, WM_NOTIFY, 0, reinterpret_cast<LPARAM>(&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<UINT_PTR>(this);
nmhdr.tabOrigin = currentTabOn;
::SendMessage(_hParent, WM_NOTIFY, 0, reinterpret_cast<LPARAM>(&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<UINT_PTR>(this);
nmhdr.tabOrigin = currentTabOn;
::SendMessage(_hParent, WM_NOTIFY, 0, reinterpret_cast<LPARAM>(&nmhdr));
notify(TCN_TABDELETE, currentTabOn);
}
return TRUE;
}

View File

@ -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);
};