Date: prev next · Thread: first prev next last
2011 Archives by date, by thread · List index


Hi,

Please find attached my patches to fix Bug 37484 [1]. It would be great if
someone could review them.

I ended up implementing my own method for scrolling to a listbox entry, and
also making public the methods related to absolute position of entries in
the list. I hope this was an OK thing to do? I tried hard to make the code
that saves & restores list position compact and readable; please tell me if
it makes sense. I have built and tested my changes a lot, but only on linux.

Kind regards,

Luke.

[1] https://bugs.freedesktop.org/show_bug.cgi?id=37484
From f3726e31957995c8554cdb84e093854977dd7623 Mon Sep 17 00:00:00 2001
From: Luke Symes <allsymes@gmail.com>
Date: Wed, 22 Jun 2011 15:40:26 +1200
Subject: [PATCH 1/3] Set the listbox height to an integer multiple of the
 listbox entry height.

This ensures that we don't get a half visible entry at the bottom of the view.
---
 svtools/source/contnr/svimpbox.cxx |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/svtools/source/contnr/svimpbox.cxx b/svtools/source/contnr/svimpbox.cxx
index da5aff8..ab6d4e1 100644
--- a/svtools/source/contnr/svimpbox.cxx
+++ b/svtools/source/contnr/svimpbox.cxx
@@ -1358,8 +1358,19 @@ void SvImpLBox::InitScrollBarBox()
 void SvImpLBox::Resize()
 {
     Size aSize( pView->Control::GetOutputSizePixel());
+    long nEntryHeight = pView->GetEntryHeight();
+    int nEntryCount = 0;
+
     if( aSize.Width() <= 0 || aSize.Height() <= 0 )
         return;
+    if( nEntryHeight )
+    {
+      // Set the view height to an integer multiple of the entry height.
+      nEntryCount = (int) aSize.Height() / nEntryHeight;
+      aSize.Height() = pView->GetEntryHeight() * nEntryCount;
+      pView->Control::SetOutputSizePixel( aSize );
+    }
+
     nFlags |= F_IN_RESIZE;
     InitScrollBarBox();
 
-- 
1.7.5.4

From 6bb119906cb470c56a5fafde52bb98202d93f71c Mon Sep 17 00:00:00 2001
From: Luke Symes <allsymes@gmail.com>
Date: Wed, 22 Jun 2011 15:56:50 +1200
Subject: [PATCH 2/3] Implement ScrollToAbsPos for listboxes.

Scrolls the listbox so the given entry is the first visible entry.
The existing MakeVisible is not good enough since it won't scroll
down if the given entry is already visible.
---
 svtools/inc/svtools/svtreebx.hxx   |    1 +
 svtools/inc/svtools/treelist.hxx   |    6 ++++++
 svtools/source/contnr/svimpbox.cxx |   26 ++++++++++++++++++++++++++
 svtools/source/contnr/svtreebx.cxx |    5 +++++
 svtools/source/inc/svimpbox.hxx    |    1 +
 5 files changed, 39 insertions(+), 0 deletions(-)

diff --git a/svtools/inc/svtools/svtreebx.hxx b/svtools/inc/svtools/svtreebx.hxx
index 4453d0f..2b0a100 100644
--- a/svtools/inc/svtools/svtreebx.hxx
+++ b/svtools/inc/svtools/svtreebx.hxx
@@ -369,6 +369,7 @@ public:
 
     SvLBoxEntry*       GetFirstEntryInView() const;
     SvLBoxEntry*       GetNextEntryInView(SvLBoxEntry*) const;
+    void                       ScrollToAbsPos( long nPos );
 
     void                       ShowFocusRect( const SvLBoxEntry* pEntry );
     void                       SetTabBar( TabBar* pTabBar );
diff --git a/svtools/inc/svtools/treelist.hxx b/svtools/inc/svtools/treelist.hxx
index 6c296d2..63545ed 100644
--- a/svtools/inc/svtools/treelist.hxx
+++ b/svtools/inc/svtools/treelist.hxx
@@ -494,9 +494,15 @@ public:
 
     SvListEntry*        LastSelected() const
     { return pModel->LastSelected(this); }
+    SvListEntry*        GetEntryAtAbsPos( sal_uLong nAbsPos ) const
+    { return pModel->GetEntryAtAbsPos(nAbsPos); }
+
     SvListEntry*        GetEntryAtVisPos( sal_uLong nVisPos ) const
     { return pModel->GetEntryAtVisPos((SvListView*)this,nVisPos); }
 
+    sal_uLong           GetAbsPos( SvListEntry* pEntry ) const
+    { return pModel->GetAbsPos(pEntry); }
+
     sal_uLong           GetVisiblePos( SvListEntry* pEntry ) const
     { return pModel->GetVisiblePos((SvListView*)this,pEntry); }
 
diff --git a/svtools/source/contnr/svimpbox.cxx b/svtools/source/contnr/svimpbox.cxx
index ab6d4e1..fd5a649 100644
--- a/svtools/source/contnr/svimpbox.cxx
+++ b/svtools/source/contnr/svimpbox.cxx
@@ -1012,6 +1012,32 @@ void SvImpLBox::MakeVisible( SvLBoxEntry* pEntry, sal_Bool bMoveToTop )
     pView->Invalidate();
 }
 
