weld NavigationBar

Change-Id: I5d31d603a9e5f91723a310900aeee875df1599c2
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/99445
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
diff --git a/include/svtools/brwbox.hxx b/include/svtools/brwbox.hxx
index 00b6880..63796c7 100644
--- a/include/svtools/brwbox.hxx
+++ b/include/svtools/brwbox.hxx
@@ -39,7 +39,7 @@
class BrowserColumn;
class BrowserHeader;
class ScrollBar;
class RecordItemWindow;
class MeasureStatusBar;

namespace svt {
    class BrowseBoxImpl;
@@ -275,7 +275,7 @@ private:
    VclPtr<BrowserDataWin> pDataWin;       // window to display data rows
    VclPtr<ScrollBar>      pVScroll;       // vertical scrollbar
    VclPtr<ScrollBar>      aHScroll;       // horizontal scrollbar
    VclPtr<RecordItemWindow> aStatusBarHeight; // statusbar, just to measure its height
    VclPtr<MeasureStatusBar> aStatusBarHeight; // statusbar, just to measure its height

    long            nDataRowHeight; // height of a single data-row
    sal_uInt16      nTitleLines;    // number of lines in title row
diff --git a/include/svtools/recorditemwindow.hxx b/include/svtools/recorditemwindow.hxx
index 576be87..06571a7 100644
--- a/include/svtools/recorditemwindow.hxx
+++ b/include/svtools/recorditemwindow.hxx
@@ -12,24 +12,24 @@
#include <vcl/InterimItemWindow.hxx>
#include <svtools/svtdllapi.h>

class SVT_DLLPUBLIC RecordItemWindow : public InterimItemWindow
class SVT_DLLPUBLIC RecordItemWindowBase
{
public:
    RecordItemWindow(vcl::Window* pParent, bool bHasFrame);
    virtual void dispose() override;
    virtual ~RecordItemWindow() override;
    RecordItemWindowBase(std::unique_ptr<weld::Entry> xEntry);
    virtual ~RecordItemWindowBase();

    void set_text(const OUString& rText) { m_xWidget->set_text(rText); }
    void set_font(const vcl::Font& rFont) { m_xWidget->set_font(rFont); }
    void set_help_id(const OString& rHelpId) { m_xWidget->set_help_id(rHelpId); }

protected:
    std::unique_ptr<weld::Entry> m_xWidget;

    virtual bool DoKeyInput(const KeyEvent& rEvt);

private:
    virtual void PositionFired(sal_Int64 nRecord);

    std::unique_ptr<weld::Entry> m_xWidget;

    DECL_LINK(KeyInputHdl, const KeyEvent&, bool);

    DECL_LINK(ActivatedHdl, weld::Entry&, bool);
@@ -39,4 +39,15 @@ private:
    void FirePosition(bool bForce);
};

class SVT_DLLPUBLIC RecordItemWindow : public InterimItemWindow, public RecordItemWindowBase
{
public:
    RecordItemWindow(vcl::Window* pParent, bool bHasFrame);
    virtual void dispose() override;
    virtual ~RecordItemWindow() override;

protected:
    virtual bool DoKeyInput(const KeyEvent& rEvt) override;
};

/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/include/svx/gridctrl.hxx b/include/svx/gridctrl.hxx
index c07f9ed4..dfcf5cb 100644
--- a/include/svx/gridctrl.hxx
+++ b/include/svx/gridctrl.hxx
@@ -39,10 +39,6 @@ namespace com::sun::star::sdb { class XRowsChangeListener; }
namespace com::sun::star::uno { class XComponentContext; }
namespace com::sun::star::util { class XNumberFormatter; }

class Button;
class ImageButton;
class FixedText;

class CursorWrapper;

bool CompareBookmark(const css::uno::Any& aLeft, const css::uno::Any& aRight);
@@ -163,6 +159,70 @@ enum class DbGridControlNavigationBarState

class FmXGridSourcePropListener;
class DisposeListenerGridBridge;

// NavigationBar
class NavigationBar final : public InterimItemWindow
{
    class AbsolutePos final : public RecordItemWindowBase
    {
    public:
        AbsolutePos(std::unique_ptr<weld::Entry> xEntry, NavigationBar* pBar);

        virtual bool DoKeyInput(const KeyEvent& rEvt) override;
        virtual void PositionFired(sal_Int64 nRecord) override;

        weld::Entry* GetWidget() { return m_xWidget.get(); }
    private:
        VclPtr<NavigationBar> m_xParent;
    };

    friend class NavigationBar::AbsolutePos;

    //  additional controls
    std::unique_ptr<weld::Label> m_xRecordText;
    std::unique_ptr<AbsolutePos> m_xAbsolute;         // absolute positioning
    std::unique_ptr<weld::Label> m_xRecordOf;
    std::unique_ptr<weld::Label> m_xRecordCount;

    std::unique_ptr<weld::Button> m_xFirstBtn;        // Button for 'go to the first record'
    std::unique_ptr<weld::Button> m_xPrevBtn;         // Button for 'go to the previous record'
    std::unique_ptr<weld::Button> m_xNextBtn;         // Button for 'go to the next record'
    std::unique_ptr<weld::Button> m_xLastBtn;         // Button for 'go to the last record'
    std::unique_ptr<weld::Button> m_xNewBtn;          // Button for 'go to a new record'

    AutoTimer m_aNextRepeat;
    AutoTimer m_aPrevRepeat;

    sal_Int32            m_nCurrentPos;

    bool                 m_bPositioning;     // protect PositionDataSource against recursion

public:
    NavigationBar(vcl::Window* pParent);
    virtual ~NavigationBar() override;
    virtual void dispose() override;

    // Status methods for Controls
    void InvalidateAll(sal_Int32 nCurrentPos, bool bAll = false);
    void InvalidateState(DbGridControlNavigationBarState nWhich) {SetState(nWhich);}
    void SetState(DbGridControlNavigationBarState nWhich);
    bool GetState(DbGridControlNavigationBarState nWhich) const;
    sal_uInt16 ArrangeControls();

private:

    DECL_LINK(OnClick, weld::Button&, void);

    DECL_LINK(PrevMousePressHdl, const MouseEvent&, bool);
    DECL_LINK(PrevMouseReleaseHdl, const MouseEvent&, bool);
    DECL_LINK(NextMousePressHdl, const MouseEvent&, bool);
    DECL_LINK(NextMouseReleaseHdl, const MouseEvent&, bool);
    DECL_LINK(PrevRepeatTimerHdl, Timer*, void);
    DECL_LINK(NextRepeatTimerHdl, Timer*, void);

    void PositionDataSource(sal_Int32 nRecord);
};

class SVXCORE_DLLPUBLIC DbGridControl : public svt::EditBrowseBox
{
    friend class FmXGridSourcePropListener;
@@ -171,59 +231,7 @@ class SVXCORE_DLLPUBLIC DbGridControl : public svt::EditBrowseBox

public:

    // NavigationBar

    class SAL_DLLPRIVATE NavigationBar final : public Control
    {
        class AbsolutePos final : public RecordItemWindow
        {
        public:
            AbsolutePos(vcl::Window* pParent);

            virtual bool DoKeyInput(const KeyEvent& rEvt) override;
            virtual void PositionFired(sal_Int64 nRecord) override;
        };

        friend class NavigationBar::AbsolutePos;

