mailmerge: Toolbar edit box to show or change the current entry number.

Change-Id: I935c059da44f2309c3cb1a8b2e93341c353bee01
diff --git a/officecfg/registry/data/org/openoffice/Office/UI/Controller.xcu b/officecfg/registry/data/org/openoffice/Office/UI/Controller.xcu
index f9c0f23..6de8c28 100644
--- a/officecfg/registry/data/org/openoffice/Office/UI/Controller.xcu
+++ b/officecfg/registry/data/org/openoffice/Office/UI/Controller.xcu
@@ -911,6 +911,17 @@
          <value>starshapes;.uno:StarShapes.star5</value>
        </prop>
      </node>
      <node oor:name="lo.writer.MMCurrentEntryController" oor:op="replace">
        <prop oor:name="Command">
          <value>.uno:MailMergeCurrentEntry</value>
        </prop>
        <prop oor:name="Module">
          <value/>
        </prop>
        <prop oor:name="Controller">
          <value>lo.writer.MMCurrentEntryController</value>
        </prop>
      </node>
      <node oor:name="lo.writer.MMExcludeEntryController" oor:op="replace">
        <prop oor:name="Command">
          <value>.uno:MailMergeExcludeEntry</value>
diff --git a/sw/inc/cmdid.h b/sw/inc/cmdid.h
index 0bb0cd4..bbb953e 100644
--- a/sw/inc/cmdid.h
+++ b/sw/inc/cmdid.h
@@ -256,6 +256,7 @@
#define FN_MAILMERGE_PREV_ENTRY (FN_INSERT + 71)    /* mail merge toolbar - go to the previous entry */
#define FN_MAILMERGE_NEXT_ENTRY (FN_INSERT + 72)    /* mail merge toolbar - go to the next entry */
#define FN_MAILMERGE_LAST_ENTRY (FN_INSERT + 73)    /* mail merge toolbar - go to the next entry */
#define FN_MAILMERGE_CURRENT_ENTRY (FN_INSERT + 74) /* mail merge toolbar - show or change the current entry */
#define FN_MAILMERGE_EXCLUDE_ENTRY (FN_INSERT + 75) /* mail merge toolbar - checkbox to exclude the current entry */

#define FN_DRAWTEXT_ATTR_DLG    (FN_INSERT + 76)    /* position DrawText */
diff --git a/sw/sdi/swriter.sdi b/sw/sdi/swriter.sdi
index 7bc5b86..3a8e315 100644
--- a/sw/sdi/swriter.sdi
+++ b/sw/sdi/swriter.sdi
@@ -3841,6 +3841,23 @@ SfxVoidItem MailMergeLastEntry FN_MAILMERGE_LAST_ENTRY
    GroupId = GID_DOCUMENT;
]

SfxVoidItem MailMergeCurrentEntry FN_MAILMERGE_CURRENT_ENTRY
()
[
    AutoUpdate = TRUE,
    FastCall = TRUE,
    ReadOnlyDoc = FALSE,
    Toggle = FALSE,
    Container = TRUE,
    RecordAbsolute = FALSE,
    RecordPerSet;

    AccelConfig = TRUE,
    MenuConfig = TRUE,
    ToolBoxConfig = TRUE,
    GroupId = GID_DOCUMENT;
]

SfxVoidItem MailMergeExcludeEntry FN_MAILMERGE_EXCLUDE_ENTRY
()
[
diff --git a/sw/sdi/wrtapp.sdi b/sw/sdi/wrtapp.sdi
index 6ead728..c13ee75 100644
--- a/sw/sdi/wrtapp.sdi
+++ b/sw/sdi/wrtapp.sdi
@@ -86,6 +86,12 @@ interface StarWriter
        StateMethod = StateOther ;
    ]

    FN_MAILMERGE_CURRENT_ENTRY
    [
        ExecMethod = ExecOther ;
        StateMethod = StateOther ;
    ]

    FN_MAILMERGE_EXCLUDE_ENTRY
    [
        StateMethod = StateOther ;
diff --git a/sw/source/uibase/app/apphdl.cxx b/sw/source/uibase/app/apphdl.cxx
index 575ddc3..e99dcc8 100644
--- a/sw/source/uibase/app/apphdl.cxx
+++ b/sw/source/uibase/app/apphdl.cxx
@@ -225,9 +225,11 @@ void SwModule::StateOther(SfxItemSet &rSet)
                }
            }
            break;
            case FN_MAILMERGE_CURRENT_ENTRY:
            case FN_MAILMERGE_EXCLUDE_ENTRY:
            {
                // just trigger calling statusChanged() of MMExcludeEntryController
                // resp. MMCurrentEntryController
                rSet.InvalidateItem(nWhich);
            }
            break;