+void SvImpLBox::ScrollToAbsPos( long nPos )
+{
+    long nLastEntryPos = pView->GetAbsPos( pView->Last() );
+
+    if( nPos < 0 )
+        nPos = 0;
+    else if( nPos > nLastEntryPos )
+        nPos = nLastEntryPos;
+
+    SvLBoxEntry* pEntry = (SvLBoxEntry*)pView->GetEntryAtAbsPos( nPos );
+    if( !pEntry || pEntry == pStartEntry )
+        return;
+
+    if( pStartEntry || (m_nStyle & WB_FORCE_MAKEVISIBLE) )
+        nFlags &= (~F_FILLING);
+
+    if( pView->IsEntryVisible(pEntry) )
+    {
+        pStartEntry = pEntry;
+        ShowCursor( sal_False );
+        aVerSBar.SetThumbPos( nPos );
+        ShowCursor( sal_True );
+        if (GetUpdateMode())
+            pView->Invalidate();
+    }
+}
 
 void SvImpLBox::RepaintSelectionItems()
 {
diff --git a/svtools/source/contnr/svtreebx.cxx b/svtools/source/contnr/svtreebx.cxx
index e9648d2..76c82b6 100644
--- a/svtools/source/contnr/svtreebx.cxx
+++ b/svtools/source/contnr/svtreebx.cxx
@@ -853,6 +853,11 @@ void SvTreeListBox::ScrollOutputArea( short nDeltaEntries )
     NotifyEndScroll();
 }
 
+void SvTreeListBox::ScrollToAbsPos( long nPos )
+{
+    pImp->ScrollToAbsPos( nPos );
+}
+
 void SvTreeListBox::SetSelectionMode( SelectionMode eSelectMode )
 {
     DBG_CHKTHIS(SvTreeListBox,0);
diff --git a/svtools/source/inc/svimpbox.hxx b/svtools/source/inc/svimpbox.hxx
index 01648d8..7f666fc 100644
--- a/svtools/source/inc/svimpbox.hxx
+++ b/svtools/source/inc/svimpbox.hxx
@@ -313,6 +313,7 @@ public:
     void                               SetCurEntry( SvLBoxEntry* );
     Point                              GetEntryPosition( SvLBoxEntry* ) const;
     void                               MakeVisible( SvLBoxEntry* pEntry, sal_Bool 
bMoveToTop=sal_False );
+    void                               ScrollToAbsPos( long nPos );
 
     void                               PaintDDCursor( SvLBoxEntry* );
 
-- 
1.7.5.4

From 36be5c5f7e4018ea78d0c0297d311fd46608491d Mon Sep 17 00:00:00 2001
From: Luke Symes <allsymes@gmail.com>
Date: Wed, 22 Jun 2011 16:03:10 +1200
Subject: [PATCH 3/3] Implement GetLastEntryInView for SvTreeListBox.

This function matches up with GetFirstEntryInView, and will be useful
in saving the scroll state of a SvTreeListBox, in particular
the CustomAnimationList.
---
 svtools/inc/svtools/svtreebx.hxx   |    1 +
 svtools/source/contnr/svtreebx.cxx |   22 ++++++++++++++++++++++
 2 files changed, 23 insertions(+), 0 deletions(-)

diff --git a/svtools/inc/svtools/svtreebx.hxx b/svtools/inc/svtools/svtreebx.hxx
index 2b0a100..29c3822 100644
--- a/svtools/inc/svtools/svtreebx.hxx
+++ b/svtools/inc/svtools/svtreebx.hxx
@@ -369,6 +369,7 @@ public:
 
     SvLBoxEntry*       GetFirstEntryInView() const;
     SvLBoxEntry*       GetNextEntryInView(SvLBoxEntry*) const;
+    SvLBoxEntry*       GetLastEntryInView() const;
     void                       ScrollToAbsPos( long nPos );
 
     void                       ShowFocusRect( const SvLBoxEntry* pEntry );
diff --git a/svtools/source/contnr/svtreebx.cxx b/svtools/source/contnr/svtreebx.cxx
index 76c82b6..175d9cd 100644
--- a/svtools/source/contnr/svtreebx.cxx
+++ b/svtools/source/contnr/svtreebx.cxx
@@ -2452,6 +2452,28 @@ SvLBoxEntry* SvTreeListBox::GetNextEntryInView(SvLBoxEntry* pEntry ) const
     return pNext;
 }
 