        //  additional controls
        VclPtr<FixedText>    m_aRecordText;
        VclPtr<AbsolutePos>  m_aAbsolute;            // absolute positioning
        VclPtr<FixedText>    m_aRecordOf;
        VclPtr<FixedText>    m_aRecordCount;

        VclPtr<ImageButton>  m_aFirstBtn;            // ImageButton for 'go to the first record'
        VclPtr<ImageButton>  m_aPrevBtn;         // ImageButton for 'go to the previous record'
        VclPtr<ImageButton>  m_aNextBtn;         // ImageButton for 'go to the next record'
        VclPtr<ImageButton>  m_aLastBtn;         // ImageButton for 'go to the last record'
        VclPtr<ImageButton>  m_aNewBtn;          // ImageButton for 'go to a new record'
        sal_Int32            m_nCurrentPos;

        bool                 m_bPositioning;     // protect PositionDataSource against recursion

    public:
        NavigationBar(vcl::Window* pParent);
        virtual ~NavigationBar() override;
        virtual void dispose() override;

        // Status methods for Controls
        void InvalidateAll(sal_Int32 nCurrentPos, bool bAll = false);
        void InvalidateState(DbGridControlNavigationBarState nWhich) {SetState(nWhich);}
        void SetState(DbGridControlNavigationBarState nWhich);
        bool GetState(DbGridControlNavigationBarState nWhich) const;
        sal_uInt16 ArrangeControls();

    private:
        virtual void Resize() override;
        virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override;
        virtual void StateChanged( StateChangedType nType ) override;

        DECL_LINK(OnClick, Button*, void);

        void PositionDataSource(sal_Int32 nRecord);
    };

    friend class DbGridControl::NavigationBar;
    friend class NavigationBar;

private:
    Link<DbGridControlNavigationBarState,int>    m_aMasterStateProvider;
diff --git a/solenv/sanitizers/ui/svx.suppr b/solenv/sanitizers/ui/svx.suppr
index 5a9d0f5..7f01613 100644
--- a/solenv/sanitizers/ui/svx.suppr
+++ b/solenv/sanitizers/ui/svx.suppr
@@ -69,6 +69,7 @@ svx/uiconfig/ui/mediawindow.ui://GtkLabel[@id='url'] orphan-label
svx/uiconfig/ui/mediawindow.ui://GtkScale[@id='timeslider'] no-labelled-by
svx/uiconfig/ui/mediawindow.ui://GtkScale[@id='volumeslider'] no-labelled-by
svx/uiconfig/ui/metricfieldbox.ui://GtkSpinButton[@id='metricfield'] no-labelled-by
svx/uiconfig/ui/navigationbar.ui://GtkEntry[@id='entry-noframe'] no-labelled-by
svx/uiconfig/ui/numberingwindow.ui://GtkButton[@id='more'] button-no-label
svx/uiconfig/ui/optgridpage.ui://GtkLabel[@id='label4'] orphan-label
svx/uiconfig/ui/optgridpage.ui://GtkLabel[@id='label5'] orphan-label
diff --git a/svtools/source/brwbox/brwbox1.cxx b/svtools/source/brwbox/brwbox1.cxx
index eb18538..943e888 100644
--- a/svtools/source/brwbox/brwbox1.cxx
+++ b/svtools/source/brwbox/brwbox1.cxx
@@ -27,6 +27,7 @@
#include <tools/fract.hxx>
#include <sal/log.hxx>
#include <vcl/scrbar.hxx>
#include <vcl/svapp.hxx>

#include <algorithm>
#include <com/sun/star/accessibility/AccessibleTableModelChange.hpp>
@@ -105,12 +106,59 @@ void BrowseBox::ConstructImpl( BrowserMode nMode )
                ( bHasFocus ? 0 : 1 ) + ( GetUpdateMode() ? 0 : 1 );
}

// we're just measuring the "real" NavigationBar
class MeasureStatusBar final : public InterimItemWindow
{
private:
    std::unique_ptr<weld::Label> m_xRecordText;
    std::unique_ptr<weld::Entry> m_xAbsolute;
    std::unique_ptr<weld::Label> m_xRecordOf;
    std::unique_ptr<weld::Label> m_xRecordCount;
public:
    MeasureStatusBar(vcl::Window *pParent)
        : InterimItemWindow(pParent, "svx/ui/navigationbar.ui", "NavigationBar")
        , m_xRecordText(m_xBuilder->weld_label("recordtext"))
        , m_xAbsolute(m_xBuilder->weld_entry("entry-noframe"))
        , m_xRecordOf(m_xBuilder->weld_label("recordof"))
        , m_xRecordCount(m_xBuilder->weld_label("recordcount"))
    {
        vcl::Font aApplFont(Application::GetSettings().GetStyleSettings().GetToolFont());
        m_xAbsolute->set_font(aApplFont);
        m_xRecordText->set_font(aApplFont);
        m_xRecordOf->set_font(aApplFont);
        m_xRecordCount->set_font(aApplFont);

        SetSizePixel(get_preferred_size());
    }

