|
|
|
@ -441,6 +441,96 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case WM_MOUSEWHEEL:
|
|
|
|
|
{
|
|
|
|
|
// ..............................................................................
|
|
|
|
|
// MOUSEWHEEL:
|
|
|
|
|
// will scroll the tab bar area (similar to Firefox's tab scrolling),
|
|
|
|
|
// it only happens if not in multi-line mode and at least one tab is hidden
|
|
|
|
|
// ..............................................................................
|
|
|
|
|
// CTRL + MOUSEWHEEL:
|
|
|
|
|
// will do previous/next tab WITH scroll wrapping (endless loop)
|
|
|
|
|
// ..............................................................................
|
|
|
|
|
// SHIFT + MOUSEWHEEL:
|
|
|
|
|
// will do previous/next tab WITHOUT scroll wrapping (stops at first/last tab)
|
|
|
|
|
// ..............................................................................
|
|
|
|
|
// CTRL + SHIFT + MOUSEWHEEL:
|
|
|
|
|
// will switch to the first/last tab
|
|
|
|
|
// ..............................................................................
|
|
|
|
|
|
|
|
|
|
if (_isDragging)
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
const bool isForward = ((short)HIWORD(wParam)) < 0; // wheel rotation towards the user will be considered as forward direction
|
|
|
|
|
const LRESULT lastTabIndex = ::SendMessage(_hSelf, TCM_GETITEMCOUNT, 0, 0) - 1;
|
|
|
|
|
|
|
|
|
|
if ((wParam & MK_CONTROL) && (wParam & MK_SHIFT))
|
|
|
|
|
{
|
|
|
|
|
::SendMessage(_hSelf, TCM_SETCURFOCUS, (isForward ? lastTabIndex : 0), 0);
|
|
|
|
|
}
|
|
|
|
|
else if (wParam & (MK_CONTROL | MK_SHIFT))
|
|
|
|
|
{
|
|
|
|
|
LRESULT tabIndex = ::SendMessage(_hSelf, TCM_GETCURSEL, 0, 0) + (isForward ? 1 : -1);
|
|
|
|
|
if (tabIndex < 0)
|
|
|
|
|
{
|
|
|
|
|
if (wParam & MK_CONTROL)
|
|
|
|
|
tabIndex = lastTabIndex; // wrap scrolling
|
|
|
|
|
else
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
else if (tabIndex > lastTabIndex)
|
|
|
|
|
{
|
|
|
|
|
if (wParam & MK_CONTROL)
|
|
|
|
|
tabIndex = 0; // wrap scrolling
|
|
|
|
|
else
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
::SendMessage(_hSelf, TCM_SETCURFOCUS, tabIndex, 0);
|
|
|
|
|
}
|
|
|
|
|
else if (not _isMultiLine) // don't scroll if in multi-line mode
|
|
|
|
|
{
|
|
|
|
|
RECT rcTabCtrl, rcLastTab;
|
|
|
|
|
::SendMessage(_hSelf, TCM_GETITEMRECT, lastTabIndex, (LPARAM)&rcLastTab);
|
|
|
|
|
::GetClientRect(_hSelf, &rcTabCtrl);
|
|
|
|
|
|
|
|
|
|
// get index of the first visible tab
|
|
|
|
|
TC_HITTESTINFO hti;
|
|
|
|
|
LONG xy = NppParameters::getInstance()->_dpiManager.scaleX(12); // an arbitrary coordinate inside the first visible tab
|
|
|
|
|
hti.pt = { xy, xy };
|
|
|
|
|
LRESULT scrollTabIndex = ::SendMessage(_hSelf, TCM_HITTEST, 0, (LPARAM)&hti);
|
|
|
|
|
|
|
|
|
|
if (scrollTabIndex < 1 && (_isVertical ? rcLastTab.bottom < rcTabCtrl.bottom : rcLastTab.right < rcTabCtrl.right)) // nothing to scroll
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
// maximal width/height of the msctls_updown32 class (arrow box in the tab bar),
|
|
|
|
|
// this area may hide parts of the last tab and needs to be excluded
|
|
|
|
|
LONG maxLengthUpDownCtrl = NppParameters::getInstance()->_dpiManager.scaleX(44); // sufficient static value
|
|
|
|
|
|
|
|
|
|
// scroll forward as long as the last tab is hidden; scroll backward till the first tab
|
|
|
|
|
if ((_isVertical ? ((rcTabCtrl.bottom - rcLastTab.bottom) < maxLengthUpDownCtrl) : ((rcTabCtrl.right - rcLastTab.right) < maxLengthUpDownCtrl)) || not isForward)
|
|
|
|
|
{
|
|
|
|
|
if (isForward)
|
|
|
|
|
++scrollTabIndex;
|
|
|
|
|
else
|
|
|
|
|
--scrollTabIndex;
|
|
|
|
|
|
|
|
|
|
if (scrollTabIndex < 0 || scrollTabIndex > lastTabIndex)
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
// clear hover state of the close button,
|
|
|
|
|
// WM_MOUSEMOVE won't handle this properly since the tab position will change
|
|
|
|
|
if (_isCloseHover)
|
|
|
|
|
{
|
|
|
|
|
_isCloseHover = false;
|
|
|
|
|
::InvalidateRect(_hSelf, &_currentHoverTabRect, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
::SendMessage(_hSelf, WM_HSCROLL, MAKEWPARAM(SB_THUMBPOSITION, scrollTabIndex), 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case WM_LBUTTONDOWN :
|
|
|
|
|
{
|
|
|
|
|
if (_drawTabCloseButton)
|
|
|
|
|