+SvLBoxEntry* SvTreeListBox::GetLastEntryInView() const
+{
+    SvLBoxEntry* pEntry = GetFirstEntryInView();
+    SvLBoxEntry* pNext = 0;
+    while( pEntry )
+    {
+        pNext = (SvLBoxEntry*)NextVisible( pEntry );
+        if( pNext )
+        {
+          Point aPos( GetEntryPosition(pNext) );
+          const Size& rSize = pImp->GetOutputSize();
+          if( aPos.Y() < 0 || aPos.Y() >= rSize.Height() )
+              break;
+          else
+              pEntry = pNext;
+        }
+        else
+            break;
+    }
+    return pEntry;
+}
+
 void SvTreeListBox::ShowFocusRect( const SvLBoxEntry* pEntry )
 {
     pImp->ShowFocusRect( pEntry );
-- 
1.7.5.4

From b366cc0b91bd228efb8796c19f8c9440322bf30d Mon Sep 17 00:00:00 2001
From: Luke Symes <allsymes@gmail.com>
Date: Wed, 22 Jun 2011 16:40:50 +1200
Subject: [PATCH 1/2] Restore the scroll position of the CustomAnimationList
 when it is updated.

We save the position of the listview, and also the selection boundary.
We move with the selection if it goes out of view, otherwise we
restore the original scroll position. If the selection was out of view
to start with, we scroll up/down to the first few entries.
---
 sd/source/ui/animations/CustomAnimationList.cxx |   86 +++++++++++++++++++++--
 1 files changed, 80 insertions(+), 6 deletions(-)

diff --git a/sd/source/ui/animations/CustomAnimationList.cxx 
b/sd/source/ui/animations/CustomAnimationList.cxx
index a1e64d2..224129a 100644
--- a/sd/source/ui/animations/CustomAnimationList.cxx
+++ b/sd/source/ui/animations/CustomAnimationList.cxx
@@ -587,21 +587,51 @@ void stl_append_effect_func::operator()(CustomAnimationEffectPtr pEffect)
 void CustomAnimationList::update()
 {
     mbIgnorePaint = true;
+    SetUpdateMode( sal_False );
 
     CustomAnimationListEntry* pEntry = 0;
 
     std::list< CustomAnimationEffectPtr > aExpanded;
     std::list< CustomAnimationEffectPtr > aSelected;
 
-    CustomAnimationEffectPtr pFirstVisibleEffect;
+    CustomAnimationEffectPtr pFirstSelEffect;
+    CustomAnimationEffectPtr pLastSelEffect;
+    long nFirstVis = -1;
+    long nLastVis = -1;
+    long nFirstSelOld = -1;
+    long nFirstSelNew = -1;
+    long nLastSelOld = -1;
+    long nLastSelNew = -1;
+    bool bMoved = false;
+    bool bMovedUp = false;
+    bool bMovedDown = false;
 
     if( mpMainSequence.get() )
     {
-        // save selection and expand states
-        pEntry = static_cast<CustomAnimationListEntry*>(FirstVisible());
+        // save scroll position
+        pEntry = static_cast<CustomAnimationListEntry*>(GetFirstEntryInView());
+        if( pEntry )
+            nFirstVis = GetAbsPos( pEntry );
+
+        pEntry = static_cast<CustomAnimationListEntry*>(GetLastEntryInView());
+        if( pEntry )
+            nLastVis = GetAbsPos( pEntry );
+
+        pEntry = static_cast<CustomAnimationListEntry*>(FirstSelected());
         if( pEntry )
-            pFirstVisibleEffect = pEntry->getEffect();
+        {
+            pFirstSelEffect = pEntry->getEffect();
+            nFirstSelOld = GetAbsPos( pEntry );
+        }
 
+        pEntry = static_cast<CustomAnimationListEntry*>(LastSelected());
+        if( pEntry )
+        {
+            pLastSelEffect = pEntry->getEffect();
+            nLastSelOld = GetAbsPos( pEntry );
+        }
+
+        // save selection and expand states
         pEntry = static_cast<CustomAnimationListEntry*>(First());
 
         while( pEntry )
@@ -668,15 +698,59 @@ void CustomAnimationList::update()
                 if( std::find( aSelected.begin(), aSelected.end(), pEffect ) != aSelected.end() )
                     Select( pEntry );
 
-                if( pFirstVisibleEffect == pEffect )
-                    MakeVisible( pEntry );
+                if( pEffect == pFirstSelEffect )
+                    nFirstSelNew = GetAbsPos( pEntry );
+
+                if( pEffect == pLastSelEffect )
+                    nLastSelNew = GetAbsPos( pEntry );
             }
 
             pEntry = static_cast<CustomAnimationListEntry*>(Next( pEntry ));
         }
+
+        // Scroll to a selected entry, depending on where the selection moved.
+        bMoved = nFirstSelNew != nFirstSelOld;
+        bMovedUp = nFirstSelNew < nFirstSelOld;
+        bMovedDown = nFirstSelNew > nFirstSelOld;
+
+        if( bMoved && nLastSelOld < nFirstVis && nLastSelNew < nFirstVis )
+        {
+            // The selection is above the visible area.
+            // Scroll up to show the last few selected entries.
+            if( nLastSelNew - (nLastVis - nFirstVis) > nFirstSelNew)
+            {
+                // The entries in the selection range can't fit in view.
+                // Scroll so the last selected entry is last in view.
+                ScrollToAbsPos( nLastSelNew - (nLastVis - nFirstVis) );
+            }
+            else
+                ScrollToAbsPos( nFirstSelNew );
+        }
+        else if( bMoved && nFirstSelOld > nLastVis && nFirstSelNew > nLastVis )
+        {
+            // The selection is below the visible area.
+            // Scroll down to the first few selected entries.
+            ScrollToAbsPos( nFirstSelNew );
+        }
+        else if( bMovedUp && nFirstSelOld <= nFirstVis )
+        {
+            // A visible entry has moved up out of view; scroll up one.
+            ScrollToAbsPos( nFirstVis - 1 );
+        }
+        else if( bMovedDown && nLastSelOld >= nLastVis )
+        {
+            // An entry has moved down out of view; scroll down one.
+            ScrollToAbsPos( nFirstVis + 1 );
+        }
+        else
+        {
+            // The selection is still in view, or it hasn't moved.
+            ScrollToAbsPos( nFirstVis );
+        }
     }
 
     mbIgnorePaint = false;