@@ -751,6 +753,7 @@ void SwModule::ExecOther(SfxRequest& rReq)
        case FN_MAILMERGE_PREV_ENTRY:
        case FN_MAILMERGE_NEXT_ENTRY:
        case FN_MAILMERGE_LAST_ENTRY:
        case FN_MAILMERGE_CURRENT_ENTRY:
        {
            SwView* pView = ::GetActiveView();
            SwMailMergeConfigItem* pConfigItem = pView->GetMailMergeConfigItem();
@@ -764,6 +767,7 @@ void SwModule::ExecOther(SfxRequest& rReq)
                case FN_MAILMERGE_PREV_ENTRY:  pConfigItem->MoveResultSet(nPos - 1); break;
                case FN_MAILMERGE_NEXT_ENTRY:  pConfigItem->MoveResultSet(nPos + 1); break;
                case FN_MAILMERGE_LAST_ENTRY:  pConfigItem->MoveResultSet(-1); break;
                case FN_MAILMERGE_CURRENT_ENTRY: /* don't move the result set, just update the document */ break;
                default: break;
            }

@@ -790,6 +794,7 @@ void SwModule::ExecOther(SfxRequest& rReq)
            rBindings.Invalidate(FN_MAILMERGE_PREV_ENTRY);
            rBindings.Invalidate(FN_MAILMERGE_NEXT_ENTRY);
            rBindings.Invalidate(FN_MAILMERGE_LAST_ENTRY);
            rBindings.Invalidate(FN_MAILMERGE_CURRENT_ENTRY);
            rBindings.Invalidate(FN_MAILMERGE_EXCLUDE_ENTRY);
            rBindings.Update();
        }
diff --git a/sw/source/uibase/dbui/mailmergetoolbarcontrols.cxx b/sw/source/uibase/dbui/mailmergetoolbarcontrols.cxx
index d4dacfb..749d65f 100644
--- a/sw/source/uibase/dbui/mailmergetoolbarcontrols.cxx
+++ b/sw/source/uibase/dbui/mailmergetoolbarcontrols.cxx
@@ -36,6 +36,74 @@ using namespace css;

namespace {

/// Controller for .uno:MailMergeCurrentEntry toolbar checkbox: creates the checkbox & handles the value.
class MMCurrentEntryController : public svt::ToolboxController, public lang::XServiceInfo
{
    VclPtr<Edit> m_pCurrentEdit;

    DECL_LINK_TYPED(CurrentEditUpdatedHdl, Edit&, void);

public:
    MMCurrentEntryController(const uno::Reference<uno::XComponentContext>& rContext)
        : svt::ToolboxController(rContext, uno::Reference<frame::XFrame>(), OUString(".uno:MailMergeCurrentEntry"))
        , m_pCurrentEdit(nullptr)
    {
    }

    virtual ~MMCurrentEntryController()
    {
    }

    // XInterface
    virtual uno::Any SAL_CALL queryInterface(const uno::Type& aType) throw (uno::RuntimeException, std::exception) override
    {
        uno::Any a(ToolboxController::queryInterface(aType));
        if (a.hasValue())
            return a;

        return ::cppu::queryInterface(aType, static_cast<lang::XServiceInfo*>(this));
    }

    void SAL_CALL acquire() throw ()
    {
        ToolboxController::acquire();
    }

    void SAL_CALL release() throw ()
    {
        ToolboxController::release();
    }

    // XServiceInfo
    virtual OUString SAL_CALL getImplementationName() throw (uno::RuntimeException, std::exception) override
    {
        return OUString("lo.writer.MMCurrentEntryController");
    }

    virtual sal_Bool SAL_CALL supportsService(const OUString& rServiceName) throw (uno::RuntimeException, std::exception) override
    {
        return cppu::supportsService(this, rServiceName);
    }

    virtual uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() throw (uno::RuntimeException, std::exception) override
    {
        uno::Sequence<OUString> aServices { "com.sun.star.frame.ToolbarController" };
        return aServices;
    }

    // XComponent
    virtual void SAL_CALL dispose() throw (uno::RuntimeException, std::exception) override;

    // XInitialization
    virtual void SAL_CALL initialize(const uno::Sequence< uno::Any >& aArguments) throw (uno::Exception, uno::RuntimeException, std::exception) override;

    // XToolbarController
    virtual uno::Reference<awt::XWindow> SAL_CALL createItemWindow(const uno::Reference<awt::XWindow>& rParent) throw (uno::RuntimeException, std::exception) override;

