From 16d7194ee73786c212e8639d41c7c31735ca930a Mon Sep 17 00:00:00 2001 From: Caolán McNamara Date: Fri, 1 Mar 2013 16:15:05 +0000 Subject: sort frame labels before frame contents for tab traversal If there is more than one widget with the same mnemonic, and one is a frame label, then we need to sort frame labels before frame bodies in the tab traversal order. Otherwise if the focus is in the body of a frame whose label has that shortcut and the shortcut is pressed again, the traversal through following widgets will encounter the frame label as the next candidate, leading back to the starting point and not onwards to the next widget using that shortcut. Frame labels have type "label" in the .ui, so suck that out to designate which widget is the frame label at load time. Change-Id: Ie21ed87867bd0c983981a3a8f3318b3cf598c1d6 --- vcl/inc/vcl/layout.hxx | 13 ++++++++++++- vcl/source/window/builder.cxx | 24 +++++++++++++++++++++++- vcl/source/window/layout.cxx | 43 ++++++++++++++++++++++++++++++++----------- 3 files changed, 67 insertions(+), 13 deletions(-) diff --git a/vcl/inc/vcl/layout.hxx b/vcl/inc/vcl/layout.hxx index 239e84cf60cd..457a389f19b9 100644 --- a/vcl/inc/vcl/layout.hxx +++ b/vcl/inc/vcl/layout.hxx @@ -436,9 +436,20 @@ public: class VCL_DLLPUBLIC VclFrame : public VclBin { +private: + Window *m_pLabel; +private: + friend class VclBuilder; + void designate_label(Window *pWindow); public: - VclFrame(Window *pParent) : VclBin(pParent) {} + VclFrame(Window *pParent) + : VclBin(pParent) + , m_pLabel(NULL) + { + } void set_label(const OUString &rLabel); + virtual Window *get_child(); + virtual const Window *get_child() const; Window *get_label_widget(); const Window *get_label_widget() const; protected: diff --git a/vcl/source/window/builder.cxx b/vcl/source/window/builder.cxx index 8654b658027d..3716a02bd644 100644 --- a/vcl/source/window/builder.cxx +++ b/vcl/source/window/builder.cxx @@ -1425,7 +1425,20 @@ bool VclBuilder::sortIntoBestTabTraversalOrder::operator()(const Window *pA, con return false; } //honour relative box positions with pack group - return m_pBuilder->get_window_packing_data(pA).m_nPosition < m_pBuilder->get_window_packing_data(pB).m_nPosition; + bPackA = m_pBuilder->get_window_packing_data(pA).m_nPosition; + bPackB = m_pBuilder->get_window_packing_data(pB).m_nPosition; + if (bPackA < bPackB) + return true; + if (bPackA > bPackB) + return false; + //sort labels of Frames before body + if (pA->GetParent() == pB->GetParent()) + { + const VclFrame *pFrameParent = dynamic_cast(pA->GetParent()); + if (pFrameParent && pA == pFrameParent->get_label_widget()) + return true; + } + return false; } void VclBuilder::handleChild(Window *pParent, xmlreader::XmlReader &reader) @@ -1487,6 +1500,15 @@ void VclBuilder::handleChild(Window *pParent, xmlreader::XmlReader &reader) } else { + // We want to sort labels before contents of frames + // for key board traversal, especially if there + // are multiple widgets using the same mnemonic + if (sType.equals("label")) + { + if (VclFrame *pFrameParent = dynamic_cast(pParent)) + pFrameParent->designate_label(pCurrentChild); + } + //To-Do make reorder a virtual in Window, move this foo //there and see above std::vector aChilds; diff --git a/vcl/source/window/layout.cxx b/vcl/source/window/layout.cxx index 934e08e8b521..88790f3e6401 100644 --- a/vcl/source/window/layout.cxx +++ b/vcl/source/window/layout.cxx @@ -1088,10 +1088,8 @@ Size VclFrame::calculateRequisition() const { Size aRet(0, 0); - WindowImpl* pWindowImpl = ImplGetWindowImpl(); - const Window *pChild = get_child(); - const Window *pLabel = pChild != pWindowImpl->mpLastChild ? pWindowImpl->mpLastChild : NULL; + const Window *pLabel = get_label_widget(); if (pChild && pChild->IsVisible()) aRet = getLayoutRequisition(*pChild); @@ -1121,11 +1119,8 @@ void VclFrame::setAllocation(const Size &rAllocation) rAllocation.Height() - rFrameStyle.top - rFrameStyle.bottom); Point aChildPos(rFrameStyle.left, rFrameStyle.top); - WindowImpl* pWindowImpl = ImplGetWindowImpl(); - - //The label widget is the last (of two) children Window *pChild = get_child(); - Window *pLabel = pChild != pWindowImpl->mpLastChild ? pWindowImpl->mpLastChild : NULL; + Window *pLabel = get_label_widget(); if (pLabel && pLabel->IsVisible()) { @@ -1141,12 +1136,22 @@ void VclFrame::setAllocation(const Size &rAllocation) setLayoutAllocation(*pChild, aChildPos, aAllocation); } +void VclFrame::designate_label(Window *pWindow) +{ + assert(pWindow->GetParent() == this); + m_pLabel = pWindow; +} + const Window *VclFrame::get_label_widget() const { - //The label widget is the last (of two) children - const Window *pChild = get_child(); + assert(GetChildCount() == 2); + if (m_pLabel) + return m_pLabel; + //The label widget is normally the first (of two) children const WindowImpl* pWindowImpl = ImplGetWindowImpl(); - return pChild != pWindowImpl->mpLastChild ? pWindowImpl->mpLastChild : NULL; + if (pWindowImpl->mpFirstChild == pWindowImpl->mpLastChild) //no label exists + return NULL; + return pWindowImpl->mpFirstChild; } Window *VclFrame::get_label_widget() @@ -1154,9 +1159,25 @@ Window *VclFrame::get_label_widget() return const_cast(const_cast(this)->get_label_widget()); } +const Window *VclFrame::get_child() const +{ + assert(GetChildCount() == 2); + //The child widget is the normally the last (of two) children + const WindowImpl* pWindowImpl = ImplGetWindowImpl(); + if (!m_pLabel) + return pWindowImpl->mpLastChild; + if (pWindowImpl->mpFirstChild == pWindowImpl->mpLastChild) //only label exists + return NULL; + return pWindowImpl->mpLastChild; +} + +Window *VclFrame::get_child() +{ + return const_cast(const_cast(this)->get_child()); +} + void VclFrame::set_label(const rtl::OUString &rLabel) { - //The label widget is the last (of two) children Window *pLabel = get_label_widget(); assert(pLabel); pLabel->SetText(rLabel); -- cgit