summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDennis Francis <dennisfrancis.in@gmail.com>2016-01-30 17:54:58 +0530
committerEike Rathke <erack@redhat.com>2016-03-10 14:45:25 +0000
commitd799daa48987c4fa19696967dd98f690e7b94c4f (patch)
tree3c1b3266825a8435f91f231d2c33b03d8782fd7e
parent3b0fda641467cc99ef86eb538de02b7bfda8fae0 (diff)
tdf#97344 : Allow focus change using mouse in autofilter popup
Also modified CycleFocus() to skip controls that are disabled. Change-Id: I6d84e0d4aacc719b83c70e92a17f58f1756ff072 Reviewed-on: https://gerrit.libreoffice.org/21922 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Eike Rathke <erack@redhat.com> Tested-by: Eike Rathke <erack@redhat.com>
-rw-r--r--sc/source/ui/cctrl/checklistmenu.cxx181
-rw-r--r--sc/source/ui/inc/checklistmenu.hxx44
-rw-r--r--svtools/source/contnr/treelistbox.cxx2
3 files changed, 181 insertions, 46 deletions
diff --git a/sc/source/ui/cctrl/checklistmenu.cxx b/sc/source/ui/cctrl/checklistmenu.cxx
index 865fb7b00b0b..cbf0caabdb24 100644
--- a/sc/source/ui/cctrl/checklistmenu.cxx
+++ b/sc/source/ui/cctrl/checklistmenu.cxx
@@ -875,33 +875,35 @@ void ScCheckListMenuWindow::CancelButton::Click()
ScCheckListMenuWindow::ScCheckListMenuWindow(vcl::Window* pParent, ScDocument* pDoc) :
ScMenuFloatingWindow(pParent, pDoc),
- maEdSearch(VclPtr<Edit>::Create(this)),
+ maEdSearch(VclPtr<ScSearchEdit>::Create(this)),
maChecks(VclPtr<ScCheckListBox>::Create(this, WB_HASBUTTONS | WB_HASLINES | WB_HASLINESATROOT | WB_HASBUTTONSATROOT) ),
maChkToggleAll(VclPtr<TriStateBox>::Create(this, 0)),
maBtnSelectSingle(VclPtr<ImageButton>::Create(this, 0)),
maBtnUnselectSingle(VclPtr<ImageButton>::Create(this, 0)),
maBtnOk(VclPtr<OKButton>::Create(this)),
maBtnCancel(VclPtr<CancelButton>::Create(this)),
- mnCurTabStop(0),
mpExtendedData(nullptr),
mpOKAction(nullptr),
mpPopupEndAction(nullptr),
maWndSize(),
- mePrevToggleAllState(TRISTATE_INDET)
+ mePrevToggleAllState(TRISTATE_INDET),
+ maTabStops(this)
{
sal_Int32 nScaleFactor = GetDPIScaleFactor();
maWndSize = Size(200 * nScaleFactor, 330 * nScaleFactor);
- maTabStopCtrls.reserve(8);
- maTabStopCtrls.push_back(this);
- maTabStopCtrls.push_back(maEdSearch.get());
- maTabStopCtrls.push_back(maChecks.get());
- maTabStopCtrls.push_back(maChkToggleAll.get());
- maTabStopCtrls.push_back(maBtnSelectSingle.get());
- maTabStopCtrls.push_back(maBtnUnselectSingle.get());
- maTabStopCtrls.push_back(maBtnOk.get());
- maTabStopCtrls.push_back(maBtnCancel.get());
+ maTabStops.AddTabStop( this );
+ maTabStops.AddTabStop( maEdSearch.get() );
+ maTabStops.AddTabStop( maChecks.get() );
+ maTabStops.AddTabStop( maChkToggleAll.get() );
+ maTabStops.AddTabStop( maBtnSelectSingle.get() );
+ maTabStops.AddTabStop( maBtnUnselectSingle.get() );
+ maTabStops.AddTabStop( maBtnOk.get() );
+ maTabStops.AddTabStop( maBtnCancel.get() );
+
+ maEdSearch->SetTabStopsContainer( &maTabStops );
+ maChecks->SetTabStopsContainer( &maTabStops );
// Enable type-ahead search in the check list box.
maChecks->SetStyle(maChecks->GetStyle() | WB_QUICK_SEARCH);
@@ -921,7 +923,7 @@ void ScCheckListMenuWindow::dispose()
maBtnUnselectSingle.disposeAndClear();
maBtnOk.disposeAndClear();
maBtnCancel.disposeAndClear();
- maTabStopCtrls.clear();
+ maTabStops.clear();
ScMenuFloatingWindow::dispose();
}
@@ -1171,30 +1173,6 @@ void ScCheckListMenuWindow::selectCurrentMemberOnly(bool bSet)
maChecks->CheckEntry(pEntry, bSet );
}
-void ScCheckListMenuWindow::cycleFocus(bool bReverse)
-{
- maTabStopCtrls[mnCurTabStop]->SetFakeFocus(false);
- maTabStopCtrls[mnCurTabStop]->LoseFocus();
- if (mnCurTabStop == 0)
- clearSelectedMenuItem();
-
- if (bReverse)
- {
- if (mnCurTabStop > 0)
- --mnCurTabStop;
- else
- mnCurTabStop = maTabStopCtrls.size() - 1;
- }
- else
- {
- ++mnCurTabStop;
- if (mnCurTabStop >= maTabStopCtrls.size())
- mnCurTabStop = 0;
- }
- maTabStopCtrls[mnCurTabStop]->SetFakeFocus(true);
- maTabStopCtrls[mnCurTabStop]->GrabFocus();
-}
-
IMPL_LINK_TYPED( ScCheckListMenuWindow, ButtonHdl, Button*, pBtn, void )
{
if (pBtn == maBtnOk.get())
@@ -1319,7 +1297,7 @@ bool ScCheckListMenuWindow::Notify(NotifyEvent& rNEvt)
bool bShift = rCode.IsShift();
if (rCode.GetCode() == KEY_TAB)
{
- cycleFocus(bShift);
+ maTabStops.CycleFocus(bShift);
return true;
}
}
@@ -1351,7 +1329,7 @@ void ScCheckListMenuWindow::Paint(vcl::RenderContext& rRenderContext, const Rect
vcl::Window* ScCheckListMenuWindow::GetPreferredKeyInputWindow()
{
- return maTabStopCtrls[mnCurTabStop];
+ return maTabStops.GetCurrentControl();
}
Reference<XAccessible> ScCheckListMenuWindow::CreateAccessible()
@@ -1468,8 +1446,105 @@ void ScCheckListMenuWindow::addMember(const OUString& rName, bool bVisible)
maMembers.push_back(aMember);
}
+ScTabStops::ScTabStops( ScCheckListMenuWindow* pMenuWin ) :
+ mpMenuWindow( pMenuWin ),
+ maControlToPos( ControlToPosMap() ),
+ mnCurTabStop(0)
+{
+ maControls.reserve( 8 );
+}
+
+ScTabStops::~ScTabStops()
+{}
+
+void ScTabStops::AddTabStop( vcl::Window* pWin )
+{
+ maControls.push_back( pWin );
+ maControlToPos[pWin] = maControls.size() - 1;
+}
+
+void ScTabStops::SetTabStop( vcl::Window* pWin )
+{
+ if ( !maControls.size() )
+ return;
+ ControlToPosMap::const_iterator aIter = maControlToPos.find( pWin );
+ if ( aIter == maControlToPos.end() )
+ return;
+ if ( aIter->second == mnCurTabStop )
+ return;
+ if ( mnCurTabStop < maControls.size() )
+ {
+ maControls[mnCurTabStop]->SetFakeFocus( false );
+ maControls[mnCurTabStop]->LoseFocus();
+ }
+ mnCurTabStop = aIter->second;
+ maControls[mnCurTabStop]->SetFakeFocus( true );
+ maControls[mnCurTabStop]->GrabFocus();
+}
+
+void ScTabStops::CycleFocus( bool bReverse )
+{
+ if (!maControls.size())
+ return;
+ if ( mnCurTabStop < maControls.size() )
+ {
+ maControls[mnCurTabStop]->SetFakeFocus( false );
+ maControls[mnCurTabStop]->LoseFocus();
+ }
+ else
+ mnCurTabStop = 0;
+
+ if ( mpMenuWindow && mnCurTabStop == 0 )
+ mpMenuWindow->clearSelectedMenuItem();
+
+ size_t nIterCount = 0;
+
+ if ( bReverse )
+ {
+ do
+ {
+ if ( mnCurTabStop > 0 )
+ --mnCurTabStop;
+ else
+ mnCurTabStop = maControls.size() - 1;
+ ++nIterCount;
+ } while ( nIterCount <= maControls.size() && !maControls[mnCurTabStop]->IsEnabled() );
+ }
+ else
+ {
+ do
+ {
+ ++mnCurTabStop;
+ if ( mnCurTabStop >= maControls.size() )
+ mnCurTabStop = 0;
+ ++nIterCount;
+ } while ( nIterCount <= maControls.size() && !maControls[mnCurTabStop]->IsEnabled() );
+ }
+
+ if ( nIterCount <= maControls.size() )
+ {
+ maControls[mnCurTabStop]->SetFakeFocus( true );
+ maControls[mnCurTabStop]->GrabFocus();
+ }
+ // else : all controls are disabled, so can't do anything
+}
+
+vcl::Window* ScTabStops::GetCurrentControl()
+{
+ if ( mnCurTabStop >= maControls.size() )
+ return nullptr;
+ return maControls[mnCurTabStop];
+}
+
+void ScTabStops::clear()
+{
+ mnCurTabStop = 0;
+ maControlToPos.clear();
+ maControls.clear();
+}
+
ScCheckListBox::ScCheckListBox( vcl::Window* pParent, WinBits nWinStyle )
- : SvTreeListBox( pParent, nWinStyle ), mpCheckButton( nullptr )
+ : SvTreeListBox( pParent, nWinStyle ), mpCheckButton( nullptr ), mbSeenMouseButtonDown( false )
{
Init();
}
@@ -1633,6 +1708,30 @@ void ScCheckListBox::KeyInput( const KeyEvent& rKEvt )
SvTreeListBox::KeyInput( rKEvt );
}
+void ScCheckListBox::MouseButtonDown(const MouseEvent& rMEvt)
+{
+ SvTreeListBox::MouseButtonDown( rMEvt );
+ if ( rMEvt.IsLeft() )
+ mbSeenMouseButtonDown = true;
+}
+
+void ScCheckListBox::MouseButtonUp(const MouseEvent& rMEvt)
+{
+ SvTreeListBox::MouseButtonUp( rMEvt );
+ if ( mpTabStops && mbSeenMouseButtonDown && rMEvt.IsLeft() )
+ {
+ mpTabStops->SetTabStop( this );
+ mbSeenMouseButtonDown = false;
+ }
+}
+
+void ScSearchEdit::MouseButtonDown(const MouseEvent& rMEvt)
+{
+ Edit::MouseButtonDown( rMEvt );
+ if ( mpTabStops && rMEvt.IsLeft() && rMEvt.GetClicks() >= 1 )
+ mpTabStops->SetTabStop( this );
+}
+
void ScCheckListMenuWindow::initMembers()
{
size_t n = maMembers.size();
@@ -1748,7 +1847,7 @@ void ScCheckListMenuWindow::launch(const Rectangle& rRect)
}
StartPopupMode(aRect, (FloatWinPopupFlags::Down | FloatWinPopupFlags::GrabFocus));
- cycleFocus(); // Set initial focus to the check list box.
+ maTabStops.CycleFocus(); // Set initial focus to the search box ( index = 1 )
}
void ScCheckListMenuWindow::close(bool bOK)
diff --git a/sc/source/ui/inc/checklistmenu.hxx b/sc/source/ui/inc/checklistmenu.hxx
index bf8281f90f1b..5f280d8a96ea 100644
--- a/sc/source/ui/inc/checklistmenu.hxx
+++ b/sc/source/ui/inc/checklistmenu.hxx
@@ -190,9 +190,31 @@ private:
VclPtr<ScMenuFloatingWindow> mpParentMenu;
};
+class ScCheckListMenuWindow;
+
+class ScTabStops
+{
+private:
+ typedef std::unordered_map<vcl::Window*, size_t> ControlToPosMap;
+ ScCheckListMenuWindow* mpMenuWindow;
+ ControlToPosMap maControlToPos;
+ std::vector<vcl::Window*> maControls;
+ size_t mnCurTabStop;
+public:
+ ScTabStops( ScCheckListMenuWindow* mpMenuWin );
+ ~ScTabStops();
+ void AddTabStop( vcl::Window* pWin );
+ void SetTabStop( vcl::Window* pWin );
+ void CycleFocus( bool bReverse = false );
+ vcl::Window* GetCurrentControl();
+ void clear();
+};
+
class ScCheckListBox : public SvTreeListBox
{
SvLBoxButtonData* mpCheckButton;
+ ScTabStops* mpTabStops;
+ bool mbSeenMouseButtonDown;
void CountCheckedEntries( SvTreeListEntry* pParent, sal_uLong& nCount ) const;
void CheckAllChildren( SvTreeListEntry* pEntry, bool bCheck = true );
@@ -210,7 +232,23 @@ class ScCheckListBox : public SvTreeListBox
sal_uInt16 GetCheckedEntryCount() const;
void ExpandChildren( SvTreeListEntry* pParent );
virtual void KeyInput( const KeyEvent& rKEvt ) override;
+ virtual void MouseButtonDown(const MouseEvent& rMEvt) override;
+ virtual void MouseButtonUp(const MouseEvent& rMEvt) override;
+ void SetTabStopsContainer( ScTabStops* pTabStops ) { mpTabStops = pTabStops; }
};
+
+class ScSearchEdit : public Edit
+{
+private:
+ ScTabStops* mpTabStops;
+public:
+ ScSearchEdit(Window* pParent) : Edit(pParent) {}
+ virtual ~ScSearchEdit() {}
+
+ virtual void MouseButtonDown( const MouseEvent& rMEvt ) override;
+ void SetTabStopsContainer( ScTabStops* pTabStops ) { mpTabStops = pTabStops; }
+};
+
/**
* This class implements a popup window for field button, for quick access
* of hide-item list, and possibly more stuff related to field options.
@@ -334,7 +372,7 @@ private:
DECL_LINK_TYPED( EdModifyHdl, Edit&, void );
private:
- VclPtr<Edit> maEdSearch;
+ VclPtr<ScSearchEdit> maEdSearch;
VclPtr<ScCheckListBox> maChecks;
VclPtr<TriStateBox> maChkToggleAll;
@@ -344,9 +382,6 @@ private:
VclPtr<OKButton> maBtnOk;
VclPtr<CancelButton> maBtnCancel;
- std::vector<VclPtr<vcl::Window> > maTabStopCtrls;
- size_t mnCurTabStop;
-
std::vector<Member> maMembers;
std::unique_ptr<ExtendedData> mpExtendedData;
std::unique_ptr<Action> mpOKAction;
@@ -356,6 +391,7 @@ private:
Size maWndSize; /// whole window size.
Size maMenuSize; /// size of all menu items combined.
TriState mePrevToggleAllState;
+ ScTabStops maTabStops;
};
#endif
diff --git a/svtools/source/contnr/treelistbox.cxx b/svtools/source/contnr/treelistbox.cxx
index d63925775588..ec9831044721 100644
--- a/svtools/source/contnr/treelistbox.cxx
+++ b/svtools/source/contnr/treelistbox.cxx
@@ -1960,7 +1960,7 @@ void SvTreeListBox::SetCheckButtonInvisible( SvTreeListEntry* pEntry)
SvButtonState SvTreeListBox::GetCheckButtonState( SvTreeListEntry* pEntry ) const
{
SvButtonState eState = SV_BUTTON_UNCHECKED;
- if( nTreeFlags & SvTreeFlags::CHKBTN )
+ if( pEntry && ( nTreeFlags & SvTreeFlags::CHKBTN ) )
{
SvLBoxButton* pItem = static_cast<SvLBoxButton*>(pEntry->GetFirstItem(SV_ITEM_ID_LBOXBUTTON));
if(!pItem)