    // XStatusListener
    virtual void SAL_CALL statusChanged(const frame::FeatureStateEvent& rEvent) throw (uno::RuntimeException, std::exception) override;
};

/// Controller for .uno:MailMergeExcludeEntry toolbar checkbox: creates the checkbox & handles the value.
class MMExcludeEntryController : public svt::ToolboxController, public lang::XServiceInfo
{
@@ -104,6 +172,78 @@ public:
    virtual void SAL_CALL statusChanged(const frame::FeatureStateEvent& rEvent) throw (uno::RuntimeException, std::exception) override;
};

void MMCurrentEntryController::dispose() throw (uno::RuntimeException, std::exception)
{
    SolarMutexGuard aSolarMutexGuard;

    svt::ToolboxController::dispose();
    m_pCurrentEdit.disposeAndClear();
}

void MMCurrentEntryController::initialize(const uno::Sequence< uno::Any >& aArguments) throw (uno::Exception, uno::RuntimeException, std::exception)
{
    svt::ToolboxController::initialize(aArguments);
}

uno::Reference<awt::XWindow> MMCurrentEntryController::createItemWindow(const uno::Reference<awt::XWindow>& rParent) throw (uno::RuntimeException, std::exception)
{
    vcl::Window* pParent = VCLUnoHelper::GetWindow(rParent);
    ToolBox* pToolbar = dynamic_cast<ToolBox*>(pParent);
    if (pToolbar)
    {
        // make it visible
        m_pCurrentEdit = VclPtr<Edit>::Create(pToolbar);
        m_pCurrentEdit->SetWidthInChars(4);
        m_pCurrentEdit->SetSizePixel(m_pCurrentEdit->GetOptimalSize());

        m_pCurrentEdit->SetModifyHdl(LINK(this, MMCurrentEntryController, CurrentEditUpdatedHdl));
    }

    return uno::Reference<awt::XWindow>(VCLUnoHelper::GetInterface(m_pCurrentEdit));
}

IMPL_LINK_TYPED(MMCurrentEntryController, CurrentEditUpdatedHdl, Edit&, rEdit, void)
{
    SwView* pView = ::GetActiveView();
    SwMailMergeConfigItem* pConfigItem = pView->GetMailMergeConfigItem();

    if (!pConfigItem)
        return;

    OUString aText(rEdit.GetText());
    sal_Int32 nEntry = aText.toInt32();
    if (!aText.isEmpty() && nEntry != pConfigItem->GetResultSetPosition())
    {
        pConfigItem->MoveResultSet(nEntry);
        // notify about the change
        dispatchCommand(".uno:MailMergeCurrentEntry", uno::Sequence<beans::PropertyValue>());
    }
};

void MMCurrentEntryController::statusChanged(const frame::FeatureStateEvent& rEvent) throw (uno::RuntimeException, std::exception)
{
    if (!m_pCurrentEdit)
        return;

    SwView* pView = ::GetActiveView();
    SwMailMergeConfigItem* pConfigItem = pView->GetMailMergeConfigItem();

    if (!pConfigItem || !rEvent.IsEnabled)
    {
        m_pCurrentEdit->Disable();
        m_pCurrentEdit->SetText("");
    }
    else
    {
        sal_Int32 nEntry = m_pCurrentEdit->GetText().toInt32();
        if (!m_pCurrentEdit->IsEnabled() || nEntry != pConfigItem->GetResultSetPosition())
        {
            m_pCurrentEdit->Enable();
            m_pCurrentEdit->SetText(OUString::number(pConfigItem->GetResultSetPosition()));
        }
    }
}

void MMExcludeEntryController::dispose() throw (uno::RuntimeException, std::exception)
{
    SolarMutexGuard aSolarMutexGuard;
@@ -166,6 +306,14 @@ void MMExcludeEntryController::statusChanged(const frame::FeatureStateEvent& rEv
}

extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface * SAL_CALL
lo_writer_MMCurrentEntryController_get_implementation(
    uno::XComponentContext *context,
    uno::Sequence<uno::Any> const &)
{
    return cppu::acquire(new MMCurrentEntryController(context));
}

extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface * SAL_CALL
lo_writer_MMExcludeEntryController_get_implementation(
    uno::XComponentContext *context,
    uno::Sequence<uno::Any> const &)
diff --git a/sw/uiconfig/swform/toolbar/mailmerge.xml b/sw/uiconfig/swform/toolbar/mailmerge.xml
index 61cca36..ff9773d 100644
--- a/sw/uiconfig/swform/toolbar/mailmerge.xml
+++ b/sw/uiconfig/swform/toolbar/mailmerge.xml
@@ -13,6 +13,7 @@
  <toolbar:toolbarseparator/>
  <toolbar:toolbaritem xlink:href=".uno:MailMergeFirstEntry"/>
  <toolbar:toolbaritem xlink:href=".uno:MailMergePrevEntry"/>
  <toolbar:toolbaritem xlink:href=".uno:MailMergeCurrentEntry"/>
  <toolbar:toolbaritem xlink:href=".uno:MailMergeNextEntry"/>
  <toolbar:toolbaritem xlink:href=".uno:MailMergeLastEntry"/>
  <toolbar:toolbaritem xlink:href=".uno:MailMergeExcludeEntry"/>
diff --git a/sw/uiconfig/swreport/toolbar/mailmerge.xml b/sw/uiconfig/swreport/toolbar/mailmerge.xml
index 61cca36..ff9773d 100644
--- a/sw/uiconfig/swreport/toolbar/mailmerge.xml
+++ b/sw/uiconfig/swreport/toolbar/mailmerge.xml
@@ -13,6 +13,7 @@
  <toolbar:toolbarseparator/>
  <toolbar:toolbaritem xlink:href=".uno:MailMergeFirstEntry"/>
  <toolbar:toolbaritem xlink:href=".uno:MailMergePrevEntry"/>
  <toolbar:toolbaritem xlink:href=".uno:MailMergeCurrentEntry"/>
  <toolbar:toolbaritem xlink:href=".uno:MailMergeNextEntry"/>
  <toolbar:toolbaritem xlink:href=".uno:MailMergeLastEntry"/>
  <toolbar:toolbaritem xlink:href=".uno:MailMergeExcludeEntry"/>
diff --git a/sw/uiconfig/swriter/toolbar/mailmerge.xml b/sw/uiconfig/swriter/toolbar/mailmerge.xml
index 61cca36..ff9773d 100644
--- a/sw/uiconfig/swriter/toolbar/mailmerge.xml
+++ b/sw/uiconfig/swriter/toolbar/mailmerge.xml
@@ -13,6 +13,7 @@
  <toolbar:toolbarseparator/>
  <toolbar:toolbaritem xlink:href=".uno:MailMergeFirstEntry"/>
  <toolbar:toolbaritem xlink:href=".uno:MailMergePrevEntry"/>
  <toolbar:toolbaritem xlink:href=".uno:MailMergeCurrentEntry"/>
  <toolbar:toolbaritem xlink:href=".uno:MailMergeNextEntry"/>
  <toolbar:toolbaritem xlink:href=".uno:MailMergeLastEntry"/>
  <toolbar:toolbaritem xlink:href=".uno:MailMergeExcludeEntry"/>
diff --git a/sw/uiconfig/swxform/toolbar/mailmerge.xml b/sw/uiconfig/swxform/toolbar/mailmerge.xml
index 61cca36..ff9773d 100644
--- a/sw/uiconfig/swxform/toolbar/mailmerge.xml
+++ b/sw/uiconfig/swxform/toolbar/mailmerge.xml
@@ -13,6 +13,7 @@
  <toolbar:toolbarseparator/>
  <toolbar:toolbaritem xlink:href=".uno:MailMergeFirstEntry"/>
  <toolbar:toolbaritem xlink:href=".uno:MailMergePrevEntry"/>
  <toolbar:toolbaritem xlink:href=".uno:MailMergeCurrentEntry"/>
  <toolbar:toolbaritem xlink:href=".uno:MailMergeNextEntry"/>
  <toolbar:toolbaritem xlink:href=".uno:MailMergeLastEntry"/>
  <toolbar:toolbaritem xlink:href=".uno:MailMergeExcludeEntry"/>
diff --git a/sw/util/sw.component b/sw/util/sw.component
index ff6b032..c069d63 100644
--- a/sw/util/sw.component
+++ b/sw/util/sw.component
@@ -27,6 +27,10 @@
    <service name="com.sun.star.sdb.DataAccessDescriptor"/>
    <service name="com.sun.star.text.MailMerge"/>
  </implementation>
  <implementation name="lo.writer.MMCurrentEntryController"
      constructor="lo_writer_MMCurrentEntryController_get_implementation">
    <service name="com.sun.star.frame.ToolbarController"/>
  </implementation>
  <implementation name="lo.writer.MMExcludeEntryController"
      constructor="lo_writer_MMExcludeEntryController_get_implementation">
    <service name="com.sun.star.frame.ToolbarController"/>