    virtual void dispose() override
    {
        m_xRecordCount.reset();
        m_xRecordOf.reset();
        m_xAbsolute.reset();
        m_xRecordText.reset();
        InterimItemWindow::dispose();
    }
};

long BrowseBox::GetBarHeight() const
{
    // tdf#115941 because some platforms have things like overlay scrollbars, take a max
    // of a statusbar height and a scrollbar height as the control area height

    // (we can't ask the scrollbars for their size cause if we're zoomed they still have to be
    // resized - which is done in UpdateScrollbars)

    return std::max(aStatusBarHeight->GetSizePixel().Height(), GetSettings().GetStyleSettings().GetScrollBarSize());
}

BrowseBox::BrowseBox( vcl::Window* pParent, WinBits nBits, BrowserMode nMode )
    :Control( pParent, nBits | WB_3DLOOK )
    ,DragSourceHelper( this )
    ,DropTargetHelper( this )
    ,aHScroll( VclPtr<ScrollBar>::Create(this, WB_HSCROLL) )
    ,aStatusBarHeight(VclPtr<RecordItemWindow>::Create(this, false))
    // see NavigationBar ctor, here we just want to know its height
    ,aStatusBarHeight(VclPtr<MeasureStatusBar>::Create(this))
{
    ConstructImpl( nMode );
}
diff --git a/svtools/source/brwbox/brwbox2.cxx b/svtools/source/brwbox/brwbox2.cxx
index 5abdf5e..298a61a 100644
--- a/svtools/source/brwbox/brwbox2.cxx
+++ b/svtools/source/brwbox/brwbox2.cxx
@@ -1029,17 +1029,6 @@ void BrowseBox::PaintData( vcl::Window const & rWin, vcl::RenderContext& rRender
    ImplPaintData(rRenderContext, rRect, false);
}

long BrowseBox::GetBarHeight() const
{
    // tdf#115941 because some platforms have things like overlay scrollbars, take a max
    // of a statusbar height and a scrollbar height as the control area height

    // (we can't ask the scrollbars for their size cause if we're zoomed they still have to be
    // resized - which is done in UpdateScrollbars)

    return std::max(aStatusBarHeight->GetSizePixel().Height(), GetSettings().GetStyleSettings().GetScrollBarSize());
}

void BrowseBox::UpdateScrollbars()
{

diff --git a/svtools/source/brwbox/recorditemwindow.cxx b/svtools/source/brwbox/recorditemwindow.cxx
index a993044..6898f9f 100644
--- a/svtools/source/brwbox/recorditemwindow.cxx
+++ b/svtools/source/brwbox/recorditemwindow.cxx
@@ -20,17 +20,23 @@
#include <svtools/recorditemwindow.hxx>
#include <vcl/event.hxx>

RecordItemWindow::RecordItemWindow(vcl::Window* pParent, bool bHasFrame)
    : InterimItemWindow(pParent, "svx/ui/absrecbox.ui", "AbsRecBox")
    , m_xWidget(m_xBuilder->weld_entry(bHasFrame ? "entry-frame" : "entry-noframe"))
RecordItemWindowBase::RecordItemWindowBase(std::unique_ptr<weld::Entry> xEntry)
    : m_xWidget(std::move(xEntry))
{
    InitControlBase(m_xWidget.get());

    m_xWidget->connect_key_press(LINK(this, RecordItemWindow, KeyInputHdl));
    m_xWidget->connect_activate(LINK(this, RecordItemWindow, ActivatedHdl));
    m_xWidget->connect_focus_out(LINK(this, RecordItemWindow, FocusOutHdl));
    m_xWidget->connect_key_press(LINK(this, RecordItemWindowBase, KeyInputHdl));
    m_xWidget->connect_activate(LINK(this, RecordItemWindowBase, ActivatedHdl));
    m_xWidget->connect_focus_out(LINK(this, RecordItemWindowBase, FocusOutHdl));

    m_xWidget->show();
}

RecordItemWindowBase::~RecordItemWindowBase() {}

RecordItemWindow::RecordItemWindow(vcl::Window* pParent, bool bHasFrame)
    : InterimItemWindow(pParent, "svx/ui/absrecbox.ui", "AbsRecBox")
    , RecordItemWindowBase(m_xBuilder->weld_entry(bHasFrame ? "entry-frame" : "entry-noframe"))
{
    InitControlBase(m_xWidget.get());

    auto aPrefSize(m_xWidget->get_preferred_size());

@@ -47,7 +53,7 @@ void RecordItemWindow::dispose()

RecordItemWindow::~RecordItemWindow() { disposeOnce(); }

void RecordItemWindow::FirePosition(bool _bForce)
void RecordItemWindowBase::FirePosition(bool _bForce)
{
    if (!_bForce && !m_xWidget->get_value_changed_from_saved())
        return;
@@ -61,9 +67,9 @@ void RecordItemWindow::FirePosition(bool _bForce)
    m_xWidget->save_value();
}

IMPL_LINK_NOARG(RecordItemWindow, FocusOutHdl, weld::Widget&, void) { FirePosition(false); }
IMPL_LINK_NOARG(RecordItemWindowBase, FocusOutHdl, weld::Widget&, void) { FirePosition(false); }

bool RecordItemWindow::DoKeyInput(const KeyEvent& rKEvt)
bool RecordItemWindowBase::DoKeyInput(const KeyEvent& rKEvt)
{
    vcl::KeyCode aCode = rKEvt.GetKeyCode();
    bool bUp = (aCode.GetCode() == KEY_UP);
@@ -82,14 +88,22 @@ bool RecordItemWindow::DoKeyInput(const KeyEvent& rKEvt)
        return true;
    }

    return ChildKeyInput(rKEvt);
    return false;
}

void RecordItemWindow::PositionFired(sal_Int64 /*nRecord*/) {}
bool RecordItemWindow::DoKeyInput(const KeyEvent& rKEvt)
{
    return RecordItemWindowBase::DoKeyInput(rKEvt) || ChildKeyInput(rKEvt);
}

IMPL_LINK(RecordItemWindow, KeyInputHdl, const KeyEvent&, rKEvt, bool) { return DoKeyInput(rKEvt); }
void RecordItemWindowBase::PositionFired(sal_Int64 /*nRecord*/) {}

IMPL_LINK_NOARG(RecordItemWindow, ActivatedHdl, weld::Entry&, bool)
IMPL_LINK(RecordItemWindowBase, KeyInputHdl, const KeyEvent&, rKEvt, bool)
{
    return DoKeyInput(rKEvt);
}

IMPL_LINK_NOARG(RecordItemWindowBase, ActivatedHdl, weld::Entry&, bool)
{
    if (!m_xWidget->get_text().isEmpty())
        FirePosition(true);
diff --git a/svx/UIConfig_svx.mk b/svx/UIConfig_svx.mk
index 4180c18..098a7d3 100644
--- a/svx/UIConfig_svx.mk
+++ b/svx/UIConfig_svx.mk
@@ -94,6 +94,7 @@ $(eval $(call gb_UIConfig_add_uifiles,svx,\
	svx/uiconfig/ui/mediawindow \
	svx/uiconfig/ui/metricfieldbox \
	svx/uiconfig/ui/namespacedialog \
	svx/uiconfig/ui/navigationbar \
	svx/uiconfig/ui/numberingwindow \
	svx/uiconfig/ui/optgridpage \
	svx/uiconfig/ui/paralinespacingcontrol \
diff --git a/svx/inc/pch/precompiled_svx.hxx b/svx/inc/pch/precompiled_svx.hxx
index 0c96cac..e1f9eca 100644
--- a/svx/inc/pch/precompiled_svx.hxx
+++ b/svx/inc/pch/precompiled_svx.hxx
@@ -13,7 +13,7 @@
 manual changes will be rewritten by the next run of update_pch.sh (which presumably
 also fixes all possible problems, so it's usually better to use it).

 Generated on 2020-07-09 17:06:53 using:
 Generated on 2020-07-25 14:55:56 using:
 ./bin/update_pch svx svx --cutoff=3 --exclude:system --exclude:module --include:local

 If after updating build fails, use the following command to locate conflicting headers:
@@ -99,6 +99,7 @@
#include <vcl/metric.hxx>
#include <vcl/outdev.hxx>
#include <vcl/ptrstyle.hxx>
#include <vcl/salctype.hxx>
#include <vcl/settings.hxx>
#include <vcl/status.hxx>
#include <vcl/svapp.hxx>
@@ -109,6 +110,7 @@
#include <vcl/vclptr.hxx>
#include <vcl/virdev.hxx>
#include <vcl/weld.hxx>
#include <vcl/weldutils.hxx>
#include <vcl/window.hxx>
#endif // PCH_LEVEL >= 2
#if PCH_LEVEL >= 3
@@ -138,7 +140,6 @@
#include <com/sun/star/awt/Rectangle.hpp>
#include <com/sun/star/awt/XControl.hpp>
#include <com/sun/star/awt/XControlContainer.hpp>
#include <com/sun/star/awt/XWindow.hpp>
#include <com/sun/star/beans/NamedValue.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/beans/XPropertyChangeListener.hpp>
@@ -361,7 +362,6 @@
#include <uno/sequence2.h>
#include <unotools/accessiblerelationsethelper.hxx>
#include <unotools/accessiblestatesethelper.hxx>
#include <unotools/configitem.hxx>
#include <unotools/fontcvt.hxx>
#include <unotools/localedatawrapper.hxx>
#include <unotools/options.hxx>
diff --git a/svx/inc/pch/precompiled_svxcore.hxx b/svx/inc/pch/precompiled_svxcore.hxx
index af5edfc..0f5d6f8 100644
--- a/svx/inc/pch/precompiled_svxcore.hxx
+++ b/svx/inc/pch/precompiled_svxcore.hxx
@@ -13,7 +13,7 @@
 manual changes will be rewritten by the next run of update_pch.sh (which presumably
 also fixes all possible problems, so it's usually better to use it).

 Generated on 2020-07-21 21:30:38 using:
 Generated on 2020-07-25 14:55:53 using:
 ./bin/update_pch svx svxcore --cutoff=7 --exclude:system --include:module --exclude:local

 If after updating build fails, use the following command to locate conflicting headers:
@@ -65,6 +65,7 @@
#include <osl/getglobalmutex.hxx>
#include <osl/interlck.h>
#include <osl/mutex.hxx>
#include <osl/thread.h>
#include <osl/time.h>
#include <rtl/alloc.h>
#include <rtl/character.hxx>
@@ -111,7 +112,6 @@
#include <vcl/ctrl.hxx>
#include <vcl/customweld.hxx>
#include <vcl/dllapi.h>
#include <vcl/dndhelp.hxx>
#include <vcl/dockwin.hxx>
#include <vcl/errcode.hxx>
#include <vcl/event.hxx>
@@ -137,7 +137,6 @@
#include <vcl/svapp.hxx>
#include <vcl/syswin.hxx>
#include <vcl/task.hxx>
#include <vcl/textfilter.hxx>
#include <vcl/timer.hxx>
#include <vcl/transfer.hxx>
#include <vcl/vclenum.hxx>
diff --git a/svx/source/fmcomp/gridctrl.cxx b/svx/source/fmcomp/gridctrl.cxx
index 820df8e..af17172 100644
--- a/svx/source/fmcomp/gridctrl.cxx
+++ b/svx/source/fmcomp/gridctrl.cxx
@@ -45,8 +45,6 @@
#include <tools/debug.hxx>
#include <tools/fract.hxx>
#include <vcl/builder.hxx>
#include <vcl/button.hxx>
#include <vcl/fixed.hxx>
#include <vcl/menu.hxx>
#include <vcl/settings.hxx>
#include <vcl/commandevent.hxx>
@@ -274,29 +272,31 @@ void FmXGridSourcePropListener::_propertyChanged(const PropertyChangeEvent& evt)
        m_pParent->DataSourcePropertyChanged(evt);
}

DbGridControl::NavigationBar::AbsolutePos::AbsolutePos(vcl::Window* pParent)
    : RecordItemWindow(pParent, false)
const int nReserveNumDigits = 7;

NavigationBar::AbsolutePos::AbsolutePos(std::unique_ptr<weld::Entry> xEntry, NavigationBar* pBar)
    : RecordItemWindowBase(std::move(xEntry))
    , m_xParent(pBar)
{
}

bool DbGridControl::NavigationBar::AbsolutePos::DoKeyInput(const KeyEvent& rEvt)
bool NavigationBar::AbsolutePos::DoKeyInput(const KeyEvent& rEvt)
{
    if (rEvt.GetKeyCode() == KEY_TAB)
    {
        GetParent()->GetParent()->GrabFocus();
        m_xParent->GetParent()->GrabFocus();
        return true;
    }
    return RecordItemWindow::DoKeyInput(rEvt);
    return RecordItemWindowBase::DoKeyInput(rEvt);
}

void DbGridControl::NavigationBar::AbsolutePos::PositionFired(sal_Int64 nRecord)
void NavigationBar::AbsolutePos::PositionFired(sal_Int64 nRecord)
{
    NavigationBar* pBar = static_cast<NavigationBar*>(GetParent());
    pBar->PositionDataSource(nRecord);
    pBar->InvalidateState(DbGridControlNavigationBarState::Absolute);
    m_xParent->PositionDataSource(nRecord);
    m_xParent->InvalidateState(DbGridControlNavigationBarState::Absolute);
}

void DbGridControl::NavigationBar::PositionDataSource(sal_Int32 nRecord)
void NavigationBar::PositionDataSource(sal_Int32 nRecord)
{
    if (m_bPositioning)
        return;
@@ -307,236 +307,145 @@ void DbGridControl::NavigationBar::PositionDataSource(sal_Int32 nRecord)
    m_bPositioning = false;
}

DbGridControl::NavigationBar::NavigationBar(vcl::Window* pParent)
          :Control(pParent, 0)
          ,m_aRecordText(VclPtr<FixedText>::Create(this, WB_VCENTER))
          ,m_aAbsolute(VclPtr<DbGridControl::NavigationBar::AbsolutePos>::Create(this))
          ,m_aRecordOf(VclPtr<FixedText>::Create(this, WB_VCENTER))
          ,m_aRecordCount(VclPtr<FixedText>::Create(this, WB_VCENTER))
          ,m_aFirstBtn(VclPtr<ImageButton>::Create(this, WB_RECTSTYLE|WB_NOPOINTERFOCUS))
          ,m_aPrevBtn(VclPtr<ImageButton>::Create(this, WB_REPEAT|WB_RECTSTYLE|WB_NOPOINTERFOCUS))
          ,m_aNextBtn(VclPtr<ImageButton>::Create(this, WB_REPEAT|WB_RECTSTYLE|WB_NOPOINTERFOCUS))
          ,m_aLastBtn(VclPtr<ImageButton>::Create(this, WB_RECTSTYLE|WB_NOPOINTERFOCUS))
          ,m_aNewBtn(VclPtr<ImageButton>::Create(this, WB_RECTSTYLE|WB_NOPOINTERFOCUS))
          ,m_nCurrentPos(-1)
          ,m_bPositioning(false)
NavigationBar::NavigationBar(vcl::Window* pParent)
    : InterimItemWindow(pParent, "svx/ui/navigationbar.ui", "NavigationBar")
    , m_xRecordText(m_xBuilder->weld_label("recordtext"))
    , m_xAbsolute(new NavigationBar::AbsolutePos(m_xBuilder->weld_entry("entry-noframe"), this))
    , m_xRecordOf(m_xBuilder->weld_label("recordof"))
    , m_xRecordCount(m_xBuilder->weld_label("recordcount"))
    , m_xFirstBtn(m_xBuilder->weld_button("first"))
    , m_xPrevBtn(m_xBuilder->weld_button("prev"))
    , m_xNextBtn(m_xBuilder->weld_button("next"))
    , m_xLastBtn(m_xBuilder->weld_button("last"))
    , m_xNewBtn(m_xBuilder->weld_button("new"))
    , m_nCurrentPos(-1)
    , m_bPositioning(false)
{
    m_aFirstBtn->SetSymbol(SymbolType::FIRST);
    m_aPrevBtn->SetSymbol(SymbolType::PREV);
    m_aNextBtn->SetSymbol(SymbolType::NEXT);
    m_aLastBtn->SetSymbol(SymbolType::LAST);
    m_aNewBtn->SetModeImage(static_cast<DbGridControl*>(pParent)->GetImage(EditBrowseBox::NEW));
    vcl::Font aApplFont(Application::GetSettings().GetStyleSettings().GetToolFont());
    m_xAbsolute->set_font(aApplFont);
    aApplFont.SetTransparent(true);
    m_xRecordText->set_font(aApplFont);
    m_xRecordOf->set_font(aApplFont);
    m_xRecordCount->set_font(aApplFont);

    m_aFirstBtn->SetHelpId(HID_GRID_TRAVEL_FIRST);
    m_aPrevBtn->SetHelpId(HID_GRID_TRAVEL_PREV);
    m_aNextBtn->SetHelpId(HID_GRID_TRAVEL_NEXT);
    m_aLastBtn->SetHelpId(HID_GRID_TRAVEL_LAST);
    m_aNewBtn->SetHelpId(HID_GRID_TRAVEL_NEW);
    m_aAbsolute->SetHelpId(HID_GRID_TRAVEL_ABSOLUTE);
    m_aRecordCount->SetHelpId(HID_GRID_NUMBEROFRECORDS);
    m_xFirstBtn->set_help_id(HID_GRID_TRAVEL_FIRST);
    m_xPrevBtn->set_help_id(HID_GRID_TRAVEL_PREV);
    m_xNextBtn->set_help_id(HID_GRID_TRAVEL_NEXT);
    m_xLastBtn->set_help_id(HID_GRID_TRAVEL_LAST);
    m_xNewBtn->set_help_id(HID_GRID_TRAVEL_NEW);
    m_xAbsolute->set_help_id(HID_GRID_TRAVEL_ABSOLUTE);
    m_xRecordCount->set_help_id(HID_GRID_NUMBEROFRECORDS);

    // set handlers for buttons
    m_aFirstBtn->SetClickHdl(LINK(this,NavigationBar,OnClick));
    m_aPrevBtn->SetClickHdl(LINK(this,NavigationBar,OnClick));
    m_aNextBtn->SetClickHdl(LINK(this,NavigationBar,OnClick));
    m_aLastBtn->SetClickHdl(LINK(this,NavigationBar,OnClick));
    m_aNewBtn->SetClickHdl(LINK(this,NavigationBar,OnClick));
    m_xFirstBtn->connect_clicked(LINK(this,NavigationBar,OnClick));
    m_xLastBtn->connect_clicked(LINK(this,NavigationBar,OnClick));
    m_xNewBtn->connect_clicked(LINK(this,NavigationBar,OnClick));

    m_aRecordText->SetText(SvxResId(RID_STR_REC_TEXT));
    m_aRecordOf->SetText(SvxResId(RID_STR_REC_FROM_TEXT));
    m_aRecordCount->SetText(OUString('?'));
    // instead of connect_clicked because we want a a button held down to
    // repeat the next/prev
    m_xPrevBtn->connect_mouse_press(LINK(this, NavigationBar, PrevMousePressHdl));
    m_xNextBtn->connect_mouse_press(LINK(this, NavigationBar, NextMousePressHdl));
    m_xPrevBtn->connect_mouse_release(LINK(this, NavigationBar, PrevMouseReleaseHdl));
    m_xNextBtn->connect_mouse_release(LINK(this, NavigationBar, NextMouseReleaseHdl));

    m_aFirstBtn->Disable();
    m_aPrevBtn->Disable();
    m_aNextBtn->Disable();
    m_aLastBtn->Disable();
    m_aNewBtn->Disable();
    m_aRecordText->Disable();
    m_aRecordOf->Disable();
    m_aRecordCount->Disable();
    m_aAbsolute->Disable();
    auto nRepeatTime = Application::GetSettings().GetMouseSettings().GetButtonRepeat();
    m_aNextRepeat.SetTimeout(nRepeatTime);
    m_aNextRepeat.SetInvokeHandler(LINK(this, NavigationBar, NextRepeatTimerHdl));
    m_aPrevRepeat.SetTimeout(nRepeatTime);
    m_aPrevRepeat.SetInvokeHandler(LINK(this, NavigationBar, PrevRepeatTimerHdl));

    m_aFirstBtn->Show();
    m_aPrevBtn->Show();
    m_aNextBtn->Show();
    m_aLastBtn->Show();
    m_aNewBtn->Show();
    m_aRecordText->Show();
    m_aRecordOf->Show();
    m_aRecordCount->Show();
    m_aAbsolute->Show();
    m_xRecordText->set_label(SvxResId(RID_STR_REC_TEXT));
    m_xRecordOf->set_label(SvxResId(RID_STR_REC_FROM_TEXT));
    m_xRecordCount->set_label(OUString('?'));

    auto nReserveWidth = m_xRecordCount->get_approximate_digit_width() * nReserveNumDigits;
    m_xAbsolute->GetWidget()->set_size_request(nReserveWidth, -1);
    m_xRecordCount->set_size_request(nReserveWidth, -1);
}

DbGridControl::NavigationBar::~NavigationBar()
NavigationBar::~NavigationBar()
{
    disposeOnce();
}

void DbGridControl::NavigationBar::dispose()
void NavigationBar::dispose()
{
    m_aRecordText.disposeAndClear();
    m_aAbsolute.disposeAndClear();
    m_aRecordOf.disposeAndClear();
    m_aRecordCount.disposeAndClear();
    m_aFirstBtn.disposeAndClear();
    m_aPrevBtn.disposeAndClear();
    m_aNextBtn.disposeAndClear();
    m_aLastBtn.disposeAndClear();
    m_aNewBtn.disposeAndClear();
    Control::dispose();
    m_xRecordText.reset();
    m_xAbsolute.reset();
    m_xRecordOf.reset();
    m_xRecordCount.reset();
    m_xFirstBtn.reset();
    m_xPrevBtn.reset();
    m_xNextBtn.reset();
    m_xLastBtn.reset();
    m_xNewBtn.reset();
    InterimItemWindow::dispose();
}

namespace
sal_uInt16 NavigationBar::ArrangeControls()
{
    void SetPosAndSize(Button& _rButton,Point& _rPos,const Size& _rSize)
    {
        _rButton.SetPosPixel( _rPos );
        _rButton.SetSizePixel( _rSize );
        _rPos.AdjustX(static_cast<sal_uInt16>(_rSize.Width()) );
    }
    return m_xContainer->get_preferred_size().Width();
}

sal_uInt16 DbGridControl::NavigationBar::ArrangeControls()
IMPL_LINK_NOARG(NavigationBar, PrevRepeatTimerHdl, Timer*, void)
{
    // positioning of the controls
    // calculate base size
    tools::Rectangle   aRect(static_cast<DbGridControl*>(GetParent())->GetControlArea());
    long nH = aRect.GetSize().Height();

    long nW = GetParent()->GetOutputSizePixel().Width();
    Size aBorder = LogicToPixel(Size(2, 2), MapMode(MapUnit::MapAppFont));
    aBorder = Size(CalcZoom(aBorder.Width()), CalcZoom(aBorder.Height()));
    sal_uInt16      nX = 1;
    sal_uInt16      nY = 0;

    {
        vcl::Font aApplFont(GetSettings().GetStyleSettings().GetToolFont());
        m_aAbsolute->set_font(aApplFont);
        aApplFont.SetTransparent( true );
        m_aRecordText->SetControlFont( aApplFont );
        m_aRecordOf->SetControlFont( aApplFont );
        m_aRecordCount->SetControlFont( aApplFont );
    }

    // set size and position of the control
    OUString aText = m_aRecordText->GetText();
    long nTextWidth = m_aRecordText->GetTextWidth(aText);
    m_aRecordText->SetPosPixel(Point(nX,nY));
    m_aRecordText->SetSizePixel(Size(nTextWidth,nH));
    nX = sal::static_int_cast< sal_uInt16 >(nX + nTextWidth + aBorder.Width());

    // count an extra hairspace (U+200A) left and right
    const OUString sevenDigits(OUString::number(6000000));
    const OUString hairSpace(u'\x200A');
    OUString textPattern = hairSpace + sevenDigits + hairSpace;
    nTextWidth = m_aAbsolute->GetTextWidth(textPattern);
    m_aAbsolute->SetPosPixel(Point(nX,nY));
    m_aAbsolute->SetSizePixel(Size(nTextWidth, nH));
    nX = sal::static_int_cast< sal_uInt16 >(nX + nTextWidth + aBorder.Width());

    aText      = m_aRecordOf->GetText();
    nTextWidth = m_aRecordOf->GetTextWidth(aText);
    m_aRecordOf->SetPosPixel(Point(nX,nY));
    m_aRecordOf->SetSizePixel(Size(nTextWidth,nH));
    nX = sal::static_int_cast< sal_uInt16 >(nX + nTextWidth + aBorder.Width());

    textPattern = sevenDigits + " * (" + sevenDigits + ")";
    nTextWidth = m_aRecordCount->GetTextWidth(textPattern);
    m_aRecordCount->SetPosPixel(Point(nX,nY));
    m_aRecordCount->SetSizePixel(Size(nTextWidth,nH));
    nX = sal::static_int_cast< sal_uInt16 >(nX + nTextWidth + aBorder.Width());

    Point aButtonPos(nX,nY);
    const Size  aButtonSize(nH,nH);
    SetPosAndSize(*m_aFirstBtn, aButtonPos, aButtonSize);
    SetPosAndSize(*m_aPrevBtn, aButtonPos, aButtonSize);
    SetPosAndSize(*m_aNextBtn, aButtonPos, aButtonSize);
    SetPosAndSize(*m_aLastBtn, aButtonPos, aButtonSize);
    SetPosAndSize(*m_aNewBtn, aButtonPos, aButtonSize);

    nX = sal::static_int_cast< sal_uInt16 >(aButtonPos.X() + 1);

    nW = std::max(nW - GetSettings().GetStyleSettings().GetScrollBarSize(), 0L);

    if (nX > nW)
    {
        aButtonPos.setX( nW-nH );
        m_aNewBtn->SetPosPixel(aButtonPos);
        aButtonPos.AdjustX( -nH );
        m_aLastBtn->SetPosPixel(aButtonPos);
        aButtonPos.AdjustX( -nH );
        m_aNextBtn->SetPosPixel(aButtonPos);
        aButtonPos.AdjustX( -nH );
        m_aPrevBtn->SetPosPixel(aButtonPos);
        aButtonPos.AdjustX( -nH );
        m_aFirstBtn->SetPosPixel(aButtonPos);

        auto nDiff = nX - nW;

        Size aSize = m_aAbsolute->GetSizePixel();
        aSize.AdjustWidth( -(nDiff/3.0) );
        m_aAbsolute->SetSizePixel(aSize);

        aSize = m_aRecordCount->GetSizePixel();
        aSize.AdjustWidth( -(nDiff/3.0*2) );
        m_aRecordCount->SetSizePixel(aSize);

        Point aPos = m_aRecordOf->GetPosPixel();
        aPos.AdjustX( -(nDiff/3.0) );
        m_aRecordOf->SetPosPixel(aPos);

        aPos = m_aRecordCount->GetPosPixel();
        aPos.AdjustX( -(nDiff/3.0) );
        m_aRecordCount->SetPosPixel(aPos);

        vcl::Window* pWindows[] =
        {
            m_aRecordText.get(),
            m_aAbsolute.get(),
            m_aRecordOf.get(),
            m_aRecordCount.get(),
            m_aFirstBtn.get(),
            m_aPrevBtn.get(),
            m_aNextBtn.get(),
            m_aLastBtn.get(),
            m_aNewBtn.get()
        };

        for (vcl::Window* pWindow : pWindows)
        {
            if (pWindow->GetPosPixel().X() < 0)
                pWindow->SetSizePixel(Size(0, nH));
            aSize = pWindow->GetSizePixel();
            auto nExcess = (pWindow->GetPosPixel().X() + aSize.Width()) - nW;
            if (nExcess > 0)
            {
                aSize.AdjustWidth( -nExcess );
                pWindow->SetSizePixel(aSize);
            }
        }

        nX = nW;
    }

    return nX;
    OnClick(*m_xPrevBtn);
}

IMPL_LINK(DbGridControl::NavigationBar, OnClick, Button *, pButton, void )
IMPL_LINK_NOARG(NavigationBar, NextRepeatTimerHdl, Timer*, void)
{
    OnClick(*m_xNextBtn);
}

IMPL_LINK_NOARG(NavigationBar, PrevMousePressHdl, const MouseEvent&, bool)
{
    if (!m_xPrevBtn->get_sensitive())
        return false;
    PrevRepeatTimerHdl(nullptr);
    if (!m_xPrevBtn->get_sensitive())
        return false;
    m_aPrevRepeat.Start();
    return false;
}

IMPL_LINK_NOARG(NavigationBar, PrevMouseReleaseHdl, const MouseEvent&, bool)
{
    m_aPrevRepeat.Stop();
    return false;
}

IMPL_LINK_NOARG(NavigationBar, NextMousePressHdl, const MouseEvent&, bool)
{
    if (m_xNextBtn->get_sensitive())
    {
        NextRepeatTimerHdl(nullptr);
        m_aNextRepeat.Start();
    }
    return false;
}

IMPL_LINK_NOARG(NavigationBar, NextMouseReleaseHdl, const MouseEvent&, bool)
{
    m_aNextRepeat.Stop();
    return false;
}

IMPL_LINK(NavigationBar, OnClick, weld::Button&, rButton, void)
{
    DbGridControl* pParent = static_cast<DbGridControl*>(GetParent());

    if (pParent->m_aMasterSlotExecutor.IsSet())
    {
        bool lResult = false;
        if (pButton == m_aFirstBtn.get())
        if (&rButton == m_xFirstBtn.get())
            lResult = pParent->m_aMasterSlotExecutor.Call(DbGridControlNavigationBarState::First);
        else if( pButton == m_aPrevBtn.get() )
        else if( &rButton == m_xPrevBtn.get() )
            lResult = pParent->m_aMasterSlotExecutor.Call(DbGridControlNavigationBarState::Prev);
        else if( pButton == m_aNextBtn.get() )
        else if( &rButton == m_xNextBtn.get() )
            lResult = pParent->m_aMasterSlotExecutor.Call(DbGridControlNavigationBarState::Next);
        else if( pButton == m_aLastBtn.get() )
        else if( &rButton == m_xLastBtn.get() )
            lResult = pParent->m_aMasterSlotExecutor.Call(DbGridControlNavigationBarState::Last);
        else if( pButton == m_aNewBtn.get() )
        else if( &rButton == m_xNewBtn.get() )
            lResult = pParent->m_aMasterSlotExecutor.Call(DbGridControlNavigationBarState::New);

        if (lResult)
@@ -544,19 +453,19 @@ IMPL_LINK(DbGridControl::NavigationBar, OnClick, Button *, pButton, void )
            return;
    }

    if (pButton == m_aFirstBtn.get())
    if (&rButton == m_xFirstBtn.get())
        pParent->MoveToFirst();
    else if( pButton == m_aPrevBtn.get() )
    else if( &rButton == m_xPrevBtn.get() )
        pParent->MoveToPrev();
    else if( pButton == m_aNextBtn.get() )
    else if( &rButton == m_xNextBtn.get() )
        pParent->MoveToNext();
    else if( pButton == m_aLastBtn.get() )
    else if( &rButton == m_xLastBtn.get() )
        pParent->MoveToLast();
    else if( pButton == m_aNewBtn.get() )
    else if( &rButton == m_xNewBtn.get() )
        pParent->AppendNew();
}

void DbGridControl::NavigationBar::InvalidateAll(sal_Int32 nCurrentPos, bool bAll)
void NavigationBar::InvalidateAll(sal_Int32 nCurrentPos, bool bAll)
{
    if (m_nCurrentPos != nCurrentPos || nCurrentPos < 0 || bAll)
    {
@@ -586,7 +495,7 @@ void DbGridControl::NavigationBar::InvalidateAll(sal_Int32 nCurrentPos, bool bAl
    }
}

bool DbGridControl::NavigationBar::GetState(DbGridControlNavigationBarState nWhich) const
bool NavigationBar::GetState(DbGridControlNavigationBarState nWhich) const
{
    DbGridControl* pParent = static_cast<DbGridControl*>(GetParent());

@@ -641,44 +550,44 @@ bool DbGridControl::NavigationBar::GetState(DbGridControlNavigationBarState nWhi
    }
}

void DbGridControl::NavigationBar::SetState(DbGridControlNavigationBarState nWhich)
void NavigationBar::SetState(DbGridControlNavigationBarState nWhich)
{
    bool bAvailable = GetState(nWhich);
    DbGridControl* pParent = static_cast<DbGridControl*>(GetParent());
    vcl::Window* pWnd = nullptr;
    weld::Widget* pWnd = nullptr;
    switch (nWhich)
    {
        case DbGridControlNavigationBarState::First:
            pWnd = m_aFirstBtn.get();
            pWnd = m_xFirstBtn.get();
            break;
        case DbGridControlNavigationBarState::Prev:
            pWnd = m_aPrevBtn.get();
            pWnd = m_xPrevBtn.get();
            break;
        case DbGridControlNavigationBarState::Next:
            pWnd = m_aNextBtn.get();
            pWnd = m_xNextBtn.get();
            break;
        case DbGridControlNavigationBarState::Last:
            pWnd = m_aLastBtn.get();
            pWnd = m_xLastBtn.get();
            break;
        case DbGridControlNavigationBarState::New:
            pWnd = m_aNewBtn.get();
            pWnd = m_xNewBtn.get();
            break;
        case DbGridControlNavigationBarState::Absolute:
            pWnd = m_aAbsolute.get();
            pWnd = m_xAbsolute->GetWidget();
            if (bAvailable)
                m_aAbsolute->set_text(OUString::number(m_nCurrentPos + 1));
                m_xAbsolute->set_text(OUString::number(m_nCurrentPos + 1));
            else
                m_aAbsolute->set_text(OUString());
                m_xAbsolute->set_text(OUString());
            break;
        case DbGridControlNavigationBarState::Text:
            pWnd = m_aRecordText.get();
            pWnd = m_xRecordText.get();
            break;
        case DbGridControlNavigationBarState::Of:
            pWnd = m_aRecordOf.get();
            pWnd = m_xRecordOf.get();
            break;
        case DbGridControlNavigationBarState::Count:
        {
            pWnd = m_aRecordCount.get();
            pWnd = m_xRecordCount.get();
            OUString aText;
            if (bAvailable)
            {
@@ -702,92 +611,30 @@ void DbGridControl::NavigationBar::SetState(DbGridControlNavigationBarState nWhi
            {
                OUString aExtendedInfo = aText + " (" +
                    OUString::number(pParent->GetSelectRowCount()) + ")";
                pWnd->SetText(aExtendedInfo);
                m_xRecordCount->set_label(aExtendedInfo);
            }
            else
                pWnd->SetText(aText);
                m_xRecordCount->set_label(aText);

            pParent->SetRealRowCount(aText);
        }   break;
        default: break;
    }
    DBG_ASSERT(pWnd, "no window");
    if (pWnd && (pWnd->IsEnabled() != bAvailable))
    if (pWnd && (pWnd->get_sensitive() != bAvailable))
    {
        // this "pWnd->IsEnabled() != bAvailable" is a little hack : Window::Enable always generates a user
        // event (ImplGenerateMouseMove) even if nothing happened. This may lead to some unwanted effects, so we
        // do this check.
        // For further explanation see Bug 69900.
        pWnd->Enable(bAvailable);
}

void DbGridControl::NavigationBar::Resize()
{
    Control::Resize();
    ArrangeControls();
}

void DbGridControl::NavigationBar::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
{
    Control::Paint(rRenderContext, rRect);
    Point aAbsolutePos = m_aAbsolute->GetPosPixel();
    Size  aAbsoluteSize = m_aAbsolute->GetSizePixel();

    rRenderContext.DrawLine(Point(aAbsolutePos.X() - 1, 0 ),
                            Point(aAbsolutePos.X() - 1, aAbsolutePos.Y() + aAbsoluteSize.Height()));

    rRenderContext.DrawLine(Point(aAbsolutePos.X() + aAbsoluteSize.Width() + 1, 0 ),
                            Point(aAbsolutePos.X() + aAbsoluteSize.Width() + 1, aAbsolutePos.Y() + aAbsoluteSize.Height()));
}

void DbGridControl::NavigationBar::StateChanged(StateChangedType nType)
{
    Control::StateChanged(nType);

    vcl::Window* pWindows[] =
    {
        m_aRecordText.get(),
        m_aAbsolute.get(),
        m_aRecordOf.get(),
        m_aRecordCount.get(),
        m_aFirstBtn.get(),
        m_aPrevBtn.get(),
        m_aNextBtn.get(),
        m_aLastBtn.get(),
        m_aNewBtn.get()
    };

    switch ( nType )
    {
        case StateChangedType::Mirroring:
        pWnd->set_sensitive(bAvailable);
        if (!bAvailable)
        {
            bool bIsRTLEnabled = IsRTLEnabled();
            for (vcl::Window* pWindow : pWindows)
                pWindow->EnableRTL( bIsRTLEnabled );
            if (pWnd == m_xNextBtn.get())
                m_aNextRepeat.Stop();
            else if (pWnd == m_xPrevBtn.get())
                m_aPrevRepeat.Stop();
        }
        break;

        case StateChangedType::Zoom:
        {
            Fraction aZoom = GetZoom();

            // not all of these controls need to know the new zoom, but to be sure ...
            vcl::Font aFont(GetSettings().GetStyleSettings().GetToolFont());
            if (IsControlFont())
                aFont.Merge(GetControlFont());

            for (vcl::Window* pWindow : pWindows)
            {
                pWindow->SetZoom(aZoom);
                pWindow->SetZoomedPointFont(*pWindow, aFont);
            }

            SetZoomedPointFont(*this, aFont);

            // rearrange the controls
            ArrangeControls();
        }
        break;
        default:;
    }
}

@@ -898,7 +745,7 @@ DbGridControl::DbGridControl(
                WinBits nBits)
            :EditBrowseBox(pParent, EditBrowseBoxFlags::NONE, nBits, DEFAULT_BROWSE_MODE )
            ,m_xContext(_rxContext)
            ,m_aBar(VclPtr<DbGridControl::NavigationBar>::Create(this))
            ,m_aBar(VclPtr<NavigationBar>::Create(this))
            ,m_nAsynAdjustEvent(nullptr)
            ,m_pDataSourcePropListener(nullptr)
            ,m_pFieldListeners(nullptr)
diff --git a/svx/uiconfig/ui/navigationbar.ui b/svx/uiconfig/ui/navigationbar.ui
new file mode 100644
index 0000000..ede3307
--- /dev/null
+++ b/svx/uiconfig/ui/navigationbar.ui
@@ -0,0 +1,224 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.36.0 -->
<interface domain="dba">
  <requires lib="gtk+" version="3.18"/>
  <object class="GtkImage" id="image1">
    <property name="visible">True</property>
    <property name="can_focus">False</property>
    <property name="stock">gtk-goto-first</property>
    <property name="icon_size">1</property>
  </object>
  <object class="GtkImage" id="image2">
    <property name="visible">True</property>
    <property name="can_focus">False</property>
    <property name="stock">gtk-media-previous</property>
    <property name="icon_size">1</property>
  </object>
  <object class="GtkImage" id="image3">
    <property name="visible">True</property>
    <property name="can_focus">False</property>
    <property name="stock">gtk-media-next</property>
    <property name="icon_size">1</property>
  </object>
  <object class="GtkImage" id="image4">
    <property name="visible">True</property>
    <property name="can_focus">False</property>
    <property name="stock">gtk-goto-last</property>
    <property name="icon_size">1</property>
  </object>
  <object class="GtkImage" id="image5">
    <property name="visible">True</property>
    <property name="can_focus">False</property>
    <property name="stock">gtk-new</property>
    <property name="icon_size">1</property>
  </object>
  <object class="GtkBox" id="NavigationBar">
    <property name="visible">True</property>
    <property name="can_focus">False</property>
    <property name="hexpand">True</property>
    <property name="vexpand">True</property>
    <child>
      <object class="GtkLabel" id="recordtext">
        <property name="visible">True</property>
        <property name="sensitive">False</property>
        <property name="can_focus">False</property>
      </object>
      <packing>
        <property name="expand">False</property>
        <property name="fill">True</property>
        <property name="position">0</property>
      </packing>
    </child>
    <child>
      <object class="GtkSeparator">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="orientation">vertical</property>
      </object>
      <packing>
        <property name="expand">False</property>
        <property name="fill">True</property>
        <property name="position">1</property>
      </packing>
    </child>
    <child>
      <object class="GtkEntry" id="entry-noframe">
        <property name="visible">True</property>
        <property name="sensitive">False</property>
        <property name="can_focus">True</property>
        <property name="hexpand">True</property>
        <property name="vexpand">True</property>
        <property name="has_frame">False</property>
        <property name="width_chars">4</property>
        <property name="xalign">0.5</property>
        <property name="shadow_type">none</property>
      </object>
      <packing>
        <property name="expand">False</property>
        <property name="fill">True</property>
        <property name="position">2</property>
      </packing>
    </child>
    <child>
      <object class="GtkSeparator">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="orientation">vertical</property>
      </object>
      <packing>
        <property name="expand">False</property>
        <property name="fill">True</property>
        <property name="position">3</property>
      </packing>
    </child>
    <child>
      <object class="GtkLabel" id="recordof">
        <property name="visible">True</property>
        <property name="sensitive">False</property>
        <property name="can_focus">False</property>
        <property name="margin_left">3</property>
        <property name="margin_right">3</property>
      </object>
      <packing>
        <property name="expand">False</property>
        <property name="fill">True</property>
        <property name="position">4</property>
      </packing>
    </child>
    <child>
      <object class="GtkLabel" id="recordcount">
        <property name="visible">True</property>
        <property name="sensitive">False</property>
        <property name="can_focus">False</property>
        <property name="xalign">0</property>
      </object>
      <packing>
        <property name="expand">False</property>
        <property name="fill">True</property>
        <property name="position">5</property>
      </packing>
    </child>
    <child>
      <object class="GtkButton" id="first">
        <property name="visible">True</property>
        <property name="sensitive">False</property>
        <property name="can_focus">True</property>
        <property name="focus_on_click">False</property>
        <property name="receives_default">True</property>
        <property name="tooltip_text" translatable="yes" context="navigationbar|first">First</property>
        <property name="image">image1</property>
        <property name="always_show_image">True</property>
        <style>
          <class name="small-button"/>
        </style>
      </object>
      <packing>
        <property name="expand">False</property>
        <property name="fill">True</property>
        <property name="position">6</property>
      </packing>
    </child>
    <child>
      <object class="GtkButton" id="prev">
        <property name="visible">True</property>
        <property name="sensitive">False</property>
        <property name="can_focus">True</property>
        <property name="focus_on_click">False</property>
        <property name="receives_default">True</property>
        <property name="events">GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property>
        <property name="tooltip_text" translatable="yes" context="navigationbar|prev">Previous</property>
        <property name="image">image2</property>
        <property name="always_show_image">True</property>
        <style>
          <class name="small-button"/>
        </style>
      </object>
      <packing>
        <property name="expand">False</property>
        <property name="fill">True</property>
        <property name="position">7</property>
      </packing>
    </child>
    <child>
      <object class="GtkButton" id="next">
        <property name="visible">True</property>
        <property name="sensitive">False</property>
        <property name="can_focus">True</property>
        <property name="focus_on_click">False</property>
        <property name="receives_default">True</property>
        <property name="events">GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property>
        <property name="tooltip_text" translatable="yes" context="navigationbar|next">Next</property>
        <property name="image">image3</property>
        <property name="always_show_image">True</property>
        <style>
          <class name="small-button"/>
        </style>
      </object>
      <packing>
        <property name="expand">False</property>
        <property name="fill">True</property>
        <property name="position">8</property>
      </packing>
    </child>
    <child>
      <object class="GtkButton" id="last">
        <property name="visible">True</property>
        <property name="sensitive">False</property>
        <property name="can_focus">True</property>
        <property name="focus_on_click">False</property>
        <property name="receives_default">True</property>
        <property name="tooltip_text" translatable="yes" context="navigationbar|last">Last</property>
        <property name="image">image4</property>
        <property name="always_show_image">True</property>
        <style>
          <class name="small-button"/>
        </style>
      </object>
      <packing>
        <property name="expand">False</property>
        <property name="fill">True</property>
        <property name="position">9</property>
      </packing>
    </child>
    <child>
      <object class="GtkButton" id="new">
        <property name="visible">True</property>
        <property name="sensitive">False</property>
        <property name="can_focus">True</property>
        <property name="focus_on_click">False</property>
        <property name="receives_default">True</property>
        <property name="tooltip_text" translatable="yes" context="navigationbar|new">New</property>
        <property name="image">image5</property>
        <property name="always_show_image">True</property>
        <style>
          <class name="small-button"/>
        </style>
      </object>
      <packing>
        <property name="expand">False</property>
        <property name="fill">True</property>
        <property name="position">10</property>
      </packing>
    </child>
  </object>
</interface>