+    SetUpdateMode( sal_True );
     Invalidate();
 }
 
-- 
1.7.5.4

From c61c5af219b3884e3881a6305ba692dec61c6555 Mon Sep 17 00:00:00 2001
From: Luke Symes <allsymes@gmail.com>
Date: Wed, 22 Jun 2011 19:13:11 +1200
Subject: [PATCH 2/2] Don't update CustomAnimationList when we are already
 updating it.

When we update the CustomAnimationList, we restore the selection state,
and we don't want this to cause more updates (since that makes the
scrollbar flash annoyingly).
---
 sd/source/ui/animations/CustomAnimationList.cxx |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/sd/source/ui/animations/CustomAnimationList.cxx 
b/sd/source/ui/animations/CustomAnimationList.cxx
index 224129a..196fc53 100644
--- a/sd/source/ui/animations/CustomAnimationList.cxx
+++ b/sd/source/ui/animations/CustomAnimationList.cxx
@@ -865,6 +865,8 @@ void CustomAnimationList::onSelectionChanged( Any aSelection )
 
 void CustomAnimationList::SelectHdl()
 {
+    if( mbIgnorePaint )
+        return;
     SvTreeListBox::SelectHdl();
     mpController->onSelect();
 }
-- 
1.7.5.4


Context


Privacy Policy | Impressum (Legal Info) | Copyright information: Unless otherwise specified, all text and images on this website are licensed under the Creative Commons Attribution-Share Alike 3.0 License. This does not include the source code of LibreOffice, which is licensed under the Mozilla Public License (MPLv2). "LibreOffice" and "The Document Foundation" are registered trademarks of their corresponding registered owners or are in actual use as trademarks in one or more countries. Their respective logos and icons are also subject to international copyright laws. Use thereof is explained in our trademark policy.