diff options
author | Caolán McNamara <caolanm@redhat.com> | 2019-04-09 11:23:48 +0100 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2019-04-10 21:23:21 +0200 |
commit | 3d648f76ac90fe8e28691313d0d4e78a8278e511 (patch) | |
tree | f3e0de959d8ddff61a9ff4af79e481bec25aa29d | |
parent | 47500ab25b9c5bbeeb6fde3866bdd924948fd88a (diff) |
weld ScCorrelationDialog
this is first of the calc dialogs with a range selector, so some temp
scaffolding is required during interim case of both welded/unwelded
in existence
Change-Id: I5480179092da7b56864cef066af781b35f735ebc
Reviewed-on: https://gerrit.libreoffice.org/70474
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
31 files changed, 1498 insertions, 87 deletions
diff --git a/formula/source/ui/dlg/formula.cxx b/formula/source/ui/dlg/formula.cxx index 68120f6bbd51..e7c5fede138d 100644 --- a/formula/source/ui/dlg/formula.cxx +++ b/formula/source/ui/dlg/formula.cxx @@ -77,6 +77,8 @@ class FormulaDlg_Impl public: ::std::pair<RefButton*, RefEdit*> RefInputStartBefore( RefEdit* pEdit, RefButton* pButton ); + static ::std::pair<WeldRefButton*, WeldRefEdit*> + RefInputStartBefore( WeldRefEdit* pEdit, WeldRefButton* pButton ); void RefInputStartAfter(); void RefInputDoneAfter( bool bForced ); bool CalcValue( const OUString& rStrExp, OUString& rStrResult, bool bForceMatrixFormula = false ); @@ -1522,6 +1524,15 @@ void FormulaDlg_Impl::UpdateSelection() return aPair; } +::std::pair<WeldRefButton*, WeldRefEdit*> FormulaDlg_Impl::RefInputStartBefore( WeldRefEdit* pEdit, WeldRefButton* pButton ) +{ + assert(!pEdit && !pButton); + ::std::pair<WeldRefButton*, WeldRefEdit*> aPair; + aPair.first = pButton; + aPair.second = pEdit; + return aPair; +} + void FormulaDlg_Impl::RefInputStartAfter() { m_pRefBtn->SetEndImage(); @@ -1779,6 +1790,11 @@ void FormulaModalDialog::Update() return m_pImpl->RefInputStartBefore( pEdit, pButton ); } +::std::pair<WeldRefButton*, WeldRefEdit*> FormulaModalDialog::RefInputStartBefore( WeldRefEdit* pEdit, WeldRefButton* pButton ) +{ + return formula::FormulaDlg_Impl::RefInputStartBefore(pEdit, pButton); +} + void FormulaModalDialog::RefInputStartAfter() { m_pImpl->RefInputStartAfter(); @@ -1868,6 +1884,11 @@ void FormulaDlg::DoEnter() return m_pImpl->RefInputStartBefore( pEdit, pButton ); } +::std::pair<WeldRefButton*, WeldRefEdit*> FormulaDlg::RefInputStartBefore( WeldRefEdit* pEdit, WeldRefButton* pButton ) +{ + return formula::FormulaDlg_Impl::RefInputStartBefore(pEdit, pButton); +} + void FormulaDlg::RefInputStartAfter() { m_pImpl->RefInputStartAfter(); diff --git a/formula/source/ui/dlg/funcutl.cxx b/formula/source/ui/dlg/funcutl.cxx index 9499992b6b7e..47c3d408d63e 100644 --- a/formula/source/ui/dlg/funcutl.cxx +++ b/formula/source/ui/dlg/funcutl.cxx @@ -517,6 +517,112 @@ IMPL_LINK_NOARG(RefEdit, UpdateHdl, Timer *, void) pAnyRefDlg->ShowReference( GetText() ); } +// class RefEdit + +WeldRefEdit::WeldRefEdit(std::unique_ptr<weld::Entry> xControl) + : xEntry(std::move(xControl)) + , aIdle("formula RefEdit Idle") + , pAnyRefDlg(nullptr) + , pLabelWidget(nullptr) +{ + xEntry->connect_focus_in(LINK(this, WeldRefEdit, GetFocus)); + xEntry->connect_focus_out(LINK(this, WeldRefEdit, LoseFocus)); + xEntry->connect_key_press(LINK(this, WeldRefEdit, KeyInput)); + xEntry->connect_changed(LINK(this, WeldRefEdit, Modify)); + aIdle.SetInvokeHandler( LINK( this, WeldRefEdit, UpdateHdl ) ); +} + +WeldRefEdit::~WeldRefEdit() +{ + aIdle.ClearInvokeHandler(); + aIdle.Stop(); +} + +void WeldRefEdit::SetRefString( const OUString& rStr ) +{ + // Prevent unwanted side effects by setting only a differing string. + // See commit message for reasons. + if (xEntry->get_text() != rStr) + xEntry->set_text(rStr); +} + +void WeldRefEdit::SetRefValid(bool bValid) +{ + xEntry->set_error(!bValid); +} + +void WeldRefEdit::SetText(const OUString& rStr) +{ + xEntry->set_text(rStr); + UpdateHdl( &aIdle ); +} + +void WeldRefEdit::StartUpdateData() +{ + aIdle.Start(); +} + +void WeldRefEdit::SetReferences(IControlReferenceHandler* pDlg, weld::Label* pLabel) +{ + pAnyRefDlg = pDlg; + pLabelWidget = pLabel; + + if( pDlg ) + { + aIdle.SetInvokeHandler(LINK(this, WeldRefEdit, UpdateHdl)); + } + else + { + aIdle.ClearInvokeHandler(); + aIdle.Stop(); + } +} + +IMPL_LINK_NOARG(WeldRefEdit, Modify, weld::Entry&, void) +{ + maModifyHdl.Call(*this); + if (pAnyRefDlg) + pAnyRefDlg->HideReference(); +} + +IMPL_LINK(WeldRefEdit, KeyInput, const KeyEvent&, rKEvt, bool) +{ + const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode(); + if (pAnyRefDlg && !rKeyCode.GetModifier() && rKeyCode.GetCode() == KEY_F2) + { + pAnyRefDlg->ReleaseFocus( this ); + return true; + } + + switch (rKeyCode.GetCode()) + { + case KEY_RETURN: + case KEY_ESCAPE: + return maActivateHdl.Call(*GetWidget()); + } + + return false; +} + +IMPL_LINK_NOARG(WeldRefEdit, GetFocus, weld::Widget&, void) +{ + maGetFocusHdl.Call(*this); + StartUpdateData(); +} + +IMPL_LINK_NOARG(WeldRefEdit, LoseFocus, weld::Widget&, void) +{ + maLoseFocusHdl.Call(*this); + if( pAnyRefDlg ) + pAnyRefDlg->HideReference(); +} + +IMPL_LINK_NOARG(WeldRefEdit, UpdateHdl, Timer *, void) +{ + if( pAnyRefDlg ) + pAnyRefDlg->ShowReference(xEntry->get_text()); +} + //class RefButton RefButton::RefButton( vcl::Window* _pParent, WinBits nStyle ) : ImageButton(_pParent, nStyle), @@ -590,6 +696,80 @@ void RefButton::LoseFocus() pRefEdit->Modify(); } +//class RefButton +WeldRefButton::WeldRefButton(std::unique_ptr<weld::Button> xControl) + : xButton(std::move(xControl)) + , pAnyRefDlg( nullptr ) + , pRefEdit( nullptr ) +{ + xButton->connect_focus_in(LINK(this, WeldRefButton, GetFocus)); + xButton->connect_focus_out(LINK(this, WeldRefButton, LoseFocus)); + xButton->connect_key_press(LINK(this, WeldRefButton, KeyInput)); + xButton->connect_clicked(LINK(this, WeldRefButton, Click)); + SetStartImage(); +} + +WeldRefButton::~WeldRefButton() +{ +} + +void WeldRefButton::SetStartImage() +{ + xButton->set_from_icon_name(RID_BMP_REFBTN1); + xButton->set_tooltip_text(ForResId(RID_STR_SHRINK)); +} + +void WeldRefButton::SetEndImage() +{ + xButton->set_from_icon_name(RID_BMP_REFBTN2); + xButton->set_tooltip_text(ForResId(RID_STR_EXPAND)); +} + +void WeldRefButton::SetReferences( IControlReferenceHandler* pDlg, WeldRefEdit* pEdit ) +{ + pAnyRefDlg = pDlg; + pRefEdit = pEdit; +} + +IMPL_LINK_NOARG(WeldRefButton, Click, weld::Button&, void) +{ + if( pAnyRefDlg ) + pAnyRefDlg->ToggleCollapsed( pRefEdit, this ); +} + +IMPL_LINK(WeldRefButton, KeyInput, const KeyEvent&, rKEvt, bool) +{ + const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode(); + if (pAnyRefDlg && !rKeyCode.GetModifier() && rKeyCode.GetCode() == KEY_F2) + { + pAnyRefDlg->ReleaseFocus( pRefEdit ); + return true; + } + + switch (rKeyCode.GetCode()) + { + case KEY_RETURN: + case KEY_ESCAPE: + return maActivateHdl.Call(*GetWidget()); + } + + return false; +} + +IMPL_LINK_NOARG(WeldRefButton, GetFocus, weld::Widget&, void) +{ + maGetFocusHdl.Call(*this); + if (pRefEdit) + pRefEdit->StartUpdateData(); +} + +IMPL_LINK_NOARG(WeldRefButton, LoseFocus, weld::Widget&, void) +{ + maLoseFocusHdl.Call(*this); + if (pRefEdit) + pRefEdit->DoModify(); +} + } // formula /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/formula/IControlReferenceHandler.hxx b/include/formula/IControlReferenceHandler.hxx index e1096c47ae38..f73a7618d346 100644 --- a/include/formula/IControlReferenceHandler.hxx +++ b/include/formula/IControlReferenceHandler.hxx @@ -26,14 +26,18 @@ namespace formula { class RefEdit; + class WeldRefEdit; class RefButton; + class WeldRefButton; class FORMULA_DLLPUBLIC SAL_NO_VTABLE IControlReferenceHandler { public: virtual void ShowReference(const OUString& _sRef) = 0; virtual void HideReference( bool bDoneRefMode = true ) = 0; virtual void ReleaseFocus( RefEdit* pEdit ) = 0; + virtual void ReleaseFocus( WeldRefEdit* pEdit ) = 0; virtual void ToggleCollapsed( RefEdit* pEdit, RefButton* pButton ) = 0; + virtual void ToggleCollapsed( WeldRefEdit* pEdit, WeldRefButton* pButton ) = 0; protected: ~IControlReferenceHandler() {} diff --git a/include/formula/formula.hxx b/include/formula/formula.hxx index 201a598891e4..defd1ecfd1a8 100644 --- a/include/formula/formula.hxx +++ b/include/formula/formula.hxx @@ -56,7 +56,9 @@ class FormulaDlg_Impl; class IControlReferenceHandler; class FormulaHelper; class RefEdit; +class WeldRefEdit; class RefButton; +class WeldRefButton; class FormEditData; class FORMULA_DLLPUBLIC FormulaModalDialog : public ModalDialog, public formula::IFormulaEditorHelper @@ -76,6 +78,7 @@ protected: virtual bool PreNotify( NotifyEvent& rNEvt ) override; ::std::pair<RefButton*,RefEdit*> RefInputStartBefore( RefEdit* pEdit, RefButton* pButton ); + static ::std::pair<WeldRefButton*,WeldRefEdit*> RefInputStartBefore( WeldRefEdit* pEdit, WeldRefButton* pButton ); void RefInputStartAfter(); void RefInputDoneAfter(); @@ -110,6 +113,7 @@ protected: virtual bool PreNotify( NotifyEvent& rNEvt ) override; ::std::pair<RefButton*,RefEdit*> RefInputStartBefore( RefEdit* pEdit, RefButton* pButton ); + static ::std::pair<WeldRefButton*,WeldRefEdit*> RefInputStartBefore( WeldRefEdit* pEdit, WeldRefButton* pButton ); void RefInputStartAfter(); void RefInputDoneAfter( bool bForced ); diff --git a/include/formula/funcutl.hxx b/include/formula/funcutl.hxx index 0a4c25d1236c..5a6c095db77e 100644 --- a/include/formula/funcutl.hxx +++ b/include/formula/funcutl.hxx @@ -28,6 +28,7 @@ #include <vcl/edit.hxx> #include <vcl/idle.hxx> #include <vcl/image.hxx> +#include <vcl/weld.hxx> #include <vcl/vclptr.hxx> class KeyEvent; @@ -83,6 +84,74 @@ public: } }; +class FORMULA_DLLPUBLIC WeldRefEdit +{ +private: + std::unique_ptr<weld::Entry> xEntry; + Idle aIdle; + IControlReferenceHandler* pAnyRefDlg; // parent dialog + weld::Label* pLabelWidget; + Link<WeldRefEdit&,void> maGetFocusHdl; + Link<WeldRefEdit&,void> maLoseFocusHdl; + Link<WeldRefEdit&,void> maModifyHdl; + Link<weld::Widget&,bool> maActivateHdl; + + DECL_LINK( UpdateHdl, Timer*, void ); + +protected: + DECL_LINK(KeyInput, const KeyEvent&, bool); + DECL_LINK(GetFocus, weld::Widget&, void); + DECL_LINK(LoseFocus, weld::Widget&, void); + DECL_LINK(Modify, weld::Entry&, void); + +public: + WeldRefEdit(std::unique_ptr<weld::Entry> xControl); + weld::Widget* GetWidget() const { return xEntry.get(); } + ~WeldRefEdit(); + + void SetRefString( const OUString& rStr ); + + /** + * Flag reference valid or invalid, which in turn changes the visual + * appearance of the control accordingly. + */ + void SetRefValid(bool bValid); + + void SetText(const OUString& rStr); + OUString GetText() const + { + return xEntry->get_text(); + } + + void StartUpdateData(); + + void SetReferences( IControlReferenceHandler* pDlg, weld::Label *pLabelWidget ); + + void DoModify() + { + Modify(*xEntry); + } + + void GrabFocus() + { + xEntry->grab_focus(); + } + + void SelectAll() + { + xEntry->select_region(0, -1); + } + + weld::Label* GetLabelWidgetForShrinkMode() + { + return pLabelWidget; + } + + void SetGetFocusHdl(const Link<WeldRefEdit&,void>& rLink) { maGetFocusHdl = rLink; } + void SetLoseFocusHdl(const Link<WeldRefEdit&,void>& rLink) { maLoseFocusHdl = rLink; } + void SetModifyHdl(const Link<WeldRefEdit&,void>& rLink) { maModifyHdl = rLink; } + void SetActivateHdl(const Link<weld::Widget&,bool>& rLink) { maActivateHdl = rLink; } +}; class FORMULA_DLLPUBLIC RefButton : public ImageButton { @@ -113,6 +182,39 @@ public: } }; +class FORMULA_DLLPUBLIC WeldRefButton +{ +private: + std::unique_ptr<weld::Button> xButton; + IControlReferenceHandler* pAnyRefDlg; // parent dialog + WeldRefEdit* pRefEdit; // associated Edit-Control + Link<WeldRefButton&,void> maGetFocusHdl; + Link<WeldRefButton&,void> maLoseFocusHdl; + Link<weld::Widget&,bool> maActivateHdl; + +protected: + DECL_LINK(Click, weld::Button&, void); + DECL_LINK(KeyInput, const KeyEvent&, bool); + DECL_LINK(GetFocus, weld::Widget&, void); + DECL_LINK(LoseFocus, weld::Widget&, void); + +public: + WeldRefButton(std::unique_ptr<weld::Button> xControl); + weld::Widget* GetWidget() const { return xButton.get(); } + ~WeldRefButton(); + void SetReferences(IControlReferenceHandler* pDlg, WeldRefEdit* pEdit); + void SetStartImage(); + void SetEndImage(); + void DoRef() + { + Click(*xButton); + } + void SetGetFocusHdl(const Link<WeldRefButton&,void>& rLink) { maGetFocusHdl = rLink; } + void SetLoseFocusHdl(const Link<WeldRefButton&,void>& rLink) { maLoseFocusHdl = rLink; } + void SetActivateHdl(const Link<weld::Widget&,bool>& rLink) { maActivateHdl = rLink; } +}; + + } // formula #endif // INCLUDED_FORMULA_FUNCUTL_HXX diff --git a/include/sfx2/basedlgs.hxx b/include/sfx2/basedlgs.hxx index 7a29b9f1bd02..6706010c6c51 100644 --- a/include/sfx2/basedlgs.hxx +++ b/include/sfx2/basedlgs.hxx @@ -139,9 +139,10 @@ class SFX2_DLLPUBLIC SfxModelessDialogController : public SfxDialogController protected: SfxModelessDialogController(SfxBindings*, SfxChildWindow* pChildWin, weld::Window* pParent, const OUString& rUIXMLDescription, const OString& rID); - virtual ~SfxModelessDialogController() override; public: + virtual ~SfxModelessDialogController() override; + void Initialize (SfxChildWinInfo const * pInfo); bool IsClosing() const; virtual void Close() override; diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx index 3b2fea407aec..2a7511b419fc 100644 --- a/include/vcl/weld.hxx +++ b/include/vcl/weld.hxx @@ -383,6 +383,11 @@ public: virtual Button* get_widget_for_response(int response) = 0; virtual Container* weld_content_area() = 0; + // shrink the dialog down to shown just these widgets + virtual void collapse(weld::Widget* pEdit, weld::Widget* pButton) = 0; + // undo previous dialog collapse + virtual void undo_collapse() = 0; + virtual void SetInstallLOKNotifierHdl(const Link<void*, vcl::ILibreOfficeKitNotifier*>& rLink) = 0; }; diff --git a/reportdesign/source/ui/dlg/Formula.cxx b/reportdesign/source/ui/dlg/Formula.cxx index 3e3d5f03206f..ac91552c351d 100644 --- a/reportdesign/source/ui/dlg/Formula.cxx +++ b/reportdesign/source/ui/dlg/Formula.cxx @@ -201,6 +201,10 @@ void FormulaDialog::ReleaseFocus( RefEdit* /*pEdit*/) { } +void FormulaDialog::ReleaseFocus( WeldRefEdit* /*pEdit*/) +{ +} + void FormulaDialog::ToggleCollapsed( RefEdit* _pEdit, RefButton* _pButton) { ::std::pair<RefButton*,RefEdit*> aPair = RefInputStartBefore( _pEdit, _pButton ); @@ -228,6 +232,11 @@ void FormulaDialog::ToggleCollapsed( RefEdit* _pEdit, RefButton* _pButton) } +void FormulaDialog::ToggleCollapsed( WeldRefEdit* /*_pEdit*/, WeldRefButton* /*_pButton*/) +{ + assert(false); +} + IMPL_LINK( FormulaDialog, OnClickHdl, OAddFieldWindow& ,_rAddFieldDlg, void) { const uno::Sequence< beans::PropertyValue > aArgs = _rAddFieldDlg.getSelectedFieldDescriptors(); diff --git a/reportdesign/source/ui/inc/Formula.hxx b/reportdesign/source/ui/inc/Formula.hxx index 68c20917af4f..e28438325329 100644 --- a/reportdesign/source/ui/inc/Formula.hxx +++ b/reportdesign/source/ui/inc/Formula.hxx @@ -101,7 +101,9 @@ public: virtual void ShowReference(const OUString& _sRef) override; virtual void HideReference( bool bDoneRefMode = true ) override; virtual void ReleaseFocus( formula::RefEdit* pEdit ) override; + virtual void ReleaseFocus( formula::WeldRefEdit* pEdit ) override; virtual void ToggleCollapsed( formula::RefEdit* pEdit, formula::RefButton* pButton ) override; + virtual void ToggleCollapsed( formula::WeldRefEdit* pEdit, formula::WeldRefButton* pButton ) override; }; diff --git a/sc/inc/scmod.hxx b/sc/inc/scmod.hxx index 883da0ba9be6..2a3fbc04b748 100644 --- a/sc/inc/scmod.hxx +++ b/sc/inc/scmod.hxx @@ -75,6 +75,7 @@ class ScSelectionTransferObj; class ScFormEditData; class ScMarkData; struct ScDragData; +class SfxModelessDialogController; class ScModule: public SfxModule, public SfxListener, public utl::ConfigurationListener { @@ -108,6 +109,7 @@ class ScModule: public SfxModule, public SfxListener, public utl::ConfigurationL bool m_bIsInSharedDocSaving:1; std::map<sal_uInt16, std::vector<VclPtr<vcl::Window> > > m_mapRefWindow; + std::map<sal_uInt16, std::vector<SfxModelessDialogController*>> m_mapRefController; css::uno::Reference< ooo::vba::XSinkCaller > mxAutomationApplicationEventsCaller; @@ -250,6 +252,9 @@ public: SC_DLLPUBLIC void UnregisterRefWindow( sal_uInt16 nSlotId, vcl::Window *pWnd ); SC_DLLPUBLIC vcl::Window * Find1RefWindow( sal_uInt16 nSlotId, vcl::Window *pWndAncestor ); + SC_DLLPUBLIC void RegisterRefController( sal_uInt16 nSlotId, SfxModelessDialogController *pWnd ); + SC_DLLPUBLIC void UnregisterRefController( sal_uInt16 nSlotId, SfxModelessDialogController *pWnd ); + SC_DLLPUBLIC void RegisterAutomationApplicationEventsCaller(css::uno::Reference< ooo::vba::XSinkCaller > const& xCaller); SC_DLLPUBLIC void CallAutomationApplicationEventSinks(const OUString& Method, css::uno::Sequence< css::uno::Any >& Arguments); }; diff --git a/sc/source/ui/StatisticsDialogs/CorrelationDialog.cxx b/sc/source/ui/StatisticsDialogs/CorrelationDialog.cxx index c7a8a7be932e..d1463f608b3d 100644 --- a/sc/source/ui/StatisticsDialogs/CorrelationDialog.cxx +++ b/sc/source/ui/StatisticsDialogs/CorrelationDialog.cxx @@ -15,15 +15,15 @@ ScCorrelationDialog::ScCorrelationDialog( SfxBindings* pSfxBindings, SfxChildWindow* pChildWindow, - vcl::Window* pParent, ScViewData* pViewData ) : - ScMatrixComparisonGenerator( + weld::Window* pParent, ScViewData* pViewData ) : + ScMatrixComparisonGeneratorController( pSfxBindings, pChildWindow, pParent, pViewData, - "CorrelationDialog", "modules/scalc/ui/correlationdialog.ui" ) + "modules/scalc/ui/correlationdialog.ui", "CorrelationDialog") {} -bool ScCorrelationDialog::Close() +void ScCorrelationDialog::Close() { - return DoClose( ScCorrelationDialogWrapper::GetChildWindowId() ); + DoClose(ScCorrelationDialogWrapper::GetChildWindowId()); } const OUString ScCorrelationDialog::getLabel() diff --git a/sc/source/ui/StatisticsDialogs/MatrixComparisonGenerator.cxx b/sc/source/ui/StatisticsDialogs/MatrixComparisonGenerator.cxx index d5aa05933f24..487602fe8a1a 100644 --- a/sc/source/ui/StatisticsDialogs/MatrixComparisonGenerator.cxx +++ b/sc/source/ui/StatisticsDialogs/MatrixComparisonGenerator.cxx @@ -109,4 +109,75 @@ ScRange ScMatrixComparisonGenerator::ApplyOutput(ScDocShell* pDocShell) return ScRange(output.mMinimumAddress, output.mMaximumAddress); } +ScMatrixComparisonGeneratorController::ScMatrixComparisonGeneratorController( + SfxBindings* pSfxBindings, SfxChildWindow* pChildWindow, + weld::Window* pParent, ScViewData* pViewData, + const OUString& rUiXmlDescription, + const OString& rID) + : ScStatisticsInputOutputDialogController(pSfxBindings, pChildWindow, pParent, pViewData, rUiXmlDescription, rID) +{} + +ScMatrixComparisonGeneratorController::~ScMatrixComparisonGeneratorController() +{} + +const char* ScMatrixComparisonGeneratorController::GetUndoNameId() +{ + return STR_CORRELATION_UNDO_NAME; +} + +ScRange ScMatrixComparisonGeneratorController::ApplyOutput(ScDocShell* pDocShell) +{ + AddressWalkerWriter output(mOutputAddress, pDocShell, mDocument, + formula::FormulaGrammar::mergeToGrammar( formula::FormulaGrammar::GRAM_ENGLISH, mAddressDetails.eConv)); + FormulaTemplate aTemplate(mDocument); + + SCTAB inTab = mInputRange.aStart.Tab(); + + ScRangeList aRangeList = (mGroupedBy == BY_COLUMN) ? + MakeColumnRangeList(inTab, mInputRange.aStart, mInputRange.aEnd) : + MakeRowRangeList(inTab, mInputRange.aStart, mInputRange.aEnd); + + // labels + output.writeString(getLabel()); + output.nextColumn(); + + const OUString strWildcardNumber("%NUMBER%"); + + // write labels to columns + for (size_t i = 0; i < aRangeList.size(); i++) + { + if (mGroupedBy == BY_COLUMN) + aTemplate.setTemplate(ScResId(STR_COLUMN_LABEL_TEMPLATE)); + else + aTemplate.setTemplate(ScResId(STR_ROW_LABEL_TEMPLATE)); + + aTemplate.applyNumber(strWildcardNumber, i + 1); + output.writeString(aTemplate.getTemplate()); + output.nextColumn(); + } + + // write labels to rows + output.resetColumn(); + output.nextRow(); + for (size_t i = 0; i < aRangeList.size(); i++) + { + if (mGroupedBy == BY_COLUMN) + aTemplate.setTemplate(ScResId(STR_COLUMN_LABEL_TEMPLATE)); + else + aTemplate.setTemplate(ScResId(STR_ROW_LABEL_TEMPLATE)); + + aTemplate.applyNumber(strWildcardNumber, i + 1); + output.writeString(aTemplate.getTemplate()); + output.nextRow(); + } + + // write correlation formulas + output.reset(); + output.push(1, 1); + + lclWriteCorrelationFormulas(output, aTemplate, aRangeList, getTemplate()); + + return ScRange(output.mMinimumAddress, output.mMaximumAddress); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/StatisticsDialogs/StatisticsInputOutputDialog.cxx b/sc/source/ui/StatisticsDialogs/StatisticsInputOutputDialog.cxx index 8d630ebc7e63..a55e34092edc 100644 --- a/sc/source/ui/StatisticsDialogs/StatisticsInputOutputDialog.cxx +++ b/sc/source/ui/StatisticsDialogs/StatisticsInputOutputDialog.cxx @@ -296,4 +296,281 @@ void ScStatisticsInputOutputDialog::ValidateDialogInput() mpButtonOk->Disable(); } +ScRangeList ScStatisticsInputOutputDialogController::MakeColumnRangeList(SCTAB aTab, ScAddress const & aStart, ScAddress const & aEnd) +{ + ScRangeList aRangeList; + for (SCCOL inCol = aStart.Col(); inCol <= aEnd.Col(); inCol++) + { + ScRange aColumnRange ( + ScAddress(inCol, aStart.Row(), aTab), + ScAddress(inCol, aEnd.Row(), aTab) ); + + aRangeList.push_back(aColumnRange); + } + return aRangeList; +} + +ScRangeList ScStatisticsInputOutputDialogController::MakeRowRangeList(SCTAB aTab, ScAddress const & aStart, ScAddress const & aEnd) +{ + ScRangeList aRangeList; + for (SCROW inRow = aStart.Row(); inRow <= aEnd.Row(); inRow++) + { + ScRange aRowRange ( + ScAddress(aStart.Col(), inRow, aTab), + ScAddress(aEnd.Col(), inRow, aTab) ); + + aRangeList.push_back(aRowRange); + } + return aRangeList; +} + +ScStatisticsInputOutputDialogController::ScStatisticsInputOutputDialogController( + SfxBindings* pSfxBindings, SfxChildWindow* pChildWindow, + weld::Window* pParent, ScViewData* pViewData, const OUString& rUIXMLDescription, const OString& rID) + : ScAnyRefDlgController(pSfxBindings, pChildWindow, pParent, rUIXMLDescription, rID) + , mxInputRangeLabel(m_xBuilder->weld_label("input-range-label")) + , mxInputRangeEdit(new formula::WeldRefEdit(m_xBuilder->weld_entry("input-range-edit"))) + , mxInputRangeButton(new formula::WeldRefButton(m_xBuilder->weld_button("input-range-button"))) + , mxOutputRangeLabel(m_xBuilder->weld_label("output-range-label")) + , mxOutputRangeEdit(new formula::WeldRefEdit(m_xBuilder->weld_entry("output-range-edit"))) + , mxOutputRangeButton(new formula::WeldRefButton(m_xBuilder->weld_button("output-range-button"))) + , mxGroupByColumnsRadio(m_xBuilder->weld_radio_button("groupedby-columns-radio")) + , mxGroupByRowsRadio(m_xBuilder->weld_radio_button("groupedby-rows-radio")) + , mViewData(pViewData) + , mDocument(pViewData->GetDocument()) + , mInputRange(ScAddress::INITIALIZE_INVALID) + , mAddressDetails(mDocument->GetAddressConvention(), 0, 0) + , mOutputAddress(ScAddress::INITIALIZE_INVALID) + , mGroupedBy(BY_COLUMN) + , mxButtonOk(m_xBuilder->weld_button("ok")) + , mpActiveEdit(nullptr) + , mCurrentAddress(pViewData->GetCurX(), pViewData->GetCurY(), pViewData->GetTabNo()) + , mDialogLostFocus(false) +{ + mxInputRangeEdit->SetReferences(this, mxInputRangeLabel.get()); + mxInputRangeButton->SetReferences(this, mxInputRangeEdit.get()); + + mxOutputRangeEdit->SetReferences(this, mxOutputRangeLabel.get()); + mxOutputRangeButton->SetReferences(this, mxOutputRangeEdit.get()); + + Init(); + GetRangeFromSelection(); +} + +ScStatisticsInputOutputDialogController::~ScStatisticsInputOutputDialogController() +{ +} + +void ScStatisticsInputOutputDialogController::Init() +{ + mxButtonOk->connect_clicked( LINK( this, ScStatisticsInputOutputDialogController, OkClicked ) ); + mxButtonOk->set_sensitive(false); + + Link<formula::WeldRefEdit&,void> aEditLink = LINK( this, ScStatisticsInputOutputDialogController, GetEditFocusHandler ); + mxInputRangeEdit->SetGetFocusHdl( aEditLink ); + mxOutputRangeEdit->SetGetFocusHdl( aEditLink ); + Link<formula::WeldRefButton&,void> aButtonLink = LINK( this, ScStatisticsInputOutputDialogController, GetButtonFocusHandler ); + mxInputRangeButton->SetGetFocusHdl( aButtonLink ); + mxOutputRangeButton->SetGetFocusHdl( aButtonLink ); + + aEditLink = LINK( this, ScStatisticsInputOutputDialogController, LoseEditFocusHandler ); + mxInputRangeEdit->SetLoseFocusHdl( aEditLink ); + mxOutputRangeEdit->SetLoseFocusHdl( aEditLink ); + aButtonLink = LINK( this, ScStatisticsInputOutputDialogController, LoseButtonFocusHandler ); + mxInputRangeButton->SetLoseFocusHdl( aButtonLink ); + mxOutputRangeButton->SetLoseFocusHdl( aButtonLink ); + + Link<formula::WeldRefEdit&,void> aLink2 = LINK( this, ScStatisticsInputOutputDialogController, RefInputModifyHandler); + mxInputRangeEdit->SetModifyHdl( aLink2); + mxOutputRangeEdit->SetModifyHdl( aLink2); + + mxOutputRangeEdit->GrabFocus(); + + mxGroupByColumnsRadio->connect_toggled( LINK( this, ScStatisticsInputOutputDialogController, GroupByChanged ) ); + mxGroupByRowsRadio->connect_toggled( LINK( this, ScStatisticsInputOutputDialogController, GroupByChanged ) ); + + mxGroupByColumnsRadio->set_active(true); + mxGroupByRowsRadio->set_active(false); +} + +void ScStatisticsInputOutputDialogController::GetRangeFromSelection() +{ + mViewData->GetSimpleArea(mInputRange); + OUString aCurrentString(mInputRange.Format(ScRefFlags::RANGE_ABS_3D, mDocument, mAddressDetails)); + mxInputRangeEdit->SetText(aCurrentString); +} + +void ScStatisticsInputOutputDialogController::SetActive() +{ + if ( mDialogLostFocus ) + { + mDialogLostFocus = false; + if( mpActiveEdit ) + mpActiveEdit->GrabFocus(); + } + else + { + m_xDialog->grab_focus(); + } + RefInputDone(); +} + +void ScStatisticsInputOutputDialogController::SetReference( const ScRange& rReferenceRange, ScDocument* pDocument ) +{ + if ( mpActiveEdit ) + { + if ( rReferenceRange.aStart != rReferenceRange.aEnd ) + RefInputStart( mpActiveEdit ); + + OUString aReferenceString; + + if (mpActiveEdit == mxInputRangeEdit.get()) + { + mInputRange = rReferenceRange; + aReferenceString = mInputRange.Format(ScRefFlags::RANGE_ABS_3D, pDocument, mAddressDetails); + mxInputRangeEdit->SetRefString( aReferenceString ); + } + else if (mpActiveEdit == mxOutputRangeEdit.get()) + { + mOutputAddress = rReferenceRange.aStart; + + ScRefFlags nFormat = ( mOutputAddress.Tab() == mCurrentAddress.Tab() ) ? + ScRefFlags::ADDR_ABS : + ScRefFlags::ADDR_ABS_3D; + aReferenceString = mOutputAddress.Format(nFormat, pDocument, pDocument->GetAddressConvention()); + mxOutputRangeEdit->SetRefString( aReferenceString ); + } + } + + ValidateDialogInput(); +} + +IMPL_LINK_NOARG( ScStatisticsInputOutputDialogController, OkClicked, weld::Button&, void ) +{ + CalculateInputAndWriteToOutput(); + response(RET_OK); +} + +IMPL_LINK(ScStatisticsInputOutputDialogController, GetEditFocusHandler, formula::WeldRefEdit&, rCtrl, void) +{ + mpActiveEdit = nullptr; + + if (&rCtrl == mxInputRangeEdit.get()) + mpActiveEdit = mxInputRangeEdit.get(); + if (&rCtrl == mxOutputRangeEdit.get()) + mpActiveEdit = mxOutputRangeEdit.get(); + + if (mpActiveEdit) + mpActiveEdit->SelectAll(); +} + +IMPL_LINK(ScStatisticsInputOutputDialogController, GetButtonFocusHandler, formula::WeldRefButton&, rCtrl, void) +{ + mpActiveEdit = nullptr; + + if (&rCtrl == mxInputRangeButton.get()) + mpActiveEdit = mxInputRangeEdit.get(); + else if (&rCtrl == mxOutputRangeButton.get()) + mpActiveEdit = mxOutputRangeEdit.get(); + + if (mpActiveEdit) + mpActiveEdit->SelectAll(); +} + +IMPL_LINK_NOARG(ScStatisticsInputOutputDialogController, LoseEditFocusHandler, formula::WeldRefEdit&, void) +{ + mDialogLostFocus = !m_xDialog->has_toplevel_focus(); +} + +IMPL_LINK_NOARG(ScStatisticsInputOutputDialogController, LoseButtonFocusHandler, formula::WeldRefButton&, void) +{ + mDialogLostFocus = !m_xDialog->has_toplevel_focus(); +} + +IMPL_LINK_NOARG( ScStatisticsInputOutputDialogController, GroupByChanged, weld::ToggleButton&, void ) +{ + if (mxGroupByColumnsRadio->get_active()) + mGroupedBy = BY_COLUMN; + else if (mxGroupByRowsRadio->get_active()) + mGroupedBy = BY_ROW; + + ValidateDialogInput(); +} + +IMPL_LINK_NOARG( ScStatisticsInputOutputDialogController, RefInputModifyHandler, formula::WeldRefEdit&, void ) +{ + if ( mpActiveEdit ) + { + if (mpActiveEdit == mxInputRangeEdit.get()) + { + ScRangeList aRangeList; + bool bValid = ParseWithNames( aRangeList, mxInputRangeEdit->GetText(), mDocument); + const ScRange* pRange = (bValid && aRangeList.size() == 1) ? &aRangeList[0] : nullptr; + if (pRange) + { + mInputRange = *pRange; + // Highlight the resulting range. + mxInputRangeEdit->StartUpdateData(); + } + else + { + mInputRange = ScRange( ScAddress::INITIALIZE_INVALID); + } + } + else if (mpActiveEdit == mxOutputRangeEdit.get()) + { + ScRangeList aRangeList; + bool bValid = ParseWithNames( aRangeList, mxOutputRangeEdit->GetText(), mDocument); + const ScRange* pRange = (bValid && aRangeList.size() == 1) ? &aRangeList[0] : nullptr; + if (pRange) + { + mOutputAddress = pRange->aStart; + + // Crop output range to top left address for Edit field. + if (pRange->aStart != pRange->aEnd) + { + ScRefFlags nFormat = ( mOutputAddress.Tab() == mCurrentAddress.Tab() ) ? + ScRefFlags::ADDR_ABS : + ScRefFlags::ADDR_ABS_3D; + OUString aReferenceString = mOutputAddress.Format(nFormat, mDocument, mDocument->GetAddressConvention()); + mxOutputRangeEdit->SetRefString( aReferenceString ); + } + + // Highlight the resulting range. + mxOutputRangeEdit->StartUpdateData(); + } + else + { + mOutputAddress = ScAddress( ScAddress::INITIALIZE_INVALID); + } + } + } + + ValidateDialogInput(); +} + +void ScStatisticsInputOutputDialogController::CalculateInputAndWriteToOutput() +{ + OUString aUndo(ScResId(GetUndoNameId())); + ScDocShell* pDocShell = mViewData->GetDocShell(); + SfxUndoManager* pUndoManager = pDocShell->GetUndoManager(); + pUndoManager->EnterListAction( aUndo, aUndo, 0, mViewData->GetViewShell()->GetViewShellId() ); + + ScRange aOutputRange = ApplyOutput(pDocShell); + + pUndoManager->LeaveListAction(); + pDocShell->PostPaint( aOutputRange, PaintPartFlags::Grid ); +} + +bool ScStatisticsInputOutputDialogController::InputRangesValid() +{ + return mInputRange.IsValid() && mOutputAddress.IsValid(); +} + +void ScStatisticsInputOutputDialogController::ValidateDialogInput() +{ + // Enable OK button if all inputs are ok. + mxButtonOk->set_sensitive(InputRangesValid()); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/app/scmod.cxx b/sc/source/ui/app/scmod.cxx index dcae91f597b8..7235c02076fb 100644 --- a/sc/source/ui/app/scmod.cxx +++ b/sc/source/ui/app/scmod.cxx @@ -1567,10 +1567,20 @@ bool ScModule::IsModalMode(SfxObjectShell* pDocSh) SfxChildWindow* pChildWnd = lcl_GetChildWinFromCurrentView( m_nCurRefDlgId ); if ( pChildWnd ) { - IAnyRefDialog* pRefDlg = dynamic_cast<IAnyRefDialog*>(pChildWnd->GetWindow()); - assert(pRefDlg); - bIsModal = pChildWnd->IsVisible() && pRefDlg && - !( pRefDlg->IsRefInputMode() && pRefDlg->IsDocAllowed(pDocSh) ); + if (pChildWnd->GetWindow()) + { + IAnyRefDialog* pRefDlg = dynamic_cast<IAnyRefDialog*>(pChildWnd->GetWindow()); + assert(pRefDlg); + bIsModal = pChildWnd->IsVisible() && pRefDlg && + !( pRefDlg->IsRefInputMode() && pRefDlg->IsDocAllowed(pDocSh) ); + } + if (pChildWnd->GetController()) + { + IAnyRefDialog* pRefDlg = dynamic_cast<IAnyRefDialog*>(pChildWnd->GetController().get()); + assert(pRefDlg); + bIsModal = pChildWnd->IsVisible() && pRefDlg && + !( pRefDlg->IsRefInputMode() && pRefDlg->IsDocAllowed(pDocSh) ); + } } } else if (pDocSh) @@ -1642,9 +1652,18 @@ bool ScModule::IsFormulaMode() SfxChildWindow* pChildWnd = lcl_GetChildWinFromCurrentView( m_nCurRefDlgId ); if ( pChildWnd ) { - IAnyRefDialog* pRefDlg = dynamic_cast<IAnyRefDialog*>(pChildWnd->GetWindow()); - assert(pRefDlg); - bIsFormula = pChildWnd->IsVisible() && pRefDlg && pRefDlg->IsRefInputMode(); + if (pChildWnd->GetWindow()) + { + IAnyRefDialog* pRefDlg = dynamic_cast<IAnyRefDialog*>(pChildWnd->GetWindow()); + assert(pRefDlg); + bIsFormula = pChildWnd->IsVisible() && pRefDlg && pRefDlg->IsRefInputMode(); + } + if (pChildWnd->GetController()) + { + IAnyRefDialog* pRefDlg = dynamic_cast<IAnyRefDialog*>(pChildWnd->GetController().get()); + assert(pRefDlg); + bIsFormula = pChildWnd->IsVisible() && pRefDlg && pRefDlg->IsRefInputMode(); + } } } else @@ -1694,14 +1713,29 @@ void ScModule::SetReference( const ScRange& rRef, ScDocument* pDoc, aNew.aEnd.SetTab(nEndTab); } - IAnyRefDialog* pRefDlg = dynamic_cast<IAnyRefDialog*>(pChildWnd->GetWindow()); - assert(pRefDlg); - if(pRefDlg) + if (pChildWnd->GetWindow()) { - // hide the (color) selection now instead of later from LoseFocus, - // don't abort the ref input that causes this call (bDoneRefMode = sal_False) - pRefDlg->HideReference( false ); - pRefDlg->SetReference( aNew, pDoc ); + IAnyRefDialog* pRefDlg = dynamic_cast<IAnyRefDialog*>(pChildWnd->GetWindow()); + assert(pRefDlg); + if(pRefDlg) + { + // hide the (color) selection now instead of later from LoseFocus, + // don't abort the ref input that causes this call (bDoneRefMode = sal_False) + pRefDlg->HideReference( false ); + pRefDlg->SetReference( aNew, pDoc ); + } + } + if (pChildWnd->GetController()) + { + IAnyRefDialog* pRefDlg = dynamic_cast<IAnyRefDialog*>(pChildWnd->GetController().get()); + assert(pRefDlg); + if(pRefDlg) + { + // hide the (color) selection now instead of later from LoseFocus, + // don't abort the ref input that causes this call (bDoneRefMode = sal_False) + pRefDlg->HideReference( false ); + pRefDlg->SetReference( aNew, pDoc ); + } } } } @@ -1760,11 +1794,23 @@ void ScModule::EndReference() OSL_ENSURE( pChildWnd, "NoChildWin" ); if ( pChildWnd ) { - IAnyRefDialog* pRefDlg = dynamic_cast<IAnyRefDialog*>(pChildWnd->GetWindow()); - assert(pRefDlg); - if(pRefDlg) + if (pChildWnd->GetWindow()) { - pRefDlg->SetActive(); + IAnyRefDialog* pRefDlg = dynamic_cast<IAnyRefDialog*>(pChildWnd->GetWindow()); + assert(pRefDlg); + if(pRefDlg) + { + pRefDlg->SetActive(); + } + } + if (pChildWnd->GetController()) + { + IAnyRefDialog* pRefDlg = dynamic_cast<IAnyRefDialog*>(pChildWnd->GetController().get()); + assert(pRefDlg); + if(pRefDlg) + { + pRefDlg->SetActive(); + } } } } @@ -2161,6 +2207,36 @@ void ScModule::UnregisterRefWindow( sal_uInt16 nSlotId, vcl::Window *pWnd ) m_mapRefWindow.erase( nSlotId ); } +void ScModule::RegisterRefController( sal_uInt16 nSlotId, SfxModelessDialogController *pWnd ) +{ + std::vector<SfxModelessDialogController*> & rlRefWindow = m_mapRefController[nSlotId]; + + if( std::find( rlRefWindow.begin(), rlRefWindow.end(), pWnd ) == rlRefWindow.end() ) + { + rlRefWindow.emplace_back(pWnd ); + } +} + +void ScModule::UnregisterRefController( sal_uInt16 nSlotId, SfxModelessDialogController *pWnd ) +{ + auto iSlot = m_mapRefController.find( nSlotId ); + + if( iSlot == m_mapRefController.end() ) + return; + + std::vector<SfxModelessDialogController* > & rlRefWindow = iSlot->second; + + auto i = std::find( rlRefWindow.begin(), rlRefWindow.end(), pWnd ); + + if( i == rlRefWindow.end() ) + return; + + rlRefWindow.erase( i ); + + if( rlRefWindow.empty() ) + m_mapRefController.erase( nSlotId ); +} + vcl::Window * ScModule::Find1RefWindow( sal_uInt16 nSlotId, vcl::Window *pWndAncestor ) { if (!pWndAncestor) diff --git a/sc/source/ui/formdlg/formula.cxx b/sc/source/ui/formdlg/formula.cxx index 56d96a456ea9..4dd504d7d809 100644 --- a/sc/source/ui/formdlg/formula.cxx +++ b/sc/source/ui/formdlg/formula.cxx @@ -393,6 +393,14 @@ void ScFormulaDlg::RefInputStart( formula::RefEdit* pEdit, formula::RefButton* p RefInputStartAfter(); } +void ScFormulaDlg::RefInputStart( formula::WeldRefEdit* pEdit, formula::WeldRefButton* pButton ) +{ + pEdit->SelectAll(); + ::std::pair<formula::WeldRefButton*,formula::WeldRefEdit*> aPair = RefInputStartBefore( pEdit, pButton ); + m_aHelper.RefInputStart( aPair.second, aPair.first); + RefInputStartAfter(); +} + void ScFormulaDlg::RefInputDone( bool bForced ) { m_aHelper.RefInputDone( bForced ); @@ -531,10 +539,18 @@ void ScFormulaDlg::ToggleCollapsed( formula::RefEdit* pEdit, formula::RefButton* { m_aHelper.ToggleCollapsed(pEdit,pButton); } +void ScFormulaDlg::ToggleCollapsed( formula::WeldRefEdit* pEdit, formula::WeldRefButton* pButton) +{ + m_aHelper.ToggleCollapsed(pEdit,pButton); +} void ScFormulaDlg::ReleaseFocus( formula::RefEdit* pEdit) { m_aHelper.ReleaseFocus(pEdit); } +void ScFormulaDlg::ReleaseFocus( formula::WeldRefEdit* pEdit) +{ + m_aHelper.ReleaseFocus(pEdit); +} void ScFormulaDlg::dispatch(bool _bOK, bool _bMatrixChecked) { SfxBoolItem aRetItem( SID_DLG_RETOK, _bOK ); diff --git a/sc/source/ui/inc/ChildWindowWrapper.hxx b/sc/source/ui/inc/ChildWindowWrapper.hxx index 60382774de03..1ad232a7b91b 100644 --- a/sc/source/ui/inc/ChildWindowWrapper.hxx +++ b/sc/source/ui/inc/ChildWindowWrapper.hxx @@ -88,6 +88,67 @@ private: } }; +template <sal_Int16 WindowID> +class ChildControllerWrapper : public SfxChildWindow +{ +public: + ChildControllerWrapper(vcl::Window* pParentP, sal_uInt16 nId, + SfxBindings* pBindings, const SfxChildWinInfo* pInfo) + : SfxChildWindow(pParentP, nId) + { + ScTabViewShell* pViewShell = getTabViewShell( pBindings ); + if (!pViewShell) + pViewShell = dynamic_cast< ScTabViewShell *>( SfxViewShell::Current() ); + OSL_ENSURE(pViewShell, "Missing view shell!"); + + if (pViewShell) + SetController(pViewShell->CreateRefDialogController(pBindings, this, pInfo, pParentP->GetFrameWeld(), WindowID)); + + if (pViewShell && !GetController()) + pViewShell->GetViewFrame()->SetChildWindow( nId, false ); + } + + static std::unique_ptr<SfxChildWindow> CreateImpl( + vcl::Window *pParent, sal_uInt16 nId, + SfxBindings *pBindings, SfxChildWinInfo* pInfo ) + { + return std::make_unique<ChildControllerWrapper>(pParent, nId, pBindings, pInfo); + } + + static void RegisterChildWindow ( + bool bVisible = false, + SfxModule* pModule = nullptr, + SfxChildWindowFlags nFlags = SfxChildWindowFlags::NONE) + { + auto pFactory = std::make_unique<SfxChildWinFactory>(ChildControllerWrapper::CreateImpl, WindowID, CHILDWIN_NOPOS ); + pFactory->aInfo.nFlags |= nFlags; + pFactory->aInfo.bVisible = bVisible; + SfxChildWindow::RegisterChildWindow(pModule, std::move(pFactory)); + } + + static sal_uInt16 GetChildWindowId() + { + return WindowID; + } + +private: + static ScTabViewShell* getTabViewShell( const SfxBindings *pBindings ) + { + if( !pBindings ) + return nullptr; + SfxDispatcher* pDispacher = pBindings ->GetDispatcher(); + if( !pDispacher ) + return nullptr; + SfxViewFrame* pFrame = pDispacher->GetFrame(); + if( !pFrame ) + return nullptr; + SfxViewShell* pViewShell = pFrame->GetViewShell(); + if( !pViewShell ) + return nullptr; + return dynamic_cast<ScTabViewShell*>( pViewShell ); + } +}; + #endif // INCLUDED_SC_SOURCE_UI_INC_CHILDWINDOWWRAPPER_HXX /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/CorrelationDialog.hxx b/sc/source/ui/inc/CorrelationDialog.hxx index ee2f433ed35d..2a98da43881f 100644 --- a/sc/source/ui/inc/CorrelationDialog.hxx +++ b/sc/source/ui/inc/CorrelationDialog.hxx @@ -13,14 +13,14 @@ #include "MatrixComparisonGenerator.hxx" -class ScCorrelationDialog : public ScMatrixComparisonGenerator +class ScCorrelationDialog : public ScMatrixComparisonGeneratorController { public: ScCorrelationDialog( SfxBindings* pSfxBindings, SfxChildWindow* pChildWindow, - vcl::Window* pParent, ScViewData* pViewData); + weld::Window* pParent, ScViewData* pViewData); - virtual bool Close() override; + virtual void Close() override; protected: virtual const OUString getLabel() override; diff --git a/sc/source/ui/inc/IAnyRefDialog.hxx b/sc/source/ui/inc/IAnyRefDialog.hxx index 0e4f81f41572..486322936ba8 100644 --- a/sc/source/ui/inc/IAnyRefDialog.hxx +++ b/sc/source/ui/inc/IAnyRefDialog.hxx @@ -36,6 +36,7 @@ public: virtual void SetReference( const ScRange& rRef, ScDocument* pDoc ) = 0; virtual void RefInputStart( formula::RefEdit* pEdit, formula::RefButton* pButton = nullptr ) = 0; + virtual void RefInputStart( formula::WeldRefEdit* pEdit, formula::WeldRefButton* pButton = nullptr ) = 0; virtual void RefInputDone( bool bForced = false ) = 0; virtual bool IsTableLocked() const = 0; virtual bool IsRefInputMode() const = 0; diff --git a/sc/source/ui/inc/MatrixComparisonGenerator.hxx b/sc/source/ui/inc/MatrixComparisonGenerator.hxx index cce103291a51..0923042120e6 100644 --- a/sc/source/ui/inc/MatrixComparisonGenerator.hxx +++ b/sc/source/ui/inc/MatrixComparisonGenerator.hxx @@ -34,6 +34,24 @@ protected: virtual const OUString getTemplate() = 0; }; +class ScMatrixComparisonGeneratorController : public ScStatisticsInputOutputDialogController +{ +public: + ScMatrixComparisonGeneratorController( + SfxBindings* pSfxBindings, SfxChildWindow* pChildWindow, + weld::Window* pParent, ScViewData* pViewData, + const OUString& rUiXmlDescription, const OString& rID); + + virtual ~ScMatrixComparisonGeneratorController() override; + +protected: + virtual const char* GetUndoNameId() override; + virtual ScRange ApplyOutput(ScDocShell* pDocShell) override; + + virtual const OUString getLabel() = 0; + virtual const OUString getTemplate() = 0; +}; + #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/StatisticsInputOutputDialog.hxx b/sc/source/ui/inc/StatisticsInputOutputDialog.hxx index b63ccd35c78e..6a18855851a4 100644 --- a/sc/source/ui/inc/StatisticsInputOutputDialog.hxx +++ b/sc/source/ui/inc/StatisticsInputOutputDialog.hxx @@ -86,6 +86,78 @@ private: DECL_LINK( RefInputModifyHandler, Edit&, void ); }; +class ScStatisticsInputOutputDialogController : public ScAnyRefDlgController +{ +public: + enum GroupedBy { + BY_COLUMN, + BY_ROW + }; + + ScStatisticsInputOutputDialogController( + SfxBindings* pB, SfxChildWindow* pCW, + weld::Window* pParent, ScViewData* pViewData, + const OUString& rUIXMLDescription, + const OString& rID); + + virtual ~ScStatisticsInputOutputDialogController() override; + + virtual void SetReference( const ScRange& rRef, ScDocument* pDoc ) override; + virtual void SetActive() override; + +protected: + void CalculateInputAndWriteToOutput(); + + virtual ScRange ApplyOutput(ScDocShell* pDocShell) = 0; + virtual const char* GetUndoNameId() = 0; + virtual bool InputRangesValid(); + void ValidateDialogInput(); + + // Widgets + std::unique_ptr<weld::Label> mxInputRangeLabel; + std::unique_ptr<formula::WeldRefEdit> mxInputRangeEdit; + std::unique_ptr<formula::WeldRefButton> mxInputRangeButton; + + std::unique_ptr<weld::Label> mxOutputRangeLabel; + std::unique_ptr<formula::WeldRefEdit> mxOutputRangeEdit; + std::unique_ptr<formula::WeldRefButton> mxOutputRangeButton; + + std::unique_ptr<weld::RadioButton> mxGroupByColumnsRadio; + std::unique_ptr<weld::RadioButton> mxGroupByRowsRadio; + + // Data + ScViewData* const mViewData; + ScDocument* const mDocument; + + ScRange mInputRange; + ScAddress::Details const mAddressDetails; + ScAddress mOutputAddress; + GroupedBy mGroupedBy; + + static ScRangeList MakeColumnRangeList(SCTAB aTab, ScAddress const & aStart, ScAddress const & aEnd); + static ScRangeList MakeRowRangeList(SCTAB aTab, ScAddress const & aStart, ScAddress const & aEnd); + +private: + // Widgets + std::unique_ptr<weld::Button> mxButtonOk; + + formula::WeldRefEdit* mpActiveEdit; + ScAddress const mCurrentAddress; + bool mDialogLostFocus; + + void Init(); + void GetRangeFromSelection(); + + DECL_LINK( GroupByChanged, weld::ToggleButton&, void ); + DECL_LINK( OkClicked, weld::Button&, void ); + DECL_LINK( GetEditFocusHandler, formula::WeldRefEdit&, void ); + DECL_LINK( GetButtonFocusHandler, formula::WeldRefButton&, void ); + DECL_LINK( LoseEditFocusHandler, formula::WeldRefEdit&, void ); + DECL_LINK( LoseButtonFocusHandler, formula::WeldRefButton&, void ); + DECL_LINK( RefInputModifyHandler, formula::WeldRefEdit&, void ); +}; + + #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/anyrefdg.hxx b/sc/source/ui/inc/anyrefdg.hxx index 069bc2650ee5..3a5726123654 100644 --- a/sc/source/ui/inc/anyrefdg.hxx +++ b/sc/source/ui/inc/anyrefdg.hxx @@ -40,7 +40,10 @@ class ScFormulaReferenceHelper ::std::unique_ptr<ScCompiler> m_pRefComp; VclPtr<formula::RefEdit> m_pRefEdit; // active input field VclPtr<formula::RefButton> m_pRefBtn; // associated button + formula::WeldRefEdit* m_pWeldRefEdit; // active input field + formula::WeldRefButton* m_pWeldRefBtn; // associated button VclPtr<vcl::Window> m_pWindow; + weld::Dialog* m_pDialog; SfxBindings* const m_pBindings; ::std::unique_ptr<Accelerator> m_pAccel; // for Enter/Escape @@ -63,6 +66,7 @@ class ScFormulaReferenceHelper bool m_bAccInserted; DECL_LINK( AccelSelectHdl, Accelerator&, void ); + DECL_LINK( ActivateHdl, weld::Widget&, bool ); public: ScFormulaReferenceHelper(IAnyRefDialog* _pDlg,SfxBindings* _pBindings); @@ -76,12 +80,16 @@ public: void ShowReference(const OUString& rStr); void ReleaseFocus( formula::RefEdit* pEdit ); + void ReleaseFocus( formula::WeldRefEdit* pEdit ); void HideReference( bool bDoneRefMode = true ); void RefInputStart( formula::RefEdit* pEdit, formula::RefButton* pButton ); + void RefInputStart( formula::WeldRefEdit* pEdit, formula::WeldRefButton* pButton ); void RefInputDone( bool bForced ); void ToggleCollapsed( formula::RefEdit* pEdit, formula::RefButton* pButton ); + void ToggleCollapsed( formula::WeldRefEdit* pEdit, formula::WeldRefButton* pButton ); - void SetWindow(vcl::Window* _pWindow) { m_pWindow = _pWindow; } + void SetWindow(vcl::Window* _pWindow) { m_pWindow = _pWindow; } + void SetDialog(weld::Dialog* pDialog) { m_pDialog = pDialog; } void DoClose( sal_uInt16 nId ); void SetDispatcherLock( bool bLock ); static void EnableSpreadsheets( bool bFlag = true ); @@ -91,13 +99,14 @@ public: public: static bool CanInputStart( const formula::RefEdit *pEdit ){ return !!pEdit; } - bool CanInputDone( bool bForced ){ return m_pRefEdit && (bForced || !m_pRefBtn); } + bool CanInputDone( bool bForced ){ return (m_pRefEdit || m_pWeldRefEdit) && (bForced || !(m_pRefBtn || m_pWeldRefBtn)); } }; class SC_DLLPUBLIC ScRefHandler : public IAnyRefDialog { VclPtr<vcl::Window> m_rWindow; + weld::DialogController* m_pController; bool m_bInRefMode; public: @@ -118,12 +127,14 @@ protected: void SetDispatcherLock( bool bLock ); virtual void RefInputStart( formula::RefEdit* pEdit, formula::RefButton* pButton = nullptr ) override; + virtual void RefInputStart( formula::WeldRefEdit* pEdit, formula::WeldRefButton* pButton = nullptr ) override; virtual void RefInputDone( bool bForced = false ) override; bool ParseWithNames( ScRangeList& rRanges, const OUString& rStr, const ScDocument* pDoc ); public: ScRefHandler( vcl::Window &rWindow, SfxBindings* pB, bool bBindRef ); + ScRefHandler( SfxModelessDialogController &rController, SfxBindings* pB, bool bBindRef ); virtual ~ScRefHandler() override; virtual void SetReference( const ScRange& rRef, ScDocument* pDoc ) override = 0; @@ -137,7 +148,9 @@ public: virtual void HideReference( bool bDoneRefMode = true ) override; virtual void ToggleCollapsed( formula::RefEdit* pEdit, formula::RefButton* pButton ) override; + virtual void ToggleCollapsed( formula::WeldRefEdit* pEdit, formula::WeldRefButton* pButton ) override; virtual void ReleaseFocus( formula::RefEdit* pEdit ) override; + virtual void ReleaseFocus( formula::WeldRefEdit* pEdit ) override; virtual void ViewShellChanged() override; void SwitchToDocument(); @@ -228,6 +241,77 @@ struct ScAnyRefDlg : ::ScRefHdlrImpl< ScAnyRefDlg, SfxModelessDialog> } }; +template< class TWindow, bool bBindRef = true > +class ScRefHdlrControllerImplBase: public TWindow, public ScRefHandler +{ +private: + template<class TBindings, class TChildWindow, class TParentWindow > + ScRefHdlrControllerImplBase( TBindings* pB, TChildWindow* pCW, + TParentWindow* pParent, const OUString& rUIXMLDescription, const OString& rID ); + + template<class TParentWindow, class TArg> + ScRefHdlrControllerImplBase(TParentWindow* pParent, const OUString& rUIXMLDescription, const OString& rID, const TArg &rArg, SfxBindings *pB); + + virtual ~ScRefHdlrControllerImplBase() override; + + template<class, class, bool> friend struct ScRefHdlrControllerImpl; +}; + +template<class TWindow, bool bBindRef > +ScRefHdlrControllerImplBase<TWindow,bBindRef>::~ScRefHdlrControllerImplBase(){} + +template<class TWindow, bool bBindRef> +template<class TBindings, class TChildWindow, class TParentWindow> +ScRefHdlrControllerImplBase<TWindow, bBindRef>::ScRefHdlrControllerImplBase(TBindings* pB, TChildWindow* pCW, + TParentWindow* pParent, const OUString& rUIXMLDescription, const OString& rID) + : TWindow(pB, pCW, pParent, rUIXMLDescription, rID) + , ScRefHandler( *static_cast<TWindow*>(this), pB, bBindRef ) +{ +} + +template<class TWindow, bool bBindRef > +template<class TParentWindow, class TArg> +ScRefHdlrControllerImplBase<TWindow,bBindRef>::ScRefHdlrControllerImplBase(TParentWindow* pParent, const OUString& rUIXMLDescription, const OString& rID, + const TArg &rArg, SfxBindings *pB) + : TWindow(pParent, rUIXMLDescription, rID, rArg) + , ScRefHandler( *static_cast<TWindow*>(this), pB, bBindRef ) +{ +} + +template<class TDerived, class TBase, bool bBindRef = true> +struct ScRefHdlrControllerImpl: ScRefHdlrControllerImplBase< TBase, bBindRef > +{ + enum { UNKNOWN_SLOTID = 0U, SLOTID = UNKNOWN_SLOTID }; + + template<class T1, class T2, class T3, class T4> + ScRefHdlrControllerImpl( const T1 & rt1, const T2 & rt2, const T3& rt3, const T4& rt4 ) + : ScRefHdlrControllerImplBase<TBase, bBindRef >(rt1, rt2, rt3, rt4) + { + SC_MOD()->RegisterRefController( static_cast<sal_uInt16>( TDerived::SLOTID ), this ); + } + + template<class T1, class T2, class T3, class T4, class T5> + ScRefHdlrControllerImpl( const T1 & rt1, const T2 & rt2, const T3& rt3, const T4& rt4, const T5& rt5 ) + : ScRefHdlrControllerImplBase<TBase, bBindRef >(rt1, rt2, rt3, rt4, rt5) + { + SC_MOD()->RegisterRefController( static_cast<sal_uInt16>( TDerived::SLOTID ), this ); + } + + ~ScRefHdlrControllerImpl() + { + SC_MOD()->UnregisterRefController( static_cast<sal_uInt16>( TDerived::SLOTID ), this ); + } +}; + +struct ScAnyRefDlgController : ::ScRefHdlrControllerImpl<ScAnyRefDlgController, SfxModelessDialogController> +{ + template<class T1, class T2, class T3, class T4, class T5> + ScAnyRefDlgController( const T1 & rt1, const T2 & rt2, const T3& rt3, const T4& rt4, const T5& rt5 ) + : ScRefHdlrControllerImpl<ScAnyRefDlgController, SfxModelessDialogController>(rt1, rt2, rt3, rt4, rt5) + { + } +}; + inline bool ScRefHandler::CanInputStart( const formula::RefEdit *pEdit ) { return ScFormulaReferenceHelper::CanInputStart( pEdit ); diff --git a/sc/source/ui/inc/formula.hxx b/sc/source/ui/inc/formula.hxx index a40b55ecb9e1..97737e7c4af9 100644 --- a/sc/source/ui/inc/formula.hxx +++ b/sc/source/ui/inc/formula.hxx @@ -83,7 +83,9 @@ public: virtual void SetReference( const ScRange& rRef, ScDocument* pD ) override; virtual void ReleaseFocus( formula::RefEdit* pEdit ) override; + virtual void ReleaseFocus( formula::WeldRefEdit* pEdit ) override; virtual void ToggleCollapsed( formula::RefEdit* pEdit, formula::RefButton* pButton ) override; + virtual void ToggleCollapsed( formula::WeldRefEdit* pEdit, formula::WeldRefButton* pButton ) override; virtual void RefInputDone( bool bForced = false ) override; virtual bool IsTableLocked() const override; virtual bool IsRefInputMode() const override; @@ -95,6 +97,7 @@ public: private: virtual void RefInputStart( formula::RefEdit* pEdit, formula::RefButton* pButton = nullptr ) override; + virtual void RefInputStart( formula::WeldRefEdit* pEdit, formula::WeldRefButton* pButton = nullptr ) override; static void SaveLRUEntry(const ScFuncDesc* pFuncDesc); static bool IsInputHdl(const ScInputHandler* pHdl); diff --git a/sc/source/ui/inc/reffact.hxx b/sc/source/ui/inc/reffact.hxx index a49f80c0de97..28c42f089a38 100644 --- a/sc/source/ui/inc/reffact.hxx +++ b/sc/source/ui/inc/reffact.hxx @@ -79,7 +79,7 @@ private: }; class ScCorrelationDialogWrapper : - public ChildWindowWrapper<SID_CORRELATION_DIALOG> + public ChildControllerWrapper<SID_CORRELATION_DIALOG> { private: ScCorrelationDialogWrapper() = delete; diff --git a/sc/source/ui/inc/tabvwsh.hxx b/sc/source/ui/inc/tabvwsh.hxx index d60cb0e388e0..f2a260030206 100644 --- a/sc/source/ui/inc/tabvwsh.hxx +++ b/sc/source/ui/inc/tabvwsh.hxx @@ -328,6 +328,10 @@ public: const SfxChildWinInfo* pInfo, vcl::Window* pParent, sal_uInt16 nSlotId ); + std::unique_ptr<SfxModelessDialogController> CreateRefDialogController(SfxBindings* pB, SfxChildWindow* pCW, + const SfxChildWinInfo* pInfo, + weld::Window* pParent, sal_uInt16 nSlotId); + void UpdateOleZoom(); virtual const FmFormShell* GetFormShell() const override { return pFormShell.get(); } diff --git a/sc/source/ui/inc/validate.hxx b/sc/source/ui/inc/validate.hxx index 62b4388272e1..c29d8b6c7335 100644 --- a/sc/source/ui/inc/validate.hxx +++ b/sc/source/ui/inc/validate.hxx @@ -228,6 +228,11 @@ public: ScValidationDlgBase::RefInputStart( pEdit, pButton ); } + virtual void RefInputStart( formula::WeldRefEdit* /*pEdit*/, formula::WeldRefButton* /*pButton*/ = nullptr ) override + { + assert(false); + } + virtual void RefInputDone( bool bForced = false ) override { if( !CanInputDone( bForced ) ) diff --git a/sc/source/ui/miscdlgs/anyrefdg.cxx b/sc/source/ui/miscdlgs/anyrefdg.cxx index b108d4487acd..29c05945b30c 100644 --- a/sc/source/ui/miscdlgs/anyrefdg.cxx +++ b/sc/source/ui/miscdlgs/anyrefdg.cxx @@ -47,7 +47,10 @@ ScFormulaReferenceHelper::ScFormulaReferenceHelper(IAnyRefDialog* _pDlg,SfxBindi : m_pDlg(_pDlg) , m_pRefEdit (nullptr) , m_pRefBtn (nullptr) + , m_pWeldRefEdit (nullptr) + , m_pWeldRefBtn (nullptr) , m_pWindow(nullptr) + , m_pDialog(nullptr) , m_pBindings(_pBindings) , m_nOldBorderWidth (0) , m_nRefTab(0) @@ -85,6 +88,7 @@ void ScFormulaReferenceHelper::dispose() m_pOldEditParent.clear(); m_pWindow.clear(); + m_pDialog = nullptr; m_pRefBtn.clear(); m_pRefEdit.clear(); } @@ -321,6 +325,39 @@ void ScFormulaReferenceHelper::ReleaseFocus( formula::RefEdit* pEdit ) } } +void ScFormulaReferenceHelper::ReleaseFocus( formula::WeldRefEdit* pEdit ) +{ + if( !m_pWeldRefEdit && pEdit ) + { + m_pDlg->RefInputStart( pEdit ); + } + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if( pViewShell ) + { + pViewShell->ActiveGrabFocus(); + if( m_pWeldRefEdit ) + { + const ScViewData& rViewData = pViewShell->GetViewData(); + ScDocument* pDoc = rViewData.GetDocument(); + ScRangeList aRangeList; + if( ParseWithNames( aRangeList, m_pWeldRefEdit->GetText(), pDoc ) ) + { + if ( !aRangeList.empty() ) + { + const ScRange & rRange = aRangeList.front(); + pViewShell->SetTabNo( rRange.aStart.Tab() ); + pViewShell->MoveCursorAbs( rRange.aStart.Col(), + rRange.aStart.Row(), SC_FOLLOW_JUMP, false, false ); + pViewShell->MoveCursorAbs( rRange.aEnd.Col(), + rRange.aEnd.Row(), SC_FOLLOW_JUMP, true, false ); + m_pDlg->SetReference( rRange, pDoc ); + } + } + } + } +} + void ScFormulaReferenceHelper::Init() { ScViewData* pViewData=ScDocShell::GetViewData(); //! use pScViewShell? @@ -353,6 +390,14 @@ IMPL_LINK( ScFormulaReferenceHelper, AccelSelectHdl, Accelerator&, rSelAccel, vo } } +IMPL_LINK_NOARG(ScFormulaReferenceHelper, ActivateHdl, weld::Widget&, bool) +{ + if (m_pWeldRefEdit) + m_pWeldRefEdit->GrabFocus(); + m_pDlg->RefInputDone(true); + return true; +} + void ScFormulaReferenceHelper::RefInputDone( bool bForced ) { if ( CanInputDone( bForced ) ) @@ -363,62 +408,86 @@ void ScFormulaReferenceHelper::RefInputDone( bool bForced ) m_bAccInserted = false; } - //get rid of all this junk when we can - if (!m_bOldDlgLayoutEnabled) + if (m_pDialog) { - m_pWindow->SetOutputSizePixel(m_aOldDialogSize); + // Adjust window title + m_pDialog->set_title(m_sOldDialogText); - // restore the parent of the edit field - m_pRefEdit->SetParent(m_pOldEditParent); + if (m_pWeldRefEdit) + m_pWeldRefEdit->SetActivateHdl(Link<weld::Widget&, bool>()); - // the window is at the old size again - m_pWindow->SetOutputSizePixel(m_aOldDialogSize); - - // set button parent - if( m_pRefBtn ) + // set button image + if (m_pWeldRefBtn) { - m_pRefBtn->SetParent(m_pWindow); + m_pWeldRefBtn->SetActivateHdl(Link<weld::Widget&, bool>()); + m_pWeldRefBtn->SetStartImage(); } + + m_pDialog->undo_collapse(); + + m_pWeldRefEdit = nullptr; + m_pWeldRefBtn = nullptr; } - if (!m_bOldEditParentLayoutEnabled) + if (m_pWindow) { - // set pEditCell to old position - m_pRefEdit->SetPosSizePixel(m_aOldEditPos, m_aOldEditSize); + //get rid of all this junk when we can + if (!m_bOldDlgLayoutEnabled) + { + m_pWindow->SetOutputSizePixel(m_aOldDialogSize); - // set button position - if( m_pRefBtn ) + // restore the parent of the edit field + m_pRefEdit->SetParent(m_pOldEditParent); + + // the window is at the old size again + m_pWindow->SetOutputSizePixel(m_aOldDialogSize); + + // set button parent + if( m_pRefBtn ) + { + m_pRefBtn->SetParent(m_pWindow); + } + } + + if (!m_bOldEditParentLayoutEnabled) { - m_pRefBtn->SetPosPixel( m_aOldButtonPos ); + // set pEditCell to old position + m_pRefEdit->SetPosSizePixel(m_aOldEditPos, m_aOldEditSize); + + // set button position + if( m_pRefBtn ) + { + m_pRefBtn->SetPosPixel( m_aOldButtonPos ); + } } - } - // Adjust window title - m_pWindow->SetText(m_sOldDialogText); + // Adjust window title + m_pWindow->SetText(m_sOldDialogText); - // set button image - if( m_pRefBtn ) - m_pRefBtn->SetStartImage(); + // set button image + if( m_pRefBtn ) + m_pRefBtn->SetStartImage(); - // All others: Show(); - for (VclPtr<vcl::Window> const & pWindow : m_aHiddenWidgets) - { - pWindow->Show(); - } - m_aHiddenWidgets.clear(); + // All others: Show(); + for (VclPtr<vcl::Window> const & pWindow : m_aHiddenWidgets) + { + pWindow->Show(); + } + m_aHiddenWidgets.clear(); - if (m_bOldDlgLayoutEnabled) - { - m_pRefEdit->set_width_request(m_nOldEditWidthReq); - Dialog* pResizeDialog = m_pRefEdit->GetParentDialog(); - pResizeDialog->set_border_width(m_nOldBorderWidth); - if (vcl::Window *pActionArea = pResizeDialog->get_action_area()) - pActionArea->Show(); - pResizeDialog->setOptimalLayoutSize(); - } + if (m_bOldDlgLayoutEnabled) + { + m_pRefEdit->set_width_request(m_nOldEditWidthReq); + Dialog* pResizeDialog = m_pRefEdit->GetParentDialog(); + pResizeDialog->set_border_width(m_nOldBorderWidth); + if (vcl::Window *pActionArea = pResizeDialog->get_action_area()) + pActionArea->Show(); + pResizeDialog->setOptimalLayoutSize(); + } - m_pRefEdit = nullptr; - m_pRefBtn = nullptr; + m_pRefEdit = nullptr; + m_pRefBtn = nullptr; + } } } @@ -591,6 +660,37 @@ void ScFormulaReferenceHelper::RefInputStart( formula::RefEdit* pEdit, formula:: } } +void ScFormulaReferenceHelper::RefInputStart( formula::WeldRefEdit* pEdit, formula::WeldRefButton* pButton ) +{ + if (!m_pWeldRefEdit) + { + m_pWeldRefEdit = pEdit; + m_pWeldRefBtn = pButton; + + // Save and adjust window title + m_sOldDialogText = m_pDialog->get_title(); + if (weld::Label *pLabel = m_pWeldRefEdit->GetLabelWidgetForShrinkMode()) + { + const OUString sLabel = pLabel->get_label(); + if (!sLabel.isEmpty()) + { + const OUString sNewDialogText = m_sOldDialogText + ": " + comphelper::string::stripEnd(sLabel, ':'); + m_pDialog->set_title(pLabel->strip_mnemonic(sNewDialogText)); + } + } + + m_pDialog->collapse(pEdit->GetWidget(), pButton ? pButton->GetWidget() : nullptr); + + // set button image + if (pButton) + pButton->SetEndImage(); + + m_pWeldRefEdit->SetActivateHdl(LINK(this, ScFormulaReferenceHelper, ActivateHdl)); + if (m_pWeldRefBtn) + m_pWeldRefBtn->SetActivateHdl(LINK(this, ScFormulaReferenceHelper, ActivateHdl)); + } +} + void ScFormulaReferenceHelper::ToggleCollapsed( formula::RefEdit* pEdit, formula::RefButton* pButton ) { if( pEdit ) @@ -611,6 +711,26 @@ void ScFormulaReferenceHelper::ToggleCollapsed( formula::RefEdit* pEdit, formula } } +void ScFormulaReferenceHelper::ToggleCollapsed( formula::WeldRefEdit* pEdit, formula::WeldRefButton* pButton ) +{ + if( pEdit ) + { + if( m_pWeldRefEdit == pEdit ) // is this the active ref edit field? + { + m_pWeldRefEdit->GrabFocus(); // before RefInputDone() + m_pDlg->RefInputDone( true ); // finish ref input + } + else + { + m_pDlg->RefInputDone( true ); // another active ref edit? + m_pDlg->RefInputStart( pEdit, pButton ); // start ref input + // pRefEdit might differ from pEdit after RefInputStart() (i.e. ScFormulaDlg) + if( m_pWeldRefEdit ) + m_pWeldRefEdit->GrabFocus(); + } + } +} + void ScFormulaReferenceHelper::DoClose( sal_uInt16 nId ) { SfxApplication* pSfxApp = SfxGetpApp(); @@ -747,11 +867,9 @@ static void lcl_HideAllReferences() } } -//The class of ScAnyRefDlg is rewritten by PengYunQuan for Validity Cell Range Picker -// class ScRefHandler - ScRefHandler::ScRefHandler( vcl::Window &rWindow, SfxBindings* pB, bool bBindRef ): m_rWindow( &rWindow ), + m_pController( nullptr ), m_bInRefMode( false ), m_aHelper(this,pB), m_pMyBindings( pB ) @@ -761,6 +879,17 @@ ScRefHandler::ScRefHandler( vcl::Window &rWindow, SfxBindings* pB, bool bBindRef if( bBindRef ) EnterRefMode(); } +ScRefHandler::ScRefHandler(SfxModelessDialogController& rController, SfxBindings* pB, bool bBindRef) + : m_pController(&rController) + , m_bInRefMode(false) + , m_aHelper(this, pB) + , m_pMyBindings(pB) +{ + m_aHelper.SetDialog(rController.getDialog()); + + if( bBindRef ) EnterRefMode(); +} + bool ScRefHandler::EnterRefMode() { if( m_bInRefMode ) return false; @@ -819,6 +948,7 @@ ScRefHandler::~ScRefHandler() void ScRefHandler::disposeRefHandler() { m_rWindow.clear(); + m_pController = nullptr; LeaveRefMode(); m_aHelper.dispose(); } @@ -831,6 +961,8 @@ bool ScRefHandler::LeaveRefMode() if( Dialog *pDlg = dynamic_cast<Dialog*>( m_rWindow.get() ) ) pDlg->SetModalInputMode(false); + if (m_pController) + m_pController->getDialog()->set_modal(false); SetDispatcherLock( false ); //! here and in DoClose ? ScTabViewShell* pScViewShell = ScTabViewShell::GetActiveViewShell(); @@ -885,6 +1017,8 @@ bool ScRefHandler::IsDocAllowed(SfxObjectShell* pDocSh) const // pDocSh may be bool ScRefHandler::IsRefInputMode() const { + if (m_pController) + return m_pController->getDialog()->get_visible(); return m_rWindow->IsVisible(); // references can only be input to visible windows } @@ -924,11 +1058,21 @@ void ScRefHandler::RefInputStart( formula::RefEdit* pEdit, formula::RefButton* p m_aHelper.RefInputStart( pEdit, pButton ); } +void ScRefHandler::RefInputStart( formula::WeldRefEdit* pEdit, formula::WeldRefButton* pButton ) +{ + m_aHelper.RefInputStart( pEdit, pButton ); +} + void ScRefHandler::ToggleCollapsed( formula::RefEdit* pEdit, formula::RefButton* pButton ) { m_aHelper.ToggleCollapsed( pEdit, pButton ); } +void ScRefHandler::ToggleCollapsed( formula::WeldRefEdit* pEdit, formula::WeldRefButton* pButton ) +{ + m_aHelper.ToggleCollapsed( pEdit, pButton ); +} + bool ScRefHandler::ParseWithNames( ScRangeList& rRanges, const OUString& rStr, const ScDocument* pDoc ) { return m_aHelper.ParseWithNames( rRanges, rStr, pDoc ); @@ -949,6 +1093,11 @@ void ScRefHandler::ReleaseFocus( formula::RefEdit* pEdit ) m_aHelper.ReleaseFocus( pEdit ); } +void ScRefHandler::ReleaseFocus( formula::WeldRefEdit* pEdit ) +{ + m_aHelper.ReleaseFocus( pEdit ); +} + void ScRefHandler::RefInputDone( bool bForced ) { m_aHelper.RefInputDone( bForced ); diff --git a/sc/source/ui/view/tabvwshc.cxx b/sc/source/ui/view/tabvwshc.cxx index 649af1829361..c826234e3da0 100644 --- a/sc/source/ui/view/tabvwshc.cxx +++ b/sc/source/ui/view/tabvwshc.cxx @@ -348,12 +348,6 @@ VclPtr<SfxModelessDialog> ScTabViewShell::CreateRefDialog( } break; - case SID_CORRELATION_DIALOG: - { - pResult = VclPtr<ScCorrelationDialog>::Create( pB, pCW, pParent, &GetViewData() ); - } - break; - case SID_COVARIANCE_DIALOG: { pResult = VclPtr<ScCovarianceDialog>::Create( pB, pCW, pParent, &GetViewData() ); @@ -512,6 +506,45 @@ VclPtr<SfxModelessDialog> ScTabViewShell::CreateRefDialog( return pResult; } +std::unique_ptr<SfxModelessDialogController> ScTabViewShell::CreateRefDialogController( + SfxBindings* pB, SfxChildWindow* pCW, + const SfxChildWinInfo* pInfo, + weld::Window* pParent, sal_uInt16 nSlotId) +{ + // only open dialog when called through ScModule::SetRefDialog, + // so that it does not re appear for instance after a crash (#42341#). + + if ( SC_MOD()->GetCurRefDlgId() != nSlotId ) + return nullptr; + + if ( nCurRefDlgId != nSlotId ) + { + // the dialog has been opened in a different view + // -> lock the dispatcher for this view (modal mode) + + GetViewData().GetDispatcher().Lock( true ); // lock is reset when closing dialog + return nullptr; + } + + std::unique_ptr<SfxModelessDialogController> xResult; + + if(pCW) + pCW->SetHideNotDelete(true); + + switch( nSlotId ) + { + case SID_CORRELATION_DIALOG: + { + xResult.reset(new ScCorrelationDialog(pB, pCW, pParent, &GetViewData())); + } + break; + } + + if (xResult) + xResult->Initialize( pInfo ); + return xResult; +} + int ScTabViewShell::getPart() const { return GetViewData().GetTabNo(); diff --git a/sc/uiconfig/scalc/ui/correlationdialog.ui b/sc/uiconfig/scalc/ui/correlationdialog.ui index 378875bec5ec..7fff92fa924d 100644 --- a/sc/uiconfig/scalc/ui/correlationdialog.ui +++ b/sc/uiconfig/scalc/ui/correlationdialog.ui @@ -1,14 +1,16 @@ <?xml version="1.0" encoding="UTF-8"?> -<!-- Generated with glade 3.18.3 --> +<!-- Generated with glade 3.22.1 --> <interface domain="sc"> <requires lib="gtk+" version="3.18"/> - <requires lib="LibreOffice" version="1.0"/> <object class="GtkDialog" id="CorrelationDialog"> <property name="can_focus">False</property> <property name="border_width">6</property> <property name="title" translatable="yes" context="correlationdialog|CorrelationDialog">Correlation</property> <property name="resizable">False</property> <property name="type_hint">dialog</property> + <child> + <placeholder/> + </child> <child internal-child="vbox"> <object class="GtkBox" id="dialog-vbox1"> <property name="can_focus">False</property> @@ -96,10 +98,10 @@ <object class="GtkLabel" id="input-range-label"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes" context="correlationdialog|input-range-label">Input range:</property> <property name="use_underline">True</property> <property name="mnemonic_widget">input-range-edit</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -110,10 +112,10 @@ <object class="GtkLabel" id="output-range-label"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes" context="correlationdialog|output-range-label">Results to:</property> <property name="use_underline">True</property> <property name="mnemonic_widget">output-range-edit</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -121,7 +123,7 @@ </packing> </child> <child> - <object class="foruilo-RefEdit" id="input-range-edit"> + <object class="GtkEntry" id="input-range-edit"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="valign">center</property> @@ -134,7 +136,7 @@ </packing> </child> <child> - <object class="foruilo-RefEdit" id="output-range-edit"> + <object class="GtkEntry" id="output-range-edit"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="valign">center</property> @@ -147,7 +149,7 @@ </packing> </child> <child> - <object class="foruilo-RefButton" id="input-range-button"> + <object class="GtkButton" id="input-range-button"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> @@ -158,7 +160,7 @@ </packing> </child> <child> - <object class="foruilo-RefButton" id="output-range-button"> + <object class="GtkButton" id="output-range-button"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> @@ -266,6 +268,7 @@ </child> <action-widgets> <action-widget response="-5">ok</action-widget> + <action-widget response="-6">cancel</action-widget> <action-widget response="-11">help</action-widget> </action-widgets> </object> diff --git a/solenv/sanitizers/ui/modules/scalc.suppr b/solenv/sanitizers/ui/modules/scalc.suppr index f15bbf423067..c3ae37462c58 100644 --- a/solenv/sanitizers/ui/modules/scalc.suppr +++ b/solenv/sanitizers/ui/modules/scalc.suppr @@ -31,6 +31,8 @@ sc/uiconfig/scalc/ui/conflictsdialog.ui://GtkLabel[@id='label1'] orphan-label sc/uiconfig/scalc/ui/conflictsdialog.ui://svtlo-SvSimpleTableContainer[@id='container:border'] no-labelled-by sc/uiconfig/scalc/ui/consolidatedialog.ui://foruilo-RefEdit[@id='eddataarea'] no-labelled-by sc/uiconfig/scalc/ui/consolidatedialog.ui://foruilo-RefEdit[@id='eddestarea'] no-labelled-by +sc/uiconfig/scalc/ui/correlationdialog.ui://GtkButton[@id='input-range-button'] button-no-label +sc/uiconfig/scalc/ui/correlationdialog.ui://GtkButton[@id='output-range-button'] button-no-label sc/uiconfig/scalc/ui/dapiservicedialog.ui://GtkLabel[@id='label2'] orphan-label sc/uiconfig/scalc/ui/dapiservicedialog.ui://GtkLabel[@id='label3'] orphan-label sc/uiconfig/scalc/ui/dapiservicedialog.ui://GtkLabel[@id='label4'] orphan-label diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx index 0926dac611fb..74716b18aa35 100644 --- a/vcl/source/app/salvtables.cxx +++ b/vcl/source/app/salvtables.cxx @@ -1016,15 +1016,48 @@ IMPL_LINK_NOARG(SalInstanceWindow, HelpHdl, vcl::Window&, bool) return false; } +typedef std::set<VclPtr<vcl::Window> > winset; + +namespace +{ + void hideUnless(const vcl::Window *pTop, const winset& rVisibleWidgets, + std::vector<VclPtr<vcl::Window> > &rWasVisibleWidgets) + { + for (vcl::Window* pChild = pTop->GetWindow(GetWindowType::FirstChild); pChild; + pChild = pChild->GetWindow(GetWindowType::Next)) + { + if (!pChild->IsVisible()) + continue; + if (rVisibleWidgets.find(pChild) == rVisibleWidgets.end()) + { + rWasVisibleWidgets.emplace_back(pChild); + pChild->Hide(); + } + else if (isContainerWindow(pChild)) + { + hideUnless(pChild, rVisibleWidgets, rWasVisibleWidgets); + } + } + } +} + class SalInstanceDialog : public SalInstanceWindow, public virtual weld::Dialog { private: VclPtr<::Dialog> m_xDialog; + // for calc ref dialog that shrink to range selection widgets and resize back + VclPtr<vcl::Window> m_xRefEdit; + std::vector<VclPtr<vcl::Window> > m_aHiddenWidgets; // vector of hidden Controls + long m_nOldEditWidthReq; // Original width request of the input field + sal_Int32 m_nOldBorderWidth; // border width for expanded dialog + public: SalInstanceDialog(::Dialog* pDialog, SalInstanceBuilder* pBuilder, bool bTakeOwnership) : SalInstanceWindow(pDialog, pBuilder, bTakeOwnership) , m_xDialog(pDialog) + , m_nOldEditWidthReq(0) + , m_nOldBorderWidth(0) { } @@ -1044,6 +1077,67 @@ public: return m_xDialog->StartExecuteAsync(aCtx); } + virtual void collapse(weld::Widget* pEdit, weld::Widget* pButton) override + { + SalInstanceWidget* pVclEdit = dynamic_cast<SalInstanceWidget*>(pEdit); + SalInstanceWidget* pVclButton = dynamic_cast<SalInstanceWidget*>(pButton); + + vcl::Window* pRefEdit = pVclEdit->getWidget(); + vcl::Window* pRefBtn = pVclButton ? pVclButton->getWidget() : nullptr; + + auto nOldEditWidth = pRefEdit->GetSizePixel().Width(); + m_nOldEditWidthReq = pRefEdit->get_width_request(); + + //We want just pRefBtn and pRefEdit to be shown + //mark widgets we want to be visible, starting with pRefEdit + //and all its direct parents. + winset aVisibleWidgets; + vcl::Window *pContentArea = m_xDialog->get_content_area(); + for (vcl::Window *pCandidate = pRefEdit; + pCandidate && (pCandidate != pContentArea && pCandidate->IsVisible()); + pCandidate = pCandidate->GetWindow(GetWindowType::RealParent)) + { + aVisibleWidgets.insert(pCandidate); + } + //same again with pRefBtn, except stop if there's a + //shared parent in the existing widgets + for (vcl::Window *pCandidate = pRefBtn; + pCandidate && (pCandidate != pContentArea && pCandidate->IsVisible()); + pCandidate = pCandidate->GetWindow(GetWindowType::RealParent)) + { + if (aVisibleWidgets.insert(pCandidate).second) + break; + } + + //hide everything except the aVisibleWidgets + hideUnless(pContentArea, aVisibleWidgets, m_aHiddenWidgets); + + pRefEdit->set_width_request(nOldEditWidth); + m_nOldBorderWidth = m_xDialog->get_border_width(); + m_xDialog->set_border_width(0); + if (vcl::Window *pActionArea = m_xDialog->get_action_area()) + pActionArea->Hide(); + m_xDialog->setOptimalLayoutSize(); + m_xRefEdit = pRefEdit; + } + + virtual void undo_collapse() override + { + // All others: Show(); + for (VclPtr<vcl::Window> const & pWindow : m_aHiddenWidgets) + { + pWindow->Show(); + } + m_aHiddenWidgets.clear(); + + m_xRefEdit->set_width_request(m_nOldEditWidthReq); + m_xRefEdit.clear(); + m_xDialog->set_border_width(m_nOldBorderWidth); + if (vcl::Window *pActionArea = m_xDialog->get_action_area()) + pActionArea->Show(); + m_xDialog->setOptimalLayoutSize(); + } + virtual void SetInstallLOKNotifierHdl(const Link<void*, vcl::ILibreOfficeKitNotifier*>& rLink) override { m_xDialog->SetInstallLOKNotifierHdl(rLink); diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx index 7f294bae8c21..f7d138f5f538 100644 --- a/vcl/unx/gtk3/gtk3gtkinst.cxx +++ b/vcl/unx/gtk3/gtk3gtkinst.cxx @@ -2761,6 +2761,34 @@ struct DialogRunner } }; +typedef std::set<GtkWidget*> winset; + +namespace +{ + void hideUnless(GtkContainer *pTop, const winset& rVisibleWidgets, + std::vector<GtkWidget*> &rWasVisibleWidgets) + { + GList* pChildren = gtk_container_get_children(pTop); + for (GList* pEntry = g_list_first(pChildren); pEntry; pEntry = g_list_next(pEntry)) + { + GtkWidget* pChild = static_cast<GtkWidget*>(pEntry->data); + if (!gtk_widget_get_visible(pChild)) + continue; + if (rVisibleWidgets.find(pChild) == rVisibleWidgets.end()) + { + g_object_ref(pChild); + rWasVisibleWidgets.emplace_back(pChild); + gtk_widget_hide(pChild); + } + else if (GTK_IS_CONTAINER(pChild)) + { + hideUnless(GTK_CONTAINER(pChild), rVisibleWidgets, rWasVisibleWidgets); + } + } + g_list_free(pChildren); + } +} + class GtkInstanceDialog : public GtkInstanceWindow, public virtual weld::Dialog { private: @@ -2773,6 +2801,13 @@ private: gulong m_nCloseSignalId; gulong m_nResponseSignalId; + // for calc ref dialog that shrink to range selection widgets and resize back + GtkWidget* m_pRefEdit; + std::vector<GtkWidget*> m_aHiddenWidgets; // vector of hidden Controls + int m_nOldEditWidth; // Original width of the input field + int m_nOldEditWidthReq; // Original width request of the input field + int m_nOldBorderWidth; // border width for expanded dialog + static void signalClose(GtkWidget*, gpointer widget) { GtkInstanceDialog* pThis = static_cast<GtkInstanceDialog*>(widget); @@ -2828,6 +2863,10 @@ public: , m_aDialogRun(pDialog) , m_nCloseSignalId(g_signal_connect(m_pDialog, "close", G_CALLBACK(signalClose), this)) , m_nResponseSignalId(0) + , m_pRefEdit(nullptr) + , m_nOldEditWidth(0) + , m_nOldEditWidthReq(0) + , m_nOldBorderWidth(0) { } @@ -2948,6 +2987,69 @@ public: return new GtkInstanceContainer(GTK_CONTAINER(gtk_dialog_get_content_area(m_pDialog)), m_pBuilder, false); } + virtual void collapse(weld::Widget* pEdit, weld::Widget* pButton) override + { + GtkInstanceWidget* pVclEdit = dynamic_cast<GtkInstanceWidget*>(pEdit); + GtkInstanceWidget* pVclButton = dynamic_cast<GtkInstanceWidget*>(pButton); + + GtkWidget* pRefEdit = pVclEdit->getWidget(); + GtkWidget* pRefBtn = pVclButton ? pVclButton->getWidget() : nullptr; + + m_nOldEditWidth = gtk_widget_get_allocated_width(pRefEdit); + + gtk_widget_get_size_request(pRefEdit, &m_nOldEditWidthReq, nullptr); + + //We want just pRefBtn and pRefEdit to be shown + //mark widgets we want to be visible, starting with pRefEdit + //and all its direct parents. + winset aVisibleWidgets; + GtkWidget *pContentArea = gtk_dialog_get_content_area(m_pDialog); + for (GtkWidget *pCandidate = pRefEdit; + pCandidate && pCandidate != pContentArea && gtk_widget_get_visible(pCandidate); + pCandidate = gtk_widget_get_parent(pCandidate)) + { + aVisibleWidgets.insert(pCandidate); + } + //same again with pRefBtn, except stop if there's a + //shared parent in the existing widgets + for (GtkWidget *pCandidate = pRefBtn; + pCandidate && pCandidate != pContentArea && gtk_widget_get_visible(pCandidate); + pCandidate = gtk_widget_get_parent(pCandidate)) + { + if (aVisibleWidgets.insert(pCandidate).second) + break; + } + + //hide everything except the aVisibleWidgets + hideUnless(GTK_CONTAINER(pContentArea), aVisibleWidgets, m_aHiddenWidgets); + + gtk_widget_set_size_request(pRefEdit, m_nOldEditWidth, -1); + m_nOldBorderWidth = gtk_container_get_border_width(GTK_CONTAINER(m_pDialog)); + gtk_container_set_border_width(GTK_CONTAINER(m_pDialog), 0); + if (GtkWidget* pActionArea = gtk_dialog_get_action_area(m_pDialog)) + gtk_widget_hide(pActionArea); + resize_to_request(); + m_pRefEdit = pRefEdit; + } + + virtual void undo_collapse() override + { + // All others: Show(); + for (GtkWidget* pWindow : m_aHiddenWidgets) + { + gtk_widget_show(pWindow); + g_object_unref(pWindow); + } + m_aHiddenWidgets.clear(); + + gtk_widget_set_size_request(m_pRefEdit, m_nOldEditWidthReq, -1); + m_pRefEdit = nullptr; + gtk_container_set_border_width(GTK_CONTAINER(m_pDialog), m_nOldBorderWidth); + if (GtkWidget* pActionArea = gtk_dialog_get_action_area(m_pDialog)) + gtk_widget_show(pActionArea); + resize_to_request(); + } + virtual void SetInstallLOKNotifierHdl(const Link<void*, vcl::ILibreOfficeKitNotifier*>&) override { //not implemented for the gtk variant @@ -2955,6 +3057,13 @@ public: virtual ~GtkInstanceDialog() override { + if (!m_aHiddenWidgets.empty()) + { + for (GtkWidget* pWindow : m_aHiddenWidgets) + g_object_unref(pWindow); + m_aHiddenWidgets.clear(); + } + g_signal_handler_disconnect(m_pDialog, m_nCloseSignalId); if (m_nResponseSignalId) g_signal_handler_disconnect(m_pDialog, m_nResponseSignalId); |