From 940b4d1848e8c70ab7642901a68594e8016caffc Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 27 Apr 2024 18:51:28 +0200 Subject: Adding upstream version 1:7.0.4. Signed-off-by: Daniel Baumann --- cui/source/customize/CommandCategoryListBox.cxx | 581 ++++ .../customize/CustomNotebookbarGenerator.cxx | 284 ++ cui/source/customize/SvxConfigPageHelper.cxx | 471 +++ cui/source/customize/SvxMenuConfigPage.cxx | 600 ++++ cui/source/customize/SvxNotebookbarConfigPage.cxx | 567 ++++ cui/source/customize/SvxToolbarConfigPage.cxx | 966 ++++++ cui/source/customize/acccfg.cxx | 1593 ++++++++++ cui/source/customize/cfg.cxx | 3201 +++++++++++++++++++ cui/source/customize/cfgutil.cxx | 1195 +++++++ cui/source/customize/eventdlg.cxx | 162 + cui/source/customize/eventdlg.hxx | 52 + cui/source/customize/macropg.cxx | 668 ++++ cui/source/customize/macropg_impl.hxx | 55 + cui/source/dialogs/DiagramDialog.cxx | 81 + cui/source/dialogs/FontFeaturesDialog.cxx | 227 ++ cui/source/dialogs/QrCodeGenDialog.cxx | 341 ++ cui/source/dialogs/SignSignatureLineDialog.cxx | 293 ++ cui/source/dialogs/SignatureLineDialog.cxx | 210 ++ cui/source/dialogs/SignatureLineDialogBase.cxx | 221 ++ cui/source/dialogs/SpellAttrib.hxx | 118 + cui/source/dialogs/SpellDialog.cxx | 2092 ++++++++++++ cui/source/dialogs/about.cxx | 260 ++ cui/source/dialogs/colorpicker.cxx | 1334 ++++++++ cui/source/dialogs/cuicharmap.cxx | 1250 ++++++++ cui/source/dialogs/cuifmsearch.cxx | 754 +++++ cui/source/dialogs/cuigaldlg.cxx | 1011 ++++++ cui/source/dialogs/cuigrfflt.cxx | 468 +++ cui/source/dialogs/cuihyperdlg.cxx | 293 ++ cui/source/dialogs/cuiimapwnd.cxx | 59 + cui/source/dialogs/cuitbxform.cxx | 33 + cui/source/dialogs/dlgname.cxx | 104 + cui/source/dialogs/hangulhanjadlg.cxx | 1505 +++++++++ cui/source/dialogs/hldocntp.cxx | 479 +++ cui/source/dialogs/hldoctp.cxx | 318 ++ cui/source/dialogs/hlinettp.cxx | 393 +++ cui/source/dialogs/hlmailtp.cxx | 228 ++ cui/source/dialogs/hlmarkwn.cxx | 473 +++ cui/source/dialogs/hltpbase.cxx | 545 ++++ cui/source/dialogs/hyphen.cxx | 471 +++ cui/source/dialogs/iconcdlg.cxx | 311 ++ cui/source/dialogs/insdlg.cxx | 583 ++++ cui/source/dialogs/insrc.cxx | 59 + cui/source/dialogs/linkdlg.cxx | 636 ++++ cui/source/dialogs/multipat.cxx | 320 ++ cui/source/dialogs/newtabledlg.cxx | 39 + cui/source/dialogs/passwdomdlg.cxx | 171 + cui/source/dialogs/pastedlg.cxx | 339 ++ cui/source/dialogs/postdlg.cxx | 180 ++ cui/source/dialogs/screenshotannotationdlg.cxx | 583 ++++ cui/source/dialogs/scriptdlg.cxx | 1351 ++++++++ cui/source/dialogs/sdrcelldlg.cxx | 62 + cui/source/dialogs/showcols.cxx | 107 + cui/source/dialogs/splitcelldlg.cxx | 88 + cui/source/dialogs/srchxtra.cxx | 235 ++ cui/source/dialogs/thesdlg.cxx | 343 ++ cui/source/dialogs/tipofthedaydlg.cxx | 168 + cui/source/dialogs/zoom.cxx | 406 +++ cui/source/factory/cuiexp.cxx | 40 + cui/source/factory/cuiresmgr.cxx | 28 + cui/source/factory/dlgfact.cxx | 1699 ++++++++++ cui/source/factory/dlgfact.hxx | 981 ++++++ cui/source/factory/init.cxx | 44 + cui/source/inc/CommandCategoryListBox.hxx | 80 + cui/source/inc/CustomNotebookbarGenerator.hxx | 42 + cui/source/inc/DiagramDialog.hxx | 42 + cui/source/inc/FontFeaturesDialog.hxx | 78 + cui/source/inc/QrCodeGenDialog.hxx | 50 + cui/source/inc/SignSignatureLineDialog.hxx | 56 + cui/source/inc/SignatureLineDialog.hxx | 39 + cui/source/inc/SignatureLineDialogBase.hxx | 34 + cui/source/inc/SpellDialog.hxx | 231 ++ cui/source/inc/SvxConfigPageHelper.hxx | 89 + cui/source/inc/SvxMenuConfigPage.hxx | 72 + cui/source/inc/SvxNotebookbarConfigPage.hxx | 87 + cui/source/inc/SvxToolbarConfigPage.hxx | 90 + cui/source/inc/about.hxx | 62 + cui/source/inc/acccfg.hxx | 155 + cui/source/inc/align.hxx | 122 + cui/source/inc/autocdlg.hxx | 417 +++ cui/source/inc/backgrnd.hxx | 70 + cui/source/inc/bbdlg.hxx | 44 + cui/source/inc/border.hxx | 194 ++ cui/source/inc/cfg.hxx | 673 ++++ cui/source/inc/cfgutil.hxx | 269 ++ cui/source/inc/chardlg.hxx | 343 ++ cui/source/inc/colorpicker.hxx | 47 + cui/source/inc/connect.hxx | 86 + cui/source/inc/cuifmsearch.hxx | 173 + cui/source/inc/cuigaldlg.hxx | 277 ++ cui/source/inc/cuigrfflt.hxx | 183 ++ cui/source/inc/cuihyperdlg.hxx | 140 + cui/source/inc/cuiimapwnd.hxx | 50 + cui/source/inc/cuioptgenrl.hxx | 75 + cui/source/inc/cuisrchdlg.hxx | 44 + cui/source/inc/cuitabarea.hxx | 739 +++++ cui/source/inc/cuitabline.hxx | 378 +++ cui/source/inc/cuitbxform.hxx | 38 + cui/source/inc/dbregister.hxx | 112 + cui/source/inc/defdlgname.hxx | 30 + cui/source/inc/dialmgr.hxx | 26 + cui/source/inc/dlgname.hxx | 125 + cui/source/inc/dstribut.hxx | 72 + cui/source/inc/grfpage.hxx | 109 + cui/source/inc/hangulhanjadlg.hxx | 305 ++ cui/source/inc/headertablistbox.hxx | 42 + cui/source/inc/helpids.h | 46 + cui/source/inc/hldocntp.hxx | 64 + cui/source/inc/hldoctp.hxx | 76 + cui/source/inc/hlinettp.hxx | 91 + cui/source/inc/hlmailtp.hxx | 65 + cui/source/inc/hlmarkwn.hxx | 72 + cui/source/inc/hlmarkwn_def.hxx | 29 + cui/source/inc/hltpbase.hxx | 138 + cui/source/inc/hyphen.hxx | 88 + cui/source/inc/iconcdlg.hxx | 84 + cui/source/inc/insdlg.hxx | 117 + cui/source/inc/insrc.hxx | 44 + cui/source/inc/labdlg.hxx | 119 + cui/source/inc/linkdlg.hxx | 85 + cui/source/inc/macroass.hxx | 92 + cui/source/inc/macropg.hxx | 131 + cui/source/inc/measure.hxx | 98 + cui/source/inc/multipat.hxx | 80 + cui/source/inc/newtabledlg.hxx | 75 + cui/source/inc/numfmt.hxx | 157 + cui/source/inc/numpages.hxx | 388 +++ cui/source/inc/optasian.hxx | 61 + cui/source/inc/optdict.hxx | 112 + cui/source/inc/optlingu.hxx | 152 + cui/source/inc/optpath.hxx | 71 + cui/source/inc/page.hxx | 185 ++ cui/source/inc/paragrph.hxx | 304 ++ cui/source/inc/passwdomdlg.hxx | 71 + cui/source/inc/pastedlg.hxx | 76 + cui/source/inc/postdlg.hxx | 103 + cui/source/inc/screenshotannotationdlg.hxx | 42 + cui/source/inc/scriptdlg.hxx | 171 + cui/source/inc/sdrcelldlg.hxx | 49 + cui/source/inc/showcols.hxx | 48 + cui/source/inc/splitcelldlg.hxx | 51 + cui/source/inc/srchxtra.hxx | 84 + cui/source/inc/swpossizetabpage.hxx | 133 + cui/source/inc/tabstpge.hxx | 149 + cui/source/inc/textanim.hxx | 108 + cui/source/inc/textattr.hxx | 95 + cui/source/inc/thesdlg.hxx | 82 + cui/source/inc/tipofthedaydlg.hxx | 48 + cui/source/inc/transfrm.hxx | 251 ++ cui/source/inc/treeopt.hxx | 238 ++ cui/source/inc/zoom.hxx | 70 + cui/source/options/certpath.cxx | 240 ++ cui/source/options/certpath.hxx | 39 + cui/source/options/cfgchart.cxx | 279 ++ cui/source/options/cfgchart.hxx | 100 + cui/source/options/connpoolconfig.cxx | 196 ++ cui/source/options/connpoolconfig.hxx | 38 + cui/source/options/connpooloptions.cxx | 261 ++ cui/source/options/connpooloptions.hxx | 71 + cui/source/options/connpoolsettings.cxx | 82 + cui/source/options/connpoolsettings.hxx | 86 + cui/source/options/cuisrchdlg.cxx | 50 + cui/source/options/dbregister.cxx | 304 ++ cui/source/options/dbregisterednamesconfig.cxx | 122 + cui/source/options/dbregisterednamesconfig.hxx | 38 + cui/source/options/dbregistersettings.cxx | 55 + cui/source/options/dbregistersettings.hxx | 79 + cui/source/options/doclinkdialog.cxx | 199 ++ cui/source/options/doclinkdialog.hxx | 61 + cui/source/options/fontsubs.cxx | 415 +++ cui/source/options/fontsubs.hxx | 61 + cui/source/options/optaboutconfig.cxx | 932 ++++++ cui/source/options/optaboutconfig.hxx | 95 + cui/source/options/optaccessibility.cxx | 111 + cui/source/options/optaccessibility.hxx | 42 + cui/source/options/optasian.cxx | 384 +++ cui/source/options/optbasic.cxx | 131 + cui/source/options/optbasic.hxx | 50 + cui/source/options/optchart.cxx | 275 ++ cui/source/options/optchart.hxx | 82 + cui/source/options/optcolor.cxx | 888 ++++++ cui/source/options/optcolor.hxx | 63 + cui/source/options/optctl.cxx | 146 + cui/source/options/optctl.hxx | 48 + cui/source/options/optdict.cxx | 773 +++++ cui/source/options/optfltr.cxx | 344 ++ cui/source/options/optfltr.hxx | 83 + cui/source/options/optgdlg.cxx | 1897 +++++++++++ cui/source/options/optgdlg.hxx | 185 ++ cui/source/options/optgenrl.cxx | 508 +++ cui/source/options/opthtml.cxx | 164 + cui/source/options/opthtml.hxx | 63 + cui/source/options/optinet2.cxx | 936 ++++++ cui/source/options/optinet2.hxx | 163 + cui/source/options/optjava.cxx | 941 ++++++ cui/source/options/optjava.hxx | 206 ++ cui/source/options/optjsearch.cxx | 358 +++ cui/source/options/optjsearch.hxx | 71 + cui/source/options/optlingu.cxx | 1971 ++++++++++++ cui/source/options/optopencl.cxx | 88 + cui/source/options/optopencl.hxx | 42 + cui/source/options/optpath.cxx | 686 ++++ cui/source/options/optsave.cxx | 619 ++++ cui/source/options/optsave.hxx | 78 + cui/source/options/optupdt.cxx | 396 +++ cui/source/options/optupdt.hxx | 72 + cui/source/options/personalization.cxx | 177 ++ cui/source/options/personalization.hxx | 65 + cui/source/options/sdbcdriverenum.cxx | 98 + cui/source/options/sdbcdriverenum.hxx | 54 + cui/source/options/securityoptions.cxx | 82 + cui/source/options/securityoptions.hxx | 63 + cui/source/options/treeopt.cxx | 2104 ++++++++++++ cui/source/options/tsaurls.cxx | 126 + cui/source/options/tsaurls.hxx | 44 + cui/source/options/webconninfo.cxx | 227 ++ cui/source/options/webconninfo.hxx | 54 + cui/source/tabpages/align.cxx | 774 +++++ cui/source/tabpages/autocdlg.cxx | 2355 ++++++++++++++ cui/source/tabpages/backgrnd.cxx | 343 ++ cui/source/tabpages/bbdlg.cxx | 90 + cui/source/tabpages/border.cxx | 1522 +++++++++ cui/source/tabpages/chardlg.cxx | 3261 +++++++++++++++++++ cui/source/tabpages/chardlg.h | 29 + cui/source/tabpages/connect.cxx | 419 +++ cui/source/tabpages/dstribut.cxx | 152 + cui/source/tabpages/grfpage.cxx | 785 +++++ cui/source/tabpages/labdlg.cxx | 514 +++ cui/source/tabpages/macroass.cxx | 389 +++ cui/source/tabpages/measure.cxx | 754 +++++ cui/source/tabpages/numfmt.cxx | 1767 +++++++++++ cui/source/tabpages/numpages.cxx | 3354 ++++++++++++++++++++ cui/source/tabpages/page.cxx | 1554 +++++++++ cui/source/tabpages/paragrph.cxx | 2311 ++++++++++++++ cui/source/tabpages/swpossizetabpage.cxx | 1891 +++++++++++ cui/source/tabpages/tabarea.cxx | 248 ++ cui/source/tabpages/tabline.cxx | 207 ++ cui/source/tabpages/tabstpge.cxx | 667 ++++ cui/source/tabpages/textanim.cxx | 536 ++++ cui/source/tabpages/textattr.cxx | 668 ++++ cui/source/tabpages/tparea.cxx | 465 +++ cui/source/tabpages/tpbitmap.cxx | 825 +++++ cui/source/tabpages/tpcolor.cxx | 747 +++++ cui/source/tabpages/tpgradnt.cxx | 630 ++++ cui/source/tabpages/tphatch.cxx | 558 ++++ cui/source/tabpages/tpline.cxx | 1689 ++++++++++ cui/source/tabpages/tplnedef.cxx | 839 +++++ cui/source/tabpages/tplneend.cxx | 609 ++++ cui/source/tabpages/tppattern.cxx | 554 ++++ cui/source/tabpages/tpshadow.cxx | 495 +++ cui/source/tabpages/tptrans.cxx | 524 +++ cui/source/tabpages/transfrm.cxx | 1584 +++++++++ cui/source/uno/services.cxx | 41 + 252 files changed, 97923 insertions(+) create mode 100644 cui/source/customize/CommandCategoryListBox.cxx create mode 100644 cui/source/customize/CustomNotebookbarGenerator.cxx create mode 100644 cui/source/customize/SvxConfigPageHelper.cxx create mode 100644 cui/source/customize/SvxMenuConfigPage.cxx create mode 100644 cui/source/customize/SvxNotebookbarConfigPage.cxx create mode 100644 cui/source/customize/SvxToolbarConfigPage.cxx create mode 100644 cui/source/customize/acccfg.cxx create mode 100644 cui/source/customize/cfg.cxx create mode 100644 cui/source/customize/cfgutil.cxx create mode 100644 cui/source/customize/eventdlg.cxx create mode 100644 cui/source/customize/eventdlg.hxx create mode 100644 cui/source/customize/macropg.cxx create mode 100644 cui/source/customize/macropg_impl.hxx create mode 100644 cui/source/dialogs/DiagramDialog.cxx create mode 100644 cui/source/dialogs/FontFeaturesDialog.cxx create mode 100644 cui/source/dialogs/QrCodeGenDialog.cxx create mode 100644 cui/source/dialogs/SignSignatureLineDialog.cxx create mode 100644 cui/source/dialogs/SignatureLineDialog.cxx create mode 100644 cui/source/dialogs/SignatureLineDialogBase.cxx create mode 100644 cui/source/dialogs/SpellAttrib.hxx create mode 100644 cui/source/dialogs/SpellDialog.cxx create mode 100644 cui/source/dialogs/about.cxx create mode 100644 cui/source/dialogs/colorpicker.cxx create mode 100644 cui/source/dialogs/cuicharmap.cxx create mode 100644 cui/source/dialogs/cuifmsearch.cxx create mode 100644 cui/source/dialogs/cuigaldlg.cxx create mode 100644 cui/source/dialogs/cuigrfflt.cxx create mode 100644 cui/source/dialogs/cuihyperdlg.cxx create mode 100644 cui/source/dialogs/cuiimapwnd.cxx create mode 100644 cui/source/dialogs/cuitbxform.cxx create mode 100644 cui/source/dialogs/dlgname.cxx create mode 100644 cui/source/dialogs/hangulhanjadlg.cxx create mode 100644 cui/source/dialogs/hldocntp.cxx create mode 100644 cui/source/dialogs/hldoctp.cxx create mode 100644 cui/source/dialogs/hlinettp.cxx create mode 100644 cui/source/dialogs/hlmailtp.cxx create mode 100644 cui/source/dialogs/hlmarkwn.cxx create mode 100644 cui/source/dialogs/hltpbase.cxx create mode 100644 cui/source/dialogs/hyphen.cxx create mode 100644 cui/source/dialogs/iconcdlg.cxx create mode 100644 cui/source/dialogs/insdlg.cxx create mode 100644 cui/source/dialogs/insrc.cxx create mode 100644 cui/source/dialogs/linkdlg.cxx create mode 100644 cui/source/dialogs/multipat.cxx create mode 100644 cui/source/dialogs/newtabledlg.cxx create mode 100644 cui/source/dialogs/passwdomdlg.cxx create mode 100644 cui/source/dialogs/pastedlg.cxx create mode 100644 cui/source/dialogs/postdlg.cxx create mode 100644 cui/source/dialogs/screenshotannotationdlg.cxx create mode 100644 cui/source/dialogs/scriptdlg.cxx create mode 100644 cui/source/dialogs/sdrcelldlg.cxx create mode 100644 cui/source/dialogs/showcols.cxx create mode 100644 cui/source/dialogs/splitcelldlg.cxx create mode 100644 cui/source/dialogs/srchxtra.cxx create mode 100644 cui/source/dialogs/thesdlg.cxx create mode 100644 cui/source/dialogs/tipofthedaydlg.cxx create mode 100644 cui/source/dialogs/zoom.cxx create mode 100644 cui/source/factory/cuiexp.cxx create mode 100644 cui/source/factory/cuiresmgr.cxx create mode 100644 cui/source/factory/dlgfact.cxx create mode 100644 cui/source/factory/dlgfact.hxx create mode 100644 cui/source/factory/init.cxx create mode 100644 cui/source/inc/CommandCategoryListBox.hxx create mode 100644 cui/source/inc/CustomNotebookbarGenerator.hxx create mode 100644 cui/source/inc/DiagramDialog.hxx create mode 100644 cui/source/inc/FontFeaturesDialog.hxx create mode 100644 cui/source/inc/QrCodeGenDialog.hxx create mode 100644 cui/source/inc/SignSignatureLineDialog.hxx create mode 100644 cui/source/inc/SignatureLineDialog.hxx create mode 100644 cui/source/inc/SignatureLineDialogBase.hxx create mode 100644 cui/source/inc/SpellDialog.hxx create mode 100644 cui/source/inc/SvxConfigPageHelper.hxx create mode 100644 cui/source/inc/SvxMenuConfigPage.hxx create mode 100644 cui/source/inc/SvxNotebookbarConfigPage.hxx create mode 100644 cui/source/inc/SvxToolbarConfigPage.hxx create mode 100644 cui/source/inc/about.hxx create mode 100644 cui/source/inc/acccfg.hxx create mode 100644 cui/source/inc/align.hxx create mode 100644 cui/source/inc/autocdlg.hxx create mode 100644 cui/source/inc/backgrnd.hxx create mode 100644 cui/source/inc/bbdlg.hxx create mode 100644 cui/source/inc/border.hxx create mode 100644 cui/source/inc/cfg.hxx create mode 100644 cui/source/inc/cfgutil.hxx create mode 100644 cui/source/inc/chardlg.hxx create mode 100644 cui/source/inc/colorpicker.hxx create mode 100644 cui/source/inc/connect.hxx create mode 100644 cui/source/inc/cuifmsearch.hxx create mode 100644 cui/source/inc/cuigaldlg.hxx create mode 100644 cui/source/inc/cuigrfflt.hxx create mode 100644 cui/source/inc/cuihyperdlg.hxx create mode 100644 cui/source/inc/cuiimapwnd.hxx create mode 100644 cui/source/inc/cuioptgenrl.hxx create mode 100644 cui/source/inc/cuisrchdlg.hxx create mode 100644 cui/source/inc/cuitabarea.hxx create mode 100644 cui/source/inc/cuitabline.hxx create mode 100644 cui/source/inc/cuitbxform.hxx create mode 100644 cui/source/inc/dbregister.hxx create mode 100644 cui/source/inc/defdlgname.hxx create mode 100644 cui/source/inc/dialmgr.hxx create mode 100644 cui/source/inc/dlgname.hxx create mode 100644 cui/source/inc/dstribut.hxx create mode 100644 cui/source/inc/grfpage.hxx create mode 100644 cui/source/inc/hangulhanjadlg.hxx create mode 100644 cui/source/inc/headertablistbox.hxx create mode 100644 cui/source/inc/helpids.h create mode 100644 cui/source/inc/hldocntp.hxx create mode 100644 cui/source/inc/hldoctp.hxx create mode 100644 cui/source/inc/hlinettp.hxx create mode 100644 cui/source/inc/hlmailtp.hxx create mode 100644 cui/source/inc/hlmarkwn.hxx create mode 100644 cui/source/inc/hlmarkwn_def.hxx create mode 100644 cui/source/inc/hltpbase.hxx create mode 100644 cui/source/inc/hyphen.hxx create mode 100644 cui/source/inc/iconcdlg.hxx create mode 100644 cui/source/inc/insdlg.hxx create mode 100644 cui/source/inc/insrc.hxx create mode 100644 cui/source/inc/labdlg.hxx create mode 100644 cui/source/inc/linkdlg.hxx create mode 100644 cui/source/inc/macroass.hxx create mode 100644 cui/source/inc/macropg.hxx create mode 100644 cui/source/inc/measure.hxx create mode 100644 cui/source/inc/multipat.hxx create mode 100644 cui/source/inc/newtabledlg.hxx create mode 100644 cui/source/inc/numfmt.hxx create mode 100644 cui/source/inc/numpages.hxx create mode 100644 cui/source/inc/optasian.hxx create mode 100644 cui/source/inc/optdict.hxx create mode 100644 cui/source/inc/optlingu.hxx create mode 100644 cui/source/inc/optpath.hxx create mode 100644 cui/source/inc/page.hxx create mode 100644 cui/source/inc/paragrph.hxx create mode 100644 cui/source/inc/passwdomdlg.hxx create mode 100644 cui/source/inc/pastedlg.hxx create mode 100644 cui/source/inc/postdlg.hxx create mode 100644 cui/source/inc/screenshotannotationdlg.hxx create mode 100644 cui/source/inc/scriptdlg.hxx create mode 100644 cui/source/inc/sdrcelldlg.hxx create mode 100644 cui/source/inc/showcols.hxx create mode 100644 cui/source/inc/splitcelldlg.hxx create mode 100644 cui/source/inc/srchxtra.hxx create mode 100644 cui/source/inc/swpossizetabpage.hxx create mode 100644 cui/source/inc/tabstpge.hxx create mode 100644 cui/source/inc/textanim.hxx create mode 100644 cui/source/inc/textattr.hxx create mode 100644 cui/source/inc/thesdlg.hxx create mode 100644 cui/source/inc/tipofthedaydlg.hxx create mode 100644 cui/source/inc/transfrm.hxx create mode 100644 cui/source/inc/treeopt.hxx create mode 100644 cui/source/inc/zoom.hxx create mode 100644 cui/source/options/certpath.cxx create mode 100644 cui/source/options/certpath.hxx create mode 100644 cui/source/options/cfgchart.cxx create mode 100644 cui/source/options/cfgchart.hxx create mode 100644 cui/source/options/connpoolconfig.cxx create mode 100644 cui/source/options/connpoolconfig.hxx create mode 100644 cui/source/options/connpooloptions.cxx create mode 100644 cui/source/options/connpooloptions.hxx create mode 100644 cui/source/options/connpoolsettings.cxx create mode 100644 cui/source/options/connpoolsettings.hxx create mode 100644 cui/source/options/cuisrchdlg.cxx create mode 100644 cui/source/options/dbregister.cxx create mode 100644 cui/source/options/dbregisterednamesconfig.cxx create mode 100644 cui/source/options/dbregisterednamesconfig.hxx create mode 100644 cui/source/options/dbregistersettings.cxx create mode 100644 cui/source/options/dbregistersettings.hxx create mode 100644 cui/source/options/doclinkdialog.cxx create mode 100644 cui/source/options/doclinkdialog.hxx create mode 100644 cui/source/options/fontsubs.cxx create mode 100644 cui/source/options/fontsubs.hxx create mode 100644 cui/source/options/optaboutconfig.cxx create mode 100644 cui/source/options/optaboutconfig.hxx create mode 100644 cui/source/options/optaccessibility.cxx create mode 100644 cui/source/options/optaccessibility.hxx create mode 100644 cui/source/options/optasian.cxx create mode 100644 cui/source/options/optbasic.cxx create mode 100644 cui/source/options/optbasic.hxx create mode 100644 cui/source/options/optchart.cxx create mode 100644 cui/source/options/optchart.hxx create mode 100644 cui/source/options/optcolor.cxx create mode 100644 cui/source/options/optcolor.hxx create mode 100644 cui/source/options/optctl.cxx create mode 100644 cui/source/options/optctl.hxx create mode 100644 cui/source/options/optdict.cxx create mode 100644 cui/source/options/optfltr.cxx create mode 100644 cui/source/options/optfltr.hxx create mode 100644 cui/source/options/optgdlg.cxx create mode 100644 cui/source/options/optgdlg.hxx create mode 100644 cui/source/options/optgenrl.cxx create mode 100644 cui/source/options/opthtml.cxx create mode 100644 cui/source/options/opthtml.hxx create mode 100644 cui/source/options/optinet2.cxx create mode 100644 cui/source/options/optinet2.hxx create mode 100644 cui/source/options/optjava.cxx create mode 100644 cui/source/options/optjava.hxx create mode 100644 cui/source/options/optjsearch.cxx create mode 100644 cui/source/options/optjsearch.hxx create mode 100644 cui/source/options/optlingu.cxx create mode 100644 cui/source/options/optopencl.cxx create mode 100644 cui/source/options/optopencl.hxx create mode 100644 cui/source/options/optpath.cxx create mode 100644 cui/source/options/optsave.cxx create mode 100644 cui/source/options/optsave.hxx create mode 100644 cui/source/options/optupdt.cxx create mode 100644 cui/source/options/optupdt.hxx create mode 100644 cui/source/options/personalization.cxx create mode 100644 cui/source/options/personalization.hxx create mode 100644 cui/source/options/sdbcdriverenum.cxx create mode 100644 cui/source/options/sdbcdriverenum.hxx create mode 100644 cui/source/options/securityoptions.cxx create mode 100644 cui/source/options/securityoptions.hxx create mode 100644 cui/source/options/treeopt.cxx create mode 100644 cui/source/options/tsaurls.cxx create mode 100644 cui/source/options/tsaurls.hxx create mode 100644 cui/source/options/webconninfo.cxx create mode 100644 cui/source/options/webconninfo.hxx create mode 100644 cui/source/tabpages/align.cxx create mode 100644 cui/source/tabpages/autocdlg.cxx create mode 100644 cui/source/tabpages/backgrnd.cxx create mode 100644 cui/source/tabpages/bbdlg.cxx create mode 100644 cui/source/tabpages/border.cxx create mode 100644 cui/source/tabpages/chardlg.cxx create mode 100644 cui/source/tabpages/chardlg.h create mode 100644 cui/source/tabpages/connect.cxx create mode 100644 cui/source/tabpages/dstribut.cxx create mode 100644 cui/source/tabpages/grfpage.cxx create mode 100644 cui/source/tabpages/labdlg.cxx create mode 100644 cui/source/tabpages/macroass.cxx create mode 100644 cui/source/tabpages/measure.cxx create mode 100644 cui/source/tabpages/numfmt.cxx create mode 100644 cui/source/tabpages/numpages.cxx create mode 100644 cui/source/tabpages/page.cxx create mode 100644 cui/source/tabpages/paragrph.cxx create mode 100644 cui/source/tabpages/swpossizetabpage.cxx create mode 100644 cui/source/tabpages/tabarea.cxx create mode 100644 cui/source/tabpages/tabline.cxx create mode 100644 cui/source/tabpages/tabstpge.cxx create mode 100644 cui/source/tabpages/textanim.cxx create mode 100644 cui/source/tabpages/textattr.cxx create mode 100644 cui/source/tabpages/tparea.cxx create mode 100644 cui/source/tabpages/tpbitmap.cxx create mode 100644 cui/source/tabpages/tpcolor.cxx create mode 100644 cui/source/tabpages/tpgradnt.cxx create mode 100644 cui/source/tabpages/tphatch.cxx create mode 100644 cui/source/tabpages/tpline.cxx create mode 100644 cui/source/tabpages/tplnedef.cxx create mode 100644 cui/source/tabpages/tplneend.cxx create mode 100644 cui/source/tabpages/tppattern.cxx create mode 100644 cui/source/tabpages/tpshadow.cxx create mode 100644 cui/source/tabpages/tptrans.cxx create mode 100644 cui/source/tabpages/transfrm.cxx create mode 100644 cui/source/uno/services.cxx (limited to 'cui/source') diff --git a/cui/source/customize/CommandCategoryListBox.cxx b/cui/source/customize/CommandCategoryListBox.cxx new file mode 100644 index 000000000..d9e3f57b1 --- /dev/null +++ b/cui/source/customize/CommandCategoryListBox.cxx @@ -0,0 +1,581 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// include search util +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include //for SaveInData + +CommandCategoryListBox::CommandCategoryListBox(std::unique_ptr xControl) + : pStylesInfo( nullptr ) + , m_xControl(std::move(xControl)) +{ + //Initialize search util + m_searchOptions.AlgorithmType2 = css::util::SearchAlgorithms2::ABSOLUTE; + m_searchOptions.transliterateFlags |= TransliterationFlags::IGNORE_CASE; + m_searchOptions.searchFlag |= (css::util::SearchFlags::REG_NOT_BEGINOFLINE + | css::util::SearchFlags::REG_NOT_ENDOFLINE); +} + +CommandCategoryListBox::~CommandCategoryListBox() +{ + ClearAll(); +} + +void CommandCategoryListBox::ClearAll() +{ + // Clear objects from m_aGroupInfo vector to avoid memory leak + for (const auto & It : m_aGroupInfo) + { + if ( It->nKind == SfxCfgKind::GROUP_STYLES && It->pObject ) + { + SfxStyleInfo_Impl* pStyle = static_cast(It->pObject); + delete pStyle; + } + else if ( It->nKind == SfxCfgKind::FUNCTION_SCRIPT && It->pObject ) + { + OUString* pScriptURI = static_cast(It->pObject); + delete pScriptURI; + } + else if ( It->nKind == SfxCfgKind::GROUP_SCRIPTCONTAINER && It->pObject) + { + css::uno::XInterface* xi = static_cast(It->pObject); + if (xi != nullptr) + { + xi->release(); + } + } + } + + m_aGroupInfo.clear(); + m_xControl->clear(); +} + +void CommandCategoryListBox::Init( + const css::uno::Reference< css::uno::XComponentContext >& xContext, + const css::uno::Reference< css::frame::XFrame >& xFrame, + const OUString& sModuleLongName) +{ + // User will not see incomplete UI + m_xControl->freeze(); + ClearAll(); + + m_xContext = xContext; + m_xFrame = xFrame; + + m_sModuleLongName = sModuleLongName; + m_xGlobalCategoryInfo = css::ui::theUICategoryDescription::get( m_xContext ); + m_xModuleCategoryInfo.set(m_xGlobalCategoryInfo->getByName(m_sModuleLongName), css::uno::UNO_QUERY_THROW); + m_xUICmdDescription = css::frame::theUICommandDescription::get( m_xContext ); + + // Support style commands + css::uno::Reference xController; + css::uno::Reference xModel; + if (xFrame.is()) + xController = xFrame->getController(); + if (xController.is()) + xModel = xController->getModel(); + + m_aStylesInfo.init(sModuleLongName, xModel); + SetStylesInfo(&m_aStylesInfo); + + try + { + css::uno::Reference< css::frame::XDispatchInformationProvider > xProvider(m_xFrame, css::uno::UNO_QUERY_THROW); + css::uno::Sequence< sal_Int16 > lGroups = xProvider->getSupportedCommandGroups(); + + sal_Int32 nGroupsLength = lGroups.getLength(); + + if ( nGroupsLength > 0 ) + { + // Add the category of "All commands" + m_aGroupInfo.push_back( std::make_unique( SfxCfgKind::GROUP_ALLFUNCTIONS, 0 ) ); + m_xControl->append(OUString::number(reinterpret_cast(m_aGroupInfo.back().get())), CuiResId(RID_SVXSTR_ALLFUNCTIONS)); + } + + // Separate the "All commands"category from the actual categories + m_xControl->append_separator(""); + + typedef std::pair str_id; + std::vector aCategories; + + // Add the actual categories + for (sal_Int32 i = 0; i < nGroupsLength; ++i) + { + sal_Int16 nGroupID = lGroups[i]; + OUString sGroupID = OUString::number(nGroupID); + OUString sGroupName; + + try + { + m_xModuleCategoryInfo->getByName(sGroupID) >>= sGroupName; + if (sGroupName.isEmpty()) + continue; + } + catch(const css::container::NoSuchElementException&) + { + continue; + } + aCategories.emplace_back(std::make_pair(sGroupName, nGroupID)); + } + + auto const sort = comphelper::string::NaturalStringSorter( + comphelper::getProcessComponentContext(), + Application::GetSettings().GetUILanguageTag().getLocale()); + + std::sort(aCategories.begin(), aCategories.end(), + [&sort](const str_id& a, const str_id& b) + { return sort.compare(a.first, b.first) < 0; }); + + // Add the actual categories + for (const auto &a : aCategories) + { + const OUString& rGroupName = a.first; + sal_Int16 nGroupID = a.second; + m_aGroupInfo.push_back(std::make_unique(SfxCfgKind::GROUP_FUNCTION, nGroupID)); + m_xControl->append(OUString::number(reinterpret_cast(m_aGroupInfo.back().get())), rGroupName); + } + + // Separate regular commands from styles and macros + m_xControl->append_separator(""); + + // Add macros category + m_aGroupInfo.push_back( + std::make_unique( SfxCfgKind::GROUP_SCRIPTCONTAINER, 0, nullptr) ); + m_xControl->append(OUString::number(reinterpret_cast(m_aGroupInfo.back().get())), CuiResId(RID_SVXSTR_MACROS)); + + // Add styles category + //TODO: last param should contain user data? + m_aGroupInfo.push_back( + std::make_unique( SfxCfgKind::GROUP_STYLES, 0, nullptr ) ); + m_xControl->append(OUString::number(reinterpret_cast(m_aGroupInfo.back().get())), CuiResId(RID_SVXSTR_GROUP_STYLES)); + } + catch(const css::uno::RuntimeException&) + { throw; } + catch(const css::uno::Exception&) + {} + + // Reveal the updated UI to user + m_xControl->thaw(); + m_xControl->set_active(0); +} + +void CommandCategoryListBox::FillFunctionsList( + const css::uno::Sequence& xCommands, + CuiConfigFunctionListBox* pFunctionListBox, + const OUString& filterTerm, + SaveInData *pCurrentSaveInData ) +{ + // Setup search filter parameters + m_searchOptions.searchString = filterTerm; + utl::TextSearch textSearch( m_searchOptions ); + + for (const auto & rInfo : xCommands) + { + auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(rInfo.Command, m_sModuleLongName); + + OUString sUIName = getCommandName(rInfo.Command); + OUString sLabel = vcl::CommandInfoProvider::GetLabelForCommand(aProperties); + OUString sTooltipLabel = vcl::CommandInfoProvider::GetTooltipForCommand(rInfo.Command, aProperties, m_xFrame); + OUString sPopupLabel = + (vcl::CommandInfoProvider::GetPopupLabelForCommand(aProperties)) + .replaceFirst("~", ""); + + // Apply the search filter + if (!filterTerm.isEmpty() + && !textSearch.searchForward( sUIName ) + && !textSearch.searchForward( sLabel ) + && !textSearch.searchForward( sTooltipLabel ) + && !textSearch.searchForward( sPopupLabel ) ) + { + continue; + } + + css::uno::Reference xImage; + if (pCurrentSaveInData) + xImage = pCurrentSaveInData->GetImage(rInfo.Command); + + m_aGroupInfo.push_back( std::make_unique( SfxCfgKind::FUNCTION_SLOT, 0 ) ); + SfxGroupInfo_Impl* pGrpInfo = m_aGroupInfo.back().get(); + pGrpInfo->sCommand = rInfo.Command; + pGrpInfo->sLabel = sUIName; + pGrpInfo->sTooltip = sTooltipLabel; + pFunctionListBox->append(OUString::number(reinterpret_cast(m_aGroupInfo.back().get())), sUIName, xImage); + } +} + +OUString CommandCategoryListBox::getCommandName(const OUString& sCommand) +{ + OUString sUIName; + try + { + css::uno::Reference< css::container::XNameAccess > xModuleConf; + m_xUICmdDescription->getByName(m_sModuleLongName) >>= xModuleConf; + if (xModuleConf.is()) + { + ::comphelper::SequenceAsHashMap lProps(xModuleConf->getByName(sCommand)); + sUIName = lProps.getUnpackedValueOrDefault("Name", OUString()); + } + } + catch(const css::uno::RuntimeException&) + { throw; } + catch(css::uno::Exception&) + { sUIName.clear(); } + + // fallback for missing UINames !? + if (sUIName.isEmpty()) + { + sUIName = sCommand; + } + + return sUIName; +} + +void CommandCategoryListBox::categorySelected(CuiConfigFunctionListBox* pFunctionListBox, + const OUString& filterTerm, SaveInData *pCurrentSaveInData) +{ + SfxGroupInfo_Impl *pInfo = reinterpret_cast(m_xControl->get_active_id().toInt64()); + std::vector> aNodesToExpand; + pFunctionListBox->freeze(); + pFunctionListBox->ClearAll(); + + switch ( pInfo->nKind ) + { + case SfxCfgKind::GROUP_ALLFUNCTIONS: + { + css::uno::Reference< css::frame::XDispatchInformationProvider > + xProvider( m_xFrame, css::uno::UNO_QUERY ); + sal_Int32 nEntryCount = m_xControl->get_count(); + + for (sal_Int32 nCurPos = 0; nCurPos < nEntryCount; ++nCurPos) + { + SfxGroupInfo_Impl *pCurrentInfo = + reinterpret_cast(m_xControl->get_id(nCurPos).toInt64()); + + if (!pCurrentInfo) //separator + continue; + + if (pCurrentInfo->nKind == SfxCfgKind::GROUP_FUNCTION) + { + css::uno::Sequence< css::frame::DispatchInformation > lCommands; + try + { + lCommands = xProvider->getConfigurableDispatchInformation( + pCurrentInfo->nUniqueID ); + FillFunctionsList( lCommands, pFunctionListBox, filterTerm, pCurrentSaveInData ); + } + catch( css::container::NoSuchElementException& ) + { + } + } + } + + break; + } + case SfxCfgKind::GROUP_FUNCTION: + { + sal_uInt16 nGroup = pInfo->nUniqueID; + css::uno::Reference< css::frame::XDispatchInformationProvider > + xProvider (m_xFrame, css::uno::UNO_QUERY_THROW); + css::uno::Sequence< css::frame::DispatchInformation > lCommands = + xProvider->getConfigurableDispatchInformation(nGroup); + FillFunctionsList( lCommands, pFunctionListBox, filterTerm, pCurrentSaveInData ); + break; + } + case SfxCfgKind::GROUP_SCRIPTCONTAINER: //Macros + { + SAL_INFO("cui.customize", "** ** About to initialise SF Scripts"); + // Add Scripting Framework entries + css::uno::Reference< css::script::browse::XBrowseNode > rootNode; + try + { + css::uno::Reference< css::script::browse::XBrowseNodeFactory > xFac + = css::script::browse::theBrowseNodeFactory::get( m_xContext ); + rootNode.set( xFac->createView( css::script::browse::BrowseNodeFactoryViewTypes::MACROSELECTOR ) ); + } + catch( css::uno::Exception const & ) + { + TOOLS_WARN_EXCEPTION("cui.customize", "Caught some exception whilst retrieving browse nodes from factory"); + // TODO exception handling + } + + if ( rootNode.is() && rootNode->hasChildNodes() ) + { + //We call acquire on the XBrowseNode so that it does not + //get autodestructed and become invalid when accessed later. + rootNode->acquire(); + + m_aGroupInfo.push_back( + std::make_unique( + SfxCfgKind::GROUP_SCRIPTCONTAINER, 0, static_cast(rootNode.get()) ) ); + + // Add main macro groups + const css::uno::Sequence> aChildNodes = rootNode->getChildNodes(); + for ( auto const & childGroup : aChildNodes ) + { + OUString sUIName; + childGroup->acquire(); + + if ( childGroup->hasChildNodes() ) + { + if ( childGroup->getName() == "user" ) + { + sUIName = CuiResId( RID_SVXSTR_MYMACROS ); + } + else if ( childGroup->getName() == "share" ) + { + sUIName = CuiResId( RID_SVXSTR_PRODMACROS ); + } + else + { + sUIName = childGroup->getName(); + } + + if (sUIName.isEmpty()) + { + continue; + } + + m_aGroupInfo.push_back( + std::make_unique( + SfxCfgKind::GROUP_SCRIPTCONTAINER, 0 ) ); + std::unique_ptr xMacroGroup(pFunctionListBox->tree_append(OUString::number(reinterpret_cast(m_aGroupInfo.back().get())), sUIName)); + + { + // tdf#128010: Do not nag user asking to enable JRE: if it's disabled, + // simply don't show relevant entries (user chose to not use JRE) + css::uno::ContextLayer layer( + comphelper::NoEnableJavaInteractionContext()); + //Add the children and the grand children + addChildren(xMacroGroup.get(), childGroup, pFunctionListBox, filterTerm, + pCurrentSaveInData, aNodesToExpand); + } + + // Remove the main group if empty + if (!pFunctionListBox->iter_has_child(*xMacroGroup)) + { + pFunctionListBox->remove(*xMacroGroup); + } + else if (!filterTerm.isEmpty()) + { + aNodesToExpand.emplace_back(std::move(xMacroGroup)); + } + } + } + } + + break; + } + case SfxCfgKind::GROUP_STYLES: + { + const std::vector< SfxStyleInfo_Impl > lStyleFamilies = pStylesInfo->getStyleFamilies(); + + for ( const auto & pIt : lStyleFamilies ) + { + if ( pIt.sLabel.isEmpty() ) + { + continue; + } + + + m_aGroupInfo.push_back( std::make_unique( SfxCfgKind::GROUP_STYLES, 0 ) ); + // pIt.sLabel is Name of the style family + std::unique_ptr xFuncEntry(pFunctionListBox->tree_append(OUString::number(reinterpret_cast(m_aGroupInfo.back().get())), pIt.sLabel)); + + const std::vector< SfxStyleInfo_Impl > lStyles = pStylesInfo->getStyles(pIt.sFamily); + + // Setup search filter parameters + m_searchOptions.searchString = filterTerm; + utl::TextSearch textSearch( m_searchOptions ); + + // Insert children (styles) + for ( const auto & pStyleIt : lStyles ) + { + OUString sUIName = pStyleIt.sLabel; + sal_Int32 aStartPos = 0; + sal_Int32 aEndPos = sUIName.getLength(); + + // Apply the search filter + if (!filterTerm.isEmpty() + && !textSearch.SearchForward( sUIName, &aStartPos, &aEndPos ) ) + { + continue; + } + + SfxStyleInfo_Impl* pStyle = new SfxStyleInfo_Impl(pStyleIt); + + m_aGroupInfo.push_back( + std::make_unique( + SfxCfgKind::GROUP_STYLES, 0, pStyle ) ); + + m_aGroupInfo.back()->sCommand = pStyle->sCommand; + m_aGroupInfo.back()->sLabel = pStyle->sLabel; + + pFunctionListBox->append(OUString::number(reinterpret_cast(m_aGroupInfo.back().get())), sUIName, xFuncEntry.get()); + } + + // Remove the style group from the list if no children + if (!pFunctionListBox->iter_has_child(*xFuncEntry)) + { + pFunctionListBox->remove(*xFuncEntry); + } + else if (!filterTerm.isEmpty()) + { + aNodesToExpand.emplace_back(std::move(xFuncEntry)); + } + } + + break; + } + default: + // Do nothing, the list box will stay empty + SAL_INFO( "cui.customize", "Ignoring unexpected SfxCfgKind: " << static_cast(pInfo->nKind) ); + break; + } + + pFunctionListBox->thaw(); + + if (pFunctionListBox->n_children()) + pFunctionListBox->select(0); + + //post freeze + for (const auto& it : aNodesToExpand) + pFunctionListBox->expand_row(*it); +} + +void CommandCategoryListBox::SetStylesInfo(SfxStylesInfo_Impl* pStyles) +{ + pStylesInfo = pStyles; +} + +void CommandCategoryListBox::addChildren( + const weld::TreeIter* parentEntry, const css::uno::Reference< css::script::browse::XBrowseNode > &parentNode, + CuiConfigFunctionListBox* pFunctionListBox, const OUString& filterTerm , SaveInData *pCurrentSaveInData, + std::vector> &rNodesToExpand) +{ + // Setup search filter parameters + m_searchOptions.searchString = filterTerm; + utl::TextSearch textSearch( m_searchOptions ); + + const css::uno::Sequence> aChildNodes = parentNode->getChildNodes(); + for (auto const & child : aChildNodes) + { + // Acquire to prevent auto-destruction + child->acquire(); + + if (child->hasChildNodes()) + { + OUString sUIName = child->getName(); + + m_aGroupInfo.push_back( std::make_unique(SfxCfgKind::GROUP_SCRIPTCONTAINER, + 0, static_cast( child.get()))); + std::unique_ptr xNewEntry(pFunctionListBox->tree_append(OUString::number(reinterpret_cast(m_aGroupInfo.back().get())), sUIName, parentEntry)); + + addChildren(xNewEntry.get(), child, pFunctionListBox, filterTerm, pCurrentSaveInData, rNodesToExpand); + + // Remove the group if empty + if (!pFunctionListBox->iter_has_child(*xNewEntry)) + pFunctionListBox->remove(*xNewEntry); + else + rNodesToExpand.emplace_back(std::move(xNewEntry)); + } + else if ( child->getType() == css::script::browse::BrowseNodeTypes::SCRIPT ) + { + // Prepare for filtering + OUString sUIName = child->getName(); + sal_Int32 aStartPos = 0; + sal_Int32 aEndPos = sUIName.getLength(); + + // Apply the search filter + if (!filterTerm.isEmpty() + && !textSearch.SearchForward( sUIName, &aStartPos, &aEndPos ) ) + { + continue; + } + + OUString uri, description; + + css::uno::Reference < css::beans::XPropertySet >xPropSet( child, css::uno::UNO_QUERY ); + + if (!xPropSet.is()) + { + continue; + } + + css::uno::Any value = xPropSet->getPropertyValue("URI"); + value >>= uri; + + try + { + value = xPropSet->getPropertyValue("Description"); + value >>= description; + } + catch (css::uno::Exception &) { + // do nothing, the description will be empty + } + + if (description.isEmpty()) + { + description = CuiResId( RID_SVXSTR_NOMACRODESC ); + } + + OUString* pScriptURI = new OUString( uri ); + + css::uno::Reference xImage; + if (pCurrentSaveInData) + xImage = pCurrentSaveInData->GetImage(uri); + + m_aGroupInfo.push_back( std::make_unique( SfxCfgKind::FUNCTION_SCRIPT, 0, pScriptURI )); + m_aGroupInfo.back()->sCommand = uri; + m_aGroupInfo.back()->sLabel = sUIName; + m_aGroupInfo.back()->sHelpText = description; + pFunctionListBox->append(OUString::number(reinterpret_cast(m_aGroupInfo.back().get())), sUIName, xImage, parentEntry); + } + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/cui/source/customize/CustomNotebookbarGenerator.cxx b/cui/source/customize/CustomNotebookbarGenerator.cxx new file mode 100644 index 000000000..893108495 --- /dev/null +++ b/cui/source/customize/CustomNotebookbarGenerator.cxx @@ -0,0 +1,284 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define aUIPropertiesCount 3 + +using namespace css; + +CustomNotebookbarGenerator::CustomNotebookbarGenerator() {} + +static OUString lcl_activeAppName(vcl::EnumContext::Application eApp) +{ + switch (eApp) + { + case vcl::EnumContext::Application::Writer: + return "ActiveWriter"; + break; + case vcl::EnumContext::Application::Calc: + return "ActiveCalc"; + break; + case vcl::EnumContext::Application::Impress: + return "ActiveImpress"; + break; + case vcl::EnumContext::Application::Draw: + return "ActiveDraw"; + break; + default: + return OUString(); + break; + } +} + +static OUString lcl_getAppName(vcl::EnumContext::Application eApp) +{ + switch (eApp) + { + case vcl::EnumContext::Application::Writer: + return "Writer"; + break; + case vcl::EnumContext::Application::Calc: + return "Calc"; + break; + case vcl::EnumContext::Application::Impress: + return "Impress"; + break; + case vcl::EnumContext::Application::Draw: + return "Draw"; + break; + default: + return OUString(); + break; + } +} + +static OUString getAppNameRegistryPath() +{ + vcl::EnumContext::Application eApp = vcl::EnumContext::Application::Any; + const Reference& xFrame + = SfxViewFrame::Current()->GetFrame().GetFrameInterface(); + const Reference xModuleManager + = frame::ModuleManager::create(::comphelper::getProcessComponentContext()); + eApp = vcl::EnumContext::GetApplicationEnum(xModuleManager->identify(xFrame)); + + OUString sAppName(lcl_getAppName(eApp)); + return "org.openoffice.Office.UI.ToolbarMode/Applications/" + sAppName; +} + +static OUString customizedUIPathBuffer() +{ + OUString sDirPath("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE( + "bootstrap") ":UserInstallation}/user/config/soffice.cfg/"); + rtl::Bootstrap::expandMacros(sDirPath); + return sDirPath; +} + +OUString CustomNotebookbarGenerator::getCustomizedUIPath() +{ + OUString sAppName, sNotebookbarUIFileName; + CustomNotebookbarGenerator::getFileNameAndAppName(sAppName, sNotebookbarUIFileName); + return customizedUIPathBuffer() + "modules/s" + sAppName.toAsciiLowerCase() + "/ui/" + + sNotebookbarUIFileName; +} + +OUString CustomNotebookbarGenerator::getOriginalUIPath() +{ + OUString sAppName, sNotebookbarUIFileName; + CustomNotebookbarGenerator::getFileNameAndAppName(sAppName, sNotebookbarUIFileName); + return VclBuilderContainer::getUIRootDir() + "modules/s" + sAppName.toAsciiLowerCase() + "/ui/" + + sNotebookbarUIFileName; +} + +static OUString getUIDirPath() +{ + OUString sAppName, sNotebookbarUIFileName; + CustomNotebookbarGenerator::getFileNameAndAppName(sAppName, sNotebookbarUIFileName); + OUString sUIDirPath + = customizedUIPathBuffer() + "modules/s" + sAppName.toAsciiLowerCase() + "/ui/"; + return sUIDirPath; +} + +OString CustomNotebookbarGenerator::getSystemPath(OUString const& sURL) +{ + if (sURL.isEmpty()) + return OString(); + OUString sSystemPathSettings; + if (osl_getSystemPathFromFileURL(sURL.pData, &sSystemPathSettings.pData) != osl_File_E_None) + { + SAL_WARN("cui.customnotebookbar", "Cannot get system path for :" << sURL); + return OString(); + } + OString osSystemPathSettings + = OUStringToOString(sSystemPathSettings, osl_getThreadTextEncoding()); + return osSystemPathSettings; +} + +static void changeNodeValue(xmlNode* pNodePtr, const char* pProperty, const char* pValue) +{ + pNodePtr = pNodePtr->xmlChildrenNode; + while (pNodePtr) + { + if (!(xmlStrcmp(pNodePtr->name, reinterpret_cast("property")))) + { + xmlChar* UriValue = xmlGetProp(pNodePtr, reinterpret_cast("name")); + if (!(xmlStrcmp(UriValue, reinterpret_cast(pProperty)))) + xmlNodeSetContent(pNodePtr, reinterpret_cast(pValue)); + xmlFree(UriValue); + break; + } + pNodePtr = pNodePtr->next; + } +} + +static void searchNodeAndAttribute(xmlNode* pNodePtr, const char* pUIItemID, const char* pProperty, + const char* pValue) +{ + pNodePtr = pNodePtr->xmlChildrenNode; + while (pNodePtr) + { + if (pNodePtr->type == XML_ELEMENT_NODE) + { + if (!(xmlStrcmp(pNodePtr->name, reinterpret_cast("object")))) + { + xmlChar* UriValue = xmlGetProp(pNodePtr, reinterpret_cast("id")); + if (!(xmlStrcmp(UriValue, reinterpret_cast(pUIItemID)))) + changeNodeValue(pNodePtr, pProperty, pValue); + xmlFree(UriValue); + } + searchNodeAndAttribute(pNodePtr, pUIItemID, pProperty, pValue); + } + pNodePtr = pNodePtr->next; + } +} + +static xmlDocPtr notebookbarXMLParser(const OString& rDocName, const OString& rUIItemID, + const OString& rProperty, const OString& rValue) +{ + xmlDocPtr pDocPtr = xmlParseFile(rDocName.getStr()); + xmlNodePtr pNodePtr = xmlDocGetRootElement(pDocPtr); + searchNodeAndAttribute(pNodePtr, rUIItemID.getStr(), rProperty.getStr(), rValue.getStr()); + return pDocPtr; +} + +void CustomNotebookbarGenerator::modifyCustomizedUIFile(const Sequence& sUIItemProperties) +{ + OString sCustomizedUIPath = getSystemPath(getCustomizedUIPath()); + for (auto const& aValue : sUIItemProperties) + { + std::vector aProperties(aUIPropertiesCount); + for (sal_Int32 aIndex = 0; aIndex < aUIPropertiesCount; aIndex++) + { + sal_Int32 nPos = aIndex; + OUString sToken = aValue.getToken(nPos, ',', nPos); + aProperties[aIndex] = OUStringToOString(sToken, RTL_TEXTENCODING_UTF8); + } + xmlDocPtr doc = notebookbarXMLParser(sCustomizedUIPath, aProperties[0], aProperties[1], + aProperties[2]); + + if (doc != nullptr) + { + xmlSaveFormatFile(sCustomizedUIPath.getStr(), doc, 1); + xmlFreeDoc(doc); + } + } +} + +void CustomNotebookbarGenerator::getFileNameAndAppName(OUString& sAppName, + OUString& sNotebookbarUIFileName) +{ + SfxViewFrame* pFrame = SfxViewFrame::Current(); + if (!pFrame) + return; + + const auto xContext = comphelper::getProcessComponentContext(); + utl::OConfigurationTreeRoot aRoot(xContext, "org.openoffice.Office.UI.ToolbarMode/", false); + const Reference& xFrame = pFrame->GetFrame().GetFrameInterface(); + const Reference xModuleManager = frame::ModuleManager::create(xContext); + + vcl::EnumContext::Application eApp + = vcl::EnumContext::GetApplicationEnum(xModuleManager->identify(xFrame)); + OUString sActiveAppName(lcl_activeAppName(eApp)); + sAppName = lcl_getAppName(eApp); + const Any aValue = aRoot.getNodeValue(sActiveAppName); + aValue >>= sNotebookbarUIFileName; +} + +void CustomNotebookbarGenerator::createCustomizedUIFile() +{ + OUString sUserUIDir = getUIDirPath(); + OUString sOriginalUIPath = getOriginalUIPath(); + OUString sCustomizedUIPath = getCustomizedUIPath(); + + sal_uInt32 nflag = osl_File_OpenFlag_Read | osl_File_OpenFlag_Write; + osl::Directory aDirectory(sUserUIDir); + if (aDirectory.open() != osl::FileBase::E_None) + osl::Directory::create(sUserUIDir, nflag); + else + SAL_WARN("cui.customnotebookbar", + "Cannot create the directory or directory was present :" << sUserUIDir); + + osl::File aFile(sCustomizedUIPath); + if (aFile.open(nflag) != osl::FileBase::E_None) + osl::File::copy(sOriginalUIPath, sCustomizedUIPath); + else + SAL_WARN("cui.customnotebookbar", + "Cannot copy the file or file was present :" << sCustomizedUIPath); +} + +Sequence CustomNotebookbarGenerator::getCustomizedUIItem(OUString sNotebookbarConfigType) +{ + OUString aPath = getAppNameRegistryPath(); + const utl::OConfigurationTreeRoot aAppNode(::comphelper::getProcessComponentContext(), aPath, + false); + + const utl::OConfigurationNode aModesNode = aAppNode.openNode("Modes"); + const utl::OConfigurationNode aModeNode(aModesNode.openNode(sNotebookbarConfigType)); + const Any aValue = aModeNode.getNodeValue("UIItemProperties"); + Sequence aValues; + aValue >>= aValues; + return aValues; +} + +void CustomNotebookbarGenerator::setCustomizedUIItem(Sequence sUIItemProperties, + OUString sNotebookbarConfigType) +{ + OUString aPath = getAppNameRegistryPath(); + const utl::OConfigurationTreeRoot aAppNode(::comphelper::getProcessComponentContext(), aPath, + true); + const utl::OConfigurationNode aModesNode = aAppNode.openNode("Modes"); + const utl::OConfigurationNode aModeNode(aModesNode.openNode(sNotebookbarConfigType)); + + css::uno::Any aUIItemProperties(makeAny(sUIItemProperties)); + aModeNode.setNodeValue("UIItemProperties", aUIItemProperties); + aAppNode.commit(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/customize/SvxConfigPageHelper.cxx b/cui/source/customize/SvxConfigPageHelper.cxx new file mode 100644 index 000000000..3ac1ca9e4 --- /dev/null +++ b/cui/source/customize/SvxConfigPageHelper.cxx @@ -0,0 +1,471 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +static sal_Int16 theImageType = + css::ui::ImageType::COLOR_NORMAL | + css::ui::ImageType::SIZE_DEFAULT; + +void SvxConfigPageHelper::RemoveEntry( SvxEntries* pEntries, SvxConfigEntry const * pChildEntry ) +{ + SvxEntries::iterator iter = pEntries->begin(); + + while ( iter != pEntries->end() ) + { + if ( pChildEntry == *iter ) + { + pEntries->erase( iter ); + break; + } + ++iter; + } +} + +OUString SvxConfigPageHelper::replaceSaveInName( const OUString& rMessage, const OUString& rSaveInName ) +{ + const OUString placeholder("%SAVE IN SELECTION%" ); + + OUString name = rMessage.replaceFirst(placeholder, rSaveInName); + + return name; +} + +OUString SvxConfigPageHelper::stripHotKey( const OUString& str ) +{ + return str.replaceFirst("~", ""); +} + +OUString SvxConfigPageHelper::replaceSixteen( const OUString& str, sal_Int32 nReplacement ) +{ + return str.replaceAll( OUString::number( 16 ), OUString::number( nReplacement )); +} + +sal_Int16 SvxConfigPageHelper::GetImageType() +{ + return theImageType; +} + +void SvxConfigPageHelper::InitImageType() +{ + theImageType = + css::ui::ImageType::COLOR_NORMAL | + css::ui::ImageType::SIZE_DEFAULT; + + if (SvtMiscOptions().GetCurrentSymbolsSize() == SFX_SYMBOLS_SIZE_LARGE) + { + theImageType |= css::ui::ImageType::SIZE_LARGE; + } + else if (SvtMiscOptions().GetCurrentSymbolsSize() == SFX_SYMBOLS_SIZE_32) + { + theImageType |= css::ui::ImageType::SIZE_32; + } +} + +css::uno::Reference< css::graphic::XGraphic > SvxConfigPageHelper::GetGraphic( + const css::uno::Reference< css::ui::XImageManager >& xImageManager, + const OUString& rCommandURL ) +{ + css::uno::Reference< css::graphic::XGraphic > result; + + if ( xImageManager.is() ) + { + // TODO handle large graphics + css::uno::Sequence< css::uno::Reference< css::graphic::XGraphic > > aGraphicSeq; + + css::uno::Sequence aImageCmdSeq { rCommandURL }; + + try + { + aGraphicSeq = + xImageManager->getImages( GetImageType(), aImageCmdSeq ); + + if ( aGraphicSeq.hasElements() ) + { + result = aGraphicSeq[0]; + } + } + catch ( css::uno::Exception& ) + { + // will return empty XGraphic + } + } + + return result; +} + +OUString +SvxConfigPageHelper::generateCustomName( + const OUString& prefix, + SvxEntries* entries, + sal_Int32 suffix /*= 1*/ ) +{ + OUString name; + sal_Int32 pos = 0; + + // find and replace the %n placeholder in the prefix string + name = prefix.replaceFirst( "%n", OUString::number( suffix ), &pos ); + + if ( pos == -1 ) + { + // no placeholder found so just append the suffix + name += OUString::number( suffix ); + } + + if (!entries) + return name; + + // now check if there is an already existing entry with this name + bool bFoundEntry = false; + for (auto const& entry : *entries) + { + if ( name.equals(entry->GetName()) ) + { + bFoundEntry = true; + break; + } + } + + if (bFoundEntry) + { + // name already exists so try the next number up + return generateCustomName( prefix, entries, ++suffix ); + } + + return name; +} + +OUString SvxConfigPageHelper::generateCustomMenuURL( + SvxEntries* entries, + sal_Int32 suffix /*= 1*/ ) +{ + OUString url = "vnd.openoffice.org:CustomMenu" + OUString::number( suffix ); + if (!entries) + return url; + + // now check is there is an already existing entry with this url + bool bFoundEntry = false; + for (auto const& entry : *entries) + { + if ( url.equals(entry->GetCommand()) ) + { + bFoundEntry = true; + break; + } + } + + if (bFoundEntry) + { + // url already exists so try the next number up + return generateCustomMenuURL( entries, ++suffix ); + } + + return url; +} + +sal_uInt32 SvxConfigPageHelper::generateRandomValue() +{ + return comphelper::rng::uniform_uint_distribution(0, std::numeric_limits::max()); +} + +OUString SvxConfigPageHelper::generateCustomURL( SvxEntries* entries ) +{ + OUString url = OUStringLiteral(ITEM_TOOLBAR_URL) + CUSTOM_TOOLBAR_STR + + // use a random number to minimize possible clash with existing custom toolbars + OUString::number( generateRandomValue(), 16 ); + + // now check is there is an already existing entry with this url + bool bFoundEntry = false; + for (auto const& entry : *entries) + { + if ( url.equals(entry->GetCommand()) ) + { + bFoundEntry = true; + break; + } + } + + if (bFoundEntry) + { + // url already exists so try the next number up + return generateCustomURL( entries ); + } + + return url; +} + +OUString SvxConfigPageHelper::GetModuleName( const OUString& aModuleId ) +{ + if ( aModuleId == "com.sun.star.text.TextDocument" || + aModuleId == "com.sun.star.text.GlobalDocument" ) + return "Writer"; + else if ( aModuleId == "com.sun.star.text.WebDocument" ) + return "Writer/Web"; + else if ( aModuleId == "com.sun.star.drawing.DrawingDocument" ) + return "Draw"; + else if ( aModuleId == "com.sun.star.presentation.PresentationDocument" ) + return "Impress"; + else if ( aModuleId == "com.sun.star.sheet.SpreadsheetDocument" ) + return "Calc"; + else if ( aModuleId == "com.sun.star.script.BasicIDE" ) + return "Basic"; + else if ( aModuleId == "com.sun.star.formula.FormulaProperties" ) + return "Math"; + else if ( aModuleId == "com.sun.star.sdb.RelationDesign" ) + return "Relation Design"; + else if ( aModuleId == "com.sun.star.sdb.QueryDesign" ) + return "Query Design"; + else if ( aModuleId == "com.sun.star.sdb.TableDesign" ) + return "Table Design"; + else if ( aModuleId == "com.sun.star.sdb.DataSourceBrowser" ) + return "Data Source Browser"; + else if ( aModuleId == "com.sun.star.sdb.DatabaseDocument" ) + return "Database"; + + return OUString(); +} + +OUString SvxConfigPageHelper::GetUIModuleName( + const OUString& aModuleId, + const css::uno::Reference< css::frame::XModuleManager2 >& rModuleManager ) +{ + assert(rModuleManager.is()); + + OUString aModuleUIName; + + try + { + css::uno::Any a = rModuleManager->getByName( aModuleId ); + css::uno::Sequence< css::beans::PropertyValue > aSeq; + + if ( a >>= aSeq ) + { + for ( css::beans::PropertyValue const & rProp : std::as_const(aSeq) ) + { + if ( rProp.Name == "ooSetupFactoryUIName" ) + { + rProp.Value >>= aModuleUIName; + break; + } + } + } + } + catch ( css::uno::RuntimeException& ) + { + throw; + } + catch ( css::uno::Exception& ) + { + } + + if ( aModuleUIName.isEmpty() ) + aModuleUIName = GetModuleName( aModuleId ); + + return aModuleUIName; +} + +bool SvxConfigPageHelper::GetMenuItemData( + const css::uno::Reference< css::container::XIndexAccess >& rItemContainer, + sal_Int32 nIndex, + OUString& rCommandURL, + OUString& rLabel, + sal_uInt16& rType, + sal_Int32& rStyle, + css::uno::Reference< css::container::XIndexAccess >& rSubMenu ) +{ + try + { + css::uno::Sequence< css::beans::PropertyValue > aProps; + if ( rItemContainer->getByIndex( nIndex ) >>= aProps ) + { + for ( css::beans::PropertyValue const & rProp : std::as_const(aProps) ) + { + if ( rProp.Name == ITEM_DESCRIPTOR_COMMANDURL ) + { + rProp.Value >>= rCommandURL; + } + else if ( rProp.Name == ITEM_DESCRIPTOR_CONTAINER ) + { + rProp.Value >>= rSubMenu; + } + else if ( rProp.Name == ITEM_DESCRIPTOR_STYLE ) + { + rProp.Value >>= rStyle; + } + else if ( rProp.Name == ITEM_DESCRIPTOR_LABEL ) + { + rProp.Value >>= rLabel; + } + else if ( rProp.Name == ITEM_DESCRIPTOR_TYPE ) + { + rProp.Value >>= rType; + } + } + + return true; + } + } + catch ( css::lang::IndexOutOfBoundsException& ) + { + } + + return false; +} + +bool SvxConfigPageHelper::GetToolbarItemData( + const css::uno::Reference< css::container::XIndexAccess >& rItemContainer, + sal_Int32 nIndex, + OUString& rCommandURL, + OUString& rLabel, + sal_uInt16& rType, + bool& rIsVisible, + sal_Int32& rStyle ) +{ + try + { + css::uno::Sequence< css::beans::PropertyValue > aProps; + if ( rItemContainer->getByIndex( nIndex ) >>= aProps ) + { + for ( css::beans::PropertyValue const & rProp : std::as_const(aProps) ) + { + if ( rProp.Name == ITEM_DESCRIPTOR_COMMANDURL ) + { + rProp.Value >>= rCommandURL; + } + else if ( rProp.Name == ITEM_DESCRIPTOR_STYLE ) + { + rProp.Value >>= rStyle; + } + else if ( rProp.Name == ITEM_DESCRIPTOR_LABEL ) + { + rProp.Value >>= rLabel; + } + else if ( rProp.Name == ITEM_DESCRIPTOR_TYPE ) + { + rProp.Value >>= rType; + } + else if ( rProp.Name == ITEM_DESCRIPTOR_ISVISIBLE ) + { + rProp.Value >>= rIsVisible; + } + } + + return true; + } + } + catch ( css::lang::IndexOutOfBoundsException& ) + { + } + + return false; +} + +css::uno::Sequence< css::beans::PropertyValue > SvxConfigPageHelper::ConvertSvxConfigEntry( + const SvxConfigEntry* pEntry ) +{ + css::uno::Sequence< css::beans::PropertyValue > aPropSeq( 4 ); + + aPropSeq[0].Name = ITEM_DESCRIPTOR_COMMANDURL; + aPropSeq[0].Value <<= pEntry->GetCommand(); + + aPropSeq[1].Name = ITEM_DESCRIPTOR_TYPE; + aPropSeq[1].Value <<= css::ui::ItemType::DEFAULT; + + // If the name has not been changed, then the label can be stored + // as an empty string. + // It will be initialised again later using the command to label map. + aPropSeq[2].Name = ITEM_DESCRIPTOR_LABEL; + if ( !pEntry->HasChangedName() && !pEntry->GetCommand().isEmpty() ) + { + aPropSeq[2].Value <<= OUString(); + } + else + { + aPropSeq[2].Value <<= pEntry->GetName(); + } + + aPropSeq[3].Name = ITEM_DESCRIPTOR_STYLE; + aPropSeq[3].Value <<= static_cast(pEntry->GetStyle()); + + return aPropSeq; +} + +css::uno::Sequence< css::beans::PropertyValue > SvxConfigPageHelper::ConvertToolbarEntry( + const SvxConfigEntry* pEntry ) +{ + css::uno::Sequence< css::beans::PropertyValue > aPropSeq( 5 ); + + aPropSeq[0].Name = ITEM_DESCRIPTOR_COMMANDURL; + aPropSeq[0].Value <<= pEntry->GetCommand(); + + aPropSeq[1].Name = ITEM_DESCRIPTOR_TYPE; + aPropSeq[1].Value <<= css::ui::ItemType::DEFAULT; + + // If the name has not been changed, then the label can be stored + // as an empty string. + // It will be initialised again later using the command to label map. + aPropSeq[2].Name = ITEM_DESCRIPTOR_LABEL; + if ( !pEntry->HasChangedName() && !pEntry->GetCommand().isEmpty() ) + { + aPropSeq[2].Value <<= OUString(); + } + else + { + aPropSeq[2].Value <<= pEntry->GetName(); + } + + aPropSeq[3].Name = ITEM_DESCRIPTOR_ISVISIBLE; + aPropSeq[3].Value <<= pEntry->IsVisible(); + + aPropSeq[4].Name = ITEM_DESCRIPTOR_STYLE; + aPropSeq[4].Value <<= static_cast(pEntry->GetStyle()); + + return aPropSeq; +} + +bool SvxConfigPageHelper::EntrySort( SvxConfigEntry const * a, SvxConfigEntry const * b ) +{ + return a->GetName().compareTo( b->GetName() ) < 0; +} + +bool SvxConfigPageHelper::SvxConfigEntryModified( SvxConfigEntry const * pEntry ) +{ + SvxEntries* pEntries = pEntry->GetEntries(); + if ( !pEntries ) + return false; + + for ( const auto& entry : *pEntries ) + { + if ( entry->IsModified() || SvxConfigEntryModified( entry ) ) + return true; + } + return false; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/customize/SvxMenuConfigPage.cxx b/cui/source/customize/SvxMenuConfigPage.cxx new file mode 100644 index 000000000..2adb56183 --- /dev/null +++ b/cui/source/customize/SvxMenuConfigPage.cxx @@ -0,0 +1,600 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include + +SvxMenuConfigPage::SvxMenuConfigPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet, bool bIsMenuBar) + : SvxConfigPage(pPage, pController, rSet) + , m_bIsMenuBar(bIsMenuBar) +{ + m_xGearBtn = m_xBuilder->weld_menu_button("menugearbtn"); + m_xGearBtn->show(); + m_xContentsListBox.reset(new SvxMenuEntriesListBox(m_xBuilder->weld_tree_view("menucontents"), this)); + weld::TreeView& rTreeView = m_xContentsListBox->get_widget(); + m_xDropTargetHelper.reset(new SvxConfigPageFunctionDropTarget(*this, rTreeView)); + rTreeView.connect_size_allocate(LINK(this, SvxMenuConfigPage, MenuEntriesSizeAllocHdl)); + Size aSize(m_xFunctions->get_size_request()); + rTreeView.set_size_request(aSize.Width(), aSize.Height()); + MenuEntriesSizeAllocHdl(aSize); + rTreeView.set_hexpand(true); + rTreeView.set_vexpand(true); + rTreeView.show(); + + rTreeView.connect_changed( + LINK( this, SvxMenuConfigPage, SelectMenuEntry ) ); + rTreeView.connect_popup_menu( LINK( this, SvxMenuConfigPage, ContentContextMenuHdl ) ); + + m_xFunctions->get_widget().connect_popup_menu( + LINK( this, SvxMenuConfigPage, FunctionContextMenuHdl ) ); + + m_xGearBtn->connect_selected(LINK(this, SvxMenuConfigPage, GearHdl)); + + m_xCommandCategoryListBox->connect_changed(LINK(this, SvxMenuConfigPage, SelectCategory)); + + m_xMoveUpButton->connect_clicked( LINK( this, SvxConfigPage, MoveHdl) ); + m_xMoveDownButton->connect_clicked( LINK( this, SvxConfigPage, MoveHdl) ); + + m_xAddCommandButton->connect_clicked( LINK( this, SvxMenuConfigPage, AddCommandHdl ) ); + m_xRemoveCommandButton->connect_clicked( LINK( this, SvxMenuConfigPage, RemoveCommandHdl ) ); + + m_xInsertBtn->connect_selected( + LINK( this, SvxMenuConfigPage, InsertHdl ) ); + m_xModifyBtn->connect_selected( + LINK( this, SvxMenuConfigPage, ModifyItemHdl ) ); + m_xResetBtn->connect_clicked( + LINK( this, SvxMenuConfigPage, ResetMenuHdl ) ); + + // These operations are not possible on menus/context menus yet + m_xModifyBtn->remove_item("changeIcon"); + m_xModifyBtn->remove_item("resetIcon"); + m_xModifyBtn->remove_item("restoreItem"); + + if ( !bIsMenuBar ) + { + //TODO: Remove this when the gear button is implemented for context menus + m_xGearBtn->set_sensitive(false); + m_xGearBtn->hide(); + } + else + { + // TODO: Remove this when it is possible to reset menubar menus individually + m_xResetBtn->set_sensitive(false); + } +} + +void SvxMenuConfigPage::ListModified() +{ + // regenerate with the current ordering within the list + SvxEntries* pEntries = GetTopLevelSelection()->GetEntries(); + pEntries->clear(); + + for (int i = 0; i < m_xContentsListBox->n_children(); ++i) + pEntries->push_back(reinterpret_cast(m_xContentsListBox->get_id(i).toInt64())); + + GetSaveInData()->SetModified(); + GetTopLevelSelection()->SetModified(); + UpdateButtonStates(); +} + +IMPL_LINK(SvxMenuConfigPage, MenuEntriesSizeAllocHdl, const Size&, rSize, void) +{ + weld::TreeView& rTreeView = m_xContentsListBox->get_widget(); + std::vector aWidths; + + int nExpectedSize = 16; + + int nStandardImageColWidth = rTreeView.get_checkbox_column_width(); + int nMargin = nStandardImageColWidth - nExpectedSize; + if (nMargin < 16) + nMargin = 16; + + if (SvxConfigPageHelper::GetImageType() & css::ui::ImageType::SIZE_LARGE) + nExpectedSize = 24; + else if (SvxConfigPageHelper::GetImageType() & css::ui::ImageType::SIZE_32) + nExpectedSize = 32; + + int nImageColWidth = nExpectedSize + nMargin; + + aWidths.push_back(nImageColWidth); + aWidths.push_back(rSize.Width() - (nImageColWidth + nStandardImageColWidth)); + rTreeView.set_column_fixed_widths(aWidths); +} + +SvxMenuConfigPage::~SvxMenuConfigPage() +{ + for (int i = 0, nCount = m_xSaveInListBox->get_count(); i < nCount; ++i) + delete reinterpret_cast(m_xSaveInListBox->get_id(i).toInt64()); + m_xSaveInListBox->clear(); +} + +// Populates the Menu combo box +void SvxMenuConfigPage::Init() +{ + // ensure that the UI is cleared before populating it + m_xTopLevelListBox->clear(); + m_xContentsListBox->clear(); + + ReloadTopLevelListBox(); + + m_xTopLevelListBox->set_active(0); + SelectElement(); + + m_xCommandCategoryListBox->Init( + comphelper::getProcessComponentContext(), + m_xFrame, m_aModuleId); + m_xCommandCategoryListBox->categorySelected(m_xFunctions.get(), OUString(), GetSaveInData()); +} + +IMPL_LINK_NOARG(SvxMenuConfigPage, SelectMenuEntry, weld::TreeView&, void) +{ + UpdateButtonStates(); +} + +void SvxMenuConfigPage::UpdateButtonStates() +{ + // Disable Up and Down buttons depending on current selection + int selection = m_xContentsListBox->get_selected_index(); + + bool bIsSeparator = + selection != -1 && reinterpret_cast(m_xContentsListBox->get_id(selection).toInt64())->IsSeparator(); + bool bIsValidSelection = + !(m_xContentsListBox->n_children() == 0 || selection == -1); + + m_xMoveUpButton->set_sensitive( + bIsValidSelection && selection != 0 ); + m_xMoveDownButton->set_sensitive( + bIsValidSelection && selection != m_xContentsListBox->n_children() - 1); + + m_xRemoveCommandButton->set_sensitive( bIsValidSelection ); + + m_xModifyBtn->set_sensitive( bIsValidSelection && !bIsSeparator); + + // If there is no top level selection (menu), then everything working on the right box + // which contains the functions of the selected menu/toolbar needs to be disabled + SvxConfigEntry* pMenuData = GetTopLevelSelection(); + + m_xInsertBtn->set_sensitive(pMenuData != nullptr); + + m_xAddCommandButton->set_sensitive(pMenuData != nullptr); + m_xRemoveCommandButton->set_sensitive(pMenuData != nullptr); + + //Handle the gear button + if (pMenuData && m_bIsMenuBar) + { + // Add option (gear_add) will always be enabled + m_xGearBtn->set_item_sensitive( "menu_gear_delete", pMenuData->IsDeletable() ); + m_xGearBtn->set_item_sensitive( "menu_gear_rename", pMenuData->IsRenamable() ); + m_xGearBtn->set_item_sensitive( "menu_gear_move", pMenuData->IsMovable() ); + } +} + +void SvxMenuConfigPage::DeleteSelectedTopLevel() +{ + SvxConfigEntry* pMenuData = GetTopLevelSelection(); + + SvxEntries* pParentEntries = + FindParentForChild( GetSaveInData()->GetEntries(), pMenuData ); + + SvxConfigPageHelper::RemoveEntry( pParentEntries, pMenuData ); + delete pMenuData; + + ReloadTopLevelListBox(); + + GetSaveInData()->SetModified( ); +} + +void SvxMenuConfigPage::DeleteSelectedContent() +{ + int nActEntry = m_xContentsListBox->get_selected_index(); + + if (nActEntry == -1) + return; + + // get currently selected menu entry + SvxConfigEntry* pMenuEntry = + reinterpret_cast(m_xContentsListBox->get_id(nActEntry).toInt64()); + + // get currently selected menu + SvxConfigEntry* pMenu = GetTopLevelSelection(); + + // remove menu entry from the list for this menu + SvxConfigPageHelper::RemoveEntry( pMenu->GetEntries(), pMenuEntry ); + + // remove menu entry from UI + m_xContentsListBox->remove(nActEntry); + + // if this is a submenu entry, redraw the menus list box + if ( pMenuEntry->IsPopup() ) + { + ReloadTopLevelListBox(); + } + + // delete data for menu entry + delete pMenuEntry; + + GetSaveInData()->SetModified(); + pMenu->SetModified(); +} + +short SvxMenuConfigPage::QueryReset() +{ + OUString msg = CuiResId( RID_SVXSTR_CONFIRM_MENU_RESET ); + + OUString saveInName = m_xSaveInListBox->get_active_text(); + + OUString label = SvxConfigPageHelper::replaceSaveInName( msg, saveInName ); + + std::unique_ptr xQueryBox(Application::CreateMessageDialog(GetFrameWeld(), + VclMessageType::Question, VclButtonsType::YesNo, + label)); + return xQueryBox->run(); +} + +void SvxMenuConfigPage::SelectElement() +{ + weld::TreeView& rTreeView = m_xContentsListBox->get_widget(); + + SvxConfigEntry* pMenuData = GetTopLevelSelection(); + if (!pMenuData) + rTreeView.clear(); + else + { + SvxEntries* pEntries = pMenuData->GetEntries(); + + rTreeView.bulk_insert_for_each(pEntries->size(), [this, &rTreeView, pEntries](weld::TreeIter& rIter, int nIdx) { + auto const& entry = (*pEntries)[nIdx]; + OUString sId(OUString::number(reinterpret_cast(entry))); + rTreeView.set_id(rIter, sId); + InsertEntryIntoUI(entry, rTreeView, rIter, 0); + }); + } + + UpdateButtonStates(); +} + +IMPL_LINK(SvxMenuConfigPage, GearHdl, const OString&, rIdent, void) +{ + if (rIdent == "menu_gear_add") + { + SvxMainMenuOrganizerDialog aDialog(GetFrameWeld(), + GetSaveInData()->GetEntries(), nullptr, true ); + + if (aDialog.run() == RET_OK) + { + GetSaveInData()->SetEntries(aDialog.ReleaseEntries()); + ReloadTopLevelListBox(aDialog.GetSelectedEntry()); + GetSaveInData()->SetModified(); + } + } + else if (rIdent == "menu_gear_delete") + { + DeleteSelectedTopLevel(); + } + else if (rIdent == "menu_gear_rename") + { + SvxConfigEntry* pMenuData = GetTopLevelSelection(); + + OUString sCurrentName( SvxConfigPageHelper::stripHotKey( pMenuData->GetName() ) ); + OUString sDesc = CuiResId( RID_SVXSTR_LABEL_NEW_NAME ); + + SvxNameDialog aNameDialog(GetFrameWeld(), sCurrentName, sDesc); + aNameDialog.set_help_id(HID_SVX_CONFIG_RENAME_MENU); + aNameDialog.set_title(CuiResId(RID_SVXSTR_RENAME_MENU)); + + if ( aNameDialog.run() == RET_OK ) + { + OUString sNewName = aNameDialog.GetName(); + + if ( sCurrentName == sNewName ) + return; + + pMenuData->SetName( sNewName ); + + ReloadTopLevelListBox(); + + GetSaveInData()->SetModified(); + } + } + else if (rIdent == "menu_gear_move") + { + SvxConfigEntry* pMenuData = GetTopLevelSelection(); + + SvxMainMenuOrganizerDialog aDialog(GetFrameWeld(), GetSaveInData()->GetEntries(), + pMenuData, false ); + if (aDialog.run() == RET_OK) + { + GetSaveInData()->SetEntries(aDialog.ReleaseEntries()); + + ReloadTopLevelListBox(); + + GetSaveInData()->SetModified(); + } + } + else + { + //This block should never be reached + SAL_WARN("cui.customize", "Unknown gear menu option: " << rIdent); + return; + } + + UpdateButtonStates(); +} + +IMPL_LINK_NOARG(SvxMenuConfigPage, SelectCategory, weld::ComboBox&, void) +{ + OUString aSearchTerm( m_xSearchEdit->get_text() ); + + m_xCommandCategoryListBox->categorySelected(m_xFunctions.get(), aSearchTerm, GetSaveInData()); +} + +IMPL_LINK_NOARG( SvxMenuConfigPage, AddCommandHdl, weld::Button&, void ) +{ + int nPos = AddFunction(-1, /*bAllowDuplicates*/false); + if (nPos == -1) + return; + weld::TreeView& rTreeView = m_xContentsListBox->get_widget(); + SvxConfigEntry* pEntry = + reinterpret_cast(rTreeView.get_id(nPos).toInt64()); + InsertEntryIntoUI(pEntry, rTreeView, nPos, 0); +} + +IMPL_LINK_NOARG( SvxMenuConfigPage, RemoveCommandHdl, weld::Button&, void ) +{ + DeleteSelectedContent(); + if ( GetSaveInData()->IsModified() ) + { + UpdateButtonStates(); + } +} + +IMPL_LINK(SvxMenuConfigPage, InsertHdl, const OString&, rIdent, void) +{ + weld::TreeView& rTreeView = m_xContentsListBox->get_widget(); + if (rIdent == "insertseparator") + { + SvxConfigEntry* pNewEntryData = new SvxConfigEntry; + pNewEntryData->SetUserDefined(); + int nPos = AppendEntry(pNewEntryData, -1); + InsertEntryIntoUI(pNewEntryData, rTreeView, nPos, 0); + } + else if (rIdent == "insertsubmenu") + { + OUString aNewName; + OUString aDesc = CuiResId( RID_SVXSTR_SUBMENU_NAME ); + + SvxNameDialog aNameDialog(GetFrameWeld(), aNewName, aDesc); + aNameDialog.set_help_id(HID_SVX_CONFIG_NAME_SUBMENU); + aNameDialog.set_title(CuiResId( RID_SVXSTR_ADD_SUBMENU)); + + if (aNameDialog.run() == RET_OK) + { + aNewName = aNameDialog.GetName(); + + SvxConfigEntry* pNewEntryData = + new SvxConfigEntry( aNewName, aNewName, true, /*bParentData*/false ); + pNewEntryData->SetName( aNewName ); + pNewEntryData->SetUserDefined(); + + int nPos = AppendEntry(pNewEntryData, -1); + InsertEntryIntoUI(pNewEntryData, rTreeView, nPos, 0); + + ReloadTopLevelListBox(); + + m_xContentsListBox->scroll_to_row(nPos); + m_xContentsListBox->select(nPos); + + GetSaveInData()->SetModified(); + } + + } + else + { + //This block should never be reached + SAL_WARN("cui.customize", "Unknown insert option: " << rIdent); + return; + } + + if ( GetSaveInData()->IsModified() ) + { + UpdateButtonStates(); + } +} + +IMPL_LINK(SvxMenuConfigPage, ModifyItemHdl, const OString&, rIdent, void) +{ + if (rIdent == "renameItem") + { + int nActEntry = m_xContentsListBox->get_selected_index(); + SvxConfigEntry* pEntry = + reinterpret_cast(m_xContentsListBox->get_id(nActEntry).toInt64()); + + OUString aNewName( SvxConfigPageHelper::stripHotKey( pEntry->GetName() ) ); + OUString aDesc = CuiResId( RID_SVXSTR_LABEL_NEW_NAME ); + + SvxNameDialog aNameDialog(GetFrameWeld(), aNewName, aDesc); + aNameDialog.set_help_id(HID_SVX_CONFIG_RENAME_MENU_ITEM); + aNameDialog.set_title(CuiResId(RID_SVXSTR_RENAME_MENU)); + + if (aNameDialog.run() == RET_OK) + { + aNewName = aNameDialog.GetName(); + + pEntry->SetName( aNewName ); + m_xContentsListBox->set_text(nActEntry, aNewName, 1); + + GetSaveInData()->SetModified(); + GetTopLevelSelection()->SetModified(); + } + } + else + { + //This block should never be reached + SAL_WARN("cui.customize", "Unknown insert option: " << rIdent); + return; + } + + if ( GetSaveInData()->IsModified() ) + { + UpdateButtonStates(); + } +} + +IMPL_LINK_NOARG(SvxMenuConfigPage, ResetMenuHdl, weld::Button&, void) +{ + SvxConfigEntry* pMenuData = GetTopLevelSelection(); + + if (pMenuData == nullptr) + { + SAL_WARN("cui.customize", "RHB top level selection is null. A menu must be selected to reset!"); + return; + } + + std::unique_ptr xQueryBox(Application::CreateMessageDialog(GetFrameWeld(), + VclMessageType::Question, VclButtonsType::YesNo, + CuiResId(RID_SVXSTR_CONFIRM_RESTORE_DEFAULT_MENU))); + + // Resetting individual top-level menus is not possible at the moment. + // So we are resetting only if it is a context menu + if (!(!m_bIsMenuBar && xQueryBox->run() == RET_YES)) + return; + + sal_Int32 nPos = m_xTopLevelListBox->get_active(); + ContextMenuSaveInData* pSaveInData = static_cast< ContextMenuSaveInData* >(GetSaveInData()); + + pSaveInData->ResetContextMenu(pMenuData); + + // ensure that the UI is cleared before populating it + m_xTopLevelListBox->clear(); + m_xContentsListBox->clear(); + + ReloadTopLevelListBox(); + + // Reselect the reset menu + m_xTopLevelListBox->set_active(nPos); + SelectElement(); +} + +SaveInData* SvxMenuConfigPage::CreateSaveInData( + const css::uno::Reference< css::ui::XUIConfigurationManager >& xCfgMgr, + const css::uno::Reference< css::ui::XUIConfigurationManager >& xParentCfgMgr, + const OUString& aModuleId, + bool bDocConfig ) +{ + if ( !m_bIsMenuBar ) + return static_cast< SaveInData* >( new ContextMenuSaveInData( xCfgMgr, xParentCfgMgr, aModuleId, bDocConfig ) ); + + return static_cast< SaveInData* >( new MenuSaveInData( xCfgMgr, xParentCfgMgr, aModuleId, bDocConfig ) ); +} + +IMPL_LINK( SvxMenuConfigPage, ContentContextMenuHdl, const CommandEvent&, rCEvt, bool ) +{ + if (rCEvt.GetCommand() != CommandEventId::ContextMenu) + return false; + + weld::TreeView& rTreeView = m_xContentsListBox->get_widget(); + + // Select clicked entry + std::unique_ptr xIter(rTreeView.make_iterator()); + if (! rTreeView.get_dest_row_at_pos( rCEvt.GetMousePosPixel(), xIter.get(), false )) + return false; + rTreeView.select(*xIter); + SelectMenuEntry( rTreeView ); + + int nSelectIndex = m_xContentsListBox->get_selected_index(); + + bool bIsSeparator = + nSelectIndex != -1 && reinterpret_cast(m_xContentsListBox->get_id(nSelectIndex).toInt64())->IsSeparator(); + bool bIsValidSelection = + !( m_xContentsListBox->n_children() == 0 || nSelectIndex == -1 ); + + std::unique_ptr xBuilder(Application::CreateBuilder( &rTreeView, "cui/ui/entrycontextmenu.ui" ) ); + auto xContextMenu = xBuilder->weld_menu("menu"); + xContextMenu->set_visible("add", false); + xContextMenu->set_visible("remove", bIsValidSelection); + xContextMenu->set_visible("rename", bIsValidSelection && !bIsSeparator); + xContextMenu->set_visible("changeIcon", false); + xContextMenu->set_visible("resetIcon", false); + xContextMenu->set_visible("restoreDefault", false); + OString sCommand(xContextMenu->popup_at_rect( &rTreeView, tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1,1) ) ) ); + + if ( sCommand == "remove") + { + RemoveCommandHdl( *m_xRemoveCommandButton ); + } + else if ( sCommand == "rename" ) + { + ModifyItemHdl( "renameItem" ); + } + else if ( !sCommand.isEmpty() ) + SAL_WARN("cui.customize", "Unknown context menu action: " << sCommand ); + return true; +} + +IMPL_LINK( SvxMenuConfigPage, FunctionContextMenuHdl, const CommandEvent&, rCEvt, bool ) +{ + if (rCEvt.GetCommand() != CommandEventId::ContextMenu) + return false; + + weld::TreeView& rTreeView = m_xFunctions->get_widget(); + + // Select clicked entry + std::unique_ptr xIter(rTreeView.make_iterator()); + if (! rTreeView.get_dest_row_at_pos( rCEvt.GetMousePosPixel(), xIter.get(), false )) + return false; + rTreeView.select(*xIter); + SelectFunctionHdl( rTreeView ); + + std::unique_ptr xBuilder(Application::CreateBuilder( &rTreeView, "cui/ui/entrycontextmenu.ui" ) ); + auto xContextMenu = xBuilder->weld_menu("menu"); + xContextMenu->set_visible("add", true); + xContextMenu->set_visible("remove", false); + xContextMenu->set_visible("rename", false); + xContextMenu->set_visible("changeIcon", false); + xContextMenu->set_visible("resetIcon", false); + xContextMenu->set_visible("restoreDefault", false); + OString sCommand(xContextMenu->popup_at_rect( &rTreeView, tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1,1) ) ) ); + + if ( sCommand == "add") + { + AddCommandHdl( *m_xAddCommandButton ); + } + else if ( !sCommand.isEmpty() ) + SAL_WARN("cui.customize", "Unknown context menu action: " << sCommand ); + return true; +} + + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/customize/SvxNotebookbarConfigPage.cxx b/cui/source/customize/SvxNotebookbarConfigPage.cxx new file mode 100644 index 000000000..0fb05678b --- /dev/null +++ b/cui/source/customize/SvxNotebookbarConfigPage.cxx @@ -0,0 +1,567 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace uno = com::sun::star::uno; +namespace frame = com::sun::star::frame; +namespace lang = com::sun::star::lang; +namespace container = com::sun::star::container; +namespace beans = com::sun::star::beans; +namespace graphic = com::sun::star::graphic; + +static bool isCategoryAvailable(const OUString& sClassId, const OUString& sUIItemId, + const OUString& sActiveCategory, bool& isCategory) +{ + if (sUIItemId == sActiveCategory) + return true; + else if ((sClassId == "GtkMenu" || sClassId == "GtkGrid") && sUIItemId != sActiveCategory) + { + isCategory = false; + return false; + } + return false; +} + +static OUString charToString(const char* cString) +{ + return OUString(cString, strlen(cString), RTL_TEXTENCODING_UTF8); +} + +static OUString getFileName(const OUString& aFileName) +{ + if (aFileName == "notebookbar.ui") + return "Tabbed"; + else if (aFileName == "notebookbar_compact.ui") + return "TabbedCompact"; + else if (aFileName == "notebookbar_groupedbar_full.ui") + return "Groupedbar"; + else if (aFileName == "notebookbar_groupedbar_compact.ui") + return "GroupedbarCompact"; + else + return "None"; +} + +static OUString getModuleId(const OUString& sModuleName) +{ + if (sModuleName == "Writer") + return "com.sun.star.text.TextDocument"; + else if (sModuleName == "Draw") + return "com.sun.star.drawing.DrawingDocument"; + else if (sModuleName == "Impress") + return "com.sun.star.presentation.PresentationDocument"; + else if (sModuleName == "Calc") + return "com.sun.star.sheet.SpreadsheetDocument"; + else + return "None"; +} + +SvxNotebookbarConfigPage::SvxNotebookbarConfigPage(weld::Container* pPage, + weld::DialogController* pController, + const SfxItemSet& rSet) + : SvxConfigPage(pPage, pController, rSet) +{ + m_xCommandCategoryListBox->set_visible(false); + m_xDescriptionFieldLb->set_visible(false); + m_xSearchEdit->set_visible(false); + m_xDescriptionField->set_visible(false); + m_xMoveUpButton->set_visible(false); + m_xMoveDownButton->set_visible(false); + m_xAddCommandButton->set_visible(false); + m_xRemoveCommandButton->set_visible(false); + m_xLeftFunctionLabel->set_visible(false); + m_xSearchLabel->set_visible(false); + m_xCategoryLabel->set_visible(false); + m_xInsertBtn->set_visible(false); + m_xModifyBtn->set_visible(false); + m_xResetBtn->set_visible(false); + m_xCustomizeLabel->set_visible(false); + + weld::TreeView& rCommandCategoryBox = m_xFunctions->get_widget(); + rCommandCategoryBox.hide(); + + m_xContentsListBox.reset( + new SvxNotebookbarEntriesListBox(m_xBuilder->weld_tree_view("toolcontents"), this)); + m_xDropTargetHelper.reset( + new SvxConfigPageFunctionDropTarget(*this, m_xContentsListBox->get_widget())); + std::vector aWidths; + weld::TreeView& rTreeView = m_xContentsListBox->get_widget(); + Size aSize(m_xFunctions->get_size_request()); + rTreeView.set_size_request(aSize.Width(), aSize.Height()); + + int nExpectedSize = 16; + + int nStandardImageColWidth = rTreeView.get_checkbox_column_width(); + int nMargin = nStandardImageColWidth - nExpectedSize; + if (nMargin < 16) + nMargin = 16; + + if (SvxConfigPageHelper::GetImageType() & css::ui::ImageType::SIZE_LARGE) + nExpectedSize = 24; + else if (SvxConfigPageHelper::GetImageType() & css::ui::ImageType::SIZE_32) + nExpectedSize = 32; + + int nImageColWidth = nExpectedSize + nMargin; + + aWidths.push_back(nStandardImageColWidth); + aWidths.push_back(nImageColWidth); + rTreeView.set_column_fixed_widths(aWidths); + + rTreeView.set_hexpand(true); + rTreeView.set_vexpand(true); + rTreeView.set_help_id(HID_SVX_CONFIG_NOTEBOOKBAR_CONTENTS); + rTreeView.show(); +} + +SvxNotebookbarConfigPage::~SvxNotebookbarConfigPage() {} + +void SvxNotebookbarConfigPage::DeleteSelectedTopLevel() {} + +void SvxNotebookbarConfigPage::DeleteSelectedContent() {} + +void SvxNotebookbarConfigPage::Init() +{ + m_xTopLevelListBox->clear(); + m_xContentsListBox->clear(); + m_xSaveInListBox->clear(); + CustomNotebookbarGenerator::createCustomizedUIFile(); + OUString sNotebookbarInterface = getFileName(m_sFileName); + + OUString sScopeName + = utl::ConfigManager::getProductName() + " " + m_sAppName + " - " + sNotebookbarInterface; + OUString sSaveInListBoxID = notebookbarTabScope; + + m_xSaveInListBox->append(sSaveInListBoxID, sScopeName); + m_xSaveInListBox->set_active_id(sSaveInListBoxID); + + m_xTopLevelListBox->append("NotebookBar", "All Commands"); + m_xTopLevelListBox->set_active_id("NotebookBar"); + SelectElement(); +} + +SaveInData* SvxNotebookbarConfigPage::CreateSaveInData( + const css::uno::Reference& xCfgMgr, + const css::uno::Reference& xParentCfgMgr, + const OUString& aModuleId, bool bDocConfig) +{ + return static_cast( + new ToolbarSaveInData(xCfgMgr, xParentCfgMgr, aModuleId, bDocConfig)); +} + +void SvxNotebookbarConfigPage::UpdateButtonStates() {} + +short SvxNotebookbarConfigPage::QueryReset() +{ + OUString msg = CuiResId(RID_SVXSTR_CONFIRM_TOOLBAR_RESET); + + OUString saveInName = m_xSaveInListBox->get_active_text(); + + OUString label = SvxConfigPageHelper::replaceSaveInName(msg, saveInName); + + std::unique_ptr xQueryBox(Application::CreateMessageDialog( + GetFrameWeld(), VclMessageType::Question, VclButtonsType::YesNo, label)); + int nValue = xQueryBox->run(); + if (nValue == RET_YES) + { + OUString sOriginalUIPath = CustomNotebookbarGenerator::getOriginalUIPath(); + OUString sCustomizedUIPath = CustomNotebookbarGenerator::getCustomizedUIPath(); + osl::File::copy(sOriginalUIPath, sCustomizedUIPath); + OUString sNotebookbarInterface = getFileName(m_sFileName); + Sequence sSequenceEntries; + CustomNotebookbarGenerator::setCustomizedUIItem(sSequenceEntries, sNotebookbarInterface); + OUString sUIPath = "modules/s" + m_sAppName.toAsciiLowerCase() + "/ui/"; + sfx2::SfxNotebookBar::ReloadNotebookBar(sUIPath); + } + return nValue; +} + +void SvxConfigPage::InsertEntryIntoNotebookbarTabUI(const OUString& sClassId, + const OUString& sUIItemId, + const OUString& sUIItemCommand, + weld::TreeView& rTreeView, + weld::TreeIter& rIter, int nStartCol) +{ + css::uno::Reference m_xCommandToLabelMap; + uno::Reference xContext = ::comphelper::getProcessComponentContext(); + uno::Reference xNameAccess( + css::frame::theUICommandDescription::get(xContext)); + + uno::Sequence aPropSeq; + + xNameAccess->getByName(getModuleId(m_sAppName)) >>= m_xCommandToLabelMap; + + try + { + uno::Any aModuleVal = m_xCommandToLabelMap->getByName(sUIItemCommand); + + aModuleVal >>= aPropSeq; + } + catch (container::NoSuchElementException&) + { + } + + OUString aLabel; + for (auto const& prop : std::as_const(aPropSeq)) + if (prop.Name == "Name") + prop.Value >>= aLabel; + + OUString aName = SvxConfigPageHelper::stripHotKey(aLabel); + + if (sClassId == "GtkSeparatorMenuItem" || sClassId == "GtkSeparator") + { + OUString sDataInTree = "--------------------------------------------"; + rTreeView.set_text(rIter, sDataInTree, nStartCol + 1); + } + else + { + if (aName.isEmpty()) + aName = sUIItemId; + auto xImage = GetSaveInData()->GetImage(sUIItemCommand); + if (xImage.is()) + rTreeView.set_image(rIter, xImage, nStartCol); + rTreeView.set_text(rIter, aName, nStartCol + 1); + rTreeView.set_id(rIter, sUIItemId); + } +} + +void SvxNotebookbarConfigPage::getNodeValue(xmlNode* pNodePtr, NotebookbarEntries& aNodeEntries) +{ + pNodePtr = pNodePtr->xmlChildrenNode; + while (pNodePtr) + { + if (!(xmlStrcmp(pNodePtr->name, reinterpret_cast("property")))) + { + xmlChar* UriValue = xmlGetProp(pNodePtr, reinterpret_cast("name")); + if (!(xmlStrcmp(UriValue, reinterpret_cast("visible")))) + { + xmlChar* aValue = xmlNodeGetContent(pNodePtr); + const char* cVisibleValue = reinterpret_cast(aValue); + aNodeEntries.sVisibleValue = charToString(cVisibleValue); + xmlFree(aValue); + } + if (!(xmlStrcmp(UriValue, reinterpret_cast("action_name")))) + { + xmlChar* aValue = xmlNodeGetContent(pNodePtr); + const char* cActionName = reinterpret_cast(aValue); + aNodeEntries.sActionName = charToString(cActionName); + xmlFree(aValue); + } + xmlFree(UriValue); + } + pNodePtr = pNodePtr->next; + } +} + +void SvxNotebookbarConfigPage::searchNodeandAttribute(std::vector& aEntries, + std::vector& aCategoryList, + OUString& sActiveCategory, + CategoriesEntries& aCurItemEntry, + xmlNode* pNodePtr, bool isCategory) +{ + pNodePtr = pNodePtr->xmlChildrenNode; + while (pNodePtr) + { + if (pNodePtr->type == XML_ELEMENT_NODE) + { + const char* cNodeName = reinterpret_cast(pNodePtr->name); + if (strcmp(cNodeName, "object") == 0) + { + OUString sSecondVal; + + xmlChar* UriValue = xmlGetProp(pNodePtr, reinterpret_cast("id")); + const char* cUIItemID = reinterpret_cast(UriValue); + OUString sUIItemId = charToString(cUIItemID); + xmlFree(UriValue); + + UriValue = xmlGetProp(pNodePtr, reinterpret_cast("class")); + const char* cClassId = reinterpret_cast(UriValue); + OUString sClassId = charToString(cClassId); + xmlFree(UriValue); + + CategoriesEntries aCategoryEntry; + if (sClassId == "sfxlo-PriorityHBox") + { + aCategoryEntry.sDisplayName = sUIItemId; + aCategoryEntry.sUIItemId = sUIItemId; + aCategoryEntry.sClassType = sClassId; + aCategoryList.push_back(aCategoryEntry); + + aCurItemEntry = aCategoryEntry; + } + else if (sClassId == "sfxlo-PriorityMergedHBox") + { + aCategoryEntry.sDisplayName = aCurItemEntry.sDisplayName + " | " + sUIItemId; + aCategoryEntry.sUIItemId = sUIItemId; + aCategoryEntry.sClassType = sClassId; + + if (aCurItemEntry.sClassType == sClassId) + { + sal_Int32 rPos = 0; + aCategoryEntry.sDisplayName + = aCurItemEntry.sDisplayName.getToken(rPos, ' ', rPos) + " | " + + sUIItemId; + } + aCategoryList.push_back(aCategoryEntry); + aCurItemEntry = aCategoryEntry; + } + else if (sClassId == "svtlo-ManagedMenuButton") + { + sal_Int32 rPos = 1; + sSecondVal = sUIItemId.getToken(rPos, ':', rPos); + if (!sSecondVal.isEmpty()) + { + aCategoryEntry.sDisplayName + = aCurItemEntry.sDisplayName + " | " + sSecondVal; + aCategoryEntry.sUIItemId = sSecondVal; + aCategoryList.push_back(aCategoryEntry); + } + } + + NotebookbarEntries nodeEntries; + if (isCategoryAvailable(sClassId, sUIItemId, sActiveCategory, isCategory) + || isCategory) + { + isCategory = true; + if (sClassId == "GtkMenuItem" || sClassId == "GtkToolButton" + || sClassId == "GtkMenuToolButton" + || (sClassId == "svtlo-ManagedMenuButton" && sSecondVal.isEmpty())) + { + nodeEntries.sClassId = sClassId; + nodeEntries.sUIItemId = sUIItemId; + nodeEntries.sDisplayName = sUIItemId; + + getNodeValue(pNodePtr, nodeEntries); + aEntries.push_back(nodeEntries); + } + else if (sClassId == "GtkSeparatorMenuItem" || sClassId == "GtkSeparator") + { + nodeEntries.sClassId = sClassId; + nodeEntries.sUIItemId = sUIItemId; + nodeEntries.sDisplayName = "Null"; + nodeEntries.sVisibleValue = "Null"; + nodeEntries.sActionName = "Null"; + aEntries.push_back(nodeEntries); + } + else if (sClassId == "sfxlo-PriorityHBox" + || sClassId == "sfxlo-PriorityMergedHBox" + || sClassId == "svtlo-ManagedMenuButton") + { + nodeEntries.sClassId = sClassId; + nodeEntries.sUIItemId = sUIItemId; + nodeEntries.sDisplayName + = aCategoryList[aCategoryList.size() - 1].sDisplayName; + nodeEntries.sVisibleValue = "Null"; + nodeEntries.sActionName = "Null"; + aEntries.push_back(nodeEntries); + } + } + } + searchNodeandAttribute(aEntries, aCategoryList, sActiveCategory, aCurItemEntry, + pNodePtr, isCategory); + } + pNodePtr = pNodePtr->next; + } +} + +void SvxNotebookbarConfigPage::FillFunctionsList(xmlNodePtr pRootNodePtr, + std::vector& aEntries, + std::vector& aCategoryList, + OUString& sActiveCategory) +{ + CategoriesEntries aCurItemEntry; + searchNodeandAttribute(aEntries, aCategoryList, sActiveCategory, aCurItemEntry, pRootNodePtr, + false); +} + +void SvxNotebookbarConfigPage::SelectElement() +{ + OString sUIFileUIPath = CustomNotebookbarGenerator::getSystemPath( + CustomNotebookbarGenerator::getCustomizedUIPath()); + xmlDocPtr pDoc = xmlParseFile(sUIFileUIPath.getStr()); + if (!pDoc) + return; + xmlNodePtr pNodePtr = xmlDocGetRootElement(pDoc); + + std::vector aEntries; + std::vector aCategoryList; + OUString sActiveCategory = m_xTopLevelListBox->get_active_id(); + FillFunctionsList(pNodePtr, aEntries, aCategoryList, sActiveCategory); + + if (m_xTopLevelListBox->get_count() == 1) + { + for (std::size_t nIdx = 0; nIdx < aCategoryList.size(); nIdx++) + m_xTopLevelListBox->append(aCategoryList[nIdx].sUIItemId, + aCategoryList[nIdx].sDisplayName); + } + unsigned long nStart = 0; + if (aEntries[nStart].sClassId == "sfxlo-PriorityHBox" + || aEntries[nStart].sClassId == "sfxlo-PriorityMergedHBox") + nStart = 1; + + std::vector aTempEntries; + for (std::size_t nIdx = nStart; nIdx < aEntries.size(); nIdx++) + { + if (aEntries[nIdx].sClassId == "svtlo-ManagedMenuButton") + { + aTempEntries.push_back(aEntries[nIdx]); + std::vector aGtkEntries; + sal_Int32 rPos = 1; + sActiveCategory = aEntries[nIdx].sUIItemId.getToken(rPos, ':', rPos); + FillFunctionsList(pNodePtr, aGtkEntries, aCategoryList, sActiveCategory); + for (std::size_t Idx = 0; Idx < aGtkEntries.size(); Idx++) + aTempEntries.push_back(aGtkEntries[Idx]); + aGtkEntries.clear(); + } + else + aTempEntries.push_back(aEntries[nIdx]); + } + + aEntries = aTempEntries; + aTempEntries.clear(); + + weld::TreeView& rTreeView = m_xContentsListBox->get_widget(); + rTreeView.bulk_insert_for_each( + aEntries.size(), [this, &rTreeView, &aEntries](weld::TreeIter& rIter, int nIdx) { + OUString sId(OUString::number(nIdx)); + rTreeView.set_id(rIter, sId); + if (aEntries[nIdx].sActionName != "Null") + { + if (aEntries[nIdx].sVisibleValue == "True") + { + rTreeView.set_toggle(rIter, TRISTATE_TRUE, 0); + } + else + { + rTreeView.set_toggle(rIter, TRISTATE_FALSE, 0); + } + } + InsertEntryIntoNotebookbarTabUI(aEntries[nIdx].sClassId, aEntries[nIdx].sDisplayName, + aEntries[nIdx].sActionName, rTreeView, rIter, 1); + }); + + aEntries.clear(); + + xmlFreeDoc(pDoc); +} + +SvxNotebookbarEntriesListBox::SvxNotebookbarEntriesListBox(std::unique_ptr xParent, + SvxConfigPage* pPg) + : SvxMenuEntriesListBox(std::move(xParent), pPg) +{ + m_xControl->connect_toggled(LINK(this, SvxNotebookbarEntriesListBox, CheckButtonHdl)); + m_xControl->connect_key_press(Link()); + m_xControl->connect_key_press(LINK(this, SvxNotebookbarEntriesListBox, KeyInputHdl)); +} + +SvxNotebookbarEntriesListBox::~SvxNotebookbarEntriesListBox() {} + +static void EditRegistryFile(const OUString& sUIItemId, const OUString& sSetEntry, + const OUString& sNotebookbarInterface) +{ + int nFlag = 0; + Sequence aOldEntries + = CustomNotebookbarGenerator::getCustomizedUIItem(sNotebookbarInterface); + Sequence aNewEntries(aOldEntries.getLength() + 1); + for (int nIdx = 0; nIdx < aOldEntries.getLength(); nIdx++) + { + sal_Int32 rPos = 0; + OUString sFirstValue = aOldEntries[nIdx].getToken(rPos, ',', rPos); + if (sFirstValue == sUIItemId) + { + aOldEntries[nIdx] = sSetEntry; + nFlag = 1; + break; + } + aNewEntries[nIdx] = aOldEntries[nIdx]; + } + + if (nFlag == 0) + { + aNewEntries[aOldEntries.getLength()] = sSetEntry; + CustomNotebookbarGenerator::setCustomizedUIItem(aNewEntries, sNotebookbarInterface); + } + else + { + CustomNotebookbarGenerator::setCustomizedUIItem(aOldEntries, sNotebookbarInterface); + } +} + +void SvxNotebookbarEntriesListBox::ChangedVisibility(int nRow) +{ + OUString sUIItemId = m_xControl->get_selected_id(); + OUString sNotebookbarInterface = getFileName(m_pPage->GetFileName()); + + OUString sVisible; + if (m_xControl->get_toggle(nRow, 0) == TRISTATE_TRUE) + sVisible = "True"; + else + sVisible = "False"; + OUString sSetEntries = sUIItemId + ",visible," + sVisible; + Sequence sSeqOfEntries(1); + sSeqOfEntries[0] = sSetEntries; + EditRegistryFile(sUIItemId, sSetEntries, sNotebookbarInterface); + CustomNotebookbarGenerator::modifyCustomizedUIFile(sSeqOfEntries); + OUString sUIPath = "modules/s" + m_pPage->GetAppName().toAsciiLowerCase() + "/ui/"; + sfx2::SfxNotebookBar::ReloadNotebookBar(sUIPath); +} + +IMPL_LINK(SvxNotebookbarEntriesListBox, CheckButtonHdl, const row_col&, rRowCol, void) +{ + ChangedVisibility(rRowCol.first); +} + +IMPL_LINK(SvxNotebookbarEntriesListBox, KeyInputHdl, const KeyEvent&, rKeyEvent, bool) +{ + if (rKeyEvent.GetKeyCode() == KEY_SPACE) + { + int nRow = m_xControl->get_selected_index(); + m_xControl->set_toggle( + nRow, m_xControl->get_toggle(nRow, 0) == TRISTATE_TRUE ? TRISTATE_FALSE : TRISTATE_TRUE, + 0); + ChangedVisibility(nRow); + return true; + } + return SvxMenuEntriesListBox::KeyInputHdl(rKeyEvent); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/customize/SvxToolbarConfigPage.cxx b/cui/source/customize/SvxToolbarConfigPage.cxx new file mode 100644 index 000000000..ead5792c0 --- /dev/null +++ b/cui/source/customize/SvxToolbarConfigPage.cxx @@ -0,0 +1,966 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include + +SvxToolbarConfigPage::SvxToolbarConfigPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SvxConfigPage(pPage, pController, rSet) +{ + m_xGearBtn = m_xBuilder->weld_menu_button("toolbargearbtn"); + m_xGearBtn->show(); + m_xContainer->set_help_id(HID_SVX_CONFIG_TOOLBAR); + + m_xContentsListBox.reset(new SvxToolbarEntriesListBox(m_xBuilder->weld_tree_view("toolcontents"), this)); + m_xDropTargetHelper.reset(new SvxConfigPageFunctionDropTarget(*this, m_xContentsListBox->get_widget())); + + std::vector aWidths; + weld::TreeView& rTreeView = m_xContentsListBox->get_widget(); + Size aSize(m_xFunctions->get_size_request()); + rTreeView.set_size_request(aSize.Width(), aSize.Height()); + + int nExpectedSize = 16; + + int nStandardImageColWidth = rTreeView.get_checkbox_column_width(); + int nMargin = nStandardImageColWidth - nExpectedSize; + if (nMargin < 16) + nMargin = 16; + + if (SvxConfigPageHelper::GetImageType() & css::ui::ImageType::SIZE_LARGE) + nExpectedSize = 24; + else if (SvxConfigPageHelper::GetImageType() & css::ui::ImageType::SIZE_32) + nExpectedSize = 32; + + int nImageColWidth = nExpectedSize + nMargin; + + aWidths.push_back(nStandardImageColWidth); + aWidths.push_back(nImageColWidth); + rTreeView.set_column_fixed_widths(aWidths); + + rTreeView.set_hexpand(true); + rTreeView.set_vexpand(true); + rTreeView.set_help_id( HID_SVX_CONFIG_TOOLBAR_CONTENTS ); + rTreeView.show(); + + rTreeView.connect_changed( + LINK( this, SvxToolbarConfigPage, SelectToolbarEntry ) ); + rTreeView.connect_popup_menu( LINK( this, SvxToolbarConfigPage, ContentContextMenuHdl ) ); + + m_xFunctions->get_widget().connect_popup_menu( + LINK( this, SvxToolbarConfigPage, FunctionContextMenuHdl ) ); + + m_xTopLevelListBox->set_help_id ( HID_SVX_TOPLEVELLISTBOX ); + m_xSaveInListBox->set_help_id( HID_SVX_SAVE_IN ); + m_xMoveUpButton->set_help_id( HID_SVX_UP_TOOLBAR_ITEM ); + m_xMoveDownButton->set_help_id( HID_SVX_DOWN_TOOLBAR_ITEM ); + m_xDescriptionField->set_help_id ( HID_SVX_DESCFIELD ); + + m_xCommandCategoryListBox->connect_changed( + LINK( this, SvxToolbarConfigPage, SelectCategory ) ); + + m_xGearBtn->connect_selected( + LINK( this, SvxToolbarConfigPage, GearHdl ) ); + + m_xMoveUpButton->connect_clicked( LINK( this, SvxToolbarConfigPage, MoveHdl) ); + m_xMoveDownButton->connect_clicked( LINK( this, SvxToolbarConfigPage, MoveHdl) ); + // Always enable Up and Down buttons + // added for issue i53677 by shizhoubo + m_xMoveDownButton->set_sensitive(true); + m_xMoveUpButton->set_sensitive(true); + + m_xAddCommandButton->connect_clicked( LINK( this, SvxToolbarConfigPage, AddCommandHdl ) ); + m_xRemoveCommandButton->connect_clicked( LINK( this, SvxToolbarConfigPage, RemoveCommandHdl ) ); + + m_xInsertBtn->connect_selected( + LINK( this, SvxToolbarConfigPage, InsertHdl ) ); + m_xModifyBtn->connect_selected( + LINK( this, SvxToolbarConfigPage, ModifyItemHdl ) ); + m_xResetBtn->connect_clicked( + LINK( this, SvxToolbarConfigPage, ResetToolbarHdl ) ); + + // "Insert Submenu" is irrelevant to the toolbars + m_xInsertBtn->remove_item("insertsubmenu"); + + // Gear menu's "Move" action is irrelevant to the toolbars + m_xGearBtn->set_item_sensitive("toolbar_gear_move", false); + + // default toolbar to select is standardbar unless a different one + // has been passed in + m_aURLToSelect = ITEM_TOOLBAR_URL; + m_aURLToSelect += "standardbar"; + + const SfxPoolItem* pItem = + rSet.GetItem( rSet.GetPool()->GetWhich( SID_CONFIG ) ); + + if ( pItem ) + { + OUString text = static_cast(pItem)->GetValue(); + if (text.startsWith( ITEM_TOOLBAR_URL )) + { + m_aURLToSelect = text.copy( 0 ); + } + } +} + +void SvxToolbarConfigPage::ListModified() +{ + // regenerate with the current ordering within the list + SvxEntries* pEntries = GetTopLevelSelection()->GetEntries(); + pEntries->clear(); + + for (int i = 0; i < m_xContentsListBox->n_children(); ++i) + pEntries->push_back(reinterpret_cast(m_xContentsListBox->get_id(i).toInt64())); + + GetSaveInData()->SetModified(); + GetTopLevelSelection()->SetModified(); + + SvxConfigEntry* pToolbar = GetTopLevelSelection(); + if ( pToolbar ) + static_cast(GetSaveInData())->ApplyToolbar( pToolbar ); +} + +SvxToolbarConfigPage::~SvxToolbarConfigPage() +{ + for (int i = 0, nCount = m_xSaveInListBox->get_count(); i < nCount; ++i) + { + ToolbarSaveInData* pData = + reinterpret_cast(m_xSaveInListBox->get_id(i).toInt64()); + delete pData; + } + m_xSaveInListBox->clear(); +} + +void SvxToolbarConfigPage::DeleteSelectedTopLevel() +{ + const sal_Int32 nSelectionPos = m_xTopLevelListBox->get_active(); + ToolbarSaveInData* pSaveInData = static_cast( GetSaveInData() ); + pSaveInData->RemoveToolbar( GetTopLevelSelection() ); + + int nCount = m_xTopLevelListBox->get_count(); + if (nCount > 1) + { + // select next entry after the one being deleted + // selection position is indexed from 0 so need to + // subtract one from the entry count + if (nSelectionPos != nCount - 1) + { + m_xTopLevelListBox->set_active(nSelectionPos + 1); + } + else + { + m_xTopLevelListBox->set_active(nSelectionPos - 1); + } + SelectElement(); + + // and now remove the entry + m_xTopLevelListBox->remove(nSelectionPos); + } + else + { + ReloadTopLevelListBox(); + } +} + +void SvxToolbarConfigPage::DeleteSelectedContent() +{ + int nActEntry = m_xContentsListBox->get_selected_index(); + + if (nActEntry == -1) + return; + + // get currently selected entry + SvxConfigEntry* pEntry = + reinterpret_cast(m_xContentsListBox->get_id(nActEntry).toInt64()); + + SvxConfigEntry* pToolbar = GetTopLevelSelection(); + + // remove entry from the list for this toolbar + SvxConfigPageHelper::RemoveEntry( pToolbar->GetEntries(), pEntry ); + + // remove toolbar entry from UI + m_xContentsListBox->remove(nActEntry); + + // delete data for toolbar entry + delete pEntry; + + static_cast(GetSaveInData())->ApplyToolbar( pToolbar ); + UpdateButtonStates(); + + // if this is the last entry in the toolbar and it is a user + // defined toolbar pop up a dialog asking the user if they + // want to delete the toolbar + if ( m_xContentsListBox->n_children() == 0 && + GetTopLevelSelection()->IsDeletable() ) + { + std::unique_ptr xQueryBox(Application::CreateMessageDialog(GetFrameWeld(), + VclMessageType::Question, VclButtonsType::YesNo, + CuiResId(RID_SXVSTR_CONFIRM_DELETE_TOOLBAR))); + if (xQueryBox->run() == RET_YES) + { + DeleteSelectedTopLevel(); + } + } +} + +IMPL_LINK( SvxToolbarConfigPage, MoveHdl, weld::Button&, rButton, void ) +{ + MoveEntry(&rButton == m_xMoveUpButton.get()); +} + +void SvxToolbarConfigPage::MoveEntry( bool bMoveUp ) +{ + SvxConfigPage::MoveEntry( bMoveUp ); + + // Apply change to currently selected toolbar + SvxConfigEntry* pToolbar = GetTopLevelSelection(); + if ( pToolbar ) + static_cast(GetSaveInData())->ApplyToolbar( pToolbar ); + else + { + SAL_WARN( "cui.customize", "SvxToolbarConfigPage::MoveEntry(): no entry" ); + UpdateButtonStates(); + } +} + +void SvxToolbarConfigPage::Init() +{ + // ensure that the UI is cleared before populating it + m_xTopLevelListBox->clear(); + m_xContentsListBox->clear(); + + ReloadTopLevelListBox(); + + sal_Int32 nPos = 0; + if ( !m_aURLToSelect.isEmpty() ) + { + for (sal_Int32 i = 0, nCount = m_xTopLevelListBox->get_count(); i < nCount; ++i) + { + SvxConfigEntry* pData = + reinterpret_cast(m_xTopLevelListBox->get_id(i).toInt64()); + + if ( pData->GetCommand().equals( m_aURLToSelect ) ) + { + nPos = i; + break; + } + } + + // in future select the default toolbar: Standard + m_aURLToSelect = ITEM_TOOLBAR_URL; + m_aURLToSelect += "standardbar"; + } + + m_xTopLevelListBox->set_active(nPos); + SelectElement(); + + m_xCommandCategoryListBox->Init( + comphelper::getProcessComponentContext(), + m_xFrame, m_aModuleId); + m_xCommandCategoryListBox->categorySelected(m_xFunctions.get(), OUString(), GetSaveInData()); +} + +SaveInData* SvxToolbarConfigPage::CreateSaveInData( + const css::uno::Reference< css::ui::XUIConfigurationManager >& xCfgMgr, + const css::uno::Reference< css::ui::XUIConfigurationManager >& xParentCfgMgr, + const OUString& aModuleId, + bool bDocConfig ) +{ + return static_cast< SaveInData* >( + new ToolbarSaveInData( xCfgMgr, xParentCfgMgr, aModuleId, bDocConfig )); +} + +IMPL_LINK_NOARG(SvxToolbarConfigPage, SelectToolbarEntry, weld::TreeView&, void) +{ + UpdateButtonStates(); +} + +IMPL_LINK( SvxToolbarConfigPage, GearHdl, const OString&, rIdent, void ) +{ + SvxConfigEntry* pCurrentToolbar = GetTopLevelSelection(); + + if (rIdent == "toolbar_gear_add") + { + OUString prefix = CuiResId( RID_SVXSTR_NEW_TOOLBAR ); + + OUString aNewName = + SvxConfigPageHelper::generateCustomName( prefix, GetSaveInData()->GetEntries() ); + + OUString aNewURL = + SvxConfigPageHelper::generateCustomURL( GetSaveInData()->GetEntries() ); + + SvxNewToolbarDialog aNameDialog(GetFrameWeld(), aNewName); + + // Reflect the actual m_xSaveInListBox into the new toolbar dialog + for (int i = 0, nCount = m_xSaveInListBox->get_count(); i < nCount; ++i) + aNameDialog.m_xSaveInListBox->append_text(m_xSaveInListBox->get_text(i)); + + aNameDialog.m_xSaveInListBox->set_active(m_xSaveInListBox->get_active()); + + if (aNameDialog.run() == RET_OK) + { + aNewName = aNameDialog.GetName(); + + // Where to save the new toolbar? (i.e. Modulewise or documentwise) + int nInsertPos = aNameDialog.m_xSaveInListBox->get_active(); + + ToolbarSaveInData* pData = + reinterpret_cast( + m_xSaveInListBox->get_id(nInsertPos).toInt64() ); + + if ( GetSaveInData() != pData ) + { + m_xSaveInListBox->set_active(nInsertPos); + SelectSaveInLocation(*m_xSaveInListBox); + } + + SvxConfigEntry* pToolbar = + new SvxConfigEntry( aNewName, aNewURL, true, false ); + + pToolbar->SetUserDefined(); + pToolbar->SetMain(); + + pData->CreateToolbar( pToolbar ); + + OUString sId(OUString::number(reinterpret_cast(pToolbar))); + m_xTopLevelListBox->append(sId, pToolbar->GetName()); + m_xTopLevelListBox->set_active_id(sId); + SelectElement(); + + pData->SetModified(); + } + } + else if (rIdent == "toolbar_gear_delete") + { + if ( pCurrentToolbar && pCurrentToolbar->IsDeletable() ) + { + DeleteSelectedTopLevel(); + UpdateButtonStates(); + } + } + else if (rIdent == "toolbar_gear_rename") + { + sal_Int32 nSelectionPos = m_xTopLevelListBox->get_active(); + SvxConfigEntry* pToolbar = + reinterpret_cast(m_xTopLevelListBox->get_id(nSelectionPos).toInt64()); + ToolbarSaveInData* pSaveInData = static_cast( GetSaveInData() ); + + //Rename the toolbar + OUString sCurrentName( SvxConfigPageHelper::stripHotKey( pToolbar->GetName() ) ); + OUString sDesc = CuiResId( RID_SVXSTR_LABEL_NEW_NAME ); + + SvxNameDialog aNameDialog(GetFrameWeld(), sCurrentName, sDesc); + aNameDialog.set_help_id(HID_SVX_CONFIG_RENAME_TOOLBAR); + aNameDialog.set_title(CuiResId(RID_SVXSTR_RENAME_TOOLBAR)); + + if ( aNameDialog.run() == RET_OK ) + { + OUString sNewName = aNameDialog.GetName(); + + if (sCurrentName == sNewName) + return; + + pToolbar->SetName( sNewName ); + pSaveInData->ApplyToolbar( pToolbar ); + + // have to use remove and insert to change the name + m_xTopLevelListBox->remove(nSelectionPos); + OUString sId(OUString::number(reinterpret_cast(pToolbar))); + m_xTopLevelListBox->insert(nSelectionPos, sNewName, &sId, nullptr, nullptr); + m_xTopLevelListBox->set_active_id(sId); + } + } + else if (rIdent == "toolbar_gear_iconOnly" || rIdent == "toolbar_gear_textOnly" || rIdent == "toolbar_gear_iconAndText") + { + ToolbarSaveInData* pSaveInData = static_cast( GetSaveInData() ); + + if (pCurrentToolbar == nullptr || pSaveInData == nullptr) + { + SAL_WARN("cui.customize", "NULL toolbar or savein data"); + return; + } + + sal_Int32 nStyle = 0; + if (rIdent == "toolbar_gear_iconOnly") + nStyle = 0; + else if (rIdent == "toolbar_gear_textOnly") + nStyle = 1; + else if (rIdent == "toolbar_gear_iconAndText") + nStyle = 2; + + pCurrentToolbar->SetStyle( nStyle ); + pSaveInData->SetSystemStyle( m_xFrame, pCurrentToolbar->GetCommand(), nStyle ); + + SelectElement(); + } + else + { + //This block should never be reached + SAL_WARN("cui.customize", "Unknown gear menu option: " << rIdent); + return; + } +} + +IMPL_LINK_NOARG( SvxToolbarConfigPage, SelectCategory, weld::ComboBox&, void ) +{ + OUString aSearchTerm(m_xSearchEdit->get_text()); + + m_xCommandCategoryListBox->categorySelected(m_xFunctions.get(), aSearchTerm, GetSaveInData()); +} + +IMPL_LINK_NOARG( SvxToolbarConfigPage, AddCommandHdl, weld::Button&, void ) +{ + AddFunction(); +} + +IMPL_LINK_NOARG( SvxToolbarConfigPage, RemoveCommandHdl, weld::Button&, void ) +{ + DeleteSelectedContent(); +} + +IMPL_LINK(SvxToolbarConfigPage, InsertHdl, const OString&, rIdent, void) +{ + if (rIdent == "insertseparator") + { + // Get the currently selected toolbar + SvxConfigEntry* pToolbar = GetTopLevelSelection(); + + SvxConfigEntry* pNewEntryData = new SvxConfigEntry; + pNewEntryData->SetUserDefined(); + + int nPos = AppendEntry(pNewEntryData, -1); + InsertEntryIntoUI(pNewEntryData, m_xContentsListBox->get_widget(), nPos, 1); + + static_cast( GetSaveInData())->ApplyToolbar( pToolbar ); + + UpdateButtonStates(); + } + else + { + //This block should never be reached + SAL_WARN("cui.customize", "Unknown insert option: " << rIdent); + return; + } +} + +IMPL_LINK(SvxToolbarConfigPage, ModifyItemHdl, const OString&, rIdent, void) +{ + bool bNeedsApply = false; + + // get currently selected toolbar + SvxConfigEntry* pToolbar = GetTopLevelSelection(); + + if (rIdent.isEmpty() || pToolbar == nullptr) + { + SAL_WARN("cui.customize", "No toolbar selected, or empty rIdent!"); + return; + } + + if (rIdent == "renameItem") + { + int nActEntry = m_xContentsListBox->get_selected_index(); + SvxConfigEntry* pEntry = + reinterpret_cast(m_xContentsListBox->get_id(nActEntry).toInt64()); + + OUString aNewName( SvxConfigPageHelper::stripHotKey( pEntry->GetName() ) ); + OUString aDesc = CuiResId( RID_SVXSTR_LABEL_NEW_NAME ); + + SvxNameDialog aNameDialog(GetFrameWeld(), aNewName, aDesc); + aNameDialog.set_help_id(HID_SVX_CONFIG_RENAME_TOOLBAR_ITEM); + aNameDialog.set_title(CuiResId(RID_SVXSTR_RENAME_TOOLBAR)); + + if (aNameDialog.run() == RET_OK) + { + aNewName = aNameDialog.GetName(); + + if( aNewName.isEmpty() ) // tdf#80758 - Accelerator character ("~") is passed as + pEntry->SetName( "~" ); // the button name in case of empty values. + else + pEntry->SetName( aNewName ); + + m_xContentsListBox->set_text(nActEntry, aNewName, 2); + bNeedsApply = true; + } + } + else if (rIdent == "changeIcon") + { + int nActEntry = m_xContentsListBox->get_selected_index(); + SvxConfigEntry* pEntry = + reinterpret_cast(m_xContentsListBox->get_id(nActEntry).toInt64()); + + SvxIconSelectorDialog aIconDialog(GetFrameWeld(), + GetSaveInData()->GetImageManager(), + GetSaveInData()->GetParentImageManager()); + + if (aIconDialog.run() == RET_OK) + { + css::uno::Reference< css::graphic::XGraphic > newgraphic = + aIconDialog.GetSelectedIcon(); + + if ( newgraphic.is() ) + { + css::uno::Sequence< css::uno::Reference< css::graphic::XGraphic > > + aGraphicSeq( 1 ); + + css::uno::Sequence aURLSeq { pEntry->GetCommand() }; + + if ( !pEntry->GetBackupGraphic().is() ) + { + css::uno::Reference< css::graphic::XGraphic > backup = + SvxConfigPageHelper::GetGraphic(GetSaveInData()->GetImageManager(), + aURLSeq[0]); + + if ( backup.is() ) + { + pEntry->SetBackupGraphic(backup); + } + } + + aGraphicSeq[ 0 ] = newgraphic; + try + { + GetSaveInData()->GetImageManager()->replaceImages( + SvxConfigPageHelper::GetImageType(), aURLSeq, aGraphicSeq ); + + m_xContentsListBox->remove(nActEntry); + + OUString sId(OUString::number(reinterpret_cast(pEntry))); + m_xContentsListBox->insert(nActEntry, sId); + m_xContentsListBox->set_toggle(nActEntry, pEntry->IsVisible() ? TRISTATE_TRUE : TRISTATE_FALSE, 0); + InsertEntryIntoUI(pEntry, m_xContentsListBox->get_widget(), nActEntry, 1); + + m_xContentsListBox->select(nActEntry); + m_xContentsListBox->scroll_to_row(nActEntry); + + GetSaveInData()->PersistChanges( + GetSaveInData()->GetImageManager() ); + } + catch ( const css::uno::Exception&) + { + TOOLS_WARN_EXCEPTION("cui.customize", "Error replacing image"); + } + } + } + } + else if (rIdent == "resetIcon") + { + int nActEntry = m_xContentsListBox->get_selected_index(); + SvxConfigEntry* pEntry = + reinterpret_cast(m_xContentsListBox->get_id(nActEntry).toInt64()); + + css::uno::Reference< css::graphic::XGraphic > backup = + pEntry->GetBackupGraphic(); + + css::uno::Sequence< css::uno::Reference< css::graphic::XGraphic > > + aGraphicSeq( 1 ); + aGraphicSeq[ 0 ] = backup; + + css::uno::Sequence aURLSeq { pEntry->GetCommand() }; + + try + { + GetSaveInData()->GetImageManager()->replaceImages( + SvxConfigPageHelper::GetImageType(), aURLSeq, aGraphicSeq ); + + m_xContentsListBox->remove(nActEntry); + + OUString sId(OUString::number(reinterpret_cast(pEntry))); + m_xContentsListBox->insert(nActEntry, sId); + m_xContentsListBox->set_toggle(nActEntry, pEntry->IsVisible() ? TRISTATE_TRUE : TRISTATE_FALSE, 0); + InsertEntryIntoUI(pEntry, m_xContentsListBox->get_widget(), nActEntry, 1); + + m_xContentsListBox->select(nActEntry); + m_xContentsListBox->scroll_to_row(nActEntry); + + // reset backup in entry + pEntry->SetBackupGraphic( + css::uno::Reference< css::graphic::XGraphic >() ); + + GetSaveInData()->PersistChanges( + GetSaveInData()->GetImageManager() ); + } + catch ( const css::uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("cui.customize", "Error resetting image"); + } + } + else if (rIdent == "restoreItem") + { + int nActEntry = m_xContentsListBox->get_selected_index(); + SvxConfigEntry* pEntry = + reinterpret_cast(m_xContentsListBox->get_id(nActEntry).toInt64()); + + ToolbarSaveInData* pSaveInData = + static_cast( GetSaveInData() ); + + OUString aSystemName = + pSaveInData->GetSystemUIName( pEntry->GetCommand() ); + + if ( !pEntry->GetName().equals( aSystemName ) ) + { + pEntry->SetName( aSystemName ); + m_xContentsListBox->set_text( + nActEntry, SvxConfigPageHelper::stripHotKey(aSystemName), 2); + bNeedsApply = true; + } + + css::uno::Sequence aURLSeq { pEntry->GetCommand() }; + + try + { + GetSaveInData()->GetImageManager()->removeImages( + SvxConfigPageHelper::GetImageType(), aURLSeq ); + + // reset backup in entry + pEntry->SetBackupGraphic( + css::uno::Reference< css::graphic::XGraphic >() ); + + GetSaveInData()->PersistChanges( + GetSaveInData()->GetImageManager() ); + + m_xContentsListBox->remove(nActEntry); + + OUString sId(OUString::number(reinterpret_cast(pEntry))); + m_xContentsListBox->insert(nActEntry, sId); + m_xContentsListBox->set_toggle(nActEntry, + pEntry->IsVisible() ? TRISTATE_TRUE : TRISTATE_FALSE, 0); + InsertEntryIntoUI(pEntry, m_xContentsListBox->get_widget(), nActEntry, 1); + + m_xContentsListBox->select(nActEntry); + m_xContentsListBox->scroll_to_row(nActEntry); + + bNeedsApply = true; + } + catch ( const css::uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("cui.customize", "Error restoring image"); + } + } + else + { + //This block should never be reached + SAL_WARN("cui.customize", "Unknown insert option: " << rIdent); + return; + } + + if ( bNeedsApply ) + { + static_cast( GetSaveInData())->ApplyToolbar( pToolbar ); + UpdateButtonStates(); + } +} + +IMPL_LINK_NOARG(SvxToolbarConfigPage, ResetToolbarHdl, weld::Button&, void) +{ + sal_Int32 nSelectionPos = m_xTopLevelListBox->get_active(); + + SvxConfigEntry* pToolbar = + reinterpret_cast(m_xTopLevelListBox->get_id(nSelectionPos).toInt64()); + + std::unique_ptr xQueryBox(Application::CreateMessageDialog(GetFrameWeld(), + VclMessageType::Question, VclButtonsType::YesNo, + CuiResId(RID_SVXSTR_CONFIRM_RESTORE_DEFAULT))); + if (xQueryBox->run() == RET_YES) + { + ToolbarSaveInData* pSaveInData = + static_cast(GetSaveInData()); + + pSaveInData->RestoreToolbar( pToolbar ); + + SelectElement(); + } +} + +void SvxToolbarConfigPage::UpdateButtonStates() +{ + SvxConfigEntry* pToolbar = GetTopLevelSelection(); + int selection = m_xContentsListBox->get_selected_index(); + + bool bIsSeparator = + selection != -1 && reinterpret_cast(m_xContentsListBox->get_id(selection).toInt64())->IsSeparator(); + bool bIsValidSelection = + !(m_xContentsListBox->n_children() == 0 || selection == -1); + + m_xMoveUpButton->set_sensitive( bIsValidSelection ); + m_xMoveDownButton->set_sensitive( bIsValidSelection ); + + m_xRemoveCommandButton->set_sensitive( bIsValidSelection ); + + m_xModifyBtn->set_sensitive( bIsValidSelection && !bIsSeparator ); + + // Handle the gear button + // "toolbar_gear_add" option is always enabled + m_xGearBtn->set_item_sensitive("toolbar_gear_delete", pToolbar && pToolbar->IsDeletable()); + m_xGearBtn->set_item_sensitive("toolbar_gear_rename", pToolbar && pToolbar->IsRenamable()); +} + +short SvxToolbarConfigPage::QueryReset() +{ + OUString msg = CuiResId( RID_SVXSTR_CONFIRM_TOOLBAR_RESET ); + + OUString saveInName = m_xSaveInListBox->get_active_text(); + + OUString label = SvxConfigPageHelper::replaceSaveInName( msg, saveInName ); + + std::unique_ptr xQueryBox(Application::CreateMessageDialog(GetFrameWeld(), + VclMessageType::Question, VclButtonsType::YesNo, + label)); + return xQueryBox->run(); +} + +void SvxToolbarConfigPage::SelectElement() +{ + m_xContentsListBox->clear(); + + SvxConfigEntry* pToolbar = GetTopLevelSelection(); + if ( pToolbar == nullptr ) + { + //TODO: Disable related buttons + m_xInsertBtn->set_sensitive( false ); + m_xResetBtn->set_sensitive( false ); + m_xGearBtn->set_sensitive( false ); + + return; + } + else + { + m_xInsertBtn->set_sensitive(true); + m_xResetBtn->set_sensitive(true); + m_xGearBtn->set_sensitive(true); + } + + switch (pToolbar->GetStyle()) + { + case 0: + { + m_xGearBtn->set_item_active("toolbar_gear_iconOnly", true); + break; + } + case 1: + { + m_xGearBtn->set_item_active("toolbar_gear_textOnly", true); + break; + } + case 2: + { + m_xGearBtn->set_item_active("toolbar_gear_iconAndText", true); + break; + } + } + + int i = 0; + SvxEntries* pEntries = pToolbar->GetEntries(); + for (auto const& entry : *pEntries) + { + OUString sId(OUString::number(reinterpret_cast(entry))); + m_xContentsListBox->insert(i, sId); + if (entry->IsBinding() && !entry->IsSeparator()) + m_xContentsListBox->set_toggle(i, entry->IsVisible() ? TRISTATE_TRUE : TRISTATE_FALSE, 0); + InsertEntryIntoUI(entry, m_xContentsListBox->get_widget(), i, 1); + ++i; + } + + UpdateButtonStates(); +} + +void SvxToolbarConfigPage::AddFunction(int nTarget) +{ + SvxConfigEntry* pToolbar = GetTopLevelSelection(); + + if (pToolbar == nullptr) + return; + + // Add the command to the contents listbox of the selected toolbar + int nNewLBEntry = + SvxConfigPage::AddFunction(nTarget, true/*bAllowDuplicates*/); + + if (nNewLBEntry == -1) + return; + + SvxConfigEntry* pEntry = reinterpret_cast(m_xContentsListBox->get_id(nNewLBEntry).toInt64()); + + if ( pEntry->IsBinding() ) //TODO sep ? + { + pEntry->SetVisible(true); + m_xContentsListBox->set_toggle(nNewLBEntry, TRISTATE_TRUE, 0); + } + + InsertEntryIntoUI(pEntry, m_xContentsListBox->get_widget(), nNewLBEntry, 1); + + // Changes are not visible on the toolbar until this point + // TODO: Figure out a way to show the changes on the toolbar, but revert if + // the dialog is closed by pressing "Cancel" + // get currently selected toolbar and apply change + if ( pToolbar != nullptr ) + { + static_cast( GetSaveInData() )->ApplyToolbar( pToolbar ); + } +} + +SvxToolbarEntriesListBox::SvxToolbarEntriesListBox(std::unique_ptr xParent, SvxToolbarConfigPage* pPg) + : SvxMenuEntriesListBox(std::move(xParent), pPg) +{ + m_xControl->connect_toggled(LINK(this, SvxToolbarEntriesListBox, CheckButtonHdl)); + m_xControl->connect_key_press(Link()); //acknowledge we first remove the old one + m_xControl->connect_key_press(LINK(this, SvxToolbarEntriesListBox, KeyInputHdl)); // then add the new one +} + +SvxToolbarEntriesListBox::~SvxToolbarEntriesListBox() +{ +} + +void SvxToolbarEntriesListBox::ChangedVisibility(int nRow) +{ + SvxConfigEntry* pEntryData = + reinterpret_cast(m_xControl->get_id(nRow).toInt64()); + + if (pEntryData->IsBinding()) + { + pEntryData->SetVisible(m_xControl->get_toggle(nRow, 0) == TRISTATE_TRUE); + + SvxConfigEntry* pToolbar = m_pPage->GetTopLevelSelection(); + + ToolbarSaveInData* pToolbarSaveInData = static_cast( + m_pPage->GetSaveInData() ); + + pToolbarSaveInData->ApplyToolbar( pToolbar ); + } +} + +IMPL_LINK(SvxToolbarEntriesListBox, CheckButtonHdl, const row_col&, rRowCol, void) +{ + ChangedVisibility(rRowCol.first); +} + +IMPL_LINK(SvxToolbarEntriesListBox, KeyInputHdl, const KeyEvent&, rKeyEvent, bool) +{ + // space key will change visibility of toolbar items + if ( rKeyEvent.GetKeyCode() == KEY_SPACE ) + { + int nRow = m_xControl->get_selected_index(); + SvxConfigEntry* pEntryData = reinterpret_cast(m_xControl->get_id(nRow).toInt64()); + if (pEntryData->IsBinding() && !pEntryData->IsSeparator()) + { + m_xControl->set_toggle(nRow, m_xControl->get_toggle(nRow, 0) == TRISTATE_TRUE ? TRISTATE_FALSE : TRISTATE_TRUE, 0); + ChangedVisibility(nRow); + } + return true; + } + return SvxMenuEntriesListBox::KeyInputHdl(rKeyEvent); +} + +IMPL_LINK( SvxToolbarConfigPage, ContentContextMenuHdl, const CommandEvent&, rCEvt, bool ) +{ + if (rCEvt.GetCommand() != CommandEventId::ContextMenu) + return false; + + weld::TreeView& rTreeView = m_xContentsListBox->get_widget(); + + // Select clicked entry + std::unique_ptr rIter(rTreeView.make_iterator()); + if (! rTreeView.get_dest_row_at_pos( rCEvt.GetMousePosPixel(), &*rIter )) + return false; + rTreeView.select(*rIter); + SelectToolbarEntry( rTreeView ); + + int nSelectIndex = m_xContentsListBox->get_selected_index(); + + bool bIsSeparator = + nSelectIndex != -1 && reinterpret_cast(m_xContentsListBox->get_id(nSelectIndex).toInt64())->IsSeparator(); + bool bIsValidSelection = + !( m_xContentsListBox->n_children() == 0 || nSelectIndex == -1 ); + + std::unique_ptr xBuilder(Application::CreateBuilder( &rTreeView, "cui/ui/entrycontextmenu.ui" ) ); + auto xContextMenu = xBuilder->weld_menu("menu"); + xContextMenu->set_visible("add", false); + xContextMenu->set_visible("remove", bIsValidSelection); + xContextMenu->set_visible("rename", bIsValidSelection && !bIsSeparator); + xContextMenu->set_visible("changeIcon", bIsValidSelection && !bIsSeparator); + xContextMenu->set_visible("resetIcon", bIsValidSelection && !bIsSeparator); + xContextMenu->set_visible("restoreDefault", bIsValidSelection && !bIsSeparator); + OString sCommand(xContextMenu->popup_at_rect( &rTreeView, tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1,1) ) ) ); + + if ( sCommand == "remove") + RemoveCommandHdl( *m_xRemoveCommandButton ); + else if ( sCommand == "rename" ) + ModifyItemHdl( "renameItem" ); + else if ( sCommand == "changeIcon" ) + ModifyItemHdl( "changeIcon" ); + else if ( sCommand == "resetIcon" ) + ModifyItemHdl( "resetIcon" ); + else if ( sCommand == "restoreDefault" ) + ModifyItemHdl( "restoreItem" ); + else if ( !sCommand.isEmpty() ) + SAL_WARN("cui.customize", "Unknown context menu action: " << sCommand ); + return true; +} + +IMPL_LINK( SvxToolbarConfigPage, FunctionContextMenuHdl, const CommandEvent&, rCEvt, bool ) +{ + if (rCEvt.GetCommand() != CommandEventId::ContextMenu) + return false; + + weld::TreeView& rTreeView = m_xFunctions->get_widget(); + + // Select clicked entry + std::unique_ptr rIter(rTreeView.make_iterator()); + if (! rTreeView.get_dest_row_at_pos( rCEvt.GetMousePosPixel(), &*rIter )) + return false; + rTreeView.select(*rIter); + SelectFunctionHdl( rTreeView ); + std::unique_ptr xBuilder(Application::CreateBuilder( &rTreeView, "cui/ui/entrycontextmenu.ui" ) ); + auto xContextMenu = xBuilder->weld_menu("menu"); + xContextMenu->set_visible("add", true); + xContextMenu->set_visible("remove", false); + xContextMenu->set_visible("rename", false); + xContextMenu->set_visible("changeIcon", false); + xContextMenu->set_visible("resetIcon", false); + xContextMenu->set_visible("restoreDefault", false); + OString sCommand(xContextMenu->popup_at_rect( &rTreeView, tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1,1) ) ) ); + + if ( sCommand == "add") + AddCommandHdl( *m_xAddCommandButton ); + else if ( !sCommand.isEmpty() ) + SAL_WARN("cui.customize", "Unknown context menu action: " << sCommand ); + return true; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/customize/acccfg.cxx b/cui/source/customize/acccfg.cxx new file mode 100644 index 000000000..2ae4f9501 --- /dev/null +++ b/cui/source/customize/acccfg.cxx @@ -0,0 +1,1593 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +// include own files + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include + +// include interface declarations +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// include search util +#include +#include +#include + +// include other projects +#include +#include +#include +#include +// namespaces + +using namespace css; + +static const char FOLDERNAME_UICONFIG[] = "Configurations2"; + +static const char MEDIATYPE_PROPNAME[] = "MediaType"; + +static const sal_uInt16 KEYCODE_ARRAY[] = { KEY_F1, + KEY_F2, + KEY_F3, + KEY_F4, + KEY_F5, + KEY_F6, + KEY_F7, + KEY_F8, + KEY_F9, + KEY_F10, + KEY_F11, + KEY_F12, + KEY_F13, + KEY_F14, + KEY_F15, + KEY_F16, + + KEY_DOWN, + KEY_UP, + KEY_LEFT, + KEY_RIGHT, + KEY_HOME, + KEY_END, + KEY_PAGEUP, + KEY_PAGEDOWN, + KEY_RETURN, + KEY_ESCAPE, + KEY_BACKSPACE, + KEY_INSERT, + KEY_DELETE, + + KEY_OPEN, + KEY_CUT, + KEY_COPY, + KEY_PASTE, + KEY_UNDO, + KEY_REPEAT, + KEY_FIND, + KEY_PROPERTIES, + KEY_FRONT, + KEY_CONTEXTMENU, + KEY_MENU, + KEY_HELP, + + KEY_SHIFT | KEY_F1, + KEY_SHIFT | KEY_F2, + KEY_SHIFT | KEY_F3, + KEY_SHIFT | KEY_F4, + KEY_SHIFT | KEY_F5, + KEY_SHIFT | KEY_F6, + KEY_SHIFT | KEY_F7, + KEY_SHIFT | KEY_F8, + KEY_SHIFT | KEY_F9, + KEY_SHIFT | KEY_F10, + KEY_SHIFT | KEY_F11, + KEY_SHIFT | KEY_F12, + KEY_SHIFT | KEY_F13, + KEY_SHIFT | KEY_F14, + KEY_SHIFT | KEY_F15, + KEY_SHIFT | KEY_F16, + + KEY_SHIFT | KEY_DOWN, + KEY_SHIFT | KEY_UP, + KEY_SHIFT | KEY_LEFT, + KEY_SHIFT | KEY_RIGHT, + KEY_SHIFT | KEY_HOME, + KEY_SHIFT | KEY_END, + KEY_SHIFT | KEY_PAGEUP, + KEY_SHIFT | KEY_PAGEDOWN, + KEY_SHIFT | KEY_RETURN, + KEY_SHIFT | KEY_SPACE, + KEY_SHIFT | KEY_ESCAPE, + KEY_SHIFT | KEY_BACKSPACE, + KEY_SHIFT | KEY_INSERT, + KEY_SHIFT | KEY_DELETE, + KEY_SHIFT | KEY_EQUAL, + + KEY_MOD1 | KEY_0, + KEY_MOD1 | KEY_1, + KEY_MOD1 | KEY_2, + KEY_MOD1 | KEY_3, + KEY_MOD1 | KEY_4, + KEY_MOD1 | KEY_5, + KEY_MOD1 | KEY_6, + KEY_MOD1 | KEY_7, + KEY_MOD1 | KEY_8, + KEY_MOD1 | KEY_9, + KEY_MOD1 | KEY_A, + KEY_MOD1 | KEY_B, + KEY_MOD1 | KEY_C, + KEY_MOD1 | KEY_D, + KEY_MOD1 | KEY_E, + KEY_MOD1 | KEY_F, + KEY_MOD1 | KEY_G, + KEY_MOD1 | KEY_H, + KEY_MOD1 | KEY_I, + KEY_MOD1 | KEY_J, + KEY_MOD1 | KEY_K, + KEY_MOD1 | KEY_L, + KEY_MOD1 | KEY_M, + KEY_MOD1 | KEY_N, + KEY_MOD1 | KEY_O, + KEY_MOD1 | KEY_P, + KEY_MOD1 | KEY_Q, + KEY_MOD1 | KEY_R, + KEY_MOD1 | KEY_S, + KEY_MOD1 | KEY_T, + KEY_MOD1 | KEY_U, + KEY_MOD1 | KEY_V, + KEY_MOD1 | KEY_W, + KEY_MOD1 | KEY_X, + KEY_MOD1 | KEY_Y, + KEY_MOD1 | KEY_Z, + KEY_MOD1 | KEY_SEMICOLON, + KEY_MOD1 | KEY_QUOTERIGHT, + KEY_MOD1 | KEY_BRACKETLEFT, + KEY_MOD1 | KEY_BRACKETRIGHT, + KEY_MOD1 | KEY_POINT, + KEY_MOD1 | KEY_COMMA, + KEY_MOD1 | KEY_TILDE, + KEY_MOD1 | KEY_TAB, + + KEY_MOD1 | KEY_F1, + KEY_MOD1 | KEY_F2, + KEY_MOD1 | KEY_F3, + KEY_MOD1 | KEY_F4, + KEY_MOD1 | KEY_F5, + KEY_MOD1 | KEY_F6, + KEY_MOD1 | KEY_F7, + KEY_MOD1 | KEY_F8, + KEY_MOD1 | KEY_F9, + KEY_MOD1 | KEY_F10, + KEY_MOD1 | KEY_F11, + KEY_MOD1 | KEY_F12, + KEY_MOD1 | KEY_F13, + KEY_MOD1 | KEY_F14, + KEY_MOD1 | KEY_F15, + KEY_MOD1 | KEY_F16, + + KEY_MOD1 | KEY_DOWN, + KEY_MOD1 | KEY_UP, + KEY_MOD1 | KEY_LEFT, + KEY_MOD1 | KEY_RIGHT, + KEY_MOD1 | KEY_HOME, + KEY_MOD1 | KEY_END, + KEY_MOD1 | KEY_PAGEUP, + KEY_MOD1 | KEY_PAGEDOWN, + KEY_MOD1 | KEY_RETURN, + KEY_MOD1 | KEY_SPACE, + KEY_MOD1 | KEY_BACKSPACE, + KEY_MOD1 | KEY_INSERT, + KEY_MOD1 | KEY_DELETE, + + KEY_MOD1 | KEY_ADD, + KEY_MOD1 | KEY_SUBTRACT, + KEY_MOD1 | KEY_MULTIPLY, + KEY_MOD1 | KEY_DIVIDE, + KEY_MOD1 | KEY_EQUAL, + + KEY_SHIFT | KEY_MOD1 | KEY_0, + KEY_SHIFT | KEY_MOD1 | KEY_1, + KEY_SHIFT | KEY_MOD1 | KEY_2, + KEY_SHIFT | KEY_MOD1 | KEY_3, + KEY_SHIFT | KEY_MOD1 | KEY_4, + KEY_SHIFT | KEY_MOD1 | KEY_5, + KEY_SHIFT | KEY_MOD1 | KEY_6, + KEY_SHIFT | KEY_MOD1 | KEY_7, + KEY_SHIFT | KEY_MOD1 | KEY_8, + KEY_SHIFT | KEY_MOD1 | KEY_9, + KEY_SHIFT | KEY_MOD1 | KEY_A, + KEY_SHIFT | KEY_MOD1 | KEY_B, + KEY_SHIFT | KEY_MOD1 | KEY_C, + KEY_SHIFT | KEY_MOD1 | KEY_D, + KEY_SHIFT | KEY_MOD1 | KEY_E, + KEY_SHIFT | KEY_MOD1 | KEY_F, + KEY_SHIFT | KEY_MOD1 | KEY_G, + KEY_SHIFT | KEY_MOD1 | KEY_H, + KEY_SHIFT | KEY_MOD1 | KEY_I, + KEY_SHIFT | KEY_MOD1 | KEY_J, + KEY_SHIFT | KEY_MOD1 | KEY_K, + KEY_SHIFT | KEY_MOD1 | KEY_L, + KEY_SHIFT | KEY_MOD1 | KEY_M, + KEY_SHIFT | KEY_MOD1 | KEY_N, + KEY_SHIFT | KEY_MOD1 | KEY_O, + KEY_SHIFT | KEY_MOD1 | KEY_P, + KEY_SHIFT | KEY_MOD1 | KEY_Q, + KEY_SHIFT | KEY_MOD1 | KEY_R, + KEY_SHIFT | KEY_MOD1 | KEY_S, + KEY_SHIFT | KEY_MOD1 | KEY_T, + KEY_SHIFT | KEY_MOD1 | KEY_U, + KEY_SHIFT | KEY_MOD1 | KEY_V, + KEY_SHIFT | KEY_MOD1 | KEY_W, + KEY_SHIFT | KEY_MOD1 | KEY_X, + KEY_SHIFT | KEY_MOD1 | KEY_Y, + KEY_SHIFT | KEY_MOD1 | KEY_Z, + KEY_SHIFT | KEY_MOD1 | KEY_SEMICOLON, + KEY_SHIFT | KEY_MOD1 | KEY_QUOTERIGHT, + KEY_SHIFT | KEY_MOD1 | KEY_BRACKETLEFT, + KEY_SHIFT | KEY_MOD1 | KEY_BRACKETRIGHT, + KEY_SHIFT | KEY_MOD1 | KEY_POINT, + KEY_SHIFT | KEY_MOD1 | KEY_COMMA, + KEY_SHIFT | KEY_MOD1 | KEY_TILDE, + KEY_SHIFT | KEY_MOD1 | KEY_TAB, + + KEY_SHIFT | KEY_MOD1 | KEY_F1, + KEY_SHIFT | KEY_MOD1 | KEY_F2, + KEY_SHIFT | KEY_MOD1 | KEY_F3, + KEY_SHIFT | KEY_MOD1 | KEY_F4, + KEY_SHIFT | KEY_MOD1 | KEY_F5, + KEY_SHIFT | KEY_MOD1 | KEY_F6, + KEY_SHIFT | KEY_MOD1 | KEY_F7, + KEY_SHIFT | KEY_MOD1 | KEY_F8, + KEY_SHIFT | KEY_MOD1 | KEY_F9, + KEY_SHIFT | KEY_MOD1 | KEY_F10, + KEY_SHIFT | KEY_MOD1 | KEY_F11, + KEY_SHIFT | KEY_MOD1 | KEY_F12, + KEY_SHIFT | KEY_MOD1 | KEY_F13, + KEY_SHIFT | KEY_MOD1 | KEY_F14, + KEY_SHIFT | KEY_MOD1 | KEY_F15, + KEY_SHIFT | KEY_MOD1 | KEY_F16, + + KEY_SHIFT | KEY_MOD1 | KEY_DOWN, + KEY_SHIFT | KEY_MOD1 | KEY_UP, + KEY_SHIFT | KEY_MOD1 | KEY_LEFT, + KEY_SHIFT | KEY_MOD1 | KEY_RIGHT, + KEY_SHIFT | KEY_MOD1 | KEY_HOME, + KEY_SHIFT | KEY_MOD1 | KEY_END, + KEY_SHIFT | KEY_MOD1 | KEY_PAGEUP, + KEY_SHIFT | KEY_MOD1 | KEY_PAGEDOWN, + KEY_SHIFT | KEY_MOD1 | KEY_RETURN, + KEY_SHIFT | KEY_MOD1 | KEY_ESCAPE, + KEY_SHIFT | KEY_MOD1 | KEY_SPACE, + KEY_SHIFT | KEY_MOD1 | KEY_BACKSPACE, + KEY_SHIFT | KEY_MOD1 | KEY_INSERT, + KEY_SHIFT | KEY_MOD1 | KEY_DELETE, + KEY_SHIFT | KEY_MOD1 | KEY_EQUAL, + + KEY_MOD2 | KEY_0, + KEY_MOD2 | KEY_1, + KEY_MOD2 | KEY_2, + KEY_MOD2 | KEY_3, + KEY_MOD2 | KEY_4, + KEY_MOD2 | KEY_5, + KEY_MOD2 | KEY_6, + KEY_MOD2 | KEY_7, + KEY_MOD2 | KEY_8, + KEY_MOD2 | KEY_9, + KEY_MOD2 | KEY_A, + KEY_MOD2 | KEY_B, + KEY_MOD2 | KEY_C, + KEY_MOD2 | KEY_D, + KEY_MOD2 | KEY_E, + KEY_MOD2 | KEY_F, + KEY_MOD2 | KEY_G, + KEY_MOD2 | KEY_H, + KEY_MOD2 | KEY_I, + KEY_MOD2 | KEY_J, + KEY_MOD2 | KEY_K, + KEY_MOD2 | KEY_L, + KEY_MOD2 | KEY_M, + KEY_MOD2 | KEY_N, + KEY_MOD2 | KEY_O, + KEY_MOD2 | KEY_P, + KEY_MOD2 | KEY_Q, + KEY_MOD2 | KEY_R, + KEY_MOD2 | KEY_S, + KEY_MOD2 | KEY_T, + KEY_MOD2 | KEY_U, + KEY_MOD2 | KEY_V, + KEY_MOD2 | KEY_W, + KEY_MOD2 | KEY_X, + KEY_MOD2 | KEY_Y, + KEY_MOD2 | KEY_Z, + KEY_MOD2 | KEY_SEMICOLON, + KEY_MOD2 | KEY_QUOTERIGHT, + KEY_MOD2 | KEY_BRACKETLEFT, + KEY_MOD2 | KEY_BRACKETRIGHT, + KEY_MOD2 | KEY_POINT, + KEY_MOD2 | KEY_COMMA, + KEY_MOD2 | KEY_TILDE, + + KEY_MOD2 | KEY_F1, + KEY_MOD2 | KEY_F2, + KEY_MOD2 | KEY_F3, + KEY_MOD2 | KEY_F4, + KEY_MOD2 | KEY_F5, + KEY_MOD2 | KEY_F6, + KEY_MOD2 | KEY_F7, + KEY_MOD2 | KEY_F8, + KEY_MOD2 | KEY_F9, + KEY_MOD2 | KEY_F10, + KEY_MOD2 | KEY_F11, + KEY_MOD2 | KEY_F12, + KEY_MOD2 | KEY_F13, + KEY_MOD2 | KEY_F14, + KEY_MOD2 | KEY_F15, + KEY_MOD2 | KEY_F16, + + KEY_MOD2 | KEY_DOWN, + KEY_MOD2 | KEY_UP, + KEY_MOD2 | KEY_LEFT, + KEY_MOD2 | KEY_RIGHT, + KEY_MOD2 | KEY_HOME, + KEY_MOD2 | KEY_END, + KEY_MOD2 | KEY_PAGEUP, + KEY_MOD2 | KEY_PAGEDOWN, + KEY_MOD2 | KEY_RETURN, + KEY_MOD2 | KEY_SPACE, + KEY_MOD2 | KEY_BACKSPACE, + KEY_MOD2 | KEY_INSERT, + KEY_MOD2 | KEY_DELETE, + KEY_MOD2 | KEY_EQUAL, + + KEY_SHIFT | KEY_MOD2 | KEY_0, + KEY_SHIFT | KEY_MOD2 | KEY_1, + KEY_SHIFT | KEY_MOD2 | KEY_2, + KEY_SHIFT | KEY_MOD2 | KEY_3, + KEY_SHIFT | KEY_MOD2 | KEY_4, + KEY_SHIFT | KEY_MOD2 | KEY_5, + KEY_SHIFT | KEY_MOD2 | KEY_6, + KEY_SHIFT | KEY_MOD2 | KEY_7, + KEY_SHIFT | KEY_MOD2 | KEY_8, + KEY_SHIFT | KEY_MOD2 | KEY_9, + KEY_SHIFT | KEY_MOD2 | KEY_A, + KEY_SHIFT | KEY_MOD2 | KEY_B, + KEY_SHIFT | KEY_MOD2 | KEY_C, + KEY_SHIFT | KEY_MOD2 | KEY_D, + KEY_SHIFT | KEY_MOD2 | KEY_E, + KEY_SHIFT | KEY_MOD2 | KEY_F, + KEY_SHIFT | KEY_MOD2 | KEY_G, + KEY_SHIFT | KEY_MOD2 | KEY_H, + KEY_SHIFT | KEY_MOD2 | KEY_I, + KEY_SHIFT | KEY_MOD2 | KEY_J, + KEY_SHIFT | KEY_MOD2 | KEY_K, + KEY_SHIFT | KEY_MOD2 | KEY_L, + KEY_SHIFT | KEY_MOD2 | KEY_M, + KEY_SHIFT | KEY_MOD2 | KEY_N, + KEY_SHIFT | KEY_MOD2 | KEY_O, + KEY_SHIFT | KEY_MOD2 | KEY_P, + KEY_SHIFT | KEY_MOD2 | KEY_Q, + KEY_SHIFT | KEY_MOD2 | KEY_R, + KEY_SHIFT | KEY_MOD2 | KEY_S, + KEY_SHIFT | KEY_MOD2 | KEY_T, + KEY_SHIFT | KEY_MOD2 | KEY_U, + KEY_SHIFT | KEY_MOD2 | KEY_V, + KEY_SHIFT | KEY_MOD2 | KEY_W, + KEY_SHIFT | KEY_MOD2 | KEY_X, + KEY_SHIFT | KEY_MOD2 | KEY_Y, + KEY_SHIFT | KEY_MOD2 | KEY_Z, + KEY_SHIFT | KEY_MOD2 | KEY_SEMICOLON, + KEY_SHIFT | KEY_MOD2 | KEY_QUOTERIGHT, + KEY_SHIFT | KEY_MOD2 | KEY_BRACKETLEFT, + KEY_SHIFT | KEY_MOD2 | KEY_BRACKETRIGHT, + KEY_SHIFT | KEY_MOD2 | KEY_POINT, + KEY_SHIFT | KEY_MOD2 | KEY_COMMA, + KEY_SHIFT | KEY_MOD2 | KEY_TILDE, + + KEY_SHIFT | KEY_MOD2 | KEY_F1, + KEY_SHIFT | KEY_MOD2 | KEY_F2, + KEY_SHIFT | KEY_MOD2 | KEY_F3, + KEY_SHIFT | KEY_MOD2 | KEY_F4, + KEY_SHIFT | KEY_MOD2 | KEY_F5, + KEY_SHIFT | KEY_MOD2 | KEY_F6, + KEY_SHIFT | KEY_MOD2 | KEY_F7, + KEY_SHIFT | KEY_MOD2 | KEY_F8, + KEY_SHIFT | KEY_MOD2 | KEY_F9, + KEY_SHIFT | KEY_MOD2 | KEY_F10, + KEY_SHIFT | KEY_MOD2 | KEY_F11, + KEY_SHIFT | KEY_MOD2 | KEY_F12, + KEY_SHIFT | KEY_MOD2 | KEY_F13, + KEY_SHIFT | KEY_MOD2 | KEY_F14, + KEY_SHIFT | KEY_MOD2 | KEY_F15, + KEY_SHIFT | KEY_MOD2 | KEY_F16, + + KEY_SHIFT | KEY_MOD2 | KEY_DOWN, + KEY_SHIFT | KEY_MOD2 | KEY_UP, + KEY_SHIFT | KEY_MOD2 | KEY_LEFT, + KEY_SHIFT | KEY_MOD2 | KEY_RIGHT, + KEY_SHIFT | KEY_MOD2 | KEY_HOME, + KEY_SHIFT | KEY_MOD2 | KEY_END, + KEY_SHIFT | KEY_MOD2 | KEY_PAGEUP, + KEY_SHIFT | KEY_MOD2 | KEY_PAGEDOWN, + KEY_SHIFT | KEY_MOD2 | KEY_RETURN, + KEY_SHIFT | KEY_MOD2 | KEY_ESCAPE, + KEY_SHIFT | KEY_MOD2 | KEY_SPACE, + KEY_SHIFT | KEY_MOD2 | KEY_BACKSPACE, + KEY_SHIFT | KEY_MOD2 | KEY_INSERT, + KEY_SHIFT | KEY_MOD2 | KEY_DELETE, + KEY_SHIFT | KEY_MOD2 | KEY_EQUAL, + + KEY_MOD1 | KEY_MOD2 | KEY_0, + KEY_MOD1 | KEY_MOD2 | KEY_1, + KEY_MOD1 | KEY_MOD2 | KEY_2, + KEY_MOD1 | KEY_MOD2 | KEY_3, + KEY_MOD1 | KEY_MOD2 | KEY_4, + KEY_MOD1 | KEY_MOD2 | KEY_5, + KEY_MOD1 | KEY_MOD2 | KEY_6, + KEY_MOD1 | KEY_MOD2 | KEY_7, + KEY_MOD1 | KEY_MOD2 | KEY_8, + KEY_MOD1 | KEY_MOD2 | KEY_9, + KEY_MOD1 | KEY_MOD2 | KEY_A, + KEY_MOD1 | KEY_MOD2 | KEY_B, + KEY_MOD1 | KEY_MOD2 | KEY_C, + KEY_MOD1 | KEY_MOD2 | KEY_D, + KEY_MOD1 | KEY_MOD2 | KEY_E, + KEY_MOD1 | KEY_MOD2 | KEY_F, + KEY_MOD1 | KEY_MOD2 | KEY_G, + KEY_MOD1 | KEY_MOD2 | KEY_H, + KEY_MOD1 | KEY_MOD2 | KEY_I, + KEY_MOD1 | KEY_MOD2 | KEY_J, + KEY_MOD1 | KEY_MOD2 | KEY_K, + KEY_MOD1 | KEY_MOD2 | KEY_L, + KEY_MOD1 | KEY_MOD2 | KEY_M, + KEY_MOD1 | KEY_MOD2 | KEY_N, + KEY_MOD1 | KEY_MOD2 | KEY_O, + KEY_MOD1 | KEY_MOD2 | KEY_P, + KEY_MOD1 | KEY_MOD2 | KEY_Q, + KEY_MOD1 | KEY_MOD2 | KEY_R, + KEY_MOD1 | KEY_MOD2 | KEY_S, + KEY_MOD1 | KEY_MOD2 | KEY_T, + KEY_MOD1 | KEY_MOD2 | KEY_U, + KEY_MOD1 | KEY_MOD2 | KEY_V, + KEY_MOD1 | KEY_MOD2 | KEY_W, + KEY_MOD1 | KEY_MOD2 | KEY_X, + KEY_MOD1 | KEY_MOD2 | KEY_Y, + KEY_MOD1 | KEY_MOD2 | KEY_Z, + KEY_MOD1 | KEY_MOD2 | KEY_SEMICOLON, + KEY_MOD1 | KEY_MOD2 | KEY_QUOTERIGHT, + KEY_MOD1 | KEY_MOD2 | KEY_BRACKETLEFT, + KEY_MOD1 | KEY_MOD2 | KEY_BRACKETRIGHT, + KEY_MOD1 | KEY_MOD2 | KEY_POINT, + KEY_MOD1 | KEY_MOD2 | KEY_COMMA, + KEY_MOD1 | KEY_MOD2 | KEY_TILDE, + + KEY_MOD1 | KEY_MOD2 | KEY_F1, + KEY_MOD1 | KEY_MOD2 | KEY_F2, + KEY_MOD1 | KEY_MOD2 | KEY_F3, + KEY_MOD1 | KEY_MOD2 | KEY_F4, + KEY_MOD1 | KEY_MOD2 | KEY_F5, + KEY_MOD1 | KEY_MOD2 | KEY_F6, + KEY_MOD1 | KEY_MOD2 | KEY_F7, + KEY_MOD1 | KEY_MOD2 | KEY_F8, + KEY_MOD1 | KEY_MOD2 | KEY_F9, + KEY_MOD1 | KEY_MOD2 | KEY_F10, + KEY_MOD1 | KEY_MOD2 | KEY_F11, + KEY_MOD1 | KEY_MOD2 | KEY_F12, + KEY_MOD1 | KEY_MOD2 | KEY_F13, + KEY_MOD1 | KEY_MOD2 | KEY_F14, + KEY_MOD1 | KEY_MOD2 | KEY_F15, + KEY_MOD1 | KEY_MOD2 | KEY_F16, + + KEY_MOD1 | KEY_MOD2 | KEY_DOWN, + KEY_MOD1 | KEY_MOD2 | KEY_UP, + KEY_MOD1 | KEY_MOD2 | KEY_LEFT, + KEY_MOD1 | KEY_MOD2 | KEY_RIGHT, + KEY_MOD1 | KEY_MOD2 | KEY_HOME, + KEY_MOD1 | KEY_MOD2 | KEY_END, + KEY_MOD1 | KEY_MOD2 | KEY_PAGEUP, + KEY_MOD1 | KEY_MOD2 | KEY_PAGEDOWN, + KEY_MOD1 | KEY_MOD2 | KEY_RETURN, + KEY_MOD1 | KEY_MOD2 | KEY_SPACE, + KEY_MOD1 | KEY_MOD2 | KEY_BACKSPACE, + KEY_MOD1 | KEY_MOD2 | KEY_INSERT, + KEY_MOD1 | KEY_MOD2 | KEY_DELETE, + + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_0, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_1, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_2, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_3, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_4, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_5, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_6, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_7, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_8, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_9, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_A, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_B, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_C, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_D, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_E, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_F, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_G, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_H, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_I, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_J, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_K, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_L, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_M, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_N, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_O, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_P, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_Q, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_R, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_S, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_T, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_U, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_V, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_W, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_X, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_Y, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_Z, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_SEMICOLON, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_QUOTERIGHT, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_BRACKETLEFT, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_BRACKETRIGHT, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_POINT, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_COMMA, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_TILDE, + + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_F1, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_F2, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_F3, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_F4, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_F5, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_F6, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_F7, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_F8, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_F9, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_F10, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_F11, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_F12, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_F13, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_F14, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_F15, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_F16, + + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_DOWN, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_UP, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_LEFT, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_RIGHT, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_HOME, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_END, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_PAGEUP, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_PAGEDOWN, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_RETURN, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_SPACE, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_BACKSPACE, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_INSERT, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_DELETE, + KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_EQUAL + +#ifdef __APPLE__ + , + KEY_MOD3 | KEY_0, + KEY_MOD3 | KEY_1, + KEY_MOD3 | KEY_2, + KEY_MOD3 | KEY_3, + KEY_MOD3 | KEY_4, + KEY_MOD3 | KEY_5, + KEY_MOD3 | KEY_6, + KEY_MOD3 | KEY_7, + KEY_MOD3 | KEY_8, + KEY_MOD3 | KEY_9, + KEY_MOD3 | KEY_A, + KEY_MOD3 | KEY_B, + KEY_MOD3 | KEY_C, + KEY_MOD3 | KEY_D, + KEY_MOD3 | KEY_E, + KEY_MOD3 | KEY_F, + KEY_MOD3 | KEY_G, + KEY_MOD3 | KEY_H, + KEY_MOD3 | KEY_I, + KEY_MOD3 | KEY_J, + KEY_MOD3 | KEY_K, + KEY_MOD3 | KEY_L, + KEY_MOD3 | KEY_M, + KEY_MOD3 | KEY_N, + KEY_MOD3 | KEY_O, + KEY_MOD3 | KEY_P, + KEY_MOD3 | KEY_Q, + KEY_MOD3 | KEY_R, + KEY_MOD3 | KEY_S, + KEY_MOD3 | KEY_T, + KEY_MOD3 | KEY_U, + KEY_MOD3 | KEY_V, + KEY_MOD3 | KEY_W, + KEY_MOD3 | KEY_X, + KEY_MOD3 | KEY_Y, + KEY_MOD3 | KEY_Z, + KEY_MOD3 | KEY_SEMICOLON, + KEY_MOD3 | KEY_QUOTERIGHT, + KEY_MOD3 | KEY_BRACKETLEFT, + KEY_MOD3 | KEY_BRACKETRIGHT, + KEY_MOD3 | KEY_POINT, + KEY_MOD3 | KEY_COMMA, + KEY_MOD3 | KEY_TILDE, + KEY_MOD3 | KEY_TAB, + + KEY_MOD3 | KEY_F1, + KEY_MOD3 | KEY_F2, + KEY_MOD3 | KEY_F3, + KEY_MOD3 | KEY_F4, + KEY_MOD3 | KEY_F5, + KEY_MOD3 | KEY_F6, + KEY_MOD3 | KEY_F7, + KEY_MOD3 | KEY_F8, + KEY_MOD3 | KEY_F9, + KEY_MOD3 | KEY_F10, + KEY_MOD3 | KEY_F11, + KEY_MOD3 | KEY_F12, + KEY_MOD3 | KEY_F13, + KEY_MOD3 | KEY_F14, + KEY_MOD3 | KEY_F15, + KEY_MOD3 | KEY_F16, + + KEY_MOD3 | KEY_DOWN, + KEY_MOD3 | KEY_UP, + KEY_MOD3 | KEY_LEFT, + KEY_MOD3 | KEY_RIGHT, + KEY_MOD3 | KEY_HOME, + KEY_MOD3 | KEY_END, + KEY_MOD3 | KEY_PAGEUP, + KEY_MOD3 | KEY_PAGEDOWN, + KEY_MOD3 | KEY_RETURN, + KEY_MOD3 | KEY_SPACE, + KEY_MOD3 | KEY_BACKSPACE, + KEY_MOD3 | KEY_INSERT, + KEY_MOD3 | KEY_DELETE, + + KEY_MOD3 | KEY_ADD, + KEY_MOD3 | KEY_SUBTRACT, + KEY_MOD3 | KEY_MULTIPLY, + KEY_MOD3 | KEY_DIVIDE, + KEY_MOD3 | KEY_EQUAL, + + KEY_SHIFT | KEY_MOD3 | KEY_0, + KEY_SHIFT | KEY_MOD3 | KEY_1, + KEY_SHIFT | KEY_MOD3 | KEY_2, + KEY_SHIFT | KEY_MOD3 | KEY_3, + KEY_SHIFT | KEY_MOD3 | KEY_4, + KEY_SHIFT | KEY_MOD3 | KEY_5, + KEY_SHIFT | KEY_MOD3 | KEY_6, + KEY_SHIFT | KEY_MOD3 | KEY_7, + KEY_SHIFT | KEY_MOD3 | KEY_8, + KEY_SHIFT | KEY_MOD3 | KEY_9, + KEY_SHIFT | KEY_MOD3 | KEY_A, + KEY_SHIFT | KEY_MOD3 | KEY_B, + KEY_SHIFT | KEY_MOD3 | KEY_C, + KEY_SHIFT | KEY_MOD3 | KEY_D, + KEY_SHIFT | KEY_MOD3 | KEY_E, + KEY_SHIFT | KEY_MOD3 | KEY_F, + KEY_SHIFT | KEY_MOD3 | KEY_G, + KEY_SHIFT | KEY_MOD3 | KEY_H, + KEY_SHIFT | KEY_MOD3 | KEY_I, + KEY_SHIFT | KEY_MOD3 | KEY_J, + KEY_SHIFT | KEY_MOD3 | KEY_K, + KEY_SHIFT | KEY_MOD3 | KEY_L, + KEY_SHIFT | KEY_MOD3 | KEY_M, + KEY_SHIFT | KEY_MOD3 | KEY_N, + KEY_SHIFT | KEY_MOD3 | KEY_O, + KEY_SHIFT | KEY_MOD3 | KEY_P, + KEY_SHIFT | KEY_MOD3 | KEY_Q, + KEY_SHIFT | KEY_MOD3 | KEY_R, + KEY_SHIFT | KEY_MOD3 | KEY_S, + KEY_SHIFT | KEY_MOD3 | KEY_T, + KEY_SHIFT | KEY_MOD3 | KEY_U, + KEY_SHIFT | KEY_MOD3 | KEY_V, + KEY_SHIFT | KEY_MOD3 | KEY_W, + KEY_SHIFT | KEY_MOD3 | KEY_X, + KEY_SHIFT | KEY_MOD3 | KEY_Y, + KEY_SHIFT | KEY_MOD3 | KEY_Z, + KEY_SHIFT | KEY_MOD3 | KEY_SEMICOLON, + KEY_SHIFT | KEY_MOD3 | KEY_QUOTERIGHT, + KEY_SHIFT | KEY_MOD3 | KEY_BRACKETLEFT, + KEY_SHIFT | KEY_MOD3 | KEY_BRACKETRIGHT, + KEY_SHIFT | KEY_MOD3 | KEY_POINT, + KEY_SHIFT | KEY_MOD3 | KEY_COMMA, + KEY_SHIFT | KEY_MOD3 | KEY_TILDE, + KEY_SHIFT | KEY_MOD3 | KEY_TAB, + + KEY_SHIFT | KEY_MOD3 | KEY_F1, + KEY_SHIFT | KEY_MOD3 | KEY_F2, + KEY_SHIFT | KEY_MOD3 | KEY_F3, + KEY_SHIFT | KEY_MOD3 | KEY_F4, + KEY_SHIFT | KEY_MOD3 | KEY_F5, + KEY_SHIFT | KEY_MOD3 | KEY_F6, + KEY_SHIFT | KEY_MOD3 | KEY_F7, + KEY_SHIFT | KEY_MOD3 | KEY_F8, + KEY_SHIFT | KEY_MOD3 | KEY_F9, + KEY_SHIFT | KEY_MOD3 | KEY_F10, + KEY_SHIFT | KEY_MOD3 | KEY_F11, + KEY_SHIFT | KEY_MOD3 | KEY_F12, + KEY_SHIFT | KEY_MOD3 | KEY_F13, + KEY_SHIFT | KEY_MOD3 | KEY_F14, + KEY_SHIFT | KEY_MOD3 | KEY_F15, + KEY_SHIFT | KEY_MOD3 | KEY_F16, + + KEY_SHIFT | KEY_MOD3 | KEY_DOWN, + KEY_SHIFT | KEY_MOD3 | KEY_UP, + KEY_SHIFT | KEY_MOD3 | KEY_LEFT, + KEY_SHIFT | KEY_MOD3 | KEY_RIGHT, + KEY_SHIFT | KEY_MOD3 | KEY_HOME, + KEY_SHIFT | KEY_MOD3 | KEY_END, + KEY_SHIFT | KEY_MOD3 | KEY_PAGEUP, + KEY_SHIFT | KEY_MOD3 | KEY_PAGEDOWN, + KEY_SHIFT | KEY_MOD3 | KEY_RETURN, + KEY_SHIFT | KEY_MOD3 | KEY_ESCAPE, + KEY_SHIFT | KEY_MOD3 | KEY_SPACE, + KEY_SHIFT | KEY_MOD3 | KEY_BACKSPACE, + KEY_SHIFT | KEY_MOD3 | KEY_INSERT, + KEY_SHIFT | KEY_MOD3 | KEY_DELETE, + KEY_SHIFT | KEY_MOD3 | KEY_EQUAL +#endif +}; + +static const sal_uInt16 KEYCODE_ARRAY_SIZE = SAL_N_ELEMENTS(KEYCODE_ARRAY); + +/** select the entry, which match the current key input ... excepting + keys, which are used for the dialog itself. + */ +IMPL_LINK(SfxAcceleratorConfigPage, KeyInputHdl, const KeyEvent&, rKey, bool) +{ + vcl::KeyCode aCode1 = rKey.GetKeyCode(); + sal_uInt16 nCode1 = aCode1.GetCode(); + sal_uInt16 nMod1 = aCode1.GetModifier(); + + // is it related to our list box ? + if ((nCode1 != KEY_DOWN) && (nCode1 != KEY_UP) && (nCode1 != KEY_LEFT) && (nCode1 != KEY_RIGHT) + && (nCode1 != KEY_PAGEUP) && (nCode1 != KEY_PAGEDOWN)) + { + for (int i = 0, nCount = m_xEntriesBox->n_children(); i < nCount; ++i) + { + TAccInfo* pUserData = reinterpret_cast(m_xEntriesBox->get_id(i).toInt64()); + if (pUserData) + { + sal_uInt16 nCode2 = pUserData->m_aKey.GetCode(); + sal_uInt16 nMod2 = pUserData->m_aKey.GetModifier(); + + if (nCode1 == nCode2 && nMod1 == nMod2) + { + m_xEntriesBox->select(i); + m_xEntriesBox->scroll_to_row(i); + return true; + } + } + } + } + + // no - handle it as normal dialog input + return false; +} + +SfxAcceleratorConfigPage::SfxAcceleratorConfigPage(weld::Container* pPage, + weld::DialogController* pController, + const SfxItemSet& aSet) + : SfxTabPage(pPage, pController, "cui/ui/accelconfigpage.ui", "AccelConfigPage", &aSet) + , m_pMacroInfoItem() + , aLoadAccelConfigStr(CuiResId(RID_SVXSTR_LOADACCELCONFIG)) + , aSaveAccelConfigStr(CuiResId(RID_SVXSTR_SAVEACCELCONFIG)) + , aFilterAllStr(SfxResId(STR_SFX_FILTERNAME_ALL)) + , aFilterCfgStr(CuiResId(RID_SVXSTR_FILTERNAME_CFG)) + , m_bStylesInfoInitialized(false) + , m_xGlobal() + , m_xModule() + , m_xAct() + , m_aUpdateDataTimer("UpdateDataTimer") + , m_xEntriesBox(m_xBuilder->weld_tree_view("shortcuts")) + , m_xOfficeButton(m_xBuilder->weld_radio_button("office")) + , m_xModuleButton(m_xBuilder->weld_radio_button("module")) + , m_xChangeButton(m_xBuilder->weld_button("change")) + , m_xRemoveButton(m_xBuilder->weld_button("delete")) + , m_xGroupLBox(new CuiConfigGroupListBox(m_xBuilder->weld_tree_view("category"))) + , m_xFunctionBox(new CuiConfigFunctionListBox(m_xBuilder->weld_tree_view("function"))) + , m_xKeyBox(m_xBuilder->weld_tree_view("keys")) + , m_xSearchEdit(m_xBuilder->weld_entry("searchEntry")) + , m_xLoadButton(m_xBuilder->weld_button("load")) + , m_xSaveButton(m_xBuilder->weld_button("save")) + , m_xResetButton(m_xBuilder->weld_button("reset")) +{ + Size aSize(m_xEntriesBox->get_approximate_digit_width() * 40, + m_xEntriesBox->get_height_rows(12)); + m_xEntriesBox->set_size_request(aSize.Width(), aSize.Height()); + aSize = Size(m_xEntriesBox->get_approximate_digit_width() * 19, + m_xEntriesBox->get_height_rows(10)); + m_xGroupLBox->set_size_request(aSize.Width(), aSize.Height()); + aSize = Size(m_xEntriesBox->get_approximate_digit_width() * 21, + m_xEntriesBox->get_height_rows(10)); + m_xFunctionBox->set_size_request(aSize.Width(), aSize.Height()); + aSize = Size(m_xEntriesBox->get_approximate_digit_width() * 20, + m_xEntriesBox->get_height_rows(10)); + m_xKeyBox->set_size_request(aSize.Width(), aSize.Height()); + + // install handler functions + m_xChangeButton->connect_clicked(LINK(this, SfxAcceleratorConfigPage, ChangeHdl)); + m_xRemoveButton->connect_clicked(LINK(this, SfxAcceleratorConfigPage, RemoveHdl)); + m_xEntriesBox->connect_changed(LINK(this, SfxAcceleratorConfigPage, SelectHdl)); + m_xEntriesBox->connect_key_press(LINK(this, SfxAcceleratorConfigPage, KeyInputHdl)); + m_xGroupLBox->connect_changed(LINK(this, SfxAcceleratorConfigPage, SelectHdl)); + m_xFunctionBox->connect_changed(LINK(this, SfxAcceleratorConfigPage, SelectHdl)); + m_xKeyBox->connect_changed(LINK(this, SfxAcceleratorConfigPage, SelectHdl)); + m_xLoadButton->connect_clicked(LINK(this, SfxAcceleratorConfigPage, Load)); + m_xSaveButton->connect_clicked(LINK(this, SfxAcceleratorConfigPage, Save)); + m_xResetButton->connect_clicked(LINK(this, SfxAcceleratorConfigPage, Default)); + m_xOfficeButton->connect_clicked(LINK(this, SfxAcceleratorConfigPage, RadioHdl)); + m_xModuleButton->connect_clicked(LINK(this, SfxAcceleratorConfigPage, RadioHdl)); + m_xSearchEdit->connect_changed(LINK(this, SfxAcceleratorConfigPage, SearchUpdateHdl)); + m_xSearchEdit->connect_focus_out(LINK(this, SfxAcceleratorConfigPage, FocusOut_Impl)); + + // detect max keyname width + int nMaxWidth = 0; + for (unsigned short i : KEYCODE_ARRAY) + { + int nTmp = m_xEntriesBox->get_pixel_size(vcl::KeyCode(i).GetName()).Width(); + if (nTmp > nMaxWidth) + nMaxWidth = nTmp; + } + // recalc second tab + auto nNewTab = nMaxWidth + 5; // additional space + + // initialize Entriesbox + std::vector aWidths; + aWidths.push_back(nNewTab); + m_xEntriesBox->set_column_fixed_widths(aWidths); + + //Initialize search util + m_options.AlgorithmType2 = util::SearchAlgorithms2::ABSOLUTE; + m_options.transliterateFlags |= TransliterationFlags::IGNORE_CASE; + m_options.searchFlag + |= (util::SearchFlags::REG_NOT_BEGINOFLINE | util::SearchFlags::REG_NOT_ENDOFLINE); + // initialize GroupBox + m_xGroupLBox->SetFunctionListBox(m_xFunctionBox.get()); + + // initialize KeyBox + m_xKeyBox->make_sorted(); + + m_aUpdateDataTimer.SetInvokeHandler(LINK(this, SfxAcceleratorConfigPage, ImplUpdateDataHdl)); + m_aUpdateDataTimer.SetDebugName("SfxAcceleratorConfigPage UpdateDataTimer"); + m_aUpdateDataTimer.SetTimeout(EDIT_UPDATEDATA_TIMEOUT); + + m_aFillGroupIdle.SetInvokeHandler(LINK(this, SfxAcceleratorConfigPage, TimeOut_Impl)); + m_aFillGroupIdle.SetPriority(TaskPriority::HIGHEST); + m_aFillGroupIdle.SetDebugName("SfxAcceleratorConfigPage m_aFillGroupIdle"); +} + +SfxAcceleratorConfigPage::~SfxAcceleratorConfigPage() +{ + m_aFillGroupIdle.Stop(); + + // free memory - remove all dynamic user data + for (int i = 0, nCount = m_xEntriesBox->n_children(); i < nCount; ++i) + { + TAccInfo* pUserData = reinterpret_cast(m_xEntriesBox->get_id(i).toInt64()); + delete pUserData; + } +} + +void SfxAcceleratorConfigPage::InitAccCfg() +{ + // already initialized ? + if (m_xContext.is()) + return; // yes -> do nothing + + try + { + // no - initialize this instance + m_xContext = comphelper::getProcessComponentContext(); + + m_xUICmdDescription = frame::theUICommandDescription::get(m_xContext); + + // get the current active frame, which should be our "parent" + // for this session + m_xFrame = GetFrame(); + if (!m_xFrame.is()) + { + uno::Reference xDesktop = frame::Desktop::create(m_xContext); + m_xFrame = xDesktop->getActiveFrame(); + } + + // identify module + uno::Reference xModuleManager + = frame::ModuleManager::create(m_xContext); + m_sModuleLongName = xModuleManager->identify(m_xFrame); + comphelper::SequenceAsHashMap lModuleProps(xModuleManager->getByName(m_sModuleLongName)); + m_sModuleUIName + = lModuleProps.getUnpackedValueOrDefault("ooSetupFactoryUIName", OUString()); + + // get global accelerator configuration + m_xGlobal = css::ui::GlobalAcceleratorConfiguration::create(m_xContext); + + // get module accelerator configuration + + uno::Reference xModuleCfgSupplier( + ui::theModuleUIConfigurationManagerSupplier::get(m_xContext)); + uno::Reference xUICfgManager + = xModuleCfgSupplier->getUIConfigurationManager(m_sModuleLongName); + m_xModule = xUICfgManager->getShortCutManager(); + } + catch (const uno::RuntimeException&) + { + throw; + } + catch (const uno::Exception&) + { + m_xContext.clear(); + } +} + +void SfxAcceleratorConfigPage::Init(const uno::Reference& xAccMgr) +{ + if (!xAccMgr.is()) + return; + + if (!m_bStylesInfoInitialized) + { + uno::Reference xController; + uno::Reference xModel; + if (m_xFrame.is()) + xController = m_xFrame->getController(); + if (xController.is()) + xModel = xController->getModel(); + + m_aStylesInfo.init(m_sModuleLongName, xModel); + m_xGroupLBox->SetStylesInfo(&m_aStylesInfo); + m_bStylesInfoInitialized = true; + } + + // Insert all editable accelerators into list box. It is possible + // that some accelerators are not mapped on the current system/keyboard + // but we don't want to lose these mappings. + for (sal_Int32 i1 = 0; i1 < KEYCODE_ARRAY_SIZE; ++i1) + { + vcl::KeyCode aKey = KEYCODE_ARRAY[i1]; + OUString sKey = aKey.GetName(); + if (sKey.isEmpty()) + continue; + TAccInfo* pEntry = new TAccInfo(i1, 0 /*nListPos*/, aKey); + m_xEntriesBox->append(OUString::number(reinterpret_cast(pEntry)), sKey); + int nPos = m_xEntriesBox->n_children() - 1; + m_xEntriesBox->set_text(nPos, OUString(), 1); + m_xEntriesBox->set_sensitive(nPos, true); + } + + // Assign all commands to its shortcuts - reading the accelerator config. + uno::Sequence lKeys = xAccMgr->getAllKeyEvents(); + sal_Int32 c2 = lKeys.getLength(); + sal_Int32 i2 = 0; + + for (i2 = 0; i2 < c2; ++i2) + { + const awt::KeyEvent& aAWTKey = lKeys[i2]; + OUString sCommand = xAccMgr->getCommandByKeyEvent(aAWTKey); + OUString sLabel = GetLabel4Command(sCommand); + vcl::KeyCode aKeyCode = svt::AcceleratorExecute::st_AWTKey2VCLKey(aAWTKey); + sal_Int32 nPos = MapKeyCodeToPos(aKeyCode); + + if (nPos == -1) + continue; + + m_xEntriesBox->set_text(nPos, sLabel, 1); + + TAccInfo* pEntry = reinterpret_cast(m_xEntriesBox->get_id(nPos).toInt64()); + pEntry->m_bIsConfigurable = true; + + pEntry->m_sCommand = sCommand; + } + + // Map the VCL hardcoded key codes and mark them as not changeable + size_t c3 = Application::GetReservedKeyCodeCount(); + size_t i3 = 0; + for (i3 = 0; i3 < c3; ++i3) + { + const vcl::KeyCode* pKeyCode = Application::GetReservedKeyCode(i3); + sal_Int32 nPos = MapKeyCodeToPos(*pKeyCode); + + if (nPos == -1) + continue; + + // Hardcoded function mapped so no ID possible and mark entry as not changeable + TAccInfo* pEntry = reinterpret_cast(m_xEntriesBox->get_id(nPos).toInt64()); + pEntry->m_bIsConfigurable = false; + + m_xEntriesBox->set_sensitive(nPos, false); + } +} + +void SfxAcceleratorConfigPage::Apply(const uno::Reference& xAccMgr) +{ + if (!xAccMgr.is()) + return; + + // Go through the list from the bottom to the top ... + // because logical accelerator must be preferred instead of + // physical ones! + for (int i = 0, nCount = m_xEntriesBox->n_children(); i < nCount; ++i) + { + TAccInfo* pUserData = reinterpret_cast(m_xEntriesBox->get_id(i).toInt64()); + OUString sCommand; + awt::KeyEvent aAWTKey; + + if (pUserData) + { + sCommand = pUserData->m_sCommand; + aAWTKey = svt::AcceleratorExecute::st_VCLKey2AWTKey(pUserData->m_aKey); + } + + try + { + if (!sCommand.isEmpty()) + xAccMgr->setKeyEvent(aAWTKey, sCommand); + else + xAccMgr->removeKeyEvent(aAWTKey); + } + catch (const uno::RuntimeException&) + { + throw; + } + catch (const uno::Exception&) + { + } + } +} + +void SfxAcceleratorConfigPage::ResetConfig() { m_xEntriesBox->clear(); } + +IMPL_LINK_NOARG(SfxAcceleratorConfigPage, ImplUpdateDataHdl, Timer*, void) +{ + SelectHdl(m_xGroupLBox->get_widget()); +} + +IMPL_LINK_NOARG(SfxAcceleratorConfigPage, SearchUpdateHdl, weld::Entry&, void) +{ + m_aUpdateDataTimer.Start(); +} + +IMPL_LINK_NOARG(SfxAcceleratorConfigPage, FocusOut_Impl, weld::Widget&, void) +{ + if (m_aUpdateDataTimer.IsActive()) + { + m_aUpdateDataTimer.Stop(); + m_aUpdateDataTimer.Invoke(); + } +} + +IMPL_LINK_NOARG(SfxAcceleratorConfigPage, Load, weld::Button&, void) +{ + // ask for filename, where we should load the new config data from + StartFileDialog(StartFileDialogType::Open, aLoadAccelConfigStr); +} + +IMPL_LINK_NOARG(SfxAcceleratorConfigPage, Save, weld::Button&, void) +{ + StartFileDialog(StartFileDialogType::SaveAs, aSaveAccelConfigStr); +} + +IMPL_LINK_NOARG(SfxAcceleratorConfigPage, Default, weld::Button&, void) +{ + uno::Reference xReset(m_xAct, uno::UNO_QUERY); + if (xReset.is()) + xReset->reset(); + + m_xEntriesBox->freeze(); + ResetConfig(); + Init(m_xAct); + m_xEntriesBox->thaw(); + m_xEntriesBox->select(0); + SelectHdl(*m_xEntriesBox); +} + +IMPL_LINK_NOARG(SfxAcceleratorConfigPage, ChangeHdl, weld::Button&, void) +{ + int nPos = m_xEntriesBox->get_selected_index(); + if (nPos == -1) + return; + + TAccInfo* pEntry = reinterpret_cast(m_xEntriesBox->get_id(nPos).toInt64()); + OUString sNewCommand = m_xFunctionBox->GetCurCommand(); + OUString sLabel = m_xFunctionBox->GetCurLabel(); + if (sLabel.isEmpty()) + sLabel = GetLabel4Command(sNewCommand); + + pEntry->m_sCommand = sNewCommand; + m_xEntriesBox->set_text(nPos, sLabel, 1); + + SelectHdl(m_xFunctionBox->get_widget()); +} + +IMPL_LINK_NOARG(SfxAcceleratorConfigPage, RemoveHdl, weld::Button&, void) +{ + // get selected entry + int nPos = m_xEntriesBox->get_selected_index(); + if (nPos == -1) + return; + + TAccInfo* pEntry = reinterpret_cast(m_xEntriesBox->get_id(nPos).toInt64()); + + // remove function name from selected entry + m_xEntriesBox->set_text(nPos, OUString(), 1); + pEntry->m_sCommand.clear(); + + SelectHdl(m_xFunctionBox->get_widget()); +} + +IMPL_LINK(SfxAcceleratorConfigPage, SelectHdl, weld::TreeView&, rListBox, void) +{ + if (&rListBox == m_xEntriesBox.get()) + { + TAccInfo* pEntry = reinterpret_cast(m_xEntriesBox->get_selected_id().toInt64()); + + OUString sPossibleNewCommand = m_xFunctionBox->GetCurCommand(); + + m_xRemoveButton->set_sensitive(false); + m_xChangeButton->set_sensitive(false); + + if (pEntry && pEntry->m_bIsConfigurable) + { + if (pEntry->isConfigured()) + m_xRemoveButton->set_sensitive(true); + m_xChangeButton->set_sensitive(pEntry->m_sCommand != sPossibleNewCommand); + } + } + else if (&rListBox == &m_xGroupLBox->get_widget()) + { + m_xGroupLBox->GroupSelected(); + + // Pause redraw (Do not redraw at each removal) + m_xFunctionBox->freeze(); + // Apply the search filter to the functions list + OUString aSearchTerm(m_xSearchEdit->get_text()); + int nMatchFound = applySearchFilter(aSearchTerm); + // Resume redraw + m_xFunctionBox->thaw(); + if (nMatchFound != -1) + { + m_xFunctionBox->select(nMatchFound); + SelectHdl(m_xFunctionBox->get_widget()); + } + else + { + m_xKeyBox->clear(); + m_xChangeButton->set_sensitive(false); + } + } + else if (&rListBox == &m_xFunctionBox->get_widget()) + { + m_xRemoveButton->set_sensitive(false); + m_xChangeButton->set_sensitive(false); + + // #i36994 First selected can return null! + TAccInfo* pEntry = reinterpret_cast(m_xEntriesBox->get_selected_id().toInt64()); + if (pEntry) + { + OUString sPossibleNewCommand = m_xFunctionBox->GetCurCommand(); + + if (pEntry->m_bIsConfigurable) + { + if (pEntry->isConfigured()) + m_xRemoveButton->set_sensitive(true); + m_xChangeButton->set_sensitive(pEntry->m_sCommand != sPossibleNewCommand + && !sPossibleNewCommand.isEmpty()); + } + + // update key box + m_xKeyBox->clear(); + if (!sPossibleNewCommand.isEmpty()) + { + for (int i = 0, nCount = m_xEntriesBox->n_children(); i < nCount; ++i) + { + TAccInfo* pUserData + = reinterpret_cast(m_xEntriesBox->get_id(i).toInt64()); + if (pUserData && pUserData->m_sCommand == sPossibleNewCommand) + { + m_xKeyBox->append(OUString::number(reinterpret_cast(pUserData)), + pUserData->m_aKey.GetName()); + } + } + } + } + } + else + { + // goto selected "key" entry of the key box + int nP2 = -1; + TAccInfo* pU2 = reinterpret_cast(m_xKeyBox->get_selected_id().toInt64()); + if (pU2) + nP2 = MapKeyCodeToPos(pU2->m_aKey); + if (nP2 != -1) + { + m_xEntriesBox->select(nP2); + m_xEntriesBox->scroll_to_row(nP2); + SelectHdl(*m_xEntriesBox); + } + } +} + +IMPL_LINK_NOARG(SfxAcceleratorConfigPage, RadioHdl, weld::Button&, void) +{ + uno::Reference xOld = m_xAct; + + if (m_xOfficeButton->get_active()) + m_xAct = m_xGlobal; + else if (m_xModuleButton->get_active()) + m_xAct = m_xModule; + + // nothing changed? => do nothing! + if (m_xAct.is() && (xOld == m_xAct)) + return; + + m_xEntriesBox->freeze(); + ResetConfig(); + Init(m_xAct); + m_xEntriesBox->thaw(); + + m_xGroupLBox->Init(m_xContext, m_xFrame, m_sModuleLongName, true); + + // pb: #133213# do not select NULL entries + if (m_xEntriesBox->n_children()) + m_xEntriesBox->select(0); + + m_aFillGroupIdle.Start(); +} + +IMPL_LINK_NOARG(SfxAcceleratorConfigPage, TimeOut_Impl, Timer*, void) +{ + // activating the selection, typically "all commands", can take a long time + // -> show wait cursor and disable input + weld::WaitObject aWaitObject(GetFrameWeld()); + + weld::TreeView& rTreeView = m_xGroupLBox->get_widget(); + SelectHdl(rTreeView); +} + +IMPL_LINK_NOARG(SfxAcceleratorConfigPage, LoadHdl, sfx2::FileDialogHelper*, void) +{ + assert(m_pFileDlg); + + OUString sCfgName; + if (ERRCODE_NONE == m_pFileDlg->GetError()) + sCfgName = m_pFileDlg->GetPath(); + + if (sCfgName.isEmpty()) + return; + + weld::WaitObject aWaitObject(GetFrameWeld()); + + uno::Reference xCfgMgr; + uno::Reference + xRootStorage; // we must hold the root storage alive, if xCfgMgr is used! + + try + { + // don't forget to release the storage afterwards! + uno::Reference xStorageFactory( + embed::StorageFactory::create(m_xContext)); + uno::Sequence lArgs(2); + lArgs[0] <<= sCfgName; + lArgs[1] <<= css::embed::ElementModes::READ; + + xRootStorage.set(xStorageFactory->createInstanceWithArguments(lArgs), uno::UNO_QUERY_THROW); + uno::Reference xUIConfig + = xRootStorage->openStorageElement(FOLDERNAME_UICONFIG, embed::ElementModes::READ); + if (xUIConfig.is()) + { + uno::Reference xCfgMgr2 + = ui::UIConfigurationManager::create(m_xContext); + xCfgMgr2->setStorage(xUIConfig); + xCfgMgr.set(xCfgMgr2, uno::UNO_QUERY_THROW); + } + + if (xCfgMgr.is()) + { + // open the configuration and update our UI + uno::Reference xTempAccMgr(xCfgMgr->getShortCutManager(), + uno::UNO_SET_THROW); + + m_xEntriesBox->freeze(); + ResetConfig(); + Init(xTempAccMgr); + m_xEntriesBox->thaw(); + if (m_xEntriesBox->n_children()) + { + m_xEntriesBox->select(0); + SelectHdl(m_xFunctionBox->get_widget()); + } + } + + // don't forget to close the new opened storage! + // We are the owner of it. + if (xRootStorage.is()) + { + uno::Reference xComponent; + xComponent.set(xCfgMgr, uno::UNO_QUERY); + if (xComponent.is()) + xComponent->dispose(); + xRootStorage->dispose(); + } + } + catch (const uno::RuntimeException&) + { + throw; + } + catch (const uno::Exception&) + { + } +} + +IMPL_LINK_NOARG(SfxAcceleratorConfigPage, SaveHdl, sfx2::FileDialogHelper*, void) +{ + assert(m_pFileDlg); + + OUString sCfgName; + if (ERRCODE_NONE == m_pFileDlg->GetError()) + sCfgName = m_pFileDlg->GetPath(); + + if (sCfgName.isEmpty()) + return; + + weld::WaitObject aWaitObject(GetFrameWeld()); + + uno::Reference xRootStorage; + + try + { + uno::Reference xStorageFactory( + embed::StorageFactory::create(m_xContext)); + uno::Sequence lArgs(2); + lArgs[0] <<= sCfgName; + lArgs[1] <<= embed::ElementModes::WRITE; + + xRootStorage.set(xStorageFactory->createInstanceWithArguments(lArgs), uno::UNO_QUERY_THROW); + + uno::Reference xUIConfig( + xRootStorage->openStorageElement(FOLDERNAME_UICONFIG, embed::ElementModes::WRITE), + uno::UNO_SET_THROW); + uno::Reference xUIConfigProps(xUIConfig, uno::UNO_QUERY_THROW); + + // set the correct media type if the storage was new created + OUString sMediaType; + xUIConfigProps->getPropertyValue(MEDIATYPE_PROPNAME) >>= sMediaType; + if (sMediaType.isEmpty()) + xUIConfigProps->setPropertyValue( + MEDIATYPE_PROPNAME, uno::Any(OUString("application/vnd.sun.xml.ui.configuration"))); + + uno::Reference xCfgMgr + = ui::UIConfigurationManager::create(m_xContext); + xCfgMgr->setStorage(xUIConfig); + + // get the target configuration access and update with all shortcuts + // which are set currently at the UI! + // Don't copy the m_xAct content to it... because m_xAct will be updated + // from the UI on pressing the button "OK" only. And inbetween it's not up to date! + uno::Reference xTargetAccMgr(xCfgMgr->getShortCutManager(), + uno::UNO_SET_THROW); + Apply(xTargetAccMgr); + + // commit (order is important!) + uno::Reference xCommit1(xTargetAccMgr, + uno::UNO_QUERY_THROW); + uno::Reference xCommit2(xCfgMgr, uno::UNO_QUERY_THROW); + xCommit1->store(); + xCommit2->store(); + + if (xRootStorage.is()) + { + // Commit root storage + uno::Reference xCommit3(xRootStorage, uno::UNO_QUERY_THROW); + xCommit3->commit(); + } + + if (xRootStorage.is()) + { + if (xCfgMgr.is()) + xCfgMgr->dispose(); + xRootStorage->dispose(); + } + } + catch (const uno::RuntimeException&) + { + throw; + } + catch (const uno::Exception&) + { + } +} + +void SfxAcceleratorConfigPage::StartFileDialog(StartFileDialogType nType, const OUString& rTitle) +{ + bool bSave = nType == StartFileDialogType::SaveAs; + short nDialogType = bSave ? ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION + : ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE; + m_pFileDlg.reset( + new sfx2::FileDialogHelper(nDialogType, FileDialogFlags::NONE, GetFrameWeld())); + + m_pFileDlg->SetTitle(rTitle); + m_pFileDlg->AddFilter(aFilterAllStr, FILEDIALOG_FILTER_ALL); + m_pFileDlg->AddFilter(aFilterCfgStr, "*.cfg"); + m_pFileDlg->SetCurrentFilter(aFilterCfgStr); + + Link aDlgClosedLink + = bSave ? LINK(this, SfxAcceleratorConfigPage, SaveHdl) + : LINK(this, SfxAcceleratorConfigPage, LoadHdl); + m_pFileDlg->StartExecuteModal(aDlgClosedLink); +} + +bool SfxAcceleratorConfigPage::FillItemSet(SfxItemSet*) +{ + Apply(m_xAct); + try + { + m_xAct->store(); + } + catch (const uno::RuntimeException&) + { + throw; + } + catch (const uno::Exception&) + { + return false; + } + + return true; +} + +void SfxAcceleratorConfigPage::Reset(const SfxItemSet* rSet) +{ + // open accelerator configs + // Note: It initialize some other members too, which are needed here ... + // e.g. m_sModuleUIName! + InitAccCfg(); + + // change the description of the radio button, which switch to the module + // dependent accelerator configuration + OUString sButtonText = m_xModuleButton->get_label(); + sButtonText + = m_xModuleButton->strip_mnemonic(sButtonText).replaceFirst("$(MODULE)", m_sModuleUIName); + m_xModuleButton->set_label(sButtonText); + + if (m_xModule.is()) + m_xModuleButton->set_active(true); + else + { + m_xModuleButton->hide(); + m_xOfficeButton->set_active(true); + } + + RadioHdl(*m_xOfficeButton); + + const SfxPoolItem* pMacroItem = nullptr; + if (SfxItemState::SET == rSet->GetItemState(SID_MACROINFO, true, &pMacroItem)) + { + m_pMacroInfoItem = &dynamic_cast(*pMacroItem); + m_xGroupLBox->SelectMacro(m_pMacroInfoItem); + } +} + +sal_Int32 SfxAcceleratorConfigPage::MapKeyCodeToPos(const vcl::KeyCode& aKey) const +{ + sal_uInt16 nCode1 = aKey.GetCode() + aKey.GetModifier(); + for (int i = 0, nCount = m_xEntriesBox->n_children(); i < nCount; ++i) + { + TAccInfo* pUserData = reinterpret_cast(m_xEntriesBox->get_id(i).toInt64()); + if (pUserData) + { + sal_uInt16 nCode2 = pUserData->m_aKey.GetCode() + pUserData->m_aKey.GetModifier(); + if (nCode1 == nCode2) + return i; + } + } + + return -1; +} + +OUString SfxAcceleratorConfigPage::GetLabel4Command(const OUString& sCommand) +{ + try + { + // check global command configuration first + uno::Reference xModuleConf; + m_xUICmdDescription->getByName(m_sModuleLongName) >>= xModuleConf; + if (xModuleConf.is()) + { + ::comphelper::SequenceAsHashMap lProps(xModuleConf->getByName(sCommand)); + OUString sLabel = lProps.getUnpackedValueOrDefault("Name", OUString()); + if (!sLabel.isEmpty()) + return sLabel; + } + } + catch (const uno::RuntimeException&) + { + throw; + } + catch (const uno::Exception&) + { + } + + // may be it's a style URL .. they must be handled special + SfxStyleInfo_Impl aStyle; + aStyle.sCommand = sCommand; + if (SfxStylesInfo_Impl::parseStyleCommand(aStyle)) + { + m_aStylesInfo.getLabel4Style(aStyle); + return aStyle.sLabel; + } + + return sCommand; +} + +/* + * Remove entries which doesn't contain the search term + */ +int SfxAcceleratorConfigPage::applySearchFilter(OUString const& rSearchTerm) +{ + if (rSearchTerm.isEmpty()) + return -1; + + m_options.searchString = rSearchTerm; + utl::TextSearch textSearch(m_options); + + for (int i = m_xFunctionBox->n_children(); i > 0; --i) + { + int nEntry = i - 1; + OUString aStr = m_xFunctionBox->get_text(nEntry); + sal_Int32 aStartPos = 0; + sal_Int32 aEndPos = aStr.getLength(); + + if (!textSearch.SearchForward(aStr, &aStartPos, &aEndPos)) + m_xFunctionBox->remove(nEntry); + } + + return m_xFunctionBox->n_children() ? 0 : -1; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/customize/cfg.cxx b/cui/source/customize/cfg.cxx new file mode 100644 index 000000000..04664d511 --- /dev/null +++ b/cui/source/customize/cfg.cxx @@ -0,0 +1,3201 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "eventdlg.hxx" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace uno = com::sun::star::uno; +namespace frame = com::sun::star::frame; +namespace lang = com::sun::star::lang; +namespace container = com::sun::star::container; +namespace beans = com::sun::star::beans; +namespace graphic = com::sun::star::graphic; + +#if OSL_DEBUG_LEVEL > 1 + +void printPropertySet( + const OUString& prefix, + const uno::Reference< beans::XPropertySet >& xPropSet ) +{ + uno::Reference< beans::XPropertySetInfo > xPropSetInfo = + xPropSet->getPropertySetInfo(); + + const uno::Sequence< beans::Property >& aPropDetails = + xPropSetInfo->getProperties(); + + SAL_WARN("cui", "printPropertySet: " << aPropDetails.getLength() << " properties" ); + + for ( beans::Property const & aPropDetail : aPropDetails ) + { + OUString tmp; + sal_Int32 ival; + + uno::Any a = xPropSet->getPropertyValue( aPropDetail.Name ); + + if ( a >>= tmp ) + { + SAL_WARN("cui", prefix << ": Got property: " << aPropDetail.Name << tmp); + } + else if ( ( a >>= ival ) ) + { + SAL_WARN("cui", prefix << ": Got property: " << aPropDetail.Name << " = " << ival); + } + else + { + SAL_WARN("cui", prefix << ": Got property: " << aPropDetail.Name << " of type " << a.getValueTypeName()); + } + } +} + +void printProperties( + const OUString& prefix, + const uno::Sequence< beans::PropertyValue >& aProp ) +{ + for (beans::PropertyValue const & aPropVal : aProp) + { + OUString tmp; + + aPropVal.Value >>= tmp; + + SAL_WARN("cui", prefix << ": Got property: " << aPropVal.Name << " = " << tmp); + } +} + +void printEntries(SvxEntries* entries) +{ + for (auto const& entry : *entries) + { + SAL_WARN("cui", "printEntries: " << entry->GetName()); + } +} + +#endif + +bool +SvxConfigPage::CanConfig( const OUString& aModuleId ) +{ + return !(aModuleId == "com.sun.star.script.BasicIDE" || aModuleId == "com.sun.star.frame.Bibliography"); +} + +static std::unique_ptr CreateSvxMenuConfigPage( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet ) +{ + return std::make_unique(pPage, pController, *rSet); +} + +static std::unique_ptr CreateSvxContextMenuConfigPage( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet ) +{ + return std::make_unique(pPage, pController, *rSet, false); +} + +static std::unique_ptr CreateKeyboardConfigPage( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet ) +{ + return std::make_unique(pPage, pController, *rSet); +} + +static std::unique_ptr CreateSvxNotebookbarConfigPage(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rSet) +{ + return std::make_unique(pPage, pController, *rSet); +} + +static std::unique_ptr CreateSvxToolbarConfigPage( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet ) +{ + return std::make_unique(pPage, pController, *rSet); +} + +static std::unique_ptr CreateSvxEventConfigPage( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet ) +{ + return std::make_unique(pPage, pController, *rSet, SvxEventConfigPage::EarlyInit()); +} + +/****************************************************************************** + * + * SvxConfigDialog is the configuration dialog which is brought up from the + * Tools menu. It includes tabs for customizing menus, toolbars, events and + * key bindings. + * + *****************************************************************************/ +SvxConfigDialog::SvxConfigDialog(weld::Window * pParent, const SfxItemSet* pInSet) + : SfxTabDialogController(pParent, "cui/ui/customizedialog.ui", "CustomizeDialog", pInSet) +{ + SvxConfigPageHelper::InitImageType(); + + AddTabPage("menus", CreateSvxMenuConfigPage, nullptr); + AddTabPage("toolbars", CreateSvxToolbarConfigPage, nullptr); + AddTabPage("notebookbar", CreateSvxNotebookbarConfigPage, nullptr); + AddTabPage("contextmenus", CreateSvxContextMenuConfigPage, nullptr); + AddTabPage("keyboard", CreateKeyboardConfigPage, nullptr); + AddTabPage("events", CreateSvxEventConfigPage, nullptr); + + const SfxPoolItem* pItem = + pInSet->GetItem( pInSet->GetPool()->GetWhich( SID_CONFIG ) ); + + if ( pItem ) + { + OUString text = static_cast(pItem)->GetValue(); + + if (text.startsWith( ITEM_TOOLBAR_URL ) ) + { + SetCurPageId("toolbars"); + } + } +} + +void SvxConfigDialog::SetFrame(const css::uno::Reference& xFrame) +{ + m_xFrame = xFrame; + OUString aModuleId = SvxConfigPage::GetFrameWithDefaultAndIdentify(m_xFrame); + + if (aModuleId != "com.sun.star.text.TextDocument" && + aModuleId != "com.sun.star.sheet.SpreadsheetDocument" && + aModuleId != "com.sun.star.presentation.PresentationDocument" && + aModuleId != "com.sun.star.drawing.DrawingDocument") + RemoveTabPage("notebookbar"); + + if (aModuleId == "com.sun.star.frame.StartModule") + RemoveTabPage("keyboard"); +} + +void SvxConfigDialog::PageCreated(const OString &rId, SfxTabPage& rPage) +{ + if (rId == "menus" || rId == "keyboard" || rId == "notebookbar" + || rId == "toolbars" || rId == "contextmenus") + { + rPage.SetFrame(m_xFrame); + } + else if (rId == "events") + { + dynamic_cast< SvxEventConfigPage& >( rPage ).LateInit( m_xFrame ); + } +} + +/****************************************************************************** + * + * The SaveInData class is used to hold data for entries in the Save In + * ListBox controls in the menu and toolbar tabs + * + ******************************************************************************/ + +// Initialize static variable which holds default XImageManager +uno::Reference< css::ui::XImageManager>* SaveInData::xDefaultImgMgr = nullptr; + +SaveInData::SaveInData( + const uno::Reference< css::ui::XUIConfigurationManager >& xCfgMgr, + const uno::Reference< css::ui::XUIConfigurationManager >& xParentCfgMgr, + const OUString& aModuleId, + bool isDocConfig ) + : + bModified( false ), + bDocConfig( isDocConfig ), + bReadOnly( false ), + m_xCfgMgr( xCfgMgr ), + m_xParentCfgMgr( xParentCfgMgr ) +{ + m_aSeparatorSeq.realloc( 1 ); + m_aSeparatorSeq[0].Name = ITEM_DESCRIPTOR_TYPE; + m_aSeparatorSeq[0].Value <<= css::ui::ItemType::SEPARATOR_LINE; + + if ( bDocConfig ) + { + uno::Reference< css::ui::XUIConfigurationPersistence > + xDocPersistence( GetConfigManager(), uno::UNO_QUERY ); + + bReadOnly = xDocPersistence->isReadOnly(); + } + + uno::Reference xContext = ::comphelper::getProcessComponentContext(); + + uno::Reference< container::XNameAccess > xNameAccess( + css::frame::theUICommandDescription::get(xContext) ); + + xNameAccess->getByName( aModuleId ) >>= m_xCommandToLabelMap; + + if ( !m_xImgMgr.is() ) + { + m_xImgMgr.set( GetConfigManager()->getImageManager(), uno::UNO_QUERY ); + } + + if ( !IsDocConfig() ) + { + // If this is not a document configuration then it is the settings + // for the module (writer, calc, impress etc.) Use this as the default + // XImageManager instance + xDefaultImgMgr = &m_xImgMgr; + } + else + { + // If this is a document configuration then use the module image manager + // as default. + if ( m_xParentCfgMgr.is() ) + { + m_xParentImgMgr.set( m_xParentCfgMgr->getImageManager(), uno::UNO_QUERY ); + xDefaultImgMgr = &m_xParentImgMgr; + } + } +} + +uno::Reference SaveInData::GetImage(const OUString& rCommandURL) +{ + uno::Reference< graphic::XGraphic > xGraphic = + SvxConfigPageHelper::GetGraphic( m_xImgMgr, rCommandURL ); + + if (!xGraphic.is() && xDefaultImgMgr != nullptr && (*xDefaultImgMgr).is()) + { + xGraphic = SvxConfigPageHelper::GetGraphic( (*xDefaultImgMgr), rCommandURL ); + } + + return xGraphic; +} + +bool SaveInData::PersistChanges( + const uno::Reference< uno::XInterface >& xManager ) +{ + bool result = true; + + try + { + if ( xManager.is() && !IsReadOnly() ) + { + uno::Reference< css::ui::XUIConfigurationPersistence > + xConfigPersistence( xManager, uno::UNO_QUERY ); + + if ( xConfigPersistence->isModified() ) + { + xConfigPersistence->store(); + } + } + } + catch ( css::io::IOException& ) + { + result = false; + } + + return result; +} + +/****************************************************************************** + * + * The MenuSaveInData class extends SaveInData and provides menu specific + * load and store functionality. + * + ******************************************************************************/ + +// Initialize static variable which holds default Menu data +MenuSaveInData* MenuSaveInData::pDefaultData = nullptr; + +MenuSaveInData::MenuSaveInData( + const uno::Reference< css::ui::XUIConfigurationManager >& cfgmgr, + const uno::Reference< css::ui::XUIConfigurationManager >& xParentCfgMgr, + const OUString& aModuleId, + bool isDocConfig ) + : + SaveInData( cfgmgr, xParentCfgMgr, aModuleId, isDocConfig ), + m_aMenuResourceURL( + ITEM_MENUBAR_URL ), + m_aDescriptorContainer( + ITEM_DESCRIPTOR_CONTAINER ) +{ + try + { + OUString url( ITEM_MENUBAR_URL ); + m_xMenuSettings = GetConfigManager()->getSettings( url, false ); + } + catch ( container::NoSuchElementException& ) + { + // will use menu settings for the module + } + + // If this is not a document configuration then it is the settings + // for the module (writer, calc, impress etc.). These settings should + // be set as the default to be used for SaveIn locations that do not + // have custom settings + if ( !IsDocConfig() ) + { + SetDefaultData( this ); + } +} + +MenuSaveInData::~MenuSaveInData() +{ +} + +SvxEntries* +MenuSaveInData::GetEntries() +{ + if ( pRootEntry == nullptr ) + { + pRootEntry.reset( new SvxConfigEntry( "MainMenus", OUString(), true, /*bParentData*/false) ); + + if ( m_xMenuSettings.is() ) + { + LoadSubMenus( m_xMenuSettings, OUString(), pRootEntry.get(), false ); + } + else if ( GetDefaultData() != nullptr ) + { + // If the doc has no config settings use module config settings + LoadSubMenus( GetDefaultData()->m_xMenuSettings, OUString(), pRootEntry.get(), false ); + } + } + + return pRootEntry->GetEntries(); +} + +void +MenuSaveInData::SetEntries( std::unique_ptr pNewEntries ) +{ + pRootEntry->SetEntries( std::move(pNewEntries) ); +} + +void SaveInData::LoadSubMenus( const uno::Reference< container::XIndexAccess >& xMenuSettings, + const OUString& rBaseTitle, SvxConfigEntry const * pParentData, bool bContextMenu ) +{ + SvxEntries* pEntries = pParentData->GetEntries(); + + // Don't access non existing menu configuration! + if ( !xMenuSettings.is() ) + return; + + for ( sal_Int32 nIndex = 0; nIndex < xMenuSettings->getCount(); ++nIndex ) + { + uno::Reference< container::XIndexAccess > xSubMenu; + OUString aCommandURL; + OUString aLabel; + + sal_uInt16 nType( css::ui::ItemType::DEFAULT ); + sal_Int32 nStyle(0); + + bool bItem = SvxConfigPageHelper::GetMenuItemData( xMenuSettings, nIndex, + aCommandURL, aLabel, nType, nStyle, xSubMenu ); + + if ( bItem ) + { + bool bIsUserDefined = true; + + if ( nType == css::ui::ItemType::DEFAULT ) + { + uno::Any a; + try + { + a = m_xCommandToLabelMap->getByName( aCommandURL ); + bIsUserDefined = false; + } + catch ( container::NoSuchElementException& ) + { + bIsUserDefined = true; + } + + bool bUseDefaultLabel = false; + // If custom label not set retrieve it from the command + // to info service + if ( aLabel.isEmpty() ) + { + bUseDefaultLabel = true; + uno::Sequence< beans::PropertyValue > aPropSeq; + if ( a >>= aPropSeq ) + { + OUString aMenuLabel; + for ( const beans::PropertyValue& prop : std::as_const(aPropSeq) ) + { + if ( bContextMenu ) + { + if ( prop.Name == "PopupLabel" ) + { + prop.Value >>= aLabel; + break; + } + else if ( prop.Name == "Label" ) + { + prop.Value >>= aMenuLabel; + } + } + else if ( prop.Name == "Label" ) + { + prop.Value >>= aLabel; + break; + } + } + if ( aLabel.isEmpty() ) + aLabel = aMenuLabel; + } + } + + SvxConfigEntry* pEntry = new SvxConfigEntry( + aLabel, aCommandURL, xSubMenu.is(), /*bParentData*/false ); + + pEntry->SetStyle( nStyle ); + pEntry->SetUserDefined( bIsUserDefined ); + if ( !bUseDefaultLabel ) + pEntry->SetName( aLabel ); + + pEntries->push_back( pEntry ); + + if ( xSubMenu.is() ) + { + // popup menu + OUString subMenuTitle( rBaseTitle ); + + if ( !subMenuTitle.isEmpty() ) + { + subMenuTitle += aMenuSeparatorStr; + } + else + { + pEntry->SetMain(); + } + + subMenuTitle += SvxConfigPageHelper::stripHotKey( aLabel ); + + LoadSubMenus( xSubMenu, subMenuTitle, pEntry, bContextMenu ); + } + } + else + { + SvxConfigEntry* pEntry = new SvxConfigEntry; + pEntry->SetUserDefined( bIsUserDefined ); + pEntries->push_back( pEntry ); + } + } + } +} + +bool MenuSaveInData::Apply() +{ + bool result = false; + + if ( IsModified() ) + { + // Apply new menu bar structure to our settings container + m_xMenuSettings = GetConfigManager()->createSettings(); + + uno::Reference< container::XIndexContainer > xIndexContainer ( + m_xMenuSettings, uno::UNO_QUERY ); + + uno::Reference< lang::XSingleComponentFactory > xFactory ( + m_xMenuSettings, uno::UNO_QUERY ); + + Apply( xIndexContainer, xFactory ); + + try + { + if ( GetConfigManager()->hasSettings( m_aMenuResourceURL ) ) + { + GetConfigManager()->replaceSettings( + m_aMenuResourceURL, m_xMenuSettings ); + } + else + { + GetConfigManager()->insertSettings( + m_aMenuResourceURL, m_xMenuSettings ); + } + } + catch ( css::uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("cui.customize", "caught some other exception saving settings"); + } + + SetModified( false ); + + result = PersistChanges( GetConfigManager() ); + } + + return result; +} + +void MenuSaveInData::Apply( + uno::Reference< container::XIndexContainer > const & rMenuBar, + uno::Reference< lang::XSingleComponentFactory >& rFactory ) +{ + uno::Reference xContext = ::comphelper::getProcessComponentContext(); + + for (auto const& entryData : *GetEntries()) + { + uno::Sequence< beans::PropertyValue > aPropValueSeq = + SvxConfigPageHelper::ConvertSvxConfigEntry(entryData); + + uno::Reference< container::XIndexContainer > xSubMenuBar( + rFactory->createInstanceWithContext( xContext ), + uno::UNO_QUERY ); + + sal_Int32 nIndex = aPropValueSeq.getLength(); + aPropValueSeq.realloc( nIndex + 1 ); + aPropValueSeq[nIndex].Name = m_aDescriptorContainer; + aPropValueSeq[nIndex].Value <<= xSubMenuBar; + rMenuBar->insertByIndex( + rMenuBar->getCount(), uno::Any( aPropValueSeq )); + ApplyMenu( xSubMenuBar, rFactory, entryData ); + } +} + +void SaveInData::ApplyMenu( + uno::Reference< container::XIndexContainer > const & rMenuBar, + uno::Reference< lang::XSingleComponentFactory >& rFactory, + SvxConfigEntry* pMenuData ) +{ + uno::Reference xContext = ::comphelper::getProcessComponentContext(); + + for (auto const& entry : *pMenuData->GetEntries()) + { + if (entry->IsPopup()) + { + uno::Sequence< beans::PropertyValue > aPropValueSeq = + SvxConfigPageHelper::ConvertSvxConfigEntry(entry); + + uno::Reference< container::XIndexContainer > xSubMenuBar( + rFactory->createInstanceWithContext( xContext ), + uno::UNO_QUERY ); + + sal_Int32 nIndex = aPropValueSeq.getLength(); + aPropValueSeq.realloc( nIndex + 1 ); + aPropValueSeq[nIndex].Name = ITEM_DESCRIPTOR_CONTAINER; + aPropValueSeq[nIndex].Value <<= xSubMenuBar; + + rMenuBar->insertByIndex( + rMenuBar->getCount(), uno::Any( aPropValueSeq )); + + ApplyMenu( xSubMenuBar, rFactory, entry ); + entry->SetModified( false ); + } + else if (entry->IsSeparator()) + { + rMenuBar->insertByIndex( + rMenuBar->getCount(), uno::Any( m_aSeparatorSeq )); + } + else + { + uno::Sequence< beans::PropertyValue > aPropValueSeq = + SvxConfigPageHelper::ConvertSvxConfigEntry(entry); + rMenuBar->insertByIndex( + rMenuBar->getCount(), uno::Any( aPropValueSeq )); + } + } + pMenuData->SetModified( false ); +} + +void +MenuSaveInData::Reset() +{ + try + { + GetConfigManager()->removeSettings( m_aMenuResourceURL ); + } + catch ( const css::uno::Exception& ) + {} + + PersistChanges( GetConfigManager() ); + + pRootEntry.reset(); + + try + { + m_xMenuSettings = GetConfigManager()->getSettings( + m_aMenuResourceURL, false ); + } + catch ( container::NoSuchElementException& ) + { + // will use default settings + } +} + +ContextMenuSaveInData::ContextMenuSaveInData( + const css::uno::Reference< css::ui::XUIConfigurationManager >& xCfgMgr, + const css::uno::Reference< css::ui::XUIConfigurationManager >& xParentCfgMgr, + const OUString& aModuleId, bool bIsDocConfig ) + : SaveInData( xCfgMgr, xParentCfgMgr, aModuleId, bIsDocConfig ) +{ + css::uno::Reference< css::uno::XComponentContext > xContext( comphelper::getProcessComponentContext() ); + css::uno::Reference< css::container::XNameAccess > xConfig( css::ui::theWindowStateConfiguration::get( xContext ) ); + xConfig->getByName( aModuleId ) >>= m_xPersistentWindowState; +} + +ContextMenuSaveInData::~ContextMenuSaveInData() +{ +} + +OUString ContextMenuSaveInData::GetUIName( const OUString& rResourceURL ) +{ + if ( m_xPersistentWindowState.is() ) + { + css::uno::Sequence< css::beans::PropertyValue > aProps; + try + { + m_xPersistentWindowState->getByName( rResourceURL ) >>= aProps; + } + catch ( const css::uno::Exception& ) + {} + + for ( const auto& aProp : std::as_const(aProps) ) + { + if ( aProp.Name == ITEM_DESCRIPTOR_UINAME ) + { + OUString aResult; + aProp.Value >>= aResult; + return aResult; + } + } + } + return OUString(); +} + +SvxEntries* ContextMenuSaveInData::GetEntries() +{ + if ( !m_pRootEntry ) + { + std::unordered_map< OUString, bool > aMenuInfo; + + m_pRootEntry.reset( new SvxConfigEntry( "ContextMenus", OUString(), true, /*bParentData*/false ) ); + css::uno::Sequence< css::uno::Sequence< css::beans::PropertyValue > > aElementsInfo; + try + { + aElementsInfo = GetConfigManager()->getUIElementsInfo( css::ui::UIElementType::POPUPMENU ); + } + catch ( const css::lang::IllegalArgumentException& ) + {} + + for ( const auto& aElement : std::as_const(aElementsInfo) ) + { + OUString aUrl; + for ( const auto& aElementProp : aElement ) + { + if ( aElementProp.Name == ITEM_DESCRIPTOR_RESOURCEURL ) + { + aElementProp.Value >>= aUrl; + break; + } + } + + css::uno::Reference< css::container::XIndexAccess > xPopupMenu; + try + { + xPopupMenu = GetConfigManager()->getSettings( aUrl, false ); + } + catch ( const css::uno::Exception& ) + {} + + if ( xPopupMenu.is() ) + { + // insert into std::unordered_map to filter duplicates from the parent + aMenuInfo.emplace( aUrl, true ); + + OUString aUIMenuName = GetUIName( aUrl ); + if ( aUIMenuName.isEmpty() ) + // Menus without UI name aren't supposed to be customized. + continue; + + SvxConfigEntry* pEntry = new SvxConfigEntry( aUIMenuName, aUrl, true, /*bParentData*/false ); + pEntry->SetMain(); + m_pRootEntry->GetEntries()->push_back( pEntry ); + LoadSubMenus( xPopupMenu, aUIMenuName, pEntry, true ); + } + } + + // Retrieve also the parent menus, to make it possible to configure module menus and save them into the document. + css::uno::Reference< css::ui::XUIConfigurationManager > xParentCfgMgr = GetParentConfigManager(); + css::uno::Sequence< css::uno::Sequence< css::beans::PropertyValue > > aParentElementsInfo; + try + { + if ( xParentCfgMgr.is() ) + aParentElementsInfo = xParentCfgMgr->getUIElementsInfo( css::ui::UIElementType::POPUPMENU ); + } + catch ( const css::lang::IllegalArgumentException& ) + {} + + for ( const auto& aElement : std::as_const(aParentElementsInfo) ) + { + OUString aUrl; + for ( const auto& aElementProp : aElement ) + { + if ( aElementProp.Name == ITEM_DESCRIPTOR_RESOURCEURL ) + { + aElementProp.Value >>= aUrl; + break; + } + } + + css::uno::Reference< css::container::XIndexAccess > xPopupMenu; + try + { + if ( aMenuInfo.find( aUrl ) == aMenuInfo.end() ) + xPopupMenu = xParentCfgMgr->getSettings( aUrl, false ); + } + catch ( const css::uno::Exception& ) + {} + + if ( xPopupMenu.is() ) + { + OUString aUIMenuName = GetUIName( aUrl ); + if ( aUIMenuName.isEmpty() ) + continue; + + SvxConfigEntry* pEntry = new SvxConfigEntry( aUIMenuName, aUrl, true, true ); + pEntry->SetMain(); + m_pRootEntry->GetEntries()->push_back( pEntry ); + LoadSubMenus( xPopupMenu, aUIMenuName, pEntry, true ); + } + } + std::sort( m_pRootEntry->GetEntries()->begin(), m_pRootEntry->GetEntries()->end(), SvxConfigPageHelper::EntrySort ); + } + return m_pRootEntry->GetEntries(); +} + +void ContextMenuSaveInData::SetEntries( std::unique_ptr pNewEntries ) +{ + m_pRootEntry->SetEntries( std::move(pNewEntries) ); +} + +bool ContextMenuSaveInData::HasURL( const OUString& rURL ) +{ + SvxEntries* pEntries = GetEntries(); + for ( const auto& pEntry : *pEntries ) + if ( pEntry->GetCommand() == rURL ) + return true; + + return false; +} + +bool ContextMenuSaveInData::HasSettings() +{ + return m_pRootEntry && !m_pRootEntry->GetEntries()->empty(); +} + +bool ContextMenuSaveInData::Apply() +{ + if ( !IsModified() ) + return false; + + SvxEntries* pEntries = GetEntries(); + for ( const auto& pEntry : *pEntries ) + { + if ( pEntry->IsModified() || SvxConfigPageHelper::SvxConfigEntryModified( pEntry ) ) + { + css::uno::Reference< css::container::XIndexContainer > xIndexContainer = GetConfigManager()->createSettings(); + css::uno::Reference< css::lang::XSingleComponentFactory > xFactory( xIndexContainer, css::uno::UNO_QUERY ); + ApplyMenu( xIndexContainer, xFactory, pEntry ); + + const OUString& aUrl = pEntry->GetCommand(); + try + { + if ( GetConfigManager()->hasSettings( aUrl ) ) + GetConfigManager()->replaceSettings( aUrl, xIndexContainer ); + else + GetConfigManager()->insertSettings( aUrl, xIndexContainer ); + } + catch ( const css::uno::Exception& ) + {} + } + } + SetModified( false ); + return PersistChanges( GetConfigManager() ); +} + +void ContextMenuSaveInData::Reset() +{ + SvxEntries* pEntries = GetEntries(); + for ( const auto& pEntry : *pEntries ) + { + try + { + GetConfigManager()->removeSettings( pEntry->GetCommand() ); + } + catch ( const css::uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("cui.customize", "Exception caught while resetting context menus"); + } + } + PersistChanges( GetConfigManager() ); + m_pRootEntry.reset(); +} + +void ContextMenuSaveInData::ResetContextMenu( const SvxConfigEntry* pEntry ) +{ + try + { + GetConfigManager()->removeSettings( pEntry->GetCommand() ); + } + catch ( const css::uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("cui.customize", "Exception caught while resetting context menu"); + } + PersistChanges( GetConfigManager() ); + m_pRootEntry.reset(); +} + +void SvxMenuEntriesListBox::CreateDropDown() +{ + int nWidth = m_xControl->get_text_height() / 2; + m_xDropDown->SetOutputSizePixel(Size(nWidth, nWidth)); + DecorationView aDecoView(m_xDropDown.get()); + aDecoView.DrawSymbol(tools::Rectangle(Point(0, 0), Size(nWidth, nWidth)), + SymbolType::SPIN_RIGHT, m_xDropDown->GetTextColor(), + DrawSymbolFlags::NONE); +} + +/****************************************************************************** + * + * SvxMenuEntriesListBox is the listbox in which the menu items for a + * particular menu are shown. We have a custom listbox because we need + * to add drag'n'drop support from the Macro Selector and within the + * listbox + * + *****************************************************************************/ +SvxMenuEntriesListBox::SvxMenuEntriesListBox(std::unique_ptr xControl, SvxConfigPage* pPg) + : m_xControl(std::move(xControl)) + , m_xDropDown(m_xControl->create_virtual_device()) + , m_pPage(pPg) +{ + CreateDropDown(); + m_xControl->connect_key_press(LINK(this, SvxMenuEntriesListBox, KeyInputHdl)); +} + +SvxMenuEntriesListBox::~SvxMenuEntriesListBox() +{ +} + +IMPL_LINK(SvxMenuEntriesListBox, KeyInputHdl, const KeyEvent&, rKeyEvent, bool) +{ + vcl::KeyCode keycode = rKeyEvent.GetKeyCode(); + + // support DELETE for removing the current entry + if ( keycode == KEY_DELETE ) + { + m_pPage->DeleteSelectedContent(); + } + // support CTRL+UP and CTRL+DOWN for moving selected entries + else if ( keycode.GetCode() == KEY_UP && keycode.IsMod1() ) + { + m_pPage->MoveEntry( true ); + } + else if ( keycode.GetCode() == KEY_DOWN && keycode.IsMod1() ) + { + m_pPage->MoveEntry( false ); + } + else + { + return false; // pass on to default handler + } + return true; +} + +/****************************************************************************** + * + * SvxConfigPage is the abstract base class on which the Menu and Toolbar + * configuration tabpages are based. It includes methods which are common to + * both tabpages to add, delete, move and rename items etc. + * + *****************************************************************************/ +SvxConfigPage::SvxConfigPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/menuassignpage.ui", "MenuAssignPage", &rSet) + , m_aUpdateDataTimer("UpdateDataTimer") + , bInitialised(false) + , pCurrentSaveInData(nullptr) + , m_xCommandCategoryListBox(new CommandCategoryListBox(m_xBuilder->weld_combo_box("commandcategorylist"))) + , m_xFunctions(new CuiConfigFunctionListBox(m_xBuilder->weld_tree_view("functions"))) + , m_xCategoryLabel(m_xBuilder->weld_label("categorylabel")) + , m_xDescriptionFieldLb(m_xBuilder->weld_label("descriptionlabel")) + , m_xDescriptionField(m_xBuilder->weld_text_view("desc")) + , m_xLeftFunctionLabel(m_xBuilder->weld_label("leftfunctionlabel")) + , m_xSearchEdit(m_xBuilder->weld_entry("searchEntry")) + , m_xSearchLabel(m_xBuilder->weld_label("searchlabel")) + , m_xCustomizeLabel(m_xBuilder->weld_label("customizelabel")) + , m_xTopLevelListBox(m_xBuilder->weld_combo_box("toplevellist")) + , m_xMoveUpButton(m_xBuilder->weld_button("up")) + , m_xMoveDownButton(m_xBuilder->weld_button("down")) + , m_xSaveInListBox(m_xBuilder->weld_combo_box("savein")) + , m_xInsertBtn(m_xBuilder->weld_menu_button("insert")) + , m_xModifyBtn(m_xBuilder->weld_menu_button("modify")) + , m_xResetBtn(m_xBuilder->weld_button("defaultsbtn")) + , m_xAddCommandButton(m_xBuilder->weld_button("add")) + , m_xRemoveCommandButton(m_xBuilder->weld_button("remove")) +{ + CustomNotebookbarGenerator::getFileNameAndAppName(m_sAppName, m_sFileName); + + m_xTopLevelListBox->connect_changed(LINK(this, SvxConfigPage, SelectElementHdl)); + + weld::TreeView& rTreeView = m_xFunctions->get_widget(); + Size aSize(rTreeView.get_approximate_digit_width() * 40, rTreeView.get_height_rows(8)); + m_xFunctions->set_size_request(aSize.Width(), aSize.Height()); + m_xDescriptionField->set_size_request(aSize.Width(), m_xDescriptionField->get_height_rows(3)); + + m_aUpdateDataTimer.SetInvokeHandler(LINK(this, SvxConfigPage, ImplUpdateDataHdl)); + m_aUpdateDataTimer.SetDebugName( "SvxConfigPage UpdateDataTimer" ); + m_aUpdateDataTimer.SetTimeout(EDIT_UPDATEDATA_TIMEOUT); + + m_xSearchEdit->connect_changed(LINK(this, SvxConfigPage, SearchUpdateHdl)); + m_xSearchEdit->connect_focus_out(LINK(this, SvxConfigPage, FocusOut_Impl)); + + rTreeView.connect_row_activated(LINK(this, SvxConfigPage, FunctionDoubleClickHdl)); + rTreeView.connect_changed(LINK(this, SvxConfigPage, SelectFunctionHdl)); +} + +IMPL_LINK_NOARG(SvxConfigPage, SelectElementHdl, weld::ComboBox&, void) +{ + SelectElement(); +} + +SvxConfigPage::~SvxConfigPage() +{ +} + +void SvxConfigPage::Reset( const SfxItemSet* ) +{ + // If we haven't initialised our XMultiServiceFactory reference + // then Reset is being called at the opening of the dialog. + + // Load menu configuration data for the module of the currently + // selected document, for the currently selected document, and for + // all other open documents of the same module type + if ( !bInitialised ) + { + sal_Int32 nPos = 0; + uno::Reference < css::ui::XUIConfigurationManager > xCfgMgr; + uno::Reference < css::ui::XUIConfigurationManager > xDocCfgMgr; + + uno::Reference< uno::XComponentContext > xContext( + ::comphelper::getProcessComponentContext(), uno::UNO_SET_THROW ); + + m_xFrame = GetFrame(); + m_aModuleId = GetFrameWithDefaultAndIdentify( m_xFrame ); + + // replace %MODULENAME in the label with the correct module name + uno::Reference< css::frame::XModuleManager2 > xModuleManager( + css::frame::ModuleManager::create( xContext )); + OUString aModuleName = SvxConfigPageHelper::GetUIModuleName( m_aModuleId, xModuleManager ); + + uno::Reference< css::ui::XModuleUIConfigurationManagerSupplier > + xModuleCfgSupplier( css::ui::theModuleUIConfigurationManagerSupplier::get(xContext) ); + + // Set up data for module specific menus + SaveInData* pModuleData = nullptr; + + try + { + xCfgMgr = + xModuleCfgSupplier->getUIConfigurationManager( m_aModuleId ); + + pModuleData = CreateSaveInData( xCfgMgr, + uno::Reference< css::ui::XUIConfigurationManager >(), + m_aModuleId, + false ); + } + catch ( container::NoSuchElementException& ) + { + } + + if ( pModuleData != nullptr ) + { + OUString sId(OUString::number(reinterpret_cast(pModuleData))); + m_xSaveInListBox->append(sId, utl::ConfigManager::getProductName() + " " + aModuleName); + } + + // try to retrieve the document based ui configuration manager + OUString aTitle; + uno::Reference< frame::XController > xController = + m_xFrame->getController(); + if ( CanConfig( m_aModuleId ) && xController.is() ) + { + uno::Reference< frame::XModel > xModel( xController->getModel() ); + if ( xModel.is() ) + { + uno::Reference< css::ui::XUIConfigurationManagerSupplier > + xCfgSupplier( xModel, uno::UNO_QUERY ); + + if ( xCfgSupplier.is() ) + { + xDocCfgMgr = xCfgSupplier->getUIConfigurationManager(); + } + aTitle = ::comphelper::DocumentInfo::getDocumentTitle( xModel ); + } + } + + SaveInData* pDocData = nullptr; + if ( xDocCfgMgr.is() ) + { + pDocData = CreateSaveInData( xDocCfgMgr, xCfgMgr, m_aModuleId, true ); + + if ( !pDocData->IsReadOnly() ) + { + OUString sId(OUString::number(reinterpret_cast(pDocData))); + m_xSaveInListBox->append(sId, aTitle); + } + } + + // if an item to select has been passed in (eg. the ResourceURL for a + // toolbar) then try to select the SaveInData entry that has that item + bool bURLToSelectFound = false; + if ( !m_aURLToSelect.isEmpty() ) + { + if ( pDocData && pDocData->HasURL( m_aURLToSelect ) ) + { + m_xSaveInListBox->set_active(nPos); + pCurrentSaveInData = pDocData; + bURLToSelectFound = true; + } + else if ( pModuleData && pModuleData->HasURL( m_aURLToSelect ) ) + { + m_xSaveInListBox->set_active(0); + pCurrentSaveInData = pModuleData; + bURLToSelectFound = true; + } + } + + if ( !bURLToSelectFound ) + { + // if the document has menu configuration settings select it + // it the SaveIn listbox, otherwise select the module data + if ( pDocData != nullptr && pDocData->HasSettings() ) + { + m_xSaveInListBox->set_active(nPos); + pCurrentSaveInData = pDocData; + } + else + { + m_xSaveInListBox->set_active(0); + pCurrentSaveInData = pModuleData; + } + } + +#ifdef DBG_UTIL + DBG_ASSERT( pCurrentSaveInData, "SvxConfigPage::Reset(): no SaveInData" ); +#endif + + if ( CanConfig( m_aModuleId ) ) + { + // Load configuration for other open documents which have + // same module type + uno::Sequence< uno::Reference< frame::XFrame > > aFrameList; + try + { + uno::Reference< frame::XDesktop2 > xFramesSupplier = frame::Desktop::create( + xContext ); + + uno::Reference< frame::XFrames > xFrames = + xFramesSupplier->getFrames(); + + aFrameList = xFrames->queryFrames( + frame::FrameSearchFlag::ALL & ~frame::FrameSearchFlag::SELF ); + + } + catch( const uno::Exception& ) + { + DBG_UNHANDLED_EXCEPTION("cui.customize"); + } + + for ( uno::Reference < frame::XFrame > const & xf : std::as_const(aFrameList) ) + { + if ( xf.is() && xf != m_xFrame ) + { + OUString aCheckId; + try{ + aCheckId = xModuleManager->identify( xf ); + } catch(const uno::Exception&) + { aCheckId.clear(); } + + if ( m_aModuleId == aCheckId ) + { + // try to get the document based ui configuration manager + OUString aTitle2; + uno::Reference< frame::XController > xController_ = + xf->getController(); + + if ( xController_.is() ) + { + uno::Reference< frame::XModel > xModel( + xController_->getModel() ); + + if ( xModel.is() ) + { + uno::Reference< + css::ui::XUIConfigurationManagerSupplier > + xCfgSupplier( xModel, uno::UNO_QUERY ); + + if ( xCfgSupplier.is() ) + { + xDocCfgMgr = + xCfgSupplier->getUIConfigurationManager(); + } + aTitle2 = ::comphelper::DocumentInfo::getDocumentTitle( xModel ); + } + } + + if ( xDocCfgMgr.is() ) + { + SaveInData* pData = CreateSaveInData( xDocCfgMgr, xCfgMgr, m_aModuleId, true ); + + if ( pData && !pData->IsReadOnly() ) + { + OUString sId(OUString::number(reinterpret_cast(pData))); + m_xSaveInListBox->append(sId, aTitle2); + } + } + } + } + } + } + + m_xSaveInListBox->connect_changed( + LINK( this, SvxConfigPage, SelectSaveInLocation ) ); + + bInitialised = true; + + Init(); + } + else + { + if ( QueryReset() == RET_YES ) + { + // Reset menu configuration for currently selected SaveInData + GetSaveInData()->Reset(); + + Init(); + } + } +} + +OUString SvxConfigPage::GetFrameWithDefaultAndIdentify( uno::Reference< frame::XFrame >& _inout_rxFrame ) +{ + OUString sModuleID; + try + { + uno::Reference< uno::XComponentContext > xContext( + ::comphelper::getProcessComponentContext() ); + + uno::Reference< frame::XDesktop2 > xDesktop = frame::Desktop::create( + xContext ); + + if ( !_inout_rxFrame.is() ) + _inout_rxFrame = xDesktop->getActiveFrame(); + + if ( !_inout_rxFrame.is() ) + { + _inout_rxFrame = xDesktop->getCurrentFrame(); + } + + if ( !_inout_rxFrame.is() && SfxViewFrame::Current() ) + _inout_rxFrame = SfxViewFrame::Current()->GetFrame().GetFrameInterface(); + + if ( !_inout_rxFrame.is() ) + { + SAL_WARN( "cui.customize", "SvxConfigPage::GetFrameWithDefaultAndIdentify(): no frame found!" ); + return sModuleID; + } + + sModuleID = vcl::CommandInfoProvider::GetModuleIdentifier(_inout_rxFrame); + } + catch( const uno::Exception& ) + { + DBG_UNHANDLED_EXCEPTION("cui.customize"); + } + + return sModuleID; +} + +OUString SvxConfigPage::GetScriptURL() const +{ + OUString result; + + SfxGroupInfo_Impl *pData = reinterpret_cast(m_xFunctions->get_selected_id().toInt64()); + if (pData) + { + if ( ( pData->nKind == SfxCfgKind::FUNCTION_SLOT ) || + ( pData->nKind == SfxCfgKind::FUNCTION_SCRIPT ) || + ( pData->nKind == SfxCfgKind::GROUP_STYLES ) ) + { + result = pData->sCommand; + } + } + + return result; +} + +OUString SvxConfigPage::GetSelectedDisplayName() const +{ + return m_xFunctions->get_selected_text(); +} + +bool SvxConfigPage::FillItemSet( SfxItemSet* ) +{ + bool result = false; + + for (int i = 0, nCount = m_xSaveInListBox->get_count(); i < nCount; ++i) + { + OUString sId = m_xSaveInListBox->get_id(i); + if (sId != notebookbarTabScope) + { + SaveInData* pData = reinterpret_cast(sId.toInt64()); + result = pData->Apply(); + } + } + return result; +} + +IMPL_LINK_NOARG(SvxConfigPage, SelectSaveInLocation, weld::ComboBox&, void) +{ + OUString sId = m_xSaveInListBox->get_active_id(); + if (sId != notebookbarTabScope) + pCurrentSaveInData = reinterpret_cast(sId.toInt64()); + Init(); +} + +void SvxConfigPage::ReloadTopLevelListBox( SvxConfigEntry const * pToSelect ) +{ + int nSelectionPos = m_xTopLevelListBox->get_active(); + m_xTopLevelListBox->clear(); + + if ( GetSaveInData() && GetSaveInData()->GetEntries() ) + { + for (auto const& entryData : *GetSaveInData()->GetEntries()) + { + OUString sId(OUString::number(reinterpret_cast(entryData))); + m_xTopLevelListBox->append(sId, SvxConfigPageHelper::stripHotKey(entryData->GetName())); + + if (entryData == pToSelect) + nSelectionPos = m_xTopLevelListBox->get_count() - 1; + + AddSubMenusToUI( SvxConfigPageHelper::stripHotKey( entryData->GetName() ), entryData ); + } + } +#ifdef DBG_UTIL + else + { + DBG_ASSERT( GetSaveInData(), "SvxConfigPage::ReloadTopLevelListBox(): no SaveInData" ); + DBG_ASSERT( GetSaveInData()->GetEntries() , + "SvxConfigPage::ReloadTopLevelListBox(): no SaveInData entries" ); + } +#endif + + nSelectionPos = (nSelectionPos != -1 && nSelectionPos < m_xTopLevelListBox->get_count()) ? + nSelectionPos : m_xTopLevelListBox->get_count() - 1; + + m_xTopLevelListBox->set_active(nSelectionPos); + SelectElement(); +} + +void SvxConfigPage::AddSubMenusToUI( + const OUString& rBaseTitle, SvxConfigEntry const * pParentData ) +{ + for (auto const& entryData : *pParentData->GetEntries()) + { + if (entryData->IsPopup()) + { + OUString subMenuTitle = rBaseTitle + aMenuSeparatorStr + SvxConfigPageHelper::stripHotKey(entryData->GetName()); + + OUString sId(OUString::number(reinterpret_cast(entryData))); + m_xTopLevelListBox->append(sId, subMenuTitle); + + AddSubMenusToUI( subMenuTitle, entryData ); + } + } +} + +SvxEntries* SvxConfigPage::FindParentForChild( + SvxEntries* pRootEntries, SvxConfigEntry* pChildData ) +{ + for (auto const& entryData : *pRootEntries) + { + + if (entryData == pChildData) + { + return pRootEntries; + } + else if (entryData->IsPopup()) + { + SvxEntries* result = + FindParentForChild( entryData->GetEntries(), pChildData ); + + if ( result != nullptr ) + { + return result; + } + } + } + return nullptr; +} + +int SvxConfigPage::AddFunction(int nTarget, bool bAllowDuplicates) +{ + OUString aURL = GetScriptURL(); + SvxConfigEntry* pParent = GetTopLevelSelection(); + + if ( aURL.isEmpty() || pParent == nullptr ) + { + return -1; + } + + OUString aDisplayName; + + auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(aURL, m_aModuleId); + + if ( typeid(*pCurrentSaveInData) == typeid(ContextMenuSaveInData) ) + aDisplayName = vcl::CommandInfoProvider::GetPopupLabelForCommand(aProperties); + else if ( typeid(*pCurrentSaveInData) == typeid(MenuSaveInData) ) + aDisplayName = vcl::CommandInfoProvider::GetMenuLabelForCommand(aProperties); + else + aDisplayName = vcl::CommandInfoProvider::GetLabelForCommand(aProperties); + + SvxConfigEntry* pNewEntryData = + new SvxConfigEntry( aDisplayName, aURL, false, /*bParentData*/false ); + pNewEntryData->SetUserDefined(); + + if ( aDisplayName.isEmpty() ) + pNewEntryData->SetName( GetSelectedDisplayName() ); + + // check that this function is not already in the menu + if ( !bAllowDuplicates ) + { + for (auto const& entry : *pParent->GetEntries()) + { + if ( entry->GetCommand() == pNewEntryData->GetCommand() ) + { + std::unique_ptr xBox(Application::CreateMessageDialog(GetFrameWeld(), + VclMessageType::Info, VclButtonsType::Ok, CuiResId(RID_SVXSTR_MNUCFG_ALREADY_INCLUDED))); + xBox->run(); + delete pNewEntryData; + return -1; + } + } + } + + return AppendEntry(pNewEntryData, nTarget); +} + +int SvxConfigPage::AppendEntry( + SvxConfigEntry* pNewEntryData, + int nTarget) +{ + SvxConfigEntry* pTopLevelSelection = GetTopLevelSelection(); + + if (pTopLevelSelection == nullptr) + return -1; + + // Grab the entries list for the currently selected menu + SvxEntries* pEntries = pTopLevelSelection->GetEntries(); + + int nNewEntry = -1; + int nCurEntry = + nTarget != -1 ? nTarget : m_xContentsListBox->get_selected_index(); + + OUString sId(OUString::number(reinterpret_cast(pNewEntryData))); + + if (nCurEntry == -1 || nCurEntry == m_xContentsListBox->n_children() - 1) + { + pEntries->push_back( pNewEntryData ); + m_xContentsListBox->insert(-1, sId); + nNewEntry = m_xContentsListBox->n_children() - 1; + } + else + { + SvxConfigEntry* pEntryData = + reinterpret_cast(m_xContentsListBox->get_id(nCurEntry).toInt64()); + + SvxEntries::iterator iter = pEntries->begin(); + SvxEntries::const_iterator end = pEntries->end(); + + // Advance the iterator to the data for currently selected entry + sal_uInt16 nPos = 0; + while (*iter != pEntryData && ++iter != end) + { + ++nPos; + } + + // Now step past it to the entry after the currently selected one + ++iter; + ++nPos; + + // Now add the new entry to the UI and to the parent's list + if ( iter != end ) + { + pEntries->insert( iter, pNewEntryData ); + m_xContentsListBox->insert(nPos, sId); + nNewEntry = nPos; + } + } + + if (nNewEntry != -1) + { + m_xContentsListBox->select(nNewEntry); + m_xContentsListBox->scroll_to_row(nNewEntry); + + GetSaveInData()->SetModified(); + GetTopLevelSelection()->SetModified(); + } + + return nNewEntry; +} + +namespace +{ + template void TmplInsertEntryIntoUI(SvxConfigEntry* pNewEntryData, weld::TreeView& rTreeView, itertype& rIter, int nStartCol, SaveInData* pSaveInData, VirtualDevice& rDropDown) + { + OUString sId(OUString::number(reinterpret_cast(pNewEntryData))); + + rTreeView.set_id(rIter, sId); + + if (pNewEntryData->IsSeparator()) + { + rTreeView.set_text(rIter, "----------------------------------", nStartCol + 1); + } + else + { + auto xImage = pSaveInData->GetImage(pNewEntryData->GetCommand()); + if (xImage.is()) + rTreeView.set_image(rIter, xImage, nStartCol); + OUString aName = SvxConfigPageHelper::stripHotKey( pNewEntryData->GetName() ); + rTreeView.set_text(rIter, aName, nStartCol + 1); + } + + if (nStartCol == 0) // menus + { + if (pNewEntryData->IsPopup() || pNewEntryData->GetStyle() & css::ui::ItemStyle::DROP_DOWN) + rTreeView.set_image(rIter, rDropDown, nStartCol + 2); + else + rTreeView.set_image(rIter, css::uno::Reference(), nStartCol + 2); + } + } +} + +void SvxConfigPage::InsertEntryIntoUI(SvxConfigEntry* pNewEntryData, weld::TreeView& rTreeView, int nPos, int nStartCol) +{ + TmplInsertEntryIntoUI(pNewEntryData, rTreeView, nPos, nStartCol, + GetSaveInData(), m_xContentsListBox->get_dropdown_image()); +} + +void SvxConfigPage::InsertEntryIntoUI(SvxConfigEntry* pNewEntryData, weld::TreeView& rTreeView, weld::TreeIter& rIter, int nStartCol) +{ + TmplInsertEntryIntoUI(pNewEntryData, rTreeView, rIter, nStartCol, + GetSaveInData(), m_xContentsListBox->get_dropdown_image()); +} + +IMPL_LINK(SvxConfigPage, MoveHdl, weld::Button&, rButton, void) +{ + MoveEntry(&rButton == m_xMoveUpButton.get()); +} + +IMPL_LINK_NOARG(SvxConfigPage, FunctionDoubleClickHdl, weld::TreeView&, bool) +{ + if (m_xAddCommandButton->get_sensitive()) + m_xAddCommandButton->clicked(); + return true; +} + +IMPL_LINK_NOARG(SvxConfigPage, SelectFunctionHdl, weld::TreeView&, void) +{ + // GetScriptURL() returns a non-empty string if a + // valid command is selected on the left box + OUString aSelectCommand = GetScriptURL(); + bool bIsValidCommand = !aSelectCommand.isEmpty(); + + // Enable/disable Add and Remove buttons depending on current selection + if (bIsValidCommand) + { + m_xAddCommandButton->set_sensitive(true); + m_xRemoveCommandButton->set_sensitive(true); + + if (SfxHelp::IsHelpInstalled()) + { + m_xDescriptionField->set_text(m_xFunctions->GetHelpText(false)); + } + else + { + SfxGroupInfo_Impl *pData = reinterpret_cast(m_xFunctions->get_selected_id().toInt64()); + if (pData) + { + OUString aLabel = CuiResId(RID_SVXSTR_COMMANDLABEL) + ": " + pData->sLabel + "\n"; + OUString aName = CuiResId(RID_SVXSTR_COMMANDNAME) + ": " + pData->sCommand + "\n"; + OUString aTip = CuiResId(RID_SVXSTR_COMMANDTIP) + ": " + pData->sTooltip; + m_xDescriptionField->set_text(aLabel + aName + aTip); + } + } + } + else + { + + m_xAddCommandButton->set_sensitive(false); + m_xRemoveCommandButton->set_sensitive(false); + + m_xDescriptionField->set_text(""); + } +} + +IMPL_LINK_NOARG(SvxConfigPage, ImplUpdateDataHdl, Timer*, void) +{ + OUString aSearchTerm(m_xSearchEdit->get_text()); + m_xCommandCategoryListBox->categorySelected(m_xFunctions.get(), aSearchTerm, GetSaveInData()); +} + +IMPL_LINK_NOARG(SvxConfigPage, SearchUpdateHdl, weld::Entry&, void) +{ + m_aUpdateDataTimer.Start(); +} + +IMPL_LINK_NOARG(SvxConfigPage, FocusOut_Impl, weld::Widget&, void) +{ + if (m_aUpdateDataTimer.IsActive()) + { + m_aUpdateDataTimer.Stop(); + m_aUpdateDataTimer.Invoke(); + } +} + +void SvxConfigPage::MoveEntry(bool bMoveUp) +{ + weld::TreeView& rTreeView = m_xContentsListBox->get_widget(); + + int nSourceEntry = rTreeView.get_selected_index(); + int nTargetEntry = -1; + int nToSelect = -1; + + if (nSourceEntry == -1) + { + return; + } + + if ( bMoveUp ) + { + // Move Up is just a Move Down with the source and target reversed + nTargetEntry = nSourceEntry; + nSourceEntry = nTargetEntry - 1; + nToSelect = nSourceEntry; + } + else + { + nTargetEntry = nSourceEntry + 1; + nToSelect = nTargetEntry; + } + + if (MoveEntryData(nSourceEntry, nTargetEntry)) + { + rTreeView.swap(nSourceEntry, nTargetEntry); + rTreeView.select(nToSelect); + rTreeView.scroll_to_row(nToSelect); + + UpdateButtonStates(); + } +} + +bool SvxConfigPage::MoveEntryData(int nSourceEntry, int nTargetEntry) +{ + //#i53677# + if (nSourceEntry == -1 || nTargetEntry == -1) + { + return false; + } + + // Grab the entries list for the currently selected menu + SvxEntries* pEntries = GetTopLevelSelection()->GetEntries(); + + SvxConfigEntry* pSourceData = + reinterpret_cast(m_xContentsListBox->get_id(nSourceEntry).toInt64()); + + SvxConfigEntry* pTargetData = + reinterpret_cast(m_xContentsListBox->get_id(nTargetEntry).toInt64()); + + if ( pSourceData != nullptr && pTargetData != nullptr ) + { + // remove the source entry from our list + SvxConfigPageHelper::RemoveEntry( pEntries, pSourceData ); + + SvxEntries::iterator iter = pEntries->begin(); + SvxEntries::const_iterator end = pEntries->end(); + + // advance the iterator to the position of the target entry + while (*iter != pTargetData && ++iter != end) ; + + // insert the source entry at the position after the target + pEntries->insert( ++iter, pSourceData ); + + GetSaveInData()->SetModified(); + GetTopLevelSelection()->SetModified(); + + return true; + } + + return false; +} + +SvxMainMenuOrganizerDialog::SvxMainMenuOrganizerDialog( + weld::Window* pParent, SvxEntries* entries, + SvxConfigEntry const * selection, bool bCreateMenu ) + : GenericDialogController(pParent, "cui/ui/movemenu.ui", "MoveMenuDialog") + , m_xMenuBox(m_xBuilder->weld_widget("namebox")) + , m_xMenuNameEdit(m_xBuilder->weld_entry("menuname")) + , m_xMenuListBox(m_xBuilder->weld_tree_view("menulist")) + , m_xMoveUpButton(m_xBuilder->weld_button("up")) + , m_xMoveDownButton(m_xBuilder->weld_button("down")) +{ + m_xMenuListBox->set_size_request(-1, m_xMenuListBox->get_height_rows(12)); + + // Copy the entries list passed in + if ( entries != nullptr ) + { + mpEntries.reset( new SvxEntries ); + for (auto const& entry : *entries) + { + m_xMenuListBox->append(OUString::number(reinterpret_cast(entry)), + SvxConfigPageHelper::stripHotKey(entry->GetName())); + mpEntries->push_back(entry); + if (entry == selection) + { + m_xMenuListBox->select(m_xMenuListBox->n_children() - 1); + } + } + } + + if ( bCreateMenu ) + { + // Generate custom name for new menu + OUString prefix = CuiResId( RID_SVXSTR_NEW_MENU ); + + OUString newname = SvxConfigPageHelper::generateCustomName( prefix, entries ); + OUString newurl = SvxConfigPageHelper::generateCustomMenuURL( mpEntries.get() ); + + SvxConfigEntry* pNewEntryData = + new SvxConfigEntry( newname, newurl, true, /*bParentData*/false ); + pNewEntryData->SetName( newname ); + pNewEntryData->SetUserDefined(); + pNewEntryData->SetMain(); + + m_sNewMenuEntryId = OUString::number(reinterpret_cast(pNewEntryData)); + m_xMenuListBox->append(m_sNewMenuEntryId, + SvxConfigPageHelper::stripHotKey(pNewEntryData->GetName())); + m_xMenuListBox->select(m_xMenuListBox->n_children() - 1); + + if (mpEntries) + mpEntries->push_back(pNewEntryData); + + m_xMenuNameEdit->set_text(newname); + m_xMenuNameEdit->connect_changed(LINK(this, SvxMainMenuOrganizerDialog, ModifyHdl)); + } + else + { + // hide name label and textfield + m_xMenuBox->hide(); + // change the title + m_xDialog->set_title(CuiResId(RID_SVXSTR_MOVE_MENU)); + } + + m_xMenuListBox->connect_changed(LINK(this, SvxMainMenuOrganizerDialog, SelectHdl)); + + m_xMoveUpButton->connect_clicked(LINK( this, SvxMainMenuOrganizerDialog, MoveHdl)); + m_xMoveDownButton->connect_clicked(LINK( this, SvxMainMenuOrganizerDialog, MoveHdl)); + + UpdateButtonStates(); +} + +SvxMainMenuOrganizerDialog::~SvxMainMenuOrganizerDialog() +{ +} + +IMPL_LINK_NOARG(SvxMainMenuOrganizerDialog, ModifyHdl, weld::Entry&, void) +{ + // if the Edit control is empty do not change the name + if (m_xMenuNameEdit->get_text().isEmpty()) + { + return; + } + + SvxConfigEntry* pNewEntryData = reinterpret_cast(m_sNewMenuEntryId.toUInt64()); + pNewEntryData->SetName(m_xMenuNameEdit->get_text()); + + const int nNewMenuPos = m_xMenuListBox->find_id(m_sNewMenuEntryId); + const int nOldSelection = m_xMenuListBox->get_selected_index(); + m_xMenuListBox->remove(nNewMenuPos); + m_xMenuListBox->insert(nNewMenuPos, pNewEntryData->GetName(), &m_sNewMenuEntryId, nullptr, nullptr); + m_xMenuListBox->select(nOldSelection); +} + +IMPL_LINK_NOARG(SvxMainMenuOrganizerDialog, SelectHdl, weld::TreeView&, void) +{ + UpdateButtonStates(); +} + +void SvxMainMenuOrganizerDialog::UpdateButtonStates() +{ + // Disable Up and Down buttons depending on current selection + const int nSelected = m_xMenuListBox->get_selected_index(); + m_xMoveUpButton->set_sensitive(nSelected > 0); + m_xMoveDownButton->set_sensitive(nSelected != -1 && nSelected < m_xMenuListBox->n_children() - 1); +} + +IMPL_LINK( SvxMainMenuOrganizerDialog, MoveHdl, weld::Button&, rButton, void ) +{ + int nSourceEntry = m_xMenuListBox->get_selected_index(); + if (nSourceEntry == -1) + return; + + int nTargetEntry; + + if (&rButton == m_xMoveDownButton.get()) + { + nTargetEntry = nSourceEntry + 1; + } + else + { + // Move Up is just a Move Down with the source and target reversed + nTargetEntry = nSourceEntry - 1; + } + + OUString sId = m_xMenuListBox->get_id(nSourceEntry); + OUString sEntry = m_xMenuListBox->get_text(nSourceEntry); + m_xMenuListBox->remove(nSourceEntry); + m_xMenuListBox->insert(nTargetEntry, sEntry, &sId, nullptr, nullptr); + m_xMenuListBox->select(nTargetEntry); + + std::swap(mpEntries->at(nSourceEntry), mpEntries->at(nTargetEntry)); + + UpdateButtonStates(); +} + +SvxConfigEntry* SvxMainMenuOrganizerDialog::GetSelectedEntry() +{ + const int nSelected(m_xMenuListBox->get_selected_index()); + if (nSelected == -1) + return nullptr; + return reinterpret_cast(m_xMenuListBox->get_id(nSelected).toUInt64()); +} + +SvxConfigEntry::SvxConfigEntry( const OUString& rDisplayName, + const OUString& rCommandURL, bool bPopup, bool bParentData ) + : nId( 1 ) + , aLabel(rDisplayName) + , aCommand(rCommandURL) + , bPopUp(bPopup) + , bStrEdited( false ) + , bIsUserDefined( false ) + , bIsMain( false ) + , bIsParentData( bParentData ) + , bIsModified( false ) + , bIsVisible( true ) + , nStyle( 0 ) +{ + if (bPopUp) + { + mpEntries.reset( new SvxEntries ); + } +} + +SvxConfigEntry::~SvxConfigEntry() +{ + if (mpEntries) + { + for (auto const& entry : *mpEntries) + { + delete entry; + } + } +} + +bool SvxConfigEntry::IsMovable() const +{ + return !IsPopup() || IsMain(); +} + +bool SvxConfigEntry::IsDeletable() const +{ + return !IsMain() || IsUserDefined(); +} + +bool SvxConfigEntry::IsRenamable() const +{ + return !IsMain() || IsUserDefined(); +} + +ToolbarSaveInData::ToolbarSaveInData( + const uno::Reference < css::ui::XUIConfigurationManager >& xCfgMgr, + const uno::Reference < css::ui::XUIConfigurationManager >& xParentCfgMgr, + const OUString& aModuleId, + bool docConfig ) : + + SaveInData ( xCfgMgr, xParentCfgMgr, aModuleId, docConfig ), + m_aDescriptorContainer ( ITEM_DESCRIPTOR_CONTAINER ) + +{ + uno::Reference xContext = ::comphelper::getProcessComponentContext(); + // Initialize the m_xPersistentWindowState variable which is used + // to get the default properties of system toolbars such as name + uno::Reference< container::XNameAccess > xPWSS = css::ui::theWindowStateConfiguration::get( xContext ); + + xPWSS->getByName( aModuleId ) >>= m_xPersistentWindowState; +} + +ToolbarSaveInData::~ToolbarSaveInData() +{ +} + +sal_Int32 ToolbarSaveInData::GetSystemStyle( const OUString& rResourceURL ) +{ + sal_Int32 result = 0; + + if ( rResourceURL.startsWith( "private" ) && + m_xPersistentWindowState.is() && + m_xPersistentWindowState->hasByName( rResourceURL ) ) + { + try + { + uno::Sequence< beans::PropertyValue > aProps; + uno::Any a( m_xPersistentWindowState->getByName( rResourceURL ) ); + + if ( a >>= aProps ) + { + for ( beans::PropertyValue const & prop : std::as_const(aProps) ) + { + if ( prop.Name == ITEM_DESCRIPTOR_STYLE ) + { + prop.Value >>= result; + break; + } + } + } + } + catch ( uno::Exception& ) + { + // do nothing, a default value is returned + } + } + + return result; +} + +void ToolbarSaveInData::SetSystemStyle( + const uno::Reference< frame::XFrame >& xFrame, + const OUString& rResourceURL, + sal_Int32 nStyle ) +{ + // change the style using the API + SetSystemStyle( rResourceURL, nStyle ); + + // this code is a temporary hack as the UI is not updating after + // changing the toolbar style via the API + uno::Reference< css::frame::XLayoutManager > xLayoutManager; + vcl::Window *window = nullptr; + + uno::Reference< beans::XPropertySet > xPropSet( xFrame, uno::UNO_QUERY ); + if ( xPropSet.is() ) + { + uno::Any a = xPropSet->getPropertyValue( "LayoutManager" ); + a >>= xLayoutManager; + } + + if ( xLayoutManager.is() ) + { + uno::Reference< css::ui::XUIElement > xUIElement = + xLayoutManager->getElement( rResourceURL ); + + // check reference before we call getRealInterface. The layout manager + // can only provide references for elements that have been created + // before. It's possible that the current element is not available. + uno::Reference< css::awt::XWindow > xWindow; + if ( xUIElement.is() ) + xWindow.set( xUIElement->getRealInterface(), uno::UNO_QUERY ); + + window = VCLUnoHelper::GetWindow( xWindow ).get(); + } + + if ( !(window != nullptr && window->GetType() == WindowType::TOOLBOX) ) + return; + + ToolBox* toolbox = static_cast(window); + + if ( nStyle == 0 ) + { + toolbox->SetButtonType( ButtonType::SYMBOLONLY ); + } + else if ( nStyle == 1 ) + { + toolbox->SetButtonType( ButtonType::TEXT ); + } + if ( nStyle == 2 ) + { + toolbox->SetButtonType( ButtonType::SYMBOLTEXT ); + } +} + +void ToolbarSaveInData::SetSystemStyle( + const OUString& rResourceURL, + sal_Int32 nStyle ) +{ + if ( !(rResourceURL.startsWith( "private" ) && + m_xPersistentWindowState.is() && + m_xPersistentWindowState->hasByName( rResourceURL )) ) + return; + + try + { + uno::Sequence< beans::PropertyValue > aProps; + + uno::Any a( m_xPersistentWindowState->getByName( rResourceURL ) ); + + if ( a >>= aProps ) + { + for ( beans::PropertyValue& prop : aProps ) + { + if ( prop.Name == ITEM_DESCRIPTOR_STYLE ) + { + prop.Value <<= nStyle; + break; + } + } + } + + uno::Reference< container::XNameReplace > + xNameReplace( m_xPersistentWindowState, uno::UNO_QUERY ); + + xNameReplace->replaceByName( rResourceURL, uno::Any( aProps ) ); + } + catch ( uno::Exception& ) + { + // do nothing, a default value is returned + SAL_WARN("cui.customize", "Exception setting toolbar style"); + } +} + +OUString ToolbarSaveInData::GetSystemUIName( const OUString& rResourceURL ) +{ + OUString result; + + if ( rResourceURL.startsWith( "private" ) && + m_xPersistentWindowState.is() && + m_xPersistentWindowState->hasByName( rResourceURL ) ) + { + try + { + uno::Sequence< beans::PropertyValue > aProps; + uno::Any a( m_xPersistentWindowState->getByName( rResourceURL ) ); + + if ( a >>= aProps ) + { + for ( beans::PropertyValue const & prop : std::as_const(aProps) ) + { + if ( prop.Name == ITEM_DESCRIPTOR_UINAME ) + { + prop.Value >>= result; + } + } + } + } + catch ( uno::Exception& ) + { + // do nothing, an empty UIName will be returned + } + } + + if ( rResourceURL.startsWith( ".uno" ) && + m_xCommandToLabelMap.is() && + m_xCommandToLabelMap->hasByName( rResourceURL ) ) + { + uno::Any a; + try + { + a = m_xCommandToLabelMap->getByName( rResourceURL ); + + uno::Sequence< beans::PropertyValue > aPropSeq; + if ( a >>= aPropSeq ) + { + for ( beans::PropertyValue const & prop : std::as_const(aPropSeq) ) + { + if ( prop.Name == ITEM_DESCRIPTOR_LABEL ) + { + prop.Value >>= result; + } + } + } + } + catch ( uno::Exception& ) + { + // not a system command name + } + } + + return result; +} + +SvxEntries* ToolbarSaveInData::GetEntries() +{ + typedef std::unordered_map ToolbarInfo; + + ToolbarInfo aToolbarInfo; + + if ( pRootEntry == nullptr ) + { + + pRootEntry.reset( new SvxConfigEntry( "MainToolbars", OUString(), true, /*bParentData*/false) ); + + const uno::Sequence< uno::Sequence < beans::PropertyValue > > info = + GetConfigManager()->getUIElementsInfo( + css::ui::UIElementType::TOOLBAR ); + + for ( uno::Sequence const & props : info ) + { + OUString url; + OUString systemname; + OUString uiname; + + for ( const beans::PropertyValue& prop : props ) + { + if ( prop.Name == ITEM_DESCRIPTOR_RESOURCEURL ) + { + prop.Value >>= url; + systemname = url.copy( url.lastIndexOf( '/' ) + 1 ); + } + else if ( prop.Name == ITEM_DESCRIPTOR_UINAME ) + { + prop.Value >>= uiname; + } + } + + try + { + uno::Reference< container::XIndexAccess > xToolbarSettings = + GetConfigManager()->getSettings( url, false ); + + if ( uiname.isEmpty() ) + { + // try to get the name from m_xPersistentWindowState + uiname = GetSystemUIName( url ); + + if ( uiname.isEmpty() ) + { + uiname = systemname; + } + } + + SvxConfigEntry* pEntry = new SvxConfigEntry( + uiname, url, true, /*bParentData*/false ); + + pEntry->SetMain(); + pEntry->SetStyle( GetSystemStyle( url ) ); + + + // insert into std::unordered_map to filter duplicates from the parent + aToolbarInfo.emplace( systemname, true ); + + OUString custom(CUSTOM_TOOLBAR_STR); + if ( systemname.startsWith( custom ) ) + { + pEntry->SetUserDefined(); + } + else + { + pEntry->SetUserDefined( false ); + } + + pRootEntry->GetEntries()->push_back( pEntry ); + + LoadToolbar( xToolbarSettings, pEntry ); + } + catch ( container::NoSuchElementException& ) + { + // TODO, handle resourceURL with no settings + } + } + + uno::Reference< css::ui::XUIConfigurationManager > xParentCfgMgr = GetParentConfigManager(); + if ( xParentCfgMgr.is() ) + { + // Retrieve also the parent toolbars to make it possible + // to configure module toolbars and save them into the document + // config manager. + const uno::Sequence< uno::Sequence < beans::PropertyValue > > info_ = + xParentCfgMgr->getUIElementsInfo( + css::ui::UIElementType::TOOLBAR ); + + for ( uno::Sequence const & props : info_ ) + { + OUString url; + OUString systemname; + OUString uiname; + + for ( const beans::PropertyValue& prop : props ) + { + if ( prop.Name == ITEM_DESCRIPTOR_RESOURCEURL ) + { + prop.Value >>= url; + systemname = url.copy( url.lastIndexOf( '/' ) + 1 ); + } + else if ( prop.Name == ITEM_DESCRIPTOR_UINAME ) + { + prop.Value >>= uiname; + } + } + + // custom toolbars of the parent are not visible in the document layer + OUString custom(CUSTOM_TOOLBAR_STR); + if ( systemname.startsWith( custom ) ) + continue; + + // check if toolbar is already in the document layer + ToolbarInfo::const_iterator pIter = aToolbarInfo.find( systemname ); + if ( pIter == aToolbarInfo.end() ) + { + aToolbarInfo.emplace( systemname, true ); + + try + { + uno::Reference< container::XIndexAccess > xToolbarSettings = + xParentCfgMgr->getSettings( url, false ); + + if ( uiname.isEmpty() ) + { + // try to get the name from m_xPersistentWindowState + uiname = GetSystemUIName( url ); + + if ( uiname.isEmpty() ) + { + uiname = systemname; + } + } + + SvxConfigEntry* pEntry = new SvxConfigEntry( + uiname, url, true, true ); + + pEntry->SetMain(); + pEntry->SetStyle( GetSystemStyle( url ) ); + + if ( systemname.startsWith( custom ) ) + { + pEntry->SetUserDefined(); + } + else + { + pEntry->SetUserDefined( false ); + } + + pRootEntry->GetEntries()->push_back( pEntry ); + + LoadToolbar( xToolbarSettings, pEntry ); + } + catch ( container::NoSuchElementException& ) + { + // TODO, handle resourceURL with no settings + } + } + } + } + + std::sort( GetEntries()->begin(), GetEntries()->end(), SvxConfigPageHelper::EntrySort ); + } + + return pRootEntry->GetEntries(); +} + +void +ToolbarSaveInData::SetEntries( std::unique_ptr pNewEntries ) +{ + pRootEntry->SetEntries( std::move(pNewEntries) ); +} + +bool +ToolbarSaveInData::HasURL( const OUString& rURL ) +{ + for (auto const& entry : *GetEntries()) + { + if (entry->GetCommand() == rURL) + { + return !entry->IsParentData(); + } + } + return false; +} + +bool ToolbarSaveInData::HasSettings() +{ + // return true if there is at least one toolbar entry + return !GetEntries()->empty(); +} + +void ToolbarSaveInData::Reset() +{ + // reset each toolbar by calling removeSettings for its toolbar URL + for (auto const& entry : *GetEntries()) + { + try + { + const OUString& url = entry->GetCommand(); + GetConfigManager()->removeSettings( url ); + } + catch ( uno::Exception& ) + { + // error occurred removing the settings + // TODO - add error dialog in future? + } + } + + // persist changes to toolbar storage + PersistChanges( GetConfigManager() ); + + // now delete the root SvxConfigEntry the next call to GetEntries() + // causes it to be reinitialised + pRootEntry.reset(); + + // reset all icons to default + try + { + GetImageManager()->reset(); + PersistChanges( GetImageManager() ); + } + catch ( uno::Exception& ) + { + SAL_WARN("cui.customize", "Error resetting all icons when resetting toolbars"); + } +} + +bool ToolbarSaveInData::Apply() +{ + // toolbar changes are instantly applied + return false; +} + +void ToolbarSaveInData::ApplyToolbar( + uno::Reference< container::XIndexContainer > const & rToolbarBar, + uno::Reference< lang::XSingleComponentFactory >& rFactory, + SvxConfigEntry const * pToolbarData ) +{ + uno::Reference xContext = ::comphelper::getProcessComponentContext(); + + for (auto const& entry : *pToolbarData->GetEntries()) + { + if (entry->IsPopup()) + { + uno::Sequence< beans::PropertyValue > aPropValueSeq = + SvxConfigPageHelper::ConvertToolbarEntry(entry); + + uno::Reference< container::XIndexContainer > xSubMenuBar( + rFactory->createInstanceWithContext( xContext ), + uno::UNO_QUERY ); + + sal_Int32 nIndex = aPropValueSeq.getLength(); + aPropValueSeq.realloc( nIndex + 1 ); + aPropValueSeq[nIndex].Name = m_aDescriptorContainer; + aPropValueSeq[nIndex].Value <<= xSubMenuBar; + rToolbarBar->insertByIndex( + rToolbarBar->getCount(), uno::Any( aPropValueSeq )); + + ApplyToolbar(xSubMenuBar, rFactory, entry); + } + else if (entry->IsSeparator()) + { + rToolbarBar->insertByIndex( + rToolbarBar->getCount(), uno::Any( m_aSeparatorSeq )); + } + else + { + uno::Sequence< beans::PropertyValue > aPropValueSeq = + SvxConfigPageHelper::ConvertToolbarEntry(entry); + + rToolbarBar->insertByIndex( + rToolbarBar->getCount(), uno::Any( aPropValueSeq )); + } + } +} + +void ToolbarSaveInData::ApplyToolbar( SvxConfigEntry* pToolbar ) +{ + // Apply new toolbar structure to our settings container + uno::Reference< container::XIndexAccess > xSettings = + GetConfigManager()->createSettings(); + + uno::Reference< container::XIndexContainer > xIndexContainer ( + xSettings, uno::UNO_QUERY ); + + uno::Reference< lang::XSingleComponentFactory > xFactory ( + xSettings, uno::UNO_QUERY ); + + ApplyToolbar( xIndexContainer, xFactory, pToolbar ); + + uno::Reference< beans::XPropertySet > xProps( + xSettings, uno::UNO_QUERY ); + + if ( pToolbar->IsUserDefined() ) + { + xProps->setPropertyValue( + ITEM_DESCRIPTOR_UINAME, + uno::Any( pToolbar->GetName() ) ); + } + + try + { + if ( GetConfigManager()->hasSettings( pToolbar->GetCommand() ) ) + { + GetConfigManager()->replaceSettings( + pToolbar->GetCommand(), xSettings ); + } + else + { + GetConfigManager()->insertSettings( + pToolbar->GetCommand(), xSettings ); + if ( pToolbar->IsParentData() ) + pToolbar->SetParentData( false ); + } + } + catch ( css::uno::Exception const & ) + { + TOOLS_WARN_EXCEPTION("cui.customize", "caught exception saving settings"); + } + + PersistChanges( GetConfigManager() ); +} + +void ToolbarSaveInData::CreateToolbar( SvxConfigEntry* pToolbar ) +{ + // show the new toolbar in the UI also + uno::Reference< container::XIndexAccess > + xSettings = GetConfigManager()->createSettings(); + + uno::Reference< beans::XPropertySet > + xPropertySet( xSettings, uno::UNO_QUERY ); + + xPropertySet->setPropertyValue( + ITEM_DESCRIPTOR_UINAME, + uno::Any( pToolbar->GetName() ) ); + + try + { + GetConfigManager()->insertSettings( pToolbar->GetCommand(), xSettings ); + } + catch ( css::uno::Exception const & ) + { + TOOLS_WARN_EXCEPTION("cui.customize", "caught exception saving settings"); + } + + GetEntries()->push_back( pToolbar ); + + PersistChanges( GetConfigManager() ); +} + +void ToolbarSaveInData::RemoveToolbar( SvxConfigEntry* pToolbar ) +{ + try + { + OUString url = pToolbar->GetCommand(); + GetConfigManager()->removeSettings( url ); + SvxConfigPageHelper::RemoveEntry( GetEntries(), pToolbar ); + delete pToolbar; + + PersistChanges( GetConfigManager() ); + + // remove the persistent window state data + css::uno::Reference< css::container::XNameContainer > xNameContainer( + m_xPersistentWindowState, css::uno::UNO_QUERY_THROW ); + + xNameContainer->removeByName( url ); + } + catch ( uno::Exception& ) + { + // error occurred removing the settings + } +} + +void ToolbarSaveInData::RestoreToolbar( SvxConfigEntry* pToolbar ) +{ + OUString url = pToolbar->GetCommand(); + + // Restore of toolbar is done by removing it from + // its configuration manager and then getting it again + bool bParentToolbar = pToolbar->IsParentData(); + + // Cannot restore parent toolbar + if ( bParentToolbar ) + return; + + try + { + GetConfigManager()->removeSettings( url ); + pToolbar->GetEntries()->clear(); + PersistChanges( GetConfigManager() ); + } + catch ( uno::Exception& ) + { + // if an error occurs removing the settings then just return + return; + } + + // Now reload the toolbar settings + try + { + uno::Reference< container::XIndexAccess > xToolbarSettings; + if ( IsDocConfig() ) + { + xToolbarSettings = GetParentConfigManager()->getSettings( url, false ); + pToolbar->SetParentData(); + } + else + xToolbarSettings = GetConfigManager()->getSettings( url, false ); + + LoadToolbar( xToolbarSettings, pToolbar ); + + // After reloading, ensure that the icon is reset of each entry + // in the toolbar + uno::Sequence< OUString > aURLSeq( 1 ); + for (auto const& entry : *pToolbar->GetEntries()) + { + aURLSeq[ 0 ] = entry->GetCommand(); + + try + { + GetImageManager()->removeImages( SvxConfigPageHelper::GetImageType(), aURLSeq ); + } + catch ( uno::Exception& ) + { + SAL_WARN("cui.customize", "Error restoring icon when resetting toolbar"); + } + } + PersistChanges( GetImageManager() ); + } + catch ( container::NoSuchElementException& ) + { + // cannot find the resource URL after removing it + // so no entry will appear in the toolbar list + } +} + +void ToolbarSaveInData::LoadToolbar( + const uno::Reference< container::XIndexAccess >& xToolbarSettings, + SvxConfigEntry const * pParentData ) +{ + SvxEntries* pEntries = pParentData->GetEntries(); + + for ( sal_Int32 nIndex = 0; nIndex < xToolbarSettings->getCount(); ++nIndex ) + { + OUString aCommandURL; + OUString aLabel; + bool bIsVisible; + sal_Int32 nStyle; + + sal_uInt16 nType( css::ui::ItemType::DEFAULT ); + + bool bItem = SvxConfigPageHelper::GetToolbarItemData( xToolbarSettings, nIndex, aCommandURL, + aLabel, nType, bIsVisible, nStyle ); + + if ( bItem ) + { + bool bIsUserDefined = true; + + if ( nType == css::ui::ItemType::DEFAULT ) + { + uno::Any a; + try + { + a = m_xCommandToLabelMap->getByName( aCommandURL ); + bIsUserDefined = false; + } + catch ( container::NoSuchElementException& ) + { + bIsUserDefined = true; + } + + bool bUseDefaultLabel = false; + // If custom label not set retrieve it from the command + // to info service + if ( aLabel.isEmpty() ) + { + bUseDefaultLabel = true; + uno::Sequence< beans::PropertyValue > aPropSeq; + if ( a >>= aPropSeq ) + { + for ( beans::PropertyValue const & prop : std::as_const(aPropSeq) ) + { + if ( prop.Name == "Name" ) + { + prop.Value >>= aLabel; + break; + } + } + } + } + + SvxConfigEntry* pEntry = new SvxConfigEntry( + aLabel, aCommandURL, false, /*bParentData*/false ); + + pEntry->SetUserDefined( bIsUserDefined ); + pEntry->SetVisible( bIsVisible ); + pEntry->SetStyle( nStyle ); + + if ( !bUseDefaultLabel ) + pEntry->SetName( aLabel ); + + pEntries->push_back( pEntry ); + } + else + { + SvxConfigEntry* pEntry = new SvxConfigEntry; + pEntry->SetUserDefined( bIsUserDefined ); + pEntries->push_back( pEntry ); + } + } + } +} + +SvxNewToolbarDialog::SvxNewToolbarDialog(weld::Window* pWindow, const OUString& rName) + : GenericDialogController(pWindow, "cui/ui/newtoolbardialog.ui", "NewToolbarDialog") + , m_xEdtName(m_xBuilder->weld_entry("edit")) + , m_xBtnOK(m_xBuilder->weld_button("ok")) + , m_xSaveInListBox(m_xBuilder->weld_combo_box("savein")) +{ + m_xEdtName->set_text(rName); + m_xEdtName->select_region(0, -1); +} + +SvxNewToolbarDialog::~SvxNewToolbarDialog() +{ +} + +/******************************************************************************* +* +* The SvxIconSelectorDialog class +* +*******************************************************************************/ +SvxIconSelectorDialog::SvxIconSelectorDialog(weld::Window *pWindow, + const uno::Reference< css::ui::XImageManager >& rXImageManager, + const uno::Reference< css::ui::XImageManager >& rXParentImageManager) + : GenericDialogController(pWindow, "cui/ui/iconselectordialog.ui", "IconSelector") + , m_xImageManager(rXImageManager) + , m_xParentImageManager(rXParentImageManager) + , m_xTbSymbol(new ValueSet(m_xBuilder->weld_scrolled_window("symbolswin"))) + , m_xTbSymbolWin(new weld::CustomWeld(*m_xBuilder, "symbolsToolbar", *m_xTbSymbol)) + , m_xFtNote(m_xBuilder->weld_label("noteLabel")) + , m_xBtnImport(m_xBuilder->weld_button("importButton")) + , m_xBtnDelete(m_xBuilder->weld_button("deleteButton")) +{ + typedef std::unordered_map< OUString, bool > ImageInfo; + + m_nExpectedSize = 16; + if (SvxConfigPageHelper::GetImageType() & css::ui::ImageType::SIZE_LARGE) + m_nExpectedSize = 24; + else if (SvxConfigPageHelper::GetImageType() & css::ui::ImageType::SIZE_32) + m_nExpectedSize = 32; + + if ( m_nExpectedSize != 16 ) + { + m_xFtNote->set_label(SvxConfigPageHelper::replaceSixteen(m_xFtNote->get_label(), m_nExpectedSize)); + } + + m_xTbSymbol->SetStyle(m_xTbSymbol->GetStyle() | WB_ITEMBORDER | WB_VSCROLL); + m_xTbSymbol->SetColCount(11); + m_xTbSymbol->SetLineCount(5); + m_xTbSymbol->SetItemWidth(m_nExpectedSize); + m_xTbSymbol->SetItemHeight(m_nExpectedSize); + m_xTbSymbol->SetExtraSpacing(6); + Size aSize(m_xTbSymbol->CalcWindowSizePixel(Size(m_nExpectedSize, m_nExpectedSize), 11, 5)); + m_xTbSymbol->set_size_request(aSize.Width(), aSize.Height()); + + uno::Reference< uno::XComponentContext > xComponentContext = + ::comphelper::getProcessComponentContext(); + + m_xGraphProvider.set( graphic::GraphicProvider::create( xComponentContext ) ); + + uno::Reference< css::util::XPathSettings > xPathSettings = + css::util::thePathSettings::get( xComponentContext ); + + + OUString aDirectory = xPathSettings->getUserConfig(); + + sal_Int32 aCount = aDirectory.getLength(); + + if ( aCount > 0 ) + { + sal_Unicode aChar = aDirectory[ aCount-1 ]; + if ( aChar != '/') + { + aDirectory += "/"; + } + } + else + { + m_xBtnImport->set_sensitive(false); + } + + aDirectory += "soffice.cfg/import"; + + uno::Reference< lang::XSingleServiceFactory > xStorageFactory( + css::embed::FileSystemStorageFactory::create( xComponentContext ) ); + + uno::Sequence< uno::Any > aArgs( 2 ); + aArgs[ 0 ] <<= aDirectory; + aArgs[ 1 ] <<= css::embed::ElementModes::READWRITE; + + uno::Reference< css::embed::XStorage > xStorage( + xStorageFactory->createInstanceWithArguments( aArgs ), uno::UNO_QUERY ); + + uno::Sequence aProp(comphelper::InitAnyPropertySequence( + { + {"UserConfigStorage", uno::Any(xStorage)}, + {"OpenMode", uno::Any(css::embed::ElementModes::READWRITE)} + })); + m_xImportedImageManager = css::ui::ImageManager::create( xComponentContext ); + m_xImportedImageManager->initialize(aProp); + + ImageInfo aImageInfo1; + if ( m_xImportedImageManager.is() ) + { + const uno::Sequence< OUString > names = m_xImportedImageManager->getAllImageNames( SvxConfigPageHelper::GetImageType() ); + for (auto const & name : names ) + aImageInfo1.emplace( name, false ); + } + + uno::Sequence< OUString > name( 1 ); + for (auto const& elem : aImageInfo1) + { + name[ 0 ] = elem.first; + uno::Sequence< uno::Reference< graphic::XGraphic> > graphics = m_xImportedImageManager->getImages( SvxConfigPageHelper::GetImageType(), name ); + if ( graphics.hasElements() ) + { + m_aGraphics.push_back(graphics[0]); + Image img(graphics[0]); + m_xTbSymbol->InsertItem(m_aGraphics.size(), img, elem.first); + } + } + + ImageInfo aImageInfo; + + if ( m_xParentImageManager.is() ) + { + const uno::Sequence< OUString > names = m_xParentImageManager->getAllImageNames( SvxConfigPageHelper::GetImageType() ); + for ( auto const & i : names ) + aImageInfo.emplace( i, false ); + } + + const uno::Sequence< OUString > names = m_xImageManager->getAllImageNames( SvxConfigPageHelper::GetImageType() ); + for ( auto const & i : names ) + { + ImageInfo::iterator pIter = aImageInfo.find( i ); + if ( pIter != aImageInfo.end() ) + pIter->second = true; + else + aImageInfo.emplace( i, true ); + } + + // large growth factor, expecting many entries + for (auto const& elem : aImageInfo) + { + name[ 0 ] = elem.first; + + uno::Sequence< uno::Reference< graphic::XGraphic> > graphics; + try + { + if (elem.second) + graphics = m_xImageManager->getImages( SvxConfigPageHelper::GetImageType(), name ); + else + graphics = m_xParentImageManager->getImages( SvxConfigPageHelper::GetImageType(), name ); + } + catch ( uno::Exception& ) + { + // can't get sequence for this name so it will not be + // added to the list + } + + if ( graphics.hasElements() ) + { + Image img(graphics[0]); + if (!img.GetBitmapEx().IsEmpty()) + { + m_aGraphics.push_back(graphics[0]); + m_xTbSymbol->InsertItem(m_aGraphics.size(), img, elem.first); + } + } + } + + m_xBtnDelete->set_sensitive( false ); + m_xTbSymbol->SetSelectHdl( LINK(this, SvxIconSelectorDialog, SelectHdl) ); + m_xBtnImport->connect_clicked( LINK(this, SvxIconSelectorDialog, ImportHdl) ); + m_xBtnDelete->connect_clicked( LINK(this, SvxIconSelectorDialog, DeleteHdl) ); +} + +SvxIconSelectorDialog::~SvxIconSelectorDialog() +{ +} + +uno::Reference< graphic::XGraphic> SvxIconSelectorDialog::GetSelectedIcon() +{ + uno::Reference result; + + sal_uInt16 nId = m_xTbSymbol->GetSelectedItemId(); + + if (nId) + { + result = m_aGraphics[nId - 1]; + } + + return result; +} + +IMPL_LINK_NOARG(SvxIconSelectorDialog, SelectHdl, ValueSet*, void) +{ + sal_uInt16 nId = m_xTbSymbol->GetSelectedItemId(); + + if (!nId) + { + m_xBtnDelete->set_sensitive(false); + return; + } + + OUString aSelImageText = m_xTbSymbol->GetItemText(nId); + if (m_xImportedImageManager->hasImage(SvxConfigPageHelper::GetImageType(), aSelImageText)) + { + m_xBtnDelete->set_sensitive(true); + } + else + { + m_xBtnDelete->set_sensitive(false); + } +} + +IMPL_LINK_NOARG(SvxIconSelectorDialog, ImportHdl, weld::Button&, void) +{ + sfx2::FileDialogHelper aImportDialog( + css::ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW, + FileDialogFlags::Graphic | FileDialogFlags::MultiSelection, m_xDialog.get()); + + // disable the link checkbox in the dialog + uno::Reference< css::ui::dialogs::XFilePickerControlAccess > + xController( aImportDialog.GetFilePicker(), uno::UNO_QUERY); + if ( xController.is() ) + { + xController->enableControl( + css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK, + false); + } + + aImportDialog.SetCurrentFilter( + "PNG - Portable Network Graphic"); + + if ( ERRCODE_NONE == aImportDialog.Execute() ) + { + uno::Sequence< OUString > paths = aImportDialog.GetMPath(); + ImportGraphics ( paths ); + } +} + +IMPL_LINK_NOARG(SvxIconSelectorDialog, DeleteHdl, weld::Button&, void) +{ + OUString message = CuiResId( RID_SVXSTR_DELETE_ICON_CONFIRM ); + + std::unique_ptr xWarn(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Warning, VclButtonsType::OkCancel, + message)); + if (xWarn->run() != RET_OK) + return; + + sal_uInt16 nId = m_xTbSymbol->GetSelectedItemId(); + + OUString aSelImageText = m_xTbSymbol->GetItemText( nId ); + uno::Sequence< OUString > URLs { aSelImageText }; + m_xTbSymbol->RemoveItem(nId); + m_xImportedImageManager->removeImages( SvxConfigPageHelper::GetImageType(), URLs ); + if ( m_xImportedImageManager->isModified() ) + { + m_xImportedImageManager->store(); + } +} + +bool SvxIconSelectorDialog::ReplaceGraphicItem( + const OUString& aURL ) +{ + uno::Sequence< OUString > URLs(1); + uno::Sequence< uno::Reference > aImportGraph( 1 ); + + uno::Reference< graphic::XGraphic > xGraphic; + uno::Sequence< beans::PropertyValue > aMediaProps( 1 ); + aMediaProps[0].Name = "URL"; + aMediaProps[0].Value <<= aURL; + + css::awt::Size aSize; + bool bOK = false; + try + { + xGraphic = m_xGraphProvider->queryGraphic( aMediaProps ); + + uno::Reference< beans::XPropertySet > props = + m_xGraphProvider->queryGraphicDescriptor( aMediaProps ); + uno::Any a = props->getPropertyValue( "SizePixel" ); + a >>= aSize; + if (0 == aSize.Width || 0 == aSize.Height) + return false; + else + bOK = true; + } + catch ( uno::Exception& ) + { + return false; + } + + bool bResult( false ); + size_t nCount = m_xTbSymbol->GetItemCount(); + for (size_t n = 0; n < nCount; ++n) + { + sal_uInt16 nId = m_xTbSymbol->GetItemId( n ); + + if ( m_xTbSymbol->GetItemText( nId ) == aURL ) + { + try + { + // replace/insert image with provided URL + size_t nPos = nId - 1; + assert(nPos == m_xTbSymbol->GetItemPos(nId)); + m_xTbSymbol->RemoveItem(nId); + aMediaProps[0].Value <<= aURL; + + Image aImage( xGraphic ); + if ( bOK && ((aSize.Width != m_nExpectedSize) || (aSize.Height != m_nExpectedSize)) ) + { + BitmapEx aBitmap = aImage.GetBitmapEx(); + BitmapEx aBitmapex = BitmapEx::AutoScaleBitmap(aBitmap, m_nExpectedSize); + aImage = Image( aBitmapex); + } + m_xTbSymbol->InsertItem(nId, aImage, aURL, nPos); //modify + + m_aGraphics[nPos] = Graphic(aImage.GetBitmapEx()).GetXGraphic(); + + URLs[0] = aURL; + aImportGraph[ 0 ] = xGraphic; + m_xImportedImageManager->replaceImages( SvxConfigPageHelper::GetImageType(), URLs, aImportGraph ); + m_xImportedImageManager->store(); + + bResult = true; + break; + } + catch ( css::uno::Exception& ) + { + break; + } + } + } + + return bResult; +} + +namespace +{ + OUString ReplaceIconName(const OUString& rMessage) + { + OUString name; + OUString message = CuiResId( RID_SVXSTR_REPLACE_ICON_WARNING ); + OUString placeholder("%ICONNAME" ); + sal_Int32 pos = message.indexOf( placeholder ); + if ( pos != -1 ) + { + name = message.replaceAt( + pos, placeholder.getLength(), rMessage ); + } + return name; + } + + class SvxIconReplacementDialog + { + private: + std::unique_ptr m_xQueryBox; + public: + SvxIconReplacementDialog(weld::Window *pParent, const OUString& rMessage, bool bYestoAll) + : m_xQueryBox(Application::CreateMessageDialog(pParent, VclMessageType::Warning, VclButtonsType::NONE, ReplaceIconName(rMessage))) + { + m_xQueryBox->set_title(CuiResId(RID_SVXSTR_REPLACE_ICON_CONFIRM)); + m_xQueryBox->add_button(GetStandardText(StandardButtonType::Yes), 2); + if (bYestoAll) + m_xQueryBox->add_button(CuiResId(RID_SVXSTR_YESTOALL), 5); + m_xQueryBox->add_button(GetStandardText(StandardButtonType::No), 4); + m_xQueryBox->add_button(GetStandardText(StandardButtonType::Cancel), 6); + m_xQueryBox->set_default_response(2); + } + short run() { return m_xQueryBox->run(); } + }; +} + +void SvxIconSelectorDialog::ImportGraphics( + const uno::Sequence< OUString >& rPaths ) +{ + uno::Sequence< OUString > rejected( rPaths.getLength() ); + sal_Int32 rejectedCount = 0; + + sal_uInt16 ret = 0; + sal_Int32 aIndex; + OUString aIconName; + + if ( rPaths.getLength() == 1 ) + { + if ( m_xImportedImageManager->hasImage( SvxConfigPageHelper::GetImageType(), rPaths[0] ) ) + { + aIndex = rPaths[0].lastIndexOf( '/' ); + aIconName = rPaths[0].copy( aIndex+1 ); + SvxIconReplacementDialog aDlg(m_xDialog.get(), aIconName, false); + ret = aDlg.run(); + if ( ret == 2 ) + { + ReplaceGraphicItem( rPaths[0] ); + } + } + else + { + if ( !ImportGraphic( rPaths[0] ) ) + { + rejected[0] = rPaths[0]; + rejectedCount = 1; + } + } + } + else + { + OUString aSourcePath( rPaths[0] ); + if ( rPaths[0].lastIndexOf( '/' ) != rPaths[0].getLength() -1 ) + aSourcePath = rPaths[0] + "/"; + + for ( sal_Int32 i = 1; i < rPaths.getLength(); ++i ) + { + OUString aPath = aSourcePath + rPaths[i]; + if ( m_xImportedImageManager->hasImage( SvxConfigPageHelper::GetImageType(), aPath ) ) + { + aIndex = rPaths[i].lastIndexOf( '/' ); + aIconName = rPaths[i].copy( aIndex+1 ); + SvxIconReplacementDialog aDlg(m_xDialog.get(), aIconName, true); + ret = aDlg.run(); + if ( ret == 2 ) + { + ReplaceGraphicItem( aPath ); + } + else if ( ret == 5 ) + { + for ( sal_Int32 k = i; k < rPaths.getLength(); ++k ) + { + aPath = aSourcePath + rPaths[k]; + bool bHasReplaced = ReplaceGraphicItem( aPath ); + + if ( !bHasReplaced ) + { + bool result = ImportGraphic( aPath ); + if ( !result ) + { + rejected[ rejectedCount ] = rPaths[i]; + ++rejectedCount; + } + } + } + break; + } + } + else + { + bool result = ImportGraphic( aSourcePath + rPaths[i] ); + if ( !result ) + { + rejected[ rejectedCount ] = rPaths[i]; + ++rejectedCount; + } + } + } + } + + if ( rejectedCount == 0 ) + return; + + OUStringBuffer message; + OUString fPath; + if (rejectedCount > 1) + fPath = rPaths[0].copy(8) + "/"; + for ( sal_Int32 i = 0; i < rejectedCount; ++i ) + { + message.append(fPath).append(rejected[i]).append("\n"); + } + + SvxIconChangeDialog aDialog(m_xDialog.get(), message.makeStringAndClear()); + aDialog.run(); +} + +bool SvxIconSelectorDialog::ImportGraphic( const OUString& aURL ) +{ + bool result = false; + + uno::Sequence< beans::PropertyValue > aMediaProps( 1 ); + aMediaProps[0].Name = "URL"; + + uno::Reference< graphic::XGraphic > xGraphic; + css::awt::Size aSize; + aMediaProps[0].Value <<= aURL; + try + { + uno::Reference< beans::XPropertySet > props = + m_xGraphProvider->queryGraphicDescriptor( aMediaProps ); + + uno::Any a = props->getPropertyValue("SizePixel"); + + xGraphic = m_xGraphProvider->queryGraphic( aMediaProps ); + if ( xGraphic.is() ) + { + bool bOK = true; + + a >>= aSize; + if ( 0 == aSize.Width || 0 == aSize.Height ) + bOK = false; + + Image aImage( xGraphic ); + + if ( bOK && ((aSize.Width != m_nExpectedSize) || (aSize.Height != m_nExpectedSize)) ) + { + BitmapEx aBitmap = aImage.GetBitmapEx(); + BitmapEx aBitmapex = BitmapEx::AutoScaleBitmap(aBitmap, m_nExpectedSize); + aImage = Image( aBitmapex); + } + if ( bOK && !!aImage ) + { + m_aGraphics.push_back(Graphic(aImage.GetBitmapEx()).GetXGraphic()); + m_xTbSymbol->InsertItem(m_aGraphics.size(), aImage, aURL); + + uno::Sequence aImportURL { aURL }; + uno::Sequence< uno::Reference > aImportGraph( 1 ); + aImportGraph[ 0 ] = xGraphic; + m_xImportedImageManager->insertImages( SvxConfigPageHelper::GetImageType(), aImportURL, aImportGraph ); + if ( m_xImportedImageManager->isModified() ) + { + m_xImportedImageManager->store(); + } + + result = true; + } + else + { + SAL_WARN("cui.customize", "could not create Image from XGraphic"); + } + } + else + { + SAL_WARN("cui.customize", "could not get query XGraphic"); + } + } + catch( uno::Exception const & ) + { + TOOLS_WARN_EXCEPTION("cui.customize", "Caught exception importing XGraphic"); + } + return result; +} + +/******************************************************************************* +* +* The SvxIconChangeDialog class added for issue83555 +* +*******************************************************************************/ +SvxIconChangeDialog::SvxIconChangeDialog(weld::Window *pWindow, const OUString& rMessage) + : MessageDialogController(pWindow, "cui/ui/iconchangedialog.ui", "IconChange", "grid") + , m_xLineEditDescription(m_xBuilder->weld_text_view("addrTextview")) +{ + m_xLineEditDescription->set_size_request(m_xLineEditDescription->get_approximate_digit_width() * 48, + m_xLineEditDescription->get_text_height() * 8); + m_xLineEditDescription->set_text(rMessage); +} + +SvxConfigPageFunctionDropTarget::SvxConfigPageFunctionDropTarget(SvxConfigPage&rPage, weld::TreeView& rTreeView) + : DropTargetHelper(rTreeView.get_drop_target()) + , m_rPage(rPage) + , m_rTreeView(rTreeView) +{ +} + +sal_Int8 SvxConfigPageFunctionDropTarget::AcceptDrop(const AcceptDropEvent& rEvt) +{ + // to enable the autoscroll when we're close to the edges + m_rTreeView.get_dest_row_at_pos(rEvt.maPosPixel, nullptr); + return DND_ACTION_MOVE; +} + +sal_Int8 SvxConfigPageFunctionDropTarget::ExecuteDrop( const ExecuteDropEvent& rEvt ) +{ + weld::TreeView* pSource = m_rTreeView.get_drag_source(); + // only dragging within the same widget allowed + if (!pSource || pSource != &m_rTreeView) + return DND_ACTION_NONE; + + std::unique_ptr xSource(m_rTreeView.make_iterator()); + if (!m_rTreeView.get_selected(xSource.get())) + return DND_ACTION_NONE; + + std::unique_ptr xTarget(m_rTreeView.make_iterator()); + int nTargetPos = -1; + if (m_rTreeView.get_dest_row_at_pos(rEvt.maPosPixel, xTarget.get())) + nTargetPos = m_rTreeView.get_iter_index_in_parent(*xTarget); + m_rTreeView.move_subtree(*xSource, nullptr, nTargetPos); + + m_rPage.ListModified(); + + return DND_ACTION_NONE; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/customize/cfgutil.cxx b/cui/source/customize/cfgutil.cxx new file mode 100644 index 000000000..d8ec5d79c --- /dev/null +++ b/cui/source/customize/cfgutil.cxx @@ -0,0 +1,1195 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::script; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::document; + +SfxStylesInfo_Impl::SfxStylesInfo_Impl() +{} + +void SfxStylesInfo_Impl::init(const OUString& rModuleName, const css::uno::Reference< css::frame::XModel >& xModel) +{ + m_aModuleName = rModuleName; + m_xDoc = xModel; +} + +static const char CMDURL_STYLEPROT_ONLY[] = ".uno:StyleApply?"; +static const char CMDURL_SPART_ONLY [] = "Style:string="; +static const char CMDURL_FPART_ONLY [] = "FamilyName:string="; + +static const char STYLEPROP_UINAME[] = "DisplayName"; + +OUString SfxStylesInfo_Impl::generateCommand(const OUString& sFamily, const OUString& sStyle) +{ + return ".uno:StyleApply?Style:string=" + + sStyle + + "&FamilyName:string=" + + sFamily; +} + +bool SfxStylesInfo_Impl::parseStyleCommand(SfxStyleInfo_Impl& aStyle) +{ + static const sal_Int32 LEN_STYLEPROT = strlen(CMDURL_STYLEPROT_ONLY); + static const sal_Int32 LEN_SPART = strlen(CMDURL_SPART_ONLY); + static const sal_Int32 LEN_FPART = strlen(CMDURL_FPART_ONLY); + + if (!aStyle.sCommand.startsWith(CMDURL_STYLEPROT_ONLY)) + return false; + + aStyle.sFamily.clear(); + aStyle.sStyle.clear(); + + sal_Int32 nCmdLen = aStyle.sCommand.getLength(); + OUString sCmdArgs = aStyle.sCommand.copy(LEN_STYLEPROT, nCmdLen-LEN_STYLEPROT); + sal_Int32 i = sCmdArgs.indexOf('&'); + if (i<0) + return false; + + OUString sArg = sCmdArgs.copy(0, i); + if (sArg.startsWith(CMDURL_SPART_ONLY)) + aStyle.sStyle = sArg.copy(LEN_SPART); + else if (sArg.startsWith(CMDURL_FPART_ONLY)) + aStyle.sFamily = sArg.copy(LEN_FPART); + + sArg = sCmdArgs.copy(i+1, sCmdArgs.getLength()-i-1); + if (sArg.startsWith(CMDURL_SPART_ONLY)) + aStyle.sStyle = sArg.copy(LEN_SPART); + else if (sArg.startsWith(CMDURL_FPART_ONLY)) + aStyle.sFamily = sArg.copy(LEN_FPART); + + return !(aStyle.sFamily.isEmpty() || aStyle.sStyle.isEmpty()); +} + +void SfxStylesInfo_Impl::getLabel4Style(SfxStyleInfo_Impl& aStyle) +{ + try + { + css::uno::Reference< css::style::XStyleFamiliesSupplier > xModel(m_xDoc, css::uno::UNO_QUERY); + + css::uno::Reference< css::container::XNameAccess > xFamilies; + if (xModel.is()) + xFamilies = xModel->getStyleFamilies(); + + css::uno::Reference< css::container::XNameAccess > xStyleSet; + if (xFamilies.is()) + xFamilies->getByName(aStyle.sFamily) >>= xStyleSet; + + css::uno::Reference< css::beans::XPropertySet > xStyle; + if (xStyleSet.is()) + xStyleSet->getByName(aStyle.sStyle) >>= xStyle; + + aStyle.sLabel.clear(); + if (xStyle.is()) + xStyle->getPropertyValue(STYLEPROP_UINAME) >>= aStyle.sLabel; + } + catch(const css::uno::RuntimeException&) + { throw; } + catch(const css::uno::Exception&) + { aStyle.sLabel.clear(); } + + if (aStyle.sLabel.isEmpty()) + { + aStyle.sLabel = aStyle.sCommand; + } +} + +std::vector< SfxStyleInfo_Impl > SfxStylesInfo_Impl::getStyleFamilies() const +{ + // It's an optional interface! + css::uno::Reference< css::style::XStyleFamiliesSupplier > xModel(m_xDoc, css::uno::UNO_QUERY); + if (!xModel.is()) + return std::vector< SfxStyleInfo_Impl >(); + + css::uno::Reference< css::container::XNameAccess > xCont = xModel->getStyleFamilies(); + const css::uno::Sequence< OUString > lFamilyNames = xCont->getElementNames(); + std::vector< SfxStyleInfo_Impl > lFamilies; + for (const auto& aFamily : lFamilyNames) + { + if ((aFamily == "CellStyles" && m_aModuleName != "com.sun.star.sheet.SpreadsheetDocument") || + aFamily == "cell" || aFamily == "table" || aFamily == "Default") + continue; + + SfxStyleInfo_Impl aFamilyInfo; + aFamilyInfo.sFamily = aFamily; + + try + { + css::uno::Reference< css::beans::XPropertySet > xFamilyInfo; + xCont->getByName(aFamilyInfo.sFamily) >>= xFamilyInfo; + if (!xFamilyInfo.is()) + { + // TODO_AS currently there is no support for an UIName property .. use internal family name instead + aFamilyInfo.sLabel = aFamilyInfo.sFamily; + } + else + xFamilyInfo->getPropertyValue(STYLEPROP_UINAME) >>= aFamilyInfo.sLabel; + } + catch(const css::uno::RuntimeException&) + { throw; } + catch(const css::uno::Exception&) + { return std::vector< SfxStyleInfo_Impl >(); } + + lFamilies.push_back(aFamilyInfo); + } + + return lFamilies; +} + +std::vector< SfxStyleInfo_Impl > SfxStylesInfo_Impl::getStyles(const OUString& sFamily) +{ + css::uno::Sequence< OUString > lStyleNames; + css::uno::Reference< css::style::XStyleFamiliesSupplier > xModel(m_xDoc, css::uno::UNO_QUERY_THROW); + css::uno::Reference< css::container::XNameAccess > xFamilies = xModel->getStyleFamilies(); + css::uno::Reference< css::container::XNameAccess > xStyleSet; + try + { + xFamilies->getByName(sFamily) >>= xStyleSet; + lStyleNames = xStyleSet->getElementNames(); + } + catch(const css::uno::RuntimeException&) + { throw; } + catch(const css::uno::Exception&) + { return std::vector< SfxStyleInfo_Impl >(); } + + std::vector< SfxStyleInfo_Impl > lStyles; + sal_Int32 c = lStyleNames.getLength(); + sal_Int32 i = 0; + for (i=0; i xStyle; + xStyleSet->getByName(aStyleInfo.sStyle) >>= xStyle; + if (!xStyle.is()) + continue; + xStyle->getPropertyValue("DisplayName") >>= aStyleInfo.sLabel; + } + catch(const css::uno::RuntimeException&) + { throw; } + catch(const css::uno::Exception&) + { continue; } + + lStyles.push_back(aStyleInfo); + } + return lStyles; +} + +OUString CuiConfigFunctionListBox::GetHelpText( bool bConsiderParent ) +{ + SfxGroupInfo_Impl *pData = reinterpret_cast(get_selected_id().toInt64()); + if (pData) + { + if ( pData->nKind == SfxCfgKind::FUNCTION_SLOT ) + { + if (bConsiderParent) + return Application::GetHelp()->GetHelpText(pData->sCommand, m_xTreeView.get()); + else + return Application::GetHelp()->GetHelpText(pData->sCommand, static_cast(nullptr)); + } + else if ( pData->nKind == SfxCfgKind::FUNCTION_SCRIPT ) + { + return pData->sHelpText; + } + } + return OUString(); +} + +OUString CuiConfigFunctionListBox::GetCurCommand() const +{ + SfxGroupInfo_Impl *pData = reinterpret_cast(get_selected_id().toInt64()); + if (!pData) + return OUString(); + return pData->sCommand; +} + +OUString CuiConfigFunctionListBox::GetCurLabel() const +{ + SfxGroupInfo_Impl *pData = reinterpret_cast(get_selected_id().toInt64()); + if (!pData) + return OUString(); + if (!pData->sLabel.isEmpty()) + return pData->sLabel; + return pData->sCommand; +} + +CuiConfigFunctionListBox::CuiConfigFunctionListBox(std::unique_ptr xTreeView) + : m_xTreeView(std::move(xTreeView)) + , m_xScratchIter(m_xTreeView->make_iterator()) +{ + m_xTreeView->make_sorted(); + m_xTreeView->set_size_request(m_xTreeView->get_approximate_digit_width() * 35, m_xTreeView->get_height_rows(9)); + m_xTreeView->connect_query_tooltip(LINK(this, CuiConfigFunctionListBox, QueryTooltip)); +} + +CuiConfigFunctionListBox::~CuiConfigFunctionListBox() +{ + ClearAll(); +} + +IMPL_LINK(CuiConfigFunctionListBox, QueryTooltip, const weld::TreeIter&, rIter, OUString) +{ + SfxGroupInfo_Impl *pData = reinterpret_cast(m_xTreeView->get_id(rIter).toInt64()); + if (!pData) + return OUString(); + OUString aLabel = CuiResId(RID_SVXSTR_COMMANDLABEL) + ": "; + OUString aName = CuiResId(RID_SVXSTR_COMMANDNAME) + ": "; + OUString aTip = CuiResId(RID_SVXSTR_COMMANDTIP) + ": "; + return aLabel + pData->sLabel + "\n" + aName + pData->sCommand+ "\n" + aTip + pData->sTooltip; +} + +void CuiConfigFunctionListBox::ClearAll() +/* Description + Deletes all entries in the FunctionListBox, all UserData and all + possibly existing MacroInfo. +*/ +{ + sal_uInt16 nCount = aArr.size(); + for ( sal_uInt16 i=0; inKind == SfxCfgKind::FUNCTION_SCRIPT ) + { + OUString* pScriptURI = static_cast(pData->pObject); + delete pScriptURI; + } + + if ( pData->nKind == SfxCfgKind::GROUP_SCRIPTCONTAINER ) + { + XInterface* xi = static_cast(pData->pObject); + if (xi != nullptr) + { + xi->release(); + } + } + } + + aArr.clear(); + m_xTreeView->clear(); +} + +OUString CuiConfigFunctionListBox::GetSelectedScriptURI() const +{ + SfxGroupInfo_Impl *pData = reinterpret_cast(get_selected_id().toInt64()); + if (pData && pData->nKind == SfxCfgKind::FUNCTION_SCRIPT) + return *static_cast(pData->pObject); + return OUString(); +} + +struct SvxConfigGroupBoxResource_Impl +{ + OUString m_sMyMacros; + OUString m_sProdMacros; + OUString m_sMacros; + OUString m_sDlgMacros; + OUString m_aStrGroupStyles; + + SvxConfigGroupBoxResource_Impl(); +}; + +SvxConfigGroupBoxResource_Impl::SvxConfigGroupBoxResource_Impl() : + m_sMyMacros(CuiResId(RID_SVXSTR_MYMACROS)), + m_sProdMacros(CuiResId(RID_SVXSTR_PRODMACROS)), + m_sMacros(CuiResId(RID_SVXSTR_BASICMACROS)), + m_sDlgMacros(CuiResId(RID_SVXSTR_PRODMACROS)), + m_aStrGroupStyles(CuiResId(RID_SVXSTR_GROUP_STYLES)) +{ +} + +void CuiConfigGroupListBox::SetStylesInfo(SfxStylesInfo_Impl* pStyles) +{ + m_pStylesInfo = pStyles; +} + +namespace +{ + + /** examines a component whether it supports XEmbeddedScripts, or provides access to such a + component by implementing XScriptInvocationContext. + @return + the model which supports the embedded scripts, or if it cannot find such a + model + */ + Reference< XModel > lcl_getDocumentWithScripts_throw( const Reference< XInterface >& _rxComponent ) + { + Reference< XEmbeddedScripts > xScripts( _rxComponent, UNO_QUERY ); + if ( !xScripts.is() ) + { + Reference< XScriptInvocationContext > xContext( _rxComponent, UNO_QUERY ); + if ( xContext.is() ) + xScripts = xContext->getScriptContainer(); + } + + return Reference< XModel >( xScripts, UNO_QUERY ); + } + + + Reference< XModel > lcl_getScriptableDocument_nothrow( const Reference< XFrame >& _rxFrame ) + { + Reference< XModel > xDocument; + + // examine our associated frame + try + { + OSL_ENSURE( _rxFrame.is(), "lcl_getScriptableDocument_nothrow: you need to pass a frame to this dialog/tab page!" ); + if ( _rxFrame.is() ) + { + // first try the model in the frame + Reference< XController > xController( _rxFrame->getController(), UNO_SET_THROW ); + xDocument = lcl_getDocumentWithScripts_throw( xController->getModel() ); + + if ( !xDocument.is() ) + { + // if there is no suitable document in the frame, try the controller + xDocument = lcl_getDocumentWithScripts_throw( _rxFrame->getController() ); + } + } + } + catch( const Exception& ) + { + } + + return xDocument; + } +} + +CuiConfigGroupListBox::CuiConfigGroupListBox(std::unique_ptr xTreeView) + : xImp(new SvxConfigGroupBoxResource_Impl()) + , m_pFunctionListBox(nullptr) + , m_pStylesInfo(nullptr) + , m_xTreeView(std::move(xTreeView)) +{ + m_xTreeView->connect_expanding(LINK(this, CuiConfigGroupListBox, ExpandingHdl)); + m_xTreeView->set_size_request(m_xTreeView->get_approximate_digit_width() * 35, m_xTreeView->get_height_rows(9)); +} + +CuiConfigGroupListBox::~CuiConfigGroupListBox() +{ + ClearAll(); +} + +void CuiConfigGroupListBox::ClearAll() +{ + sal_uInt16 nCount = aArr.size(); + for ( sal_uInt16 i=0; inKind == SfxCfgKind::GROUP_SCRIPTCONTAINER) + { + XInterface* xi = static_cast(pData->pObject); + if (xi != nullptr) + { + xi->release(); + } + } + } + + aArr.clear(); + m_xTreeView->clear(); +} + +void CuiConfigGroupListBox::InitModule() +{ + try + { + css::uno::Reference< css::frame::XDispatchInformationProvider > xProvider(m_xFrame, css::uno::UNO_QUERY_THROW); + css::uno::Sequence< sal_Int16 > lGroups = xProvider->getSupportedCommandGroups(); + sal_Int32 c1 = lGroups.getLength(); + sal_Int32 i1 = 0; + + if ( c1 ) + { + // Add All Commands category + aArr.push_back(std::make_unique(SfxCfgKind::GROUP_ALLFUNCTIONS, 0)); + m_xTreeView->append(OUString::number(reinterpret_cast(aArr.back().get())), + CuiResId(RID_SVXSTR_ALLFUNCTIONS)); + } + + for (i1=0; i1getByName(sGroupID) >>= sGroupName; + if (sGroupName.isEmpty()) + continue; + } + catch(const css::container::NoSuchElementException&) + { continue; } + + aArr.push_back( std::make_unique( SfxCfgKind::GROUP_FUNCTION, rGroupID ) ); + m_xTreeView->append(OUString::number(reinterpret_cast(aArr.back().get())), + sGroupName); + } + } + catch(const css::uno::RuntimeException&) + { throw; } + catch(const css::uno::Exception&) + {} +} + +void CuiConfigGroupListBox::FillScriptList(const css::uno::Reference< css::script::browse::XBrowseNode >& xRootNode, + const weld::TreeIter* pParentEntry, bool bCheapChildrenOnDemand) +{ + try { + if ( xRootNode->hasChildNodes() ) + { + // tdf#120362: Don't ask to enable disabled Java when filling script list + css::uno::ContextLayer layer(comphelper::NoEnableJavaInteractionContext()); + + const Sequence< Reference< browse::XBrowseNode > > children = + xRootNode->getChildNodes(); + bool bIsRootNode = false; + + OUString user("user"); + OUString share("share"); + if ( xRootNode->getName() == "Root" ) + { + bIsRootNode = true; + } + + //To mimic current starbasic behaviour we + //need to make sure that only the current document + //is displayed in the config tree. Tests below + //set the bDisplay flag to FALSE if the current + //node is a first level child of the Root and is NOT + //either the current document, user or share + OUString currentDocTitle; + Reference< XModel > xDocument( lcl_getScriptableDocument_nothrow( m_xFrame ) ); + if ( xDocument.is() ) + { + currentDocTitle = ::comphelper::DocumentInfo::getDocumentTitle( xDocument ); + } + + for ( Reference< browse::XBrowseNode > const & theChild : children ) + { + bool bDisplay = true; + OUString uiName = theChild->getName(); + if ( bIsRootNode ) + { + if ( ! (uiName == user || uiName == share || + uiName == currentDocTitle ) ) + { + bDisplay=false; + } + else + { + if ( uiName == user ) + { + uiName = xImp->m_sMyMacros; + } + else if ( uiName == share ) + { + uiName = xImp->m_sProdMacros; + } + } + } + if (theChild->getType() != browse::BrowseNodeTypes::SCRIPT && bDisplay ) + { +// We call acquire on the XBrowseNode so that it does not +// get autodestructed and become invalid when accessed later. + theChild->acquire(); + + bool bChildOnDemand = false; + if ( !bCheapChildrenOnDemand && theChild->hasChildNodes() ) + { + const Sequence< Reference< browse::XBrowseNode > > grandchildren = + theChild->getChildNodes(); + + for ( const auto& rxNode : grandchildren ) + { + if ( rxNode->getType() == browse::BrowseNodeTypes::CONTAINER ) + { + bChildOnDemand = true; + break; + } + } + } + else + { + /* i30923 - Would be nice if there was a better + * way to determine if a basic lib had children + * without having to ask for them (which forces + * the library to be loaded */ + bChildOnDemand = true; + } + + OUString aImage = GetImage(theChild, m_xContext, bIsRootNode); + + aArr.push_back( std::make_unique(SfxCfgKind::GROUP_SCRIPTCONTAINER, + 0, static_cast( theChild.get()))); + + OUString sId(OUString::number(reinterpret_cast(aArr.back().get()))); + m_xTreeView->insert(pParentEntry, -1, &uiName, &sId, nullptr, nullptr, &aImage, bChildOnDemand, nullptr); + } + } + } + } + catch (RuntimeException&) { + // do nothing, the entry will not be displayed in the UI + } +} + +void CuiConfigGroupListBox::FillFunctionsList(const css::uno::Sequence& xCommands) +{ + m_pFunctionListBox->freeze(); + for (const auto & rInfo : xCommands) + { + auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(rInfo.Command, m_sModuleLongName); + + OUString sUIName = MapCommand2UIName(rInfo.Command); + aArr.push_back( std::make_unique( SfxCfgKind::FUNCTION_SLOT, 0 ) ); + SfxGroupInfo_Impl* pGrpInfo = aArr.back().get(); + pGrpInfo->sCommand = rInfo.Command; + pGrpInfo->sLabel = sUIName; + pGrpInfo->sTooltip = vcl::CommandInfoProvider::GetTooltipForCommand(rInfo.Command, aProperties, m_xFrame); + m_pFunctionListBox->append(OUString::number(reinterpret_cast(pGrpInfo)), sUIName); + } + m_pFunctionListBox->thaw(); +} + +void CuiConfigGroupListBox::Init(const css::uno::Reference< css::uno::XComponentContext >& xContext, + const css::uno::Reference< css::frame::XFrame >& xFrame, + const OUString& sModuleLongName, + bool bEventMode) +{ + m_xTreeView->freeze(); + ClearAll(); // Remove all old entries from treelist box + + m_xContext = xContext; + m_xFrame = xFrame; + if( bEventMode ) + { + m_sModuleLongName = sModuleLongName; + m_xGlobalCategoryInfo = css::ui::theUICategoryDescription::get( m_xContext ); + m_xModuleCategoryInfo.set(m_xGlobalCategoryInfo->getByName(m_sModuleLongName), css::uno::UNO_QUERY_THROW); + m_xUICmdDescription = css::frame::theUICommandDescription::get( m_xContext ); + + InitModule(); + } + + SAL_INFO("cui.customize", "** ** About to initialise SF Scripts"); + // Add Scripting Framework entries + Reference< browse::XBrowseNode > rootNode; + try + { + Reference< browse::XBrowseNodeFactory > xFac = browse::theBrowseNodeFactory::get( m_xContext ); + rootNode.set( xFac->createView( browse::BrowseNodeFactoryViewTypes::MACROSELECTOR ) ); + } + catch( const Exception& ) + { + TOOLS_WARN_EXCEPTION("cui.customize", "Caught some exception whilst retrieving browse nodes from factory"); + // TODO exception handling + } + + + if ( rootNode.is() ) + { + if ( bEventMode ) + { + //We call acquire on the XBrowseNode so that it does not + //get autodestructed and become invalid when accessed later. + rootNode->acquire(); + + aArr.push_back( std::make_unique( SfxCfgKind::GROUP_SCRIPTCONTAINER, 0, + static_cast(rootNode.get()))); + OUString aTitle(xImp->m_sDlgMacros); + OUString sId(OUString::number(reinterpret_cast(aArr.back().get()))); + m_xTreeView->insert(nullptr, -1, &aTitle, &sId, nullptr, nullptr, nullptr, true, nullptr); + } + else + { + //We are only showing scripts not slot APIs so skip + //Root node and show location nodes + FillScriptList(rootNode, nullptr, false); + } + } + + // add styles + if ( bEventMode ) + { + aArr.push_back( std::make_unique( SfxCfgKind::GROUP_STYLES, 0, nullptr ) ); // TODO last parameter should contain user data + OUString sStyle(xImp->m_aStrGroupStyles); + OUString sId(OUString::number(reinterpret_cast(aArr.back().get()))); + m_xTreeView->insert(nullptr, -1, &sStyle, &sId, nullptr, nullptr, nullptr, true, nullptr); + } + + m_xTreeView->thaw(); + m_xTreeView->scroll_to_row(0); + m_xTreeView->select(0); +} + +OUString CuiConfigGroupListBox::GetImage( + const Reference< browse::XBrowseNode >& node, + Reference< XComponentContext > const & xCtx, + bool bIsRootNode) +{ + OUString aImage; + if ( bIsRootNode ) + { + if (node->getName() == "user" || node->getName() == "share" ) + { + aImage = RID_CUIBMP_HARDDISK; + } + else + { + OUString factoryURL; + OUString nodeName = node->getName(); + Reference xDocumentModel = getDocumentModel(xCtx, nodeName ); + if ( xDocumentModel.is() ) + { + Reference< frame::XModuleManager2 > xModuleManager( frame::ModuleManager::create(xCtx) ); + // get the long name of the document: + OUString appModule( xModuleManager->identify( + xDocumentModel ) ); + Sequence moduleDescr; + Any aAny = xModuleManager->getByName(appModule); + if( !( aAny >>= moduleDescr ) ) + { + throw RuntimeException("SFTreeListBox::Init: failed to get PropertyValue"); + } + beans::PropertyValue const * pmoduleDescr = + moduleDescr.getConstArray(); + for ( sal_Int32 pos = moduleDescr.getLength(); pos--; ) + { + if ( pmoduleDescr[ pos ].Name == "ooSetupFactoryEmptyDocumentURL" ) + { + pmoduleDescr[ pos ].Value >>= factoryURL; + SAL_INFO("cui.customize", "factory url for doc images is " << factoryURL); + break; + } + } + } + if( !factoryURL.isEmpty() ) + { + aImage = SvFileInformationManager::GetFileImageId(INetURLObject(factoryURL)); + } + else + { + aImage = RID_CUIBMP_DOC; + } + } + } + else + { + if( node->getType() == browse::BrowseNodeTypes::SCRIPT ) + aImage = RID_CUIBMP_MACRO; + else + aImage = RID_CUIBMP_LIB; + } + return aImage; +} + +Reference< XInterface > +CuiConfigGroupListBox::getDocumentModel( Reference< XComponentContext > const & xCtx, OUString const & docName ) +{ + Reference< XInterface > xModel; + Reference< frame::XDesktop2 > desktop = frame::Desktop::create( xCtx ); + + Reference< container::XEnumerationAccess > componentsAccess = + desktop->getComponents(); + Reference< container::XEnumeration > components = + componentsAccess->createEnumeration(); + while (components->hasMoreElements()) + { + Reference< frame::XModel > model( + components->nextElement(), UNO_QUERY ); + if ( model.is() ) + { + OUString sTdocUrl = + ::comphelper::DocumentInfo::getDocumentTitle( model ); + if( sTdocUrl == docName ) + { + xModel = model; + break; + } + } + } + return xModel; +} + +OUString CuiConfigGroupListBox::MapCommand2UIName(const OUString& sCommand) +{ + OUString sUIName; + try + { + css::uno::Reference< css::container::XNameAccess > xModuleConf; + m_xUICmdDescription->getByName(m_sModuleLongName) >>= xModuleConf; + if (xModuleConf.is()) + { + ::comphelper::SequenceAsHashMap lProps(xModuleConf->getByName(sCommand)); + sUIName = lProps.getUnpackedValueOrDefault("Name", OUString()); + } + } + catch(const css::uno::RuntimeException&) + { throw; } + catch(css::uno::Exception&) + { sUIName.clear(); } + + // fallback for missing UINames !? + if (sUIName.isEmpty()) + { + sUIName = sCommand; + } + + return sUIName; +} + +void CuiConfigGroupListBox::GroupSelected() +/* Description + A function group or a basic module has been selected. + All functions/macros are displayed in the functionlistbox. +*/ +{ + std::unique_ptr xIter(m_xTreeView->make_iterator()); + if (!m_xTreeView->get_selected(xIter.get())) + return; + + SfxGroupInfo_Impl *pInfo = reinterpret_cast(m_xTreeView->get_id(*xIter).toInt64()); + m_pFunctionListBox->freeze(); + m_pFunctionListBox->ClearAll(); + + switch ( pInfo->nKind ) + { + case SfxCfgKind::GROUP_ALLFUNCTIONS: + { + css::uno::Reference< css::frame::XDispatchInformationProvider > xProvider( m_xFrame, UNO_QUERY ); + bool bValidIter = m_xTreeView->get_iter_first(*xIter); + while (bValidIter) + { + SfxGroupInfo_Impl *pCurrentInfo = reinterpret_cast(m_xTreeView->get_id(*xIter).toInt64()); + if (pCurrentInfo->nKind == SfxCfgKind::GROUP_FUNCTION) + { + css::uno::Sequence< css::frame::DispatchInformation > lCommands; + try + { + lCommands = xProvider->getConfigurableDispatchInformation( pCurrentInfo->nUniqueID ); + FillFunctionsList( lCommands ); + } + catch ( container::NoSuchElementException& ) + { + } + } + bValidIter = m_xTreeView->iter_next(*xIter); + } + break; + } + + case SfxCfgKind::GROUP_FUNCTION : + { + sal_uInt16 nGroup = pInfo->nUniqueID; + css::uno::Reference< css::frame::XDispatchInformationProvider > xProvider (m_xFrame, css::uno::UNO_QUERY_THROW); + css::uno::Sequence< css::frame::DispatchInformation > lCommands = xProvider->getConfigurableDispatchInformation(nGroup); + FillFunctionsList( lCommands ); + break; + } + + case SfxCfgKind::GROUP_SCRIPTCONTAINER: + { + if (!m_xTreeView->iter_has_child(*xIter)) + { + Reference< browse::XBrowseNode > rootNode( + static_cast< browse::XBrowseNode* >( pInfo->pObject ) ) ; + + try { + if ( rootNode->hasChildNodes() ) + { + const Sequence< Reference< browse::XBrowseNode > > children = + rootNode->getChildNodes(); + + for ( const Reference< browse::XBrowseNode >& childNode : children ) + { + if (childNode->getType() == browse::BrowseNodeTypes::SCRIPT) + { + OUString uri, description; + + Reference < beans::XPropertySet >xPropSet( childNode, UNO_QUERY ); + if (!xPropSet.is()) + { + continue; + } + + Any value = + xPropSet->getPropertyValue("URI"); + value >>= uri; + + try + { + value = xPropSet->getPropertyValue("Description"); + value >>= description; + } + catch (Exception &) { + // do nothing, the description will be empty + } + + OUString* pScriptURI = new OUString( uri ); + + OUString aImage = GetImage(childNode, Reference< XComponentContext >(), false); + m_pFunctionListBox->aArr.push_back( std::make_unique( SfxCfgKind::FUNCTION_SCRIPT, 0, pScriptURI )); + m_pFunctionListBox->aArr.back()->sCommand = uri; + m_pFunctionListBox->aArr.back()->sLabel = childNode->getName(); + m_pFunctionListBox->aArr.back()->sHelpText = description; + + OUString sId(OUString::number(reinterpret_cast(m_pFunctionListBox->aArr.back().get()))); + m_pFunctionListBox->append(sId, childNode->getName(), aImage); + } + } + } + } + catch (RuntimeException&) { + // do nothing, the entry will not be displayed in the UI + } + } + break; + } + + case SfxCfgKind::GROUP_STYLES : + { + SfxStyleInfo_Impl* pFamily = static_cast(pInfo->pObject); + if (pFamily) + { + const std::vector< SfxStyleInfo_Impl > lStyles = m_pStylesInfo->getStyles(pFamily->sFamily); + for (auto const& lStyle : lStyles) + { + SfxStyleInfo_Impl* pStyle = new SfxStyleInfo_Impl(lStyle); + m_pFunctionListBox->aArr.push_back(std::make_unique(SfxCfgKind::GROUP_STYLES, 0, pStyle)); + m_pFunctionListBox->aArr.back()->sCommand = pStyle->sCommand; + m_pFunctionListBox->aArr.back()->sLabel = pStyle->sLabel; + OUString sId(OUString::number(reinterpret_cast(m_pFunctionListBox->aArr.back().get()))); + m_pFunctionListBox->append(sId, pStyle->sLabel); + } + } + break; + } + + default: + // Do nothing, the list box will stay empty + SAL_INFO( "cui.customize", "Ignoring unexpected SfxCfgKind: " << static_cast(pInfo->nKind) ); + break; + } + + m_pFunctionListBox->thaw(); + + if (m_pFunctionListBox->n_children()) + m_pFunctionListBox->select(0); +} + +/* Description + A basic or a library is opened. +*/ +IMPL_LINK(CuiConfigGroupListBox, ExpandingHdl, const weld::TreeIter&, rIter, bool) +{ + SfxGroupInfo_Impl *pInfo = reinterpret_cast(m_xTreeView->get_id(rIter).toInt64()); + switch ( pInfo->nKind ) + { + case SfxCfgKind::GROUP_SCRIPTCONTAINER: + { + if (!m_xTreeView->iter_has_child(rIter)) + { + Reference< browse::XBrowseNode > rootNode( + static_cast< browse::XBrowseNode* >( pInfo->pObject ) ) ; + FillScriptList(rootNode, &rIter, true /* i30923 */ ); + } + break; + } + + case SfxCfgKind::GROUP_STYLES: + { + if (!m_xTreeView->iter_has_child(rIter)) + { + const std::vector lStyleFamilies = m_pStylesInfo->getStyleFamilies(); + for (auto const& lStyleFamily : lStyleFamilies) + { + SfxStyleInfo_Impl* pFamily = new SfxStyleInfo_Impl(lStyleFamily); + aArr.push_back( std::make_unique( SfxCfgKind::GROUP_STYLES, 0, pFamily )); + OUString sId(OUString::number(reinterpret_cast(aArr.back().get()))); + m_xTreeView->insert(&rIter, -1, &pFamily->sLabel, &sId, nullptr, nullptr, nullptr, false, nullptr); + } + } + break; + } + + default: + OSL_FAIL( "Wrong group type!" ); + break; + } + return true; +} + +void CuiConfigGroupListBox::SelectMacro( const SfxMacroInfoItem *pItem ) +{ + SelectMacro( pItem->GetBasicManager()->GetName(), + pItem->GetQualifiedName() ); +} + +void CuiConfigGroupListBox::SelectMacro( const OUString& rBasic, + const OUString& rMacro ) +{ + const OUString aBasicName(rBasic + " " + xImp->m_sMacros); + sal_Int32 nIdx {rMacro.lastIndexOf('.')}; + const OUString aMethod( rMacro.copy(nIdx+1) ); + OUString aLib; + OUString aModule; + if ( nIdx>0 ) + { + // string contains at least 2 tokens + nIdx = rMacro.lastIndexOf('.', nIdx); + if (nIdx>=0) + { + // string contains at least 3 tokens + aLib = rMacro.getToken( 0, '.' ); + aModule = rMacro.getToken( 0, '.', ++nIdx ); + } + } + + std::unique_ptr xIter = m_xTreeView->make_iterator(); + if (!m_xTreeView->get_iter_first(*xIter)) + return; + + do + { + OUString aEntryBas = m_xTreeView->get_text(*xIter); + if (aEntryBas == aBasicName) + { + m_xTreeView->expand_row(*xIter); + std::unique_ptr xLibIter = m_xTreeView->make_iterator(xIter.get()); + if (m_xTreeView->get_iter_first(*xLibIter)) + { + do + { + OUString aEntryLib = m_xTreeView->get_text(*xLibIter); + if (aEntryLib == aLib) + { + m_xTreeView->expand_row(*xLibIter); + std::unique_ptr xModIter = m_xTreeView->make_iterator(xLibIter.get()); + if (m_xTreeView->get_iter_first(*xModIter)) + { + do + { + OUString aEntryMod = m_xTreeView->get_text(*xModIter); + if ( aEntryMod == aModule ) + { + m_xTreeView->expand_row(*xModIter); + m_xTreeView->scroll_to_row(*xModIter); + m_xTreeView->select(*xModIter); + for (int i = 0, nCount = m_pFunctionListBox->n_children(); i < nCount; ++i) + { + OUString aEntryMethod = m_pFunctionListBox->get_text(i); + if (aEntryMethod == aMethod) + { + m_pFunctionListBox->select(i); + m_pFunctionListBox->scroll_to_row(i); + return; + } + } + } + } while (m_xTreeView->iter_next_sibling(*xModIter)); + } + } + } while (m_xTreeView->iter_next_sibling(*xLibIter)); + } + } + } while (m_xTreeView->iter_next_sibling(*xIter)); +} + +/* + * Implementation of SvxScriptSelectorDialog + * + * This dialog is used for selecting Slot API commands + * and Scripting Framework Scripts. + */ + +SvxScriptSelectorDialog::SvxScriptSelectorDialog( + weld::Window* pParent, const css::uno::Reference< css::frame::XFrame >& xFrame) + : GenericDialogController(pParent, "cui/ui/macroselectordialog.ui", "MacroSelectorDialog") + , m_xDialogDescription(m_xBuilder->weld_label("helpmacro")) + , m_xCategories(new CuiConfigGroupListBox(m_xBuilder->weld_tree_view("categories"))) + , m_xCommands(new CuiConfigFunctionListBox(m_xBuilder->weld_tree_view("commands"))) + , m_xLibraryFT(m_xBuilder->weld_label("libraryft")) + , m_xCategoryFT(m_xBuilder->weld_label("categoryft")) + , m_xMacronameFT(m_xBuilder->weld_label("macronameft")) + , m_xCommandsFT(m_xBuilder->weld_label("commandsft")) + , m_xOKButton(m_xBuilder->weld_button("ok")) + , m_xCancelButton(m_xBuilder->weld_button("cancel")) + , m_xDescriptionText(m_xBuilder->weld_text_view("description")) +{ + m_xCancelButton->show(); + m_xDialogDescription->show(); + m_xOKButton->show(); + + m_xLibraryFT->set_visible(true); + m_xCategoryFT->set_visible(false); + m_xMacronameFT->set_visible(true); + m_xCommandsFT->set_visible(false); + + const OUString aModuleName(vcl::CommandInfoProvider::GetModuleIdentifier(xFrame)); + m_xCategories->SetFunctionListBox(m_xCommands.get()); + m_xCategories->Init(comphelper::getProcessComponentContext(), xFrame, aModuleName, /*bShowSlots*/false); + + m_xCategories->connect_changed( + LINK( this, SvxScriptSelectorDialog, SelectHdl ) ); + m_xCommands->connect_changed( LINK( this, SvxScriptSelectorDialog, SelectHdl ) ); + m_xCommands->connect_row_activated( LINK( this, SvxScriptSelectorDialog, FunctionDoubleClickHdl ) ); + + m_xOKButton->connect_clicked( LINK( this, SvxScriptSelectorDialog, ClickHdl ) ); + m_xCancelButton->connect_clicked( LINK( this, SvxScriptSelectorDialog, ClickHdl ) ); + + m_sDefaultDesc = m_xDescriptionText->get_text(); + + // Support style commands + uno::Reference xController; + uno::Reference xModel; + if (xFrame.is()) + xController = xFrame->getController(); + if (xController.is()) + xModel = xController->getModel(); + + m_aStylesInfo.init(aModuleName, xModel); + m_xCategories->SetStylesInfo(&m_aStylesInfo); + + UpdateUI(); +} + +SvxScriptSelectorDialog::~SvxScriptSelectorDialog() +{ +} + +IMPL_LINK(SvxScriptSelectorDialog, SelectHdl, weld::TreeView&, rCtrl, void) +{ + if (&rCtrl == &m_xCategories->get_widget()) + { + m_xCategories->GroupSelected(); + } + UpdateUI(); +} + +IMPL_LINK_NOARG(SvxScriptSelectorDialog, FunctionDoubleClickHdl, weld::TreeView&, bool) +{ + if (m_xOKButton->get_sensitive()) + ClickHdl(*m_xOKButton); + return true; +} + +// Check if command is selected and enable the OK button accordingly +// Grab the help text for this id if available and update the description field +void +SvxScriptSelectorDialog::UpdateUI() +{ + OUString url = GetScriptURL(); + if ( !url.isEmpty() ) + { + OUString sMessage = m_xCommands->GetHelpText(); + m_xDescriptionText->set_text(sMessage.isEmpty() ? m_sDefaultDesc : sMessage); + + m_xOKButton->set_sensitive(true); + } + else + { + m_xDescriptionText->set_text(m_sDefaultDesc); + m_xOKButton->set_sensitive(false); + } +} + +IMPL_LINK(SvxScriptSelectorDialog, ClickHdl, weld::Button&, rButton, void) +{ + if (&rButton == m_xCancelButton.get()) + { + m_xDialog->response(RET_CANCEL); + } + else if (&rButton == m_xOKButton.get()) + { + m_xDialog->response(RET_OK); + } +} + +void +SvxScriptSelectorDialog::SetRunLabel() +{ + m_xOKButton->set_label(CuiResId(RID_SVXSTR_SELECTOR_RUN)); +} + +OUString +SvxScriptSelectorDialog::GetScriptURL() const +{ + OUString result; + + std::unique_ptr xIter = m_xCommands->make_iterator(); + if (m_xCommands->get_selected(xIter.get())) + { + SfxGroupInfo_Impl *pData = reinterpret_cast(m_xCommands->get_id(*xIter).toInt64()); + if ( ( pData->nKind == SfxCfgKind::FUNCTION_SLOT ) + || ( pData->nKind == SfxCfgKind::FUNCTION_SCRIPT ) + || ( pData->nKind == SfxCfgKind::GROUP_STYLES ) + ) + { + result = pData->sCommand; + } + } + + return result; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/customize/eventdlg.cxx b/cui/source/customize/eventdlg.cxx new file mode 100644 index 000000000..72cd08b16 --- /dev/null +++ b/cui/source/customize/eventdlg.cxx @@ -0,0 +1,162 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "eventdlg.hxx" +#include "macropg_impl.hxx" + +#include + +using namespace ::com::sun::star; + + +SvxEventConfigPage::SvxEventConfigPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet, + SvxEventConfigPage::EarlyInit) + : SvxMacroTabPage_(pPage, pController, "cui/ui/eventsconfigpage.ui", "EventsConfigPage", rSet) + , m_xSaveInListBox(m_xBuilder->weld_combo_box("savein")) +{ + mpImpl->xEventLB = m_xBuilder->weld_tree_view("events"); + mpImpl->xAssignPB = m_xBuilder->weld_button("macro"); + mpImpl->xDeletePB = m_xBuilder->weld_button("delete"); + mpImpl->xAssignComponentPB = m_xBuilder->weld_button("component"); + + mpImpl->xEventLB->set_size_request(mpImpl->xEventLB->get_approximate_digit_width() * 70, + mpImpl->xEventLB->get_height_rows(20)); + + InitResources(); + + m_xSaveInListBox->connect_changed( LINK( this, SvxEventConfigPage, + SelectHdl_Impl ) ); + + uno::Reference< frame::XGlobalEventBroadcaster > xSupplier = + frame::theGlobalEventBroadcaster::get(::comphelper::getProcessComponentContext()); + + m_xAppEvents = xSupplier->getEvents(); + m_xSaveInListBox->append(OUString::boolean(true), utl::ConfigManager::getProductName()); + m_xSaveInListBox->set_active(0); +} + +void SvxEventConfigPage::LateInit( const uno::Reference< frame::XFrame >& _rxFrame ) +{ + SetFrame( _rxFrame ); + ImplInitDocument(); + + InitAndSetHandler( m_xAppEvents, m_xDocumentEvents, m_xDocumentModifiable ); + + SelectHdl_Impl( *m_xSaveInListBox ); +} + +SvxEventConfigPage::~SvxEventConfigPage() +{ +} + +void SvxEventConfigPage::ImplInitDocument() +{ + uno::Reference< frame::XFrame > xFrame( GetFrame() ); + OUString aModuleId = SvxConfigPage::GetFrameWithDefaultAndIdentify( xFrame ); + if ( !xFrame.is() ) + return; + + try + { + uno::Reference< frame::XModel > xModel; + if ( !SvxConfigPage::CanConfig( aModuleId ) ) + return; + + uno::Reference< frame::XController > xController = + xFrame->getController(); + + if ( xController.is() ) + { + xModel = xController->getModel(); + } + + if ( !xModel.is() ) + return; + + uno::Reference< document::XEventsSupplier > xSupplier( xModel, uno::UNO_QUERY ); + + if ( xSupplier.is() ) + { + m_xDocumentEvents = xSupplier->getEvents(); + m_xDocumentModifiable.set(xModel, css::uno::UNO_QUERY); + + OUString aTitle = ::comphelper::DocumentInfo::getDocumentTitle( xModel ); + + m_xSaveInListBox->append(OUString::boolean(false), aTitle); + m_xSaveInListBox->set_active(m_xSaveInListBox->get_count() - 1); + } + } + catch( const uno::Exception& ) + { + DBG_UNHANDLED_EXCEPTION("cui.customize"); + } +} + +IMPL_LINK_NOARG( SvxEventConfigPage, SelectHdl_Impl, weld::ComboBox&, void ) +{ + bool bApp = m_xSaveInListBox->get_active_id().toBoolean(); + + mpImpl->xEventLB->freeze(); + if (bApp) + { + SetReadOnly( false ); + SvxMacroTabPage_::DisplayAppEvents( true ); + } + else + { + bool isReadonly = false; + + uno::Reference< frame::XDesktop2 > xFramesSupplier = frame::Desktop::create( + ::comphelper::getProcessComponentContext() ); + + uno::Reference< frame::XFrame > xFrame = + xFramesSupplier->getActiveFrame(); + + if ( xFrame.is() ) + { + uno::Reference< frame::XController > xController = + xFrame->getController(); + + if ( xController.is() ) + { + uno::Reference< frame::XStorable > xStorable( + xController->getModel(), uno::UNO_QUERY ); + isReadonly = xStorable->isReadonly(); + } + } + + SetReadOnly( isReadonly ); + SvxMacroTabPage_::DisplayAppEvents( false ); + } + + mpImpl->xEventLB->thaw(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/customize/eventdlg.hxx b/cui/source/customize/eventdlg.hxx new file mode 100644 index 000000000..2d368e982 --- /dev/null +++ b/cui/source/customize/eventdlg.hxx @@ -0,0 +1,52 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include +#include + +#include + +class SvxEventConfigPage : public SvxMacroTabPage_ +{ + css::uno::Reference< css::container::XNameReplace > m_xAppEvents; + css::uno::Reference< css::container::XNameReplace > m_xDocumentEvents; + css::uno::Reference< css::util::XModifiable > m_xDocumentModifiable; + + std::unique_ptr m_xSaveInListBox; + + DECL_LINK( SelectHdl_Impl, weld::ComboBox&, void ); + + SvxEventConfigPage (const SvxEventConfigPage &) = delete; + SvxEventConfigPage & operator= (const SvxEventConfigPage &) = delete; + +public: + + /// this is only to let callers know that there is a LateInit which *must* be called + struct EarlyInit { }; + SvxEventConfigPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet, EarlyInit); + virtual ~SvxEventConfigPage() override; + + void LateInit( const css::uno::Reference< css::frame::XFrame >& _rxFrame ); + +private: + void ImplInitDocument(); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/customize/macropg.cxx b/cui/source/customize/macropg.cxx new file mode 100644 index 000000000..7b45afa86 --- /dev/null +++ b/cui/source/customize/macropg.cxx @@ -0,0 +1,668 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "macropg_impl.hxx" +#include +#include +#include +#include + +#include +#include +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +static const char aVndSunStarUNO[] = "vnd.sun.star.UNO:"; + +SvxMacroTabPage_Impl::SvxMacroTabPage_Impl( const SfxItemSet& rAttrSet ) + : bReadOnly(false) + , bIDEDialogMode(false) +{ + const SfxPoolItem* pItem; + if ( SfxItemState::SET == rAttrSet.GetItemState( SID_ATTR_MACROITEM, false, &pItem ) ) + bIDEDialogMode = static_cast(pItem)->GetValue(); +} + +MacroEventListBox::MacroEventListBox(std::unique_ptr xTreeView) + : m_xTreeView(std::move(xTreeView)) +{ + m_xTreeView->set_help_id(HID_MACRO_HEADERTABLISTBOX); + m_xTreeView->set_size_request(m_xTreeView->get_approximate_digit_width() * 70, m_xTreeView->get_height_rows(9)); +} + +// assign button ("Add Command") is enabled only if it is not read only +// delete button ("Remove Command") is enabled if a current binding exists +// and it is not read only +void SvxMacroTabPage_::EnableButtons() +{ + int nEvent = mpImpl->xEventLB->get_selected_index(); + if (nEvent != -1) + { + mpImpl->xDeletePB->set_sensitive( !mpImpl->bReadOnly ); + mpImpl->xAssignPB->set_sensitive( !mpImpl->bReadOnly ); + if( mpImpl->xAssignComponentPB ) + mpImpl->xAssignComponentPB->set_sensitive( !mpImpl->bReadOnly ); + } +} + +SvxMacroTabPage_::SvxMacroTabPage_(weld::Container* pPage, weld::DialogController* pController, const OUString& rUIXMLDescription, + const OString& rID, const SfxItemSet& rAttrSet) + : SfxTabPage(pPage, pController, rUIXMLDescription, rID, &rAttrSet) + , bDocModified(false) + , bAppEvents(false) + , bInitialized(false) +{ + mpImpl.reset( new SvxMacroTabPage_Impl( rAttrSet ) ); +} + +SvxMacroTabPage_::~SvxMacroTabPage_() +{ + mpImpl.reset(); +} + +void SvxMacroTabPage_::InitResources() +{ + // Note: the order here controls the order in which the events are displayed in the UI! + + // the event name to UI string mappings for App Events + aDisplayNames.emplace_back( "OnStartApp", RID_SVXSTR_EVENT_STARTAPP ); + aDisplayNames.emplace_back( "OnCloseApp", RID_SVXSTR_EVENT_CLOSEAPP ); + aDisplayNames.emplace_back( "OnCreate", RID_SVXSTR_EVENT_CREATEDOC ); + aDisplayNames.emplace_back( "OnNew", RID_SVXSTR_EVENT_NEWDOC ); + aDisplayNames.emplace_back( "OnLoadFinished", RID_SVXSTR_EVENT_LOADDOCFINISHED ); + aDisplayNames.emplace_back( "OnLoad", RID_SVXSTR_EVENT_OPENDOC ); + aDisplayNames.emplace_back( "OnPrepareUnload", RID_SVXSTR_EVENT_PREPARECLOSEDOC ); + aDisplayNames.emplace_back( "OnUnload", RID_SVXSTR_EVENT_CLOSEDOC ) ; + aDisplayNames.emplace_back( "OnViewCreated", RID_SVXSTR_EVENT_VIEWCREATED ); + aDisplayNames.emplace_back( "OnPrepareViewClosing", RID_SVXSTR_EVENT_PREPARECLOSEVIEW ); + aDisplayNames.emplace_back( "OnViewClosed", RID_SVXSTR_EVENT_CLOSEVIEW ) ; + aDisplayNames.emplace_back( "OnFocus", RID_SVXSTR_EVENT_ACTIVATEDOC ); + aDisplayNames.emplace_back( "OnUnfocus", RID_SVXSTR_EVENT_DEACTIVATEDOC ); + aDisplayNames.emplace_back( "OnSave", RID_SVXSTR_EVENT_SAVEDOC ); + aDisplayNames.emplace_back( "OnSaveDone", RID_SVXSTR_EVENT_SAVEDOCDONE ); + aDisplayNames.emplace_back( "OnSaveFailed", RID_SVXSTR_EVENT_SAVEDOCFAILED ); + aDisplayNames.emplace_back( "OnSaveAs", RID_SVXSTR_EVENT_SAVEASDOC ); + aDisplayNames.emplace_back( "OnSaveAsDone", RID_SVXSTR_EVENT_SAVEASDOCDONE ); + aDisplayNames.emplace_back( "OnSaveAsFailed", RID_SVXSTR_EVENT_SAVEASDOCFAILED ); + aDisplayNames.emplace_back( "OnCopyTo", RID_SVXSTR_EVENT_COPYTODOC ); + aDisplayNames.emplace_back( "OnCopyToDone", RID_SVXSTR_EVENT_COPYTODOCDONE ); + aDisplayNames.emplace_back( "OnCopyToFailed", RID_SVXSTR_EVENT_COPYTODOCFAILED ); + aDisplayNames.emplace_back( "OnPrint", RID_SVXSTR_EVENT_PRINTDOC ); + aDisplayNames.emplace_back( "OnModifyChanged", RID_SVXSTR_EVENT_MODIFYCHANGED ); + aDisplayNames.emplace_back( "OnTitleChanged", RID_SVXSTR_EVENT_TITLECHANGED ); + + // application specific events + aDisplayNames.emplace_back( "OnMailMerge", RID_SVXSTR_EVENT_MAILMERGE ); + aDisplayNames.emplace_back( "OnMailMergeFinished", RID_SVXSTR_EVENT_MAILMERGE_END ); + aDisplayNames.emplace_back( "OnFieldMerge", RID_SVXSTR_EVENT_FIELDMERGE ); + aDisplayNames.emplace_back( "OnFieldMergeFinished", RID_SVXSTR_EVENT_FIELDMERGE_FINISHED ); + aDisplayNames.emplace_back( "OnPageCountChange", RID_SVXSTR_EVENT_PAGECOUNTCHANGE ); + aDisplayNames.emplace_back( "OnSubComponentOpened", RID_SVXSTR_EVENT_SUBCOMPONENT_OPENED ); + aDisplayNames.emplace_back( "OnSubComponentClosed", RID_SVXSTR_EVENT_SUBCOMPONENT_CLOSED ); + aDisplayNames.emplace_back( "OnSelect", RID_SVXSTR_EVENT_SELECTIONCHANGED ); + aDisplayNames.emplace_back( "OnDoubleClick", RID_SVXSTR_EVENT_DOUBLECLICK ); + aDisplayNames.emplace_back( "OnRightClick", RID_SVXSTR_EVENT_RIGHTCLICK ); + aDisplayNames.emplace_back( "OnCalculate", RID_SVXSTR_EVENT_CALCULATE ); + aDisplayNames.emplace_back( "OnChange", RID_SVXSTR_EVENT_CONTENTCHANGED ); + + // the event name to UI string mappings for forms & dialogs + + aDisplayNames.emplace_back( "approveAction", RID_SVXSTR_EVENT_APPROVEACTIONPERFORMED ); + aDisplayNames.emplace_back( "actionPerformed", RID_SVXSTR_EVENT_ACTIONPERFORMED ); + aDisplayNames.emplace_back( "changed", RID_SVXSTR_EVENT_CHANGED ); + aDisplayNames.emplace_back( "textChanged", RID_SVXSTR_EVENT_TEXTCHANGED ); + aDisplayNames.emplace_back( "itemStateChanged", RID_SVXSTR_EVENT_ITEMSTATECHANGED ); + aDisplayNames.emplace_back( "focusGained", RID_SVXSTR_EVENT_FOCUSGAINED ); + aDisplayNames.emplace_back( "focusLost", RID_SVXSTR_EVENT_FOCUSLOST ); + aDisplayNames.emplace_back( "keyPressed", RID_SVXSTR_EVENT_KEYTYPED ); + aDisplayNames.emplace_back( "keyReleased", RID_SVXSTR_EVENT_KEYUP ); + aDisplayNames.emplace_back( "mouseEntered", RID_SVXSTR_EVENT_MOUSEENTERED ); + aDisplayNames.emplace_back( "mouseDragged", RID_SVXSTR_EVENT_MOUSEDRAGGED ); + aDisplayNames.emplace_back( "mouseMoved", RID_SVXSTR_EVENT_MOUSEMOVED ); + aDisplayNames.emplace_back( "mousePressed", RID_SVXSTR_EVENT_MOUSEPRESSED ); + aDisplayNames.emplace_back( "mouseReleased", RID_SVXSTR_EVENT_MOUSERELEASED ); + aDisplayNames.emplace_back( "mouseExited", RID_SVXSTR_EVENT_MOUSEEXITED ); + aDisplayNames.emplace_back( "approveReset", RID_SVXSTR_EVENT_APPROVERESETTED ); + aDisplayNames.emplace_back( "resetted", RID_SVXSTR_EVENT_RESETTED ); + aDisplayNames.emplace_back( "approveSubmit", RID_SVXSTR_EVENT_SUBMITTED ); + aDisplayNames.emplace_back( "approveUpdate", RID_SVXSTR_EVENT_BEFOREUPDATE ); + aDisplayNames.emplace_back( "updated", RID_SVXSTR_EVENT_AFTERUPDATE ); + aDisplayNames.emplace_back( "loaded", RID_SVXSTR_EVENT_LOADED ); + aDisplayNames.emplace_back( "reloading", RID_SVXSTR_EVENT_RELOADING ); + aDisplayNames.emplace_back( "reloaded", RID_SVXSTR_EVENT_RELOADED ); + aDisplayNames.emplace_back( "unloading", RID_SVXSTR_EVENT_UNLOADING ); + aDisplayNames.emplace_back( "unloaded", RID_SVXSTR_EVENT_UNLOADED ); + aDisplayNames.emplace_back( "confirmDelete", RID_SVXSTR_EVENT_CONFIRMDELETE ); + aDisplayNames.emplace_back( "approveRowChange", RID_SVXSTR_EVENT_APPROVEROWCHANGE ); + aDisplayNames.emplace_back( "rowChanged", RID_SVXSTR_EVENT_ROWCHANGE ); + aDisplayNames.emplace_back( "approveCursorMove", RID_SVXSTR_EVENT_POSITIONING ); + aDisplayNames.emplace_back( "cursorMoved", RID_SVXSTR_EVENT_POSITIONED ); + aDisplayNames.emplace_back( "approveParameter", RID_SVXSTR_EVENT_APPROVEPARAMETER ); + aDisplayNames.emplace_back( "errorOccured", RID_SVXSTR_EVENT_ERROROCCURRED ); + aDisplayNames.emplace_back( "adjustmentValueChanged", RID_SVXSTR_EVENT_ADJUSTMENTVALUECHANGED ); +} + +// the following method is called when the user clicks OK +// We use the contents of the hashes to replace the settings +bool SvxMacroTabPage_::FillItemSet( SfxItemSet* /*rSet*/ ) +{ + try + { + OUString eventName; + if( m_xAppEvents.is() ) + { + for (auto const& appEvent : m_appEventsHash) + { + eventName = appEvent.first; + try + { + m_xAppEvents->replaceByName( eventName, GetPropsByName( eventName, m_appEventsHash ) ); + } + catch (const Exception&) + { + DBG_UNHANDLED_EXCEPTION("cui.customize"); + } + } + } + if( m_xDocEvents.is() && bDocModified ) + { + for (auto const& docEvent : m_docEventsHash) + { + eventName = docEvent.first; + try + { + m_xDocEvents->replaceByName( eventName, GetPropsByName( eventName, m_docEventsHash ) ); + } + catch (const Exception&) + { + DBG_UNHANDLED_EXCEPTION("cui.customize"); + } + } + // if we have a valid XModifiable (in the case of doc events) + // call setModified(true) + // in principle this should not be necessary (see issue ??) + if(m_xModifiable.is()) + { + m_xModifiable->setModified( true ); + } + } + } + catch (const Exception&) + { + } + // what is the return value about?? + return false; +} + +// the following method clears the bindings in the hashes for both doc & app +void SvxMacroTabPage_::Reset( const SfxItemSet* ) +{ + // called once in creation - don't reset the data this time + if(!bInitialized) + { + bInitialized = true; + return; + } + + try + { + if( m_xAppEvents.is() ) + { + for (auto & appEvent : m_appEventsHash) + { + appEvent.second.second.clear(); + } + } + if( m_xDocEvents.is() && bDocModified ) + { + for (auto & docEvent : m_docEventsHash) + { + docEvent.second.second.clear(); + } + // if we have a valid XModifiable (in the case of doc events) + // call setModified(true) + if(m_xModifiable.is()) + { + m_xModifiable->setModified( true ); + } + } + } + catch (const Exception&) + { + } + DisplayAppEvents(bAppEvents); +} + +void SvxMacroTabPage_::SetReadOnly( bool bSet ) +{ + mpImpl->bReadOnly = bSet; +} + +bool SvxMacroTabPage_::IsReadOnly() const +{ + return mpImpl->bReadOnly; +} + +namespace +{ + OUString GetEventDisplayText(const OUString &rURL) + { + if (rURL.isEmpty()) + return OUString(); + sal_Int32 nIndex = rURL.indexOf(aVndSunStarUNO); + bool bUNO = nIndex == 0; + OUString aPureMethod; + if (bUNO) + { + aPureMethod = rURL.copy(strlen(aVndSunStarUNO)); + } + else + { + aPureMethod = rURL.copy(strlen("vnd.sun.star.script:")); + aPureMethod = aPureMethod.copy( 0, aPureMethod.indexOf( '?' ) ); + } + return aPureMethod; + } + + OUString GetEventDisplayImage(const OUString &rURL) + { + if (rURL.isEmpty()) + return OUString(); + sal_Int32 nIndex = rURL.indexOf(aVndSunStarUNO); + bool bUNO = nIndex == 0; + return bUNO ? OUString(RID_SVXBMP_COMPONENT) : OUString(RID_SVXBMP_MACRO); + } +} + +// displays the app events if appEvents=true, otherwise displays the doc events +void SvxMacroTabPage_::DisplayAppEvents( bool appEvents) +{ + bAppEvents = appEvents; + + mpImpl->xEventLB->freeze(); + mpImpl->xEventLB->clear(); + EventsHash* eventsHash; + Reference< container::XNameReplace> nameReplace; + if(bAppEvents) + { + eventsHash = &m_appEventsHash; + nameReplace = m_xAppEvents; + } + else + { + eventsHash = &m_docEventsHash; + nameReplace = m_xDocEvents; + } + // have to use the original XNameReplace since the hash iterators do + // not guarantee the order in which the elements are returned + if(!nameReplace.is()) + return; + + Sequence< OUString > eventNames = nameReplace->getElementNames(); + std::set< OUString > aEventNamesCache; + std::copy( + eventNames.begin(), + eventNames.end(), + std::insert_iterator< std::set< OUString > >( aEventNamesCache, aEventNamesCache.end() ) + ); + + for (auto const& displayableEvent : aDisplayNames) + { + OUString sEventName( OUString::createFromAscii( displayableEvent.pAsciiEventName ) ); + if ( !nameReplace->hasByName( sEventName ) ) + continue; + + EventsHash::iterator h_it = eventsHash->find( sEventName ); + if( h_it == eventsHash->end() ) + { + OSL_FAIL( "SvxMacroTabPage_::DisplayAppEvents: something's suspicious here!" ); + continue; + } + + OUString eventURL = h_it->second.second; + OUString displayName(CuiResId(displayableEvent.pEventResourceID)); + + int nRow = mpImpl->xEventLB->n_children(); + mpImpl->xEventLB->append(sEventName, displayName); + mpImpl->xEventLB->set_image(nRow, GetEventDisplayImage(eventURL), 1); + mpImpl->xEventLB->set_text(nRow, GetEventDisplayText(eventURL), 2); + } + + mpImpl->xEventLB->thaw(); + + if (mpImpl->xEventLB->n_children()) + { + mpImpl->xEventLB->select(0); + mpImpl->xEventLB->scroll_to_row(0); + } + + EnableButtons(); +} + +// select event handler on the listbox +IMPL_LINK_NOARG( SvxMacroTabPage_, SelectEvent_Impl, weld::TreeView&, void) +{ + int nEntry = mpImpl->xEventLB->get_selected_index(); + + if (nEntry == -1) + { + DBG_ASSERT(false, "Where does the empty entry come from?" ); + return; + } + + EnableButtons(); +} + +IMPL_LINK( SvxMacroTabPage_, AssignDeleteHdl_Impl, weld::Button&, rBtn, void ) +{ + GenericHandler_Impl(this, &rBtn); +} + +IMPL_LINK_NOARG( SvxMacroTabPage_, DoubleClickHdl_Impl, weld::TreeView&, bool) +{ + GenericHandler_Impl(this, nullptr); + return true; +} + +// handler for double click on the listbox, and for the assign/delete buttons +void SvxMacroTabPage_::GenericHandler_Impl(SvxMacroTabPage_* pThis, const weld::Button* pBtn) +{ + SvxMacroTabPage_Impl* pImpl = pThis->mpImpl.get(); + weld::TreeView& rListBox = *pImpl->xEventLB; + int nEntry = rListBox.get_selected_index(); + if (nEntry == -1) + { + DBG_ASSERT(false, "Where does the empty entry come from?"); + return; + } + + const bool bAssEnabled = pBtn != pImpl->xDeletePB.get() && pImpl->xAssignPB->get_sensitive(); + + OUString sEventName = rListBox.get_id(nEntry); + + OUString sEventURL; + OUString sEventType; + if(pThis->bAppEvents) + { + EventsHash::iterator h_it = pThis->m_appEventsHash.find(sEventName); + if(h_it != pThis->m_appEventsHash.end() ) + { + sEventType = h_it->second.first; + sEventURL = h_it->second.second; + } + } + else + { + EventsHash::iterator h_it = pThis->m_docEventsHash.find(sEventName); + if(h_it != pThis->m_docEventsHash.end() ) + { + sEventType = h_it->second.first; + sEventURL = h_it->second.second; + } + } + + bool bDoubleClick = (pBtn == nullptr); + bool bUNOAssigned = sEventURL.startsWith( aVndSunStarUNO ); + if( pBtn == pImpl->xDeletePB.get() ) + { + // delete pressed + sEventType = "Script" ; + sEventURL.clear(); + if(!pThis->bAppEvents) + pThis->bDocModified = true; + } + else if ( ( ( pBtn != nullptr ) + && ( pBtn == pImpl->xAssignComponentPB.get() ) + ) + || ( bDoubleClick + && bUNOAssigned + ) + ) + { + AssignComponentDialog aAssignDlg(pThis->GetFrameWeld(), sEventURL); + + short ret = aAssignDlg.run(); + if( ret ) + { + sEventType = "UNO"; + sEventURL = aAssignDlg.getURL(); + if(!pThis->bAppEvents) + pThis->bDocModified = true; + } + } + else if( bAssEnabled ) + { + // assign pressed + SvxScriptSelectorDialog aDlg(pThis->GetFrameWeld(), pThis->GetFrame()); + short ret = aDlg.run(); + if ( ret ) + { + sEventType = "Script"; + sEventURL = aDlg.GetScriptURL(); + if(!pThis->bAppEvents) + pThis->bDocModified = true; + } + } + + // update the hashes + if(pThis->bAppEvents) + { + EventsHash::iterator h_it = pThis->m_appEventsHash.find(sEventName); + h_it->second.first = sEventType; + h_it->second.second = sEventURL; + } + else + { + EventsHash::iterator h_it = pThis->m_docEventsHash.find(sEventName); + h_it->second.first = sEventType; + h_it->second.second = sEventURL; + } + + rListBox.set_image(nEntry, GetEventDisplayImage(sEventURL), 1); + rListBox.set_text(nEntry, GetEventDisplayText(sEventURL), 2); + + rListBox.select(nEntry ); + rListBox.scroll_to_row(nEntry); + + pThis->EnableButtons(); +} + +// pass in the XNameReplace. +// can remove the 3rd arg once issue ?? is fixed +void SvxMacroTabPage_::InitAndSetHandler( const Reference< container::XNameReplace>& xAppEvents, const Reference< container::XNameReplace>& xDocEvents, const Reference< util::XModifiable >& xModifiable ) +{ + m_xAppEvents = xAppEvents; + m_xDocEvents = xDocEvents; + m_xModifiable = xModifiable; + Link aLnk(LINK(this, SvxMacroTabPage_, AssignDeleteHdl_Impl )); + mpImpl->xDeletePB->connect_clicked(aLnk); + mpImpl->xAssignPB->connect_clicked(aLnk); + if( mpImpl->xAssignComponentPB ) + mpImpl->xAssignComponentPB->connect_clicked( aLnk ); + mpImpl->xEventLB->connect_row_activated( LINK(this, SvxMacroTabPage_, DoubleClickHdl_Impl ) ); + mpImpl->xEventLB->connect_changed( LINK( this, SvxMacroTabPage_, SelectEvent_Impl )); + + std::vector aWidths; + aWidths.push_back(mpImpl->xEventLB->get_approximate_digit_width() * 32); + aWidths.push_back(mpImpl->xEventLB->get_checkbox_column_width()); + mpImpl->xEventLB->set_column_fixed_widths(aWidths); + + mpImpl->xEventLB->show(); + mpImpl->xEventLB->set_sensitive(true); + + if(!m_xAppEvents.is()) + { + return; + } + Sequence< OUString > eventNames = m_xAppEvents->getElementNames(); + sal_Int32 nEventCount = eventNames.getLength(); + for(sal_Int32 nEvent = 0; nEvent < nEventCount; ++nEvent ) + { + //need exception handling here + try + { + m_appEventsHash[ eventNames[nEvent] ] = GetPairFromAny( m_xAppEvents->getByName( eventNames[nEvent] ) ); + } + catch (const Exception&) + { + } + } + if(!m_xDocEvents.is()) + return; + + eventNames = m_xDocEvents->getElementNames(); + nEventCount = eventNames.getLength(); + for(sal_Int32 nEvent = 0; nEvent < nEventCount; ++nEvent ) + { + try + { + m_docEventsHash[ eventNames[nEvent] ] = GetPairFromAny( m_xDocEvents->getByName( eventNames[nEvent] ) ); + } + catch (const Exception&) + { + } + } +} + +// returns the two props EventType & Script for a given event name +Any SvxMacroTabPage_::GetPropsByName( const OUString& eventName, EventsHash& eventsHash ) +{ + const std::pair< OUString, OUString >& rAssignedEvent( eventsHash[ eventName ] ); + + Any aReturn; + ::comphelper::NamedValueCollection aProps; + if ( !(rAssignedEvent.first.isEmpty() || rAssignedEvent.second.isEmpty()) ) + { + aProps.put( "EventType", rAssignedEvent.first ); + aProps.put( "Script", rAssignedEvent.second ); + } + aReturn <<= aProps.getPropertyValues(); + + return aReturn; +} + +// converts the Any returned by GetByName into a pair which can be stored in +// the EventHash +std::pair< OUString, OUString > SvxMacroTabPage_::GetPairFromAny( const Any& aAny ) +{ + Sequence< beans::PropertyValue > props; + OUString type, url; + if( aAny >>= props ) + { + ::comphelper::NamedValueCollection aProps( props ); + type = aProps.getOrDefault( "EventType", type ); + url = aProps.getOrDefault( "Script", url ); + } + return std::make_pair( type, url ); +} + +SvxMacroTabPage::SvxMacroTabPage(weld::Container* pPage, weld::DialogController* pController, + const Reference< frame::XFrame >& _rxDocumentFrame, + const SfxItemSet& rSet, + Reference< container::XNameReplace > const & xNameReplace, + sal_uInt16 nSelectedIndex) + : SvxMacroTabPage_(pPage, pController, "cui/ui/macroassignpage.ui", "MacroAssignPage", rSet) +{ + mpImpl->xEventLB = m_xBuilder->weld_tree_view("assignments"); + mpImpl->xEventLB->set_size_request(mpImpl->xEventLB->get_approximate_digit_width() * 70, + mpImpl->xEventLB->get_height_rows(9)); + mpImpl->xAssignPB = m_xBuilder->weld_button("assign"); + mpImpl->xDeletePB = m_xBuilder->weld_button("delete"); + mpImpl->xAssignComponentPB = m_xBuilder->weld_button("component"); + + SetFrame( _rxDocumentFrame ); + + if( !mpImpl->bIDEDialogMode ) + { + mpImpl->xAssignComponentPB->hide(); + mpImpl->xAssignComponentPB->set_sensitive(false); + } + + InitResources(); + + InitAndSetHandler( xNameReplace, Reference< container::XNameReplace>(nullptr), Reference< util::XModifiable >(nullptr)); + DisplayAppEvents(true); + mpImpl->xEventLB->select(nSelectedIndex); +} + +SvxMacroAssignDlg::SvxMacroAssignDlg(weld::Window* pParent, const Reference< frame::XFrame >& _rxDocumentFrame, const SfxItemSet& rSet, + const Reference< container::XNameReplace >& xNameReplace, sal_uInt16 nSelectedIndex) + : SvxMacroAssignSingleTabDialog(pParent, rSet) +{ + SetTabPage(std::make_unique(get_content_area(), this, _rxDocumentFrame, rSet, xNameReplace, nSelectedIndex)); +} + +IMPL_LINK_NOARG(AssignComponentDialog, ButtonHandler, weld::Button&, void) +{ + OUString aMethodName = mxMethodEdit->get_text(); + maURL.clear(); + if( !aMethodName.isEmpty() ) + { + maURL = aVndSunStarUNO; + maURL += aMethodName; + } + m_xDialog->response(RET_OK); +} + +AssignComponentDialog::AssignComponentDialog(weld::Window* pParent, const OUString& rURL) + : GenericDialogController(pParent, "cui/ui/assigncomponentdialog.ui", "AssignComponent") + , maURL( rURL ) + , mxMethodEdit(m_xBuilder->weld_entry("methodEntry")) + , mxOKButton(m_xBuilder->weld_button("ok")) +{ + mxOKButton->connect_clicked(LINK(this, AssignComponentDialog, ButtonHandler)); + + OUString aMethodName; + if( maURL.startsWith( aVndSunStarUNO ) ) + { + aMethodName = maURL.copy( strlen(aVndSunStarUNO) ); + } + mxMethodEdit->set_text(aMethodName); + mxMethodEdit->select_region(0, -1); +} + +AssignComponentDialog::~AssignComponentDialog() +{ +} + +IMPL_LINK_NOARG(SvxMacroAssignSingleTabDialog, OKHdl_Impl, weld::Button&, void) +{ + m_xSfxPage->FillItemSet(nullptr); + m_xDialog->response(RET_OK); +} + +SvxMacroAssignSingleTabDialog::SvxMacroAssignSingleTabDialog(weld::Window *pParent, + const SfxItemSet& rSet) + : SfxSingleTabDialogController(pParent, &rSet, "cui/ui/macroassigndialog.ui", "MacroAssignDialog") +{ + GetOKButton().connect_clicked(LINK(this, SvxMacroAssignSingleTabDialog, OKHdl_Impl)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/customize/macropg_impl.hxx b/cui/source/customize/macropg_impl.hxx new file mode 100644 index 000000000..2a36d0f5c --- /dev/null +++ b/cui/source/customize/macropg_impl.hxx @@ -0,0 +1,55 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include +#include + +class SvxMacroTabPage_Impl +{ +public: + explicit SvxMacroTabPage_Impl( const SfxItemSet& rAttrSet ); + + std::unique_ptr xAssignPB; + std::unique_ptr xAssignComponentPB; + std::unique_ptr xDeletePB; + std::unique_ptr xEventLB; + bool bReadOnly; + bool bIDEDialogMode; +}; + +class AssignComponentDialog : public weld::GenericDialogController +{ +private: + OUString maURL; + + std::unique_ptr mxMethodEdit; + std::unique_ptr mxOKButton; + + DECL_LINK(ButtonHandler, weld::Button&, void); + +public: + AssignComponentDialog(weld::Window* pParent, const OUString& rURL); + virtual ~AssignComponentDialog() override; + + const OUString& getURL() const { return maURL; } +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/DiagramDialog.cxx b/cui/source/dialogs/DiagramDialog.cxx new file mode 100644 index 000000000..f3a4a069a --- /dev/null +++ b/cui/source/dialogs/DiagramDialog.cxx @@ -0,0 +1,81 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* +* This file is part of the LibreOffice project. +* +* This Source Code Form is subject to the terms of the Mozilla Public +* License, v. 2.0. If a copy of the MPL was not distributed with this +* file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#include + +#include +#include +#include + +DiagramDialog::DiagramDialog(weld::Window* pWindow, + std::shared_ptr pDiagramData) + : GenericDialogController(pWindow, "cui/ui/diagramdialog.ui", "DiagramDialog") + , mpDiagramData(pDiagramData) + , mpBtnOk(m_xBuilder->weld_button("btnOk")) + , mpBtnCancel(m_xBuilder->weld_button("btnCancel")) + , mpBtnAdd(m_xBuilder->weld_button("btnAdd")) + , mpBtnRemove(m_xBuilder->weld_button("btnRemove")) + , mpTreeDiagram(m_xBuilder->weld_tree_view("treeDiagram")) + , mpTextAdd(m_xBuilder->weld_text_view("textAdd")) +{ + mpBtnAdd->connect_clicked(LINK(this, DiagramDialog, OnAddClick)); + mpBtnRemove->connect_clicked(LINK(this, DiagramDialog, OnRemoveClick)); + + populateTree(nullptr, OUString()); + + // expand all items + weld::TreeView* pTreeDiagram = mpTreeDiagram.get(); + pTreeDiagram->all_foreach([pTreeDiagram](weld::TreeIter& rEntry) { + pTreeDiagram->expand_row(rEntry); + return false; + }); +} + +IMPL_LINK_NOARG(DiagramDialog, OnAddClick, weld::Button&, void) +{ + OUString sText = mpTextAdd->get_text(); + if (!sText.isEmpty()) + { + OUString sNodeId = mpDiagramData->addNode(sText); + std::unique_ptr pEntry(mpTreeDiagram->make_iterator()); + mpTreeDiagram->insert(nullptr, -1, &sText, &sNodeId, nullptr, nullptr, nullptr, false, + pEntry.get()); + mpTreeDiagram->select(*pEntry); + comphelper::dispatchCommand(".uno:RegenerateDiagram", {}); + } +} + +IMPL_LINK_NOARG(DiagramDialog, OnRemoveClick, weld::Button&, void) +{ + std::unique_ptr pEntry(mpTreeDiagram->make_iterator()); + if (mpTreeDiagram->get_selected(pEntry.get())) + { + if (mpDiagramData->removeNode(mpTreeDiagram->get_id(*pEntry))) + { + mpTreeDiagram->remove(*pEntry); + comphelper::dispatchCommand(".uno:RegenerateDiagram", {}); + } + } +} + +void DiagramDialog::populateTree(const weld::TreeIter* pParent, const OUString& rParentId) +{ + auto aItems = mpDiagramData->getChildren(rParentId); + for (auto& aItem : aItems) + { + std::unique_ptr pEntry(mpTreeDiagram->make_iterator()); + mpTreeDiagram->insert(pParent, -1, &aItem.second, &aItem.first, nullptr, nullptr, nullptr, + false, pEntry.get()); + populateTree(pEntry.get(), aItem.first); + } +} + +DiagramDialog::~DiagramDialog() {} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/FontFeaturesDialog.cxx b/cui/source/dialogs/FontFeaturesDialog.cxx new file mode 100644 index 000000000..a34912d5d --- /dev/null +++ b/cui/source/dialogs/FontFeaturesDialog.cxx @@ -0,0 +1,227 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#include +#include +#include +#include +#include +#include + +using namespace css; + +namespace cui +{ +FontFeaturesDialog::FontFeaturesDialog(weld::Window* pParent, OUString const& rFontName) + : GenericDialogController(pParent, "cui/ui/fontfeaturesdialog.ui", "FontFeaturesDialog") + , m_sFontName(rFontName) + , m_xContentWindow(m_xBuilder->weld_scrolled_window("contentWindow")) + , m_xContentGrid(m_xBuilder->weld_container("contentGrid")) + , m_xPreviewWindow(new weld::CustomWeld(*m_xBuilder, "preview", m_aPreviewWindow)) +{ + svtools::ColorConfig aColorConfig; + Color aFillColor(aColorConfig.GetColorValue(svtools::DOCCOLOR).nColor); + m_aPreviewWindow.SetBackColor(aFillColor); + initialize(); +} + +FontFeaturesDialog::~FontFeaturesDialog() {} + +static sal_Int32 makeEnumComboBox(weld::ComboBox& rNameBox, + vcl::font::FeatureDefinition const& rFeatureDefinition, + uint32_t nDefault) +{ + sal_Int32 nRes = 0; + int count = 0; + for (vcl::font::FeatureParameter const& rParameter : rFeatureDefinition.getEnumParameters()) + { + rNameBox.append(OUString::number(rParameter.getCode()), rParameter.getDescription()); + if (rParameter.getCode() == nDefault) + nRes = count; + ++count; + } + return nRes; +} + +void FontFeaturesDialog::initialize() +{ + ScopedVclPtrInstance aVDev(*Application::GetDefaultDevice(), + DeviceFormat::DEFAULT, DeviceFormat::DEFAULT); + aVDev->SetOutputSizePixel(Size(10, 10)); + + vcl::Font aFont = aVDev->GetFont(); + aFont.SetFamilyName(m_sFontName); + aVDev->SetFont(aFont); + + std::vector rFontFeatures; + + if (!aVDev->GetFontFeatures(rFontFeatures)) + return; + + std::unordered_set aDoneFeatures; + std::vector rFilteredFontFeatures; + + for (vcl::font::Feature const& rFontFeature : rFontFeatures) + { + sal_uInt32 nFontFeatureCode = rFontFeature.m_aID.m_aFeatureCode; + if (!aDoneFeatures.insert(nFontFeatureCode).second) + continue; + rFilteredFontFeatures.push_back(rFontFeature); + } + + fillGrid(rFilteredFontFeatures); + + updateFontPreview(); +} + +void FontFeaturesDialog::fillGrid(std::vector const& rFontFeatures) +{ + vcl::font::FeatureParser aParser(m_sFontName); + auto aExistingFeatures = aParser.getFeaturesMap(); + + sal_Int32 i = 0; + for (vcl::font::Feature const& rFontFeature : rFontFeatures) + { + sal_uInt32 nFontFeatureCode = rFontFeature.m_aID.m_aFeatureCode; + + vcl::font::FeatureDefinition aDefinition; + if (rFontFeature.m_aDefinition) + aDefinition = rFontFeature.m_aDefinition; + if (!aDefinition) + aDefinition = { nFontFeatureCode, nullptr }; + + m_aFeatureItems.emplace_back(m_xContentGrid.get()); + + uint32_t nValue = 0; + if (aExistingFeatures.find(nFontFeatureCode) != aExistingFeatures.end()) + nValue = aExistingFeatures.at(nFontFeatureCode); + else + nValue = aDefinition.getDefault(); + + FontFeatureItem& aCurrentItem = m_aFeatureItems.back(); + aCurrentItem.m_aFeatureCode = nFontFeatureCode; + aCurrentItem.m_nDefault = aDefinition.getDefault(); + + sal_Int32 nGridPositionX = (i % 2) * 2; + sal_Int32 nGridPositionY = i / 2; + aCurrentItem.m_xContainer->set_grid_left_attach(nGridPositionX); + aCurrentItem.m_xContainer->set_grid_top_attach(nGridPositionY); + + Link aComboBoxSelectHandler + = LINK(this, FontFeaturesDialog, ComboBoxSelectedHdl); + Link aCheckBoxToggleHandler + = LINK(this, FontFeaturesDialog, CheckBoxToggledHdl); + + if (aDefinition.getType() == vcl::font::FeatureParameterType::ENUM) + { + aCurrentItem.m_xText->set_label(aDefinition.getDescription()); + aCurrentItem.m_xText->show(); + + sal_Int32 nInit = makeEnumComboBox(*aCurrentItem.m_xCombo, aDefinition, nValue); + + aCurrentItem.m_xCombo->set_active(nInit); + aCurrentItem.m_xCombo->connect_changed(aComboBoxSelectHandler); + aCurrentItem.m_xCombo->show(); + } + else + { + aCurrentItem.m_xCheck->set_active(nValue > 0); + aCurrentItem.m_xCheck->set_label(aDefinition.getDescription()); + aCurrentItem.m_xCheck->connect_toggled(aCheckBoxToggleHandler); + aCurrentItem.m_xCheck->show(); + } + + i++; + } +} + +void FontFeaturesDialog::updateFontPreview() +{ + vcl::Font rPreviewFont = m_aPreviewWindow.GetFont(); + vcl::Font rPreviewFontCJK = m_aPreviewWindow.GetCJKFont(); + vcl::Font rPreviewFontCTL = m_aPreviewWindow.GetCTLFont(); + + OUString sNewFontName = createFontNameWithFeatures(); + + rPreviewFont.SetFamilyName(sNewFontName); + rPreviewFontCJK.SetFamilyName(sNewFontName); + rPreviewFontCTL.SetFamilyName(sNewFontName); + + m_aPreviewWindow.SetFont(rPreviewFont, rPreviewFontCJK, rPreviewFontCTL); +} + +IMPL_LINK_NOARG(FontFeaturesDialog, CheckBoxToggledHdl, weld::ToggleButton&, void) +{ + updateFontPreview(); +} + +IMPL_LINK_NOARG(FontFeaturesDialog, ComboBoxSelectedHdl, weld::ComboBox&, void) +{ + updateFontPreview(); +} + +OUString FontFeaturesDialog::createFontNameWithFeatures() +{ + OUString sResultFontName; + OUStringBuffer sNameSuffix; + bool bFirst = true; + + for (const FontFeatureItem& rItem : m_aFeatureItems) + { + if (rItem.m_xCheck->get_visible()) + { + if (sal_uInt32(rItem.m_xCheck->get_active()) != rItem.m_nDefault) + { + if (!bFirst) + sNameSuffix.append(OUString(vcl::font::FeatureSeparator)); + else + bFirst = false; + + sNameSuffix.append(vcl::font::featureCodeAsString(rItem.m_aFeatureCode)); + if (!rItem.m_xCheck->get_active()) + sNameSuffix.append("=0"); + } + } + else if (rItem.m_xCombo->get_visible() && rItem.m_xText->get_visible()) + { + sal_Int32 nSelection = rItem.m_xCombo->get_active_id().toInt32(); + if (nSelection != int(rItem.m_nDefault)) + { + if (!bFirst) + sNameSuffix.append(OUString(vcl::font::FeatureSeparator)); + else + bFirst = false; + + sNameSuffix.append(vcl::font::featureCodeAsString(rItem.m_aFeatureCode)); + sNameSuffix.append("="); + sNameSuffix.append(OUString::number(nSelection)); + } + } + } + sResultFontName = vcl::font::trimFontNameFeatures(m_sFontName); + if (!sNameSuffix.isEmpty()) + sResultFontName + += OUStringChar(vcl::font::FeaturePrefix) + sNameSuffix.makeStringAndClear(); + return sResultFontName; +} + +short FontFeaturesDialog::run() +{ + short nResult = GenericDialogController::run(); + if (nResult == RET_OK) + { + m_sResultFontName = createFontNameWithFeatures(); + } + return nResult; +} + +} // end svx namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/QrCodeGenDialog.cxx b/cui/source/dialogs/QrCodeGenDialog.cxx new file mode 100644 index 000000000..7f3f6a806 --- /dev/null +++ b/cui/source/dialogs/QrCodeGenDialog.cxx @@ -0,0 +1,341 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#if ENABLE_QRCODEGEN +#if defined(SYSTEM_QRCODEGEN) +#include +#else +#include +#endif +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace css; +using namespace css::uno; +using namespace css::beans; +using namespace css::container; +using namespace css::frame; +using namespace css::io; +using namespace css::lang; +using namespace css::frame; +using namespace css::sheet; +using namespace css::text; +using namespace css::drawing; +using namespace css::graphic; +#if ENABLE_QRCODEGEN +using namespace qrcodegen; +#endif + +QrCodeGenDialog::QrCodeGenDialog(weld::Widget* pParent, Reference xModel, + bool bEditExisting) + : GenericDialogController(pParent, "cui/ui/qrcodegen.ui", "QrCodeGenDialog") + , m_xModel(std::move(xModel)) + , m_xEdittext(m_xBuilder->weld_entry("edit_text")) + , m_xECC{ m_xBuilder->weld_radio_button("button_low"), + m_xBuilder->weld_radio_button("button_medium"), + m_xBuilder->weld_radio_button("button_quartile"), + m_xBuilder->weld_radio_button("button_high") } + , m_xSpinBorder(m_xBuilder->weld_spin_button("edit_border")) +#if ENABLE_QRCODEGEN + , mpParent(pParent) +#endif +{ + if (!bEditExisting) + { + // TODO: This only works in Writer doc. Should also work in shapes + Reference xSelections(m_xModel->getCurrentSelection(), UNO_QUERY); + if (xSelections.is()) + { + Reference xSelection(xSelections->getByIndex(0), UNO_QUERY); + if (xSelection.is()) + m_xEdittext->set_text(xSelection->getString()); + } + return; + } + + Reference xIndexAccess(m_xModel->getCurrentSelection(), + UNO_QUERY_THROW); + Reference xProps(xIndexAccess->getByIndex(0), UNO_QUERY_THROW); + + // Read properties from selected QR Code + css::drawing::QRCode aQRCode; + xProps->getPropertyValue("QRCodeProperties") >>= aQRCode; + + m_xEdittext->set_text(aQRCode.Payload); + + //Get Error Correction Constant from selected QR Code + GetErrorCorrection(aQRCode.ErrorCorrection); + + m_xSpinBorder->set_value(aQRCode.Border); + + // Mark this as existing shape + m_xExistingShapeProperties = xProps; +} + +short QrCodeGenDialog::run() +{ +#if ENABLE_QRCODEGEN + short nRet; + while (true) + { + nRet = GenericDialogController::run(); + if (nRet == RET_OK) + { + try + { + Apply(); + break; + } + catch (const qrcodegen::data_too_long&) + { + std::unique_ptr xBox(Application::CreateMessageDialog( + mpParent, VclMessageType::Warning, VclButtonsType::Ok, + CuiResId(RID_SVXSTR_QRCODEDATALONG))); + xBox->run(); + } + } + else + break; + } + return nRet; +#else + return RET_CANCEL; +#endif +} + +void QrCodeGenDialog::Apply() +{ +#if ENABLE_QRCODEGEN + css::drawing::QRCode aQRCode; + aQRCode.Payload = m_xEdittext->get_text(); + + bool bLowECCActive(m_xECC[0]->get_active()); + bool bMediumECCActive(m_xECC[1]->get_active()); + bool bQuartileECCActive(m_xECC[2]->get_active()); + + if (bLowECCActive) + { + aQRCode.ErrorCorrection = css::drawing::QRCodeErrorCorrection::LOW; + } + else if (bMediumECCActive) + { + aQRCode.ErrorCorrection = css::drawing::QRCodeErrorCorrection::MEDIUM; + } + else if (bQuartileECCActive) + { + aQRCode.ErrorCorrection = css::drawing::QRCodeErrorCorrection::QUARTILE; + } + else + { + aQRCode.ErrorCorrection = css::drawing::QRCodeErrorCorrection::HIGH; + } + + aQRCode.Border = m_xSpinBorder->get_value(); + + // Read svg and replace placeholder texts + OUString aSvgImage = GenerateQRCode(aQRCode.Payload, aQRCode.ErrorCorrection, aQRCode.Border); + + // Insert/Update graphic + SvMemoryStream aSvgStream(4096, 4096); + aSvgStream.WriteOString(OUStringToOString(aSvgImage, RTL_TEXTENCODING_UTF8)); + Reference xInputStream(new utl::OSeekableInputStreamWrapper(aSvgStream)); + Reference xContext(comphelper::getProcessComponentContext()); + Reference xProvider = css::graphic::GraphicProvider::create(xContext); + + Sequence aMediaProperties(1); + aMediaProperties[0].Name = "InputStream"; + aMediaProperties[0].Value <<= xInputStream; + Reference xGraphic(xProvider->queryGraphic(aMediaProperties)); + + bool bIsExistingQRCode = m_xExistingShapeProperties.is(); + Reference xShapeProps; + if (bIsExistingQRCode) + xShapeProps = m_xExistingShapeProperties; + else + xShapeProps.set(Reference(m_xModel, UNO_QUERY_THROW) + ->createInstance("com.sun.star.drawing.GraphicObjectShape"), + UNO_QUERY); + + xShapeProps->setPropertyValue("Graphic", Any(xGraphic)); + + // Set QRCode properties + xShapeProps->setPropertyValue("QRCodeProperties", Any(aQRCode)); + + if (bIsExistingQRCode) + return; + + // Default size + Reference xShape(xShapeProps, UNO_QUERY); + awt::Size aShapeSize; + aShapeSize.Height = 4000; + aShapeSize.Width = 4000; + xShape->setSize(aShapeSize); + + // Default anchoring + xShapeProps->setPropertyValue("AnchorType", Any(TextContentAnchorType_AT_PARAGRAPH)); + + const Reference xServiceInfo(m_xModel, UNO_QUERY_THROW); + + // Writer + if (xServiceInfo->supportsService("com.sun.star.text.TextDocument")) + { + Reference xTextContent(xShape, UNO_QUERY_THROW); + Reference xViewCursorSupplier(m_xModel->getCurrentController(), + UNO_QUERY_THROW); + Reference xCursor = xViewCursorSupplier->getViewCursor(); + // use cursor's XText - it might be in table cell, frame, ... + Reference const xText(xCursor->getText()); + assert(xText.is()); + xText->insertTextContent(xCursor, xTextContent, true); + return; + } + + // Calc + else if (xServiceInfo->supportsService("com.sun.star.sheet.SpreadsheetDocument")) + { + Reference xSheetCell(m_xModel->getCurrentSelection(), UNO_QUERY_THROW); + awt::Point aCellPosition; + xSheetCell->getPropertyValue("Position") >>= aCellPosition; + xShape->setPosition(aCellPosition); + + Reference xView(m_xModel->getCurrentController(), UNO_QUERY_THROW); + Reference xSheet(xView->getActiveSheet(), UNO_SET_THROW); + Reference xDrawPageSupplier(xSheet, UNO_QUERY_THROW); + Reference xDrawPage(xDrawPageSupplier->getDrawPage(), UNO_SET_THROW); + Reference xShapes(xDrawPage, UNO_QUERY_THROW); + + xShapes->add(xShape); + return; + } + + //Impress and Draw + else if (xServiceInfo->supportsService("com.sun.star.presentation.PresentationDocument") + || xServiceInfo->supportsService("com.sun.star.drawing.DrawingDocument")) + { + Reference xView(m_xModel->getCurrentController(), UNO_QUERY_THROW); + Reference xPage(xView->getCurrentPage(), UNO_SET_THROW); + Reference xShapes(xPage, UNO_QUERY_THROW); + + xShapes->add(xShape); + return; + } + + else + { + //Not implemented for math,base and other apps. + throw uno::RuntimeException("Not implemented"); + } +#endif +} + +OUString QrCodeGenDialog::GenerateQRCode(OUString aQRText, long aQRECC, int aQRBorder) +{ +#if ENABLE_QRCODEGEN + //Select ECC:: value from aQrECC + qrcodegen::QrCode::Ecc bqrEcc = qrcodegen::QrCode::Ecc::LOW; + + switch (aQRECC) + { + case 1: + { + bqrEcc = qrcodegen::QrCode::Ecc::LOW; + break; + } + case 2: + { + bqrEcc = qrcodegen::QrCode::Ecc::MEDIUM; + break; + } + case 3: + { + bqrEcc = qrcodegen::QrCode::Ecc::QUARTILE; + break; + } + case 4: + { + bqrEcc = qrcodegen::QrCode::Ecc::HIGH; + break; + } + } + + //OuString to char* qrtext + OString o = OUStringToOString(aQRText, RTL_TEXTENCODING_UTF8); + const char* qrtext = o.pData->buffer; + + // From QR Code library + qrcodegen::QrCode qr0 = qrcodegen::QrCode::encodeText(qrtext, bqrEcc); + std::string svg = qr0.toSvgString(aQRBorder); + //cstring to OUString + return OUString::createFromAscii(svg.c_str()); +#else + (void)aQRText; + (void)aQRECC; + (void)aQRBorder; + return OUString(); +#endif +} + +void QrCodeGenDialog::GetErrorCorrection(long ErrorCorrection) +{ + switch (ErrorCorrection) + { + case css::drawing::QRCodeErrorCorrection::LOW: + { + m_xECC[0]->set_active(true); + break; + } + case css::drawing::QRCodeErrorCorrection::MEDIUM: + { + m_xECC[1]->set_active(true); + break; + } + case css::drawing::QRCodeErrorCorrection::QUARTILE: + { + m_xECC[2]->set_active(true); + break; + } + case css::drawing::QRCodeErrorCorrection::HIGH: + { + m_xECC[3]->set_active(true); + break; + } + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/cui/source/dialogs/SignSignatureLineDialog.cxx b/cui/source/dialogs/SignSignatureLineDialog.cxx new file mode 100644 index 000000000..10f80f729 --- /dev/null +++ b/cui/source/dialogs/SignSignatureLineDialog.cxx @@ -0,0 +1,293 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace comphelper; +using namespace css; +using namespace css::uno; +using namespace css::beans; +using namespace css::frame; +using namespace css::io; +using namespace css::lang; +using namespace css::frame; +using namespace css::text; +using namespace css::graphic; +using namespace css::security; +using namespace css::ui::dialogs; + +SignSignatureLineDialog::SignSignatureLineDialog(weld::Widget* pParent, Reference xModel) + : SignatureLineDialogBase(pParent, std::move(xModel), "cui/ui/signsignatureline.ui", + "SignSignatureLineDialog") + , m_xEditName(m_xBuilder->weld_entry("edit_name")) + , m_xEditComment(m_xBuilder->weld_text_view("edit_comment")) + , m_xBtnLoadImage(m_xBuilder->weld_button("btn_load_image")) + , m_xBtnClearImage(m_xBuilder->weld_button("btn_clear_image")) + , m_xBtnChooseCertificate(m_xBuilder->weld_button("btn_select_certificate")) + , m_xBtnSign(m_xBuilder->weld_button("ok")) + , m_xLabelHint(m_xBuilder->weld_label("label_hint")) + , m_xLabelHintText(m_xBuilder->weld_label("label_hint_text")) + , m_xLabelAddComment(m_xBuilder->weld_label("label_add_comment")) + , m_bShowSignDate(false) +{ + Reference xIndexAccess(m_xModel->getCurrentSelection(), + UNO_QUERY_THROW); + m_xShapeProperties.set(xIndexAccess->getByIndex(0), UNO_QUERY_THROW); + + bool bIsSignatureLine(false); + m_xShapeProperties->getPropertyValue("IsSignatureLine") >>= bIsSignatureLine; + if (!bIsSignatureLine) + { + SAL_WARN("cui.dialogs", "No signature line selected!"); + return; + } + + m_xBtnLoadImage->connect_clicked(LINK(this, SignSignatureLineDialog, loadImage)); + m_xBtnClearImage->connect_clicked(LINK(this, SignSignatureLineDialog, clearImage)); + m_xBtnChooseCertificate->connect_clicked( + LINK(this, SignSignatureLineDialog, chooseCertificate)); + m_xEditName->connect_changed(LINK(this, SignSignatureLineDialog, entryChanged)); + + // Read properties from selected signature line + m_xShapeProperties->getPropertyValue("SignatureLineId") >>= m_aSignatureLineId; + m_xShapeProperties->getPropertyValue("SignatureLineSuggestedSignerName") + >>= m_aSuggestedSignerName; + m_xShapeProperties->getPropertyValue("SignatureLineSuggestedSignerTitle") + >>= m_aSuggestedSignerTitle; + OUString aSigningInstructions; + m_xShapeProperties->getPropertyValue("SignatureLineSigningInstructions") + >>= aSigningInstructions; + m_xShapeProperties->getPropertyValue("SignatureLineShowSignDate") >>= m_bShowSignDate; + bool bCanAddComment(false); + m_xShapeProperties->getPropertyValue("SignatureLineCanAddComment") >>= bCanAddComment; + + if (aSigningInstructions.isEmpty()) + { + m_xLabelHint->hide(); + m_xLabelHintText->hide(); + } + else + { + m_xLabelHintText->set_label(aSigningInstructions); + } + + if (bCanAddComment) + { + m_xEditComment->set_size_request(m_xEditComment->get_approximate_digit_width() * 48, + m_xEditComment->get_text_height() * 5); + } + else + { + m_xLabelAddComment->hide(); + m_xEditComment->hide(); + m_xEditComment->set_size_request(0, 0); + } + + ValidateFields(); +} + +IMPL_LINK_NOARG(SignSignatureLineDialog, loadImage, weld::Button&, void) +{ + Reference xContext = comphelper::getProcessComponentContext(); + Reference xFilePicker + = FilePicker::createWithMode(xContext, TemplateDescription::FILEOPEN_PREVIEW); + if (!xFilePicker->execute()) + return; + + Sequence aSelectedFiles = xFilePicker->getSelectedFiles(); + if (!aSelectedFiles.hasElements()) + return; + + Reference xProvider = GraphicProvider::create(xContext); + Sequence aMediaProperties(1); + aMediaProperties[0].Name = "URL"; + aMediaProperties[0].Value <<= aSelectedFiles[0]; + m_xSignatureImage = xProvider->queryGraphic(aMediaProperties); + m_sOriginalImageBtnLabel = m_xBtnLoadImage->get_label(); + + INetURLObject aObj(aSelectedFiles[0]); + m_xBtnLoadImage->set_label(aObj.GetLastName()); + + ValidateFields(); +} + +IMPL_LINK_NOARG(SignSignatureLineDialog, clearImage, weld::Button&, void) +{ + m_xSignatureImage.set(nullptr); + m_xBtnLoadImage->set_label(m_sOriginalImageBtnLabel); + ValidateFields(); +} + +IMPL_LINK_NOARG(SignSignatureLineDialog, chooseCertificate, weld::Button&, void) +{ + // Document needs to be saved before selecting a certificate + SfxObjectShell* pShell = SfxObjectShell::Current(); + if (!pShell->PrepareForSigning(m_xDialog.get())) + return; + + Reference xSigner; + if (pShell->GetMedium()->GetFilter()->IsAlienFormat()) + { + xSigner + = DocumentDigitalSignatures::createDefault(comphelper::getProcessComponentContext()); + } + else + { + OUString const aODFVersion( + comphelper::OStorageHelper::GetODFVersionFromStorage(pShell->GetStorage())); + xSigner = DocumentDigitalSignatures::createWithVersion( + comphelper::getProcessComponentContext(), aODFVersion); + } + xSigner->setParentWindow(m_xDialog->GetXWindow()); + OUString aDescription; + CertificateKind certificateKind = CertificateKind_NONE; + // When signing ooxml, we only want X.509 certificates + if (pShell->GetMedium()->GetFilter()->IsAlienFormat()) + certificateKind = CertificateKind_X509; + Reference xSignCertificate + = xSigner->selectSigningCertificateWithType(certificateKind, aDescription); + + if (xSignCertificate.is()) + { + m_xSelectedCertifate = xSignCertificate; + m_xBtnChooseCertificate->set_label(xmlsec::GetContentPart( + xSignCertificate->getSubjectName(), xSignCertificate->getCertificateKind())); + } + ValidateFields(); +} + +IMPL_LINK_NOARG(SignSignatureLineDialog, entryChanged, weld::Entry&, void) { ValidateFields(); } + +void SignSignatureLineDialog::ValidateFields() +{ + bool bEnableSignBtn = m_xSelectedCertifate.is() + && (!m_xEditName->get_text().isEmpty() || m_xSignatureImage.is()); + m_xBtnSign->set_sensitive(bEnableSignBtn); + + m_xEditName->set_sensitive(!m_xSignatureImage.is()); + m_xBtnLoadImage->set_sensitive(m_xEditName->get_text().isEmpty()); + m_xBtnClearImage->set_sensitive(m_xSignatureImage.is()); +} + +void SignSignatureLineDialog::Apply() +{ + if (!m_xSelectedCertifate.is()) + { + SAL_WARN("cui.dialogs", "No certificate selected!"); + return; + } + + SfxObjectShell* pShell = SfxObjectShell::Current(); + Reference xValidGraphic = getSignedGraphic(true); + Reference xInvalidGraphic = getSignedGraphic(false); + pShell->SignSignatureLine(m_xDialog.get(), m_aSignatureLineId, m_xSelectedCertifate, + xValidGraphic, xInvalidGraphic, m_xEditComment->get_text()); +} + +css::uno::Reference SignSignatureLineDialog::getSignedGraphic(bool bValid) +{ + // Read svg and replace placeholder texts + OUString aSvgImage(getSignatureImage()); + aSvgImage = aSvgImage.replaceAll("[SIGNER_NAME]", getCDataString(m_aSuggestedSignerName)); + aSvgImage = aSvgImage.replaceAll("[SIGNER_TITLE]", getCDataString(m_aSuggestedSignerTitle)); + + OUString aIssuerLine + = CuiResId(RID_SVXSTR_SIGNATURELINE_SIGNED_BY) + .replaceFirst("%1", + xmlsec::GetContentPart(m_xSelectedCertifate->getSubjectName(), + m_xSelectedCertifate->getCertificateKind())); + aSvgImage = aSvgImage.replaceAll("[SIGNED_BY]", getCDataString(aIssuerLine)); + if (bValid) + aSvgImage = aSvgImage.replaceAll("[INVALID_SIGNATURE]", ""); + + OUString aDate; + if (m_bShowSignDate && bValid) + { + const SvtSysLocale aSysLocale; + const LocaleDataWrapper& rLocaleData = aSysLocale.GetLocaleData(); + Date aDateTime(Date::SYSTEM); + aDate = rLocaleData.getDate(aDateTime); + } + aSvgImage = aSvgImage.replaceAll("[DATE]", aDate); + + // Custom signature image + if (m_xSignatureImage.is()) + { + OUString aGraphicInBase64; + Graphic aGraphic(m_xSignatureImage); + if (!XOutBitmap::GraphicToBase64(aGraphic, aGraphicInBase64, false)) + SAL_WARN("cui.dialogs", "Could not convert graphic to base64"); + + OUString aImagePart = "\" " + "preserveAspectRatio=\"xMidYMid\" height=\"1520\" " + "width=\"7600\" />"; + aImagePart = aImagePart.replaceAll( + "[MIMETYPE]", GraphicMimeTypeHelper::GetMimeTypeForXGraphic(m_xSignatureImage)); + aImagePart = aImagePart.replaceAll("[BASE64_IMG]", aGraphicInBase64); + aSvgImage = aSvgImage.replaceAll("[SIGNATURE_IMAGE]", aImagePart); + + aSvgImage = aSvgImage.replaceAll("[SIGNATURE]", ""); + } + else + { + aSvgImage = aSvgImage.replaceAll("[SIGNATURE_IMAGE]", ""); + aSvgImage = aSvgImage.replaceAll("[SIGNATURE]", getCDataString(m_xEditName->get_text())); + } + + // Create graphic + SvMemoryStream aSvgStream(4096, 4096); + aSvgStream.WriteOString(OUStringToOString(aSvgImage, RTL_TEXTENCODING_UTF8)); + Reference xInputStream(new utl::OSeekableInputStreamWrapper(aSvgStream)); + Reference xContext(comphelper::getProcessComponentContext()); + Reference xProvider = css::graphic::GraphicProvider::create(xContext); + + Sequence aMediaProperties(1); + aMediaProperties[0].Name = "InputStream"; + aMediaProperties[0].Value <<= xInputStream; + return xProvider->queryGraphic(aMediaProperties); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/cui/source/dialogs/SignatureLineDialog.cxx b/cui/source/dialogs/SignatureLineDialog.cxx new file mode 100644 index 000000000..e295e288e --- /dev/null +++ b/cui/source/dialogs/SignatureLineDialog.cxx @@ -0,0 +1,210 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace css; +using namespace css::uno; +using namespace css::beans; +using namespace css::container; +using namespace css::frame; +using namespace css::io; +using namespace css::lang; +using namespace css::frame; +using namespace css::sheet; +using namespace css::text; +using namespace css::drawing; +using namespace css::graphic; + +SignatureLineDialog::SignatureLineDialog(weld::Widget* pParent, Reference xModel, + bool bEditExisting) + : SignatureLineDialogBase(pParent, std::move(xModel), "cui/ui/signatureline.ui", + "SignatureLineDialog") + , m_xEditName(m_xBuilder->weld_entry("edit_name")) + , m_xEditTitle(m_xBuilder->weld_entry("edit_title")) + , m_xEditEmail(m_xBuilder->weld_entry("edit_email")) + , m_xEditInstructions(m_xBuilder->weld_text_view("edit_instructions")) + , m_xCheckboxCanAddComments(m_xBuilder->weld_check_button("checkbox_can_add_comments")) + , m_xCheckboxShowSignDate(m_xBuilder->weld_check_button("checkbox_show_sign_date")) +{ + m_xEditInstructions->set_size_request(m_xEditInstructions->get_approximate_digit_width() * 48, + m_xEditInstructions->get_text_height() * 5); + + // No signature line selected - start with empty dialog and set some default values + if (!bEditExisting) + { + m_xCheckboxCanAddComments->set_active(true); + m_xCheckboxShowSignDate->set_active(true); + return; + } + + Reference xIndexAccess(m_xModel->getCurrentSelection(), + UNO_QUERY_THROW); + Reference xProps(xIndexAccess->getByIndex(0), UNO_QUERY_THROW); + + // Read properties from selected signature line + xProps->getPropertyValue("SignatureLineId") >>= m_aSignatureLineId; + OUString aSuggestedSignerName; + xProps->getPropertyValue("SignatureLineSuggestedSignerName") >>= aSuggestedSignerName; + m_xEditName->set_text(aSuggestedSignerName); + OUString aSuggestedSignerTitle; + xProps->getPropertyValue("SignatureLineSuggestedSignerTitle") >>= aSuggestedSignerTitle; + m_xEditTitle->set_text(aSuggestedSignerTitle); + OUString aSuggestedSignerEmail; + xProps->getPropertyValue("SignatureLineSuggestedSignerEmail") >>= aSuggestedSignerEmail; + m_xEditEmail->set_text(aSuggestedSignerEmail); + OUString aSigningInstructions; + xProps->getPropertyValue("SignatureLineSigningInstructions") >>= aSigningInstructions; + m_xEditInstructions->set_text(aSigningInstructions); + bool bCanAddComments = false; + xProps->getPropertyValue("SignatureLineCanAddComment") >>= bCanAddComments; + m_xCheckboxCanAddComments->set_active(bCanAddComments); + bool bShowSignDate = false; + xProps->getPropertyValue("SignatureLineShowSignDate") >>= bShowSignDate; + m_xCheckboxShowSignDate->set_active(bShowSignDate); + + // Mark this as existing shape + m_xExistingShapeProperties = xProps; +} + +void SignatureLineDialog::Apply() +{ + if (m_aSignatureLineId.isEmpty()) + m_aSignatureLineId + = OStringToOUString(comphelper::xml::generateGUIDString(), RTL_TEXTENCODING_ASCII_US); + OUString aSignerName(m_xEditName->get_text()); + OUString aSignerTitle(m_xEditTitle->get_text()); + OUString aSignerEmail(m_xEditEmail->get_text()); + OUString aSigningInstructions(m_xEditInstructions->get_text()); + bool bCanAddComments(m_xCheckboxCanAddComments->get_active()); + bool bShowSignDate(m_xCheckboxShowSignDate->get_active()); + + // Read svg and replace placeholder texts + OUString aSvgImage(getSignatureImage()); + aSvgImage = aSvgImage.replaceAll("[SIGNER_NAME]", getCDataString(aSignerName)); + aSvgImage = aSvgImage.replaceAll("[SIGNER_TITLE]", getCDataString(aSignerTitle)); + + // These are only filled if the signature line is signed. + aSvgImage = aSvgImage.replaceAll("[SIGNATURE]", ""); + aSvgImage = aSvgImage.replaceAll("[SIGNED_BY]", ""); + aSvgImage = aSvgImage.replaceAll("[INVALID_SIGNATURE]", ""); + aSvgImage = aSvgImage.replaceAll("[DATE]", ""); + + // Insert/Update graphic + SvMemoryStream aSvgStream(4096, 4096); + aSvgStream.WriteOString(OUStringToOString(aSvgImage, RTL_TEXTENCODING_UTF8)); + Reference xInputStream(new utl::OSeekableInputStreamWrapper(aSvgStream)); + Reference xContext(comphelper::getProcessComponentContext()); + Reference xProvider = css::graphic::GraphicProvider::create(xContext); + + Sequence aMediaProperties(1); + aMediaProperties[0].Name = "InputStream"; + aMediaProperties[0].Value <<= xInputStream; + Reference xGraphic(xProvider->queryGraphic(aMediaProperties)); + + bool bIsExistingSignatureLine = m_xExistingShapeProperties.is(); + Reference xShapeProps; + if (bIsExistingSignatureLine) + xShapeProps = m_xExistingShapeProperties; + else + xShapeProps.set(Reference(m_xModel, UNO_QUERY_THROW) + ->createInstance("com.sun.star.drawing.GraphicObjectShape"), + UNO_QUERY); + + xShapeProps->setPropertyValue("Graphic", Any(xGraphic)); + xShapeProps->setPropertyValue("SignatureLineUnsignedImage", Any(xGraphic)); + + // Set signature line properties + xShapeProps->setPropertyValue("IsSignatureLine", Any(true)); + xShapeProps->setPropertyValue("SignatureLineId", Any(m_aSignatureLineId)); + if (!aSignerName.isEmpty()) + xShapeProps->setPropertyValue("SignatureLineSuggestedSignerName", Any(aSignerName)); + if (!aSignerTitle.isEmpty()) + xShapeProps->setPropertyValue("SignatureLineSuggestedSignerTitle", Any(aSignerTitle)); + if (!aSignerEmail.isEmpty()) + xShapeProps->setPropertyValue("SignatureLineSuggestedSignerEmail", Any(aSignerEmail)); + if (!aSigningInstructions.isEmpty()) + xShapeProps->setPropertyValue("SignatureLineSigningInstructions", + Any(aSigningInstructions)); + xShapeProps->setPropertyValue("SignatureLineShowSignDate", Any(bShowSignDate)); + xShapeProps->setPropertyValue("SignatureLineCanAddComment", Any(bCanAddComments)); + + if (bIsExistingSignatureLine) + return; + + // Default size + Reference xShape(xShapeProps, UNO_QUERY); + awt::Size aShapeSize; + aShapeSize.Height = 3000; + aShapeSize.Width = 6000; + xShape->setSize(aShapeSize); + + // Default anchoring + xShapeProps->setPropertyValue("AnchorType", Any(TextContentAnchorType_AT_PARAGRAPH)); + + // Writer + const Reference xTextDocument(m_xModel, UNO_QUERY); + if (xTextDocument.is()) + { + Reference xTextContent(xShape, UNO_QUERY_THROW); + Reference xViewCursorSupplier(m_xModel->getCurrentController(), + UNO_QUERY_THROW); + Reference xCursor = xViewCursorSupplier->getViewCursor(); + // use cursor's XText - it might be in table cell, frame, ... + Reference const xText(xCursor->getText()); + assert(xText.is()); + xText->insertTextContent(xCursor, xTextContent, true); + return; + } + + // Calc + const Reference xSpreadsheetDocument(m_xModel, UNO_QUERY); + if (!xSpreadsheetDocument.is()) + return; + + Reference xSheetCell(m_xModel->getCurrentSelection(), UNO_QUERY_THROW); + awt::Point aCellPosition; + xSheetCell->getPropertyValue("Position") >>= aCellPosition; + xShape->setPosition(aCellPosition); + + Reference xView(m_xModel->getCurrentController(), UNO_QUERY_THROW); + Reference xSheet(xView->getActiveSheet(), UNO_SET_THROW); + Reference xDrawPageSupplier(xSheet, UNO_QUERY_THROW); + Reference xDrawPage(xDrawPageSupplier->getDrawPage(), UNO_SET_THROW); + Reference xShapes(xDrawPage, UNO_QUERY_THROW); + + xShapes->add(xShape); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/cui/source/dialogs/SignatureLineDialogBase.cxx b/cui/source/dialogs/SignatureLineDialogBase.cxx new file mode 100644 index 000000000..4dadbf68e --- /dev/null +++ b/cui/source/dialogs/SignatureLineDialogBase.cxx @@ -0,0 +1,221 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include +#include + +using namespace css; +using namespace css::uno; +using namespace css::frame; + +SignatureLineDialogBase::SignatureLineDialogBase(weld::Widget* pParent, Reference xModel, + const OUString& rUIFile, const OString& rDialogId) + : GenericDialogController(pParent, rUIFile, rDialogId) + , m_xModel(std::move(xModel)) +{ +} + +short SignatureLineDialogBase::run() +{ + short nRet = GenericDialogController::run(); + if (nRet == RET_OK) + Apply(); + return nRet; +} + +OUString SignatureLineDialogBase::getCDataString(const OUString& rString) +{ + return ""; +} + +OUString SignatureLineDialogBase::getSignatureImage() +{ + OUString const svg( + "image/svg+xml150139132512: " + "XPATHSTROKE_SEQ_BEGIN132133109512: XPATHSTROKE_SEQ_END140150139133132111140150512: XTEXT_PAINTSHAPE_BEGIN138136135134113type: Text; content: [SIGNATURE]; [SIGNATURE]512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOW512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOW512: XTEXT_EOL512: XTEXT_EOP512: XTEXT_PAINTSHAPE_END150512: " + "XTEXT_PAINTSHAPE_BEGIN138136135134113type: Text; content: " + "[SIGNER_NAME]; [SIGNER_NAME]512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOW512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOW512: XTEXT_EOL512: XTEXT_EOP512: XTEXT_PAINTSHAPE_END150512: " + "XTEXT_PAINTSHAPE_BEGIN138136135134113type: Text; content: " + "[SIGNER_TITLE]; [SIGNER_TITLE]512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOW512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOW512: XTEXT_EOL512: XTEXT_EOP512: " + "XTEXT_PAINTSHAPE_END150512: " + "XTEXT_PAINTSHAPE_BEGIN138136135134113type: Text; content: " + "[SIGNED_BY]; [SIGNED_BY]512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOW512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOW512: XTEXT_EOL512: XTEXT_EOP512: XTEXT_PAINTSHAPE_END150512: " + "XTEXT_PAINTSHAPE_BEGIN138136135134113type: Text; content: [DATE]; [DATE]512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOW512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOC512: XTEXT_EOW512: XTEXT_EOL512: XTEXT_EOP512: XTEXT_PAINTSHAPE_END150512: " + "XTEXT_PAINTSHAPE_BEGIN138136135134113type: Text; content: " + "[INVALID_SIGNATURE]; [INVALID_SIGNATURE]512: " + "XTEXT_EOC512: XTEXT_EOC512: " + "XTEXT_EOW512: XTEXT_EOC512: " + "XTEXT_EOC512: XTEXT_EOC512: " + "XTEXT_EOC512: XTEXT_EOC512: " + "XTEXT_EOC512: XTEXT_EOC512: " + "XTEXT_EOC512: XTEXT_EOC512: " + "XTEXT_EOC512: XTEXT_EOC512: " + "XTEXT_EOC512: XTEXT_EOC512: " + "XTEXT_EOC512: XTEXT_EOC512: " + "XTEXT_EOC512: XTEXT_EOC512: " + "XTEXT_EOW512: XTEXT_EOL512: " + "XTEXT_EOP512: " + "XTEXT_PAINTSHAPE_END[SIGNATURE_IMAGE]"); + return svg; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/cui/source/dialogs/SpellAttrib.hxx b/cui/source/dialogs/SpellAttrib.hxx new file mode 100644 index 000000000..c086fe3d0 --- /dev/null +++ b/cui/source/dialogs/SpellAttrib.hxx @@ -0,0 +1,118 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include +#include +#include +#include + +namespace svx{ +struct SpellErrorDescription +{ + bool bIsGrammarError; + OUString sErrorText; + OUString sDialogTitle; + OUString sExplanation; + OUString sExplanationURL; + css::lang::Locale aLocale; + css::uno::Reference< css::linguistic2::XProofreader > xGrammarChecker; + css::uno::Sequence< OUString > aSuggestions; + OUString sRuleId; + + SpellErrorDescription( bool bGrammar, + const OUString& rText, + const css::lang::Locale& rLocale, + const css::uno::Sequence< OUString >& rSuggestions, + css::uno::Reference< css::linguistic2::XProofreader > const & rxGrammarChecker, + const OUString* pDialogTitle = nullptr, + const OUString* pExplanation = nullptr, + const OUString* pRuleId = nullptr, + const OUString* pExplanationURL = nullptr ) : + bIsGrammarError( bGrammar ), + sErrorText( rText ), + sDialogTitle( ), + sExplanation( ), + sExplanationURL( ), + aLocale( rLocale ), + xGrammarChecker( rxGrammarChecker ), + aSuggestions( rSuggestions ) + { + if( pDialogTitle ) + sDialogTitle = *pDialogTitle; + if( pExplanation ) + sExplanation = *pExplanation; + if( pExplanationURL ) + sExplanationURL = *pExplanationURL; + if( pRuleId ) + sRuleId = *pRuleId; + }; + + SpellErrorDescription() + : bIsGrammarError(false) + { + } + + bool operator==( const SpellErrorDescription& rDesc ) const + { + return bIsGrammarError == rDesc.bIsGrammarError && + sErrorText == rDesc.sErrorText && + aLocale.Language == rDesc.aLocale.Language && + aLocale.Country == rDesc.aLocale.Country && + aLocale.Variant == rDesc.aLocale.Variant && + aSuggestions == rDesc.aSuggestions && + xGrammarChecker == rDesc.xGrammarChecker && + sDialogTitle == rDesc.sDialogTitle && + sExplanation == rDesc.sExplanation && + sExplanationURL == rDesc.sExplanationURL && + sRuleId == rDesc.sRuleId; + } + + css::uno::Sequence toSequence() const + { + css::uno::Sequence aEntries(9); + aEntries[0] <<= bIsGrammarError; + aEntries[1] <<= sErrorText; + aEntries[2] <<= sDialogTitle; + aEntries[3] <<= sExplanation; + aEntries[4] <<= sExplanationURL; + aEntries[5] <<= aLocale; + aEntries[6] <<= xGrammarChecker; + aEntries[7] <<= aSuggestions; + aEntries[8] <<= sRuleId; + return aEntries; + } + + void fromSequence(const css::uno::Sequence& rEntries) + { + rEntries[0] >>= bIsGrammarError; + rEntries[1] >>= sErrorText; + rEntries[2] >>= sDialogTitle; + rEntries[3] >>= sExplanation; + rEntries[4] >>= sExplanationURL; + rEntries[5] >>= aLocale; + rEntries[6] >>= xGrammarChecker; + rEntries[7] >>= aSuggestions; + rEntries[8] >>= sRuleId; + } +}; + +}//namespace svx + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/SpellDialog.cxx b/cui/source/dialogs/SpellDialog.cxx new file mode 100644 index 000000000..b3b66d9e6 --- /dev/null +++ b/cui/source/dialogs/SpellDialog.cxx @@ -0,0 +1,2092 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include "SpellAttrib.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::linguistic2; +using namespace linguistic; + + +// struct SpellDialog_Impl --------------------------------------------- + +struct SpellDialog_Impl +{ + Sequence< Reference< XDictionary > > aDics; +}; + + +#define SPELLUNDO_START 200 + +#define SPELLUNDO_CHANGE_LANGUAGE (SPELLUNDO_START + 1) +#define SPELLUNDO_CHANGE_TEXTENGINE (SPELLUNDO_START + 2) +#define SPELLUNDO_CHANGE_NEXTERROR (SPELLUNDO_START + 3) +#define SPELLUNDO_CHANGE_ADD_TO_DICTIONARY (SPELLUNDO_START + 4) +#define SPELLUNDO_CHANGE_GROUP (SPELLUNDO_START + 5) //undo list +#define SPELLUNDO_MOVE_ERROREND (SPELLUNDO_START + 6) +#define SPELLUNDO_UNDO_EDIT_MODE (SPELLUNDO_START + 7) +#define SPELLUNDO_ADD_IGNORE_RULE (SPELLUNDO_START + 8) + +namespace svx{ +class SpellUndoAction_Impl : public SfxUndoAction +{ + sal_uInt16 m_nId; + const Link& m_rActionLink; + //undo of button enabling + bool m_bEnableChangePB; + bool m_bEnableChangeAllPB; + //undo of MarkNextError - used in change and change all, ignore and ignore all + long m_nOldErrorStart; + long m_nOldErrorEnd; + bool m_bIsErrorLanguageSelected; + //undo of AddToDictionary + Reference m_xDictionary; + OUString m_sAddedWord; + //move end of error - ::ChangeMarkedWord() + long m_nOffset; + +public: + SpellUndoAction_Impl(sal_uInt16 nId, const Link& rActionLink) : + m_nId(nId), + m_rActionLink( rActionLink), + m_bEnableChangePB(false), + m_bEnableChangeAllPB(false), + m_nOldErrorStart(-1), + m_nOldErrorEnd(-1), + m_bIsErrorLanguageSelected(false), + m_nOffset(0) + {} + + virtual void Undo() override; + sal_uInt16 GetId() const; + + void SetEnableChangePB(){m_bEnableChangePB = true;} + bool IsEnableChangePB() const {return m_bEnableChangePB;} + + void SetEnableChangeAllPB(){m_bEnableChangeAllPB = true;} + bool IsEnableChangeAllPB() const {return m_bEnableChangeAllPB;} + + void SetErrorMove(long nOldStart, long nOldEnd) + { + m_nOldErrorStart = nOldStart; + m_nOldErrorEnd = nOldEnd; + } + long GetOldErrorStart() const { return m_nOldErrorStart;} + long GetOldErrorEnd() const { return m_nOldErrorEnd;} + + void SetErrorLanguageSelected(bool bSet){ m_bIsErrorLanguageSelected = bSet;} + bool IsErrorLanguageSelected() const {return m_bIsErrorLanguageSelected;} + + void SetDictionary(const Reference& xDict) { m_xDictionary = xDict; } + const Reference& GetDictionary() const { return m_xDictionary; } + void SetAddedWord(const OUString& rWord) {m_sAddedWord = rWord;} + const OUString& GetAddedWord() const { return m_sAddedWord;} + + void SetOffset(long nSet) {m_nOffset = nSet;} + long GetOffset() const {return m_nOffset;} +}; +}//namespace svx +using namespace ::svx; + +void SpellUndoAction_Impl::Undo() +{ + m_rActionLink.Call(*this); +} + + +sal_uInt16 SpellUndoAction_Impl::GetId()const +{ + return m_nId; +} + +// class SvxSpellCheckDialog --------------------------------------------- + +SpellDialog::SpellDialog(SpellDialogChildWindow* pChildWindow, + weld::Window * pParent, SfxBindings* _pBindings) + : SfxModelessDialogController (_pBindings, pChildWindow, + pParent, "cui/ui/spellingdialog.ui", "SpellingDialog") + , aDialogUndoLink(LINK (this, SpellDialog, DialogUndoHdl)) + , bFocusLocked(true) + , rParent(*pChildWindow) + , pImpl( new SpellDialog_Impl ) + , m_xAltTitle(m_xBuilder->weld_label("alttitleft")) + , m_xResumeFT(m_xBuilder->weld_label("resumeft")) + , m_xNoSuggestionsFT(m_xBuilder->weld_label("nosuggestionsft")) + , m_xLanguageFT(m_xBuilder->weld_label("languageft")) + , m_xLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box("languagelb"))) + , m_xExplainFT(m_xBuilder->weld_label("explain")) + , m_xExplainLink(m_xBuilder->weld_link_button("explainlink")) + , m_xNotInDictFT(m_xBuilder->weld_label("notindictft")) + , m_xSentenceED(new SentenceEditWindow_Impl) + , m_xSuggestionFT(m_xBuilder->weld_label("suggestionsft")) + , m_xSuggestionLB(m_xBuilder->weld_tree_view("suggestionslb")) + , m_xIgnorePB(m_xBuilder->weld_button("ignore")) + , m_xIgnoreAllPB(m_xBuilder->weld_button("ignoreall")) + , m_xIgnoreRulePB(m_xBuilder->weld_button("ignorerule")) + , m_xAddToDictPB(m_xBuilder->weld_button("add")) + , m_xAddToDictMB(m_xBuilder->weld_menu_button("addmb")) + , m_xChangePB(m_xBuilder->weld_button("change")) + , m_xChangeAllPB(m_xBuilder->weld_button("changeall")) + , m_xAutoCorrPB(m_xBuilder->weld_button("autocorrect")) + , m_xCheckGrammarCB(m_xBuilder->weld_check_button("checkgrammar")) + , m_xOptionsPB(m_xBuilder->weld_button("options")) + , m_xUndoPB(m_xBuilder->weld_button("undo")) + , m_xClosePB(m_xBuilder->weld_button("close")) + , m_xToolbar(m_xBuilder->weld_toolbar("toolbar")) + , m_xSentenceEDWeld(new weld::CustomWeld(*m_xBuilder, "sentence", *m_xSentenceED)) +{ + m_xSentenceED->SetSpellDialog(this); + m_xSentenceED->Init(m_xToolbar.get()); + + m_sTitleSpellingGrammar = m_xDialog->get_title(); + m_sTitleSpelling = m_xAltTitle->get_label(); + + // fdo#68794 set initial title for cases where no text has been processed + // yet to show its language attributes + OUString sTitle = rParent.HasGrammarChecking() ? m_sTitleSpellingGrammar : m_sTitleSpelling; + m_xDialog->set_title(m_xDialog->strip_mnemonic(sTitle.replaceFirst("$LANGUAGE ($LOCATION)", ""))); + + m_sResumeST = m_xResumeFT->get_label(); + m_sNoSuggestionsST = m_xNoSuggestionsFT->strip_mnemonic(m_xNoSuggestionsFT->get_label()); + + Size aEdSize(m_xSuggestionLB->get_approximate_digit_width() * 60, + m_xSuggestionLB->get_height_rows(6)); + m_xSuggestionLB->set_size_request(aEdSize.Width(), -1); + m_sIgnoreOnceST = m_xIgnorePB->get_label(); + m_xAddToDictMB->set_help_id(m_xAddToDictPB->get_help_id()); + xSpell = LinguMgr::GetSpellChecker(); + + Init_Impl(); + + // disable controls if service is missing + m_xDialog->set_sensitive(xSpell.is()); + + //InitHdl wants to use virtual methods, so it + //can't be called during the ctor, so init + //it on next event cycle post-ctor + Application::PostUserEvent(LINK(this, SpellDialog, InitHdl)); +} + +SpellDialog::~SpellDialog() +{ + if (pImpl) + { + // save possibly modified user-dictionaries + Reference< XSearchableDictionaryList > xDicList( LinguMgr::GetDictionaryList() ); + if (xDicList.is()) + SaveDictionaries( xDicList ); + + pImpl.reset(); + } +} + +void SpellDialog::Init_Impl() +{ + // initialize handler + m_xClosePB->connect_clicked(LINK( this, SpellDialog, CancelHdl ) ); + m_xChangePB->connect_clicked(LINK( this, SpellDialog, ChangeHdl ) ); + m_xChangeAllPB->connect_clicked(LINK( this, SpellDialog, ChangeAllHdl ) ); + m_xIgnorePB->connect_clicked(LINK( this, SpellDialog, IgnoreHdl ) ); + m_xIgnoreAllPB->connect_clicked(LINK( this, SpellDialog, IgnoreAllHdl ) ); + m_xIgnoreRulePB->connect_clicked(LINK( this, SpellDialog, IgnoreAllHdl ) ); + m_xUndoPB->connect_clicked(LINK( this, SpellDialog, UndoHdl ) ); + + m_xAutoCorrPB->connect_clicked( LINK( this, SpellDialog, ExtClickHdl ) ); + m_xCheckGrammarCB->connect_clicked( LINK( this, SpellDialog, CheckGrammarHdl )); + m_xOptionsPB->connect_clicked( LINK( this, SpellDialog, ExtClickHdl ) ); + + m_xSuggestionLB->connect_row_activated( LINK( this, SpellDialog, DoubleClickChangeHdl ) ); + + m_xSentenceED->SetModifyHdl(LINK ( this, SpellDialog, ModifyHdl) ); + + m_xAddToDictMB->connect_selected(LINK ( this, SpellDialog, AddToDictSelectHdl ) ); + m_xAddToDictPB->connect_clicked(LINK ( this, SpellDialog, AddToDictClickHdl ) ); + + m_xLanguageLB->connect_changed(LINK( this, SpellDialog, LanguageSelectHdl ) ); + + // initialize language ListBox + m_xLanguageLB->SetLanguageList(SvxLanguageListFlags::SPELL_USED, false, false, true); + + m_xSentenceED->ClearModifyFlag(); + LinguMgr::GetChangeAllList()->clear(); +} + +void SpellDialog::UpdateBoxes_Impl(bool bCallFromSelectHdl) +{ + sal_Int32 i; + m_xSuggestionLB->clear(); + + SpellErrorDescription aSpellErrorDescription; + bool bSpellErrorDescription = m_xSentenceED->GetAlternatives(aSpellErrorDescription); + + LanguageType nAltLanguage = LANGUAGE_NONE; + Sequence< OUString > aNewWords; + bool bIsGrammarError = false; + if( bSpellErrorDescription ) + { + nAltLanguage = LanguageTag::convertToLanguageType( aSpellErrorDescription.aLocale ); + aNewWords = aSpellErrorDescription.aSuggestions; + bIsGrammarError = aSpellErrorDescription.bIsGrammarError; + m_xExplainLink->set_uri( aSpellErrorDescription.sExplanationURL ); + m_xExplainFT->set_label( aSpellErrorDescription.sExplanation ); + } + if( bSpellErrorDescription && !aSpellErrorDescription.sDialogTitle.isEmpty() ) + { + // use this function to apply the correct image to be used... + SetTitle_Impl( nAltLanguage ); + // then change the title to the one to be actually used + m_xDialog->set_title(m_xDialog->strip_mnemonic(aSpellErrorDescription.sDialogTitle)); + } + else + SetTitle_Impl( nAltLanguage ); + if( !bCallFromSelectHdl ) + m_xLanguageLB->set_active_id( nAltLanguage ); + int nDicts = InitUserDicts(); + + // enter alternatives + const OUString *pNewWords = aNewWords.getConstArray(); + const sal_Int32 nSize = aNewWords.getLength(); + for ( i = 0; i < nSize; ++i ) + { + OUString aTmp( pNewWords[i] ); + if (m_xSuggestionLB->find_text(aTmp) == -1) + m_xSuggestionLB->append_text(aTmp); + } + if(!nSize) + m_xSuggestionLB->append_text(m_sNoSuggestionsST); + m_xAutoCorrPB->set_sensitive( nSize > 0 ); + + m_xSuggestionFT->set_sensitive(nSize > 0); + m_xSuggestionLB->set_sensitive(nSize > 0); + if( nSize ) + { + m_xSuggestionLB->select(0); + } + m_xChangePB->set_sensitive( nSize > 0); + m_xChangeAllPB->set_sensitive(nSize > 0); + bool bShowChangeAll = !bIsGrammarError; + m_xChangeAllPB->set_visible( bShowChangeAll ); + m_xExplainFT->set_visible( !bShowChangeAll ); + m_xLanguageLB->set_sensitive( bShowChangeAll ); + m_xIgnoreAllPB->set_visible( bShowChangeAll ); + + m_xAddToDictMB->set_visible( bShowChangeAll && nDicts > 1); + m_xAddToDictPB->set_visible( bShowChangeAll && nDicts <= 1); + m_xIgnoreRulePB->set_visible( !bShowChangeAll ); + m_xIgnoreRulePB->set_sensitive(bSpellErrorDescription && !aSpellErrorDescription.sRuleId.isEmpty()); + m_xAutoCorrPB->set_visible( bShowChangeAll && rParent.HasAutoCorrection() ); + + bool bOldShowGrammar = m_xCheckGrammarCB->get_visible(); + bool bOldShowExplain = m_xExplainLink->get_visible(); + + m_xCheckGrammarCB->set_visible(rParent.HasGrammarChecking()); + m_xExplainLink->set_visible(!m_xExplainLink->get_uri().isEmpty()); + if (m_xExplainFT->get_label().isEmpty()) + { + m_xExplainFT->hide(); + m_xExplainLink->hide(); + } + + if (bOldShowExplain != m_xExplainLink->get_visible() || bOldShowGrammar != m_xCheckGrammarCB->get_visible()) + m_xDialog->resize_to_request(); +} + +void SpellDialog::SpellContinue_Impl(std::unique_ptr* pGuard, bool bUseSavedSentence, bool bIgnoreCurrentError) +{ + //initially or after the last error of a sentence MarkNextError will fail + //then GetNextSentence() has to be called followed again by MarkNextError() + //MarkNextError is not initially called if the UndoEdit mode is active + bool bNextSentence = false; + if(!((!m_xSentenceED->IsUndoEditMode() && m_xSentenceED->MarkNextError( bIgnoreCurrentError, xSpell )) || + ( bNextSentence = GetNextSentence_Impl(pGuard, bUseSavedSentence, m_xSentenceED->IsUndoEditMode()) && m_xSentenceED->MarkNextError( false, xSpell )))) + return; + + SpellErrorDescription aSpellErrorDescription; + bool bSpellErrorDescription = m_xSentenceED->GetAlternatives(aSpellErrorDescription); + if (bSpellErrorDescription) + { + UpdateBoxes_Impl(); + weld::Widget* aControls[] = + { + m_xNotInDictFT.get(), + m_xSentenceED->GetDrawingArea(), + m_xLanguageFT.get(), + nullptr + }; + sal_Int32 nIdx = 0; + do + { + aControls[nIdx]->set_sensitive(true); + } + while(aControls[++nIdx]); + + } + if( bNextSentence ) + { + //remove undo if a new sentence is active + m_xSentenceED->ResetUndo(); + m_xUndoPB->set_sensitive(false); + } +} +/* Initialize, asynchronous to prevent virtual calls + from a constructor + */ +IMPL_LINK_NOARG( SpellDialog, InitHdl, void*, void) +{ + m_xDialog->freeze(); + //show or hide AutoCorrect depending on the modules abilities + m_xAutoCorrPB->set_visible(rParent.HasAutoCorrection()); + SpellContinue_Impl(nullptr); + m_xSentenceED->ResetUndo(); + m_xUndoPB->set_sensitive(false); + + // get current language + UpdateBoxes_Impl(); + + // fill dictionary PopupMenu + InitUserDicts(); + + LockFocusChanges(true); + if( m_xChangePB->get_sensitive() ) + m_xChangePB->grab_focus(); + else if( m_xIgnorePB->get_sensitive() ) + m_xIgnorePB->grab_focus(); + else if( m_xClosePB->get_sensitive() ) + m_xClosePB->grab_focus(); + LockFocusChanges(false); + //show grammar CheckBox depending on the modules abilities + m_xCheckGrammarCB->set_active(rParent.IsGrammarChecking()); + m_xDialog->thaw(); +}; + +IMPL_LINK( SpellDialog, ExtClickHdl, weld::Button&, rBtn, void ) +{ + if (m_xOptionsPB.get() == &rBtn) + StartSpellOptDlg_Impl(); + else if (m_xAutoCorrPB.get() == &rBtn) + { + //get the currently selected wrong word + OUString sCurrentErrorText = m_xSentenceED->GetErrorText(); + //get the wrong word from the XSpellAlternative + SpellErrorDescription aSpellErrorDescription; + bool bSpellErrorDescription = m_xSentenceED->GetAlternatives(aSpellErrorDescription); + if (bSpellErrorDescription) + { + OUString sWrong(aSpellErrorDescription.sErrorText); + //if the word has not been edited in the MultiLineEdit then + //the current suggestion should be used + //if it's not the 'no suggestions' entry + if(sWrong == sCurrentErrorText && + m_xSuggestionLB->get_sensitive() && m_xSuggestionLB->get_selected_index() != -1 && + m_sNoSuggestionsST != m_xSuggestionLB->get_selected_text()) + { + sCurrentErrorText = m_xSuggestionLB->get_selected_text(); + } + if(sWrong != sCurrentErrorText) + { + SvxPrepareAutoCorrect( sWrong, sCurrentErrorText ); + LanguageType eLang = GetSelectedLang_Impl(); + rParent.AddAutoCorrection( sWrong, sCurrentErrorText, eLang ); + } + } + } +} + +IMPL_LINK_NOARG(SpellDialog, CheckGrammarHdl, weld::Button&, void) +{ + rParent.SetGrammarChecking(m_xCheckGrammarCB->get_active()); + Impl_Restore(true); +} + +void SpellDialog::StartSpellOptDlg_Impl() +{ + SfxItemSet aSet( SfxGetpApp()->GetPool(), svl::Items{}); + SfxSingleTabDialogController aDlg(m_xDialog.get(), &aSet, "cui/ui/spelloptionsdialog.ui", "SpellOptionsDialog"); + + std::unique_ptr xPage = SvxLinguTabPage::Create(aDlg.get_content_area(), &aDlg, &aSet); + static_cast(xPage.get())->HideGroups( GROUP_MODULES ); + aDlg.SetTabPage(std::move(xPage)); + if (RET_OK == aDlg.run()) + { + InitUserDicts(); + const SfxItemSet* pOutSet = aDlg.GetOutputItemSet(); + if(pOutSet) + OfaTreeOptionsDialog::ApplyLanguageOptions(*pOutSet); + } +} + +namespace +{ + OUString getDotReplacementString(const OUString &rErrorText, const OUString &rSuggestedReplacement) + { + OUString aString = rErrorText; + + //dots are sometimes part of the spelled word but they are not necessarily part of the replacement + bool bDot = aString.endsWith("."); + + aString = rSuggestedReplacement; + + if(bDot && (aString.isEmpty() || !aString.endsWith("."))) + aString += "."; + + return aString; + } +} + +OUString SpellDialog::getReplacementString() const +{ + OUString sOrigString = m_xSentenceED->GetErrorText(); + + OUString sReplacement(sOrigString); + + if(m_xSuggestionLB->get_sensitive() && + m_xSuggestionLB->get_selected_index() != -1 && + m_sNoSuggestionsST != m_xSuggestionLB->get_selected_text()) + sReplacement = m_xSuggestionLB->get_selected_text(); + + return getDotReplacementString(sOrigString, sReplacement); +} + +IMPL_LINK_NOARG(SpellDialog, DoubleClickChangeHdl, weld::TreeView&, bool) +{ + ChangeHdl(*m_xChangePB); + return true; +} + +/* tdf#132822 start an undo group in ctor and close it in the dtor. This can + then be passed to SpellContinue_Impl which can delete it in advance of its + natural scope to force closing the undo group if SpellContinue_Impl needs to + fetch a new paragraph and discard all undo information which can only be + done properly if there are no open undo groups */ +class UndoChangeGroupGuard +{ +private: + SentenceEditWindow_Impl& m_rSentenceED; +public: + UndoChangeGroupGuard(SentenceEditWindow_Impl& rSentenceED) + : m_rSentenceED(rSentenceED) + { + m_rSentenceED.UndoActionStart(SPELLUNDO_CHANGE_GROUP); + } + ~UndoChangeGroupGuard() + { + m_rSentenceED.UndoActionEnd(); + } +}; + +IMPL_LINK_NOARG(SpellDialog, ChangeHdl, weld::Button&, void) +{ + if (m_xSentenceED->IsUndoEditMode()) + { + SpellContinue_Impl(); + } + else + { + auto xGuard(std::make_unique(*m_xSentenceED)); + OUString aString = getReplacementString(); + m_xSentenceED->ChangeMarkedWord(aString, GetSelectedLang_Impl()); + SpellContinue_Impl(&xGuard); + } + if(!m_xChangePB->get_sensitive()) + m_xIgnorePB->grab_focus(); +} + +IMPL_LINK_NOARG(SpellDialog, ChangeAllHdl, weld::Button&, void) +{ + auto xGuard(std::make_unique(*m_xSentenceED)); + OUString aString = getReplacementString(); + LanguageType eLang = GetSelectedLang_Impl(); + + // add new word to ChangeAll list + OUString aOldWord( m_xSentenceED->GetErrorText() ); + SvxPrepareAutoCorrect( aOldWord, aString ); + Reference aXDictionary = LinguMgr::GetChangeAllList(); + DictionaryError nAdded = AddEntryToDic( aXDictionary, + aOldWord, true, + aString ); + + if(nAdded == DictionaryError::NONE) + { + std::unique_ptr pAction(new SpellUndoAction_Impl( + SPELLUNDO_CHANGE_ADD_TO_DICTIONARY, aDialogUndoLink)); + pAction->SetDictionary(aXDictionary); + pAction->SetAddedWord(aOldWord); + m_xSentenceED->AddUndoAction(std::move(pAction)); + } + + m_xSentenceED->ChangeMarkedWord(aString, eLang); + SpellContinue_Impl(&xGuard); +} + +IMPL_LINK( SpellDialog, IgnoreAllHdl, weld::Button&, rButton, void ) +{ + auto xGuard(std::make_unique(*m_xSentenceED)); + // add word to IgnoreAll list + Reference< XDictionary > aXDictionary = LinguMgr::GetIgnoreAllList(); + //in case the error has been changed manually it has to be restored + m_xSentenceED->RestoreCurrentError(); + if (&rButton == m_xIgnoreRulePB.get()) + { + SpellErrorDescription aSpellErrorDescription; + bool bSpellErrorDescription = m_xSentenceED->GetAlternatives(aSpellErrorDescription); + try + { + if( bSpellErrorDescription && aSpellErrorDescription.xGrammarChecker.is() ) + { + aSpellErrorDescription.xGrammarChecker->ignoreRule(aSpellErrorDescription.sRuleId, + aSpellErrorDescription.aLocale); + // refresh the layout (workaround to launch a dictionary event) + aXDictionary->setActive(false); + aXDictionary->setActive(true); + } + } + catch( const uno::Exception& ) + { + } + } + else + { + OUString sErrorText(m_xSentenceED->GetErrorText()); + DictionaryError nAdded = AddEntryToDic( aXDictionary, + sErrorText, false, + OUString() ); + if (nAdded == DictionaryError::NONE) + { + std::unique_ptr pAction(new SpellUndoAction_Impl( + SPELLUNDO_CHANGE_ADD_TO_DICTIONARY, aDialogUndoLink)); + pAction->SetDictionary(aXDictionary); + pAction->SetAddedWord(sErrorText); + m_xSentenceED->AddUndoAction(std::move(pAction)); + } + } + + SpellContinue_Impl(&xGuard); +} + +IMPL_LINK_NOARG(SpellDialog, UndoHdl, weld::Button&, void) +{ + m_xSentenceED->Undo(); + if(!m_xSentenceED->GetUndoActionCount()) + m_xUndoPB->set_sensitive(false); +} + + +IMPL_LINK( SpellDialog, DialogUndoHdl, SpellUndoAction_Impl&, rAction, void ) +{ + switch(rAction.GetId()) + { + case SPELLUNDO_CHANGE_TEXTENGINE: + { + if(rAction.IsEnableChangePB()) + m_xChangePB->set_sensitive(false); + if(rAction.IsEnableChangeAllPB()) + m_xChangeAllPB->set_sensitive(false); + } + break; + case SPELLUNDO_CHANGE_NEXTERROR: + { + m_xSentenceED->MoveErrorMarkTo(static_cast(rAction.GetOldErrorStart()), + static_cast(rAction.GetOldErrorEnd()), + false); + if(rAction.IsErrorLanguageSelected()) + { + UpdateBoxes_Impl(); + } + } + break; + case SPELLUNDO_CHANGE_ADD_TO_DICTIONARY: + { + if(rAction.GetDictionary().is()) + rAction.GetDictionary()->remove(rAction.GetAddedWord()); + } + break; + case SPELLUNDO_MOVE_ERROREND : + { + if(rAction.GetOffset() != 0) + m_xSentenceED->MoveErrorEnd(rAction.GetOffset()); + } + break; + case SPELLUNDO_UNDO_EDIT_MODE : + { + //refill the dialog with the currently spelled sentence - throw away all changes + SpellContinue_Impl(nullptr, true); + } + break; + case SPELLUNDO_ADD_IGNORE_RULE: + //undo of ignored rules is not supported + break; + } +} + +void SpellDialog::Impl_Restore(bool bUseSavedSentence) +{ + //clear the "ChangeAllList" + LinguMgr::GetChangeAllList()->clear(); + //get a new sentence + m_xSentenceED->SetText(OUString()); + m_xSentenceED->ResetModified(); + //Resolves: fdo#39348 refill the dialog with the currently spelled sentence + SpellContinue_Impl(nullptr, bUseSavedSentence); + m_xIgnorePB->set_label(m_sIgnoreOnceST); +} + +IMPL_LINK_NOARG(SpellDialog, IgnoreHdl, weld::Button&, void) +{ + if (m_sResumeST == m_xIgnorePB->get_label()) + { + Impl_Restore(false); + } + else + { + //in case the error has been changed manually it has to be restored, + // since the users choice now was to ignore the error + m_xSentenceED->RestoreCurrentError(); + + // the word is being ignored + SpellContinue_Impl(nullptr, false, true); + } +} + +void SpellDialog::Close() +{ + if (IsClosing()) + return; + + // We have to call ToggleChildWindow directly; calling SfxDispatcher's + // Execute() does not work here when we are in a document with protected + // section - in that case, the cursor can move from the editable field to + // the protected area, and the slots get disabled because of + // SfxDisableFlags::SwOnProtectedCursor (see FN_SPELL_GRAMMAR_DIALOG in .sdi). + SfxViewFrame* pViewFrame = SfxViewFrame::Current(); + if (pViewFrame) + pViewFrame->ToggleChildWindow(rParent.GetType()); +} + +LanguageType SpellDialog::GetSelectedLang_Impl() const +{ + LanguageType nLang = m_xLanguageLB->get_active_id(); + return nLang; +} + +IMPL_LINK_NOARG(SpellDialog, LanguageSelectHdl, weld::ComboBox&, void) +{ + //If selected language changes, then add->list should be regenerated to + //match + InitUserDicts(); + + //if currently an error is selected then search for alternatives for + //this word and fill the alternatives ListBox accordingly + OUString sError = m_xSentenceED->GetErrorText(); + m_xSuggestionLB->clear(); + if (!sError.isEmpty()) + { + LanguageType eLanguage = m_xLanguageLB->get_active_id(); + Reference xAlt = xSpell->spell( sError, static_cast(eLanguage), + Sequence< PropertyValue >() ); + if( xAlt.is() ) + m_xSentenceED->SetAlternatives( xAlt ); + else + { + m_xSentenceED->ChangeMarkedWord( sError, eLanguage ); + SpellContinue_Impl(); + } + + m_xSentenceED->AddUndoAction(std::make_unique(SPELLUNDO_CHANGE_LANGUAGE, aDialogUndoLink)); + } + SpellDialog::UpdateBoxes_Impl(true); +} + +void SpellDialog::SetTitle_Impl(LanguageType nLang) +{ + OUString sTitle = rParent.HasGrammarChecking() ? m_sTitleSpellingGrammar : m_sTitleSpelling; + sTitle = sTitle.replaceFirst( "$LANGUAGE ($LOCATION)", SvtLanguageTable::GetLanguageString(nLang) ); + m_xDialog->set_title(m_xDialog->strip_mnemonic(sTitle)); +} + +int SpellDialog::InitUserDicts() +{ + const LanguageType nLang = m_xLanguageLB->get_active_id(); + + const Reference< XDictionary > *pDic = nullptr; + + // get list of dictionaries + Reference< XSearchableDictionaryList > xDicList( LinguMgr::GetDictionaryList() ); + if (xDicList.is()) + { + // add active, positive dictionary to dic-list (if not already done). + // This is to ensure that there is at least on dictionary to which + // words could be added. + Reference< XDictionary > xDic( LinguMgr::GetStandardDic() ); + if (xDic.is()) + xDic->setActive( true ); + + pImpl->aDics = xDicList->getDictionaries(); + } + + SvtLinguConfig aCfg; + + // list suitable dictionaries + bool bEnable = false; + const sal_Int32 nSize = pImpl->aDics.getLength(); + pDic = pImpl->aDics.getConstArray(); + m_xAddToDictMB->clear(); + sal_uInt16 nItemId = 1; // menu items should be enumerated from 1 and not 0 + for (sal_Int32 i = 0; i < nSize; ++i) + { + uno::Reference< linguistic2::XDictionary > xDicTmp = pDic[i]; + if (!xDicTmp.is() || LinguMgr::GetIgnoreAllList() == xDicTmp) + continue; + + uno::Reference< frame::XStorable > xStor( xDicTmp, uno::UNO_QUERY ); + LanguageType nActLanguage = LanguageTag( xDicTmp->getLocale() ).getLanguageType(); + if( xDicTmp->isActive() + && xDicTmp->getDictionaryType() != linguistic2::DictionaryType_NEGATIVE + && (nLang == nActLanguage || LANGUAGE_NONE == nActLanguage ) + && (!xStor.is() || !xStor->isReadonly()) ) + { + bEnable = true; + + OUString aDictionaryImageUrl; + uno::Reference< lang::XServiceInfo > xSvcInfo( xDicTmp, uno::UNO_QUERY ); + if (xSvcInfo.is()) + { + aDictionaryImageUrl = aCfg.GetSpellAndGrammarContextDictionaryImage( + xSvcInfo->getImplementationName()); + } + + m_xAddToDictMB->append_item(OUString::number(nItemId), xDicTmp->getName(), aDictionaryImageUrl); + + ++nItemId; + } + } + m_xAddToDictMB->set_sensitive( bEnable ); + m_xAddToDictPB->set_sensitive( bEnable ); + + int nDicts = nItemId-1; + + m_xAddToDictMB->set_visible( nDicts > 1 ); + m_xAddToDictPB->set_visible( nDicts <= 1 ); + + return nDicts; +} + +IMPL_LINK_NOARG(SpellDialog, AddToDictClickHdl, weld::Button&, void) +{ + AddToDictionaryExecute(OString::number(1)); +} + +IMPL_LINK(SpellDialog, AddToDictSelectHdl, const OString&, rIdent, void) +{ + AddToDictionaryExecute(rIdent); +} + +void SpellDialog::AddToDictionaryExecute(const OString& rItemId) +{ + auto xGuard(std::make_unique(*m_xSentenceED)); + + //GetErrorText() returns the current error even if the text is already + //manually changed + const OUString aNewWord = m_xSentenceED->GetErrorText(); + + OUString aDicName(m_xAddToDictMB->get_item_label(rItemId)); + + uno::Reference< linguistic2::XDictionary > xDic; + uno::Reference< linguistic2::XSearchableDictionaryList > xDicList( LinguMgr::GetDictionaryList() ); + if (xDicList.is()) + xDic = xDicList->getDictionaryByName( aDicName ); + + DictionaryError nAddRes = DictionaryError::UNKNOWN; + if (xDic.is()) + { + nAddRes = AddEntryToDic( xDic, aNewWord, false, OUString() ); + // save modified user-dictionary if it is persistent + uno::Reference< frame::XStorable > xSavDic( xDic, uno::UNO_QUERY ); + if (xSavDic.is()) + xSavDic->store(); + + if (nAddRes == DictionaryError::NONE) + { + std::unique_ptr pAction(new SpellUndoAction_Impl( + SPELLUNDO_CHANGE_ADD_TO_DICTIONARY, aDialogUndoLink)); + pAction->SetDictionary( xDic ); + pAction->SetAddedWord( aNewWord ); + m_xSentenceED->AddUndoAction( std::move(pAction) ); + } + // failed because there is already an entry? + if (DictionaryError::NONE != nAddRes && xDic->getEntry( aNewWord ).is()) + nAddRes = DictionaryError::NONE; + } + if (DictionaryError::NONE != nAddRes) + { + SvxDicError(m_xDialog.get(), nAddRes); + return; // don't continue + } + + // go on + SpellContinue_Impl(&xGuard); +} + +IMPL_LINK_NOARG(SpellDialog, ModifyHdl, LinkParamNone*, void) +{ + m_xSuggestionLB->unselect_all(); + m_xSuggestionLB->set_sensitive(false); + m_xAutoCorrPB->set_sensitive(false); + std::unique_ptr pSpellAction(new SpellUndoAction_Impl(SPELLUNDO_CHANGE_TEXTENGINE, aDialogUndoLink)); + if(!m_xChangeAllPB->get_sensitive()) + { + m_xChangeAllPB->set_sensitive(true); + pSpellAction->SetEnableChangeAllPB(); + } + if(!m_xChangePB->get_sensitive()) + { + m_xChangePB->set_sensitive(true); + pSpellAction->SetEnableChangePB(); + } + m_xSentenceED->AddUndoAction(std::move(pSpellAction)); +} + +IMPL_LINK_NOARG(SpellDialog, CancelHdl, weld::Button&, void) +{ + //apply changes and ignored text parts first - if there are any + rParent.ApplyChangedSentence(m_xSentenceED->CreateSpellPortions(), false); + Close(); +} + +void SpellDialog::ToplevelFocusChanged() +{ + /* #i38338# + * FIXME: LoseFocus and GetFocus are signals from vcl that + * a window actually got/lost the focus, it never should be + * forwarded from another window, that is simply wrong. + * FIXME: overriding the virtual methods GetFocus and LoseFocus + * in SpellDialogChildWindow by making them pure is at least questionable. + * The only sensible thing would be to call the new Method differently, + * e.g. DialogGot/LostFocus or so. + */ + if (!(m_xDialog->get_visible() && !bFocusLocked)) + return; + + if (m_xDialog->has_toplevel_focus()) + { + //notify the child window of the focus change + rParent.GetFocus(); + } + else + { + //notify the child window of the focus change + rParent.LoseFocus(); + } +} + +void SpellDialog::Activate() +{ + SfxModelessDialogController::Activate(); + ToplevelFocusChanged(); +} + +void SpellDialog::Deactivate() +{ + SfxModelessDialogController::Activate(); + ToplevelFocusChanged(); +} + +void SpellDialog::InvalidateDialog() +{ + if( bFocusLocked ) + return; + m_xIgnorePB->set_label(m_sResumeST); + weld::Widget* aDisableArr[] = + { + m_xNotInDictFT.get(), + m_xSentenceED->GetDrawingArea(), + m_xSuggestionFT.get(), + m_xSuggestionLB.get(), + m_xLanguageFT.get(), + m_xLanguageLB->get_widget(), + m_xIgnoreAllPB.get(), + m_xIgnoreRulePB.get(), + m_xAddToDictMB.get(), + m_xAddToDictPB.get(), + m_xChangePB.get(), + m_xChangeAllPB.get(), + m_xAutoCorrPB.get(), + m_xUndoPB.get(), + nullptr + }; + sal_Int16 i = 0; + while(aDisableArr[i]) + { + aDisableArr[i]->set_sensitive(false); + i++; + } + SfxModelessDialogController::Deactivate(); +} + +bool SpellDialog::GetNextSentence_Impl(std::unique_ptr* pGuard, bool bUseSavedSentence, bool bRecheck) +{ + bool bRet = false; + if(!bUseSavedSentence) + { + //apply changes and ignored text parts + rParent.ApplyChangedSentence(m_xSentenceED->CreateSpellPortions(), bRecheck); + } + m_xSentenceED->ResetIgnoreErrorsAt(); + m_xSentenceED->ResetModified(); + SpellPortions aSentence = bUseSavedSentence ? m_aSavedSentence : rParent.GetNextWrongSentence( bRecheck ); + if(!bUseSavedSentence) + m_aSavedSentence = aSentence; + bool bHasReplaced = false; + while(!aSentence.empty()) + { + //apply all changes that are already part of the "ChangeAllList" + //returns true if the list still contains errors after the changes have been applied + + if(!ApplyChangeAllList_Impl(aSentence, bHasReplaced)) + { + rParent.ApplyChangedSentence(aSentence, bRecheck); + aSentence = rParent.GetNextWrongSentence( bRecheck ); + } + else + break; + } + + if(!aSentence.empty()) + { + OUStringBuffer sText; + for (auto const& elem : aSentence) + { + // hidden text has to be ignored + if(!elem.bIsHidden) + sText.append(elem.sText); + } + // tdf#132822 fire undo-stack UndoActionEnd to close undo stack because we're about to throw away the paragraph entirely + if (pGuard) + pGuard->reset(); + m_xSentenceED->SetText(sText.makeStringAndClear()); + sal_Int32 nStartPosition = 0; + sal_Int32 nEndPosition = 0; + + for (auto const& elem : aSentence) + { + // hidden text has to be ignored + if(!elem.bIsHidden) + { + nEndPosition += elem.sText.getLength(); + if(elem.xAlternatives.is()) + { + uno::Reference< container::XNamed > xNamed( elem.xAlternatives, uno::UNO_QUERY ); + OUString sServiceName; + if( xNamed.is() ) + sServiceName = xNamed->getName(); + SpellErrorDescription aDesc( false, elem.xAlternatives->getWord(), + elem.xAlternatives->getLocale(), elem.xAlternatives->getAlternatives(), nullptr); + SfxGrabBagItem aSpellErrorDescription(EE_CHAR_GRABBAG); + aSpellErrorDescription.GetGrabBag()["SpellErrorDescription"] <<= aDesc.toSequence(); + m_xSentenceED->SetAttrib(aSpellErrorDescription, nStartPosition, nEndPosition); + } + else if(elem.bIsGrammarError ) + { + beans::PropertyValues aProperties = elem.aGrammarError.aProperties; + OUString sFullCommentURL; + sal_Int32 i = 0; + while ( sFullCommentURL.isEmpty() && i < aProperties.getLength() ) + { + if ( aProperties[i].Name == "FullCommentURL" ) + { + uno::Any aValue = aProperties[i].Value; + aValue >>= sFullCommentURL; + } + ++i; + } + + SpellErrorDescription aDesc( true, + elem.sText, + LanguageTag::convertToLocale( elem.eLanguage ), + elem.aGrammarError.aSuggestions, + elem.xGrammarChecker, + &elem.sDialogTitle, + &elem.aGrammarError.aFullComment, + &elem.aGrammarError.aRuleIdentifier, + &sFullCommentURL ); + + SfxGrabBagItem aSpellErrorDescriptionItem(EE_CHAR_GRABBAG); + aSpellErrorDescriptionItem.GetGrabBag()["SpellErrorDescription"] <<= aDesc.toSequence(); + m_xSentenceED->SetAttrib(aSpellErrorDescriptionItem, nStartPosition, nEndPosition); + } + + if (elem.bIsField) + m_xSentenceED->SetAttrib(SvxBackgroundColorItem(COL_LIGHTGRAY, EE_CHAR_BKGCOLOR), nStartPosition, nEndPosition); + m_xSentenceED->SetAttrib(SvxLanguageItem(elem.eLanguage, EE_CHAR_LANGUAGE), nStartPosition, nEndPosition); + nStartPosition = nEndPosition; + } + } + //the edit field needs to be modified to apply the change from the ApplyChangeAllList + if(!bHasReplaced) + m_xSentenceED->ClearModifyFlag(); + m_xSentenceED->ResetUndo(); + m_xUndoPB->set_sensitive(false); + bRet = nStartPosition > 0; + } + return bRet; +} +/*------------------------------------------------------------------------- + replace errors that have a replacement in the ChangeAllList + returns false if the result doesn't contain errors after the replacement + -----------------------------------------------------------------------*/ +bool SpellDialog::ApplyChangeAllList_Impl(SpellPortions& rSentence, bool &bHasReplaced) +{ + bHasReplaced = false; + bool bRet = true; + Reference xChangeAll = LinguMgr::GetChangeAllList(); + if(!xChangeAll->getCount()) + return bRet; + bRet = false; + for (auto & elem : rSentence) + { + if(elem.xAlternatives.is()) + { + const OUString &rString = elem.sText; + + Reference xEntry = xChangeAll->getEntry(rString); + + if(xEntry.is()) + { + elem.sText = getDotReplacementString(rString, xEntry->getReplacementText()); + elem.xAlternatives = nullptr; + bHasReplaced = true; + } + else + bRet = true; + } + else if( elem.bIsGrammarError ) + bRet = true; + } + return bRet; +} + +SentenceEditWindow_Impl::SentenceEditWindow_Impl() + : m_pSpellDialog(nullptr) + , m_pToolbar(nullptr) + , m_nErrorStart(0) + , m_nErrorEnd(0) + , m_bIsUndoEditMode(false) +{ +} + +void SentenceEditWindow_Impl::SetDrawingArea(weld::DrawingArea* pDrawingArea) +{ + Size aSize(pDrawingArea->get_approximate_digit_width() * 60, + pDrawingArea->get_text_height() * 6); + pDrawingArea->set_size_request(aSize.Width(), aSize.Height()); + WeldEditView::SetDrawingArea(pDrawingArea); + // tdf#132288 don't merge equal adjacent attributes + m_xEditEngine->DisableAttributeExpanding(); +} + +SentenceEditWindow_Impl::~SentenceEditWindow_Impl() +{ +} + +namespace +{ + const EECharAttrib* FindCharAttrib(int nPosition, sal_uInt16 nWhich, std::vector& rAttribList) + { + for (auto it = rAttribList.rbegin(); it != rAttribList.rend(); ++it) + { + const auto& rTextAtr = *it; + if (rTextAtr.pAttr->Which() != nWhich) + continue; + if (rTextAtr.nStart <= nPosition && rTextAtr.nEnd >= nPosition) + { + return &rTextAtr; + } + } + + return nullptr; + } + + void ExtractErrorDescription(const EECharAttrib& rEECharAttrib, SpellErrorDescription& rSpellErrorDescription) + { + css::uno::Sequence aSequence; + static_cast(rEECharAttrib.pAttr)->GetGrabBag().find("SpellErrorDescription")->second >>= aSequence; + rSpellErrorDescription.fromSequence(aSequence); + } +} + +/*------------------------------------------------------------------------- + The selection before inputting a key may have a range or not + and it may be inside or outside of field or error attributes. + A range may include the attribute partially, completely or together + with surrounding text. It may also contain more than one attribute + or no attribute at all. + Depending on this starting conditions some actions are necessary: + Attempts to delete a field are only allowed if the selection is the same + as the field's selection. Otherwise the field has to be selected and the key + input action has to be skipped. + Input of text at the start of the field requires the field attribute to be + corrected - it is not allowed to grow. + + In case of errors the appending of text should grow the error attribute because + that is what the user usually wants to do. + + Backspace at the start of the attribute requires to find out if a field ends + directly in front of the cursor position. In case of a field this attribute has to be + selected otherwise the key input method is allowed. + + All changes outside of the error attributes switch the dialog mode to a "Undo edit" state that + removes all visible attributes and switches off further attribute checks. + Undo in this restarts the dialog with a current sentence newly presented. + All changes to the sentence are undone including the ones before the "Undo edit state" has been reached + + We end up with 9 types of selection + 1 (LEFT_NO) - no range, start of attribute - can also be 3 at the same time + 2 (INSIDE_NO) - no range, inside of attribute + 3 (RIGHT_NO) - no range, end of attribute - can also be 1 at the same time + 4 (FULL) - range, same as attribute + 5 (INSIDE_YES) - range, inside of the attribute + 6 (BRACE)- range, from outside of the attribute to the inside or + including the complete attribute and something outside, + maybe more than one attribute + 7 (OUTSIDE_NO) - no range, not at an attribute + 8 (OUTSIDE_YES) - range, completely outside of all attributes + + What has to be done depending on the attribute type involved + possible actions: UE - Undo edit mode + CO - Continue, no additional action is required + FS - Field has to be completely selected + EX - The attribute has to be expanded to include the added text + + 1 - backspace delete any other + UE on field FS on error CO on field FS on error CO + + 2 - on field FS on error C + 3 - backspace delete any other + on field FS on error CO UE on field UE on error EX + + if 1 and 3 happen to apply both then backspace and other handling is 1 delete is 3 + + 4 - on field UE and on error CO + 5 - on field FS and on error CO + 6 - on field FS and on error UE + 7 - UE + 8 - UE + -----------------------------------------------------------------------*/ +#define INVALID 0 +#define LEFT_NO 1 +#define INSIDE_NO 2 +#define RIGHT_NO 3 +#define FULL 4 +#define INSIDE_YES 5 +#define BRACE 6 +#define OUTSIDE_NO 7 +#define OUTSIDE_YES 8 + +#define ACTION_UNDOEDIT 0 +#define ACTION_CONTINUE 1 +#define ACTION_SELECTFIELD 2 +#define ACTION_EXPAND 3 + +bool SentenceEditWindow_Impl::KeyInput(const KeyEvent& rKeyEvt) +{ + if (rKeyEvt.GetKeyCode().GetCode() == KEY_TAB) + return false; + + bool bConsumed = false; + + bool bChange = TextEngine::DoesKeyChangeText( rKeyEvt ); + if (bChange && !IsUndoEditMode()) + { + bConsumed = true; + + ESelection aCurrentSelection(m_xEditView->GetSelection()); + aCurrentSelection.Adjust(); + + //determine if the selection contains a field + bool bHasFieldLeft = false; + bool bHasErrorLeft = false; + + bool bHasRange = aCurrentSelection.HasRange(); + sal_uInt8 nSelectionType = 0; // invalid type! + + std::vector aAttribList; + m_xEditEngine->GetCharAttribs(0, aAttribList); + + auto nCursor = aCurrentSelection.nStartPos; + const EECharAttrib* pBackAttr = FindCharAttrib(nCursor, EE_CHAR_BKGCOLOR, aAttribList); + const EECharAttrib* pErrorAttr = FindCharAttrib(nCursor, EE_CHAR_GRABBAG, aAttribList); + const EECharAttrib* pBackAttrLeft = nullptr; + const EECharAttrib* pErrorAttrLeft = nullptr; + + bool bHasField = pBackAttr != nullptr && (bHasRange || pBackAttr->nEnd > nCursor); + bool bHasError = pErrorAttr != nullptr && (bHasRange || pErrorAttr->nEnd > nCursor); + if (bHasRange) + { + if (pBackAttr && + pBackAttr->nStart == aCurrentSelection.nStartPos && + pBackAttr->nEnd == aCurrentSelection.nEndPos) + { + nSelectionType = FULL; + } + else if (pErrorAttr && + pErrorAttr->nStart <= aCurrentSelection.nStartPos && + pErrorAttr->nEnd >= aCurrentSelection.nEndPos) + { + nSelectionType = INSIDE_YES; + } + else + { + nSelectionType = bHasField||bHasError ? BRACE : OUTSIDE_NO; + while (nCursor < aCurrentSelection.nEndPos) + { + ++nCursor; + const EECharAttrib* pIntBackAttr = FindCharAttrib(nCursor, EE_CHAR_BKGCOLOR, aAttribList); + const EECharAttrib* pIntErrorAttr = FindCharAttrib(nCursor, EE_CHAR_GRABBAG, aAttribList); + //if any attr has been found then BRACE + if (pIntBackAttr || pIntErrorAttr) + nSelectionType = BRACE; + //the field has to be selected + if (pIntBackAttr && !pBackAttr) + pBackAttr = pIntBackAttr; + bHasField |= pIntBackAttr != nullptr; + } + } + } + else + { + //no range selection: then 1 2 3 and 8 are possible + const EECharAttrib* pCurAttr = pBackAttr ? pBackAttr : pErrorAttr; + if (pCurAttr) + { + nSelectionType = pCurAttr->nStart == aCurrentSelection.nStartPos ? + LEFT_NO : pCurAttr->nEnd == aCurrentSelection.nEndPos ? RIGHT_NO : INSIDE_NO; + } + else + nSelectionType = OUTSIDE_NO; + + bHasFieldLeft = pBackAttr && pBackAttr->nEnd == nCursor; + if(bHasFieldLeft) + { + pBackAttrLeft = pBackAttr; + pBackAttr = nullptr; + } + bHasErrorLeft = pErrorAttr && pErrorAttr->nEnd == nCursor; + if(bHasErrorLeft) + { + pErrorAttrLeft = pErrorAttr; + pErrorAttr = nullptr; + } + + //check previous position if this exists + //that is a redundant in the case the attribute found above already is on the left cursor side + //but it's o.k. for two errors/fields side by side + if (nCursor) + { + --nCursor; + pBackAttrLeft = FindCharAttrib(nCursor, EE_CHAR_BKGCOLOR, aAttribList); + pErrorAttrLeft = FindCharAttrib(nCursor, EE_CHAR_GRABBAG, aAttribList); + bHasFieldLeft = pBackAttrLeft !=nullptr; + bHasErrorLeft = pErrorAttrLeft != nullptr; + ++nCursor; + } + } + //Here we have to determine if the error found is the one currently active + bool bIsErrorActive = (pErrorAttr && pErrorAttr->nStart == m_nErrorStart) || + (pErrorAttrLeft && pErrorAttrLeft->nStart == m_nErrorStart); + + SAL_WARN_IF( + nSelectionType == INVALID, "cui.dialogs", + "selection type not set"); + + const vcl::KeyCode& rKeyCode = rKeyEvt.GetKeyCode(); + bool bDelete = rKeyCode.GetCode() == KEY_DELETE; + bool bBackspace = rKeyCode.GetCode() == KEY_BACKSPACE; + + sal_Int8 nAction = ACTION_CONTINUE; + switch(nSelectionType) + { +// 1 - backspace delete any other +// UE on field FS on error CO on field FS on error CO + case LEFT_NO : + if(bBackspace) + { + nAction = bHasFieldLeft ? ACTION_SELECTFIELD : ACTION_UNDOEDIT; + //to force the use of pBackAttrLeft + pBackAttr = nullptr; + } + else if(bDelete) + nAction = bHasField ? ACTION_SELECTFIELD : ACTION_CONTINUE; + else + nAction = bHasError && !nCursor ? ACTION_CONTINUE : + bHasError ? ACTION_EXPAND : bHasErrorLeft ? ACTION_CONTINUE : ACTION_UNDOEDIT; + break; +// 2 - on field FS on error C + case INSIDE_NO : + nAction = bHasField ? ACTION_SELECTFIELD : + bIsErrorActive ? ACTION_CONTINUE : ACTION_UNDOEDIT; + break; +// 3 - backspace delete any other +// on field FS on error CO UE on field UE on error EX + case RIGHT_NO : + if(bBackspace) + nAction = bHasFieldLeft ? ACTION_SELECTFIELD : ACTION_CONTINUE; + else if(bDelete) + nAction = bHasFieldLeft && bHasError ? ACTION_CONTINUE : ACTION_UNDOEDIT; + else + nAction = bHasFieldLeft && bHasError ? ACTION_EXPAND : + bHasError ? ACTION_CONTINUE : bHasErrorLeft ? ACTION_EXPAND :ACTION_UNDOEDIT; + break; +// 4 - on field UE and on error CO + case FULL : + nAction = ACTION_UNDOEDIT; + break; +// 5 - on field FS and on error CO + case INSIDE_YES : + nAction = bHasField ? ACTION_SELECTFIELD : ACTION_CONTINUE; + break; +// 6 - on field FS and on error UE + case BRACE : + nAction = bHasField ? ACTION_SELECTFIELD : ACTION_UNDOEDIT; + break; +// 7 - UE +// 8 - UE + case OUTSIDE_NO : + case OUTSIDE_YES: + nAction = ACTION_UNDOEDIT; + break; + } + //save the current paragraph + sal_Int32 nCurrentLen = m_xEditEngine->GetText().getLength(); + if (nAction != ACTION_SELECTFIELD) + { + m_xEditView->PostKeyEvent(rKeyEvt); + } + else + { + const EECharAttrib* pCharAttr = pBackAttr ? pBackAttr : pBackAttrLeft; + if (pCharAttr) + m_xEditView->SetSelection(ESelection(0, pCharAttr->nStart, 0, pCharAttr->nEnd)); + } + if(nAction == ACTION_EXPAND) + { + DBG_ASSERT(pErrorAttrLeft || pErrorAttr, "where is the error"); + //text has been added on the right and only the 'error attribute has to be corrected + if (pErrorAttrLeft) + { + SpellErrorDescription aSpellErrorDescription; + ExtractErrorDescription(*pErrorAttrLeft, aSpellErrorDescription); + + std::unique_ptr xNewError(pErrorAttrLeft->pAttr->Clone()); + sal_Int32 nStart = pErrorAttrLeft->nStart; + sal_Int32 nEnd = pErrorAttrLeft->nEnd + 1; + m_xEditEngine->RemoveAttribs(ESelection(0, nStart, 0, nEnd), false, EE_CHAR_GRABBAG); + SetAttrib(*xNewError, nStart, nEnd); + //only active errors move the mark + if (bIsErrorActive) + { + bool bGrammar = aSpellErrorDescription.bIsGrammarError; + MoveErrorMarkTo(nStart, nEnd, bGrammar); + } + } + //text has been added on the left then the error attribute has to be expanded and the + //field attribute on the right - if any - has to be contracted + else if (pErrorAttr) + { + SpellErrorDescription aSpellErrorDescription; + ExtractErrorDescription(*pErrorAttr, aSpellErrorDescription); + + //determine the change + sal_Int32 nAddedChars = m_xEditEngine->GetText().getLength() - nCurrentLen; + + std::unique_ptr xNewError(pErrorAttr->pAttr->Clone()); + sal_Int32 nStart = pErrorAttr->nStart + nAddedChars; + sal_Int32 nEnd = pErrorAttr->nEnd + nAddedChars; + m_xEditEngine->RemoveAttribs(ESelection(0, nStart, 0, nEnd), false, EE_CHAR_GRABBAG); + nStart = pErrorAttr->nStart; + SetAttrib(*xNewError, nStart, nEnd); + //only if the error is active the mark is moved here + if (bIsErrorActive) + { + bool bGrammar = aSpellErrorDescription.bIsGrammarError; + MoveErrorMarkTo(nStart, nEnd, bGrammar); + } + xNewError.reset(); + + if (pBackAttrLeft) + { + std::unique_ptr xNewBack(pBackAttrLeft->pAttr->Clone()); + sal_Int32 _nStart = pBackAttrLeft->nStart + nAddedChars; + sal_Int32 _nEnd = pBackAttrLeft->nEnd + nAddedChars; + m_xEditEngine->RemoveAttribs(ESelection(0, _nStart, 0, _nEnd), false, EE_CHAR_BKGCOLOR); + _nStart = pBackAttrLeft->nStart; + SetAttrib(*xNewBack, _nStart, _nEnd); + } + } + } + else if(nAction == ACTION_UNDOEDIT) + { + SetUndoEditMode(true); + } + //make sure the error positions are correct after text changes + //the old attribute may have been deleted + //all changes inside of the current error leave the error attribute at the current + //start position + if (!IsUndoEditMode() && bIsErrorActive) + { + const EECharAttrib* pFontColor = FindCharAttrib(nCursor, EE_CHAR_COLOR, aAttribList); + const EECharAttrib* pErrorAttrib = FindCharAttrib(m_nErrorStart, EE_CHAR_GRABBAG, aAttribList); + if (pFontColor && pErrorAttrib) + { + m_nErrorStart = pFontColor->nStart; + m_nErrorEnd = pFontColor->nEnd; + if (pErrorAttrib->nStart != m_nErrorStart || pErrorAttrib->nEnd != m_nErrorEnd) + { + std::unique_ptr xNewError(pErrorAttrib->pAttr->Clone()); + assert(pErrorAttr); + m_xEditEngine->RemoveAttribs(ESelection(0, pErrorAttr->nStart, 0, pErrorAttr->nEnd), false, EE_CHAR_GRABBAG); + SetAttrib(*xNewError, m_nErrorStart, m_nErrorEnd); + } + } + } + //this is not a modification anymore + if(nAction != ACTION_SELECTFIELD && !m_bIsUndoEditMode) + CallModifyLink(); + } + else + bConsumed = m_xEditView->PostKeyEvent(rKeyEvt); + + return bConsumed; +} + +void SentenceEditWindow_Impl::Init(weld::Toolbar* pToolbar) +{ + m_pToolbar = pToolbar; + m_pToolbar->connect_clicked(LINK(this,SentenceEditWindow_Impl,ToolbarHdl)); +} + +IMPL_LINK(SentenceEditWindow_Impl, ToolbarHdl, const OString&, rCurItemId, void) +{ + if (rCurItemId == "paste") + { + m_xEditView->Paste(); + CallModifyLink(); + } + else if (rCurItemId == "insert") + { + if (vcl::GetGetSpecialCharsFunction()) + { + OUString aChars = vcl::GetGetSpecialCharsFunction()(GetDrawingArea(), m_xEditEngine->GetStandardFont(0)); + if (!aChars.isEmpty()) + { + ESelection aCurrentSelection(m_xEditView->GetSelection()); + m_xEditEngine->QuickInsertText(aChars, aCurrentSelection); + CallModifyLink(); + } + } + } +} + +bool SentenceEditWindow_Impl::MarkNextError( bool bIgnoreCurrentError, const css::uno::Reference& xSpell ) +{ + if (bIgnoreCurrentError) + m_aIgnoreErrorsAt.insert( m_nErrorStart ); + + const sal_Int32 nTextLen = m_xEditEngine->GetTextLen(0); + + if (m_nErrorEnd >= nTextLen - 1) + return false; + //if it's not already modified the modified flag has to be reset at the end of the marking + bool bModified = IsModified(); + bool bRet = false; + const sal_Int32 nOldErrorStart = m_nErrorStart; + const sal_Int32 nOldErrorEnd = m_nErrorEnd; + + //create a cursor behind the end of the last error + //- or at 0 at the start of the sentence + sal_Int32 nCursor(m_nErrorEnd ? m_nErrorEnd + 1 : 0); + + //search for SpellErrorDescription + SpellErrorDescription aSpellErrorDescription; + + std::vector aAttribList; + m_xEditEngine->GetCharAttribs(0, aAttribList); + + //iterate over the text and search for the next error that maybe has + //to be replace by a ChangeAllList replacement + bool bGrammarError = false; + while (nCursor < nTextLen) + { + const SpellErrorDescription* pSpellErrorDescription = nullptr; + const EECharAttrib* pEECharAttrib = nullptr; + + sal_Int32 nMinPos = nTextLen + 1; + for (const auto& rTextAtr : aAttribList) + { + if (rTextAtr.pAttr->Which() != EE_CHAR_GRABBAG) + continue; + if (rTextAtr.nEnd > nCursor && rTextAtr.nStart < nMinPos) + { + nMinPos = rTextAtr.nStart; + pEECharAttrib = &rTextAtr; + } + } + + if (pEECharAttrib) + { + ExtractErrorDescription(*pEECharAttrib, aSpellErrorDescription); + + bGrammarError = aSpellErrorDescription.bIsGrammarError; + m_nErrorStart = pEECharAttrib->nStart; + m_nErrorEnd = pEECharAttrib->nEnd; + + pSpellErrorDescription = &aSpellErrorDescription; + } + + nCursor = std::max(nCursor, nMinPos); // move forward if possible + + // maybe the error found here is already in the ChangeAllList and has to be replaced + Reference xChangeAll = LinguMgr::GetChangeAllList(); + Reference xEntry; + + if (xChangeAll->getCount() && pSpellErrorDescription && + (xEntry = xChangeAll->getEntry( pSpellErrorDescription->sErrorText )).is()) + { + OUString sReplacement(getDotReplacementString(GetErrorText(), xEntry->getReplacementText())); + + int nLenChange = ChangeMarkedWord(sReplacement, LanguageTag::convertToLanguageType(pSpellErrorDescription->aLocale)); + + nCursor += sReplacement.getLength(); + + if (nLenChange) + m_xEditEngine->GetCharAttribs(0, aAttribList); + // maybe the error found here is already added to the dictionary and has to be ignored + } + else if(pSpellErrorDescription && !bGrammarError && + xSpell->isValid(GetErrorText(), + static_cast(LanguageTag::convertToLanguageType( pSpellErrorDescription->aLocale )), + Sequence< PropertyValue >() )) + { + ++nCursor; + } + else + break; + } + + //if an attrib has been found search for the end of the error string + if (nCursor < nTextLen) + { + MoveErrorMarkTo(nCursor, m_nErrorEnd, bGrammarError); + bRet = true; + //add an undo action + std::unique_ptr pAction(new SpellUndoAction_Impl( + SPELLUNDO_CHANGE_NEXTERROR, GetSpellDialog()->aDialogUndoLink)); + pAction->SetErrorMove(nOldErrorStart, nOldErrorEnd); + + if (GetErrorDescription(aSpellErrorDescription, nOldErrorStart)) + { + pAction->SetErrorLanguageSelected(aSpellErrorDescription.aSuggestions.hasElements() && + LanguageTag(aSpellErrorDescription.aLocale).getLanguageType() == GetSpellDialog()->m_xLanguageLB->get_active_id()); + } + else + pAction->SetErrorLanguageSelected(false); + + AddUndoAction(std::move(pAction)); + } + else + m_nErrorStart = m_nErrorEnd = nTextLen; + if( !bModified ) + ClearModifyFlag(); + SpellDialog* pSpellDialog = GetSpellDialog(); + pSpellDialog->m_xIgnorePB->set_sensitive(bRet); + pSpellDialog->m_xIgnoreAllPB->set_sensitive(bRet); + pSpellDialog->m_xAutoCorrPB->set_sensitive(bRet); + pSpellDialog->m_xAddToDictMB->set_sensitive(bRet); + pSpellDialog->m_xAddToDictPB->set_sensitive(bRet); + return bRet; +} + +void SentenceEditWindow_Impl::MoveErrorMarkTo(sal_Int32 nStart, sal_Int32 nEnd, bool bGrammarError) +{ + ESelection aAll(0, 0, 0, EE_TEXTPOS_ALL); + m_xEditEngine->RemoveAttribs(aAll, false, EE_CHAR_COLOR); + m_xEditEngine->RemoveAttribs(aAll, false, EE_CHAR_WEIGHT); + m_xEditEngine->RemoveAttribs(aAll, false, EE_CHAR_WEIGHT_CJK); + m_xEditEngine->RemoveAttribs(aAll, false, EE_CHAR_WEIGHT_CTL); + + SfxItemSet aSet(m_xEditEngine->GetEmptyItemSet()); + aSet.Put(SvxColorItem(bGrammarError ? COL_LIGHTBLUE : COL_LIGHTRED, EE_CHAR_COLOR)); + aSet.Put(SvxWeightItem(WEIGHT_BOLD, EE_CHAR_WEIGHT)); + aSet.Put(SvxWeightItem(WEIGHT_BOLD, EE_CHAR_WEIGHT_CJK)); + aSet.Put(SvxWeightItem(WEIGHT_BOLD, EE_CHAR_WEIGHT_CTL)); + + m_xEditEngine->QuickSetAttribs(aSet, ESelection(0, nStart, 0, nEnd)); + + // Set the selection so the editview will autoscroll to make this visible + // unless (tdf#133958) the selection already overlaps this range + ESelection aCurrentSelection = m_xEditView->GetSelection(); + aCurrentSelection.Adjust(); + bool bCurrentSelectionInRange = nStart <= aCurrentSelection.nEndPos && aCurrentSelection.nStartPos <= nEnd; + if (!bCurrentSelectionInRange) + { + m_xEditView->SetSelection(ESelection(0, nStart)); + } + + Invalidate(); + + m_nErrorStart = nStart; + m_nErrorEnd = nEnd; +} + +int SentenceEditWindow_Impl::ChangeMarkedWord(const OUString& rNewWord, LanguageType eLanguage) +{ + std::vector aAttribList; + m_xEditEngine->GetCharAttribs(0, aAttribList); + + //calculate length changes + auto nDiffLen = rNewWord.getLength() - m_nErrorEnd + m_nErrorStart; + //Remove spell error attribute + m_xEditEngine->UndoActionStart(SPELLUNDO_MOVE_ERROREND); + const EECharAttrib* pErrorAttrib = FindCharAttrib(m_nErrorStart, EE_CHAR_GRABBAG, aAttribList); + DBG_ASSERT(pErrorAttrib, "no error attribute found"); + bool bSpellErrorDescription = false; + SpellErrorDescription aSpellErrorDescription; + if (pErrorAttrib) + { + ExtractErrorDescription(*pErrorAttrib, aSpellErrorDescription); + m_xEditEngine->RemoveAttribs(ESelection(0, pErrorAttrib->nStart, 0, pErrorAttrib->nEnd), false, EE_CHAR_GRABBAG); + bSpellErrorDescription = true; + } + + const EECharAttrib* pBackAttrib = FindCharAttrib(m_nErrorStart, EE_CHAR_BKGCOLOR, aAttribList); + + ESelection aSel(0, m_nErrorStart, 0, m_nErrorEnd); + m_xEditEngine->QuickInsertText(rNewWord, aSel); + + const sal_Int32 nTextLen = m_xEditEngine->GetTextLen(0); + + if (nDiffLen) + m_xEditEngine->GetCharAttribs(0, aAttribList); + + if (!m_nErrorStart) + { + //attributes following an error at the start of the text are not moved but expanded from the + //text engine - this is done to keep full-paragraph-attributes + //in the current case that handling is not desired + const EECharAttrib* pLangAttrib = FindCharAttrib(m_nErrorEnd, EE_CHAR_LANGUAGE, aAttribList); + + if (pLangAttrib && !pLangAttrib->nStart && pLangAttrib->nEnd == nTextLen) + { + LanguageType eNewLanguage = static_cast(pLangAttrib->pAttr)->GetLanguage(); + m_xEditEngine->RemoveAttribs(ESelection(0, pLangAttrib->nStart, 0, pLangAttrib->nEnd), false, EE_CHAR_LANGUAGE); + SetAttrib(SvxLanguageItem(eNewLanguage, EE_CHAR_LANGUAGE), m_nErrorEnd + nDiffLen, nTextLen); + } + } + + // undo expanded attributes! + if (pBackAttrib && pBackAttrib->nStart < m_nErrorStart && pBackAttrib->nEnd == m_nErrorEnd + nDiffLen) + { + std::unique_ptr xNewBackground(pBackAttrib->pAttr->Clone()); + const sal_Int32 nStart = pBackAttrib->nStart; + + m_xEditEngine->RemoveAttribs(ESelection(0, pBackAttrib->nStart, 0, pBackAttrib->nEnd), false, EE_CHAR_BKGCOLOR); + + SetAttrib(*xNewBackground, nStart, m_nErrorStart); + } + m_xEditEngine->SetModified(); + + //adjust end position + long nEndTemp = m_nErrorEnd; + nEndTemp += nDiffLen; + m_nErrorEnd = static_cast(nEndTemp); + + std::unique_ptr pAction(new SpellUndoAction_Impl( + SPELLUNDO_MOVE_ERROREND, GetSpellDialog()->aDialogUndoLink)); + pAction->SetOffset(nDiffLen); + AddUndoAction(std::move(pAction)); + if (bSpellErrorDescription) + { + SfxGrabBagItem aSpellErrorDescriptionItem(EE_CHAR_GRABBAG); + aSpellErrorDescriptionItem.GetGrabBag()["SpellErrorDescription"] <<= aSpellErrorDescription.toSequence(); + SetAttrib(aSpellErrorDescriptionItem, m_nErrorStart, m_nErrorEnd); + } + SetAttrib(SvxLanguageItem(eLanguage, EE_CHAR_LANGUAGE), m_nErrorStart, m_nErrorEnd); + m_xEditEngine->UndoActionEnd(); + + Invalidate(); + + return nDiffLen; +} + +OUString SentenceEditWindow_Impl::GetErrorText() const +{ + return m_xEditEngine->GetText(ESelection(0, m_nErrorStart, 0, m_nErrorEnd)); +} + +bool SentenceEditWindow_Impl::GetErrorDescription(SpellErrorDescription& rSpellErrorDescription, sal_Int32 nPosition) +{ + std::vector aAttribList; + m_xEditEngine->GetCharAttribs(0, aAttribList); + + if (const EECharAttrib* pEECharAttrib = FindCharAttrib(nPosition, EE_CHAR_GRABBAG, aAttribList)) + { + ExtractErrorDescription(*pEECharAttrib, rSpellErrorDescription); + return true; + } + + return false; +} + +bool SentenceEditWindow_Impl::GetAlternatives(SpellErrorDescription& rSpellErrorDescription) +{ + return GetErrorDescription(rSpellErrorDescription, m_nErrorStart); +} + +void SentenceEditWindow_Impl::RestoreCurrentError() +{ + SpellErrorDescription aSpellErrorDescription; + if (GetErrorDescription(aSpellErrorDescription, m_nErrorStart)) + { + if (aSpellErrorDescription.sErrorText != GetErrorText() ) + ChangeMarkedWord(aSpellErrorDescription.sErrorText, LanguageTag::convertToLanguageType(aSpellErrorDescription.aLocale)); + } +} + +void SentenceEditWindow_Impl::SetAlternatives( const Reference< XSpellAlternatives>& xAlt ) +{ + OUString aWord; + lang::Locale aLocale; + uno::Sequence< OUString > aAlts; + OUString sServiceName; + if (xAlt.is()) + { + aWord = xAlt->getWord(); + aLocale = xAlt->getLocale(); + aAlts = xAlt->getAlternatives(); + uno::Reference< container::XNamed > xNamed( xAlt, uno::UNO_QUERY ); + if (xNamed.is()) + sServiceName = xNamed->getName(); + } + SpellErrorDescription aDesc( false, aWord, aLocale, aAlts, nullptr); + SfxGrabBagItem aSpellErrorDescription(EE_CHAR_GRABBAG); + aSpellErrorDescription.GetGrabBag()["SpellErrorDescription"] <<= aDesc.toSequence(); + SetAttrib(aSpellErrorDescription, m_nErrorStart, m_nErrorEnd); +} + +void SentenceEditWindow_Impl::SetAttrib(const SfxPoolItem& rItem, sal_Int32 nStart, sal_Int32 nEnd) +{ + SfxItemSet aSet(m_xEditEngine->GetEmptyItemSet()); + aSet.Put(rItem); + m_xEditEngine->QuickSetAttribs(aSet, ESelection(0, nStart, 0, nEnd)); + Invalidate(); +} + +void SentenceEditWindow_Impl::SetText( const OUString& rStr ) +{ + m_nErrorStart = m_nErrorEnd = 0; + m_xEditEngine->SetText(rStr); +} + +namespace { + +struct LanguagePosition_Impl +{ + sal_Int32 nPosition; + LanguageType eLanguage; + + LanguagePosition_Impl(sal_Int32 nPos, LanguageType eLang) : + nPosition(nPos), + eLanguage(eLang) + {} +}; + +} + +typedef std::vector LanguagePositions_Impl; + +static void lcl_InsertBreakPosition_Impl( + LanguagePositions_Impl& rBreakPositions, sal_Int32 nInsert, LanguageType eLanguage) +{ + LanguagePositions_Impl::iterator aStart = rBreakPositions.begin(); + while(aStart != rBreakPositions.end()) + { + if(aStart->nPosition == nInsert) + { + //the language of following starts has to overwrite + //the one of previous ends + aStart->eLanguage = eLanguage; + return; + } + else if(aStart->nPosition > nInsert) + { + + rBreakPositions.insert(aStart, LanguagePosition_Impl(nInsert, eLanguage)); + return; + } + else + ++aStart; + } + rBreakPositions.emplace_back(nInsert, eLanguage); +} + +/*------------------------------------------------------------------------- + Returns the text in spell portions. Each portion contains text with an + equal language and attribute. The spell alternatives are empty. + -----------------------------------------------------------------------*/ +svx::SpellPortions SentenceEditWindow_Impl::CreateSpellPortions() const +{ + svx::SpellPortions aRet; + + const sal_Int32 nTextLen = m_xEditEngine->GetTextLen(0); + + std::vector aAttribList; + m_xEditEngine->GetCharAttribs(0, aAttribList); + + if (nTextLen) + { + int nCursor(0); + LanguagePositions_Impl aBreakPositions; + const EECharAttrib* pLastLang = nullptr; + const EECharAttrib* pLastError = nullptr; + LanguageType eLang = LANGUAGE_DONTKNOW; + const EECharAttrib* pError = nullptr; + while (nCursor < nTextLen) + { + const EECharAttrib* pLang = FindCharAttrib(nCursor, EE_CHAR_LANGUAGE, aAttribList); + if(pLang && pLang != pLastLang) + { + eLang = static_cast(pLang->pAttr)->GetLanguage(); + lcl_InsertBreakPosition_Impl(aBreakPositions, pLang->nStart, eLang); + lcl_InsertBreakPosition_Impl(aBreakPositions, pLang->nEnd, eLang); + pLastLang = pLang; + } + pError = FindCharAttrib(nCursor, EE_CHAR_GRABBAG, aAttribList); + if (pError && pLastError != pError) + { + lcl_InsertBreakPosition_Impl(aBreakPositions, pError->nStart, eLang); + lcl_InsertBreakPosition_Impl(aBreakPositions, pError->nEnd, eLang); + pLastError = pError; + + } + ++nCursor; + } + + if (aBreakPositions.empty()) + { + //if all content has been overwritten the attributes may have been removed, too + svx::SpellPortion aPortion1; + aPortion1.eLanguage = GetSpellDialog()->GetSelectedLang_Impl(); + + aPortion1.sText = m_xEditEngine->GetText(ESelection(0, 0, 0, nTextLen)); + + aRet.push_back(aPortion1); + } + else + { + LanguagePositions_Impl::iterator aStart = aBreakPositions.begin(); + //start should always be Null + eLang = aStart->eLanguage; + sal_Int32 nStart = aStart->nPosition; + DBG_ASSERT(!nStart, "invalid start position - language attribute missing?"); + ++aStart; + + while(aStart != aBreakPositions.end()) + { + svx::SpellPortion aPortion1; + aPortion1.eLanguage = eLang; + + aPortion1.sText = m_xEditEngine->GetText(ESelection(0, nStart, 0, aStart->nPosition)); + + bool bIsIgnoreError = m_aIgnoreErrorsAt.find( nStart ) != m_aIgnoreErrorsAt.end(); + if( bIsIgnoreError ) + { + aPortion1.bIgnoreThisError = true; + } + aRet.push_back(aPortion1); + nStart = aStart->nPosition; + eLang = aStart->eLanguage; + ++aStart; + } + } + + // quick partly fix of #i71318. Correct fix needs to patch the EditEngine itself... + // this one will only prevent text from disappearing. It may to not have the + // correct language and will probably not spell checked... + const sal_uInt32 nPara = m_xEditEngine->GetParagraphCount(); + if (nPara > 1) + { + OUStringBuffer aLeftOverText; + for (sal_uInt32 i = 1; i < nPara; ++i) + { + aLeftOverText.append("\x0a"); // the manual line break... + aLeftOverText.append(m_xEditEngine->GetText(i)); + } + if (pError) + { // we need to add a new portion containing the left-over text + svx::SpellPortion aPortion2; + aPortion2.eLanguage = eLang; + aPortion2.sText = aLeftOverText.makeStringAndClear(); + aRet.push_back( aPortion2 ); + } + else + { // we just need to append the left-over text to the last portion (which had no errors) + aRet[ aRet.size() - 1 ].sText += aLeftOverText; + } + } + } + + return aRet; +} + +void SentenceEditWindow_Impl::Undo() +{ + SfxUndoManager& rUndoMgr = m_xEditEngine->GetUndoManager(); + DBG_ASSERT(GetUndoActionCount(), "no undo actions available" ); + if(!GetUndoActionCount()) + return; + bool bSaveUndoEdit = IsUndoEditMode(); + SpellUndoAction_Impl* pUndoAction; + //if the undo edit mode is active then undo all changes until the UNDO_EDIT_MODE action has been found + do + { + pUndoAction = static_cast(rUndoMgr.GetUndoAction()); + rUndoMgr.Undo(); + }while(bSaveUndoEdit && SPELLUNDO_UNDO_EDIT_MODE != pUndoAction->GetId() && GetUndoActionCount()); + + if(bSaveUndoEdit || SPELLUNDO_CHANGE_GROUP == pUndoAction->GetId()) + GetSpellDialog()->UpdateBoxes_Impl(); +} + +void SentenceEditWindow_Impl::ResetUndo() +{ + SfxUndoManager& rUndo = m_xEditEngine->GetUndoManager(); + rUndo.Clear(); +} + +void SentenceEditWindow_Impl::AddUndoAction( std::unique_ptr pAction ) +{ + SfxUndoManager& rUndoMgr = m_xEditEngine->GetUndoManager(); + rUndoMgr.AddUndoAction(std::move(pAction)); + GetSpellDialog()->m_xUndoPB->set_sensitive(true); +} + +size_t SentenceEditWindow_Impl::GetUndoActionCount() const +{ + return m_xEditEngine->GetUndoManager().GetUndoActionCount(); +} + +void SentenceEditWindow_Impl::UndoActionStart( sal_uInt16 nId ) +{ + m_xEditEngine->UndoActionStart(nId); +} + +void SentenceEditWindow_Impl::UndoActionEnd() +{ + m_xEditEngine->UndoActionEnd(); +} + +void SentenceEditWindow_Impl::MoveErrorEnd(long nOffset) +{ + // Shouldn't we always add the real signed value instead??? + if(nOffset > 0) + m_nErrorEnd = m_nErrorEnd - static_cast(nOffset); + else + m_nErrorEnd = m_nErrorEnd - static_cast(-nOffset); +} + + +void SentenceEditWindow_Impl::SetUndoEditMode(bool bSet) +{ + DBG_ASSERT(!bSet || m_bIsUndoEditMode != bSet, "SetUndoEditMode with equal values?"); + m_bIsUndoEditMode = bSet; + //disable all buttons except the Change + SpellDialog* pSpellDialog = GetSpellDialog(); + weld::Widget* aControls[] = + { + pSpellDialog->m_xChangeAllPB.get(), + pSpellDialog->m_xExplainFT.get(), + pSpellDialog->m_xIgnoreAllPB.get(), + pSpellDialog->m_xIgnoreRulePB.get(), + pSpellDialog->m_xIgnorePB.get(), + pSpellDialog->m_xSuggestionLB.get(), + pSpellDialog->m_xSuggestionFT.get(), + pSpellDialog->m_xLanguageFT.get(), + pSpellDialog->m_xLanguageLB->get_widget(), + pSpellDialog->m_xAddToDictMB.get(), + pSpellDialog->m_xAddToDictPB.get(), + pSpellDialog->m_xAutoCorrPB.get(), + nullptr + }; + sal_Int32 nIdx = 0; + do + { + aControls[nIdx]->set_sensitive(false); + } + while(aControls[++nIdx]); + + //remove error marks + ESelection aAll(0, 0, 0, EE_TEXTPOS_ALL); + m_xEditEngine->RemoveAttribs(aAll, false, EE_CHAR_COLOR); + m_xEditEngine->RemoveAttribs(aAll, false, EE_CHAR_WEIGHT); + m_xEditEngine->RemoveAttribs(aAll, false, EE_CHAR_WEIGHT_CJK); + m_xEditEngine->RemoveAttribs(aAll, false, EE_CHAR_WEIGHT_CTL); + Invalidate(); + + //put the appropriate action on the Undo-stack + AddUndoAction( std::make_unique( + SPELLUNDO_UNDO_EDIT_MODE, GetSpellDialog()->aDialogUndoLink) ); + pSpellDialog->m_xChangePB->set_sensitive(true); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/about.cxx b/cui/source/dialogs/about.cxx new file mode 100644 index 000000000..99245b94b --- /dev/null +++ b/cui/source/dialogs/about.cxx @@ -0,0 +1,260 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include //osl_getProcessLocale +#include //rtl::isAsciiHexDigit +#include //SAL_WARN +#include //GetSettings +#include //Application:: +#include //VirtualDevice +#include + +#include //EXTRA_BUILDID +#include //CuiResId +#include +#include //SfxApplication::loadBrandSvg +#include +#include +#include //utl::Bootstrap::getBuildIdData +#include //ConfigManager:: + +#include +#include + +#include +#if HAVE_FEATURE_OPENCL +#include +#endif +#include +#include + +using namespace ::com::sun::star::uno; + +AboutDialog::AboutDialog(weld::Window *pParent) + : GenericDialogController(pParent, "cui/ui/aboutdialog.ui", "AboutDialog"), + m_pCreditsButton(m_xBuilder->weld_link_button("btnCredits")), + m_pWebsiteButton(m_xBuilder->weld_link_button("btnWebsite")), + m_pReleaseNotesButton(m_xBuilder->weld_link_button("btnReleaseNotes")), + m_pCloseButton(m_xBuilder->weld_button("btnClose")), + m_pCopyButton(m_xBuilder->weld_button("btnCopyVersion")), + m_pBrandImage(m_xBuilder->weld_image("imBrand")), + m_pAboutImage(m_xBuilder->weld_image("imAbout")), + m_pVersionLabel(m_xBuilder->weld_label("lbVersionString")), + m_pBuildCaption(m_xBuilder->weld_label("lbBuild")), + m_pBuildLabel(m_xBuilder->weld_link_button("lbBuildString")), + m_pEnvLabel(m_xBuilder->weld_label("lbEnvString")), + m_pUILabel(m_xBuilder->weld_label("lbUIString")), + m_pLocaleLabel(m_xBuilder->weld_label("lbLocaleString")), + m_pMiscLabel(m_xBuilder->weld_label("lbMiscString")), + m_pCopyrightLabel(m_xBuilder->weld_label("lbCopyright")) { + + // Labels + m_pVersionLabel->set_label(GetVersionString()); + + OUString sbuildId = GetBuildString(); + const long nMaxChar = 25; + if (IsStringValidGitHash(sbuildId)) { + m_pBuildLabel->set_uri("https://gerrit.libreoffice.org/gitweb?p=core.git;a=log;h=" + + sbuildId); + m_pBuildLabel->set_label(sbuildId.getLength() > nMaxChar ? sbuildId.replaceAt( + nMaxChar, sbuildId.getLength() - nMaxChar, "...") + : sbuildId); + } else { + m_pBuildCaption->hide(); + m_pBuildLabel->hide(); + } + + m_pEnvLabel->set_label(Application::GetHWOSConfInfo(1)); + m_pUILabel->set_label(Application::GetHWOSConfInfo(2)); + m_pLocaleLabel->set_label(GetLocaleString()); + m_pMiscLabel->set_label(GetMiscString()); + m_pCopyrightLabel->set_label(GetCopyrightString()); + + // Images + const long nWidth(m_pCopyrightLabel->get_preferred_size().getWidth()); + BitmapEx aBackgroundBitmap; + + if (SfxApplication::loadBrandSvg(Application::GetSettings() + .GetStyleSettings() + .GetDialogColor() + .IsDark() + ? "shell/logo_inverted" + : "shell/logo", + aBackgroundBitmap, nWidth * 0.8)) { + ScopedVclPtr m_pVirDev = + m_pBrandImage->create_virtual_device(); + m_pVirDev->SetOutputSizePixel(aBackgroundBitmap.GetSizePixel()); + m_pVirDev->DrawBitmapEx(Point(0, 0), aBackgroundBitmap); + m_pBrandImage->set_image(m_pVirDev.get()); + m_pVirDev.disposeAndClear(); + } + if (SfxApplication::loadBrandSvg("shell/about", aBackgroundBitmap, nWidth * 0.9)) { + ScopedVclPtr m_pVirDev = + m_pAboutImage->create_virtual_device(); + m_pVirDev->SetOutputSizePixel(aBackgroundBitmap.GetSizePixel()); + m_pVirDev->DrawBitmapEx(Point(0, 0), aBackgroundBitmap); + m_pAboutImage->set_image(m_pVirDev.get()); + m_pVirDev.disposeAndClear(); + } + + // Links + m_pCreditsButton->set_uri(CuiResId(RID_SVXSTR_ABOUT_CREDITS_URL)); + + OUString sURL(officecfg::Office::Common::Help::StartCenter::InfoURL::get()); + localizeWebserviceURI(sURL); + m_pWebsiteButton->set_uri(sURL); + + sURL = officecfg::Office::Common::Menus::ReleaseNotesURL::get() + + "?LOvers=" + utl::ConfigManager::getProductVersion() + "&LOlocale=" + + LanguageTag(utl::ConfigManager::getUILocale()).getLanguage(); + m_pReleaseNotesButton->set_uri(sURL); + + // Handler + m_pCopyButton->connect_clicked(LINK(this, AboutDialog, HandleClick)); + m_pCloseButton->grab_focus(); +} + +AboutDialog::~AboutDialog() {} + +bool AboutDialog::IsStringValidGitHash(const OUString &hash) { + for (int i = 0; i < hash.getLength(); i++) { + if (!std::isxdigit(hash[i])) { + return false; + } + } + return true; +} + +OUString AboutDialog::GetVersionString() { + OUString sVersion = CuiResId("%ABOUTBOXPRODUCTVERSION%ABOUTBOXPRODUCTVERSIONSUFFIX"); + +#ifdef _WIN64 + sVersion += " (x64)"; +#elif defined(_WIN32) + sVersion += " (x86)"; +#endif + return sVersion; +} + +OUString AboutDialog::GetBuildString() +{ + OUString sBuildId(utl::Bootstrap::getBuildIdData("")); + SAL_WARN_IF(sBuildId.isEmpty(), "cui.dialogs", "No BUILDID in bootstrap file"); + + return sBuildId; +} + +OUString AboutDialog::GetLocaleString() { + + OUString sLocaleStr; + + rtl_Locale *pLocale; + osl_getProcessLocale(&pLocale); + if (pLocale && pLocale->Language) { + if (pLocale->Country && rtl_uString_getLength(pLocale->Country) > 0) + sLocaleStr = OUString::unacquired(&pLocale->Language) + "_" + + OUString::unacquired(&pLocale->Country); + else + sLocaleStr = OUString(pLocale->Language); + if (pLocale->Variant && rtl_uString_getLength(pLocale->Variant) > 0) + sLocaleStr += OUString(pLocale->Variant); + } + + sLocaleStr = Application::GetSettings().GetLanguageTag().getBcp47() + " (" + + sLocaleStr + ")"; + + OUString aUILocaleStr = + Application::GetSettings().GetUILanguageTag().getBcp47(); + OUString sUILocaleStr(CuiResId(RID_SVXSTR_ABOUT_UILOCALE)); + if (sUILocaleStr.indexOf("$LOCALE") == -1) { + SAL_WARN("cui.dialogs", "translated uilocale string in translations " + "doesn't contain $LOCALE placeholder"); + sUILocaleStr += " $LOCALE"; + } + sUILocaleStr = sUILocaleStr.replaceAll("$LOCALE", aUILocaleStr); + + return sLocaleStr + "; " + sUILocaleStr; +} + +OUString AboutDialog::GetMiscString() { + + OUString sMisc; + + bool const extra = EXTRA_BUILDID[0] != '\0'; + // extracted from the 'if' to avoid Clang -Wunreachable-code + if (extra) { + sMisc = EXTRA_BUILDID "\n"; + } + + OUString aCalcMode = "Calc: "; // Calc calculation mode + +#if HAVE_FEATURE_OPENCL + bool bOpenCL = openclwrapper::GPUEnv::isOpenCLEnabled(); + if (bOpenCL) + aCalcMode += "CL"; +#else + const bool bOpenCL = false; +#endif + + static const bool bThreadingProhibited = + std::getenv("SC_NO_THREADED_CALCULATION"); + bool bThreadedCalc = officecfg::Office::Calc::Formula::Calculation:: + UseThreadedCalculationForFormulaGroups::get(); + + if (!bThreadingProhibited && !bOpenCL && bThreadedCalc) { + if (!aCalcMode.endsWith(" ")) + aCalcMode += " "; + aCalcMode += "threaded"; + } + + sMisc += aCalcMode; + + return sMisc; +} + +OUString AboutDialog::GetCopyrightString() { + OUString sVendorTextStr(CuiResId(RID_SVXSTR_ABOUT_VENDOR)); + OUString aCopyrightString = + sVendorTextStr + "\n" + CuiResId(RID_SVXSTR_ABOUT_COPYRIGHT) + "\n"; + + if (utl::ConfigManager::getProductName() == "LibreOffice") + aCopyrightString += CuiResId(RID_SVXSTR_ABOUT_BASED_ON); + else + aCopyrightString += CuiResId(RID_SVXSTR_ABOUT_DERIVED); + + return aCopyrightString; +} + +//special labels to comply with previous version info +IMPL_LINK_NOARG(AboutDialog, HandleClick, weld::Button &, void) { + css::uno::Reference xClipboard = + css::datatransfer::clipboard::SystemClipboard::create( + comphelper::getProcessComponentContext()); + + OUString sInfo = "Version: " + m_pVersionLabel->get_label() + "\n" // version + "Build ID: " + GetBuildString() + "\n" + // build id + Application::GetHWOSConfInfo(0,false) + "\n" // env+UI + "Locale: " + m_pLocaleLabel->get_label() + "\n" + // locale + m_pMiscLabel->get_label(); // misc + + vcl::unohelper::TextDataObject::CopyStringTo(sInfo, xClipboard); +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ \ No newline at end of file diff --git a/cui/source/dialogs/colorpicker.cxx b/cui/source/dialogs/colorpicker.cxx new file mode 100644 index 000000000..65f03fb3a --- /dev/null +++ b/cui/source/dialogs/colorpicker.cxx @@ -0,0 +1,1334 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star::beans; +using namespace ::basegfx; + +namespace { + +enum class UpdateFlags +{ + NONE = 0x00, + RGB = 0x01, + CMYK = 0x02, + HSB = 0x04, + ColorChooser = 0x08, + ColorSlider = 0x10, + Hex = 0x20, + All = 0x3f, +}; + +} + +namespace o3tl { + template<> struct typed_flags : is_typed_flags {}; +} + + +namespace cui +{ + +namespace { + +enum class ColorComponent { + Red, + Green, + Blue, + Hue, + Saturation, + Brightness, + Cyan, + Yellow, + Magenta, + Key, +}; + +} + +// color space conversion helpers + +static void RGBtoHSV( double dR, double dG, double dB, double& dH, double& dS, double& dV ) +{ + BColor result = basegfx::utils::rgb2hsv( BColor( dR, dG, dB ) ); + + dH = result.getX(); + dS = result.getY(); + dV = result.getZ(); +} + +static void HSVtoRGB(double dH, double dS, double dV, double& dR, double& dG, double& dB ) +{ + BColor result = basegfx::utils::hsv2rgb( BColor( dH, dS, dV ) ); + + dR = result.getRed(); + dG = result.getGreen(); + dB = result.getBlue(); +} + +// CMYK values from 0 to 1 +static void CMYKtoRGB( double fCyan, double fMagenta, double fYellow, double fKey, double& dR, double& dG, double& dB ) +{ + fCyan = (fCyan * ( 1.0 - fKey )) + fKey; + fMagenta = (fMagenta * ( 1.0 - fKey )) + fKey; + fYellow = (fYellow * ( 1.0 - fKey )) + fKey; + + dR = std::max( std::min( ( 1.0 - fCyan ), 1.0), 0.0 ); + dG = std::max( std::min( ( 1.0 - fMagenta ), 1.0), 0.0 ); + dB = std::max( std::min( ( 1.0 - fYellow ), 1.0), 0.0 ); +} + +// CMY results from 0 to 1 +static void RGBtoCMYK( double dR, double dG, double dB, double& fCyan, double& fMagenta, double& fYellow, double& fKey ) +{ + fCyan = 1 - dR; + fMagenta = 1 - dG; + fYellow = 1 - dB; + + //CMYK and CMY values from 0 to 1 + fKey = 1.0; + if( fCyan < fKey ) fKey = fCyan; + if( fMagenta < fKey ) fKey = fMagenta; + if( fYellow < fKey ) fKey = fYellow; + + if( fKey >= 1.0 ) + { + //Black + fCyan = 0.0; + fMagenta = 0.0; + fYellow = 0.0; + } + else + { + fCyan = ( fCyan - fKey ) / ( 1.0 - fKey ); + fMagenta = ( fMagenta - fKey ) / ( 1.0 - fKey ); + fYellow = ( fYellow - fKey ) / ( 1.0 - fKey ); + } +} + +namespace { + +class ColorPreviewControl : public weld::CustomWidgetController +{ +private: + Color m_aColor; + + virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&) override; +public: + ColorPreviewControl() + { + } + + virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override + { + CustomWidgetController::SetDrawingArea(pDrawingArea); + pDrawingArea->set_size_request(pDrawingArea->get_approximate_digit_width() * 10, + pDrawingArea->get_text_height() * 2); + } + + void SetColor(const Color& rCol) + { + if (rCol != m_aColor) + { + m_aColor = rCol; + Invalidate(); + } + } +}; + +} + +void ColorPreviewControl::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&) +{ + rRenderContext.SetFillColor(m_aColor); + rRenderContext.SetLineColor(m_aColor); + rRenderContext.DrawRect(tools::Rectangle(Point(0, 0), GetOutputSizePixel())); +} + +namespace { + +enum ColorMode { HUE, SATURATION, BRIGHTNESS, RED, GREEN, BLUE }; + +} + +const ColorMode DefaultMode = HUE; + +namespace { + +class ColorFieldControl : public weld::CustomWidgetController +{ +public: + ColorFieldControl() + : meMode( DefaultMode ) + , mdX( -1.0 ) + , mdY( -1.0 ) + , mbMouseCaptured(false) + { + } + + virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override + { + CustomWidgetController::SetDrawingArea(pDrawingArea); + pDrawingArea->set_size_request(pDrawingArea->get_approximate_digit_width() * 40, + pDrawingArea->get_text_height() * 10); + } + + virtual ~ColorFieldControl() override + { + mxBitmap.disposeAndClear(); + } + + virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override; + virtual void Resize() override; + virtual bool MouseButtonDown(const MouseEvent& rMEvt) override; + virtual bool MouseMove(const MouseEvent& rMEvt) override; + virtual bool MouseButtonUp(const MouseEvent& rMEvt) override; + + void UpdateBitmap(); + void ShowPosition( const Point& rPos, bool bUpdate ); + void UpdatePosition(); + void Modify(); + + void SetValues(Color aColor, ColorMode eMode, double x, double y); + double GetX() const { return mdX;} + double GetY() const { return mdY;} + + void SetModifyHdl(const Link& rLink) { maModifyHdl = rLink; } + +private: + ColorMode meMode; + Color maColor; + double mdX; + double mdY; + bool mbMouseCaptured; + Point maPosition; + VclPtr mxBitmap; + Link maModifyHdl; + std::vector maRGB_Horiz; + std::vector maGrad_Horiz; + std::vector maPercent_Horiz; + std::vector maRGB_Vert; + std::vector maPercent_Vert; +}; + +} + +void ColorFieldControl::UpdateBitmap() +{ + const Size aSize(GetOutputSizePixel()); + + if (mxBitmap && mxBitmap->GetOutputSizePixel() != aSize) + mxBitmap.disposeAndClear(); + + const sal_Int32 nWidth = aSize.Width(); + const sal_Int32 nHeight = aSize.Height(); + + if (nWidth == 0 || nHeight == 0) + return; + + if (!mxBitmap) + { + mxBitmap = VclPtr::Create(); + mxBitmap->SetOutputSizePixel(aSize); + + maRGB_Horiz.resize( nWidth ); + maGrad_Horiz.resize( nWidth ); + maPercent_Horiz.resize( nWidth ); + + sal_uInt8* pRGB = maRGB_Horiz.data(); + sal_uInt16* pGrad = maGrad_Horiz.data(); + sal_uInt16* pPercent = maPercent_Horiz.data(); + + for( sal_Int32 x = 0; x < nWidth; x++ ) + { + *pRGB++ = static_cast((x * 256) / nWidth); + *pGrad++ = static_cast((x * 359) / nWidth); + *pPercent++ = static_cast((x * 100) / nWidth); + } + + maRGB_Vert.resize(nHeight); + maPercent_Vert.resize(nHeight); + + pRGB = maRGB_Vert.data(); + pPercent = maPercent_Vert.data(); + + sal_Int32 y = nHeight; + while (y--) + { + *pRGB++ = static_cast((y * 256) / nHeight); + *pPercent++ = static_cast((y * 100) / nHeight); + } + } + + sal_uInt8* pRGB_Horiz = maRGB_Horiz.data(); + sal_uInt16* pGrad_Horiz = maGrad_Horiz.data(); + sal_uInt16* pPercent_Horiz = maPercent_Horiz.data(); + sal_uInt8* pRGB_Vert = maRGB_Vert.data(); + sal_uInt16* pPercent_Vert = maPercent_Vert.data(); + + Color aBitmapColor(maColor); + + sal_uInt16 nHue, nSat, nBri; + maColor.RGBtoHSB(nHue, nSat, nBri); + + // this has been unlooped for performance reason, please do not merge back! + + sal_uInt16 y = nHeight,x; + + switch(meMode) + { + case HUE: + while (y--) + { + nBri = pPercent_Vert[y]; + x = nWidth; + while (x--) + { + nSat = pPercent_Horiz[x]; + mxBitmap->DrawPixel(Point(x,y), Color::HSBtoRGB(nHue, nSat, nBri)); + } + } + break; + case SATURATION: + while (y--) + { + nBri = pPercent_Vert[y]; + x = nWidth; + while (x--) + { + nHue = pGrad_Horiz[x]; + mxBitmap->DrawPixel(Point(x,y), Color::HSBtoRGB(nHue, nSat, nBri)); + } + } + break; + case BRIGHTNESS: + while (y--) + { + nSat = pPercent_Vert[y]; + x = nWidth; + while (x--) + { + nHue = pGrad_Horiz[x]; + mxBitmap->DrawPixel(Point(x,y), Color::HSBtoRGB(nHue, nSat, nBri)); + } + } + break; + case RED: + while (y--) + { + aBitmapColor.SetGreen(pRGB_Vert[y]); + x = nWidth; + while (x--) + { + aBitmapColor.SetBlue(pRGB_Horiz[x]); + mxBitmap->DrawPixel(Point(x,y), aBitmapColor); + } + } + break; + case GREEN: + while (y--) + { + aBitmapColor.SetRed(pRGB_Vert[y]); + x = nWidth; + while (x--) + { + aBitmapColor.SetBlue(pRGB_Horiz[x]); + mxBitmap->DrawPixel(Point(x,y), aBitmapColor); + } + } + break; + case BLUE: + while (y--) + { + aBitmapColor.SetGreen(pRGB_Vert[y]); + x = nWidth; + while (x--) + { + aBitmapColor.SetRed(pRGB_Horiz[x]); + mxBitmap->DrawPixel(Point(x,y), aBitmapColor); + } + } + break; + } +} + +void ColorFieldControl::ShowPosition( const Point& rPos, bool bUpdate ) +{ + if (!mxBitmap) + { + UpdateBitmap(); + Invalidate(); + } + + if (!mxBitmap) + return; + + const Size aSize(mxBitmap->GetOutputSizePixel()); + + long nX = rPos.X(); + long nY = rPos.Y(); + if (nX < 0) + nX = 0; + else if (nX >= aSize.Width()) + nX = aSize.Width() - 1; + + if (nY < 0) + nY = 0; + else if (nY >= aSize.Height()) + nY = aSize.Height() - 1; + + Point aPos = maPosition; + maPosition.setX( nX - 5 ); + maPosition.setY( nY - 5 ); + Invalidate(tools::Rectangle(aPos, Size(11, 11))); + Invalidate(tools::Rectangle(maPosition, Size(11, 11))); + + if (bUpdate) + { + mdX = double(nX) / double(aSize.Width() - 1.0); + mdY = double(aSize.Height() - 1.0 - nY) / double(aSize.Height() - 1.0); + + maColor = mxBitmap->GetPixel(Point(nX, nY)); + } +} + +bool ColorFieldControl::MouseButtonDown(const MouseEvent& rMEvt) +{ + CaptureMouse(); + mbMouseCaptured = true; + ShowPosition(rMEvt.GetPosPixel(), true); + Modify(); + return true; +} + +bool ColorFieldControl::MouseMove(const MouseEvent& rMEvt) +{ + if (mbMouseCaptured) + { + ShowPosition(rMEvt.GetPosPixel(), true); + Modify(); + } + return true; +} + +bool ColorFieldControl::MouseButtonUp(const MouseEvent&) +{ + ReleaseMouse(); + mbMouseCaptured = false; + return true; +} + +void ColorFieldControl::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&) +{ + if (!mxBitmap) + UpdateBitmap(); + + if (mxBitmap) + { + Size aSize(GetOutputSizePixel()); + rRenderContext.DrawOutDev(Point(0, 0), aSize, Point(0, 0), aSize, *mxBitmap); + } + + // draw circle around current color + if (maColor.IsDark()) + rRenderContext.SetLineColor( COL_WHITE ); + else + rRenderContext.SetLineColor( COL_BLACK ); + + rRenderContext.SetFillColor(); + + rRenderContext.DrawEllipse(::tools::Rectangle(maPosition, Size(11, 11))); +} + +void ColorFieldControl::Resize() +{ + CustomWidgetController::Resize(); + UpdateBitmap(); + UpdatePosition(); +} + +void ColorFieldControl::Modify() +{ + maModifyHdl.Call( *this ); +} + +void ColorFieldControl::SetValues( Color aColor, ColorMode eMode, double x, double y ) +{ + bool bUpdateBitmap = (maColor!= aColor) || (meMode != eMode); + if( !(bUpdateBitmap || (mdX != x) || (mdY != y)) ) + return; + + maColor = aColor; + meMode = eMode; + mdX = x; + mdY = y; + + if (bUpdateBitmap) + UpdateBitmap(); + UpdatePosition(); + if (bUpdateBitmap) + Invalidate(); +} + +void ColorFieldControl::UpdatePosition() +{ + Size aSize(GetOutputSizePixel()); + ShowPosition(Point(static_cast(mdX * aSize.Width()), static_cast((1.0 - mdY) * aSize.Height())), false); +} + +namespace { + +class ColorSliderControl : public weld::CustomWidgetController +{ +public: + ColorSliderControl(); + virtual ~ColorSliderControl() override; + + virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override; + + virtual bool MouseButtonDown(const MouseEvent& rMEvt) override; + virtual bool MouseMove(const MouseEvent& rMEvt) override; + virtual bool MouseButtonUp(const MouseEvent& rMEvt) override; + virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&) override; + virtual void Resize() override; + + void UpdateBitmap(); + void ChangePosition( long nY ); + void Modify(); + + void SetValue( const Color& rColor, ColorMode eMode, double dValue ); + double GetValue() const { return mdValue; } + + void SetModifyHdl( const Link& rLink ) { maModifyHdl = rLink; } + + sal_Int16 GetLevel() const { return mnLevel; } + +private: + Link maModifyHdl; + Color maColor; + ColorMode meMode; + VclPtr mxBitmap; + sal_Int16 mnLevel; + double mdValue; +}; + +} + +ColorSliderControl::ColorSliderControl() + : meMode( DefaultMode ) + , mnLevel( 0 ) + , mdValue( -1.0 ) +{ +} + +void ColorSliderControl::SetDrawingArea(weld::DrawingArea* pDrawingArea) +{ + CustomWidgetController::SetDrawingArea(pDrawingArea); + pDrawingArea->set_size_request(pDrawingArea->get_approximate_digit_width() * 3, -1); +} + +ColorSliderControl::~ColorSliderControl() +{ + mxBitmap.disposeAndClear(); +} + +void ColorSliderControl::UpdateBitmap() +{ + Size aSize(1, GetOutputSizePixel().Height()); + + if (mxBitmap && mxBitmap->GetOutputSizePixel() != aSize) + mxBitmap.disposeAndClear(); + + if (!mxBitmap) + { + mxBitmap = VclPtr::Create(); + mxBitmap->SetOutputSizePixel(aSize); + } + + const long nY = aSize.Height() - 1; + + Color aBitmapColor(maColor); + + sal_uInt16 nHue, nSat, nBri; + maColor.RGBtoHSB(nHue, nSat, nBri); + + // this has been unlooped for performance reason, please do not merge back! + + switch (meMode) + { + case HUE: + nSat = 100; + nBri = 100; + for (long y = 0; y <= nY; y++) + { + nHue = static_cast((359 * y) / nY); + mxBitmap->DrawPixel(Point(0, nY - y), Color::HSBtoRGB(nHue, nSat, nBri)); + } + break; + + case SATURATION: + nBri = std::max(sal_uInt16(32), nBri); + for (long y = 0; y <= nY; y++) + { + nSat = static_cast((100 * y) / nY); + mxBitmap->DrawPixel(Point(0, nY - y), Color::HSBtoRGB(nHue, nSat, nBri)); + } + break; + + case BRIGHTNESS: + for (long y = 0; y <= nY; y++) + { + nBri = static_cast((100 * y) / nY); + mxBitmap->DrawPixel(Point(0, nY - y), Color::HSBtoRGB(nHue, nSat, nBri)); + } + break; + + case RED: + for (long y = 0; y <= nY; y++) + { + aBitmapColor.SetRed(sal_uInt8((long(255) * y) / nY)); + mxBitmap->DrawPixel(Point(0, nY - y), aBitmapColor); + } + break; + + case GREEN: + for (long y = 0; y <= nY; y++) + { + aBitmapColor.SetGreen(sal_uInt8((long(255) * y) / nY)); + mxBitmap->DrawPixel(Point(0, nY - y), aBitmapColor); + } + break; + + case BLUE: + for (long y = 0; y <= nY; y++) + { + aBitmapColor.SetBlue(sal_uInt8((long(255) * y) / nY)); + mxBitmap->DrawPixel(Point(0, nY - y), aBitmapColor); + } + break; + } +} + +void ColorSliderControl::ChangePosition(long nY) +{ + const long nHeight = GetOutputSizePixel().Height() - 1; + + if (nY < 0) + nY = 0; + else if (nY > nHeight) + nY = nHeight; + + mnLevel = nY; + mdValue = double(nHeight - nY) / double(nHeight); +} + +bool ColorSliderControl::MouseButtonDown(const MouseEvent& rMEvt) +{ + CaptureMouse(); + ChangePosition(rMEvt.GetPosPixel().Y()); + Modify(); + return true; +} + +bool ColorSliderControl::MouseMove(const MouseEvent& rMEvt) +{ + if (IsMouseCaptured()) + { + ChangePosition(rMEvt.GetPosPixel().Y()); + Modify(); + } + return true; +} + +bool ColorSliderControl::MouseButtonUp(const MouseEvent&) +{ + ReleaseMouse(); + return true; +} + +void ColorSliderControl::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&) +{ + if (!mxBitmap) + UpdateBitmap(); + + const Size aSize(GetOutputSizePixel()); + + Point aPos; + int x = aSize.Width(); + while (x--) + { + rRenderContext.DrawOutDev(aPos, aSize, Point(0,0), aSize, *mxBitmap); + aPos.AdjustX(1); + } +} + +void ColorSliderControl::Resize() +{ + CustomWidgetController::Resize(); + UpdateBitmap(); +} + +void ColorSliderControl::Modify() +{ + maModifyHdl.Call(*this); +} + +void ColorSliderControl::SetValue(const Color& rColor, ColorMode eMode, double dValue) +{ + bool bUpdateBitmap = (rColor != maColor) || (eMode != meMode); + if( bUpdateBitmap || (mdValue != dValue)) + { + maColor = rColor; + mdValue = dValue; + mnLevel = static_cast((1.0-dValue) * GetOutputSizePixel().Height()); + meMode = eMode; + if (bUpdateBitmap) + UpdateBitmap(); + Invalidate(); + } +} + +namespace { + +class ColorPickerDialog : public weld::GenericDialogController +{ +private: + ColorFieldControl m_aColorField; + ColorSliderControl m_aColorSlider; + ColorPreviewControl m_aColorPreview; + ColorPreviewControl m_aColorPrevious; + + std::unique_ptr m_xColorField; + std::unique_ptr m_xColorSlider; + std::unique_ptr m_xColorPreview; + std::unique_ptr m_xColorPrevious; + + std::unique_ptr m_xFISliderLeft; + std::unique_ptr m_xFISliderRight; + std::unique_ptr m_xRBRed; + std::unique_ptr m_xRBGreen; + std::unique_ptr m_xRBBlue; + std::unique_ptr m_xRBHue; + std::unique_ptr m_xRBSaturation; + std::unique_ptr m_xRBBrightness; + + std::unique_ptr m_xMFRed; + std::unique_ptr m_xMFGreen; + std::unique_ptr m_xMFBlue; + std::unique_ptr m_xEDHex; + + std::unique_ptr m_xMFHue; + std::unique_ptr m_xMFSaturation; + std::unique_ptr m_xMFBrightness; + + std::unique_ptr m_xMFCyan; + std::unique_ptr m_xMFMagenta; + std::unique_ptr m_xMFYellow; + std::unique_ptr m_xMFKey; + +public: + ColorPickerDialog(weld::Window* pParent, Color nColor, sal_Int16 nMode); + + void update_color(UpdateFlags n = UpdateFlags::All); + + DECL_LINK(ColorFieldControlModifydl, ColorFieldControl&, void); + DECL_LINK(ColorSliderControlModifyHdl, ColorSliderControl&, void); + DECL_LINK(ColorModifyMetricHdl, weld::MetricSpinButton&, void); + DECL_LINK(ColorModifySpinHdl, weld::SpinButton&, void); + DECL_LINK(ColorModifyEditHdl, weld::Entry&, void); + DECL_LINK(ModeModifyHdl, weld::ToggleButton&, void); + + Color GetColor() const; + + void setColorComponent(ColorComponent nComp, double dValue); + +private: + ColorMode meMode; + + double mdRed, mdGreen, mdBlue; + double mdHue, mdSat, mdBri; + double mdCyan, mdMagenta, mdYellow, mdKey; +}; + +} + +ColorPickerDialog::ColorPickerDialog(weld::Window* pParent, Color nColor, sal_Int16 nDialogMode) + : GenericDialogController(pParent, "cui/ui/colorpickerdialog.ui", "ColorPicker") + , m_xColorField(new weld::CustomWeld(*m_xBuilder, "colorField", m_aColorField)) + , m_xColorSlider(new weld::CustomWeld(*m_xBuilder, "colorSlider", m_aColorSlider)) + , m_xColorPreview(new weld::CustomWeld(*m_xBuilder, "preview", m_aColorPreview)) + , m_xColorPrevious(new weld::CustomWeld(*m_xBuilder, "previous", m_aColorPrevious)) + , m_xFISliderLeft(m_xBuilder->weld_widget("leftImage")) + , m_xFISliderRight(m_xBuilder->weld_widget("rightImage")) + , m_xRBRed(m_xBuilder->weld_radio_button("redRadiobutton")) + , m_xRBGreen(m_xBuilder->weld_radio_button("greenRadiobutton")) + , m_xRBBlue(m_xBuilder->weld_radio_button("blueRadiobutton")) + , m_xRBHue(m_xBuilder->weld_radio_button("hueRadiobutton")) + , m_xRBSaturation(m_xBuilder->weld_radio_button("satRadiobutton")) + , m_xRBBrightness(m_xBuilder->weld_radio_button("brightRadiobutton")) + , m_xMFRed(m_xBuilder->weld_spin_button("redSpinbutton")) + , m_xMFGreen(m_xBuilder->weld_spin_button("greenSpinbutton")) + , m_xMFBlue(m_xBuilder->weld_spin_button("blueSpinbutton")) + , m_xEDHex(new weld::HexColorControl(m_xBuilder->weld_entry("hexEntry"))) + , m_xMFHue(m_xBuilder->weld_metric_spin_button("hueSpinbutton", FieldUnit::DEGREE)) + , m_xMFSaturation(m_xBuilder->weld_metric_spin_button("satSpinbutton", FieldUnit::PERCENT)) + , m_xMFBrightness(m_xBuilder->weld_metric_spin_button("brightSpinbutton", FieldUnit::PERCENT)) + , m_xMFCyan(m_xBuilder->weld_metric_spin_button("cyanSpinbutton", FieldUnit::PERCENT)) + , m_xMFMagenta(m_xBuilder->weld_metric_spin_button("magSpinbutton", FieldUnit::PERCENT)) + , m_xMFYellow(m_xBuilder->weld_metric_spin_button("yellowSpinbutton", FieldUnit::PERCENT)) + , m_xMFKey(m_xBuilder->weld_metric_spin_button("keySpinbutton", FieldUnit::PERCENT)) + , meMode( DefaultMode ) +{ + m_aColorField.SetModifyHdl( LINK( this, ColorPickerDialog, ColorFieldControlModifydl ) ); + m_aColorSlider.SetModifyHdl( LINK( this, ColorPickerDialog, ColorSliderControlModifyHdl ) ); + + int nMargin = (m_xFISliderLeft->get_preferred_size().Height() + 1) / 2; + m_xColorSlider->set_margin_top(nMargin); + m_xColorSlider->set_margin_bottom(nMargin); + + Link aLink3( LINK( this, ColorPickerDialog, ColorModifyMetricHdl ) ); + m_xMFCyan->connect_value_changed( aLink3 ); + m_xMFMagenta->connect_value_changed( aLink3 ); + m_xMFYellow->connect_value_changed( aLink3 ); + m_xMFKey->connect_value_changed( aLink3 ); + + m_xMFHue->connect_value_changed( aLink3 ); + m_xMFSaturation->connect_value_changed( aLink3 ); + m_xMFBrightness->connect_value_changed( aLink3 ); + + Link aLink4(LINK(this, ColorPickerDialog, ColorModifySpinHdl)); + m_xMFRed->connect_value_changed(aLink4); + m_xMFGreen->connect_value_changed(aLink4); + m_xMFBlue->connect_value_changed(aLink4); + + m_xEDHex->connect_changed(LINK(this, ColorPickerDialog, ColorModifyEditHdl)); + + Link aLink2 = LINK( this, ColorPickerDialog, ModeModifyHdl ); + m_xRBRed->connect_toggled( aLink2 ); + m_xRBGreen->connect_toggled( aLink2 ); + m_xRBBlue->connect_toggled( aLink2 ); + m_xRBHue->connect_toggled( aLink2 ); + m_xRBSaturation->connect_toggled( aLink2 ); + m_xRBBrightness->connect_toggled( aLink2 ); + + Color aColor(nColor); + + // modify + if (nDialogMode == 2) + { + m_aColorPrevious.SetColor(aColor); + m_xColorPrevious->show(); + } + + mdRed = static_cast(aColor.GetRed()) / 255.0; + mdGreen = static_cast(aColor.GetGreen()) / 255.0; + mdBlue = static_cast(aColor.GetBlue()) / 255.0; + + RGBtoHSV( mdRed, mdGreen, mdBlue, mdHue, mdSat, mdBri ); + RGBtoCMYK( mdRed, mdGreen, mdBlue, mdCyan, mdMagenta, mdYellow, mdKey ); + + update_color(); +} + +static int toInt( double dValue, double dRange ) +{ + return static_cast< int >( std::floor((dValue * dRange) + 0.5 ) ); +} + +Color ColorPickerDialog::GetColor() const +{ + return Color( toInt(mdRed,255.0), toInt(mdGreen,255.0), toInt(mdBlue,255.0) ); +} + +void ColorPickerDialog::update_color( UpdateFlags n ) +{ + sal_uInt8 nRed = toInt(mdRed,255.0); + sal_uInt8 nGreen = toInt(mdGreen,255.0); + sal_uInt8 nBlue = toInt(mdBlue,255.0); + + Color aColor(nRed, nGreen, nBlue); + + if (n & UpdateFlags::RGB) // update RGB + { + m_xMFRed->set_value(nRed); + m_xMFGreen->set_value(nGreen); + m_xMFBlue->set_value(nBlue); + } + + if (n & UpdateFlags::CMYK) // update CMYK + { + m_xMFCyan->set_value(toInt(mdCyan, 100.0), FieldUnit::PERCENT); + m_xMFMagenta->set_value(toInt(mdMagenta, 100.0), FieldUnit::PERCENT); + m_xMFYellow->set_value(toInt(mdYellow, 100.0), FieldUnit::PERCENT); + m_xMFKey->set_value(toInt(mdKey, 100.0), FieldUnit::PERCENT); + } + + if (n & UpdateFlags::HSB ) // update HSB + { + m_xMFHue->set_value(toInt(mdHue, 1.0), FieldUnit::DEGREE); + m_xMFSaturation->set_value(toInt( mdSat, 100.0), FieldUnit::PERCENT); + m_xMFBrightness->set_value(toInt( mdBri, 100.0), FieldUnit::PERCENT); + } + + if (n & UpdateFlags::ColorChooser ) // update Color Chooser 1 + { + switch( meMode ) + { + case HUE: + m_aColorField.SetValues(aColor, meMode, mdSat, mdBri); + break; + case SATURATION: + m_aColorField.SetValues(aColor, meMode, mdHue / 360.0, mdBri); + break; + case BRIGHTNESS: + m_aColorField.SetValues(aColor, meMode, mdHue / 360.0, mdSat); + break; + case RED: + m_aColorField.SetValues(aColor, meMode, mdBlue, mdGreen); + break; + case GREEN: + m_aColorField.SetValues(aColor, meMode, mdBlue, mdRed); + break; + case BLUE: + m_aColorField.SetValues(aColor, meMode, mdRed, mdGreen); + break; + } + } + + if (n & UpdateFlags::ColorSlider) // update Color Chooser 2 + { + switch (meMode) + { + case HUE: + m_aColorSlider.SetValue(aColor, meMode, mdHue / 360.0); + break; + case SATURATION: + m_aColorSlider.SetValue(aColor, meMode, mdSat); + break; + case BRIGHTNESS: + m_aColorSlider.SetValue(aColor, meMode, mdBri); + break; + case RED: + m_aColorSlider.SetValue(aColor, meMode, mdRed); + break; + case GREEN: + m_aColorSlider.SetValue(aColor, meMode, mdGreen); + break; + case BLUE: + m_aColorSlider.SetValue(aColor, meMode, mdBlue); + break; + } + } + + if (n & UpdateFlags::Hex) // update hex + { + m_xFISliderLeft->set_margin_top(m_aColorSlider.GetLevel()); + m_xFISliderRight->set_margin_top(m_aColorSlider.GetLevel()); + m_xEDHex->SetColor(aColor); + } + m_aColorPreview.SetColor(aColor); +} + +IMPL_LINK_NOARG(ColorPickerDialog, ColorFieldControlModifydl, ColorFieldControl&, void) +{ + double x = m_aColorField.GetX(); + double y = m_aColorField.GetY(); + + switch( meMode ) + { + case HUE: + mdSat = x; + setColorComponent( ColorComponent::Brightness, y ); + break; + case SATURATION: + mdHue = x * 360.0; + setColorComponent( ColorComponent::Brightness, y ); + break; + case BRIGHTNESS: + mdHue = x * 360.0; + setColorComponent( ColorComponent::Saturation, y ); + break; + case RED: + mdBlue = x; + setColorComponent( ColorComponent::Green, y ); + break; + case GREEN: + mdBlue = x; + setColorComponent( ColorComponent::Red, y ); + break; + case BLUE: + mdRed = x; + setColorComponent( ColorComponent::Green, y ); + break; + } + + update_color(UpdateFlags::All & ~UpdateFlags::ColorChooser); +} + +IMPL_LINK_NOARG(ColorPickerDialog, ColorSliderControlModifyHdl, ColorSliderControl&, void) +{ + double dValue = m_aColorSlider.GetValue(); + switch (meMode) + { + case HUE: + setColorComponent( ColorComponent::Hue, dValue * 360.0 ); + break; + case SATURATION: + setColorComponent( ColorComponent::Saturation, dValue ); + break; + case BRIGHTNESS: + setColorComponent( ColorComponent::Brightness, dValue ); + break; + case RED: + setColorComponent( ColorComponent::Red, dValue ); + break; + case GREEN: + setColorComponent( ColorComponent::Green, dValue ); + break; + case BLUE: + setColorComponent( ColorComponent::Blue, dValue ); + break; + } + + update_color(UpdateFlags::All & ~UpdateFlags::ColorSlider); +} + +IMPL_LINK(ColorPickerDialog, ColorModifyMetricHdl, weld::MetricSpinButton&, rEdit, void) +{ + UpdateFlags n = UpdateFlags::NONE; + + if (&rEdit == m_xMFHue.get()) + { + setColorComponent( ColorComponent::Hue, static_cast(m_xMFHue->get_value(FieldUnit::DEGREE)) ); + n = UpdateFlags::All & ~UpdateFlags::HSB; + } + else if (&rEdit == m_xMFSaturation.get()) + { + setColorComponent( ColorComponent::Saturation, static_cast(m_xMFSaturation->get_value(FieldUnit::PERCENT)) / 100.0 ); + n = UpdateFlags::All & ~UpdateFlags::HSB; + } + else if (&rEdit == m_xMFBrightness.get()) + { + setColorComponent( ColorComponent::Brightness, static_cast(m_xMFBrightness->get_value(FieldUnit::PERCENT)) / 100.0 ); + n = UpdateFlags::All & ~UpdateFlags::HSB; + } + else if (&rEdit == m_xMFCyan.get()) + { + setColorComponent( ColorComponent::Cyan, static_cast(m_xMFCyan->get_value(FieldUnit::PERCENT)) / 100.0 ); + n = UpdateFlags::All & ~UpdateFlags::CMYK; + } + else if (&rEdit == m_xMFMagenta.get()) + { + setColorComponent( ColorComponent::Magenta, static_cast(m_xMFMagenta->get_value(FieldUnit::PERCENT)) / 100.0 ); + n = UpdateFlags::All & ~UpdateFlags::CMYK; + } + else if (&rEdit == m_xMFYellow.get()) + { + setColorComponent( ColorComponent::Yellow, static_cast(m_xMFYellow->get_value(FieldUnit::PERCENT)) / 100.0 ); + n = UpdateFlags::All & ~UpdateFlags::CMYK; + } + else if (&rEdit == m_xMFKey.get()) + { + setColorComponent( ColorComponent::Key, static_cast(m_xMFKey->get_value(FieldUnit::PERCENT)) / 100.0 ); + n = UpdateFlags::All & ~UpdateFlags::CMYK; + } + + if (n != UpdateFlags::NONE) + update_color(n); +} + +IMPL_LINK_NOARG(ColorPickerDialog, ColorModifyEditHdl, weld::Entry&, void) +{ + UpdateFlags n = UpdateFlags::NONE; + + Color aColor = m_xEDHex->GetColor(); + + if (aColor != Color(0xffffffff) && aColor != GetColor()) + { + mdRed = static_cast(aColor.GetRed()) / 255.0; + mdGreen = static_cast(aColor.GetGreen()) / 255.0; + mdBlue = static_cast(aColor.GetBlue()) / 255.0; + + RGBtoHSV( mdRed, mdGreen, mdBlue, mdHue, mdSat, mdBri ); + RGBtoCMYK( mdRed, mdGreen, mdBlue, mdCyan, mdMagenta, mdYellow, mdKey ); + n = UpdateFlags::All & ~UpdateFlags::Hex; + } + + if (n != UpdateFlags::NONE) + update_color(n); +} + +IMPL_LINK(ColorPickerDialog, ColorModifySpinHdl, weld::SpinButton&, rEdit, void) +{ + UpdateFlags n = UpdateFlags::NONE; + + if (&rEdit == m_xMFRed.get()) + { + setColorComponent( ColorComponent::Red, static_cast(m_xMFRed->get_value()) / 255.0 ); + n = UpdateFlags::All & ~UpdateFlags::RGB; + } + else if (&rEdit == m_xMFGreen.get()) + { + setColorComponent( ColorComponent::Green, static_cast(m_xMFGreen->get_value()) / 255.0 ); + n = UpdateFlags::All & ~UpdateFlags::RGB; + } + else if (&rEdit == m_xMFBlue.get()) + { + setColorComponent( ColorComponent::Blue, static_cast(m_xMFBlue->get_value()) / 255.0 ); + n = UpdateFlags::All & ~UpdateFlags::RGB; + } + + if (n != UpdateFlags::NONE) + update_color(n); +} + + +IMPL_LINK_NOARG(ColorPickerDialog, ModeModifyHdl, weld::ToggleButton&, void) +{ + ColorMode eMode = HUE; + + if (m_xRBRed->get_active()) + { + eMode = RED; + } + else if (m_xRBGreen->get_active()) + { + eMode = GREEN; + } + else if (m_xRBBlue->get_active()) + { + eMode = BLUE; + } + else if (m_xRBSaturation->get_active()) + { + eMode = SATURATION; + } + else if (m_xRBBrightness->get_active()) + { + eMode = BRIGHTNESS; + } + + if (meMode != eMode) + { + meMode = eMode; + update_color(UpdateFlags::ColorChooser | UpdateFlags::ColorSlider); + } +} + +void ColorPickerDialog::setColorComponent( ColorComponent nComp, double dValue ) +{ + switch( nComp ) + { + case ColorComponent::Red: + mdRed = dValue; + break; + case ColorComponent::Green: + mdGreen = dValue; + break; + case ColorComponent::Blue: + mdBlue = dValue; + break; + case ColorComponent::Hue: + mdHue = dValue; + break; + case ColorComponent::Saturation: + mdSat = dValue; + break; + case ColorComponent::Brightness: + mdBri = dValue; + break; + case ColorComponent::Cyan: + mdCyan = dValue; + break; + case ColorComponent::Yellow: + mdYellow = dValue; + break; + case ColorComponent::Magenta: + mdMagenta = dValue; + break; + case ColorComponent::Key: + mdKey = dValue; + break; + } + + if (nComp == ColorComponent::Red || nComp == ColorComponent::Green || nComp == ColorComponent::Blue) + { + RGBtoHSV( mdRed, mdGreen, mdBlue, mdHue, mdSat, mdBri ); + RGBtoCMYK( mdRed, mdGreen, mdBlue, mdCyan, mdMagenta, mdYellow, mdKey ); + } + else if (nComp == ColorComponent::Hue || nComp == ColorComponent::Saturation || nComp == ColorComponent::Brightness) + { + HSVtoRGB( mdHue, mdSat, mdBri, mdRed, mdGreen, mdBlue ); + RGBtoCMYK( mdRed, mdGreen, mdBlue, mdCyan, mdMagenta, mdYellow, mdKey ); + } + else + { + CMYKtoRGB( mdCyan, mdMagenta, mdYellow, mdKey, mdRed, mdGreen, mdBlue ); + RGBtoHSV( mdRed, mdGreen, mdBlue, mdHue, mdSat, mdBri ); + } +} + +typedef ::cppu::WeakComponentImplHelper< XServiceInfo, XExecutableDialog, XInitialization, XPropertyAccess > ColorPickerBase; + +namespace { + +class ColorPicker : protected ::cppu::BaseMutex, // Struct for right initialization of mutex member! Must be first of baseclasses. + public ColorPickerBase +{ +public: + explicit ColorPicker(); + + // XInitialization + virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) override; + + // XInitialization + virtual OUString SAL_CALL getImplementationName( ) override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; + + // XPropertyAccess + virtual Sequence< PropertyValue > SAL_CALL getPropertyValues( ) override; + virtual void SAL_CALL setPropertyValues( const Sequence< PropertyValue >& aProps ) override; + + // XExecutableDialog + virtual void SAL_CALL setTitle( const OUString& aTitle ) override; + virtual sal_Int16 SAL_CALL execute( ) override; + +private: + Color mnColor; + sal_Int16 mnMode; + Reference mxParent; +}; + +} + +OUString ColorPicker_getImplementationName() +{ + return "com.sun.star.cui.ColorPicker"; +} + +Reference< XInterface > ColorPicker_createInstance( Reference< XComponentContext > const & ) +{ + return static_cast( new ColorPicker ); +} + +Sequence< OUString > ColorPicker_getSupportedServiceNames() +{ + Sequence< OUString > seq { "com.sun.star.ui.dialogs.ColorPicker" }; + return seq; +} + +static const OUStringLiteral gsColorKey( "Color" ); +static const OUStringLiteral gsModeKey( "Mode" ); + +ColorPicker::ColorPicker() + : ColorPickerBase( m_aMutex ) + , mnColor( 0 ) + , mnMode( 0 ) +{ +} + +// XInitialization +void SAL_CALL ColorPicker::initialize( const Sequence< Any >& aArguments ) +{ + if( aArguments.getLength() == 1 ) + { + aArguments[0] >>= mxParent; + } +} + +// XInitialization +OUString SAL_CALL ColorPicker::getImplementationName( ) +{ + return ColorPicker_getImplementationName(); +} + +sal_Bool SAL_CALL ColorPicker::supportsService( const OUString& sServiceName ) +{ + return cppu::supportsService(this, sServiceName); +} + +Sequence< OUString > SAL_CALL ColorPicker::getSupportedServiceNames( ) +{ + return ColorPicker_getSupportedServiceNames(); +} + +// XPropertyAccess +Sequence< PropertyValue > SAL_CALL ColorPicker::getPropertyValues( ) +{ + Sequence< PropertyValue > props(1); + props[0].Name = gsColorKey; + props[0].Value <<= mnColor; + return props; +} + +void SAL_CALL ColorPicker::setPropertyValues( const Sequence< PropertyValue >& aProps ) +{ + for ( const PropertyValue& rProp : aProps ) + { + if( rProp.Name == gsColorKey ) + { + rProp.Value >>= mnColor; + } + else if( rProp.Name == gsModeKey ) + { + rProp.Value >>= mnMode; + } + } +} + +// XExecutableDialog +void SAL_CALL ColorPicker::setTitle( const OUString& ) +{ +} + +sal_Int16 SAL_CALL ColorPicker::execute() +{ + std::unique_ptr xDlg(new ColorPickerDialog(Application::GetFrameWeld(mxParent), mnColor, mnMode)); + sal_Int16 ret = xDlg->run(); + if (ret) + mnColor = xDlg->GetColor(); + return ret; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/cuicharmap.cxx b/cui/source/dialogs/cuicharmap.cxx new file mode 100644 index 000000000..bcc1dd16a --- /dev/null +++ b/cui/source/dialogs/cuicharmap.cxx @@ -0,0 +1,1250 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace css; + +SvxCharacterMap::SvxCharacterMap(weld::Widget* pParent, const SfxItemSet* pSet, + const css::uno::Reference& rFrame) + : SfxDialogController(pParent, "cui/ui/specialcharacters.ui", "SpecialCharactersDialog") + , m_xVirDev(VclPtr::Create()) + , isSearchMode(true) + , m_xFrame(rFrame) + , mxContext(comphelper::getProcessComponentContext()) + , m_aRecentCharView{SvxCharView(m_xVirDev), + SvxCharView(m_xVirDev), + SvxCharView(m_xVirDev), + SvxCharView(m_xVirDev), + SvxCharView(m_xVirDev), + SvxCharView(m_xVirDev), + SvxCharView(m_xVirDev), + SvxCharView(m_xVirDev), + SvxCharView(m_xVirDev), + SvxCharView(m_xVirDev), + SvxCharView(m_xVirDev), + SvxCharView(m_xVirDev), + SvxCharView(m_xVirDev), + SvxCharView(m_xVirDev), + SvxCharView(m_xVirDev), + SvxCharView(m_xVirDev)} + , m_aFavCharView{SvxCharView(m_xVirDev), + SvxCharView(m_xVirDev), + SvxCharView(m_xVirDev), + SvxCharView(m_xVirDev), + SvxCharView(m_xVirDev), + SvxCharView(m_xVirDev), + SvxCharView(m_xVirDev), + SvxCharView(m_xVirDev), + SvxCharView(m_xVirDev), + SvxCharView(m_xVirDev), + SvxCharView(m_xVirDev), + SvxCharView(m_xVirDev), + SvxCharView(m_xVirDev), + SvxCharView(m_xVirDev), + SvxCharView(m_xVirDev), + SvxCharView(m_xVirDev)} + , m_aShowChar(m_xVirDev) + , m_xOKBtn(m_xFrame.is() ? m_xBuilder->weld_button("insert") : m_xBuilder->weld_button("ok")) + , m_xFontText(m_xBuilder->weld_label("fontft")) + , m_xFontLB(m_xBuilder->weld_combo_box("fontlb")) + , m_xSubsetText(m_xBuilder->weld_label("subsetft")) + , m_xSubsetLB(m_xBuilder->weld_combo_box("subsetlb")) + , m_xSearchText(m_xBuilder->weld_entry("search")) + , m_xHexCodeText(m_xBuilder->weld_entry("hexvalue")) + , m_xDecimalCodeText(m_xBuilder->weld_entry("decimalvalue")) + , m_xFavouritesBtn(m_xBuilder->weld_button("favbtn")) + , m_xCharName(m_xBuilder->weld_label("charname")) + , m_xRecentGrid(m_xBuilder->weld_widget("viewgrid")) + , m_xFavGrid(m_xBuilder->weld_widget("favgrid")) + , m_xShowChar(new weld::CustomWeld(*m_xBuilder, "showchar", m_aShowChar)) + , m_xRecentCharView{std::make_unique(*m_xBuilder, "viewchar1", m_aRecentCharView[0]), + std::make_unique(*m_xBuilder, "viewchar2", m_aRecentCharView[1]), + std::make_unique(*m_xBuilder, "viewchar3", m_aRecentCharView[2]), + std::make_unique(*m_xBuilder, "viewchar4", m_aRecentCharView[3]), + std::make_unique(*m_xBuilder, "viewchar5", m_aRecentCharView[4]), + std::make_unique(*m_xBuilder, "viewchar6", m_aRecentCharView[5]), + std::make_unique(*m_xBuilder, "viewchar7", m_aRecentCharView[6]), + std::make_unique(*m_xBuilder, "viewchar8", m_aRecentCharView[7]), + std::make_unique(*m_xBuilder, "viewchar9", m_aRecentCharView[8]), + std::make_unique(*m_xBuilder, "viewchar10", m_aRecentCharView[9]), + std::make_unique(*m_xBuilder, "viewchar11", m_aRecentCharView[10]), + std::make_unique(*m_xBuilder, "viewchar12", m_aRecentCharView[11]), + std::make_unique(*m_xBuilder, "viewchar13", m_aRecentCharView[12]), + std::make_unique(*m_xBuilder, "viewchar14", m_aRecentCharView[13]), + std::make_unique(*m_xBuilder, "viewchar15", m_aRecentCharView[14]), + std::make_unique(*m_xBuilder, "viewchar16", m_aRecentCharView[15])} + , m_xFavCharView{std::make_unique(*m_xBuilder, "favchar1", m_aFavCharView[0]), + std::make_unique(*m_xBuilder, "favchar2", m_aFavCharView[1]), + std::make_unique(*m_xBuilder, "favchar3", m_aFavCharView[2]), + std::make_unique(*m_xBuilder, "favchar4", m_aFavCharView[3]), + std::make_unique(*m_xBuilder, "favchar5", m_aFavCharView[4]), + std::make_unique(*m_xBuilder, "favchar6", m_aFavCharView[5]), + std::make_unique(*m_xBuilder, "favchar7", m_aFavCharView[6]), + std::make_unique(*m_xBuilder, "favchar8", m_aFavCharView[7]), + std::make_unique(*m_xBuilder, "favchar9", m_aFavCharView[8]), + std::make_unique(*m_xBuilder, "favchar10", m_aFavCharView[9]), + std::make_unique(*m_xBuilder, "favchar11", m_aFavCharView[10]), + std::make_unique(*m_xBuilder, "favchar12", m_aFavCharView[11]), + std::make_unique(*m_xBuilder, "favchar13", m_aFavCharView[12]), + std::make_unique(*m_xBuilder, "favchar14", m_aFavCharView[13]), + std::make_unique(*m_xBuilder, "favchar15", m_aFavCharView[14]), + std::make_unique(*m_xBuilder, "favchar16", m_aFavCharView[15])} + , m_xShowSet(new SvxShowCharSet(m_xBuilder->weld_scrolled_window("showscroll"), m_xVirDev)) + , m_xShowSetArea(new weld::CustomWeld(*m_xBuilder, "showcharset", *m_xShowSet)) + , m_xSearchSet(new SvxSearchCharSet(m_xBuilder->weld_scrolled_window("searchscroll"), m_xVirDev)) + , m_xSearchSetArea(new weld::CustomWeld(*m_xBuilder, "searchcharset", *m_xSearchSet)) +{ + m_aShowChar.SetCentered(true); + m_xFontLB->make_sorted(); + //lock the size request of this widget to the width of all possible entries + fillAllSubsets(*m_xSubsetLB); + m_xSubsetLB->set_size_request(m_xSubsetLB->get_preferred_size().Width(), -1); + m_xCharName->set_size_request(m_aShowChar.get_preferred_size().Width(), m_xCharName->get_text_height() * 4); + //lock the size request of this widget to the width of the original .ui string + m_xHexCodeText->set_size_request(m_xHexCodeText->get_preferred_size().Width(), -1); + //so things don't jump around if all the children are hidden + m_xRecentGrid->set_size_request(-1, m_aRecentCharView[0].get_preferred_size().Height()); + m_xFavGrid->set_size_request(-1, m_aFavCharView[0].get_preferred_size().Height()); + + init(); + + const SfxInt32Item* pCharItem = SfxItemSet::GetItem(pSet, SID_ATTR_CHAR, false); + if ( pCharItem ) + SetChar( pCharItem->GetValue() ); + + const SfxBoolItem* pDisableItem = SfxItemSet::GetItem(pSet, FN_PARAM_2, false); + if ( pDisableItem && pDisableItem->GetValue() ) + DisableFontSelection(); + + const SvxFontItem* pFontItem = SfxItemSet::GetItem(pSet, SID_ATTR_CHAR_FONT, false); + const SfxStringItem* pFontNameItem = SfxItemSet::GetItem(pSet, SID_FONT_NAME, false); + if ( pFontItem ) + { + vcl::Font aTmpFont( pFontItem->GetFamilyName(), pFontItem->GetStyleName(), GetCharFont().GetFontSize() ); + aTmpFont.SetCharSet( pFontItem->GetCharSet() ); + aTmpFont.SetPitch( pFontItem->GetPitch() ); + SetCharFont( aTmpFont ); + } + else if ( pFontNameItem ) + { + vcl::Font aTmpFont( GetCharFont() ); + aTmpFont.SetFamilyName( pFontNameItem->GetValue() ); + SetCharFont( aTmpFont ); + } + + m_xOutputSet.reset(new SfxAllItemSet(pSet ? *pSet->GetPool() : SfxGetpApp()->GetPool())); + m_xShowSet->Show(); + m_xSearchSet->Hide(); +} + +short SvxCharacterMap::run() +{ + if( SvxShowCharSet::getSelectedChar() == ' ') + { + m_xOKBtn->set_sensitive(false); + setFavButtonState(OUString(), OUString()); + } + else + { + sal_UCS4 cChar = m_xShowSet->GetSelectCharacter(); + // using the new UCS4 constructor + OUString aOUStr( &cChar, 1 ); + m_aShowChar.SetText(aOUStr); + + setFavButtonState(aOUStr, m_aShowChar.GetFont().GetFamilyName()); + m_xOKBtn->set_sensitive(true); + } + + return SfxDialogController::run(); +} + +void SvxCharacterMap::SetChar( sal_UCS4 c ) +{ + m_xShowSet->SelectCharacter( c ); + setFavButtonState(OUString(&c, 1), aFont.GetFamilyName()); +} + +sal_UCS4 SvxCharacterMap::GetChar() const +{ + return m_aShowChar.GetText().toChar(); +} + +void SvxCharacterMap::DisableFontSelection() +{ + m_xFontText->set_sensitive(false); + m_xFontLB->set_sensitive(false); +} + + +void SvxCharacterMap::getRecentCharacterList() +{ + //retrieve recent character list + const css::uno::Sequence< OUString > rRecentCharList( officecfg::Office::Common::RecentCharacters::RecentCharacterList::get() ); + for (OUString const & s : rRecentCharList) + { + maRecentCharList.push_back(s); + } + + //retrieve recent character font list + const css::uno::Sequence< OUString > rRecentCharFontList( officecfg::Office::Common::RecentCharacters::RecentCharacterFontList::get() ); + for (OUString const & s : rRecentCharFontList) + { + maRecentCharFontList.push_back(s); + } +} + + +void SvxCharacterMap::getFavCharacterList() +{ + maFavCharList.clear(); + maFavCharFontList.clear(); + //retrieve recent character list + const css::uno::Sequence< OUString > rFavCharList( officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterList::get() ); + for (const OUString& s : rFavCharList) + { + maFavCharList.push_back(s); + } + + //retrieve recent character font list + const css::uno::Sequence< OUString > rFavCharFontList( officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterFontList::get() ); + for (const OUString& s : rFavCharFontList) + { + maFavCharFontList.push_back(s); + } +} + + +void SvxCharacterMap::updateRecentCharControl() +{ + int i = 0; + for ( std::deque< OUString >::iterator it = maRecentCharList.begin(), it2 = maRecentCharFontList.begin(); + it != maRecentCharList.end() && it2 != maRecentCharFontList.end(); + ++it, ++it2, i++) + { + m_aRecentCharView[i].SetText(*it); + vcl::Font rFont = m_aRecentCharView[i].GetFont(); + rFont.SetFamilyName( *it2 ); + m_aRecentCharView[i].SetFont(rFont); + m_aRecentCharView[i].Show(); + } + + for(; i < 16 ; i++) + { + m_aRecentCharView[i].SetText(OUString()); + m_aRecentCharView[i].Hide(); + } +} + +void SvxCharacterMap::updateRecentCharacterList(const OUString& sTitle, const OUString& rFont) +{ + auto itChar = std::find(maRecentCharList.begin(), maRecentCharList.end(), sTitle); + + auto itChar2 = std::find(maRecentCharFontList.begin(), maRecentCharFontList.end(), rFont); + + // if recent char to be added is already in list, remove it + if( itChar != maRecentCharList.end() && itChar2 != maRecentCharFontList.end() ) + { + maRecentCharList.erase( itChar ); + maRecentCharFontList.erase( itChar2); + } + + if (maRecentCharList.size() == 16) + { + maRecentCharList.pop_back(); + maRecentCharFontList.pop_back(); + } + + maRecentCharList.push_front(sTitle); + maRecentCharFontList.push_front(rFont); + + css::uno::Sequence< OUString > aRecentCharList(maRecentCharList.size()); + css::uno::Sequence< OUString > aRecentCharFontList(maRecentCharFontList.size()); + + for (size_t i = 0; i < maRecentCharList.size(); ++i) + { + aRecentCharList[i] = maRecentCharList[i]; + aRecentCharFontList[i] = maRecentCharFontList[i]; + } + + std::shared_ptr batch(comphelper::ConfigurationChanges::create(mxContext)); + officecfg::Office::Common::RecentCharacters::RecentCharacterList::set(aRecentCharList, batch); + officecfg::Office::Common::RecentCharacters::RecentCharacterFontList::set(aRecentCharFontList, batch); + batch->commit(); + + updateRecentCharControl(); +} + + +void SvxCharacterMap::updateFavCharacterList(const OUString& sTitle, const OUString& rFont) +{ + auto itChar = std::find(maFavCharList.begin(), maFavCharList.end(), sTitle); + + auto itChar2 = std::find(maFavCharFontList.begin(), maFavCharFontList.end(), rFont); + + // if Fav char to be added is already in list, remove it + if( itChar != maFavCharList.end() && itChar2 != maFavCharFontList.end() ) + { + maFavCharList.erase( itChar ); + maFavCharFontList.erase( itChar2); + } + + if (maFavCharList.size() == 16) + { + maFavCharList.pop_back(); + maFavCharFontList.pop_back(); + } + + maFavCharList.push_back(sTitle); + maFavCharFontList.push_back(rFont); + + css::uno::Sequence< OUString > aFavCharList(maFavCharList.size()); + css::uno::Sequence< OUString > aFavCharFontList(maFavCharFontList.size()); + + for (size_t i = 0; i < maFavCharList.size(); ++i) + { + aFavCharList[i] = maFavCharList[i]; + aFavCharFontList[i] = maFavCharFontList[i]; + } + + std::shared_ptr batch(comphelper::ConfigurationChanges::create(mxContext)); + officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterList::set(aFavCharList, batch); + officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterFontList::set(aFavCharFontList, batch); + batch->commit(); +} + + +void SvxCharacterMap::updateFavCharControl() +{ + int i = 0; + for ( std::deque< OUString >::iterator it = maFavCharList.begin(), it2 = maFavCharFontList.begin(); + it != maFavCharList.end() && it2 != maFavCharFontList.end(); + ++it, ++it2, i++) + { + m_aFavCharView[i].SetText(*it); + vcl::Font rFont = m_aFavCharView[i].GetFont(); + rFont.SetFamilyName( *it2 ); + m_aFavCharView[i].SetFont(rFont); + m_aFavCharView[i].Show(); + } + + for(; i < 16 ; i++) + { + m_aFavCharView[i].SetText(OUString()); + m_aFavCharView[i].Hide(); + } + m_xShowSet->getFavCharacterList(); + m_xSearchSet->getFavCharacterList(); +} + +void SvxCharacterMap::deleteFavCharacterFromList(const OUString& sTitle, const OUString& rFont) +{ + auto itChar = std::find(maFavCharList.begin(), maFavCharList.end(), sTitle); + + auto itChar2 = std::find(maFavCharFontList.begin(), maFavCharFontList.end(), rFont); + + // if Fav char to be added is already in list, remove it + if( itChar != maFavCharList.end() && itChar2 != maFavCharFontList.end() ) + { + maFavCharList.erase( itChar ); + maFavCharFontList.erase( itChar2); + } + + css::uno::Sequence< OUString > aFavCharList(maFavCharList.size()); + css::uno::Sequence< OUString > aFavCharFontList(maFavCharFontList.size()); + + for (size_t i = 0; i < maFavCharList.size(); ++i) + { + aFavCharList[i] = maFavCharList[i]; + aFavCharFontList[i] = maFavCharFontList[i]; + } + + std::shared_ptr batch(comphelper::ConfigurationChanges::create(mxContext)); + officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterList::set(aFavCharList, batch); + officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterFontList::set(aFavCharFontList, batch); + batch->commit(); +} + +void SvxCharacterMap::init() +{ + aFont = m_xVirDev->GetFont(); + aFont.SetTransparent( true ); + aFont.SetFamily( FAMILY_DONTKNOW ); + aFont.SetPitch( PITCH_DONTKNOW ); + aFont.SetCharSet( RTL_TEXTENCODING_DONTKNOW ); + + OUString aDefStr( aFont.GetFamilyName() ); + OUString aLastName; + int nCount = m_xVirDev->GetDevFontCount(); + std::vector aEntries; + aEntries.reserve(nCount); + for (int i = 0; i < nCount; ++i) + { + OUString aFontName( m_xVirDev->GetDevFont( i ).GetFamilyName() ); + if (aFontName != aLastName) + { + aLastName = aFontName; + aEntries.emplace_back(aFontName, OUString::number(i)); + } + } + m_xFontLB->insert_vector(aEntries, true); + // the font may not be in the list => + // try to find a font name token in list and select found font, + // else select topmost entry + bool bFound = (m_xFontLB->find_text(aDefStr) == -1); + if (!bFound) + { + sal_Int32 nIndex = 0; + do + { + OUString aToken = aDefStr.getToken(0, ';', nIndex); + if (m_xFontLB->find_text(aToken) != -1) + { + aDefStr = aToken; + bFound = true; + break; + } + } + while ( nIndex >= 0 ); + } + + if (bFound) + m_xFontLB->set_active_text(aDefStr); + else if (m_xFontLB->get_count() ) + m_xFontLB->set_active(0); + FontSelectHdl(*m_xFontLB); + if (m_xSubsetLB->get_count()) + m_xSubsetLB->set_active(0); + + m_xFontLB->connect_changed(LINK( this, SvxCharacterMap, FontSelectHdl)); + m_xSubsetLB->connect_changed(LINK( this, SvxCharacterMap, SubsetSelectHdl)); + m_xOKBtn->connect_clicked(LINK(this, SvxCharacterMap, InsertClickHdl)); + m_xOKBtn->show(); + + m_xShowSet->SetDoubleClickHdl( LINK( this, SvxCharacterMap, CharDoubleClickHdl ) ); + m_xShowSet->SetSelectHdl( LINK( this, SvxCharacterMap, CharSelectHdl ) ); + m_xShowSet->SetHighlightHdl( LINK( this, SvxCharacterMap, CharHighlightHdl ) ); + m_xShowSet->SetPreSelectHdl( LINK( this, SvxCharacterMap, CharPreSelectHdl ) ); + m_xShowSet->SetFavClickHdl( LINK( this, SvxCharacterMap, FavClickHdl ) ); + + m_xSearchSet->SetDoubleClickHdl( LINK( this, SvxCharacterMap, SearchCharDoubleClickHdl ) ); + m_xSearchSet->SetSelectHdl( LINK( this, SvxCharacterMap, SearchCharSelectHdl ) ); + m_xSearchSet->SetHighlightHdl( LINK( this, SvxCharacterMap, SearchCharHighlightHdl ) ); + m_xSearchSet->SetPreSelectHdl( LINK( this, SvxCharacterMap, SearchCharPreSelectHdl ) ); + m_xSearchSet->SetFavClickHdl( LINK( this, SvxCharacterMap, FavClickHdl ) ); + + m_xDecimalCodeText->connect_changed( LINK( this, SvxCharacterMap, DecimalCodeChangeHdl ) ); + m_xHexCodeText->connect_changed( LINK( this, SvxCharacterMap, HexCodeChangeHdl ) ); + m_xFavouritesBtn->connect_clicked( LINK(this, SvxCharacterMap, FavSelectHdl)); + + // tdf#117038 set the buttons width to its max possible width so it doesn't + // make layout change when the label changes + m_xFavouritesBtn->set_label(CuiResId(RID_SVXSTR_REMOVE_FAVORITES)); + auto nMaxWidth = m_xFavouritesBtn->get_preferred_size().Width(); + m_xFavouritesBtn->set_label(CuiResId(RID_SVXSTR_ADD_FAVORITES)); + nMaxWidth = std::max(nMaxWidth, m_xFavouritesBtn->get_preferred_size().Width()); + m_xFavouritesBtn->set_size_request(nMaxWidth, -1); + + if( SvxShowCharSet::getSelectedChar() == ' ') + { + m_xOKBtn->set_sensitive(false); + } + else + { + sal_UCS4 cChar = m_xShowSet->GetSelectCharacter(); + // using the new UCS4 constructor + OUString aOUStr( &cChar, 1 ); + m_aShowChar.SetText(aOUStr); + + setFavButtonState(aOUStr, aDefStr); + m_xOKBtn->set_sensitive(true); + } + + getRecentCharacterList(); + updateRecentCharControl(); + + getFavCharacterList(); + updateFavCharControl(); + + bool bHasInsert = m_xFrame.is(); + + for(int i = 0; i < 16; i++) + { + m_aRecentCharView[i].SetHasInsert(bHasInsert); + m_aRecentCharView[i].setMouseClickHdl(LINK(this,SvxCharacterMap, CharClickHdl)); + m_aRecentCharView[i].setClearClickHdl(LINK(this,SvxCharacterMap, RecentClearClickHdl)); + m_aRecentCharView[i].setClearAllClickHdl(LINK(this,SvxCharacterMap, RecentClearAllClickHdl)); + m_aFavCharView[i].SetHasInsert(bHasInsert); + m_aFavCharView[i].setMouseClickHdl(LINK(this,SvxCharacterMap, CharClickHdl)); + m_aFavCharView[i].setClearClickHdl(LINK(this,SvxCharacterMap, FavClearClickHdl)); + m_aFavCharView[i].setClearAllClickHdl(LINK(this,SvxCharacterMap, FavClearAllClickHdl)); + } + + setCharName(90); + + m_xSearchText->connect_focus_in(LINK( this, SvxCharacterMap, SearchFieldGetFocusHdl )); + m_xSearchText->connect_changed(LINK(this, SvxCharacterMap, SearchUpdateHdl)); +} + +bool SvxCharacterMap::isFavChar(const OUString& sTitle, const OUString& rFont) +{ + auto isFavCharTitleExists = std::any_of(maFavCharList.begin(), + maFavCharList.end(), + [sTitle] (const OUString & a) { return a == sTitle; }); + + auto isFavCharFontExists = std::any_of(maFavCharFontList.begin(), + maFavCharFontList.end(), + [rFont] (const OUString & a) { return a == rFont; }); + + // if Fav char to be added is already in list, remove it + return isFavCharTitleExists && isFavCharFontExists; +} + + +void SvxCharacterMap::setFavButtonState(const OUString& sTitle, const OUString& rFont) +{ + if(sTitle.isEmpty() || rFont.isEmpty()) + { + m_xFavouritesBtn->set_sensitive(false); + return; + } + else + m_xFavouritesBtn->set_sensitive(true); + + if (isFavChar(sTitle, rFont)) + { + m_xFavouritesBtn->set_label(CuiResId(RID_SVXSTR_REMOVE_FAVORITES)); + } + else + { + if(maFavCharList.size() == 16) + { + m_xFavouritesBtn->set_sensitive(false); + } + + m_xFavouritesBtn->set_label(CuiResId(RID_SVXSTR_ADD_FAVORITES)); + } +} + + +void SvxCharacterMap::SetCharFont( const vcl::Font& rFont ) +{ + // first get the underlying info in order to get font names + // like "Times New Roman;Times" resolved + vcl::Font aTmp(m_xVirDev->GetFontMetric(rFont)); + + if (aTmp.GetFamilyName() == "StarSymbol" && m_xFontLB->find_text(aTmp.GetFamilyName()) == -1) + { + //if for some reason, like font in an old document, StarSymbol is requested and it's not available, then + //try OpenSymbol instead + aTmp.SetFamilyName("OpenSymbol"); + } + + if (m_xFontLB->find_text(aTmp.GetFamilyName()) == -1) + return; + + m_xFontLB->set_active_text(aTmp.GetFamilyName()); + aFont = aTmp; + FontSelectHdl(*m_xFontLB); + if (m_xSubsetLB->get_count()) + m_xSubsetLB->set_active(0); +} + +void SvxCharacterMap::fillAllSubsets(weld::ComboBox& rListBox) +{ + SubsetMap aAll(nullptr); + std::vector aEntries; + for (auto & subset : aAll.GetSubsetMap()) + aEntries.emplace_back(subset.GetName()); + rListBox.insert_vector(aEntries, true); +} + +void SvxCharacterMap::insertCharToDoc(const OUString& sGlyph) +{ + if(sGlyph.isEmpty()) + return; + + if (m_xFrame.is()) { + uno::Sequence aArgs(2); + aArgs[0].Name = "Symbols"; + aArgs[0].Value <<= sGlyph; + + aArgs[1].Name = "FontName"; + aArgs[1].Value <<= aFont.GetFamilyName(); + comphelper::dispatchCommand(".uno:InsertSymbol", m_xFrame, aArgs); + + updateRecentCharacterList(sGlyph, aFont.GetFamilyName()); + + } else { + sal_Int32 tmp = 0; + sal_UCS4 cChar = sGlyph.iterateCodePoints(&tmp); + const SfxItemPool* pPool = m_xOutputSet->GetPool(); + m_xOutputSet->Put( SfxStringItem( pPool->GetWhich(SID_CHARMAP), sGlyph ) ); + m_xOutputSet->Put( SvxFontItem( aFont.GetFamilyType(), aFont.GetFamilyName(), + aFont.GetStyleName(), aFont.GetPitch(), aFont.GetCharSet(), pPool->GetWhich(SID_ATTR_CHAR_FONT) ) ); + m_xOutputSet->Put( SfxStringItem( pPool->GetWhich(SID_FONT_NAME), aFont.GetFamilyName() ) ); + m_xOutputSet->Put( SfxInt32Item( pPool->GetWhich(SID_ATTR_CHAR), cChar ) ); + } +} + +IMPL_LINK_NOARG(SvxCharacterMap, FontSelectHdl, weld::ComboBox&, void) +{ + const sal_uInt32 nFont = m_xFontLB->get_active_id().toUInt32(); + aFont = m_xVirDev->GetDevFont(nFont); + aFont.SetWeight( WEIGHT_DONTKNOW ); + aFont.SetItalic( ITALIC_NONE ); + aFont.SetWidthType( WIDTH_DONTKNOW ); + aFont.SetPitch( PITCH_DONTKNOW ); + aFont.SetFamily( FAMILY_DONTKNOW ); + + // notify children using this font + m_xShowSet->SetFont( aFont ); + m_xSearchSet->SetFont( aFont ); + m_aShowChar.SetFont( aFont ); + + // setup unicode subset listbar with font specific subsets, + // hide unicode subset listbar for symbol fonts + // TODO: get info from the Font once it provides it + pSubsetMap.reset(); + m_xSubsetLB->clear(); + + bool bNeedSubset = (aFont.GetCharSet() != RTL_TEXTENCODING_SYMBOL); + if (bNeedSubset) + { + FontCharMapRef xFontCharMap = m_xShowSet->GetFontCharMap(); + pSubsetMap.reset(new SubsetMap( xFontCharMap )); + + // update subset listbox for new font's unicode subsets + for (auto const& subset : pSubsetMap->GetSubsetMap()) + { + m_xSubsetLB->append(OUString::number(reinterpret_cast(&subset)), subset.GetName()); + // NOTE: subset must live at least as long as the selected font + } + + if (m_xSubsetLB->get_count() <= 1) + bNeedSubset = false; + } + + m_xSubsetText->set_sensitive(bNeedSubset); + m_xSubsetLB->set_sensitive(bNeedSubset); + + if (isSearchMode) + { + // tdf#137294 do this after modifying m_xSubsetLB sensitivity to + // restore insensitive for the search case + SearchUpdateHdl(*m_xSearchText); + SearchCharHighlightHdl(m_xSearchSet.get()); + } + + // tdf#118304 reselect current glyph to see if its still there in new font + selectCharByCode(Radix::hexadecimal); +} + +void SvxCharacterMap::toggleSearchView(bool state) +{ + isSearchMode = state; + m_xHexCodeText->set_editable(!state); + m_xDecimalCodeText->set_editable(!state); + m_xSubsetLB->set_sensitive(!state); + + if(state) + { + m_xSearchSet->Show(); + m_xShowSet->Hide(); + } + else + { + m_xSearchSet->Hide(); + m_xShowSet->Show(); + } +} + +void SvxCharacterMap::setCharName(sal_UCS4 nDecimalValue) +{ + /* get the character name */ + UErrorCode errorCode = U_ZERO_ERROR; + // icu has a private uprv_getMaxCharNameLength function which returns the max possible + // length of this property. Unicode 3.2 max char name length was 83 + char buffer[100]; + u_charName(nDecimalValue, U_UNICODE_CHAR_NAME, buffer, sizeof(buffer), &errorCode); + if (U_SUCCESS(errorCode)) + m_xCharName->set_label(OUString::createFromAscii(buffer)); +} + +IMPL_LINK_NOARG(SvxCharacterMap, SubsetSelectHdl, weld::ComboBox&, void) +{ + const sal_Int32 nPos = m_xSubsetLB->get_active(); + const Subset* pSubset = reinterpret_cast(m_xSubsetLB->get_active_id().toUInt64()); + + if( pSubset && !isSearchMode) + { + sal_UCS4 cFirst = pSubset->GetRangeMin(); + m_xShowSet->SelectCharacter( cFirst ); + + setFavButtonState(OUString(&cFirst, 1), aFont.GetFamilyName()); + m_xSubsetLB->set_active(nPos); + } + else if( pSubset && isSearchMode) + { + m_xSearchSet->SelectCharacter( pSubset ); + + const Subset* curSubset = nullptr; + if( pSubsetMap ) + curSubset = pSubsetMap->GetSubsetByUnicode( m_xSearchSet->GetSelectCharacter() ); + if( curSubset ) + m_xSubsetLB->set_active_text(curSubset->GetName()); + else + m_xSubsetLB->set_active(-1); + + sal_UCS4 sChar = m_xSearchSet->GetSelectCharacter(); + setFavButtonState(OUString(&sChar, 1), aFont.GetFamilyName()); + } +} + +IMPL_LINK(SvxCharacterMap, RecentClearClickHdl, SvxCharView*, rView, void) +{ + const OUString& sTitle = rView->GetText(); + auto itChar = std::find(maRecentCharList.begin(), maRecentCharList.end(), sTitle); + + OUString sFont = rView->GetFont().GetFamilyName(); + auto itChar2 = std::find(maRecentCharFontList.begin(), maRecentCharFontList.end(), sFont); + + // if recent char to be added is already in list, remove it + if( itChar != maRecentCharList.end() && itChar2 != maRecentCharFontList.end() ) + { + maRecentCharList.erase( itChar ); + maRecentCharFontList.erase( itChar2); + } + + css::uno::Sequence< OUString > aRecentCharList(maRecentCharList.size()); + css::uno::Sequence< OUString > aRecentCharFontList(maRecentCharFontList.size()); + + for (size_t i = 0; i < maRecentCharList.size(); ++i) + { + aRecentCharList[i] = maRecentCharList[i]; + aRecentCharFontList[i] = maRecentCharFontList[i]; + } + + std::shared_ptr batch(comphelper::ConfigurationChanges::create(mxContext)); + officecfg::Office::Common::RecentCharacters::RecentCharacterList::set(aRecentCharList, batch); + officecfg::Office::Common::RecentCharacters::RecentCharacterFontList::set(aRecentCharFontList, batch); + batch->commit(); + + updateRecentCharControl(); +} + +IMPL_LINK_NOARG(SvxCharacterMap, RecentClearAllClickHdl, SvxCharView*, void) +{ + css::uno::Sequence< OUString > aRecentCharList(0); + css::uno::Sequence< OUString > aRecentCharFontList(0); + + maRecentCharList.clear(); + maRecentCharFontList.clear(); + + std::shared_ptr batch(comphelper::ConfigurationChanges::create(mxContext)); + officecfg::Office::Common::RecentCharacters::RecentCharacterList::set(aRecentCharList, batch); + officecfg::Office::Common::RecentCharacters::RecentCharacterFontList::set(aRecentCharFontList, batch); + batch->commit(); + + updateRecentCharControl(); +} + +IMPL_LINK(SvxCharacterMap, FavClearClickHdl, SvxCharView*, rView, void) +{ + deleteFavCharacterFromList(rView->GetText(), rView->GetFont().GetFamilyName()); + updateFavCharControl(); +} + +IMPL_LINK_NOARG(SvxCharacterMap, FavClearAllClickHdl, SvxCharView*, void) +{ + css::uno::Sequence< OUString > aFavCharList(0); + css::uno::Sequence< OUString > aFavCharFontList(0); + + maFavCharList.clear(); + maFavCharFontList.clear(); + + std::shared_ptr batch(comphelper::ConfigurationChanges::create(mxContext)); + officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterList::set(aFavCharList, batch); + officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterFontList::set(aFavCharFontList, batch); + batch->commit(); + + updateFavCharControl(); +} + +IMPL_LINK_NOARG(SvxCharacterMap, SearchFieldGetFocusHdl, weld::Widget&, void) +{ + m_xOKBtn->set_sensitive(false); +} + +IMPL_LINK_NOARG(SvxCharacterMap, SearchUpdateHdl, weld::Entry&, void) +{ + if (!m_xSearchText->get_text().isEmpty()) + { + m_xSearchSet->ClearPreviousData(); + OUString aKeyword = m_xSearchText->get_text(); + + toggleSearchView(true); + + FontCharMapRef xFontCharMap = m_xSearchSet->GetFontCharMap(); + + sal_UCS4 sChar = xFontCharMap->GetFirstChar(); + while(sChar != xFontCharMap->GetLastChar()) + { + UErrorCode errorCode = U_ZERO_ERROR; + char buffer[100]; + u_charName(sChar, U_UNICODE_CHAR_NAME, buffer, sizeof(buffer), &errorCode); + if (U_SUCCESS(errorCode)) + { + OUString sName = OUString::createFromAscii(buffer); + if(!sName.isEmpty() && sName.toAsciiLowerCase().indexOf(aKeyword.toAsciiLowerCase()) >= 0) + m_xSearchSet->AppendCharToList(sChar); + } + sChar = xFontCharMap->GetNextChar(sChar); + } + //for last char + UErrorCode errorCode = U_ZERO_ERROR; + char buffer[100]; + u_charName(sChar, U_UNICODE_CHAR_NAME, buffer, sizeof(buffer), &errorCode); + if (U_SUCCESS(errorCode)) + { + OUString sName = OUString::createFromAscii(buffer); + if(!sName.isEmpty() && sName.toAsciiLowerCase().indexOf(aKeyword.toAsciiLowerCase()) >= 0) + m_xSearchSet->AppendCharToList(sChar); + } + } + else + { + toggleSearchView(false); + } +} + + +IMPL_LINK(SvxCharacterMap, CharClickHdl, SvxCharView*, rView, void) +{ + rView->GrabFocus(); + + m_aShowChar.SetText( rView->GetText() ); + m_aShowChar.SetFont(rView->GetFont()); + m_aShowChar.Invalidate(); + + setFavButtonState(rView->GetText(), rView->GetFont().GetFamilyName());//check state + + // Get the hexadecimal code + OUString charValue = rView->GetText(); + sal_Int32 tmp = 1; + sal_UCS4 cChar = charValue.iterateCodePoints(&tmp, -1); + OUString aHexText = OUString::number(cChar, 16).toAsciiUpperCase(); + + // Get the decimal code + OUString aDecimalText = OUString::number(cChar); + + m_xHexCodeText->set_text(aHexText); + m_xDecimalCodeText->set_text(aDecimalText); + setCharName(cChar); + + rView->Invalidate(); + m_xOKBtn->set_sensitive(true); +} + +IMPL_LINK_NOARG(SvxCharacterMap, CharDoubleClickHdl, SvxShowCharSet*, void) +{ + sal_UCS4 cChar = m_xShowSet->GetSelectCharacter(); + // using the new UCS4 constructor + OUString aOUStr( &cChar, 1 ); + setFavButtonState(aOUStr, aFont.GetFamilyName()); + insertCharToDoc(aOUStr); +} + +IMPL_LINK_NOARG(SvxCharacterMap, SearchCharDoubleClickHdl, SvxShowCharSet*, void) +{ + sal_UCS4 cChar = m_xSearchSet->GetSelectCharacter(); + // using the new UCS4 constructor + OUString aOUStr( &cChar, 1 ); + setFavButtonState(aOUStr, aFont.GetFamilyName()); + insertCharToDoc(aOUStr); +} + +IMPL_LINK_NOARG(SvxCharacterMap, CharSelectHdl, SvxShowCharSet*, void) +{ + m_xOKBtn->set_sensitive(true); +} + +IMPL_LINK_NOARG(SvxCharacterMap, SearchCharSelectHdl, SvxShowCharSet*, void) +{ + m_xOKBtn->set_sensitive(true); +} + +IMPL_LINK_NOARG(SvxCharacterMap, InsertClickHdl, weld::Button&, void) +{ + OUString sChar = m_aShowChar.GetText(); + insertCharToDoc(sChar); + // Need to update recent character list, when OK button does not insert + if(!m_xFrame.is()) + updateRecentCharacterList(sChar, aFont.GetFamilyName()); + m_xDialog->response(RET_OK); +} + +IMPL_LINK_NOARG(SvxCharacterMap, FavSelectHdl, weld::Button&, void) +{ + if (m_xFavouritesBtn->get_label().match(CuiResId(RID_SVXSTR_ADD_FAVORITES))) + { + updateFavCharacterList(m_aShowChar.GetText(), m_aShowChar.GetFont().GetFamilyName()); + setFavButtonState(m_aShowChar.GetText(), m_aShowChar.GetFont().GetFamilyName()); + } + else + { + deleteFavCharacterFromList(m_aShowChar.GetText(), m_aShowChar.GetFont().GetFamilyName()); + m_xFavouritesBtn->set_label(CuiResId(RID_SVXSTR_ADD_FAVORITES)); + m_xFavouritesBtn->set_sensitive(false); + } + + updateFavCharControl(); +} + +IMPL_LINK_NOARG(SvxCharacterMap, FavClickHdl, SvxShowCharSet*, void) +{ + getFavCharacterList(); + updateFavCharControl(); +} + +IMPL_LINK_NOARG(SvxCharacterMap, CharHighlightHdl, SvxShowCharSet*, void) +{ + OUString aText; + OUString aHexText; + OUString aDecimalText; + sal_UCS4 cChar = m_xShowSet->GetSelectCharacter(); + bool bSelect = (cChar > 0); + + // show char sample + if ( bSelect ) + { + // using the new UCS4 constructor + aText = OUString( &cChar, 1 ); + // Get the hexadecimal code + aHexText = OUString::number(cChar, 16).toAsciiUpperCase(); + // Get the decimal code + aDecimalText = OUString::number(cChar); + setCharName(cChar); + + // Update the hex and decimal codes only if necessary + if (!m_xHexCodeText->get_text().equalsIgnoreAsciiCase(aHexText)) + m_xHexCodeText->set_text(aHexText); + if (m_xDecimalCodeText->get_text() != aDecimalText) + m_xDecimalCodeText->set_text( aDecimalText ); + + const Subset* pSubset = nullptr; + if( pSubsetMap ) + pSubset = pSubsetMap->GetSubsetByUnicode( cChar ); + if( pSubset ) + m_xSubsetLB->set_active_text(pSubset->GetName()); + else + m_xSubsetLB->set_active(-1); + } + + m_aShowChar.SetText( aText ); + m_aShowChar.SetFont( aFont ); + m_aShowChar.Invalidate(); + + setFavButtonState(aText, aFont.GetFamilyName()); +} + +IMPL_LINK_NOARG(SvxCharacterMap, SearchCharHighlightHdl, SvxShowCharSet*, void) +{ + OUString aText; + OUString aHexText; + OUString aDecimalText; + sal_UCS4 cChar = m_xSearchSet->GetSelectCharacter(); + bool bSelect = (cChar > 0); + + // show char sample + if ( bSelect ) + { + aText = OUString( &cChar, 1 ); + // Get the hexadecimal code + aHexText = OUString::number(cChar, 16).toAsciiUpperCase(); + // Get the decimal code + aDecimalText = OUString::number(cChar); + setCharName(cChar); + + // Update the hex and decimal codes only if necessary + if (!m_xHexCodeText->get_text().equalsIgnoreAsciiCase(aHexText)) + m_xHexCodeText->set_text(aHexText); + if (m_xDecimalCodeText->get_text() != aDecimalText) + m_xDecimalCodeText->set_text( aDecimalText ); + + const Subset* pSubset = nullptr; + if( pSubsetMap ) + pSubset = pSubsetMap->GetSubsetByUnicode( cChar ); + if( pSubset ) + m_xSubsetLB->set_active_text(pSubset->GetName()); + else + m_xSubsetLB->set_active(-1); + } + + if(m_xSearchSet->HasFocus()) + { + m_aShowChar.SetText( aText ); + m_aShowChar.SetFont( aFont ); + m_aShowChar.Invalidate(); + + setFavButtonState(aText, aFont.GetFamilyName()); + } +} + +void SvxCharacterMap::selectCharByCode(Radix radix) +{ + OUString aCodeString; + switch(radix) + { + case Radix::decimal: + aCodeString = m_xDecimalCodeText->get_text(); + break; + case Radix::hexadecimal: + aCodeString = m_xHexCodeText->get_text(); + break; + } + // Convert the code back to a character using the appropriate radix + sal_UCS4 cChar = aCodeString.toUInt32(static_cast (radix)); + // Use FontCharMap::HasChar(sal_UCS4 cChar) to see if the desired character is in the font + FontCharMapRef xFontCharMap = m_xShowSet->GetFontCharMap(); + if (xFontCharMap->HasChar(cChar)) + // Select the corresponding character + SetChar(cChar); + else { + m_xCharName->set_label(CuiResId(RID_SVXSTR_MISSING_CHAR)); + m_aShowChar.SetText(" "); + switch(radix) + { + case Radix::decimal: + m_xHexCodeText->set_text(OUString::number(cChar, 16)); + break; + case Radix::hexadecimal: + m_xDecimalCodeText->set_text(OUString::number(cChar)); + break; + } + } +} + +IMPL_LINK_NOARG(SvxCharacterMap, DecimalCodeChangeHdl, weld::Entry&, void) +{ + selectCharByCode(Radix::decimal); +} + +IMPL_LINK_NOARG(SvxCharacterMap, HexCodeChangeHdl, weld::Entry&, void) +{ + selectCharByCode(Radix::hexadecimal); +} + +IMPL_LINK_NOARG(SvxCharacterMap, CharPreSelectHdl, SvxShowCharSet*, void) +{ + // adjust subset selection + if( pSubsetMap ) + { + sal_UCS4 cChar = m_xShowSet->GetSelectCharacter(); + + setFavButtonState(OUString(&cChar, 1), aFont.GetFamilyName()); + const Subset* pSubset = pSubsetMap->GetSubsetByUnicode( cChar ); + if( pSubset ) + m_xSubsetLB->set_active_text(pSubset->GetName()); + } + + m_xOKBtn->set_sensitive(true); +} + +IMPL_LINK_NOARG(SvxCharacterMap, SearchCharPreSelectHdl, SvxShowCharSet*, void) +{ + // adjust subset selection + if( pSubsetMap ) + { + sal_UCS4 cChar = m_xSearchSet->GetSelectCharacter(); + + setFavButtonState(OUString(&cChar, 1), aFont.GetFamilyName()); + const Subset* pSubset = pSubsetMap->GetSubsetByUnicode( cChar ); + if( pSubset ) + m_xSubsetLB->set_active_text(pSubset->GetName()); + } + + m_xOKBtn->set_sensitive(true); +} + +// class SvxShowText ===================================================== +SvxShowText::SvxShowText(const VclPtr& rVirDev) + : m_xVirDev(rVirDev) + , mnY(0) + , mbCenter(false) +{ +} + +void SvxShowText::SetDrawingArea(weld::DrawingArea* pDrawingArea) +{ + CustomWidgetController::SetDrawingArea(pDrawingArea); + vcl::Font aFont = m_xVirDev->GetFont(); + Size aFontSize(aFont.GetFontSize().Width() * 5, aFont.GetFontSize().Height() * 5); + aFont.SetFontSize(aFontSize); + m_xVirDev->Push(PUSH_ALLFONT); + m_xVirDev->SetFont(aFont); + pDrawingArea->set_size_request(m_xVirDev->approximate_digit_width() + 2 * 12, + m_xVirDev->LogicToPixel(aFontSize).Height() * 2); + m_xVirDev->Pop(); +} + +void SvxShowText::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&) +{ + rRenderContext.SetFont(m_aFont); + + Color aTextCol = rRenderContext.GetTextColor(); + Color aFillCol = rRenderContext.GetFillColor(); + + const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); + const Color aWindowTextColor(rStyleSettings.GetDialogTextColor()); + const Color aWindowColor(rStyleSettings.GetWindowColor()); + rRenderContext.SetTextColor(aWindowTextColor); + rRenderContext.SetFillColor(aWindowColor); + + const OUString aText = GetText(); + + Size aSize(GetOutputSizePixel()); + long nAvailWidth = aSize.Width(); + long nWinHeight = aSize.Height(); + + bool bGotBoundary = true; + bool bShrankFont = false; + vcl::Font aOrigFont(rRenderContext.GetFont()); + Size aFontSize(aOrigFont.GetFontSize()); + ::tools::Rectangle aBoundRect; + + for (long nFontHeight = aFontSize.Height(); nFontHeight > 0; nFontHeight -= 5) + { + if (!rRenderContext.GetTextBoundRect( aBoundRect, aText ) || aBoundRect.IsEmpty()) + { + bGotBoundary = false; + break; + } + if (!mbCenter) + break; + //only shrink in the single glyph large view mode + long nTextWidth = aBoundRect.GetWidth(); + if (nAvailWidth > nTextWidth) + break; + vcl::Font aFont(aOrigFont); + aFontSize.setHeight( nFontHeight ); + aFont.SetFontSize(aFontSize); + rRenderContext.SetFont(aFont); + mnY = (nWinHeight - rRenderContext.GetTextHeight()) / 2; + bShrankFont = true; + } + + Point aPoint(2, mnY); + // adjust position using ink boundary if possible + if (!bGotBoundary) + aPoint.setX( (aSize.Width() - rRenderContext.GetTextWidth(aText)) / 2 ); + else + { + // adjust position before it gets out of bounds + aBoundRect += aPoint; + + // shift back vertically if needed + int nYLDelta = aBoundRect.Top(); + int nYHDelta = aSize.Height() - aBoundRect.Bottom(); + if( nYLDelta <= 0 ) + aPoint.AdjustY( -(nYLDelta - 1) ); + else if( nYHDelta <= 0 ) + aPoint.AdjustY(nYHDelta - 1 ); + + if (mbCenter) + { + // move glyph to middle of cell + aPoint.setX( -aBoundRect.Left() + (aSize.Width() - aBoundRect.GetWidth()) / 2 ); + } + else + { + // shift back horizontally if needed + int nXLDelta = aBoundRect.Left(); + int nXHDelta = aSize.Width() - aBoundRect.Right(); + if( nXLDelta <= 0 ) + aPoint.AdjustX( -(nXLDelta - 1) ); + else if( nXHDelta <= 0 ) + aPoint.AdjustX(nXHDelta - 1 ); + } + } + + rRenderContext.DrawRect(tools::Rectangle(Point(0, 0), aSize)); + rRenderContext.DrawText(aPoint, aText); + rRenderContext.SetTextColor(aTextCol); + rRenderContext.SetFillColor(aFillCol); + if (bShrankFont) + rRenderContext.SetFont(aOrigFont); +} + +void SvxShowText::SetFont( const vcl::Font& rFont ) +{ + long nWinHeight = GetOutputSizePixel().Height(); + + m_aFont = rFont; + m_aFont.SetWeight(WEIGHT_NORMAL); + m_aFont.SetAlignment(ALIGN_TOP); + m_aFont.SetFontSize(m_xVirDev->PixelToLogic(Size(0, nWinHeight / 2))); + m_aFont.SetTransparent(true); + + m_xVirDev->Push(PUSH_ALLFONT); + m_xVirDev->SetFont(m_aFont); + mnY = (nWinHeight - m_xVirDev->GetTextHeight()) / 2; + m_xVirDev->Pop(); + + Invalidate(); +} + +void SvxShowText::Resize() +{ + SetFont(GetFont()); //force recalculation of size +} + +void SvxShowText::SetText(const OUString& rText) +{ + m_sText = rText; + Invalidate(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/cuifmsearch.cxx b/cui/source/dialogs/cuifmsearch.cxx new file mode 100644 index 000000000..de7681fa7 --- /dev/null +++ b/cui/source/dialogs/cuifmsearch.cxx @@ -0,0 +1,754 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace css::uno; +using namespace css::i18n; +using namespace ::svxform; +using namespace css::sdbc; +using namespace css::util; + +#define MAX_HISTORY_ENTRIES 50 + +void FmSearchDialog::initCommon( const Reference< XResultSet >& _rxCursor ) +{ + // init the engine + DBG_ASSERT( m_pSearchEngine, "FmSearchDialog::initCommon: have no engine!" ); + m_pSearchEngine->SetProgressHandler(LINK(this, FmSearchDialog, OnSearchProgress)); + + // some layout changes according to available CJK options + SvtCJKOptions aCJKOptions; + if (!aCJKOptions.IsJapaneseFindEnabled()) + { + // hide the options for the japanese search + m_pSoundsLikeCJK->hide(); + m_pSoundsLikeCJKSettings->hide(); + } + + if (!aCJKOptions.IsCJKFontEnabled()) + { + m_pHalfFullFormsCJK->hide(); + + // never ignore the width (ignoring is expensive) if the option is not available at all + m_pSearchEngine->SetIgnoreWidthCJK( false ); + } + + // some initial record texts + m_pftRecord->set_label( OUString::number(_rxCursor->getRow()) ); + m_pbClose->set_tooltip_text(OUString()); +} + +FmSearchDialog::FmSearchDialog(weld::Window* pParent, const OUString& sInitialText, const std::vector< OUString >& _rContexts, sal_Int16 nInitialContext, + const Link& lnkContextSupplier) + : GenericDialogController(pParent, "cui/ui/fmsearchdialog.ui", "RecordSearchDialog") + , m_sCancel( GetStandardText( StandardButtonType::Cancel ) ) + , m_lnkContextSupplier(lnkContextSupplier) + , m_prbSearchForText(m_xBuilder->weld_radio_button("rbSearchForText")) + , m_prbSearchForNull(m_xBuilder->weld_radio_button("rbSearchForNull")) + , m_prbSearchForNotNull(m_xBuilder->weld_radio_button("rbSearchForNotNull")) + , m_pcmbSearchText(m_xBuilder->weld_combo_box("cmbSearchText")) + , m_pftForm(m_xBuilder->weld_label("ftForm")) + , m_plbForm(m_xBuilder->weld_combo_box("lbForm")) + , m_prbAllFields(m_xBuilder->weld_radio_button("rbAllFields")) + , m_prbSingleField(m_xBuilder->weld_radio_button("rbSingleField")) + , m_plbField(m_xBuilder->weld_combo_box("lbField")) + , m_pftPosition(m_xBuilder->weld_label("ftPosition")) + , m_plbPosition(m_xBuilder->weld_combo_box("lbPosition")) + , m_pcbUseFormat(m_xBuilder->weld_check_button("cbUseFormat")) + , m_pcbCase(m_xBuilder->weld_check_button("cbCase")) + , m_pcbBackwards(m_xBuilder->weld_check_button("cbBackwards")) + , m_pcbStartOver(m_xBuilder->weld_check_button("cbStartOver")) + , m_pcbWildCard(m_xBuilder->weld_check_button("cbWildCard")) + , m_pcbRegular(m_xBuilder->weld_check_button("cbRegular")) + , m_pcbApprox(m_xBuilder->weld_check_button("cbApprox")) + , m_ppbApproxSettings(m_xBuilder->weld_button("pbApproxSettings")) + , m_pHalfFullFormsCJK(m_xBuilder->weld_check_button("HalfFullFormsCJK")) + , m_pSoundsLikeCJK(m_xBuilder->weld_check_button("SoundsLikeCJK")) + , m_pSoundsLikeCJKSettings(m_xBuilder->weld_button("SoundsLikeCJKSettings")) + , m_pftRecord(m_xBuilder->weld_label("ftRecord")) + , m_pftHint(m_xBuilder->weld_label("ftHint")) + , m_pbSearchAgain(m_xBuilder->weld_button("pbSearchAgain")) + , m_pbClose(m_xBuilder->weld_button("close")) +{ + m_pcmbSearchText->set_size_request(m_pcmbSearchText->get_approximate_digit_width() * 38, -1); + m_plbForm->set_size_request(m_plbForm->get_approximate_digit_width() * 38, -1); + m_sSearch = m_pbSearchAgain->get_label(); + + DBG_ASSERT(m_lnkContextSupplier.IsSet(), "FmSearchDialog::FmSearchDialog : have no ContextSupplier !"); + + FmSearchContext fmscInitial; + fmscInitial.nContext = nInitialContext; + m_lnkContextSupplier.Call(fmscInitial); + DBG_ASSERT(fmscInitial.xCursor.is(), "FmSearchDialog::FmSearchDialog : invalid data supplied by ContextSupplier !"); + DBG_ASSERT(comphelper::string::getTokenCount(fmscInitial.strUsedFields, ';') == static_cast(fmscInitial.arrFields.size()), + "FmSearchDialog::FmSearchDialog : invalid data supplied by ContextSupplied !"); +#if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL + for (const Reference & arrField : fmscInitial.arrFields) + { + DBG_ASSERT(arrField.is(), "FmSearchDialog::FmSearchDialog : invalid data supplied by ContextSupplier !"); + } +#endif // (OSL_DEBUG_LEVEL > 1) || DBG_UTIL + + for ( std::vector< OUString >::const_iterator context = _rContexts.begin(); + context != _rContexts.end(); + ++context + ) + { + m_arrContextFields.emplace_back(); + m_plbForm->append_text(*context); + } + m_plbForm->set_active(nInitialContext); + + m_plbForm->connect_changed(LINK(this, FmSearchDialog, OnContextSelection)); + + if (m_arrContextFields.size() == 1) + { + // hide dispensable controls + m_pftForm->hide(); + m_plbForm->hide(); + } + + m_pSearchEngine.reset( new FmSearchEngine( + ::comphelper::getProcessComponentContext(), fmscInitial.xCursor, fmscInitial.strUsedFields, fmscInitial.arrFields ) ); + initCommon( fmscInitial.xCursor ); + + if ( !fmscInitial.sFieldDisplayNames.isEmpty() ) + { // use the display names if supplied + DBG_ASSERT(comphelper::string::getTokenCount(fmscInitial.sFieldDisplayNames, ';') == comphelper::string::getTokenCount(fmscInitial.strUsedFields, ';'), + "FmSearchDialog::FmSearchDialog : invalid initial context description !"); + Init(fmscInitial.sFieldDisplayNames, sInitialText); + } + else + Init(fmscInitial.strUsedFields, sInitialText); +} + +FmSearchDialog::~FmSearchDialog() +{ + SaveParams(); + + m_pConfig.reset(); + m_pSearchEngine.reset(); +} + +void FmSearchDialog::Init(const OUString& strVisibleFields, const OUString& sInitialText) +{ + //the initialization of all the Controls + m_prbSearchForText->connect_clicked(LINK(this, FmSearchDialog, OnClickedFieldRadios)); + m_prbSearchForNull->connect_clicked(LINK(this, FmSearchDialog, OnClickedFieldRadios)); + m_prbSearchForNotNull->connect_clicked(LINK(this, FmSearchDialog, OnClickedFieldRadios)); + + m_prbAllFields->connect_clicked(LINK(this, FmSearchDialog, OnClickedFieldRadios)); + m_prbSingleField->connect_clicked(LINK(this, FmSearchDialog, OnClickedFieldRadios)); + + m_pbSearchAgain->connect_clicked(LINK(this, FmSearchDialog, OnClickedSearchAgain)); + m_ppbApproxSettings->connect_clicked(LINK(this, FmSearchDialog, OnClickedSpecialSettings)); + m_pSoundsLikeCJKSettings->connect_clicked(LINK(this, FmSearchDialog, OnClickedSpecialSettings)); + + m_plbPosition->connect_changed(LINK(this, FmSearchDialog, OnPositionSelected)); + m_plbField->connect_changed(LINK(this, FmSearchDialog, OnFieldSelected)); + + m_pcmbSearchText->connect_changed(LINK(this, FmSearchDialog, OnSearchTextModified)); + m_pcmbSearchText->set_entry_completion(false); + m_pcmbSearchText->connect_focus_in(LINK(this, FmSearchDialog, OnFocusGrabbed)); + + m_pcbUseFormat->connect_toggled(LINK(this, FmSearchDialog, OnCheckBoxToggled)); + m_pcbBackwards->connect_toggled(LINK(this, FmSearchDialog, OnCheckBoxToggled)); + m_pcbStartOver->connect_toggled(LINK(this, FmSearchDialog, OnCheckBoxToggled)); + m_pcbCase->connect_toggled(LINK(this, FmSearchDialog, OnCheckBoxToggled)); + m_pcbWildCard->connect_toggled(LINK(this, FmSearchDialog, OnCheckBoxToggled)); + m_pcbRegular->connect_toggled(LINK(this, FmSearchDialog, OnCheckBoxToggled)); + m_pcbApprox->connect_toggled(LINK(this, FmSearchDialog, OnCheckBoxToggled)); + m_pHalfFullFormsCJK->connect_toggled(LINK(this, FmSearchDialog, OnCheckBoxToggled)); + m_pSoundsLikeCJK->connect_toggled(LINK(this, FmSearchDialog, OnCheckBoxToggled)); + + // fill the listboxes + // method of field comparison + const char* const aResIds[] = { + RID_STR_SEARCH_ANYWHERE, + RID_STR_SEARCH_BEGINNING, + RID_STR_SEARCH_END, + RID_STR_SEARCH_WHOLE + }; + for (auto pResId : aResIds) + m_plbPosition->append_text(CuiResId(pResId)); + m_plbPosition->set_active(MATCHING_ANYWHERE); + + // the field listbox + if (!strVisibleFields.isEmpty()) + { + sal_Int32 nPos {0}; + do { + m_plbField->append_text(strVisibleFields.getToken(0, ';', nPos)); + } while (nPos>=0); + } + + + m_pConfig.reset( new FmSearchConfigItem ); + LoadParams(); + + m_pcmbSearchText->set_entry_text(sInitialText); + // if the Edit-line has changed the text (e.g. because it contains + // control characters, as can be the case with memo fields), I use + // an empty OUString. + OUString sRealSetText = m_pcmbSearchText->get_active_text(); + if (sRealSetText != sInitialText) + m_pcmbSearchText->set_entry_text(OUString()); + OnSearchTextModified(*m_pcmbSearchText); + + // initial + EnableSearchUI(true); + + if ( m_prbSearchForText->get_active() ) + m_pcmbSearchText->grab_focus(); + +} + +short FmSearchDialog::run() +{ + short nRet = weld::GenericDialogController::run(); + m_pSearchEngine->CancelSearch(); + return nRet; +} + +IMPL_LINK(FmSearchDialog, OnClickedFieldRadios, weld::Button&, rButton, void) +{ + if ((&rButton == m_prbSearchForText.get()) || (&rButton == m_prbSearchForNull.get()) || (&rButton == m_prbSearchForNotNull.get())) + { + EnableSearchForDependees(true); + } + else + // en- or disable field list box accordingly + if (&rButton == m_prbSingleField.get()) + { + m_plbField->set_sensitive(true); + m_pSearchEngine->RebuildUsedFields(m_plbField->get_active()); + } + else + { + m_plbField->set_sensitive(false); + m_pSearchEngine->RebuildUsedFields(-1); + } +} + +IMPL_LINK_NOARG(FmSearchDialog, OnClickedSearchAgain, weld::Button&, void) +{ + if (m_pbClose->get_sensitive()) + { // the button has the function 'search' + OUString strThisRoundText = m_pcmbSearchText->get_active_text(); + // to history + m_pcmbSearchText->remove_text(strThisRoundText); + m_pcmbSearchText->insert_text(0, strThisRoundText); + // the remove/insert makes sure that a) the OUString does not appear twice and + // that b) the last searched strings are at the beginning and limit the list length + while (m_pcmbSearchText->get_count() > MAX_HISTORY_ENTRIES) + m_pcmbSearchText->remove(m_pcmbSearchText->get_count()-1); + + // take out the 'overflow' hint + m_pftHint->set_label(OUString()); + + if (m_pcbStartOver->get_active()) + { + m_pcbStartOver->set_active(false); + EnableSearchUI(false); + if (m_prbSearchForText->get_active()) + m_pSearchEngine->StartOver(strThisRoundText); + else + m_pSearchEngine->StartOverSpecial(m_prbSearchForNull->get_active()); + } + else + { + EnableSearchUI(false); + if (m_prbSearchForText->get_active()) + m_pSearchEngine->SearchNext(strThisRoundText); + else + m_pSearchEngine->SearchNextSpecial(m_prbSearchForNull->get_active()); + } + } + else + { // the button has the function 'cancel' + // the CancelButton is usually only disabled, when working in a thread or with reschedule + m_pSearchEngine->CancelSearch(); + // the ProgressHandler is called when it's really finished, here it's only a demand + } +} + +IMPL_LINK(FmSearchDialog, OnClickedSpecialSettings, weld::Button&, rButton, void) +{ + if (m_ppbApproxSettings.get() == &rButton) + { + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateSvxSearchSimilarityDialog(m_xDialog.get(), m_pSearchEngine->GetLevRelaxed(), m_pSearchEngine->GetLevOther(), + m_pSearchEngine->GetLevShorter(), m_pSearchEngine->GetLevLonger() )); + if (pDlg->Execute() == RET_OK) + { + m_pSearchEngine->SetLevRelaxed( pDlg->IsRelaxed() ); + m_pSearchEngine->SetLevOther( pDlg->GetOther() ); + m_pSearchEngine->SetLevShorter(pDlg->GetShorter() ); + m_pSearchEngine->SetLevLonger( pDlg->GetLonger() ); + } + } + else if (m_pSoundsLikeCJKSettings.get() == &rButton) + { + SfxItemSet aSet( SfxGetpApp()->GetPool() ); + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr aDlg(pFact->CreateSvxJSearchOptionsDialog(m_xDialog.get(), aSet, m_pSearchEngine->GetTransliterationFlags() )); + aDlg->Execute(); + + TransliterationFlags nFlags = aDlg->GetTransliterationFlags(); + m_pSearchEngine->SetTransliterationFlags(nFlags); + + m_pcbCase->set_active(m_pSearchEngine->GetCaseSensitive()); + OnCheckBoxToggled( *m_pcbCase ); + m_pHalfFullFormsCJK->set_active( !m_pSearchEngine->GetIgnoreWidthCJK() ); + OnCheckBoxToggled( *m_pHalfFullFormsCJK ); + } +} + +IMPL_LINK_NOARG(FmSearchDialog, OnSearchTextModified, weld::ComboBox&, void) +{ + if ((!m_pcmbSearchText->get_active_text().isEmpty()) || !m_prbSearchForText->get_active()) + m_pbSearchAgain->set_sensitive(true); + else + m_pbSearchAgain->set_sensitive(false); + + m_pSearchEngine->InvalidatePreviousLoc(); +} + +IMPL_LINK_NOARG(FmSearchDialog, OnFocusGrabbed, weld::Widget&, void) +{ + m_pcmbSearchText->select_entry_region(0, -1); +} + +IMPL_LINK_NOARG(FmSearchDialog, OnPositionSelected, weld::ComboBox&, void) +{ + m_pSearchEngine->SetPosition(m_plbPosition->get_active()); +} + +IMPL_LINK_NOARG(FmSearchDialog, OnFieldSelected, weld::ComboBox&, void) +{ + m_pSearchEngine->RebuildUsedFields(m_prbAllFields->get_active() ? -1 : m_plbField->get_active()); + // calls m_pSearchEngine->InvalidatePreviousLoc too + + int nCurrentContext = m_plbForm->get_active(); + if (nCurrentContext != -1) + m_arrContextFields[nCurrentContext] = m_plbField->get_active_text(); +} + +IMPL_LINK(FmSearchDialog, OnCheckBoxToggled, weld::ToggleButton&, rBox, void) +{ + bool bChecked = rBox.get_active(); + + // formatter or case -> pass on to the engine + if (&rBox == m_pcbUseFormat.get()) + m_pSearchEngine->SetFormatterUsing(bChecked); + else if (&rBox == m_pcbCase.get()) + m_pSearchEngine->SetCaseSensitive(bChecked); + // direction -> pass on and reset the checkbox-text for StartOver + else if (&rBox == m_pcbBackwards.get()) + { + m_pcbStartOver->set_label( CuiResId( bChecked ? RID_STR_FROM_BOTTOM : RID_STR_FROM_TOP ) ); + m_pSearchEngine->SetDirection(!bChecked); + } + // similarity-search or regular expression + else if ((&rBox == m_pcbApprox.get()) || (&rBox == m_pcbRegular.get()) || (&rBox == m_pcbWildCard.get())) + { + weld::CheckButton* pBoxes[] = { m_pcbWildCard.get(), m_pcbRegular.get(), m_pcbApprox.get() }; + for (weld::CheckButton* pBoxe : pBoxes) + { + if (pBoxe != &rBox) + { + if (bChecked) + pBoxe->set_sensitive(false); + else + pBoxe->set_sensitive(true); + } + } + + // pass on to the engine + m_pSearchEngine->SetWildcard(m_pcbWildCard->get_sensitive() && m_pcbWildCard->get_active()); + m_pSearchEngine->SetRegular(m_pcbRegular->get_sensitive() && m_pcbRegular->get_active()); + m_pSearchEngine->SetLevenshtein(m_pcbApprox->get_sensitive() && m_pcbApprox->get_active()); + // (disabled boxes have to be passed to the engine as sal_False) + + // adjust the Position-Listbox (which is not allowed during Wildcard-search) + if (&rBox == m_pcbWildCard.get()) + { + if (bChecked) + { + m_pftPosition->set_sensitive(false); + m_plbPosition->set_sensitive(false); + } + else + { + m_pftPosition->set_sensitive(true); + m_plbPosition->set_sensitive(true); + } + } + + // and the button for similarity-search + if (&rBox == m_pcbApprox.get()) + { + if (bChecked) + m_ppbApproxSettings->set_sensitive(true); + else + m_ppbApproxSettings->set_sensitive(false); + } + } + else if (&rBox == m_pHalfFullFormsCJK.get()) + { + // forward to the search engine + m_pSearchEngine->SetIgnoreWidthCJK( !bChecked ); + } + else if (&rBox == m_pSoundsLikeCJK.get()) + { + m_pSoundsLikeCJKSettings->set_sensitive(bChecked); + + // two other buttons which depend on this one + bool bEnable = ( m_prbSearchForText->get_active() + && !m_pSoundsLikeCJK->get_active() + ) + || !SvtCJKOptions().IsJapaneseFindEnabled(); + m_pcbCase->set_sensitive(bEnable); + m_pHalfFullFormsCJK->set_sensitive(bEnable); + + // forward to the search engine + m_pSearchEngine->SetTransliteration( bChecked ); + } +} + +void FmSearchDialog::InitContext(sal_Int16 nContext) +{ + FmSearchContext fmscContext; + fmscContext.nContext = nContext; + + sal_uInt32 nResult = m_lnkContextSupplier.Call(fmscContext); + DBG_ASSERT(nResult > 0, "FmSearchDialog::InitContext : ContextSupplier didn't give me any controls !"); + + // put the field names into the respective listbox + m_plbField->clear(); + + if (!fmscContext.sFieldDisplayNames.isEmpty()) + { + // use the display names if supplied + DBG_ASSERT(comphelper::string::getTokenCount(fmscContext.sFieldDisplayNames, ';') == comphelper::string::getTokenCount(fmscContext.strUsedFields, ';'), + "FmSearchDialog::InitContext : invalid context description supplied !"); + sal_Int32 nPos {0}; + do { + m_plbField->append_text(fmscContext.sFieldDisplayNames.getToken(0, ';', nPos)); + } while (nPos>=0); + } + else if (!fmscContext.strUsedFields.isEmpty()) + { + // else use the field names + sal_Int32 nPos {0}; + do { + m_plbField->append_text(fmscContext.strUsedFields.getToken(0, ';', nPos)); + } while (nPos>=0); + } + + if (nContext < static_cast(m_arrContextFields.size()) && !m_arrContextFields[nContext].isEmpty()) + { + m_plbField->set_active_text(m_arrContextFields[nContext]); + } + else + { + m_plbField->set_active(0); + if (m_prbSingleField->get_active() && (m_plbField->get_count() > 1)) + m_plbField->grab_focus(); + } + + m_pSearchEngine->SwitchToContext(fmscContext.xCursor, fmscContext.strUsedFields, fmscContext.arrFields, + m_prbAllFields->get_active() ? -1 : 0); + + m_pftRecord->set_label(OUString::number(fmscContext.xCursor->getRow())); +} + +IMPL_LINK(FmSearchDialog, OnContextSelection, weld::ComboBox&, rBox, void) +{ + InitContext(rBox.get_active()); +} + +void FmSearchDialog::EnableSearchUI(bool bEnable) +{ + // the search button has two functions -> adjust its text accordingly + OUString sButtonText( bEnable ? m_sSearch : m_sCancel ); + m_pbSearchAgain->set_label(sButtonText); + + m_prbSearchForText->set_sensitive(bEnable); + m_prbSearchForNull->set_sensitive(bEnable); + m_prbSearchForNotNull->set_sensitive(bEnable); + m_plbForm->set_sensitive(bEnable); + m_prbAllFields->set_sensitive(bEnable); + m_prbSingleField->set_sensitive(bEnable); + m_plbField->set_sensitive(bEnable && m_prbSingleField->get_active()); + m_pcbBackwards->set_sensitive(bEnable); + m_pcbStartOver->set_sensitive(bEnable); + m_pbClose->set_sensitive(bEnable); + EnableSearchForDependees(bEnable); + + if ( !bEnable ) + { // this means we're preparing for starting a search + // In this case, EnableSearchForDependees disabled the search button + // But as we're about to use it for cancelling the search, we really need to enable it, again + m_pbSearchAgain->set_sensitive(true); + } +} + +void FmSearchDialog::EnableSearchForDependees(bool bEnable) +{ + bool bSearchingForText = m_prbSearchForText->get_active(); + m_pbSearchAgain->set_sensitive(bEnable && (!bSearchingForText || (!m_pcmbSearchText->get_active_text().isEmpty()))); + + bEnable = bEnable && bSearchingForText; + + bool bEnableRedundants = !m_pSoundsLikeCJK->get_active() || !SvtCJKOptions().IsJapaneseFindEnabled(); + + m_pcmbSearchText->set_sensitive(bEnable); + m_pftPosition->set_sensitive(bEnable && !m_pcbWildCard->get_active()); + m_pcbWildCard->set_sensitive(bEnable && !m_pcbRegular->get_active() && !m_pcbApprox->get_active()); + m_pcbRegular->set_sensitive(bEnable && !m_pcbWildCard->get_active() && !m_pcbApprox->get_active()); + m_pcbApprox->set_sensitive(bEnable && !m_pcbWildCard->get_active() && !m_pcbRegular->get_active()); + m_ppbApproxSettings->set_sensitive(bEnable && m_pcbApprox->get_active()); + m_pHalfFullFormsCJK->set_sensitive(bEnable && bEnableRedundants); + m_pSoundsLikeCJK->set_sensitive(bEnable); + m_pSoundsLikeCJKSettings->set_sensitive(bEnable && m_pSoundsLikeCJK->get_active()); + m_plbPosition->set_sensitive(bEnable && !m_pcbWildCard->get_active()); + m_pcbUseFormat->set_sensitive(bEnable); + m_pcbCase->set_sensitive(bEnable && bEnableRedundants); +} + +void FmSearchDialog::OnFound(const css::uno::Any& aCursorPos, sal_Int16 nFieldPos) +{ + FmFoundRecordInformation friInfo; + friInfo.nContext = m_plbForm->get_active(); + // if I don't do a search in a context, this has an invalid value - but then it doesn't matter anyway + friInfo.aPosition = aCursorPos; + if (m_prbAllFields->get_active()) + friInfo.nFieldPos = nFieldPos; + else + friInfo.nFieldPos = m_plbField->get_active(); + // this of course implies that I have really searched in the field that is selected in the listbox, + // which is made sure in RebuildUsedFields + + m_lnkFoundHandler.Call(friInfo); + + m_pcmbSearchText->grab_focus(); +} + +IMPL_LINK(FmSearchDialog, OnSearchProgress, const FmSearchProgress*, pProgress, void) +{ + SolarMutexGuard aGuard; + // make this single method thread-safe (it's an overkill to block the whole application for this, + // but we don't have another safety concept at the moment) + + switch (pProgress->aSearchState) + { + case FmSearchProgress::State::Progress: + if (pProgress->bOverflow) + { + OUString sHint( CuiResId( m_pcbBackwards->get_active() ? RID_STR_OVERFLOW_BACKWARD : RID_STR_OVERFLOW_FORWARD ) ); + m_pftHint->set_label( sHint ); + } + + m_pftRecord->set_label(OUString::number(1 + pProgress->nCurrentRecord)); + break; + + case FmSearchProgress::State::ProgressCounting: + m_pftHint->set_label(CuiResId(RID_STR_SEARCH_COUNTING)); + m_pftRecord->set_label(OUString::number(pProgress->nCurrentRecord)); + break; + + case FmSearchProgress::State::Successful: + OnFound(pProgress->aBookmark, static_cast(pProgress->nFieldIndex)); + EnableSearchUI(true); + break; + + case FmSearchProgress::State::Error: + case FmSearchProgress::State::NothingFound: + { + const char* pErrorId = (FmSearchProgress::State::Error == pProgress->aSearchState) + ? RID_STR_SEARCH_GENERAL_ERROR + : RID_STR_SEARCH_NORECORD; + std::unique_ptr xBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Warning, VclButtonsType::Ok, CuiResId(pErrorId))); + xBox->run(); + [[fallthrough]]; + } + case FmSearchProgress::State::Canceled: + EnableSearchUI(true); + if (m_lnkCanceledNotFoundHdl.IsSet()) + { + FmFoundRecordInformation friInfo; + friInfo.nContext = m_plbForm->get_active(); + // if I don't do a search in a context, this has an invalid value - but then it doesn't matter anyway + friInfo.aPosition = pProgress->aBookmark; + m_lnkCanceledNotFoundHdl.Call(friInfo); + } + break; + } + + m_pftRecord->set_label(OUString::number(1 + pProgress->nCurrentRecord)); +} + +void FmSearchDialog::LoadParams() +{ + FmSearchParams aParams(m_pConfig->getParams()); + + const OUString* pHistory = aParams.aHistory.getConstArray(); + const OUString* pHistoryEnd = pHistory + aParams.aHistory.getLength(); + for (; pHistory != pHistoryEnd; ++pHistory) + m_pcmbSearchText->append_text( *pHistory ); + + // I do the settings at my UI-elements and then I simply call the respective change-handler, + // that way the data is handed on to the SearchEngine and all dependent settings are done + + // current field + int nInitialField = m_plbField->find_text( aParams.sSingleSearchField ); + if (nInitialField == -1) + nInitialField = 0; + m_plbField->set_active(nInitialField); + OnFieldSelected(*m_plbField); + // all fields/single field (AFTER selecting the field because OnClickedFieldRadios expects a valid value there) + if (aParams.bAllFields) + { + m_prbSingleField->set_active(false); + m_prbAllFields->set_active(true); + OnClickedFieldRadios(*m_prbAllFields); + // OnClickedFieldRadios also calls to RebuildUsedFields + } + else + { + m_prbAllFields->set_active(false); + m_prbSingleField->set_active(true); + OnClickedFieldRadios(*m_prbSingleField); + } + + m_plbPosition->set_active(aParams.nPosition); + OnPositionSelected(*m_plbPosition); + + // field formatting/case sensitivity/direction + m_pcbUseFormat->set_active(aParams.bUseFormatter); + m_pcbCase->set_active( aParams.isCaseSensitive() ); + m_pcbBackwards->set_active(aParams.bBackwards); + OnCheckBoxToggled(*m_pcbUseFormat); + OnCheckBoxToggled(*m_pcbCase); + OnCheckBoxToggled(*m_pcbBackwards); + + m_pHalfFullFormsCJK->set_active( !aParams.isIgnoreWidthCJK( ) ); // BEWARE: this checkbox has an inverse semantics! + m_pSoundsLikeCJK->set_active( aParams.bSoundsLikeCJK ); + OnCheckBoxToggled(*m_pHalfFullFormsCJK); + OnCheckBoxToggled(*m_pSoundsLikeCJK); + + m_pcbWildCard->set_active(false); + m_pcbRegular->set_active(false); + m_pcbApprox->set_active(false); + OnCheckBoxToggled(*m_pcbWildCard); + OnCheckBoxToggled(*m_pcbRegular); + OnCheckBoxToggled(*m_pcbApprox); + + weld::CheckButton* pToCheck = nullptr; + if (aParams.bWildcard) + pToCheck = m_pcbWildCard.get(); + if (aParams.bRegular) + pToCheck = m_pcbRegular.get(); + if (aParams.bApproxSearch) + pToCheck = m_pcbApprox.get(); + if (aParams.bSoundsLikeCJK) + pToCheck = m_pSoundsLikeCJK.get(); + if (pToCheck) + { + pToCheck->set_active(true); + OnCheckBoxToggled(*pToCheck); + } + + // set Levenshtein-parameters directly at the SearchEngine + m_pSearchEngine->SetLevRelaxed(aParams.bLevRelaxed); + m_pSearchEngine->SetLevOther(aParams.nLevOther); + m_pSearchEngine->SetLevShorter(aParams.nLevShorter); + m_pSearchEngine->SetLevLonger(aParams.nLevLonger); + + m_pSearchEngine->SetTransliterationFlags( aParams.getTransliterationFlags( ) ); + + m_prbSearchForText->set_active(false); + m_prbSearchForNull->set_active(false); + m_prbSearchForNotNull->set_active(false); + switch (aParams.nSearchForType) + { + case 1: m_prbSearchForNull->set_active(true); break; + case 2: m_prbSearchForNotNull->set_active(true); break; + default: m_prbSearchForText->set_active(true); break; + } + OnClickedFieldRadios(*m_prbSearchForText); +} + +void FmSearchDialog::SaveParams() const +{ + if (!m_pConfig) + return; + + FmSearchParams aCurrentSettings; + + int nCount = m_pcmbSearchText->get_count(); + aCurrentSettings.aHistory.realloc(nCount); + OUString* pHistory = aCurrentSettings.aHistory.getArray(); + for (int i = 0; i < nCount; ++i, ++pHistory) + *pHistory = m_pcmbSearchText->get_text(i); + + aCurrentSettings.sSingleSearchField = m_plbField->get_active_text(); + aCurrentSettings.bAllFields = m_prbAllFields->get_active(); + aCurrentSettings.nPosition = m_pSearchEngine->GetPosition(); + aCurrentSettings.bUseFormatter = m_pSearchEngine->GetFormatterUsing(); + aCurrentSettings.setCaseSensitive ( m_pSearchEngine->GetCaseSensitive() ); + aCurrentSettings.bBackwards = !m_pSearchEngine->GetDirection(); + aCurrentSettings.bWildcard = m_pSearchEngine->GetWildcard(); + aCurrentSettings.bRegular = m_pSearchEngine->GetRegular(); + aCurrentSettings.bApproxSearch = m_pSearchEngine->GetLevenshtein(); + aCurrentSettings.bLevRelaxed = m_pSearchEngine->GetLevRelaxed(); + aCurrentSettings.nLevOther = m_pSearchEngine->GetLevOther(); + aCurrentSettings.nLevShorter = m_pSearchEngine->GetLevShorter(); + aCurrentSettings.nLevLonger = m_pSearchEngine->GetLevLonger(); + + aCurrentSettings.bSoundsLikeCJK = m_pSearchEngine->GetTransliteration(); + aCurrentSettings.setTransliterationFlags ( m_pSearchEngine->GetTransliterationFlags() ); + + if (m_prbSearchForNull->get_active()) + aCurrentSettings.nSearchForType = 1; + else if (m_prbSearchForNotNull->get_active()) + aCurrentSettings.nSearchForType = 2; + else + aCurrentSettings.nSearchForType = 0; + + m_pConfig->setParams( aCurrentSettings ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/cuigaldlg.cxx b/cui/source/dialogs/cuigaldlg.cxx new file mode 100644 index 000000000..de0b0c166 --- /dev/null +++ b/cui/source/dialogs/cuigaldlg.cxx @@ -0,0 +1,1011 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace ::ucbhelper; +using namespace ::cppu; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::ucb; +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star::uno; + + +SearchThread::SearchThread(SearchProgress* pProgress, + TPGalleryThemeProperties* pBrowser, + const INetURLObject& rStartURL) + : Thread("cuiSearchThread") + , mpProgress(pProgress) + , mpBrowser(pBrowser) + , maStartURL(rStartURL) +{ +} + +SearchThread::~SearchThread() +{ +} + +void SearchThread::execute() +{ + const OUString aFileType(mpBrowser->m_xCbbFileType->get_active_text()); + + if (!aFileType.isEmpty()) + { + const int nFileNumber = mpBrowser->m_xCbbFileType->find_text(aFileType); + sal_Int32 nBeginFormat, nEndFormat; + std::vector< OUString > aFormats; + + if( !nFileNumber || nFileNumber == -1) + { + nBeginFormat = 1; + nEndFormat = mpBrowser->m_xCbbFileType->get_count() - 1; + } + else + nBeginFormat = nEndFormat = nFileNumber; + + for (sal_Int32 i = nBeginFormat; i <= nEndFormat; ++i) + aFormats.push_back( mpBrowser->aFilterEntryList[ i ]->aFilterName.toAsciiLowerCase() ); + + ImplSearch( maStartURL, aFormats, mpBrowser->bSearchRecursive ); + } + + Application::PostUserEvent(LINK(mpProgress, SearchProgress, CleanUpHdl)); +} + + +void SearchThread::ImplSearch( const INetURLObject& rStartURL, + const std::vector< OUString >& rFormats, + bool bRecursive ) +{ + { + SolarMutexGuard aGuard; + + mpProgress->SetDirectory( rStartURL ); + } + + try + { + css::uno::Reference< XCommandEnvironment > xEnv; + Content aCnt( rStartURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), xEnv, comphelper::getProcessComponentContext() ); + Sequence< OUString > aProps( 2 ); + + aProps.getArray()[ 0 ] = "IsFolder"; + aProps.getArray()[ 1 ] = "IsDocument"; + css::uno::Reference< XResultSet > xResultSet( + aCnt.createCursor( aProps ) ); + + if( xResultSet.is() ) + { + css::uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY_THROW ); + css::uno::Reference< XRow > xRow( xResultSet, UNO_QUERY_THROW ); + + while( xResultSet->next() && schedule() ) + { + INetURLObject aFoundURL( xContentAccess->queryContentIdentifierString() ); + DBG_ASSERT( aFoundURL.GetProtocol() != INetProtocol::NotValid, "invalid URL" ); + + bool bFolder = xRow->getBoolean( 1 ); // property "IsFolder" + if ( xRow->wasNull() ) + bFolder = false; + + if( bRecursive && bFolder ) + ImplSearch( aFoundURL, rFormats, true ); + else + { + bool bDocument = xRow->getBoolean( 2 ); // property "IsDocument" + if ( xRow->wasNull() ) + bDocument = false; + + if( bDocument ) + { + GraphicDescriptor aDesc( aFoundURL ); + + if( ( aDesc.Detect() && + std::find( rFormats.begin(), + rFormats.end(), + GraphicDescriptor::GetImportFormatShortName( + aDesc.GetFileFormat() ).toAsciiLowerCase() ) + != rFormats.end() ) || + std::find( rFormats.begin(), + rFormats.end(), + aFoundURL.GetFileExtension().toAsciiLowerCase()) + != rFormats.end() ) + { + SolarMutexGuard aGuard; + + mpBrowser->aFoundList.push_back( + aFoundURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) + ); + mpBrowser->m_xLbxFound->insert_text( + mpBrowser->aFoundList.size() - 1, + GetReducedString(aFoundURL, 50)); + } + } + } + } + } + } + catch (const ContentCreationException&) + { + } + catch (const css::uno::RuntimeException&) + { + } + catch (const css::uno::Exception&) + { + } +} + +SearchProgress::SearchProgress(weld::Window* pParent, TPGalleryThemeProperties* pTabPage, const INetURLObject& rStartURL) + : GenericDialogController(pParent, "cui/ui/gallerysearchprogress.ui", "GallerySearchProgress") + , startUrl_(rStartURL) + , m_pTabPage(pTabPage) + , m_xFtSearchDir(m_xBuilder->weld_label("dir")) + , m_xFtSearchType(m_xBuilder->weld_label("file")) + , m_xBtnCancel(m_xBuilder->weld_button("cancel")) +{ + m_xFtSearchType->set_size_request(m_xFtSearchType->get_preferred_size().Width(), -1); + m_xBtnCancel->connect_clicked(LINK(this, SearchProgress, ClickCancelBtn)); +} + +SearchProgress::~SearchProgress() +{ +} + +IMPL_LINK_NOARG(SearchProgress, ClickCancelBtn, weld::Button&, void) +{ + if (m_aSearchThread.is()) + m_aSearchThread->terminate(); +} + +IMPL_LINK_NOARG(SearchProgress, CleanUpHdl, void*, void) +{ + if (m_aSearchThread.is()) + m_aSearchThread->join(); + + m_xDialog->response(RET_OK); +} + +void SearchProgress::LaunchThread() +{ + assert(!m_aSearchThread.is()); + m_aSearchThread = new SearchThread(this, m_pTabPage, startUrl_); + m_aSearchThread->launch(); +} + +TakeThread::TakeThread( + TakeProgress* pProgress, + TPGalleryThemeProperties* pBrowser, + TokenList_impl& rTakenList +) : + Thread ( "cuiTakeThread" ), + mpProgress ( pProgress ), + mpBrowser ( pBrowser ), + mrTakenList ( rTakenList ) +{ +} + + +TakeThread::~TakeThread() +{ +} + +void TakeThread::execute() +{ + sal_Int32 nEntries; + GalleryTheme* pThm = mpBrowser->GetXChgData()->pTheme; + std::unique_ptr pStatusProgress; + + std::vector aSelectedRows; + + { + SolarMutexGuard aGuard; + pStatusProgress.reset(new GalleryProgress); + if (mpBrowser->bTakeAll) + nEntries = mpBrowser->m_xLbxFound->n_children(); + else + { + aSelectedRows = mpBrowser->m_xLbxFound->get_selected_rows(); + nEntries = aSelectedRows.size(); + } + pThm->LockBroadcaster(); + } + + for( sal_Int32 i = 0; i < nEntries && schedule(); ++i ) + { + const sal_Int32 nPos = mpBrowser->bTakeAll ? i : aSelectedRows[i]; + const INetURLObject aURL( mpBrowser->aFoundList[ nPos ]); + + mrTakenList.push_back( nPos ); + + { + SolarMutexGuard aGuard; + + mpProgress->SetFile( aURL ); + pStatusProgress->Update( i, nEntries - 1 ); + pThm->InsertURL( aURL ); + } + } + + { + SolarMutexGuard aGuard; + + pThm->UnlockBroadcaster(); + pStatusProgress.reset(); + } + + Application::PostUserEvent(LINK(mpProgress, TakeProgress, CleanUpHdl)); +} + +TakeProgress::TakeProgress(weld::Window* pParent, TPGalleryThemeProperties* pTabPage) + : GenericDialogController(pParent, "cui/ui/galleryapplyprogress.ui", + "GalleryApplyProgress") + , m_pParent(pParent) + , m_pTabPage(pTabPage) + , m_xFtTakeFile(m_xBuilder->weld_label("file")) + , m_xBtnCancel(m_xBuilder->weld_button("cancel")) +{ + m_xBtnCancel->connect_clicked(LINK(this, TakeProgress, ClickCancelBtn)); +} + +TakeProgress::~TakeProgress() +{ +} + +IMPL_LINK_NOARG(TakeProgress, ClickCancelBtn, weld::Button&, void) +{ + if (maTakeThread.is()) + maTakeThread->terminate(); +} + + +IMPL_LINK_NOARG(TakeProgress, CleanUpHdl, void*, void) +{ + if (maTakeThread.is()) + maTakeThread->join(); + + std::vector > aRemoveEntries(m_pTabPage->aFoundList.size(), false); + std::vector< OUString > aRemainingVector; + sal_uInt32 i, nCount; + + std::unique_ptr xWait(new weld::WaitObject(m_pParent)); + + m_pTabPage->m_xLbxFound->select(-1); + m_pTabPage->m_xLbxFound->freeze(); + + // mark all taken positions in aRemoveEntries + for( i = 0, nCount = maTakenList.size(); i < nCount; ++i ) + aRemoveEntries[ maTakenList[ i ] ] = true; + maTakenList.clear(); + + // refill found list + for( i = 0, nCount = aRemoveEntries.size(); i < nCount; ++i ) + if( !aRemoveEntries[ i ] ) + aRemainingVector.push_back( m_pTabPage->aFoundList[i] ); + + m_pTabPage->aFoundList.clear(); + + for( i = 0, nCount = aRemainingVector.size(); i < nCount; ++i ) + m_pTabPage->aFoundList.push_back( aRemainingVector[ i ] ); + + aRemainingVector.clear(); + + // refill list box + for( i = 0, nCount = aRemoveEntries.size(); i < nCount; ++i ) + if( !aRemoveEntries[ i ] ) + aRemainingVector.push_back(m_pTabPage->m_xLbxFound->get_text(i)); + + m_pTabPage->m_xLbxFound->clear(); + + for( i = 0, nCount = aRemainingVector.size(); i < nCount; ++i ) + m_pTabPage->m_xLbxFound->append_text(aRemainingVector[i]); + + aRemainingVector.clear(); + + m_pTabPage->m_xLbxFound->thaw(); + m_pTabPage->SelectFoundHdl( *m_pTabPage->m_xLbxFound ); + + xWait.reset(); + + m_xDialog->response(RET_OK); +} + +void TakeProgress::LaunchThread() +{ + assert(!maTakeThread.is()); + maTakeThread = new TakeThread(this, m_pTabPage, maTakenList); + maTakeThread->launch(); +} + +ActualizeProgress::ActualizeProgress(weld::Widget* pWindow, GalleryTheme* pThm) + : GenericDialogController(pWindow, "cui/ui/galleryupdateprogress.ui", + "GalleryUpdateProgress") + , pIdle(nullptr) + , pTheme(pThm) + , m_xFtActualizeFile(m_xBuilder->weld_label("file")) + , m_xBtnCancel(m_xBuilder->weld_button("cancel")) +{ + m_xBtnCancel->connect_clicked(LINK(this, ActualizeProgress, ClickCancelBtn)); +} + +ActualizeProgress::~ActualizeProgress() +{ +} + +short ActualizeProgress::run() +{ + pIdle = new Idle("ActualizeProgressTimeout"); + pIdle->SetInvokeHandler( LINK( this, ActualizeProgress, TimeoutHdl ) ); + pIdle->SetPriority( TaskPriority::LOWEST ); + pIdle->Start(); + + return GenericDialogController::run(); +} + +IMPL_LINK_NOARG(ActualizeProgress, ClickCancelBtn, weld::Button&, void) +{ + pTheme->AbortActualize(); + m_xDialog->response(RET_OK); +} + +IMPL_LINK( ActualizeProgress, TimeoutHdl, Timer*, _pTimer, void) +{ + if (_pTimer) + { + _pTimer->Stop(); + delete _pTimer; + } + + pTheme->Actualize(LINK(this, ActualizeProgress, ActualizeHdl), &aStatusProgress); + ClickCancelBtn(*m_xBtnCancel); +} + +IMPL_LINK( ActualizeProgress, ActualizeHdl, const INetURLObject&, rURL, void ) +{ + Application::Reschedule(true); + m_xFtActualizeFile->set_label(GetReducedString(rURL, 30)); +} + +TitleDialog::TitleDialog(weld::Widget* pParent, const OUString& rOldTitle) + : GenericDialogController(pParent, "cui/ui/gallerytitledialog.ui", "GalleryTitleDialog") + , m_xEdit(m_xBuilder->weld_entry("entry")) +{ + m_xEdit->set_text(rOldTitle); + m_xEdit->grab_focus(); +} + +TitleDialog::~TitleDialog() +{ +} + +GalleryIdDialog::GalleryIdDialog(weld::Widget* pParent, GalleryTheme* _pThm) + : GenericDialogController(pParent, "cui/ui/gallerythemeiddialog.ui", "GalleryThemeIDDialog") + , m_pThm(_pThm) + , m_xBtnOk(m_xBuilder->weld_button("ok")) + , m_xLbResName(m_xBuilder->weld_combo_box("entry")) +{ + m_xLbResName->append_text("!!! No Id !!!"); + + GalleryTheme::InsertAllThemes(*m_xLbResName); + + m_xLbResName->set_active(m_pThm->GetId()); + m_xLbResName->grab_focus(); + + m_xBtnOk->connect_clicked(LINK(this, GalleryIdDialog, ClickOkHdl)); +} + +GalleryIdDialog::~GalleryIdDialog() +{ +} + +IMPL_LINK_NOARG(GalleryIdDialog, ClickOkHdl, weld::Button&, void) +{ + Gallery* pGal = m_pThm->GetParent(); + const sal_uInt32 nId = GetId(); + bool bDifferentThemeExists = false; + + for( size_t i = 0, nCount = pGal->GetThemeCount(); i < nCount && !bDifferentThemeExists; i++ ) + { + const GalleryThemeEntry* pInfo = pGal->GetThemeInfo( i ); + + if ((pInfo->GetId() == nId) && (pInfo->GetThemeName() != m_pThm->GetName())) + { + OUString aStr = CuiResId( RID_SVXSTR_GALLERY_ID_EXISTS ) + + " (" + pInfo->GetThemeName() + ")"; + + std::unique_ptr xInfoBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Info, VclButtonsType::Ok, + aStr)); + xInfoBox->run(); + m_xLbResName->grab_focus(); + bDifferentThemeExists = true; + } + } + + if (!bDifferentThemeExists) + m_xDialog->response(RET_OK); +} + +GalleryThemeProperties::GalleryThemeProperties(weld::Widget* pParent, + ExchangeData* _pData, SfxItemSet const * pItemSet) + : SfxTabDialogController(pParent, "cui/ui/gallerythemedialog.ui", + "GalleryThemeDialog", pItemSet) + , pData(_pData) +{ + AddTabPage("general", TPGalleryThemeGeneral::Create, nullptr); + AddTabPage("files", TPGalleryThemeProperties::Create, nullptr); + if (pData->pTheme->IsReadOnly()) + RemoveTabPage("files"); + + OUString aText = m_xDialog->get_title().replaceFirst( "%1", pData->pTheme->GetName() ); + + if (pData->pTheme->IsReadOnly()) + aText += " " + CuiResId( RID_SVXSTR_GALLERY_READONLY ); + + m_xDialog->set_title(aText); +} + +void GalleryThemeProperties::PageCreated(const OString& rId, SfxTabPage &rPage) +{ + if (rId == "general") + static_cast( rPage ).SetXChgData( pData ); + else + static_cast( rPage ).SetXChgData( pData ); +} + +TPGalleryThemeGeneral::TPGalleryThemeGeneral(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/gallerygeneralpage.ui", "GalleryGeneralPage", &rSet) + , pData(nullptr) + , m_xFiMSImage(m_xBuilder->weld_image("image")) + , m_xEdtMSName(m_xBuilder->weld_entry("name")) + , m_xFtMSShowType(m_xBuilder->weld_label("type")) + , m_xFtMSShowPath(m_xBuilder->weld_label("location")) + , m_xFtMSShowContent(m_xBuilder->weld_label("contents")) + , m_xFtMSShowChangeDate(m_xBuilder->weld_label("modified")) +{ +} + +void TPGalleryThemeGeneral::SetXChgData( ExchangeData* _pData ) +{ + pData = _pData; + + GalleryTheme* pThm = pData->pTheme; + OUString aOutStr( OUString::number(pThm->GetObjectCount()) ); + OUString aObjStr( CuiResId( RID_SVXSTR_GALLERYPROPS_OBJECT ) ); + OUString aAccess; + OUString aType( SvxResId( RID_SVXSTR_GALLERYPROPS_GALTHEME ) ); + bool bReadOnly = pThm->IsReadOnly(); + + m_xEdtMSName->set_text(pThm->GetName()); + m_xEdtMSName->set_editable(!bReadOnly); + m_xEdtMSName->set_sensitive(!bReadOnly); + + if( pThm->IsReadOnly() ) + aType += CuiResId( RID_SVXSTR_GALLERY_READONLY ); + + m_xFtMSShowType->set_label(aType); + m_xFtMSShowPath->set_label(pThm->GetSdgURL().GetMainURL(INetURLObject::DecodeMechanism::Unambiguous)); + + // singular or plural? + if ( 1 == pThm->GetObjectCount() ) + aObjStr = aObjStr.getToken( 0, ';' ); + else + aObjStr = aObjStr.getToken( 1, ';' ); + + aOutStr += " " + aObjStr; + + m_xFtMSShowContent->set_label(aOutStr); + + // get locale wrapper (singleton) + const SvtSysLocale aSysLocale; + const LocaleDataWrapper& aLocaleData = aSysLocale.GetLocaleData(); + + // ChangeDate/Time + aAccess = aLocaleData.getDate( pData->aThemeChangeDate ) + ", " + aLocaleData.getTime( pData->aThemeChangeTime ); + m_xFtMSShowChangeDate->set_label(aAccess); + + // set image + OUString sId; + + if( pThm->IsReadOnly() ) + sId = RID_SVXBMP_THEME_READONLY_BIG; + else if( pThm->IsDefault() ) + sId = RID_SVXBMP_THEME_DEFAULT_BIG; + else + sId = RID_SVXBMP_THEME_NORMAL_BIG; + + m_xFiMSImage->set_from_icon_name(sId); +} + +bool TPGalleryThemeGeneral::FillItemSet( SfxItemSet* /*rSet*/ ) +{ + pData->aEditedTitle = m_xEdtMSName->get_text(); + return true; +} + +std::unique_ptr TPGalleryThemeGeneral::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet) +{ + return std::make_unique(pPage, pController, *rSet); +} + +TPGalleryThemeProperties::TPGalleryThemeProperties(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/galleryfilespage.ui", "GalleryFilesPage", &rSet) + , pData(nullptr) + , bEntriesFound(false) + , bInputAllowed(true) + , bTakeAll(false) + , bSearchRecursive(false) + , xDialogListener(new ::svt::DialogClosedListener()) + , m_xCbbFileType(m_xBuilder->weld_combo_box("filetype")) + , m_xLbxFound(m_xBuilder->weld_tree_view("files")) + , m_xBtnSearch(m_xBuilder->weld_button("findfiles")) + , m_xBtnTake(m_xBuilder->weld_button("add")) + , m_xBtnTakeAll(m_xBuilder->weld_button("addall")) + , m_xCbxPreview(m_xBuilder->weld_check_button("preview")) + , m_xWndPreview(new weld::CustomWeld(*m_xBuilder, "image", m_aWndPreview)) +{ + m_xLbxFound->set_size_request(m_xLbxFound->get_approximate_digit_width() * 35, + m_xLbxFound->get_height_rows(15)); + m_xLbxFound->set_selection_mode(SelectionMode::Multiple); + xDialogListener->SetDialogClosedLink( LINK( this, TPGalleryThemeProperties, DialogClosedHdl ) ); +} + +void TPGalleryThemeProperties::SetXChgData( ExchangeData* _pData ) +{ + pData = _pData; + + aPreviewTimer.SetInvokeHandler( LINK( this, TPGalleryThemeProperties, PreviewTimerHdl ) ); + aPreviewTimer.SetTimeout( 500 ); + m_xBtnSearch->connect_clicked(LINK(this, TPGalleryThemeProperties, ClickSearchHdl)); + m_xBtnTake->connect_clicked(LINK(this, TPGalleryThemeProperties, ClickTakeHdl)); + m_xBtnTakeAll->connect_clicked(LINK(this, TPGalleryThemeProperties, ClickTakeAllHdl)); + m_xCbxPreview->connect_toggled(LINK(this, TPGalleryThemeProperties, ClickPreviewHdl)); + m_xCbbFileType->connect_changed(LINK(this, TPGalleryThemeProperties, SelectFileTypeHdl)); + m_xLbxFound->connect_row_activated(LINK(this, TPGalleryThemeProperties, DClickFoundHdl)); + m_xLbxFound->connect_changed(LINK(this, TPGalleryThemeProperties, SelectFoundHdl)); + m_xLbxFound->append_text(CuiResId(RID_SVXSTR_GALLERY_NOFILES)); + m_xLbxFound->show(); + + FillFilterList(); + + m_xBtnTake->set_sensitive(true); + m_xBtnTakeAll->set_sensitive(false); + m_xCbxPreview->set_sensitive(false); +} + +void TPGalleryThemeProperties::StartSearchFiles( const OUString& _rFolderURL, short _nDlgResult ) +{ + if ( RET_OK == _nDlgResult ) + { + aURL = INetURLObject( _rFolderURL ); + bSearchRecursive = true; // UI choice no longer possible, windows file picker allows no user controls + SearchFiles(); + } +} + +TPGalleryThemeProperties::~TPGalleryThemeProperties() +{ + xMediaPlayer.clear(); + xDialogListener.clear(); + aFilterEntryList.clear(); +} + +std::unique_ptr TPGalleryThemeProperties::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet) +{ + return std::make_unique(pPage, pController, *rSet); +} + +OUString TPGalleryThemeProperties::addExtension( const OUString& _rDisplayText, const OUString& _rExtension ) +{ + OUString sRet = _rDisplayText; + if ( sRet.indexOf( "(*.*)" ) == -1 ) + { + sRet += " (" + _rExtension + ")"; + } + return sRet; +} + +void TPGalleryThemeProperties::FillFilterList() +{ + GraphicFilter &rFilter = GraphicFilter::GetGraphicFilter(); + OUString aExt; + OUString aName; + sal_uInt16 i, nKeyCount; + + // graphic filters + for( i = 0, nKeyCount = rFilter.GetImportFormatCount(); i < nKeyCount; i++ ) + { + aExt = rFilter.GetImportFormatShortName( i ); + aName = rFilter.GetImportFormatName( i ); + size_t entryIndex = 0; + FilterEntry* pTestEntry = aFilterEntryList.empty() ? nullptr : aFilterEntryList[ entryIndex ].get(); + bool bInList = false; + + OUString aExtensions; + int j = 0; + OUString sWildcard; + while( true ) + { + sWildcard = rFilter.GetImportWildcard( i, j++ ); + if ( sWildcard.isEmpty() ) + break; + if ( aExtensions.indexOf( sWildcard ) == -1 ) + { + if ( !aExtensions.isEmpty() ) + aExtensions += ";"; + aExtensions += sWildcard; + } + } + aName = addExtension( aName, aExtensions ); + + while( pTestEntry ) + { + if ( pTestEntry->aFilterName == aExt ) + { + bInList = true; + break; + } + pTestEntry = ( ++entryIndex < aFilterEntryList.size() ) + ? aFilterEntryList[ entryIndex ].get() : nullptr; + } + if ( !bInList ) + { + std::unique_ptr pFilterEntry(new FilterEntry); + pFilterEntry->aFilterName = aExt; + m_xCbbFileType->append_text(aName); + aFilterEntryList.push_back(std::move(pFilterEntry)); + } + } + +#if HAVE_FEATURE_AVMEDIA + // media filters + static const char aWildcard[] = "*."; + ::avmedia::FilterNameVector aFilters= ::avmedia::MediaWindow::getMediaFilters(); + + for(const std::pair & aFilter : aFilters) + { + for( sal_Int32 nIndex = 0; nIndex >= 0; ) + { + OUString aFilterWildcard( aWildcard ); + + std::unique_ptr pFilterEntry(new FilterEntry); + pFilterEntry->aFilterName = aFilter.second.getToken( 0, ';', nIndex ); + aFilterWildcard += pFilterEntry->aFilterName; + m_xCbbFileType->append_text(addExtension(aFilter.first, aFilterWildcard)); + aFilterEntryList.push_back( std::move(pFilterEntry) ); + } + } +#endif + + // 'All' filters + OUString aExtensions; + + // graphic filters + for ( i = 0; i < nKeyCount; ++i ) + { + int j = 0; + OUString sWildcard; + while( true ) + { + sWildcard = rFilter.GetImportWildcard( i, j++ ); + if ( sWildcard.isEmpty() ) + break; + if ( aExtensions.indexOf( sWildcard ) == -1 ) + { + if ( !aExtensions.isEmpty() ) + aExtensions += ";"; + + aExtensions += sWildcard; + } + } + } + +#if HAVE_FEATURE_AVMEDIA + // media filters + for(const std::pair & aFilter : aFilters) + { + for( sal_Int32 nIndex = 0; nIndex >= 0; ) + { + if ( !aExtensions.isEmpty() ) + aExtensions += ";"; + aExtensions += aWildcard + aFilter.second.getToken( 0, ';', nIndex ); + } + } +#endif + +#if defined(_WIN32) + if (aExtensions.getLength() > 240) + aExtensions = "*.*"; +#endif + + std::unique_ptr pFilterEntry(new FilterEntry); + pFilterEntry->aFilterName = CuiResId(RID_SVXSTR_GALLERY_ALLFILES); + pFilterEntry->aFilterName = addExtension(pFilterEntry->aFilterName, aExtensions); + m_xCbbFileType->insert_text(0, pFilterEntry->aFilterName); + m_xCbbFileType->set_active(0); + aFilterEntryList.insert(aFilterEntryList.begin(), std::move(pFilterEntry)); +} + +IMPL_LINK_NOARG(TPGalleryThemeProperties, SelectFileTypeHdl, weld::ComboBox&, void) +{ + OUString aText(m_xCbbFileType->get_active_text()); + + if( bInputAllowed && ( aLastFilterName != aText ) ) + { + aLastFilterName = aText; + + std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/queryupdategalleryfilelistdialog.ui")); + std::unique_ptr xQuery(xBuilder->weld_message_dialog("QueryUpdateFileListDialog")); + if (xQuery->run() == RET_YES) + SearchFiles(); + } +} + +void TPGalleryThemeProperties::SearchFiles() +{ + auto xProgress = std::make_shared(GetFrameWeld(), this, aURL); + + aFoundList.clear(); + m_xLbxFound->clear(); + + xProgress->SetFileType( m_xCbbFileType->get_active_text() ); + xProgress->SetDirectory( INetURLObject() ); + + xProgress->LaunchThread(); + weld::DialogController::runAsync(xProgress, [this](sal_Int32 nResult) { + EndSearchProgressHdl(nResult); + }); +} + +IMPL_LINK_NOARG(TPGalleryThemeProperties, ClickSearchHdl, weld::Button&, void) +{ + if( !bInputAllowed ) + return; + + try + { + // setup folder picker + css::uno::Reference< XComponentContext > xContext( ::comphelper::getProcessComponentContext() ); + xFolderPicker = FolderPicker::create(xContext); + + OUString aDlgPathName( SvtPathOptions().GetGraphicPath() ); + xFolderPicker->setDisplayDirectory(aDlgPathName); + + aPreviewTimer.Stop(); + + css::uno::Reference< XAsynchronousExecutableDialog > xAsyncDlg( xFolderPicker, UNO_QUERY ); + if ( xAsyncDlg.is() ) + xAsyncDlg->startExecuteModal( xDialogListener.get() ); + else + { + if( xFolderPicker->execute() == RET_OK ) + { + aURL = INetURLObject( xFolderPicker->getDirectory() ); + bSearchRecursive = true; // UI choice no longer possible, windows file picker allows no user controls + SearchFiles(); + } + } + } + catch (const IllegalArgumentException&) + { + OSL_FAIL( "Folder picker failed with illegal arguments" ); + } +} + +void TPGalleryThemeProperties::TakeFiles() +{ + if (m_xLbxFound->count_selected_rows() || (bTakeAll && bEntriesFound)) + { + auto xTakeProgress = std::make_shared(GetFrameWeld(), this); + xTakeProgress->LaunchThread(); + weld::DialogController::runAsync(xTakeProgress, [=](sal_Int32 /*nResult*/) { + /* no postprocessing needed, pTakeProgress + will be disposed in TakeProgress::CleanupHdl */ + }); + + } +} + +IMPL_LINK_NOARG(TPGalleryThemeProperties, ClickPreviewHdl, weld::ToggleButton&, void) +{ + if ( !bInputAllowed ) + return; + + aPreviewTimer.Stop(); + aPreviewString.clear(); + + if (!m_xCbxPreview->get_active()) + { + xMediaPlayer.clear(); + m_aWndPreview.SetGraphic(Graphic()); + m_aWndPreview.Invalidate(); + } + else + DoPreview(); +} + +void TPGalleryThemeProperties::DoPreview() +{ + int nIndex = m_xLbxFound->get_selected_index(); + OUString aString(m_xLbxFound->get_text(nIndex)); + + if (aString == aPreviewString) + return; + + INetURLObject _aURL(aFoundList[nIndex]); + bInputAllowed = false; + + if (!m_aWndPreview.SetGraphic(_aURL)) + { + weld::WaitObject aWaitObject(GetFrameWeld()); + ErrorHandler::HandleError(ERRCODE_IO_NOTEXISTSPATH, GetFrameWeld()); + } +#if HAVE_FEATURE_AVMEDIA + else if( ::avmedia::MediaWindow::isMediaURL( _aURL.GetMainURL( INetURLObject::DecodeMechanism::Unambiguous ), "" ) ) + { + xMediaPlayer = ::avmedia::MediaWindow::createPlayer( _aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), "" ); + if( xMediaPlayer.is() ) + xMediaPlayer->start(); + } +#endif + bInputAllowed = true; + aPreviewString = aString; +} + +IMPL_LINK_NOARG(TPGalleryThemeProperties, ClickTakeHdl, weld::Button&, void) +{ + if( !bInputAllowed ) + return; + + aPreviewTimer.Stop(); + + if (!m_xLbxFound->count_selected_rows() || !bEntriesFound) + { + SvxOpenGraphicDialog aDlg(CuiResId(RID_SVXSTR_KEY_GALLERY_DIR), GetFrameWeld()); + aDlg.EnableLink(false); + aDlg.AsLink(false); + + if( !aDlg.Execute() ) + pData->pTheme->InsertURL( INetURLObject( aDlg.GetPath() ) ); + } + else + { + bTakeAll = false; + TakeFiles(); + } +} + +IMPL_LINK_NOARG(TPGalleryThemeProperties, ClickTakeAllHdl, weld::Button&, void) +{ + if( bInputAllowed ) + { + aPreviewTimer.Stop(); + bTakeAll = true; + TakeFiles(); + } +} + +IMPL_LINK_NOARG(TPGalleryThemeProperties, SelectFoundHdl, weld::TreeView&, void) +{ + if (!bInputAllowed) + return; + + bool bPreviewPossible = false; + + aPreviewTimer.Stop(); + + if( bEntriesFound ) + { + if (m_xLbxFound->count_selected_rows() == 1) + { + m_xCbxPreview->set_sensitive(true); + bPreviewPossible = true; + } + else + m_xCbxPreview->set_sensitive(false); + + if( !aFoundList.empty() ) + m_xBtnTakeAll->set_sensitive(true); + else + m_xBtnTakeAll->set_sensitive(false); + } + + if (bPreviewPossible && m_xCbxPreview->get_active()) + aPreviewTimer.Start(); +} + +IMPL_LINK_NOARG(TPGalleryThemeProperties, DClickFoundHdl, weld::TreeView&, bool) +{ + if( bInputAllowed ) + { + aPreviewTimer.Stop(); + + if (m_xLbxFound->count_selected_rows() == 1 && bEntriesFound) + ClickTakeHdl(*m_xBtnTake); + } + return true; +} + +IMPL_LINK_NOARG(TPGalleryThemeProperties, PreviewTimerHdl, Timer *, void) +{ + aPreviewTimer.Stop(); + DoPreview(); +} + +void TPGalleryThemeProperties::EndSearchProgressHdl(sal_Int32 /*nResult*/) +{ + if( !aFoundList.empty() ) + { + m_xLbxFound->select(0); + m_xBtnTakeAll->set_sensitive(true); + m_xCbxPreview->set_sensitive(true); + bEntriesFound = true; + } + else + { + m_xLbxFound->append_text(CuiResId(RID_SVXSTR_GALLERY_NOFILES)); + m_xBtnTakeAll->set_sensitive(false); + m_xCbxPreview->set_sensitive(false); + bEntriesFound = false; + } +} + +IMPL_LINK( TPGalleryThemeProperties, DialogClosedHdl, css::ui::dialogs::DialogClosedEvent*, pEvt, void ) +{ + DBG_ASSERT( xFolderPicker.is(), "TPGalleryThemeProperties::DialogClosedHdl(): no folder picker" ); + + OUString sURL = xFolderPicker->getDirectory(); + StartSearchFiles( sURL, pEvt->DialogResult ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/cuigrfflt.cxx b/cui/source/dialogs/cuigrfflt.cxx new file mode 100644 index 000000000..baaa6603c --- /dev/null +++ b/cui/source/dialogs/cuigrfflt.cxx @@ -0,0 +1,468 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +CuiGraphicPreviewWindow::CuiGraphicPreviewWindow() + : mpOrigGraphic(nullptr) + , mfScaleX(0.0) + , mfScaleY(0.0) +{ +} + +void CuiGraphicPreviewWindow::SetDrawingArea(weld::DrawingArea* pDrawingArea) +{ + CustomWidgetController::SetDrawingArea(pDrawingArea); + OutputDevice &rDevice = pDrawingArea->get_ref_device(); + maOutputSizePixel = rDevice.LogicToPixel(Size(81, 73), MapMode(MapUnit::MapAppFont)); + pDrawingArea->set_size_request(maOutputSizePixel.Width(), maOutputSizePixel.Height()); +} + +void CuiGraphicPreviewWindow::Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle&) +{ + rRenderContext.SetBackground(Wallpaper(Application::GetSettings().GetStyleSettings().GetDialogColor())); + rRenderContext.Erase(); + + const Size aOutputSize(GetOutputSizePixel()); + + if (maPreview.IsAnimated()) + { + const Size aGraphicSize(rRenderContext.LogicToPixel(maPreview.GetPrefSize(), maPreview.GetPrefMapMode())); + const Point aGraphicPosition((aOutputSize.Width() - aGraphicSize.Width() ) >> 1, + (aOutputSize.Height() - aGraphicSize.Height() ) >> 1); + maPreview.StartAnimation(&rRenderContext, aGraphicPosition, aGraphicSize); + } + else + { + const Size aGraphicSize(maPreview.GetSizePixel()); + const Point aGraphicPosition((aOutputSize.Width() - aGraphicSize.Width()) >> 1, + (aOutputSize.Height() - aGraphicSize.Height()) >> 1); + maPreview.Draw(&rRenderContext, aGraphicPosition, aGraphicSize); + } +} + +void CuiGraphicPreviewWindow::SetPreview(const Graphic& rGraphic) +{ + maPreview = rGraphic; + Invalidate(); +} + +void CuiGraphicPreviewWindow::ScaleImageToFit() +{ + if (!mpOrigGraphic) + return; + + maScaledOrig = *mpOrigGraphic; + + const Size aPreviewSize(GetOutputSizePixel()); + Size aGrfSize(maOrigGraphicSizePixel); + + if( mpOrigGraphic->GetType() == GraphicType::Bitmap && + aPreviewSize.Width() && aPreviewSize.Height() && + aGrfSize.Width() && aGrfSize.Height() ) + { + const double fGrfWH = static_cast(aGrfSize.Width()) / aGrfSize.Height(); + const double fPreWH = static_cast(aPreviewSize.Width()) / aPreviewSize.Height(); + + if( fGrfWH < fPreWH ) + { + aGrfSize.setWidth( static_cast( aPreviewSize.Height() * fGrfWH ) ); + aGrfSize.setHeight( aPreviewSize.Height() ); + } + else + { + aGrfSize.setWidth( aPreviewSize.Width() ); + aGrfSize.setHeight( static_cast( aPreviewSize.Width() / fGrfWH ) ); + } + + mfScaleX = static_cast(aGrfSize.Width()) / maOrigGraphicSizePixel.Width(); + mfScaleY = static_cast(aGrfSize.Height()) / maOrigGraphicSizePixel.Height(); + + if( !mpOrigGraphic->IsAnimated() ) + { + BitmapEx aBmpEx( mpOrigGraphic->GetBitmapEx() ); + + if( aBmpEx.Scale( aGrfSize ) ) + maScaledOrig = aBmpEx; + } + } + + maModifyHdl.Call(nullptr); +} + +void CuiGraphicPreviewWindow::Resize() +{ + maOutputSizePixel = GetOutputSizePixel(); + ScaleImageToFit(); +} + +GraphicFilterDialog::GraphicFilterDialog(weld::Window* pParent, + const OUString& rUIXMLDescription, const OString& rID, + const Graphic& rGraphic) + : GenericDialogController(pParent, rUIXMLDescription, rID) + , maModifyHdl(LINK(this, GraphicFilterDialog, ImplModifyHdl)) + , mxPreview(new weld::CustomWeld(*m_xBuilder, "preview", maPreview)) +{ + bIsBitmap = rGraphic.GetType() == GraphicType::Bitmap; + + maTimer.SetInvokeHandler(LINK(this, GraphicFilterDialog, ImplPreviewTimeoutHdl)); + maTimer.SetTimeout(5); + + maPreview.init(&rGraphic, maModifyHdl); +} + +IMPL_LINK_NOARG(GraphicFilterDialog, ImplPreviewTimeoutHdl, Timer *, void) +{ + maTimer.Stop(); + maPreview.SetPreview(GetFilteredGraphic(maPreview.GetScaledOriginal(), + maPreview.GetScaleX(), maPreview.GetScaleY())); +} + +IMPL_LINK_NOARG(GraphicFilterDialog, ImplModifyHdl, LinkParamNone*, void) +{ + if (bIsBitmap) + { + maTimer.Stop(); + maTimer.Start(); + } +} + +GraphicFilterMosaic::GraphicFilterMosaic(weld::Window* pParent, const Graphic& rGraphic, + sal_uInt16 nTileWidth, sal_uInt16 nTileHeight, bool bEnhanceEdges) + : GraphicFilterDialog(pParent, "cui/ui/mosaicdialog.ui", "MosaicDialog", rGraphic) + , mxMtrWidth(m_xBuilder->weld_metric_spin_button("width", FieldUnit::PIXEL)) + , mxMtrHeight(m_xBuilder->weld_metric_spin_button("height", FieldUnit::PIXEL)) + , mxCbxEdges(m_xBuilder->weld_check_button("edges")) +{ + mxMtrWidth->set_value(nTileWidth, FieldUnit::PIXEL); + mxMtrWidth->set_max(GetGraphicSizePixel().Width(), FieldUnit::PIXEL); + mxMtrWidth->connect_value_changed(LINK(this, GraphicFilterMosaic, EditModifyHdl)); + + mxMtrHeight->set_value(nTileHeight, FieldUnit::PIXEL); + mxMtrHeight->set_max(GetGraphicSizePixel().Height(), FieldUnit::PIXEL); + mxMtrHeight->connect_value_changed(LINK(this, GraphicFilterMosaic, EditModifyHdl)); + + mxCbxEdges->set_active(bEnhanceEdges); + mxCbxEdges->connect_toggled(LINK(this, GraphicFilterMosaic, CheckBoxModifyHdl)); + + mxMtrWidth->grab_focus(); +} + +IMPL_LINK_NOARG(GraphicFilterMosaic, CheckBoxModifyHdl, weld::ToggleButton&, void) +{ + GetModifyHdl().Call(nullptr); +} + +IMPL_LINK_NOARG(GraphicFilterMosaic, EditModifyHdl, weld::MetricSpinButton&, void) +{ + GetModifyHdl().Call(nullptr); +} + +Graphic GraphicFilterMosaic::GetFilteredGraphic( const Graphic& rGraphic, + double fScaleX, double fScaleY ) +{ + Graphic aRet; + long nTileWidth = static_cast(mxMtrWidth->get_value(FieldUnit::PIXEL)); + long nTileHeight = static_cast(mxMtrHeight->get_value(FieldUnit::PIXEL)); + const Size aSize( std::max( FRound( nTileWidth * fScaleX ), 1L ), + std::max( FRound( nTileHeight * fScaleY ), 1L ) ); + + if( rGraphic.IsAnimated() ) + { + Animation aAnim( rGraphic.GetAnimation() ); + + if (BitmapFilter::Filter(aAnim, BitmapMosaicFilter(aSize.getWidth(), aSize.getHeight()))) + { + if( IsEnhanceEdges() ) + (void)BitmapFilter::Filter(aAnim, BitmapSharpenFilter()); + + aRet = aAnim; + } + } + else + { + BitmapEx aBmpEx( rGraphic.GetBitmapEx() ); + + if (BitmapFilter::Filter(aBmpEx, BitmapMosaicFilter(aSize.getWidth(), aSize.getHeight()))) + { + if( IsEnhanceEdges() ) + BitmapFilter::Filter(aBmpEx, BitmapSharpenFilter()); + + aRet = aBmpEx; + } + } + + return aRet; +} + +GraphicFilterSmooth::GraphicFilterSmooth(weld::Window* pParent, const Graphic& rGraphic, double nRadius) + : GraphicFilterDialog(pParent, "cui/ui/smoothdialog.ui", "SmoothDialog", rGraphic) + , mxMtrRadius(m_xBuilder->weld_spin_button("radius")) +{ + mxMtrRadius->set_value(nRadius * 10); + mxMtrRadius->connect_value_changed(LINK(this, GraphicFilterSmooth, EditModifyHdl)); + mxMtrRadius->grab_focus(); +} + +IMPL_LINK_NOARG(GraphicFilterSmooth, EditModifyHdl, weld::SpinButton&, void) +{ + GetModifyHdl().Call(nullptr); +} + +Graphic GraphicFilterSmooth::GetFilteredGraphic( const Graphic& rGraphic, double, double ) +{ + Graphic aRet; + double nRadius = mxMtrRadius->get_value() / 10.0; + + if( rGraphic.IsAnimated() ) + { + Animation aAnim( rGraphic.GetAnimation() ); + + if (BitmapFilter::Filter(aAnim, BitmapSmoothenFilter(nRadius))) + { + aRet = aAnim; + } + } + else + { + BitmapEx aBmpEx( rGraphic.GetBitmapEx() ); + + if (BitmapFilter::Filter(aBmpEx, BitmapSmoothenFilter(nRadius))) + { + aRet = aBmpEx; + } + } + + return aRet; +} + +GraphicFilterSolarize::GraphicFilterSolarize(weld::Window* pParent, const Graphic& rGraphic, + sal_uInt8 cGreyThreshold, bool bInvert) + : GraphicFilterDialog(pParent, "cui/ui/solarizedialog.ui", "SolarizeDialog", rGraphic) + , mxMtrThreshold(m_xBuilder->weld_metric_spin_button("value", FieldUnit::PERCENT)) + , mxCbxInvert(m_xBuilder->weld_check_button("invert")) +{ + mxMtrThreshold->set_value(FRound(cGreyThreshold / 2.55), FieldUnit::PERCENT); + mxMtrThreshold->connect_value_changed(LINK(this, GraphicFilterSolarize, EditModifyHdl)); + + mxCbxInvert->set_active(bInvert); + mxCbxInvert->connect_toggled(LINK(this, GraphicFilterSolarize, CheckBoxModifyHdl)); +} + +IMPL_LINK_NOARG(GraphicFilterSolarize, CheckBoxModifyHdl, weld::ToggleButton&, void) +{ + GetModifyHdl().Call(nullptr); +} + +IMPL_LINK_NOARG(GraphicFilterSolarize, EditModifyHdl, weld::MetricSpinButton&, void) +{ + GetModifyHdl().Call(nullptr); +} + +Graphic GraphicFilterSolarize::GetFilteredGraphic( const Graphic& rGraphic, double, double ) +{ + Graphic aRet; + sal_uInt8 nGreyThreshold = static_cast(FRound(mxMtrThreshold->get_value(FieldUnit::PERCENT) * 2.55)); + + if( rGraphic.IsAnimated() ) + { + Animation aAnim( rGraphic.GetAnimation() ); + + if (BitmapFilter::Filter(aAnim, BitmapSolarizeFilter(nGreyThreshold))) + { + if( IsInvert() ) + aAnim.Invert(); + + aRet = aAnim; + } + } + else + { + BitmapEx aBmpEx( rGraphic.GetBitmapEx() ); + + if (BitmapFilter::Filter(aBmpEx, BitmapSolarizeFilter(nGreyThreshold))) + { + if( IsInvert() ) + aBmpEx.Invert(); + + aRet = aBmpEx; + } + } + + return aRet; +} + +GraphicFilterSepia::GraphicFilterSepia(weld::Window* pParent, const Graphic& rGraphic, + sal_uInt16 nSepiaPercent) + : GraphicFilterDialog(pParent, "cui/ui/agingdialog.ui", "AgingDialog", rGraphic) + , mxMtrSepia(m_xBuilder->weld_metric_spin_button("value", FieldUnit::PERCENT)) +{ + mxMtrSepia->set_value(nSepiaPercent, FieldUnit::PERCENT); + mxMtrSepia->connect_value_changed(LINK(this, GraphicFilterSepia, EditModifyHdl)); +} + +IMPL_LINK_NOARG(GraphicFilterSepia, EditModifyHdl, weld::MetricSpinButton&, void) +{ + GetModifyHdl().Call(nullptr); +} + +Graphic GraphicFilterSepia::GetFilteredGraphic( const Graphic& rGraphic, double, double ) +{ + Graphic aRet; + sal_uInt16 nSepiaPct = sal::static_int_cast< sal_uInt16 >(mxMtrSepia->get_value(FieldUnit::PERCENT)); + + if( rGraphic.IsAnimated() ) + { + Animation aAnim( rGraphic.GetAnimation() ); + + if (BitmapFilter::Filter(aAnim, BitmapSepiaFilter(nSepiaPct))) + aRet = aAnim; + } + else + { + BitmapEx aBmpEx( rGraphic.GetBitmapEx() ); + + if (BitmapFilter::Filter(aBmpEx, BitmapSepiaFilter(nSepiaPct))) + aRet = aBmpEx; + } + + return aRet; +} + +GraphicFilterPoster::GraphicFilterPoster(weld::Window* pParent, const Graphic& rGraphic, + sal_uInt16 nPosterCount) + : GraphicFilterDialog(pParent, "cui/ui/posterdialog.ui", "PosterDialog", rGraphic) + , mxNumPoster(m_xBuilder->weld_spin_button("value")) +{ + mxNumPoster->set_range(2, rGraphic.GetBitmapEx().GetBitCount()); + mxNumPoster->set_value(nPosterCount); + mxNumPoster->connect_value_changed(LINK(this, GraphicFilterPoster, EditModifyHdl)); +} + +IMPL_LINK_NOARG(GraphicFilterPoster, EditModifyHdl, weld::SpinButton&, void) +{ + GetModifyHdl().Call(nullptr); +} + +Graphic GraphicFilterPoster::GetFilteredGraphic( const Graphic& rGraphic, double, double ) +{ + Graphic aRet; + const sal_uInt16 nPosterCount = static_cast(mxNumPoster->get_value()); + + if( rGraphic.IsAnimated() ) + { + Animation aAnim( rGraphic.GetAnimation() ); + + if( aAnim.ReduceColors( nPosterCount ) ) + aRet = aAnim; + } + else + { + BitmapEx aBmpEx( rGraphic.GetBitmapEx() ); + + if (BitmapFilter::Filter(aBmpEx, BitmapColorQuantizationFilter(nPosterCount))) + aRet = aBmpEx; + } + + return aRet; +} + +bool EmbossControl::MouseButtonDown( const MouseEvent& rEvt ) +{ + const RectPoint eOldRP = GetActualRP(); + + SvxRectCtl::MouseButtonDown( rEvt ); + + if( GetActualRP() != eOldRP ) + maModifyHdl.Call( nullptr ); + + return true; +} + +void EmbossControl::SetDrawingArea(weld::DrawingArea* pDrawingArea) +{ + SvxRectCtl::SetDrawingArea(pDrawingArea); + Size aSize(pDrawingArea->get_ref_device().LogicToPixel(Size(77, 60), MapMode(MapUnit::MapAppFont))); + pDrawingArea->set_size_request(aSize.Width(), aSize.Height()); +} + +GraphicFilterEmboss::GraphicFilterEmboss(weld::Window* pParent, + const Graphic& rGraphic, RectPoint eLightSource) + : GraphicFilterDialog(pParent, "cui/ui/embossdialog.ui", "EmbossDialog", rGraphic) + , mxCtlLight(new weld::CustomWeld(*m_xBuilder, "lightsource", maCtlLight)) +{ + maCtlLight.SetActualRP(eLightSource); + maCtlLight.SetModifyHdl( GetModifyHdl() ); + maCtlLight.GrabFocus(); +} + +GraphicFilterEmboss::~GraphicFilterEmboss() +{ +} + +Graphic GraphicFilterEmboss::GetFilteredGraphic( const Graphic& rGraphic, double, double ) +{ + Graphic aRet; + sal_uInt16 nAzim, nElev; + + switch (maCtlLight.GetActualRP()) + { + default: OSL_FAIL("svx::GraphicFilterEmboss::GetFilteredGraphic(), unknown Reference Point!" ); + [[fallthrough]]; + case RectPoint::LT: nAzim = 4500; nElev = 4500; break; + case RectPoint::MT: nAzim = 9000; nElev = 4500; break; + case RectPoint::RT: nAzim = 13500; nElev = 4500; break; + case RectPoint::LM: nAzim = 0; nElev = 4500; break; + case RectPoint::MM: nAzim = 0; nElev = 9000; break; + case RectPoint::RM: nAzim = 18000; nElev = 4500; break; + case RectPoint::LB: nAzim = 31500; nElev = 4500; break; + case RectPoint::MB: nAzim = 27000; nElev = 4500; break; + case RectPoint::RB: nAzim = 22500; nElev = 4500; break; + } + + if( rGraphic.IsAnimated() ) + { + Animation aAnim( rGraphic.GetAnimation() ); + + if (BitmapFilter::Filter(aAnim, BitmapEmbossGreyFilter(nAzim, nElev))) + aRet = aAnim; + } + else + { + BitmapEx aBmpEx( rGraphic.GetBitmapEx() ); + + if (BitmapFilter::Filter(aBmpEx, BitmapEmbossGreyFilter(nAzim, nElev))) + aRet = aBmpEx; + } + + return aRet; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/cuihyperdlg.cxx b/cui/source/dialogs/cuihyperdlg.cxx new file mode 100644 index 000000000..9ca722680 --- /dev/null +++ b/cui/source/dialogs/cuihyperdlg.cxx @@ -0,0 +1,293 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::frame::XFrame; + + +//# # +//# Childwindow-Wrapper-Class # +//# # + + +SvxHlinkCtrl::SvxHlinkCtrl( sal_uInt16 _nId, SfxBindings & rBindings, SvxHpLinkDlg* pDlg ) + : SfxControllerItem ( _nId, rBindings ) + , aRdOnlyForwarder ( SID_READONLY_MODE, *this ) +{ + pParent = pDlg; +} + +void SvxHlinkCtrl::dispose() +{ + pParent = nullptr; + aRdOnlyForwarder.dispose(); + ::SfxControllerItem::dispose(); +} + +void SvxHlinkCtrl::StateChanged( sal_uInt16 nSID, SfxItemState eState, + const SfxPoolItem* pState ) +{ + if (!(eState == SfxItemState::DEFAULT && pParent)) + return; + + switch ( nSID ) + { + case SID_HYPERLINK_GETLINK : + { + pParent->SetPage( static_cast(pState) ); + } + break; + case SID_READONLY_MODE : + { + pParent->SetReadOnlyMode( static_cast(pState)->GetValue() ); + } + break; + } +} + +//# # +//# Hyperlink - Dialog # +//# # +SvxHpLinkDlg::SvxHpLinkDlg(SfxBindings* pBindings, SfxChildWindow* pChild, weld::Window* pParent) + : SfxModelessDialogController(pBindings, pChild, pParent, "cui/ui/hyperlinkdialog.ui", "HyperlinkDialog") + , pSet ( nullptr ) + , pExampleSet ( nullptr ) + , maCtrl ( SID_HYPERLINK_GETLINK, *pBindings, this ) + , mbIsHTMLDoc ( false ) + , m_xIconCtrl(m_xBuilder->weld_notebook("tabcontrol")) + , m_xOKBtn(m_xBuilder->weld_button("ok")) + , m_xApplyBtn(m_xBuilder->weld_button("apply")) + , m_xCancelBtn(m_xBuilder->weld_button("cancel")) + , m_xHelpBtn(m_xBuilder->weld_button("help")) + , m_xResetBtn(m_xBuilder->weld_button("reset")) +{ + m_xIconCtrl->connect_enter_page( LINK ( this, SvxHpLinkDlg, ChosePageHdl_Impl ) ); + m_xIconCtrl->show(); + + // ItemSet + if ( pSet ) + { + pExampleSet = new SfxItemSet( *pSet ); + pOutSet.reset(new SfxItemSet( *pSet->GetPool(), pSet->GetRanges() )); + } + + // Buttons + m_xOKBtn->show(); + m_xApplyBtn->show(); + m_xCancelBtn->show(); + m_xHelpBtn->show(); + m_xResetBtn->show(); + + mbGrabFocus = true; + + // set OK/Cancel - button + m_xCancelBtn->set_label(CuiResId(RID_SVXSTR_HYPDLG_CLOSEBUT)); + + // create itemset for tabpages + mpItemSet = std::make_unique( SfxGetpApp()->GetPool(), svl::Items{} ); + + SvxHyperlinkItem aItem(SID_HYPERLINK_GETLINK); + mpItemSet->Put(aItem); + + SetInputSet (mpItemSet.get()); + + // insert pages + AddTabPage("internet", SvxHyperlinkInternetTp::Create); + AddTabPage("mail", SvxHyperlinkMailTp::Create); + if (!comphelper::LibreOfficeKit::isActive()) + { + AddTabPage("document", SvxHyperlinkDocTp::Create); + AddTabPage("newdocument", SvxHyperlinkNewDocTp::Create); + } + + SetCurPageId("internet"); + + // Init Dialog + Start(); + + GetBindings().Update(SID_READONLY_MODE); + + m_xResetBtn->connect_clicked( LINK( this, SvxHpLinkDlg, ResetHdl ) ); + m_xOKBtn->connect_clicked( LINK ( this, SvxHpLinkDlg, ClickOkHdl_Impl ) ); + m_xApplyBtn->connect_clicked ( LINK ( this, SvxHpLinkDlg, ClickApplyHdl_Impl ) ); +} + +SvxHpLinkDlg::~SvxHpLinkDlg() +{ + // delete config item, so the base class (SfxModelessDialogController) can not load it on the next start + SvtViewOptions aViewOpt( EViewType::TabDialog, OUString::number(SID_HYPERLINK_DIALOG) ); + aViewOpt.Delete(); + + mpItemSet.reset(); + + maCtrl.dispose(); + + maPageList.clear(); + + pRanges.reset(); + pOutSet.reset(); +} + +void SvxHpLinkDlg::Close() +{ + if (IsClosing()) + return; + SfxViewFrame* pViewFrame = SfxViewFrame::Current(); + if (pViewFrame) + pViewFrame->ToggleChildWindow(SID_HYPERLINK_DIALOG); +} + +void SvxHpLinkDlg::Apply() +{ + SfxItemSet aItemSet( SfxGetpApp()->GetPool(), svl::Items{} ); + + SvxHyperlinkTabPageBase* pCurrentPage = static_cast( + GetTabPage( GetCurPageId() ) ); + + if ( pCurrentPage->AskApply() ) + { + pCurrentPage->FillItemSet( &aItemSet ); + + const SvxHyperlinkItem *aItem = aItemSet.GetItem(SID_HYPERLINK_SETLINK); + if ( !aItem->GetURL().isEmpty() ) + GetDispatcher()->ExecuteList(SID_HYPERLINK_SETLINK, + SfxCallMode::ASYNCHRON | SfxCallMode::RECORD, { aItem }); + + static_cast( GetTabPage( GetCurPageId() ) )->DoApply(); + } +} + +/// Click on OK button +IMPL_LINK_NOARG(SvxHpLinkDlg, ClickOkHdl_Impl, weld::Button&, void) +{ + Apply(); + m_xDialog->response(RET_OK); +} + +/************************************************************************* +|* +|* Click on Apply-button +|* +|************************************************************************/ +IMPL_LINK_NOARG(SvxHpLinkDlg, ClickApplyHdl_Impl, weld::Button&, void) +{ + Apply(); +} + +/************************************************************************* +|* +|* Set Page +|* +|************************************************************************/ +void SvxHpLinkDlg::SetPage ( SvxHyperlinkItem const * pItem ) +{ + OString sPageId("internet"); + + OUString aStrURL(pItem->GetURL()); + INetURLObject aURL(aStrURL); + INetProtocol eProtocolTyp = aURL.GetProtocol(); + + switch ( eProtocolTyp ) + { + case INetProtocol::Http : + case INetProtocol::Ftp : + sPageId = "internet"; + break; + case INetProtocol::File : + sPageId = "document"; + break; + case INetProtocol::Mailto : + sPageId = "mail"; + break; + default : + if (aStrURL.startsWith("#")) + sPageId = "document"; + else + { + // not valid + sPageId = GetCurPageId(); + } + break; + } + + ShowPage (sPageId); + + SvxHyperlinkTabPageBase* pCurrentPage = static_cast(GetTabPage( sPageId )); + + mbIsHTMLDoc = (pItem->GetInsertMode() & HLINK_HTMLMODE) != 0; + + IconChoicePage* pPage = GetTabPage (sPageId); + if(pPage) + { + SfxItemSet& aPageSet = const_cast(pPage->GetItemSet ()); + aPageSet.Put ( *pItem ); + + pCurrentPage->Reset( aPageSet ); + if ( mbGrabFocus ) + { + pCurrentPage->SetInitFocus(); // #92535# grab the focus only once at initialization + mbGrabFocus = false; + } + } +} + +/************************************************************************* +|* +|* Enable/Disable ReadOnly mode +|* +|************************************************************************/ +void SvxHpLinkDlg::SetReadOnlyMode( bool bRdOnly ) +{ + m_xOKBtn->set_sensitive(!bRdOnly); +} + +/************************************************************************* +|* +|* late-initialization of newly created pages +|* +|************************************************************************/ +void SvxHpLinkDlg::PageCreated(const OString& /*rId*/, IconChoicePage& rPage) +{ + SvxHyperlinkTabPageBase& rHyperlinkPage = dynamic_cast< SvxHyperlinkTabPageBase& >( rPage ); + Reference< XFrame > xDocumentFrame = GetBindings().GetActiveFrame(); + OSL_ENSURE( xDocumentFrame.is(), "SvxHpLinkDlg::PageCreated: macro assignment functionality won't work with a proper frame!" ); + rHyperlinkPage.SetDocumentFrame( xDocumentFrame ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/cuiimapwnd.cxx b/cui/source/dialogs/cuiimapwnd.cxx new file mode 100644 index 000000000..60346dc69 --- /dev/null +++ b/cui/source/dialogs/cuiimapwnd.cxx @@ -0,0 +1,59 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +/************************************************************************* +|* +|* URLDlg +|* +\************************************************************************/ + +URLDlg::URLDlg(weld::Widget* pWindow, const OUString& rURL, const OUString& rAlternativeText, + const OUString& rDescription, const OUString& rTarget, const OUString& rName, + TargetList& rTargetList) + : GenericDialogController(pWindow, "cui/ui/cuiimapdlg.ui", "IMapDialog") + , m_xEdtURL(m_xBuilder->weld_entry("urlentry")) + , m_xCbbTargets(m_xBuilder->weld_combo_box("frameCB")) + , m_xEdtName(m_xBuilder->weld_entry("nameentry")) + , m_xEdtAlternativeText(m_xBuilder->weld_entry("textentry")) + , m_xEdtDescription(m_xBuilder->weld_text_view("descTV")) +{ + m_xEdtDescription->set_size_request(m_xEdtDescription->get_approximate_digit_width() * 51, + m_xEdtDescription->get_height_rows(5)); + + m_xEdtURL->set_text( rURL ); + m_xEdtAlternativeText->set_text( rAlternativeText ); + m_xEdtDescription->set_text( rDescription ); + m_xEdtName->set_text( rName ); + + for (const OUString& a : rTargetList) + m_xCbbTargets->append_text(a); + + if (rTarget.isEmpty()) + m_xCbbTargets->set_entry_text("_self"); + else + m_xCbbTargets->set_entry_text(rTarget); +} + +URLDlg::~URLDlg() +{ +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/cuitbxform.cxx b/cui/source/dialogs/cuitbxform.cxx new file mode 100644 index 000000000..eb0a76814 --- /dev/null +++ b/cui/source/dialogs/cuitbxform.cxx @@ -0,0 +1,33 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +FmInputRecordNoDialog::FmInputRecordNoDialog(weld::Window * pParent) + : GenericDialogController(pParent, "cui/ui/recordnumberdialog.ui", "RecordNumberDialog") + , m_xRecordNo(m_xBuilder->weld_spin_button("entry")) +{ + m_xRecordNo->set_range(1, 0x7FFFFFFF); +} + +FmInputRecordNoDialog::~FmInputRecordNoDialog() +{ +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/dlgname.cxx b/cui/source/dialogs/dlgname.cxx new file mode 100644 index 000000000..d8044366b --- /dev/null +++ b/cui/source/dialogs/dlgname.cxx @@ -0,0 +1,104 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +/************************************************************************* +|* +|* Dialog for editing a name +|* +\************************************************************************/ + +SvxNameDialog::SvxNameDialog(weld::Window* pParent, const OUString& rName, const OUString& rDesc) + : GenericDialogController(pParent, "cui/ui/namedialog.ui", "NameDialog") + , m_xEdtName(m_xBuilder->weld_entry("name_entry")) + , m_xFtDescription(m_xBuilder->weld_label("description_label")) + , m_xBtnOK(m_xBuilder->weld_button("ok")) +{ + m_xFtDescription->set_label(rDesc); + m_xEdtName->set_text(rName); + m_xEdtName->select_region(0, -1); + ModifyHdl(*m_xEdtName); + m_xEdtName->connect_changed(LINK(this, SvxNameDialog, ModifyHdl)); +} + +IMPL_LINK_NOARG(SvxNameDialog, ModifyHdl, weld::Entry&, void) +{ + // Do not allow empty names + bool bEnable; + if (m_aCheckNameHdl.IsSet()) + bEnable = !m_xEdtName->get_text().isEmpty() && m_aCheckNameHdl.Call(*this); + else + bEnable = !m_xEdtName->get_text().isEmpty(); + m_xBtnOK->set_sensitive(bEnable); + // tdf#129032: feedback on reason to disabled controls + m_xEdtName->set_message_type(bEnable ? weld::EntryMessageType::Normal : weld::EntryMessageType::Error); + OUString rTip = ""; + if (!bEnable && m_aCheckNameTooltipHdl.IsSet()) + rTip = m_aCheckNameTooltipHdl.Call(*this); + m_xBtnOK->set_tooltip_text(rTip); + m_xEdtName->set_tooltip_text(rTip); +} + +// #i68101# +// Dialog for editing Object Name +// plus uniqueness-callback-linkHandler + +SvxObjectNameDialog::SvxObjectNameDialog(weld::Window* pParent, const OUString& rName) + : GenericDialogController(pParent, "cui/ui/objectnamedialog.ui", "ObjectNameDialog") + , m_xEdtName(m_xBuilder->weld_entry("object_name_entry")) + , m_xBtnOK(m_xBuilder->weld_button("ok")) +{ + // set name + m_xEdtName->set_text(rName); + m_xEdtName->select_region(0, -1); + + // activate name + ModifyHdl(*m_xEdtName); + m_xEdtName->connect_changed(LINK(this, SvxObjectNameDialog, ModifyHdl)); +} + +IMPL_LINK_NOARG(SvxObjectNameDialog, ModifyHdl, weld::Entry&, void) +{ + if (aCheckNameHdl.IsSet()) + { + m_xBtnOK->set_sensitive(aCheckNameHdl.Call(*this)); + } +} + +// #i68101# +// Dialog for editing Object Title and Description + +SvxObjectTitleDescDialog::SvxObjectTitleDescDialog(weld::Window* pParent, const OUString& rTitle, + const OUString& rDescription) + : GenericDialogController(pParent, "cui/ui/objecttitledescdialog.ui", "ObjectTitleDescDialog") + , m_xEdtTitle(m_xBuilder->weld_entry("object_title_entry")) + , m_xEdtDescription(m_xBuilder->weld_text_view("desc_entry")) +{ + //lock height to initial height + m_xEdtDescription->set_size_request(-1, m_xEdtDescription->get_text_height() * 5); + // set title & desc + m_xEdtTitle->set_text(rTitle); + m_xEdtDescription->set_text(rDescription); + + // activate title + m_xEdtTitle->select_region(0, -1); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/hangulhanjadlg.cxx b/cui/source/dialogs/hangulhanjadlg.cxx new file mode 100644 index 000000000..5e273b3b1 --- /dev/null +++ b/cui/source/dialogs/hangulhanjadlg.cxx @@ -0,0 +1,1505 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define HHC editeng::HangulHanjaConversion +#define LINE_CNT static_cast< sal_uInt16 >(2) +#define MAXNUM_SUGGESTIONS 50 + + +namespace svx +{ + + using namespace ::com::sun::star; + using namespace css::uno; + using namespace css::linguistic2; + using namespace css::lang; + using namespace css::container; + + + namespace + { + class FontSwitch + { + private: + OutputDevice& m_rDev; + + public: + FontSwitch( OutputDevice& _rDev, const vcl::Font& _rTemporaryFont ) + :m_rDev( _rDev ) + { + m_rDev.Push( PushFlags::FONT ); + m_rDev.SetFont( _rTemporaryFont ); + } + ~FontSwitch() COVERITY_NOEXCEPT_FALSE + { + m_rDev.Pop(); + } + }; + + /** a class which allows to draw two texts in a pseudo-ruby way (which basically + means one text above or below the other, and a little bit smaller) + */ + class PseudoRubyText + { + public: + enum RubyPosition + { + eAbove, eBelow + }; + + protected: + OUString m_sPrimaryText; + OUString m_sSecondaryText; + RubyPosition m_ePosition; + + public: + PseudoRubyText(); + void init( const OUString& rPrimaryText, const OUString& rSecondaryText, const RubyPosition& rPosition ); + const OUString& getPrimaryText() const { return m_sPrimaryText; } + const OUString& getSecondaryText() const { return m_sSecondaryText; } + + public: + void Paint( vcl::RenderContext& _rDevice, const ::tools::Rectangle& _rRect, + ::tools::Rectangle* _pPrimaryLocation, ::tools::Rectangle* _pSecondaryLocation ); + }; + + } + + PseudoRubyText::PseudoRubyText() + : m_ePosition(eAbove) + { + } + + void PseudoRubyText::init( const OUString& rPrimaryText, const OUString& rSecondaryText, const RubyPosition& rPosition ) + { + m_sPrimaryText = rPrimaryText; + m_sSecondaryText = rSecondaryText; + m_ePosition = rPosition; + } + + + void PseudoRubyText::Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle& _rRect, + ::tools::Rectangle* _pPrimaryLocation, ::tools::Rectangle* _pSecondaryLocation ) + { + // calculate the text flags for the painting + constexpr DrawTextFlags nTextStyle = DrawTextFlags::Mnemonic | + DrawTextFlags::Left | + DrawTextFlags::VCenter; + + Size aPlaygroundSize(_rRect.GetSize()); + + // the font for the secondary text: + vcl::Font aSmallerFont(rRenderContext.GetFont()); + // heuristic: 80% of the original size + aSmallerFont.SetFontHeight( static_cast( 0.8 * aSmallerFont.GetFontHeight() ) ); + + // let's calculate the size of our two texts + ::tools::Rectangle aPrimaryRect = rRenderContext.GetTextRect( _rRect, m_sPrimaryText, nTextStyle ); + ::tools::Rectangle aSecondaryRect; + { + FontSwitch aFontRestore(rRenderContext, aSmallerFont); + aSecondaryRect = rRenderContext.GetTextRect(_rRect, m_sSecondaryText, nTextStyle); + } + + // position these rectangles properly + // x-axis: + sal_Int32 nCombinedWidth = std::max( aSecondaryRect.GetWidth(), aPrimaryRect.GetWidth() ); + // the rectangle where both texts will reside is as high as possible, and as wide as the + // widest of both text rects + aPrimaryRect.SetLeft( _rRect.Left() ); + aSecondaryRect.SetLeft( aPrimaryRect.Left() ); + aPrimaryRect.SetRight( _rRect.Left() + nCombinedWidth ); + aSecondaryRect.SetRight( aPrimaryRect.Right() ); + + // y-axis: + sal_Int32 nCombinedHeight = aPrimaryRect.GetHeight() + aSecondaryRect.GetHeight(); + // align to the top, for the moment + aPrimaryRect.Move( 0, _rRect.Top() - aPrimaryRect.Top() ); + aSecondaryRect.Move( 0, aPrimaryRect.Top() + aPrimaryRect.GetHeight() - aSecondaryRect.Top() ); + // move the rects to the bottom + aPrimaryRect.Move( 0, ( aPlaygroundSize.Height() - nCombinedHeight ) / 2 ); + aSecondaryRect.Move( 0, ( aPlaygroundSize.Height() - nCombinedHeight ) / 2 ); + + // 'til here, everything we did assumes that the secondary text is painted _below_ the primary + // text. If this isn't the case, we need to correct the rectangles + if (eAbove == m_ePosition) + { + sal_Int32 nVertDistance = aSecondaryRect.Top() - aPrimaryRect.Top(); + aSecondaryRect.Move( 0, -nVertDistance ); + aPrimaryRect.Move( 0, nCombinedHeight - nVertDistance ); + } + + // now draw the texts + // as we already calculated the precise rectangles for the texts, we don't want to + // use the alignment flags given - within it's rect, every text is centered + DrawTextFlags nDrawTextStyle( nTextStyle ); + nDrawTextStyle &= ~DrawTextFlags( DrawTextFlags::Right | DrawTextFlags::Left | DrawTextFlags::Bottom | DrawTextFlags::Top ); + nDrawTextStyle |= DrawTextFlags::Center | DrawTextFlags::VCenter; + + rRenderContext.DrawText( aPrimaryRect, m_sPrimaryText, nDrawTextStyle ); + { + FontSwitch aFontRestore(rRenderContext, aSmallerFont); + rRenderContext.DrawText( aSecondaryRect, m_sSecondaryText, nDrawTextStyle ); + } + + // outta here + if (_pPrimaryLocation) + *_pPrimaryLocation = aPrimaryRect; + if (_pSecondaryLocation) + *_pSecondaryLocation = aSecondaryRect; + } + + class RubyRadioButton + { + public: + RubyRadioButton(std::unique_ptr xControl); + void init(const OUString& rPrimaryText, const OUString& rSecondaryText, const PseudoRubyText::RubyPosition& rPosition); + + void set_sensitive(bool sensitive) { m_xControl->set_sensitive(sensitive); } + void set_active(bool active) { m_xControl->set_active(active); } + bool get_active() const { return m_xControl->get_active(); } + + void connect_clicked(const Link& rLink) { m_xControl->connect_clicked(rLink); } + + private: + Size GetOptimalSize() const; + void Paint(vcl::RenderContext& rRenderContext); + + ScopedVclPtr m_xVirDev; + std::unique_ptr m_xControl; + PseudoRubyText m_aRubyText; + }; + + RubyRadioButton::RubyRadioButton(std::unique_ptr xControl) + : m_xVirDev(xControl->create_virtual_device()) + , m_xControl(std::move(xControl)) + { + // expand the point size of the desired font to the equivalent pixel size + if (vcl::Window* pDefaultDevice = dynamic_cast(Application::GetDefaultDevice())) + pDefaultDevice->SetPointFont(*m_xVirDev, m_xControl->get_font()); + } + + void RubyRadioButton::init( const OUString& rPrimaryText, const OUString& rSecondaryText, const PseudoRubyText::RubyPosition& rPosition ) + { + m_aRubyText.init(rPrimaryText, rSecondaryText, rPosition); + + m_xVirDev->SetOutputSizePixel(GetOptimalSize()); + + Paint(*m_xVirDev); + + m_xControl->set_image(m_xVirDev.get()); + } + + void RubyRadioButton::Paint(vcl::RenderContext& rRenderContext) + { + ::tools::Rectangle aOverallRect(Point(0, 0), rRenderContext.GetOutputSizePixel()); + // inflate the rect a little bit (because the VCL radio button does the same) + ::tools::Rectangle aTextRect( aOverallRect ); + aTextRect.AdjustLeft( 1 ); aTextRect.AdjustRight( -1 ); + aTextRect.AdjustTop( 1 ); aTextRect.AdjustBottom( -1 ); + + // paint the ruby text + ::tools::Rectangle aPrimaryTextLocation; + ::tools::Rectangle aSecondaryTextLocation; + + m_aRubyText.Paint(rRenderContext, aTextRect, &aPrimaryTextLocation, &aSecondaryTextLocation); + } + + Size RubyRadioButton::GetOptimalSize() const + { + vcl::Font aSmallerFont(m_xVirDev->GetFont()); + aSmallerFont.SetFontHeight( static_cast( 0.8 * aSmallerFont.GetFontHeight() ) ); + ::tools::Rectangle rect( Point(), Size( SAL_MAX_INT32, SAL_MAX_INT32 ) ); + + Size aPrimarySize = m_xVirDev->GetTextRect( rect, m_aRubyText.getPrimaryText() ).GetSize(); + Size aSecondarySize; + { + FontSwitch aFontRestore(*m_xVirDev, aSmallerFont); + aSecondarySize = m_xVirDev->GetTextRect( rect, m_aRubyText.getSecondaryText() ).GetSize(); + } + + Size minimumSize; + minimumSize.setHeight( aPrimarySize.Height() + aSecondarySize.Height() + 5 ); + minimumSize.setWidth( aPrimarySize.Width() + aSecondarySize.Width() + 5 ); + return minimumSize; + } + + SuggestionSet::SuggestionSet(std::unique_ptr xScrolledWindow) + : ValueSet(std::move(xScrolledWindow)) + + { + } + + void SuggestionSet::UserDraw( const UserDrawEvent& rUDEvt ) + { + vcl::RenderContext* pDev = rUDEvt.GetRenderContext(); + ::tools::Rectangle aRect = rUDEvt.GetRect(); + sal_uInt16 nItemId = rUDEvt.GetItemId(); + + OUString sText = *static_cast< OUString* >( GetItemData( nItemId ) ); + pDev->DrawText( aRect, sText, DrawTextFlags::Center | DrawTextFlags::VCenter ); + } + + SuggestionDisplay::SuggestionDisplay(weld::Builder& rBuilder) + : m_bDisplayListBox( true ) + , m_bInSelectionUpdate( false ) + , m_xValueSet(new SuggestionSet(rBuilder.weld_scrolled_window("scrollwin"))) + , m_xValueSetWin(new weld::CustomWeld(rBuilder, "valueset", *m_xValueSet)) + , m_xListBox(rBuilder.weld_tree_view("listbox")) + { + m_xValueSet->SetSelectHdl( LINK( this, SuggestionDisplay, SelectSuggestionValueSetHdl ) ); + m_xListBox->connect_changed( LINK( this, SuggestionDisplay, SelectSuggestionListBoxHdl ) ); + + m_xValueSet->SetLineCount( LINE_CNT ); + m_xValueSet->SetStyle( m_xValueSet->GetStyle() | WB_ITEMBORDER | WB_VSCROLL ); + + OUString const aOneCharacter("AU"); + auto nItemWidth = 2 * m_xListBox->get_pixel_size(aOneCharacter).Width(); + m_xValueSet->SetItemWidth( nItemWidth ); + + Size aSize(m_xListBox->get_approximate_digit_width() * 42, m_xListBox->get_text_height() * 5); + m_xValueSet->set_size_request(aSize.Width(), aSize.Height()); + m_xListBox->set_size_request(aSize.Width(), aSize.Height()); + + implUpdateDisplay(); + } + + void SuggestionDisplay::implUpdateDisplay() + { + m_xListBox->set_visible(m_bDisplayListBox); + if (!m_bDisplayListBox) + m_xValueSetWin->show(); + else + m_xValueSetWin->hide(); + } + + weld::Widget& SuggestionDisplay::implGetCurrentControl() + { + if (m_bDisplayListBox) + return *m_xListBox; + return *m_xValueSet->GetDrawingArea(); + } + + void SuggestionDisplay::DisplayListBox( bool bDisplayListBox ) + { + if( m_bDisplayListBox == bDisplayListBox ) + return; + + weld::Widget& rOldControl = implGetCurrentControl(); + bool bHasFocus = rOldControl.has_focus(); + + m_bDisplayListBox = bDisplayListBox; + + if( bHasFocus ) + { + weld::Widget& rNewControl = implGetCurrentControl(); + rNewControl.grab_focus(); + } + + implUpdateDisplay(); + } + + IMPL_LINK_NOARG(SuggestionDisplay, SelectSuggestionValueSetHdl, ValueSet*, void) + { + SelectSuggestionHdl(false); + } + + IMPL_LINK_NOARG(SuggestionDisplay, SelectSuggestionListBoxHdl, weld::TreeView&, void) + { + SelectSuggestionHdl(true); + } + + void SuggestionDisplay::SelectSuggestionHdl(bool bListBox) + { + if( m_bInSelectionUpdate ) + return; + + m_bInSelectionUpdate = true; + if (bListBox) + { + sal_uInt16 nPos = m_xListBox->get_selected_index(); + m_xValueSet->SelectItem( nPos+1 ); //itemid == pos+1 (id 0 has special meaning) + } + else + { + sal_uInt16 nPos = m_xValueSet->GetSelectedItemId()-1; //itemid == pos+1 (id 0 has special meaning) + m_xListBox->select(nPos); + } + m_bInSelectionUpdate = false; + m_aSelectLink.Call( *this ); + } + + void SuggestionDisplay::SetSelectHdl( const Link& rLink ) + { + m_aSelectLink = rLink; + } + + void SuggestionDisplay::Clear() + { + m_xListBox->clear(); + m_xValueSet->Clear(); + } + + void SuggestionDisplay::InsertEntry( const OUString& rStr ) + { + m_xListBox->append_text(rStr); + sal_uInt16 nItemId = m_xListBox->n_children(); //itemid == pos+1 (id 0 has special meaning) + m_xValueSet->InsertItem( nItemId ); + OUString* pItemData = new OUString( rStr ); + m_xValueSet->SetItemData( nItemId, pItemData ); + } + + void SuggestionDisplay::SelectEntryPos( sal_uInt16 nPos ) + { + m_xListBox->select(nPos); + m_xValueSet->SelectItem( nPos+1 ); //itemid == pos+1 (id 0 has special meaning) + } + + sal_uInt16 SuggestionDisplay::GetEntryCount() const + { + return m_xListBox->n_children(); + } + + OUString SuggestionDisplay::GetEntry( sal_uInt16 nPos ) const + { + return m_xListBox->get_text( nPos ); + } + + OUString SuggestionDisplay::GetSelectedEntry() const + { + return m_xListBox->get_selected_text(); + } + + void SuggestionDisplay::SetHelpIds() + { + m_xValueSet->SetHelpId(HID_HANGULDLG_SUGGESTIONS_GRID); + m_xListBox->set_help_id(HID_HANGULDLG_SUGGESTIONS_LIST); + } + + HangulHanjaConversionDialog::HangulHanjaConversionDialog(weld::Window* pParent) + : GenericDialogController(pParent, "cui/ui/hangulhanjaconversiondialog.ui", "HangulHanjaConversionDialog") + , m_bDocumentMode( true ) + , m_xFind(m_xBuilder->weld_button("find")) + , m_xIgnore(m_xBuilder->weld_button("ignore")) + , m_xIgnoreAll(m_xBuilder->weld_button("ignoreall")) + , m_xReplace(m_xBuilder->weld_button("replace")) + , m_xReplaceAll(m_xBuilder->weld_button("replaceall")) + , m_xOptions(m_xBuilder->weld_button("options")) + , m_xSuggestions(new SuggestionDisplay(*m_xBuilder)) + , m_xSimpleConversion(m_xBuilder->weld_radio_button("simpleconversion")) + , m_xHangulBracketed(m_xBuilder->weld_radio_button("hangulbracket")) + , m_xHanjaBracketed(m_xBuilder->weld_radio_button("hanjabracket")) + , m_xWordInput(m_xBuilder->weld_entry("wordinput")) + , m_xOriginalWord(m_xBuilder->weld_label("originalword")) + , m_xHanjaAbove(new RubyRadioButton(m_xBuilder->weld_radio_button("hanja_above"))) + , m_xHanjaBelow(new RubyRadioButton(m_xBuilder->weld_radio_button("hanja_below"))) + , m_xHangulAbove(new RubyRadioButton(m_xBuilder->weld_radio_button("hangul_above"))) + , m_xHangulBelow(new RubyRadioButton(m_xBuilder->weld_radio_button("hangul_below"))) + , m_xHangulOnly(m_xBuilder->weld_check_button("hangulonly")) + , m_xHanjaOnly(m_xBuilder->weld_check_button("hanjaonly")) + , m_xReplaceByChar(m_xBuilder->weld_check_button("replacebychar")) + { + m_xSuggestions->set_size_request(m_xOriginalWord->get_approximate_digit_width() * 42, + m_xOriginalWord->get_text_height() * 5); + + const OUString sHangul(CuiResId(RID_SVXSTR_HANGUL)); + const OUString sHanja(CuiResId(RID_SVXSTR_HANJA)); + m_xHanjaAbove->init( sHangul, sHanja, PseudoRubyText::eAbove ); + m_xHanjaBelow->init( sHangul, sHanja, PseudoRubyText::eBelow ); + m_xHangulAbove->init( sHanja, sHangul, PseudoRubyText::eAbove ); + m_xHangulBelow->init( sHanja, sHangul, PseudoRubyText::eBelow ); + + m_xWordInput->connect_changed( LINK( this, HangulHanjaConversionDialog, OnSuggestionModified ) ); + m_xSuggestions->SetSelectHdl( LINK( this, HangulHanjaConversionDialog, OnSuggestionSelected ) ); + m_xReplaceByChar->connect_toggled( LINK( this, HangulHanjaConversionDialog, ClickByCharacterHdl ) ); + m_xHangulOnly->connect_toggled( LINK( this, HangulHanjaConversionDialog, OnConversionDirectionClicked ) ); + m_xHanjaOnly->connect_toggled( LINK( this, HangulHanjaConversionDialog, OnConversionDirectionClicked ) ); + m_xOptions->connect_clicked(LINK(this, HangulHanjaConversionDialog, OnOption)); + + // initial focus + FocusSuggestion( ); + + // initial control values + m_xSimpleConversion->set_active(true); + + m_xSuggestions->SetHelpIds(); + } + + HangulHanjaConversionDialog::~HangulHanjaConversionDialog() + { + } + + void HangulHanjaConversionDialog::FillSuggestions( const css::uno::Sequence< OUString >& _rSuggestions ) + { + m_xSuggestions->Clear(); + for ( auto const & suggestion : _rSuggestions ) + m_xSuggestions->InsertEntry( suggestion ); + + // select the first suggestion, and fill in the suggestion edit field + OUString sFirstSuggestion; + if ( m_xSuggestions->GetEntryCount() ) + { + sFirstSuggestion = m_xSuggestions->GetEntry( 0 ); + m_xSuggestions->SelectEntryPos( 0 ); + } + m_xWordInput->set_text( sFirstSuggestion ); + m_xWordInput->save_value(); + OnSuggestionModified( *m_xWordInput ); + } + + void HangulHanjaConversionDialog::SetOptionsChangedHdl(const Link& rHdl) + { + m_aOptionsChangedLink = rHdl; + } + + void HangulHanjaConversionDialog::SetIgnoreHdl(const Link& rHdl) + { + m_xIgnore->connect_clicked(rHdl); + } + + void HangulHanjaConversionDialog::SetIgnoreAllHdl(const Link& rHdl) + { + m_xIgnoreAll->connect_clicked(rHdl); + } + + void HangulHanjaConversionDialog::SetChangeHdl(const Link& rHdl ) + { + m_xReplace->connect_clicked(rHdl); + } + + void HangulHanjaConversionDialog::SetChangeAllHdl(const Link& rHdl) + { + m_xReplaceAll->connect_clicked(rHdl); + } + + void HangulHanjaConversionDialog::SetFindHdl(const Link& rHdl) + { + m_xFind->connect_clicked(rHdl); + } + + void HangulHanjaConversionDialog::SetConversionFormatChangedHdl( const Link& rHdl ) + { + m_xSimpleConversion->connect_clicked( rHdl ); + m_xHangulBracketed->connect_clicked( rHdl ); + m_xHanjaBracketed->connect_clicked( rHdl ); + m_xHanjaAbove->connect_clicked( rHdl ); + m_xHanjaBelow->connect_clicked( rHdl ); + m_xHangulAbove->connect_clicked( rHdl ); + m_xHangulBelow->connect_clicked( rHdl ); + } + + void HangulHanjaConversionDialog::SetClickByCharacterHdl( const Link& _rHdl ) + { + m_aClickByCharacterLink = _rHdl; + } + + IMPL_LINK_NOARG( HangulHanjaConversionDialog, OnSuggestionSelected, SuggestionDisplay&, void ) + { + m_xWordInput->set_text(m_xSuggestions->GetSelectedEntry()); + OnSuggestionModified( *m_xWordInput ); + } + + IMPL_LINK_NOARG( HangulHanjaConversionDialog, OnSuggestionModified, weld::Entry&, void ) + { + m_xFind->set_sensitive(m_xWordInput->get_value_changed_from_saved()); + + bool bSameLen = m_xWordInput->get_text().getLength() == m_xOriginalWord->get_label().getLength(); + m_xReplace->set_sensitive( m_bDocumentMode && bSameLen ); + m_xReplaceAll->set_sensitive( m_bDocumentMode && bSameLen ); + } + + IMPL_LINK(HangulHanjaConversionDialog, ClickByCharacterHdl, weld::ToggleButton&, rBox, void) + { + m_aClickByCharacterLink.Call(rBox); + bool bByCharacter = rBox.get_active(); + m_xSuggestions->DisplayListBox( !bByCharacter ); + } + + IMPL_LINK(HangulHanjaConversionDialog, OnConversionDirectionClicked, weld::ToggleButton&, rBox, void) + { + weld::CheckButton* pOtherBox = nullptr; + if (&rBox == m_xHangulOnly.get()) + pOtherBox = m_xHanjaOnly.get(); + else + pOtherBox = m_xHangulOnly.get(); + bool bBoxChecked = rBox.get_active(); + if (bBoxChecked) + pOtherBox->set_active(false); + pOtherBox->set_sensitive(!bBoxChecked); + } + + IMPL_LINK_NOARG(HangulHanjaConversionDialog, OnOption, weld::Button&, void) + { + HangulHanjaOptionsDialog aOptDlg(m_xDialog.get()); + aOptDlg.run(); + m_aOptionsChangedLink.Call( nullptr ); + } + + OUString HangulHanjaConversionDialog::GetCurrentString( ) const + { + return m_xOriginalWord->get_label(); + } + + void HangulHanjaConversionDialog::FocusSuggestion( ) + { + m_xWordInput->grab_focus(); + } + + void HangulHanjaConversionDialog::SetCurrentString( const OUString& _rNewString, + const Sequence< OUString >& _rSuggestions, bool _bOriginatesFromDocument ) + { + m_xOriginalWord->set_label(_rNewString); + + bool bOldDocumentMode = m_bDocumentMode; + m_bDocumentMode = _bOriginatesFromDocument; // before FillSuggestions! + FillSuggestions( _rSuggestions ); + + m_xIgnoreAll->set_sensitive( m_bDocumentMode ); + + // switch the def button depending if we're working for document text + if (bOldDocumentMode == m_bDocumentMode) + return; + + weld::Widget* pOldDefButton = nullptr; + weld::Widget* pNewDefButton = nullptr; + if (m_bDocumentMode) + { + pOldDefButton = m_xFind.get(); + pNewDefButton = m_xReplace.get(); + } + else + { + pOldDefButton = m_xReplace.get(); + pNewDefButton = m_xFind.get(); + } + + pOldDefButton->set_has_default(false); + pNewDefButton->set_has_default(true); + } + + OUString HangulHanjaConversionDialog::GetCurrentSuggestion( ) const + { + return m_xWordInput->get_text(); + } + + void HangulHanjaConversionDialog::SetByCharacter( bool _bByCharacter ) + { + m_xReplaceByChar->set_active( _bByCharacter ); + m_xSuggestions->DisplayListBox( !_bByCharacter ); + } + + void HangulHanjaConversionDialog::SetConversionDirectionState( + bool _bTryBothDirections, + HHC::ConversionDirection ePrimaryConversionDirection ) + { + // default state: try both direction + m_xHangulOnly->set_active( false ); + m_xHangulOnly->set_sensitive(true); + m_xHanjaOnly->set_active( false ); + m_xHanjaOnly->set_sensitive(true); + + if (!_bTryBothDirections) + { + weld::CheckButton* pBox = ePrimaryConversionDirection == HHC::eHangulToHanja ? + m_xHangulOnly.get() : m_xHanjaOnly.get(); + pBox->set_active(true); + OnConversionDirectionClicked(*pBox); + } + } + + bool HangulHanjaConversionDialog::GetUseBothDirections( ) const + { + return !m_xHangulOnly->get_active() && !m_xHanjaOnly->get_active(); + } + + HHC::ConversionDirection HangulHanjaConversionDialog::GetDirection( + HHC::ConversionDirection eDefaultDirection ) const + { + HHC::ConversionDirection eDirection = eDefaultDirection; + if (m_xHangulOnly->get_active() && !m_xHanjaOnly->get_active()) + eDirection = HHC::eHangulToHanja; + else if (!m_xHangulOnly->get_active() && m_xHanjaOnly->get_active()) + eDirection = HHC::eHanjaToHangul; + return eDirection; + } + + void HangulHanjaConversionDialog::SetConversionFormat( HHC::ConversionFormat _eType ) + { + switch ( _eType ) + { + case HHC::eSimpleConversion: m_xSimpleConversion->set_active(true); break; + case HHC::eHangulBracketed: m_xHangulBracketed->set_active(true); break; + case HHC::eHanjaBracketed: m_xHanjaBracketed->set_active(true); break; + case HHC::eRubyHanjaAbove: m_xHanjaAbove->set_active(true); break; + case HHC::eRubyHanjaBelow: m_xHanjaBelow->set_active(true); break; + case HHC::eRubyHangulAbove: m_xHangulAbove->set_active(true); break; + case HHC::eRubyHangulBelow: m_xHangulBelow->set_active(true); break; + default: + OSL_FAIL( "HangulHanjaConversionDialog::SetConversionFormat: unknown type!" ); + } + } + + HHC::ConversionFormat HangulHanjaConversionDialog::GetConversionFormat( ) const + { + if ( m_xSimpleConversion->get_active() ) + return HHC::eSimpleConversion; + if ( m_xHangulBracketed->get_active() ) + return HHC::eHangulBracketed; + if ( m_xHanjaBracketed->get_active() ) + return HHC::eHanjaBracketed; + if ( m_xHanjaAbove->get_active() ) + return HHC::eRubyHanjaAbove; + if ( m_xHanjaBelow->get_active() ) + return HHC::eRubyHanjaBelow; + if ( m_xHangulAbove->get_active() ) + return HHC::eRubyHangulAbove; + if ( m_xHangulBelow->get_active() ) + return HHC::eRubyHangulBelow; + + OSL_FAIL( "HangulHanjaConversionDialog::GetConversionFormat: no radio checked?" ); + return HHC::eSimpleConversion; + } + + void HangulHanjaConversionDialog::EnableRubySupport( bool bVal ) + { + m_xHanjaAbove->set_sensitive( bVal ); + m_xHanjaBelow->set_sensitive( bVal ); + m_xHangulAbove->set_sensitive( bVal ); + m_xHangulBelow->set_sensitive( bVal ); + } + + void HangulHanjaOptionsDialog::Init() + { + if( !m_xConversionDictionaryList.is() ) + { + m_xConversionDictionaryList = ConversionDictionaryList::create( ::comphelper::getProcessComponentContext() ); + } + + m_aDictList.clear(); + m_xDictsLB->clear(); + + Reference< XNameContainer > xNameCont = m_xConversionDictionaryList->getDictionaryContainer(); + if( xNameCont.is() ) + { + Sequence< OUString > aDictNames( xNameCont->getElementNames() ); + + const OUString* pDic = aDictNames.getConstArray(); + sal_Int32 nCount = aDictNames.getLength(); + + sal_Int32 i; + for( i = 0 ; i < nCount ; ++i ) + { + Any aAny( xNameCont->getByName( pDic[ i ] ) ); + Reference< XConversionDictionary > xDic; + if( ( aAny >>= xDic ) && xDic.is() ) + { + if( LANGUAGE_KOREAN == LanguageTag( xDic->getLocale() ).getLanguageType() ) + { + m_aDictList.push_back( xDic ); + AddDict( xDic->getName(), xDic->isActive() ); + } + } + } + } + if (m_xDictsLB->n_children()) + m_xDictsLB->select(0); + } + + IMPL_LINK_NOARG(HangulHanjaOptionsDialog, OkHdl, weld::Button&, void) + { + sal_uInt32 nCnt = m_aDictList.size(); + sal_uInt32 n = 0; + sal_uInt32 nActiveDics = 0; + Sequence< OUString > aActiveDics; + + aActiveDics.realloc( nCnt ); + OUString* pActActiveDic = aActiveDics.getArray(); + + while( nCnt ) + { + Reference< XConversionDictionary > xDict = m_aDictList[ n ]; + + DBG_ASSERT( xDict.is(), "-HangulHanjaOptionsDialog::OkHdl(): someone is evaporated..." ); + + bool bActive = m_xDictsLB->get_toggle(n, 0) == TRISTATE_TRUE; + xDict->setActive( bActive ); + Reference< util::XFlushable > xFlush( xDict, uno::UNO_QUERY ); + if( xFlush.is() ) + xFlush->flush(); + + if( bActive ) + { + pActActiveDic[ nActiveDics ] = xDict->getName(); + ++nActiveDics; + } + + ++n; + --nCnt; + } + + // save configuration + aActiveDics.realloc( nActiveDics ); + Any aTmp; + SvtLinguConfig aLngCfg; + aTmp <<= aActiveDics; + aLngCfg.SetProperty( UPH_ACTIVE_CONVERSION_DICTIONARIES, aTmp ); + + aTmp <<= m_xIgnorepostCB->get_active(); + aLngCfg.SetProperty( UPH_IS_IGNORE_POST_POSITIONAL_WORD, aTmp ); + + aTmp <<= m_xShowrecentlyfirstCB->get_active(); + aLngCfg.SetProperty( UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST, aTmp ); + + aTmp <<= m_xAutoreplaceuniqueCB->get_active(); + aLngCfg.SetProperty( UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES, aTmp ); + + m_xDialog->response(RET_OK); + } + + IMPL_LINK_NOARG(HangulHanjaOptionsDialog, DictsLB_SelectHdl, weld::TreeView&, void) + { + bool bSel = m_xDictsLB->get_selected_index() != -1; + + m_xEditPB->set_sensitive(bSel); + m_xDeletePB->set_sensitive(bSel); + } + + IMPL_LINK_NOARG(HangulHanjaOptionsDialog, NewDictHdl, weld::Button&, void) + { + OUString aName; + HangulHanjaNewDictDialog aNewDlg(m_xDialog.get()); + aNewDlg.run(); + if (!aNewDlg.GetName(aName)) + return; + + if( !m_xConversionDictionaryList.is() ) + return; + + try + { + Reference< XConversionDictionary > xDic = + m_xConversionDictionaryList->addNewDictionary( aName, LanguageTag::convertToLocale( LANGUAGE_KOREAN ), ConversionDictionaryType::HANGUL_HANJA ); + + if( xDic.is() ) + { + //adapt local caches: + m_aDictList.push_back( xDic ); + AddDict( xDic->getName(), xDic->isActive() ); + } + } + catch( const ElementExistException& ) + { + } + catch( const NoSupportException& ) + { + } + } + + IMPL_LINK_NOARG(HangulHanjaOptionsDialog, EditDictHdl, weld::Button&, void) + { + int nEntry = m_xDictsLB->get_selected_index(); + DBG_ASSERT(nEntry != -1, "+HangulHanjaEditDictDialog::EditDictHdl(): call of edit should not be possible with no selection!"); + if (nEntry != -1) + { + HangulHanjaEditDictDialog aEdDlg(m_xDialog.get(), m_aDictList, nEntry); + aEdDlg.run(); + } + } + + IMPL_LINK_NOARG(HangulHanjaOptionsDialog, DeleteDictHdl, weld::Button&, void) + { + int nSelPos = m_xDictsLB->get_selected_index(); + if (nSelPos == -1) + return; + + Reference< XConversionDictionary > xDic( m_aDictList[ nSelPos ] ); + if( !(m_xConversionDictionaryList.is() && xDic.is()) ) + return; + + Reference< XNameContainer > xNameCont = m_xConversionDictionaryList->getDictionaryContainer(); + if( !xNameCont.is() ) + return; + + try + { + xNameCont->removeByName( xDic->getName() ); + + //adapt local caches: + m_aDictList.erase(m_aDictList.begin()+nSelPos ); + m_xDictsLB->remove(nSelPos); + } + catch( const ElementExistException& ) + { + } + catch( const NoSupportException& ) + { + } + } + + HangulHanjaOptionsDialog::HangulHanjaOptionsDialog(weld::Window* pParent) + : GenericDialogController(pParent, "cui/ui/hangulhanjaoptdialog.ui", "HangulHanjaOptDialog") + , m_xDictsLB(m_xBuilder->weld_tree_view("dicts")) + , m_xIgnorepostCB(m_xBuilder->weld_check_button("ignorepost")) + , m_xShowrecentlyfirstCB(m_xBuilder->weld_check_button("showrecentfirst")) + , m_xAutoreplaceuniqueCB(m_xBuilder->weld_check_button("autoreplaceunique")) + , m_xNewPB(m_xBuilder->weld_button("new")) + , m_xEditPB(m_xBuilder->weld_button("edit")) + , m_xDeletePB(m_xBuilder->weld_button("delete")) + , m_xOkPB(m_xBuilder->weld_button("ok")) + { + m_xDictsLB->set_size_request(m_xDictsLB->get_approximate_digit_width() * 32, + m_xDictsLB->get_height_rows(5)); + + std::vector aWidths; + aWidths.push_back(m_xDictsLB->get_checkbox_column_width()); + m_xDictsLB->set_column_fixed_widths(aWidths); + + m_xDictsLB->connect_changed( LINK( this, HangulHanjaOptionsDialog, DictsLB_SelectHdl ) ); + + m_xOkPB->connect_clicked( LINK( this, HangulHanjaOptionsDialog, OkHdl ) ); + m_xNewPB->connect_clicked( LINK( this, HangulHanjaOptionsDialog, NewDictHdl ) ); + m_xEditPB->connect_clicked( LINK( this, HangulHanjaOptionsDialog, EditDictHdl ) ); + m_xDeletePB->connect_clicked( LINK( this, HangulHanjaOptionsDialog, DeleteDictHdl ) ); + + SvtLinguConfig aLngCfg; + Any aTmp; + bool bVal = bool(); + aTmp = aLngCfg.GetProperty( UPH_IS_IGNORE_POST_POSITIONAL_WORD ); + if( aTmp >>= bVal ) + m_xIgnorepostCB->set_active( bVal ); + + aTmp = aLngCfg.GetProperty( UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST ); + if( aTmp >>= bVal ) + m_xShowrecentlyfirstCB->set_active( bVal ); + + aTmp = aLngCfg.GetProperty( UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES ); + if( aTmp >>= bVal ) + m_xAutoreplaceuniqueCB->set_active( bVal ); + + Init(); + } + + HangulHanjaOptionsDialog::~HangulHanjaOptionsDialog() + { + } + + void HangulHanjaOptionsDialog::AddDict(const OUString& rName, bool bChecked) + { + m_xDictsLB->append(); + int nRow = m_xDictsLB->n_children() - 1; + m_xDictsLB->set_toggle(nRow, bChecked ? TRISTATE_TRUE : TRISTATE_FALSE, 0); + m_xDictsLB->set_text(nRow, rName, 1); + m_xDictsLB->set_id(nRow, rName); + } + + IMPL_LINK_NOARG(HangulHanjaNewDictDialog, OKHdl, weld::Button&, void) + { + OUString aName(comphelper::string::stripEnd(m_xDictNameED->get_text(), ' ')); + + m_bEntered = !aName.isEmpty(); + if (m_bEntered) + m_xDictNameED->set_text(aName); // do this in case of trailing chars have been deleted + + m_xDialog->response(RET_OK); + } + + IMPL_LINK_NOARG(HangulHanjaNewDictDialog, ModifyHdl, weld::Entry&, void) + { + OUString aName(comphelper::string::stripEnd(m_xDictNameED->get_text(), ' ')); + + m_xOkBtn->set_sensitive(!aName.isEmpty()); + } + + HangulHanjaNewDictDialog::HangulHanjaNewDictDialog(weld::Window* pParent) + : GenericDialogController(pParent, "cui/ui/hangulhanjaadddialog.ui", "HangulHanjaAddDialog") + , m_bEntered(false) + , m_xOkBtn(m_xBuilder->weld_button("ok")) + , m_xDictNameED(m_xBuilder->weld_entry("entry")) + { + m_xOkBtn->connect_clicked( LINK( this, HangulHanjaNewDictDialog, OKHdl ) ); + m_xDictNameED->connect_changed( LINK( this, HangulHanjaNewDictDialog, ModifyHdl ) ); + } + + HangulHanjaNewDictDialog::~HangulHanjaNewDictDialog() + { + } + + bool HangulHanjaNewDictDialog::GetName( OUString& _rRetName ) const + { + if( m_bEntered ) + _rRetName = comphelper::string::stripEnd(m_xDictNameED->get_text(), ' '); + + return m_bEntered; + } + + class SuggestionList + { + private: + protected: + std::vector m_vElements; + sal_uInt16 m_nNumOfEntries; + // index of the internal iterator, used for First() and Next() methods + sal_uInt16 m_nAct; + + const OUString* Next_(); + public: + SuggestionList(); + ~SuggestionList(); + + void Set( const OUString& _rElement, sal_uInt16 _nNumOfElement ); + void Reset( sal_uInt16 _nNumOfElement ); + const OUString & Get( sal_uInt16 _nNumOfElement ) const; + void Clear(); + + const OUString* First(); + const OUString* Next(); + + sal_uInt16 GetCount() const { return m_nNumOfEntries; } + }; + + SuggestionList::SuggestionList() : + m_vElements(MAXNUM_SUGGESTIONS) + { + m_nAct = m_nNumOfEntries = 0; + } + + SuggestionList::~SuggestionList() + { + Clear(); + } + + void SuggestionList::Set( const OUString& _rElement, sal_uInt16 _nNumOfElement ) + { + m_vElements[_nNumOfElement] = _rElement; + ++m_nNumOfEntries; + } + + void SuggestionList::Reset( sal_uInt16 _nNumOfElement ) + { + m_vElements[_nNumOfElement].clear(); + --m_nNumOfEntries; + } + + const OUString& SuggestionList::Get( sal_uInt16 _nNumOfElement ) const + { + return m_vElements[_nNumOfElement]; + } + + void SuggestionList::Clear() + { + if( m_nNumOfEntries ) + { + for (auto & vElement : m_vElements) + vElement.clear(); + m_nNumOfEntries = m_nAct = 0; + } + } + + const OUString* SuggestionList::Next_() + { + while( m_nAct < m_vElements.size() ) + { + auto & s = m_vElements[ m_nAct ]; + if (!s.isEmpty()) + return &s; + ++m_nAct; + } + + return nullptr; + } + + const OUString* SuggestionList::First() + { + m_nAct = 0; + return Next_(); + } + + const OUString* SuggestionList::Next() + { + const OUString* pRet; + + if( m_nAct < m_nNumOfEntries ) + { + ++m_nAct; + pRet = Next_(); + } + else + pRet = nullptr; + + return pRet; + } + + + bool SuggestionEdit::ShouldScroll( bool _bUp ) const + { + bool bRet = false; + + if( _bUp ) + { + if( !m_pPrev ) + bRet = m_pScrollBar->vadjustment_get_value() > m_pScrollBar->vadjustment_get_lower(); + } + else + { + if( !m_pNext ) + bRet = m_pScrollBar->vadjustment_get_value() < ( m_pScrollBar->vadjustment_get_upper() - 4 ); + } + + return bRet; + } + + void SuggestionEdit::DoJump( bool _bUp ) + { + m_pScrollBar->vadjustment_set_value( m_pScrollBar->vadjustment_get_value() + ( _bUp? -1 : 1 ) ); + m_pParent->UpdateScrollbar(); + } + + SuggestionEdit::SuggestionEdit(std::unique_ptr xEntry, HangulHanjaEditDictDialog* pParent) + : m_pParent(pParent) + , m_pPrev(nullptr) + , m_pNext(nullptr) + , m_pScrollBar(nullptr) + , m_xEntry(std::move(xEntry)) + { + m_xEntry->connect_key_press(LINK(this, SuggestionEdit, KeyInputHdl)); + } + + IMPL_LINK(SuggestionEdit, KeyInputHdl, const KeyEvent&, rKEvt, bool) + { + bool bHandled = false; + + const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode(); + sal_uInt16 nMod = rKeyCode.GetModifier(); + sal_uInt16 nCode = rKeyCode.GetCode(); + if( nCode == KEY_TAB && ( !nMod || KEY_SHIFT == nMod ) ) + { + bool bUp = KEY_SHIFT == nMod; + if( ShouldScroll( bUp ) ) + { + DoJump( bUp ); + m_xEntry->select_region(0, -1); + // Tab-travel doesn't really happen, so emulate it by setting a selection manually + bHandled = true; + } + } + else if( KEY_UP == nCode || KEY_DOWN == nCode ) + { + bool bUp = KEY_UP == nCode; + if( ShouldScroll( bUp ) ) + { + DoJump( bUp ); + bHandled = true; + } + else if( bUp ) + { + if( m_pPrev ) + { + m_pPrev->grab_focus(); + bHandled = true; + } + } + else if( m_pNext ) + { + m_pNext->grab_focus(); + bHandled = true; + } + } + + return bHandled; + } + + void SuggestionEdit::init(weld::ScrolledWindow* pScrollBar, SuggestionEdit* pPrev, SuggestionEdit* pNext) + { + m_pScrollBar = pScrollBar; + m_pPrev = pPrev; + m_pNext = pNext; + } + + namespace + { + bool GetConversions( const Reference< XConversionDictionary >& _xDict, + const OUString& _rOrg, + Sequence< OUString >& _rEntries ) + { + bool bRet = false; + if( _xDict.is() && !_rOrg.isEmpty() ) + { + try + { + _rEntries = _xDict->getConversions( _rOrg, + 0, + _rOrg.getLength(), + ConversionDirection_FROM_LEFT, + css::i18n::TextConversionOption::NONE ); + bRet = _rEntries.hasElements(); + } + catch( const IllegalArgumentException& ) + { + } + } + + return bRet; + } + } + + IMPL_LINK_NOARG( HangulHanjaEditDictDialog, ScrollHdl, weld::ScrolledWindow&, void ) + { + UpdateScrollbar(); + } + + IMPL_LINK_NOARG( HangulHanjaEditDictDialog, OriginalModifyHdl, weld::ComboBox&, void ) + { + m_bModifiedOriginal = true; + m_aOriginal = comphelper::string::stripEnd( m_xOriginalLB->get_active_text(), ' ' ); + + UpdateSuggestions(); + UpdateButtonStates(); + } + + IMPL_LINK( HangulHanjaEditDictDialog, EditModifyHdl1, weld::Entry&, rEdit, void ) + { + EditModify( &rEdit, 0 ); + } + + IMPL_LINK( HangulHanjaEditDictDialog, EditModifyHdl2, weld::Entry&, rEdit, void ) + { + EditModify( &rEdit, 1 ); + } + + IMPL_LINK( HangulHanjaEditDictDialog, EditModifyHdl3, weld::Entry&, rEdit, void ) + { + EditModify( &rEdit, 2 ); + } + + IMPL_LINK( HangulHanjaEditDictDialog, EditModifyHdl4, weld::Entry&, rEdit, void ) + { + EditModify( &rEdit, 3 ); + } + + IMPL_LINK_NOARG( HangulHanjaEditDictDialog, BookLBSelectHdl, weld::ComboBox&, void ) + { + InitEditDictDialog( m_xBookLB->get_active() ); + } + + IMPL_LINK_NOARG( HangulHanjaEditDictDialog, NewPBPushHdl, weld::Button&, void ) + { + DBG_ASSERT( m_xSuggestions, "-HangulHanjaEditDictDialog::NewPBPushHdl(): no suggestions... search in hell..." ); + Reference< XConversionDictionary > xDict = m_rDictList[ m_nCurrentDict ]; + if( xDict.is() && m_xSuggestions ) + { + //delete old entry + bool bRemovedSomething = DeleteEntryFromDictionary( xDict ); + + OUString aLeft( m_aOriginal ); + const OUString* pRight = m_xSuggestions->First(); + bool bAddedSomething = false; + while( pRight ) + { + try + { + //add new entry + xDict->addEntry( aLeft, *pRight ); + bAddedSomething = true; + } + catch( const IllegalArgumentException& ) + { + } + catch( const ElementExistException& ) + { + } + + pRight = m_xSuggestions->Next(); + } + + if( bAddedSomething || bRemovedSomething ) + InitEditDictDialog( m_nCurrentDict ); + } + else + { + SAL_INFO( "cui.dialogs", "dictionary faded away..." ); + } + } + + bool HangulHanjaEditDictDialog::DeleteEntryFromDictionary( const Reference< XConversionDictionary >& xDict ) + { + bool bRemovedSomething = false; + if( xDict.is() ) + { + OUString aOrg( m_aOriginal ); + Sequence< OUString > aEntries; + GetConversions( xDict, m_aOriginal, aEntries ); + + sal_uInt32 n = aEntries.getLength(); + OUString* pEntry = aEntries.getArray(); + while( n ) + { + try + { + xDict->removeEntry( aOrg, *pEntry ); + bRemovedSomething = true; + } + catch( const NoSuchElementException& ) + { // can not be... + } + + ++pEntry; + --n; + } + } + return bRemovedSomething; + } + + IMPL_LINK_NOARG( HangulHanjaEditDictDialog, DeletePBPushHdl, weld::Button&, void ) + { + if( DeleteEntryFromDictionary( m_rDictList[ m_nCurrentDict ] ) ) + { + m_aOriginal.clear(); + m_bModifiedOriginal = true; + InitEditDictDialog( m_nCurrentDict ); + } + } + + void HangulHanjaEditDictDialog::InitEditDictDialog( sal_uInt32 nSelDict ) + { + if( m_xSuggestions ) + m_xSuggestions->Clear(); + + if( m_nCurrentDict != nSelDict ) + { + m_nCurrentDict = nSelDict; + m_aOriginal.clear(); + m_bModifiedOriginal = true; + } + + UpdateOriginalLB(); + + m_xOriginalLB->set_entry_text( !m_aOriginal.isEmpty() ? m_aOriginal : m_aEditHintText); + m_xOriginalLB->select_entry_region(0, -1); + m_xOriginalLB->grab_focus(); + + UpdateSuggestions(); + UpdateButtonStates(); + } + + void HangulHanjaEditDictDialog::UpdateOriginalLB() + { + m_xOriginalLB->clear(); + Reference< XConversionDictionary > xDict = m_rDictList[ m_nCurrentDict ]; + if( xDict.is() ) + { + Sequence< OUString > aEntries = xDict->getConversionEntries( ConversionDirection_FROM_LEFT ); + sal_uInt32 n = aEntries.getLength(); + OUString* pEntry = aEntries.getArray(); + while( n ) + { + m_xOriginalLB->append_text( *pEntry ); + + ++pEntry; + --n; + } + } + else + { + SAL_INFO( "cui.dialogs", "dictionary faded away..." ); + } + } + + void HangulHanjaEditDictDialog::UpdateButtonStates() + { + bool bHaveValidOriginalString = !m_aOriginal.isEmpty() && m_aOriginal != m_aEditHintText; + bool bNew = bHaveValidOriginalString && m_xSuggestions && m_xSuggestions->GetCount() > 0; + bNew = bNew && ( m_bModifiedSuggestions || m_bModifiedOriginal ); + + m_xNewPB->set_sensitive( bNew ); + m_xDeletePB->set_sensitive(!m_bModifiedOriginal && bHaveValidOriginalString); + } + + void HangulHanjaEditDictDialog::UpdateSuggestions() + { + Sequence< OUString > aEntries; + bool bFound = GetConversions( m_rDictList[ m_nCurrentDict ], m_aOriginal, aEntries ); + if( bFound ) + { + m_bModifiedOriginal = false; + + if( m_xSuggestions ) + m_xSuggestions->Clear(); + + //fill found entries into boxes + sal_uInt32 nCnt = aEntries.getLength(); + if( nCnt ) + { + if( !m_xSuggestions ) + m_xSuggestions.reset(new SuggestionList); + + const OUString* pSugg = aEntries.getConstArray(); + sal_uInt32 n = 0; + while( nCnt ) + { + m_xSuggestions->Set( pSugg[ n ], sal_uInt16( n ) ); + ++n; + --nCnt; + } + } + m_bModifiedSuggestions = false; + } + + m_xScrollSB->vadjustment_set_value( 0 ); + UpdateScrollbar(); // will force edits to be filled new + } + + void HangulHanjaEditDictDialog::SetEditText(SuggestionEdit& rEdit, sal_uInt16 nEntryNum) + { + OUString aStr; + if( m_xSuggestions ) + { + aStr = m_xSuggestions->Get(nEntryNum); + } + + rEdit.set_text(aStr); + } + + void HangulHanjaEditDictDialog::EditModify(const weld::Entry* pEdit, sal_uInt8 _nEntryOffset) + { + m_bModifiedSuggestions = true; + + OUString aTxt( pEdit->get_text() ); + sal_uInt16 nEntryNum = m_nTopPos + _nEntryOffset; + if( aTxt.isEmpty() ) + { + //reset suggestion + if( m_xSuggestions ) + m_xSuggestions->Reset( nEntryNum ); + } + else + { + //set suggestion + if( !m_xSuggestions ) + m_xSuggestions.reset(new SuggestionList); + m_xSuggestions->Set( aTxt, nEntryNum ); + } + + UpdateButtonStates(); + } + + HangulHanjaEditDictDialog::HangulHanjaEditDictDialog(weld::Window* pParent, HHDictList& _rDictList, sal_uInt32 nSelDict) + : GenericDialogController(pParent, "cui/ui/hangulhanjaeditdictdialog.ui", "HangulHanjaEditDictDialog") + , m_aEditHintText ( CuiResId(RID_SVXSTR_EDITHINT) ) + , m_rDictList ( _rDictList ) + , m_nCurrentDict ( 0xFFFFFFFF ) + , m_nTopPos ( 0 ) + , m_bModifiedSuggestions ( false ) + , m_bModifiedOriginal ( false ) + , m_xBookLB(m_xBuilder->weld_combo_box("book")) + , m_xOriginalLB(m_xBuilder->weld_combo_box("original")) + , m_xEdit1(new SuggestionEdit(m_xBuilder->weld_entry("edit1"), this)) + , m_xEdit2(new SuggestionEdit(m_xBuilder->weld_entry("edit2"), this)) + , m_xEdit3(new SuggestionEdit(m_xBuilder->weld_entry("edit3"), this)) + , m_xEdit4(new SuggestionEdit(m_xBuilder->weld_entry("edit4"), this)) + , m_xContents(m_xBuilder->weld_widget("box")) + , m_xScrollSB(m_xBuilder->weld_scrolled_window("scrollbar")) + , m_xNewPB(m_xBuilder->weld_button("new")) + , m_xDeletePB(m_xBuilder->weld_button("delete")) + { + m_xScrollSB->set_user_managed_scrolling(); + + Size aSize(m_xContents->get_preferred_size()); + m_xScrollSB->set_size_request(-1, aSize.Height()); + + m_xEdit1->init( m_xScrollSB.get(), nullptr, m_xEdit2.get() ); + m_xEdit2->init( m_xScrollSB.get(), m_xEdit1.get(), m_xEdit3.get() ); + m_xEdit3->init( m_xScrollSB.get(), m_xEdit2.get(), m_xEdit4.get() ); + m_xEdit4->init( m_xScrollSB.get(), m_xEdit3.get(), nullptr ); + + m_xOriginalLB->connect_changed( LINK( this, HangulHanjaEditDictDialog, OriginalModifyHdl ) ); + + m_xNewPB->connect_clicked( LINK( this, HangulHanjaEditDictDialog, NewPBPushHdl ) ); + m_xNewPB->set_sensitive( false ); + + m_xDeletePB->connect_clicked( LINK( this, HangulHanjaEditDictDialog, DeletePBPushHdl ) ); + m_xDeletePB->set_sensitive( false ); + + static_assert(MAXNUM_SUGGESTIONS >= 5, "number of suggestions should not under-run the value of 5"); + + // 4 here, because we have 4 edits / page + m_xScrollSB->vadjustment_configure(0, 0, MAXNUM_SUGGESTIONS, 1, 4, 4); + m_xScrollSB->connect_vadjustment_changed(LINK(this, HangulHanjaEditDictDialog, ScrollHdl)); + + m_xEdit1->connect_changed( LINK( this, HangulHanjaEditDictDialog, EditModifyHdl1 ) ); + m_xEdit2->connect_changed( LINK( this, HangulHanjaEditDictDialog, EditModifyHdl2 ) ); + m_xEdit3->connect_changed( LINK( this, HangulHanjaEditDictDialog, EditModifyHdl3 ) ); + m_xEdit4->connect_changed( LINK( this, HangulHanjaEditDictDialog, EditModifyHdl4 ) ); + + m_xBookLB->connect_changed( LINK( this, HangulHanjaEditDictDialog, BookLBSelectHdl ) ); + sal_uInt32 nDictCnt = m_rDictList.size(); + for( sal_uInt32 n = 0 ; n < nDictCnt ; ++n ) + { + Reference< XConversionDictionary > xDic( m_rDictList[n] ); + OUString aName; + if( xDic.is() ) + aName = xDic->getName(); + m_xBookLB->append_text( aName ); + } + m_xBookLB->set_active(nSelDict); + + InitEditDictDialog(nSelDict); + } + + HangulHanjaEditDictDialog::~HangulHanjaEditDictDialog() + { + } + + void HangulHanjaEditDictDialog::UpdateScrollbar() + { + sal_uInt16 nPos = m_xScrollSB->vadjustment_get_value(); + m_nTopPos = nPos; + + SetEditText( *m_xEdit1, nPos++ ); + SetEditText( *m_xEdit2, nPos++ ); + SetEditText( *m_xEdit3, nPos++ ); + SetEditText( *m_xEdit4, nPos ); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/hldocntp.cxx b/cui/source/dialogs/hldocntp.cxx new file mode 100644 index 000000000..50d7131ad --- /dev/null +++ b/cui/source/dialogs/hldocntp.cxx @@ -0,0 +1,479 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star::uno; + +using namespace ::com::sun::star; + +/************************************************************************* +|* +|* Data-struct for documenttypes in listbox +|* +|************************************************************************/ + +namespace { + +struct DocumentTypeData +{ + OUString aStrURL; + OUString aStrExt; + DocumentTypeData (const OUString& aURL, const OUString& aExt) : aStrURL(aURL), aStrExt(aExt) + {} +}; + +} + +bool SvxHyperlinkNewDocTp::ImplGetURLObject( const OUString& rPath, const OUString& rBase, INetURLObject& aURLObject ) const +{ + bool bIsValidURL = !rPath.isEmpty(); + if ( bIsValidURL ) + { + aURLObject.SetURL( rPath ); + if ( aURLObject.GetProtocol() == INetProtocol::NotValid ) // test if the source is already a valid url + { // if not we have to create a url from a physical file name + bool wasAbs; + INetURLObject base(rBase); + base.setFinalSlash(); + aURLObject = base.smartRel2Abs( + rPath, wasAbs, true, INetURLObject::EncodeMechanism::All, + RTL_TEXTENCODING_UTF8, true); + } + bIsValidURL = aURLObject.GetProtocol() != INetProtocol::NotValid; + if ( bIsValidURL ) + { + OUString aBase( aURLObject.getName( INetURLObject::LAST_SEGMENT, false ) ); + if ( aBase.isEmpty() || ( aBase[0] == '.' ) ) + bIsValidURL = false; + } + if ( bIsValidURL ) + { + sal_Int32 nPos = m_xLbDocTypes->get_selected_index(); + if (nPos != -1) + aURLObject.SetExtension(reinterpret_cast(m_xLbDocTypes->get_id(nPos).toInt64())->aStrExt); + } + + } + return bIsValidURL; +} + +/************************************************************************* +|* +|* Constructor / Destructor +|* +|************************************************************************/ + +SvxHyperlinkNewDocTp::SvxHyperlinkNewDocTp(weld::Container* pParent, SvxHpLinkDlg* pDlg, const SfxItemSet* pItemSet) + : SvxHyperlinkTabPageBase(pParent, pDlg, "cui/ui/hyperlinknewdocpage.ui", "HyperlinkNewDocPage", pItemSet) + , m_xRbtEditNow(xBuilder->weld_radio_button("editnow")) + , m_xRbtEditLater(xBuilder->weld_radio_button("editlater")) + , m_xCbbPath(new SvxHyperURLBox(xBuilder->weld_combo_box("path"))) + , m_xBtCreate(xBuilder->weld_button("create")) + , m_xLbDocTypes(xBuilder->weld_tree_view("types")) +{ + m_xCbbPath->SetSmartProtocol(INetProtocol::File); + m_xLbDocTypes->set_size_request(-1, m_xLbDocTypes->get_height_rows(5)); + + InitStdControls(); + + SetExchangeSupport (); + + m_xCbbPath->show(); + m_xCbbPath->SetBaseURL(SvtPathOptions().GetWorkPath()); + + // set defaults + m_xRbtEditNow->set_active(true); + + m_xBtCreate->connect_clicked(LINK(this, SvxHyperlinkNewDocTp, ClickNewHdl_Impl)); + + FillDocumentList (); +} + +SvxHyperlinkNewDocTp::~SvxHyperlinkNewDocTp () +{ + if (m_xLbDocTypes) + { + for (sal_Int32 n = 0, nEntryCount = m_xLbDocTypes->n_children(); n < nEntryCount; ++n) + delete reinterpret_cast(m_xLbDocTypes->get_id(n).toInt64()); + m_xLbDocTypes = nullptr; + } +} + +/************************************************************************* +|* +|* Fill the all dialog-controls except controls in groupbox "more..." +|* +|************************************************************************/ + + +void SvxHyperlinkNewDocTp::FillDlgFields(const OUString& /*rStrURL*/) +{ +} + +void SvxHyperlinkNewDocTp::FillDocumentList() +{ + weld::WaitObject aWaitObj(mpDialog->getDialog()); + + uno::Sequence< uno::Sequence< beans::PropertyValue > > + aDynamicMenuEntries( SvtDynamicMenuOptions().GetMenu( EDynamicMenuType::NewMenu ) ); + + sal_uInt32 i, nCount = aDynamicMenuEntries.getLength(); + for ( i = 0; i < nCount; i++ ) + { + const uno::Sequence< beans::PropertyValue >& rDynamicMenuEntry = aDynamicMenuEntries[ i ]; + + OUString aDocumentUrl, aTitle; + + for ( const beans::PropertyValue& e : rDynamicMenuEntry ) + { + if ( e.Name == DYNAMICMENU_PROPERTYNAME_URL ) + e.Value >>= aDocumentUrl; + else if ( e.Name == DYNAMICMENU_PROPERTYNAME_TITLE ) + e.Value >>= aTitle; + } + //#i96822# business cards, labels and database should not be inserted here + if( aDocumentUrl == "private:factory/swriter?slot=21051" || + aDocumentUrl == "private:factory/swriter?slot=21052" || + aDocumentUrl == "private:factory/sdatabase?Interactive" ) + continue; + + // Insert into listbox + if ( !aDocumentUrl.isEmpty() ) + { + if ( aDocumentUrl == "private:factory/simpress?slot=6686" ) // SJ: #106216# do not start + aDocumentUrl = "private:factory/simpress"; // the AutoPilot for impress + + // insert private-url and default-extension as user-data + std::shared_ptr pFilter = SfxFilter::GetDefaultFilterFromFactory( aDocumentUrl ); + if ( pFilter ) + { + // insert doc-name and image + OUString aTitleName = aTitle.replaceFirst( "~", "" ); + + OUString aStrDefExt(pFilter->GetDefaultExtension()); + DocumentTypeData *pTypeData = new DocumentTypeData(aDocumentUrl, aStrDefExt.copy(2)); + OUString sId(OUString::number(reinterpret_cast(pTypeData))); + m_xLbDocTypes->append(sId, aTitleName); + } + } + } + m_xLbDocTypes->select(0); +} + +/************************************************************************* +|* +|* retrieve and prepare data from dialog-fields +|* +|************************************************************************/ + +void SvxHyperlinkNewDocTp::GetCurentItemData ( OUString& rStrURL, OUString& aStrName, + OUString& aStrIntName, OUString& aStrFrame, + SvxLinkInsertMode& eMode ) +{ + // get data from dialog-controls + rStrURL = m_xCbbPath->get_active_text(); + INetURLObject aURL; + if ( ImplGetURLObject( rStrURL, m_xCbbPath->GetBaseURL(), aURL ) ) + { + rStrURL = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ); + } + + GetDataFromCommonFields( aStrName, aStrIntName, aStrFrame, eMode ); +} + +/************************************************************************* +|* +|* static method to create Tabpage +|* +|************************************************************************/ + +std::unique_ptr SvxHyperlinkNewDocTp::Create(weld::Container* pWindow, SvxHpLinkDlg* pDlg, const SfxItemSet* pItemSet) +{ + return std::make_unique(pWindow, pDlg, pItemSet); +} + +/************************************************************************* +|* +|* Set initial focus +|* +|************************************************************************/ +void SvxHyperlinkNewDocTp::SetInitFocus() +{ + m_xCbbPath->grab_focus(); +} + +/************************************************************************* +|* +|* Ask page whether an insert is possible +|* +\************************************************************************/ +bool SvxHyperlinkNewDocTp::AskApply() +{ + INetURLObject aINetURLObject; + bool bRet = ImplGetURLObject(m_xCbbPath->get_active_text(), m_xCbbPath->GetBaseURL(), aINetURLObject); + if ( !bRet ) + { + std::unique_ptr xWarn(Application::CreateMessageDialog(mpDialog->getDialog(), + VclMessageType::Warning, VclButtonsType::Ok, + CuiResId(RID_SVXSTR_HYPDLG_NOVALIDFILENAME))); + xWarn->run(); + } + return bRet; +} + +namespace +{ + struct ExecuteInfo + { + bool bRbtEditLater; + bool bRbtEditNow; + INetURLObject aURL; + OUString aStrDocName; + // current document + css::uno::Reference xFrame; + SfxDispatcher* pDispatcher; + }; +} + +IMPL_STATIC_LINK(SvxHyperlinkNewDocTp, DispatchDocument, void*, p, void) +{ + std::unique_ptr xExecuteInfo(static_cast(p)); + if (!xExecuteInfo->xFrame.is()) + return; + try + { + //if it throws dispatcher is invalid + css::uno::Reference(xExecuteInfo->xFrame->getContainerWindow(), css::uno::UNO_QUERY_THROW); + + SfxViewFrame *pViewFrame = nullptr; + + // create items + SfxStringItem aName( SID_FILE_NAME, xExecuteInfo->aStrDocName ); + SfxStringItem aReferer( SID_REFERER, "private:user" ); + SfxStringItem aFrame( SID_TARGETNAME, "_blank"); + + OUString aStrFlags('S'); + if (xExecuteInfo->bRbtEditLater) + { + aStrFlags += "H"; + } + SfxStringItem aFlags (SID_OPTIONS, aStrFlags); + + // open url + const SfxPoolItem* pReturn = xExecuteInfo->pDispatcher->ExecuteList( + SID_OPENDOC, SfxCallMode::SYNCHRON, + { &aName, &aFlags, &aFrame, &aReferer }); + + // save new doc + const SfxViewFrameItem *pItem = dynamic_cast( pReturn ); // SJ: pReturn is NULL if the Hyperlink + if ( pItem ) // creation is cancelled #106216# + { + pViewFrame = pItem->GetFrame(); + if (pViewFrame) + { + SfxStringItem aNewName( SID_FILE_NAME, xExecuteInfo->aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); + SfxUnoFrameItem aDocFrame( SID_FILLFRAME, pViewFrame->GetFrame().GetFrameInterface() ); + fprintf(stderr, "is there a frame int %p\n", pViewFrame->GetFrame().GetFrameInterface().get() ); + pViewFrame->GetDispatcher()->ExecuteList( + SID_SAVEASDOC, SfxCallMode::SYNCHRON, + { &aNewName }, { &aDocFrame }); + } + } + + if (xExecuteInfo->bRbtEditNow) + { + css::uno::Reference xWindow(xExecuteInfo->xFrame->getContainerWindow(), css::uno::UNO_QUERY); + if (xWindow.is()) //will be false if the frame was exited while the document was loading (e.g. we waited for warning dialogs) + xWindow->toFront(); + } + + if (pViewFrame && xExecuteInfo->bRbtEditLater) + { + SfxObjectShell* pObjShell = pViewFrame->GetObjectShell(); + pObjShell->DoClose(); + } + } + catch (...) + { + } +} + +/************************************************************************* +|* +|* Any action to do after apply-button is pressed +|* +\************************************************************************/ +void SvxHyperlinkNewDocTp::DoApply() +{ + weld::WaitObject aWait(mpDialog->getDialog()); + + // get data from dialog-controls + OUString aStrNewName = m_xCbbPath->get_active_text(); + + if ( aStrNewName.isEmpty() ) + aStrNewName = maStrInitURL; + + // create a real URL-String + INetURLObject aURL; + if ( !ImplGetURLObject( aStrNewName, m_xCbbPath->GetBaseURL(), aURL ) ) + return; + + // create Document + aStrNewName = aURL.GetURLPath( INetURLObject::DecodeMechanism::NONE ); + bool bCreate = true; + try + { + // check if file exists, warn before we overwrite it + std::unique_ptr pIStm = ::utl::UcbStreamHelper::CreateStream( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), StreamMode::READ ); + + bool bOk = pIStm && ( pIStm->GetError() == ERRCODE_NONE); + + pIStm.reset(); + + if( bOk ) + { + std::unique_ptr xWarn(Application::CreateMessageDialog(mpDialog->getDialog(), + VclMessageType::Warning, VclButtonsType::YesNo, + CuiResId(RID_SVXSTR_HYPERDLG_QUERYOVERWRITE))); + bCreate = xWarn->run() == RET_YES; + } + } + catch (const uno::Exception&) + { + } + + if (!(bCreate && !aStrNewName.isEmpty())) + return; + + ExecuteInfo* pExecuteInfo = new ExecuteInfo; + + pExecuteInfo->bRbtEditLater = m_xRbtEditLater->get_active(); + pExecuteInfo->bRbtEditNow = m_xRbtEditNow->get_active(); + // get private-url + sal_Int32 nPos = m_xLbDocTypes->get_selected_index(); + if (nPos == -1) + nPos = 0; + pExecuteInfo->aURL = aURL; + pExecuteInfo->aStrDocName = reinterpret_cast(m_xLbDocTypes->get_id(nPos).toInt64())->aStrURL; + + // current document + pExecuteInfo->xFrame = GetDispatcher()->GetFrame()->GetFrame().GetFrameInterface(); + pExecuteInfo->pDispatcher = GetDispatcher(); + + Application::PostUserEvent(LINK(nullptr, SvxHyperlinkNewDocTp, DispatchDocument), pExecuteInfo); +} + +/************************************************************************* +|* +|* Click on imagebutton : new +|* +|************************************************************************/ +IMPL_LINK_NOARG(SvxHyperlinkNewDocTp, ClickNewHdl_Impl, weld::Button&, void) +{ + DisableClose( true ); + uno::Reference < XComponentContext > xContext( ::comphelper::getProcessComponentContext() ); + uno::Reference < XFolderPicker2 > xFolderPicker = FolderPicker::create(xContext); + + OUString aStrURL; + OUString aTempStrURL( m_xCbbPath->get_active_text() ); + osl::FileBase::getFileURLFromSystemPath( aTempStrURL, aStrURL ); + + OUString aStrPath = aStrURL; + bool bZeroPath = aStrPath.isEmpty(); + bool bHandleFileName = bZeroPath; // when path has length of 0, then the rest should always be handled + // as file name, otherwise we do not yet know + + if( bZeroPath ) + aStrPath = SvtPathOptions().GetWorkPath(); + else if( !::utl::UCBContentHelper::IsFolder( aStrURL ) ) + bHandleFileName = true; + + xFolderPicker->setDisplayDirectory( aStrPath ); + sal_Int16 nResult = xFolderPicker->execute(); + DisableClose( false ); + if( ExecutableDialogResults::OK != nResult ) + return; + + char const sSlash[] = "/"; + + INetURLObject aURL( aStrURL, INetProtocol::File ); + OUString aStrName; + if( bHandleFileName ) + aStrName = bZeroPath? aTempStrURL : aURL.getName(); + + m_xCbbPath->SetBaseURL( xFolderPicker->getDirectory() ); + OUString aStrTmp( xFolderPicker->getDirectory() ); + + if( aStrTmp[ aStrTmp.getLength() - 1 ] != sSlash[0] ) + aStrTmp += sSlash; + + // append old file name + if( bHandleFileName ) + aStrTmp += aStrName; + + INetURLObject aNewURL( aStrTmp ); + + if (!aStrName.isEmpty() && !aNewURL.getExtension().isEmpty() && + m_xLbDocTypes->get_selected_index() != -1) + { + // get private-url + const sal_Int32 nPos = m_xLbDocTypes->get_selected_index(); + aNewURL.setExtension(reinterpret_cast(m_xLbDocTypes->get_id(nPos).toInt64())->aStrExt); + } + + if( aNewURL.GetProtocol() == INetProtocol::File ) + { + osl::FileBase::getSystemPathFromFileURL(aNewURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), aStrTmp); + } + else + { + aStrTmp = aNewURL.GetMainURL( INetURLObject::DecodeMechanism::Unambiguous ); + } + + m_xCbbPath->set_entry_text( aStrTmp ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/hldoctp.cxx b/cui/source/dialogs/hldoctp.cxx new file mode 100644 index 000000000..8bfe89465 --- /dev/null +++ b/cui/source/dialogs/hldoctp.cxx @@ -0,0 +1,318 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include + +#include +#include + +char const sHash[] = "#"; +char const sFileScheme[] = INET_FILE_SCHEME; + +/************************************************************************* +|* +|* Constructor / Destructor +|* +|************************************************************************/ + +SvxHyperlinkDocTp::SvxHyperlinkDocTp(weld::Container* pParent, SvxHpLinkDlg* pDlg, const SfxItemSet* pItemSet) + : SvxHyperlinkTabPageBase(pParent, pDlg, "cui/ui/hyperlinkdocpage.ui", "HyperlinkDocPage", pItemSet) + , m_xCbbPath(new SvxHyperURLBox(xBuilder->weld_combo_box("path"))) + , m_xBtFileopen(xBuilder->weld_button("fileopen")) + , m_xEdTarget(xBuilder->weld_entry("target")) + , m_xFtFullURL(xBuilder->weld_label("url")) + , m_xBtBrowse(xBuilder->weld_button("browse")) + , m_bMarkWndOpen(false) +{ + m_xCbbPath->SetSmartProtocol(INetProtocol::File); + + InitStdControls(); + + m_xCbbPath->show(); + m_xCbbPath->SetBaseURL(INET_FILE_SCHEME); + + SetExchangeSupport(); + + // set handlers + m_xBtFileopen->connect_clicked( LINK ( this, SvxHyperlinkDocTp, ClickFileopenHdl_Impl ) ); + m_xBtBrowse->connect_clicked( LINK ( this, SvxHyperlinkDocTp, ClickTargetHdl_Impl ) ); + m_xCbbPath->connect_changed( LINK ( this, SvxHyperlinkDocTp, ModifiedPathHdl_Impl ) ); + m_xEdTarget->connect_changed( LINK ( this, SvxHyperlinkDocTp, ModifiedTargetHdl_Impl ) ); + + m_xCbbPath->connect_focus_out( LINK ( this, SvxHyperlinkDocTp, LostFocusPathHdl_Impl ) ); + + maTimer.SetInvokeHandler ( LINK ( this, SvxHyperlinkDocTp, TimeoutHdl_Impl ) ); +} + +SvxHyperlinkDocTp::~SvxHyperlinkDocTp() +{ +} + +/************************************************************************* +|* +|* Fill all dialog-controls except controls in groupbox "more..." +|* +|************************************************************************/ +void SvxHyperlinkDocTp::FillDlgFields(const OUString& rStrURL) +{ + sal_Int32 nPos = rStrURL.indexOf(sHash); + // path + m_xCbbPath->set_entry_text( rStrURL.copy( 0, ( nPos == -1 ? rStrURL.getLength() : nPos ) ) ); + + // set target in document at editfield + OUString aStrMark; + if ( nPos != -1 && nPos < rStrURL.getLength()-1 ) + aStrMark = rStrURL.copy( nPos+1 ); + m_xEdTarget->set_text( aStrMark ); + + ModifiedPathHdl_Impl(*m_xCbbPath->getWidget()); +} + +/************************************************************************* +|* +|* retrieve current url-string +|* +|************************************************************************/ +OUString SvxHyperlinkDocTp::GetCurrentURL () const +{ + // get data from dialog-controls + OUString aStrURL; + OUString aStrPath( m_xCbbPath->get_active_text() ); + OUString aStrMark( m_xEdTarget->get_text() ); + + if ( !aStrPath.isEmpty() ) + { + INetURLObject aURL( aStrPath ); + if ( aURL.GetProtocol() != INetProtocol::NotValid ) // maybe the path is already a valid + aStrURL = aStrPath; // hyperlink, then we can use this path directly + else + { + osl::FileBase::getFileURLFromSystemPath( aStrPath, aStrURL ); + aStrURL = INetURLObject::decode(aStrURL, INetURLObject::DecodeMechanism::ToIUri, RTL_TEXTENCODING_UTF8); + } + + //#105788# always create a URL even if it is not valid + if( aStrURL.isEmpty() ) + aStrURL = aStrPath; + } + + if( !aStrMark.isEmpty() ) + { + aStrURL += sHash + aStrMark; + } + + return aStrURL; +} + +/************************************************************************* +|* +|* retrieve and prepare data from dialog-fields +|* +|************************************************************************/ +void SvxHyperlinkDocTp::GetCurentItemData ( OUString& rStrURL, OUString& aStrName, + OUString& aStrIntName, OUString& aStrFrame, + SvxLinkInsertMode& eMode ) +{ + // get data from standard-fields + rStrURL = GetCurrentURL(); + + if( rStrURL.equalsIgnoreAsciiCase( sFileScheme ) ) + rStrURL.clear(); + + GetDataFromCommonFields( aStrName, aStrIntName, aStrFrame, eMode ); +} + +/************************************************************************* +|* +|* static method to create Tabpage +|* +|************************************************************************/ +std::unique_ptr SvxHyperlinkDocTp::Create(weld::Container* pWindow, SvxHpLinkDlg* pDlg, const SfxItemSet* pItemSet) +{ + return std::make_unique(pWindow, pDlg, pItemSet); +} + +/************************************************************************* +|* +|* Set initial focus +|* +|************************************************************************/ +void SvxHyperlinkDocTp::SetInitFocus() +{ + m_xCbbPath->grab_focus(); +} + +/************************************************************************* +|* +|* Click on imagebutton : fileopen +|* +|************************************************************************/ +IMPL_LINK_NOARG(SvxHyperlinkDocTp, ClickFileopenHdl_Impl, weld::Button&, void) +{ + DisableClose( true ); + // Open Fileopen-Dialog + sfx2::FileDialogHelper aDlg( + css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE, FileDialogFlags::NONE, + mpDialog->getDialog() ); + OUString aOldURL( GetCurrentURL() ); + if( aOldURL.startsWithIgnoreAsciiCase( sFileScheme ) ) + { + OUString aPath; + osl::FileBase::getSystemPathFromFileURL(aOldURL, aPath); + aDlg.SetDisplayFolder( aPath ); + } + + ErrCode nError = aDlg.Execute(); + DisableClose( false ); + + if ( ERRCODE_NONE != nError ) + return; + + OUString aURL( aDlg.GetPath() ); + OUString aPath; + + osl::FileBase::getSystemPathFromFileURL(aURL, aPath); + + m_xCbbPath->SetBaseURL( aURL ); + m_xCbbPath->set_entry_text(aPath); + + if ( aOldURL != GetCurrentURL() ) + ModifiedPathHdl_Impl(*m_xCbbPath->getWidget()); +} + +/************************************************************************* +|* +|* Click on imagebutton : target +|* +|************************************************************************/ +IMPL_LINK_NOARG(SvxHyperlinkDocTp, ClickTargetHdl_Impl, weld::Button&, void) +{ + ShowMarkWnd(); + + if ( GetPathType ( maStrURL ) == EPathType::ExistsFile || + maStrURL.isEmpty() || + maStrURL.equalsIgnoreAsciiCase( sFileScheme ) || + maStrURL.startsWith( sHash ) ) + { + mxMarkWnd->SetError( LERR_NOERROR ); + + weld::WaitObject aWait(mpDialog->getDialog()); + + if ( maStrURL.equalsIgnoreAsciiCase( sFileScheme ) ) + mxMarkWnd->RefreshTree ( "" ); + else + mxMarkWnd->RefreshTree ( maStrURL ); + } + else + mxMarkWnd->SetError( LERR_DOCNOTOPEN ); +} + +/************************************************************************* +|* +|* Contents of combobox "Path" modified +|* +|************************************************************************/ +IMPL_LINK_NOARG(SvxHyperlinkDocTp, ModifiedPathHdl_Impl, weld::ComboBox&, void) +{ + maStrURL = GetCurrentURL(); + + maTimer.SetTimeout( 2500 ); + maTimer.Start(); + + m_xFtFullURL->set_label( maStrURL ); +} + +/************************************************************************* +|* +|* If path-field was modify, to browse the new doc after timeout +|* +|************************************************************************/ +IMPL_LINK_NOARG(SvxHyperlinkDocTp, TimeoutHdl_Impl, Timer *, void) +{ + if ( IsMarkWndVisible() && ( GetPathType( maStrURL )== EPathType::ExistsFile || + maStrURL.isEmpty() || + maStrURL.equalsIgnoreAsciiCase( sFileScheme ) ) ) + { + weld::WaitObject aWait(mpDialog->getDialog()); + + if ( maStrURL.equalsIgnoreAsciiCase( sFileScheme ) ) + mxMarkWnd->RefreshTree ( "" ); + else + mxMarkWnd->RefreshTree ( maStrURL ); + } +} + +/************************************************************************* +|* +|* Contents of editfield "Target" modified +|* +|************************************************************************/ +IMPL_LINK_NOARG(SvxHyperlinkDocTp, ModifiedTargetHdl_Impl, weld::Entry&, void) +{ + maStrURL = GetCurrentURL(); + + if (IsMarkWndVisible()) + mxMarkWnd->SelectEntry(m_xEdTarget->get_text()); + + m_xFtFullURL->set_label( maStrURL ); +} + +/************************************************************************* +|* +|* editfield "Target" lost focus +|* +|************************************************************************/ +IMPL_LINK_NOARG(SvxHyperlinkDocTp, LostFocusPathHdl_Impl, weld::Widget&, void) +{ + maStrURL = GetCurrentURL(); + + m_xFtFullURL->set_label( maStrURL ); +} + +/************************************************************************* +|* +|* Get String from Bookmark-Wnd +|* +|************************************************************************/ +void SvxHyperlinkDocTp::SetMarkStr ( const OUString& aStrMark ) +{ + m_xEdTarget->set_text(aStrMark); + + ModifiedTargetHdl_Impl ( *m_xEdTarget ); +} + +/************************************************************************* +|* +|* retrieve kind of pathstr +|* +|************************************************************************/ +SvxHyperlinkDocTp::EPathType SvxHyperlinkDocTp::GetPathType ( const OUString& rStrPath ) +{ + INetURLObject aURL( rStrPath, INetProtocol::File ); + + if( aURL.HasError() ) + return EPathType::Invalid; + else + return EPathType::ExistsFile; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/hlinettp.cxx b/cui/source/dialogs/hlinettp.cxx new file mode 100644 index 000000000..f2deeb9b3 --- /dev/null +++ b/cui/source/dialogs/hlinettp.cxx @@ -0,0 +1,393 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +#include +#include + +char const sAnonymous[] = "anonymous"; +char const sFTPScheme[] = INET_FTP_SCHEME; + +/************************************************************************* +|* +|* Constructor / Destructor +|* +|************************************************************************/ +SvxHyperlinkInternetTp::SvxHyperlinkInternetTp(weld::Container* pParent, + SvxHpLinkDlg* pDlg, + const SfxItemSet* pItemSet) + : SvxHyperlinkTabPageBase(pParent, pDlg, "cui/ui/hyperlinkinternetpage.ui", "HyperlinkInternetPage", + pItemSet) + , m_bMarkWndOpen(false) + , m_xRbtLinktypInternet(xBuilder->weld_radio_button("linktyp_internet")) + , m_xRbtLinktypFTP(xBuilder->weld_radio_button("linktyp_ftp")) + , m_xCbbTarget(new SvxHyperURLBox(xBuilder->weld_combo_box("target"))) + , m_xFtTarget(xBuilder->weld_label("target_label")) + , m_xFtLogin(xBuilder->weld_label("login_label")) + , m_xEdLogin(xBuilder->weld_entry("login")) + , m_xFtPassword(xBuilder->weld_label("password_label")) + , m_xEdPassword(xBuilder->weld_entry("password")) + , m_xCbAnonymous(xBuilder->weld_check_button("anonymous")) +{ + // gtk_size_group_set_ignore_hidden, "Measuring the size of hidden widgets + // ... they will report a size of 0 nowadays, and thus, their size will + // not affect the other size group members", which is unfortunate. So here + // before we hide the labels, take the size group width and set it as + // explicit preferred size on a label that won't be hidden + auto nLabelWidth = m_xFtTarget->get_preferred_size().Width(); + m_xFtTarget->set_size_request(nLabelWidth, -1); + + m_xCbbTarget->SetSmartProtocol(INetProtocol::Http); + + InitStdControls(); + + m_xCbbTarget->show(); + + SetExchangeSupport (); + + // set defaults + m_xRbtLinktypInternet->set_active(true); + + // set handlers + Link aLink( LINK ( this, SvxHyperlinkInternetTp, Click_SmartProtocol_Impl ) ); + m_xRbtLinktypInternet->connect_clicked( aLink ); + m_xRbtLinktypFTP->connect_clicked( aLink ); + m_xCbAnonymous->connect_clicked( LINK ( this, SvxHyperlinkInternetTp, ClickAnonymousHdl_Impl ) ); + m_xEdLogin->connect_changed( LINK ( this, SvxHyperlinkInternetTp, ModifiedLoginHdl_Impl ) ); + m_xCbbTarget->connect_focus_out( LINK ( this, SvxHyperlinkInternetTp, LostFocusTargetHdl_Impl ) ); + m_xCbbTarget->connect_changed( LINK ( this, SvxHyperlinkInternetTp, ModifiedTargetHdl_Impl ) ); + maTimer.SetInvokeHandler ( LINK ( this, SvxHyperlinkInternetTp, TimeoutHdl_Impl ) ); +} + +SvxHyperlinkInternetTp::~SvxHyperlinkInternetTp() +{ +} + +/************************************************************************* +|* +|* Fill the all dialog-controls except controls in groupbox "more..." +|* +|************************************************************************/ +void SvxHyperlinkInternetTp::FillDlgFields(const OUString& rStrURL) +{ + INetURLObject aURL(rStrURL); + OUString aStrScheme(GetSchemeFromURL(rStrURL)); + + // set additional controls for FTP: Username / Password + if (aStrScheme.startsWith(sFTPScheme)) + { + if ( aURL.GetUser().toAsciiLowerCase().startsWith( sAnonymous ) ) + setAnonymousFTPUser(); + else + setFTPUser(aURL.GetUser(), aURL.GetPass()); + + //do not show password and user in url + if(!aURL.GetUser().isEmpty() || !aURL.GetPass().isEmpty() ) + aURL.SetUserAndPass("", ""); + } + + // set URL-field + // Show the scheme, #72740 + if ( aURL.GetProtocol() != INetProtocol::NotValid ) + m_xCbbTarget->set_entry_text( aURL.GetMainURL( INetURLObject::DecodeMechanism::Unambiguous ) ); + else + m_xCbbTarget->set_entry_text(rStrURL); + + SetScheme(aStrScheme); +} + +void SvxHyperlinkInternetTp::setAnonymousFTPUser() +{ + m_xEdLogin->set_text(sAnonymous); + SvAddressParser aAddress(SvtUserOptions().GetEmail()); + m_xEdPassword->set_text(aAddress.Count() ? aAddress.GetEmailAddress(0) : OUString()); + + m_xFtLogin->set_sensitive(false); + m_xFtPassword->set_sensitive(false); + m_xEdLogin->set_sensitive(false); + m_xEdPassword->set_sensitive(false); + m_xCbAnonymous->set_active(true); +} + +void SvxHyperlinkInternetTp::setFTPUser(const OUString& rUser, const OUString& rPassword) +{ + m_xEdLogin->set_text(rUser); + m_xEdPassword->set_text(rPassword); + + m_xFtLogin->set_sensitive(true); + m_xFtPassword->set_sensitive(true); + m_xEdLogin->set_sensitive(true); + m_xEdPassword->set_sensitive(true); + m_xCbAnonymous->set_active(false); +} + +/************************************************************************* +|* +|* retrieve and prepare data from dialog-fields +|* +|************************************************************************/ + +void SvxHyperlinkInternetTp::GetCurentItemData ( OUString& rStrURL, OUString& aStrName, + OUString& aStrIntName, OUString& aStrFrame, + SvxLinkInsertMode& eMode ) +{ + rStrURL = CreateAbsoluteURL(); + GetDataFromCommonFields( aStrName, aStrIntName, aStrFrame, eMode ); +} + +OUString SvxHyperlinkInternetTp::CreateAbsoluteURL() const +{ + // erase leading and trailing whitespaces + OUString aStrURL(m_xCbbTarget->get_active_text().trim()); + + INetURLObject aURL(aStrURL); + + if( aURL.GetProtocol() == INetProtocol::NotValid ) + { + aURL.SetSmartProtocol( GetSmartProtocolFromButtons() ); + aURL.SetSmartURL(aStrURL); + } + + // username and password for ftp-url + if( aURL.GetProtocol() == INetProtocol::Ftp && !m_xEdLogin->get_text().isEmpty() ) + aURL.SetUserAndPass ( m_xEdLogin->get_text(), m_xEdPassword->get_text() ); + + if ( aURL.GetProtocol() != INetProtocol::NotValid ) + return aURL.GetMainURL( INetURLObject::DecodeMechanism::ToIUri ); + else //#105788# always create a URL even if it is not valid + return aStrURL; +} + +/************************************************************************* +|* +|* static method to create Tabpage +|* +|************************************************************************/ + +std::unique_ptr SvxHyperlinkInternetTp::Create(weld::Container* pWindow, SvxHpLinkDlg* pDlg, const SfxItemSet* pItemSet) +{ + return std::make_unique(pWindow, pDlg, pItemSet); +} + +/************************************************************************* +|* +|* Set initial focus +|* +|************************************************************************/ +void SvxHyperlinkInternetTp::SetInitFocus() +{ + m_xCbbTarget->grab_focus(); +} + +/************************************************************************* +|* +|* Contents of editfield "Target" modified +|* +|************************************************************************/ +IMPL_LINK_NOARG(SvxHyperlinkInternetTp, ModifiedTargetHdl_Impl, weld::ComboBox&, void) +{ + OUString aScheme = GetSchemeFromURL( m_xCbbTarget->get_active_text() ); + if( !aScheme.isEmpty() ) + SetScheme( aScheme ); + + // start timer + maTimer.SetTimeout( 2500 ); + maTimer.Start(); +} + +/************************************************************************* +|* +|* If target-field was modify, to browse the new doc after timeout +|* +|************************************************************************/ +IMPL_LINK_NOARG(SvxHyperlinkInternetTp, TimeoutHdl_Impl, Timer *, void) +{ + RefreshMarkWindow(); +} + +/************************************************************************* +|* +|* Contents of editfield "Login" modified +|* +|************************************************************************/ +IMPL_LINK_NOARG(SvxHyperlinkInternetTp, ModifiedLoginHdl_Impl, weld::Entry&, void) +{ + OUString aStrLogin ( m_xEdLogin->get_text() ); + if ( aStrLogin.equalsIgnoreAsciiCase( sAnonymous ) ) + { + m_xCbAnonymous->set_active(true); + ClickAnonymousHdl_Impl(*m_xCbAnonymous); + } +} + +void SvxHyperlinkInternetTp::SetScheme(const OUString& rScheme) +{ + //if rScheme is empty or unknown the default behaviour is like it where HTTP + bool bFTP = rScheme.startsWith(sFTPScheme); + bool bInternet = !bFTP; + + //update protocol button selection: + m_xRbtLinktypFTP->set_active(bFTP); + m_xRbtLinktypInternet->set_active(bInternet); + + //update target: + RemoveImproperProtocol(rScheme); + m_xCbbTarget->SetSmartProtocol( GetSmartProtocolFromButtons() ); + + //show/hide special fields for FTP: + m_xFtLogin->set_visible( bFTP ); + m_xFtPassword->set_visible( bFTP ); + m_xEdLogin->set_visible( bFTP ); + m_xEdPassword->set_visible( bFTP ); + m_xCbAnonymous->set_visible( bFTP ); + + //update 'link target in document'-window and opening-button + if (rScheme.startsWith(INET_HTTP_SCHEME) || rScheme.isEmpty()) + { + if ( m_bMarkWndOpen ) + ShowMarkWnd (); + } + else + { + //disable for https and ftp + if ( m_bMarkWndOpen ) + HideMarkWnd (); + } +} + +/************************************************************************* +|* +|* Remove protocol if it does not fit to the current button selection +|* +|************************************************************************/ + +void SvxHyperlinkInternetTp::RemoveImproperProtocol(const OUString& aProperScheme) +{ + OUString aStrURL ( m_xCbbTarget->get_active_text() ); + if ( !aStrURL.isEmpty() ) + { + OUString aStrScheme(GetSchemeFromURL(aStrURL)); + if ( !aStrScheme.isEmpty() && aStrScheme != aProperScheme ) + { + aStrURL = aStrURL.copy( aStrScheme.getLength() ); + m_xCbbTarget->set_entry_text( aStrURL ); + } + } +} + +OUString SvxHyperlinkInternetTp::GetSchemeFromButtons() const +{ + if( m_xRbtLinktypFTP->get_active() ) + return INET_FTP_SCHEME; + return INET_HTTP_SCHEME; +} + +INetProtocol SvxHyperlinkInternetTp::GetSmartProtocolFromButtons() const +{ + if( m_xRbtLinktypFTP->get_active() ) + { + return INetProtocol::Ftp; + } + return INetProtocol::Http; +} + +/************************************************************************* +|* +|* Click on Radiobutton : Internet or FTP +|* +|************************************************************************/ +IMPL_LINK_NOARG(SvxHyperlinkInternetTp, Click_SmartProtocol_Impl, weld::Button&, void) +{ + OUString aScheme = GetSchemeFromButtons(); + SetScheme(aScheme); +} + +/************************************************************************* +|* +|* Click on Checkbox : Anonymous user +|* +|************************************************************************/ +IMPL_LINK_NOARG(SvxHyperlinkInternetTp, ClickAnonymousHdl_Impl, weld::Button&, void) +{ + // disable login-editfields if checked + if ( m_xCbAnonymous->get_active() ) + { + if ( m_xEdLogin->get_text().toAsciiLowerCase().startsWith( sAnonymous ) ) + { + maStrOldUser.clear(); + maStrOldPassword.clear(); + } + else + { + maStrOldUser = m_xEdLogin->get_text(); + maStrOldPassword = m_xEdPassword->get_text(); + } + + setAnonymousFTPUser(); + } + else + setFTPUser(maStrOldUser, maStrOldPassword); +} + +/************************************************************************* +|* +|* Combobox Target lost the focus +|* +|************************************************************************/ +IMPL_LINK_NOARG(SvxHyperlinkInternetTp, LostFocusTargetHdl_Impl, weld::Widget&, void) +{ + RefreshMarkWindow(); +} + +void SvxHyperlinkInternetTp::RefreshMarkWindow() +{ + if (m_xRbtLinktypInternet->get_active() && IsMarkWndVisible()) + { + weld::WaitObject aWait(mpDialog->getDialog()); + OUString aStrURL( CreateAbsoluteURL() ); + if ( !aStrURL.isEmpty() ) + mxMarkWnd->RefreshTree ( aStrURL ); + else + mxMarkWnd->SetError( LERR_DOCNOTOPEN ); + } +} + +/************************************************************************* +|* +|* Get String from Bookmark-Wnd +|* +|************************************************************************/ +void SvxHyperlinkInternetTp::SetMarkStr ( const OUString& aStrMark ) +{ + OUString aStrURL(m_xCbbTarget->get_active_text()); + + const sal_Unicode sUHash = '#'; + sal_Int32 nPos = aStrURL.lastIndexOf( sUHash ); + + if( nPos != -1 ) + aStrURL = aStrURL.copy(0, nPos); + + aStrURL += OUStringChar(sUHash) + aStrMark; + + m_xCbbTarget->set_entry_text(aStrURL); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/hlmailtp.cxx b/cui/source/dialogs/hlmailtp.cxx new file mode 100644 index 000000000..4e2e111fc --- /dev/null +++ b/cui/source/dialogs/hlmailtp.cxx @@ -0,0 +1,228 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include +#include + +#include + +#include + +using namespace ::com::sun::star; + +/************************************************************************* +|* +|* Constructor / Destructor +|* +|************************************************************************/ +SvxHyperlinkMailTp::SvxHyperlinkMailTp(weld::Container* pParent, SvxHpLinkDlg* pDlg, const SfxItemSet* pItemSet) + : SvxHyperlinkTabPageBase(pParent, pDlg, "cui/ui/hyperlinkmailpage.ui", "HyperlinkMailPage", pItemSet) + , m_xCbbReceiver(new SvxHyperURLBox(xBuilder->weld_combo_box("receiver"))) + , m_xBtAdrBook(xBuilder->weld_button("adressbook")) + , m_xFtSubject(xBuilder->weld_label("subject_label")) + , m_xEdSubject(xBuilder->weld_entry("subject")) +{ + m_xCbbReceiver->SetSmartProtocol(INetProtocol::Mailto); + + InitStdControls(); + + m_xCbbReceiver->show(); + + SetExchangeSupport (); + + // set handlers + m_xBtAdrBook->connect_clicked( LINK ( this, SvxHyperlinkMailTp, ClickAdrBookHdl_Impl ) ); + m_xCbbReceiver->connect_changed( LINK ( this, SvxHyperlinkMailTp, ModifiedReceiverHdl_Impl) ); + + if ( !SvtModuleOptions().IsModuleInstalled( SvtModuleOptions::EModule::DATABASE ) || + comphelper::LibreOfficeKit::isActive() ) + m_xBtAdrBook->hide(); +} + +SvxHyperlinkMailTp::~SvxHyperlinkMailTp() +{ +} + +/************************************************************************* +|* +|* Fill the all dialog-controls except controls in groupbox "more..." +|* +|************************************************************************/ + +void SvxHyperlinkMailTp::FillDlgFields(const OUString& rStrURL) +{ + OUString aStrScheme = GetSchemeFromURL(rStrURL); + + // set URL-field and additional controls + OUString aStrURLc (rStrURL); + // set additional controls for EMail: + if ( aStrScheme.startsWith( INET_MAILTO_SCHEME ) ) + { + // Find mail-subject + OUString aStrSubject, aStrTmp( aStrURLc ); + + sal_Int32 nPos = aStrTmp.toAsciiLowerCase().indexOf( "subject" ); + + if ( nPos != -1 ) + nPos = aStrTmp.indexOf( '=', nPos ); + + if ( nPos != -1 ) + aStrSubject = aStrURLc.copy( nPos+1 ); + + nPos = aStrURLc.indexOf( '?' ); + + if ( nPos != -1 ) + aStrURLc = aStrURLc.copy( 0, nPos ); + + m_xEdSubject->set_text( aStrSubject ); + } + else + { + m_xEdSubject->set_text(""); + } + + m_xCbbReceiver->set_entry_text(aStrURLc); + + SetScheme( aStrScheme ); +} + +/************************************************************************* +|* +|* retrieve and prepare data from dialog-fields +|* +|************************************************************************/ +void SvxHyperlinkMailTp::GetCurentItemData ( OUString& rStrURL, OUString& aStrName, + OUString& aStrIntName, OUString& aStrFrame, + SvxLinkInsertMode& eMode ) +{ + rStrURL = CreateAbsoluteURL(); + GetDataFromCommonFields( aStrName, aStrIntName, aStrFrame, eMode ); +} + +OUString SvxHyperlinkMailTp::CreateAbsoluteURL() const +{ + OUString aStrURL = m_xCbbReceiver->get_active_text(); + INetURLObject aURL(aStrURL); + + if( aURL.GetProtocol() == INetProtocol::NotValid ) + { + aURL.SetSmartProtocol( INetProtocol::Mailto ); + aURL.SetSmartURL(aStrURL); + } + + // subject for EMail-url + if( aURL.GetProtocol() == INetProtocol::Mailto ) + { + if (!m_xEdSubject->get_text().isEmpty()) + { + OUString aQuery = "subject=" + m_xEdSubject->get_text(); + aURL.SetParam(aQuery); + } + } + + if ( aURL.GetProtocol() != INetProtocol::NotValid ) + return aURL.GetMainURL( INetURLObject::DecodeMechanism::WithCharset ); + else //#105788# always create a URL even if it is not valid + return aStrURL; +} + +/************************************************************************* +|* +|* static method to create Tabpage +|* +|************************************************************************/ + +std::unique_ptr SvxHyperlinkMailTp::Create(weld::Container* pWindow, SvxHpLinkDlg* pDlg, const SfxItemSet* pItemSet) +{ + return std::make_unique(pWindow, pDlg, pItemSet); +} + +/************************************************************************* +|* +|* Set initial focus +|* +|************************************************************************/ +void SvxHyperlinkMailTp::SetInitFocus() +{ + m_xCbbReceiver->grab_focus(); +} + +/************************************************************************* +|************************************************************************/ +void SvxHyperlinkMailTp::SetScheme(const OUString& rScheme) +{ + //update target: + RemoveImproperProtocol(rScheme); + m_xCbbReceiver->SetSmartProtocol( INetProtocol::Mailto ); + + //show/hide special fields for MAIL: + m_xBtAdrBook->set_sensitive(true); + m_xEdSubject->set_sensitive(true); +} + +/************************************************************************* +|* +|* Remove protocol if it does not fit to the current button selection +|* +|************************************************************************/ +void SvxHyperlinkMailTp::RemoveImproperProtocol(const OUString& aProperScheme) +{ + OUString aStrURL(m_xCbbReceiver->get_active_text()); + if ( !aStrURL.isEmpty() ) + { + OUString aStrScheme = GetSchemeFromURL( aStrURL ); + if ( !aStrScheme.isEmpty() && aStrScheme != aProperScheme ) + { + aStrURL = aStrURL.copy( aStrScheme.getLength() ); + m_xCbbReceiver->set_entry_text(aStrURL); + } + } +} + +/************************************************************************* +|* +|* Contents of editfield "receiver" modified +|* +|************************************************************************/ +IMPL_LINK_NOARG(SvxHyperlinkMailTp, ModifiedReceiverHdl_Impl, weld::ComboBox&, void) +{ + OUString aScheme = GetSchemeFromURL( m_xCbbReceiver->get_active_text() ); + if(!aScheme.isEmpty()) + SetScheme( aScheme ); +} + +/************************************************************************* +|* +|* Click on imagebutton : addressbook +|* +|************************************************************************/ +IMPL_STATIC_LINK_NOARG(SvxHyperlinkMailTp, ClickAdrBookHdl_Impl, weld::Button&, void) +{ + SfxViewFrame* pViewFrame = SfxViewFrame::Current(); + if( pViewFrame ) + { + SfxItemPool &rPool = pViewFrame->GetPool(); + SfxRequest aReq(SID_VIEW_DATA_SOURCE_BROWSER, SfxCallMode::SLOT, rPool); + pViewFrame->ExecuteSlot( aReq, true ); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/hlmarkwn.cxx b/cui/source/dialogs/hlmarkwn.cxx new file mode 100644 index 000000000..3b985b2b0 --- /dev/null +++ b/cui/source/dialogs/hlmarkwn.cxx @@ -0,0 +1,473 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include + +// UNO-Stuff +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +using namespace ::com::sun::star; + +namespace { + +// Userdata-struct for tree-entries +struct TargetData +{ + OUString aUStrLinkname; + bool bIsTarget; + + TargetData (const OUString& aUStrLName, bool bTarget) + : bIsTarget(bTarget) + { + if (bIsTarget) + aUStrLinkname = aUStrLName; + } +}; + +} + +//*** Window-Class *** +// Constructor / Destructor +SvxHlinkDlgMarkWnd::SvxHlinkDlgMarkWnd(weld::Window* pParentDialog, SvxHyperlinkTabPageBase *pParentPage) + : GenericDialogController(pParentDialog, "cui/ui/hyperlinkmarkdialog.ui", "HyperlinkMark") + , mpParent(pParentPage) + , mnError(LERR_NOERROR) + , mxBtApply(m_xBuilder->weld_button("ok")) + , mxBtClose(m_xBuilder->weld_button("close")) + , mxLbTree(m_xBuilder->weld_tree_view("TreeListBox")) + , mxError(m_xBuilder->weld_label("error")) +{ + mxLbTree->set_size_request(mxLbTree->get_approximate_digit_width() * 25, + mxLbTree->get_height_rows(12)); + mxBtApply->connect_clicked( LINK ( this, SvxHlinkDlgMarkWnd, ClickApplyHdl_Impl ) ); + mxBtClose->connect_clicked( LINK ( this, SvxHlinkDlgMarkWnd, ClickCloseHdl_Impl ) ); + mxLbTree->connect_row_activated( LINK ( this, SvxHlinkDlgMarkWnd, DoubleClickApplyHdl_Impl ) ); +} + +SvxHlinkDlgMarkWnd::~SvxHlinkDlgMarkWnd() +{ + ClearTree(); +} + +void SvxHlinkDlgMarkWnd::ErrorChanged() +{ + if (mnError == LERR_NOENTRIES) + { + OUString aStrMessage = CuiResId( RID_SVXSTR_HYPDLG_ERR_LERR_NOENTRIES ); + mxError->set_label(aStrMessage); + mxError->show(); + mxLbTree->hide(); + } + else if (mnError == LERR_DOCNOTOPEN) + { + OUString aStrMessage = CuiResId( RID_SVXSTR_HYPDLG_ERR_LERR_DOCNOTOPEN ); + mxError->set_label(aStrMessage); + mxError->show(); + mxLbTree->hide(); + } + else + { + mxLbTree->show(); + mxError->hide(); + } +} + +// Set an errorstatus +sal_uInt16 SvxHlinkDlgMarkWnd::SetError( sal_uInt16 nError) +{ + sal_uInt16 nOldError = mnError; + mnError = nError; + + if( mnError != LERR_NOERROR ) + ClearTree(); + + ErrorChanged(); + + return nOldError; +} + +// Move window +void SvxHlinkDlgMarkWnd::MoveTo(const Point& rNewPos) +{ + m_xDialog->window_move(rNewPos.X(), rNewPos.Y()); +} + +namespace +{ + void SelectPath(weld::TreeIter* pEntry, weld::TreeView& rLbTree, + std::deque &rLastSelectedPath) + { + OUString sTitle(rLastSelectedPath.front()); + rLastSelectedPath.pop_front(); + if (sTitle.isEmpty()) + return; + while (pEntry) + { + if (sTitle == rLbTree.get_text(*pEntry)) + { + rLbTree.select(*pEntry); + rLbTree.scroll_to_row(*pEntry); + if (!rLastSelectedPath.empty()) + { + rLbTree.expand_row(*pEntry); + if (!rLbTree.iter_children(*pEntry)) + pEntry = nullptr; + SelectPath(pEntry, rLbTree, rLastSelectedPath); + } + break; + } + if (!rLbTree.iter_next_sibling(*pEntry)) + pEntry = nullptr; + } + } +} + +#define TG_SETTING_MANAGER "TargetInDocument" +#define TG_SETTING_LASTMARK "LastSelectedMark" +#define TG_SETTING_LASTPATH "LastSelectedPath" + +void SvxHlinkDlgMarkWnd::RestoreLastSelection() +{ + bool bSelectedEntry = false; + + OUString sLastSelectedMark; + std::deque aLastSelectedPath; + SvtViewOptions aViewSettings( EViewType::Dialog, TG_SETTING_MANAGER ); + if (aViewSettings.Exists()) + { + //Maybe we might want to have some sort of mru list and keep a mapping + //per document, rather than the current reuse of "the last thing + //selected, regardless of the document" + aViewSettings.GetUserItem(TG_SETTING_LASTMARK) >>= sLastSelectedMark; + uno::Sequence aTmp; + aViewSettings.GetUserItem(TG_SETTING_LASTPATH) >>= aTmp; + aLastSelectedPath = comphelper::sequenceToContainer< std::deque >(aTmp); + } + //fallback to previous entry selected the last time we executed this dialog. + //First see if the exact mark exists and re-use that + if (!sLastSelectedMark.isEmpty()) + bSelectedEntry = SelectEntry(sLastSelectedMark); + //Otherwise just select the closest path available + //now to what was available at dialog close time + if (!bSelectedEntry && !aLastSelectedPath.empty()) + { + std::deque aTmpSelectedPath(aLastSelectedPath); + std::unique_ptr xEntry(mxLbTree->make_iterator()); + if (!mxLbTree->get_iter_first(*xEntry)) + xEntry.reset(); + SelectPath(xEntry.get(), *mxLbTree, aTmpSelectedPath); + } +} + +// Interface to refresh tree +void SvxHlinkDlgMarkWnd::RefreshTree (const OUString& aStrURL) +{ + OUString aUStrURL; + + weld::WaitObject aWait(m_xDialog.get()); + + ClearTree(); + + sal_Int32 nPos = aStrURL.indexOf('#'); + + if (nPos != 0) + aUStrURL = aStrURL; + + if (!RefreshFromDoc(aUStrURL)) + ErrorChanged(); + + bool bSelectedEntry = false; + + if ( nPos != -1 ) + { + OUString aStrMark = aStrURL.copy(nPos+1); + bSelectedEntry = SelectEntry(aStrMark); + } + + if (!bSelectedEntry) + RestoreLastSelection(); +} + +// get links from document +bool SvxHlinkDlgMarkWnd::RefreshFromDoc(const OUString& aURL) +{ + mnError = LERR_NOERROR; + + uno::Reference< frame::XDesktop2 > xDesktop = frame::Desktop::create( ::comphelper::getProcessComponentContext() ); + uno::Reference< lang::XComponent > xComp; + + if( !aURL.isEmpty() ) + { + // load from url + if( xDesktop.is() ) + { + try + { + uno::Sequence< beans::PropertyValue > aArg(1); + aArg.getArray()[0].Name = "Hidden"; + aArg.getArray()[0].Value <<= true; + xComp = xDesktop->loadComponentFromURL( aURL, "_blank", 0, aArg ); + } + catch( const io::IOException& ) + { + + } + catch( const lang::IllegalArgumentException& ) + { + + } + } + } + else + { + // the component with user focus ( current document ) + xComp = xDesktop->getCurrentComponent(); + } + + if( xComp.is() ) + { + uno::Reference< document::XLinkTargetSupplier > xLTS( xComp, uno::UNO_QUERY ); + + if( xLTS.is() ) + { + if( FillTree( xLTS->getLinks() ) == 0 ) + mnError = LERR_NOENTRIES; + } + else + mnError = LERR_DOCNOTOPEN; + + if ( !aURL.isEmpty() ) + xComp->dispose(); + } + else + { + if( !aURL.isEmpty() ) + mnError=LERR_DOCNOTOPEN; + } + return (mnError==0); +} + +// Fill Tree-Control +int SvxHlinkDlgMarkWnd::FillTree( const uno::Reference< container::XNameAccess >& xLinks, const weld::TreeIter* pParentEntry ) +{ + int nEntries=0; + const uno::Sequence< OUString > aNames( xLinks->getElementNames() ); + const sal_uLong nLinks = aNames.getLength(); + const OUString* pNames = aNames.getConstArray(); + + const OUString aProp_LinkDisplayName( "LinkDisplayName" ); + const OUString aProp_LinkTarget( "com.sun.star.document.LinkTarget" ); + const OUString aProp_LinkDisplayBitmap( "LinkDisplayBitmap" ); + for( sal_uLong i = 0; i < nLinks; i++ ) + { + uno::Any aAny; + OUString aLink( *pNames++ ); + + bool bError = false; + try + { + aAny = xLinks->getByName( aLink ); + } + catch(const uno::Exception&) + { + // if the name of the target was invalid (like empty headings) + // no object can be provided + bError = true; + } + if(bError) + continue; + + uno::Reference< beans::XPropertySet > xTarget; + + if( aAny >>= xTarget ) + { + try + { + // get name to display + aAny = xTarget->getPropertyValue( aProp_LinkDisplayName ); + OUString aDisplayName; + aAny >>= aDisplayName; + OUString aStrDisplayname ( aDisplayName ); + + // is it a target ? + uno::Reference< lang::XServiceInfo > xSI( xTarget, uno::UNO_QUERY ); + bool bIsTarget = xSI->supportsService( aProp_LinkTarget ); + + // create userdata + TargetData *pData = new TargetData ( aLink, bIsTarget ); + OUString sId(OUString::number(reinterpret_cast(pData))); + + std::unique_ptr xEntry(mxLbTree->make_iterator()); + mxLbTree->insert(pParentEntry, -1, &aStrDisplayname, &sId, nullptr, nullptr, nullptr, false, xEntry.get()); + + try + { + // get bitmap for the tree-entry + uno::Reference< awt::XBitmap > + aXBitmap( xTarget->getPropertyValue( aProp_LinkDisplayBitmap ), uno::UNO_QUERY ); + if (aXBitmap.is()) + { + Graphic aBmp(Graphic(VCLUnoHelper::GetBitmap(aXBitmap))); + // insert Displayname into treelist with bitmaps + mxLbTree->set_image(*xEntry, aBmp.GetXGraphic(), -1); + } + } + catch(const css::uno::Exception&) + { + } + + nEntries++; + + uno::Reference< document::XLinkTargetSupplier > xLTS( xTarget, uno::UNO_QUERY ); + if( xLTS.is() ) + nEntries += FillTree( xLTS->getLinks(), xEntry.get() ); + } + catch(const css::uno::Exception&) + { + } + } + } + + return nEntries; +} + +// Clear Tree +void SvxHlinkDlgMarkWnd::ClearTree() +{ + std::unique_ptr xEntry = mxLbTree->make_iterator(); + bool bEntry = mxLbTree->get_iter_first(*xEntry); + + while (bEntry) + { + TargetData* pUserData = reinterpret_cast(mxLbTree->get_id(*xEntry).toInt64()); + delete pUserData; + + bEntry = mxLbTree->iter_next(*xEntry); + } + + mxLbTree->clear(); +} + +// Find Entry for String +std::unique_ptr SvxHlinkDlgMarkWnd::FindEntry (const OUString& aStrName) +{ + bool bFound=false; + std::unique_ptr xEntry = mxLbTree->make_iterator(); + bool bEntry = mxLbTree->get_iter_first(*xEntry); + + while (bEntry && !bFound) + { + TargetData* pUserData = reinterpret_cast(mxLbTree->get_id(*xEntry).toInt64()); + if (aStrName == pUserData->aUStrLinkname) + bFound = true; + else + bEntry = mxLbTree->iter_next(*xEntry); + } + + if (!bFound) + xEntry.reset(); + + return xEntry; +} + +// Select Entry +bool SvxHlinkDlgMarkWnd::SelectEntry(const OUString& aStrMark) +{ + std::unique_ptr xEntry = FindEntry(aStrMark); + if (!xEntry) + return false; + mxLbTree->select(*xEntry); + mxLbTree->scroll_to_row(*xEntry); + return true; +} + +// Click on Apply-Button / Double-click on item in tree +IMPL_LINK_NOARG(SvxHlinkDlgMarkWnd, DoubleClickApplyHdl_Impl, weld::TreeView&, bool) +{ + ClickApplyHdl_Impl(*mxBtApply); + return true; +} + +IMPL_LINK_NOARG(SvxHlinkDlgMarkWnd, ClickApplyHdl_Impl, weld::Button&, void) +{ + std::unique_ptr xEntry(mxLbTree->make_iterator()); + bool bEntry = mxLbTree->get_cursor(xEntry.get()); + if (bEntry) + { + TargetData* pData = reinterpret_cast(mxLbTree->get_id(*xEntry).toInt64()); + if (pData->bIsTarget) + { + mpParent->SetMarkStr(pData->aUStrLinkname); + } + } +} + +// Click on Close-Button +IMPL_LINK_NOARG(SvxHlinkDlgMarkWnd, ClickCloseHdl_Impl, weld::Button&, void) +{ + std::unique_ptr xEntry(mxLbTree->make_iterator()); + bool bEntry = mxLbTree->get_cursor(xEntry.get()); + if (bEntry) + { + TargetData* pUserData = reinterpret_cast(mxLbTree->get_id(*xEntry).toInt64()); + OUString sLastSelectedMark = pUserData->aUStrLinkname; + + std::deque aLastSelectedPath; + //If the bottommost entry is expanded but nothing + //underneath it is selected leave a dummy entry + if (mxLbTree->get_row_expanded(*xEntry)) + aLastSelectedPath.push_front(OUString()); + while (bEntry) + { + aLastSelectedPath.push_front(mxLbTree->get_text(*xEntry)); + bEntry = mxLbTree->iter_parent(*xEntry); + } + + uno::Sequence< beans::NamedValue > aSettings + { + { TG_SETTING_LASTMARK, css::uno::Any(sLastSelectedMark) }, + { TG_SETTING_LASTPATH, css::uno::Any(comphelper::containerToSequence(aLastSelectedPath)) } + }; + + // write + SvtViewOptions aViewSettings( EViewType::Dialog, TG_SETTING_MANAGER ); + aViewSettings.SetUserData( aSettings ); + } + + m_xDialog->response(RET_CANCEL); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/hltpbase.cxx b/cui/source/dialogs/hltpbase.cxx new file mode 100644 index 000000000..b3c7b076f --- /dev/null +++ b/cui/source/dialogs/hltpbase.cxx @@ -0,0 +1,545 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace ::ucbhelper; + +namespace { + +OUString CreateUiNameFromURL( const OUString& aStrURL ) +{ + OUString aStrUiURL; + INetURLObject aURLObj( aStrURL ); + + switch(aURLObj.GetProtocol()) + { + case INetProtocol::File: + osl::FileBase::getSystemPathFromFileURL(aURLObj.GetMainURL(INetURLObject::DecodeMechanism::NONE), aStrUiURL); + break; + case INetProtocol::Ftp : + { + //remove password from name + INetURLObject aTmpURL(aURLObj); + aTmpURL.SetPass(""); + aStrUiURL = aTmpURL.GetMainURL( INetURLObject::DecodeMechanism::Unambiguous ); + } + break; + default : + { + aStrUiURL = aURLObj.GetMainURL(INetURLObject::DecodeMechanism::Unambiguous); + } + } + if(aStrUiURL.isEmpty()) + return aStrURL; + return aStrUiURL; +} + +} + +// ComboBox-Control for URL's with History and Autocompletion +SvxHyperURLBox::SvxHyperURLBox(std::unique_ptr xControl) + : SvtURLBox(std::move(xControl)) + , DropTargetHelper(getWidget()->get_drop_target()) +{ + SetSmartProtocol(INetProtocol::Http); +} + +sal_Int8 SvxHyperURLBox::AcceptDrop( const AcceptDropEvent& /* rEvt */ ) +{ + return IsDropFormatSupported( SotClipboardFormatId::STRING ) ? DND_ACTION_COPY : DND_ACTION_NONE; +} + +sal_Int8 SvxHyperURLBox::ExecuteDrop( const ExecuteDropEvent& rEvt ) +{ + TransferableDataHelper aDataHelper( rEvt.maDropEvent.Transferable ); + OUString aString; + sal_Int8 nRet = DND_ACTION_NONE; + + if( aDataHelper.GetString( SotClipboardFormatId::STRING, aString ) ) + { + set_entry_text(aString); + nRet = DND_ACTION_COPY; + } + + return nRet; +} + +//# Hyperlink-Dialog: Tabpages-Baseclass # + +SvxHyperlinkTabPageBase::SvxHyperlinkTabPageBase(weld::Container* pParent, + SvxHpLinkDlg* pDlg, + const OUString& rUIXMLDescription, + const OString& rID, + const SfxItemSet* pItemSet) + : IconChoicePage(pParent, rUIXMLDescription, rID, pItemSet) + , mxCbbFrame(xBuilder->weld_combo_box("frame")) + , mxLbForm(xBuilder->weld_combo_box("form")) + , mxEdIndication(xBuilder->weld_entry("indication")) + , mxEdText(xBuilder->weld_entry("name")) + , mxBtScript(xBuilder->weld_button("script")) + , mxFormLabel(xBuilder->weld_label("form_label")) + , mxFrameLabel(xBuilder->weld_label("frame_label")) + , mbIsCloseDisabled( false ) + , mpDialog( pDlg ) + , mbStdControlsInit( false ) +{ + // create bookmark-window +} + +SvxHyperlinkTabPageBase::~SvxHyperlinkTabPageBase() +{ + maTimer.Stop(); + + HideMarkWnd(); +} + +bool SvxHyperlinkTabPageBase::QueryClose() +{ + return !mbIsCloseDisabled; +} + +void SvxHyperlinkTabPageBase::InitStdControls () +{ + if ( !mbStdControlsInit ) + { + SfxDispatcher* pDispatch = GetDispatcher(); + SfxViewFrame* pViewFrame = pDispatch ? pDispatch->GetFrame() : nullptr; + SfxFrame* pFrame = pViewFrame ? &pViewFrame->GetFrame() : nullptr; + if ( pFrame ) + { + std::unique_ptr pList(new TargetList); + SfxFrame::GetDefaultTargetList(*pList); + if( !pList->empty() ) + { + size_t nCount = pList->size(); + size_t i; + for ( i = 0; i < nCount; i++ ) + { + mxCbbFrame->append_text( pList->at( i ) ); + } + } + } + + mxBtScript->set_from_icon_name(RID_SVXBMP_SCRIPT); + + mxBtScript->connect_clicked ( LINK ( this, SvxHyperlinkTabPageBase, ClickScriptHdl_Impl ) ); + } + + mbStdControlsInit = true; +} + +// Move Extra-Window +void SvxHyperlinkTabPageBase::MoveToExtraWnd( Point aNewPos ) +{ + mxMarkWnd->MoveTo(aNewPos); +} + +// Show Extra-Window +void SvxHyperlinkTabPageBase::ShowMarkWnd() +{ + if (mxMarkWnd) + { + mxMarkWnd->getDialog()->present(); + return; + } + + weld::Dialog* pDialog = mpDialog->getDialog(); + + mxMarkWnd = std::make_shared(pDialog, this); + + // Size of dialog-window in screen pixels + Point aDlgPos(pDialog->get_position()); + Size aDlgSize(pDialog->get_size()); + + // Absolute size of the screen + ::tools::Rectangle aScreen(pDialog->get_monitor_workarea()); + + // Size of Extrawindow + Size aExtraWndSize(mxMarkWnd->getDialog()->get_preferred_size()); + + // mxMarkWnd is a child of mpDialog, so coordinates for positioning must be relative to mpDialog + if( aDlgPos.X()+(1.05*aDlgSize.Width())+aExtraWndSize.Width() > aScreen.Right() ) + { + if( aDlgPos.X() - ( 0.05*aDlgSize.Width() ) - aExtraWndSize.Width() < 0 ) + { + // Pos Extrawindow anywhere + MoveToExtraWnd( Point(10,10) ); // very unlikely + } + else + { + // Pos Extrawindow on the left side of Dialog + MoveToExtraWnd( Point(0,0) - Point( long(0.05*aDlgSize.Width()), 0 ) - Point( aExtraWndSize.Width(), 0 ) ); + } + } + else + { + // Pos Extrawindow on the right side of Dialog + MoveToExtraWnd ( Point( long(1.05*aDlgSize.getWidth()), 0 ) ); + } + + // Set size of Extra-Window + mxMarkWnd->getDialog()->set_size_request(aExtraWndSize.Width(), aDlgSize.Height()); + + weld::DialogController::runAsync(mxMarkWnd, [this](sal_Int32 /*nResult*/) { mxMarkWnd.reset(); } ); +} + +void SvxHyperlinkTabPageBase::HideMarkWnd() +{ + if (mxMarkWnd) + { + mxMarkWnd->response(RET_CANCEL); + mxMarkWnd.reset(); + } +} + +// Fill Dialogfields +void SvxHyperlinkTabPageBase::FillStandardDlgFields ( const SvxHyperlinkItem* pHyperlinkItem ) +{ + if (!comphelper::LibreOfficeKit::isActive()) + { + // Frame + sal_Int32 nPos = mxCbbFrame->find_text(pHyperlinkItem->GetTargetFrame()); + if (nPos != -1) + mxCbbFrame->set_active(nPos); + + // Form + OUString aStrFormText = CuiResId( RID_SVXSTR_HYPERDLG_FROM_TEXT ); + + OUString aStrFormButton = CuiResId( RID_SVXSTR_HYPERDLG_FORM_BUTTON ); + + if( pHyperlinkItem->GetInsertMode() & HLINK_HTMLMODE ) + { + mxLbForm->clear(); + mxLbForm->append_text( aStrFormText ); + mxLbForm->set_active( 0 ); + } + else + { + mxLbForm->clear(); + mxLbForm->append_text( aStrFormText ); + mxLbForm->append_text( aStrFormButton ); + mxLbForm->set_active( pHyperlinkItem->GetInsertMode() == HLINK_BUTTON ? 1 : 0 ); + } + } + else + { + mxCbbFrame->hide(); + mxLbForm->hide(); + mxFormLabel->hide(); + mxFrameLabel->hide(); + } + + // URL + mxEdIndication->set_text( pHyperlinkItem->GetName() ); + + // Name + mxEdText->set_text( pHyperlinkItem->GetIntName() ); + + // Script-button + if (!comphelper::LibreOfficeKit::isActive()) + { + if ( pHyperlinkItem->GetMacroEvents() == HyperDialogEvent::NONE ) + mxBtScript->set_sensitive(false); + else + mxBtScript->set_sensitive(true); + } + else + { + mxBtScript->hide(); + } +} + +// Any action to do after apply-button is pressed +void SvxHyperlinkTabPageBase::DoApply () +{ + // default-implementation : do nothing +} + +// Ask page whether an insert is possible +bool SvxHyperlinkTabPageBase::AskApply () +{ + // default-implementation + return true; +} + +// This method would be called from bookmark-window to set new mark-string +void SvxHyperlinkTabPageBase::SetMarkStr ( const OUString& /*aStrMark*/ ) +{ + // default-implementation : do nothing +} + +// Set initial focus +void SvxHyperlinkTabPageBase::SetInitFocus() +{ + xContainer->grab_focus(); +} + +// retrieve dispatcher +SfxDispatcher* SvxHyperlinkTabPageBase::GetDispatcher() const +{ + return mpDialog->GetDispatcher(); +} + +void SvxHyperlinkTabPageBase::DisableClose(bool _bDisable) +{ + mbIsCloseDisabled = _bDisable; + if (mbIsCloseDisabled) + maBusy.incBusy(mpDialog->getDialog()); + else + maBusy.decBusy(); +} + +// Click on imagebutton : Script +IMPL_LINK_NOARG(SvxHyperlinkTabPageBase, ClickScriptHdl_Impl, weld::Button&, void) +{ + SvxHyperlinkItem *pHyperlinkItem = const_cast(static_cast( + GetItemSet().GetItem (SID_HYPERLINK_GETLINK))); + + if ( pHyperlinkItem->GetMacroEvents() == HyperDialogEvent::NONE ) + return; + + // get macros from itemset + const SvxMacroTableDtor* pMacroTbl = pHyperlinkItem->GetMacroTable(); + SvxMacroItem aItem ( SID_ATTR_MACROITEM ); + if( pMacroTbl ) + aItem.SetMacroTable( *pMacroTbl ); + + // create empty itemset for macro-dlg + std::unique_ptr pItemSet( new SfxItemSet(SfxGetpApp()->GetPool(), + svl::Items{} ) ); + pItemSet->Put ( aItem ); + + DisableClose( true ); + + SfxMacroAssignDlg aDlg(mpDialog->getDialog(), mxDocumentFrame, *pItemSet); + + // add events + SfxMacroTabPage *pMacroPage = aDlg.GetTabPage(); + + if ( pHyperlinkItem->GetMacroEvents() & HyperDialogEvent::MouseOverObject ) + pMacroPage->AddEvent( CuiResId(RID_SVXSTR_HYPDLG_MACROACT1), + SvMacroItemId::OnMouseOver ); + if ( pHyperlinkItem->GetMacroEvents() & HyperDialogEvent::MouseClickObject ) + pMacroPage->AddEvent( CuiResId(RID_SVXSTR_HYPDLG_MACROACT2), + SvMacroItemId::OnClick); + if ( pHyperlinkItem->GetMacroEvents() & HyperDialogEvent::MouseOutObject ) + pMacroPage->AddEvent( CuiResId(RID_SVXSTR_HYPDLG_MACROACT3), + SvMacroItemId::OnMouseOut); + // execute dlg + short nRet = aDlg.run(); + DisableClose( false ); + if ( RET_OK == nRet ) + { + const SfxItemSet* pOutSet = aDlg.GetOutputItemSet(); + const SfxPoolItem* pItem; + if( SfxItemState::SET == pOutSet->GetItemState( SID_ATTR_MACROITEM, false, &pItem )) + { + pHyperlinkItem->SetMacroTable( static_cast(pItem)->GetMacroTable() ); + } + } +} + +// Get Macro-Infos +HyperDialogEvent SvxHyperlinkTabPageBase::GetMacroEvents() const +{ + const SvxHyperlinkItem *pHyperlinkItem = static_cast( + GetItemSet().GetItem (SID_HYPERLINK_GETLINK)); + + return pHyperlinkItem->GetMacroEvents(); +} + +SvxMacroTableDtor* SvxHyperlinkTabPageBase::GetMacroTable() +{ + const SvxHyperlinkItem *pHyperlinkItem = static_cast( + GetItemSet().GetItem (SID_HYPERLINK_GETLINK)); + + return const_cast(pHyperlinkItem->GetMacroTable()); +} + +// try to detect the current protocol that is used in rStrURL +OUString SvxHyperlinkTabPageBase::GetSchemeFromURL( const OUString& rStrURL ) +{ + OUString aStrScheme; + + INetURLObject aURL( rStrURL ); + INetProtocol aProtocol = aURL.GetProtocol(); + + // our new INetUrlObject now has the ability + // to detect if a Url is valid or not :-( + if ( aProtocol == INetProtocol::NotValid ) + { + if ( rStrURL.startsWithIgnoreAsciiCase( INET_HTTP_SCHEME ) ) + { + aStrScheme = INET_HTTP_SCHEME; + } + else if ( rStrURL.startsWithIgnoreAsciiCase( INET_HTTPS_SCHEME ) ) + { + aStrScheme = INET_HTTPS_SCHEME; + } + else if ( rStrURL.startsWithIgnoreAsciiCase( INET_FTP_SCHEME ) ) + { + aStrScheme = INET_FTP_SCHEME; + } + else if ( rStrURL.startsWithIgnoreAsciiCase( INET_MAILTO_SCHEME ) ) + { + aStrScheme = INET_MAILTO_SCHEME; + } + } + else + aStrScheme = INetURLObject::GetScheme( aProtocol ); + return aStrScheme; +} + +void SvxHyperlinkTabPageBase::GetDataFromCommonFields( OUString& aStrName, + OUString& aStrIntName, OUString& aStrFrame, + SvxLinkInsertMode& eMode ) +{ + aStrIntName = mxEdText->get_text(); + aStrName = mxEdIndication->get_text(); + aStrFrame = mxCbbFrame->get_active_text(); + + sal_Int32 nPos = mxLbForm->get_active(); + if (nPos == -1) + // This happens when FillStandardDlgFields() hides mpLbForm. + nPos = 0; + eMode = static_cast(nPos + 1); + + // Ask dialog whether the current doc is a HTML-doc + if (mpDialog->IsHTMLDoc()) + eMode = static_cast( sal_uInt16(eMode) | HLINK_HTMLMODE ); +} + +// reset dialog-fields +void SvxHyperlinkTabPageBase::Reset( const SfxItemSet& rItemSet) +{ + + // Set dialog-fields from create-itemset + maStrInitURL.clear(); + + const SvxHyperlinkItem *pHyperlinkItem = static_cast( + rItemSet.GetItem (SID_HYPERLINK_GETLINK)); + + if ( pHyperlinkItem ) + { + // set dialog-fields + FillStandardDlgFields (pHyperlinkItem); + + // set all other fields + FillDlgFields ( pHyperlinkItem->GetURL() ); + + // Store initial URL + maStrInitURL = pHyperlinkItem->GetURL(); + } +} + +// Fill output-ItemSet +bool SvxHyperlinkTabPageBase::FillItemSet( SfxItemSet* rOut) +{ + OUString aStrURL, aStrName, aStrIntName, aStrFrame; + SvxLinkInsertMode eMode; + + GetCurentItemData ( aStrURL, aStrName, aStrIntName, aStrFrame, eMode); + if ( aStrName.isEmpty() ) //automatically create a visible name if the link is created without name + aStrName = CreateUiNameFromURL(aStrURL); + + HyperDialogEvent nEvents = GetMacroEvents(); + SvxMacroTableDtor* pTable = GetMacroTable(); + + SvxHyperlinkItem aItem( SID_HYPERLINK_SETLINK, aStrName, aStrURL, aStrFrame, + aStrIntName, eMode, nEvents, pTable ); + rOut->Put (aItem); + + return true; +} + +// Activate / Deactivate Tabpage +void SvxHyperlinkTabPageBase::ActivatePage( const SfxItemSet& rItemSet ) +{ + + // Set dialog-fields from input-itemset + const SvxHyperlinkItem *pHyperlinkItem = static_cast( + rItemSet.GetItem (SID_HYPERLINK_GETLINK)); + + if ( pHyperlinkItem ) + { + // standard-fields + FillStandardDlgFields (pHyperlinkItem); + } + + // show mark-window if it was open before + if ( ShouldOpenMarkWnd () ) + ShowMarkWnd (); +} + +DeactivateRC SvxHyperlinkTabPageBase::DeactivatePage( SfxItemSet* _pSet) +{ + // hide mark-wnd + SetMarkWndShouldOpen( IsMarkWndVisible () ); + HideMarkWnd (); + + // retrieve data of dialog + OUString aStrURL, aStrName, aStrIntName, aStrFrame; + SvxLinkInsertMode eMode; + + GetCurentItemData ( aStrURL, aStrName, aStrIntName, aStrFrame, eMode); + + HyperDialogEvent nEvents = GetMacroEvents(); + SvxMacroTableDtor* pTable = GetMacroTable(); + + if( _pSet ) + { + SvxHyperlinkItem aItem( SID_HYPERLINK_GETLINK, aStrName, aStrURL, aStrFrame, + aStrIntName, eMode, nEvents, pTable ); + _pSet->Put( aItem ); + } + + return DeactivateRC::LeavePage; +} + +bool SvxHyperlinkTabPageBase::ShouldOpenMarkWnd() +{ + return false; +} + +void SvxHyperlinkTabPageBase::SetMarkWndShouldOpen(bool) +{ +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/hyphen.cxx b/cui/source/dialogs/hyphen.cxx new file mode 100644 index 000000000..f7b6549fc --- /dev/null +++ b/cui/source/dialogs/hyphen.cxx @@ -0,0 +1,471 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#define HYPH_POS_CHAR '=' + +#define CUR_HYPH_POS_CHAR '-' + +using namespace css; + +IMPL_LINK_NOARG(SvxHyphenWordDialog, CursorChangeHdl_Impl, weld::Entry&, void) +{ + int nStart, nEnd; + m_xWordEdit->get_selection_bounds(nStart, nEnd); + if (nStart == m_nOldPos && nEnd == m_nOldPos + 1) + return; + bool bReSelect; + if (nStart <= m_nOldPos) + bReSelect = !SelLeft(); + else + bReSelect = !SelRight(); + if (bReSelect) + select_region(m_nOldPos, m_nOldPos + 1); +} + +void SvxHyphenWordDialog::EnableLRBtn_Impl() +{ + const sal_Int32 nLen = m_aEditWord.getLength(); + + m_xRightBtn->set_sensitive(false); + for ( sal_Int32 i = m_nOldPos + 2; i < nLen; ++i ) + { + if ( m_aEditWord[ i ] == sal_Unicode( HYPH_POS_CHAR ) ) + { + m_xRightBtn->set_sensitive(true); + break; + } + } + + DBG_ASSERT(m_nOldPos < nLen, "nOldPos out of range"); + if (m_nOldPos >= nLen) + m_nOldPos = nLen - 1; + m_xLeftBtn->set_sensitive(false); + for ( sal_Int32 i = m_nOldPos; i-- > 0; ) + { + if ( m_aEditWord[ i ] == sal_Unicode( HYPH_POS_CHAR ) ) + { + m_xLeftBtn->set_sensitive(true); + break; + } + } +} + +OUString SvxHyphenWordDialog::EraseUnusableHyphens_Impl() +{ + // returns a String showing only those hyphen positions which will result + // in a line break if hyphenation is done there + // 1) we will need to discard all hyphenation positions at the end that + // will not result in a line break where the text to the left still fits + // on the line. + // 2) since as from OOo 3.2 '-' are part of a word and thus text like + // 'multi-line-editor' is regarded as single word we also need to discard those + // hyphenation positions to the left of the rightmost '-' that is still left of + // the rightmost valid hyphenation position according to 1) + + // Example: + // If the possible hyphenation position in 'multi-line-editor' are to be marked + // by '=' then the text will look like this: 'mul=ti-line-ed=it=or'. + // If now the first line is only large enough for 'multi-line-edi' we need to discard + // the last possible hyphenation point because of 1). The right most valid + // hyphenation position is "ed=itor". The first '-' left of this position is + // "line-ed", thus because of 2) we now need to discard all possible hyphenation + // positions to the left of that as well. Thus in the end leaving us with just + // 'multi-line-ed=itor' as return value for this function. (Just one valid hyphenation + // position for the user to choose from. However ALL the '-' characters in the word + // will ALWAYS be valid implicit hyphenation positions for the core to choose from! + // And thus even if this word is skipped in the hyphenation dialog it will still be broken + // right after 'multi-line-' (actually it might already be broken up that way before + // the hyphenation dialog is called!). + // Thus rule 2) just eliminates those positions which will not be used by the core at all + // even if the user were to select one of them. + + OUString aTxt; + DBG_ASSERT(m_xPossHyph.is(), "missing possible hyphens"); + if (m_xPossHyph.is()) + { + DBG_ASSERT( m_aActWord == m_xPossHyph->getWord(), "word mismatch" ); + + aTxt = m_xPossHyph->getPossibleHyphens(); + + m_nHyphenationPositionsOffset = 0; + uno::Sequence< sal_Int16 > aHyphenationPositions( + m_xPossHyph->getHyphenationPositions() ); + sal_Int32 nLen = aHyphenationPositions.getLength(); + const sal_Int16 *pHyphenationPos = aHyphenationPositions.getConstArray(); + + // find position nIdx after which all hyphen positions are unusable + sal_Int32 nIdx = -1; + sal_Int32 nPos = 0, nPos1 = 0; + if (nLen) + { + sal_Int32 nStart = 0; + for (sal_Int32 i = 0; i < nLen; ++i) + { + if (pHyphenationPos[i] > m_nMaxHyphenationPos) + break; + else + { + // find corresponding hyphen positions in string + nPos = aTxt.indexOf( sal_Unicode( HYPH_POS_CHAR ), nStart ); + + if (nPos == -1) + break; + else + { + nIdx = nPos; + nStart = nPos + 1; + } + } + } + } + DBG_ASSERT(nIdx != -1, "no usable hyphenation position"); + + // 1) remove all not usable hyphenation positions from the end of the string + nPos = nIdx == -1 ? 0 : nIdx + 1; + nPos1 = nPos; //save for later use in 2) below + const OUString aTmp( sal_Unicode( HYPH_POS_CHAR ) ); + while (nPos != -1) + { + nPos++; + aTxt = aTxt.replaceFirst( aTmp, "", &nPos); + } + + // 2) remove all hyphenation positions from the start that are not considered by the core + const OUString aSearchRange( aTxt.copy( 0, nPos1 ) ); + sal_Int32 nPos2 = aSearchRange.lastIndexOf( '-' ); // the '-' position the core will use by default + if (nPos2 != -1 ) + { + OUString aLeft( aSearchRange.copy( 0, nPos2 ) ); + nPos = 0; + while (nPos != -1) + { + nPos++; + aLeft = aLeft.replaceFirst( aTmp, "", &nPos ); + if (nPos != -1) + ++m_nHyphenationPositionsOffset; + } + aTxt = aTxt.replaceAt( 0, nPos2, aLeft ); + } + } + return aTxt; +} + +void SvxHyphenWordDialog::InitControls_Impl() +{ + m_xPossHyph = nullptr; + if (m_xHyphenator.is()) + { + lang::Locale aLocale( LanguageTag::convertToLocale(m_nActLanguage) ); + m_xPossHyph = m_xHyphenator->createPossibleHyphens( m_aActWord, aLocale, + uno::Sequence< beans::PropertyValue >() ); + if (m_xPossHyph.is()) + m_aEditWord = EraseUnusableHyphens_Impl(); + } + m_xWordEdit->set_text(m_aEditWord); + + m_nOldPos = m_aEditWord.getLength(); + SelLeft(); + EnableLRBtn_Impl(); +} + +void SvxHyphenWordDialog::ContinueHyph_Impl( sal_Int32 nInsPos ) +{ + if ( nInsPos >= 0 && m_xPossHyph.is() ) + { + if (nInsPos) + { + DBG_ASSERT(nInsPos <= m_aEditWord.getLength() - 2, "wrong hyphen position"); + + sal_Int32 nIdxPos = -1; + for (sal_Int32 i = 0; i <= nInsPos; ++i) + { + if (HYPH_POS_CHAR == m_aEditWord[ i ]) + nIdxPos++; + } + // take the possible hyphenation positions that got removed from the + // start of the word into account: + nIdxPos += m_nHyphenationPositionsOffset; + + uno::Sequence< sal_Int16 > aSeq = m_xPossHyph->getHyphenationPositions(); + sal_Int32 nLen = aSeq.getLength(); + DBG_ASSERT(nLen, "empty sequence"); + DBG_ASSERT(0 <= nIdxPos && nIdxPos < nLen, "index out of range"); + if (nLen && 0 <= nIdxPos && nIdxPos < nLen) + { + nInsPos = aSeq.getConstArray()[ nIdxPos ]; + m_pHyphWrapper->InsertHyphen( nInsPos ); + } + } + else + { + //! calling with 0 as argument will remove hyphens! + m_pHyphWrapper->InsertHyphen( nInsPos ); + } + } + + if ( m_pHyphWrapper->FindSpellError() ) + { + uno::Reference< linguistic2::XHyphenatedWord > xHyphWord( m_pHyphWrapper->GetLast(), uno::UNO_QUERY ); + + // adapt actual word and language to new found hyphenation result + if(xHyphWord.is()) + { + m_aActWord = xHyphWord->getWord(); + m_nActLanguage = LanguageTag( xHyphWord->getLocale() ).getLanguageType(); + m_nMaxHyphenationPos = xHyphWord->getHyphenationPos(); + InitControls_Impl(); + SetWindowTitle( m_nActLanguage ); + } + } + else + { + m_xCloseBtn->set_sensitive(false); + m_xDialog->response(RET_OK); + } +} + +bool SvxHyphenWordDialog::SelLeft() +{ + bool bRet = false; + DBG_ASSERT( m_nOldPos > 0, "invalid hyphenation position" ); + if (m_nOldPos > 0) + { + OUString aTxt( m_aEditWord ); + for( sal_Int32 i = m_nOldPos - 1; i > 0; --i ) + { + DBG_ASSERT(i <= aTxt.getLength(), "index out of range"); + if (aTxt[ i ] == sal_Unicode( HYPH_POS_CHAR )) + { + aTxt = aTxt.replaceAt( i, 1, OUString( CUR_HYPH_POS_CHAR ) ); + + m_nOldPos = i; + m_xWordEdit->set_text(aTxt); + select_region(i, i + 1); + m_xWordEdit->grab_focus(); + bRet = true; + break; + } + } + EnableLRBtn_Impl(); + } + return bRet; +} + +bool SvxHyphenWordDialog::SelRight() +{ + bool bRet = false; + OUString aTxt( m_aEditWord ); + for ( sal_Int32 i = m_nOldPos + 1; i < aTxt.getLength(); ++i ) + { + if (aTxt[ i ] == sal_Unicode( HYPH_POS_CHAR )) + { + aTxt = aTxt.replaceAt( i, 1, OUString( CUR_HYPH_POS_CHAR ) ); + + m_nOldPos = i; + m_xWordEdit->set_text(aTxt); + select_region(i, i + 1); + m_xWordEdit->grab_focus(); + bRet = true; + break; + } + } + EnableLRBtn_Impl(); + return bRet; +} + +IMPL_LINK_NOARG(SvxHyphenWordDialog, CutHdl_Impl, weld::Button&, void) +{ + if( !m_bBusy ) + { + m_bBusy = true; + ContinueHyph_Impl( /*m_nHyphPos*/m_nOldPos ); + m_bBusy = false; + } +} + +IMPL_LINK_NOARG(SvxHyphenWordDialog, HyphenateAllHdl_Impl, weld::Button&, void) +{ + if( m_bBusy ) + return; + + try + { + uno::Reference< linguistic2::XLinguProperties > xProp( LinguMgr::GetLinguPropertySet() ); + + xProp->setIsHyphAuto( true ); + + m_bBusy = true; + ContinueHyph_Impl( /*m_nHyphPos*/m_nOldPos ); + m_bBusy = false; + + xProp->setIsHyphAuto( false ); + } + catch (uno::Exception &) + { + SAL_WARN( "cui.dialogs", "Hyphenate All failed" ); + } +} + +IMPL_LINK_NOARG(SvxHyphenWordDialog, DeleteHdl_Impl, weld::Button&, void) +{ + if( !m_bBusy ) + { + m_bBusy = true; + ContinueHyph_Impl( 0 ); + m_bBusy = false; + } +} + +IMPL_LINK_NOARG(SvxHyphenWordDialog, ContinueHdl_Impl, weld::Button&, void) +{ + if( !m_bBusy ) + { + m_bBusy = true; + ContinueHyph_Impl(); + m_bBusy = false; + } +} + +IMPL_LINK_NOARG(SvxHyphenWordDialog, CancelHdl_Impl, weld::Button&, void) +{ + if( !m_bBusy ) + { + m_bBusy = true; + m_xDialog->response(RET_CANCEL); + m_bBusy = false; + } +} + +IMPL_LINK_NOARG(SvxHyphenWordDialog, Left_Impl, weld::Button&, void) +{ + if( !m_bBusy ) + { + m_bBusy = true; + SelLeft(); + m_bBusy = false; + } +} + +IMPL_LINK_NOARG(SvxHyphenWordDialog, Right_Impl, weld::Button&, void) +{ + if( !m_bBusy ) + { + m_bBusy = true; + SelRight(); + m_bBusy = false; + } +} + +void SvxHyphenWordDialog::select_region(int nStart, int nEnd) +{ + int nScrollPos = nStart + m_nWordEditWidth/2; + if (nScrollPos > m_aEditWord.getLength()) + nScrollPos = m_aEditWord.getLength() - m_nWordEditWidth/2; + if (nScrollPos < 0) + nScrollPos = 0; + m_xWordEdit->set_position(nScrollPos); + m_xWordEdit->select_region(nStart, nEnd); +} + +IMPL_LINK_NOARG(SvxHyphenWordDialog, GetFocusHdl_Impl, weld::Widget&, void) +{ + select_region(m_nOldPos, m_nOldPos + 1); +} + +// class SvxHyphenWordDialog --------------------------------------------- + +SvxHyphenWordDialog::SvxHyphenWordDialog( + const OUString &rWord, LanguageType nLang, + weld::Window* pParent, + uno::Reference< linguistic2::XHyphenator > const &xHyphen, + SvxSpellWrapper* pWrapper) + : SfxDialogController(pParent, "cui/ui/hyphenate.ui", "HyphenateDialog") + , m_pHyphWrapper(pWrapper) + , m_aActWord(rWord) + , m_nActLanguage(nLang) + , m_nMaxHyphenationPos(0) + , m_nOldPos(0) + , m_nHyphenationPositionsOffset(0) + , m_bBusy(false) + , m_xWordEdit(m_xBuilder->weld_entry("worded")) + , m_xLeftBtn(m_xBuilder->weld_button("left")) + , m_xRightBtn(m_xBuilder->weld_button("right")) + , m_xOkBtn(m_xBuilder->weld_button("ok")) + , m_xContBtn(m_xBuilder->weld_button("continue")) + , m_xDelBtn(m_xBuilder->weld_button("delete")) + , m_xHyphAll(m_xBuilder->weld_button("hyphall")) + , m_xCloseBtn(m_xBuilder->weld_button("close")) +{ + m_nWordEditWidth = m_xWordEdit->get_width_chars(); + m_aLabel = m_xDialog->get_title(); + m_xHyphenator = xHyphen; + + uno::Reference< linguistic2::XHyphenatedWord > xHyphWord( m_pHyphWrapper ? + m_pHyphWrapper->GetLast() : nullptr, uno::UNO_QUERY ); + DBG_ASSERT( xHyphWord.is(), "hyphenation result missing" ); + if (xHyphWord.is()) + { + DBG_ASSERT( m_aActWord == xHyphWord->getWord(), "word mismatch" ); + DBG_ASSERT( m_nActLanguage == LanguageTag( xHyphWord->getLocale() ).getLanguageType(), "language mismatch" ); + m_nMaxHyphenationPos = xHyphWord->getHyphenationPos(); + } + + InitControls_Impl(); + m_xWordEdit->grab_focus(); + + m_xLeftBtn->connect_clicked( LINK( this, SvxHyphenWordDialog, Left_Impl ) ); + m_xRightBtn->connect_clicked( LINK( this, SvxHyphenWordDialog, Right_Impl ) ); + m_xOkBtn->connect_clicked( LINK( this, SvxHyphenWordDialog, CutHdl_Impl ) ); + m_xContBtn->connect_clicked( LINK( this, SvxHyphenWordDialog, ContinueHdl_Impl ) ); + m_xDelBtn->connect_clicked( LINK( this, SvxHyphenWordDialog, DeleteHdl_Impl ) ); + m_xHyphAll->connect_clicked( LINK( this, SvxHyphenWordDialog, HyphenateAllHdl_Impl ) ); + m_xCloseBtn->connect_clicked( LINK( this, SvxHyphenWordDialog, CancelHdl_Impl ) ); + m_xWordEdit->connect_focus_in( LINK( this, SvxHyphenWordDialog, GetFocusHdl_Impl ) ); + m_xWordEdit->connect_cursor_position( LINK( this, SvxHyphenWordDialog, CursorChangeHdl_Impl ) ); + + SetWindowTitle( nLang ); + + // disable controls if service is not available + if (!m_xHyphenator.is()) + m_xDialog->set_sensitive(false); +} + +SvxHyphenWordDialog::~SvxHyphenWordDialog() +{ + if (m_xCloseBtn->get_sensitive()) + m_pHyphWrapper->SpellEnd(); +} + +void SvxHyphenWordDialog::SetWindowTitle(LanguageType nLang) +{ + m_xDialog->set_title(m_aLabel + " (" + SvtLanguageTable::GetLanguageString(nLang) + ")"); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/iconcdlg.cxx b/cui/source/dialogs/iconcdlg.cxx new file mode 100644 index 000000000..bca5984f8 --- /dev/null +++ b/cui/source/dialogs/iconcdlg.cxx @@ -0,0 +1,311 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +#include +#include +#include + +/********************************************************************** +| +| Ctor / Dtor +| +\**********************************************************************/ + +IconChoicePage::IconChoicePage(weld::Container* pParent, + const OUString& rUIXMLDescription, const OString& rID, + const SfxItemSet* pItemSet) + : xBuilder(Application::CreateBuilder(pParent, rUIXMLDescription)) + , xContainer(xBuilder->weld_container(rID)) + , pSet(pItemSet) + , bHasExchangeSupport(false) +{ +} + +IconChoicePage::~IconChoicePage() +{ +} + +/********************************************************************** +| +| Activate / Deactivate +| +\**********************************************************************/ + +void IconChoicePage::ActivatePage( const SfxItemSet& ) +{ +} + + +DeactivateRC IconChoicePage::DeactivatePage( SfxItemSet* ) +{ + return DeactivateRC::LeavePage; +} + +bool IconChoicePage::QueryClose() +{ + return true; +} + +/********************************************************************** +| +| add new page +| +\**********************************************************************/ +void SvxHpLinkDlg::AddTabPage(const OString& rId, CreatePage pCreateFunc /* != 0 */) +{ + weld::Container* pPage = m_xIconCtrl->get_page(rId); + maPageList.emplace_back(new IconChoicePageData(rId, pCreateFunc(pPage, this, pSet))); + maPageList.back()->xPage->Reset(*pSet); + PageCreated(rId, *maPageList.back()->xPage); +} + +/********************************************************************** +| +| Show / Hide page or button +| +\**********************************************************************/ +void SvxHpLinkDlg::ShowPage(const OString& rId) +{ + OString sOldPageId = GetCurPageId(); + bool bInvalidate = sOldPageId != rId; + if (bInvalidate) + { + IconChoicePageData* pOldData = GetPageData(sOldPageId); + if (pOldData && pOldData->xPage) + { + DeActivatePageImpl(); + } + } + SetCurPageId(rId); + ActivatePageImpl(); +} + +/********************************************************************** +| +| select a page +| +\**********************************************************************/ +IMPL_LINK(SvxHpLinkDlg, ChosePageHdl_Impl, const OString&, rId, void) +{ + if (rId != msCurrentPageId) + { + ShowPage(rId); + } +} + +/********************************************************************** +| +| Button-handler +| +\**********************************************************************/ +IMPL_LINK_NOARG(SvxHpLinkDlg, ResetHdl, weld::Button&, void) +{ + ResetPageImpl (); + + IconChoicePageData* pData = GetPageData ( msCurrentPageId ); + assert( pData && "ID not known " ); + + pData->xPage->Reset( *pSet ); +} + +/********************************************************************** +| +| call page +| +\**********************************************************************/ +void SvxHpLinkDlg::ActivatePageImpl() +{ + assert( !maPageList.empty() && "no Pages registered " ); + IconChoicePageData* pData = GetPageData ( msCurrentPageId ); + assert( pData && "ID not known " ); + + if ( pData->bRefresh ) + { + pData->xPage->Reset( *pSet ); + pData->bRefresh = false; + } + + if ( pExampleSet ) + pData->xPage->ActivatePage( *pExampleSet ); + m_xDialog->set_help_id(pData->xPage->GetHelpId()); + + m_xResetBtn->show(); +} + +void SvxHpLinkDlg::DeActivatePageImpl () +{ + IconChoicePageData *pData = GetPageData ( msCurrentPageId ); + + DeactivateRC nRet = DeactivateRC::LeavePage; + + if ( !pData ) + return; + + IconChoicePage * pPage = pData->xPage.get(); + + if ( !pExampleSet && pPage->HasExchangeSupport() && pSet ) + pExampleSet = new SfxItemSet( *pSet->GetPool(), pSet->GetRanges() ); + + if ( pSet ) + { + SfxItemSet aTmp( *pSet->GetPool(), pSet->GetRanges() ); + + if ( pPage->HasExchangeSupport() ) + nRet = pPage->DeactivatePage( &aTmp ); + + if ( ( DeactivateRC::LeavePage & nRet ) && + aTmp.Count() ) + { + if (pExampleSet) + pExampleSet->Put(aTmp); + pOutSet->Put( aTmp ); + } + } + else + { + if ( pPage->HasExchangeSupport() ) //!!! + { + if ( !pExampleSet ) + { + SfxItemPool* pPool = pPage->GetItemSet().GetPool(); + pExampleSet = + new SfxItemSet( *pPool, GetInputRanges( *pPool ) ); + } + nRet = pPage->DeactivatePage( pExampleSet ); + } + else + nRet = pPage->DeactivatePage( nullptr ); + } + + if ( nRet & DeactivateRC::RefreshSet ) + { + // TODO refresh input set + // flag all pages to be newly initialized + for (auto & pObj : maPageList) + { + if ( pObj->xPage.get() != pPage ) + pObj->bRefresh = true; + else + pObj->bRefresh = false; + } + } +} + + +void SvxHpLinkDlg::ResetPageImpl () +{ + IconChoicePageData *pData = GetPageData ( msCurrentPageId ); + + assert( pData && "ID not known " ); + + pData->xPage->Reset( *pSet ); +} + +/********************************************************************** +| +| handling itemsets +| +\**********************************************************************/ + +const sal_uInt16* SvxHpLinkDlg::GetInputRanges( const SfxItemPool& ) +{ + if ( pSet ) + { + SAL_WARN( "cui.dialogs", "Set does already exist!" ); + return pSet->GetRanges(); + } + + if ( pRanges ) + return pRanges.get(); + + pRanges.reset(new sal_uInt16[1]); + pRanges[0] = 0; + + return pRanges.get(); +} + + +void SvxHpLinkDlg::SetInputSet( const SfxItemSet* pInSet ) +{ + bool bSet = ( pSet != nullptr ); + + pSet = pInSet; + + if ( !bSet && !pExampleSet && !pOutSet ) + { + pExampleSet = new SfxItemSet( *pSet ); + pOutSet.reset(new SfxItemSet( *pSet->GetPool(), pSet->GetRanges() )); + } +} + +bool SvxHpLinkDlg::QueryClose() +{ + bool bRet = true; + for (auto & pData : maPageList) + { + if ( pData->xPage && !pData->xPage->QueryClose() ) + { + bRet = false; + break; + } + } + return bRet; +} + +void SvxHpLinkDlg::Start() +{ + SwitchPage(msCurrentPageId); + ActivatePageImpl(); +} + +/********************************************************************** +| +| tool-methods +| +\**********************************************************************/ + +IconChoicePageData* SvxHpLinkDlg::GetPageData ( const OString& rId ) +{ + IconChoicePageData *pRet = nullptr; + for (const auto & pData : maPageList) + { + if ( pData->sId == rId ) + { + pRet = pData.get(); + break; + } + } + return pRet; +} + +/********************************************************************** +| +| OK-Status +| +\**********************************************************************/ + +void SvxHpLinkDlg::SwitchPage( const OString& rId ) +{ + m_xIconCtrl->set_current_page(rId); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/insdlg.cxx b/cui/source/dialogs/insdlg.cxx new file mode 100644 index 000000000..4f34b461e --- /dev/null +++ b/cui/source/dialogs/insdlg.cxx @@ -0,0 +1,583 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::ui::dialogs; + +bool InsertObjectDialog_Impl::IsCreateNew() const +{ + return false; +} + +uno::Reference< io::XInputStream > InsertObjectDialog_Impl::GetIconIfIconified( OUString* /*pGraphicMediaType*/ ) +{ + return uno::Reference< io::XInputStream >(); +} + +InsertObjectDialog_Impl::InsertObjectDialog_Impl(weld::Window* pParent, + const OUString& rUIXMLDescription, const OString& rID, + const css::uno::Reference < css::embed::XStorage >& xStorage) + : GenericDialogController(pParent, rUIXMLDescription, rID) + , m_xStorage( xStorage ) + , aCnt( m_xStorage ) +{ +} + +IMPL_LINK_NOARG(SvInsertOleDlg, DoubleClickHdl, weld::TreeView&, bool) +{ + m_xDialog->response(RET_OK); + return true; +} + +IMPL_LINK_NOARG(SvInsertOleDlg, BrowseHdl, weld::Button&, void) +{ + sfx2::FileDialogHelper aHelper(ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE, FileDialogFlags::NONE, m_xDialog.get()); + const Reference< XFilePicker3 >& xFilePicker = aHelper.GetFilePicker(); + + // add filter + try + { + xFilePicker->appendFilter(CuiResId(RID_SVXSTR_FILTER_ALL), "*.*"); + } + catch( const IllegalArgumentException& ) + { + SAL_WARN( "cui.dialogs", "caught IllegalArgumentException when registering filter" ); + } + + if( xFilePicker->execute() == ExecutableDialogResults::OK ) + { + Sequence< OUString > aPathSeq( xFilePicker->getSelectedFiles() ); + INetURLObject aObj( aPathSeq[0] ); + m_xEdFilepath->set_text(aObj.PathToFileName()); + } +} + +IMPL_LINK_NOARG(SvInsertOleDlg, RadioHdl, weld::Button&, void) +{ + if (m_xRbNewObject->get_active()) + { + m_xObjectTypeFrame->show(); + m_xFileFrame->hide(); + } + else + { + m_xFileFrame->show(); + m_xObjectTypeFrame->hide(); + } +} + +SvInsertOleDlg::SvInsertOleDlg(weld::Window* pParent, const Reference& xStorage, + const SvObjectServerList* pServers) + : InsertObjectDialog_Impl( pParent, "cui/ui/insertoleobject.ui", "InsertOLEObjectDialog", xStorage) + , m_pServers( pServers ) + , m_xRbNewObject(m_xBuilder->weld_radio_button("createnew")) + , m_xRbObjectFromfile(m_xBuilder->weld_radio_button("createfromfile")) + , m_xObjectTypeFrame(m_xBuilder->weld_frame("objecttypeframe")) + , m_xLbObjecttype(m_xBuilder->weld_tree_view("types")) + , m_xFileFrame(m_xBuilder->weld_frame("fileframe")) + , m_xEdFilepath(m_xBuilder->weld_entry("urled")) + , m_xBtnFilepath(m_xBuilder->weld_button("urlbtn")) + , m_xCbFilelink(m_xBuilder->weld_check_button("linktofile")) + , m_xCbAsIcon(m_xBuilder->weld_check_button("asicon")) +{ + m_xLbObjecttype->set_size_request(m_xLbObjecttype->get_approximate_digit_width() * 32, + m_xLbObjecttype->get_height_rows(6)); + m_xLbObjecttype->connect_row_activated(LINK(this, SvInsertOleDlg, DoubleClickHdl)); + m_xBtnFilepath->connect_clicked(LINK( this, SvInsertOleDlg, BrowseHdl)); + Link aLink( LINK( this, SvInsertOleDlg, RadioHdl ) ); + m_xRbNewObject->connect_clicked( aLink ); + m_xRbObjectFromfile->connect_clicked( aLink ); + m_xRbNewObject->set_active(true); +} + +short SvInsertOleDlg::run() +{ + short nRet = RET_OK; + SvObjectServerList aObjS; + if ( !m_pServers ) + { + // if no list was provided, take the complete one + aObjS.FillInsertObjects(); + m_pServers = &aObjS; + } + + // fill listbox and select default + m_xLbObjecttype->freeze(); + for ( sal_uLong i = 0; i < m_pServers->Count(); i++ ) + m_xLbObjecttype->append_text((*m_pServers)[i].GetHumanName()); + m_xLbObjecttype->thaw(); + m_xLbObjecttype->select(0); + OUString aName; + + DBG_ASSERT( m_xStorage.is(), "No storage!"); + if ( m_xStorage.is() && ( nRet = InsertObjectDialog_Impl::run() ) == RET_OK ) + { + OUString aFileName; + bool bCreateNew = IsCreateNew(); + if ( bCreateNew ) + { + // create and insert new embedded object + OUString aServerName = m_xLbObjecttype->get_selected_text(); + const SvObjectServer* pS = m_pServers->Get( aServerName ); + if ( pS ) + { + if( pS->GetClassName() == SvGlobalName( SO3_OUT_CLASSID ) ) + { + try + { + uno::Reference < embed::XInsertObjectDialog > xDialogCreator( + embed::MSOLEObjectSystemCreator::create( ::comphelper::getProcessComponentContext() ), + uno::UNO_QUERY ); + + if ( xDialogCreator.is() ) + { + aName = aCnt.CreateUniqueObjectName(); + const embed::InsertedObjectInfo aNewInf = xDialogCreator->createInstanceByDialog( + m_xStorage, + aName, + uno::Sequence < beans::PropertyValue >() ); + + OSL_ENSURE( aNewInf.Object.is(), "The object must be created or an exception must be thrown!" ); + m_xObj = aNewInf.Object; + for ( const auto& opt : aNewInf.Options ) + if ( opt.Name == "Icon" ) + { + opt.Value >>= m_aIconMetaFile; + } + else if ( opt.Name == "IconFormat" ) + { + datatransfer::DataFlavor aFlavor; + if ( opt.Value >>= aFlavor ) + m_aIconMediaType = aFlavor.MimeType; + } + + } + } + catch( ucb::CommandAbortedException& ) + { + // the user has pressed cancel + } + catch( uno::Exception& ) + { + // TODO: Error handling + } + } + else + { + // create object with desired ClassId + m_xObj = aCnt.CreateEmbeddedObject( pS->GetClassName().GetByteSequence(), aName ); + } + + if ( !m_xObj.is() ) + { + if( !aFileName.isEmpty() ) // from OLE Dialog + { + // object couldn't be created from file + // global Resource from svtools (former so3 resource) + OUString aErr(SvtResId(STR_ERROR_OBJNOCREATE_FROM_FILE)); + aErr = aErr.replaceFirst( "%", aFileName ); + + std::unique_ptr xBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Warning, VclButtonsType::Ok, aErr)); + xBox->run(); + } + else + { + // object couldn't be created + // global Resource from svtools (former so3 resource) + OUString aErr(SvtResId(STR_ERROR_OBJNOCREATE)); + aErr = aErr.replaceFirst( "%", aServerName ); + + std::unique_ptr xBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Warning, VclButtonsType::Ok, aErr)); + xBox->run(); + } + } + } + } + else + { + aFileName = m_xEdFilepath->get_text(); + INetURLObject aURL; + aURL.SetSmartProtocol( INetProtocol::File ); + aURL.SetSmartURL( aFileName ); + aFileName = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ); + bool bLink = m_xCbFilelink->get_active(); + + if ( !aFileName.isEmpty() ) + { + // create MediaDescriptor for file to create object from + uno::Sequence < beans::PropertyValue > aMedium( 2 ); + aMedium[0].Name = "URL"; + aMedium[0].Value <<= aFileName; + + uno::Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext(); + uno::Reference< task::XInteractionHandler2 > xInteraction( + task::InteractionHandler::createWithParent(xContext, nullptr) ); + + aMedium[1].Name = "InteractionHandler"; + aMedium[1].Value <<= xInteraction; + + // create object from media descriptor + if ( bLink ) + m_xObj = aCnt.InsertEmbeddedLink( aMedium, aName ); + else + m_xObj = aCnt.InsertEmbeddedObject( aMedium, aName ); + } + + if ( !m_xObj.is() ) + { + // object couldn't be created from file + // global Resource from svtools (former so3 resource) + OUString aErr(SvtResId(STR_ERROR_OBJNOCREATE_FROM_FILE)); + aErr = aErr.replaceFirst( "%", aFileName ); + + std::unique_ptr xBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Warning, VclButtonsType::Ok, aErr)); + xBox->run(); + } + else + { + if (m_xCbAsIcon->get_active()) + { + //something nice here I guess would be to write the filename into + //the image with this icon above it + Image aImage = SvFileInformationManager::GetImage(aURL, true); + SvMemoryStream aTemp; + WriteDIBBitmapEx(aImage.GetBitmapEx(), aTemp); + m_aIconMetaFile = Sequence(static_cast(aTemp.GetData()), aTemp.TellEnd()); + m_aIconMediaType = "application/x-openoffice-bitmap;windows_formatname=\"Bitmap\""; + } + } + } + } + + m_pServers = nullptr; + return nRet; +} + +uno::Reference< io::XInputStream > SvInsertOleDlg::GetIconIfIconified( OUString* pGraphicMediaType ) +{ + if ( m_aIconMetaFile.hasElements() ) + { + if ( pGraphicMediaType ) + *pGraphicMediaType = m_aIconMediaType; + + return uno::Reference< io::XInputStream >( new ::comphelper::SequenceInputStream( m_aIconMetaFile ) ); + } + + return uno::Reference< io::XInputStream >(); +} + + +SfxInsertFloatingFrameDialog::SfxInsertFloatingFrameDialog(weld::Window *pParent, + const css::uno::Reference < css::embed::XStorage >& xStorage) + : InsertObjectDialog_Impl(pParent, "cui/ui/insertfloatingframe.ui", "InsertFloatingFrameDialog", + xStorage) +{ + Init(); +} + +SfxInsertFloatingFrameDialog::SfxInsertFloatingFrameDialog(weld::Window *pParent, + const uno::Reference < embed::XEmbeddedObject >& xObj) + : InsertObjectDialog_Impl(pParent, "cui/ui/insertfloatingframe.ui", "InsertFloatingFrameDialog", + uno::Reference()) +{ + m_xObj = xObj; + + Init(); +} + +void SfxInsertFloatingFrameDialog::Init() +{ + m_xEDName = m_xBuilder->weld_entry("edname"); + m_xEDURL = m_xBuilder->weld_entry("edurl"); + m_xBTOpen = m_xBuilder->weld_button("buttonbrowse"); + m_xRBScrollingOn = m_xBuilder->weld_radio_button("scrollbaron"); + m_xRBScrollingOff = m_xBuilder->weld_radio_button("scrollbaroff"); + m_xRBScrollingAuto = m_xBuilder->weld_radio_button("scrollbarauto"); + m_xRBFrameBorderOn = m_xBuilder->weld_radio_button("borderon"); + m_xRBFrameBorderOff = m_xBuilder->weld_radio_button("borderoff"); + m_xFTMarginWidth = m_xBuilder->weld_label("widthlabel"); + m_xNMMarginWidth = m_xBuilder->weld_spin_button("width"); + m_xCBMarginWidthDefault = m_xBuilder->weld_check_button("defaultwidth"); + m_xFTMarginHeight = m_xBuilder->weld_label("heightlabel"); + m_xNMMarginHeight = m_xBuilder->weld_spin_button("height"); + m_xCBMarginHeightDefault = m_xBuilder->weld_check_button("defaultheight"); + + Link aLink(LINK(this, SfxInsertFloatingFrameDialog, CheckHdl)); + m_xCBMarginWidthDefault->connect_clicked(aLink); + m_xCBMarginHeightDefault->connect_clicked(aLink); + + m_xCBMarginWidthDefault->set_active(true); + m_xCBMarginHeightDefault->set_active(true); + m_xRBScrollingAuto->set_active(true); + m_xRBFrameBorderOn->set_active(true); + + m_xBTOpen->connect_clicked(LINK(this, SfxInsertFloatingFrameDialog, OpenHdl)); +} + +short SfxInsertFloatingFrameDialog::run() +{ + short nRet = RET_OK; + bool bOK = false; + uno::Reference < beans::XPropertySet > xSet; + if ( m_xObj.is() ) + { + try + { + if ( m_xObj->getCurrentState() == embed::EmbedStates::LOADED ) + m_xObj->changeState( embed::EmbedStates::RUNNING ); + xSet.set( m_xObj->getComponent(), uno::UNO_QUERY ); + OUString aStr; + uno::Any aAny = xSet->getPropertyValue( "FrameURL" ); + if ( aAny >>= aStr ) + m_xEDURL->set_text( aStr ); + aAny = xSet->getPropertyValue( "FrameName" ); + if ( aAny >>= aStr ) + m_xEDName->set_text(aStr); + + sal_Int32 nSize = SIZE_NOT_SET; + aAny = xSet->getPropertyValue( "FrameMarginWidth" ); + aAny >>= nSize; + + if ( nSize == SIZE_NOT_SET ) + { + m_xCBMarginWidthDefault->set_active(true); + m_xNMMarginWidth->set_text(OUString::number(DEFAULT_MARGIN_WIDTH)); + m_xFTMarginWidth->set_sensitive(false); + m_xNMMarginWidth->set_sensitive(false); + } + else + m_xNMMarginWidth->set_text(OUString::number(nSize)); + + aAny = xSet->getPropertyValue( "FrameMarginHeight" ); + aAny >>= nSize; + + if ( nSize == SIZE_NOT_SET ) + { + m_xCBMarginHeightDefault->set_active(true); + m_xNMMarginHeight->set_text(OUString::number(DEFAULT_MARGIN_HEIGHT)); + m_xFTMarginHeight->set_sensitive(false); + m_xNMMarginHeight->set_sensitive(false); + } + else + m_xNMMarginHeight->set_text(OUString::number(nSize)); + + bool bScrollOn = false; + bool bScrollOff = false; + bool bScrollAuto = false; + + bool bSet = false; + aAny = xSet->getPropertyValue( "FrameIsAutoScroll" ); + aAny >>= bSet; + if ( !bSet ) + { + aAny = xSet->getPropertyValue( "FrameIsScrollingMode" ); + aAny >>= bSet; + bScrollOn = bSet; + bScrollOff = !bSet; + } + else + bScrollAuto = true; + + m_xRBScrollingOn->set_sensitive(bScrollOn); + m_xRBScrollingOff->set_sensitive(bScrollOff); + m_xRBScrollingAuto->set_sensitive(bScrollAuto); + + bSet = false; + aAny = xSet->getPropertyValue( "FrameIsAutoBorder" ); + aAny >>= bSet; + if ( !bSet ) + { + aAny = xSet->getPropertyValue( "FrameIsBorder" ); + aAny >>= bSet; + m_xRBFrameBorderOn->set_active(bSet); + m_xRBFrameBorderOff->set_active(!bSet); + } + + bOK = true; + } + catch ( uno::Exception& ) + { + OSL_FAIL( "No IFrame!" ); + } + } + else + { + DBG_ASSERT( m_xStorage.is(), "No storage!"); + bOK = m_xStorage.is(); + } + + if (!bOK) + return RET_OK; + + nRet = InsertObjectDialog_Impl::run(); + if ( nRet == RET_OK ) + { + OUString aURL; + if (!m_xEDURL->get_text().isEmpty()) + { + // URL can be a valid and absolute URL or a system file name + INetURLObject aObj; + aObj.SetSmartProtocol( INetProtocol::File ); + if ( aObj.SetSmartURL( m_xEDURL->get_text() ) ) + aURL = aObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ); + } + + if ( !m_xObj.is() && !aURL.isEmpty() ) + { + // create the object + OUString aName; + SvGlobalName aClassId( SO3_IFRAME_CLASSID ); + m_xObj = aCnt.CreateEmbeddedObject( aClassId.GetByteSequence(), aName ); + if ( m_xObj->getCurrentState() == embed::EmbedStates::LOADED ) + m_xObj->changeState( embed::EmbedStates::RUNNING ); + xSet.set( m_xObj->getComponent(), uno::UNO_QUERY ); + } + + if ( m_xObj.is() ) + { + try + { + bool bIPActive = m_xObj->getCurrentState() == embed::EmbedStates::INPLACE_ACTIVE; + if ( bIPActive ) + m_xObj->changeState( embed::EmbedStates::RUNNING ); + + OUString aName = m_xEDName->get_text(); + ScrollingMode eScroll = ScrollingMode::No; + if (m_xRBScrollingOn->get_active()) + eScroll = ScrollingMode::Yes; + if (m_xRBScrollingOff->get_active()) + eScroll = ScrollingMode::No; + if (m_xRBScrollingAuto->get_active()) + eScroll = ScrollingMode::Auto; + + bool bHasBorder = m_xRBFrameBorderOn->get_active(); + + long lMarginWidth; + if (!m_xCBMarginWidthDefault->get_active()) + lMarginWidth = static_cast(m_xNMMarginWidth->get_text().toInt32()); + else + lMarginWidth = SIZE_NOT_SET; + + long lMarginHeight; + if (!m_xCBMarginHeightDefault->get_active()) + lMarginHeight = static_cast(m_xNMMarginHeight->get_text().toInt32()); + else + lMarginHeight = SIZE_NOT_SET; + + xSet->setPropertyValue( "FrameURL", Any( aURL ) ); + xSet->setPropertyValue( "FrameName", Any( aName ) ); + + if ( eScroll == ScrollingMode::Auto ) + xSet->setPropertyValue( "FrameIsAutoScroll", Any( true ) ); + else + xSet->setPropertyValue( "FrameIsScrollingMode", Any( eScroll == ScrollingMode::Yes ) ); + + xSet->setPropertyValue( "FrameIsBorder", Any( bHasBorder ) ); + xSet->setPropertyValue( "FrameMarginWidth", Any( sal_Int32( lMarginWidth ) ) ); + xSet->setPropertyValue( "FrameMarginHeight", Any( sal_Int32( lMarginHeight ) ) ); + + if ( bIPActive ) + m_xObj->changeState( embed::EmbedStates::INPLACE_ACTIVE ); + } + catch ( uno::Exception& ) + { + OSL_FAIL( "No IFrame!" ); + } + } + } + + return nRet; +} + +IMPL_LINK(SfxInsertFloatingFrameDialog, CheckHdl, weld::Button&, rButton, void) +{ + weld::CheckButton& rCB = dynamic_cast(rButton); + if (&rCB == m_xCBMarginWidthDefault.get()) + { + if (rCB.get_active()) + m_xNMMarginWidth->set_text(OUString::number(DEFAULT_MARGIN_WIDTH)); + m_xFTMarginWidth->set_sensitive(!rCB.get_active()); + m_xNMMarginWidth->set_sensitive(!rCB.get_active()); + } + + if (&rCB == m_xCBMarginHeightDefault.get()) + { + if (rCB.get_active()) + m_xNMMarginHeight->set_text(OUString::number(DEFAULT_MARGIN_HEIGHT)); + m_xFTMarginHeight->set_sensitive(!rCB.get_active()); + m_xNMMarginHeight->set_sensitive(!rCB.get_active()); + } +} + +IMPL_LINK_NOARG( SfxInsertFloatingFrameDialog, OpenHdl, weld::Button&, void) +{ + // create the file dialog + sfx2::FileDialogHelper aFileDlg( + ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE, FileDialogFlags::NONE, OUString(), + SfxFilterFlags::NONE, SfxFilterFlags::NONE, m_xDialog.get()); + + // set the title + aFileDlg.SetTitle(CuiResId(RID_SVXSTR_SELECT_FILE_IFRAME)); + + // show the dialog + if ( aFileDlg.Execute() == ERRCODE_NONE ) + m_xEDURL->set_text(INetURLObject(aFileDlg.GetPath()).GetMainURL(INetURLObject::DecodeMechanism::WithCharset)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/insrc.cxx b/cui/source/dialogs/insrc.cxx new file mode 100644 index 000000000..862963275 --- /dev/null +++ b/cui/source/dialogs/insrc.cxx @@ -0,0 +1,59 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include + +bool SvxInsRowColDlg::isInsertBefore() const +{ + return !m_xAfterBtn->get_active(); +} + +sal_uInt16 SvxInsRowColDlg::getInsertCount() const +{ + return m_xCountEdit->get_value(); +} + +SvxInsRowColDlg::SvxInsRowColDlg(weld::Window* pParent, bool bColumn, const OString& rHelpId) + : GenericDialogController(pParent, "cui/ui/insertrowcolumn.ui", "InsertRowColumnDialog") + , m_xCountEdit(m_xBuilder->weld_spin_button("insert_number")) + , m_xBeforeBtn(m_xBuilder->weld_radio_button("insert_before")) + , m_xAfterBtn(m_xBuilder->weld_radio_button("insert_after")) +{ + m_xDialog->set_title(bColumn ? CuiResId(RID_SVXSTR_COL) : CuiResId(RID_SVXSTR_ROW)); + + // tdf#119293 + if (bColumn) { + m_xBeforeBtn->set_label(CuiResId(RID_SVXSTR_INSERTCOL_BEFORE)); + m_xAfterBtn->set_label(CuiResId(RID_SVXSTR_INSERTCOL_AFTER)); + } else { + m_xBeforeBtn->set_label(CuiResId(RID_SVXSTR_INSERTROW_BEFORE)); + m_xAfterBtn->set_label(CuiResId(RID_SVXSTR_INSERTROW_AFTER)); + } + + m_xDialog->set_help_id(rHelpId); +} + +short SvxInsRowColDlg::Execute() +{ + return run(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/linkdlg.cxx b/cui/source/dialogs/linkdlg.cxx new file mode 100644 index 000000000..764d29e0c --- /dev/null +++ b/cui/source/dialogs/linkdlg.cxx @@ -0,0 +1,636 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + + +using namespace sfx2; +using namespace ::com::sun::star; + +namespace { + +class SvBaseLinkMemberList { +private: + std::vector mLinks; + +public: + ~SvBaseLinkMemberList() + { + for (auto const& link : mLinks) + { + if( link ) + link->ReleaseRef(); + } + } + + size_t size() const { return mLinks.size(); } + + SvBaseLink *operator[](size_t i) const { return mLinks[i]; } + + void push_back(SvBaseLink* p) + { + mLinks.push_back(p); + p->AddFirstRef(); + } +}; + +} + +SvBaseLinksDlg::SvBaseLinksDlg(weld::Window * pParent, LinkManager* pMgr, bool bHtmlMode) + : GenericDialogController(pParent, "cui/ui/baselinksdialog.ui", "BaseLinksDialog") + , aStrAutolink( CuiResId( STR_AUTOLINK ) ) + , aStrManuallink( CuiResId( STR_MANUALLINK ) ) + , aStrBrokenlink( CuiResId( STR_BROKENLINK ) ) + , aStrCloselinkmsg( CuiResId( STR_CLOSELINKMSG ) ) + , aStrCloselinkmsgMulti( CuiResId( STR_CLOSELINKMSG_MULTI ) ) + , aStrWaitinglink( CuiResId( STR_WAITINGLINK ) ) + , pLinkMgr( nullptr ) + , aUpdateIdle("cui SvBaseLinksDlg UpdateIdle") + , m_xTbLinks(m_xBuilder->weld_tree_view("TB_LINKS")) + , m_xFtFullFileName(m_xBuilder->weld_link_button("FULL_FILE_NAME")) + , m_xFtFullSourceName(m_xBuilder->weld_label("FULL_SOURCE_NAME")) + , m_xFtFullTypeName(m_xBuilder->weld_label("FULL_TYPE_NAME")) + , m_xRbAutomatic(m_xBuilder->weld_radio_button("AUTOMATIC")) + , m_xRbManual(m_xBuilder->weld_radio_button("MANUAL")) + , m_xPbUpdateNow(m_xBuilder->weld_button("UPDATE_NOW")) + , m_xPbChangeSource(m_xBuilder->weld_button("CHANGE_SOURCE")) + , m_xPbBreakLink(m_xBuilder->weld_button("BREAK_LINK")) + , m_xVirDev(VclPtr::Create()) +{ + // expand the point size of the desired font to the equivalent pixel size + if (vcl::Window* pDefaultDevice = dynamic_cast(Application::GetDefaultDevice())) + pDefaultDevice->SetPointFont(*m_xVirDev, m_xTbLinks->get_font()); + m_xTbLinks->set_size_request(m_xTbLinks->get_approximate_digit_width() * 90, + m_xTbLinks->get_height_rows(12)); + + m_xTbLinks->set_selection_mode(SelectionMode::Multiple); + + std::vector aWidths; + aWidths.push_back(m_xTbLinks->get_approximate_digit_width() * 30); + aWidths.push_back(m_xTbLinks->get_approximate_digit_width() * 20); + aWidths.push_back(m_xTbLinks->get_approximate_digit_width() * 20); + m_xTbLinks->set_column_fixed_widths(aWidths); + + // UpdateTimer for DDE-/Grf-links, which are waited for + aUpdateIdle.SetInvokeHandler( LINK( this, SvBaseLinksDlg, UpdateWaitingHdl ) ); + aUpdateIdle.SetPriority( TaskPriority::LOWEST ); + + m_xTbLinks->connect_changed( LINK( this, SvBaseLinksDlg, LinksSelectHdl ) ); + m_xTbLinks->connect_row_activated( LINK( this, SvBaseLinksDlg, LinksDoubleClickHdl ) ); + m_xRbAutomatic->connect_clicked( LINK( this, SvBaseLinksDlg, AutomaticClickHdl ) ); + m_xRbManual->connect_clicked( LINK( this, SvBaseLinksDlg, ManualClickHdl ) ); + m_xPbUpdateNow->connect_clicked( LINK( this, SvBaseLinksDlg, UpdateNowClickHdl ) ); + m_xPbChangeSource->connect_clicked( LINK( this, SvBaseLinksDlg, ChangeSourceClickHdl ) ); + if(!bHtmlMode) + m_xPbBreakLink->connect_clicked( LINK( this, SvBaseLinksDlg, BreakLinkClickHdl ) ); + else + m_xPbBreakLink->hide(); + + SetManager( pMgr ); +} + +SvBaseLinksDlg::~SvBaseLinksDlg() +{ +} + +/************************************************************************* +|* SvBaseLinksDlg::Handler() +*************************************************************************/ +IMPL_LINK(SvBaseLinksDlg, LinksSelectHdl, weld::TreeView&, rTreeView, void) +{ + LinksSelectHdl(&rTreeView); +} + +void SvBaseLinksDlg::LinksSelectHdl(weld::TreeView* pSvTabListBox) +{ + const int nSelectionCount = pSvTabListBox ? + pSvTabListBox->count_selected_rows() : 0; + if (nSelectionCount > 1) + { + // possibly deselect old entries in case of multi-selection + int nSelEntry = pSvTabListBox->get_selected_index(); + SvBaseLink* pLink = reinterpret_cast(pSvTabListBox->get_id(nSelEntry).toInt64()); + SvBaseLinkObjectType nObjectType = pLink->GetObjType(); + if(!isClientFileType(nObjectType)) + { + pSvTabListBox->unselect_all(); + pSvTabListBox->select(nSelEntry); + } + else + { + std::vector aRows = pSvTabListBox->get_selected_rows(); + for (auto nEntry : aRows) + { + pLink = reinterpret_cast(pSvTabListBox->get_id(nEntry).toInt64()); + DBG_ASSERT(pLink, "Where is the Link?"); + if (!pLink) + continue; + if( !isClientFileType(pLink->GetObjType()) ) + pSvTabListBox->unselect(nEntry); + } + } + + m_xPbUpdateNow->set_sensitive(true); + m_xRbAutomatic->set_sensitive(false); + m_xRbManual->set_active(true); + m_xRbManual->set_sensitive(false); + } + else + { + int nPos; + SvBaseLink* pLink = GetSelEntry( &nPos ); + if( !pLink ) + return; + + m_xPbUpdateNow->set_sensitive(true); + + OUString sType, sLink; + OUString *pLinkNm = &sLink, *pFilter = nullptr; + + if( isClientFileType(pLink->GetObjType()) ) + { + m_xRbAutomatic->set_sensitive(false); + m_xRbManual->set_active(true); + m_xRbManual->set_sensitive(false); + if( SvBaseLinkObjectType::ClientGraphic == pLink->GetObjType() ) + { + pLinkNm = nullptr; + pFilter = &sLink; + } + } + else + { + m_xRbAutomatic->set_sensitive(true); + m_xRbManual->set_sensitive(true); + + if( SfxLinkUpdateMode::ALWAYS == pLink->GetUpdateMode() ) + m_xRbAutomatic->set_active(true); + else + m_xRbManual->set_active(true); + } + + OUString aFileName; + sfx2::LinkManager::GetDisplayNames( pLink, &sType, &aFileName, pLinkNm, pFilter ); + aFileName = INetURLObject::decode(aFileName, INetURLObject::DecodeMechanism::Unambiguous); + m_xFtFullFileName->set_label( aFileName ); + m_xFtFullFileName->set_uri( aFileName ); + m_xFtFullSourceName->set_label( sLink ); + m_xFtFullTypeName->set_label( sType ); + } +} + +IMPL_LINK_NOARG( SvBaseLinksDlg, LinksDoubleClickHdl, weld::TreeView&, bool ) +{ + ChangeSourceClickHdl(*m_xPbChangeSource); + return true; +} + +IMPL_LINK_NOARG( SvBaseLinksDlg, AutomaticClickHdl, weld::Button&, void ) +{ + int nPos; + SvBaseLink* pLink = GetSelEntry( &nPos ); + if( pLink && !isClientFileType( pLink->GetObjType() ) && + SfxLinkUpdateMode::ALWAYS != pLink->GetUpdateMode() ) + SetType( *pLink, nPos, SfxLinkUpdateMode::ALWAYS ); +} + +IMPL_LINK_NOARG( SvBaseLinksDlg, ManualClickHdl, weld::Button&, void ) +{ + int nPos; + SvBaseLink* pLink = GetSelEntry( &nPos ); + if( pLink && !isClientFileType( pLink->GetObjType() ) && + SfxLinkUpdateMode::ONCALL != pLink->GetUpdateMode()) + SetType( *pLink, nPos, SfxLinkUpdateMode::ONCALL ); +} + +IMPL_LINK_NOARG(SvBaseLinksDlg, UpdateNowClickHdl, weld::Button&, void) +{ + std::vector< SvBaseLink* > aLnkArr; + std::vector< sal_Int16 > aPosArr; + + std::vector aRows = m_xTbLinks->get_selected_rows(); + for (int nFndPos : aRows) + { + aLnkArr.push_back( reinterpret_cast( m_xTbLinks->get_id(nFndPos).toInt64() ) ); + aPosArr.push_back( nFndPos ); + } + + if( aLnkArr.empty() ) + return; + + for( size_t n = 0; n < aLnkArr.size(); ++n ) + { + tools::SvRef xLink = aLnkArr[ n ]; + + // first look for the entry in the array + for(const auto & i : pLinkMgr->GetLinks()) + if( xLink == i ) + { + SetType( *xLink, aPosArr[ n ], xLink->GetUpdateMode() ); + break; + } + } + + // if somebody is of the opinion to swap his links (SD) + LinkManager* pNewMgr = pLinkMgr; + pLinkMgr = nullptr; + SetManager( pNewMgr ); + + + OUString sId = OUString::number(reinterpret_cast(aLnkArr[0])); + int nE = m_xTbLinks->find_id(sId); + if (nE == -1) + nE = m_xTbLinks->get_selected_index(); + int nSelEntry = m_xTbLinks->get_selected_index(); + if (nE != nSelEntry) + m_xTbLinks->unselect(nSelEntry); + m_xTbLinks->select(nE); + m_xTbLinks->scroll_to_row(nE); + + pNewMgr->CloseCachedComps(); +} + +IMPL_LINK_NOARG(SvBaseLinksDlg, ChangeSourceClickHdl, weld::Button&, void) +{ + std::vector aRows = m_xTbLinks->get_selected_rows(); + if (aRows.size() > 1) + { + try + { + uno::Reference xFolderPicker = ui::dialogs::FolderPicker::create(comphelper::getProcessComponentContext()); + + OUString sType, sFile, sLinkName; + OUString sFilter; + SvBaseLink* pLink = reinterpret_cast(m_xTbLinks->get_id(aRows[0]).toInt64()); + sfx2::LinkManager::GetDisplayNames( pLink, &sType, &sFile ); + INetURLObject aUrl(sFile); + if(aUrl.GetProtocol() == INetProtocol::File) + { + OUString sOldPath(aUrl.PathToFileName()); + sal_Int32 nLen = aUrl.GetLastName().getLength(); + sOldPath = sOldPath.copy(0, sOldPath.getLength() - nLen); + xFolderPicker->setDisplayDirectory(sOldPath); + } + if (xFolderPicker->execute() == ui::dialogs::ExecutableDialogResults::OK) + { + OUString aPath = xFolderPicker->getDirectory(); + + for (auto nRow : aRows) + { + pLink = reinterpret_cast(m_xTbLinks->get_id(nRow).toInt64()); + DBG_ASSERT(pLink,"Where is the link?"); + if (!pLink) + continue; + sfx2::LinkManager::GetDisplayNames( pLink, &sType, &sFile, &sLinkName, &sFilter ); + INetURLObject aUrl_(sFile); + INetURLObject aUrl2(aPath, INetProtocol::File); + aUrl2.insertName( aUrl_.getName() ); + OUString sNewLinkName; + MakeLnkName( sNewLinkName, nullptr , + aUrl2.GetMainURL(INetURLObject::DecodeMechanism::ToIUri), sLinkName, &sFilter); + pLink->SetLinkSourceName( sNewLinkName ); + pLink->Update(); + } + if( pLinkMgr->GetPersist() ) + pLinkMgr->GetPersist()->SetModified(); + LinkManager* pNewMgr = pLinkMgr; + pLinkMgr = nullptr; + SetManager( pNewMgr ); + } + } + catch (const uno::Exception &) + { + TOOLS_WARN_EXCEPTION("cui.dialogs", "SvBaseLinksDlg"); + } + } + else + { + int nPos; + SvBaseLink* pLink = GetSelEntry( &nPos ); + if ( pLink && !pLink->GetLinkSourceName().isEmpty() ) + pLink->Edit(m_xDialog.get(), LINK(this, SvBaseLinksDlg, EndEditHdl)); + } +} + +IMPL_LINK_NOARG( SvBaseLinksDlg, BreakLinkClickHdl, weld::Button&, void ) +{ + bool bModified = false; + if (m_xTbLinks->count_selected_rows() <= 1) + { + int nPos; + tools::SvRef xLink = GetSelEntry( &nPos ); + if( !xLink.is() ) + return; + + std::unique_ptr xQueryBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Question, VclButtonsType::YesNo, + aStrCloselinkmsg)); + xQueryBox->set_default_response(RET_YES); + + if (RET_YES == xQueryBox->run()) + { + m_xTbLinks->remove(nPos); + + // close object, if it's still existing + bool bNewLnkMgr = SvBaseLinkObjectType::ClientFile == xLink->GetObjType(); + + // tell the link that it will be resolved! + xLink->Closed(); + + // if somebody has forgotten to deregister himself + if( xLink.is() ) + pLinkMgr->Remove( xLink.get() ); + + if( bNewLnkMgr ) + { + LinkManager* pNewMgr = pLinkMgr; + pLinkMgr = nullptr; + SetManager( pNewMgr ); + m_xTbLinks->set_cursor(nPos ? --nPos : 0); + } + bModified = true; + } + } + else + { + std::unique_ptr xQueryBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Question, VclButtonsType::YesNo, + aStrCloselinkmsgMulti)); + xQueryBox->set_default_response(RET_YES); + + if (RET_YES == xQueryBox->run()) + { + std::vector aRows = m_xTbLinks->get_selected_rows(); + SvBaseLinkMemberList aLinkList; + for (auto nRow : aRows) + { + SvBaseLink* pLink = reinterpret_cast(m_xTbLinks->get_id(nRow).toInt64()); + if (pLink) + aLinkList.push_back(pLink); + } + std::sort(aRows.begin(), aRows.end()); + for (auto it = aRows.rbegin(); it != aRows.rend(); ++it) + m_xTbLinks->remove(*it); + for (size_t i = 0; i < aLinkList.size(); ++i) + { + tools::SvRef xLink = aLinkList[i]; + // tell the link that it will be resolved! + xLink->Closed(); + + // if somebody has forgotten to deregister himself + pLinkMgr->Remove( xLink.get() ); + bModified = true; + } + // then remove all selected entries + } + } + if(!bModified) + return; + + if (!m_xTbLinks->n_children()) + { + m_xRbAutomatic->set_sensitive(false); + m_xRbManual->set_sensitive(false); + m_xPbUpdateNow->set_sensitive(false); + m_xPbChangeSource->set_sensitive(false); + m_xPbBreakLink->set_sensitive(false); + + m_xFtFullSourceName->set_label( "" ); + m_xFtFullTypeName->set_label( "" ); + } + if( pLinkMgr && pLinkMgr->GetPersist() ) + pLinkMgr->GetPersist()->SetModified(); +} + +IMPL_LINK_NOARG( SvBaseLinksDlg, UpdateWaitingHdl, Timer*, void ) +{ + m_xTbLinks->freeze(); + for (int nPos = m_xTbLinks->n_children(); nPos; --nPos) + { + tools::SvRef xLink( reinterpret_cast(m_xTbLinks->get_id(nPos).toInt64()) ); + if( xLink.is() ) + { + OUString sCur( ImplGetStateStr( *xLink ) ), + sOld( m_xTbLinks->get_text(nPos, 3) ); + if( sCur != sOld ) + m_xTbLinks->set_text(nPos, sCur, 3); + } + } + m_xTbLinks->thaw(); +} + +IMPL_LINK( SvBaseLinksDlg, EndEditHdl, sfx2::SvBaseLink&, _rLink, void ) +{ + int nPos; + GetSelEntry( &nPos ); + + if( !_rLink.WasLastEditOK() ) + return; + + // StarImpress/Draw swap the LinkObjects themselves! + // So search for the link in the manager; if it does not exist + // anymore, fill the list completely new. Otherwise only the + // edited link needs to be refreshed. + bool bLinkFnd = false; + for( size_t n = pLinkMgr->GetLinks().size(); n; ) + if( &_rLink == &(*pLinkMgr->GetLinks()[ --n ]) ) + { + bLinkFnd = true; + break; + } + + if( bLinkFnd ) + { + m_xTbLinks->remove(nPos); + int nToUnselect = m_xTbLinks->get_selected_index(); + InsertEntry(_rLink, nPos, true); + if (nToUnselect != -1) + m_xTbLinks->unselect(nToUnselect); + } + else + { + LinkManager* pNewMgr = pLinkMgr; + pLinkMgr = nullptr; + SetManager( pNewMgr ); + } + if (pLinkMgr && pLinkMgr->GetPersist()) + pLinkMgr->GetPersist()->SetModified(); +} + +OUString SvBaseLinksDlg::ImplGetStateStr( const SvBaseLink& rLnk ) +{ + OUString sRet; + if( !rLnk.GetObj() ) + sRet = aStrBrokenlink; + else if( rLnk.GetObj()->IsPending() ) + { + sRet = aStrWaitinglink; + aUpdateIdle.Start(); + } + else if( SfxLinkUpdateMode::ALWAYS == rLnk.GetUpdateMode() ) + sRet = aStrAutolink; + else + sRet = aStrManuallink; + + return sRet; +} + +void SvBaseLinksDlg::SetManager( LinkManager* pNewMgr ) +{ + if( pLinkMgr == pNewMgr ) + return; + + if (pNewMgr) + { + // update has to be stopped before clear + m_xTbLinks->freeze(); + } + + m_xTbLinks->clear(); + pLinkMgr = pNewMgr; + + if( !pLinkMgr ) + return; + + SvBaseLinks& rLnks = const_cast(pLinkMgr->GetLinks()); + for( size_t n = 0; n < rLnks.size(); ++n ) + { + tools::SvRef& rLinkRef = rLnks[ n ]; + if( !rLinkRef.is() ) + { + rLnks.erase( rLnks.begin() + n ); + --n; + continue; + } + if( rLinkRef->IsVisible() ) + InsertEntry( *rLinkRef ); + } + + m_xTbLinks->thaw(); + + if( !rLnks.empty() ) + { + m_xTbLinks->set_cursor(0); + m_xTbLinks->select(0); + LinksSelectHdl( nullptr ); + } +} + +void SvBaseLinksDlg::InsertEntry(const SvBaseLink& rLink, int nPos, bool bSelect) +{ + OUString sFileNm, sLinkNm, sTypeNm, sFilter; + + sfx2::LinkManager::GetDisplayNames( &rLink, &sTypeNm, &sFileNm, &sLinkNm, &sFilter ); + + auto nWidthPixel = m_xTbLinks->get_column_width(0); + OUString aTxt = m_xVirDev->GetEllipsisString(sFileNm, nWidthPixel, DrawTextFlags::PathEllipsis); + INetURLObject aPath( sFileNm, INetProtocol::File ); + OUString aFileName = aPath.getName( + INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::Unambiguous); + + if( aFileName.getLength() > aTxt.getLength() ) + aTxt = aFileName; + else if (!aFileName.isEmpty() && aTxt.indexOf(aFileName, aTxt.getLength() - aFileName.getLength()) == -1) + // filename not in string + aTxt = aFileName; + + if (nPos == -1) + nPos = m_xTbLinks->n_children(); + m_xTbLinks->insert(nPos); + m_xTbLinks->set_text(nPos, aTxt, 0); + m_xTbLinks->set_id(nPos, OUString::number(reinterpret_cast(&rLink))); + if( SvBaseLinkObjectType::ClientGraphic == rLink.GetObjType() ) + m_xTbLinks->set_text(nPos, sFilter, 1); + else + m_xTbLinks->set_text(nPos, sLinkNm, 1); + m_xTbLinks->set_text(nPos, sTypeNm, 2); + m_xTbLinks->set_text(nPos, ImplGetStateStr(rLink), 3); + if (bSelect) + m_xTbLinks->select(nPos); +} + +SvBaseLink* SvBaseLinksDlg::GetSelEntry(int* pPos) +{ + int nPos = m_xTbLinks->get_selected_index(); + if (nPos != -1) + { + if (pPos) + *pPos = nPos; + return reinterpret_cast(m_xTbLinks->get_id(nPos).toInt64()); + } + return nullptr; +} + +void SvBaseLinksDlg::SetType(SvBaseLink& rLink, + int nSelPos, + SfxLinkUpdateMode nType) +{ + rLink.SetUpdateMode( nType ); + rLink.Update(); + m_xTbLinks->set_text(nSelPos, ImplGetStateStr(rLink), 3); + if (pLinkMgr->GetPersist()) + pLinkMgr->GetPersist()->SetModified(); +} + +void SvBaseLinksDlg::SetActLink( SvBaseLink const * pLink ) +{ + if( !pLinkMgr ) + return; + + const SvBaseLinks& rLnks = pLinkMgr->GetLinks(); + int nSelect = 0; + for(const auto & rLinkRef : rLnks) + { + // #109573# only visible links have been inserted into the TreeListBox, + // invisible ones have to be skipped here + if( rLinkRef->IsVisible() ) + { + if( pLink == rLinkRef.get() ) + { + m_xTbLinks->select(nSelect); + LinksSelectHdl( nullptr ); + return ; + } + ++nSelect; + } + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/multipat.cxx b/cui/source/dialogs/multipat.cxx new file mode 100644 index 000000000..48dc545f9 --- /dev/null +++ b/cui/source/dialogs/multipat.cxx @@ -0,0 +1,320 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include + +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star::uno; + +IMPL_LINK_NOARG(SvxMultiPathDialog, SelectHdl_Impl, weld::TreeView&, void) +{ + auto nCount = m_xRadioLB->n_children(); + bool bIsSelected = m_xRadioLB->get_selected_index() != -1; + bool bEnable = nCount > 1; + m_xDelBtn->set_sensitive(bEnable && bIsSelected); +} + +IMPL_LINK_NOARG(SvxPathSelectDialog, SelectHdl_Impl, weld::TreeView&, void) +{ + auto nCount = m_xPathLB->n_children(); + bool bIsSelected = m_xPathLB->get_selected_index() != -1; + bool bEnable = nCount > 1; + m_xDelBtn->set_sensitive(bEnable && bIsSelected); +} + +void SvxMultiPathDialog::HandleEntryChecked(int nRow) +{ + m_xRadioLB->select(nRow); + bool bChecked = m_xRadioLB->get_toggle(nRow, 0) == TRISTATE_TRUE; + if (bChecked) + { + // we have radio button behavior -> so uncheck the other entries + int nCount = m_xRadioLB->n_children(); + for (int i = 0; i < nCount; ++i) + { + if (i != nRow) + m_xRadioLB->set_toggle(i, TRISTATE_FALSE, 0); + } + } +} + +IMPL_LINK(SvxMultiPathDialog, CheckHdl_Impl, const row_col&, rRowCol, void) +{ + HandleEntryChecked(rRowCol.first); +} + +void SvxMultiPathDialog::AppendEntry(const OUString& rText, const OUString& rId) +{ + m_xRadioLB->append(); + const int nRow = m_xRadioLB->n_children() - 1; + m_xRadioLB->set_toggle(nRow, TRISTATE_FALSE, 0); + m_xRadioLB->set_text(nRow, rText, 1); + m_xRadioLB->set_id(nRow, rId); +} + +IMPL_LINK_NOARG(SvxMultiPathDialog, AddHdl_Impl, weld::Button&, void) +{ + Reference < XComponentContext > xContext( ::comphelper::getProcessComponentContext() ); + Reference < XFolderPicker2 > xFolderPicker = FolderPicker::create(xContext); + + if ( xFolderPicker->execute() != ExecutableDialogResults::OK ) + return; + + INetURLObject aPath( xFolderPicker->getDirectory() ); + aPath.removeFinalSlash(); + OUString aURL = aPath.GetMainURL( INetURLObject::DecodeMechanism::NONE ); + OUString sInsPath; + osl::FileBase::getSystemPathFromFileURL(aURL, sInsPath); + + if (m_xRadioLB->find_text(sInsPath) != -1) + { + OUString sMsg( CuiResId( RID_MULTIPATH_DBL_ERR ) ); + sMsg = sMsg.replaceFirst( "%1", sInsPath ); + std::unique_ptr xInfoBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Info, VclButtonsType::Ok, sMsg)); + xInfoBox->run(); + } + else + { + AppendEntry(sInsPath, aURL); + } + + SelectHdl_Impl(*m_xRadioLB); +} + +IMPL_LINK_NOARG(SvxPathSelectDialog, AddHdl_Impl, weld::Button&, void) +{ + Reference < XComponentContext > xContext( ::comphelper::getProcessComponentContext() ); + Reference < XFolderPicker2 > xFolderPicker = FolderPicker::create(xContext); + + if ( xFolderPicker->execute() != ExecutableDialogResults::OK ) + return; + + INetURLObject aPath( xFolderPicker->getDirectory() ); + aPath.removeFinalSlash(); + OUString aURL = aPath.GetMainURL( INetURLObject::DecodeMechanism::NONE ); + OUString sInsPath; + osl::FileBase::getSystemPathFromFileURL(aURL, sInsPath); + + if (m_xPathLB->find_text(sInsPath) != -1) + { + OUString sMsg( CuiResId( RID_MULTIPATH_DBL_ERR ) ); + sMsg = sMsg.replaceFirst( "%1", sInsPath ); + std::unique_ptr xInfoBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Info, VclButtonsType::Ok, sMsg)); + xInfoBox->run(); + } + else + { + m_xPathLB->append(aURL, sInsPath); + } + + SelectHdl_Impl(*m_xPathLB); +} + +IMPL_LINK_NOARG(SvxMultiPathDialog, DelHdl_Impl, weld::Button&, void) +{ + int nPos = m_xRadioLB->get_selected_index(); + bool bChecked = m_xRadioLB->get_toggle(nPos, 0) == TRISTATE_TRUE; + m_xRadioLB->remove(nPos); + int nCnt = m_xRadioLB->n_children(); + if (nCnt) + { + --nCnt; + + if ( nPos > nCnt ) + nPos = nCnt; + if (bChecked) + { + m_xRadioLB->set_toggle(nPos, TRISTATE_TRUE, 0); + HandleEntryChecked(nPos); + } + m_xRadioLB->select(nPos); + } + + SelectHdl_Impl(*m_xRadioLB); +} + +IMPL_LINK_NOARG(SvxPathSelectDialog, DelHdl_Impl, weld::Button&, void) +{ + int nPos = m_xPathLB->get_selected_index(); + m_xPathLB->remove(nPos); + int nCnt = m_xPathLB->n_children(); + + if (nCnt) + { + --nCnt; + + if ( nPos > nCnt ) + nPos = nCnt; + m_xPathLB->select(nPos); + } + + SelectHdl_Impl(*m_xPathLB); +} + +SvxMultiPathDialog::SvxMultiPathDialog(weld::Window* pParent) + : GenericDialogController(pParent, "cui/ui/multipathdialog.ui", "MultiPathDialog") + , m_xRadioLB(m_xBuilder->weld_tree_view("paths")) + , m_xAddBtn(m_xBuilder->weld_button("add")) + , m_xDelBtn(m_xBuilder->weld_button("delete")) +{ + m_xRadioLB->set_size_request(m_xRadioLB->get_approximate_digit_width() * 60, + m_xRadioLB->get_text_height() * 10); + + std::vector aWidths; + aWidths.push_back(m_xRadioLB->get_checkbox_column_width()); + m_xRadioLB->set_column_fixed_widths(aWidths); + + std::vector aRadioColumns; + aRadioColumns.push_back(0); + m_xRadioLB->set_toggle_columns_as_radio(aRadioColumns); + m_xRadioLB->connect_toggled(LINK(this, SvxMultiPathDialog, CheckHdl_Impl)); + m_xRadioLB->connect_changed(LINK(this, SvxMultiPathDialog, SelectHdl_Impl)); + m_xAddBtn->connect_clicked(LINK(this, SvxMultiPathDialog, AddHdl_Impl)); + m_xDelBtn->connect_clicked(LINK(this, SvxMultiPathDialog, DelHdl_Impl)); + + SelectHdl_Impl(*m_xRadioLB); +} + +SvxPathSelectDialog::SvxPathSelectDialog(weld::Window* pParent) + : GenericDialogController(pParent, "cui/ui/selectpathdialog.ui", "SelectPathDialog") + , m_xPathLB(m_xBuilder->weld_tree_view("paths")) + , m_xAddBtn(m_xBuilder->weld_button("add")) + , m_xDelBtn(m_xBuilder->weld_button("delete")) +{ + m_xPathLB->set_size_request(m_xPathLB->get_approximate_digit_width() * 60, + m_xPathLB->get_text_height() * 10); + + m_xPathLB->connect_changed(LINK(this, SvxPathSelectDialog, SelectHdl_Impl)); + m_xAddBtn->connect_clicked(LINK(this, SvxPathSelectDialog, AddHdl_Impl)); + m_xDelBtn->connect_clicked(LINK(this, SvxPathSelectDialog, DelHdl_Impl)); + + SelectHdl_Impl(*m_xPathLB); +} + +SvxMultiPathDialog::~SvxMultiPathDialog() +{ +} + +OUString SvxMultiPathDialog::GetPath() const +{ + OUStringBuffer sNewPath; + sal_Unicode cDelim = SVT_SEARCHPATH_DELIMITER; + + OUString sWritable; + for (int i = 0, nCount = m_xRadioLB->n_children(); i < nCount; ++i) + { + if (m_xRadioLB->get_toggle(i, 0) == TRISTATE_TRUE) + sWritable = m_xRadioLB->get_id(i); + else + { + if (!sNewPath.isEmpty()) + sNewPath.append(cDelim); + sNewPath.append(m_xRadioLB->get_id(i)); + } + } + if (!sNewPath.isEmpty()) + sNewPath.append(cDelim); + sNewPath.append(sWritable); + + return sNewPath.makeStringAndClear(); +} + +OUString SvxPathSelectDialog::GetPath() const +{ + OUStringBuffer sNewPath; + + for (int i = 0; i < m_xPathLB->n_children(); ++i) + { + if ( !sNewPath.isEmpty() ) + sNewPath.append(SVT_SEARCHPATH_DELIMITER); + sNewPath.append( m_xPathLB->get_id(i)); + } + + return sNewPath.makeStringAndClear(); +} + +void SvxMultiPathDialog::SetPath( const OUString& rPath ) +{ + if ( !rPath.isEmpty() ) + { + const sal_Unicode cDelim = SVT_SEARCHPATH_DELIMITER; + int nCount = 0; + sal_Int32 nIndex = 0; + do + { + const OUString sPath = rPath.getToken( 0, cDelim, nIndex ); + OUString sSystemPath; + bool bIsSystemPath = + osl::FileBase::getSystemPathFromFileURL(sPath, sSystemPath) == osl::FileBase::E_None; + + const OUString sEntry((bIsSystemPath ? sSystemPath : sPath)); + AppendEntry(sEntry, sPath); + ++nCount; + } + while (nIndex >= 0); + + if (nCount) + { + m_xRadioLB->set_toggle(nCount - 1, TRISTATE_TRUE, 0); + HandleEntryChecked(nCount - 1); + } + } + + SelectHdl_Impl(*m_xRadioLB); +} + +void SvxPathSelectDialog::SetPath(const OUString& rPath) +{ + if ( !rPath.isEmpty() ) + { + sal_Int32 nIndex = 0; + do + { + const OUString sPath = rPath.getToken( 0, SVT_SEARCHPATH_DELIMITER, nIndex ); + OUString sSystemPath; + bool bIsSystemPath = + osl::FileBase::getSystemPathFromFileURL(sPath, sSystemPath) == osl::FileBase::E_None; + + m_xPathLB->append(sPath, bIsSystemPath ? sSystemPath : sPath); + } + while (nIndex >= 0); + } + + SelectHdl_Impl(*m_xPathLB); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/newtabledlg.cxx b/cui/source/dialogs/newtabledlg.cxx new file mode 100644 index 000000000..16e81f8d9 --- /dev/null +++ b/cui/source/dialogs/newtabledlg.cxx @@ -0,0 +1,39 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +SvxNewTableDialog::SvxNewTableDialog(weld::Window* pWindow) + : GenericDialogController(pWindow, "cui/ui/newtabledialog.ui", "NewTableDialog") + , mxNumColumns(m_xBuilder->weld_spin_button("columns")) + , mxNumRows(m_xBuilder->weld_spin_button("rows")) +{ +} + +sal_Int32 SvxNewTableDialog::getRows() const +{ + return sal::static_int_cast< sal_Int32 >( mxNumRows->get_value() ); +} + +sal_Int32 SvxNewTableDialog::getColumns() const +{ + return sal::static_int_cast< sal_Int32 >( mxNumColumns->get_value() ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/passwdomdlg.cxx b/cui/source/dialogs/passwdomdlg.cxx new file mode 100644 index 000000000..250f9e728 --- /dev/null +++ b/cui/source/dialogs/passwdomdlg.cxx @@ -0,0 +1,171 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include + +IMPL_LINK_NOARG(PasswordToOpenModifyDialog, OkBtnClickHdl, weld::Button&, void) +{ + bool bInvalidState = !m_xOpenReadonlyCB->get_active() && + m_xPasswdToOpenED->get_text().isEmpty() && + m_xPasswdToModifyED->get_text().isEmpty(); + if (bInvalidState) + { + std::unique_ptr xErrorBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Warning, VclButtonsType::Ok, + m_bIsPasswordToModify? m_aInvalidStateForOkButton : m_aInvalidStateForOkButton_v2)); + xErrorBox->run(); + } + else // check for mismatched passwords... + { + const bool bToOpenMatch = m_xPasswdToOpenED->get_text() == m_xReenterPasswdToOpenED->get_text(); + const bool bToModifyMatch = m_xPasswdToModifyED->get_text() == m_xReenterPasswdToModifyED->get_text(); + const int nMismatch = (bToOpenMatch? 0 : 1) + (bToModifyMatch? 0 : 1); + if (nMismatch > 0) + { + std::unique_ptr xErrorBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Warning, VclButtonsType::Ok, + nMismatch == 1 ? m_aOneMismatch : m_aTwoMismatch)); + xErrorBox->run(); + + weld::Entry* pEdit = !bToOpenMatch ? m_xPasswdToOpenED.get() : m_xPasswdToModifyED.get(); + weld::Entry* pRepeatEdit = !bToOpenMatch? m_xReenterPasswdToOpenED.get() : m_xReenterPasswdToModifyED.get(); + if (nMismatch == 1) + { + pEdit->set_text( "" ); + pRepeatEdit->set_text( "" ); + } + else if (nMismatch == 2) + { + m_xPasswdToOpenED->set_text( "" ); + m_xReenterPasswdToOpenED->set_text( "" ); + m_xPasswdToModifyED->set_text( "" ); + m_xReenterPasswdToModifyED->set_text( "" ); + } + pEdit->grab_focus(); + } + else + { + m_xDialog->response(RET_OK); + } + } +} + +IMPL_LINK(PasswordToOpenModifyDialog, ChangeHdl, weld::Entry&, rEntry, void) +{ + weld::Label* pIndicator = nullptr; + int nLength = rEntry.get_text().getLength(); + if (&rEntry == m_xPasswdToOpenED.get()) + pIndicator = m_xPasswdToOpenInd.get(); + else if (&rEntry == m_xReenterPasswdToOpenED.get()) + pIndicator = m_xReenterPasswdToOpenInd.get(); + else if (&rEntry == m_xPasswdToModifyED.get()) + pIndicator = m_xPasswdToModifyInd.get(); + else if (&rEntry == m_xReenterPasswdToModifyED.get()) + pIndicator = m_xReenterPasswdToModifyInd.get(); + assert(pIndicator); + pIndicator->set_visible(nLength >= m_nMaxPasswdLen); +} + +PasswordToOpenModifyDialog::PasswordToOpenModifyDialog(weld::Window * pParent, sal_uInt16 nMaxPasswdLen, bool bIsPasswordToModify) + : SfxDialogController(pParent, "cui/ui/password.ui", "PasswordDialog") + , m_xPasswdToOpenED(m_xBuilder->weld_entry("newpassEntry")) + , m_xPasswdToOpenInd(m_xBuilder->weld_label("newpassIndicator")) + , m_xReenterPasswdToOpenED(m_xBuilder->weld_entry("confirmpassEntry")) + , m_xReenterPasswdToOpenInd(m_xBuilder->weld_label("confirmpassIndicator")) + , m_xOptionsExpander(m_xBuilder->weld_expander("expander")) + , m_xOk(m_xBuilder->weld_button("ok")) + , m_xOpenReadonlyCB(m_xBuilder->weld_check_button("readonly")) + , m_xPasswdToModifyFT(m_xBuilder->weld_label("label7")) + , m_xPasswdToModifyED(m_xBuilder->weld_entry("newpassroEntry")) + , m_xPasswdToModifyInd(m_xBuilder->weld_label("newpassroIndicator")) + , m_xReenterPasswdToModifyFT(m_xBuilder->weld_label("label8")) + , m_xReenterPasswdToModifyED(m_xBuilder->weld_entry("confirmropassEntry")) + , m_xReenterPasswdToModifyInd(m_xBuilder->weld_label("confirmropassIndicator")) + , m_aOneMismatch( CuiResId( RID_SVXSTR_ONE_PASSWORD_MISMATCH ) ) + , m_aTwoMismatch( CuiResId( RID_SVXSTR_TWO_PASSWORDS_MISMATCH ) ) + , m_aInvalidStateForOkButton( CuiResId( RID_SVXSTR_INVALID_STATE_FOR_OK_BUTTON ) ) + , m_aInvalidStateForOkButton_v2( CuiResId( RID_SVXSTR_INVALID_STATE_FOR_OK_BUTTON_V2 ) ) + , m_aIndicatorTemplate(CuiResId(RID_SVXSTR_PASSWORD_LEN_INDICATOR).replaceFirst("%1", OUString::number(nMaxPasswdLen))) + , m_nMaxPasswdLen(nMaxPasswdLen) + , m_bIsPasswordToModify( bIsPasswordToModify ) +{ + m_xOk->connect_clicked(LINK(this, PasswordToOpenModifyDialog, OkBtnClickHdl)); + + if (nMaxPasswdLen) + { + m_xPasswdToOpenED->set_max_length( nMaxPasswdLen ); + m_xPasswdToOpenED->connect_changed(LINK(this, PasswordToOpenModifyDialog, ChangeHdl)); + m_xPasswdToOpenInd->set_label(m_aIndicatorTemplate); + m_xReenterPasswdToOpenED->set_max_length( nMaxPasswdLen ); + m_xReenterPasswdToOpenED->connect_changed(LINK(this, PasswordToOpenModifyDialog, ChangeHdl)); + m_xReenterPasswdToOpenInd->set_label(m_aIndicatorTemplate); + m_xPasswdToModifyED->set_max_length( nMaxPasswdLen ); + m_xPasswdToModifyED->connect_changed(LINK(this, PasswordToOpenModifyDialog, ChangeHdl)); + m_xPasswdToModifyInd->set_label(m_aIndicatorTemplate); + m_xReenterPasswdToModifyED->set_max_length( nMaxPasswdLen ); + m_xReenterPasswdToModifyED->connect_changed(LINK(this, PasswordToOpenModifyDialog, ChangeHdl)); + m_xReenterPasswdToModifyInd->set_label(m_aIndicatorTemplate); + } + + m_xPasswdToOpenED->grab_focus(); + + m_xOptionsExpander->set_sensitive(bIsPasswordToModify); + if (!bIsPasswordToModify) + m_xOptionsExpander->hide(); + + m_xOpenReadonlyCB->connect_clicked(LINK(this, PasswordToOpenModifyDialog, ReadonlyOnOffHdl)); + ReadonlyOnOffHdl(*m_xOpenReadonlyCB); +} + +OUString PasswordToOpenModifyDialog::GetPasswordToOpen() const +{ + const bool bPasswdOk = + !m_xPasswdToOpenED->get_text().isEmpty() && + m_xPasswdToOpenED->get_text() == m_xReenterPasswdToOpenED->get_text(); + return bPasswdOk ? m_xPasswdToOpenED->get_text() : OUString(); +} + + +OUString PasswordToOpenModifyDialog::GetPasswordToModify() const +{ + const bool bPasswdOk = + !m_xPasswdToModifyED->get_text().isEmpty() && + m_xPasswdToModifyED->get_text() == m_xReenterPasswdToModifyED->get_text(); + return bPasswdOk ? m_xPasswdToModifyED->get_text() : OUString(); +} + + +bool PasswordToOpenModifyDialog::IsRecommendToOpenReadonly() const +{ + return m_xOpenReadonlyCB->get_active(); +} + +IMPL_LINK_NOARG(PasswordToOpenModifyDialog, ReadonlyOnOffHdl, weld::Button&, void) +{ + bool bEnable = m_xOpenReadonlyCB->get_active(); + m_xPasswdToModifyED->set_sensitive(bEnable); + m_xPasswdToModifyFT->set_sensitive(bEnable); + m_xReenterPasswdToModifyED->set_sensitive(bEnable); + m_xReenterPasswdToModifyFT->set_sensitive(bEnable); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/pastedlg.cxx b/cui/source/dialogs/pastedlg.cxx new file mode 100644 index 000000000..375a966c7 --- /dev/null +++ b/cui/source/dialogs/pastedlg.cxx @@ -0,0 +1,339 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +SvPasteObjectDialog::SvPasteObjectDialog(weld::Window* pParent) + : GenericDialogController(pParent, "cui/ui/pastespecial.ui", "PasteSpecialDialog") + , m_xFtObjectSource(m_xBuilder->weld_label("source")) + , m_xLbInsertList(m_xBuilder->weld_tree_view("list")) + , m_xOKButton(m_xBuilder->weld_button("ok")) +{ + m_xLbInsertList->set_size_request(m_xLbInsertList->get_approximate_digit_width() * 40, + m_xLbInsertList->get_height_rows(6)); + m_xOKButton->set_sensitive(false); + + ObjectLB().connect_changed(LINK(this, SvPasteObjectDialog, SelectHdl)); + ObjectLB().connect_row_activated(LINK( this, SvPasteObjectDialog, DoubleClickHdl)); +} + +void SvPasteObjectDialog::SelectObject() +{ + if (m_xLbInsertList->n_children()) + { + m_xLbInsertList->select(0); + SelectHdl(*m_xLbInsertList); + } +} + +IMPL_LINK_NOARG(SvPasteObjectDialog, SelectHdl, weld::TreeView&, void) +{ + if (!m_xOKButton->get_sensitive()) + m_xOKButton->set_sensitive(true); +} + +IMPL_LINK_NOARG(SvPasteObjectDialog, DoubleClickHdl, weld::TreeView&, bool) +{ + m_xDialog->response(RET_OK); + return true; +} + +/************************************************************************* +|* SvPasteObjectDialog::Insert() +*************************************************************************/ +void SvPasteObjectDialog::Insert( SotClipboardFormatId nFormat, const OUString& rFormatName ) +{ + aSupplementMap.insert( std::make_pair( nFormat, rFormatName ) ); +} + +void SvPasteObjectDialog::InsertUno(const OUString& sCmd, const OUString& sLabel) +{ + aExtraCommand.first = sCmd; + aExtraCommand.second = sLabel; +} + + +void SvPasteObjectDialog::PreGetFormat( const TransferableDataHelper &rHelper ) +{ + //TODO/LATER: why is the Descriptor never used?! + TransferableObjectDescriptor aDesc; + if (rHelper.HasFormat(SotClipboardFormatId::OBJECTDESCRIPTOR)) + { + (void)const_cast(rHelper).GetTransferableObjectDescriptor( + SotClipboardFormatId::OBJECTDESCRIPTOR, aDesc); + } + const DataFlavorExVector* pFormats = &rHelper.GetDataFlavorExVector(); + + // create and fill dialog box + OUString aSourceName, aTypeName; + SvGlobalName aEmptyNm; + + //ObjectLB().SetUpdateMode( false ); + ObjectLB().freeze(); + + DataFlavorExVector::iterator aIter( const_cast(*pFormats).begin() ), + aEnd( const_cast(*pFormats).end() ); + while( aIter != aEnd ) + { + SotClipboardFormatId nFormat = (*aIter++).mnSotId; + + std::map< SotClipboardFormatId, OUString >::iterator itName = + aSupplementMap.find( nFormat ); + + // if there is an "Embed Source" or and "Embedded Object" on the + // Clipboard we read the Description and the Source of this object + // from an accompanied "Object Descriptor" format on the clipboard + // Remember: these formats mostly appear together on the clipboard + OUString aName; + const OUString* pName = nullptr; + if ( itName == aSupplementMap.end() ) + { + SvPasteObjectHelper::GetEmbeddedName(rHelper,aName,aSourceName,nFormat); + if ( !aName.isEmpty() ) + pName = &aName; + } + else + { + pName = &(itName->second); + } + + if( pName ) + { + aName = *pName; + + if( SotClipboardFormatId::EMBED_SOURCE == nFormat ) + { + if( aDesc.maClassName != aEmptyNm ) + { + aSourceName = aDesc.maDisplayName; + + if( aDesc.maClassName == aObjClassName ) + aName = aObjName; + else + aName = aTypeName = aDesc.maTypeName; + } + } + else if( SotClipboardFormatId::LINK_SOURCE == nFormat ) + { + continue; + } + else if( aName.isEmpty() ) + aName = SvPasteObjectHelper::GetSotFormatUIName( nFormat ); + + // Show RICHTEXT only in case RTF is not present. + if (nFormat == SotClipboardFormatId::RICHTEXT && + std::any_of(pFormats->begin(), pFormats->end(), + [](const DataFlavorEx& rFlavor) { + return rFlavor.mnSotId == SotClipboardFormatId::RTF; + })) + { + continue; + } + + if (ObjectLB().find_text(aName) == -1) + { + ObjectLB().append(OUString::number(static_cast(nFormat)), aName); + } + } + } + + if( aTypeName.isEmpty() && aSourceName.isEmpty() ) + { + if( aDesc.maClassName != aEmptyNm ) + { + aSourceName = aDesc.maDisplayName; + aTypeName = aDesc.maTypeName; + } + + if( aTypeName.isEmpty() && aSourceName.isEmpty() ) + { + // global resource from svtools (former so3 resource) + aSourceName = SvtResId(STR_UNKNOWN_SOURCE); + } + } + + ObjectLB().thaw(); + SelectObject(); + + if( !aSourceName.isEmpty() ) + { + if( !aTypeName.isEmpty() ) + aTypeName += "\n"; + + aTypeName += aSourceName; + aTypeName = convertLineEnd(aTypeName, GetSystemLineEnd()); + } + + m_xFtObjectSource->set_label(aTypeName); +} + +SotClipboardFormatId SvPasteObjectDialog::GetFormatOnly() +{ + return static_cast(ObjectLB().get_selected_id().toUInt32()); +} + +SotClipboardFormatId SvPasteObjectDialog::GetFormat( const TransferableDataHelper& rHelper) +{ + //TODO/LATER: why is the Descriptor never used?! + TransferableObjectDescriptor aDesc; + if (rHelper.HasFormat(SotClipboardFormatId::OBJECTDESCRIPTOR)) + { + (void)const_cast(rHelper).GetTransferableObjectDescriptor( + SotClipboardFormatId::OBJECTDESCRIPTOR, aDesc); + } + const DataFlavorExVector* pFormats = &rHelper.GetDataFlavorExVector(); + + // create and fill dialog box + OUString aSourceName, aTypeName; + SotClipboardFormatId nSelFormat = SotClipboardFormatId::NONE; + SvGlobalName aEmptyNm; + + ObjectLB().freeze(); + + for (auto const& format : *pFormats) + { + SotClipboardFormatId nFormat = format.mnSotId; + + std::map< SotClipboardFormatId, OUString >::iterator itName = + aSupplementMap.find( nFormat ); + + // if there is an "Embed Source" or and "Embedded Object" on the + // Clipboard we read the Description and the Source of this object + // from an accompanied "Object Descriptor" format on the clipboard + // Remember: these formats mostly appear together on the clipboard + OUString aName; + const OUString* pName = nullptr; + if ( itName == aSupplementMap.end() ) + { + SvPasteObjectHelper::GetEmbeddedName(rHelper,aName,aSourceName,nFormat); + if ( !aName.isEmpty() ) + pName = &aName; + } + else + { + pName = &(itName->second); + } + + if( pName ) + { + aName = *pName; + + if( SotClipboardFormatId::EMBED_SOURCE == nFormat ) + { + if( aDesc.maClassName != aEmptyNm ) + { + aSourceName = aDesc.maDisplayName; + + if( aDesc.maClassName == aObjClassName ) + aName = aObjName; + else + aName = aTypeName = aDesc.maTypeName; + } + } + else if( SotClipboardFormatId::LINK_SOURCE == nFormat ) + { + continue; + } + else if( aName.isEmpty() ) + aName = SvPasteObjectHelper::GetSotFormatUIName( nFormat ); + + // Show RICHTEXT only in case RTF is not present. + if (nFormat == SotClipboardFormatId::RICHTEXT && + std::any_of(pFormats->begin(), pFormats->end(), + [](const DataFlavorEx& rFlavor) { + return rFlavor.mnSotId == SotClipboardFormatId::RTF; + })) + { + continue; + } + + if (ObjectLB().find_text(aName) == -1) + { + ObjectLB().append(OUString::number(static_cast(nFormat)), aName); + } + } + } + + if( aTypeName.isEmpty() && aSourceName.isEmpty() ) + { + if( aDesc.maClassName != aEmptyNm ) + { + aSourceName = aDesc.maDisplayName; + aTypeName = aDesc.maTypeName; + } + + if( aTypeName.isEmpty() && aSourceName.isEmpty() ) + { + // global resource from svtools (former so3 resource) + aSourceName = SvtResId(STR_UNKNOWN_SOURCE); + } + } + + if (!aExtraCommand.first.isEmpty()) + { + ObjectLB().append(aExtraCommand.first, aExtraCommand.second); + } + + ObjectLB().thaw(); + SelectObject(); + + if( !aSourceName.isEmpty() ) + { + if( !aTypeName.isEmpty() ) + aTypeName += "\n"; + + aTypeName += aSourceName; + aTypeName = convertLineEnd(aTypeName, GetSystemLineEnd()); + } + + m_xFtObjectSource->set_label(aTypeName); + + if (run() == RET_OK) + { + if (ObjectLB().get_selected_id().startsWithIgnoreAsciiCase(".uno")) + { + comphelper::dispatchCommand(aExtraCommand.first, {}); + nSelFormat = SotClipboardFormatId::NONE; + } + else + { + nSelFormat = static_cast(ObjectLB().get_selected_id().toUInt32()); + } + } + + return nSelFormat; +} + +void SvPasteObjectDialog::SetObjName( const SvGlobalName & rClass, const OUString & rObjName ) +{ + aObjClassName = rClass; + aObjName = rObjName; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/postdlg.cxx b/cui/source/dialogs/postdlg.cxx new file mode 100644 index 000000000..b96c1dd85 --- /dev/null +++ b/cui/source/dialogs/postdlg.cxx @@ -0,0 +1,180 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +// class SvxPostItDialog ------------------------------------------------- + +SvxPostItDialog::SvxPostItDialog(weld::Widget* pParent, const SfxItemSet& rCoreSet, + bool bPrevNext) + : SfxDialogController(pParent, "cui/ui/comment.ui", "CommentDialog") + , m_rSet(rCoreSet) + , m_xLastEditFT(m_xBuilder->weld_label("lastedit")) + , m_xAltTitle(m_xBuilder->weld_label("alttitle")) + , m_xEditED(m_xBuilder->weld_text_view("edit")) + , m_xInsertAuthor(m_xBuilder->weld_widget("insertauthor")) + , m_xAuthorBtn(m_xBuilder->weld_button("author")) + , m_xOKBtn(m_xBuilder->weld_button("ok")) + , m_xPrevBtn(m_xBuilder->weld_button("previous")) + , m_xNextBtn(m_xBuilder->weld_button("next")) +{ + m_xPrevBtn->connect_clicked( LINK( this, SvxPostItDialog, PrevHdl ) ); + m_xNextBtn->connect_clicked( LINK( this, SvxPostItDialog, NextHdl ) ); + m_xAuthorBtn->connect_clicked( LINK( this, SvxPostItDialog, Stamp ) ); + m_xOKBtn->connect_clicked( LINK( this, SvxPostItDialog, OKHdl ) ); + + bool bNew = true; + sal_uInt16 nWhich = 0; + + m_xPrevBtn->set_visible(bPrevNext); + m_xNextBtn->set_visible(bPrevNext); + + nWhich = m_rSet.GetPool()->GetWhich( SID_ATTR_POSTIT_AUTHOR ); + OUString aAuthorStr, aDateStr; + + if (m_rSet.GetItemState( nWhich ) >= SfxItemState::DEFAULT) + { + bNew = false; + const SvxPostItAuthorItem& rAuthor = + static_cast(m_rSet.Get(nWhich)); + aAuthorStr = rAuthor.GetValue(); + } + else + aAuthorStr = SvtUserOptions().GetID(); + + nWhich = m_rSet.GetPool()->GetWhich( SID_ATTR_POSTIT_DATE ); + + if (m_rSet.GetItemState( nWhich ) >= SfxItemState::DEFAULT) + { + const SvxPostItDateItem& rDate = + static_cast(m_rSet.Get( nWhich )); + aDateStr = rDate.GetValue(); + } + else + { + const LocaleDataWrapper& rLocaleWrapper( Application::GetSettings().GetLocaleDataWrapper() ); + aDateStr = rLocaleWrapper.getDate( Date( Date::SYSTEM ) ); + } + + nWhich = m_rSet.GetPool()->GetWhich( SID_ATTR_POSTIT_TEXT ); + + OUString aTextStr; + if (m_rSet.GetItemState( nWhich ) >= SfxItemState::DEFAULT) + { + const SvxPostItTextItem& rText = + static_cast(m_rSet.Get( nWhich )); + aTextStr = rText.GetValue(); + } + + ShowLastAuthor(aAuthorStr, aDateStr); + + //lock to an initial size before replacing contents + m_xEditED->set_size_request(m_xEditED->get_approximate_digit_width() * 32, + m_xEditED->get_height_rows(10)); + m_xEditED->set_text(convertLineEnd(aTextStr, GetSystemLineEnd())); + + if (!bNew) + m_xDialog->set_title(m_xAltTitle->get_label()); +} + + +SvxPostItDialog::~SvxPostItDialog() +{ +} + +void SvxPostItDialog::ShowLastAuthor(const OUString& rAuthor, const OUString& rDate) +{ + OUString sTxt = rAuthor + ", " + rDate; + m_xLastEditFT->set_label( sTxt ); +} + +const sal_uInt16* SvxPostItDialog::GetRanges() +{ + static const sal_uInt16 pRanges[] = + { + SID_ATTR_POSTIT_AUTHOR, + SID_ATTR_POSTIT_TEXT, + 0 + }; + return pRanges; +} + +void SvxPostItDialog::EnableTravel(bool bNext, bool bPrev) +{ + m_xPrevBtn->set_sensitive(bPrev); + m_xNextBtn->set_sensitive(bNext); +} + +IMPL_LINK_NOARG(SvxPostItDialog, PrevHdl, weld::Button&, void) +{ + m_aPrevHdlLink.Call( *this ); +} + +IMPL_LINK_NOARG(SvxPostItDialog, NextHdl, weld::Button&, void) +{ + m_aNextHdlLink.Call( *this ); +} + +IMPL_LINK_NOARG(SvxPostItDialog, Stamp, weld::Button&, void) +{ + Date aDate( Date::SYSTEM ); + tools::Time aTime( tools::Time::SYSTEM ); + OUString aTmp( SvtUserOptions().GetID() ); + const LocaleDataWrapper& rLocaleWrapper( Application::GetSettings().GetLocaleDataWrapper() ); + OUString aStr( m_xEditED->get_text() + "\n---- " ); + + if ( !aTmp.isEmpty() ) + { + aStr += aTmp + ", "; + } + aStr += rLocaleWrapper.getDate(aDate) + ", " + rLocaleWrapper.getTime(aTime, false) + " ----\n"; + aStr = convertLineEnd(aStr, GetSystemLineEnd()); + + m_xEditED->set_text(aStr); + sal_Int32 nLen = aStr.getLength(); + m_xEditED->grab_focus(); + m_xEditED->select_region(nLen, nLen); +} + +IMPL_LINK_NOARG(SvxPostItDialog, OKHdl, weld::Button&, void) +{ + const LocaleDataWrapper& rLocaleWrapper( Application::GetSettings().GetLocaleDataWrapper() ); + m_xOutSet.reset(new SfxItemSet(m_rSet)); + m_xOutSet->Put( SvxPostItAuthorItem(SvtUserOptions().GetID(), + m_rSet.GetPool()->GetWhich( SID_ATTR_POSTIT_AUTHOR ) ) ); + m_xOutSet->Put( SvxPostItDateItem(rLocaleWrapper.getDate( Date( Date::SYSTEM ) ), + m_rSet.GetPool()->GetWhich( SID_ATTR_POSTIT_DATE ) ) ); + m_xOutSet->Put( SvxPostItTextItem(m_xEditED->get_text(), + m_rSet.GetPool()->GetWhich( SID_ATTR_POSTIT_TEXT ) ) ); + m_xDialog->response(RET_OK); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/screenshotannotationdlg.cxx b/cui/source/dialogs/screenshotannotationdlg.cxx new file mode 100644 index 000000000..4054fa573 --- /dev/null +++ b/cui/source/dialogs/screenshotannotationdlg.cxx @@ -0,0 +1,583 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace com::sun::star; + +namespace +{ + OUString lcl_genRandom( const OUString &rId ) + { + //FIXME: plus timestamp + unsigned int nRand = comphelper::rng::uniform_uint_distribution(0, 0xFFFF); + return OUString( rId + OUString::number( nRand ) ); + } + + + OUString lcl_AltDescr() + { + OUString aTempl("" + " " //FIXME real dialog title or something + ""); + aTempl = aTempl.replaceFirst( "%1", lcl_genRandom("alt_id") ); + + return aTempl; + } + + OUString lcl_Image( const OUString& rScreenshotId, const Size& rSize ) + { + OUString aTempl("" + "%5" + ""); + aTempl = aTempl.replaceFirst( "%1", lcl_genRandom("img_id") ); + aTempl = aTempl.replaceFirst( "%2", rScreenshotId ); + aTempl = aTempl.replaceFirst( "%3", OUString::number( rSize.Width() ) ); + aTempl = aTempl.replaceFirst( "%4", OUString::number( rSize.Height() ) ); + aTempl = aTempl.replaceFirst( "%5", lcl_AltDescr() ); + + return aTempl; + } + + OUString lcl_ParagraphWithImage( const OUString& rScreenshotId, const Size& rSize ) + { + OUString aTempl( "%2" + "" SAL_NEWLINE_STRING ); + aTempl = aTempl.replaceFirst( "%1", lcl_genRandom("par_id") ); + aTempl = aTempl.replaceFirst( "%2", lcl_Image(rScreenshotId, rSize) ); + + return aTempl; + } + + OUString lcl_Bookmark( const OUString& rWidgetId ) + { + OUString aTempl = "" SAL_NEWLINE_STRING + "" SAL_NEWLINE_STRING; + aTempl = aTempl.replaceFirst( "%1", rWidgetId ); + aTempl = aTempl.replaceFirst( "%2", rWidgetId ); + aTempl = aTempl.replaceFirst( "%3", lcl_genRandom("bm_id") ); + + return aTempl; + } +} + +namespace +{ + class Picture : public weld::CustomWidgetController + { + private: + ScreenshotAnnotationDlg_Impl *m_pDialog; + bool m_bMouseOver; + private: + virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&) override; + virtual bool MouseMove(const MouseEvent& rMouseEvent) override; + virtual bool MouseButtonUp(const MouseEvent& rMouseEvent) override; + public: + Picture(ScreenshotAnnotationDlg_Impl* pDialog) + : m_pDialog(pDialog) + , m_bMouseOver(false) + { + } + + bool IsMouseOver() const + { + return m_bMouseOver; + } + }; +} + +class ScreenshotAnnotationDlg_Impl +{ +public: + ScreenshotAnnotationDlg_Impl( + weld::Window* pParent, + weld::Builder& rParent, + weld::Dialog& rParentDialog); + ~ScreenshotAnnotationDlg_Impl(); + +private: + // Handler for click on save + DECL_LINK(saveButtonHandler, weld::Button&, void); + + // helper methods + weld::ScreenShotEntry* CheckHit(const basegfx::B2IPoint& rPosition); + void PaintScreenShotEntry( + const weld::ScreenShotEntry& rEntry, + const Color& rColor, + double fLineWidth, + double fTransparency); + void RepaintToBuffer( + bool bUseDimmed = false, + bool bPaintHilight = false); + void RepaintPictureElement(); + Point GetOffsetInPicture() const; + + // local variables + weld::Window* mpParentWindow; + weld::Dialog& mrParentDialog; + BitmapEx maParentDialogBitmap; + BitmapEx maDimmedDialogBitmap; + Size maParentDialogSize; + + // VirtualDevice for buffered interaction paints + VclPtr mxVirtualBufferDevice; + + // all detected children + weld::ScreenShotCollection maAllChildren; + + // highlighted/selected children + weld::ScreenShotEntry* mpHilighted; + std::set< weld::ScreenShotEntry* > + maSelected; + + // list of detected controls + Picture maPicture; + std::unique_ptr mxPicture; + std::unique_ptr mxText; + std::unique_ptr mxSave; + + // save as text + OUString maSaveAsText; + OUString maMainMarkupText; + + // folder URL + static OUString maLastFolderURL; +public: + void Paint(vcl::RenderContext& rRenderContext); + bool MouseMove(const MouseEvent& rMouseEvent); + bool MouseButtonUp(); +}; + +OUString ScreenshotAnnotationDlg_Impl::maLastFolderURL = OUString(); + +ScreenshotAnnotationDlg_Impl::ScreenshotAnnotationDlg_Impl( + weld::Window* pParent, + weld::Builder& rParentBuilder, + weld::Dialog& rParentDialog) +: mpParentWindow(pParent), + mrParentDialog(rParentDialog), + mxVirtualBufferDevice(nullptr), + maAllChildren(), + mpHilighted(nullptr), + maSelected(), + maPicture(this), + maSaveAsText(CuiResId(RID_SVXSTR_SAVE_SCREENSHOT_AS)) +{ + VclPtr xParentDialogSurface(VclPtr::Create(DeviceFormat::DEFAULT)); + rParentDialog.draw(*xParentDialogSurface); + maParentDialogSize = xParentDialogSurface->GetOutputSizePixel(); + maParentDialogBitmap = xParentDialogSurface->GetBitmapEx(Point(), maParentDialogSize); + maDimmedDialogBitmap = maParentDialogBitmap; + + // image ain't empty + assert(!maParentDialogBitmap.IsEmpty()); + assert(0 != maParentDialogBitmap.GetSizePixel().Width()); + assert(0 != maParentDialogBitmap.GetSizePixel().Height()); + + // get needed widgets + mxPicture.reset(new weld::CustomWeld(rParentBuilder, "picture", maPicture)); + assert(mxPicture); + mxText = rParentBuilder.weld_text_view("text"); + assert(mxText); + mxSave = rParentBuilder.weld_button("save"); + assert(mxSave); + + // set screenshot image at DrawingArea, resize, set event listener + if (mxPicture) + { + maAllChildren = mrParentDialog.collect_screenshot_data(); + + // to make clear that maParentDialogBitmap is a background image, adjust + // luminance a bit for maDimmedDialogBitmap - other methods may be applied + maDimmedDialogBitmap.Adjust(-15, 0, 0, 0, 0); + + // init paint buffering VirtualDevice + mxVirtualBufferDevice = VclPtr::Create(*Application::GetDefaultDevice(), DeviceFormat::DEFAULT, DeviceFormat::BITMASK); + mxVirtualBufferDevice->SetOutputSizePixel(maParentDialogSize); + mxVirtualBufferDevice->SetFillColor(COL_TRANSPARENT); + + // initially set image for picture control + mxVirtualBufferDevice->DrawBitmapEx(Point(0, 0), maDimmedDialogBitmap); + + // set size for picture control, this will re-layout so that + // the picture control shows the whole dialog + maPicture.SetOutputSizePixel(maParentDialogSize); + mxPicture->set_size_request(maParentDialogSize.Width(), maParentDialogSize.Height()); + + mxPicture->queue_draw(); + } + + // set some test text at VclMultiLineEdit and make read-only - only + // copying content to clipboard is allowed + if (mxText) + { + mxText->set_size_request(400, mxText->get_height_rows(10)); + OUString aHelpId = OStringToOUString( mrParentDialog.get_help_id(), RTL_TEXTENCODING_UTF8 ); + Size aSizeCm = Application::GetDefaultDevice()->PixelToLogic(maParentDialogSize, MapMode(MapUnit::MapCM)); + maMainMarkupText = lcl_ParagraphWithImage( aHelpId, aSizeCm ); + mxText->set_text( maMainMarkupText ); + mxText->set_editable(false); + } + + // set click handler for save button + if (mxSave) + { + mxSave->connect_clicked(LINK(this, ScreenshotAnnotationDlg_Impl, saveButtonHandler)); + } +} + +ScreenshotAnnotationDlg_Impl::~ScreenshotAnnotationDlg_Impl() +{ + mxVirtualBufferDevice.disposeAndClear(); +} + +IMPL_LINK_NOARG(ScreenshotAnnotationDlg_Impl, saveButtonHandler, weld::Button&, void) +{ + // 'save screenshot...' pressed, offer to save maParentDialogBitmap + // as PNG image, use *.id file name as screenshot file name offering + // get a suggestion for the filename from buildable name + OString aDerivedFileName = mrParentDialog.get_buildable_name(); + + auto xFileDlg = std::make_unique(ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION, + FileDialogFlags::NONE, mpParentWindow); + + const uno::Reference< ui::dialogs::XFilePicker3 > xFilePicker = xFileDlg->GetFilePicker(); + + xFilePicker->setTitle(maSaveAsText); + + if (!maLastFolderURL.isEmpty()) + { + xFilePicker->setDisplayDirectory(maLastFolderURL); + } + + xFilePicker->appendFilter("*.png", "*.png"); + xFilePicker->setCurrentFilter("*.png"); + xFilePicker->setDefaultName(OStringToOUString(aDerivedFileName, RTL_TEXTENCODING_UTF8)); + xFilePicker->setMultiSelectionMode(false); + + if (xFilePicker->execute() != ui::dialogs::ExecutableDialogResults::OK) + return; + + maLastFolderURL = xFilePicker->getDisplayDirectory(); + const uno::Sequence< OUString > files(xFilePicker->getSelectedFiles()); + + if (!files.hasElements()) + return; + + OUString aConfirmedName = files[0]; + + if (aConfirmedName.isEmpty()) + return; + + INetURLObject aConfirmedURL(aConfirmedName); + OUString aCurrentExtension(aConfirmedURL.getExtension()); + + if (!aCurrentExtension.isEmpty() && aCurrentExtension != "png") + { + aConfirmedURL.removeExtension(); + aCurrentExtension.clear(); + } + + if (aCurrentExtension.isEmpty()) + { + aConfirmedURL.setExtension("png"); + } + + // open stream + SvFileStream aNew(aConfirmedURL.PathToFileName(), StreamMode::WRITE | StreamMode::TRUNC); + + if (!aNew.IsOpen()) + return; + + // prepare bitmap to save - do use the original screenshot here, + // not the dimmed one + RepaintToBuffer(); + + // extract Bitmap + const BitmapEx aTargetBitmap( + mxVirtualBufferDevice->GetBitmapEx( + Point(0, 0), + mxVirtualBufferDevice->GetOutputSizePixel())); + + // write as PNG + vcl::PNGWriter aPNGWriter(aTargetBitmap); + aPNGWriter.Write(aNew); +} + +weld::ScreenShotEntry* ScreenshotAnnotationDlg_Impl::CheckHit(const basegfx::B2IPoint& rPosition) +{ + weld::ScreenShotEntry* pRetval = nullptr; + + for (auto&& rCandidate : maAllChildren) + { + if (rCandidate.getB2IRange().isInside(rPosition)) + { + if (pRetval) + { + if (pRetval->getB2IRange().isInside(rCandidate.getB2IRange().getMinimum()) + && pRetval->getB2IRange().isInside(rCandidate.getB2IRange().getMaximum())) + { + pRetval = &rCandidate; + } + } + else + { + pRetval = &rCandidate; + } + } + } + + return pRetval; +} + +void ScreenshotAnnotationDlg_Impl::PaintScreenShotEntry( + const weld::ScreenShotEntry& rEntry, + const Color& rColor, + double fLineWidth, + double fTransparency) +{ + if (!(mxPicture && mxVirtualBufferDevice)) + return; + + basegfx::B2DRange aB2DRange(rEntry.getB2IRange()); + + // grow in pixels to be a little bit 'outside'. This also + // ensures that getWidth()/getHeight() ain't 0.0 (see division below) + static const double fGrowTopLeft(1.5); + static const double fGrowBottomRight(0.5); + aB2DRange.expand(aB2DRange.getMinimum() - basegfx::B2DPoint(fGrowTopLeft, fGrowTopLeft)); + aB2DRange.expand(aB2DRange.getMaximum() + basegfx::B2DPoint(fGrowBottomRight, fGrowBottomRight)); + + // edge rounding in pixel. Need to convert, value for + // createPolygonFromRect is relative [0.0 .. 1.0] + static const double fEdgeRoundPixel(8.0); + const basegfx::B2DPolygon aPolygon( + basegfx::utils::createPolygonFromRect( + aB2DRange, + fEdgeRoundPixel / aB2DRange.getWidth(), + fEdgeRoundPixel / aB2DRange.getHeight())); + + mxVirtualBufferDevice->SetLineColor(rColor); + + // try to use transparency + if (!mxVirtualBufferDevice->DrawPolyLineDirect( + basegfx::B2DHomMatrix(), + aPolygon, + fLineWidth, + fTransparency, + nullptr, // MM01 + basegfx::B2DLineJoin::Round)) + { + // no transparency, draw without + mxVirtualBufferDevice->DrawPolyLine( + aPolygon, + fLineWidth); + } +} + +Point ScreenshotAnnotationDlg_Impl::GetOffsetInPicture() const +{ + const Size aPixelSizeTarget(maPicture.GetOutputSizePixel()); + + return Point( + aPixelSizeTarget.Width() > maParentDialogSize.Width() ? (aPixelSizeTarget.Width() - maParentDialogSize.Width()) >> 1 : 0, + aPixelSizeTarget.Height() > maParentDialogSize.Height() ? (aPixelSizeTarget.Height() - maParentDialogSize.Height()) >> 1 : 0); +} + +void ScreenshotAnnotationDlg_Impl::RepaintToBuffer( + bool bUseDimmed, + bool bPaintHilight) +{ + if (!mxVirtualBufferDevice) + return; + + // reset with original screenshot bitmap + mxVirtualBufferDevice->DrawBitmapEx( + Point(0, 0), + bUseDimmed ? maDimmedDialogBitmap : maParentDialogBitmap); + + // get various options + const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer; + const Color aHilightColor(aSvtOptionsDrawinglayer.getHilightColor()); + const double fTransparence(aSvtOptionsDrawinglayer.GetTransparentSelectionPercent() * 0.01); + const bool bIsAntiAliasing(aSvtOptionsDrawinglayer.IsAntiAliasing()); + const AntialiasingFlags nOldAA(mxVirtualBufferDevice->GetAntialiasing()); + + if (bIsAntiAliasing) + { + mxVirtualBufferDevice->SetAntialiasing(AntialiasingFlags::EnableB2dDraw); + } + + // paint selected entries + for (auto&& rCandidate : maSelected) + { + static const double fLineWidthEntries(5.0); + PaintScreenShotEntry(*rCandidate, COL_LIGHTRED, fLineWidthEntries, fTransparence * 0.2); + } + + // paint highlighted entry + if (mpHilighted && bPaintHilight) + { + static const double fLineWidthHilight(7.0); + PaintScreenShotEntry(*mpHilighted, aHilightColor, fLineWidthHilight, fTransparence); + } + + if (bIsAntiAliasing) + { + mxVirtualBufferDevice->SetAntialiasing(nOldAA); + } +} + +void ScreenshotAnnotationDlg_Impl::RepaintPictureElement() +{ + if (mxPicture && mxVirtualBufferDevice) + { + // reset image in buffer, use dimmed version and allow highlight + RepaintToBuffer(true, true); + mxPicture->queue_draw(); + } +} + +void ScreenshotAnnotationDlg_Impl::Paint(vcl::RenderContext& rRenderContext) +{ + Point aPos(GetOffsetInPicture()); + Size aSize(mxVirtualBufferDevice->GetOutputSizePixel()); + rRenderContext.DrawOutDev(aPos, aSize, Point(), aSize, *mxVirtualBufferDevice); +} + +void Picture::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&) +{ + m_pDialog->Paint(rRenderContext); +} + +bool ScreenshotAnnotationDlg_Impl::MouseMove(const MouseEvent& rMouseEvent) +{ + bool bRepaint(false); + + if (maPicture.IsMouseOver()) + { + const weld::ScreenShotEntry* pOldHit = mpHilighted; + const Point aOffset(GetOffsetInPicture()); + const basegfx::B2IPoint aMousePos( + rMouseEvent.GetPosPixel().X() - aOffset.X(), + rMouseEvent.GetPosPixel().Y() - aOffset.Y()); + const weld::ScreenShotEntry* pHit = CheckHit(aMousePos); + + if (pHit && pOldHit != pHit) + { + mpHilighted = const_cast(pHit); + bRepaint = true; + } + } + else if (mpHilighted) + { + mpHilighted = nullptr; + bRepaint = true; + } + + if (bRepaint) + { + RepaintPictureElement(); + } + + return true; +} + +bool Picture::MouseMove(const MouseEvent& rMouseEvent) +{ + if (rMouseEvent.IsEnterWindow()) + m_bMouseOver = true; + if (rMouseEvent.IsLeaveWindow()) + m_bMouseOver = false; + return m_pDialog->MouseMove(rMouseEvent); +} + +bool ScreenshotAnnotationDlg_Impl::MouseButtonUp() +{ + // event in picture frame + bool bRepaint(false); + + if (maPicture.IsMouseOver() && mpHilighted) + { + if (maSelected.erase(mpHilighted) == 0) + { + maSelected.insert(mpHilighted); + } + + OUStringBuffer aBookmarks(maMainMarkupText); + for (auto&& rCandidate : maSelected) + { + OUString aHelpId = OStringToOUString( rCandidate->GetHelpId(), RTL_TEXTENCODING_UTF8 ); + aBookmarks.append(lcl_Bookmark( aHelpId )); + } + + mxText->set_text( aBookmarks.makeStringAndClear() ); + bRepaint = true; + } + + if (bRepaint) + { + RepaintPictureElement(); + } + + return true; +} + +bool Picture::MouseButtonUp(const MouseEvent&) +{ + return m_pDialog->MouseButtonUp(); +} + +ScreenshotAnnotationDlg::ScreenshotAnnotationDlg(weld::Dialog& rParentDialog) + : GenericDialogController(&rParentDialog, "cui/ui/screenshotannotationdialog.ui", "ScreenshotAnnotationDialog") +{ + m_pImpl.reset(new ScreenshotAnnotationDlg_Impl(m_xDialog.get(), *m_xBuilder, rParentDialog)); +} + +ScreenshotAnnotationDlg::~ScreenshotAnnotationDlg() +{ +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/scriptdlg.cxx b/cui/source/dialogs/scriptdlg.cxx new file mode 100644 index 000000000..5319ac680 --- /dev/null +++ b/cui/source/dialogs/scriptdlg.cxx @@ -0,0 +1,1351 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +using namespace ::com::sun::star; +using namespace css::uno; +using namespace css::script; +using namespace css::frame; +using namespace css::document; + +static void ShowErrorDialog( const Any& aException ) +{ + ScopedVclPtrInstance pDlg( aException ); + pDlg->Execute(); +} + +void SvxScriptOrgDialog::delUserData(const weld::TreeIter& rIter) +{ + SFEntry* pUserData = reinterpret_cast(m_xScriptsBox->get_id(rIter).toInt64()); + if (pUserData) + { + delete pUserData; + // TBD seem to get a Select event on node that is remove ( below ) + // so need to be able to detect that this node is not to be + // processed in order to do this, setting userData to NULL ( must + // be a better way to do this ) + m_xScriptsBox->set_id(rIter, OUString()); + } +} + +void SvxScriptOrgDialog::deleteTree(weld::TreeIter& rIter) +{ + delUserData(rIter); + std::unique_ptr xIter = m_xScriptsBox->make_iterator(&rIter); + if (!m_xScriptsBox->iter_children(*xIter)) + return; + + std::unique_ptr xAltIter = m_xScriptsBox->make_iterator(); + bool bNextEntry; + do + { + m_xScriptsBox->copy_iterator(*xIter, *xAltIter); + bNextEntry = m_xScriptsBox->iter_next_sibling(*xAltIter); + deleteTree(*xIter); + m_xScriptsBox->remove(*xIter); + m_xScriptsBox->copy_iterator(*xAltIter, *xIter); + } + while (bNextEntry); +} + +void SvxScriptOrgDialog::deleteAllTree() +{ + std::unique_ptr xIter = m_xScriptsBox->make_iterator(); + if (!m_xScriptsBox->get_iter_first(*xIter)) + return; + + std::unique_ptr xAltIter = m_xScriptsBox->make_iterator(); + // TBD - below is a candidate for a destroyAllTrees method + bool bNextEntry; + do + { + m_xScriptsBox->copy_iterator(*xIter, *xAltIter); + bNextEntry = m_xScriptsBox->iter_next_sibling(*xAltIter); + deleteTree(*xIter); + m_xScriptsBox->remove(*xIter); + m_xScriptsBox->copy_iterator(*xAltIter, *xIter); + } + while (bNextEntry); +} + +void SvxScriptOrgDialog::Init( const OUString& language ) +{ + m_xScriptsBox->freeze(); + + deleteAllTree(); + + Reference< browse::XBrowseNode > rootNode; + Reference< XComponentContext > xCtx( + comphelper::getProcessComponentContext() ); + + Sequence< Reference< browse::XBrowseNode > > children; + + OUString userStr("user"); + OUString const shareStr("share"); + + try + { + Reference< browse::XBrowseNodeFactory > xFac = browse::theBrowseNodeFactory::get(xCtx); + + rootNode.set( xFac->createView( + browse::BrowseNodeFactoryViewTypes::MACROORGANIZER ) ); + + if ( rootNode.is() && rootNode->hasChildNodes() ) + { + children = rootNode->getChildNodes(); + } + } + catch( const Exception& ) + { + TOOLS_WARN_EXCEPTION("cui.dialogs", "Exception getting root browse node from factory"); + // TODO exception handling + } + + Reference xDocumentModel; + for ( const Reference< browse::XBrowseNode >& childNode : std::as_const(children) ) + { + bool app = false; + OUString uiName = childNode->getName(); + OUString factoryURL; + if ( uiName == userStr || uiName == shareStr ) + { + app = true; + if ( uiName == userStr ) + { + uiName = m_sMyMacros; + } + else + { + uiName = m_sProdMacros; + } + } + else + { + xDocumentModel.set(getDocumentModel(xCtx, uiName ), UNO_QUERY); + + if ( xDocumentModel.is() ) + { + Reference< frame::XModuleManager2 > xModuleManager( frame::ModuleManager::create(xCtx) ); + + // get the long name of the document: + Sequence moduleDescr; + try{ + OUString appModule = xModuleManager->identify( xDocumentModel ); + xModuleManager->getByName(appModule) >>= moduleDescr; + } catch(const uno::Exception&) + {} + + for ( const beans::PropertyValue& prop : std::as_const(moduleDescr)) + { + if ( prop.Name == "ooSetupFactoryEmptyDocumentURL" ) + { + prop.Value >>= factoryURL; + break; + } + } + } + } + + Reference< browse::XBrowseNode > langEntries = + getLangNodeFromRootNode( childNode, language ); + + insertEntry( uiName, app ? OUStringLiteral(RID_CUIBMP_HARDDISK) : OUStringLiteral(RID_CUIBMP_DOC), + nullptr, true, std::make_unique< SFEntry >( langEntries, xDocumentModel ), factoryURL, false ); + } + + m_xScriptsBox->thaw(); +} + +Reference< XInterface > +SvxScriptOrgDialog::getDocumentModel( Reference< XComponentContext > const & xCtx, OUString const & docName ) +{ + Reference< XInterface > xModel; + Reference< frame::XDesktop2 > desktop = frame::Desktop::create(xCtx); + + Reference< container::XEnumerationAccess > componentsAccess = + desktop->getComponents(); + Reference< container::XEnumeration > components = + componentsAccess->createEnumeration(); + while (components->hasMoreElements()) + { + Reference< frame::XModel > model( + components->nextElement(), UNO_QUERY ); + if ( model.is() ) + { + OUString sTdocUrl = ::comphelper::DocumentInfo::getDocumentTitle( model ); + if( sTdocUrl == docName ) + { + xModel = model; + break; + } + } + } + return xModel; +} + +Reference< browse::XBrowseNode > +SvxScriptOrgDialog::getLangNodeFromRootNode( Reference< browse::XBrowseNode > const & rootNode, OUString const & language ) +{ + Reference< browse::XBrowseNode > langNode; + + try + { + auto tryFind = [&] { + const Sequence> children = rootNode->getChildNodes(); + const auto it = std::find_if(children.begin(), children.end(), + [&](const Reference& child) { + return child->getName() == language; + }); + return (it != children.end()) ? *it : nullptr; + }; + { + // First try without Java interaction, to avoid warnings for non-JRE-dependent providers + css::uno::ContextLayer layer(comphelper::NoEnableJavaInteractionContext()); + langNode = tryFind(); + } + if (!langNode) + { + // Now try with Java interaction enabled + langNode = tryFind(); + } + } + catch ( Exception& ) + { + // if getChildNodes() throws an exception we just return + // the empty Reference + } + return langNode; +} + +void SvxScriptOrgDialog::RequestSubEntries(const weld::TreeIter& rRootEntry, Reference< css::script::browse::XBrowseNode > const & node, + Reference< XModel >& model) +{ + if (!node.is()) + { + return; + } + + Sequence< Reference< browse::XBrowseNode > > children; + try + { + children = node->getChildNodes(); + } + catch ( Exception& ) + { + // if we catch an exception in getChildNodes then no entries are added + } + + for ( const Reference< browse::XBrowseNode >& childNode : std::as_const(children) ) + { + OUString name( childNode->getName() ); + if ( childNode->getType() != browse::BrowseNodeTypes::SCRIPT) + { + insertEntry(name, RID_CUIBMP_LIB, &rRootEntry, true, std::make_unique(childNode, model), false); + } + else + { + insertEntry(name, RID_CUIBMP_MACRO, &rRootEntry, false, std::make_unique(childNode, model), false); + } + } +} + +void SvxScriptOrgDialog::insertEntry(const OUString& rText, const OUString& rBitmap, + const weld::TreeIter* pParent, bool bChildrenOnDemand, std::unique_ptr && aUserData, + const OUString& factoryURL, bool bSelect) +{ + if (rBitmap == RID_CUIBMP_DOC && !factoryURL.isEmpty()) + { + OUString aImage = SvFileInformationManager::GetFileImageId(INetURLObject(factoryURL)); + insertEntry(rText, aImage, pParent, bChildrenOnDemand, std::move(aUserData), bSelect); + return; + } + insertEntry(rText, rBitmap, pParent, bChildrenOnDemand, std::move(aUserData), bSelect); +} + +void SvxScriptOrgDialog::insertEntry( + const OUString& rText, const OUString& rBitmap, const weld::TreeIter* pParent, + bool bChildrenOnDemand, std::unique_ptr && aUserData, bool bSelect) +{ + std::unique_ptr xRetIter; + if (bSelect) + xRetIter = m_xScriptsBox->make_iterator(); + OUString sId(OUString::number(reinterpret_cast(aUserData.release()))); // XXX possible leak + m_xScriptsBox->insert(pParent, -1, &rText, &sId, nullptr, nullptr, &rBitmap, + bChildrenOnDemand, xRetIter.get()); + if (bSelect) + { + m_xScriptsBox->set_cursor(*xRetIter); + m_xScriptsBox->select(*xRetIter); + } +} + +IMPL_LINK(SvxScriptOrgDialog, ExpandingHdl, const weld::TreeIter&, rIter, bool) +{ + SFEntry* userData = reinterpret_cast(m_xScriptsBox->get_id(rIter).toInt64()); + + Reference< browse::XBrowseNode > node; + Reference< XModel > model; + if ( userData && !userData->isLoaded() ) + { + node = userData->GetNode(); + model = userData->GetModel(); + RequestSubEntries(rIter, node, model); + userData->setLoaded(); + } + + return true; +} + +// CuiInputDialog ------------------------------------------------------------ +CuiInputDialog::CuiInputDialog(weld::Window * pParent, InputDialogMode nMode) + : GenericDialogController(pParent, "cui/ui/newlibdialog.ui", "NewLibDialog") + , m_xEdit(m_xBuilder->weld_entry("entry")) +{ + m_xEdit->grab_focus(); + + std::unique_ptr xNewLibFT(m_xBuilder->weld_label("newlibft")); + + if ( nMode == InputDialogMode::NEWMACRO ) + { + xNewLibFT->hide(); + std::unique_ptr xNewMacroFT(m_xBuilder->weld_label("newmacroft")); + xNewMacroFT->show(); + std::unique_ptr xAltTitle(m_xBuilder->weld_label("altmacrotitle")); + m_xDialog->set_title(xAltTitle->get_label()); + } + else if ( nMode == InputDialogMode::RENAME ) + { + xNewLibFT->hide(); + std::unique_ptr xRenameFT(m_xBuilder->weld_label("renameft")); + xRenameFT->show(); + std::unique_ptr xAltTitle(m_xBuilder->weld_label("altrenametitle")); + m_xDialog->set_title(xAltTitle->get_label()); + } +} + +// ScriptOrgDialog ------------------------------------------------------------ + +SvxScriptOrgDialog::SvxScriptOrgDialog(weld::Window* pParent, const OUString& language) + : SfxDialogController(pParent, "cui/ui/scriptorganizer.ui", "ScriptOrganizerDialog") + , m_sLanguage(language) + , m_delErrStr(CuiResId(RID_SVXSTR_DELFAILED)) + , m_delErrTitleStr(CuiResId(RID_SVXSTR_DELFAILED_TITLE)) + , m_delQueryStr(CuiResId(RID_SVXSTR_DELQUERY)) + , m_delQueryTitleStr(CuiResId(RID_SVXSTR_DELQUERY_TITLE)) + , m_createErrStr(CuiResId(RID_SVXSTR_CREATEFAILED)) + , m_createDupStr(CuiResId(RID_SVXSTR_CREATEFAILEDDUP)) + , m_createErrTitleStr(CuiResId(RID_SVXSTR_CREATEFAILED_TITLE)) + , m_renameErrStr(CuiResId(RID_SVXSTR_RENAMEFAILED)) + , m_renameErrTitleStr(CuiResId(RID_SVXSTR_RENAMEFAILED_TITLE)) + , m_sMyMacros(CuiResId(RID_SVXSTR_MYMACROS)) + , m_sProdMacros(CuiResId(RID_SVXSTR_PRODMACROS)) + , m_xScriptsBox(m_xBuilder->weld_tree_view("scripts")) + , m_xRunButton(m_xBuilder->weld_button("ok")) + , m_xCloseButton(m_xBuilder->weld_button("close")) + , m_xCreateButton(m_xBuilder->weld_button("create")) + , m_xEditButton(m_xBuilder->weld_button("edit")) + , m_xRenameButton(m_xBuilder->weld_button("rename")) + , m_xDelButton(m_xBuilder->weld_button("delete")) +{ + // must be a neater way to deal with the strings than as above + // append the language to the dialog title + OUString winTitle(m_xDialog->get_title()); + winTitle = winTitle.replaceFirst( "%MACROLANG", m_sLanguage ); + m_xDialog->set_title(winTitle); + + m_xScriptsBox->set_size_request(m_xScriptsBox->get_approximate_digit_width() * 45, + m_xScriptsBox->get_height_rows(12)); + + m_xScriptsBox->connect_changed( LINK( this, SvxScriptOrgDialog, ScriptSelectHdl ) ); + m_xScriptsBox->connect_expanding(LINK( this, SvxScriptOrgDialog, ExpandingHdl ) ); + m_xRunButton->connect_clicked( LINK( this, SvxScriptOrgDialog, ButtonHdl ) ); + m_xCloseButton->connect_clicked( LINK( this, SvxScriptOrgDialog, ButtonHdl ) ); + m_xRenameButton->connect_clicked( LINK( this, SvxScriptOrgDialog, ButtonHdl ) ); + m_xEditButton->connect_clicked( LINK( this, SvxScriptOrgDialog, ButtonHdl ) ); + m_xDelButton->connect_clicked( LINK( this, SvxScriptOrgDialog, ButtonHdl ) ); + m_xCreateButton->connect_clicked( LINK( this, SvxScriptOrgDialog, ButtonHdl ) ); + + m_xRunButton->set_sensitive(false); + m_xRenameButton->set_sensitive(false); + m_xEditButton->set_sensitive(false); + m_xDelButton->set_sensitive(false); + m_xCreateButton->set_sensitive(false); + + Init(m_sLanguage); + RestorePreviousSelection(); +} + +SvxScriptOrgDialog::~SvxScriptOrgDialog() +{ + deleteAllTree(); +} + +short SvxScriptOrgDialog::run() +{ + SfxObjectShell *pDoc = SfxObjectShell::GetFirst(); + + // force load of MSPs for all documents + while ( pDoc ) + { + Reference< provider::XScriptProviderSupplier > xSPS( pDoc->GetModel(), UNO_QUERY ); + if ( xSPS.is() ) + { + xSPS->getScriptProvider(); + } + + pDoc = SfxObjectShell::GetNext(*pDoc); + } + + return SfxDialogController::run(); +} + +void SvxScriptOrgDialog::CheckButtons( Reference< browse::XBrowseNode > const & node ) +{ + if ( node.is() ) + { + if ( node->getType() == browse::BrowseNodeTypes::SCRIPT) + { + m_xRunButton->set_sensitive(true); + } + else + { + m_xRunButton->set_sensitive(false); + } + Reference< beans::XPropertySet > xProps( node, UNO_QUERY ); + + if ( !xProps.is() ) + { + m_xEditButton->set_sensitive(false); + m_xDelButton->set_sensitive(false); + m_xCreateButton->set_sensitive(false); + m_xRunButton->set_sensitive(false); + return; + } + + OUString sName("Editable"); + + if ( getBoolProperty( xProps, sName ) ) + { + m_xEditButton->set_sensitive(true); + } + else + { + m_xEditButton->set_sensitive(false); + } + + sName = "Deletable"; + + if ( getBoolProperty( xProps, sName ) ) + { + m_xDelButton->set_sensitive(true); + } + else + { + m_xDelButton->set_sensitive(false); + } + + sName = "Creatable"; + + if ( getBoolProperty( xProps, sName ) ) + { + m_xCreateButton->set_sensitive(true); + } + else + { + m_xCreateButton->set_sensitive(false); + } + + sName = "Renamable"; + + if ( getBoolProperty( xProps, sName ) ) + { + m_xRenameButton->set_sensitive(true); + } + else + { + m_xRenameButton->set_sensitive(false); + } + } + else + { + // no node info available, disable all configurable actions + m_xDelButton->set_sensitive(false); + m_xCreateButton->set_sensitive(false); + m_xEditButton->set_sensitive(false); + m_xRunButton->set_sensitive(false); + m_xRenameButton->set_sensitive(false); + } +} + +IMPL_LINK_NOARG(SvxScriptOrgDialog, ScriptSelectHdl, weld::TreeView&, void) +{ + std::unique_ptr xIter = m_xScriptsBox->make_iterator(); + if (!m_xScriptsBox->get_selected(xIter.get())) + return; + + SFEntry* userData = reinterpret_cast(m_xScriptsBox->get_id(*xIter).toInt64()); + + Reference< browse::XBrowseNode > node; + if (userData) + { + node = userData->GetNode(); + CheckButtons(node); + } +} + +IMPL_LINK(SvxScriptOrgDialog, ButtonHdl, weld::Button&, rButton, void) +{ + if ( &rButton == m_xCloseButton.get() ) + { + StoreCurrentSelection(); + m_xDialog->response(RET_CANCEL); + } + if (!(&rButton == m_xEditButton.get() || + &rButton == m_xCreateButton.get() || + &rButton == m_xDelButton.get() || + &rButton == m_xRunButton.get() || + &rButton == m_xRenameButton.get())) + + return; + + std::unique_ptr xIter = m_xScriptsBox->make_iterator(); + if (!m_xScriptsBox->get_selected(xIter.get())) + return; + SFEntry* userData = reinterpret_cast(m_xScriptsBox->get_id(*xIter).toInt64()); + if (!userData) + return; + + Reference< browse::XBrowseNode > node; + Reference< XModel > xModel; + + node = userData->GetNode(); + xModel = userData->GetModel(); + + if ( !node.is() ) + { + return; + } + + if (&rButton == m_xRunButton.get()) + { + OUString tmpString; + Reference< beans::XPropertySet > xProp( node, UNO_QUERY ); + Reference< provider::XScriptProvider > mspNode; + if( !xProp.is() ) + { + return; + } + + if ( xModel.is() ) + { + Reference< XEmbeddedScripts > xEmbeddedScripts( xModel, UNO_QUERY); + if( !xEmbeddedScripts.is() ) + { + return; + } + + if (!xEmbeddedScripts->getAllowMacroExecution()) + { + // Please FIXME: Show a message box if AllowMacroExecution is false + return; + } + } + + std::unique_ptr xParentIter = m_xScriptsBox->make_iterator(xIter.get()); + bool bParent = m_xScriptsBox->iter_parent(*xParentIter); + while (bParent && !mspNode.is() ) + { + SFEntry* mspUserData = reinterpret_cast(m_xScriptsBox->get_id(*xParentIter).toInt64()); + mspNode.set( mspUserData->GetNode() , UNO_QUERY ); + bParent = m_xScriptsBox->iter_parent(*xParentIter); + } + xProp->getPropertyValue("URI") >>= tmpString; + const OUString scriptURL( tmpString ); + + if ( mspNode.is() ) + { + try + { + Reference< provider::XScript > xScript( + mspNode->getScript( scriptURL ), UNO_SET_THROW ); + + const Sequence< Any > args(0); + Sequence< sal_Int16 > outIndex; + Sequence< Any > outArgs( 0 ); + xScript->invoke( args, outIndex, outArgs ); + } + catch ( reflection::InvocationTargetException& ite ) + { + ShowErrorDialog(css::uno::Any(ite)); + } + catch ( provider::ScriptFrameworkErrorException& ite ) + { + ShowErrorDialog(css::uno::Any(ite)); + } + catch ( RuntimeException& re ) + { + ShowErrorDialog(css::uno::Any(re)); + } + catch ( Exception& e ) + { + ShowErrorDialog(css::uno::Any(e)); + } + } + StoreCurrentSelection(); + m_xDialog->response(RET_CANCEL); + } + else if ( &rButton == m_xEditButton.get() ) + { + Reference< script::XInvocation > xInv( node, UNO_QUERY ); + if ( xInv.is() ) + { + StoreCurrentSelection(); + m_xDialog->response(RET_CANCEL); + Sequence< Any > args(0); + Sequence< Any > outArgs( 0 ); + Sequence< sal_Int16 > outIndex; + try + { + // ISSUE need code to run script here + xInv->invoke( "Editable", args, outIndex, outArgs ); + } + catch( Exception const & ) + { + TOOLS_WARN_EXCEPTION("cui.dialogs", "Caught exception trying to invoke" ); + } + } + } + else if ( &rButton == m_xCreateButton.get() ) + { + createEntry(*xIter); + } + else if ( &rButton == m_xDelButton.get() ) + { + deleteEntry(*xIter); + } + else if ( &rButton == m_xRenameButton.get() ) + { + renameEntry(*xIter); + } +} + +Reference< browse::XBrowseNode > SvxScriptOrgDialog::getBrowseNode(const weld::TreeIter& rEntry) +{ + Reference< browse::XBrowseNode > node; + SFEntry* userData = reinterpret_cast(m_xScriptsBox->get_id(rEntry).toInt64()); + if (userData) + { + node = userData->GetNode(); + } + return node; +} + +Reference< XModel > SvxScriptOrgDialog::getModel(const weld::TreeIter& rEntry) +{ + Reference< XModel > model; + SFEntry* userData = reinterpret_cast(m_xScriptsBox->get_id(rEntry).toInt64()); + if ( userData ) + { + model = userData->GetModel(); + } + return model; +} + +void SvxScriptOrgDialog::createEntry(weld::TreeIter& rEntry) +{ + + Reference< browse::XBrowseNode > aChildNode; + Reference< browse::XBrowseNode > node = getBrowseNode( rEntry ); + Reference< script::XInvocation > xInv( node, UNO_QUERY ); + + if ( xInv.is() ) + { + OUString aNewName; + OUString aNewStdName; + InputDialogMode nMode = InputDialogMode::NEWLIB; + if (m_xScriptsBox->get_iter_depth(rEntry) == 0) + { + aNewStdName = "Library" ; + } + else + { + aNewStdName = "Macro" ; + nMode = InputDialogMode::NEWMACRO; + } + //do we need L10N for this? ie something like: + //String aNewStdName( ResId( STR_STDMODULENAME ) ); + bool bValid = false; + sal_Int32 i = 1; + + Sequence< Reference< browse::XBrowseNode > > childNodes; + // no children => ok to create Parcel1 or Script1 without checking + try + { + if( !node->hasChildNodes() ) + { + aNewName = aNewStdName + OUString::number(i); + bValid = true; + } + else + { + childNodes = node->getChildNodes(); + } + } + catch ( Exception& ) + { + // ignore, will continue on with empty sequence + } + + OUString extn; + while ( !bValid ) + { + aNewName = aNewStdName + OUString::number(i); + bool bFound = false; + if(childNodes.hasElements() ) + { + OUString nodeName = childNodes[0]->getName(); + sal_Int32 extnPos = nodeName.lastIndexOf( '.' ); + if(extnPos>0) + extn = nodeName.copy(extnPos); + } + for( const Reference< browse::XBrowseNode >& n : std::as_const(childNodes) ) + { + if (aNewName+extn == n->getName()) + { + bFound = true; + break; + } + } + if( bFound ) + { + i++; + } + else + { + bValid = true; + } + } + + CuiInputDialog aNewDlg(m_xDialog.get(), nMode); + aNewDlg.SetObjectName(aNewName); + + do + { + if (aNewDlg.run() && !aNewDlg.GetObjectName().isEmpty()) + { + OUString aUserSuppliedName = aNewDlg.GetObjectName(); + bValid = true; + for( const Reference< browse::XBrowseNode >& n : std::as_const(childNodes) ) + { + if (aUserSuppliedName+extn == n->getName()) + { + bValid = false; + OUString aError = m_createErrStr + m_createDupStr; + + std::unique_ptr xErrorBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Warning, VclButtonsType::Ok, aError)); + xErrorBox->set_title(m_createErrTitleStr); + xErrorBox->run(); + aNewDlg.SetObjectName(aNewName); + break; + } + } + if( bValid ) + aNewName = aUserSuppliedName; + } + else + { + // user hit cancel or hit OK with nothing in the editbox + + return; + } + } + while ( !bValid ); + + // open up parent node (which ensures it's loaded) + m_xScriptsBox->expand_row(rEntry); + + Sequence< Any > args( 1 ); + args[ 0 ] <<= aNewName; + Sequence< Any > outArgs( 0 ); + Sequence< sal_Int16 > outIndex; + try + { + Any aResult = xInv->invoke( "Creatable", args, outIndex, outArgs ); + Reference< browse::XBrowseNode > newNode( aResult, UNO_QUERY ); + aChildNode = newNode; + + } + catch( Exception const & ) + { + TOOLS_WARN_EXCEPTION("cui.dialogs", "Caught exception trying to Create" ); + } + } + if ( aChildNode.is() ) + { + OUString aChildName = aChildNode->getName(); + + Reference xDocumentModel = getModel( rEntry ); + + // ISSUE do we need to remove all entries for parent + // to achieve sort? Just need to determine position + // -- Basic doesn't do this on create. + // Suppose we could avoid this too. -> created nodes are + // not in alphabetical order + if ( aChildNode->getType() == browse::BrowseNodeTypes::SCRIPT ) + { + insertEntry(aChildName, RID_CUIBMP_MACRO, &rEntry, false, + std::make_unique(aChildNode,xDocumentModel), true); + } + else + { + insertEntry(aChildName, RID_CUIBMP_LIB, &rEntry, false, + std::make_unique(aChildNode,xDocumentModel), true); + + // If the Parent is not loaded then set to + // loaded, this will prevent RequestingChildren ( called + // from vcl via RequestingChildren ) from + // creating new ( duplicate ) children + SFEntry* userData = reinterpret_cast(m_xScriptsBox->get_id(rEntry).toInt64()); + if ( userData && !userData->isLoaded() ) + { + userData->setLoaded(); + } + } + } + else + { + //ISSUE L10N & message from exception? + OUString aError( m_createErrStr ); + std::unique_ptr xErrorBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Warning, VclButtonsType::Ok, aError)); + xErrorBox->set_title(m_createErrTitleStr); + xErrorBox->run(); + } +} + +void SvxScriptOrgDialog::renameEntry(const weld::TreeIter& rEntry) +{ + + Reference< browse::XBrowseNode > aChildNode; + Reference< browse::XBrowseNode > node = getBrowseNode(rEntry); + Reference< script::XInvocation > xInv( node, UNO_QUERY ); + + if ( xInv.is() ) + { + OUString aNewName = node->getName(); + sal_Int32 extnPos = aNewName.lastIndexOf( '.' ); + if(extnPos>0) + { + aNewName = aNewName.copy(0,extnPos); + } + CuiInputDialog aNewDlg(m_xDialog.get(), InputDialogMode::RENAME); + aNewDlg.SetObjectName(aNewName); + + if (!aNewDlg.run() || aNewDlg.GetObjectName().isEmpty()) + return; // user hit cancel or hit OK with nothing in the editbox + + aNewName = aNewDlg.GetObjectName(); + + Sequence< Any > args( 1 ); + args[ 0 ] <<= aNewName; + Sequence< Any > outArgs( 0 ); + Sequence< sal_Int16 > outIndex; + try + { + Any aResult = xInv->invoke( "Renamable", args, outIndex, outArgs ); + Reference< browse::XBrowseNode > newNode( aResult, UNO_QUERY ); + aChildNode = newNode; + + } + catch( Exception const & ) + { + TOOLS_WARN_EXCEPTION("cui.dialogs", "Caught exception trying to Rename" ); + } + } + if ( aChildNode.is() ) + { + m_xScriptsBox->set_text(rEntry, aChildNode->getName()); + m_xScriptsBox->set_cursor(rEntry); + m_xScriptsBox->select(rEntry); + + } + else + { + //ISSUE L10N & message from exception? + OUString aError( m_renameErrStr ); + std::unique_ptr xErrorBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Warning, VclButtonsType::Ok, aError)); + xErrorBox->set_title(m_renameErrTitleStr); + xErrorBox->run(); + } +} + +void SvxScriptOrgDialog::deleteEntry(weld::TreeIter& rEntry) +{ + bool result = false; + Reference< browse::XBrowseNode > node = getBrowseNode(rEntry); + // ISSUE L10N string & can we center list? + OUString aQuery = m_delQueryStr + getListOfChildren( node, 0 ); + std::unique_ptr xQueryBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Question, VclButtonsType::YesNo, aQuery)); + xQueryBox->set_title(m_delQueryTitleStr); + if (xQueryBox->run() == RET_NO) + { + return; + } + + Reference< script::XInvocation > xInv( node, UNO_QUERY ); + if ( xInv.is() ) + { + Sequence< Any > args( 0 ); + Sequence< Any > outArgs( 0 ); + Sequence< sal_Int16 > outIndex; + try + { + Any aResult = xInv->invoke( "Deletable", args, outIndex, outArgs ); + aResult >>= result; // or do we just assume true if no exception ? + } + catch( Exception const & ) + { + TOOLS_WARN_EXCEPTION("cui.dialogs", "Caught exception trying to delete" ); + } + } + + if ( result ) + { + deleteTree(rEntry); + m_xScriptsBox->remove(rEntry); + } + else + { + //ISSUE L10N & message from exception? + std::unique_ptr xErrorBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Warning, VclButtonsType::Ok, m_delErrStr)); + xErrorBox->set_title(m_delErrTitleStr); + xErrorBox->run(); + } + +} + +bool SvxScriptOrgDialog::getBoolProperty( Reference< beans::XPropertySet > const & xProps, + OUString const & propName ) +{ + bool result = false; + try + { + xProps->getPropertyValue( propName ) >>= result; + } + catch ( Exception& ) + { + return result; + } + return result; +} + +OUString SvxScriptOrgDialog::getListOfChildren( const Reference< browse::XBrowseNode >& node, int depth ) +{ + OUStringBuffer result = "\n"; + for( int i=0;i<=depth;i++ ) + { + result.append("\t"); + } + result.append(node->getName()); + + try + { + if ( node->hasChildNodes() ) + { + const Sequence< Reference< browse::XBrowseNode > > children + = node->getChildNodes(); + for( const Reference< browse::XBrowseNode >& n : children ) + { + result.append( getListOfChildren( n , depth+1 ) ); + } + } + } + catch ( Exception& ) + { + // ignore, will return an empty string + } + + return result.makeStringAndClear(); +} + +Selection_hash SvxScriptOrgDialog::m_lastSelection; + +void SvxScriptOrgDialog::StoreCurrentSelection() +{ + std::unique_ptr xIter = m_xScriptsBox->make_iterator(); + if (!m_xScriptsBox->get_selected(xIter.get())) + return; + OUString aDescription; + bool bEntry; + do + { + aDescription = m_xScriptsBox->get_text(*xIter) + aDescription; + bEntry = m_xScriptsBox->iter_parent(*xIter); + if (bEntry) + aDescription = ";" + aDescription; + } + while (bEntry); + OUString sDesc( aDescription ); + m_lastSelection[ m_sLanguage ] = sDesc; +} + +void SvxScriptOrgDialog::RestorePreviousSelection() +{ + OUString aStoredEntry = m_lastSelection[ m_sLanguage ]; + if( aStoredEntry.isEmpty() ) + return; + std::unique_ptr xEntry; + std::unique_ptr xTmpEntry(m_xScriptsBox->make_iterator()); + sal_Int32 nIndex = 0; + while (nIndex != -1) + { + OUString aTmp( aStoredEntry.getToken( 0, ';', nIndex ) ); + + bool bTmpEntry; + if (!xEntry) + { + xEntry = m_xScriptsBox->make_iterator(); + bTmpEntry = m_xScriptsBox->get_iter_first(*xEntry); + m_xScriptsBox->copy_iterator(*xEntry, *xTmpEntry); + } + else + { + m_xScriptsBox->copy_iterator(*xEntry, *xTmpEntry); + bTmpEntry = m_xScriptsBox->iter_children(*xTmpEntry); + } + + while (bTmpEntry) + { + if (m_xScriptsBox->get_text(*xTmpEntry) == aTmp) + { + m_xScriptsBox->copy_iterator(*xTmpEntry, *xEntry); + break; + } + bTmpEntry = m_xScriptsBox->iter_next_sibling(*xTmpEntry); + } + + if (!bTmpEntry) + break; + + m_xScriptsBox->expand_row(*xEntry); + } + + if (xEntry) + m_xScriptsBox->set_cursor(*xEntry); +} + +namespace { + +OUString ReplaceString( + const OUString& source, + const OUString& token, + const OUString& value ) +{ + sal_Int32 pos = source.indexOf( token ); + + if ( pos != -1 && !value.isEmpty() ) + { + return source.replaceAt( pos, token.getLength(), value ); + } + else + { + return source; + } +} + +OUString FormatErrorString( + const OUString& unformatted, + const OUString& language, + const OUString& script, + const OUString& line, + const OUString& type, + const OUString& message ) +{ + OUString result = unformatted.copy( 0 ); + + result = ReplaceString(result, "%LANGUAGENAME", language ); + result = ReplaceString(result, "%SCRIPTNAME", script ); + result = ReplaceString(result, "%LINENUMBER", line ); + + if ( !type.isEmpty() ) + { + result += "\n\n" + CuiResId(RID_SVXSTR_ERROR_TYPE_LABEL) + " " + type; + } + + if ( !message.isEmpty() ) + { + result += "\n\n" + CuiResId(RID_SVXSTR_ERROR_MESSAGE_LABEL) + " " + message; + } + + return result; +} + +OUString GetErrorMessage( + const provider::ScriptErrorRaisedException& eScriptError ) +{ + OUString unformatted = CuiResId( RID_SVXSTR_ERROR_AT_LINE ); + + OUString unknown("UNKNOWN"); + OUString language = unknown; + OUString script = unknown; + OUString line = unknown; + OUString type = ""; + OUString message = eScriptError.Message; + + if ( !eScriptError.language.isEmpty() ) + { + language = eScriptError.language; + } + + if ( !eScriptError.scriptName.isEmpty() ) + { + script = eScriptError.scriptName; + } + + if ( !eScriptError.Message.isEmpty() ) + { + message = eScriptError.Message; + } + if ( eScriptError.lineNum != -1 ) + { + line = OUString::number( eScriptError.lineNum ); + unformatted = CuiResId( RID_SVXSTR_ERROR_AT_LINE ); + } + else + { + unformatted = CuiResId( RID_SVXSTR_ERROR_RUNNING ); + } + + return FormatErrorString( + unformatted, language, script, line, type, message ); +} + +OUString GetErrorMessage( + const provider::ScriptExceptionRaisedException& eScriptException ) +{ + OUString unformatted = CuiResId( RID_SVXSTR_EXCEPTION_AT_LINE ); + + OUString unknown("UNKNOWN"); + OUString language = unknown; + OUString script = unknown; + OUString line = unknown; + OUString type = unknown; + OUString message = eScriptException.Message; + + if ( !eScriptException.language.isEmpty() ) + { + language = eScriptException.language; + } + if ( !eScriptException.scriptName.isEmpty() ) + { + script = eScriptException.scriptName; + } + + if ( !eScriptException.Message.isEmpty() ) + { + message = eScriptException.Message; + } + + if ( eScriptException.lineNum != -1 ) + { + line = OUString::number( eScriptException.lineNum ); + unformatted = CuiResId( RID_SVXSTR_EXCEPTION_AT_LINE ); + } + else + { + unformatted = CuiResId( RID_SVXSTR_EXCEPTION_RUNNING ); + } + + if ( !eScriptException.exceptionType.isEmpty() ) + { + type = eScriptException.exceptionType; + } + + return FormatErrorString( + unformatted, language, script, line, type, message ); + +} +OUString GetErrorMessage( + const provider::ScriptFrameworkErrorException& sError ) +{ + OUString unformatted = CuiResId( RID_SVXSTR_FRAMEWORK_ERROR_RUNNING ); + + OUString language("UNKNOWN"); + + OUString script("UNKNOWN"); + + OUString message; + + if ( !sError.scriptName.isEmpty() ) + { + script = sError.scriptName; + } + if ( !sError.language.isEmpty() ) + { + language = sError.language; + } + if ( sError.errorType == provider::ScriptFrameworkErrorType::NOTSUPPORTED ) + { + message = + CuiResId( RID_SVXSTR_ERROR_LANG_NOT_SUPPORTED ); + message = ReplaceString(message, "%LANGUAGENAME", language ); + + } + else + { + message = sError.Message; + } + return FormatErrorString( + unformatted, language, script, OUString(), OUString(), message ); +} + +OUString GetErrorMessage( const css::uno::Any& aException ) +{ + if ( aException.getValueType() == + cppu::UnoType::get()) + { + reflection::InvocationTargetException ite; + aException >>= ite; + if ( ite.TargetException.getValueType() == cppu::UnoType::get()) + { + // Error raised by script + provider::ScriptErrorRaisedException scriptError; + ite.TargetException >>= scriptError; + return GetErrorMessage( scriptError ); + } + else if ( ite.TargetException.getValueType() == cppu::UnoType::get()) + { + // Exception raised by script + provider::ScriptExceptionRaisedException scriptException; + ite.TargetException >>= scriptException; + return GetErrorMessage( scriptException ); + } + else + { + // Unknown error, shouldn't happen + // OSL_ASSERT(...) + } + + } + else if ( aException.getValueType() == cppu::UnoType::get()) + { + // A Script Framework error has occurred + provider::ScriptFrameworkErrorException sfe; + aException >>= sfe; + return GetErrorMessage( sfe ); + + } + // unknown exception + auto msg = aException.getValueTypeName(); + Exception e; + if ( (aException >>= e) && !e.Message.isEmpty() ) + { + msg += ": " + e.Message; + } + return msg; +} + +} + +SvxScriptErrorDialog::SvxScriptErrorDialog( css::uno::Any const & aException ) + : m_sMessage() +{ + SolarMutexGuard aGuard; + m_sMessage = GetErrorMessage( aException ); +} + +SvxScriptErrorDialog::~SvxScriptErrorDialog() +{ +} + +short SvxScriptErrorDialog::Execute() +{ + // Show Error dialog asynchronously + + // Pass a copy of the message to the ShowDialog method as the + // SvxScriptErrorDialog may be deleted before ShowDialog is called + Application::PostUserEvent( + LINK( this, SvxScriptErrorDialog, ShowDialog ), + new OUString( m_sMessage ) ); + + return 0; +} + +IMPL_STATIC_LINK( SvxScriptErrorDialog, ShowDialog, void*, p, void ) +{ + OUString* pMessage = static_cast(p); + OUString message; + + if ( pMessage && !pMessage->isEmpty() ) + { + message = *pMessage; + } + else + { + message = CuiResId( RID_SVXSTR_ERROR_TITLE ); + } + + std::unique_ptr xBox(Application::CreateMessageDialog(nullptr, + VclMessageType::Warning, VclButtonsType::Ok, message)); + xBox->set_title(CuiResId(RID_SVXSTR_ERROR_TITLE)); + xBox->run(); + + delete pMessage; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/sdrcelldlg.cxx b/cui/source/dialogs/sdrcelldlg.cxx new file mode 100644 index 000000000..3c745692f --- /dev/null +++ b/cui/source/dialogs/sdrcelldlg.cxx @@ -0,0 +1,62 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include + +SvxFormatCellsDialog::SvxFormatCellsDialog(weld::Window* pParent, const SfxItemSet* pAttr, const SdrModel& rModel) + : SfxTabDialogController(pParent, "cui/ui/formatcellsdialog.ui", "FormatCellsDialog", pAttr) + , mrOutAttrs(*pAttr) + , mpColorTab(rModel.GetColorList()) + , mpGradientList(rModel.GetGradientList()) + , mpHatchingList(rModel.GetHatchList()) + , mpBitmapList(rModel.GetBitmapList()) + , mpPatternList(rModel.GetPatternList()) +{ + AddTabPage("name", RID_SVXPAGE_CHAR_NAME); + AddTabPage("effects", RID_SVXPAGE_CHAR_EFFECTS); + AddTabPage("border", RID_SVXPAGE_BORDER ); + AddTabPage("area", RID_SVXPAGE_AREA); +} + +void SvxFormatCellsDialog::PageCreated(const OString& rId, SfxTabPage &rPage) +{ + if (rId == "area") + { + SvxAreaTabPage& rAreaPage = static_cast(rPage); + rAreaPage.SetColorList( mpColorTab ); + rAreaPage.SetGradientList( mpGradientList ); + rAreaPage.SetHatchingList( mpHatchingList ); + rAreaPage.SetBitmapList( mpBitmapList ); + rAreaPage.SetPatternList( mpPatternList ); + rAreaPage.ActivatePage( mrOutAttrs ); + } + else if (rId == "border") + { + SvxBorderTabPage& rBorderPage = static_cast(rPage); + rBorderPage.SetTableMode(); + } + else + SfxTabDialogController::PageCreated(rId, rPage); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/showcols.cxx b/cui/source/dialogs/showcols.cxx new file mode 100644 index 000000000..895ed485e --- /dev/null +++ b/cui/source/dialogs/showcols.cxx @@ -0,0 +1,107 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include +#include +#include +#include + +#define CUIFM_PROP_HIDDEN "Hidden" +#define CUIFM_PROP_LABEL "Label" + +FmShowColsDialog::FmShowColsDialog(weld::Window* pParent) + : GenericDialogController(pParent, "cui/ui/showcoldialog.ui", "ShowColDialog") + , m_xList(m_xBuilder->weld_tree_view("treeview")) + , m_xOK(m_xBuilder->weld_button("ok")) +{ + m_xList->set_size_request(m_xList->get_approximate_digit_width() * 40, m_xList->get_height_rows(8)); + m_xList->set_selection_mode(SelectionMode::Multiple); + m_xOK->connect_clicked(LINK(this, FmShowColsDialog, OnClickedOk)); +} + +FmShowColsDialog::~FmShowColsDialog() +{ +} + +IMPL_LINK_NOARG(FmShowColsDialog, OnClickedOk, weld::Button&, void) +{ + DBG_ASSERT(m_xColumns.is(), "FmShowColsDialog::OnClickedOk : you should call SetColumns before executing the dialog !"); + if (m_xColumns.is()) + { + css::uno::Reference< css::beans::XPropertySet > xCol; + auto nSelectedRows = m_xList->get_selected_rows(); + for (auto i : nSelectedRows) + { + m_xColumns->getByIndex(m_xList->get_id(i).toInt32()) >>= xCol; + if (xCol.is()) + { + try + { + xCol->setPropertyValue(CUIFM_PROP_HIDDEN, css::uno::Any(false)); + } + catch(...) + { + OSL_FAIL("FmShowColsDialog::OnClickedOk Exception occurred!"); + } + } + } + } + + m_xDialog->response(RET_OK); +} + +void FmShowColsDialog::SetColumns(const css::uno::Reference< css::container::XIndexContainer>& xCols) +{ + DBG_ASSERT(xCols.is(), "FmShowColsDialog::SetColumns : invalid columns !"); + if (!xCols.is()) + return; + m_xColumns = xCols.get(); + + m_xList->clear(); + + css::uno::Reference< css::beans::XPropertySet> xCurCol; + OUString sCurName; + for (sal_Int32 i=0; igetCount(); ++i) + { + sCurName.clear(); + xCurCol.set(xCols->getByIndex(i), css::uno::UNO_QUERY); + bool bIsHidden = false; + try + { + css::uno::Any aHidden = xCurCol->getPropertyValue(CUIFM_PROP_HIDDEN); + bIsHidden = ::comphelper::getBOOL(aHidden); + + OUString sName; + xCurCol->getPropertyValue(CUIFM_PROP_LABEL) >>= sName; + sCurName = sName; + } + catch(...) + { + OSL_FAIL("FmShowColsDialog::SetColumns Exception occurred!"); + } + + // if the col is hidden, put it into the list + if (bIsHidden) + m_xList->append(OUString::number(i), sCurName); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/splitcelldlg.cxx b/cui/source/dialogs/splitcelldlg.cxx new file mode 100644 index 000000000..40b798b7c --- /dev/null +++ b/cui/source/dialogs/splitcelldlg.cxx @@ -0,0 +1,88 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +SvxSplitTableDlg::SvxSplitTableDlg(weld::Window *pParent, bool bIsTableVertical, long nMaxVertical, long nMaxHorizontal) + : GenericDialogController(pParent, "cui/ui/splitcellsdialog.ui", "SplitCellsDialog") + , m_xCountEdit(m_xBuilder->weld_spin_button("countnf")) + , m_xHorzBox(!bIsTableVertical ? m_xBuilder->weld_radio_button("hori") : m_xBuilder->weld_radio_button("vert")) + , m_xVertBox(!bIsTableVertical ? m_xBuilder->weld_radio_button("vert") : m_xBuilder->weld_radio_button("hori")) + , m_xPropCB(m_xBuilder->weld_check_button("prop")) + , mnMaxVertical(nMaxVertical) + , mnMaxHorizontal(nMaxHorizontal) +{ + m_xHorzBox->connect_clicked(LINK(this, SvxSplitTableDlg, ClickHdl)); + m_xPropCB->connect_clicked(LINK(this, SvxSplitTableDlg, ClickHdl)); + m_xVertBox->connect_clicked(LINK(this, SvxSplitTableDlg, ClickHdl)); + + if (mnMaxVertical < 2) + { + if (!bIsTableVertical) + m_xVertBox->set_sensitive(false); + else + m_xHorzBox->set_sensitive(false); + } + + //exchange the meaning of horizontal and vertical for vertical text + if (bIsTableVertical) + { + int nHorzTopAttach = m_xHorzBox->get_grid_top_attach(); + int nVertTopAttach = m_xVertBox->get_grid_top_attach(); + m_xHorzBox->set_grid_top_attach(nVertTopAttach); + m_xVertBox->set_grid_top_attach(nHorzTopAttach); + m_xHorzBox->set_active(m_xVertBox->get_active()); + } +} + +IMPL_LINK(SvxSplitTableDlg, ClickHdl, weld::Button&, rButton, void) +{ + const bool bIsVert = &rButton == m_xVertBox.get(); + long nMax = bIsVert ? mnMaxVertical : mnMaxHorizontal; + m_xPropCB->set_sensitive(!bIsVert); + m_xCountEdit->set_max(nMax); +} + +bool SvxSplitTableDlg::IsHorizontal() const +{ + return m_xHorzBox->get_active(); +} + +bool SvxSplitTableDlg::IsProportional() const +{ + return m_xPropCB->get_active() && m_xHorzBox->get_active(); +} + +long SvxSplitTableDlg::GetCount() const +{ + return m_xCountEdit->get_value(); +} + +short SvxSplitTableDlg::Execute() +{ + return run(); +} + +void SvxSplitTableDlg::SetSplitVerticalByDefault() +{ + if( mnMaxVertical >= 2 ) + m_xVertBox->set_active(true); // tdf#60242 +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/srchxtra.cxx b/cui/source/dialogs/srchxtra.cxx new file mode 100644 index 000000000..2a68293f0 --- /dev/null +++ b/cui/source/dialogs/srchxtra.cxx @@ -0,0 +1,235 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +SvxSearchFormatDialog::SvxSearchFormatDialog(weld::Window* pParent, const SfxItemSet& rSet) + : SfxTabDialogController(pParent, "cui/ui/searchformatdialog.ui", "SearchFormatDialog", &rSet) +{ + AddTabPage("font", SvxCharNamePage::Create, nullptr); + AddTabPage("fonteffects", SvxCharEffectsPage::Create, nullptr); + AddTabPage("position", SvxCharPositionPage::Create, nullptr); + AddTabPage("asianlayout", SvxCharTwoLinesPage::Create, nullptr); + AddTabPage("labelTP_PARA_STD", SvxStdParagraphTabPage::Create, nullptr); + AddTabPage("labelTP_PARA_ALIGN", SvxParaAlignTabPage::Create, nullptr); + AddTabPage("labelTP_PARA_EXT", SvxExtParagraphTabPage::Create, nullptr); + AddTabPage("labelTP_PARA_ASIAN", SvxAsianTabPage::Create, nullptr ); + AddTabPage("background", SvxBkgTabPage::Create, nullptr); + + // remove asian tabpages if necessary + SvtCJKOptions aCJKOptions; + if ( !aCJKOptions.IsDoubleLinesEnabled() ) + RemoveTabPage("asianlayout"); + if ( !aCJKOptions.IsAsianTypographyEnabled() ) + RemoveTabPage("labelTP_PARA_ASIAN"); +} + +SvxSearchFormatDialog::~SvxSearchFormatDialog() +{ +} + +void SvxSearchFormatDialog::PageCreated(const OString& rId, SfxTabPage& rPage) +{ + if (rId == "font") + { + const FontList* pApm_pFontList = nullptr; + SfxObjectShell* pSh = SfxObjectShell::Current(); + + if ( pSh ) + { + const SvxFontListItem* pFLItem = static_cast( + pSh->GetItem( SID_ATTR_CHAR_FONTLIST )); + if ( pFLItem ) + pApm_pFontList = pFLItem->GetFontList(); + } + + const FontList* pList = pApm_pFontList; + + if ( !pList ) + { + if ( !m_pFontList ) + m_pFontList.reset(new FontList(Application::GetDefaultDevice())); + pList = m_pFontList.get(); + } + + static_cast(rPage). + SetFontList( SvxFontListItem( pList, SID_ATTR_CHAR_FONTLIST ) ); + static_cast(rPage).EnableSearchMode(); + } + else if (rId == "labelTP_PARA_STD") + { + static_cast(rPage).EnableAutoFirstLine(); + } + else if (rId == "labelTP_PARA_ALIGN") + { + static_cast(rPage).EnableJustifyExt(); + } + else if (rId == "background") + { + SfxAllItemSet aSet(*(GetInputSetImpl()->GetPool())); + aSet.Put(SfxUInt32Item(SID_FLAG_TYPE,static_cast(SvxBackgroundTabFlags::SHOW_HIGHLIGHTING))); + rPage.PageCreated(aSet); + } +} + +SvxSearchAttributeDialog::SvxSearchAttributeDialog(weld::Window* pParent, + SearchAttrItemList& rLst, const sal_uInt16* pWhRanges) + : GenericDialogController(pParent, "cui/ui/searchattrdialog.ui", "SearchAttrDialog") + , rList(rLst) + , m_xAttrLB(m_xBuilder->weld_tree_view("treeview")) + , m_xOKBtn(m_xBuilder->weld_button("ok")) +{ + m_xAttrLB->set_size_request(m_xAttrLB->get_approximate_digit_width() * 50, + m_xAttrLB->get_height_rows(12)); + + std::vector aWidths; + aWidths.push_back(m_xAttrLB->get_checkbox_column_width()); + m_xAttrLB->set_column_fixed_widths(aWidths); + + m_xOKBtn->connect_clicked(LINK( this, SvxSearchAttributeDialog, OKHdl)); + + SfxObjectShell* pSh = SfxObjectShell::Current(); + DBG_ASSERT( pSh, "No DocShell" ); + + SfxItemPool& rPool = pSh->GetPool(); + SfxItemSet aSet( rPool, pWhRanges ); + SfxWhichIter aIter( aSet ); + sal_uInt16 nWhich = aIter.FirstWhich(); + + while ( nWhich ) + { + sal_uInt16 nSlot = rPool.GetSlotId( nWhich ); + if ( nSlot >= SID_SVX_START ) + { + bool bChecked = false, bFound = false; + for ( sal_uInt16 i = 0; !bFound && i < rList.Count(); ++i ) + { + if ( nSlot == rList[i].nSlot ) + { + bFound = true; + if ( IsInvalidItem( rList[i].pItem ) ) + bChecked = true; + } + } + + // item resources are in svx + sal_uInt32 nId = SvxAttrNameTable::FindIndex(nSlot); + if (RESARRAY_INDEX_NOTFOUND != nId) + { + m_xAttrLB->append(); + const int nRow = m_xAttrLB->n_children() - 1; + m_xAttrLB->set_toggle(nRow, bChecked ? TRISTATE_TRUE : TRISTATE_FALSE, 0); + m_xAttrLB->set_text(nRow, SvxAttrNameTable::GetString(nId), 1); + m_xAttrLB->set_id(nRow, OUString::number(nSlot)); + } + else + SAL_WARN( "cui.dialogs", "no resource for slot id " << static_cast(nSlot) ); + } + nWhich = aIter.NextWhich(); + } + + m_xAttrLB->make_sorted(); + m_xAttrLB->select(0); +} + +SvxSearchAttributeDialog::~SvxSearchAttributeDialog() +{ +} + +IMPL_LINK_NOARG(SvxSearchAttributeDialog, OKHdl, weld::Button&, void) +{ + SearchAttrItem aInvalidItem; + aInvalidItem.pItem = INVALID_POOL_ITEM; + + for (int i = 0, nCount = m_xAttrLB->n_children(); i < nCount; ++i) + { + sal_uInt16 nSlot = m_xAttrLB->get_id(i).toUInt32(); + bool bChecked = m_xAttrLB->get_toggle(i, 0) == TRISTATE_TRUE; + + sal_uInt16 j; + for ( j = rList.Count(); j; ) + { + SearchAttrItem& rItem = rList[ --j ]; + if( rItem.nSlot == nSlot ) + { + if( bChecked ) + { + if( !IsInvalidItem( rItem.pItem ) ) + delete rItem.pItem; + rItem.pItem = INVALID_POOL_ITEM; + } + else if( IsInvalidItem( rItem.pItem ) ) + rItem.pItem = nullptr; + j = 1; + break; + } + } + + if ( !j && bChecked ) + { + aInvalidItem.nSlot = nSlot; + rList.Insert( aInvalidItem ); + } + } + + // remove invalid items (pItem == NULL) + for ( sal_uInt16 n = rList.Count(); n; ) + if ( !rList[ --n ].pItem ) + rList.Remove( n ); + + m_xDialog->response(RET_OK); +} + +// class SvxSearchSimilarityDialog --------------------------------------- + +SvxSearchSimilarityDialog::SvxSearchSimilarityDialog(weld::Window* pParent, bool bRelax, + sal_uInt16 nOther, sal_uInt16 nShorter, sal_uInt16 nLonger) + : GenericDialogController(pParent, "cui/ui/similaritysearchdialog.ui", "SimilaritySearchDialog") + , m_xOtherFld(m_xBuilder->weld_spin_button("otherfld")) + , m_xLongerFld(m_xBuilder->weld_spin_button("longerfld")) + , m_xShorterFld(m_xBuilder->weld_spin_button("shorterfld")) + , m_xRelaxBox(m_xBuilder->weld_check_button("relaxbox")) +{ + m_xOtherFld->set_value(nOther); + m_xShorterFld->set_value(nShorter); + m_xLongerFld->set_value(nLonger); + m_xRelaxBox->set_active(bRelax); +} + +SvxSearchSimilarityDialog::~SvxSearchSimilarityDialog() +{ +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/thesdlg.cxx b/cui/source/dialogs/thesdlg.cxx new file mode 100644 index 000000000..612f5fe01 --- /dev/null +++ b/cui/source/dialogs/thesdlg.cxx @@ -0,0 +1,343 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +using namespace ::com::sun::star; + +IMPL_LINK_NOARG( SvxThesaurusDialog, ModifyTimer_Hdl, Timer *, void ) +{ + LookUp(m_xWordCB->get_active_text()); + m_aModifyIdle.Stop(); +} + +IMPL_LINK_NOARG(SvxThesaurusDialog, ReplaceEditHdl_Impl, weld::Entry&, void) +{ + m_xReplaceBtn->set_sensitive(!m_xReplaceEdit->get_text().isEmpty()); +} + +IMPL_LINK(SvxThesaurusDialog, KeyInputHdl, const KeyEvent&, rKEvt, bool) +{ + const vcl::KeyCode& rKey = rKEvt.GetKeyCode(); + + if (rKey.GetCode() == KEY_RETURN) + { + m_xDialog->response(RET_OK); + return true; + } + + return false; +} + +uno::Sequence< uno::Reference< linguistic2::XMeaning > > SvxThesaurusDialog::queryMeanings_Impl( + OUString& rTerm, + const lang::Locale& rLocale, + const beans::PropertyValues& rProperties ) +{ + uno::Sequence< uno::Reference< linguistic2::XMeaning > > aMeanings( + xThesaurus->queryMeanings( rTerm, rLocale, rProperties ) ); + + // text with '.' at the end? + if ( !aMeanings.hasElements() && rTerm.endsWith(".") ) + { + // try again without trailing '.' chars. It may be a word at the + // end of a sentence and not an abbreviation... + OUString aTxt(comphelper::string::stripEnd(rTerm, '.')); + aMeanings = xThesaurus->queryMeanings( aTxt, rLocale, rProperties ); + if (aMeanings.hasElements()) + { + rTerm = aTxt; + } + } + + return aMeanings; +} + +bool SvxThesaurusDialog::UpdateAlternativesBox_Impl() +{ + lang::Locale aLocale( LanguageTag::convertToLocale( nLookUpLanguage ) ); + uno::Sequence< uno::Reference< linguistic2::XMeaning > > aMeanings = queryMeanings_Impl( + aLookUpText, aLocale, uno::Sequence< beans::PropertyValue >() ); + const sal_Int32 nMeanings = aMeanings.getLength(); + const uno::Reference< linguistic2::XMeaning > *pMeanings = aMeanings.getConstArray(); + + m_xAlternativesCT->freeze(); + + m_xAlternativesCT->clear(); + int nRow = 0; + for (sal_Int32 i = 0; i < nMeanings; ++i) + { + OUString rMeaningTxt = pMeanings[i]->getMeaning(); + uno::Sequence< OUString > aSynonyms( pMeanings[i]->querySynonyms() ); + const sal_Int32 nSynonyms = aSynonyms.getLength(); + const OUString *pSynonyms = aSynonyms.getConstArray(); + DBG_ASSERT( !rMeaningTxt.isEmpty(), "meaning with empty text" ); + DBG_ASSERT( nSynonyms > 0, "meaning without synonym" ); + + OUString sHeading = OUString::number(i + 1) + ". " + rMeaningTxt; + m_xAlternativesCT->append_text(sHeading); + m_xAlternativesCT->set_text_emphasis(nRow, true, 0); + ++nRow; + + for (sal_Int32 k = 0; k < nSynonyms; ++k) + { + // GetThesaurusReplaceText will strip the leading spaces + m_xAlternativesCT->append_text(" " + pSynonyms[k]); + m_xAlternativesCT->set_text_emphasis(nRow, false, 0); + ++nRow; + } + } + + m_xAlternativesCT->thaw(); + + return nMeanings > 0; +} + +void SvxThesaurusDialog::LookUp( const OUString &rText ) +{ + if (rText != m_xWordCB->get_active_text()) // avoid moving of the cursor if the text is the same + m_xWordCB->set_entry_text(rText); + LookUp_Impl(); +} + +IMPL_LINK_NOARG(SvxThesaurusDialog, LeftBtnHdl_Impl, weld::Button&, void) +{ + if (aLookUpHistory.size() >= 2) + { + aLookUpHistory.pop(); // remove current look up word from stack + m_xWordCB->set_entry_text(aLookUpHistory.top()); // retrieve previous look up word + aLookUpHistory.pop(); + LookUp_Impl(); + } +} + +IMPL_LINK( SvxThesaurusDialog, LanguageHdl_Impl, weld::ComboBox&, rLB, void ) +{ + OUString aLangText(rLB.get_active_text()); + LanguageType nLang = SvtLanguageTable::GetLanguageType( aLangText ); + DBG_ASSERT( nLang != LANGUAGE_NONE && nLang != LANGUAGE_DONTKNOW, "failed to get language" ); + if (xThesaurus->hasLocale( LanguageTag::convertToLocale( nLang ) )) + nLookUpLanguage = nLang; + SetWindowTitle( nLang ); + LookUp_Impl(); +} + +void SvxThesaurusDialog::LookUp_Impl() +{ + OUString aText(m_xWordCB->get_active_text()); + + aLookUpText = aText; + if (!aLookUpText.isEmpty() && + (aLookUpHistory.empty() || aLookUpText != aLookUpHistory.top())) + aLookUpHistory.push( aLookUpText ); + + m_bWordFound = UpdateAlternativesBox_Impl(); + m_xAlternativesCT->set_visible(m_bWordFound); + m_xNotFound->set_visible(!m_bWordFound); + + if (m_bWordFound) + Application::PostUserEvent(LINK(this, SvxThesaurusDialog, SelectFirstHdl_Impl)); + + if (m_xWordCB->find_text(aText) == -1) + m_xWordCB->append_text(aText); + + m_xReplaceEdit->set_text( OUString() ); + ReplaceEditHdl_Impl(*m_xReplaceEdit); + m_xLeftBtn->set_sensitive( aLookUpHistory.size() > 1 ); +} + +IMPL_LINK_NOARG(SvxThesaurusDialog, WordSelectHdl_Impl, weld::ComboBox&, void) +{ + m_aModifyIdle.Start(); +} + +IMPL_LINK( SvxThesaurusDialog, AlternativesSelectHdl_Impl, weld::TreeView&, rBox, void ) +{ + int nEntry = rBox.get_selected_index(); + if (nEntry != -1) + { + bool bIsHeader = rBox.get_text_emphasis(nEntry, 0); + if (bIsHeader) + { + ++nEntry; + rBox.select(nEntry); + } + OUString aStr = linguistic::GetThesaurusReplaceText(rBox.get_text(nEntry)); + m_xReplaceEdit->set_text(aStr); + ReplaceEditHdl_Impl(*m_xReplaceEdit); + } +} + +IMPL_LINK( SvxThesaurusDialog, AlternativesDoubleClickHdl_Impl, weld::TreeView&, rBox, bool ) +{ + int nEntry = rBox.get_selected_index(); + if (nEntry != -1) + { + bool bIsHeader = rBox.get_text_emphasis(nEntry, 0); + if (bIsHeader) + { + ++nEntry; + rBox.select(nEntry); + } + OUString aStr = linguistic::GetThesaurusReplaceText(rBox.get_text(nEntry)); + m_xWordCB->set_entry_text(aStr); + if (!aStr.isEmpty()) + LookUp_Impl(); + } + + //! workaround to set the selection since calling SelectEntryPos within + //! the double click handler does not work + Application::PostUserEvent(LINK(this, SvxThesaurusDialog, SelectFirstHdl_Impl)); + + return true; +} + +IMPL_LINK_NOARG(SvxThesaurusDialog, SelectFirstHdl_Impl, void *, void) +{ + if (m_xAlternativesCT->n_children() >= 2) + { + m_xAlternativesCT->select(1); // pos 0 is a 'header' that is not selectable + AlternativesSelectHdl_Impl(*m_xAlternativesCT); + } +} + +// class SvxThesaurusDialog ---------------------------------------------- + +SvxThesaurusDialog::SvxThesaurusDialog( + weld::Window* pParent, + uno::Reference< linguistic2::XThesaurus > const & xThes, + const OUString &rWord, + LanguageType nLanguage) + : SfxDialogController(pParent, "cui/ui/thesaurus.ui", "ThesaurusDialog") + , m_aModifyIdle("cui SvxThesaurusDialog LookUp Modify") + , aLookUpText() + , nLookUpLanguage(LANGUAGE_NONE) + , m_bWordFound(false) + , m_xLeftBtn(m_xBuilder->weld_button("left")) + , m_xWordCB(m_xBuilder->weld_combo_box("wordcb")) + , m_xAlternativesCT(m_xBuilder->weld_tree_view("alternatives")) + , m_xNotFound(m_xBuilder->weld_label("notfound")) + , m_xReplaceEdit(m_xBuilder->weld_entry("replaceed")) + , m_xLangLB(m_xBuilder->weld_combo_box("langcb")) + , m_xReplaceBtn(m_xBuilder->weld_button("ok")) +{ + m_aModifyIdle.SetInvokeHandler( LINK( this, SvxThesaurusDialog, ModifyTimer_Hdl ) ); + m_aModifyIdle.SetPriority( TaskPriority::LOWEST ); + + m_xReplaceEdit->connect_changed( LINK( this, SvxThesaurusDialog, ReplaceEditHdl_Impl ) ); + m_xReplaceBtn->connect_clicked( LINK( this, SvxThesaurusDialog, ReplaceBtnHdl_Impl ) ); + m_xLeftBtn->connect_clicked( LINK( this, SvxThesaurusDialog, LeftBtnHdl_Impl ) ); + m_xWordCB->set_entry_completion(false); + m_xWordCB->connect_changed( LINK( this, SvxThesaurusDialog, WordSelectHdl_Impl ) ); + m_xLangLB->connect_changed( LINK( this, SvxThesaurusDialog, LanguageHdl_Impl ) ); + m_xAlternativesCT->connect_changed( LINK( this, SvxThesaurusDialog, AlternativesSelectHdl_Impl )); + m_xAlternativesCT->connect_row_activated( LINK( this, SvxThesaurusDialog, AlternativesDoubleClickHdl_Impl )); + m_xAlternativesCT->connect_key_press(LINK(this, SvxThesaurusDialog, KeyInputHdl)); + + xThesaurus = xThes; + aLookUpText = rWord; + nLookUpLanguage = nLanguage; + if (!rWord.isEmpty()) + aLookUpHistory.push( rWord ); + + OUString aTmp( rWord ); + (void)linguistic::RemoveHyphens( aTmp ); + (void)linguistic::ReplaceControlChars( aTmp ); + m_xReplaceEdit->set_text( aTmp ); + ReplaceEditHdl_Impl(*m_xReplaceEdit); + m_xWordCB->append_text( aTmp ); + + LookUp( aTmp ); + m_xAlternativesCT->grab_focus(); + m_xLeftBtn->set_sensitive(false); + + // fill language menu button list + uno::Sequence< lang::Locale > aLocales; + if (xThesaurus.is()) + aLocales = xThesaurus->getLocales(); + const sal_Int32 nLocales = aLocales.getLength(); + const lang::Locale *pLocales = aLocales.getConstArray(); + m_xLangLB->clear(); + std::vector< OUString > aLangVec; + for (sal_Int32 i = 0; i < nLocales; ++i) + { + const LanguageType nLang = LanguageTag::convertToLanguageType( pLocales[i] ); + DBG_ASSERT( nLang != LANGUAGE_NONE && nLang != LANGUAGE_DONTKNOW, "failed to get language" ); + aLangVec.push_back( SvtLanguageTable::GetLanguageString( nLang ) ); + } + std::sort( aLangVec.begin(), aLangVec.end() ); + m_xLangLB->freeze(); + for (const OUString & i : aLangVec) + m_xLangLB->append_text(i); + m_xLangLB->thaw(); + + std::vector< OUString >::iterator aI = std::find(aLangVec.begin(), aLangVec.end(), + SvtLanguageTable::GetLanguageString(nLanguage)); + if (aI != aLangVec.end()) + { + m_xLangLB->set_active_text(*aI); + } + + SetWindowTitle(nLanguage); + + // disable controls if service is missing + if (!xThesaurus.is()) + m_xDialog->set_sensitive(false); +} + +SvxThesaurusDialog::~SvxThesaurusDialog() +{ +} + +IMPL_LINK_NOARG(SvxThesaurusDialog, ReplaceBtnHdl_Impl, weld::Button&, void) +{ + m_xDialog->response(RET_OK); +} + +void SvxThesaurusDialog::SetWindowTitle( LanguageType nLanguage ) +{ + // adjust language + OUString aStr(m_xDialog->get_title()); + sal_Int32 nIndex = aStr.indexOf( '(' ); + if( nIndex != -1 ) + aStr = aStr.copy( 0, nIndex - 1 ); + aStr += " (" + SvtLanguageTable::GetLanguageString( nLanguage ) + ")"; + m_xDialog->set_title(aStr); // set window title +} + +OUString SvxThesaurusDialog::GetWord() const +{ + return m_xReplaceEdit->get_text(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/tipofthedaydlg.cxx b/cui/source/dialogs/tipofthedaydlg.cxx new file mode 100644 index 000000000..4775ed057 --- /dev/null +++ b/cui/source/dialogs/tipofthedaydlg.cxx @@ -0,0 +1,168 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +TipOfTheDayDialog::TipOfTheDayDialog(weld::Window* pParent) + : GenericDialogController(pParent, "cui/ui/tipofthedaydialog.ui", "TipOfTheDayDialog") + , m_pImage(m_xBuilder->weld_image("imImage")) + , m_pText(m_xBuilder->weld_label("lbText")) + , m_pShowTip(m_xBuilder->weld_check_button("cbShowTip")) + , m_pNext(m_xBuilder->weld_button("btnNext")) + , m_pLink(m_xBuilder->weld_link_button("btnLink")) +{ + m_pShowTip->set_active(officecfg::Office::Common::Misc::ShowTipOfTheDay::get()); + m_pNext->connect_clicked(LINK(this, TipOfTheDayDialog, OnNextClick)); + + nNumberOfTips = SAL_N_ELEMENTS(TIPOFTHEDAY_STRINGARRAY); + nCurrentTip = officecfg::Office::Common::Misc::LastTipOfTheDayID::get(); + + const auto t0 = std::chrono::system_clock::now().time_since_epoch(); + nDay = std::chrono::duration_cast(t0).count() / 24; //days since 1970-01-01 + if (nDay > officecfg::Office::Common::Misc::LastTipOfTheDayShown::get()) + nCurrentTip++; + + UpdateTip(); +} + +TipOfTheDayDialog::~TipOfTheDayDialog() +{ + std::shared_ptr xChanges( + comphelper::ConfigurationChanges::create()); + officecfg::Office::Common::Misc::LastTipOfTheDayShown::set(nDay, xChanges); + officecfg::Office::Common::Misc::LastTipOfTheDayID::set(nCurrentTip, xChanges); + officecfg::Office::Common::Misc::ShowTipOfTheDay::set(m_pShowTip->get_active(), xChanges); + xChanges->commit(); +} + +static bool file_exists(const OUString& fileName) +{ + ::osl::File aFile(fileName); + return aFile.open(osl_File_OpenFlag_Read) == osl::FileBase::E_None; +} + +void TipOfTheDayDialog::UpdateTip() +{ + if ((nCurrentTip + 1 > nNumberOfTips) || (nCurrentTip < 0)) + nCurrentTip = 0; + m_xDialog->set_title(CuiResId(STR_TITLE) + ": " + OUString::number(nCurrentTip + 1) + "/" + + OUString::number(nNumberOfTips)); + + // text + OUString aText = CuiResId(std::get<0>(TIPOFTHEDAY_STRINGARRAY[nCurrentTip])); +//replace MOD1 & MOD2 shortcuts depending on platform +#ifdef MACOSX + const OUString aMOD1 = CuiResId(STR_CMD); + const OUString aMOD2 = CuiResId(STR_Option); +#else + const OUString aMOD1 = CuiResId(STR_CTRL); + const OUString aMOD2 = CuiResId(STR_Alt); +#endif + sal_Int32 aPos; + aPos = aText.indexOf("%MOD1"); + while (aPos != -1) + { + aText = aText.replaceAt(aPos, 5, aMOD1); + aPos = aText.indexOf("%MOD1"); + } + aPos = aText.indexOf("%MOD2"); + while (aPos != -1) + { + aText = aText.replaceAt(aPos, 5, aMOD2); + aPos = aText.indexOf("%MOD2"); + } + m_pText->set_label(aText); + + // hyperlink + aLink = std::get<1>(TIPOFTHEDAY_STRINGARRAY[nCurrentTip]); + if (aLink.isEmpty()) + { + m_pLink->set_visible(false); + } + else if (aLink.startsWith("http")) + { + // Links may have some %PRODUCTVERSION which need to be expanded + aText = Translate::ExpandVariables(aLink); + aPos = aText.indexOf("%LANGUAGENAME"); + if (aPos != -1) + { + OUString aLang = LanguageTag(utl::ConfigManager::getUILocale()).getLanguage(); + if (aLang == "en" || aLang == "pt" || aLang == "zh") //en-US/GB, pt-BR, zh-CH/TW + aLang = LanguageTag(utl::ConfigManager::getUILocale()).getBcp47(); + aText = aText.replaceAt(aPos, 13, aLang); + } + m_pLink->set_uri(aText); + + m_pLink->set_label(CuiResId(STR_MORE_LINK)); + m_pLink->set_visible(true); + m_pLink->connect_activate_link(Link()); + } + else + { + m_pLink->set_uri(""); + m_pLink->set_label(CuiResId(STR_HELP_LINK)); + m_pLink->set_visible(true); + //converts aLink into the proper offline/online hyperlink + m_pLink->connect_activate_link(LINK(this, TipOfTheDayDialog, OnLinkClick)); + } + // image + OUString aURL("$BRAND_BASE_DIR/$BRAND_SHARE_SUBDIR/tipoftheday/"); + rtl::Bootstrap::expandMacros(aURL); + OUString aImage = std::get<2>(TIPOFTHEDAY_STRINGARRAY[nCurrentTip]); + // use default image if none is available with the number + if (aImage.isEmpty() || !file_exists(aURL + aImage)) + aImage = "tipoftheday.png"; + // draw image + Graphic aGraphic; + if (GraphicFilter::LoadGraphic(aURL + aImage, OUString(), aGraphic) == ERRCODE_NONE) + { + ScopedVclPtr m_pVirDev = m_pImage->create_virtual_device(); + m_pVirDev->SetOutputSizePixel(aGraphic.GetSizePixel()); + m_pVirDev->DrawBitmapEx(Point(0, 0), aGraphic.GetBitmapEx()); + m_pImage->set_image(m_pVirDev.get()); + m_pVirDev.disposeAndClear(); + } +} + +IMPL_LINK_NOARG(TipOfTheDayDialog, OnLinkClick, weld::LinkButton&, bool) +{ + Application::GetHelp()->Start(aLink, static_cast(nullptr)); + return true; +} + +IMPL_LINK_NOARG(TipOfTheDayDialog, OnNextClick, weld::Button&, void) +{ + nCurrentTip++; //zeroed at updatetip when out of range + UpdateTip(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/zoom.cxx b/cui/source/dialogs/zoom.cxx new file mode 100644 index 000000000..b80080dfa --- /dev/null +++ b/cui/source/dialogs/zoom.cxx @@ -0,0 +1,406 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ +const sal_uInt16 SPECIAL_FACTOR = 0xFFFF; + +} // anonymous namespace + +sal_uInt16 SvxZoomDialog::GetFactor() const +{ + if (m_x100Btn->get_active()) + return 100; + + if (m_xUserBtn->get_active()) + return static_cast(m_xUserEdit->get_value(FieldUnit::PERCENT)); + else + return SPECIAL_FACTOR; +} + +void SvxZoomDialog::SetFactor(sal_uInt16 nNewFactor, ZoomButtonId nButtonId) +{ + m_xUserEdit->set_sensitive(false); + + if (nButtonId == ZoomButtonId::NONE) + { + if (nNewFactor == 100) + { + m_x100Btn->set_active(true); + m_x100Btn->grab_focus(); + } + else + { + m_xUserBtn->set_active(true); + m_xUserEdit->set_sensitive(true); + m_xUserEdit->set_value(nNewFactor, FieldUnit::PERCENT); + m_xUserEdit->grab_focus(); + } + } + else + { + m_xUserEdit->set_value(nNewFactor, FieldUnit::PERCENT); + switch (nButtonId) + { + case ZoomButtonId::OPTIMAL: + { + m_xOptimalBtn->set_active(true); + m_xOptimalBtn->grab_focus(); + break; + } + case ZoomButtonId::PAGEWIDTH: + { + m_xPageWidthBtn->set_active(true); + m_xPageWidthBtn->grab_focus(); + break; + } + case ZoomButtonId::WHOLEPAGE: + { + m_xWholePageBtn->set_active(true); + m_xWholePageBtn->grab_focus(); + break; + } + default: + break; + } + } +} + +void SvxZoomDialog::HideButton(ZoomButtonId nButtonId) +{ + switch (nButtonId) + { + case ZoomButtonId::OPTIMAL: + m_xOptimalBtn->hide(); + break; + + case ZoomButtonId::PAGEWIDTH: + m_xPageWidthBtn->hide(); + break; + + case ZoomButtonId::WHOLEPAGE: + m_xWholePageBtn->hide(); + break; + + default: + OSL_FAIL("Wrong button number!"); + } +} + +void SvxZoomDialog::SetLimits(sal_uInt16 nMin, sal_uInt16 nMax) +{ + DBG_ASSERT(nMin < nMax, "invalid limits"); + m_xUserEdit->set_range(nMin, nMax, FieldUnit::PERCENT); +} + +const SfxItemSet* SvxZoomDialog::GetOutputItemSet() const { return m_pOutSet.get(); } + +SvxZoomDialog::SvxZoomDialog(weld::Window* pParent, const SfxItemSet& rCoreSet) + : SfxDialogController(pParent, "cui/ui/zoomdialog.ui", "ZoomDialog") + , m_rSet(rCoreSet) + , m_bModified(false) + , m_xOptimalBtn(m_xBuilder->weld_radio_button("optimal")) + , m_xWholePageBtn(m_xBuilder->weld_radio_button("fitwandh")) + , m_xPageWidthBtn(m_xBuilder->weld_radio_button("fitw")) + , m_x100Btn(m_xBuilder->weld_radio_button("100pc")) + , m_xUserBtn(m_xBuilder->weld_radio_button("variable")) + , m_xUserEdit(m_xBuilder->weld_metric_spin_button("zoomsb", FieldUnit::PERCENT)) + , m_xViewFrame(m_xBuilder->weld_widget("viewframe")) + , m_xAutomaticBtn(m_xBuilder->weld_radio_button("automatic")) + , m_xSingleBtn(m_xBuilder->weld_radio_button("singlepage")) + , m_xColumnsBtn(m_xBuilder->weld_radio_button("columns")) + , m_xColumnsEdit(m_xBuilder->weld_spin_button("columnssb")) + , m_xBookModeChk(m_xBuilder->weld_check_button("bookmode")) + , m_xOKBtn(m_xBuilder->weld_button("ok")) +{ + Link aLink = LINK(this, SvxZoomDialog, UserHdl); + m_x100Btn->connect_toggled(aLink); + m_xOptimalBtn->connect_toggled(aLink); + m_xPageWidthBtn->connect_toggled(aLink); + m_xWholePageBtn->connect_toggled(aLink); + m_xUserBtn->connect_toggled(aLink); + + Link aViewLayoutLink = LINK(this, SvxZoomDialog, ViewLayoutUserHdl); + m_xAutomaticBtn->connect_toggled(aViewLayoutLink); + m_xSingleBtn->connect_toggled(aViewLayoutLink); + m_xColumnsBtn->connect_toggled(aViewLayoutLink); + + Link aViewLayoutSpinLink + = LINK(this, SvxZoomDialog, ViewLayoutSpinHdl); + m_xColumnsEdit->connect_value_changed(aViewLayoutSpinLink); + + Link aViewLayoutCheckLink + = LINK(this, SvxZoomDialog, ViewLayoutCheckHdl); + m_xBookModeChk->connect_toggled(aViewLayoutCheckLink); + + m_xOKBtn->connect_clicked(LINK(this, SvxZoomDialog, OKHdl)); + m_xUserEdit->connect_value_changed(LINK(this, SvxZoomDialog, SpinHdl)); + + // default values + sal_uInt16 nValue = 100; + sal_uInt16 nMin = 10; + sal_uInt16 nMax = 1000; + + // maybe get the old value first + const SfxUInt16Item* pOldUserItem = nullptr; + SfxObjectShell* pShell = SfxObjectShell::Current(); + + if (pShell) + pOldUserItem = pShell->GetItem(SID_ATTR_ZOOM_USER); + + if (pOldUserItem) + nValue = pOldUserItem->GetValue(); + + // initialize UserEdit + if (nMin > nValue) + nMin = nValue; + if (nMax < nValue) + nMax = nValue; + + SetLimits(nMin, nMax); + m_xUserEdit->set_value(nValue, FieldUnit::PERCENT); + + const SfxPoolItem& rItem = m_rSet.Get(m_rSet.GetPool()->GetWhich(SID_ATTR_ZOOM)); + + if (nullptr != dynamic_cast(&rItem)) + { + const SvxZoomItem& rZoomItem = static_cast(rItem); + const sal_uInt16 nZoom = rZoomItem.GetValue(); + const SvxZoomType eType = rZoomItem.GetType(); + const SvxZoomEnableFlags nValSet = rZoomItem.GetValueSet(); + ZoomButtonId nButtonId = ZoomButtonId::NONE; + + switch (eType) + { + case SvxZoomType::OPTIMAL: + nButtonId = ZoomButtonId::OPTIMAL; + break; + case SvxZoomType::PAGEWIDTH: + nButtonId = ZoomButtonId::PAGEWIDTH; + break; + case SvxZoomType::WHOLEPAGE: + nButtonId = ZoomButtonId::WHOLEPAGE; + break; + case SvxZoomType::PERCENT: + break; + case SvxZoomType::PAGEWIDTH_NOBORDER: + break; + } + + if (!(SvxZoomEnableFlags::N100 & nValSet)) + m_x100Btn->set_sensitive(false); + if (!(SvxZoomEnableFlags::OPTIMAL & nValSet)) + m_xOptimalBtn->set_sensitive(false); + if (!(SvxZoomEnableFlags::PAGEWIDTH & nValSet)) + m_xPageWidthBtn->set_sensitive(false); + if (!(SvxZoomEnableFlags::WHOLEPAGE & nValSet)) + m_xWholePageBtn->set_sensitive(false); + + SetFactor(nZoom, nButtonId); + } + else + { + const sal_uInt16 nZoom = static_cast(rItem).GetValue(); + SetFactor(nZoom); + } + + const SfxPoolItem* pPoolViewLayoutItem = nullptr; + if (SfxItemState::SET == m_rSet.GetItemState(SID_ATTR_VIEWLAYOUT, false, &pPoolViewLayoutItem)) + { + const SvxViewLayoutItem* pViewLayoutItem + = static_cast(pPoolViewLayoutItem); + const sal_uInt16 nColumns = pViewLayoutItem->GetValue(); + const bool bBookMode = pViewLayoutItem->IsBookMode(); + + if (0 == nColumns) + { + m_xAutomaticBtn->set_active(true); + m_xColumnsEdit->set_value(2); + m_xColumnsEdit->set_sensitive(false); + m_xBookModeChk->set_sensitive(false); + } + else if (1 == nColumns) + { + m_xSingleBtn->set_active(true); + m_xColumnsEdit->set_value(2); + m_xColumnsEdit->set_sensitive(false); + m_xBookModeChk->set_sensitive(false); + } + else + { + m_xColumnsBtn->set_active(true); + if (!bBookMode) + { + m_xColumnsEdit->set_value(nColumns); + if (nColumns % 2 != 0) + m_xBookModeChk->set_sensitive(false); + } + else + { + m_xColumnsEdit->set_value(nColumns); + m_xBookModeChk->set_active(true); + } + } + } + else + { + // hide view layout related controls: + m_xViewFrame->set_sensitive(false); + } +} + +IMPL_LINK_NOARG(SvxZoomDialog, UserHdl, weld::ToggleButton&, void) +{ + m_bModified = true; + + if (m_xUserBtn->get_active()) + { + m_xUserEdit->set_sensitive(true); + m_xUserEdit->grab_focus(); + } + else + { + m_xUserEdit->set_sensitive(false); + } +} + +IMPL_LINK_NOARG(SvxZoomDialog, SpinHdl, weld::MetricSpinButton&, void) +{ + if (!m_xUserBtn->get_active()) + return; + + m_bModified = true; +} + +IMPL_LINK_NOARG(SvxZoomDialog, ViewLayoutUserHdl, weld::ToggleButton&, void) +{ + m_bModified = true; + + if (m_xAutomaticBtn->get_active() || m_xSingleBtn->get_active()) + { + m_xColumnsEdit->set_sensitive(false); + m_xBookModeChk->set_sensitive(false); + } + else if (m_xColumnsBtn->get_active()) + { + m_xColumnsEdit->set_sensitive(true); + m_xColumnsEdit->grab_focus(); + if (m_xColumnsEdit->get_value() % 2 == 0) + m_xBookModeChk->set_sensitive(true); + } +} + +IMPL_LINK_NOARG(SvxZoomDialog, ViewLayoutSpinHdl, weld::SpinButton&, void) +{ + if (!m_xColumnsBtn->get_active()) + return; + + if (m_xColumnsEdit->get_value() % 2 == 0) + { + m_xBookModeChk->set_sensitive(true); + } + else + { + m_xBookModeChk->set_active(false); + m_xBookModeChk->set_sensitive(false); + } + + m_bModified = true; +} + +IMPL_LINK_NOARG(SvxZoomDialog, ViewLayoutCheckHdl, weld::ToggleButton&, void) +{ + if (!m_xColumnsBtn->get_active()) + return; + + m_bModified = true; +} + +IMPL_LINK_NOARG(SvxZoomDialog, OKHdl, weld::Button&, void) +{ + if (m_bModified) + { + SvxZoomItem aZoomItem(SvxZoomType::PERCENT, 0, m_rSet.GetPool()->GetWhich(SID_ATTR_ZOOM)); + SvxViewLayoutItem aViewLayoutItem(0, false, + m_rSet.GetPool()->GetWhich(SID_ATTR_VIEWLAYOUT)); + + sal_uInt16 nFactor = GetFactor(); + + if (SPECIAL_FACTOR == nFactor) + { + if (m_xOptimalBtn->get_active()) + aZoomItem.SetType(SvxZoomType::OPTIMAL); + else if (m_xPageWidthBtn->get_active()) + aZoomItem.SetType(SvxZoomType::PAGEWIDTH); + else if (m_xWholePageBtn->get_active()) + aZoomItem.SetType(SvxZoomType::WHOLEPAGE); + } + else + { + aZoomItem.SetValue(nFactor); + } + + if (m_xAutomaticBtn->get_active()) + { + aViewLayoutItem.SetValue(0); + aViewLayoutItem.SetBookMode(false); + } + if (m_xSingleBtn->get_active()) + { + aViewLayoutItem.SetValue(1); + aViewLayoutItem.SetBookMode(false); + } + else if (m_xColumnsBtn->get_active()) + { + aViewLayoutItem.SetValue(static_cast(m_xColumnsEdit->get_value())); + aViewLayoutItem.SetBookMode(m_xBookModeChk->get_active()); + } + + m_pOutSet.reset(new SfxItemSet(m_rSet)); + m_pOutSet->Put(aZoomItem); + + // don't set attribute in case the whole viewlayout stuff is disabled: + if (m_xViewFrame->get_sensitive()) + m_pOutSet->Put(aViewLayoutItem); + + // memorize value from the UserEdit beyond the dialog + SfxObjectShell* pShell = SfxObjectShell::Current(); + + if (pShell) + { + sal_uInt16 nZoomValue + = static_cast(m_xUserEdit->get_value(FieldUnit::PERCENT)); + pShell->PutItem(SfxUInt16Item(SID_ATTR_ZOOM_USER, nZoomValue)); + } + m_xDialog->response(RET_OK); + } + else + m_xDialog->response(RET_CANCEL); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/factory/cuiexp.cxx b/cui/source/factory/cuiexp.cxx new file mode 100644 index 000000000..bbe1d7431 --- /dev/null +++ b/cui/source/factory/cuiexp.cxx @@ -0,0 +1,40 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "dlgfact.hxx" +#include + +namespace cui +{ + static AbstractDialogFactory_Impl* GetFactory() + { + static AbstractDialogFactory_Impl* pFactory = new AbstractDialogFactory_Impl; + return pFactory; + } +} + +extern "C" +{ + SAL_DLLPUBLIC_EXPORT VclAbstractDialogFactory* CreateDialogFactory() + { + return ::cui::GetFactory(); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/factory/cuiresmgr.cxx b/cui/source/factory/cuiresmgr.cxx new file mode 100644 index 000000000..b59f73cf8 --- /dev/null +++ b/cui/source/factory/cuiresmgr.cxx @@ -0,0 +1,28 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +OUString CuiResId(const char *pKey) +{ + return Translate::get(pKey, Translate::Create("cui")); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/factory/dlgfact.cxx b/cui/source/factory/dlgfact.cxx new file mode 100644 index 000000000..40102bae7 --- /dev/null +++ b/cui/source/factory/dlgfact.cxx @@ -0,0 +1,1699 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include "dlgfact.hxx" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::container; + +using ::com::sun::star::uno::Reference; + +using namespace svx; +// AbstractTabDialog implementations just forwards everything to the dialog + +short CuiAbstractController_Impl::Execute() +{ + return m_xDlg->run(); +} + +short CuiAbstractSingleTabController_Impl::Execute() +{ + return m_xDlg->run(); +} + +short AbstractSvxDistributeDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +short AbstractHangulHanjaConversionDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +short AbstractFmShowColsDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +short AbstractHyphenWordDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +short AbstractThesaurusDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +bool AbstractThesaurusDialog_Impl::StartExecuteAsync(AsyncContext &rCtx) +{ + return SfxDialogController::runAsync(m_xDlg, rCtx.maEndDialogFn); +} + +short AbstractSvxZoomDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +short AbstractTitleDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +short AbstractScriptSelectorDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +short AbstractGalleryIdDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +short AbstractURLDlg_Impl::Execute() +{ + return m_xDlg->run(); +} + +short AbstractSvxSearchSimilarityDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +short AbstractSvxTransformTabDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +bool AbstractSvxTransformTabDialog_Impl::StartExecuteAsync(AsyncContext &rCtx) +{ + return SfxTabDialogController::runAsync(m_xDlg, rCtx.maEndDialogFn); +} + +short AbstractSvxCaptionDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +bool AbstractSvxCaptionDialog_Impl::StartExecuteAsync(AsyncContext &rCtx) +{ + return SfxTabDialogController::runAsync(m_xDlg, rCtx.maEndDialogFn); +} + +short AbstractSvxJSearchOptionsDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +short AbstractFmInputRecordNoDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +short AbstractSvxNewDictionaryDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +short AbstractSvxNameDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +// #i68101# +short AbstractSvxObjectNameDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +short AbstractSvxObjectTitleDescDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +short AbstractSvxMultiPathDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +short AbstractSvxPathSelectDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +short AbstractSvxHpLinkDlg_Impl::Execute() +{ + return m_xDlg->run(); +} + +short AbstractFmSearchDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +short AbstractGraphicFilterDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +short AbstractSvxAreaTabDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +bool AbstractSvxAreaTabDialog_Impl::StartExecuteAsync(AsyncContext &rCtx) +{ + return SfxTabDialogController::runAsync(m_xDlg, rCtx.maEndDialogFn); +} + +short AbstractPasteDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +bool AbstractPasteDialog_Impl::StartExecuteAsync(AsyncContext &rCtx) +{ + return SfxDialogController::runAsync(m_xDlg, rCtx.maEndDialogFn); +} + +short AbstractInsertObjectDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +short AbstractLinksDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +short AbstractSpellDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +bool AbstractSpellDialog_Impl::StartExecuteAsync(AsyncContext &rCtx) +{ + return SfxDialogController::runAsync(m_xDlg, rCtx.maEndDialogFn); +} + +short AbstractSvxPostItDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +short AbstractPasswordToOpenModifyDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +short AbstractSvxCharacterMapDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +const SfxItemSet* AbstractSvxCharacterMapDialog_Impl::GetOutputItemSet() const +{ + return m_xDlg->GetOutputItemSet(); +} + +void AbstractSvxCharacterMapDialog_Impl::SetText(const OUString& rStr) +{ + m_xDlg->set_title(rStr); +} + +short AbstractSignatureLineDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +short AbstractSignSignatureLineDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +short AbstractQrCodeGenDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +short AbstractScreenshotAnnotationDlg_Impl::Execute() +{ + return m_xDlg->run(); +} + +short CuiAbstractTabController_Impl::Execute() +{ + return m_xDlg->run(); +} + +bool CuiAbstractTabController_Impl::StartExecuteAsync(AsyncContext &rCtx) +{ + return SfxTabDialogController::runAsync(m_xDlg, rCtx.maEndDialogFn); +} + +void CuiAbstractTabController_Impl::SetCurPageId( const OString &rName ) +{ + m_xDlg->SetCurPageId( rName ); +} + +const SfxItemSet* CuiAbstractTabController_Impl::GetOutputItemSet() const +{ + return m_xDlg->GetOutputItemSet(); +} + +const sal_uInt16* CuiAbstractTabController_Impl::GetInputRanges(const SfxItemPool& pItem ) +{ + return m_xDlg->GetInputRanges( pItem ); +} + +void CuiAbstractTabController_Impl::SetInputSet( const SfxItemSet* pInSet ) +{ + m_xDlg->SetInputSet( pInSet ); +} + +//From class Window. +void CuiAbstractTabController_Impl::SetText( const OUString& rStr ) +{ + m_xDlg->set_title(rStr); +} + +std::vector CuiAbstractTabController_Impl::getAllPageUIXMLDescriptions() const +{ + return m_xDlg->getAllPageUIXMLDescriptions(); +} + +bool CuiAbstractTabController_Impl::selectPageByUIXMLDescription(const OString& rUIXMLDescription) +{ + return m_xDlg->selectPageByUIXMLDescription(rUIXMLDescription); +} + +BitmapEx CuiAbstractTabController_Impl::createScreenshot() const +{ + return m_xDlg->createScreenshot(); +} + +OString CuiAbstractTabController_Impl::GetScreenshotId() const +{ + return m_xDlg->GetScreenshotId(); +} + +const SfxItemSet* CuiAbstractSingleTabController_Impl::GetOutputItemSet() const +{ + return m_xDlg->GetOutputItemSet(); +} + +void CuiAbstractSingleTabController_Impl::SetText(const OUString& rStr) +{ + m_xDlg->set_title(rStr); +} + +SvxDistributeHorizontal AbstractSvxDistributeDialog_Impl::GetDistributeHor()const +{ + return m_xDlg->GetDistributeHor(); +} +SvxDistributeVertical AbstractSvxDistributeDialog_Impl::GetDistributeVer()const +{ + return m_xDlg->GetDistributeVer(); +} + +void AbstractHangulHanjaConversionDialog_Impl::EndDialog(sal_Int32 nResult) +{ + m_xDlg->response(nResult); +} + +void AbstractHangulHanjaConversionDialog_Impl::EnableRubySupport( bool _bVal ) +{ + m_xDlg->EnableRubySupport(_bVal); +} + +void AbstractHangulHanjaConversionDialog_Impl::SetByCharacter( bool _bByCharacter ) +{ + m_xDlg->SetByCharacter(_bByCharacter); +} + +void AbstractHangulHanjaConversionDialog_Impl::SetConversionDirectionState( bool _bTryBothDirections, editeng::HangulHanjaConversion::ConversionDirection _ePrimaryConversionDirection ) +{ + m_xDlg->SetConversionDirectionState(_bTryBothDirections, _ePrimaryConversionDirection); +} + +void AbstractHangulHanjaConversionDialog_Impl::SetConversionFormat( editeng::HangulHanjaConversion::ConversionFormat _eType ) +{ + m_xDlg->SetConversionFormat(_eType); +} + +void AbstractHangulHanjaConversionDialog_Impl::SetOptionsChangedHdl( const Link& _rHdl ) +{ + m_xDlg->SetOptionsChangedHdl(_rHdl ); +} + +void AbstractHangulHanjaConversionDialog_Impl::SetIgnoreHdl( const Link& _rHdl ) +{ + m_xDlg->SetIgnoreHdl(_rHdl ); +} + +void AbstractHangulHanjaConversionDialog_Impl::SetIgnoreAllHdl(const Link& rHdl) +{ + m_xDlg->SetIgnoreAllHdl(rHdl); +} + +void AbstractHangulHanjaConversionDialog_Impl::SetChangeHdl(const Link& rHdl) +{ + m_xDlg->SetChangeHdl(rHdl); +} + +void AbstractHangulHanjaConversionDialog_Impl::SetChangeAllHdl( const Link& rHdl ) +{ + m_xDlg->SetChangeAllHdl(rHdl); +} + +void AbstractHangulHanjaConversionDialog_Impl::SetClickByCharacterHdl( const Link& _rHdl ) +{ + m_xDlg->SetClickByCharacterHdl(_rHdl ); +} + +void AbstractHangulHanjaConversionDialog_Impl::SetConversionFormatChangedHdl(const Link& rHdl) +{ + m_xDlg->SetConversionFormatChangedHdl(rHdl); +} + +void AbstractHangulHanjaConversionDialog_Impl::SetFindHdl( const Link& rHdl ) +{ + m_xDlg->SetFindHdl(rHdl); +} + +bool AbstractHangulHanjaConversionDialog_Impl::GetUseBothDirections( ) const +{ + return m_xDlg->GetUseBothDirections(); +} + +editeng::HangulHanjaConversion::ConversionDirection AbstractHangulHanjaConversionDialog_Impl::GetDirection( editeng::HangulHanjaConversion::ConversionDirection _eDefaultDirection ) const +{ + return m_xDlg->GetDirection( _eDefaultDirection ); +} + +void AbstractHangulHanjaConversionDialog_Impl::SetCurrentString( + const OUString& _rNewString, + const css::uno::Sequence< OUString >& _rSuggestions, + bool _bOriginatesFromDocument + ) +{ + m_xDlg->SetCurrentString(_rNewString,_rSuggestions,_bOriginatesFromDocument); +} + +OUString AbstractHangulHanjaConversionDialog_Impl::GetCurrentString( ) const +{ + return m_xDlg->GetCurrentString(); +} + +editeng::HangulHanjaConversion::ConversionFormat AbstractHangulHanjaConversionDialog_Impl::GetConversionFormat( ) const +{ + return m_xDlg->GetConversionFormat(); +} + +void AbstractHangulHanjaConversionDialog_Impl::FocusSuggestion( ) +{ + m_xDlg->FocusSuggestion(); +} + +OUString AbstractHangulHanjaConversionDialog_Impl::GetCurrentSuggestion( ) const +{ + return m_xDlg->GetCurrentSuggestion(); +} + +OUString AbstractThesaurusDialog_Impl::GetWord() +{ + return m_xDlg->GetWord(); +}; + +Reference < css::embed::XEmbeddedObject > AbstractInsertObjectDialog_Impl::GetObject() +{ + return m_xDlg->GetObject(); +} + +bool AbstractInsertObjectDialog_Impl::IsCreateNew() +{ + return m_xDlg->IsCreateNew(); +} + +::Reference< css::io::XInputStream > AbstractInsertObjectDialog_Impl::GetIconIfIconified( OUString* pGraphicMediaType ) +{ + return m_xDlg->GetIconIfIconified( pGraphicMediaType ); +} + +void AbstractPasteDialog_Impl::Insert(SotClipboardFormatId nFormat, const OUString& rFormatName) +{ + m_xDlg->Insert(nFormat, rFormatName); +} + +void AbstractPasteDialog_Impl::InsertUno(const OUString& sCmd, const OUString& sLabel) +{ + m_xDlg->InsertUno(sCmd, sLabel); +} + +void AbstractPasteDialog_Impl::SetObjName(const SvGlobalName & rClass, const OUString& rObjName) +{ + m_xDlg->SetObjName(rClass, rObjName); +} + +void AbstractPasteDialog_Impl::PreGetFormat( const TransferableDataHelper& aHelper ) +{ + m_xDlg->PreGetFormat(aHelper); +} + +SotClipboardFormatId AbstractPasteDialog_Impl::GetFormatOnly() +{ + return m_xDlg->GetFormatOnly(); +} + +SotClipboardFormatId AbstractPasteDialog_Impl::GetFormat( const TransferableDataHelper& aHelper ) +{ + return m_xDlg->GetFormat(aHelper); +} + +void AbstractFmShowColsDialog_Impl::SetColumns(const ::Reference< css::container::XIndexContainer>& xCols) +{ + m_xDlg->SetColumns(xCols); +} + +void AbstractSvxZoomDialog_Impl::SetLimits( sal_uInt16 nMin, sal_uInt16 nMax ) +{ + m_xDlg->SetLimits( nMin, nMax ); +} + +void AbstractSvxZoomDialog_Impl::HideButton( ZoomButtonId nBtnId ) +{ + m_xDlg->HideButton( nBtnId ); +} + +const SfxItemSet* AbstractSvxZoomDialog_Impl::GetOutputItemSet() const +{ + return m_xDlg->GetOutputItemSet(); +} + +void AbstractSpellDialog_Impl::InvalidateDialog() +{ + m_xDlg->InvalidateDialog(); +} + +std::shared_ptr AbstractSpellDialog_Impl::GetController() +{ + return m_xDlg; +} + +SfxBindings& AbstractSpellDialog_Impl::GetBindings() +{ + return m_xDlg->GetBindings(); +} + +OUString AbstractTitleDialog_Impl::GetTitle() const +{ + return m_xDlg->GetTitle(); +} + +sal_uInt32 AbstractGalleryIdDialog_Impl::GetId() const +{ + return m_xDlg->GetId(); +} + +OUString AbstractURLDlg_Impl::GetURL() const +{ + return m_xDlg->GetURL(); +} + +OUString AbstractURLDlg_Impl::GetAltText() const +{ + return m_xDlg->GetAltText(); +} + +OUString AbstractURLDlg_Impl::GetDesc() const +{ + return m_xDlg->GetDesc(); +} + +OUString AbstractURLDlg_Impl::GetTarget() const +{ + return m_xDlg->GetTarget(); +} + +OUString AbstractURLDlg_Impl::GetName() const +{ + return m_xDlg->GetName(); +} + +sal_uInt16 AbstractSvxSearchSimilarityDialog_Impl::GetOther() +{ + return m_xDlg->GetOther(); +} + +sal_uInt16 AbstractSvxSearchSimilarityDialog_Impl::GetShorter() +{ + return m_xDlg->GetShorter(); +} + +sal_uInt16 AbstractSvxSearchSimilarityDialog_Impl::GetLonger() +{ + return m_xDlg->GetLonger(); +} + +bool AbstractSvxSearchSimilarityDialog_Impl::IsRelaxed() +{ + return m_xDlg->IsRelaxed(); +} + +// AbstractSvxTransformTabDialog implementations just forwards everything to the dialog +void AbstractSvxTransformTabDialog_Impl::SetCurPageId( const OString& rName ) +{ + m_xDlg->SetCurPageId( rName ); +} + +const SfxItemSet* AbstractSvxTransformTabDialog_Impl::GetOutputItemSet() const +{ + return m_xDlg->GetOutputItemSet(); +} + +const sal_uInt16* AbstractSvxTransformTabDialog_Impl::GetInputRanges(const SfxItemPool& pItem ) +{ + return m_xDlg->GetInputRanges( pItem ); +} + +void AbstractSvxTransformTabDialog_Impl::SetInputSet( const SfxItemSet* pInSet ) +{ + m_xDlg->SetInputSet( pInSet ); +} + +//From class Window. +void AbstractSvxTransformTabDialog_Impl::SetText( const OUString& rStr ) +{ + m_xDlg->set_title(rStr); +} + +void AbstractSvxTransformTabDialog_Impl::SetValidateFramePosLink( const Link& rLink ) +{ + m_xDlg->SetValidateFramePosLink( rLink ); +} + +// AbstractSvxCaptionDialog implementations just forwards everything to the dialog +void AbstractSvxCaptionDialog_Impl::SetCurPageId( const OString& rName ) +{ + m_xDlg->SetCurPageId(rName); +} + +const SfxItemSet* AbstractSvxCaptionDialog_Impl::GetOutputItemSet() const +{ + return m_xDlg->GetOutputItemSet(); +} + +const sal_uInt16* AbstractSvxCaptionDialog_Impl::GetInputRanges(const SfxItemPool& pItem ) +{ + return m_xDlg->GetInputRanges( pItem ); +} + +void AbstractSvxCaptionDialog_Impl::SetInputSet( const SfxItemSet* pInSet ) +{ + m_xDlg->SetInputSet( pInSet ); +} + +void AbstractSvxCaptionDialog_Impl::SetText( const OUString& rStr ) +{ + m_xDlg->set_title(rStr); +} + +void AbstractSvxCaptionDialog_Impl::SetValidateFramePosLink( const Link& rLink ) +{ + m_xDlg->SetValidateFramePosLink( rLink ); +} + +TransliterationFlags AbstractSvxJSearchOptionsDialog_Impl::GetTransliterationFlags() const +{ + return m_xDlg->GetTransliterationFlags(); +} + +void AbstractFmInputRecordNoDialog_Impl::SetValue(long nNew) +{ + m_xDlg->SetValue(nNew); +} + +long AbstractFmInputRecordNoDialog_Impl::GetValue() const +{ + return m_xDlg->GetValue(); +} + +::Reference< css::linguistic2::XDictionary > AbstractSvxNewDictionaryDialog_Impl::GetNewDictionary() +{ + return m_xDlg->GetNewDictionary(); +} + +void AbstractSvxNameDialog_Impl::GetName(OUString& rName) +{ + rName = m_xDlg->GetName(); +} + +void AbstractSvxNameDialog_Impl::SetCheckNameHdl( const Link& rLink, bool bCheckImmediately ) +{ + aCheckNameHdl = rLink; + if( rLink.IsSet() ) + m_xDlg->SetCheckNameHdl( LINK(this, AbstractSvxNameDialog_Impl, CheckNameHdl), bCheckImmediately ); + else + m_xDlg->SetCheckNameHdl( Link(), bCheckImmediately ); +} + +void AbstractSvxNameDialog_Impl::SetCheckNameTooltipHdl( const Link& rLink) +{ + aCheckNameTooltipHdl = rLink; + if( rLink.IsSet() ) + m_xDlg->SetCheckNameTooltipHdl( LINK(this, AbstractSvxNameDialog_Impl, CheckNameTooltipHdl)); + else + m_xDlg->SetCheckNameTooltipHdl( Link()); +} + +void AbstractSvxNameDialog_Impl::SetEditHelpId(const OString& rHelpId) +{ + m_xDlg->SetEditHelpId(rHelpId); +} + +void AbstractSvxNameDialog_Impl::SetHelpId(const OString& rHelpId) +{ + m_xDlg->set_help_id(rHelpId); +} + +void AbstractSvxNameDialog_Impl::SetText( const OUString& rStr ) +{ + m_xDlg->set_title(rStr); +} + +IMPL_LINK_NOARG(AbstractSvxNameDialog_Impl, CheckNameHdl, SvxNameDialog&, bool) +{ + return aCheckNameHdl.Call(*this); +} + +IMPL_LINK_NOARG(AbstractSvxNameDialog_Impl, CheckNameTooltipHdl, SvxNameDialog&, OUString) +{ + return aCheckNameTooltipHdl.Call(*this); +} + +void AbstractSvxObjectNameDialog_Impl::GetName(OUString& rName) +{ + rName = m_xDlg->GetName(); +} + +void AbstractSvxObjectNameDialog_Impl::SetCheckNameHdl(const Link& rLink) +{ + aCheckNameHdl = rLink; + + if(rLink.IsSet()) + { + m_xDlg->SetCheckNameHdl(LINK(this, AbstractSvxObjectNameDialog_Impl, CheckNameHdl)); + } + else + { + m_xDlg->SetCheckNameHdl(Link()); + } +} + +IMPL_LINK_NOARG(AbstractSvxObjectNameDialog_Impl, CheckNameHdl, SvxObjectNameDialog&, bool) +{ + return aCheckNameHdl.Call(*this); +} + +void AbstractSvxObjectTitleDescDialog_Impl::GetTitle(OUString& rTitle) +{ + rTitle = m_xDlg->GetTitle(); +} + +void AbstractSvxObjectTitleDescDialog_Impl::GetDescription(OUString& rDescription) +{ + rDescription = m_xDlg->GetDescription(); +} + +OUString AbstractSvxMultiPathDialog_Impl::GetPath() const +{ + return m_xDlg->GetPath(); +} + +void AbstractSvxMultiPathDialog_Impl::SetPath( const OUString& rPath ) +{ + m_xDlg->SetPath( rPath ); +} + +void AbstractSvxMultiPathDialog_Impl::SetTitle( const OUString& rNewTitle ) +{ + m_xDlg->SetTitle(rNewTitle); +} + +OUString AbstractSvxPathSelectDialog_Impl::GetPath() const +{ + return m_xDlg->GetPath(); +} + +void AbstractSvxPathSelectDialog_Impl::SetPath( const OUString& rPath ) +{ + m_xDlg->SetPath( rPath ); +} + +void AbstractSvxPathSelectDialog_Impl::SetTitle( const OUString& rNewTitle ) +{ + m_xDlg->SetTitle(rNewTitle); +} + +std::shared_ptr AbstractSvxHpLinkDlg_Impl::GetController() +{ + return m_xDlg; +} + +bool AbstractSvxHpLinkDlg_Impl::QueryClose() +{ + return m_xDlg->QueryClose(); +} + +void AbstractFmSearchDialog_Impl::SetFoundHandler(const Link& lnk) +{ + m_xDlg->SetFoundHandler(lnk); +} + +void AbstractFmSearchDialog_Impl::SetCanceledNotFoundHdl(const Link& lnk) +{ + m_xDlg->SetCanceledNotFoundHdl(lnk); +} + +void AbstractFmSearchDialog_Impl::SetActiveField(const OUString& strField) +{ + m_xDlg->SetActiveField(strField); +} + +Graphic AbstractGraphicFilterDialog_Impl::GetFilteredGraphic(const Graphic& rGraphic, double fScaleX, double fScaleY) +{ + return m_xDlg->GetFilteredGraphic(rGraphic, fScaleX, fScaleY); +} + +// AbstractSvxAreaTabDialog implementations just forwards everything to the dialog +void AbstractSvxAreaTabDialog_Impl::SetCurPageId( const OString& rName ) +{ + m_xDlg->SetCurPageId( rName ); +} + +const SfxItemSet* AbstractSvxAreaTabDialog_Impl::GetOutputItemSet() const +{ + return m_xDlg->GetOutputItemSet(); +} + +const sal_uInt16* AbstractSvxAreaTabDialog_Impl::GetInputRanges(const SfxItemPool& pItem ) +{ + return m_xDlg->GetInputRanges( pItem ); +} + +void AbstractSvxAreaTabDialog_Impl::SetInputSet( const SfxItemSet* pInSet ) +{ + m_xDlg->SetInputSet( pInSet ); +} + +void AbstractSvxAreaTabDialog_Impl::SetText( const OUString& rStr ) +{ + m_xDlg->set_title(rStr); +} + +void AbstractSvxPostItDialog_Impl::SetText( const OUString& rStr ) +{ + m_xDlg->set_title(rStr); +} + +const SfxItemSet* AbstractSvxPostItDialog_Impl::GetOutputItemSet() const +{ + return m_xDlg->GetOutputItemSet(); +} + +void AbstractSvxPostItDialog_Impl::EnableTravel(bool bNext, bool bPrev) +{ + m_xDlg->EnableTravel( bNext, bPrev ); +} + +OUString AbstractSvxPostItDialog_Impl::GetNote() +{ + return m_xDlg->GetNote(); +} + +void AbstractSvxPostItDialog_Impl::SetNote(const OUString& rTxt) +{ + m_xDlg->SetNote( rTxt ); +} + +void AbstractSvxPostItDialog_Impl::ShowLastAuthor(const OUString& rAuthor, const OUString& rDate) +{ + m_xDlg->ShowLastAuthor( rAuthor, rDate ); +} + +void AbstractSvxPostItDialog_Impl::DontChangeAuthor() +{ + m_xDlg->DontChangeAuthor(); +} + +void AbstractSvxPostItDialog_Impl::HideAuthor() +{ + m_xDlg->HideAuthor(); +} + +void AbstractSvxPostItDialog_Impl::SetNextHdl( const Link& rLink ) +{ + aNextHdl = rLink; + if( rLink.IsSet() ) + m_xDlg->SetNextHdl( LINK(this, AbstractSvxPostItDialog_Impl, NextHdl ) ); + else + m_xDlg->SetNextHdl( Link() ); +} + +void AbstractSvxPostItDialog_Impl::SetPrevHdl( const Link& rLink ) +{ + aPrevHdl = rLink; + if( rLink.IsSet() ) + m_xDlg->SetPrevHdl( LINK(this, AbstractSvxPostItDialog_Impl, PrevHdl ) ); + else + m_xDlg->SetPrevHdl( Link() ); +} + +IMPL_LINK_NOARG(AbstractSvxPostItDialog_Impl, NextHdl, SvxPostItDialog&, void) +{ + aNextHdl.Call(*this); +} + +IMPL_LINK_NOARG(AbstractSvxPostItDialog_Impl, PrevHdl, SvxPostItDialog&, void) +{ + aPrevHdl.Call(*this); +} + +std::shared_ptr AbstractSvxPostItDialog_Impl::GetDialog() +{ + return m_xDlg->GetDialog(); +} + +OUString AbstractPasswordToOpenModifyDialog_Impl::GetPasswordToOpen() const +{ + return m_xDlg->GetPasswordToOpen(); +} + +OUString AbstractPasswordToOpenModifyDialog_Impl::GetPasswordToModify() const +{ + return m_xDlg->GetPasswordToModify(); +} + +bool AbstractPasswordToOpenModifyDialog_Impl::IsRecommendToOpenReadonly() const +{ + return m_xDlg->IsRecommendToOpenReadonly(); +} + +// Create dialogs with simplest interface +VclPtr AbstractDialogFactory_Impl::CreateVclDialog(weld::Window* pParent, sal_uInt32 nResId) +{ + std::unique_ptr xDlg; + switch ( nResId ) + { + case SID_OPTIONS_TREEDIALOG : + case SID_OPTIONS_DATABASES : + case SID_LANGUAGE_OPTIONS : + { + bool bActivateLastSelection = false; + if (nResId == SID_OPTIONS_TREEDIALOG) + bActivateLastSelection = true; + Reference< frame::XFrame > xFrame; + xDlg = std::make_unique(pParent, xFrame, bActivateLastSelection); + if (nResId == SID_OPTIONS_DATABASES) + { + xDlg->ActivatePage(SID_SB_DBREGISTEROPTIONS); + } + else if (nResId == SID_LANGUAGE_OPTIONS) + { + //open the tab page "tools/options/languages" + xDlg->ActivatePage(OFA_TP_LANGUAGES_FOR_SET_DOCUMENT_LANGUAGE); + } + } + break; + default: + break; + } + + if (xDlg) + return VclPtr::Create(std::move(xDlg)); + return nullptr; +} + +VclPtr AbstractDialogFactory_Impl::CreateFrameDialog(weld::Window* pParent, const Reference< frame::XFrame >& rxFrame, + sal_uInt32 nResId, const OUString& rParameter ) +{ + std::unique_ptr xDlg; + if (SID_OPTIONS_TREEDIALOG == nResId || SID_OPTIONS_DATABASES == nResId) + { + // only activate last page if we don't want to activate a special page + bool bActivateLastSelection = ( nResId != SID_OPTIONS_DATABASES && rParameter.isEmpty() ); + xDlg = std::make_unique(pParent, rxFrame, bActivateLastSelection); + if ( nResId == SID_OPTIONS_DATABASES ) + xDlg->ActivatePage(SID_SB_DBREGISTEROPTIONS); + else if ( !rParameter.isEmpty() ) + xDlg->ActivatePage( rParameter ); + } + + if (xDlg) + return VclPtr::Create(std::move(xDlg)); + return nullptr; +} + +// TabDialog outside the drawing layer +VclPtr AbstractDialogFactory_Impl::CreateAutoCorrTabDialog(weld::Window* pParent, const SfxItemSet* pAttrSet) +{ + return VclPtr::Create(std::make_shared(pParent, pAttrSet)); +} + +VclPtr AbstractDialogFactory_Impl::CreateCustomizeTabDialog(weld::Window* pParent, + const SfxItemSet* pAttrSet, + const Reference< frame::XFrame >& xViewFrame ) +{ + auto xDlg1 = std::make_shared(pParent, pAttrSet); + xDlg1->SetFrame(xViewFrame); + return VclPtr::Create(std::move(xDlg1)); +} + +// TabDialog that use functionality of the drawing layer +VclPtr AbstractDialogFactory_Impl::CreateTextTabDialog(weld::Window* pParent, + const SfxItemSet* pAttrSet, + SdrView* pView) +{ + return VclPtr::Create(std::make_shared(pParent, pAttrSet, pView)); +} + +// TabDialog that use functionality of the drawing layer and add AnchorTypes -- for SvxCaptionTabDialog +VclPtr AbstractDialogFactory_Impl::CreateCaptionDialog(weld::Window* pParent, + const SdrView* pView, + SvxAnchorIds nAnchorTypes) +{ + return VclPtr::Create(std::make_shared(pParent, pView, nAnchorTypes)); +} + +VclPtr AbstractDialogFactory_Impl::CreateSvxDistributeDialog(weld::Window* pParent, + const SfxItemSet& rAttr) +{ + return VclPtr::Create(std::make_unique(pParent, rAttr, SvxDistributeHorizontal::NONE, SvxDistributeVertical::NONE)); +} + +VclPtr AbstractDialogFactory_Impl::CreateHangulHanjaConversionDialog(weld::Window* pParent) +{ + return VclPtr::Create(std::make_unique(pParent)); +} + +VclPtr AbstractDialogFactory_Impl::CreateThesaurusDialog(weld::Window* pParent, + css::uno::Reference xThesaurus, + const OUString &rWord, LanguageType nLanguage) +{ + return VclPtr::Create(std::make_shared(pParent, xThesaurus, rWord, nLanguage)); +} + +VclPtr AbstractDialogFactory_Impl::CreateHyphenWordDialog(weld::Window* pParent, + const OUString &rWord, LanguageType nLang, + css::uno::Reference< css::linguistic2::XHyphenator > &xHyphen, + SvxSpellWrapper* pWrapper) +{ + return VclPtr::Create(std::make_unique(rWord, nLang, pParent, xHyphen, pWrapper)); +} + +VclPtr AbstractDialogFactory_Impl::CreateFmShowColsDialog(weld::Window* pParent) +{ + return VclPtr::Create(std::make_unique(pParent)); +} + +VclPtr AbstractDialogFactory_Impl::CreateSvxZoomDialog(weld::Window* pParent, const SfxItemSet& rCoreSet) +{ + return VclPtr::Create(std::make_unique(pParent, rCoreSet)); +} + +VclPtr AbstractDialogFactory_Impl::CreateSvxSpellDialog( + weld::Window* pParent, + SfxBindings* pBindings, + svx::SpellDialogChildWindow* pSpellChildWindow) +{ + return VclPtr::Create(std::make_shared(pSpellChildWindow, pParent, pBindings)); +} + +VclPtr AbstractDialogFactory_Impl::CreateActualizeProgressDialog(weld::Widget* pParent, + GalleryTheme* pThm) +{ + return VclPtr::Create(std::make_unique(pParent, pThm)); +} + +VclPtr AbstractDialogFactory_Impl::CreateScriptErrorDialog(const css::uno::Any& rException) +{ + return VclPtr::Create(rException); +} + +VclPtr AbstractDialogFactory_Impl::CreateScriptSelectorDialog(weld::Window* pParent, + const Reference& rxFrame) +{ + return VclPtr::Create(std::make_unique(pParent, rxFrame)); +} + +OUString AbstractScriptSelectorDialog_Impl::GetScriptURL() const +{ + return m_xDlg->GetScriptURL(); +} + +void AbstractScriptSelectorDialog_Impl::SetRunLabel() +{ + m_xDlg->SetRunLabel(); +} + +VclPtr AbstractDialogFactory_Impl::CreateSvxScriptOrgDialog(weld::Window* pParent, + const OUString& rLanguage) +{ + return VclPtr::Create(std::make_unique(pParent, rLanguage)); +} + +VclPtr AbstractDialogFactory_Impl::CreateTitleDialog(weld::Widget* pParent, + const OUString& rOldText) +{ + return VclPtr::Create(std::make_unique(pParent, rOldText)); +} + +VclPtr AbstractDialogFactory_Impl::CreateGalleryIdDialog(weld::Widget* pParent, + GalleryTheme* pThm) +{ + return VclPtr::Create(std::make_unique(pParent, pThm)); +} + +VclPtr AbstractDialogFactory_Impl::CreateGalleryThemePropertiesDialog(weld::Widget* pParent, + ExchangeData* pData, + SfxItemSet* pItemSet) +{ + return VclPtr::Create(std::make_shared( + pParent, pData, pItemSet)); +} + +VclPtr AbstractDialogFactory_Impl::CreateURLDialog(weld::Widget* pParent, + const OUString& rURL, const OUString& rAltText, const OUString& rDescription, + const OUString& rTarget, const OUString& rName, + TargetList& rTargetList ) +{ + return VclPtr::Create(std::make_unique(pParent, rURL, rAltText, rDescription, + rTarget, rName, rTargetList)); + +} + +VclPtr AbstractDialogFactory_Impl::CreateTabItemDialog(weld::Window* pParent, + const SfxItemSet& rSet) +{ + return VclPtr::Create(std::make_shared( + pParent, rSet)); +} + +VclPtr AbstractDialogFactory_Impl::CreateSvxSearchAttributeDialog(weld::Window* pParent, + SearchAttrItemList& rLst, + const sal_uInt16* pWhRanges ) +{ + return VclPtr::Create(std::make_unique(pParent, rLst, pWhRanges)); +} + +VclPtr AbstractDialogFactory_Impl::CreateSvxSearchSimilarityDialog(weld::Window* pParent, + bool bRelax, + sal_uInt16 nOther, + sal_uInt16 nShorter, + sal_uInt16 nLonger) +{ + return VclPtr::Create(std::make_unique(pParent, bRelax, nOther, nShorter, nLonger)); +} + +VclPtr AbstractDialogFactory_Impl::CreateSvxBorderBackgroundDlg( + weld::Window* pParent, + const SfxItemSet& rCoreSet, + bool bEnableDrawingLayerFillStyles) +{ + return VclPtr::Create(std::make_shared( + pParent, + rCoreSet, + /*bEnableSelector*/true, + bEnableDrawingLayerFillStyles)); +} + +VclPtr AbstractDialogFactory_Impl::CreateSvxTransformTabDialog(weld::Window* pParent, + const SfxItemSet* pAttr, + const SdrView* pView, + SvxAnchorIds nAnchorTypes) +{ + return VclPtr::Create(std::make_shared(pParent, pAttr,pView, nAnchorTypes)); +} + +VclPtr AbstractDialogFactory_Impl::CreateSchTransformTabDialog(weld::Window* pParent, + const SfxItemSet* pAttr, + const SdrView* pSdrView, + bool bSizeTabPage) +{ + auto pDlg = std::make_shared(pParent, pAttr, pSdrView, + bSizeTabPage ? SvxAnchorIds::NoProtect : SvxAnchorIds::NoProtect|SvxAnchorIds::NoResize); + pDlg->RemoveTabPage( "RID_SVXPAGE_ANGLE" ); + pDlg->RemoveTabPage( "RID_SVXPAGE_SLANT" ); + return VclPtr::Create(std::move(pDlg)); +} + +VclPtr AbstractDialogFactory_Impl::CreateSvxJSearchOptionsDialog(weld::Window* pParent, + const SfxItemSet& rOptionsSet, + TransliterationFlags nInitialFlags) +{ + return VclPtr::Create(std::make_unique(pParent, rOptionsSet, nInitialFlags)); +} + +VclPtr AbstractDialogFactory_Impl::CreateFmInputRecordNoDialog(weld::Window* pParent) +{ + return VclPtr::Create(std::make_unique(pParent)); +} + +VclPtr AbstractDialogFactory_Impl::CreateSvxNewDictionaryDialog(weld::Window* pParent) +{ + return VclPtr::Create(std::make_unique(pParent)); +} + +VclPtr AbstractDialogFactory_Impl::CreateSvxEditDictionaryDialog(weld::Window* pParent, const OUString& rName) +{ + return VclPtr::Create(std::make_unique(pParent, rName)); +} + +VclPtr AbstractDialogFactory_Impl::CreateSvxNameDialog(weld::Window* pParent, + const OUString& rName, const OUString& rDesc) +{ + return VclPtr::Create(std::make_unique(pParent, rName, rDesc)); +} + +VclPtr AbstractDialogFactory_Impl::CreateSvxObjectNameDialog(weld::Window* pParent, const OUString& rName) +{ + return VclPtr::Create(std::make_unique(pParent, rName)); +} + +VclPtr AbstractDialogFactory_Impl::CreateSvxObjectTitleDescDialog(weld::Window* pParent, const OUString& rTitle, const OUString& rDescription) +{ + return VclPtr::Create(std::make_unique(pParent, rTitle, rDescription)); +} + +VclPtr AbstractDialogFactory_Impl::CreateSvxMultiPathDialog(weld::Window* pParent) +{ + return VclPtr::Create(std::make_unique(pParent)); +} + +VclPtr AbstractDialogFactory_Impl::CreateSvxPathSelectDialog(weld::Window* pParent) +{ + return VclPtr::Create(std::make_unique(pParent)); +} + +VclPtr AbstractDialogFactory_Impl::CreateSvxHpLinkDlg(SfxChildWindow* pChild, SfxBindings* pBindings, weld::Window* pParent) +{ + return VclPtr::Create(std::make_shared(pBindings, pChild, pParent)); +} + +VclPtr AbstractDialogFactory_Impl::CreateFmSearchDialog(weld::Window* pParent, + const OUString& strInitialText, + const std::vector< OUString >& _rContexts, + sal_Int16 nInitialContext, + const Link& lnkContextSupplier) +{ + return VclPtr::Create(std::make_unique(pParent, + strInitialText, _rContexts, nInitialContext, lnkContextSupplier)); + +} + +VclPtr AbstractDialogFactory_Impl::CreateGraphicFilterEmboss(weld::Window* pParent, + const Graphic& rGraphic) +{ + return VclPtr::Create(std::make_unique(pParent, rGraphic, RectPoint::MM)); +} + +VclPtr AbstractDialogFactory_Impl::CreateGraphicFilterPoster(weld::Window* pParent, + const Graphic& rGraphic) +{ + return VclPtr::Create(std::make_unique(pParent, rGraphic, 16)); +} + +VclPtr AbstractDialogFactory_Impl::CreateGraphicFilterSepia(weld::Window* pParent, + const Graphic& rGraphic) +{ + return VclPtr::Create(std::make_unique(pParent, rGraphic, 10)); +} + +VclPtr AbstractDialogFactory_Impl::CreateGraphicFilterSmooth(weld::Window* pParent, + const Graphic& rGraphic, double nRadius) +{ + return VclPtr::Create(std::make_unique(pParent, rGraphic, nRadius)); +} + +VclPtr AbstractDialogFactory_Impl::CreateGraphicFilterSolarize(weld::Window* pParent, + const Graphic& rGraphic) +{ + return VclPtr::Create(std::make_unique(pParent, rGraphic, 128, false /*bInvert*/)); +} + +VclPtr AbstractDialogFactory_Impl::CreateGraphicFilterMosaic(weld::Window* pParent, + const Graphic& rGraphic) +{ + return VclPtr::Create(std::make_unique(pParent, rGraphic, 4, 4, false /*bEnhanceEdges*/)); +} + +VclPtr AbstractDialogFactory_Impl::CreateSvxAreaTabDialog(weld::Window* pParent, + const SfxItemSet* pAttr, + SdrModel* pModel, + bool bShadow) +{ + return VclPtr::Create(std::make_shared(pParent, pAttr, pModel, bShadow)); +} + +VclPtr AbstractDialogFactory_Impl::CreateSvxLineTabDialog(weld::Window* pParent, const SfxItemSet* pAttr, //add forSvxLineTabDialog + SdrModel* pModel, + const SdrObject* pObj , + bool bHasObj) +{ + return VclPtr::Create(std::make_shared(pParent, pAttr, pModel, pObj,bHasObj)); +} + +VclPtr AbstractDialogFactory_Impl::CreateCharMapDialog(weld::Window* pParent, const SfxItemSet& rAttr, + const Reference< XFrame >& rDocumentFrame) +{ + return VclPtr::Create(std::make_unique(pParent, &rAttr, rDocumentFrame)); +} + +VclPtr AbstractDialogFactory_Impl::CreateEventConfigDialog(weld::Widget* pParent, + const SfxItemSet& rAttr, + const Reference< XFrame >& rDocumentFrame) +{ + return VclPtr::Create(std::make_unique(pParent, rDocumentFrame, rAttr)); +} + +VclPtr AbstractDialogFactory_Impl::CreateSfxDialog(weld::Window* pParent, + const SfxItemSet& rAttr, + const SdrView* pView, + sal_uInt32 nResId) +{ + switch ( nResId ) + { + case RID_SVXPAGE_MEASURE: + return VclPtr::Create(std::make_unique(pParent, rAttr, pView)); + case RID_SVXPAGE_CONNECTION: + return VclPtr::Create(std::make_unique(pParent, rAttr, pView)); + case RID_SFXPAGE_DBREGISTER: + return VclPtr::Create(std::make_unique(pParent, rAttr)); + } + + return nullptr; +} + +VclPtr AbstractDialogFactory_Impl::CreateSvxPostItDialog(weld::Widget* pParent, + const SfxItemSet& rCoreSet, + bool bPrevNext) +{ + return VclPtr::Create(std::make_unique(pParent, rCoreSet, bPrevNext)); +} + +namespace { + +class SvxMacroAssignDialog : public VclAbstractDialog +{ +public: + SvxMacroAssignDialog( weld::Window* _pParent, const Reference< XFrame >& _rxDocumentFrame, const bool _bUnoDialogMode, + const Reference< XNameReplace >& _rxEvents, const sal_uInt16 _nInitiallySelectedEvent ) + :m_aItems( SfxGetpApp()->GetPool(), svl::Items{} ) + { + m_aItems.Put( SfxBoolItem( SID_ATTR_MACROITEM, _bUnoDialogMode ) ); + m_xDialog.reset(new SvxMacroAssignDlg(_pParent, _rxDocumentFrame, m_aItems, _rxEvents, _nInitiallySelectedEvent)); + } + + virtual short Execute() override; + +private: + SfxItemSet m_aItems; + std::unique_ptr m_xDialog; +}; + +} + +short SvxMacroAssignDialog::Execute() +{ + return m_xDialog->run(); +} + +short AbstractAboutDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +short AbstractTipOfTheDayDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +short AbstractDiagramDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +VclPtr AbstractDialogFactory_Impl::CreateSvxMacroAssignDlg( + weld::Window* _pParent, const Reference< XFrame >& _rxDocumentFrame, const bool _bUnoDialogMode, + const Reference< XNameReplace >& _rxEvents, const sal_uInt16 _nInitiallySelectedEvent ) +{ + return VclPtr::Create( _pParent, _rxDocumentFrame, _bUnoDialogMode, _rxEvents, _nInitiallySelectedEvent ); +} + +// Factories for TabPages +CreateTabPage AbstractDialogFactory_Impl::GetTabPageCreatorFunc( sal_uInt16 nId ) +{ + switch ( nId ) + { + case RID_SW_TP_BACKGROUND : + case RID_SVXPAGE_BKG : + return SvxBkgTabPage::Create; + case RID_SVXPAGE_TEXTANIMATION : + return SvxTextAnimationPage::Create; + case RID_SVXPAGE_TRANSPARENCE : + return SvxTransparenceTabPage::Create; + case RID_SVXPAGE_AREA : + return SvxAreaTabPage::Create; + case RID_SVXPAGE_SHADOW : + return SvxShadowTabPage::Create; + case RID_SVXPAGE_LINE : + return SvxLineTabPage::Create; + case RID_SVXPAGE_CONNECTION : + return SvxConnectionPage::Create; + case RID_SVXPAGE_MEASURE : + return SvxMeasurePage::Create; + case RID_SFXPAGE_GENERAL : + return SvxGeneralTabPage::Create; + case RID_SVXPAGE_PICK_SINGLE_NUM : + return SvxSingleNumPickTabPage::Create; + case RID_SVXPAGE_PICK_BMP : + return SvxBitmapPickTabPage::Create; + case RID_SVXPAGE_PICK_BULLET : + return SvxBulletPickTabPage::Create; + case RID_SVXPAGE_NUM_OPTIONS : + return SvxNumOptionsTabPage::Create; + case RID_SVXPAGE_PICK_NUM : + return SvxNumPickTabPage::Create; + case RID_SVXPAGE_NUM_POSITION : + return SvxNumPositionTabPage::Create; + case RID_SVXPAGE_PARA_ASIAN : + return SvxAsianTabPage::Create; + case RID_SVXPAGE_EXT_PARAGRAPH : + return SvxExtParagraphTabPage::Create; + case RID_SVXPAGE_ALIGN_PARAGRAPH : + return SvxParaAlignTabPage::Create; + case RID_SVXPAGE_STD_PARAGRAPH : + return SvxStdParagraphTabPage::Create; + case RID_SVXPAGE_TABULATOR : + return SvxTabulatorTabPage::Create; + case RID_SVXPAGE_TEXTATTR : + return SvxTextAttrPage::Create; + case RID_SVXPAGE_ALIGNMENT : + return svx::AlignmentTabPage::Create; + case RID_SVXPAGE_BORDER : + return SvxBorderTabPage::Create; + case RID_SVXPAGE_CHAR_NAME : + return SvxCharNamePage::Create; + case RID_SVXPAGE_CHAR_EFFECTS : + return SvxCharEffectsPage::Create; + case RID_SVXPAGE_CHAR_POSITION : + return SvxCharPositionPage::Create; + case RID_SVXPAGE_CHAR_TWOLINES : + return SvxCharTwoLinesPage::Create; + case RID_SVXPAGE_NUMBERFORMAT : + return SvxNumberFormatTabPage::Create; + case RID_SVXPAGE_PAGE : + return SvxPageDescPage::Create; + case RID_SVXPAGE_GRFCROP : + return SvxGrfCropPage::Create; + case RID_SVXPAGE_MACROASSIGN : + return SfxMacroTabPage::Create; + default: + break; + } + + return nullptr; +} + +DialogGetRanges AbstractDialogFactory_Impl::GetDialogGetRangesFunc() +{ + return SvxPostItDialog::GetRanges; +} + +GetTabPageRanges AbstractDialogFactory_Impl::GetTabPageRangesFunc( sal_uInt16 nId ) +{ + switch ( nId ) + { + case RID_SVXPAGE_TEXTANIMATION : + return SvxTextAnimationPage::GetRanges; + case RID_SVXPAGE_TRANSPARENCE : + return SvxTransparenceTabPage::GetRanges; + case RID_SVXPAGE_AREA : + return SvxAreaTabPage::GetRanges; + case RID_SVXPAGE_SHADOW : + return SvxShadowTabPage::GetRanges; + case RID_SVXPAGE_LINE : + return SvxLineTabPage::GetRanges; + case RID_SVXPAGE_CONNECTION : + return SvxConnectionPage::GetRanges; + case RID_SVXPAGE_MEASURE : + return SvxMeasurePage::GetRanges; + case RID_SVXPAGE_PARA_ASIAN : + return SvxAsianTabPage::GetRanges; + case RID_SVXPAGE_EXT_PARAGRAPH : + return SvxExtParagraphTabPage::GetRanges; + case RID_SVXPAGE_ALIGN_PARAGRAPH : + return SvxParaAlignTabPage::GetRanges; + case RID_SVXPAGE_STD_PARAGRAPH : + return SvxStdParagraphTabPage::GetRanges; + case RID_SVXPAGE_TABULATOR : + return SvxTabulatorTabPage::GetRanges; + case RID_SVXPAGE_TEXTATTR : + return SvxTextAttrPage::GetRanges; + case RID_SVXPAGE_ALIGNMENT : + return svx::AlignmentTabPage::GetRanges; + case RID_SW_TP_BACKGROUND : + case RID_SVXPAGE_BKG: + return SvxBkgTabPage::GetRanges; + case RID_SVXPAGE_BORDER : + return SvxBorderTabPage::GetRanges; + case RID_SVXPAGE_CHAR_NAME : + return SvxCharNamePage::GetRanges; + case RID_SVXPAGE_CHAR_EFFECTS : + return SvxCharEffectsPage::GetRanges; + case RID_SVXPAGE_CHAR_POSITION : + return SvxCharPositionPage::GetRanges; + case RID_SVXPAGE_CHAR_TWOLINES : + return SvxCharTwoLinesPage::GetRanges; + case RID_SVXPAGE_NUMBERFORMAT : + return SvxNumberFormatTabPage::GetRanges; + case RID_SVXPAGE_PAGE : + return SvxPageDescPage::GetRanges; + case RID_SVXPAGE_ASIAN_LAYOUT: + return SvxAsianLayoutPage::GetRanges; + default: + break; + } + + return nullptr; +} + +VclPtr AbstractDialogFactory_Impl::CreateInsertObjectDialog(weld::Window* pParent, const OUString& rCommand, + const Reference & xStor, const SvObjectServerList* pList) +{ + std::unique_ptr pDlg; + if ( rCommand == ".uno:InsertObject" ) + pDlg.reset(new SvInsertOleDlg(pParent, xStor, pList)); + else if ( rCommand == ".uno:InsertObjectFloatingFrame" ) + pDlg.reset(new SfxInsertFloatingFrameDialog(pParent, xStor)); + + if ( pDlg ) + { + pDlg->SetHelpId( OUStringToOString( rCommand, RTL_TEXTENCODING_UTF8 ) ); + return VclPtr::Create( std::move(pDlg) ); + } + return nullptr; +} + +VclPtr AbstractDialogFactory_Impl::CreateEditObjectDialog(weld::Window* pParent, const OUString& rCommand, + const Reference& xObj) +{ + if ( rCommand == ".uno:InsertObjectFloatingFrame" ) + { + auto pDlg = std::make_unique(pParent, xObj); + pDlg->SetHelpId( OUStringToOString( rCommand, RTL_TEXTENCODING_UTF8 ) ); + return VclPtr::Create( std::move(pDlg) ); + } + return nullptr; +} + +VclPtr AbstractDialogFactory_Impl::CreatePasteDialog(weld::Window* pParent) +{ + return VclPtr::Create(std::make_shared(pParent)); +} + +VclPtr AbstractDialogFactory_Impl::CreateLinksDialog(weld::Window* pParent, sfx2::LinkManager* pMgr, bool bHTML, sfx2::SvBaseLink* p) +{ + auto xLinkDlg(std::make_unique(pParent, pMgr, bHTML)); + if (p) + xLinkDlg->SetActLink(p); + return VclPtr::Create(std::move(xLinkDlg)); +} + +VclPtr AbstractDialogFactory_Impl::CreateSvxFormatCellsDialog(weld::Window* pParent, const SfxItemSet* pAttr, const SdrModel& rModel) +{ + return VclPtr::Create(std::make_shared(pParent, pAttr, rModel)); +} + +VclPtr AbstractDialogFactory_Impl::CreateSvxSplitTableDialog(weld::Window* pParent, bool bIsTableVertical, long nMaxVertical) +{ + return VclPtr::Create( pParent, bIsTableVertical, nMaxVertical, 99 ); +} + +std::shared_ptr AbstractDialogFactory_Impl::CreateSvxNewTableDialog(weld::Window* pParent) +{ + return std::make_shared(pParent); +} + +VclPtr AbstractDialogFactory_Impl::CreateOptionsDialog(weld::Window* pParent, const OUString& rExtensionId) +{ + return VclPtr::Create(std::make_unique(pParent, rExtensionId)); +} + +VclPtr AbstractDialogFactory_Impl::CreateSvxInsRowColDlg(weld::Window* pParent, bool bCol, const OString& rHelpId) +{ + return VclPtr::Create(pParent, bCol, rHelpId); +} + +VclPtr AbstractDialogFactory_Impl::CreatePasswordToOpenModifyDialog( + weld::Window * pParent, sal_uInt16 nMaxPasswdLen, bool bIsPasswordToModify) +{ + return VclPtr::Create(std::make_unique(pParent, nMaxPasswdLen, bIsPasswordToModify)); +} + +VclPtr AbstractDialogFactory_Impl::CreateScreenshotAnnotationDlg(weld::Dialog& rParentDialog) +{ + return VclPtr::Create(std::make_unique(rParentDialog)); +} + +VclPtr AbstractDialogFactory_Impl::CreateSignatureLineDialog( + weld::Window* pParent, const Reference xModel, bool bEditExisting) +{ + return VclPtr::Create( + std::make_unique(pParent, xModel, bEditExisting)); +} + +VclPtr +AbstractDialogFactory_Impl::CreateSignSignatureLineDialog(weld::Window* pParent, + const Reference xModel) +{ + return VclPtr::Create( + std::make_unique(pParent, xModel)); +} + +VclPtr AbstractDialogFactory_Impl::CreateQrCodeGenDialog( + weld::Window* pParent, const Reference xModel, bool bEditExisting) +{ + return VclPtr::Create( + std::make_unique(pParent, xModel, bEditExisting)); +} + +VclPtr +AbstractDialogFactory_Impl::CreateAboutDialog(weld::Window* pParent) +{ + return VclPtr::Create( + std::make_unique(pParent)); +} + +VclPtr +AbstractDialogFactory_Impl::CreateTipOfTheDayDialog(weld::Window* pParent) +{ + return VclPtr::Create(std::make_unique(pParent)); +} + +VclPtr +AbstractDialogFactory_Impl::CreateDiagramDialog(weld::Window* pParent, std::shared_ptr pDiagramData) +{ + return VclPtr::Create( + std::make_unique(pParent, pDiagramData)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/factory/dlgfact.hxx b/cui/source/factory/dlgfact.hxx new file mode 100644 index 000000000..4f54b03f9 --- /dev/null +++ b/cui/source/factory/dlgfact.hxx @@ -0,0 +1,981 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_FACTORY_DLGFACT_HXX +#define INCLUDED_CUI_SOURCE_FACTORY_DLGFACT_HXX + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class SfxSingleTabDialogController; +class SfxItemPool; +class FmShowColsDialog; +class SvxZoomDialog; +class FmInputRecordNoDialog; +class SvxJSearchOptionsDialog; +class SvxNewDictionaryDialog; +class SvxNameDialog; + +// #i68101# +class SvxObjectNameDialog; +class SvxObjectTitleDescDialog; + +class SvxMultiPathDialog; +class SvxHpLinkDlg; +class FmSearchDialog; +class Graphic; +class GraphicFilterDialog; +class SvxAreaTabDialog; +class InsertObjectDialog_Impl; +class SvPasteObjectDialog; +class SvBaseLinksDlg; +class SvxTransformTabDialog; +class SvxCaptionTabDialog; +class SvxThesaurusDialog; +class SvxHyphenWordDialog; + +namespace svx{ +class HangulHanjaConversionDialog; +} +using namespace svx; + +#define DECL_ABSTDLG_BASE(Class,DialogClass) \ + ScopedVclPtr pDlg; \ +public: \ + explicit Class( DialogClass* p) \ + : pDlg(p) \ + {} \ + virtual short Execute() override; \ + virtual bool StartExecuteAsync(VclAbstractDialog::AsyncContext &rCtx) override; + +#define IMPL_ABSTDLG_BASE(Class) \ +short Class::Execute() \ +{ \ + return pDlg->Execute(); \ +} \ +bool Class::StartExecuteAsync(VclAbstractDialog::AsyncContext &rCtx) \ +{ \ + return pDlg->StartExecuteAsync(rCtx); \ +} + +class CuiAbstractController_Impl : public VclAbstractDialog +{ + std::unique_ptr m_xDlg; +public: + explicit CuiAbstractController_Impl(std::unique_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; +}; + +class CuiAbstractSingleTabController_Impl : public SfxAbstractDialog +{ + std::unique_ptr m_xDlg; +public: + explicit CuiAbstractSingleTabController_Impl(std::unique_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; + virtual const SfxItemSet* GetOutputItemSet() const override; + + //From class Window. + virtual void SetText( const OUString& rStr ) override; +}; + +class CuiAbstractTabController_Impl : public SfxAbstractTabDialog +{ + std::shared_ptr m_xDlg; +public: + explicit CuiAbstractTabController_Impl(std::shared_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; + virtual bool StartExecuteAsync(AsyncContext &rCtx) override; + virtual void SetCurPageId( const OString &rName ) override; + virtual const SfxItemSet* GetOutputItemSet() const override; + virtual const sal_uInt16* GetInputRanges( const SfxItemPool& pItem ) override; + virtual void SetInputSet( const SfxItemSet* pInSet ) override; + virtual void SetText( const OUString& rStr ) override; + + // screenshotting + virtual std::vector getAllPageUIXMLDescriptions() const override; + virtual bool selectPageByUIXMLDescription(const OString& rUIXMLDescription) override; + virtual BitmapEx createScreenshot() const override; + virtual OString GetScreenshotId() const override; +}; + +class SvxDistributeDialog; +class AbstractSvxDistributeDialog_Impl: public AbstractSvxDistributeDialog +{ + std::unique_ptr m_xDlg; +public: + explicit AbstractSvxDistributeDialog_Impl(std::unique_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; +public: + virtual SvxDistributeHorizontal GetDistributeHor() const override; + virtual SvxDistributeVertical GetDistributeVer() const override; +}; + +class AbstractHangulHanjaConversionDialog_Impl: public AbstractHangulHanjaConversionDialog +{ +private: + std::unique_ptr m_xDlg; +public: + explicit AbstractHangulHanjaConversionDialog_Impl(std::unique_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; + virtual void EndDialog(sal_Int32 nResult) override; + virtual void EnableRubySupport( bool _bVal ) override; + virtual void SetByCharacter( bool _bByCharacter ) override ; + virtual void SetConversionDirectionState( bool _bTryBothDirections, editeng::HangulHanjaConversion::ConversionDirection _ePrimaryConversionDirection ) override; + virtual void SetConversionFormat( editeng::HangulHanjaConversion::ConversionFormat _eType ) override; + virtual void SetOptionsChangedHdl( const Link& _rHdl ) override; + virtual void SetIgnoreHdl( const Link& _rHdl ) override; + virtual void SetIgnoreAllHdl( const Link& _rHdl ) override ; + virtual void SetChangeHdl( const Link& _rHdl ) override ; + virtual void SetChangeAllHdl( const Link& rHdl ) override ; + virtual void SetClickByCharacterHdl( const Link& rHdl ) override ; + virtual void SetConversionFormatChangedHdl( const Link& _rHdl ) override ; + virtual void SetFindHdl( const Link& _rHdl ) override; + virtual bool GetUseBothDirections( ) const override; + virtual editeng::HangulHanjaConversion::ConversionDirection + GetDirection( editeng::HangulHanjaConversion::ConversionDirection _eDefaultDirection ) const override; + virtual void SetCurrentString( + const OUString& _rNewString, + const css::uno::Sequence< OUString >& _rSuggestions, + bool _bOriginatesFromDocument = true + ) override; + virtual OUString GetCurrentString( ) const override ; + virtual editeng::HangulHanjaConversion::ConversionFormat + GetConversionFormat( ) const override ; + virtual void FocusSuggestion( ) override; + virtual OUString GetCurrentSuggestion( ) const override; +}; + +class AbstractThesaurusDialog_Impl : public AbstractThesaurusDialog +{ + std::shared_ptr m_xDlg; +public: + explicit AbstractThesaurusDialog_Impl(std::shared_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; + virtual bool StartExecuteAsync(AsyncContext &rCtx) override; + virtual OUString GetWord() override; +}; + +class AbstractHyphenWordDialog_Impl: public AbstractHyphenWordDialog +{ + std::unique_ptr m_xDlg; +public: + explicit AbstractHyphenWordDialog_Impl(std::unique_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; +}; + +class FmShowColsDialog; +class AbstractFmShowColsDialog_Impl : public AbstractFmShowColsDialog +{ + std::unique_ptr m_xDlg; +public: + explicit AbstractFmShowColsDialog_Impl(std::unique_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; + virtual void SetColumns(const css::uno::Reference< css::container::XIndexContainer>& xCols) override; +}; + +class SvxZoomDialog; +class AbstractSvxZoomDialog_Impl : public AbstractSvxZoomDialog +{ + std::unique_ptr m_xDlg; +public: + explicit AbstractSvxZoomDialog_Impl(std::unique_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; + virtual void SetLimits( sal_uInt16 nMin, sal_uInt16 nMax ) override; + virtual void HideButton( ZoomButtonId nBtnId ) override; + virtual const SfxItemSet* GetOutputItemSet() const override ; +}; + +namespace svx{ class SpellDialog;} +class AbstractSpellDialog_Impl : public AbstractSpellDialog +{ + std::shared_ptr m_xDlg; +public: + explicit AbstractSpellDialog_Impl(std::shared_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; + virtual bool StartExecuteAsync(AsyncContext &rCtx) override; + virtual void InvalidateDialog() override; + virtual std::shared_ptr GetController() override; + virtual SfxBindings& GetBindings() override; +}; + +class TitleDialog; +class AbstractTitleDialog_Impl : public AbstractTitleDialog +{ +protected: + std::unique_ptr m_xDlg; +public: + explicit AbstractTitleDialog_Impl(std::unique_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; + virtual OUString GetTitle() const override ; + +}; + +class SvxScriptSelectorDialog; +class AbstractScriptSelectorDialog_Impl : public AbstractScriptSelectorDialog +{ + std::unique_ptr m_xDlg; +public: + explicit AbstractScriptSelectorDialog_Impl(std::unique_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; + virtual OUString GetScriptURL() const override; + virtual void SetRunLabel() override; +}; + +class GalleryIdDialog; +class AbstractGalleryIdDialog_Impl : public AbstractGalleryIdDialog +{ +protected: + std::unique_ptr m_xDlg; +public: + explicit AbstractGalleryIdDialog_Impl(std::unique_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; + virtual sal_uInt32 GetId() const override; +}; + +class URLDlg; +class AbstractURLDlg_Impl :public AbstractURLDlg +{ +protected: + std::unique_ptr m_xDlg; +public: + explicit AbstractURLDlg_Impl(std::unique_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; + virtual OUString GetURL() const override; + virtual OUString GetAltText() const override; + virtual OUString GetDesc() const override; + virtual OUString GetTarget() const override; + virtual OUString GetName() const override; +}; + +class SvxSearchSimilarityDialog; +class AbstractSvxSearchSimilarityDialog_Impl :public AbstractSvxSearchSimilarityDialog +{ + std::unique_ptr m_xDlg; +public: + explicit AbstractSvxSearchSimilarityDialog_Impl(std::unique_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; + virtual sal_uInt16 GetOther() override; + virtual sal_uInt16 GetShorter() override; + virtual sal_uInt16 GetLonger() override; + virtual bool IsRelaxed() override; +}; + +class SvxJSearchOptionsDialog; +class AbstractSvxJSearchOptionsDialog_Impl : public AbstractSvxJSearchOptionsDialog +{ + std::unique_ptr m_xDlg; +public: + explicit AbstractSvxJSearchOptionsDialog_Impl(std::unique_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; + virtual TransliterationFlags GetTransliterationFlags() const override; +}; + +class AbstractSvxTransformTabDialog_Impl : public AbstractSvxTransformTabDialog +{ + std::shared_ptr m_xDlg; +public: + explicit AbstractSvxTransformTabDialog_Impl(std::shared_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; + virtual bool StartExecuteAsync(AsyncContext &rCtx) override; + virtual void SetValidateFramePosLink( const Link& rLink ) override; + virtual void SetCurPageId( const OString& rName ) override; + virtual const SfxItemSet* GetOutputItemSet() const override; + virtual const sal_uInt16* GetInputRanges( const SfxItemPool& pItem ) override; + virtual void SetInputSet( const SfxItemSet* pInSet ) override; + virtual void SetText( const OUString& rStr ) override; +}; + +class AbstractSvxCaptionDialog_Impl : public AbstractSvxCaptionDialog +{ + std::shared_ptr m_xDlg; +public: + explicit AbstractSvxCaptionDialog_Impl(std::shared_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; + virtual bool StartExecuteAsync(AsyncContext &rCtx) override; + virtual void SetValidateFramePosLink( const Link& rLink ) override; + virtual void SetCurPageId( const OString& rName ) override; + virtual const SfxItemSet* GetOutputItemSet() const override; + virtual const sal_uInt16* GetInputRanges( const SfxItemPool& pItem ) override; + virtual void SetInputSet( const SfxItemSet* pInSet ) override; + virtual void SetText( const OUString& rStr ) override; +}; + +class FmInputRecordNoDialog; +class AbstractFmInputRecordNoDialog_Impl :public AbstractFmInputRecordNoDialog +{ + std::unique_ptr m_xDlg; +public: + explicit AbstractFmInputRecordNoDialog_Impl(std::unique_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; + virtual void SetValue(long nNew) override ; + virtual long GetValue() const override ; +}; + +class SvxNewDictionaryDialog; +class AbstractSvxNewDictionaryDialog_Impl :public AbstractSvxNewDictionaryDialog +{ + std::unique_ptr m_xDlg; +public: + explicit AbstractSvxNewDictionaryDialog_Impl(std::unique_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; + virtual css::uno::Reference< css::linguistic2::XDictionary > GetNewDictionary() override; +}; + +class SvxNameDialog; +class AbstractSvxNameDialog_Impl :public AbstractSvxNameDialog +{ +public: + explicit AbstractSvxNameDialog_Impl(std::unique_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; + virtual void GetName( OUString& rName ) override ; + virtual void SetCheckNameHdl( const Link& rLink, bool bCheckImmediately = false ) override ; + virtual void SetCheckNameTooltipHdl( const Link& rLink ) override ; + virtual void SetEditHelpId(const OString&) override ; + //from class Window + virtual void SetHelpId( const OString& ) override ; + virtual void SetText( const OUString& rStr ) override ; +private: + std::unique_ptr m_xDlg; + Link aCheckNameHdl; + Link aCheckNameTooltipHdl; + DECL_LINK(CheckNameHdl, SvxNameDialog&, bool); + DECL_LINK(CheckNameTooltipHdl, SvxNameDialog&, OUString); +}; + +class SvxObjectNameDialog; +class SvxObjectTitleDescDialog; + +class AbstractSvxObjectNameDialog_Impl : public AbstractSvxObjectNameDialog +{ +public: + explicit AbstractSvxObjectNameDialog_Impl(std::unique_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; + virtual void GetName(OUString& rName) override ; + virtual void SetCheckNameHdl(const Link& rLink) override; + +private: + std::unique_ptr m_xDlg; + Link aCheckNameHdl; + DECL_LINK(CheckNameHdl, SvxObjectNameDialog&, bool); +}; + +class AbstractSvxObjectTitleDescDialog_Impl :public AbstractSvxObjectTitleDescDialog +{ + std::unique_ptr m_xDlg; +public: + explicit AbstractSvxObjectTitleDescDialog_Impl(std::unique_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; + virtual void GetTitle(OUString& rName) override; + virtual void GetDescription(OUString& rName) override; +}; + +class AbstractSvxMultiPathDialog_Impl : public AbstractSvxMultiPathDialog +{ + std::unique_ptr m_xDlg; +public: + explicit AbstractSvxMultiPathDialog_Impl(std::unique_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; + virtual OUString GetPath() const override; + virtual void SetPath( const OUString& rPath ) override; + virtual void SetTitle( const OUString& rNewTitle ) override; +}; + +class SvxPathSelectDialog; +class AbstractSvxPathSelectDialog_Impl : public AbstractSvxMultiPathDialog +{ +protected: + std::unique_ptr m_xDlg; +public: + explicit AbstractSvxPathSelectDialog_Impl(std::unique_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; + virtual OUString GetPath() const override; + virtual void SetPath( const OUString& rPath ) override; + virtual void SetTitle( const OUString& rNewTitle ) override; +}; + +class SvxHpLinkDlg; +class AbstractSvxHpLinkDlg_Impl : public AbstractSvxHpLinkDlg +{ +protected: + std::shared_ptr m_xDlg; +public: + explicit AbstractSvxHpLinkDlg_Impl(std::shared_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; + virtual std::shared_ptr GetController() override; + virtual bool QueryClose() override; +}; + +class FmSearchDialog; +struct FmFoundRecordInformation; +class AbstractFmSearchDialog_Impl :public AbstractFmSearchDialog +{ + std::unique_ptr m_xDlg; +public: + explicit AbstractFmSearchDialog_Impl(std::unique_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; + virtual void SetFoundHandler(const Link& lnk) override ; + virtual void SetCanceledNotFoundHdl(const Link& lnk) override; + virtual void SetActiveField(const OUString& strField) override; +}; + +class AbstractGraphicFilterDialog_Impl : public AbstractGraphicFilterDialog +{ + std::unique_ptr m_xDlg; +public: + explicit AbstractGraphicFilterDialog_Impl(std::unique_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; + virtual Graphic GetFilteredGraphic( const Graphic& rGraphic, double fScaleX, double fScaleY ) override; +}; + +class SvxAreaTabDialog; +class AbstractSvxAreaTabDialog_Impl : public AbstractSvxAreaTabDialog +{ + std::shared_ptr m_xDlg; +public: + explicit AbstractSvxAreaTabDialog_Impl(std::shared_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; + virtual bool StartExecuteAsync(AsyncContext &rCtx) override; + virtual void SetCurPageId(const OString& rName) override; + virtual const SfxItemSet* GetOutputItemSet() const override; + virtual const sal_uInt16* GetInputRanges(const SfxItemPool& pItem) override; + virtual void SetInputSet(const SfxItemSet* pInSet) override; + virtual void SetText(const OUString& rStr) override; +}; + +class AbstractInsertObjectDialog_Impl : public SfxAbstractInsertObjectDialog +{ + std::unique_ptr m_xDlg; +public: + explicit AbstractInsertObjectDialog_Impl(std::unique_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; + virtual css::uno::Reference < css::embed::XEmbeddedObject > GetObject() override; + virtual css::uno::Reference< css::io::XInputStream > GetIconIfIconified( OUString* pGraphicMediaType ) override; + virtual bool IsCreateNew() override; +}; + +class AbstractPasteDialog_Impl : public SfxAbstractPasteDialog +{ + std::shared_ptr m_xDlg; +public: + explicit AbstractPasteDialog_Impl(std::shared_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; + virtual bool StartExecuteAsync(AsyncContext &rCtx) override; +public: + virtual void Insert( SotClipboardFormatId nFormat, const OUString & rFormatName ) override; + virtual void InsertUno( const OUString & sCmd, const OUString& sLabel ) override; + virtual void SetObjName( const SvGlobalName & rClass, const OUString & rObjName ) override; + virtual void PreGetFormat( const TransferableDataHelper& aHelper ) override; + virtual SotClipboardFormatId GetFormatOnly() override; + virtual SotClipboardFormatId GetFormat( const TransferableDataHelper& aHelper ) override; +}; + +class AbstractLinksDialog_Impl : public SfxAbstractLinksDialog +{ +protected: + std::unique_ptr m_xDlg; +public: + explicit AbstractLinksDialog_Impl(std::unique_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; +}; + +class SvxPostItDialog; +class AbstractSvxPostItDialog_Impl :public AbstractSvxPostItDialog +{ +public: + AbstractSvxPostItDialog_Impl(std::unique_ptr pDlg) + : m_xDlg(std::move(pDlg)) + { + } + virtual short Execute() override; + virtual void SetText( const OUString& rStr ) override; //From class Window + virtual const SfxItemSet* GetOutputItemSet() const override; + virtual void SetPrevHdl( const Link& rLink ) override; + virtual void SetNextHdl( const Link& rLink ) override; + virtual void EnableTravel(bool bNext, bool bPrev) override; + virtual OUString GetNote() override; + virtual void SetNote(const OUString& rTxt) override; + virtual void ShowLastAuthor(const OUString& rAuthor, const OUString& rDate) override; + virtual void DontChangeAuthor() override; + virtual void HideAuthor() override; + virtual std::shared_ptr GetDialog() override; +private: + std::unique_ptr m_xDlg; + Link aNextHdl; + Link aPrevHdl; + DECL_LINK(NextHdl, SvxPostItDialog&, void); + DECL_LINK(PrevHdl, SvxPostItDialog&, void); +}; + +class PasswordToOpenModifyDialog; +class AbstractPasswordToOpenModifyDialog_Impl : public AbstractPasswordToOpenModifyDialog +{ + std::unique_ptr m_xDlg; +public: + explicit AbstractPasswordToOpenModifyDialog_Impl(std::unique_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; + virtual OUString GetPasswordToOpen() const override; + virtual OUString GetPasswordToModify() const override; + virtual bool IsRecommendToOpenReadonly() const override; +}; + +class SvxCharacterMap; +class AbstractSvxCharacterMapDialog_Impl : public SfxAbstractDialog +{ + std::unique_ptr m_xDlg; +public: + explicit AbstractSvxCharacterMapDialog_Impl(std::unique_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; + virtual const SfxItemSet* GetOutputItemSet() const override; + virtual void SetText(const OUString& rStr) override; +}; + +class ScreenshotAnnotationDlg; +class AbstractScreenshotAnnotationDlg_Impl : public AbstractScreenshotAnnotationDlg +{ + std::unique_ptr m_xDlg; + +public: + explicit AbstractScreenshotAnnotationDlg_Impl(std::unique_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; +}; + +class SignatureLineDialog; +class AbstractSignatureLineDialog_Impl : public AbstractSignatureLineDialog +{ + std::unique_ptr m_xDlg; + +public: + explicit AbstractSignatureLineDialog_Impl(std::unique_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; +}; + +class QrCodeGenDialog; +class AbstractQrCodeGenDialog_Impl : public AbstractQrCodeGenDialog +{ + std::unique_ptr m_xDlg; + +public: + explicit AbstractQrCodeGenDialog_Impl(std::unique_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; +}; + +class SignSignatureLineDialog; +class AbstractSignSignatureLineDialog_Impl : public AbstractSignSignatureLineDialog +{ +protected: + std::unique_ptr m_xDlg; + +public: + explicit AbstractSignSignatureLineDialog_Impl(std::unique_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; +}; + +class AboutDialog; +class AbstractAboutDialog_Impl : public AbstractAboutDialog +{ +protected: + std::unique_ptr m_xDlg; + +public: + explicit AbstractAboutDialog_Impl(std::unique_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; +}; + +class TipOfTheDayDialog; +class AbstractTipOfTheDayDialog_Impl : public AbstractTipOfTheDayDialog +{ +protected: + std::unique_ptr m_xDlg; + +public: + explicit AbstractTipOfTheDayDialog_Impl(std::unique_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; +}; + +class DiagramDialog; + +/** Edit Diagram dialog */ +class AbstractDiagramDialog_Impl : public AbstractDiagramDialog +{ +protected: + std::unique_ptr m_xDlg; + +public: + explicit AbstractDiagramDialog_Impl(std::unique_ptr p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; +}; + +//AbstractDialogFactory_Impl implementations +class AbstractDialogFactory_Impl : public SvxAbstractDialogFactory +{ +public: + virtual VclPtr CreateVclDialog(weld::Window* pParent, sal_uInt32 nResId) override; + + virtual VclPtr CreateSfxDialog( weld::Window* pParent, + const SfxItemSet& rAttr, + const SdrView* pView, + sal_uInt32 nResId ) override; + virtual VclPtr CreateCharMapDialog(weld::Window* pParent, + const SfxItemSet& rAttr, + const css::uno::Reference< css::frame::XFrame >& rFrame) override; + virtual VclPtr CreateEventConfigDialog(weld::Widget* pParent, + const SfxItemSet& rAttr, + const css::uno::Reference< css::frame::XFrame >& rFrame) override; + virtual VclPtr CreateFrameDialog(weld::Window* pParent, const css::uno::Reference< css::frame::XFrame >& rxFrame, + sal_uInt32 nResId, + const OUString& rParameter ) override; + virtual VclPtr CreateAutoCorrTabDialog(weld::Window* pParent, const SfxItemSet* pAttrSet) override; + virtual VclPtr CreateCustomizeTabDialog(weld::Window* pParent, + const SfxItemSet* pAttrSet, + const css::uno::Reference< css::frame::XFrame >& xViewFrame ) override; + virtual VclPtr CreateTextTabDialog( weld::Window* pParent, + const SfxItemSet* pAttrSet, + SdrView* pView ) override; + virtual VclPtr CreateTabItemDialog(weld::Window* pParent, const SfxItemSet& rSet) override; + virtual VclPtr + CreateCaptionDialog(weld::Window* pParent, + const SdrView* pView, + SvxAnchorIds nAnchorTypes = SvxAnchorIds::NONE) override; + virtual VclPtr + CreateSvxDistributeDialog(weld::Window* pParent, const SfxItemSet& rAttr) override; + virtual VclPtr + CreateInsertObjectDialog(weld::Window* pParent, const OUString& rCommmand, + const css::uno::Reference < css::embed::XStorage >& xStor, + const SvObjectServerList* pList ) override; + virtual VclPtr CreateEditObjectDialog(weld::Window* pParent, const OUString& rCommmand, + const css::uno::Reference < css::embed::XEmbeddedObject >& xObj ) override; + virtual VclPtr CreatePasteDialog(weld::Window* pParent) override; + virtual VclPtr CreateLinksDialog(weld::Window* pParent, sfx2::LinkManager* pMgr, bool bHTML = false, sfx2::SvBaseLink* p=nullptr) override; + + virtual VclPtr CreateHangulHanjaConversionDialog(weld::Window* pParent) override; + virtual VclPtr CreateThesaurusDialog(weld::Window*, + css::uno::Reference xThesaurus, + const OUString &rWord, LanguageType nLanguage) override; + + virtual VclPtr CreateHyphenWordDialog(weld::Window*, + const OUString &rWord, LanguageType nLang, + css::uno::Reference< css::linguistic2::XHyphenator > &xHyphen, + SvxSpellWrapper* pWrapper) override; + + virtual VclPtr CreateFmShowColsDialog(weld::Window* pParent) override; + virtual VclPtr CreateSvxZoomDialog(weld::Window* pParent, const SfxItemSet& rCoreSet) override; + // add for SvxBorderBackgroundDlg + virtual VclPtr CreateSvxBorderBackgroundDlg( + weld::Window* pParent, + const SfxItemSet& rCoreSet, + bool bEnableDrawingLayerFillStyles) override; + + virtual VclPtr CreateSvxTransformTabDialog(weld::Window* pParent, + const SfxItemSet* pAttr, + const SdrView* pView, + SvxAnchorIds nAnchorTypes = SvxAnchorIds::NONE) override ; + virtual VclPtr CreateSchTransformTabDialog(weld::Window* pParent, + const SfxItemSet* pAttr, + const SdrView* pSdrView, + bool bSizeTabPage) override; + virtual VclPtr CreateSvxSpellDialog( + weld::Window* pParent, + SfxBindings* pBindings, + svx::SpellDialogChildWindow* pSpellChildWindow ) override; + + virtual VclPtr CreateActualizeProgressDialog(weld::Widget* pParent, GalleryTheme* pThm) override; + virtual VclPtr CreateTitleDialog(weld::Widget* pParent, const OUString& rOldText) override; + virtual VclPtr CreateGalleryIdDialog(weld::Widget* pParent, + GalleryTheme* pThm) override; + virtual VclPtr CreateGalleryThemePropertiesDialog(weld::Widget* pParent, + ExchangeData* pData, + SfxItemSet* pItemSet) override; + + virtual VclPtr CreateURLDialog(weld::Widget* pParent, + const OUString& rURL, const OUString& rAltText, const OUString& rDescription, + const OUString& rTarget, const OUString& rName, + TargetList& rTargetList ) override; + + virtual VclPtr CreateSvxSearchAttributeDialog(weld::Window* pParent, + SearchAttrItemList& rLst, + const sal_uInt16* pWhRanges) override; + virtual VclPtr CreateSvxSearchSimilarityDialog( weld::Window* pParent, + bool bRelax, + sal_uInt16 nOther, + sal_uInt16 nShorter, + sal_uInt16 nLonger) override; + virtual VclPtr CreateSvxJSearchOptionsDialog(weld::Window* pParent, + const SfxItemSet& rOptionsSet, + TransliterationFlags nInitialFlags) override; + virtual VclPtr CreateFmInputRecordNoDialog(weld::Window* pParent) override; + virtual VclPtr CreateSvxNewDictionaryDialog(weld::Window* pParent) override; + virtual VclPtr CreateSvxEditDictionaryDialog(weld::Window* pParent, const OUString& rName) override; + virtual VclPtr CreateSvxNameDialog(weld::Window* pParent, + const OUString& rName, const OUString& rDesc) override; + // #i68101# + virtual VclPtr CreateSvxObjectNameDialog(weld::Window* pParent, const OUString& rName) override; + virtual VclPtr CreateSvxObjectTitleDescDialog(weld::Window* pParent, const OUString& rTitle, const OUString& rDescription) override; + virtual VclPtr CreateSvxMultiPathDialog(weld::Window* pParent) override; + virtual VclPtr CreateSvxPathSelectDialog(weld::Window* pParent) override; + virtual VclPtr CreateSvxHpLinkDlg(SfxChildWindow* pChild, SfxBindings* pBindings, weld::Window* pParent) override; + virtual VclPtr CreateFmSearchDialog(weld::Window* pParent, + const OUString& strInitialText, + const std::vector< OUString >& _rContexts, + sal_Int16 nInitialContext, + const Link& lnkContextSupplier) override; + virtual VclPtr CreateGraphicFilterEmboss(weld::Window* pParent, + const Graphic& rGraphic) override; + virtual VclPtr CreateGraphicFilterPoster(weld::Window* pParent, + const Graphic& rGraphic) override; + virtual VclPtr CreateGraphicFilterSepia(weld::Window* pParent, + const Graphic& rGraphic) override; + virtual VclPtr CreateGraphicFilterSmooth(weld::Window* pParent, + const Graphic& rGraphic, double nRadius) override; + virtual VclPtr CreateGraphicFilterSolarize(weld::Window* pParent, + const Graphic& rGraphic) override; + virtual VclPtr CreateGraphicFilterMosaic(weld::Window* pParent, + const Graphic& rGraphic) override; + virtual VclPtr CreateSvxAreaTabDialog(weld::Window* pParent, + const SfxItemSet* pAttr, + SdrModel* pModel, + bool bShadow) override; + virtual VclPtr CreateSvxLineTabDialog(weld::Window* pParent, const SfxItemSet* pAttr, + SdrModel* pModel, + const SdrObject* pObj, + bool bHasObj ) override; + virtual VclPtr CreateSvxPostItDialog(weld::Widget* pParent, + const SfxItemSet& rCoreSet, + bool bPrevNext = false) override; + + // For TabPage + virtual CreateTabPage GetTabPageCreatorFunc( sal_uInt16 nId ) override; + + virtual GetTabPageRanges GetTabPageRangesFunc( sal_uInt16 nId ) override; + virtual DialogGetRanges GetDialogGetRangesFunc() override; + virtual VclPtr CreateSvxScriptOrgDialog(weld::Window* pParent, const OUString& rLanguage) override; + + virtual VclPtr CreateScriptSelectorDialog(weld::Window* pParent, + const css::uno::Reference< css::frame::XFrame >& rxFrame) override; + + virtual VclPtr CreateScriptErrorDialog(const css::uno::Any& rException) override; + + virtual VclPtr CreateSvxMacroAssignDlg( + weld::Window* _pParent, + const css::uno::Reference< css::frame::XFrame >& _rxDocumentFrame, + const bool _bUnoDialogMode, + const css::uno::Reference< css::container::XNameReplace >& _rxEvents, + const sal_uInt16 _nInitiallySelectedEvent + ) override; + + virtual VclPtr CreateSvxFormatCellsDialog(weld::Window* pParent, const SfxItemSet* pAttr, const SdrModel& rModel) override; + + virtual VclPtr CreateSvxSplitTableDialog(weld::Window* pParent, bool bIsTableVertical, long nMaxVertical) override; + + virtual std::shared_ptr CreateSvxNewTableDialog(weld::Window* pParent) override ; + + virtual VclPtr CreateOptionsDialog( + weld::Window* pParent, const OUString& rExtensionId ) override; + + virtual VclPtr CreateSvxInsRowColDlg(weld::Window* pParent, bool bCol, const OString& rHelpId) override; + + virtual VclPtr CreatePasswordToOpenModifyDialog(weld::Window* pParent, sal_uInt16 nMaxPasswdLen, bool bIsPasswordToModify) override; + + virtual VclPtr CreateScreenshotAnnotationDlg(weld::Dialog& rParentDialog) override; + + virtual VclPtr + CreateSignatureLineDialog(weld::Window* pParent, + const css::uno::Reference xModel, bool bEditExisting) override; + + virtual VclPtr + CreateSignSignatureLineDialog(weld::Window* pParent, + const css::uno::Reference xModel) override; + + virtual VclPtr + CreateQrCodeGenDialog(weld::Window* pParent, + const css::uno::Reference xModel, bool bEditExisting) override; + + virtual VclPtr CreateAboutDialog(weld::Window* pParent) override; + + virtual VclPtr CreateTipOfTheDayDialog(weld::Window* pParent) override; + + virtual VclPtr CreateDiagramDialog( + weld::Window* pParent, + std::shared_ptr pDiagramData) override; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/factory/init.cxx b/cui/source/factory/init.cxx new file mode 100644 index 000000000..87f3105a0 --- /dev/null +++ b/cui/source/factory/init.cxx @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +// hook to call special character dialog for edits +// caution: needs C-Linkage since dynamically loaded via symbol name +extern "C" +{ +SAL_DLLPUBLIC_EXPORT bool GetSpecialCharsForEdit(weld::Widget* i_pParent, const vcl::Font& i_rFont, OUString& o_rResult) +{ + bool bRet = false; + SvxCharacterMap aDlg(i_pParent, nullptr, nullptr); + aDlg.DisableFontSelection(); + aDlg.SetCharFont(i_rFont); + if (aDlg.run() == RET_OK) + { + sal_UCS4 cChar = aDlg.GetChar(); + // using the new UCS4 constructor + OUString aOUStr( &cChar, 1 ); + o_rResult = aOUStr; + bRet = true; + } + return bRet; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/CommandCategoryListBox.hxx b/cui/source/inc/CommandCategoryListBox.hxx new file mode 100644 index 000000000..059c1474f --- /dev/null +++ b/cui/source/inc/CommandCategoryListBox.hxx @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include +#include "cfgutil.hxx" + +class CommandCategoryListBox +{ + SfxGroupInfoArr_Impl m_aGroupInfo; + OUString m_sModuleLongName; + css::uno::Reference< css::uno::XComponentContext > m_xContext; + css::uno::Reference< css::frame::XFrame > m_xFrame; + css::uno::Reference< css::container::XNameAccess > m_xGlobalCategoryInfo; + css::uno::Reference< css::container::XNameAccess > m_xModuleCategoryInfo; + css::uno::Reference< css::container::XNameAccess > m_xUICmdDescription; + + // For search + i18nutil::SearchOptions2 m_searchOptions; + + SfxStylesInfo_Impl* pStylesInfo; + SfxStylesInfo_Impl m_aStylesInfo; + + std::unique_ptr m_xControl; + +public: + CommandCategoryListBox(std::unique_ptr xControl); + ~CommandCategoryListBox(); + void ClearAll(); + + void Init( + const css::uno::Reference< css::uno::XComponentContext >& xContext, + const css::uno::Reference< css::frame::XFrame >& xFrame, + const OUString& sModuleLongName); + void FillFunctionsList( + const css::uno::Sequence< css::frame::DispatchInformation >& xCommands, + CuiConfigFunctionListBox* pFunctionListBox, + const OUString& filterTerm, + SaveInData *pCurrentSaveInData ); + OUString getCommandName(const OUString& sCommand); + + void connect_changed(const Link& rLink) { m_xControl->connect_changed(rLink); } + + /** + Signals that a command category has been selected. + And updates the functions list box to include + the commands in the selected category. + */ + void categorySelected(CuiConfigFunctionListBox* pFunctionListBox, + const OUString& filterTerm, SaveInData* pCurrentSaveInData = nullptr); + + void SetStylesInfo(SfxStylesInfo_Impl* pStyles); + + // Adds children of the given macro group to the functions list + void addChildren( + const weld::TreeIter* parentEntry, const css::uno::Reference &parentNode, + CuiConfigFunctionListBox* pFunctionListBox, const OUString &filterTerm , SaveInData *pCurrentSaveInData, + std::vector> &rNodesToExpand); + + void set_visible(bool bVisible) {m_xControl->set_visible(bVisible);} +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/cui/source/inc/CustomNotebookbarGenerator.hxx b/cui/source/inc/CustomNotebookbarGenerator.hxx new file mode 100644 index 000000000..b06848dbb --- /dev/null +++ b/cui/source/inc/CustomNotebookbarGenerator.hxx @@ -0,0 +1,42 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include +#include + +using namespace css::uno; + +class CustomNotebookbarGenerator +{ +public: + CustomNotebookbarGenerator(); + static OUString getCustomizedUIPath(); + static OUString getOriginalUIPath(); + static OString getSystemPath(OUString const& sURL); + static Sequence getCustomizedUIItem(OUString sNotebookbarConfigType); + static void getFileNameAndAppName(OUString& sAppName, OUString& sNotebookbarUIFileName); + static void modifyCustomizedUIFile(const Sequence& sUIItemProperties); + static void createCustomizedUIFile(); + static void setCustomizedUIItem(Sequence sUIItemProperties, + OUString sNotebookbarConfigType); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/DiagramDialog.hxx b/cui/source/inc/DiagramDialog.hxx new file mode 100644 index 000000000..e97144050 --- /dev/null +++ b/cui/source/inc/DiagramDialog.hxx @@ -0,0 +1,42 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* +* This file is part of the LibreOffice project. +* +* This Source Code Form is subject to the terms of the Mozilla Public +* License, v. 2.0. If a copy of the MPL was not distributed with this +* file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#ifndef INCLUDED_CUI_SOURCE_INC_DIAGRAMDIALOG_HXX +#define INCLUDED_CUI_SOURCE_INC_DIAGRAMDIALOG_HXX + +#include +#include + +class DiagramDataInterface; + +/** Edit Diagram dialog */ +class DiagramDialog : public weld::GenericDialogController +{ +public: + DiagramDialog(weld::Window* pWindow, std::shared_ptr pDiagramData); + virtual ~DiagramDialog() override; + +private: + std::shared_ptr mpDiagramData; + std::unique_ptr mpBtnOk; + std::unique_ptr mpBtnCancel; + std::unique_ptr mpBtnAdd; + std::unique_ptr mpBtnRemove; + std::unique_ptr mpTreeDiagram; + std::unique_ptr mpTextAdd; + + DECL_LINK(OnAddClick, weld::Button&, void); + DECL_LINK(OnRemoveClick, weld::Button&, void); + + void populateTree(const weld::TreeIter* pParent, const OUString& rParentId); +}; + +#endif // INCLUDED_CUI_SOURCE_INC_DIAGRAMDIALOG_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/FontFeaturesDialog.hxx b/cui/source/inc/FontFeaturesDialog.hxx new file mode 100644 index 000000000..93e5f7c4a --- /dev/null +++ b/cui/source/inc/FontFeaturesDialog.hxx @@ -0,0 +1,78 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#ifndef INCLUDED_CUI_SOURCE_INC_FONTFEATURESDIALOG_HXX +#define INCLUDED_CUI_SOURCE_INC_FONTFEATURESDIALOG_HXX + +#include +#include +#include +#include +#include + +namespace cui +{ +struct FontFeatureItem +{ + FontFeatureItem(weld::Widget* pParent) + : m_aFeatureCode(0) + , m_nDefault(0) + , m_xBuilder(Application::CreateBuilder(pParent, "cui/ui/fontfragment.ui")) + , m_xContainer(m_xBuilder->weld_widget("fontentry")) + , m_xText(m_xBuilder->weld_label("label")) + , m_xCombo(m_xBuilder->weld_combo_box("combo")) + , m_xCheck(m_xBuilder->weld_check_button("check")) + { + } + + sal_uInt32 m_aFeatureCode; + sal_uInt32 m_nDefault; + std::unique_ptr m_xBuilder; + std::unique_ptr m_xContainer; + std::unique_ptr m_xText; + std::unique_ptr m_xCombo; + std::unique_ptr m_xCheck; +}; + +class FontFeaturesDialog : public weld::GenericDialogController +{ +private: + std::vector m_aFeatureItems; + OUString m_sFontName; + OUString m_sResultFontName; + + SvxFontPrevWindow m_aPreviewWindow; + std::unique_ptr m_xContentWindow; + std::unique_ptr m_xContentGrid; + std::unique_ptr m_xPreviewWindow; + + void initialize(); + OUString createFontNameWithFeatures(); + + void fillGrid(std::vector const& rFontFeatures); + + DECL_LINK(ComboBoxSelectedHdl, weld::ComboBox&, void); + DECL_LINK(CheckBoxToggledHdl, weld::ToggleButton&, void); + +public: + FontFeaturesDialog(weld::Window* pParent, OUString const& rFontName); + ~FontFeaturesDialog() override; + virtual short run() override; + + OUString const& getResultFontName() const { return m_sResultFontName; } + + void updateFontPreview(); +}; + +} // end svx namespaces + +#endif // INCLUDED_CUI_SOURCE_INC_FONTFEATURESDIALOG_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/QrCodeGenDialog.hxx b/cui/source/inc/QrCodeGenDialog.hxx new file mode 100644 index 000000000..832662837 --- /dev/null +++ b/cui/source/inc/QrCodeGenDialog.hxx @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef INCLUDED_CUI_INC_QRCODEGENDIALOG_HXX +#define INCLUDED_CUI_INC_QRCODEGENDIALOG_HXX + +#include + +#include + +#include +#include + +#include + +class QrCodeGenDialog : public weld::GenericDialogController +{ +public: + QrCodeGenDialog(weld::Widget* pParent, css::uno::Reference xModel, + bool bEditExisting); + + virtual short run() override; + +protected: + css::uno::Reference m_xModel; + void Apply(); + +private: + std::unique_ptr m_xEdittext; + std::unique_ptr m_xECC[4]; + std::unique_ptr m_xSpinBorder; +#if ENABLE_QRCODEGEN + weld::Widget* mpParent; +#endif + + css::uno::Reference m_xExistingShapeProperties; + + void GetErrorCorrection(long); + //Function contains QR Code Generating Library Calls + static OUString GenerateQRCode(OUString aQrText, long aQrECC, int aQrBorder); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/cui/source/inc/SignSignatureLineDialog.hxx b/cui/source/inc/SignSignatureLineDialog.hxx new file mode 100644 index 000000000..6bd08ff4b --- /dev/null +++ b/cui/source/inc/SignSignatureLineDialog.hxx @@ -0,0 +1,56 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef INCLUDED_CUI_INC_SIGNSIGNATURELINEDIALOG_HXX +#define INCLUDED_CUI_INC_SIGNSIGNATURELINEDIALOG_HXX + +#include "SignatureLineDialogBase.hxx" + +#include +#include +#include +#include + +class SignSignatureLineDialog : public SignatureLineDialogBase +{ +public: + SignSignatureLineDialog(weld::Widget* pParent, css::uno::Reference xModel); + +private: + std::unique_ptr m_xEditName; + std::unique_ptr m_xEditComment; + std::unique_ptr m_xBtnLoadImage; + std::unique_ptr m_xBtnClearImage; + std::unique_ptr m_xBtnChooseCertificate; + std::unique_ptr m_xBtnSign; + std::unique_ptr m_xLabelHint; + std::unique_ptr m_xLabelHintText; + std::unique_ptr m_xLabelAddComment; + + css::uno::Reference m_xShapeProperties; + css::uno::Reference m_xSelectedCertifate; + css::uno::Reference m_xSignatureImage; + OUString m_aSignatureLineId; + OUString m_aSuggestedSignerName; + OUString m_aSuggestedSignerTitle; + bool m_bShowSignDate; + OUString m_sOriginalImageBtnLabel; + + void ValidateFields(); + css::uno::Reference getSignedGraphic(bool bValid); + virtual void Apply() override; + + DECL_LINK(clearImage, weld::Button&, void); + DECL_LINK(loadImage, weld::Button&, void); + DECL_LINK(chooseCertificate, weld::Button&, void); + DECL_LINK(entryChanged, weld::Entry&, void); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/cui/source/inc/SignatureLineDialog.hxx b/cui/source/inc/SignatureLineDialog.hxx new file mode 100644 index 000000000..fd671acd5 --- /dev/null +++ b/cui/source/inc/SignatureLineDialog.hxx @@ -0,0 +1,39 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef INCLUDED_CUI_INC_SIGNATURELINEDIALOG_HXX +#define INCLUDED_CUI_INC_SIGNATURELINEDIALOG_HXX + +#include "SignatureLineDialogBase.hxx" + +#include +#include + +class SignatureLineDialog : public SignatureLineDialogBase +{ +public: + SignatureLineDialog(weld::Widget* pParent, css::uno::Reference xModel, + bool bEditExisting); + +private: + std::unique_ptr m_xEditName; + std::unique_ptr m_xEditTitle; + std::unique_ptr m_xEditEmail; + std::unique_ptr m_xEditInstructions; + std::unique_ptr m_xCheckboxCanAddComments; + std::unique_ptr m_xCheckboxShowSignDate; + + css::uno::Reference m_xExistingShapeProperties; + OUString m_aSignatureLineId; + + virtual void Apply() override; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/cui/source/inc/SignatureLineDialogBase.hxx b/cui/source/inc/SignatureLineDialogBase.hxx new file mode 100644 index 000000000..2e046d945 --- /dev/null +++ b/cui/source/inc/SignatureLineDialogBase.hxx @@ -0,0 +1,34 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef INCLUDED_CUI_INC_SIGNATURELINEDIALOGBASE_HXX +#define INCLUDED_CUI_INC_SIGNATURELINEDIALOGBASE_HXX + +#include + +#include +#include + +class SignatureLineDialogBase : public weld::GenericDialogController +{ +public: + SignatureLineDialogBase(weld::Widget* pParent, css::uno::Reference xModel, + const OUString& rUIFile, const OString& rDialogId); + + virtual short run() override; + +protected: + css::uno::Reference m_xModel; + static OUString getSignatureImage(); + virtual void Apply() = 0; + static OUString getCDataString(const OUString& rString); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/cui/source/inc/SpellDialog.hxx b/cui/source/inc/SpellDialog.hxx new file mode 100644 index 000000000..cb23f1004 --- /dev/null +++ b/cui/source/inc/SpellDialog.hxx @@ -0,0 +1,231 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_SPELLDIALOG_HXX +#define INCLUDED_CUI_SOURCE_INC_SPELLDIALOG_HXX + +#include +#include + + +#include +#include +#include +#include +#include +#include + +#include + +namespace svx{ class SpellUndoAction_Impl;} +class UndoChangeGroupGuard; + +// forward --------------------------------------------------------------- + +struct SpellDialog_Impl; +namespace com::sun::star::linguistic2 { class XSpellChecker1; } + +namespace svx{ +class SpellDialog; +struct SpellErrorDescription; + +class SentenceEditWindow_Impl : public WeldEditView +{ +private: + std::set m_aIgnoreErrorsAt; + SpellDialog* m_pSpellDialog; + weld::Toolbar* m_pToolbar; + sal_Int32 m_nErrorStart; + sal_Int32 m_nErrorEnd; + bool m_bIsUndoEditMode; + + Link m_aModifyLink; + + void CallModifyLink() {m_aModifyLink.Call(nullptr); } + + SpellDialog* GetSpellDialog() const { return m_pSpellDialog; } + + bool GetErrorDescription(SpellErrorDescription& rSpellErrorDescription, sal_Int32 nPosition); + + DECL_LINK(ToolbarHdl, const OString&, void); + +protected: + virtual bool KeyInput( const KeyEvent& rKEvt ) override; + +public: + SentenceEditWindow_Impl(); + virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override; + void SetSpellDialog(SpellDialog* pDialog) { m_pSpellDialog = pDialog; } + virtual ~SentenceEditWindow_Impl() override; + + void Init(weld::Toolbar* pToolbar); + void SetModifyHdl(const Link& rLink) + { + m_aModifyLink = rLink; + m_xEditEngine->SetModifyHdl(m_aModifyLink); + } + + void SetAttrib(const SfxPoolItem& rItem, sal_Int32 nStart, sal_Int32 nEnd); + + void SetText(const OUString& rStr); + + bool MarkNextError( bool bIgnoreCurrentError, const css::uno::Reference& ); + int ChangeMarkedWord(const OUString& rNewWord, LanguageType eLanguage); + void MoveErrorMarkTo(sal_Int32 nErrorStart, sal_Int32 nErrorEnd, bool bGrammar); + OUString GetErrorText() const; + void RestoreCurrentError(); + + void SetAlternatives( + const css::uno::Reference& ); + + bool GetAlternatives(SpellErrorDescription& rDesc); + + void ClearModifyFlag() { m_xEditEngine->ClearModifyFlag(); } + void ResetModified() { ClearModifyFlag(); m_bIsUndoEditMode = false;} + bool IsModified() const { return m_xEditEngine->IsModified(); } + + bool IsUndoEditMode() const { return m_bIsUndoEditMode;} + void SetUndoEditMode(bool bSet); + + svx::SpellPortions CreateSpellPortions() const; + + void ResetUndo(); + void Undo(); + void AddUndoAction( std::unique_ptr pAction ); + size_t GetUndoActionCount() const; + void UndoActionStart( sal_uInt16 nId ); + void UndoActionEnd(); + + void MoveErrorEnd(long nOffset); + + void ResetIgnoreErrorsAt() { m_aIgnoreErrorsAt.clear(); } +}; + +// class SvxSpellDialog --------------------------------------------- +class SpellDialogChildWindow; + +class SpellDialog : public SfxModelessDialogController +{ + friend class SentenceEditWindow_Impl; +private: + OUString m_sResumeST; + OUString m_sIgnoreOnceST; + OUString m_sNoSuggestionsST; + + OUString m_sTitleSpelling; + OUString m_sTitleSpellingGrammar; + + Link aDialogUndoLink; + + bool bFocusLocked; + + svx::SpellDialogChildWindow& rParent; + svx::SpellPortions m_aSavedSentence; + + std::unique_ptr pImpl; + css::uno::Reference< + css::linguistic2::XSpellChecker1 > xSpell; + + std::unique_ptr m_xAltTitle; + std::unique_ptr m_xResumeFT; + std::unique_ptr m_xNoSuggestionsFT; + std::unique_ptr m_xIgnoreOnceFT; + std::unique_ptr m_xLanguageFT; + std::unique_ptr m_xLanguageLB; + std::unique_ptr m_xExplainFT; + std::unique_ptr m_xExplainLink; + std::unique_ptr m_xNotInDictFT; + std::unique_ptr m_xSentenceED; + std::unique_ptr m_xSuggestionFT; + std::unique_ptr m_xSuggestionLB; + std::unique_ptr m_xIgnorePB; + std::unique_ptr m_xIgnoreAllPB; + std::unique_ptr m_xIgnoreRulePB; + std::unique_ptr m_xAddToDictPB; + std::unique_ptr m_xAddToDictMB; + std::unique_ptr m_xChangePB; + std::unique_ptr m_xChangeAllPB; + std::unique_ptr m_xAutoCorrPB; + std::unique_ptr m_xCheckGrammarCB; + std::unique_ptr m_xOptionsPB; + std::unique_ptr m_xUndoPB; + std::unique_ptr m_xClosePB; + std::unique_ptr m_xToolbar; + std::unique_ptr m_xSentenceEDWeld; + + DECL_LINK(ChangeHdl, weld::Button&, void); + DECL_LINK(DoubleClickChangeHdl, weld::TreeView&, bool); + DECL_LINK(ChangeAllHdl, weld::Button&, void); + DECL_LINK(IgnoreAllHdl, weld::Button&, void); + DECL_LINK(IgnoreHdl, weld::Button&, void); + DECL_LINK(CheckGrammarHdl, weld::Button&, void); + DECL_LINK(ExtClickHdl, weld::Button&, void); + DECL_LINK(CancelHdl, weld::Button&, void); + DECL_LINK(ModifyHdl, LinkParamNone*, void); + DECL_LINK(UndoHdl, weld::Button&, void); + DECL_LINK(AddToDictSelectHdl, const OString&, void); + DECL_LINK(AddToDictClickHdl, weld::Button&, void); + DECL_LINK(LanguageSelectHdl, weld::ComboBox&, void); + DECL_LINK(DialogUndoHdl, SpellUndoAction_Impl&, void); + + DECL_LINK(InitHdl, void*, void); + + void AddToDictionaryExecute(const OString& rItemId); + void StartSpellOptDlg_Impl(); + int InitUserDicts(); + void UpdateBoxes_Impl(bool bCallFromSelectHdl = false); + void Init_Impl(); + void SpellContinue_Impl(std::unique_ptr* pGuard = nullptr, bool UseSavedSentence = false, bool bIgnoreCurrentError = false ); + void LockFocusChanges( bool bLock ) {bFocusLocked = bLock;} + void ToplevelFocusChanged(); + void Impl_Restore(bool bUseSavedSentence); + + LanguageType GetSelectedLang_Impl() const; + + /** Retrieves the next sentence. + */ + bool GetNextSentence_Impl(std::unique_ptr* pGuard, bool bUseSavedSentence, bool bRecheck /*for rechecking the current sentence*/); + /** Corrects all errors that have been selected to be changed always + */ + static bool ApplyChangeAllList_Impl(SpellPortions& rSentence, bool& bHasReplaced); + void SetTitle_Impl(LanguageType nLang); + +protected: + + OUString getReplacementString() const; + +public: + SpellDialog( + svx::SpellDialogChildWindow* pChildWindow, + weld::Window * pParent, + SfxBindings* pBindings); + virtual ~SpellDialog() override; + + virtual void Activate() override; + virtual void Deactivate() override; + + virtual void Close() override; + + void InvalidateDialog(); +}; + +} //namespace svx + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/SvxConfigPageHelper.hxx b/cui/source/inc/SvxConfigPageHelper.hxx new file mode 100644 index 000000000..8beed6069 --- /dev/null +++ b/cui/source/inc/SvxConfigPageHelper.hxx @@ -0,0 +1,89 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include + +#include "cfg.hxx" + +class SvxConfigPageHelper +{ +public: + static void RemoveEntry( SvxEntries* pEntries, SvxConfigEntry const * pChildEntry ); + + static OUString replaceSaveInName( const OUString& rMessage, const OUString& rSaveInName ); + static OUString stripHotKey( const OUString& str ); + static OUString replaceSixteen( const OUString& str, sal_Int32 nReplacement ); + + static sal_Int16 GetImageType(); + static void InitImageType(); + static css::uno::Reference< css::graphic::XGraphic > GetGraphic( + const css::uno::Reference< css::ui::XImageManager >& xImageManager, + const OUString& rCommandURL ); + + static OUString generateCustomName( + const OUString& prefix, + SvxEntries* entries, + sal_Int32 suffix = 1 ); + static OUString generateCustomMenuURL( + SvxEntries* entries, + sal_Int32 suffix = 1 ); + static sal_uInt32 generateRandomValue(); + /** + Generates a custom resource URL for a new toolbar. + Typically something like: private:resource/toolbar/custom_toolbar_######## + The last 8 letters are randomly generated alphanumeric characters. + */ + static OUString generateCustomURL( SvxEntries* entries ); + + static OUString GetModuleName( const OUString& aModuleId ); + static OUString GetUIModuleName( + const OUString& aModuleId, + const css::uno::Reference< css::frame::XModuleManager2 >& rModuleManager ); + + static bool GetMenuItemData( + const css::uno::Reference< css::container::XIndexAccess >& rItemContainer, + sal_Int32 nIndex, + OUString& rCommandURL, + OUString& rLabel, + sal_uInt16& rType, + sal_Int32& rStyle, + css::uno::Reference< css::container::XIndexAccess >& rSubMenu ); + static bool GetToolbarItemData( + const css::uno::Reference< css::container::XIndexAccess >& rItemContainer, + sal_Int32 nIndex, + OUString& rCommandURL, + OUString& rLabel, + sal_uInt16& rType, + bool& rIsVisible, + sal_Int32& rStyle ); + + static css::uno::Sequence< css::beans::PropertyValue > ConvertSvxConfigEntry( + const SvxConfigEntry* pEntry ); + static css::uno::Sequence< css::beans::PropertyValue > ConvertToolbarEntry( + const SvxConfigEntry* pEntry ); + + static bool EntrySort( SvxConfigEntry const * a, SvxConfigEntry const * b ); + + static bool SvxConfigEntryModified( SvxConfigEntry const * pEntry ); + +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/SvxMenuConfigPage.hxx b/cui/source/inc/SvxMenuConfigPage.hxx new file mode 100644 index 000000000..50124e46a --- /dev/null +++ b/cui/source/inc/SvxMenuConfigPage.hxx @@ -0,0 +1,72 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include +#include + +#include "cfg.hxx" //for SvxConfigPage and SaveInData + +class SvxMenuConfigPage : public SvxConfigPage +{ +private: + bool m_bIsMenuBar; + + DECL_LINK( SelectMenuEntry, weld::TreeView&, void ); + DECL_LINK( ContentContextMenuHdl, const CommandEvent&, bool ); + DECL_LINK( FunctionContextMenuHdl, const CommandEvent&, bool ); + + DECL_LINK( GearHdl, const OString&, void ); + + DECL_LINK( SelectCategory, weld::ComboBox&, void ); + + DECL_LINK( AddCommandHdl, weld::Button&, void ); + DECL_LINK( RemoveCommandHdl, weld::Button&, void ); + + DECL_LINK( InsertHdl, const OString&, void ); + DECL_LINK( ModifyItemHdl, const OString&, void ); + DECL_LINK( ResetMenuHdl, weld::Button&, void ); + + DECL_LINK( MenuEntriesSizeAllocHdl, const Size&, void ); + + virtual void ListModified() override; + + void Init() override; + void UpdateButtonStates() override; + short QueryReset() override; + void DeleteSelectedContent() override; + void DeleteSelectedTopLevel() override; + + virtual void SelectElement() override; + +public: + SvxMenuConfigPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rItemSet, bool bIsMenuBar = true); + virtual ~SvxMenuConfigPage() override; + + SaveInData* CreateSaveInData( + const css::uno::Reference < + css::ui::XUIConfigurationManager >&, + const css::uno::Reference < + css::ui::XUIConfigurationManager >&, + const OUString& aModuleId, + bool docConfig ) override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/SvxNotebookbarConfigPage.hxx b/cui/source/inc/SvxNotebookbarConfigPage.hxx new file mode 100644 index 000000000..47870949d --- /dev/null +++ b/cui/source/inc/SvxNotebookbarConfigPage.hxx @@ -0,0 +1,87 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include +#include +#include + +#include +#include + +#include "cfg.hxx" //for SvxConfigPage and SaveInData + +class SvxNotebookbarConfigPage : public SvxConfigPage +{ +private: + void UpdateButtonStates() override; + short QueryReset() override; + void Init() override; + void DeleteSelectedContent() override; + void DeleteSelectedTopLevel() override; + virtual void SelectElement() override; + void SetElement(); + +public: + struct NotebookbarEntries + { + OUString sUIItemId; + OUString sClassId; + OUString sActionName; + OUString sDisplayName; + OUString sVisibleValue; + }; + struct CategoriesEntries + { + OUString sDisplayName; + OUString sUIItemId; + OUString sClassType; + }; + SvxNotebookbarConfigPage(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet& rItemSet); + virtual ~SvxNotebookbarConfigPage() override; + SaveInData* CreateSaveInData(const css::uno::Reference&, + const css::uno::Reference&, + const OUString& aModuleId, bool docConfig) override; + static void FillFunctionsList(xmlNodePtr pRootNodePtr, + std::vector& aEntries, + std::vector& aCategoryList, + OUString& sActiveCategory); + static void searchNodeandAttribute(std::vector& aEntries, + std::vector& aCategoryList, + OUString& sActiveCategory, + CategoriesEntries& aCurCategoryEntry, xmlNode* pNodePtr, + bool isCategory); + static void getNodeValue(xmlNode* pNodePtr, NotebookbarEntries& aNodeEntries); +}; + +class SvxNotebookbarEntriesListBox final : public SvxMenuEntriesListBox +{ + void ChangedVisibility(int nRow); + typedef std::pair row_col; + DECL_LINK(CheckButtonHdl, const row_col&, void); + DECL_LINK(KeyInputHdl, const KeyEvent&, bool); + +public: + SvxNotebookbarEntriesListBox(std::unique_ptr xControl, SvxConfigPage* pPg); + virtual ~SvxNotebookbarEntriesListBox() override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/SvxToolbarConfigPage.hxx b/cui/source/inc/SvxToolbarConfigPage.hxx new file mode 100644 index 000000000..5902cdf4b --- /dev/null +++ b/cui/source/inc/SvxToolbarConfigPage.hxx @@ -0,0 +1,90 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include +#include + +#include + +#include "cfg.hxx" //for SvxConfigPage and SaveInData + +class SvxToolbarConfigPage : public SvxConfigPage +{ +private: + + DECL_LINK( SelectToolbarEntry, weld::TreeView&, void ); + DECL_LINK( MoveHdl, weld::Button&, void ); + + DECL_LINK( GearHdl, const OString&, void ); + + DECL_LINK( SelectCategory, weld::ComboBox&, void ); + + DECL_LINK( ContentContextMenuHdl, const CommandEvent&, bool ); + DECL_LINK( FunctionContextMenuHdl, const CommandEvent&, bool ); + + DECL_LINK( AddCommandHdl, weld::Button&, void ); + DECL_LINK( RemoveCommandHdl, weld::Button&, void ); + + DECL_LINK( InsertHdl, const OString&, void ); + DECL_LINK( ModifyItemHdl, const OString&, void ); + DECL_LINK( ResetToolbarHdl, weld::Button&, void ); + + virtual void ListModified() override; + + void UpdateButtonStates() override; + short QueryReset() override; + void Init() override; + void DeleteSelectedContent() override; + void DeleteSelectedTopLevel() override; + virtual void SelectElement() override; + +public: + SvxToolbarConfigPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rItemSet); + virtual ~SvxToolbarConfigPage() override; + + void AddFunction(int nTarget = -1); + + void MoveEntry( bool bMoveUp ) override; + + SaveInData* CreateSaveInData( + const css::uno::Reference < + css::ui::XUIConfigurationManager >&, + const css::uno::Reference < + css::ui::XUIConfigurationManager >&, + const OUString& aModuleId, + bool docConfig ) override; +}; + +class SvxToolbarEntriesListBox final : public SvxMenuEntriesListBox +{ + void ChangedVisibility(int nRow); + + typedef std::pair row_col; + DECL_LINK(CheckButtonHdl, const row_col&, void); + DECL_LINK(KeyInputHdl, const KeyEvent&, bool); + +public: + + SvxToolbarEntriesListBox(std::unique_ptr xControl, SvxToolbarConfigPage* pPg); + virtual ~SvxToolbarEntriesListBox() override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/about.hxx b/cui/source/inc/about.hxx new file mode 100644 index 000000000..2262da38d --- /dev/null +++ b/cui/source/inc/about.hxx @@ -0,0 +1,62 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_ABOUT_HXX +#define INCLUDED_CUI_SOURCE_INC_ABOUT_HXX + +#include +#include + +class AboutDialog : public weld::GenericDialogController +{ +private: + std::unique_ptr m_pCreditsButton; + std::unique_ptr m_pWebsiteButton; + std::unique_ptr m_pReleaseNotesButton; + std::unique_ptr m_pCloseButton; + std::unique_ptr m_pCopyButton; + + std::unique_ptr m_pBrandImage; + std::unique_ptr m_pAboutImage; + std::unique_ptr m_pVersionLabel; + std::unique_ptr m_pBuildCaption; + std::unique_ptr m_pBuildLabel; + std::unique_ptr m_pEnvLabel; + std::unique_ptr m_pUILabel; + std::unique_ptr m_pLocaleLabel; + std::unique_ptr m_pMiscLabel; + std::unique_ptr m_pCopyrightLabel; + + static OUString GetVersionString(); + static OUString GetBuildString(); + static OUString GetLocaleString(); + static OUString GetMiscString(); + + static OUString GetCopyrightString(); + static bool IsStringValidGitHash(const OUString& hash); + + DECL_LINK(HandleClick, weld::Button&, void); + +public: + AboutDialog(weld::Window* pParent); + virtual ~AboutDialog() override; +}; + +#endif // INCLUDED_CUI_SOURCE_INC_ABOUT_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/acccfg.hxx b/cui/source/inc/acccfg.hxx new file mode 100644 index 000000000..aecc923ad --- /dev/null +++ b/cui/source/inc/acccfg.hxx @@ -0,0 +1,155 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include +#include +#include +#include + +#include +#include +#include +#include +#include "cfgutil.hxx" + +class SfxMacroInfoItem; +class CuiConfigFunctionListBox; +class SfxAcceleratorConfigPage; +class SfxStringItem; + +// class SfxAcceleratorConfigPage ---------------------------------------- + +struct TAccInfo +{ +public: + TAccInfo(sal_Int32 nKeyPos, sal_Int32 nListPos, const vcl::KeyCode& aKey) + : m_nKeyPos(nKeyPos) + , m_nListPos(nListPos) + , m_bIsConfigurable(true) /**< it's important to set true as default - + because only fix entries will be disabled later... */ + , m_sCommand() + , m_aKey(aKey) + { + } + + bool isConfigured() const + { + return (m_nKeyPos > -1 && m_nListPos > -1 && !m_sCommand.isEmpty()); + } + + sal_Int32 m_nKeyPos; + sal_Int32 m_nListPos; + bool m_bIsConfigurable; + OUString m_sCommand; + vcl::KeyCode m_aKey; +}; + +namespace sfx2 +{ +class FileDialogHelper; +} + +enum class StartFileDialogType +{ + Open, + SaveAs +}; + +class SfxAcceleratorConfigPage : public SfxTabPage +{ +private: + const SfxMacroInfoItem* m_pMacroInfoItem; + std::unique_ptr m_pFileDlg; + + OUString aLoadAccelConfigStr; + OUString aSaveAccelConfigStr; + OUString aFilterAllStr; + OUString aFilterCfgStr; + SfxStylesInfo_Impl m_aStylesInfo; + bool m_bStylesInfoInitialized; + + css::uno::Reference m_xContext; + css::uno::Reference m_xGlobal; + css::uno::Reference m_xModule; + css::uno::Reference m_xAct; + css::uno::Reference m_xUICmdDescription; + css::uno::Reference m_xFrame; + + OUString m_sModuleLongName; + OUString m_sModuleUIName; + + // For search + Timer m_aUpdateDataTimer; + i18nutil::SearchOptions2 m_options; + + Idle m_aFillGroupIdle; + + std::unique_ptr m_xEntriesBox; + std::unique_ptr m_xOfficeButton; + std::unique_ptr m_xModuleButton; + std::unique_ptr m_xChangeButton; + std::unique_ptr m_xRemoveButton; + std::unique_ptr m_xGroupLBox; + std::unique_ptr m_xFunctionBox; + std::unique_ptr m_xKeyBox; + std::unique_ptr m_xSearchEdit; + std::unique_ptr m_xLoadButton; + std::unique_ptr m_xSaveButton; + std::unique_ptr m_xResetButton; + + DECL_LINK(ChangeHdl, weld::Button&, void); + DECL_LINK(RemoveHdl, weld::Button&, void); + DECL_LINK(SelectHdl, weld::TreeView&, void); + DECL_LINK(SearchUpdateHdl, weld::Entry&, void); + DECL_LINK(Save, weld::Button&, void); + DECL_LINK(Load, weld::Button&, void); + DECL_LINK(Default, weld::Button&, void); + DECL_LINK(RadioHdl, weld::Button&, void); + DECL_LINK(ImplUpdateDataHdl, Timer*, void); + DECL_LINK(FocusOut_Impl, weld::Widget&, void); + DECL_LINK(TimeOut_Impl, Timer*, void); + + DECL_LINK(KeyInputHdl, const KeyEvent&, bool); + + DECL_LINK(LoadHdl, sfx2::FileDialogHelper*, void); + DECL_LINK(SaveHdl, sfx2::FileDialogHelper*, void); + + OUString GetLabel4Command(const OUString& rCommand); + int applySearchFilter(OUString const& rSearchTerm); + void InitAccCfg(); + sal_Int32 MapKeyCodeToPos(const vcl::KeyCode& rCode) const; + void StartFileDialog(StartFileDialogType nType, const OUString& rTitle); + + void Init(const css::uno::Reference& pAccMgr); + void ResetConfig(); + +public: + SfxAcceleratorConfigPage(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet& rItemSet); + virtual ~SfxAcceleratorConfigPage() override; + + virtual bool FillItemSet(SfxItemSet*) override; + virtual void Reset(const SfxItemSet*) override; + + void Apply(const css::uno::Reference& pAccMgr); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/align.hxx b/cui/source/inc/align.hxx new file mode 100644 index 000000000..43c2fe0ee --- /dev/null +++ b/cui/source/inc/align.hxx @@ -0,0 +1,122 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_ALIGN_HXX +#define INCLUDED_CUI_SOURCE_INC_ALIGN_HXX + +// list box indexes +#define ALIGNDLG_HORALIGN_STD 0 +#define ALIGNDLG_HORALIGN_LEFT 1 +#define ALIGNDLG_HORALIGN_CENTER 2 +#define ALIGNDLG_HORALIGN_RIGHT 3 +#define ALIGNDLG_HORALIGN_BLOCK 4 +#define ALIGNDLG_HORALIGN_FILL 5 +#define ALIGNDLG_HORALIGN_DISTRIBUTED 6 + +#define ALIGNDLG_VERALIGN_STD 0 +#define ALIGNDLG_VERALIGN_TOP 1 +#define ALIGNDLG_VERALIGN_MID 2 +#define ALIGNDLG_VERALIGN_BOTTOM 3 +#define ALIGNDLG_VERALIGN_BLOCK 4 +#define ALIGNDLG_VERALIGN_DISTRIBUTED 5 + +#include +#include +#include +#include +#include + +namespace svx { + + +class AlignmentTabPage : public SfxTabPage +{ + static const sal_uInt16 s_pRanges[]; + +public: + virtual ~AlignmentTabPage() override; + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet ); + explicit AlignmentTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreSet); + + static const sal_uInt16* GetRanges() { return s_pRanges; } + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; + virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override; + +private: + void InitVsRefEgde(); + void UpdateEnableControls(); + + bool HasAlignmentChanged( const SfxItemSet& rNew, sal_uInt16 nWhich ) const; + + DECL_LINK(UpdateEnableHdl, weld::ComboBox&, void); + DECL_LINK(StackedClickHdl, weld::ToggleButton&, void); + DECL_LINK(AsianModeClickHdl, weld::ToggleButton&, void); + DECL_LINK(WrapClickHdl, weld::ToggleButton&, void); + DECL_LINK(HyphenClickHdl, weld::ToggleButton&, void); + DECL_LINK(ShrinkClickHdl, weld::ToggleButton&, void); + +private: + weld::TriStateEnabled m_aStackedState; + weld::TriStateEnabled m_aAsianModeState; + weld::TriStateEnabled m_aWrapState; + weld::TriStateEnabled m_aHyphenState; + weld::TriStateEnabled m_aShrinkState; + + ValueSet m_aVsRefEdge; + + std::unique_ptr m_xLbHorAlign; + std::unique_ptr m_xFtIndent; + std::unique_ptr m_xEdIndent; + std::unique_ptr m_xFtVerAlign; + std::unique_ptr m_xLbVerAlign; + + std::unique_ptr m_xFtRotate; + std::unique_ptr m_xNfRotate; + std::unique_ptr m_xFtRefEdge; + std::unique_ptr m_xCbStacked; + std::unique_ptr m_xCbAsianMode; + + std::unique_ptr m_xBoxDirection; + std::unique_ptr m_xBtnWrap; + std::unique_ptr m_xBtnHyphen; + std::unique_ptr m_xBtnShrink; + std::unique_ptr m_xLbFrameDir; + + // hidden labels/string + std::unique_ptr m_xFtBotLock; + std::unique_ptr m_xFtTopLock; + std::unique_ptr m_xFtCelLock; + std::unique_ptr m_xFtABCD; + + std::unique_ptr m_xAlignmentFrame; + std::unique_ptr m_xOrientFrame; + std::unique_ptr m_xPropertiesFrame; + + std::unique_ptr m_xVsRefEdge; + std::unique_ptr m_xCtrlDial; + std::unique_ptr m_xCtrlDialWin; +}; + + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/autocdlg.hxx b/cui/source/inc/autocdlg.hxx new file mode 100644 index 000000000..e0c780fe8 --- /dev/null +++ b/cui/source/inc/autocdlg.hxx @@ -0,0 +1,417 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_AUTOCDLG_HXX +#define INCLUDED_CUI_SOURCE_INC_AUTOCDLG_HXX + +#include +#include +#include + +#include +#include + +class CharClass; +class CollatorWrapper; +class SmartTagMgr; + +namespace editeng { class SortedAutoCompleteStrings; } + +// class OfaAutoCorrDlg -------------------------------------------------- + +class OfaAutoCorrDlg : public SfxTabDialogController +{ + std::unique_ptr m_xLanguageBox; + std::unique_ptr m_xLanguageLB; + + DECL_LINK(SelectLanguageHdl, weld::ComboBox&, void); +public: + + OfaAutoCorrDlg(weld::Window* pParent, const SfxItemSet *pSet); + virtual ~OfaAutoCorrDlg() override; + + void EnableLanguage(bool bEnable); +}; + +// class OfaAutocorrOptionsPage ------------------------------------------ + +class OfaAutocorrOptionsPage : public SfxTabPage +{ +private: + OUString m_sInput; + OUString m_sDoubleCaps; + OUString m_sStartCap; + OUString m_sBoldUnderline; + OUString m_sURL; + OUString m_sNoDblSpaces; + OUString m_sDash; + OUString m_sAccidentalCaps; + + std::unique_ptr m_xCheckLB; + + void InsertEntry(const OUString& rTxt); + +public: + OfaAutocorrOptionsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + virtual ~OfaAutocorrOptionsPage() override; + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet); + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; + virtual void ActivatePage( const SfxItemSet& ) override; + +}; + +// class OfaSwAutoFmtOptionsPage ---------------------------------------------------- + +class OfaSwAutoFmtOptionsPage : public SfxTabPage +{ + OUString sDeleteEmptyPara; + OUString sUseReplaceTbl; + OUString sCapitalStartWord; + OUString sCapitalStartSentence; + OUString sUserStyle; + OUString sBullet; + OUString sBoldUnder; + OUString sNoDblSpaces; + OUString sCorrectCapsLock; + OUString sDetectURL; + OUString sDash; + OUString sRightMargin; + OUString sNum; + OUString sBorder; + OUString sTable; + OUString sReplaceTemplates; + OUString sDelSpaceAtSttEnd; + OUString sDelSpaceBetweenLines; + + OUString sMargin; + OUString sBulletChar; + OUString sByInputBulletChar; + + vcl::Font aBulletFont; + vcl::Font aByInputBulletFont; + sal_uInt16 nPercent; + + std::unique_ptr m_xCheckLB; + std::unique_ptr m_xEditPB; + + DECL_LINK(SelectHdl, weld::TreeView&, void); + DECL_LINK(EditHdl, weld::Button&, void); + DECL_LINK(DoubleClickEditHdl, weld::TreeView&, bool); + + void CreateEntry(const OUString& rTxt, sal_uInt16 nCol); + +public: + OfaSwAutoFmtOptionsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet); + virtual ~OfaSwAutoFmtOptionsPage() override; + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; + virtual void ActivatePage( const SfxItemSet& ) override; +}; + +// class OfaAutocorrReplacePage ------------------------------------------ + +struct DoubleString +{ + OUString sShort; + OUString sLong; + void* pUserData; ///< CheckBox -> form. Text Bool -> selection text +}; + +typedef std::vector DoubleStringArray; + +struct StringChangeList +{ + DoubleStringArray aNewEntries; + DoubleStringArray aDeletedEntries; +}; + +typedef std::map StringChangeTable; + +class OfaAutocorrReplacePage : public SfxTabPage +{ +private: + + StringChangeTable aChangesTable; + + OUString sModify; + OUString sNew; + + std::set aFormatText; + std::map + aDoubleStringTable; + std::unique_ptr pCompareClass; + std::unique_ptr pCharClass; + LanguageType eLang; + + bool bHasSelectionText; + bool bFirstSelect:1; + bool bReplaceEditChanged:1; + bool bSWriter:1; + + std::vector m_aReplaceFixedWidths; + std::unique_ptr m_xTextOnlyCB; + std::unique_ptr m_xShortED; + std::unique_ptr m_xReplaceED; + std::unique_ptr m_xReplaceTLB; + std::unique_ptr m_xNewReplacePB; + std::unique_ptr m_xReplacePB; + std::unique_ptr m_xDeleteReplacePB; + std::unique_ptr m_xButtonBox; + + DECL_LINK(SelectHdl, weld::TreeView&, void); + DECL_LINK(NewDelButtonHdl, weld::Button&, void); + DECL_LINK(NewDelActionHdl, weld::Entry&, bool); + DECL_LINK(EntrySizeAllocHdl, const Size&, void); + DECL_LINK(ModifyHdl, weld::Entry&, void); + bool NewDelHdl(const weld::Widget*); + + void RefillReplaceBox( bool bFromReset, + LanguageType eOldLanguage, + LanguageType eNewLanguage); + +public: + OfaAutocorrReplacePage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + virtual ~OfaAutocorrReplacePage() override; + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet); + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; + virtual void ActivatePage( const SfxItemSet& ) override; + virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override; + + void SetLanguage(LanguageType eSet); + void DeleteEntry(const OUString& sShort, const OUString& sLong); + void NewEntry(const OUString& sShort, const OUString& sLong, bool bKeepSourceFormatting); +}; + +// class OfaAutocorrExceptPage --------------------------------------------- + +struct StringsArrays +{ + std::vector aAbbrevStrings; + std::vector aDoubleCapsStrings; + + StringsArrays() { } +}; +typedef std::map StringsTable; + +class OfaAutocorrExceptPage : public SfxTabPage +{ +private: + StringsTable aStringsTable; + std::unique_ptr pCompareClass; + LanguageType eLang; + + std::unique_ptr m_xAbbrevED; + std::unique_ptr m_xAbbrevLB; + std::unique_ptr m_xNewAbbrevPB; + std::unique_ptr m_xDelAbbrevPB; + std::unique_ptr m_xAutoAbbrevCB; + + std::unique_ptr m_xDoubleCapsED; + std::unique_ptr m_xDoubleCapsLB; + std::unique_ptr m_xNewDoublePB; + std::unique_ptr m_xDelDoublePB; + std::unique_ptr m_xAutoCapsCB; + + DECL_LINK(NewDelButtonHdl, weld::Button&, void); + DECL_LINK(NewDelActionHdl, weld::Entry&, bool); + DECL_LINK(SelectHdl, weld::TreeView&, void); + DECL_LINK(ModifyHdl, weld::Entry&, void); + void NewDelHdl(const weld::Widget*); + /// Box filled with new language + void RefillReplaceBoxes(bool bFromReset, + LanguageType eOldLanguage, + LanguageType eNewLanguage); +public: + OfaAutocorrExceptPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + virtual ~OfaAutocorrExceptPage() override; + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet); + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; + virtual void ActivatePage( const SfxItemSet& ) override; + virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override; + void SetLanguage(LanguageType eSet); + +}; + +// class OfaQuoteTabPage ------------------------------------------------- + +class OfaQuoteTabPage : public SfxTabPage +{ +private: + OUString sNonBrkSpace; + OUString sOrdinal; + OUString sTransliterateRTL; + OUString sAngleQuotes; + + sal_UCS4 cSglStartQuote; + sal_UCS4 cSglEndQuote; + + sal_UCS4 cStartQuote; + sal_UCS4 cEndQuote; + + std::unique_ptr m_xSingleTypoCB; + std::unique_ptr m_xSglStartQuotePB; + std::unique_ptr m_xSglStartExFT; + std::unique_ptr m_xSglEndQuotePB; + std::unique_ptr m_xSglEndExFT; + std::unique_ptr m_xSglStandardPB; + std::unique_ptr m_xDoubleTypoCB; + std::unique_ptr m_xDblStartQuotePB; + std::unique_ptr m_xDblStartExFT; + std::unique_ptr m_xDblEndQuotePB; + std::unique_ptr m_xDblEndExFT; + std::unique_ptr m_xDblStandardPB; + OUString m_sStandard; + /// For anything but writer + std::unique_ptr m_xCheckLB; + /// Just for writer + std::unique_ptr m_xSwCheckLB; + + + DECL_LINK(QuoteHdl, weld::Button&, void); + DECL_LINK(StdQuoteHdl, weld::Button&, void); + + OUString ChangeStringExt_Impl( sal_UCS4 ); + + static void CreateEntry(weld::TreeView& rLstBox, const OUString& rTxt, + sal_uInt16 nCol, sal_uInt16 nTextCol); + +public: + OfaQuoteTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + static std::unique_ptr Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet); + virtual ~OfaQuoteTabPage() override; + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; + virtual void ActivatePage( const SfxItemSet& ) override; +}; + +// class OfaAutoCompleteTabPage --------------------------------------------- + +class OfaAutoCompleteTabPage : public SfxTabPage +{ +private: + editeng::SortedAutoCompleteStrings* m_pAutoCompleteList; + sal_uInt16 m_nAutoCmpltListCnt; + + std::unique_ptr m_xCBActiv; /// m_xCBAppendSpace;/// m_xCBAsTip; /// m_xCBCollect;/// m_xCBRemoveList;///<...save the list for later use... + + std::unique_ptr m_xDCBExpandKey; + std::unique_ptr m_xNFMinWordlen; + std::unique_ptr m_xNFMaxEntries; + std::unique_ptr m_xLBEntries; + std::unique_ptr m_xPBEntries; + + DECL_LINK(CheckHdl, weld::ToggleButton&, void); + DECL_LINK(KeyReleaseHdl, const KeyEvent&, bool); + +public: + OfaAutoCompleteTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + static std::unique_ptr Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet); + virtual ~OfaAutoCompleteTabPage() override; + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; + virtual void ActivatePage( const SfxItemSet& ) override; + + void CopyToClipboard() const; + DECL_LINK(DeleteHdl, weld::Button&, void); +}; + +// class OfaSmartTagOptionsTabPage --------------------------------------------- + +/** Smart tag options tab page + + This tab page is used to enable/disable smart tag types +*/ +class OfaSmartTagOptionsTabPage : public SfxTabPage +{ +private: + + // controls + std::unique_ptr m_xMainCB; + std::unique_ptr m_xSmartTagTypesLB; + std::unique_ptr m_xPropertiesPB; + + /** Inserts items into m_aSmartTagTypesLB + + Reads out the smart tag types supported by the SmartTagMgr and + inserts the associated strings into the list box. + */ + void FillListBox( const SmartTagMgr& rSmartTagMgr ); + + /** Clears the m_aSmartTagTypesLB + */ + void ClearListBox(); + + /** Handler for the check box + + Enables/disables all controls in the tab page (except from the + check box. + */ + DECL_LINK(CheckHdl, weld::ToggleButton&, void); + + /** Handler for the push button + + Calls the displayPropertyPage function of the smart tag recognizer + associated with the currently selected smart tag type. + */ + DECL_LINK(ClickHdl, weld::Button&, void); + + /** Handler for the list box + + Enables/disables the properties push button if selection in the + smart tag types list box changes. + */ + DECL_LINK(SelectHdl, weld::TreeView&, void); + +public: + /// construction via Create() + OfaSmartTagOptionsTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + virtual ~OfaSmartTagOptionsTabPage() override; + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet); + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; + virtual void ActivatePage( const SfxItemSet& ) override; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/backgrnd.hxx b/cui/source/inc/backgrnd.hxx new file mode 100644 index 000000000..14d30703e --- /dev/null +++ b/cui/source/inc/backgrnd.hxx @@ -0,0 +1,70 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_BACKGRND_HXX +#define INCLUDED_CUI_SOURCE_INC_BACKGRND_HXX + +#include + +#include "cuitabarea.hxx" + +class BackgroundPreviewImpl; +class SvxOpenGraphicDialog; +class SvxBrushItem; + +/** class SvxBackgroundTabPage -------------------------------------------- + + [Description] + With this TabPage a Brush (e. g. for a frame's background color) + can be set. + [Items] + : ; +*/ + +class SvxBkgTabPage : public SvxAreaTabPage +{ + static const sal_uInt16 pPageRanges[]; + + std::unique_ptr m_xTblLBox; + bool bHighlighting : 1; + bool bCharBackColor : 1; + SfxItemSet maSet; + std::unique_ptr m_pResetSet; + + sal_Int32 m_nActPos = -1; + + DECL_LINK(TblDestinationHdl_Impl, weld::ComboBox&, void); +public: + SvxBkgTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + virtual ~SvxBkgTabPage() override; + + // returns the area of the which-values + static const sal_uInt16* GetRanges() { return pPageRanges; } + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* ); + virtual bool FillItemSet( SfxItemSet* ) override; + virtual void ActivatePage( const SfxItemSet& ) override; + virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override; + virtual void PageCreated( const SfxAllItemSet& aSet ) override; + virtual void Reset( const SfxItemSet * ) override; +}; + +#endif // INCLUDED_CUI_SOURCE_INC_BACKGRND_HXX + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/bbdlg.hxx b/cui/source/inc/bbdlg.hxx new file mode 100644 index 000000000..b25b7cc09 --- /dev/null +++ b/cui/source/inc/bbdlg.hxx @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_BBDLG_HXX +#define INCLUDED_CUI_SOURCE_INC_BBDLG_HXX + +#include + +/*-------------------------------------------------------------------- + Description: bunch the border background pages + --------------------------------------------------------------------*/ + +class SvxBorderBackgroundDlg: public SfxTabDialogController +{ +public: + SvxBorderBackgroundDlg(weld::Window *pParent, + const SfxItemSet& rCoreSet, + bool bEnableSelector, + bool bEnableDrawingLayerFillStyles); +protected: + virtual void PageCreated(const OString& rPageId, SfxTabPage& rTabPage) override; + +private: + bool mbEnableBackgroundSelector : 1; ///< for Border/Background +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/border.hxx b/cui/source/inc/border.hxx new file mode 100644 index 000000000..7af464924 --- /dev/null +++ b/cui/source/inc/border.hxx @@ -0,0 +1,194 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_BORDER_HXX +#define INCLUDED_CUI_SOURCE_INC_BORDER_HXX + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +// forward --------------------------------------------------------------- + +namespace editeng +{ + class SvxBorderLine; +} + +class ShadowControlsWrapper +{ +public: + explicit ShadowControlsWrapper(ValueSet& rVsPos, weld::MetricSpinButton& rMfSize, ColorListBox& rLbColor); + + SvxShadowItem GetControlValue(const SvxShadowItem& rItem) const; + void SetControlValue(const SvxShadowItem& rItem); + void SetControlDontKnow(); + + bool get_value_changed_from_saved() const; + +private: + ValueSet& mrVsPos; + weld::MetricSpinButton& mrMfSize; + ColorListBox& mrLbColor; +}; + +class MarginControlsWrapper +{ +public: + explicit MarginControlsWrapper(weld::MetricSpinButton& rMfLeft, weld::MetricSpinButton& rMfRight, + weld::MetricSpinButton& rMfTop, weld::MetricSpinButton& rMfBottom); + + SvxMarginItem GetControlValue(const SvxMarginItem& rItem) const; + void SetControlValue(const SvxMarginItem& rItem); + void SetControlDontKnow(); + + bool get_value_changed_from_saved() const; + +private: + weld::MetricSpinButton& mrLeftWrp; + weld::MetricSpinButton& mrRightWrp; + weld::MetricSpinButton& mrTopWrp; + weld::MetricSpinButton& mrBottomWrp; +}; + +class SvxBorderTabPage : public SfxTabPage +{ + static const sal_uInt16 pRanges[]; + +public: + SvxBorderTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs); + virtual ~SvxBorderTabPage() override; + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet); + static const sal_uInt16* GetRanges() { return pRanges; } + + virtual bool FillItemSet( SfxItemSet* rCoreAttrs ) override; + virtual void Reset( const SfxItemSet* ) override; + virtual void ChangesApplied() override; + + void HideShadowControls(); + virtual void PageCreated(const SfxAllItemSet& aSet) override; + void SetTableMode(); +protected: + virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override; + +private: + std::vector m_aShadowImgVec; + std::vector m_aBorderImgVec; + + long nMinValue; ///< minimum distance + SwBorderModes nSWMode; ///< table, textframe, paragraph + sal_uInt16 mnBoxSlot; + sal_uInt16 mnShadowSlot; + + bool mbHorEnabled; ///< true = Inner horizontal border enabled. + bool mbVerEnabled; ///< true = Inner vertical border enabled. + bool mbTLBREnabled; ///< true = Top-left to bottom-right border enabled. + bool mbBLTREnabled; ///< true = Bottom-left to top-right border enabled. + bool mbUseMarginItem; + bool mbLeftModified; + bool mbRightModified; + bool mbTopModified; + bool mbBottomModified; + bool mbSync; + bool mbRemoveAdjacentCellBorders; + bool bIsCalcDoc; + + std::set maUsedBorderStyles; + + // Controls + svx::FrameSelector m_aFrameSel; + std::unique_ptr m_xWndPresets; + std::unique_ptr m_xWndPresetsWin; + std::unique_ptr m_xUserDefFT; + std::unique_ptr m_xFrameSelWin; + + std::unique_ptr m_xLbLineStyle; + std::unique_ptr m_xLbLineColor; + std::unique_ptr m_xLineWidthMF; + + std::unique_ptr m_xSpacingFrame; + std::unique_ptr m_xLeftFT; + std::unique_ptr m_xLeftMF; + std::unique_ptr m_xRightFT; + std::unique_ptr m_xRightMF; + std::unique_ptr m_xTopFT; + std::unique_ptr m_xTopMF; + std::unique_ptr m_xBottomFT; + std::unique_ptr m_xBottomMF; + std::unique_ptr m_xSynchronizeCB; + + std::unique_ptr m_xShadowFrame; + std::unique_ptr m_xWndShadows; + std::unique_ptr m_xWndShadowsWin; + std::unique_ptr m_xFtShadowSize; + std::unique_ptr m_xEdShadowSize; + std::unique_ptr m_xFtShadowColor; + std::unique_ptr m_xLbShadowColor; + + std::unique_ptr m_xPropertiesFrame;///< properties - "Merge with next paragraph" in Writer + std::unique_ptr m_xMergeWithNextCB; + // #i29550# + std::unique_ptr m_xMergeAdjacentBordersCB; + std::unique_ptr m_xRemoveAdjcentCellBordersCB; + std::unique_ptr m_xRemoveAdjcentCellBordersFT; + std::unique_ptr m_xShadowControls; + std::unique_ptr m_xMarginControls; + + // Handler + DECL_LINK(SelStyleHdl_Impl, SvtLineListBox&, void); + DECL_LINK(SelColHdl_Impl, ColorListBox&, void); + DECL_LINK(SelPreHdl_Impl, ValueSet*, void); + DECL_LINK(SelSdwHdl_Impl, ValueSet*, void); + DECL_LINK(LinesChanged_Impl, LinkParamNone*, void); + DECL_LINK(ModifyDistanceHdl_Impl, weld::MetricSpinButton&, void); + DECL_LINK(ModifyWidthHdl_Impl, weld::MetricSpinButton&, void); + DECL_LINK(SyncHdl_Impl, weld::ToggleButton&, void); + DECL_LINK(RemoveAdjacentCellBorderHdl_Impl, weld::ToggleButton&, void); + + sal_uInt16 GetPresetImageId(sal_uInt16 nValueSetIdx) const; + const char* GetPresetStringId(sal_uInt16 nValueSetIdx) const; + + void FillPresetVS(); + void FillShadowVS(); + void FillValueSets(); + + // Filler + void FillLineListBox_Impl(); + + /// share for individual Frame-/Core-Line + void ResetFrameLine_Impl( svx::FrameBorderType eBorder, + const editeng::SvxBorderLine* pCurLine, + bool bValid ); + + bool IsBorderLineStyleAllowed( SvxBorderLineStyle nStyle ) const; + void UpdateRemoveAdjCellBorderCB( sal_uInt16 nPreset ); +}; + + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/cfg.hxx b/cui/source/inc/cfg.hxx new file mode 100644 index 000000000..f413495a1 --- /dev/null +++ b/cui/source/inc/cfg.hxx @@ -0,0 +1,673 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "cfgutil.hxx" +#include "CommandCategoryListBox.hxx" + +#define notebookbarTabScope "notebookbarTabScope" + +static const char ITEM_DESCRIPTOR_COMMANDURL[] = "CommandURL"; +static const char ITEM_DESCRIPTOR_CONTAINER[] = "ItemDescriptorContainer"; +static const char ITEM_DESCRIPTOR_LABEL[] = "Label"; +static const char ITEM_DESCRIPTOR_TYPE[] = "Type"; +static const char ITEM_DESCRIPTOR_STYLE[] = "Style"; +static const char ITEM_DESCRIPTOR_ISVISIBLE[] = "IsVisible"; +static const char ITEM_DESCRIPTOR_RESOURCEURL[] = "ResourceURL"; +static const char ITEM_DESCRIPTOR_UINAME[] = "UIName"; + +static const char ITEM_MENUBAR_URL[] = "private:resource/menubar/menubar"; +static const char ITEM_TOOLBAR_URL[] = "private:resource/toolbar/"; + +static const char CUSTOM_TOOLBAR_STR[] = "custom_toolbar_"; + +static const char aMenuSeparatorStr[] = " | "; + +class SvxConfigEntry; +class SvxConfigPage; + +typedef std::vector< SvxConfigEntry* > SvxEntries; + +class SvxConfigDialog : public SfxTabDialogController +{ +private: + css::uno::Reference< css::frame::XFrame > m_xFrame; + +public: + SvxConfigDialog(weld::Window*, const SfxItemSet*); + + virtual void PageCreated(const OString& rId, SfxTabPage &rPage) override; + void SetFrame(const css::uno::Reference< css::frame::XFrame >& xFrame); +}; + +class SaveInData +{ +private: + + bool bModified; + + bool bDocConfig; + bool bReadOnly; + + css::uno::Reference + < css::ui::XUIConfigurationManager > m_xCfgMgr; + + css::uno::Reference + < css::ui::XUIConfigurationManager > m_xParentCfgMgr; + + css::uno::Reference + < css::ui::XImageManager > m_xImgMgr; + + css::uno::Reference + < css::ui::XImageManager > m_xParentImgMgr; + + static css::uno::Reference + < css::ui::XImageManager >* xDefaultImgMgr; + +protected: + + void ApplyMenu( + css::uno::Reference< css::container::XIndexContainer > const & rMenuBar, + css::uno::Reference< css::lang::XSingleComponentFactory >& rFactory, + SvxConfigEntry *pMenuData ); + + void LoadSubMenus( + const css::uno::Reference< css::container::XIndexAccess >& xMenuSettings, + const OUString& rBaseTitle, SvxConfigEntry const * pParentData, bool bContextMenu ); + +public: + + SaveInData( + const css::uno::Reference < css::ui::XUIConfigurationManager >& xCfgMgr, + const css::uno::Reference < css::ui::XUIConfigurationManager >& xParentCfgMgr, + const OUString& aModuleId, + bool docConfig ); + + virtual ~SaveInData() {} + + bool PersistChanges( + const css::uno::Reference< css::uno::XInterface >& xManager ); + + void SetModified( bool bValue = true ) { bModified = bValue; } + bool IsModified( ) const { return bModified; } + + bool IsReadOnly( ) const { return bReadOnly; } + bool IsDocConfig( ) const { return bDocConfig; } + + const css::uno::Reference + < css::ui::XUIConfigurationManager >& + GetConfigManager() const { return m_xCfgMgr; }; + + const css::uno::Reference + < css::ui::XUIConfigurationManager >& + GetParentConfigManager() const { return m_xParentCfgMgr; }; + + const css::uno::Reference + < css::ui::XImageManager >& + GetImageManager() const { return m_xImgMgr; }; + + const css::uno::Reference + < css::ui::XImageManager >& + GetParentImageManager() const { return m_xParentImgMgr; }; + + css::uno::Reference + < css::container::XNameAccess > m_xCommandToLabelMap; + + css::uno::Sequence + < css::beans::PropertyValue > m_aSeparatorSeq; + + css::uno::Reference GetImage(const OUString& rCommandURL); + + virtual bool HasURL( const OUString& aURL ) = 0; + virtual bool HasSettings() = 0; + virtual SvxEntries* GetEntries() = 0; + virtual void SetEntries( std::unique_ptr ) = 0; + virtual void Reset() = 0; + virtual bool Apply() = 0; +}; + +class MenuSaveInData : public SaveInData +{ +private: + + OUString m_aMenuResourceURL; + OUString m_aDescriptorContainer; + + css::uno::Reference + < css::container::XIndexAccess > m_xMenuSettings; + + std::unique_ptr pRootEntry; + + + static MenuSaveInData* pDefaultData; ///< static holder of the default menu data + + static void SetDefaultData( MenuSaveInData* pData ) {pDefaultData = pData;} + static MenuSaveInData* GetDefaultData() { return pDefaultData; } + + void Apply( + css::uno::Reference< css::container::XIndexContainer > const & rNewMenuBar, + css::uno::Reference< css::lang::XSingleComponentFactory >& rFactory ); + +public: + + MenuSaveInData( + const css::uno::Reference< css::ui::XUIConfigurationManager >&, + const css::uno::Reference< css::ui::XUIConfigurationManager >&, + const OUString& aModuleId, + bool docConfig ); + + virtual ~MenuSaveInData() override; + + /// methods inherited from SaveInData + SvxEntries* GetEntries() override; + void SetEntries( std::unique_ptr ) override; + bool HasURL( const OUString& ) override { return false; } + bool HasSettings() override { return m_xMenuSettings.is(); } + void Reset() override; + bool Apply() override; +}; + +class ContextMenuSaveInData : public SaveInData +{ +private: + std::unique_ptr< SvxConfigEntry > m_pRootEntry; + css::uno::Reference< css::container::XNameAccess > m_xPersistentWindowState; + OUString GetUIName( const OUString& rResourceURL ); + +public: + ContextMenuSaveInData( + const css::uno::Reference< css::ui::XUIConfigurationManager >& xCfgMgr, + const css::uno::Reference< css::ui::XUIConfigurationManager >& xParentCfgMgr, + const OUString& aModuleId, bool bIsDocConfig ); + virtual ~ContextMenuSaveInData() override; + + SvxEntries* GetEntries() override; + void SetEntries( std::unique_ptr pNewEntries ) override; + bool HasSettings() override; + bool HasURL( const OUString& rURL ) override; + void Reset() override; + bool Apply() override; + + void ResetContextMenu( const SvxConfigEntry* pEntry ); +}; + +class SvxConfigEntry +{ +private: + + /// common properties + sal_uInt16 nId; + OUString aLabel; + OUString aCommand; + + bool bPopUp; + bool bStrEdited; + bool bIsUserDefined; + bool bIsMain; + bool bIsParentData; + bool bIsModified; + + /// toolbar specific properties + bool bIsVisible; + sal_Int32 nStyle; + + css::uno::Reference< + css::graphic::XGraphic > xBackupGraphic; + + std::unique_ptr mpEntries; + +public: + + SvxConfigEntry( const OUString& rDisplayName, + const OUString& rCommandURL, + bool bPopup, + bool bParentData ); + + SvxConfigEntry() + : + nId( 0 ), + bPopUp( false ), + bStrEdited( false ), + bIsUserDefined( false ), + bIsMain( false ), + bIsParentData( false ), + bIsModified( false ), + bIsVisible( true ), + nStyle( 0 ) + {} + + ~SvxConfigEntry(); + + const OUString& GetCommand() const { return aCommand; } + + const OUString& GetName() const { return aLabel; } + void SetName( const OUString& rStr ) { aLabel = rStr; bStrEdited = true; } + bool HasChangedName() const { return bStrEdited; } + + bool IsPopup() const { return bPopUp; } + + void SetUserDefined( bool bOn = true ) { bIsUserDefined = bOn; } + bool IsUserDefined() const { return bIsUserDefined; } + + bool IsBinding() const { return !bPopUp; } + bool IsSeparator() const { return nId == 0; } + + SvxEntries* GetEntries() const { return mpEntries.get(); } + void SetEntries( std::unique_ptr entries ) { mpEntries = std::move(entries); } + + void SetMain() { bIsMain = true; } + bool IsMain() const { return bIsMain; } + + void SetParentData( bool bValue = true ) { bIsParentData = bValue; } + bool IsParentData() const { return bIsParentData; } + + void SetModified( bool bValue = true ) { bIsModified = bValue; } + bool IsModified() const { return bIsModified; } + + bool IsMovable() const; + bool IsDeletable() const; + bool IsRenamable() const; + + void SetVisible( bool b ) { bIsVisible = b; } + bool IsVisible() const { return bIsVisible; } + + void SetBackupGraphic( css::uno::Reference< css::graphic::XGraphic > const & graphic ) + { xBackupGraphic = graphic; } + + const css::uno::Reference< css::graphic::XGraphic >& GetBackupGraphic() const + { return xBackupGraphic; } + + sal_Int32 GetStyle() const { return nStyle; } + void SetStyle( sal_Int32 style ) { nStyle = style; } +}; + +class SvxMenuEntriesListBox +{ +protected: + std::unique_ptr m_xControl; + ScopedVclPtr m_xDropDown; + SvxConfigPage* m_pPage; + +public: + SvxMenuEntriesListBox(std::unique_ptr xControl, SvxConfigPage* pPage); + virtual ~SvxMenuEntriesListBox(); + + VirtualDevice& get_dropdown_image() const { return *m_xDropDown; } + + int get_selected_index() const { return m_xControl->get_selected_index(); } + OUString get_id(int nPos) const { return m_xControl->get_id(nPos); } + void remove(int nPos) { m_xControl->remove(nPos); } + int n_children() const { return m_xControl->n_children(); } + void set_text(int row, const OUString& rText, int col) { m_xControl->set_text(row, rText, col); } + OUString get_text(int row) { return m_xControl->get_text(row); } + void set_image(int row, const css::uno::Reference& rImage, int col) { m_xControl->set_image(row, rImage, col); } + void set_dropdown(int row, int col) { m_xControl->set_image(row, *m_xDropDown, col); } + void set_id(int row, const OUString& rId) { m_xControl->set_id(row, rId); } + void clear() { m_xControl->clear(); } //need frees ? + void set_toggle(int row, TriState eState, int col) { m_xControl->set_toggle(row, eState, col); } + void scroll_to_row(int pos) { m_xControl->scroll_to_row(pos); } + void select(int pos) { m_xControl->select(pos); } + + weld::TreeView& get_widget() { return *m_xControl; } + + void insert(int pos, const OUString& rId) + { + m_xControl->insert(nullptr, pos, nullptr, &rId, + nullptr, nullptr, nullptr, false, nullptr); + } + + DECL_LINK(KeyInputHdl, const KeyEvent&, bool); + + void CreateDropDown(); +}; + +class SvxConfigPageFunctionDropTarget : public DropTargetHelper +{ +private: + SvxConfigPage& m_rPage; + weld::TreeView& m_rTreeView; + + virtual sal_Int8 AcceptDrop( const AcceptDropEvent& rEvt ) override; + virtual sal_Int8 ExecuteDrop( const ExecuteDropEvent& rEvt ) override; + +public: + SvxConfigPageFunctionDropTarget(SvxConfigPage&rPage, weld::TreeView& rTreeView); +}; + +class SvxConfigPage : public SfxTabPage +{ +private: + + Timer m_aUpdateDataTimer; + bool bInitialised; + SaveInData* pCurrentSaveInData; + + DECL_LINK(SearchUpdateHdl, weld::Entry&, void); + +protected: + + /// the ResourceURL to select when opening the dialog + OUString m_aURLToSelect; + + css::uno::Reference< css::frame::XFrame > m_xFrame; + OUString m_aModuleId; + + // Left side of the dialog where command categories and the available + // commands in them are displayed as a searchable list + std::unique_ptr m_xCommandCategoryListBox; + std::unique_ptr m_xFunctions; + + std::unique_ptr m_xCategoryLabel; + std::unique_ptr m_xDescriptionFieldLb; + std::unique_ptr m_xDescriptionField; + std::unique_ptr m_xLeftFunctionLabel; + std::unique_ptr m_xSearchEdit; + std::unique_ptr m_xSearchLabel; + + + // Right side of the dialog where the contents of the selected + // menu or toolbar are displayed + std::unique_ptr m_xCustomizeLabel; + std::unique_ptr m_xTopLevelListBox; + // Used to add and remove toolbars/menus + std::unique_ptr m_xGearBtn; + std::unique_ptr m_xContentsListBox; + std::unique_ptr m_xDropTargetHelper; + + std::unique_ptr m_xMoveUpButton; + std::unique_ptr m_xMoveDownButton; + + std::unique_ptr m_xSaveInListBox; + + std::unique_ptr m_xInsertBtn; + std::unique_ptr m_xModifyBtn; + // Used to reset the selected toolbar/menu/context menu + std::unique_ptr m_xResetBtn; + + // Middle buttons + std::unique_ptr m_xAddCommandButton; + std::unique_ptr m_xRemoveCommandButton; + + OUString m_sAppName; + OUString m_sFileName; + + SvxConfigPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet&); + + DECL_LINK(MoveHdl, weld::Button&, void); + DECL_LINK(SelectFunctionHdl, weld::TreeView&, void); + DECL_LINK(FunctionDoubleClickHdl, weld::TreeView&, bool); + DECL_LINK(SelectSaveInLocation, weld::ComboBox&, void); + DECL_LINK(SelectElementHdl, weld::ComboBox&, void); + DECL_LINK(ImplUpdateDataHdl, Timer*, void); + DECL_LINK(FocusOut_Impl, weld::Widget&, void); + + virtual SaveInData* CreateSaveInData( + const css::uno::Reference< css::ui::XUIConfigurationManager >&, + const css::uno::Reference< css::ui::XUIConfigurationManager >&, + const OUString& aModuleId, + bool docConfig ) = 0; + + virtual void Init() = 0; + virtual void UpdateButtonStates() = 0; + virtual short QueryReset() = 0; + + virtual void SelectElement() = 0; + + int AppendEntry(SvxConfigEntry* pNewEntryData, + int nTarget); + + void AddSubMenusToUI( const OUString& rBaseTitle, + SvxConfigEntry const * pParentData ); + + void InsertEntryIntoUI(SvxConfigEntry* pNewEntryData, + weld::TreeView& rTreeView, int nPos, + int nStartCol); + void InsertEntryIntoUI(SvxConfigEntry* pNewEntryData, + weld::TreeView& rTreeView, weld::TreeIter& rIter, + int nStartCol); + + void InsertEntryIntoNotebookbarTabUI(const OUString& sClassId, const OUString& sUIItemId, + const OUString& sUIItemCommand, + weld::TreeView& rTreeView, weld::TreeIter& rIter, + int nStartCol); + + SvxEntries* FindParentForChild( SvxEntries* pParentEntries, + SvxConfigEntry* pChildData ); + + void ReloadTopLevelListBox( SvxConfigEntry const * pSelection = nullptr ); + +public: + + virtual ~SvxConfigPage() override; + + static bool CanConfig( const OUString& rModuleId ); + + SaveInData* GetSaveInData() { return pCurrentSaveInData; } + const OUString& GetAppName() const { return m_sAppName; } + const OUString& GetFileName() const { return m_sFileName; } + + int AddFunction(int nTarget, + bool bAllowDuplicates); + + virtual void MoveEntry( bool bMoveUp ); + + bool MoveEntryData(int SourceEntry, int nTargetEntry); + + bool FillItemSet( SfxItemSet* ) override; + void Reset( const SfxItemSet* ) override; + + virtual void DeleteSelectedContent() = 0; + virtual void DeleteSelectedTopLevel() = 0; + + virtual void ListModified() {} + + SvxConfigEntry* GetTopLevelSelection() + { + return reinterpret_cast(m_xTopLevelListBox->get_active_id().toInt64()); + } + + /** identifies the module in the given frame. If the frame is , a default + frame will be determined beforehand. + + If the given frame is , a default frame will be used: The method the active + frame of the desktop, then the current frame. If both are , + the SfxViewFrame::Current's XFrame is used. If this is , too, an empty string is returned. + + If the given frame is not , or a default frame could be successfully determined, then + the ModuleManager is asked for the module ID of the component in the frame. + */ + static OUString + GetFrameWithDefaultAndIdentify( css::uno::Reference< css::frame::XFrame >& _inout_rxFrame ); + + OUString GetScriptURL() const; + OUString GetSelectedDisplayName() const; +}; + +class SvxMainMenuOrganizerDialog : public weld::GenericDialogController +{ + std::unique_ptr mpEntries; + OUString m_sNewMenuEntryId; + + std::unique_ptr m_xMenuBox; + std::unique_ptr m_xMenuNameEdit; + std::unique_ptr m_xMenuListBox; + std::unique_ptr m_xMoveUpButton; + std::unique_ptr m_xMoveDownButton; + + void UpdateButtonStates(); + + DECL_LINK(MoveHdl, weld::Button&, void); + DECL_LINK(ModifyHdl, weld::Entry&, void); + DECL_LINK(SelectHdl, weld::TreeView&, void); + +public: + SvxMainMenuOrganizerDialog( + weld::Window*, SvxEntries*, + SvxConfigEntry const *, bool bCreateMenu); + virtual ~SvxMainMenuOrganizerDialog() override; + + std::unique_ptr ReleaseEntries() { return std::move(mpEntries);} + SvxConfigEntry* GetSelectedEntry(); +}; + +class ToolbarSaveInData : public SaveInData +{ +private: + + std::unique_ptr pRootEntry; + OUString m_aDescriptorContainer; + + css::uno::Reference + < css::container::XNameAccess > m_xPersistentWindowState; + + void LoadToolbar( + const css::uno::Reference< css::container::XIndexAccess >& xToolBarSettings, + SvxConfigEntry const * pParentData ); + + void ApplyToolbar( + css::uno::Reference< css::container::XIndexContainer > const & rNewToolbarBar, + css::uno::Reference< css::lang::XSingleComponentFactory >& rFactory, + SvxConfigEntry const *pToolbar ); + +public: + + ToolbarSaveInData( + const css::uno::Reference< css::ui::XUIConfigurationManager >&, + const css::uno::Reference< css::ui::XUIConfigurationManager >&, + const OUString& aModuleId, + bool docConfig ); + + virtual ~ToolbarSaveInData() override; + + void CreateToolbar( SvxConfigEntry* pToolbar ); + void RestoreToolbar( SvxConfigEntry* pToolbar ); + void RemoveToolbar( SvxConfigEntry* pToolbar ); + void ApplyToolbar( SvxConfigEntry* pToolbar ); + + OUString GetSystemUIName( const OUString& rResourceURL ); + + sal_Int32 GetSystemStyle( const OUString& rResourceURL ); + + void SetSystemStyle( const OUString& rResourceURL, sal_Int32 nStyle ); + + void SetSystemStyle( + const css::uno::Reference< css::frame::XFrame >& xFrame, + const OUString& rResourceURL, sal_Int32 nStyle ); + + SvxEntries* GetEntries() override; + void SetEntries( std::unique_ptr ) override; + bool HasSettings() override; + bool HasURL( const OUString& rURL ) override; + void Reset() override; + bool Apply() override; +}; + +class SvxNewToolbarDialog : public weld::GenericDialogController +{ +private: + std::unique_ptr m_xEdtName; + std::unique_ptr m_xBtnOK; +public: + std::unique_ptr m_xSaveInListBox; + + SvxNewToolbarDialog(weld::Window* pWindow, const OUString& rName); + virtual ~SvxNewToolbarDialog() override; + + OUString GetName() const + { + return m_xEdtName->get_text(); + } +}; + +class SvxIconSelectorDialog : public weld::GenericDialogController +{ +private: + sal_Int32 m_nExpectedSize; + + css::uno::Reference< + css::ui::XImageManager > m_xImageManager; + + css::uno::Reference< + css::ui::XImageManager > m_xParentImageManager; + + css::uno::Reference< + css::ui::XImageManager > m_xImportedImageManager; + + css::uno::Reference< + css::graphic::XGraphicProvider > m_xGraphProvider; + + std::vector> m_aGraphics; + + std::unique_ptr m_xTbSymbol; + std::unique_ptr m_xTbSymbolWin; + std::unique_ptr m_xFtNote; + std::unique_ptr m_xBtnImport; + std::unique_ptr m_xBtnDelete; + + bool ReplaceGraphicItem( const OUString& aURL ); + + bool ImportGraphic( const OUString& aURL ); + + void ImportGraphics( const css::uno::Sequence< OUString >& aURLs ); + +public: + + SvxIconSelectorDialog( + weld::Window *pWindow, + const css::uno::Reference< css::ui::XImageManager >& rXImageManager, + const css::uno::Reference< css::ui::XImageManager >& rXParentImageManager); + + virtual ~SvxIconSelectorDialog() override; + + css::uno::Reference< css::graphic::XGraphic > + GetSelectedIcon(); + + DECL_LINK(SelectHdl, ValueSet*, void); + DECL_LINK(ImportHdl, weld::Button&, void); + DECL_LINK(DeleteHdl, weld::Button&, void); +}; + +//added for issue83555 +class SvxIconChangeDialog : public weld::MessageDialogController +{ +private: + std::unique_ptr m_xLineEditDescription; +public: + SvxIconChangeDialog(weld::Window *pWindow, const OUString& rMessage); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/cfgutil.hxx b/cui/source/inc/cfgutil.hxx new file mode 100644 index 000000000..944ab68e8 --- /dev/null +++ b/cui/source/inc/cfgutil.hxx @@ -0,0 +1,269 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_CFGUTIL_HXX +#define INCLUDED_CUI_SOURCE_INC_CFGUTIL_HXX + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +class Button; +class SaveInData; +class SfxMacroInfoItem; + +struct SfxStyleInfo_Impl +{ + OUString sFamily; + OUString sStyle; + OUString sCommand; + OUString sLabel; + + SfxStyleInfo_Impl() + {} + + SfxStyleInfo_Impl(const SfxStyleInfo_Impl& rCopy) + { + sFamily = rCopy.sFamily; + sStyle = rCopy.sStyle; + sCommand = rCopy.sCommand; + sLabel = rCopy.sLabel; + } +}; + +struct SfxStylesInfo_Impl +{ +private: + OUString m_aModuleName; + css::uno::Reference< css::frame::XModel > m_xDoc; + +public: + + SfxStylesInfo_Impl(); + void init(const OUString& rModuleName, const css::uno::Reference< css::frame::XModel >& xModel); + + static bool parseStyleCommand(SfxStyleInfo_Impl& aStyle); + void getLabel4Style(SfxStyleInfo_Impl& aStyle); + + std::vector< SfxStyleInfo_Impl > getStyleFamilies() const; + std::vector< SfxStyleInfo_Impl > getStyles(const OUString& sFamily); + + static OUString generateCommand(const OUString& sFamily, const OUString& sStyle); +}; + +enum class SfxCfgKind +{ + GROUP_FUNCTION = 1, + FUNCTION_SLOT = 2, + GROUP_SCRIPTCONTAINER = 3, + FUNCTION_SCRIPT = 4, + GROUP_STYLES = 5, + GROUP_ALLFUNCTIONS = 6 +}; + +struct SfxGroupInfo_Impl +{ + SfxCfgKind nKind; + sal_uInt16 nUniqueID; + void* pObject; + OUString sCommand; + OUString sLabel; + OUString sHelpText; + OUString sTooltip; + + SfxGroupInfo_Impl( SfxCfgKind n, sal_uInt16 nr, void* pObj = nullptr ) : + nKind( n ), nUniqueID( nr ), pObject( pObj ) {} +}; + +typedef std::vector > SfxGroupInfoArr_Impl; + +class CuiConfigFunctionListBox +{ + friend class CuiConfigGroupListBox; + SfxGroupInfoArr_Impl aArr; + + std::unique_ptr m_xTreeView; + std::unique_ptr m_xScratchIter; + +public: + CuiConfigFunctionListBox(std::unique_ptr xTreeView); + void set_sensitive(bool bSensitive) { m_xTreeView->set_sensitive(bSensitive); } + void connect_changed(const Link& rLink) { m_xTreeView->connect_changed(rLink); } + void connect_row_activated(const Link& rLink) { m_xTreeView->connect_row_activated(rLink); } + void freeze() { m_xTreeView->freeze(); } + void thaw() { m_xTreeView->thaw(); } + void append(const OUString& rId, const OUString& rStr, const weld::TreeIter* pParent = nullptr) + { + m_xTreeView->insert(pParent, -1, &rStr, &rId, nullptr, nullptr, nullptr, false, nullptr); + } + std::unique_ptr tree_append(const OUString& rId, const OUString& rStr, const weld::TreeIter* pParent = nullptr) + { + std::unique_ptr xIter(m_xTreeView->make_iterator()); + m_xTreeView->insert(pParent, -1, &rStr, &rId, nullptr, nullptr, nullptr, false, xIter.get()); + return xIter; + } + void append(const OUString& rId, const OUString& rStr, const OUString& rImage, const weld::TreeIter* pParent = nullptr) + { + m_xTreeView->insert(pParent, -1, &rStr, &rId, nullptr, nullptr, &rImage, false, nullptr); + } + void append(const OUString& rId, const OUString& rStr, const css::uno::Reference& rImage, const weld::TreeIter* pParent = nullptr) + { + m_xTreeView->insert(pParent, -1, &rStr, &rId, nullptr, nullptr, nullptr, false, m_xScratchIter.get()); + m_xTreeView->set_image(*m_xScratchIter, rImage, -1); + } + void remove(int nPos) { m_xTreeView->remove(nPos); } + void scroll_to_row(int pos) { m_xTreeView->scroll_to_row(pos); } + void remove(const weld::TreeIter& rIter) { m_xTreeView->remove(rIter); } + void expand_row(const weld::TreeIter& rIter) { m_xTreeView->expand_row(rIter); } + int n_children() const { return m_xTreeView->n_children(); } + std::unique_ptr make_iterator(const weld::TreeIter* pOrig = nullptr) const { return m_xTreeView->make_iterator(pOrig); } + bool get_iter_first(weld::TreeIter& rIter) const { return m_xTreeView->get_iter_first(rIter); } + // set iter to point to next node, depth first, then sibling + bool iter_next(weld::TreeIter& rIter) const { return m_xTreeView->iter_next(rIter); } + bool iter_next_sibling(weld::TreeIter& rIter) const { return m_xTreeView->iter_next_sibling(rIter); } + bool iter_has_child(const weld::TreeIter& rIter) const { return m_xTreeView->iter_has_child(rIter); } + OUString get_text(const weld::TreeIter& rIter) const { return m_xTreeView->get_text(rIter); } + OUString get_text(int nPos) const { return m_xTreeView->get_text(nPos); } + OUString get_id(const weld::TreeIter& rIter) const { return m_xTreeView->get_id(rIter); } + OUString get_id(int nPos) const { return m_xTreeView->get_id(nPos); } + bool get_selected(weld::TreeIter* pIter) const { return m_xTreeView->get_selected(pIter); } + OUString get_selected_text() const + { + if (!m_xTreeView->get_selected(m_xScratchIter.get())) + return OUString(); + return m_xTreeView->get_text(*m_xScratchIter); + } + OUString get_selected_id() const + { + if (!m_xTreeView->get_selected(m_xScratchIter.get())) + return OUString(); + return m_xTreeView->get_id(*m_xScratchIter); + } + int get_selected_index() const { return m_xTreeView->get_selected_index(); } + void select(const weld::TreeIter& rIter) { m_xTreeView->select(rIter); } + void select(int pos) { m_xTreeView->select(pos); } + void set_size_request(int nWidth, int nHeight) { m_xTreeView->set_size_request(nWidth, nHeight); } + Size get_size_request() const { return m_xTreeView->get_size_request(); } + weld::TreeView& get_widget() { return *m_xTreeView; } + + ~CuiConfigFunctionListBox(); + + void ClearAll(); + OUString GetSelectedScriptURI() const; + OUString GetHelpText( bool bConsiderParent = true ); + OUString GetCurCommand() const; + OUString GetCurLabel() const; + + DECL_LINK(QueryTooltip, const weld::TreeIter& rIter, OUString); +}; + +struct SvxConfigGroupBoxResource_Impl; +class CuiConfigGroupListBox +{ + std::unique_ptr xImp; + CuiConfigFunctionListBox* m_pFunctionListBox; + SfxGroupInfoArr_Impl aArr; + OUString m_sModuleLongName; + css::uno::Reference< css::uno::XComponentContext > m_xContext; + css::uno::Reference< css::frame::XFrame > m_xFrame; + css::uno::Reference< css::container::XNameAccess > m_xGlobalCategoryInfo; + css::uno::Reference< css::container::XNameAccess > m_xModuleCategoryInfo; + css::uno::Reference< css::container::XNameAccess > m_xUICmdDescription; + SfxStylesInfo_Impl* m_pStylesInfo; + std::unique_ptr m_xTreeView; + + static OUString GetImage( + const css::uno::Reference< css::script::browse::XBrowseNode >& node, + css::uno::Reference< css::uno::XComponentContext > const & xCtx, + bool bIsRootNode); + + static css::uno::Reference< css::uno::XInterface > getDocumentModel( + css::uno::Reference< css::uno::XComponentContext > const & xCtx, + OUString const & docName); + + void InitModule(); + void FillScriptList(const css::uno::Reference< css::script::browse::XBrowseNode >& xRootNode, + const weld::TreeIter* pParentEntry, bool bCheapChildrenOnDemand); + void FillFunctionsList(const css::uno::Sequence< css::frame::DispatchInformation >& xCommands); + OUString MapCommand2UIName(const OUString& sCommand); + + DECL_LINK(ExpandingHdl, const weld::TreeIter&, bool); + +public: + CuiConfigGroupListBox(std::unique_ptr xTreeView); + void set_sensitive(bool bSensitive) { m_xTreeView->set_sensitive(bSensitive); } + void connect_changed(const Link& rLink) { m_xTreeView->connect_changed(rLink); } + void set_size_request(int nWidth, int nHeight) { m_xTreeView->set_size_request(nWidth, nHeight); } + weld::TreeView& get_widget() { return *m_xTreeView; } + ~CuiConfigGroupListBox(); + void ClearAll(); + + void Init(const css::uno::Reference< css::uno::XComponentContext >& xContext, + const css::uno::Reference< css::frame::XFrame >& xFrame, + const OUString& sModuleLongName, + bool bEventMode); + void SetFunctionListBox( CuiConfigFunctionListBox *pBox ) + { m_pFunctionListBox = pBox; } + void GroupSelected(); + void SelectMacro(const SfxMacroInfoItem*); + void SelectMacro(const OUString&, const OUString&); + void SetStylesInfo(SfxStylesInfo_Impl* pStyles); +}; + +class SvxScriptSelectorDialog : public weld::GenericDialogController +{ + OUString m_sDefaultDesc; + SfxStylesInfo_Impl m_aStylesInfo; + + std::unique_ptr m_xDialogDescription; + std::unique_ptr m_xCategories; + std::unique_ptr m_xCommands; + std::unique_ptr m_xLibraryFT; + std::unique_ptr m_xCategoryFT; + std::unique_ptr m_xMacronameFT; + std::unique_ptr m_xCommandsFT; + std::unique_ptr m_xOKButton; + std::unique_ptr m_xCancelButton; + std::unique_ptr m_xDescriptionText; + + DECL_LINK(ClickHdl, weld::Button&, void); + DECL_LINK(SelectHdl, weld::TreeView&, void); + DECL_LINK(FunctionDoubleClickHdl, weld::TreeView&, bool); + + void UpdateUI(); + +public: + SvxScriptSelectorDialog(weld::Window* pParent, + const css::uno::Reference< css::frame::XFrame >& xFrame); + virtual ~SvxScriptSelectorDialog() override; + + OUString GetScriptURL() const; + void SetRunLabel(); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/chardlg.hxx b/cui/source/inc/chardlg.hxx new file mode 100644 index 000000000..e81284cc6 --- /dev/null +++ b/cui/source/inc/chardlg.hxx @@ -0,0 +1,343 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_CHARDLG_HXX +#define INCLUDED_CUI_SOURCE_INC_CHARDLG_HXX + +#include +#include +#include +#include +#include +#include +#include + +// forward --------------------------------------------------------------- + +class SvxFontListItem; +class FontList; + +class SvxCharBasePage : public SfxTabPage +{ +protected: + SvxFontPrevWindow m_aPreviewWin; + std::unique_ptr m_xPreviewWin; + + bool m_bPreviewBackgroundToCharacter; + + SvxCharBasePage(weld::Container* pPage, weld::DialogController* pController, const OUString& rUIXMLDescription, const OString& rID, const SfxItemSet& rAttrSet); + + void SetPrevFontWidthScale( const SfxItemSet& rSet ); + void SetPrevFontEscapement( sal_uInt8 nProp, sal_uInt8 nEscProp, short nEsc ); + + inline SvxFont& GetPreviewFont(); + inline SvxFont& GetPreviewCJKFont(); + inline SvxFont& GetPreviewCTLFont(); + +public: + virtual ~SvxCharBasePage() override; + + virtual void ActivatePage( const SfxItemSet& rSet ) override; +}; + +// class SvxCharNamePage ------------------------------------------------- + +struct SvxCharNamePage_Impl; + +class SvxCharNamePage : public SvxCharBasePage +{ +private: + static const sal_uInt16 pNameRanges[]; + + std::unique_ptr m_pImpl; + + std::unique_ptr m_xWestFrame; + std::unique_ptr m_xWestFontNameFT; + std::unique_ptr m_xWestFontNameLB; + std::unique_ptr m_xWestFontStyleFT; + std::unique_ptr m_xWestFontStyleLB; + std::unique_ptr m_xWestFontSizeFT; + std::unique_ptr m_xWestFontSizeLB; + std::unique_ptr m_xWestFontLanguageFT; + std::unique_ptr m_xWestFontLanguageLB; + std::unique_ptr m_xWestFontTypeFT; + std::unique_ptr m_xWestFontFeaturesButton; + + std::unique_ptr m_xEastFrame; + std::unique_ptr m_xEastFontNameFT; + std::unique_ptr m_xEastFontNameLB; + std::unique_ptr m_xEastFontStyleFT; + std::unique_ptr m_xEastFontStyleLB; + std::unique_ptr m_xEastFontSizeFT; + std::unique_ptr m_xEastFontSizeLB; + std::unique_ptr m_xEastFontLanguageFT; + std::unique_ptr m_xEastFontLanguageLB; + std::unique_ptr m_xEastFontTypeFT; + std::unique_ptr m_xEastFontFeaturesButton; + + std::unique_ptr m_xCTLFrame; + std::unique_ptr m_xCTLFontNameFT; + std::unique_ptr m_xCTLFontNameLB; + std::unique_ptr m_xCTLFontStyleFT; + std::unique_ptr m_xCTLFontStyleLB; + std::unique_ptr m_xCTLFontSizeFT; + std::unique_ptr m_xCTLFontSizeLB; + std::unique_ptr m_xCTLFontLanguageFT; + std::unique_ptr m_xCTLFontLanguageLB; + std::unique_ptr m_xCTLFontTypeFT; + std::unique_ptr m_xCTLFontFeaturesButton; + + void Initialize(); + const FontList* GetFontList() const; + void UpdatePreview_Impl(); + void FillStyleBox_Impl(const weld::Widget& rBox); + void FillSizeBox_Impl(const weld::Widget& rBox); + + enum LanguageGroup + { + /** Language for western text. + */ + Western = 0, + + /** Language for asian text. + */ + Asian, + + /** Language for ctl text. + */ + Ctl + }; + + void Reset_Impl( const SfxItemSet& rSet, LanguageGroup eLangGrp ); + bool FillItemSet_Impl( SfxItemSet& rSet, LanguageGroup eLangGrp ); + + DECL_LINK(UpdateHdl_Impl, Timer *, void ); + DECL_LINK(FontModifyComboBoxHdl_Impl, weld::ComboBox&, void); + DECL_LINK(FontFeatureButtonClicked, weld::Button&, void); + + void FontModifyHdl_Impl(const weld::Widget&); + +public: + virtual void ActivatePage( const SfxItemSet& rSet ) override; + virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override; + +public: + SvxCharNamePage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet ); + virtual ~SvxCharNamePage() override; + + static const sal_uInt16* GetRanges() { return pNameRanges; } + + virtual void Reset( const SfxItemSet* rSet ) override; + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void ChangesApplied() override; + + void SetFontList( const SvxFontListItem& rItem ); + void EnableRelativeMode(); + void EnableSearchMode(); + + void DisableControls( sal_uInt16 nDisable ); + virtual void PageCreated(const SfxAllItemSet& aSet) override; +}; + +// class SvxCharEffectsPage ---------------------------------------------- + +class SvxCharEffectsPage : public SvxCharBasePage +{ +private: + static const sal_uInt16 pEffectsRanges[]; + bool m_bOrigFontColor; + bool m_bNewFontColor; + bool m_bEnableNoneFontColor; + Color m_aOrigFontColor; + sal_uInt16 m_nHtmlMode; + bool m_bUnderlineColorDisabled; + + weld::TriStateEnabled m_aOutlineState; + weld::TriStateEnabled m_aShadowState; + weld::TriStateEnabled m_aHiddenState; + weld::TriStateEnabled m_aIndividualWordsState; + + std::unique_ptr m_xFontColorFT; + std::unique_ptr m_xFontColorLB; + std::unique_ptr m_xFontTransparencyFT; + std::unique_ptr m_xFontTransparencyMtr; + std::unique_ptr m_xEffectsFT; + std::unique_ptr m_xEffectsLB; + std::unique_ptr m_xReliefFT; + std::unique_ptr m_xReliefLB; + std::unique_ptr m_xOutlineBtn; + std::unique_ptr m_xShadowBtn; + std::unique_ptr m_xHiddenBtn; + std::unique_ptr m_xOverlineLB; + std::unique_ptr m_xOverlineColorFT; + std::unique_ptr m_xOverlineColorLB; + std::unique_ptr m_xStrikeoutLB; + std::unique_ptr m_xUnderlineLB; + std::unique_ptr m_xUnderlineColorFT; + std::unique_ptr m_xUnderlineColorLB; + std::unique_ptr m_xIndividualWordsBtn; + std::unique_ptr m_xEmphasisFT; + std::unique_ptr m_xEmphasisLB; + std::unique_ptr m_xPositionFT; + std::unique_ptr m_xPositionLB; + std::unique_ptr m_xA11yWarningFT; + + void Initialize(); + void UpdatePreview_Impl(); + void SetCaseMap_Impl( SvxCaseMap eCaseMap ); + void ResetColor_Impl( const SfxItemSet& rSet ); + bool FillItemSetColor_Impl( SfxItemSet& rSet ); + Color GetPreviewFontColor(const Color& rColor) const; + void EnableNoneFontColor(); + + void SelectHdl_Impl(const weld::ComboBox*); + DECL_LINK(SelectListBoxHdl_Impl, weld::ComboBox&, void); + DECL_LINK(OutlineBtnClickHdl, weld::ToggleButton&, void); + DECL_LINK(ShadowBtnClickHdl, weld::ToggleButton&, void); + DECL_LINK(HiddenBtnClickHdl, weld::ToggleButton&, void); + DECL_LINK(CbClickHdl_Impl, weld::ToggleButton&, void); + DECL_LINK(ColorBoxSelectHdl_Impl, ColorListBox&, void); + DECL_LINK(ModifyFontTransparencyHdl_Impl, weld::MetricSpinButton&, void); + +public: + SvxCharEffectsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet ); + virtual ~SvxCharEffectsPage() override; + + virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override; + +public: + static const sal_uInt16* GetRanges() { return pEffectsRanges; } + + virtual void Reset( const SfxItemSet* rSet ) override; + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void ChangesApplied() override; + + void DisableControls( sal_uInt16 nDisable ); + virtual void PageCreated(const SfxAllItemSet& aSet) override; +}; + +// class SvxCharPositionPage --------------------------------------------- +class SvxCharPositionPage : public SvxCharBasePage +{ + static const sal_uInt16 pPositionRanges[]; + +private: + short m_nSuperEsc; + short m_nSubEsc; + + sal_uInt16 m_nScaleWidthItemSetVal; + sal_uInt16 m_nScaleWidthInitialVal; + + sal_uInt8 m_nSuperProp; + sal_uInt8 m_nSubProp; + + std::unique_ptr m_xHighPosBtn; + std::unique_ptr m_xNormalPosBtn; + std::unique_ptr m_xLowPosBtn; + std::unique_ptr m_xHighLowFT; + std::unique_ptr m_xHighLowMF; + std::unique_ptr m_xHighLowRB; + std::unique_ptr m_xFontSizeFT; + std::unique_ptr m_xFontSizeMF; + + std::unique_ptr m_xRotationContainer; + + std::unique_ptr m_xScalingFT; + std::unique_ptr m_xScalingAndRotationFT; + std::unique_ptr m_x0degRB; + std::unique_ptr m_x90degRB; + std::unique_ptr m_x270degRB; + std::unique_ptr m_xFitToLineCB; + + std::unique_ptr m_xScaleWidthMF; + + std::unique_ptr m_xKerningMF; + std::unique_ptr m_xPairKerningBtn; + + void Initialize(); + void UpdatePreview_Impl( sal_uInt8 nProp, sal_uInt8 nEscProp, short nEsc ); + void SetEscapement_Impl( SvxEscapement nEsc ); + + DECL_LINK(PositionHdl_Impl, weld::ToggleButton&, void); + DECL_LINK(RotationHdl_Impl, weld::ToggleButton&, void); + DECL_LINK(AutoPositionHdl_Impl, weld::ToggleButton&, void); + DECL_LINK(FitToLineHdl_Impl, weld::ToggleButton&, void); + DECL_LINK(KerningModifyHdl_Impl, weld::MetricSpinButton&, void); + DECL_LINK(ValueChangedHdl_Impl, weld::MetricSpinButton&, void); + DECL_LINK(ScaleWidthModifyHdl_Impl, weld::MetricSpinButton&, void); + void FontModifyHdl_Impl(); + +public: + SvxCharPositionPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet ); + virtual ~SvxCharPositionPage() override; + + virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override; + +public: + static const sal_uInt16* GetRanges() { return pPositionRanges; } + + virtual void Reset( const SfxItemSet* rSet ) override; + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void ChangesApplied() override; + virtual void FillUserData() override; + virtual void PageCreated(const SfxAllItemSet& aSet) override; +}; + +// class SvxCharTwoLinesPage --------------------------------------------- + +class SvxCharTwoLinesPage : public SvxCharBasePage +{ +private: + static const sal_uInt16 pTwoLinesRanges[]; + sal_uInt16 m_nStartBracketPosition; + sal_uInt16 m_nEndBracketPosition; + + std::unique_ptr m_xTwoLinesBtn; + std::unique_ptr m_xEnclosingFrame; + std::unique_ptr m_xStartBracketLB; + std::unique_ptr m_xEndBracketLB; + + void UpdatePreview_Impl(); + void Initialize(); + void SelectCharacter(weld::TreeView* pBox); + void SetBracket(sal_Unicode cBracket, bool bStart); + + DECL_LINK(TwoLinesHdl_Impl, weld::ToggleButton&, void); + DECL_LINK(CharacterMapHdl_Impl, weld::TreeView&, void); + +public: + SvxCharTwoLinesPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet ); + virtual ~SvxCharTwoLinesPage() override; + + virtual void ActivatePage( const SfxItemSet& rSet ) override; + virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override; + + static const sal_uInt16* GetRanges() { return pTwoLinesRanges; } + + virtual void Reset( const SfxItemSet* rSet ) override; + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void PageCreated(const SfxAllItemSet& aSet) override; +}; + +#endif // INCLUDED_CUI_SOURCE_INC_CHARDLG_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/colorpicker.hxx b/cui/source/inc/colorpicker.hxx new file mode 100644 index 000000000..7c05ebabc --- /dev/null +++ b/cui/source/inc/colorpicker.hxx @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_CUI_SOURCE_INC_COLORPICKER_HXX +#define INCLUDED_CUI_SOURCE_INC_COLORPICKER_HXX + +#include + +#include +#include +#include + +namespace com::sun::star::uno { + class XComponentContext; + class XInterface; +} + +namespace cui { + +OUString ColorPicker_getImplementationName(); + +css::uno::Reference ColorPicker_createInstance( + css::uno::Reference const &); + +/// @throws css::uno::RuntimeException +css::uno::Sequence ColorPicker_getSupportedServiceNames(); +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/connect.hxx b/cui/source/inc/connect.hxx new file mode 100644 index 000000000..1b4185147 --- /dev/null +++ b/cui/source/inc/connect.hxx @@ -0,0 +1,86 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_CONNECT_HXX +#define INCLUDED_CUI_SOURCE_INC_CONNECT_HXX + +#include +#include +#include +#include +#include + +class SdrView; + +/// Dialog for changing connectors. +class SvxConnectionPage : public SfxTabPage +{ +private: + static const sal_uInt16 pRanges[]; + const SfxItemSet& rOutAttrs; + SfxItemSet aAttrSet; + const SdrView* pView; + MapUnit eUnit; + + SvxXConnectionPreview m_aCtlPreview; + std::unique_ptr m_xLbType; + std::unique_ptr m_xFtLine1; + std::unique_ptr m_xMtrFldLine1; + std::unique_ptr m_xFtLine2; + std::unique_ptr m_xMtrFldLine2; + std::unique_ptr m_xFtLine3; + std::unique_ptr m_xMtrFldLine3; + std::unique_ptr m_xMtrFldHorz1; + std::unique_ptr m_xMtrFldVert1; + std::unique_ptr m_xMtrFldHorz2; + std::unique_ptr m_xMtrFldVert2; + std::unique_ptr m_xCtlPreview; + + void FillTypeLB(); + + DECL_LINK(ChangeAttrEditHdl_Impl, weld::MetricSpinButton&, void); + DECL_LINK(ChangeAttrListBoxHdl_Impl, weld::ComboBox&, void); + +public: + + SvxConnectionPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + virtual ~SvxConnectionPage() override; + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* ); + static const sal_uInt16* GetRanges() { return pRanges; } + + virtual bool FillItemSet( SfxItemSet* ) override; + virtual void Reset( const SfxItemSet * ) override; + + void Construct(); + void SetView( const SdrView* pSdrView ) { pView = pSdrView; } + virtual void PageCreated(const SfxAllItemSet& aSet) override; +}; + +/* Derived from SfxSingleTabDialogController, in order to be informed about + virtual methods by the control. */ +class SvxConnectionDialog : public SfxSingleTabDialogController +{ +public: + SvxConnectionDialog(weld::Window* pParent, const SfxItemSet& rAttr, + const SdrView* pView); +}; + +#endif // INCLUDED_CUI_SOURCE_INC_CONNECT_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/cuifmsearch.hxx b/cui/source/inc/cuifmsearch.hxx new file mode 100644 index 000000000..42183e627 --- /dev/null +++ b/cui/source/inc/cuifmsearch.hxx @@ -0,0 +1,173 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_CUI_SOURCE_INC_CUIFMSEARCH_HXX +#define INCLUDED_CUI_SOURCE_INC_CUIFMSEARCH_HXX + +#include + +#include +#include +#include +#include + +namespace svxform { + class FmSearchConfigItem; +} + +struct FmSearchProgress; + +class FmSearchEngine; + +/// Dialog for searching in Forms/Tables +class FmSearchDialog final : public weld::GenericDialogController +{ + friend class FmSearchEngine; + + OUString m_sSearch; + OUString m_sCancel; + + Link m_lnkFoundHandler; ///< Handler for "found" + Link m_lnkCanceledNotFoundHdl; ///< Handler for Positioning the Cursors + + Link m_lnkContextSupplier; ///< for search in contexts + + /// memorize the currently selected field for every context + std::vector m_arrContextFields; + + std::unique_ptr m_pSearchEngine; + + // see EnableSearchUI + std::unique_ptr<::svxform::FmSearchConfigItem> m_pConfig; + + // my all Controls + std::unique_ptr m_prbSearchForText; + std::unique_ptr m_prbSearchForNull; + std::unique_ptr m_prbSearchForNotNull; + std::unique_ptr m_pcmbSearchText; + std::unique_ptr m_pftForm; + std::unique_ptr m_plbForm; + std::unique_ptr m_prbAllFields; + std::unique_ptr m_prbSingleField; + std::unique_ptr m_plbField; + std::unique_ptr m_pftPosition; + std::unique_ptr m_plbPosition; + std::unique_ptr m_pcbUseFormat; + std::unique_ptr m_pcbCase; + std::unique_ptr m_pcbBackwards; + std::unique_ptr m_pcbStartOver; + std::unique_ptr m_pcbWildCard; + std::unique_ptr m_pcbRegular; + std::unique_ptr m_pcbApprox; + std::unique_ptr m_ppbApproxSettings; + std::unique_ptr m_pHalfFullFormsCJK; + std::unique_ptr m_pSoundsLikeCJK; + std::unique_ptr m_pSoundsLikeCJKSettings; + std::unique_ptr m_pftRecord; + std::unique_ptr m_pftHint; + std::unique_ptr m_pbSearchAgain; + std::unique_ptr m_pbClose; + +public: + /** This can search in different sets of fields. There is a number of contexts; their names are in strContexts (separated + by ';'), the user can choose one of them. + When the user chooses a context, lnkContextSupplier is called, it gets a pointer on a FmSearchContext-structure, + that has to be filled. + The following counts for the search : + a) in case of formatted search the iterator itself is used (like in the first constructor) + b) in case of formatted search NOT the FormatKey at the fields of the iterator is used, but the respective TextComponent + is asked (that's why the original iterator is used; by its move the controls behind the TextComponent-interface are + updated hopefully) + c) in case of not-formatted search a clone of the iterator is used (because the TextComponent-interfaces don't need to + be asked) + (of course needed : the string number i in strUsedFields of a context must correspond with the interface number i in the + arrFields of the context) + */ + FmSearchDialog(weld::Window* pParent, const OUString& strInitialText, const std::vector< OUString >& _rContexts, sal_Int16 nInitialContext, + const Link& lnkContextSupplier); + + virtual short run() override; + + virtual ~FmSearchDialog() override; + + /** The found-handler gets in the 'found'-case a pointer on a FmFoundRecordInformation-structure + (which is only valid in the handler; so if one needs to memorize the data, don't copy the pointer but + the structure). + This handler MUST be set. + Furthermore, it should be considered, that during the handler the search-dialog is still modal. + */ + void SetFoundHandler(const Link& lnk) { m_lnkFoundHandler = lnk; } + /** + If the search has been cancelled or has been finished without success, the current data set is always displayed in the + search dialog. This handler exists to make this synchronous with the possible display of the caller (it does not + necessarily need to be set). + The pointer that is passed to the handler points to a FmFoundRecordInformation-structure, for which aPosition and + possibly (in a search with contexts) nContext are valid. + */ + void SetCanceledNotFoundHdl(const Link& lnk) { m_lnkCanceledNotFoundHdl = lnk; } + + inline void SetActiveField(const OUString& strField); + +private: + void Init(const OUString& strVisibleFields, const OUString& strInitialText); + // only to be used out of the constructors + + void OnFound(const css::uno::Any& aCursorPos, sal_Int16 nFieldPos); + + void EnableSearchUI(bool bEnable); + + void EnableSearchForDependees(bool bEnable); + + void InitContext(sal_Int16 nContext); + + void LoadParams(); + void SaveParams() const; + + // Handler for the Controls + DECL_LINK( OnClickedFieldRadios, weld::Button&, void ); + DECL_LINK( OnClickedSearchAgain, weld::Button&, void ); + DECL_LINK( OnClickedSpecialSettings, weld::Button&, void ); + + DECL_LINK( OnSearchTextModified, weld::ComboBox&, void ); + + DECL_LINK( OnPositionSelected, weld::ComboBox&, void ); + DECL_LINK( OnFieldSelected, weld::ComboBox&, void ); + + DECL_LINK( OnFocusGrabbed, weld::Widget&, void ); + DECL_LINK( OnCheckBoxToggled, weld::ToggleButton&, void ); + + DECL_LINK( OnContextSelection, weld::ComboBox&, void ); + + DECL_LINK( OnSearchProgress, const FmSearchProgress*, void ); + + void initCommon( const css::uno::Reference< css::sdbc::XResultSet >& _rxCursor ); +}; + +inline void FmSearchDialog::SetActiveField(const OUString& strField) +{ + int nInitialField = m_plbField->find_text(strField); + if (nInitialField == -1) + nInitialField = 0; + m_plbField->set_active(nInitialField); + OnFieldSelected(*m_plbField); +} + +#endif // INCLUDED_CUI_SOURCE_INC_CUIFMSEARCH_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/cuigaldlg.hxx b/cui/source/inc/cuigaldlg.hxx new file mode 100644 index 000000000..0ad85b654 --- /dev/null +++ b/cui/source/inc/cuigaldlg.hxx @@ -0,0 +1,277 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_CUI_SOURCE_INC_CUIGALDLG_HXX +#define INCLUDED_CUI_SOURCE_INC_CUIGALDLG_HXX + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class GalleryTheme; +class SearchProgress; +class TakeProgress; +class TPGalleryThemeProperties; + +typedef std::vector< sal_uLong > TokenList_impl; + +struct FilterEntry +{ + OUString aFilterName; +}; + +class SearchThread: public salhelper::Thread +{ +private: + + SearchProgress* mpProgress; + TPGalleryThemeProperties* mpBrowser; + INetURLObject maStartURL; + + void ImplSearch( const INetURLObject& rStartURL, + const std::vector< OUString >& rFormats, + bool bRecursive ); + + virtual ~SearchThread() override; + virtual void execute() override; + +public: + + SearchThread(SearchProgress* pProgress, + TPGalleryThemeProperties* pBrowser, + const INetURLObject& rStartURL); +}; + +class SearchProgress : public weld::GenericDialogController +{ +private: + INetURLObject startUrl_; + TPGalleryThemeProperties* m_pTabPage; + rtl::Reference< SearchThread > m_aSearchThread; + std::unique_ptr m_xFtSearchDir; + std::unique_ptr m_xFtSearchType; + std::unique_ptr m_xBtnCancel; + + DECL_LINK(ClickCancelBtn, weld::Button&, void); + +public: + SearchProgress(weld::Window* pParent, TPGalleryThemeProperties* pTabPage, const INetURLObject& rStartURL); + void LaunchThread(); + virtual ~SearchProgress() override; + + DECL_LINK( CleanUpHdl, void*, void ); + + void SetFileType( const OUString& rType ) { m_xFtSearchType->set_label(rType); } + void SetDirectory( const INetURLObject& rURL ) { m_xFtSearchDir->set_label(GetReducedString(rURL, 30)); } +}; + +class TakeThread: public salhelper::Thread +{ +private: + + TakeProgress* mpProgress; + TPGalleryThemeProperties* mpBrowser; + TokenList_impl& mrTakenList; + + virtual ~TakeThread() override; + virtual void execute() override; + +public: + + TakeThread( + TakeProgress* pProgress, + TPGalleryThemeProperties* pBrowser, + TokenList_impl& rTakenList + ); +}; + +class TakeProgress : public weld::GenericDialogController +{ +private: + weld::Window* m_pParent; + TPGalleryThemeProperties* m_pTabPage; + rtl::Reference< TakeThread > maTakeThread; + TokenList_impl maTakenList; + std::unique_ptr m_xFtTakeFile; + std::unique_ptr m_xBtnCancel; + + DECL_LINK(ClickCancelBtn, weld::Button&, void); + +public: + + TakeProgress(weld::Window* pParent, TPGalleryThemeProperties* pTabPage); + void LaunchThread(); + virtual ~TakeProgress() override; + + DECL_LINK( CleanUpHdl, void*, void ); + + void SetFile( const INetURLObject& rURL ) { m_xFtTakeFile->set_label(GetReducedString(rURL, 30)); } +}; + +class ActualizeProgress : public weld::GenericDialogController +{ +private: + Idle* pIdle; + GalleryTheme* pTheme; + GalleryProgress aStatusProgress; + std::unique_ptr m_xFtActualizeFile; + std::unique_ptr m_xBtnCancel; + + DECL_LINK(ClickCancelBtn, weld::Button&, void); + DECL_LINK(TimeoutHdl, Timer*, void); + DECL_LINK(ActualizeHdl, const INetURLObject&, void); + +public: + ActualizeProgress(weld::Widget* pWindow, GalleryTheme* pThm); + virtual ~ActualizeProgress() override; + + virtual short run() override; +}; + +class TitleDialog : public weld::GenericDialogController +{ +private: + std::unique_ptr m_xEdit; +public: + TitleDialog(weld::Widget* pParent, const OUString& rOldText); + virtual ~TitleDialog() override; + OUString GetTitle() const { return m_xEdit->get_text(); } +}; + +class GalleryIdDialog : public weld::GenericDialogController +{ +private: + GalleryTheme* m_pThm; + std::unique_ptr m_xBtnOk; + std::unique_ptr m_xLbResName; + + DECL_LINK(ClickOkHdl, weld::Button&, void); +public: + GalleryIdDialog(weld::Widget* pParent, GalleryTheme* pThm); + virtual ~GalleryIdDialog() override; + sal_uInt32 GetId() const { return m_xLbResName->get_active(); } +}; + +class GalleryThemeProperties : public SfxTabDialogController +{ + ExchangeData* pData; + + virtual void PageCreated(const OString& rId, SfxTabPage &rPage) override; + +public: + GalleryThemeProperties(weld::Widget* pParent, ExchangeData* pData, SfxItemSet const * pItemSet); +}; + +class TPGalleryThemeGeneral : public SfxTabPage +{ +private: + ExchangeData* pData; + + std::unique_ptr m_xFiMSImage; + std::unique_ptr m_xEdtMSName; + std::unique_ptr m_xFtMSShowType; + std::unique_ptr m_xFtMSShowPath; + std::unique_ptr m_xFtMSShowContent; + std::unique_ptr m_xFtMSShowChangeDate; + + virtual void Reset( const SfxItemSet* ) override {} + virtual bool FillItemSet( SfxItemSet* rSet ) override; + +public: + TPGalleryThemeGeneral(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + void SetXChgData( ExchangeData* pData ); + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet ); +}; + +class TPGalleryThemeProperties : public SfxTabPage +{ + friend class SearchThread; + friend class TakeProgress; + friend class TakeThread; + + ExchangeData* pData; + std::vector aFoundList; + std::vector< std::unique_ptr > + aFilterEntryList; + Timer aPreviewTimer; + OUString aLastFilterName; + OUString aPreviewString; + INetURLObject aURL; + bool bEntriesFound; + bool bInputAllowed; + bool bTakeAll; + bool bSearchRecursive; + + rtl::Reference< ::svt::DialogClosedListener > xDialogListener; + css::uno::Reference< css::media::XPlayer > xMediaPlayer; + css::uno::Reference< css::ui::dialogs::XFolderPicker2 > xFolderPicker; + + DialogGalleryPreview m_aWndPreview; + std::unique_ptr m_xCbbFileType; + std::unique_ptr m_xLbxFound; + std::unique_ptr m_xBtnSearch; + std::unique_ptr m_xBtnTake; + std::unique_ptr m_xBtnTakeAll; + std::unique_ptr m_xCbxPreview; + std::unique_ptr m_xWndPreview; + + virtual void Reset( const SfxItemSet* /*rSet*/ ) override {} + virtual bool FillItemSet( SfxItemSet* /*rSet*/ ) override { return true; } + static OUString addExtension( const OUString&, const OUString& ); + void FillFilterList(); + + void SearchFiles(); + void TakeFiles(); + void DoPreview(); + void EndSearchProgressHdl(sal_Int32 nResult); + + DECL_LINK(ClickPreviewHdl, weld::ToggleButton&, void); + DECL_LINK(ClickSearchHdl, weld::Button&, void); + DECL_LINK(ClickTakeHdl, weld::Button&, void); + DECL_LINK(ClickTakeAllHdl, weld::Button&, void); + DECL_LINK(SelectFoundHdl, weld::TreeView&, void); + DECL_LINK(SelectFileTypeHdl, weld::ComboBox&, void); + DECL_LINK(DClickFoundHdl, weld::TreeView&, bool); + DECL_LINK(PreviewTimerHdl, Timer*, void); + DECL_LINK(DialogClosedHdl, css::ui::dialogs::DialogClosedEvent*, void); + +public: + TPGalleryThemeProperties(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + virtual ~TPGalleryThemeProperties() override; + + void SetXChgData( ExchangeData* pData ); + const ExchangeData* GetXChgData() const { return pData; } + + void StartSearchFiles( const OUString& _rFolderURL, short _nDlgResult ); + + static std::unique_ptr Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet); +}; + +#endif // INCLUDED_CUI_SOURCE_INC_CUIGALDLG_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/cuigrfflt.hxx b/cui/source/inc/cuigrfflt.hxx new file mode 100644 index 000000000..b52804673 --- /dev/null +++ b/cui/source/inc/cuigrfflt.hxx @@ -0,0 +1,183 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_CUI_SOURCE_INC_CUIGRFFLT_HXX +#define INCLUDED_CUI_SOURCE_INC_CUIGRFFLT_HXX + +#include +#include +#include + +class CuiGraphicPreviewWindow : public weld::CustomWidgetController +{ +private: + const Graphic* mpOrigGraphic; + Size maOrigGraphicSizePixel; + Size maOutputSizePixel; + Link maModifyHdl; + Graphic maScaledOrig; + Graphic maPreview; + double mfScaleX; + double mfScaleY; + + virtual void Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle& rRect) override; + virtual void Resize() override; + + void ScaleImageToFit(); + +public: + CuiGraphicPreviewWindow(); + virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override; + void init(const Graphic* pOrigGraphic, const Link& rLink) + { + mpOrigGraphic = pOrigGraphic; + maModifyHdl = rLink; + maOrigGraphicSizePixel = GetDrawingArea()->get_ref_device().LogicToPixel(mpOrigGraphic->GetPrefSize(), + mpOrigGraphic->GetPrefMapMode()); + ScaleImageToFit(); + } + + void SetPreview(const Graphic& rGraphic); + const Graphic& GetScaledOriginal() const { return maScaledOrig; } + double GetScaleX() const { return mfScaleX; } + double GetScaleY() const { return mfScaleY; } + const Size& GetGraphicSizePixel() const { return maOrigGraphicSizePixel; } +}; + +class GraphicFilterDialog : public weld::GenericDialogController +{ +private: + + Timer maTimer; + Link maModifyHdl; + bool bIsBitmap; + + DECL_LINK( ImplPreviewTimeoutHdl, Timer *, void ); + DECL_LINK( ImplModifyHdl, LinkParamNone*, void); + + CuiGraphicPreviewWindow maPreview; + std::unique_ptr mxPreview; + +protected: + const Link& GetModifyHdl() const { return maModifyHdl; } + const Size& GetGraphicSizePixel() const { return maPreview.GetGraphicSizePixel(); } + +public: + + GraphicFilterDialog(weld::Window* pParent, const OUString& rUIXMLDescription, const OString& rID, const Graphic& rGraphic); + virtual Graphic GetFilteredGraphic(const Graphic& rGraphic, double fScaleX, double fScaleY) = 0; +}; + +class GraphicFilterSmooth : public GraphicFilterDialog +{ +private: + std::unique_ptr mxMtrRadius; + DECL_LINK(EditModifyHdl, weld::SpinButton&, void); + +public: + + GraphicFilterSmooth(weld::Window* pParent, const Graphic& rGraphic, double nRadius); + virtual Graphic GetFilteredGraphic( const Graphic& rGraphic, double fScaleX, double fScaleY ) override; +}; + +class GraphicFilterMosaic : public GraphicFilterDialog +{ +private: + std::unique_ptr mxMtrWidth; + std::unique_ptr mxMtrHeight; + std::unique_ptr mxCbxEdges; + DECL_LINK(CheckBoxModifyHdl, weld::ToggleButton&, void); + DECL_LINK(EditModifyHdl, weld::MetricSpinButton&, void); +public: + + GraphicFilterMosaic(weld::Window* pParent, const Graphic& rGraphic, + sal_uInt16 nTileWidth, sal_uInt16 nTileHeight, bool bEnhanceEdges); + + virtual Graphic GetFilteredGraphic( const Graphic& rGraphic, double fScaleX, double fScaleY ) override; + bool IsEnhanceEdges() const { return mxCbxEdges->get_active(); } +}; + +class GraphicFilterSolarize : public GraphicFilterDialog +{ +private: + std::unique_ptr mxMtrThreshold; + std::unique_ptr mxCbxInvert; + DECL_LINK(CheckBoxModifyHdl, weld::ToggleButton&, void); + DECL_LINK(EditModifyHdl, weld::MetricSpinButton&, void); + +public: + GraphicFilterSolarize(weld::Window* pParent, const Graphic& rGraphic, + sal_uInt8 nGreyThreshold, bool bInvert); + virtual Graphic GetFilteredGraphic( const Graphic& rGraphic, double fScaleX, double fScaleY ) override; + bool IsInvert() const { return mxCbxInvert->get_active(); } +}; + +class GraphicFilterSepia : public GraphicFilterDialog +{ +private: + std::unique_ptr mxMtrSepia; + DECL_LINK(EditModifyHdl, weld::MetricSpinButton&, void); +public: + GraphicFilterSepia(weld::Window* pParent, const Graphic& rGraphic, + sal_uInt16 nSepiaPercent); + virtual Graphic GetFilteredGraphic( const Graphic& rGraphic, double fScaleX, double fScaleY ) override; +}; + +class GraphicFilterPoster : public GraphicFilterDialog +{ +private: + std::unique_ptr mxNumPoster; + DECL_LINK(EditModifyHdl, weld::SpinButton&, void); +public: + GraphicFilterPoster(weld::Window* pParent, const Graphic& rGraphic, + sal_uInt16 nPosterColorCount); + virtual Graphic GetFilteredGraphic( const Graphic& rGraphic, double fScaleX, double fScaleY ) override; +}; + +class EmbossControl : public SvxRectCtl +{ +private: + Link maModifyHdl; + virtual bool MouseButtonDown( const MouseEvent& rEvt ) override; + virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override; +public: + EmbossControl() + : SvxRectCtl(nullptr) + { + } + + void SetModifyHdl( const Link& rHdl ) { maModifyHdl = rHdl; } +}; + +class GraphicFilterEmboss : public GraphicFilterDialog +{ +private: + EmbossControl maCtlLight; + std::unique_ptr mxCtlLight; +public: + GraphicFilterEmboss(weld::Window* pParent, const Graphic& rGraphic, + RectPoint eLightSource); + virtual ~GraphicFilterEmboss() override; + + virtual Graphic GetFilteredGraphic(const Graphic& rGraphic, double fScaleX, double fScaleY) override; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/cuihyperdlg.hxx b/cui/source/inc/cuihyperdlg.hxx new file mode 100644 index 000000000..702cf6396 --- /dev/null +++ b/cui/source/inc/cuihyperdlg.hxx @@ -0,0 +1,140 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_CUI_SOURCE_INC_CUIHYPERDLG_HXX +#define INCLUDED_CUI_SOURCE_INC_CUIHYPERDLG_HXX + +#include + +#include + +#include +#include +#include +#include + +#include "iconcdlg.hxx" + +/************************************************************************* +|* +|* Hyperlink-Dialog +|* +\************************************************************************/ + +class SvxHpLinkDlg; +class SvxHlinkCtrl : public SfxControllerItem +{ +private: + SvxHpLinkDlg* pParent; + + SfxStatusForwarder aRdOnlyForwarder; + +public: + SvxHlinkCtrl( sal_uInt16 nId, SfxBindings & rBindings, SvxHpLinkDlg* pDlg); + virtual void dispose() override; + + virtual void StateChanged( sal_uInt16 nSID, SfxItemState eState, + const SfxPoolItem* pState ) override; +}; + + +/************************************************************************* +|* +|* Hyperlink-Dialog +|* +\************************************************************************/ + +class SvxHpLinkDlg : public SfxModelessDialogController +{ +private: + friend class IconChoicePage; + + std::vector< std::unique_ptr > maPageList; + + OString msCurrentPageId; + + const SfxItemSet* pSet; + std::unique_ptr pOutSet; + SfxItemSet* pExampleSet; + std::unique_ptr pRanges; + + SvxHlinkCtrl maCtrl; ///< Controller + std::unique_ptr mpItemSet; + + bool mbGrabFocus : 1; + bool mbIsHTMLDoc : 1; + + std::unique_ptr m_xIconCtrl; + std::unique_ptr m_xOKBtn; + std::unique_ptr m_xApplyBtn; + std::unique_ptr m_xCancelBtn; + std::unique_ptr m_xHelpBtn; + std::unique_ptr m_xResetBtn; + + DECL_LINK( ChosePageHdl_Impl, const OString&, void ); + + IconChoicePageData* GetPageData ( const OString& rId ); + + void SwitchPage( const OString& rId ); + + DECL_LINK( ResetHdl, weld::Button&, void) ; + DECL_LINK (ClickOkHdl_Impl, weld::Button&, void ); + DECL_LINK (ClickApplyHdl_Impl, weld::Button&, void ); + + IconChoicePage* GetTabPage( const OString& rPageId ) + { return GetPageData(rPageId)->xPage.get(); } + + void ActivatePageImpl (); + void DeActivatePageImpl (); + void ResetPageImpl (); + + virtual void Close() override; + void Apply(); + +public: + SvxHpLinkDlg(SfxBindings* pBindings, SfxChildWindow* pChild, weld::Window* pParent); + virtual ~SvxHpLinkDlg () override; + + // interface + void AddTabPage(const OString &rId, CreatePage pCreateFunc /* != NULL */); + + void SetCurPageId( const OString& rId ) { msCurrentPageId = rId; SwitchPage(rId ); } + OString GetCurPageId() const { return msCurrentPageId; } + void ShowPage( const OString& rId ); + + /// gives via map converted local slots if applicable + const sal_uInt16* GetInputRanges( const SfxItemPool& ); + void SetInputSet( const SfxItemSet* pInSet ); + + void Start(); + bool QueryClose(); + + void PageCreated(const OString& rId, IconChoicePage& rPage); + + void SetPage( SvxHyperlinkItem const * pItem ); + void SetReadOnlyMode( bool bReadOnly ); + bool IsHTMLDoc() const { return mbIsHTMLDoc; } + + SfxDispatcher* GetDispatcher() const { return GetBindings().GetDispatcher(); } +}; + + +#endif // INCLUDED_CUI_SOURCE_INC_CUIHYPERDLG_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/cuiimapwnd.hxx b/cui/source/inc/cuiimapwnd.hxx new file mode 100644 index 000000000..b8fcf1053 --- /dev/null +++ b/cui/source/inc/cuiimapwnd.hxx @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_CUIIMAPWND_HXX +#define INCLUDED_CUI_SOURCE_INC_CUIIMAPWND_HXX + +#include +#include + +class URLDlg : public weld::GenericDialogController +{ + std::unique_ptr m_xEdtURL; + std::unique_ptr m_xCbbTargets; + std::unique_ptr m_xEdtName; + std::unique_ptr m_xEdtAlternativeText; + std::unique_ptr m_xEdtDescription; + +public: + + URLDlg(weld::Widget* pWindow, + const OUString& rURL, const OUString& rAlternativeText, const OUString& rDescription, + const OUString& rTarget, const OUString& rName, + TargetList& rTargetList); + virtual ~URLDlg() override; + + OUString GetURL() const { return m_xEdtURL->get_text(); } + OUString GetAltText() const { return m_xEdtAlternativeText->get_text(); } + OUString GetDesc() const { return m_xEdtDescription->get_text(); } + OUString GetTarget() const { return m_xCbbTargets->get_active_text(); } + OUString GetName() const { return m_xEdtName->get_text(); } +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/cuioptgenrl.hxx b/cui/source/inc/cuioptgenrl.hxx new file mode 100644 index 000000000..fa2310d17 --- /dev/null +++ b/cui/source/inc/cuioptgenrl.hxx @@ -0,0 +1,75 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_CUIOPTGENRL_HXX +#define INCLUDED_CUI_SOURCE_INC_CUIOPTGENRL_HXX + +// include --------------------------------------------------------------- + +#include +#include + +#include + +// class SvxGeneralTabPage ----------------------------------------------- + +class SvxGeneralTabPage : public SfxTabPage +{ +private: + // the "Use data for document properties" checkbox + std::unique_ptr m_xUseDataCB; + std::unique_ptr m_xCryptoFrame; + std::unique_ptr m_xSigningKeyLB; + std::unique_ptr m_xEncryptionKeyLB; + std::unique_ptr m_xEncryptToSelfCB; + // rows + struct Row; + std::vector > vRows; + // fields + struct Field; + std::vector > vFields; + // "name" fields + unsigned nNameRow; + unsigned nShortNameField; + + DECL_LINK( ModifyHdl_Impl, weld::Entry&, void ); + + bool GetData_Impl(); + void SetData_Impl(); + + void InitControls (); + void InitCryptography(); + void SetLinks (); + +protected: + virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override; + +public: + SvxGeneralTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + virtual ~SvxGeneralTabPage() override; + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet ); + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; +}; + +#endif // INCLUDED_CUI_SOURCE_INC_CUIOPTGENRL_HXX + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/cuisrchdlg.hxx b/cui/source/inc/cuisrchdlg.hxx new file mode 100644 index 000000000..fc16a4a10 --- /dev/null +++ b/cui/source/inc/cuisrchdlg.hxx @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_CUISRCHDLG_HXX +#define INCLUDED_CUI_SOURCE_INC_CUISRCHDLG_HXX + +#include +#include + +class SvxJSearchOptionsPage; + +class SvxJSearchOptionsDialog : public SfxSingleTabDialogController +{ + SvxJSearchOptionsPage* m_pPage; + + SvxJSearchOptionsDialog( const SvxJSearchOptionsDialog & ) = delete; + SvxJSearchOptionsDialog & operator == ( const SvxJSearchOptionsDialog & ) = delete; + +public: + SvxJSearchOptionsDialog(weld::Window *pParent, + const SfxItemSet& rOptionsSet, TransliterationFlags nInitialFlags); + virtual ~SvxJSearchOptionsDialog() override; + + TransliterationFlags GetTransliterationFlags() const; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/cuitabarea.hxx b/cui/source/inc/cuitabarea.hxx new file mode 100644 index 000000000..849b009c3 --- /dev/null +++ b/cui/source/inc/cuitabarea.hxx @@ -0,0 +1,739 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_CUITABAREA_HXX +#define INCLUDED_CUI_SOURCE_INC_CUITABAREA_HXX + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NO_BUTTON_SELECTED -1 + +class ColorListBox; +class SdrModel; +class SvxBitmapCtl; + +/************************************************************************/ +class ButtonBox +{ + private: + sal_Int32 mnCurrentButton; + std::vector maButtonList; + std::map maButtonToPos; + void SelectButtonImpl( sal_Int32 nPos ) + { + if(mnCurrentButton != NO_BUTTON_SELECTED) + { + maButtonList[mnCurrentButton]->set_active(false); + } + mnCurrentButton = nPos; + maButtonList[mnCurrentButton]->set_active(true); + }; + public: + ButtonBox() + { + mnCurrentButton = NO_BUTTON_SELECTED; + }; + void AddButton(weld::ToggleButton* pButton) + { + maButtonList.push_back(pButton); + maButtonToPos.insert( std::make_pair(pButton, maButtonList.size() - 1) ); + } + sal_Int32 GetCurrentButtonPos() const { return mnCurrentButton; } + sal_Int32 GetButtonPos(weld::ToggleButton* pButton) + { + std::map::const_iterator aBtnPos = maButtonToPos.find(pButton); + if(aBtnPos != maButtonToPos.end()) + return aBtnPos->second; + else + return -1; + } + void SelectButton(weld::ToggleButton* pButton) + { + sal_Int32 nPos = GetButtonPos(pButton); + if(nPos != -1) + SelectButtonImpl(nPos); + } +}; + +enum class PageType +{ + Area, + Gradient, + Hatch, + Bitmap, + Shadow, + Transparence, +}; + +class SvxAreaTabDialog final : public SfxTabDialogController +{ + SdrModel* mpDrawModel; + + XColorListRef mpColorList; + XColorListRef mpNewColorList; + XGradientListRef mpGradientList; + XGradientListRef mpNewGradientList; + XHatchListRef mpHatchingList; + XHatchListRef mpNewHatchingList; + XBitmapListRef mpBitmapList; + XBitmapListRef mpNewBitmapList; + XPatternListRef mpPatternList; + XPatternListRef mpNewPatternList; + + ChangeType mnColorListState; + ChangeType mnBitmapListState; + ChangeType mnPatternListState; + ChangeType mnGradientListState; + ChangeType mnHatchingListState; + + virtual void PageCreated(const OString& rId, SfxTabPage &rPage) override; + + virtual short Ok() override; + DECL_LINK(CancelHdlImpl, weld::Button&, void); + void SavePalettes(); + +public: + SvxAreaTabDialog(weld::Window* pParent, const SfxItemSet* pAttr, SdrModel* pModel, bool bShadow); + + void SetNewColorList( XColorListRef const & pColorList ) + { mpNewColorList = pColorList; } + const XColorListRef& GetNewColorList() const { return mpNewColorList; } +}; + +/************************************************************************/ + +class SvxTransparenceTabPage : public SfxTabPage +{ + static const sal_uInt16 pTransparenceRanges[]; + + const SfxItemSet& rOutAttrs; + + PageType nPageType; + sal_uInt16 nDlgType; + + bool bBitmap; + + XFillAttrSetItem aXFillAttr; + SfxItemSet& rXFSet; + + SvxXRectPreview m_aCtlBitmapPreview; + SvxXRectPreview m_aCtlXRectPreview; + + // main selection + std::unique_ptr m_xRbtTransOff; + std::unique_ptr m_xRbtTransLinear; + std::unique_ptr m_xRbtTransGradient; + + /// linear transparency + std::unique_ptr m_xMtrTransparent; + + // gradient transparency + std::unique_ptr m_xGridGradient; + std::unique_ptr m_xLbTrgrGradientType; + std::unique_ptr m_xFtTrgrCenterX; + std::unique_ptr m_xMtrTrgrCenterX; + std::unique_ptr m_xFtTrgrCenterY; + std::unique_ptr m_xMtrTrgrCenterY; + std::unique_ptr m_xFtTrgrAngle; + std::unique_ptr m_xMtrTrgrAngle; + std::unique_ptr m_xMtrTrgrBorder; + std::unique_ptr m_xMtrTrgrStartValue; + std::unique_ptr m_xMtrTrgrEndValue; + std::unique_ptr m_xCtlBitmapBorder; + std::unique_ptr m_xCtlXRectBorder; + + // preview + std::unique_ptr m_xCtlBitmapPreview; + std::unique_ptr m_xCtlXRectPreview; + + DECL_LINK(ClickTransOffHdl_Impl, weld::ToggleButton&, void); + DECL_LINK(ClickTransLinearHdl_Impl, weld::ToggleButton&, void); + DECL_LINK(ClickTransGradientHdl_Impl, weld::ToggleButton&, void ); + DECL_LINK(ModifyTransparentHdl_Impl, weld::MetricSpinButton&, void); + DECL_LINK(ModifiedTrgrEditHdl_Impl, weld::MetricSpinButton&, void); + DECL_LINK(ModifiedTrgrListBoxHdl_Impl, weld::ComboBox&, void); + void ModifiedTrgrHdl_Impl(const weld::ComboBox*); + + void ActivateLinear(bool bActivate); + void ActivateGradient(bool bActivate); + void SetControlState_Impl(css::awt::GradientStyle eXGS); + + bool InitPreview ( const SfxItemSet& rSet ); + void InvalidatePreview (bool bEnable = true ); + +public: + SvxTransparenceTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + virtual ~SvxTransparenceTabPage() override; + + static std::unique_ptr Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet*); + static const sal_uInt16* GetRanges() { return pTransparenceRanges; } + + virtual bool FillItemSet(SfxItemSet*) override; + virtual void Reset(const SfxItemSet*) override; + virtual void ChangesApplied() override; + virtual void ActivatePage(const SfxItemSet& rSet) override; + virtual DeactivateRC DeactivatePage(SfxItemSet* pSet) override; + + void SetPageType(PageType nInType) { nPageType = nInType; } + void SetDlgType(sal_uInt16 nInType) { nDlgType = nInType; } + virtual void PageCreated(const SfxAllItemSet& aSet) override; +}; + +/************************************************************************/ + +class SvxAreaTabPage : public SfxTabPage +{ + static const sal_uInt16 pAreaRanges[]; +private: + std::unique_ptr m_xFillTabPage; + ButtonBox maBox; + + XColorListRef m_pColorList; + XGradientListRef m_pGradientList; + XHatchListRef m_pHatchingList; + XBitmapListRef m_pBitmapList; + XPatternListRef m_pPatternList; + + // Placeholders for pointer-based entries; these will be inited + // to point to these so that the page is usable without that + // SvxAreaTabDialog has to call the setter methods (e.g. SetColorChgd). + // Without that the pages used in SvxAreaTabDialog are not usable + ChangeType maFixed_ChangeType; + + ChangeType* m_pnColorListState; + ChangeType* m_pnBitmapListState; + ChangeType* m_pnPatternListState; + ChangeType* m_pnGradientListState; + ChangeType* m_pnHatchingListState; + + XFillAttrSetItem m_aXFillAttr; + SfxItemSet& m_rXFSet; + + bool m_bBtnClicked = false; + +protected: + std::unique_ptr m_xFillTab; + std::unique_ptr m_xBtnNone; + std::unique_ptr m_xBtnColor; + std::unique_ptr m_xBtnGradient; + std::unique_ptr m_xBtnHatch; + std::unique_ptr m_xBtnBitmap; + std::unique_ptr m_xBtnPattern; + + void SetOptimalSize(weld::DialogController* pController); + + void SelectFillType( weld::ToggleButton& rButton, const SfxItemSet* _pSet = nullptr ); + SfxTabPage* GetFillTabPage() { return m_xFillTabPage.get(); } + + bool IsBtnClicked() const { return m_bBtnClicked; } + +private: + DECL_LINK(SelectFillTypeHdl_Impl, weld::ToggleButton&, void); + + template< typename TabPage > + bool FillItemSet_Impl( SfxItemSet* ); + template< typename TabPage > + void Reset_Impl( const SfxItemSet* ); + template< typename TabPage > + DeactivateRC DeactivatePage_Impl( SfxItemSet* pSet ); + +public: + SvxAreaTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + virtual ~SvxAreaTabPage() override; + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* ); + static const sal_uInt16* GetRanges() { return pAreaRanges; } + + virtual bool FillItemSet( SfxItemSet* ) override; + virtual void Reset( const SfxItemSet * ) override; + virtual void ActivatePage( const SfxItemSet& rSet ) override; + virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override; + + void SetColorList( XColorListRef const & pColorList ) { m_pColorList = pColorList; } + void SetGradientList( XGradientListRef const & pGrdLst) + { m_pGradientList = pGrdLst; } + void SetHatchingList( XHatchListRef const & pHtchLst) + { m_pHatchingList = pHtchLst; } + void SetBitmapList( XBitmapListRef const & pBmpLst) { m_pBitmapList = pBmpLst; } + void SetPatternList( XPatternListRef const &pPtrnLst ) { m_pPatternList = pPtrnLst; } + virtual void PageCreated(const SfxAllItemSet& aSet) override; + void CreatePage(sal_Int32 nId, SfxTabPage* pTab); + void SetColorChgd( ChangeType* pIn ) { m_pnColorListState = pIn; } + void SetGrdChgd( ChangeType* pIn ) { m_pnGradientListState = pIn; } + void SetHtchChgd( ChangeType* pIn ) { m_pnHatchingListState = pIn; } + void SetBmpChgd( ChangeType* pIn ) { m_pnBitmapListState = pIn; } + void SetPtrnChgd( ChangeType* pIn ) { m_pnPatternListState = pIn; } +}; + + +class SvxShadowTabPage : public SvxTabPage +{ + static const sal_uInt16 pShadowRanges[]; + +private: + const SfxItemSet& m_rOutAttrs; + + XColorListRef m_pColorList; + ChangeType* m_pnColorListState; + PageType m_nPageType; + sal_uInt16 m_nDlgType; + + XFillAttrSetItem m_aXFillAttr; + SfxItemSet& m_rXFSet; + MapUnit m_ePoolUnit; + + SvxRectCtl m_aCtlPosition; + SvxXShadowPreview m_aCtlXRectPreview; + std::unique_ptr m_xTsbShowShadow; + std::unique_ptr m_xGridShadow; + std::unique_ptr m_xMtrDistance; + std::unique_ptr m_xLbShadowColor; + std::unique_ptr m_xMtrTransparent; + std::unique_ptr m_xCtlPosition; + std::unique_ptr m_xCtlXRectPreview; + + DECL_LINK(ClickShadowHdl_Impl, weld::ToggleButton&, void); + DECL_LINK(ModifyShadowHdl_Impl, weld::MetricSpinButton&, void); + DECL_LINK(SelectShadowHdl_Impl, ColorListBox&, void); + +public: + SvxShadowTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + virtual ~SvxShadowTabPage() override; + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* ); + static const sal_uInt16* GetRanges() { return pShadowRanges; } + + virtual bool FillItemSet( SfxItemSet* ) override; + virtual void Reset( const SfxItemSet * ) override; + virtual void ActivatePage( const SfxItemSet& rSet ) override; + virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override; + virtual void PointChanged( weld::DrawingArea* pWindow, RectPoint eRP ) override; + + void SetColorList( XColorListRef const & pColorList ) { m_pColorList = pColorList; } + void SetPageType( PageType nInType ) { m_nPageType = nInType; } + void SetDlgType( sal_uInt16 nInType ) { m_nDlgType = nInType; } + void SetColorChgd( ChangeType* pIn ) { m_pnColorListState = pIn; } + virtual void PageCreated(const SfxAllItemSet& aSet) override; +}; + +/************************************************************************/ + +class SvxGradientTabPage : public SfxTabPage +{ +private: + const SfxItemSet& m_rOutAttrs; + + XColorListRef m_pColorList; + XGradientListRef m_pGradientList; + + ChangeType* m_pnGradientListState; + ChangeType* m_pnColorListState; + + XFillAttrSetItem m_aXFillAttr; + SfxItemSet& m_rXFSet; + + SvxXRectPreview m_aCtlPreview; + std::unique_ptr m_xLbGradientType; + std::unique_ptr m_xFtCenter; + std::unique_ptr m_xMtrCenterX; + std::unique_ptr m_xMtrCenterY; + std::unique_ptr m_xFtAngle; + std::unique_ptr m_xMtrAngle; + std::unique_ptr m_xSliderAngle; + std::unique_ptr m_xMtrBorder; + std::unique_ptr m_xSliderBorder; + std::unique_ptr m_xLbColorFrom; + std::unique_ptr m_xMtrColorFrom; + std::unique_ptr m_xLbColorTo; + std::unique_ptr m_xMtrColorTo; + std::unique_ptr m_xGradientLB; + std::unique_ptr m_xMtrIncrement; + std::unique_ptr m_xCbIncrement; + std::unique_ptr m_xBtnAdd; + std::unique_ptr m_xBtnModify; + std::unique_ptr m_xCtlPreview; + std::unique_ptr m_xGradientLBWin; + + DECL_LINK( ClickAddHdl_Impl, weld::Button&, void ); + DECL_LINK( ClickModifyHdl_Impl, weld::Button&, void ); + DECL_LINK( ChangeGradientHdl, ValueSet*, void ); + void ChangeGradientHdl_Impl(); + DECL_LINK( ClickRenameHdl_Impl, SvxPresetListBox*, void ); + DECL_LINK( ClickDeleteHdl_Impl, SvxPresetListBox*, void ); + DECL_LINK( ModifiedEditHdl_Impl, weld::SpinButton&, void ); + DECL_LINK( ModifiedMetricHdl_Impl, weld::MetricSpinButton&, void ); + DECL_LINK( ModifiedColorListBoxHdl_Impl, ColorListBox&, void ); + DECL_LINK( ModifiedListBoxHdl_Impl, weld::ComboBox&, void ); + DECL_LINK( ChangeAutoStepHdl_Impl, weld::ToggleButton&, void ); + DECL_LINK( ModifiedSliderHdl_Impl, weld::Scale&, void ); + void ModifiedHdl_Impl(void const *); + + void SetControlState_Impl( css::awt::GradientStyle eXGS ); + sal_Int32 SearchGradientList(const OUString& rGradientName); + +public: + SvxGradientTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + virtual ~SvxGradientTabPage() override; + + void Construct(); + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* ); + virtual bool FillItemSet( SfxItemSet* ) override; + virtual void Reset( const SfxItemSet * ) override; + + virtual void ActivatePage( const SfxItemSet& rSet ) override; + virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override; + + void SetColorList( XColorListRef const & pColorList ) { m_pColorList = pColorList; } + void SetGradientList( XGradientListRef const & pGrdLst) + { m_pGradientList = pGrdLst; } + void SetGrdChgd( ChangeType* pIn ) { m_pnGradientListState = pIn; } + void SetColorChgd( ChangeType* pIn ) { m_pnColorListState = pIn; } +}; + +/************************************************************************/ + +class SvxHatchTabPage : public SfxTabPage +{ +private: + const SfxItemSet& m_rOutAttrs; + + XColorListRef m_pColorList; + XHatchListRef m_pHatchingList; + + ChangeType* m_pnHatchingListState; + ChangeType* m_pnColorListState; + + XFillAttrSetItem m_aXFillAttr; + SfxItemSet& m_rXFSet; + + MapUnit m_ePoolUnit; + + SvxXRectPreview m_aCtlPreview; + std::unique_ptr m_xMtrDistance; + std::unique_ptr m_xMtrAngle; + std::unique_ptr m_xSliderAngle; + std::unique_ptr m_xLbLineType; + std::unique_ptr m_xLbLineColor; + std::unique_ptr m_xCbBackgroundColor; + std::unique_ptr m_xLbBackgroundColor; + std::unique_ptr m_xHatchLB; + std::unique_ptr m_xBtnAdd; + std::unique_ptr m_xBtnModify; + std::unique_ptr m_xHatchLBWin; + std::unique_ptr m_xCtlPreview; + + DECL_LINK(ChangeHatchHdl, ValueSet*, void); + void ChangeHatchHdl_Impl(); + DECL_LINK( ModifiedEditHdl_Impl, weld::MetricSpinButton&, void ); + DECL_LINK( ModifiedListBoxHdl_Impl, weld::ComboBox&, void ); + DECL_LINK( ModifiedColorListBoxHdl_Impl, ColorListBox&, void ); + DECL_LINK( ToggleHatchBackgroundColor_Impl, weld::ToggleButton&, void ); + DECL_LINK( ModifiedBackgroundHdl_Impl, ColorListBox&, void ); + DECL_LINK( ModifiedSliderHdl_Impl, weld::Scale&, void ); + void ModifiedHdl_Impl(void const *); + DECL_LINK( ClickAddHdl_Impl, weld::Button&, void ); + DECL_LINK( ClickModifyHdl_Impl, weld::Button&, void ); + DECL_LINK( ClickRenameHdl_Impl, SvxPresetListBox*, void ); + DECL_LINK( ClickDeleteHdl_Impl, SvxPresetListBox*, void ); + + sal_Int32 SearchHatchList(const OUString& rHatchName); + +public: + SvxHatchTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + virtual ~SvxHatchTabPage() override; + + void Construct(); + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* ); + virtual bool FillItemSet( SfxItemSet* ) override; + virtual void Reset( const SfxItemSet * ) override; + + virtual void ActivatePage( const SfxItemSet& rSet ) override; + virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override; + + void SetColorList( XColorListRef const & pColorList ) { m_pColorList = pColorList; } + void SetHatchingList( XHatchListRef const & pHtchLst) + { m_pHatchingList = pHtchLst; } + + void SetHtchChgd( ChangeType* pIn ) { m_pnHatchingListState = pIn; } + void SetColorChgd( ChangeType* pIn ) { m_pnColorListState = pIn; } +}; + +/************************************************************************/ + +class SvxBitmapTabPage : public SfxTabPage +{ + static const sal_uInt16 pBitmapRanges[]; +private: + + const SfxItemSet& m_rOutAttrs; + + XBitmapListRef m_pBitmapList; + ChangeType* m_pnBitmapListState; + + double m_fObjectWidth; + double m_fObjectHeight; + bool m_bLogicalSize; + + XFillAttrSetItem m_aXFillAttr; + SfxItemSet& m_rXFSet; + const SdrView* mpView; + MapUnit mePoolUnit; + FieldUnit meFieldUnit; + Size rBitmapSize; + Size rFilledSize; + Size rZoomedSize; + + SvxXRectPreview m_aCtlBitmapPreview; + std::unique_ptr m_xBitmapLB; + std::unique_ptr m_xBitmapStyleLB; + std::unique_ptr m_xSizeBox; + std::unique_ptr m_xTsbScale; + std::unique_ptr m_xBitmapWidth; + std::unique_ptr m_xBitmapHeight; + std::unique_ptr m_xPositionBox; + std::unique_ptr m_xPositionLB; + std::unique_ptr m_xPositionOffBox; + std::unique_ptr m_xPositionOffX; + std::unique_ptr m_xPositionOffY; + std::unique_ptr m_xTileOffBox; + std::unique_ptr m_xTileOffLB; + std::unique_ptr m_xTileOffset; + std::unique_ptr m_xBtnImport; + std::unique_ptr m_xCtlBitmapPreview; + std::unique_ptr m_xBitmapLBWin; + + DECL_LINK( ModifyBitmapHdl, ValueSet*, void ); + DECL_LINK( ClickScaleHdl, weld::Button&, void ); + DECL_LINK( ModifyBitmapStyleHdl, weld::ComboBox&, void ); + DECL_LINK( ModifyBitmapSizeHdl, weld::MetricSpinButton&, void ); + DECL_LINK( ModifyBitmapPositionHdl, weld::ComboBox&, void ); + DECL_LINK( ModifyPositionOffsetHdl, weld::MetricSpinButton&, void ); + DECL_LINK( ModifyTileOffsetHdl, weld::MetricSpinButton&, void ); + DECL_LINK( ClickRenameHdl, SvxPresetListBox*, void ); + DECL_LINK( ClickDeleteHdl, SvxPresetListBox*, void ); + DECL_LINK( ClickImportHdl, weld::Button&, void ); + void ClickBitmapHdl_Impl(); + void CalculateBitmapPresetSize(); + sal_Int32 SearchBitmapList(const OUString& rBitmapName); + sal_Int32 SearchBitmapList(const GraphicObject& rGraphicObject); + +public: + SvxBitmapTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + virtual ~SvxBitmapTabPage() override; + + void Construct(); + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* ); + + virtual bool FillItemSet( SfxItemSet* ) override; + virtual void Reset( const SfxItemSet * ) override; + virtual void ActivatePage( const SfxItemSet& rSet ) override; + virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override; + + void SetBitmapList( const XBitmapListRef& pBmpLst) { m_pBitmapList = pBmpLst; } + void SetBmpChgd( ChangeType* pIn ) { m_pnBitmapListState = pIn; } +}; + +/************************************************************************/ + +class SvxPatternTabPage : public SvxTabPage +{ +private: + const SfxItemSet& m_rOutAttrs; + + XColorListRef m_pColorList; + XPatternListRef m_pPatternList; + + ChangeType* m_pnPatternListState; + ChangeType* m_pnColorListState; + + XFillAttrSetItem m_aXFillAttr; + SfxItemSet& m_rXFSet; + + SvxXRectPreview m_aCtlPreview; + std::unique_ptr m_xCtlPixel; + std::unique_ptr m_xLbColor; + std::unique_ptr m_xLbBackgroundColor; + std::unique_ptr m_xPatternLB; + std::unique_ptr m_xBtnAdd; + std::unique_ptr m_xBtnModify; + std::unique_ptr m_xCtlPixelWin; + std::unique_ptr m_xCtlPreview; + std::unique_ptr m_xPatternLBWin; + std::unique_ptr m_xBitmapCtl; + + DECL_LINK( ClickAddHdl_Impl, weld::Button&, void ); + DECL_LINK( ClickModifyHdl_Impl, weld::Button&, void ); + DECL_LINK( ChangePatternHdl_Impl, ValueSet*, void ); + DECL_LINK( ChangeColorHdl_Impl, ColorListBox&, void ); + DECL_LINK( ClickRenameHdl_Impl, SvxPresetListBox*, void ); + DECL_LINK( ClickDeleteHdl_Impl, SvxPresetListBox*, void ); + + sal_Int32 SearchPatternList(const OUString& rPatternName); + +public: + SvxPatternTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + virtual ~SvxPatternTabPage() override; + + void Construct(); + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* ); + virtual bool FillItemSet( SfxItemSet* ) override; + virtual void Reset( const SfxItemSet * ) override; + + virtual void ActivatePage( const SfxItemSet& rSet ) override; + virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override; + + virtual void PointChanged( weld::DrawingArea*, RectPoint eRP ) override; + + void SetColorList( XColorListRef const & pColorList ) { m_pColorList = pColorList; } + void SetPatternList( XPatternListRef const & pPatternList) { m_pPatternList = pPatternList; } + void SetPtrnChgd( ChangeType* pIn ) { m_pnPatternListState = pIn; } + void SetColorChgd( ChangeType* pIn ) { m_pnColorListState = pIn; } + void ChangeColor_Impl(); +}; + +/************************************************************************/ + +enum class ColorModel +{ + RGB, + CMYK +}; + +class SvxColorTabPage : public SfxTabPage +{ +private: + const SfxItemSet& rOutAttrs; + + XColorListRef pColorList; + + ChangeType* pnColorListState; + + XFillAttrSetItem aXFillAttr; + SfxItemSet& rXFSet; + + ColorModel eCM; + + Color aPreviousColor; + Color aCurrentColor; + + css::uno::Reference< css::uno::XComponentContext > m_context; + + PaletteManager maPaletteManager; + SvxXRectPreview m_aCtlPreviewOld; + SvxXRectPreview m_aCtlPreviewNew; + std::unique_ptr m_xValSetColorList; + std::unique_ptr m_xValSetRecentList; + std::unique_ptr m_xSelectPalette; + std::unique_ptr m_xRbRGB; + std::unique_ptr m_xRbCMYK; + std::unique_ptr m_xRGBcustom; + std::unique_ptr m_xRGBpreset; + std::unique_ptr m_xRpreset; + std::unique_ptr m_xGpreset; + std::unique_ptr m_xBpreset; + std::unique_ptr m_xRcustom; + std::unique_ptr m_xGcustom; + std::unique_ptr m_xBcustom; + std::unique_ptr m_xHexpreset; + std::unique_ptr m_xHexcustom; + std::unique_ptr m_xCMYKcustom; + std::unique_ptr m_xCMYKpreset; + std::unique_ptr m_xCpreset; + std::unique_ptr m_xYpreset; + std::unique_ptr m_xMpreset; + std::unique_ptr m_xKpreset; + std::unique_ptr m_xCcustom; + std::unique_ptr m_xYcustom; + std::unique_ptr m_xMcustom; + std::unique_ptr m_xKcustom; + std::unique_ptr m_xBtnAdd; + std::unique_ptr m_xBtnDelete; + std::unique_ptr m_xBtnWorkOn; + std::unique_ptr m_xCtlPreviewOld; + std::unique_ptr m_xCtlPreviewNew; + std::unique_ptr m_xValSetColorListWin; + std::unique_ptr m_xValSetRecentListWin; + + static void ConvertColorValues (Color& rColor, ColorModel eModell); + static void RgbToCmyk_Impl( Color& rColor, sal_uInt16& rK ); + static void CmykToRgb_Impl( Color& rColor, const sal_uInt16 nKey ); + sal_uInt16 ColorToPercent_Impl( sal_uInt16 nColor ); + sal_uInt16 PercentToColor_Impl( sal_uInt16 nPercent ); + + void ImpColorCountChanged(); + void FillPaletteLB(); + + DECL_LINK(ClickAddHdl_Impl, weld::Button&, void); + DECL_LINK(ClickWorkOnHdl_Impl, weld::Button&, void); + DECL_LINK(ClickDeleteHdl_Impl, weld::Button&, void); + + DECL_LINK(SelectPaletteLBHdl, weld::ComboBox&, void); + DECL_LINK( SelectValSetHdl_Impl, ValueSet*, void ); + DECL_LINK( SelectColorModeHdl_Impl, weld::ToggleButton&, void ); + void ChangeColor(const Color &rNewColor, bool bUpdatePreset = true); + void SetColorModel(ColorModel eModel); + void ChangeColorModel(); + void UpdateColorValues( bool bUpdatePreset = true ); + DECL_LINK(SpinValueHdl_Impl, weld::SpinButton&, void); + DECL_LINK(MetricSpinValueHdl_Impl, weld::MetricSpinButton&, void); + DECL_LINK(ModifiedHdl_Impl, weld::Entry&, void); + + void UpdateModified(); + + static sal_Int32 FindInCustomColors( OUString const & aColorName ); + sal_Int32 FindInPalette( const Color& rColor ); + +public: + SvxColorTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + virtual ~SvxColorTabPage() override; + + void Construct(); + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* ); + virtual bool FillItemSet( SfxItemSet* ) override; + virtual void Reset( const SfxItemSet * ) override; + + virtual void ActivatePage( const SfxItemSet& rSet ) override; + virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override; + + void SetPropertyList( XPropertyListType t, const XPropertyListRef &xRef ); + void SetColorList( const XColorListRef& pColList ); + + + void SetColorChgd( ChangeType* pIn ) { pnColorListState = pIn; } + + void SetCtlPreviewOld( const SfxItemSet& rAttrs ) { m_aCtlPreviewOld.SetAttributes( rAttrs ); } + + virtual void FillUserData() override; +}; + +#endif // INCLUDED_CUI_SOURCE_INC_CUITABAREA_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/cuitabline.hxx b/cui/source/inc/cuitabline.hxx new file mode 100644 index 000000000..87ae008da --- /dev/null +++ b/cui/source/inc/cuitabline.hxx @@ -0,0 +1,378 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_CUI_SOURCE_INC_CUITABLINE_HXX +#define INCLUDED_CUI_SOURCE_INC_CUITABLINE_HXX + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum class PageType; +class ColorListBox; + +class SvxLineTabDialog final : public SfxTabDialogController +{ + SdrModel* pDrawModel; + const SdrObject* pObj; + + XColorListRef pColorList; + XColorListRef mpNewColorList; + XDashListRef pDashList; + XDashListRef pNewDashList; + XLineEndListRef pLineEndList; + XLineEndListRef pNewLineEndList; + bool bObjSelected; + + ChangeType nLineEndListState; + ChangeType nDashListState; + ChangeType mnColorListState; + + PageType nPageType; + sal_Int32 nPosDashLb; + sal_Int32 nPosLineEndLb; + + virtual void PageCreated(const OString& rId, SfxTabPage &rPage) override; + + virtual short Ok() override; + DECL_LINK(CancelHdlImpl, weld::Button&, void); + void SavePalettes(); + +public: + SvxLineTabDialog(weld::Window* pParent, const SfxItemSet* pAttr, + SdrModel* pModel, const SdrObject* pObj, + bool bHasObj); + + void SetNewDashList( XDashListRef const & pInLst) + { pNewDashList = pInLst; } + const XDashListRef& GetNewDashList() const { return pNewDashList; } + + void SetNewLineEndList( XLineEndListRef const & pInLst) + { pNewLineEndList = pInLst; } + const XLineEndListRef& GetNewLineEndList() const { return pNewLineEndList; } + + void SetNewColorList( XColorListRef const & pColTab ) { mpNewColorList = pColTab; } + const XColorListRef& GetNewColorList() const { return mpNewColorList; } +}; + +/*************************************************************************/ + +struct SvxBmpItemInfo +{ + std::unique_ptr pBrushItem; + OUString sItemId; +}; + +class SvxLineTabPage : public SfxTabPage +{ + static const sal_uInt16 pLineRanges[]; +private: + //#58425# symbols on a line (e. g. StarChart) -> + /** a list of symbols to be shown in menu. Symbol at position SID_ATTR_SYMBOLTYPE is to be shown in preview. + The list position is to be used cyclic. */ + SdrObjList* m_pSymbolList; + bool m_bNewSize; + /// a graphic to be displayed in the preview in case that an automatic symbol is chosen + Graphic m_aAutoSymbolGraphic; + long m_nSymbolType; + /// attributes for the shown symbols; only necessary if not equal to line properties + SfxItemSet* m_pSymbolAttr; + + std::vector m_aGrfNames; + std::vector< std::unique_ptr > + m_aGalleryBrushItems; + std::vector< std::unique_ptr > + m_aSymbolBrushItems; + bool m_bLastWidthModified; + Size m_aSymbolLastSize; + Graphic m_aSymbolGraphic; + Size m_aSymbolSize; + bool m_bSymbols; + + const SfxItemSet& m_rOutAttrs; + bool m_bObjSelected; + + XLineAttrSetItem m_aXLineAttr; + SfxItemSet& m_rXLSet; + + XDashListRef m_pDashList; + XLineEndListRef m_pLineEndList; + + ChangeType* m_pnLineEndListState; + ChangeType* m_pnDashListState; + ChangeType* m_pnColorListState; + PageType m_nPageType; + sal_uInt16 m_nDlgType; + sal_Int32* m_pPosDashLb; + sal_Int32* m_pPosLineEndLb; + + MapUnit m_ePoolUnit; + + sal_Int32 m_nActLineWidth; + + SvxXLinePreview m_aCtlPreview; + std::unique_ptr m_xBoxColor; + std::unique_ptr m_xLbLineStyle; + std::unique_ptr m_xLbColor; + std::unique_ptr m_xBoxWidth; + std::unique_ptr m_xMtrLineWidth; + std::unique_ptr m_xBoxTransparency; + std::unique_ptr m_xMtrTransparent; + std::unique_ptr m_xFlLineEnds; + std::unique_ptr m_xBoxArrowStyles; + std::unique_ptr m_xLbStartStyle; + std::unique_ptr m_xBoxStart; + std::unique_ptr m_xMtrStartWidth; + std::unique_ptr m_xTsbCenterStart; + std::unique_ptr m_xBoxEnd; + std::unique_ptr m_xLbEndStyle; + std::unique_ptr m_xMtrEndWidth; + std::unique_ptr m_xTsbCenterEnd; + std::unique_ptr m_xCbxSynchronize; + std::unique_ptr m_xCtlPreview; + + std::unique_ptr m_xFLEdgeStyle; + std::unique_ptr m_xGridEdgeCaps; + std::unique_ptr m_xLBEdgeStyle; + + // LineCaps + std::unique_ptr m_xLBCapStyle; + + std::unique_ptr m_xFlSymbol; + std::unique_ptr m_xGridIconSize; + std::unique_ptr m_xSymbolMB; + std::unique_ptr m_xSymbolsMenu; + std::unique_ptr m_xGalleryMenu; + std::unique_ptr m_xSymbolWidthMF; + std::unique_ptr m_xSymbolHeightMF; + std::unique_ptr m_xSymbolRatioCB; + + // handler for gallery popup menu button + size + DECL_LINK(GraphicHdl_Impl, const OString&, void); + DECL_LINK(SizeHdl_Impl, weld::MetricSpinButton&, void); + DECL_LINK(MenuCreateHdl_Impl, weld::ToggleButton&, void); + DECL_LINK(RatioHdl_Impl, weld::ToggleButton&, void); + + DECL_LINK(ClickInvisibleHdl_Impl, weld::ComboBox&, void); + void ClickInvisibleHdl_Impl(); + DECL_LINK(ChangeStartClickHdl_Impl, weld::Button&, void); + DECL_LINK(ChangeStartListBoxHdl_Impl, weld::ComboBox&, void); + DECL_LINK(ChangeStartModifyHdl_Impl, weld::MetricSpinButton&, void); + DECL_LINK(ChangeEndListBoxHdl_Impl, weld::ComboBox&, void); + DECL_LINK(ChangeEndModifyHdl_Impl, weld::MetricSpinButton&, void); + DECL_LINK(ChangeEndClickHdl_Impl, weld::Button&, void); + DECL_LINK(ChangePreviewListBoxHdl_Impl, ColorListBox&, void); + DECL_LINK(ChangePreviewModifyHdl_Impl, weld::MetricSpinButton&, void); + void ChangePreviewHdl_Impl(const weld::MetricSpinButton*); + DECL_LINK(ChangeTransparentHdl_Impl, weld::MetricSpinButton&, void); + + DECL_LINK(ChangeEdgeStyleHdl_Impl, weld::ComboBox&, void); + + // LineCaps + DECL_LINK(ChangeCapStyleHdl_Impl, weld::ComboBox&, void); + + void FillXLSet_Impl(); + + void FillListboxes(); +public: + + void ShowSymbolControls(bool bOn); + + SvxLineTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + virtual ~SvxLineTabPage() override; + + void Construct(); + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* ); + static const sal_uInt16* GetRanges() { return pLineRanges; } + + virtual bool FillItemSet( SfxItemSet* ) override; + virtual void Reset( const SfxItemSet* ) override; + + virtual void ActivatePage( const SfxItemSet& rSet ) override; + virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override; + + virtual void FillUserData() override; + + void SetDashList( XDashListRef const & pDshLst ) { m_pDashList = pDshLst; } + void SetLineEndList( XLineEndListRef const & pLneEndLst) { m_pLineEndList = pLneEndLst; } + void SetObjSelected( bool bHasObj ) { m_bObjSelected = bHasObj; } + + void SetPageType( PageType nInType ) { m_nPageType = nInType; } + void SetDlgType( sal_uInt16 nInType ) { m_nDlgType = nInType; } + void SetPosDashLb( sal_Int32* pInPos ) { m_pPosDashLb = pInPos; } + void SetPosLineEndLb( sal_Int32* pInPos ) { m_pPosLineEndLb = pInPos; } + + void SetLineEndChgd( ChangeType* pIn ) { m_pnLineEndListState = pIn; } + void SetDashChgd( ChangeType* pIn ) { m_pnDashListState = pIn; } + void SetColorChgd( ChangeType* pIn ) { m_pnColorListState = pIn; } + + virtual void PageCreated(const SfxAllItemSet& aSet) override; +}; + +/*************************************************************************/ + +class SvxLineDefTabPage : public SfxTabPage +{ +private: + const SfxItemSet& rOutAttrs; + XDash aDash; + + XLineAttrSetItem aXLineAttr; + SfxItemSet& rXLSet; + + XDashListRef pDashList; + + ChangeType* pnDashListState; + PageType* pPageType; + sal_uInt16 nDlgType; + sal_Int32* pPosDashLb; + + MapUnit ePoolUnit; + FieldUnit eFUnit; + + SvxXLinePreview m_aCtlPreview; + std::unique_ptr m_xLbLineStyles; + std::unique_ptr m_xLbType1; + std::unique_ptr m_xLbType2; + std::unique_ptr m_xNumFldNumber1; + std::unique_ptr m_xNumFldNumber2; + std::unique_ptr m_xMtrLength1; + std::unique_ptr m_xMtrLength2; + std::unique_ptr m_xMtrDistance; + std::unique_ptr m_xCbxSynchronize; + std::unique_ptr m_xBtnAdd; + std::unique_ptr m_xBtnModify; + std::unique_ptr m_xBtnDelete; + std::unique_ptr m_xBtnLoad; + std::unique_ptr m_xBtnSave; + std::unique_ptr m_xCtlPreview; + + void FillDash_Impl(); + void FillDialog_Impl(); + + DECL_LINK(ClickAddHdl_Impl, weld::Button&, void); + DECL_LINK(ClickModifyHdl_Impl, weld::Button&, void); + DECL_LINK(ClickDeleteHdl_Impl, weld::Button&, void); + DECL_LINK(SelectLinestyleListBoxHdl_Impl, weld::ComboBox&, void); + void SelectLinestyleHdl_Impl(const weld::ComboBox*); + DECL_LINK(ChangePreviewHdl_Impl, weld::MetricSpinButton&, void); + DECL_LINK(ChangeNumber1Hdl_Impl, weld::SpinButton&, void); + DECL_LINK(ChangeNumber2Hdl_Impl, weld::SpinButton&, void); + DECL_LINK(ClickLoadHdl_Impl, weld::Button&, void); + DECL_LINK(ClickSaveHdl_Impl, weld::Button&, void); + DECL_LINK(ChangeMetricHdl_Impl, weld::ToggleButton&, void); + DECL_LINK(SelectTypeListBoxHdl_Impl, weld::ComboBox&, void); + void SelectTypeHdl_Impl(const weld::ComboBox*); + void ChangeMetricHdl_Impl(const weld::ToggleButton*); + + void CheckChanges_Impl(); + +public: + SvxLineDefTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + virtual ~SvxLineDefTabPage() override; + + void Construct(); + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* ); + virtual bool FillItemSet( SfxItemSet* ) override; + virtual void Reset( const SfxItemSet * ) override; + + virtual void ActivatePage( const SfxItemSet& rSet ) override; + virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override; + + void SetDashList( XDashListRef const & pDshLst ) { pDashList = pDshLst; } + + void SetPageType( PageType* pInType ) { pPageType = pInType; } + void SetDlgType( sal_uInt16 nInType ) { nDlgType = nInType; } + void SetPosDashLb( sal_Int32* pInPos ) { pPosDashLb = pInPos; } + + void SetDashChgd( ChangeType* pIn ) { pnDashListState = pIn; } +}; + +/*************************************************************************/ + +class SvxLineEndDefTabPage : public SfxTabPage +{ +private: + const SfxItemSet& rOutAttrs; + const SdrObject* pPolyObj; + + XLineAttrSetItem aXLineAttr; + SfxItemSet& rXLSet; + + XLineEndListRef pLineEndList; + + ChangeType* pnLineEndListState; + PageType* pPageType; + sal_uInt16 nDlgType; + sal_Int32* pPosLineEndLb; + + SvxXLinePreview m_aCtlPreview; + std::unique_ptr m_xEdtName; + std::unique_ptr m_xLbLineEnds; + std::unique_ptr m_xBtnAdd; + std::unique_ptr m_xBtnModify; + std::unique_ptr m_xBtnDelete; + std::unique_ptr m_xBtnLoad; + std::unique_ptr m_xBtnSave; + std::unique_ptr m_xCtlPreview; + + DECL_LINK(ClickAddHdl_Impl, weld::Button&, void); + DECL_LINK(ClickModifyHdl_Impl, weld::Button&, void); + DECL_LINK(ClickDeleteHdl_Impl, weld::Button&, void); + DECL_LINK(ClickLoadHdl_Impl, weld::Button&, void); + DECL_LINK(ClickSaveHdl_Impl, weld::Button&, void); + DECL_LINK(SelectLineEndHdl_Impl, weld::ComboBox&, void); + + void SelectLineEndHdl_Impl(); + void CheckChanges_Impl(); + +public: + SvxLineEndDefTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + virtual ~SvxLineEndDefTabPage() override; + + void Construct(); + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* ); + virtual bool FillItemSet( SfxItemSet* ) override; + virtual void Reset( const SfxItemSet * ) override; + + virtual void ActivatePage( const SfxItemSet& rSet ) override; + virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override; + + void SetLineEndList( XLineEndListRef const & pInList ) { pLineEndList = pInList; } + void SetPolyObj( const SdrObject* pObj ) { pPolyObj = pObj; } + + void SetPageType( PageType* pInType ) { pPageType = pInType; } + void SetDlgType( sal_uInt16 nInType ) { nDlgType = nInType; } + void SetPosLineEndLb( sal_Int32* pInPos ) { pPosLineEndLb = pInPos; } + + void SetLineEndChgd( ChangeType* pIn ) { pnLineEndListState = pIn; } +}; + +#endif // INCLUDED_CUI_SOURCE_INC_CUITABLINE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/cuitbxform.hxx b/cui/source/inc/cuitbxform.hxx new file mode 100644 index 000000000..f6e52b094 --- /dev/null +++ b/cui/source/inc/cuitbxform.hxx @@ -0,0 +1,38 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_CUITBXFORM_HXX +#define INCLUDED_CUI_SOURCE_INC_CUITBXFORM_HXX + +#include + +class FmInputRecordNoDialog : public weld::GenericDialogController +{ + std::unique_ptr m_xRecordNo; + +public: + FmInputRecordNoDialog(weld::Window* pParent); + virtual ~FmInputRecordNoDialog() override; + + void SetValue(int dNew) { m_xRecordNo->set_value(dNew); } + int GetValue() const { return m_xRecordNo->get_value(); } +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/dbregister.hxx b/cui/source/inc/dbregister.hxx new file mode 100644 index 000000000..e1bc2f6b1 --- /dev/null +++ b/cui/source/inc/dbregister.hxx @@ -0,0 +1,112 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_CUI_SOURCE_INC_DBREGISTER_HXX +#define INCLUDED_CUI_SOURCE_INC_DBREGISTER_HXX + +#include +#include +#include + +namespace svx +{ + + class DbRegistrationOptionsPage : public SfxTabPage + { + private: + sal_uLong m_nOldCount; + bool m_bModified; + + std::unique_ptr m_xNew; + std::unique_ptr m_xEdit; + std::unique_ptr m_xDelete; + std::unique_ptr m_xPathBox; + std::unique_ptr m_xIter; + + DECL_LINK( NewHdl, weld::Button&, void ); + DECL_LINK( EditHdl, weld::Button&, void ); + DECL_LINK( DeleteHdl, weld::Button&, void ); + DECL_LINK( PathBoxDoubleClickHdl, weld::TreeView&, bool); + + DECL_LINK( PathSelect_Impl, weld::TreeView&, void); + + DECL_LINK( HeaderSelect_Impl, int, void ); + DECL_LINK( NameValidator, const OUString&, bool); + + /** inserts a new entry in the tablistbox + @param _sName + The name of the entry. + @param _sLocation + The location of the file. + */ + void insertNewEntry( const OUString& _sName,const OUString& _sLocation, const bool bReadOnly ); + + /** opens the LinkDialog to create a register pair + @param sOldName + The old name of the entry may be empty. + @param sOldLocation + The old location of the entry may be empty. + @param nEntry + The entry to remove if the entry will be changed + */ + void openLinkDialog(const OUString& sOldName, const OUString& sOldLocation, int nEntry = -1); + + public: + DbRegistrationOptionsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + virtual ~DbRegistrationOptionsPage() override; + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet ); + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; + virtual void FillUserData() override; + }; + + /** helper for DatabaseRegistrationDialog + + Necessary so that DatabaseRegistrationDialog is self-contained, i.e. always reflects + the current registration state. + */ + class RegistrationItemSetHolder + { + private: + SfxItemSet m_aRegistrationItems; + + protected: + RegistrationItemSetHolder( const SfxItemSet& _rMasterSet ); + ~RegistrationItemSetHolder(); + + protected: + const SfxItemSet& getRegistrationItems() const { return m_aRegistrationItems; } + }; + + class DatabaseRegistrationDialog :public RegistrationItemSetHolder + ,public SfxSingleTabDialogController + { + public: + DatabaseRegistrationDialog(weld::Window* pParent, const SfxItemSet& rAttr); + + virtual short run() override; + }; +} + +#endif // INCLUDED_CUI_SOURCE_INC_DBREGISTER_HXX + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/defdlgname.hxx b/cui/source/inc/defdlgname.hxx new file mode 100644 index 000000000..08aa42497 --- /dev/null +++ b/cui/source/inc/defdlgname.hxx @@ -0,0 +1,30 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_DEFDLGNAME_HXX +#define INCLUDED_CUI_SOURCE_INC_DEFDLGNAME_HXX + + +// const ----------------------------------------------------------------- + +const short RET_BTN_1 = 100; +const short RET_BTN_2 = 101; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/dialmgr.hxx b/cui/source/inc/dialmgr.hxx new file mode 100644 index 000000000..c31fde3a2 --- /dev/null +++ b/cui/source/inc/dialmgr.hxx @@ -0,0 +1,26 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include + +OUString CuiResId(const char* pKey); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/dlgname.hxx b/cui/source/inc/dlgname.hxx new file mode 100644 index 000000000..8fd754990 --- /dev/null +++ b/cui/source/inc/dlgname.hxx @@ -0,0 +1,125 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_DLGNAME_HXX +#define INCLUDED_CUI_SOURCE_INC_DLGNAME_HXX + +#include + +/// Dialog for editing a name +class SvxNameDialog : public weld::GenericDialogController +{ +private: + std::unique_ptr m_xEdtName; + std::unique_ptr m_xFtDescription; + std::unique_ptr m_xBtnOK; + + Link m_aCheckNameHdl; + Link m_aCheckNameTooltipHdl; + + DECL_LINK(ModifyHdl, weld::Entry&, void); + +public: + SvxNameDialog(weld::Window* pWindow, const OUString& rName, const OUString& rDesc); + + OUString GetName() const { return m_xEdtName->get_text(); } + + /** add a callback Link that is called whenever the content of the edit + field is changed. The Link result determines whether the OK + Button is enabled (> 0) or disabled (== 0). + + @param rLink a Callback declared with DECL_LINK and implemented with + IMPL_LINK, that is executed on modification. + + @param bCheckImmediately If true, the Link is called directly after + setting it. It is recommended to set this flag to true to avoid + an inconsistent state if the initial String (given in the CTOR) + does not satisfy the check condition. + + @todo Remove the parameter bCheckImmediately and incorporate the 'true' + behaviour as default. + */ + void SetCheckNameHdl(const Link& rLink, bool bCheckImmediately) + { + m_aCheckNameHdl = rLink; + if (bCheckImmediately) + m_xBtnOK->set_sensitive(rLink.Call(*this)); + } + + void SetCheckNameTooltipHdl(const Link& rLink) + { + m_aCheckNameTooltipHdl = rLink; + m_xBtnOK->set_tooltip_text(rLink.Call(*this)); + } + + void SetEditHelpId(const OString& aHelpId) { m_xEdtName->set_help_id(aHelpId);} +}; + +/** #i68101# + Dialog for editing Object name + plus uniqueness-callback-linkHandler */ +class SvxObjectNameDialog : public weld::GenericDialogController +{ +private: + // name + std::unique_ptr m_xEdtName; + + // buttons + std::unique_ptr m_xBtnOK; + + // callback link for name uniqueness + Link aCheckNameHdl; + + DECL_LINK(ModifyHdl, weld::Entry&, void); + +public: + // constructor + SvxObjectNameDialog(weld::Window* pWindow, const OUString& rName); + + // data access + OUString GetName() const { return m_xEdtName->get_text(); } + + // set handler + void SetCheckNameHdl(const Link& rLink) + { + aCheckNameHdl = rLink; + } +}; + +/** #i68101# + Dialog for editing Object Title and Description */ +class SvxObjectTitleDescDialog : public weld::GenericDialogController +{ +private: + // title + std::unique_ptr m_xEdtTitle; + + // description + std::unique_ptr m_xEdtDescription; + +public: + // constructor + SvxObjectTitleDescDialog(weld::Window* pWindow, const OUString& rTitle, const OUString& rDesc); + // data access + OUString GetTitle() const { return m_xEdtTitle->get_text(); } + OUString GetDescription() const { return m_xEdtDescription->get_text(); } +}; + +#endif // INCLUDED_CUI_SOURCE_INC_DLGNAME_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/dstribut.hxx b/cui/source/inc/dstribut.hxx new file mode 100644 index 000000000..3d3c99de1 --- /dev/null +++ b/cui/source/inc/dstribut.hxx @@ -0,0 +1,72 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_DSTRIBUT_HXX +#define INCLUDED_CUI_SOURCE_INC_DSTRIBUT_HXX + +#include +#include +#include + +class SvxDistributePage : public SfxTabPage +{ + SvxDistributeHorizontal m_eDistributeHor; + SvxDistributeVertical m_eDistributeVer; + + std::unique_ptr m_xBtnHorNone; + std::unique_ptr m_xBtnHorLeft; + std::unique_ptr m_xBtnHorCenter; + std::unique_ptr m_xBtnHorDistance; + std::unique_ptr m_xBtnHorRight; + std::unique_ptr m_xBtnVerNone; + std::unique_ptr m_xBtnVerTop; + std::unique_ptr m_xBtnVerCenter; + std::unique_ptr m_xBtnVerDistance; + std::unique_ptr m_xBtnVerBottom; + +public: + SvxDistributePage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs, + SvxDistributeHorizontal eHor, + SvxDistributeVertical eVer); + virtual ~SvxDistributePage() override; + + virtual bool FillItemSet(SfxItemSet*) override; + virtual void Reset(const SfxItemSet*) override; + + SvxDistributeHorizontal GetDistributeHor() const { return m_eDistributeHor; } + SvxDistributeVertical GetDistributeVer() const { return m_eDistributeVer; } +}; + +class SvxDistributeDialog : public SfxSingleTabDialogController +{ + SvxDistributePage* mpPage; + +public: + SvxDistributeDialog(weld::Window* pParent, const SfxItemSet& rAttr, + SvxDistributeHorizontal eHor, + SvxDistributeVertical eVer); + virtual ~SvxDistributeDialog() override; + + SvxDistributeHorizontal GetDistributeHor() const { return mpPage->GetDistributeHor(); } + SvxDistributeVertical GetDistributeVer() const { return mpPage->GetDistributeVer(); } +}; + + +#endif // INCLUDED_CUI_SOURCE_INC_DSTRIBUT_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/grfpage.hxx b/cui/source/inc/grfpage.hxx new file mode 100644 index 000000000..afdc7cb6b --- /dev/null +++ b/cui/source/inc/grfpage.hxx @@ -0,0 +1,109 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_CUI_SOURCE_INC_GRFPAGE_HXX +#define INCLUDED_CUI_SOURCE_INC_GRFPAGE_HXX + +#include +#include +#include + +class SvxCropExample : public weld::CustomWidgetController +{ + MapMode m_aMapMode; + Size m_aFrameSize; + Point m_aTopLeft, m_aBottomRight; + Graphic m_aGrf; + +public: + SvxCropExample(); + + virtual void Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle& rRect) override; + virtual void Resize() override; + virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override; + + void SetTop( long nVal ) { m_aTopLeft.setX(nVal); } + void SetBottom( long nVal ) { m_aBottomRight.setX(nVal); } + void SetLeft( long nVal ) { m_aTopLeft.setY(nVal); } + void SetRight( long nVal) { m_aBottomRight.setY(nVal); } + void SetFrameSize( const Size& rSz ); + void SetGraphic( const Graphic& rGrf ) { m_aGrf = rGrf; } +}; + +class SvxGrfCropPage : public SfxTabPage +{ + friend class VclPtr; + + OUString aGraphicName; + Size aOrigSize; + Size aOrigPixelSize; + Size aPageSize; + long nOldWidth; + long nOldHeight; + bool bSetOrigSize; + + SvxCropExample m_aExampleWN; + + std::unique_ptr m_xCropFrame; + std::unique_ptr m_xZoomConstRB; + std::unique_ptr m_xSizeConstRB; + std::unique_ptr m_xLeftMF; + std::unique_ptr m_xRightMF; + std::unique_ptr m_xTopMF; + std::unique_ptr m_xBottomMF; + + std::unique_ptr m_xScaleFrame; + std::unique_ptr m_xWidthZoomMF; + std::unique_ptr m_xHeightZoomMF; + + std::unique_ptr m_xSizeFrame; + std::unique_ptr m_xWidthMF; + std::unique_ptr m_xHeightMF; + + std::unique_ptr m_xOrigSizeGrid; + std::unique_ptr m_xOrigSizeFT; + std::unique_ptr m_xOrigSizePB; + + // Example + std::unique_ptr m_xExampleWN; + + DECL_LINK(ZoomHdl, weld::MetricSpinButton&, void); + DECL_LINK(SizeHdl, weld::MetricSpinButton&, void); + DECL_LINK(CropModifyHdl, weld::MetricSpinButton&, void); + DECL_LINK(OrigSizeHdl, weld::Button&, void); + + void CalcZoom(); + void CalcMinMaxBorder(); + void GraphicHasChanged(bool bFound); + virtual void ActivatePage(const SfxItemSet& rSet) override; + + static Size GetGrfOrigSize(const Graphic&); +public: + SvxGrfCropPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet); + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet ); + virtual ~SvxGrfCropPage() override; + + virtual bool FillItemSet( SfxItemSet *rSet ) override; + virtual void Reset( const SfxItemSet *rSet ) override; + virtual DeactivateRC DeactivatePage( SfxItemSet *pSet ) override; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/hangulhanjadlg.hxx b/cui/source/inc/hangulhanjadlg.hxx new file mode 100644 index 000000000..056aee159 --- /dev/null +++ b/cui/source/inc/hangulhanjadlg.hxx @@ -0,0 +1,305 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_HANGULHANJADLG_HXX +#define INCLUDED_CUI_SOURCE_INC_HANGULHANJADLG_HXX + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace svx +{ + + class SuggestionSet : public ValueSet + { + public: + SuggestionSet(std::unique_ptr xScrolledWindow); + + virtual void UserDraw( const UserDrawEvent& rUDEvt ) override; + }; + + class SuggestionDisplay + { + public: + SuggestionDisplay(weld::Builder& rBuilder); + + void DisplayListBox( bool bDisplayListBox ); + + void SetSelectHdl( const Link& rLink ); + + void Clear(); + void InsertEntry( const OUString& rStr ); + void SelectEntryPos( sal_uInt16 nPos ); + + sal_uInt16 GetEntryCount() const; + + OUString GetEntry( sal_uInt16 nPos ) const; + OUString GetSelectedEntry() const; + + DECL_LINK( SelectSuggestionListBoxHdl, weld::TreeView&, void ); + DECL_LINK( SelectSuggestionValueSetHdl, ValueSet*, void ); + void SelectSuggestionHdl(bool bListBox); + + void SetHelpIds(); + + void set_size_request(int nWidth, int nHeight) + { + m_xValueSetWin->set_size_request(nWidth, nHeight); + m_xListBox->set_size_request(nWidth, nHeight); + } + + private: + void implUpdateDisplay(); + weld::Widget& implGetCurrentControl(); + + private: + bool m_bDisplayListBox; //otherwise ValueSet + bool m_bInSelectionUpdate; + Link m_aSelectLink; + + std::unique_ptr m_xValueSet; + std::unique_ptr m_xValueSetWin; + std::unique_ptr m_xListBox; + }; + + class RubyRadioButton; + + class HangulHanjaConversionDialog : public weld::GenericDialogController + { + private: + /** are we working for a document? This is normally true, but in case + the user uses the "find" functionality, we switch to working + with what the user entered, which then does not have any relation to + the document anymore. Some functionality must be disabled then */ + bool m_bDocumentMode; + + Link m_aOptionsChangedLink; + Link m_aClickByCharacterLink; + + std::unique_ptr m_xFind; + std::unique_ptr m_xIgnore; + std::unique_ptr m_xIgnoreAll; + std::unique_ptr m_xReplace; + std::unique_ptr m_xReplaceAll; + std::unique_ptr m_xOptions; + std::unique_ptr m_xSuggestions; + std::unique_ptr m_xSimpleConversion; + std::unique_ptr m_xHangulBracketed; + std::unique_ptr m_xHanjaBracketed; + std::unique_ptr m_xWordInput; + std::unique_ptr m_xOriginalWord; + std::unique_ptr m_xHanjaAbove; + std::unique_ptr m_xHanjaBelow; + std::unique_ptr m_xHangulAbove; + std::unique_ptr m_xHangulBelow; + std::unique_ptr m_xHangulOnly; + std::unique_ptr m_xHanjaOnly; + std::unique_ptr m_xReplaceByChar; + public: + HangulHanjaConversionDialog(weld::Window* pParent); + virtual ~HangulHanjaConversionDialog() override; + + public: + void SetOptionsChangedHdl( const Link& _rHdl ); + void SetIgnoreHdl( const Link& _rHdl ); + void SetIgnoreAllHdl( const Link& _rHdl ); + void SetChangeHdl( const Link& _rHdl ); + void SetChangeAllHdl( const Link& _rHdl ); + + void SetClickByCharacterHdl( const Link& _rHdl ); + void SetConversionFormatChangedHdl( const Link& _rHdl ); + void SetFindHdl( const Link& _rHdl ); + + OUString GetCurrentString( ) const; + void SetCurrentString( + const OUString& _rNewString, + const css::uno::Sequence< OUString >& _rSuggestions, + bool _bOriginatesFromDocument + ); + + void FocusSuggestion( ); + + /// retrieves the current suggestion + OUString GetCurrentSuggestion( ) const; + + void SetConversionFormat( editeng::HangulHanjaConversion::ConversionFormat _eType ); + editeng::HangulHanjaConversion::ConversionFormat GetConversionFormat( ) const; + + void SetByCharacter( bool _bByCharacter ); + void SetConversionDirectionState( bool _bTryBothDirections, editeng::HangulHanjaConversion::ConversionDirection _ePrimaryConversionDirection ); + + /// should text which does not match the primary conversion direction be ignored? + bool GetUseBothDirections( ) const; + + /** get current conversion direction to use + (return argument if GetUseBothDirections is true) */ + editeng::HangulHanjaConversion::ConversionDirection GetDirection( editeng::HangulHanjaConversion::ConversionDirection eDefaultDirection ) const; + + /// enables or disables the checkboxes for ruby formatted replacements + void EnableRubySupport( bool bVal ); + + private: + DECL_LINK( OnOption, weld::Button&, void ); + DECL_LINK( OnSuggestionModified, weld::Entry&, void ); + DECL_LINK( OnSuggestionSelected, SuggestionDisplay&, void ); + DECL_LINK( OnConversionDirectionClicked, weld::ToggleButton&, void ); + DECL_LINK( ClickByCharacterHdl, weld::ToggleButton&, void ); + + /// fill the suggestion list box with suggestions for the actual input + void FillSuggestions( const css::uno::Sequence< OUString >& _rSuggestions ); + }; + + + typedef std::vector< css::uno::Reference< css::linguistic2::XConversionDictionary > > HHDictList; + + class HangulHanjaOptionsDialog : public weld::GenericDialogController + { + private: + HHDictList m_aDictList; + css::uno::Reference< css::linguistic2::XConversionDictionaryList > m_xConversionDictionaryList; + + std::unique_ptr m_xDictsLB; + std::unique_ptr m_xIgnorepostCB; + std::unique_ptr m_xShowrecentlyfirstCB; + std::unique_ptr m_xAutoreplaceuniqueCB; + std::unique_ptr m_xNewPB; + std::unique_ptr m_xEditPB; + std::unique_ptr m_xDeletePB; + std::unique_ptr m_xOkPB; + + DECL_LINK( OkHdl, weld::Button&, void ); + DECL_LINK( DictsLB_SelectHdl, weld::TreeView&, void ); + DECL_LINK( NewDictHdl, weld::Button&, void ); + DECL_LINK( EditDictHdl, weld::Button&, void ); + DECL_LINK( DeleteDictHdl, weld::Button&, void ); + + void Init(); ///< reads settings from core and init controls + public: + HangulHanjaOptionsDialog(weld::Window* pParent); + virtual ~HangulHanjaOptionsDialog() override; + + void AddDict( const OUString& _rName, bool _bChecked ); + }; + + class HangulHanjaNewDictDialog : public weld::GenericDialogController + { + private: + bool m_bEntered; + + std::unique_ptr m_xOkBtn; + std::unique_ptr m_xDictNameED; + + DECL_LINK(OKHdl, weld::Button&, void); + DECL_LINK(ModifyHdl, weld::Entry&, void); + public: + HangulHanjaNewDictDialog(weld::Window* pParent); + virtual ~HangulHanjaNewDictDialog() override; + + bool GetName( OUString& _rRetName ) const; + }; + + class SuggestionList; + class HangulHanjaEditDictDialog; + + class SuggestionEdit + { + private: + HangulHanjaEditDictDialog* m_pParent; + SuggestionEdit* m_pPrev; + SuggestionEdit* m_pNext; + weld::ScrolledWindow* m_pScrollBar; + std::unique_ptr m_xEntry; + + bool ShouldScroll( bool _bUp ) const; + void DoJump( bool _bUp ); + public: + SuggestionEdit(std::unique_ptr xEntry, HangulHanjaEditDictDialog* pParent); + DECL_LINK(KeyInputHdl, const KeyEvent&, bool); + void init(weld::ScrolledWindow* pScrollBar, SuggestionEdit* pPrev, SuggestionEdit* pNext); + + void grab_focus() { m_xEntry->grab_focus(); } + OUString get_text() const { return m_xEntry->get_text(); } + void set_text(const OUString& rText) { m_xEntry->set_text(rText); } + void connect_changed(const Link& rLink) { m_xEntry->connect_changed(rLink); } + }; + + class HangulHanjaEditDictDialog : public weld::GenericDialogController + { + private: + const OUString m_aEditHintText; + HHDictList& m_rDictList; + sal_uInt32 m_nCurrentDict; + + OUString m_aOriginal; + std::unique_ptr m_xSuggestions; + + sal_uInt16 m_nTopPos; + bool m_bModifiedSuggestions; + bool m_bModifiedOriginal; + + std::unique_ptr m_xBookLB; + std::unique_ptr m_xOriginalLB; + std::unique_ptr m_xEdit1; + std::unique_ptr m_xEdit2; + std::unique_ptr m_xEdit3; + std::unique_ptr m_xEdit4; + std::unique_ptr m_xContents; + std::unique_ptr m_xScrollSB; + std::unique_ptr m_xNewPB; + std::unique_ptr m_xDeletePB; + + DECL_LINK( OriginalModifyHdl, weld::ComboBox&, void ); + DECL_LINK( ScrollHdl, weld::ScrolledWindow&, void ); + DECL_LINK( EditModifyHdl1, weld::Entry&, void ); + DECL_LINK( EditModifyHdl2, weld::Entry&, void ); + DECL_LINK( EditModifyHdl3, weld::Entry&, void ); + DECL_LINK( EditModifyHdl4, weld::Entry&, void ); + + DECL_LINK( BookLBSelectHdl, weld::ComboBox&, void ); + DECL_LINK( NewPBPushHdl, weld::Button&, void ); + DECL_LINK( DeletePBPushHdl, weld::Button&, void ); + + void InitEditDictDialog(sal_uInt32 nSelDict); + void UpdateOriginalLB(); + void UpdateSuggestions(); + void UpdateButtonStates(); + + void SetEditText( SuggestionEdit& rEdit, sal_uInt16 nEntryNum ); + void EditModify( const weld::Entry* pEdit, sal_uInt8 nEntryOffset ); + + bool DeleteEntryFromDictionary( const css::uno::Reference< css::linguistic2::XConversionDictionary >& xDict ); + + public: + HangulHanjaEditDictDialog(weld::Window* pParent, HHDictList& rDictList, sal_uInt32 nSelDict); + virtual ~HangulHanjaEditDictDialog() override; + + void UpdateScrollbar(); + }; +} + +#endif // SVX_HANGUL_HANJA_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/headertablistbox.hxx b/cui/source/inc/headertablistbox.hxx new file mode 100644 index 000000000..c4c65feac --- /dev/null +++ b/cui/source/inc/headertablistbox.hxx @@ -0,0 +1,42 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_CUI_SOURCE_INC_HEADERTABLISTBOX_HXX +#define INCLUDED_CUI_SOURCE_INC_HEADERTABLISTBOX_HXX + +#include + +class MacroEventListBox final +{ +private: + std::unique_ptr m_xTreeView; +public: + MacroEventListBox(std::unique_ptr xTreeView); + void set_sensitive(bool bSensitive) { m_xTreeView->set_sensitive(bSensitive); } + void show() { m_xTreeView->show(); } + + weld::TreeView& GetListBox() + { + return *m_xTreeView; + } +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/helpids.h b/cui/source/inc/helpids.h new file mode 100644 index 000000000..3ae4404c1 --- /dev/null +++ b/cui/source/inc/helpids.h @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_HELPID_HRC +#define INCLUDED_CUI_SOURCE_INC_HELPID_HRC + +#define HID_OPTIONS_COLORCONFIG_SAVE_SCHEME "CUI_HID_OPTIONS_COLORCONFIG_SAVE_SCHEME" +#define HID_OFA_FONT_SUBST_CLB "CUI_HID_OFA_FONT_SUBST_CLB" +#define HID_DBPATH_CTL_PATH "CUI_HID_DBPATH_CTL_PATH" +#define HID_DBPATH_HEADERBAR "CUI_HID_DBPATH_HEADERBAR" +#define HID_OFADLG_TREELISTBOX "CUI_HID_OFADLG_TREELISTBOX" +#define HID_SVX_CONFIG_TOOLBAR "CUI_HID_SVX_CONFIG_TOOLBAR" +#define HID_SVX_CONFIG_TOOLBAR_CONTENTS "CUI_HID_SVX_CONFIG_TOOLBAR_CONTENTS" +#define HID_SVX_CONFIG_NOTEBOOKBAR_CONTENTS "CUI_HID_SVX_CONFIG_NOTEBOOKBAR_CONTENTS" +#define HID_HANGULDLG_SUGGESTIONS_GRID "CUI_HID_HANGULDLG_SUGGESTIONS_GRID" +#define HID_HANGULDLG_SUGGESTIONS_LIST "CUI_HID_HANGULDLG_SUGGESTIONS_LIST" +#define HID_SVX_CONFIG_NAME_SUBMENU "CUI_HID_SVX_CONFIG_NAME_SUBMENU" +#define HID_SVX_CONFIG_RENAME_MENU "CUI_HID_SVX_CONFIG_RENAME_MENU" +#define HID_SVX_CONFIG_RENAME_MENU_ITEM "CUI_HID_SVX_CONFIG_RENAME_MENU_ITEM" +#define HID_SVX_CONFIG_RENAME_TOOLBAR "CUI_HID_SVX_CONFIG_RENAME_TOOLBAR" +#define HID_SVX_CONFIG_RENAME_TOOLBAR_ITEM "CUI_HID_SVX_CONFIG_RENAME_TOOLBAR_ITEM" +#define HID_SVX_UP_TOOLBAR_ITEM "CUI_HID_SVX_UP_TOOLBAR_ITEM" +#define HID_SVX_DOWN_TOOLBAR_ITEM "CUI_HID_SVX_DOWN_TOOLBAR_ITEM" +#define HID_SVX_SAVE_IN "CUI_HID_SVX_SAVE_IN" +#define HID_SVX_TOPLEVELLISTBOX "CUI_HID_SVX_TOPLEVELLISTBOX" +#define HID_SVX_DESCFIELD "CUI_HID_SVX_DESCFIELD" +#define HID_MACRO_HEADERTABLISTBOX "CUI_HID_MACRO_HEADERTABLISTBOX" + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/hldocntp.hxx b/cui/source/inc/hldocntp.hxx new file mode 100644 index 000000000..719968853 --- /dev/null +++ b/cui/source/inc/hldocntp.hxx @@ -0,0 +1,64 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_HLDOCNTP_HXX +#define INCLUDED_CUI_SOURCE_INC_HLDOCNTP_HXX + +#include "hltpbase.hxx" + +/************************************************************************* +|* +|* Tabpage : Hyperlink - New Document +|* +\************************************************************************/ +class SvxHyperlinkNewDocTp : public SvxHyperlinkTabPageBase +{ +private: + std::unique_ptr m_xRbtEditNow; + std::unique_ptr m_xRbtEditLater; + std::unique_ptr m_xCbbPath; + std::unique_ptr m_xBtCreate; + std::unique_ptr m_xLbDocTypes; + + bool ImplGetURLObject( const OUString& rPath, const OUString& rBase, INetURLObject& aURLObject ) const; + void FillDocumentList (); + + DECL_LINK (ClickNewHdl_Impl, weld::Button&, void ); + DECL_STATIC_LINK(SvxHyperlinkNewDocTp, DispatchDocument, void*, void); + +protected: + void FillDlgFields(const OUString& rStrURL) override; + void GetCurentItemData ( OUString& rStrURL, OUString& aStrName, + OUString& aStrIntName, OUString& aStrFrame, + SvxLinkInsertMode& eMode ) override; + +public: + SvxHyperlinkNewDocTp(weld::Container* pParent, SvxHpLinkDlg* pDlg, const SfxItemSet* pItemSet); + virtual ~SvxHyperlinkNewDocTp () override; + + static std::unique_ptr Create(weld::Container* pWindow, SvxHpLinkDlg* pDlg, const SfxItemSet* pItemSet); + + virtual bool AskApply () override; + virtual void DoApply () override; + + virtual void SetInitFocus() override; +}; + +#endif // INCLUDED_CUI_SOURCE_INC_HLDOCNTP_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/hldoctp.hxx b/cui/source/inc/hldoctp.hxx new file mode 100644 index 000000000..9f5f8395f --- /dev/null +++ b/cui/source/inc/hldoctp.hxx @@ -0,0 +1,76 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_HLDOCTP_HXX +#define INCLUDED_CUI_SOURCE_INC_HLDOCTP_HXX + +#include "hltpbase.hxx" + +/************************************************************************* +|* +|* Tabpage : Hyperlink - Document +|* +\************************************************************************/ +class SvxHyperlinkDocTp final : public SvxHyperlinkTabPageBase +{ +private: + std::unique_ptr m_xCbbPath; + std::unique_ptr m_xBtFileopen; + std::unique_ptr m_xEdTarget; + std::unique_ptr m_xFtFullURL; + std::unique_ptr m_xBtBrowse; + + OUString maStrURL; + + bool m_bMarkWndOpen; + + DECL_LINK (ClickFileopenHdl_Impl, weld::Button&, void ); + DECL_LINK (ClickTargetHdl_Impl, weld::Button&, void ); + + DECL_LINK (ModifiedPathHdl_Impl, weld::ComboBox&, void ); ///< Contents of combobox "Path" modified + DECL_LINK (ModifiedTargetHdl_Impl, weld::Entry&, void ); ///< Contents of editfield "Target" modified + + DECL_LINK( LostFocusPathHdl_Impl, weld::Widget&, void ); ///< Combobox "path" lost its focus + + DECL_LINK( TimeoutHdl_Impl, Timer *, void ); ///< Handler for timer -timeout + + enum class EPathType { Invalid, ExistsFile }; + static EPathType GetPathType ( const OUString& rStrPath ); + + void FillDlgFields(const OUString& rStrURL) override; + void GetCurentItemData ( OUString& rStrURL, OUString& aStrName, + OUString& aStrIntName, OUString& aStrFrame, + SvxLinkInsertMode& eMode ) override; + virtual bool ShouldOpenMarkWnd () override {return m_bMarkWndOpen;} + virtual void SetMarkWndShouldOpen (bool bOpen) override {m_bMarkWndOpen=bOpen;} + OUString GetCurrentURL() const; + +public: + SvxHyperlinkDocTp(weld::Container* pParent, SvxHpLinkDlg* pDlg, const SfxItemSet* pItemSet); + virtual ~SvxHyperlinkDocTp() override; + + static std::unique_ptr Create(weld::Container* pWindow, SvxHpLinkDlg* pDlg, const SfxItemSet* pItemSet); + + virtual void SetMarkStr ( const OUString& aStrMark ) override; + + virtual void SetInitFocus() override; +}; + +#endif // INCLUDED_CUI_SOURCE_INC_HLDOCTP_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/hlinettp.hxx b/cui/source/inc/hlinettp.hxx new file mode 100644 index 000000000..115e1e428 --- /dev/null +++ b/cui/source/inc/hlinettp.hxx @@ -0,0 +1,91 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_HLINETTP_HXX +#define INCLUDED_CUI_SOURCE_INC_HLINETTP_HXX + +#include "cuihyperdlg.hxx" +#include "hltpbase.hxx" + +/************************************************************************* +|* +|* Tabpage : Hyperlink - Internet +|* +\************************************************************************/ + +class SvxHyperlinkInternetTp : public SvxHyperlinkTabPageBase +{ +private: + OUString maStrOldUser; + OUString maStrOldPassword; + + bool m_bMarkWndOpen; + + std::unique_ptr m_xRbtLinktypInternet; + std::unique_ptr m_xRbtLinktypFTP; + std::unique_ptr m_xCbbTarget; + std::unique_ptr m_xFtTarget; + std::unique_ptr m_xFtLogin; + std::unique_ptr m_xEdLogin; + std::unique_ptr m_xFtPassword; + std::unique_ptr m_xEdPassword; + std::unique_ptr m_xCbAnonymous; + + DECL_LINK( Click_SmartProtocol_Impl, weld::Button&, void ); ///< Radiobutton clicked: Type HTTP or FTP + DECL_LINK( ClickAnonymousHdl_Impl, weld::Button&, void ); ///< Checkbox : Anonymous User + DECL_LINK( ModifiedLoginHdl_Impl, weld::Entry&, void ); ///< Contents of editfield "Login" modified + DECL_LINK( LostFocusTargetHdl_Impl, weld::Widget&, void ); ///< Combobox "Target" lost its focus + DECL_LINK( ModifiedTargetHdl_Impl, weld::ComboBox&, void ); ///< Contents of editfield "Target" modified + + DECL_LINK( TimeoutHdl_Impl, Timer *, void); ///< Handler for timer -timeout + + + void SetScheme(const OUString& rScheme); + void RemoveImproperProtocol(const OUString& rProperScheme); + OUString GetSchemeFromButtons() const; + INetProtocol GetSmartProtocolFromButtons() const; + + OUString CreateAbsoluteURL() const; + + void setAnonymousFTPUser(); + void setFTPUser(const OUString& rUser, const OUString& rPassword); + void RefreshMarkWindow(); + +protected: + virtual void FillDlgFields(const OUString& rStrURL) override; + virtual void GetCurentItemData ( OUString& rStrURL, OUString& aStrName, + OUString& aStrIntName, OUString& aStrFrame, + SvxLinkInsertMode& eMode ) override; + virtual bool ShouldOpenMarkWnd () override {return ( m_bMarkWndOpen && m_xRbtLinktypInternet->get_active() );} + virtual void SetMarkWndShouldOpen (bool bOpen) override {m_bMarkWndOpen=bOpen;} + +public: + SvxHyperlinkInternetTp(weld::Container* pParent, SvxHpLinkDlg* pDlg, const SfxItemSet* pItemSet); + virtual ~SvxHyperlinkInternetTp() override; + + static std::unique_ptr Create(weld::Container* pWindow, SvxHpLinkDlg* pDlg, const SfxItemSet* pItemSet); + + virtual void SetMarkStr ( const OUString& aStrMark ) override; + + virtual void SetInitFocus() override; +}; + + +#endif // INCLUDED_CUI_SOURCE_INC_HLINETTP_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/hlmailtp.hxx b/cui/source/inc/hlmailtp.hxx new file mode 100644 index 000000000..c137a3cf1 --- /dev/null +++ b/cui/source/inc/hlmailtp.hxx @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_HLMAILTP_HXX +#define INCLUDED_CUI_SOURCE_INC_HLMAILTP_HXX + +#include "hltpbase.hxx" + +/************************************************************************* +|* +|* Tabpage : Hyperlink - Mail +|* +\************************************************************************/ + +class SvxHyperlinkMailTp : public SvxHyperlinkTabPageBase +{ +private: + std::unique_ptr m_xCbbReceiver; + std::unique_ptr m_xBtAdrBook; + std::unique_ptr m_xFtSubject; + std::unique_ptr m_xEdSubject; + + DECL_STATIC_LINK(SvxHyperlinkMailTp, ClickAdrBookHdl_Impl, weld::Button&, void); + ///< Button : Address book + DECL_LINK (ModifiedReceiverHdl_Impl, weld::ComboBox&, void ); ///< Combobox "receiver" modified + + void SetScheme(const OUString& rScheme); + void RemoveImproperProtocol(const OUString& aProperScheme); + + OUString CreateAbsoluteURL() const; + +protected: + virtual void FillDlgFields(const OUString& rStrURL) override; + virtual void GetCurentItemData ( OUString& rStrURL, OUString& aStrName, + OUString& aStrIntName, OUString& aStrFrame, + SvxLinkInsertMode& eMode ) override; + +public: + SvxHyperlinkMailTp(weld::Container* pParent, SvxHpLinkDlg* pDlg, const SfxItemSet* pItemSet); + virtual ~SvxHyperlinkMailTp() override; + + static std::unique_ptr Create(weld::Container* pWindow, SvxHpLinkDlg* pDlg, const SfxItemSet* pItemSet); + + virtual void SetInitFocus() override; +}; + + +#endif // INCLUDED_CUI_SOURCE_INC_HLMAILTP_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/hlmarkwn.hxx b/cui/source/inc/hlmarkwn.hxx new file mode 100644 index 000000000..9dd566a74 --- /dev/null +++ b/cui/source/inc/hlmarkwn.hxx @@ -0,0 +1,72 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_CUI_SOURCE_INC_HLMARKWN_HXX +#define INCLUDED_CUI_SOURCE_INC_HLMARKWN_HXX + +#include +#include + +class SvxHyperlinkTabPageBase; + +//# # +//# Window-Class # +//# # +class SvxHlinkDlgMarkWnd : public weld::GenericDialogController +{ +private: + friend class SvxHlmarkTreeLBox; + + SvxHyperlinkTabPageBase* mpParent; + + sal_uInt16 mnError; + + std::unique_ptr mxBtApply; + std::unique_ptr mxBtClose; + std::unique_ptr mxLbTree; + std::unique_ptr mxError; + + void ErrorChanged(); + +protected: + bool RefreshFromDoc( const OUString& aURL ); + void RestoreLastSelection(); + + std::unique_ptr FindEntry(const OUString& aStrName); + void ClearTree(); + int FillTree( const css::uno::Reference< css::container::XNameAccess >& xLinks, const weld::TreeIter* pParentEntry =nullptr ); + + DECL_LINK( ClickApplyHdl_Impl, weld::Button&, void ); + DECL_LINK( DoubleClickApplyHdl_Impl, weld::TreeView&, bool ); + DECL_LINK( ClickCloseHdl_Impl, weld::Button&, void ); + +public: + SvxHlinkDlgMarkWnd(weld::Window* pParentDialog, SvxHyperlinkTabPageBase *pParentPage); + virtual ~SvxHlinkDlgMarkWnd() override; + + void MoveTo(const Point& rNewPos); + void RefreshTree(const OUString& aStrURL); + bool SelectEntry(const OUString& aStrMark); + + sal_uInt16 SetError( sal_uInt16 nError); +}; + +#endif // INCLUDED_CUI_SOURCE_INC_HLMARKWN_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/hlmarkwn_def.hxx b/cui/source/inc/hlmarkwn_def.hxx new file mode 100644 index 000000000..6caa0c510 --- /dev/null +++ b/cui/source/inc/hlmarkwn_def.hxx @@ -0,0 +1,29 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_CUI_SOURCE_INC_HLMARKWN_DEF_HXX +#define INCLUDED_CUI_SOURCE_INC_HLMARKWN_DEF_HXX + +#define LERR_NOERROR 0 +#define LERR_NOENTRIES 1 +#define LERR_DOCNOTOPEN 2 + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/hltpbase.hxx b/cui/source/inc/hltpbase.hxx new file mode 100644 index 000000000..0860fff0e --- /dev/null +++ b/cui/source/inc/hltpbase.hxx @@ -0,0 +1,138 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_HLTPBASE_HXX +#define INCLUDED_CUI_SOURCE_INC_HLTPBASE_HXX + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "hlmarkwn.hxx" +#include "iconcdlg.hxx" + +/// ComboBox-Control for URL's with History and Autocompletion +class SvxHyperURLBox : public SvtURLBox, public DropTargetHelper +{ +protected: + virtual sal_Int8 AcceptDrop( const AcceptDropEvent& rEvt ) override; + virtual sal_Int8 ExecuteDrop( const ExecuteDropEvent& rEvt ) override; + +public: + SvxHyperURLBox(std::unique_ptr xWidget); +}; + +/// Tabpage : Basisclass +class SvxHyperlinkTabPageBase : public IconChoicePage +{ +private: + std::unique_ptr mxCbbFrame; + std::unique_ptr mxLbForm; + std::unique_ptr mxEdIndication; + std::unique_ptr mxEdText; + std::unique_ptr mxBtScript; + std::unique_ptr mxFormLabel; + std::unique_ptr mxFrameLabel; + + bool mbIsCloseDisabled; + + css::uno::Reference< css::frame::XFrame > + mxDocumentFrame; + +protected: + SvxHpLinkDlg* mpDialog; + + bool mbStdControlsInit; + + OUString maStrInitURL; + + Timer maTimer; + + TopLevelWindowLocker maBusy; + + std::shared_ptr mxMarkWnd; + + void InitStdControls (); + void FillStandardDlgFields ( const SvxHyperlinkItem* pHyperlinkItem ); + virtual void FillDlgFields(const OUString& rStrURL) = 0; + virtual void GetCurentItemData ( OUString& rStrURL, OUString& aStrName, + OUString& aStrIntName, OUString& aStrFrame, + SvxLinkInsertMode& eMode ) = 0; + + void GetDataFromCommonFields( OUString& aStrName, + OUString& aStrIntName, OUString& aStrFrame, + SvxLinkInsertMode& eMode ); + + DECL_LINK (ClickScriptHdl_Impl, weld::Button&, void ); ///< Button : Script + + static OUString GetSchemeFromURL( const OUString& rStrURL ); + + void DisableClose( bool _bDisable ); + +public: + SvxHyperlinkTabPageBase ( + weld::Container* pParent, + SvxHpLinkDlg* pDlg, + const OUString& rUIXMLDescription, + const OString& rID, + const SfxItemSet* pItemSet + ); + virtual ~SvxHyperlinkTabPageBase () override; + + void SetDocumentFrame( + const css::uno::Reference< css::frame::XFrame >& rxDocumentFrame ) + { + mxDocumentFrame = rxDocumentFrame; + } + + virtual bool AskApply (); + virtual void DoApply (); + virtual void SetInitFocus(); + virtual void SetMarkStr ( const OUString& aStrMark ); + virtual void Reset( const SfxItemSet& ) override; + virtual bool FillItemSet( SfxItemSet* ) override; + virtual void ActivatePage( const SfxItemSet& rItemSet ) override; + virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override; + + bool IsMarkWndVisible() const { return static_cast(mxMarkWnd); } + void MoveToExtraWnd ( Point aNewPos ); + + virtual bool QueryClose() override; + +protected: + virtual bool ShouldOpenMarkWnd(); + virtual void SetMarkWndShouldOpen(bool bOpen); + + void ShowMarkWnd(); + void HideMarkWnd(); + + SfxDispatcher* GetDispatcher() const; + + HyperDialogEvent GetMacroEvents() const; + SvxMacroTableDtor* GetMacroTable(); +}; + +#endif // INCLUDED_CUI_SOURCE_INC_HLTPBASE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/hyphen.hxx b/cui/source/inc/hyphen.hxx new file mode 100644 index 000000000..fdf65cd4b --- /dev/null +++ b/cui/source/inc/hyphen.hxx @@ -0,0 +1,88 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_HYPHEN_HXX +#define INCLUDED_CUI_SOURCE_INC_HYPHEN_HXX + +#include + +#include +#include +#include +#include +#include + +class SvxSpellWrapper; + +class SvxHyphenWordDialog : public SfxDialogController +{ + OUString m_aLabel; + SvxSpellWrapper *const m_pHyphWrapper; + css::uno::Reference< css::linguistic2::XHyphenator > m_xHyphenator; + css::uno::Reference< css::linguistic2::XPossibleHyphens > m_xPossHyph; + OUString m_aEditWord; // aEditWord and aWordEdit.GetText() differ only by the character for the current selected hyphenation position + OUString m_aActWord; // actual word to be hyphenated + LanguageType m_nActLanguage; // and its language + sal_Int16 m_nMaxHyphenationPos; // right most valid hyphenation pos + sal_Int32 m_nOldPos; + sal_Int32 m_nHyphenationPositionsOffset; + int m_nWordEditWidth; + bool m_bBusy; + + std::unique_ptr m_xWordEdit; + std::unique_ptr m_xLeftBtn; + std::unique_ptr m_xRightBtn; + std::unique_ptr m_xOkBtn; + std::unique_ptr m_xContBtn; + std::unique_ptr m_xDelBtn; + std::unique_ptr m_xHyphAll; + std::unique_ptr m_xCloseBtn; + + void EnableLRBtn_Impl(); + OUString EraseUnusableHyphens_Impl(); + + void InitControls_Impl(); + void ContinueHyph_Impl( sal_Int32 nInsPos = -1 ); // continue by default + + void select_region(int nStart, int nEnd); + + DECL_LINK(Left_Impl, weld::Button&, void); + DECL_LINK(Right_Impl, weld::Button&, void); + DECL_LINK(CutHdl_Impl, weld::Button&, void); + DECL_LINK(ContinueHdl_Impl, weld::Button&, void); + DECL_LINK(DeleteHdl_Impl, weld::Button&, void); + DECL_LINK(HyphenateAllHdl_Impl, weld::Button&, void); + DECL_LINK(CancelHdl_Impl, weld::Button&, void); + DECL_LINK(GetFocusHdl_Impl, weld::Widget&, void); + DECL_LINK(CursorChangeHdl_Impl, weld::Entry&, void); + +public: + SvxHyphenWordDialog(const OUString &rWord, LanguageType nLang, + weld::Window* pParent, + css::uno::Reference const &xHyphen, + SvxSpellWrapper* pWrapper); + virtual ~SvxHyphenWordDialog() override; + + void SetWindowTitle( LanguageType nLang ); + bool SelLeft(); + bool SelRight(); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/iconcdlg.hxx b/cui/source/inc/iconcdlg.hxx new file mode 100644 index 000000000..230c22be7 --- /dev/null +++ b/cui/source/inc/iconcdlg.hxx @@ -0,0 +1,84 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_ICONCDLG_HXX +#define INCLUDED_CUI_SOURCE_INC_ICONCDLG_HXX + +#include +#include + +// forward-declarations +struct IconChoicePageData; +class SvxHpLinkDlg; +class IconChoicePage; +class SfxItemPool; +class SfxItemSet; + +// Create-Function +typedef std::unique_ptr (*CreatePage)(weld::Container* pParent, SvxHpLinkDlg* pDlg, const SfxItemSet* pAttrSet); + +/// Data-structure for pages in dialog +struct IconChoicePageData +{ + OString sId; + std::unique_ptr xPage; ///< the TabPage itself + bool bRefresh; ///< Flag: page has to be newly initialized + + // constructor + IconChoicePageData(const OString& rId, std::unique_ptr xInPage) + : sId(rId) + , xPage(std::move(xInPage)) + , bRefresh(false) + {} +}; + +class IconChoicePage +{ +protected: + std::unique_ptr xBuilder; + std::unique_ptr xContainer; + +private: + const SfxItemSet* pSet; + bool bHasExchangeSupport; + +protected: + + IconChoicePage(weld::Container* pParent, const OUString& rUIXMLDescription, const OString& rID, const SfxItemSet* pItemSet); + +public: + virtual ~IconChoicePage(); + + OString GetHelpId() const { return xContainer->get_help_id(); } + + const SfxItemSet& GetItemSet() const { return *pSet; } + + virtual bool FillItemSet( SfxItemSet* ) = 0; + virtual void Reset( const SfxItemSet& ) = 0; + + bool HasExchangeSupport() const { return bHasExchangeSupport; } + void SetExchangeSupport() { bHasExchangeSupport = true; } + + virtual void ActivatePage( const SfxItemSet& ); + virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ); + virtual bool QueryClose(); +}; + +#endif // INCLUDED_CUI_SOURCE_INC_ICONCDLG_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/insdlg.hxx b/cui/source/inc/insdlg.hxx new file mode 100644 index 000000000..7c17022ed --- /dev/null +++ b/cui/source/inc/insdlg.hxx @@ -0,0 +1,117 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_INSDLG_HXX +#define INCLUDED_CUI_SOURCE_INC_INSDLG_HXX + +#include +#include +#include + +#include +#include +#include + +class INetURLObject; + +class InsertObjectDialog_Impl : public weld::GenericDialogController +{ +protected: + css::uno::Reference < css::embed::XEmbeddedObject > m_xObj; + const css::uno::Reference < css::embed::XStorage > m_xStorage; + comphelper::EmbeddedObjectContainer aCnt; + + InsertObjectDialog_Impl(weld::Window * pParent, + const OUString& rUIXMLDescription, const OString& rID, + const css::uno::Reference < css::embed::XStorage >& xStorage); +public: + const css::uno::Reference& GetObject() const { return m_xObj; } + virtual css::uno::Reference GetIconIfIconified(OUString* pGraphicMediaType); + void SetHelpId(const OString& rHelpId) { m_xDialog->set_help_id(rHelpId); } + virtual bool IsCreateNew() const; +}; + +class SvInsertOleDlg : public InsertObjectDialog_Impl +{ + const SvObjectServerList* m_pServers; + + css::uno::Sequence< sal_Int8 > m_aIconMetaFile; + OUString m_aIconMediaType; + + std::unique_ptr m_xRbNewObject; + std::unique_ptr m_xRbObjectFromfile; + std::unique_ptr m_xObjectTypeFrame; + std::unique_ptr m_xLbObjecttype; + std::unique_ptr m_xFileFrame; + std::unique_ptr m_xEdFilepath; + std::unique_ptr m_xBtnFilepath; + std::unique_ptr m_xCbFilelink; + std::unique_ptr m_xCbAsIcon; + + DECL_LINK(DoubleClickHdl, weld::TreeView&, bool); + DECL_LINK(BrowseHdl, weld::Button&, void); + DECL_LINK(RadioHdl, weld::Button&, void); + bool IsCreateNew() const override { return m_xRbNewObject->get_active(); } + +public: + SvInsertOleDlg(weld::Window* pParent, + const css::uno::Reference < css::embed::XStorage >& xStorage, + const SvObjectServerList* pServers ); + virtual short run() override; + + /// get replacement for the iconified embedded object and the mediatype of the replacement + css::uno::Reference< css::io::XInputStream > GetIconIfIconified( OUString* pGraphicMediaType ) override; +}; + +class SfxInsertFloatingFrameDialog : public InsertObjectDialog_Impl +{ +private: + std::unique_ptr m_xEDName; + std::unique_ptr m_xEDURL; + std::unique_ptr m_xBTOpen; + + std::unique_ptr m_xRBScrollingOn; + std::unique_ptr m_xRBScrollingOff; + std::unique_ptr m_xRBScrollingAuto; + + std::unique_ptr m_xRBFrameBorderOn; + std::unique_ptr m_xRBFrameBorderOff; + + std::unique_ptr m_xFTMarginWidth; + std::unique_ptr m_xNMMarginWidth; + std::unique_ptr m_xCBMarginWidthDefault; + std::unique_ptr m_xFTMarginHeight; + std::unique_ptr m_xNMMarginHeight; + std::unique_ptr m_xCBMarginHeightDefault; + + DECL_LINK(OpenHdl, weld::Button&, void); + DECL_LINK(CheckHdl, weld::Button&, void); + + void Init(); + +public: + SfxInsertFloatingFrameDialog(weld::Window *pParent, + const css::uno::Reference& xStorage); + SfxInsertFloatingFrameDialog(weld::Window* pParent, + const css::uno::Reference& xObj); + virtual short run() override; +}; + +#endif // INCLUDED_CUI_SOURCE_INC_INSDLG_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/insrc.hxx b/cui/source/inc/insrc.hxx new file mode 100644 index 000000000..ea6428eb3 --- /dev/null +++ b/cui/source/inc/insrc.hxx @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_INSRC_HXX +#define INCLUDED_CUI_SOURCE_INC_INSRC_HXX + +#include +#include +#include + +class SvxInsRowColDlg : public SvxAbstractInsRowColDlg, public weld::GenericDialogController +{ +private: + std::unique_ptr m_xCountEdit; + std::unique_ptr m_xBeforeBtn; + std::unique_ptr m_xAfterBtn; + +public: + SvxInsRowColDlg(weld::Window* pParent, bool bCol, const OString& rHelpId); + + virtual short Execute() override; + + virtual bool isInsertBefore() const override; + virtual sal_uInt16 getInsertCount() const override; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/labdlg.hxx b/cui/source/inc/labdlg.hxx new file mode 100644 index 000000000..d759df2e6 --- /dev/null +++ b/cui/source/inc/labdlg.hxx @@ -0,0 +1,119 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_LABDLG_HXX +#define INCLUDED_CUI_SOURCE_INC_LABDLG_HXX + +#include +#include +#include +#include +#include +#include + +class SdrView; + +// class SvxCaptionTabPage ----------------------------------------------- + +const sal_uInt16 CAPTYPE_BITMAPS_COUNT = 3; + +class SvxCaptionTabPage : public SfxTabPage +{ +private: + static const sal_uInt16 pCaptionRanges[]; + + Image m_aBmpCapTypes[CAPTYPE_BITMAPS_COUNT]; + + std::vector m_aStrHorzList; + std::vector m_aStrVertList; + + SdrCaptionType nCaptionType; + sal_Int32 nGap; + SdrCaptionEscDir nEscDir; + bool bEscRel; + sal_Int32 nEscAbs; + sal_Int32 nEscRel; + sal_Int32 nLineLen; + bool bFitLineLen; + + sal_uInt16 nPosition; + sal_uInt16 nExtension; + + const SfxItemSet& rOutAttrs; + const SdrView* pView; + + std::unique_ptr m_xMF_SPACING; + std::unique_ptr m_xLB_EXTENSION; + std::unique_ptr m_xFT_BYFT; + std::unique_ptr m_xMF_BY; + std::unique_ptr m_xFT_POSITIONFT; + std::unique_ptr m_xLB_POSITION; + std::unique_ptr m_xLineTypes; + std::unique_ptr m_xFT_LENGTHFT; + std::unique_ptr m_xMF_LENGTH; + std::unique_ptr m_xCB_OPTIMAL; + std::unique_ptr m_xCT_CAPTTYPE; + std::unique_ptr m_xCT_CAPTTYPEWin; + + void SetupExtension_Impl( sal_uInt16 nType ); + void SetupType_Impl( SdrCaptionType nType ); + DECL_LINK(ExtensionSelectHdl_Impl, weld::ComboBox&, void); + DECL_LINK(PositionSelectHdl_Impl, weld::ComboBox&, void); + DECL_LINK(LineOptHdl_Impl, weld::ToggleButton&, void); + DECL_LINK(SelectCaptTypeHdl_Impl, ValueSet*, void); + +public: + SvxCaptionTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + virtual ~SvxCaptionTabPage() override; + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* ); + static const sal_uInt16* GetRanges() { return pCaptionRanges; } + + virtual bool FillItemSet( SfxItemSet* ) override; + virtual void Reset( const SfxItemSet * ) override; + void Construct(); + void SetView( const SdrView* pSdrView ) + { pView = pSdrView; } + + void FillValueSet(); +}; + +// class SvxCaptionTabDialog --------------------------------------------- +struct SvxSwFrameValidation; +class SvxCaptionTabDialog : public SfxTabDialogController +{ +private: + const SdrView* pView; + SvxAnchorIds nAnchorCtrls; + + Link aValidateLink; + + virtual void PageCreated(const OString& rId, SfxTabPage &rPage) override; + +public: + SvxCaptionTabDialog(weld::Window* pParent, const SdrView* pView, + SvxAnchorIds nAnchorTypes); + + /// link for the Writer to validate positions + void SetValidateFramePosLink( const Link& rLink ); +}; + + +#endif // INCLUDED_CUI_SOURCE_INC_LABDLG_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/linkdlg.hxx b/cui/source/inc/linkdlg.hxx new file mode 100644 index 000000000..90d51aba8 --- /dev/null +++ b/cui/source/inc/linkdlg.hxx @@ -0,0 +1,85 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_CUI_SOURCE_INC_LINKDLG_HXX +#define INCLUDED_CUI_SOURCE_INC_LINKDLG_HXX + +#include +#include +#include + +/********************** SvUpdateLinksDialog ****************************** +*************************************************************************/ +namespace sfx2 +{ + class LinkManager; + class SvBaseLink; +} + +enum class SfxLinkUpdateMode; + +class SvBaseLinksDlg : public weld::GenericDialogController +{ + OUString aStrAutolink; + OUString aStrManuallink; + OUString aStrBrokenlink; + OUString aStrCloselinkmsg; + OUString aStrCloselinkmsgMulti; + OUString aStrWaitinglink; + sfx2::LinkManager* pLinkMgr; + Idle aUpdateIdle; + + std::unique_ptr m_xTbLinks; + std::unique_ptr m_xFtFullFileName; + std::unique_ptr m_xFtFullSourceName; + std::unique_ptr m_xFtFullTypeName; + std::unique_ptr m_xRbAutomatic; + std::unique_ptr m_xRbManual; + std::unique_ptr m_xPbUpdateNow; + std::unique_ptr m_xPbChangeSource; + std::unique_ptr m_xPbBreakLink; + + ScopedVclPtr m_xVirDev; + + DECL_LINK( LinksSelectHdl, weld::TreeView&, void ); + DECL_LINK( LinksDoubleClickHdl, weld::TreeView&, bool ); + DECL_LINK( AutomaticClickHdl, weld::Button&, void ); + DECL_LINK( ManualClickHdl, weld::Button&, void ); + DECL_LINK( UpdateNowClickHdl, weld::Button&, void); + DECL_LINK( ChangeSourceClickHdl, weld::Button&, void ); + DECL_LINK( BreakLinkClickHdl, weld::Button&, void ); + DECL_LINK( UpdateWaitingHdl, Timer *, void ); + DECL_LINK( EndEditHdl, sfx2::SvBaseLink&, void ); + void LinksSelectHdl(weld::TreeView* pTreeView); + sfx2::SvBaseLink* GetSelEntry(int* pPos); + OUString ImplGetStateStr( const sfx2::SvBaseLink& ); + void SetType(sfx2::SvBaseLink& rLink, int nPos, SfxLinkUpdateMode nType); + void InsertEntry(const sfx2::SvBaseLink& rLink, int nPos = -1, bool bSelect = false); + + void SetManager( sfx2::LinkManager* ); + +public: + SvBaseLinksDlg(weld::Window * pParent, sfx2::LinkManager*, bool bHtml); + virtual ~SvBaseLinksDlg() override; + void SetActLink( sfx2::SvBaseLink const * pLink ); +}; + +#endif // INCLUDED_CUI_SOURCE_INC_LINKDLG_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/macroass.hxx b/cui/source/inc/macroass.hxx new file mode 100644 index 000000000..d4403686c --- /dev/null +++ b/cui/source/inc/macroass.hxx @@ -0,0 +1,92 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_MACROASS_HXX +#define INCLUDED_CUI_SOURCE_INC_MACROASS_HXX + +#include + +#include +#include +#include +#include +#include +#include + +class SfxMacroTabPage_; +class SfxMacroTabPage_Impl; + +class SfxMacroTabPage final : public SfxTabPage +{ + SvxMacroTableDtor aTbl; + DECL_LINK(SelectEvent_Impl, weld::TreeView&, void); + DECL_LINK(SelectGroup_Impl, weld::TreeView&, void); + DECL_LINK(SelectMacro_Impl, weld::TreeView&, void); + + DECL_LINK(AssignDeleteHdl_Impl, weld::TreeView&, bool); + DECL_LINK(AssignDeleteClickHdl_Impl, weld::Button&, void); + void AssignDeleteHdl(const weld::Widget*); + DECL_LINK( TimeOut_Impl, Timer*, void ); + + std::unique_ptr mpImpl; + + void InitAndSetHandler(); + void FillEvents(); + void EnableButtons(); + +public: + SfxMacroTabPage( + weld::Container* pPage, weld::DialogController* pController, + const css::uno::Reference< css::frame::XFrame >& rxDocumentFrame, + const SfxItemSet& rSet + ); + + virtual ~SfxMacroTabPage() override; + + void AddEvent( const OUString & rEventName, SvMacroItemId nEventId ); + + void ScriptChanged(); + virtual void PageCreated (const SfxAllItemSet& aSet) override; + virtual void ActivatePage( const SfxItemSet& ) override; + void LaunchFillGroup(); + + // --------- inherit from the base ------------- + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; + + bool IsReadOnly() const override; + + // --------- inherit from the base ------------- + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet ); +}; + +class SfxMacroAssignDlg : public SfxSingleTabDialogController +{ +public: + SfxMacroAssignDlg(weld::Widget* pParent, + const css::uno::Reference< css::frame::XFrame >& rxDocumentFrame, + const SfxItemSet& rSet); + SfxMacroTabPage* GetTabPage() + { + return static_cast(m_xSfxPage.get()); + } +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/macropg.hxx b/cui/source/inc/macropg.hxx new file mode 100644 index 000000000..5017aeeab --- /dev/null +++ b/cui/source/inc/macropg.hxx @@ -0,0 +1,131 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_MACROPG_HXX +#define INCLUDED_CUI_SOURCE_INC_MACROPG_HXX + +#include +#include + +#include +#include +#include +#include + +#include +#include + +typedef std::unordered_map< OUString, std::pair< OUString, OUString > > EventsHash; + +struct EventDisplayName +{ + const char* pAsciiEventName; + const char* pEventResourceID; + EventDisplayName(const char* pAsciiName, const char* pResId) + : pAsciiEventName(pAsciiName) + , pEventResourceID(pResId) + { + } +}; +typedef std::vector< EventDisplayName > EventDisplayNames; + +class SvxMacroTabPage_; +class SvTabListBox; + +class SvxMacroTabPage_Impl; + + +class SvxMacroTabPage_ : public SfxTabPage +{ + DECL_LINK( SelectEvent_Impl, weld::TreeView&, void ); + DECL_LINK( AssignDeleteHdl_Impl, weld::Button&, void ); + DECL_LINK( DoubleClickHdl_Impl, weld::TreeView&, bool ); + + static void GenericHandler_Impl( SvxMacroTabPage_* pThis, const weld::Button* pBtn ); + + css::uno::Reference< css::container::XNameReplace > m_xAppEvents; +protected: + std::unique_ptr mpImpl; + css::uno::Reference< css::container::XNameReplace > m_xDocEvents; + css::uno::Reference< css::util::XModifiable > m_xModifiable; + EventsHash m_appEventsHash; + EventsHash m_docEventsHash; + bool bDocModified, bAppEvents, bInitialized; + EventDisplayNames aDisplayNames; + + SvxMacroTabPage_(weld::Container* pPage, weld::DialogController* pController, const OUString& rUIXMLDescription, const OString& rID, const SfxItemSet& rItemSet); + + void EnableButtons(); + static css::uno::Any GetPropsByName( const OUString& eventName, EventsHash& eventsHash ); + static std::pair< OUString, OUString > GetPairFromAny( const css::uno::Any& aAny ); + +public: + + virtual ~SvxMacroTabPage_() override; + void InitResources(); + + void InitAndSetHandler( const css::uno::Reference< css::container::XNameReplace >& xAppEvents, const css::uno::Reference< css::container::XNameReplace >& xDocEvents, const css::uno::Reference< css::util::XModifiable >& xModifiable ); + virtual bool FillItemSet( SfxItemSet* rSet ) override; + + virtual void Reset( const SfxItemSet* ) override; + + void DisplayAppEvents( bool appEvents); + void SetReadOnly( bool bSet ); + bool IsReadOnly() const override; +}; + +class SvxMacroTabPage : public SvxMacroTabPage_ +{ +public: + SvxMacroTabPage( + weld::Container* pPage, weld::DialogController* pController, + const css::uno::Reference< css::frame::XFrame >& _rxDocumentFrame, + const SfxItemSet& rSet, + css::uno::Reference< css::container::XNameReplace > const & xNameReplace, + sal_uInt16 nSelectedIndex + ); +}; + +// class SvxMacroAssignDlg -------------------------------------------------- + +typedef const sal_uInt16* (*GetTabPageRanges)(); // gives international Which-values + +class SvxMacroAssignSingleTabDialog : public SfxSingleTabDialogController +{ +public: + SvxMacroAssignSingleTabDialog(weld::Window* pParent, const SfxItemSet& rOptionsSet); + +private: + DECL_LINK(OKHdl_Impl, weld::Button&, void); +}; + +class SvxMacroAssignDlg : public SvxMacroAssignSingleTabDialog +{ +public: + SvxMacroAssignDlg( + weld::Window* pParent, + const css::uno::Reference< css::frame::XFrame >& _rxDocumentFrame, + const SfxItemSet& rSet, + const css::uno::Reference< css::container::XNameReplace >& xNameReplace, + sal_uInt16 nSelectedIndex + ); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/measure.hxx b/cui/source/inc/measure.hxx new file mode 100644 index 000000000..7915fcc38 --- /dev/null +++ b/cui/source/inc/measure.hxx @@ -0,0 +1,98 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_MEASURE_HXX +#define INCLUDED_CUI_SOURCE_INC_MEASURE_HXX + +#include +#include +#include + +class SdrView; + +/// Dialog for changing TextAttributes +class SvxMeasurePage : public SvxTabPage +{ +private: + static const sal_uInt16 pRanges[]; + + const SfxItemSet& rOutAttrs; + SfxItemSet aAttrSet; + const SdrView* pView; + MapUnit eUnit; + + bool bPositionModified; + + SvxRectCtl m_aCtlPosition; + SvxXMeasurePreview m_aCtlPreview; + std::unique_ptr m_xMtrFldLineDist; + std::unique_ptr m_xMtrFldHelplineOverhang; + std::unique_ptr m_xMtrFldHelplineDist; + std::unique_ptr m_xMtrFldHelpline1Len; + std::unique_ptr m_xMtrFldHelpline2Len; + std::unique_ptr m_xTsbBelowRefEdge; + std::unique_ptr m_xMtrFldDecimalPlaces; + std::unique_ptr m_xTsbAutoPosV; + std::unique_ptr m_xTsbAutoPosH; + std::unique_ptr m_xTsbShowUnit; + std::unique_ptr m_xLbUnit; + std::unique_ptr m_xTsbParallel; + std::unique_ptr m_xFtAutomatic; + std::unique_ptr m_xCtlPosition; + std::unique_ptr m_xCtlPreview; + + void FillUnitLB(); + + DECL_LINK(ClickAutoPosHdl_Impl, weld::ToggleButton&, void); + DECL_LINK(ChangeAttrEditHdl_Impl, weld::MetricSpinButton&, void); + DECL_LINK(ChangeAttrSpinHdl_Impl, weld::SpinButton&, void); + DECL_LINK(ChangeAttrListBoxHdl_Impl, weld::ComboBox&, void); + DECL_LINK(ChangeAttrClickHdl_Impl, weld::ToggleButton&, void); + void ChangeAttrHdl_Impl(void const *); + +public: + + SvxMeasurePage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + virtual ~SvxMeasurePage() override; + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* ); + static const sal_uInt16* GetRanges() { return pRanges; } + + virtual bool FillItemSet( SfxItemSet* ) override; + virtual void Reset( const SfxItemSet * ) override; + + virtual void PointChanged( weld::DrawingArea* pWindow, RectPoint eRP ) override; + + void Construct(); + void SetView( const SdrView* pSdrView ) { pView = pSdrView; } + virtual void PageCreated(const SfxAllItemSet& aSet) override; + +}; + +/* Derived from SfxSingleTabDialogController, in order to be able to be + informed about virtual methods by the control. */ +class SvxMeasureDialog : public SfxSingleTabDialogController +{ +public: + SvxMeasureDialog(weld::Window* pParent, const SfxItemSet& rAttr, + const SdrView* pView); +}; + +#endif // INCLUDED_CUI_SOURCE_INC_MEASURE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/multipat.hxx b/cui/source/inc/multipat.hxx new file mode 100644 index 000000000..67832c1e8 --- /dev/null +++ b/cui/source/inc/multipat.hxx @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_MULTIPAT_HXX +#define INCLUDED_CUI_SOURCE_INC_MULTIPAT_HXX + +#include + +// define ---------------------------------------------------------------- + +// different delimiter for Unix (:) and Windows (;) + +#ifdef UNX +#define CLASSPATH_DELIMITER ':' +#else +#define CLASSPATH_DELIMITER ';' +#endif + +class SvxMultiPathDialog : public weld::GenericDialogController +{ +private: + std::unique_ptr m_xRadioLB; + std::unique_ptr m_xAddBtn; + std::unique_ptr m_xDelBtn; + + void AppendEntry(const OUString& rText, const OUString& rId); + void HandleEntryChecked(int nRow); + + DECL_LINK(AddHdl_Impl, weld::Button&, void); + DECL_LINK(DelHdl_Impl, weld::Button&, void); + DECL_LINK(SelectHdl_Impl, weld::TreeView&, void); + typedef std::pair row_col; + DECL_LINK(CheckHdl_Impl, const row_col&, void); + +public: + SvxMultiPathDialog(weld::Window* pParent); + virtual ~SvxMultiPathDialog() override; + + OUString GetPath() const; + void SetPath(const OUString& rPath); + void SetTitle(const OUString& rTitle) { m_xDialog->set_title(rTitle); } +}; + +class SvxPathSelectDialog : public weld::GenericDialogController +{ +private: + std::unique_ptr m_xPathLB; + std::unique_ptr m_xAddBtn; + std::unique_ptr m_xDelBtn; + + DECL_LINK(AddHdl_Impl, weld::Button&, void); + DECL_LINK(DelHdl_Impl, weld::Button&, void); + DECL_LINK(SelectHdl_Impl, weld::TreeView&, void); + +public: + SvxPathSelectDialog(weld::Window* pParent); + + OUString GetPath() const; + void SetPath( const OUString& rPath ); + void SetTitle(const OUString& rTitle) { m_xDialog->set_title(rTitle); } +}; + +#endif // INCLUDED_CUI_SOURCE_INC_MULTIPAT_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/newtabledlg.hxx b/cui/source/inc/newtabledlg.hxx new file mode 100644 index 000000000..9ec717c70 --- /dev/null +++ b/cui/source/inc/newtabledlg.hxx @@ -0,0 +1,75 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_NEWTABLEDLG_HXX +#define INCLUDED_CUI_SOURCE_INC_NEWTABLEDLG_HXX + +#include +#include + +class SvxNewTableDialog : public weld::GenericDialogController +{ +private: + std::unique_ptr mxNumColumns; + std::unique_ptr mxNumRows; + +public: + SvxNewTableDialog(weld::Window* pParent); + + virtual sal_Int32 getRows() const; + virtual sal_Int32 getColumns() const; +}; + +class SvxNewTableDialogWrapper : public SvxAbstractNewTableDialog +{ +private: + std::shared_ptr m_xDlg; + +public: + SvxNewTableDialogWrapper(weld::Window* pParent) + : m_xDlg(std::make_shared(pParent)) + { + } + + virtual std::shared_ptr getDialogController() override + { + return m_xDlg; + } + + virtual sal_Int32 getRows() const override + { + SvxNewTableDialog* pDlg = dynamic_cast(m_xDlg.get()); + if (pDlg) + return pDlg->getRows(); + + return 0; + } + + virtual sal_Int32 getColumns() const override + { + SvxNewTableDialog* pDlg = dynamic_cast(m_xDlg.get()); + if (pDlg) + return pDlg->getColumns(); + + return 0; + } +}; + +#endif // INCLUDED_CUI_SOURCE_INC_NEWTABLEDLG_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/numfmt.hxx b/cui/source/inc/numfmt.hxx new file mode 100644 index 000000000..1be328d94 --- /dev/null +++ b/cui/source/inc/numfmt.hxx @@ -0,0 +1,157 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_NUMFMT_HXX +#define INCLUDED_CUI_SOURCE_INC_NUMFMT_HXX + + +#include +#include +#include +#include +#include +#include + +class SvxNumberFormatShell; +class SvxNumberInfoItem; +class vector; + + +class SvxNumberPreview : public weld::CustomWidgetController +{ +private: + OUString aPrevStr; + Color aPrevCol; + sal_Int32 mnPos; + sal_Unicode mnChar; + +protected: + virtual void Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle& rRect) override; + +public: + SvxNumberPreview(); + + void NotifyChange( const OUString& rPrevStr, const Color* pColor = nullptr ); + + virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override + { + CustomWidgetController::SetDrawingArea(pDrawingArea); + pDrawingArea->set_size_request(-1, pDrawingArea->get_text_height() * 3); + } +}; + +class SvxNumberFormatTabPage : public SfxTabPage +{ + static const sal_uInt16 pRanges[]; + +public: + SvxNumberFormatTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs); + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet ); + virtual ~SvxNumberFormatTabPage() override; + // Returns area information. + static const sal_uInt16* GetRanges() { return pRanges; } + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; + virtual DeactivateRC DeactivatePage ( SfxItemSet* pSet ) override; + + void HideLanguage(bool bFlag=true); + virtual void PageCreated(const SfxAllItemSet& aSet) override; + +private: + std::unique_ptr pNumItem; + std::unique_ptr pNumFmtShell; + sal_uLong nInitFormat; + short m_nLbFormatSelPosEdComment; + + bool bNumItemFlag; ///< for handling with DocShell + bool bOneAreaFlag; + bool bLegacyAutomaticCurrency; + short nFixedCategory; + + OUString sAutomaticLangEntry; + OUString sAutomaticCurrencyEntry; + + SvxNumberPreview m_aWndPreview; + std::unique_ptr m_xFtCategory; + std::unique_ptr m_xLbCategory; + std::unique_ptr m_xFtFormat; + std::unique_ptr m_xLbCurrency; + std::unique_ptr m_xLbFormat; + std::unique_ptr m_xFtLanguage; + std::unique_ptr m_xCbSourceFormat; + std::unique_ptr m_xFtOptions; + std::unique_ptr m_xFtDecimals; + std::unique_ptr m_xEdDecimals; + std::unique_ptr m_xFtDenominator; + std::unique_ptr m_xEdDenominator; + std::unique_ptr m_xBtnNegRed; + std::unique_ptr m_xFtLeadZeroes; + std::unique_ptr m_xEdLeadZeroes; + std::unique_ptr m_xBtnThousand; + std::unique_ptr m_xBtnEngineering; + std::unique_ptr m_xFormatCodeFrame; + std::unique_ptr m_xEdFormat; + std::unique_ptr m_xIbAdd; + std::unique_ptr m_xIbInfo; + std::unique_ptr m_xIbRemove; + std::unique_ptr m_xFtComment; + std::unique_ptr m_xEdComment; + std::unique_ptr m_xLbLanguage; + std::unique_ptr m_xWndPreview; + + void Init_Impl(); + void FillCurrencyBox(); + void FillFormatListBox_Impl( std::vector& rEntries ); + void UpdateOptions_Impl( bool bCheckCatChange ); + void UpdateFormatListBox_Impl( bool bCat, bool bUpdateEdit ); + void UpdateThousandEngineeringCheckBox(); + void UpdateDecimalsDenominatorEditBox(); + void Obstructing(); + void EnableBySourceFormat_Impl(); + void SetCategory( sal_uInt16 nPos ); + OUString GetExpColorString( Color*& rpPreviewColor, const OUString& aFormatStr, short nTmpCatPos ); + void MakePreviewText( const OUString& rFormat ); + void ChangePreviewText( sal_uInt16 nPos ); + void AddAutomaticLanguage_Impl(LanguageType eAutoLang, bool bSelect); + bool Click_Impl(weld::Button& rIB); + // Handler + DECL_LINK(LostFocusHdl_Impl, weld::Widget&, void); + DECL_LINK(DoubleClickHdl_Impl, weld::TreeView&, bool); + DECL_LINK(SelFormatListBoxHdl_Impl, weld::ComboBox&, void); + DECL_LINK(SelFormatTreeListBoxHdl_Impl, weld::TreeView&, void); + DECL_LINK(SelFormatClickHdl_Impl, weld::Button&, void); + void SelFormatHdl_Impl(weld::Widget*); + DECL_LINK(ClickHdl_Impl, weld::Button&, void); + DECL_LINK(EditModifyHdl_Impl, weld::Entry&, void); + DECL_LINK(OptEditHdl_Impl, weld::SpinButton&, void); + DECL_LINK(OptClickHdl_Impl, weld::Button&, void); + void EditHdl_Impl(const weld::Entry*); + void OptHdl_Impl(const weld::Widget*); + + // set and get currency, taking into account if the legacy + // automatic currency entry exists + void set_active_currency(sal_Int32 nCurCurrencyEntryPos); + sal_uInt32 get_active_currency() const; + +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/numpages.hxx b/cui/source/inc/numpages.hxx new file mode 100644 index 000000000..ebbe46625 --- /dev/null +++ b/cui/source/inc/numpages.hxx @@ -0,0 +1,388 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_NUMPAGES_HXX +#define INCLUDED_CUI_SOURCE_INC_NUMPAGES_HXX + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define MN_GALLERY_ENTRY 100 + +class ColorListBox; +class SvxNumValueSet; +class SvxNumRule; +class SvxBmpNumValueSet; +class SvxBrushItem; +struct ImplSVEvent; + +struct SvxNumSettings_Impl +{ + SvxNumType nNumberType; + short nParentNumbering; + OUString sPrefix; + OUString sSuffix; + OUString sBulletChar; + OUString sBulletFont; + SvxNumSettings_Impl() : + nNumberType(SVX_NUM_CHARS_UPPER_LETTER), + nParentNumbering(0) + {} +}; + +typedef std::vector > SvxNumSettingsArr_Impl; + + +class SvxSingleNumPickTabPage final : public SfxTabPage +{ + SvxNumSettingsArr_Impl aNumSettingsArr; + std::unique_ptr pActNum; + std::unique_ptr pSaveNum; + sal_uInt16 nActNumLvl; + bool bModified : 1; + bool bPreset : 1; + + sal_uInt16 nNumItemId; + + std::unique_ptr m_xExamplesVS; + std::unique_ptr m_xExamplesVSWin; + + DECL_LINK(NumSelectHdl_Impl, ValueSet*, void); + DECL_LINK(DoubleClickHdl_Impl, ValueSet*, void); + +public: + SvxSingleNumPickTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + virtual ~SvxSingleNumPickTabPage() override; + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet); + + virtual void ActivatePage(const SfxItemSet& rSet) override; + virtual DeactivateRC DeactivatePage(SfxItemSet *pSet) override; + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; +}; + +class SvxBulletPickTabPage final : public SfxTabPage +{ + std::unique_ptr pActNum; + std::unique_ptr pSaveNum; + sal_uInt16 nActNumLvl; + bool bModified : 1; + bool bPreset : 1; + sal_uInt16 nNumItemId; + + OUString sBulletCharFormatName; + + std::unique_ptr m_xExamplesVS; + std::unique_ptr m_xExamplesVSWin; + + DECL_LINK(NumSelectHdl_Impl, ValueSet*, void); + DECL_LINK(DoubleClickHdl_Impl, ValueSet*, void); +public: + SvxBulletPickTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + virtual ~SvxBulletPickTabPage() override; + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet); + + virtual void ActivatePage(const SfxItemSet& rSet) override; + virtual DeactivateRC DeactivatePage(SfxItemSet *pSet) override; + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; + + virtual void PageCreated(const SfxAllItemSet& aSet) override; +}; + +#define NUM_VALUSET_COUNT 16 + +/// TabPage for complete numeration +class SvxNumPickTabPage final : public SfxTabPage +{ + OUString sNumCharFmtName; + OUString sBulletCharFormatName; + + SvxNumSettingsArr_Impl aNumSettingsArrays[NUM_VALUSET_COUNT]; // is initialized with the five formats + + std::unique_ptr pActNum; + std::unique_ptr pSaveNum; + sal_uInt16 nActNumLvl; + sal_uInt16 nNumItemId; + bool bModified : 1; + bool bPreset : 1; + + std::unique_ptr m_xExamplesVS; + std::unique_ptr m_xExamplesVSWin; + + DECL_LINK(NumSelectHdl_Impl, ValueSet*, void); + DECL_LINK(DoubleClickHdl_Impl, ValueSet*, void); + +public: + SvxNumPickTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + virtual ~SvxNumPickTabPage() override; + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet); + + virtual void ActivatePage(const SfxItemSet& rSet) override; + virtual DeactivateRC DeactivatePage(SfxItemSet *pSet) override; + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; + + void SetCharFormatNames(const OUString& rCharName, const OUString& rBulName) + { sNumCharFmtName = rCharName; + sBulletCharFormatName = rBulName;} + virtual void PageCreated(const SfxAllItemSet& aSet) override; +}; + +class SvxBitmapPickTabPage final : public SfxTabPage +{ + std::vector aGrfNames; + + std::unique_ptr pActNum; + std::unique_ptr pSaveNum; + sal_uInt16 nActNumLvl; + sal_uInt16 nNumItemId; + MapUnit eCoreUnit; + bool bModified : 1; + bool bPreset : 1; + + std::unique_ptr m_xErrorText; + std::unique_ptr m_xBtBrowseFile; + std::unique_ptr m_xExamplesVS; + std::unique_ptr m_xExamplesVSWin; + + DECL_LINK(NumSelectHdl_Impl, ValueSet*, void); + DECL_LINK(DoubleClickHdl_Impl, ValueSet*, void); + DECL_LINK(ClickAddBrowseHdl_Impl, weld::Button&, void); + +public: + SvxBitmapPickTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + virtual ~SvxBitmapPickTabPage() override; + + static std::unique_ptr Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet); + + virtual void ActivatePage(const SfxItemSet& rSet) override; + virtual DeactivateRC DeactivatePage(SfxItemSet *pSet) override; + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; +}; + +class SvxNumOptionsTabPage : public SfxTabPage +{ + OUString m_sNumCharFmtName; + OUString m_sBulletCharFormatName; + + Timer aInvalidateTimer; + + std::unique_ptr pActNum; + std::unique_ptr pSaveNum; + + Size aInitSize[SVX_MAX_NUM]; + + ImplSVEvent* m_pLevelHdlEvent; + + bool bLastWidthModified : 1; + bool bModified : 1; + bool bPreset : 1; + bool bAutomaticCharStyles: 1; + bool bHTMLMode : 1; + + std::vector aGrfNames; + vcl::Font aActBulletFont; + + sal_uInt8 nBullet; + sal_uInt16 nActNumLvl; + sal_uInt16 nNumItemId; + MapUnit eCoreUnit; + + SvxNumberingPreview m_aPreviewWIN; + std::unique_ptr m_xGrid; + std::unique_ptr m_xLevelLB; + std::unique_ptr m_xFmtLB; + std::unique_ptr m_xSeparatorFT; + std::unique_ptr m_xPrefixFT; + std::unique_ptr m_xPrefixED; + std::unique_ptr m_xSuffixFT; + std::unique_ptr m_xSuffixED; + std::unique_ptr m_xCharFmtFT; + std::unique_ptr m_xCharFmtLB; + std::unique_ptr m_xBulColorFT; + std::unique_ptr m_xBulColLB; + std::unique_ptr m_xBulRelSizeFT; + std::unique_ptr m_xBulRelSizeMF; + std::unique_ptr m_xAllLevelFT; + std::unique_ptr m_xAllLevelNF; + std::unique_ptr m_xStartFT; + std::unique_ptr m_xStartED; + std::unique_ptr m_xBulletFT; + std::unique_ptr m_xBulletPB; + std::unique_ptr m_xBitmapFT; + std::unique_ptr m_xBitmapMB; + std::unique_ptr m_xWidthFT; + std::unique_ptr m_xWidthMF; + std::unique_ptr m_xHeightFT; + std::unique_ptr m_xHeightMF; + std::unique_ptr m_xRatioCB; + std::unique_ptr m_xOrientFT; + std::unique_ptr m_xOrientLB; + std::unique_ptr m_xAllLevelsFrame; + std::unique_ptr m_xGalleryMenu; + std::unique_ptr m_xSameLevelCB; + std::unique_ptr m_xPreviewWIN; + + void InitControls(); + /** To switch between the numbering type + 0 - Number; + 1 - Bullet; + 2 - Bitmap; */ + void SwitchNumberType( sal_uInt8 nType ); + void CheckForStartValue_Impl(sal_uInt16 nNumberingType); + + DECL_LINK(NumberTypeSelectHdl_Impl, weld::ComboBox&, void); + DECL_LINK(LevelHdl_Impl, weld::TreeView&, void); + DECL_LINK(LevelHdl, void *, void); + DECL_LINK(PopupActivateHdl_Impl, weld::ToggleButton&, void); + DECL_LINK(GraphicHdl_Impl, const OString&, void); + DECL_LINK(BulletHdl_Impl, weld::Button&, void); + DECL_LINK(SizeHdl_Impl, weld::MetricSpinButton&, void); + DECL_LINK(RatioHdl_Impl, weld::ToggleButton&, void); + DECL_LINK(CharFmtHdl_Impl, weld::ComboBox&, void); + DECL_LINK(EditModifyHdl_Impl, weld::Entry&, void); + DECL_LINK(SpinModifyHdl_Impl, weld::SpinButton&, void); + DECL_LINK(AllLevelHdl_Impl, weld::SpinButton&, void); + DECL_LINK(OrientHdl_Impl, weld::ComboBox&, void); + DECL_LINK(SameLevelHdl_Impl, weld::ToggleButton&, void); + DECL_LINK(BulColorHdl_Impl, ColorListBox&, void); + DECL_LINK(BulRelSizeHdl_Impl, weld::MetricSpinButton&, void); + DECL_LINK(PreviewInvalidateHdl_Impl, Timer*, void); + void EditModifyHdl_Impl(const weld::Entry*); + +public: + SvxNumOptionsTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + virtual ~SvxNumOptionsTabPage() override; + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet); + + virtual void ActivatePage(const SfxItemSet& rSet) override; + virtual DeactivateRC DeactivatePage(SfxItemSet *pSet) override; + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; + + void SetCharFmts(const OUString& rNumName, const OUString& rBulletName) + { + m_sNumCharFmtName = rNumName; + m_sBulletCharFormatName = rBulletName; + } + void SetMetric(FieldUnit eSet); + + void SetModified(bool bRepaint = true); + virtual void PageCreated(const SfxAllItemSet& aSet) override; +}; + + +class SvxNumPositionTabPage : public SfxTabPage +{ + std::unique_ptr pActNum; + std::unique_ptr pSaveNum; + + ImplSVEvent* m_pLevelHdlEvent; + sal_uInt16 nActNumLvl; + sal_uInt16 nNumItemId; + MapUnit eCoreUnit; + + bool bModified : 1; + bool bPreset : 1; + bool bInInintControl : 1; // workaround for Modify-error, is said to be corrected from 391 on + bool bLabelAlignmentPosAndSpaceModeActive; + + SvxNumberingPreview m_aPreviewWIN; + std::unique_ptr m_xLevelLB; + // former set of controls shown for numbering rules containing list level + // attributes in SvxNumberFormat::SvxNumPositionAndSpaceMode == LABEL_WIDTH_AND_POSITION + std::unique_ptr m_xDistBorderFT; + std::unique_ptr m_xDistBorderMF; + std::unique_ptr m_xRelativeCB; + std::unique_ptr m_xIndentFT; + std::unique_ptr m_xIndentMF; + std::unique_ptr m_xDistNumFT; + std::unique_ptr m_xDistNumMF; + std::unique_ptr m_xAlignFT; + std::unique_ptr m_xAlignLB; + // new set of controls shown for numbering rules containing list level + // attributes in SvxNumberFormat::SvxNumPositionAndSpaceMode == LABEL_ALIGNMENT + std::unique_ptr m_xLabelFollowedByFT; + std::unique_ptr m_xLabelFollowedByLB; + std::unique_ptr m_xListtabFT; + std::unique_ptr m_xListtabMF; + std::unique_ptrm_xAlign2FT; + std::unique_ptr m_xAlign2LB; + std::unique_ptr m_xAlignedAtFT; + std::unique_ptr m_xAlignedAtMF; + std::unique_ptr m_xIndentAtFT; + std::unique_ptr m_xIndentAtMF; + std::unique_ptr m_xStandardPB; + std::unique_ptr m_xPreviewWIN; + + void InitControls(); + + DECL_LINK(LevelHdl_Impl, weld::TreeView&, void); + DECL_LINK(LevelHdl, void *, void); + DECL_LINK(EditModifyHdl_Impl, weld::ComboBox&, void); + DECL_LINK(DistanceHdl_Impl, weld::MetricSpinButton&, void); + DECL_LINK(RelativeHdl_Impl, weld::ToggleButton&, void); + DECL_LINK(StandardHdl_Impl, weld::Button&, void); + + void InitPosAndSpaceMode(); + void ShowControlsDependingOnPosAndSpaceMode(); + + DECL_LINK(LabelFollowedByHdl_Impl, weld::ComboBox&, void); + DECL_LINK(ListtabPosHdl_Impl, weld::MetricSpinButton&, void); + DECL_LINK(AlignAtHdl_Impl, weld::MetricSpinButton&, void); + DECL_LINK(IndentAtHdl_Impl, weld::MetricSpinButton&, void); + +public: + SvxNumPositionTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + virtual ~SvxNumPositionTabPage() override; + + virtual void ActivatePage(const SfxItemSet& rSet) override; + virtual DeactivateRC DeactivatePage(SfxItemSet *pSet) override; + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet); + + void SetMetric(FieldUnit eSet); + void SetModified(); + virtual void PageCreated(const SfxAllItemSet& aSet) override; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/optasian.hxx b/cui/source/inc/optasian.hxx new file mode 100644 index 000000000..d8febfb7b --- /dev/null +++ b/cui/source/inc/optasian.hxx @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_OPTASIAN_HXX +#define INCLUDED_CUI_SOURCE_INC_OPTASIAN_HXX + +#include +#include +#include + +struct SvxAsianLayoutPage_Impl; +class SvxAsianLayoutPage : public SfxTabPage +{ + std::unique_ptr pImpl; + + std::unique_ptr m_xCharKerningRB; + std::unique_ptr m_xCharPunctKerningRB; + std::unique_ptr m_xNoCompressionRB; + std::unique_ptr m_xPunctCompressionRB; + std::unique_ptr m_xPunctKanaCompressionRB; + std::unique_ptr m_xLanguageFT; + std::unique_ptr m_xLanguageLB; + std::unique_ptr m_xStandardCB; + std::unique_ptr m_xStartFT; + std::unique_ptr m_xStartED; + std::unique_ptr m_xEndFT; + std::unique_ptr m_xEndED; + std::unique_ptr m_xHintFT; + + DECL_LINK(LanguageHdl, weld::ComboBox&, void); + DECL_LINK(ChangeStandardHdl, weld::ToggleButton&, void); + DECL_LINK(ModifyHdl, weld::Entry&, void); + +public: + SvxAsianLayoutPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet ); + virtual ~SvxAsianLayoutPage() override; + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet ); + static const sal_uInt16* GetRanges(); + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/optdict.hxx b/cui/source/inc/optdict.hxx new file mode 100644 index 000000000..7d8ffd522 --- /dev/null +++ b/cui/source/inc/optdict.hxx @@ -0,0 +1,112 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_OPTDICT_HXX +#define INCLUDED_CUI_SOURCE_INC_OPTDICT_HXX + +#include +#include +#include +#include + +namespace com::sun::star{ + namespace linguistic2{ + class XDictionary; + class XSpellChecker1; + } +} + +// forward --------------------------------------------------------------- + + +// class SvxNewDictionaryDialog ------------------------------------------ + +class SvxNewDictionaryDialog : public weld::GenericDialogController +{ +private: + std::unique_ptr m_xNameEdit; + std::unique_ptr m_xLanguageLB; + std::unique_ptr m_xExceptBtn; + std::unique_ptr m_xOKBtn; + css::uno::Reference m_xNewDic; + + DECL_LINK(OKHdl_Impl, weld::Button&, void); + DECL_LINK(ModifyHdl_Impl, weld::Entry&, void); + +public: + SvxNewDictionaryDialog(weld::Window* pParent); + + const css::uno::Reference& GetNewDictionary() const { return m_xNewDic; } +}; + +// class SvxEditDictionaryDialog ----------------------------------------- + +class SvxEditDictionaryDialog : public weld::GenericDialogController +{ +private: + OUString sModify; + OUString sNew; + OUString sReplaceFT_Text; + + css::uno::Sequence< + css::uno::Reference< + css::linguistic2::XDictionary > > aDics; //! snapshot copy to work on + + bool bFirstSelect; + bool bDoNothing; + bool bDicIsReadonly; + + weld::TreeView* m_pWordsLB; + std::unique_ptr m_xAllDictsLB; + std::unique_ptr m_xLangFT; + std::unique_ptr m_xLangLB; + std::unique_ptr m_xWordED; + std::unique_ptr m_xReplaceFT; + std::unique_ptr m_xReplaceED; + std::unique_ptr m_xSingleColumnLB; + std::unique_ptr m_xDoubleColumnLB; + std::unique_ptr m_xNewReplacePB; + std::unique_ptr m_xDeletePB; + + DECL_LINK(SelectBookHdl_Impl, weld::ComboBox&, void); + DECL_LINK(SelectLangHdl_Impl, weld::ComboBox&, void); + DECL_LINK(SelectHdl, weld::TreeView&, void); + DECL_LINK(NewDelButtonHdl, weld::Button&, void); + DECL_LINK(NewDelActionHdl, weld::Entry&, bool); + DECL_LINK(ModifyHdl, weld::Entry&, void); + DECL_LINK(EntrySizeAllocHdl, const Size&, void); + DECL_STATIC_LINK(SvxEditDictionaryDialog, InsertTextHdl, OUString&, bool); + bool NewDelHdl(const weld::Widget*); + + void ShowWords_Impl( sal_uInt16 nId ); + void SetLanguage_Impl( LanguageType nLanguage ); + bool IsDicReadonly_Impl() const { return bDicIsReadonly; } + void SetDicReadonly_Impl( css::uno::Reference< + css::linguistic2::XDictionary > const &xDic ); + + void RemoveDictEntry(int nEntry); + int GetLBInsertPos(const OUString &rDicWord); + +public: + SvxEditDictionaryDialog(weld::Window* pParent, const OUString& rName); + virtual ~SvxEditDictionaryDialog() override; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/optlingu.hxx b/cui/source/inc/optlingu.hxx new file mode 100644 index 000000000..cbaaaefdf --- /dev/null +++ b/cui/source/inc/optlingu.hxx @@ -0,0 +1,152 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_OPTLINGU_HXX +#define INCLUDED_CUI_SOURCE_INC_OPTLINGU_HXX + +#include +#include +#include +#include + +namespace com::sun::star{ + namespace beans{ + class XPropertySet; + } + namespace linguistic2{ + class XDictionary; + class XDictionaryList; + class XLinguProperties; + } +} + +class SvTreeListEntry; +class SvxLinguData_Impl; + +// define ---------------------------------------------------------------- + +#define GROUP_MODULES (sal_uInt16(0x0008)) + +// forward --------------------------------------------------------------- + +class SvxEditModulesDlg : public weld::GenericDialogController +{ + OUString sSpell; + OUString sHyph; + OUString sThes; + OUString sGrammar; + + std::unique_ptr pDefaultLinguData; + SvxLinguData_Impl& rLinguData; + + std::unique_ptr m_xModulesCLB; + std::unique_ptr m_xPrioUpPB; + std::unique_ptr m_xPrioDownPB; + std::unique_ptr m_xBackPB; + std::unique_ptr m_xMoreDictsLink; + std::unique_ptr m_xClosePB; + std::unique_ptr m_xLanguageLB; + + DECL_LINK( SelectHdl_Impl, weld::TreeView&, void ); + DECL_LINK( UpDownHdl_Impl, weld::Button&, void ); + DECL_LINK( ClickHdl_Impl, weld::Button&, void ); + DECL_LINK( BackHdl_Impl, weld::Button&, void ); + DECL_LINK( LangSelectListBoxHdl_Impl, weld::ComboBox&, void ); + typedef std::pair row_col; + DECL_LINK( BoxCheckButtonHdl_Impl, const row_col&, void ); + void LangSelectHdl_Impl(const SvxLanguageBox* pBox); + +public: + SvxEditModulesDlg(weld::Window* pParent, SvxLinguData_Impl& rData); + virtual ~SvxEditModulesDlg() override; +}; + +struct ImplSVEvent; + +// class SvxLinguTabPage ------------------------------------------------- +class SvxLinguTabPage : public SfxTabPage +{ +private: + OUString sCapitalWords; + OUString sWordsWithDigits; + OUString sSpellSpecial; + OUString sSpellAuto; + OUString sGrammarAuto; + OUString sNumMinWordlen; + OUString sNumPreBreak; + OUString sNumPostBreak; + OUString sHyphAuto; + OUString sHyphSpecial; + + int nUPN_HYPH_MIN_WORD_LENGTH; + int nUPN_HYPH_MIN_LEADING; + int nUPN_HYPH_MIN_TRAILING; + + ImplSVEvent* m_nDlbClickEventId; + + css::uno::Reference< + css::linguistic2::XLinguProperties > xProp; + + css::uno::Reference< + css::linguistic2::XDictionaryList > xDicList; + css::uno::Sequence< + css::uno::Reference< + css::linguistic2::XDictionary > > aDics; + + std::unique_ptr pLinguData; + + std::unique_ptr m_xLinguModulesFT; + std::unique_ptr m_xLinguModulesCLB; + std::unique_ptr m_xLinguModulesEditPB; + std::unique_ptr m_xLinguDicsFT; + std::unique_ptr m_xLinguDicsCLB; + std::unique_ptr m_xLinguDicsNewPB; + std::unique_ptr m_xLinguDicsEditPB; + std::unique_ptr m_xLinguDicsDelPB; + std::unique_ptr m_xLinguOptionsCLB; + std::unique_ptr m_xLinguOptionsEditPB; + std::unique_ptr m_xMoreDictsLink; + + void AddDicBoxEntry( const css::uno::Reference< css::linguistic2::XDictionary > &rxDic, sal_uInt16 nIdx ); + static sal_uInt32 GetDicUserData( const css::uno::Reference< css::linguistic2::XDictionary > &rxDic, sal_uInt16 nIdx ); + + DECL_LINK( SelectHdl_Impl, weld::TreeView&, void ); + DECL_LINK( ClickHdl_Impl, weld::Button&, void ); + DECL_LINK( BoxDoubleClickHdl_Impl, weld::TreeView&, bool ); + typedef std::pair row_col; + DECL_LINK( ModulesBoxCheckButtonHdl_Impl, const row_col&, void ); + DECL_LINK( DicsBoxCheckButtonHdl_Impl, const row_col&, void ); + DECL_LINK( PostDblClickHdl_Impl, void *, void); + + void UpdateModulesBox_Impl(); + void UpdateDicBox_Impl(); + +public: + SvxLinguTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreSet); + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet ); + virtual ~SvxLinguTabPage() override; + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; + + void HideGroups( sal_uInt16 nGrp ); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/optpath.hxx b/cui/source/inc/optpath.hxx new file mode 100644 index 000000000..cc3d67b42 --- /dev/null +++ b/cui/source/inc/optpath.hxx @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_OPTPATH_HXX +#define INCLUDED_CUI_SOURCE_INC_OPTPATH_HXX + +#include +#include + +#include +#include + +// forward --------------------------------------------------------------- +struct OptPath_Impl; +class SvxPathTabPage; + +// class SvxPathTabPage -------------------------------------------------- +class SvxPathTabPage : public SfxTabPage +{ +private: + std::unique_ptr pImpl; + + rtl::Reference< ::svt::DialogClosedListener > xDialogListener; + css::uno::Reference< css::ui::dialogs::XFolderPicker2 > xFolderPicker; + + std::unique_ptr m_xStandardBtn; + std::unique_ptr m_xPathBtn; + std::unique_ptr m_xPathBox; + + void ChangeCurrentEntry( const OUString& _rFolder ); + + DECL_LINK(PathHdl_Impl, weld::Button&, void); + DECL_LINK(DoubleClickPathHdl_Impl, weld::TreeView&, bool); + DECL_LINK(StandardHdl_Impl, weld::Button&, void); + + DECL_LINK(PathSelect_Impl, weld::TreeView&, void); + + DECL_LINK(DialogClosedHdl, css::ui::dialogs::DialogClosedEvent*, void); + + void GetPathList( sal_uInt16 _nPathHandle, OUString& _rInternalPath, + OUString& _rUserPath, OUString& _rWritablePath, bool& _rReadOnly ); + void SetPathList( sal_uInt16 _nPathHandle, + const OUString& _rUserPath, const OUString& _rWritablePath ); + +public: + SvxPathTabPage( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet ); + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet ); + virtual ~SvxPathTabPage() override; + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/page.hxx b/cui/source/inc/page.hxx new file mode 100644 index 000000000..1019a9fbc --- /dev/null +++ b/cui/source/inc/page.hxx @@ -0,0 +1,185 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_PAGE_HXX +#define INCLUDED_CUI_SOURCE_INC_PAGE_HXX + +#include +#include +#include +#include +#include +#include +#include + +// class SvxPageDescPage ------------------------------------------------- +/* + [Description] + TabPage for page settings (size, margins, ...) + + [Items] + : + : + : + : + : + : + : + : + : + + : + : + : + : + : + : + : + + : + : + : + : + : + : + : +*/ + +typedef sal_uInt16 MarginPosition; + +class SvxPageDescPage : public SfxTabPage +{ + static const sal_uInt16 pRanges[]; +private: + OUString sStandardRegister; + long nFirstLeftMargin; + long nFirstRightMargin; + long nFirstTopMargin; + long nFirstBottomMargin; + long nLastLeftMargin; + long nLastRightMargin; + long nLastTopMargin; + long nLastBottomMargin; + + bool bLandscape; + bool bBorderModified; + SvxModeType eMode; + Paper ePaperStart; + + MarginPosition m_nPos; + VclPtr mpDefPrinter; + + bool mbDelPrinter : 1; + bool mbEnableDrawingLayerFillStyles : 1; + + SvxPageWindow m_aBspWin; + + // paper format + std::unique_ptr m_xPaperSizeBox; + std::unique_ptr m_xPaperWidthEdit; + std::unique_ptr m_xPaperHeightEdit; + std::unique_ptr m_xOrientationFT; + std::unique_ptr m_xPortraitBtn; + std::unique_ptr m_xLandscapeBtn; + std::unique_ptr m_xTextFlowLbl; + std::unique_ptr m_xTextFlowBox; + std::unique_ptr m_xPaperTrayBox; + // Margins + std::unique_ptr m_xLeftMarginLbl; + std::unique_ptr m_xLeftMarginEdit; + std::unique_ptr m_xRightMarginLbl; + std::unique_ptr m_xRightMarginEdit; + std::unique_ptr m_xTopMarginEdit; + std::unique_ptr m_xBottomMarginEdit; + // layout settings + std::unique_ptr m_xPageText; + std::unique_ptr m_xLayoutBox; + std::unique_ptr m_xNumberFormatText; + std::unique_ptr m_xNumberFormatBox; + //Extras Calc + std::unique_ptr m_xTblAlignFT; + std::unique_ptr m_xHorzBox; + std::unique_ptr m_xVertBox; + // Impress and Draw + std::unique_ptr m_xAdaptBox; + //Register Writer + std::unique_ptr m_xRegisterCB; + std::unique_ptr m_xRegisterFT; + std::unique_ptr m_xRegisterLB; + std::unique_ptr m_xInsideLbl; + std::unique_ptr m_xOutsideLbl; + std::unique_ptr m_xPrintRangeQueryText; + std::unique_ptr m_xBspWin; + + void Init_Impl(); + DECL_LINK(LayoutHdl_Impl, weld::ComboBox&, void); + DECL_LINK(PaperBinHdl_Impl, weld::Widget&, void); + DECL_LINK(SwapOrientation_Impl, weld::Button&, void); + void SwapFirstValues_Impl( bool bSet ); + DECL_LINK(BorderModify_Impl, weld::MetricSpinButton&, void); + void InitHeadFoot_Impl( const SfxItemSet& rSet ); + DECL_LINK(CenterHdl_Impl, weld::ToggleButton&, void); + void UpdateExample_Impl( bool bResetbackground = false ); + + DECL_LINK(PaperSizeSelect_Impl, weld::ComboBox&, void ); + DECL_LINK(PaperSizeModify_Impl, weld::MetricSpinButton&, void); + + DECL_LINK(FrameDirectionModify_Impl, weld::ComboBox&, void ); + + void ResetBackground_Impl( const SfxItemSet& rSet ); + + void RangeHdl_Impl(); + void CalcMargin_Impl(); + + DECL_LINK(RegisterModify, weld::ToggleButton&, void); + + // page direction + /** Disables vertical page direction entries in the text flow listbox. */ + void DisableVerticalPageDir(); + + bool IsPrinterRangeOverflow(weld::MetricSpinButton& rField, long nFirstMargin, + long nLastMargin, MarginPosition nPos); + void CheckMarginEdits( bool _bClear ); + bool IsMarginOutOfRange() const; + +protected: + virtual void ActivatePage( const SfxItemSet& rSet ) override; + virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override; + +public: + SvxPageDescPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet ); + virtual ~SvxPageDescPage() override; + + // returns the range of the Which values + static const sal_uInt16* GetRanges() { return pRanges; } + + virtual bool FillItemSet( SfxItemSet* rOutSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; + virtual void FillUserData() override; + + void SetPaperFormatRanges( Paper eStart ) + { ePaperStart = eStart; } + + void SetCollectionList(const std::vector &aList); + virtual void PageCreated(const SfxAllItemSet& aSet) override; +}; + +#endif // INCLUDED_CUI_SOURCE_INC_PAGE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/paragrph.hxx b/cui/source/inc/paragrph.hxx new file mode 100644 index 000000000..b57199d91 --- /dev/null +++ b/cui/source/inc/paragrph.hxx @@ -0,0 +1,304 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_PARAGRPH_HXX +#define INCLUDED_CUI_SOURCE_INC_PARAGRPH_HXX + +#include +#include +#include +#include + +class SvxLineSpacingItem; + +// class SvxStdParagraphTabPage ------------------------------------------ +/* + [Description] + With this TabPage standard attributes of a paragraph can be set + (indention, distance, alignment, line spacing). + + [Items] + + + + +*/ + +class SvxStdParagraphTabPage: public SfxTabPage +{ + static const sal_uInt16 pStdRanges[]; + +private: + long nWidth; + long nMinFixDist; + bool bRelativeMode; + OUString sAbsDist; + + SvxParaPrevWindow m_aExampleWin; + + // indention + std::unique_ptr m_xLeftIndent; + + std::unique_ptr m_xRightLabel; + std::unique_ptr m_xRightIndent; + + std::unique_ptr m_xFLineLabel; + std::unique_ptr m_xFLineIndent; + std::unique_ptr m_xAutoCB; + + // distance + std::unique_ptr m_xTopDist; + std::unique_ptr m_xBottomDist; + std::unique_ptr m_xContextualCB; + + // line spacing + std::unique_ptr m_xLineDist; + std::unique_ptr m_xLineDistAtPercentBox; + std::unique_ptr m_xLineDistAtMetricBox; + std::unique_ptr m_xLineDistAtLabel; + std::unique_ptr m_xAbsDist; + + // only writer + std::unique_ptr m_xRegisterFL; + std::unique_ptr m_xRegisterCB; + + // preview + std::unique_ptr m_xExampleWin; + + void SetLineSpacing_Impl( const SvxLineSpacingItem& rAttr ); + void Init_Impl(); + void UpdateExample_Impl(); + void ELRLoseFocus(); + + DECL_LINK(LineDistPopupHdl_Impl, weld::ComboBox&, void); + DECL_LINK(LineDistHdl_Impl, weld::ComboBox&, void); + DECL_LINK(ModifyHdl_Impl, weld::MetricSpinButton&, void); + DECL_LINK(AutoHdl_Impl, weld::ToggleButton&, void); + + bool m_bLineDistToggled = false; + +protected: + virtual void ActivatePage( const SfxItemSet& rSet ) override; + virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override; + + +public: + SvxStdParagraphTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet ); + virtual ~SvxStdParagraphTabPage() override; + + DECL_LINK(ELRLoseFocusHdl, weld::MetricSpinButton&, void); + + static const sal_uInt16* GetRanges() { return pStdRanges; } + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; + virtual void ChangesApplied() override; + + void EnableRelativeMode(); + void EnableRegisterMode(); + void EnableContextualMode(); + void EnableAutoFirstLine(); + void EnableAbsLineDist(long nMinTwip); + void EnableNegativeMode(); + virtual void PageCreated(const SfxAllItemSet& aSet) override; +}; + +// class SvxParaAlignTabPage ------------------------------------------------ + +class SvxParaAlignTabPage : public SfxTabPage +{ + static const sal_uInt16 pAlignRanges[]; + + SvxParaPrevWindow m_aExampleWin; + + // alignment + std::unique_ptr m_xLeft; + std::unique_ptr m_xRight; + std::unique_ptr m_xCenter; + std::unique_ptr m_xJustify; + std::unique_ptr m_xLeftBottom; + std::unique_ptr m_xRightTop; + + std::unique_ptr m_xLastLineFT; + std::unique_ptr m_xLastLineLB; + std::unique_ptr m_xExpandCB; + + std::unique_ptr m_xSnapToGridCB; + + //preview + std::unique_ptr m_xExampleWin; + //vertical alignment + std::unique_ptr m_xVertAlignFL; + std::unique_ptr m_xVertAlignLB; + + std::unique_ptr m_xPropertiesFL; + std::unique_ptr m_xTextDirectionLB; + + DECL_LINK(AlignHdl_Impl, weld::ToggleButton&, void); + DECL_LINK(LastLineHdl_Impl, weld::ComboBox&, void); + DECL_LINK(TextDirectionHdl_Impl, weld::ComboBox&, void); + + void UpdateExample_Impl(); + +protected: + virtual void ActivatePage( const SfxItemSet& rSet ) override; + virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override; + +public: + SvxParaAlignTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet ); + virtual ~SvxParaAlignTabPage() override; + + static const sal_uInt16* GetRanges() { return pAlignRanges; } + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; + virtual void ChangesApplied() override; + + void EnableJustifyExt(); + virtual void PageCreated(const SfxAllItemSet& aSet) override; +}; + +// class SvxExtParagraphTabPage ------------------------------------------ +/* + [Description] + With this TabPage special attributes of a paragraph can be set + (hyphenation, pagebreak, orphan, widow, ...). + + [Items] + + + + + +*/ + +class SvxExtParagraphTabPage: public SfxTabPage +{ + static const sal_uInt16 pExtRanges[]; + +public: + SvxExtParagraphTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rSet ); + virtual ~SvxExtParagraphTabPage() override; + + static const sal_uInt16* GetRanges() { return pExtRanges; } + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; + virtual void ChangesApplied() override; + + void DisablePageBreak(); + +protected: + virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override; + +private: + weld::TriStateEnabled aHyphenState; + weld::TriStateEnabled aPageBreakState; + weld::TriStateEnabled aApplyCollState; + weld::TriStateEnabled aPageNumState; + weld::TriStateEnabled aKeepTogetherState; + weld::TriStateEnabled aKeepParaState; + weld::TriStateEnabled aOrphanState; + weld::TriStateEnabled aWidowState; + + bool bPageBreak; + bool bHtmlMode; + sal_uInt16 nStdPos; + + // hyphenation + std::unique_ptr m_xHyphenBox; + std::unique_ptr m_xHyphenNoCapsBox; + std::unique_ptr m_xBeforeText; + std::unique_ptr m_xExtHyphenBeforeBox; + std::unique_ptr m_xAfterText; + std::unique_ptr m_xExtHyphenAfterBox; + std::unique_ptr m_xMaxHyphenLabel; + std::unique_ptr m_xMaxHyphenEdit; + + // pagebreak + std::unique_ptr m_xPageBreakBox; + std::unique_ptr m_xBreakTypeFT; + std::unique_ptr m_xBreakTypeLB; + std::unique_ptr m_xBreakPositionFT; + std::unique_ptr m_xBreakPositionLB; + std::unique_ptr m_xApplyCollBtn; + std::unique_ptr m_xApplyCollBox; + std::unique_ptr m_xPageNumBox; + std::unique_ptr m_xPagenumEdit; + + // paragraph division + std::unique_ptr m_xKeepTogetherBox; + std::unique_ptr m_xKeepParaBox; + + // orphan/widow + std::unique_ptr m_xOrphanBox; + std::unique_ptr m_xOrphanRowNo; + std::unique_ptr m_xOrphanRowLabel; + + std::unique_ptr m_xWidowBox; + std::unique_ptr m_xWidowRowNo; + std::unique_ptr m_xWidowRowLabel; + + void HyphenClickHdl(); + void PageNumBoxClickHdl(); + void ApplyCollClickHdl(); + void PageBreakHdl(); + void KeepTogetherHdl(); + void OrphanHdl(); + void WidowHdl(); + + DECL_LINK(PageBreakHdl_Impl, weld::ToggleButton&, void); + DECL_LINK(KeepTogetherHdl_Impl, weld::ToggleButton&, void); + DECL_LINK(WidowHdl_Impl, weld::ToggleButton&, void); + DECL_LINK(OrphanHdl_Impl, weld::ToggleButton&, void); + DECL_LINK(HyphenClickHdl_Impl, weld::ToggleButton&, void); + DECL_LINK(ApplyCollClickHdl_Impl, weld::ToggleButton&, void); + DECL_LINK(PageBreakPosHdl_Impl, weld::ComboBox&, void); + DECL_LINK(PageBreakTypeHdl_Impl, weld::ComboBox&, void); + DECL_LINK(PageNumBoxClickHdl_Impl, weld::ToggleButton&, void); + DECL_LINK(KeepParaBoxClickHdl_Impl, weld::ToggleButton&, void); + + virtual void PageCreated(const SfxAllItemSet& aSet) override; +}; + +class SvxAsianTabPage : public SfxTabPage +{ + std::unique_ptr m_xForbiddenRulesCB; + std::unique_ptr m_xHangingPunctCB; + std::unique_ptr m_xScriptSpaceCB; + +public: + SvxAsianTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + static std::unique_ptr Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet); + virtual ~SvxAsianTabPage() override; + + static const sal_uInt16* GetRanges(); + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; + virtual void ChangesApplied() override; +}; + +#endif // INCLUDED_CUI_SOURCE_INC_PARAGRPH_HXX + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/passwdomdlg.hxx b/cui/source/inc/passwdomdlg.hxx new file mode 100644 index 000000000..1f690ca39 --- /dev/null +++ b/cui/source/inc/passwdomdlg.hxx @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_PASSWDOMDLG_HXX +#define INCLUDED_CUI_SOURCE_INC_PASSWDOMDLG_HXX + +#include +#include + +class PasswordToOpenModifyDialog : public SfxDialogController +{ + std::unique_ptr m_xPasswdToOpenED; + std::unique_ptr m_xPasswdToOpenInd; + std::unique_ptr m_xReenterPasswdToOpenED; + std::unique_ptr m_xReenterPasswdToOpenInd; + std::unique_ptr m_xOptionsExpander; + std::unique_ptr m_xOk; + std::unique_ptr m_xOpenReadonlyCB; + std::unique_ptr m_xPasswdToModifyFT; + std::unique_ptr m_xPasswdToModifyED; + std::unique_ptr m_xPasswdToModifyInd; + std::unique_ptr m_xReenterPasswdToModifyFT; + std::unique_ptr m_xReenterPasswdToModifyED; + std::unique_ptr m_xReenterPasswdToModifyInd; + + OUString m_aOneMismatch; + OUString m_aTwoMismatch; + OUString m_aInvalidStateForOkButton; + OUString m_aInvalidStateForOkButton_v2; + OUString m_aIndicatorTemplate; + + int m_nMaxPasswdLen; + bool m_bIsPasswordToModify; + + + DECL_LINK(OkBtnClickHdl, weld::Button&, void); + DECL_LINK(ReadonlyOnOffHdl, weld::Button&, void); + DECL_LINK(ChangeHdl, weld::Entry&, void); + + PasswordToOpenModifyDialog( const PasswordToOpenModifyDialog & ) = delete; + PasswordToOpenModifyDialog & operator = ( const PasswordToOpenModifyDialog & ) = delete; + +public: + PasswordToOpenModifyDialog(weld::Window* pParent, + sal_uInt16 nMaxPasswdLen /* 0 -> no max len enforced */, + bool bIsPasswordToModify ); + + // AbstractPasswordToOpenModifyDialog + OUString GetPasswordToOpen() const; + OUString GetPasswordToModify() const; + bool IsRecommendToOpenReadonly() const; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/pastedlg.hxx b/cui/source/inc/pastedlg.hxx new file mode 100644 index 000000000..a9a691b4f --- /dev/null +++ b/cui/source/inc/pastedlg.hxx @@ -0,0 +1,76 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_CUI_SOURCE_INC_PASTEDLG_HXX +#define INCLUDED_CUI_SOURCE_INC_PASTEDLG_HXX + +#include +#include +#include +#include +#include + +struct TransferableObjectDescriptor; +class TransferableDataHelper; + +class SvPasteObjectDialog : public weld::GenericDialogController +{ + std::map< SotClipboardFormatId, OUString > aSupplementMap; + // Additional UNO command to be displayed along the supported paste formats + std::pair aExtraCommand; + SvGlobalName aObjClassName; + OUString aObjName; + + std::unique_ptr m_xFtObjectSource; + std::unique_ptr m_xLbInsertList; + std::unique_ptr m_xOKButton; + + weld::TreeView& ObjectLB() { return *m_xLbInsertList; } + + void SelectObject(); + DECL_LINK(SelectHdl, weld::TreeView&, void); + DECL_LINK(DoubleClickHdl, weld::TreeView&, bool); + +public: + SvPasteObjectDialog(weld::Window* pParent); + + void Insert( SotClipboardFormatId nFormat, const OUString & rFormatName ); + void InsertUno( const OUString& sUnoCmd, const OUString& sLabel); + void SetObjName( const SvGlobalName & rClass, const OUString & rObjName ); + /** + * @brief PreGetFormat Prepares the dialog for running to get format of paste as a SotClipboardFormatId value by calling GetFormatOnly() + * @param aHelper + */ + void PreGetFormat( const TransferableDataHelper& aHelper); + /** + * @brief GetFormatOnly Returns a SotClipboardFormatId value. Should be called after actually running the dialog. + * @return + */ + SotClipboardFormatId GetFormatOnly(); + /** + * @brief GetFormat Prepares and runs the dialog, and returns a SotClipboardFormatId depending on the RET_OK result + * @param aHelper TransferableDataHelper containing the data to be pasted + * @return a SotClipboardFormatId value depending on the result of running the dialog + */ + SotClipboardFormatId GetFormat( const TransferableDataHelper& aHelper); +}; + +#endif // INCLUDED_CUI_SOURCE_INC_PASTEDLG_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/postdlg.hxx b/cui/source/inc/postdlg.hxx new file mode 100644 index 000000000..62a3379b9 --- /dev/null +++ b/cui/source/inc/postdlg.hxx @@ -0,0 +1,103 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_POSTDLG_HXX +#define INCLUDED_CUI_SOURCE_INC_POSTDLG_HXX + +#include + +// class SvxPostItDialog ------------------------------------------------- +/* + [Description] + In this dialog a note can be created or edited. If the + application holds a list of notes, it can be iterated + over this list with links. + + [Items] + + + +*/ + +class SvxPostItDialog : public SfxDialogController +{ +public: + SvxPostItDialog(weld::Widget* pParent, const SfxItemSet& rCoreSet, + bool bPrevNext); + virtual ~SvxPostItDialog() override; + + static const sal_uInt16* GetRanges(); + const SfxItemSet* GetOutputItemSet() const { return m_xOutSet.get(); } + + void SetPrevHdl( const Link& rLink ) + { m_aPrevHdlLink = rLink; } + void SetNextHdl( const Link& rLink ) + { m_aNextHdlLink = rLink; } + + void EnableTravel(bool bNext, bool bPrev); + OUString GetNote() const + { + return m_xEditED->get_text(); + } + void SetNote(const OUString& rTxt) + { + m_xEditED->set_text(rTxt); + } + void ShowLastAuthor(const OUString& rAuthor, const OUString& rDate); + void DontChangeAuthor() + { + m_xAuthorBtn->set_sensitive(false); + } + void HideAuthor() + { + m_xInsertAuthor->hide(); + } + void set_title(const OUString& rTitle) + { + m_xDialog->set_title(rTitle); + } + std::shared_ptr const & GetDialog() const + { + return m_xDialog; + } + +private: + const SfxItemSet& m_rSet; + std::unique_ptr m_xOutSet; + + Link m_aPrevHdlLink; + Link m_aNextHdlLink; + + std::unique_ptr m_xLastEditFT; + std::unique_ptr m_xAltTitle; + std::unique_ptr m_xEditED; + std::unique_ptr m_xInsertAuthor; + std::unique_ptr m_xAuthorBtn; + std::unique_ptr m_xOKBtn; + std::unique_ptr m_xPrevBtn; + std::unique_ptr m_xNextBtn; + + DECL_LINK(Stamp, weld::Button&, void); + DECL_LINK(OKHdl, weld::Button&, void); + DECL_LINK(PrevHdl, weld::Button&, void); + DECL_LINK(NextHdl, weld::Button&, void); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/screenshotannotationdlg.hxx b/cui/source/inc/screenshotannotationdlg.hxx new file mode 100644 index 000000000..94972219d --- /dev/null +++ b/cui/source/inc/screenshotannotationdlg.hxx @@ -0,0 +1,42 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_SCREENSHANNDLG_HXX +#define INCLUDED_CUI_SOURCE_INC_SCREENSHANNDLG_HXX + +#include +#include + +class ScreenshotAnnotationDlg_Impl; + +class ScreenshotAnnotationDlg : public weld::GenericDialogController +{ +private: + std::unique_ptr< ScreenshotAnnotationDlg_Impl > m_pImpl; + + ScreenshotAnnotationDlg(const ScreenshotAnnotationDlg &) = delete; + ScreenshotAnnotationDlg& operator=(const ScreenshotAnnotationDlg &) = delete; + +public: + ScreenshotAnnotationDlg(weld::Dialog& rParentDialog); + virtual ~ScreenshotAnnotationDlg() override; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/scriptdlg.hxx b/cui/source/inc/scriptdlg.hxx new file mode 100644 index 000000000..7ae0f3335 --- /dev/null +++ b/cui/source/inc/scriptdlg.hxx @@ -0,0 +1,171 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_CUI_SOURCE_INC_SCRIPTDLG_HXX +#define INCLUDED_CUI_SOURCE_INC_SCRIPTDLG_HXX + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#define OBJTYPE_METHOD 2L +#define OBJTYPE_SCRIPTCONTAINER 3L +#define OBJTYPE_SFROOT 4L + +typedef std::unordered_map < OUString, OUString > Selection_hash; + +class SFEntry; + +enum class InputDialogMode { + NEWLIB = 1, + NEWMACRO = 2, + RENAME = 3, +}; + +class CuiInputDialog : public weld::GenericDialogController +{ +private: + std::unique_ptr m_xEdit; +public: + CuiInputDialog(weld::Window * pParent, InputDialogMode nMode); + OUString GetObjectName() const { return m_xEdit->get_text(); } + void SetObjectName(const OUString& rName) + { + m_xEdit->set_text(rName); + m_xEdit->select_region(0, -1); + } +}; + +class SFEntry final +{ +private: + bool loaded; + css::uno::Reference< css::script::browse::XBrowseNode > nodes; + css::uno::Reference< css::frame::XModel > model; +public: + SFEntry( const css::uno::Reference< css::script::browse::XBrowseNode >& entryNodes , + const css::uno::Reference< css::frame::XModel >& entryModel) { nodes = entryNodes; loaded=false; model = entryModel; } + SFEntry( const SFEntry& r ) { nodes = r.nodes; loaded = r.loaded; } + const css::uno::Reference< css::script::browse::XBrowseNode >& GetNode() const { return nodes ;} + const css::uno::Reference< css::frame::XModel >& GetModel() const { return model ;}; + bool isLoaded() const { return loaded; } + void setLoaded() { loaded=true; } +}; + +class SvxScriptOrgDialog : public SfxDialogController +{ +protected: + OUString m_sLanguage; + static Selection_hash m_lastSelection; + const OUString m_delErrStr; + const OUString m_delErrTitleStr; + const OUString m_delQueryStr; + const OUString m_delQueryTitleStr; + const OUString m_createErrStr; + const OUString m_createDupStr; + const OUString m_createErrTitleStr; + const OUString m_renameErrStr; + const OUString m_renameErrTitleStr; + const OUString m_sMyMacros; + const OUString m_sProdMacros; + + std::unique_ptr m_xScriptsBox; + std::unique_ptr m_xRunButton; + std::unique_ptr m_xCloseButton; + std::unique_ptr m_xCreateButton; + std::unique_ptr m_xEditButton; + std::unique_ptr m_xRenameButton; + std::unique_ptr m_xDelButton; + + DECL_LINK( ScriptSelectHdl, weld::TreeView&, void ); + DECL_LINK( ExpandingHdl, const weld::TreeIter&, bool ); + DECL_LINK( ButtonHdl, weld::Button&, void ); + static bool getBoolProperty( css::uno::Reference< css::beans::XPropertySet > const & xProps, OUString const & propName ); + void CheckButtons( css::uno::Reference< css::script::browse::XBrowseNode > const & node ); + + void createEntry(weld::TreeIter& rEntry); + void renameEntry(const weld::TreeIter& rEntry); + void deleteEntry(weld::TreeIter& rEntry); + css::uno::Reference getBrowseNode(const weld::TreeIter& rEntry); + css::uno::Reference getModel(const weld::TreeIter& rEntry); + OUString getListOfChildren( const css::uno::Reference< css::script::browse::XBrowseNode >& node, int depth ); + void StoreCurrentSelection(); + void RestorePreviousSelection(); + + void Init(const OUString& language); + void delUserData(const weld::TreeIter& rIter); + void deleteTree(weld::TreeIter& rIter); + void deleteAllTree(); + void insertEntry(OUString const & rText, OUString const & rBitmap, + const weld::TreeIter* pParent, + bool bChildrenOnDemand, + std::unique_ptr< SFEntry > && aUserData, + const OUString& factoryURL, bool bSelect); + void insertEntry(OUString const & rText, OUString const & rBitmap, + const weld::TreeIter* pParent, + bool bChildrenOnDemand, + std::unique_ptr< SFEntry > && aUserData, + bool bSelect); + + void RequestSubEntries(const weld::TreeIter& rRootEntry, + css::uno::Reference< css::script::browse::XBrowseNode > const & node, + css::uno::Reference< css::frame::XModel>& model); + + static css::uno::Reference< css::script::browse::XBrowseNode > + getLangNodeFromRootNode( css::uno::Reference< css::script::browse::XBrowseNode > const & root, OUString const & language ); + + static css::uno::Reference< css::uno::XInterface > getDocumentModel( css::uno::Reference< css::uno::XComponentContext > const & xCtx, OUString const & docName ); + +public: + // prob need another arg in the ctor + // to specify the language or provider + SvxScriptOrgDialog(weld::Window* pParent, const OUString& language); + virtual ~SvxScriptOrgDialog() override; + + virtual short run() override; +}; + +class SvxScriptErrorDialog : public VclAbstractDialog +{ +private: + + OUString m_sMessage; + + DECL_STATIC_LINK( SvxScriptErrorDialog, ShowDialog, void*, void ); + +public: + + SvxScriptErrorDialog( css::uno::Any const & aException ); + + virtual ~SvxScriptErrorDialog() override; + + short Execute() override; +}; + +#endif // INCLUDED_CUI_SOURCE_INC_SCRIPTDLG_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/sdrcelldlg.hxx b/cui/source/inc/sdrcelldlg.hxx new file mode 100644 index 000000000..50ab4b39a --- /dev/null +++ b/cui/source/inc/sdrcelldlg.hxx @@ -0,0 +1,49 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_CUI_SOURCE_INC_SDRCELLDLG_HXX +#define INCLUDED_CUI_SOURCE_INC_SDRCELLDLG_HXX + + +#include +#include + +class SdrModel; +class SvxFormatCellsDialog : public SfxTabDialogController +{ +private: + const SfxItemSet& mrOutAttrs; + + XColorListRef mpColorTab; + XGradientListRef mpGradientList; + XHatchListRef mpHatchingList; + XBitmapListRef mpBitmapList; + XPatternListRef mpPatternList; + +public: + SvxFormatCellsDialog(weld::Window* pParent, const SfxItemSet* pAttr, const SdrModel& rModel); + + virtual void PageCreated(const OString& rId, SfxTabPage &rPage) override; + +}; + +#endif // INCLUDED_CUI_SOURCE_INC_SDRCELLDLG_HXX + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/showcols.hxx b/cui/source/inc/showcols.hxx new file mode 100644 index 000000000..3b15abfd3 --- /dev/null +++ b/cui/source/inc/showcols.hxx @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_CUI_SOURCE_INC_SHOWCOLS_HXX +#define INCLUDED_CUI_SOURCE_INC_SHOWCOLS_HXX + +#include +#include +#include + +// FmShowColsDialog + +class FmShowColsDialog final : public weld::GenericDialogController +{ + std::unique_ptr m_xList; + std::unique_ptr m_xOK; + + css::uno::Reference m_xColumns; + +public: + FmShowColsDialog(weld::Window* pParent); + virtual ~FmShowColsDialog() override; + + void SetColumns(const css::uno::Reference& xCols); + +private: + DECL_LINK(OnClickedOk, weld::Button&, void); +}; + +#endif // INCLUDED_CUI_SOURCE_INC_SHOWCOLS_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/splitcelldlg.hxx b/cui/source/inc/splitcelldlg.hxx new file mode 100644 index 000000000..b0c2fddae --- /dev/null +++ b/cui/source/inc/splitcelldlg.hxx @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_SPLITCELLDLG_HXX +#define INCLUDED_CUI_SOURCE_INC_SPLITCELLDLG_HXX + +#include +#include + +class SvxSplitTableDlg : public SvxAbstractSplitTableDialog, public weld::GenericDialogController +{ +private: + std::unique_ptr m_xCountEdit; + std::unique_ptr m_xHorzBox; + std::unique_ptr m_xVertBox; + std::unique_ptr m_xPropCB; + + long mnMaxVertical; + long mnMaxHorizontal; + +public: + SvxSplitTableDlg(weld::Window *pParent, bool bIsTableVertical, long nMaxVertical, long nMaxHorizontal); + + DECL_LINK(ClickHdl, weld::Button&, void); + + virtual bool IsHorizontal() const override; + virtual bool IsProportional() const override; + virtual long GetCount() const override; + + virtual short Execute() override; + virtual void SetSplitVerticalByDefault() override; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/srchxtra.hxx b/cui/source/inc/srchxtra.hxx new file mode 100644 index 000000000..5513ae236 --- /dev/null +++ b/cui/source/inc/srchxtra.hxx @@ -0,0 +1,84 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_SRCHXTRA_HXX +#define INCLUDED_CUI_SOURCE_INC_SRCHXTRA_HXX + +#include +#include +#include +#include + +class SvxSearchFormatDialog : public SfxTabDialogController +{ +public: + SvxSearchFormatDialog(weld::Window* pParent, const SfxItemSet& rSet); + virtual ~SvxSearchFormatDialog() override; + +protected: + virtual void PageCreated(const OString& rId, SfxTabPage &rPage) override; + +private: + std::unique_ptr m_pFontList; +}; + +// class SvxSearchFormatDialog ------------------------------------------- + +class SvxSearchAttributeDialog : public weld::GenericDialogController +{ +public: + SvxSearchAttributeDialog(weld::Window* pParent, SearchAttrItemList& rLst, + const sal_uInt16* pWhRanges); + virtual ~SvxSearchAttributeDialog() override; + +private: + SearchAttrItemList& rList; + + std::unique_ptr m_xAttrLB; + std::unique_ptr m_xOKBtn; + + DECL_LINK(OKHdl, weld::Button&, void); +}; + +// class SvxSearchSimilarityDialog --------------------------------------- + +class SvxSearchSimilarityDialog : public weld::GenericDialogController +{ +private: + std::unique_ptr m_xOtherFld; + std::unique_ptr m_xLongerFld; + std::unique_ptr m_xShorterFld; + std::unique_ptr m_xRelaxBox; + +public: + SvxSearchSimilarityDialog(weld::Window* pParent, + bool bRelax, + sal_uInt16 nOther, + sal_uInt16 nShorter, + sal_uInt16 nLonger); + virtual ~SvxSearchSimilarityDialog() override; + + sal_uInt16 GetOther() const { return static_cast(m_xOtherFld->get_value()); } + sal_uInt16 GetShorter() const { return static_cast(m_xShorterFld->get_value()); } + sal_uInt16 GetLonger() const { return static_cast(m_xLongerFld->get_value()); } + bool IsRelaxed() const { return m_xRelaxBox->get_active(); } +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/swpossizetabpage.hxx b/cui/source/inc/swpossizetabpage.hxx new file mode 100644 index 000000000..1fe926566 --- /dev/null +++ b/cui/source/inc/swpossizetabpage.hxx @@ -0,0 +1,133 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_SWPOSSIZETABPAGE_HXX +#define INCLUDED_CUI_SOURCE_INC_SWPOSSIZETABPAGE_HXX + +#include +#include +#include + +// SvxSwPosSizeTabPage - position and size page for Writer drawing objects +struct FrmMap; +class SdrView; +struct SvxSwFrameValidation; +enum class SvxAnchorIds; + +class SvxSwPosSizeTabPage : public SfxTabPage +{ + Link m_aValidateLink; + + ::tools::Rectangle m_aRect; //size of all selected objects + ::tools::Rectangle m_aWorkArea; + Point m_aAnchorPos; + + FrmMap const * m_pVMap; + FrmMap const * m_pHMap; + const SdrView* m_pSdrView; + + // initial values + short m_nOldH; + short m_nOldHRel; + short m_nOldV; + short m_nOldVRel; + + double m_fWidthHeightRatio; //width-to-height ratio to support the KeepRatio button + bool m_bHtmlMode; + bool m_bIsVerticalFrame; + bool m_bPositioningDisabled; + bool m_bIsMultiSelection; + bool m_bIsInRightToLeft; + TriState m_nProtectSizeState; + + SwFrameExample m_aExampleWN; + + std::unique_ptr m_xWidthMF; + std::unique_ptr m_xHeightMF; + std::unique_ptr m_xKeepRatioCB; + std::unique_ptr m_xToPageRB; + std::unique_ptr m_xToParaRB; + std::unique_ptr m_xToCharRB; + std::unique_ptr m_xAsCharRB; + std::unique_ptr m_xToFrameRB; + std::unique_ptr m_xPositionCB; + std::unique_ptr m_xSizeCB; + std::unique_ptr m_xPosFrame; + std::unique_ptr m_xHoriFT; + std::unique_ptr m_xHoriLB; + std::unique_ptr m_xHoriByFT; + std::unique_ptr m_xHoriByMF; + std::unique_ptr m_xHoriToFT; + std::unique_ptr m_xHoriToLB; + std::unique_ptr m_xHoriMirrorCB; + std::unique_ptr m_xVertFT; + std::unique_ptr m_xVertLB; + std::unique_ptr m_xVertByFT; + std::unique_ptr m_xVertByMF; + std::unique_ptr m_xVertToFT; + std::unique_ptr m_xVertToLB; + std::unique_ptr m_xFollowCB; + std::unique_ptr m_xExampleWN; + + DECL_LINK(RangeModifyHdl, weld::Widget&, void); + DECL_LINK(RangeModifyClickHdl, weld::ToggleButton&, void); + DECL_LINK(AnchorTypeHdl, weld::ToggleButton&, void); + DECL_LINK(PosHdl, weld::ComboBox&, void); + DECL_LINK(RelHdl, weld::ComboBox&, void); + DECL_LINK(MirrorHdl, weld::ToggleButton&, void); + DECL_LINK(ModifyHdl, weld::MetricSpinButton&, void); + DECL_LINK(ProtectHdl, weld::ToggleButton&, void); + + void InitPos(RndStdIds nAnchorType, sal_uInt16 nH, sal_uInt16 nHRel, + sal_uInt16 nV, sal_uInt16 nVRel, + long nX, long nY); + static sal_uInt16 GetMapPos(FrmMap const *pMap, const weld::ComboBox& rAlignLB); + static short GetAlignment(FrmMap const *pMap, sal_uInt16 nMapPos, const weld::ComboBox& rRelationLB); + static short GetRelation(const weld::ComboBox& rRelationLB); + RndStdIds GetAnchorType(bool* pbHasChanged = nullptr); + void FillRelLB(FrmMap const *pMap, sal_uInt16 nLBSelPos, sal_uInt16 nAlign, sal_uInt16 nRel, weld::ComboBox& rLB, weld::Label& rFT); + sal_uInt16 FillPosLB(FrmMap const *pMap, sal_uInt16 nAlign, const sal_uInt16 _nRel, weld::ComboBox& rLB); + + void UpdateExample(); + + void setOptimalFrmWidth(); + void setOptimalRelWidth(); + +public: + SvxSwPosSizeTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* ); + virtual ~SvxSwPosSizeTabPage() override; + + static const sal_uInt16* GetRanges(); + + virtual bool FillItemSet( SfxItemSet* ) override; + virtual void Reset( const SfxItemSet * ) override; + + virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override; + + void EnableAnchorTypes(SvxAnchorIds nAnchorEnable); + + void SetValidateFramePosLink( const Link& rLink ) + {m_aValidateLink = rLink;} + + void SetView( const SdrView* pSdrView ); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/tabstpge.hxx b/cui/source/inc/tabstpge.hxx new file mode 100644 index 000000000..6c9e63b10 --- /dev/null +++ b/cui/source/inc/tabstpge.hxx @@ -0,0 +1,149 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_TABSTPGE_HXX +#define INCLUDED_CUI_SOURCE_INC_TABSTPGE_HXX + +#include +#include +#include + +#include +#include + +class SvxTabulatorTabPage; + +// class TabWin_Impl ----------------------------------------------------- + +class TabWin_Impl : public weld::CustomWidgetController +{ +private: + sal_uInt16 nTabStyle; + +public: + + TabWin_Impl() : nTabStyle(0) + { + } + virtual void Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle& rRect) override; + + void SetTabStyle(sal_uInt16 nStyle) {nTabStyle = nStyle; } +}; + +// class SvxTabulatorTabPage --------------------------------------------- +/* + [Description] + In this TabPage tabulators are managed. + + [Items] + + + + +*/ + +class SvxTabulatorTabPage : public SfxTabPage +{ + static const sal_uInt16 pRanges[]; + +public: + SvxTabulatorTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet ); + virtual ~SvxTabulatorTabPage() override; + + static const sal_uInt16* GetRanges() { return pRanges; } + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; + + void DisableControls( const TabulatorDisableFlags nFlag ); + +protected: + virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override; + +private: + // local variables, internal functions + SvxTabStop aCurrentTab; + std::unique_ptr aNewTabs; + long nDefDist; + + TabWin_Impl m_aLeftWin; + TabWin_Impl m_aRightWin; + TabWin_Impl m_aCenterWin; + TabWin_Impl m_aDezWin; + + // just to format the numbers, not shown + std::unique_ptr m_xTabSpin; + // tabulators and positions + std::unique_ptr m_xTabBox; + // TabType + std::unique_ptr m_xLeftTab; + std::unique_ptr m_xRightTab; + std::unique_ptr m_xCenterTab; + std::unique_ptr m_xDezTab; + + std::unique_ptr m_xDezChar; + std::unique_ptr m_xDezCharLabel; + + std::unique_ptr m_xNoFillChar; + std::unique_ptr m_xFillPoints; + std::unique_ptr m_xFillDashLine ; + std::unique_ptr m_xFillSolidLine; + std::unique_ptr m_xFillSpecial; + std::unique_ptr m_xFillChar; + + std::unique_ptr m_xNewBtn; + std::unique_ptr m_xDelAllBtn; + std::unique_ptr m_xDelBtn; + + std::unique_ptr m_xTypeFrame; + std::unique_ptr m_xFillFrame; + + std::unique_ptr m_xLeftWin; + std::unique_ptr m_xRightWin; + std::unique_ptr m_xCenterWin; + std::unique_ptr m_xDezWin; + + void InitTabPos_Impl( sal_uInt16 nPos = 0 ); + void SetFillAndTabType_Impl(); + void NewHdl_Impl(const weld::Button*); + + OUString FormatTab(); + + // Handler + DECL_LINK(NewHdl_Impl, weld::Button&, void); + DECL_LINK(DelHdl_Impl, weld::Button&, void); + DECL_LINK(DelAllHdl_Impl, weld::Button&, void); + + DECL_LINK(FillTypeCheckHdl_Impl, weld::ToggleButton&, void); + DECL_LINK(TabTypeCheckHdl_Impl, weld::ToggleButton&, void); + + DECL_LINK(SelectHdl_Impl, weld::TreeView&, bool); + DECL_LINK(ModifyHdl_Impl, weld::ComboBox&, void); + DECL_LINK(ReformatHdl_Impl, weld::Widget&, void); + DECL_LINK(GetFillCharHdl_Impl, weld::Widget&, void); + DECL_LINK(GetDezCharHdl_Impl, weld::Widget&, void); + + int FindCurrentTab(); + + virtual void PageCreated(const SfxAllItemSet& aSet) override; +}; + +#endif // INCLUDED_CUI_SOURCE_INC_TABSTPGE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/textanim.hxx b/cui/source/inc/textanim.hxx new file mode 100644 index 000000000..3ae2452b0 --- /dev/null +++ b/cui/source/inc/textanim.hxx @@ -0,0 +1,108 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_TEXTANIM_HXX +#define INCLUDED_CUI_SOURCE_INC_TEXTANIM_HXX + +#include +#include +#include +#include + +class SdrView; + +/************************************************************************* +|* +|* Page for changing TextAnimations (running text etc.) +|* +\************************************************************************/ + +class SvxTextAnimationPage : public SfxTabPage +{ +private: + static const sal_uInt16 pRanges[]; + + SdrTextAniKind eAniKind; + FieldUnit eFUnit; + MapUnit eUnit; + + TriState m_aUpState; + TriState m_aLeftState; + TriState m_aRightState; + TriState m_aDownState; + + std::unique_ptr m_xLbEffect; + std::unique_ptr m_xBoxDirection; + std::unique_ptr m_xBtnUp; + std::unique_ptr m_xBtnLeft; + std::unique_ptr m_xBtnRight; + std::unique_ptr m_xBtnDown; + + std::unique_ptr m_xFlProperties; + std::unique_ptr m_xTsbStartInside; + std::unique_ptr m_xTsbStopInside; + + std::unique_ptr m_xBoxCount; + std::unique_ptr m_xTsbEndless; + std::unique_ptr m_xNumFldCount; + + std::unique_ptr m_xTsbPixel; + std::unique_ptr m_xMtrFldAmount; + + std::unique_ptr m_xTsbAuto; + std::unique_ptr m_xMtrFldDelay; + + DECL_LINK( SelectEffectHdl_Impl, weld::ComboBox&, void ); + DECL_LINK( ClickEndlessHdl_Impl, weld::Button&, void ); + DECL_LINK( ClickAutoHdl_Impl, weld::Button&, void ); + DECL_LINK( ClickPixelHdl_Impl, weld::Button&, void ); + DECL_LINK( ClickDirectionHdl_Impl, weld::Button&, void ); + + void SelectDirection( SdrTextAniDirection nValue ); + sal_uInt16 GetSelectedDirection() const; + +public: + SvxTextAnimationPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + virtual ~SvxTextAnimationPage() override; + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* ); + static const sal_uInt16* GetRanges() { return pRanges; } + + virtual bool FillItemSet( SfxItemSet* ) override; + virtual void Reset( const SfxItemSet * ) override; +}; + +/************************************************************************* +|* +|* Text-Tab-Dialog +|* +\************************************************************************/ +class SvxTextTabDialog : public SfxTabDialogController +{ +private: + const SdrView* pView; + + virtual void PageCreated(const OString& rId, SfxTabPage &rPage) override; + +public: + SvxTextTabDialog(weld::Window* pParent, const SfxItemSet* pAttr, const SdrView* pView); +}; + +#endif // INCLUDED_CUI_SOURCE_INC_TEXTANIM_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/textattr.hxx b/cui/source/inc/textattr.hxx new file mode 100644 index 000000000..392794de9 --- /dev/null +++ b/cui/source/inc/textattr.hxx @@ -0,0 +1,95 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_TEXTATTR_HXX +#define INCLUDED_CUI_SOURCE_INC_TEXTATTR_HXX + +#include +#include + +class SdrView; + +/************************************************************************* +|* +|* Dialog for changing TextAttributes +|* +\************************************************************************/ + +class SvxTextAttrPage : public SvxTabPage +{ +private: + static const sal_uInt16 pRanges[]; + + const SfxItemSet& rOutAttrs; + SdrObjKind m_eObjKind; + + bool bAutoGrowSizeEnabled; + bool bContourEnabled; + bool bAutoGrowWidthEnabled; + bool bAutoGrowHeightEnabled; + bool bWordWrapTextEnabled; + bool bFitToSizeEnabled; + + SvxRectCtl m_aCtlPosition; + + std::unique_ptr m_xDrawingText; + std::unique_ptr m_xCustomShapeText; + std::unique_ptr m_xTsbAutoGrowWidth; + std::unique_ptr m_xTsbAutoGrowHeight; + std::unique_ptr m_xTsbFitToSize; + std::unique_ptr m_xTsbContour; + std::unique_ptr m_xTsbWordWrapText; + std::unique_ptr m_xTsbAutoGrowSize; + std::unique_ptr m_xFlDistance; + std::unique_ptr m_xMtrFldLeft; + std::unique_ptr m_xMtrFldRight; + std::unique_ptr m_xMtrFldTop; + std::unique_ptr m_xMtrFldBottom; + std::unique_ptr m_xFlPosition; + std::unique_ptr m_xCtlPosition; + std::unique_ptr m_xTsbFullWidth; + + DECL_LINK(ClickFullWidthHdl_Impl, weld::Button&, void); + DECL_LINK(ClickHdl_Impl, weld::Button&, void); + + /** Return whether the text direction is from left to right () or + top to bottom (). + */ + bool IsTextDirectionLeftToRight() const; + +public: + + SvxTextAttrPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + virtual ~SvxTextAttrPage() override; + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* ); + static const sal_uInt16* GetRanges() { return pRanges; } + + virtual bool FillItemSet( SfxItemSet* ) override; + virtual void Reset( const SfxItemSet * ) override; + + virtual void PointChanged( weld::DrawingArea* pWindow, RectPoint eRP ) override; + + void Construct(); + void SetObjKind(SdrObjKind eObjKind) { m_eObjKind = eObjKind; } + virtual void PageCreated(const SfxAllItemSet& aSet) override; +}; + +#endif // INCLUDED_CUI_SOURCE_INC_TEXTATTR_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/thesdlg.hxx b/cui/source/inc/thesdlg.hxx new file mode 100644 index 000000000..65c4050cc --- /dev/null +++ b/cui/source/inc/thesdlg.hxx @@ -0,0 +1,82 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_THESDLG_HXX +#define INCLUDED_CUI_SOURCE_INC_THESDLG_HXX + +#include + +#include +#include + +#include +#include + +class SvxThesaurusDialog : public SfxDialogController +{ + Idle m_aModifyIdle; + + css::uno::Reference< css::linguistic2::XThesaurus > xThesaurus; + OUString aLookUpText; + LanguageType nLookUpLanguage; + std::stack< OUString > aLookUpHistory; + bool m_bWordFound; + + std::unique_ptr m_xLeftBtn; + std::unique_ptr m_xWordCB; + std::unique_ptr m_xAlternativesCT; + std::unique_ptr m_xNotFound; + std::unique_ptr m_xReplaceEdit; + std::unique_ptr m_xLangLB; + std::unique_ptr m_xReplaceBtn; + +public: + virtual ~SvxThesaurusDialog() override; + + // Handler + DECL_LINK( ReplaceBtnHdl_Impl, weld::Button&, void ); + DECL_LINK( LeftBtnHdl_Impl, weld::Button&, void ); + DECL_LINK( LanguageHdl_Impl, weld::ComboBox&, void ); + DECL_LINK( WordSelectHdl_Impl, weld::ComboBox&, void ); + DECL_LINK( AlternativesSelectHdl_Impl, weld::TreeView&, void ); + DECL_LINK( AlternativesDoubleClickHdl_Impl, weld::TreeView&, bool ); + DECL_LINK( SelectFirstHdl_Impl, void*, void ); + DECL_LINK( ReplaceEditHdl_Impl, weld::Entry&, void ); + DECL_LINK( ModifyTimer_Hdl, Timer *, void ); + DECL_LINK( KeyInputHdl, const KeyEvent&, bool ); + + /// @throws css::lang::IllegalArgumentException + /// @throws css::uno::RuntimeException + css::uno::Sequence< css::uno::Reference< css::linguistic2::XMeaning > > + queryMeanings_Impl( OUString& rTerm, const css::lang::Locale& rLocale, const css::beans::PropertyValues& rProperties ); + + bool UpdateAlternativesBox_Impl(); + void LookUp( const OUString &rText ); + void LookUp_Impl(); + +public: + SvxThesaurusDialog(weld::Window* pParent, + css::uno::Reference< css::linguistic2::XThesaurus > const & xThesaurus, + const OUString &rWord, LanguageType nLanguage); + void SetWindowTitle( LanguageType nLanguage ); + OUString GetWord() const; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/tipofthedaydlg.hxx b/cui/source/inc/tipofthedaydlg.hxx new file mode 100644 index 000000000..425805af6 --- /dev/null +++ b/cui/source/inc/tipofthedaydlg.hxx @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_TIPOFTHEDAYDLG_HXX +#define INCLUDED_CUI_SOURCE_INC_TIPOFTHEDAYDLG_HXX + +#include + +class TipOfTheDayDialog : public weld::GenericDialogController +{ +private: + std::unique_ptr m_pImage; + std::unique_ptr m_pText; + std::unique_ptr m_pShowTip; + std::unique_ptr m_pNext; + std::unique_ptr m_pLink; + + sal_Int32 nCurrentTip; + sal_Int32 nNumberOfTips; + sal_Int32 nDay; + OUString aLink; + void UpdateTip(); + DECL_LINK(OnNextClick, weld::Button&, void); + DECL_LINK(OnLinkClick, weld::LinkButton&, bool); + +public: + TipOfTheDayDialog(weld::Window* pWindow); + virtual ~TipOfTheDayDialog() override; +}; + +#endif // INCLUDED_CUI_SOURCE_INC_TIPOFTHEDAYDLG_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/transfrm.hxx b/cui/source/inc/transfrm.hxx new file mode 100644 index 000000000..2c27a19fb --- /dev/null +++ b/cui/source/inc/transfrm.hxx @@ -0,0 +1,251 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_TRANSFRM_HXX +#define INCLUDED_CUI_SOURCE_INC_TRANSFRM_HXX + +#include +#include +#include +#include + +// predefines +class SdrView; + +/************************************************************************* +|* +|* Transform-Tab-Dialog +|* +\************************************************************************/ + +struct SvxSwFrameValidation; +class SvxTransformTabDialog : public SfxTabDialogController +{ +private: + const SdrView* pView; + + SvxAnchorIds nAnchorCtrls; + Link aValidateLink; + + virtual void PageCreated(const OString& rId, SfxTabPage &rPage) override; + +public: + SvxTransformTabDialog(weld::Window* pParent, const SfxItemSet* pAttr, + const SdrView* pView, + SvxAnchorIds nAnchorTypes); + + //link for the Writer to validate positions + void SetValidateFramePosLink( const Link& rLink ); +}; + +/************************************************************************* +|* +|* position and size tab page +|* +\************************************************************************/ + +class SvxPositionSizeTabPage : public SvxTabPage +{ + static const sal_uInt16 pPosSizeRanges[]; + +private: + const SfxItemSet& mrOutAttrs; + + const SdrView* mpView; + + // #i75273# + basegfx::B2DRange maRange; + basegfx::B2DRange maWorkRange; + basegfx::B2DPoint maAnchor; + + MapUnit mePoolUnit; + FieldUnit meDlgUnit; + TriState mnProtectSizeState; + bool mbPageDisabled; + bool mbProtectDisabled; + bool mbSizeDisabled; + bool mbAdjustDisabled; + bool mbIgnoreAutoGrowWidth; + bool mbIgnoreAutoGrowHeight; + + // from size + // #i75273# + double mfOldWidth; + double mfOldHeight; + RectPoint meRP; + + SvxRectCtl m_aCtlPos; + SvxRectCtl m_aCtlSize; + + // position + std::unique_ptr m_xFlPosition; + std::unique_ptr m_xMtrPosX; + std::unique_ptr m_xMtrPosY; + std::unique_ptr m_xCtlPos; + + // size + std::unique_ptr m_xFlSize; + std::unique_ptr m_xFtWidth; + std::unique_ptr m_xMtrWidth; + std::unique_ptr m_xFtHeight; + std::unique_ptr m_xMtrHeight; + std::unique_ptr m_xCbxScale; + std::unique_ptr m_xCtlSize; + + // protect + std::unique_ptr m_xFlProtect; + std::unique_ptr m_xTsbPosProtect; + std::unique_ptr m_xTsbSizeProtect; + + // adjust + std::unique_ptr m_xFlAdjust; + std::unique_ptr m_xTsbAutoGrowWidth; + std::unique_ptr m_xTsbAutoGrowHeight; + + DECL_LINK(ChangePosProtectHdl, weld::ToggleButton&, void); + DECL_LINK(ChangeSizeProtectHdl, weld::ToggleButton&, void); + + void SetMinMaxPosition(); + void GetTopLeftPosition(double& rfX, double& rfY, const basegfx::B2DRange& rRange); + + DECL_LINK( ChangeWidthHdl, weld::MetricSpinButton&, void ); + DECL_LINK( ChangeHeightHdl, weld::MetricSpinButton&, void ); + DECL_LINK( ClickSizeProtectHdl, weld::ToggleButton&, void ); + DECL_LINK( ClickAutoHdl, weld::ToggleButton&, void ); + +public: + SvxPositionSizeTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + virtual ~SvxPositionSizeTabPage() override; + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* ); + static const sal_uInt16* GetRanges() { return pPosSizeRanges; } + + virtual bool FillItemSet( SfxItemSet* ) override; + virtual void Reset( const SfxItemSet * ) override; + + virtual void ActivatePage( const SfxItemSet& rSet ) override; + virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override; + + virtual void PointChanged(weld::DrawingArea* pWindow, RectPoint eRP) override; + + void Construct(); + void SetView( const SdrView* pSdrView ) { mpView = pSdrView; } + + virtual void FillUserData() override; + + void DisableResize(); + void DisableProtect(); + + void UpdateControlStates(); +}; + +/************************************************************************* +|* +|* rotation angle tab page +|* +\************************************************************************/ +class SvxAngleTabPage : public SvxTabPage +{ + static const sal_uInt16 pAngleRanges[]; + +private: + const SdrView* pView; + + // #i75273# + basegfx::B2DRange maRange; + basegfx::B2DPoint maAnchor; + + MapUnit ePoolUnit; + FieldUnit eDlgUnit; + + SvxRectCtl m_aCtlRect; + + std::unique_ptr m_xFlPosition; + std::unique_ptr m_xMtrPosX; + std::unique_ptr m_xMtrPosY; + std::unique_ptr m_xCtlRect; + std::unique_ptr m_xFlAngle; + std::unique_ptr m_xNfAngle; + std::unique_ptr m_xCtlAngle; + std::unique_ptr m_xCtlAngleWin; + +public: + SvxAngleTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + virtual ~SvxAngleTabPage() override; + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* ); + static const sal_uInt16* GetRanges() { return pAngleRanges; } + + virtual bool FillItemSet( SfxItemSet* ) override; + virtual void Reset( const SfxItemSet * ) override; + + virtual void ActivatePage( const SfxItemSet& rSet ) override; + virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override; + + virtual void PointChanged(weld::DrawingArea* pWindow, RectPoint eRP) override; + + void Construct(); + void SetView( const SdrView* pSdrView ) { pView = pSdrView; } +}; + +/************************************************************************* +|* +|* slant/corner radius tab page +|* +\************************************************************************/ +class SvxSlantTabPage : public SfxTabPage +{ + static const sal_uInt16 pSlantRanges[]; + +private: + const SdrView* pView; + + MapUnit ePoolUnit; + FieldUnit eDlgUnit; + + std::unique_ptr m_xFlRadius; + std::unique_ptr m_xMtrRadius; + std::unique_ptr m_xFlAngle; + std::unique_ptr m_xMtrAngle; + std::unique_ptr m_aControlGroups[2]; + std::unique_ptr m_aControlGroupX[2]; + std::unique_ptr m_aControlX[2]; + std::unique_ptr m_aControlGroupY[2]; + std::unique_ptr m_aControlY[2]; + +public: + SvxSlantTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + virtual ~SvxSlantTabPage() override; + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* ); + static const sal_uInt16* GetRanges() { return pSlantRanges; } + + virtual bool FillItemSet( SfxItemSet* ) override; + virtual void Reset( const SfxItemSet * ) override; + + virtual void ActivatePage( const SfxItemSet& rSet ) override; + virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override; + + void Construct(); + void SetView( const SdrView* pSdrView ) { pView = pSdrView; } +}; + + +#endif // INCLUDED_CUI_SOURCE_INC_TRANSFRM_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/treeopt.hxx b/cui/source/inc/treeopt.hxx new file mode 100644 index 000000000..c2aac20ee --- /dev/null +++ b/cui/source/inc/treeopt.hxx @@ -0,0 +1,238 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_CUI_SOURCE_INC_TREEOPT_HXX +#define INCLUDED_CUI_SOURCE_INC_TREEOPT_HXX + +#include + +#include + +#include +#include + +class SfxModule; +class SfxShell; + +// struct OrderedEntry --------------------------------------------------- + +struct OrderedEntry +{ + sal_Int32 m_nIndex; + OUString m_sId; + + OrderedEntry( sal_Int32 nIndex, const OUString& rId ) : + m_nIndex( nIndex ), m_sId( rId ) {} +}; + + +// struct Module --------------------------------------------------------- + +struct Module +{ + bool m_bActive; + std::vector< std::unique_ptr > m_aNodeList; + + Module() : m_bActive( false ) {} +}; + +// struct OptionsLeaf ---------------------------------------------------- + +struct OptionsLeaf +{ + OUString m_sLabel; + OUString m_sPageURL; + OUString m_sEventHdl; + OUString m_sGroupId; + sal_Int32 m_nGroupIndex; + + OptionsLeaf( const OUString& rLabel, + const OUString& rPageURL, + const OUString& rEventHdl, + const OUString& rGroupId, + sal_Int32 nGroupIndex ) : + m_sLabel( rLabel ), + m_sPageURL( rPageURL ), + m_sEventHdl( rEventHdl ), + m_sGroupId( rGroupId ), + m_nGroupIndex( nGroupIndex ) {} +}; + +// struct OptionsNode ---------------------------------------------------- + +struct OptionsNode +{ + OUString m_sId; + OUString m_sLabel; + bool m_bAllModules; + std::vector< std::unique_ptr > m_aLeaves; + std::vector< std::vector< std::unique_ptr > > + m_aGroupedLeaves; + + OptionsNode( const OUString& rId, + const OUString& rLabel, + bool bAllModules ) : + m_sId( rId ), + m_sLabel( rLabel ), + m_bAllModules( bAllModules ) {} +}; + +typedef std::vector< std::unique_ptr > VectorOfNodes; + +struct LastPageSaver +{ + sal_uInt16 m_nLastPageId; + OUString m_sLastPageURL_Tools; + OUString m_sLastPageURL_ExtMgr; + + LastPageSaver() : m_nLastPageId( USHRT_MAX ) {} +}; + +// class OfaTreeOptionsDialog -------------------------------------------- + +namespace com::sun::star::frame { class XFrame; } +namespace com::sun::star::awt { class XContainerWindowProvider; } + +struct OptionsPageInfo; +struct Module; +class ExtensionsTabPage; +class SvxColorTabPage; + +class OfaTreeOptionsDialog final: public SfxOkDialogController +{ +private: + std::unique_ptr xOkPB; + std::unique_ptr xApplyPB; + std::unique_ptr xBackPB; + + std::unique_ptr xTreeLB; + std::unique_ptr xTabBox; + + weld::Window* m_pParent; + + std::unique_ptr xCurrentPageEntry; + + OUString sTitle; + + bool bForgetSelection; + bool bIsFromExtensionManager; + + // check "for the current document only" and set focus to "Western" languages box + bool bIsForSetDocumentLanguage; + + bool bNeedsRestart; + svtools::RestartReason eRestartReason; + + css::uno::Reference < css::awt::XContainerWindowProvider > + m_xContainerWinProvider; + + static LastPageSaver* pLastPageSaver; + + std::unique_ptr CreateItemSet( sal_uInt16 nId ); + static void ApplyItemSet( sal_uInt16 nId, const SfxItemSet& rSet ); + void InitTreeAndHandler(); + void Initialize( const css::uno::Reference< css::frame::XFrame >& _xFrame ); + void InitWidgets(); + + void LoadExtensionOptions( const OUString& rExtensionId ); + static OUString GetModuleIdentifier( const css::uno::Reference< + css::frame::XFrame >& xFrame ); + static std::unique_ptr LoadModule( const OUString& rModuleIdentifier ); + static VectorOfNodes LoadNodes( Module* pModule, const OUString& rExtensionId ); + void InsertNodes( const VectorOfNodes& rNodeList ); + + void ApplyOptions( bool deactivate ); + + DECL_LINK(ShowPageHdl_Impl, weld::TreeView&, void); + DECL_LINK(BackHdl_Impl, weld::Button&, void); + DECL_LINK(ApplyHdl_Impl, weld::Button&, void); + DECL_LINK(OKHdl_Impl, weld::Button&, void); + DECL_LINK(HelpHdl_Impl, weld::Widget&, bool); + void SelectHdl_Impl(); + + virtual short run() override; + + virtual weld::Button& GetOKButton() const override { return *xOkPB; } + virtual const SfxItemSet* GetExampleSet() const override { return nullptr; } + +public: + OfaTreeOptionsDialog(weld::Window* pParent, + const css::uno::Reference< css::frame::XFrame >& _xFrame, + bool bActivateLastSelection); + OfaTreeOptionsDialog(weld::Window* pParent, const OUString& rExtensionId); + virtual ~OfaTreeOptionsDialog() override; + + OptionsPageInfo* AddTabPage( sal_uInt16 nId, const OUString& rPageName, sal_uInt16 nGroup ); + sal_uInt16 AddGroup( const OUString& rGroupName, SfxShell* pCreateShell, + SfxModule* pCreateModule, sal_uInt16 nDialogId ); + + void ActivateLastSelection(); + void ActivatePage( sal_uInt16 nResId ); + void ActivatePage( const OUString& rPageURL ); + void ApplyItemSets(); + + // helper functions to call the language settings TabPage from the SpellDialog + static void ApplyLanguageOptions(const SfxItemSet& rSet); + + void SetNeedsRestart( svtools::RestartReason eReason ); +}; + +// class ExtensionsTabPage ----------------------------------------------- + +namespace com::sun::star::awt { class XWindow; } +namespace com::sun::star::awt { class XContainerWindowEventHandler; } + +class ExtensionsTabPage +{ +private: + weld::Container* m_pContainer; + OUString m_sPageURL; + css::uno::Reference m_xPageParent; + css::uno::Reference m_xPage; + OUString m_sEventHdl; + css::uno::Reference< css::awt::XContainerWindowEventHandler > + m_xEventHdl; + css::uno::Reference< css::awt::XContainerWindowProvider > + m_xWinProvider; + + void CreateDialogWithHandler(); + bool DispatchAction( const OUString& rAction ); + +public: + ExtensionsTabPage( + weld::Container* pParent, + const OUString& rPageURL, const OUString& rEvtHdl, + const css::uno::Reference< + css::awt::XContainerWindowProvider >& rProvider ); + + ~ExtensionsTabPage(); + + void Show(); + void Hide(); + + void ActivatePage(); + void DeactivatePage(); + + void ResetPage(); + void SavePage(); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/zoom.hxx b/cui/source/inc/zoom.hxx new file mode 100644 index 000000000..f35a7bfba --- /dev/null +++ b/cui/source/inc/zoom.hxx @@ -0,0 +1,70 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_INC_ZOOM_HXX +#define INCLUDED_CUI_SOURCE_INC_ZOOM_HXX + +#include +#include +#include +#include +#include + +class SvxZoomDialog : public SfxDialogController +{ +private: + const SfxItemSet& m_rSet; + std::unique_ptr m_pOutSet; + bool m_bModified; + + std::unique_ptr m_xOptimalBtn; + std::unique_ptr m_xWholePageBtn; + std::unique_ptr m_xPageWidthBtn; + std::unique_ptr m_x100Btn; + std::unique_ptr m_xUserBtn; + std::unique_ptr m_xUserEdit; + std::unique_ptr m_xViewFrame; + std::unique_ptr m_xAutomaticBtn; + std::unique_ptr m_xSingleBtn; + std::unique_ptr m_xColumnsBtn; + std::unique_ptr m_xColumnsEdit; + std::unique_ptr m_xBookModeChk; + std::unique_ptr m_xOKBtn; + + DECL_LINK(UserHdl, weld::ToggleButton&, void); + DECL_LINK(SpinHdl, weld::MetricSpinButton&, void); + DECL_LINK(ViewLayoutUserHdl, weld::ToggleButton&, void); + DECL_LINK(ViewLayoutSpinHdl, weld::SpinButton&, void); + DECL_LINK(ViewLayoutCheckHdl, weld::ToggleButton&, void); + DECL_LINK(OKHdl, weld::Button&, void); + +public: + SvxZoomDialog(weld::Window* pParent, const SfxItemSet& rCoreSet); + + const SfxItemSet* GetOutputItemSet() const; + + sal_uInt16 GetFactor() const; + void SetFactor(sal_uInt16 nNewFactor, ZoomButtonId nButtonId = ZoomButtonId::NONE); + + void HideButton(ZoomButtonId nButtonId); + void SetLimits(sal_uInt16 nMin, sal_uInt16 nMax); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/certpath.cxx b/cui/source/options/certpath.cxx new file mode 100644 index 000000000..b98811dc4 --- /dev/null +++ b/cui/source/options/certpath.cxx @@ -0,0 +1,240 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include +#include "certpath.hxx" + +#include +#include +#include +#include + +using namespace ::com::sun::star; + +CertPathDialog::CertPathDialog(weld::Window* pParent) + : GenericDialogController(pParent, "cui/ui/certdialog.ui", "CertDialog") + , m_xManualButton(m_xBuilder->weld_button("add")) + , m_xOKButton(m_xBuilder->weld_button("ok")) + , m_xCertPathList(m_xBuilder->weld_tree_view("paths")) + , m_sAddDialogText(m_xBuilder->weld_label("certdir")->get_label()) + , m_sManualLabel(m_xBuilder->weld_label("manual")->get_label()) +{ + // these are just used to get translated strings + + m_xCertPathList->set_size_request(m_xCertPathList->get_approximate_digit_width() * 70, + m_xCertPathList->get_height_rows(6)); + + std::vector aWidths; + aWidths.push_back(m_xCertPathList->get_checkbox_column_width()); + aWidths.push_back(m_xCertPathList->get_approximate_digit_width() * 20); + m_xCertPathList->set_column_fixed_widths(aWidths); + + std::vector aRadioColumns; + aRadioColumns.push_back(0); + m_xCertPathList->set_toggle_columns_as_radio(aRadioColumns); + + m_xCertPathList->connect_toggled(LINK(this, CertPathDialog, CheckHdl_Impl)); + m_xManualButton->connect_clicked( LINK( this, CertPathDialog, ManualHdl_Impl ) ); + m_xOKButton->connect_clicked( LINK( this, CertPathDialog, OKHdl_Impl ) ); + + try + { + // In the reverse order of preference for the default selected profile + mozilla::MozillaProductType const productTypes[3] = { + mozilla::MozillaProductType_Thunderbird, + mozilla::MozillaProductType_Firefox, + mozilla::MozillaProductType_Mozilla }; + const char* const productNames[3] = { + "thunderbird", + "firefox", + "mozilla" }; + bool bSelected = false; + + uno::Reference xMozillaBootstrap = mozilla::MozillaBootstrap::create( comphelper::getProcessComponentContext() ); + + for (sal_Int32 i = 0; i < sal_Int32(SAL_N_ELEMENTS(productTypes)); ++i) + { + sal_Int32 nProfileCount = xMozillaBootstrap->getProfileCount(productTypes[i]); + if (nProfileCount <= 0) + continue; + OUString sDefaultProfile = xMozillaBootstrap->getDefaultProfile(productTypes[i]); + uno::Sequence aProfileList(nProfileCount); +#ifndef NDEBUG + sal_Int32 nListLen = +#endif + xMozillaBootstrap->getProfileList(productTypes[i], aProfileList); + assert((nProfileCount == nListLen) && (nListLen == aProfileList.getLength())); + + for (const auto& sProfileName : std::as_const(aProfileList)) + { + OUString sEntry = OUString::createFromAscii(productNames[i]) + ":" + sProfileName; + OUString sProfilePath = xMozillaBootstrap->getProfilePath(productTypes[i], sProfileName); + const bool bSelectDefaultProfile = !bSelected && sProfileName == sDefaultProfile; + AddCertPath(sEntry, sProfilePath, bSelectDefaultProfile); + if (bSelectDefaultProfile) + bSelected = true; + } + } + } + catch (const uno::Exception&) + { + } + + try + { + AddManualCertPath(officecfg::Office::Common::Security::Scripting::CertDir::get().value_or(OUString())); + if (m_sManualPath.isEmpty()) + AddManualCertPath(officecfg::Office::Common::Security::Scripting::ManualCertDir::get(), false); + } + catch (const uno::Exception &) + { + TOOLS_WARN_EXCEPTION("cui.options", "CertPathDialog::CertPathDialog()"); + } + + const char* pEnv = getenv("MOZILLA_CERTIFICATE_FOLDER"); + if (pEnv) + AddCertPath("$MOZILLA_CERTIFICATE_FOLDER", OUString(pEnv, strlen(pEnv), osl_getThreadTextEncoding())); +} + +void CertPathDialog::AddManualCertPath(const OUString& sUserSetCertPath, bool bSelect) +{ + if (sUserSetCertPath.isEmpty()) + return; + + // check existence + ::osl::DirectoryItem aUserPathItem; + OUString sUserSetCertURLPath; + osl::FileBase::getFileURLFromSystemPath(sUserSetCertPath, sUserSetCertURLPath); + if (::osl::FileBase::E_None == ::osl::DirectoryItem::get(sUserSetCertURLPath, aUserPathItem)) + { + ::osl::FileStatus aStatus( osl_FileStatus_Mask_Validate ); + if (::osl::FileBase::E_None == aUserPathItem.getFileStatus(aStatus)) + // the cert path exists + AddCertPath(m_sManualLabel, sUserSetCertPath, bSelect); + } +} + +IMPL_LINK_NOARG(CertPathDialog, OKHdl_Impl, weld::Button&, void) +{ + try + { + std::shared_ptr< comphelper::ConfigurationChanges > batch( + comphelper::ConfigurationChanges::create()); + officecfg::Office::Common::Security::Scripting::CertDir::set( + getDirectory(), batch); + officecfg::Office::Common::Security::Scripting::ManualCertDir::set(m_sManualPath, batch); + batch->commit(); + } + catch (const uno::Exception &) + { + TOOLS_WARN_EXCEPTION("cui.options", "CertPathDialog::OKHdl_Impl()"); + } + + m_xDialog->response(RET_OK); +} + +OUString CertPathDialog::getDirectory() const +{ + int nEntry = m_xCertPathList->get_selected_index(); + if (nEntry == -1) + return OUString(); + return m_xCertPathList->get_id(nEntry); +} + +CertPathDialog::~CertPathDialog() +{ +} + +IMPL_LINK(CertPathDialog, CheckHdl_Impl, const row_col&, rRowCol, void) +{ + HandleEntryChecked(rRowCol.first); +} + +void CertPathDialog::HandleEntryChecked(int nRow) +{ + const bool bChecked = m_xCertPathList->get_toggle(nRow, 0) == TRISTATE_TRUE; + if (bChecked) + { + // we have radio button behavior -> so uncheck the other entries + m_xCertPathList->select(nRow); + const int nCount = m_xCertPathList->n_children(); + for (int i = 0; i < nCount; ++i) + { + if (i != nRow) + m_xCertPathList->set_toggle(i, TRISTATE_FALSE, 0); + } + } +} + +void CertPathDialog::AddCertPath(const OUString &rProfile, const OUString &rPath, const bool bSelect) +{ + int nRow = -1; + for (int i = 0, nCount = m_xCertPathList->n_children(); i < nCount; ++i) + { + OUString sCertPath = m_xCertPathList->get_id(i); + //already exists, just select the original one + if (sCertPath == rPath) + { + const bool bWantSelected = bSelect || m_xCertPathList->get_toggle(i, 0); + m_xCertPathList->set_toggle(i, bWantSelected ? TRISTATE_TRUE : TRISTATE_FALSE, 0); + HandleEntryChecked(i); + return; + } + else if (m_xCertPathList->get_text(i, 1) == rProfile) + nRow = i; + } + + if (m_sManualLabel == rProfile) + m_sManualPath = rPath; + + if (nRow < 0) + { + m_xCertPathList->append(); + nRow = m_xCertPathList->n_children() - 1; + } + m_xCertPathList->set_toggle(nRow, bSelect ? TRISTATE_TRUE : TRISTATE_FALSE, 0); + m_xCertPathList->set_text(nRow, rProfile, 1); + m_xCertPathList->set_text(nRow, rPath, 2); + m_xCertPathList->set_id(nRow, rPath); + HandleEntryChecked(nRow); +} + +IMPL_LINK_NOARG(CertPathDialog, ManualHdl_Impl, weld::Button&, void) +{ + try + { + uno::Reference xFolderPicker = ui::dialogs::FolderPicker::create(comphelper::getProcessComponentContext()); + + OUString sURL; + if (!m_sManualPath.isEmpty()) + osl::FileBase::getFileURLFromSystemPath(m_sManualPath, sURL); + if (sURL.isEmpty()) + osl::Security().getHomeDir(sURL); + xFolderPicker->setDisplayDirectory(sURL); + xFolderPicker->setDescription(m_sAddDialogText); + + if (xFolderPicker->execute() == ui::dialogs::ExecutableDialogResults::OK) + { + sURL = xFolderPicker->getDirectory(); + OUString aPath; + if (osl::FileBase::E_None == osl::FileBase::getSystemPathFromFileURL(sURL, aPath)) + AddCertPath(m_sManualLabel, aPath); + } + } + catch (const uno::Exception &) + { + TOOLS_WARN_EXCEPTION("cui.options", ""); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/certpath.hxx b/cui/source/options/certpath.hxx new file mode 100644 index 000000000..7ab30955d --- /dev/null +++ b/cui/source/options/certpath.hxx @@ -0,0 +1,39 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +class CertPathDialog : public weld::GenericDialogController +{ + std::unique_ptr m_xManualButton; + std::unique_ptr m_xOKButton; + std::unique_ptr m_xCertPathList; + OUString m_sAddDialogText; + OUString m_sManualLabel; + OUString m_sManualPath; + + typedef std::pair row_col; + DECL_LINK(CheckHdl_Impl, const row_col&, void); + DECL_LINK(ManualHdl_Impl, weld::Button&, void); + DECL_LINK(OKHdl_Impl, weld::Button&, void); + + void HandleEntryChecked(int nRow); + void AddCertPath(const OUString& rProfile, const OUString& rPath, bool bSelect = true); + void AddManualCertPath(const OUString& sUserSetCertPath, bool bSelect = true); + +public: + explicit CertPathDialog(weld::Window* pParent); + virtual ~CertPathDialog() override; + + OUString getDirectory() const; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/cfgchart.cxx b/cui/source/options/cfgchart.cxx new file mode 100644 index 000000000..660241519 --- /dev/null +++ b/cui/source/options/cfgchart.cxx @@ -0,0 +1,279 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include "cfgchart.hxx" +#include +#include + +#define ROW_COLOR_COUNT 12 + +using namespace com::sun::star; + +// accessors +size_t SvxChartColorTable::size() const +{ + return m_aColorEntries.size(); +} + +const XColorEntry & SvxChartColorTable::operator[]( size_t _nIndex ) const +{ + if ( _nIndex >= m_aColorEntries.size() ) + { + SAL_WARN( "cui.options", "SvxChartColorTable::[] invalid index" ); + return m_aColorEntries[ 0 ]; + } + + return m_aColorEntries[ _nIndex ]; +} + +Color SvxChartColorTable::getColor( size_t _nIndex ) const +{ + if ( _nIndex >= m_aColorEntries.size() ) + { + SAL_WARN( "cui.options", "SvxChartColorTable::getColorData invalid index" ); + return COL_BLACK; + } + + return m_aColorEntries[ _nIndex ].GetColor().GetRGBColor(); +} + +// mutators +void SvxChartColorTable::clear() +{ + m_aColorEntries.clear(); +} + +void SvxChartColorTable::append( const XColorEntry & _rEntry ) +{ + m_aColorEntries.push_back( _rEntry ); +} + +void SvxChartColorTable::remove( size_t _nIndex ) +{ + if (!m_aColorEntries.empty()) + m_aColorEntries.erase( m_aColorEntries.begin() + _nIndex); + + for (size_t i=0 ; i aNames = GetPropertyNames(); + uno::Sequence< uno::Any > aProperties( aNames.getLength()); + aProperties = GetProperties( aNames ); + + if( aProperties.getLength() == aNames.getLength()) + { + // 1. default colors for series + maDefColors.clear(); + uno::Sequence< sal_Int64 > aColorSeq; + aProperties[ 0 ] >>= aColorSeq; + + sal_Int32 nCount = aColorSeq.getLength(); + Color aCol; + + // create strings for entry names + OUString aResName( CuiResId( RID_SVXSTR_DIAGRAM_ROW ) ); + OUString aPrefix, aPostfix, aName; + sal_Int32 nPos = aResName.indexOf( "$(ROW)" ); + if( nPos != -1 ) + { + aPrefix = aResName.copy( 0, nPos ); + sal_Int32 idx = nPos + sizeof( "$(ROW)" ) - 1; + aPostfix = aResName.copy( idx ); + } + else + aPrefix = aResName; + + // set color values + for( sal_Int32 i=0; i < nCount; i++ ) + { + aCol = Color(aColorSeq[ i ]); + + aName = aPrefix + OUString::number(i + 1) + aPostfix; + + maDefColors.append( XColorEntry( aCol, aName )); + } + return true; + } + return false; +} + +void SvxChartOptions::ImplCommit() +{ + uno::Sequence< OUString > aNames = GetPropertyNames(); + uno::Sequence< uno::Any > aValues( aNames.getLength()); + + if( aValues.hasElements() ) + { + // 1. default colors for series + // convert list to sequence + const size_t nCount = maDefColors.size(); + uno::Sequence< sal_Int64 > aColors( nCount ); + for( size_t i=0; i < nCount; i++ ) + { + Color aData = maDefColors.getColor( i ); + aColors[ i ] = sal_uInt32(aData); + } + + aValues[ 0 ] <<= aColors; + } + + PutProperties( aNames, aValues ); +} + +void SvxChartOptions::Notify( const css::uno::Sequence< OUString >& ) +{ +} + + + + +SvxChartColorTableItem::SvxChartColorTableItem( sal_uInt16 nWhich_, const SvxChartColorTable& aTable ) : + SfxPoolItem( nWhich_ ), + m_aColorTable( aTable ) +{ +} + +SvxChartColorTableItem* SvxChartColorTableItem::Clone( SfxItemPool * ) const +{ + return new SvxChartColorTableItem( *this ); +} + +bool SvxChartColorTableItem::operator==( const SfxPoolItem& rAttr ) const +{ + assert(SfxPoolItem::operator==(rAttr)); + + return static_cast( rAttr ).m_aColorTable == m_aColorTable; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/cfgchart.hxx b/cui/source/options/cfgchart.hxx new file mode 100644 index 000000000..acbe41a9b --- /dev/null +++ b/cui/source/options/cfgchart.hxx @@ -0,0 +1,100 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include +#include +#include + +#include + +class SvxChartColorTable +{ +private: + std::vector< XColorEntry > m_aColorEntries; + +public: + // accessors + size_t size() const; + const XColorEntry & operator[]( size_t _nIndex ) const; + Color getColor( size_t _nIndex ) const; + + // mutators + void clear(); + void append( const XColorEntry & _rEntry ); + void remove( size_t _nIndex ); + void replace( size_t _nIndex, const XColorEntry & _rEntry ); + void useDefault(); + static OUString getDefaultName(size_t _nIndex); + + // comparison + bool operator==( const SvxChartColorTable & _rOther ) const; +}; + + +// all options + +class SvxChartOptions : public ::utl::ConfigItem +{ +private: + SvxChartColorTable maDefColors; + bool mbIsInitialized; + + css::uno::Sequence< OUString > + maPropertyNames; + + const css::uno::Sequence< OUString >& GetPropertyNames() const + { return maPropertyNames; } + bool RetrieveOptions(); + + virtual void ImplCommit() override; + +public: + SvxChartOptions(); + virtual ~SvxChartOptions() override; + + const SvxChartColorTable& GetDefaultColors(); + void SetDefaultColors( const SvxChartColorTable& aCol ); + + virtual void Notify( const css::uno::Sequence< OUString >& _rPropertyNames) override; +}; + + +// items +// Make Item read-only (no non-const access methods). Two reasons: +// (1) Preparation for Item refactor +// (2) Dangerous due to SfxItem may not be what you expect (e.g. when +// ::Set in SfxItemSet, not your instance may be used there, no control +// about what will happen without deep knowledge about SfxItems/SfxItemSets) +class SvxChartColorTableItem : public SfxPoolItem +{ +public: + SvxChartColorTableItem( sal_uInt16 nWhich, const SvxChartColorTable& ); + + virtual SvxChartColorTableItem* Clone( SfxItemPool *pPool = nullptr ) const override; + virtual bool operator==( const SfxPoolItem& ) const override; + + const SvxChartColorTable & GetColorList() const { return m_aColorTable;} + +private: + SvxChartColorTable m_aColorTable; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/connpoolconfig.cxx b/cui/source/options/connpoolconfig.cxx new file mode 100644 index 000000000..8bf95ee0d --- /dev/null +++ b/cui/source/options/connpoolconfig.cxx @@ -0,0 +1,196 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "connpoolconfig.hxx" +#include "connpoolsettings.hxx" + +#include +#include +#include +#include +#include +#include "sdbcdriverenum.hxx" + +#include + +namespace offapp +{ + + + using namespace ::utl; + using namespace ::com::sun::star::uno; + + + static OUString getConnectionPoolNodeName() + { + return "org.openoffice.Office.DataAccess/ConnectionPool"; + } + + + static OUString getEnablePoolingNodeName() + { + return "EnablePooling"; + } + + + static OUString getDriverSettingsNodeName() + { + return "DriverSettings"; + } + + + static OUString getDriverNameNodeName() + { + return "DriverName"; + } + + + static OUString getEnableNodeName() + { + return "Enable"; + } + + + static OUString getTimeoutNodeName() + { + return "Timeout"; + } + + void ConnectionPoolConfig::GetOptions(SfxItemSet& _rFillItems) + { + // the config node where all pooling relevant info are stored under + OConfigurationTreeRoot aConnectionPoolRoot = OConfigurationTreeRoot::createWithComponentContext( + ::comphelper::getProcessComponentContext(), getConnectionPoolNodeName(), -1, OConfigurationTreeRoot::CM_READONLY); + + // the global "enabled" flag + Any aEnabled = aConnectionPoolRoot.getNodeValue(getEnablePoolingNodeName()); + bool bEnabled = true; + aEnabled >>= bEnabled; + _rFillItems.Put(SfxBoolItem(SID_SB_POOLING_ENABLED, bEnabled)); + + // the settings for the single drivers + DriverPoolingSettings aSettings; + // first get all the drivers register at the driver manager + ODriverEnumeration aEnumDrivers; + for (auto const& elem : aEnumDrivers) + { + aSettings.push_back(DriverPooling(elem)); + } + + // then look for which of them settings are stored in the configuration + OConfigurationNode aDriverSettings = aConnectionPoolRoot.openNode(getDriverSettingsNodeName()); + + Sequence< OUString > aDriverKeys = aDriverSettings.getNodeNames(); + const OUString* pDriverKeys = aDriverKeys.getConstArray(); + const OUString* pDriverKeysEnd = pDriverKeys + aDriverKeys.getLength(); + for (;pDriverKeys != pDriverKeysEnd; ++pDriverKeys) + { + // the name of the driver in this round + OConfigurationNode aThisDriverSettings = aDriverSettings.openNode(*pDriverKeys); + OUString sThisDriverName; + aThisDriverSettings.getNodeValue(getDriverNameNodeName()) >>= sThisDriverName; + + // look if we (resp. the driver manager) know this driver + // doing O(n) search here, which is expensive, but this doesn't matter in this small case ... + DriverPoolingSettings::iterator aLookup; + for ( aLookup = aSettings.begin(); + aLookup != aSettings.end(); + ++aLookup + ) + if (sThisDriverName == aLookup->sName) + break; + + if (aLookup == aSettings.end()) + { // do not know the driver - add it + aSettings.push_back(DriverPooling(sThisDriverName)); + + // and the position of the new entry + aLookup = aSettings.end(); + --aLookup; + } + + // now fill this entry with the settings from the configuration + aThisDriverSettings.getNodeValue(getEnableNodeName()) >>= aLookup->bEnabled; + aThisDriverSettings.getNodeValue(getTimeoutNodeName()) >>= aLookup->nTimeoutSeconds; + } + + _rFillItems.Put(DriverPoolingSettingsItem(SID_SB_DRIVER_TIMEOUTS, aSettings)); + } + + + void ConnectionPoolConfig::SetOptions(const SfxItemSet& _rSourceItems) + { + // the config node where all pooling relevant info are stored under + OConfigurationTreeRoot aConnectionPoolRoot = OConfigurationTreeRoot::createWithComponentContext( + ::comphelper::getProcessComponentContext(), getConnectionPoolNodeName()); + + if (!aConnectionPoolRoot.isValid()) + // already asserted by the OConfigurationTreeRoot + return; + + bool bNeedCommit = false; + + // the global "enabled" flag + const SfxBoolItem* pEnabled = _rSourceItems.GetItem(SID_SB_POOLING_ENABLED); + if (pEnabled) + { + bool bEnabled = pEnabled->GetValue(); + aConnectionPoolRoot.setNodeValue(getEnablePoolingNodeName(), Any(bEnabled)); + bNeedCommit = true; + } + + // the settings for the single drivers + const DriverPoolingSettingsItem* pDriverSettings = _rSourceItems.GetItem(SID_SB_DRIVER_TIMEOUTS); + if (pDriverSettings) + { + OConfigurationNode aDriverSettings = aConnectionPoolRoot.openNode(getDriverSettingsNodeName()); + if (!aDriverSettings.isValid()) + return; + + OUString sThisDriverName; + OConfigurationNode aThisDriverSettings; + + const DriverPoolingSettings& rNewSettings = pDriverSettings->getSettings(); + for (auto const& newSetting : rNewSettings) + { + // need the name as OUString + sThisDriverName = newSetting.sName; + + // the sub-node for this driver + if (aDriverSettings.hasByName(newSetting.sName)) + aThisDriverSettings = aDriverSettings.openNode(newSetting.sName); + else + aThisDriverSettings = aDriverSettings.createNode(newSetting.sName); + + // set the values + aThisDriverSettings.setNodeValue(getDriverNameNodeName(), Any(sThisDriverName)); + aThisDriverSettings.setNodeValue(getEnableNodeName(), Any(newSetting.bEnabled)); + aThisDriverSettings.setNodeValue(getTimeoutNodeName(), Any(newSetting.nTimeoutSeconds)); + } + bNeedCommit = true; + } + if (bNeedCommit) + aConnectionPoolRoot.commit(); + } + + +} // namespace offapp + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/connpoolconfig.hxx b/cui/source/options/connpoolconfig.hxx new file mode 100644 index 000000000..41ec88d5b --- /dev/null +++ b/cui/source/options/connpoolconfig.hxx @@ -0,0 +1,38 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +class SfxItemSet; + +namespace offapp +{ + + class ConnectionPoolConfig + { + + public: + static void GetOptions(SfxItemSet& _rFillItems); + static void SetOptions(const SfxItemSet& _rSourceItems); + }; + + +} // namespace offapp + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/connpooloptions.cxx b/cui/source/options/connpooloptions.cxx new file mode 100644 index 000000000..45ca5d9f3 --- /dev/null +++ b/cui/source/options/connpooloptions.cxx @@ -0,0 +1,261 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include "connpooloptions.hxx" +#include +#include "connpoolsettings.hxx" +#include +#include +#include +#include + +using ::svt::EditBrowseBox; + +namespace offapp +{ + bool ConnectionPoolOptionsPage::isModifiedDriverList() const + { + if (m_aSettings.size() != m_aSavedSettings.size()) + return true; + + DriverPoolingSettings::const_iterator aSaved = m_aSavedSettings.begin(); + for (auto const& currentSetting : m_aSettings) + { + if (currentSetting != *aSaved) + return true; + ++aSaved; + } + + return false; + } + + ConnectionPoolOptionsPage::ConnectionPoolOptionsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet) + : SfxTabPage(pPage, pController, "cui/ui/connpooloptions.ui", "ConnPoolPage", &_rAttrSet) + , m_sYes(CuiResId(RID_SVXSTR_YES)) + , m_sNo(CuiResId(RID_SVXSTR_NO)) + , m_xEnablePooling(m_xBuilder->weld_check_button("connectionpooling")) + , m_xDriversLabel(m_xBuilder->weld_label("driverslabel")) + , m_xDriverList(m_xBuilder->weld_tree_view("driverlist")) + , m_xDriverLabel(m_xBuilder->weld_label("driverlabel")) + , m_xDriver(m_xBuilder->weld_label("driver")) + , m_xDriverPoolingEnabled(m_xBuilder->weld_check_button("enablepooling")) + , m_xTimeoutLabel(m_xBuilder->weld_label("timeoutlabel")) + , m_xTimeout(m_xBuilder->weld_spin_button("timeout")) + { + m_xDriverList->set_size_request(m_xDriverList->get_approximate_digit_width() * 60, + m_xDriverList->get_height_rows(15)); + m_xDriverList->show(); + + std::vector aWidths; + aWidths.push_back(m_xDriverList->get_approximate_digit_width() * 50); + aWidths.push_back(m_xDriverList->get_approximate_digit_width() * 8); + m_xDriverList->set_column_fixed_widths(aWidths); + + m_xEnablePooling->connect_clicked( LINK(this, ConnectionPoolOptionsPage, OnEnabledDisabled) ); + m_xDriverPoolingEnabled->connect_clicked( LINK(this, ConnectionPoolOptionsPage, OnEnabledDisabled) ); + + m_xDriverList->connect_changed(LINK(this, ConnectionPoolOptionsPage, OnDriverRowChanged)); + m_xTimeout->connect_value_changed(LINK(this, ConnectionPoolOptionsPage, OnSpinValueChanged)); + } + + void ConnectionPoolOptionsPage::updateRow(size_t nRow) + { + auto const& currentSetting = m_aSettings[nRow]; + m_xDriverList->set_text(nRow, currentSetting.sName, 0); + if (currentSetting.bEnabled) + { + m_xDriverList->set_text(nRow, m_sYes, 1); + m_xDriverList->set_text(nRow, OUString::number(currentSetting.nTimeoutSeconds), 2); + } + else + { + m_xDriverList->set_text(nRow, m_sNo, 1); + m_xDriverList->set_text(nRow, "-", 2); + } + } + + void ConnectionPoolOptionsPage::updateCurrentRow() + { + int nRow = m_xDriverList->get_selected_index(); + if (nRow == -1) + return; + updateRow(nRow); + } + + void ConnectionPoolOptionsPage::UpdateDriverList(const DriverPoolingSettings& _rSettings) + { + m_aSettings = _rSettings; + + m_xDriverList->freeze(); + m_xDriverList->clear(); + + for (size_t i = 0; i < m_aSettings.size(); ++i) + { + m_xDriverList->append(); + updateRow(i); + } + + m_xDriverList->thaw(); + + if (!m_aSettings.empty()) + { + m_xDriverList->select(0); + OnDriverRowChanged(*m_xDriverList); + } + } + + ConnectionPoolOptionsPage::~ConnectionPoolOptionsPage() + { + } + + std::unique_ptr ConnectionPoolOptionsPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet) + { + return std::make_unique(pPage, pController, *_rAttrSet); + } + + void ConnectionPoolOptionsPage::implInitControls(const SfxItemSet& _rSet) + { + // the enabled flag + const SfxBoolItem* pEnabled = _rSet.GetItem(SID_SB_POOLING_ENABLED); + OSL_ENSURE(pEnabled, "ConnectionPoolOptionsPage::implInitControls: missing the Enabled item!"); + m_xEnablePooling->set_active(pEnabled == nullptr || pEnabled->GetValue()); + + m_xEnablePooling->save_state(); + + // the settings for the single drivers + const DriverPoolingSettingsItem* pDriverSettings = _rSet.GetItem(SID_SB_DRIVER_TIMEOUTS); + if (pDriverSettings) + UpdateDriverList(pDriverSettings->getSettings()); + else + { + OSL_FAIL("ConnectionPoolOptionsPage::implInitControls: missing the DriverTimeouts item!"); + UpdateDriverList(DriverPoolingSettings()); + } + saveDriverList(); + + // reflect the new settings + OnEnabledDisabled(*m_xEnablePooling); + } + + IMPL_LINK_NOARG(ConnectionPoolOptionsPage, OnSpinValueChanged, weld::SpinButton&, void) + { + commitTimeoutField(); + } + + bool ConnectionPoolOptionsPage::FillItemSet(SfxItemSet* _rSet) + { + commitTimeoutField(); + + bool bModified = false; + // the enabled flag + if (m_xEnablePooling->get_state_changed_from_saved()) + { + _rSet->Put(SfxBoolItem(SID_SB_POOLING_ENABLED, m_xEnablePooling->get_active())); + bModified = true; + } + + // the settings for the single drivers + if (isModifiedDriverList()) + { + _rSet->Put(DriverPoolingSettingsItem(SID_SB_DRIVER_TIMEOUTS, m_aSettings)); + bModified = true; + } + + return bModified; + } + + void ConnectionPoolOptionsPage::ActivatePage( const SfxItemSet& _rSet) + { + SfxTabPage::ActivatePage(_rSet); + implInitControls(_rSet); + } + + void ConnectionPoolOptionsPage::Reset(const SfxItemSet* _rSet) + { + implInitControls(*_rSet); + } + + IMPL_LINK_NOARG(ConnectionPoolOptionsPage, OnDriverRowChanged, weld::TreeView&, void) + { + const int nDriverPos = m_xDriverList->get_selected_index(); + bool bValidRow = (nDriverPos != -1); + m_xDriverPoolingEnabled->set_sensitive(bValidRow && m_xEnablePooling->get_active()); + m_xTimeoutLabel->set_sensitive(bValidRow); + m_xTimeout->set_sensitive(bValidRow); + + if (!bValidRow) + { // positioned on an invalid row + m_xDriver->set_label(OUString()); + } + else + { + auto const& currentSetting = m_aSettings[nDriverPos]; + m_xDriver->set_label(currentSetting.sName); + m_xDriverPoolingEnabled->set_active(currentSetting.bEnabled); + m_xTimeout->set_value(currentSetting.nTimeoutSeconds); + + OnEnabledDisabled(*m_xDriverPoolingEnabled); + } + } + + void ConnectionPoolOptionsPage::commitTimeoutField() + { + const int nDriverPos = m_xDriverList->get_selected_index(); + if (nDriverPos == -1) + return; + m_aSettings[nDriverPos].nTimeoutSeconds = m_xTimeout->get_value(); + updateCurrentRow(); + } + + IMPL_LINK( ConnectionPoolOptionsPage, OnEnabledDisabled, weld::Button&, rCheckBox, void ) + { + bool bGloballyEnabled = m_xEnablePooling->get_active(); + bool bLocalDriverChanged = m_xDriverPoolingEnabled.get() == &rCheckBox; + + if (m_xEnablePooling.get() == &rCheckBox) + { + m_xDriversLabel->set_sensitive(bGloballyEnabled); + m_xDriverList->set_sensitive(bGloballyEnabled); + if (!bGloballyEnabled) + m_xDriverList->select(-1); + m_xDriverLabel->set_sensitive(bGloballyEnabled); + m_xDriver->set_sensitive(bGloballyEnabled); + m_xDriverPoolingEnabled->set_sensitive(bGloballyEnabled); + } + else + OSL_ENSURE(bLocalDriverChanged, "ConnectionPoolOptionsPage::OnEnabledDisabled: where did this come from?"); + + m_xTimeoutLabel->set_sensitive(bGloballyEnabled && m_xDriverPoolingEnabled->get_active()); + m_xTimeout->set_sensitive(bGloballyEnabled && m_xDriverPoolingEnabled->get_active()); + + if (bLocalDriverChanged) + { + // update the list + const int nDriverPos = m_xDriverList->get_selected_index(); + if (nDriverPos == -1) + return; + m_aSettings[nDriverPos].bEnabled = m_xDriverPoolingEnabled->get_active(); + updateCurrentRow(); + } + } + +} // namespace offapp + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/connpooloptions.hxx b/cui/source/options/connpooloptions.hxx new file mode 100644 index 000000000..570ec66ab --- /dev/null +++ b/cui/source/options/connpooloptions.hxx @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include + +#include "connpoolsettings.hxx" + +namespace offapp +{ + class ConnectionPoolOptionsPage final : public SfxTabPage + { + OUString m_sYes; + OUString m_sNo; + DriverPoolingSettings m_aSettings; + DriverPoolingSettings m_aSavedSettings; + + std::unique_ptr m_xEnablePooling; + std::unique_ptr m_xDriversLabel; + std::unique_ptr m_xDriverList; + std::unique_ptr m_xDriverLabel; + std::unique_ptr m_xDriver; + std::unique_ptr m_xDriverPoolingEnabled; + std::unique_ptr m_xTimeoutLabel; + std::unique_ptr m_xTimeout; + + public: + ConnectionPoolOptionsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& _rAttrSet); + virtual ~ConnectionPoolOptionsPage() override; + static std::unique_ptr Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* _rAttrSet); + + private: + virtual bool FillItemSet(SfxItemSet* _rSet) override; + virtual void Reset(const SfxItemSet* _rSet) override; + virtual void ActivatePage( const SfxItemSet& _rSet) override; + + void updateRow(size_t nRow); + void updateCurrentRow(); + void UpdateDriverList(const DriverPoolingSettings& _rSettings); + bool isModifiedDriverList() const; + void saveDriverList() { m_aSavedSettings = m_aSettings; } + + DECL_LINK(OnEnabledDisabled, weld::Button&, void); + DECL_LINK(OnSpinValueChanged, weld::SpinButton&, void); + DECL_LINK(OnDriverRowChanged, weld::TreeView&, void); + + void implInitControls(const SfxItemSet& _rSet); + + void commitTimeoutField(); + }; + +} // namespace offapp + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/connpoolsettings.cxx b/cui/source/options/connpoolsettings.cxx new file mode 100644 index 000000000..46742d826 --- /dev/null +++ b/cui/source/options/connpoolsettings.cxx @@ -0,0 +1,82 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "connpoolsettings.hxx" + + +namespace offapp +{ + + DriverPooling::DriverPooling( const OUString& _rName ) + :sName(_rName) + ,bEnabled(false) + ,nTimeoutSeconds(120) + { + } + + + bool DriverPooling::operator == (const DriverPooling& _rR) const + { + return (sName == _rR.sName) + && (bEnabled == _rR.bEnabled) + && (nTimeoutSeconds == _rR.nTimeoutSeconds); + } + + DriverPoolingSettings::DriverPoolingSettings() + { + } + + + DriverPoolingSettingsItem::DriverPoolingSettingsItem( sal_uInt16 _nId, const DriverPoolingSettings &_rSettings ) + :SfxPoolItem(_nId) + ,m_aSettings(_rSettings) + { + } + + + bool DriverPoolingSettingsItem::operator==( const SfxPoolItem& _rCompare ) const + { + assert(SfxPoolItem::operator==(_rCompare)); + const DriverPoolingSettingsItem* pItem = static_cast( &_rCompare ); + + if (m_aSettings.size() != pItem->m_aSettings.size()) + return false; + + DriverPoolingSettings::const_iterator aForeign = pItem->m_aSettings.begin(); + for (auto const& ownSetting : m_aSettings) + { + if (ownSetting != *aForeign) + return false; + + ++aForeign; + } + + return true; + } + + DriverPoolingSettingsItem* DriverPoolingSettingsItem::Clone( SfxItemPool * ) const + { + return new DriverPoolingSettingsItem(*this); + } + + +} // namespace offapp + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/connpoolsettings.hxx b/cui/source/options/connpoolsettings.hxx new file mode 100644 index 000000000..8f8c6bc3b --- /dev/null +++ b/cui/source/options/connpoolsettings.hxx @@ -0,0 +1,86 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include + +#include + +#include +#include + + +namespace offapp +{ + + struct DriverPooling + { + OUString sName; + bool bEnabled; + sal_Int32 nTimeoutSeconds; + + explicit DriverPooling( const OUString& _rName ); + + bool operator == (const DriverPooling& _rR) const; + bool operator != (const DriverPooling& _rR) const { return !operator ==(_rR); } + }; + + class DriverPoolingSettings final + { + typedef std::vector DriverSettings; + DriverSettings m_aDrivers; + + public: + typedef DriverSettings::const_iterator const_iterator; + typedef DriverSettings::iterator iterator; + + DriverPoolingSettings(); + + size_t size() const { return m_aDrivers.size(); } + DriverPooling& operator[]( size_t nPos ) { return m_aDrivers[nPos]; } + bool empty() const { return m_aDrivers.empty(); } + + const_iterator begin() const { return m_aDrivers.begin(); } + const_iterator end() const { return m_aDrivers.end(); } + + iterator begin() { return m_aDrivers.begin(); } + iterator end() { return m_aDrivers.end(); } + + void push_back(const DriverPooling& _rElement) { m_aDrivers.push_back(_rElement); } + }; + + class DriverPoolingSettingsItem final : public SfxPoolItem + { + DriverPoolingSettings m_aSettings; + + public: + + DriverPoolingSettingsItem( sal_uInt16 _nId, const DriverPoolingSettings &_rSettings ); + + virtual bool operator==( const SfxPoolItem& ) const override; + virtual DriverPoolingSettingsItem* Clone( SfxItemPool *pPool = nullptr ) const override; + + const DriverPoolingSettings& getSettings() const { return m_aSettings; } + }; + + +} // namespace offapp + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/cuisrchdlg.cxx b/cui/source/options/cuisrchdlg.cxx new file mode 100644 index 000000000..f58985d90 --- /dev/null +++ b/cui/source/options/cuisrchdlg.cxx @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include + +#include "optjsearch.hxx" + + +// class SvxJSearchOptionsDialog ----------------------------------------- + +SvxJSearchOptionsDialog::SvxJSearchOptionsDialog(weld::Window *pParent, + const SfxItemSet& rOptionsSet, TransliterationFlags nInitialFlags) + : SfxSingleTabDialogController(pParent, &rOptionsSet) +{ + // m_xPage will be implicitly destroyed by the + // SfxSingleTabDialog destructor + SetTabPage(SvxJSearchOptionsPage::Create(get_content_area(), this, &rOptionsSet)); //! implicitly calls m_xPage->Reset(...)! + m_pPage = static_cast(GetTabPage()); + m_pPage->EnableSaveOptions(false); + m_pPage->SetTransliterationFlags(nInitialFlags); +} + +SvxJSearchOptionsDialog::~SvxJSearchOptionsDialog() +{ +} + +TransliterationFlags SvxJSearchOptionsDialog::GetTransliterationFlags() const +{ + return m_pPage->GetTransliterationFlags(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/dbregister.cxx b/cui/source/options/dbregister.cxx new file mode 100644 index 000000000..98fd6d19f --- /dev/null +++ b/cui/source/options/dbregister.cxx @@ -0,0 +1,304 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include "dbregistersettings.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include "doclinkdialog.hxx" +#include +#include "dbregisterednamesconfig.hxx" +#include + +#define COL_TYPE 0 + +namespace svx +{ + + +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star::uno; +using namespace ::svt; + +// class RegistrationItemSetHolder ------------------------------------------------- + +RegistrationItemSetHolder::RegistrationItemSetHolder( const SfxItemSet& _rMasterSet ) + :m_aRegistrationItems( _rMasterSet ) +{ + DbRegisteredNamesConfig::GetOptions( m_aRegistrationItems ); +} + +RegistrationItemSetHolder::~RegistrationItemSetHolder() +{ +} + +// class DatabaseRegistrationDialog ------------------------------------------------ + +DatabaseRegistrationDialog::DatabaseRegistrationDialog(weld::Window* pParent, const SfxItemSet& rInAttrs) + : RegistrationItemSetHolder(rInAttrs) + , SfxSingleTabDialogController(pParent, &getRegistrationItems()) +{ + SetTabPage(DbRegistrationOptionsPage::Create(get_content_area(), this, &getRegistrationItems())); + m_xDialog->set_title(CuiResId(RID_SVXSTR_REGISTERED_DATABASES)); +} + +short DatabaseRegistrationDialog::run() +{ + short result = SfxSingleTabDialogController::run(); + if (result == RET_OK) + { + DBG_ASSERT( GetOutputItemSet(), "DatabaseRegistrationDialog::Execute: no output items!" ); + if ( GetOutputItemSet() ) + DbRegisteredNamesConfig::SetOptions( *GetOutputItemSet() ); + } + return result; +} + +// class DbRegistrationOptionsPage -------------------------------------------------- + +DbRegistrationOptionsPage::DbRegistrationOptionsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/dbregisterpage.ui", "DbRegisterPage", &rSet) + , m_nOldCount(0) + , m_bModified(false) + , m_xNew(m_xBuilder->weld_button("new")) + , m_xEdit(m_xBuilder->weld_button("edit")) + , m_xDelete(m_xBuilder->weld_button("delete")) + , m_xPathBox(m_xBuilder->weld_tree_view("pathctrl")) + , m_xIter(m_xPathBox->make_iterator()) +{ + Size aControlSize(m_xPathBox->get_approximate_digit_width() * 60, + m_xPathBox->get_height_rows(12)); + m_xPathBox->set_size_request(aControlSize.Width(), aControlSize.Height()); + + std::vector aWidths; + aWidths.push_back(m_xPathBox->get_approximate_digit_width() * 20); + m_xPathBox->set_column_fixed_widths(aWidths); + + m_xNew->connect_clicked( LINK( this, DbRegistrationOptionsPage, NewHdl ) ); + m_xEdit->connect_clicked( LINK( this, DbRegistrationOptionsPage, EditHdl ) ); + m_xDelete->connect_clicked( LINK( this, DbRegistrationOptionsPage, DeleteHdl ) ); + + m_xPathBox->connect_column_clicked(LINK(this, DbRegistrationOptionsPage, HeaderSelect_Impl)); + + m_xPathBox->make_sorted(); + m_xPathBox->connect_row_activated( LINK( this, DbRegistrationOptionsPage, PathBoxDoubleClickHdl ) ); + m_xPathBox->connect_changed( LINK( this, DbRegistrationOptionsPage, PathSelect_Impl ) ); + + m_xPathBox->set_help_id(HID_DBPATH_CTL_PATH); +} + +DbRegistrationOptionsPage::~DbRegistrationOptionsPage() +{ + for (int i = 0, nCount = m_xPathBox->n_children(); i < nCount; ++i ) + delete reinterpret_cast(m_xPathBox->get_id(i).toInt64()); +} + +std::unique_ptr DbRegistrationOptionsPage::Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet ) +{ + return std::make_unique(pPage, pController, *rAttrSet); +} + +bool DbRegistrationOptionsPage::FillItemSet( SfxItemSet* rCoreSet ) +{ + // the settings for the single drivers + bool bModified = false; + DatabaseRegistrations aRegistrations; + int nCount = m_xPathBox->n_children(); + for (int i = 0; i < nCount; ++i) + { + DatabaseRegistration* pRegistration = reinterpret_cast(m_xPathBox->get_id(i).toInt64()); + if ( pRegistration && !pRegistration->sLocation.isEmpty() ) + { + OUString sName(m_xPathBox->get_text(i, 0)); + OFileNotation aTransformer( pRegistration->sLocation ); + aRegistrations[ sName ] = DatabaseRegistration( aTransformer.get( OFileNotation::N_URL ), pRegistration->bReadOnly ); + } + } + if ( m_nOldCount != aRegistrations.size() || m_bModified ) + { + rCoreSet->Put(DatabaseMapItem( SID_SB_DB_REGISTER, aRegistrations )); + bModified = true; + } + + return bModified; +} + +void DbRegistrationOptionsPage::Reset( const SfxItemSet* rSet ) +{ + // the settings for the single drivers + const DatabaseMapItem* pRegistrations = rSet->GetItem(SID_SB_DB_REGISTER); + if ( !pRegistrations ) + return; + + m_xPathBox->clear(); + + const DatabaseRegistrations& rRegistrations = pRegistrations->getRegistrations(); + m_nOldCount = rRegistrations.size(); + for (auto const& elem : rRegistrations) + { + OFileNotation aTransformer( elem.second.sLocation ); + insertNewEntry( elem.first, aTransformer.get( OFileNotation::N_SYSTEM ), elem.second.bReadOnly ); + } + + OUString aUserData = GetUserData(); + if ( !aUserData.isEmpty() ) + { + sal_Int32 nIdx {0}; + // restore column width + std::vector aWidths; + aWidths.push_back(aUserData.getToken(0, ';', nIdx).toInt32()); + m_xPathBox->set_column_fixed_widths(aWidths); + // restore sort direction + bool bUp = aUserData.getToken(0, ';', nIdx).toInt32() != 0; + m_xPathBox->set_sort_order(bUp); + m_xPathBox->set_sort_indicator(bUp ? TRISTATE_TRUE : TRISTATE_FALSE, COL_TYPE); + } +} + +void DbRegistrationOptionsPage::FillUserData() +{ + OUString aUserData = OUString::number( m_xPathBox->get_column_width(COL_TYPE) ) + ";"; + bool bUp = m_xPathBox->get_sort_order(); + aUserData += (bUp ? OUStringLiteral("1") : OUStringLiteral("0")); + SetUserData( aUserData ); +} + +IMPL_LINK_NOARG(DbRegistrationOptionsPage, DeleteHdl, weld::Button&, void) +{ + int nEntry = m_xPathBox->get_selected_index(); + if (nEntry != -1) + { + std::unique_ptr xQuery(Application::CreateMessageDialog(GetFrameWeld(), + VclMessageType::Question, VclButtonsType::YesNo, CuiResId(RID_SVXSTR_QUERY_DELETE_CONFIRM))); + if (xQuery->run() == RET_YES) + m_xPathBox->remove(nEntry); + } +} + +IMPL_LINK_NOARG(DbRegistrationOptionsPage, NewHdl, weld::Button&, void) +{ + openLinkDialog(OUString(),OUString()); +} + +IMPL_LINK_NOARG(DbRegistrationOptionsPage, PathBoxDoubleClickHdl, weld::TreeView&, bool) +{ + EditHdl(*m_xEdit); + return true; +} + +IMPL_LINK_NOARG(DbRegistrationOptionsPage, EditHdl, weld::Button&, void) +{ + int nEntry = m_xPathBox->get_selected_index(); + if (nEntry == -1) + return; + + DatabaseRegistration* pOldRegistration = reinterpret_cast(m_xPathBox->get_id(nEntry).toInt64()); + if (!pOldRegistration || pOldRegistration->bReadOnly) + return; + + OUString sOldName = m_xPathBox->get_text(nEntry, 0); + openLinkDialog(sOldName, pOldRegistration->sLocation, nEntry); +} + +IMPL_LINK( DbRegistrationOptionsPage, HeaderSelect_Impl, int, nCol, void ) +{ + if (nCol != COL_TYPE) + return; + + bool bSortMode = m_xPathBox->get_sort_order(); + + //set new arrow positions in headerbar + bSortMode = !bSortMode; + m_xPathBox->set_sort_order(bSortMode); + + //sort lists + m_xPathBox->set_sort_indicator(bSortMode ? TRISTATE_TRUE : TRISTATE_FALSE, nCol); +} + +IMPL_LINK_NOARG(DbRegistrationOptionsPage, PathSelect_Impl, weld::TreeView&, void) +{ + DatabaseRegistration* pRegistration = reinterpret_cast(m_xPathBox->get_selected_id().toInt64()); + + bool bReadOnly = true; + if (pRegistration) + { + bReadOnly = pRegistration->bReadOnly; + } + + m_xEdit->set_sensitive( !bReadOnly ); + m_xDelete->set_sensitive( !bReadOnly ); +} + +void DbRegistrationOptionsPage::insertNewEntry(const OUString& _sName,const OUString& _sLocation, const bool _bReadOnly) +{ + OUString sId(OUString::number(reinterpret_cast(new DatabaseRegistration(_sLocation, _bReadOnly)))); + m_xPathBox->insert(nullptr, -1, &_sName, &sId, nullptr, nullptr, nullptr, false, m_xIter.get()); + + if (_bReadOnly) + m_xPathBox->set_image(*m_xIter, RID_SVXBMP_LOCK); + + m_xPathBox->set_text(*m_xIter, _sLocation, 1); +} + +void DbRegistrationOptionsPage::openLinkDialog(const OUString& sOldName, const OUString& sOldLocation, int nEntry) +{ + ODocumentLinkDialog aDlg(GetFrameWeld(), nEntry == -1); + + aDlg.setLink(sOldName, sOldLocation); + aDlg.setNameValidator(LINK( this, DbRegistrationOptionsPage, NameValidator ) ); + + if (aDlg.run() != RET_OK) + return; + + OUString sNewName,sNewLocation; + aDlg.getLink(sNewName,sNewLocation); + if ( nEntry == -1 || sNewName != sOldName || sNewLocation != sOldLocation ) + { + if (nEntry != -1) + { + delete reinterpret_cast(m_xPathBox->get_id(nEntry).toInt64()); + m_xPathBox->remove(nEntry); + } + insertNewEntry( sNewName, sNewLocation, false ); + m_bModified = true; + } +} + +IMPL_LINK( DbRegistrationOptionsPage, NameValidator, const OUString&, _rName, bool ) +{ + int nCount = m_xPathBox->n_children(); + for (int i = 0; i < nCount; ++i) + { + if (m_xPathBox->get_text(i, 0) == _rName) + return false; + } + return true; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/dbregisterednamesconfig.cxx b/cui/source/options/dbregisterednamesconfig.cxx new file mode 100644 index 000000000..87681866e --- /dev/null +++ b/cui/source/options/dbregisterednamesconfig.cxx @@ -0,0 +1,122 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "dbregisterednamesconfig.hxx" +#include "dbregistersettings.hxx" +#include +#include +#include +#include +#include + + +namespace svx +{ + + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::sdb; + using namespace ::com::sun::star::container; + + void DbRegisteredNamesConfig::GetOptions( SfxItemSet& _rFillItems ) + { + DatabaseRegistrations aSettings; + + try + { + Reference xContext( ::comphelper::getProcessComponentContext() ); + Reference< XDatabaseContext > xRegistrations( + DatabaseContext::create(xContext) ); + + Sequence< OUString > aRegistrationNames( xRegistrations->getRegistrationNames() ); + const OUString* pRegistrationName = aRegistrationNames.getConstArray(); + const OUString* pRegistrationNamesEnd = pRegistrationName + aRegistrationNames.getLength(); + for ( ; pRegistrationName != pRegistrationNamesEnd; ++pRegistrationName ) + { + OUString sLocation( xRegistrations->getDatabaseLocation( *pRegistrationName ) ); + aSettings[ *pRegistrationName ] = + DatabaseRegistration( sLocation, xRegistrations->isDatabaseRegistrationReadOnly( *pRegistrationName ) ); + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("cui.options"); + } + + _rFillItems.Put( DatabaseMapItem( SID_SB_DB_REGISTER, aSettings ) ); + } + + + void DbRegisteredNamesConfig::SetOptions(const SfxItemSet& _rSourceItems) + { + // the settings for the single drivers + const DatabaseMapItem* pRegistrations = _rSourceItems.GetItem(SID_SB_DB_REGISTER); + if ( !pRegistrations ) + return; + + try + { + Reference< XDatabaseContext > xRegistrations( + DatabaseContext::create( + comphelper::getProcessComponentContext())); + + const DatabaseRegistrations& rNewRegistrations = pRegistrations->getRegistrations(); + for ( DatabaseRegistrations::const_iterator reg = rNewRegistrations.begin(); + reg != rNewRegistrations.end(); + ++reg + ) + { + const OUString sName = reg->first; + const OUString sLocation = reg->second.sLocation; + + if ( xRegistrations->hasRegisteredDatabase( sName ) ) + { + if ( !xRegistrations->isDatabaseRegistrationReadOnly( sName ) ) + xRegistrations->changeDatabaseLocation( sName, sLocation ); + else + { + OSL_ENSURE( xRegistrations->getDatabaseLocation( sName ) == sLocation, + "DbRegisteredNamesConfig::SetOptions: somebody changed a read-only registration. How unrespectful." ); + } + } + else + xRegistrations->registerDatabaseLocation( sName, sLocation ); + } + + // delete unused entries + Sequence< OUString > aRegistrationNames = xRegistrations->getRegistrationNames(); + const OUString* pRegistrationName = aRegistrationNames.getConstArray(); + const OUString* pRegistrationNamesEnd = pRegistrationName + aRegistrationNames.getLength(); + for ( ; pRegistrationName != pRegistrationNamesEnd; ++pRegistrationName ) + { + if ( rNewRegistrations.find( *pRegistrationName ) == rNewRegistrations.end() ) + xRegistrations->revokeDatabaseLocation( *pRegistrationName ); + } + } + catch( const Exception& ) + { + //DBG_UNHANDLED_EXCEPTION(); + } + } + + +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/dbregisterednamesconfig.hxx b/cui/source/options/dbregisterednamesconfig.hxx new file mode 100644 index 000000000..9decf7e11 --- /dev/null +++ b/cui/source/options/dbregisterednamesconfig.hxx @@ -0,0 +1,38 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +class SfxItemSet; + +namespace svx +{ + + class DbRegisteredNamesConfig + { + + public: + static void GetOptions(SfxItemSet& _rFillItems); + static void SetOptions(const SfxItemSet& _rSourceItems); + }; + + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/dbregistersettings.cxx b/cui/source/options/dbregistersettings.cxx new file mode 100644 index 000000000..f7739a109 --- /dev/null +++ b/cui/source/options/dbregistersettings.cxx @@ -0,0 +1,55 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "dbregistersettings.hxx" + +#include + + +namespace svx +{ + + DatabaseMapItem::DatabaseMapItem( sal_uInt16 _nId, const DatabaseRegistrations& _rRegistrations ) + :SfxPoolItem( _nId ) + ,m_aRegistrations( _rRegistrations ) + { + } + + bool DatabaseMapItem::operator==( const SfxPoolItem& _rCompare ) const + { + if (!SfxPoolItem::operator==(_rCompare)) + return false; + const DatabaseMapItem* pItem = static_cast( &_rCompare ); + if ( !pItem ) + return false; + + if ( m_aRegistrations.size() != pItem->m_aRegistrations.size() ) + return false; + + return m_aRegistrations == pItem->m_aRegistrations; + } + + DatabaseMapItem* DatabaseMapItem::Clone( SfxItemPool* ) const + { + return new DatabaseMapItem( *this ); + } + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/dbregistersettings.hxx b/cui/source/options/dbregistersettings.hxx new file mode 100644 index 000000000..9146afe7b --- /dev/null +++ b/cui/source/options/dbregistersettings.hxx @@ -0,0 +1,79 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include + +#include + +#include + + +namespace svx +{ + + + struct DatabaseRegistration + { + OUString sLocation; + bool bReadOnly; + + DatabaseRegistration() + :sLocation() + ,bReadOnly( true ) + { + } + + DatabaseRegistration( const OUString& _rLocation, const bool _bReadOnly ) + :sLocation( _rLocation ) + ,bReadOnly( _bReadOnly ) + { + } + + bool operator==( const DatabaseRegistration& _rhs ) const + { + return ( sLocation == _rhs.sLocation ); + // do not take the read-only-ness into account, this is not maintained everywhere, but only + // properly set when filling the struct from the XDatabaseRegistrations data + } + + }; + + typedef std::map< OUString, DatabaseRegistration > DatabaseRegistrations; + + class DatabaseMapItem final : public SfxPoolItem + { + DatabaseRegistrations m_aRegistrations; + + public: + + DatabaseMapItem( sal_uInt16 _nId, const DatabaseRegistrations& _rRegistrations ); + + virtual bool operator==( const SfxPoolItem& ) const override; + virtual DatabaseMapItem* Clone( SfxItemPool *pPool = nullptr ) const override; + + const DatabaseRegistrations& + getRegistrations() const { return m_aRegistrations; } + }; + + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/doclinkdialog.cxx b/cui/source/options/doclinkdialog.cxx new file mode 100644 index 000000000..4218a18a1 --- /dev/null +++ b/cui/source/options/doclinkdialog.cxx @@ -0,0 +1,199 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "doclinkdialog.hxx" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace svx +{ + using namespace ::com::sun::star; + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::ucb; + using namespace ::svt; + + ODocumentLinkDialog::ODocumentLinkDialog(weld::Window* pParent, bool _bCreateNew) + : GenericDialogController(pParent, "cui/ui/databaselinkdialog.ui", "DatabaseLinkDialog") + , m_xBrowseFile(m_xBuilder->weld_button("browse")) + , m_xName(m_xBuilder->weld_entry("name")) + , m_xOK(m_xBuilder->weld_button("ok")) + , m_xAltTitle(m_xBuilder->weld_label("alttitle")) + , m_xURL(new SvtURLBox(m_xBuilder->weld_combo_box("url"))) + { + if (!_bCreateNew) + m_xDialog->set_title(m_xAltTitle->get_label()); + + m_xURL->SetSmartProtocol(INetProtocol::File); + m_xURL->DisableHistory(); + m_xURL->SetFilter("*.odb"); + + m_xName->connect_changed( LINK(this, ODocumentLinkDialog, OnEntryModified) ); + m_xURL->connect_changed( LINK(this, ODocumentLinkDialog, OnComboBoxModified) ); + m_xBrowseFile->connect_clicked( LINK(this, ODocumentLinkDialog, OnBrowseFile) ); + m_xOK->connect_clicked( LINK(this, ODocumentLinkDialog, OnOk) ); + + validate(); + } + + ODocumentLinkDialog::~ODocumentLinkDialog() + { + } + + void ODocumentLinkDialog::setLink(const OUString& rName, const OUString& rURL) + { + m_xName->set_text(rName); + m_xURL->set_entry_text(rURL); + validate(); + } + + void ODocumentLinkDialog::getLink(OUString& rName, OUString& rURL) const + { + rName = m_xName->get_text(); + rURL = m_xURL->get_active_text(); + } + + void ODocumentLinkDialog::validate( ) + { + m_xOK->set_sensitive((!m_xName->get_text().isEmpty()) && (!m_xURL->get_active_text().isEmpty())); + } + + IMPL_LINK_NOARG(ODocumentLinkDialog, OnOk, weld::Button&, void) + { + // get the current URL + OUString sURL = m_xURL->get_active_text(); + OFileNotation aTransformer(sURL); + sURL = aTransformer.get(OFileNotation::N_URL); + + // check for the existence of the selected file + bool bFileExists = false; + try + { + ::ucbhelper::Content aFile(sURL, Reference< XCommandEnvironment >(), comphelper::getProcessComponentContext()); + if (aFile.isDocument()) + bFileExists = true; + } + catch(Exception&) + { + } + + if (!bFileExists) + { + OUString sMsg = CuiResId(STR_LINKEDDOC_DOESNOTEXIST); + sMsg = sMsg.replaceFirst("$file$", m_xURL->get_active_text()); + std::unique_ptr xErrorBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Warning, VclButtonsType::Ok, sMsg)); + xErrorBox->run(); + return; + } // if (!bFileExists) + INetURLObject aURL( sURL ); + if ( aURL.GetProtocol() != INetProtocol::File ) + { + OUString sMsg = CuiResId(STR_LINKEDDOC_NO_SYSTEM_FILE); + sMsg = sMsg.replaceFirst("$file$", m_xURL->get_active_text()); + std::unique_ptr xErrorBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Warning, VclButtonsType::Ok, sMsg)); + xErrorBox->run(); + return; + } + + OUString sCurrentText = m_xName->get_text(); + if ( m_aNameValidator.IsSet() ) + { + if ( !m_aNameValidator.Call( sCurrentText ) ) + { + OUString sMsg = CuiResId(STR_NAME_CONFLICT); + sMsg = sMsg.replaceFirst("$file$", sCurrentText); + std::unique_ptr xErrorBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Info, VclButtonsType::Ok, sMsg)); + xErrorBox->run(); + + m_xName->select_region(0, -1); + m_xName->grab_focus(); + return; + } + } + + m_xDialog->response(RET_OK); + } + + IMPL_LINK_NOARG(ODocumentLinkDialog, OnBrowseFile, weld::Button&, void) + { + ::sfx2::FileDialogHelper aFileDlg( + ui::dialogs::TemplateDescription::FILEOPEN_READONLY_VERSION, FileDialogFlags::NONE, m_xDialog.get()); + std::shared_ptr pFilter = SfxFilter::GetFilterByName("StarOffice XML (Base)"); + if ( pFilter ) + { + aFileDlg.AddFilter(pFilter->GetUIName(),pFilter->GetDefaultExtension()); + aFileDlg.SetCurrentFilter(pFilter->GetUIName()); + } + + OUString sPath = m_xURL->get_active_text(); + if (!sPath.isEmpty()) + { + OFileNotation aTransformer( sPath, OFileNotation::N_SYSTEM ); + aFileDlg.SetDisplayDirectory( aTransformer.get( OFileNotation::N_URL ) ); + } + + if (ERRCODE_NONE != aFileDlg.Execute()) + return; + + if (m_xName->get_text().isEmpty()) + { // default the name to the base of the chosen URL + INetURLObject aParser; + + aParser.SetSmartProtocol(INetProtocol::File); + aParser.SetSmartURL(aFileDlg.GetPath()); + + m_xName->set_text(aParser.getBase(INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::WithCharset)); + + m_xName->select_region(0, -1); + m_xName->grab_focus(); + } + else + m_xURL->grab_focus(); + + // get the path in system notation + OFileNotation aTransformer(aFileDlg.GetPath(), OFileNotation::N_URL); + m_xURL->set_entry_text(aTransformer.get(OFileNotation::N_SYSTEM)); + + validate(); + } + + IMPL_LINK_NOARG(ODocumentLinkDialog, OnEntryModified, weld::Entry&, void) + { + validate(); + } + + IMPL_LINK_NOARG(ODocumentLinkDialog, OnComboBoxModified, weld::ComboBox&, void) + { + validate(); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/doclinkdialog.hxx b/cui/source/options/doclinkdialog.hxx new file mode 100644 index 000000000..371dc6504 --- /dev/null +++ b/cui/source/options/doclinkdialog.hxx @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include +#include + +namespace svx +{ + /** dialog for editing document links associated with data sources + */ + class ODocumentLinkDialog final : public weld::GenericDialogController + { + Link m_aNameValidator; + + std::unique_ptr m_xBrowseFile; + std::unique_ptr m_xName; + std::unique_ptr m_xOK; + std::unique_ptr m_xAltTitle; + std::unique_ptr m_xURL; + + public: + ODocumentLinkDialog(weld::Window* pParent, bool bCreateNew); + virtual ~ODocumentLinkDialog() override; + + // name validation has to be done by an external instance + // the validator link gets a pointer to a String, and should return 0 if the string is not + // acceptable + void setNameValidator( const Link& _rValidator ) { m_aNameValidator = _rValidator; } + + void setLink( const OUString& _rName, const OUString& _rURL ); + void getLink( OUString& _rName, OUString& _rURL ) const; + + private: + DECL_LINK( OnEntryModified, weld::Entry&, void ); + DECL_LINK( OnComboBoxModified, weld::ComboBox&, void ); + DECL_LINK( OnBrowseFile, weld::Button&, void ); + DECL_LINK( OnOk, weld::Button&, void ); + + void validate(); + }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/fontsubs.cxx b/cui/source/options/fontsubs.cxx new file mode 100644 index 000000000..d6e724fa4 --- /dev/null +++ b/cui/source/options/fontsubs.cxx @@ -0,0 +1,415 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include +#include +#include +#include +#include "fontsubs.hxx" +#include + +/*********************************************************************/ +/* */ +/* TabPage font replacement */ +/* */ +/*********************************************************************/ + +SvxFontSubstTabPage::SvxFontSubstTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/optfontspage.ui", "OptFontsPage", &rSet) + , m_xConfig(new SvtFontSubstConfig) + , m_xUseTableCB(m_xBuilder->weld_check_button("usetable")) + , m_xFont1CB(m_xBuilder->weld_combo_box("font1")) + , m_xFont2CB(m_xBuilder->weld_combo_box("font2")) + , m_xApply(m_xBuilder->weld_button("apply")) + , m_xDelete(m_xBuilder->weld_button("delete")) + , m_xCheckLB(m_xBuilder->weld_tree_view("checklb")) + , m_xFontNameLB(m_xBuilder->weld_combo_box("fontname")) + , m_xNonPropFontsOnlyCB(m_xBuilder->weld_check_button("nonpropfontonly")) + , m_xFontHeightLB(m_xBuilder->weld_combo_box("fontheight")) +{ + m_xFont1CB->make_sorted(); + m_xFont1CB->set_size_request(1, -1); + m_xFont2CB->make_sorted(); + m_xFont2CB->set_size_request(1, -1); + m_sAutomatic = m_xFontNameLB->get_text(0); + assert(!m_sAutomatic.isEmpty()); + + m_xCheckLB->set_size_request(m_xCheckLB->get_approximate_digit_width() * 60, + m_xCheckLB->get_height_rows(8)); + m_xCheckLB->set_help_id(HID_OFA_FONT_SUBST_CLB); + m_xCheckLB->set_selection_mode(SelectionMode::Multiple); + + setColSizes(m_xCheckLB->get_size_request()); + m_xCheckLB->connect_size_allocate(LINK(this, SvxFontSubstTabPage, ResizeHdl)); + + m_xCheckLB->set_centered_column(1); + m_xCheckLB->set_centered_column(2); + + Link aLink2(LINK(this, SvxFontSubstTabPage, SelectComboBoxHdl)); + Link aClickLink(LINK(this, SvxFontSubstTabPage, ClickHdl)); + + m_xCheckLB->connect_changed(LINK(this, SvxFontSubstTabPage, TreeListBoxSelectHdl)); + m_xCheckLB->connect_column_clicked(LINK(this, SvxFontSubstTabPage, HeaderBarClick)); + m_xUseTableCB->connect_clicked(aClickLink); + m_xFont1CB->connect_changed(aLink2); + m_xFont2CB->connect_changed(aLink2); + m_xApply->connect_clicked(aClickLink); + m_xDelete->connect_clicked(aClickLink); + + m_xNonPropFontsOnlyCB->connect_toggled(LINK(this, SvxFontSubstTabPage, NonPropFontsHdl)); + + sal_uInt16 nHeight; + for(nHeight = 6; nHeight <= 16; nHeight++) + m_xFontHeightLB->append_text(OUString::number(nHeight)); + for(nHeight = 18; nHeight <= 28; nHeight+= 2) + m_xFontHeightLB->append_text(OUString::number(nHeight)); + for(nHeight = 32; nHeight <= 48; nHeight+= 4) + m_xFontHeightLB->append_text(OUString::number(nHeight)); + for(nHeight = 54; nHeight <= 72; nHeight+= 6) + m_xFontHeightLB->append_text(OUString::number(nHeight)); + for(nHeight = 80; nHeight <= 96; nHeight+= 8) + m_xFontHeightLB->append_text(OUString::number(nHeight)); +} + +IMPL_LINK(SvxFontSubstTabPage, HeaderBarClick, int, nColumn, void) +{ + bool bSortAtoZ = m_xCheckLB->get_sort_order(); + + //set new arrow positions in headerbar + if (nColumn == m_xCheckLB->get_sort_column()) + { + bSortAtoZ = !bSortAtoZ; + m_xCheckLB->set_sort_order(bSortAtoZ); + } + else + { + m_xCheckLB->set_sort_indicator(TRISTATE_INDET, m_xCheckLB->get_sort_column()); + m_xCheckLB->set_sort_column(nColumn); + } + + if (nColumn != -1) + { + //sort lists + m_xCheckLB->set_sort_indicator(bSortAtoZ ? TRISTATE_TRUE : TRISTATE_FALSE, nColumn); + } +} + +void SvxFontSubstTabPage::setColSizes(const Size& rSize) +{ + int nW1 = m_xCheckLB->get_pixel_size(m_xCheckLB->get_column_title(3)).Width(); + int nW2 = m_xCheckLB->get_pixel_size(m_xCheckLB->get_column_title(4)).Width(); + int nMax = std::max( nW1, nW2 ) + 6; // width of the longest header + a little offset + int nMin = m_xCheckLB->get_checkbox_column_width(); + nMax = std::max(nMax, nMin); + const int nDoubleMax = 2*nMax; + const int nRest = rSize.Width() - nDoubleMax; + std::vector aWidths; + aWidths.push_back(1); // just abandon the built-in column for checkbuttons and use another + aWidths.push_back(nMax); + aWidths.push_back(nMax); + aWidths.push_back(nRest/2); + m_xCheckLB->set_column_fixed_widths(aWidths); +} + +IMPL_LINK(SvxFontSubstTabPage, ResizeHdl, const Size&, rSize, void) +{ + setColSizes(rSize); +} + +SvxFontSubstTabPage::~SvxFontSubstTabPage() +{ +} + +std::unique_ptr SvxFontSubstTabPage::Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet) +{ + return std::make_unique(pPage, pController, *rAttrSet); +} + +bool SvxFontSubstTabPage::FillItemSet( SfxItemSet* ) +{ + m_xConfig->ClearSubstitutions();// remove all entries + + m_xConfig->Enable(m_xUseTableCB->get_active()); + + m_xCheckLB->all_foreach([this](weld::TreeIter& rIter) { + SubstitutionStruct aAdd; + aAdd.sFont = m_xCheckLB->get_text(rIter, 3); + aAdd.sReplaceBy = m_xCheckLB->get_text(rIter, 4); + aAdd.bReplaceAlways = m_xCheckLB->get_toggle(rIter, 1); + aAdd.bReplaceOnScreenOnly = m_xCheckLB->get_toggle(rIter, 2); + m_xConfig->AddSubstitution(aAdd); + return false; + }); + + if(m_xConfig->IsModified()) + m_xConfig->Commit(); + m_xConfig->Apply(); + std::shared_ptr< comphelper::ConfigurationChanges > batch( + comphelper::ConfigurationChanges::create()); + if (m_xFontHeightLB->get_value_changed_from_saved()) + officecfg::Office::Common::Font::SourceViewFont::FontHeight::set( + static_cast< sal_Int16 >(m_xFontHeightLB->get_active_text().toInt32()), + batch); + if (m_xNonPropFontsOnlyCB->get_state_changed_from_saved()) + officecfg::Office::Common::Font::SourceViewFont:: + NonProportionalFontsOnly::set( + m_xNonPropFontsOnlyCB->get_active(), batch); + //font name changes cannot be detected by saved values + OUString sFontName; + if (m_xFontNameLB->get_active() != -1) + sFontName = m_xFontNameLB->get_active_text(); + officecfg::Office::Common::Font::SourceViewFont::FontName::set( + std::optional< OUString >(sFontName), batch); + batch->commit(); + + return false; +} + +void SvxFontSubstTabPage::Reset( const SfxItemSet* ) +{ + m_xCheckLB->freeze(); + m_xCheckLB->clear(); + + m_xFont1CB->freeze(); + m_xFont1CB->clear(); + m_xFont2CB->freeze(); + m_xFont2CB->clear(); + + FontList aFntLst(Application::GetDefaultDevice()); + sal_uInt16 nFontCount = aFntLst.GetFontNameCount(); + for (sal_uInt16 i = 0; i < nFontCount; ++i) + { + const FontMetric& rFontMetric = aFntLst.GetFontName(i); + m_xFont1CB->append_text(rFontMetric.GetFamilyName()); + m_xFont2CB->append_text(rFontMetric.GetFamilyName()); + } + + m_xFont2CB->thaw(); + m_xFont1CB->thaw(); + + sal_Int32 nCount = m_xConfig->SubstitutionCount(); + if (nCount) + m_xUseTableCB->set_active(m_xConfig->IsEnabled()); + + std::unique_ptr xIter(m_xCheckLB->make_iterator()); + for (sal_Int32 i = 0; i < nCount; ++i) + { + m_xCheckLB->append(xIter.get()); + const SubstitutionStruct* pSubs = m_xConfig->GetSubstitution(i); + m_xCheckLB->set_toggle(*xIter, pSubs->bReplaceAlways ? TRISTATE_TRUE : TRISTATE_FALSE, 1); + m_xCheckLB->set_toggle(*xIter, pSubs->bReplaceOnScreenOnly ? TRISTATE_TRUE : TRISTATE_FALSE, 2); + m_xCheckLB->set_text(*xIter, pSubs->sFont, 3); + m_xCheckLB->set_text(*xIter, pSubs->sReplaceBy, 4); + } + + m_xCheckLB->thaw(); + + m_xCheckLB->make_sorted(); + m_xCheckLB->set_sort_column(3); + m_xCheckLB->set_sort_indicator(TRISTATE_TRUE, 3); + + CheckEnable(); + + //fill font name box first + m_xNonPropFontsOnlyCB->set_active( + officecfg::Office::Common::Font::SourceViewFont:: + NonProportionalFontsOnly::get()); + NonPropFontsHdl(*m_xNonPropFontsOnlyCB); + OUString sFontName( + officecfg::Office::Common::Font::SourceViewFont::FontName::get(). + value_or(OUString())); + if(!sFontName.isEmpty()) + m_xFontNameLB->set_active_text(sFontName); + else + m_xFontNameLB->set_active(0); + m_xFontHeightLB->set_active_text( + OUString::number( + officecfg::Office::Common::Font::SourceViewFont::FontHeight:: + get())); + m_xNonPropFontsOnlyCB->save_state(); + m_xFontHeightLB->save_value(); +} + +IMPL_LINK(SvxFontSubstTabPage, ClickHdl, weld::Button&, rButton, void) +{ + SelectHdl(&rButton); +} + +IMPL_LINK(SvxFontSubstTabPage, TreeListBoxSelectHdl, weld::TreeView&, rButton, void) +{ + SelectHdl(&rButton); +} + +IMPL_LINK(SvxFontSubstTabPage, SelectComboBoxHdl, weld::ComboBox&, rBox, void) +{ + SelectHdl(&rBox); +} + +namespace +{ + // search in the "font" column + int findText(const weld::TreeView& rTreeView, const OUString& rCol) + { + for (int i = 0, nEntryCount = rTreeView.n_children(); i < nEntryCount; ++i) + { + if (rTreeView.get_text(i, 3) == rCol) + return i; + } + return -1; + } + + bool findRow(const weld::TreeView& rTreeView, const OUString& rCol1, const OUString& rCol2) + { + int nRow = findText(rTreeView, rCol1); + if (nRow == -1) + return false; + return rTreeView.get_text(nRow, 4) == rCol2; + } +} + +void SvxFontSubstTabPage::SelectHdl(const weld::Widget* pWin) +{ + if (pWin == m_xApply.get() || pWin == m_xDelete.get()) + { + int nPos = findText(*m_xCheckLB, m_xFont1CB->get_active_text()); + if (pWin == m_xApply.get()) + { + m_xCheckLB->unselect_all(); + if (nPos != -1) + { + // change entry + m_xCheckLB->set_text(nPos, m_xFont2CB->get_active_text(), 4); + m_xCheckLB->select(nPos); + } + else + { + // new entry + OUString sFont1 = m_xFont1CB->get_active_text(); + OUString sFont2 = m_xFont2CB->get_active_text(); + + std::unique_ptr xIter(m_xCheckLB->make_iterator()); + m_xCheckLB->append(xIter.get()); + m_xCheckLB->set_toggle(*xIter, TRISTATE_FALSE, 1); + m_xCheckLB->set_toggle(*xIter, TRISTATE_FALSE, 2); + m_xCheckLB->set_text(*xIter, sFont1, 3); + m_xCheckLB->set_text(*xIter, sFont2, 4); + m_xCheckLB->select(*xIter); + } + } + else if (pWin == m_xDelete.get()) + { + m_xCheckLB->remove_selection(); + } + } + + if (pWin == m_xCheckLB.get()) + { + if (m_xCheckLB->count_selected_rows() == 1) + { + int nRow = m_xCheckLB->get_selected_index(); + m_xFont1CB->set_entry_text(m_xCheckLB->get_text(nRow, 3)); + m_xFont2CB->set_entry_text(m_xCheckLB->get_text(nRow, 4)); + } + } + + if (pWin == m_xFont1CB.get()) + { + int nPos = findText(*m_xCheckLB, m_xFont1CB->get_active_text()); + + if (nPos != -1) + { + int nSelectedRow = m_xCheckLB->get_selected_index(); + if (nPos != nSelectedRow) + { + m_xCheckLB->unselect_all(); + m_xCheckLB->select(nPos); + } + } + } + + CheckEnable(); +} + +IMPL_LINK(SvxFontSubstTabPage, NonPropFontsHdl, weld::ToggleButton&, rBox, void) +{ + OUString sFontName = m_xFontNameLB->get_active_text(); + bool bNonPropOnly = rBox.get_active(); + m_xFontNameLB->clear(); + FontList aFntLst( Application::GetDefaultDevice() ); + m_xFontNameLB->append_text(m_sAutomatic); + sal_uInt16 nFontCount = aFntLst.GetFontNameCount(); + for(sal_uInt16 nFont = 0; nFont < nFontCount; nFont++) + { + const FontMetric& rFontMetric = aFntLst.GetFontName( nFont ); + if(!bNonPropOnly || rFontMetric.GetPitch() == PITCH_FIXED) + m_xFontNameLB->append_text(rFontMetric.GetFamilyName()); + } + m_xFontNameLB->set_active_text(sFontName); +} + +void SvxFontSubstTabPage::CheckEnable() +{ + bool bEnableAll = m_xUseTableCB->get_active(); + m_xCheckLB->set_sensitive(bEnableAll); + if (bEnableAll) + { + bool bApply, bDelete; + + int nEntry = m_xCheckLB->get_selected_index(); + + // because of OS/2 optimization error (Bug #56267) a bit more intricate: + if (m_xFont1CB->get_active_text().isEmpty() || m_xFont2CB->get_active_text().isEmpty()) + bApply = false; + else if (m_xFont1CB->get_active_text() == m_xFont2CB->get_active_text()) + bApply = false; + else if (findRow(*m_xCheckLB, m_xFont1CB->get_active_text(), m_xFont2CB->get_active_text())) + bApply = false; + else if (nEntry != -1 && m_xCheckLB->count_selected_rows() != 1) + bApply = false; + else + bApply = true; + + bDelete = nEntry != -1; + + m_xApply->set_sensitive(bApply); + m_xDelete->set_sensitive(bDelete); + } + + if (bEnableAll) + { + if (!m_xCheckLB->get_sensitive()) + { + m_xCheckLB->set_sensitive(true); + SelectHdl(m_xFont1CB.get()); + } + } + else + { + if (m_xCheckLB->get_sensitive()) + { + m_xCheckLB->set_sensitive(false); + m_xCheckLB->unselect_all(); + } + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/fontsubs.hxx b/cui/source/options/fontsubs.hxx new file mode 100644 index 000000000..7af81e211 --- /dev/null +++ b/cui/source/options/fontsubs.hxx @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include + +// class SvxFontSubstTabPage ---------------------------------------------------- +class SvtFontSubstConfig; +class SvxFontSubstTabPage : public SfxTabPage +{ + OUString m_sAutomatic; + std::unique_ptr m_xConfig; + + std::unique_ptr m_xUseTableCB; + std::unique_ptr m_xFont1CB; + std::unique_ptr m_xFont2CB; + std::unique_ptr m_xApply; + std::unique_ptr m_xDelete; + std::unique_ptr m_xCheckLB; + std::unique_ptr m_xFontNameLB; + std::unique_ptr m_xNonPropFontsOnlyCB; + std::unique_ptr m_xFontHeightLB; + + DECL_LINK(SelectComboBoxHdl, weld::ComboBox&, void); + DECL_LINK(ClickHdl, weld::Button&, void); + DECL_LINK(TreeListBoxSelectHdl, weld::TreeView&, void); + DECL_LINK(NonPropFontsHdl, weld::ToggleButton&, void); + DECL_LINK(HeaderBarClick, int, void); + DECL_LINK(ResizeHdl, const Size&, void); + + void SelectHdl(const weld::Widget* pWidget); + + void CheckEnable(); + void setColSizes(const Size& rSize); + +public: + SvxFontSubstTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet); + virtual ~SvxFontSubstTabPage() override; + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/optaboutconfig.cxx b/cui/source/options/optaboutconfig.cxx new file mode 100644 index 000000000..7f5e73a80 --- /dev/null +++ b/cui/source/options/optaboutconfig.cxx @@ -0,0 +1,932 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "optaboutconfig.hxx" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +using namespace ::com::sun::star; +using namespace com::sun::star::uno; +using namespace com::sun::star::container; + +#define SHORT_LEN_LIMIT 7 +#define LONG_LEN_LIMIT 11 +#define HYPER_LEN_LIMIT 20 + +struct Prop_Impl +{ + OUString Name; + OUString Property; + Any Value; + + Prop_Impl( const OUString& sName, const OUString& sProperty, const Any& aValue ) + : Name( sName ) + , Property( sProperty ) + , Value( aValue ) + {} +}; + +struct UserData +{ + bool bIsPropertyPath; + OUString sPropertyPath; + int aLineage; + Reference aXNameAccess; + + explicit UserData( OUString const & rPropertyPath ) + : bIsPropertyPath( true ) + , sPropertyPath(rPropertyPath) + , aLineage(0) + {} + + explicit UserData( Reference const & rXNameAccess, int rIndex ) + : bIsPropertyPath( false ) + , aLineage(rIndex) + , aXNameAccess( rXNameAccess ) + {} +}; + +IMPL_LINK(CuiAboutConfigValueDialog, KeyInputHdl, const KeyEvent&, rKeyEvent, bool) +{ + bool bValid = false; + bool bNonSpace = rKeyEvent.GetKeyCode().GetCode() != KEY_SPACE; + if (m_bNumericOnly && bNonSpace ) + { + const vcl::KeyCode& rKeyCode = rKeyEvent.GetKeyCode(); + sal_uInt16 nGroup = rKeyCode.GetGroup(); + sal_uInt16 nKey = rKeyCode.GetCode(); + + switch ( nGroup ) { + case KEYGROUP_NUM : + case KEYGROUP_CURSOR : + { + bValid = true; + break; + } + + case KEYGROUP_MISC : + { + switch ( nKey ) { + case KEY_SUBTRACT : + case KEY_COMMA : + case KEY_POINT : + { + bValid = true; + break; + } + + default : + { + if( nKey < KEY_ADD || nKey > KEY_EQUAL ) + bValid = true; + break; + } + } + break; + } + + default : + { + bValid = false; + break; + } + } + + //Select all, Copy, Paste, Cut, Undo Keys + if ( !bValid && ( rKeyCode.IsMod1() && ( + KEY_A == nKey || KEY_C == nKey || KEY_V == nKey || KEY_X == nKey || KEY_Z == nKey ) ) ) + bValid = true; + } + else + bValid = true; + + //if value return true to claim that it has been handled + return !bValid; +} + +CuiAboutConfigTabPage::CuiAboutConfigTabPage(weld::Window* pParent) + : GenericDialogController(pParent, "cui/ui/aboutconfigdialog.ui", "AboutConfig") + , m_xResetBtn(m_xBuilder->weld_button("reset")) + , m_xEditBtn(m_xBuilder->weld_button("edit")) + , m_xSearchBtn(m_xBuilder->weld_button("searchButton")) + , m_xSearchEdit(m_xBuilder->weld_entry("searchEntry")) + , m_xPrefBox(m_xBuilder->weld_tree_view("preferences")) + , m_xScratchIter(m_xPrefBox->make_iterator()) + , m_vectorOfModified() + , m_bSorted(false) +{ + m_xPrefBox->set_size_request(m_xPrefBox->get_approximate_digit_width() * 100, + m_xPrefBox->get_height_rows(28)); + m_xPrefBox->connect_column_clicked(LINK(this, CuiAboutConfigTabPage, HeaderBarClick)); + + m_xEditBtn->connect_clicked(LINK( this, CuiAboutConfigTabPage, StandardHdl_Impl)); + m_xResetBtn->connect_clicked(LINK( this, CuiAboutConfigTabPage, ResetBtnHdl_Impl)); + m_xPrefBox->connect_row_activated(LINK(this, CuiAboutConfigTabPage, DoubleClickHdl_Impl)); + m_xPrefBox->connect_expanding(LINK(this, CuiAboutConfigTabPage, ExpandingHdl_Impl)); + m_xSearchBtn->connect_clicked(LINK(this, CuiAboutConfigTabPage, SearchHdl_Impl)); + + m_options.AlgorithmType2 = util::SearchAlgorithms2::ABSOLUTE; + m_options.transliterateFlags |= TransliterationFlags::IGNORE_CASE; + m_options.searchFlag |= (util::SearchFlags::REG_NOT_BEGINOFLINE | + util::SearchFlags::REG_NOT_ENDOFLINE); + + float fWidth = m_xPrefBox->get_approximate_digit_width(); + std::vector aWidths; + aWidths.push_back(fWidth * 65); + aWidths.push_back(fWidth * 20); + aWidths.push_back(fWidth * 8); + m_xPrefBox->set_column_fixed_widths(aWidths); +} + +IMPL_LINK(CuiAboutConfigTabPage, HeaderBarClick, int, nColumn, void) +{ + if (!m_bSorted) + { + m_xPrefBox->make_sorted(); + m_bSorted = true; + } + + bool bSortAtoZ = m_xPrefBox->get_sort_order(); + + //set new arrow positions in headerbar + if (nColumn == m_xPrefBox->get_sort_column()) + { + bSortAtoZ = !bSortAtoZ; + m_xPrefBox->set_sort_order(bSortAtoZ); + } + else + { + int nOldSortColumn = m_xPrefBox->get_sort_column(); + if (nOldSortColumn != -1) + m_xPrefBox->set_sort_indicator(TRISTATE_INDET, nOldSortColumn); + m_xPrefBox->set_sort_column(nColumn); + } + + if (nColumn != -1) + { + //sort lists + m_xPrefBox->set_sort_indicator(bSortAtoZ ? TRISTATE_TRUE : TRISTATE_FALSE, nColumn); + } +} + +CuiAboutConfigTabPage::~CuiAboutConfigTabPage() +{ +} + +void CuiAboutConfigTabPage::InsertEntry(const OUString& rPropertyPath, const OUString& rProp, const OUString& rStatus, + const OUString& rType, const OUString& rValue, const weld::TreeIter* pParentEntry, + bool bInsertToPrefBox) +{ + m_vectorUserData.push_back(std::make_unique(rPropertyPath)); + if (bInsertToPrefBox) + { + OUString sId(OUString::number(reinterpret_cast(m_vectorUserData.back().get()))); + m_xPrefBox->insert(pParentEntry, -1, &rProp, &sId, nullptr, nullptr, nullptr, false, m_xScratchIter.get()); + m_xPrefBox->set_text(*m_xScratchIter, rStatus, 1); + m_xPrefBox->set_text(*m_xScratchIter, rType, 2); + m_xPrefBox->set_text(*m_xScratchIter, rValue, 3); + } + else + { + m_prefBoxEntries.push_back({rProp, rStatus, rType, rValue, m_vectorUserData.back().get()}); + } +} + +void CuiAboutConfigTabPage::Reset() +{ + weld::WaitObject aWait(m_xDialog.get()); + + m_xPrefBox->clear(); + m_vectorOfModified.clear(); + if (m_bSorted) + { + m_xPrefBox->set_sort_indicator(TRISTATE_INDET, m_xPrefBox->get_sort_column()); + m_xPrefBox->make_unsorted(); + m_bSorted = false; + } + m_prefBoxEntries.clear(); + m_modifiedPrefBoxEntries.clear(); + + m_xPrefBox->freeze(); + Reference< XNameAccess > xConfigAccess = getConfigAccess( "/", false ); + //Load all XNameAccess to m_prefBoxEntries + FillItems( xConfigAccess, nullptr, 0, true ); + //Load xConfigAccess' children to m_prefBox + FillItems( xConfigAccess ); + m_xPrefBox->thaw(); +} + +void CuiAboutConfigTabPage::FillItemSet() +{ + std::vector< std::shared_ptr< Prop_Impl > >::iterator pIter; + for( pIter = m_vectorOfModified.begin() ; pIter != m_vectorOfModified.end(); ++pIter ) + { + Reference< XNameAccess > xUpdateAccess = getConfigAccess( (*pIter)->Name , true ); + Reference< XNameReplace > xNameReplace( xUpdateAccess, UNO_QUERY_THROW ); + + xNameReplace->replaceByName( (*pIter)->Property, (*pIter)->Value ); + + Reference< util::XChangesBatch > xChangesBatch( xUpdateAccess, UNO_QUERY_THROW ); + xChangesBatch->commitChanges(); + } +} + +void CuiAboutConfigTabPage::FillItems(const Reference< XNameAccess >& xNameAccess, const weld::TreeIter* pParentEntry, + int lineage, bool bLoadAll) +{ + OUString sPath = Reference< XHierarchicalName >( + xNameAccess, uno::UNO_QUERY_THROW )->getHierarchicalName(); + const uno::Sequence< OUString > seqItems = xNameAccess->getElementNames(); + for( const OUString& item : seqItems ) + { + Any aNode = xNameAccess->getByName( item ); + + bool bNotLeaf = false; + + Reference< XNameAccess > xNextNameAccess; + try + { + xNextNameAccess.set(aNode, uno::UNO_QUERY); + bNotLeaf = xNextNameAccess.is(); + } + catch (const RuntimeException&) + { + TOOLS_WARN_EXCEPTION( "cui.options", "CuiAboutConfigTabPage"); + } + + if (bNotLeaf) + { + if(bLoadAll) + FillItems(xNextNameAccess, nullptr, lineage + 1, true); + else + { + // not leaf node + m_vectorUserData.push_back(std::make_unique(xNextNameAccess, lineage + 1)); + OUString sId(OUString::number(reinterpret_cast(m_vectorUserData.back().get()))); + + m_xPrefBox->insert(pParentEntry, -1, &item, &sId, nullptr, nullptr, nullptr, true, m_xScratchIter.get()); + //It is needed, without this the selection line will be truncated. + m_xPrefBox->set_text(*m_xScratchIter, "", 1); + m_xPrefBox->set_text(*m_xScratchIter, "", 2); + m_xPrefBox->set_text(*m_xScratchIter, "", 3); + } + } + else + { + // leaf node + OUString sPropertyName = item; + auto it = std::find_if(m_modifiedPrefBoxEntries.begin(), m_modifiedPrefBoxEntries.end(), + [&sPath, &sPropertyName](const prefBoxEntry& rEntry) -> bool + { + return rEntry.pUserData->sPropertyPath == sPath + && rEntry.sStatus == sPropertyName; + } + ); + + OUString sType = aNode.getValueTypeName(); + OUStringBuffer sValue; + + if (it != m_modifiedPrefBoxEntries.end()) + sValue = it->sValue; + else + { + switch( aNode.getValueType().getTypeClass() ) + { + case css::uno::TypeClass_VOID: + break; + + case css::uno::TypeClass_BOOLEAN: + sValue = OUString::boolean( aNode.get() ); + break; + + case css::uno::TypeClass_SHORT: + case css::uno::TypeClass_LONG: + case css::uno::TypeClass_HYPER: + sValue = OUString::number( aNode.get() ); + break; + + case css::uno::TypeClass_DOUBLE: + sValue = OUString::number( aNode.get() ); + break; + + case css::uno::TypeClass_STRING: + sValue = aNode.get(); + break; + + case css::uno::TypeClass_SEQUENCE: + if( sType == "[]boolean" ) + { + uno::Sequence seq = aNode.get< uno::Sequence >(); + for( sal_Int32 j = 0; j != seq.getLength(); ++j ) + { + if( j != 0 ) + { + sValue.append(","); + } + sValue.append(OUString::boolean( seq[j] )); + } + } + else if( sType == "[]byte" ) + { + uno::Sequence seq = aNode.get< uno::Sequence >(); + for( sal_Int8 j : seq ) + { + OUString s = OUString::number( + static_cast(j), 16 ); + if( s.getLength() == 1 ) + { + sValue.append("0"); + } + sValue.append(s.toAsciiUpperCase()); + } + } + else if( sType == "[][]byte" ) + { + uno::Sequence< uno::Sequence > seq = aNode.get< uno::Sequence< uno::Sequence > >(); + for( sal_Int32 j = 0; j != seq.getLength(); ++j ) + { + if( j != 0 ) + { + sValue.append(","); + } + for( sal_Int8 k : seq[j] ) + { + OUString s = OUString::number( + static_cast(k), 16 ); + if( s.getLength() == 1 ) + { + sValue.append("0"); + } + sValue.append(s.toAsciiUpperCase()); + } + } + } + else if( sType == "[]short" ) + { + uno::Sequence seq = aNode.get< uno::Sequence >(); + for( sal_Int32 j = 0; j != seq.getLength(); ++j ) + { + if( j != 0 ) + { + sValue.append(","); + } + sValue.append(OUString::number( seq[j] )); + } + } + else if( sType == "[]long" ) + { + uno::Sequence seq = aNode.get< uno::Sequence >(); + for( sal_Int32 j = 0; j != seq.getLength(); ++j ) + { + if( j != 0 ) + { + sValue.append(","); + } + sValue.append(OUString::number( seq[j] )); + } + } + else if( sType == "[]hyper" ) + { + uno::Sequence seq = aNode.get< uno::Sequence >(); + for( sal_Int32 j = 0; j != seq.getLength(); ++j ) + { + if( j != 0 ) + { + sValue.append(","); + } + sValue.append(OUString::number( seq[j] )); + } + } + else if( sType == "[]double" ) + { + uno::Sequence seq = aNode.get< uno::Sequence >(); + for( sal_Int32 j = 0; j != seq.getLength(); ++j ) + { + if( j != 0 ) + { + sValue.append(","); + } + sValue.append(OUString::number( seq[j] )); + } + } + else if( sType == "[]string" ) + { + uno::Sequence seq = aNode.get< uno::Sequence >(); + for( sal_Int32 j = 0; j != seq.getLength(); ++j ) + { + if( j != 0 ) + { + sValue.append(","); + } + sValue.append(seq[j]); + } + } + else + { + SAL_WARN( + "cui.options", + "path \"" << sPath << "\" member " << item + << " of unsupported type " << sType); + } + break; + + default: + SAL_WARN( + "cui.options", + "path \"" << sPath << "\" member " << item + << " of unsupported type " << sType); + break; + } + } + + //Short name + int index = 0; + for(int j = 1; j < lineage; ++j) + index = sPath.indexOf("/", index + 1); + + InsertEntry(sPath, sPath.copy(index+1), item, sType, sValue.makeStringAndClear(), pParentEntry, !bLoadAll); + } + } +} + +Reference< XNameAccess > CuiAboutConfigTabPage::getConfigAccess( const OUString& sNodePath, bool bUpdate ) +{ + uno::Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() ); + + uno::Reference< lang::XMultiServiceFactory > xConfigProvider( + css::configuration::theDefaultProvider::get( xContext ) ); + + beans::NamedValue aProperty; + aProperty.Name = "nodepath"; + aProperty.Value <<= sNodePath; + + uno::Sequence< uno::Any > aArgumentList( 1 ); + aArgumentList[0] <<= aProperty; + + OUString sAccessString; + + if( bUpdate ) + sAccessString = "com.sun.star.configuration.ConfigurationUpdateAccess"; + else + sAccessString = "com.sun.star.configuration.ConfigurationAccess"; + + uno::Reference< container::XNameAccess > xNameAccess( + xConfigProvider->createInstanceWithArguments( + sAccessString, aArgumentList ), + uno::UNO_QUERY_THROW ); + + return xNameAccess; +} + +void CuiAboutConfigTabPage::AddToModifiedVector( const std::shared_ptr< Prop_Impl >& rProp ) +{ + bool isModifiedBefore = false; + //Check if value modified before + for(std::shared_ptr & nInd : m_vectorOfModified) + { + if( rProp->Name == nInd->Name && rProp->Property == nInd->Property ) + { + //property modified before. Assign reference to the modified value + //do your changes on this object. They will be saved later. + nInd = rProp; + isModifiedBefore = true; + break; + } + } + + if( !isModifiedBefore ) + m_vectorOfModified.push_back( rProp ); + //property is not modified before +} + +std::vector< OUString > CuiAboutConfigTabPage::commaStringToSequence( const OUString& rCommaSepString ) +{ + std::vector tempVector; + + sal_Int32 index = 0; + do + { + OUString word = rCommaSepString.getToken(0, u',', index); + word = word.trim(); + if( !word.isEmpty()) + tempVector.push_back(word); + }while( index >= 0 ); + return tempVector; +} + +CuiAboutConfigValueDialog::CuiAboutConfigValueDialog(weld::Window* pWindow, + const OUString& rValue, + int limit) + : GenericDialogController(pWindow, "cui/ui/aboutconfigvaluedialog.ui", "AboutConfigValueDialog") + , m_bNumericOnly(limit != 0) + , m_xEDValue(m_xBuilder->weld_entry("valuebox")) +{ + if (limit) + m_xEDValue->set_max_length(limit); + m_xEDValue->set_text(rValue); + m_xEDValue->connect_key_press(LINK(this, CuiAboutConfigValueDialog, KeyInputHdl)); +} + +CuiAboutConfigValueDialog::~CuiAboutConfigValueDialog() +{ +} + +IMPL_LINK_NOARG( CuiAboutConfigTabPage, ResetBtnHdl_Impl, weld::Button&, void ) +{ + Reset(); +} + +IMPL_LINK_NOARG(CuiAboutConfigTabPage, DoubleClickHdl_Impl, weld::TreeView&, bool) +{ + StandardHdl_Impl(*m_xEditBtn); + return true; +} + +IMPL_LINK_NOARG( CuiAboutConfigTabPage, StandardHdl_Impl, weld::Button&, void ) +{ + if (!m_xPrefBox->get_selected(m_xScratchIter.get())) + return; + + UserData *pUserData = reinterpret_cast(m_xPrefBox->get_id(*m_xScratchIter).toInt64()); + if (!(pUserData && pUserData->bIsPropertyPath)) + return; + + //if selection is a node + OUString sPropertyName = m_xPrefBox->get_text(*m_xScratchIter, 1); + OUString sPropertyType = m_xPrefBox->get_text(*m_xScratchIter, 2); + OUString sPropertyValue = m_xPrefBox->get_text(*m_xScratchIter, 3); + + auto pProperty = std::make_shared( pUserData->sPropertyPath, sPropertyName, Any( sPropertyValue ) ); + bool bSaveChanges = false; + + bool bOpenDialog = true; + OUString sDialogValue; + OUString sNewValue; + + if( sPropertyType == "boolean" ) + { + bool bValue; + if( sPropertyValue == "true" ) + { + sDialogValue = "false"; + bValue = false; + } + else + { + sDialogValue = "true"; + bValue = true; + } + + pProperty->Value <<= bValue; + bOpenDialog = false; + bSaveChanges = true; + } + else if ( sPropertyType == "void" ) + { + bOpenDialog = false; + } + else + { + sDialogValue = sPropertyValue; + bOpenDialog = true; + } + + try + { + if( bOpenDialog ) + { + //Cosmetic length limit for integer values. + int limit=0; + if( sPropertyType == "short" ) + limit = SHORT_LEN_LIMIT; + else if( sPropertyType == "long" ) + limit = LONG_LEN_LIMIT; + else if( sPropertyType == "hyper" ) + limit = HYPER_LEN_LIMIT; + + CuiAboutConfigValueDialog aValueDialog(m_xDialog.get(), sDialogValue, limit); + + if (aValueDialog.run() == RET_OK ) + { + sNewValue = aValueDialog.getValue(); + bSaveChanges = true; + if ( sPropertyType == "short") + { + sal_Int16 nShort; + sal_Int32 nNumb = sNewValue.toInt32(); + + //if the value is 0 and length is not 1, there is something wrong + if( ( nNumb==0 && sNewValue.getLength()!=1 ) || nNumb > SAL_MAX_INT16 || nNumb < SAL_MIN_INT16) + throw uno::Exception("out of range short", nullptr); + nShort = static_cast(nNumb); + pProperty->Value <<= nShort; + } + else if( sPropertyType == "long" ) + { + sal_Int32 nLong = sNewValue.toInt32(); + if( nLong==0 && sNewValue.getLength()!=1) + throw uno::Exception("out of range long", nullptr); + pProperty->Value <<= nLong; + } + else if( sPropertyType == "hyper") + { + sal_Int64 nHyper = sNewValue.toInt64(); + if( nHyper==0 && sNewValue.getLength()!=1) + throw uno::Exception("out of range hyper", nullptr); + pProperty->Value <<= nHyper; + } + else if( sPropertyType == "double") + { + double nDoub = sNewValue.toDouble(); + if( nDoub ==0 && sNewValue.getLength()!=1) + throw uno::Exception("out of range double", nullptr); + pProperty->Value <<= nDoub; + } + else if( sPropertyType == "float") + { + float nFloat = sNewValue.toFloat(); + if( nFloat ==0 && sNewValue.getLength()!=1) + throw uno::Exception("out of range float", nullptr); + pProperty->Value <<= nFloat; + } + else if( sPropertyType == "string" ) + { + pProperty->Value <<= sNewValue; + } + else if( sPropertyType == "[]short" ) + { + //create string sequence from comma separated string + //uno::Sequence< OUString > seqStr; + std::vector< OUString > seqStr = commaStringToSequence( sNewValue ); + + //create appropriate sequence with same size as string sequence + uno::Sequence< sal_Int16 > seqShort( seqStr.size() ); + //convert all strings to appropriate type + for( size_t i = 0; i < seqStr.size(); ++i ) + { + seqShort[i] = static_cast(seqStr[i].toInt32()); + } + pProperty->Value <<= seqShort; + } + else if( sPropertyType == "[]long" ) + { + std::vector< OUString > seqStrLong = commaStringToSequence( sNewValue ); + + uno::Sequence< sal_Int32 > seqLong( seqStrLong.size() ); + for( size_t i = 0; i < seqStrLong.size(); ++i ) + { + seqLong[i] = seqStrLong[i].toInt32(); + } + pProperty->Value <<= seqLong; + } + else if( sPropertyType == "[]hyper" ) + { + std::vector< OUString > seqStrHyper = commaStringToSequence( sNewValue ); + uno::Sequence< sal_Int64 > seqHyper( seqStrHyper.size() ); + for( size_t i = 0; i < seqStrHyper.size(); ++i ) + { + seqHyper[i] = seqStrHyper[i].toInt64(); + } + pProperty->Value <<= seqHyper; + } + else if( sPropertyType == "[]double" ) + { + std::vector< OUString > seqStrDoub = commaStringToSequence( sNewValue ); + uno::Sequence< double > seqDoub( seqStrDoub.size() ); + for( size_t i = 0; i < seqStrDoub.size(); ++i ) + { + seqDoub[i] = seqStrDoub[i].toDouble(); + } + pProperty->Value <<= seqDoub; + } + else if( sPropertyType == "[]float" ) + { + std::vector< OUString > seqStrFloat = commaStringToSequence( sNewValue ); + uno::Sequence< sal_Int16 > seqFloat( seqStrFloat.size() ); + for( size_t i = 0; i < seqStrFloat.size(); ++i ) + { + seqFloat[i] = seqStrFloat[i].toFloat(); + } + pProperty->Value <<= seqFloat; + } + else if( sPropertyType == "[]string" ) + { + pProperty->Value <<= comphelper::containerToSequence( commaStringToSequence( sNewValue )); + } + else //unknown + throw uno::Exception("unknown property type " + sPropertyType, nullptr); + + sDialogValue = sNewValue; + } + } + + if(bSaveChanges) + { + AddToModifiedVector( pProperty ); + + //update listbox value. + m_xPrefBox->set_text(*m_xScratchIter, sDialogValue, 3); + //update m_prefBoxEntries + auto it = std::find_if(m_prefBoxEntries.begin(), m_prefBoxEntries.end(), + [&pUserData, &sPropertyName](const prefBoxEntry& rEntry) -> bool + { + return rEntry.pUserData->sPropertyPath == pUserData->sPropertyPath + && rEntry.sStatus == sPropertyName; + } + ); + if (it != m_prefBoxEntries.end()) + { + it->sValue = sDialogValue; + + auto modifiedIt = std::find_if( + m_modifiedPrefBoxEntries.begin(), m_modifiedPrefBoxEntries.end(), + [&pUserData, &sPropertyName](const prefBoxEntry& rEntry) -> bool + { + return rEntry.pUserData->sPropertyPath == pUserData->sPropertyPath + && rEntry.sStatus == sPropertyName; + } + ); + + if (modifiedIt != m_modifiedPrefBoxEntries.end()) + { + modifiedIt->sValue = sDialogValue; + } + else + { + m_modifiedPrefBoxEntries.push_back(*it); + } + } + } + } + catch( uno::Exception& ) + { + } +} + +IMPL_LINK_NOARG( CuiAboutConfigTabPage, SearchHdl_Impl, weld::Button&, void) +{ + weld::WaitObject aWait(m_xDialog.get()); + + m_xPrefBox->hide(); + m_xPrefBox->clear(); + m_xPrefBox->freeze(); + + if (m_bSorted) + m_xPrefBox->make_unsorted(); + + if (m_xSearchEdit->get_text().isEmpty()) + { + m_xPrefBox->clear(); + Reference< XNameAccess > xConfigAccess = getConfigAccess( "/", false ); + FillItems( xConfigAccess ); + } + else + { + m_options.searchString = m_xSearchEdit->get_text(); + utl::TextSearch textSearch( m_options ); + for (auto const& it : m_prefBoxEntries) + { + sal_Int32 endPos, startPos = 0; + + for(size_t i = 0; i < 5; ++i) + { + OUString scrTxt; + + if (i == 0) + scrTxt = it.pUserData->sPropertyPath; + else if (i == 1) + scrTxt = it.sProp; + else if (i == 2) + scrTxt = it.sStatus; + else if (i == 3) + scrTxt = it.sType; + else if (i == 4) + scrTxt = it.sValue; + + endPos = scrTxt.getLength(); + if (textSearch.SearchForward(scrTxt, &startPos, &endPos)) + { + InsertEntry(it); + break; + } + } + } + } + + m_xPrefBox->thaw(); + if (m_bSorted) + m_xPrefBox->make_sorted(); + + m_xPrefBox->all_foreach([this](weld::TreeIter& rEntry) { + m_xPrefBox->expand_row(rEntry); + return false; + }); + m_xPrefBox->show(); +} + +void CuiAboutConfigTabPage::InsertEntry(const prefBoxEntry& rEntry) +{ + OUString sPathWithProperty = rEntry.pUserData->sPropertyPath; + sal_Int32 index = sPathWithProperty.lastIndexOf(rEntry.sProp); + OUString sPath = sPathWithProperty.copy(0, index); + index = 0; + std::unique_ptr xParentEntry(m_xPrefBox->make_iterator()); + std::unique_ptr xGrandParentEntry; + + do + { + int prevIndex = index; + index = sPath.indexOf("/", index+1); + // deal with no parent case (tdf#107811) + if (index < 0) + { + OUString sId(OUString::number(reinterpret_cast(rEntry.pUserData))); + m_xPrefBox->insert(nullptr, -1, &rEntry.sProp, &sId, nullptr, nullptr, nullptr, false, m_xScratchIter.get()); + m_xPrefBox->set_text(*m_xScratchIter, rEntry.sStatus, 1); + m_xPrefBox->set_text(*m_xScratchIter, rEntry.sType, 2); + m_xPrefBox->set_text(*m_xScratchIter, rEntry.sValue, 3); + return; + } + OUString sParentName = sPath.copy(prevIndex+1, index - prevIndex - 1); + + bool hasEntry = false; + bool bStartOk; + + if (!xGrandParentEntry) + bStartOk = m_xPrefBox->get_iter_first(*xParentEntry); + else + { + m_xPrefBox->copy_iterator(*xGrandParentEntry, *xParentEntry); + bStartOk = m_xPrefBox->iter_children(*xParentEntry); + } + + if (bStartOk) + { + do + { + if (m_xPrefBox->get_text(*xParentEntry, 0) == sParentName) + { + hasEntry = true; + break; + } + } while (m_xPrefBox->iter_next_sibling(*xParentEntry)); + } + + if (!hasEntry) + { + m_xPrefBox->insert(xGrandParentEntry.get(), -1, &sParentName, nullptr, nullptr, nullptr, nullptr, false, xParentEntry.get()); + //It is needed, without this the selection line will be truncated. + m_xPrefBox->set_text(*xParentEntry, "", 1); + m_xPrefBox->set_text(*xParentEntry, "", 2); + m_xPrefBox->set_text(*xParentEntry, "", 3); + } + + xGrandParentEntry = m_xPrefBox->make_iterator(xParentEntry.get()); + } while(index < sPath.getLength() - 1); + + OUString sId(OUString::number(reinterpret_cast(rEntry.pUserData))); + m_xPrefBox->insert(xParentEntry.get(), -1, &rEntry.sProp, &sId, nullptr, nullptr, nullptr, false, m_xScratchIter.get()); + m_xPrefBox->set_text(*m_xScratchIter, rEntry.sStatus, 1); + m_xPrefBox->set_text(*m_xScratchIter, rEntry.sType, 2); + m_xPrefBox->set_text(*m_xScratchIter, rEntry.sValue, 3); +} + +IMPL_LINK(CuiAboutConfigTabPage, ExpandingHdl_Impl, const weld::TreeIter&, rEntry, bool) +{ + if (m_xPrefBox->iter_has_child(rEntry)) + return true; + UserData *pUserData = reinterpret_cast(m_xPrefBox->get_id(rEntry).toInt64()); + if (pUserData && !pUserData->bIsPropertyPath) + { + assert(pUserData->aXNameAccess.is()); + FillItems(pUserData->aXNameAccess, &rEntry, pUserData->aLineage); + } + return true; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/optaboutconfig.hxx b/cui/source/options/optaboutconfig.hxx new file mode 100644 index 000000000..69a207da6 --- /dev/null +++ b/cui/source/options/optaboutconfig.hxx @@ -0,0 +1,95 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +#include +#include + +#include + +class CuiAboutConfigTabPage; +class CuiAboutConfigValueDialog; +struct Prop_Impl; +struct UserData; + +struct prefBoxEntry +{ + OUString sProp; + OUString sStatus; + OUString sType; + OUString sValue; + UserData* pUserData; +}; + +class CuiAboutConfigTabPage : public weld::GenericDialogController +{ +private: + std::unique_ptr m_xResetBtn; + std::unique_ptr m_xEditBtn; + std::unique_ptr m_xSearchBtn; + std::unique_ptr m_xSearchEdit; + std::unique_ptr m_xPrefBox; + std::unique_ptr m_xScratchIter; + + std::vector < std::unique_ptr > m_vectorUserData; + + std::vector m_modifiedPrefBoxEntries; + std::vector< std::shared_ptr< Prop_Impl > > m_vectorOfModified; + + //for search + i18nutil::SearchOptions2 m_options; + std::vector m_prefBoxEntries; + + bool m_bSorted; + + void AddToModifiedVector( const std::shared_ptr< Prop_Impl >& rProp ); + static std::vector< OUString > commaStringToSequence( const OUString& rCommaSepString ); + void InsertEntry(const prefBoxEntry& rEntry); + + DECL_LINK(StandardHdl_Impl, weld::Button&, void); + DECL_LINK(DoubleClickHdl_Impl, weld::TreeView&, bool); + DECL_LINK(ResetBtnHdl_Impl, weld::Button&, void); + DECL_LINK(SearchHdl_Impl, weld::Button&, void); + DECL_LINK(ExpandingHdl_Impl, const weld::TreeIter&, bool); + DECL_LINK(HeaderBarClick, int, void); + +public: + explicit CuiAboutConfigTabPage(weld::Window* pParent); + virtual ~CuiAboutConfigTabPage() override; + void InsertEntry(const OUString &rPropertyPath, const OUString& rProp, const OUString& rStatus, const OUString& rType, const OUString& rValue, + const weld::TreeIter* pParentEntry, bool bInsertToPrefBox); + void Reset(); + void FillItems(const css::uno::Reference& xNameAccess, + const weld::TreeIter* pParentEntry = nullptr, int lineage = 0, bool bLoadAll = false); + static css::uno::Reference< css::container::XNameAccess > getConfigAccess( const OUString& sNodePath, bool bUpdate ); + void FillItemSet(); +}; + +class CuiAboutConfigValueDialog : public weld::GenericDialogController +{ +private: + bool m_bNumericOnly; + std::unique_ptr m_xEDValue; + + DECL_LINK(KeyInputHdl, const KeyEvent&, bool); + +public: + CuiAboutConfigValueDialog(weld::Window* pWindow, const OUString& rValue , int limit); + virtual ~CuiAboutConfigValueDialog() override; + + OUString getValue() const + { + return m_xEDValue->get_text(); + } +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/optaccessibility.cxx b/cui/source/options/optaccessibility.cxx new file mode 100644 index 000000000..a394ff955 --- /dev/null +++ b/cui/source/options/optaccessibility.cxx @@ -0,0 +1,111 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "optaccessibility.hxx" +#include +#include +#include + +SvxAccessibilityOptionsTabPage::SvxAccessibilityOptionsTabPage(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/optaccessibilitypage.ui", "OptAccessibilityPage", &rSet) + , m_xAccessibilityTool(m_xBuilder->weld_check_button("acctool")) + , m_xTextSelectionInReadonly(m_xBuilder->weld_check_button("textselinreadonly")) + , m_xAnimatedGraphics(m_xBuilder->weld_check_button("animatedgraphics")) + , m_xAnimatedTexts(m_xBuilder->weld_check_button("animatedtext")) + , m_xAutoDetectHC(m_xBuilder->weld_check_button("autodetecthc")) + , m_xAutomaticFontColor(m_xBuilder->weld_check_button("autofontcolor")) + , m_xPagePreviews(m_xBuilder->weld_check_button("systempagepreviewcolor")) +{ +#ifdef UNX + // UNIX: read the gconf2 setting instead to use the checkbox + m_xAccessibilityTool->hide(); +#endif +} + +SvxAccessibilityOptionsTabPage::~SvxAccessibilityOptionsTabPage() +{ +} + +std::unique_ptr SvxAccessibilityOptionsTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet) +{ + return std::make_unique(pPage, pController, *rAttrSet); +} + +bool SvxAccessibilityOptionsTabPage::FillItemSet( SfxItemSet* ) +{ + std::shared_ptr batch( comphelper::ConfigurationChanges::create() ); + if ( !officecfg::Office::Common::Accessibility::IsForPagePreviews::isReadOnly() ) + officecfg::Office::Common::Accessibility::IsForPagePreviews::set(m_xPagePreviews->get_active(), batch); + if ( !officecfg::Office::Common::Accessibility::IsAllowAnimatedGraphics::isReadOnly() ) + officecfg::Office::Common::Accessibility::IsAllowAnimatedGraphics::set(m_xAnimatedGraphics->get_active(), batch); + if ( !officecfg::Office::Common::Accessibility::IsAllowAnimatedText::isReadOnly() ) + officecfg::Office::Common::Accessibility::IsAllowAnimatedText::set(m_xAnimatedTexts->get_active(), batch); + if ( !officecfg::Office::Common::Accessibility::IsAutomaticFontColor::isReadOnly() ) + officecfg::Office::Common::Accessibility::IsAutomaticFontColor::set(m_xAutomaticFontColor->get_active(), batch); + if ( !officecfg::Office::Common::Accessibility::IsSelectionInReadonly::isReadOnly() ) + officecfg::Office::Common::Accessibility::IsSelectionInReadonly::set(m_xTextSelectionInReadonly->get_active(), batch); + if ( !officecfg::Office::Common::Accessibility::AutoDetectSystemHC::isReadOnly() ) + officecfg::Office::Common::Accessibility::AutoDetectSystemHC::set(m_xAutoDetectHC->get_active(), batch); + batch->commit(); + + AllSettings aAllSettings = Application::GetSettings(); + MiscSettings aMiscSettings = aAllSettings.GetMiscSettings(); +#ifndef UNX + aMiscSettings.SetEnableATToolSupport(m_xAccessibilityTool->get_active()); +#endif + aAllSettings.SetMiscSettings(aMiscSettings); + Application::MergeSystemSettings( aAllSettings ); + Application::SetSettings(aAllSettings); + + return false; +} + +void SvxAccessibilityOptionsTabPage::Reset( const SfxItemSet* ) +{ + m_xPagePreviews->set_active( officecfg::Office::Common::Accessibility::IsForPagePreviews::get() ); + if( officecfg::Office::Common::Accessibility::IsForPagePreviews::isReadOnly() ) + m_xPagePreviews->set_sensitive(false); + + m_xAnimatedGraphics->set_active( officecfg::Office::Common::Accessibility::IsAllowAnimatedGraphics::get() ); + if( officecfg::Office::Common::Accessibility::IsAllowAnimatedGraphics::isReadOnly() ) + m_xAnimatedGraphics->set_sensitive(false); + + m_xAnimatedTexts->set_active( officecfg::Office::Common::Accessibility::IsAllowAnimatedText::get() ); + if( officecfg::Office::Common::Accessibility::IsAllowAnimatedText::isReadOnly() ) + m_xAnimatedTexts->set_sensitive(false); + + m_xAutomaticFontColor->set_active( officecfg::Office::Common::Accessibility::IsAutomaticFontColor::get() ); + if( officecfg::Office::Common::Accessibility::IsAutomaticFontColor::isReadOnly() ) + m_xAutomaticFontColor->set_sensitive(false); + + m_xTextSelectionInReadonly->set_active( officecfg::Office::Common::Accessibility::IsSelectionInReadonly::get() ); + if( officecfg::Office::Common::Accessibility::IsSelectionInReadonly::isReadOnly() ) + m_xTextSelectionInReadonly->set_sensitive(false); + + m_xAutoDetectHC->set_active( officecfg::Office::Common::Accessibility::AutoDetectSystemHC::get() ); + if( officecfg::Office::Common::Accessibility::AutoDetectSystemHC::isReadOnly() ) + m_xAutoDetectHC->set_sensitive(false); + + AllSettings aAllSettings = Application::GetSettings(); + const MiscSettings& aMiscSettings = aAllSettings.GetMiscSettings(); + m_xAccessibilityTool->set_active(aMiscSettings.GetEnableATToolSupport()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/optaccessibility.hxx b/cui/source/options/optaccessibility.hxx new file mode 100644 index 000000000..35d5fdefd --- /dev/null +++ b/cui/source/options/optaccessibility.hxx @@ -0,0 +1,42 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include + +class SvxAccessibilityOptionsTabPage : public SfxTabPage +{ + std::unique_ptr m_xAccessibilityTool; + std::unique_ptr m_xTextSelectionInReadonly; + std::unique_ptr m_xAnimatedGraphics; + std::unique_ptr m_xAnimatedTexts; + std::unique_ptr m_xAutoDetectHC; + std::unique_ptr m_xAutomaticFontColor; + std::unique_ptr m_xPagePreviews; + +public: + SvxAccessibilityOptionsTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + virtual ~SvxAccessibilityOptionsTabPage() override; + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet ); + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/optasian.cxx b/cui/source/options/optasian.cxx new file mode 100644 index 000000000..6907eca46 --- /dev/null +++ b/cui/source/options/optasian.cxx @@ -0,0 +1,384 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::i18n; +using namespace com::sun::star::frame; +using namespace com::sun::star::beans; + +const char cIsKernAsianPunctuation[] = "IsKernAsianPunctuation"; +const char cCharacterCompressionType[] = "CharacterCompressionType"; + +namespace { + +struct SvxForbiddenChars_Impl +{ + bool bRemoved; + std::unique_ptr pCharacters; +}; + +} + +struct SvxAsianLayoutPage_Impl +{ + SvxAsianConfig aConfig; + SvxAsianLayoutPage_Impl() {} + + Reference< XForbiddenCharacters > xForbidden; + Reference< XPropertySet > xPrSet; + Reference< XPropertySetInfo > xPrSetInfo; + std::map< LanguageType, std::unique_ptr > + aChangedLanguagesMap; + + bool hasForbiddenCharacters(LanguageType eLang); + SvxForbiddenChars_Impl* getForbiddenCharacters(LanguageType eLang); + void addForbiddenCharacters(LanguageType eLang, std::unique_ptr pForbidden); +}; + +bool SvxAsianLayoutPage_Impl::hasForbiddenCharacters(LanguageType eLang) +{ + return aChangedLanguagesMap.count( eLang ); +} + +SvxForbiddenChars_Impl* SvxAsianLayoutPage_Impl::getForbiddenCharacters(LanguageType eLang) +{ + auto it = aChangedLanguagesMap.find( eLang ); + DBG_ASSERT( ( it != aChangedLanguagesMap.end() ), "language not available"); + if( it != aChangedLanguagesMap.end() ) + return it->second.get(); + return nullptr; +} + +void SvxAsianLayoutPage_Impl::addForbiddenCharacters( + LanguageType eLang, std::unique_ptr pForbidden) +{ + auto itOld = aChangedLanguagesMap.find( eLang ); + if( itOld == aChangedLanguagesMap.end() ) + { + std::unique_ptr pChar(new SvxForbiddenChars_Impl); + pChar->bRemoved = nullptr == pForbidden; + pChar->pCharacters = std::move(pForbidden); + aChangedLanguagesMap.emplace( eLang, std::move(pChar) ); + } + else + { + itOld->second->bRemoved = nullptr == pForbidden; + itOld->second->pCharacters = std::move(pForbidden); + } +} + +static LanguageType eLastUsedLanguageTypeForForbiddenCharacters(USHRT_MAX); + +SvxAsianLayoutPage::SvxAsianLayoutPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/optasianpage.ui", "OptAsianPage", &rSet) + , pImpl(new SvxAsianLayoutPage_Impl) + , m_xCharKerningRB(m_xBuilder->weld_radio_button("charkerning")) + , m_xCharPunctKerningRB(m_xBuilder->weld_radio_button("charpunctkerning")) + , m_xNoCompressionRB(m_xBuilder->weld_radio_button("nocompression")) + , m_xPunctCompressionRB(m_xBuilder->weld_radio_button("punctcompression")) + , m_xPunctKanaCompressionRB(m_xBuilder->weld_radio_button("punctkanacompression")) + , m_xLanguageFT(m_xBuilder->weld_label("languageft")) + , m_xLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box("language"))) + , m_xStandardCB(m_xBuilder->weld_check_button("standard")) + , m_xStartFT(m_xBuilder->weld_label("startft")) + , m_xStartED(m_xBuilder->weld_entry("start")) + , m_xEndFT(m_xBuilder->weld_label("endft")) + , m_xEndED(m_xBuilder->weld_entry("end")) + , m_xHintFT(m_xBuilder->weld_label("hintft")) +{ + LanguageHdl(*m_xLanguageLB->get_widget()); + m_xLanguageLB->connect_changed(LINK(this, SvxAsianLayoutPage, LanguageHdl)); + m_xStandardCB->connect_toggled(LINK(this, SvxAsianLayoutPage, ChangeStandardHdl)); + Link aLk(LINK(this, SvxAsianLayoutPage, ModifyHdl)); + m_xStartED->connect_changed(aLk); + m_xEndED->connect_changed(aLk); + + m_xLanguageLB->SetLanguageList( SvxLanguageListFlags::FBD_CHARS, false, false ); +} + +SvxAsianLayoutPage::~SvxAsianLayoutPage() +{ +} + +std::unique_ptr SvxAsianLayoutPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet) +{ + return std::make_unique(pPage, pController, *rAttrSet); +} + +bool SvxAsianLayoutPage::FillItemSet( SfxItemSet* ) +{ + if(m_xCharKerningRB->get_state_changed_from_saved()) + { + pImpl->aConfig.SetKerningWesternTextOnly(m_xCharKerningRB->get_active()); + OUString sPunct(cIsKernAsianPunctuation); + if(pImpl->xPrSetInfo.is() && pImpl->xPrSetInfo->hasPropertyByName(sPunct)) + { + bool bVal = !m_xCharKerningRB->get_active(); + pImpl->xPrSet->setPropertyValue(sPunct, Any(bVal)); + } + } + + if(m_xNoCompressionRB->get_state_changed_from_saved() || + m_xPunctCompressionRB->get_state_changed_from_saved()) + { + CharCompressType nSet = m_xNoCompressionRB->get_active() ? CharCompressType::NONE : + m_xPunctCompressionRB->get_active() ? CharCompressType::PunctuationOnly : + CharCompressType::PunctuationAndKana; + pImpl->aConfig.SetCharDistanceCompression(nSet); + OUString sCompress(cCharacterCompressionType); + if(pImpl->xPrSetInfo.is() && pImpl->xPrSetInfo->hasPropertyByName(sCompress)) + { + pImpl->xPrSet->setPropertyValue(sCompress, Any(static_cast(nSet))); + } + } + pImpl->aConfig.Commit(); + if(pImpl->xForbidden.is()) + { + try + { + for (auto const& changedLanguage : pImpl->aChangedLanguagesMap) + { + Locale aLocale( LanguageTag::convertToLocale(changedLanguage.first)); + if(changedLanguage.second->bRemoved) + pImpl->xForbidden->removeForbiddenCharacters( aLocale ); + else if(changedLanguage.second->pCharacters) + pImpl->xForbidden->setForbiddenCharacters( aLocale, *( changedLanguage.second->pCharacters ) ); + } + } + catch (const Exception&) + { + OSL_FAIL("exception in XForbiddenCharacters"); + } + } + eLastUsedLanguageTypeForForbiddenCharacters = m_xLanguageLB->get_active_id(); + + return false; +} + +void SvxAsianLayoutPage::Reset( const SfxItemSet* ) +{ + SfxViewFrame* pCurFrm = SfxViewFrame::Current(); + SfxObjectShell* pDocSh = pCurFrm ? pCurFrm->GetObjectShell() : nullptr; + Reference< XModel > xModel; + if(pDocSh) + xModel = pDocSh->GetModel(); + Reference xFact(xModel, UNO_QUERY); + if(xFact.is()) + { + pImpl->xPrSet.set(xFact->createInstance("com.sun.star.document.Settings"), UNO_QUERY); + } + if( pImpl->xPrSet.is() ) + pImpl->xPrSetInfo = pImpl->xPrSet->getPropertySetInfo(); + OUString sForbidden("ForbiddenCharacters"); + bool bKernWesternText = pImpl->aConfig.IsKerningWesternTextOnly(); + CharCompressType nCompress = pImpl->aConfig.GetCharDistanceCompression(); + if(pImpl->xPrSetInfo.is()) + { + if(pImpl->xPrSetInfo->hasPropertyByName(sForbidden)) + { + Any aForbidden = pImpl->xPrSet->getPropertyValue(sForbidden); + aForbidden >>= pImpl->xForbidden; + } + OUString sCompress(cCharacterCompressionType); + if(pImpl->xPrSetInfo->hasPropertyByName(sCompress)) + { + Any aVal = pImpl->xPrSet->getPropertyValue(sCompress); + sal_uInt16 nTmp; + if (aVal >>= nTmp) + nCompress = static_cast(nTmp); + } + OUString sPunct(cIsKernAsianPunctuation); + if(pImpl->xPrSetInfo->hasPropertyByName(sPunct)) + { + Any aVal = pImpl->xPrSet->getPropertyValue(sPunct); + bKernWesternText = !*o3tl::doAccess(aVal); + } + } + else + { + m_xLanguageFT->set_sensitive(false); + m_xLanguageLB->set_sensitive(false); + m_xStandardCB->set_sensitive(false); + m_xStartFT->set_sensitive(false); + m_xStartED->set_sensitive(false); + m_xEndFT->set_sensitive(false); + m_xEndED->set_sensitive(false); + m_xHintFT->set_sensitive(false); + } + if(bKernWesternText) + m_xCharKerningRB->set_active(true); + else + m_xCharPunctKerningRB->set_active(true); + switch(nCompress) + { + case CharCompressType::NONE : m_xNoCompressionRB->set_active(true); break; + case CharCompressType::PunctuationOnly : m_xPunctCompressionRB->set_active(true); break; + default: m_xPunctKanaCompressionRB->set_active(true); + } + m_xCharKerningRB->save_state(); + m_xNoCompressionRB->save_state(); + m_xPunctCompressionRB->save_state(); + m_xPunctKanaCompressionRB->save_state(); + + m_xLanguageLB->set_active(0); + //preselect the system language in the box - if available + if(LanguageType(USHRT_MAX) == eLastUsedLanguageTypeForForbiddenCharacters) + { + eLastUsedLanguageTypeForForbiddenCharacters = + Application::GetSettings().GetLanguageTag().getLanguageType(); + if (MsLangId::isSimplifiedChinese(eLastUsedLanguageTypeForForbiddenCharacters)) + eLastUsedLanguageTypeForForbiddenCharacters = LANGUAGE_CHINESE_SIMPLIFIED; + else if (MsLangId::isTraditionalChinese(eLastUsedLanguageTypeForForbiddenCharacters)) + eLastUsedLanguageTypeForForbiddenCharacters = LANGUAGE_CHINESE_TRADITIONAL; + } + m_xLanguageLB->set_active_id(eLastUsedLanguageTypeForForbiddenCharacters); + LanguageHdl(*m_xLanguageLB->get_widget()); +} + +IMPL_LINK_NOARG(SvxAsianLayoutPage, LanguageHdl, weld::ComboBox&, void) +{ + //set current value + LanguageType eSelectLanguage = m_xLanguageLB->get_active_id(); + LanguageTag aLanguageTag( eSelectLanguage); + const Locale& aLocale( aLanguageTag.getLocale()); + + OUString sStart, sEnd; + bool bAvail; + if(pImpl->xForbidden.is()) + { + bAvail = pImpl->hasForbiddenCharacters(eSelectLanguage); + if(bAvail) + { + SvxForbiddenChars_Impl* pElement = pImpl->getForbiddenCharacters(eSelectLanguage); + if(pElement->bRemoved || !pElement->pCharacters) + { + bAvail = false; + } + else + { + sStart = pElement->pCharacters->beginLine; + sEnd = pElement->pCharacters->endLine; + } + } + else + { + try + { + bAvail = pImpl->xForbidden->hasForbiddenCharacters(aLocale); + if(bAvail) + { + ForbiddenCharacters aForbidden = pImpl->xForbidden->getForbiddenCharacters( aLocale ); + sStart = aForbidden.beginLine; + sEnd = aForbidden.endLine; + } + } + catch (const Exception&) + { + OSL_FAIL("exception in XForbiddenCharacters"); + } + } + } + else + { + bAvail = pImpl->aConfig.GetStartEndChars( aLocale, sStart, sEnd ); + } + if(!bAvail) + { + LocaleDataWrapper aWrap( aLanguageTag ); + ForbiddenCharacters aForbidden = aWrap.getForbiddenCharacters(); + sStart = aForbidden.beginLine; + sEnd = aForbidden.endLine; + } + m_xStandardCB->set_active(!bAvail); + m_xStartED->set_sensitive(bAvail); + m_xEndED->set_sensitive(bAvail); + m_xStartFT->set_sensitive(bAvail); + m_xEndFT->set_sensitive(bAvail); + m_xStartED->set_text(sStart); + m_xEndED->set_text(sEnd); +} + +IMPL_LINK(SvxAsianLayoutPage, ChangeStandardHdl, weld::ToggleButton&, rBox, void) +{ + bool bCheck = rBox.get_active(); + m_xStartED->set_sensitive(!bCheck); + m_xEndED->set_sensitive(!bCheck); + m_xStartFT->set_sensitive(!bCheck); + m_xEndFT->set_sensitive(!bCheck); + + ModifyHdl(*m_xStartED); +} + +IMPL_LINK(SvxAsianLayoutPage, ModifyHdl, weld::Entry&, rEdit, void) +{ + LanguageType eSelectLanguage = m_xLanguageLB->get_active_id(); + Locale aLocale( LanguageTag::convertToLocale( eSelectLanguage )); + OUString sStart = m_xStartED->get_text(); + OUString sEnd = m_xEndED->get_text(); + bool bEnable = rEdit.get_sensitive(); + if(pImpl->xForbidden.is()) + { + try + { + if(bEnable) + { + std::unique_ptr pFCSet(new ForbiddenCharacters); + pFCSet->beginLine = sStart; + pFCSet->endLine = sEnd; + pImpl->addForbiddenCharacters(eSelectLanguage, std::move(pFCSet)); + } + else + pImpl->addForbiddenCharacters(eSelectLanguage, nullptr); + } + catch (const Exception&) + { + OSL_FAIL("exception in XForbiddenCharacters"); + } + } + pImpl->aConfig.SetStartEndChars( aLocale, bEnable ? &sStart : nullptr, bEnable ? &sEnd : nullptr); +} + +const sal_uInt16* SvxAsianLayoutPage::GetRanges() +{ + //no items are used + static const sal_uInt16 pAsianLayoutRanges[] = { 0 }; + return pAsianLayoutRanges; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/optbasic.cxx b/cui/source/options/optbasic.cxx new file mode 100644 index 000000000..c550d9440 --- /dev/null +++ b/cui/source/options/optbasic.cxx @@ -0,0 +1,131 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "optbasic.hxx" +#include +#include + +SvxBasicIDEOptionsPage::SvxBasicIDEOptionsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/optbasicidepage.ui", "OptBasicIDEPage", &rSet) + , m_xCodeCompleteChk(m_xBuilder->weld_check_button("codecomplete_enable")) + , m_xAutocloseProcChk(m_xBuilder->weld_check_button("autoclose_proc")) + , m_xAutocloseParenChk(m_xBuilder->weld_check_button("autoclose_paren")) + , m_xAutocloseQuotesChk(m_xBuilder->weld_check_button("autoclose_quotes")) + , m_xAutoCorrectChk(m_xBuilder->weld_check_button("autocorrect")) + , m_xUseExtendedTypesChk(m_xBuilder->weld_check_button("extendedtypes_enable")) +{ + LoadConfig(); +} + +SvxBasicIDEOptionsPage::~SvxBasicIDEOptionsPage() +{ +} + +void SvxBasicIDEOptionsPage::LoadConfig() +{ + m_xCodeCompleteChk->set_active( officecfg::Office::BasicIDE::Autocomplete::CodeComplete::get() ); + m_xCodeCompleteChk->set_sensitive( !officecfg::Office::BasicIDE::Autocomplete::CodeComplete::isReadOnly() ); + m_xAutocloseProcChk->set_active( officecfg::Office::BasicIDE::Autocomplete::AutocloseProc::get() ); + m_xAutocloseProcChk->set_sensitive( !officecfg::Office::BasicIDE::Autocomplete::AutocloseProc::isReadOnly() ); + m_xAutocloseQuotesChk->set_active( officecfg::Office::BasicIDE::Autocomplete::AutocloseDoubleQuotes::get() ); + m_xAutocloseQuotesChk->set_sensitive( !officecfg::Office::BasicIDE::Autocomplete::AutocloseDoubleQuotes::isReadOnly() ); + m_xAutocloseParenChk->set_active( officecfg::Office::BasicIDE::Autocomplete::AutocloseParenthesis::get() ); + m_xAutocloseParenChk->set_sensitive( !officecfg::Office::BasicIDE::Autocomplete::AutocloseParenthesis::isReadOnly() ); + m_xAutoCorrectChk->set_active( officecfg::Office::BasicIDE::Autocomplete::AutoCorrect::get() ); + m_xAutoCorrectChk->set_sensitive( !officecfg::Office::BasicIDE::Autocomplete::AutoCorrect::isReadOnly() ); + m_xUseExtendedTypesChk->set_active( officecfg::Office::BasicIDE::Autocomplete::UseExtended::get() ); + m_xUseExtendedTypesChk->set_sensitive( !officecfg::Office::BasicIDE::Autocomplete::UseExtended::isReadOnly() ); +} + +bool SvxBasicIDEOptionsPage::FillItemSet( SfxItemSet* /*rCoreSet*/ ) +{ + bool bModified = false; + std::shared_ptr< comphelper::ConfigurationChanges > batch( comphelper::ConfigurationChanges::create() ); + + if( m_xAutocloseProcChk->get_state_changed_from_saved() ) + { + officecfg::Office::BasicIDE::Autocomplete::AutocloseProc::set( m_xAutocloseProcChk->get_active(), batch ); + CodeCompleteOptions::SetProcedureAutoCompleteOn( m_xAutocloseProcChk->get_active() ); + bModified = true; + } + + if( m_xCodeCompleteChk->get_state_changed_from_saved() ) + { + //std::shared_ptr< comphelper::ConfigurationChanges > batch( comphelper::ConfigurationChanges::create() ); + officecfg::Office::BasicIDE::Autocomplete::CodeComplete::set( m_xCodeCompleteChk->get_active(), batch ); + CodeCompleteOptions::SetCodeCompleteOn( m_xCodeCompleteChk->get_active() ); + bModified = true; + } + + if( m_xUseExtendedTypesChk->get_state_changed_from_saved() ) + { + officecfg::Office::BasicIDE::Autocomplete::UseExtended::set( m_xUseExtendedTypesChk->get_active(), batch ); + CodeCompleteOptions::SetExtendedTypeDeclaration( m_xUseExtendedTypesChk->get_active() ); + bModified = true; + } + + if( m_xAutocloseParenChk->get_state_changed_from_saved() ) + { + officecfg::Office::BasicIDE::Autocomplete::AutocloseParenthesis::set( m_xAutocloseParenChk->get_active(), batch ); + CodeCompleteOptions::SetAutoCloseParenthesisOn( m_xAutocloseParenChk->get_active() ); + bModified = true; + } + + if( m_xAutocloseQuotesChk->get_state_changed_from_saved() ) + { + officecfg::Office::BasicIDE::Autocomplete::AutocloseDoubleQuotes::set( m_xAutocloseQuotesChk->get_active(), batch ); + CodeCompleteOptions::SetAutoCloseQuotesOn( m_xAutocloseQuotesChk->get_active() ); + bModified = true; + } + + if( m_xAutoCorrectChk->get_state_changed_from_saved() ) + { + officecfg::Office::BasicIDE::Autocomplete::AutoCorrect::set( m_xAutoCorrectChk->get_active(), batch ); + CodeCompleteOptions::SetAutoCorrectOn( m_xAutoCorrectChk->get_active() ); + bModified = true; + } + + if( bModified ) + batch->commit(); + + return bModified; +} + +void SvxBasicIDEOptionsPage::Reset( const SfxItemSet* /*rSet*/ ) +{ + LoadConfig(); + m_xCodeCompleteChk->save_state(); + m_xAutocloseProcChk->save_state(); + m_xAutocloseQuotesChk->save_state(); + m_xAutocloseParenChk->save_state(); + m_xAutoCorrectChk->save_state(); + m_xUseExtendedTypesChk->save_state(); +} + +std::unique_ptr SvxBasicIDEOptionsPage::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet ) +{ + return std::make_unique(pPage, pController, *rAttrSet); +} + +void SvxBasicIDEOptionsPage::FillUserData() +{ + SetUserData( OUString() ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/optbasic.hxx b/cui/source/options/optbasic.hxx new file mode 100644 index 000000000..5510fc129 --- /dev/null +++ b/cui/source/options/optbasic.hxx @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_CUI_SOURCE_OPTIONS_OPTBASIC_HXX +#define INCLUDED_CUI_SOURCE_OPTIONS_OPTBASIC_HXX + +#include + +class SvxBasicIDEOptionsPage: public SfxTabPage +{ +private: + std::unique_ptr m_xCodeCompleteChk; + std::unique_ptr m_xAutocloseProcChk; + std::unique_ptr m_xAutocloseParenChk; + std::unique_ptr m_xAutocloseQuotesChk; + std::unique_ptr m_xAutoCorrectChk; + std::unique_ptr m_xUseExtendedTypesChk; + + void LoadConfig(); + +public: + SvxBasicIDEOptionsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + virtual ~SvxBasicIDEOptionsPage() override; + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet ); + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; + virtual void FillUserData() override; +}; + + +#endif // INCLUDED_CUI_SOURCE_OPTIONS_OPTBASIC_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/optchart.cxx b/cui/source/options/optchart.cxx new file mode 100644 index 000000000..c77f2e4f4 --- /dev/null +++ b/cui/source/options/optchart.cxx @@ -0,0 +1,275 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "optchart.hxx" +#include +#include +#include +#include +#include +#include +#include +#include + +void SvxDefaultColorOptPage::InsertColorEntry(const XColorEntry& rEntry, sal_Int32 nPos) +{ + const Color& rColor = rEntry.GetColor(); + const OUString& rStr = rEntry.GetName(); + + const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); + Size aImageSize = rStyleSettings.GetListBoxPreviewDefaultPixelSize(); + + ScopedVclPtrInstance xDevice; + xDevice->SetOutputSize(aImageSize); + const ::tools::Rectangle aRect(Point(0, 0), aImageSize); + xDevice->SetFillColor(rColor); + xDevice->SetLineColor(rStyleSettings.GetDisableColor()); + xDevice->DrawRect(aRect); + + m_xLbChartColors->insert(nullptr, nPos, &rStr, nullptr, + nullptr, xDevice.get(), nullptr, false, nullptr); + + if (nPos == -1) + aColorList.push_back( rColor ); + else + { + ImpColorList::iterator it = aColorList.begin(); + std::advance( it, nPos ); + aColorList.insert( it, rColor ); + } +} + +void SvxDefaultColorOptPage::RemoveColorEntry(sal_Int32 nPos) +{ + m_xLbChartColors->remove(nPos); + ImpColorList::iterator it = aColorList.begin(); + std::advance(it, nPos); + aColorList.erase(it); +} + +void SvxDefaultColorOptPage::ClearColorEntries() +{ + aColorList.clear(); + m_xLbChartColors->clear(); +} + +void SvxDefaultColorOptPage::ModifyColorEntry(const XColorEntry& rEntry, sal_Int32 nPos) +{ + RemoveColorEntry(nPos); + InsertColorEntry(rEntry, nPos); +} + +void SvxDefaultColorOptPage::FillBoxChartColorLB() +{ + if (!m_SvxChartColorTableUniquePtr) + return; + + m_xLbChartColors->freeze(); + ClearColorEntries(); + const long nCount(m_SvxChartColorTableUniquePtr->size()); + for (long i = 0; i < nCount; ++i) + InsertColorEntry((*m_SvxChartColorTableUniquePtr)[i]); + m_xLbChartColors->thaw(); +} + +SvxDefaultColorOptPage::SvxDefaultColorOptPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "cui/ui/optchartcolorspage.ui", "OptChartColorsPage", &rInAttrs) + , m_xLbChartColors(m_xBuilder->weld_tree_view("colors")) + , m_xLbPaletteSelector(m_xBuilder->weld_combo_box("paletteselector")) + , m_xPBDefault(m_xBuilder->weld_button("default")) + , m_xPBAdd(m_xBuilder->weld_button("add")) + , m_xPBRemove(m_xBuilder->weld_button("delete")) + , m_xValSetColorBox(new SvxColorValueSet(m_xBuilder->weld_scrolled_window("tablewin"))) + , m_xValSetColorBoxWin(new weld::CustomWeld(*m_xBuilder, "table", *m_xValSetColorBox)) +{ + m_xLbChartColors->set_size_request(-1, m_xLbChartColors->get_height_rows(16)); + + m_xPBDefault->connect_clicked( LINK( this, SvxDefaultColorOptPage, ResetToDefaults ) ); + m_xPBAdd->connect_clicked( LINK( this, SvxDefaultColorOptPage, AddChartColor ) ); + m_xPBRemove->connect_clicked( LINK( this, SvxDefaultColorOptPage, RemoveChartColor ) ); + m_xValSetColorBox->SetSelectHdl( LINK( this, SvxDefaultColorOptPage, BoxClickedHdl ) ); + m_xLbPaletteSelector->connect_changed( LINK( this, SvxDefaultColorOptPage, SelectPaletteLbHdl ) ); + + m_xValSetColorBox->SetStyle( m_xValSetColorBox->GetStyle() + | WB_ITEMBORDER | WB_NAMEFIELD | WB_VSCROLL ); + + m_SvxChartOptionsUniquePtr.reset(new SvxChartOptions); + + const SfxPoolItem* pItem = nullptr; + if ( rInAttrs.GetItemState( SID_SCH_EDITOPTIONS, false, &pItem ) == SfxItemState::SET ) + { + m_SvxChartColorTableUniquePtr = std::make_unique( + static_cast(pItem)->GetColorList()); + } + else + { + m_SvxChartColorTableUniquePtr = std::make_unique(); + m_SvxChartColorTableUniquePtr->useDefault(); + m_SvxChartOptionsUniquePtr->SetDefaultColors(*m_SvxChartColorTableUniquePtr); + } + + Construct(); +} + +SvxDefaultColorOptPage::~SvxDefaultColorOptPage() +{ + m_xValSetColorBoxWin.reset(); + m_xValSetColorBox.reset(); +} + +void SvxDefaultColorOptPage::Construct() +{ + FillBoxChartColorLB(); + FillPaletteLB(); + + m_xLbChartColors->select( 0 ); +} + +std::unique_ptr SvxDefaultColorOptPage::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrs ) +{ + return std::make_unique( pPage, pController, *rAttrs ); +} + +bool SvxDefaultColorOptPage::FillItemSet( SfxItemSet* rOutAttrs ) +{ + if( m_SvxChartColorTableUniquePtr ) + { + rOutAttrs->Put(SvxChartColorTableItem(SID_SCH_EDITOPTIONS, *m_SvxChartColorTableUniquePtr)); + } + + return true; +} + +void SvxDefaultColorOptPage::Reset( const SfxItemSet* ) +{ + m_xLbChartColors->select( 0 ); +} + +void SvxDefaultColorOptPage::FillPaletteLB() +{ + m_xLbPaletteSelector->clear(); + std::vector aPaletteList = aPaletteManager.GetPaletteList(); + for (auto const& palette : aPaletteList) + m_xLbPaletteSelector->append_text(palette); + + OUString aPaletteName(officecfg::Office::Common::UserColors::PaletteName::get()); + m_xLbPaletteSelector->set_active_text(aPaletteName); + if (m_xLbPaletteSelector->get_active() != -1) + SelectPaletteLbHdl( *m_xLbPaletteSelector ); +} + +void SvxDefaultColorOptPage::SaveChartOptions() +{ + if (m_SvxChartOptionsUniquePtr && m_SvxChartColorTableUniquePtr) + { + m_SvxChartOptionsUniquePtr->SetDefaultColors(*m_SvxChartColorTableUniquePtr); + m_SvxChartOptionsUniquePtr->Commit(); + } +} + +// event handlers + + +// ResetToDefaults +IMPL_LINK_NOARG(SvxDefaultColorOptPage, ResetToDefaults, weld::Button&, void) +{ + if( m_SvxChartColorTableUniquePtr ) + { + m_SvxChartColorTableUniquePtr->useDefault(); + + FillBoxChartColorLB(); + + m_xLbChartColors->grab_focus(); + m_xLbChartColors->select( 0 ); + m_xPBRemove->set_sensitive(true); + } +} + +// AddChartColor +IMPL_LINK_NOARG(SvxDefaultColorOptPage, AddChartColor, weld::Button&, void) +{ + if( m_SvxChartColorTableUniquePtr ) + { + Color const black( 0x00, 0x00, 0x00 ); + + m_SvxChartColorTableUniquePtr->append( + XColorEntry(black, SvxChartColorTable::getDefaultName(m_SvxChartColorTableUniquePtr->size()))); + + FillBoxChartColorLB(); + m_xLbChartColors->grab_focus(); + m_xLbChartColors->select(m_SvxChartColorTableUniquePtr->size() - 1); + m_xPBRemove->set_sensitive(true); + } +} + +// RemoveChartColor +IMPL_LINK_NOARG( SvxDefaultColorOptPage, RemoveChartColor, weld::Button&, void ) +{ + sal_Int32 nIndex = m_xLbChartColors->get_selected_index(); + if (nIndex == -1) + return; + + if( !m_SvxChartColorTableUniquePtr ) + return; + + OSL_ENSURE(m_SvxChartColorTableUniquePtr->size() > 1, "don't delete the last chart color"); + + std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querydeletechartcolordialog.ui")); + std::unique_ptr xQuery(xBuilder->weld_message_dialog("QueryDeleteChartColorDialog")); + + if (RET_YES != xQuery->run()) + return; + + m_SvxChartColorTableUniquePtr->remove(nIndex); + + FillBoxChartColorLB(); + + m_xLbChartColors->grab_focus(); + + if (nIndex == m_xLbChartColors->n_children() && m_xLbChartColors->n_children() > 0) + m_xLbChartColors->select(m_SvxChartColorTableUniquePtr->size() - 1); + else if (m_xLbChartColors->n_children() > 0) + m_xLbChartColors->select( nIndex ); + else + m_xPBRemove->set_sensitive(true); +} + +IMPL_LINK_NOARG( SvxDefaultColorOptPage, SelectPaletteLbHdl, weld::ComboBox&, void) +{ + sal_Int32 nPos = m_xLbPaletteSelector->get_active(); + aPaletteManager.SetPalette( nPos ); + aPaletteManager.ReloadColorSet( *m_xValSetColorBox ); + m_xValSetColorBox->Resize(); +} + +IMPL_LINK_NOARG(SvxDefaultColorOptPage, BoxClickedHdl, ValueSet*, void) +{ + sal_Int32 nIdx = m_xLbChartColors->get_selected_index(); + if (nIdx != -1) + { + const XColorEntry aEntry(m_xValSetColorBox->GetItemColor(m_xValSetColorBox->GetSelectedItemId()), m_xLbChartColors->get_selected_text()); + + ModifyColorEntry(aEntry, nIdx); + m_SvxChartColorTableUniquePtr->replace(nIdx, aEntry); + + m_xLbChartColors->select(nIdx); // reselect entry + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/optchart.hxx b/cui/source/options/optchart.hxx new file mode 100644 index 000000000..eb9b1983b --- /dev/null +++ b/cui/source/options/optchart.hxx @@ -0,0 +1,82 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_CUI_SOURCE_OPTIONS_OPTCHART_HXX +#define INCLUDED_CUI_SOURCE_OPTIONS_OPTCHART_HXX + +#include +#include +#include +#include +#include + +#include "cfgchart.hxx" + +typedef std::vector ImpColorList; + +class SvxDefaultColorOptPage : public SfxTabPage +{ +private: + std::unique_ptr m_SvxChartOptionsUniquePtr; + // no reason to use a cloned SfxItem here (SvxChartColorTableItem) + // that just leads to non-const SfxItem and potential trouble + std::unique_ptr m_SvxChartColorTableUniquePtr; + + ImpColorList aColorList; + PaletteManager aPaletteManager; + + std::unique_ptr m_xLbChartColors; + std::unique_ptr m_xLbPaletteSelector; + std::unique_ptr m_xPBDefault; + std::unique_ptr m_xPBAdd; + std::unique_ptr m_xPBRemove; + std::unique_ptr m_xValSetColorBox; + std::unique_ptr m_xValSetColorBoxWin; + + DECL_LINK(ResetToDefaults, weld::Button&, void); + DECL_LINK(AddChartColor, weld::Button&, void); + DECL_LINK(RemoveChartColor, weld::Button&, void); + DECL_LINK(BoxClickedHdl, ValueSet*, void); + DECL_LINK(SelectPaletteLbHdl, weld::ComboBox&, void); + + void FillPaletteLB(); + +private: + void InsertColorEntry(const XColorEntry& rEntry, sal_Int32 nPos = -1); + void RemoveColorEntry(sal_Int32 nPos); + void ModifyColorEntry(const XColorEntry& rEntry, sal_Int32 nPos); + void ClearColorEntries(); + void FillBoxChartColorLB(); + +public: + SvxDefaultColorOptPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + virtual ~SvxDefaultColorOptPage() override; + + void Construct(); + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rInAttrs ); + virtual bool FillItemSet( SfxItemSet* rOutAttrs ) override; + virtual void Reset( const SfxItemSet* rInAttrs ) override; + + void SaveChartOptions(); +}; + +#endif // INCLUDED_CUI_SOURCE_OPTIONS_OPTCHART_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/optcolor.cxx b/cui/source/options/optcolor.cxx new file mode 100644 index 000000000..f7807adc5 --- /dev/null +++ b/cui/source/options/optcolor.cxx @@ -0,0 +1,888 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "optcolor.hxx" +#include + +using namespace ::com::sun::star; +using namespace ::svtools; + +namespace +{ + +// list of default groups +enum Group +{ + Group_General, + Group_Writer, + Group_Html, + Group_Calc, + Group_Draw, + Group_Basic, + Group_Sql, + + nGroupCount +}; + +// group data +struct +{ + // group + Group eGroup; + // .ui group name + const char *pGroup; +} +const vGroupInfo[] = +{ + // the groups are in the same order as in enum Group above + { Group_General, "general" }, + { Group_Writer, "writer" }, + { Group_Html, "html" }, + { Group_Calc, "calc" }, + { Group_Draw, "draw" }, + { Group_Basic, "basic" }, + { Group_Sql, "sql" } +}; + +// color config entry data (see ColorConfigWindow_Impl::Entry below) +struct +{ + // group + Group eGroup; + //checkbox (or simple text) + const char *pText; + //color listbox + const char *pColor; + // has checkbox? + bool bCheckBox; +} +const vEntryInfo[] = +{ + #define IDS(Name) \ + SAL_STRINGIFY(Name), SAL_STRINGIFY(Name##_lb), false + + #define IDS_CB(Name) \ + SAL_STRINGIFY(Name), SAL_STRINGIFY(Name##_lb), true + + // The list of these entries (enum ColorConfigEntry) are in colorcfg.hxx. + + { Group_General, IDS(doccolor) }, + { Group_General, IDS_CB(docboundaries) }, + { Group_General, IDS(appback) }, + { Group_General, IDS_CB(objboundaries) }, + { Group_General, IDS_CB(tblboundaries) }, + { Group_General, IDS(font) }, + { Group_General, IDS_CB(unvisitedlinks) }, + { Group_General, IDS_CB(visitedlinks) }, + { Group_General, IDS(autospellcheck) }, + { Group_General, IDS(smarttags) }, + { Group_General, IDS_CB(shadows) }, + + { Group_Writer, IDS(writergrid) }, + { Group_Writer, IDS_CB(field) }, + { Group_Writer, IDS_CB(index) }, + { Group_Writer, IDS(direct) }, + { Group_Writer, IDS(script) }, + { Group_Writer, IDS_CB(section) }, + { Group_Writer, IDS(hdft) }, + { Group_Writer, IDS(pagebreak) }, + + { Group_Html, IDS(sgml) }, + { Group_Html, IDS(htmlcomment) }, + { Group_Html, IDS(htmlkeyword) }, + { Group_Html, IDS(unknown) }, + + { Group_Calc, IDS(calcgrid) }, + { Group_Calc, IDS(brk) }, + { Group_Calc, IDS(brkmanual) }, + { Group_Calc, IDS(brkauto) }, + { Group_Calc, IDS(det) }, + { Group_Calc, IDS(deterror) }, + { Group_Calc, IDS(ref) }, + { Group_Calc, IDS(notes) }, + { Group_Calc, IDS(values) }, + { Group_Calc, IDS(formulas) }, + { Group_Calc, IDS(text) }, + { Group_Calc, IDS(protectedcells) }, + + { Group_Draw, IDS(drawgrid) }, + + { Group_Basic, IDS(basicid) }, + { Group_Basic, IDS(basiccomment) }, + { Group_Basic, IDS(basicnumber) }, + { Group_Basic, IDS(basicstring) }, + { Group_Basic, IDS(basicop) }, + { Group_Basic, IDS(basickeyword) }, + { Group_Basic, IDS(error) }, + + { Group_Sql, IDS(sqlid) }, + { Group_Sql, IDS(sqlnumber) }, + { Group_Sql, IDS(sqlstring) }, + { Group_Sql, IDS(sqlop) }, + { Group_Sql, IDS(sqlkeyword) }, + { Group_Sql, IDS(sqlparam) }, + { Group_Sql, IDS(sqlcomment) } + + #undef IDS +}; + +// ColorConfigWindow_Impl + +class ColorConfigWindow_Impl +{ +public: + explicit ColorConfigWindow_Impl(weld::Window* pTopLevel, weld::Container* pParent); + +public: + void SetLinks(Link const&, + Link const&, + Link const&, + weld::ScrolledWindow& rScroll); + void Update(EditableColorConfig const*, EditableExtendedColorConfig const*); + void ClickHdl(EditableColorConfig*, weld::ToggleButton&); + void ColorHdl(EditableColorConfig*, EditableExtendedColorConfig*, const ColorListBox*); + + weld::Widget& GetWidget1() + { + return *m_xWidget1; + } + + weld::Widget& GetWidget2() + { + return *m_xWidget2; + } + + weld::Widget& GetBody() + { + return *m_xGrid; + } + + void AdjustExtraWidths(int nTextWidth); + +private: + // Chapter -- horizontal group separator stripe with text + class Chapter + { + // text + std::unique_ptr m_xText; + public: + Chapter(weld::Builder& rBuilder, const char* pLabelWidget, bool bShow); + void SetText(const OUString& rLabel) { m_xText->set_label(rLabel); } + }; + + // Entry -- a color config entry: + // text (checkbox) + color list box + class Entry + { + public: + Entry(weld::Window* pTopLevel, weld::Builder& rBuilder, const char* pTextWidget, const char* pColorWidget, + const Color& rColor, long nCheckBoxLabelOffset, bool bCheckBox, bool bShow); + public: + void SetText(const OUString& rLabel) { dynamic_cast(*m_xText).set_label(rLabel); } + void set_width_request(int nTextWidth) { m_xText->set_size_request(nTextWidth, -1); } + int get_height_request() const + { + return std::max(m_xText->get_preferred_size().Height(), + m_xColorList->get_widget().get_preferred_size().Height()); + } + void Hide (); + public: + void SetLinks(Link const&, + Link const&, + Link const&); + void Update (ColorConfigValue const&); + void Update (ExtendedColorConfigValue const&); + void ColorChanged (ColorConfigValue&); + void ColorChanged (ExtendedColorConfigValue&); + public: + bool Is(const weld::ToggleButton* pBox) const { return m_xText.get() == pBox; } + bool Is(const ColorListBox* pBox) const { return m_xColorList.get() == pBox; } + private: + // checkbox (CheckBox) or simple text (FixedText) + std::unique_ptr m_xText; + // color list box + std::unique_ptr m_xColorList; + // default color + Color m_aDefaultColor; + }; + +private: + weld::Window* m_pTopLevel; + std::unique_ptr m_xBuilder; + std::unique_ptr m_xGrid; + std::unique_ptr m_xWidget1; + std::unique_ptr m_xWidget2; + + std::vector> vExtBuilders; + std::vector> vExtContainers; + // vChapters -- groups (group headers) + std::vector > vChapters; + // vEntries -- color options + std::vector > vEntries; + + // module options + SvtModuleOptions aModuleOptions; + + // initialization + void CreateEntries(); + +private: + + bool IsGroupVisible (Group) const; +}; + +} // namespace + +// ColorConfigWindow_Impl::Chapter + +// ctor for default groups +// rParent: parent window (ColorConfigWindow_Impl) +// eGroup: which group is this? +ColorConfigWindow_Impl::Chapter::Chapter(weld::Builder& rBuilder, const char* pLabelWidget, bool bShow) + : m_xText(rBuilder.weld_label(pLabelWidget)) +{ + if (!bShow) + m_xText->hide(); +} + +// ColorConfigWindow_Impl::Entry +ColorConfigWindow_Impl::Entry::Entry(weld::Window* pTopLevel, weld::Builder& rBuilder, + const char* pTextWidget, const char* pColorWidget, + const Color& rColor, + long nCheckBoxLabelOffset, bool bCheckBox, bool bShow) + : m_xColorList(new ColorListBox(rBuilder.weld_menu_button(pColorWidget), pTopLevel)) + , m_aDefaultColor(rColor) +{ + if (bCheckBox) + m_xText = rBuilder.weld_check_button(pTextWidget); + else + m_xText = rBuilder.weld_label(pTextWidget); + + // color list + m_xColorList->SetSlotId(SID_ATTR_CHAR_COLOR); + m_xColorList->SetAutoDisplayColor(m_aDefaultColor); + + if (!bCheckBox) + { + m_xText->set_margin_left(m_xText->get_margin_left() + + nCheckBoxLabelOffset); + } + + if (!bShow) + Hide(); +} + +void ColorConfigWindow_Impl::Entry::Hide() +{ + m_xText->hide(); + m_xColorList->hide(); +} + +// SetLinks() +void ColorConfigWindow_Impl::Entry::SetLinks(Link const& rCheckLink, + Link const& rColorLink, + Link const& rGetFocusLink) +{ + m_xColorList->SetSelectHdl(rColorLink); + m_xColorList->connect_focus_in(rGetFocusLink); + if (weld::ToggleButton* pCheckBox = dynamic_cast(m_xText.get())) + { + pCheckBox->connect_toggled(rCheckLink); + pCheckBox->connect_focus_in(rGetFocusLink); + } +} + +// updates a default color config entry +void ColorConfigWindow_Impl::Entry::Update(ColorConfigValue const& rValue) +{ + Color aColor(rValue.nColor); + m_xColorList->SelectEntry(aColor); + if (weld::ToggleButton* pCheckBox = dynamic_cast(m_xText.get())) + pCheckBox->set_active(rValue.bIsVisible); +} + +// updates an extended color config entry +void ColorConfigWindow_Impl::Entry::Update(ExtendedColorConfigValue const& rValue) +{ + Color aColor(rValue.getColor()); + if (rValue.getColor() == rValue.getDefaultColor()) + m_xColorList->SelectEntry(COL_AUTO); + else + m_xColorList->SelectEntry(aColor); +} + +// color of a default entry has changed +void ColorConfigWindow_Impl::Entry::ColorChanged(ColorConfigValue& rValue) +{ + Color aColor = m_xColorList->GetSelectEntryColor(); + rValue.nColor = aColor; +} + +// color of an extended entry has changed +void ColorConfigWindow_Impl::Entry::ColorChanged(ExtendedColorConfigValue& rValue) +{ + Color aColor = m_xColorList->GetSelectEntryColor(); + rValue.setColor(aColor); + if (aColor == COL_AUTO) + { + rValue.setColor(rValue.getDefaultColor()); + } +} + +// ColorConfigWindow_Impl +ColorConfigWindow_Impl::ColorConfigWindow_Impl(weld::Window* pTopLevel, weld::Container* pParent) + : m_pTopLevel(pTopLevel) + , m_xBuilder(Application::CreateBuilder(pParent, "cui/ui/colorconfigwin.ui")) + , m_xGrid(m_xBuilder->weld_container("ColorConfigWindow")) + , m_xWidget1(m_xBuilder->weld_widget("doccolor")) + , m_xWidget2(m_xBuilder->weld_widget("doccolor_lb")) +{ + CreateEntries(); +} + +void ColorConfigWindow_Impl::CreateEntries() +{ + std::bitset aModulesInstalled; + // creating group headers + vChapters.reserve(nGroupCount); + for (unsigned i = 0; i != nGroupCount; ++i) + { + aModulesInstalled[i] = IsGroupVisible(vGroupInfo[i].eGroup); + vChapters.push_back(std::make_shared(*m_xBuilder, vGroupInfo[i].pGroup, aModulesInstalled[i])); + } + + // Here we want to get the amount to add to the position of a FixedText to + // get it to align its contents with that of a CheckBox + long nCheckBoxLabelOffset = 0; + { + OUString sSampleText("X"); + std::unique_ptr xCheckBox(m_xBuilder->weld_check_button("docboundaries")); + std::unique_ptr xFixedText(m_xBuilder->weld_label("doccolor")); + OUString sOrigCheck(xCheckBox->get_label()); + OUString sOrigFixed(xFixedText->get_label()); + xCheckBox->set_label(sSampleText); + xFixedText->set_label(sSampleText); + Size aCheckSize(xCheckBox->get_preferred_size()); + Size aFixedSize(xFixedText->get_preferred_size()); + xCheckBox->set_label(sOrigCheck); + xFixedText->set_label(sOrigFixed); + nCheckBoxLabelOffset = aCheckSize.Width() - aFixedSize.Width(); + } + + // creating entries + vEntries.reserve(ColorConfigEntryCount); + for (size_t i = 0; i < SAL_N_ELEMENTS(vEntryInfo); ++i) + { + vEntries.push_back(std::make_shared(m_pTopLevel, *m_xBuilder, + vEntryInfo[i].pText, vEntryInfo[i].pColor, + ColorConfig::GetDefaultColor(static_cast(i)), + nCheckBoxLabelOffset, + vEntryInfo[i].bCheckBox, + aModulesInstalled[vEntryInfo[i].eGroup])); + } + + // extended entries + ExtendedColorConfig aExtConfig; + unsigned const nExtGroupCount = aExtConfig.GetComponentCount(); + if (!nExtGroupCount) + return; + + size_t nLineNum = vChapters.size() + vEntries.size() + 1; + for (unsigned j = 0; j != nExtGroupCount; ++j) + { + vExtBuilders.emplace_back(Application::CreateBuilder(m_xGrid.get(), "cui/ui/chapterfragment.ui")); + vExtContainers.emplace_back(vExtBuilders.back()->weld_container("ChapterFragment")); + + vExtContainers.back()->set_grid_width(3); + vExtContainers.back()->set_grid_left_attach(0); + vExtContainers.back()->set_grid_top_attach(nLineNum); + + OUString const sComponentName = aExtConfig.GetComponentName(j); + vChapters.push_back(std::make_shared( + *vExtBuilders.back(), "chapter", true)); + vChapters.back()->SetText(aExtConfig.GetComponentDisplayName(sComponentName)); + ++nLineNum; + unsigned nColorCount = aExtConfig.GetComponentColorCount(sComponentName); + for (unsigned i = 0; i != nColorCount; ++i) + { + vExtBuilders.emplace_back(Application::CreateBuilder(m_xGrid.get(), "cui/ui/colorfragment.ui")); + vExtContainers.emplace_back(vExtBuilders.back()->weld_container("ColorFragment")); + + vExtContainers.back()->set_grid_width(3); + vExtContainers.back()->set_grid_left_attach(0); + vExtContainers.back()->set_grid_top_attach(nLineNum); + + ExtendedColorConfigValue const aColorEntry = + aExtConfig.GetComponentColorConfigValue(sComponentName, i); + vEntries.push_back(std::make_shared(m_pTopLevel, *vExtBuilders.back(), + "label", "button", aColorEntry.getDefaultColor(), + nCheckBoxLabelOffset, false, true)); + vEntries.back()->SetText(aColorEntry.getDisplayName()); + ++nLineNum; + } + } +} + +void ColorConfigWindow_Impl::AdjustExtraWidths(int nTextWidth) +{ + for (size_t i = SAL_N_ELEMENTS(vEntryInfo); i < vEntries.size(); ++i) + vEntries[i]->set_width_request(nTextWidth); +} + +// SetLinks() +void ColorConfigWindow_Impl::SetLinks(Link const& aCheckLink, + Link const& aColorLink, + Link const& rGetFocusLink, + weld::ScrolledWindow& rScroll) +{ + if (vEntries.empty()) + return; + for (auto const & i: vEntries) + i->SetLinks(aCheckLink, aColorLink, rGetFocusLink); + // 6 is the spacing set on ColorConfigWindow + rScroll.vadjustment_set_step_increment(vEntries[0]->get_height_request() + 6); +} + +// Update() +void ColorConfigWindow_Impl::Update ( + EditableColorConfig const* pConfig, + EditableExtendedColorConfig const* pExtConfig) +{ + // updating default entries + for (unsigned i = 0; i != ColorConfigEntryCount; ++i) + { + ColorConfigEntry const aColorEntry = static_cast(i); + vEntries[i]->Update( + pConfig->GetColorValue(aColorEntry) + ); + } + + // updating extended entries + decltype(vEntries)::size_type i = ColorConfigEntryCount; + unsigned const nExtCount = pExtConfig->GetComponentCount(); + for (unsigned j = 0; j != nExtCount; ++j) + { + OUString sComponentName = pExtConfig->GetComponentName(j); + unsigned const nColorCount = pExtConfig->GetComponentColorCount(sComponentName); + for (unsigned k = 0; i != vEntries.size() && k != nColorCount; ++i, ++k) + vEntries[i]->Update( + pExtConfig->GetComponentColorConfigValue(sComponentName, k) + ); + } +} + +// ClickHdl() +void ColorConfigWindow_Impl::ClickHdl(EditableColorConfig* pConfig, weld::ToggleButton& rBox) +{ + for (unsigned i = 0; i != ColorConfigEntryCount; ++i) + { + if (vEntries[i]->Is(&rBox)) + { + ColorConfigEntry const aEntry = static_cast(i); + ColorConfigValue aValue = pConfig->GetColorValue(aEntry); + aValue.bIsVisible = rBox.get_active(); + pConfig->SetColorValue(aEntry, aValue); + break; + } + } +} + +// ColorHdl() +void ColorConfigWindow_Impl::ColorHdl( + EditableColorConfig* pConfig, EditableExtendedColorConfig* pExtConfig, + const ColorListBox* pBox) +{ + unsigned i = 0; + + // default entries + for ( ; i != ColorConfigEntryCount; ++i) + { + if (pBox && vEntries[i]->Is(pBox)) + { + ColorConfigEntry const aColorEntry = static_cast(i); + ColorConfigValue aValue = pConfig->GetColorValue(aColorEntry); + vEntries[i]->ColorChanged(aValue); + pConfig->SetColorValue(aColorEntry, aValue); + break; + } + } + + // extended entries + unsigned const nExtCount = pExtConfig->GetComponentCount(); + i = ColorConfigEntryCount; + for (unsigned j = 0; j != nExtCount; ++j) + { + OUString sComponentName = pExtConfig->GetComponentName(j); + unsigned const nColorCount = pExtConfig->GetComponentColorCount(sComponentName); + unsigned const nCount = vEntries.size(); + for (unsigned k = 0; i != nCount && k != nColorCount; ++i, ++k) + { + if (pBox && vEntries[i]->Is(pBox)) + { + ExtendedColorConfigValue aValue = + pExtConfig->GetComponentColorConfigValue(sComponentName, k); + vEntries[i]->ColorChanged(aValue); + pExtConfig->SetColorValue(sComponentName, aValue); + break; + } + } + } +} + + +// IsGroupVisible() +bool ColorConfigWindow_Impl::IsGroupVisible (Group eGroup) const +{ + switch (eGroup) + { + case Group_Writer: + case Group_Html: + return aModuleOptions.IsModuleInstalled(SvtModuleOptions::EModule::WRITER); + case Group_Calc: + return aModuleOptions.IsModuleInstalled(SvtModuleOptions::EModule::CALC); + case Group_Draw: + return + aModuleOptions.IsModuleInstalled(SvtModuleOptions::EModule::DRAW) || + aModuleOptions.IsModuleInstalled(SvtModuleOptions::EModule::IMPRESS); + case Group_Sql: + return aModuleOptions.IsModuleInstalled(SvtModuleOptions::EModule::DATABASE); + default: + return true; + } +} + +class ColorConfigCtrl_Impl +{ + std::unique_ptr m_xVScroll; + std::unique_ptr m_xBody; + std::unique_ptr m_xScrollWindow; + + EditableColorConfig* pColorConfig; + EditableExtendedColorConfig* pExtColorConfig; + + DECL_LINK(ClickHdl, weld::ToggleButton&, void); + DECL_LINK(ColorHdl, ColorListBox&, void); + DECL_LINK(ControlFocusHdl, weld::Widget&, void); + +public: + explicit ColorConfigCtrl_Impl(weld::Window* pTopLevel, weld::Builder& rbuilder); + + void AdjustExtraWidths(int nTextWidth) { m_xScrollWindow->AdjustExtraWidths(nTextWidth); } + void SetConfig (EditableColorConfig& rConfig) { pColorConfig = &rConfig; } + void SetExtendedConfig (EditableExtendedColorConfig& rConfig) { pExtColorConfig = &rConfig; } + void Update(); + long GetScrollPosition() const + { + return m_xVScroll->vadjustment_get_value(); + } + void SetScrollPosition(long nSet) + { + m_xVScroll->vadjustment_set_value(nSet); + } + weld::Widget& GetWidget1() + { + return m_xScrollWindow->GetWidget1(); + } + weld::Widget& GetWidget2() + { + return m_xScrollWindow->GetWidget2(); + } +}; + +ColorConfigCtrl_Impl::ColorConfigCtrl_Impl(weld::Window* pTopLevel, weld::Builder& rBuilder) + : m_xVScroll(rBuilder.weld_scrolled_window("scroll")) + , m_xBody(rBuilder.weld_container("colorconfig")) + , m_xScrollWindow(std::make_unique(pTopLevel, m_xBody.get())) + , pColorConfig(nullptr) + , pExtColorConfig(nullptr) +{ + m_xBody->set_stack_background(); + + Link aCheckLink = LINK(this, ColorConfigCtrl_Impl, ClickHdl); + Link aColorLink = LINK(this, ColorConfigCtrl_Impl, ColorHdl); + Link const& aGetFocusLink = LINK(this, ColorConfigCtrl_Impl, ControlFocusHdl); + m_xScrollWindow->SetLinks(aCheckLink, aColorLink, aGetFocusLink, *m_xVScroll); +} + +void ColorConfigCtrl_Impl::Update () +{ + DBG_ASSERT(pColorConfig, "Configuration not set"); + m_xScrollWindow->Update(pColorConfig, pExtColorConfig); +} + +IMPL_LINK(ColorConfigCtrl_Impl, ClickHdl, weld::ToggleButton&, rBox, void) +{ + DBG_ASSERT(pColorConfig, "Configuration not set"); + m_xScrollWindow->ClickHdl(pColorConfig, rBox); +} + +// a color list has changed +IMPL_LINK(ColorConfigCtrl_Impl, ColorHdl, ColorListBox&, rBox, void) +{ + DBG_ASSERT(pColorConfig, "Configuration not set" ); + m_xScrollWindow->ColorHdl(pColorConfig, pExtColorConfig, &rBox); +} + +IMPL_LINK(ColorConfigCtrl_Impl, ControlFocusHdl, weld::Widget&, rCtrl, void) +{ + // determine whether a control is completely visible + // and make it visible + unsigned const nWinHeight = m_xVScroll->vadjustment_get_page_size(); + + // calc visible area + auto nThumbPos = m_xVScroll->vadjustment_get_value(); + int const nWinTop = nThumbPos; + int const nWinBottom = nWinTop + nWinHeight; + + int x, nCtrlPosY, width, nHeight; + rCtrl.get_extents_relative_to(m_xScrollWindow->GetBody(), x, nCtrlPosY, width, nHeight); + + int const nSelectedItemTop = nCtrlPosY; + int const nSelectedItemBottom = nCtrlPosY + nHeight; + bool const shouldScrollDown = nSelectedItemBottom >= nWinBottom; + bool const shouldScrollUp = nSelectedItemTop <= nWinTop; + bool const isNeedToScroll = shouldScrollDown || shouldScrollUp || nCtrlPosY < 0; + + if (!isNeedToScroll) + return; + + if (shouldScrollDown) + { + int nOffset = nSelectedItemBottom - nWinBottom; + nThumbPos += nOffset + 2; + } + else + { + int nOffset = nWinTop - nSelectedItemTop; + nThumbPos -= nOffset + 2; + if(nThumbPos < 0) + nThumbPos = 0; + } + m_xVScroll->vadjustment_set_value(nThumbPos); +} + +// SvxColorOptionsTabPage +SvxColorOptionsTabPage::SvxColorOptionsTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreSet) + : SfxTabPage(pPage, pController, "cui/ui/optappearancepage.ui", "OptAppearancePage", &rCoreSet) + , bFillItemSetCalled(false) + , m_xColorSchemeLB(m_xBuilder->weld_combo_box("colorschemelb")) + , m_xSaveSchemePB(m_xBuilder->weld_button("save")) + , m_xDeleteSchemePB(m_xBuilder->weld_button("delete")) + , m_xColorConfigCT(new ColorConfigCtrl_Impl(pController->getDialog(), *m_xBuilder)) + , m_xTable(m_xBuilder->weld_widget("table")) + , m_xOnFT(m_xBuilder->weld_label("on")) + , m_xElementFT(m_xBuilder->weld_label("uielements")) + , m_xColorFT(m_xBuilder->weld_label("colorsetting")) + , m_rWidget1(m_xColorConfigCT->GetWidget1()) + , m_rWidget2(m_xColorConfigCT->GetWidget2()) +{ + m_xColorSchemeLB->make_sorted(); + m_xColorSchemeLB->connect_changed(LINK(this, SvxColorOptionsTabPage, SchemeChangedHdl_Impl)); + Link aLk = LINK(this, SvxColorOptionsTabPage, SaveDeleteHdl_Impl ); + m_xSaveSchemePB->connect_clicked(aLk); + m_xDeleteSchemePB->connect_clicked(aLk); + + m_rWidget1.connect_size_allocate(LINK(this, SvxColorOptionsTabPage, AdjustHeaderBar)); + m_rWidget2.connect_size_allocate(LINK(this, SvxColorOptionsTabPage, AdjustHeaderBar)); +} + +SvxColorOptionsTabPage::~SvxColorOptionsTabPage() +{ + if (pColorConfig) + { + //when the dialog is cancelled but the color scheme ListBox has been changed these + //changes need to be undone + if (!bFillItemSetCalled && m_xColorSchemeLB->get_value_changed_from_saved()) + { + OUString sOldScheme = m_xColorSchemeLB->get_saved_value(); + if(!sOldScheme.isEmpty()) + { + pColorConfig->SetCurrentSchemeName(sOldScheme); + pExtColorConfig->SetCurrentSchemeName(sOldScheme); + } + } + pColorConfig->ClearModified(); + pColorConfig->EnableBroadcast(); + pColorConfig.reset(); + + pExtColorConfig->ClearModified(); + pExtColorConfig->EnableBroadcast(); + pExtColorConfig.reset(); + } + m_xColorConfigCT.reset(); +} + +std::unique_ptr SvxColorOptionsTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet) +{ + return std::make_unique(pPage, pController, *rAttrSet); +} + +bool SvxColorOptionsTabPage::FillItemSet( SfxItemSet* ) +{ + bFillItemSetCalled = true; + if (m_xColorSchemeLB->get_value_changed_from_saved()) + { + pColorConfig->SetModified(); + pExtColorConfig->SetModified(); + } + if (pColorConfig->IsModified()) + pColorConfig->Commit(); + if (pExtColorConfig->IsModified()) + pExtColorConfig->Commit(); + return true; +} + +void SvxColorOptionsTabPage::Reset( const SfxItemSet* ) +{ + if(pColorConfig) + { + pColorConfig->ClearModified(); + pColorConfig->DisableBroadcast(); + } + pColorConfig.reset(new EditableColorConfig); + m_xColorConfigCT->SetConfig(*pColorConfig); + + if(pExtColorConfig) + { + pExtColorConfig->ClearModified(); + pExtColorConfig->DisableBroadcast(); + } + pExtColorConfig.reset(new EditableExtendedColorConfig); + m_xColorConfigCT->SetExtendedConfig(*pExtColorConfig); + + OUString sUser = GetUserData(); + //has to be called always to speed up accessibility tools + m_xColorConfigCT->SetScrollPosition(sUser.toInt32()); + m_xColorSchemeLB->clear(); + const uno::Sequence< OUString > aSchemes = pColorConfig->GetSchemeNames(); + for(const OUString& s : aSchemes) + m_xColorSchemeLB->append_text(s); + m_xColorSchemeLB->set_active_text(pColorConfig->GetCurrentSchemeName()); + m_xColorSchemeLB->save_value(); + m_xDeleteSchemePB->set_sensitive( aSchemes.getLength() > 1 ); + UpdateColorConfig(); +} + +DeactivateRC SvxColorOptionsTabPage::DeactivatePage( SfxItemSet* pSet_ ) +{ + if ( pSet_ ) + FillItemSet( pSet_ ); + return DeactivateRC::LeavePage; +} + +void SvxColorOptionsTabPage::UpdateColorConfig() +{ + //update the color config control + m_xColorConfigCT->Update(); +} + +IMPL_LINK(SvxColorOptionsTabPage, SchemeChangedHdl_Impl, weld::ComboBox&, rBox, void) +{ + pColorConfig->LoadScheme(rBox.get_active_text()); + pExtColorConfig->LoadScheme(rBox.get_active_text()); + UpdateColorConfig(); +} + +IMPL_LINK(SvxColorOptionsTabPage, SaveDeleteHdl_Impl, weld::Button&, rButton, void) +{ + if (m_xSaveSchemePB.get() == &rButton) + { + OUString sName; + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr aNameDlg(pFact->CreateSvxNameDialog(GetFrameWeld(), + sName, CuiResId(RID_SVXSTR_COLOR_CONFIG_SAVE2) )); + aNameDlg->SetCheckNameHdl( LINK(this, SvxColorOptionsTabPage, CheckNameHdl_Impl)); + aNameDlg->SetText(CuiResId(RID_SVXSTR_COLOR_CONFIG_SAVE1)); + aNameDlg->SetHelpId(HID_OPTIONS_COLORCONFIG_SAVE_SCHEME); + aNameDlg->SetCheckNameHdl( LINK(this, SvxColorOptionsTabPage, CheckNameHdl_Impl)); + if(RET_OK == aNameDlg->Execute()) + { + aNameDlg->GetName(sName); + pColorConfig->AddScheme(sName); + pExtColorConfig->AddScheme(sName); + m_xColorSchemeLB->append_text(sName); + m_xColorSchemeLB->set_active_text(sName); + SchemeChangedHdl_Impl(*m_xColorSchemeLB); + } + } + else + { + DBG_ASSERT(m_xColorSchemeLB->get_count() > 1, "don't delete the last scheme"); + std::unique_ptr xQuery(Application::CreateMessageDialog(GetFrameWeld(), + VclMessageType::Question, VclButtonsType::YesNo, + CuiResId(RID_SVXSTR_COLOR_CONFIG_DELETE))); + xQuery->set_title(CuiResId(RID_SVXSTR_COLOR_CONFIG_DELETE_TITLE)); + if (RET_YES == xQuery->run()) + { + OUString sDeleteScheme(m_xColorSchemeLB->get_active_text()); + m_xColorSchemeLB->remove(m_xColorSchemeLB->get_active()); + m_xColorSchemeLB->set_active(0); + SchemeChangedHdl_Impl(*m_xColorSchemeLB); + //first select the new scheme and then delete the old one + pColorConfig->DeleteScheme(sDeleteScheme); + pExtColorConfig->DeleteScheme(sDeleteScheme); + } + } + m_xDeleteSchemePB->set_sensitive(m_xColorSchemeLB->get_count() > 1); +} + +IMPL_LINK(SvxColorOptionsTabPage, CheckNameHdl_Impl, AbstractSvxNameDialog&, rDialog, bool ) +{ + OUString sName; + rDialog.GetName(sName); + return !sName.isEmpty() && m_xColorSchemeLB->find_text(sName) == -1; +} + +void SvxColorOptionsTabPage::FillUserData() +{ + SetUserData(OUString::number(m_xColorConfigCT->GetScrollPosition())); +} + +IMPL_LINK_NOARG(SvxColorOptionsTabPage, AdjustHeaderBar, const Size&, void) +{ + // horizontal positions + int nX0 = 0, nX1, nX2, y, width, height; + if (!m_rWidget1.get_extents_relative_to(*m_xTable, nX1, y, width, height)) + return; + if (!m_rWidget2.get_extents_relative_to(*m_xTable, nX2, y, width, height)) + return; + auto nTextWidth1 = nX1 - nX0; + auto nTextWidth2 = nX2 - nX1; + m_xOnFT->set_size_request(nTextWidth1, -1); + m_xElementFT->set_size_request(nTextWidth2, -1); + m_xColorConfigCT->AdjustExtraWidths(nTextWidth2 - 12); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/optcolor.hxx b/cui/source/options/optcolor.hxx new file mode 100644 index 000000000..de84e06b1 --- /dev/null +++ b/cui/source/options/optcolor.hxx @@ -0,0 +1,63 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include + +namespace svtools {class EditableColorConfig;class EditableExtendedColorConfig;} +class ColorConfigCtrl_Impl; +class AbstractSvxNameDialog; +class SvxColorOptionsTabPage : public SfxTabPage +{ + bool bFillItemSetCalled; + + std::unique_ptr m_xColorSchemeLB; + std::unique_ptr m_xSaveSchemePB; + std::unique_ptr m_xDeleteSchemePB; + std::unique_ptr m_xColorConfigCT; + std::unique_ptr m_xTable; + std::unique_ptr m_xOnFT; + std::unique_ptr m_xElementFT; + std::unique_ptr m_xColorFT; + weld::Widget& m_rWidget1; + weld::Widget& m_rWidget2; + + std::unique_ptr pColorConfig; + std::unique_ptr pExtColorConfig; + + DECL_LINK(SchemeChangedHdl_Impl, weld::ComboBox&, void); + DECL_LINK(SaveDeleteHdl_Impl, weld::Button&, void); + DECL_LINK(CheckNameHdl_Impl, AbstractSvxNameDialog&, bool); + DECL_LINK(AdjustHeaderBar, const Size&, void); + void UpdateColorConfig(); + +public: + SvxColorOptionsTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + virtual ~SvxColorOptionsTabPage() override; + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet ); + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; + + virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override; + virtual void FillUserData() override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/optctl.cxx b/cui/source/options/optctl.cxx new file mode 100644 index 000000000..983f077e7 --- /dev/null +++ b/cui/source/options/optctl.cxx @@ -0,0 +1,146 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "optctl.hxx" +#include +#include +#include + +// class SvxCTLOptionsPage ----------------------------------------------------- + +IMPL_LINK_NOARG(SvxCTLOptionsPage, SequenceCheckingCB_Hdl, weld::Button&, void) +{ + bool bIsSequenceChecking = m_xSequenceCheckingCB->get_active(); + m_xRestrictedCB->set_sensitive( bIsSequenceChecking ); + m_xTypeReplaceCB->set_sensitive( bIsSequenceChecking ); + // #i48117#: by default restricted and type&replace have to be switched on + if (bIsSequenceChecking) + { + m_xTypeReplaceCB->set_active(true); + m_xRestrictedCB->set_active(true); + } +} + +SvxCTLOptionsPage::SvxCTLOptionsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/optctlpage.ui", "OptCTLPage", &rSet) + , m_xSequenceCheckingCB(m_xBuilder->weld_check_button("sequencechecking")) + , m_xRestrictedCB(m_xBuilder->weld_check_button("restricted")) + , m_xTypeReplaceCB(m_xBuilder->weld_check_button("typeandreplace")) + , m_xMovementLogicalRB(m_xBuilder->weld_radio_button("movementlogical")) + , m_xMovementVisualRB(m_xBuilder->weld_radio_button("movementvisual")) + , m_xNumeralsLB(m_xBuilder->weld_combo_box("numerals")) +{ + m_xSequenceCheckingCB->connect_clicked(LINK(this, SvxCTLOptionsPage, SequenceCheckingCB_Hdl)); +} + +SvxCTLOptionsPage::~SvxCTLOptionsPage() +{ +} + +std::unique_ptr SvxCTLOptionsPage::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet ) +{ + return std::make_unique( pPage, pController, *rAttrSet ); +} + +bool SvxCTLOptionsPage::FillItemSet( SfxItemSet* ) +{ + bool bModified = false; + SvtCTLOptions aCTLOptions; + + // Sequence checking + bool bChecked = m_xSequenceCheckingCB->get_active(); + if ( m_xSequenceCheckingCB->get_state_changed_from_saved() ) + { + aCTLOptions.SetCTLSequenceChecking( bChecked ); + bModified = true; + } + + bChecked = m_xRestrictedCB->get_active(); + if( m_xRestrictedCB->get_state_changed_from_saved() ) + { + aCTLOptions.SetCTLSequenceCheckingRestricted( bChecked ); + bModified = true; + } + bChecked = m_xTypeReplaceCB->get_active(); + if( m_xTypeReplaceCB->get_state_changed_from_saved()) + { + aCTLOptions.SetCTLSequenceCheckingTypeAndReplace(bChecked); + bModified = true; + } + + bool bLogicalChecked = m_xMovementLogicalRB->get_active(); + if ( m_xMovementLogicalRB->get_state_changed_from_saved() || + m_xMovementVisualRB->get_state_changed_from_saved() ) + { + SvtCTLOptions::CursorMovement eMovement = + bLogicalChecked ? SvtCTLOptions::MOVEMENT_LOGICAL : SvtCTLOptions::MOVEMENT_VISUAL; + aCTLOptions.SetCTLCursorMovement( eMovement ); + bModified = true; + } + + if (m_xNumeralsLB->get_value_changed_from_saved()) + { + const sal_Int32 nPos = m_xNumeralsLB->get_active(); + aCTLOptions.SetCTLTextNumerals( static_cast(nPos) ); + bModified = true; + } + + return bModified; +} + +void SvxCTLOptionsPage::Reset( const SfxItemSet* ) +{ + SvtCTLOptions aCTLOptions; + + m_xSequenceCheckingCB->set_active( aCTLOptions.IsCTLSequenceChecking() ); + m_xRestrictedCB->set_active( aCTLOptions.IsCTLSequenceCheckingRestricted() ); + m_xTypeReplaceCB->set_active( aCTLOptions.IsCTLSequenceCheckingTypeAndReplace() ); + + SvtCTLOptions::CursorMovement eMovement = aCTLOptions.GetCTLCursorMovement(); + switch ( eMovement ) + { + case SvtCTLOptions::MOVEMENT_LOGICAL : + m_xMovementLogicalRB->set_active(true); + break; + + case SvtCTLOptions::MOVEMENT_VISUAL : + m_xMovementVisualRB->set_active(true); + break; + + default: + SAL_WARN( "cui.options", "SvxCTLOptionsPage::Reset(): invalid movement enum" ); + } + + sal_uInt16 nPos = static_cast(aCTLOptions.GetCTLTextNumerals()); + DBG_ASSERT( nPos < m_xNumeralsLB->get_count(), "SvxCTLOptionsPage::Reset(): invalid numerals enum" ); + m_xNumeralsLB->set_active(nPos); + + m_xSequenceCheckingCB->save_state(); + m_xRestrictedCB->save_state(); + m_xTypeReplaceCB->save_state(); + m_xMovementLogicalRB->save_state(); + m_xMovementVisualRB->save_state(); + m_xNumeralsLB->save_value(); + + bool bIsSequenceChecking = m_xSequenceCheckingCB->get_active(); + m_xRestrictedCB->set_sensitive( bIsSequenceChecking ); + m_xTypeReplaceCB->set_sensitive( bIsSequenceChecking ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/optctl.hxx b/cui/source/options/optctl.hxx new file mode 100644 index 000000000..5f8e807b1 --- /dev/null +++ b/cui/source/options/optctl.hxx @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_OPTIONS_OPTCTL_HXX +#define INCLUDED_CUI_SOURCE_OPTIONS_OPTCTL_HXX + +#include + +// class SvxCTLOptionsPage ----------------------------------------------------- + +class SvxCTLOptionsPage : public SfxTabPage +{ +private: + std::unique_ptr m_xSequenceCheckingCB; + std::unique_ptr m_xRestrictedCB; + std::unique_ptr m_xTypeReplaceCB; + std::unique_ptr m_xMovementLogicalRB; + std::unique_ptr m_xMovementVisualRB; + std::unique_ptr m_xNumeralsLB; + + DECL_LINK( SequenceCheckingCB_Hdl, weld::Button&, void ); + +public: + SvxCTLOptionsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + virtual ~SvxCTLOptionsPage() override; + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet ); + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; +}; + +#endif // INCLUDED_CUI_SOURCE_OPTIONS_OPTCTL_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/optdict.cxx b/cui/source/options/optdict.cxx new file mode 100644 index 000000000..58ccf42e3 --- /dev/null +++ b/cui/source/options/optdict.cxx @@ -0,0 +1,773 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::linguistic2; +using namespace linguistic; + +// static function ------------------------------------------------------- + +static OUString getNormDicEntry_Impl(const OUString &rText) +{ + OUString aTmp(comphelper::string::stripEnd(rText, '.')); + // non-standard hyphenation + if (aTmp.indexOf('[') > -1) + { + OUStringBuffer aTmp2 ( aTmp.getLength() ); + bool bSkip = false; + for (sal_Int32 i = 0; i < aTmp.getLength(); i++) + { + sal_Unicode cTmp = aTmp[i]; + if (cTmp == '[') + bSkip = true; + else if (!bSkip) + aTmp2.append( cTmp ); + else if (cTmp == ']') + bSkip = false; + } + aTmp = aTmp2.makeStringAndClear(); + } + return aTmp.replaceAll("=", ""); +} + +namespace { + +// Compare Dictionary Entry result +enum CDE_RESULT { CDE_EQUAL, CDE_SIMILAR, CDE_DIFFERENT }; + +} + +static CDE_RESULT cmpDicEntry_Impl( const OUString &rText1, const OUString &rText2 ) +{ + CDE_RESULT eRes = CDE_DIFFERENT; + + if (rText1 == rText2) + eRes = CDE_EQUAL; + else + { // similar = equal up to trailing '.' and hyphenation positions + // marked with '=' and '[' + alternative spelling pattern + ']' + if (getNormDicEntry_Impl( rText1 ) == getNormDicEntry_Impl( rText2 )) + eRes = CDE_SIMILAR; + } + + return eRes; +} + +// class SvxNewDictionaryDialog ------------------------------------------- + +SvxNewDictionaryDialog::SvxNewDictionaryDialog(weld::Window* pParent) + : GenericDialogController(pParent, "cui/ui/optnewdictionarydialog.ui", "OptNewDictionaryDialog") + , m_xNameEdit(m_xBuilder->weld_entry("nameedit")) + , m_xLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box("language"))) + , m_xExceptBtn(m_xBuilder->weld_check_button("except")) + , m_xOKBtn(m_xBuilder->weld_button("ok")) +{ + // Prevent creation of dictionary without a name. + m_xOKBtn->set_sensitive(false); + + // install handler + m_xNameEdit->connect_changed(LINK(this, SvxNewDictionaryDialog, ModifyHdl_Impl)); + m_xOKBtn->connect_clicked(LINK(this, SvxNewDictionaryDialog, OKHdl_Impl)); + + // display languages + m_xLanguageLB->SetLanguageList(SvxLanguageListFlags::ALL, true, true); + m_xLanguageLB->set_active(0); +} + +IMPL_LINK_NOARG(SvxNewDictionaryDialog, OKHdl_Impl, weld::Button&, void) +{ + + // add extension for personal dictionaries + OUString sDict = comphelper::string::stripEnd(m_xNameEdit->get_text(), ' ') + ".dic"; + + Reference< XSearchableDictionaryList > xDicList( LinguMgr::GetDictionaryList() ); + + Sequence< Reference< XDictionary > > aDics; + if (xDicList.is()) + aDics = xDicList->getDictionaries(); + const Reference< XDictionary > *pDic = aDics.getConstArray(); + sal_Int32 nCount = aDics.getLength(); + + bool bFound = false; + sal_Int32 i; + for (i = 0; !bFound && i < nCount; ++i ) + if ( sDict.equalsIgnoreAsciiCase( pDic[i]->getName()) ) + bFound = true; + + if ( sDict.indexOf("/") != -1 || sDict.indexOf("\\") != -1 ) + { + // Detected an invalid character. + std::unique_ptr xInfoBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Info, VclButtonsType::Ok, + CuiResId(RID_SVXSTR_OPT_INVALID_DICT_NAME))); + xInfoBox->run(); + m_xNameEdit->grab_focus(); + return; + } + + if ( bFound ) + { + // duplicate names? + std::unique_ptr xInfoBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Info, VclButtonsType::Ok, + CuiResId(RID_SVXSTR_OPT_DOUBLE_DICTS))); + xInfoBox->run(); + m_xNameEdit->grab_focus(); + return; + } + + // create and add + LanguageType nLang = m_xLanguageLB->get_active_id(); + try + { + // create new dictionary + DictionaryType eType = m_xExceptBtn->get_active() ? + DictionaryType_NEGATIVE : DictionaryType_POSITIVE; + if (xDicList.is()) + { + lang::Locale aLocale( LanguageTag::convertToLocale(nLang) ); + OUString aURL( linguistic::GetWritableDictionaryURL( sDict ) ); + m_xNewDic = xDicList->createDictionary(sDict, aLocale, eType, aURL); + m_xNewDic->setActive(true); + } + DBG_ASSERT(m_xNewDic.is(), "NULL pointer"); + } + catch(...) + { + m_xNewDic = nullptr; + // error: couldn't create new dictionary + SfxErrorContext aContext( ERRCTX_SVX_LINGU_DICTIONARY, OUString(), + m_xDialog.get(), RID_SVXERRCTX, SvxResLocale() ); + ErrorHandler::HandleError( *new StringErrorInfo( + ERRCODE_SVX_LINGU_DICT_NOTWRITEABLE, sDict ) ); + m_xDialog->response(RET_CANCEL); + } + + if (xDicList.is() && m_xNewDic.is()) + { + xDicList->addDictionary(m_xNewDic); + + // refresh list of dictionaries + //! dictionaries may have been added/removed elsewhere too. + aDics = xDicList->getDictionaries(); + } + + m_xDialog->response(RET_OK); +} + +IMPL_LINK_NOARG(SvxNewDictionaryDialog, ModifyHdl_Impl, weld::Entry&, void) +{ + m_xOKBtn->set_sensitive(!m_xNameEdit->get_text().isEmpty()); +} + +// class SvxEditDictionaryDialog ------------------------------------------- + +SvxEditDictionaryDialog::SvxEditDictionaryDialog(weld::Window* pParent, const OUString& rName) + : GenericDialogController(pParent, "cui/ui/editdictionarydialog.ui", "EditDictionaryDialog") + , sModify(CuiResId(STR_MODIFY)) + , bFirstSelect(false) + , bDoNothing(false) + , bDicIsReadonly(false) + , m_xAllDictsLB(m_xBuilder->weld_combo_box("book")) + , m_xLangFT(m_xBuilder->weld_label("lang_label")) + , m_xLangLB(new SvxLanguageBox(m_xBuilder->weld_combo_box("lang"))) + , m_xWordED(m_xBuilder->weld_entry("word")) + , m_xReplaceFT(m_xBuilder->weld_label("replace_label")) + , m_xReplaceED(m_xBuilder->weld_entry("replace")) + , m_xSingleColumnLB(m_xBuilder->weld_tree_view("words")) + , m_xDoubleColumnLB(m_xBuilder->weld_tree_view("replaces")) + , m_xNewReplacePB(m_xBuilder->weld_button("newreplace")) + , m_xDeletePB(m_xBuilder->weld_button("delete")) +{ + sReplaceFT_Text = m_xReplaceFT->get_label(); + m_xSingleColumnLB->set_size_request(-1, m_xSingleColumnLB->get_height_rows(8)); + m_xDoubleColumnLB->set_size_request(-1, m_xDoubleColumnLB->get_height_rows(8)); + m_pWordsLB = m_xDoubleColumnLB.get(); + m_xSingleColumnLB->hide(); + + //set to max of both sizes to avoid resizes + sNew = m_xNewReplacePB->get_label(); + auto nNewWidth = m_xNewReplacePB->get_preferred_size().Width(); + m_xNewReplacePB->set_label(sModify); + auto nReplaceWidth = m_xNewReplacePB->get_preferred_size().Width(); + m_xNewReplacePB->set_label(sNew); + m_xNewReplacePB->set_size_request(std::max(nNewWidth, nReplaceWidth), -1); + + if (LinguMgr::GetDictionaryList().is()) + aDics = LinguMgr::GetDictionaryList()->getDictionaries(); + + m_xSingleColumnLB->connect_changed(LINK(this, SvxEditDictionaryDialog, SelectHdl)); + m_xDoubleColumnLB->connect_changed(LINK(this, SvxEditDictionaryDialog, SelectHdl)); + + std::vector aWidths; + aWidths.push_back(m_xDoubleColumnLB->get_approximate_digit_width() * 22); + m_xDoubleColumnLB->set_column_fixed_widths(aWidths); + + // install handler + m_xNewReplacePB->connect_clicked( + LINK( this, SvxEditDictionaryDialog, NewDelButtonHdl)); + m_xDeletePB->connect_clicked( + LINK( this, SvxEditDictionaryDialog, NewDelButtonHdl)); + + m_xLangLB->connect_changed( + LINK( this, SvxEditDictionaryDialog, SelectLangHdl_Impl ) ); + m_xAllDictsLB->connect_changed( + LINK( this, SvxEditDictionaryDialog, SelectBookHdl_Impl ) ); + + m_xWordED->connect_changed(LINK(this, SvxEditDictionaryDialog, ModifyHdl)); + m_xReplaceED->connect_changed(LINK(this, SvxEditDictionaryDialog, ModifyHdl)); + m_xWordED->connect_activate(LINK(this, SvxEditDictionaryDialog, NewDelActionHdl)); + m_xReplaceED->connect_activate(LINK(this, SvxEditDictionaryDialog, NewDelActionHdl)); + + // fill listbox with all available WB's + const Reference< XDictionary > *pDic = aDics.getConstArray(); + sal_Int32 nCount = aDics.getLength(); + + OUString aLookUpEntry; + for ( sal_Int32 i = 0; i < nCount; ++i ) + { + Reference< XDictionary > xDic = pDic[i]; + if (xDic.is()) + { + bool bNegative = xDic->getDictionaryType() == DictionaryType_NEGATIVE; + OUString aDicName( xDic->getName() ); + const OUString aTxt( ::GetDicInfoStr( aDicName, + LanguageTag( xDic->getLocale() ).getLanguageType(), bNegative ) ); + m_xAllDictsLB->append_text(aTxt); + + if (rName == aDicName) + aLookUpEntry = aTxt; + } + } + + m_xLangLB->SetLanguageList( SvxLanguageListFlags::ALL, true, true ); + + Link aLink = LINK(this, SvxEditDictionaryDialog, InsertTextHdl); + m_xReplaceED->connect_insert_text(aLink); + m_xWordED->connect_insert_text(aLink); + + if ( nCount > 0 ) + { + m_xAllDictsLB->set_active_text(aLookUpEntry); + int nPos = m_xAllDictsLB->get_active(); + + if (nPos == -1) + { + nPos = 0; + m_xAllDictsLB->set_active(nPos); + } + Reference< XDictionary > xDic; + if (nPos != -1) + xDic = aDics[ nPos ]; + if (xDic.is()) + SetLanguage_Impl( LanguageTag( xDic->getLocale() ).getLanguageType() ); + + // check if dictionary is read-only + SetDicReadonly_Impl(xDic); + bool bEnable = !IsDicReadonly_Impl(); + m_xNewReplacePB->set_sensitive( false ); + m_xDeletePB->set_sensitive( false ); + m_xLangFT->set_sensitive( bEnable ); + m_xLangLB->set_sensitive( bEnable ); + ShowWords_Impl( nPos ); + } + else + { + m_xNewReplacePB->set_sensitive(false); + m_xDeletePB->set_sensitive(false); + } + + m_xWordED->connect_size_allocate(LINK(this, SvxEditDictionaryDialog, EntrySizeAllocHdl)); + m_xReplaceED->connect_size_allocate(LINK(this, SvxEditDictionaryDialog, EntrySizeAllocHdl)); +} + +IMPL_LINK_NOARG(SvxEditDictionaryDialog, EntrySizeAllocHdl, const Size&, void) +{ + std::vector aWidths; + int x, y, width, height; + if (m_xReplaceED->get_extents_relative_to(*m_pWordsLB, x, y, width, height)) + { + aWidths.push_back(x); + m_xDoubleColumnLB->set_column_fixed_widths(aWidths); + } +} + +SvxEditDictionaryDialog::~SvxEditDictionaryDialog() +{ +} + +void SvxEditDictionaryDialog::SetDicReadonly_Impl( + Reference< XDictionary > const &xDic ) +{ + // enable or disable new and delete button according to file attributes + bDicIsReadonly = true; + if (xDic.is()) + { + Reference< frame::XStorable > xStor( xDic, UNO_QUERY ); + if ( !xStor.is() // non persistent dictionary + || !xStor->hasLocation() // not yet persistent + || !xStor->isReadonly() ) + { + bDicIsReadonly = false; + } + } +} + +void SvxEditDictionaryDialog::SetLanguage_Impl(LanguageType nLanguage) +{ + // select language + m_xLangLB->set_active_id(nLanguage); +} + +int SvxEditDictionaryDialog::GetLBInsertPos(const OUString &rDicWord) +{ + IntlWrapper aIntlWrapper(SvtSysLocale().GetUILanguageTag()); + const CollatorWrapper* pCollator = aIntlWrapper.getCollator(); + int j; + int nCount = m_pWordsLB->n_children(); + for (j = 0; j < nCount; ++j) + { + OUString aNormEntry( getNormDicEntry_Impl( rDicWord ) ); + sal_Int32 nCmpRes = pCollator-> + compareString( aNormEntry, getNormDicEntry_Impl( m_pWordsLB->get_text(j, 0) ) ); + if (nCmpRes < 0) + break; + } + + return j; +} + +void SvxEditDictionaryDialog::RemoveDictEntry(int nEntry) +{ + int nLBPos = m_xAllDictsLB->get_active(); + if (nEntry != -1 && nLBPos != -1) + { + OUString sTmpShort(m_pWordsLB->get_text(nEntry, 0)); + + Reference xDic = aDics.getConstArray()[nLBPos]; + if (xDic->remove(sTmpShort)) // sal_True on success + { + m_pWordsLB->remove(nEntry); + SelectHdl(*m_pWordsLB); + } + } +} + +IMPL_LINK_NOARG(SvxEditDictionaryDialog, SelectBookHdl_Impl, weld::ComboBox&, void) +{ + int nPos = m_xAllDictsLB->get_active(); + if (nPos == -1) + return; + + m_xNewReplacePB->set_sensitive( false ); + m_xDeletePB->set_sensitive( false ); + // display dictionary + ShowWords_Impl( nPos ); + // enable or disable new and delete button according to file attributes + Reference< XDictionary > const & xDic = aDics[ nPos ]; + if (xDic.is()) + SetLanguage_Impl( LanguageTag( xDic->getLocale() ).getLanguageType() ); + + SetDicReadonly_Impl(xDic); + bool bEnable = !IsDicReadonly_Impl(); + m_xLangFT->set_sensitive( bEnable ); + m_xLangLB->set_sensitive( bEnable ); +} + +IMPL_LINK_NOARG(SvxEditDictionaryDialog, SelectLangHdl_Impl, weld::ComboBox&, void) +{ + int nDicPos = m_xAllDictsLB->get_active(); + LanguageType nLang = m_xLangLB->get_active_id(); + Reference< XDictionary > const & xDic = aDics[ nDicPos ]; + LanguageType nOldLang = LanguageTag( xDic->getLocale() ).getLanguageType(); + + if ( nLang == nOldLang ) + return; + + std::unique_ptr xBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Question, VclButtonsType::YesNo, + CuiResId(RID_SVXSTR_CONFIRM_SET_LANGUAGE))); + OUString sTxt(xBox->get_primary_text()); + sTxt = sTxt.replaceFirst("%1", m_xAllDictsLB->get_active_text()); + xBox->set_primary_text(sTxt); + + if (xBox->run() == RET_YES) + { + xDic->setLocale( LanguageTag::convertToLocale( nLang ) ); + bool bNegativ = xDic->getDictionaryType() == DictionaryType_NEGATIVE; + + const OUString sName( + ::GetDicInfoStr( xDic->getName(), + LanguageTag( xDic->getLocale() ).getLanguageType(), + bNegativ ) ); + m_xAllDictsLB->remove(nDicPos); + m_xAllDictsLB->insert_text(nDicPos, sName); + m_xAllDictsLB->set_active(nDicPos); + } + else + SetLanguage_Impl( nOldLang ); +} + +void SvxEditDictionaryDialog::ShowWords_Impl( sal_uInt16 nId ) +{ + Reference< XDictionary > xDic = aDics.getConstArray()[ nId ]; + + weld::WaitObject aWait(m_xDialog.get()); + + m_xWordED->set_text(OUString()); + m_xReplaceED->set_text(OUString()); + + bool bIsNegative = xDic->getDictionaryType() != DictionaryType_POSITIVE; + bool bLangNone = LanguageTag( + xDic->getLocale() ).getLanguageType() == LANGUAGE_NONE; + + // The label is "Replace By" only in negative dictionaries (forbidden + // words), otherwise "Grammar By" in language-specific dictionaries + // (where the optional second word is the sample word for + // the Hunspell based affixation/compounding of the new dictionary word) + if (bIsNegative) + { + m_xReplaceFT->set_label(sReplaceFT_Text); + } else if (!bLangNone) { + m_xReplaceFT->set_label(CuiResId(RID_SVXSTR_OPT_GRAMMAR_BY)); + } + + if(bIsNegative || !bLangNone) + { + // make controls for replacement text active + if (!m_xReplaceFT->get_visible()) + { + m_xReplaceFT->show(); + m_xReplaceED->show(); + m_xSingleColumnLB->hide(); + m_xDoubleColumnLB->show(); + m_pWordsLB = m_xDoubleColumnLB.get(); + } + } + else + { + // deactivate controls for replacement text + if (m_xReplaceFT->get_visible()) + { + m_xReplaceFT->hide(); + m_xReplaceED->hide(); + m_xDoubleColumnLB->hide(); + m_xSingleColumnLB->show(); + m_pWordsLB = m_xSingleColumnLB.get(); + } + } + + m_pWordsLB->clear(); + + Sequence< Reference< XDictionaryEntry > > aEntries( xDic->getEntries() ); + const Reference< XDictionaryEntry > *pEntry = aEntries.getConstArray(); + sal_Int32 nCount = aEntries.getLength(); + std::vector aSortedDicEntries; + aSortedDicEntries.reserve(nCount); + for (sal_Int32 i = 0; i < nCount; i++) + { + OUString aStr = pEntry[i]->getDictionaryWord(); + if(!pEntry[i]->getReplacementText().isEmpty()) + { + aStr += "\t" + pEntry[i]->getReplacementText(); + } + aSortedDicEntries.push_back(aStr); + } + + IntlWrapper aIntlWrapper(SvtSysLocale().GetUILanguageTag()); + const CollatorWrapper* pCollator = aIntlWrapper.getCollator(); + std::sort(aSortedDicEntries.begin(), aSortedDicEntries.end(), + [&] (OUString const & lhs, OUString const & rhs) + { + sal_Int32 nCmpRes = pCollator-> + compareString( getNormDicEntry_Impl(lhs), getNormDicEntry_Impl( rhs ) ); + return nCmpRes < 0; + }); + + m_pWordsLB->freeze(); // speed up insert + int nRow = 0; + for (OUString const & rStr : aSortedDicEntries) + { + m_pWordsLB->append_text(rStr.getToken(0, '\t')); + if (m_pWordsLB == m_xDoubleColumnLB.get()) + { + OUString sReplace = rStr.getToken(1, '\t'); + m_pWordsLB->set_text(nRow, sReplace, 1); + ++nRow; + } + } + m_pWordsLB->thaw(); + + if (m_pWordsLB->n_children()) + { + m_pWordsLB->select(0); + m_pWordsLB->set_cursor(0); + SelectHdl(*m_pWordsLB); + } +} + +IMPL_LINK(SvxEditDictionaryDialog, SelectHdl, weld::TreeView&, rBox, void) +{ + if (bDoNothing) + return; + + int nEntry = rBox.get_selected_index(); + + if(!bFirstSelect) + { + if (nEntry != -1) + { + OUString sTmpShort(rBox.get_text(nEntry, 0)); + // without this the cursor is always at the beginning of a word, if the text + // is set over the ModifyHdl, although you're editing there at the moment + if (m_xWordED->get_text() != sTmpShort) + m_xWordED->set_text(sTmpShort); + if (&rBox == m_xDoubleColumnLB.get()) + m_xReplaceED->set_text(rBox.get_text(nEntry, 1)); + } + } + else + bFirstSelect = false; + + // entries in the list box should exactly correspond to those from the + // dictionary. Thus: + m_xNewReplacePB->set_sensitive(false); + m_xDeletePB->set_sensitive(nEntry != -1 && !IsDicReadonly_Impl()); +} + +IMPL_LINK(SvxEditDictionaryDialog, NewDelButtonHdl, weld::Button&, rBtn, void) +{ + NewDelHdl(&rBtn); +} + +IMPL_LINK(SvxEditDictionaryDialog, NewDelActionHdl, weld::Entry&, rDictEdit, bool) +{ + return NewDelHdl(&rDictEdit); +} + +bool SvxEditDictionaryDialog::NewDelHdl(const weld::Widget* pBtn) +{ + if (pBtn == m_xDeletePB.get()) + { + OUString aStr; + + m_xWordED->set_text(aStr); + m_xReplaceED->set_text(aStr); + m_xDeletePB->set_sensitive(false); + + int nEntry = m_pWordsLB->get_selected_index(); + RemoveDictEntry(nEntry); // remove entry from dic and list-box + } + if (pBtn == m_xNewReplacePB.get() || m_xNewReplacePB->get_sensitive()) + { + int nEntry = m_pWordsLB->get_selected_index(); + OUString aNewWord(m_xWordED->get_text()); + OUString sEntry(aNewWord); + OUString aReplaceStr(m_xReplaceED->get_text()); + + DictionaryError nAddRes = DictionaryError::UNKNOWN; + int nPos = m_xAllDictsLB->get_active(); + if (nPos != -1 && !aNewWord.isEmpty()) + { + DBG_ASSERT(nPos < aDics.getLength(), "invalid dictionary index"); + Reference< XDictionary > const & xDic = aDics[ nPos ]; + if (xDic.is()) + { + // make changes in dic + + bool bIsNegEntry = xDic->getDictionaryType() == DictionaryType_NEGATIVE; + + OUString aRplcText; + if(!aReplaceStr.isEmpty()) + aRplcText = aReplaceStr; + + if (nEntry != -1) // entry selected in m_pWordsLB ie action = modify entry + xDic->remove(m_pWordsLB->get_text(nEntry, 0)); + // if remove has failed the following add should fail too + // and thus a warning message should be triggered... + + nAddRes = linguistic::AddEntryToDic( xDic, + aNewWord, bIsNegEntry, + aRplcText, false ); + } + } + if (DictionaryError::NONE != nAddRes) + SvxDicError(m_xDialog.get(), nAddRes); + + if (DictionaryError::NONE == nAddRes && !sEntry.isEmpty()) + { + // insert new entry in list-box etc... + m_pWordsLB->freeze(); + + if (nEntry != -1) // entry selected in m_pWordsLB ie action = modify entry + { + m_pWordsLB->set_text(nEntry, sEntry); + if (!aReplaceStr.isEmpty()) + m_pWordsLB->set_text(nEntry, aReplaceStr, 1); + } + else + { + nEntry = GetLBInsertPos(aNewWord); + m_pWordsLB->insert_text(nEntry, sEntry); + if(!aReplaceStr.isEmpty()) + m_pWordsLB->set_text(nEntry, aReplaceStr, 1); + } + + m_pWordsLB->thaw(); + m_pWordsLB->scroll_to_row(nEntry); + + // if the request came from the ReplaceEdit, give focus to the ShortEdit + if (m_xReplaceED->has_focus()) + m_xWordED->grab_focus(); + } + } + else + { + // this can only be an enter in one of the two edit fields + // which means EndDialog() - has to be evaluated in KeyInput + return false; + } + ModifyHdl(*m_xWordED); + return true; +} + +IMPL_LINK(SvxEditDictionaryDialog, ModifyHdl, weld::Entry&, rEdt, void) +{ + OUString rEntry = rEdt.get_text(); + + sal_Int32 nWordLen = rEntry.getLength(); + const OUString& rRepString = m_xReplaceED->get_text(); + + bool bEnableNewReplace = false; + bool bEnableDelete = false; + OUString aNewReplaceText = sNew; + + if (&rEdt == m_xWordED.get()) + { + if(nWordLen>0) + { + bool bFound = false; + bool bTmpSelEntry=false; + CDE_RESULT eCmpRes = CDE_DIFFERENT; + + bool bDoubleColumn = m_pWordsLB == m_xDoubleColumnLB.get(); + + for (int i = 0, nCount = m_pWordsLB->n_children(); i < nCount; ++i) + { + OUString aTestStr(m_pWordsLB->get_text(i, 0)); + eCmpRes = cmpDicEntry_Impl( rEntry, aTestStr ); + if(CDE_DIFFERENT != eCmpRes) + { + if(!rRepString.isEmpty()) + bFirstSelect = true; + bDoNothing=true; + m_pWordsLB->set_cursor(i); + bDoNothing=false; + if (bDoubleColumn) + m_xReplaceED->set_text(m_pWordsLB->get_text(i, 1)); + + if (CDE_SIMILAR == eCmpRes) + { + aNewReplaceText = sModify; + bEnableNewReplace = true; + } + bFound= true; + break; + } + else if(getNormDicEntry_Impl(aTestStr).indexOf( + getNormDicEntry_Impl( rEntry ) ) == 0 + && !bTmpSelEntry) + { + bDoNothing=true; + m_pWordsLB->scroll_to_row(i); + bDoNothing=false; + bTmpSelEntry=true; + + aNewReplaceText = sNew; + bEnableNewReplace = true; + } + } + + if(!bFound) + { + m_pWordsLB->unselect_all(); + aNewReplaceText = sNew; + bEnableNewReplace = true; + } + bEnableDelete = CDE_DIFFERENT != eCmpRes; + } + else if (m_pWordsLB->n_children() > 0) + { + bDoNothing=true; + m_pWordsLB->scroll_to_row(0); + bDoNothing=false; + } + } + else if(&rEdt == m_xReplaceED.get()) + { + OUString aReplaceText; + OUString aWordText; + int nFirstSel = m_pWordsLB->get_selected_index(); + if (nFirstSel != -1) // a m_pWordsLB entry is selected + { + aWordText = m_pWordsLB->get_text(nFirstSel, 0); + aReplaceText = m_pWordsLB->get_text(nFirstSel, 1); + + aNewReplaceText = sModify; + bEnableDelete = true; + } + bool bIsChange = + CDE_EQUAL != cmpDicEntry_Impl(m_xWordED->get_text(), aWordText) + || CDE_EQUAL != cmpDicEntry_Impl(m_xReplaceED->get_text(), aReplaceText); + if (!m_xWordED->get_text().isEmpty() && bIsChange) + bEnableNewReplace = true; + } + + m_xNewReplacePB->set_label(aNewReplaceText); + m_xNewReplacePB->set_sensitive(bEnableNewReplace && !IsDicReadonly_Impl()); + m_xDeletePB->set_sensitive(bEnableDelete && !IsDicReadonly_Impl()); +} + +IMPL_STATIC_LINK(SvxEditDictionaryDialog, InsertTextHdl, OUString&, rText, bool) +{ + rText = rText.replaceAll(" ", ""); + return true; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/optfltr.cxx b/cui/source/options/optfltr.cxx new file mode 100644 index 000000000..5708f14a3 --- /dev/null +++ b/cui/source/options/optfltr.cxx @@ -0,0 +1,344 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include "optfltr.hxx" +#include +#include + +enum class MSFltrPg2_CheckBoxEntries { + Math, + Writer, + Calc, + Impress, + SmartArt, + Visio, + PDF, + InvalidCBEntry +}; + + +OfaMSFilterTabPage::OfaMSFilterTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/optfltrpage.ui", "OptFltrPage", &rSet) + , m_xWBasicCodeCB(m_xBuilder->weld_check_button("wo_basic")) + , m_xWBasicWbctblCB(m_xBuilder->weld_check_button("wo_exec")) + , m_xWBasicStgCB(m_xBuilder->weld_check_button("wo_saveorig")) + , m_xEBasicCodeCB(m_xBuilder->weld_check_button("ex_basic")) + , m_xEBasicExectblCB(m_xBuilder->weld_check_button("ex_exec")) + , m_xEBasicStgCB(m_xBuilder->weld_check_button("ex_saveorig")) + , m_xPBasicCodeCB(m_xBuilder->weld_check_button("pp_basic")) + , m_xPBasicStgCB(m_xBuilder->weld_check_button("pp_saveorig")) +{ + m_xWBasicCodeCB->connect_clicked( LINK( this, OfaMSFilterTabPage, LoadWordBasicCheckHdl_Impl ) ); + m_xEBasicCodeCB->connect_clicked( LINK( this, OfaMSFilterTabPage, LoadExcelBasicCheckHdl_Impl ) ); +} + +OfaMSFilterTabPage::~OfaMSFilterTabPage() +{ +} + +IMPL_LINK_NOARG(OfaMSFilterTabPage, LoadWordBasicCheckHdl_Impl, weld::Button&, void) +{ + m_xWBasicWbctblCB->set_sensitive(m_xWBasicCodeCB->get_active()); +} + +IMPL_LINK_NOARG(OfaMSFilterTabPage, LoadExcelBasicCheckHdl_Impl, weld::Button&, void) +{ + m_xEBasicExectblCB->set_sensitive(m_xEBasicCodeCB->get_active()); +} + +std::unique_ptr OfaMSFilterTabPage::Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet ) +{ + return std::make_unique(pPage, pController, *rAttrSet); +} + +bool OfaMSFilterTabPage::FillItemSet( SfxItemSet* ) +{ + SvtFilterOptions& rOpt = SvtFilterOptions::Get(); + + if( m_xWBasicCodeCB->get_state_changed_from_saved() ) + rOpt.SetLoadWordBasicCode( m_xWBasicCodeCB->get_active() ); + if( m_xWBasicWbctblCB->get_state_changed_from_saved() ) + rOpt.SetLoadWordBasicExecutable( m_xWBasicWbctblCB->get_active() ); + if( m_xWBasicStgCB->get_state_changed_from_saved() ) + rOpt.SetLoadWordBasicStorage( m_xWBasicStgCB->get_active() ); + + if( m_xEBasicCodeCB->get_state_changed_from_saved()) + rOpt.SetLoadExcelBasicCode( m_xEBasicCodeCB->get_active() ); + if( m_xEBasicExectblCB->get_state_changed_from_saved()) + rOpt.SetLoadExcelBasicExecutable( m_xEBasicExectblCB->get_active() ); + if( m_xEBasicStgCB->get_state_changed_from_saved()) + rOpt.SetLoadExcelBasicStorage( m_xEBasicStgCB->get_active() ); + + if( m_xPBasicCodeCB->get_state_changed_from_saved()) + rOpt.SetLoadPPointBasicCode( m_xPBasicCodeCB->get_active() ); + if( m_xPBasicStgCB->get_state_changed_from_saved()) + rOpt.SetLoadPPointBasicStorage( m_xPBasicStgCB->get_active() ); + + return false; +} + +void OfaMSFilterTabPage::Reset( const SfxItemSet* ) +{ + const SvtFilterOptions& rOpt = SvtFilterOptions::Get(); + + m_xWBasicCodeCB->set_active( rOpt.IsLoadWordBasicCode() ); + m_xWBasicCodeCB->save_state(); + m_xWBasicWbctblCB->set_active( rOpt.IsLoadWordBasicExecutable() ); + m_xWBasicWbctblCB->save_state(); + m_xWBasicStgCB->set_active( rOpt.IsLoadWordBasicStorage() ); + m_xWBasicStgCB->save_state(); + LoadWordBasicCheckHdl_Impl( *m_xWBasicCodeCB ); + + m_xEBasicCodeCB->set_active( rOpt.IsLoadExcelBasicCode() ); + m_xEBasicCodeCB->save_state(); + m_xEBasicExectblCB->set_active( rOpt.IsLoadExcelBasicExecutable() ); + m_xEBasicExectblCB->save_state(); + m_xEBasicStgCB->set_active( rOpt.IsLoadExcelBasicStorage() ); + m_xEBasicStgCB->save_state(); + LoadExcelBasicCheckHdl_Impl( *m_xEBasicCodeCB ); + + m_xPBasicCodeCB->set_active( rOpt.IsLoadPPointBasicCode() ); + m_xPBasicCodeCB->save_state(); + m_xPBasicStgCB->set_active( rOpt.IsLoadPPointBasicStorage() ); + m_xPBasicStgCB->save_state(); +} + +OfaMSFilterTabPage2::OfaMSFilterTabPage2(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/optfltrembedpage.ui", "OptFilterPage", &rSet) + , sChgToFromMath(CuiResId(RID_SVXSTR_CHG_MATH)) + , sChgToFromWriter(CuiResId(RID_SVXSTR_CHG_WRITER)) + , sChgToFromCalc(CuiResId(RID_SVXSTR_CHG_CALC)) + , sChgToFromImpress(CuiResId(RID_SVXSTR_CHG_IMPRESS)) + , sChgToFromSmartArt(CuiResId(RID_SVXSTR_CHG_SMARTART)) + , sChgToFromVisio(CuiResId(RID_SVXSTR_CHG_VISIO)) + , sChgToFromPDF(CuiResId(RID_SVXSTR_CHG_PDF)) + , m_xCheckLB(m_xBuilder->weld_tree_view("checklbcontainer")) + , m_xHighlightingRB(m_xBuilder->weld_radio_button("highlighting")) + , m_xShadingRB(m_xBuilder->weld_radio_button("shading")) + , m_xMSOLockFileCB(m_xBuilder->weld_check_button("mso_lockfile")) +{ + std::vector aWidths; + aWidths.push_back(m_xCheckLB->get_checkbox_column_width()); + aWidths.push_back(m_xCheckLB->get_checkbox_column_width()); + m_xCheckLB->set_column_fixed_widths(aWidths); +} + +OfaMSFilterTabPage2::~OfaMSFilterTabPage2() +{ +} + +std::unique_ptr OfaMSFilterTabPage2::Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet ) +{ + return std::make_unique( pPage, pController, *rAttrSet ); +} + +bool OfaMSFilterTabPage2::FillItemSet( SfxItemSet* ) +{ + SvtFilterOptions& rOpt = SvtFilterOptions::Get(); + + static struct ChkCBoxEntries{ + MSFltrPg2_CheckBoxEntries eType; + bool (SvtFilterOptions:: *FnIs)() const; + void (SvtFilterOptions:: *FnSet)( bool bFlag ); + } const aChkArr[] = { + { MSFltrPg2_CheckBoxEntries::Math, &SvtFilterOptions::IsMathType2Math, + &SvtFilterOptions::SetMathType2Math }, + { MSFltrPg2_CheckBoxEntries::Math, &SvtFilterOptions::IsMath2MathType, + &SvtFilterOptions::SetMath2MathType }, + { MSFltrPg2_CheckBoxEntries::Writer, &SvtFilterOptions::IsWinWord2Writer, + &SvtFilterOptions::SetWinWord2Writer }, + { MSFltrPg2_CheckBoxEntries::Writer, &SvtFilterOptions::IsWriter2WinWord, + &SvtFilterOptions::SetWriter2WinWord }, + { MSFltrPg2_CheckBoxEntries::Calc, &SvtFilterOptions::IsExcel2Calc, + &SvtFilterOptions::SetExcel2Calc }, + { MSFltrPg2_CheckBoxEntries::Calc, &SvtFilterOptions::IsCalc2Excel, + &SvtFilterOptions::SetCalc2Excel }, + { MSFltrPg2_CheckBoxEntries::Impress, &SvtFilterOptions::IsPowerPoint2Impress, + &SvtFilterOptions::SetPowerPoint2Impress }, + { MSFltrPg2_CheckBoxEntries::Impress, &SvtFilterOptions::IsImpress2PowerPoint, + &SvtFilterOptions::SetImpress2PowerPoint }, + { MSFltrPg2_CheckBoxEntries::SmartArt, &SvtFilterOptions::IsSmartArt2Shape, + &SvtFilterOptions::SetSmartArt2Shape }, + { MSFltrPg2_CheckBoxEntries::Visio, &SvtFilterOptions::IsVisio2Draw, + &SvtFilterOptions::SetVisio2Draw }, + }; + + bool bFirstCol = true; + for( const ChkCBoxEntries & rEntry : aChkArr ) + { + // we loop through the list, alternating reading the first/second column, + // each row appears twice in the list (except for smartart and later entries, which are + // import only) + sal_uInt16 nCol = bFirstCol ? 0 : 1; + bFirstCol = !bFirstCol; + int nEntry = GetEntry4Type(rEntry.eType); + if (nEntry != -1) + { + bool bCheck = m_xCheckLB->get_toggle(nEntry, nCol); + if( bCheck != (rOpt.*rEntry.FnIs)() ) + (rOpt.*rEntry.FnSet)( bCheck ); + } + if (rEntry.eType == MSFltrPg2_CheckBoxEntries::SmartArt) + { + bFirstCol = !bFirstCol; + } + } + int nPDFEntry = GetEntry4Type(MSFltrPg2_CheckBoxEntries::PDF); + bool bPDFCheck = m_xCheckLB->get_toggle(nPDFEntry, 0); + if (bPDFCheck != officecfg::Office::Common::Filter::Adobe::Import::PDFToDraw::get()) + { + std::shared_ptr pBatch( + comphelper::ConfigurationChanges::create()); + officecfg::Office::Common::Filter::Adobe::Import::PDFToDraw::set(bPDFCheck, pBatch); + pBatch->commit(); + } + + if( m_xHighlightingRB->get_state_changed_from_saved() ) + { + if (m_xHighlightingRB->get_active()) + rOpt.SetCharBackground2Highlighting(); + else + rOpt.SetCharBackground2Shading(); + } + + if (m_xMSOLockFileCB->get_state_changed_from_saved()) + { + rOpt.EnableMSOLockFileCreation(m_xMSOLockFileCB->get_active()); + } + + return true; +} + +void OfaMSFilterTabPage2::Reset( const SfxItemSet* ) +{ + SvtFilterOptions& rOpt = SvtFilterOptions::Get(); + + m_xCheckLB->freeze(); + m_xCheckLB->clear(); + + SvtModuleOptions aModuleOpt; + + // int the same sequence as the enums of MSFltrPg2_CheckBoxEntries + if ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::MATH ) ) + InsertEntry( sChgToFromMath, MSFltrPg2_CheckBoxEntries::Math ); + if ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::WRITER ) ) + InsertEntry( sChgToFromWriter, MSFltrPg2_CheckBoxEntries::Writer ); + if ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::CALC ) ) + InsertEntry( sChgToFromCalc, MSFltrPg2_CheckBoxEntries::Calc ); + if ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::IMPRESS ) ) + InsertEntry( sChgToFromImpress, MSFltrPg2_CheckBoxEntries::Impress ); + InsertEntry( sChgToFromSmartArt, MSFltrPg2_CheckBoxEntries::SmartArt, false ); + if (aModuleOpt.IsModuleInstalled(SvtModuleOptions::EModule::DRAW)) + { + InsertEntry(sChgToFromVisio, MSFltrPg2_CheckBoxEntries::Visio, false); + InsertEntry(sChgToFromPDF, MSFltrPg2_CheckBoxEntries::PDF, false); + } + + static struct ChkCBoxEntries{ + MSFltrPg2_CheckBoxEntries eType; + bool (SvtFilterOptions:: *FnIs)() const; + } const aChkArr[] = { + { MSFltrPg2_CheckBoxEntries::Math, &SvtFilterOptions::IsMathType2Math }, + { MSFltrPg2_CheckBoxEntries::Math, &SvtFilterOptions::IsMath2MathType }, + { MSFltrPg2_CheckBoxEntries::Writer, &SvtFilterOptions::IsWinWord2Writer }, + { MSFltrPg2_CheckBoxEntries::Writer, &SvtFilterOptions::IsWriter2WinWord }, + { MSFltrPg2_CheckBoxEntries::Calc, &SvtFilterOptions::IsExcel2Calc }, + { MSFltrPg2_CheckBoxEntries::Calc, &SvtFilterOptions::IsCalc2Excel }, + { MSFltrPg2_CheckBoxEntries::Impress, &SvtFilterOptions::IsPowerPoint2Impress }, + { MSFltrPg2_CheckBoxEntries::Impress, &SvtFilterOptions::IsImpress2PowerPoint }, + { MSFltrPg2_CheckBoxEntries::SmartArt, &SvtFilterOptions::IsSmartArt2Shape }, + { MSFltrPg2_CheckBoxEntries::Visio, &SvtFilterOptions::IsVisio2Draw }, + { MSFltrPg2_CheckBoxEntries::PDF, nullptr }, + }; + + bool bFirstCol = true; + for( const ChkCBoxEntries & rArr : aChkArr ) + { + // we loop through the list, alternating reading the first/second column, + // each row appears twice in the list (except for smartart and later entries, which are + // import only) + sal_uInt16 nCol = bFirstCol ? 0 : 1; + bFirstCol = !bFirstCol; + int nEntry = GetEntry4Type( rArr.eType ); + if (nEntry != -1) + { + bool bCheck = false; + if (rArr.eType != MSFltrPg2_CheckBoxEntries::PDF) + { + bCheck = (rOpt.*rArr.FnIs)(); + } + else + { + bCheck = officecfg::Office::Common::Filter::Adobe::Import::PDFToDraw::get(); + nCol = 0; + } + m_xCheckLB->set_toggle(nEntry, bCheck ? TRISTATE_TRUE : TRISTATE_FALSE, nCol); + } + if (rArr.eType == MSFltrPg2_CheckBoxEntries::SmartArt) + { + bFirstCol = !bFirstCol; + } + } + m_xCheckLB->thaw(); + + if (rOpt.IsCharBackground2Highlighting()) + m_xHighlightingRB->set_active(true); + else + m_xShadingRB->set_active(true); + + m_xHighlightingRB->save_state(); + + m_xMSOLockFileCB->set_active(rOpt.IsMSOLockFileCreationIsEnabled()); + m_xMSOLockFileCB->save_state(); + m_xMSOLockFileCB->set_sensitive(!officecfg::Office::Common::Filter::Microsoft::Import::CreateMSOLockFiles::isReadOnly()); +} + +void OfaMSFilterTabPage2::InsertEntry( const OUString& _rTxt, MSFltrPg2_CheckBoxEntries _nType ) +{ + InsertEntry( _rTxt, _nType, true ); +} + +void OfaMSFilterTabPage2::InsertEntry( const OUString& _rTxt, MSFltrPg2_CheckBoxEntries _nType, + bool saveEnabled ) +{ + int nPos = m_xCheckLB->n_children(); + m_xCheckLB->append(); + m_xCheckLB->set_toggle(nPos, TRISTATE_FALSE, 0); + if (saveEnabled) + m_xCheckLB->set_toggle(nPos, TRISTATE_FALSE, 1); + m_xCheckLB->set_text(nPos, _rTxt, 2); + m_xCheckLB->set_id(nPos, OUString::number(static_cast(_nType))); +} + +int OfaMSFilterTabPage2::GetEntry4Type( MSFltrPg2_CheckBoxEntries _nType ) const +{ + for (int i = 0, nEntryCount = m_xCheckLB->n_children(); i < nEntryCount; ++i) + { + if (_nType == static_cast(m_xCheckLB->get_id(i).toInt32())) + return i; + } + return -1; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/optfltr.hxx b/cui/source/options/optfltr.hxx new file mode 100644 index 000000000..efc956843 --- /dev/null +++ b/cui/source/options/optfltr.hxx @@ -0,0 +1,83 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_OPTIONS_OPTFLTR_HXX +#define INCLUDED_CUI_SOURCE_OPTIONS_OPTFLTR_HXX + +#include + +class OfaMSFilterTabPage : public SfxTabPage +{ + std::unique_ptr m_xWBasicCodeCB; + std::unique_ptr m_xWBasicWbctblCB; + std::unique_ptr m_xWBasicStgCB; + std::unique_ptr m_xEBasicCodeCB; + std::unique_ptr m_xEBasicExectblCB; + std::unique_ptr m_xEBasicStgCB; + std::unique_ptr m_xPBasicCodeCB; + std::unique_ptr m_xPBasicStgCB; + + DECL_LINK(LoadWordBasicCheckHdl_Impl, weld::Button&, void); + DECL_LINK(LoadExcelBasicCheckHdl_Impl, weld::Button&, void); +public: + OfaMSFilterTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet ); + virtual ~OfaMSFilterTabPage() override; + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet ); + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; +}; + +enum class MSFltrPg2_CheckBoxEntries; + +class OfaMSFilterTabPage2 : public SfxTabPage +{ + OUString sChgToFromMath, + sChgToFromWriter, + sChgToFromCalc, + sChgToFromImpress, + sChgToFromSmartArt, + sChgToFromVisio, + sChgToFromPDF; + + std::unique_ptr m_xCheckLB; + std::unique_ptr m_xHighlightingRB; + std::unique_ptr m_xShadingRB; + std::unique_ptr m_xMSOLockFileCB; + + void InsertEntry( const OUString& _rTxt, MSFltrPg2_CheckBoxEntries _nType ); + void InsertEntry( const OUString& _rTxt, MSFltrPg2_CheckBoxEntries _nType, + bool saveEnabled ); + int GetEntry4Type( MSFltrPg2_CheckBoxEntries _nType ) const; + +public: + OfaMSFilterTabPage2(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet ); + virtual ~OfaMSFilterTabPage2() override; + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; +}; + + +#endif + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/optgdlg.cxx b/cui/source/options/optgdlg.cxx new file mode 100644 index 000000000..1972354cc --- /dev/null +++ b/cui/source/options/optgdlg.cxx @@ -0,0 +1,1897 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#if defined(_WIN32) +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if HAVE_FEATURE_BREAKPAD +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#if HAVE_FEATURE_OPENGL +#include +#endif +#include +#include "optgdlg.hxx" +#include +#include +#include +#include + +#if defined(_WIN32) +#include +#include +#include +#include +#endif +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::util; +using namespace ::utl; + +namespace svt { + +class SkiaCfg +{ +private: + bool mbUseSkia; + bool mbForceSkiaRaster; + bool mbModified; + +public: + SkiaCfg(); + ~SkiaCfg(); + + bool useSkia() const; + bool forceSkiaRaster() const; + + void setUseSkia(bool bSkia); + void setForceSkiaRaster(bool bSkia); + + void reset(); +}; + +SkiaCfg::SkiaCfg(): + mbModified(false) +{ + reset(); +} + +void SkiaCfg::reset() +{ + mbUseSkia = officecfg::Office::Common::VCL::UseSkia::get(); + mbForceSkiaRaster = officecfg::Office::Common::VCL::ForceSkiaRaster::get(); + mbModified = false; +} + +SkiaCfg::~SkiaCfg() +{ + if (!mbModified) + return; + + try + { + std::shared_ptr batch(comphelper::ConfigurationChanges::create()); + if (!officecfg::Office::Common::VCL::UseSkia::isReadOnly()) + officecfg::Office::Common::VCL::UseSkia::set(mbUseSkia, batch); + if (!officecfg::Office::Common::VCL::ForceSkiaRaster::isReadOnly()) + officecfg::Office::Common::VCL::ForceSkiaRaster::set(mbForceSkiaRaster, batch); + batch->commit(); + } + catch (...) + { + } +} + +bool SkiaCfg::useSkia() const +{ + return mbUseSkia; +} + +bool SkiaCfg::forceSkiaRaster() const +{ + return mbForceSkiaRaster; +} + +void SkiaCfg::setUseSkia(bool bSkia) +{ + if (bSkia != mbUseSkia) + { + mbUseSkia = bSkia; + mbModified = true; + } +} + +void SkiaCfg::setForceSkiaRaster(bool bSkia) +{ + if (mbForceSkiaRaster != bSkia) + { + mbForceSkiaRaster = bSkia; + mbModified = true; + } +} + +} + +// class OfaMiscTabPage -------------------------------------------------- + +DeactivateRC OfaMiscTabPage::DeactivatePage( SfxItemSet* pSet_ ) +{ + if ( pSet_ ) + FillItemSet( pSet_ ); + return DeactivateRC::LeavePage; +} + +namespace +{ +OUString impl_SystemFileOpenServiceName() +{ + #if defined(_WIN32) + return "com.sun.star.ui.dialogs.SystemFilePicker"; + #elif defined MACOSX + return "com.sun.star.ui.dialogs.AquaFilePicker"; + #else + return OUString(); + #endif +} + +bool lcl_HasSystemFilePicker() +{ + if( Application::hasNativeFileSelection() ) + return true; + + // Otherwise fall-back on querying services + bool bRet = false; + Reference< XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory(); + + Reference< XContentEnumerationAccess > xEnumAccess( xFactory, UNO_QUERY ); + Reference< XSet > xSet( xFactory, UNO_QUERY ); + + if ( ! xEnumAccess.is() || ! xSet.is() ) + return bRet; + + try + { + OUString aFileService = impl_SystemFileOpenServiceName(); + Reference< XEnumeration > xEnum = xEnumAccess->createContentEnumeration( aFileService ); + if ( xEnum.is() && xEnum->hasMoreElements() ) + bRet = true; + } + catch (const IllegalArgumentException&) + { + } + catch (const ElementExistException&) + { + } + return bRet; +} +} + +OfaMiscTabPage::OfaMiscTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/optgeneralpage.ui", "OptGeneralPage", &rSet) + , m_xExtHelpCB(m_xBuilder->weld_check_button("exthelp")) + , m_xPopUpNoHelpCB(m_xBuilder->weld_check_button("popupnohelp")) + , m_xShowTipOfTheDay(m_xBuilder->weld_check_button("cbShowTipOfTheDay")) + , m_xFileDlgFrame(m_xBuilder->weld_widget("filedlgframe")) + , m_xPrintDlgFrame(m_xBuilder->weld_widget("printdlgframe")) + , m_xFileDlgROImage(m_xBuilder->weld_widget("lockimage")) + , m_xFileDlgCB(m_xBuilder->weld_check_button("filedlg")) + , m_xPrintDlgCB(m_xBuilder->weld_check_button("printdlg")) + , m_xDocStatusCB(m_xBuilder->weld_check_button("docstatus")) + , m_xYearFrame(m_xBuilder->weld_widget("yearframe")) + , m_xYearValueField(m_xBuilder->weld_spin_button("year")) + , m_xToYearFT(m_xBuilder->weld_label("toyear")) + , m_xCollectUsageInfo(m_xBuilder->weld_check_button("collectusageinfo")) + , m_xCrashReport(m_xBuilder->weld_check_button("crashreport")) + , m_xQuickStarterFrame(m_xBuilder->weld_widget("quickstarter")) +#if defined(UNX) + , m_xQuickLaunchCB(m_xBuilder->weld_check_button("systray")) +#else + , m_xQuickLaunchCB(m_xBuilder->weld_check_button("quicklaunch")) +#endif +#if defined(_WIN32) + , m_xFileAssocFrame(m_xBuilder->weld_widget("fileassoc")) + , m_xFileAssocBtn(m_xBuilder->weld_button("assocfiles")) +#endif +{ + if (!lcl_HasSystemFilePicker()) + m_xFileDlgFrame->hide(); + else if (SvtMiscOptions().IsUseSystemFileDialogReadOnly()) + { + m_xFileDlgROImage->show(); + m_xFileDlgCB->set_sensitive(false); + } + +#if !ENABLE_GTK3 + m_xPrintDlgFrame->hide(); +#else + if (!SvtMiscOptions().IsExperimentalMode()) + { + m_xPrintDlgFrame->hide(); + } +#endif + + m_xQuickLaunchCB->show(); + + //Only available in Win or if building the gtk systray +#if !defined(_WIN32) + m_xQuickStarterFrame->hide(); +#endif + +#if defined(_WIN32) + m_xFileAssocFrame->show(); + m_xFileAssocBtn->connect_clicked(LINK(this, OfaMiscTabPage, FileAssocClick)); +#endif + + m_aStrDateInfo = m_xToYearFT->get_label(); + m_xYearValueField->connect_value_changed( LINK( this, OfaMiscTabPage, TwoFigureHdl ) ); + + SetExchangeSupport(); +} + +OfaMiscTabPage::~OfaMiscTabPage() +{ +} + +std::unique_ptr OfaMiscTabPage::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet ) +{ + return std::make_unique( pPage, pController, *rAttrSet ); +} + +bool OfaMiscTabPage::FillItemSet( SfxItemSet* rSet ) +{ + bool bModified = false; + std::shared_ptr batch(comphelper::ConfigurationChanges::create()); + + SvtHelpOptions aHelpOptions; + if ( m_xPopUpNoHelpCB->get_state_changed_from_saved() ) + aHelpOptions.SetOfflineHelpPopUp( m_xPopUpNoHelpCB->get_active() ); + + if ( m_xExtHelpCB->get_state_changed_from_saved() ) + aHelpOptions.SetExtendedHelp( m_xExtHelpCB->get_active() ); + + if ( m_xShowTipOfTheDay->get_state_changed_from_saved() ) + { + officecfg::Office::Common::Misc::ShowTipOfTheDay::set(m_xShowTipOfTheDay->get_active(), batch); + bModified = true; + } + + if ( m_xFileDlgCB->get_state_changed_from_saved() ) + { + SvtMiscOptions aMiscOpt; + aMiscOpt.SetUseSystemFileDialog( !m_xFileDlgCB->get_active() ); + bModified = true; + } + + if ( m_xPrintDlgCB->get_state_changed_from_saved() ) + { + SvtMiscOptions aMiscOpt; + aMiscOpt.SetUseSystemPrintDialog( !m_xPrintDlgCB->get_active() ); + bModified = true; + } + + if ( m_xDocStatusCB->get_state_changed_from_saved() ) + { + SvtPrintWarningOptions aPrintOptions; + aPrintOptions.SetModifyDocumentOnPrintingAllowed( m_xDocStatusCB->get_active() ); + bModified = true; + } + + const SfxUInt16Item* pUInt16Item = dynamic_cast< const SfxUInt16Item* >( GetOldItem( *rSet, SID_ATTR_YEAR2000 ) ); + sal_uInt16 nNum = static_cast(m_xYearValueField->get_text().toInt32()); + if ( pUInt16Item && pUInt16Item->GetValue() != nNum ) + { + bModified = true; + rSet->Put( SfxUInt16Item( SID_ATTR_YEAR2000, nNum ) ); + } + + if (m_xCollectUsageInfo->get_state_changed_from_saved()) + { + officecfg::Office::Common::Misc::CollectUsageInformation::set(m_xCollectUsageInfo->get_active(), batch); + bModified = true; + } + +#if HAVE_FEATURE_BREAKPAD + if (m_xCrashReport->get_state_changed_from_saved()) + { + officecfg::Office::Common::Misc::CrashReport::set(m_xCrashReport->get_active(), batch); + bModified = true; + } +#endif + + batch->commit(); + + if( m_xQuickLaunchCB->get_state_changed_from_saved()) + { + rSet->Put(SfxBoolItem(SID_ATTR_QUICKLAUNCHER, m_xQuickLaunchCB->get_active())); + bModified = true; + } + + return bModified; +} + +void OfaMiscTabPage::Reset( const SfxItemSet* rSet ) +{ + SvtHelpOptions aHelpOptions; + m_xExtHelpCB->set_active( aHelpOptions.IsHelpTips() && aHelpOptions.IsExtendedHelp() ); + m_xExtHelpCB->save_state(); + m_xPopUpNoHelpCB->set_active( aHelpOptions.IsOfflineHelpPopUp() ); + m_xPopUpNoHelpCB->save_state(); + m_xShowTipOfTheDay->set_active( officecfg::Office::Common::Misc::ShowTipOfTheDay::get() ); + m_xShowTipOfTheDay->save_state(); + SvtMiscOptions aMiscOpt; + m_xFileDlgCB->set_active( !aMiscOpt.UseSystemFileDialog() ); + m_xFileDlgCB->save_state(); + m_xPrintDlgCB->set_active( !aMiscOpt.UseSystemPrintDialog() ); + m_xPrintDlgCB->save_state(); + + SvtPrintWarningOptions aPrintOptions; + m_xDocStatusCB->set_active(aPrintOptions.IsModifyDocumentOnPrintingAllowed()); + m_xDocStatusCB->save_state(); + + const SfxPoolItem* pItem = nullptr; + if ( SfxItemState::SET == rSet->GetItemState( SID_ATTR_YEAR2000, false, &pItem ) ) + { + m_xYearValueField->set_value( static_cast(pItem)->GetValue() ); + TwoFigureHdl(*m_xYearValueField); + } + else + m_xYearFrame->set_sensitive(false); + + m_xCollectUsageInfo->set_active(officecfg::Office::Common::Misc::CollectUsageInformation::get()); + m_xCollectUsageInfo->set_sensitive(!officecfg::Office::Common::Misc::CollectUsageInformation::isReadOnly()); + m_xCollectUsageInfo->save_state(); + +#if HAVE_FEATURE_BREAKPAD + m_xCrashReport->set_active(officecfg::Office::Common::Misc::CrashReport::get() && CrashReporter::IsDumpEnable()); + m_xCrashReport->set_sensitive(!officecfg::Office::Common::Misc::CrashReport::isReadOnly() && CrashReporter::IsDumpEnable()); + m_xCrashReport->save_state(); +#else + m_xCrashReport->hide(); +#endif + + SfxItemState eState = rSet->GetItemState( SID_ATTR_QUICKLAUNCHER, false, &pItem ); + if ( SfxItemState::SET == eState ) + m_xQuickLaunchCB->set_active( static_cast(pItem)->GetValue() ); + else if ( SfxItemState::DISABLED == eState ) + { + // quickstart not installed + m_xQuickStarterFrame->hide(); + } + + m_xQuickLaunchCB->save_state(); +} + +IMPL_LINK_NOARG( OfaMiscTabPage, TwoFigureHdl, weld::SpinButton&, void ) +{ + OUString aOutput( m_aStrDateInfo ); + OUString aStr( m_xYearValueField->get_text() ); + sal_Int32 nNum = aStr.toInt32(); + if ( aStr.getLength() != 4 || nNum < m_xYearValueField->get_min() || nNum > m_xYearValueField->get_max() ) + aOutput += "????"; + else + { + nNum += 99; + aOutput += OUString::number( nNum ); + } + m_xToYearFT->set_label( aOutput ); +} + +#if defined(_WIN32) +IMPL_STATIC_LINK_NOARG(OfaMiscTabPage, FileAssocClick, weld::Button&, void) +{ + const bool bUninit = SUCCEEDED(CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED)); + IApplicationAssociationRegistrationUI* pIf = nullptr; + HRESULT res = CoCreateInstance(CLSID_ApplicationAssociationRegistrationUI, nullptr, + CLSCTX_INPROC_SERVER, IID_IApplicationAssociationRegistrationUI, + reinterpret_cast(&pIf)); + + if (SUCCEEDED(res) && pIf) + { + // LaunchAdvancedAssociationUI only works for applications registered under + // Software\RegisteredApplications. See scp2/source/ooo/registryitem_ooo.scp + const OUString expanded = Translate::ExpandVariables("%PRODUCTNAME %PRODUCTVERSION"); + // This will only show "To change your default apps, go to Settings > Apps > Default apps" + // on Win10; this is expected. At least this will self-document it to users. + pIf->LaunchAdvancedAssociationUI(o3tl::toW(expanded.getStr())); + pIf->Release(); + } + if (bUninit) + CoUninitialize(); +} +#endif + +class CanvasSettings +{ +public: + CanvasSettings(); + + bool IsHardwareAccelerationEnabled() const; + bool IsHardwareAccelerationAvailable() const; + bool IsHardwareAccelerationRO() const; + void EnabledHardwareAcceleration( bool _bEnabled ) const; + +private: + typedef std::vector< std::pair > > ServiceVector; + + Reference mxForceFlagNameAccess; + ServiceVector maAvailableImplementations; + mutable bool mbHWAccelAvailable; + mutable bool mbHWAccelChecked; +}; + +CanvasSettings::CanvasSettings() : + mxForceFlagNameAccess(), + mbHWAccelAvailable(false), + mbHWAccelChecked(false) +{ + try + { + Reference xConfigProvider( + css::configuration::theDefaultProvider::get( + comphelper::getProcessComponentContext())); + + Sequence aArgs1(comphelper::InitAnyPropertySequence( + { + {"nodepath", Any(OUString("/org.openoffice.Office.Canvas"))} + })); + mxForceFlagNameAccess.set( + xConfigProvider->createInstanceWithArguments( + "com.sun.star.configuration.ConfigurationUpdateAccess", + aArgs1 ), + UNO_QUERY_THROW ); + + Sequence aArgs2(comphelper::InitAnyPropertySequence( + { + {"nodepath", Any(OUString("/org.openoffice.Office.Canvas/CanvasServiceList"))} + })); + Reference xNameAccess( + xConfigProvider->createInstanceWithArguments( + "com.sun.star.configuration.ConfigurationAccess", + aArgs2 ), UNO_QUERY_THROW ); + Reference xHierarchicalNameAccess( + xNameAccess, UNO_QUERY_THROW); + + Sequence serviceNames = xNameAccess->getElementNames(); + const OUString* pCurr = serviceNames.getConstArray(); + const OUString* const pEnd = pCurr + serviceNames.getLength(); + while( pCurr != pEnd ) + { + Reference xEntryNameAccess( + xHierarchicalNameAccess->getByHierarchicalName(*pCurr), + UNO_QUERY ); + + if( xEntryNameAccess.is() ) + { + Sequence preferredImplementations; + if( xEntryNameAccess->getByName("PreferredImplementations") >>= preferredImplementations ) + maAvailableImplementations.emplace_back(*pCurr,preferredImplementations ); + } + + ++pCurr; + } + } + catch (const Exception&) + { + } +} + +bool CanvasSettings::IsHardwareAccelerationAvailable() const +{ + if (SkiaHelper::isVCLSkiaEnabled() && Application::GetToolkitName() != "gtk3") + { + mbHWAccelAvailable = false; + return false; + } +#if HAVE_FEATURE_OPENGL + if (OpenGLWrapper::isVCLOpenGLEnabled() && Application::GetToolkitName() != "gtk3") + { + mbHWAccelAvailable = false; + return false; + } +#endif + if( !mbHWAccelChecked ) + { + mbHWAccelChecked = true; + + Reference< XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory(); + + // check whether any of the service lists has an + // implementation that presents the "HardwareAcceleration" property + for (auto const& availableImpl : maAvailableImplementations) + { + const OUString* pCurrImpl = availableImpl.second.getConstArray(); + const OUString* const pEndImpl = pCurrImpl + availableImpl.second.getLength(); + + while( pCurrImpl != pEndImpl ) + { + try + { + Reference xPropSet( xFactory->createInstance( + pCurrImpl->trim() ), + UNO_QUERY_THROW ); + bool bHasAccel(false); + if( xPropSet->getPropertyValue("HardwareAcceleration") >>= bHasAccel ) + if( bHasAccel ) + { + mbHWAccelAvailable = true; + return mbHWAccelAvailable; + } + } + catch (const Exception&) + { + } + + ++pCurrImpl; + } + } + } + + return mbHWAccelAvailable; +} + +bool CanvasSettings::IsHardwareAccelerationEnabled() const +{ + bool bForceLastEntry(false); + if( !mxForceFlagNameAccess.is() ) + return true; + + if( !(mxForceFlagNameAccess->getByName("ForceSafeServiceImpl") >>= bForceLastEntry) ) + return true; + + return !bForceLastEntry; +} + +bool CanvasSettings::IsHardwareAccelerationRO() const +{ + Reference< XPropertySet > xSet(mxForceFlagNameAccess, UNO_QUERY); + if (!xSet.is()) + return true; + + Reference< XPropertySetInfo > xInfo = xSet->getPropertySetInfo(); + Property aProp = xInfo->getPropertyByName("ForceSafeServiceImpl"); + return ((aProp.Attributes & css::beans::PropertyAttribute::READONLY ) == css::beans::PropertyAttribute::READONLY); +} + +void CanvasSettings::EnabledHardwareAcceleration( bool _bEnabled ) const +{ + Reference< XNameReplace > xNameReplace( + mxForceFlagNameAccess, UNO_QUERY ); + + if( !xNameReplace.is() ) + return; + + xNameReplace->replaceByName( "ForceSafeServiceImpl", Any(!_bEnabled) ); + + Reference< XChangesBatch > xChangesBatch( + mxForceFlagNameAccess, UNO_QUERY ); + + if( !xChangesBatch.is() ) + return; + + xChangesBatch->commitChanges(); +} + +// class OfaViewTabPage -------------------------------------------------- + +static bool DisplayNameCompareLessThan(const vcl::IconThemeInfo& rInfo1, const vcl::IconThemeInfo& rInfo2) +{ + return rInfo1.GetDisplayName().compareTo(rInfo2.GetDisplayName()) < 0; +} + +OfaViewTabPage::OfaViewTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/optviewpage.ui", "OptViewPage", &rSet) + , nSizeLB_InitialSelection(0) + , nSidebarSizeLB_InitialSelection(0) + , nNotebookbarSizeLB_InitialSelection(0) + , nStyleLB_InitialSelection(0) + , pAppearanceCfg(new SvtTabAppearanceCfg) + , pCanvasSettings(new CanvasSettings) + , mpDrawinglayerOpt(new SvtOptionsDrawinglayer) + , mpSkiaConfig(new svt::SkiaCfg) + , m_xIconSizeLB(m_xBuilder->weld_combo_box("iconsize")) + , m_xSidebarIconSizeLB(m_xBuilder->weld_combo_box("sidebariconsize")) + , m_xNotebookbarIconSizeLB(m_xBuilder->weld_combo_box("notebookbariconsize")) + , m_xIconStyleLB(m_xBuilder->weld_combo_box("iconstyle")) + , m_xFontAntiAliasing(m_xBuilder->weld_check_button("aafont")) + , m_xAAPointLimitLabel(m_xBuilder->weld_label("aafrom")) + , m_xAAPointLimit(m_xBuilder->weld_metric_spin_button("aanf", FieldUnit::PIXEL)) + , m_xMenuIconBox(m_xBuilder->weld_widget("menuiconsbox")) + , m_xMenuIconsLB(m_xBuilder->weld_combo_box("menuicons")) + , m_xContextMenuShortcutsLB(m_xBuilder->weld_combo_box("contextmenushortcuts")) + , m_xFontShowCB(m_xBuilder->weld_check_button("showfontpreview")) + , m_xUseHardwareAccell(m_xBuilder->weld_check_button("useaccel")) + , m_xUseAntiAliase(m_xBuilder->weld_check_button("useaa")) + , m_xUseSkia(m_xBuilder->weld_check_button("useskia")) + , m_xForceSkiaRaster(m_xBuilder->weld_check_button("forceskiaraster")) + , m_xSkiaStatusEnabled(m_xBuilder->weld_label("skiaenabled")) + , m_xSkiaStatusDisabled(m_xBuilder->weld_label("skiadisabled")) + , m_xMousePosLB(m_xBuilder->weld_combo_box("mousepos")) + , m_xMouseMiddleLB(m_xBuilder->weld_combo_box("mousemiddle")) +{ + if (Application::GetToolkitName() == "gtk3") + { + m_xUseSkia->hide(); + m_xForceSkiaRaster->hide(); + m_xSkiaStatusEnabled->hide(); + m_xSkiaStatusDisabled->hide(); + m_xMenuIconBox->hide(); + } + +#if !HAVE_FEATURE_SKIA || !defined(_WIN32) + // Duplicated also in UpdateSkiaStatus(). + // For now Skia is used mainly on Windows, hide the controls everywhere else. + // It can also be used on Linux, but only with the rarely used 'gen' backend. + m_xUseSkia->hide(); + m_xForceSkiaRaster->hide(); + m_xSkiaStatusEnabled->hide(); + m_xSkiaStatusDisabled->hide(); +#endif + + m_xFontAntiAliasing->connect_toggled( LINK( this, OfaViewTabPage, OnAntialiasingToggled ) ); + + m_xForceSkiaRaster->connect_toggled(LINK(this, OfaViewTabPage, OnForceSkiaRasterToggled)); + + // Set known icon themes + OUString sAutoStr( m_xIconStyleLB->get_text( 0 ) ); + m_xIconStyleLB->clear(); + StyleSettings aStyleSettings = Application::GetSettings().GetStyleSettings(); + mInstalledIconThemes = aStyleSettings.GetInstalledIconThemes(); + std::sort(mInstalledIconThemes.begin(), mInstalledIconThemes.end(), DisplayNameCompareLessThan); + + // Start with the automatically chosen icon theme + OUString autoThemeId = aStyleSettings.GetAutomaticallyChosenIconTheme(); + const vcl::IconThemeInfo& autoIconTheme = vcl::IconThemeInfo::FindIconThemeById(mInstalledIconThemes, autoThemeId); + + OUString entryForAuto = sAutoStr + " (" + + autoIconTheme.GetDisplayName() + + ")"; + m_xIconStyleLB->append("auto", entryForAuto); // index 0 means choose style automatically + + // separate auto and other icon themes + m_xIconStyleLB->append_separator(""); + + for (auto const& installIconTheme : mInstalledIconThemes) + m_xIconStyleLB->append(installIconTheme.GetThemeId(), installIconTheme.GetDisplayName()); + + m_xIconStyleLB->set_active(0); + + // FIXME: should really add code to show a 'lock' icon here. + if (officecfg::Office::Common::VCL::UseSkia::isReadOnly()) + m_xUseSkia->set_sensitive(false); + if (officecfg::Office::Common::VCL::ForceSkiaRaster::isReadOnly()) + m_xForceSkiaRaster->set_sensitive(false); + + UpdateSkiaStatus(); +} + +OfaViewTabPage::~OfaViewTabPage() +{ +} + +IMPL_LINK_NOARG( OfaViewTabPage, OnAntialiasingToggled, weld::ToggleButton&, void ) +{ + bool bAAEnabled = m_xFontAntiAliasing->get_active(); + + m_xAAPointLimitLabel->set_sensitive(bAAEnabled); + m_xAAPointLimit->set_sensitive(bAAEnabled); +} + +IMPL_LINK_NOARG(OfaViewTabPage, OnForceSkiaRasterToggled, weld::ToggleButton&, void) +{ + if (m_xForceSkiaRaster->get_active()) + { + // Forcing Skia raster implies that Skia is on. + m_xUseSkia->set_active(true); + } +} + +std::unique_ptr OfaViewTabPage::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet ) +{ + return std::make_unique(pPage, pController, *rAttrSet); +} + +bool OfaViewTabPage::FillItemSet( SfxItemSet* ) +{ + SvtFontOptions aFontOpt; + SvtMenuOptions aMenuOpt; + + bool bModified = false; + bool bMenuOptModified = false; + bool bRepaintWindows(false); + + SvtMiscOptions aMiscOptions; + const sal_Int32 nSizeLB_NewSelection = m_xIconSizeLB->get_active(); + if( nSizeLB_InitialSelection != nSizeLB_NewSelection ) + { + // from now on it's modified, even if via auto setting the same size was set as now selected in the LB + sal_Int16 eSet = SFX_SYMBOLS_SIZE_AUTO; + switch( nSizeLB_NewSelection ) + { + case 0: eSet = SFX_SYMBOLS_SIZE_AUTO; break; + case 1: eSet = SFX_SYMBOLS_SIZE_SMALL; break; + case 2: eSet = SFX_SYMBOLS_SIZE_LARGE; break; + case 3: eSet = SFX_SYMBOLS_SIZE_32; break; + default: + OSL_FAIL( "OfaViewTabPage::FillItemSet(): This state of m_xIconSizeLB should not be possible!" ); + } + aMiscOptions.SetSymbolsSize( eSet ); + } + + const sal_Int32 nSidebarSizeLB_NewSelection = m_xSidebarIconSizeLB->get_active(); + if( nSidebarSizeLB_InitialSelection != nSidebarSizeLB_NewSelection ) + { + // from now on it's modified, even if via auto setting the same size was set as now selected in the LB + ToolBoxButtonSize eSet = ToolBoxButtonSize::DontCare; + switch( nSidebarSizeLB_NewSelection ) + { + case 0: eSet = ToolBoxButtonSize::DontCare; break; + case 1: eSet = ToolBoxButtonSize::Small; break; + case 2: eSet = ToolBoxButtonSize::Large; break; + default: + OSL_FAIL( "OfaViewTabPage::FillItemSet(): This state of m_xSidebarIconSizeLB should not be possible!" ); + } + aMiscOptions.SetSidebarIconSize( eSet ); + } + + const sal_Int32 nNotebookbarSizeLB_NewSelection = m_xNotebookbarIconSizeLB->get_active(); + if( nNotebookbarSizeLB_InitialSelection != nNotebookbarSizeLB_NewSelection ) + { + // from now on it's modified, even if via auto setting the same size was set as now selected in the LB + ToolBoxButtonSize eSet = ToolBoxButtonSize::DontCare; + switch( nNotebookbarSizeLB_NewSelection ) + { + case 0: eSet = ToolBoxButtonSize::DontCare; break; + case 1: eSet = ToolBoxButtonSize::Small; break; + case 2: eSet = ToolBoxButtonSize::Large; break; + default: + OSL_FAIL( "OfaViewTabPage::FillItemSet(): This state of m_xNotebookbarIconSizeLB should not be possible!" ); + } + aMiscOptions.SetNotebookbarIconSize( eSet ); + } + + const sal_Int32 nStyleLB_NewSelection = m_xIconStyleLB->get_active(); + if( nStyleLB_InitialSelection != nStyleLB_NewSelection ) + { + aMiscOptions.SetIconTheme(m_xIconStyleLB->get_active_id()); + nStyleLB_InitialSelection = nStyleLB_NewSelection; + } + + bool bAppearanceChanged = false; + + // Mouse Snap Mode + SnapType eOldSnap = pAppearanceCfg->GetSnapMode(); + SnapType eNewSnap = static_cast(m_xMousePosLB->get_active()); + if(eNewSnap > SnapType::NONE) + eNewSnap = SnapType::NONE; + + if ( eNewSnap != eOldSnap ) + { + pAppearanceCfg->SetSnapMode(eNewSnap ); + bAppearanceChanged = true; + } + + // Middle Mouse Button + MouseMiddleButtonAction eOldMiddleMouse = pAppearanceCfg->GetMiddleMouseButton(); + short eNewMiddleMouse = m_xMouseMiddleLB->get_active(); + if(eNewMiddleMouse > 2) + eNewMiddleMouse = 2; + + if ( eNewMiddleMouse != static_cast(eOldMiddleMouse) ) + { + pAppearanceCfg->SetMiddleMouseButton( static_cast(eNewMiddleMouse) ); + bAppearanceChanged = true; + } + + if (m_xFontAntiAliasing->get_state_changed_from_saved()) + { + pAppearanceCfg->SetFontAntiAliasing(m_xFontAntiAliasing->get_active()); + bAppearanceChanged = true; + } + + if (m_xAAPointLimit->get_value_changed_from_saved()) + { + pAppearanceCfg->SetFontAntialiasingMinPixelHeight(m_xAAPointLimit->get_value(FieldUnit::PIXEL)); + bAppearanceChanged = true; + } + + if (m_xFontShowCB->get_state_changed_from_saved()) + { + aFontOpt.EnableFontWYSIWYG(m_xFontShowCB->get_active()); + bModified = true; + } + + if (m_xMenuIconsLB->get_value_changed_from_saved()) + { + aMenuOpt.SetMenuIconsState(m_xMenuIconsLB->get_active() == 0 ? + TRISTATE_INDET : + static_cast(m_xMenuIconsLB->get_active() - 1)); + bModified = true; + bMenuOptModified = true; + bAppearanceChanged = true; + } + + if (m_xContextMenuShortcutsLB->get_value_changed_from_saved()) + { + aMenuOpt.SetContextMenuShortcuts(m_xContextMenuShortcutsLB->get_active() == 0 ? + TRISTATE_INDET : + static_cast(m_xContextMenuShortcutsLB->get_active() - 1)); + bModified = true; + bMenuOptModified = true; + bAppearanceChanged = true; + } + + // #i95644# if disabled, do not use value, see in ::Reset() + if (m_xUseHardwareAccell->get_sensitive()) + { + if(m_xUseHardwareAccell->get_state_changed_from_saved()) + { + pCanvasSettings->EnabledHardwareAcceleration(m_xUseHardwareAccell->get_active()); + bModified = true; + } + } + + // #i95644# if disabled, do not use value, see in ::Reset() + if (m_xUseAntiAliase->get_sensitive()) + { + if (m_xUseAntiAliase->get_active() != mpDrawinglayerOpt->IsAntiAliasing()) + { + mpDrawinglayerOpt->SetAntiAliasing(m_xUseAntiAliase->get_active()); + bModified = true; + bRepaintWindows = true; + } + } + + if (m_xUseSkia->get_state_changed_from_saved() || + m_xForceSkiaRaster->get_state_changed_from_saved()) + { + mpSkiaConfig->setUseSkia(m_xUseSkia->get_active()); + mpSkiaConfig->setForceSkiaRaster(m_xForceSkiaRaster->get_active()); + bModified = true; + } + + if( bMenuOptModified ) + { + // Set changed settings to the application instance + AllSettings aAllSettings = Application::GetSettings(); + StyleSettings aStyleSettings = aAllSettings.GetStyleSettings(); + aAllSettings.SetStyleSettings(aStyleSettings); + Application::MergeSystemSettings( aAllSettings ); + Application::SetSettings(aAllSettings); + } + + if ( bAppearanceChanged ) + { + pAppearanceCfg->Commit(); + pAppearanceCfg->SetApplicationDefaults ( GetpApp() ); + } + + if(bRepaintWindows) + { + vcl::Window* pAppWindow = Application::GetFirstTopLevelWindow(); + + while(pAppWindow) + { + pAppWindow->Invalidate(); + pAppWindow = Application::GetNextTopLevelWindow(pAppWindow); + } + } + + if (m_xUseSkia->get_state_changed_from_saved() || + m_xForceSkiaRaster->get_state_changed_from_saved()) + { + SolarMutexGuard aGuard; + if( svtools::executeRestartDialog( + comphelper::getProcessComponentContext(), nullptr, + svtools::RESTART_REASON_SKIA)) + GetDialogController()->response(RET_OK); + } + + return bModified; +} + +void OfaViewTabPage::Reset( const SfxItemSet* ) +{ + SvtMiscOptions aMiscOptions; + mpSkiaConfig->reset(); + + if (aMiscOptions.GetSymbolsSize() != SFX_SYMBOLS_SIZE_AUTO) + { + nSizeLB_InitialSelection = 1; + + if (aMiscOptions.GetSymbolsSize() == SFX_SYMBOLS_SIZE_LARGE) + nSizeLB_InitialSelection = 2; + else if (aMiscOptions.GetSymbolsSize() == SFX_SYMBOLS_SIZE_32) + nSizeLB_InitialSelection = 3; + } + m_xIconSizeLB->set_active( nSizeLB_InitialSelection ); + m_xIconSizeLB->save_value(); + + if( aMiscOptions.GetSidebarIconSize() == ToolBoxButtonSize::DontCare ) + ; // do nothing + else if( aMiscOptions.GetSidebarIconSize() == ToolBoxButtonSize::Small ) + nSidebarSizeLB_InitialSelection = 1; + else if( aMiscOptions.GetSidebarIconSize() == ToolBoxButtonSize::Large ) + nSidebarSizeLB_InitialSelection = 2; + m_xSidebarIconSizeLB->set_active( nSidebarSizeLB_InitialSelection ); + m_xSidebarIconSizeLB->save_value(); + if( aMiscOptions.GetNotebookbarIconSize() == ToolBoxButtonSize::DontCare ) + ; // do nothing + else if( aMiscOptions.GetNotebookbarIconSize() == ToolBoxButtonSize::Small ) + nNotebookbarSizeLB_InitialSelection = 1; + else if( aMiscOptions.GetNotebookbarIconSize() == ToolBoxButtonSize::Large ) + nNotebookbarSizeLB_InitialSelection = 2; + m_xNotebookbarIconSizeLB->set_active(nNotebookbarSizeLB_InitialSelection); + m_xNotebookbarIconSizeLB->save_value(); + + if (aMiscOptions.IconThemeWasSetAutomatically()) { + nStyleLB_InitialSelection = 0; + } + else { + const OUString& selected = aMiscOptions.GetIconTheme(); + const vcl::IconThemeInfo& selectedInfo = + vcl::IconThemeInfo::FindIconThemeById(mInstalledIconThemes, selected); + nStyleLB_InitialSelection = m_xIconStyleLB->find_text(selectedInfo.GetDisplayName()); + } + + m_xIconStyleLB->set_active(nStyleLB_InitialSelection); + m_xIconStyleLB->save_value(); + + // Mouse Snap + m_xMousePosLB->set_active(static_cast(pAppearanceCfg->GetSnapMode())); + m_xMousePosLB->save_value(); + + // Mouse Snap + m_xMouseMiddleLB->set_active(static_cast(pAppearanceCfg->GetMiddleMouseButton())); + m_xMouseMiddleLB->save_value(); + + m_xFontAntiAliasing->set_active( pAppearanceCfg->IsFontAntiAliasing() ); + m_xAAPointLimit->set_value(pAppearanceCfg->GetFontAntialiasingMinPixelHeight(), FieldUnit::PIXEL); + + // WorkingSet + SvtFontOptions aFontOpt; + m_xFontShowCB->set_active( aFontOpt.IsFontWYSIWYGEnabled() ); + SvtMenuOptions aMenuOpt; + m_xMenuIconsLB->set_active(aMenuOpt.GetMenuIconsState() == 2 ? 0 : aMenuOpt.GetMenuIconsState() + 1); + m_xMenuIconsLB->save_value(); + + TriState eContextMenuShortcuts = aMenuOpt.GetContextMenuShortcuts(); + bool bContextMenuShortcutsNonDefault = eContextMenuShortcuts == TRISTATE_FALSE || eContextMenuShortcuts == TRISTATE_TRUE; + m_xContextMenuShortcutsLB->set_active(bContextMenuShortcutsNonDefault ? eContextMenuShortcuts + 1 : 0); + m_xContextMenuShortcutsLB->save_value(); + + { // #i95644# HW accel (unified to disable mechanism) + if(pCanvasSettings->IsHardwareAccelerationAvailable()) + { + m_xUseHardwareAccell->set_active(pCanvasSettings->IsHardwareAccelerationEnabled()); + m_xUseHardwareAccell->set_sensitive(!pCanvasSettings->IsHardwareAccelerationRO()); + } + else + { + m_xUseHardwareAccell->set_active(false); + m_xUseHardwareAccell->set_sensitive(false); + } + + m_xUseHardwareAccell->save_state(); + } + + { // #i95644# AntiAliasing + if(mpDrawinglayerOpt->IsAAPossibleOnThisSystem()) + { + m_xUseAntiAliase->set_active(mpDrawinglayerOpt->IsAntiAliasing()); + } + else + { + m_xUseAntiAliase->set_active(false); + m_xUseAntiAliase->set_sensitive(false); + } + + m_xUseAntiAliase->save_state(); + } + m_xUseSkia->set_active(mpSkiaConfig->useSkia()); + m_xForceSkiaRaster->set_active(mpSkiaConfig->forceSkiaRaster()); + + m_xFontAntiAliasing->save_state(); + m_xAAPointLimit->save_value(); + m_xFontShowCB->save_state(); + + m_xUseSkia->save_state(); + m_xForceSkiaRaster->save_state(); + + OnAntialiasingToggled(*m_xFontAntiAliasing); +} + +void OfaViewTabPage::UpdateSkiaStatus() +{ + if (Application::GetToolkitName() == "gtk3") + return; +#if HAVE_FEATURE_SKIA && defined(_WIN32) + // Easier than a custom translation string. + bool bEnabled = SkiaHelper::isVCLSkiaEnabled(); + m_xSkiaStatusEnabled->set_visible(bEnabled); + m_xSkiaStatusDisabled->set_visible(!bEnabled); +#endif +} + +struct LanguageConfig_Impl +{ + SvtLanguageOptions aLanguageOptions; + SvtSysLocaleOptions aSysLocaleOptions; + SvtLinguConfig aLinguConfig; +}; + +static bool bLanguageCurrentDoc_Impl = false; + +// some things we'll need... +static const char sAccessSrvc[] = "com.sun.star.configuration.ConfigurationAccess"; +static const char sAccessUpdSrvc[] = "com.sun.star.configuration.ConfigurationUpdateAccess"; +static const char sInstalledLocalesPath[] = "org.openoffice.Setup/Office/InstalledLocales"; +static const char sUserLocalePath[] = "org.openoffice.Office.Linguistic/General"; +static const char sUserLocaleKey[] = "UILocale"; +static Sequence< OUString > seqInstalledLanguages; + +static OUString lcl_getDatePatternsConfigString( const LocaleDataWrapper& rLocaleWrapper ) +{ + Sequence< OUString > aDateAcceptancePatterns = rLocaleWrapper.getDateAcceptancePatterns(); + sal_Int32 nPatterns = aDateAcceptancePatterns.getLength(); + OUStringBuffer aBuf( nPatterns * 6 ); // 6 := length of Y-M-D; + SAL_WARN_IF( !nPatterns, "cui.options", "No date acceptance pattern"); + if (nPatterns) + { + const OUString* pPatterns = aDateAcceptancePatterns.getConstArray(); + aBuf.append( pPatterns[0]); + for (sal_Int32 i=1; i < nPatterns; ++i) + aBuf.append(';').append( pPatterns[i]); + } + return aBuf.makeStringAndClear(); +} + +namespace +{ + //what ui language will be selected by default if the user override of General::UILocale is unset ? + LanguageTag GetInstalledLocaleForSystemUILanguage() + { + css::uno::Sequence inst(officecfg::Setup::Office::InstalledLocales::get()->getElementNames()); + return LanguageTag(getInstalledLocaleForSystemUILanguage(inst, false)).makeFallback(); + } +} + +OfaLanguagesTabPage::OfaLanguagesTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/optlanguagespage.ui", "OptLanguagesPage", &rSet) + , pLangConfig(new LanguageConfig_Impl) + , m_bDatePatternsValid(false) + , m_xUserInterfaceLB(m_xBuilder->weld_combo_box("userinterface")) + , m_xLocaleSettingFT(m_xBuilder->weld_label("localesettingFT")) + , m_xLocaleSettingLB(new SvxLanguageBox(m_xBuilder->weld_combo_box("localesetting"))) + , m_xDecimalSeparatorCB(m_xBuilder->weld_check_button("decimalseparator")) + , m_xCurrencyFT(m_xBuilder->weld_label("defaultcurrency")) + , m_xCurrencyLB(m_xBuilder->weld_combo_box("currencylb")) + , m_xDatePatternsFT(m_xBuilder->weld_label("dataaccpatterns")) + , m_xDatePatternsED(m_xBuilder->weld_entry("datepatterns")) + , m_xWesternLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box("westernlanguage"))) + , m_xWesternLanguageFT(m_xBuilder->weld_label("western")) + , m_xAsianLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box("asianlanguage"))) + , m_xComplexLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box("complexlanguage"))) + , m_xCurrentDocCB(m_xBuilder->weld_check_button("currentdoc")) + , m_xAsianSupportCB(m_xBuilder->weld_check_button("asiansupport")) + , m_xCTLSupportCB(m_xBuilder->weld_check_button("ctlsupport")) + , m_xIgnoreLanguageChangeCB(m_xBuilder->weld_check_button("ignorelanguagechange")) +{ + // tdf#125483 save original default label + m_sDecimalSeparatorLabel = m_xDecimalSeparatorCB->get_label(); + + // initialize user interface language selection + m_sSystemDefaultString = SvtLanguageTable::GetLanguageString( LANGUAGE_SYSTEM ); + + OUString aUILang = m_sSystemDefaultString + + " - " + + SvtLanguageTable::GetLanguageString(GetInstalledLocaleForSystemUILanguage().getLanguageType()); + + m_xUserInterfaceLB->append("0", aUILang); + m_xUserInterfaceLB->append_separator(""); + try + { + Reference< XMultiServiceFactory > theConfigProvider( + css::configuration::theDefaultProvider::get( + comphelper::getProcessComponentContext())); + Sequence< Any > theArgs(1); + Reference< XNameAccess > theNameAccess; + + // find out which locales are currently installed and add them to the listbox + theArgs[0] <<= NamedValue("nodepath", Any(OUString(sInstalledLocalesPath))); + theNameAccess.set( + theConfigProvider->createInstanceWithArguments(sAccessSrvc, theArgs ), UNO_QUERY_THROW ); + seqInstalledLanguages = theNameAccess->getElementNames(); + LanguageType aLang = LANGUAGE_DONTKNOW; + std::vector< std::pair > aUILanguages; + for (sal_Int32 i=0; iappend(OUString::number(nGroupID), sGroupName); + } + + m_xUserInterfaceLB->set_active(0); + + // find out whether the user has a specific locale specified + Sequence< Any > theArgs2(1); + theArgs2[0] <<= NamedValue("nodepath", Any(OUString(sUserLocalePath))); + theNameAccess.set( + theConfigProvider->createInstanceWithArguments(sAccessSrvc, theArgs2 ), UNO_QUERY_THROW ); + if (theNameAccess->hasByName(sUserLocaleKey)) + theNameAccess->getByName(sUserLocaleKey) >>= m_sUserLocaleValue; + // select the user specified locale in the listbox + if (!m_sUserLocaleValue.isEmpty()) + { + for (sal_Int32 i = 0, nEntryCount = m_xUserInterfaceLB->get_count(); i < nEntryCount; ++i) + { + sal_Int32 d = m_xUserInterfaceLB->get_id(i).toInt32(); + if ( d > 0 && seqInstalledLanguages.getLength() > d-1 && seqInstalledLanguages[d-1] == m_sUserLocaleValue) + m_xUserInterfaceLB->set_active(i); + } + } + + } + catch (const Exception &) + { + // we'll just leave the box in its default setting and won't + // even give it event handler... + TOOLS_WARN_EXCEPTION("cui.options", "ignoring" ); + } + + m_xWesternLanguageLB->SetLanguageList( + SvxLanguageListFlags::WESTERN | SvxLanguageListFlags::ONLY_KNOWN, true, false, true, true, + LANGUAGE_SYSTEM, css::i18n::ScriptType::LATIN); + + m_xAsianLanguageLB->SetLanguageList( + SvxLanguageListFlags::CJK | SvxLanguageListFlags::ONLY_KNOWN, true, false, true, true, + LANGUAGE_SYSTEM, css::i18n::ScriptType::ASIAN); + + m_xComplexLanguageLB->SetLanguageList( + SvxLanguageListFlags::CTL | SvxLanguageListFlags::ONLY_KNOWN, true, false, true, true, + LANGUAGE_SYSTEM, css::i18n::ScriptType::COMPLEX); + + m_xLocaleSettingLB->SetLanguageList( + SvxLanguageListFlags::ALL | SvxLanguageListFlags::ONLY_KNOWN, false, false, false, true, + LANGUAGE_USER_SYSTEM_CONFIG, css::i18n::ScriptType::WEAK); + + const NfCurrencyTable& rCurrTab = SvNumberFormatter::GetTheCurrencyTable(); + const NfCurrencyEntry& rCurr = SvNumberFormatter::GetCurrencyEntry( LANGUAGE_SYSTEM ); + // insert SYSTEM entry + OUString aDefaultCurr = m_sSystemDefaultString + " - " + rCurr.GetBankSymbol(); + m_xCurrencyLB->append("default", aDefaultCurr); + m_xCurrencyLB->append_separator(""); + + assert(m_xCurrencyLB->find_id("default") != -1); + // all currencies + OUString aTwoSpace( " " ); + sal_uInt16 nCurrCount = rCurrTab.size(); + std::vector< const NfCurrencyEntry* > aCurrencies; + // first entry is SYSTEM, skip it + for ( sal_uInt16 j=1; j < nCurrCount; ++j ) + { + aCurrencies.push_back(&rCurrTab[j]); + } + std::sort(aCurrencies.begin(), aCurrencies.end(), + [](const NfCurrencyEntry* c1, const NfCurrencyEntry* c2) { + return c1->GetBankSymbol().compareTo(c2->GetBankSymbol()) < 0; + }); + + for (auto &v : aCurrencies) + { + OUString aStr_ = v->GetBankSymbol() + + aTwoSpace + + v->GetSymbol(); + aStr_ = ApplyLreOrRleEmbedding( aStr_ ) + + aTwoSpace + + ApplyLreOrRleEmbedding( SvtLanguageTable::GetLanguageString( v->GetLanguage() ) ); + m_xCurrencyLB->append(OUString::number(reinterpret_cast(v)), aStr_); + } + + m_xCurrencyLB->set_active(0); + + m_xLocaleSettingLB->connect_changed( LINK( this, OfaLanguagesTabPage, LocaleSettingHdl ) ); + m_xDatePatternsED->connect_changed( LINK( this, OfaLanguagesTabPage, DatePatternsHdl ) ); + + Link aLink( LINK( this, OfaLanguagesTabPage, SupportHdl ) ); + m_xAsianSupportCB->connect_toggled( aLink ); + m_xCTLSupportCB->connect_toggled( aLink ); + + m_bOldAsian = pLangConfig->aLanguageOptions.IsAnyEnabled(); + m_xAsianSupportCB->set_active(m_bOldAsian); + m_xAsianSupportCB->save_state(); + bool bReadonly = pLangConfig->aLanguageOptions.IsReadOnly(SvtLanguageOptions::E_ALLCJK); + m_xAsianSupportCB->set_sensitive(!bReadonly); + SupportHdl(*m_xAsianSupportCB); + + m_bOldCtl = pLangConfig->aLanguageOptions.IsCTLFontEnabled(); + m_xCTLSupportCB->set_active(m_bOldCtl); + m_xCTLSupportCB->save_state(); + bReadonly = pLangConfig->aLanguageOptions.IsReadOnly(SvtLanguageOptions::E_CTLFONT); + m_xCTLSupportCB->set_sensitive(!bReadonly); + SupportHdl(*m_xCTLSupportCB); + + m_xIgnoreLanguageChangeCB->set_active( pLangConfig->aSysLocaleOptions.IsIgnoreLanguageChange() ); +} + +OfaLanguagesTabPage::~OfaLanguagesTabPage() +{ +} + +std::unique_ptr OfaLanguagesTabPage::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet ) +{ + return std::make_unique(pPage, pController, *rAttrSet); +} + +static void lcl_Update(std::unique_ptr pInvalidItems[], std::unique_ptr pBoolItems[], sal_uInt16 nCount) +{ + SfxViewFrame* pCurrentFrm = SfxViewFrame::Current(); + SfxViewFrame* pViewFrm = SfxViewFrame::GetFirst(); + while(pViewFrm) + { + SfxBindings& rBind = pViewFrm->GetBindings(); + for(sal_uInt16 i = 0; i < nCount; i++) + { + if(pCurrentFrm == pViewFrm) + rBind.InvalidateAll(false); + rBind.SetState( *pInvalidItems[i] ); + rBind.SetState( *pBoolItems[i] ); + } + pViewFrm = SfxViewFrame::GetNext(*pViewFrm); + } +} + +bool OfaLanguagesTabPage::FillItemSet( SfxItemSet* rSet ) +{ + // lock configuration broadcasters so that we can coordinate the notifications + pLangConfig->aSysLocaleOptions.BlockBroadcasts( true ); + pLangConfig->aLanguageOptions.BlockBroadcasts( true ); + pLangConfig->aLinguConfig.BlockBroadcasts( true ); + + /* + * Sequence checking only matters when CTL support is enabled. + * + * So we only need to check for sequence checking if + * a) previously it was unchecked and is now checked or + * b) it was already checked but the CTL language has changed + */ + if ( + m_xCTLSupportCB->get_active() && + (m_xCTLSupportCB->get_saved_state() != TRISTATE_TRUE || + m_xComplexLanguageLB->get_active_id_changed_from_saved()) + ) + { + //sequence checking has to be switched on depending on the selected CTL language + LanguageType eCTLLang = m_xComplexLanguageLB->get_active_id(); + bool bOn = MsLangId::needsSequenceChecking( eCTLLang); + pLangConfig->aLanguageOptions.SetCTLSequenceCheckingRestricted(bOn); + pLangConfig->aLanguageOptions.SetCTLSequenceChecking(bOn); + pLangConfig->aLanguageOptions.SetCTLSequenceCheckingTypeAndReplace(bOn); + } + try + { + // handle settings for UI Language + // a change of setting needs to bring up a warning message + OUString aLangString; + sal_Int32 d = m_xUserInterfaceLB->get_active_id().toInt32(); + if( d > 0 && seqInstalledLanguages.getLength() > d-1) + aLangString = seqInstalledLanguages[d-1]; + + /* + if( m_xUserInterfaceLB->GetSelectedEntryPos() > 0) + aLangString = ConvertLanguageToIsoString(m_xUserInterfaceLB->get_active_id()); + */ + Reference< XMultiServiceFactory > theConfigProvider( + css::configuration::theDefaultProvider::get( + comphelper::getProcessComponentContext())); + Sequence< Any > theArgs(1); + theArgs[0] <<= NamedValue("nodepath", Any(OUString(sUserLocalePath))); + Reference< XPropertySet >xProp( + theConfigProvider->createInstanceWithArguments(sAccessUpdSrvc, theArgs ), UNO_QUERY_THROW ); + if ( m_sUserLocaleValue != aLangString) + { + // OSL_FAIL("UserInterface language was changed, restart."); + // write new value + xProp->setPropertyValue(sUserLocaleKey, Any(aLangString)); + Reference< XChangesBatch >(xProp, UNO_QUERY_THROW)->commitChanges(); + // display info + SolarMutexGuard aGuard; + if (svtools::executeRestartDialog( + comphelper::getProcessComponentContext(), GetFrameWeld(), + svtools::RESTART_REASON_LANGUAGE_CHANGE)) + GetDialogController()->response(RET_OK); + + // tell quickstarter to stop being a veto listener + + Reference< XComponentContext > xContext( + comphelper::getProcessComponentContext()); + css::office::Quickstart::createAndSetVeto(xContext, false, false, false/*DisableVeto*/); + } + } + catch (const Exception&) + { + // we'll just leave the box in its default setting and won't + // even give it event handler... + TOOLS_WARN_EXCEPTION("cui.options", "ignoring"); + } + + LanguageTag aLanguageTag( pLangConfig->aSysLocaleOptions.GetLanguageTag()); + LanguageType eOldLocale = (aLanguageTag.isSystemLocale() ? LANGUAGE_SYSTEM : + aLanguageTag.makeFallback().getLanguageType()); + LanguageType eNewLocale = m_xLocaleSettingLB->get_active_id(); + + // If the "Default ..." entry was selected that means SYSTEM, the actual + // eNewLocale value is temporary for the dialog only, do not resolve to + // what system currently is. + if (eNewLocale == LANGUAGE_USER_SYSTEM_CONFIG) + eNewLocale = LANGUAGE_SYSTEM; + + if ( eOldLocale != eNewLocale ) + { + // an empty string denotes SYSTEM locale + OUString sNewLang; + if ( eNewLocale != LANGUAGE_SYSTEM ) + sNewLang = LanguageTag::convertToBcp47( eNewLocale); + + // locale nowadays get to AppSettings via notification + // this will happen after releasing the lock on the ConfigurationBroadcaster at + // the end of this method + pLangConfig->aSysLocaleOptions.SetLocaleConfigString( sNewLang ); + rSet->Put( SfxBoolItem( SID_OPT_LOCALE_CHANGED, true ) ); + + SvtScriptType nNewType = SvtLanguageOptions::GetScriptTypeOfLanguage( eNewLocale ); + bool bNewCJK = bool( nNewType & SvtScriptType::ASIAN ); + SvtCompatibilityOptions aCompatOpts; + aCompatOpts.SetDefault( SvtCompatibilityEntry::Index::ExpandWordSpace, !bNewCJK ); + } + + if(m_xDecimalSeparatorCB->get_state_changed_from_saved()) + pLangConfig->aSysLocaleOptions.SetDecimalSeparatorAsLocale(m_xDecimalSeparatorCB->get_active()); + + if(m_xIgnoreLanguageChangeCB->get_state_changed_from_saved()) + pLangConfig->aSysLocaleOptions.SetIgnoreLanguageChange(m_xIgnoreLanguageChangeCB->get_active()); + + // Configured currency, for example, USD-en-US or EUR-de-DE, or empty for locale default. + OUString sOldCurr = pLangConfig->aSysLocaleOptions.GetCurrencyConfigString(); + OUString sId = m_xCurrencyLB->get_active_id(); + const NfCurrencyEntry* pCurr = sId == "default" ? nullptr : reinterpret_cast(sId.toInt64()); + OUString sNewCurr; + if ( pCurr ) + sNewCurr = SvtSysLocaleOptions::CreateCurrencyConfigString( + pCurr->GetBankSymbol(), pCurr->GetLanguage() ); + if ( sOldCurr != sNewCurr ) + pLangConfig->aSysLocaleOptions.SetCurrencyConfigString( sNewCurr ); + + // Configured date acceptance patterns, for example Y-M-D;M-D or empty for + // locale default. + if (m_bDatePatternsValid && m_xDatePatternsED->get_value_changed_from_saved()) + pLangConfig->aSysLocaleOptions.SetDatePatternsConfigString( m_xDatePatternsED->get_text()); + + SfxObjectShell* pCurrentDocShell = SfxObjectShell::Current(); + Reference< css::linguistic2::XLinguProperties > xLinguProp = LinguMgr::GetLinguPropertySet(); + bool bCurrentDocCBChecked = m_xCurrentDocCB->get_active(); + if (m_xCurrentDocCB->get_sensitive()) + bLanguageCurrentDoc_Impl = bCurrentDocCBChecked; + bool bCurrentDocCBChanged = m_xCurrentDocCB->get_state_changed_from_saved(); + + bool bValChanged = m_xWesternLanguageLB->get_active_id_changed_from_saved(); + if( (bCurrentDocCBChanged && !bCurrentDocCBChecked) || bValChanged) + { + LanguageType eSelectLang = m_xWesternLanguageLB->get_active_id(); + if(!bCurrentDocCBChecked) + { + Any aValue; + Locale aLocale = LanguageTag::convertToLocale( eSelectLang, false); + aValue <<= aLocale; + pLangConfig->aLinguConfig.SetProperty( "DefaultLocale", aValue ); + if (xLinguProp.is()) + xLinguProp->setDefaultLocale( aLocale ); + } + if(pCurrentDocShell) + { + rSet->Put(SvxLanguageItem(MsLangId::resolveSystemLanguageByScriptType(eSelectLang, css::i18n::ScriptType::LATIN), + SID_ATTR_LANGUAGE)); + } + } + bValChanged = m_xAsianLanguageLB->get_active_id_changed_from_saved(); + if( (bCurrentDocCBChanged && !bCurrentDocCBChecked) || bValChanged) + { + LanguageType eSelectLang = m_xAsianLanguageLB->get_active_id(); + if(!bCurrentDocCBChecked) + { + Any aValue; + Locale aLocale = LanguageTag::convertToLocale( eSelectLang, false); + aValue <<= aLocale; + pLangConfig->aLinguConfig.SetProperty( "DefaultLocale_CJK", aValue ); + if (xLinguProp.is()) + xLinguProp->setDefaultLocale_CJK( aLocale ); + } + if(pCurrentDocShell) + { + rSet->Put(SvxLanguageItem(MsLangId::resolveSystemLanguageByScriptType(eSelectLang, css::i18n::ScriptType::ASIAN), + SID_ATTR_CHAR_CJK_LANGUAGE)); + } + } + bValChanged = m_xComplexLanguageLB->get_active_id_changed_from_saved(); + if( (bCurrentDocCBChanged && !bCurrentDocCBChecked) || bValChanged) + { + LanguageType eSelectLang = m_xComplexLanguageLB->get_active_id(); + if(!bCurrentDocCBChecked) + { + Any aValue; + Locale aLocale = LanguageTag::convertToLocale( eSelectLang, false); + aValue <<= aLocale; + pLangConfig->aLinguConfig.SetProperty( "DefaultLocale_CTL", aValue ); + if (xLinguProp.is()) + xLinguProp->setDefaultLocale_CTL( aLocale ); + } + if(pCurrentDocShell) + { + rSet->Put(SvxLanguageItem(MsLangId::resolveSystemLanguageByScriptType(eSelectLang, css::i18n::ScriptType::COMPLEX), + SID_ATTR_CHAR_CTL_LANGUAGE)); + } + } + + if(m_xAsianSupportCB->get_state_changed_from_saved() ) + { + bool bChecked = m_xAsianSupportCB->get_active(); + pLangConfig->aLanguageOptions.SetAll(bChecked); + + //iterate over all bindings to invalidate vertical text direction + const sal_uInt16 STATE_COUNT = 2; + + std::unique_ptr pBoolItems[STATE_COUNT]; + pBoolItems[0].reset(new SfxBoolItem(SID_VERTICALTEXT_STATE, false)); + pBoolItems[1].reset(new SfxBoolItem(SID_TEXT_FITTOSIZE_VERTICAL, false)); + + std::unique_ptr pInvalidItems[STATE_COUNT]; + pInvalidItems[0].reset(new SfxVoidItem(SID_VERTICALTEXT_STATE)); + pInvalidItems[1].reset(new SfxVoidItem(SID_TEXT_FITTOSIZE_VERTICAL)); + + lcl_Update(pInvalidItems, pBoolItems, STATE_COUNT); + } + + if ( m_xCTLSupportCB->get_state_changed_from_saved() ) + { + SvtSearchOptions aOpt; + aOpt.SetIgnoreDiacritics_CTL(true); + aOpt.SetIgnoreKashida_CTL(true); + aOpt.Commit(); + pLangConfig->aLanguageOptions.SetCTLFontEnabled( m_xCTLSupportCB->get_active() ); + + const sal_uInt16 STATE_COUNT = 1; + std::unique_ptr pBoolItems[STATE_COUNT]; + pBoolItems[0].reset(new SfxBoolItem(SID_CTLFONT_STATE, false)); + std::unique_ptr pInvalidItems[STATE_COUNT]; + pInvalidItems[0].reset(new SfxVoidItem(SID_CTLFONT_STATE)); + lcl_Update(pInvalidItems, pBoolItems, STATE_COUNT); + } + + if ( pLangConfig->aSysLocaleOptions.IsModified() ) + pLangConfig->aSysLocaleOptions.Commit(); + + // first release the lock on the ConfigurationBroadcaster for Locale changes + // it seems that our code relies on the fact that before other changes like e.g. currency + // are broadcasted locale changes have been done + pLangConfig->aSysLocaleOptions.BlockBroadcasts( false ); + pLangConfig->aLanguageOptions.BlockBroadcasts( false ); + pLangConfig->aLinguConfig.BlockBroadcasts( false ); + + return false; +} + +void OfaLanguagesTabPage::Reset( const SfxItemSet* rSet ) +{ + LanguageTag aLanguageTag( pLangConfig->aSysLocaleOptions.GetLanguageTag()); + if ( aLanguageTag.isSystemLocale() ) + m_xLocaleSettingLB->set_active_id( LANGUAGE_USER_SYSTEM_CONFIG ); + else + m_xLocaleSettingLB->set_active_id( aLanguageTag.makeFallback().getLanguageType()); + bool bReadonly = pLangConfig->aSysLocaleOptions.IsReadOnly(SvtSysLocaleOptions::EOption::Locale); + m_xLocaleSettingLB->set_sensitive(!bReadonly); + m_xLocaleSettingFT->set_sensitive(!bReadonly); + + + m_xDecimalSeparatorCB->set_active( pLangConfig->aSysLocaleOptions.IsDecimalSeparatorAsLocale()); + m_xDecimalSeparatorCB->save_state(); + + m_xIgnoreLanguageChangeCB->set_active( pLangConfig->aSysLocaleOptions.IsIgnoreLanguageChange()); + m_xIgnoreLanguageChangeCB->save_state(); + + // let LocaleSettingHdl enable/disable checkboxes for CJK/CTL support + // #i15812# must be done *before* the configured currency is set + // and update the decimal separator used for the given locale + LocaleSettingHdl(*m_xLocaleSettingLB->get_widget()); + + // configured currency, for example, USD-en-US or EUR-de-DE, or empty for locale default + OUString aAbbrev; + LanguageType eLang; + const NfCurrencyEntry* pCurr = nullptr; + OUString sCurrency = pLangConfig->aSysLocaleOptions.GetCurrencyConfigString(); + if ( !sCurrency.isEmpty() ) + { + SvtSysLocaleOptions::GetCurrencyAbbrevAndLanguage( aAbbrev, eLang, sCurrency ); + pCurr = SvNumberFormatter::GetCurrencyEntry( aAbbrev, eLang ); + } + // if pCurr==nullptr the SYSTEM entry is selected + OUString sId = !pCurr ? OUString("default") : OUString::number(reinterpret_cast(pCurr)); + m_xCurrencyLB->set_active_id(sId); + bReadonly = pLangConfig->aSysLocaleOptions.IsReadOnly(SvtSysLocaleOptions::EOption::Currency); + m_xCurrencyLB->set_sensitive(!bReadonly); + m_xCurrencyFT->set_sensitive(!bReadonly); + + // date acceptance patterns + OUString aDatePatternsString = pLangConfig->aSysLocaleOptions.GetDatePatternsConfigString(); + if (aDatePatternsString.isEmpty()) + { + const LocaleDataWrapper& rLocaleWrapper( Application::GetSettings().GetLocaleDataWrapper() ); + aDatePatternsString = lcl_getDatePatternsConfigString( rLocaleWrapper); + } + // Let's assume patterns are valid at this point. + m_bDatePatternsValid = true; + m_xDatePatternsED->set_text(aDatePatternsString); + bReadonly = pLangConfig->aSysLocaleOptions.IsReadOnly(SvtSysLocaleOptions::EOption::DatePatterns); + m_xDatePatternsED->set_sensitive(!bReadonly); + m_xDatePatternsFT->set_sensitive(!bReadonly); + m_xDatePatternsED->save_value(); + + //western/CJK/CLK language + LanguageType eCurLang = LANGUAGE_NONE; + LanguageType eCurLangCJK = LANGUAGE_NONE; + LanguageType eCurLangCTL = LANGUAGE_NONE; + SfxObjectShell* pCurrentDocShell = SfxObjectShell::Current(); + //collect the configuration values first + m_xCurrentDocCB->set_sensitive(false); + + Any aWestLang; + Any aCJKLang; + Any aCTLLang; + try + { + aWestLang = pLangConfig->aLinguConfig.GetProperty("DefaultLocale"); + Locale aLocale; + aWestLang >>= aLocale; + + eCurLang = LanguageTag::convertToLanguageType( aLocale, false); + + aCJKLang = pLangConfig->aLinguConfig.GetProperty("DefaultLocale_CJK"); + aLocale = Locale(); + aCJKLang >>= aLocale; + eCurLangCJK = LanguageTag::convertToLanguageType( aLocale, false); + + aCTLLang = pLangConfig->aLinguConfig.GetProperty("DefaultLocale_CTL"); + aLocale = Locale(); + aCTLLang >>= aLocale; + eCurLangCTL = LanguageTag::convertToLanguageType( aLocale, false); + } + catch (const Exception&) + { + } + //overwrite them by the values provided by the DocShell + if(pCurrentDocShell) + { + m_xCurrentDocCB->set_sensitive(true); + m_xCurrentDocCB->set_active(bLanguageCurrentDoc_Impl); + const SfxPoolItem* pLang; + if( SfxItemState::SET == rSet->GetItemState(SID_ATTR_LANGUAGE, false, &pLang)) + { + LanguageType eTempCurLang = static_cast(pLang)->GetValue(); + if (MsLangId::resolveSystemLanguageByScriptType(eCurLang, css::i18n::ScriptType::LATIN) != eTempCurLang) + eCurLang = eTempCurLang; + } + + if( SfxItemState::SET == rSet->GetItemState(SID_ATTR_CHAR_CJK_LANGUAGE, false, &pLang)) + { + LanguageType eTempCurLang = static_cast(pLang)->GetValue(); + if (MsLangId::resolveSystemLanguageByScriptType(eCurLangCJK, css::i18n::ScriptType::ASIAN) != eTempCurLang) + eCurLangCJK = eTempCurLang; + } + + if( SfxItemState::SET == rSet->GetItemState(SID_ATTR_CHAR_CTL_LANGUAGE, false, &pLang)) + { + LanguageType eTempCurLang = static_cast(pLang)->GetValue(); + if (MsLangId::resolveSystemLanguageByScriptType(eCurLangCTL, css::i18n::ScriptType::COMPLEX) != eTempCurLang) + eCurLangCTL = eTempCurLang; + } + } + if(LANGUAGE_NONE == eCurLang || LANGUAGE_DONTKNOW == eCurLang) + m_xWesternLanguageLB->set_active_id(LANGUAGE_NONE); + else + m_xWesternLanguageLB->set_active_id(eCurLang); + + if(LANGUAGE_NONE == eCurLangCJK || LANGUAGE_DONTKNOW == eCurLangCJK) + m_xAsianLanguageLB->set_active_id(LANGUAGE_NONE); + else + m_xAsianLanguageLB->set_active_id(eCurLangCJK); + + if(LANGUAGE_NONE == eCurLangCTL || LANGUAGE_DONTKNOW == eCurLangCTL) + m_xComplexLanguageLB->set_active_id(LANGUAGE_NONE); + else + m_xComplexLanguageLB->set_active_id(eCurLangCTL); + + m_xWesternLanguageLB->save_active_id(); + m_xAsianLanguageLB->save_active_id(); + m_xComplexLanguageLB->save_active_id(); + m_xIgnoreLanguageChangeCB->save_state(); + m_xCurrentDocCB->save_state(); + + bool bEnable = !pLangConfig->aLinguConfig.IsReadOnly( "DefaultLocale" ); + m_xWesternLanguageFT->set_sensitive( bEnable ); + m_xWesternLanguageLB->set_sensitive( bEnable ); + + // check the box "For the current document only" + // set the focus to the Western Language box + const SfxPoolItem* pLang = nullptr; + if ( SfxItemState::SET == rSet->GetItemState(SID_SET_DOCUMENT_LANGUAGE, false, &pLang ) && static_cast(pLang)->GetValue() ) + { + m_xWesternLanguageLB->grab_focus(); + m_xCurrentDocCB->set_sensitive(true); + m_xCurrentDocCB->set_active(true); + } +} + +IMPL_LINK(OfaLanguagesTabPage, SupportHdl, weld::ToggleButton&, rBox, void) +{ + bool bCheck = rBox.get_active(); + if ( m_xAsianSupportCB.get() == &rBox ) + { + bool bReadonly = pLangConfig->aLinguConfig.IsReadOnly("DefaultLocale_CJK"); + bCheck = ( bCheck && !bReadonly ); + m_xAsianLanguageLB->set_sensitive( bCheck ); + if (rBox.get_sensitive()) + m_bOldAsian = bCheck; + } + else if ( m_xCTLSupportCB.get() == &rBox ) + { + bool bReadonly = pLangConfig->aLinguConfig.IsReadOnly("DefaultLocale_CTL"); + bCheck = ( bCheck && !bReadonly ); + m_xComplexLanguageLB->set_sensitive( bCheck ); + if (rBox.get_sensitive()) + m_bOldCtl = bCheck; + } + else + SAL_WARN( "cui.options", "OfaLanguagesTabPage::SupportHdl(): wrong rBox" ); +} + +namespace +{ + void lcl_checkLanguageCheckBox(weld::CheckButton& _rCB, bool _bNewValue, bool _bOldValue) + { + if ( _bNewValue ) + _rCB.set_active(true); + else + _rCB.set_active( _bOldValue ); +// #i15082# do not call save_state() in running dialog... +// _rCB.save_state(); + _rCB.set_sensitive( !_bNewValue ); + } +} + +IMPL_LINK_NOARG(OfaLanguagesTabPage, LocaleSettingHdl, weld::ComboBox&, void) +{ + LanguageType eLang = m_xLocaleSettingLB->get_active_id(); + SvtScriptType nType = SvtLanguageOptions::GetScriptTypeOfLanguage(eLang); + // first check if CTL must be enabled + // #103299# - if CTL font setting is not readonly + if(!pLangConfig->aLanguageOptions.IsReadOnly(SvtLanguageOptions::E_CTLFONT)) + { + bool bIsCTLFixed = bool(nType & SvtScriptType::COMPLEX); + lcl_checkLanguageCheckBox(*m_xCTLSupportCB, bIsCTLFixed, m_bOldCtl); + SupportHdl(*m_xCTLSupportCB); + } + // second check if CJK must be enabled + // #103299# - if CJK support is not readonly + if(!pLangConfig->aLanguageOptions.IsReadOnly(SvtLanguageOptions::E_ALLCJK)) + { + bool bIsCJKFixed = bool(nType & SvtScriptType::ASIAN); + lcl_checkLanguageCheckBox(*m_xAsianSupportCB, bIsCJKFixed, m_bOldAsian); + SupportHdl(*m_xAsianSupportCB); + } + + const NfCurrencyEntry& rCurr = SvNumberFormatter::GetCurrencyEntry( + (eLang == LANGUAGE_USER_SYSTEM_CONFIG) ? MsLangId::getSystemLanguage() : eLang); + const OUString aDefaultID = "default"; + // Update the "Default ..." currency. + m_xCurrencyLB->remove_id(aDefaultID); + OUString aDefaultCurr = m_sSystemDefaultString + " - " + rCurr.GetBankSymbol(); + m_xCurrencyLB->insert(0, aDefaultCurr, &aDefaultID, nullptr, nullptr); + assert(m_xCurrencyLB->find_id(aDefaultID) != -1); + m_xCurrencyLB->set_active_text(aDefaultCurr); + + // obtain corresponding locale data + LanguageTag aLanguageTag( eLang); + LocaleDataWrapper aLocaleWrapper( aLanguageTag ); + + // update the decimal separator key of the related CheckBox + OUString sTempLabel(m_sDecimalSeparatorLabel); + sTempLabel = sTempLabel.replaceFirst("%1", aLocaleWrapper.getNumDecimalSep() ); + m_xDecimalSeparatorCB->set_label(sTempLabel); + + // update the date acceptance patterns + OUString aDatePatternsString = lcl_getDatePatternsConfigString( aLocaleWrapper); + m_bDatePatternsValid = true; + m_xDatePatternsED->set_text( aDatePatternsString); +} + +IMPL_LINK( OfaLanguagesTabPage, DatePatternsHdl, weld::Entry&, rEd, void ) +{ + const OUString aPatterns(rEd.get_text()); + OUStringBuffer aBuf( aPatterns); + sal_Int32 nChar = 0; + bool bValid = true; + bool bModified = false; + if (!aPatterns.isEmpty()) + { + for (sal_Int32 nIndex=0; nIndex >= 0 && bValid; ++nChar) + { + const OUString aPat( aPatterns.getToken( 0, ';', nIndex)); + if (aPat.isEmpty() && nIndex < 0) + { + // Indicating failure when about to append a pattern is too + // confusing. Empty patterns are ignored anyway when sequencing + // to SvtSysLocale. + continue; // for + } + else if (aPat.getLength() < 2) + bValid = false; + else + { + bool bY, bM, bD; + bY = bM = bD = false; + bool bSep = true; + for (sal_Int32 i = 0; i < aPat.getLength() && bValid; /*nop*/) + { + const sal_Int32 j = i; + const sal_uInt32 c = aPat.iterateCodePoints( &i); + // Only one Y,M,D per pattern, separated by any character(s). + switch (c) + { + case 'y': + case 'Y': + if (bY || !bSep) + bValid = false; + else if (c == 'y') + { + aBuf[nChar] = 'Y'; + bModified = true; + } + bY = true; + bSep = false; + break; + case 'm': + case 'M': + if (bM || !bSep) + bValid = false; + else if (c == 'm') + { + aBuf[nChar] = 'M'; + bModified = true; + } + bM = true; + bSep = false; + break; + case 'd': + case 'D': + if (bD || !bSep) + bValid = false; + else if (c == 'd') + { + aBuf[nChar] = 'D'; + bModified = true; + } + bD = true; + bSep = false; + break; + default: + // A pattern must not start with a separator (but + // may end with). + if (!(bY || bM || bD)) + bValid = false; + bSep = true; + } + nChar += i-j; + } + // At least one of Y,M,D + bValid &= (bY || bM || bD); + } + } + } + if (bModified) + rEd.replace_selection(aBuf.makeStringAndClear()); + if (bValid) + rEd.set_message_type(weld::EntryMessageType::Normal); + else + rEd.set_message_type(weld::EntryMessageType::Error); + m_bDatePatternsValid = bValid; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/optgdlg.hxx b/cui/source/options/optgdlg.hxx new file mode 100644 index 000000000..e01bca949 --- /dev/null +++ b/cui/source/options/optgdlg.hxx @@ -0,0 +1,185 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_OPTIONS_OPTGDLG_HXX +#define INCLUDED_CUI_SOURCE_OPTIONS_OPTGDLG_HXX +#include +#include +#include + +class CanvasSettings; +class SvtOptionsDrawinglayer; + +namespace vcl { + class IconThemeInfo; +} + +namespace svt { + class SkiaCfg; +} + +class OfaMiscTabPage : public SfxTabPage +{ +private: + OUString m_aStrDateInfo; + + std::unique_ptr m_xExtHelpCB; + std::unique_ptr m_xPopUpNoHelpCB; + std::unique_ptr m_xShowTipOfTheDay; + std::unique_ptr m_xFileDlgFrame; + std::unique_ptr m_xPrintDlgFrame; + std::unique_ptr m_xFileDlgROImage; + std::unique_ptr m_xFileDlgCB; + std::unique_ptr m_xPrintDlgCB; + std::unique_ptr m_xDocStatusCB; + std::unique_ptr m_xYearFrame; + std::unique_ptr m_xYearValueField; + std::unique_ptr m_xToYearFT; + std::unique_ptr m_xCollectUsageInfo; + std::unique_ptr m_xCrashReport; + std::unique_ptr m_xQuickStarterFrame; + std::unique_ptr m_xQuickLaunchCB; +#if defined(_WIN32) + std::unique_ptr m_xFileAssocFrame; + std::unique_ptr m_xFileAssocBtn; +#endif + + DECL_LINK(TwoFigureHdl, weld::SpinButton&, void); +#if defined(_WIN32) + DECL_STATIC_LINK(OfaMiscTabPage, FileAssocClick, weld::Button&, void); +#endif +protected: + virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override; + +public: + OfaMiscTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + virtual ~OfaMiscTabPage() override; + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet ); + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; +}; + +class SvtTabAppearanceCfg; + +class OfaViewTabPage : public SfxTabPage +{ +private: + sal_Int32 nSizeLB_InitialSelection; + sal_Int32 nSidebarSizeLB_InitialSelection; + sal_Int32 nNotebookbarSizeLB_InitialSelection; + sal_Int32 nStyleLB_InitialSelection; + + std::unique_ptr pAppearanceCfg; + std::unique_ptr pCanvasSettings; + std::unique_ptr mpDrawinglayerOpt; + std::unique_ptr mpSkiaConfig; + + std::vector mInstalledIconThemes; + + std::unique_ptr m_xIconSizeLB; + std::unique_ptr m_xSidebarIconSizeLB; + std::unique_ptr m_xNotebookbarIconSizeLB; + std::unique_ptr m_xIconStyleLB; + + std::unique_ptr m_xFontAntiAliasing; + std::unique_ptr m_xAAPointLimitLabel; + std::unique_ptr m_xAAPointLimit; + + std::unique_ptr m_xMenuIconBox; + std::unique_ptr m_xMenuIconsLB; + + std::unique_ptr m_xContextMenuShortcutsLB; + + std::unique_ptr m_xFontShowCB; + + std::unique_ptr m_xUseHardwareAccell; + std::unique_ptr m_xUseAntiAliase; + std::unique_ptr m_xUseSkia; + std::unique_ptr m_xForceSkiaRaster; + + std::unique_ptr m_xSkiaStatusEnabled; + std::unique_ptr m_xSkiaStatusDisabled; + + std::unique_ptr m_xMousePosLB; + std::unique_ptr m_xMouseMiddleLB; + + DECL_LINK(OnAntialiasingToggled, weld::ToggleButton&, void); + DECL_LINK(OnForceSkiaRasterToggled, weld::ToggleButton&, void); + void UpdateSkiaStatus(); + +public: + OfaViewTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + virtual ~OfaViewTabPage() override; + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet ); + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; +}; + +struct LanguageConfig_Impl; + +class OfaLanguagesTabPage : public SfxTabPage +{ + bool m_bOldAsian; + bool m_bOldCtl; + std::unique_ptr pLangConfig; + + OUString m_sUserLocaleValue; + OUString m_sSystemDefaultString; + OUString m_sDecimalSeparatorLabel; + + bool m_bDatePatternsValid; + + std::unique_ptr m_xUserInterfaceLB; + std::unique_ptr m_xLocaleSettingFT; + std::unique_ptr m_xLocaleSettingLB; + std::unique_ptr m_xDecimalSeparatorCB; + std::unique_ptr m_xCurrencyFT; + std::unique_ptr m_xCurrencyLB; + std::unique_ptr m_xDatePatternsFT; + std::unique_ptr m_xDatePatternsED; + + std::unique_ptr m_xWesternLanguageLB; + std::unique_ptr m_xWesternLanguageFT; + std::unique_ptr m_xAsianLanguageLB; + std::unique_ptr m_xComplexLanguageLB; + std::unique_ptr m_xCurrentDocCB; + std::unique_ptr m_xAsianSupportCB; + std::unique_ptr m_xCTLSupportCB; + std::unique_ptr m_xIgnoreLanguageChangeCB; + + DECL_LINK(SupportHdl, weld::ToggleButton&, void); + DECL_LINK(LocaleSettingHdl, weld::ComboBox&, void); + DECL_LINK(DatePatternsHdl, weld::Entry&, void); + +public: + OfaLanguagesTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + virtual ~OfaLanguagesTabPage() override; + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet ); + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; +}; + +#endif // INCLUDED_CUI_SOURCE_OPTIONS_OPTGDLG_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/optgenrl.cxx b/cui/source/options/optgenrl.cxx new file mode 100644 index 000000000..6fcef3319 --- /dev/null +++ b/cui/source/options/optgenrl.cxx @@ -0,0 +1,508 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +#include +#if HAVE_FEATURE_GPGME +# include +# include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +using namespace css; + +namespace +{ + +// rows +enum RowType +{ + Row_Company, + Row_Name, + Row_Name_Russian, + Row_Name_Eastern, + Row_Street, + Row_Street_Russian, + Row_City, + Row_City_US, + Row_Country, + Row_TitlePos, + Row_Phone, + Row_FaxMail, + + nRowCount +}; + +// language flags +namespace Lang +{ + unsigned const Others = 1; + unsigned const Russian = 2; + unsigned const Eastern = 4; + unsigned const US = 8; + unsigned const All = static_cast(-1); +} + + +// vRowInfo[] -- rows (text + one or more edit boxes) +// The order is the same as in RowType above, which is up to down. + +struct +{ + // id of the text + const char *pTextId; + // language flags (see Lang above): + // which language is this row for? + unsigned nLangFlags; +} +const vRowInfo[] = +{ + { "companyft", Lang::All }, + { "nameft", Lang::All & ~Lang::Russian & ~Lang::Eastern }, + { "rusnameft", Lang::Russian }, + { "eastnameft", Lang::Eastern }, + { "streetft", Lang::All & ~Lang::Russian }, + { "russtreetft", Lang::Russian }, + { "icityft", Lang::All & ~Lang::US }, + { "cityft", Lang::US }, + { "countryft", Lang::All }, + { "titleft", Lang::All }, + { "phoneft", Lang::All }, + { "faxft", Lang::All }, +}; + + +// vFieldInfo[] -- edit boxes +// The order is up to down, and then left to right. + +struct +{ + // in which row? + RowType eRow; + // id of the edit box + const char *pEditId; + // id for SvtUserOptions in unotools/useroptions.hxx + UserOptToken nUserOptionsId; + // id for settings the focus (defined in svx/optgenrl.hxx) + EditPosition nGrabFocusId; +} +const vFieldInfo[] = +{ + // Company + { Row_Company, "company", UserOptToken::Company, EditPosition::COMPANY }, + // Name + { Row_Name, "firstname", UserOptToken::FirstName, EditPosition::FIRSTNAME }, + { Row_Name, "lastname", UserOptToken::LastName, EditPosition::LASTNAME }, + { Row_Name, "shortname", UserOptToken::ID, EditPosition::SHORTNAME }, + // Name (russian) + { Row_Name_Russian, "ruslastname", UserOptToken::LastName, EditPosition::LASTNAME }, + { Row_Name_Russian, "rusfirstname", UserOptToken::FirstName, EditPosition::FIRSTNAME }, + { Row_Name_Russian, "rusfathersname", UserOptToken::FathersName, EditPosition::UNKNOWN }, + { Row_Name_Russian, "russhortname", UserOptToken::ID, EditPosition::SHORTNAME }, + // Name (eastern: reversed name ord + { Row_Name_Eastern, "eastlastname", UserOptToken::LastName, EditPosition::LASTNAME }, + { Row_Name_Eastern, "eastfirstname", UserOptToken::FirstName, EditPosition::FIRSTNAME }, + { Row_Name_Eastern, "eastshortname", UserOptToken::ID, EditPosition::SHORTNAME }, + // Street + { Row_Street, "street", UserOptToken::Street, EditPosition::STREET }, + // Street (russian) + { Row_Street_Russian, "russtreet", UserOptToken::Street, EditPosition::STREET }, + { Row_Street_Russian, "apartnum", UserOptToken::Apartment, EditPosition::UNKNOWN }, + // City + { Row_City, "izip", UserOptToken::Zip, EditPosition::PLZ }, + { Row_City, "icity", UserOptToken::City, EditPosition::CITY }, + // City (US) + { Row_City_US, "city", UserOptToken::City, EditPosition::CITY }, + { Row_City_US, "state", UserOptToken::State, EditPosition::STATE }, + { Row_City_US, "zip", UserOptToken::Zip, EditPosition::PLZ }, + // Country + { Row_Country, "country", UserOptToken::Country, EditPosition::COUNTRY }, + // Title/Position + { Row_TitlePos, "title", UserOptToken::Title, EditPosition::TITLE }, + { Row_TitlePos, "position", UserOptToken::Position, EditPosition::POSITION }, + // Phone + { Row_Phone, "home", UserOptToken::TelephoneHome, EditPosition::TELPRIV }, + { Row_Phone, "work", UserOptToken::TelephoneWork, EditPosition::TELCOMPANY }, + // Fax/Mail + { Row_FaxMail, "fax", UserOptToken::Fax, EditPosition::FAX }, + { Row_FaxMail, "email", UserOptToken::Email, EditPosition::EMAIL }, +}; + + +} // namespace + + +// Row + +struct SvxGeneralTabPage::Row +{ + // row label + std::unique_ptr xLabel; + // first and last field in the row (last is exclusive) + unsigned nFirstField, nLastField; + +public: + explicit Row (std::unique_ptr xLabel_) + : xLabel(std::move(xLabel_)) + , nFirstField(0) + , nLastField(0) + { + xLabel->show(); + } +}; + + +// Field + +struct SvxGeneralTabPage::Field +{ + // which field is this? (in vFieldInfo[] above) + unsigned iField; + // edit box + std::unique_ptr xEdit; + std::unique_ptr xParent; + +public: + Field (std::unique_ptr xEdit_, unsigned iField_) + : iField(iField_) + , xEdit(std::move(xEdit_)) + , xParent(xEdit->weld_parent()) + { + //We want all widgets inside a container, so each row of the toplevel + //grid has another container in it. To avoid adding spacing to these + //empty grids they all default to invisible, so show them if their + //children are visible + xParent->show(); + xEdit->show(); + } +}; + +SvxGeneralTabPage::SvxGeneralTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreSet) + : SfxTabPage(pPage, pController, "cui/ui/optuserpage.ui", "OptUserPage", &rCoreSet) + , m_xUseDataCB(m_xBuilder->weld_check_button("usefordocprop")) + , m_xCryptoFrame(m_xBuilder->weld_widget( "cryptography")) + , m_xSigningKeyLB(m_xBuilder->weld_combo_box("signingkey")) + , m_xEncryptionKeyLB(m_xBuilder->weld_combo_box("encryptionkey")) + , m_xEncryptToSelfCB(m_xBuilder->weld_check_button("encrypttoself")) +{ + InitControls(); +#if HAVE_FEATURE_GPGME + InitCryptography(); +#else + m_xCryptoFrame->hide(); +#endif + + SetExchangeSupport(); // this page needs ExchangeSupport + SetLinks(); +} + +SvxGeneralTabPage::~SvxGeneralTabPage() +{ +} + +// Initializes the titles and the edit boxes, +// according to vRowInfo[] and vFieldInfo[] above. +void SvxGeneralTabPage::InitControls () +{ + // which language bit do we use? (see Lang and vRowInfo[] above) + unsigned LangBit; + LanguageType l = Application::GetSettings().GetUILanguageTag().getLanguageType(); + if (l == LANGUAGE_ENGLISH_US) + LangBit = Lang::US; + else if (l == LANGUAGE_RUSSIAN) + LangBit = Lang::Russian; + else + { + if (MsLangId::isFamilyNameFirst(l)) + LangBit = Lang::Eastern; + else + LangBit = Lang::Others; + } + + // creating rows + unsigned iField = 0; + for (unsigned iRow = 0; iRow != nRowCount; ++iRow) + { + RowType const eRow = static_cast(iRow); + // is the row visible? + if (!(vRowInfo[iRow].nLangFlags & LangBit)) + continue; + // creating row + vRows.push_back(std::make_shared( + m_xBuilder->weld_label(vRowInfo[iRow].pTextId))); + Row& rRow = *vRows.back(); + // fields in the row + static unsigned const nFieldCount = SAL_N_ELEMENTS(vFieldInfo); + // skipping other (invisible) rows + while (iField != nFieldCount && vFieldInfo[iField].eRow != eRow) + ++iField; + // fields in the row + rRow.nFirstField = vFields.size(); + for ( ; iField != nFieldCount && vFieldInfo[iField].eRow == eRow; ++iField) + { + // creating edit field + vFields.push_back(std::make_shared( + m_xBuilder->weld_entry(vFieldInfo[iField].pEditId), iField)); + // "short name" field? + if (vFieldInfo[iField].nUserOptionsId == UserOptToken::ID) + { + nNameRow = vRows.size() - 1; + nShortNameField = vFields.size() - 1; + } + } + rRow.nLastField = vFields.size(); + } +} + +void SvxGeneralTabPage::InitCryptography() +{ +#if HAVE_FEATURE_GPGME + m_xCryptoFrame->show(); + + uno::Reference< xml::crypto::XSEInitializer > xSEInitializer; + try + { + xSEInitializer = xml::crypto::GPGSEInitializer::create( comphelper::getProcessComponentContext() ); + uno::Reference xSC = xSEInitializer->createSecurityContext( OUString() ); + if (xSC.is()) + { + uno::Reference xSE = xSC->getSecurityEnvironment(); + uno::Sequence> xCertificates = xSE->getPersonalCertificates(); + + if (xCertificates.hasElements()) + { + for (auto& xCert : xCertificates) + { + m_xSigningKeyLB->append_text( xCert->getIssuerName()); + m_xEncryptionKeyLB->append_text( xCert->getIssuerName()); + } + } + + //tdf#115015: wrap checkbox text and listboxes if necessary + int nPrefWidth(m_xEncryptToSelfCB->get_preferred_size().Width()); + int nMaxWidth = m_xEncryptToSelfCB->get_approximate_digit_width() * 40; + if (nPrefWidth > nMaxWidth) + { + m_xSigningKeyLB->set_size_request(nMaxWidth, -1); + m_xEncryptionKeyLB->set_size_request(nMaxWidth, -1); + m_xEncryptToSelfCB->set_label_line_wrap(true); + m_xEncryptToSelfCB->set_size_request(nMaxWidth, -1); + } + } + } + catch ( uno::Exception const & ) + {} +#endif + +} + +void SvxGeneralTabPage::SetLinks () +{ + // link for updating the initials + Link aLink = LINK( this, SvxGeneralTabPage, ModifyHdl_Impl ); + Row& rNameRow = *vRows[nNameRow]; + for (unsigned i = rNameRow.nFirstField; i != rNameRow.nLastField - 1; ++i) + vFields[i]->xEdit->connect_changed(aLink); +} + + +std::unique_ptr SvxGeneralTabPage::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet ) +{ + return std::make_unique( pPage, pController, *rAttrSet ); +} + +bool SvxGeneralTabPage::FillItemSet( SfxItemSet* ) +{ + // remove leading and trailing whitespaces + for (auto const & i: vFields) + i->xEdit->set_text(comphelper::string::strip(i->xEdit->get_text(), ' ')); + + bool bModified = false; + bModified |= GetData_Impl(); + SvtSaveOptions aSaveOpt; + if (m_xUseDataCB->get_active() != aSaveOpt.IsUseUserData()) + { + aSaveOpt.SetUseUserData(m_xUseDataCB->get_active()); + bModified = true; + } + return bModified; +} + +void SvxGeneralTabPage::Reset( const SfxItemSet* rSet ) +{ + SetData_Impl(); + + sal_uInt16 const nWhich = GetWhich(SID_FIELD_GRABFOCUS); + + if (rSet->GetItemState(nWhich) == SfxItemState::SET) + { + EditPosition nField = static_cast(static_cast(rSet->Get(nWhich)).GetValue()); + if (nField != EditPosition::UNKNOWN) + { + for (auto const & i: vFields) + if (nField == vFieldInfo[i->iField].nGrabFocusId) + i->xEdit->grab_focus(); + } + else + vFields.front()->xEdit->grab_focus(); + } + + m_xUseDataCB->set_active(SvtSaveOptions().IsUseUserData()); +} + + +// ModifyHdl_Impl() +// This handler updates the initials (short name) +// when one of the name fields was updated. +IMPL_LINK( SvxGeneralTabPage, ModifyHdl_Impl, weld::Entry&, rEdit, void ) +{ + // short name field and row + Field& rShortName = *vFields[nShortNameField]; + Row& rNameRow = *vRows[nNameRow]; + // number of initials + unsigned const nInits = rNameRow.nLastField - rNameRow.nFirstField - 1; + // which field was updated? (in rNameRow) + unsigned nField = nInits; + for (unsigned i = 0; i != nInits; ++i) + { + if (vFields[rNameRow.nFirstField + i]->xEdit.get() == &rEdit) + nField = i; + } + // updating the initial + if (!(nField < nInits && rShortName.xEdit->get_sensitive())) + return; + + OUString sShortName = rShortName.xEdit->get_text(); + // clear short name if it contains more characters than the number of initials + if (o3tl::make_unsigned(sShortName.getLength()) > nInits) + { + rShortName.xEdit->set_text(OUString()); + } + while (o3tl::make_unsigned(sShortName.getLength()) < nInits) + sShortName += " "; + OUString sName = rEdit.get_text(); + OUString sLetter = sName.isEmpty() + ? OUString(u' ') : sName.copy(0, 1); + rShortName.xEdit->set_text(sShortName.replaceAt(nField, 1, sLetter).trim()); +} + + +bool SvxGeneralTabPage::GetData_Impl() +{ + // updating + SvtUserOptions aUserOpt; + for (auto const & i: vFields) + aUserOpt.SetToken( + vFieldInfo[i->iField].nUserOptionsId, + i->xEdit->get_text() + ); + + // modified? + bool bModified = false; + for (auto const & i: vFields) + { + if (i->xEdit->get_value_changed_from_saved()) + { + bModified = true; + break; + } + } + +#if HAVE_FEATURE_GPGME + OUString aSK = m_xSigningKeyLB->get_active() == 0 ? OUString() //i.e. no key + : m_xSigningKeyLB->get_active_text(); + OUString aEK = m_xEncryptionKeyLB->get_active() == 0 ? OUString() + : m_xEncryptionKeyLB->get_active_text(); + + aUserOpt.SetToken( UserOptToken::SigningKey, aSK ); + aUserOpt.SetToken( UserOptToken::EncryptionKey, aEK ); + aUserOpt.SetBoolValue( UserOptToken::EncryptToSelf, m_xEncryptToSelfCB->get_active() ); + + bModified |= m_xSigningKeyLB->get_value_changed_from_saved() || + m_xEncryptionKeyLB->get_value_changed_from_saved() || + m_xEncryptToSelfCB->get_state_changed_from_saved(); +#endif + + return bModified; +} + + +void SvxGeneralTabPage::SetData_Impl() +{ + // updating and disabling edit boxes + SvtUserOptions aUserOpt; + for (auto const & i: vRows) + { + Row& rRow = *i; + // the label is enabled if any of its edit fields are enabled + bool bEnableLabel = false; + for (unsigned iField = rRow.nFirstField; iField != rRow.nLastField; ++iField) + { + Field& rField = *vFields[iField]; + // updating content + UserOptToken const nToken = vFieldInfo[rField.iField].nUserOptionsId; + rField.xEdit->set_text(aUserOpt.GetToken(nToken)); + // is enabled? + bool const bEnableEdit = !aUserOpt.IsTokenReadonly(nToken); + rField.xEdit->set_sensitive(bEnableEdit); + bEnableLabel = bEnableLabel || bEnableEdit; + } + rRow.xLabel->set_sensitive(bEnableLabel); + } + + // saving + for (auto const & i: vFields) + i->xEdit->save_value(); + +#if HAVE_FEATURE_GPGME + OUString aSK = aUserOpt.GetToken(UserOptToken::SigningKey); + aSK.isEmpty() ? m_xSigningKeyLB->set_active( 0 ) //i.e. 'No Key' + : m_xSigningKeyLB->set_active_text( aSK ); + + OUString aEK = aUserOpt.GetToken(UserOptToken::EncryptionKey); + aEK.isEmpty() ? m_xEncryptionKeyLB->set_active( 0 ) //i.e. 'No Key' + : m_xEncryptionKeyLB->set_active_text( aEK ); + + m_xEncryptToSelfCB->set_active( aUserOpt.GetEncryptToSelf() ); +#endif +} + + +DeactivateRC SvxGeneralTabPage::DeactivatePage( SfxItemSet* pSet_ ) +{ + if ( pSet_ ) + FillItemSet( pSet_ ); + return DeactivateRC::LeavePage; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/opthtml.cxx b/cui/source/options/opthtml.cxx new file mode 100644 index 000000000..fca286ddb --- /dev/null +++ b/cui/source/options/opthtml.cxx @@ -0,0 +1,164 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include "opthtml.hxx" + + +OfaHtmlTabPage::OfaHtmlTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/opthtmlpage.ui", "OptHtmlPage", &rSet) + , m_xSize1NF(m_xBuilder->weld_spin_button("size1")) + , m_xSize2NF(m_xBuilder->weld_spin_button("size2")) + , m_xSize3NF(m_xBuilder->weld_spin_button("size3")) + , m_xSize4NF(m_xBuilder->weld_spin_button("size4")) + , m_xSize5NF(m_xBuilder->weld_spin_button("size5")) + , m_xSize6NF(m_xBuilder->weld_spin_button("size6")) + , m_xSize7NF(m_xBuilder->weld_spin_button("size7")) + , m_xNumbersEnglishUSCB(m_xBuilder->weld_check_button("numbersenglishus")) + , m_xUnknownTagCB(m_xBuilder->weld_check_button("unknowntag")) + , m_xIgnoreFontNamesCB(m_xBuilder->weld_check_button("ignorefontnames")) + , m_xStarBasicCB(m_xBuilder->weld_check_button("starbasic")) + , m_xStarBasicWarningCB(m_xBuilder->weld_check_button("starbasicwarning")) + , m_xPrintExtensionCB(m_xBuilder->weld_check_button("printextension")) + , m_xSaveGrfLocalCB(m_xBuilder->weld_check_button("savegrflocal")) + , m_xCharSetLB(new SvxTextEncodingBox(m_xBuilder->weld_combo_box("charset"))) +{ + // replace placeholder with UI string from language list + OUString aText(m_xNumbersEnglishUSCB->get_label()); + OUString aPlaceholder("%ENGLISHUSLOCALE"); + sal_Int32 nPos; + if ((nPos = aText.indexOf( aPlaceholder)) != -1) + { + const OUString& rStr = SvtLanguageTable::GetLanguageString( LANGUAGE_ENGLISH_US); + if (!rStr.isEmpty()) + { + aText = aText.replaceAt( nPos, aPlaceholder.getLength(), rStr); + m_xNumbersEnglishUSCB->set_label( aText); + } + } + + m_xStarBasicCB->connect_toggled(LINK(this, OfaHtmlTabPage, CheckBoxHdl_Impl)); + + // initialize the characterset listbox + m_xCharSetLB->FillWithMimeAndSelectBest(); +} + +OfaHtmlTabPage::~OfaHtmlTabPage() +{ +} + +std::unique_ptr OfaHtmlTabPage::Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet ) +{ + return std::make_unique(pPage, pController, *rAttrSet); +} + +bool OfaHtmlTabPage::FillItemSet( SfxItemSet* ) +{ + SvxHtmlOptions& rHtmlOpt = SvxHtmlOptions::Get(); + if(m_xSize1NF->get_value_changed_from_saved()) + rHtmlOpt.SetFontSize(0, static_cast(m_xSize1NF->get_value())); + if(m_xSize2NF->get_value_changed_from_saved()) + rHtmlOpt.SetFontSize(1, static_cast(m_xSize2NF->get_value())); + if(m_xSize3NF->get_value_changed_from_saved()) + rHtmlOpt.SetFontSize(2, static_cast(m_xSize3NF->get_value())); + if(m_xSize4NF->get_value_changed_from_saved()) + rHtmlOpt.SetFontSize(3, static_cast(m_xSize4NF->get_value())); + if(m_xSize5NF->get_value_changed_from_saved()) + rHtmlOpt.SetFontSize(4, static_cast(m_xSize5NF->get_value())); + if(m_xSize6NF->get_value_changed_from_saved()) + rHtmlOpt.SetFontSize(5, static_cast(m_xSize6NF->get_value())); + if(m_xSize7NF->get_value_changed_from_saved()) + rHtmlOpt.SetFontSize(6, static_cast(m_xSize7NF->get_value())); + + if(m_xNumbersEnglishUSCB->get_state_changed_from_saved()) + rHtmlOpt.SetNumbersEnglishUS(m_xNumbersEnglishUSCB->get_active()); + + if(m_xUnknownTagCB->get_state_changed_from_saved()) + rHtmlOpt.SetImportUnknown(m_xUnknownTagCB->get_active()); + + if(m_xIgnoreFontNamesCB->get_state_changed_from_saved()) + rHtmlOpt.SetIgnoreFontFamily(m_xIgnoreFontNamesCB->get_active()); + + if(m_xStarBasicCB->get_state_changed_from_saved()) + rHtmlOpt.SetStarBasic(m_xStarBasicCB->get_active()); + + if(m_xStarBasicWarningCB->get_state_changed_from_saved()) + rHtmlOpt.SetStarBasicWarning(m_xStarBasicWarningCB->get_active()); + + if(m_xSaveGrfLocalCB->get_state_changed_from_saved()) + rHtmlOpt.SetSaveGraphicsLocal(m_xSaveGrfLocalCB->get_active()); + + if(m_xPrintExtensionCB->get_state_changed_from_saved()) + rHtmlOpt.SetPrintLayoutExtension(m_xPrintExtensionCB->get_active()); + + if( m_xCharSetLB->GetSelectTextEncoding() != rHtmlOpt.GetTextEncoding() ) + rHtmlOpt.SetTextEncoding( m_xCharSetLB->GetSelectTextEncoding() ); + + return false; +} + +void OfaHtmlTabPage::Reset( const SfxItemSet* ) +{ + SvxHtmlOptions& rHtmlOpt = SvxHtmlOptions::Get(); + m_xSize1NF->set_value(rHtmlOpt.GetFontSize(0)); + m_xSize2NF->set_value(rHtmlOpt.GetFontSize(1)); + m_xSize3NF->set_value(rHtmlOpt.GetFontSize(2)); + m_xSize4NF->set_value(rHtmlOpt.GetFontSize(3)); + m_xSize5NF->set_value(rHtmlOpt.GetFontSize(4)); + m_xSize6NF->set_value(rHtmlOpt.GetFontSize(5)); + m_xSize7NF->set_value(rHtmlOpt.GetFontSize(6)); + m_xNumbersEnglishUSCB->set_active(rHtmlOpt.IsNumbersEnglishUS()); + m_xUnknownTagCB->set_active(rHtmlOpt.IsImportUnknown()); + m_xIgnoreFontNamesCB->set_active(rHtmlOpt.IsIgnoreFontFamily()); + + m_xStarBasicCB->set_active(rHtmlOpt.IsStarBasic()); + m_xStarBasicWarningCB->set_active(rHtmlOpt.IsStarBasicWarning()); + m_xStarBasicWarningCB->set_sensitive(!m_xStarBasicCB->get_active()); + m_xSaveGrfLocalCB->set_active(rHtmlOpt.IsSaveGraphicsLocal()); + m_xPrintExtensionCB->set_active(rHtmlOpt.IsPrintLayoutExtension()); + + m_xPrintExtensionCB->save_state(); + m_xStarBasicCB->save_state(); + m_xStarBasicWarningCB->save_state(); + m_xSaveGrfLocalCB->save_state(); + m_xSize1NF->save_value(); + m_xSize2NF->save_value(); + m_xSize3NF->save_value(); + m_xSize4NF->save_value(); + m_xSize5NF->save_value(); + m_xSize6NF->save_value(); + m_xSize7NF->save_value(); + m_xNumbersEnglishUSCB->save_state(); + m_xUnknownTagCB->save_state(); + m_xIgnoreFontNamesCB->save_state(); + + if( !rHtmlOpt.IsDefaultTextEncoding() && + m_xCharSetLB->GetSelectTextEncoding() != rHtmlOpt.GetTextEncoding() ) + m_xCharSetLB->SelectTextEncoding( rHtmlOpt.GetTextEncoding() ); +} + +IMPL_LINK(OfaHtmlTabPage, CheckBoxHdl_Impl, weld::ToggleButton&, rBox, void) +{ + m_xStarBasicWarningCB->set_sensitive(!rBox.get_active()); +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/opthtml.hxx b/cui/source/options/opthtml.hxx new file mode 100644 index 000000000..0468518f1 --- /dev/null +++ b/cui/source/options/opthtml.hxx @@ -0,0 +1,63 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_OPTIONS_OPTHTML_HXX +#define INCLUDED_CUI_SOURCE_OPTIONS_OPTHTML_HXX + +#include +#include + +class OfaHtmlTabPage : public SfxTabPage +{ + + std::unique_ptr m_xSize1NF; + std::unique_ptr m_xSize2NF; + std::unique_ptr m_xSize3NF; + std::unique_ptr m_xSize4NF; + std::unique_ptr m_xSize5NF; + std::unique_ptr m_xSize6NF; + std::unique_ptr m_xSize7NF; + + std::unique_ptr m_xNumbersEnglishUSCB; + std::unique_ptr m_xUnknownTagCB; + std::unique_ptr m_xIgnoreFontNamesCB; + + std::unique_ptr m_xStarBasicCB; + std::unique_ptr m_xStarBasicWarningCB; + std::unique_ptr m_xPrintExtensionCB; + std::unique_ptr m_xSaveGrfLocalCB; + std::unique_ptr m_xCharSetLB; + + DECL_LINK(CheckBoxHdl_Impl, weld::ToggleButton&, void); + +public: + OfaHtmlTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + virtual ~OfaHtmlTabPage() override; + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet ); + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; + +}; + + +#endif + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/optinet2.cxx b/cui/source/options/optinet2.cxx new file mode 100644 index 000000000..0644d84ec --- /dev/null +++ b/cui/source/options/optinet2.cxx @@ -0,0 +1,936 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "optinet2.hxx" +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "securityoptions.hxx" +#include "webconninfo.hxx" +#include "certpath.hxx" +#include "tsaurls.hxx" + +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::sfx2; + +namespace { + +bool isValidPort(OUString const & value) { + if (!comphelper::string::isdigitAsciiString(value)) { + return false; + } + auto const n = value.toUInt64(); + if (n > 65535) { + return false; + } + if (n != 0) { + return true; + } + // Overflow in OUString::toUInt64 returns 0, so need to check value contains only zeroes: + return std::u16string_view(value).find_first_not_of(u'0') == std::u16string_view::npos; +} + +} + +IMPL_LINK(SvxProxyTabPage, PortChangedHdl, weld::Entry&, rEdit, void) +{ + if (!isValidPort(rEdit.get_text())) + { + std::unique_ptr xErrorBox(Application::CreateMessageDialog(GetFrameWeld(), + VclMessageType::Warning, VclButtonsType::Ok, + CuiResId( RID_SVXSTR_OPT_PROXYPORTS))); + xErrorBox->run(); + } +} + +static const char g_aProxyModePN[] = "ooInetProxyType"; +static const char g_aHttpProxyPN[] = "ooInetHTTPProxyName"; +static const char g_aHttpPortPN[] = "ooInetHTTPProxyPort"; +static const char g_aHttpsProxyPN[] = "ooInetHTTPSProxyName"; +static const char g_aHttpsPortPN[] = "ooInetHTTPSProxyPort"; +static const char g_aFtpProxyPN[] = "ooInetFTPProxyName"; +static const char g_aFtpPortPN[] = "ooInetFTPProxyPort"; +static const char g_aNoProxyDescPN[] = "ooInetNoProxy"; + +IMPL_STATIC_LINK(SvxProxyTabPage, NumberOnlyTextFilterHdl, OUString&, rTest, bool) +{ + OUStringBuffer sAllowed; + for (sal_Int32 i = 0, nLen = rTest.getLength(); i < nLen; ++i) + { + if (rTest[i] >= '0' && rTest[i] <= '9') + sAllowed.append(rTest[i]); + } + rTest = sAllowed.makeStringAndClear(); + return true; +} + +IMPL_STATIC_LINK(SvxProxyTabPage, NoSpaceTextFilterHdl, OUString&, rTest, bool) +{ + rTest = rTest.replaceAll(" ", ""); + return true; +} + +/********************************************************************/ +/* */ +/* SvxProxyTabPage */ +/* */ +/********************************************************************/ +SvxProxyTabPage::SvxProxyTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/optproxypage.ui", "OptProxyPage", &rSet) + , m_xProxyModeLB(m_xBuilder->weld_combo_box("proxymode")) + , m_xHttpProxyFT(m_xBuilder->weld_label("httpft")) + , m_xHttpProxyED(m_xBuilder->weld_entry("http")) + , m_xHttpPortFT(m_xBuilder->weld_label("httpportft")) + , m_xHttpPortED(m_xBuilder->weld_entry("httpport")) + , m_xHttpsProxyFT(m_xBuilder->weld_label("httpsft")) + , m_xHttpsProxyED(m_xBuilder->weld_entry("https")) + , m_xHttpsPortFT(m_xBuilder->weld_label("httpsportft")) + , m_xHttpsPortED(m_xBuilder->weld_entry("httpsport")) + , m_xFtpProxyFT(m_xBuilder->weld_label("ftpft")) + , m_xFtpProxyED(m_xBuilder->weld_entry("ftp")) + , m_xFtpPortFT(m_xBuilder->weld_label("ftpportft")) + , m_xFtpPortED(m_xBuilder->weld_entry("ftpport")) + , m_xNoProxyForFT(m_xBuilder->weld_label("noproxyft")) + , m_xNoProxyForED(m_xBuilder->weld_entry("noproxy")) + , m_xNoProxyDescFT(m_xBuilder->weld_label("noproxydesc")) +{ + m_xHttpProxyED->connect_insert_text(LINK(this, SvxProxyTabPage, NoSpaceTextFilterHdl)); + m_xHttpPortED->connect_insert_text(LINK(this, SvxProxyTabPage, NumberOnlyTextFilterHdl)); + m_xHttpPortED->connect_changed(LINK(this, SvxProxyTabPage, PortChangedHdl)); + m_xHttpsProxyED->connect_insert_text(LINK(this, SvxProxyTabPage, NoSpaceTextFilterHdl)); + m_xHttpsPortED->connect_insert_text(LINK(this, SvxProxyTabPage, NumberOnlyTextFilterHdl)); + m_xHttpsPortED->connect_changed(LINK(this, SvxProxyTabPage, PortChangedHdl)); + m_xFtpProxyED->connect_insert_text(LINK(this, SvxProxyTabPage, NoSpaceTextFilterHdl)); + m_xFtpPortED->connect_insert_text(LINK(this, SvxProxyTabPage, NumberOnlyTextFilterHdl)); + m_xFtpPortED->connect_changed(LINK(this, SvxProxyTabPage, PortChangedHdl)); + + Link aLink = LINK( this, SvxProxyTabPage, LoseFocusHdl_Impl ); + m_xHttpPortED->connect_focus_out( aLink ); + m_xHttpsPortED->connect_focus_out( aLink ); + m_xFtpPortED->connect_focus_out( aLink ); + + m_xProxyModeLB->connect_changed(LINK( this, SvxProxyTabPage, ProxyHdl_Impl )); + + Reference< css::lang::XMultiServiceFactory > + xConfigurationProvider( + configuration::theDefaultProvider::get( + comphelper::getProcessComponentContext() ) ); + + beans::NamedValue aProperty; + aProperty.Name = "nodepath"; + aProperty.Value <<= OUString( "org.openoffice.Inet/Settings" ); + + Sequence< Any > aArgumentList( 1 ); + aArgumentList[0] <<= aProperty; + + m_xConfigurationUpdateAccess = xConfigurationProvider->createInstanceWithArguments( + "com.sun.star.configuration.ConfigurationUpdateAccess", + aArgumentList ); +} + +SvxProxyTabPage::~SvxProxyTabPage() +{ +} + +std::unique_ptr SvxProxyTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet ) +{ + return std::make_unique(pPage, pController, *rAttrSet); +} + +void SvxProxyTabPage::ReadConfigData_Impl() +{ + sal_Int32 nIntValue = 0; + + std::optional x(officecfg::Inet::Settings::ooInetProxyType::get()); + if (x) + { + nIntValue = *x; + m_xProxyModeLB->set_active(nIntValue); + } + + m_xHttpProxyED->set_text( officecfg::Inet::Settings::ooInetHTTPProxyName::get() ); + x = officecfg::Inet::Settings::ooInetHTTPProxyPort::get(); + if (x) + { + nIntValue = *x; + m_xHttpPortED->set_text( OUString::number( nIntValue )); + } + + m_xHttpsProxyED->set_text( officecfg::Inet::Settings::ooInetHTTPSProxyName::get() ); + x = officecfg::Inet::Settings::ooInetHTTPSProxyPort::get(); + if (x) + { + nIntValue = *x; + m_xHttpsPortED->set_text( OUString::number( nIntValue )); + } + + m_xFtpProxyED->set_text( officecfg::Inet::Settings::ooInetFTPProxyName::get() ); + x = officecfg::Inet::Settings::ooInetFTPProxyPort::get(); + if (x) + { + nIntValue = *x; + m_xFtpPortED->set_text( OUString::number( nIntValue )); + } + + m_xNoProxyForED->set_text( officecfg::Inet::Settings::ooInetNoProxy::get() ); +} + +void SvxProxyTabPage::ReadConfigDefaults_Impl() +{ + try + { + Reference< beans::XPropertyState > xPropertyState(m_xConfigurationUpdateAccess, UNO_QUERY_THROW); + + sal_Int32 nIntValue = 0; + OUString aStringValue; + + if( xPropertyState->getPropertyDefault(g_aHttpProxyPN) >>= aStringValue ) + { + m_xHttpProxyED->set_text( aStringValue ); + } + + if( xPropertyState->getPropertyDefault(g_aHttpPortPN) >>= nIntValue ) + { + m_xHttpPortED->set_text( OUString::number( nIntValue )); + } + + if( xPropertyState->getPropertyDefault(g_aHttpsProxyPN) >>= aStringValue ) + { + m_xHttpsProxyED->set_text( aStringValue ); + } + + if( xPropertyState->getPropertyDefault(g_aHttpsPortPN) >>= nIntValue ) + { + m_xHttpsPortED->set_text( OUString::number( nIntValue )); + } + + if( xPropertyState->getPropertyDefault(g_aFtpProxyPN) >>= aStringValue ) + { + m_xFtpProxyED->set_text( aStringValue ); + } + + if( xPropertyState->getPropertyDefault(g_aFtpPortPN) >>= nIntValue ) + { + m_xFtpPortED->set_text( OUString::number( nIntValue )); + } + + if( xPropertyState->getPropertyDefault(g_aNoProxyDescPN) >>= aStringValue ) + { + m_xNoProxyForED->set_text( aStringValue ); + } + } + catch (const beans::UnknownPropertyException &) + { + SAL_WARN("cui.options", "SvxProxyTabPage::ReadConfigDefaults_Impl: UnknownPropertyException caught" ); + } + catch (const css::lang::WrappedTargetException &) { + SAL_WARN("cui.options", "SvxProxyTabPage::ReadConfigDefaults_Impl: WrappedTargetException caught" ); + } + catch (const RuntimeException &) + { + SAL_WARN("cui.options", "SvxProxyTabPage::ReadConfigDefaults_Impl: RuntimeException caught" ); + } +} + +void SvxProxyTabPage::RestoreConfigDefaults_Impl() +{ + try + { + Reference< beans::XPropertyState > xPropertyState(m_xConfigurationUpdateAccess, UNO_QUERY_THROW); + + xPropertyState->setPropertyToDefault(g_aProxyModePN); + xPropertyState->setPropertyToDefault(g_aHttpProxyPN); + xPropertyState->setPropertyToDefault(g_aHttpPortPN); + xPropertyState->setPropertyToDefault(g_aHttpsProxyPN); + xPropertyState->setPropertyToDefault(g_aHttpsPortPN); + xPropertyState->setPropertyToDefault(g_aFtpProxyPN); + xPropertyState->setPropertyToDefault(g_aFtpPortPN); + xPropertyState->setPropertyToDefault(g_aNoProxyDescPN); + + Reference< util::XChangesBatch > xChangesBatch(m_xConfigurationUpdateAccess, UNO_QUERY_THROW); + xChangesBatch->commitChanges(); + } + catch (const beans::UnknownPropertyException &) + { + SAL_WARN("cui.options", "SvxProxyTabPage::RestoreConfigDefaults_Impl: UnknownPropertyException caught" ); + } + catch (const css::lang::WrappedTargetException &) { + SAL_WARN("cui.options", "SvxProxyTabPage::RestoreConfigDefaults_Impl: WrappedTargetException caught" ); + } + catch (const RuntimeException &) + { + SAL_WARN("cui.options", "SvxProxyTabPage::RestoreConfigDefaults_Impl: RuntimeException caught" ); + } +} + +void SvxProxyTabPage::Reset(const SfxItemSet*) +{ + ReadConfigData_Impl(); + + m_xProxyModeLB->save_value(); + m_xHttpProxyED->save_value(); + m_xHttpPortED->save_value(); + m_xHttpsProxyED->save_value(); + m_xHttpsPortED->save_value(); + m_xFtpProxyED->save_value(); + m_xFtpPortED->save_value(); + m_xNoProxyForED->save_value(); + + EnableControls_Impl(); +} + +bool SvxProxyTabPage::FillItemSet(SfxItemSet* ) +{ + bool bModified = false; + + try { + Reference< beans::XPropertySet > xPropertySet(m_xConfigurationUpdateAccess, UNO_QUERY_THROW ); + + sal_Int32 nSelPos = m_xProxyModeLB->get_active(); + if(m_xProxyModeLB->get_value_changed_from_saved()) + { + if( nSelPos == 1 ) + { + RestoreConfigDefaults_Impl(); + return true; + } + + xPropertySet->setPropertyValue(g_aProxyModePN, Any(nSelPos)); + bModified = true; + } + + if(m_xHttpProxyED->get_value_changed_from_saved()) + { + xPropertySet->setPropertyValue( g_aHttpProxyPN, Any(m_xHttpProxyED->get_text())); + bModified = true; + } + + if ( m_xHttpPortED->get_value_changed_from_saved()) + { + xPropertySet->setPropertyValue( g_aHttpPortPN, Any(m_xHttpPortED->get_text().toInt32())); + bModified = true; + } + + if( m_xHttpsProxyED->get_value_changed_from_saved() ) + { + xPropertySet->setPropertyValue( g_aHttpsProxyPN, Any(m_xHttpsProxyED->get_text()) ); + bModified = true; + } + + if ( m_xHttpsPortED->get_value_changed_from_saved() ) + { + xPropertySet->setPropertyValue( g_aHttpsPortPN, Any(m_xHttpsPortED->get_text().toInt32()) ); + bModified = true; + } + + if( m_xFtpProxyED->get_value_changed_from_saved()) + { + xPropertySet->setPropertyValue( g_aFtpProxyPN, Any(m_xFtpProxyED->get_text()) ); + bModified = true; + } + + if ( m_xFtpPortED->get_value_changed_from_saved() ) + { + xPropertySet->setPropertyValue( g_aFtpPortPN, Any(m_xFtpPortED->get_text().toInt32())); + bModified = true; + } + + if ( m_xNoProxyForED->get_value_changed_from_saved() ) + { + xPropertySet->setPropertyValue( g_aNoProxyDescPN, Any( m_xNoProxyForED->get_text())); + bModified = true; + } + + Reference< util::XChangesBatch > xChangesBatch(m_xConfigurationUpdateAccess, UNO_QUERY_THROW); + xChangesBatch->commitChanges(); + } + catch (const css::lang::IllegalArgumentException &) { + SAL_WARN("cui.options", "SvxProxyTabPage::FillItemSet: IllegalArgumentException caught" ); + } + catch (const beans::UnknownPropertyException &) { + SAL_WARN("cui.options", "SvxProxyTabPage::FillItemSet: UnknownPropertyException caught" ); + } + catch (const beans::PropertyVetoException &) { + SAL_WARN("cui.options", "SvxProxyTabPage::FillItemSet: PropertyVetoException caught" ); + } + catch (const css::lang::WrappedTargetException &) { + SAL_WARN("cui.options", "SvxProxyTabPage::FillItemSet: WrappedTargetException caught" ); + } + catch (const RuntimeException &) { + SAL_WARN("cui.options", "SvxProxyTabPage::FillItemSet: RuntimeException caught" ); + } + + return bModified; +} + +void SvxProxyTabPage::EnableControls_Impl() +{ + m_xProxyModeLB->set_sensitive(!officecfg::Inet::Settings::ooInetNoProxy::isReadOnly()); + + const bool bManualConfig = m_xProxyModeLB->get_active() == 2; + + const bool bHTTPProxyNameEnabled = bManualConfig && !officecfg::Inet::Settings::ooInetHTTPProxyName::isReadOnly(); + const bool bHTTPProxyPortEnabled = bManualConfig && !officecfg::Inet::Settings::ooInetHTTPProxyPort::isReadOnly(); + m_xHttpProxyFT->set_sensitive(bHTTPProxyNameEnabled); + m_xHttpProxyED->set_sensitive(bHTTPProxyNameEnabled); + m_xHttpPortFT->set_sensitive(bHTTPProxyPortEnabled); + m_xHttpPortED->set_sensitive(bHTTPProxyPortEnabled); + + const bool bHTTPSProxyNameEnabled = bManualConfig && !officecfg::Inet::Settings::ooInetHTTPSProxyName::isReadOnly(); + const bool bHTTPSProxyPortEnabled = bManualConfig && !officecfg::Inet::Settings::ooInetHTTPSProxyPort::isReadOnly(); + m_xHttpsProxyFT->set_sensitive(bHTTPSProxyNameEnabled); + m_xHttpsProxyED->set_sensitive(bHTTPSProxyNameEnabled); + m_xHttpsPortFT->set_sensitive(bHTTPSProxyPortEnabled); + m_xHttpsPortED->set_sensitive(bHTTPSProxyPortEnabled); + + const bool bFTPProxyNameEnabled = bManualConfig && !officecfg::Inet::Settings::ooInetFTPProxyName::isReadOnly(); + const bool bFTPProxyPortEnabled = bManualConfig && !officecfg::Inet::Settings::ooInetFTPProxyPort::isReadOnly(); + m_xFtpProxyFT->set_sensitive(bFTPProxyNameEnabled); + m_xFtpProxyED->set_sensitive(bFTPProxyNameEnabled); + m_xFtpPortFT->set_sensitive(bFTPProxyPortEnabled); + m_xFtpPortED->set_sensitive(bFTPProxyPortEnabled); + + const bool bInetNoProxyEnabled = bManualConfig && !officecfg::Inet::Settings::ooInetNoProxy::isReadOnly(); + m_xNoProxyForFT->set_sensitive(bInetNoProxyEnabled); + m_xNoProxyForED->set_sensitive(bInetNoProxyEnabled); + m_xNoProxyDescFT->set_sensitive(bInetNoProxyEnabled); +} + +IMPL_LINK(SvxProxyTabPage, ProxyHdl_Impl, weld::ComboBox&, rBox, void) +{ + sal_Int32 nPos = rBox.get_active(); + + // Restore original system values + if( nPos == 1 ) + { + ReadConfigDefaults_Impl(); + } + + EnableControls_Impl(); +} + +IMPL_STATIC_LINK(SvxProxyTabPage, LoseFocusHdl_Impl, weld::Widget&, rControl, void) +{ + weld::Entry* pEdit = dynamic_cast(&rControl); + if (pEdit && !isValidPort(pEdit->get_text())) + pEdit->set_text(OUString('0')); +} + +/********************************************************************/ +/* */ +/* SvxSecurityTabPage */ +/* */ +/********************************************************************/ +SvxSecurityTabPage::SvxSecurityTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/optsecuritypage.ui", "OptSecurityPage", &rSet) + , mpSecOptions(new SvtSecurityOptions) + , m_xSecurityOptionsPB(m_xBuilder->weld_button("options")) + , m_xSavePasswordsCB(m_xBuilder->weld_check_button("savepassword")) + , m_xShowConnectionsPB(m_xBuilder->weld_button("connections")) + , m_xMasterPasswordCB(m_xBuilder->weld_check_button("usemasterpassword")) + , m_xMasterPasswordFT(m_xBuilder->weld_label("masterpasswordtext")) + , m_xMasterPasswordPB(m_xBuilder->weld_button("masterpassword")) + , m_xMacroSecFrame(m_xBuilder->weld_container("macrosecurity")) + , m_xMacroSecPB(m_xBuilder->weld_button("macro")) + , m_xCertFrame(m_xBuilder->weld_container("certificatepath")) + , m_xCertPathPB(m_xBuilder->weld_button("cert")) + , m_xTSAURLsFrame(m_xBuilder->weld_container("tsaurls")) + , m_xTSAURLsPB(m_xBuilder->weld_button("tsas")) + , m_xNoPasswordSaveFT(m_xBuilder->weld_label("nopasswordsave")) +{ + //fdo#65595, we need height-for-width support here, but for now we can + //bodge it + Size aPrefSize(m_xSavePasswordsCB->get_preferred_size()); + int nMaxWidth = m_xSavePasswordsCB->get_approximate_digit_width() * 40; + if (aPrefSize.Width() > nMaxWidth) + { + m_xSavePasswordsCB->set_label_line_wrap(true); + m_xSavePasswordsCB->set_size_request(nMaxWidth, -1); + } + + m_sPasswordStoringDeactivateStr = m_xNoPasswordSaveFT->get_label(); + + InitControls(); + + m_xSecurityOptionsPB->connect_clicked( LINK( this, SvxSecurityTabPage, SecurityOptionsHdl ) ); + m_xSavePasswordsCB->connect_clicked( LINK( this, SvxSecurityTabPage, SavePasswordHdl ) ); + m_xMasterPasswordPB->connect_clicked( LINK( this, SvxSecurityTabPage, MasterPasswordHdl ) ); + m_xMasterPasswordCB->connect_clicked( LINK( this, SvxSecurityTabPage, MasterPasswordCBHdl ) ); + m_xShowConnectionsPB->connect_clicked( LINK( this, SvxSecurityTabPage, ShowPasswordsHdl ) ); + m_xMacroSecPB->connect_clicked( LINK( this, SvxSecurityTabPage, MacroSecPBHdl ) ); + m_xCertPathPB->connect_clicked( LINK( this, SvxSecurityTabPage, CertPathPBHdl ) ); + m_xTSAURLsPB->connect_clicked( LINK( this, SvxSecurityTabPage, TSAURLsPBHdl ) ); + + ActivatePage( rSet ); +} + +SvxSecurityTabPage::~SvxSecurityTabPage() +{ +} + +IMPL_LINK_NOARG(SvxSecurityTabPage, SecurityOptionsHdl, weld::Button&, void) +{ + if (!m_xSecOptDlg) + m_xSecOptDlg.reset(new svx::SecurityOptionsDialog(GetFrameWeld(), mpSecOptions.get())); + m_xSecOptDlg->run(); +} + +IMPL_LINK_NOARG(SvxSecurityTabPage, SavePasswordHdl, weld::Button&, void) +{ + try + { + Reference< task::XPasswordContainer2 > xMasterPasswd( + task::PasswordContainer::create(comphelper::getProcessComponentContext())); + + if ( m_xSavePasswordsCB->get_active() ) + { + bool bOldValue = xMasterPasswd->allowPersistentStoring( true ); + xMasterPasswd->removeMasterPassword(); + + uno::Reference xTmpHandler(task::InteractionHandler::createWithParent(comphelper::getProcessComponentContext(), + GetDialogController()->getDialog()->GetXWindow())); + + if ( xMasterPasswd->changeMasterPassword(xTmpHandler) ) + { + m_xMasterPasswordPB->set_sensitive(true); + m_xMasterPasswordCB->set_active(true); + m_xMasterPasswordCB->set_sensitive(true); + m_xMasterPasswordFT->set_sensitive(true); + m_xShowConnectionsPB->set_sensitive(true); + } + else + { + xMasterPasswd->allowPersistentStoring( bOldValue ); + m_xSavePasswordsCB->set_active( false ); + } + } + else + { + std::unique_ptr xQueryBox(Application::CreateMessageDialog(GetFrameWeld(), + VclMessageType::Question, VclButtonsType::YesNo, + m_sPasswordStoringDeactivateStr)); + xQueryBox->set_default_response(RET_NO); + + sal_uInt16 nRet = xQueryBox->run(); + + if( RET_YES == nRet ) + { + xMasterPasswd->allowPersistentStoring( false ); + m_xMasterPasswordCB->set_active(true); + m_xMasterPasswordPB->set_sensitive( false ); + m_xMasterPasswordCB->set_sensitive( false ); + m_xMasterPasswordFT->set_sensitive( false ); + m_xShowConnectionsPB->set_sensitive( false ); + } + else + { + m_xSavePasswordsCB->set_active(true); + m_xMasterPasswordPB->set_sensitive(true); + m_xShowConnectionsPB->set_sensitive(true); + } + } + } + catch (const Exception&) + { + m_xSavePasswordsCB->set_active( !m_xSavePasswordsCB->get_active() ); + } +} + +IMPL_LINK_NOARG(SvxSecurityTabPage, MasterPasswordHdl, weld::Button&, void) +{ + try + { + Reference< task::XPasswordContainer2 > xMasterPasswd( + task::PasswordContainer::create(comphelper::getProcessComponentContext())); + + if ( xMasterPasswd->isPersistentStoringAllowed() ) + { + uno::Reference xTmpHandler(task::InteractionHandler::createWithParent(comphelper::getProcessComponentContext(), + GetDialogController()->getDialog()->GetXWindow())); + xMasterPasswd->changeMasterPassword(xTmpHandler); + } + } + catch (const Exception&) + {} +} + +IMPL_LINK_NOARG(SvxSecurityTabPage, MasterPasswordCBHdl, weld::Button&, void) +{ + try + { + Reference< task::XPasswordContainer2 > xMasterPasswd( + task::PasswordContainer::create(comphelper::getProcessComponentContext())); + + uno::Reference xTmpHandler(task::InteractionHandler::createWithParent(comphelper::getProcessComponentContext(), + GetDialogController()->getDialog()->GetXWindow())); + + if ( m_xMasterPasswordCB->get_active() ) + { + if (xMasterPasswd->isPersistentStoringAllowed() && xMasterPasswd->changeMasterPassword(xTmpHandler)) + { + m_xMasterPasswordPB->set_sensitive(true); + m_xMasterPasswordFT->set_sensitive(true); + } + else + { + m_xMasterPasswordCB->set_active( false ); + m_xMasterPasswordPB->set_sensitive(true); + m_xMasterPasswordFT->set_sensitive(true); + } + } + else + { + if ( xMasterPasswd->isPersistentStoringAllowed() && xMasterPasswd->useDefaultMasterPassword(xTmpHandler) ) + { + m_xMasterPasswordPB->set_sensitive( false ); + m_xMasterPasswordFT->set_sensitive( false ); + } + else + { + m_xMasterPasswordCB->set_active(true); + m_xMasterPasswordPB->set_sensitive(true); + m_xShowConnectionsPB->set_sensitive(true); + } + } + } + catch (const Exception&) + { + m_xSavePasswordsCB->set_active( !m_xSavePasswordsCB->get_active() ); + } +} + +IMPL_LINK_NOARG(SvxSecurityTabPage, ShowPasswordsHdl, weld::Button&, void) +{ + try + { + Reference< task::XPasswordContainer2 > xMasterPasswd( + task::PasswordContainer::create(comphelper::getProcessComponentContext())); + + uno::Reference xTmpHandler(task::InteractionHandler::createWithParent(comphelper::getProcessComponentContext(), + GetDialogController()->getDialog()->GetXWindow())); + + if ( xMasterPasswd->isPersistentStoringAllowed() && xMasterPasswd->authorizateWithMasterPassword(xTmpHandler) ) + { + svx::WebConnectionInfoDialog aDlg(GetFrameWeld()); + aDlg.run(); + } + } + catch (const Exception&) + {} +} + +IMPL_LINK_NOARG(SvxSecurityTabPage, CertPathPBHdl, weld::Button&, void) +{ + if (!mpCertPathDlg) + mpCertPathDlg.reset(new CertPathDialog(GetFrameWeld())); + + OUString sOrig = mpCertPathDlg->getDirectory(); + short nRet = mpCertPathDlg->run(); + + if (nRet == RET_OK && sOrig != mpCertPathDlg->getDirectory()) + { + SolarMutexGuard aGuard; + if (svtools::executeRestartDialog(comphelper::getProcessComponentContext(), nullptr, svtools::RESTART_REASON_ADDING_PATH)) + GetDialogController()->response(RET_OK); + } +} + +IMPL_LINK_NOARG(SvxSecurityTabPage, TSAURLsPBHdl, weld::Button&, void) +{ + // Unlike the mpCertPathDlg, we *don't* keep the same dialog object around between + // invocations. Seems clearer to my little brain that way. + TSAURLsDialog aTSAURLsDlg(GetFrameWeld()); + aTSAURLsDlg.run(); +} + +IMPL_LINK_NOARG(SvxSecurityTabPage, MacroSecPBHdl, weld::Button&, void) +{ + try + { + Reference< security::XDocumentDigitalSignatures > xD( + security::DocumentDigitalSignatures::createDefault(comphelper::getProcessComponentContext() ) ); + xD->setParentWindow(GetDialogController()->getDialog()->GetXWindow()); + xD->manageTrustedSources(); + } + catch (const Exception&) + { + TOOLS_WARN_EXCEPTION( "cui.options", ""); + } +} + +void SvxSecurityTabPage::InitControls() +{ +#ifndef UNX + m_xCertFrame->hide(); +#endif + + m_xMasterPasswordPB->set_sensitive( false ); + m_xMasterPasswordCB->set_sensitive( false ); + m_xMasterPasswordCB->set_active(true); + m_xMasterPasswordFT->set_sensitive( false ); + m_xShowConnectionsPB->set_sensitive( false ); + + // initialize the password saving checkbox + try + { + Reference< task::XPasswordContainer2 > xMasterPasswd( + task::PasswordContainer::create(comphelper::getProcessComponentContext())); + + if ( xMasterPasswd->isPersistentStoringAllowed() ) + { + m_xMasterPasswordCB->set_sensitive(true); + m_xShowConnectionsPB->set_sensitive(true); + m_xSavePasswordsCB->set_active(true); + + if ( xMasterPasswd->isDefaultMasterPasswordUsed() ) + m_xMasterPasswordCB->set_active( false ); + else + { + m_xMasterPasswordPB->set_sensitive(true); + m_xMasterPasswordCB->set_active(true); + m_xMasterPasswordFT->set_sensitive(true); + } + } + } + catch (const Exception&) + { + m_xSavePasswordsCB->set_sensitive( false ); + } +} + +std::unique_ptr SvxSecurityTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet ) +{ + return std::make_unique(pPage, pController, *rAttrSet); +} + +void SvxSecurityTabPage::ActivatePage( const SfxItemSet& ) +{ +} + +DeactivateRC SvxSecurityTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if( _pSet ) + FillItemSet( _pSet ); + return DeactivateRC::LeavePage; +} + +namespace +{ + bool CheckAndSave( SvtSecurityOptions& _rOpt, SvtSecurityOptions::EOption _eOpt, const bool _bIsChecked, bool& _rModfied ) + { + bool bModified = false; + if ( _rOpt.IsOptionEnabled( _eOpt ) ) + { + bModified = _rOpt.IsOptionSet( _eOpt ) != _bIsChecked; + if ( bModified ) + { + _rOpt.SetOption( _eOpt, _bIsChecked ); + _rModfied = true; + } + } + + return bModified; + } +} + +bool SvxSecurityTabPage::FillItemSet( SfxItemSet* ) +{ + bool bModified = false; + + if (m_xSecOptDlg) + { + CheckAndSave( *mpSecOptions, SvtSecurityOptions::EOption::DocWarnSaveOrSend, m_xSecOptDlg->IsSaveOrSendDocsChecked(), bModified ); + CheckAndSave( *mpSecOptions, SvtSecurityOptions::EOption::DocWarnSigning, m_xSecOptDlg->IsSignDocsChecked(), bModified ); + CheckAndSave( *mpSecOptions, SvtSecurityOptions::EOption::DocWarnPrint, m_xSecOptDlg->IsPrintDocsChecked(), bModified ); + CheckAndSave( *mpSecOptions, SvtSecurityOptions::EOption::DocWarnCreatePdf, m_xSecOptDlg->IsCreatePdfChecked(), bModified ); + CheckAndSave( *mpSecOptions, SvtSecurityOptions::EOption::DocWarnRemovePersonalInfo, m_xSecOptDlg->IsRemovePersInfoChecked(), bModified ); + CheckAndSave( *mpSecOptions, SvtSecurityOptions::EOption::DocWarnRecommendPassword, m_xSecOptDlg->IsRecommPasswdChecked(), bModified ); + CheckAndSave( *mpSecOptions, SvtSecurityOptions::EOption::CtrlClickHyperlink, m_xSecOptDlg->IsCtrlHyperlinkChecked(), bModified ); + CheckAndSave( *mpSecOptions, SvtSecurityOptions::EOption::BlockUntrustedRefererLinks, m_xSecOptDlg->IsBlockUntrustedRefererLinksChecked(), bModified ); + } + + return bModified; +} + +/*--------------------------------------------------------------------*/ + +void SvxSecurityTabPage::Reset( const SfxItemSet* ) +{ +} + +struct SvxEMailTabPage_Impl +{ + SvxEMailTabPage_Impl(): + sProgram(officecfg::Office::Common::ExternalMailer::Program::get()), + bROProgram( + officecfg::Office::Common::ExternalMailer::Program::isReadOnly()), + bHideContent( + officecfg::Office::Security::HiddenContent::RemoveHiddenContent::get()), + bROHideContent( + officecfg::Office::Security::HiddenContent::RemoveHiddenContent::isReadOnly()) + {} + + OUString sProgram; + bool bROProgram; + bool bHideContent; + bool bROHideContent; +}; + +SvxEMailTabPage::SvxEMailTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage( pPage, pController, "cui/ui/optemailpage.ui", "OptEmailPage", &rSet) + , pImpl(new SvxEMailTabPage_Impl) + , m_xMailContainer(m_xBuilder->weld_container("program")) + , m_xMailerURLFI(m_xBuilder->weld_image("lockemail")) + , m_xMailerURLED(m_xBuilder->weld_entry("url")) + , m_xMailerURLPB(m_xBuilder->weld_button("browse")) + , m_xSuppressHiddenContainer(m_xBuilder->weld_container("suppressHiddenCont")) + , m_xSuppressHiddenFI(m_xBuilder->weld_image("lockSuppressHidden")) + , m_xSuppressHidden(m_xBuilder->weld_check_button("suppressHidden")) + , m_xDefaultFilterFT(m_xBuilder->weld_label("browsetitle")) +{ + m_sDefaultFilterName = m_xDefaultFilterFT->get_label(); + m_xMailerURLPB->connect_clicked( LINK( this, SvxEMailTabPage, FileDialogHdl_Impl ) ); +} + +/* -------------------------------------------------------------------------*/ + +SvxEMailTabPage::~SvxEMailTabPage() +{ +} + +/* -------------------------------------------------------------------------*/ + +std::unique_ptr SvxEMailTabPage::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet ) +{ + return std::make_unique(pPage, pController, *rAttrSet); +} + +/* -------------------------------------------------------------------------*/ + +bool SvxEMailTabPage::FillItemSet( SfxItemSet* ) +{ + std::shared_ptr batch( + comphelper::ConfigurationChanges::create()); + if (!pImpl->bROProgram && m_xMailerURLED->get_value_changed_from_saved()) + { + pImpl->sProgram = m_xMailerURLED->get_text(); + officecfg::Office::Common::ExternalMailer::Program::set( + pImpl->sProgram, batch); + } + if (!pImpl->bROHideContent + && pImpl->bHideContent != m_xSuppressHidden->get_active()) + { + pImpl->bHideContent = m_xSuppressHidden->get_active(); + officecfg::Office::Security::HiddenContent::RemoveHiddenContent::set( + pImpl->bHideContent, batch); + } + batch->commit(); + return false; +} + +/* -------------------------------------------------------------------------*/ + +void SvxEMailTabPage::Reset( const SfxItemSet* ) +{ + m_xMailerURLED->set_sensitive(true); + m_xMailerURLPB->set_sensitive(true); + + if (pImpl->bROProgram) + m_xMailerURLFI->show(); + + m_xMailerURLED->set_text(pImpl->sProgram); + m_xMailerURLED->save_value(); + + m_xMailContainer->set_sensitive(!pImpl->bROProgram); + + if (pImpl->bROHideContent) + m_xSuppressHiddenFI->show(); + + m_xSuppressHidden->set_active(pImpl->bHideContent); + + m_xSuppressHiddenContainer->set_sensitive(!pImpl->bROHideContent); +} + +/* -------------------------------------------------------------------------*/ + +IMPL_LINK_NOARG(SvxEMailTabPage, FileDialogHdl_Impl, weld::Button&, void) +{ + if (pImpl->bROProgram) + return; + + FileDialogHelper aHelper(css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE, FileDialogFlags::NONE, GetFrameWeld()); + OUString sPath = m_xMailerURLED->get_text(); + if ( sPath.isEmpty() ) + sPath = "/usr/bin"; + + OUString sUrl; + osl::FileBase::getFileURLFromSystemPath(sPath, sUrl); + aHelper.SetDisplayDirectory(sUrl); + aHelper.AddFilter( m_sDefaultFilterName, "*"); + + if ( ERRCODE_NONE == aHelper.Execute() ) + { + sUrl = aHelper.GetPath(); + if (osl::FileBase::getSystemPathFromFileURL(sUrl, sPath) + != osl::FileBase::E_None) + { + sPath.clear(); + } + m_xMailerURLED->set_text(sPath); + } +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/optinet2.hxx b/cui/source/options/optinet2.hxx new file mode 100644 index 000000000..4d434ce8d --- /dev/null +++ b/cui/source/options/optinet2.hxx @@ -0,0 +1,163 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_OPTIONS_OPTINET2_HXX +#define INCLUDED_CUI_SOURCE_OPTIONS_OPTINET2_HXX + +#include +#include + +namespace svx { + class SecurityOptionsDialog; +} + +// class SvxProxyTabPage ------------------------------------------------- +class SvxProxyTabPage : public SfxTabPage +{ +private: + + std::unique_ptr m_xProxyModeLB; + + std::unique_ptr m_xHttpProxyFT; + std::unique_ptr m_xHttpProxyED; + std::unique_ptr m_xHttpPortFT; + std::unique_ptr m_xHttpPortED; + + std::unique_ptr m_xHttpsProxyFT; + std::unique_ptr m_xHttpsProxyED; + std::unique_ptr m_xHttpsPortFT; + std::unique_ptr m_xHttpsPortED; + + std::unique_ptr m_xFtpProxyFT; + std::unique_ptr m_xFtpProxyED; + std::unique_ptr m_xFtpPortFT; + std::unique_ptr m_xFtpPortED; + + std::unique_ptr m_xNoProxyForFT; + std::unique_ptr m_xNoProxyForED; + std::unique_ptr m_xNoProxyDescFT; + + css::uno::Reference< css::uno::XInterface > m_xConfigurationUpdateAccess; + + void EnableControls_Impl(); + void ReadConfigData_Impl(); + void ReadConfigDefaults_Impl(); + void RestoreConfigDefaults_Impl(); + + DECL_LINK(PortChangedHdl, weld::Entry&, void); + DECL_STATIC_LINK(SvxProxyTabPage, NumberOnlyTextFilterHdl, OUString&, bool); + DECL_STATIC_LINK(SvxProxyTabPage, NoSpaceTextFilterHdl, OUString&, bool); + DECL_LINK(ProxyHdl_Impl, weld::ComboBox&, void); + DECL_STATIC_LINK(SvxProxyTabPage, LoseFocusHdl_Impl, weld::Widget&, void); + +public: + SvxProxyTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + virtual ~SvxProxyTabPage() override; + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet ); + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; +}; + +// class SvxSecurityTabPage --------------------------------------------- + +class SvtSecurityOptions; +class CertPathDialog; +class SvxSecurityTabPage : public SfxTabPage +{ +private: + std::unique_ptr mpSecOptions; + std::unique_ptr m_xSecOptDlg; + + std::unique_ptr mpCertPathDlg; + + OUString m_sPasswordStoringDeactivateStr; + + std::unique_ptr m_xSecurityOptionsPB; + + std::unique_ptr m_xSavePasswordsCB; + std::unique_ptr m_xShowConnectionsPB; + + std::unique_ptr m_xMasterPasswordCB; + std::unique_ptr m_xMasterPasswordFT; + std::unique_ptr m_xMasterPasswordPB; + + std::unique_ptr m_xMacroSecFrame; + std::unique_ptr m_xMacroSecPB; + + std::unique_ptr m_xCertFrame; + std::unique_ptr m_xCertPathPB; + + std::unique_ptr m_xTSAURLsFrame; + std::unique_ptr m_xTSAURLsPB; + + std::unique_ptr m_xNoPasswordSaveFT; + + DECL_LINK(SecurityOptionsHdl, weld::Button&, void); + DECL_LINK(SavePasswordHdl, weld::Button&, void); + DECL_LINK(MasterPasswordHdl, weld::Button&, void); + DECL_LINK(MasterPasswordCBHdl, weld::Button&, void); + DECL_LINK(ShowPasswordsHdl, weld::Button&, void); + DECL_LINK(MacroSecPBHdl, weld::Button&, void ); + DECL_LINK(CertPathPBHdl, weld::Button&, void ); + DECL_LINK(TSAURLsPBHdl, weld::Button&, void ); + + void InitControls(); + +protected: + virtual void ActivatePage( const SfxItemSet& rSet ) override; + virtual DeactivateRC DeactivatePage( SfxItemSet* pSet ) override; + +public: + SvxSecurityTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet ); + virtual ~SvxSecurityTabPage() override; + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; +}; + +struct SvxEMailTabPage_Impl; +class SvxEMailTabPage : public SfxTabPage +{ + OUString m_sDefaultFilterName; + + std::unique_ptr pImpl; + + std::unique_ptr m_xMailContainer; + std::unique_ptr m_xMailerURLFI; + std::unique_ptr m_xMailerURLED; + std::unique_ptr m_xMailerURLPB; + std::unique_ptr m_xSuppressHiddenContainer; + std::unique_ptr m_xSuppressHiddenFI; + std::unique_ptr m_xSuppressHidden; + std::unique_ptr m_xDefaultFilterFT; + + DECL_LINK(FileDialogHdl_Impl, weld::Button&, void); + +public: + SvxEMailTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet ); + virtual ~SvxEMailTabPage() override; + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet ); + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; +}; + +#endif // INCLUDED_CUI_SOURCE_OPTIONS_OPTINET2_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/optjava.cxx b/cui/source/options/optjava.cxx new file mode 100644 index 000000000..f3c9dcfee --- /dev/null +++ b/cui/source/options/optjava.cxx @@ -0,0 +1,941 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +#include +#include +#include + +#include + +#include "optaboutconfig.hxx" +#include "optjava.hxx" +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if HAVE_FEATURE_JAVA +#include +#endif + +// define ---------------------------------------------------------------- + +#define CLASSPATH_DELIMITER SAL_PATHSEPARATOR + +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::ucb; +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star::uno; + +// class SvxJavaOptionsPage ---------------------------------------------- +SvxJavaOptionsPage::SvxJavaOptionsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/optadvancedpage.ui", "OptAdvancedPage", &rSet) + , m_aResetIdle("cui options SvxJavaOptionsPage Reset") + , xDialogListener(new ::svt::DialogClosedListener()) + , m_xJavaEnableCB(m_xBuilder->weld_check_button("javaenabled")) + , m_xJavaList(m_xBuilder->weld_tree_view("javas")) + , m_xJavaPathText(m_xBuilder->weld_label("javapath")) + , m_xAddBtn(m_xBuilder->weld_button("add")) + , m_xParameterBtn(m_xBuilder->weld_button("parameters")) + , m_xClassPathBtn(m_xBuilder->weld_button("classpath")) + , m_xExpertConfigBtn(m_xBuilder->weld_button("expertconfig")) + , m_xExperimentalCB(m_xBuilder->weld_check_button("experimental")) + , m_xMacroCB(m_xBuilder->weld_check_button("macrorecording")) + , m_xAddDialogText(m_xBuilder->weld_label("selectruntime")) + , m_xJavaFrame(m_xBuilder->weld_widget("javaframe")) +{ + m_sInstallText = m_xJavaPathText->get_label(); + m_sAddDialogText = m_xAddDialogText->get_label(); + + m_xJavaList->set_size_request(m_xJavaList->get_approximate_digit_width() * 30, + m_xJavaList->get_height_rows(8)); + + std::vector aWidths; + aWidths.push_back(m_xJavaList->get_checkbox_column_width()); + aWidths.push_back(m_xJavaList->get_pixel_size("Sun Microsystems Inc.").Width()); + m_xJavaList->set_column_fixed_widths(aWidths); + + std::vector aRadioColumns; + aRadioColumns.push_back(0); + m_xJavaList->set_toggle_columns_as_radio(aRadioColumns); + + m_xJavaEnableCB->connect_clicked( LINK( this, SvxJavaOptionsPage, EnableHdl_Impl ) ); + m_xJavaList->connect_toggled( LINK( this, SvxJavaOptionsPage, CheckHdl_Impl ) ); + m_xJavaList->connect_changed( LINK( this, SvxJavaOptionsPage, SelectHdl_Impl ) ); + m_xAddBtn->connect_clicked( LINK( this, SvxJavaOptionsPage, AddHdl_Impl ) ); + m_xParameterBtn->connect_clicked( LINK( this, SvxJavaOptionsPage, ParameterHdl_Impl ) ); + m_xClassPathBtn->connect_clicked( LINK( this, SvxJavaOptionsPage, ClassPathHdl_Impl ) ); + m_aResetIdle.SetInvokeHandler( LINK( this, SvxJavaOptionsPage, ResetHdl_Impl ) ); + + m_xExpertConfigBtn->connect_clicked( LINK( this, SvxJavaOptionsPage, ExpertConfigHdl_Impl) ); + if (!officecfg::Office::Common::Security::EnableExpertConfiguration::get()) + m_xExpertConfigBtn->set_sensitive(false); + + if (officecfg::Office::Common::Misc::MacroRecorderMode::isReadOnly()) + m_xMacroCB->set_sensitive(false); + + if (officecfg::Office::Common::Misc::ExperimentalMode::isReadOnly()) + m_xExperimentalCB->set_sensitive(false); + + xDialogListener->SetDialogClosedLink( LINK( this, SvxJavaOptionsPage, DialogClosedHdl ) ); + + EnableHdl_Impl(*m_xJavaEnableCB); +#if HAVE_FEATURE_JAVA + jfw_lock(); +#else + m_xJavaFrame->set_sensitive(false); +#endif +} + +SvxJavaOptionsPage::~SvxJavaOptionsPage() +{ + ClearJavaInfo(); +#if HAVE_FEATURE_JAVA + m_aAddedInfos.clear(); + + jfw_unlock(); +#endif +} + +IMPL_LINK_NOARG(SvxJavaOptionsPage, EnableHdl_Impl, weld::Button&, void) +{ + bool bEnable = m_xJavaEnableCB->get_active(); + m_xJavaList->set_sensitive(bEnable); +} + +IMPL_LINK(SvxJavaOptionsPage, CheckHdl_Impl, const row_col&, rRowCol, void) +{ + HandleCheckEntry(rRowCol.first); +} + +IMPL_LINK_NOARG(SvxJavaOptionsPage, SelectHdl_Impl, weld::TreeView&, void) +{ + UpdateJavaPathText(); +} + +IMPL_LINK_NOARG(SvxJavaOptionsPage, AddHdl_Impl, weld::Button&, void) +{ + try + { + Reference < XComponentContext > xContext( ::comphelper::getProcessComponentContext() ); + xFolderPicker = FolderPicker::create(xContext); + + OUString sWorkFolder = SvtPathOptions().GetWorkPath(); + xFolderPicker->setDisplayDirectory( sWorkFolder ); + xFolderPicker->setDescription( m_sAddDialogText ); + + Reference< XAsynchronousExecutableDialog > xAsyncDlg( xFolderPicker, UNO_QUERY ); + if ( xAsyncDlg.is() ) + xAsyncDlg->startExecuteModal( xDialogListener.get() ); + else if ( xFolderPicker.is() && xFolderPicker->execute() == ExecutableDialogResults::OK ) + AddFolder( xFolderPicker->getDirectory() ); + } + catch (const Exception&) + { + TOOLS_WARN_EXCEPTION( "cui.options", "SvxJavaOptionsPage::AddHdl_Impl()"); + } +} + +IMPL_LINK_NOARG(SvxJavaOptionsPage, ParameterHdl_Impl, weld::Button&, void) +{ +#if HAVE_FEATURE_JAVA + std::vector< OUString > aParameterList; + if (!m_xParamDlg) + { + m_xParamDlg.reset(new SvxJavaParameterDlg(GetFrameWeld())); + javaFrameworkError eErr = jfw_getVMParameters( &m_parParameters ); + if ( JFW_E_NONE == eErr && !m_parParameters.empty() ) + { + aParameterList = m_parParameters; + m_xParamDlg->SetParameters( aParameterList ); + } + } + else + { + aParameterList = m_xParamDlg->GetParameters(); + m_xParamDlg->DisableButtons(); //disable add, edit and remove button when dialog is reopened + } + + if (m_xParamDlg->run() == RET_OK) + { + if ( aParameterList != m_xParamDlg->GetParameters() ) + { + aParameterList = m_xParamDlg->GetParameters(); + if ( jfw_isVMRunning() ) + { + RequestRestart( svtools::RESTART_REASON_ASSIGNING_JAVAPARAMETERS ); + } + } + } + else + m_xParamDlg->SetParameters( aParameterList ); +#else + (void) this; // Silence loplugin:staticmethods +#endif +} + + +IMPL_LINK_NOARG(SvxJavaOptionsPage, ClassPathHdl_Impl, weld::Button&, void) +{ +#if HAVE_FEATURE_JAVA + OUString sClassPath; + + if ( !m_xPathDlg ) + { + m_xPathDlg.reset(new SvxJavaClassPathDlg(GetFrameWeld())); + javaFrameworkError eErr = jfw_getUserClassPath( &m_pClassPath ); + if ( JFW_E_NONE == eErr ) + { + sClassPath = m_pClassPath; + m_xPathDlg->SetClassPath( sClassPath ); + } + } + else + sClassPath = m_xPathDlg->GetClassPath(); + + m_xPathDlg->SetFocus(); + if (m_xPathDlg->run() == RET_OK) + { + + if (m_xPathDlg->GetClassPath() != sClassPath) + { + sClassPath = m_xPathDlg->GetClassPath(); + if ( jfw_isVMRunning() ) + { + RequestRestart( svtools::RESTART_REASON_ASSIGNING_FOLDERS ); + } + } + } + else + m_xPathDlg->SetClassPath( sClassPath ); +#else + (void) this; +#endif +} + + +IMPL_LINK_NOARG(SvxJavaOptionsPage, ResetHdl_Impl, Timer *, void) +{ + LoadJREs(); +} + + +IMPL_LINK_NOARG(SvxJavaOptionsPage, StartFolderPickerHdl, void*, void) +{ + try + { + Reference< XAsynchronousExecutableDialog > xAsyncDlg( xFolderPicker, UNO_QUERY ); + if ( xAsyncDlg.is() ) + xAsyncDlg->startExecuteModal( xDialogListener.get() ); + else if ( xFolderPicker.is() && xFolderPicker->execute() == ExecutableDialogResults::OK ) + AddFolder( xFolderPicker->getDirectory() ); + } + catch ( Exception const & ) + { + TOOLS_WARN_EXCEPTION( "cui.options", "SvxJavaOptionsPage::StartFolderPickerHdl()" ); + } +} + +IMPL_LINK( SvxJavaOptionsPage, DialogClosedHdl, DialogClosedEvent*, pEvt, void ) +{ + if ( RET_OK == pEvt->DialogResult ) + { + DBG_ASSERT( xFolderPicker.is(), "SvxJavaOptionsPage::DialogClosedHdl(): no folder picker" ); + + AddFolder( xFolderPicker->getDirectory() ); + } +} + +IMPL_LINK_NOARG(SvxJavaOptionsPage, ExpertConfigHdl_Impl, weld::Button&, void) +{ + CuiAboutConfigTabPage aExpertConfigDlg(GetFrameWeld()); + { + weld::WaitObject aWait(GetFrameWeld()); + aExpertConfigDlg.Reset();//initialize and reset function + } + + if (RET_OK == aExpertConfigDlg.run()) + { + aExpertConfigDlg.FillItemSet();//save changes if there are any + } +} + +void SvxJavaOptionsPage::ClearJavaInfo() +{ +#if HAVE_FEATURE_JAVA + m_parJavaInfo.clear(); +#else + (void) this; +#endif +} + +void SvxJavaOptionsPage::LoadJREs() +{ +#if HAVE_FEATURE_JAVA + weld::WaitObject aWaitObj(GetFrameWeld()); + javaFrameworkError eErr = jfw_findAllJREs( &m_parJavaInfo ); + if ( JFW_E_NONE == eErr ) + { + for (auto const & pInfo: m_parJavaInfo) + { + AddJRE( pInfo.get() ); + } + } + + for (auto const & pInfo: m_aAddedInfos) + { + AddJRE( pInfo.get() ); + } + + std::unique_ptr pSelectedJava; + eErr = jfw_getSelectedJRE( &pSelectedJava ); + if ( !(JFW_E_NONE == eErr && pSelectedJava) ) + return; + + sal_Int32 i = 0; + for (auto const & pCmpInfo: m_parJavaInfo) + { + if ( jfw_areEqualJavaInfo( pCmpInfo.get(), pSelectedJava.get() ) ) + { + HandleCheckEntry(i); + UpdateJavaPathText(); + break; + } + ++i; + } +#else + (void) this; +#endif +} + + +void SvxJavaOptionsPage::AddJRE( JavaInfo const * _pInfo ) +{ +#if HAVE_FEATURE_JAVA + int nPos = m_xJavaList->n_children(); + m_xJavaList->append(); + m_xJavaList->set_toggle(nPos, TRISTATE_FALSE, 0); + m_xJavaList->set_text(nPos, _pInfo->sVendor, 1); + m_xJavaList->set_text(nPos, _pInfo->sVersion, 2); + + INetURLObject aLocObj(_pInfo->sLocation); + OUString sLocation = aLocObj.getFSysPath(FSysStyle::Detect); + m_xJavaList->set_id(nPos, sLocation); +#else + (void) this; + (void)_pInfo; +#endif +} + +void SvxJavaOptionsPage::HandleCheckEntry(int nCheckedRow) +{ + m_xJavaList->select(nCheckedRow); + for (int i = 0, nCount = m_xJavaList->n_children(); i < nCount; ++i) + { + // we have radio button behavior -> so uncheck the other entries + m_xJavaList->set_toggle(i, i == nCheckedRow ? TRISTATE_TRUE : TRISTATE_FALSE, 0); + } +} + +void SvxJavaOptionsPage::UpdateJavaPathText() +{ + assert(m_xJavaList->get_selected_index() != -1); + // set installation directory info + OUString sLocation = m_xJavaList->get_selected_id(); + // tdf#80646 insert LTR mark after label + OUString sInfo = m_sInstallText + u"\u200E" + sLocation; + m_xJavaPathText->set_label(sInfo); +} + +void SvxJavaOptionsPage::AddFolder( const OUString& _rFolder ) +{ +#if HAVE_FEATURE_JAVA + bool bStartAgain = true; + std::unique_ptr pInfo; + javaFrameworkError eErr = jfw_getJavaInfoByPath( _rFolder, &pInfo ); + if ( JFW_E_NONE == eErr && pInfo ) + { + sal_Int32 nPos = 0; + bool bFound = false; + for (auto const & pCmpInfo: m_parJavaInfo) + { + if ( jfw_areEqualJavaInfo( pCmpInfo.get(), pInfo.get() ) ) + { + bFound = true; + break; + } + ++nPos; + } + + if ( !bFound ) + { + for (auto const & pCmpInfo: m_aAddedInfos) + { + if ( jfw_areEqualJavaInfo( pCmpInfo.get(), pInfo.get() ) ) + { + bFound = true; + break; + } + ++nPos; + } + } + + if ( !bFound ) + { + jfw_addJRELocation( pInfo->sLocation ); + AddJRE( pInfo.get() ); + m_aAddedInfos.push_back( std::move(pInfo) ); + nPos = m_xJavaList->n_children() - 1; + } + + HandleCheckEntry(nPos); + UpdateJavaPathText(); + bStartAgain = false; + } + else if ( JFW_E_NOT_RECOGNIZED == eErr ) + { + std::unique_ptr xBox(Application::CreateMessageDialog(GetFrameWeld(), + VclMessageType::Warning, VclButtonsType::Ok, + CuiResId(RID_SVXSTR_JRE_NOT_RECOGNIZED))); + xBox->run(); + } + else if ( JFW_E_FAILED_VERSION == eErr ) + { + std::unique_ptr xBox(Application::CreateMessageDialog(GetFrameWeld(), + VclMessageType::Warning, VclButtonsType::Ok, + CuiResId(RID_SVXSTR_JRE_FAILED_VERSION))); + xBox->run(); + } + + if ( bStartAgain ) + { + xFolderPicker->setDisplayDirectory( _rFolder ); + Application::PostUserEvent( LINK( this, SvxJavaOptionsPage, StartFolderPickerHdl ) ); + } +#else + (void) this; + (void)_rFolder; +#endif +} + +void SvxJavaOptionsPage::RequestRestart(svtools::RestartReason eReason) +{ + OfaTreeOptionsDialog* pParentDlg(static_cast(GetDialogController())); + if (pParentDlg) + pParentDlg->SetNeedsRestart(eReason); +} + +std::unique_ptr SvxJavaOptionsPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet) +{ + return std::make_unique(pPage, pController, *rAttrSet); +} + +bool SvxJavaOptionsPage::FillItemSet( SfxItemSet* /*rCoreSet*/ ) +{ + bool bModified = false; + + if ( m_xExperimentalCB->get_state_changed_from_saved() ) + { + SvtMiscOptions aMiscOpt; + aMiscOpt.SetExperimentalMode( m_xExperimentalCB->get_active() ); + bModified = true; + RequestRestart( svtools::RESTART_REASON_EXP_FEATURES ); + } + + if ( m_xMacroCB->get_state_changed_from_saved() ) + { + SvtMiscOptions aMiscOpt; + aMiscOpt.SetMacroRecorderMode(m_xMacroCB->get_active()); + bModified = true; + } + +#if HAVE_FEATURE_JAVA + javaFrameworkError eErr = JFW_E_NONE; + if (m_xParamDlg) + { + eErr = jfw_setVMParameters(m_xParamDlg->GetParameters()); + SAL_WARN_IF(JFW_E_NONE != eErr, "cui.options", "SvxJavaOptionsPage::FillItemSet(): error in jfw_setVMParameters"); + bModified = true; + } + + if (m_xPathDlg) + { + OUString sPath(m_xPathDlg->GetClassPath()); + if (m_xPathDlg->GetOldPath() != sPath) + { + eErr = jfw_setUserClassPath( sPath ); + SAL_WARN_IF(JFW_E_NONE != eErr, "cui.options", "SvxJavaOptionsPage::FillItemSet(): error in jfw_setUserClassPath"); + bModified = true; + } + } + + sal_uInt32 nCount = m_xJavaList->n_children(); + for (sal_uInt32 i = 0; i < nCount; ++i) + { + if (m_xJavaList->get_toggle(i, 0) == TRISTATE_TRUE) + { + JavaInfo const * pInfo; + if ( i < m_parJavaInfo.size() ) + pInfo = m_parJavaInfo[i].get(); + else + pInfo = m_aAddedInfos[ i - m_parJavaInfo.size() ].get(); + + std::unique_ptr pSelectedJava; + eErr = jfw_getSelectedJRE( &pSelectedJava ); + if ( JFW_E_NONE == eErr || JFW_E_INVALID_SETTINGS == eErr ) + { + if (!pSelectedJava || !jfw_areEqualJavaInfo( pInfo, pSelectedJava.get() ) ) + { + if ( jfw_isVMRunning() || + ( ( pInfo->nRequirements & JFW_REQUIRE_NEEDRESTART ) == JFW_REQUIRE_NEEDRESTART ) ) + { + RequestRestart( svtools::RESTART_REASON_JAVA ); + } + + eErr = jfw_setSelectedJRE( pInfo ); + SAL_WARN_IF(JFW_E_NONE != eErr, "cui.options", "SvxJavaOptionsPage::FillItemSet(): error in jfw_setSelectedJRE"); + bModified = true; + } + } + break; + } + } + + bool bEnabled = false; + eErr = jfw_getEnabled( &bEnabled ); + DBG_ASSERT( JFW_E_NONE == eErr, + "SvxJavaOptionsPage::FillItemSet(): error in jfw_getEnabled" ); + if ( bEnabled != m_xJavaEnableCB->get_active() ) + { + eErr = jfw_setEnabled( m_xJavaEnableCB->get_active() ); + DBG_ASSERT( JFW_E_NONE == eErr, + "SvxJavaOptionsPage::FillItemSet(): error in jfw_setEnabled" ); + bModified = true; + } +#endif + + return bModified; +} + + +void SvxJavaOptionsPage::Reset( const SfxItemSet* /*rSet*/ ) +{ + ClearJavaInfo(); + m_xJavaList->clear(); + + SvtMiscOptions aMiscOpt; + +#if HAVE_FEATURE_JAVA + bool bEnabled = false; + javaFrameworkError eErr = jfw_getEnabled( &bEnabled ); + if ( eErr != JFW_E_NONE ) + bEnabled = false; + m_xJavaEnableCB->set_active(bEnabled); + EnableHdl_Impl(*m_xJavaEnableCB); +#else + m_xJavaEnableCB->set_active(false); + m_xJavaEnableCB->set_sensitive(false); +#endif + + m_xExperimentalCB->set_active( aMiscOpt.IsExperimentalMode() ); + m_xExperimentalCB->save_state(); + m_xMacroCB->set_active(aMiscOpt.IsMacroRecorderMode()); + m_xMacroCB->save_state(); + + m_aResetIdle.Start(); +} + + +void SvxJavaOptionsPage::FillUserData() +{ + SetUserData( OUString() ); +} + +// class SvxJavaParameterDlg --------------------------------------------- + +SvxJavaParameterDlg::SvxJavaParameterDlg(weld::Window* pParent) + : GenericDialogController(pParent, "cui/ui/javastartparametersdialog.ui", + "JavaStartParameters") + , m_xParameterEdit(m_xBuilder->weld_entry("parameterfield")) + , m_xAssignBtn(m_xBuilder->weld_button("assignbtn")) + , m_xAssignedList(m_xBuilder->weld_tree_view("assignlist")) + , m_xRemoveBtn(m_xBuilder->weld_button("removebtn")) + , m_xEditBtn(m_xBuilder->weld_button("editbtn")) +{ + m_xAssignedList->set_size_request(m_xAssignedList->get_approximate_digit_width() * 54, + m_xAssignedList->get_height_rows(6)); + m_xParameterEdit->connect_changed( LINK( this, SvxJavaParameterDlg, ModifyHdl_Impl ) ); + m_xAssignBtn->connect_clicked( LINK( this, SvxJavaParameterDlg, AssignHdl_Impl ) ); + m_xRemoveBtn->connect_clicked( LINK( this, SvxJavaParameterDlg, RemoveHdl_Impl ) ); + m_xEditBtn->connect_clicked( LINK( this, SvxJavaParameterDlg, EditHdl_Impl ) ); + m_xAssignedList->connect_changed( LINK( this, SvxJavaParameterDlg, SelectHdl_Impl ) ); + m_xAssignedList->connect_row_activated( LINK( this, SvxJavaParameterDlg, DblClickHdl_Impl ) ); + + ModifyHdl_Impl(*m_xParameterEdit); + EnableEditButton(); + EnableRemoveButton(); +} + +SvxJavaParameterDlg::~SvxJavaParameterDlg() +{ +} + +IMPL_LINK_NOARG(SvxJavaParameterDlg, ModifyHdl_Impl, weld::Entry&, void) +{ + OUString sParam = comphelper::string::strip(m_xParameterEdit->get_text(), ' '); + m_xAssignBtn->set_sensitive(!sParam.isEmpty()); +} + +IMPL_LINK_NOARG(SvxJavaParameterDlg, AssignHdl_Impl, weld::Button&, void) +{ + OUString sParam = comphelper::string::strip(m_xParameterEdit->get_text(), ' '); + if (sParam.isEmpty()) + return; + + int nPos = m_xAssignedList->find_text(sParam); + if (nPos == -1) + { + m_xAssignedList->append_text(sParam); + m_xAssignedList->select(m_xAssignedList->n_children() - 1); + } + else + m_xAssignedList->select(nPos); + m_xParameterEdit->set_text(OUString()); + ModifyHdl_Impl(*m_xParameterEdit); + EnableEditButton(); + EnableRemoveButton(); +} + +IMPL_LINK_NOARG(SvxJavaParameterDlg, EditHdl_Impl, weld::Button&, void) +{ + EditParameter(); +} + +IMPL_LINK_NOARG(SvxJavaParameterDlg, SelectHdl_Impl, weld::TreeView&, void) +{ + EnableEditButton(); + EnableRemoveButton(); +} + +IMPL_LINK_NOARG(SvxJavaParameterDlg, DblClickHdl_Impl, weld::TreeView&, bool) +{ + EditParameter(); + return true; +} + +IMPL_LINK_NOARG(SvxJavaParameterDlg, RemoveHdl_Impl, weld::Button&, void) +{ + int nPos = m_xAssignedList->get_selected_index(); + if (nPos != -1) + { + m_xAssignedList->remove(nPos); + int nCount = m_xAssignedList->n_children(); + if (nCount) + { + if (nPos >= nCount) + nPos = nCount - 1; + m_xAssignedList->select(nPos); + } + else + { + DisableEditButton(); + } + } + EnableRemoveButton(); +} + +void SvxJavaParameterDlg::EditParameter() +{ + int nPos = m_xAssignedList->get_selected_index(); + m_xParameterEdit->set_text(OUString()); + + if (nPos == -1) + return; + + InputDialog aParamEditDlg(m_xDialog.get(), CuiResId(RID_SVXSTR_JAVA_START_PARAM)); + OUString editableClassPath = m_xAssignedList->get_selected_text(); + aParamEditDlg.SetEntryText(editableClassPath); + aParamEditDlg.HideHelpBtn(); + + if (!aParamEditDlg.run()) + return; + OUString editedClassPath = comphelper::string::strip(aParamEditDlg.GetEntryText(), ' '); + + if ( !editedClassPath.isEmpty() && editableClassPath != editedClassPath ) + { + m_xAssignedList->remove(nPos); + m_xAssignedList->insert_text(nPos, editedClassPath); + m_xAssignedList->select(nPos); + } +} + +short SvxJavaParameterDlg::run() +{ + m_xParameterEdit->grab_focus(); + m_xAssignedList->select(-1); + return GenericDialogController::run(); +} + +std::vector< OUString > SvxJavaParameterDlg::GetParameters() const +{ + int nCount = m_xAssignedList->n_children(); + std::vector< OUString > aParamList; + aParamList.reserve(nCount); + for (int i = 0; i < nCount; ++i) + aParamList.push_back(m_xAssignedList->get_text(i)); + return aParamList; +} + +void SvxJavaParameterDlg::DisableButtons() +{ + DisableAssignButton(); + DisableEditButton(); + DisableRemoveButton(); +} + +void SvxJavaParameterDlg::SetParameters( std::vector< OUString > const & rParams ) +{ + m_xAssignedList->clear(); + for (auto const & sParam: rParams) + { + m_xAssignedList->append_text(sParam); + } + DisableEditButton(); + DisableRemoveButton(); +} + + +// class SvxJavaClassPathDlg --------------------------------------------- + +SvxJavaClassPathDlg::SvxJavaClassPathDlg(weld::Window* pParent) + : GenericDialogController(pParent, "cui/ui/javaclasspathdialog.ui", "JavaClassPath") + , m_xPathList(m_xBuilder->weld_tree_view("paths")) + , m_xAddArchiveBtn(m_xBuilder->weld_button("archive")) + , m_xAddPathBtn(m_xBuilder->weld_button("folder")) + , m_xRemoveBtn(m_xBuilder->weld_button("remove")) +{ + m_xPathList->set_size_request(m_xPathList->get_approximate_digit_width() * 54, + m_xPathList->get_height_rows(8)); + m_xAddArchiveBtn->connect_clicked( LINK( this, SvxJavaClassPathDlg, AddArchiveHdl_Impl ) ); + m_xAddPathBtn->connect_clicked( LINK( this, SvxJavaClassPathDlg, AddPathHdl_Impl ) ); + m_xRemoveBtn->connect_clicked( LINK( this, SvxJavaClassPathDlg, RemoveHdl_Impl ) ); + m_xPathList->connect_changed( LINK( this, SvxJavaClassPathDlg, SelectHdl_Impl ) ); + + // set initial focus to path list + m_xPathList->grab_focus(); +} + +SvxJavaClassPathDlg::~SvxJavaClassPathDlg() +{ +} + +IMPL_LINK_NOARG(SvxJavaClassPathDlg, AddArchiveHdl_Impl, weld::Button&, void) +{ + sfx2::FileDialogHelper aDlg(TemplateDescription::FILEOPEN_SIMPLE, FileDialogFlags::NONE, m_xDialog.get()); + aDlg.SetTitle( CuiResId( RID_SVXSTR_ARCHIVE_TITLE ) ); + aDlg.AddFilter( CuiResId( RID_SVXSTR_ARCHIVE_HEADLINE ), "*.jar;*.zip" ); + OUString sFolder; + if (m_xPathList->count_selected_rows() > 0) + { + osl::FileBase::getFileURLFromSystemPath(m_xPathList->get_selected_text(), sFolder); + // best effort + } + if (sFolder.isEmpty()) + sFolder = SvtPathOptions().GetWorkPath(); + aDlg.SetDisplayDirectory( sFolder ); + if ( aDlg.Execute() == ERRCODE_NONE ) + { + OUString sURL = aDlg.GetPath(); + OUString sFile; + if (osl::FileBase::getSystemPathFromFileURL(sURL, sFile) == osl::FileBase::E_None) + { + INetURLObject aURL( sURL ); + if ( !IsPathDuplicate( sFile ) ) + { + m_xPathList->append("", sFile, SvFileInformationManager::GetImageId(aURL)); + m_xPathList->select(m_xPathList->n_children() - 1); + } + else + { + OUString sMsg( CuiResId( RID_SVXSTR_MULTIFILE_DBL_ERR ) ); + sMsg = sMsg.replaceFirst( "%1", sFile ); + std::unique_ptr xBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Warning, VclButtonsType::Ok, sMsg)); + xBox->run(); + } + } + else + { + OUString sMsg( CuiResId( RID_SVXSTR_CANNOTCONVERTURL_ERR ) ); + sMsg = sMsg.replaceFirst( "%1", sURL ); + std::unique_ptr xBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Warning, VclButtonsType::Ok, sMsg)); + xBox->run(); + } + } + EnableRemoveButton(); +} + +IMPL_LINK_NOARG(SvxJavaClassPathDlg, AddPathHdl_Impl, weld::Button&, void) +{ + Reference < XComponentContext > xContext( ::comphelper::getProcessComponentContext() ); + Reference < XFolderPicker2 > xFolderPicker = FolderPicker::create(xContext); + + OUString sOldFolder; + if (m_xPathList->count_selected_rows() > 0) + { + osl::FileBase::getFileURLFromSystemPath(m_xPathList->get_selected_text(), sOldFolder); + // best effort + } + if (sOldFolder.isEmpty()) + sOldFolder = SvtPathOptions().GetWorkPath(); + xFolderPicker->setDisplayDirectory( sOldFolder ); + if ( xFolderPicker->execute() == ExecutableDialogResults::OK ) + { + OUString sFolderURL( xFolderPicker->getDirectory() ); + INetURLObject aURL( sFolderURL ); + OUString sNewFolder; + if (osl::FileBase::getSystemPathFromFileURL(sFolderURL, sNewFolder) + == osl::FileBase::E_None) + { + if ( !IsPathDuplicate( sNewFolder ) ) + { + m_xPathList->append("", sNewFolder, SvFileInformationManager::GetImageId(aURL)); + m_xPathList->select(m_xPathList->n_children() - 1); + } + else + { + OUString sMsg( CuiResId( RID_SVXSTR_MULTIFILE_DBL_ERR ) ); + sMsg = sMsg.replaceFirst( "%1", sNewFolder ); + std::unique_ptr xBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Warning, VclButtonsType::Ok, sMsg)); + xBox->run(); + } + } + else + { + OUString sMsg( CuiResId( RID_SVXSTR_CANNOTCONVERTURL_ERR ) ); + sMsg = sMsg.replaceFirst( "%1", sFolderURL ); + std::unique_ptr xBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Warning, VclButtonsType::Ok, sMsg)); + xBox->run(); + } + } + EnableRemoveButton(); +} + +IMPL_LINK_NOARG(SvxJavaClassPathDlg, RemoveHdl_Impl, weld::Button&, void) +{ + int nPos = m_xPathList->get_selected_index(); + if (nPos != -1) + { + m_xPathList->remove(nPos); + int nCount = m_xPathList->n_children(); + if (nCount) + { + if (nPos >= nCount) + nPos = nCount - 1; + m_xPathList->select( nPos ); + } + } + + EnableRemoveButton(); +} + +IMPL_LINK_NOARG(SvxJavaClassPathDlg, SelectHdl_Impl, weld::TreeView&, void) +{ + EnableRemoveButton(); +} + +bool SvxJavaClassPathDlg::IsPathDuplicate( const OUString& _rPath ) +{ + bool bRet = false; + int nCount = m_xPathList->n_children(); + for (int i = 0; i < nCount; ++i) + { + if ( m_xPathList->get_text(i) == _rPath ) + { + bRet = true; + break; + } + } + + return bRet; +} + +OUString SvxJavaClassPathDlg::GetClassPath() const +{ + OUStringBuffer sPath; + int nCount = m_xPathList->n_children(); + for (int i = 0; i < nCount; ++i) + { + if (!sPath.isEmpty()) + sPath.append(CLASSPATH_DELIMITER); + sPath.append(m_xPathList->get_text(i)); + } + return sPath.makeStringAndClear(); +} + +void SvxJavaClassPathDlg::SetClassPath( const OUString& _rPath ) +{ + if ( m_sOldPath.isEmpty() ) + m_sOldPath = _rPath; + m_xPathList->clear(); + if (!_rPath.isEmpty()) + { + sal_Int32 nIdx = 0; + do + { + OUString sToken = _rPath.getToken( 0, CLASSPATH_DELIMITER, nIdx ); + OUString sURL; + osl::FileBase::getFileURLFromSystemPath(sToken, sURL); // best effort + INetURLObject aURL( sURL ); + m_xPathList->append("", sToken, SvFileInformationManager::GetImageId(aURL)); + } + while (nIdx>=0); + // select first entry + m_xPathList->select(0); + } + SelectHdl_Impl(*m_xPathList); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/optjava.hxx b/cui/source/options/optjava.hxx new file mode 100644 index 000000000..df90e2824 --- /dev/null +++ b/cui/source/options/optjava.hxx @@ -0,0 +1,206 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// forward --------------------------------------------------------------- + +#if HAVE_FEATURE_JAVA +struct JavaInfo; +#else +typedef void* JavaInfo; +#endif + +class SvxJavaParameterDlg; +class SvxJavaClassPathDlg; +class SvxJavaListBox; +class OfaTreeOptionsDialog; + +// class SvxJavaOptionsPage ---------------------------------------------- + +class SvxJavaOptionsPage : public SfxTabPage +{ +private: +#if HAVE_FEATURE_JAVA + std::vector> m_parJavaInfo; + std::vector m_parParameters; + OUString m_pClassPath; +#endif + OUString m_sInstallText; + OUString m_sAddDialogText; + Idle m_aResetIdle; + + std::vector> m_aAddedInfos; + + rtl::Reference< ::svt::DialogClosedListener > xDialogListener; + css::uno::Reference< css::ui::dialogs::XFolderPicker2 > xFolderPicker; + + std::unique_ptr m_xJavaEnableCB; + std::unique_ptr m_xJavaList; + std::unique_ptr m_xJavaPathText; + std::unique_ptr m_xAddBtn; + std::unique_ptr m_xParameterBtn; + std::unique_ptr m_xClassPathBtn; + std::unique_ptr m_xExpertConfigBtn; + + std::unique_ptr m_xParamDlg; + std::unique_ptr m_xPathDlg; + + std::unique_ptr m_xExperimentalCB; + std::unique_ptr m_xMacroCB; + + std::unique_ptr m_xAddDialogText; + + std::unique_ptr m_xJavaFrame; + + DECL_LINK(EnableHdl_Impl, weld::Button&, void); + typedef std::pair row_col; + DECL_LINK(CheckHdl_Impl, const row_col&, void); + DECL_LINK(SelectHdl_Impl, weld::TreeView&, void); + DECL_LINK(AddHdl_Impl, weld::Button&, void); + DECL_LINK(ParameterHdl_Impl, weld::Button&, void); + DECL_LINK(ClassPathHdl_Impl, weld::Button&, void); + DECL_LINK(ResetHdl_Impl, Timer *, void); + + DECL_LINK(StartFolderPickerHdl, void *, void); + DECL_LINK(DialogClosedHdl, css::ui::dialogs::DialogClosedEvent*, void); + + DECL_LINK(ExpertConfigHdl_Impl, weld::Button&, void); + + void ClearJavaInfo(); + void LoadJREs(); + void AddJRE( JavaInfo const * _pInfo ); + void HandleCheckEntry(int nCheckedRow); + void UpdateJavaPathText(); + void AddFolder( const OUString& _rFolder ); + void RequestRestart( svtools::RestartReason eReason ); + +public: + SvxJavaOptionsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + virtual ~SvxJavaOptionsPage() override; + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet ); + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; + virtual void FillUserData() override; +}; + +// class SvxJavaParameterDlg --------------------------------------------- + +class SvxJavaParameterDlg : public weld::GenericDialogController +{ +private: + std::unique_ptr m_xParameterEdit; + std::unique_ptr m_xAssignBtn; + std::unique_ptr m_xAssignedList; + std::unique_ptr m_xRemoveBtn; + std::unique_ptr m_xEditBtn; + + DECL_LINK(ModifyHdl_Impl, weld::Entry&, void); + DECL_LINK(AssignHdl_Impl, weld::Button&, void); + DECL_LINK(SelectHdl_Impl, weld::TreeView&, void); + DECL_LINK(DblClickHdl_Impl, weld::TreeView&, bool); + DECL_LINK(RemoveHdl_Impl, weld::Button&, void); + DECL_LINK(EditHdl_Impl, weld::Button&, void); + + void EnableRemoveButton() + { + m_xRemoveBtn->set_sensitive(m_xAssignedList->get_selected_index() != -1); + } + + void EnableEditButton() + { + m_xEditBtn->set_sensitive(m_xAssignedList->get_selected_index() != -1); + } + + void DisableAssignButton() + { + m_xAssignBtn->set_sensitive(false); + } + + void DisableRemoveButton() + { + m_xRemoveBtn->set_sensitive(false); + } + + void DisableEditButton() + { + m_xEditBtn->set_sensitive(false); + } + +public: + explicit SvxJavaParameterDlg(weld::Window* pParent); + virtual ~SvxJavaParameterDlg() override; + + virtual short run() override; + + std::vector< OUString > GetParameters() const; + void SetParameters( std::vector< OUString > const & rParams ); + void DisableButtons(); + void EditParameter(); +}; + +// class SvxJavaClassPathDlg --------------------------------------------- + +class SvxJavaClassPathDlg : public weld::GenericDialogController +{ +private: + std::unique_ptr m_xPathList; + std::unique_ptr m_xAddArchiveBtn; + std::unique_ptr m_xAddPathBtn; + std::unique_ptr m_xRemoveBtn; + + OUString m_sOldPath; + + DECL_LINK(AddArchiveHdl_Impl, weld::Button&, void); + DECL_LINK(AddPathHdl_Impl, weld::Button&, void); + DECL_LINK(RemoveHdl_Impl, weld::Button&, void); + DECL_LINK(SelectHdl_Impl, weld::TreeView&, void); + + bool IsPathDuplicate(const OUString& _rPath); + void EnableRemoveButton() + { + m_xRemoveBtn->set_sensitive(m_xPathList->get_selected_index() != -1); + } + +public: + explicit SvxJavaClassPathDlg(weld::Window* pParent); + virtual ~SvxJavaClassPathDlg() override; + + const OUString& GetOldPath() const { return m_sOldPath; } + void SetFocus() { m_xPathList->grab_focus(); } + + OUString GetClassPath() const; + void SetClassPath( const OUString& _rPath ); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/optjsearch.cxx b/cui/source/options/optjsearch.cxx new file mode 100644 index 000000000..4a2c31c49 --- /dev/null +++ b/cui/source/options/optjsearch.cxx @@ -0,0 +1,358 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include "optjsearch.hxx" + +using namespace com::sun::star::i18n; + + +SvxJSearchOptionsPage::SvxJSearchOptionsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/optjsearchpage.ui", "OptJSearchPage", &rSet) + , m_xMatchCase(m_xBuilder->weld_check_button("matchcase")) + , m_xMatchFullHalfWidth(m_xBuilder->weld_check_button("matchfullhalfwidth")) + , m_xMatchHiraganaKatakana(m_xBuilder->weld_check_button("matchhiraganakatakana")) + , m_xMatchContractions(m_xBuilder->weld_check_button("matchcontractions")) + , m_xMatchMinusDashChoon(m_xBuilder->weld_check_button("matchminusdashchoon")) + , m_xMatchRepeatCharMarks(m_xBuilder->weld_check_button("matchrepeatcharmarks")) + , m_xMatchVariantFormKanji(m_xBuilder->weld_check_button("matchvariantformkanji")) + , m_xMatchOldKanaForms(m_xBuilder->weld_check_button("matcholdkanaforms")) + , m_xMatchDiziDuzu(m_xBuilder->weld_check_button("matchdiziduzu")) + , m_xMatchBavaHafa(m_xBuilder->weld_check_button("matchbavahafa")) + , m_xMatchTsithichiDhizi(m_xBuilder->weld_check_button("matchtsithichidhizi")) + , m_xMatchHyuiyuByuvyu(m_xBuilder->weld_check_button("matchhyuiyubyuvyu")) + , m_xMatchSesheZeje(m_xBuilder->weld_check_button("matchseshezeje")) + , m_xMatchIaiya(m_xBuilder->weld_check_button("matchiaiya")) + , m_xMatchKiku(m_xBuilder->weld_check_button("matchkiku")) + , m_xMatchProlongedSoundMark(m_xBuilder->weld_check_button("matchprolongedsoundmark")) + , m_xIgnorePunctuation(m_xBuilder->weld_check_button("ignorepunctuation")) + , m_xIgnoreWhitespace(m_xBuilder->weld_check_button("ignorewhitespace")) + , m_xIgnoreMiddleDot(m_xBuilder->weld_check_button("ignoremiddledot")) + , nTransliterationFlags(TransliterationFlags::NONE) + , bSaveOptions(true) +{ +} + +SvxJSearchOptionsPage::~SvxJSearchOptionsPage() +{ +} + +std::unique_ptr SvxJSearchOptionsPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet) +{ + return std::make_unique(pPage, pController, *rSet); +} + +void SvxJSearchOptionsPage::SetTransliterationFlags( TransliterationFlags nSettings ) +{ + bool bVal(nSettings & TransliterationFlags::IGNORE_CASE); + m_xMatchCase ->set_active( bVal ); //! treat as equal uppercase/lowercase + bVal = bool(nSettings & TransliterationFlags::IGNORE_WIDTH); + m_xMatchFullHalfWidth ->set_active( bVal ); + bVal = bool(nSettings & TransliterationFlags::IGNORE_KANA); + m_xMatchHiraganaKatakana ->set_active( bVal ); + bVal = bool(nSettings & TransliterationFlags::ignoreSize_ja_JP); + m_xMatchContractions ->set_active( bVal ); + bVal = bool(nSettings & TransliterationFlags::ignoreMinusSign_ja_JP); + m_xMatchMinusDashChoon ->set_active( bVal ); + bVal = bool(nSettings & TransliterationFlags::ignoreIterationMark_ja_JP); + m_xMatchRepeatCharMarks ->set_active( bVal ); + bVal = bool(nSettings & TransliterationFlags::ignoreTraditionalKanji_ja_JP); + m_xMatchVariantFormKanji ->set_active( bVal ); + bVal = bool(nSettings & TransliterationFlags::ignoreTraditionalKana_ja_JP); + m_xMatchOldKanaForms ->set_active( bVal ); + bVal = bool(nSettings & TransliterationFlags::ignoreZiZu_ja_JP); + m_xMatchDiziDuzu ->set_active( bVal ); + bVal = bool(nSettings & TransliterationFlags::ignoreBaFa_ja_JP); + m_xMatchBavaHafa ->set_active( bVal ); + bVal = bool(nSettings & TransliterationFlags::ignoreTiJi_ja_JP); + m_xMatchTsithichiDhizi ->set_active( bVal ); + bVal = bool(nSettings & TransliterationFlags::ignoreHyuByu_ja_JP); + m_xMatchHyuiyuByuvyu ->set_active( bVal ); + bVal = bool(nSettings & TransliterationFlags::ignoreSeZe_ja_JP); + m_xMatchSesheZeje ->set_active( bVal ); + bVal = bool(nSettings & TransliterationFlags::ignoreIandEfollowedByYa_ja_JP); + m_xMatchIaiya ->set_active( bVal ); + bVal = bool(nSettings & TransliterationFlags::ignoreKiKuFollowedBySa_ja_JP); + m_xMatchKiku ->set_active( bVal ); + bVal = bool(nSettings & TransliterationFlags::ignoreSeparator_ja_JP); + m_xIgnorePunctuation ->set_active( bVal ); + bVal = bool(nSettings & TransliterationFlags::ignoreSpace_ja_JP); + m_xIgnoreWhitespace ->set_active( bVal ); + bVal = bool(nSettings & TransliterationFlags::ignoreProlongedSoundMark_ja_JP); + m_xMatchProlongedSoundMark->set_active( bVal ); + bVal = bool(nSettings & TransliterationFlags::ignoreMiddleDot_ja_JP); + m_xIgnoreMiddleDot ->set_active( bVal ); + + nTransliterationFlags = nSettings; +} + +TransliterationFlags SvxJSearchOptionsPage::GetTransliterationFlags_Impl() +{ + TransliterationFlags nTmp = TransliterationFlags::NONE; + if (m_xMatchCase->get_active()) //! treat as equal uppercase/lowercase + nTmp |= TransliterationFlags::IGNORE_CASE; + if (m_xMatchFullHalfWidth->get_active()) + nTmp |= TransliterationFlags::IGNORE_WIDTH; + if (m_xMatchHiraganaKatakana->get_active()) + nTmp |= TransliterationFlags::IGNORE_KANA; + if (m_xMatchContractions->get_active()) + nTmp |= TransliterationFlags::ignoreSize_ja_JP; + if (m_xMatchMinusDashChoon->get_active()) + nTmp |= TransliterationFlags::ignoreMinusSign_ja_JP; + if (m_xMatchRepeatCharMarks->get_active()) + nTmp |= TransliterationFlags::ignoreIterationMark_ja_JP; + if (m_xMatchVariantFormKanji->get_active()) + nTmp |= TransliterationFlags::ignoreTraditionalKanji_ja_JP; + if (m_xMatchOldKanaForms->get_active()) + nTmp |= TransliterationFlags::ignoreTraditionalKana_ja_JP; + if (m_xMatchDiziDuzu->get_active()) + nTmp |= TransliterationFlags::ignoreZiZu_ja_JP; + if (m_xMatchBavaHafa->get_active()) + nTmp |= TransliterationFlags::ignoreBaFa_ja_JP; + if (m_xMatchTsithichiDhizi->get_active()) + nTmp |= TransliterationFlags::ignoreTiJi_ja_JP; + if (m_xMatchHyuiyuByuvyu->get_active()) + nTmp |= TransliterationFlags::ignoreHyuByu_ja_JP; + if (m_xMatchSesheZeje->get_active()) + nTmp |= TransliterationFlags::ignoreSeZe_ja_JP; + if (m_xMatchIaiya->get_active()) + nTmp |= TransliterationFlags::ignoreIandEfollowedByYa_ja_JP; + if (m_xMatchKiku->get_active()) + nTmp |= TransliterationFlags::ignoreKiKuFollowedBySa_ja_JP; + if (m_xIgnorePunctuation->get_active()) + nTmp |= TransliterationFlags::ignoreSeparator_ja_JP; + if (m_xIgnoreWhitespace->get_active()) + nTmp |= TransliterationFlags::ignoreSpace_ja_JP; + if (m_xMatchProlongedSoundMark->get_active()) + nTmp |= TransliterationFlags::ignoreProlongedSoundMark_ja_JP; + if (m_xIgnoreMiddleDot->get_active()) + nTmp |= TransliterationFlags::ignoreMiddleDot_ja_JP; + + nTransliterationFlags = nTmp; + return nTransliterationFlags; +} + + +void SvxJSearchOptionsPage::Reset( const SfxItemSet* ) +{ + SvtSearchOptions aOpt; + + // read settings from configuration + m_xMatchCase ->set_active(!aOpt.IsMatchCase() ); //! treat as equal uppercase/lowercase + m_xMatchFullHalfWidth ->set_active( aOpt.IsMatchFullHalfWidthForms() ); + m_xMatchHiraganaKatakana ->set_active( aOpt.IsMatchHiraganaKatakana() ); + m_xMatchContractions ->set_active( aOpt.IsMatchContractions() ); + m_xMatchMinusDashChoon ->set_active( aOpt.IsMatchMinusDashChoon() ); + m_xMatchRepeatCharMarks ->set_active( aOpt.IsMatchRepeatCharMarks() ); + m_xMatchVariantFormKanji ->set_active( aOpt.IsMatchVariantFormKanji() ); + m_xMatchOldKanaForms ->set_active( aOpt.IsMatchOldKanaForms() ); + m_xMatchDiziDuzu ->set_active( aOpt.IsMatchDiziDuzu() ); + m_xMatchBavaHafa ->set_active( aOpt.IsMatchBavaHafa() ); + m_xMatchTsithichiDhizi ->set_active( aOpt.IsMatchTsithichiDhizi() ); + m_xMatchHyuiyuByuvyu ->set_active( aOpt.IsMatchHyuiyuByuvyu() ); + m_xMatchSesheZeje ->set_active( aOpt.IsMatchSesheZeje() ); + m_xMatchIaiya ->set_active( aOpt.IsMatchIaiya() ); + m_xMatchKiku ->set_active( aOpt.IsMatchKiku() ); + m_xIgnorePunctuation ->set_active( aOpt.IsIgnorePunctuation() ); + m_xIgnoreWhitespace ->set_active( aOpt.IsIgnoreWhitespace() ); + m_xMatchProlongedSoundMark ->set_active( aOpt.IsIgnoreProlongedSoundMark() ); + m_xIgnoreMiddleDot ->set_active( aOpt.IsIgnoreMiddleDot() ); + + nTransliterationFlags = GetTransliterationFlags_Impl(); + DBG_ASSERT( nTransliterationFlags == aOpt.GetTransliterationFlags(), + "Transliteration settings different" ); + + m_xMatchCase ->save_state(); + m_xMatchFullHalfWidth ->save_state(); + m_xMatchHiraganaKatakana ->save_state(); + m_xMatchContractions ->save_state(); + m_xMatchMinusDashChoon ->save_state(); + m_xMatchRepeatCharMarks ->save_state(); + m_xMatchVariantFormKanji ->save_state(); + m_xMatchOldKanaForms ->save_state(); + m_xMatchDiziDuzu ->save_state(); + m_xMatchBavaHafa ->save_state(); + m_xMatchTsithichiDhizi ->save_state(); + m_xMatchHyuiyuByuvyu ->save_state(); + m_xMatchSesheZeje ->save_state(); + m_xMatchIaiya ->save_state(); + m_xMatchKiku ->save_state(); + m_xIgnorePunctuation ->save_state(); + m_xIgnoreWhitespace ->save_state(); + m_xMatchProlongedSoundMark ->save_state(); + m_xIgnoreMiddleDot ->save_state(); +} + + +bool SvxJSearchOptionsPage::FillItemSet( SfxItemSet* ) +{ + TransliterationFlags nOldVal = nTransliterationFlags; + nTransliterationFlags = GetTransliterationFlags_Impl(); + bool bModified = nOldVal != nTransliterationFlags; + + if (!bSaveOptions) + return bModified; + + bModified = false; + SvtSearchOptions aOpt; + bool bNewVal, bChanged; + + bNewVal = m_xMatchCase->get_active(); //! treat as equal uppercase/lowercase + bChanged = m_xMatchCase->get_state_changed_from_saved(); + if (bChanged) + { + aOpt.SetMatchCase(!bNewVal ); + bModified = true; + } + bNewVal = m_xMatchFullHalfWidth->get_active(); + bChanged = m_xMatchFullHalfWidth->get_state_changed_from_saved(); + if (bChanged) + { + aOpt.SetMatchFullHalfWidthForms( bNewVal ); + bModified = true; + } + bNewVal = m_xMatchHiraganaKatakana->get_active(); + bChanged = m_xMatchHiraganaKatakana->get_state_changed_from_saved(); + if (bChanged) + { + aOpt.SetMatchHiraganaKatakana( bNewVal ); + bModified = true; + } + bNewVal = m_xMatchContractions->get_active(); + bChanged = m_xMatchContractions->get_state_changed_from_saved(); + if (bChanged) + { + aOpt.SetMatchContractions( bNewVal ); + bModified = true; + } + bNewVal = m_xMatchMinusDashChoon->get_active(); + bChanged = m_xMatchMinusDashChoon->get_state_changed_from_saved(); + if (bChanged) + { + aOpt.SetMatchMinusDashChoon( bNewVal ); + bModified = true; + } + bNewVal = m_xMatchRepeatCharMarks->get_active(); + bChanged = m_xMatchRepeatCharMarks->get_state_changed_from_saved(); + if (bChanged) + { + aOpt.SetMatchRepeatCharMarks( bNewVal ); + bModified = true; + } + bNewVal = m_xMatchVariantFormKanji->get_active(); + bChanged = m_xMatchVariantFormKanji->get_state_changed_from_saved(); + if (bChanged) + { + aOpt.SetMatchVariantFormKanji( bNewVal ); + bModified = true; + } + bNewVal = m_xMatchOldKanaForms->get_active(); + bChanged = m_xMatchOldKanaForms->get_state_changed_from_saved(); + if (bChanged) + { + aOpt.SetMatchOldKanaForms( bNewVal ); + bModified = true; + } + bNewVal = m_xMatchDiziDuzu->get_active(); + bChanged = m_xMatchDiziDuzu->get_state_changed_from_saved(); + if (bChanged) + { + aOpt.SetMatchDiziDuzu( bNewVal ); + bModified = true; + } + bNewVal = m_xMatchBavaHafa->get_active(); + bChanged = m_xMatchBavaHafa->get_state_changed_from_saved(); + if (bChanged) + { + aOpt.SetMatchBavaHafa( bNewVal ); + bModified = true; + } + bNewVal = m_xMatchTsithichiDhizi->get_active(); + bChanged = m_xMatchTsithichiDhizi->get_state_changed_from_saved(); + if (bChanged) + { + aOpt.SetMatchTsithichiDhizi( bNewVal ); + bModified = true; + } + bNewVal = m_xMatchHyuiyuByuvyu->get_active(); + bChanged = m_xMatchHyuiyuByuvyu->get_state_changed_from_saved(); + if (bChanged) + { + aOpt.SetMatchHyuiyuByuvyu( bNewVal ); + bModified = true; + } + bNewVal = m_xMatchSesheZeje->get_active(); + bChanged = m_xMatchSesheZeje->get_state_changed_from_saved(); + if (bChanged) + { + aOpt.SetMatchSesheZeje( bNewVal ); + bModified = true; + } + bNewVal = m_xMatchIaiya->get_active(); + bChanged = m_xMatchIaiya->get_state_changed_from_saved(); + if (bChanged) + { + aOpt.SetMatchIaiya( bNewVal ); + bModified = true; + } + bNewVal = m_xMatchKiku->get_active(); + bChanged = m_xMatchKiku->get_state_changed_from_saved(); + if (bChanged) + { + aOpt.SetMatchKiku( bNewVal ); + bModified = true; + } + bNewVal = m_xIgnorePunctuation->get_active(); + bChanged = m_xIgnorePunctuation->get_state_changed_from_saved(); + if (bChanged) + { + aOpt.SetIgnorePunctuation( bNewVal ); + bModified = true; + } + bNewVal = m_xIgnoreWhitespace->get_active(); + bChanged = m_xIgnoreWhitespace->get_state_changed_from_saved(); + if (bChanged) + { + aOpt.SetIgnoreWhitespace( bNewVal ); + bModified = true; + } + bNewVal = m_xMatchProlongedSoundMark->get_active(); + bChanged = m_xMatchProlongedSoundMark->get_state_changed_from_saved(); + if (bChanged) + { + aOpt.SetIgnoreProlongedSoundMark( bNewVal ); + bModified = true; + } + bNewVal = m_xIgnoreMiddleDot->get_active(); + bChanged = m_xIgnoreMiddleDot->get_state_changed_from_saved(); + if (bChanged) + { + aOpt.SetIgnoreMiddleDot( bNewVal ); + bModified = true; + } + + if (bModified) + aOpt.Commit(); + + return bModified; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/optjsearch.hxx b/cui/source/options/optjsearch.hxx new file mode 100644 index 000000000..f0da350ae --- /dev/null +++ b/cui/source/options/optjsearch.hxx @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include +#include +#include + +class SfxItemSet; + +class SvxJSearchOptionsPage : public SfxTabPage +{ +private: + std::unique_ptr m_xMatchCase; + std::unique_ptr m_xMatchFullHalfWidth; + std::unique_ptr m_xMatchHiraganaKatakana; + std::unique_ptr m_xMatchContractions; + std::unique_ptr m_xMatchMinusDashChoon; + std::unique_ptr m_xMatchRepeatCharMarks; + std::unique_ptr m_xMatchVariantFormKanji; + std::unique_ptr m_xMatchOldKanaForms; + std::unique_ptr m_xMatchDiziDuzu; + std::unique_ptr m_xMatchBavaHafa; + std::unique_ptr m_xMatchTsithichiDhizi; + std::unique_ptr m_xMatchHyuiyuByuvyu; + std::unique_ptr m_xMatchSesheZeje; + std::unique_ptr m_xMatchIaiya; + std::unique_ptr m_xMatchKiku; + std::unique_ptr m_xMatchProlongedSoundMark; + + std::unique_ptr m_xIgnorePunctuation; + std::unique_ptr m_xIgnoreWhitespace; + std::unique_ptr m_xIgnoreMiddleDot; + + TransliterationFlags nTransliterationFlags; + bool bSaveOptions; + + TransliterationFlags GetTransliterationFlags_Impl(); + +public: + SvxJSearchOptionsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + virtual ~SvxJSearchOptionsPage() override; + static std::unique_ptr Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet); + + virtual void Reset( const SfxItemSet* rSet ) override; + virtual bool FillItemSet( SfxItemSet* rSet ) override; + + void EnableSaveOptions( bool bVal ) { bSaveOptions = bVal; } + + TransliterationFlags GetTransliterationFlags() const { return nTransliterationFlags; } + void SetTransliterationFlags( TransliterationFlags nSettings ); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/optlingu.cxx b/cui/source/options/optlingu.cxx new file mode 100644 index 000000000..dd5cda2d9 --- /dev/null +++ b/cui/source/options/optlingu.cxx @@ -0,0 +1,1971 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include + +using namespace ::ucbhelper; +using namespace ::com::sun::star; +using namespace css::lang; +using namespace css::uno; +using namespace css::linguistic2; +using namespace css::beans; + +static const char cSpell[] = SN_SPELLCHECKER; +static const char cGrammar[] = SN_GRAMMARCHECKER; +static const char cHyph[] = SN_HYPHENATOR; +static const char cThes[] = SN_THESAURUS; + +// static ---------------------------------------------------------------- + +static sal_Int32 lcl_SeqGetEntryPos( + const Sequence< OUString > &rSeq, const OUString &rEntry ) +{ + sal_Int32 i; + sal_Int32 nLen = rSeq.getLength(); + const OUString *pItem = rSeq.getConstArray(); + for (i = 0; i < nLen; ++i) + { + if (rEntry == pItem[i]) + break; + } + return i < nLen ? i : -1; +} + +static bool KillFile_Impl( const OUString& rURL ) +{ + bool bRet = true; + try + { + Content aCnt( rURL, uno::Reference< css::ucb::XCommandEnvironment >(), comphelper::getProcessComponentContext() ); + aCnt.executeCommand( "delete", Any( true ) ); + } + catch( ... ) + { + TOOLS_WARN_EXCEPTION( "cui.options", "KillFile" ); + bRet = false; + } + + return bRet; +} + +// 0x 0p 0t 0c nn +// p: 1 -> parent +// t: 1 -> spell, 2 -> hyph, 3 -> thes, 4 -> grammar +// c: 1 -> checked 0 -> unchecked +// n: index + +#define TYPE_SPELL sal_uInt8(1) +#define TYPE_GRAMMAR sal_uInt8(2) +#define TYPE_HYPH sal_uInt8(3) +#define TYPE_THES sal_uInt8(4) + +namespace { + +class ModuleUserData_Impl +{ + bool bParent; + bool bIsChecked; + sal_uInt8 nType; + sal_uInt8 nIndex; + OUString sImplName; + +public: + ModuleUserData_Impl( const OUString& sImpName, bool bIsParent, bool bChecked, sal_uInt8 nSetType, sal_uInt8 nSetIndex ) : + bParent(bIsParent), + bIsChecked(bChecked), + nType(nSetType), + nIndex(nSetIndex), + sImplName(sImpName) + { + } + bool IsParent() const {return bParent;} + sal_uInt8 GetType() const {return nType;} + bool IsChecked() const {return bIsChecked;} + sal_uInt8 GetIndex() const {return nIndex;} + const OUString& GetImplName() const {return sImplName;} + +}; + + +// User for user-dictionaries (XDictionary interface) + +class DicUserData +{ + sal_uInt32 nVal; + +public: + explicit DicUserData(sal_uInt32 nUserData) : nVal( nUserData ) {} + DicUserData( sal_uInt16 nEID, + bool bChecked, bool bEditable, bool bDeletable ); + + sal_uInt32 GetUserData() const { return nVal; } + sal_uInt16 GetEntryId() const { return static_cast(nVal >> 16); } + bool IsChecked() const { return static_cast((nVal >> 8) & 0x01); } + bool IsDeletable() const { return static_cast((nVal >> 10) & 0x01); } +}; + +} + +DicUserData::DicUserData( + sal_uInt16 nEID, + bool bChecked, bool bEditable, bool bDeletable ) +{ + DBG_ASSERT( nEID < 65000, "Entry Id out of range" ); + nVal = (static_cast(0xFFFF & nEID) << 16) | + (static_cast(bChecked ? 1 : 0) << 8) | + (static_cast(bEditable ? 1 : 0) << 9) | + (static_cast(bDeletable ? 1 : 0) << 10); +} + +/*-------------------------------------------------- + Entry IDs for options listbox of dialog +--------------------------------------------------*/ + +namespace { + +enum EID_OPTIONS +{ + EID_SPELL_AUTO, + EID_GRAMMAR_AUTO, + EID_CAPITAL_WORDS, + EID_WORDS_WITH_DIGITS, + EID_SPELL_SPECIAL, + EID_NUM_MIN_WORDLEN, + EID_NUM_PRE_BREAK, + EID_NUM_POST_BREAK, + EID_HYPH_AUTO, + EID_HYPH_SPECIAL +}; + +} + +//! this array must have an entry for every value of EID_OPTIONS. +// It is used to get the respective property name. +static const char * aEidToPropName[] = +{ + UPN_IS_SPELL_AUTO, // EID_SPELL_AUTO + UPN_IS_GRAMMAR_AUTO, // EID_GRAMMAR_AUTO + UPN_IS_SPELL_UPPER_CASE, // EID_CAPITAL_WORDS + UPN_IS_SPELL_WITH_DIGITS, // EID_WORDS_WITH_DIGITS + UPN_IS_SPELL_SPECIAL, // EID_SPELL_SPECIAL + UPN_HYPH_MIN_WORD_LENGTH, // EID_NUM_MIN_WORDLEN, + UPN_HYPH_MIN_LEADING, // EID_NUM_PRE_BREAK + UPN_HYPH_MIN_TRAILING, // EID_NUM_POST_BREAK + UPN_IS_HYPH_AUTO, // EID_HYPH_AUTO + UPN_IS_HYPH_SPECIAL // EID_HYPH_SPECIAL +}; + +static OUString lcl_GetPropertyName( EID_OPTIONS eEntryId ) +{ + DBG_ASSERT( static_cast(eEntryId) < SAL_N_ELEMENTS(aEidToPropName), "index out of range" ); + return OUString::createFromAscii( aEidToPropName[ static_cast(eEntryId) ] ); +} + +namespace { + +class OptionsBreakSet : public weld::GenericDialogController +{ + std::unique_ptr m_xBeforeFrame; + std::unique_ptr m_xAfterFrame; + std::unique_ptr m_xMinimalFrame; + std::unique_ptr m_xBreakNF; + +public: + OptionsBreakSet(weld::Window* pParent, sal_uInt16 nRID) + : GenericDialogController(pParent, "cui/ui/breaknumberoption.ui", "BreakNumberOption") + , m_xBeforeFrame(m_xBuilder->weld_widget("beforeframe")) + , m_xAfterFrame(m_xBuilder->weld_widget("afterframe")) + , m_xMinimalFrame(m_xBuilder->weld_widget("miniframe")) + { + assert(EID_NUM_PRE_BREAK == nRID || EID_NUM_POST_BREAK == nRID || EID_NUM_MIN_WORDLEN == nRID); //unexpected ID + + if (nRID == EID_NUM_PRE_BREAK) + { + m_xBeforeFrame->show(); + m_xBreakNF = m_xBuilder->weld_spin_button("beforebreak"); + } + else if(nRID == EID_NUM_POST_BREAK) + { + m_xAfterFrame->show(); + m_xBreakNF = m_xBuilder->weld_spin_button("afterbreak"); + } + else if(nRID == EID_NUM_MIN_WORDLEN) + { + m_xMinimalFrame->show(); + m_xBreakNF = m_xBuilder->weld_spin_button("wordlength"); + } + } + + weld::SpinButton& GetNumericFld() + { + return *m_xBreakNF; + } +}; + +// class OptionsUserData ------------------------------------------------- + +class OptionsUserData +{ + sal_uInt32 nVal; + +public: + explicit OptionsUserData( sal_uInt32 nUserData ) : nVal( nUserData ) {} + OptionsUserData( sal_uInt16 nEID, + bool bHasNV, sal_uInt16 nNumVal, + bool bCheckable, bool bChecked ); + + sal_uInt32 GetUserData() const { return nVal; } + sal_uInt16 GetEntryId() const { return static_cast(nVal >> 16); } + bool HasNumericValue() const { return static_cast((nVal >> 10) & 0x01); } + sal_uInt16 GetNumericValue() const { return static_cast(nVal & 0xFF); } + bool IsCheckable() const { return static_cast((nVal >> 9) & 0x01); } + bool IsModified() const { return static_cast((nVal >> 11) & 0x01); } + + void SetNumericValue( sal_uInt8 nNumVal ); +}; + +} + +OptionsUserData::OptionsUserData( sal_uInt16 nEID, + bool bHasNV, sal_uInt16 nNumVal, + bool bCheckable, bool bChecked ) +{ + DBG_ASSERT( nEID < 65000, "Entry Id out of range" ); + DBG_ASSERT( nNumVal < 256, "value out of range" ); + nVal = (static_cast(0xFFFF & nEID) << 16) | + (static_cast(bHasNV ? 1 : 0) << 10) | + (static_cast(bCheckable ? 1 : 0) << 9) | + (static_cast(bChecked ? 1 : 0) << 8) | + static_cast(0xFF & nNumVal); +} + +void OptionsUserData::SetNumericValue( sal_uInt8 nNumVal ) +{ + if (HasNumericValue() && (GetNumericValue() != nNumVal)) + { + nVal &= 0xffffff00; + nVal |= nNumVal; + nVal |= sal_uInt32(1) << 11; // mark as modified + } +} + +// ServiceInfo_Impl ---------------------------------------------------- + +namespace { + +struct ServiceInfo_Impl +{ + OUString sDisplayName; + OUString sSpellImplName; + OUString sHyphImplName; + OUString sThesImplName; + OUString sGrammarImplName; + uno::Reference< XSpellChecker > xSpell; + uno::Reference< XHyphenator > xHyph; + uno::Reference< XThesaurus > xThes; + uno::Reference< XProofreader > xGrammar; + bool bConfigured; + + ServiceInfo_Impl() : bConfigured(false) {} +}; + +} + +typedef std::vector< ServiceInfo_Impl > ServiceInfoArr; +typedef std::map< LanguageType, Sequence< OUString > > LangImplNameTable; + + +// SvxLinguData_Impl ---------------------------------------------------- + +class SvxLinguData_Impl +{ + //contains services and implementation names sorted by implementation names + ServiceInfoArr aDisplayServiceArr; + sal_uInt32 nDisplayServices; + + Sequence< Locale > aAllServiceLocales; + LangImplNameTable aCfgSpellTable; + LangImplNameTable aCfgHyphTable; + LangImplNameTable aCfgThesTable; + LangImplNameTable aCfgGrammarTable; + uno::Reference< XLinguServiceManager2 > xLinguSrvcMgr; + + + static bool AddRemove( Sequence< OUString > &rConfigured, + const OUString &rImplName, bool bAdd ); + +public: + SvxLinguData_Impl(); + + uno::Reference & GetManager() { return xLinguSrvcMgr; } + + void SetChecked( const Sequence< OUString > &rConfiguredServices ); + void Reconfigure( const OUString &rDisplayName, bool bEnable ); + + const Sequence & GetAllSupportedLocales() const { return aAllServiceLocales; } + + LangImplNameTable & GetSpellTable() { return aCfgSpellTable; } + LangImplNameTable & GetHyphTable() { return aCfgHyphTable; } + LangImplNameTable & GetThesTable() { return aCfgThesTable; } + LangImplNameTable & GetGrammarTable() { return aCfgGrammarTable; } + + ServiceInfoArr & GetDisplayServiceArray() { return aDisplayServiceArr; } + + const sal_uInt32 & GetDisplayServiceCount() const { return nDisplayServices; } + void SetDisplayServiceCount( sal_uInt32 nVal ) { nDisplayServices = nVal; } + + // returns the list of service implementation names for the specified + // language and service (TYPE_SPELL, TYPE_HYPH, TYPE_THES) sorted in + // the proper order for the SvxEditModulesDlg (the ones from the + // configuration (keeping that order!) first and then the other ones. + // I.e. the ones available but not configured in arbitrary order). + // They available ones may contain names that do not(!) support that + // language. + Sequence< OUString > GetSortedImplNames( LanguageType nLang, sal_uInt8 nType ); + + ServiceInfo_Impl * GetInfoByImplName( const OUString &rSvcImplName ); +}; + + +static sal_Int32 lcl_SeqGetIndex( const Sequence< OUString > &rSeq, const OUString &rTxt ) +{ + sal_Int32 nRes = -1; + sal_Int32 nLen = rSeq.getLength(); + const OUString *pString = rSeq.getConstArray(); + for (sal_Int32 i = 0; i < nLen && nRes == -1; ++i) + { + if (pString[i] == rTxt) + nRes = i; + } + return nRes; +} + + +Sequence< OUString > SvxLinguData_Impl::GetSortedImplNames( LanguageType nLang, sal_uInt8 nType ) +{ + LangImplNameTable *pTable = nullptr; + switch (nType) + { + case TYPE_SPELL : pTable = &aCfgSpellTable; break; + case TYPE_HYPH : pTable = &aCfgHyphTable; break; + case TYPE_THES : pTable = &aCfgThesTable; break; + case TYPE_GRAMMAR : pTable = &aCfgGrammarTable; break; + } + Sequence< OUString > aRes; + if (!pTable) + { + SAL_WARN( "cui.options", "unknown linguistic type" ); + return aRes; + } + if (pTable->count( nLang )) + aRes = (*pTable)[ nLang ]; // add configured services + sal_Int32 nIdx = aRes.getLength(); + DBG_ASSERT( static_cast(nDisplayServices) >= nIdx, "size mismatch" ); + aRes.realloc( nDisplayServices ); + OUString *pRes = aRes.getArray(); + + // add not configured services + for (sal_Int32 i = 0; i < static_cast(nDisplayServices); ++i) + { + const ServiceInfo_Impl &rInfo = aDisplayServiceArr[ i ]; + OUString aImplName; + switch (nType) + { + case TYPE_SPELL : aImplName = rInfo.sSpellImplName; break; + case TYPE_HYPH : aImplName = rInfo.sHyphImplName; break; + case TYPE_THES : aImplName = rInfo.sThesImplName; break; + case TYPE_GRAMMAR : aImplName = rInfo.sGrammarImplName; break; + } + + if (!aImplName.isEmpty() && (lcl_SeqGetIndex( aRes, aImplName) == -1)) // name not yet added + { + DBG_ASSERT( nIdx < aRes.getLength(), "index out of range" ); + if (nIdx < aRes.getLength()) + pRes[ nIdx++ ] = aImplName; + } + } + // don't forget to put aRes back to its actual size just in case you allocated too much + // since all of the names may have already been added + // otherwise you get duplicate entries in the edit dialog + aRes.realloc( nIdx ); + return aRes; +} + + +ServiceInfo_Impl * SvxLinguData_Impl::GetInfoByImplName( const OUString &rSvcImplName ) +{ + for (sal_uInt32 i = 0; i < nDisplayServices; ++i) + { + ServiceInfo_Impl &rTmp = aDisplayServiceArr[ i ]; + if (rTmp.sSpellImplName == rSvcImplName || + rTmp.sHyphImplName == rSvcImplName || + rTmp.sThesImplName == rSvcImplName || + rTmp.sGrammarImplName == rSvcImplName) + { + return &rTmp; + } + } + return nullptr; +} + + +static void lcl_MergeLocales(Sequence< Locale >& aAllLocales, const Sequence< Locale >& rAdd) +{ + Sequence aLocToAdd(rAdd.getLength()); + Locale* pLocToAdd = aLocToAdd.getArray(); + sal_Int32 nFound = 0; + for(const Locale& i : rAdd) + { + bool bFound = false; + for(const Locale& j : std::as_const(aAllLocales)) + { + if (i.Language == j.Language && + i.Country == j.Country && + i.Variant == j.Variant) + { + bFound = true; + break; + } + } + if(!bFound) + { + pLocToAdd[nFound++] = i; + } + } + sal_Int32 nLength = aAllLocales.getLength(); + aAllLocales.realloc( nLength + nFound); + Locale* pAllLocales2 = aAllLocales.getArray(); + for(sal_Int32 i = 0; i < nFound; i++) + pAllLocales2[nLength++] = pLocToAdd[i]; +} + +static void lcl_MergeDisplayArray( + SvxLinguData_Impl &rData, + const ServiceInfo_Impl &rToAdd ) +{ + sal_uInt32 nCnt = 0; + + ServiceInfoArr &rSvcInfoArr = rData.GetDisplayServiceArray(); + sal_uInt32 nEntries = rData.GetDisplayServiceCount(); + + for (sal_uInt32 i = 0; i < nEntries; ++i) + { + ServiceInfo_Impl& rEntry = rSvcInfoArr[i]; + if (rEntry.sDisplayName == rToAdd.sDisplayName) + { + if(rToAdd.xSpell.is()) + { + DBG_ASSERT( !rEntry.xSpell.is() && + rEntry.sSpellImplName.isEmpty(), + "merge conflict" ); + rEntry.sSpellImplName = rToAdd.sSpellImplName; + rEntry.xSpell = rToAdd.xSpell; + } + if(rToAdd.xGrammar.is()) + { + DBG_ASSERT( !rEntry.xGrammar.is() && + rEntry.sGrammarImplName.isEmpty(), + "merge conflict" ); + rEntry.sGrammarImplName = rToAdd.sGrammarImplName; + rEntry.xGrammar = rToAdd.xGrammar; + } + if(rToAdd.xHyph.is()) + { + DBG_ASSERT( !rEntry.xHyph.is() && + rEntry.sHyphImplName.isEmpty(), + "merge conflict" ); + rEntry.sHyphImplName = rToAdd.sHyphImplName; + rEntry.xHyph = rToAdd.xHyph; + } + if(rToAdd.xThes.is()) + { + DBG_ASSERT( !rEntry.xThes.is() && + rEntry.sThesImplName.isEmpty(), + "merge conflict" ); + rEntry.sThesImplName = rToAdd.sThesImplName; + rEntry.xThes = rToAdd.xThes; + } + return ; + } + ++nCnt; + } + rData.GetDisplayServiceArray().push_back( rToAdd ); + rData.SetDisplayServiceCount( nCnt + 1 ); +} + +SvxLinguData_Impl::SvxLinguData_Impl() : + nDisplayServices (0) +{ + uno::Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext(); + xLinguSrvcMgr = LinguServiceManager::create(xContext); + + const Locale& rCurrentLocale = Application::GetSettings().GetLanguageTag().getLocale(); + Sequence aArgs(2);//second arguments has to be empty! + aArgs.getArray()[0] <<= LinguMgr::GetLinguPropertySet(); + + //read spell checker + const Sequence< OUString > aSpellNames = xLinguSrvcMgr->getAvailableServices( + cSpell, Locale() ); + + for(const OUString& spellName : aSpellNames) + { + ServiceInfo_Impl aInfo; + aInfo.sSpellImplName = spellName; + aInfo.xSpell.set( + xContext->getServiceManager()->createInstanceWithArgumentsAndContext(aInfo.sSpellImplName, aArgs, xContext), UNO_QUERY); + + uno::Reference xDispName(aInfo.xSpell, UNO_QUERY); + if(xDispName.is()) + aInfo.sDisplayName = xDispName->getServiceDisplayName( rCurrentLocale ); + + const Sequence< Locale > aLocales( aInfo.xSpell->getLocales() ); + //! suppress display of entries with no supported languages (see feature 110994) + if (aLocales.hasElements()) + { + lcl_MergeLocales( aAllServiceLocales, aLocales ); + lcl_MergeDisplayArray( *this, aInfo ); + } + } + + //read grammar checker + const Sequence< OUString > aGrammarNames = xLinguSrvcMgr->getAvailableServices( + cGrammar, Locale() ); + for(const OUString& grammarName : aGrammarNames) + { + ServiceInfo_Impl aInfo; + aInfo.sGrammarImplName = grammarName; + aInfo.xGrammar.set( + xContext->getServiceManager()->createInstanceWithArgumentsAndContext(aInfo.sGrammarImplName, aArgs, xContext), UNO_QUERY); + + uno::Reference xDispName(aInfo.xGrammar, UNO_QUERY); + if(xDispName.is()) + aInfo.sDisplayName = xDispName->getServiceDisplayName( rCurrentLocale ); + + const Sequence< Locale > aLocales( aInfo.xGrammar->getLocales() ); + //! suppress display of entries with no supported languages (see feature 110994) + if (aLocales.hasElements()) + { + lcl_MergeLocales( aAllServiceLocales, aLocales ); + lcl_MergeDisplayArray( *this, aInfo ); + } + } + + //read hyphenator + const Sequence< OUString > aHyphNames = xLinguSrvcMgr->getAvailableServices( + cHyph, Locale() ); + for(const OUString& hyphName : aHyphNames) + { + ServiceInfo_Impl aInfo; + aInfo.sHyphImplName = hyphName; + aInfo.xHyph.set( xContext->getServiceManager()->createInstanceWithArgumentsAndContext(aInfo.sHyphImplName, aArgs, xContext), UNO_QUERY); + + uno::Reference xDispName(aInfo.xHyph, UNO_QUERY); + if(xDispName.is()) + aInfo.sDisplayName = xDispName->getServiceDisplayName( rCurrentLocale ); + + const Sequence< Locale > aLocales( aInfo.xHyph->getLocales() ); + //! suppress display of entries with no supported languages (see feature 110994) + if (aLocales.hasElements()) + { + lcl_MergeLocales( aAllServiceLocales, aLocales ); + lcl_MergeDisplayArray( *this, aInfo ); + } + } + + //read thesauri + const Sequence< OUString > aThesNames = xLinguSrvcMgr->getAvailableServices( + cThes, Locale() ); + for(const OUString& thesName : aThesNames) + { + ServiceInfo_Impl aInfo; + aInfo.sThesImplName = thesName; + aInfo.xThes.set( xContext->getServiceManager()->createInstanceWithArgumentsAndContext(aInfo.sThesImplName, aArgs, xContext), UNO_QUERY); + + uno::Reference xDispName(aInfo.xThes, UNO_QUERY); + if(xDispName.is()) + aInfo.sDisplayName = xDispName->getServiceDisplayName( rCurrentLocale ); + + const Sequence< Locale > aLocales( aInfo.xThes->getLocales() ); + //! suppress display of entries with no supported languages (see feature 110994) + if (aLocales.hasElements()) + { + lcl_MergeLocales( aAllServiceLocales, aLocales ); + lcl_MergeDisplayArray( *this, aInfo ); + } + } + + Sequence< OUString > aCfgSvcs; + for(auto const & locale : std::as_const(aAllServiceLocales)) + { + LanguageType nLang = LanguageTag::convertToLanguageType( locale ); + + aCfgSvcs = xLinguSrvcMgr->getConfiguredServices(cSpell, locale); + SetChecked( aCfgSvcs ); + if (aCfgSvcs.hasElements()) + aCfgSpellTable[ nLang ] = aCfgSvcs; + + aCfgSvcs = xLinguSrvcMgr->getConfiguredServices(cGrammar, locale); + SetChecked( aCfgSvcs ); + if (aCfgSvcs.hasElements()) + aCfgGrammarTable[ nLang ] = aCfgSvcs; + + aCfgSvcs = xLinguSrvcMgr->getConfiguredServices(cHyph, locale); + SetChecked( aCfgSvcs ); + if (aCfgSvcs.hasElements()) + aCfgHyphTable[ nLang ] = aCfgSvcs; + + aCfgSvcs = xLinguSrvcMgr->getConfiguredServices(cThes, locale); + SetChecked( aCfgSvcs ); + if (aCfgSvcs.hasElements()) + aCfgThesTable[ nLang ] = aCfgSvcs; + } +} + +void SvxLinguData_Impl::SetChecked(const Sequence& rConfiguredServices) +{ + for(OUString const & configService : rConfiguredServices) + { + for (sal_uInt32 i = 0; i < nDisplayServices; ++i) + { + ServiceInfo_Impl& rEntry = aDisplayServiceArr[i]; + if (!rEntry.bConfigured) + { + const OUString &rSrvcImplName = configService; + if (!rSrvcImplName.isEmpty() && + (rEntry.sSpellImplName == rSrvcImplName || + rEntry.sGrammarImplName == rSrvcImplName || + rEntry.sHyphImplName == rSrvcImplName || + rEntry.sThesImplName == rSrvcImplName)) + { + rEntry.bConfigured = true; + break; + } + } + } + } +} + +bool SvxLinguData_Impl::AddRemove( + Sequence< OUString > &rConfigured, + const OUString &rImplName, bool bAdd ) +{ + bool bRet = false; // modified? + + sal_Int32 nEntries = rConfigured.getLength(); + sal_Int32 nPos = lcl_SeqGetEntryPos(rConfigured, rImplName); + if (bAdd && nPos < 0) // add new entry + { + rConfigured.realloc( ++nEntries ); + OUString *pConfigured = rConfigured.getArray(); + pConfigured[nEntries - 1] = rImplName; + bRet = true; + } + else if (!bAdd && nPos >= 0) // remove existing entry + { + OUString *pConfigured = rConfigured.getArray(); + for (sal_Int32 i = nPos; i < nEntries - 1; ++i) + pConfigured[i] = pConfigured[i + 1]; + rConfigured.realloc(--nEntries); + bRet = true; + } + + return bRet; +} + + +void SvxLinguData_Impl::Reconfigure( const OUString &rDisplayName, bool bEnable ) +{ + DBG_ASSERT( !rDisplayName.isEmpty(), "empty DisplayName" ); + + ServiceInfo_Impl *pInfo = nullptr; + for (sal_uInt32 i = 0; i < nDisplayServices; ++i) + { + ServiceInfo_Impl& rTmp = aDisplayServiceArr[i]; + if (rTmp.sDisplayName == rDisplayName) + { + pInfo = &rTmp; + break; + } + } + DBG_ASSERT( pInfo, "DisplayName entry not found" ); + if (!pInfo) + return; + + pInfo->bConfigured = bEnable; + + Sequence< Locale > aLocales; + const Locale *pLocale = nullptr; + sal_Int32 nLocales = 0; + sal_Int32 i; + + // update configured spellchecker entries + if (pInfo->xSpell.is()) + { + aLocales = pInfo->xSpell->getLocales(); + pLocale = aLocales.getConstArray(); + nLocales = aLocales.getLength(); + for (i = 0; i < nLocales; ++i) + { + LanguageType nLang = LanguageTag::convertToLanguageType( pLocale[i] ); + if (!aCfgSpellTable.count( nLang ) && bEnable) + aCfgSpellTable[ nLang ] = Sequence< OUString >(); + if (aCfgSpellTable.count( nLang )) + AddRemove( aCfgSpellTable[ nLang ], pInfo->sSpellImplName, bEnable ); + } + } + + // update configured grammar checker entries + if (pInfo->xGrammar.is()) + { + aLocales = pInfo->xGrammar->getLocales(); + pLocale = aLocales.getConstArray(); + nLocales = aLocales.getLength(); + for (i = 0; i < nLocales; ++i) + { + LanguageType nLang = LanguageTag::convertToLanguageType( pLocale[i] ); + if (!aCfgGrammarTable.count( nLang ) && bEnable) + aCfgGrammarTable[ nLang ] = Sequence< OUString >(); + if (aCfgGrammarTable.count( nLang )) + AddRemove( aCfgGrammarTable[ nLang ], pInfo->sGrammarImplName, bEnable ); + } + } + + // update configured hyphenator entries + if (pInfo->xHyph.is()) + { + aLocales = pInfo->xHyph->getLocales(); + pLocale = aLocales.getConstArray(); + nLocales = aLocales.getLength(); + for (i = 0; i < nLocales; ++i) + { + LanguageType nLang = LanguageTag::convertToLanguageType( pLocale[i] ); + if (!aCfgHyphTable.count( nLang ) && bEnable) + aCfgHyphTable[ nLang ] = Sequence< OUString >(); + if (aCfgHyphTable.count( nLang )) + AddRemove( aCfgHyphTable[ nLang ], pInfo->sHyphImplName, bEnable ); + } + } + + // update configured spellchecker entries + if (!pInfo->xThes.is()) + return; + + aLocales = pInfo->xThes->getLocales(); + pLocale = aLocales.getConstArray(); + nLocales = aLocales.getLength(); + for (i = 0; i < nLocales; ++i) + { + LanguageType nLang = LanguageTag::convertToLanguageType( pLocale[i] ); + if (!aCfgThesTable.count( nLang ) && bEnable) + aCfgThesTable[ nLang ] = Sequence< OUString >(); + if (aCfgThesTable.count( nLang )) + AddRemove( aCfgThesTable[ nLang ], pInfo->sThesImplName, bEnable ); + } +} + + +// class SvxLinguTabPage ------------------------------------------------- + +SvxLinguTabPage::SvxLinguTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/optlingupage.ui", "OptLinguPage", &rSet) + , sCapitalWords (CuiResId(RID_SVXSTR_CAPITAL_WORDS)) + , sWordsWithDigits(CuiResId(RID_SVXSTR_WORDS_WITH_DIGITS)) + , sSpellSpecial (CuiResId(RID_SVXSTR_SPELL_SPECIAL)) + , sSpellAuto (CuiResId(RID_SVXSTR_SPELL_AUTO)) + , sGrammarAuto (CuiResId(RID_SVXSTR_GRAMMAR_AUTO)) + , sNumMinWordlen (CuiResId(RID_SVXSTR_NUM_MIN_WORDLEN)) + , sNumPreBreak (CuiResId(RID_SVXSTR_NUM_PRE_BREAK)) + , sNumPostBreak (CuiResId(RID_SVXSTR_NUM_POST_BREAK)) + , sHyphAuto (CuiResId(RID_SVXSTR_HYPH_AUTO)) + , sHyphSpecial (CuiResId(RID_SVXSTR_HYPH_SPECIAL)) + , nUPN_HYPH_MIN_WORD_LENGTH(-1) + , nUPN_HYPH_MIN_LEADING(-1) + , nUPN_HYPH_MIN_TRAILING(-1) + , m_nDlbClickEventId(nullptr) + , m_xLinguModulesFT(m_xBuilder->weld_label("lingumodulesft")) + , m_xLinguModulesCLB(m_xBuilder->weld_tree_view("lingumodules")) + , m_xLinguModulesEditPB(m_xBuilder->weld_button("lingumodulesedit")) + , m_xLinguDicsFT(m_xBuilder->weld_label("lingudictsft")) + , m_xLinguDicsCLB(m_xBuilder->weld_tree_view("lingudicts")) + , m_xLinguDicsNewPB(m_xBuilder->weld_button("lingudictsnew")) + , m_xLinguDicsEditPB(m_xBuilder->weld_button("lingudictsedit")) + , m_xLinguDicsDelPB(m_xBuilder->weld_button("lingudictsdelete")) + , m_xLinguOptionsCLB(m_xBuilder->weld_tree_view("linguoptions")) + , m_xLinguOptionsEditPB(m_xBuilder->weld_button("linguoptionsedit")) + , m_xMoreDictsLink(m_xBuilder->weld_link_button("moredictslink")) +{ + std::vector aWidths; + aWidths.push_back(m_xLinguModulesCLB->get_checkbox_column_width()); + + m_xLinguModulesCLB->set_column_fixed_widths(aWidths); + m_xLinguDicsCLB->set_column_fixed_widths(aWidths); + m_xLinguOptionsCLB->set_column_fixed_widths(aWidths); + + m_xLinguModulesCLB->connect_changed( LINK( this, SvxLinguTabPage, SelectHdl_Impl )); + m_xLinguModulesCLB->connect_row_activated(LINK(this, SvxLinguTabPage, BoxDoubleClickHdl_Impl)); + m_xLinguModulesCLB->connect_toggled(LINK(this, SvxLinguTabPage, ModulesBoxCheckButtonHdl_Impl)); + + m_xLinguModulesEditPB->connect_clicked( LINK( this, SvxLinguTabPage, ClickHdl_Impl )); + m_xLinguOptionsEditPB->connect_clicked( LINK( this, SvxLinguTabPage, ClickHdl_Impl )); + + m_xLinguDicsCLB->connect_changed( LINK( this, SvxLinguTabPage, SelectHdl_Impl )); + m_xLinguDicsCLB->connect_toggled(LINK(this, SvxLinguTabPage, DicsBoxCheckButtonHdl_Impl)); + + m_xLinguDicsNewPB->connect_clicked( LINK( this, SvxLinguTabPage, ClickHdl_Impl )); + m_xLinguDicsEditPB->connect_clicked( LINK( this, SvxLinguTabPage, ClickHdl_Impl )); + m_xLinguDicsDelPB->connect_clicked( LINK( this, SvxLinguTabPage, ClickHdl_Impl )); + + m_xLinguOptionsCLB->connect_changed( LINK( this, SvxLinguTabPage, SelectHdl_Impl )); + m_xLinguOptionsCLB->connect_row_activated(LINK(this, SvxLinguTabPage, BoxDoubleClickHdl_Impl)); + + if ( SvtExtendedSecurityOptions().GetOpenHyperlinkMode() == SvtExtendedSecurityOptions::OPEN_NEVER ) + m_xMoreDictsLink->hide(); + + xProp = LinguMgr::GetLinguPropertySet(); + xDicList.set( LinguMgr::GetDictionaryList() ); + if (xDicList.is()) + { + // keep references to all **currently** available dictionaries, + // since the diclist may get changed meanwhile (e.g. through the API). + // We want the dialog to operate on the same set of dictionaries it + // was started with. + // Also we have to take care to not lose the last reference when + // someone else removes a dictionary from the list. + // removed dics will be replaced by NULL new entries be added to the end + // Thus we may use indices as consistent references. + aDics = xDicList->getDictionaries(); + + UpdateDicBox_Impl(); + } + else + { + m_xLinguDicsFT->set_sensitive(false); + m_xLinguDicsCLB->set_sensitive(false); + m_xLinguDicsNewPB->set_sensitive(false); + m_xLinguDicsEditPB->set_sensitive(false); + m_xLinguDicsDelPB->set_sensitive(false); + } +} + +SvxLinguTabPage::~SvxLinguTabPage() +{ + if (m_nDlbClickEventId) + { + Application::RemoveUserEvent(m_nDlbClickEventId); + m_nDlbClickEventId = nullptr; + } + pLinguData.reset(); +} + +std::unique_ptr SvxLinguTabPage::Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet ) +{ + return std::make_unique( pPage, pController, *rAttrSet ); +} + +bool SvxLinguTabPage::FillItemSet( SfxItemSet* rCoreSet ) +{ + bool bModified = true; // !!!! + + // if not HideGroups was called with GROUP_MODULES... + if (m_xLinguModulesCLB->get_visible()) + { + DBG_ASSERT( pLinguData, "pLinguData not yet initialized" ); + if (!pLinguData) + pLinguData.reset( new SvxLinguData_Impl ); + + // update spellchecker configuration entries + const LangImplNameTable *pTable = &pLinguData->GetSpellTable(); + for (auto const& elem : *pTable) + { + LanguageType nLang = elem.first; + const Sequence< OUString > aImplNames(elem.second); + uno::Reference< XLinguServiceManager2 > xMgr( pLinguData->GetManager() ); + Locale aLocale( LanguageTag::convertToLocale(nLang) ); + if (xMgr.is()) + xMgr->setConfiguredServices( cSpell, aLocale, aImplNames ); + } + + // update grammar checker configuration entries + pTable = &pLinguData->GetGrammarTable(); + for (auto const& elem : *pTable) + { + LanguageType nLang = elem.first; + const Sequence< OUString > aImplNames(elem.second); + uno::Reference< XLinguServiceManager2 > xMgr( pLinguData->GetManager() ); + Locale aLocale( LanguageTag::convertToLocale(nLang) ); + if (xMgr.is()) + xMgr->setConfiguredServices( cGrammar, aLocale, aImplNames ); + } + + // update hyphenator configuration entries + pTable = &pLinguData->GetHyphTable(); + for (auto const& elem : *pTable) + { + LanguageType nLang = elem.first; + const Sequence< OUString > aImplNames(elem.second); + uno::Reference< XLinguServiceManager2 > xMgr( pLinguData->GetManager() ); + Locale aLocale( LanguageTag::convertToLocale(nLang) ); + if (xMgr.is()) + xMgr->setConfiguredServices( cHyph, aLocale, aImplNames ); + } + + // update thesaurus configuration entries + pTable = &pLinguData->GetThesTable(); + for (auto const& elem : *pTable) + { + LanguageType nLang = elem.first; + const Sequence< OUString > aImplNames(elem.second); + uno::Reference< XLinguServiceManager2 > xMgr( pLinguData->GetManager() ); + Locale aLocale( LanguageTag::convertToLocale(nLang) ); + if (xMgr.is()) + xMgr->setConfiguredServices( cThes, aLocale, aImplNames ); + } + } + + + // activate dictionaries according to checkbox state + + Sequence< OUString > aActiveDics; + sal_Int32 nActiveDics = 0; + int nEntries = m_xLinguDicsCLB->n_children(); + for (int i = 0; i < nEntries; ++i) + { + sal_Int32 nDics = aDics.getLength(); + + aActiveDics.realloc( nDics ); + OUString *pActiveDic = aActiveDics.getArray(); + + DicUserData aData(m_xLinguDicsCLB->get_id(i).toUInt32()); + if (aData.GetEntryId() < nDics) + { + bool bChecked = m_xLinguDicsCLB->get_toggle(i, 0) == TRISTATE_TRUE; + uno::Reference< XDictionary > xDic( aDics.getConstArray()[ i ] ); + if (xDic.is()) + { + if (LinguMgr::GetIgnoreAllList() == xDic) + bChecked = true; + xDic->setActive( bChecked ); + + if (bChecked) + { + OUString aDicName( xDic->getName() ); + pActiveDic[ nActiveDics++ ] = aDicName; + } + } + } + } + + aActiveDics.realloc( nActiveDics ); + Any aTmp; + aTmp <<= aActiveDics; + SvtLinguConfig aLngCfg; + aLngCfg.SetProperty( UPH_ACTIVE_DICTIONARIES, aTmp ); + + + nEntries = m_xLinguOptionsCLB->n_children(); + for (int j = 0; j < nEntries; ++j) + { + OptionsUserData aData(m_xLinguOptionsCLB->get_id(j).toUInt32()); + OUString aPropName( lcl_GetPropertyName( static_cast(aData.GetEntryId()) ) ); + + Any aAny; + if (aData.IsCheckable()) + { + bool bChecked = m_xLinguOptionsCLB->get_toggle(j, 0) == TRISTATE_TRUE; + aAny <<= bChecked; + } + else if (aData.HasNumericValue()) + { + sal_Int16 nVal = aData.GetNumericValue(); + aAny <<= nVal; + } + + if (xProp.is()) + xProp->setPropertyValue( aPropName, aAny ); + aLngCfg.SetProperty( aPropName, aAny ); + } + + OptionsUserData aPreBreakData(m_xLinguOptionsCLB->get_id(EID_NUM_PRE_BREAK).toUInt32()); + OptionsUserData aPostBreakData(m_xLinguOptionsCLB->get_id(EID_NUM_POST_BREAK).toUInt32()); + if ( aPreBreakData.IsModified() || aPostBreakData.IsModified() ) + { + SfxHyphenRegionItem aHyp( GetWhich( SID_ATTR_HYPHENREGION ) ); + aHyp.GetMinLead() = static_cast(aPreBreakData.GetNumericValue()); + aHyp.GetMinTrail() = static_cast(aPostBreakData.GetNumericValue()); + rCoreSet->Put( aHyp ); + } + + // automatic spell checking + bool bNewAutoCheck = m_xLinguOptionsCLB->get_toggle(EID_SPELL_AUTO, 0) == TRISTATE_TRUE; + const SfxPoolItem* pOld = GetOldItem( *rCoreSet, SID_AUTOSPELL_CHECK ); + if ( !pOld || static_cast(pOld)->GetValue() != bNewAutoCheck ) + { + rCoreSet->Put( SfxBoolItem( GetWhich( SID_AUTOSPELL_CHECK ), + bNewAutoCheck ) ); + bModified = true; + } + + return bModified; +} + +sal_uInt32 SvxLinguTabPage::GetDicUserData( const uno::Reference< XDictionary > &rxDic, sal_uInt16 nIdx ) +{ + sal_uInt32 nRes = 0; + DBG_ASSERT( rxDic.is(), "dictionary not supplied" ); + if (rxDic.is()) + { + uno::Reference< frame::XStorable > xStor( rxDic, UNO_QUERY ); + + bool bChecked = rxDic->isActive(); + bool bEditable = !xStor.is() || !xStor->isReadonly(); + bool bDeletable = bEditable; + + nRes = DicUserData( nIdx, + bChecked, bEditable, bDeletable ).GetUserData(); + } + return nRes; +} + + +void SvxLinguTabPage::AddDicBoxEntry( + const uno::Reference< XDictionary > &rxDic, + sal_uInt16 nIdx ) +{ + m_xLinguDicsCLB->freeze(); + + OUString aTxt( ::GetDicInfoStr( rxDic->getName(), + LanguageTag( rxDic->getLocale() ).getLanguageType(), + DictionaryType_NEGATIVE == rxDic->getDictionaryType() ) ); + m_xLinguDicsCLB->append(); // append at end + int nEntry = m_xLinguDicsCLB->n_children() - 1; + DicUserData aData( GetDicUserData( rxDic, nIdx ) ); + m_xLinguDicsCLB->set_id(nEntry, OUString::number(aData.GetUserData())); + m_xLinguDicsCLB->set_toggle(nEntry, aData.IsChecked() ? TRISTATE_TRUE : TRISTATE_FALSE, 0); + m_xLinguDicsCLB->set_text(nEntry, aTxt, 1); // append at end + + m_xLinguDicsCLB->thaw(); +} + +void SvxLinguTabPage::UpdateDicBox_Impl() +{ + m_xLinguDicsCLB->freeze(); + m_xLinguDicsCLB->clear(); + + sal_Int32 nDics = aDics.getLength(); + const uno::Reference< XDictionary > *pDic = aDics.getConstArray(); + for (sal_Int32 i = 0; i < nDics; ++i) + { + const uno::Reference< XDictionary > &rDic = pDic[i]; + if (rDic.is()) + AddDicBoxEntry( rDic, static_cast(i) ); + } + + m_xLinguDicsCLB->thaw(); + if (m_xLinguDicsCLB->n_children()) + { + m_xLinguDicsCLB->select(0); + SelectHdl_Impl(*m_xLinguDicsCLB); + } +} + +void SvxLinguTabPage::UpdateModulesBox_Impl() +{ + if (!pLinguData) + return; + + const ServiceInfoArr &rAllDispSrvcArr = pLinguData->GetDisplayServiceArray(); + const sal_uInt32 nDispSrvcCount = pLinguData->GetDisplayServiceCount(); + + m_xLinguModulesCLB->clear(); + + for (sal_uInt32 i = 0; i < nDispSrvcCount; ++i) + { + const ServiceInfo_Impl &rInfo = rAllDispSrvcArr[i]; + m_xLinguModulesCLB->append(); + m_xLinguModulesCLB->set_id(i, OUString::number(reinterpret_cast(&rInfo))); + m_xLinguModulesCLB->set_toggle(i, rInfo.bConfigured ? TRISTATE_TRUE : TRISTATE_FALSE, 0); + m_xLinguModulesCLB->set_text(i, rInfo.sDisplayName, 1); + } + if (nDispSrvcCount) + { + m_xLinguModulesCLB->select(0); + SelectHdl_Impl(*m_xLinguModulesCLB); + } + m_xLinguModulesEditPB->set_sensitive( nDispSrvcCount > 0 ); +} + +void SvxLinguTabPage::Reset( const SfxItemSet* rSet ) +{ + // if not HideGroups was called with GROUP_MODULES... + if (m_xLinguModulesCLB->get_visible()) + { + if (!pLinguData) + pLinguData.reset( new SvxLinguData_Impl ); + UpdateModulesBox_Impl(); + } + + + // get data from configuration + SvtLinguConfig aLngCfg; + + m_xLinguOptionsCLB->freeze(); + m_xLinguOptionsCLB->clear(); + + sal_Int16 nVal = 0; + bool bVal = false; + sal_uInt32 nUserData = 0; + + m_xLinguOptionsCLB->append(); + int nEntry = 0; + + aLngCfg.GetProperty( UPN_IS_SPELL_AUTO ) >>= bVal; + const SfxPoolItem* pItem = GetItem( *rSet, SID_AUTOSPELL_CHECK ); + if (pItem) + bVal = static_cast(pItem)->GetValue(); + nUserData = OptionsUserData( EID_SPELL_AUTO, false, 0, true, bVal).GetUserData(); + m_xLinguOptionsCLB->set_toggle(nEntry, bVal ? TRISTATE_TRUE : TRISTATE_FALSE, 0); + m_xLinguOptionsCLB->set_text(nEntry, sSpellAuto, 1); + m_xLinguOptionsCLB->set_id(nEntry, OUString::number(nUserData)); + + m_xLinguOptionsCLB->append(); + ++nEntry; + + aLngCfg.GetProperty( UPN_IS_GRAMMAR_AUTO ) >>= bVal; + nUserData = OptionsUserData( EID_GRAMMAR_AUTO, false, 0, true, bVal).GetUserData(); + m_xLinguOptionsCLB->set_toggle(nEntry, bVal ? TRISTATE_TRUE : TRISTATE_FALSE, 0); + m_xLinguOptionsCLB->set_text(nEntry, sGrammarAuto, 1); + m_xLinguOptionsCLB->set_id(nEntry, OUString::number(nUserData)); + + m_xLinguOptionsCLB->append(); + ++nEntry; + + aLngCfg.GetProperty( UPN_IS_SPELL_UPPER_CASE ) >>= bVal; + nUserData = OptionsUserData( EID_CAPITAL_WORDS, false, 0, true, bVal).GetUserData(); + m_xLinguOptionsCLB->set_toggle(nEntry, bVal ? TRISTATE_TRUE : TRISTATE_FALSE, 0); + m_xLinguOptionsCLB->set_text(nEntry, sCapitalWords, 1); + m_xLinguOptionsCLB->set_id(nEntry, OUString::number(nUserData)); + + m_xLinguOptionsCLB->append(); + ++nEntry; + + aLngCfg.GetProperty( UPN_IS_SPELL_WITH_DIGITS ) >>= bVal; + nUserData = OptionsUserData( EID_WORDS_WITH_DIGITS, false, 0, true, bVal).GetUserData(); + m_xLinguOptionsCLB->set_toggle(nEntry, bVal ? TRISTATE_TRUE : TRISTATE_FALSE, 0); + m_xLinguOptionsCLB->set_text(nEntry, sWordsWithDigits, 1); + m_xLinguOptionsCLB->set_id(nEntry, OUString::number(nUserData)); + + m_xLinguOptionsCLB->append(); + ++nEntry; + + aLngCfg.GetProperty( UPN_IS_SPELL_SPECIAL ) >>= bVal; + nUserData = OptionsUserData( EID_SPELL_SPECIAL, false, 0, true, bVal).GetUserData(); + m_xLinguOptionsCLB->set_toggle(nEntry, bVal ? TRISTATE_TRUE : TRISTATE_FALSE, 0); + m_xLinguOptionsCLB->set_text(nEntry, sSpellSpecial, 1); + m_xLinguOptionsCLB->set_id(nEntry, OUString::number(nUserData)); + + m_xLinguOptionsCLB->append(); + ++nEntry; + + aLngCfg.GetProperty( UPN_HYPH_MIN_WORD_LENGTH ) >>= nVal; + nUserData = OptionsUserData( EID_NUM_MIN_WORDLEN, true, static_cast(nVal), false, false).GetUserData(); + m_xLinguOptionsCLB->set_text(nEntry, sNumMinWordlen + " " + OUString::number(nVal), 1); + m_xLinguOptionsCLB->set_id(nEntry, OUString::number(nUserData)); + nUPN_HYPH_MIN_WORD_LENGTH = nEntry; + + const SfxHyphenRegionItem *pHyp = nullptr; + sal_uInt16 nWhich = GetWhich( SID_ATTR_HYPHENREGION ); + if ( rSet->GetItemState( nWhich, false ) == SfxItemState::SET ) + pHyp = &static_cast( rSet->Get( nWhich ) ); + + m_xLinguOptionsCLB->append(); + ++nEntry; + + aLngCfg.GetProperty( UPN_HYPH_MIN_LEADING ) >>= nVal; + if (pHyp) + nVal = static_cast(pHyp->GetMinLead()); + nUserData = OptionsUserData( EID_NUM_PRE_BREAK, true, static_cast(nVal), false, false).GetUserData(); + m_xLinguOptionsCLB->set_text(nEntry, sNumPreBreak + " " + OUString::number(nVal), 1); + m_xLinguOptionsCLB->set_id(nEntry, OUString::number(nUserData)); + nUPN_HYPH_MIN_LEADING = nEntry; + + m_xLinguOptionsCLB->append(); + ++nEntry; + + aLngCfg.GetProperty( UPN_HYPH_MIN_TRAILING ) >>= nVal; + if (pHyp) + nVal = static_cast(pHyp->GetMinTrail()); + nUserData = OptionsUserData( EID_NUM_POST_BREAK, true, static_cast(nVal), false, false).GetUserData(); + m_xLinguOptionsCLB->set_text(nEntry, sNumPostBreak + " " + OUString::number(nVal), 1); + m_xLinguOptionsCLB->set_id(nEntry, OUString::number(nUserData)); + nUPN_HYPH_MIN_TRAILING = nEntry; + + m_xLinguOptionsCLB->append(); + ++nEntry; + + aLngCfg.GetProperty( UPN_IS_HYPH_AUTO ) >>= bVal; + nUserData = OptionsUserData( EID_HYPH_AUTO, false, 0, true, bVal).GetUserData(); + m_xLinguOptionsCLB->set_toggle(nEntry, bVal ? TRISTATE_TRUE : TRISTATE_FALSE, 0); + m_xLinguOptionsCLB->set_text(nEntry, sHyphAuto, 1); + m_xLinguOptionsCLB->set_id(nEntry, OUString::number(nUserData)); + + m_xLinguOptionsCLB->append(); + ++nEntry; + + aLngCfg.GetProperty( UPN_IS_HYPH_SPECIAL ) >>= bVal; + nUserData = OptionsUserData( EID_HYPH_SPECIAL, false, 0, true, bVal).GetUserData(); + m_xLinguOptionsCLB->set_toggle(nEntry, bVal ? TRISTATE_TRUE : TRISTATE_FALSE, 0); + m_xLinguOptionsCLB->set_text(nEntry, sHyphSpecial, 1); + m_xLinguOptionsCLB->set_id(nEntry, OUString::number(nUserData)); + + m_xLinguOptionsCLB->thaw(); + + m_xLinguOptionsCLB->select(0); + SelectHdl_Impl(*m_xLinguOptionsCLB); + + m_xLinguModulesCLB->set_size_request(m_xLinguModulesCLB->get_preferred_size().Width(), + m_xLinguModulesCLB->get_height_rows(3)); + m_xLinguDicsCLB->set_size_request(m_xLinguDicsCLB->get_preferred_size().Width(), + m_xLinguDicsCLB->get_height_rows(5)); + m_xLinguOptionsCLB->set_size_request(m_xLinguOptionsCLB->get_preferred_size().Width(), + m_xLinguOptionsCLB->get_height_rows(5)); +} + +IMPL_LINK(SvxLinguTabPage, BoxDoubleClickHdl_Impl, weld::TreeView&, rBox, bool) +{ + if (&rBox == m_xLinguModulesCLB.get() && !m_nDlbClickEventId) + { + //! in order to avoid a bug causing a GPF when double clicking + //! on a module entry and exiting the "Edit Modules" dialog + //! after that. + m_nDlbClickEventId = Application::PostUserEvent(LINK(this, SvxLinguTabPage, PostDblClickHdl_Impl)); + } + else if (&rBox == m_xLinguOptionsCLB.get()) + { + ClickHdl_Impl(*m_xLinguOptionsEditPB); + } + return true; +} + +IMPL_LINK_NOARG(SvxLinguTabPage, PostDblClickHdl_Impl, void*, void) +{ + m_nDlbClickEventId = nullptr; + ClickHdl_Impl(*m_xLinguModulesEditPB); +} + +IMPL_LINK(SvxLinguTabPage, ModulesBoxCheckButtonHdl_Impl, const row_col&, rRowCol, void) +{ + if (!pLinguData) + return; + auto nPos = rRowCol.first; + pLinguData->Reconfigure(m_xLinguModulesCLB->get_text(nPos, 1), + m_xLinguModulesCLB->get_toggle(nPos, 0) == TRISTATE_TRUE); +} + +IMPL_LINK(SvxLinguTabPage, DicsBoxCheckButtonHdl_Impl, const row_col&, rRowCol, void) +{ + auto nPos = rRowCol.first; + const uno::Reference &rDic = aDics.getConstArray()[ nPos ]; + if (LinguMgr::GetIgnoreAllList() == rDic) + m_xLinguDicsCLB->set_toggle(nPos, TRISTATE_TRUE, 0); +} + +IMPL_LINK(SvxLinguTabPage, ClickHdl_Impl, weld::Button&, rBtn, void) +{ + if (m_xLinguModulesEditPB.get() == &rBtn) + { + if (!pLinguData) + pLinguData.reset( new SvxLinguData_Impl ); + + SvxLinguData_Impl aOldLinguData( *pLinguData ); + SvxEditModulesDlg aDlg(GetFrameWeld(), *pLinguData); + if (aDlg.run() != RET_OK) + *pLinguData = aOldLinguData; + + // evaluate new status of 'bConfigured' flag + sal_uInt32 nLen = pLinguData->GetDisplayServiceCount(); + for (sal_uInt32 i = 0; i < nLen; ++i) + pLinguData->GetDisplayServiceArray()[i].bConfigured = false; + const Locale* pAllLocales = pLinguData->GetAllSupportedLocales().getConstArray(); + sal_Int32 nLocales = pLinguData->GetAllSupportedLocales().getLength(); + for (sal_Int32 k = 0; k < nLocales; ++k) + { + LanguageType nLang = LanguageTag::convertToLanguageType( pAllLocales[k] ); + if (pLinguData->GetSpellTable().count( nLang )) + pLinguData->SetChecked( pLinguData->GetSpellTable()[ nLang ] ); + if (pLinguData->GetGrammarTable().count( nLang )) + pLinguData->SetChecked( pLinguData->GetGrammarTable()[ nLang ] ); + if (pLinguData->GetHyphTable().count( nLang )) + pLinguData->SetChecked( pLinguData->GetHyphTable()[ nLang ] ); + if (pLinguData->GetThesTable().count( nLang )) + pLinguData->SetChecked( pLinguData->GetThesTable()[ nLang ] ); + } + + // show new status of modules + UpdateModulesBox_Impl(); + } + else if (m_xLinguDicsNewPB.get() == &rBtn) + { + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr aDlg(pFact->CreateSvxNewDictionaryDialog(GetFrameWeld())); + uno::Reference< XDictionary > xNewDic; + if ( aDlg->Execute() == RET_OK ) + xNewDic = aDlg->GetNewDictionary(); + if ( xNewDic.is() ) + { + // add new dics to the end + sal_Int32 nLen = aDics.getLength(); + aDics.realloc( nLen + 1 ); + + aDics.getArray()[ nLen ] = xNewDic; + + AddDicBoxEntry( xNewDic, static_cast(nLen) ); + } + } + else if (m_xLinguDicsEditPB.get() == &rBtn) + { + int nEntry = m_xLinguDicsCLB->get_selected_index(); + if (nEntry != -1) + { + DicUserData aData(m_xLinguDicsCLB->get_id(nEntry).toUInt32()); + sal_uInt16 nDicPos = aData.GetEntryId(); + sal_Int32 nDics = aDics.getLength(); + if (nDicPos < nDics) + { + uno::Reference< XDictionary > xDic = aDics.getConstArray()[ nDicPos ]; + if (xDic.is()) + { + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr aDlg(pFact->CreateSvxEditDictionaryDialog(GetFrameWeld(), xDic->getName())); + aDlg->Execute(); + } + } + } + } + else if (m_xLinguDicsDelPB.get() == &rBtn) + { + std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querydeletedictionarydialog.ui")); + std::unique_ptr xQuery(xBuilder->weld_message_dialog("QueryDeleteDictionaryDialog")); + if (RET_NO == xQuery->run()) + return; + + int nEntry = m_xLinguDicsCLB->get_selected_index(); + if (nEntry != -1) + { + DicUserData aData(m_xLinguDicsCLB->get_id(nEntry).toUInt32()); + sal_uInt16 nDicPos = aData.GetEntryId(); + sal_Int32 nDics = aDics.getLength(); + if (nDicPos < nDics) + { + uno::Reference< XDictionary > xDic = aDics.getConstArray()[ nDicPos ]; + if (xDic.is()) + { + if (LinguMgr::GetIgnoreAllList() == xDic) + xDic->clear(); + else + { + if (xDicList.is()) + xDicList->removeDictionary( xDic ); + + uno::Reference< frame::XStorable > xStor( xDic, UNO_QUERY ); + if ( xStor->hasLocation() && !xStor->isReadonly() ) + { + OUString sURL = xStor->getLocation(); + INetURLObject aObj(sURL); + DBG_ASSERT( aObj.GetProtocol() == INetProtocol::File, + "non-file URLs cannot be deleted" ); + if ( aObj.GetProtocol() == INetProtocol::File ) + { + KillFile_Impl( aObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); + } + } + + aDics.getArray()[ nDicPos ] = nullptr; + + // remove entry from checklistbox + int nCnt = m_xLinguDicsCLB->n_children(); + for (int i = 0; i < nCnt; ++i) + { + DicUserData aDicData(m_xLinguDicsCLB->get_id(i).toUInt32()); + if (aDicData.GetEntryId() == nDicPos ) + { + m_xLinguDicsCLB->remove(i); + break; + } + } + DBG_ASSERT( nCnt > m_xLinguDicsCLB->n_children(), + "remove failed ?"); + } + } + } + } + } + else if (m_xLinguOptionsEditPB.get() == &rBtn) + { + int nEntry = m_xLinguOptionsCLB->get_selected_index(); + DBG_ASSERT(nEntry != -1, "no entry selected"); + if (nEntry != -1) + { + OptionsUserData aData(m_xLinguOptionsCLB->get_id(nEntry).toUInt32()); + if (aData.HasNumericValue()) + { + sal_uInt16 nRID = aData.GetEntryId(); + OptionsBreakSet aDlg(GetFrameWeld(), nRID); + aDlg.GetNumericFld().set_value(aData.GetNumericValue()); + if (RET_OK == aDlg.run()) + { + int nVal = aDlg.GetNumericFld().get_value(); + if (-1 != nVal && aData.GetNumericValue() != nVal) + { + aData.SetNumericValue( static_cast(nVal) ); //! sets IsModified ! + m_xLinguOptionsCLB->set_id(nEntry, OUString::number(aData.GetUserData())); + if (nEntry == nUPN_HYPH_MIN_WORD_LENGTH) + m_xLinguOptionsCLB->set_text(nEntry, sNumMinWordlen + " " + OUString::number(nVal), 1); + else if (nEntry == nUPN_HYPH_MIN_LEADING) + m_xLinguOptionsCLB->set_text(nEntry, sNumPreBreak + " " + OUString::number(nVal), 1); + else if (nEntry == nUPN_HYPH_MIN_TRAILING) + m_xLinguOptionsCLB->set_text(nEntry, sNumPostBreak + " " + OUString::number(nVal), 1); + m_xLinguOptionsCLB->set_id(nEntry, OUString::number(aData.GetUserData())); + } + } + } + } + } + else + { + OSL_FAIL( "rBtn unexpected value" ); + } +} + +IMPL_LINK(SvxLinguTabPage, SelectHdl_Impl, weld::TreeView&, rBox, void) +{ + if (m_xLinguModulesCLB.get() == &rBox) + { + } + else if (m_xLinguDicsCLB.get() == &rBox) + { + int nEntry = rBox.get_selected_index(); + if (nEntry != -1) + { + DicUserData aData(rBox.get_id(nEntry).toUInt32()); + + // always allow to edit (i.e. at least view the content of the dictionary) + m_xLinguDicsEditPB->set_sensitive( true ); + m_xLinguDicsDelPB->set_sensitive( aData.IsDeletable() ); + } + } + else if (m_xLinguOptionsCLB.get() == &rBox) + { + int nEntry = rBox.get_selected_index(); + if (nEntry != -1) + { + OptionsUserData aData(rBox.get_id(nEntry).toUInt32()); + m_xLinguOptionsEditPB->set_sensitive( aData.HasNumericValue() ); + } + } + else + { + OSL_FAIL( "rBox unexpected value" ); + } +} + +void SvxLinguTabPage::HideGroups( sal_uInt16 nGrp ) +{ + if ( 0 != ( GROUP_MODULES & nGrp ) ) + { + m_xLinguModulesFT->hide(); + m_xLinguModulesCLB->hide(); + m_xLinguModulesEditPB->hide(); + + if ( SvtExtendedSecurityOptions().GetOpenHyperlinkMode() + != SvtExtendedSecurityOptions::OPEN_NEVER ) + { + m_xMoreDictsLink->show(); + } + } +} + +SvxEditModulesDlg::SvxEditModulesDlg(weld::Window* pParent, SvxLinguData_Impl& rData) + : GenericDialogController(pParent, "cui/ui/editmodulesdialog.ui", "EditModulesDialog") + , sSpell(CuiResId(RID_SVXSTR_SPELL)) + , sHyph(CuiResId(RID_SVXSTR_HYPH)) + , sThes(CuiResId(RID_SVXSTR_THES)) + , sGrammar(CuiResId(RID_SVXSTR_GRAMMAR)) + , rLinguData(rData) + , m_xModulesCLB(m_xBuilder->weld_tree_view("lingudicts")) + , m_xPrioUpPB(m_xBuilder->weld_button("up")) + , m_xPrioDownPB(m_xBuilder->weld_button("down")) + , m_xBackPB(m_xBuilder->weld_button("back")) + , m_xMoreDictsLink(m_xBuilder->weld_link_button("moredictslink")) + , m_xClosePB(m_xBuilder->weld_button("close")) + , m_xLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box("language"))) +{ + m_xModulesCLB->set_size_request(m_xModulesCLB->get_approximate_digit_width() * 40, + m_xModulesCLB->get_height_rows(12)); + + std::vector aWidths; + aWidths.push_back(m_xModulesCLB->get_checkbox_column_width()); + m_xModulesCLB->set_column_fixed_widths(aWidths); + + pDefaultLinguData.reset( new SvxLinguData_Impl( rLinguData ) ); + + m_xModulesCLB->connect_changed( LINK( this, SvxEditModulesDlg, SelectHdl_Impl )); + m_xModulesCLB->connect_toggled(LINK(this, SvxEditModulesDlg, BoxCheckButtonHdl_Impl)); + + m_xClosePB->connect_clicked( LINK( this, SvxEditModulesDlg, ClickHdl_Impl )); + m_xPrioUpPB->connect_clicked( LINK( this, SvxEditModulesDlg, UpDownHdl_Impl )); + m_xPrioDownPB->connect_clicked( LINK( this, SvxEditModulesDlg, UpDownHdl_Impl )); + m_xBackPB->connect_clicked( LINK( this, SvxEditModulesDlg, BackHdl_Impl )); + // in case of not installed language modules + m_xPrioUpPB->set_sensitive( false ); + m_xPrioDownPB->set_sensitive( false ); + + if ( SvtExtendedSecurityOptions().GetOpenHyperlinkMode() == SvtExtendedSecurityOptions::OPEN_NEVER ) + m_xMoreDictsLink->hide(); + + // set that we want the checkbox shown if spellchecking is available + m_xLanguageLB->SetLanguageList(SvxLanguageListFlags::EMPTY, false, false, true); + + //fill language box + const Sequence< Locale >& rLoc = rLinguData.GetAllSupportedLocales(); + for (Locale const & locale : rLoc) + { + LanguageType nLang = LanguageTag::convertToLanguageType( locale ); + m_xLanguageLB->InsertLanguage(nLang); + } + LanguageType eSysLang = MsLangId::getSystemLanguage(); + m_xLanguageLB->set_active_id( eSysLang ); + if (m_xLanguageLB->get_active_id() != eSysLang) + m_xLanguageLB->set_active(0); + + m_xLanguageLB->connect_changed( LINK( this, SvxEditModulesDlg, LangSelectListBoxHdl_Impl )); + LangSelectHdl_Impl(m_xLanguageLB.get()); +} + +SvxEditModulesDlg::~SvxEditModulesDlg() +{ + for (int i = 0, nEntryCount = m_xModulesCLB->n_children(); i < nEntryCount; ++i) + delete reinterpret_cast(m_xModulesCLB->get_id(i).toInt64()); +} + +IMPL_LINK( SvxEditModulesDlg, SelectHdl_Impl, weld::TreeView&, rBox, void ) +{ + int nCurPos = rBox.get_selected_index(); + if (nCurPos == -1) + return; + + bool bDisableUp = true; + bool bDisableDown = true; + ModuleUserData_Impl* pData = reinterpret_cast(rBox.get_id(nCurPos).toInt64()); + if (!pData->IsParent() && pData->GetType() != TYPE_HYPH) + { + if (nCurPos < rBox.n_children() - 1) + { + bDisableDown = reinterpret_cast(rBox.get_id(nCurPos + 1).toInt64())->IsParent(); + } + if (nCurPos > 1) + { + bDisableUp = reinterpret_cast(rBox.get_id(nCurPos - 1).toInt64())->IsParent(); + } + } + m_xPrioUpPB->set_sensitive(!bDisableUp); + m_xPrioDownPB->set_sensitive(!bDisableDown); +} + +IMPL_LINK( SvxEditModulesDlg, BoxCheckButtonHdl_Impl, const row_col&, rRowCol, void ) +{ + auto nPos = rRowCol.first; + ModuleUserData_Impl* pData = reinterpret_cast(m_xModulesCLB->get_id(nPos).toInt64()); + if (!(!pData->IsParent() && pData->GetType() == TYPE_HYPH)) + return; + + // make hyphenator checkboxes function as radio-buttons + // (at most one box may be checked) + for (int i = 0, nEntryCount = m_xModulesCLB->n_children(); i < nEntryCount; ++i) + { + pData = reinterpret_cast(m_xModulesCLB->get_id(i).toInt64()); + if (!pData->IsParent() && pData->GetType() == TYPE_HYPH && i != nPos) + { + m_xModulesCLB->set_toggle(i, TRISTATE_FALSE, 0); + } + } +} + +IMPL_LINK_NOARG(SvxEditModulesDlg, LangSelectListBoxHdl_Impl, weld::ComboBox&, void) +{ + LangSelectHdl_Impl(m_xLanguageLB.get()); +} + +void SvxEditModulesDlg::LangSelectHdl_Impl(const SvxLanguageBox* pBox) +{ + LanguageType eCurLanguage = m_xLanguageLB->get_active_id(); + static Locale aLastLocale; + Locale aCurLocale( LanguageTag::convertToLocale( eCurLanguage)); + + if (pBox) + { + // save old probably changed settings + // before switching to new language entries + + LanguageType nLang = LanguageTag::convertToLanguageType( aLastLocale ); + + sal_Int32 nStart = 0, nLocalIndex = 0; + Sequence< OUString > aChange; + bool bChanged = false; + for (int i = 0, nEntryCount = m_xModulesCLB->n_children(); i < nEntryCount; ++i) + { + ModuleUserData_Impl* pData = reinterpret_cast(m_xModulesCLB->get_id(i).toInt64()); + if (pData->IsParent()) + { + if (bChanged) + { + LangImplNameTable *pTable = nullptr; + sal_uInt8 nType = pData->GetType(); + switch (nType - 1) + { + case TYPE_SPELL : pTable = &rLinguData.GetSpellTable(); break; + case TYPE_GRAMMAR : pTable = &rLinguData.GetGrammarTable(); break; + case TYPE_HYPH : pTable = &rLinguData.GetHyphTable(); break; + case TYPE_THES : pTable = &rLinguData.GetThesTable(); break; + } + if (pTable) + { + aChange.realloc(nStart); + (*pTable)[ nLang ] = aChange; + } + } + nLocalIndex = nStart = 0; + aChange.realloc(nEntryCount); + bChanged = false; + } + else + { + OUString* pChange = aChange.getArray(); + pChange[nStart] = pData->GetImplName(); + bChanged |= pData->GetIndex() != nLocalIndex || + static_cast(pData->IsChecked()) != m_xModulesCLB->get_toggle(i, 0); + if (m_xModulesCLB->get_toggle(i, 0)) + nStart++; + ++nLocalIndex; + } + } + if(bChanged) + { + aChange.realloc(nStart); + rLinguData.GetThesTable()[ nLang ] = aChange; + } + } + + for (int i = 0, nEntryCount = m_xModulesCLB->n_children(); i < nEntryCount; ++i) + delete reinterpret_cast(m_xModulesCLB->get_id(i).toInt64()); + m_xModulesCLB->clear(); + + // display entries for new selected language + + if (LANGUAGE_DONTKNOW != eCurLanguage) + { + sal_Int32 n; + ServiceInfo_Impl* pInfo; + + int nRow = 0; + // spellchecker entries + + ModuleUserData_Impl* pUserData = new ModuleUserData_Impl( + OUString(), true, false, TYPE_SPELL, 0 ); + OUString sId(OUString::number(reinterpret_cast(pUserData))); + m_xModulesCLB->append(nullptr); + m_xModulesCLB->set_id(nRow, sId); + m_xModulesCLB->set_text(nRow, sSpell, 1); + m_xModulesCLB->set_text_emphasis(nRow, true, 1); + ++nRow; + + Sequence< OUString > aNames( rLinguData.GetSortedImplNames( eCurLanguage, TYPE_SPELL ) ); + const OUString *pName = aNames.getConstArray(); + sal_Int32 nNames = aNames.getLength(); + sal_Int32 nLocalIndex = 0; // index relative to parent + for (n = 0; n < nNames; ++n) + { + OUString aImplName; + bool bIsSuppLang = false; + + pInfo = rLinguData.GetInfoByImplName( pName[n] ); + if (pInfo) + { + bIsSuppLang = pInfo->xSpell.is() && + pInfo->xSpell->hasLocale( aCurLocale ); + aImplName = pInfo->sSpellImplName; + } + if (!aImplName.isEmpty() && bIsSuppLang) + { + OUString aTxt( pInfo->sDisplayName ); + + LangImplNameTable &rTable = rLinguData.GetSpellTable(); + const bool bHasLang = rTable.count( eCurLanguage ); + if (!bHasLang) + { + SAL_INFO( "cui.options", "language entry missing" ); // only relevant if all languages found should be supported + } + const bool bCheck = bHasLang && lcl_SeqGetEntryPos( rTable[ eCurLanguage ], aImplName ) >= 0; + pUserData = new ModuleUserData_Impl( aImplName, false, + bCheck, TYPE_SPELL, static_cast(nLocalIndex++) ); + sId = OUString::number(reinterpret_cast(pUserData)); + + m_xModulesCLB->append(nullptr); + m_xModulesCLB->set_id(nRow, sId); + m_xModulesCLB->set_toggle(nRow, bCheck ? TRISTATE_TRUE : TRISTATE_FALSE, 0); + m_xModulesCLB->set_text(nRow, aTxt, 1); + m_xModulesCLB->set_text_emphasis(nRow, false, 1); + ++nRow; + } + } + + // grammar checker entries + + pUserData = new ModuleUserData_Impl( OUString(), true, false, TYPE_GRAMMAR, 0 ); + sId = OUString::number(reinterpret_cast(pUserData)); + m_xModulesCLB->append(nullptr); + m_xModulesCLB->set_id(nRow, sId); + m_xModulesCLB->set_text(nRow, sGrammar, 1); + m_xModulesCLB->set_text_emphasis(nRow, true, 1); + ++nRow; + + aNames = rLinguData.GetSortedImplNames( eCurLanguage, TYPE_GRAMMAR ); + pName = aNames.getConstArray(); + nNames = aNames.getLength(); + nLocalIndex = 0; + for (n = 0; n < nNames; ++n) + { + OUString aImplName; + bool bIsSuppLang = false; + + pInfo = rLinguData.GetInfoByImplName( pName[n] ); + if (pInfo) + { + bIsSuppLang = pInfo->xGrammar.is() && + pInfo->xGrammar->hasLocale( aCurLocale ); + aImplName = pInfo->sGrammarImplName; + } + if (!aImplName.isEmpty() && bIsSuppLang) + { + OUString aTxt( pInfo->sDisplayName ); + + LangImplNameTable &rTable = rLinguData.GetGrammarTable(); + const bool bHasLang = rTable.count( eCurLanguage ); + if (!bHasLang) + { + SAL_INFO( "cui.options", "language entry missing" ); // only relevant if all languages found should be supported + } + const bool bCheck = bHasLang && lcl_SeqGetEntryPos( rTable[ eCurLanguage ], aImplName ) >= 0; + pUserData = new ModuleUserData_Impl( aImplName, false, + bCheck, TYPE_GRAMMAR, static_cast(nLocalIndex++) ); + + sId = OUString::number(reinterpret_cast(pUserData)); + + m_xModulesCLB->append(nullptr); + m_xModulesCLB->set_id(nRow, sId); + m_xModulesCLB->set_toggle(nRow, bCheck ? TRISTATE_TRUE : TRISTATE_FALSE, 0); + m_xModulesCLB->set_text(nRow, aTxt, 1); + m_xModulesCLB->set_text_emphasis(nRow, false, 1); + ++nRow; + } + } + + // hyphenator entries + + pUserData = new ModuleUserData_Impl( OUString(), true, false, TYPE_HYPH, 0 ); + sId = OUString::number(reinterpret_cast(pUserData)); + m_xModulesCLB->append(nullptr); + m_xModulesCLB->set_id(nRow, sId); + m_xModulesCLB->set_text(nRow, sHyph, 1); + m_xModulesCLB->set_text_emphasis(nRow, true, 1); + ++nRow; + + aNames = rLinguData.GetSortedImplNames( eCurLanguage, TYPE_HYPH ); + pName = aNames.getConstArray(); + nNames = aNames.getLength(); + nLocalIndex = 0; + for (n = 0; n < nNames; ++n) + { + OUString aImplName; + bool bIsSuppLang = false; + + pInfo = rLinguData.GetInfoByImplName( pName[n] ); + if (pInfo) + { + bIsSuppLang = pInfo->xHyph.is() && + pInfo->xHyph->hasLocale( aCurLocale ); + aImplName = pInfo->sHyphImplName; + } + if (!aImplName.isEmpty() && bIsSuppLang) + { + OUString aTxt( pInfo->sDisplayName ); + + LangImplNameTable &rTable = rLinguData.GetHyphTable(); + const bool bHasLang = rTable.count( eCurLanguage ); + if (!bHasLang) + { + SAL_INFO( "cui.options", "language entry missing" ); // only relevant if all languages found should be supported + } + const bool bCheck = bHasLang && lcl_SeqGetEntryPos( rTable[ eCurLanguage ], aImplName ) >= 0; + pUserData = new ModuleUserData_Impl( aImplName, false, + bCheck, TYPE_HYPH, static_cast(nLocalIndex++) ); + sId = OUString::number(reinterpret_cast(pUserData)); + + m_xModulesCLB->append(nullptr); + m_xModulesCLB->set_id(nRow, sId); + m_xModulesCLB->set_toggle(nRow, bCheck ? TRISTATE_TRUE : TRISTATE_FALSE, 0); + m_xModulesCLB->set_text(nRow, aTxt, 1); + m_xModulesCLB->set_text_emphasis(nRow, false, 1); + ++nRow; + } + } + + // thesaurus entries + + pUserData = new ModuleUserData_Impl( OUString(), true, false, TYPE_THES, 0 ); + sId = OUString::number(reinterpret_cast(pUserData)); + m_xModulesCLB->append(nullptr); + m_xModulesCLB->set_id(nRow, sId); + m_xModulesCLB->set_text(nRow, sThes, 1); + m_xModulesCLB->set_text_emphasis(nRow, true, 1); + ++nRow; + + aNames = rLinguData.GetSortedImplNames( eCurLanguage, TYPE_THES ); + pName = aNames.getConstArray(); + nNames = aNames.getLength(); + nLocalIndex = 0; + for (n = 0; n < nNames; ++n) + { + OUString aImplName; + bool bIsSuppLang = false; + + pInfo = rLinguData.GetInfoByImplName( pName[n] ); + if (pInfo) + { + bIsSuppLang = pInfo->xThes.is() && + pInfo->xThes->hasLocale( aCurLocale ); + aImplName = pInfo->sThesImplName; + } + if (!aImplName.isEmpty() && bIsSuppLang) + { + OUString aTxt( pInfo->sDisplayName ); + + LangImplNameTable &rTable = rLinguData.GetThesTable(); + const bool bHasLang = rTable.count( eCurLanguage ); + if (!bHasLang) + { + SAL_INFO( "cui.options", "language entry missing" ); // only relevant if all languages found should be supported + } + const bool bCheck = bHasLang && lcl_SeqGetEntryPos( rTable[ eCurLanguage ], aImplName ) >= 0; + pUserData = new ModuleUserData_Impl( aImplName, false, + bCheck, TYPE_THES, static_cast(nLocalIndex++) ); + sId = OUString::number(reinterpret_cast(pUserData)); + + m_xModulesCLB->append(nullptr); + m_xModulesCLB->set_id(nRow, sId); + m_xModulesCLB->set_toggle(nRow, bCheck ? TRISTATE_TRUE : TRISTATE_FALSE, 0); + m_xModulesCLB->set_text(nRow, aTxt, 1); + m_xModulesCLB->set_text_emphasis(nRow, false, 1); + ++nRow; + } + } + } + aLastLocale = aCurLocale; +} + +IMPL_LINK( SvxEditModulesDlg, UpDownHdl_Impl, weld::Button&, rBtn, void ) +{ + bool bUp = m_xPrioUpPB.get() == &rBtn; + int nCurPos = m_xModulesCLB->get_selected_index(); + if (nCurPos == -1) + return; + + m_xModulesCLB->freeze(); + + OUString sId(m_xModulesCLB->get_id(nCurPos)); + OUString sStr(m_xModulesCLB->get_text(nCurPos)); + bool bIsChecked = m_xModulesCLB->get_toggle(nCurPos, nCurPos); + + m_xModulesCLB->remove(nCurPos); + + int nDestPos = bUp ? nCurPos - 1 : nCurPos + 1; + + m_xModulesCLB->insert_text(nDestPos, sStr); + m_xModulesCLB->set_id(nDestPos, sId); + m_xModulesCLB->set_toggle(nDestPos, bIsChecked ? TRISTATE_TRUE : TRISTATE_FALSE, 0); + + m_xModulesCLB->thaw(); + + m_xModulesCLB->select(nDestPos); + SelectHdl_Impl(*m_xModulesCLB); +} + +IMPL_LINK_NOARG(SvxEditModulesDlg, ClickHdl_Impl, weld::Button&, void) +{ + // store language config + LangSelectHdl_Impl(m_xLanguageLB.get()); + m_xDialog->response(RET_OK); +} + +IMPL_LINK_NOARG(SvxEditModulesDlg, BackHdl_Impl, weld::Button&, void) +{ + rLinguData = *pDefaultLinguData; + LangSelectHdl_Impl(nullptr); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/optopencl.cxx b/cui/source/options/optopencl.cxx new file mode 100644 index 000000000..e85ef1d7e --- /dev/null +++ b/cui/source/options/optopencl.cxx @@ -0,0 +1,88 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include + +#include "optopencl.hxx" + +SvxOpenCLTabPage::SvxOpenCLTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/optopenclpage.ui", "OptOpenCLPage", &rSet) + , maConfig(OpenCLConfig::get()) + , mxUseOpenCL(m_xBuilder->weld_check_button("useopencl")) + , mxOclUsed(m_xBuilder->weld_label("openclused")) + , mxOclNotUsed(m_xBuilder->weld_label("openclnotused")) +{ + mxUseOpenCL->set_active(maConfig.mbUseOpenCL); + mxUseOpenCL->set_sensitive(!officecfg::Office::Common::Misc::UseOpenCL::isReadOnly()); + + bool bCLUsed = openclwrapper::GPUEnv::isOpenCLEnabled(); + mxOclUsed->set_visible(bCLUsed); + mxOclNotUsed->set_visible(!bCLUsed); +} + +SvxOpenCLTabPage::~SvxOpenCLTabPage() +{ +} + +std::unique_ptr SvxOpenCLTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet) +{ + return std::make_unique(pPage, pController, *rAttrSet); +} + +bool SvxOpenCLTabPage::FillItemSet( SfxItemSet* ) +{ + bool bModified = false; + std::shared_ptr batch(comphelper::ConfigurationChanges::create()); + + if (mxUseOpenCL->get_state_changed_from_saved()) + maConfig.mbUseOpenCL = mxUseOpenCL->get_active(); + + if (maConfig != OpenCLConfig::get()) + { + maConfig.set(); + bModified = true; + } + + if (bModified) + { + batch->commit(); + SolarMutexGuard aGuard; + if (svtools::executeRestartDialog(comphelper::getProcessComponentContext(), nullptr, + svtools::RESTART_REASON_OPENCL)) + GetDialogController()->response(RET_OK); + } + + return bModified; +} + +void SvxOpenCLTabPage::Reset( const SfxItemSet* ) +{ + maConfig = OpenCLConfig::get(); + + mxUseOpenCL->set_active(maConfig.mbUseOpenCL); + mxUseOpenCL->save_state(); +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/optopencl.hxx b/cui/source/options/optopencl.hxx new file mode 100644 index 000000000..f7097d3fd --- /dev/null +++ b/cui/source/options/optopencl.hxx @@ -0,0 +1,42 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include +#include + +class SvxOpenCLTabPage : public SfxTabPage +{ +private: + OpenCLConfig maConfig; + + std::unique_ptr mxUseOpenCL; + std::unique_ptr mxOclUsed; + std::unique_ptr mxOclNotUsed; + +public: + SvxOpenCLTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet ); + virtual ~SvxOpenCLTabPage() override; + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/optpath.cxx b/cui/source/options/optpath.cxx new file mode 100644 index 000000000..809bab6b4 --- /dev/null +++ b/cui/source/options/optpath.cxx @@ -0,0 +1,686 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace css; +using namespace css::beans; +using namespace css::lang; +using namespace css::ui::dialogs; +using namespace css::uno; +using namespace svx; + +// define ---------------------------------------------------------------- + +#define POSTFIX_INTERNAL "_internal" +#define POSTFIX_USER "_user" +#define POSTFIX_WRITABLE "_writable" +#define VAR_ONE "%1" +#define IODLG_CONFIGNAME "FilePicker_Save" + +// struct OptPath_Impl --------------------------------------------------- + +struct OptPath_Impl +{ + SvtDefaultOptions m_aDefOpt; + OUString m_sMultiPathDlg; + Reference< css::util::XPathSettings > m_xPathSettings; + + OptPath_Impl() + : m_sMultiPathDlg(CuiResId(RID_SVXSTR_EDIT_PATHS)) + { + } +}; + +namespace { + +struct PathUserData_Impl +{ + sal_uInt16 nRealId; + SfxItemState eState; + OUString sUserPath; + OUString sWritablePath; + bool bReadOnly; + + explicit PathUserData_Impl(sal_uInt16 nId) + : nRealId(nId) + , eState(SfxItemState::UNKNOWN) + , bReadOnly(false) + { + } +}; + +struct Handle2CfgNameMapping_Impl +{ + sal_uInt16 m_nHandle; + const char* m_pCfgName; +}; + +} + +static Handle2CfgNameMapping_Impl const Hdl2CfgMap_Impl[] = +{ + { SvtPathOptions::PATH_AUTOCORRECT, "AutoCorrect" }, + { SvtPathOptions::PATH_AUTOTEXT, "AutoText" }, + { SvtPathOptions::PATH_BACKUP, "Backup" }, + { SvtPathOptions::PATH_GALLERY, "Gallery" }, + { SvtPathOptions::PATH_GRAPHIC, "Graphic" }, + { SvtPathOptions::PATH_TEMP, "Temp" }, + { SvtPathOptions::PATH_TEMPLATE, "Template" }, + { SvtPathOptions::PATH_WORK, "Work" }, + { SvtPathOptions::PATH_DICTIONARY, "Dictionary" }, + { SvtPathOptions::PATH_CLASSIFICATION, "Classification" }, +#if OSL_DEBUG_LEVEL > 1 + { SvtPathOptions::PATH_LINGUISTIC, "Linguistic" }, +#endif + { USHRT_MAX, nullptr } +}; + +static OUString getCfgName_Impl( sal_uInt16 _nHandle ) +{ + OUString sCfgName; + sal_uInt16 nIndex = 0; + while ( Hdl2CfgMap_Impl[ nIndex ].m_nHandle != USHRT_MAX ) + { + if ( Hdl2CfgMap_Impl[ nIndex ].m_nHandle == _nHandle ) + { + // config name found + sCfgName = OUString::createFromAscii( Hdl2CfgMap_Impl[ nIndex ].m_pCfgName ); + break; + } + ++nIndex; + } + + return sCfgName; +} + +#define MULTIPATH_DELIMITER ';' + +static OUString Convert_Impl( const OUString& rValue ) +{ + if (rValue.isEmpty()) + return OUString(); + + sal_Int32 nPos = 0; + OUStringBuffer aReturn; + for (;;) + { + OUString aValue = rValue.getToken( 0, MULTIPATH_DELIMITER, nPos ); + INetURLObject aObj( aValue ); + if ( aObj.GetProtocol() == INetProtocol::File ) + aReturn.append(aObj.PathToFileName()); + if ( nPos < 0 ) + break; + aReturn.append(MULTIPATH_DELIMITER); + } + + return aReturn.makeStringAndClear(); +} + +// functions ------------------------------------------------------------- + +static bool IsMultiPath_Impl( const sal_uInt16 nIndex ) +{ +#if OSL_DEBUG_LEVEL > 1 + return ( SvtPathOptions::PATH_AUTOCORRECT == nIndex || + SvtPathOptions::PATH_AUTOTEXT == nIndex || + SvtPathOptions::PATH_BASIC == nIndex || + SvtPathOptions::PATH_GALLERY == nIndex || + SvtPathOptions::PATH_TEMPLATE == nIndex ); +#else + return ( SvtPathOptions::PATH_AUTOCORRECT == nIndex || + SvtPathOptions::PATH_AUTOTEXT == nIndex || + SvtPathOptions::PATH_BASIC == nIndex || + SvtPathOptions::PATH_GALLERY == nIndex || + SvtPathOptions::PATH_TEMPLATE == nIndex || + SvtPathOptions::PATH_LINGUISTIC == nIndex || + SvtPathOptions::PATH_DICTIONARY == nIndex ); +#endif +} + +// class SvxPathTabPage -------------------------------------------------- + +SvxPathTabPage::SvxPathTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage( pPage, pController, "cui/ui/optpathspage.ui", "OptPathsPage", &rSet) + , pImpl(new OptPath_Impl) + , xDialogListener ( new ::svt::DialogClosedListener() ) + , m_xStandardBtn(m_xBuilder->weld_button("default")) + , m_xPathBtn(m_xBuilder->weld_button("edit")) + , m_xPathBox(m_xBuilder->weld_tree_view("paths")) +{ + m_xStandardBtn->connect_clicked(LINK(this, SvxPathTabPage, StandardHdl_Impl)); + m_xPathBtn->connect_clicked( LINK( this, SvxPathTabPage, PathHdl_Impl ) ); + + m_xPathBox->set_size_request(m_xPathBox->get_approximate_digit_width() * 60, + m_xPathBox->get_height_rows(20)); + + m_xPathBox->connect_row_activated( LINK( this, SvxPathTabPage, DoubleClickPathHdl_Impl ) ); + m_xPathBox->connect_changed( LINK( this, SvxPathTabPage, PathSelect_Impl ) ); + m_xPathBox->set_selection_mode(SelectionMode::Multiple); + + xDialogListener->SetDialogClosedLink( LINK( this, SvxPathTabPage, DialogClosedHdl ) ); +} + +SvxPathTabPage::~SvxPathTabPage() +{ + for (int i = 0, nEntryCount = m_xPathBox->n_children(); i < nEntryCount; ++i) + delete reinterpret_cast(m_xPathBox->get_id(i).toInt64()); +} + +std::unique_ptr SvxPathTabPage::Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet ) +{ + return std::make_unique( pPage, pController, *rAttrSet ); +} + +bool SvxPathTabPage::FillItemSet( SfxItemSet* ) +{ + for (int i = 0, nEntryCount = m_xPathBox->n_children(); i < nEntryCount; ++i) + { + PathUserData_Impl* pPathImpl = reinterpret_cast(m_xPathBox->get_id(i).toInt64()); + sal_uInt16 nRealId = pPathImpl->nRealId; + if (pPathImpl->eState == SfxItemState::SET) + SetPathList( nRealId, pPathImpl->sUserPath, pPathImpl->sWritablePath ); + } + return true; +} + +void SvxPathTabPage::Reset( const SfxItemSet* ) +{ + m_xPathBox->clear(); + + std::unique_ptr xIter = m_xPathBox->make_iterator(); + for( sal_uInt16 i = 0; i <= sal_uInt16(SvtPathOptions::PATH_CLASSIFICATION); ++i ) + { + // only writer uses autotext + if ( i == SvtPathOptions::PATH_AUTOTEXT + && !SvtModuleOptions().IsModuleInstalled( SvtModuleOptions::EModule::WRITER ) ) + continue; + + const char* pId = nullptr; + + switch (i) + { + case SvtPathOptions::PATH_AUTOCORRECT: + pId = RID_SVXSTR_KEY_AUTOCORRECT_DIR; + break; + case SvtPathOptions::PATH_AUTOTEXT: + pId = RID_SVXSTR_KEY_GLOSSARY_PATH; + break; + case SvtPathOptions::PATH_BACKUP: + pId = RID_SVXSTR_KEY_BACKUP_PATH; + break; + case SvtPathOptions::PATH_GALLERY: + pId = RID_SVXSTR_KEY_GALLERY_DIR; + break; + case SvtPathOptions::PATH_GRAPHIC: + pId = RID_SVXSTR_KEY_GRAPHICS_PATH; + break; + case SvtPathOptions::PATH_TEMP: + pId = RID_SVXSTR_KEY_TEMP_PATH; + break; + case SvtPathOptions::PATH_TEMPLATE: + pId = RID_SVXSTR_KEY_TEMPLATE_PATH; + break; + case SvtPathOptions::PATH_DICTIONARY: + pId = RID_SVXSTR_KEY_DICTIONARY_PATH; + break; + case SvtPathOptions::PATH_CLASSIFICATION: + pId = RID_SVXSTR_KEY_CLASSIFICATION_PATH; + break; +#if OSL_DEBUG_LEVEL > 1 + case SvtPathOptions::PATH_LINGUISTIC: + pId = RID_SVXSTR_KEY_LINGUISTIC_DIR; + break; +#endif + case SvtPathOptions::PATH_WORK: + pId = RID_SVXSTR_KEY_WORK_PATH; + break; + } + + if (pId) + { + m_xPathBox->append(xIter.get()); + + OUString aStr(CuiResId(pId)); + m_xPathBox->set_text(*xIter, aStr, 0); + + OUString sInternal, sUser, sWritable; + bool bReadOnly = false; + GetPathList( i, sInternal, sUser, sWritable, bReadOnly ); + + if (bReadOnly) + m_xPathBox->set_image(*xIter, RID_SVXBMP_LOCK); + + OUString sTmpPath = sUser; + if ( !sTmpPath.isEmpty() && !sWritable.isEmpty() ) + sTmpPath += OUStringChar(MULTIPATH_DELIMITER); + sTmpPath += sWritable; + const OUString aValue = Convert_Impl( sTmpPath ); + + m_xPathBox->set_text(*xIter, aValue, 1); + + const OUString aValueInternal = Convert_Impl( sInternal ); + + m_xPathBox->set_text(*xIter, aValueInternal, 2); + + m_xPathBox->set_sensitive(*xIter, !bReadOnly, 0); + m_xPathBox->set_sensitive(*xIter, !bReadOnly, 1); + m_xPathBox->set_sensitive(*xIter, !bReadOnly, 2); + + PathUserData_Impl* pPathImpl = new PathUserData_Impl(i); + pPathImpl->sUserPath = sUser; + pPathImpl->sWritablePath = sWritable; + pPathImpl->bReadOnly = bReadOnly; + + OUString sId = OUString::number(reinterpret_cast(pPathImpl)); + m_xPathBox->set_id(*xIter, sId); + } + } + + m_xPathBox->columns_autosize(); + PathSelect_Impl(*m_xPathBox); +} + +IMPL_LINK_NOARG(SvxPathTabPage, PathSelect_Impl, weld::TreeView&, void) +{ + bool bEnable = false; + int nEntry = m_xPathBox->get_selected_index(); + if (nEntry != -1) + { + PathUserData_Impl* pPathImpl = reinterpret_cast(m_xPathBox->get_id(nEntry).toInt64()); + bEnable = !pPathImpl->bReadOnly; + } + sal_uInt16 nSelCount = m_xPathBox->count_selected_rows(); + m_xPathBtn->set_sensitive(1 == nSelCount && bEnable); + m_xStandardBtn->set_sensitive(nSelCount > 0 && bEnable); +} + +IMPL_LINK_NOARG(SvxPathTabPage, StandardHdl_Impl, weld::Button&, void) +{ + m_xPathBox->selected_foreach([this](weld::TreeIter& rEntry){ + PathUserData_Impl* pPathImpl = reinterpret_cast(m_xPathBox->get_id(rEntry).toInt64()); + OUString aOldPath = pImpl->m_aDefOpt.GetDefaultPath( pPathImpl->nRealId ); + + if ( !aOldPath.isEmpty() ) + { + OUString sInternal, sUser, sWritable, sTemp; + bool bReadOnly = false; + GetPathList( pPathImpl->nRealId, sInternal, sUser, sWritable, bReadOnly ); + + sal_Int32 nOldPos = 0; + do + { + bool bFound = false; + const OUString sOnePath = aOldPath.getToken( 0, MULTIPATH_DELIMITER, nOldPos ); + if ( !sInternal.isEmpty() ) + { + sal_Int32 nInternalPos = 0; + do + { + if ( sInternal.getToken( 0, MULTIPATH_DELIMITER, nInternalPos ) == sOnePath ) + bFound = true; + } + while ( !bFound && nInternalPos >= 0 ); + } + if ( !bFound ) + { + if ( !sTemp.isEmpty() ) + sTemp += OUStringChar(MULTIPATH_DELIMITER); + sTemp += sOnePath; + } + } + while ( nOldPos >= 0 ); + + OUString sWritablePath; + OUStringBuffer sUserPath; + if ( !sTemp.isEmpty() ) + { + sal_Int32 nNextPos = 0; + for (;;) + { + const OUString sToken = sTemp.getToken( 0, MULTIPATH_DELIMITER, nNextPos ); + if ( nNextPos<0 ) + { + // Last token need a different handling + sWritablePath = sToken; + break; + } + if ( !sUserPath.isEmpty() ) + sUserPath.append(MULTIPATH_DELIMITER); + sUserPath.append(sToken); + } + } + m_xPathBox->set_text(rEntry, Convert_Impl(sTemp), 1); + pPathImpl->eState = SfxItemState::SET; + pPathImpl->sUserPath = sUserPath.makeStringAndClear(); + pPathImpl->sWritablePath = sWritablePath; + } + return false; + }); +} + +void SvxPathTabPage::ChangeCurrentEntry( const OUString& _rFolder ) +{ + int nEntry = m_xPathBox->get_cursor_index(); + if (nEntry == -1) + { + SAL_WARN( "cui.options", "SvxPathTabPage::ChangeCurrentEntry(): no entry" ); + return; + } + + OUString sInternal, sUser, sWritable; + PathUserData_Impl* pPathImpl = reinterpret_cast(m_xPathBox->get_id(nEntry).toInt64()); + bool bReadOnly = false; + GetPathList( pPathImpl->nRealId, sInternal, sUser, sWritable, bReadOnly ); + sUser = pPathImpl->sUserPath; + sWritable = pPathImpl->sWritablePath; + + // old path is a URL? + INetURLObject aObj( sWritable ); + bool bURL = ( aObj.GetProtocol() != INetProtocol::NotValid ); + INetURLObject aNewObj( _rFolder ); + aNewObj.removeFinalSlash(); + + // then the new path also a URL else system path + OUString sNewPathStr = bURL ? _rFolder : aNewObj.getFSysPath( FSysStyle::Detect ); + + bool bChanged = +#ifdef UNX +// Unix is case sensitive + ( sNewPathStr != sWritable ); +#else + !sNewPathStr.equalsIgnoreAsciiCase( sWritable ); +#endif + + if ( !bChanged ) + return; + + m_xPathBox->set_text(nEntry, Convert_Impl(sNewPathStr), 1); + pPathImpl->eState = SfxItemState::SET; + pPathImpl->sWritablePath = sNewPathStr; + if ( SvtPathOptions::PATH_WORK == pPathImpl->nRealId ) + { + // Remove view options entry so the new work path + // will be used for the next open dialog. + SvtViewOptions aDlgOpt( EViewType::Dialog, IODLG_CONFIGNAME ); + aDlgOpt.Delete(); + // Reset also last used dir in the sfx application instance + SfxApplication *pSfxApp = SfxGetpApp(); + pSfxApp->ResetLastDir(); + } +} + +IMPL_LINK_NOARG(SvxPathTabPage, DoubleClickPathHdl_Impl, weld::TreeView&, bool) +{ + PathHdl_Impl(*m_xPathBtn); + return true; +} + +IMPL_LINK_NOARG(SvxPathTabPage, PathHdl_Impl, weld::Button&, void) +{ + int nEntry = m_xPathBox->get_cursor_index(); + PathUserData_Impl* pPathImpl = nEntry != -1 ? reinterpret_cast(m_xPathBox->get_id(nEntry).toInt64()) : nullptr; + if (!pPathImpl || pPathImpl->bReadOnly) + return; + + sal_uInt16 nPos = pPathImpl->nRealId; + OUString sInternal, sUser, sWritable; + bool bPickFile = false; + bool bReadOnly = false; + GetPathList( pPathImpl->nRealId, sInternal, sUser, sWritable, bReadOnly ); + sUser = pPathImpl->sUserPath; + sWritable = pPathImpl->sWritablePath; + bPickFile = pPathImpl->nRealId == SvtPathOptions::PATH_CLASSIFICATION; + + if (IsMultiPath_Impl(nPos)) + { + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr pMultiDlg( + pFact->CreateSvxMultiPathDialog(GetFrameWeld())); + + OUString sPath( sUser ); + if ( !sPath.isEmpty() ) + sPath += OUStringChar(MULTIPATH_DELIMITER); + sPath += sWritable; + pMultiDlg->SetPath( sPath ); + + const OUString sPathName = m_xPathBox->get_text(nEntry, 0); + const OUString sNewTitle = pImpl->m_sMultiPathDlg.replaceFirst( VAR_ONE, sPathName ); + pMultiDlg->SetTitle( sNewTitle ); + + if (pMultiDlg->Execute() == RET_OK) + { + sUser.clear(); + sWritable.clear(); + OUString sFullPath; + OUString sNewPath = pMultiDlg->GetPath(); + if ( !sNewPath.isEmpty() ) + { + sal_Int32 nNextPos = 0; + for (;;) + { + const OUString sToken(sNewPath.getToken( 0, MULTIPATH_DELIMITER, nNextPos )); + if ( nNextPos<0 ) + { + // Last token need a different handling + sWritable = sToken; + break; + } + if ( !sUser.isEmpty() ) + sUser += OUStringChar(MULTIPATH_DELIMITER); + sUser += sToken; + } + sFullPath = sUser; + if ( !sFullPath.isEmpty() ) + sFullPath += OUStringChar(MULTIPATH_DELIMITER); + sFullPath += sWritable; + } + + m_xPathBox->set_text(nEntry, Convert_Impl(sFullPath), 1); + // save modified flag + pPathImpl->eState = SfxItemState::SET; + pPathImpl->sUserPath = sUser; + pPathImpl->sWritablePath = sWritable; + } + } + else if (!bPickFile) + { + try + { + Reference < XComponentContext > xContext( ::comphelper::getProcessComponentContext() ); + xFolderPicker = FolderPicker::create(xContext); + + INetURLObject aURL( sWritable, INetProtocol::File ); + xFolderPicker->setDisplayDirectory( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); + + Reference< XAsynchronousExecutableDialog > xAsyncDlg( xFolderPicker, UNO_QUERY ); + if ( xAsyncDlg.is() ) + xAsyncDlg->startExecuteModal( xDialogListener.get() ); + else + { + short nRet = xFolderPicker->execute(); + if (ExecutableDialogResults::OK != nRet) + return; + + OUString sFolder(xFolderPicker->getDirectory()); + ChangeCurrentEntry(sFolder); + } + } + catch( Exception const & ) + { + TOOLS_WARN_EXCEPTION( "cui.options", "SvxPathTabPage::PathHdl_Impl: exception from folder picker" ); + } + } + else + { + try + { + uno::Reference xComponentContext(comphelper::getProcessComponentContext()); + uno::Reference xFilePicker = ui::dialogs::FilePicker::createWithMode(xComponentContext, ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE); + xFilePicker->appendFilter(OUString(), "*.xml"); + if (xFilePicker->execute() == ui::dialogs::ExecutableDialogResults::OK) + { + uno::Sequence aPathSeq(xFilePicker->getSelectedFiles()); + ChangeCurrentEntry(aPathSeq[0]); + } + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("cui.options", "exception from file picker"); + } + } +} + +IMPL_LINK( SvxPathTabPage, DialogClosedHdl, DialogClosedEvent*, pEvt, void ) +{ + if (RET_OK == pEvt->DialogResult) + { + assert(xFolderPicker.is() && "SvxPathTabPage::DialogClosedHdl(): no folder picker"); + OUString sURL = xFolderPicker->getDirectory(); + ChangeCurrentEntry( sURL ); + } +} + +void SvxPathTabPage::GetPathList( + sal_uInt16 _nPathHandle, OUString& _rInternalPath, + OUString& _rUserPath, OUString& _rWritablePath, bool& _rReadOnly ) +{ + OUString sCfgName = getCfgName_Impl( _nPathHandle ); + + try + { + // load PathSettings service if necessary + if ( !pImpl->m_xPathSettings.is() ) + { + Reference< XComponentContext > xContext = comphelper::getProcessComponentContext(); + pImpl->m_xPathSettings = css::util::thePathSettings::get( xContext ); + } + + // load internal paths + Any aAny = pImpl->m_xPathSettings->getPropertyValue( + sCfgName + POSTFIX_INTERNAL); + Sequence< OUString > aPathSeq; + if ( aAny >>= aPathSeq ) + { + long i, nCount = aPathSeq.getLength(); + const OUString* pPaths = aPathSeq.getConstArray(); + + for ( i = 0; i < nCount; ++i ) + { + if ( !_rInternalPath.isEmpty() ) + _rInternalPath += ";"; + _rInternalPath += pPaths[i]; + } + } + // load user paths + aAny = pImpl->m_xPathSettings->getPropertyValue( + sCfgName + POSTFIX_USER); + if ( aAny >>= aPathSeq ) + { + long i, nCount = aPathSeq.getLength(); + const OUString* pPaths = aPathSeq.getConstArray(); + + for ( i = 0; i < nCount; ++i ) + { + if ( !_rUserPath.isEmpty() ) + _rUserPath += ";"; + _rUserPath += pPaths[i]; + } + } + // then the writable path + aAny = pImpl->m_xPathSettings->getPropertyValue( + sCfgName + POSTFIX_WRITABLE); + OUString sWritablePath; + if ( aAny >>= sWritablePath ) + _rWritablePath = sWritablePath; + + // and the readonly flag + Reference< XPropertySetInfo > xInfo = pImpl->m_xPathSettings->getPropertySetInfo(); + Property aProp = xInfo->getPropertyByName(sCfgName); + _rReadOnly = ( ( aProp.Attributes & PropertyAttribute::READONLY ) == PropertyAttribute::READONLY ); + } + catch( const Exception& ) + { + TOOLS_WARN_EXCEPTION( "cui.options", "SvxPathTabPage::GetPathList()" ); + } +} + + +void SvxPathTabPage::SetPathList( + sal_uInt16 _nPathHandle, const OUString& _rUserPath, const OUString& _rWritablePath ) +{ + OUString sCfgName = getCfgName_Impl( _nPathHandle ); + + try + { + // load PathSettings service if necessary + if ( !pImpl->m_xPathSettings.is() ) + { + Reference< XComponentContext > xContext = comphelper::getProcessComponentContext(); + pImpl->m_xPathSettings = css::util::thePathSettings::get( xContext ); + } + + // save user paths + const sal_Int32 nCount = comphelper::string::getTokenCount(_rUserPath, MULTIPATH_DELIMITER); + Sequence< OUString > aPathSeq( nCount ); + OUString* pArray = aPathSeq.getArray(); + sal_Int32 nPos = 0; + for ( sal_Int32 i = 0; i < nCount; ++i ) + pArray[i] = _rUserPath.getToken( 0, MULTIPATH_DELIMITER, nPos ); + Any aValue( aPathSeq ); + pImpl->m_xPathSettings->setPropertyValue( + sCfgName + POSTFIX_USER, aValue); + + // then the writable path + aValue <<= _rWritablePath; + pImpl->m_xPathSettings->setPropertyValue( + sCfgName + POSTFIX_WRITABLE, aValue); + } + catch( const Exception& ) + { + TOOLS_WARN_EXCEPTION("cui.options", ""); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/optsave.cxx b/cui/source/options/optsave.cxx new file mode 100644 index 000000000..564fabb73 --- /dev/null +++ b/cui/source/options/optsave.cxx @@ -0,0 +1,619 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include "optsave.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace com::sun::star::uno; +using namespace com::sun::star::util; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; +using namespace com::sun::star::container; +using namespace comphelper; + +#define CFG_PAGE_AND_GROUP "General", "LoadSave" + + +struct SvxSaveTabPage_Impl +{ + Reference< XNameContainer > xFact; + std::vector< OUString > aFilterArr[APP_COUNT]; + std::vector< bool > aODFArr[APP_COUNT]; + std::vector< OUString > aUIFilterArr[APP_COUNT]; + OUString aDefaultArr[APP_COUNT]; + bool aDefaultReadonlyArr[APP_COUNT]; + bool bInitialized; + + SvxSaveTabPage_Impl(); +}; + +SvxSaveTabPage_Impl::SvxSaveTabPage_Impl() : bInitialized( false ) +{ +} + +// class SvxSaveTabPage -------------------------------------------------- + +SvxSaveTabPage::SvxSaveTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreSet) + : SfxTabPage( pPage, pController, "cui/ui/optsavepage.ui", "OptSavePage", &rCoreSet ) + , pImpl(new SvxSaveTabPage_Impl) + , m_xLoadUserSettingsCB(m_xBuilder->weld_check_button("load_settings")) + , m_xLoadDocPrinterCB(m_xBuilder->weld_check_button("load_docprinter")) + , m_xDocInfoCB(m_xBuilder->weld_check_button("docinfo")) + , m_xBackupCB(m_xBuilder->weld_check_button("backup")) + , m_xAutoSaveCB(m_xBuilder->weld_check_button("autosave")) + , m_xAutoSaveEdit(m_xBuilder->weld_spin_button("autosave_spin")) + , m_xMinuteFT(m_xBuilder->weld_label("autosave_mins")) + , m_xUserAutoSaveCB(m_xBuilder->weld_check_button("userautosave")) + , m_xRelativeFsysCB(m_xBuilder->weld_check_button("relative_fsys")) + , m_xRelativeInetCB(m_xBuilder->weld_check_button("relative_inet")) + , m_xODFVersionLB(m_xBuilder->weld_combo_box("odfversion")) + , m_xWarnAlienFormatCB(m_xBuilder->weld_check_button("warnalienformat")) + , m_xDocTypeLB(m_xBuilder->weld_combo_box("doctype")) + , m_xSaveAsFT(m_xBuilder->weld_label("saveas_label")) + , m_xSaveAsLB(m_xBuilder->weld_combo_box("saveas")) + , m_xODFWarningFI(m_xBuilder->weld_widget("odfwarning_image")) + , m_xODFWarningFT(m_xBuilder->weld_label("odfwarning_label")) +{ + m_xODFVersionLB->set_id(0, OUString::number(SvtSaveOptions::ODFVER_011)); // 1.0/1.1 + m_xODFVersionLB->set_id(1, OUString::number(SvtSaveOptions::ODFVER_012)); // 1.2 + m_xODFVersionLB->set_id(2, OUString::number(SvtSaveOptions::ODFVER_012_EXT_COMPAT)); // 1.2 Extended (compatibility mode) + m_xODFVersionLB->set_id(3, OUString::number(SvtSaveOptions::ODFVER_012_EXTENDED)); // 1.2 Extended + m_xODFVersionLB->set_id(4, OUString::number(SvtSaveOptions::ODFVER_013)); // 1.3 + m_xODFVersionLB->set_id(5, OUString::number(SvtSaveOptions::ODFVER_LATEST)); // 1.3 Extended (recommended) + + m_xDocTypeLB->set_id(0, OUString::number(APP_WRITER) ); + m_xDocTypeLB->set_id(1, OUString::number(APP_WRITER_WEB) ); + m_xDocTypeLB->set_id(2, OUString::number(APP_WRITER_GLOBAL)); + m_xDocTypeLB->set_id(3, OUString::number(APP_CALC) ); + m_xDocTypeLB->set_id(4, OUString::number(APP_IMPRESS) ); + m_xDocTypeLB->set_id(5, OUString::number(APP_DRAW) ); + m_xDocTypeLB->set_id(6, OUString::number(APP_MATH) ); + + m_xAutoSaveCB->connect_clicked( LINK( this, SvxSaveTabPage, AutoClickHdl_Impl ) ); + + SvtModuleOptions aModuleOpt; + if ( !aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::MATH ) ) + { + m_xSaveAsLB->remove_id(OUString::number(APP_MATH)); + m_xDocTypeLB->remove_id(OUString::number(APP_MATH)); + } + else + { + pImpl->aDefaultArr[APP_MATH] = aModuleOpt.GetFactoryDefaultFilter(SvtModuleOptions::EFactory::MATH); + pImpl->aDefaultReadonlyArr[APP_MATH] = aModuleOpt.IsDefaultFilterReadonly(SvtModuleOptions::EFactory::MATH); + } + + if ( !aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::DRAW ) ) + { + m_xSaveAsLB->remove_id(OUString::number(APP_DRAW)); + m_xDocTypeLB->remove_id(OUString::number(APP_DRAW)); + } + else + { + pImpl->aDefaultArr[APP_DRAW] = aModuleOpt.GetFactoryDefaultFilter(SvtModuleOptions::EFactory::DRAW); + pImpl->aDefaultReadonlyArr[APP_DRAW] = aModuleOpt.IsDefaultFilterReadonly(SvtModuleOptions::EFactory::DRAW); + } + + if ( !aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::IMPRESS ) ) + { + m_xSaveAsLB->remove_id(OUString::number(APP_IMPRESS)); + m_xDocTypeLB->remove_id(OUString::number(APP_IMPRESS)); + } + else + { + pImpl->aDefaultArr[APP_IMPRESS] = aModuleOpt.GetFactoryDefaultFilter(SvtModuleOptions::EFactory::IMPRESS); + pImpl->aDefaultReadonlyArr[APP_IMPRESS] = aModuleOpt.IsDefaultFilterReadonly(SvtModuleOptions::EFactory::IMPRESS); + } + + if ( !aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::CALC ) ) + { + m_xSaveAsLB->remove_id(OUString::number(APP_CALC)); + m_xDocTypeLB->remove_id(OUString::number(APP_CALC)); + } + else + { + pImpl->aDefaultArr[APP_CALC] = aModuleOpt.GetFactoryDefaultFilter(SvtModuleOptions::EFactory::CALC); + pImpl->aDefaultReadonlyArr[APP_CALC] = aModuleOpt.IsDefaultFilterReadonly(SvtModuleOptions::EFactory::CALC); + } + + if ( !aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::WRITER ) ) + { + m_xSaveAsLB->remove_id(OUString::number(APP_WRITER)); + m_xSaveAsLB->remove_id(OUString::number(APP_WRITER_WEB)); + m_xSaveAsLB->remove_id(OUString::number(APP_WRITER_GLOBAL)); + m_xDocTypeLB->remove_id(OUString::number(APP_WRITER)); + m_xDocTypeLB->remove_id(OUString::number(APP_WRITER_WEB)); + m_xDocTypeLB->remove_id(OUString::number(APP_WRITER_GLOBAL)); + } + else + { + pImpl->aDefaultArr[APP_WRITER] = aModuleOpt.GetFactoryDefaultFilter(SvtModuleOptions::EFactory::WRITER); + pImpl->aDefaultArr[APP_WRITER_WEB] = aModuleOpt.GetFactoryDefaultFilter(SvtModuleOptions::EFactory::WRITERWEB); + pImpl->aDefaultArr[APP_WRITER_GLOBAL] = aModuleOpt.GetFactoryDefaultFilter(SvtModuleOptions::EFactory::WRITERGLOBAL); + pImpl->aDefaultReadonlyArr[APP_WRITER] = aModuleOpt.IsDefaultFilterReadonly(SvtModuleOptions::EFactory::WRITER); + pImpl->aDefaultReadonlyArr[APP_WRITER_WEB] = aModuleOpt.IsDefaultFilterReadonly(SvtModuleOptions::EFactory::WRITERWEB); + pImpl->aDefaultReadonlyArr[APP_WRITER_GLOBAL] = aModuleOpt.IsDefaultFilterReadonly(SvtModuleOptions::EFactory::WRITERGLOBAL); + } + + Link aLink = LINK( this, SvxSaveTabPage, ODFVersionHdl_Impl ); + m_xODFVersionLB->connect_changed( aLink ); + aLink = LINK( this, SvxSaveTabPage, FilterHdl_Impl ); + m_xDocTypeLB->connect_changed( aLink ); + m_xSaveAsLB->connect_changed( aLink ); + + DetectHiddenControls(); +} + +SvxSaveTabPage::~SvxSaveTabPage() +{ +} + +std::unique_ptr SvxSaveTabPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet) +{ + return std::make_unique(pPage, pController, *rAttrSet); +} + +void SvxSaveTabPage::DetectHiddenControls() +{ + SvtOptionsDialogOptions aOptionsDlgOpt; + + if ( aOptionsDlgOpt.IsOptionHidden( "Backup", CFG_PAGE_AND_GROUP ) ) + { + // hide controls of "Backup" + m_xBackupCB->hide(); + } + + if ( aOptionsDlgOpt.IsOptionHidden( "AutoSave", CFG_PAGE_AND_GROUP ) ) + { + // hide controls of "AutoSave" + m_xAutoSaveCB->hide(); + m_xAutoSaveEdit->hide(); + m_xMinuteFT->hide(); + } + + if ( aOptionsDlgOpt.IsOptionHidden( "UserAutoSave", CFG_PAGE_AND_GROUP ) ) + { + // hide controls of "UserAutoSave" + m_xUserAutoSaveCB->hide(); + } + +} + +bool SvxSaveTabPage::FillItemSet( SfxItemSet* rSet ) +{ + bool bModified = false; + SvtSaveOptions aSaveOpt; + if(m_xLoadUserSettingsCB->get_state_changed_from_saved()) + { + aSaveOpt.SetLoadUserSettings(m_xLoadUserSettingsCB->get_active()); + } + + if ( m_xLoadDocPrinterCB->get_state_changed_from_saved() ) + aSaveOpt.SetLoadDocumentPrinter( m_xLoadDocPrinterCB->get_active() ); + + if ( m_xODFVersionLB->get_value_changed_from_saved() ) + { + sal_Int32 nVersion = m_xODFVersionLB->get_active_id().toInt32(); + aSaveOpt.SetODFDefaultVersion( SvtSaveOptions::ODFDefaultVersion( nVersion ) ); + } + + if ( m_xDocInfoCB->get_state_changed_from_saved() ) + { + rSet->Put( SfxBoolItem( GetWhich( SID_ATTR_DOCINFO ), + m_xDocInfoCB->get_active() ) ); + bModified = true; + } + + if ( m_xBackupCB->get_sensitive() && m_xBackupCB->get_state_changed_from_saved() ) + { + rSet->Put( SfxBoolItem( GetWhich( SID_ATTR_BACKUP ), + m_xBackupCB->get_active() ) ); + bModified = true; + } + + if ( m_xAutoSaveCB->get_state_changed_from_saved() ) + { + rSet->Put( SfxBoolItem( GetWhich( SID_ATTR_AUTOSAVE ), + m_xAutoSaveCB->get_active() ) ); + bModified = true; + } + if ( m_xWarnAlienFormatCB->get_state_changed_from_saved() ) + { + rSet->Put( SfxBoolItem( GetWhich( SID_ATTR_WARNALIENFORMAT ), + m_xWarnAlienFormatCB->get_active() ) ); + bModified = true; + } + + if ( m_xAutoSaveEdit->get_value_changed_from_saved() ) + { + rSet->Put( SfxUInt16Item( GetWhich( SID_ATTR_AUTOSAVEMINUTE ), + static_cast(m_xAutoSaveEdit->get_value()) ) ); + bModified = true; + } + + if ( m_xUserAutoSaveCB->get_state_changed_from_saved() ) + { + rSet->Put( SfxBoolItem( GetWhich( SID_ATTR_USERAUTOSAVE ), + m_xUserAutoSaveCB->get_active() ) ); + bModified = true; + } + // save relatively + if ( m_xRelativeFsysCB->get_state_changed_from_saved() ) + { + rSet->Put( SfxBoolItem( GetWhich( SID_SAVEREL_FSYS ), + m_xRelativeFsysCB->get_active() ) ); + bModified = true; + } + + if ( m_xRelativeInetCB->get_state_changed_from_saved() ) + { + rSet->Put( SfxBoolItem( GetWhich( SID_SAVEREL_INET ), + m_xRelativeInetCB->get_active() ) ); + bModified = true; + } + + SvtModuleOptions aModuleOpt; + if(!pImpl->aDefaultArr[APP_MATH].isEmpty() && + pImpl->aDefaultArr[APP_MATH] != aModuleOpt.GetFactoryDefaultFilter(SvtModuleOptions::EFactory::MATH)) + aModuleOpt.SetFactoryDefaultFilter(SvtModuleOptions::EFactory::MATH, pImpl->aDefaultArr[APP_MATH]); + + if( !pImpl->aDefaultArr[APP_DRAW].isEmpty() && + pImpl->aDefaultArr[APP_DRAW] != aModuleOpt.GetFactoryDefaultFilter(SvtModuleOptions::EFactory::DRAW)) + aModuleOpt.SetFactoryDefaultFilter(SvtModuleOptions::EFactory::DRAW, pImpl->aDefaultArr[APP_DRAW]); + + if(!pImpl->aDefaultArr[APP_IMPRESS].isEmpty() && + pImpl->aDefaultArr[APP_IMPRESS] != aModuleOpt.GetFactoryDefaultFilter(SvtModuleOptions::EFactory::IMPRESS)) + aModuleOpt.SetFactoryDefaultFilter(SvtModuleOptions::EFactory::IMPRESS, pImpl->aDefaultArr[APP_IMPRESS]); + + if(!pImpl->aDefaultArr[APP_CALC].isEmpty() && + pImpl->aDefaultArr[APP_CALC] != aModuleOpt.GetFactoryDefaultFilter(SvtModuleOptions::EFactory::CALC)) + aModuleOpt.SetFactoryDefaultFilter(SvtModuleOptions::EFactory::CALC, pImpl->aDefaultArr[APP_CALC]); + + if(!pImpl->aDefaultArr[APP_WRITER].isEmpty() && + pImpl->aDefaultArr[APP_WRITER] != aModuleOpt.GetFactoryDefaultFilter(SvtModuleOptions::EFactory::WRITER)) + aModuleOpt.SetFactoryDefaultFilter(SvtModuleOptions::EFactory::WRITER, pImpl->aDefaultArr[APP_WRITER]); + + if(!pImpl->aDefaultArr[APP_WRITER_WEB].isEmpty() && + pImpl->aDefaultArr[APP_WRITER_WEB] != aModuleOpt.GetFactoryDefaultFilter(SvtModuleOptions::EFactory::WRITERWEB)) + aModuleOpt.SetFactoryDefaultFilter(SvtModuleOptions::EFactory::WRITERWEB, pImpl->aDefaultArr[APP_WRITER_WEB]); + + if(!pImpl->aDefaultArr[APP_WRITER_GLOBAL].isEmpty() && + pImpl->aDefaultArr[APP_WRITER_GLOBAL] != aModuleOpt.GetFactoryDefaultFilter(SvtModuleOptions::EFactory::WRITERGLOBAL)) + aModuleOpt.SetFactoryDefaultFilter(SvtModuleOptions::EFactory::WRITERGLOBAL, pImpl->aDefaultArr[APP_WRITER_GLOBAL]); + + return bModified; +} + +static bool isODFFormat( const OUString& sFilter ) +{ + static const char* aODFFormats[] = + { + "writer8", + "writer8_template", + "writerglobal8", + "writerglobal8_writer", + "calc8", + "calc8_template", + "draw8", + "draw8_template", + "impress8", + "impress8_template", + "impress8_draw", + "chart8", + "math8", + nullptr + }; + + bool bRet = false; + int i = 0; + while ( aODFFormats[i] != nullptr ) + { + if ( sFilter.equalsAscii( aODFFormats[i++] ) ) + { + bRet = true; + break; + } + } + + return bRet; +} + +void SvxSaveTabPage::Reset( const SfxItemSet* ) +{ + SvtSaveOptions aSaveOpt; + m_xLoadUserSettingsCB->set_active(aSaveOpt.IsLoadUserSettings()); + m_xLoadUserSettingsCB->save_state(); + m_xLoadUserSettingsCB->set_sensitive(!aSaveOpt.IsReadOnly(SvtSaveOptions::EOption::UseUserData)); + m_xLoadDocPrinterCB->set_active( aSaveOpt.IsLoadDocumentPrinter() ); + m_xLoadDocPrinterCB->save_state(); + m_xLoadDocPrinterCB->set_sensitive(!aSaveOpt.IsReadOnly(SvtSaveOptions::EOption::LoadDocPrinter)); + + if ( !pImpl->bInitialized ) + { + try + { + Reference< XMultiServiceFactory > xMSF = comphelper::getProcessServiceFactory(); + pImpl->xFact.set(xMSF->createInstance("com.sun.star.document.FilterFactory"), UNO_QUERY); + + DBG_ASSERT(pImpl->xFact.is(), "service com.sun.star.document.FilterFactory unavailable"); + Reference< XContainerQuery > xQuery(pImpl->xFact, UNO_QUERY); + if(xQuery.is()) + { + for (sal_Int32 n = 0, nEntryCount = m_xDocTypeLB->get_count(); n < nEntryCount; ++n) + { + int nData = m_xDocTypeLB->get_id(n).toInt32(); + OUString sCommand = "getSortedFilterList():module=%1:iflags=" + + OUString::number(static_cast(SfxFilterFlags::IMPORT|SfxFilterFlags::EXPORT)) + + ":eflags=" + + OUString::number(static_cast(SfxFilterFlags::NOTINFILEDLG)); + OUString sReplace; + switch(nData) + { + case APP_WRITER : sReplace = "com.sun.star.text.TextDocument"; break; + case APP_WRITER_WEB : sReplace = "com.sun.star.text.WebDocument"; break; + case APP_WRITER_GLOBAL : sReplace = "com.sun.star.text.GlobalDocument"; break; + case APP_CALC : sReplace = "com.sun.star.sheet.SpreadsheetDocument";break; + case APP_IMPRESS : sReplace = "com.sun.star.presentation.PresentationDocument";break; + case APP_DRAW : sReplace = "com.sun.star.drawing.DrawingDocument";break; + case APP_MATH : sReplace = "com.sun.star.formula.FormulaProperties";break; + default: OSL_FAIL("illegal user data"); + } + sCommand = sCommand.replaceFirst("%1", sReplace); + Reference< XEnumeration > xList = xQuery->createSubSetEnumerationByQuery(sCommand); + std::vector< OUString > lList; + std::vector lODFList; + while(xList->hasMoreElements()) + { + SequenceAsHashMap aFilter(xList->nextElement()); + OUString sFilter = aFilter.getUnpackedValueOrDefault("Name",OUString()); + if (!sFilter.isEmpty()) + { + lList.push_back(sFilter); + lODFList.push_back( isODFFormat( sFilter ) ); + } + } + pImpl->aFilterArr[nData] = lList; + pImpl->aODFArr[nData] = lODFList; + } + } + m_xDocTypeLB->set_active(0); + FilterHdl_Impl(*m_xDocTypeLB); + } + catch(Exception const &) + { + TOOLS_WARN_EXCEPTION( "cui.options", "exception in FilterFactory access" ); + } + + pImpl->bInitialized = true; + } + + m_xDocInfoCB->set_active(aSaveOpt.IsDocInfoSave()); + m_xDocInfoCB->set_sensitive(!aSaveOpt.IsReadOnly(SvtSaveOptions::EOption::DocInfSave)); + + m_xBackupCB->set_active(aSaveOpt.IsBackup()); + m_xBackupCB->set_sensitive(!aSaveOpt.IsReadOnly(SvtSaveOptions::EOption::Backup)); + + m_xAutoSaveCB->set_active(aSaveOpt.IsAutoSave()); + m_xAutoSaveCB->set_sensitive(!aSaveOpt.IsReadOnly(SvtSaveOptions::EOption::AutoSave)); + + m_xUserAutoSaveCB->set_active(aSaveOpt.IsUserAutoSave()); + m_xUserAutoSaveCB->set_sensitive(!aSaveOpt.IsReadOnly(SvtSaveOptions::EOption::UserAutoSave)); + + m_xWarnAlienFormatCB->set_active(aSaveOpt.IsWarnAlienFormat()); + m_xWarnAlienFormatCB->set_sensitive(!aSaveOpt.IsReadOnly(SvtSaveOptions::EOption::WarnAlienFormat)); + + m_xAutoSaveEdit->set_value(aSaveOpt.GetAutoSaveTime()); + m_xAutoSaveEdit->set_sensitive(!aSaveOpt.IsReadOnly(SvtSaveOptions::EOption::AutoSaveTime)); + + // save relatively + m_xRelativeFsysCB->set_active(aSaveOpt.IsSaveRelFSys()); + m_xRelativeFsysCB->set_sensitive(!aSaveOpt.IsReadOnly(SvtSaveOptions::EOption::SaveRelFsys)); + + m_xRelativeInetCB->set_active(aSaveOpt.IsSaveRelINet()); + m_xRelativeInetCB->set_sensitive(!aSaveOpt.IsReadOnly(SvtSaveOptions::EOption::SaveRelInet)); + + sal_Int32 nDefaultVersion = aSaveOpt.GetODFDefaultVersion(); + m_xODFVersionLB->set_active_id(OUString::number(nDefaultVersion)); + m_xODFVersionLB->set_sensitive(!aSaveOpt.IsReadOnly(SvtSaveOptions::EOption::OdfDefaultVersion)); + + AutoClickHdl_Impl(*m_xAutoSaveCB); + ODFVersionHdl_Impl(*m_xODFVersionLB); + + m_xDocInfoCB->save_state(); + m_xBackupCB->save_state(); + m_xWarnAlienFormatCB->save_state(); + m_xAutoSaveCB->save_state(); + m_xAutoSaveEdit->save_value(); + + m_xUserAutoSaveCB->save_state(); + + m_xRelativeFsysCB->save_state(); + m_xRelativeInetCB->save_state(); + m_xODFVersionLB->save_value(); +} + +IMPL_LINK(SvxSaveTabPage, AutoClickHdl_Impl, weld::Button&, rBox, void) +{ + if (&rBox != m_xAutoSaveCB.get()) + return; + + if (m_xAutoSaveCB->get_active()) + { + m_xAutoSaveEdit->set_sensitive(true); + m_xMinuteFT->set_sensitive(true); + m_xUserAutoSaveCB->set_sensitive(true); + } + else + { + m_xAutoSaveEdit->set_sensitive(false); + m_xMinuteFT->set_sensitive(false); + m_xUserAutoSaveCB->set_sensitive(false); + } +} + +static OUString lcl_ExtracUIName(const Sequence &rProperties, const OUString& rExtension) +{ + OUString sName; + const PropertyValue* pPropVal = rProperties.getConstArray(); + const PropertyValue* const pEnd = pPropVal + rProperties.getLength(); + for( ; pPropVal != pEnd; pPropVal++ ) + { + const OUString &rName = pPropVal->Name; + if (rName == "UIName") + { + OUString sUIName; + if ( ( pPropVal->Value >>= sUIName ) && sUIName.getLength() ) + { + if (!rExtension.isEmpty()) + { + return sUIName + " (" + rExtension + ")"; + } + else + { + return sUIName; + } + } + } + else if (rName == "Name") + { + pPropVal->Value >>= sName; + } + } + + OSL_ENSURE( false, "Filter without UIName!" ); + + return sName; +} + +IMPL_LINK( SvxSaveTabPage, FilterHdl_Impl, weld::ComboBox&, rBox, void ) +{ + const int nCurPos = m_xDocTypeLB->get_active(); + + int nData = -1; + if (nCurPos < APP_COUNT) + nData = m_xDocTypeLB->get_id(nCurPos).toInt32(); + + if ( nData >= 0 && nData < APP_COUNT ) + { + if(m_xDocTypeLB.get() == &rBox) + { + m_xSaveAsLB->clear(); + auto & rFilters = pImpl->aFilterArr[nData]; + if(pImpl->aUIFilterArr[nData].empty()) + { + pImpl->aUIFilterArr[nData].resize(pImpl->aFilterArr[nData].size()); + auto & rUIFilters = pImpl->aUIFilterArr[nData]; + for(size_t nFilter = 0; nFilter < pImpl->aFilterArr[nData].size(); nFilter++) + { + Any aProps = pImpl->xFact->getByName(rFilters[nFilter]); + // get the extension of the filter + OUString extension; + SfxFilterMatcher matcher; + std::shared_ptr pFilter = matcher.GetFilter4FilterName(rFilters[nFilter]); + if (pFilter) + { + extension = pFilter->GetWildcard().getGlob().getToken(0, ';'); + } + Sequence aProperties; + aProps >>= aProperties; + rUIFilters[nFilter] = lcl_ExtracUIName(aProperties, extension); + } + } + auto const & rUIFilters = pImpl->aUIFilterArr[nData]; + OUString sSelect; + for(size_t i = 0; i < pImpl->aUIFilterArr[nData].size(); i++) + { + OUString sId; + if (pImpl->aODFArr[nData][i]) + sId = OUString::number(reinterpret_cast(pImpl.get())); + m_xSaveAsLB->append(sId, rUIFilters[i]); + if (rFilters[i] == pImpl->aDefaultArr[nData]) + sSelect = rUIFilters[i]; + } + if (!sSelect.isEmpty()) + { + m_xSaveAsLB->set_active_text(sSelect); + } + + m_xSaveAsFT->set_sensitive(!pImpl->aDefaultReadonlyArr[nData]); + m_xSaveAsLB->set_sensitive(!pImpl->aDefaultReadonlyArr[nData]); + } + else + { + OUString sSelect = rBox.get_active_text(); + auto const & rFilters = pImpl->aFilterArr[nData]; + auto const & rUIFilters = pImpl->aUIFilterArr[nData]; + for(size_t i = 0; i < pImpl->aUIFilterArr[nData].size(); i++) + if(rUIFilters[i] == sSelect) + { + sSelect = rFilters[i]; + break; + } + + pImpl->aDefaultArr[nData] = sSelect; + } + } + + ODFVersionHdl_Impl( *m_xSaveAsLB ); +} + +IMPL_LINK_NOARG(SvxSaveTabPage, ODFVersionHdl_Impl, weld::ComboBox&, void) +{ + sal_Int32 nVersion = m_xODFVersionLB->get_active_id().toInt32(); + bool bShown = SvtSaveOptions::ODFDefaultVersion(nVersion) != SvtSaveOptions::ODFVER_LATEST; + if ( bShown ) + { + bool bHasODFFormat = false; + const int nCount = m_xSaveAsLB->get_count(); + for (int i = 0; i < nCount; ++i ) + { + if ( m_xSaveAsLB->get_id(i).toInt64() != 0 ) + { + bHasODFFormat = true; + break; + } + } + + bShown = !bHasODFFormat + || ( m_xSaveAsLB->get_active_id().toInt64() != 0); + } + + m_xODFWarningFI->set_visible(bShown); + m_xODFWarningFT->set_visible(bShown); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/optsave.hxx b/cui/source/options/optsave.hxx new file mode 100644 index 000000000..f916963e4 --- /dev/null +++ b/cui/source/options/optsave.hxx @@ -0,0 +1,78 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include +#include + +#define APP_WRITER 0 +#define APP_WRITER_WEB 1 +#define APP_WRITER_GLOBAL 2 +#define APP_CALC 3 +#define APP_IMPRESS 4 +#define APP_DRAW 5 +#define APP_MATH 6 +#define APP_COUNT 7 + +namespace com::sun::star::beans { struct PropertyValue; } + +// class SvxSaveTabPage -------------------------------------------------- + +struct SvxSaveTabPage_Impl; + +class SvxSaveTabPage : public SfxTabPage +{ +private: + std::unique_ptr pImpl; + + std::unique_ptr m_xLoadUserSettingsCB; + std::unique_ptr m_xLoadDocPrinterCB; + std::unique_ptr m_xDocInfoCB; + std::unique_ptr m_xBackupCB; + std::unique_ptr m_xAutoSaveCB; + std::unique_ptr m_xAutoSaveEdit; + std::unique_ptr m_xMinuteFT; + std::unique_ptr m_xUserAutoSaveCB; + std::unique_ptr m_xRelativeFsysCB; + std::unique_ptr m_xRelativeInetCB; + std::unique_ptr m_xODFVersionLB; + std::unique_ptr m_xWarnAlienFormatCB; + std::unique_ptr m_xDocTypeLB; + std::unique_ptr m_xSaveAsFT; + std::unique_ptr m_xSaveAsLB; + std::unique_ptr m_xODFWarningFI; + std::unique_ptr m_xODFWarningFT; + + DECL_LINK( AutoClickHdl_Impl, weld::Button&, void ); + DECL_LINK( FilterHdl_Impl, weld::ComboBox&, void ); + DECL_LINK(ODFVersionHdl_Impl, weld::ComboBox&, void ); + + void DetectHiddenControls(); + +public: + SvxSaveTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + virtual ~SvxSaveTabPage() override; + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet ); + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/optupdt.cxx b/cui/source/options/optupdt.cxx new file mode 100644 index 000000000..2f39687cc --- /dev/null +++ b/cui/source/options/optupdt.cxx @@ -0,0 +1,396 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include "optupdt.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace ::css; + +SvxOnlineUpdateTabPage::SvxOnlineUpdateTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/optonlineupdatepage.ui", "OptOnlineUpdatePage", &rSet) + , m_xNeverChecked(m_xBuilder->weld_label("neverchecked")) + , m_xAutoCheckCheckBox(m_xBuilder->weld_check_button("autocheck")) + , m_xEveryDayButton(m_xBuilder->weld_radio_button("everyday")) + , m_xEveryWeekButton(m_xBuilder->weld_radio_button("everyweek")) + , m_xEveryMonthButton(m_xBuilder->weld_radio_button("everymonth")) + , m_xCheckNowButton(m_xBuilder->weld_button("checknow")) + , m_xAutoDownloadCheckBox(m_xBuilder->weld_check_button("autodownload")) + , m_xDestPathLabel(m_xBuilder->weld_label("destpathlabel")) + , m_xDestPath(m_xBuilder->weld_label("destpath")) + , m_xChangePathButton(m_xBuilder->weld_button("changepath")) + , m_xLastChecked(m_xBuilder->weld_label("lastchecked")) + , m_xExtrasCheckBox(m_xBuilder->weld_check_button("extrabits")) + , m_xUserAgentLabel(m_xBuilder->weld_label("useragent")) +{ + m_aNeverChecked = m_xNeverChecked->get_label(); + + m_xAutoCheckCheckBox->connect_toggled( LINK( this, SvxOnlineUpdateTabPage, AutoCheckHdl_Impl ) ); + m_xExtrasCheckBox->connect_clicked( LINK( this, SvxOnlineUpdateTabPage, ExtrasCheckHdl_Impl ) ); + m_xCheckNowButton->connect_clicked( LINK( this, SvxOnlineUpdateTabPage, CheckNowHdl_Impl ) ); + m_xChangePathButton->connect_clicked( LINK( this, SvxOnlineUpdateTabPage, FileDialogHdl_Impl ) ); + + uno::Reference < uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() ); + + m_xUpdateAccess = setup::UpdateCheckConfig::create( xContext ); + m_xReadWriteAccess = css::configuration::ReadWriteAccess::create(xContext, "*"); + + bool bDownloadSupported = false; + m_xUpdateAccess->getByName( "DownloadSupported" ) >>= bDownloadSupported; + + m_xAutoDownloadCheckBox->set_visible(bDownloadSupported); + m_xDestPathLabel->set_visible(bDownloadSupported); + m_xDestPath->set_visible(bDownloadSupported); + m_xChangePathButton->set_visible(bDownloadSupported); + + m_aLastCheckedTemplate = m_xLastChecked->get_label(); + + UpdateLastCheckedText(); + UpdateUserAgent(); +} + +SvxOnlineUpdateTabPage::~SvxOnlineUpdateTabPage() +{ +} + +void SvxOnlineUpdateTabPage::UpdateLastCheckedText() +{ + OUString aDateStr; + OUString aTimeStr; + OUString aText; + sal_Int64 lastChecked = 0; + + m_xUpdateAccess->getByName("LastCheck") >>= lastChecked; + + if( lastChecked == 0 ) // never checked + { + aText = m_aNeverChecked; + } + else + { + TimeValue lastCheckedTV; + oslDateTime lastCheckedDT; + + Date aDate( Date::EMPTY ); + tools::Time aTime( tools::Time::EMPTY ); + + lastCheckedTV.Seconds = static_cast(lastChecked); + osl_getLocalTimeFromSystemTime( &lastCheckedTV, &lastCheckedTV ); + + if ( osl_getDateTimeFromTimeValue( &lastCheckedTV, &lastCheckedDT ) ) + { + aDate = Date( lastCheckedDT.Day, lastCheckedDT.Month, lastCheckedDT.Year ); + aTime = ::tools::Time( lastCheckedDT.Hours, lastCheckedDT.Minutes ); + } + + LanguageType eUILang = Application::GetSettings().GetUILanguageTag().getLanguageType(); + std::unique_ptr pNumberFormatter(new SvNumberFormatter( ::comphelper::getProcessComponentContext(), eUILang )); + Color* pColor = nullptr; + const Date& rNullDate = pNumberFormatter->GetNullDate(); + sal_uInt32 nFormat = pNumberFormatter->GetStandardFormat( SvNumFormatType::DATE, eUILang ); + + pNumberFormatter->GetOutputString( aDate - rNullDate, nFormat, aDateStr, &pColor ); + + nFormat = pNumberFormatter->GetStandardFormat( SvNumFormatType::TIME, eUILang ); + pNumberFormatter->GetOutputString( aTime.GetTimeInDays(), nFormat, aTimeStr, &pColor ); + + pNumberFormatter.reset(); + + aText = m_aLastCheckedTemplate; + sal_Int32 nIndex = aText.indexOf( "%DATE%" ); + if ( nIndex != -1 ) + aText = aText.replaceAt( nIndex, 6, aDateStr ); + + nIndex = aText.indexOf( "%TIME%" ); + if ( nIndex != -1 ) + aText = aText.replaceAt( nIndex, 6, aTimeStr ); + } + + m_xLastChecked->set_label(aText); +} + +void SvxOnlineUpdateTabPage::UpdateUserAgent() +{ + try { + uno::Reference< ucb::XWebDAVCommandEnvironment > xDav( + css::deployment::UpdateInformationProvider::create( + ::comphelper::getProcessComponentContext() ), + css::uno::UNO_QUERY_THROW ); + + OUString aPseudoURL = "useragent:normal"; + if( m_xExtrasCheckBox->get_active() ) + aPseudoURL = "useragent:extended"; + const uno::Sequence< beans::StringPair > aHeaders + = xDav->getUserRequestHeaders( aPseudoURL, ucb::WebDAVHTTPMethod(0) ); + + for (const css::beans::StringPair & aHeader : aHeaders) + { + if ( aHeader.First == "User-Agent" ) + { + OUString aText = aHeader.Second; + aText = aText.replaceAll(";", ";\n"); + aText = aText.replaceAll("(", "\n("); + m_xUserAgentLabel->set_label(aText); + break; + } + } + } catch (const uno::Exception &) { + TOOLS_WARN_EXCEPTION( "cui.options", "Unexpected exception fetching User Agent" ); + } +} + +std::unique_ptr SvxOnlineUpdateTabPage::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet ) +{ + return std::make_unique( pPage, pController, *rAttrSet ); +} + +bool SvxOnlineUpdateTabPage::FillItemSet( SfxItemSet* ) +{ + bool bModified = false; + + bool bValue; + sal_Int64 nValue; + + if( m_xAutoCheckCheckBox->get_state_changed_from_saved() ) + { + bValue = m_xAutoCheckCheckBox->get_active(); + m_xUpdateAccess->replaceByName( "AutoCheckEnabled", uno::Any( bValue ) ); + bModified = true; + } + + nValue = 0; + if( m_xEveryDayButton->get_active() ) + { + if( !m_xEveryDayButton->get_saved_state() ) + nValue = 86400; + } + else if( m_xEveryWeekButton->get_active() ) + { + if( !m_xEveryWeekButton->get_saved_state() ) + nValue = 604800; + } + else if( m_xEveryMonthButton->get_active() ) + { + if( !m_xEveryMonthButton->get_saved_state() ) + nValue = 2592000; + } + + if( nValue > 0 ) + { + m_xUpdateAccess->replaceByName( "CheckInterval", uno::Any( nValue ) ); + bModified = true; + } + + if( m_xAutoDownloadCheckBox->get_state_changed_from_saved() ) + { + bValue = m_xAutoDownloadCheckBox->get_active(); + m_xUpdateAccess->replaceByName( "AutoDownloadEnabled", uno::Any( bValue ) ); + bModified = true; + } + + OUString sValue, aURL; + m_xUpdateAccess->getByName( "DownloadDestination" ) >>= sValue; + + if( ( osl::FileBase::E_None == osl::FileBase::getFileURLFromSystemPath(m_xDestPath->get_label(), aURL) ) && + ( aURL != sValue ) ) + { + m_xUpdateAccess->replaceByName( "DownloadDestination", uno::Any( aURL ) ); + bModified = true; + } + + if( m_xExtrasCheckBox->get_state_changed_from_saved() ) + { + bValue = m_xExtrasCheckBox->get_active(); + m_xUpdateAccess->replaceByName( "ExtendedUserAgent", uno::Any( bValue ) ); + bModified = true; + } + + uno::Reference< util::XChangesBatch > xChangesBatch(m_xUpdateAccess, uno::UNO_QUERY); + if( xChangesBatch.is() && xChangesBatch->hasPendingChanges() ) + xChangesBatch->commitChanges(); + + return bModified; +} + +void SvxOnlineUpdateTabPage::Reset( const SfxItemSet* ) +{ + bool bValue = false; + m_xUpdateAccess->getByName( "AutoCheckEnabled" ) >>= bValue; + beans::Property aProperty = m_xReadWriteAccess->getPropertyByHierarchicalName("/org.openoffice.Office.Jobs/Jobs/org.openoffice.Office.Jobs:Job['UpdateCheck']/Arguments/AutoCheckEnabled"); + bool bReadOnly = (aProperty.Attributes & beans::PropertyAttribute::READONLY) != 0; + + m_xAutoCheckCheckBox->set_active(bValue); + m_xAutoCheckCheckBox->set_sensitive(!bReadOnly); + + sal_Int64 nValue = 0; + m_xUpdateAccess->getByName( "CheckInterval" ) >>= nValue; + aProperty = m_xReadWriteAccess->getPropertyByHierarchicalName("/org.openoffice.Office.Jobs/Jobs/org.openoffice.Office.Jobs:Job['UpdateCheck']/Arguments/CheckInterval"); + bool bReadOnly2 = (aProperty.Attributes & beans::PropertyAttribute::READONLY) != 0; + m_xEveryDayButton->set_sensitive(bValue && !(bReadOnly || bReadOnly2)); + m_xEveryWeekButton->set_sensitive(bValue && !(bReadOnly || bReadOnly2)); + m_xEveryMonthButton->set_sensitive(bValue && !(bReadOnly || bReadOnly2)); + + if( nValue == 86400 ) + m_xEveryDayButton->set_active(true); + else if( nValue == 604800 ) + m_xEveryWeekButton->set_active(true); + else + m_xEveryMonthButton->set_active(true); + + m_xAutoCheckCheckBox->save_state(); + m_xEveryDayButton->save_state(); + m_xEveryWeekButton->save_state(); + m_xEveryMonthButton->save_state(); + + m_xUpdateAccess->getByName( "AutoDownloadEnabled" ) >>= bValue; + aProperty = m_xReadWriteAccess->getPropertyByHierarchicalName("/org.openoffice.Office.Jobs/Jobs/org.openoffice.Office.Jobs:Job['UpdateCheck']/Arguments/AutoDownloadEnabled"); + bReadOnly = (aProperty.Attributes & beans::PropertyAttribute::READONLY) != 0; + m_xAutoDownloadCheckBox->set_active(bValue); + m_xAutoDownloadCheckBox->set_sensitive(!bReadOnly); + m_xDestPathLabel->set_sensitive(true); + m_xDestPath->set_sensitive(true); + + OUString sValue, aPath; + m_xUpdateAccess->getByName( "DownloadDestination" ) >>= sValue; + aProperty = m_xReadWriteAccess->getPropertyByHierarchicalName("/org.openoffice.Office.Jobs/Jobs/org.openoffice.Office.Jobs:Job['UpdateCheck']/Arguments/DownloadDestination"); + bReadOnly = (aProperty.Attributes & beans::PropertyAttribute::READONLY) != 0; + m_xChangePathButton->set_sensitive(!bReadOnly); + + if( osl::FileBase::E_None == osl::FileBase::getSystemPathFromFileURL(sValue, aPath) ) + m_xDestPath->set_label(aPath); + + m_xUpdateAccess->getByName( "ExtendedUserAgent" ) >>= bValue; + aProperty = m_xReadWriteAccess->getPropertyByHierarchicalName("/org.openoffice.Office.Jobs/Jobs/org.openoffice.Office.Jobs:Job['UpdateCheck']/Arguments/ExtendedUserAgent"); + bReadOnly = (aProperty.Attributes & beans::PropertyAttribute::READONLY) != 0; + m_xExtrasCheckBox->set_active(bValue); + m_xExtrasCheckBox->set_sensitive(!bReadOnly); + m_xExtrasCheckBox->save_state(); + UpdateUserAgent(); + + m_xAutoDownloadCheckBox->save_state(); +} + +void SvxOnlineUpdateTabPage::FillUserData() +{ +} + +IMPL_LINK(SvxOnlineUpdateTabPage, AutoCheckHdl_Impl, weld::ToggleButton&, rBox, void) +{ + bool bEnabled = rBox.get_active(); + beans::Property aProperty = m_xReadWriteAccess->getPropertyByHierarchicalName("/org.openoffice.Office.Jobs/Jobs/org.openoffice.Office.Jobs:Job['UpdateCheck']/Arguments/CheckInterval"); + bool bReadOnly = (aProperty.Attributes & beans::PropertyAttribute::READONLY) != 0; + m_xEveryDayButton->set_sensitive(bEnabled && !bReadOnly); + m_xEveryWeekButton->set_sensitive(bEnabled && !bReadOnly); + m_xEveryMonthButton->set_sensitive(bEnabled && !bReadOnly); +} + +IMPL_LINK_NOARG(SvxOnlineUpdateTabPage, ExtrasCheckHdl_Impl, weld::Button&, void) +{ + UpdateUserAgent(); +} + +IMPL_LINK_NOARG(SvxOnlineUpdateTabPage, FileDialogHdl_Impl, weld::Button&, void) +{ + uno::Reference < uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() ); + uno::Reference < ui::dialogs::XFolderPicker2 > xFolderPicker = ui::dialogs::FolderPicker::create(xContext); + + OUString aURL; + if( osl::FileBase::E_None != osl::FileBase::getFileURLFromSystemPath(m_xDestPath->get_label(), aURL) ) + osl::Security().getHomeDir(aURL); + + xFolderPicker->setDisplayDirectory( aURL ); + sal_Int16 nRet = xFolderPicker->execute(); + + if ( ui::dialogs::ExecutableDialogResults::OK == nRet ) + { + OUString aFolder; + if( osl::FileBase::E_None == osl::FileBase::getSystemPathFromFileURL(xFolderPicker->getDirectory(), aFolder)) + m_xDestPath->set_label(aFolder); + } +} + +IMPL_LINK_NOARG(SvxOnlineUpdateTabPage, CheckNowHdl_Impl, weld::Button&, void) +{ + uno::Reference < uno::XComponentContext> xContext( ::comphelper::getProcessComponentContext() ); + + try + { + uno::Reference< lang::XMultiServiceFactory > xConfigProvider( + css::configuration::theDefaultProvider::get( xContext ) ); + + beans::NamedValue aProperty; + aProperty.Name = "nodepath"; + aProperty.Value <<= OUString("org.openoffice.Office.Addons/AddonUI/OfficeHelp/UpdateCheckJob"); + + uno::Sequence< uno::Any > aArgumentList( 1 ); + aArgumentList[0] <<= aProperty; + + uno::Reference< container::XNameAccess > xNameAccess( + xConfigProvider->createInstanceWithArguments( + "com.sun.star.configuration.ConfigurationAccess", aArgumentList ), + uno::UNO_QUERY_THROW ); + + util::URL aURL; + xNameAccess->getByName("URL") >>= aURL.Complete; + + uno::Reference < util::XURLTransformer > xTransformer( util::URLTransformer::create( xContext ) ); + + xTransformer->parseStrict(aURL); + + uno::Reference < frame::XDesktop2 > xDesktop = frame::Desktop::create( xContext ); + + uno::Reference< frame::XDispatchProvider > xDispatchProvider( + xDesktop->getCurrentFrame(), uno::UNO_QUERY ); + + uno::Reference< frame::XDispatch > xDispatch; + if( xDispatchProvider.is() ) + xDispatch = xDispatchProvider->queryDispatch(aURL, OUString(), 0); + + if( xDispatch.is() ) + xDispatch->dispatch(aURL, uno::Sequence< beans::PropertyValue > ()); + + UpdateLastCheckedText(); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("cui.options", "Caught exception, thread terminated"); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/optupdt.hxx b/cui/source/options/optupdt.hxx new file mode 100644 index 000000000..bd418991c --- /dev/null +++ b/cui/source/options/optupdt.hxx @@ -0,0 +1,72 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_CUI_SOURCE_OPTIONS_OPTUPDT_HXX +#define INCLUDED_CUI_SOURCE_OPTIONS_OPTUPDT_HXX + +#include +#include +#include + +// class SvxPathTabPage -------------------------------------------------- + +class SvxOnlineUpdateTabPage : public SfxTabPage +{ +private: + OUString m_aNeverChecked; + OUString m_aLastCheckedTemplate; + + css::uno::Reference< css::container::XNameReplace > m_xUpdateAccess; + css::uno::Reference m_xReadWriteAccess; + + std::unique_ptr m_xNeverChecked; + std::unique_ptr m_xAutoCheckCheckBox; + std::unique_ptr m_xEveryDayButton; + std::unique_ptr m_xEveryWeekButton; + std::unique_ptr m_xEveryMonthButton; + std::unique_ptr m_xCheckNowButton; + std::unique_ptr m_xAutoDownloadCheckBox; + std::unique_ptr m_xDestPathLabel; + std::unique_ptr m_xDestPath; + std::unique_ptr m_xChangePathButton; + std::unique_ptr m_xLastChecked; + std::unique_ptr m_xExtrasCheckBox; + std::unique_ptr m_xUserAgentLabel; + + DECL_LINK(FileDialogHdl_Impl, weld::Button&, void); + DECL_LINK(CheckNowHdl_Impl, weld::Button&, void); + DECL_LINK(AutoCheckHdl_Impl, weld::ToggleButton&, void); + DECL_LINK(ExtrasCheckHdl_Impl, weld::Button&, void); + + void UpdateLastCheckedText(); + void UpdateUserAgent(); + +public: + SvxOnlineUpdateTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet ); + virtual ~SvxOnlineUpdateTabPage() override; + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; + virtual void FillUserData() override; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/personalization.cxx b/cui/source/options/personalization.cxx new file mode 100644 index 000000000..a732053ba --- /dev/null +++ b/cui/source/options/personalization.cxx @@ -0,0 +1,177 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include "personalization.hxx" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; + +// persona +SvxPersonalizationTabPage::SvxPersonalizationTabPage(weld::Container* pPage, + weld::DialogController* pController, + const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/personalization_tab.ui", "PersonalizationTabPage", + &rSet) + , m_xNoPersona(m_xBuilder->weld_radio_button("no_persona")) + , m_xDefaultPersona(m_xBuilder->weld_radio_button("default_persona")) +{ + for (sal_uInt32 i = 0; i < MAX_DEFAULT_PERSONAS; ++i) + { + OString sDefaultId("default" + OString::number(i)); + m_vDefaultPersonaImages[i] = m_xBuilder->weld_toggle_button(sDefaultId); + m_vDefaultPersonaImages[i]->connect_clicked( + LINK(this, SvxPersonalizationTabPage, DefaultPersona)); + } + + LoadDefaultImages(); +} + +SvxPersonalizationTabPage::~SvxPersonalizationTabPage() {} + +std::unique_ptr SvxPersonalizationTabPage::Create(weld::Container* pPage, + weld::DialogController* pController, + const SfxItemSet* rSet) +{ + return std::make_unique(pPage, pController, *rSet); +} + +bool SvxPersonalizationTabPage::FillItemSet(SfxItemSet*) +{ + // persona + OUString aPersona("default"); + if (m_xNoPersona->get_active()) + aPersona = "no"; + + bool bModified = false; + uno::Reference xContext(comphelper::getProcessComponentContext()); + if (xContext.is() + && (aPersona != officecfg::Office::Common::Misc::Persona::get(xContext) + || m_aPersonaSettings + != officecfg::Office::Common::Misc::PersonaSettings::get(xContext))) + { + bModified = true; + } + + // write + std::shared_ptr batch( + comphelper::ConfigurationChanges::create()); + if (aPersona == "no") + m_aPersonaSettings.clear(); + officecfg::Office::Common::Misc::Persona::set(aPersona, batch); + officecfg::Office::Common::Misc::PersonaSettings::set(m_aPersonaSettings, batch); + batch->commit(); + + if (bModified) + { + // broadcast the change + DataChangedEvent aDataChanged(DataChangedEventType::SETTINGS, nullptr, + AllSettingsFlags::STYLE); + Application::NotifyAllWindows(aDataChanged); + } + + return bModified; +} + +void SvxPersonalizationTabPage::Reset(const SfxItemSet*) +{ + uno::Reference xContext(comphelper::getProcessComponentContext()); + + // persona + OUString aPersona("default"); + if (xContext.is()) + { + aPersona = officecfg::Office::Common::Misc::Persona::get(xContext); + m_aPersonaSettings = officecfg::Office::Common::Misc::PersonaSettings::get(xContext); + } + + if (aPersona == "no") + m_xNoPersona->set_active(true); + else + m_xDefaultPersona->set_active(true); +} + +void SvxPersonalizationTabPage::LoadDefaultImages() +{ + // Load the pre saved personas + + OUString gallery = "$BRAND_BASE_DIR/" LIBO_SHARE_FOLDER "/gallery/personas/"; + rtl::Bootstrap::expandMacros(gallery); + OUString aPersonasList = gallery + "personas_list.txt"; + SvFileStream aStream(aPersonasList, StreamMode::READ); + GraphicFilter aFilter; + Graphic aGraphic; + sal_Int32 nIndex = 0; + bool foundOne = false; + + while (aStream.IsOpen() && !aStream.eof() && nIndex < MAX_DEFAULT_PERSONAS) + { + OString aLine; + OUString aPersonaSetting, aPreviewFile, aName; + sal_Int32 nParseIndex = 0; + + aStream.ReadLine(aLine); + aPersonaSetting = OStringToOUString(aLine, RTL_TEXTENCODING_UTF8); + aName = aPersonaSetting.getToken(1, ';', nParseIndex); + aPreviewFile = aPersonaSetting.getToken(0, ';', nParseIndex); + + if (aPreviewFile.isEmpty()) + break; + + m_vDefaultPersonaSettings.push_back(aPersonaSetting); + + INetURLObject aURLObj(gallery + aPreviewFile); + aFilter.ImportGraphic(aGraphic, aURLObj); + + Size aSize(aGraphic.GetSizePixel()); + aSize.setWidth(aSize.Width() / 4); + aSize.setHeight(aSize.Height() / 1.5); + ScopedVclPtr xVirDev + = m_vDefaultPersonaImages[nIndex]->create_virtual_device(); + xVirDev->SetOutputSizePixel(aSize); + aGraphic.Draw(xVirDev.get(), Point(0, 0)); + m_vDefaultPersonaImages[nIndex]->set_image(xVirDev.get()); + xVirDev.disposeAndClear(); + + m_vDefaultPersonaImages[nIndex]->set_tooltip_text(aName); + m_vDefaultPersonaImages[nIndex++]->show(); + foundOne = true; + } + + m_xDefaultPersona->set_sensitive(foundOne); +} + +IMPL_LINK(SvxPersonalizationTabPage, DefaultPersona, weld::Button&, rButton, void) +{ + m_xDefaultPersona->set_active(true); + for (sal_Int32 nIndex = 0; nIndex < MAX_DEFAULT_PERSONAS; ++nIndex) + { + if (&rButton == m_vDefaultPersonaImages[nIndex].get()) + m_aPersonaSettings = m_vDefaultPersonaSettings[nIndex]; + else + m_vDefaultPersonaImages[nIndex]->set_active(false); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/personalization.hxx b/cui/source/options/personalization.hxx new file mode 100644 index 000000000..072a89b81 --- /dev/null +++ b/cui/source/options/personalization.hxx @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_CUI_SOURCE_OPTIONS_PERSONALIZATION_HXX +#define INCLUDED_CUI_SOURCE_OPTIONS_PERSONALIZATION_HXX + +#include +#include + +#define MAX_DEFAULT_PERSONAS 6 // Maximum number of default personas + +class SvxPersonalizationTabPage : public SfxTabPage +{ +private: + std::unique_ptr m_xNoPersona; ///< Just the default look, without any bitmap + std::unique_ptr m_xDefaultPersona; ///< Use the built-in bitmap + std::unique_ptr m_vDefaultPersonaImages + [MAX_DEFAULT_PERSONAS]; ///< Buttons to show the default persona images + OUString m_aPersonaSettings; ///< Header and footer images + color to be set in the settings. + + std::vector m_vDefaultPersonaSettings; + +public: + SvxPersonalizationTabPage(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet& rSet); + virtual ~SvxPersonalizationTabPage() override; + + static std::unique_ptr + Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet); + + /// Apply the settings ([OK] button). + virtual bool FillItemSet(SfxItemSet* rSet) override; + + /// Reset to default settings ([Revert] button). + virtual void Reset(const SfxItemSet* rSet) override; + + /* + * Loads the default personas from the shared personas directory + * which resides in the shared gallery. + * There needs to be a separate subdirectory for each default persona, + * which includes the preview, header, and footer images. + * And there needs to be a personas_list.txt file in the personas directory + * which keeps the index/info of the default personas, one persona per line. + * A line should look like this: + * persona_slug;Persona Name;subdir/preview.jpg;subdir/header.jpg;subdir/footer.jpg;#textcolor + * (It is recommended to keep the subdir name the same as the slug) + * Example line: + * abstract;Abstract;abstract/preview.jpg;abstract/Header2.jpg;abstract/Footer2.jpg;#ffffff + */ + void LoadDefaultImages(); + +private: + /// Handle the default Persona selection + DECL_LINK(DefaultPersona, weld::Button&, void); +}; + +#endif // INCLUDED_CUI_SOURCE_OPTIONS_PERSONALIZATION_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/sdbcdriverenum.cxx b/cui/source/options/sdbcdriverenum.cxx new file mode 100644 index 000000000..1370c93c2 --- /dev/null +++ b/cui/source/options/sdbcdriverenum.cxx @@ -0,0 +1,98 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "sdbcdriverenum.hxx" +#include +#include +#include +#include + + +namespace offapp +{ + + + using namespace css::uno; + using namespace css::lang; + using namespace css::container; + using namespace css::sdbc; + + class ODriverEnumerationImpl + { + protected: + std::vector< OUString > m_aImplNames; + + public: + ODriverEnumerationImpl(); + + const std::vector< OUString >& getDriverImplNames() const { return m_aImplNames; } + }; + + + ODriverEnumerationImpl::ODriverEnumerationImpl() + { + try + { + Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext(); + Reference< XDriverManager2 > xEnumAccess = DriverManager::create( xContext ); + + Reference< XEnumeration > xEnumDrivers = xEnumAccess->createEnumeration(); + OSL_ENSURE(xEnumDrivers.is(), "ODriverEnumerationImpl::ODriverEnumerationImpl: invalid enumeration object!"); + + Reference< XServiceInfo > xDriverSI; + while (xEnumDrivers->hasMoreElements()) + { + xEnumDrivers->nextElement() >>= xDriverSI; + OSL_ENSURE(xDriverSI.is(), "ODriverEnumerationImpl::ODriverEnumerationImpl: driver without service info!"); + if (xDriverSI.is()) + m_aImplNames.push_back(xDriverSI->getImplementationName()); + } + } + catch(const Exception&) + { + OSL_FAIL("ODriverEnumerationImpl::ODriverEnumerationImpl: caught an exception while enumerating the drivers!"); + } + } + + ODriverEnumeration::ODriverEnumeration() throw() + :m_pImpl(new ODriverEnumerationImpl) + { + } + + + ODriverEnumeration::~ODriverEnumeration() throw() + { + } + + + ODriverEnumeration::const_iterator ODriverEnumeration::begin() const throw() + { + return m_pImpl->getDriverImplNames().begin(); + } + + + ODriverEnumeration::const_iterator ODriverEnumeration::end() const throw() + { + return m_pImpl->getDriverImplNames().end(); + } + +} // namespace offapp + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/sdbcdriverenum.hxx b/cui/source/options/sdbcdriverenum.hxx new file mode 100644 index 000000000..ef25bca00 --- /dev/null +++ b/cui/source/options/sdbcdriverenum.hxx @@ -0,0 +1,54 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include + +#include +#include + + +namespace offapp +{ + + class ODriverEnumerationImpl; + /** simple class for accessing SDBC drivers registered within the office +

Rather small, introduced to not contaminate other instances with the + exception handling (code-size-bloating) implementations here. +

+ */ + class ODriverEnumeration + { + private: + std::unique_ptr m_pImpl; + + public: + ODriverEnumeration() throw(); + ~ODriverEnumeration() throw(); + typedef std::vector< OUString >::const_iterator const_iterator; + + const_iterator begin() const throw(); + const_iterator end() const throw(); + }; + + +} // namespace offapp + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/securityoptions.cxx b/cui/source/options/securityoptions.cxx new file mode 100644 index 000000000..202128b99 --- /dev/null +++ b/cui/source/options/securityoptions.cxx @@ -0,0 +1,82 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include "securityoptions.hxx" + +namespace +{ + bool enableAndSet(const SvtSecurityOptions& rOptions, + SvtSecurityOptions::EOption eOption, + weld::CheckButton& rCheckBox, weld::Widget& rFixedImage) + { + bool bEnable = rOptions.IsOptionEnabled(eOption); + rCheckBox.set_sensitive(bEnable); + rFixedImage.set_visible(!bEnable); + rCheckBox.set_active(rOptions.IsOptionSet(eOption)); + return bEnable; + } +} + +namespace svx +{ + +SecurityOptionsDialog::SecurityOptionsDialog(weld::Window* pParent, SvtSecurityOptions const * pOptions) + : GenericDialogController(pParent, "cui/ui/securityoptionsdialog.ui", "SecurityOptionsDialog") + , m_xSaveOrSendDocsCB(m_xBuilder->weld_check_button("savesenddocs")) + , m_xSaveOrSendDocsImg(m_xBuilder->weld_widget("locksavesenddocs")) + , m_xSignDocsCB(m_xBuilder->weld_check_button("whensigning")) + , m_xSignDocsImg(m_xBuilder->weld_widget("lockwhensigning")) + , m_xPrintDocsCB(m_xBuilder->weld_check_button("whenprinting")) + , m_xPrintDocsImg(m_xBuilder->weld_widget("lockwhenprinting")) + , m_xCreatePdfCB(m_xBuilder->weld_check_button("whenpdf")) + , m_xCreatePdfImg(m_xBuilder->weld_widget("lockwhenpdf")) + , m_xRemovePersInfoCB(m_xBuilder->weld_check_button("removepersonal")) + , m_xRemovePersInfoImg(m_xBuilder->weld_widget("lockremovepersonal")) + , m_xRecommPasswdCB(m_xBuilder->weld_check_button("password")) + , m_xRecommPasswdImg(m_xBuilder->weld_widget("lockpassword")) + , m_xCtrlHyperlinkCB(m_xBuilder->weld_check_button("ctrlclick")) + , m_xCtrlHyperlinkImg(m_xBuilder->weld_widget("lockctrlclick")) + , m_xBlockUntrustedRefererLinksCB(m_xBuilder->weld_check_button("blockuntrusted")) + , m_xBlockUntrustedRefererLinksImg(m_xBuilder->weld_widget("lockblockuntrusted")) +{ + DBG_ASSERT( pOptions, "SecurityOptionsDialog::SecurityOptionsDialog(): invalid SvtSecurityOptions" ); + enableAndSet(*pOptions, SvtSecurityOptions::EOption::DocWarnSaveOrSend, *m_xSaveOrSendDocsCB, + *m_xSaveOrSendDocsImg); + enableAndSet(*pOptions, SvtSecurityOptions::EOption::DocWarnSigning, *m_xSignDocsCB, + *m_xSignDocsImg); + enableAndSet(*pOptions, SvtSecurityOptions::EOption::DocWarnPrint, *m_xPrintDocsCB, + *m_xPrintDocsImg); + enableAndSet(*pOptions, SvtSecurityOptions::EOption::DocWarnCreatePdf, *m_xCreatePdfCB, + *m_xCreatePdfImg); + enableAndSet(*pOptions, SvtSecurityOptions::EOption::DocWarnRemovePersonalInfo, *m_xRemovePersInfoCB, + *m_xRemovePersInfoImg); + enableAndSet(*pOptions, SvtSecurityOptions::EOption::DocWarnRecommendPassword, *m_xRecommPasswdCB, + *m_xRecommPasswdImg); + enableAndSet(*pOptions, SvtSecurityOptions::EOption::CtrlClickHyperlink, *m_xCtrlHyperlinkCB, + *m_xCtrlHyperlinkImg); + enableAndSet(*pOptions, SvtSecurityOptions::EOption::BlockUntrustedRefererLinks, *m_xBlockUntrustedRefererLinksCB, + *m_xBlockUntrustedRefererLinksImg); +} + +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/securityoptions.hxx b/cui/source/options/securityoptions.hxx new file mode 100644 index 000000000..d5ed7b01a --- /dev/null +++ b/cui/source/options/securityoptions.hxx @@ -0,0 +1,63 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include + +class SvtSecurityOptions; + +namespace svx +{ + + class SecurityOptionsDialog : public weld::GenericDialogController + { + private: + std::unique_ptr m_xSaveOrSendDocsCB; + std::unique_ptr m_xSaveOrSendDocsImg; + std::unique_ptr m_xSignDocsCB; + std::unique_ptr m_xSignDocsImg; + std::unique_ptr m_xPrintDocsCB; + std::unique_ptr m_xPrintDocsImg; + std::unique_ptr m_xCreatePdfCB; + std::unique_ptr m_xCreatePdfImg; + + std::unique_ptr m_xRemovePersInfoCB; + std::unique_ptr m_xRemovePersInfoImg; + std::unique_ptr m_xRecommPasswdCB; + std::unique_ptr m_xRecommPasswdImg; + std::unique_ptr m_xCtrlHyperlinkCB; + std::unique_ptr m_xCtrlHyperlinkImg; + std::unique_ptr m_xBlockUntrustedRefererLinksCB; + std::unique_ptr m_xBlockUntrustedRefererLinksImg; + + public: + SecurityOptionsDialog(weld::Window* pParent, SvtSecurityOptions const * pOptions); + + bool IsSaveOrSendDocsChecked() const { return m_xSaveOrSendDocsCB->get_active(); } + bool IsSignDocsChecked() const { return m_xSignDocsCB->get_active(); } + bool IsPrintDocsChecked() const { return m_xPrintDocsCB->get_active(); } + bool IsCreatePdfChecked() const { return m_xCreatePdfCB->get_active(); } + bool IsRemovePersInfoChecked() const { return m_xRemovePersInfoCB->get_active(); } + bool IsRecommPasswdChecked() const { return m_xRecommPasswdCB->get_active(); } + bool IsCtrlHyperlinkChecked() const { return m_xCtrlHyperlinkCB->get_active(); } + bool IsBlockUntrustedRefererLinksChecked() const { return m_xBlockUntrustedRefererLinksCB->get_active(); } + }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/treeopt.cxx b/cui/source/options/treeopt.cxx new file mode 100644 index 000000000..0e63a774d --- /dev/null +++ b/cui/source/options/treeopt.cxx @@ -0,0 +1,2104 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "cfgchart.hxx" +#include "connpoolconfig.hxx" +#include "connpooloptions.hxx" +#include +#include +#include "dbregisterednamesconfig.hxx" +#include +#include "fontsubs.hxx" +#include "optaccessibility.hxx" +#include +#include "optchart.hxx" +#include "optcolor.hxx" +#include "optctl.hxx" +#include "optfltr.hxx" +#include "optgdlg.hxx" +#include "opthtml.hxx" +#include "optinet2.hxx" +#include "optjava.hxx" +#include "optjsearch.hxx" +#include +#if HAVE_FEATURE_OPENCL +#include "optopencl.hxx" +#endif +#include +#include "optsave.hxx" +#include "optupdt.hxx" +#include "personalization.hxx" +#include +#include "optbasic.hxx" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::linguistic2; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::util; + +LastPageSaver* OfaTreeOptionsDialog::pLastPageSaver = nullptr; + +// some stuff for easier changes for SvtViewOptions +static const OUString VIEWOPT_DATANAME = "page data"; + +static void SetViewOptUserItem( SvtViewOptions& rOpt, const OUString& rData ) +{ + rOpt.SetUserItem( VIEWOPT_DATANAME, Any( rData ) ); +} + +static OUString GetViewOptUserItem( const SvtViewOptions& rOpt ) +{ + Any aAny( rOpt.GetUserItem( VIEWOPT_DATANAME ) ); + OUString aUserData; + aAny >>= aUserData; + + return aUserData; +} + +namespace { + +struct ModuleToGroupNameMap_Impl +{ + OUStringLiteral m_pModule; + OUString m_sGroupName; + sal_uInt16 m_nNodeId; +}; +} + +static ModuleToGroupNameMap_Impl ModuleMap[] = +{ + { "ProductName", OUString(), SID_GENERAL_OPTIONS }, + { "LanguageSettings", OUString(), SID_LANGUAGE_OPTIONS }, + { "Internet", OUString(), SID_INET_DLG }, + { "LoadSave", OUString(), SID_FILTER_DLG }, + { "Writer", OUString(), SID_SW_EDITOPTIONS }, + { "WriterWeb", OUString(), SID_SW_ONLINEOPTIONS }, + { "Math", OUString(), SID_SM_EDITOPTIONS }, + { "Calc", OUString(), SID_SC_EDITOPTIONS }, + { "Impress", OUString(), SID_SD_EDITOPTIONS }, + { "Draw", OUString(), SID_SD_GRAPHIC_OPTIONS }, + { "Charts", OUString(), SID_SCH_EDITOPTIONS }, + { "Base", OUString(), SID_SB_STARBASEOPTIONS }, +}; + +static void setGroupName( const OUString& rModule, const OUString& rGroupName ) +{ + for (ModuleToGroupNameMap_Impl& rEntry : ModuleMap) + { + if ( rEntry.m_pModule == rModule ) + { + rEntry.m_sGroupName = rGroupName; + break; + } + } +} + +static OUString getGroupName( const OUString& rModule, bool bForced ) +{ + OUString sGroupName; + for (const ModuleToGroupNameMap_Impl& rEntry : ModuleMap) + { + if ( rEntry.m_pModule == rModule ) + { + sGroupName = rEntry.m_sGroupName; + break; + } + } + + if ( sGroupName.isEmpty() && bForced ) + { + if ( rModule == "Writer" ) + sGroupName = CuiResId(SID_SW_EDITOPTIONS_RES[0].first); + else if ( rModule == "WriterWeb" ) + sGroupName = CuiResId(SID_SW_ONLINEOPTIONS_RES[0].first); + else if ( rModule == "Calc" ) + sGroupName = CuiResId(SID_SC_EDITOPTIONS_RES[0].first); + else if ( rModule == "Impress" ) + sGroupName = CuiResId(SID_SD_EDITOPTIONS_RES[0].first); + else if ( rModule == "Draw" ) + sGroupName = CuiResId(SID_SD_GRAPHIC_OPTIONS_RES[0].first); + else if ( rModule == "Math" ) + sGroupName = CuiResId(SID_SM_EDITOPTIONS_RES[0].first); + else if ( rModule == "Base" ) + sGroupName = CuiResId(SID_SB_STARBASEOPTIONS_RES[0].first); + } + return sGroupName; +} + +static void deleteGroupNames() +{ + for (ModuleToGroupNameMap_Impl& rEntry : ModuleMap) + rEntry.m_sGroupName.clear(); +} + +static sal_uInt16 getGroupNodeId( const OUString& rModule ) +{ + sal_uInt16 nNodeId = 0xFFFF; + for (const ModuleToGroupNameMap_Impl& rEntry : ModuleMap) + { + if ( rEntry.m_pModule == rModule ) + { + nNodeId = rEntry.m_nNodeId; + break; + } + } + + return nNodeId; +} + +namespace { + +class MailMergeCfg_Impl : public utl::ConfigItem +{ +private: + // variables + bool bIsEmailSupported; + + virtual void ImplCommit() override; + +public: + MailMergeCfg_Impl(); + + virtual void Notify( const css::uno::Sequence< OUString >& _rPropertyNames) override; + + bool IsEmailSupported() const {return bIsEmailSupported;} + +}; + +} + +MailMergeCfg_Impl::MailMergeCfg_Impl() : + utl::ConfigItem("Office.Writer/MailMergeWizard"), + bIsEmailSupported(false) +{ + Sequence aNames { "EMailSupported" }; + const Sequence< Any > aValues = GetProperties(aNames); + const Any* pValues = aValues.getConstArray(); + if(aValues.hasElements() && pValues[0].hasValue()) + pValues[0] >>= bIsEmailSupported; +} + +void MailMergeCfg_Impl::ImplCommit() +{ +} + +void MailMergeCfg_Impl::Notify( const css::uno::Sequence< OUString >& ) +{ +} + +//typedef SfxTabPage* (*FNCreateTabPage)(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rAttrSet); +static std::unique_ptr CreateGeneralTabPage(sal_uInt16 nId, weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) +{ + CreateTabPage fnCreate = nullptr; + switch(nId) + { + case RID_SFXPAGE_SAVE: fnCreate = &SvxSaveTabPage::Create; break; + case RID_SFXPAGE_PATH: fnCreate = &SvxPathTabPage::Create; break; + case RID_SFXPAGE_GENERAL: fnCreate = &SvxGeneralTabPage::Create; break; + case RID_SFXPAGE_PRINTOPTIONS: fnCreate = &SfxCommonPrintOptionsTabPage::Create; break; + case OFA_TP_LANGUAGES: fnCreate = &OfaLanguagesTabPage::Create; break; + case RID_SFXPAGE_LINGU: fnCreate = &SvxLinguTabPage::Create; break; + case OFA_TP_VIEW: fnCreate = &OfaViewTabPage::Create; break; + case OFA_TP_MISC: fnCreate = &OfaMiscTabPage::Create; break; + case RID_SVXPAGE_ASIAN_LAYOUT: fnCreate = &SvxAsianLayoutPage::Create; break; + case RID_SVX_FONT_SUBSTITUTION: fnCreate = &SvxFontSubstTabPage::Create; break; + case RID_SVXPAGE_INET_PROXY: fnCreate = &SvxProxyTabPage::Create; break; + case RID_SVXPAGE_INET_SECURITY: fnCreate = &SvxSecurityTabPage::Create; break; + case RID_SVXPAGE_INET_MAIL: fnCreate = &SvxEMailTabPage::Create; break; +#if HAVE_FEATURE_DESKTOP + case RID_SVXPAGE_PERSONALIZATION: fnCreate = &SvxPersonalizationTabPage::Create; break; +#endif + case RID_SVXPAGE_COLORCONFIG: fnCreate = &SvxColorOptionsTabPage::Create; break; + case RID_OFAPAGE_HTMLOPT: fnCreate = &OfaHtmlTabPage::Create; break; + case SID_OPTFILTER_MSOFFICE: fnCreate = &OfaMSFilterTabPage::Create; break; + case RID_OFAPAGE_MSFILTEROPT2: fnCreate = &OfaMSFilterTabPage2::Create; break; + case RID_SVXPAGE_JSEARCH_OPTIONS: fnCreate = &SvxJSearchOptionsPage::Create ; break; + case SID_SB_CONNECTIONPOOLING: fnCreate = &::offapp::ConnectionPoolOptionsPage::Create; break; + case SID_SB_DBREGISTEROPTIONS: fnCreate = &svx::DbRegistrationOptionsPage::Create; break; + case RID_SVXPAGE_ACCESSIBILITYCONFIG: fnCreate = &SvxAccessibilityOptionsTabPage::Create; break; + case RID_SVXPAGE_OPTIONS_CTL: fnCreate = &SvxCTLOptionsPage::Create ; break; + case RID_SVXPAGE_OPTIONS_JAVA: fnCreate = &SvxJavaOptionsPage::Create ; break; +#if HAVE_FEATURE_OPENCL + case RID_SVXPAGE_OPENCL: fnCreate = &SvxOpenCLTabPage::Create ; break; +#endif + case RID_SVXPAGE_ONLINEUPDATE: fnCreate = &SvxOnlineUpdateTabPage::Create; break; + case RID_OPTPAGE_CHART_DEFCOLORS: fnCreate = &SvxDefaultColorOptPage::Create; break; +#if HAVE_FEATURE_SCRIPTING + case RID_SVXPAGE_BASICIDE_OPTIONS: fnCreate = &SvxBasicIDEOptionsPage::Create; break; +#endif + } + + return fnCreate ? (*fnCreate)( pPage, pController, &rSet ) : nullptr; +} + +namespace { + +struct OptionsMapping_Impl +{ + const char* m_pGroupName; + const char* m_pPageName; + sal_uInt16 m_nPageId; +}; + +} + +static OptionsMapping_Impl const OptionsMap_Impl[] = +{ +// GROUP PAGE PAGE-ID + { "ProductName", nullptr, SID_GENERAL_OPTIONS }, + { "ProductName", "UserData", RID_SFXPAGE_GENERAL }, + { "ProductName", "General", OFA_TP_MISC }, + { "ProductName", "View", OFA_TP_VIEW }, + { "ProductName", "Print", RID_SFXPAGE_PRINTOPTIONS }, + { "ProductName", "Paths", RID_SFXPAGE_PATH }, + { "ProductName", "Fonts", RID_SVX_FONT_SUBSTITUTION }, + { "ProductName", "Security", RID_SVXPAGE_INET_SECURITY }, + { "ProductName", "Personalization", RID_SVXPAGE_PERSONALIZATION }, + { "ProductName", "Appearance", RID_SVXPAGE_COLORCONFIG }, + { "ProductName", "Accessibility", RID_SVXPAGE_ACCESSIBILITYCONFIG }, + { "ProductName", "Java", RID_SVXPAGE_OPTIONS_JAVA }, + { "ProductName", "BasicIDEOptions", RID_SVXPAGE_BASICIDE_OPTIONS }, + { "ProductName", "OnlineUpdate", RID_SVXPAGE_ONLINEUPDATE }, + { "LanguageSettings", nullptr, SID_LANGUAGE_OPTIONS }, + { "LanguageSettings", "Languages", OFA_TP_LANGUAGES }, + { "LanguageSettings", "WritingAids", RID_SFXPAGE_LINGU }, + { "LanguageSettings", "SearchingInJapanese", RID_SVXPAGE_JSEARCH_OPTIONS }, + { "LanguageSettings", "AsianLayout", RID_SVXPAGE_ASIAN_LAYOUT }, + { "LanguageSettings", "ComplexTextLayout", RID_SVXPAGE_OPTIONS_CTL }, + { "Internet", nullptr, SID_INET_DLG }, + { "Internet", "Proxy", RID_SVXPAGE_INET_PROXY }, + { "Internet", "Email", RID_SVXPAGE_INET_MAIL }, + { "LoadSave", nullptr, SID_FILTER_DLG }, + { "LoadSave", "General", RID_SFXPAGE_SAVE }, + { "LoadSave", "VBAProperties", SID_OPTFILTER_MSOFFICE }, + { "LoadSave", "MicrosoftOffice", RID_OFAPAGE_MSFILTEROPT2 }, + { "LoadSave", "HTMLCompatibility", RID_OFAPAGE_HTMLOPT }, + { "Writer", nullptr, SID_SW_EDITOPTIONS }, + { "Writer", "General", RID_SW_TP_OPTLOAD_PAGE }, + { "Writer", "View", RID_SW_TP_CONTENT_OPT }, + { "Writer", "FormattingAids", RID_SW_TP_OPTSHDWCRSR }, + { "Writer", "Grid", RID_SVXPAGE_GRID }, + { "Writer", "BasicFontsWestern", RID_SW_TP_STD_FONT }, + { "Writer", "BasicFontsAsian", RID_SW_TP_STD_FONT_CJK }, + { "Writer", "BasicFontsCTL", RID_SW_TP_STD_FONT_CTL }, + { "Writer", "Print", RID_SW_TP_OPTPRINT_PAGE }, + { "Writer", "Table", RID_SW_TP_OPTTABLE_PAGE }, + { "Writer", "Changes", RID_SW_TP_REDLINE_OPT }, + { "Writer", "Comparison", RID_SW_TP_COMPARISON_OPT }, + { "Writer", "Compatibility", RID_SW_TP_OPTCOMPATIBILITY_PAGE }, + { "Writer", "AutoCaption", RID_SW_TP_OPTCAPTION_PAGE }, + { "Writer", "MailMerge", RID_SW_TP_MAILCONFIG }, + { "WriterWeb", nullptr, SID_SW_ONLINEOPTIONS }, + { "WriterWeb", "View", RID_SW_TP_HTML_CONTENT_OPT }, + { "WriterWeb", "FormattingAids", RID_SW_TP_HTML_OPTSHDWCRSR }, + { "WriterWeb", "Grid", RID_SW_TP_HTML_OPTGRID_PAGE }, + { "WriterWeb", "Print", RID_SW_TP_HTML_OPTPRINT_PAGE }, + { "WriterWeb", "Table", RID_SW_TP_HTML_OPTTABLE_PAGE }, + { "WriterWeb", "Background", RID_SW_TP_BACKGROUND }, + { "Math", nullptr, SID_SM_EDITOPTIONS }, + { "Math", "Settings", SID_SM_TP_PRINTOPTIONS }, + { "Calc", nullptr, SID_SC_EDITOPTIONS }, + { "Calc", "General", SID_SC_TP_LAYOUT }, + { "Calc", "View", SID_SC_TP_CONTENT }, + { "Calc", "Calculate", SID_SC_TP_CALC }, + { "Calc", "Formula", SID_SC_TP_FORMULA }, + { "Calc", "SortLists", SID_SC_TP_USERLISTS }, + { "Calc", "Changes", SID_SC_TP_CHANGES }, + { "Calc", "Compatibility", SID_SC_TP_COMPATIBILITY }, + { "Calc", "Grid", SID_SC_TP_GRID }, + { "Calc", "Print", RID_SC_TP_PRINT }, + { "Impress", nullptr, SID_SD_EDITOPTIONS }, + { "Impress", "General", SID_SI_TP_MISC }, + { "Impress", "View", SID_SI_TP_CONTENTS }, + { "Impress", "Grid", SID_SI_TP_SNAP }, + { "Impress", "Print", SID_SI_TP_PRINT }, + { "Draw", nullptr, SID_SD_GRAPHIC_OPTIONS }, + { "Draw", "General", SID_SD_TP_MISC }, + { "Draw", "View", SID_SD_TP_CONTENTS }, + { "Draw", "Grid", SID_SD_TP_SNAP }, + { "Draw", "Print", SID_SD_TP_PRINT }, + { "Charts", nullptr, SID_SCH_EDITOPTIONS }, + { "Charts", "DefaultColors", RID_OPTPAGE_CHART_DEFCOLORS }, + { "Base", nullptr, SID_SB_STARBASEOPTIONS }, + { "Base", "Connections", SID_SB_CONNECTIONPOOLING }, + { "Base", "Databases", SID_SB_DBREGISTEROPTIONS }, + { nullptr, nullptr, 0 } +}; + +static bool lcl_getStringFromID( sal_uInt16 _nPageId, OUString& _rGroupName, OUString& _rPageName ) +{ + bool bRet = false; + + sal_uInt16 nIdx = 0; + while ( OptionsMap_Impl[nIdx].m_pGroupName != nullptr ) + { + if ( _nPageId == OptionsMap_Impl[nIdx].m_nPageId ) + { + bRet = true; + _rGroupName = OUString::createFromAscii( OptionsMap_Impl[nIdx].m_pGroupName ); + if ( OptionsMap_Impl[nIdx].m_pPageName != nullptr ) + _rPageName = OUString::createFromAscii( OptionsMap_Impl[nIdx].m_pPageName ); + break; + } + ++nIdx; + } + + return bRet; +} + +static bool lcl_isOptionHidden( sal_uInt16 _nPageId, const SvtOptionsDialogOptions& _rOptOptions ) +{ + bool bIsHidden = false; + OUString sGroupName, sPageName; + if ( lcl_getStringFromID( _nPageId, sGroupName, sPageName ) ) + { + if ( sPageName.isEmpty() ) + bIsHidden = _rOptOptions.IsGroupHidden( sGroupName ); + else + bIsHidden = _rOptOptions.IsPageHidden( sPageName, sGroupName ); + } + return bIsHidden; +} + +struct OptionsPageInfo +{ + std::unique_ptr m_xPage; + sal_uInt16 m_nPageId; + OUString m_sPageURL; + OUString m_sEventHdl; + std::unique_ptr m_xExtPage; + + explicit OptionsPageInfo( sal_uInt16 nId ) : m_nPageId( nId ) {} +}; + +namespace { + +struct OptionsGroupInfo +{ + std::unique_ptr m_pInItemSet; + std::unique_ptr m_pOutItemSet; + SfxShell* m_pShell; // used to create the page + SfxModule* m_pModule; // used to create the ItemSet + sal_uInt16 m_nDialogId; // Id of the former dialog + + OptionsGroupInfo( SfxShell* pSh, SfxModule* pMod, sal_uInt16 nId ) : + m_pShell( pSh ), + m_pModule( pMod ), m_nDialogId( nId ) {} +}; + +} + +#define INI_LIST() \ + , m_pParent ( pParent )\ + , sTitle ( m_xDialog->get_title() )\ + , bForgetSelection ( false )\ + , bIsFromExtensionManager( false ) \ + , bIsForSetDocumentLanguage( false ) \ + , bNeedsRestart ( false ) \ + , eRestartReason( svtools::RESTART_REASON_NONE ) + + +void OfaTreeOptionsDialog::InitWidgets() +{ + xOkPB = m_xBuilder->weld_button("ok"); + xApplyPB = m_xBuilder->weld_button("apply"); + xBackPB = m_xBuilder->weld_button("revert"); + xTreeLB = m_xBuilder->weld_tree_view("pages"); + xTabBox = m_xBuilder->weld_container("box"); + Size aSize(xTreeLB->get_approximate_digit_width() * 82, xTreeLB->get_height_rows(30)); +#if HAVE_FEATURE_GPGME + { + // load this little .ui just to measure the height of an Entry + std::unique_ptr xBuilder(Application::CreateBuilder(m_xDialog.get(), "cui/ui/namedialog.ui")); + std::unique_ptr xEntry(xBuilder->weld_entry("name_entry")); + // tdf#115015: make enough space for crypto settings (approx. 14 text edits + padding) + aSize.setHeight((xEntry->get_preferred_size().Height() + 6) * 14); + } +#endif + xTabBox->set_size_request(aSize.Width(), aSize.Height()); + xTreeLB->set_size_request(xTreeLB->get_approximate_digit_width() * 30, aSize.Height()); +} + +// Ctor() with Frame ----------------------------------------------------- +OfaTreeOptionsDialog::OfaTreeOptionsDialog(weld::Window* pParent, const Reference< XFrame >& _xFrame, bool bActivateLastSelection) + : SfxOkDialogController(pParent, "cui/ui/optionsdialog.ui", "OptionsDialog") + INI_LIST() +{ + InitWidgets(); + + InitTreeAndHandler(); + Initialize( _xFrame ); + LoadExtensionOptions( OUString() ); + if (bActivateLastSelection) + ActivateLastSelection(); + + xTreeLB->set_accessible_name(m_xDialog->get_title()); +} + +// Ctor() with ExtensionId ----------------------------------------------- +OfaTreeOptionsDialog::OfaTreeOptionsDialog(weld::Window* pParent, const OUString& rExtensionId) + : SfxOkDialogController(pParent, "cui/ui/optionsdialog.ui", "OptionsDialog") + INI_LIST() +{ + InitWidgets(); + + bIsFromExtensionManager = ( !rExtensionId.isEmpty() ); + InitTreeAndHandler(); + LoadExtensionOptions( rExtensionId ); + ActivateLastSelection(); +} + +OfaTreeOptionsDialog::~OfaTreeOptionsDialog() +{ + xCurrentPageEntry.reset(); + + std::unique_ptr xEntry = xTreeLB->make_iterator(); + bool bEntry = xTreeLB->get_iter_first(*xEntry); + // first children + while (bEntry) + { + // if Child (has parent), then OptionsPageInfo + if (xTreeLB->get_iter_depth(*xEntry)) + { + OptionsPageInfo *pPageInfo = reinterpret_cast(xTreeLB->get_id(*xEntry).toInt64()); + if(pPageInfo->m_xPage) + { + pPageInfo->m_xPage->FillUserData(); + OUString aPageData(pPageInfo->m_xPage->GetUserData()); + if ( !aPageData.isEmpty() ) + { + SvtViewOptions aTabPageOpt( EViewType::TabPage, OUString::number( pPageInfo->m_nPageId) ); + SetViewOptUserItem( aTabPageOpt, aPageData ); + } + pPageInfo->m_xPage.reset(); + } + + if (pPageInfo->m_nPageId == RID_SFXPAGE_LINGU) + { + // write personal dictionaries + Reference< XSearchableDictionaryList > xDicList( LinguMgr::GetDictionaryList() ); + if (xDicList.is()) + { + linguistic::SaveDictionaries( xDicList ); + } + } + + pPageInfo->m_xExtPage.reset(); + + delete pPageInfo; + } + bEntry = xTreeLB->iter_next(*xEntry); + } + + // and parents + bEntry = xTreeLB->get_iter_first(*xEntry); + while (bEntry) + { + if (!xTreeLB->get_iter_depth(*xEntry)) + { + OptionsGroupInfo* pGroupInfo = reinterpret_cast(xTreeLB->get_id(*xEntry).toInt64()); + delete pGroupInfo; + } + bEntry = xTreeLB->iter_next(*xEntry); + } + deleteGroupNames(); +} + +OptionsPageInfo* OfaTreeOptionsDialog::AddTabPage( + sal_uInt16 nId, const OUString& rPageName, sal_uInt16 nGroup ) +{ + std::unique_ptr xParent = xTreeLB->make_iterator(); + if (!xTreeLB->get_iter_first(*xParent)) + return nullptr; + xTreeLB->iter_nth_sibling(*xParent, nGroup); + + OptionsPageInfo* pPageInfo = new OptionsPageInfo( nId ); + OUString sId(OUString::number(reinterpret_cast(pPageInfo))); + xTreeLB->insert(xParent.get(), -1, &rPageName, &sId, nullptr, nullptr, nullptr, false, nullptr); + return pPageInfo; +} + +// the ItemSet* is passed on to the dialog's ownership +sal_uInt16 OfaTreeOptionsDialog::AddGroup(const OUString& rGroupName, + SfxShell* pCreateShell, + SfxModule* pCreateModule, + sal_uInt16 nDialogId ) +{ + OptionsGroupInfo* pInfo = + new OptionsGroupInfo( pCreateShell, pCreateModule, nDialogId ); + OUString sId(OUString::number(reinterpret_cast(pInfo))); + xTreeLB->append(sId, rGroupName); + + sal_uInt16 nRet = 0; + std::unique_ptr xEntry = xTreeLB->make_iterator(); + bool bEntry = xTreeLB->get_iter_first(*xEntry); + while (bEntry) + { + if (!xTreeLB->get_iter_depth(*xEntry)) + nRet++; + bEntry = xTreeLB->iter_next(*xEntry); + } + return nRet - 1; +} + +IMPL_LINK_NOARG(OfaTreeOptionsDialog, ShowPageHdl_Impl, weld::TreeView&, void) +{ + SelectHdl_Impl(); +} + +IMPL_LINK_NOARG(OfaTreeOptionsDialog, BackHdl_Impl, weld::Button&, void) +{ + if (!(xCurrentPageEntry && xTreeLB->get_iter_depth(*xCurrentPageEntry))) + return; + + OptionsPageInfo* pPageInfo = reinterpret_cast(xTreeLB->get_id(*xCurrentPageEntry).toInt64()); + if (pPageInfo->m_xPage) + { + std::unique_ptr xParent = xTreeLB->make_iterator(xCurrentPageEntry.get()); + xTreeLB->iter_parent(*xParent); + OptionsGroupInfo* pGroupInfo = + reinterpret_cast(xTreeLB->get_id(*xParent).toInt64()); + pPageInfo->m_xPage->Reset( pGroupInfo->m_pInItemSet.get() ); + } + else if ( pPageInfo->m_xExtPage ) + pPageInfo->m_xExtPage->ResetPage(); +} + +void OfaTreeOptionsDialog::ApplyOptions(bool deactivate) +{ + std::unique_ptr xEntry = xTreeLB->make_iterator(); + bool bEntry = xTreeLB->get_iter_first(*xEntry); + while (bEntry) + { + if (xTreeLB->get_iter_depth(*xEntry)) + { + OptionsPageInfo* pPageInfo = reinterpret_cast(xTreeLB->get_id(*xEntry).toInt64()); + if ( pPageInfo->m_xPage && !pPageInfo->m_xPage->HasExchangeSupport() ) + { + std::unique_ptr xParent = xTreeLB->make_iterator(xEntry.get()); + xTreeLB->iter_parent(*xParent); + OptionsGroupInfo* pGroupInfo = + reinterpret_cast(xTreeLB->get_id(*xParent).toInt64()); + pPageInfo->m_xPage->FillItemSet(pGroupInfo->m_pOutItemSet.get()); + } + + if ( pPageInfo->m_xExtPage ) + { + if ( deactivate ) + { + pPageInfo->m_xExtPage->DeactivatePage(); + } + pPageInfo->m_xExtPage->SavePage(); + } + if ( pPageInfo->m_xPage && RID_OPTPAGE_CHART_DEFCOLORS == pPageInfo->m_nPageId ) + { + SvxDefaultColorOptPage* pPage = static_cast(pPageInfo->m_xPage.get()); + pPage->SaveChartOptions(); + } + } + bEntry = xTreeLB->iter_next(*xEntry); + } +} + +IMPL_LINK_NOARG(OfaTreeOptionsDialog, ApplyHdl_Impl, weld::Button&, void) +{ + ApplyOptions(/*deactivate =*/false); + + if ( bNeedsRestart ) + { + SolarMutexGuard aGuard; + if (svtools::executeRestartDialog(comphelper::getProcessComponentContext(), + m_xDialog.get(), eRestartReason)) + m_xDialog->response(RET_OK); + } +} + +IMPL_LINK_NOARG(OfaTreeOptionsDialog, HelpHdl_Impl, weld::Widget&, bool) +{ + Help* pHelp = Application::GetHelp(); + if (pHelp && xCurrentPageEntry && xTreeLB->get_iter_depth(*xCurrentPageEntry)) + { + OptionsPageInfo* pPageInfo = reinterpret_cast(xTreeLB->get_id(*xCurrentPageEntry).toInt64()); + if (pPageInfo->m_xPage) + { + OString sHelpId(pPageInfo->m_xPage->GetHelpId()); + pHelp->Start(OStringToOUString(sHelpId, RTL_TEXTENCODING_UTF8), m_xDialog.get()); + return false; + } + } + return true; +} + +IMPL_LINK_NOARG(OfaTreeOptionsDialog, OKHdl_Impl, weld::Button&, void) +{ + if (xCurrentPageEntry && xTreeLB->get_iter_depth(*xCurrentPageEntry)) + { + OptionsPageInfo* pPageInfo = reinterpret_cast(xTreeLB->get_id(*xCurrentPageEntry).toInt64()); + if ( pPageInfo->m_xPage ) + { + std::unique_ptr xParent = xTreeLB->make_iterator(xCurrentPageEntry.get()); + xTreeLB->iter_parent(*xParent); + + OptionsGroupInfo* pGroupInfo = reinterpret_cast(xTreeLB->get_id(*xParent).toInt64()); + if ( RID_SVXPAGE_COLOR != pPageInfo->m_nPageId + && pPageInfo->m_xPage->HasExchangeSupport() ) + { + DeactivateRC nLeave = pPageInfo->m_xPage->DeactivatePage(pGroupInfo->m_pOutItemSet.get()); + if ( nLeave == DeactivateRC::KeepPage ) + { + // the page mustn't be left + xTreeLB->select(*xCurrentPageEntry); + return; + } + } + pPageInfo->m_xPage->set_visible(false); + } + } + + ApplyOptions(/*deactivate =*/ true); + m_xDialog->response(RET_OK); + + if ( bNeedsRestart ) + { + SolarMutexGuard aGuard; + ::svtools::executeRestartDialog(comphelper::getProcessComponentContext(), + m_pParent, eRestartReason); + } +} + +void OfaTreeOptionsDialog::ApplyItemSets() +{ + std::unique_ptr xEntry = xTreeLB->make_iterator(); + bool bEntry = xTreeLB->get_iter_first(*xEntry); + while (bEntry) + { + if (!xTreeLB->get_iter_depth(*xEntry)) + { + OptionsGroupInfo* pGroupInfo = reinterpret_cast(xTreeLB->get_id(*xEntry).toInt64()); + if(pGroupInfo->m_pOutItemSet) + { + if(pGroupInfo->m_pShell) + pGroupInfo->m_pShell->ApplyItemSet( pGroupInfo->m_nDialogId, *pGroupInfo->m_pOutItemSet); + else + ApplyItemSet( pGroupInfo->m_nDialogId, *pGroupInfo->m_pOutItemSet); + } + } + bEntry = xTreeLB->iter_next(*xEntry); + } +} + +void OfaTreeOptionsDialog::InitTreeAndHandler() +{ + xTreeLB->set_help_id(HID_OFADLG_TREELISTBOX); + xTreeLB->connect_changed( LINK( this, OfaTreeOptionsDialog, ShowPageHdl_Impl ) ); + xBackPB->connect_clicked( LINK( this, OfaTreeOptionsDialog, BackHdl_Impl ) ); + xApplyPB->connect_clicked( LINK( this, OfaTreeOptionsDialog, ApplyHdl_Impl ) ); + xOkPB->connect_clicked( LINK( this, OfaTreeOptionsDialog, OKHdl_Impl ) ); + m_xDialog->connect_help( LINK( this, OfaTreeOptionsDialog, HelpHdl_Impl ) ); +} + +void OfaTreeOptionsDialog::ActivatePage( sal_uInt16 nResId ) +{ + bIsForSetDocumentLanguage = false; + if ( nResId == OFA_TP_LANGUAGES_FOR_SET_DOCUMENT_LANGUAGE ) + { + bIsForSetDocumentLanguage = true; + nResId = OFA_TP_LANGUAGES; + } + + DBG_ASSERT( !bIsFromExtensionManager, "OfaTreeOptionsDialog::ActivatePage(): call from extension manager" ); + if ( !pLastPageSaver ) + pLastPageSaver = new LastPageSaver; + bForgetSelection = true; + sal_uInt16 nTemp = pLastPageSaver->m_nLastPageId; + pLastPageSaver->m_nLastPageId = nResId; + ActivateLastSelection(); + pLastPageSaver->m_nLastPageId = nTemp; +} + +void OfaTreeOptionsDialog::ActivatePage( const OUString& rPageURL ) +{ + DBG_ASSERT( !bIsFromExtensionManager, "OfaTreeOptionsDialog::ActivatePage(): call from extension manager" ); + if ( !pLastPageSaver ) + pLastPageSaver = new LastPageSaver; + bForgetSelection = true; + pLastPageSaver->m_nLastPageId = 0; + pLastPageSaver->m_sLastPageURL_Tools = rPageURL; + ActivateLastSelection(); +} + +void OfaTreeOptionsDialog::ActivateLastSelection() +{ + std::unique_ptr xEntry; + + if (pLastPageSaver) + { + OUString sLastURL = bIsFromExtensionManager ? pLastPageSaver->m_sLastPageURL_ExtMgr + : pLastPageSaver->m_sLastPageURL_Tools; + if ( sLastURL.isEmpty() ) + { + sLastURL = !bIsFromExtensionManager ? pLastPageSaver->m_sLastPageURL_ExtMgr + : pLastPageSaver->m_sLastPageURL_Tools; + } + + bool bMustExpand = ( INetURLObject( sLastURL ).GetProtocol() == INetProtocol::File ); + + std::unique_ptr xTemp = xTreeLB->make_iterator(); + bool bTemp = xTreeLB->get_iter_first(*xTemp); + while (bTemp) + { + // restore only selection of a leaf + if (xTreeLB->get_iter_depth(*xTemp) && xTreeLB->get_id(*xTemp).toInt64()) + { + OptionsPageInfo* pPageInfo = reinterpret_cast(xTreeLB->get_id(*xTemp).toInt64()); + OUString sPageURL = pPageInfo->m_sPageURL; + if ( bMustExpand ) + { + sPageURL = comphelper::getExpandedUri( + comphelper::getProcessComponentContext(), sPageURL); + } + + if ( ( !bIsFromExtensionManager + && pPageInfo->m_nPageId && pPageInfo->m_nPageId == pLastPageSaver->m_nLastPageId ) + || ( !pPageInfo->m_nPageId && sLastURL == sPageURL ) ) + { + xEntry = xTreeLB->make_iterator(xTemp.get()); + break; + } + } + bTemp = xTreeLB->iter_next(*xTemp); + } + } + + if (!xEntry) + { + xEntry = xTreeLB->make_iterator(); + if (!xTreeLB->get_iter_first(*xEntry) || !xTreeLB->iter_next(*xEntry)) + xEntry.reset(); + } + + if (!xEntry) + return; + + std::unique_ptr xParent(xTreeLB->make_iterator(xEntry.get())); + xTreeLB->iter_parent(*xParent); + xTreeLB->expand_row(*xParent); + xTreeLB->scroll_to_row(*xParent); + xTreeLB->scroll_to_row(*xEntry); + xTreeLB->set_cursor(*xEntry); + xTreeLB->select(*xEntry); + xTreeLB->grab_focus(); + SelectHdl_Impl(); +} + +void OfaTreeOptionsDialog::SelectHdl_Impl() +{ + std::unique_ptr xEntry(xTreeLB->make_iterator()); + + if (!xTreeLB->get_cursor(xEntry.get())) + return; + + if (xCurrentPageEntry && xCurrentPageEntry->equal(*xEntry)) + return; + + std::unique_ptr xParent(xTreeLB->make_iterator(xEntry.get())); + bool bParent = xTreeLB->iter_parent(*xParent); + + // If the user has selected a category, automatically switch to a suitable + // default sub-page instead. + if (!bParent) + return; + + BuilderPage* pNewPage = nullptr; + OptionsPageInfo* pOptPageInfo = (xCurrentPageEntry && xTreeLB->get_iter_depth(*xCurrentPageEntry)) + ? reinterpret_cast(xTreeLB->get_id(*xCurrentPageEntry).toInt64()) : nullptr; + + if (pOptPageInfo && pOptPageInfo->m_xPage && pOptPageInfo->m_xPage->IsVisible()) + { + std::unique_ptr xCurParent(xTreeLB->make_iterator(xCurrentPageEntry.get())); + xTreeLB->iter_parent(*xCurParent); + + OptionsGroupInfo* pGroupInfo = reinterpret_cast(xTreeLB->get_id(*xCurParent).toInt64()); + DeactivateRC nLeave = DeactivateRC::LeavePage; + if ( RID_SVXPAGE_COLOR != pOptPageInfo->m_nPageId && pOptPageInfo->m_xPage->HasExchangeSupport() ) + nLeave = pOptPageInfo->m_xPage->DeactivatePage( pGroupInfo->m_pOutItemSet.get() ); + + if ( nLeave == DeactivateRC::KeepPage ) + { + // we cannot leave this page + xTreeLB->select(*xCurrentPageEntry); + return; + } + else + pOptPageInfo->m_xPage->set_visible(false); + } + else if ( pOptPageInfo && pOptPageInfo->m_xExtPage ) + { + pOptPageInfo->m_xExtPage->Hide(); + pOptPageInfo->m_xExtPage->DeactivatePage(); + } + + OptionsPageInfo *pPageInfo = reinterpret_cast(xTreeLB->get_id(*xEntry).toInt64()); + OptionsGroupInfo* pGroupInfo = reinterpret_cast(xTreeLB->get_id(*xParent).toInt64()); + if(!pPageInfo->m_xPage && pPageInfo->m_nPageId > 0) + { + if(!pGroupInfo->m_pInItemSet) + pGroupInfo->m_pInItemSet = pGroupInfo->m_pShell + ? pGroupInfo->m_pShell->CreateItemSet( pGroupInfo->m_nDialogId ) + : CreateItemSet( pGroupInfo->m_nDialogId ); + if(!pGroupInfo->m_pOutItemSet) + pGroupInfo->m_pOutItemSet = std::make_unique( + *pGroupInfo->m_pInItemSet->GetPool(), + pGroupInfo->m_pInItemSet->GetRanges()); + + pPageInfo->m_xPage = ::CreateGeneralTabPage(pPageInfo->m_nPageId, xTabBox.get(), this, *pGroupInfo->m_pInItemSet); + + if(!pPageInfo->m_xPage && pGroupInfo->m_pModule) + pPageInfo->m_xPage = pGroupInfo->m_pModule->CreateTabPage(pPageInfo->m_nPageId, xTabBox.get(), this, *pGroupInfo->m_pInItemSet); + + DBG_ASSERT( pPageInfo->m_xPage, "tabpage could not created"); + if ( pPageInfo->m_xPage ) + { + SvtViewOptions aTabPageOpt( EViewType::TabPage, OUString::number( pPageInfo->m_nPageId) ); + pPageInfo->m_xPage->SetUserData( GetViewOptUserItem( aTabPageOpt ) ); + pPageInfo->m_xPage->Reset( pGroupInfo->m_pInItemSet.get() ); + } + } + else if ( 0 == pPageInfo->m_nPageId && !pPageInfo->m_xExtPage ) + { + if ( !m_xContainerWinProvider.is() ) + { + m_xContainerWinProvider = awt::ContainerWindowProvider::create( ::comphelper::getProcessComponentContext() ); + } + + pPageInfo->m_xExtPage = std::make_unique( + xTabBox.get(), pPageInfo->m_sPageURL, pPageInfo->m_sEventHdl, m_xContainerWinProvider); + } + + if ( pPageInfo->m_xPage ) + { + if ( RID_SVXPAGE_COLOR != pPageInfo->m_nPageId && + pPageInfo->m_xPage->HasExchangeSupport()) + { + pPageInfo->m_xPage->ActivatePage(*pGroupInfo->m_pOutItemSet); + } + pPageInfo->m_xPage->set_visible(true); + } + else if ( pPageInfo->m_xExtPage ) + { + pPageInfo->m_xExtPage->Show(); + pPageInfo->m_xExtPage->ActivatePage(); + } + + { + OUString sTitleText = sTitle + + " - " + xTreeLB->get_text(*xParent) + + " - " + xTreeLB->get_text(*xEntry); + m_xDialog->set_title(sTitleText); + } + + xCurrentPageEntry = std::move(xEntry); + + if ( !bForgetSelection ) + { + if ( !pLastPageSaver ) + pLastPageSaver = new LastPageSaver; + if ( !bIsFromExtensionManager ) + pLastPageSaver->m_nLastPageId = pPageInfo->m_nPageId; + if ( pPageInfo->m_xExtPage ) + { + if ( bIsFromExtensionManager ) + pLastPageSaver->m_sLastPageURL_ExtMgr = pPageInfo->m_sPageURL; + else + pLastPageSaver->m_sLastPageURL_Tools = pPageInfo->m_sPageURL; + } + } + pNewPage = pPageInfo->m_xPage.get(); + + // fdo#58170 use current page's layout child HelpId, unless there isn't a current page + OString sHelpId(pNewPage ? pNewPage->GetHelpId() : OString()); + if (sHelpId.isEmpty()) + sHelpId = HID_OFADLG_TREELISTBOX; + xTreeLB->set_help_id(sHelpId); +} + +std::unique_ptr OfaTreeOptionsDialog::CreateItemSet( sal_uInt16 nId ) +{ + Reference< XLinguProperties > xProp( LinguMgr::GetLinguPropertySet() ); + std::unique_ptr pRet; + switch(nId) + { + case SID_GENERAL_OPTIONS: + { + pRet = std::make_unique( + SfxGetpApp()->GetPool(), + svl::Items< + SID_HTML_MODE, SID_HTML_MODE, + SID_ATTR_METRIC, SID_ATTR_METRIC, + SID_AUTOSPELL_CHECK, SID_AUTOSPELL_CHECK, + SID_ATTR_QUICKLAUNCHER, SID_ATTR_QUICKLAUNCHER, + SID_ATTR_YEAR2000, SID_ATTR_YEAR2000>{} ); + + SfxItemSet aOptSet( SfxGetpApp()->GetPool(), svl::Items{} ); + SfxGetpApp()->GetOptions(aOptSet); + pRet->Put(aOptSet); + + utl::MiscCfg aMisc; + SfxViewFrame* pViewFrame = SfxViewFrame::Current(); + if ( pViewFrame ) + { + const SfxPoolItem* pItem = nullptr; + SfxDispatcher* pDispatch = pViewFrame->GetDispatcher(); + + // miscellaneous - Year2000 + if( SfxItemState::DEFAULT <= pDispatch->QueryState( SID_ATTR_YEAR2000, pItem ) ) + pRet->Put( SfxUInt16Item( SID_ATTR_YEAR2000, static_cast(pItem)->GetValue() ) ); + else + pRet->Put( SfxUInt16Item( SID_ATTR_YEAR2000, static_cast(aMisc.GetYear2000()) ) ); + } + else + pRet->Put( SfxUInt16Item( SID_ATTR_YEAR2000, static_cast(aMisc.GetYear2000()) ) ); + + + // miscellaneous - Tabulator + pRet->Put(SfxBoolItem(SID_PRINTER_NOTFOUND_WARN, aMisc.IsNotFoundWarning())); + + SfxPrinterChangeFlags nFlag = aMisc.IsPaperSizeWarning() ? SfxPrinterChangeFlags::CHG_SIZE : SfxPrinterChangeFlags::NONE; + nFlag |= aMisc.IsPaperOrientationWarning() ? SfxPrinterChangeFlags::CHG_ORIENTATION : SfxPrinterChangeFlags::NONE; + pRet->Put( SfxFlagItem( SID_PRINTER_CHANGESTODOC, static_cast(nFlag) )); + + } + break; + case SID_LANGUAGE_OPTIONS : + { + pRet = std::make_unique( + SfxGetpApp()->GetPool(), + svl::Items< + SID_ATTR_CHAR_CJK_LANGUAGE, SID_ATTR_CHAR_CJK_LANGUAGE, + SID_ATTR_CHAR_CTL_LANGUAGE, SID_ATTR_CHAR_CTL_LANGUAGE, + SID_SET_DOCUMENT_LANGUAGE, SID_SET_DOCUMENT_LANGUAGE, + SID_ATTR_LANGUAGE, SID_ATTR_LANGUAGE, + SID_AUTOSPELL_CHECK, SID_AUTOSPELL_CHECK, + SID_OPT_LOCALE_CHANGED, SID_OPT_LOCALE_CHANGED>{}); + + // for linguistic + SfxHyphenRegionItem aHyphen( SID_ATTR_HYPHENREGION ); + + sal_Int16 nMinLead = 2, + nMinTrail = 2; + if (xProp.is()) + { + nMinLead = xProp->getHyphMinLeading(); + nMinTrail = xProp->getHyphMinTrailing(); + } + aHyphen.GetMinLead() = static_cast(nMinLead); + aHyphen.GetMinTrail() = static_cast(nMinTrail); + + SfxViewFrame* pViewFrame = SfxViewFrame::Current(); + if ( pViewFrame ) + { + const SfxPoolItem* pItem = nullptr; + SfxDispatcher* pDispatch = pViewFrame->GetDispatcher(); + if(SfxItemState::DEFAULT <= pDispatch->QueryState(SID_ATTR_LANGUAGE, pItem)) + pRet->Put( + SvxLanguageItem( + (static_cast(pItem) + ->GetLanguage()), + SID_ATTR_LANGUAGE)); + if(SfxItemState::DEFAULT <= pDispatch->QueryState(SID_ATTR_CHAR_CJK_LANGUAGE, pItem)) + pRet->Put( + SvxLanguageItem( + (static_cast(pItem) + ->GetLanguage()), + SID_ATTR_CHAR_CJK_LANGUAGE)); + if(SfxItemState::DEFAULT <= pDispatch->QueryState(SID_ATTR_CHAR_CTL_LANGUAGE, pItem)) + pRet->Put( + SvxLanguageItem( + (static_cast(pItem) + ->GetLanguage()), + SID_ATTR_CHAR_CTL_LANGUAGE)); + + pRet->Put(aHyphen); + if(SfxItemState::DEFAULT <= pDispatch->QueryState(SID_AUTOSPELL_CHECK, pItem)) + { + pRet->Put(std::unique_ptr(pItem->Clone())); + } + else + { + bool bVal = false; + if (xProp.is()) + { + bVal = xProp->getIsSpellAuto(); + } + + pRet->Put(SfxBoolItem(SID_AUTOSPELL_CHECK, bVal)); + } + } + pRet->Put( SfxBoolItem( SID_SET_DOCUMENT_LANGUAGE, bIsForSetDocumentLanguage ) ); + } + break; + case SID_INET_DLG : + pRet = std::make_unique( SfxGetpApp()->GetPool(), + svl::Items{} ); + SfxGetpApp()->GetOptions(*pRet); + break; + case SID_FILTER_DLG: + pRet = std::make_unique( + SfxGetpApp()->GetPool(), + svl::Items< + SID_ATTR_WARNALIENFORMAT, SID_ATTR_WARNALIENFORMAT, + SID_ATTR_DOCINFO, SID_ATTR_AUTOSAVEMINUTE, + SID_SAVEREL_INET, SID_SAVEREL_FSYS, + SID_ATTR_PRETTYPRINTING, SID_ATTR_PRETTYPRINTING>{} ); + SfxGetpApp()->GetOptions(*pRet); + break; + + case SID_SB_STARBASEOPTIONS: + pRet = std::make_unique( SfxGetpApp()->GetPool(), + svl::Items{} ); + ::offapp::ConnectionPoolConfig::GetOptions(*pRet); + svx::DbRegisteredNamesConfig::GetOptions(*pRet); + break; + + case SID_SCH_EDITOPTIONS: + { + SvxChartOptions aChartOpt; + pRet = std::make_unique( SfxGetpApp()->GetPool(), svl::Items{} ); + pRet->Put( SvxChartColorTableItem( SID_SCH_EDITOPTIONS, aChartOpt.GetDefaultColors() ) ); + break; + } + } + return pRet; +} + +void OfaTreeOptionsDialog::ApplyItemSet( sal_uInt16 nId, const SfxItemSet& rSet ) +{ + switch(nId) + { + case SID_GENERAL_OPTIONS: + { + utl::MiscCfg aMisc; + const SfxPoolItem* pItem = nullptr; + SfxItemSet aOptSet(SfxGetpApp()->GetPool(), svl::Items{} ); + aOptSet.Put(rSet); + if(aOptSet.Count()) + SfxGetpApp()->SetOptions( aOptSet ); + // get dispatcher anew, because SetOptions() might have destroyed the dispatcher + SfxViewFrame *pViewFrame = SfxViewFrame::Current(); + +// evaluate Year2000 + + sal_uInt16 nY2K = USHRT_MAX; + if( SfxItemState::SET == rSet.GetItemState( SID_ATTR_YEAR2000, false, &pItem ) ) + nY2K = static_cast(pItem)->GetValue(); + if( USHRT_MAX != nY2K ) + { + if ( pViewFrame ) + { + SfxDispatcher* pDispatch = pViewFrame->GetDispatcher(); + pDispatch->ExecuteList(SID_ATTR_YEAR2000, + SfxCallMode::ASYNCHRON, { pItem }); + } + aMisc.SetYear2000(nY2K); + } + + +// evaluate print + + if(SfxItemState::SET == rSet.GetItemState(SID_PRINTER_NOTFOUND_WARN, false, &pItem)) + aMisc.SetNotFoundWarning(static_cast(pItem)->GetValue()); + + if(SfxItemState::SET == rSet.GetItemState(SID_PRINTER_CHANGESTODOC, false, &pItem)) + { + const SfxFlagItem* pFlag = static_cast(pItem); + aMisc.SetPaperSizeWarning(bool(static_cast(pFlag->GetValue()) & SfxPrinterChangeFlags::CHG_SIZE )); + aMisc.SetPaperOrientationWarning(bool(static_cast(pFlag->GetValue()) & SfxPrinterChangeFlags::CHG_ORIENTATION )); + } + +// evaluate help options + + if ( SvtHelpOptions().IsHelpTips() != Help::IsQuickHelpEnabled() ) + SvtHelpOptions().IsHelpTips() ? Help::EnableQuickHelp() : Help::DisableQuickHelp(); + if ( SvtHelpOptions().IsExtendedHelp() != Help::IsBalloonHelpEnabled() ) + SvtHelpOptions().IsExtendedHelp() ? Help::EnableBalloonHelp() : Help::DisableBalloonHelp(); + } + break; + case SID_LANGUAGE_OPTIONS : + { + OfaTreeOptionsDialog::ApplyLanguageOptions(rSet); + } + break; + case SID_INET_DLG : + case SID_FILTER_DLG: + SfxGetpApp()->SetOptions( rSet ); + break; + + case SID_SB_STARBASEOPTIONS: + ::offapp::ConnectionPoolConfig::SetOptions( rSet ); + svx::DbRegisteredNamesConfig::SetOptions(rSet); + break; + + case SID_SCH_EDITOPTIONS: + // nothing to do. Chart options only apply to newly created charts + break; + + default: + { + OSL_FAIL( "Unhandled option in ApplyItemSet" ); + } + break; + } + +} +void OfaTreeOptionsDialog::ApplyLanguageOptions(const SfxItemSet& rSet) +{ + bool bSaveSpellCheck = false; + const SfxPoolItem* pItem = nullptr; + + Reference< XComponentContext > xContext( ::comphelper::getProcessComponentContext() ); + Reference< XLinguProperties > xProp = LinguProperties::create( xContext ); + if ( SfxItemState::SET == rSet.GetItemState(SID_ATTR_HYPHENREGION, false, &pItem ) ) + { + const SfxHyphenRegionItem* pHyphenItem = static_cast(pItem); + + xProp->setHyphMinLeading( static_cast(pHyphenItem->GetMinLead()) ); + xProp->setHyphMinTrailing( static_cast(pHyphenItem->GetMinTrail()) ); + bSaveSpellCheck = true; + } + + SfxViewFrame *pViewFrame = SfxViewFrame::Current(); + if ( pViewFrame ) + { + SfxDispatcher* pDispatch = pViewFrame->GetDispatcher(); + pItem = nullptr; + if(SfxItemState::SET == rSet.GetItemState( SID_ATTR_LANGUAGE, false, &pItem )) + { + pDispatch->ExecuteList(pItem->Which(), SfxCallMode::ASYNCHRON, { pItem }); + bSaveSpellCheck = true; + } + if(SfxItemState::SET == rSet.GetItemState( SID_ATTR_CHAR_CTL_LANGUAGE, false, &pItem )) + { + pDispatch->ExecuteList(pItem->Which(), SfxCallMode::ASYNCHRON, { pItem }); + bSaveSpellCheck = true; + } + if(SfxItemState::SET == rSet.GetItemState( SID_ATTR_CHAR_CJK_LANGUAGE, false, &pItem )) + { + pDispatch->ExecuteList(pItem->Which(), SfxCallMode::ASYNCHRON, { pItem }); + bSaveSpellCheck = true; + } + + if( SfxItemState::SET == rSet.GetItemState(SID_AUTOSPELL_CHECK, false, &pItem )) + { + bool bOnlineSpelling = static_cast(pItem)->GetValue(); + pDispatch->ExecuteList(SID_AUTOSPELL_CHECK, + SfxCallMode::ASYNCHRON|SfxCallMode::RECORD, { pItem }); + + xProp->setIsSpellAuto( bOnlineSpelling ); + } + + if( bSaveSpellCheck ) + { + //! the config item has changed since we modified the + //! property set it uses + pDispatch->Execute(SID_SPELLCHECKER_CHANGED, SfxCallMode::ASYNCHRON); + } + } + + if( SfxItemState::SET == rSet.GetItemState(SID_OPT_LOCALE_CHANGED, false, &pItem )) + { + SfxViewFrame* _pViewFrame = SfxViewFrame::GetFirst(); + while ( _pViewFrame ) + { + _pViewFrame->GetDispatcher()->ExecuteList(pItem->Which(), + SfxCallMode::ASYNCHRON, { pItem }); + _pViewFrame = SfxViewFrame::GetNext( *_pViewFrame ); + } + } +} + +static OUString getCurrentFactory_Impl( const Reference< XFrame >& _xFrame ) +{ + OUString sIdentifier; + Reference < XFrame > xCurrentFrame( _xFrame ); + Reference < XModuleManager2 > xModuleManager = ModuleManager::create(::comphelper::getProcessComponentContext()); + if ( !xCurrentFrame.is() ) + { + Reference< XDesktop2 > xDesktop = Desktop::create( ::comphelper::getProcessComponentContext() ); + xCurrentFrame = xDesktop->getCurrentFrame(); + } + + if ( xCurrentFrame.is() ) + { + try + { + sIdentifier = xModuleManager->identify( xCurrentFrame ); + } + catch ( css::frame::UnknownModuleException& ) + { + SAL_INFO( "cui.options", "unknown module" ); + } + catch ( Exception const & ) + { + TOOLS_WARN_EXCEPTION( "cui.options", "getActiveModule_Impl(): exception of XModuleManager::identify()" ); + } + } + + return sIdentifier; +} + +void OfaTreeOptionsDialog::Initialize( const Reference< XFrame >& _xFrame ) +{ + sal_uInt16 nGroup = 0; + + SvtOptionsDialogOptions aOptionsDlgOpt; + sal_uInt16 nPageId; + + // %PRODUCTNAME options + if ( !lcl_isOptionHidden( SID_GENERAL_OPTIONS, aOptionsDlgOpt ) ) + { + setGroupName("ProductName", CuiResId(SID_GENERAL_OPTIONS_RES[0].first)); + nGroup = AddGroup(CuiResId(SID_GENERAL_OPTIONS_RES[0].first), nullptr, nullptr, SID_GENERAL_OPTIONS ); + const sal_uInt16 nEnd = static_cast(SAL_N_ELEMENTS(SID_GENERAL_OPTIONS_RES)); + + for (sal_uInt16 i = 1; i < nEnd; ++i) + { + OUString sNewTitle = CuiResId(SID_GENERAL_OPTIONS_RES[i].first); + nPageId = SID_GENERAL_OPTIONS_RES[i].second; + if ( lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) ) + continue; + + // Disable Online Update page if service not installed + if( RID_SVXPAGE_ONLINEUPDATE == nPageId ) + { + try + { + Reference < XInterface > xService( setup::UpdateCheck::create( ::comphelper::getProcessComponentContext() ) ); + if( ! xService.is() ) + continue; + } + catch ( css::uno::DeploymentException& ) + { + continue; + } + } + + // Disable Basic IDE options, if experimental features are not enabled + if( RID_SVXPAGE_BASICIDE_OPTIONS == nPageId ) + { + SvtMiscOptions aMiscOpt; + if( ! aMiscOpt.IsExperimentalMode() ) + continue; + } + + AddTabPage( nPageId, sNewTitle, nGroup ); + } + } + + // Load and Save options + if ( !lcl_isOptionHidden( SID_FILTER_DLG, aOptionsDlgOpt ) ) + { + setGroupName( "LoadSave", CuiResId(SID_FILTER_DLG_RES[0].first) ); + nGroup = AddGroup( CuiResId(SID_FILTER_DLG_RES[0].first), nullptr, nullptr, SID_FILTER_DLG ); + for ( size_t i = 1; i < SAL_N_ELEMENTS(SID_FILTER_DLG_RES); ++i ) + { + nPageId = static_cast(SID_FILTER_DLG_RES[i].second); + if ( !lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) ) + AddTabPage( nPageId, CuiResId(SID_FILTER_DLG_RES[i].first), nGroup ); + } + } + + // Language options + SvtLanguageOptions aLanguageOptions; + if ( !lcl_isOptionHidden( SID_LANGUAGE_OPTIONS, aOptionsDlgOpt ) ) + { + setGroupName("LanguageSettings", CuiResId(SID_LANGUAGE_OPTIONS_RES[0].first)); + nGroup = AddGroup(CuiResId(SID_LANGUAGE_OPTIONS_RES[0].first), nullptr, nullptr, SID_LANGUAGE_OPTIONS ); + for (size_t i = 1; i < SAL_N_ELEMENTS(SID_LANGUAGE_OPTIONS_RES); ++i) + { + nPageId = static_cast(SID_LANGUAGE_OPTIONS_RES[i].second); + if ( lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) ) + continue; + if ( ( RID_SVXPAGE_JSEARCH_OPTIONS != nPageId || aLanguageOptions.IsJapaneseFindEnabled() ) && + ( RID_SVXPAGE_ASIAN_LAYOUT != nPageId || aLanguageOptions.IsAsianTypographyEnabled() ) && + ( RID_SVXPAGE_OPTIONS_CTL != nPageId || aLanguageOptions.IsCTLFontEnabled() ) ) + AddTabPage(nPageId, CuiResId(SID_LANGUAGE_OPTIONS_RES[i].first), nGroup); + } + } + + OUString aFactory = getCurrentFactory_Impl( _xFrame ); + DBG_ASSERT( GetModuleIdentifier( _xFrame ) == aFactory, "S H I T!!!" ); + + // Writer and Writer/Web options + SvtModuleOptions aModuleOpt; + if ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::WRITER ) ) + { + // text document + if ( aFactory == "com.sun.star.text.TextDocument" + || aFactory == "com.sun.star.text.WebDocument" + || aFactory == "com.sun.star.text.GlobalDocument" ) + { + SfxModule* pSwMod = SfxApplication::GetModule(SfxToolsModule::Writer); + if ( !lcl_isOptionHidden( SID_SW_EDITOPTIONS, aOptionsDlgOpt ) ) + { + if ( aFactory == "com.sun.star.text.WebDocument" ) + setGroupName( "WriterWeb", CuiResId(SID_SW_EDITOPTIONS_RES[0].first) ); + else + setGroupName( "Writer", CuiResId(SID_SW_EDITOPTIONS_RES[0].first) ); + nGroup = AddGroup(CuiResId(SID_SW_EDITOPTIONS_RES[0].first), pSwMod, pSwMod, SID_SW_EDITOPTIONS ); + for ( size_t i = 1; i < SAL_N_ELEMENTS(SID_SW_EDITOPTIONS_RES); ++i ) + { + nPageId = static_cast(SID_SW_EDITOPTIONS_RES[i].second); + if ( lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) ) + continue; + if ( ( RID_SW_TP_STD_FONT_CJK != nPageId || aLanguageOptions.IsCJKFontEnabled() ) && + ( RID_SW_TP_STD_FONT_CTL != nPageId || aLanguageOptions.IsCTLFontEnabled() ) && + ( RID_SW_TP_MAILCONFIG != nPageId || MailMergeCfg_Impl().IsEmailSupported() ) ) + AddTabPage( nPageId, CuiResId(SID_SW_EDITOPTIONS_RES[i].first), nGroup ); + } +#ifdef DBG_UTIL + AddTabPage( RID_SW_TP_OPTTEST_PAGE, "Internal Test", nGroup ); +#endif + } + + // HTML documents + if ( !lcl_isOptionHidden( SID_SW_ONLINEOPTIONS, aOptionsDlgOpt ) ) + { + nGroup = AddGroup(CuiResId(SID_SW_ONLINEOPTIONS_RES[0].first), pSwMod, pSwMod, SID_SW_ONLINEOPTIONS ); + for( size_t i = 1; i < SAL_N_ELEMENTS(SID_SW_ONLINEOPTIONS_RES); ++i ) + { + nPageId = static_cast(SID_SW_ONLINEOPTIONS_RES[i].second); + if ( !lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) ) + AddTabPage(nPageId, CuiResId(SID_SW_ONLINEOPTIONS_RES[i].first), nGroup); + } +#ifdef DBG_UTIL + AddTabPage( RID_SW_TP_OPTTEST_PAGE, "Internal Test", nGroup ); +#endif + } + } + } + + // Calc options + if ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::CALC ) ) + { + if ( aFactory == "com.sun.star.sheet.SpreadsheetDocument" ) + { + if ( !lcl_isOptionHidden( SID_SC_EDITOPTIONS, aOptionsDlgOpt ) ) + { + SfxModule* pScMod = SfxApplication::GetModule( SfxToolsModule::Calc ); + setGroupName( "Calc", CuiResId(SID_SC_EDITOPTIONS_RES[0].first) ); + nGroup = AddGroup( CuiResId(SID_SC_EDITOPTIONS_RES[0].first), pScMod, pScMod, SID_SC_EDITOPTIONS ); + const sal_uInt16 nCount = static_cast(SAL_N_ELEMENTS(SID_SC_EDITOPTIONS_RES)); + for ( sal_uInt16 i = 1; i < nCount; ++i ) + { + nPageId = static_cast(SID_SC_EDITOPTIONS_RES[i].second); + if ( lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) ) + continue; + + AddTabPage( nPageId, CuiResId(SID_SC_EDITOPTIONS_RES[i].first), nGroup ); + } + } + } + } + + // Impress options + SfxModule* pSdMod = SfxApplication::GetModule( SfxToolsModule::Draw ); + if ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::IMPRESS ) ) + { + if ( aFactory == "com.sun.star.presentation.PresentationDocument" ) + { + if ( !lcl_isOptionHidden( SID_SD_EDITOPTIONS, aOptionsDlgOpt ) ) + { + setGroupName( "Impress", CuiResId(SID_SD_EDITOPTIONS_RES[0].first) ); + nGroup = AddGroup( CuiResId(SID_SD_EDITOPTIONS_RES[0].first), pSdMod, pSdMod, SID_SD_EDITOPTIONS ); + const sal_uInt16 nCount = static_cast(SAL_N_ELEMENTS(SID_SD_EDITOPTIONS_RES)); + for ( sal_uInt16 i = 1; i < nCount; ++i ) + { + nPageId = static_cast(SID_SD_EDITOPTIONS_RES[i].second); + if ( lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) ) + continue; + + AddTabPage( nPageId, CuiResId(SID_SD_EDITOPTIONS_RES[i].first), nGroup ); + } + } + } + } + + // Draw options + if ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::DRAW ) ) + { + if ( aFactory == "com.sun.star.drawing.DrawingDocument" ) + { + if ( !lcl_isOptionHidden( SID_SD_GRAPHIC_OPTIONS, aOptionsDlgOpt ) ) + { + setGroupName( "Draw", CuiResId(SID_SD_GRAPHIC_OPTIONS_RES[0].first) ); + nGroup = AddGroup( CuiResId(SID_SD_GRAPHIC_OPTIONS_RES[0].first), pSdMod, pSdMod, SID_SD_GRAPHIC_OPTIONS ); + const sal_uInt16 nCount = static_cast(SAL_N_ELEMENTS(SID_SD_GRAPHIC_OPTIONS_RES)); + for ( sal_uInt16 i = 1; i < nCount; ++i ) + { + nPageId = static_cast(SID_SD_GRAPHIC_OPTIONS_RES[i].second); + if ( lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) ) + continue; + + AddTabPage( nPageId, CuiResId(SID_SD_GRAPHIC_OPTIONS_RES[i].first), nGroup ); + } + } + } + } + + // Math options + if ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::MATH ) ) + { + if ( aFactory == "com.sun.star.formula.FormulaProperties" ) + { + if ( !lcl_isOptionHidden( SID_SM_EDITOPTIONS, aOptionsDlgOpt ) ) + { + SfxModule* pSmMod = SfxApplication::GetModule(SfxToolsModule::Math); + setGroupName( "Math", CuiResId(SID_SM_EDITOPTIONS_RES[0].first) ); + nGroup = AddGroup(CuiResId(SID_SM_EDITOPTIONS_RES[0].first), pSmMod, pSmMod, SID_SM_EDITOPTIONS ); + for ( size_t i = 1; i < SAL_N_ELEMENTS(SID_SM_EDITOPTIONS_RES); ++i ) + { + nPageId = static_cast(SID_SM_EDITOPTIONS_RES[i].second); + if ( !lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) ) + AddTabPage( nPageId, CuiResId(SID_SM_EDITOPTIONS_RES[i].first), nGroup ); + } + } + } + } + + // Database - needed only if there is an application which integrates with databases + if ( !lcl_isOptionHidden( SID_SB_STARBASEOPTIONS, aOptionsDlgOpt ) && + ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::DATABASE ) + || aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::WRITER ) + || aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::CALC ) + ) ) + { + setGroupName( "Base", CuiResId(SID_SB_STARBASEOPTIONS_RES[0].first) ); + nGroup = AddGroup( CuiResId(SID_SB_STARBASEOPTIONS_RES[0].first), nullptr, nullptr, SID_SB_STARBASEOPTIONS ); + for ( size_t i = 1; i < SAL_N_ELEMENTS(SID_SB_STARBASEOPTIONS_RES); ++i ) + { + nPageId = static_cast(SID_SB_STARBASEOPTIONS_RES[i].second); + if ( !lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) ) + AddTabPage( nPageId, CuiResId(SID_SB_STARBASEOPTIONS_RES[i].first), nGroup ); + } + } + + // Chart options (always installed and active) + if ( !lcl_isOptionHidden( SID_SCH_EDITOPTIONS, aOptionsDlgOpt ) ) + { + setGroupName( "Charts", CuiResId(SID_SCH_EDITOPTIONS_RES[0].first) ); + nGroup = AddGroup( CuiResId(SID_SCH_EDITOPTIONS_RES[0].first), nullptr, nullptr, SID_SCH_EDITOPTIONS ); + for ( size_t i = 1; i < SAL_N_ELEMENTS(SID_SCH_EDITOPTIONS_RES); ++i ) + { + nPageId = static_cast(SID_SCH_EDITOPTIONS_RES[i].second); + if ( !lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) ) + AddTabPage( nPageId, CuiResId(SID_SCH_EDITOPTIONS_RES[i].first), nGroup ); + } + } + + // Internet options + if ( lcl_isOptionHidden( SID_INET_DLG, aOptionsDlgOpt ) ) + return; + + setGroupName("Internet", CuiResId(SID_INET_DLG_RES[0].first)); + nGroup = AddGroup(CuiResId(SID_INET_DLG_RES[0].first), nullptr, nullptr, SID_INET_DLG ); + + for ( size_t i = 1; i < SAL_N_ELEMENTS(SID_INET_DLG_RES); ++i ) + { + nPageId = static_cast(SID_INET_DLG_RES[i].second); + if ( lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) ) + continue; +#if defined(_WIN32) + // Disable E-mail tab-page on Windows + if ( nPageId == RID_SVXPAGE_INET_MAIL ) + continue; +#endif + AddTabPage( nPageId, CuiResId(SID_INET_DLG_RES[i].first), nGroup ); + } +} + +static bool isNodeActive( OptionsNode const * pNode, Module* pModule ) +{ + if ( pNode ) + { + // Node for all modules active? + if ( pNode->m_bAllModules ) + return true; + + // OOo-Nodes (Writer, Calc, Impress...) are active if node is already inserted + if ( !getGroupName( pNode->m_sId, false ).isEmpty() ) + return true; + + // no module -> not active + if ( !pModule ) + return false; + + // search node in active module + if ( pModule->m_bActive ) + { + for (auto const& j : pModule->m_aNodeList) + if ( j->m_sId == pNode->m_sId ) + return true; + } + } + return false; +} + +void OfaTreeOptionsDialog::LoadExtensionOptions( const OUString& rExtensionId ) +{ + std::unique_ptr pModule; + + // when called by Tools - Options then load nodes of active module + if ( rExtensionId.isEmpty() ) + { + pModule = LoadModule( GetModuleIdentifier( Reference< XFrame >() ) ); + } + + VectorOfNodes aNodeList = LoadNodes( pModule.get(), rExtensionId ); + InsertNodes( aNodeList ); +} + +OUString OfaTreeOptionsDialog::GetModuleIdentifier( const Reference< XFrame >& rFrame ) +{ + OUString sModule; + Reference < XFrame > xCurrentFrame( rFrame ); + Reference< XComponentContext > xContext = comphelper::getProcessComponentContext(); + Reference < XModuleManager2 > xModuleManager = ModuleManager::create(xContext); + + if ( !xCurrentFrame.is() ) + { + Reference < XDesktop2 > xDesktop = Desktop::create( xContext ); + xCurrentFrame = xDesktop->getCurrentFrame(); + } + + if ( xCurrentFrame.is() ) + { + try + { + sModule = xModuleManager->identify( xCurrentFrame ); + } + catch ( css::frame::UnknownModuleException& ) + { + SAL_INFO( "cui.options", "unknown module" ); + } + catch ( Exception const & ) + { + TOOLS_WARN_EXCEPTION( "cui.options", "OfaTreeOptionsDialog::GetModuleIdentifier(): exception of XModuleManager::identify()"); + } + } + return sModule; +} + +std::unique_ptr OfaTreeOptionsDialog::LoadModule( + const OUString& rModuleIdentifier ) +{ + std::unique_ptr pModule; + Reference< XNameAccess > xSet( + officecfg::Office::OptionsDialog::Modules::get()); + + const Sequence< OUString > seqNames = xSet->getElementNames(); + for ( const OUString& rModule : seqNames ) + { + if ( rModuleIdentifier == rModule ) + { + // current active module found + pModule.reset(new Module); + pModule->m_bActive = true; + + Reference< XNameAccess > xModAccess; + xSet->getByName( rModule ) >>= xModAccess; + if ( xModAccess.is() ) + { + // load the nodes of this module + Reference< XNameAccess > xNodeAccess; + xModAccess->getByName( "Nodes" ) >>= xNodeAccess; + if ( xNodeAccess.is() ) + { + const Sequence< OUString > xTemp = xNodeAccess->getElementNames(); + Reference< XNameAccess > xAccess; + sal_Int32 nIndex = -1; + for ( const OUString& rNode : xTemp) + { + xNodeAccess->getByName( rNode ) >>= xAccess; + if ( xAccess.is() ) + { + xAccess->getByName( "Index" ) >>= nIndex; + if ( nIndex < 0 ) + // append nodes with index < 0 + pModule->m_aNodeList.push_back( + std::unique_ptr(new OrderedEntry(nIndex, rNode))); + else + { + // search position of the node + std::vector::size_type y = 0; + for ( ; y < pModule->m_aNodeList.size(); ++y ) + { + sal_Int32 nNodeIdx = pModule->m_aNodeList[y]->m_nIndex; + if ( nNodeIdx < 0 || nNodeIdx > nIndex ) + break; + } + // and insert the node on this position + pModule->m_aNodeList.insert( + pModule->m_aNodeList.begin() + y, + std::unique_ptr(new OrderedEntry( nIndex, rNode )) ); + } + } + } + } + } + break; + } + } + return pModule; +} + +VectorOfNodes OfaTreeOptionsDialog::LoadNodes( + Module* pModule, const OUString& rExtensionId) +{ + VectorOfNodes aOutNodeList; + + Reference< XNameAccess > xSet( + officecfg::Office::OptionsDialog::Nodes::get()); + VectorOfNodes aNodeList; + const Sequence< OUString > seqNames = xSet->getElementNames(); + + for ( OUString const & sGroupName : seqNames ) + { + Reference< XNameAccess > xNodeAccess; + xSet->getByName( sGroupName ) >>= xNodeAccess; + + if ( xNodeAccess.is() ) + { + OUString sNodeId, sLabel, sPageURL; + bool bAllModules = false; + + sNodeId = sGroupName; + xNodeAccess->getByName( "Label" ) >>= sLabel; + xNodeAccess->getByName( "OptionsPage" ) >>= sPageURL; + xNodeAccess->getByName( "AllModules" ) >>= bAllModules; + + if ( sLabel.isEmpty() ) + sLabel = sGroupName; + OUString sTemp = getGroupName( sLabel, !rExtensionId.isEmpty() ); + if ( !sTemp.isEmpty() ) + sLabel = sTemp; + std::unique_ptr pNode(new OptionsNode(sNodeId, sLabel, bAllModules)); + + if ( rExtensionId.isEmpty() && !isNodeActive( pNode.get(), pModule ) ) + { + continue; + } + + Reference< XNameAccess > xLeavesSet; + xNodeAccess->getByName( "Leaves" ) >>= xLeavesSet; + if ( xLeavesSet.is() ) + { + const Sequence< OUString > seqLeaves = xLeavesSet->getElementNames(); + for ( OUString const & leafName : seqLeaves ) + { + Reference< XNameAccess > xLeaveAccess; + xLeavesSet->getByName( leafName ) >>= xLeaveAccess; + + if ( xLeaveAccess.is() ) + { + OUString sId, sLeafLabel, sEventHdl, sLeafURL, sLeafGrpId; + sal_Int32 nLeafGrpIdx = 0; + + xLeaveAccess->getByName( "Id" ) >>= sId; + xLeaveAccess->getByName( "Label" ) >>= sLeafLabel; + xLeaveAccess->getByName( "OptionsPage" ) >>= sLeafURL; + xLeaveAccess->getByName( "EventHandlerService" ) >>= sEventHdl; + xLeaveAccess->getByName( "GroupId" ) >>= sLeafGrpId; + xLeaveAccess->getByName( "GroupIndex" ) >>= nLeafGrpIdx; + + if ( rExtensionId.isEmpty() || sId == rExtensionId ) + { + std::unique_ptr pLeaf(new OptionsLeaf( + sLeafLabel, sLeafURL, sEventHdl, sLeafGrpId, nLeafGrpIdx )); + + if ( !sLeafGrpId.isEmpty() ) + { + bool bAlreadyOpened = false; + if ( !pNode->m_aGroupedLeaves.empty() ) + { + for (auto & rGroup : pNode->m_aGroupedLeaves) + { + if ( !rGroup.empty() && + rGroup[0]->m_sGroupId == sLeafGrpId ) + { + std::vector>::size_type l = 0; + for ( ; l < rGroup.size(); ++l ) + { + if ( rGroup[l]->m_nGroupIndex >= nLeafGrpIdx ) + break; + } + rGroup.insert( rGroup.begin() + l, std::move(pLeaf) ); + bAlreadyOpened = true; + break; + } + } + } + if ( !bAlreadyOpened ) + { + std::vector< std::unique_ptr > aGroupedLeaves; + aGroupedLeaves.push_back( std::move(pLeaf) ); + pNode->m_aGroupedLeaves.push_back( std::move(aGroupedLeaves) ); + } + } + else + pNode->m_aLeaves.push_back( std::move(pLeaf) ); + } + } + } + } + + // do not insert nodes without leaves + if ( !pNode->m_aLeaves.empty() || !pNode->m_aGroupedLeaves.empty() ) + { + pModule ? aNodeList.push_back( std::move(pNode) ) : aOutNodeList.push_back( std::move(pNode) ); + } + } + } + + if ( pModule && !aNodeList.empty() ) + { + for ( auto const & i: pModule->m_aNodeList ) + { + OUString sNodeId = i->m_sId; + for ( auto j = aNodeList.begin(); j != aNodeList.end(); ++j ) + { + if ( (*j)->m_sId == sNodeId ) + { + aOutNodeList.push_back( std::move(*j) ); + aNodeList.erase( j ); + break; + } + } + } + + for ( auto & i: aNodeList ) + aOutNodeList.push_back( std::move(i) ); + } + return aOutNodeList; +} + +static sal_uInt16 lcl_getGroupId( const OUString& rGroupName, const weld::TreeView& rTreeLB ) +{ + sal_uInt16 nRet = 0; + + std::unique_ptr xEntry = rTreeLB.make_iterator(); + bool bEntry = rTreeLB.get_iter_first(*xEntry); + while (bEntry) + { + if (!rTreeLB.get_iter_depth(*xEntry)) + { + OUString sTemp(rTreeLB.get_text(*xEntry)); + if (sTemp == rGroupName) + return nRet; + nRet++; + } + bEntry = rTreeLB.iter_next(*xEntry); + } + + return USHRT_MAX; +} + +static void lcl_insertLeaf( + OfaTreeOptionsDialog* pDlg, OptionsNode const * pNode, OptionsLeaf const * pLeaf, const weld::TreeView& rTreeLB ) +{ + sal_uInt16 nGrpId = lcl_getGroupId( pNode->m_sLabel, rTreeLB ); + if ( USHRT_MAX == nGrpId ) + { + sal_uInt16 nNodeGrpId = getGroupNodeId( pNode->m_sId ); + nGrpId = pDlg->AddGroup( pNode->m_sLabel, nullptr, nullptr, nNodeGrpId ); + } + OptionsPageInfo* pInfo = pDlg->AddTabPage( 0, pLeaf->m_sLabel, nGrpId ); + pInfo->m_sPageURL = pLeaf->m_sPageURL; + pInfo->m_sEventHdl = pLeaf->m_sEventHdl; +} + +void OfaTreeOptionsDialog::InsertNodes( const VectorOfNodes& rNodeList ) +{ + for (auto const& node : rNodeList) + { + if ( !node->m_aLeaves.empty() || !node->m_aGroupedLeaves.empty() ) + { + for ( auto const & j: node->m_aGroupedLeaves ) + { + for ( size_t k = 0; k < j.size(); ++k ) + { + lcl_insertLeaf( this, node.get(), j[k].get(), *xTreeLB ); + } + } + + for ( auto const & j: node->m_aLeaves ) + { + lcl_insertLeaf( this, node.get(), j.get(), *xTreeLB ); + } + } + } +} + +void OfaTreeOptionsDialog::SetNeedsRestart( svtools::RestartReason eReason) +{ + bNeedsRestart = true; + eRestartReason = eReason; +} + +short OfaTreeOptionsDialog::run() +{ + std::unique_ptr< SvxDicListChgClamp > pClamp; + if ( !bIsFromExtensionManager ) + { + // collect all DictionaryList Events while the dialog is executed + Reference xDictionaryList(LinguMgr::GetDictionaryList()); + pClamp.reset( new SvxDicListChgClamp( xDictionaryList ) ); + } + + short nRet = SfxOkDialogController::run(); + + if( RET_OK == nRet ) + { + ApplyItemSets(); + utl::ConfigManager::storeConfigItems(); + } + + return nRet; +} + +// class ExtensionsTabPage ----------------------------------------------- +ExtensionsTabPage::ExtensionsTabPage( + weld::Container* pParent, const OUString& rPageURL, + const OUString& rEvtHdl, const Reference< awt::XContainerWindowProvider >& rProvider ) + : m_pContainer(pParent) + , m_sPageURL(rPageURL) + , m_sEventHdl(rEvtHdl) + , m_xWinProvider(rProvider) +{ +} + +ExtensionsTabPage::~ExtensionsTabPage() +{ + Hide(); + DeactivatePage(); + + if ( m_xPage.is() ) + { + try + { + m_xPage->dispose(); + } + catch (const Exception&) + { + } + m_xPage.clear(); + } + + if ( m_xPageParent.is() ) + { + try + { + m_xPageParent->dispose(); + } + catch (const Exception&) + { + } + m_xPageParent.clear(); + } +} + +void ExtensionsTabPage::CreateDialogWithHandler() +{ + try + { + bool bWithHandler = !m_sEventHdl.isEmpty(); + if ( bWithHandler ) + { + Reference < XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() ); + m_xEventHdl.set( xFactory->createInstance( m_sEventHdl ), UNO_QUERY ); + } + + if ( !bWithHandler || m_xEventHdl.is() ) + { + m_xPageParent = m_pContainer->CreateChildFrame(); + Reference xParent(m_xPageParent, UNO_QUERY); + m_xPage = + m_xWinProvider->createContainerWindow( + m_sPageURL, OUString(), xParent, m_xEventHdl ); + + Reference< awt::XControl > xPageControl( m_xPage, UNO_QUERY ); + if ( xPageControl.is() ) + { + Reference< awt::XWindowPeer > xWinPeer( xPageControl->getPeer() ); + if ( xWinPeer.is() ) + { + VclPtr pWindow = VCLUnoHelper::GetWindow( xWinPeer ); + if ( pWindow ) + pWindow->SetStyle( pWindow->GetStyle() | WB_DIALOGCONTROL | WB_CHILDDLGCTRL ); + } + } + } + } + catch (const Exception&) + { + TOOLS_WARN_EXCEPTION( "cui.options", "ExtensionsTabPage::CreateDialogWithHandler(): exception of XDialogProvider2::createDialogWithHandler()"); + } +} + +bool ExtensionsTabPage::DispatchAction( const OUString& rAction ) +{ + bool bRet = false; + if ( m_xEventHdl.is() ) + { + try + { + bRet = m_xEventHdl->callHandlerMethod( m_xPage, Any( rAction ), "external_event" ); + } + catch ( Exception const & ) + { + TOOLS_WARN_EXCEPTION( "cui.options", "ExtensionsTabPage::DispatchAction(): exception of XDialogEventHandler::callHandlerMethod()" ); + } + } + return bRet; +} + +void ExtensionsTabPage::Show() +{ + if (!m_xPageParent.is()) + return; + + VclPtr xPageParent = VCLUnoHelper::GetWindow(m_xPageParent); + if (xPageParent) + { + // NoActivate otherwise setVisible will call Window::Show which will grab + // focus to the page by default + xPageParent->Show(true, ShowFlags::NoActivate); + } + + m_xPageParent->setVisible(true); +} + +void ExtensionsTabPage::Hide() +{ + if (!m_xPageParent.is()) + return; + m_xPageParent->setVisible(false); +} + +void ExtensionsTabPage::ActivatePage() +{ + if ( !m_xPage.is() ) + { + CreateDialogWithHandler(); + + if ( m_xPage.is() ) + { + auto aWindowRect = m_xPageParent->getPosSize(); + m_xPage->setPosSize(0, 0, aWindowRect.Width, aWindowRect.Height, awt::PosSize::POSSIZE); + if ( !m_sEventHdl.isEmpty() ) + DispatchAction( "initialize" ); + } + } + + if ( m_xPage.is() ) + { + m_xPage->setVisible( true ); + } +} + +void ExtensionsTabPage::DeactivatePage() +{ + if ( m_xPage.is() ) + m_xPage->setVisible( false ); +} + +void ExtensionsTabPage::ResetPage() +{ + DispatchAction( "back" ); + ActivatePage(); +} + +void ExtensionsTabPage::SavePage() +{ + DispatchAction( "ok" ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/tsaurls.cxx b/cui/source/options/tsaurls.cxx new file mode 100644 index 000000000..62f08298d --- /dev/null +++ b/cui/source/options/tsaurls.cxx @@ -0,0 +1,126 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include + +#include "tsaurls.hxx" + +using namespace ::com::sun::star; + +TSAURLsDialog::TSAURLsDialog(weld::Window* pParent) + : GenericDialogController(pParent, "cui/ui/tsaurldialog.ui", "TSAURLDialog") + , m_xAddBtn(m_xBuilder->weld_button("add")) + , m_xDeleteBtn(m_xBuilder->weld_button("delete")) + , m_xOKBtn(m_xBuilder->weld_button("ok")) + , m_xURLListBox(m_xBuilder->weld_tree_view("urls")) + , m_xEnterAUrl(m_xBuilder->weld_label("enteraurl")) +{ + m_xURLListBox->set_size_request(m_xURLListBox->get_approximate_digit_width() * 28, + m_xURLListBox->get_height_rows(8)); + m_xOKBtn->set_sensitive(false); + + m_xAddBtn->connect_clicked( LINK( this, TSAURLsDialog, AddHdl_Impl ) ); + m_xDeleteBtn->connect_clicked( LINK( this, TSAURLsDialog, DeleteHdl_Impl ) ); + m_xOKBtn->connect_clicked( LINK( this, TSAURLsDialog, OKHdl_Impl ) ); + m_xURLListBox->connect_changed( LINK( this, TSAURLsDialog, SelectHdl ) ); + + try + { + std::optional> aUserSetTSAURLs(officecfg::Office::Common::Security::Scripting::TSAURLs::get()); + if (aUserSetTSAURLs) + { + const css::uno::Sequence& rUserSetTSAURLs = *aUserSetTSAURLs; + for (auto const& userSetTSAURL : rUserSetTSAURLs) + { + AddTSAURL(userSetTSAURL); + } + } + } + catch (const uno::Exception &) + { + TOOLS_WARN_EXCEPTION("cui.options", "TSAURLsDialog::TSAURLsDialog()"); + } + + if (m_xURLListBox->get_selected_index() == -1) + { + m_xDeleteBtn->set_sensitive(false); + } +} + +IMPL_LINK_NOARG(TSAURLsDialog, OKHdl_Impl, weld::Button&, void) +{ + std::shared_ptr batch(comphelper::ConfigurationChanges::create()); + + officecfg::Office::Common::Security::Scripting::TSAURLs::set(comphelper::containerToSequence(m_aURLs), batch); + batch->commit(); + + m_xDialog->response(RET_OK); +} + +TSAURLsDialog::~TSAURLsDialog() +{ +} + +void TSAURLsDialog::AddTSAURL(const OUString& rURL) +{ + m_aURLs.insert(rURL); + + m_xURLListBox->freeze(); + m_xURLListBox->clear(); + + for (auto const& url : m_aURLs) + { + m_xURLListBox->append_text(url); + } + + m_xURLListBox->thaw(); +} + +IMPL_LINK_NOARG(TSAURLsDialog, AddHdl_Impl, weld::Button&, void) +{ + OUString aURL; + OUString aDesc(m_xEnterAUrl->get_label()); + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateSvxNameDialog(m_xDialog.get(), aURL, aDesc)); + + if (pDlg->Execute() == RET_OK) + { + pDlg->GetName(aURL); + AddTSAURL(aURL); + m_xOKBtn->set_sensitive(true); + } + m_xURLListBox->unselect_all(); + // After operations in a ListBox we have nothing selected + m_xDeleteBtn->set_sensitive(false); +} + +IMPL_LINK_NOARG(TSAURLsDialog, SelectHdl, weld::TreeView&, void) +{ + m_xDeleteBtn->set_sensitive(true); +} + +IMPL_LINK_NOARG(TSAURLsDialog, DeleteHdl_Impl, weld::Button&, void) +{ + int nSel = m_xURLListBox->get_selected_index(); + if (nSel == -1) + return; + + m_aURLs.erase(m_xURLListBox->get_text(nSel)); + m_xURLListBox->remove(nSel); + m_xURLListBox->unselect_all(); + // After operations in a ListBox we have nothing selected + m_xDeleteBtn->set_sensitive(false); + m_xOKBtn->set_sensitive(true); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/tsaurls.hxx b/cui/source/options/tsaurls.hxx new file mode 100644 index 000000000..ddec756bd --- /dev/null +++ b/cui/source/options/tsaurls.hxx @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_CUI_SOURCE_OPTIONS_TSAURLS_HXX +#define INCLUDED_CUI_SOURCE_OPTIONS_TSAURLS_HXX + +#include + +#include + +class TSAURLsDialog : public weld::GenericDialogController +{ +private: + std::unique_ptr m_xAddBtn; + std::unique_ptr m_xDeleteBtn; + std::unique_ptr m_xOKBtn; + std::unique_ptr m_xURLListBox; + std::unique_ptr m_xEnterAUrl; + + DECL_LINK(AddHdl_Impl, weld::Button&, void); + DECL_LINK(DeleteHdl_Impl, weld::Button&, void); + DECL_LINK(OKHdl_Impl, weld::Button&, void); + // After operations in a TreeView we have nothing selected + // Is Selected element handler for the TreeView + DECL_LINK(SelectHdl, weld::TreeView&, void); + + std::set m_aURLs; + + void AddTSAURL(const OUString& rURL); + +public: + explicit TSAURLsDialog(weld::Window* pParent); + virtual ~TSAURLsDialog() override; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/webconninfo.cxx b/cui/source/options/webconninfo.cxx new file mode 100644 index 000000000..1d3abe82f --- /dev/null +++ b/cui/source/options/webconninfo.cxx @@ -0,0 +1,227 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "webconninfo.hxx" +#include +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; + + +namespace svx +{ + +// class WebConnectionInfoDialog ----------------------------------------- + +WebConnectionInfoDialog::WebConnectionInfoDialog(weld::Window* pParent) + : GenericDialogController(pParent, "cui/ui/storedwebconnectiondialog.ui", "StoredWebConnectionDialog") + , m_nPos( -1 ) + , m_xRemoveBtn(m_xBuilder->weld_button("remove")) + , m_xRemoveAllBtn(m_xBuilder->weld_button("removeall")) + , m_xChangeBtn(m_xBuilder->weld_button("change")) + , m_xPasswordsLB(m_xBuilder->weld_tree_view("logins")) +{ + std::vector aWidths; + aWidths.push_back(m_xPasswordsLB->get_approximate_digit_width() * 50); + m_xPasswordsLB->set_column_fixed_widths(aWidths); + m_xPasswordsLB->set_size_request(m_xPasswordsLB->get_approximate_digit_width() * 70, + m_xPasswordsLB->get_height_rows(8)); + + m_xPasswordsLB->connect_column_clicked(LINK(this, WebConnectionInfoDialog, HeaderBarClickedHdl)); + + FillPasswordList(); + + m_xRemoveBtn->connect_clicked( LINK( this, WebConnectionInfoDialog, RemovePasswordHdl ) ); + m_xRemoveAllBtn->connect_clicked( LINK( this, WebConnectionInfoDialog, RemoveAllPasswordsHdl ) ); + m_xChangeBtn->connect_clicked( LINK( this, WebConnectionInfoDialog, ChangePasswordHdl ) ); + m_xPasswordsLB->connect_changed( LINK( this, WebConnectionInfoDialog, EntrySelectedHdl ) ); + + m_xRemoveBtn->set_sensitive( false ); + m_xChangeBtn->set_sensitive( false ); + + m_xPasswordsLB->make_sorted(); +} + +WebConnectionInfoDialog::~WebConnectionInfoDialog() +{ +} + +IMPL_LINK(WebConnectionInfoDialog, HeaderBarClickedHdl, int, nColumn, void) +{ + if (nColumn == 0) // only the first column is sorted + { + m_xPasswordsLB->set_sort_order(!m_xPasswordsLB->get_sort_order()); + } +} + +void WebConnectionInfoDialog::FillPasswordList() +{ + try + { + uno::Reference< task::XPasswordContainer2 > xMasterPasswd( + task::PasswordContainer::create(comphelper::getProcessComponentContext())); + + if ( xMasterPasswd->isPersistentStoringAllowed() ) + { + uno::Reference< task::XInteractionHandler > xInteractionHandler = + task::InteractionHandler::createWithParent(comphelper::getProcessComponentContext(), nullptr); + + const uno::Sequence< task::UrlRecord > aURLEntries = xMasterPasswd->getAllPersistent( xInteractionHandler ); + sal_Int32 nCount = 0; + for ( task::UrlRecord const & urlEntry : aURLEntries ) + { + for ( auto const & user : urlEntry.UserList ) + { + m_xPasswordsLB->append(OUString::number(nCount), urlEntry.Url); + m_xPasswordsLB->set_text(nCount, user.UserName, 1); + ++nCount; + } + } + + // remember pos of first url container entry. + m_nPos = nCount; + + const uno::Sequence< OUString > aUrls + = xMasterPasswd->getUrls( true /* OnlyPersistent */ ); + + for ( OUString const & url : aUrls ) + { + m_xPasswordsLB->append(OUString::number(nCount), url); + m_xPasswordsLB->set_text(nCount, "*"); + ++nCount; + } + } + } + catch( uno::Exception& ) + {} +} + + +IMPL_LINK_NOARG(WebConnectionInfoDialog, RemovePasswordHdl, weld::Button&, void) +{ + try + { + int nEntry = m_xPasswordsLB->get_selected_index(); + if (nEntry != -1) + { + OUString aURL = m_xPasswordsLB->get_text(nEntry, 0); + OUString aUserName = m_xPasswordsLB->get_text(nEntry, 1); + + uno::Reference< task::XPasswordContainer2 > xPasswdContainer( + task::PasswordContainer::create(comphelper::getProcessComponentContext())); + + int nPos = m_xPasswordsLB->get_id(nEntry).toInt32(); + if ( nPos < m_nPos ) + { + xPasswdContainer->removePersistent( aURL, aUserName ); + } + else + { + xPasswdContainer->removeUrl( aURL ); + } + + m_xPasswordsLB->remove(nEntry); + } + } + catch( uno::Exception& ) + {} +} + +IMPL_LINK_NOARG(WebConnectionInfoDialog, RemoveAllPasswordsHdl, weld::Button&, void) +{ + try + { + uno::Reference< task::XPasswordContainer2 > xPasswdContainer( + task::PasswordContainer::create(comphelper::getProcessComponentContext())); + + // should the master password be requested before? + xPasswdContainer->removeAllPersistent(); + + const uno::Sequence< OUString > aUrls + = xPasswdContainer->getUrls( true /* OnlyPersistent */ ); + for ( OUString const & url : aUrls ) + xPasswdContainer->removeUrl( url ); + + m_xPasswordsLB->clear(); + } + catch( uno::Exception& ) + {} +} + +IMPL_LINK_NOARG(WebConnectionInfoDialog, ChangePasswordHdl, weld::Button&, void) +{ + try + { + int nEntry = m_xPasswordsLB->get_selected_index(); + if (nEntry != -1) + { + OUString aURL = m_xPasswordsLB->get_text(nEntry, 0); + OUString aUserName = m_xPasswordsLB->get_text(nEntry, 1); + + ::comphelper::SimplePasswordRequest* pPasswordRequest + = new ::comphelper::SimplePasswordRequest; + uno::Reference< task::XInteractionRequest > rRequest( pPasswordRequest ); + + uno::Reference< task::XInteractionHandler > xInteractionHandler = + task::InteractionHandler::createWithParent(comphelper::getProcessComponentContext(), m_xDialog->GetXWindow()); + xInteractionHandler->handle( rRequest ); + + if ( pPasswordRequest->isPassword() ) + { + OUString aNewPass = pPasswordRequest->getPassword(); + uno::Sequence aPasswd { aNewPass }; + + uno::Reference< task::XPasswordContainer2 > xPasswdContainer( + task::PasswordContainer::create(comphelper::getProcessComponentContext())); + xPasswdContainer->addPersistent( + aURL, aUserName, aPasswd, xInteractionHandler ); + } + } + } + catch( uno::Exception& ) + {} +} + + +IMPL_LINK_NOARG(WebConnectionInfoDialog, EntrySelectedHdl, weld::TreeView&, void) +{ + int nEntry = m_xPasswordsLB->get_selected_index(); + if (nEntry == -1) + { + m_xRemoveBtn->set_sensitive(false); + m_xChangeBtn->set_sensitive(false); + } + else + { + m_xRemoveBtn->set_sensitive(true); + + // url container entries (-> use system credentials) have + // no password + int nPos = m_xPasswordsLB->get_id(nEntry).toInt32(); + m_xChangeBtn->set_sensitive(nPos < m_nPos); + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/webconninfo.hxx b/cui/source/options/webconninfo.hxx new file mode 100644 index 000000000..95d524c8a --- /dev/null +++ b/cui/source/options/webconninfo.hxx @@ -0,0 +1,54 @@ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_OPTIONS_WEBCONNINFO_HXX +#define INCLUDED_CUI_SOURCE_OPTIONS_WEBCONNINFO_HXX + +#include + +namespace svx +{ + class WebConnectionInfoDialog : public weld::GenericDialogController + { + private: + sal_Int32 m_nPos; + + std::unique_ptr m_xRemoveBtn; + std::unique_ptr m_xRemoveAllBtn; + std::unique_ptr m_xChangeBtn; + std::unique_ptr m_xPasswordsLB; + + DECL_LINK( HeaderBarClickedHdl, int, void ); + DECL_LINK( RemovePasswordHdl, weld::Button&, void ); + DECL_LINK( RemoveAllPasswordsHdl, weld::Button&, void ); + DECL_LINK( ChangePasswordHdl, weld::Button&, void ); + DECL_LINK( EntrySelectedHdl, weld::TreeView&, void ); + + void FillPasswordList(); + + public: + explicit WebConnectionInfoDialog(weld::Window* pParent); + virtual ~WebConnectionInfoDialog() override; + }; + + +} + + +#endif // INCLUDED_CUI_SOURCE_OPTIONS_WEBCONNINFO_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/align.cxx b/cui/source/tabpages/align.cxx new file mode 100644 index 000000000..30965cf9c --- /dev/null +++ b/cui/source/tabpages/align.cxx @@ -0,0 +1,774 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define IID_BOTTOMLOCK 1 +#define IID_TOPLOCK 2 +#define IID_CELLLOCK 3 + +namespace svx { + +const sal_uInt16 AlignmentTabPage::s_pRanges[] = +{ + SID_ATTR_ALIGN_HOR_JUSTIFY,SID_ATTR_ALIGN_VER_JUSTIFY, + SID_ATTR_ALIGN_STACKED,SID_ATTR_ALIGN_LINEBREAK, + SID_ATTR_ALIGN_INDENT,SID_ATTR_ALIGN_INDENT, + SID_ATTR_ALIGN_DEGREES,SID_ATTR_ALIGN_DEGREES, + SID_ATTR_ALIGN_LOCKPOS,SID_ATTR_ALIGN_LOCKPOS, + SID_ATTR_ALIGN_HYPHENATION,SID_ATTR_ALIGN_HYPHENATION, + SID_ATTR_ALIGN_ASIANVERTICAL,SID_ATTR_ALIGN_ASIANVERTICAL, + SID_ATTR_FRAMEDIRECTION,SID_ATTR_FRAMEDIRECTION, + SID_ATTR_ALIGN_SHRINKTOFIT,SID_ATTR_ALIGN_SHRINKTOFIT, + 0 +}; + + +namespace { + +template +void lcl_MaybeResetAlignToDistro( + weld::ComboBox& rLB, sal_uInt16 nListPos, const SfxItemSet& rCoreAttrs, sal_uInt16 nWhichAlign, sal_uInt16 nWhichJM, JustEnumType eBlock) +{ + const SfxPoolItem* pItem; + if (rCoreAttrs.GetItemState(nWhichAlign, true, &pItem) != SfxItemState::SET) + // alignment not set. + return; + + const SfxEnumItemInterface* p = static_cast(pItem); + JustContainerType eVal = static_cast(p->GetEnumValue()); + if (eVal != eBlock) + // alignment is not 'justify'. No need to go further. + return; + + if (rCoreAttrs.GetItemState(nWhichJM, true, &pItem) != SfxItemState::SET) + // justification method is not set. + return; + + p = static_cast(pItem); + SvxCellJustifyMethod eMethod = static_cast(p->GetEnumValue()); + if (eMethod == SvxCellJustifyMethod::Distribute) + { + // Select the 'distribute' entry in the specified list box. + rLB.set_active(nListPos); + } +} + +void lcl_SetJustifyMethodToItemSet(SfxItemSet& rSet, const SfxItemSet& rOldSet, sal_uInt16 nWhichJM, const weld::ComboBox& rLB, sal_uInt16 nListPos) +{ + SvxCellJustifyMethod eJM = SvxCellJustifyMethod::Auto; + if (rLB.get_active() == nListPos) + eJM = SvxCellJustifyMethod::Distribute; + + // tdf#129300 If it would create no change, don't force it + const SvxJustifyMethodItem& rOldItem = static_cast(rOldSet.Get(nWhichJM)); + if (rOldItem.GetValue() == eJM) + { + rSet.InvalidateItem(nWhichJM); + return; + } + + SvxJustifyMethodItem aItem(eJM, nWhichJM); + rSet.Put(aItem); +} + +}//namespace + +AlignmentTabPage::AlignmentTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs) + : SfxTabPage(pPage, pController, "cui/ui/cellalignment.ui", "CellAlignPage", &rCoreAttrs) + , m_aVsRefEdge(nullptr) + // text alignment + , m_xLbHorAlign(m_xBuilder->weld_combo_box("comboboxHorzAlign")) + , m_xFtIndent(m_xBuilder->weld_label("labelIndent")) + , m_xEdIndent(m_xBuilder->weld_metric_spin_button("spinIndentFrom", FieldUnit::POINT)) + , m_xFtVerAlign(m_xBuilder->weld_label("labelVertAlign")) + , m_xLbVerAlign(m_xBuilder->weld_combo_box("comboboxVertAlign")) + //text rotation + , m_xFtRotate(m_xBuilder->weld_label("labelDegrees")) + , m_xNfRotate(m_xBuilder->weld_metric_spin_button("spinDegrees", FieldUnit::DEGREE)) + , m_xFtRefEdge(m_xBuilder->weld_label("labelRefEdge")) + //Asian mode + , m_xCbStacked(m_xBuilder->weld_check_button("checkVertStack")) + , m_xCbAsianMode(m_xBuilder->weld_check_button("checkAsianMode")) + // Properties + , m_xBoxDirection(m_xBuilder->weld_widget("boxDirection")) + , m_xBtnWrap(m_xBuilder->weld_check_button("checkWrapTextAuto")) + , m_xBtnHyphen(m_xBuilder->weld_check_button("checkHyphActive")) + , m_xBtnShrink(m_xBuilder->weld_check_button("checkShrinkFitCellSize")) + , m_xLbFrameDir(new svx::FrameDirectionListBox(m_xBuilder->weld_combo_box("comboTextDirBox"))) + //ValueSet hover strings + , m_xFtBotLock(m_xBuilder->weld_label("labelSTR_BOTTOMLOCK")) + , m_xFtTopLock(m_xBuilder->weld_label("labelSTR_TOPLOCK")) + , m_xFtCelLock(m_xBuilder->weld_label("labelSTR_CELLLOCK")) + , m_xFtABCD(m_xBuilder->weld_label("labelABCD")) + , m_xAlignmentFrame(m_xBuilder->weld_widget("alignment")) + , m_xOrientFrame(m_xBuilder->weld_widget("orientation")) + , m_xPropertiesFrame(m_xBuilder->weld_widget("properties")) + , m_xVsRefEdge(new weld::CustomWeld(*m_xBuilder, "references", m_aVsRefEdge)) + , m_xCtrlDial(new DialControl) + , m_xCtrlDialWin(new weld::CustomWeld(*m_xBuilder, "dialcontrol", *m_xCtrlDial)) +{ + m_xCtrlDial->SetLinkedField(m_xNfRotate.get()); + m_xCtrlDial->SetText(m_xFtABCD->get_label()); + + InitVsRefEgde(); + + m_xLbHorAlign->connect_changed(LINK(this, AlignmentTabPage, UpdateEnableHdl)); + + m_xCbStacked->connect_toggled(LINK(this, AlignmentTabPage, StackedClickHdl)); + m_xCbAsianMode->connect_toggled(LINK(this, AlignmentTabPage, AsianModeClickHdl)); + m_xBtnWrap->connect_toggled(LINK(this, AlignmentTabPage, WrapClickHdl)); + m_xBtnHyphen->connect_toggled(LINK(this, AlignmentTabPage, HyphenClickHdl)); + m_xBtnShrink->connect_toggled(LINK(this, AlignmentTabPage, ShrinkClickHdl)); + + // Asian vertical mode + m_xCbAsianMode->set_visible(SvtCJKOptions().IsVerticalTextEnabled()); + + m_xLbFrameDir->append(SvxFrameDirection::Horizontal_LR_TB, SvxResId(RID_SVXSTR_FRAMEDIR_LTR)); + m_xLbFrameDir->append(SvxFrameDirection::Horizontal_RL_TB, SvxResId(RID_SVXSTR_FRAMEDIR_RTL)); + m_xLbFrameDir->append(SvxFrameDirection::Environment, SvxResId(RID_SVXSTR_FRAMEDIR_SUPER)); + + // This page needs ExchangeSupport. + SetExchangeSupport(); +} + +AlignmentTabPage::~AlignmentTabPage() +{ + m_xCtrlDialWin.reset(); + m_xCtrlDial.reset(); + m_xVsRefEdge.reset(); + m_xLbFrameDir.reset(); +} + +std::unique_ptr AlignmentTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet) +{ + return std::make_unique(pPage, pController, *rAttrSet); +} + +bool AlignmentTabPage::FillItemSet( SfxItemSet* rSet ) +{ + const SfxItemSet& rOldSet = GetItemSet(); + + bool bChanged = SfxTabPage::FillItemSet(rSet); + + sal_uInt16 nWhich = GetWhich(SID_ATTR_ALIGN_HOR_JUSTIFY); + if (m_xLbHorAlign->get_value_changed_from_saved()) + { + SvxCellHorJustify eJustify(SvxCellHorJustify::Standard); + switch (m_xLbHorAlign->get_active_id().toInt32()) + { + case ALIGNDLG_HORALIGN_STD: + eJustify = SvxCellHorJustify::Standard; + break; + case ALIGNDLG_HORALIGN_LEFT: + eJustify = SvxCellHorJustify::Left; + break; + case ALIGNDLG_HORALIGN_CENTER: + eJustify = SvxCellHorJustify::Center; + break; + case ALIGNDLG_HORALIGN_RIGHT: + eJustify = SvxCellHorJustify::Right; + break; + case ALIGNDLG_HORALIGN_BLOCK: + case ALIGNDLG_HORALIGN_DISTRIBUTED: + eJustify = SvxCellHorJustify::Block; + break; + case ALIGNDLG_HORALIGN_FILL: + eJustify = SvxCellHorJustify::Repeat; + break; + } + rSet->Put(SvxHorJustifyItem(eJustify, nWhich)); + bChanged = true; + } + else if (SfxItemState::DEFAULT == rOldSet.GetItemState(nWhich, false)) + rSet->InvalidateItem(nWhich); + + nWhich = GetWhich(SID_ATTR_ALIGN_INDENT); + if (m_xEdIndent->get_value_changed_from_saved()) + { + const SfxUInt16Item* pIndentItem = static_cast(GetOldItem( + *rSet, SID_ATTR_ALIGN_INDENT)); + assert(pIndentItem); + std::unique_ptr pNewIndentItem(pIndentItem->Clone()); + pNewIndentItem->SetValue(m_xEdIndent->get_value(FieldUnit::TWIP)); + rSet->Put(*pNewIndentItem); + bChanged = true; + } + else if (SfxItemState::DEFAULT == rOldSet.GetItemState(nWhich, false)) + rSet->InvalidateItem(nWhich); + + nWhich = GetWhich(SID_ATTR_ALIGN_VER_JUSTIFY); + if (m_xLbVerAlign->get_value_changed_from_saved()) + { + SvxCellVerJustify eJustify(SvxCellVerJustify::Standard); + switch (m_xLbVerAlign->get_active_id().toInt32()) + { + case ALIGNDLG_VERALIGN_STD: + eJustify = SvxCellVerJustify::Standard; + break; + case ALIGNDLG_VERALIGN_TOP: + eJustify = SvxCellVerJustify::Top; + break; + case ALIGNDLG_VERALIGN_MID: + eJustify = SvxCellVerJustify::Center; + break; + case ALIGNDLG_VERALIGN_BOTTOM: + eJustify = SvxCellVerJustify::Bottom; + break; + case ALIGNDLG_VERALIGN_BLOCK: + case ALIGNDLG_VERALIGN_DISTRIBUTED: + eJustify = SvxCellVerJustify::Block; + break; + } + rSet->Put(SvxVerJustifyItem(eJustify, nWhich)); + bChanged = true; + } + else if (SfxItemState::DEFAULT == rOldSet.GetItemState(nWhich, false)) + rSet->InvalidateItem(nWhich); + + nWhich = GetWhich(SID_ATTR_ALIGN_DEGREES); + if (m_xNfRotate->get_value_changed_from_saved()) + { + const SdrAngleItem* pAngleItem = static_cast(GetOldItem( + *rSet, SID_ATTR_ALIGN_DEGREES)); + assert(pAngleItem); + std::unique_ptr pNewAngleItem(pAngleItem->Clone()); + pNewAngleItem->SetValue(m_xCtrlDial->GetRotation()); + rSet->Put(*pNewAngleItem); + bChanged = true; + } + else if (SfxItemState::DEFAULT == rOldSet.GetItemState(nWhich, false)) + rSet->InvalidateItem(nWhich); + + nWhich = GetWhich(SID_ATTR_ALIGN_LOCKPOS); + if (m_aVsRefEdge.IsValueChangedFromSaved()) + { + switch (m_aVsRefEdge.GetSelectedItemId()) + { + case IID_CELLLOCK: + rSet->Put(SvxRotateModeItem(SvxRotateMode::SVX_ROTATE_MODE_STANDARD, nWhich)); + break; + case IID_TOPLOCK: + rSet->Put(SvxRotateModeItem(SvxRotateMode::SVX_ROTATE_MODE_TOP, nWhich)); + break; + case IID_BOTTOMLOCK: + rSet->Put(SvxRotateModeItem(SvxRotateMode::SVX_ROTATE_MODE_BOTTOM, nWhich)); + break; + default: + m_aVsRefEdge.SetNoSelection(); + break; + } + bChanged = true; + } + else if (SfxItemState::DEFAULT == rOldSet.GetItemState(nWhich, false)) + rSet->InvalidateItem(nWhich); + + nWhich = GetWhich(SID_ATTR_ALIGN_STACKED); + if (m_xCbStacked->get_state_changed_from_saved()) + { + const SfxBoolItem* pStackItem = static_cast(GetOldItem( + *rSet, SID_ATTR_ALIGN_STACKED)); + assert(pStackItem); + std::unique_ptr pNewStackItem(pStackItem->Clone()); + pNewStackItem->SetValue(m_xCbStacked->get_active()); + rSet->Put(*pNewStackItem); + bChanged = true; + } + else if (SfxItemState::DEFAULT == rOldSet.GetItemState(nWhich, false)) + rSet->InvalidateItem(nWhich); + + nWhich = GetWhich(SID_ATTR_ALIGN_ASIANVERTICAL); + if (m_xCbAsianMode->get_state_changed_from_saved()) + { + rSet->Put(SfxBoolItem(nWhich, m_xCbAsianMode->get_active())); + bChanged = true; + } + else if (SfxItemState::DEFAULT == rOldSet.GetItemState(nWhich, false)) + rSet->InvalidateItem(nWhich); + + nWhich = GetWhich(SID_ATTR_ALIGN_LINEBREAK); + if (m_xBtnWrap->get_state_changed_from_saved()) + { + const SfxBoolItem* pWrapItem = static_cast(GetOldItem( + *rSet, SID_ATTR_ALIGN_LINEBREAK)); + assert(pWrapItem); + std::unique_ptr pNewWrapItem(pWrapItem->Clone()); + pNewWrapItem->SetValue(m_xBtnWrap->get_active()); + rSet->Put(*pNewWrapItem); + bChanged = true; + } + else if (SfxItemState::DEFAULT == rOldSet.GetItemState(nWhich, false)) + rSet->InvalidateItem(nWhich); + + nWhich = GetWhich(SID_ATTR_ALIGN_HYPHENATION); + if (m_xBtnHyphen->get_state_changed_from_saved()) + { + const SfxBoolItem* pHyphItem = static_cast(GetOldItem( + *rSet, SID_ATTR_ALIGN_HYPHENATION)); + assert(pHyphItem); + std::unique_ptr pNewHyphItem(pHyphItem->Clone()); + pNewHyphItem->SetValue(m_xBtnHyphen->get_active()); + rSet->Put(*pNewHyphItem); + bChanged = true; + } + else if (SfxItemState::DEFAULT == rOldSet.GetItemState(nWhich, false)) + rSet->InvalidateItem(nWhich); + + nWhich = GetWhich(SID_ATTR_ALIGN_SHRINKTOFIT); + if (m_xBtnShrink->get_state_changed_from_saved()) + { + const SfxBoolItem* pShrinkItem = static_cast(GetOldItem( + *rSet, SID_ATTR_ALIGN_SHRINKTOFIT)); + assert(pShrinkItem); + std::unique_ptr pNewShrinkItem(pShrinkItem->Clone()); + pNewShrinkItem->SetValue(m_xBtnShrink->get_active()); + rSet->Put(*pNewShrinkItem); + bChanged = true; + } + else if (SfxItemState::DEFAULT == rOldSet.GetItemState(nWhich, false)) + rSet->InvalidateItem(nWhich); + + if (m_xLbFrameDir->get_visible()) + { + nWhich = GetWhich(SID_ATTR_FRAMEDIRECTION); + if (m_xLbFrameDir->get_value_changed_from_saved()) + { + SvxFrameDirection eDir = m_xLbFrameDir->get_active_id(); + rSet->Put(SvxFrameDirectionItem(eDir, nWhich)); + bChanged = true; + } + else if (SfxItemState::DEFAULT == rOldSet.GetItemState(nWhich, false)) + rSet->InvalidateItem(nWhich); + } + + // Special treatment for distributed alignment; we need to set the justify + // method to 'distribute' to distinguish from the normal justification. + sal_uInt16 nWhichHorJM = GetWhich(SID_ATTR_ALIGN_HOR_JUSTIFY_METHOD); + lcl_SetJustifyMethodToItemSet(*rSet, rOldSet, nWhichHorJM, *m_xLbHorAlign, ALIGNDLG_HORALIGN_DISTRIBUTED); + if (!bChanged) + bChanged = HasAlignmentChanged(*rSet, nWhichHorJM); + + sal_uInt16 nWhichVerJM = GetWhich(SID_ATTR_ALIGN_VER_JUSTIFY_METHOD); + lcl_SetJustifyMethodToItemSet(*rSet, rOldSet, nWhichVerJM, *m_xLbVerAlign, ALIGNDLG_VERALIGN_DISTRIBUTED); + if (!bChanged) + bChanged = HasAlignmentChanged(*rSet, nWhichVerJM); + + return bChanged; +} + +namespace +{ + void ResetBool(sal_uInt16 nWhich, const SfxItemSet* pSet, weld::CheckButton& rBtn, weld::TriStateEnabled& rTriState) + { + SfxItemState eState = pSet->GetItemState(nWhich); + switch (eState) + { + case SfxItemState::UNKNOWN: + rBtn.hide(); + rTriState.bTriStateEnabled = false; + break; + case SfxItemState::DISABLED: + case SfxItemState::READONLY: + rBtn.set_sensitive(false); + rTriState.bTriStateEnabled = false; + break; + case SfxItemState::DONTCARE: + rBtn.set_state(TRISTATE_INDET); + rTriState.bTriStateEnabled = true; + break; + case SfxItemState::DEFAULT: + case SfxItemState::SET: + { + const SfxBoolItem& rItem = static_cast(pSet->Get(nWhich)); + rBtn.set_state(static_cast(rItem.GetValue())); + rTriState.bTriStateEnabled = false; + break; + } + } + rBtn.save_state(); + } +} + +void AlignmentTabPage::Reset(const SfxItemSet* pCoreAttrs) +{ + SfxTabPage::Reset(pCoreAttrs); + + ResetBool(GetWhich(SID_ATTR_ALIGN_STACKED), pCoreAttrs, *m_xCbStacked, m_aStackedState); + ResetBool(GetWhich(SID_ATTR_ALIGN_ASIANVERTICAL), pCoreAttrs, *m_xCbAsianMode, m_aAsianModeState); + ResetBool(GetWhich(SID_ATTR_ALIGN_LINEBREAK), pCoreAttrs, *m_xBtnWrap, m_aWrapState); + ResetBool(GetWhich(SID_ATTR_ALIGN_HYPHENATION), pCoreAttrs, *m_xBtnHyphen, m_aHyphenState); + ResetBool(GetWhich(SID_ATTR_ALIGN_SHRINKTOFIT), pCoreAttrs, *m_xBtnShrink, m_aShrinkState); + + sal_uInt16 nWhich = GetWhich(SID_ATTR_ALIGN_HOR_JUSTIFY); + SfxItemState eState = pCoreAttrs->GetItemState(nWhich); + switch (eState) + { + case SfxItemState::UNKNOWN: + m_xLbHorAlign->hide(); + break; + case SfxItemState::DISABLED: + case SfxItemState::READONLY: + m_xLbHorAlign->set_sensitive(false); + break; + case SfxItemState::DONTCARE: + m_xLbHorAlign->set_active(-1); + break; + case SfxItemState::DEFAULT: + case SfxItemState::SET: + { + const SvxHorJustifyItem& rJustifyItem = static_cast(pCoreAttrs->Get(nWhich)); + switch (rJustifyItem.GetValue()) + { + case SvxCellHorJustify::Standard: + m_xLbHorAlign->set_active_id(OUString::number(ALIGNDLG_HORALIGN_STD)); + break; + case SvxCellHorJustify::Left: + m_xLbHorAlign->set_active_id(OUString::number(ALIGNDLG_HORALIGN_LEFT)); + break; + case SvxCellHorJustify::Center: + m_xLbHorAlign->set_active_id(OUString::number(ALIGNDLG_HORALIGN_CENTER)); + break; + case SvxCellHorJustify::Right: + m_xLbHorAlign->set_active_id(OUString::number(ALIGNDLG_HORALIGN_RIGHT)); + break; + case SvxCellHorJustify::Block: + m_xLbHorAlign->set_active_id(OUString::number(ALIGNDLG_HORALIGN_BLOCK)); + break; + case SvxCellHorJustify::Repeat: + m_xLbHorAlign->set_active_id(OUString::number(ALIGNDLG_HORALIGN_FILL)); + break; + } + break; + } + } + + nWhich = GetWhich(SID_ATTR_ALIGN_INDENT); + eState = pCoreAttrs->GetItemState(nWhich); + switch (eState) + { + case SfxItemState::UNKNOWN: + m_xEdIndent->hide(); + m_xFtIndent->hide(); + break; + case SfxItemState::DISABLED: + case SfxItemState::READONLY: + m_xEdIndent->set_sensitive(false); + break; + case SfxItemState::DONTCARE: + m_xEdIndent->set_text(""); + break; + case SfxItemState::DEFAULT: + case SfxItemState::SET: + { + const SfxUInt16Item& rIndentItem = static_cast(pCoreAttrs->Get(nWhich)); + m_xEdIndent->set_value(rIndentItem.GetValue(), FieldUnit::TWIP); + break; + } + } + + nWhich = GetWhich(SID_ATTR_ALIGN_VER_JUSTIFY); + eState = pCoreAttrs->GetItemState(nWhich); + switch (eState) + { + case SfxItemState::UNKNOWN: + m_xLbVerAlign->hide(); + m_xFtVerAlign->hide(); + break; + case SfxItemState::DISABLED: + case SfxItemState::READONLY: + m_xLbVerAlign->set_sensitive(false); + break; + case SfxItemState::DONTCARE: + m_xLbVerAlign->set_active(-1); + break; + case SfxItemState::DEFAULT: + case SfxItemState::SET: + { + const SvxVerJustifyItem& rJustifyItem = static_cast(pCoreAttrs->Get(nWhich)); + switch (rJustifyItem.GetValue()) + { + case SvxCellVerJustify::Standard: + m_xLbVerAlign->set_active_id(OUString::number(ALIGNDLG_VERALIGN_STD)); + break; + case SvxCellVerJustify::Top: + m_xLbVerAlign->set_active_id(OUString::number(ALIGNDLG_VERALIGN_TOP)); + break; + case SvxCellVerJustify::Center: + m_xLbVerAlign->set_active_id(OUString::number(ALIGNDLG_VERALIGN_MID)); + break; + case SvxCellVerJustify::Bottom: + m_xLbVerAlign->set_active_id(OUString::number(ALIGNDLG_VERALIGN_BOTTOM)); + break; + case SvxCellVerJustify::Block: + m_xLbVerAlign->set_active_id(OUString::number(ALIGNDLG_VERALIGN_BLOCK)); + break; + } + break; + } + } + + nWhich = GetWhich(SID_ATTR_ALIGN_DEGREES); + eState = pCoreAttrs->GetItemState(nWhich); + switch (eState) + { + case SfxItemState::UNKNOWN: + m_xNfRotate->hide(); + m_xCtrlDialWin->hide(); + break; + case SfxItemState::DISABLED: + case SfxItemState::READONLY: + m_xNfRotate->set_sensitive(false); + m_xCtrlDialWin->set_sensitive(false); + break; + case SfxItemState::DONTCARE: + m_xCtrlDial->SetNoRotation(); + break; + case SfxItemState::DEFAULT: + case SfxItemState::SET: + { + const SdrAngleItem& rAlignItem = static_cast(pCoreAttrs->Get(nWhich)); + m_xCtrlDial->SetRotation(rAlignItem.GetValue()); + break; + } + } + + nWhich = GetWhich(SID_ATTR_ALIGN_LOCKPOS); + eState = pCoreAttrs->GetItemState(nWhich); + switch (eState) + { + case SfxItemState::UNKNOWN: + m_xVsRefEdge->hide(); + break; + case SfxItemState::DISABLED: + case SfxItemState::READONLY: + m_xVsRefEdge->set_sensitive(false); + break; + case SfxItemState::DONTCARE: + m_aVsRefEdge.SetNoSelection(); + break; + case SfxItemState::DEFAULT: + case SfxItemState::SET: + { + const SvxRotateModeItem& rRotateModeItem = static_cast(pCoreAttrs->Get(nWhich)); + switch (rRotateModeItem.GetValue()) + { + case SvxRotateMode::SVX_ROTATE_MODE_STANDARD: + m_aVsRefEdge.SelectItem(IID_CELLLOCK); + break; + case SvxRotateMode::SVX_ROTATE_MODE_TOP: + m_aVsRefEdge.SelectItem(IID_TOPLOCK); + break; + case SvxRotateMode::SVX_ROTATE_MODE_BOTTOM: + m_aVsRefEdge.SelectItem(IID_BOTTOMLOCK); + break; + default: + m_aVsRefEdge.SetNoSelection(); + break; + } + break; + } + } + m_aVsRefEdge.SaveValue(); + + //text direction + nWhich = GetWhich(SID_ATTR_FRAMEDIRECTION); + eState = pCoreAttrs->GetItemState(nWhich); + switch (eState) + { + case SfxItemState::UNKNOWN: + m_xLbFrameDir->hide(); + break; + case SfxItemState::DISABLED: + case SfxItemState::READONLY: + m_xLbFrameDir->set_sensitive(false); + break; + case SfxItemState::DONTCARE: + m_xLbFrameDir->set_active(-1); + break; + case SfxItemState::DEFAULT: + case SfxItemState::SET: + { + const SvxFrameDirectionItem& rFrameDirItem = static_cast(pCoreAttrs->Get(nWhich)); + m_xLbFrameDir->set_active_id(rFrameDirItem.GetValue()); + break; + } + } + + + // Special treatment for distributed alignment; we need to set the justify + // method to 'distribute' to distinguish from the normal justification. + + lcl_MaybeResetAlignToDistro( + *m_xLbHorAlign, ALIGNDLG_HORALIGN_DISTRIBUTED, *pCoreAttrs, + GetWhich(SID_ATTR_ALIGN_HOR_JUSTIFY), GetWhich(SID_ATTR_ALIGN_HOR_JUSTIFY_METHOD), + SvxCellHorJustify::Block); + + lcl_MaybeResetAlignToDistro( + *m_xLbVerAlign, ALIGNDLG_VERALIGN_DISTRIBUTED, *pCoreAttrs, + GetWhich(SID_ATTR_ALIGN_VER_JUSTIFY), GetWhich(SID_ATTR_ALIGN_VER_JUSTIFY_METHOD), + SvxCellVerJustify::Block); + + m_xLbHorAlign->save_value(); + m_xLbFrameDir->save_value(); + m_xLbVerAlign->save_value(); + m_xNfRotate->save_value(); + m_xEdIndent->save_value(); + + UpdateEnableControls(); +} + +DeactivateRC AlignmentTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if( _pSet ) + FillItemSet( _pSet ); + return DeactivateRC::LeavePage; +} + +void AlignmentTabPage::InitVsRefEgde() +{ + // remember selection - is deleted in call to ValueSet::Clear() + sal_uInt16 nSel = m_aVsRefEdge.GetSelectedItemId(); + + Image aBottomLock(StockImage::Yes, RID_SVXBMP_BOTTOMLOCK); + Image aTopLock(StockImage::Yes, RID_SVXBMP_TOPLOCK); + Image aCellLock(StockImage::Yes, RID_SVXBMP_CELLLOCK); + + m_aVsRefEdge.Clear(); + m_aVsRefEdge.SetStyle(m_aVsRefEdge.GetStyle() | WB_ITEMBORDER | WB_DOUBLEBORDER); + + m_aVsRefEdge.SetColCount(3); + m_aVsRefEdge.InsertItem(IID_BOTTOMLOCK, aBottomLock, m_xFtBotLock->get_label()); + m_aVsRefEdge.InsertItem(IID_TOPLOCK, aTopLock, m_xFtTopLock->get_label()); + m_aVsRefEdge.InsertItem(IID_CELLLOCK, aCellLock, m_xFtCelLock->get_label()); + m_aVsRefEdge.SetOptimalSize(); + + m_aVsRefEdge.SelectItem( nSel ); +} + +void AlignmentTabPage::UpdateEnableControls() +{ + const sal_Int32 nHorAlign = m_xLbHorAlign->get_active(); + bool bHorLeft = (nHorAlign == ALIGNDLG_HORALIGN_LEFT); + bool bHorBlock = (nHorAlign == ALIGNDLG_HORALIGN_BLOCK); + bool bHorFill = (nHorAlign == ALIGNDLG_HORALIGN_FILL); + bool bHorDist = (nHorAlign == ALIGNDLG_HORALIGN_DISTRIBUTED); + + // indent edit field only for left alignment + m_xFtIndent->set_sensitive( bHorLeft ); + m_xEdIndent->set_sensitive( bHorLeft ); + + // stacked disabled for fill alignment + m_xCbStacked->set_sensitive(!bHorFill); + + // hyphenation only for automatic line breaks or for block alignment + m_xBtnHyphen->set_sensitive( m_xBtnWrap->get_active() || bHorBlock ); + + // shrink only without automatic line break, and not for block, fill or distribute. + m_xBtnShrink->set_sensitive( (m_xBtnWrap->get_state() == TRISTATE_FALSE) && !bHorBlock && !bHorFill && !bHorDist ); + + // visibility of frames + m_xAlignmentFrame->set_visible(m_xLbHorAlign->get_visible() || m_xEdIndent->get_visible() || + m_xLbVerAlign->get_visible()); + m_xOrientFrame->set_visible(m_xCtrlDialWin->get_visible() || m_xVsRefEdge->get_visible() || + m_xCbStacked->get_visible() || m_xCbAsianMode->get_visible()); + m_xPropertiesFrame->set_visible(m_xBtnWrap->get_visible() || m_xBtnHyphen->get_visible() || + m_xBtnShrink->get_visible() || m_xLbFrameDir->get_visible()); + + bool bStackedText = m_xCbStacked->get_active(); + // windows to be disabled, if stacked text is turned ON + m_xFtRotate->set_sensitive(!bStackedText); + m_xFtRefEdge->set_sensitive(!bStackedText); + m_xVsRefEdge->set_sensitive(!bStackedText); + // windows to be disabled, if stacked text is turned OFF + m_xCbAsianMode->set_sensitive(bStackedText); + // rotation/stacked disabled for fill alignment/stacked + m_xCtrlDialWin->set_sensitive(!bHorFill && !bStackedText); + m_xNfRotate->set_sensitive(!bHorFill && !bStackedText); +} + +bool AlignmentTabPage::HasAlignmentChanged( const SfxItemSet& rNew, sal_uInt16 nWhich ) const +{ + const SfxItemSet& rOld = GetItemSet(); + const SfxPoolItem* pItem; + SvxCellJustifyMethod eMethodOld = SvxCellJustifyMethod::Auto; + SvxCellJustifyMethod eMethodNew = SvxCellJustifyMethod::Auto; + if (rOld.GetItemState(nWhich, true, &pItem) == SfxItemState::SET) + { + const SfxEnumItemInterface* p = static_cast(pItem); + eMethodOld = static_cast(p->GetEnumValue()); + } + + if (rNew.GetItemState(nWhich, true, &pItem) == SfxItemState::SET) + { + const SfxEnumItemInterface* p = static_cast(pItem); + eMethodNew = static_cast(p->GetEnumValue()); + } + + return eMethodOld != eMethodNew; +} + +IMPL_LINK(AlignmentTabPage, StackedClickHdl, weld::ToggleButton&, rToggle, void) +{ + m_aStackedState.ButtonToggled(rToggle); + UpdateEnableControls(); +} + +IMPL_LINK(AlignmentTabPage, AsianModeClickHdl, weld::ToggleButton&, rToggle, void) +{ + m_aAsianModeState.ButtonToggled(rToggle); +} + +IMPL_LINK(AlignmentTabPage, WrapClickHdl, weld::ToggleButton&, rToggle, void) +{ + m_aWrapState.ButtonToggled(rToggle); + UpdateEnableControls(); +} + +IMPL_LINK(AlignmentTabPage, HyphenClickHdl, weld::ToggleButton&, rToggle, void) +{ + m_aHyphenState.ButtonToggled(rToggle); +} + +IMPL_LINK(AlignmentTabPage, ShrinkClickHdl, weld::ToggleButton&, rToggle, void) +{ + m_aShrinkState.ButtonToggled(rToggle); +} + +IMPL_LINK_NOARG(AlignmentTabPage, UpdateEnableHdl, weld::ComboBox&, void) +{ + UpdateEnableControls(); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/autocdlg.cxx b/cui/source/tabpages/autocdlg.cxx new file mode 100644 index 000000000..449e231d9 --- /dev/null +++ b/cui/source/tabpages/autocdlg.cxx @@ -0,0 +1,2355 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +static LanguageType eLastDialogLanguage = LANGUAGE_SYSTEM; + +using namespace ::com::sun::star::util; +using namespace ::com::sun::star; + +OfaAutoCorrDlg::OfaAutoCorrDlg(weld::Window* pParent, const SfxItemSet* _pSet ) + : SfxTabDialogController(pParent, "cui/ui/autocorrectdialog.ui", "AutoCorrectDialog", _pSet) + , m_xLanguageBox(m_xBuilder->weld_widget("langbox")) + , m_xLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box("lang"))) +{ + bool bShowSWOptions = false; + bool bOpenSmartTagOptions = false; + + if ( _pSet ) + { + const SfxBoolItem* pItem = SfxItemSet::GetItem(_pSet, SID_AUTO_CORRECT_DLG, false); + if ( pItem && pItem->GetValue() ) + bShowSWOptions = true; + + const SfxBoolItem* pItem2 = SfxItemSet::GetItem(_pSet, SID_OPEN_SMARTTAGOPTIONS, false); + if ( pItem2 && pItem2->GetValue() ) + bOpenSmartTagOptions = true; + } + + AddTabPage("options", OfaAutocorrOptionsPage::Create, nullptr); + AddTabPage("applypage", OfaSwAutoFmtOptionsPage::Create, nullptr); + AddTabPage("wordcompletion", OfaAutoCompleteTabPage::Create, nullptr); + AddTabPage("smarttags", OfaSmartTagOptionsTabPage::Create, nullptr); + + if (!bShowSWOptions) + { + RemoveTabPage("applypage"); + RemoveTabPage("wordcompletion"); + RemoveTabPage("smarttags"); + } + else + { + // remove smart tag tab page if no extensions are installed + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + SvxSwAutoFormatFlags& rOpt = pAutoCorrect->GetSwFlags(); + if (!rOpt.pSmartTagMgr || 0 == rOpt.pSmartTagMgr->NumberOfRecognizers()) + RemoveTabPage("smarttags"); + + RemoveTabPage("options"); + } + + AddTabPage("replace", OfaAutocorrReplacePage::Create, nullptr); + AddTabPage("exceptions", OfaAutocorrExceptPage::Create, nullptr); + AddTabPage("localized", OfaQuoteTabPage::Create, nullptr); + + // initialize languages + //! LANGUAGE_NONE is displayed as '[All]' and the LanguageType + //! will be set to LANGUAGE_UNDETERMINED + SvxLanguageListFlags nLangList = SvxLanguageListFlags::WESTERN; + + if( SvtLanguageOptions().IsCTLFontEnabled() ) + nLangList |= SvxLanguageListFlags::CTL; + if( SvtLanguageOptions().IsCJKFontEnabled() ) + nLangList |= SvxLanguageListFlags::CJK; + m_xLanguageLB->SetLanguageList( nLangList, true, true ); + m_xLanguageLB->set_active_id( LANGUAGE_NONE ); + int nPos = m_xLanguageLB->get_active(); + DBG_ASSERT(nPos != -1, "listbox entry missing" ); + m_xLanguageLB->set_id(nPos, LANGUAGE_UNDETERMINED); + + // Initializing doesn't work for static on linux - therefore here + if (LANGUAGE_SYSTEM == eLastDialogLanguage) + eLastDialogLanguage = Application::GetSettings().GetLanguageTag().getLanguageType(); + + LanguageType nSelectLang = LANGUAGE_UNDETERMINED; + nPos = m_xLanguageLB->find_id(eLastDialogLanguage); + if (nPos != -1) + nSelectLang = eLastDialogLanguage; + m_xLanguageLB->set_active_id(nSelectLang); + + m_xLanguageLB->connect_changed(LINK(this, OfaAutoCorrDlg, SelectLanguageHdl)); + + if ( bOpenSmartTagOptions ) + SetCurPageId("smarttags"); +} + +OfaAutoCorrDlg::~OfaAutoCorrDlg() +{ +} + +void OfaAutoCorrDlg::EnableLanguage(bool bEnable) +{ + m_xLanguageBox->set_sensitive(bEnable); +} + +static bool lcl_FindEntry(weld::TreeView& rLB, const OUString& rEntry, + CollatorWrapper const & rCmpClass) +{ + int nCount = rLB.n_children(); + int nSelPos = rLB.get_selected_index(); + for (int i = 0; i < nCount; i++) + { + if (0 == rCmpClass.compareString(rEntry, rLB.get_text(i))) + { + rLB.select(i); + return true; + } + } + if (nSelPos != -1) + rLB.unselect(nSelPos); + return false; +} + +IMPL_LINK_NOARG(OfaAutoCorrDlg, SelectLanguageHdl, weld::ComboBox&, void) +{ + LanguageType eNewLang = m_xLanguageLB->get_active_id(); + // save old settings and fill anew + if(eNewLang == eLastDialogLanguage) + return; + + OString sPageId = GetCurPageId(); + if (sPageId == "replace") + { + OfaAutocorrReplacePage* pPage = static_cast(GetTabPage(sPageId)); + assert(pPage); + pPage->SetLanguage(eNewLang); + } + else if (sPageId == "exceptions") + { + OfaAutocorrExceptPage* pPage = static_cast(GetTabPage(sPageId)); + assert(pPage); + pPage->SetLanguage(eNewLang); + } +} + +OfaAutocorrOptionsPage::OfaAutocorrOptionsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/acoroptionspage.ui", "AutocorrectOptionsPage", &rSet) + , m_sInput(CuiResId(RID_SVXSTR_USE_REPLACE)) + , m_sDoubleCaps(CuiResId(RID_SVXSTR_CPTL_STT_WORD)) + , m_sStartCap(CuiResId(RID_SVXSTR_CPTL_STT_SENT)) + , m_sBoldUnderline(CuiResId(RID_SVXSTR_BOLD_UNDER)) + , m_sURL(CuiResId(RID_SVXSTR_DETECT_URL)) + , m_sNoDblSpaces(CuiResId(RID_SVXSTR_NO_DBL_SPACES)) + , m_sDash(CuiResId(RID_SVXSTR_DASH)) + , m_sAccidentalCaps(CuiResId(RID_SVXSTR_CORRECT_ACCIDENTAL_CAPS_LOCK)) + , m_xCheckLB(m_xBuilder->weld_tree_view("checklist")) +{ + std::vector aWidths; + aWidths.push_back(m_xCheckLB->get_checkbox_column_width()); + m_xCheckLB->set_column_fixed_widths(aWidths); + m_xCheckLB->set_size_request(-1, m_xCheckLB->get_height_rows(10)); +} + +OfaAutocorrOptionsPage::~OfaAutocorrOptionsPage() +{ +} + +std::unique_ptr OfaAutocorrOptionsPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rSet) +{ + return std::make_unique(pPage, pController, *rSet); +} + +#define CBCOL_FIRST 0 +#define CBCOL_SECOND 1 +#define CBCOL_BOTH 2 + +bool OfaAutocorrOptionsPage::FillItemSet( SfxItemSet* ) +{ + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + ACFlags nFlags = pAutoCorrect->GetFlags(); + + int nPos = 0; + pAutoCorrect->SetAutoCorrFlag(ACFlags::Autocorrect, m_xCheckLB->get_toggle(nPos++, CBCOL_FIRST) == TRISTATE_TRUE); + pAutoCorrect->SetAutoCorrFlag(ACFlags::CapitalStartWord, m_xCheckLB->get_toggle(nPos++, CBCOL_FIRST) == TRISTATE_TRUE); + pAutoCorrect->SetAutoCorrFlag(ACFlags::CapitalStartSentence, m_xCheckLB->get_toggle(nPos++, CBCOL_FIRST) == TRISTATE_TRUE); + pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgWeightUnderl, m_xCheckLB->get_toggle(nPos++, CBCOL_FIRST) == TRISTATE_TRUE); + pAutoCorrect->SetAutoCorrFlag(ACFlags::SetINetAttr, m_xCheckLB->get_toggle(nPos++, CBCOL_FIRST) == TRISTATE_TRUE); + pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgToEnEmDash, m_xCheckLB->get_toggle(nPos++, CBCOL_FIRST) == TRISTATE_TRUE); + pAutoCorrect->SetAutoCorrFlag(ACFlags::IgnoreDoubleSpace, m_xCheckLB->get_toggle(nPos++, CBCOL_FIRST) == TRISTATE_TRUE); + pAutoCorrect->SetAutoCorrFlag(ACFlags::CorrectCapsLock, m_xCheckLB->get_toggle(nPos++, CBCOL_FIRST) == TRISTATE_TRUE); + + bool bReturn = nFlags != pAutoCorrect->GetFlags(); + if(bReturn ) + { + SvxAutoCorrCfg& rCfg = SvxAutoCorrCfg::Get(); + rCfg.SetModified(); + rCfg.Commit(); + } + return bReturn; +} + +void OfaAutocorrOptionsPage::ActivatePage( const SfxItemSet& ) +{ + static_cast(GetDialogController())->EnableLanguage(false); +} + +void OfaAutocorrOptionsPage::InsertEntry(const OUString& rTxt) +{ + m_xCheckLB->append(); + const int nRow = m_xCheckLB->n_children() - 1; + m_xCheckLB->set_toggle(nRow, TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_text(nRow, rTxt, 1); +} + +void OfaAutocorrOptionsPage::Reset( const SfxItemSet* ) +{ + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + const ACFlags nFlags = pAutoCorrect->GetFlags(); + + m_xCheckLB->freeze(); + m_xCheckLB->clear(); + + InsertEntry(m_sInput); + InsertEntry(m_sDoubleCaps); + InsertEntry(m_sStartCap); + InsertEntry(m_sBoldUnderline); + InsertEntry(m_sURL); + InsertEntry(m_sDash); + InsertEntry(m_sNoDblSpaces); + InsertEntry(m_sAccidentalCaps); + + int nPos = 0; + m_xCheckLB->set_toggle( nPos++, bool(nFlags & ACFlags::Autocorrect) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST ); + m_xCheckLB->set_toggle( nPos++, bool(nFlags & ACFlags::CapitalStartWord) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST ); + m_xCheckLB->set_toggle( nPos++, bool(nFlags & ACFlags::CapitalStartSentence) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST ); + m_xCheckLB->set_toggle( nPos++, bool(nFlags & ACFlags::ChgWeightUnderl) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST ); + m_xCheckLB->set_toggle( nPos++, bool(nFlags & ACFlags::SetINetAttr) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST ); + m_xCheckLB->set_toggle( nPos++, bool(nFlags & ACFlags::ChgToEnEmDash) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST ); + m_xCheckLB->set_toggle( nPos++, bool(nFlags & ACFlags::IgnoreDoubleSpace) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST ); + m_xCheckLB->set_toggle( nPos++, bool(nFlags & ACFlags::CorrectCapsLock) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST ); + + m_xCheckLB->thaw(); +} + +/*********************************************************************/ +/* */ +/* helping struct for dUserData of the Checklistbox */ +/* */ +/*********************************************************************/ + +namespace { + +struct ImpUserData +{ + OUString *pString; + vcl::Font *pFont; + + ImpUserData(OUString* pText, vcl::Font* pFnt) + { pString = pText; pFont = pFnt;} +}; + + +/*********************************************************************/ +/* */ +/* dialog for per cent settings */ +/* */ +/*********************************************************************/ + +class OfaAutoFmtPrcntSet : public weld::GenericDialogController +{ + std::unique_ptr m_xPrcntMF; +public: + explicit OfaAutoFmtPrcntSet(weld::Window* pParent) + : GenericDialogController(pParent, "cui/ui/percentdialog.ui", "PercentDialog") + , m_xPrcntMF(m_xBuilder->weld_metric_spin_button("margin", FieldUnit::PERCENT)) + { + } + + weld::MetricSpinButton& GetPrcntFld() + { + return *m_xPrcntMF; + } +}; + +/*********************************************************************/ +/* */ +/* use TabPage autoformat */ +/* */ +/*********************************************************************/ + +enum OfaAutoFmtOptions +{ + USE_REPLACE_TABLE, + CORR_UPPER, + BEGIN_UPPER, + BOLD_UNDERLINE, + DETECT_URL, + REPLACE_DASHES, + DEL_SPACES_AT_STT_END, + DEL_SPACES_BETWEEN_LINES, + IGNORE_DBLSPACE, + CORRECT_CAPS_LOCK, + APPLY_NUMBERING, + INSERT_BORDER, + CREATE_TABLE, + REPLACE_STYLES, + DEL_EMPTY_NODE, + REPLACE_USER_COLL, + REPLACE_BULLETS, + MERGE_SINGLE_LINE_PARA +}; + +} + +OfaSwAutoFmtOptionsPage::OfaSwAutoFmtOptionsPage(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet& rSet ) + : SfxTabPage(pPage, pController, "cui/ui/applyautofmtpage.ui", "ApplyAutoFmtPage", &rSet) + , sDeleteEmptyPara(CuiResId(RID_SVXSTR_DEL_EMPTY_PARA)) + , sUseReplaceTbl(CuiResId(RID_SVXSTR_USE_REPLACE)) + , sCapitalStartWord(CuiResId(RID_SVXSTR_CPTL_STT_WORD)) + , sCapitalStartSentence(CuiResId(RID_SVXSTR_CPTL_STT_SENT)) + , sUserStyle(CuiResId(RID_SVXSTR_USER_STYLE)) + , sBullet(CuiResId(RID_SVXSTR_BULLET)) + , sBoldUnder(CuiResId(RID_SVXSTR_BOLD_UNDER)) + , sNoDblSpaces(CuiResId(RID_SVXSTR_NO_DBL_SPACES)) + , sCorrectCapsLock(CuiResId(RID_SVXSTR_CORRECT_ACCIDENTAL_CAPS_LOCK)) + , sDetectURL(CuiResId(RID_SVXSTR_DETECT_URL)) + , sDash(CuiResId(RID_SVXSTR_DASH)) + , sRightMargin(CuiResId(RID_SVXSTR_RIGHT_MARGIN)) + , sNum(CuiResId(RID_SVXSTR_NUM)) + , sBorder(CuiResId(RID_SVXSTR_BORDER)) + , sTable(CuiResId(RID_SVXSTR_CREATE_TABLE)) + , sReplaceTemplates(CuiResId(RID_SVXSTR_REPLACE_TEMPLATES)) + , sDelSpaceAtSttEnd(CuiResId(RID_SVXSTR_DEL_SPACES_AT_STT_END)) + , sDelSpaceBetweenLines(CuiResId(RID_SVXSTR_DEL_SPACES_BETWEEN_LINES)) + , nPercent(50) + , m_xCheckLB(m_xBuilder->weld_tree_view("list")) + , m_xEditPB(m_xBuilder->weld_button("edit")) +{ + m_xCheckLB->connect_changed(LINK(this, OfaSwAutoFmtOptionsPage, SelectHdl)); + m_xCheckLB->connect_row_activated(LINK(this, OfaSwAutoFmtOptionsPage, DoubleClickEditHdl)); + + std::vector aWidths; + aWidths.push_back(m_xCheckLB->get_pixel_size(m_xCheckLB->get_column_title(0)).Width() * 2); + aWidths.push_back(m_xCheckLB->get_pixel_size(m_xCheckLB->get_column_title(1)).Width() * 2); + m_xCheckLB->set_column_fixed_widths(aWidths); + + m_xEditPB->connect_clicked(LINK(this, OfaSwAutoFmtOptionsPage, EditHdl)); +} + +void OfaSwAutoFmtOptionsPage::CreateEntry(const OUString& rTxt, sal_uInt16 nCol) +{ + m_xCheckLB->append(); + const int nRow = m_xCheckLB->n_children() - 1; + if (nCol == CBCOL_FIRST || nCol == CBCOL_BOTH) + m_xCheckLB->set_toggle(nRow, TRISTATE_FALSE, CBCOL_FIRST); + if (nCol == CBCOL_SECOND || nCol == CBCOL_BOTH) + m_xCheckLB->set_toggle(nRow, TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_text(nRow, rTxt, 2); +} + +OfaSwAutoFmtOptionsPage::~OfaSwAutoFmtOptionsPage() +{ + delete reinterpret_cast(m_xCheckLB->get_id(REPLACE_BULLETS).toInt64()); + delete reinterpret_cast(m_xCheckLB->get_id(APPLY_NUMBERING).toInt64()); + delete reinterpret_cast(m_xCheckLB->get_id(MERGE_SINGLE_LINE_PARA).toInt64()); +} + +std::unique_ptr OfaSwAutoFmtOptionsPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet) +{ + return std::make_unique(pPage, pController, *rAttrSet); +} + +bool OfaSwAutoFmtOptionsPage::FillItemSet( SfxItemSet* ) +{ + bool bModified = false; + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + SvxSwAutoFormatFlags *pOpt = &pAutoCorrect->GetSwFlags(); + ACFlags nFlags = pAutoCorrect->GetFlags(); + + bool bCheck = m_xCheckLB->get_toggle(USE_REPLACE_TABLE, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bAutoCorrect != bCheck; + pOpt->bAutoCorrect = bCheck; + pAutoCorrect->SetAutoCorrFlag(ACFlags::Autocorrect, + m_xCheckLB->get_toggle(USE_REPLACE_TABLE, CBCOL_SECOND) == TRISTATE_TRUE); + + bCheck = m_xCheckLB->get_toggle(CORR_UPPER, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bCapitalStartWord != bCheck; + pOpt->bCapitalStartWord = bCheck; + pAutoCorrect->SetAutoCorrFlag(ACFlags::CapitalStartWord, + m_xCheckLB->get_toggle(CORR_UPPER, CBCOL_SECOND) == TRISTATE_TRUE); + + bCheck = m_xCheckLB->get_toggle(BEGIN_UPPER, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bCapitalStartSentence != bCheck; + pOpt->bCapitalStartSentence = bCheck; + pAutoCorrect->SetAutoCorrFlag(ACFlags::CapitalStartSentence, + m_xCheckLB->get_toggle(BEGIN_UPPER, CBCOL_SECOND) == TRISTATE_TRUE); + + bCheck = m_xCheckLB->get_toggle(BOLD_UNDERLINE, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bChgWeightUnderl != bCheck; + pOpt->bChgWeightUnderl = bCheck; + pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgWeightUnderl, + m_xCheckLB->get_toggle(BOLD_UNDERLINE, CBCOL_SECOND) == TRISTATE_TRUE); + + pAutoCorrect->SetAutoCorrFlag(ACFlags::IgnoreDoubleSpace, + m_xCheckLB->get_toggle(IGNORE_DBLSPACE, CBCOL_SECOND) == TRISTATE_TRUE); + + pAutoCorrect->SetAutoCorrFlag(ACFlags::CorrectCapsLock, + m_xCheckLB->get_toggle(CORRECT_CAPS_LOCK, CBCOL_SECOND) == TRISTATE_TRUE); + + bCheck = m_xCheckLB->get_toggle(DETECT_URL, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bSetINetAttr != bCheck; + pOpt->bSetINetAttr = bCheck; + pAutoCorrect->SetAutoCorrFlag(ACFlags::SetINetAttr, + m_xCheckLB->get_toggle(DETECT_URL, CBCOL_SECOND) == TRISTATE_TRUE); + + bCheck = m_xCheckLB->get_toggle(DEL_EMPTY_NODE, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bDelEmptyNode != bCheck; + pOpt->bDelEmptyNode = bCheck; + + bCheck = m_xCheckLB->get_toggle(REPLACE_USER_COLL, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bChgUserColl != bCheck; + pOpt->bChgUserColl = bCheck; + + bCheck = m_xCheckLB->get_toggle(REPLACE_BULLETS, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bChgEnumNum != bCheck; + pOpt->bChgEnumNum = bCheck; + bModified |= aBulletFont != pOpt->aBulletFont; + pOpt->aBulletFont = aBulletFont; + bModified |= !comphelper::string::equals(sBulletChar, pOpt->cBullet); + pOpt->cBullet = sBulletChar[0]; + + bModified |= aByInputBulletFont != pOpt->aByInputBulletFont; + bModified |= !comphelper::string::equals(sByInputBulletChar, pOpt->cByInputBullet); + pOpt->aByInputBulletFont = aByInputBulletFont; + pOpt->cByInputBullet = sByInputBulletChar[0]; + + bCheck = m_xCheckLB->get_toggle(MERGE_SINGLE_LINE_PARA, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bRightMargin != bCheck; + pOpt->bRightMargin = bCheck; + bModified |= nPercent != pOpt->nRightMargin; + pOpt->nRightMargin = static_cast(nPercent); + + bCheck = m_xCheckLB->get_toggle(APPLY_NUMBERING, CBCOL_SECOND) == TRISTATE_TRUE; + bModified |= pOpt->bSetNumRule != bCheck; + pOpt->bSetNumRule = bCheck; + + bCheck = m_xCheckLB->get_toggle(INSERT_BORDER, CBCOL_SECOND) == TRISTATE_TRUE; + bModified |= pOpt->bSetBorder != bCheck; + pOpt->bSetBorder = bCheck; + + bCheck = m_xCheckLB->get_toggle(CREATE_TABLE, CBCOL_SECOND) == TRISTATE_TRUE; + bModified |= pOpt->bCreateTable != bCheck; + pOpt->bCreateTable = bCheck; + + bCheck = m_xCheckLB->get_toggle(REPLACE_STYLES, CBCOL_SECOND) == TRISTATE_TRUE; + bModified |= pOpt->bReplaceStyles != bCheck; + pOpt->bReplaceStyles = bCheck; + + bCheck = m_xCheckLB->get_toggle(REPLACE_DASHES, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bChgToEnEmDash != bCheck; + pOpt->bChgToEnEmDash = bCheck; + pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgToEnEmDash, + m_xCheckLB->get_toggle(REPLACE_DASHES, CBCOL_SECOND) == TRISTATE_TRUE); + + bCheck = m_xCheckLB->get_toggle(DEL_SPACES_AT_STT_END, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bAFormatDelSpacesAtSttEnd != bCheck; + pOpt->bAFormatDelSpacesAtSttEnd = bCheck; + bCheck = m_xCheckLB->get_toggle(DEL_SPACES_AT_STT_END, CBCOL_SECOND) == TRISTATE_TRUE; + bModified |= pOpt->bAFormatByInpDelSpacesAtSttEnd != bCheck; + pOpt->bAFormatByInpDelSpacesAtSttEnd = bCheck; + + bCheck = m_xCheckLB->get_toggle(DEL_SPACES_BETWEEN_LINES, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bAFormatDelSpacesBetweenLines != bCheck; + pOpt->bAFormatDelSpacesBetweenLines = bCheck; + bCheck = m_xCheckLB->get_toggle(DEL_SPACES_BETWEEN_LINES, CBCOL_SECOND) == TRISTATE_TRUE; + bModified |= pOpt->bAFormatByInpDelSpacesBetweenLines != bCheck; + pOpt->bAFormatByInpDelSpacesBetweenLines = bCheck; + + if(bModified || nFlags != pAutoCorrect->GetFlags()) + { + SvxAutoCorrCfg& rCfg = SvxAutoCorrCfg::Get(); + rCfg.SetModified(); + rCfg.Commit(); + } + + return true; +} + +void OfaSwAutoFmtOptionsPage::ActivatePage( const SfxItemSet& ) +{ + static_cast(GetDialogController())->EnableLanguage(false); +} + +void OfaSwAutoFmtOptionsPage::Reset( const SfxItemSet* ) +{ + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + SvxSwAutoFormatFlags *pOpt = &pAutoCorrect->GetSwFlags(); + const ACFlags nFlags = pAutoCorrect->GetFlags(); + + aBulletFont = pOpt->aBulletFont; + sBulletChar = OUString(pOpt->cBullet); + + aByInputBulletFont = pOpt->aByInputBulletFont; + sByInputBulletChar = OUString( pOpt->cByInputBullet ); + + nPercent = pOpt->nRightMargin; + sMargin = unicode::formatPercent(nPercent, Application::GetSettings().GetUILanguageTag()); + + m_xCheckLB->freeze(); + m_xCheckLB->clear(); + + // The following entries have to be inserted in the same order + // as in the OfaAutoFmtOptions-enum! + CreateEntry(sUseReplaceTbl, CBCOL_BOTH ); + CreateEntry(sCapitalStartWord, CBCOL_BOTH ); + CreateEntry(sCapitalStartSentence, CBCOL_BOTH ); + CreateEntry(sBoldUnder, CBCOL_BOTH ); + CreateEntry(sDetectURL, CBCOL_BOTH ); + CreateEntry(sDash, CBCOL_BOTH ); + CreateEntry(sDelSpaceAtSttEnd, CBCOL_BOTH ); + CreateEntry(sDelSpaceBetweenLines, CBCOL_BOTH ); + + CreateEntry(sNoDblSpaces, CBCOL_SECOND); + CreateEntry(sCorrectCapsLock, CBCOL_SECOND); + CreateEntry(sNum.replaceFirst("%1", sBulletChar), CBCOL_SECOND); + CreateEntry(sBorder, CBCOL_SECOND); + CreateEntry(sTable, CBCOL_SECOND); + CreateEntry(sReplaceTemplates, CBCOL_SECOND); + CreateEntry(sDeleteEmptyPara, CBCOL_FIRST ); + CreateEntry(sUserStyle, CBCOL_FIRST ); + CreateEntry(sBullet.replaceFirst("%1", sByInputBulletChar), CBCOL_FIRST); + CreateEntry(sRightMargin.replaceFirst("%1", sMargin), CBCOL_FIRST); + + m_xCheckLB->set_toggle(USE_REPLACE_TABLE, pOpt->bAutoCorrect ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(USE_REPLACE_TABLE, bool(nFlags & ACFlags::Autocorrect) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(CORR_UPPER, pOpt->bCapitalStartWord ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(CORR_UPPER, bool(nFlags & ACFlags::CapitalStartWord) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(BEGIN_UPPER, pOpt->bCapitalStartSentence ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(BEGIN_UPPER, bool(nFlags & ACFlags::CapitalStartSentence) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(BOLD_UNDERLINE, pOpt->bChgWeightUnderl ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(BOLD_UNDERLINE, bool(nFlags & ACFlags::ChgWeightUnderl) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(DETECT_URL, pOpt->bSetINetAttr ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(DETECT_URL, bool(nFlags & ACFlags::SetINetAttr) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(REPLACE_DASHES, pOpt->bChgToEnEmDash ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(REPLACE_DASHES, bool(nFlags & ACFlags::ChgToEnEmDash) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(DEL_SPACES_AT_STT_END, pOpt->bAFormatDelSpacesAtSttEnd ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(DEL_SPACES_AT_STT_END, pOpt->bAFormatByInpDelSpacesAtSttEnd ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(DEL_SPACES_BETWEEN_LINES, pOpt->bAFormatDelSpacesBetweenLines ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(DEL_SPACES_BETWEEN_LINES, pOpt->bAFormatByInpDelSpacesBetweenLines ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(IGNORE_DBLSPACE, bool(nFlags & ACFlags::IgnoreDoubleSpace) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(CORRECT_CAPS_LOCK, bool(nFlags & ACFlags::CorrectCapsLock) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(APPLY_NUMBERING, pOpt->bSetNumRule ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(INSERT_BORDER, pOpt->bSetBorder ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(CREATE_TABLE, pOpt->bCreateTable ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(REPLACE_STYLES, pOpt->bReplaceStyles ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(DEL_EMPTY_NODE, pOpt->bDelEmptyNode ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(REPLACE_USER_COLL, pOpt->bChgUserColl ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(REPLACE_BULLETS, pOpt->bChgEnumNum ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(MERGE_SINGLE_LINE_PARA, pOpt->bRightMargin ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + + ImpUserData* pUserData = new ImpUserData(&sBulletChar, &aBulletFont); + OUString sId(OUString::number(reinterpret_cast(pUserData))); + m_xCheckLB->set_id(REPLACE_BULLETS, sId); + + pUserData = new ImpUserData(&sMargin, nullptr); + sId = OUString::number(reinterpret_cast(pUserData)); + m_xCheckLB->set_id(MERGE_SINGLE_LINE_PARA, sId); + + ImpUserData* pUserData2 = new ImpUserData(&sByInputBulletChar, &aByInputBulletFont); + sId = OUString::number(reinterpret_cast(pUserData2)); + m_xCheckLB->set_id(APPLY_NUMBERING, sId); + + m_xCheckLB->thaw(); +} + +IMPL_LINK(OfaSwAutoFmtOptionsPage, SelectHdl, weld::TreeView&, rBox, void) +{ + m_xEditPB->set_sensitive(rBox.get_selected_id().toInt64() != 0); +} + +IMPL_LINK_NOARG(OfaSwAutoFmtOptionsPage, DoubleClickEditHdl, weld::TreeView&, bool) +{ + EditHdl(*m_xEditPB); + return true; +} + +IMPL_LINK_NOARG(OfaSwAutoFmtOptionsPage, EditHdl, weld::Button&, void) +{ + int nSelEntryPos = m_xCheckLB->get_selected_index(); + if (nSelEntryPos == REPLACE_BULLETS || nSelEntryPos == APPLY_NUMBERING) + { + SvxCharacterMap aMapDlg(GetFrameWeld(), nullptr, nullptr); + ImpUserData* pUserData = reinterpret_cast(m_xCheckLB->get_id(nSelEntryPos).toInt64()); + aMapDlg.SetCharFont(*pUserData->pFont); + aMapDlg.SetChar( (*pUserData->pString)[0] ); + if (RET_OK == aMapDlg.run()) + { + const vcl::Font& aFont(aMapDlg.GetCharFont()); + *pUserData->pFont = aFont; + sal_UCS4 aChar = aMapDlg.GetChar(); + // using the UCS4 constructor + OUString aOUStr( &aChar, 1 ); + *pUserData->pString = aOUStr; + if (nSelEntryPos == REPLACE_BULLETS) + m_xCheckLB->set_text(nSelEntryPos, sNum.replaceFirst("%1", aOUStr), 2); + else + m_xCheckLB->set_text(nSelEntryPos, sBullet.replaceFirst("%1", aOUStr), 2); + } + } + else if( MERGE_SINGLE_LINE_PARA == nSelEntryPos ) + { + // dialog for per cent settings + OfaAutoFmtPrcntSet aDlg(GetFrameWeld()); + aDlg.GetPrcntFld().set_value(nPercent, FieldUnit::PERCENT); + if (aDlg.run() == RET_OK) + { + nPercent = static_cast(aDlg.GetPrcntFld().get_value(FieldUnit::PERCENT)); + sMargin = unicode::formatPercent(nPercent, Application::GetSettings().GetUILanguageTag()); + m_xCheckLB->set_text(nSelEntryPos, sRightMargin.replaceFirst("%1", sMargin), 2); + } + } +} + + +OfaAutocorrReplacePage::OfaAutocorrReplacePage(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/acorreplacepage.ui", "AcorReplacePage", &rSet) + , eLang(eLastDialogLanguage) + , bHasSelectionText(false) + , bFirstSelect(true) + , bReplaceEditChanged(false) + , bSWriter(true) + , m_xTextOnlyCB(m_xBuilder->weld_check_button("textonly")) + , m_xShortED(m_xBuilder->weld_entry("origtext")) + , m_xReplaceED(m_xBuilder->weld_entry("newtext")) + , m_xReplaceTLB(m_xBuilder->weld_tree_view("tabview")) + , m_xNewReplacePB(m_xBuilder->weld_button("new")) + , m_xReplacePB(m_xBuilder->weld_button("replace")) + , m_xDeleteReplacePB(m_xBuilder->weld_button("delete")) + , m_xButtonBox(m_xBuilder->weld_container("buttonbox")) +{ + sNew = m_xNewReplacePB->get_label(); + sModify = m_xReplacePB->get_label(); + + // lock down the width of the button box to its max + // desired width + auto nMaxWidth = m_xButtonBox->get_preferred_size().Width(); + m_xButtonBox->set_size_request(nMaxWidth, -1); + m_xReplacePB->hide(); + + // tdf#125348 set some small but fixed initial width size, final width will + // depend on the size of the entry boxes + m_xReplaceTLB->set_size_request(42, m_xReplaceTLB->get_height_rows(10)); + + SfxModule *pMod = SfxApplication::GetModule(SfxToolsModule::Writer); + bSWriter = pMod == SfxModule::GetActiveModule(); + + LanguageTag aLanguageTag( eLastDialogLanguage ); + pCompareClass.reset( new CollatorWrapper( comphelper::getProcessComponentContext() ) ); + pCompareClass->loadDefaultCollator( aLanguageTag.getLocale(), 0 ); + pCharClass.reset( new CharClass( aLanguageTag ) ); + + auto nColWidth = m_xReplaceTLB->get_approximate_digit_width() * 32; + m_aReplaceFixedWidths.push_back(nColWidth); + m_aReplaceFixedWidths.push_back(nColWidth); + + m_xReplaceTLB->connect_changed( LINK(this, OfaAutocorrReplacePage, SelectHdl) ); + m_xNewReplacePB->connect_clicked( LINK(this, OfaAutocorrReplacePage, NewDelButtonHdl) ); + m_xDeleteReplacePB->connect_clicked( LINK(this, OfaAutocorrReplacePage, NewDelButtonHdl) ); + m_xShortED->connect_changed( LINK(this, OfaAutocorrReplacePage, ModifyHdl) ); + m_xReplaceED->connect_changed( LINK(this, OfaAutocorrReplacePage, ModifyHdl) ); + m_xShortED->connect_activate( LINK(this, OfaAutocorrReplacePage, NewDelActionHdl) ); + m_xReplaceED->connect_activate( LINK(this, OfaAutocorrReplacePage, NewDelActionHdl) ); + m_xShortED->connect_size_allocate(LINK(this, OfaAutocorrReplacePage, EntrySizeAllocHdl)); + m_xReplaceED->connect_size_allocate(LINK(this, OfaAutocorrReplacePage, EntrySizeAllocHdl)); +} + +OfaAutocorrReplacePage::~OfaAutocorrReplacePage() +{ + aDoubleStringTable.clear(); + aChangesTable.clear(); + + pCompareClass.reset(); + pCharClass.reset(); +} + +std::unique_ptr OfaAutocorrReplacePage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet) +{ + return std::make_unique(pPage, pController, *rSet); +} + +void OfaAutocorrReplacePage::ActivatePage( const SfxItemSet& ) +{ + if(eLang != eLastDialogLanguage) + SetLanguage(eLastDialogLanguage); + static_cast(GetDialogController())->EnableLanguage(true); +} + +DeactivateRC OfaAutocorrReplacePage::DeactivatePage( SfxItemSet* ) +{ + return DeactivateRC::LeavePage; +} + +bool OfaAutocorrReplacePage::FillItemSet( SfxItemSet* ) +{ + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + + for (StringChangeTable::reverse_iterator it = aChangesTable.rbegin(); it != aChangesTable.rend(); ++it) + { + LanguageType eCurrentLang = it->first; + StringChangeList& rStringChangeList = it->second; + std::vector aDeleteWords; + std::vector aNewWords; + + aDeleteWords.reserve( rStringChangeList.aDeletedEntries.size() ); + for (const DoubleString & deleteEntry : rStringChangeList.aDeletedEntries) + { + SvxAutocorrWord aDeleteWord( deleteEntry.sShort, deleteEntry.sLong ); + aDeleteWords.push_back( aDeleteWord ); + } + + aNewWords.reserve( rStringChangeList.aNewEntries.size() ); + for (const DoubleString & newEntry : rStringChangeList.aNewEntries) + { + //fdo#67697 if the user data is set then we want to retain the + //source formatting of the entry, so don't use the optimized + //text-only MakeCombinedChanges for this entry + bool bKeepSourceFormatting = newEntry.pUserData == &bHasSelectionText; + if (bKeepSourceFormatting) + { + pAutoCorrect->PutText(newEntry.sShort, *SfxObjectShell::Current(), eCurrentLang); + continue; + } + + SvxAutocorrWord aNewWord( newEntry.sShort, newEntry.sLong ); + aNewWords.push_back( aNewWord ); + } + pAutoCorrect->MakeCombinedChanges( aNewWords, aDeleteWords, eCurrentLang ); + } + aChangesTable.clear(); + return false; +} + +void OfaAutocorrReplacePage::RefillReplaceBox(bool bFromReset, + LanguageType eOldLanguage, + LanguageType eNewLanguage) +{ + eLang = eNewLanguage; + if(bFromReset) + { + aDoubleStringTable.clear(); + aChangesTable.clear(); + } + else + { + DoubleStringArray* pArray; + if(aDoubleStringTable.find(eOldLanguage) != aDoubleStringTable.end()) + { + pArray = &aDoubleStringTable[eOldLanguage]; + pArray->clear(); + } + else + { + pArray = &aDoubleStringTable[eOldLanguage]; // create new array + } + + m_xReplaceTLB->all_foreach([this, &pArray](weld::TreeIter& rIter) { + pArray->push_back(DoubleString()); + DoubleString& rDouble = pArray->back(); + rDouble.sShort = m_xReplaceTLB->get_text(rIter, 0); + rDouble.sLong = m_xReplaceTLB->get_text(rIter, 1); + rDouble.pUserData = reinterpret_cast(m_xReplaceTLB->get_id(rIter).toInt64()); + return false; + }); + } + + if( !bSWriter ) + aFormatText.clear(); + + if (aDoubleStringTable.find(eLang) != aDoubleStringTable.end()) + { + DoubleStringArray& rArray = aDoubleStringTable[eNewLanguage]; + + m_xReplaceTLB->bulk_insert_for_each(rArray.size(), [this, &rArray](weld::TreeIter& rIter, int nIndex) { + DoubleString &rDouble = rArray[nIndex]; + bool bTextOnly = nullptr == rDouble.pUserData; + // formatted text is only in Writer + if (bSWriter || bTextOnly) + { + if (!bTextOnly) + { + // that means: with format info or even with selection text + OUString sId = OUString::number(reinterpret_cast(rDouble.pUserData)); + m_xReplaceTLB->set_id(rIter, sId); + } + m_xReplaceTLB->set_text(rIter, rDouble.sShort, 0); + m_xReplaceTLB->set_text(rIter, rDouble.sLong, 1); + } + else + { + aFormatText.insert(rDouble.sShort); + } + }, &m_aReplaceFixedWidths); + } + else + { + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + SvxAutocorrWordList* pWordList = pAutoCorrect->LoadAutocorrWordList(eLang); + const SvxAutocorrWordList::AutocorrWordSetType & rContent = pWordList->getSortedContent(); + m_xReplaceTLB->bulk_insert_for_each(rContent.size(), [this, rContent](weld::TreeIter& rIter, int nIndex) { + auto const& elem = rContent[nIndex]; + bool bTextOnly = elem.IsTextOnly(); + // formatted text is only in Writer + if (bSWriter || bTextOnly) + { + if (!bTextOnly) + { + // that means: with format info or even with selection text + OUString sId = OUString::number(reinterpret_cast(m_xTextOnlyCB.get())); + m_xReplaceTLB->set_id(rIter, sId); + } + m_xReplaceTLB->set_text(rIter, elem.GetShort(), 0); + m_xReplaceTLB->set_text(rIter, elem.GetLong(), 1); + } + else + { + aFormatText.insert(elem.GetShort()); + } + }, &m_aReplaceFixedWidths); + m_xNewReplacePB->set_sensitive(false); + m_xDeleteReplacePB->set_sensitive(false); + } + + SfxViewShell* pViewShell = SfxViewShell::Current(); + if (pViewShell && pViewShell->HasSelection()) + { + bHasSelectionText = true; + const OUString sSelection( pViewShell->GetSelectionText() ); + m_xReplaceED->set_text(sSelection); + m_xTextOnlyCB->set_active(!bSWriter); + m_xTextOnlyCB->set_sensitive(bSWriter && !sSelection.isEmpty()); + } + else + { + m_xTextOnlyCB->set_active(true); + m_xTextOnlyCB->set_sensitive(false); + } +} + +void OfaAutocorrReplacePage::Reset( const SfxItemSet* ) +{ + RefillReplaceBox(true, eLang, eLang); + m_xShortED->grab_focus(); +} + +void OfaAutocorrReplacePage::SetLanguage(LanguageType eSet) +{ + //save old settings and refill + if(eSet != eLang) + { + RefillReplaceBox(false, eLang, eSet); + eLastDialogLanguage = eSet; + + LanguageTag aLanguageTag( eLastDialogLanguage ); + pCompareClass.reset( new CollatorWrapper( comphelper::getProcessComponentContext() ) ); + pCompareClass->loadDefaultCollator( aLanguageTag.getLocale(), 0 ); + pCharClass.reset( new CharClass( aLanguageTag ) ); + ModifyHdl(*m_xShortED); + } +} + +IMPL_LINK(OfaAutocorrReplacePage, SelectHdl, weld::TreeView&, rBox, void) +{ + if(!bFirstSelect || !bHasSelectionText) + { + int nEntry = rBox.get_selected_index(); + OUString sTmpShort(rBox.get_text(nEntry, 0)); + // if the text is set via ModifyHdl, the cursor is always at the beginning + // of a word, although you're editing here + bool bSameContent = 0 == pCompareClass->compareString(sTmpShort, m_xShortED->get_text()); + int nStartPos, nEndPos; + m_xShortED->get_selection_bounds(nStartPos, nEndPos); + if (m_xShortED->get_text() != sTmpShort) + { + m_xShortED->set_text(sTmpShort); + // if it was only a different notation, the selection has to be set again + if (bSameContent) + { + m_xShortED->select_region(nStartPos, nEndPos); + } + } + m_xReplaceED->set_text(rBox.get_text(nEntry, 1)); + // with UserData there is a Formatinfo + m_xTextOnlyCB->set_active(rBox.get_id(nEntry).isEmpty()); + } + else + { + bFirstSelect = false; + } + + m_xNewReplacePB->set_sensitive(false); + m_xDeleteReplacePB->set_sensitive(true); +}; + +void OfaAutocorrReplacePage::NewEntry(const OUString& sShort, const OUString& sLong, bool bKeepSourceFormatting) +{ + DoubleStringArray& rNewArray = aChangesTable[eLang].aNewEntries; + for (size_t i = 0; i < rNewArray.size(); i++) + { + if (rNewArray[i].sShort == sShort) + { + rNewArray.erase(rNewArray.begin() + i); + break; + } + } + + DoubleStringArray& rDeletedArray = aChangesTable[eLang].aDeletedEntries; + for (size_t i = 0; i < rDeletedArray.size(); i++) + { + if (rDeletedArray[i].sShort == sShort) + { + rDeletedArray.erase(rDeletedArray.begin() + i); + break; + } + } + + DoubleString aNewString; + aNewString.sShort = sShort; + aNewString.sLong = sLong; + rNewArray.push_back(aNewString); + if (bKeepSourceFormatting) + rNewArray.back().pUserData = &bHasSelectionText; +} + +void OfaAutocorrReplacePage::DeleteEntry(const OUString& sShort, const OUString& sLong) +{ + DoubleStringArray& rNewArray = aChangesTable[eLang].aNewEntries; + for (size_t i = 0; i < rNewArray.size(); i++) + { + if (rNewArray[i].sShort == sShort) + { + rNewArray.erase(rNewArray.begin() + i); + break; + } + } + + DoubleStringArray& rDeletedArray = aChangesTable[eLang].aDeletedEntries; + for (size_t i = 0; i < rDeletedArray.size(); i++) + { + if (rDeletedArray[i].sShort == sShort) + { + rDeletedArray.erase(rDeletedArray.begin() + i); + break; + } + } + + DoubleString aDeletedString; + aDeletedString.sShort = sShort; + aDeletedString.sLong = sLong; + rDeletedArray.push_back(aDeletedString); +} + +IMPL_LINK(OfaAutocorrReplacePage, NewDelButtonHdl, weld::Button&, rBtn, void) +{ + NewDelHdl(&rBtn); +} + +IMPL_LINK(OfaAutocorrReplacePage, NewDelActionHdl, weld::Entry&, rEdit, bool) +{ + return NewDelHdl(&rEdit); +} + +IMPL_LINK_NOARG(OfaAutocorrReplacePage, EntrySizeAllocHdl, const Size&, void) +{ + m_aReplaceFixedWidths.clear(); + int x, y, width, height; + if (m_xReplaceED->get_extents_relative_to(*m_xReplaceTLB, x, y, width, height)) + { + m_aReplaceFixedWidths.push_back(x); + m_aReplaceFixedWidths.push_back(width - 1); + m_xReplaceTLB->set_column_fixed_widths(m_aReplaceFixedWidths); + } +} + +bool OfaAutocorrReplacePage::NewDelHdl(const weld::Widget* pBtn) +{ + int nEntry = m_xReplaceTLB->get_selected_index(); + if (pBtn == m_xDeleteReplacePB.get()) + { + DBG_ASSERT( nEntry != -1, "no entry selected" ); + if (nEntry != -1) + { + DeleteEntry(m_xReplaceTLB->get_text(nEntry, 0), m_xReplaceTLB->get_text(nEntry, 1)); + m_xReplaceTLB->remove(nEntry); + ModifyHdl(*m_xShortED); + return false; + } + } + + if (pBtn == m_xNewReplacePB.get() || m_xNewReplacePB->get_sensitive()) + { + OUString sEntry(m_xShortED->get_text()); + if (!sEntry.isEmpty() && (!m_xReplaceED->get_text().isEmpty() || + ( bHasSelectionText && bSWriter ) )) + { + bool bKeepSourceFormatting = !bReplaceEditChanged && !m_xTextOnlyCB->get_active(); + + NewEntry(m_xShortED->get_text(), m_xReplaceED->get_text(), bKeepSourceFormatting); + m_xReplaceTLB->freeze(); + int nPos = -1; + if (nEntry != -1) + { + nPos = nEntry; + m_xReplaceTLB->remove(nEntry); + } + else + { + int j; + int nCount = m_xReplaceTLB->n_children(); + for (j = 0; j < nCount; ++j) + { + if (0 >= pCompareClass->compareString(sEntry, m_xReplaceTLB->get_text(j, 0))) + break; + } + nPos = j; + } + + OUString sId; + if (bKeepSourceFormatting) + { + sId = OUString::number(reinterpret_cast(&bHasSelectionText)); // new formatted text + } + + m_xReplaceTLB->insert(nPos, sEntry, &sId, nullptr, nullptr); + m_xReplaceTLB->set_text(nPos, m_xReplaceED->get_text(), 1); + m_xReplaceTLB->thaw(); + m_xReplaceTLB->scroll_to_row(nPos); + // if the request came from the ReplaceEdit, give focus to the ShortEdit + if (m_xReplaceED->has_focus()) + { + m_xShortED->grab_focus(); + } + } + } + else + { + // this can only be an enter in one of the two edit fields + // which means EndDialog() - has to be evaluated in KeyInput + return false; + } + ModifyHdl(*m_xShortED); + return true; +} + +IMPL_LINK(OfaAutocorrReplacePage, ModifyHdl, weld::Entry&, rEdt, void) +{ + std::unique_ptr xFirstSel(m_xReplaceTLB->make_iterator()); + bool bFirstSelIterSet = m_xReplaceTLB->get_selected(xFirstSel.get()); + bool bShort = &rEdt == m_xShortED.get(); + const OUString rEntry = rEdt.get_text(); + const OUString rRepString = m_xReplaceED->get_text(); + OUString aWordStr(pCharClass->lowercase(rEntry)); + + if(bShort) + { + if(!rEntry.isEmpty()) + { + bool bFound = false; + bool bTmpSelEntry=false; + + m_xReplaceTLB->all_foreach([this, &rEntry, &rRepString, &bFound, + &bTmpSelEntry, &bFirstSelIterSet, + &xFirstSel, &aWordStr](weld::TreeIter& rIter){ + OUString aTestStr = m_xReplaceTLB->get_text(rIter, 0); + if( pCompareClass->compareString(rEntry, aTestStr ) == 0 ) + { + if (!rRepString.isEmpty()) + bFirstSelect = true; + m_xReplaceTLB->set_cursor(rIter); + m_xReplaceTLB->copy_iterator(rIter, *xFirstSel); + bFirstSelIterSet = true; + m_xNewReplacePB->set_label(sModify); + bFound = true; + return true; + } + else + { + aTestStr = pCharClass->lowercase( aTestStr ); + if( aTestStr.startsWith(aWordStr) && !bTmpSelEntry ) + { + m_xReplaceTLB->scroll_to_row(rIter); + bTmpSelEntry = true; + } + } + return false; + }); + if( !bFound ) + { + m_xReplaceTLB->select(-1); + bFirstSelIterSet = false; + m_xNewReplacePB->set_label(sNew); + if( bReplaceEditChanged ) + m_xTextOnlyCB->set_sensitive(false); + } + m_xDeleteReplacePB->set_sensitive(bFound); + } + else if (m_xReplaceTLB->n_children() > 0) + { + m_xReplaceTLB->scroll_to_row(0); + } + + } + else if( !bShort ) + { + bReplaceEditChanged = true; + if (bFirstSelIterSet) + { + m_xNewReplacePB->set_label(sModify); + } + } + + const OUString& rShortTxt = m_xShortED->get_text(); + bool bEnableNew = !rShortTxt.isEmpty() && + ( !rRepString.isEmpty() || + ( bHasSelectionText && bSWriter )) && + ( !bFirstSelIterSet || rRepString != + m_xReplaceTLB->get_text(*xFirstSel, 1) ); + if( bEnableNew ) + { + for (auto const& elem : aFormatText) + { + if(elem == rShortTxt) + { + bEnableNew = false; + break; + } + } + } + m_xNewReplacePB->set_sensitive(bEnableNew); +} + +static bool lcl_FindInArray(std::vector& rStrings, const OUString& rString) +{ + for (auto const& elem : rStrings) + { + if(elem == rString) + { + return true; + } + } + return false; +} + +OfaAutocorrExceptPage::OfaAutocorrExceptPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/acorexceptpage.ui", "AcorExceptPage", &rSet) + , eLang(eLastDialogLanguage) + , m_xAbbrevED(m_xBuilder->weld_entry("abbrev")) + , m_xAbbrevLB(m_xBuilder->weld_tree_view("abbrevlist")) + , m_xNewAbbrevPB(m_xBuilder->weld_button("newabbrev")) + , m_xDelAbbrevPB(m_xBuilder->weld_button("delabbrev")) + , m_xAutoAbbrevCB(m_xBuilder->weld_check_button("autoabbrev")) + , m_xDoubleCapsED(m_xBuilder->weld_entry("double")) + , m_xDoubleCapsLB(m_xBuilder->weld_tree_view("doublelist")) + , m_xNewDoublePB(m_xBuilder->weld_button("newdouble")) + , m_xDelDoublePB(m_xBuilder->weld_button("deldouble")) + , m_xAutoCapsCB(m_xBuilder->weld_check_button("autodouble")) +{ + m_xAbbrevLB->make_sorted(); + m_xAbbrevLB->set_size_request(-1, m_xAbbrevLB->get_height_rows(6)); + + m_xDoubleCapsLB->make_sorted(); + m_xDoubleCapsLB->set_size_request(-1, m_xDoubleCapsLB->get_height_rows(6)); + + css::lang::Locale aLcl( LanguageTag::convertToLocale(eLastDialogLanguage )); + pCompareClass.reset( new CollatorWrapper( comphelper::getProcessComponentContext() ) ); + pCompareClass->loadDefaultCollator( aLcl, 0 ); + + m_xNewAbbrevPB->connect_clicked(LINK(this, OfaAutocorrExceptPage, NewDelButtonHdl)); + m_xDelAbbrevPB->connect_clicked(LINK(this, OfaAutocorrExceptPage, NewDelButtonHdl)); + m_xNewDoublePB->connect_clicked(LINK(this, OfaAutocorrExceptPage, NewDelButtonHdl)); + m_xDelDoublePB->connect_clicked(LINK(this, OfaAutocorrExceptPage, NewDelButtonHdl)); + + m_xAbbrevLB->connect_changed(LINK(this, OfaAutocorrExceptPage, SelectHdl)); + m_xDoubleCapsLB->connect_changed(LINK(this, OfaAutocorrExceptPage, SelectHdl)); + m_xAbbrevED->connect_changed(LINK(this, OfaAutocorrExceptPage, ModifyHdl)); + m_xDoubleCapsED->connect_changed(LINK(this, OfaAutocorrExceptPage, ModifyHdl)); + + m_xAbbrevED->connect_activate(LINK(this, OfaAutocorrExceptPage, NewDelActionHdl)); + m_xDoubleCapsED->connect_activate(LINK(this, OfaAutocorrExceptPage, NewDelActionHdl)); +} + +OfaAutocorrExceptPage::~OfaAutocorrExceptPage() +{ + aStringsTable.clear(); + pCompareClass.reset(); +} + +std::unique_ptr OfaAutocorrExceptPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rSet) +{ + return std::make_unique(pPage, pController, *rSet); +} + +void OfaAutocorrExceptPage::ActivatePage( const SfxItemSet& ) +{ + if(eLang != eLastDialogLanguage) + SetLanguage(eLastDialogLanguage); + static_cast(GetDialogController())->EnableLanguage(true); +} + +DeactivateRC OfaAutocorrExceptPage::DeactivatePage( SfxItemSet* ) +{ + return DeactivateRC::LeavePage; +} + +bool OfaAutocorrExceptPage::FillItemSet( SfxItemSet* ) +{ + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + for(StringsTable::reverse_iterator it1 = aStringsTable.rbegin(); it1 != aStringsTable.rend(); ++it1) + { + LanguageType eCurLang = it1->first; + StringsArrays& rArrays = it1->second; + if(eCurLang != eLang) // current language is treated later + { + SvStringsISortDtor* pWrdList = pAutoCorrect->LoadWrdSttExceptList(eCurLang); + + if(pWrdList) + { + size_t nCount = pWrdList->size(); + size_t i; + for( i = nCount; i; ) + { + OUString aString = (*pWrdList)[ --i ]; + + if( !lcl_FindInArray(rArrays.aDoubleCapsStrings, aString)) + { + pWrdList->erase(i); + } + } + + for (auto const& elem : rArrays.aDoubleCapsStrings) + { + pWrdList->insert(elem); + } + pAutoCorrect->SaveWrdSttExceptList(eCurLang); + } + + SvStringsISortDtor* pCplList = pAutoCorrect->LoadCplSttExceptList(eCurLang); + + if(pCplList) + { + size_t nCount = pCplList->size(); + size_t i; + for( i = nCount; i; ) + { + OUString aString = (*pCplList)[ --i ]; + if( !lcl_FindInArray(rArrays.aAbbrevStrings, aString)) + { + pCplList->erase(i); + } + } + + for (auto const& elem : rArrays.aAbbrevStrings) + { + pCplList->insert(elem); + } + + pAutoCorrect->SaveCplSttExceptList(eCurLang); + } + } + } + aStringsTable.clear(); + + SvStringsISortDtor* pWrdList = pAutoCorrect->LoadWrdSttExceptList(eLang); + + if(pWrdList) + { + size_t nCount = pWrdList->size(); + size_t i; + for( i = nCount; i; ) + { + OUString aString = (*pWrdList)[ --i ]; + if (m_xDoubleCapsLB->find_text(aString) == -1) + { + pWrdList->erase(i); + } + } + nCount = m_xDoubleCapsLB->n_children(); + for( i = 0; i < nCount; ++i ) + { + pWrdList->insert(m_xDoubleCapsLB->get_text(i)); + } + pAutoCorrect->SaveWrdSttExceptList(eLang); + } + + SvStringsISortDtor* pCplList = pAutoCorrect->LoadCplSttExceptList(eLang); + + if(pCplList) + { + size_t nCount = pCplList->size(); + for( size_t i = nCount; i; ) + { + OUString aString = (*pCplList)[ --i ]; + if (m_xAbbrevLB->find_text(aString) == -1) + { + pCplList->erase(i); + } + } + sal_Int32 nAbbrevCount = m_xAbbrevLB->n_children(); + for( sal_Int32 ia = 0; ia < nAbbrevCount; ++ia ) + { + pCplList->insert(m_xAbbrevLB->get_text(ia)); + } + pAutoCorrect->SaveCplSttExceptList(eLang); + } + if (m_xAutoAbbrevCB->get_state_changed_from_saved()) + pAutoCorrect->SetAutoCorrFlag( ACFlags::SaveWordCplSttLst, m_xAutoAbbrevCB->get_active()); + if (m_xAutoCapsCB->get_state_changed_from_saved()) + pAutoCorrect->SetAutoCorrFlag( ACFlags::SaveWordWrdSttLst, m_xAutoCapsCB->get_active()); + return false; +} + +void OfaAutocorrExceptPage::SetLanguage(LanguageType eSet) +{ + if(eLang != eSet) + { + // save old settings and fill anew + RefillReplaceBoxes(false, eLang, eSet); + eLastDialogLanguage = eSet; + pCompareClass.reset( new CollatorWrapper( comphelper::getProcessComponentContext() ) ); + pCompareClass->loadDefaultCollator( LanguageTag::convertToLocale( eLastDialogLanguage ), 0 ); + ModifyHdl(*m_xAbbrevED); + ModifyHdl(*m_xDoubleCapsED); + } +} + +void OfaAutocorrExceptPage::RefillReplaceBoxes(bool bFromReset, + LanguageType eOldLanguage, + LanguageType eNewLanguage) +{ + eLang = eNewLanguage; + if(bFromReset) + { + aStringsTable.clear(); + } + else + { + StringsArrays* pArrays; + if(aStringsTable.find(eOldLanguage) != aStringsTable.end()) + { + pArrays = &aStringsTable[eOldLanguage]; + pArrays->aAbbrevStrings.clear(); + pArrays->aDoubleCapsStrings.clear(); + } + else + { + pArrays = &aStringsTable[eOldLanguage]; // create new array + } + + sal_Int32 i, nCount; + nCount = m_xAbbrevLB->n_children(); + for(i = 0; i < nCount; i++) + pArrays->aAbbrevStrings.push_back(m_xAbbrevLB->get_text(i)); + + nCount = m_xDoubleCapsLB->n_children(); + for(i = 0; i < nCount; i++) + pArrays->aDoubleCapsStrings.push_back(m_xDoubleCapsLB->get_text(i)); + } + m_xDoubleCapsLB->clear(); + m_xAbbrevLB->clear(); + OUString sTemp; + m_xAbbrevED->set_text(sTemp); + m_xDoubleCapsED->set_text(sTemp); + + if(aStringsTable.find(eLang) != aStringsTable.end()) + { + StringsArrays& rArrays = aStringsTable[eLang]; + for (auto const& elem : rArrays.aAbbrevStrings) + m_xAbbrevLB->append_text(elem); + + for (auto const& elem : rArrays.aDoubleCapsStrings) + m_xDoubleCapsLB->append_text(elem); + } + else + { + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + const SvStringsISortDtor* pCplList = pAutoCorrect->GetCplSttExceptList(eLang); + const SvStringsISortDtor* pWrdList = pAutoCorrect->GetWrdSttExceptList(eLang); + size_t i; + for( i = 0; i < pCplList->size(); i++ ) + { + m_xAbbrevLB->append_text((*pCplList)[i]); + } + for( i = 0; i < pWrdList->size(); i++ ) + { + m_xDoubleCapsLB->append_text((*pWrdList)[i]); + } + } +} + +void OfaAutocorrExceptPage::Reset( const SfxItemSet* ) +{ + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + RefillReplaceBoxes(true, eLang, eLang); + m_xAutoAbbrevCB->set_active(pAutoCorrect->IsAutoCorrFlag( ACFlags::SaveWordCplSttLst)); + m_xAutoCapsCB->set_active(pAutoCorrect->IsAutoCorrFlag( ACFlags::SaveWordWrdSttLst)); + m_xAutoAbbrevCB->save_state(); + m_xAutoCapsCB->save_state(); +} + +IMPL_LINK(OfaAutocorrExceptPage, NewDelButtonHdl, weld::Button&, rBtn, void) +{ + NewDelHdl(&rBtn); +} + +IMPL_LINK(OfaAutocorrExceptPage, NewDelActionHdl, weld::Entry&, rEdit, bool) +{ + NewDelHdl(&rEdit); + return false; +} + +void OfaAutocorrExceptPage::NewDelHdl(const weld::Widget* pBtn) +{ + if ((pBtn == m_xNewAbbrevPB.get() || pBtn == m_xAbbrevED.get()) + && !m_xAbbrevED->get_text().isEmpty()) + { + m_xAbbrevLB->append_text(m_xAbbrevED->get_text()); + ModifyHdl(*m_xAbbrevED); + } + else if(pBtn == m_xDelAbbrevPB.get()) + { + m_xAbbrevLB->remove_text(m_xAbbrevED->get_text()); + ModifyHdl(*m_xAbbrevED); + } + else if((pBtn == m_xNewDoublePB.get() || pBtn == m_xDoubleCapsED.get() ) + && !m_xDoubleCapsED->get_text().isEmpty()) + { + m_xDoubleCapsLB->append_text(m_xDoubleCapsED->get_text()); + ModifyHdl(*m_xDoubleCapsED); + } + else if (pBtn == m_xDelDoublePB.get()) + { + m_xDoubleCapsLB->remove_text(m_xDoubleCapsED->get_text()); + ModifyHdl(*m_xDoubleCapsED); + } +} + +IMPL_LINK(OfaAutocorrExceptPage, SelectHdl, weld::TreeView&, rBox, void) +{ + if (&rBox == m_xAbbrevLB.get()) + { + m_xAbbrevED->set_text(rBox.get_selected_text()); + m_xNewAbbrevPB->set_sensitive(false); + m_xDelAbbrevPB->set_sensitive(true); + } + else + { + m_xDoubleCapsED->set_text(rBox.get_selected_text()); + m_xNewDoublePB->set_sensitive(false); + m_xDelDoublePB->set_sensitive(true); + } +} + +IMPL_LINK(OfaAutocorrExceptPage, ModifyHdl, weld::Entry&, rEdt, void) +{ + const OUString& sEntry = rEdt.get_text(); + bool bEntryLen = !sEntry.isEmpty(); + if (&rEdt == m_xAbbrevED.get()) + { + bool bSame = lcl_FindEntry(*m_xAbbrevLB, sEntry, *pCompareClass); + if(bSame && sEntry != m_xAbbrevLB->get_selected_text()) + rEdt.set_text(m_xAbbrevLB->get_selected_text()); + m_xNewAbbrevPB->set_sensitive(!bSame && bEntryLen); + m_xDelAbbrevPB->set_sensitive(bSame && bEntryLen); + } + else + { + bool bSame = lcl_FindEntry(*m_xDoubleCapsLB, sEntry, *pCompareClass); + if(bSame && sEntry != m_xDoubleCapsLB->get_selected_text()) + rEdt.set_text(m_xDoubleCapsLB->get_selected_text()); + m_xNewDoublePB->set_sensitive(!bSame && bEntryLen); + m_xDelDoublePB->set_sensitive(bSame && bEntryLen); + } +} + +namespace { + +enum OfaQuoteOptions +{ + ADD_NONBRK_SPACE, + REPLACE_1ST, + TRANSLITERATE_RTL, + REPLACE_ANGLE_QUOTES +}; + +} + +void OfaQuoteTabPage::CreateEntry(weld::TreeView& rCheckLB, const OUString& rTxt, sal_uInt16 nCol, sal_uInt16 nTextCol) +{ + rCheckLB.append(); + const int nRow = rCheckLB.n_children() - 1; + if (nCol == CBCOL_FIRST || nCol == CBCOL_BOTH) + rCheckLB.set_toggle(nRow, TRISTATE_FALSE, CBCOL_FIRST); + if (nCol == CBCOL_SECOND || nCol == CBCOL_BOTH) + rCheckLB.set_toggle(nRow, TRISTATE_FALSE, CBCOL_SECOND); + rCheckLB.set_text(nRow, rTxt, nTextCol); +} + +OfaQuoteTabPage::OfaQuoteTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/applylocalizedpage.ui", "ApplyLocalizedPage", &rSet) + , sNonBrkSpace(CuiResId(RID_SVXSTR_NON_BREAK_SPACE)) + , sOrdinal(CuiResId(RID_SVXSTR_ORDINAL)) + , sTransliterateRTL(CuiResId(RID_SVXSTR_OLD_HUNGARIAN)) + , sAngleQuotes(CuiResId(RID_SVXSTR_ANGLE_QUOTES)) + , cSglStartQuote(0) + , cSglEndQuote(0) + , cStartQuote(0) + , cEndQuote(0) + , m_xSingleTypoCB(m_xBuilder->weld_check_button("singlereplace")) + , m_xSglStartQuotePB(m_xBuilder->weld_button("startsingle")) + , m_xSglStartExFT(m_xBuilder->weld_label("singlestartex")) + , m_xSglEndQuotePB(m_xBuilder->weld_button("endsingle")) + , m_xSglEndExFT(m_xBuilder->weld_label("singleendex")) + , m_xSglStandardPB(m_xBuilder->weld_button("defaultsingle")) + , m_xDoubleTypoCB(m_xBuilder->weld_check_button("doublereplace")) + , m_xDblStartQuotePB(m_xBuilder->weld_button("startdouble")) + , m_xDblStartExFT(m_xBuilder->weld_label("doublestartex")) + , m_xDblEndQuotePB(m_xBuilder->weld_button("enddouble")) + , m_xDblEndExFT(m_xBuilder->weld_label("doubleendex")) + , m_xDblStandardPB(m_xBuilder->weld_button("defaultdouble")) + , m_sStandard(m_xSglStartExFT->get_label()) + , m_xCheckLB(m_xBuilder->weld_tree_view("checklist")) + , m_xSwCheckLB(m_xBuilder->weld_tree_view("list")) +{ + m_xSwCheckLB->set_size_request(m_xSwCheckLB->get_approximate_digit_width() * 50, + m_xSwCheckLB->get_height_rows(6)); + + bool bShowSWOptions = false; + + const SfxBoolItem* pItem = rSet.GetItem(SID_AUTO_CORRECT_DLG, false); + if ( pItem && pItem->GetValue() ) + bShowSWOptions = true; + + if ( bShowSWOptions ) + { + std::vector aWidths; + aWidths.push_back(m_xSwCheckLB->get_pixel_size(m_xSwCheckLB->get_column_title(0)).Width() * 2); + aWidths.push_back(m_xSwCheckLB->get_pixel_size(m_xSwCheckLB->get_column_title(1)).Width() * 2); + m_xSwCheckLB->set_column_fixed_widths(aWidths); + m_xCheckLB->hide(); + } + else + { + std::vector aWidths; + aWidths.push_back(m_xSwCheckLB->get_checkbox_column_width()); + m_xCheckLB->set_column_fixed_widths(aWidths); + m_xSwCheckLB->hide(); + } + + m_xDblStartQuotePB->connect_clicked(LINK(this, OfaQuoteTabPage, QuoteHdl)); + m_xDblEndQuotePB->connect_clicked(LINK(this, OfaQuoteTabPage, QuoteHdl)); + m_xSglStartQuotePB->connect_clicked(LINK(this, OfaQuoteTabPage, QuoteHdl)); + m_xSglEndQuotePB->connect_clicked(LINK(this, OfaQuoteTabPage, QuoteHdl)); + m_xDblStandardPB->connect_clicked(LINK(this, OfaQuoteTabPage, StdQuoteHdl)); + m_xSglStandardPB->connect_clicked(LINK(this, OfaQuoteTabPage, StdQuoteHdl)); +} + +OfaQuoteTabPage::~OfaQuoteTabPage() +{ +} + +std::unique_ptr OfaQuoteTabPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet) +{ + return std::make_unique(pPage, pController, *rAttrSet); +} + +bool OfaQuoteTabPage::FillItemSet( SfxItemSet* ) +{ + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + + ACFlags nFlags = pAutoCorrect->GetFlags(); + + if (m_xCheckLB->get_visible()) + { + int nPos = 0; + pAutoCorrect->SetAutoCorrFlag(ACFlags::AddNonBrkSpace, m_xCheckLB->get_toggle(nPos++, CBCOL_FIRST) == TRISTATE_TRUE); + pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgOrdinalNumber, m_xCheckLB->get_toggle(nPos++, CBCOL_FIRST) == TRISTATE_TRUE); + pAutoCorrect->SetAutoCorrFlag(ACFlags::TransliterateRTL, m_xCheckLB->get_toggle(nPos++, CBCOL_FIRST) == TRISTATE_TRUE); + pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgAngleQuotes, m_xCheckLB->get_toggle(nPos++, CBCOL_FIRST) == TRISTATE_TRUE); + } + + bool bModified = false; + if (m_xSwCheckLB->get_visible()) + { + SvxSwAutoFormatFlags *pOpt = &pAutoCorrect->GetSwFlags(); + + bool bCheck = m_xSwCheckLB->get_toggle(ADD_NONBRK_SPACE, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bAddNonBrkSpace != bCheck; + pOpt->bAddNonBrkSpace = bCheck; + pAutoCorrect->SetAutoCorrFlag(ACFlags::AddNonBrkSpace, + m_xSwCheckLB->get_toggle(ADD_NONBRK_SPACE, CBCOL_SECOND) == TRISTATE_TRUE); + + bCheck = m_xSwCheckLB->get_toggle(REPLACE_1ST, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bChgOrdinalNumber != bCheck; + pOpt->bChgOrdinalNumber = bCheck; + pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgOrdinalNumber, + m_xSwCheckLB->get_toggle(REPLACE_1ST, CBCOL_SECOND) == TRISTATE_TRUE); + + bCheck = m_xSwCheckLB->get_toggle(TRANSLITERATE_RTL, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bTransliterateRTL != bCheck; + pOpt->bTransliterateRTL = bCheck; + pAutoCorrect->SetAutoCorrFlag(ACFlags::TransliterateRTL, + m_xSwCheckLB->get_toggle(TRANSLITERATE_RTL, CBCOL_SECOND) == TRISTATE_TRUE); + + bCheck = m_xSwCheckLB->get_toggle(REPLACE_ANGLE_QUOTES, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bChgAngleQuotes != bCheck; + pOpt->bChgAngleQuotes = bCheck; + pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgAngleQuotes, + m_xSwCheckLB->get_toggle(REPLACE_ANGLE_QUOTES, CBCOL_SECOND) == TRISTATE_TRUE); + } + + pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgQuotes, m_xDoubleTypoCB->get_active()); + pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgSglQuotes, m_xSingleTypoCB->get_active()); + bool bReturn = nFlags != pAutoCorrect->GetFlags(); + if(cStartQuote != pAutoCorrect->GetStartDoubleQuote()) + { + bReturn = true; + sal_Unicode cUCS2 = static_cast(cStartQuote); //TODO + pAutoCorrect->SetStartDoubleQuote(cUCS2); + } + if(cEndQuote != pAutoCorrect->GetEndDoubleQuote()) + { + bReturn = true; + sal_Unicode cUCS2 = static_cast(cEndQuote); //TODO + pAutoCorrect->SetEndDoubleQuote(cUCS2); + } + if(cSglStartQuote != pAutoCorrect->GetStartSingleQuote()) + { + bReturn = true; + sal_Unicode cUCS2 = static_cast(cSglStartQuote); //TODO + pAutoCorrect->SetStartSingleQuote(cUCS2); + } + if(cSglEndQuote != pAutoCorrect->GetEndSingleQuote()) + { + bReturn = true; + sal_Unicode cUCS2 = static_cast(cSglEndQuote); //TODO + pAutoCorrect->SetEndSingleQuote(cUCS2); + } + + if( bModified || bReturn ) + { + SvxAutoCorrCfg& rCfg = SvxAutoCorrCfg::Get(); + rCfg.SetModified(); + rCfg.Commit(); + } + return bReturn; +} + +void OfaQuoteTabPage::ActivatePage( const SfxItemSet& ) +{ + static_cast(GetDialogController())->EnableLanguage(false); +} + +void OfaQuoteTabPage::Reset( const SfxItemSet* ) +{ + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + const ACFlags nFlags = pAutoCorrect->GetFlags(); + + // Initialize the Sw options + if (m_xSwCheckLB->get_visible()) + { + SvxSwAutoFormatFlags *pOpt = &pAutoCorrect->GetSwFlags(); + + m_xSwCheckLB->freeze(); + m_xSwCheckLB->clear(); + + CreateEntry(*m_xSwCheckLB, sNonBrkSpace, CBCOL_BOTH, 2); + CreateEntry(*m_xSwCheckLB, sOrdinal, CBCOL_BOTH, 2); + CreateEntry(*m_xSwCheckLB, sTransliterateRTL, CBCOL_BOTH, 2); + CreateEntry(*m_xSwCheckLB, sAngleQuotes, CBCOL_BOTH, 2); + + m_xSwCheckLB->set_toggle(ADD_NONBRK_SPACE, pOpt->bAddNonBrkSpace ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xSwCheckLB->set_toggle(ADD_NONBRK_SPACE, bool(nFlags & ACFlags::AddNonBrkSpace) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xSwCheckLB->set_toggle(REPLACE_1ST, pOpt->bChgOrdinalNumber ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xSwCheckLB->set_toggle(REPLACE_1ST, bool(nFlags & ACFlags::ChgOrdinalNumber) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xSwCheckLB->set_toggle(TRANSLITERATE_RTL, pOpt->bTransliterateRTL ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xSwCheckLB->set_toggle(TRANSLITERATE_RTL, bool(nFlags & ACFlags::TransliterateRTL) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xSwCheckLB->set_toggle(REPLACE_ANGLE_QUOTES, pOpt->bChgAngleQuotes ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xSwCheckLB->set_toggle(REPLACE_ANGLE_QUOTES, bool(nFlags & ACFlags::ChgAngleQuotes) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + + m_xSwCheckLB->thaw(); + } + + // Initialize the non Sw options + if (m_xCheckLB->get_visible()) + { + m_xCheckLB->freeze(); + m_xCheckLB->clear(); + + CreateEntry(*m_xCheckLB, sNonBrkSpace, CBCOL_FIRST, 1); + CreateEntry(*m_xCheckLB, sOrdinal, CBCOL_FIRST, 1); + CreateEntry(*m_xCheckLB, sTransliterateRTL, CBCOL_FIRST, 1); + CreateEntry(*m_xCheckLB, sAngleQuotes, CBCOL_FIRST, 1); + + int nPos = 0; + m_xCheckLB->set_toggle(nPos++, bool(nFlags & ACFlags::AddNonBrkSpace) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(nPos++, bool(nFlags & ACFlags::ChgOrdinalNumber) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(nPos++, bool(nFlags & ACFlags::TransliterateRTL) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(nPos++, bool(nFlags & ACFlags::ChgAngleQuotes) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + + m_xCheckLB->thaw(); + } + + // Initialize the quote stuffs + m_xDoubleTypoCB->set_active(bool(nFlags & ACFlags::ChgQuotes)); + m_xSingleTypoCB->set_active(bool(nFlags & ACFlags::ChgSglQuotes)); + m_xDoubleTypoCB->save_state(); + m_xSingleTypoCB->save_state(); + + cStartQuote = pAutoCorrect->GetStartDoubleQuote(); + cEndQuote = pAutoCorrect->GetEndDoubleQuote(); + cSglStartQuote = pAutoCorrect->GetStartSingleQuote(); + cSglEndQuote = pAutoCorrect->GetEndSingleQuote(); + + m_xSglStartExFT->set_label(ChangeStringExt_Impl(cSglStartQuote)); + m_xSglEndExFT->set_label(ChangeStringExt_Impl(cSglEndQuote)); + m_xDblStartExFT->set_label(ChangeStringExt_Impl(cStartQuote)); + m_xDblEndExFT->set_label(ChangeStringExt_Impl(cEndQuote)); +} + +#define SGL_START 0 +#define DBL_START 1 +#define SGL_END 2 +#define DBL_END 3 + + +IMPL_LINK(OfaQuoteTabPage, QuoteHdl, weld::Button&, rBtn, void) +{ + sal_uInt16 nMode = SGL_START; + if (&rBtn == m_xSglEndQuotePB.get()) + nMode = SGL_END; + else if (&rBtn == m_xDblStartQuotePB.get()) + nMode = DBL_START; + else if (&rBtn == m_xDblEndQuotePB.get()) + nMode = DBL_END; + // start character selection dialog + SvxCharacterMap aMap(GetFrameWeld(), nullptr, nullptr); + aMap.SetCharFont( OutputDevice::GetDefaultFont(DefaultFontType::LATIN_TEXT, + LANGUAGE_ENGLISH_US, GetDefaultFontFlags::OnlyOne )); + aMap.set_title(nMode < SGL_END ? CuiResId(RID_SVXSTR_STARTQUOTE) : CuiResId(RID_SVXSTR_ENDQUOTE)); + sal_UCS4 cDlg; + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + LanguageType eLang = Application::GetSettings().GetLanguageTag().getLanguageType(); + switch( nMode ) + { + case SGL_START: + cDlg = cSglStartQuote; + if(cDlg == 0) + cDlg = pAutoCorrect->GetQuote('\'', true, eLang); + break; + case SGL_END: + cDlg = cSglEndQuote; + if(cDlg == 0) + cDlg = pAutoCorrect->GetQuote('\'', false, eLang); + break; + case DBL_START: + cDlg = cStartQuote; + if(cDlg == 0) + cDlg = pAutoCorrect->GetQuote('\"', true, eLang); + break; + case DBL_END: + cDlg = cEndQuote; + if(cDlg == 0) + cDlg = pAutoCorrect->GetQuote('\"', false, eLang); + break; + default: + OSL_FAIL("svx::OfaQuoteTabPage::QuoteHdl(), how to initialize cDlg?" ); + cDlg = 0; + break; + + } + aMap.SetChar( cDlg ); + aMap.DisableFontSelection(); + if (aMap.run() != RET_OK) + return; + + sal_UCS4 cNewChar = aMap.GetChar(); + switch( nMode ) + { + case SGL_START: + cSglStartQuote = cNewChar; + m_xSglStartExFT->set_label(ChangeStringExt_Impl(cNewChar)); + break; + case SGL_END: + cSglEndQuote = cNewChar; + m_xSglEndExFT->set_label(ChangeStringExt_Impl(cNewChar)); + break; + case DBL_START: + cStartQuote = cNewChar; + m_xDblStartExFT->set_label(ChangeStringExt_Impl(cNewChar)); + break; + case DBL_END: + cEndQuote = cNewChar; + m_xDblEndExFT->set_label(ChangeStringExt_Impl(cNewChar)); + break; + } +} + +IMPL_LINK(OfaQuoteTabPage, StdQuoteHdl, weld::Button&, rBtn, void) +{ + if (&rBtn == m_xDblStandardPB.get()) + { + cStartQuote = 0; + m_xDblStartExFT->set_label(ChangeStringExt_Impl(0)); + cEndQuote = 0; + m_xDblEndExFT->set_label(ChangeStringExt_Impl(0)); + + } + else + { + cSglStartQuote = 0; + m_xSglStartExFT->set_label(ChangeStringExt_Impl(0)); + cSglEndQuote = 0; + m_xSglEndExFT->set_label(ChangeStringExt_Impl(0)); + } +} + +OUString OfaQuoteTabPage::ChangeStringExt_Impl( sal_UCS4 cChar ) +{ + if (!cChar) + return m_sStandard; + + // convert codepoint value to unicode-hex string + sal_UCS4 aStrCodes[32] = { 0, ' ', '(', 'U', '+', '0' }; + aStrCodes[0] = cChar; + int nFullLen = 5; + int nHexLen = 4; + while( (cChar >> (4*nHexLen)) != 0 ) + ++nHexLen; + for( int i = nHexLen; --i >= 0;) + { + sal_UCS4 cHexDigit = ((cChar >> (4*i)) & 0x0f) + '0'; + if( cHexDigit > '9' ) + cHexDigit += 'A' - ('9' + 1); + aStrCodes[ nFullLen++ ] = cHexDigit; + } + aStrCodes[ nFullLen++ ] = ')'; + // using the new UCS4 constructor + OUString aOUStr( aStrCodes, nFullLen ); + return aOUStr; +} + +OfaAutoCompleteTabPage::OfaAutoCompleteTabPage(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/wordcompletionpage.ui", + "WordCompletionPage", &rSet) + , m_pAutoCompleteList(nullptr) + , m_nAutoCmpltListCnt(0) + , m_xCBActiv(m_xBuilder->weld_check_button("enablewordcomplete")) + , m_xCBAppendSpace(m_xBuilder->weld_check_button("appendspace")) + , m_xCBAsTip(m_xBuilder->weld_check_button("showastip")) + , m_xCBCollect(m_xBuilder->weld_check_button("collectwords")) + , m_xCBRemoveList(m_xBuilder->weld_check_button("whenclosing")) + , m_xDCBExpandKey(m_xBuilder->weld_combo_box("acceptwith")) + , m_xNFMinWordlen(m_xBuilder->weld_spin_button("minwordlen")) + , m_xNFMaxEntries(m_xBuilder->weld_spin_button("maxentries")) + , m_xLBEntries(m_xBuilder->weld_tree_view("entries")) + , m_xPBEntries(m_xBuilder->weld_button("delete")) +{ + //fdo#65595, we need height-for-width support here, but for now we can + //bodge it + Size aPrefSize(m_xCBRemoveList->get_preferred_size()); + int nMaxWidth = m_xCBRemoveList->get_approximate_digit_width() * 40; + if (aPrefSize.Width() > nMaxWidth) + { + m_xCBRemoveList->set_label_line_wrap(true); + m_xCBRemoveList->set_size_request(nMaxWidth, -1); + } + + m_xLBEntries->set_size_request(m_xLBEntries->get_approximate_digit_width() * 30, + m_xLBEntries->get_height_rows(10)); + + // the defined KEYs + static const sal_uInt16 aKeyCodes[] = { + KEY_END, + KEY_RETURN, + KEY_SPACE, + KEY_RIGHT, + KEY_TAB, + 0 + }; + + for( const sal_uInt16* pKeys = aKeyCodes; *pKeys; ++pKeys ) + { + vcl::KeyCode aKCode(*pKeys); + m_xDCBExpandKey->append(OUString::number(static_cast(*pKeys)), aKCode.GetName()); + if (KEY_RETURN == *pKeys) // default to RETURN + m_xDCBExpandKey->set_active(std::distance(aKeyCodes, pKeys)); + } + + m_xPBEntries->connect_clicked(LINK(this, OfaAutoCompleteTabPage, DeleteHdl)); + m_xCBActiv->connect_toggled(LINK(this, OfaAutoCompleteTabPage, CheckHdl)); + m_xCBCollect->connect_toggled(LINK(this, OfaAutoCompleteTabPage, CheckHdl)); + m_xLBEntries->connect_key_release(LINK(this, OfaAutoCompleteTabPage, KeyReleaseHdl)); +} + +OfaAutoCompleteTabPage::~OfaAutoCompleteTabPage() +{ +} + +std::unique_ptr OfaAutoCompleteTabPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rSet) +{ + return std::make_unique(pPage, pController, *rSet); +} + +bool OfaAutoCompleteTabPage::FillItemSet( SfxItemSet* ) +{ + bool bModified = false, bCheck; + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + SvxSwAutoFormatFlags *pOpt = &pAutoCorrect->GetSwFlags(); + sal_uInt16 nVal; + + bCheck = m_xCBActiv->get_active(); + bModified |= pOpt->bAutoCompleteWords != bCheck; + pOpt->bAutoCompleteWords = bCheck; + bCheck = m_xCBCollect->get_active(); + bModified |= pOpt->bAutoCmpltCollectWords != bCheck; + pOpt->bAutoCmpltCollectWords = bCheck; + bCheck = !m_xCBRemoveList->get_active(); // inverted value! + bModified |= pOpt->bAutoCmpltKeepList != bCheck; + pOpt->bAutoCmpltKeepList = bCheck; + bCheck = m_xCBAppendSpace->get_active(); + bModified |= pOpt->bAutoCmpltAppendBlanc != bCheck; + pOpt->bAutoCmpltAppendBlanc = bCheck; + bCheck = m_xCBAsTip->get_active(); + bModified |= pOpt->bAutoCmpltShowAsTip != bCheck; + pOpt->bAutoCmpltShowAsTip = bCheck; + + nVal = static_cast(m_xNFMinWordlen->get_value()); + bModified |= nVal != pOpt->nAutoCmpltWordLen; + pOpt->nAutoCmpltWordLen = nVal; + + nVal = static_cast(m_xNFMaxEntries->get_value()); + bModified |= nVal != pOpt->nAutoCmpltListLen; + pOpt->nAutoCmpltListLen = nVal; + + const int nPos = m_xDCBExpandKey->get_active(); + if (nPos != -1) + { + sal_Int32 nKey = m_xDCBExpandKey->get_id(nPos).toInt32(); + bModified |= nKey != pOpt->nAutoCmpltExpandKey; + pOpt->nAutoCmpltExpandKey = static_cast(nKey); + } + + if (m_pAutoCompleteList && m_nAutoCmpltListCnt != m_xLBEntries->n_children()) + { + bModified = true; + pOpt->m_pAutoCompleteList = m_pAutoCompleteList; + } + if( bModified ) + { + SvxAutoCorrCfg& rCfg = SvxAutoCorrCfg::Get(); + rCfg.SetModified(); + rCfg.Commit(); + } + return true; +} + +void OfaAutoCompleteTabPage::Reset( const SfxItemSet* ) +{ + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + SvxSwAutoFormatFlags *pOpt = &pAutoCorrect->GetSwFlags(); + + m_xCBActiv->set_active( pOpt->bAutoCompleteWords ); + m_xCBCollect->set_active( pOpt->bAutoCmpltCollectWords ); + m_xCBRemoveList->set_active( !pOpt->bAutoCmpltKeepList ); //inverted value! + m_xCBAppendSpace->set_active( pOpt->bAutoCmpltAppendBlanc ); + m_xCBAsTip->set_active( pOpt->bAutoCmpltShowAsTip ); + + m_xNFMinWordlen->set_value( pOpt->nAutoCmpltWordLen ); + m_xNFMaxEntries->set_value( pOpt->nAutoCmpltListLen ); + + // select the specific KeyCode: + { + sal_Int32 nKey = pOpt->nAutoCmpltExpandKey; + for (int n = 0, nCnt = m_xDCBExpandKey->get_count(); n < nCnt; ++n) + { + if (nKey == m_xDCBExpandKey->get_id(n).toInt32()) + { + m_xDCBExpandKey->set_active(n); + break; + } + } + } + + if (pOpt->m_pAutoCompleteList && !pOpt->m_pAutoCompleteList->empty()) + { + m_pAutoCompleteList = const_cast( + pOpt->m_pAutoCompleteList); + pOpt->m_pAutoCompleteList = nullptr; + m_nAutoCmpltListCnt = m_pAutoCompleteList->size(); + for (size_t n = 0; n < m_nAutoCmpltListCnt; ++n) + { + const OUString* pStr = + &(*m_pAutoCompleteList)[n]->GetAutoCompleteString(); + OUString sId(OUString::number(reinterpret_cast(pStr))); + m_xLBEntries->append(sId, *pStr); + } + } + else + { + m_xLBEntries->set_sensitive(false); + m_xPBEntries->set_sensitive(false); + } + + CheckHdl(*m_xCBActiv); + CheckHdl(*m_xCBCollect); +} + +void OfaAutoCompleteTabPage::ActivatePage( const SfxItemSet& ) +{ + static_cast(GetDialogController())->EnableLanguage( false ); +} + +IMPL_LINK_NOARG(OfaAutoCompleteTabPage, DeleteHdl, weld::Button&, void) +{ + auto rows = m_xLBEntries->get_selected_rows(); + std::sort(rows.begin(), rows.end()); + while (!rows.empty()) + { + sal_Int32 nPos = rows.back(); + OUString* pStr = reinterpret_cast(m_xLBEntries->get_id(nPos).toInt64()); + m_xLBEntries->remove(nPos); + editeng::IAutoCompleteString hack(*pStr); // UGLY + m_pAutoCompleteList->erase(&hack); + rows.pop_back(); + } +} + +IMPL_LINK(OfaAutoCompleteTabPage, CheckHdl, weld::ToggleButton&, rBox, void) +{ + bool bEnable = rBox.get_active(); + if (&rBox == m_xCBActiv.get()) + { + m_xCBAppendSpace->set_sensitive(bEnable); + m_xCBAppendSpace->set_sensitive(bEnable); + m_xCBAsTip->set_sensitive(bEnable); + m_xDCBExpandKey->set_sensitive(bEnable); + } + else if (&rBox == m_xCBCollect.get()) + m_xCBRemoveList->set_sensitive(bEnable); +} + +void OfaAutoCompleteTabPage::CopyToClipboard() const +{ + auto rows = m_xLBEntries->get_selected_rows(); + if (!(m_pAutoCompleteList && !rows.empty())) + return; + + rtl::Reference pCntnr = new TransferDataContainer; + + OStringBuffer sData; + + rtl_TextEncoding nEncode = osl_getThreadTextEncoding(); + + for (auto a : rows) + { + sData.append(OUStringToOString(m_xLBEntries->get_text(a), nEncode)); +#if defined(_WIN32) + sData.append("\015\012"); +#else + sData.append("\012"); +#endif + } + pCntnr->CopyByteString( SotClipboardFormatId::STRING, sData.makeStringAndClear() ); + pCntnr->CopyToClipboard(GetSystemClipboard()); +} + +IMPL_LINK(OfaAutoCompleteTabPage, KeyReleaseHdl, const KeyEvent&, rEvent, bool) +{ + bool bHandled = false; + const vcl::KeyCode& rKeyCode = rEvent.GetKeyCode(); + switch (rKeyCode.GetModifier() | rKeyCode.GetCode()) + { + case KEY_DELETE: + DeleteHdl(*m_xPBEntries); + bHandled = true; + break; + default: + if (KeyFuncType::COPY == rKeyCode.GetFunction()) + { + CopyToClipboard(); + bHandled = true; + } + break; + } + return bHandled; +} + +// class OfaSmartTagOptionsTabPage --------------------------------------------- + +OfaSmartTagOptionsTabPage::OfaSmartTagOptionsTabPage(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet& rSet ) + : SfxTabPage(pPage, pController, "cui/ui/smarttagoptionspage.ui", "SmartTagOptionsPage", &rSet) + , m_xMainCB(m_xBuilder->weld_check_button("main")) + , m_xSmartTagTypesLB(m_xBuilder->weld_tree_view("list")) + , m_xPropertiesPB(m_xBuilder->weld_button("properties")) +{ + m_xSmartTagTypesLB->set_size_request(m_xSmartTagTypesLB->get_approximate_digit_width() * 50, + m_xSmartTagTypesLB->get_height_rows(6)); + + std::vector aWidths; + aWidths.push_back(m_xSmartTagTypesLB->get_checkbox_column_width()); + m_xSmartTagTypesLB->set_column_fixed_widths(aWidths); + + // set the handlers: + m_xMainCB->connect_toggled(LINK(this, OfaSmartTagOptionsTabPage, CheckHdl)); + m_xPropertiesPB->connect_clicked(LINK(this, OfaSmartTagOptionsTabPage, ClickHdl)); + m_xSmartTagTypesLB->connect_changed(LINK(this, OfaSmartTagOptionsTabPage, SelectHdl)); +} + +OfaSmartTagOptionsTabPage::~OfaSmartTagOptionsTabPage() +{ +} + +std::unique_ptr OfaSmartTagOptionsTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet) +{ + return std::make_unique(pPage, pController, *rSet); +} + +namespace { + +/** This struct is used to associate list box entries with smart tag data +*/ +struct ImplSmartTagLBUserData +{ + OUString maSmartTagType; + uno::Reference< smarttags::XSmartTagRecognizer > mxRec; + sal_Int32 mnSmartTagIdx; + + ImplSmartTagLBUserData( const OUString& rSmartTagType, + uno::Reference< smarttags::XSmartTagRecognizer > const & xRec, + sal_Int32 nSmartTagIdx ) : + maSmartTagType( rSmartTagType ), + mxRec( xRec ), + mnSmartTagIdx( nSmartTagIdx ) {} +}; + +} + +/** Clears m_xSmartTagTypesLB +*/ +void OfaSmartTagOptionsTabPage::ClearListBox() +{ + const int nCount = m_xSmartTagTypesLB->n_children(); + for (int i = 0; i < nCount; ++i) + { + const ImplSmartTagLBUserData* pUserData = reinterpret_cast(m_xSmartTagTypesLB->get_id(i).toInt64()); + delete pUserData; + } + + m_xSmartTagTypesLB->clear(); +} + +/** Inserts items into m_xSmartTagTypesLB +*/ +void OfaSmartTagOptionsTabPage::FillListBox( const SmartTagMgr& rSmartTagMgr ) +{ + // first we have to clear the list box: + ClearListBox(); + + // fill list box: + const sal_uInt32 nNumberOfRecognizers = rSmartTagMgr.NumberOfRecognizers(); + const lang::Locale aLocale( LanguageTag::convertToLocale( eLastDialogLanguage ) ); + + for ( sal_uInt32 i = 0; i < nNumberOfRecognizers; ++i ) + { + const uno::Reference< smarttags::XSmartTagRecognizer >& xRec = rSmartTagMgr.GetRecognizer(i); + + const OUString aName = xRec->getName( aLocale ); + const sal_Int32 nNumberOfSupportedSmartTags = xRec->getSmartTagCount(); + + for ( sal_Int32 j = 0; j < nNumberOfSupportedSmartTags; ++j ) + { + const OUString aSmartTagType = xRec->getSmartTagName(j); + OUString aSmartTagCaption = rSmartTagMgr.GetSmartTagCaption( aSmartTagType, aLocale ); + + if ( aSmartTagCaption.isEmpty() ) + aSmartTagCaption = aSmartTagType; + + const OUString aLBEntry = aSmartTagCaption + " (" + aName + ")"; + + m_xSmartTagTypesLB->append(); + const int nRow = m_xSmartTagTypesLB->n_children() - 1; + const bool bCheck = rSmartTagMgr.IsSmartTagTypeEnabled( aSmartTagType ); + m_xSmartTagTypesLB->set_toggle(nRow, bCheck ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xSmartTagTypesLB->set_text(nRow, aLBEntry, 1); + m_xSmartTagTypesLB->set_id(nRow, OUString::number(reinterpret_cast(new ImplSmartTagLBUserData(aSmartTagType, xRec, j)))); + } + } +} + +/** Handler for the push button +*/ +IMPL_LINK_NOARG(OfaSmartTagOptionsTabPage, ClickHdl, weld::Button&, void) +{ + const int nPos = m_xSmartTagTypesLB->get_selected_index(); + const ImplSmartTagLBUserData* pUserData = reinterpret_cast(m_xSmartTagTypesLB->get_id(nPos).toInt64()); + uno::Reference< smarttags::XSmartTagRecognizer > xRec = pUserData->mxRec; + const sal_Int32 nSmartTagIdx = pUserData->mnSmartTagIdx; + + const lang::Locale aLocale( LanguageTag::convertToLocale( eLastDialogLanguage ) ); + if ( xRec->hasPropertyPage( nSmartTagIdx, aLocale ) ) + xRec->displayPropertyPage( nSmartTagIdx, aLocale ); +} + +/** Handler for the check box +*/ +IMPL_LINK_NOARG(OfaSmartTagOptionsTabPage, CheckHdl, weld::ToggleButton&, void) +{ + const bool bEnable = m_xMainCB->get_active(); + m_xSmartTagTypesLB->set_sensitive(bEnable); + m_xPropertiesPB->set_sensitive(false); + + // if the controls are currently enabled, we still have to check + // if the properties button should be disabled because the currently + // selected smart tag type does not have a properties dialog. + // We do this by calling SelectHdl: + if (bEnable) + SelectHdl(*m_xSmartTagTypesLB); +} + +/** Handler for the list box +*/ +IMPL_LINK_NOARG(OfaSmartTagOptionsTabPage, SelectHdl, weld::TreeView&, void) +{ + const int nPos = m_xSmartTagTypesLB->get_selected_index(); + if (nPos == -1) + return; + const ImplSmartTagLBUserData* pUserData = reinterpret_cast(m_xSmartTagTypesLB->get_id(nPos).toInt64()); + uno::Reference< smarttags::XSmartTagRecognizer > xRec = pUserData->mxRec; + const sal_Int32 nSmartTagIdx = pUserData->mnSmartTagIdx; + + const lang::Locale aLocale( LanguageTag::convertToLocale( eLastDialogLanguage ) ); + if ( xRec->hasPropertyPage( nSmartTagIdx, aLocale ) ) + m_xPropertiesPB->set_sensitive(true); + else + m_xPropertiesPB->set_sensitive(false); +} + +/** Propagates the current settings to the smart tag manager. +*/ +bool OfaSmartTagOptionsTabPage::FillItemSet( SfxItemSet* ) +{ + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + SvxSwAutoFormatFlags *pOpt = &pAutoCorrect->GetSwFlags(); + SmartTagMgr* pSmartTagMgr = pOpt->pSmartTagMgr; + + // robust! + if ( !pSmartTagMgr ) + return false; + + bool bModifiedSmartTagTypes = false; + std::vector< OUString > aDisabledSmartTagTypes; + + const int nCount = m_xSmartTagTypesLB->n_children(); + + for (int i = 0; i < nCount; ++i) + { + const ImplSmartTagLBUserData* pUserData = reinterpret_cast(m_xSmartTagTypesLB->get_id(i).toInt64()); + const bool bChecked = m_xSmartTagTypesLB->get_toggle(i, CBCOL_FIRST) == TRISTATE_TRUE; + const bool bIsCurrentlyEnabled = pSmartTagMgr->IsSmartTagTypeEnabled( pUserData->maSmartTagType ); + + bModifiedSmartTagTypes = bModifiedSmartTagTypes || ( !bChecked != !bIsCurrentlyEnabled ); + + if ( !bChecked ) + aDisabledSmartTagTypes.push_back( pUserData->maSmartTagType ); + + delete pUserData; + } + + const bool bModifiedRecognize = ( !m_xMainCB->get_active() != !pSmartTagMgr->IsLabelTextWithSmartTags() ); + if ( bModifiedSmartTagTypes || bModifiedRecognize ) + { + bool bLabelTextWithSmartTags = m_xMainCB->get_active(); + pSmartTagMgr->WriteConfiguration( bModifiedRecognize ? &bLabelTextWithSmartTags : nullptr, + bModifiedSmartTagTypes ? &aDisabledSmartTagTypes : nullptr ); + } + + return true; +} + +/** Sets the controls based on the current settings at SmartTagMgr. +*/ +void OfaSmartTagOptionsTabPage::Reset( const SfxItemSet* ) +{ + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + SvxSwAutoFormatFlags *pOpt = &pAutoCorrect->GetSwFlags(); + const SmartTagMgr* pSmartTagMgr = pOpt->pSmartTagMgr; + + // robust, should not happen! + if ( !pSmartTagMgr ) + return; + + FillListBox(*pSmartTagMgr); + m_xSmartTagTypesLB->select(0); + m_xMainCB->set_active(pSmartTagMgr->IsLabelTextWithSmartTags()); + CheckHdl(*m_xMainCB); +} + +void OfaSmartTagOptionsTabPage::ActivatePage( const SfxItemSet& ) +{ + static_cast(GetDialogController())->EnableLanguage( false ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/backgrnd.cxx b/cui/source/tabpages/backgrnd.cxx new file mode 100644 index 000000000..38190271d --- /dev/null +++ b/cui/source/tabpages/backgrnd.cxx @@ -0,0 +1,343 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace css; + +// table background +#define TBL_DEST_CELL 0 +#define TBL_DEST_ROW 1 +#define TBL_DEST_TBL 2 + +const sal_uInt16 SvxBkgTabPage::pPageRanges[] = +{ + SID_ATTR_BRUSH, SID_ATTR_BRUSH, + SID_ATTR_BRUSH_CHAR, SID_ATTR_BRUSH_CHAR, + 0 +}; + +static sal_uInt16 lcl_GetTableDestSlot(sal_Int32 nTblDest) +{ + switch (nTblDest) + { + default: + case TBL_DEST_CELL: + { + return SID_ATTR_BRUSH; + } + case TBL_DEST_ROW: + { + return SID_ATTR_BRUSH_ROW; + } + case TBL_DEST_TBL: + { + return SID_ATTR_BRUSH_TABLE; + } + } +} + +SvxBkgTabPage::SvxBkgTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SvxAreaTabPage(pPage, pController, rInAttrs), + bHighlighting(false), + bCharBackColor(false), + maSet(rInAttrs) +{ + m_xBtnGradient->hide(); + m_xBtnHatch->hide(); + m_xBtnBitmap->hide(); + m_xBtnPattern->hide(); + + SfxObjectShell* pDocSh = SfxObjectShell::Current(); + + XColorListRef pColorTable; + if ( pDocSh ) + if (auto pItem = pDocSh->GetItem( SID_COLOR_TABLE )) + pColorTable = pItem->GetColorList(); + + if ( !pColorTable.is() ) + pColorTable = XColorList::CreateStdColorList(); + + XBitmapListRef pBitmapList; + if ( pDocSh ) + if (auto pItem = pDocSh->GetItem( SID_BITMAP_LIST ) ) + pBitmapList = pItem->GetBitmapList(); + + SetColorList(pColorTable); + SetBitmapList(pBitmapList); +} + +SvxBkgTabPage::~SvxBkgTabPage() +{ + m_xTblLBox.reset(); +} + +void SvxBkgTabPage::ActivatePage( const SfxItemSet& ) +{ + SvxAreaTabPage::ActivatePage( maSet ); +} + +DeactivateRC SvxBkgTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if ( DeactivateRC::KeepPage == SvxAreaTabPage::DeactivatePage( &maSet ) ) + return DeactivateRC::KeepPage; + + if ( _pSet ) + FillItemSet( _pSet ); + + return DeactivateRC::LeavePage; +} + +void SvxBkgTabPage::Reset( const SfxItemSet* ) +{ + maSet.Set( *m_pResetSet ); + if ( m_xTblLBox && m_xTblLBox->get_visible() ) + { + m_nActPos = -1; + const SfxPoolItem* pItem; + if ( SfxItemState::SET == m_pResetSet->GetItemState( SID_BACKGRND_DESTINATION, false, &pItem ) ) + { + sal_uInt16 nDestValue = static_cast(pItem)->GetValue(); + m_xTblLBox->set_active( nDestValue ); + TblDestinationHdl_Impl( *m_xTblLBox ); + } + m_xTblLBox->save_value(); + } + SvxAreaTabPage::Reset( &maSet ); +} + +bool SvxBkgTabPage::FillItemSet( SfxItemSet* rCoreSet ) +{ + sal_uInt16 nSlot = SID_ATTR_BRUSH; + if (m_xTblLBox && m_xTblLBox->get_visible()) + nSlot = lcl_GetTableDestSlot(m_xTblLBox->get_active()); + else if ( bHighlighting ) + nSlot = SID_ATTR_BRUSH_CHAR; + else if( bCharBackColor ) + nSlot = SID_ATTR_CHAR_BACK_COLOR; + + sal_uInt16 nWhich = GetWhich(nSlot); + + drawing::FillStyle eFillType = maSet.Get( XATTR_FILLSTYLE ).GetValue(); + switch( eFillType ) + { + case drawing::FillStyle_NONE: + { + if ( IsBtnClicked() ) + { + if ( SID_ATTR_CHAR_BACK_COLOR == nSlot ) + { + maSet.Put( SvxBackgroundColorItem( COL_TRANSPARENT, nWhich ) ); + rCoreSet->Put( SvxBackgroundColorItem( COL_TRANSPARENT, nWhich ) ); + } + else + { + maSet.Put( SvxBrushItem( COL_TRANSPARENT, nWhich ) ); + rCoreSet->Put( SvxBrushItem( COL_TRANSPARENT, nWhich ) ); + } + } + break; + } + case drawing::FillStyle_SOLID: + { + XFillColorItem aColorItem( maSet.Get( XATTR_FILLCOLOR ) ); + if ( SID_ATTR_CHAR_BACK_COLOR == nSlot ) + { + maSet.Put( SvxBackgroundColorItem( aColorItem.GetColorValue(), nWhich ) ); + rCoreSet->Put( SvxBackgroundColorItem( aColorItem.GetColorValue(), nWhich ) ); + } + else + { + maSet.Put( SvxBrushItem( aColorItem.GetColorValue(), nWhich ) ); + rCoreSet->Put( SvxBrushItem( aColorItem.GetColorValue(), nWhich ) ); + } + break; + } + case drawing::FillStyle_BITMAP: + { + std::unique_ptr aBrushItem( getSvxBrushItemFromSourceSet( maSet, nWhich ) ); + if ( GraphicType::NONE != aBrushItem->GetGraphicObject()->GetType() ) + rCoreSet->Put( *aBrushItem ); + break; + } + default: + break; + } + + if (m_xTblLBox && m_xTblLBox->get_visible()) + { + if (nSlot != SID_ATTR_BRUSH) + { + nWhich = maSet.GetPool()->GetWhich(SID_ATTR_BRUSH); + if (SfxItemState::SET == maSet.GetItemState(nWhich)) + { + SvxBrushItem aBrushItem(static_cast(maSet.Get(nWhich))); + rCoreSet->Put(aBrushItem); + } + } + if (nSlot != SID_ATTR_BRUSH_ROW) + { + nWhich = maSet.GetPool()->GetWhich(SID_ATTR_BRUSH_ROW); + if (SfxItemState::SET == maSet.GetItemState(nWhich)) + { + SvxBrushItem aBrushItem(static_cast(maSet.Get(nWhich))); + rCoreSet->Put(aBrushItem); + } + } + if (nSlot != SID_ATTR_BRUSH_TABLE) + { + nWhich = maSet.GetPool()->GetWhich(SID_ATTR_BRUSH_TABLE); + if (SfxItemState::SET == maSet.GetItemState(nWhich)) + { + SvxBrushItem aBrushItem(static_cast(maSet.Get(nWhich))); + rCoreSet->Put(aBrushItem); + } + } + + if (m_xTblLBox->get_value_changed_from_saved()) + { + rCoreSet->Put(SfxUInt16Item(SID_BACKGRND_DESTINATION, m_xTblLBox->get_active())); + } + } + + return true; +} + +std::unique_ptr SvxBkgTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrs) +{ + auto xRet = std::make_unique(pPage, pController, *rAttrs); + xRet->SetOptimalSize(pController); + return xRet; +} + +void SvxBkgTabPage::PageCreated(const SfxAllItemSet& aSet) +{ + const SfxUInt32Item* pFlagItem = aSet.GetItem(SID_FLAG_TYPE, false); + if (pFlagItem) + { + SvxBackgroundTabFlags nFlags = static_cast(pFlagItem->GetValue()); + if ( nFlags & SvxBackgroundTabFlags::SHOW_TBLCTL ) + { + m_xBtnBitmap->show(); + m_xTblLBox = m_xBuilder->weld_combo_box("tablelb"); + m_xTblLBox->connect_changed(LINK(this, SvxBkgTabPage, TblDestinationHdl_Impl)); + m_xTblLBox->show(); + } + if ((nFlags & SvxBackgroundTabFlags::SHOW_HIGHLIGHTING) || + (nFlags & SvxBackgroundTabFlags::SHOW_CHAR_BKGCOLOR)) + { + bHighlighting = bool(nFlags & SvxBackgroundTabFlags::SHOW_HIGHLIGHTING); + bCharBackColor = bool(nFlags & SvxBackgroundTabFlags::SHOW_CHAR_BKGCOLOR); + } + if (nFlags & SvxBackgroundTabFlags::SHOW_SELECTOR) + m_xBtnBitmap->show(); + SetOptimalSize(GetDialogController()); + } + + if ( bCharBackColor ) + { + sal_uInt16 nWhich(maSet.GetPool()->GetWhich(SID_ATTR_CHAR_BACK_COLOR)); + Color aBackColor(static_cast(maSet.Get(nWhich)).GetValue()); + SvxBrushItem aBrushItem(SvxBrushItem(aBackColor, SID_ATTR_BRUSH_CHAR)); + setSvxBrushItemAsFillAttributesToTargetSet(aBrushItem, maSet); + } + else + { + sal_uInt16 nWhich(maSet.GetPool()->GetWhich(bHighlighting ? SID_ATTR_BRUSH_CHAR : SID_ATTR_BRUSH)); + SvxBrushItem aBrushItem(static_cast(maSet.Get(nWhich))); + setSvxBrushItemAsFillAttributesToTargetSet(aBrushItem, maSet); + } + + m_pResetSet = maSet.Clone(); + + SvxAreaTabPage::PageCreated(aSet); +} + +IMPL_LINK(SvxBkgTabPage, TblDestinationHdl_Impl, weld::ComboBox&, rBox, void) +{ + if (m_nActPos > -1) + { + // fill local item set with XATTR_FILL settings gathered from tab page + // and convert to SvxBrushItem and store in table destination slot Which + SvxAreaTabPage::FillItemSet(&maSet); + maSet.Put(*getSvxBrushItemFromSourceSet(maSet, maSet.GetPool()->GetWhich(lcl_GetTableDestSlot(m_nActPos)))); + } + + sal_Int32 nSelPos = rBox.get_active(); + if (m_nActPos == nSelPos) + return; + + m_nActPos = nSelPos; + + // fill local item set with XATTR_FILL created from SvxBushItem for table destination slot Which + sal_uInt16 nWhich = maSet.GetPool()->GetWhich(lcl_GetTableDestSlot(nSelPos)); + if (SfxItemState::SET == maSet.GetItemState(nWhich)) + { + SvxBrushItem aBrushItem(static_cast(maSet.Get(nWhich))); + setSvxBrushItemAsFillAttributesToTargetSet(aBrushItem, maSet); + } + else + { + SelectFillType(*m_xBtnNone, &maSet); + return; + } + + // show tab page + drawing::FillStyle eXFS = drawing::FillStyle_NONE; + if (maSet.GetItemState(XATTR_FILLSTYLE) != SfxItemState::DONTCARE) + { + XFillStyleItem aFillStyleItem(static_cast(maSet.Get(GetWhich( XATTR_FILLSTYLE)))); + eXFS = aFillStyleItem.GetValue(); + } + switch(eXFS) + { + default: + case drawing::FillStyle_NONE: + { + SelectFillType(*m_xBtnNone, &maSet); + break; + } + case drawing::FillStyle_SOLID: + { + SelectFillType(*m_xBtnColor, &maSet); + // color tab page Active and New preview controls are same after SelectFillType + // hack to restore color tab page Active preview + setSvxBrushItemAsFillAttributesToTargetSet(static_cast(m_pResetSet->Get(nWhich)), *m_pResetSet); + static_cast(GetFillTabPage())->SetCtlPreviewOld(*m_pResetSet); + break; + } + case drawing::FillStyle_BITMAP: + { + SelectFillType(*m_xBtnBitmap, &maSet); + break; + } + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/bbdlg.cxx b/cui/source/tabpages/bbdlg.cxx new file mode 100644 index 000000000..d21d046da --- /dev/null +++ b/cui/source/tabpages/bbdlg.cxx @@ -0,0 +1,90 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include + +SvxBorderBackgroundDlg::SvxBorderBackgroundDlg(weld::Window *pParent, + const SfxItemSet& rCoreSet, + bool bEnableSelector, + bool bEnableDrawingLayerFillStyles) + : SfxTabDialogController(pParent, + bEnableDrawingLayerFillStyles + ? OUString("cui/ui/borderareatransparencydialog.ui") + : OUString("cui/ui/borderbackgrounddialog.ui"), + bEnableDrawingLayerFillStyles + ? OString("BorderAreaTransparencyDialog") + : OString("BorderBackgroundDialog"), + &rCoreSet) + , mbEnableBackgroundSelector(bEnableSelector) +{ + AddTabPage("borders", SvxBorderTabPage::Create, nullptr ); + if (bEnableDrawingLayerFillStyles) + { + // Here we want full DrawingLayer FillStyle access, so add Area and Transparency TabPages + AddTabPage("area", SvxAreaTabPage::Create, nullptr); + AddTabPage("transparence", SvxTransparenceTabPage::Create, nullptr); + } + else + { + AddTabPage("background", SvxBkgTabPage::Create, nullptr ); + } +} + +void SvxBorderBackgroundDlg::PageCreated(const OString& rPageId, SfxTabPage& rTabPage) +{ + if (rPageId == "background") + { + SfxAllItemSet aSet(*(GetInputSetImpl()->GetPool())); + // allow switching between Color/graphic + if (mbEnableBackgroundSelector) + aSet.Put(SfxUInt32Item(SID_FLAG_TYPE, static_cast(SvxBackgroundTabFlags::SHOW_SELECTOR))); + rTabPage.PageCreated(aSet); + } + // inits for Area and Transparency TabPages + // The selection attribute lists (XPropertyList derivates, e.g. XColorList for + // the color table) need to be added as items (e.g. SvxColorTableItem) to make + // these pages find the needed attributes for fill style suggestions. + // These are added in SwDocStyleSheet::GetItemSet() for the SfxStyleFamily::Para on + // demand, but could also be directly added from the DrawModel. + else if (rPageId == "area") + { + SfxItemSet aNew( + *GetInputSetImpl()->GetPool(), + svl::Items{}); + + aNew.Put(*GetInputSetImpl()); + + // add flag for direct graphic content selection + aNew.Put(SfxBoolItem(SID_OFFER_IMPORT, true)); + + rTabPage.PageCreated(aNew); + } + else if (rPageId == "transparence") + { + rTabPage.PageCreated(*GetInputSetImpl()); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/border.cxx b/cui/source/tabpages/border.cxx new file mode 100644 index 000000000..ed6c1add9 --- /dev/null +++ b/cui/source/tabpages/border.cxx @@ -0,0 +1,1522 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace ::editeng; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::lang::XServiceInfo; +using ::com::sun::star::uno::UNO_QUERY; + + +/* + * [Description:] + * TabPage for setting the border attributes. + * Needs + * a SvxShadowItem: shadow + * a SvxBoxItem: lines left, right, top, bottom, + * a SvxBoxInfo: lines vertical, horizontal, distance, flags + * + * Lines can have three conditions: + * 1. Show ( -> valid values ) + * 2. Hide ( -> NULL-Pointer ) + * 3. DontCare ( -> special Valid-Flags in the InfoItem ) + */ + +// static ---------------------------------------------------------------- + +const sal_uInt16 SvxBorderTabPage::pRanges[] = +{ + SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_SHADOW, + SID_ATTR_ALIGN_MARGIN, SID_ATTR_ALIGN_MARGIN, + SID_ATTR_BORDER_CONNECT, SID_ATTR_BORDER_CONNECT, + SID_SW_COLLAPSING_BORDERS, SID_SW_COLLAPSING_BORDERS, + SID_ATTR_BORDER_DIAG_TLBR, SID_ATTR_BORDER_DIAG_BLTR, + 0 +}; + +static void lcl_SetDecimalDigitsTo1(weld::MetricSpinButton& rField) +{ + auto nMin = rField.denormalize(rField.get_min(FieldUnit::TWIP)); + rField.set_digits(1); + rField.set_min(rField.normalize(nMin), FieldUnit::TWIP); +} + +// number of preset images to show +const sal_uInt16 SVX_BORDER_PRESET_COUNT = 5; + +// number of shadow images to show +const sal_uInt16 SVX_BORDER_SHADOW_COUNT = 5; + +ShadowControlsWrapper::ShadowControlsWrapper(ValueSet& rVsPos, weld::MetricSpinButton& rMfSize, ColorListBox& rLbColor) + : mrVsPos(rVsPos) + , mrMfSize(rMfSize) + , mrLbColor(rLbColor) +{ +} + +SvxShadowItem ShadowControlsWrapper::GetControlValue(const SvxShadowItem& rItem) const +{ + SvxShadowItem aItem(rItem); + if (!mrVsPos.IsNoSelection()) + { + switch (mrVsPos.GetSelectedItemId()) + { + case 1: + aItem.SetLocation(SvxShadowLocation::NONE); + break; + case 2: + aItem.SetLocation(SvxShadowLocation::BottomRight); + break; + case 3: + aItem.SetLocation(SvxShadowLocation::TopRight); + break; + case 4: + aItem.SetLocation(SvxShadowLocation::BottomLeft); + break; + case 5: + aItem.SetLocation(SvxShadowLocation::TopLeft); + break; + default: + aItem.SetLocation(SvxShadowLocation::NONE); + break; + } + } + // Default value was saved; so don't change the aItem's width if the control + // has not changed its value, to avoid round-trip errors (like twip->cm->twip) + // E.g., initial 100 twip will become 0.18 cm, which will return as 102 twip + if (mrMfSize.get_value_changed_from_saved()) + aItem.SetWidth(mrMfSize.denormalize(mrMfSize.get_value(FieldUnit::TWIP))); + if (!mrLbColor.IsNoSelection()) + aItem.SetColor(mrLbColor.GetSelectEntryColor()); + return aItem; +} + +void ShadowControlsWrapper::SetControlValue(const SvxShadowItem& rItem) +{ + switch (rItem.GetLocation()) + { + case SvxShadowLocation::NONE: + mrVsPos.SelectItem(1); + break; + case SvxShadowLocation::BottomRight: + mrVsPos.SelectItem(2); + break; + case SvxShadowLocation::TopRight: + mrVsPos.SelectItem(3); + break; + case SvxShadowLocation::BottomLeft: + mrVsPos.SelectItem(4); + break; + case SvxShadowLocation::TopLeft: + mrVsPos.SelectItem(5); + break; + default: + mrVsPos.SetNoSelection(); + break; + } + mrVsPos.SaveValue(); + mrMfSize.set_value(mrMfSize.normalize(rItem.GetWidth()), FieldUnit::TWIP); + mrMfSize.save_value(); + mrLbColor.SelectEntry(rItem.GetColor()); + mrLbColor.SaveValue(); +} + +bool ShadowControlsWrapper::get_value_changed_from_saved() const +{ + return mrVsPos.IsValueChangedFromSaved() || + mrMfSize.get_value_changed_from_saved() || + mrLbColor.IsValueChangedFromSaved(); +} + +void ShadowControlsWrapper::SetControlDontKnow() +{ + mrVsPos.SetNoSelection(); + mrMfSize.set_text(""); + mrLbColor.SetNoSelection(); +} + +MarginControlsWrapper::MarginControlsWrapper(weld::MetricSpinButton& rMfLeft, weld::MetricSpinButton& rMfRight, + weld::MetricSpinButton& rMfTop, weld::MetricSpinButton& rMfBottom) + : mrLeftWrp(rMfLeft) + , mrRightWrp(rMfRight) + , mrTopWrp(rMfTop) + , mrBottomWrp(rMfBottom) +{ +} + +SvxMarginItem MarginControlsWrapper::GetControlValue(const SvxMarginItem &rItem) const +{ + SvxMarginItem aItem(rItem); + if (mrLeftWrp.get_sensitive()) + aItem.SetLeftMargin(mrLeftWrp.denormalize(mrLeftWrp.get_value(FieldUnit::TWIP))); + if (mrRightWrp.get_sensitive()) + aItem.SetRightMargin(mrRightWrp.denormalize(mrRightWrp.get_value(FieldUnit::TWIP))); + if (mrTopWrp.get_sensitive()) + aItem.SetTopMargin(mrTopWrp.denormalize(mrTopWrp.get_value(FieldUnit::TWIP))); + if (mrBottomWrp.get_sensitive()) + aItem.SetBottomMargin(mrBottomWrp.denormalize(mrBottomWrp.get_value(FieldUnit::TWIP))); + return aItem; +} + +bool MarginControlsWrapper::get_value_changed_from_saved() const +{ + return mrLeftWrp.get_value_changed_from_saved() || + mrRightWrp.get_value_changed_from_saved() || + mrTopWrp.get_value_changed_from_saved() || + mrBottomWrp.get_value_changed_from_saved(); +} + +void MarginControlsWrapper::SetControlValue(const SvxMarginItem& rItem) +{ + mrLeftWrp.set_value(mrLeftWrp.normalize(rItem.GetLeftMargin()), FieldUnit::TWIP); + mrRightWrp.set_value(mrRightWrp.normalize(rItem.GetRightMargin()), FieldUnit::TWIP); + mrTopWrp.set_value(mrTopWrp.normalize(rItem.GetTopMargin()), FieldUnit::TWIP); + mrBottomWrp.set_value(mrBottomWrp.normalize(rItem.GetBottomMargin()), FieldUnit::TWIP); + mrLeftWrp.save_value(); + mrRightWrp.save_value(); + mrTopWrp.save_value(); + mrBottomWrp.save_value(); +} + +void MarginControlsWrapper::SetControlDontKnow() +{ + const OUString sEmpty; + mrLeftWrp.set_text(sEmpty); + mrRightWrp.set_text(sEmpty); + mrTopWrp.set_text(sEmpty); + mrBottomWrp.set_text(sEmpty); +} + +SvxBorderTabPage::SvxBorderTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs) + : SfxTabPage(pPage, pController, "cui/ui/borderpage.ui", "BorderPage", &rCoreAttrs) + , nMinValue(0) + , nSWMode(SwBorderModes::NONE) + , mnBoxSlot(SID_ATTR_BORDER_OUTER) + , mnShadowSlot(SID_ATTR_BORDER_SHADOW) + , mbHorEnabled(false) + , mbVerEnabled(false) + , mbTLBREnabled(false) + , mbBLTREnabled(false) + , mbUseMarginItem(false) + , mbLeftModified(false) + , mbRightModified(false) + , mbTopModified(false) + , mbBottomModified(false) + , mbSync(true) + , mbRemoveAdjacentCellBorders(false) + , bIsCalcDoc(false) + , m_xWndPresets(new ValueSet(nullptr)) + , m_xWndPresetsWin(new weld::CustomWeld(*m_xBuilder, "presets", *m_xWndPresets)) + , m_xUserDefFT(m_xBuilder->weld_label("userdefft")) + , m_xFrameSelWin(new weld::CustomWeld(*m_xBuilder, "framesel", m_aFrameSel)) + , m_xLbLineStyle(new SvtLineListBox(m_xBuilder->weld_menu_button("linestylelb"))) + , m_xLbLineColor(new ColorListBox(m_xBuilder->weld_menu_button("linecolorlb"), pController->getDialog())) + , m_xLineWidthMF(m_xBuilder->weld_metric_spin_button("linewidthmf", FieldUnit::POINT)) + , m_xSpacingFrame(m_xBuilder->weld_container("spacing")) + , m_xLeftFT(m_xBuilder->weld_label("leftft")) + , m_xLeftMF(m_xBuilder->weld_metric_spin_button("leftmf", FieldUnit::MM)) + , m_xRightFT(m_xBuilder->weld_label("rightft")) + , m_xRightMF(m_xBuilder->weld_metric_spin_button("rightmf", FieldUnit::MM)) + , m_xTopFT(m_xBuilder->weld_label("topft")) + , m_xTopMF(m_xBuilder->weld_metric_spin_button("topmf", FieldUnit::MM)) + , m_xBottomFT(m_xBuilder->weld_label("bottomft")) + , m_xBottomMF(m_xBuilder->weld_metric_spin_button("bottommf", FieldUnit::MM)) + , m_xSynchronizeCB(m_xBuilder->weld_check_button("sync")) + , m_xShadowFrame(m_xBuilder->weld_container("shadow")) + , m_xWndShadows(new ValueSet(nullptr)) + , m_xWndShadowsWin(new weld::CustomWeld(*m_xBuilder, "shadows", *m_xWndShadows)) + , m_xFtShadowSize(m_xBuilder->weld_label("distanceft")) + , m_xEdShadowSize(m_xBuilder->weld_metric_spin_button("distancemf", FieldUnit::MM)) + , m_xFtShadowColor(m_xBuilder->weld_label("shadowcolorft")) + , m_xLbShadowColor(new ColorListBox(m_xBuilder->weld_menu_button("shadowcolorlb"), pController->getDialog())) + , m_xPropertiesFrame(m_xBuilder->weld_container("properties")) + , m_xMergeWithNextCB(m_xBuilder->weld_check_button("mergewithnext")) + , m_xMergeAdjacentBordersCB(m_xBuilder->weld_check_button("mergeadjacent")) + , m_xRemoveAdjcentCellBordersCB(m_xBuilder->weld_check_button("rmadjcellborders")) + , m_xRemoveAdjcentCellBordersFT(m_xBuilder->weld_label("rmadjcellbordersft")) +{ + static std::vector aBorderImageIds; + + if (aBorderImageIds.empty()) + { + if (comphelper::LibreOfficeKit::isActive()) + { + aBorderImageIds.insert(aBorderImageIds.end(), { + RID_SVXBMP_CELL_NONE_32, + RID_SVXBMP_CELL_ALL_32, + RID_SVXBMP_CELL_LR_32, + RID_SVXBMP_CELL_TB_32, + RID_SVXBMP_CELL_L_32, + RID_SVXBMP_CELL_DIAG_32 + }); + } + else + { + aBorderImageIds.insert(aBorderImageIds.end(), { + RID_SVXBMP_CELL_NONE, + RID_SVXBMP_CELL_ALL, + RID_SVXBMP_CELL_LR, + RID_SVXBMP_CELL_TB, + RID_SVXBMP_CELL_L, + RID_SVXBMP_CELL_DIAG + }); + } + aBorderImageIds.insert(aBorderImageIds.end(), { + RID_SVXBMP_HOR_NONE, + RID_SVXBMP_HOR_OUTER, + RID_SVXBMP_HOR_HOR, + RID_SVXBMP_HOR_ALL, + RID_SVXBMP_HOR_OUTER2, + RID_SVXBMP_VER_NONE, + RID_SVXBMP_VER_OUTER, + RID_SVXBMP_VER_VER, + RID_SVXBMP_VER_ALL, + RID_SVXBMP_VER_OUTER2, + RID_SVXBMP_TABLE_NONE, + RID_SVXBMP_TABLE_OUTER, + RID_SVXBMP_TABLE_OUTERH, + RID_SVXBMP_TABLE_ALL, + RID_SVXBMP_TABLE_OUTER2 + }); + } + + for (auto const & rImageId : aBorderImageIds) + m_aBorderImgVec.emplace_back(StockImage::Yes, rImageId); + + static std::vector aShadowImageIds; + if (aShadowImageIds.empty()) + { + if (comphelper::LibreOfficeKit::isActive()) + { + aShadowImageIds.insert(aShadowImageIds.end(), { + RID_SVXBMP_SHADOWNONE_32, + RID_SVXBMP_SHADOW_BOT_RIGHT_32, + RID_SVXBMP_SHADOW_TOP_RIGHT_32, + RID_SVXBMP_SHADOW_BOT_LEFT_32, + RID_SVXBMP_SHADOW_TOP_LEFT_32 + }); + } + else + { + aShadowImageIds.insert(aShadowImageIds.end(), { + RID_SVXBMP_SHADOWNONE, + RID_SVXBMP_SHADOW_BOT_RIGHT, + RID_SVXBMP_SHADOW_TOP_RIGHT, + RID_SVXBMP_SHADOW_BOT_LEFT, + RID_SVXBMP_SHADOW_TOP_LEFT + }); + } + } + + for (auto const & rImageId : aShadowImageIds) + m_aShadowImgVec.emplace_back(StockImage::Yes, rImageId); + + assert(m_aShadowImgVec.size() == SVX_BORDER_SHADOW_COUNT); + + // this page needs ExchangeSupport + SetExchangeSupport(); + + /* Use SvxMarginItem instead of margins from SvxBoxItem, if present. + -> Remember this state in mbUseMarginItem, because other special handling + is needed across various functions... */ + mbUseMarginItem = rCoreAttrs.GetItemState(GetWhich(SID_ATTR_ALIGN_MARGIN)) != SfxItemState::UNKNOWN; + + const SfxPoolItem* pItem = nullptr; + if (rCoreAttrs.HasItem(SID_ATTR_BORDER_STYLES, &pItem)) + { + const SfxIntegerListItem* p = static_cast(pItem); + std::vector aUsedStyles = p->GetList(); + for (int aUsedStyle : aUsedStyles) + maUsedBorderStyles.insert(static_cast(aUsedStyle)); + } + + if (rCoreAttrs.HasItem(SID_ATTR_BORDER_DEFAULT_WIDTH, &pItem)) + { + // The caller specifies default line width. Honor it. + const SfxInt64Item* p = static_cast(pItem); + m_xLineWidthMF->set_value(p->GetValue(), FieldUnit::POINT); + } + + // set metric + FieldUnit eFUnit = GetModuleFieldUnit( rCoreAttrs ); + + if( mbUseMarginItem ) + { + // copied from SvxAlignmentTabPage + switch ( eFUnit ) + { + // #103396# the default value (1pt) can't be accurately represented in + // inches or pica with two decimals, so point is used instead. + case FieldUnit::PICA: + case FieldUnit::INCH: + case FieldUnit::FOOT: + case FieldUnit::MILE: + eFUnit = FieldUnit::POINT; + break; + + case FieldUnit::CM: + case FieldUnit::M: + case FieldUnit::KM: + eFUnit = FieldUnit::MM; + break; + default: ;//prevent warning + } + } + else + { + switch ( eFUnit ) + { + case FieldUnit::M: + case FieldUnit::KM: + eFUnit = FieldUnit::MM; + break; + default: ; //prevent warning + } + } + + SetFieldUnit(*m_xEdShadowSize, eFUnit); + + sal_uInt16 nWhich = GetWhich( SID_ATTR_BORDER_INNER, false ); + bool bIsDontCare = true; + + if ( rCoreAttrs.GetItemState( nWhich ) >= SfxItemState::DEFAULT ) + { + // paragraph or table + const SvxBoxInfoItem* pBoxInfo = + static_cast(&( rCoreAttrs.Get( nWhich ) )); + + mbHorEnabled = pBoxInfo->IsHorEnabled(); + mbVerEnabled = pBoxInfo->IsVerEnabled(); + mbTLBREnabled = rCoreAttrs.GetItemState(GetWhich(SID_ATTR_BORDER_DIAG_TLBR)) != SfxItemState::UNKNOWN; + mbBLTREnabled = rCoreAttrs.GetItemState(GetWhich(SID_ATTR_BORDER_DIAG_BLTR)) != SfxItemState::UNKNOWN; + + if(pBoxInfo->IsDist()) + { + SetFieldUnit(*m_xLeftMF, eFUnit); + SetFieldUnit(*m_xRightMF, eFUnit); + SetFieldUnit(*m_xTopMF, eFUnit); + SetFieldUnit(*m_xBottomMF, eFUnit); + m_xSynchronizeCB->connect_toggled(LINK(this, SvxBorderTabPage, SyncHdl_Impl)); + m_xLeftMF->connect_value_changed(LINK(this, SvxBorderTabPage, ModifyDistanceHdl_Impl)); + m_xRightMF->connect_value_changed(LINK(this, SvxBorderTabPage, ModifyDistanceHdl_Impl)); + m_xTopMF->connect_value_changed(LINK(this, SvxBorderTabPage, ModifyDistanceHdl_Impl)); + m_xBottomMF->connect_value_changed(LINK(this, SvxBorderTabPage, ModifyDistanceHdl_Impl)); + } + else + { + m_xSpacingFrame->hide(); + } + bIsDontCare = !pBoxInfo->IsValid( SvxBoxInfoItemValidFlags::DISABLE ); + } + if(!mbUseMarginItem && eFUnit == FieldUnit::MM && MapUnit::MapTwip == rCoreAttrs.GetPool()->GetMetric( GetWhich( SID_ATTR_BORDER_INNER ) )) + { + //#i91548# changing the number of decimal digits changes the minimum values, too + lcl_SetDecimalDigitsTo1(*m_xLeftMF); + lcl_SetDecimalDigitsTo1(*m_xRightMF); + lcl_SetDecimalDigitsTo1(*m_xTopMF); + lcl_SetDecimalDigitsTo1(*m_xBottomMF); + lcl_SetDecimalDigitsTo1(*m_xEdShadowSize); + } + + FrameSelFlags nFlags = FrameSelFlags::Outer; + if( mbHorEnabled ) + nFlags |= FrameSelFlags::InnerHorizontal; + if( mbVerEnabled ) + nFlags |= FrameSelFlags::InnerVertical; + if( mbTLBREnabled ) + nFlags |= FrameSelFlags::DiagonalTLBR; + if( mbBLTREnabled ) + nFlags |= FrameSelFlags::DiagonalBLTR; + if( bIsDontCare ) + nFlags |= FrameSelFlags::DontCare; + m_aFrameSel.Initialize( nFlags ); + + m_aFrameSel.SetSelectHdl(LINK(this, SvxBorderTabPage, LinesChanged_Impl)); + m_xLbLineStyle->SetSelectHdl( LINK( this, SvxBorderTabPage, SelStyleHdl_Impl ) ); + m_xLbLineColor->SetSelectHdl( LINK( this, SvxBorderTabPage, SelColHdl_Impl ) ); + m_xLineWidthMF->connect_value_changed( LINK( this, SvxBorderTabPage, ModifyWidthHdl_Impl ) ); + m_xWndPresets->SetSelectHdl( LINK( this, SvxBorderTabPage, SelPreHdl_Impl ) ); + m_xWndShadows->SetSelectHdl( LINK( this, SvxBorderTabPage, SelSdwHdl_Impl ) ); + + FillValueSets(); + FillLineListBox_Impl(); + + // connections + if (rCoreAttrs.HasItem(GetWhich(SID_ATTR_PARA_GRABBAG), &pItem)) + { + const SfxGrabBagItem* pGrabBag = static_cast(pItem); + auto it = pGrabBag->GetGrabBag().find("DialogUseCharAttr"); + if (it != pGrabBag->GetGrabBag().end()) + { + bool bDialogUseCharAttr = false; + it->second >>= bDialogUseCharAttr; + if (bDialogUseCharAttr) + { + mnShadowSlot = SID_ATTR_CHAR_SHADOW; + mnBoxSlot = SID_ATTR_CHAR_BOX; + } + } + } + + bool bSupportsShadow = !SfxItemPool::IsSlot(GetWhich(mnShadowSlot)); + if( bSupportsShadow ) + m_xShadowControls.reset(new ShadowControlsWrapper(*m_xWndShadows, *m_xEdShadowSize, *m_xLbShadowColor)); + else + HideShadowControls(); + + if (mbUseMarginItem) + m_xMarginControls.reset(new MarginControlsWrapper(*m_xLeftMF, *m_xRightMF, *m_xTopMF, *m_xBottomMF)); + + // checkbox "Merge with next paragraph" only visible for Writer dialog format.paragraph + m_xMergeWithNextCB->hide(); + // checkbox "Merge adjacent line styles" only visible for Writer dialog format.table + m_xMergeAdjacentBordersCB->hide(); + + SfxObjectShell* pDocSh = SfxObjectShell::Current(); + if (pDocSh) + { + Reference< XServiceInfo > xSI( pDocSh->GetModel(), UNO_QUERY ); + if ( xSI.is() ) + bIsCalcDoc = xSI->supportsService("com.sun.star.sheet.SpreadsheetDocument"); + } + if( bIsCalcDoc ) + { + m_xRemoveAdjcentCellBordersCB->connect_toggled(LINK(this, SvxBorderTabPage, RemoveAdjacentCellBorderHdl_Impl)); + m_xRemoveAdjcentCellBordersCB->show(); + m_xRemoveAdjcentCellBordersCB->set_sensitive(false); + } + else + { + m_xRemoveAdjcentCellBordersCB->hide(); + m_xRemoveAdjcentCellBordersFT->hide(); + } +} + +SvxBorderTabPage::~SvxBorderTabPage() +{ + m_xLbShadowColor.reset(); + m_xWndShadowsWin.reset(); + m_xWndShadows.reset(); + m_xLbLineColor.reset(); + m_xLbLineStyle.reset(); + m_xFrameSelWin.reset(); + m_xWndPresetsWin.reset(); + m_xWndPresets.reset(); +} + +std::unique_ptr SvxBorderTabPage::Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet ) +{ + return std::make_unique(pPage, pController, *rAttrSet); +} + +void SvxBorderTabPage::ResetFrameLine_Impl( svx::FrameBorderType eBorder, const SvxBorderLine* pCoreLine, bool bValid ) +{ + if( m_aFrameSel.IsBorderEnabled( eBorder ) ) + { + if( bValid ) + m_aFrameSel.ShowBorder( eBorder, pCoreLine ); + else + m_aFrameSel.SetBorderDontCare( eBorder ); + } +} + +bool SvxBorderTabPage::IsBorderLineStyleAllowed( SvxBorderLineStyle nStyle ) const +{ + if (maUsedBorderStyles.empty()) + // All border styles are allowed. + return true; + + return maUsedBorderStyles.count(nStyle) > 0; +} + +void SvxBorderTabPage::Reset( const SfxItemSet* rSet ) +{ + SfxItemPool* pPool = rSet->GetPool(); + + if (m_aFrameSel.IsBorderEnabled(svx::FrameBorderType::TLBR)) + { + sal_uInt16 nBorderDiagId = pPool->GetWhich(SID_ATTR_BORDER_DIAG_TLBR); + if (const SvxLineItem* pLineItem = static_cast(rSet->GetItem(nBorderDiagId))) + m_aFrameSel.ShowBorder(svx::FrameBorderType::TLBR, pLineItem->GetLine()); + else + m_aFrameSel.SetBorderDontCare(svx::FrameBorderType::TLBR); + } + + if (m_aFrameSel.IsBorderEnabled(svx::FrameBorderType::BLTR)) + { + sal_uInt16 nBorderDiagId = pPool->GetWhich(SID_ATTR_BORDER_DIAG_BLTR); + if (const SvxLineItem* pLineItem = static_cast(rSet->GetItem(nBorderDiagId))) + m_aFrameSel.ShowBorder(svx::FrameBorderType::BLTR, pLineItem->GetLine()); + else + m_aFrameSel.SetBorderDontCare(svx::FrameBorderType::BLTR); + } + + if (m_xShadowControls) + { + sal_uInt16 nShadowId = pPool->GetWhich(mnShadowSlot); + const SfxPoolItem* pItem = rSet->GetItem(nShadowId); + if (pItem) + m_xShadowControls->SetControlValue(*static_cast(pItem)); + else + m_xShadowControls->SetControlDontKnow(); + } + + if (m_xMarginControls) + { + sal_uInt16 nAlignMarginId = pPool->GetWhich(SID_ATTR_ALIGN_MARGIN); + const SfxPoolItem* pItem = rSet->GetItem(nAlignMarginId); + if (pItem) + m_xMarginControls->SetControlValue(*static_cast(pItem)); + else + m_xMarginControls->SetControlDontKnow(); + } + + sal_uInt16 nMergeAdjacentBordersId = pPool->GetWhich(SID_SW_COLLAPSING_BORDERS); + const SfxBoolItem *pMergeAdjacentBorders = static_cast(rSet->GetItem(nMergeAdjacentBordersId)); + if (!pMergeAdjacentBorders) + m_xMergeAdjacentBordersCB->set_state(TRISTATE_INDET); + else + m_xMergeAdjacentBordersCB->set_active(pMergeAdjacentBorders->GetValue()); + m_xMergeAdjacentBordersCB->save_state(); + + sal_uInt16 nMergeWithNextId = pPool->GetWhich(SID_ATTR_BORDER_CONNECT); + const SfxBoolItem *pMergeWithNext = static_cast(rSet->GetItem(nMergeWithNextId)); + if (!pMergeWithNext) + m_xMergeWithNextCB->set_state(TRISTATE_INDET); + else + m_xMergeWithNextCB->set_active(pMergeWithNext->GetValue()); + m_xMergeWithNextCB->save_state(); + + const SvxBoxItem* pBoxItem; + const SvxBoxInfoItem* pBoxInfoItem; + sal_uInt16 nWhichBox = GetWhich(mnBoxSlot); + MapUnit eCoreUnit; + + pBoxItem = static_cast(GetItem( *rSet, mnBoxSlot )); + + pBoxInfoItem = GetItem( *rSet, SID_ATTR_BORDER_INNER, false ); + + eCoreUnit = pPool->GetMetric( nWhichBox ); + + if ( pBoxItem && pBoxInfoItem ) // -> Don't Care + { + ResetFrameLine_Impl( svx::FrameBorderType::Left, pBoxItem->GetLeft(), pBoxInfoItem->IsValid( SvxBoxInfoItemValidFlags::LEFT ) ); + ResetFrameLine_Impl( svx::FrameBorderType::Right, pBoxItem->GetRight(), pBoxInfoItem->IsValid( SvxBoxInfoItemValidFlags::RIGHT ) ); + ResetFrameLine_Impl( svx::FrameBorderType::Top, pBoxItem->GetTop(), pBoxInfoItem->IsValid( SvxBoxInfoItemValidFlags::TOP ) ); + ResetFrameLine_Impl( svx::FrameBorderType::Bottom, pBoxItem->GetBottom(), pBoxInfoItem->IsValid( SvxBoxInfoItemValidFlags::BOTTOM ) ); + ResetFrameLine_Impl( svx::FrameBorderType::Vertical, pBoxInfoItem->GetVert(), pBoxInfoItem->IsValid( SvxBoxInfoItemValidFlags::VERT ) ); + ResetFrameLine_Impl( svx::FrameBorderType::Horizontal, pBoxInfoItem->GetHori(), pBoxInfoItem->IsValid( SvxBoxInfoItemValidFlags::HORI ) ); + + + // distance inside + + if( !mbUseMarginItem ) + { + if (m_xLeftMF->get_visible()) + { + SetMetricValue(*m_xLeftMF, pBoxInfoItem->GetDefDist(), eCoreUnit); + SetMetricValue(*m_xRightMF, pBoxInfoItem->GetDefDist(), eCoreUnit); + SetMetricValue(*m_xTopMF, pBoxInfoItem->GetDefDist(), eCoreUnit); + SetMetricValue(*m_xBottomMF, pBoxInfoItem->GetDefDist(), eCoreUnit); + + nMinValue = m_xLeftMF->get_value(FieldUnit::NONE); + + if ( pBoxInfoItem->IsDist() ) + { + if( rSet->GetItemState( nWhichBox ) >= SfxItemState::DEFAULT ) + { + bool bIsAnyBorderVisible = m_aFrameSel.IsAnyBorderVisible(); + if( !bIsAnyBorderVisible || !pBoxInfoItem->IsMinDist() ) + { + m_xLeftMF->set_min(0, FieldUnit::NONE); + m_xRightMF->set_min(0, FieldUnit::NONE); + m_xTopMF->set_min(0, FieldUnit::NONE); + m_xBottomMF->set_min(0, FieldUnit::NONE); + } + long nLeftDist = pBoxItem->GetDistance( SvxBoxItemLine::LEFT); + SetMetricValue(*m_xLeftMF, nLeftDist, eCoreUnit); + long nRightDist = pBoxItem->GetDistance( SvxBoxItemLine::RIGHT); + SetMetricValue(*m_xRightMF, nRightDist, eCoreUnit); + long nTopDist = pBoxItem->GetDistance( SvxBoxItemLine::TOP); + SetMetricValue( *m_xTopMF, nTopDist, eCoreUnit ); + long nBottomDist = pBoxItem->GetDistance( SvxBoxItemLine::BOTTOM); + SetMetricValue( *m_xBottomMF, nBottomDist, eCoreUnit ); + + // if the distance is set with no active border line + // or it is null with an active border line + // no automatic changes should be made + const long nDefDist = bIsAnyBorderVisible ? pBoxInfoItem->GetDefDist() : 0; + bool bDiffDist = (nDefDist != nLeftDist || + nDefDist != nRightDist || + nDefDist != nTopDist || + nDefDist != nBottomDist); + if ((pBoxItem->GetSmallestDistance() || bIsAnyBorderVisible) && bDiffDist ) + { + mbLeftModified = true; + mbRightModified = true; + mbTopModified = true; + mbBottomModified = true; + } + } + else + { + // #106224# different margins -> do not fill the edits + m_xLeftMF->set_text( OUString() ); + m_xRightMF->set_text( OUString() ); + m_xTopMF->set_text( OUString() ); + m_xBottomMF->set_text( OUString() ); + } + } + m_xLeftMF->save_value(); + m_xRightMF->save_value(); + m_xTopMF->save_value(); + m_xBottomMF->save_value(); + } + } + } + else + { + // avoid ResetFrameLine-calls: + m_aFrameSel.HideAllBorders(); + } + + if( !m_aFrameSel.IsAnyBorderVisible() ) + m_aFrameSel.DeselectAllBorders(); + + // depict line (color) in controllers if unambiguous: + + { + // Do all visible lines show the same line widths? + long nWidth; + SvxBorderLineStyle nStyle; + bool bWidthEq = m_aFrameSel.GetVisibleWidth( nWidth, nStyle ); + if( bWidthEq ) + { + // Determine the width first as some styles can be missing depending on it + sal_Int64 nWidthPt = static_cast(vcl::ConvertDoubleValue( + sal_Int64( nWidth ), m_xLineWidthMF->get_digits(), + MapUnit::MapTwip, FieldUnit::POINT )); + m_xLineWidthMF->set_value(nWidthPt, FieldUnit::POINT); + m_xLbLineStyle->SetWidth(nWidth); + + // then set the style + m_xLbLineStyle->SelectEntry( nStyle ); + } + else + m_xLbLineStyle->SelectEntry(SvxBorderLineStyle::SOLID); + + // Do all visible lines show the same line color? + Color aColor; + bool bColorEq = m_aFrameSel.GetVisibleColor( aColor ); + if( !bColorEq ) + aColor = COL_BLACK; + + m_xLbLineColor->SelectEntry(aColor); + auto nTextColor = Application::GetSettings().GetStyleSettings().GetWindowTextColor(); + m_xLbLineStyle->SetColor(nTextColor); + + // Select all visible lines, if they are all equal. + if( bWidthEq && bColorEq ) + m_aFrameSel.SelectAllVisibleBorders(); + + // set the current style and color (caches style in control even if nothing is selected) + SelStyleHdl_Impl(*m_xLbLineStyle); + SelColHdl_Impl(*m_xLbLineColor); + } + + bool bEnable = m_xWndShadows->GetSelectedItemId() > 1 ; + m_xFtShadowSize->set_sensitive(bEnable); + m_xEdShadowSize->set_sensitive(bEnable); + m_xFtShadowColor->set_sensitive(bEnable); + m_xLbShadowColor->set_sensitive(bEnable); + + m_xWndPresets->SetNoSelection(); + + // - no line - should not be selected + + if (m_xLbLineStyle->GetSelectEntryStyle() == SvxBorderLineStyle::NONE) + { + m_xLbLineStyle->SelectEntry(SvxBorderLineStyle::SOLID); + SelStyleHdl_Impl(*m_xLbLineStyle); + } + + const SfxPoolItem* pItem; + SfxObjectShell* pShell; + if(SfxItemState::SET == rSet->GetItemState(SID_HTML_MODE, false, &pItem) || + ( nullptr != (pShell = SfxObjectShell::Current()) && + nullptr != (pItem = pShell->GetItem(SID_HTML_MODE)))) + { + sal_uInt16 nHtmlMode = static_cast(pItem)->GetValue(); + if(nHtmlMode & HTMLMODE_ON) + { + // there are no shadows in Html-mode and only complete borders + m_xShadowFrame->set_sensitive(false); + + if( !(nSWMode & SwBorderModes::TABLE) ) + { + m_xUserDefFT->set_sensitive(false); + m_xFrameSelWin->set_sensitive(false); + m_xWndPresets->RemoveItem(3); + m_xWndPresets->RemoveItem(4); + m_xWndPresets->RemoveItem(5); + } + } + } + + LinesChanged_Impl( nullptr ); + if (m_xLeftMF->get_value(FieldUnit::NONE) == m_xRightMF->get_value(FieldUnit::NONE) && + m_xTopMF->get_value(FieldUnit::NONE) == m_xBottomMF->get_value(FieldUnit::NONE) && + m_xTopMF->get_value(FieldUnit::NONE) == m_xLeftMF->get_value(FieldUnit::NONE)) + { + mbSync = true; + } + else + mbSync = false; + m_xSynchronizeCB->set_active(mbSync); + + mbRemoveAdjacentCellBorders = false; + m_xRemoveAdjcentCellBordersCB->set_active(false); + m_xRemoveAdjcentCellBordersCB->set_sensitive(false); +} + +void SvxBorderTabPage::ChangesApplied() +{ + m_xLeftMF->save_value(); + m_xRightMF->save_value(); + m_xTopMF->save_value(); + m_xBottomMF->save_value(); + m_xMergeWithNextCB->save_state(); + m_xMergeAdjacentBordersCB->save_state(); +} + +DeactivateRC SvxBorderTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if ( _pSet ) + FillItemSet( _pSet ); + + return DeactivateRC::LeavePage; +} + +bool SvxBorderTabPage::FillItemSet( SfxItemSet* rCoreAttrs ) +{ + bool bAttrsChanged = false; + + SfxItemPool* pPool = rCoreAttrs->GetPool(); + + if (m_aFrameSel.IsBorderEnabled(svx::FrameBorderType::TLBR) && + m_aFrameSel.GetFrameBorderState(svx::FrameBorderType::TLBR) != svx::FrameBorderState::DontCare) + { + SvxLineItem aLineItem(*static_cast(GetOldItem(*rCoreAttrs, SID_ATTR_BORDER_DIAG_TLBR))); + aLineItem.SetLine(m_aFrameSel.GetFrameBorderStyle(svx::FrameBorderType::TLBR)); + rCoreAttrs->Put(aLineItem); + bAttrsChanged = true; + } + + if (m_aFrameSel.IsBorderEnabled(svx::FrameBorderType::BLTR) && + m_aFrameSel.GetFrameBorderState(svx::FrameBorderType::BLTR) != svx::FrameBorderState::DontCare) + { + SvxLineItem aLineItem(*static_cast(GetOldItem(*rCoreAttrs, SID_ATTR_BORDER_DIAG_BLTR))); + aLineItem.SetLine(m_aFrameSel.GetFrameBorderStyle(svx::FrameBorderType::BLTR)); + rCoreAttrs->Put(aLineItem); + bAttrsChanged = true; + } + + if (m_xShadowControls && m_xShadowControls->get_value_changed_from_saved()) + { + const SvxShadowItem& rOldShadowItem = *static_cast(GetOldItem(*rCoreAttrs, mnShadowSlot)); + rCoreAttrs->Put(m_xShadowControls->GetControlValue(rOldShadowItem)); + bAttrsChanged = true; + } + + if (m_xMarginControls && m_xMarginControls->get_value_changed_from_saved()) + { + const SvxMarginItem& rOldMarginItem = *static_cast(GetOldItem(*rCoreAttrs, SID_ATTR_ALIGN_MARGIN)); + rCoreAttrs->Put(m_xMarginControls->GetControlValue(rOldMarginItem)); + bAttrsChanged = true; + } + + if (m_xMergeAdjacentBordersCB->get_state_changed_from_saved()) + { + auto nState = m_xMergeAdjacentBordersCB->get_state(); + if (nState == TRISTATE_INDET) + { + sal_uInt16 nMergeAdjacentBordersId = pPool->GetWhich(SID_SW_COLLAPSING_BORDERS); + rCoreAttrs->ClearItem(nMergeAdjacentBordersId); + } + else + { + std::unique_ptr xNewItem(static_cast(GetOldItem(*rCoreAttrs, SID_SW_COLLAPSING_BORDERS)->Clone())); + xNewItem->SetValue(static_cast(nState)); + rCoreAttrs->Put(std::move(xNewItem)); + } + bAttrsChanged = true; + } + + if (m_xMergeWithNextCB->get_state_changed_from_saved()) + { + auto nState = m_xMergeWithNextCB->get_state(); + if (nState == TRISTATE_INDET) + { + sal_uInt16 nMergeWithNextId = pPool->GetWhich(SID_ATTR_BORDER_CONNECT); + rCoreAttrs->ClearItem(nMergeWithNextId); + } + else + { + std::unique_ptr xNewItem(static_cast(GetOldItem(*rCoreAttrs, SID_ATTR_BORDER_CONNECT)->Clone())); + xNewItem->SetValue(static_cast(nState)); + rCoreAttrs->Put(std::move(xNewItem)); + } + bAttrsChanged = true; + } + + bool bPut = true; + sal_uInt16 nBoxWhich = GetWhich( mnBoxSlot ); + sal_uInt16 nBoxInfoWhich = pPool->GetWhich( SID_ATTR_BORDER_INNER, false ); + const SfxItemSet& rOldSet = GetItemSet(); + SvxBoxItem aBoxItem ( nBoxWhich ); + SvxBoxInfoItem aBoxInfoItem ( nBoxInfoWhich ); + const SvxBoxItem* pOldBoxItem = static_cast(GetOldItem( *rCoreAttrs, mnBoxSlot )); + + MapUnit eCoreUnit = rOldSet.GetPool()->GetMetric( nBoxWhich ); + + + // outer border: + + std::pair eTypes1[] = { + { svx::FrameBorderType::Top,SvxBoxItemLine::TOP }, + { svx::FrameBorderType::Bottom,SvxBoxItemLine::BOTTOM }, + { svx::FrameBorderType::Left,SvxBoxItemLine::LEFT }, + { svx::FrameBorderType::Right,SvxBoxItemLine::RIGHT }, + }; + + for (std::pair const & i : eTypes1) + aBoxItem.SetLine( m_aFrameSel.GetFrameBorderStyle( i.first ), i.second ); + + + aBoxItem.SetRemoveAdjacentCellBorder( mbRemoveAdjacentCellBorders ); + // border hor/ver and TableFlag + + std::pair eTypes2[] = { + { svx::FrameBorderType::Horizontal,SvxBoxInfoItemLine::HORI }, + { svx::FrameBorderType::Vertical,SvxBoxInfoItemLine::VERT } + }; + for (std::pair const & j : eTypes2) + aBoxInfoItem.SetLine( m_aFrameSel.GetFrameBorderStyle( j.first ), j.second ); + + aBoxInfoItem.EnableHor( mbHorEnabled ); + aBoxInfoItem.EnableVer( mbVerEnabled ); + + + // inner distance + + if (m_xLeftMF->get_visible()) + { + // #i40405# enable distance controls for next dialog call + aBoxInfoItem.SetDist( true ); + + if( !mbUseMarginItem ) + { + // #106224# all edits empty: do nothing + if( !m_xLeftMF->get_text().isEmpty() || !m_xRightMF->get_text().isEmpty() || + !m_xTopMF->get_text().isEmpty() || !m_xBottomMF->get_text().isEmpty() ) + { + const SvxBoxInfoItem* pOldBoxInfoItem = GetOldItem( *rCoreAttrs, SID_ATTR_BORDER_INNER ); + if ( + !pOldBoxItem || + m_xLeftMF->get_value_changed_from_saved() || + m_xRightMF->get_value_changed_from_saved() || + m_xTopMF->get_value_changed_from_saved() || + m_xBottomMF->get_value_changed_from_saved() || + nMinValue == m_xLeftMF->get_value(FieldUnit::NONE) || + nMinValue == m_xRightMF->get_value(FieldUnit::NONE) || + nMinValue == m_xTopMF->get_value(FieldUnit::NONE) || + nMinValue == m_xBottomMF->get_value(FieldUnit::NONE) || + (pOldBoxInfoItem && !pOldBoxInfoItem->IsValid(SvxBoxInfoItemValidFlags::DISTANCE)) + ) + { + aBoxItem.SetDistance( static_cast(GetCoreValue(*m_xLeftMF, eCoreUnit )), SvxBoxItemLine::LEFT ); + aBoxItem.SetDistance( static_cast(GetCoreValue(*m_xRightMF, eCoreUnit )), SvxBoxItemLine::RIGHT ); + aBoxItem.SetDistance( static_cast(GetCoreValue(*m_xTopMF, eCoreUnit )), SvxBoxItemLine::TOP ); + aBoxItem.SetDistance( static_cast(GetCoreValue(*m_xBottomMF, eCoreUnit )), SvxBoxItemLine::BOTTOM); + } + else + { + aBoxItem.SetDistance(pOldBoxItem->GetDistance(SvxBoxItemLine::LEFT ), SvxBoxItemLine::LEFT); + aBoxItem.SetDistance(pOldBoxItem->GetDistance(SvxBoxItemLine::RIGHT), SvxBoxItemLine::RIGHT); + aBoxItem.SetDistance(pOldBoxItem->GetDistance(SvxBoxItemLine::TOP ), SvxBoxItemLine::TOP); + aBoxItem.SetDistance(pOldBoxItem->GetDistance(SvxBoxItemLine::BOTTOM), SvxBoxItemLine::BOTTOM); + } + aBoxInfoItem.SetValid( SvxBoxInfoItemValidFlags::DISTANCE ); + } + } + } + + + // note Don't Care Status in the Info-Item: + + aBoxInfoItem.SetValid( SvxBoxInfoItemValidFlags::TOP, m_aFrameSel.GetFrameBorderState( svx::FrameBorderType::Top ) != svx::FrameBorderState::DontCare ); + aBoxInfoItem.SetValid( SvxBoxInfoItemValidFlags::BOTTOM, m_aFrameSel.GetFrameBorderState( svx::FrameBorderType::Bottom ) != svx::FrameBorderState::DontCare ); + aBoxInfoItem.SetValid( SvxBoxInfoItemValidFlags::LEFT, m_aFrameSel.GetFrameBorderState( svx::FrameBorderType::Left ) != svx::FrameBorderState::DontCare ); + aBoxInfoItem.SetValid( SvxBoxInfoItemValidFlags::RIGHT, m_aFrameSel.GetFrameBorderState( svx::FrameBorderType::Right ) != svx::FrameBorderState::DontCare ); + aBoxInfoItem.SetValid( SvxBoxInfoItemValidFlags::HORI, m_aFrameSel.GetFrameBorderState( svx::FrameBorderType::Horizontal ) != svx::FrameBorderState::DontCare ); + aBoxInfoItem.SetValid( SvxBoxInfoItemValidFlags::VERT, m_aFrameSel.GetFrameBorderState( svx::FrameBorderType::Vertical ) != svx::FrameBorderState::DontCare ); + + + // Put or Clear of the border? + + bPut = true; + + if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nBoxWhich, false )) + { + bPut = aBoxItem != static_cast(rOldSet.Get(nBoxWhich)); + } + if( SfxItemState::DEFAULT == rOldSet.GetItemState( nBoxInfoWhich, false ) ) + { + const SvxBoxInfoItem& rOldBoxInfo = static_cast( + rOldSet.Get(nBoxInfoWhich)); + + aBoxInfoItem.SetMinDist( rOldBoxInfo.IsMinDist() ); + aBoxInfoItem.SetDefDist( rOldBoxInfo.GetDefDist() ); + bPut |= (aBoxInfoItem != rOldBoxInfo ); + } + + if ( bPut ) + { + if ( !pOldBoxItem || *pOldBoxItem != aBoxItem ) + { + rCoreAttrs->Put( aBoxItem ); + bAttrsChanged = true; + } + const SfxPoolItem* pOld = GetOldItem( *rCoreAttrs, SID_ATTR_BORDER_INNER, false ); + + if ( !pOld || *static_cast(pOld) != aBoxInfoItem ) + { + rCoreAttrs->Put( aBoxInfoItem ); + bAttrsChanged = true; + } + } + else + { + rCoreAttrs->ClearItem( nBoxWhich ); + rCoreAttrs->ClearItem( nBoxInfoWhich ); + } + + return bAttrsChanged; +} + +void SvxBorderTabPage::HideShadowControls() +{ + m_xShadowFrame->hide(); +} + +#define IID_PRE_CELL_NONE 1 +#define IID_PRE_CELL_ALL 2 +#define IID_PRE_CELL_LR 3 +#define IID_PRE_CELL_TB 4 +#define IID_PRE_CELL_L 5 +#define IID_PRE_CELL_DIAG 6 +#define IID_PRE_HOR_NONE 7 +#define IID_PRE_HOR_OUTER 8 +#define IID_PRE_HOR_HOR 9 +#define IID_PRE_HOR_ALL 10 +#define IID_PRE_HOR_OUTER2 11 +#define IID_PRE_VER_NONE 12 +#define IID_PRE_VER_OUTER 13 +#define IID_PRE_VER_VER 14 +#define IID_PRE_VER_ALL 15 +#define IID_PRE_VER_OUTER2 16 +#define IID_PRE_TABLE_NONE 17 +#define IID_PRE_TABLE_OUTER 18 +#define IID_PRE_TABLE_OUTERH 19 +#define IID_PRE_TABLE_ALL 20 +#define IID_PRE_TABLE_OUTER2 21 + +IMPL_LINK_NOARG(SvxBorderTabPage, SelPreHdl_Impl, ValueSet*, void) +{ + const svx::FrameBorderState SHOW = svx::FrameBorderState::Show; + const svx::FrameBorderState HIDE = svx::FrameBorderState::Hide; + const svx::FrameBorderState DONT = svx::FrameBorderState::DontCare; + + static const svx::FrameBorderState ppeStates[][ svx::FRAMEBORDERTYPE_COUNT ] = + { /* Left Right Top Bot Hor Ver TLBR BLTR */ +/* ---------------------+--------------------------------------------------- */ +/* IID_PRE_CELL_NONE */ { HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE }, +/* IID_PRE_CELL_ALL */ { SHOW, SHOW, SHOW, SHOW, HIDE, HIDE, HIDE, HIDE }, +/* IID_PRE_CELL_LR */ { SHOW, SHOW, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE }, +/* IID_PRE_CELL_TB */ { HIDE, HIDE, SHOW, SHOW, HIDE, HIDE, HIDE, HIDE }, +/* IID_PRE_CELL_L */ { SHOW, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE }, +/* IID_PRE_CELL_DIAG */ { HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, SHOW, SHOW }, +/* IID_PRE_HOR_NONE */ { HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE }, +/* IID_PRE_HOR_OUTER */ { SHOW, SHOW, SHOW, SHOW, HIDE, HIDE, HIDE, HIDE }, +/* IID_PRE_HOR_HOR */ { HIDE, HIDE, SHOW, SHOW, SHOW, HIDE, HIDE, HIDE }, +/* IID_PRE_HOR_ALL */ { SHOW, SHOW, SHOW, SHOW, SHOW, HIDE, HIDE, HIDE }, +/* IID_PRE_HOR_OUTER2 */ { SHOW, SHOW, SHOW, SHOW, DONT, HIDE, HIDE, HIDE }, +/* IID_PRE_VER_NONE */ { HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE }, +/* IID_PRE_VER_OUTER */ { SHOW, SHOW, SHOW, SHOW, HIDE, HIDE, HIDE, HIDE }, +/* IID_PRE_VER_VER */ { SHOW, SHOW, HIDE, HIDE, HIDE, SHOW, HIDE, HIDE }, +/* IID_PRE_VER_ALL */ { SHOW, SHOW, SHOW, SHOW, HIDE, SHOW, HIDE, HIDE }, +/* IID_PRE_VER_OUTER2 */ { SHOW, SHOW, SHOW, SHOW, HIDE, DONT, HIDE, HIDE }, +/* IID_PRE_TABLE_NONE */ { HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE }, +/* IID_PRE_TABLE_OUTER */ { SHOW, SHOW, SHOW, SHOW, HIDE, HIDE, HIDE, HIDE }, +/* IID_PRE_TABLE_OUTERH */ { SHOW, SHOW, SHOW, SHOW, SHOW, HIDE, HIDE, HIDE }, +/* IID_PRE_TABLE_ALL */ { SHOW, SHOW, SHOW, SHOW, SHOW, SHOW, HIDE, HIDE }, +/* IID_PRE_TABLE_OUTER2 */ { SHOW, SHOW, SHOW, SHOW, DONT, DONT, HIDE, HIDE } + }; + + // first hide and deselect all frame borders + m_aFrameSel.HideAllBorders(); + m_aFrameSel.DeselectAllBorders(); + + // Using image ID to find correct line in table above. + sal_uInt16 nLine = GetPresetImageId( m_xWndPresets->GetSelectedItemId() ) - 1; + + // Apply all styles from the table + for( int nBorder = 0; nBorder < svx::FRAMEBORDERTYPE_COUNT; ++nBorder ) + { + svx::FrameBorderType eBorder = svx::GetFrameBorderTypeFromIndex( nBorder ); + switch( ppeStates[ nLine ][ nBorder ] ) + { + case SHOW: m_aFrameSel.SelectBorder( eBorder ); break; + case HIDE: /* nothing to do */ break; + case DONT: m_aFrameSel.SetBorderDontCare( eBorder ); break; + } + } + + // Show all lines that have been selected above + if( m_aFrameSel.IsAnyBorderSelected() ) + { + // any visible style, but "no-line" in line list box? -> use hair-line + if (m_xLbLineStyle->GetSelectEntryStyle() == SvxBorderLineStyle::NONE) + m_xLbLineStyle->SelectEntry(SvxBorderLineStyle::SOLID); + + // set current style to all previously selected lines + SelStyleHdl_Impl(*m_xLbLineStyle); + SelColHdl_Impl(*m_xLbLineColor); + } + + // Presets ValueSet does not show a selection (used as push buttons). + m_xWndPresets->SetNoSelection(); + + LinesChanged_Impl( nullptr ); + UpdateRemoveAdjCellBorderCB( nLine + 1 ); +} + +IMPL_LINK_NOARG(SvxBorderTabPage, SelSdwHdl_Impl, ValueSet*, void) +{ + bool bEnable = m_xWndShadows->GetSelectedItemId() > 1; + m_xFtShadowSize->set_sensitive(bEnable); + m_xEdShadowSize->set_sensitive(bEnable); + m_xFtShadowColor->set_sensitive(bEnable); + m_xLbShadowColor->set_sensitive(bEnable); +} + +IMPL_LINK(SvxBorderTabPage, SelColHdl_Impl, ColorListBox&, rColorBox, void) +{ + Color aColor = rColorBox.GetSelectEntryColor(); + m_aFrameSel.SetColorToSelection(aColor); +} + +IMPL_LINK_NOARG(SvxBorderTabPage, ModifyWidthHdl_Impl, weld::MetricSpinButton&, void) +{ + sal_Int64 nVal = m_xLineWidthMF->get_value(FieldUnit::NONE); + nVal = static_cast(vcl::ConvertDoubleValue( + nVal, + m_xLineWidthMF->get_digits(), + FieldUnit::POINT, MapUnit::MapTwip )); + m_xLbLineStyle->SetWidth( nVal ); + + m_aFrameSel.SetStyleToSelection( nVal, + m_xLbLineStyle->GetSelectEntryStyle() ); +} + +IMPL_LINK_NOARG(SvxBorderTabPage, SelStyleHdl_Impl, SvtLineListBox&, void) +{ + sal_Int64 nVal = m_xLineWidthMF->get_value(FieldUnit::NONE); + nVal = static_cast(vcl::ConvertDoubleValue( + nVal, + m_xLineWidthMF->get_digits(), + FieldUnit::POINT, MapUnit::MapTwip )); + m_aFrameSel.SetStyleToSelection ( nVal, + m_xLbLineStyle->GetSelectEntryStyle() ); +} + +// ValueSet handling +sal_uInt16 SvxBorderTabPage::GetPresetImageId( sal_uInt16 nValueSetIdx ) const +{ + // table with all sets of predefined border styles + static const sal_uInt16 ppnImgIds[][ SVX_BORDER_PRESET_COUNT ] = + { + // simple cell without diagonal frame borders + { IID_PRE_CELL_NONE, IID_PRE_CELL_ALL, IID_PRE_CELL_LR, IID_PRE_CELL_TB, IID_PRE_CELL_L }, + // simple cell with diagonal frame borders + { IID_PRE_CELL_NONE, IID_PRE_CELL_ALL, IID_PRE_CELL_LR, IID_PRE_CELL_TB, IID_PRE_CELL_DIAG }, + // with horizontal inner frame border + { IID_PRE_HOR_NONE, IID_PRE_HOR_OUTER, IID_PRE_HOR_HOR, IID_PRE_HOR_ALL, IID_PRE_HOR_OUTER2 }, + // with vertical inner frame border + { IID_PRE_VER_NONE, IID_PRE_VER_OUTER, IID_PRE_VER_VER, IID_PRE_VER_ALL, IID_PRE_VER_OUTER2 }, + // with horizontal and vertical inner frame borders + { IID_PRE_TABLE_NONE, IID_PRE_TABLE_OUTER, IID_PRE_TABLE_OUTERH, IID_PRE_TABLE_ALL, IID_PRE_TABLE_OUTER2 } + }; + + // find correct set of presets + int nLine = 0; + if( !mbHorEnabled && !mbVerEnabled ) + nLine = (mbTLBREnabled || mbBLTREnabled) ? 1 : 0; + else if( mbHorEnabled && !mbVerEnabled ) + nLine = 2; + else if( !mbHorEnabled && mbVerEnabled ) + nLine = 3; + else + nLine = 4; + + DBG_ASSERT( (1 <= nValueSetIdx) && (nValueSetIdx <= SVX_BORDER_PRESET_COUNT), + "SvxBorderTabPage::GetPresetImageId - wrong index" ); + return ppnImgIds[ nLine ][ nValueSetIdx - 1 ]; +} + +const char* SvxBorderTabPage::GetPresetStringId( sal_uInt16 nValueSetIdx ) const +{ + // string resource IDs for each image (in order of the IID_PRE_* image IDs) + static const char* pnStrIds[] = + { + RID_SVXSTR_TABLE_PRESET_NONE, + RID_SVXSTR_PARA_PRESET_ALL, + RID_SVXSTR_PARA_PRESET_LEFTRIGHT, + RID_SVXSTR_PARA_PRESET_TOPBOTTOM, + RID_SVXSTR_PARA_PRESET_ONLYLEFT, + RID_SVXSTR_PARA_PRESET_DIAGONAL, + + RID_SVXSTR_TABLE_PRESET_NONE, + RID_SVXSTR_TABLE_PRESET_ONLYOUTER, + RID_SVXSTR_HOR_PRESET_ONLYHOR, + RID_SVXSTR_TABLE_PRESET_OUTERALL, + RID_SVXSTR_TABLE_PRESET_OUTERINNER, + + RID_SVXSTR_TABLE_PRESET_NONE, + RID_SVXSTR_TABLE_PRESET_ONLYOUTER, + RID_SVXSTR_VER_PRESET_ONLYVER, + RID_SVXSTR_TABLE_PRESET_OUTERALL, + RID_SVXSTR_TABLE_PRESET_OUTERINNER, + + RID_SVXSTR_TABLE_PRESET_NONE, + RID_SVXSTR_TABLE_PRESET_ONLYOUTER, + RID_SVXSTR_TABLE_PRESET_OUTERHORI, + RID_SVXSTR_TABLE_PRESET_OUTERALL, + RID_SVXSTR_TABLE_PRESET_OUTERINNER + }; + return pnStrIds[ GetPresetImageId( nValueSetIdx ) - 1 ]; +} + +void SvxBorderTabPage::FillPresetVS() +{ + // basic initialization of the ValueSet + m_xWndPresets->SetStyle( m_xWndPresets->GetStyle() | WB_ITEMBORDER | WB_DOUBLEBORDER ); + m_xWndPresets->SetColCount( SVX_BORDER_PRESET_COUNT ); + + // insert images and help texts + for( sal_uInt16 nVSIdx = 1; nVSIdx <= SVX_BORDER_PRESET_COUNT; ++nVSIdx ) + { + m_xWndPresets->InsertItem( nVSIdx ); + m_xWndPresets->SetItemImage(nVSIdx, m_aBorderImgVec[GetPresetImageId(nVSIdx) - 1]); + m_xWndPresets->SetItemText( nVSIdx, CuiResId( GetPresetStringId( nVSIdx ) ) ); + } + + // show the control + m_xWndPresets->SetNoSelection(); + m_xWndPresets->SetOptimalSize(); + m_xWndPresets->Show(); +} + +void SvxBorderTabPage::FillShadowVS() +{ + // basic initialization of the ValueSet + m_xWndShadows->SetStyle( m_xWndShadows->GetStyle() | WB_ITEMBORDER | WB_DOUBLEBORDER ); + m_xWndShadows->SetColCount( SVX_BORDER_SHADOW_COUNT ); + + // string resource IDs for each image + static const char* pnStrIds[ SVX_BORDER_SHADOW_COUNT ] = + { RID_SVXSTR_SHADOW_STYLE_NONE, RID_SVXSTR_SHADOW_STYLE_BOTTOMRIGHT, RID_SVXSTR_SHADOW_STYLE_TOPRIGHT, RID_SVXSTR_SHADOW_STYLE_BOTTOMLEFT, RID_SVXSTR_SHADOW_STYLE_TOPLEFT }; + + // insert images and help texts + for( sal_uInt16 nVSIdx = 1; nVSIdx <= SVX_BORDER_SHADOW_COUNT; ++nVSIdx ) + { + m_xWndShadows->InsertItem( nVSIdx ); + m_xWndShadows->SetItemImage(nVSIdx, m_aShadowImgVec[nVSIdx-1]); + m_xWndShadows->SetItemText( nVSIdx, CuiResId( pnStrIds[ nVSIdx - 1 ] ) ); + } + + // show the control + m_xWndShadows->SelectItem( 1 ); + m_xWndShadows->SetOptimalSize(); + m_xWndShadows->Show(); +} + + +void SvxBorderTabPage::FillValueSets() +{ + FillPresetVS(); + FillShadowVS(); +} + + +static Color lcl_mediumColor( Color aMain, Color /*aDefault*/ ) +{ + return SvxBorderLine::threeDMediumColor( aMain ); +} + +void SvxBorderTabPage::FillLineListBox_Impl() +{ + using namespace ::com::sun::star::table::BorderLineStyle; + + static struct { + SvxBorderLineStyle mnStyle; + long mnMinWidth; + SvtLineListBox::ColorFunc mpColor1Fn; + SvtLineListBox::ColorFunc mpColor2Fn; + SvtLineListBox::ColorDistFunc mpColorDistFn; + } const aLines[] = { + // Simple lines + { SvxBorderLineStyle::SOLID, 0, &sameColor, &sameColor, &sameDistColor }, + { SvxBorderLineStyle::DOTTED, 0, &sameColor, &sameColor, &sameDistColor }, + { SvxBorderLineStyle::DASHED, 0, &sameColor, &sameColor, &sameDistColor }, + { SvxBorderLineStyle::FINE_DASHED, 0, &sameColor, &sameColor, &sameDistColor }, + { SvxBorderLineStyle::DASH_DOT, 0, &sameColor, &sameColor, &sameDistColor }, + { SvxBorderLineStyle::DASH_DOT_DOT, 0, &sameColor, &sameColor, &sameDistColor }, + + // Double lines + { SvxBorderLineStyle::DOUBLE, 10, &sameColor, &sameColor, &sameDistColor }, + { SvxBorderLineStyle::DOUBLE_THIN, 10, &sameColor, &sameColor, &sameDistColor }, + { SvxBorderLineStyle::THINTHICK_SMALLGAP, 20, &sameColor, &sameColor, &sameDistColor }, + { SvxBorderLineStyle::THINTHICK_MEDIUMGAP, 0, &sameColor, &sameColor, &sameDistColor }, + { SvxBorderLineStyle::THINTHICK_LARGEGAP, 0, &sameColor, &sameColor, &sameDistColor }, + { SvxBorderLineStyle::THICKTHIN_SMALLGAP, 20, &sameColor, &sameColor, &sameDistColor }, + { SvxBorderLineStyle::THICKTHIN_MEDIUMGAP, 0, &sameColor, &sameColor, &sameDistColor }, + { SvxBorderLineStyle::THICKTHIN_LARGEGAP, 0, &sameColor, &sameColor, &sameDistColor }, + + { SvxBorderLineStyle::EMBOSSED, 15, &SvxBorderLine::threeDLightColor, &SvxBorderLine::threeDDarkColor, &lcl_mediumColor }, + { SvxBorderLineStyle::ENGRAVED, 15, &SvxBorderLine::threeDDarkColor, &SvxBorderLine::threeDLightColor, &lcl_mediumColor }, + + { SvxBorderLineStyle::OUTSET, 10, &SvxBorderLine::lightColor, &SvxBorderLine::darkColor, &sameDistColor }, + { SvxBorderLineStyle::INSET, 10, &SvxBorderLine::darkColor, &SvxBorderLine::lightColor, &sameDistColor } + }; + + m_xLbLineStyle->SetSourceUnit( FieldUnit::TWIP ); + + for (size_t i = 0; i < SAL_N_ELEMENTS(aLines); ++i) + { + if (!IsBorderLineStyleAllowed(aLines[i].mnStyle)) + continue; + + m_xLbLineStyle->InsertEntry( + SvxBorderLine::getWidthImpl(aLines[i].mnStyle), aLines[i].mnStyle, + aLines[i].mnMinWidth, aLines[i].mpColor1Fn, aLines[i].mpColor2Fn, aLines[i].mpColorDistFn); + } + + sal_Int64 nVal = m_xLineWidthMF->get_value(FieldUnit::NONE); + nVal = static_cast(vcl::ConvertDoubleValue(nVal, m_xLineWidthMF->get_digits(), + m_xLineWidthMF->get_unit(), MapUnit::MapTwip)); + m_xLbLineStyle->SetWidth( nVal ); +} + + +IMPL_LINK_NOARG(SvxBorderTabPage, LinesChanged_Impl, LinkParamNone*, void) +{ + if (!mbUseMarginItem && m_xLeftMF->get_visible()) + { + bool bLineSet = m_aFrameSel.IsAnyBorderVisible(); + bool bSpaceModified = mbLeftModified || + mbRightModified || + mbTopModified || + mbBottomModified; + + if(bLineSet) + { + if(!bSpaceModified) + { + m_xLeftMF->set_value(nMinValue, FieldUnit::NONE); + m_xRightMF->set_value(nMinValue, FieldUnit::NONE); + m_xTopMF->set_value(nMinValue, FieldUnit::NONE); + m_xBottomMF->set_value(nMinValue, FieldUnit::NONE); + } + } + else + { + m_xLeftMF->set_min(0, FieldUnit::NONE); + m_xRightMF->set_min(0, FieldUnit::NONE); + m_xTopMF->set_min(0, FieldUnit::NONE); + m_xBottomMF->set_min(0, FieldUnit::NONE); + } + // for tables everything is allowed + SvxBoxInfoItemValidFlags nValid = SvxBoxInfoItemValidFlags::TOP|SvxBoxInfoItemValidFlags::BOTTOM|SvxBoxInfoItemValidFlags::LEFT|SvxBoxInfoItemValidFlags::RIGHT; + + m_xLeftFT->set_sensitive( bool(nValid & SvxBoxInfoItemValidFlags::LEFT) ); + m_xRightFT->set_sensitive( bool(nValid & SvxBoxInfoItemValidFlags::RIGHT) ); + m_xTopFT->set_sensitive( bool(nValid & SvxBoxInfoItemValidFlags::TOP) ); + m_xBottomFT->set_sensitive( bool(nValid & SvxBoxInfoItemValidFlags::BOTTOM) ); + m_xLeftMF->set_sensitive( bool(nValid & SvxBoxInfoItemValidFlags::LEFT) ); + m_xRightMF->set_sensitive( bool(nValid & SvxBoxInfoItemValidFlags::RIGHT) ); + m_xTopMF->set_sensitive( bool(nValid & SvxBoxInfoItemValidFlags::TOP) ); + m_xBottomMF->set_sensitive( bool(nValid & SvxBoxInfoItemValidFlags::BOTTOM) ); + m_xSynchronizeCB->set_sensitive(m_xRightMF->get_sensitive() || m_xTopMF->get_sensitive() || + m_xBottomMF->get_sensitive() || m_xLeftMF->get_sensitive()); + } + UpdateRemoveAdjCellBorderCB( SAL_MAX_UINT16 ); +} + + +IMPL_LINK( SvxBorderTabPage, ModifyDistanceHdl_Impl, weld::MetricSpinButton&, rField, void) +{ + if (&rField == m_xLeftMF.get()) + mbLeftModified = true; + else if (&rField == m_xRightMF.get()) + mbRightModified = true; + else if (&rField == m_xTopMF.get()) + mbTopModified = true; + else if (&rField == m_xBottomMF.get()) + mbBottomModified = true; + + if (mbSync) + { + const auto nVal = rField.get_value(FieldUnit::NONE); + if (&rField != m_xLeftMF.get()) + m_xLeftMF->set_value(nVal, FieldUnit::NONE); + if (&rField != m_xRightMF.get()) + m_xRightMF->set_value(nVal, FieldUnit::NONE); + if (&rField != m_xTopMF.get()) + m_xTopMF->set_value(nVal, FieldUnit::NONE); + if (&rField != m_xBottomMF.get()) + m_xBottomMF->set_value(nVal, FieldUnit::NONE); + } +} + +IMPL_LINK( SvxBorderTabPage, SyncHdl_Impl, weld::ToggleButton&, rBox, void) +{ + mbSync = rBox.get_active(); +} + +IMPL_LINK( SvxBorderTabPage, RemoveAdjacentCellBorderHdl_Impl, weld::ToggleButton&, rBox, void) +{ + mbRemoveAdjacentCellBorders = rBox.get_active(); +} + +void SvxBorderTabPage::UpdateRemoveAdjCellBorderCB( sal_uInt16 nPreset ) +{ + if( !bIsCalcDoc ) + return; + const SfxItemSet& rOldSet = GetItemSet(); + const SvxBoxInfoItem* pOldBoxInfoItem = GetOldItem( rOldSet, SID_ATTR_BORDER_INNER ); + const SvxBoxItem* pOldBoxItem = static_cast(GetOldItem( rOldSet, mnBoxSlot )); + if( !pOldBoxInfoItem || !pOldBoxItem ) + return; + std::pair eTypes1[] = { + { svx::FrameBorderType::Top,SvxBoxInfoItemValidFlags::TOP }, + { svx::FrameBorderType::Bottom,SvxBoxInfoItemValidFlags::BOTTOM }, + { svx::FrameBorderType::Left,SvxBoxInfoItemValidFlags::LEFT }, + { svx::FrameBorderType::Right,SvxBoxInfoItemValidFlags::RIGHT }, + }; + SvxBoxItemLine const eTypes2[] = { + SvxBoxItemLine::TOP, + SvxBoxItemLine::BOTTOM, + SvxBoxItemLine::LEFT, + SvxBoxItemLine::RIGHT, + }; + + // Check if current selection involves deletion of at least one border + bool bBorderDeletionReq = false; + for ( size_t i=0; i < SAL_N_ELEMENTS( eTypes1 ); ++i ) + { + if( pOldBoxItem->GetLine( eTypes2[i] ) || !( pOldBoxInfoItem->IsValid( eTypes1[i].second ) ) ) + { + if( m_aFrameSel.GetFrameBorderState( eTypes1[i].first ) == svx::FrameBorderState::Hide ) + { + bBorderDeletionReq = true; + break; + } + } + } + + if( !bBorderDeletionReq && ( nPreset == IID_PRE_CELL_NONE || nPreset == IID_PRE_TABLE_NONE ) ) + bBorderDeletionReq = true; + + m_xRemoveAdjcentCellBordersCB->set_sensitive(bBorderDeletionReq); + + if( !bBorderDeletionReq ) + { + mbRemoveAdjacentCellBorders = false; + m_xRemoveAdjcentCellBordersCB->set_active(false); + } +} + +void SvxBorderTabPage::PageCreated(const SfxAllItemSet& aSet) +{ + const SfxUInt16Item* pSWModeItem = aSet.GetItem(SID_SWMODE_TYPE, false); + const SfxUInt32Item* pFlagItem = aSet.GetItem(SID_FLAG_TYPE, false); + if (pSWModeItem) + { + nSWMode = static_cast(pSWModeItem->GetValue()); + // #i43593# + // show checkbox for format.paragraph + if ( nSWMode == SwBorderModes::PARA ) + { + m_xMergeWithNextCB->show(); + m_xPropertiesFrame->show(); + } + // show checkbox for format.paragraph + else if ( nSWMode == SwBorderModes::TABLE ) + { + m_xMergeAdjacentBordersCB->show(); + m_xPropertiesFrame->show(); + } + } + if (pFlagItem) + if ( ( pFlagItem->GetValue() & SVX_HIDESHADOWCTL ) == SVX_HIDESHADOWCTL ) + HideShadowControls(); +} + +void SvxBorderTabPage::SetTableMode() +{ + nSWMode = SwBorderModes::TABLE; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/chardlg.cxx b/cui/source/tabpages/chardlg.cxx new file mode 100644 index 000000000..077a62aec --- /dev/null +++ b/cui/source/tabpages/chardlg.cxx @@ -0,0 +1,3261 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "chardlg.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; + +// static ---------------------------------------------------------------- + +const sal_uInt16 SvxCharNamePage::pNameRanges[] = +{ + SID_ATTR_CHAR_FONT, + SID_ATTR_CHAR_WEIGHT, + SID_ATTR_CHAR_FONTHEIGHT, + SID_ATTR_CHAR_FONTHEIGHT, + SID_ATTR_CHAR_COLOR, + SID_ATTR_CHAR_COLOR, + SID_ATTR_CHAR_LANGUAGE, + SID_ATTR_CHAR_LANGUAGE, + SID_ATTR_CHAR_CJK_FONT, + SID_ATTR_CHAR_CJK_WEIGHT, + SID_ATTR_CHAR_CTL_FONT, + SID_ATTR_CHAR_CTL_WEIGHT, + 0 +}; + +const sal_uInt16 SvxCharEffectsPage::pEffectsRanges[] = +{ + SID_ATTR_CHAR_SHADOWED, + SID_ATTR_CHAR_UNDERLINE, + SID_ATTR_CHAR_COLOR, + SID_ATTR_CHAR_COLOR, + SID_ATTR_CHAR_CASEMAP, + SID_ATTR_CHAR_CASEMAP, + SID_ATTR_FLASH, + SID_ATTR_FLASH, + SID_ATTR_CHAR_EMPHASISMARK, + SID_ATTR_CHAR_EMPHASISMARK, + SID_ATTR_CHAR_RELIEF, + SID_ATTR_CHAR_RELIEF, + SID_ATTR_CHAR_HIDDEN, + SID_ATTR_CHAR_HIDDEN, + SID_ATTR_CHAR_OVERLINE, + SID_ATTR_CHAR_OVERLINE, + 0 +}; + +const sal_uInt16 SvxCharPositionPage::pPositionRanges[] = +{ + SID_ATTR_CHAR_KERNING, + SID_ATTR_CHAR_KERNING, + SID_ATTR_CHAR_ESCAPEMENT, + SID_ATTR_CHAR_ESCAPEMENT, + SID_ATTR_CHAR_AUTOKERN, + SID_ATTR_CHAR_AUTOKERN, + SID_ATTR_CHAR_ROTATED, + SID_ATTR_CHAR_SCALEWIDTH, + SID_ATTR_CHAR_WIDTH_FIT_TO_LINE, + SID_ATTR_CHAR_WIDTH_FIT_TO_LINE, + 0 +}; + +const sal_uInt16 SvxCharTwoLinesPage::pTwoLinesRanges[] = +{ + SID_ATTR_CHAR_TWO_LINES, + SID_ATTR_CHAR_TWO_LINES, + 0 +}; + +// C-Function ------------------------------------------------------------ + +static bool StateToAttr( TriState aState ) +{ + return ( TRISTATE_TRUE == aState ); +} + +namespace +{ + void setPrevFontEscapement(SvxFont& _rFont,sal_uInt8 nProp, sal_uInt8 nEscProp, short nEsc ) + { + _rFont.SetPropr( nProp ); + _rFont.SetProprRel( nEscProp ); + _rFont.SetEscapement( nEsc ); + } +} + +inline SvxFont& SvxCharBasePage::GetPreviewFont() +{ + return m_aPreviewWin.GetFont(); +} + +inline SvxFont& SvxCharBasePage::GetPreviewCJKFont() +{ + return m_aPreviewWin.GetCJKFont(); +} + +inline SvxFont& SvxCharBasePage::GetPreviewCTLFont() +{ + return m_aPreviewWin.GetCTLFont(); +} + +SvxCharBasePage::SvxCharBasePage(weld::Container* pPage, weld::DialogController* pController, const OUString& rUIXMLDescription, const OString& rID, const SfxItemSet& rItemset) + : SfxTabPage(pPage, pController, rUIXMLDescription, rID, &rItemset) + , m_bPreviewBackgroundToCharacter( false ) +{ +} + +SvxCharBasePage::~SvxCharBasePage() +{ +} + +void SvxCharBasePage::ActivatePage(const SfxItemSet& rSet) +{ + m_aPreviewWin.SetFromItemSet(rSet, m_bPreviewBackgroundToCharacter); +} + +void SvxCharBasePage::SetPrevFontWidthScale( const SfxItemSet& rSet ) +{ + sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_SCALEWIDTH ); + if (rSet.GetItemState(nWhich)>=SfxItemState::DEFAULT) + { + const SvxCharScaleWidthItem &rItem = static_cast( rSet.Get( nWhich ) ); + m_aPreviewWin.SetFontWidthScale(rItem.GetValue()); + } +} + +void SvxCharBasePage::SetPrevFontEscapement( sal_uInt8 nProp, sal_uInt8 nEscProp, short nEsc ) +{ + setPrevFontEscapement(GetPreviewFont(),nProp,nEscProp,nEsc); + setPrevFontEscapement(GetPreviewCJKFont(),nProp,nEscProp,nEsc); + setPrevFontEscapement(GetPreviewCTLFont(),nProp,nEscProp,nEsc); + m_aPreviewWin.Invalidate(); +} + + +// SvxCharNamePage_Impl -------------------------------------------------- + +struct SvxCharNamePage_Impl +{ + Idle m_aUpdateIdle; + OUString m_aNoStyleText; + std::unique_ptr m_pFontList; + int m_nExtraEntryPos; + bool m_bInSearchMode; + + SvxCharNamePage_Impl() + : m_nExtraEntryPos(std::numeric_limits::max()) + , m_bInSearchMode(false) + + { + m_aUpdateIdle.SetPriority( TaskPriority::LOWEST ); + } +}; + +// class SvxCharNamePage ------------------------------------------------- + +SvxCharNamePage::SvxCharNamePage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInSet) + : SvxCharBasePage(pPage, pController, "cui/ui/charnamepage.ui", "CharNamePage", rInSet) + , m_pImpl(new SvxCharNamePage_Impl) + , m_xEastFrame(m_xBuilder->weld_widget("asian")) + , m_xEastFontNameFT(m_xBuilder->weld_label("eastfontnameft")) + , m_xEastFontNameLB(m_xBuilder->weld_combo_box("eastfontnamelb")) + , m_xEastFontStyleFT(m_xBuilder->weld_label("eaststyleft")) + , m_xEastFontStyleLB(new FontStyleBox(m_xBuilder->weld_combo_box("eaststylelb"))) + , m_xEastFontSizeFT(m_xBuilder->weld_label("eastsizeft")) + , m_xEastFontSizeLB(new FontSizeBox(m_xBuilder->weld_combo_box("eastsizelb"))) + , m_xEastFontLanguageFT(m_xBuilder->weld_label("eastlangft")) + , m_xEastFontLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box("eastlanglb"))) + , m_xEastFontTypeFT(m_xBuilder->weld_label("eastfontinfo")) + , m_xEastFontFeaturesButton(m_xBuilder->weld_button("east_features_button")) + , m_xCTLFrame(m_xBuilder->weld_widget("ctl")) + , m_xCTLFontNameFT(m_xBuilder->weld_label("ctlfontnameft")) + , m_xCTLFontNameLB(m_xBuilder->weld_combo_box("ctlfontnamelb")) + , m_xCTLFontStyleFT(m_xBuilder->weld_label("ctlstyleft")) + , m_xCTLFontStyleLB(new FontStyleBox(m_xBuilder->weld_combo_box("ctlstylelb"))) + , m_xCTLFontSizeFT(m_xBuilder->weld_label("ctlsizeft")) + , m_xCTLFontSizeLB(new FontSizeBox(m_xBuilder->weld_combo_box("ctlsizelb"))) + , m_xCTLFontLanguageFT(m_xBuilder->weld_label("ctllangft")) + , m_xCTLFontLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box("ctllanglb"))) + , m_xCTLFontTypeFT(m_xBuilder->weld_label("ctlfontinfo")) + , m_xCTLFontFeaturesButton(m_xBuilder->weld_button("ctl_features_button")) +{ + m_xPreviewWin.reset(new weld::CustomWeld(*m_xBuilder, "preview", m_aPreviewWin)); +#ifdef IOS + m_xPreviewWin->hide(); +#endif + m_pImpl->m_aNoStyleText = CuiResId( RID_SVXSTR_CHARNAME_NOSTYLE ); + + SvtLanguageOptions aLanguageOptions; + bool bShowCJK = aLanguageOptions.IsCJKFontEnabled(); + bool bShowCTL = aLanguageOptions.IsCTLFontEnabled(); + bool bShowNonWestern = bShowCJK || bShowCTL; + + if (bShowNonWestern) + { + m_xWestFrame = m_xBuilder->weld_widget("western"); + m_xWestFontNameFT = m_xBuilder->weld_label("westfontnameft-cjk"); + m_xWestFontNameLB = m_xBuilder->weld_combo_box("westfontnamelb-cjk"); + m_xWestFontStyleFT = m_xBuilder->weld_label("weststyleft-cjk"); + m_xWestFontSizeFT = m_xBuilder->weld_label("westsizeft-cjk"); + + m_xWestFontStyleLB.reset(new FontStyleBox(m_xBuilder->weld_combo_box("weststylelb-cjk"))); + m_xWestFontSizeLB.reset(new FontSizeBox(m_xBuilder->weld_combo_box("westsizelb-cjk"))); + + m_xWestFontLanguageFT = m_xBuilder->weld_label("westlangft-cjk"); + m_xWestFontLanguageLB.reset(new SvxLanguageBox(m_xBuilder->weld_combo_box("westlanglb-cjk"))); + m_xWestFontTypeFT = m_xBuilder->weld_label("westfontinfo-cjk"); + + m_xWestFontFeaturesButton = m_xBuilder->weld_button("west_features_button-cjk"); + } + else + { + m_xWestFrame = m_xBuilder->weld_widget("simple"); + m_xWestFontNameFT = m_xBuilder->weld_label("westfontnameft-nocjk"); + m_xWestFontStyleFT = m_xBuilder->weld_label("weststyleft-nocjk"); + m_xWestFontSizeFT = m_xBuilder->weld_label("westsizeft-nocjk"); + + m_xWestFontLanguageFT = m_xBuilder->weld_label("westlangft-nocjk"); + m_xWestFontLanguageLB.reset(new SvxLanguageBox(m_xBuilder->weld_combo_box("westlanglb-nocjk"))); + m_xWestFontTypeFT = m_xBuilder->weld_label("westfontinfo-nocjk"); + + m_xWestFontFeaturesButton = m_xBuilder->weld_button("west_features_button-nocjk"); + + std::unique_ptr xWestFontNameLB = m_xBuilder->weld_entry_tree_view("namegrid", "westfontname-nocjk", "westfontnamelb-nocjk"); + std::unique_ptr xWestFontStyleLB = m_xBuilder->weld_entry_tree_view("stylegrid", "weststyle-nocjk", "weststylelb-nocjk"); + std::unique_ptr xWestFontSizeLB = m_xBuilder->weld_entry_tree_view("sizegrid", "westsize-nocjk", "westsizelb-nocjk"); + + // 7 lines in the treeview + xWestFontNameLB->set_height_request_by_rows(7); + xWestFontStyleLB->set_height_request_by_rows(7); + xWestFontSizeLB->set_height_request_by_rows(7); + + m_xWestFontNameLB = std::move(xWestFontNameLB); + m_xWestFontStyleLB.reset(new FontStyleBox(std::move(xWestFontStyleLB))); + m_xWestFontSizeLB.reset(new FontSizeBox(std::move(xWestFontSizeLB))); + } + + //In MacOSX the standard dialogs name font-name, font-style as + //Family, Typeface + //In GNOME the standard dialogs name font-name, font-style as + //Family, Style + //In Windows the standard dialogs name font-name, font-style as + //Font, Style +#ifdef _WIN32 + OUString sFontFamilyString(CuiResId(RID_SVXSTR_CHARNAME_FONT)); +#else + OUString sFontFamilyString(CuiResId(RID_SVXSTR_CHARNAME_FAMILY)); +#endif + m_xWestFontNameFT->set_label(sFontFamilyString); + m_xEastFontNameFT->set_label(sFontFamilyString); + m_xCTLFontNameFT->set_label(sFontFamilyString); + +#ifdef MACOSX + OUString sFontStyleString(CuiResId(RID_SVXSTR_CHARNAME_TYPEFACE)); +#else + OUString sFontStyleString(CuiResId(RID_SVXSTR_CHARNAME_STYLE)); +#endif + m_xWestFontStyleFT->set_label(sFontStyleString); + m_xEastFontStyleFT->set_label(sFontStyleString); + m_xCTLFontStyleFT->set_label(sFontStyleString); + + m_xWestFrame->show(); + m_xEastFrame->set_visible(bShowCJK); + m_xCTLFrame->set_visible(bShowCTL); + + m_xWestFontLanguageLB->SetLanguageList(SvxLanguageListFlags::WESTERN, true, false, true, true, + LANGUAGE_SYSTEM, css::i18n::ScriptType::LATIN); + m_xEastFontLanguageLB->SetLanguageList(SvxLanguageListFlags::CJK, true, false, true, true, + LANGUAGE_SYSTEM, css::i18n::ScriptType::ASIAN); + m_xCTLFontLanguageLB->SetLanguageList(SvxLanguageListFlags::CTL, true, false, true, true, + LANGUAGE_SYSTEM, css::i18n::ScriptType::COMPLEX); + + Initialize(); +} + +SvxCharNamePage::~SvxCharNamePage() +{ + m_pImpl.reset(); + m_xCTLFontStyleLB.reset(); + m_xEastFontLanguageLB.reset(); + m_xWestFontStyleLB.reset(); + m_xCTLFontSizeLB.reset(); + m_xEastFontSizeLB.reset(); + m_xWestFontSizeLB.reset(); + m_xWestFontLanguageLB.reset(); + m_xPreviewWin.reset(); + m_xCTLFontLanguageLB.reset(); + m_xEastFontLanguageLB.reset(); +} + +void SvxCharNamePage::Initialize() +{ + // to handle the changes of the other pages + SetExchangeSupport(); + + Link aLink = LINK(this, SvxCharNamePage, FontModifyComboBoxHdl_Impl); + m_xWestFontNameLB->connect_changed(aLink); + m_xWestFontStyleLB->connect_changed(aLink); + m_xWestFontSizeLB->connect_changed(aLink); + m_xWestFontLanguageLB->connect_changed(aLink); + + m_xWestFontFeaturesButton->connect_clicked(LINK(this, SvxCharNamePage, FontFeatureButtonClicked)); + + m_xEastFontNameLB->connect_changed(aLink); + m_xEastFontStyleLB->connect_changed(aLink); + m_xEastFontSizeLB->connect_changed(aLink); + m_xEastFontLanguageLB->connect_changed(aLink); + m_xEastFontFeaturesButton->connect_clicked(LINK(this, SvxCharNamePage, FontFeatureButtonClicked)); + + m_xCTLFontNameLB->connect_changed(aLink); + m_xCTLFontStyleLB->connect_changed(aLink); + m_xCTLFontSizeLB->connect_changed(aLink); + m_xCTLFontLanguageLB->connect_changed(aLink); + m_xCTLFontFeaturesButton->connect_clicked(LINK(this, SvxCharNamePage, FontFeatureButtonClicked)); + + m_pImpl->m_aUpdateIdle.SetInvokeHandler( LINK( this, SvxCharNamePage, UpdateHdl_Impl ) ); +} + +const FontList* SvxCharNamePage::GetFontList() const +{ + if ( !m_pImpl->m_pFontList ) + { + SfxObjectShell* pDocSh = SfxObjectShell::Current(); + + /* #110771# SvxFontListItem::GetFontList can return NULL */ + if ( pDocSh ) + { + const SfxPoolItem* pItem = pDocSh->GetItem( SID_ATTR_CHAR_FONTLIST ); + if ( pItem != nullptr ) + { + DBG_ASSERT(nullptr != static_cast(pItem)->GetFontList(), + "Where is the font list?"); + m_pImpl->m_pFontList = static_cast(pItem )->GetFontList()->Clone(); + } + } + if(!m_pImpl->m_pFontList) + { + m_pImpl->m_pFontList.reset(new FontList( Application::GetDefaultDevice() )); + } + } + + return m_pImpl->m_pFontList.get(); +} + + +namespace +{ + FontMetric calcFontMetrics( SvxFont& _rFont, + SvxCharNamePage const * _pPage, + const weld::ComboBox* _pFontNameLB, + const FontStyleBox* _pFontStyleLB, + const FontSizeBox* _pFontSizeLB, + const SvxLanguageBox* _pLanguageLB, + const FontList* _pFontList, + sal_uInt16 _nFontWhich, + sal_uInt16 _nFontHeightWhich) + { + Size aSize = _rFont.GetFontSize(); + aSize.setWidth( 0 ); + FontMetric aFontMetrics; + OUString sFontName(_pFontNameLB->get_active_text()); + bool bFontAvailable = _pFontList->IsAvailable( sFontName ); + if (bFontAvailable || _pFontNameLB->get_value_changed_from_saved()) + aFontMetrics = _pFontList->Get(sFontName, _pFontStyleLB->get_active_text()); + else + { + //get the font from itemset + SfxItemState eState = _pPage->GetItemSet().GetItemState( _nFontWhich ); + if ( eState >= SfxItemState::DEFAULT ) + { + const SvxFontItem* pFontItem = static_cast(&( _pPage->GetItemSet().Get( _nFontWhich ) )); + aFontMetrics.SetFamilyName(pFontItem->GetFamilyName()); + aFontMetrics.SetStyleName(pFontItem->GetStyleName()); + aFontMetrics.SetFamily(pFontItem->GetFamily()); + aFontMetrics.SetPitch(pFontItem->GetPitch()); + aFontMetrics.SetCharSet(pFontItem->GetCharSet()); + } + } + if ( _pFontSizeLB->IsRelative() ) + { + DBG_ASSERT( _pPage->GetItemSet().GetParent(), "No parent set" ); + const SvxFontHeightItem& rOldItem = static_cast(_pPage->GetItemSet().GetParent()->Get( _nFontHeightWhich )); + + // old value, scaled + long nHeight; + if ( _pFontSizeLB->IsPtRelative() ) + nHeight = rOldItem.GetHeight() + PointToTwips( static_cast(_pFontSizeLB->get_value() / 10) ); + else + nHeight = static_cast(rOldItem.GetHeight() * _pFontSizeLB->get_value() / 100); + + // conversion twips for the example-window + aSize.setHeight( + ItemToControl( nHeight, _pPage->GetItemSet().GetPool()->GetMetric( _nFontHeightWhich ), FieldUnit::TWIP ) ); + } + else if ( !_pFontSizeLB->get_active_text().isEmpty() ) + aSize.setHeight( PointToTwips( static_cast(_pFontSizeLB->get_value() / 10) ) ); + else + aSize.setHeight( 200 ); // default 10pt + aFontMetrics.SetFontSize( aSize ); + + _rFont.SetLanguage(_pLanguageLB->get_active_id()); + + _rFont.SetFamily( aFontMetrics.GetFamilyType() ); + _rFont.SetFamilyName( aFontMetrics.GetFamilyName() ); + _rFont.SetStyleName( aFontMetrics.GetStyleName() ); + _rFont.SetPitch( aFontMetrics.GetPitch() ); + _rFont.SetCharSet( aFontMetrics.GetCharSet() ); + _rFont.SetWeight( aFontMetrics.GetWeight() ); + _rFont.SetItalic( aFontMetrics.GetItalic() ); + _rFont.SetFontSize( aFontMetrics.GetFontSize() ); + + return aFontMetrics; + } +} + + +void SvxCharNamePage::UpdatePreview_Impl() +{ + SvxFont& rFont = GetPreviewFont(); + SvxFont& rCJKFont = GetPreviewCJKFont(); + SvxFont& rCTLFont = GetPreviewCTLFont(); + // Font + const FontList* pFontList = GetFontList(); + + FontMetric aWestFontMetric = calcFontMetrics(rFont, this, m_xWestFontNameLB.get(), + m_xWestFontStyleLB.get(), m_xWestFontSizeLB.get(), m_xWestFontLanguageLB.get(), + pFontList, GetWhich(SID_ATTR_CHAR_FONT), + GetWhich(SID_ATTR_CHAR_FONTHEIGHT)); + + m_xWestFontTypeFT->set_label(pFontList->GetFontMapText(aWestFontMetric)); + + FontMetric aEastFontMetric = calcFontMetrics(rCJKFont, this, m_xEastFontNameLB.get(), + m_xEastFontStyleLB.get(), m_xEastFontSizeLB.get(), m_xEastFontLanguageLB.get(), + pFontList, GetWhich(SID_ATTR_CHAR_CJK_FONT), + GetWhich(SID_ATTR_CHAR_CJK_FONTHEIGHT)); + + m_xEastFontTypeFT->set_label(pFontList->GetFontMapText(aEastFontMetric)); + + FontMetric aCTLFontMetric = calcFontMetrics(rCTLFont, + this, m_xCTLFontNameLB.get(), m_xCTLFontStyleLB.get(), m_xCTLFontSizeLB.get(), + m_xCTLFontLanguageLB.get(), pFontList, GetWhich(SID_ATTR_CHAR_CTL_FONT), + GetWhich(SID_ATTR_CHAR_CTL_FONTHEIGHT)); + + m_xCTLFontTypeFT->set_label(pFontList->GetFontMapText(aCTLFontMetric)); + + m_aPreviewWin.Invalidate(); +} + +void SvxCharNamePage::FillStyleBox_Impl(const weld::Widget& rNameBox) +{ + const FontList* pFontList = GetFontList(); + DBG_ASSERT( pFontList, "no fontlist" ); + + FontStyleBox* pStyleBox = nullptr; + OUString sFontName; + + if (m_xWestFontNameLB.get() == &rNameBox) + { + pStyleBox = m_xWestFontStyleLB.get(); + sFontName = m_xWestFontNameLB->get_active_text(); + } + else if (m_xEastFontNameLB.get() == &rNameBox) + { + pStyleBox = m_xEastFontStyleLB.get(); + sFontName = m_xEastFontStyleLB->get_active_text(); + } + else if (m_xCTLFontNameLB.get() == &rNameBox) + { + pStyleBox = m_xCTLFontStyleLB.get(); + sFontName = m_xCTLFontNameLB->get_active_text(); + } + else + { + SAL_WARN( "cui.tabpages", "invalid font name box" ); + return; + } + + pStyleBox->Fill(sFontName, pFontList); + + if ( !m_pImpl->m_bInSearchMode ) + return; + + // additional entries for the search: + // "not bold" and "not italic" + OUString aEntry = m_pImpl->m_aNoStyleText; + const char sS[] = "%1"; + aEntry = aEntry.replaceFirst( sS, pFontList->GetBoldStr() ); + m_pImpl->m_nExtraEntryPos = pStyleBox->get_count(); + pStyleBox->append_text( aEntry ); + aEntry = m_pImpl->m_aNoStyleText; + aEntry = aEntry.replaceFirst( sS, pFontList->GetItalicStr() ); + pStyleBox->append_text(aEntry); +} + +void SvxCharNamePage::FillSizeBox_Impl(const weld::Widget& rNameBox) +{ + const FontList* pFontList = GetFontList(); + DBG_ASSERT( pFontList, "no fontlist" ); + + FontStyleBox* pStyleBox = nullptr; + FontSizeBox* pSizeBox = nullptr; + OUString sFontName; + + if (m_xWestFontNameLB.get() == &rNameBox) + { + pStyleBox = m_xWestFontStyleLB.get(); + pSizeBox = m_xWestFontSizeLB.get(); + sFontName = m_xWestFontNameLB->get_active_text(); + } + else if (m_xEastFontNameLB.get() == &rNameBox) + { + pStyleBox = m_xEastFontStyleLB.get(); + pSizeBox = m_xEastFontSizeLB.get(); + sFontName = m_xEastFontNameLB->get_active_text(); + } + else if (m_xCTLFontNameLB.get() == &rNameBox) + { + pStyleBox = m_xCTLFontStyleLB.get(); + pSizeBox = m_xCTLFontSizeLB.get(); + sFontName = m_xCTLFontNameLB->get_active_text(); + } + else + { + SAL_WARN( "cui.tabpages", "invalid font name box" ); + return; + } + + FontMetric _aFontMetric(pFontList->Get(sFontName, pStyleBox->get_active_text())); + pSizeBox->Fill( &_aFontMetric, pFontList ); +} + +namespace +{ + void FillFontNames(weld::ComboBox& rBox, const FontList& rList) + { + // insert fonts + sal_uInt16 nFontCount = rList.GetFontNameCount(); + std::vector aVector; + aVector.reserve(nFontCount); + for (sal_uInt16 i = 0; i < nFontCount; ++i) + { + const FontMetric& rFontMetric = rList.GetFontName(i); + aVector.emplace_back(rFontMetric.GetFamilyName()); + } + rBox.insert_vector(aVector, false); + } +} + +void SvxCharNamePage::Reset_Impl( const SfxItemSet& rSet, LanguageGroup eLangGrp ) +{ + weld::ComboBox* pNameBox = nullptr; + weld::Label* pStyleLabel = nullptr; + FontStyleBox* pStyleBox = nullptr; + weld::Label* pSizeLabel = nullptr; + FontSizeBox* pSizeBox = nullptr; + weld::Label* pLangFT = nullptr; + SvxLanguageBox* pLangBox = nullptr; + sal_uInt16 nWhich = 0; + + switch ( eLangGrp ) + { + case Western : + pNameBox = m_xWestFontNameLB.get(); + pStyleLabel = m_xWestFontStyleFT.get(); + pStyleBox = m_xWestFontStyleLB.get(); + pSizeLabel = m_xWestFontSizeFT.get(); + pSizeBox = m_xWestFontSizeLB.get(); + pLangFT = m_xWestFontLanguageFT.get(); + pLangBox = m_xWestFontLanguageLB.get(); + nWhich = GetWhich( SID_ATTR_CHAR_FONT ); + break; + + case Asian : + pNameBox = m_xEastFontNameLB.get(); + pStyleLabel = m_xEastFontStyleFT.get(); + pStyleBox = m_xEastFontStyleLB.get(); + pSizeLabel = m_xEastFontSizeFT.get(); + pSizeBox = m_xEastFontSizeLB.get(); + pLangFT = m_xEastFontLanguageFT.get(); + pLangBox = m_xEastFontLanguageLB.get(); + nWhich = GetWhich( SID_ATTR_CHAR_CJK_FONT ); + break; + + case Ctl : + pNameBox = m_xCTLFontNameLB.get(); + pStyleLabel = m_xCTLFontStyleFT.get(); + pStyleBox = m_xCTLFontStyleLB.get(); + pSizeLabel = m_xCTLFontSizeFT.get(); + pSizeBox = m_xCTLFontSizeLB.get(); + pLangFT = m_xCTLFontLanguageFT.get(); + pLangBox = m_xCTLFontLanguageLB.get(); + nWhich = GetWhich( SID_ATTR_CHAR_CTL_FONT ); + break; + } + + const FontList* pFontList = GetFontList(); + FillFontNames(*pNameBox, *pFontList); + + const SvxFontItem* pFontItem = nullptr; + SfxItemState eState = rSet.GetItemState( nWhich ); + + if ( eState >= SfxItemState::DEFAULT ) + { + pFontItem = static_cast(&( rSet.Get( nWhich ) )); + const OUString &rName = pFontItem->GetFamilyName(); + int nIndex = pNameBox->find_text(rName); + pNameBox->set_active(nIndex); + // tdf#122992 if it didn't exist in the list, set the entry text to it anyway + if (nIndex == -1) + pNameBox->set_entry_text(rName); + } + else + { + pNameBox->set_active_text( OUString() ); + } + + FillStyleBox_Impl(*pNameBox); + + bool bStyle = false; + bool bStyleAvailable = true; + FontItalic eItalic = ITALIC_NONE; + FontWeight eWeight = WEIGHT_NORMAL; + switch ( eLangGrp ) + { + case Western : nWhich = GetWhich( SID_ATTR_CHAR_POSTURE ); break; + case Asian : nWhich = GetWhich( SID_ATTR_CHAR_CJK_POSTURE ); break; + case Ctl : nWhich = GetWhich( SID_ATTR_CHAR_CTL_POSTURE ); break; + } + eState = rSet.GetItemState( nWhich ); + + if ( eState >= SfxItemState::DEFAULT ) + { + const SvxPostureItem& rItem = static_cast(rSet.Get( nWhich )); + eItalic = rItem.GetValue(); + bStyle = true; + } + bStyleAvailable = bStyleAvailable && (eState >= SfxItemState::DONTCARE); + + switch ( eLangGrp ) + { + case Western : nWhich = GetWhich( SID_ATTR_CHAR_WEIGHT ); break; + case Asian : nWhich = GetWhich( SID_ATTR_CHAR_CJK_WEIGHT ); break; + case Ctl : nWhich = GetWhich( SID_ATTR_CHAR_CTL_WEIGHT ); break; + } + eState = rSet.GetItemState( nWhich ); + + if ( eState >= SfxItemState::DEFAULT ) + { + const SvxWeightItem& rItem = static_cast(rSet.Get( nWhich )); + eWeight = rItem.GetValue(); + } + else + bStyle = false; + bStyleAvailable = bStyleAvailable && (eState >= SfxItemState::DONTCARE); + + // currently chosen font + if ( bStyle && pFontItem ) + { + FontMetric aFontMetric = pFontList->Get( pFontItem->GetFamilyName(), eWeight, eItalic ); + pStyleBox->set_active_text( pFontList->GetStyleName( aFontMetric ) ); + } + else if ( !m_pImpl->m_bInSearchMode || !bStyle ) + { + pStyleBox->set_active_text( OUString() ); + } + else if ( bStyle ) + { + FontMetric aFontMetric = pFontList->Get( OUString(), eWeight, eItalic ); + pStyleBox->set_active_text( pFontList->GetStyleName( aFontMetric ) ); + } + if (!bStyleAvailable) + { + pStyleBox->set_sensitive(false); + pStyleLabel->set_sensitive(false); + } + + FillSizeBox_Impl(*pNameBox); + switch ( eLangGrp ) + { + case Western : nWhich = GetWhich( SID_ATTR_CHAR_FONTHEIGHT ); break; + case Asian : nWhich = GetWhich( SID_ATTR_CHAR_CJK_FONTHEIGHT ); break; + case Ctl : nWhich = GetWhich( SID_ATTR_CHAR_CTL_FONTHEIGHT ); break; + } + eState = rSet.GetItemState( nWhich ); + + if ( pSizeBox->IsRelativeMode() ) + { + MapUnit eUnit = rSet.GetPool()->GetMetric( nWhich ); + const SvxFontHeightItem& rItem = static_cast(rSet.Get( nWhich )); + + if( rItem.GetProp() != 100 || MapUnit::MapRelative != rItem.GetPropUnit() ) + { + bool bPtRel = MapUnit::MapPoint == rItem.GetPropUnit(); + pSizeBox->SetPtRelative( bPtRel ); + pSizeBox->set_value( bPtRel ? static_cast(rItem.GetProp()) * 10 : rItem.GetProp() ); + } + else + { + pSizeBox->SetRelative(false); + pSizeBox->set_value( CalcToPoint( rItem.GetHeight(), eUnit, 10 ) ); + } + } + else if ( eState >= SfxItemState::DEFAULT ) + { + MapUnit eUnit = rSet.GetPool()->GetMetric( nWhich ); + const SvxFontHeightItem& rItem = static_cast(rSet.Get( nWhich )); + pSizeBox->set_value( CalcToPoint( rItem.GetHeight(), eUnit, 10 ) ); + } + else + { + pSizeBox->set_active_or_entry_text(OUString()); + if ( eState <= SfxItemState::READONLY ) + { + pSizeBox->set_sensitive(false); + pSizeLabel->set_sensitive(false); + } + } + + switch ( eLangGrp ) + { + case Western : nWhich = GetWhich( SID_ATTR_CHAR_LANGUAGE ); break; + case Asian : nWhich = GetWhich( SID_ATTR_CHAR_CJK_LANGUAGE ); break; + case Ctl : nWhich = GetWhich( SID_ATTR_CHAR_CTL_LANGUAGE ); break; + } + pLangBox->set_active(-1); + eState = rSet.GetItemState( nWhich ); + + switch ( eState ) + { + case SfxItemState::UNKNOWN: + pLangFT->hide(); + pLangBox->hide(); + break; + + case SfxItemState::DISABLED: + case SfxItemState::READONLY: + pLangFT->set_sensitive(false); + pLangBox->set_sensitive(false); + break; + + case SfxItemState::DEFAULT: + case SfxItemState::SET: + { + const SvxLanguageItem& rItem = static_cast(rSet.Get( nWhich )); + LanguageType eLangType = rItem.GetValue(); + DBG_ASSERT( eLangType != LANGUAGE_SYSTEM, "LANGUAGE_SYSTEM not allowed" ); + if (eLangType != LANGUAGE_DONTKNOW) + pLangBox->set_active_id(eLangType); + break; + } + case SfxItemState::DONTCARE: + break; + } + + OUString sMapText(pFontList->GetFontMapText( + pFontList->Get(pNameBox->get_active_text(), pStyleBox->get_active_text()))); + + switch (eLangGrp) + { + case Western: + m_xWestFontTypeFT->set_label(sMapText); + break; + case Asian: + m_xEastFontTypeFT->set_label(sMapText); + break; + case Ctl: + m_xCTLFontTypeFT->set_label(sMapText); + break; + } + + // save these settings + pNameBox->save_value(); + pStyleBox->save_value(); + pSizeBox->save_value(); + pLangBox->save_active_id(); +} + +bool SvxCharNamePage::FillItemSet_Impl( SfxItemSet& rSet, LanguageGroup eLangGrp ) +{ + bool bModified = false; + + weld::ComboBox* pNameBox = nullptr; + FontStyleBox* pStyleBox = nullptr; + FontSizeBox* pSizeBox = nullptr; + SvxLanguageBox* pLangBox = nullptr; + sal_uInt16 nWhich = 0; + sal_uInt16 nSlot = 0; + + switch ( eLangGrp ) + { + case Western : + pNameBox = m_xWestFontNameLB.get(); + pStyleBox = m_xWestFontStyleLB.get(); + pSizeBox = m_xWestFontSizeLB.get(); + pLangBox = m_xWestFontLanguageLB.get(); + nSlot = SID_ATTR_CHAR_FONT; + break; + + case Asian : + pNameBox = m_xEastFontNameLB.get(); + pStyleBox = m_xEastFontStyleLB.get(); + pSizeBox = m_xEastFontSizeLB.get(); + pLangBox = m_xEastFontLanguageLB.get(); + nSlot = SID_ATTR_CHAR_CJK_FONT; + break; + + case Ctl : + pNameBox = m_xCTLFontNameLB.get(); + pStyleBox = m_xCTLFontStyleLB.get(); + pSizeBox = m_xCTLFontSizeLB.get(); + pLangBox = m_xCTLFontLanguageLB.get(); + nSlot = SID_ATTR_CHAR_CTL_FONT; + break; + } + + nWhich = GetWhich( nSlot ); + const SfxPoolItem* pItem = nullptr; + const SfxItemSet& rOldSet = GetItemSet(); + const SfxPoolItem* pOld = nullptr; + + const SfxItemSet* pExampleSet = GetDialogExampleSet(); + + bool bChanged = true; + const OUString& rFontName = pNameBox->get_active_text(); + const FontList* pFontList = GetFontList(); + OUString aStyleBoxText = pStyleBox->get_active_text(); + int nEntryPos = pStyleBox->find_text(aStyleBoxText); + if (nEntryPos >= m_pImpl->m_nExtraEntryPos) + aStyleBoxText.clear(); + FontMetric aInfo( pFontList->Get( rFontName, aStyleBoxText ) ); + SvxFontItem aFontItem( aInfo.GetFamilyType(), aInfo.GetFamilyName(), aInfo.GetStyleName(), + aInfo.GetPitch(), aInfo.GetCharSet(), nWhich ); + pOld = GetOldItem( rSet, nSlot ); + + if ( pOld ) + { + const SvxFontItem& rItem = *static_cast(pOld); + + if ( rItem.GetFamilyName() == aFontItem.GetFamilyName() ) + bChanged = false; + } + + if ( !bChanged ) + bChanged = pNameBox->get_saved_value().isEmpty(); + + if ( !bChanged && pExampleSet && + pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET && + static_cast(pItem)->GetFamilyName() != aFontItem.GetFamilyName() ) + bChanged = true; + + if ( bChanged && !rFontName.isEmpty() ) + { + rSet.Put( aFontItem ); + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet.ClearItem( nWhich ); + + + bChanged = true; + switch ( eLangGrp ) + { + case Western : nSlot = SID_ATTR_CHAR_WEIGHT; break; + case Asian : nSlot = SID_ATTR_CHAR_CJK_WEIGHT; break; + case Ctl : nSlot = SID_ATTR_CHAR_CTL_WEIGHT; break; + } + nWhich = GetWhich( nSlot ); + FontWeight eWeight = aInfo.GetWeight(); + if ( nEntryPos >= m_pImpl->m_nExtraEntryPos ) + eWeight = WEIGHT_NORMAL; + SvxWeightItem aWeightItem( eWeight, nWhich ); + pOld = GetOldItem( rSet, nSlot ); + + if ( pOld ) + { + const SvxWeightItem& rItem = *static_cast(pOld); + + if ( rItem.GetValue() == aWeightItem.GetValue() ) + bChanged = false; + } + + if ( !bChanged ) + { + bChanged = pStyleBox->get_saved_value().isEmpty(); + + if ( m_pImpl->m_bInSearchMode && bChanged && + aInfo.GetWeight() == WEIGHT_NORMAL && aInfo.GetItalic() != ITALIC_NONE ) + bChanged = false; + } + + if ( !bChanged && pExampleSet && + pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET && + static_cast(pItem)->GetValue() != aWeightItem.GetValue() ) + bChanged = true; + + if ( nEntryPos >= m_pImpl->m_nExtraEntryPos ) + bChanged = ( nEntryPos == m_pImpl->m_nExtraEntryPos ); + + OUString aText( pStyleBox->get_active_text() ); // Tristate, then text empty + + if ( bChanged && !aText.isEmpty() ) + { + rSet.Put( aWeightItem ); + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet.InvalidateItem(nWhich); + + bChanged = true; + switch ( eLangGrp ) + { + case Western : nSlot = SID_ATTR_CHAR_POSTURE; break; + case Asian : nSlot = SID_ATTR_CHAR_CJK_POSTURE; break; + case Ctl : nSlot = SID_ATTR_CHAR_CTL_POSTURE; break; + } + nWhich = GetWhich( nSlot ); + FontItalic eItalic = aInfo.GetItalic(); + if ( nEntryPos >= m_pImpl->m_nExtraEntryPos ) + eItalic = ITALIC_NONE; + SvxPostureItem aPostureItem( eItalic, nWhich ); + pOld = GetOldItem( rSet, nSlot ); + + if ( pOld ) + { + const SvxPostureItem& rItem = *static_cast(pOld); + + if ( rItem.GetValue() == aPostureItem.GetValue() ) + bChanged = false; + } + + if ( !bChanged ) + { + bChanged = pStyleBox->get_saved_value().isEmpty(); + + if ( m_pImpl->m_bInSearchMode && bChanged && + aInfo.GetItalic() == ITALIC_NONE && aInfo.GetWeight() != WEIGHT_NORMAL ) + bChanged = false; + } + + if ( !bChanged && pExampleSet && + pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET && + static_cast(pItem)->GetValue() != aPostureItem.GetValue() ) + bChanged = true; + + if ( nEntryPos >= m_pImpl->m_nExtraEntryPos ) + bChanged = ( nEntryPos == ( m_pImpl->m_nExtraEntryPos + 1 ) ); + + if ( bChanged && !aText.isEmpty() ) + { + rSet.Put( aPostureItem ); + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet.InvalidateItem(nWhich); + + // FontSize + long nSize = pSizeBox->get_value(); + + if ( pSizeBox->get_active_text().isEmpty() ) // GetValue() returns the min-value + nSize = 0; + long nSavedSize = pSizeBox->get_saved_value(); + const bool bRel = pSizeBox->IsRelative(); + + switch ( eLangGrp ) + { + case Western : nSlot = SID_ATTR_CHAR_FONTHEIGHT; break; + case Asian : nSlot = SID_ATTR_CHAR_CJK_FONTHEIGHT; break; + case Ctl : nSlot = SID_ATTR_CHAR_CTL_FONTHEIGHT; break; + } + nWhich = GetWhich( nSlot ); + const SvxFontHeightItem* pOldHeight = static_cast(GetOldItem( rSet, nSlot )); + bChanged = ( nSize != nSavedSize ); + + if ( !bChanged && pExampleSet && + pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET ) + { + float fSize = static_cast(nSize) / 10; + long nVal = CalcToUnit( fSize, rSet.GetPool()->GetMetric( nWhich ) ); + if ( static_cast(pItem)->GetHeight() != static_cast(nVal) ) + bChanged = true; + } + + if ( bChanged || !pOldHeight || + bRel != ( MapUnit::MapRelative != pOldHeight->GetPropUnit() || 100 != pOldHeight->GetProp() ) ) + { + MapUnit eUnit = rSet.GetPool()->GetMetric( nWhich ); + if ( pSizeBox->IsRelative() ) + { + DBG_ASSERT( GetItemSet().GetParent(), "No parent set" ); + const SvxFontHeightItem& rOldItem = + static_cast(GetItemSet().GetParent()->Get( nWhich )); + + SvxFontHeightItem aHeight( 240, 100, nWhich ); + if ( pSizeBox->IsPtRelative() ) + aHeight.SetHeight( rOldItem.GetHeight(), static_cast( nSize / 10 ), MapUnit::MapPoint, eUnit ); + else + aHeight.SetHeight( rOldItem.GetHeight(), static_cast(nSize) ); + rSet.Put( aHeight ); + } + else + { + float fSize = static_cast(nSize) / 10; + rSet.Put( SvxFontHeightItem( CalcToUnit( fSize, eUnit ), 100, nWhich ) ); + } + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet.InvalidateItem(nWhich); + + bChanged = true; + switch ( eLangGrp ) + { + case Western : nSlot = SID_ATTR_CHAR_LANGUAGE; break; + case Asian : nSlot = SID_ATTR_CHAR_CJK_LANGUAGE; break; + case Ctl : nSlot = SID_ATTR_CHAR_CTL_LANGUAGE; break; + } + nWhich = GetWhich( nSlot ); + pOld = GetOldItem( rSet, nSlot ); + + // For language list boxes acting as ComboBox, check for, add and select an + // edited entry. + if (pLangBox == m_xWestFontLanguageLB.get()) + { + switch (pLangBox->GetEditedAndValid()) + { + case SvxLanguageBox::EditedAndValid::No: + ; // nothing to do + break; + case SvxLanguageBox::EditedAndValid::Valid: + { + const int nPos = pLangBox->SaveEditedAsEntry(); + if (nPos != -1) + pLangBox->set_active(nPos); + } + break; + case SvxLanguageBox::EditedAndValid::Invalid: + pLangBox->set_active_id(pLangBox->get_saved_active_id()); + break; + } + } + + int nLangPos = pLangBox->get_active(); + LanguageType eLangType = pLangBox->get_active_id(); + + if (pOld) + { + const SvxLanguageItem& rItem = *static_cast(pOld); + if (nLangPos == -1 || eLangType == rItem.GetValue()) + bChanged = false; + } + + if (!bChanged) + bChanged = pLangBox->get_active_id_changed_from_saved(); + + if (bChanged && nLangPos != -1) + { + rSet.Put(SvxLanguageItem(eLangType, nWhich)); + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet.InvalidateItem(nWhich); + + return bModified; +} + +IMPL_LINK_NOARG(SvxCharNamePage, UpdateHdl_Impl, Timer *, void) +{ + UpdatePreview_Impl(); +} + +IMPL_LINK(SvxCharNamePage, FontModifyComboBoxHdl_Impl, weld::ComboBox&, rBox, void) +{ + FontModifyHdl_Impl(rBox); +} + +IMPL_LINK(SvxCharNamePage, FontFeatureButtonClicked, weld::Button&, rButton, void) +{ + OUString sFontName; + weld::ComboBox* pNameBox = nullptr; + + if (&rButton == m_xWestFontFeaturesButton.get()) + { + pNameBox = m_xWestFontNameLB.get(); + sFontName = GetPreviewFont().GetFamilyName(); + } + else if (&rButton == m_xEastFontFeaturesButton.get()) + { + pNameBox = m_xEastFontNameLB.get(); + sFontName = GetPreviewCJKFont().GetFamilyName(); + } + else if (&rButton == m_xCTLFontFeaturesButton.get()) + { + pNameBox = m_xCTLFontNameLB.get(); + sFontName = GetPreviewCTLFont().GetFamilyName(); + } + + if (!sFontName.isEmpty() && pNameBox) + { + cui::FontFeaturesDialog aDialog(GetFrameWeld(), sFontName); + if (aDialog.run() == RET_OK) + { + pNameBox->set_entry_text(aDialog.getResultFontName()); + UpdatePreview_Impl(); + } + } +} + +void SvxCharNamePage::FontModifyHdl_Impl(const weld::Widget& rNameBox) +{ + m_pImpl->m_aUpdateIdle.Start(); + + if (m_xWestFontNameLB.get() == &rNameBox || m_xEastFontNameLB.get() == &rNameBox || m_xCTLFontNameLB.get() == &rNameBox) + { + FillStyleBox_Impl(rNameBox); + FillSizeBox_Impl(rNameBox); + } +} + +void SvxCharNamePage::ActivatePage( const SfxItemSet& rSet ) +{ + SvxCharBasePage::ActivatePage( rSet ); + + UpdatePreview_Impl(); // instead of asynchronous calling in ctor +} + +DeactivateRC SvxCharNamePage::DeactivatePage( SfxItemSet* _pSet ) +{ + if ( _pSet ) + FillItemSet( _pSet ); + return DeactivateRC::LeavePage; +} + +std::unique_ptr SvxCharNamePage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet) +{ + return std::make_unique(pPage, pController, *rSet ); +} + +void SvxCharNamePage::Reset( const SfxItemSet* rSet ) +{ + Reset_Impl( *rSet, Western ); + Reset_Impl( *rSet, Asian ); + Reset_Impl( *rSet, Ctl ); + + SetPrevFontWidthScale( *rSet ); + UpdatePreview_Impl(); +} + +void SvxCharNamePage::ChangesApplied() +{ + m_xWestFontNameLB->save_value(); + m_xWestFontStyleLB->save_value(); + m_xWestFontSizeLB->save_value(); + m_xWestFontLanguageLB->save_active_id(); + m_xEastFontNameLB->save_value(); + m_xEastFontStyleLB->save_value(); + m_xEastFontSizeLB->save_value(); + m_xEastFontLanguageLB->save_active_id(); + m_xCTLFontNameLB->save_value(); + m_xCTLFontStyleLB->save_value(); + m_xCTLFontSizeLB->save_value(); + m_xCTLFontLanguageLB->save_active_id(); +} + +bool SvxCharNamePage::FillItemSet( SfxItemSet* rSet ) +{ + bool bModified = FillItemSet_Impl( *rSet, Western ); + bModified |= FillItemSet_Impl( *rSet, Asian ); + bModified |= FillItemSet_Impl( *rSet, Ctl ); + return bModified; +} + +void SvxCharNamePage::SetFontList( const SvxFontListItem& rItem ) +{ + m_pImpl->m_pFontList = rItem.GetFontList()->Clone(); +} + +namespace +{ + void enableRelativeMode( SvxCharNamePage const * _pPage, FontSizeBox* _pFontSizeLB, sal_uInt16 _nHeightWhich ) + { + _pFontSizeLB->EnableRelativeMode( 5, 995 ); // min 5%, max 995%, step 5 + + const SvxFontHeightItem& rHeightItem = + static_cast(_pPage->GetItemSet().GetParent()->Get( _nHeightWhich )); + MapUnit eUnit = _pPage->GetItemSet().GetPool()->GetMetric( _nHeightWhich ); + short nCurHeight = + static_cast< short >( CalcToPoint( rHeightItem.GetHeight(), eUnit, 1 ) * 10 ); + + // based on the current height: + // - negative until minimum of 2 pt + // - positive until maximum of 999 pt + _pFontSizeLB->EnablePtRelativeMode( sal::static_int_cast< short >(-(nCurHeight - 20)), (9999 - nCurHeight) ); + } +} + +void SvxCharNamePage::EnableRelativeMode() +{ + DBG_ASSERT( GetItemSet().GetParent(), "RelativeMode, but no ParentSet!" ); + enableRelativeMode(this,m_xWestFontSizeLB.get(),GetWhich( SID_ATTR_CHAR_FONTHEIGHT )); + enableRelativeMode(this,m_xEastFontSizeLB.get(),GetWhich( SID_ATTR_CHAR_CJK_FONTHEIGHT )); + enableRelativeMode(this,m_xCTLFontSizeLB.get(),GetWhich( SID_ATTR_CHAR_CTL_FONTHEIGHT )); +} + +void SvxCharNamePage::EnableSearchMode() +{ + m_pImpl->m_bInSearchMode = true; +} + +void SvxCharNamePage::DisableControls( sal_uInt16 nDisable ) +{ + if ( DISABLE_LANGUAGE & nDisable ) + { + if ( m_xWestFontLanguageFT ) m_xWestFontLanguageFT->set_sensitive(false); + if ( m_xWestFontLanguageLB ) m_xWestFontLanguageLB->set_sensitive(false); + if ( m_xEastFontLanguageFT ) m_xEastFontLanguageFT->set_sensitive(false); + if ( m_xEastFontLanguageLB ) m_xEastFontLanguageLB->set_sensitive(false); + if ( m_xCTLFontLanguageFT ) m_xCTLFontLanguageFT->set_sensitive(false); + if ( m_xCTLFontLanguageLB ) m_xCTLFontLanguageLB->set_sensitive(false); + } + + if ( DISABLE_HIDE_LANGUAGE & nDisable ) + { + if ( m_xWestFontLanguageFT ) m_xWestFontLanguageFT->hide(); + if ( m_xWestFontLanguageLB ) m_xWestFontLanguageLB->hide(); + if ( m_xEastFontLanguageFT ) m_xEastFontLanguageFT->hide(); + if ( m_xEastFontLanguageLB ) m_xEastFontLanguageLB->hide(); + if ( m_xCTLFontLanguageFT ) m_xCTLFontLanguageFT->hide(); + if ( m_xCTLFontLanguageLB ) m_xCTLFontLanguageLB->hide(); + } +} + +void SvxCharNamePage::PageCreated(const SfxAllItemSet& aSet) +{ + const SvxFontListItem* pFontListItem = aSet.GetItem(SID_ATTR_CHAR_FONTLIST, false); + const SfxUInt32Item* pFlagItem = aSet.GetItem(SID_FLAG_TYPE, false); + const SfxUInt16Item* pDisalbeItem = aSet.GetItem(SID_DISABLE_CTL, false); + if (pFontListItem) + SetFontList(*pFontListItem); + + if (pFlagItem) + { + sal_uInt32 nFlags=pFlagItem->GetValue(); + if ( ( nFlags & SVX_RELATIVE_MODE ) == SVX_RELATIVE_MODE ) + EnableRelativeMode(); + if ( ( nFlags & SVX_PREVIEW_CHARACTER ) == SVX_PREVIEW_CHARACTER ) + // the writer uses SID_ATTR_BRUSH as font background + m_bPreviewBackgroundToCharacter = true; + } + if (pDisalbeItem) + DisableControls(pDisalbeItem->GetValue()); +} +// class SvxCharEffectsPage ---------------------------------------------- + +SvxCharEffectsPage::SvxCharEffectsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInSet) + : SvxCharBasePage(pPage, pController, "cui/ui/effectspage.ui", "EffectsPage", rInSet) + , m_bOrigFontColor(false) + , m_bNewFontColor(false) + , m_bEnableNoneFontColor(false) + , m_bUnderlineColorDisabled(false) + , m_xFontColorFT(m_xBuilder->weld_label("fontcolorft")) + , m_xFontColorLB(new ColorListBox(m_xBuilder->weld_menu_button("fontcolorlb"), pController->getDialog())) + , m_xFontTransparencyFT(m_xBuilder->weld_label("fonttransparencyft")) + , m_xFontTransparencyMtr( + m_xBuilder->weld_metric_spin_button("fonttransparencymtr", FieldUnit::PERCENT)) + , m_xEffectsFT(m_xBuilder->weld_label("effectsft")) + , m_xEffectsLB(m_xBuilder->weld_combo_box("effectslb")) + , m_xReliefFT(m_xBuilder->weld_label("reliefft")) + , m_xReliefLB(m_xBuilder->weld_combo_box("relieflb")) + , m_xOutlineBtn(m_xBuilder->weld_check_button("outlinecb")) + , m_xShadowBtn(m_xBuilder->weld_check_button("shadowcb")) + , m_xHiddenBtn(m_xBuilder->weld_check_button("hiddencb")) + , m_xOverlineLB(m_xBuilder->weld_combo_box("overlinelb")) + , m_xOverlineColorFT(m_xBuilder->weld_label("overlinecolorft")) + , m_xOverlineColorLB(new ColorListBox(m_xBuilder->weld_menu_button("overlinecolorlb"), pController->getDialog())) + , m_xStrikeoutLB(m_xBuilder->weld_combo_box("strikeoutlb")) + , m_xUnderlineLB(m_xBuilder->weld_combo_box("underlinelb")) + , m_xUnderlineColorFT(m_xBuilder->weld_label("underlinecolorft")) + , m_xUnderlineColorLB(new ColorListBox(m_xBuilder->weld_menu_button("underlinecolorlb"), pController->getDialog())) + , m_xIndividualWordsBtn(m_xBuilder->weld_check_button("individualwordscb")) + , m_xEmphasisFT(m_xBuilder->weld_label("emphasisft")) + , m_xEmphasisLB(m_xBuilder->weld_combo_box("emphasislb")) + , m_xPositionFT(m_xBuilder->weld_label("positionft")) + , m_xPositionLB(m_xBuilder->weld_combo_box("positionlb")) + , m_xA11yWarningFT(m_xBuilder->weld_label("a11ywarning")) +{ + m_xPreviewWin.reset(new weld::CustomWeld(*m_xBuilder, "preview", m_aPreviewWin)); +#ifdef IOS + m_xPreviewWin->hide(); +#endif + m_xFontColorLB->SetSlotId(SID_ATTR_CHAR_COLOR); + m_xOverlineColorLB->SetSlotId(SID_ATTR_CHAR_COLOR); + m_xUnderlineColorLB->SetSlotId(SID_ATTR_CHAR_COLOR); + Initialize(); +} + +void SvxCharEffectsPage::EnableNoneFontColor() +{ + m_xFontColorLB->SetSlotId(SID_ATTR_CHAR_COLOR, true); + m_bEnableNoneFontColor = true; +} + +Color SvxCharEffectsPage::GetPreviewFontColor(const Color& rColor) const +{ + if (rColor == COL_AUTO) + return COL_BLACK; + if (m_bEnableNoneFontColor && rColor == COL_NONE_COLOR) + return COL_BLACK; + return rColor; +} + +SvxCharEffectsPage::~SvxCharEffectsPage() +{ + m_xUnderlineColorLB.reset(); + m_xOverlineColorLB.reset(); + m_xFontTransparencyMtr.reset(); + m_xFontColorLB.reset(); +} + +void SvxCharEffectsPage::Initialize() +{ + // to handle the changes of the other pages + SetExchangeSupport(); + + // HTML-Mode + const SfxPoolItem* pItem; + SfxObjectShell* pShell; + if ( SfxItemState::SET == GetItemSet().GetItemState( SID_HTML_MODE, false, &pItem ) || + ( nullptr != ( pShell = SfxObjectShell::Current() ) && + nullptr != ( pItem = pShell->GetItem( SID_HTML_MODE ) ) ) ) + { + m_nHtmlMode = static_cast(pItem)->GetValue(); + if ( ( m_nHtmlMode & HTMLMODE_ON ) == HTMLMODE_ON ) + { + //!!! hide some controls please + } + } + + m_xFontColorLB->SetSelectHdl(LINK(this, SvxCharEffectsPage, ColorBoxSelectHdl_Impl)); + m_xFontTransparencyMtr->connect_value_changed( + LINK(this, SvxCharEffectsPage, ModifyFontTransparencyHdl_Impl)); + + // handler + Link aLink = LINK( this, SvxCharEffectsPage, SelectListBoxHdl_Impl ); + m_xUnderlineLB->connect_changed( aLink ); + m_xUnderlineColorLB->SetSelectHdl(LINK(this, SvxCharEffectsPage, ColorBoxSelectHdl_Impl)); + m_xOverlineLB->connect_changed( aLink ); + m_xOverlineColorLB->SetSelectHdl(LINK(this, SvxCharEffectsPage, ColorBoxSelectHdl_Impl)); + m_xStrikeoutLB->connect_changed( aLink ); + m_xEmphasisLB->connect_changed( aLink ); + m_xPositionLB->connect_changed( aLink ); + m_xEffectsLB->connect_changed( aLink ); + m_xReliefLB->connect_changed( aLink ); + + m_xUnderlineLB->set_active( 0 ); + m_xOverlineLB->set_active( 0 ); + m_xStrikeoutLB->set_active( 0 ); + m_xEmphasisLB->set_active( 0 ); + m_xPositionLB->set_active( 0 ); + SelectHdl_Impl(nullptr); + SelectHdl_Impl(m_xEmphasisLB.get()); + + m_xEffectsLB->set_active( 0 ); + + m_xHiddenBtn->connect_toggled(LINK(this, SvxCharEffectsPage, HiddenBtnClickHdl)); + m_xIndividualWordsBtn->connect_toggled(LINK(this, SvxCharEffectsPage, CbClickHdl_Impl)); + m_xOutlineBtn->connect_toggled(LINK(this, SvxCharEffectsPage, OutlineBtnClickHdl)); + m_xShadowBtn->connect_toggled(LINK(this, SvxCharEffectsPage, ShadowBtnClickHdl)); + + if ( !SvtLanguageOptions().IsAsianTypographyEnabled() ) + { + m_xEmphasisFT->hide(); + m_xEmphasisLB->hide(); + m_xPositionFT->hide(); + m_xPositionLB->hide(); + } + + m_xA11yWarningFT->set_visible(officecfg::Office::Common::Accessibility::IsAutomaticFontColor::get()); +} + +void SvxCharEffectsPage::UpdatePreview_Impl() +{ + SvxFont& rFont = GetPreviewFont(); + SvxFont& rCJKFont = GetPreviewCJKFont(); + SvxFont& rCTLFont = GetPreviewCTLFont(); + + const Color& rSelectedColor = m_xFontColorLB->GetSelectEntryColor(); + rFont.SetColor(GetPreviewFontColor(rSelectedColor)); + rCJKFont.SetColor(GetPreviewFontColor(rSelectedColor)); + rCTLFont.SetColor(GetPreviewFontColor(rSelectedColor)); + + FontLineStyle eUnderline = static_cast(m_xUnderlineLB->get_active_id().toInt32()); + FontLineStyle eOverline = static_cast(m_xOverlineLB->get_active_id().toInt32()); + FontStrikeout eStrikeout = static_cast(m_xStrikeoutLB->get_active_id().toInt32()); + rFont.SetUnderline( eUnderline ); + rCJKFont.SetUnderline( eUnderline ); + rCTLFont.SetUnderline( eUnderline ); + m_aPreviewWin.SetTextLineColor( m_xUnderlineColorLB->GetSelectEntryColor() ); + rFont.SetOverline( eOverline ); + rCJKFont.SetOverline( eOverline ); + rCTLFont.SetOverline( eOverline ); + m_aPreviewWin.SetOverlineColor( m_xOverlineColorLB->GetSelectEntryColor() ); + rFont.SetStrikeout( eStrikeout ); + rCJKFont.SetStrikeout( eStrikeout ); + rCTLFont.SetStrikeout( eStrikeout ); + + auto nEmphasis = m_xEmphasisLB->get_active(); + if (nEmphasis != -1) + { + bool bUnder = (CHRDLG_POSITION_UNDER == m_xPositionLB->get_active_id().toInt32()); + FontEmphasisMark eMark = static_cast(nEmphasis); + eMark |= bUnder ? FontEmphasisMark::PosBelow : FontEmphasisMark::PosAbove; + rFont.SetEmphasisMark( eMark ); + rCJKFont.SetEmphasisMark( eMark ); + rCTLFont.SetEmphasisMark( eMark ); + } + + auto nRelief = m_xReliefLB->get_active(); + if (nRelief != -1) + { + rFont.SetRelief( static_cast(nRelief) ); + rCJKFont.SetRelief( static_cast(nRelief) ); + rCTLFont.SetRelief( static_cast(nRelief) ); + } + + rFont.SetOutline( StateToAttr( m_xOutlineBtn->get_state() ) ); + rCJKFont.SetOutline( rFont.IsOutline() ); + rCTLFont.SetOutline( rFont.IsOutline() ); + + rFont.SetShadow( StateToAttr( m_xShadowBtn->get_state() ) ); + rCJKFont.SetShadow( rFont.IsShadow() ); + rCTLFont.SetShadow( rFont.IsShadow() ); + + auto nCapsPos = m_xEffectsLB->get_active(); + if (nCapsPos != -1) + { + SvxCaseMap eCaps = static_cast(nCapsPos); + rFont.SetCaseMap( eCaps ); + rCJKFont.SetCaseMap( eCaps ); + // #i78474# small caps do not exist in CTL fonts + rCTLFont.SetCaseMap( eCaps == SvxCaseMap::SmallCaps ? SvxCaseMap::NotMapped : eCaps ); + } + + bool bWordLine = StateToAttr( m_xIndividualWordsBtn->get_state() ); + rFont.SetWordLineMode( bWordLine ); + rCJKFont.SetWordLineMode( bWordLine ); + rCTLFont.SetWordLineMode( bWordLine ); + + m_aPreviewWin.Invalidate(); +} + +void SvxCharEffectsPage::SetCaseMap_Impl( SvxCaseMap eCaseMap ) +{ + if ( SvxCaseMap::End > eCaseMap ) + m_xEffectsLB->set_active( + sal::static_int_cast< sal_Int32 >( eCaseMap ) ); + else + { + // not mapped + m_xEffectsLB->set_active(-1); + } + + UpdatePreview_Impl(); +} + +void SvxCharEffectsPage::ResetColor_Impl( const SfxItemSet& rSet ) +{ + sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_COLOR ); + SfxItemState eState = rSet.GetItemState( nWhich ); + + m_bOrigFontColor = false; + switch ( eState ) + { + case SfxItemState::UNKNOWN: + m_xFontColorFT->hide(); + m_xFontColorLB->hide(); + break; + + case SfxItemState::DISABLED: + case SfxItemState::READONLY: + m_xFontColorFT->set_sensitive(false); + m_xFontColorLB->set_sensitive(false); + break; + + case SfxItemState::DONTCARE: + //Related: tdf#106080 if there is no font color, then allow "none" + //as a color so the listbox can display that state. + EnableNoneFontColor(); + m_xFontColorLB->SetNoSelection(); + break; + + case SfxItemState::DEFAULT: + case SfxItemState::SET: + { + SvxFont& rFont = GetPreviewFont(); + SvxFont& rCJKFont = GetPreviewCJKFont(); + SvxFont& rCTLFont = GetPreviewCTLFont(); + + const SvxColorItem& rItem = static_cast(rSet.Get( nWhich )); + Color aColor = rItem.GetValue(); + rFont.SetColor(GetPreviewFontColor(aColor)); + rCJKFont.SetColor(GetPreviewFontColor(aColor)); + rCTLFont.SetColor(GetPreviewFontColor(aColor)); + + m_aPreviewWin.Invalidate(); + + Color aRGBColor = aColor; + if (aRGBColor.GetTransparency() && aColor != COL_AUTO) + { + aRGBColor.SetTransparency(0); + } + m_xFontColorLB->SelectEntry(aRGBColor); + + if (m_xFontTransparencyMtr->get_visible() && aColor != COL_AUTO) + { + double fTransparency = aColor.GetTransparency() * 100.0 / 255; + m_xFontTransparencyMtr->set_value(basegfx::fround(fTransparency), + FieldUnit::PERCENT); + } + + m_aOrigFontColor = aColor; + m_bOrigFontColor = true; + break; + } + } + m_bNewFontColor = false; +} + +bool SvxCharEffectsPage::FillItemSetColor_Impl( SfxItemSet& rSet ) +{ + sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_COLOR ); + const SfxItemSet& rOldSet = GetItemSet(); + + Color aSelectedColor; + bool bChanged = m_bNewFontColor; + + if (bChanged) + { + aSelectedColor = m_xFontColorLB->GetSelectEntryColor(); + + if (m_xFontTransparencyMtr->get_value_changed_from_saved()) + { + double fTransparency + = m_xFontTransparencyMtr->get_value(FieldUnit::PERCENT) * 255.0 / 100; + aSelectedColor.SetTransparency(static_cast(basegfx::fround(fTransparency))); + } + + if (m_bOrigFontColor) + bChanged = aSelectedColor != m_aOrigFontColor; + if (m_bEnableNoneFontColor && bChanged && aSelectedColor == COL_NONE_COLOR) + bChanged = false; + } + + if (bChanged) + rSet.Put( SvxColorItem( aSelectedColor, nWhich ) ); + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet.InvalidateItem(nWhich); + + return bChanged; +} + +IMPL_LINK( SvxCharEffectsPage, SelectListBoxHdl_Impl, weld::ComboBox&, rBox, void ) +{ + SelectHdl_Impl(&rBox); +} + +void SvxCharEffectsPage::SelectHdl_Impl(const weld::ComboBox* pBox) +{ + if (m_xEmphasisLB.get() == pBox) + { + auto nEPos = m_xEmphasisLB->get_active(); + bool bEnable = nEPos > 0; + m_xPositionFT->set_sensitive( bEnable ); + m_xPositionLB->set_sensitive( bEnable ); + } + else if (m_xReliefLB.get() == pBox) + { + bool bEnable = ( pBox->get_active() == 0 ); + m_xOutlineBtn->set_sensitive( bEnable ); + m_xShadowBtn->set_sensitive( bEnable ); + } + else if (m_xPositionLB.get() != pBox) + { + bool bUEnable = false; + if (!m_bUnderlineColorDisabled) + { + auto nUPos = m_xUnderlineLB->get_active(); + bUEnable = nUPos > 0; + m_xUnderlineColorFT->set_sensitive(bUEnable); + m_xUnderlineColorLB->set_sensitive(bUEnable); + } + + auto nOPos = m_xOverlineLB->get_active(); + bool bOEnable = nOPos > 0; + m_xOverlineColorFT->set_sensitive(bOEnable); + m_xOverlineColorLB->set_sensitive(bOEnable); + + auto nSPos = m_xStrikeoutLB->get_active(); + m_xIndividualWordsBtn->set_sensitive( bUEnable || bOEnable || nSPos > 0); + } + UpdatePreview_Impl(); +} + +IMPL_LINK(SvxCharEffectsPage, CbClickHdl_Impl, weld::ToggleButton&, rToggle, void) +{ + m_aIndividualWordsState.ButtonToggled(rToggle); + UpdatePreview_Impl(); + UpdatePreview_Impl(); +} + +IMPL_LINK(SvxCharEffectsPage, ColorBoxSelectHdl_Impl, ColorListBox&, rBox, void) +{ + if (m_xFontColorLB.get() == &rBox) + m_bNewFontColor = true; + UpdatePreview_Impl(); +} + +IMPL_LINK_NOARG(SvxCharEffectsPage, ModifyFontTransparencyHdl_Impl, weld::MetricSpinButton&, void) +{ + m_bNewFontColor = true; +} + +DeactivateRC SvxCharEffectsPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if ( _pSet ) + FillItemSet( _pSet ); + return DeactivateRC::LeavePage; +} + +std::unique_ptr SvxCharEffectsPage::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet ) +{ + return std::make_unique( pPage, pController, *rSet ); +} + +void SvxCharEffectsPage::Reset( const SfxItemSet* rSet ) +{ + SvxFont& rFont = GetPreviewFont(); + SvxFont& rCJKFont = GetPreviewCJKFont(); + SvxFont& rCTLFont = GetPreviewCTLFont(); + + bool bEnable = false; + + // Underline + sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_UNDERLINE ); + rFont.SetUnderline( LINESTYLE_NONE ); + rCJKFont.SetUnderline( LINESTYLE_NONE ); + rCTLFont.SetUnderline( LINESTYLE_NONE ); + + m_xUnderlineLB->set_active( 0 ); + SfxItemState eState = rSet->GetItemState( nWhich ); + + if ( eState >= SfxItemState::DONTCARE ) + { + if ( eState == SfxItemState::DONTCARE ) + m_xUnderlineLB->set_active(-1); + else + { + const SvxUnderlineItem& rItem = static_cast(rSet->Get( nWhich )); + FontLineStyle eUnderline = rItem.GetValue(); + rFont.SetUnderline( eUnderline ); + rCJKFont.SetUnderline( eUnderline ); + rCTLFont.SetUnderline( eUnderline ); + + if ( eUnderline != LINESTYLE_NONE ) + { + auto nPos = m_xUnderlineLB->find_id(OUString::number(eUnderline)); + if (nPos != -1) + { + m_xUnderlineLB->set_active(nPos); + bEnable = true; + } + Color aColor = rItem.GetColor(); + m_xUnderlineColorLB->SelectEntry(aColor); + } + else + { + m_xUnderlineColorLB->SelectEntry(COL_AUTO); + m_xUnderlineColorLB->set_sensitive(false); + } + } + } + + // Overline + nWhich = GetWhich( SID_ATTR_CHAR_OVERLINE ); + rFont.SetOverline( LINESTYLE_NONE ); + rCJKFont.SetOverline( LINESTYLE_NONE ); + rCTLFont.SetOverline( LINESTYLE_NONE ); + + m_xOverlineLB->set_active( 0 ); + eState = rSet->GetItemState( nWhich ); + + if ( eState >= SfxItemState::DONTCARE ) + { + if ( eState == SfxItemState::DONTCARE ) + m_xOverlineLB->set_active(-1); + else + { + const SvxOverlineItem& rItem = static_cast(rSet->Get( nWhich )); + FontLineStyle eOverline = rItem.GetValue(); + rFont.SetOverline( eOverline ); + rCJKFont.SetOverline( eOverline ); + rCTLFont.SetOverline( eOverline ); + + if ( eOverline != LINESTYLE_NONE ) + { + auto nPos = m_xOverlineLB->find_id(OUString::number(eOverline)); + if (nPos != -1) + { + m_xOverlineLB->set_active(nPos); + bEnable = true; + } + Color aColor = rItem.GetColor(); + m_xOverlineColorLB->SelectEntry(aColor); + } + else + { + m_xOverlineColorLB->SelectEntry(COL_AUTO); + m_xOverlineColorLB->set_sensitive(false); + } + } + } + + // Strikeout + nWhich = GetWhich( SID_ATTR_CHAR_STRIKEOUT ); + rFont.SetStrikeout( STRIKEOUT_NONE ); + rCJKFont.SetStrikeout( STRIKEOUT_NONE ); + rCTLFont.SetStrikeout( STRIKEOUT_NONE ); + + m_xStrikeoutLB->set_active( 0 ); + eState = rSet->GetItemState( nWhich ); + + if ( eState >= SfxItemState::DONTCARE ) + { + if ( eState == SfxItemState::DONTCARE ) + m_xStrikeoutLB->set_active(-1); + else + { + const SvxCrossedOutItem& rItem = static_cast(rSet->Get( nWhich )); + FontStrikeout eStrikeout = rItem.GetValue(); + rFont.SetStrikeout( eStrikeout ); + rCJKFont.SetStrikeout( eStrikeout ); + rCTLFont.SetStrikeout( eStrikeout ); + + if ( eStrikeout != STRIKEOUT_NONE ) + { + auto nPos = m_xStrikeoutLB->find_id(OUString::number(eStrikeout)); + if (nPos != -1) + { + m_xStrikeoutLB->set_active(nPos); + bEnable = true; + } + } + } + } + + // WordLineMode + nWhich = GetWhich( SID_ATTR_CHAR_WORDLINEMODE ); + eState = rSet->GetItemState( nWhich ); + + switch ( eState ) + { + case SfxItemState::UNKNOWN: + m_aIndividualWordsState.bTriStateEnabled = false; + m_xIndividualWordsBtn->hide(); + break; + + case SfxItemState::DISABLED: + case SfxItemState::READONLY: + m_aIndividualWordsState.bTriStateEnabled = false; + m_xIndividualWordsBtn->set_sensitive(false); + break; + + case SfxItemState::DONTCARE: + m_aIndividualWordsState.bTriStateEnabled = true; + m_xIndividualWordsBtn->set_state( TRISTATE_INDET ); + break; + + case SfxItemState::DEFAULT: + case SfxItemState::SET: + { + const SvxWordLineModeItem& rItem = static_cast(rSet->Get( nWhich )); + rFont.SetWordLineMode( rItem.GetValue() ); + rCJKFont.SetWordLineMode( rItem.GetValue() ); + rCTLFont.SetWordLineMode( rItem.GetValue() ); + + m_aIndividualWordsState.bTriStateEnabled = false; + m_xIndividualWordsBtn->set_active(rItem.GetValue()); + m_xIndividualWordsBtn->set_sensitive(bEnable); + break; + } + } + + // Emphasis + nWhich = GetWhich( SID_ATTR_CHAR_EMPHASISMARK ); + eState = rSet->GetItemState( nWhich ); + + if ( eState >= SfxItemState::DEFAULT ) + { + const SvxEmphasisMarkItem& rItem = static_cast(rSet->Get( nWhich )); + FontEmphasisMark eMark = rItem.GetEmphasisMark(); + rFont.SetEmphasisMark( eMark ); + rCJKFont.SetEmphasisMark( eMark ); + rCTLFont.SetEmphasisMark( eMark ); + + m_xEmphasisLB->set_active( static_cast(FontEmphasisMark( eMark & FontEmphasisMark::Style )) ); + eMark &= ~FontEmphasisMark::Style; + int nEntryData = ( eMark == FontEmphasisMark::PosAbove ) + ? CHRDLG_POSITION_OVER + : ( eMark == FontEmphasisMark::PosBelow ) ? CHRDLG_POSITION_UNDER : 0; + + auto nPos = m_xPositionLB->find_id(OUString::number(nEntryData)); + if (nPos != -1) + m_xPositionLB->set_active(nPos); + } + else if ( eState == SfxItemState::DONTCARE ) + m_xEmphasisLB->set_active(-1); + else if ( eState == SfxItemState::UNKNOWN ) + { + m_xEmphasisFT->hide(); + m_xEmphasisLB->hide(); + } + else // SfxItemState::DISABLED or SfxItemState::READONLY + { + m_xEmphasisFT->set_sensitive(false); + m_xEmphasisLB->set_sensitive(false); + } + + // the select handler for the underline/overline/strikeout list boxes + SelectHdl_Impl(m_xUnderlineLB.get()); + + // the select handler for the emphasis listbox + SelectHdl_Impl(m_xEmphasisLB.get()); + + // Effects + SvxCaseMap eCaseMap = SvxCaseMap::End; + nWhich = GetWhich( SID_ATTR_CHAR_CASEMAP ); + eState = rSet->GetItemState( nWhich ); + switch ( eState ) + { + case SfxItemState::UNKNOWN: + m_xEffectsFT->hide(); + m_xEffectsLB->hide(); + break; + + case SfxItemState::DISABLED: + case SfxItemState::READONLY: + m_xEffectsFT->set_sensitive(false); + m_xEffectsLB->set_sensitive(false); + break; + + case SfxItemState::DONTCARE: + m_xEffectsLB->set_active(-1); + break; + + case SfxItemState::DEFAULT: + case SfxItemState::SET: + { + const SvxCaseMapItem& rItem = static_cast(rSet->Get( nWhich )); + eCaseMap = rItem.GetValue(); + break; + } + } + SetCaseMap_Impl( eCaseMap ); + + //Relief + nWhich = GetWhich(SID_ATTR_CHAR_RELIEF); + eState = rSet->GetItemState( nWhich ); + switch ( eState ) + { + case SfxItemState::UNKNOWN: + m_xReliefFT->hide(); + m_xReliefLB->hide(); + break; + + case SfxItemState::DISABLED: + case SfxItemState::READONLY: + m_xReliefFT->set_sensitive(false); + m_xReliefLB->set_sensitive(false); + break; + + case SfxItemState::DONTCARE: + m_xReliefLB->set_active(-1); + break; + + case SfxItemState::DEFAULT: + case SfxItemState::SET: + { + const SvxCharReliefItem& rItem = static_cast(rSet->Get( nWhich )); + m_xReliefLB->set_active(static_cast(rItem.GetValue())); + SelectHdl_Impl(m_xReliefLB.get()); + break; + } + } + + // Outline + nWhich = GetWhich( SID_ATTR_CHAR_CONTOUR ); + eState = rSet->GetItemState( nWhich ); + switch ( eState ) + { + case SfxItemState::UNKNOWN: + m_aOutlineState.bTriStateEnabled = false; + m_xOutlineBtn->hide(); + break; + + case SfxItemState::DISABLED: + case SfxItemState::READONLY: + m_aOutlineState.bTriStateEnabled = false; + m_xOutlineBtn->set_sensitive(false); + break; + + case SfxItemState::DONTCARE: + m_aOutlineState.bTriStateEnabled = true; + m_xOutlineBtn->set_state(TRISTATE_INDET); + break; + + case SfxItemState::DEFAULT: + case SfxItemState::SET: + { + const SvxContourItem& rItem = static_cast(rSet->Get( nWhich )); + m_aOutlineState.bTriStateEnabled = false; + m_xOutlineBtn->set_state(static_cast(rItem.GetValue())); + break; + } + } + + // Shadow + nWhich = GetWhich( SID_ATTR_CHAR_SHADOWED ); + eState = rSet->GetItemState( nWhich ); + + switch ( eState ) + { + case SfxItemState::UNKNOWN: + m_aShadowState.bTriStateEnabled = false; + m_xShadowBtn->hide(); + break; + + case SfxItemState::DISABLED: + case SfxItemState::READONLY: + m_aShadowState.bTriStateEnabled = false; + m_xShadowBtn->set_sensitive(false); + break; + + case SfxItemState::DONTCARE: + m_aShadowState.bTriStateEnabled = true; + m_xShadowBtn->set_state( TRISTATE_INDET ); + break; + + case SfxItemState::DEFAULT: + case SfxItemState::SET: + { + const SvxShadowedItem& rItem = static_cast(rSet->Get( nWhich )); + m_aShadowState.bTriStateEnabled = false; + m_xShadowBtn->set_state( static_cast(rItem.GetValue()) ); + break; + } + } + + // Hidden + nWhich = GetWhich( SID_ATTR_CHAR_HIDDEN ); + eState = rSet->GetItemState( nWhich ); + + switch ( eState ) + { + case SfxItemState::UNKNOWN: + m_aHiddenState.bTriStateEnabled = false; + m_xHiddenBtn->hide(); + break; + + case SfxItemState::DISABLED: + case SfxItemState::READONLY: + m_aHiddenState.bTriStateEnabled = false; + m_xHiddenBtn->set_sensitive(false); + break; + + case SfxItemState::DONTCARE: + m_aHiddenState.bTriStateEnabled = true; + m_xHiddenBtn->set_state(TRISTATE_INDET); + break; + + case SfxItemState::DEFAULT: + case SfxItemState::SET: + { + const SvxCharHiddenItem& rItem = static_cast(rSet->Get( nWhich )); + m_aHiddenState.bTriStateEnabled = false; + m_xHiddenBtn->set_state(static_cast(rItem.GetValue())); + break; + } + } + + SetPrevFontWidthScale( *rSet ); + ResetColor_Impl( *rSet ); + + // preview update + m_aPreviewWin.Invalidate(); + + // save this settings + ChangesApplied(); +} + +IMPL_LINK(SvxCharEffectsPage, HiddenBtnClickHdl, weld::ToggleButton&, rToggle, void) +{ + m_aHiddenState.ButtonToggled(rToggle); +} + +IMPL_LINK(SvxCharEffectsPage, OutlineBtnClickHdl, weld::ToggleButton&, rToggle, void) +{ + m_aOutlineState.ButtonToggled(rToggle); + UpdatePreview_Impl(); +} + +IMPL_LINK(SvxCharEffectsPage, ShadowBtnClickHdl, weld::ToggleButton&, rToggle, void) +{ + m_aShadowState.ButtonToggled(rToggle); + UpdatePreview_Impl(); +} + +void SvxCharEffectsPage::ChangesApplied() +{ + m_xUnderlineLB->save_value(); + m_xOverlineLB->save_value(); + m_xStrikeoutLB->save_value(); + m_xIndividualWordsBtn->save_state(); + m_xEmphasisLB->save_value(); + m_xPositionLB->save_value(); + m_xEffectsLB->save_value(); + m_xReliefLB->save_value(); + m_xOutlineBtn->save_state(); + m_xShadowBtn->save_state(); + m_xHiddenBtn->save_state(); + m_xFontTransparencyMtr->save_value(); +} + +bool SvxCharEffectsPage::FillItemSet( SfxItemSet* rSet ) +{ + const SfxPoolItem* pOld = nullptr; + const SfxItemSet& rOldSet = GetItemSet(); + bool bModified = false; + bool bChanged = true; + + // Underline + sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_UNDERLINE ); + pOld = GetOldItem( *rSet, SID_ATTR_CHAR_UNDERLINE ); + auto nPos = m_xUnderlineLB->get_active(); + FontLineStyle eUnder = static_cast(m_xUnderlineLB->get_active_id().toInt32()); + + if ( pOld ) + { + //! if there are different underline styles in the selection the + //! item-state in the 'rOldSet' will be invalid. In this case + //! changing the underline style will be allowed if a style is + //! selected in the listbox. + bool bAllowChg = nPos != -1 && + SfxItemState::DEFAULT > rOldSet.GetItemState( nWhich ); + + const SvxUnderlineItem& rItem = *static_cast(pOld); + if ( rItem.GetValue() == eUnder && + ( LINESTYLE_NONE == eUnder || rItem.GetColor() == m_xUnderlineColorLB->GetSelectEntryColor() ) && + ! bAllowChg ) + bChanged = false; + } + + if ( bChanged ) + { + SvxUnderlineItem aNewItem( eUnder, nWhich ); + aNewItem.SetColor( m_xUnderlineColorLB->GetSelectEntryColor() ); + rSet->Put( aNewItem ); + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet->InvalidateItem(nWhich); + + bChanged = true; + + // Overline + nWhich = GetWhich( SID_ATTR_CHAR_OVERLINE ); + pOld = GetOldItem( *rSet, SID_ATTR_CHAR_OVERLINE ); + nPos = m_xOverlineLB->get_active(); + FontLineStyle eOver = static_cast(m_xOverlineLB->get_active_id().toInt32()); + + if ( pOld ) + { + //! if there are different underline styles in the selection the + //! item-state in the 'rOldSet' will be invalid. In this case + //! changing the underline style will be allowed if a style is + //! selected in the listbox. + bool bAllowChg = nPos != -1 && + SfxItemState::DEFAULT > rOldSet.GetItemState( nWhich ); + + const SvxOverlineItem& rItem = *static_cast(pOld); + if ( rItem.GetValue() == eOver && + ( LINESTYLE_NONE == eOver || rItem.GetColor() == m_xOverlineColorLB->GetSelectEntryColor() ) && + ! bAllowChg ) + bChanged = false; + } + + if ( bChanged ) + { + SvxOverlineItem aNewItem( eOver, nWhich ); + aNewItem.SetColor( m_xOverlineColorLB->GetSelectEntryColor() ); + rSet->Put( aNewItem ); + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet->InvalidateItem(nWhich); + + bChanged = true; + + // Strikeout + nWhich = GetWhich( SID_ATTR_CHAR_STRIKEOUT ); + pOld = GetOldItem( *rSet, SID_ATTR_CHAR_STRIKEOUT ); + nPos = m_xStrikeoutLB->get_active(); + FontStrikeout eStrike = static_cast(m_xStrikeoutLB->get_active_id().toInt32()); + + if ( pOld ) + { + //! if there are different strikeout styles in the selection the + //! item-state in the 'rOldSet' will be invalid. In this case + //! changing the strikeout style will be allowed if a style is + //! selected in the listbox. + bool bAllowChg = nPos != -1 && + SfxItemState::DEFAULT > rOldSet.GetItemState( nWhich ); + + const SvxCrossedOutItem& rItem = *static_cast(pOld); + if ( !m_xStrikeoutLB->get_sensitive() + || (rItem.GetValue() == eStrike && !bAllowChg) ) + bChanged = false; + } + + if ( bChanged ) + { + rSet->Put( SvxCrossedOutItem( eStrike, nWhich ) ); + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet->InvalidateItem(nWhich); + + bChanged = true; + + // Individual words + const SfxItemSet* pExampleSet = GetDialogExampleSet(); + nWhich = GetWhich( SID_ATTR_CHAR_WORDLINEMODE ); + pOld = GetOldItem( *rSet, SID_ATTR_CHAR_WORDLINEMODE ); + TriState eState = m_xIndividualWordsBtn->get_state(); + const SfxPoolItem* pItem; + + if ( pOld ) + { + const SvxWordLineModeItem& rItem = *static_cast(pOld); + if ( rItem.GetValue() == StateToAttr( eState ) && m_xIndividualWordsBtn->get_saved_state() == eState ) + bChanged = false; + } + + if ( !bChanged && pExampleSet && pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET && + !StateToAttr( eState ) && static_cast(pItem)->GetValue() ) + bChanged = true; + + if ( bChanged && eState != TRISTATE_INDET ) + { + rSet->Put( SvxWordLineModeItem( StateToAttr( eState ), nWhich ) ); + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet->InvalidateItem(nWhich); + + bChanged = true; + + // Emphasis + nWhich = GetWhich( SID_ATTR_CHAR_EMPHASISMARK ); + pOld = GetOldItem( *rSet, SID_ATTR_CHAR_EMPHASISMARK ); + int nMarkPos = m_xEmphasisLB->get_active(); + OUString sMarkPos = m_xEmphasisLB->get_active_text(); + OUString sPosPos = m_xPositionLB->get_active_text(); + FontEmphasisMark eMark = static_cast(nMarkPos); + if (m_xPositionLB->get_sensitive()) + { + eMark |= (CHRDLG_POSITION_UNDER == m_xPositionLB->get_active_id().toInt32()) + ? FontEmphasisMark::PosBelow : FontEmphasisMark::PosAbove; + } + + if ( pOld ) + { + if( rOldSet.GetItemState( nWhich ) != SfxItemState::DONTCARE ) + { + const SvxEmphasisMarkItem& rItem = *static_cast(pOld); + if ( rItem.GetEmphasisMark() == eMark ) + bChanged = false; + } + } + + if (rOldSet.GetItemState( nWhich ) == SfxItemState::DONTCARE && + m_xEmphasisLB->get_saved_value() == sMarkPos && m_xPositionLB->get_saved_value() == sPosPos) + { + bChanged = false; + } + + if (bChanged) + { + rSet->Put( SvxEmphasisMarkItem( eMark, nWhich ) ); + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet->InvalidateItem(nWhich); + + bChanged = true; + + // Effects + nWhich = GetWhich( SID_ATTR_CHAR_CASEMAP ); + pOld = GetOldItem( *rSet, SID_ATTR_CHAR_CASEMAP ); + SvxCaseMap eCaseMap = SvxCaseMap::NotMapped; + bool bChecked = false; + auto nCapsPos = m_xEffectsLB->get_active(); + if (nCapsPos != -1) + { + eCaseMap = static_cast(nCapsPos); + bChecked = true; + } + + if ( pOld ) + { + //! if there are different effect styles in the selection the + //! item-state in the 'rOldSet' will be invalid. In this case + //! changing the effect style will be allowed if a style is + //! selected in the listbox. + bool bAllowChg = nPos != -1 && + SfxItemState::DEFAULT > rOldSet.GetItemState( nWhich ); + + const SvxCaseMapItem& rItem = *static_cast(pOld); + if ( rItem.GetValue() == eCaseMap && !bAllowChg ) + bChanged = false; + } + + if ( bChanged && bChecked ) + { + rSet->Put( SvxCaseMapItem( eCaseMap, nWhich ) ); + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet->InvalidateItem(nWhich); + + bChanged = true; + + //Relief + nWhich = GetWhich(SID_ATTR_CHAR_RELIEF); + if (m_xReliefLB->get_value_changed_from_saved()) + { + m_xReliefLB->save_value(); + SvxCharReliefItem aRelief(static_cast(m_xReliefLB->get_active()), nWhich); + rSet->Put(aRelief); + } + + // Outline + nWhich = GetWhich( SID_ATTR_CHAR_CONTOUR ); + pOld = GetOldItem( *rSet, SID_ATTR_CHAR_CONTOUR ); + eState = m_xOutlineBtn->get_state(); + + if ( pOld ) + { + const SvxContourItem& rItem = *static_cast(pOld); + if ( rItem.GetValue() == StateToAttr( eState ) && m_xOutlineBtn->get_saved_state() == eState ) + bChanged = false; + } + + if ( !bChanged && pExampleSet && pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET && + !StateToAttr( eState ) && static_cast(pItem)->GetValue() ) + bChanged = true; + + if ( bChanged && eState != TRISTATE_INDET ) + { + rSet->Put( SvxContourItem( StateToAttr( eState ), nWhich ) ); + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet->InvalidateItem(nWhich); + + bChanged = true; + + // Shadow + nWhich = GetWhich( SID_ATTR_CHAR_SHADOWED ); + pOld = GetOldItem( *rSet, SID_ATTR_CHAR_SHADOWED ); + eState = m_xShadowBtn->get_state(); + + if ( pOld ) + { + const SvxShadowedItem& rItem = *static_cast(pOld); + if ( rItem.GetValue() == StateToAttr( eState ) && m_xShadowBtn->get_saved_state() == eState ) + bChanged = false; + } + + if ( !bChanged && pExampleSet && pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET && + !StateToAttr( eState ) && static_cast(pItem)->GetValue() ) + bChanged = true; + + if ( bChanged && eState != TRISTATE_INDET ) + { + rSet->Put( SvxShadowedItem( StateToAttr( eState ), nWhich ) ); + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet->InvalidateItem(nWhich); + + bChanged = true; + + // Hidden + nWhich = GetWhich( SID_ATTR_CHAR_HIDDEN ); + pOld = GetOldItem( *rSet, SID_ATTR_CHAR_HIDDEN ); + eState = m_xHiddenBtn->get_state(); + bChanged = true; + + if ( pOld ) + { + const SvxCharHiddenItem& rItem = *static_cast(pOld); + if ( rItem.GetValue() == StateToAttr( eState ) && m_xHiddenBtn->get_saved_state() == eState ) + bChanged = false; + } + + if ( !bChanged && pExampleSet && pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET && + !StateToAttr( eState ) && static_cast(pItem)->GetValue() ) + bChanged = true; + + if ( bChanged && eState != TRISTATE_INDET ) + { + rSet->Put( SvxCharHiddenItem( StateToAttr( eState ), nWhich ) ); + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet->InvalidateItem(nWhich); + + bModified |= FillItemSetColor_Impl( *rSet ); + + return bModified; +} + +void SvxCharEffectsPage::DisableControls( sal_uInt16 nDisable ) +{ + if ( ( DISABLE_CASEMAP & nDisable ) == DISABLE_CASEMAP ) + { + m_xEffectsFT->set_sensitive(false); + m_xEffectsLB->set_sensitive(false); + } + + if ( ( DISABLE_WORDLINE & nDisable ) == DISABLE_WORDLINE ) + m_xIndividualWordsBtn->set_sensitive(false); + + if ( ( DISABLE_UNDERLINE_COLOR & nDisable ) == DISABLE_UNDERLINE_COLOR ) + { + // disable the controls + m_xUnderlineColorFT->set_sensitive(false); + m_xUnderlineColorLB->set_sensitive(false); + m_bUnderlineColorDisabled = true; + } +} + +void SvxCharEffectsPage::PageCreated(const SfxAllItemSet& aSet) +{ + const SfxUInt16Item* pDisableCtlItem = aSet.GetItem(SID_DISABLE_CTL, false); + const SfxUInt32Item* pFlagItem = aSet.GetItem(SID_FLAG_TYPE, false); + if (pDisableCtlItem) + DisableControls(pDisableCtlItem->GetValue()); + + if (!pFlagItem) + return; + + sal_uInt32 nFlags=pFlagItem->GetValue(); + if ( ( nFlags & SVX_PREVIEW_CHARACTER ) == SVX_PREVIEW_CHARACTER ) + // the writer uses SID_ATTR_BRUSH as font background + m_bPreviewBackgroundToCharacter = true; + if ((nFlags & SVX_ENABLE_CHAR_TRANSPARENCY) != SVX_ENABLE_CHAR_TRANSPARENCY) + { + // Only show these in case client code explicitly wants this. + m_xFontTransparencyFT->hide(); + m_xFontTransparencyMtr->hide(); + } +} + +// class SvxCharPositionPage --------------------------------------------- + +SvxCharPositionPage::SvxCharPositionPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInSet) + : SvxCharBasePage(pPage, pController, "cui/ui/positionpage.ui", "PositionPage", rInSet) + , m_nSuperEsc(short(DFLT_ESC_SUPER)) + , m_nSubEsc(short(DFLT_ESC_SUB)) + , m_nScaleWidthItemSetVal(100) + , m_nScaleWidthInitialVal(100) + , m_nSuperProp(sal_uInt8(DFLT_ESC_PROP)) + , m_nSubProp(sal_uInt8(DFLT_ESC_PROP)) + , m_xHighPosBtn(m_xBuilder->weld_radio_button("superscript")) + , m_xNormalPosBtn(m_xBuilder->weld_radio_button("normal")) + , m_xLowPosBtn(m_xBuilder->weld_radio_button("subscript")) + , m_xHighLowFT(m_xBuilder->weld_label("raiselower")) + , m_xHighLowMF(m_xBuilder->weld_metric_spin_button("raiselowersb", FieldUnit::PERCENT)) + , m_xHighLowRB(m_xBuilder->weld_check_button("automatic")) + , m_xFontSizeFT(m_xBuilder->weld_label("relativefontsize")) + , m_xFontSizeMF(m_xBuilder->weld_metric_spin_button("fontsizesb", FieldUnit::PERCENT)) + , m_xRotationContainer(m_xBuilder->weld_widget("rotationcontainer")) + , m_xScalingFT(m_xBuilder->weld_label("scale")) + , m_xScalingAndRotationFT(m_xBuilder->weld_label("rotateandscale")) + , m_x0degRB(m_xBuilder->weld_radio_button("0deg")) + , m_x90degRB(m_xBuilder->weld_radio_button("90deg")) + , m_x270degRB(m_xBuilder->weld_radio_button("270deg")) + , m_xFitToLineCB(m_xBuilder->weld_check_button("fittoline")) + , m_xScaleWidthMF(m_xBuilder->weld_metric_spin_button("scalewidthsb", FieldUnit::PERCENT)) + , m_xKerningMF(m_xBuilder->weld_metric_spin_button("kerningsb", FieldUnit::POINT)) + , m_xPairKerningBtn(m_xBuilder->weld_check_button("pairkerning")) +{ + m_xPreviewWin.reset(new weld::CustomWeld(*m_xBuilder, "preview", m_aPreviewWin)); +#ifdef IOS + m_xPreviewWin->hide(); +#endif + Initialize(); +} + +SvxCharPositionPage::~SvxCharPositionPage() +{ +} + + +void SvxCharPositionPage::Initialize() +{ + // to handle the changes of the other pages + SetExchangeSupport(); + + GetPreviewFont().SetFontSize( Size( 0, 240 ) ); + GetPreviewCJKFont().SetFontSize( Size( 0, 240 ) ); + GetPreviewCTLFont().SetFontSize( Size( 0, 240 ) ); + + m_xNormalPosBtn->set_active(true); + PositionHdl_Impl(*m_xNormalPosBtn); + + Link aLink2 = LINK(this, SvxCharPositionPage, PositionHdl_Impl); + m_xHighPosBtn->connect_toggled(aLink2); + m_xNormalPosBtn->connect_toggled(aLink2); + m_xLowPosBtn->connect_toggled(aLink2); + + aLink2 = LINK( this, SvxCharPositionPage, RotationHdl_Impl ); + m_x0degRB->connect_toggled(aLink2); + m_x90degRB->connect_toggled(aLink2); + m_x270degRB->connect_toggled(aLink2); + + Link aLink3 = LINK(this, SvxCharPositionPage, ValueChangedHdl_Impl); + m_xHighLowMF->connect_value_changed(aLink3); + m_xFontSizeMF->connect_value_changed(aLink3); + + m_xHighLowRB->connect_toggled(LINK(this, SvxCharPositionPage, AutoPositionHdl_Impl)); + m_xFitToLineCB->connect_toggled(LINK(this, SvxCharPositionPage, FitToLineHdl_Impl)); + m_xKerningMF->connect_value_changed(LINK(this, SvxCharPositionPage, KerningModifyHdl_Impl)); + m_xScaleWidthMF->connect_value_changed(LINK(this, SvxCharPositionPage, ScaleWidthModifyHdl_Impl)); +} + +void SvxCharPositionPage::UpdatePreview_Impl( sal_uInt8 nProp, sal_uInt8 nEscProp, short nEsc ) +{ + SetPrevFontEscapement( nProp, nEscProp, nEsc ); +} + + +void SvxCharPositionPage::SetEscapement_Impl( SvxEscapement nEsc ) +{ + SvxEscapementItem aEscItm( nEsc, SID_ATTR_CHAR_ESCAPEMENT ); + + if ( SvxEscapement::Superscript == nEsc ) + { + aEscItm.GetEsc() = m_nSuperEsc; + aEscItm.GetProportionalHeight() = m_nSuperProp; + } + else if ( SvxEscapement::Subscript == nEsc ) + { + aEscItm.GetEsc() = m_nSubEsc; + aEscItm.GetProportionalHeight() = m_nSubProp; + } + + short nFac = aEscItm.GetEsc() < 0 ? -1 : 1; + + m_xHighLowMF->set_value(aEscItm.GetEsc() * nFac, FieldUnit::PERCENT); + m_xFontSizeMF->set_value(aEscItm.GetProportionalHeight(), FieldUnit::PERCENT); + + if ( SvxEscapement::Off == nEsc ) + { + m_xHighLowFT->set_sensitive(false); + m_xHighLowMF->set_sensitive(false); + m_xFontSizeFT->set_sensitive(false); + m_xFontSizeMF->set_sensitive(false); + m_xHighLowRB->set_sensitive(false); + } + else + { + m_xFontSizeFT->set_sensitive(true); + m_xFontSizeMF->set_sensitive(true); + m_xHighLowRB->set_sensitive(true); + + if (!m_xHighLowRB->get_active()) + { + m_xHighLowFT->set_sensitive(true); + m_xHighLowMF->set_sensitive(true); + } + else + AutoPositionHdl_Impl(*m_xHighLowRB); + } + + UpdatePreview_Impl( 100, aEscItm.GetProportionalHeight(), aEscItm.GetEsc() ); +} + + +IMPL_LINK_NOARG(SvxCharPositionPage, PositionHdl_Impl, weld::ToggleButton&, void) +{ + SvxEscapement nEsc = SvxEscapement::Off; // also when pBtn == NULL + + if (m_xHighPosBtn->get_active()) + nEsc = SvxEscapement::Superscript; + else if (m_xLowPosBtn->get_active()) + nEsc = SvxEscapement::Subscript; + + SetEscapement_Impl( nEsc ); +} + +IMPL_LINK_NOARG(SvxCharPositionPage, RotationHdl_Impl, weld::ToggleButton&, void) +{ + bool bEnable = false; + if (m_x90degRB->get_active() || m_x270degRB->get_active()) + bEnable = true; + else + OSL_ENSURE(m_x0degRB->get_active(), "unexpected button"); + m_xFitToLineCB->set_sensitive(bEnable); +} + +void SvxCharPositionPage::FontModifyHdl_Impl() +{ + sal_uInt8 nEscProp = static_cast(m_xFontSizeMF->get_value(FieldUnit::PERCENT)); + short nEsc = static_cast(m_xHighLowMF->get_value(FieldUnit::PERCENT)); + nEsc *= m_xLowPosBtn->get_active() ? -1 : 1; + UpdatePreview_Impl( 100, nEscProp, nEsc ); +} + +IMPL_LINK(SvxCharPositionPage, AutoPositionHdl_Impl, weld::ToggleButton&, rBox, void) +{ + if (rBox.get_active()) + { + m_xHighLowFT->set_sensitive(false); + m_xHighLowMF->set_sensitive(false); + } + else + PositionHdl_Impl(m_xHighPosBtn->get_active() ? *m_xHighPosBtn + : m_xLowPosBtn->get_active() ? *m_xLowPosBtn + : *m_xNormalPosBtn); +} + +IMPL_LINK_NOARG(SvxCharPositionPage, FitToLineHdl_Impl, weld::ToggleButton&, void) +{ + sal_uInt16 nVal = m_nScaleWidthInitialVal; + if (m_xFitToLineCB->get_active()) + nVal = m_nScaleWidthItemSetVal; + m_xScaleWidthMF->set_value(nVal, FieldUnit::PERCENT); + m_aPreviewWin.SetFontWidthScale( nVal ); +} + +IMPL_LINK_NOARG(SvxCharPositionPage, KerningModifyHdl_Impl, weld::MetricSpinButton&, void) +{ + long nVal = static_cast(m_xKerningMF->get_value(FieldUnit::POINT)); + nVal = OutputDevice::LogicToLogic( nVal, MapUnit::MapPoint, MapUnit::MapTwip ); + long nKern = static_cast(m_xKerningMF->denormalize(nVal)); + + SvxFont& rFont = GetPreviewFont(); + SvxFont& rCJKFont = GetPreviewCJKFont(); + SvxFont& rCTLFont = GetPreviewCTLFont(); + + rFont.SetFixKerning( static_cast(nKern) ); + rCJKFont.SetFixKerning( static_cast(nKern) ); + rCTLFont.SetFixKerning( static_cast(nKern) ); + m_aPreviewWin.Invalidate(); +} + +IMPL_LINK(SvxCharPositionPage, ValueChangedHdl_Impl, weld::MetricSpinButton&, rField, void) +{ + bool bHigh = m_xHighPosBtn->get_active(); + bool bLow = m_xLowPosBtn->get_active(); + DBG_ASSERT( bHigh || bLow, "normal position is not valid" ); + + if (m_xHighLowMF.get() == &rField) + { + if ( bLow ) + m_nSubEsc = static_cast(m_xHighLowMF->get_value(FieldUnit::PERCENT)) * -1; + else + m_nSuperEsc = static_cast(m_xHighLowMF->get_value(FieldUnit::PERCENT)); + } + else if (m_xFontSizeMF.get() == &rField) + { + if ( bLow ) + m_nSubProp = static_cast(m_xFontSizeMF->get_value(FieldUnit::PERCENT)); + else + m_nSuperProp = static_cast(m_xFontSizeMF->get_value(FieldUnit::PERCENT)); + } + + FontModifyHdl_Impl(); +} + +IMPL_LINK_NOARG(SvxCharPositionPage, ScaleWidthModifyHdl_Impl, weld::MetricSpinButton&, void) +{ + m_aPreviewWin.SetFontWidthScale(sal_uInt16(m_xScaleWidthMF->get_value(FieldUnit::PERCENT))); +} + +DeactivateRC SvxCharPositionPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if ( _pSet ) + FillItemSet( _pSet ); + return DeactivateRC::LeavePage; +} + +std::unique_ptr SvxCharPositionPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet) +{ + return std::make_unique(pPage, pController, *rSet); +} + +void SvxCharPositionPage::Reset( const SfxItemSet* rSet ) +{ + OUString sUser = GetUserData(); + + if ( !sUser.isEmpty() ) + { + sal_Int32 nIdx {0}; + m_nSuperEsc = static_cast(sUser.getToken( 0, ';', nIdx ).toInt32()); + m_nSubEsc = static_cast(sUser.getToken( 0, ';', nIdx ).toInt32()); + m_nSuperProp = static_cast(sUser.getToken( 0, ';', nIdx ).toInt32()); + m_nSubProp = static_cast(sUser.getToken( 0, ';', nIdx ).toInt32()); + + m_xHighLowMF->set_max(MAX_ESC_POS, FieldUnit::PERCENT); + + //fdo#75307 validate all the entries and discard all of them if any are + //out of range + bool bValid = true; + if (m_nSuperEsc < m_xHighLowMF->get_min(FieldUnit::PERCENT) || m_nSuperEsc > m_xHighLowMF->get_max(FieldUnit::PERCENT)) + bValid = false; + if (m_nSubEsc*-1 < m_xHighLowMF->get_min(FieldUnit::PERCENT) || m_nSubEsc*-1 > m_xHighLowMF->get_max(FieldUnit::PERCENT)) + bValid = false; + if (m_nSuperProp < m_xFontSizeMF->get_min(FieldUnit::PERCENT) || m_nSuperProp > m_xFontSizeMF->get_max(FieldUnit::PERCENT)) + bValid = false; + if (m_nSubProp < m_xFontSizeMF->get_min(FieldUnit::PERCENT) || m_nSubProp > m_xFontSizeMF->get_max(FieldUnit::PERCENT)) + bValid = false; + + if (!bValid) + { + m_nSuperEsc = DFLT_ESC_SUPER; + m_nSubEsc = DFLT_ESC_SUB; + m_nSuperProp = DFLT_ESC_PROP; + m_nSubProp = DFLT_ESC_PROP; + } + } + + short nEsc = 0; + sal_uInt8 nEscProp = 100; + + m_xHighLowFT->set_sensitive(false); + m_xHighLowMF->set_sensitive(false); + m_xFontSizeFT->set_sensitive(false); + m_xFontSizeMF->set_sensitive(false); + + SvxFont& rFont = GetPreviewFont(); + SvxFont& rCJKFont = GetPreviewCJKFont(); + SvxFont& rCTLFont = GetPreviewCTLFont(); + sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_ESCAPEMENT ); + + if ( rSet->GetItemState( nWhich ) >= SfxItemState::DEFAULT ) + { + const SvxEscapementItem& rItem = static_cast(rSet->Get( nWhich )); + nEsc = rItem.GetEsc(); + nEscProp = rItem.GetProportionalHeight(); + + if ( nEsc != 0 ) + { + m_xHighLowFT->set_sensitive(true); + m_xHighLowMF->set_sensitive(true); + m_xFontSizeFT->set_sensitive(true); + m_xFontSizeMF->set_sensitive(true); + + short nFac; + bool bAutomatic(false); + + if ( nEsc > 0 ) + { + nFac = 1; + m_xHighPosBtn->set_active(true); + if ( nEsc == DFLT_ESC_AUTO_SUPER ) + { + nEsc = DFLT_ESC_SUPER; + bAutomatic = true; + } + } + else + { + nFac = -1; + m_xLowPosBtn->set_active(true); + if ( nEsc == DFLT_ESC_AUTO_SUB ) + { + nEsc = DFLT_ESC_SUB; + bAutomatic = true; + } + } + if (!m_xHighLowRB->get_sensitive()) + { + m_xHighLowRB->set_sensitive(true); + } + m_xHighLowRB->set_active(bAutomatic); + + if (m_xHighLowRB->get_active()) + { + m_xHighLowFT->set_sensitive(false); + m_xHighLowMF->set_sensitive(false); + } + m_xHighLowMF->set_value(m_xHighLowMF->normalize(nFac * nEsc), FieldUnit::PERCENT); + } + else + { + m_xNormalPosBtn->set_active(true); + m_xHighLowRB->set_active(true); + PositionHdl_Impl(*m_xNormalPosBtn); + } + //the height has to be set after the handler is called to keep the value also if the escapement is zero + m_xFontSizeMF->set_value(m_xFontSizeMF->normalize(nEscProp), FieldUnit::PERCENT); + } + else + { + m_xHighPosBtn->set_active(false); + m_xNormalPosBtn->set_active(false); + m_xLowPosBtn->set_active(false); + } + + // set BspFont + SetPrevFontEscapement( 100, nEscProp, nEsc ); + + // Kerning + nWhich = GetWhich( SID_ATTR_CHAR_KERNING ); + + if ( rSet->GetItemState( nWhich ) >= SfxItemState::DEFAULT ) + { + const SvxKerningItem& rItem = static_cast(rSet->Get( nWhich )); + MapUnit eUnit = rSet->GetPool()->GetMetric( nWhich ); + long nBig = static_cast(m_xKerningMF->normalize( static_cast(rItem.GetValue()) )); + long nKerning = OutputDevice::LogicToLogic(nBig, eUnit, MapUnit::MapPoint); + + // set Kerning at the Font, convert into Twips before + long nKern = OutputDevice::LogicToLogic(rItem.GetValue(), eUnit, MapUnit::MapTwip); + rFont.SetFixKerning( static_cast(nKern) ); + rCJKFont.SetFixKerning( static_cast(nKern) ); + rCTLFont.SetFixKerning( static_cast(nKern) ); + + //the attribute value must be displayed also if it's above the maximum allowed value + long nVal = static_cast(m_xKerningMF->get_max(FieldUnit::POINT)); + if(nVal < nKerning) + m_xKerningMF->set_max(nKerning, FieldUnit::POINT); + m_xKerningMF->set_value(nKerning, FieldUnit::POINT); + } + else + m_xKerningMF->set_text(OUString()); + + // Pair kerning + nWhich = GetWhich( SID_ATTR_CHAR_AUTOKERN ); + + if ( rSet->GetItemState( nWhich ) >= SfxItemState::DEFAULT ) + { + const SvxAutoKernItem& rItem = static_cast(rSet->Get( nWhich )); + m_xPairKerningBtn->set_active(rItem.GetValue()); + } + else + m_xPairKerningBtn->set_active(false); + + // Scale Width + nWhich = GetWhich( SID_ATTR_CHAR_SCALEWIDTH ); + if ( rSet->GetItemState( nWhich ) >= SfxItemState::DEFAULT ) + { + const SvxCharScaleWidthItem& rItem = static_cast( rSet->Get( nWhich ) ); + m_nScaleWidthInitialVal = rItem.GetValue(); + m_xScaleWidthMF->set_value(m_nScaleWidthInitialVal, FieldUnit::PERCENT); + } + else + m_xScaleWidthMF->set_value(100, FieldUnit::PERCENT); + + nWhich = GetWhich( SID_ATTR_CHAR_WIDTH_FIT_TO_LINE ); + if ( rSet->GetItemState( nWhich ) >= SfxItemState::DEFAULT ) + m_nScaleWidthItemSetVal = static_cast( rSet->Get( nWhich )).GetValue(); + + // Rotation + nWhich = GetWhich( SID_ATTR_CHAR_ROTATED ); + SfxItemState eState = rSet->GetItemState( nWhich ); + if( SfxItemState::UNKNOWN == eState ) + { + m_xRotationContainer->hide(); + m_xScalingAndRotationFT->hide(); + m_xScalingFT->show(); + } + else + { + m_xRotationContainer->show(); + m_xScalingAndRotationFT->show(); + m_xScalingFT->hide(); + + if( eState >= SfxItemState::DEFAULT ) + { + const SvxCharRotateItem& rItem = + static_cast( rSet->Get( nWhich )); + if (rItem.IsBottomToTop()) + m_x90degRB->set_active(true); + else if (rItem.IsTopToBottom()) + m_x270degRB->set_active(true); + else + { + DBG_ASSERT( 0 == rItem.GetValue(), "incorrect value" ); + m_x0degRB->set_active(true); + } + m_xFitToLineCB->set_active(rItem.IsFitToLine()); + } + else + { + if( eState == SfxItemState::DONTCARE ) + { + m_x0degRB->set_active(false); + m_x90degRB->set_active(false); + m_x270degRB->set_active(false); + } + else + m_x0degRB->set_active(true); + + m_xFitToLineCB->set_active(false); + } + m_xFitToLineCB->set_sensitive(!m_x0degRB->get_active()); + + // is this value set? + if( SfxItemState::UNKNOWN == rSet->GetItemState( GetWhich( + SID_ATTR_CHAR_WIDTH_FIT_TO_LINE ) )) + m_xFitToLineCB->hide(); + } + ChangesApplied(); +} + +void SvxCharPositionPage::ChangesApplied() +{ + m_xHighPosBtn->save_state(); + m_xNormalPosBtn->save_state(); + m_xLowPosBtn->save_state(); + m_xHighLowRB->save_state(); + m_x0degRB->save_state(); + m_x90degRB->save_state(); + m_x270degRB->save_state(); + m_xFitToLineCB->save_state(); + m_xScaleWidthMF->save_value(); + m_xKerningMF->save_value(); + m_xPairKerningBtn->save_state(); +} + +bool SvxCharPositionPage::FillItemSet( SfxItemSet* rSet ) +{ + // Position (high, normal or low) + const SfxItemSet& rOldSet = GetItemSet(); + bool bModified = false, bChanged = true; + sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_ESCAPEMENT ); + const SfxPoolItem* pOld = GetOldItem( *rSet, SID_ATTR_CHAR_ESCAPEMENT ); + const bool bHigh = m_xHighPosBtn->get_active(); + short nEsc; + sal_uInt8 nEscProp; + + if (bHigh || m_xLowPosBtn->get_active()) + { + if (m_xHighLowRB->get_active()) + nEsc = bHigh ? DFLT_ESC_AUTO_SUPER : DFLT_ESC_AUTO_SUB; + else + { + nEsc = static_cast(m_xHighLowMF->denormalize(m_xHighLowMF->get_value(FieldUnit::PERCENT))); + nEsc *= (bHigh ? 1 : -1); + } + nEscProp = static_cast(m_xFontSizeMF->denormalize(m_xFontSizeMF->get_value(FieldUnit::PERCENT))); + } + else + { + nEsc = 0; + nEscProp = 100; + } + + if ( pOld ) + { + const SvxEscapementItem& rItem = *static_cast(pOld); + if (rItem.GetEsc() == nEsc && rItem.GetProportionalHeight() == nEscProp) + bChanged = false; + } + + if ( !bChanged && !m_xHighPosBtn->get_saved_state() && + !m_xNormalPosBtn->get_saved_state() && !m_xLowPosBtn->get_saved_state() ) + bChanged = true; + + if ( bChanged && + ( m_xHighPosBtn->get_active() || m_xNormalPosBtn->get_active() || m_xLowPosBtn->get_active() ) ) + { + rSet->Put( SvxEscapementItem( nEsc, nEscProp, nWhich ) ); + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet->InvalidateItem(nWhich); + + bChanged = true; + + // Kerning + nWhich = GetWhich( SID_ATTR_CHAR_KERNING ); + pOld = GetOldItem( *rSet, SID_ATTR_CHAR_KERNING ); + short nKerning = 0; + MapUnit eUnit = rSet->GetPool()->GetMetric( nWhich ); + + long nTmp = static_cast(m_xKerningMF->get_value(FieldUnit::POINT)); + long nVal = OutputDevice::LogicToLogic(nTmp, MapUnit::MapPoint, eUnit); + nKerning = static_cast(m_xKerningMF->denormalize( nVal )); + + SfxItemState eOldKernState = rOldSet.GetItemState( nWhich, false ); + if ( pOld ) + { + const SvxKerningItem& rItem = *static_cast(pOld); + if ( (eOldKernState >= SfxItemState::DEFAULT || m_xKerningMF->get_text().isEmpty()) && rItem.GetValue() == nKerning ) + bChanged = false; + } + + if ( bChanged ) + { + rSet->Put( SvxKerningItem( nKerning, nWhich ) ); + bModified = true; + } + else if ( SfxItemState::DEFAULT == eOldKernState ) + rSet->InvalidateItem(nWhich); + + // Pair-Kerning + nWhich = GetWhich( SID_ATTR_CHAR_AUTOKERN ); + + if (m_xPairKerningBtn->get_state_changed_from_saved()) + { + rSet->Put( SvxAutoKernItem( m_xPairKerningBtn->get_active(), nWhich ) ); + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet->InvalidateItem(nWhich); + + // Scale Width + nWhich = GetWhich( SID_ATTR_CHAR_SCALEWIDTH ); + if (m_xScaleWidthMF->get_value_changed_from_saved()) + { + rSet->Put(SvxCharScaleWidthItem(static_cast(m_xScaleWidthMF->get_value(FieldUnit::PERCENT)), nWhich)); + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet->InvalidateItem(nWhich); + + // Rotation + nWhich = GetWhich( SID_ATTR_CHAR_ROTATED ); + if ( m_x0degRB->get_state_changed_from_saved() || + m_x90degRB->get_state_changed_from_saved() || + m_x270degRB->get_state_changed_from_saved() || + m_xFitToLineCB->get_state_changed_from_saved() ) + { + SvxCharRotateItem aItem( 0, m_xFitToLineCB->get_active(), nWhich ); + if (m_x90degRB->get_active()) + aItem.SetBottomToTop(); + else if (m_x270degRB->get_active()) + aItem.SetTopToBottom(); + rSet->Put( aItem ); + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet->InvalidateItem(nWhich); + + return bModified; +} + + +void SvxCharPositionPage::FillUserData() +{ + const OUString cTok( ";" ); + + OUString sUser = OUString::number( m_nSuperEsc ) + cTok + + OUString::number( m_nSubEsc ) + cTok + + OUString::number( m_nSuperProp ) + cTok + + OUString::number( m_nSubProp ); + SetUserData( sUser ); +} + + +void SvxCharPositionPage::PageCreated(const SfxAllItemSet& aSet) +{ + const SfxUInt32Item* pFlagItem = aSet.GetItem(SID_FLAG_TYPE, false); + if (pFlagItem) + { + sal_uInt32 nFlags=pFlagItem->GetValue(); + if ( ( nFlags & SVX_PREVIEW_CHARACTER ) == SVX_PREVIEW_CHARACTER ) + // the writer uses SID_ATTR_BRUSH as font background + m_bPreviewBackgroundToCharacter = true; + } +} +// class SvxCharTwoLinesPage ------------------------------------------------ + +SvxCharTwoLinesPage::SvxCharTwoLinesPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInSet) + : SvxCharBasePage(pPage, pController, "cui/ui/twolinespage.ui", "TwoLinesPage", rInSet) + , m_nStartBracketPosition( 0 ) + , m_nEndBracketPosition( 0 ) + , m_xTwoLinesBtn(m_xBuilder->weld_check_button("twolines")) + , m_xEnclosingFrame(m_xBuilder->weld_widget("enclosing")) + , m_xStartBracketLB(m_xBuilder->weld_tree_view("startbracket")) + , m_xEndBracketLB(m_xBuilder->weld_tree_view("endbracket")) +{ + for (size_t i = 0; i < SAL_N_ELEMENTS(TWOLINE_OPEN); ++i) + m_xStartBracketLB->append(OUString::number(TWOLINE_OPEN[i].second), CuiResId(TWOLINE_OPEN[i].first)); + for (size_t i = 0; i < SAL_N_ELEMENTS(TWOLINE_CLOSE); ++i) + m_xEndBracketLB->append(OUString::number(TWOLINE_CLOSE[i].second), CuiResId(TWOLINE_CLOSE[i].first)); + + m_xPreviewWin.reset(new weld::CustomWeld(*m_xBuilder, "preview", m_aPreviewWin)); +#ifdef IOS + m_xPreviewWin->hide(); +#endif + Initialize(); +} + +SvxCharTwoLinesPage::~SvxCharTwoLinesPage() +{ +} + +void SvxCharTwoLinesPage::Initialize() +{ + m_xTwoLinesBtn->set_active(false); + TwoLinesHdl_Impl(*m_xTwoLinesBtn); + + m_xTwoLinesBtn->connect_toggled(LINK(this, SvxCharTwoLinesPage, TwoLinesHdl_Impl)); + + Link aLink = LINK(this, SvxCharTwoLinesPage, CharacterMapHdl_Impl); + m_xStartBracketLB->connect_changed(aLink); + m_xEndBracketLB->connect_changed(aLink); + + SvxFont& rFont = GetPreviewFont(); + SvxFont& rCJKFont = GetPreviewCJKFont(); + SvxFont& rCTLFont = GetPreviewCTLFont(); + rFont.SetFontSize( Size( 0, 220 ) ); + rCJKFont.SetFontSize( Size( 0, 220 ) ); + rCTLFont.SetFontSize( Size( 0, 220 ) ); +} + +void SvxCharTwoLinesPage::SelectCharacter(weld::TreeView* pBox) +{ + bool bStart = pBox == m_xStartBracketLB.get(); + SvxCharacterMap aDlg(GetFrameWeld(), nullptr, nullptr); + aDlg.DisableFontSelection(); + + if (aDlg.run() == RET_OK) + { + sal_Unicode cChar = static_cast(aDlg.GetChar()); + SetBracket( cChar, bStart ); + } + else + { + pBox->select(bStart ? m_nStartBracketPosition : m_nEndBracketPosition); + } +} + + +void SvxCharTwoLinesPage::SetBracket( sal_Unicode cBracket, bool bStart ) +{ + int nEntryPos = 0; + weld::TreeView* pBox = bStart ? m_xStartBracketLB.get() : m_xEndBracketLB.get(); + if (cBracket == 0) + pBox->select(0); + else + { + bool bFound = false; + for (int i = 1; i < pBox->n_children(); ++i) + { + if (pBox->get_id(i).toInt32() != CHRDLG_ENCLOSE_SPECIAL_CHAR) + { + const sal_Unicode cChar = pBox->get_text(i)[0]; + if (cChar == cBracket) + { + pBox->select(i); + nEntryPos = i; + bFound = true; + break; + } + } + } + + if (!bFound) + { + pBox->append_text(OUString(cBracket)); + nEntryPos = pBox->n_children() - 1; + pBox->select(nEntryPos); + } + } + if (bStart) + m_nStartBracketPosition = nEntryPos; + else + m_nEndBracketPosition = nEntryPos; +} + +IMPL_LINK_NOARG(SvxCharTwoLinesPage, TwoLinesHdl_Impl, weld::ToggleButton&, void) +{ + bool bChecked = m_xTwoLinesBtn->get_active(); + m_xEnclosingFrame->set_sensitive(bChecked); + UpdatePreview_Impl(); +} + +IMPL_LINK(SvxCharTwoLinesPage, CharacterMapHdl_Impl, weld::TreeView&, rBox, void) +{ + int nPos = rBox.get_selected_index(); + if (rBox.get_id(nPos).toInt32() == CHRDLG_ENCLOSE_SPECIAL_CHAR) + SelectCharacter( &rBox ); + else + { + bool bStart = &rBox == m_xStartBracketLB.get(); + if (bStart) + m_nStartBracketPosition = nPos; + else + m_nEndBracketPosition = nPos; + } + UpdatePreview_Impl(); +} + +void SvxCharTwoLinesPage::ActivatePage( const SfxItemSet& rSet ) +{ + SvxCharBasePage::ActivatePage(rSet); +} + +DeactivateRC SvxCharTwoLinesPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if ( _pSet ) + FillItemSet( _pSet ); + return DeactivateRC::LeavePage; +} + +std::unique_ptr SvxCharTwoLinesPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet) +{ + return std::make_unique(pPage, pController, *rSet); +} + +void SvxCharTwoLinesPage::Reset( const SfxItemSet* rSet ) +{ + m_xTwoLinesBtn->set_active(false); + sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_TWO_LINES ); + SfxItemState eState = rSet->GetItemState( nWhich ); + + if ( eState >= SfxItemState::DONTCARE ) + { + const SvxTwoLinesItem& rItem = static_cast(rSet->Get( nWhich )); + m_xTwoLinesBtn->set_active(rItem.GetValue()); + + if ( rItem.GetValue() ) + { + SetBracket( rItem.GetStartBracket(), true ); + SetBracket( rItem.GetEndBracket(), false ); + } + } + TwoLinesHdl_Impl(*m_xTwoLinesBtn); + + SetPrevFontWidthScale( *rSet ); +} + +bool SvxCharTwoLinesPage::FillItemSet( SfxItemSet* rSet ) +{ + const SfxItemSet& rOldSet = GetItemSet(); + bool bModified = false, bChanged = true; + sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_TWO_LINES ); + const SfxPoolItem* pOld = GetOldItem( *rSet, SID_ATTR_CHAR_TWO_LINES ); + bool bOn = m_xTwoLinesBtn->get_active(); + sal_Unicode cStart = ( bOn && m_xStartBracketLB->get_selected_index() > 0 ) + ? m_xStartBracketLB->get_selected_text()[0] : 0; + sal_Unicode cEnd = ( bOn && m_xEndBracketLB->get_selected_index() > 0 ) + ? m_xEndBracketLB->get_selected_text()[0] : 0; + + if ( pOld ) + { + const SvxTwoLinesItem& rItem = *static_cast(pOld); + if ( rItem.GetValue() == bOn && + ( !bOn || ( rItem.GetStartBracket() == cStart && rItem.GetEndBracket() == cEnd ) ) ) + bChanged = false; + } + + if ( bChanged ) + { + rSet->Put( SvxTwoLinesItem( bOn, cStart, cEnd, nWhich ) ); + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet->InvalidateItem(nWhich); + + return bModified; +} + +void SvxCharTwoLinesPage::UpdatePreview_Impl() +{ + sal_Unicode cStart = m_xStartBracketLB->get_selected_index() > 0 + ? m_xStartBracketLB->get_selected_text()[0] : 0; + sal_Unicode cEnd = m_xEndBracketLB->get_selected_index() > 0 + ? m_xEndBracketLB->get_selected_text()[0] : 0; + m_aPreviewWin.SetBrackets(cStart, cEnd); + m_aPreviewWin.SetTwoLines(m_xTwoLinesBtn->get_active()); + m_aPreviewWin.Invalidate(); +} + +void SvxCharTwoLinesPage::PageCreated(const SfxAllItemSet& aSet) +{ + const SfxUInt32Item* pFlagItem = aSet.GetItem(SID_FLAG_TYPE, false); + if (pFlagItem) + { + sal_uInt32 nFlags=pFlagItem->GetValue(); + if ( ( nFlags & SVX_PREVIEW_CHARACTER ) == SVX_PREVIEW_CHARACTER ) + // the writer uses SID_ATTR_BRUSH as font background + m_bPreviewBackgroundToCharacter = true; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/chardlg.h b/cui/source/tabpages/chardlg.h new file mode 100644 index 000000000..b72beae2e --- /dev/null +++ b/cui/source/tabpages/chardlg.h @@ -0,0 +1,29 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CUI_SOURCE_TABPAGES_CHARDLG_H +#define INCLUDED_CUI_SOURCE_TABPAGES_CHARDLG_H + +// define ---------------------------------------------------------------- + +#define CHRDLG_POSITION_OVER 0 +#define CHRDLG_POSITION_UNDER 1 + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/connect.cxx b/cui/source/tabpages/connect.cxx new file mode 100644 index 000000000..70b38bbc9 --- /dev/null +++ b/cui/source/tabpages/connect.cxx @@ -0,0 +1,419 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +const sal_uInt16 SvxConnectionPage::pRanges[] = +{ + SDRATTR_EDGE_FIRST, + SDRATTR_EDGE_LAST, + 0 +}; + +/************************************************************************* +|* +|* dialog for changing connectors +|* +\************************************************************************/ +SvxConnectionDialog::SvxConnectionDialog(weld::Window* pParent, const SfxItemSet& rInAttrs, const SdrView* pSdrView) + : SfxSingleTabDialogController(pParent, &rInAttrs) +{ + auto xPage = std::make_unique(get_content_area(), this, rInAttrs); + + xPage->SetView(pSdrView); + xPage->Construct(); + + SetTabPage(std::move(xPage)); + m_xDialog->set_title(CuiResId(RID_SVXSTR_CONNECTOR)); +} + +/************************************************************************* +|* +|* page for changing connectors +|* +\************************************************************************/ + +SvxConnectionPage::SvxConnectionPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "cui/ui/connectortabpage.ui", "ConnectorTabPage", &rInAttrs) + , rOutAttrs(rInAttrs) + , aAttrSet(*rInAttrs.GetPool()) + , pView(nullptr) + , m_xLbType(m_xBuilder->weld_combo_box("LB_TYPE")) + , m_xFtLine1(m_xBuilder->weld_label("FT_LINE_1")) + , m_xMtrFldLine1(m_xBuilder->weld_metric_spin_button("MTR_FLD_LINE_1", FieldUnit::CM)) + , m_xFtLine2(m_xBuilder->weld_label("FT_LINE_2")) + , m_xMtrFldLine2(m_xBuilder->weld_metric_spin_button("MTR_FLD_LINE_2", FieldUnit::CM)) + , m_xFtLine3(m_xBuilder->weld_label("FT_LINE_3")) + , m_xMtrFldLine3(m_xBuilder->weld_metric_spin_button("MTR_FLD_LINE_3", FieldUnit::CM)) + , m_xMtrFldHorz1(m_xBuilder->weld_metric_spin_button("MTR_FLD_HORZ_1", FieldUnit::MM)) + , m_xMtrFldVert1(m_xBuilder->weld_metric_spin_button("MTR_FLD_VERT_1", FieldUnit::MM)) + , m_xMtrFldHorz2(m_xBuilder->weld_metric_spin_button("MTR_FLD_HORZ_2", FieldUnit::MM)) + , m_xMtrFldVert2(m_xBuilder->weld_metric_spin_button("MTR_FLD_VERT_2", FieldUnit::MM)) + , m_xCtlPreview(new weld::CustomWeld(*m_xBuilder, "CTL_PREVIEW", m_aCtlPreview)) +{ + SfxItemPool* pPool = rOutAttrs.GetPool(); + DBG_ASSERT( pPool, "Where is the pool" ); + eUnit = pPool->GetMetric( SDRATTR_EDGENODE1HORZDIST ); + + FillTypeLB(); + + const FieldUnit eFUnit = GetModuleFieldUnit( rInAttrs ); + SetFieldUnit( *m_xMtrFldHorz1, eFUnit ); + SetFieldUnit( *m_xMtrFldHorz2, eFUnit ); + SetFieldUnit( *m_xMtrFldVert1, eFUnit ); + SetFieldUnit( *m_xMtrFldVert2, eFUnit ); + SetFieldUnit( *m_xMtrFldLine1, eFUnit ); + SetFieldUnit( *m_xMtrFldLine2, eFUnit ); + SetFieldUnit( *m_xMtrFldLine3, eFUnit ); + if( eFUnit == FieldUnit::MM ) + { + m_xMtrFldHorz1->set_increments(50, 500, FieldUnit::NONE); + m_xMtrFldHorz2->set_increments(50, 500, FieldUnit::NONE); + m_xMtrFldVert1->set_increments(50, 500, FieldUnit::NONE); + m_xMtrFldVert2->set_increments(50, 500, FieldUnit::NONE); + m_xMtrFldLine1->set_increments(50, 500, FieldUnit::NONE); + m_xMtrFldLine2->set_increments(50, 500, FieldUnit::NONE); + m_xMtrFldLine3->set_increments(50, 500, FieldUnit::NONE); + } + + Link aLink(LINK(this, SvxConnectionPage, ChangeAttrEditHdl_Impl)); + m_xMtrFldHorz1->connect_value_changed(aLink); + m_xMtrFldVert1->connect_value_changed(aLink); + m_xMtrFldHorz2->connect_value_changed(aLink); + m_xMtrFldVert2->connect_value_changed(aLink); + m_xMtrFldLine1->connect_value_changed(aLink); + m_xMtrFldLine2->connect_value_changed(aLink); + m_xMtrFldLine3->connect_value_changed(aLink); + m_xLbType->connect_changed(LINK(this, SvxConnectionPage, ChangeAttrListBoxHdl_Impl)); +} + +SvxConnectionPage::~SvxConnectionPage() +{ + m_xCtlPreview.reset(); +} + +/************************************************************************* +|* +|* reads passed Item-Set +|* +\************************************************************************/ + +void SvxConnectionPage::Reset( const SfxItemSet* rAttrs ) +{ + const SfxPoolItem* pItem = GetItem( *rAttrs, SDRATTR_EDGENODE1HORZDIST ); + const SfxItemPool* pPool = rAttrs->GetPool(); + + // SdrEdgeNode1HorzDistItem + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_EDGENODE1HORZDIST ); + SetMetricValue(*m_xMtrFldHorz1, static_cast(pItem)->GetValue(), + eUnit); + m_xMtrFldHorz1->save_value(); + + // SdrEdgeNode2HorzDistItem + pItem = GetItem( *rAttrs, SDRATTR_EDGENODE2HORZDIST ); + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_EDGENODE2HORZDIST ); + SetMetricValue(*m_xMtrFldHorz2, static_cast(pItem)->GetValue(), + eUnit); + m_xMtrFldHorz2->save_value(); + + // SdrEdgeNode1VertDistItem + pItem = GetItem( *rAttrs, SDRATTR_EDGENODE1VERTDIST ); + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_EDGENODE1VERTDIST ); + SetMetricValue(*m_xMtrFldVert1, static_cast(pItem)->GetValue(), + eUnit); + m_xMtrFldVert1->save_value(); + + // SdrEdgeNode2VertDistItem + pItem = GetItem( *rAttrs, SDRATTR_EDGENODE2VERTDIST ); + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_EDGENODE2VERTDIST ); + SetMetricValue(*m_xMtrFldVert2, static_cast(pItem)->GetValue(), + eUnit); + m_xMtrFldVert2->save_value(); + + // SdrEdgeLine1DeltaItem + pItem = GetItem( *rAttrs, SDRATTR_EDGELINE1DELTA ); + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_EDGELINE1DELTA ); + SetMetricValue(*m_xMtrFldLine1, static_cast(pItem)->GetValue(), eUnit); + m_xMtrFldLine1->save_value(); + + // SdrEdgeLine2DeltaItem + pItem = GetItem( *rAttrs, SDRATTR_EDGELINE2DELTA ); + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_EDGELINE2DELTA ); + SetMetricValue(*m_xMtrFldLine2, static_cast(pItem)->GetValue(), eUnit); + m_xMtrFldLine2->save_value(); + + // SdrEdgeLine3DeltaItem + pItem = GetItem( *rAttrs, SDRATTR_EDGELINE3DELTA ); + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_EDGELINE3DELTA ); + SetMetricValue(*m_xMtrFldLine3, static_cast(pItem)->GetValue(), eUnit); + m_xMtrFldLine3->save_value(); + + // SdrEdgeLineDeltaAnzItem + pItem = GetItem( *rAttrs, SDRATTR_EDGELINEDELTACOUNT ); + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_EDGELINEDELTACOUNT ); + switch (static_cast(pItem)->GetValue()) + { + case 0: + m_xFtLine1->set_sensitive(false); + m_xMtrFldLine1->set_sensitive(false); + m_xMtrFldLine1->set_text(""); + [[fallthrough]]; + case 1: + m_xFtLine2->set_sensitive(false); + m_xMtrFldLine2->set_sensitive(false); + m_xMtrFldLine2->set_text(""); + [[fallthrough]]; + case 2: + m_xFtLine3->set_sensitive(false); + m_xMtrFldLine3->set_sensitive(false); + m_xMtrFldLine3->set_text(""); + break; + } + + // SdrEdgeKindItem + pItem = GetItem( *rAttrs, SDRATTR_EDGEKIND ); + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_EDGEKIND ); + m_xLbType->set_active( + sal::static_int_cast(static_cast(pItem)->GetValue())); + m_xLbType->save_value(); +} + +/************************************************************************* +|* +|* fills the passed Item-Set width Dialogbox attributes +|* +\************************************************************************/ + +bool SvxConnectionPage::FillItemSet( SfxItemSet* rAttrs) +{ + bool bModified = false; + sal_Int32 nValue; + + if (m_xMtrFldHorz1->get_value_changed_from_saved()) + { + nValue = GetCoreValue(*m_xMtrFldHorz1, eUnit); + rAttrs->Put( SdrEdgeNode1HorzDistItem( nValue ) ); + bModified = true; + } + + if (m_xMtrFldHorz2->get_value_changed_from_saved()) + { + nValue = GetCoreValue(*m_xMtrFldHorz2, eUnit); + rAttrs->Put( SdrEdgeNode2HorzDistItem( nValue ) ); + bModified = true; + } + + if (m_xMtrFldVert1->get_value_changed_from_saved()) + { + nValue = GetCoreValue(*m_xMtrFldVert1, eUnit); + rAttrs->Put( SdrEdgeNode1VertDistItem( nValue ) ); + bModified = true; + } + + if (m_xMtrFldVert2->get_value_changed_from_saved()) + { + nValue = GetCoreValue(*m_xMtrFldVert2, eUnit); + rAttrs->Put( SdrEdgeNode2VertDistItem( nValue ) ); + bModified = true; + } + + if (m_xMtrFldLine1->get_value_changed_from_saved()) + { + nValue = GetCoreValue(*m_xMtrFldLine1, eUnit); + rAttrs->Put( makeSdrEdgeLine1DeltaItem( nValue ) ); + bModified = true; + } + + if (m_xMtrFldLine2->get_value_changed_from_saved()) + { + nValue = GetCoreValue(*m_xMtrFldLine2, eUnit); + rAttrs->Put( makeSdrEdgeLine2DeltaItem( nValue ) ); + bModified = true; + } + + if (m_xMtrFldLine3->get_value_changed_from_saved()) + { + nValue = GetCoreValue(*m_xMtrFldLine3, eUnit); + rAttrs->Put( makeSdrEdgeLine3DeltaItem( nValue ) ); + bModified = true; + } + + int nPos = m_xLbType->get_active(); + if (m_xLbType->get_value_changed_from_saved()) + { + if (nPos != -1) + { + rAttrs->Put( SdrEdgeKindItem( static_cast(nPos) ) ); + bModified = true; + } + } + + return bModified; +} + +void SvxConnectionPage::Construct() +{ + DBG_ASSERT( pView, "No valid View transfer!" ); + + m_aCtlPreview.SetView(pView); + m_aCtlPreview.Construct(); +} + +/************************************************************************* +|* +|* creates the page +|* +\************************************************************************/ +std::unique_ptr SvxConnectionPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrs) +{ + return std::make_unique(pPage, pController, *rAttrs); +} + +IMPL_LINK_NOARG(SvxConnectionPage, ChangeAttrListBoxHdl_Impl, weld::ComboBox&, void) +{ + int nPos = m_xLbType->get_active(); + if (nPos != -1) + { + aAttrSet.Put( SdrEdgeKindItem( static_cast(nPos) ) ); + } + + m_aCtlPreview.SetAttributes(aAttrSet); + + // get the number of line displacements + sal_uInt16 nCount = m_aCtlPreview.GetLineDeltaCount(); + + m_xFtLine3->set_sensitive( nCount > 2 ); + m_xMtrFldLine3->set_sensitive( nCount > 2 ); + if( nCount > 2 ) + m_xMtrFldLine3->set_value(m_xMtrFldLine3->get_value(FieldUnit::NONE), FieldUnit::NONE); + else + m_xMtrFldLine3->set_text(""); + + m_xFtLine2->set_sensitive( nCount > 1 ); + m_xMtrFldLine2->set_sensitive( nCount > 1 ); + if( nCount > 1 ) + m_xMtrFldLine2->set_value(m_xMtrFldLine2->get_value(FieldUnit::NONE), FieldUnit::NONE); + else + m_xMtrFldLine2->set_text(""); + + m_xFtLine1->set_sensitive( nCount > 0 ); + m_xMtrFldLine1->set_sensitive( nCount > 0 ); + if( nCount > 0 ) + m_xMtrFldLine1->set_value(m_xMtrFldLine1->get_value(FieldUnit::NONE), FieldUnit::NONE); + else + m_xMtrFldLine1->set_text(""); +} + +IMPL_LINK(SvxConnectionPage, ChangeAttrEditHdl_Impl, weld::MetricSpinButton&, r, void) +{ + if (&r == m_xMtrFldHorz1.get()) + { + sal_Int32 nValue = GetCoreValue(*m_xMtrFldHorz1, eUnit); + aAttrSet.Put( SdrEdgeNode1HorzDistItem( nValue ) ); + } + + if (&r == m_xMtrFldHorz2.get()) + { + sal_Int32 nValue = GetCoreValue( *m_xMtrFldHorz2, eUnit ); + aAttrSet.Put( SdrEdgeNode2HorzDistItem( nValue ) ); + } + + if (&r == m_xMtrFldVert1.get()) + { + sal_Int32 nValue = GetCoreValue(*m_xMtrFldVert1, eUnit); + aAttrSet.Put( SdrEdgeNode1VertDistItem( nValue ) ); + } + + if (&r == m_xMtrFldVert2.get()) + { + sal_Int32 nValue = GetCoreValue(*m_xMtrFldVert2, eUnit); + aAttrSet.Put( SdrEdgeNode2VertDistItem( nValue ) ); + } + + if (&r == m_xMtrFldLine1.get()) + { + sal_Int32 nValue = GetCoreValue(*m_xMtrFldLine1, eUnit); + aAttrSet.Put( makeSdrEdgeLine1DeltaItem( nValue ) ); + } + + if (&r == m_xMtrFldLine2.get()) + { + sal_Int32 nValue = GetCoreValue(*m_xMtrFldLine2, eUnit); + aAttrSet.Put( makeSdrEdgeLine2DeltaItem( nValue ) ); + } + + if (&r == m_xMtrFldLine3.get()) + { + sal_Int32 nValue = GetCoreValue(*m_xMtrFldLine3, eUnit); + aAttrSet.Put( makeSdrEdgeLine3DeltaItem( nValue ) ); + } + + m_aCtlPreview.SetAttributes(aAttrSet); +} + +void SvxConnectionPage::FillTypeLB() +{ + // fill ListBox with connector names + const SfxPoolItem* pItem = GetItem( rOutAttrs, SDRATTR_EDGEKIND ); + const SfxItemPool* pPool = rOutAttrs.GetPool(); + + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_EDGEKIND ); + const SdrEdgeKindItem* pEdgeKindItem = static_cast(pItem); + const sal_uInt16 nCount = pEdgeKindItem->GetValueCount(); + for (sal_uInt16 i = 0; i < nCount; i++) + { + OUString aStr = SdrEdgeKindItem::GetValueTextByPos(i); + m_xLbType->append_text(aStr); + } +} +void SvxConnectionPage::PageCreated(const SfxAllItemSet& aSet) +{ + const OfaPtrItem* pOfaPtrItem = aSet.GetItem(SID_OBJECT_LIST, false); + if (pOfaPtrItem) + SetView( static_cast(pOfaPtrItem->GetValue()) ); + + Construct(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/dstribut.cxx b/cui/source/tabpages/dstribut.cxx new file mode 100644 index 000000000..e1653ca4d --- /dev/null +++ b/cui/source/tabpages/dstribut.cxx @@ -0,0 +1,152 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +/************************************************************************* +|* +|* Dialog +|* +\************************************************************************/ + +SvxDistributeDialog::SvxDistributeDialog(weld::Window* pParent, + const SfxItemSet& rInAttrs, SvxDistributeHorizontal eHor, + SvxDistributeVertical eVer) + : SfxSingleTabDialogController(pParent, &rInAttrs, "cui/ui/distributiondialog.ui", + "DistributionDialog") +{ + SetTabPage(std::make_unique(get_content_area(), this, rInAttrs, eHor, eVer)); + mpPage = static_cast(GetTabPage()); +} + +SvxDistributeDialog::~SvxDistributeDialog() +{ +} + +/************************************************************************* +|* +|* Tabpage +|* +\************************************************************************/ + +SvxDistributePage::SvxDistributePage(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet& rInAttrs, SvxDistributeHorizontal eHor, + SvxDistributeVertical eVer) + : SfxTabPage(pPage, pController, "cui/ui/distributionpage.ui", "DistributionPage", + &rInAttrs) + , m_eDistributeHor(eHor) + , m_eDistributeVer(eVer) + , m_xBtnHorNone(m_xBuilder->weld_radio_button("hornone")) + , m_xBtnHorLeft(m_xBuilder->weld_radio_button("horleft")) + , m_xBtnHorCenter(m_xBuilder->weld_radio_button("horcenter")) + , m_xBtnHorDistance(m_xBuilder->weld_radio_button("hordistance")) + , m_xBtnHorRight(m_xBuilder->weld_radio_button("horright")) + , m_xBtnVerNone(m_xBuilder->weld_radio_button("vernone")) + , m_xBtnVerTop(m_xBuilder->weld_radio_button("vertop")) + , m_xBtnVerCenter(m_xBuilder->weld_radio_button("vercenter")) + , m_xBtnVerDistance(m_xBuilder->weld_radio_button("verdistance")) + , m_xBtnVerBottom(m_xBuilder->weld_radio_button("verbottom")) +{ +} + +SvxDistributePage::~SvxDistributePage() +{ +} + +/************************************************************************* +|* +|* read the delivered Item-Set +|* +\************************************************************************/ + +void SvxDistributePage::Reset(const SfxItemSet* ) +{ + m_xBtnHorNone->set_active(false); + m_xBtnHorLeft->set_active(false); + m_xBtnHorCenter->set_active(false); + m_xBtnHorDistance->set_active(false); + m_xBtnHorRight->set_active(false); + + switch(m_eDistributeHor) + { + case SvxDistributeHorizontal::NONE : m_xBtnHorNone->set_active(true); break; + case SvxDistributeHorizontal::Left : m_xBtnHorLeft->set_active(true); break; + case SvxDistributeHorizontal::Center : m_xBtnHorCenter->set_active(true); break; + case SvxDistributeHorizontal::Distance : m_xBtnHorDistance->set_active(true); break; + case SvxDistributeHorizontal::Right : m_xBtnHorRight->set_active(true); break; + } + + m_xBtnVerNone->set_active(false); + m_xBtnVerTop->set_active(false); + m_xBtnVerCenter->set_active(false); + m_xBtnVerDistance->set_active(false); + m_xBtnVerBottom->set_active(false); + + switch(m_eDistributeVer) + { + case SvxDistributeVertical::NONE : m_xBtnVerNone->set_active(true); break; + case SvxDistributeVertical::Top : m_xBtnVerTop->set_active(true); break; + case SvxDistributeVertical::Center : m_xBtnVerCenter->set_active(true); break; + case SvxDistributeVertical::Distance : m_xBtnVerDistance->set_active(true); break; + case SvxDistributeVertical::Bottom : m_xBtnVerBottom->set_active(true); break; + } +} + +/************************************************************************* +|* +|* Fill the delivered Item-Set with dialogbox-attributes +|* +\************************************************************************/ + +bool SvxDistributePage::FillItemSet( SfxItemSet* ) +{ + SvxDistributeHorizontal eDistributeHor(SvxDistributeHorizontal::NONE); + SvxDistributeVertical eDistributeVer(SvxDistributeVertical::NONE); + + if(m_xBtnHorLeft->get_active()) + eDistributeHor = SvxDistributeHorizontal::Left; + else if(m_xBtnHorCenter->get_active()) + eDistributeHor = SvxDistributeHorizontal::Center; + else if(m_xBtnHorDistance->get_active()) + eDistributeHor = SvxDistributeHorizontal::Distance; + else if(m_xBtnHorRight->get_active()) + eDistributeHor = SvxDistributeHorizontal::Right; + + if(m_xBtnVerTop->get_active()) + eDistributeVer = SvxDistributeVertical::Top; + else if(m_xBtnVerCenter->get_active()) + eDistributeVer = SvxDistributeVertical::Center; + else if(m_xBtnVerDistance->get_active()) + eDistributeVer = SvxDistributeVertical::Distance; + else if(m_xBtnVerBottom->get_active()) + eDistributeVer = SvxDistributeVertical::Bottom; + + if(eDistributeHor != m_eDistributeHor || eDistributeVer != m_eDistributeVer) + { + m_eDistributeHor = eDistributeHor; + m_eDistributeVer = eDistributeVer; + return true; + } + + return false; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/grfpage.cxx b/cui/source/tabpages/grfpage.cxx new file mode 100644 index 000000000..7f334e2f1 --- /dev/null +++ b/cui/source/tabpages/grfpage.cxx @@ -0,0 +1,785 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CM_1_TO_TWIP 567 +#define TWIP_TO_INCH 1440 + + +static int lcl_GetValue(const weld::MetricSpinButton& rMetric, FieldUnit eUnit) +{ + return rMetric.denormalize(rMetric.get_value(eUnit)); +} + +/*-------------------------------------------------------------------- + description: crop graphic + --------------------------------------------------------------------*/ + +SvxGrfCropPage::SvxGrfCropPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet) + : SfxTabPage(pPage, pController, "cui/ui/croppage.ui", "CropPage", &rSet) + , nOldWidth(0) + , nOldHeight(0) + , bSetOrigSize(false) + , m_xCropFrame(m_xBuilder->weld_widget("cropframe")) + , m_xZoomConstRB(m_xBuilder->weld_radio_button("keepscale")) + , m_xSizeConstRB(m_xBuilder->weld_radio_button("keepsize")) + , m_xLeftMF(m_xBuilder->weld_metric_spin_button("left", FieldUnit::CM)) + , m_xRightMF(m_xBuilder->weld_metric_spin_button("right", FieldUnit::CM)) + , m_xTopMF(m_xBuilder->weld_metric_spin_button("top", FieldUnit::CM)) + , m_xBottomMF(m_xBuilder->weld_metric_spin_button("bottom", FieldUnit::CM)) + , m_xScaleFrame(m_xBuilder->weld_widget("scaleframe")) + , m_xWidthZoomMF(m_xBuilder->weld_metric_spin_button("widthzoom", FieldUnit::PERCENT)) + , m_xHeightZoomMF(m_xBuilder->weld_metric_spin_button("heightzoom", FieldUnit::PERCENT)) + , m_xSizeFrame(m_xBuilder->weld_widget("sizeframe")) + , m_xWidthMF(m_xBuilder->weld_metric_spin_button("width", FieldUnit::CM)) + , m_xHeightMF(m_xBuilder->weld_metric_spin_button("height", FieldUnit::CM)) + , m_xOrigSizeGrid(m_xBuilder->weld_widget("origsizegrid")) + , m_xOrigSizeFT(m_xBuilder->weld_label("origsizeft")) + , m_xOrigSizePB(m_xBuilder->weld_button("origsize")) + , m_xExampleWN(new weld::CustomWeld(*m_xBuilder, "preview", m_aExampleWN)) +{ + SetExchangeSupport(); + + // set the correct metric + const FieldUnit eMetric = GetModuleFieldUnit( rSet ); + + SetFieldUnit( *m_xWidthMF, eMetric ); + SetFieldUnit( *m_xHeightMF, eMetric ); + SetFieldUnit( *m_xLeftMF, eMetric ); + SetFieldUnit( *m_xRightMF, eMetric ); + SetFieldUnit( *m_xTopMF , eMetric ); + SetFieldUnit( *m_xBottomMF, eMetric ); + + Link aLk = LINK(this, SvxGrfCropPage, SizeHdl); + m_xWidthMF->connect_value_changed( aLk ); + m_xHeightMF->connect_value_changed( aLk ); + + aLk = LINK(this, SvxGrfCropPage, ZoomHdl); + m_xWidthZoomMF->connect_value_changed( aLk ); + m_xHeightZoomMF->connect_value_changed( aLk ); + + aLk = LINK(this, SvxGrfCropPage, CropModifyHdl); + m_xLeftMF->connect_value_changed( aLk ); + m_xRightMF->connect_value_changed( aLk ); + m_xTopMF->connect_value_changed( aLk ); + m_xBottomMF->connect_value_changed( aLk ); + + m_xOrigSizePB->connect_clicked(LINK(this, SvxGrfCropPage, OrigSizeHdl)); +} + +SvxGrfCropPage::~SvxGrfCropPage() +{ + m_xExampleWN.reset(); +} + +std::unique_ptr SvxGrfCropPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet) +{ + return std::make_unique(pPage, pController, *rSet); +} + +void SvxGrfCropPage::Reset( const SfxItemSet *rSet ) +{ + const SfxPoolItem* pItem; + const SfxItemPool& rPool = *rSet->GetPool(); + + if(SfxItemState::SET == rSet->GetItemState( rPool.GetWhich( + SID_ATTR_GRAF_KEEP_ZOOM ), true, &pItem )) + { + if( static_cast(pItem)->GetValue() ) + m_xZoomConstRB->set_active(true); + else + m_xSizeConstRB->set_active(true); + m_xZoomConstRB->save_state(); + } + + sal_uInt16 nW = rPool.GetWhich( SID_ATTR_GRAF_CROP ); + if( SfxItemState::SET == rSet->GetItemState( nW, true, &pItem)) + { + FieldUnit eUnit = MapToFieldUnit( rSet->GetPool()->GetMetric( nW )); + + const SvxGrfCrop* pCrop = static_cast(pItem); + + m_aExampleWN.SetLeft(pCrop->GetLeft()); + m_aExampleWN.SetRight(pCrop->GetRight()); + m_aExampleWN.SetTop(pCrop->GetTop()); + m_aExampleWN.SetBottom(pCrop->GetBottom()); + + m_xLeftMF->set_value( m_xLeftMF->normalize( pCrop->GetLeft()), eUnit ); + m_xRightMF->set_value( m_xRightMF->normalize( pCrop->GetRight()), eUnit ); + m_xTopMF->set_value( m_xTopMF->normalize( pCrop->GetTop()), eUnit ); + m_xBottomMF->set_value( m_xBottomMF->normalize( pCrop->GetBottom()), eUnit ); + } + else + { + m_xLeftMF->set_value(0, FieldUnit::NONE); + m_xRightMF->set_value(0, FieldUnit::NONE); + m_xTopMF->set_value(0, FieldUnit::NONE); + m_xBottomMF->set_value(0, FieldUnit::NONE); + } + + m_xLeftMF->save_value(); + m_xRightMF->save_value(); + m_xTopMF->save_value(); + m_xBottomMF->save_value(); + + nW = rPool.GetWhich( SID_ATTR_PAGE_SIZE ); + if ( SfxItemState::SET == rSet->GetItemState( nW, false, &pItem ) ) + { + // orientation and size from the PageItem + FieldUnit eUnit = MapToFieldUnit( rSet->GetPool()->GetMetric( nW )); + + aPageSize = static_cast(pItem)->GetSize(); + + auto nMin = m_xWidthMF->normalize( 23 ); + auto nMax = m_xHeightMF->normalize(aPageSize.Height()); + m_xHeightMF->set_range(nMin, nMax, eUnit); + nMax = m_xWidthMF->normalize(aPageSize.Width()); + m_xWidthMF->set_range(nMin, nMax, eUnit); + } + else + { + aPageSize = OutputDevice::LogicToLogic( + Size( CM_1_TO_TWIP, CM_1_TO_TWIP ), + MapMode( MapUnit::MapTwip ), + MapMode( rSet->GetPool()->GetMetric( nW ) ) ); + } + + bool bFound = false; + if( SfxItemState::SET == rSet->GetItemState( SID_ATTR_GRAF_GRAPHIC, false, &pItem ) ) + { + OUString referer; + SfxStringItem const * it = static_cast( + rSet->GetItem(SID_REFERER)); + if (it != nullptr) { + referer = it->GetValue(); + } + const Graphic* pGrf = static_cast(pItem)->GetGraphic(referer); + if( pGrf ) + { + aOrigSize = GetGrfOrigSize( *pGrf ); + if (pGrf->GetType() == GraphicType::Bitmap && aOrigSize.Width() && aOrigSize.Height()) + { + aOrigPixelSize = pGrf->GetSizePixel(); + } + + if( aOrigSize.Width() && aOrigSize.Height() ) + { + CalcMinMaxBorder(); + m_aExampleWN.SetGraphic( *pGrf ); + m_aExampleWN.SetFrameSize( aOrigSize ); + + bFound = true; + if( !static_cast(pItem)->GetGraphicLink().isEmpty() ) + aGraphicName = static_cast(pItem)->GetGraphicLink(); + } + } + } + + GraphicHasChanged( bFound ); + ActivatePage( *rSet ); +} + +bool SvxGrfCropPage::FillItemSet(SfxItemSet *rSet) +{ + const SfxItemPool& rPool = *rSet->GetPool(); + bool bModified = false; + if( m_xWidthMF->get_value_changed_from_saved() || + m_xHeightMF->get_value_changed_from_saved() ) + { + sal_uInt16 nW = rPool.GetWhich( SID_ATTR_GRAF_FRMSIZE ); + FieldUnit eUnit = MapToFieldUnit( rSet->GetPool()->GetMetric( nW )); + + std::shared_ptr aSz(std::make_shared(nW)); + + // size could already have been set from another page + const SfxItemSet* pExSet = GetDialogExampleSet(); + const SfxPoolItem* pItem = nullptr; + if( pExSet && SfxItemState::SET ==pExSet->GetItemState( nW, false, &pItem ) ) + { + aSz.reset(static_cast< SvxSizeItem*>(pItem->Clone())); + } + else + { + aSz.reset(static_cast< SvxSizeItem*>(GetItemSet().Get(nW).Clone())); + } + + Size aTmpSz( aSz->GetSize() ); + if( m_xWidthMF->get_value_changed_from_saved() ) + aTmpSz.setWidth( lcl_GetValue( *m_xWidthMF, eUnit ) ); + if( m_xHeightMF->get_value_changed_from_saved() ) + aTmpSz.setHeight( lcl_GetValue( *m_xHeightMF, eUnit ) ); + aSz->SetSize( aTmpSz ); + m_xWidthMF->save_value(); + m_xHeightMF->save_value(); + + bModified |= nullptr != rSet->Put( *aSz ); + + if( bSetOrigSize ) + { + bModified |= nullptr != rSet->Put( SvxSizeItem( rPool.GetWhich( + SID_ATTR_GRAF_FRMSIZE_PERCENT ), Size( 0, 0 )) ); + } + } + if( m_xLeftMF->get_value_changed_from_saved() || m_xRightMF->get_value_changed_from_saved() || + m_xTopMF->get_value_changed_from_saved() || m_xBottomMF->get_value_changed_from_saved() ) + { + sal_uInt16 nW = rPool.GetWhich( SID_ATTR_GRAF_CROP ); + FieldUnit eUnit = MapToFieldUnit( rSet->GetPool()->GetMetric( nW )); + std::unique_ptr pNew(static_cast(rSet->Get( nW ).Clone())); + + pNew->SetLeft( lcl_GetValue( *m_xLeftMF, eUnit ) ); + pNew->SetRight( lcl_GetValue( *m_xRightMF, eUnit ) ); + pNew->SetTop( lcl_GetValue( *m_xTopMF, eUnit ) ); + pNew->SetBottom( lcl_GetValue( *m_xBottomMF, eUnit ) ); + bModified |= nullptr != rSet->Put( *pNew ); + } + + if( m_xZoomConstRB->get_state_changed_from_saved() ) + { + bModified |= nullptr != rSet->Put( SfxBoolItem( rPool.GetWhich( + SID_ATTR_GRAF_KEEP_ZOOM), m_xZoomConstRB->get_active() ) ); + } + + return bModified; +} + +void SvxGrfCropPage::ActivatePage(const SfxItemSet& rSet) +{ +#ifdef DBG_UTIL + SfxItemPool* pPool = GetItemSet().GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); +#endif + + bSetOrigSize = false; + + // Size + Size aSize; + const SfxPoolItem* pItem; + if( SfxItemState::SET == rSet.GetItemState( SID_ATTR_GRAF_FRMSIZE, false, &pItem ) ) + aSize = static_cast(pItem)->GetSize(); + + nOldWidth = aSize.Width(); + nOldHeight = aSize.Height(); + + auto nWidth = m_xWidthMF->normalize(nOldWidth); + auto nHeight = m_xHeightMF->normalize(nOldHeight); + + if (nWidth != m_xWidthMF->get_value(FieldUnit::TWIP)) + m_xWidthMF->set_value(nWidth, FieldUnit::TWIP); + m_xWidthMF->save_value(); + + if (nHeight != m_xHeightMF->get_value(FieldUnit::TWIP)) + m_xHeightMF->set_value(nHeight, FieldUnit::TWIP); + m_xHeightMF->save_value(); + + if( SfxItemState::SET == rSet.GetItemState( SID_ATTR_GRAF_GRAPHIC, false, &pItem ) ) + { + const SvxBrushItem& rBrush = *static_cast(pItem); + if( !rBrush.GetGraphicLink().isEmpty() && + aGraphicName != rBrush.GetGraphicLink() ) + aGraphicName = rBrush.GetGraphicLink(); + + OUString referer; + SfxStringItem const * it = static_cast( + rSet.GetItem(SID_REFERER)); + if (it != nullptr) { + referer = it->GetValue(); + } + const Graphic* pGrf = rBrush.GetGraphic(referer); + if( pGrf ) + { + m_aExampleWN.SetGraphic( *pGrf ); + aOrigSize = GetGrfOrigSize( *pGrf ); + if (pGrf->GetType() == GraphicType::Bitmap && aOrigSize.Width() > 1 && aOrigSize.Height() > 1) { + aOrigPixelSize = pGrf->GetSizePixel(); + } + m_aExampleWN.SetFrameSize(aOrigSize); + GraphicHasChanged( aOrigSize.Width() && aOrigSize.Height() ); + CalcMinMaxBorder(); + } + else + GraphicHasChanged( false ); + } + + CalcZoom(); +} + +DeactivateRC SvxGrfCropPage::DeactivatePage(SfxItemSet *_pSet) +{ + if ( _pSet ) + FillItemSet( _pSet ); + return DeactivateRC::LeavePage; +} + +/*-------------------------------------------------------------------- + description: scale changed, adjust size + --------------------------------------------------------------------*/ + +IMPL_LINK( SvxGrfCropPage, ZoomHdl, weld::MetricSpinButton&, rField, void ) +{ + SfxItemPool* pPool = GetItemSet().GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( pPool->GetWhich( + SID_ATTR_GRAF_CROP ) ) ); + + if (&rField == m_xWidthZoomMF.get()) + { + long nLRBorders = lcl_GetValue(*m_xLeftMF, eUnit) + +lcl_GetValue(*m_xRightMF, eUnit); + m_xWidthMF->set_value( m_xWidthMF->normalize( + ((aOrigSize.Width() - nLRBorders) * rField.get_value(FieldUnit::NONE))/100), + eUnit); + } + else + { + long nULBorders = lcl_GetValue(*m_xTopMF, eUnit) + +lcl_GetValue(*m_xBottomMF, eUnit); + m_xHeightMF->set_value( m_xHeightMF->normalize( + ((aOrigSize.Height() - nULBorders ) * rField.get_value(FieldUnit::NONE))/100) , + eUnit ); + } +} + +/*-------------------------------------------------------------------- + description: change size, adjust scale + --------------------------------------------------------------------*/ + +IMPL_LINK( SvxGrfCropPage, SizeHdl, weld::MetricSpinButton&, rField, void ) +{ + SfxItemPool* pPool = GetItemSet().GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( pPool->GetWhich( + SID_ATTR_GRAF_CROP ) ) ); + + Size aSize( lcl_GetValue(*m_xWidthMF, eUnit), + lcl_GetValue(*m_xHeightMF, eUnit) ); + + if(&rField == m_xWidthMF.get()) + { + long nWidth = aOrigSize.Width() - + ( lcl_GetValue(*m_xLeftMF, eUnit) + + lcl_GetValue(*m_xRightMF, eUnit) ); + if(!nWidth) + nWidth++; + sal_uInt16 nZoom = static_cast( aSize.Width() * 100 / nWidth); + m_xWidthZoomMF->set_value(nZoom, FieldUnit::NONE); + } + else + { + long nHeight = aOrigSize.Height() - + ( lcl_GetValue(*m_xTopMF, eUnit) + + lcl_GetValue(*m_xBottomMF, eUnit)); + if(!nHeight) + nHeight++; + sal_uInt16 nZoom = static_cast( aSize.Height() * 100 / nHeight); + m_xHeightZoomMF->set_value(nZoom, FieldUnit::NONE); + } +} + +/*-------------------------------------------------------------------- + description: evaluate border + --------------------------------------------------------------------*/ + +IMPL_LINK( SvxGrfCropPage, CropModifyHdl, weld::MetricSpinButton&, rField, void ) +{ + SfxItemPool* pPool = GetItemSet().GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( pPool->GetWhich( + SID_ATTR_GRAF_CROP ) ) ); + + bool bZoom = m_xZoomConstRB->get_active(); + if (&rField == m_xLeftMF.get() || &rField == m_xRightMF.get()) + { + long nLeft = lcl_GetValue( *m_xLeftMF, eUnit ); + long nRight = lcl_GetValue( *m_xRightMF, eUnit ); + long nWidthZoom = static_cast(m_xWidthZoomMF->get_value(FieldUnit::NONE)); + if (bZoom && nWidthZoom != 0 && ( ( ( aOrigSize.Width() - (nLeft + nRight )) * nWidthZoom ) + / 100 >= aPageSize.Width() ) ) + { + if (&rField == m_xLeftMF.get()) + { + nLeft = aOrigSize.Width() - + ( aPageSize.Width() * 100 / nWidthZoom + nRight ); + m_xLeftMF->set_value( m_xLeftMF->normalize( nLeft ), eUnit ); + } + else + { + nRight = aOrigSize.Width() - + ( aPageSize.Width() * 100 / nWidthZoom + nLeft ); + m_xRightMF->set_value( m_xRightMF->normalize( nRight ), eUnit ); + } + } + if (AllSettings::GetLayoutRTL()) + { + m_aExampleWN.SetLeft(nRight); + m_aExampleWN.SetRight(nLeft); + } + else + { + m_aExampleWN.SetLeft(nLeft); + m_aExampleWN.SetRight(nRight); + } + if(bZoom) + { + // scale stays, recompute width + ZoomHdl(*m_xWidthZoomMF); + } + } + else + { + long nTop = lcl_GetValue( *m_xTopMF, eUnit ); + long nBottom = lcl_GetValue( *m_xBottomMF, eUnit ); + long nHeightZoom = static_cast(m_xHeightZoomMF->get_value(FieldUnit::NONE)); + if(bZoom && ( ( ( aOrigSize.Height() - (nTop + nBottom )) * nHeightZoom) + / 100 >= aPageSize.Height())) + { + assert(nHeightZoom && "div-by-zero"); + if(&rField == m_xTopMF.get()) + { + nTop = aOrigSize.Height() - + ( aPageSize.Height() * 100 / nHeightZoom + nBottom); + m_xTopMF->set_value( m_xWidthMF->normalize( nTop ), eUnit ); + } + else + { + nBottom = aOrigSize.Height() - + ( aPageSize.Height() * 100 / nHeightZoom + nTop); + m_xBottomMF->set_value( m_xWidthMF->normalize( nBottom ), eUnit ); + } + } + m_aExampleWN.SetTop( nTop ); + m_aExampleWN.SetBottom( nBottom ); + if(bZoom) + { + // scale stays, recompute height + ZoomHdl(*m_xHeightZoomMF); + } + } + m_aExampleWN.Invalidate(); + // size and border changed -> recompute scale + if(!bZoom) + CalcZoom(); + CalcMinMaxBorder(); +} +/*-------------------------------------------------------------------- + description: set original size + --------------------------------------------------------------------*/ + +IMPL_LINK_NOARG(SvxGrfCropPage, OrigSizeHdl, weld::Button&, void) +{ + SfxItemPool* pPool = GetItemSet().GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( pPool->GetWhich( + SID_ATTR_GRAF_CROP ) ) ); + + long nWidth = aOrigSize.Width() - + lcl_GetValue( *m_xLeftMF, eUnit ) - + lcl_GetValue( *m_xRightMF, eUnit ); + m_xWidthMF->set_value( m_xWidthMF->normalize( nWidth ), eUnit ); + long nHeight = aOrigSize.Height() - + lcl_GetValue( *m_xTopMF, eUnit ) - + lcl_GetValue( *m_xBottomMF, eUnit ); + m_xHeightMF->set_value( m_xHeightMF->normalize( nHeight ), eUnit ); + m_xWidthZoomMF->set_value(100, FieldUnit::NONE); + m_xHeightZoomMF->set_value(100, FieldUnit::NONE); + bSetOrigSize = true; +} +/*-------------------------------------------------------------------- + description: compute scale + --------------------------------------------------------------------*/ + +void SvxGrfCropPage::CalcZoom() +{ + SfxItemPool* pPool = GetItemSet().GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( pPool->GetWhich( + SID_ATTR_GRAF_CROP ) ) ); + + long nWidth = lcl_GetValue( *m_xWidthMF, eUnit ); + long nHeight = lcl_GetValue( *m_xHeightMF, eUnit ); + long nLRBorders = lcl_GetValue( *m_xLeftMF, eUnit ) + + lcl_GetValue( *m_xRightMF, eUnit ); + long nULBorders = lcl_GetValue( *m_xTopMF, eUnit ) + + lcl_GetValue( *m_xBottomMF, eUnit ); + sal_uInt16 nZoom = 0; + long nDen; + if( (nDen = aOrigSize.Width() - nLRBorders) > 0) + nZoom = static_cast((( nWidth * 1000 / nDen )+5)/10); + m_xWidthZoomMF->set_value(nZoom, FieldUnit::NONE); + if( (nDen = aOrigSize.Height() - nULBorders) > 0) + nZoom = static_cast((( nHeight * 1000 / nDen )+5)/10); + else + nZoom = 0; + m_xHeightZoomMF->set_value(nZoom, FieldUnit::NONE); +} + +/*-------------------------------------------------------------------- + description: set minimum/maximum values for the margins + --------------------------------------------------------------------*/ + +void SvxGrfCropPage::CalcMinMaxBorder() +{ + SfxItemPool* pPool = GetItemSet().GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( pPool->GetWhich( + SID_ATTR_GRAF_CROP ) ) ); + long nR = lcl_GetValue(*m_xRightMF, eUnit ); + long nMinWidth = (aOrigSize.Width() * 10) /11; + long nMin = nMinWidth - (nR >= 0 ? nR : 0); + m_xLeftMF->set_max( m_xLeftMF->normalize(nMin), eUnit ); + + long nL = lcl_GetValue(*m_xLeftMF, eUnit ); + nMin = nMinWidth - (nL >= 0 ? nL : 0); + m_xRightMF->set_max( m_xRightMF->normalize(nMin), eUnit ); + + long nUp = lcl_GetValue( *m_xTopMF, eUnit ); + long nMinHeight = (aOrigSize.Height() * 10) /11; + nMin = nMinHeight - (nUp >= 0 ? nUp : 0); + m_xBottomMF->set_max( m_xBottomMF->normalize(nMin), eUnit ); + + long nLow = lcl_GetValue(*m_xBottomMF, eUnit ); + nMin = nMinHeight - (nLow >= 0 ? nLow : 0); + m_xTopMF->set_max( m_xTopMF->normalize(nMin), eUnit ); +} +/*-------------------------------------------------------------------- + description: set spinsize to 1/20 of the original size, + fill FixedText with the original size + --------------------------------------------------------------------*/ + +void SvxGrfCropPage::GraphicHasChanged( bool bFound ) +{ + if( bFound ) + { + SfxItemPool* pPool = GetItemSet().GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( pPool->GetWhich( + SID_ATTR_GRAF_CROP ) )); + + sal_Int64 nSpin = m_xLeftMF->normalize(aOrigSize.Width()) / 20; + nSpin = vcl::ConvertValue( nSpin, aOrigSize.Width(), 0, + eUnit, m_xLeftMF->get_unit()); + + // if the margin is too big, it is set to 1/3 on both pages + long nR = lcl_GetValue( *m_xRightMF, eUnit ); + long nL = lcl_GetValue( *m_xLeftMF, eUnit ); + if((nL + nR) < - aOrigSize.Width()) + { + long nVal = aOrigSize.Width() / -3; + m_xRightMF->set_value( m_xRightMF->normalize( nVal ), eUnit ); + m_xLeftMF->set_value( m_xLeftMF->normalize( nVal ), eUnit ); + m_aExampleWN.SetLeft(nVal); + m_aExampleWN.SetRight(nVal); + } + long nUp = lcl_GetValue(*m_xTopMF, eUnit ); + long nLow = lcl_GetValue(*m_xBottomMF, eUnit ); + if((nUp + nLow) < - aOrigSize.Height()) + { + long nVal = aOrigSize.Height() / -3; + m_xTopMF->set_value( m_xTopMF->normalize( nVal ), eUnit ); + m_xBottomMF->set_value( m_xBottomMF->normalize( nVal ), eUnit ); + m_aExampleWN.SetTop(nVal); + m_aExampleWN.SetBottom(nVal); + } + + m_xLeftMF->set_increments(nSpin, nSpin * 10, FieldUnit::NONE); + m_xRightMF->set_increments(nSpin, nSpin * 10, FieldUnit::NONE); + nSpin = m_xTopMF->normalize(aOrigSize.Height()) / 20; + nSpin = vcl::ConvertValue( nSpin, aOrigSize.Width(), 0, + eUnit, m_xLeftMF->get_unit() ); + m_xTopMF->set_increments(nSpin, nSpin * 10, FieldUnit::NONE); + m_xBottomMF->set_increments(nSpin, nSpin * 10, FieldUnit::NONE); + + // display original size + const FieldUnit eMetric = GetModuleFieldUnit( GetItemSet() ); + + OUString sTemp; + { + std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/spinbox.ui")); + std::unique_ptr xFld(xBuilder->weld_metric_spin_button("spin", FieldUnit::CM)); + SetFieldUnit( *xFld, eMetric ); + xFld->set_digits(m_xWidthMF->get_digits()); + xFld->set_max(INT_MAX - 1, FieldUnit::NONE); + + xFld->set_value(xFld->normalize(aOrigSize.Width()), eUnit); + sTemp = xFld->get_text(); + xFld->set_value(xFld->normalize(aOrigSize.Height()), eUnit); + // multiplication sign (U+00D7) + sTemp += u"\u00D7" + xFld->get_text(); + } + + if ( aOrigPixelSize.Width() && aOrigPixelSize.Height() ) { + sal_Int32 ax = sal_Int32(floor(static_cast(aOrigPixelSize.Width()) / + (static_cast(aOrigSize.Width())/TWIP_TO_INCH)+0.5)); + sal_Int32 ay = sal_Int32(floor(static_cast(aOrigPixelSize.Height()) / + (static_cast(aOrigSize.Height())/TWIP_TO_INCH)+0.5)); + sTemp += " " + CuiResId( RID_SVXSTR_PPI ); + OUString sPPI = OUString::number(ax); + if (abs(ax - ay) > 1) { + sPPI += u"\u00D7" + OUString::number(ay); + } + sTemp = sTemp.replaceAll("%1", sPPI); + } + m_xOrigSizeFT->set_label(sTemp); + } + + m_xCropFrame->set_sensitive(bFound); + m_xScaleFrame->set_sensitive(bFound); + m_xSizeFrame->set_sensitive(bFound); + m_xOrigSizeGrid->set_sensitive(bFound); + m_xZoomConstRB->set_sensitive(bFound); +} + +Size SvxGrfCropPage::GetGrfOrigSize(const Graphic& rGrf) +{ + const MapMode aMapTwip( MapUnit::MapTwip ); + Size aSize( rGrf.GetPrefSize() ); + if( MapUnit::MapPixel == rGrf.GetPrefMapMode().GetMapUnit() ) + aSize = Application::GetDefaultDevice()->PixelToLogic(aSize, aMapTwip); + else + aSize = OutputDevice::LogicToLogic( aSize, + rGrf.GetPrefMapMode(), aMapTwip ); + return aSize; +} + +/*****************************************************************/ + +SvxCropExample::SvxCropExample() + : m_aTopLeft(0, 0) + , m_aBottomRight(0, 0) +{ +} + +void SvxCropExample::SetDrawingArea(weld::DrawingArea* pDrawingArea) +{ + CustomWidgetController::SetDrawingArea(pDrawingArea); + OutputDevice& rDevice = pDrawingArea->get_ref_device(); + Size aSize(rDevice.LogicToPixel(Size(78, 78), MapMode(MapUnit::MapAppFont))); + pDrawingArea->set_size_request(aSize.Width(), aSize.Height()); + + m_aMapMode = rDevice.GetMapMode(); + m_aFrameSize = OutputDevice::LogicToLogic( + Size(CM_1_TO_TWIP / 2, CM_1_TO_TWIP / 2), + MapMode(MapUnit::MapTwip), m_aMapMode); +} + +void SvxCropExample::Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle&) +{ + rRenderContext.Push(PushFlags::MAPMODE); + rRenderContext.SetMapMode(m_aMapMode); + + // Win BG + const Size aWinSize(rRenderContext.PixelToLogic(GetOutputSizePixel())); + rRenderContext.SetLineColor(); + rRenderContext.SetFillColor(rRenderContext.GetSettings().GetStyleSettings().GetWindowColor()); + rRenderContext.DrawRect(::tools::Rectangle(Point(), aWinSize)); + + // use AA, the Graphic may be a metafile/svg and would then look ugly + rRenderContext.SetAntialiasing(AntialiasingFlags::EnableB2dDraw); + + // draw Graphic + ::tools::Rectangle aRect( + Point((aWinSize.Width() - m_aFrameSize.Width())/2, (aWinSize.Height() - m_aFrameSize.Height())/2), + m_aFrameSize); + m_aGrf.Draw(&rRenderContext, aRect.TopLeft(), aRect.GetSize()); + + // Remove one more case that uses XOR paint (RasterOp::Invert). + // Get colors and logic DashLength from settings, use equal to + // PolygonMarkerPrimitive2D, may be changed to that primitive later. + // Use this to guarantee good visibility - that was the purpose of + // the former used XOR paint. + const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer; + const Color aColA(aSvtOptionsDrawinglayer.GetStripeColorA().getBColor()); + const Color aColB(aSvtOptionsDrawinglayer.GetStripeColorB().getBColor()); + const double fStripeLength(aSvtOptionsDrawinglayer.GetStripeLength()); + const basegfx::B2DVector aDashVector(rRenderContext.GetInverseViewTransformation() * basegfx::B2DVector(fStripeLength, 0.0)); + const double fLogicDashLength(aDashVector.getX()); + + // apply current crop settings + aRect.AdjustLeft(m_aTopLeft.Y()); + aRect.AdjustTop(m_aTopLeft.X()); + aRect.AdjustRight(-m_aBottomRight.Y()); + aRect.AdjustBottom(-m_aBottomRight.X()); + + // apply dash with direct paint callbacks + basegfx::utils::applyLineDashing( + basegfx::utils::createPolygonFromRect( + basegfx::B2DRange(aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom())), + std::vector< double >(2, fLogicDashLength), + [&aColA,&rRenderContext](const basegfx::B2DPolygon& rSnippet) + { + rRenderContext.SetLineColor(aColA); + rRenderContext.DrawPolyLine(rSnippet); + }, + [&aColB,&rRenderContext](const basegfx::B2DPolygon& rSnippet) + { + rRenderContext.SetLineColor(aColB); + rRenderContext.DrawPolyLine(rSnippet); + }, + 2.0 * fLogicDashLength); + + rRenderContext.Pop(); +} + +void SvxCropExample::Resize() +{ + SetFrameSize(m_aFrameSize); +} + +void SvxCropExample::SetFrameSize( const Size& rSz ) +{ + m_aFrameSize = rSz; + if (!m_aFrameSize.Width()) + m_aFrameSize.setWidth( 1 ); + if (!m_aFrameSize.Height()) + m_aFrameSize.setHeight( 1 ); + Size aWinSize( GetOutputSizePixel() ); + Fraction aXScale( aWinSize.Width() * 4, m_aFrameSize.Width() * 5 ); + Fraction aYScale( aWinSize.Height() * 4, m_aFrameSize.Height() * 5 ); + + if( aYScale < aXScale ) + aXScale = aYScale; + + m_aMapMode.SetScaleX(aXScale); + m_aMapMode.SetScaleY(aXScale); + + Invalidate(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/labdlg.cxx b/cui/source/tabpages/labdlg.cxx new file mode 100644 index 000000000..39098871b --- /dev/null +++ b/cui/source/tabpages/labdlg.cxx @@ -0,0 +1,514 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +// define ---------------------------------------------------------------- + +#define EXT_OPTIMAL 0 +#define EXT_FROM_TOP 1 +#define EXT_FROM_LEFT 2 +#define EXT_HORIZONTAL 3 +#define EXT_VERTICAL 4 + +#define POS_TOP 0 +#define POS_MIDDLE 1 +#define POS_BOTTOM 2 + +#define BMP_CAPTTYPE_1 1 +#define BMP_CAPTTYPE_2 2 +#define BMP_CAPTTYPE_3 3 + +// static ---------------------------------------------------------------- + +const sal_uInt16 SvxCaptionTabPage::pCaptionRanges[] = +{ + SDRATTR_CAPTIONTYPE, + SDRATTR_CAPTIONFIXEDANGLE, + SDRATTR_CAPTIONANGLE, + SDRATTR_CAPTIONGAP, + SDRATTR_CAPTIONESCDIR, + SDRATTR_CAPTIONESCISREL, + SDRATTR_CAPTIONESCREL, + SDRATTR_CAPTIONESCABS, + SDRATTR_CAPTIONLINELEN, + SDRATTR_CAPTIONFITLINELEN, + 0 +}; + +SvxCaptionTabPage::SvxCaptionTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "cui/ui/calloutpage.ui", "CalloutPage", &rInAttrs) + , nCaptionType(SdrCaptionType::Type1) + , nGap(0) + , nEscDir(SdrCaptionEscDir::Horizontal) + , bEscRel(false) + , nEscAbs(0) + , nEscRel(0) + , nLineLen(0) + , bFitLineLen(false) + , nPosition(0) + , nExtension(0) + , rOutAttrs(rInAttrs) + , pView(nullptr) + , m_xMF_SPACING(m_xBuilder->weld_metric_spin_button("spacing", FieldUnit::MM)) + , m_xLB_EXTENSION(m_xBuilder->weld_combo_box("extension")) + , m_xFT_BYFT(m_xBuilder->weld_label("byft")) + , m_xMF_BY(m_xBuilder->weld_metric_spin_button("by", FieldUnit::MM)) + , m_xFT_POSITIONFT(m_xBuilder->weld_label("positionft")) + , m_xLB_POSITION(m_xBuilder->weld_combo_box("position")) + , m_xLineTypes(m_xBuilder->weld_combo_box("linetypes")) + , m_xFT_LENGTHFT(m_xBuilder->weld_label("lengthft")) + , m_xMF_LENGTH(m_xBuilder->weld_metric_spin_button("length", FieldUnit::MM)) + , m_xCB_OPTIMAL(m_xBuilder->weld_check_button("optimal")) + , m_xCT_CAPTTYPE(new ValueSet(m_xBuilder->weld_scrolled_window("valuesetwin"))) + , m_xCT_CAPTTYPEWin(new weld::CustomWeld(*m_xBuilder, "valueset", *m_xCT_CAPTTYPE)) +{ + Size aSize(m_xCT_CAPTTYPE->GetDrawingArea()->get_ref_device().LogicToPixel(Size(187, 38), MapMode(MapUnit::MapAppFont))); + m_xCT_CAPTTYPEWin->set_size_request(aSize.Width(), aSize.Height()); + + assert(m_xLB_POSITION->get_count() == 6); + for (int i = 0; i < 3; ++i) + m_aStrHorzList.push_back(m_xLB_POSITION->get_text(i)); + for (int i = 3; i < 6; ++i) + m_aStrVertList.push_back(m_xLB_POSITION->get_text(i)); + m_xLB_POSITION->clear(); + + assert(m_xLineTypes->get_count() == 3); + std::vector aLineTypes; + aLineTypes.reserve(3); + for (int i = 0; i < 3; ++i) + aLineTypes.push_back(m_xLineTypes->get_text(i)); + + static_assert(CAPTYPE_BITMAPS_COUNT == 3, "unexpected"); + m_aBmpCapTypes[0] = Image(StockImage::Yes, RID_SVXBMP_LEGTYP1); + m_aBmpCapTypes[1] = Image(StockImage::Yes, RID_SVXBMP_LEGTYP2); + m_aBmpCapTypes[2] = Image(StockImage::Yes, RID_SVXBMP_LEGTYP3); + + //------------install ValueSet-------------------------- + m_xCT_CAPTTYPE->SetStyle( m_xCT_CAPTTYPE->GetStyle() | WB_ITEMBORDER | WB_DOUBLEBORDER | WB_NAMEFIELD ); + m_xCT_CAPTTYPE->SetColCount(5);//XXX + m_xCT_CAPTTYPE->SetLineCount(1); + m_xCT_CAPTTYPE->SetSelectHdl(LINK( this, SvxCaptionTabPage, SelectCaptTypeHdl_Impl)); + + Image aImage; + m_xCT_CAPTTYPE->InsertItem(BMP_CAPTTYPE_1, aImage, aLineTypes[0]); + m_xCT_CAPTTYPE->InsertItem(BMP_CAPTTYPE_2, aImage, aLineTypes[1]); + m_xCT_CAPTTYPE->InsertItem(BMP_CAPTTYPE_3, aImage, aLineTypes[2]); + + FillValueSet(); + + m_xLB_EXTENSION->connect_changed(LINK(this, SvxCaptionTabPage, ExtensionSelectHdl_Impl)); + m_xLB_POSITION->connect_changed(LINK(this, SvxCaptionTabPage, PositionSelectHdl_Impl)); + m_xCB_OPTIMAL->connect_toggled(LINK(this, SvxCaptionTabPage, LineOptHdl_Impl)); +} + +SvxCaptionTabPage::~SvxCaptionTabPage() +{ + m_xCT_CAPTTYPEWin.reset(); + m_xCT_CAPTTYPE.reset(); +} + +void SvxCaptionTabPage::Construct() +{ + // set rectangle and working area + DBG_ASSERT( pView, "No valid View transferred!" ); +} + +bool SvxCaptionTabPage::FillItemSet( SfxItemSet* _rOutAttrs) +{ + SfxItemPool* pPool = _rOutAttrs->GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + + MapUnit eUnit; + + nCaptionType = static_cast(m_xCT_CAPTTYPE->GetSelectedItemId()-1); + + _rOutAttrs->Put( SdrCaptionTypeItem( nCaptionType ) ); + + if (m_xMF_SPACING->get_value_changed_from_saved()) + { + eUnit = pPool->GetMetric( GetWhich( SDRATTR_CAPTIONGAP ) ); + _rOutAttrs->Put( SdrCaptionGapItem( GetCoreValue(*m_xMF_SPACING, eUnit ) ) ); + } + + // special treatment!!! XXX + if( nCaptionType==SdrCaptionType::Type1 ) + { + switch( nEscDir ) + { + case SdrCaptionEscDir::Horizontal: nEscDir=SdrCaptionEscDir::Vertical;break; + case SdrCaptionEscDir::Vertical: nEscDir=SdrCaptionEscDir::Horizontal;break; + default: break; + } + } + + _rOutAttrs->Put( SdrCaptionEscDirItem( nEscDir ) ); + + bEscRel = m_xLB_POSITION->get_visible(); + _rOutAttrs->Put( SdrCaptionEscIsRelItem( bEscRel ) ); + + if( bEscRel ) + { + long nVal = 0; + + switch (m_xLB_POSITION->get_active()) + { + case POS_TOP: nVal=0;break; + case POS_MIDDLE: nVal=5000;break; + case POS_BOTTOM: nVal=10000;break; + } + _rOutAttrs->Put( SdrCaptionEscRelItem( nVal ) ); + } + else + { + if (m_xMF_BY->get_value_changed_from_saved()) + { + eUnit = pPool->GetMetric( GetWhich( SDRATTR_CAPTIONESCABS ) ); + _rOutAttrs->Put( SdrCaptionEscAbsItem( GetCoreValue(*m_xMF_BY, eUnit ) ) ); + } + } + + bFitLineLen = m_xCB_OPTIMAL->get_active(); + _rOutAttrs->Put( SdrCaptionFitLineLenItem( bFitLineLen ) ); + + if( ! bFitLineLen ) + { + if (m_xMF_LENGTH->get_value_changed_from_saved()) + { + eUnit = pPool->GetMetric( GetWhich( SDRATTR_CAPTIONLINELEN ) ); + _rOutAttrs->Put( SdrCaptionLineLenItem( GetCoreValue(*m_xMF_LENGTH, eUnit ) ) ); + } + } + +//NYI-------------the angles have to be added here!!! XXX---------------------- + + return true; +} + +void SvxCaptionTabPage::Reset( const SfxItemSet* ) +{ + + //------------set metric----------------------------- + + FieldUnit eFUnit = GetModuleFieldUnit( rOutAttrs ); + + switch ( eFUnit ) + { + case FieldUnit::CM: + case FieldUnit::M: + case FieldUnit::KM: + eFUnit = FieldUnit::MM; + break; + default: ;//prevent warning + } + SetFieldUnit( *m_xMF_SPACING, eFUnit ); + SetFieldUnit( *m_xMF_BY, eFUnit ); + SetFieldUnit( *m_xMF_LENGTH, eFUnit ); + + SfxItemPool* pPool = rOutAttrs.GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + + sal_uInt16 nWhich; + MapUnit eUnit; + + nWhich = GetWhich( SDRATTR_CAPTIONESCABS ); + eUnit = pPool->GetMetric( nWhich ); + nEscAbs = static_cast( rOutAttrs.Get( nWhich ) ).GetValue(); + SetMetricValue( *m_xMF_BY, nEscAbs, eUnit ); + nEscAbs = m_xMF_BY->get_value(FieldUnit::NONE); + + nWhich = GetWhich( SDRATTR_CAPTIONESCREL ); + nEscRel = static_cast(static_cast( rOutAttrs.Get( nWhich ) ).GetValue()); + + //------- line length ---------- + nWhich = GetWhich( SDRATTR_CAPTIONLINELEN ); + eUnit = pPool->GetMetric( nWhich ); + nLineLen = static_cast( rOutAttrs.Get( nWhich ) ).GetValue(); + SetMetricValue( *m_xMF_LENGTH, nLineLen, eUnit ); + nLineLen = m_xMF_LENGTH->get_value(FieldUnit::NONE); + + //------- distance to box ---------- + nWhich = GetWhich( SDRATTR_CAPTIONGAP ); + eUnit = pPool->GetMetric( nWhich ); + nGap = static_cast( rOutAttrs.Get( nWhich ) ).GetValue(); + SetMetricValue( *m_xMF_SPACING, nGap, eUnit ); + nGap = m_xMF_SPACING->get_value(FieldUnit::NONE); + + nCaptionType = static_cast( rOutAttrs.Get( GetWhich( SDRATTR_CAPTIONTYPE ) ) ).GetValue(); + bFitLineLen = static_cast( rOutAttrs.Get( GetWhich( SDRATTR_CAPTIONFITLINELEN ) ) ).GetValue(); + nEscDir = static_cast( rOutAttrs.Get( GetWhich( SDRATTR_CAPTIONESCDIR ) ) ).GetValue(); + bEscRel = static_cast( rOutAttrs.Get( GetWhich( SDRATTR_CAPTIONESCISREL ) ) ).GetValue(); + + // special treatment!!! XXX + if( nCaptionType==SdrCaptionType::Type1 ) + { + switch( nEscDir ) + { + case SdrCaptionEscDir::Horizontal: nEscDir=SdrCaptionEscDir::Vertical;break; + case SdrCaptionEscDir::Vertical: nEscDir=SdrCaptionEscDir::Horizontal;break; + default: break; + } + } + + nPosition = POS_MIDDLE; + nExtension = EXT_OPTIMAL; + + m_xMF_SPACING->set_value(nGap, FieldUnit::NONE); + + if( nEscDir == SdrCaptionEscDir::Horizontal ) + { + if( bEscRel ) + { + if( nEscRel < 3333 ) + nPosition = POS_TOP; + if( nEscRel > 6666 ) + nPosition = POS_BOTTOM; + nExtension = EXT_HORIZONTAL; + } + else + { + nExtension = EXT_FROM_TOP; + m_xMF_BY->set_value(nEscAbs, FieldUnit::NONE); + } + } + else if( nEscDir == SdrCaptionEscDir::Vertical ) + { + if( bEscRel ) + { + if( nEscRel < 3333 ) + nPosition = POS_TOP; + if( nEscRel > 6666 ) + nPosition = POS_BOTTOM; + nExtension = EXT_VERTICAL; + } + else + { + nExtension = EXT_FROM_LEFT; + m_xMF_BY->set_value(nEscAbs, FieldUnit::NONE); + } + } + else if( nEscDir == SdrCaptionEscDir::BestFit ) + { + nExtension = EXT_OPTIMAL; + } + + m_xCB_OPTIMAL->set_active(bFitLineLen); + m_xMF_LENGTH->set_value(nLineLen, FieldUnit::NONE); + + m_xLB_EXTENSION->set_active(nExtension); + + SetupExtension_Impl( nExtension ); + m_xCT_CAPTTYPE->SelectItem( static_cast(nCaptionType)+1 ); // Enum starts at 0! + SetupType_Impl( nCaptionType ); +} + +std::unique_ptr SvxCaptionTabPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rOutAttrs) +{ + return std::make_unique(pPage, pController, *rOutAttrs); +} + +void SvxCaptionTabPage::SetupExtension_Impl( sal_uInt16 nType ) +{ + switch( nType ) + { + case EXT_OPTIMAL: + m_xMF_BY->show(); + m_xFT_BYFT->show(); + m_xFT_POSITIONFT->hide(); + m_xLB_POSITION->hide(); + nEscDir = SdrCaptionEscDir::BestFit; + break; + + case EXT_FROM_TOP: + m_xMF_BY->show(); + m_xFT_BYFT->show(); + m_xFT_POSITIONFT->hide(); + m_xLB_POSITION->hide(); + nEscDir = SdrCaptionEscDir::Horizontal; + break; + + case EXT_FROM_LEFT: + m_xMF_BY->show(); + m_xFT_BYFT->show(); + m_xFT_POSITIONFT->hide(); + m_xLB_POSITION->hide(); + nEscDir = SdrCaptionEscDir::Vertical; + break; + + case EXT_HORIZONTAL: + m_xLB_POSITION->clear(); + for (const OUString & i : m_aStrHorzList) + m_xLB_POSITION->append_text(i); + m_xLB_POSITION->set_active(nPosition); + + m_xMF_BY->hide(); + m_xFT_BYFT->hide(); + m_xFT_POSITIONFT->show(); + m_xLB_POSITION->show(); + nEscDir = SdrCaptionEscDir::Horizontal; + break; + + case EXT_VERTICAL: + m_xLB_POSITION->clear(); + for (const OUString & i : m_aStrVertList) + m_xLB_POSITION->append_text(i); + m_xLB_POSITION->set_active(nPosition); + + m_xMF_BY->hide(); + m_xFT_BYFT->hide(); + m_xFT_POSITIONFT->show(); + m_xLB_POSITION->show(); + nEscDir = SdrCaptionEscDir::Vertical; + break; + } +} + +IMPL_LINK(SvxCaptionTabPage, ExtensionSelectHdl_Impl, weld::ComboBox&, rListBox, void) +{ + if (&rListBox == m_xLB_EXTENSION.get()) + { + SetupExtension_Impl(m_xLB_EXTENSION->get_active()); + } +} + +IMPL_LINK(SvxCaptionTabPage, PositionSelectHdl_Impl, weld::ComboBox&, rListBox, void) +{ + if (&rListBox == m_xLB_POSITION.get()) + { + nPosition = m_xLB_POSITION->get_active(); + } +} + +IMPL_LINK( SvxCaptionTabPage, LineOptHdl_Impl, weld::ToggleButton&, rButton, void ) +{ + if (&rButton != m_xCB_OPTIMAL.get()) + return; + + if (m_xCB_OPTIMAL->get_active() || !m_xCB_OPTIMAL->get_sensitive()) + { + m_xFT_LENGTHFT->set_sensitive(false); + m_xMF_LENGTH->set_sensitive(false); + } + else + { + m_xFT_LENGTHFT->set_sensitive(true); + m_xMF_LENGTH->set_sensitive(true); + } +} + +IMPL_LINK_NOARG(SvxCaptionTabPage, SelectCaptTypeHdl_Impl, ValueSet*, void) +{ + SetupType_Impl( static_cast(m_xCT_CAPTTYPE->GetSelectedItemId()) ); +} + +void SvxCaptionTabPage::SetupType_Impl( SdrCaptionType nType ) +{ + switch( nType ) + { + case SdrCaptionType::Type1: + case SdrCaptionType::Type2: + m_xFT_LENGTHFT->set_sensitive(false); + m_xCB_OPTIMAL->set_sensitive(false); + LineOptHdl_Impl(*m_xCB_OPTIMAL); + break; + case SdrCaptionType::Type3: + case SdrCaptionType::Type4: + m_xFT_LENGTHFT->set_sensitive(true); + m_xCB_OPTIMAL->set_sensitive(true); + LineOptHdl_Impl(*m_xCB_OPTIMAL); + break; + } +} + +void SvxCaptionTabPage::FillValueSet() +{ + m_xCT_CAPTTYPE->SetItemImage(BMP_CAPTTYPE_1, m_aBmpCapTypes[0] ); + m_xCT_CAPTTYPE->SetItemImage(BMP_CAPTTYPE_2, m_aBmpCapTypes[1] ); + m_xCT_CAPTTYPE->SetItemImage(BMP_CAPTTYPE_3, m_aBmpCapTypes[2] ); +} + +SvxCaptionTabDialog::SvxCaptionTabDialog(weld::Window* pParent, const SdrView* pSdrView, + SvxAnchorIds nAnchorTypes) + : SfxTabDialogController(pParent, "cui/ui/calloutdialog.ui", "CalloutDialog") + , pView(pSdrView) + , nAnchorCtrls(nAnchorTypes) +{ + assert(pView); // No valid View transferred! + + //different positioning page in Writer + if (nAnchorCtrls & (SvxAnchorIds::Paragraph | SvxAnchorIds::Character | SvxAnchorIds::Page | SvxAnchorIds::Fly)) + { + AddTabPage("RID_SVXPAGE_SWPOSSIZE", SvxSwPosSizeTabPage::Create, + SvxSwPosSizeTabPage::GetRanges ); + RemoveTabPage("RID_SVXPAGE_POSITION_SIZE"); + } + else + { + AddTabPage("RID_SVXPAGE_POSITION_SIZE", SvxPositionSizeTabPage::Create, + SvxPositionSizeTabPage::GetRanges ); + RemoveTabPage("RID_SVXPAGE_SWPOSSIZE"); + } + AddTabPage("RID_SVXPAGE_CAPTION", SvxCaptionTabPage::Create, + SvxCaptionTabPage::GetRanges ); +} + +void SvxCaptionTabDialog::PageCreated(const OString& rId, SfxTabPage &rPage) +{ + if (rId == "RID_SVXPAGE_POSITION_SIZE") + { + static_cast( rPage ).SetView( pView ); + static_cast( rPage ).Construct(); + if( nAnchorCtrls & SvxAnchorIds::NoResize ) + static_cast( rPage ).DisableResize(); + + if( nAnchorCtrls & SvxAnchorIds::NoProtect ) + static_cast( rPage ).DisableProtect(); + } + else if (rId == "RID_SVXPAGE_SWPOSSIZE") + { + SvxSwPosSizeTabPage& rSwPage = static_cast(rPage); + rSwPage.EnableAnchorTypes(nAnchorCtrls); + rSwPage.SetValidateFramePosLink( aValidateLink ); + } + else if (rId == "RID_SVXPAGE_CAPTION") + { + static_cast( rPage ).SetView( pView ); + static_cast( rPage ).Construct(); + } +} + +void SvxCaptionTabDialog::SetValidateFramePosLink( const Link& rLink ) +{ + aValidateLink = rLink; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/macroass.cxx b/cui/source/tabpages/macroass.cxx new file mode 100644 index 000000000..df3e47bf4 --- /dev/null +++ b/cui/source/tabpages/macroass.cxx @@ -0,0 +1,389 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::frame::XFrame; + +class SfxMacroTabPage_Impl +{ +public: + SfxMacroTabPage_Impl(); + + OUString m_aStaticMacroLBLabel; + std::unique_ptr m_xAssignPB; + std::unique_ptr m_xDeletePB; + std::unique_ptr m_xEventLB; + std::unique_ptr m_xGroupFrame; + std::unique_ptr m_xGroupLB; + std::unique_ptr m_xMacroFrame; + std::unique_ptr m_xMacroLB; + + Idle m_aFillGroupIdle; + bool m_bGotEvents; +}; + +SfxMacroTabPage_Impl::SfxMacroTabPage_Impl() + : m_bGotEvents(false) +{ +} + +static sal_uInt16 aPageRg[] = { + SID_ATTR_MACROITEM, SID_ATTR_MACROITEM, + 0 +}; + +static OUString ConvertToUIName_Impl( SvxMacro const *pMacro ) +{ + OUString aName( pMacro->GetMacName() ); + if ( pMacro->GetLanguage() != "JavaScript" ) + { + const sal_Int32 nCount = comphelper::string::getTokenCount(aName, '.'); + OUString aEntry = aName.getToken( nCount-1, '.' ); + if ( nCount > 2 ) + { + aEntry += "(" + aName.getToken( 0, '.' ) + "." + aName.getToken( nCount-2, '.' ) + ")"; + } + return aEntry; + } + else + return aName; +} + +void SfxMacroTabPage::EnableButtons() +{ + // don't do anything as long as the eventbox is empty + weld::TreeView& rTreeView = mpImpl->m_xEventLB->GetListBox(); + int nSelected = rTreeView.get_selected_index(); + if (nSelected != -1) + { + // get bound macro + const SvxMacro* pM = aTbl.Get(static_cast(rTreeView.get_selected_id().toInt32())); + mpImpl->m_xDeletePB->set_sensitive(nullptr != pM); + + OUString sEventMacro = rTreeView.get_text(nSelected, 1); + + OUString sScriptURI = mpImpl->m_xMacroLB->GetSelectedScriptURI(); + mpImpl->m_xAssignPB->set_sensitive(!sScriptURI.equalsIgnoreAsciiCase(sEventMacro)); + } + else + mpImpl->m_xAssignPB->set_sensitive(false); +} + +SfxMacroTabPage::SfxMacroTabPage(weld::Container* pPage, weld::DialogController* pController, const Reference< XFrame >& rxDocumentFrame, const SfxItemSet& rAttrSet ) + : SfxTabPage(pPage, pController, "cui/ui/eventassignpage.ui", "EventAssignPage", &rAttrSet) +{ + mpImpl.reset(new SfxMacroTabPage_Impl); + + mpImpl->m_aFillGroupIdle.SetInvokeHandler( LINK( this, SfxMacroTabPage, TimeOut_Impl ) ); + mpImpl->m_aFillGroupIdle.SetPriority( TaskPriority::HIGHEST ); + mpImpl->m_aFillGroupIdle.SetDebugName( "SfxMacroTabPage m_aFillGroupIdle" ); + + mpImpl->m_xEventLB.reset(new MacroEventListBox(m_xBuilder->weld_tree_view("assignments"))); + mpImpl->m_xAssignPB = m_xBuilder->weld_button("assign"); + mpImpl->m_xDeletePB = m_xBuilder->weld_button("delete"); + mpImpl->m_xGroupFrame = m_xBuilder->weld_widget("groupframe"); + mpImpl->m_xGroupLB.reset(new CuiConfigGroupListBox(m_xBuilder->weld_tree_view("libraries"))); + mpImpl->m_xMacroFrame = m_xBuilder->weld_frame("macroframe"); + mpImpl->m_aStaticMacroLBLabel = mpImpl->m_xMacroFrame->get_label(); + mpImpl->m_xMacroLB.reset(new CuiConfigFunctionListBox(m_xBuilder->weld_tree_view("macros"))); + + SetFrame( rxDocumentFrame ); + + InitAndSetHandler(); + + ScriptChanged(); +} + +SfxMacroTabPage::~SfxMacroTabPage() +{ + mpImpl.reset(); +} + +void SfxMacroTabPage::AddEvent(const OUString& rEventName, SvMacroItemId nEventId) +{ + weld::TreeView& rTreeView = mpImpl->m_xEventLB->GetListBox(); + rTreeView.append(OUString::number(static_cast(nEventId)), rEventName); + + // if the table is valid already + SvxMacro* pM = aTbl.Get(nEventId); + if (pM) + { + OUString sNew(ConvertToUIName_Impl(pM)); + rTreeView.set_text(rTreeView.n_children() - 1, sNew, 1); + } +} + +void SfxMacroTabPage::ScriptChanged() +{ + // get new areas and their functions + mpImpl->m_xGroupFrame->show(); + mpImpl->m_xMacroFrame->show(); + + EnableButtons(); +} + +bool SfxMacroTabPage::FillItemSet( SfxItemSet* rSet ) +{ + SvxMacroItem aItem( GetWhich( aPageRg[0] ) ); + const_cast(aItem.GetMacroTable()) = aTbl; + + const SfxPoolItem* pItem; + if( SfxItemState::SET != GetItemSet().GetItemState( aItem.Which(), true, &pItem ) + || aItem != *static_cast(pItem) ) + { + rSet->Put( aItem ); + return true; + } + return false; +} + +void SfxMacroTabPage::LaunchFillGroup() +{ + if (! mpImpl->m_aFillGroupIdle.IsActive() ) + mpImpl->m_aFillGroupIdle.Start(); +} + +void SfxMacroTabPage::ActivatePage( const SfxItemSet& ) +{ + LaunchFillGroup(); +} + +void SfxMacroTabPage::PageCreated(const SfxAllItemSet& aSet) +{ + const SfxPoolItem* pEventsItem; + if( !mpImpl->m_bGotEvents && SfxItemState::SET == aSet.GetItemState( SID_EVENTCONFIG, true, &pEventsItem ) ) + { + mpImpl->m_bGotEvents = true; + const SfxEventNamesList& rList = static_cast(pEventsItem)->GetEvents(); + for ( size_t nNo = 0, nCnt = rList.size(); nNo < nCnt; ++nNo ) + { + const SfxEventName &rOwn = rList.at(nNo); + AddEvent( rOwn.maUIName, rOwn.mnId ); + } + } +} + +void SfxMacroTabPage::Reset( const SfxItemSet* rSet ) +{ + const SfxPoolItem* pItem; + if( SfxItemState::SET == rSet->GetItemState( GetWhich( aPageRg[0] ), true, &pItem )) + aTbl = static_cast(pItem)->GetMacroTable(); + + const SfxPoolItem* pEventsItem; + if( !mpImpl->m_bGotEvents && SfxItemState::SET == rSet->GetItemState( SID_EVENTCONFIG, true, &pEventsItem ) ) + { + mpImpl->m_bGotEvents = true; + const SfxEventNamesList& rList = static_cast(pEventsItem)->GetEvents(); + for ( size_t nNo = 0, nCnt = rList.size(); nNo < nCnt; ++nNo ) + { + const SfxEventName &rOwn = rList.at(nNo); + AddEvent( rOwn.maUIName, rOwn.mnId ); + } + } + + FillEvents(); + + weld::TreeView& rListBox = mpImpl->m_xEventLB->GetListBox(); + std::unique_ptr xIter(rListBox.make_iterator()); + if (rListBox.get_iter_first(*xIter)) + rListBox.set_cursor(*xIter); +} + +bool SfxMacroTabPage::IsReadOnly() const +{ + return false; +} + +IMPL_LINK_NOARG(SfxMacroTabPage, SelectEvent_Impl, weld::TreeView&, void) +{ + weld::TreeView& rListBox = mpImpl->m_xEventLB->GetListBox(); + int nSelected = rListBox.get_selected_index(); + if (nSelected == -1) + { + DBG_ASSERT(nSelected != -1, "Where does the empty entry come from?"); + return; + } + + ScriptChanged(); + EnableButtons(); +} + +IMPL_LINK_NOARG(SfxMacroTabPage, SelectGroup_Impl, weld::TreeView&, void) +{ + mpImpl->m_xGroupLB->GroupSelected(); + const OUString sScriptURI = mpImpl->m_xMacroLB->GetSelectedScriptURI(); + OUString aLabelText; + if( !sScriptURI.isEmpty() ) + aLabelText = mpImpl->m_aStaticMacroLBLabel; + mpImpl->m_xMacroFrame->set_label( aLabelText ); + + EnableButtons(); +} + +IMPL_LINK_NOARG(SfxMacroTabPage, SelectMacro_Impl, weld::TreeView&, void) +{ + EnableButtons(); +} + +IMPL_LINK(SfxMacroTabPage, AssignDeleteClickHdl_Impl, weld::Button&, rBtn, void) +{ + AssignDeleteHdl(&rBtn); +} + +IMPL_LINK(SfxMacroTabPage, AssignDeleteHdl_Impl, weld::TreeView&, rBtn, bool) +{ + AssignDeleteHdl(&rBtn); + return true; +} + +void SfxMacroTabPage::AssignDeleteHdl(const weld::Widget* pBtn) +{ + weld::TreeView& rListBox = mpImpl->m_xEventLB->GetListBox(); + int nSelected = rListBox.get_selected_index(); + if (nSelected == -1) + { + DBG_ASSERT(nSelected != -1, "Where does the empty entry come from?"); + return; + } + + const bool bAssEnabled = pBtn != mpImpl->m_xDeletePB.get() && mpImpl->m_xAssignPB->get_sensitive(); + + // remove from the table + SvMacroItemId nEvent = static_cast(rListBox.get_selected_id().toInt32()); + aTbl.Erase( nEvent ); + + OUString sScriptURI; + if( bAssEnabled ) + { + sScriptURI = mpImpl->m_xMacroLB->GetSelectedScriptURI(); + if( sScriptURI.startsWith( "vnd.sun.star.script:" ) ) + { + aTbl.Insert( + nEvent, SvxMacro( sScriptURI, SVX_MACRO_LANGUAGE_SF ) ); + } + else + { + OSL_ENSURE( false, "SfxMacroTabPage::AssignDeleteHdl_Impl: this branch is *not* dead? (out of interest: tell fs, please!)" ); + aTbl.Insert( + nEvent, SvxMacro( sScriptURI, SVX_MACRO_LANGUAGE_STARBASIC ) ); + } + } + + rListBox.set_text(nSelected, sScriptURI, 1); + + EnableButtons(); +} + +IMPL_LINK( SfxMacroTabPage, TimeOut_Impl, Timer*,, void ) +{ + // FillMacroList() can take a long time -> show wait cursor and disable input + weld::Window* pDialog = GetFrameWeld(); + // perhaps the tabpage is part of a SingleTabDialog then pDialog == nullptr + std::unique_ptr xWait(pDialog ? new weld::WaitObject(pDialog) : nullptr); + // fill macro list + mpImpl->m_xGroupLB->Init(comphelper::getProcessComponentContext(), GetFrame(), + OUString(), false); +} + +void SfxMacroTabPage::InitAndSetHandler() +{ + weld::TreeView& rListBox = mpImpl->m_xEventLB->GetListBox(); + Link aLnk(LINK(this, SfxMacroTabPage, AssignDeleteHdl_Impl)); + mpImpl->m_xMacroLB->connect_row_activated( aLnk); + mpImpl->m_xDeletePB->connect_clicked(LINK(this, SfxMacroTabPage, AssignDeleteClickHdl_Impl)); + mpImpl->m_xAssignPB->connect_clicked(LINK(this, SfxMacroTabPage, AssignDeleteClickHdl_Impl)); + rListBox.connect_row_activated(aLnk); + + rListBox.connect_changed(LINK(this, SfxMacroTabPage, SelectEvent_Impl)); + mpImpl->m_xGroupLB->connect_changed(LINK(this, SfxMacroTabPage, SelectGroup_Impl)); + mpImpl->m_xMacroLB->connect_changed(LINK(this, SfxMacroTabPage, SelectMacro_Impl)); + + std::vector aWidths; + aWidths.push_back(rListBox.get_approximate_digit_width() * 35); + rListBox.set_column_fixed_widths(aWidths); + + mpImpl->m_xEventLB->show(); + + mpImpl->m_xEventLB->set_sensitive(true); + mpImpl->m_xGroupLB->set_sensitive(true); + mpImpl->m_xMacroLB->set_sensitive(true); + + mpImpl->m_xGroupLB->SetFunctionListBox(mpImpl->m_xMacroLB.get()); +} + +void SfxMacroTabPage::FillEvents() +{ + weld::TreeView& rListBox = mpImpl->m_xEventLB->GetListBox(); + + int nEntryCnt = rListBox.n_children(); + + // get events from the table and fill the EventListBox respectively + for (int n = 0 ; n < nEntryCnt; ++n) + { + OUString sOld = rListBox.get_text(n, 1); + OUString sNew; + SvMacroItemId nEventId = static_cast(rListBox.get_id(n).toInt32()); + if (aTbl.IsKeyValid(nEventId)) + sNew = ConvertToUIName_Impl(aTbl.Get(nEventId)); + + if (sOld == sNew) + continue; + + rListBox.set_text(n, sNew, 1); + } +} + +namespace +{ + std::unique_ptr CreateSfxMacroTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rAttrSet) + { + return std::make_unique( pPage, pController, nullptr, rAttrSet ); + } +} + +std::unique_ptr SfxMacroTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet) +{ + return CreateSfxMacroTabPage(pPage, pController, *rAttrSet); +} + +SfxMacroAssignDlg::SfxMacroAssignDlg(weld::Widget* pParent, + const Reference< XFrame >& rxDocumentFrame, const SfxItemSet& rSet) + : SfxSingleTabDialogController(pParent, &rSet,"cui/ui/eventassigndialog.ui", + "EventAssignDialog") +{ + std::unique_ptr xPage = CreateSfxMacroTabPage(get_content_area(), this, rSet); + xPage->SetFrame(rxDocumentFrame); + SetTabPage(std::move(xPage)); + GetTabPage()->LaunchFillGroup(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/measure.cxx b/cui/source/tabpages/measure.cxx new file mode 100644 index 000000000..e7a7fbe12 --- /dev/null +++ b/cui/source/tabpages/measure.cxx @@ -0,0 +1,754 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +const sal_uInt16 SvxMeasurePage::pRanges[] = +{ + SDRATTR_MEASURE_FIRST, + SDRATTR_MEASURE_LAST, + 0 +}; + +/************************************************************************* +|* +|* Dialog to change measure-attributes +|* +\************************************************************************/ +SvxMeasureDialog::SvxMeasureDialog(weld::Window* pParent, const SfxItemSet& rInAttrs, + const SdrView* pSdrView) + : SfxSingleTabDialogController(pParent, &rInAttrs) +{ + auto xPage = std::make_unique(get_content_area(), this, rInAttrs); + + xPage->SetView(pSdrView); + xPage->Construct(); + + SetTabPage(std::move(xPage)); + m_xDialog->set_title(CuiResId(RID_SVXSTR_DIMENSION_LINE)); +} + +/************************************************************************* +|* +|* Tabpage for changing measure-attributes +|* +\************************************************************************/ + +SvxMeasurePage::SvxMeasurePage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SvxTabPage(pPage, pController, "cui/ui/dimensionlinestabpage.ui", "DimensionLinesTabPage", rInAttrs) + , rOutAttrs(rInAttrs) + , aAttrSet(*rInAttrs.GetPool()) + , pView(nullptr) + , eUnit(MapUnit::Map100thMM) + , bPositionModified(false) + , m_aCtlPosition(this) + , m_xMtrFldLineDist(m_xBuilder->weld_metric_spin_button("MTR_LINE_DIST", FieldUnit::MM)) + , m_xMtrFldHelplineOverhang(m_xBuilder->weld_metric_spin_button("MTR_FLD_HELPLINE_OVERHANG", FieldUnit::MM)) + , m_xMtrFldHelplineDist(m_xBuilder->weld_metric_spin_button("MTR_FLD_HELPLINE_DIST", FieldUnit::MM)) + , m_xMtrFldHelpline1Len(m_xBuilder->weld_metric_spin_button("MTR_FLD_HELPLINE1_LEN", FieldUnit::MM)) + , m_xMtrFldHelpline2Len(m_xBuilder->weld_metric_spin_button("MTR_FLD_HELPLINE2_LEN", FieldUnit::MM)) + , m_xTsbBelowRefEdge(m_xBuilder->weld_check_button("TSB_BELOW_REF_EDGE")) + , m_xMtrFldDecimalPlaces(m_xBuilder->weld_spin_button("MTR_FLD_DECIMALPLACES")) + , m_xTsbAutoPosV(m_xBuilder->weld_check_button("TSB_AUTOPOSV")) + , m_xTsbAutoPosH(m_xBuilder->weld_check_button("TSB_AUTOPOSH")) + , m_xTsbShowUnit(m_xBuilder->weld_check_button("TSB_SHOW_UNIT")) + , m_xLbUnit(m_xBuilder->weld_combo_box("LB_UNIT")) + , m_xTsbParallel(m_xBuilder->weld_check_button("TSB_PARALLEL")) + , m_xFtAutomatic(m_xBuilder->weld_label("STR_MEASURE_AUTOMATIC")) + , m_xCtlPosition(new weld::CustomWeld(*m_xBuilder, "CTL_POSITION", m_aCtlPosition)) + , m_xCtlPreview(new weld::CustomWeld(*m_xBuilder, "CTL_PREVIEW", m_aCtlPreview)) +{ + m_aCtlPreview.SetAttributes(rInAttrs); + + FillUnitLB(); + + const FieldUnit eFUnit = GetModuleFieldUnit( rInAttrs ); + SetFieldUnit( *m_xMtrFldLineDist, eFUnit ); + SetFieldUnit( *m_xMtrFldHelplineOverhang, eFUnit ); + SetFieldUnit( *m_xMtrFldHelplineDist, eFUnit ); + SetFieldUnit( *m_xMtrFldHelpline1Len, eFUnit ); + SetFieldUnit( *m_xMtrFldHelpline2Len, eFUnit ); + if( eFUnit == FieldUnit::MM ) + { + m_xMtrFldLineDist->set_increments(50, 500, FieldUnit::NONE); + m_xMtrFldHelplineOverhang->set_increments(50, 500, FieldUnit::NONE); + m_xMtrFldHelplineDist->set_increments(50, 500, FieldUnit::NONE); + m_xMtrFldHelpline1Len->set_increments(50, 500, FieldUnit::NONE); + m_xMtrFldHelpline2Len->set_increments(50, 500, FieldUnit::NONE); + } + + m_xTsbAutoPosV->connect_toggled(LINK( this, SvxMeasurePage, ClickAutoPosHdl_Impl)); + m_xTsbAutoPosH->connect_toggled(LINK(this, SvxMeasurePage, ClickAutoPosHdl_Impl)); + + Link aLink(LINK(this, SvxMeasurePage, ChangeAttrEditHdl_Impl)); + m_xMtrFldLineDist->connect_value_changed(aLink); + m_xMtrFldHelplineOverhang->connect_value_changed(aLink); + m_xMtrFldHelplineDist->connect_value_changed(aLink); + m_xMtrFldHelpline1Len->connect_value_changed(aLink); + m_xMtrFldHelpline2Len->connect_value_changed(aLink); + m_xMtrFldDecimalPlaces->connect_value_changed(LINK(this, SvxMeasurePage, ChangeAttrSpinHdl_Impl)); + m_xTsbBelowRefEdge->connect_toggled(LINK(this, SvxMeasurePage, ChangeAttrClickHdl_Impl)); + m_xTsbParallel->connect_toggled( LINK( this, SvxMeasurePage, ChangeAttrClickHdl_Impl)); + m_xTsbShowUnit->connect_toggled(LINK(this, SvxMeasurePage, ChangeAttrClickHdl_Impl)); + m_xLbUnit->connect_changed(LINK(this, SvxMeasurePage, ChangeAttrListBoxHdl_Impl)); +} + +SvxMeasurePage::~SvxMeasurePage() +{ + m_xCtlPreview.reset(); + m_xCtlPosition.reset(); +} + +/************************************************************************* +|* +|* read the delivered Item-Set +|* +\************************************************************************/ + +void SvxMeasurePage::Reset( const SfxItemSet* rAttrs ) +{ + SfxItemPool* pPool = rAttrs->GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + eUnit = pPool->GetMetric( SDRATTR_MEASURELINEDIST ); + + const SfxPoolItem* pItem = GetItem( *rAttrs, SDRATTR_MEASURELINEDIST ); + + // SdrMeasureLineDistItem + if( pItem == nullptr ) + pItem = &pPool->GetDefaultItem( SDRATTR_MEASURELINEDIST ); + SetMetricValue(*m_xMtrFldLineDist, static_cast(pItem)->GetValue(), eUnit); + m_xMtrFldLineDist->save_value(); + + // SdrMeasureHelplineOverhangItem + pItem = GetItem( *rAttrs, SDRATTR_MEASUREHELPLINEOVERHANG ); + if( pItem == nullptr ) + pItem = &pPool->GetDefaultItem( SDRATTR_MEASUREHELPLINEOVERHANG ); + SetMetricValue(*m_xMtrFldHelplineOverhang, static_cast(pItem)->GetValue(), + eUnit); + m_xMtrFldHelplineOverhang->save_value(); + + // SdrMeasureHelplineDistItem + pItem = GetItem( *rAttrs, SDRATTR_MEASUREHELPLINEDIST ); + if( pItem == nullptr ) + pItem = &pPool->GetDefaultItem( SDRATTR_MEASUREHELPLINEDIST ); + SetMetricValue(*m_xMtrFldHelplineDist, static_cast(pItem)->GetValue(), + eUnit); + m_xMtrFldHelplineDist->save_value(); + + // SdrMeasureHelpline1LenItem + pItem = GetItem( *rAttrs, SDRATTR_MEASUREHELPLINE1LEN ); + if( pItem == nullptr ) + pItem = &pPool->GetDefaultItem( SDRATTR_MEASUREHELPLINE1LEN ); + SetMetricValue(*m_xMtrFldHelpline1Len, static_cast(pItem)->GetValue(), + eUnit); + m_xMtrFldHelpline1Len->save_value(); + + // SdrMeasureHelpline2LenItem + pItem = GetItem( *rAttrs, SDRATTR_MEASUREHELPLINE2LEN ); + if( pItem == nullptr ) + pItem = &pPool->GetDefaultItem( SDRATTR_MEASUREHELPLINE2LEN ); + SetMetricValue(*m_xMtrFldHelpline2Len, static_cast(pItem)->GetValue(), + eUnit); + m_xMtrFldHelpline2Len->save_value(); + + // SdrMeasureBelowRefEdgeItem + if( rAttrs->GetItemState( SDRATTR_MEASUREBELOWREFEDGE ) != SfxItemState::DONTCARE ) + { + m_xTsbBelowRefEdge->set_state( rAttrs->Get( SDRATTR_MEASUREBELOWREFEDGE ). + GetValue() ? TRISTATE_TRUE : TRISTATE_FALSE ); + } + else + { + m_xTsbBelowRefEdge->set_state( TRISTATE_INDET ); + } + m_xTsbBelowRefEdge->save_state(); + + // SdrMeasureDecimalPlacesItem + pItem = GetItem( *rAttrs, SDRATTR_MEASUREDECIMALPLACES ); + if( pItem == nullptr ) + pItem = &pPool->GetDefaultItem( SDRATTR_MEASUREDECIMALPLACES ); + m_xMtrFldDecimalPlaces->set_value( + static_cast(pItem)->GetValue()); + m_xMtrFldDecimalPlaces->save_value(); + + // SdrMeasureTextRota90Item + // Attention: negate ! + if( rAttrs->GetItemState( SDRATTR_MEASURETEXTROTA90 ) != SfxItemState::DONTCARE ) + { + m_xTsbParallel->set_state( rAttrs->Get( SDRATTR_MEASURETEXTROTA90 ). + GetValue() ? TRISTATE_FALSE : TRISTATE_TRUE ); + } + else + { + m_xTsbParallel->set_state( TRISTATE_INDET ); + } + m_xTsbParallel->save_state(); + + // SdrMeasureShowUnitItem + if( rAttrs->GetItemState( SDRATTR_MEASURESHOWUNIT ) != SfxItemState::DONTCARE ) + { + m_xTsbShowUnit->set_state( rAttrs->Get( SDRATTR_MEASURESHOWUNIT ). + GetValue() ? TRISTATE_TRUE : TRISTATE_FALSE ); + } + else + { + m_xTsbShowUnit->set_state( TRISTATE_INDET ); + } + m_xTsbShowUnit->save_state(); + + // SdrMeasureUnitItem + if( rAttrs->GetItemState( SDRATTR_MEASUREUNIT ) != SfxItemState::DONTCARE ) + { + long nFieldUnit = static_cast(rAttrs->Get( SDRATTR_MEASUREUNIT ).GetValue()); + + for (sal_Int32 i = 0; i < m_xLbUnit->get_count(); ++i) + { + if (m_xLbUnit->get_id(i).toInt32() == nFieldUnit) + { + m_xLbUnit->set_active(i); + break; + } + } + } + else + { + m_xLbUnit->set_active(-1); + } + m_xLbUnit->save_value(); + + // Position + if ( rAttrs->GetItemState( SDRATTR_MEASURETEXTVPOS ) != SfxItemState::DONTCARE ) + { + css::drawing::MeasureTextVertPos eVPos = + rAttrs->Get( SDRATTR_MEASURETEXTVPOS ).GetValue(); + { + if ( rAttrs->GetItemState( SDRATTR_MEASURETEXTHPOS ) != SfxItemState::DONTCARE ) + { + css::drawing::MeasureTextHorzPos eHPos = + rAttrs->Get( SDRATTR_MEASURETEXTHPOS ).GetValue(); + RectPoint eRP = RectPoint::MM; + switch( eVPos ) + { + case css::drawing::MeasureTextVertPos_EAST: + switch( eHPos ) + { + case css::drawing::MeasureTextHorzPos_LEFTOUTSIDE: eRP = RectPoint::LT; break; + case css::drawing::MeasureTextHorzPos_INSIDE: eRP = RectPoint::MT; break; + case css::drawing::MeasureTextHorzPos_RIGHTOUTSIDE: eRP = RectPoint::RT; break; + case css::drawing::MeasureTextHorzPos_AUTO: eRP = RectPoint::MT; break; + default: break; + } + break; + case css::drawing::MeasureTextVertPos_CENTERED: + switch( eHPos ) + { + case css::drawing::MeasureTextHorzPos_LEFTOUTSIDE: eRP = RectPoint::LM; break; + case css::drawing::MeasureTextHorzPos_INSIDE: eRP = RectPoint::MM; break; + case css::drawing::MeasureTextHorzPos_RIGHTOUTSIDE: eRP = RectPoint::RM; break; + case css::drawing::MeasureTextHorzPos_AUTO: eRP = RectPoint::MM; break; + default: break; + } + break; + case css::drawing::MeasureTextVertPos_WEST: + switch( eHPos ) + { + case css::drawing::MeasureTextHorzPos_LEFTOUTSIDE: eRP = RectPoint::LB; break; + case css::drawing::MeasureTextHorzPos_INSIDE: eRP = RectPoint::MB; break; + case css::drawing::MeasureTextHorzPos_RIGHTOUTSIDE: eRP = RectPoint::RB; break; + case css::drawing::MeasureTextHorzPos_AUTO: eRP = RectPoint::MB; break; + default: break; + } + break; + case css::drawing::MeasureTextVertPos_AUTO: + switch( eHPos ) + { + case css::drawing::MeasureTextHorzPos_LEFTOUTSIDE: eRP = RectPoint::LM; break; + case css::drawing::MeasureTextHorzPos_INSIDE: eRP = RectPoint::MM; break; + case css::drawing::MeasureTextHorzPos_RIGHTOUTSIDE: eRP = RectPoint::RM; break; + case css::drawing::MeasureTextHorzPos_AUTO: eRP = RectPoint::MM; break; + default: break; + } + break; + default: ;//prevent warning + } + + CTL_STATE nState = CTL_STATE::NONE; + + if (eHPos == css::drawing::MeasureTextHorzPos_AUTO) + { + m_xTsbAutoPosH->set_state( TRISTATE_TRUE ); + nState = CTL_STATE::NOHORZ; + } + + if (eVPos == css::drawing::MeasureTextVertPos_AUTO) + { + m_xTsbAutoPosV->set_state( TRISTATE_TRUE ); + nState |= CTL_STATE::NOVERT; + } + + m_aCtlPosition.SetState(nState); + m_aCtlPosition.SetActualRP(eRP); + } + } + } + else + { + m_aCtlPosition.Reset(); + m_xTsbAutoPosV->set_state( TRISTATE_INDET ); + m_xTsbAutoPosH->set_state( TRISTATE_INDET ); + } + + // put the attributes to the preview-control, + // otherwise the control don't know about + // the settings of the dialog (#67930) + ChangeAttrHdl_Impl(m_xTsbShowUnit.get()); + m_aCtlPreview.SetAttributes(*rAttrs); + + bPositionModified = false; +} + +/************************************************************************* +|* +|* Fill the delivered Item-Set with dialogbox-attributes +|* +\************************************************************************/ + +bool SvxMeasurePage::FillItemSet( SfxItemSet* rAttrs) +{ + bool bModified = false; + sal_Int32 nValue; + TriState eState; + + if( m_xMtrFldLineDist->get_value_changed_from_saved() ) + { + nValue = GetCoreValue( *m_xMtrFldLineDist, eUnit ); + rAttrs->Put( makeSdrMeasureLineDistItem( nValue ) ); + bModified = true; + } + + if( m_xMtrFldHelplineOverhang->get_value_changed_from_saved() ) + { + nValue = GetCoreValue( *m_xMtrFldHelplineOverhang, eUnit ); + rAttrs->Put( makeSdrMeasureHelplineOverhangItem( nValue ) ); + bModified = true; + } + + if( m_xMtrFldHelplineDist->get_value_changed_from_saved() ) + { + nValue = GetCoreValue( *m_xMtrFldHelplineDist, eUnit ); + rAttrs->Put( makeSdrMeasureHelplineDistItem( nValue ) ); + bModified = true; + } + + if( m_xMtrFldHelpline1Len->get_value_changed_from_saved() ) + { + nValue = GetCoreValue( *m_xMtrFldHelpline1Len, eUnit ); + rAttrs->Put( makeSdrMeasureHelpline1LenItem( nValue ) ); + bModified = true; + } + + if( m_xMtrFldHelpline2Len->get_value_changed_from_saved() ) + { + nValue = GetCoreValue( *m_xMtrFldHelpline2Len, eUnit ); + rAttrs->Put( makeSdrMeasureHelpline2LenItem( nValue ) ); + bModified = true; + } + + eState = m_xTsbBelowRefEdge->get_state(); + if( m_xTsbBelowRefEdge->get_state_changed_from_saved() ) + { + rAttrs->Put( SdrMeasureBelowRefEdgeItem( TRISTATE_TRUE == eState ) ); + bModified = true; + } + + if( m_xMtrFldDecimalPlaces->get_value_changed_from_saved() ) + { + nValue = m_xMtrFldDecimalPlaces->get_value(); + rAttrs->Put( + SdrMeasureDecimalPlacesItem( + sal::static_int_cast< sal_Int16 >( nValue ) ) ); + bModified = true; + } + + eState = m_xTsbParallel->get_state(); + if( m_xTsbParallel->get_state_changed_from_saved() ) + { + rAttrs->Put( SdrMeasureTextRota90Item( TRISTATE_FALSE == eState ) ); + bModified = true; + } + + eState = m_xTsbShowUnit->get_state(); + if( m_xTsbShowUnit->get_state_changed_from_saved() ) + { + rAttrs->Put( SdrYesNoItem(SDRATTR_MEASURESHOWUNIT, TRISTATE_TRUE == eState ) ); + bModified = true; + } + + int nPos = m_xLbUnit->get_active(); + if( m_xLbUnit->get_value_changed_from_saved() ) + { + if (nPos != -1) + { + sal_uInt16 nFieldUnit = m_xLbUnit->get_id(nPos).toUInt32(); + FieldUnit _eUnit = static_cast(nFieldUnit); + rAttrs->Put( SdrMeasureUnitItem( _eUnit ) ); + bModified = true; + } + } + + if( bPositionModified ) + { + // Position + css::drawing::MeasureTextVertPos eVPos, eOldVPos; + css::drawing::MeasureTextHorzPos eHPos, eOldHPos; + + RectPoint eRP = m_aCtlPosition.GetActualRP(); + switch( eRP ) + { + default: + case RectPoint::LT: eVPos = css::drawing::MeasureTextVertPos_EAST; + eHPos = css::drawing::MeasureTextHorzPos_LEFTOUTSIDE; break; + case RectPoint::LM: eVPos = css::drawing::MeasureTextVertPos_CENTERED; + eHPos = css::drawing::MeasureTextHorzPos_LEFTOUTSIDE; break; + case RectPoint::LB: eVPos = css::drawing::MeasureTextVertPos_WEST; + eHPos = css::drawing::MeasureTextHorzPos_LEFTOUTSIDE; break; + case RectPoint::MT: eVPos = css::drawing::MeasureTextVertPos_EAST; + eHPos = css::drawing::MeasureTextHorzPos_INSIDE; break; + case RectPoint::MM: eVPos = css::drawing::MeasureTextVertPos_CENTERED; + eHPos = css::drawing::MeasureTextHorzPos_INSIDE; break; + case RectPoint::MB: eVPos = css::drawing::MeasureTextVertPos_WEST; + eHPos = css::drawing::MeasureTextHorzPos_INSIDE; break; + case RectPoint::RT: eVPos = css::drawing::MeasureTextVertPos_EAST; + eHPos = css::drawing::MeasureTextHorzPos_RIGHTOUTSIDE; break; + case RectPoint::RM: eVPos = css::drawing::MeasureTextVertPos_CENTERED; + eHPos = css::drawing::MeasureTextHorzPos_RIGHTOUTSIDE; break; + case RectPoint::RB: eVPos = css::drawing::MeasureTextVertPos_WEST; + eHPos = css::drawing::MeasureTextHorzPos_RIGHTOUTSIDE; break; + } + if (m_xTsbAutoPosH->get_state() == TRISTATE_TRUE) + eHPos = css::drawing::MeasureTextHorzPos_AUTO; + + if (m_xTsbAutoPosV->get_state() == TRISTATE_TRUE) + eVPos = css::drawing::MeasureTextVertPos_AUTO; + + if ( rAttrs->GetItemState( SDRATTR_MEASURETEXTVPOS ) != SfxItemState::DONTCARE ) + { + eOldVPos = rOutAttrs.Get(SDRATTR_MEASURETEXTVPOS).GetValue(); + if( eOldVPos != eVPos ) + { + rAttrs->Put( SdrMeasureTextVPosItem( eVPos ) ); + bModified = true; + } + } + else + { + rAttrs->Put( SdrMeasureTextVPosItem( eVPos ) ); + bModified = true; + } + + if ( rAttrs->GetItemState( SDRATTR_MEASURETEXTHPOS ) != SfxItemState::DONTCARE ) + { + eOldHPos = rOutAttrs.Get( SDRATTR_MEASURETEXTHPOS ).GetValue(); + if( eOldHPos != eHPos ) + { + rAttrs->Put( SdrMeasureTextHPosItem( eHPos ) ); + bModified = true; + } + } + else + { + rAttrs->Put( SdrMeasureTextHPosItem( eHPos ) ); + bModified = true; + } + } + + return bModified; +} + +/************************************************************************* +|* +|* The View have to set at the measure-object to be able to notify +|* unit and floatingpoint-values +|* +\************************************************************************/ + +void SvxMeasurePage::Construct() +{ + DBG_ASSERT( pView, "No valid View transferred!" ); + + // TTTT + // pMeasureObj is member of SvxXMeasurePreview and can only be accessed due to + // SvxMeasurePage being a friend. It has its own SdrModel (also in SvxXMeasurePreview) + // and 'setting' the SdrModel is a hack. The comment above about 'notify unit and + // floatingpoint-values' is not clear, but has to be done another way - if needed. + // Checked on original aw080, is just commented out there, too. + + m_aCtlPreview.Invalidate(); +} + +std::unique_ptr SvxMeasurePage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrs) +{ + return std::make_unique(pPage, pController, *rAttrs); +} + +void SvxMeasurePage::PointChanged(weld::DrawingArea* pDrawingArea, RectPoint /*eRP*/) +{ + ChangeAttrHdl_Impl(pDrawingArea); +} + +IMPL_LINK( SvxMeasurePage, ClickAutoPosHdl_Impl, weld::ToggleButton&, rBox, void ) +{ + if (m_xTsbAutoPosH->get_state() == TRISTATE_TRUE) + { + switch( m_aCtlPosition.GetActualRP() ) + { + case RectPoint::LT: + case RectPoint::RT: + m_aCtlPosition.SetActualRP( RectPoint::MT ); + break; + + case RectPoint::LM: + case RectPoint::RM: + m_aCtlPosition.SetActualRP( RectPoint::MM ); + break; + + case RectPoint::LB: + case RectPoint::RB: + m_aCtlPosition.SetActualRP( RectPoint::MB ); + break; + default: ;//prevent warning + } + } + if (m_xTsbAutoPosV->get_state() == TRISTATE_TRUE) + { + switch( m_aCtlPosition.GetActualRP() ) + { + case RectPoint::LT: + case RectPoint::LB: + m_aCtlPosition.SetActualRP( RectPoint::LM ); + break; + + case RectPoint::MT: + case RectPoint::MB: + m_aCtlPosition.SetActualRP( RectPoint::MM ); + break; + + case RectPoint::RT: + case RectPoint::RB: + m_aCtlPosition.SetActualRP( RectPoint::RM ); + break; + default: ;//prevent warning + } + } + ChangeAttrHdl_Impl(&rBox); +} + +IMPL_LINK(SvxMeasurePage, ChangeAttrClickHdl_Impl, weld::ToggleButton&, r, void) +{ + ChangeAttrHdl_Impl(&r); +} + +IMPL_LINK(SvxMeasurePage, ChangeAttrListBoxHdl_Impl, weld::ComboBox&, rBox, void) +{ + ChangeAttrHdl_Impl(&rBox); +} + +IMPL_LINK(SvxMeasurePage, ChangeAttrEditHdl_Impl, weld::MetricSpinButton&, rBox, void) +{ + ChangeAttrHdl_Impl(&rBox); +} + +IMPL_LINK( SvxMeasurePage, ChangeAttrSpinHdl_Impl, weld::SpinButton&, rBox, void ) +{ + ChangeAttrHdl_Impl(&rBox); +} + +void SvxMeasurePage::ChangeAttrHdl_Impl( void const * p ) +{ + if (p == m_xMtrFldLineDist.get()) + { + sal_Int32 nValue = GetCoreValue( *m_xMtrFldLineDist, eUnit ); + aAttrSet.Put( makeSdrMeasureLineDistItem( nValue ) ); + } + + if (p == m_xMtrFldHelplineOverhang.get()) + { + sal_Int32 nValue = GetCoreValue( *m_xMtrFldHelplineOverhang, eUnit ); + aAttrSet.Put( makeSdrMeasureHelplineOverhangItem( nValue) ); + } + + if (p == m_xMtrFldHelplineDist.get()) + { + sal_Int32 nValue = GetCoreValue( *m_xMtrFldHelplineDist, eUnit ); + aAttrSet.Put( makeSdrMeasureHelplineDistItem( nValue) ); + } + + if (p == m_xMtrFldHelpline1Len.get()) + { + sal_Int32 nValue = GetCoreValue( *m_xMtrFldHelpline1Len, eUnit ); + aAttrSet.Put( makeSdrMeasureHelpline1LenItem( nValue ) ); + } + + if (p == m_xMtrFldHelpline2Len.get()) + { + sal_Int32 nValue = GetCoreValue( *m_xMtrFldHelpline2Len, eUnit ); + aAttrSet.Put( makeSdrMeasureHelpline2LenItem( nValue ) ); + } + + if (p == m_xTsbBelowRefEdge.get()) + { + TriState eState = m_xTsbBelowRefEdge->get_state(); + if( eState != TRISTATE_INDET ) + aAttrSet.Put( SdrMeasureBelowRefEdgeItem( TRISTATE_TRUE == eState ) ); + } + + if (p == m_xMtrFldDecimalPlaces.get()) + { + sal_Int16 nValue = sal::static_int_cast< sal_Int16 >( + m_xMtrFldDecimalPlaces->get_value() ); + aAttrSet.Put( SdrMeasureDecimalPlacesItem( nValue ) ); + } + + if (p == m_xTsbParallel.get()) + { + TriState eState = m_xTsbParallel->get_state(); + if( eState != TRISTATE_INDET ) + aAttrSet.Put( SdrMeasureTextRota90Item( TRISTATE_FALSE == eState ) ); + } + + if (p == m_xTsbShowUnit.get()) + { + TriState eState = m_xTsbShowUnit->get_state(); + if( eState != TRISTATE_INDET ) + aAttrSet.Put( SdrYesNoItem( SDRATTR_MEASURESHOWUNIT, TRISTATE_TRUE == eState ) ); + } + + if (p == m_xLbUnit.get()) + { + int nPos = m_xLbUnit->get_active(); + if (nPos != -1) + { + sal_uInt16 nFieldUnit = m_xLbUnit->get_id(nPos).toUInt32(); + FieldUnit _eUnit = static_cast(nFieldUnit); + aAttrSet.Put( SdrMeasureUnitItem( _eUnit ) ); + } + } + + if (p == m_xTsbAutoPosV.get() || p == m_xTsbAutoPosH.get() || p == m_aCtlPosition.GetDrawingArea()) + { + bPositionModified = true; + + // Position + RectPoint eRP = m_aCtlPosition.GetActualRP(); + css::drawing::MeasureTextVertPos eVPos; + css::drawing::MeasureTextHorzPos eHPos; + + switch( eRP ) + { + default: + case RectPoint::LT: eVPos = css::drawing::MeasureTextVertPos_EAST; + eHPos = css::drawing::MeasureTextHorzPos_LEFTOUTSIDE; break; + case RectPoint::LM: eVPos = css::drawing::MeasureTextVertPos_CENTERED; + eHPos = css::drawing::MeasureTextHorzPos_LEFTOUTSIDE; break; + case RectPoint::LB: eVPos = css::drawing::MeasureTextVertPos_WEST; + eHPos = css::drawing::MeasureTextHorzPos_LEFTOUTSIDE; break; + case RectPoint::MT: eVPos = css::drawing::MeasureTextVertPos_EAST; + eHPos = css::drawing::MeasureTextHorzPos_INSIDE; break; + case RectPoint::MM: eVPos = css::drawing::MeasureTextVertPos_CENTERED; + eHPos = css::drawing::MeasureTextHorzPos_INSIDE; break; + case RectPoint::MB: eVPos = css::drawing::MeasureTextVertPos_WEST; + eHPos = css::drawing::MeasureTextHorzPos_INSIDE; break; + case RectPoint::RT: eVPos = css::drawing::MeasureTextVertPos_EAST; + eHPos = css::drawing::MeasureTextHorzPos_RIGHTOUTSIDE; break; + case RectPoint::RM: eVPos = css::drawing::MeasureTextVertPos_CENTERED; + eHPos = css::drawing::MeasureTextHorzPos_RIGHTOUTSIDE; break; + case RectPoint::RB: eVPos = css::drawing::MeasureTextVertPos_WEST; + eHPos = css::drawing::MeasureTextHorzPos_RIGHTOUTSIDE; break; + } + + CTL_STATE nState = CTL_STATE::NONE; + + if (m_xTsbAutoPosH->get_state() == TRISTATE_TRUE) + { + eHPos = css::drawing::MeasureTextHorzPos_AUTO; + nState = CTL_STATE::NOHORZ; + } + + if (m_xTsbAutoPosV->get_state() == TRISTATE_TRUE) + { + eVPos = css::drawing::MeasureTextVertPos_AUTO; + nState |= CTL_STATE::NOVERT; + } + + if (p == m_xTsbAutoPosV.get() || p == m_xTsbAutoPosH.get()) + m_aCtlPosition.SetState( nState ); + + aAttrSet.Put( SdrMeasureTextVPosItem( eVPos ) ); + aAttrSet.Put( SdrMeasureTextHPosItem( eHPos ) ); + } + + m_aCtlPreview.SetAttributes(aAttrSet); + m_aCtlPreview.Invalidate(); +} + +void SvxMeasurePage::FillUnitLB() +{ + // fill ListBox with metrics + + FieldUnit nUnit = FieldUnit::NONE; + OUString aStrMetric(m_xFtAutomatic->get_label()); + m_xLbUnit->append(OUString::number(sal_uInt32(nUnit)), aStrMetric); + + for( sal_uInt32 i = 0; i < SvxFieldUnitTable::Count(); ++i ) + { + aStrMetric = SvxFieldUnitTable::GetString(i); + nUnit = SvxFieldUnitTable::GetValue(i); + m_xLbUnit->append(OUString::number(sal_uInt32(nUnit)), aStrMetric); + } +} + +void SvxMeasurePage::PageCreated(const SfxAllItemSet& aSet) +{ + const OfaPtrItem* pOfaPtrItem = aSet.GetItem(SID_OBJECT_LIST, false); + + if (pOfaPtrItem) + SetView( static_cast(pOfaPtrItem->GetValue())); + + Construct(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/numfmt.cxx b/cui/source/tabpages/numfmt.cxx new file mode 100644 index 000000000..5e3e4252a --- /dev/null +++ b/cui/source/tabpages/numfmt.cxx @@ -0,0 +1,1767 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::lang::XServiceInfo; +using ::com::sun::star::uno::UNO_QUERY; + +#define NUMKEY_UNDEFINED SAL_MAX_UINT32 + +// static ---------------------------------------------------------------- + +const sal_uInt16 SvxNumberFormatTabPage::pRanges[] = +{ + SID_ATTR_NUMBERFORMAT_VALUE, + SID_ATTR_NUMBERFORMAT_INFO, + SID_ATTR_NUMBERFORMAT_NOLANGUAGE, + SID_ATTR_NUMBERFORMAT_NOLANGUAGE, + SID_ATTR_NUMBERFORMAT_ONE_AREA, + SID_ATTR_NUMBERFORMAT_ONE_AREA, + SID_ATTR_NUMBERFORMAT_SOURCE, + SID_ATTR_NUMBERFORMAT_SOURCE, + 0 +}; + +/************************************************************************* +#* Method: SvxNumberPreview +#*------------------------------------------------------------------------ +#* +#* Class: SvxNumberPreview +#* Function: Constructor of the class SvxNumberPreview +#* Input: Window, Resource-ID +#* Output: --- +#* +#************************************************************************/ + +SvxNumberPreview::SvxNumberPreview() + : mnPos(-1) + , mnChar(0x0) +{ +} + +/************************************************************************* +#* Method: NotifyChange +#*------------------------------------------------------------------------ +#* +#* Class: SvxNumberPreview +#* Function: Function for changing the preview string +#* Input: String, color +#* Output: --- +#* +#************************************************************************/ + +void SvxNumberPreview::NotifyChange( const OUString& rPrevStr, + const Color* pColor ) +{ + // detect and strip out '*' related placeholders + aPrevStr = rPrevStr; + mnPos = aPrevStr.indexOf( 0x1B ); + if ( mnPos != -1 ) + { + // Right during user input the star symbol is the very + // last character before the user enters another one. + if (mnPos < aPrevStr.getLength() - 1) + { + mnChar = aPrevStr[ mnPos + 1 ]; + // delete placeholder and char to repeat + aPrevStr = aPrevStr.replaceAt( mnPos, 2, "" ); + } + else + { + // delete placeholder + aPrevStr = aPrevStr.replaceAt( mnPos, 1, "" ); + // do not attempt to draw a 0 fill character + mnPos = -1; + } + } + svtools::ColorConfig aColorConfig; + Color aWindowTextColor( aColorConfig.GetColorValue( svtools::FONTCOLOR ).nColor ); + aPrevCol = pColor ? *pColor : aWindowTextColor; + Invalidate(); +} + +/************************************************************************* +#* Method: Paint +#*------------------------------------------------------------------------ +#* +#* Class: SvxNumberPreview +#* Function: Function for repainting the window. +#* Input: --- +#* Output: --- +#* +#************************************************************************/ + +void SvxNumberPreview::Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle&) +{ + rRenderContext.Push(PushFlags::ALL); + + svtools::ColorConfig aColorConfig; + rRenderContext.SetTextColor(aColorConfig.GetColorValue( svtools::FONTCOLOR ).nColor); + const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); + rRenderContext.SetBackground(rStyleSettings.GetWindowColor()); + + vcl::Font aDrawFont = rRenderContext.GetFont(); + Size aSzWnd(GetOutputSizePixel()); + OUString aTmpStr( aPrevStr ); + long nLeadSpace = (aSzWnd.Width() - rRenderContext.GetTextWidth(aTmpStr)) / 2; + + aDrawFont.SetTransparent(true); + aDrawFont.SetColor(aPrevCol); + rRenderContext.SetFont(aDrawFont); + + if (mnPos != -1) + { + long nCharWidth = rRenderContext.GetTextWidth(OUString(mnChar)); + + int nNumCharsToInsert = 0; + if (nCharWidth > 0) + nNumCharsToInsert = nLeadSpace / nCharWidth; + + if (nNumCharsToInsert > 0) + { + for (int i = 0; i < nNumCharsToInsert; ++i) + aTmpStr = aTmpStr.replaceAt(mnPos, 0, OUString(mnChar)); + } + } + + long nX = 0; + if (mnPos == -1 && nLeadSpace > 0) //tdf#122120 if it won't fit anyway, then left align it + { + nX = nLeadSpace; + } + + Point aPosText(nX, (aSzWnd.Height() - GetTextHeight()) / 2); + rRenderContext.DrawText(aPosText, aTmpStr); + rRenderContext.Pop(); +} + +// class SvxNumberFormatTabPage ------------------------------------------ + +#define REMOVE_DONTKNOW() \ + if (!m_xFtLanguage->get_sensitive()) \ + { \ + m_xFtLanguage->set_sensitive(true); \ + m_xLbLanguage->set_sensitive(true); \ + m_xLbLanguage->set_active_id(pNumFmtShell->GetCurLanguage()); \ + } + +#define HDL(hdl) LINK( this, SvxNumberFormatTabPage, hdl ) + +SvxNumberFormatTabPage::SvxNumberFormatTabPage(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet& rCoreAttrs) + : SfxTabPage(pPage, pController, "cui/ui/numberingformatpage.ui", "NumberingFormatPage", &rCoreAttrs) + , nInitFormat(ULONG_MAX) + , m_nLbFormatSelPosEdComment(SELPOS_NONE) + , bLegacyAutomaticCurrency(false) + , sAutomaticLangEntry(CuiResId(RID_SVXSTR_AUTO_ENTRY)) + , m_xFtCategory(m_xBuilder->weld_label("categoryft")) + , m_xLbCategory(m_xBuilder->weld_tree_view("categorylb")) + , m_xFtFormat(m_xBuilder->weld_label("formatft")) + , m_xLbCurrency(m_xBuilder->weld_combo_box("currencylb")) + , m_xLbFormat(m_xBuilder->weld_tree_view("formatlb")) + , m_xFtLanguage(m_xBuilder->weld_label("languageft")) + , m_xCbSourceFormat(m_xBuilder->weld_check_button("sourceformat")) + , m_xFtOptions(m_xBuilder->weld_label("optionsft")) + , m_xFtDecimals(m_xBuilder->weld_label("decimalsft")) + , m_xEdDecimals(m_xBuilder->weld_spin_button("decimalsed")) + , m_xFtDenominator(m_xBuilder->weld_label("denominatorft")) + , m_xEdDenominator(m_xBuilder->weld_spin_button("denominatored")) + , m_xBtnNegRed(m_xBuilder->weld_check_button("negnumred")) + , m_xFtLeadZeroes(m_xBuilder->weld_label("leadzerosft")) + , m_xEdLeadZeroes(m_xBuilder->weld_spin_button("leadzerosed")) + , m_xBtnThousand(m_xBuilder->weld_check_button("thousands")) + , m_xBtnEngineering(m_xBuilder->weld_check_button("engineering")) + , m_xFormatCodeFrame(m_xBuilder->weld_widget("formatcode")) + , m_xEdFormat(m_xBuilder->weld_entry("formatted")) + , m_xIbAdd(m_xBuilder->weld_button("add")) + , m_xIbInfo(m_xBuilder->weld_button("edit")) + , m_xIbRemove(m_xBuilder->weld_button("delete")) + , m_xFtComment(m_xBuilder->weld_label("commentft")) + , m_xEdComment(m_xBuilder->weld_entry("commented")) + , m_xLbLanguage(new SvxLanguageBox(m_xBuilder->weld_combo_box("languagelb"))) + , m_xWndPreview(new weld::CustomWeld(*m_xBuilder, "preview", m_aWndPreview)) +{ + for (size_t i = 0; i < SAL_N_ELEMENTS(NUM_CATEGORIES); ++i) + m_xLbCategory->append_text(CuiResId(NUM_CATEGORIES[i])); + + auto nWidth = m_xLbCategory->get_approximate_digit_width() * 22; + m_xLbCategory->set_size_request(nWidth, m_xLbCategory->get_height_rows(7)); + m_xLbFormat->set_size_request(nWidth, m_xLbFormat->get_height_rows(5)); + m_xLbCurrency->set_size_request(nWidth, -1); // force using (narrower) width of its LbFormat sibling + + // Initially remove the "Automatically" entry. + m_xLbCurrency->set_active(-1); // First ensure that nothing is selected. + sAutomaticCurrencyEntry = m_xLbCurrency->get_text(0); + m_xLbCurrency->remove(0); + + Init_Impl(); + SetExchangeSupport(); // this page needs ExchangeSupport + nFixedCategory=-1; +} + +SvxNumberFormatTabPage::~SvxNumberFormatTabPage() +{ + pNumFmtShell.reset(); + pNumItem.reset(); + m_xWndPreview.reset(); + m_xLbLanguage.reset(); +} + +void SvxNumberFormatTabPage::Init_Impl() +{ + bNumItemFlag=true; + bOneAreaFlag=false; + + m_xIbAdd->set_sensitive(false ); + m_xIbRemove->set_sensitive(false ); + m_xIbInfo->set_sensitive(false ); + + m_xEdComment->set_text(m_xLbCategory->get_text(1)); // string for user defined + + m_xEdComment->hide(); + + m_xCbSourceFormat->set_active( false ); + m_xCbSourceFormat->set_sensitive(false); + m_xCbSourceFormat->hide(); + + Link aLink2 = LINK(this, SvxNumberFormatTabPage, SelFormatTreeListBoxHdl_Impl); + Link aLink3 = LINK(this, SvxNumberFormatTabPage, SelFormatListBoxHdl_Impl); + m_xLbCategory->connect_changed(aLink2); + m_xLbCategory->connect_focus_in(LINK(this, SvxNumberFormatTabPage, LostFocusHdl_Impl)); + m_xLbFormat->connect_changed(aLink2); + m_xLbFormat->connect_focus_in(LINK(this, SvxNumberFormatTabPage, LostFocusHdl_Impl)); + m_xLbLanguage->connect_changed(aLink3); + m_xLbLanguage->connect_focus_in(LINK(this, SvxNumberFormatTabPage, LostFocusHdl_Impl)); + m_xLbCurrency->connect_changed(aLink3); + m_xLbCurrency->connect_focus_in(LINK(this, SvxNumberFormatTabPage, LostFocusHdl_Impl)); + m_xCbSourceFormat->connect_clicked(LINK(this, SvxNumberFormatTabPage, SelFormatClickHdl_Impl)); + m_xCbSourceFormat->connect_focus_in(LINK(this, SvxNumberFormatTabPage, LostFocusHdl_Impl)); + + Link aLink = LINK( this, SvxNumberFormatTabPage, OptEditHdl_Impl ); + + m_xEdDecimals->connect_value_changed(aLink); + m_xEdDecimals->connect_focus_in(LINK(this, SvxNumberFormatTabPage, LostFocusHdl_Impl)); + m_xEdDenominator->connect_value_changed(aLink); + m_xEdDenominator->connect_focus_in(LINK(this, SvxNumberFormatTabPage, LostFocusHdl_Impl)); + m_xEdLeadZeroes->connect_value_changed(aLink); + m_xEdLeadZeroes->connect_focus_in(LINK(this, SvxNumberFormatTabPage, LostFocusHdl_Impl)); + + m_xBtnNegRed->connect_clicked(LINK(this, SvxNumberFormatTabPage, OptClickHdl_Impl)); + m_xBtnNegRed->connect_focus_in(LINK(this, SvxNumberFormatTabPage, LostFocusHdl_Impl)); + m_xBtnThousand->connect_clicked(LINK(this, SvxNumberFormatTabPage, OptClickHdl_Impl)); + m_xBtnThousand->connect_focus_in(LINK(this, SvxNumberFormatTabPage, LostFocusHdl_Impl)); + m_xBtnEngineering->connect_clicked(LINK(this, SvxNumberFormatTabPage, OptClickHdl_Impl)); + m_xBtnEngineering->connect_focus_in(LINK(this, SvxNumberFormatTabPage, LostFocusHdl_Impl)); + m_xLbFormat->connect_row_activated(HDL(DoubleClickHdl_Impl)); + m_xEdFormat->connect_changed(HDL(EditModifyHdl_Impl)); + m_xEdFormat->connect_focus_in(LINK(this, SvxNumberFormatTabPage, LostFocusHdl_Impl)); + m_xIbAdd->connect_clicked(HDL(ClickHdl_Impl)); + m_xIbAdd->connect_focus_in(LINK(this, SvxNumberFormatTabPage, LostFocusHdl_Impl)); + m_xIbRemove->connect_clicked(HDL(ClickHdl_Impl)); + m_xIbRemove->connect_focus_in(LINK(this, SvxNumberFormatTabPage, LostFocusHdl_Impl)); + m_xIbInfo->connect_clicked(HDL(ClickHdl_Impl)); + UpdateThousandEngineeringCheckBox(); + UpdateDecimalsDenominatorEditBox(); + + // initialize language ListBox + + m_xLbLanguage->SetLanguageList(SvxLanguageListFlags::ALL | SvxLanguageListFlags::ONLY_KNOWN, + false, false, false, true, LANGUAGE_SYSTEM, + css::i18n::ScriptType::WEAK); +} + +std::unique_ptr SvxNumberFormatTabPage::Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet ) +{ + return std::make_unique(pPage, pController, *rAttrSet); +} + + +/************************************************************************* +#* Method: Reset +#*------------------------------------------------------------------------ +#* +#* Class: SvxNumberFormatTabPage +#* Function: The dialog's attributes are reset +#* using the Itemset. +#* Input: SfxItemSet +#* Output: --- +#* +#************************************************************************/ + +void SvxNumberFormatTabPage::set_active_currency(sal_Int32 nPos) +{ + static_assert(SELPOS_NONE == -1, "SELPOS_NONE was -1 at time of writing"); + if (nPos == 0 && !bLegacyAutomaticCurrency) + { + // Insert "Automatically" if currently used so it is selectable. + m_xLbCurrency->insert_text(0, sAutomaticCurrencyEntry); + bLegacyAutomaticCurrency = true; + } + if (nPos != -1 && !bLegacyAutomaticCurrency) + --nPos; + m_xLbCurrency->set_active(nPos); +} + +sal_uInt32 SvxNumberFormatTabPage::get_active_currency() const +{ + static_assert(SELPOS_NONE == -1, "SELPOS_NONE was -1 at time of writing"); + sal_Int32 nCurrencyPos = m_xLbCurrency->get_active(); + if (nCurrencyPos != -1 && !bLegacyAutomaticCurrency) + ++nCurrencyPos; + return nCurrencyPos; +} + +void SvxNumberFormatTabPage::Reset( const SfxItemSet* rSet ) +{ + const SfxUInt32Item* pValFmtAttr = nullptr; + const SfxPoolItem* pItem = nullptr; + const SfxBoolItem* pAutoEntryAttr = nullptr; + + sal_uInt16 nCatLbSelPos = 0; + sal_uInt16 nFmtLbSelPos = 0; + LanguageType eLangType = LANGUAGE_DONTKNOW; + std::vector aFmtEntryList; + SvxNumberValueType eValType = SvxNumberValueType::Undefined; + double nValDouble = 0; + OUString aValString; + + SfxItemState eState = rSet->GetItemState( GetWhich( SID_ATTR_NUMBERFORMAT_NOLANGUAGE ),true,&pItem); + + if(eState==SfxItemState::SET) + { + const SfxBoolItem* pBoolLangItem = static_cast( + GetItem( *rSet, SID_ATTR_NUMBERFORMAT_NOLANGUAGE)); + + if(pBoolLangItem!=nullptr && pBoolLangItem->GetValue()) + { + HideLanguage(); + } + else + { + HideLanguage(false); + } + + } + + eState = rSet->GetItemState( GetWhich( SID_ATTR_NUMBERFORMAT_INFO ),true,&pItem); + + if(eState==SfxItemState::SET) + { + if(pNumItem==nullptr) + { + bNumItemFlag=true; + pNumItem.reset( static_cast(pItem->Clone()) ); + } + else + { + bNumItemFlag=false; + } + } + else + { + bNumItemFlag=false; + } + + + eState = rSet->GetItemState( GetWhich( SID_ATTR_NUMBERFORMAT_ONE_AREA )); + + if(eState==SfxItemState::SET) + { + const SfxBoolItem* pBoolItem = static_cast( + GetItem( *rSet, SID_ATTR_NUMBERFORMAT_ONE_AREA)); + + if(pBoolItem!=nullptr) + { + bOneAreaFlag= pBoolItem->GetValue(); + } + } + + eState = rSet->GetItemState( GetWhich( SID_ATTR_NUMBERFORMAT_SOURCE ) ); + + if ( eState == SfxItemState::SET ) + { + const SfxBoolItem* pBoolItem = static_cast( + GetItem( *rSet, SID_ATTR_NUMBERFORMAT_SOURCE )); + if ( pBoolItem ) + m_xCbSourceFormat->set_active(pBoolItem->GetValue()); + else + m_xCbSourceFormat->set_active( false ); + m_xCbSourceFormat->set_sensitive(true); + m_xCbSourceFormat->show(); + } + else + { + bool bInit = false; // set to sal_True for debug test + m_xCbSourceFormat->set_active( bInit ); + m_xCbSourceFormat->set_sensitive( bInit ); + m_xCbSourceFormat->set_visible( bInit ); + } + + // pNumItem must have been set from outside! + DBG_ASSERT( pNumItem, "No NumberInfo, no NumberFormatter, goodbye. CRASH. :-(" ); + + eState = rSet->GetItemState( GetWhich( SID_ATTR_NUMBERFORMAT_VALUE ) ); + + if ( SfxItemState::DONTCARE != eState ) + pValFmtAttr = GetItem( *rSet, SID_ATTR_NUMBERFORMAT_VALUE ); + + eValType = pNumItem->GetValueType(); + + switch ( eValType ) + { + case SvxNumberValueType::String: + aValString = pNumItem->GetValueString(); + break; + case SvxNumberValueType::Number: + // #50441# string may be set in addition to the value + aValString = pNumItem->GetValueString(); + nValDouble = pNumItem->GetValueDouble(); + break; + case SvxNumberValueType::Undefined: + default: + break; + } + + pNumFmtShell.reset(); // delete old shell if applicable (== reset) + + nInitFormat = pValFmtAttr // memorize init key + ? pValFmtAttr->GetValue() // (for FillItemSet()) + : ULONG_MAX; // == DONT_KNOW + + + if ( eValType == SvxNumberValueType::String ) + pNumFmtShell.reset( SvxNumberFormatShell::Create( + pNumItem->GetNumberFormatter(), + pValFmtAttr ? nInitFormat : 0, + eValType, + aValString ) ); + else + pNumFmtShell.reset( SvxNumberFormatShell::Create( + pNumItem->GetNumberFormatter(), + pValFmtAttr ? nInitFormat : 0, + eValType, + nValDouble, + &aValString ) ); + + + bool bUseStarFormat = false; + SfxObjectShell* pDocSh = SfxObjectShell::Current(); + if ( pDocSh ) + { + // is this a calc document + Reference< XServiceInfo > xSI( pDocSh->GetModel(), UNO_QUERY ); + if ( xSI.is() ) + bUseStarFormat = xSI->supportsService("com.sun.star.sheet.SpreadsheetDocument"); + } + pNumFmtShell->SetUseStarFormat( bUseStarFormat ); + + FillCurrencyBox(); + + OUString aPrevString; + Color* pDummy = nullptr; + pNumFmtShell->GetInitSettings( nCatLbSelPos, eLangType, nFmtLbSelPos, + aFmtEntryList, aPrevString, pDummy ); + + if (nCatLbSelPos==CAT_CURRENCY) + set_active_currency(pNumFmtShell->GetCurrencySymbol()); + + nFixedCategory=nCatLbSelPos; + if(bOneAreaFlag) + { + OUString sFixedCategory = m_xLbCategory->get_text(nFixedCategory); + m_xLbCategory->clear(); + m_xLbCategory->append_text(sFixedCategory); + SetCategory(0); + } + else + { + SetCategory(nCatLbSelPos ); + } + eState = rSet->GetItemState( GetWhich( SID_ATTR_NUMBERFORMAT_ADD_AUTO ) ); + if(SfxItemState::SET == eState) + pAutoEntryAttr = static_cast( + GetItem( *rSet, SID_ATTR_NUMBERFORMAT_ADD_AUTO )); + // no_NO is an alias for nb_NO and normally isn't listed, we need it for + // backwards compatibility, but only if the format passed is of + // LanguageType no_NO. + if ( eLangType == LANGUAGE_NORWEGIAN ) + { + m_xLbLanguage->remove_id(eLangType); // in case we're already called + m_xLbLanguage->InsertLanguage( eLangType ); + } + m_xLbLanguage->set_active_id(eLangType); + if(pAutoEntryAttr) + AddAutomaticLanguage_Impl(eLangType, pAutoEntryAttr->GetValue()); + UpdateFormatListBox_Impl(false,true); + +//! This spoils everything because it rematches currency formats based on +//! the selected m_xLbCurrency entry instead of the current format. +//! Besides that everything seems to be initialized by now, so why call it? +// SelFormatHdl_Impl(m_xLbCategory.get()); + + if ( pValFmtAttr ) + { + EditHdl_Impl(m_xEdFormat.get()); // UpdateOptions_Impl() as a side effect + } + else // DONT_KNOW + { + // everything disabled except direct input or changing the category + Obstructing(); + } + + if ( m_xCbSourceFormat->get_active() ) + { + // everything disabled except SourceFormat checkbox + EnableBySourceFormat_Impl(); + } +} + +/************************************************************************* +#* Method: Obstructing +#*------------------------------------------------------------------------ +#* +#* Class: SvxNumberFormatTabPage +#* Function: Disable the controls except from changing the category +#* and direct input. +#* Input: --- +#* Output: --- +#* +#************************************************************************/ +void SvxNumberFormatTabPage::Obstructing() +{ + m_xLbFormat->select(-1); + m_xLbLanguage->set_active(-1); + m_xFtLanguage->set_sensitive(false); + m_xLbLanguage->set_sensitive(false); + + m_xIbAdd->set_sensitive(false ); + m_xIbRemove->set_sensitive(false ); + m_xIbInfo->set_sensitive(false ); + + m_xBtnNegRed->set_sensitive(false); + m_xBtnThousand->set_sensitive(false); + m_xBtnEngineering->set_sensitive(false); + m_xFtLeadZeroes->set_sensitive(false); + m_xFtDecimals->set_sensitive(false); + m_xFtDenominator->set_sensitive(false); + m_xEdLeadZeroes->set_sensitive(false); + m_xEdDecimals->set_sensitive(false); + m_xEdDenominator->set_sensitive(false); + m_xFtOptions->set_sensitive(false); + m_xEdDecimals->set_text( OUString() ); + m_xEdLeadZeroes->set_text( OUString() ); + m_xBtnNegRed->set_active( false ); + m_xBtnThousand->set_active( false ); + m_xBtnEngineering->set_active( false ); + m_aWndPreview.NotifyChange( OUString() ); + + m_xLbCategory->select(0); + m_xEdFormat->set_text( OUString() ); + m_xFtComment->set_label( OUString() ); + m_xEdComment->set_text(m_xLbCategory->get_text(1)); // string for user defined + + m_xEdFormat->grab_focus(); +} + + +/************************************************************************* +#* Enable/Disable dialog parts depending on the value of the SourceFormat +#* checkbox. +#************************************************************************/ +void SvxNumberFormatTabPage::EnableBySourceFormat_Impl() +{ + bool bEnable = !m_xCbSourceFormat->get_active(); + if ( !bEnable ) + m_xCbSourceFormat->grab_focus(); + m_xFtCategory->set_sensitive( bEnable ); + m_xLbCategory->set_sensitive( bEnable ); + m_xFtFormat->set_sensitive( bEnable ); + m_xLbCurrency->set_sensitive( bEnable ); + m_xLbFormat->set_sensitive( bEnable ); + m_xFtLanguage->set_sensitive( bEnable ); + m_xLbLanguage->set_sensitive( bEnable ); + m_xFtDecimals->set_sensitive( bEnable ); + m_xEdDecimals->set_sensitive( bEnable ); + m_xFtDenominator->set_sensitive( bEnable ); + m_xEdDenominator->set_sensitive( bEnable ); + m_xFtLeadZeroes->set_sensitive( bEnable ); + m_xEdLeadZeroes->set_sensitive( bEnable ); + m_xBtnNegRed->set_sensitive( bEnable ); + m_xBtnThousand->set_sensitive( bEnable ); + m_xBtnEngineering->set_sensitive( bEnable ); + m_xFtOptions->set_sensitive( bEnable ); + m_xFormatCodeFrame->set_sensitive( bEnable ); +} + + +/************************************************************************* +#* Method: HideLanguage +#*------------------------------------------------------------------------ +#* +#* Class: SvxNumberFormatTabPage +#* Function: Hides the language settings: +#* Input: sal_Bool nFlag +#* Output: --- +#* +#************************************************************************/ + +void SvxNumberFormatTabPage::HideLanguage(bool bFlag) +{ + m_xFtLanguage->set_visible(!bFlag); + m_xLbLanguage->set_visible(!bFlag); +} + +/************************************************************************* +#* Method: FillItemSet +#*------------------------------------------------------------------------ +#* +#* Class: SvxNumberFormatTabPage +#* Function: Adjusts the attributes in the ItemSet, +#* and - if bNumItemFlag is not set - the +#* numItem in the DocShell. +#* Input: SfxItemSet +#* Output: --- +#* +#************************************************************************/ + +bool SvxNumberFormatTabPage::FillItemSet( SfxItemSet* rCoreAttrs ) +{ + bool bDataChanged = m_xFtLanguage->get_sensitive() || m_xCbSourceFormat->get_sensitive(); + if ( bDataChanged ) + { + const SfxItemSet& rMyItemSet = GetItemSet(); + sal_uInt16 nWhich = GetWhich( SID_ATTR_NUMBERFORMAT_VALUE ); + SfxItemState eItemState = rMyItemSet.GetItemState( nWhich, false ); + + // OK chosen - Is format code input entered already taken over? + // If not, simulate Add. Upon syntax error ignore input and prevent Put. + OUString aFormat = m_xEdFormat->get_text(); + sal_uInt32 nCurKey = pNumFmtShell->GetCurNumFmtKey(); + + if ( m_xIbAdd->get_sensitive() || pNumFmtShell->IsTmpCurrencyFormat(aFormat) ) + { // #79599# It is not sufficient to just add the format code (or + // delete it in case of bOneAreaFlag and resulting category change). + // Upon switching tab pages we need all settings to be consistent + // in case this page will be redisplayed later. + bDataChanged = Click_Impl(*m_xIbAdd); + nCurKey = pNumFmtShell->GetCurNumFmtKey(); + } + else if(nCurKey == NUMKEY_UNDEFINED) + { // something went wrong, e.g. in Writer #70281# + pNumFmtShell->FindEntry(aFormat, &nCurKey); + } + + + // Chosen format: + + if ( bDataChanged ) + { + bDataChanged = ( nInitFormat != nCurKey ); + + if (bDataChanged) + { + rCoreAttrs->Put( SfxUInt32Item( nWhich, nCurKey ) ); + } + else if(SfxItemState::DEFAULT == eItemState) + { + rCoreAttrs->ClearItem( nWhich ); + } + } + + + // List of changed user defined formats: + + std::vector const & aDelFormats = pNumFmtShell->GetUpdateData(); + + if ( !aDelFormats.empty() ) + { + + pNumItem->SetDelFormats( aDelFormats ); + + if(bNumItemFlag) + { + rCoreAttrs->Put( *pNumItem ); + } + else + { + SfxObjectShell* pDocSh = SfxObjectShell::Current(); + + DBG_ASSERT( pDocSh, "DocShell not found!" ); + + + if ( pDocSh ) + pDocSh->PutItem( *pNumItem ); + } + } + + + // Whether source format is to be taken or not: + + if ( m_xCbSourceFormat->get_sensitive() ) + { + sal_uInt16 _nWhich = GetWhich( SID_ATTR_NUMBERFORMAT_SOURCE ); + SfxItemState _eItemState = rMyItemSet.GetItemState( _nWhich, false ); + const SfxBoolItem* pBoolItem = static_cast( + GetItem( rMyItemSet, SID_ATTR_NUMBERFORMAT_SOURCE )); + bool bOld = pBoolItem && pBoolItem->GetValue(); + rCoreAttrs->Put( SfxBoolItem( _nWhich, m_xCbSourceFormat->get_active() ) ); + if ( !bDataChanged ) + bDataChanged = (bOld != m_xCbSourceFormat->get_active() || + _eItemState != SfxItemState::SET); + } + + // FillItemSet is only called on OK, here we can notify the + // NumberFormatShell that all new user defined formats are valid. + pNumFmtShell->ValidateNewEntries(); + if(m_xLbLanguage->get_visible() && + m_xLbLanguage->find_text(sAutomaticLangEntry) != -1) + rCoreAttrs->Put(SfxBoolItem(SID_ATTR_NUMBERFORMAT_ADD_AUTO, + m_xLbLanguage->get_active_text() == sAutomaticLangEntry)); + } + + return bDataChanged; +} + + +DeactivateRC SvxNumberFormatTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if ( _pSet ) + FillItemSet( _pSet ); + return DeactivateRC::LeavePage; +} + +void SvxNumberFormatTabPage::FillFormatListBox_Impl( std::vector& rEntries ) +{ + OUString aEntry; + OUString aTmpString; + size_t i = 0; + short nTmpCatPos; + + m_xLbFormat->clear(); + if (rEntries.empty()) + return; + + m_xLbFormat->freeze(); + + if(bOneAreaFlag) + { + nTmpCatPos=nFixedCategory; + } + else + { + nTmpCatPos=m_xLbCategory->get_selected_index(); + } + + switch (nTmpCatPos) + { + case CAT_ALL: + case CAT_TEXT: + case CAT_NUMBER: i=1; + aEntry=rEntries[0]; + if (nTmpCatPos == CAT_TEXT) + aTmpString=aEntry; + else + aTmpString = pNumFmtShell->GetStandardName(); + m_xLbFormat->append_text(aTmpString); + break; + + default: break; + } + + if(pNumFmtShell!=nullptr) + { + for ( ; i < rEntries.size(); ++i ) + { + aEntry = rEntries[i]; + short aPrivCat = pNumFmtShell->GetCategory4Entry( static_cast(i) ); + if(aPrivCat!=CAT_TEXT) + { + Color* pPreviewColor = nullptr; + OUString aPreviewString( GetExpColorString( pPreviewColor, aEntry, aPrivCat ) ); + m_xLbFormat->append_text(aPreviewString); + if (pPreviewColor) + m_xLbFormat->set_font_color(m_xLbFormat->n_children() - 1, *pPreviewColor); + } + else + { + m_xLbFormat->append_text(aEntry); + } + } + } + m_xLbFormat->thaw(); + rEntries.clear(); +} + +/************************************************************************* +#* Method: UpdateOptions_Impl +#*------------------------------------------------------------------------ +#* +#* Class: SvxNumberFormatTabPage +#* Function: Adjusts the options attributes +#* depending on the selected format. +#* Input: Flag, whether the category has changed. +#* Output: --- +#* +#************************************************************************/ + +void SvxNumberFormatTabPage::UpdateOptions_Impl( bool bCheckCatChange /*= sal_False*/ ) +{ + OUString theFormat = m_xEdFormat->get_text(); + sal_Int32 nCurCategory = m_xLbCategory->get_selected_index(); + sal_uInt16 nCategory = static_cast(nCurCategory); + sal_uInt16 nDecimals = 0; + sal_uInt16 nZeroes = 0; + bool bNegRed = false; + bool bThousand = false; + sal_Int32 nCurrencyPos = get_active_currency(); + + if(bOneAreaFlag) + nCurCategory=nFixedCategory; + + + pNumFmtShell->GetOptions( theFormat, + bThousand, bNegRed, + nDecimals, nZeroes, + nCategory ); + bool bDoIt=false; + if(nCategory==CAT_CURRENCY) + { + sal_uInt16 nTstPos=pNumFmtShell->FindCurrencyFormat(theFormat); + if(nCurrencyPos!=static_cast(nTstPos) && nTstPos!=sal_uInt16(-1)) + { + set_active_currency(nTstPos); + pNumFmtShell->SetCurrencySymbol(nTstPos); + bDoIt=true; + } + } + + if ( nCategory != nCurCategory || bDoIt) + { + if ( bCheckCatChange ) + { + if(bOneAreaFlag) + SetCategory(0); + else + SetCategory(nCategory ); + + UpdateFormatListBox_Impl( true, false ); + } + } + else if ( m_xLbFormat->n_children() > 0 ) + { + sal_uInt32 nCurEntryKey=NUMKEY_UNDEFINED; + if(!pNumFmtShell->FindEntry( m_xEdFormat->get_text(),&nCurEntryKey)) + { + m_xLbFormat->select(-1); + } + } + if(bOneAreaFlag) + { + nCategory=nFixedCategory; + } + + UpdateThousandEngineeringCheckBox(); + UpdateDecimalsDenominatorEditBox(); + switch ( nCategory ) + { + case CAT_SCIENTIFIC: // bThousand is for Engineering notation + { + sal_uInt16 nIntDigits = pNumFmtShell->GetFormatIntegerDigits(theFormat); + bThousand = (nIntDigits > 0) && (nIntDigits % 3 == 0); + m_xBtnEngineering->set_sensitive(true); + m_xBtnEngineering->set_active( bThousand ); + } + [[fallthrough]]; + case CAT_NUMBER: + case CAT_PERCENT: + case CAT_CURRENCY: + case CAT_FRACTION: + case CAT_TIME: + m_xFtOptions->set_sensitive(true); + if ( nCategory == CAT_FRACTION ) + { + m_xFtDenominator->set_sensitive(true); + m_xEdDenominator->set_sensitive(true); + } + else + { + m_xFtDecimals->set_sensitive(true); + m_xEdDecimals->set_sensitive(true); + } + m_xFtLeadZeroes->set_sensitive( nCategory != CAT_TIME ); + m_xEdLeadZeroes->set_sensitive( nCategory != CAT_TIME ); + m_xBtnNegRed->set_sensitive(true); + if ( nCategory == CAT_NUMBER && m_xLbFormat->get_selected_index() == 0 ) + m_xEdDecimals->set_text( "" ); //General format tdf#44399 + else + if ( nCategory == CAT_FRACTION ) + m_xEdDenominator->set_value( nDecimals ); + else + m_xEdDecimals->set_value( nDecimals ); + if ( nCategory != CAT_TIME ) + m_xEdLeadZeroes->set_value( nZeroes ); + m_xBtnNegRed->set_active( bNegRed ); + if ( nCategory != CAT_SCIENTIFIC ) + { + m_xBtnThousand->set_sensitive( nCategory != CAT_TIME ); + m_xBtnThousand->set_active( bThousand && nCategory != CAT_TIME ); + } + break; + + case CAT_ALL: + case CAT_USERDEFINED: + case CAT_TEXT: + case CAT_DATE: + case CAT_BOOLEAN: + default: + m_xFtOptions->set_sensitive(false); + m_xFtDecimals->set_sensitive(false); + m_xEdDecimals->set_sensitive(false); + m_xFtDenominator->set_sensitive(false); + m_xEdDenominator->set_sensitive(false); + m_xFtLeadZeroes->set_sensitive(false); + m_xEdLeadZeroes->set_sensitive(false); + m_xBtnNegRed->set_sensitive(false); + m_xBtnThousand->set_sensitive(false); + m_xBtnEngineering->set_sensitive(false); + m_xEdDecimals->set_text( OUString() ); + m_xEdLeadZeroes->set_text( OUString() ); + m_xBtnNegRed->set_active( false ); + m_xBtnThousand->set_active( false ); + m_xBtnEngineering->set_active( false ); + } +} + + +/************************************************************************* +#* Method: UpdateFormatListBox_Impl +#*------------------------------------------------------------------------ +#* +#* Class: SvxNumberFormatTabPage +#* Function: Updates the format listbox and additionally the +#* string in the editbox is changed depending on +#* the bUpdateEdit flag. +#* Input: Flags for category and editbox. +#* Output: --- +#* +#************************************************************************/ + +void SvxNumberFormatTabPage::UpdateFormatListBox_Impl + ( + bool bCat, // Category or country/language ListBox? + bool bUpdateEdit + ) +{ + std::vector aEntryList; + short nFmtLbSelPos = 0; + short nTmpCatPos; + + if(bOneAreaFlag) + { + nTmpCatPos=nFixedCategory; + } + else + { + nTmpCatPos=m_xLbCategory->get_selected_index(); + } + + + if ( bCat ) + { + if(nTmpCatPos!=CAT_CURRENCY) + m_xLbCurrency->hide(); + else + m_xLbCurrency->show(); + + pNumFmtShell->CategoryChanged(nTmpCatPos,nFmtLbSelPos, aEntryList); + } + else + pNumFmtShell->LanguageChanged(m_xLbLanguage->get_active_id(), + nFmtLbSelPos,aEntryList); + + REMOVE_DONTKNOW() // possibly UI-Enable + + + if ( (!aEntryList.empty()) && (nFmtLbSelPos != SELPOS_NONE) ) + { + if(bUpdateEdit) + { + OUString aFormat=aEntryList[nFmtLbSelPos]; + m_xEdFormat->set_text(aFormat); + m_xFtComment->set_label(pNumFmtShell->GetComment4Entry(nFmtLbSelPos)); + } + + if(!bOneAreaFlag || !bCat) + { + FillFormatListBox_Impl( aEntryList ); + m_xLbFormat->select(nFmtLbSelPos); + + m_xFtComment->set_label(pNumFmtShell->GetComment4Entry(nFmtLbSelPos)); + if(pNumFmtShell->GetUserDefined4Entry(nFmtLbSelPos)) + { + if(pNumFmtShell->GetComment4Entry(nFmtLbSelPos).isEmpty()) + { + m_xFtComment->set_label(m_xLbCategory->get_text(1)); + } + } + ChangePreviewText( static_cast(nFmtLbSelPos) ); + } + + } + else + { + FillFormatListBox_Impl( aEntryList ); + if(nFmtLbSelPos != SELPOS_NONE) + { + m_xLbFormat->select(static_cast(nFmtLbSelPos)); + + m_xFtComment->set_label(pNumFmtShell->GetComment4Entry(nFmtLbSelPos)); + if(pNumFmtShell->GetUserDefined4Entry(nFmtLbSelPos)) + { + if(pNumFmtShell->GetComment4Entry(nFmtLbSelPos).isEmpty()) + { + m_xFtComment->set_label(m_xLbCategory->get_text(1)); + } + } + } + else + { + m_xLbFormat->select(-1); + } + + if ( bUpdateEdit ) + { + m_xEdFormat->set_text( OUString() ); + m_aWndPreview.NotifyChange( OUString() ); + } + } + + aEntryList.clear(); +} + + +/** + * Change visible checkbox according to category format + * if scientific format "Engineering notation" + * else "Thousands separator" + */ + +void SvxNumberFormatTabPage::UpdateThousandEngineeringCheckBox() +{ + bool bIsScientific = m_xLbCategory->get_selected_index() == CAT_SCIENTIFIC; + m_xBtnThousand->set_visible( !bIsScientific ); + m_xBtnEngineering->set_visible( bIsScientific ); +} + + +/** + * Change visible Edit box and Fixed text according to category format + * if fraction format "Denominator places" + * else "Decimal places" + */ + +void SvxNumberFormatTabPage::UpdateDecimalsDenominatorEditBox() +{ + bool bIsFraction = m_xLbCategory->get_selected_index() == CAT_FRACTION; + m_xFtDecimals->set_visible( !bIsFraction ); + m_xEdDecimals->set_visible( !bIsFraction ); + m_xFtDenominator->set_visible( bIsFraction ); + m_xEdDenominator->set_visible( bIsFraction ); +} + + +/************************************************************************* +#* Handle: DoubleClickHdl_Impl +#*------------------------------------------------------------------------ +#* +#* Class: SvxNumberFormatTabPage +#* Function: On a double click in the format listbox the +#* value is adopted and the OK button pushed. +#* Input: Pointer on the Listbox +#* Output: --- +#* +#************************************************************************/ +IMPL_LINK(SvxNumberFormatTabPage, DoubleClickHdl_Impl, weld::TreeView&, rLb, bool) +{ + SelFormatHdl_Impl(&rLb); + + SfxOkDialogController* pController = GetDialogController(); + assert(pController); + weld::Button& rOkButton = pController->GetOKButton(); + rOkButton.clicked(); + + return true; +} + +/************************************************************************* +#* Method: SelFormatHdl_Impl +#*------------------------------------------------------------------------ +#* +#* Class: SvxNumberFormatTabPage +#* Function: Is called when the language, the category or the format +#* is changed. Accordingly the settings are adjusted. +#* Input: Pointer on the Listbox +#* Output: --- +#* +#************************************************************************/ + +IMPL_LINK(SvxNumberFormatTabPage, SelFormatClickHdl_Impl, weld::Button&, rLb, void) +{ + SelFormatHdl_Impl(&rLb); +} + +IMPL_LINK(SvxNumberFormatTabPage, SelFormatTreeListBoxHdl_Impl, weld::TreeView&, rLb, void) +{ + SelFormatHdl_Impl(&rLb); +} + +IMPL_LINK(SvxNumberFormatTabPage, SelFormatListBoxHdl_Impl, weld::ComboBox&, rLb, void) +{ + SelFormatHdl_Impl(&rLb); +} + +void SvxNumberFormatTabPage::SelFormatHdl_Impl(weld::Widget* pLb) +{ + if (m_nLbFormatSelPosEdComment != SELPOS_NONE) + { + // Click handler is called before focus change handler, so finish + // comment editing of previous format, otherwise a new format will have + // the old comment displayed after LostFocusHdl_Impl() is called + // later. Also, clicking into another category invalidates the format + // list and SvxNumberFormatShell::SetComment4Entry() could either + // access a wrong format from aCurEntryList[nEntry] or crash there if + // the new vector has less elements. + LostFocusHdl_Impl(*pLb); + } + + if (pLb == m_xCbSourceFormat.get()) + { + EnableBySourceFormat_Impl(); // enable/disable everything else + if ( m_xCbSourceFormat->get_active() ) + return; // just disabled everything else + + // Reinit options enable/disable for current selection. + + // Current category may be UserDefined with no format entries defined. + if (m_xLbFormat->get_selected_index() == -1) + pLb = m_xLbCategory.get(); // continue with the current category selected + else + pLb = m_xLbFormat.get(); // continue with the current format selected + } + + sal_Int32 nTmpCatPos; + + if(bOneAreaFlag) + { + nTmpCatPos=nFixedCategory; + } + else + { + nTmpCatPos=m_xLbCategory->get_selected_index(); + } + + if (nTmpCatPos==CAT_CURRENCY && pLb == m_xLbCurrency.get()) + pNumFmtShell->SetCurrencySymbol(get_active_currency()); + + // Format-ListBox ---------------------------------------------------- + if (pLb == m_xLbFormat.get()) + { + sal_uLong nSelPos = m_xLbFormat->get_selected_index(); + short nFmtLbSelPos = static_cast(nSelPos); + + OUString aFormat = pNumFmtShell->GetFormat4Entry(nFmtLbSelPos); + OUString aComment = pNumFmtShell->GetComment4Entry(nFmtLbSelPos); + + if(pNumFmtShell->GetUserDefined4Entry(nFmtLbSelPos)) + { + if(aComment.isEmpty()) + { + aComment = m_xLbCategory->get_text(1); + } + } + + if ( !aFormat.isEmpty() ) + { + if (!m_xEdFormat->has_focus()) + m_xEdFormat->set_text( aFormat ); + m_xFtComment->set_label(aComment); + ChangePreviewText( static_cast(nSelPos) ); + } + + REMOVE_DONTKNOW() // possibly UI-Enable + + if ( pNumFmtShell->FindEntry( aFormat) ) + { + m_xIbAdd->set_sensitive(false ); + bool bIsUserDef=pNumFmtShell->IsUserDefined( aFormat ); + m_xIbRemove->set_sensitive(bIsUserDef); + m_xIbInfo->set_sensitive(bIsUserDef); + + } + else + { + m_xIbAdd->set_sensitive(true); + m_xIbInfo->set_sensitive(true); + m_xIbRemove->set_sensitive(false ); + m_xFtComment->set_label(m_xEdComment->get_text()); + + } + UpdateOptions_Impl( false ); + + return; + } + + + // category-ListBox ------------------------------------------------- + if (pLb == m_xLbCategory.get() || pLb == m_xLbCurrency.get()) + { + UpdateFormatListBox_Impl( true, true ); + EditHdl_Impl( nullptr ); + UpdateOptions_Impl( false ); + + return; + } + + + // language/country-ListBox ---------------------------------------------- + if (pLb == m_xLbLanguage->get_widget()) + { + UpdateFormatListBox_Impl( false, true ); + EditHdl_Impl(m_xEdFormat.get()); + + return; + } +} + + +/************************************************************************* +#* Method: ClickHdl_Impl, weld::Button& rIB +#*------------------------------------------------------------------------ +#* +#* Class: SvxNumberFormatTabPage +#* Function: Called when the add or delete button is pushed, +#* adjusts the number format list. +#* Input: Toolbox- Button +#* Output: --- +#* +#************************************************************************/ + +IMPL_LINK( SvxNumberFormatTabPage, ClickHdl_Impl, weld::Button&, rIB, void) +{ + Click_Impl(rIB); +} + +bool SvxNumberFormatTabPage::Click_Impl(weld::Button& rIB) +{ + sal_uLong nReturn = 0; + const sal_uLong nReturnChanged = 0x1; // THE boolean return value + const sal_uLong nReturnAdded = 0x2; // temp: format added + const sal_uLong nReturnOneArea = 0x4; // temp: one area but category changed => ignored + + if (&rIB == m_xIbAdd.get()) + { // Also called from FillItemSet() if a temporary currency format has + // to be added, not only if the Add button is enabled. + OUString aFormat = m_xEdFormat->get_text(); + std::vector aEntryList; + std::vector a2EntryList; + sal_uInt16 nCatLbSelPos = 0; + short nFmtLbSelPos = SELPOS_NONE; + sal_Int32 nErrPos=0; + + pNumFmtShell->SetCurCurrencyEntry(nullptr); + bool bAdded = pNumFmtShell->AddFormat( aFormat, nErrPos, + nCatLbSelPos, nFmtLbSelPos, + aEntryList); + if ( bAdded ) + nReturn |= nReturnChanged | nReturnAdded; + + if (m_xEdComment->get_visible()) + { + m_xEdFormat->grab_focus(); + m_xEdComment->hide(); + m_xFtComment->show(); + m_xFtComment->set_label(m_xEdComment->get_text()); + } + + if ( !nErrPos ) // Syntax ok? + { + // May be sorted under a different locale if LCID was parsed. + if (bAdded) + m_xLbLanguage->set_active_id(pNumFmtShell->GetCurLanguage()); + + if (nCatLbSelPos==CAT_CURRENCY) + set_active_currency(pNumFmtShell->GetCurrencySymbol()); + + if(bOneAreaFlag && (nFixedCategory!=nCatLbSelPos)) + { + if(bAdded) aEntryList.clear(); + pNumFmtShell->RemoveFormat( aFormat, + nCatLbSelPos, + nFmtLbSelPos, + a2EntryList); + a2EntryList.clear(); + m_xEdFormat->grab_focus(); + m_xEdFormat->select_region(0, -1); + nReturn |= nReturnOneArea; + } + else + { + if ( bAdded && (nFmtLbSelPos != SELPOS_NONE) ) + { + // everything all right + if(bOneAreaFlag) //@@ ??? + SetCategory(0); + else + SetCategory(nCatLbSelPos ); + + FillFormatListBox_Impl( aEntryList ); + if (m_xEdComment->get_text()!=m_xLbCategory->get_text(1)) + { + pNumFmtShell->SetComment4Entry(nFmtLbSelPos, + m_xEdComment->get_text()); + } + else + { + pNumFmtShell->SetComment4Entry(nFmtLbSelPos, + OUString()); + } + m_xLbFormat->select(static_cast(nFmtLbSelPos)); + m_xEdFormat->set_text( aFormat ); + + m_xEdComment->set_text(m_xLbCategory->get_text(1)); // String for user defined + + ChangePreviewText( static_cast(nFmtLbSelPos) ); + } + } + } + else // syntax error + { + m_xEdFormat->grab_focus(); + m_xEdFormat->select_region(nErrPos == -1 ? m_xEdFormat->get_text().getLength() : nErrPos, -1); + } + EditHdl_Impl(m_xEdFormat.get()); + nReturn = ((nReturn & nReturnOneArea) ? 0 : (nReturn & nReturnChanged)); + + aEntryList.clear(); + a2EntryList.clear(); + } + else if (&rIB == m_xIbRemove.get()) + { + OUString aFormat = m_xEdFormat->get_text(); + std::vector aEntryList; + sal_uInt16 nCatLbSelPos = 0; + short nFmtLbSelPos = SELPOS_NONE; + + pNumFmtShell->RemoveFormat( aFormat, + nCatLbSelPos, + nFmtLbSelPos, + aEntryList ); + + m_xEdComment->set_text(m_xLbCategory->get_text(1)); + + if( nFmtLbSelPos>=0 && o3tl::make_unsigned(nFmtLbSelPos)select(static_cast(nFmtLbSelPos)); + m_xEdFormat->set_text( aFormat ); + ChangePreviewText( static_cast(nFmtLbSelPos) ); + } + else + { + // set to "all/standard" + SetCategory(0); + SelFormatHdl_Impl(m_xLbCategory.get()); + } + + EditHdl_Impl(m_xEdFormat.get()); + + aEntryList.clear(); + } + else if (&rIB == m_xIbInfo.get()) + { + if (!m_xEdComment->get_visible()) + { + if (!m_xIbAdd->get_sensitive()) + // Editing for existing format. + m_nLbFormatSelPosEdComment = m_xLbFormat->get_selected_index(); + + m_xEdComment->set_text(m_xFtComment->get_label()); + m_xEdComment->show(); + m_xFtComment->hide(); + m_xEdComment->grab_focus(); + } + else + { + m_xEdFormat->grab_focus(); + m_xFtComment->set_label( m_xEdComment->get_text()); + m_xEdComment->hide(); + m_xFtComment->show(); + } + } + + return nReturn; +} + + +/************************************************************************* +#* Method: EditHdl_Impl +#*------------------------------------------------------------------------ +#* +#* Class: SvxNumberFormatTabPage +#* Function: When the entry in the edit field is changed +#* the preview is updated and +#* Input: Pointer on Editbox +#* Output: --- +#* +#************************************************************************/ + +IMPL_LINK(SvxNumberFormatTabPage, EditModifyHdl_Impl, weld::Entry&, rEdit, void) +{ + EditHdl_Impl(&rEdit); +} + +void SvxNumberFormatTabPage::EditHdl_Impl(const weld::Entry* pEdFormat) +{ + sal_uInt32 nCurKey = NUMKEY_UNDEFINED; + + if ( m_xEdFormat->get_text().isEmpty() ) + { + m_xIbAdd->set_sensitive(false ); + m_xIbRemove->set_sensitive(false ); + m_xIbInfo->set_sensitive(false ); + m_xFtComment->set_label(OUString()); + } + else + { + OUString aFormat = m_xEdFormat->get_text(); + MakePreviewText( aFormat ); + + if ( pNumFmtShell->FindEntry( aFormat, &nCurKey ) ) + { + m_xIbAdd->set_sensitive(false ); + bool bUserDef=pNumFmtShell->IsUserDefined( aFormat ); + + m_xIbRemove->set_sensitive(bUserDef); + m_xIbInfo->set_sensitive(bUserDef); + + if(bUserDef) + { + sal_uInt16 nTmpCurPos=pNumFmtShell->FindCurrencyFormat(aFormat ); + if (nTmpCurPos != sal_uInt16(-1)) + set_active_currency(nTmpCurPos); + } + short nPosi=pNumFmtShell->GetListPos4Entry( nCurKey, aFormat); + if(nPosi>=0) + m_xLbFormat->select(static_cast(nPosi)); + + } + else + { + + m_xIbAdd->set_sensitive(true); + m_xIbInfo->set_sensitive(true); + m_xIbRemove->set_sensitive(false ); + + m_xFtComment->set_label(m_xEdComment->get_text()); + + } + } + + if (pEdFormat) + { + pNumFmtShell->SetCurNumFmtKey( nCurKey ); + UpdateOptions_Impl( true ); + } +} + + +/************************************************************************* +#* Method: NotifyChange +#*------------------------------------------------------------------------ +#* +#* Class: SvxNumberFormatTabPage +#* Function: Does changes in the number attributes. +#* Input: Options- Controls +#* Output: --- +#* +#************************************************************************/ + +IMPL_LINK(SvxNumberFormatTabPage, OptClickHdl_Impl, weld::Button&, rOptCtrl, void) +{ + OptHdl_Impl(&rOptCtrl); +} + +IMPL_LINK(SvxNumberFormatTabPage, OptEditHdl_Impl, weld::SpinButton&, rEdit, void) +{ + OptHdl_Impl(&rEdit); +} + +void SvxNumberFormatTabPage::OptHdl_Impl(const weld::Widget* pOptCtrl) +{ + if ( !(pOptCtrl == m_xEdLeadZeroes.get() + || pOptCtrl == m_xEdDecimals.get() + || pOptCtrl == m_xEdDenominator.get() + || pOptCtrl == m_xBtnNegRed.get() + || pOptCtrl == m_xBtnThousand.get() + || pOptCtrl == m_xBtnEngineering.get())) + return; + + OUString aFormat; + bool bThousand = ( m_xBtnThousand->get_visible() && m_xBtnThousand->get_sensitive() && m_xBtnThousand->get_active() ) + || ( m_xBtnEngineering->get_visible() && m_xBtnEngineering->get_sensitive() && m_xBtnEngineering->get_active() ); + bool bNegRed = m_xBtnNegRed->get_sensitive() && m_xBtnNegRed->get_active(); + sal_uInt16 nPrecision = (m_xEdDecimals->get_sensitive() && m_xEdDecimals->get_visible()) + ? static_cast(m_xEdDecimals->get_value()) + : ( (m_xEdDenominator->get_sensitive() && m_xEdDenominator->get_visible()) + ? static_cast(m_xEdDenominator->get_value()) + : sal_uInt16(0) ); + sal_uInt16 nLeadZeroes = (m_xEdLeadZeroes->get_sensitive()) + ? static_cast(m_xEdLeadZeroes->get_value()) + : sal_uInt16(0); + if ( pNumFmtShell->GetStandardName() == m_xEdFormat->get_text() ) + { + m_xEdDecimals->set_value(nPrecision); + } + + pNumFmtShell->MakeFormat( aFormat, + bThousand, bNegRed, + nPrecision, nLeadZeroes, + static_cast(m_xLbFormat->get_selected_index()) ); + + m_xEdFormat->set_text( aFormat ); + MakePreviewText( aFormat ); + + if ( pNumFmtShell->FindEntry( aFormat ) ) + { + m_xIbAdd->set_sensitive(false ); + bool bUserDef=pNumFmtShell->IsUserDefined( aFormat ); + m_xIbRemove->set_sensitive(bUserDef); + m_xIbInfo->set_sensitive(bUserDef); + EditHdl_Impl(m_xEdFormat.get()); + + } + else + { + EditHdl_Impl( nullptr ); + m_xLbFormat->select(-1); + } +} + +/************************************************************************* +#* Method: LostFocusHdl_Impl +#*------------------------------------------------------------------------ +#* +#* Class: SvxNumberFormatTabPage +#* Function: Does changes in the number attributes. +#* Input: Options- Controls +#* Output: --- +#* +#************************************************************************/ + +IMPL_LINK_NOARG(SvxNumberFormatTabPage, LostFocusHdl_Impl, weld::Widget&, void) +{ + if (!pNumFmtShell) + return; + + const bool bAddSensitive = m_xIbAdd->get_sensitive(); + if (bAddSensitive || m_nLbFormatSelPosEdComment != SELPOS_NONE) + // Comment editing was possible. + m_xFtComment->set_label(m_xEdComment->get_text()); + + m_xEdComment->hide(); + m_xFtComment->show(); + if (m_nLbFormatSelPosEdComment != SELPOS_NONE) + { + // Save edited comment of existing format. + pNumFmtShell->SetComment4Entry( m_nLbFormatSelPosEdComment, m_xEdComment->get_text()); + m_nLbFormatSelPosEdComment = SELPOS_NONE; + } + if (!bAddSensitive) + { + // String for user defined, if present + OUString sEntry = m_xLbCategory->n_children() > 1 ? m_xLbCategory->get_text(1) : OUString(); + m_xEdComment->set_text(sEntry); + } +} + +/************************************************************************* +#* Method: NotifyChange +#*------------------------------------------------------------------------ +#* +#* Class: SvxNumberFormatTabPage +#* Function: Does changes in the number attributes. +#* Input: Options- Controls +#* Output: --- +#* +#************************************************************************/ + +OUString SvxNumberFormatTabPage::GetExpColorString( + Color*& rpPreviewColor, const OUString& rFormatStr, short nTmpCatPos) +{ + SvxNumValCategory i; + switch (nTmpCatPos) + { + case CAT_ALL: i=SvxNumValCategory::Standard; break; + + case CAT_NUMBER: i=SvxNumValCategory::Standard; break; + + case CAT_PERCENT: i=SvxNumValCategory::Percent; break; + + case CAT_CURRENCY: i=SvxNumValCategory::Currency; break; + + case CAT_DATE: i=SvxNumValCategory::Date; break; + + case CAT_TIME: i=SvxNumValCategory::Time; break; + + case CAT_SCIENTIFIC: i=SvxNumValCategory::Scientific; break; + + case CAT_FRACTION: i=SvxNumValCategory::Fraction; break; + + case CAT_BOOLEAN: i=SvxNumValCategory::Boolean; break; + + case CAT_USERDEFINED: i=SvxNumValCategory::Standard; break; + + case CAT_TEXT: + default: i=SvxNumValCategory::NoValue;break; + } + double fVal = fSvxNumValConst[i]; + + OUString aPreviewString; + pNumFmtShell->MakePrevStringFromVal( rFormatStr, aPreviewString, rpPreviewColor, fVal ); + return aPreviewString; +} + +void SvxNumberFormatTabPage::MakePreviewText( const OUString& rFormat ) +{ + OUString aPreviewString; + Color* pPreviewColor = nullptr; + pNumFmtShell->MakePreviewString( rFormat, aPreviewString, pPreviewColor ); + m_aWndPreview.NotifyChange( aPreviewString, pPreviewColor ); +} + +void SvxNumberFormatTabPage::ChangePreviewText( sal_uInt16 nPos ) +{ + OUString aPreviewString; + Color* pPreviewColor = nullptr; + pNumFmtShell->FormatChanged( nPos, aPreviewString, pPreviewColor ); + m_aWndPreview.NotifyChange( aPreviewString, pPreviewColor ); +} + +void SvxNumberFormatTabPage::FillCurrencyBox() +{ + std::vector aList; + + sal_uInt16 nSelPos=0; + pNumFmtShell->GetCurrencySymbols(aList, &nSelPos); + + m_xLbCurrency->freeze(); + m_xLbCurrency->clear(); + bLegacyAutomaticCurrency = false; + for (std::vector::iterator i = aList.begin() + 1;i != aList.end(); ++i) + m_xLbCurrency->append_text(*i); + m_xLbCurrency->thaw(); + + set_active_currency(nSelPos); +} + +void SvxNumberFormatTabPage::SetCategory(sal_uInt16 nPos) +{ + int nCurCategory = m_xLbCategory->get_selected_index(); + sal_uInt16 nTmpCatPos; + + if (bOneAreaFlag) + { + nTmpCatPos=nFixedCategory; + } + else + { + nTmpCatPos=nPos; + } + + if(m_xLbCategory->n_children()==1 || nCurCategory!=nPos) + { + if(nTmpCatPos!=CAT_CURRENCY) + m_xLbCurrency->hide(); + else + m_xLbCurrency->show(); + } + m_xLbCategory->select(nPos); +} + +/* to support Writer text field language handling an + additional entry needs to be inserted into the ListBox + which marks a certain language as automatically detected + Additionally the "Default" language is removed +*/ +void SvxNumberFormatTabPage::AddAutomaticLanguage_Impl(LanguageType eAutoLang, bool bSelect) +{ + m_xLbLanguage->remove_id(LANGUAGE_SYSTEM); + m_xLbLanguage->append(eAutoLang, sAutomaticLangEntry); + if (bSelect) + m_xLbLanguage->set_active_id(eAutoLang); +} + +void SvxNumberFormatTabPage::PageCreated(const SfxAllItemSet& aSet) +{ + const SvxNumberInfoItem* pNumberInfoItem = aSet.GetItem(SID_ATTR_NUMBERFORMAT_INFO, false); + if (pNumberInfoItem && !pNumItem) + pNumItem.reset(pNumberInfoItem->Clone()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/numpages.cxx b/cui/source/tabpages/numpages.cxx new file mode 100644 index 000000000..b921e6cde --- /dev/null +++ b/cui/source/tabpages/numpages.cxx @@ -0,0 +1,3354 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace css; +using namespace css::uno; +using namespace css::beans; +using namespace css::lang; +using namespace css::text; +using namespace css::container; +using namespace css::style; + +#define SHOW_NUMBERING 0 +#define SHOW_BULLET 1 +#define SHOW_BITMAP 2 + +#define MAX_BMP_WIDTH 16 +#define MAX_BMP_HEIGHT 16 +#define SEARCHPATH_DELIMITER u';' +#define SEARCHFILENAME_DELIMITER u'/' + +static bool bLastRelative = false; + +static SvxNumSettings_Impl* lcl_CreateNumSettingsPtr(const Sequence& rLevelProps) +{ + const PropertyValue* pValues = rLevelProps.getConstArray(); + SvxNumSettings_Impl* pNew = new SvxNumSettings_Impl; + for(sal_Int32 j = 0; j < rLevelProps.getLength(); j++) + { + if ( pValues[j].Name == "NumberingType" ) + { + sal_Int16 nTmp; + if (pValues[j].Value >>= nTmp) + pNew->nNumberType = static_cast(nTmp); + } + else if ( pValues[j].Name == "Prefix" ) + pValues[j].Value >>= pNew->sPrefix; + else if ( pValues[j].Name == "Suffix" ) + pValues[j].Value >>= pNew->sSuffix; + else if ( pValues[j].Name == "ParentNumbering" ) + pValues[j].Value >>= pNew->nParentNumbering; + else if ( pValues[j].Name == "BulletChar" ) + pValues[j].Value >>= pNew->sBulletChar; + else if ( pValues[j].Name == "BulletFontName" ) + pValues[j].Value >>= pNew->sBulletFont; + } + return pNew; +} + +// the selection of bullets from the OpenSymbol +static const sal_Unicode aBulletTypes[] = +{ + 0x2022, + 0x25cf, + 0xe00c, + 0xe00a, + 0x2794, + 0x27a2, + 0x2717, + 0x2714 +}; + +// Is one of the masked formats set? +static bool lcl_IsNumFmtSet(SvxNumRule const * pNum, sal_uInt16 nLevelMask) +{ + bool bRet = false; + sal_uInt16 nMask = 1; + for( sal_uInt16 i = 0; i < SVX_MAX_NUM && !bRet; i++ ) + { + if(nLevelMask & nMask) + bRet |= nullptr != pNum->Get( i ); + nMask <<= 1 ; + } + return bRet; +} + +static const vcl::Font& lcl_GetDefaultBulletFont() +{ + static vcl::Font aDefBulletFont = [&]() + { + vcl::Font tmp("OpenSymbol", "", Size(0, 14)); + tmp.SetCharSet( RTL_TEXTENCODING_SYMBOL ); + tmp.SetFamily( FAMILY_DONTKNOW ); + tmp.SetPitch( PITCH_DONTKNOW ); + tmp.SetWeight( WEIGHT_DONTKNOW ); + tmp.SetTransparent( true ); + return tmp; + }(); + return aDefBulletFont; +} + +SvxSingleNumPickTabPage::SvxSingleNumPickTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/picknumberingpage.ui", "PickNumberingPage", &rSet) + , nActNumLvl(SAL_MAX_UINT16) + , bModified(false) + , bPreset(false) + , nNumItemId(SID_ATTR_NUMBERING_RULE) + , m_xExamplesVS(new SvxNumValueSet(m_xBuilder->weld_scrolled_window("valuesetwin"))) + , m_xExamplesVSWin(new weld::CustomWeld(*m_xBuilder, "valueset", *m_xExamplesVS)) +{ + SetExchangeSupport(); + m_xExamplesVS->init(NumberingPageType::SINGLENUM); + m_xExamplesVS->SetSelectHdl(LINK(this, SvxSingleNumPickTabPage, NumSelectHdl_Impl)); + m_xExamplesVS->SetDoubleClickHdl(LINK(this, SvxSingleNumPickTabPage, DoubleClickHdl_Impl)); + + Reference xDefNum = SvxNumOptionsTabPageHelper::GetNumberingProvider(); + if(!xDefNum.is()) + return; + + Sequence< Sequence< PropertyValue > > aNumberings; + const Locale& rLocale = Application::GetSettings().GetLanguageTag().getLocale(); + try + { + aNumberings = + xDefNum->getDefaultContinuousNumberingLevels( rLocale ); + + + sal_Int32 nLength = std::min(aNumberings.getLength(), NUM_VALUSET_COUNT); + + const Sequence* pValuesArr = aNumberings.getConstArray(); + for(sal_Int32 i = 0; i < nLength; i++) + { + SvxNumSettings_Impl* pNew = lcl_CreateNumSettingsPtr(pValuesArr[i]); + aNumSettingsArr.push_back(std::unique_ptr(pNew)); + } + } + catch(const Exception&) + { + } + Reference xFormat(xDefNum, UNO_QUERY); + m_xExamplesVS->SetNumberingSettings(aNumberings, xFormat, rLocale); +} + +SvxSingleNumPickTabPage::~SvxSingleNumPickTabPage() +{ + m_xExamplesVSWin.reset(); + m_xExamplesVS.reset(); +} + +std::unique_ptr SvxSingleNumPickTabPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet) +{ + return std::make_unique(pPage, pController, *rAttrSet); +} + +bool SvxSingleNumPickTabPage::FillItemSet( SfxItemSet* rSet ) +{ + if( (bPreset || bModified) && pSaveNum) + { + *pSaveNum = *pActNum; + rSet->Put(SvxNumBulletItem( *pSaveNum, nNumItemId )); + rSet->Put(SfxBoolItem(SID_PARAM_NUM_PRESET, bPreset)); + } + + return bModified; +} + +void SvxSingleNumPickTabPage::ActivatePage(const SfxItemSet& rSet) +{ + const SfxPoolItem* pItem; + bPreset = false; + bool bIsPreset = false; + const SfxItemSet* pExampleSet = GetDialogExampleSet(); + if(pExampleSet) + { + if(SfxItemState::SET == pExampleSet->GetItemState(SID_PARAM_NUM_PRESET, false, &pItem)) + bIsPreset = static_cast(pItem)->GetValue(); + if(SfxItemState::SET == pExampleSet->GetItemState(SID_PARAM_CUR_NUM_LEVEL, false, &pItem)) + nActNumLvl = static_cast(pItem)->GetValue(); + } + if(SfxItemState::SET == rSet.GetItemState(nNumItemId, false, &pItem)) + { + pSaveNum.reset( new SvxNumRule(*static_cast(pItem)->GetNumRule()) ); + } + if(pActNum && *pSaveNum != *pActNum) + { + *pActNum = *pSaveNum; + m_xExamplesVS->SetNoSelection(); + } + + if(pActNum && (!lcl_IsNumFmtSet(pActNum.get(), nActNumLvl) || bIsPreset)) + { + m_xExamplesVS->SelectItem(1); + NumSelectHdl_Impl(m_xExamplesVS.get()); + bPreset = true; + } + bPreset |= bIsPreset; + + bModified = false; +} + +DeactivateRC SvxSingleNumPickTabPage::DeactivatePage(SfxItemSet *_pSet) +{ + if(_pSet) + FillItemSet(_pSet); + return DeactivateRC::LeavePage; +} + +void SvxSingleNumPickTabPage::Reset( const SfxItemSet* rSet ) +{ + const SfxPoolItem* pItem; + + // in Draw the item exists as WhichId, in Writer only as SlotId + SfxItemState eState = rSet->GetItemState(SID_ATTR_NUMBERING_RULE, false, &pItem); + if(eState != SfxItemState::SET) + { + nNumItemId = rSet->GetPool()->GetWhich(SID_ATTR_NUMBERING_RULE); + eState = rSet->GetItemState(nNumItemId, false, &pItem); + + if( eState != SfxItemState::SET ) + { + pItem = &static_cast< const SvxNumBulletItem& >( rSet->Get( nNumItemId ) ); + eState = SfxItemState::SET; + } + } + DBG_ASSERT(eState == SfxItemState::SET, "no item found!"); + pSaveNum.reset( new SvxNumRule(*static_cast(pItem)->GetNumRule()) ); + + if(!pActNum) + pActNum.reset( new SvxNumRule(*pSaveNum) ); + else if(*pSaveNum != *pActNum) + *pActNum = *pSaveNum; +} + +IMPL_LINK_NOARG(SvxSingleNumPickTabPage, NumSelectHdl_Impl, ValueSet*, void) +{ + if(!pActNum) + return; + + bPreset = false; + bModified = true; + sal_uInt16 nIdx = m_xExamplesVS->GetSelectedItemId() - 1; + DBG_ASSERT(aNumSettingsArr.size() > nIdx, "wrong index"); + if(aNumSettingsArr.size() <= nIdx) + return; + SvxNumSettings_Impl* _pSet = aNumSettingsArr[nIdx].get(); + SvxNumType eNewType = _pSet->nNumberType; + const sal_Unicode cLocalPrefix = !_pSet->sPrefix.isEmpty() ? _pSet->sPrefix[0] : 0; + const sal_Unicode cLocalSuffix = !_pSet->sSuffix.isEmpty() ? _pSet->sSuffix[0] : 0; + + sal_uInt16 nMask = 1; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + { + SvxNumberFormat aFmt(pActNum->GetLevel(i)); + aFmt.SetNumberingType(eNewType); + if(cLocalPrefix == ' ') + aFmt.SetPrefix( "" ); + else + aFmt.SetPrefix(_pSet->sPrefix); + if(cLocalSuffix == ' ') + aFmt.SetSuffix( "" ); + else + aFmt.SetSuffix(_pSet->sSuffix); + aFmt.SetCharFormatName(""); + aFmt.SetBulletRelSize(100); + pActNum->SetLevel(i, aFmt); + } + nMask <<= 1; + } +} + +IMPL_LINK_NOARG(SvxSingleNumPickTabPage, DoubleClickHdl_Impl, ValueSet*, void) +{ + NumSelectHdl_Impl(m_xExamplesVS.get()); + weld::Button& rOk = GetDialogController()->GetOKButton(); + rOk.clicked(); +} + +SvxBulletPickTabPage::SvxBulletPickTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/pickbulletpage.ui", "PickBulletPage", &rSet) + , nActNumLvl(SAL_MAX_UINT16) + , bModified(false) + , bPreset(false) + , nNumItemId(SID_ATTR_NUMBERING_RULE) + , m_xExamplesVS(new SvxNumValueSet(m_xBuilder->weld_scrolled_window("valuesetwin"))) + , m_xExamplesVSWin(new weld::CustomWeld(*m_xBuilder, "valueset", *m_xExamplesVS)) +{ + SetExchangeSupport(); + m_xExamplesVS->init(NumberingPageType::BULLET); + m_xExamplesVS->SetSelectHdl(LINK(this, SvxBulletPickTabPage, NumSelectHdl_Impl)); + m_xExamplesVS->SetDoubleClickHdl(LINK(this, SvxBulletPickTabPage, DoubleClickHdl_Impl)); +} + +SvxBulletPickTabPage::~SvxBulletPickTabPage() +{ + m_xExamplesVSWin.reset(); + m_xExamplesVS.reset(); +} + +std::unique_ptr SvxBulletPickTabPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet) +{ + return std::make_unique(pPage, pController, *rAttrSet); +} + +bool SvxBulletPickTabPage::FillItemSet( SfxItemSet* rSet ) +{ + if( (bPreset || bModified) && pActNum) + { + *pSaveNum = *pActNum; + rSet->Put(SvxNumBulletItem( *pSaveNum, nNumItemId )); + rSet->Put(SfxBoolItem(SID_PARAM_NUM_PRESET, bPreset)); + } + return bModified; +} + +void SvxBulletPickTabPage::ActivatePage(const SfxItemSet& rSet) +{ + const SfxPoolItem* pItem; + bPreset = false; + bool bIsPreset = false; + const SfxItemSet* pExampleSet = GetDialogExampleSet(); + if(pExampleSet) + { + if(SfxItemState::SET == pExampleSet->GetItemState(SID_PARAM_NUM_PRESET, false, &pItem)) + bIsPreset = static_cast(pItem)->GetValue(); + if(SfxItemState::SET == pExampleSet->GetItemState(SID_PARAM_CUR_NUM_LEVEL, false, &pItem)) + nActNumLvl = static_cast(pItem)->GetValue(); + } + if(SfxItemState::SET == rSet.GetItemState(nNumItemId, false, &pItem)) + { + pSaveNum.reset( new SvxNumRule(*static_cast(pItem)->GetNumRule()) ); + } + if(pActNum && *pSaveNum != *pActNum) + { + *pActNum = *pSaveNum; + m_xExamplesVS->SetNoSelection(); + } + + if(pActNum && (!lcl_IsNumFmtSet(pActNum.get(), nActNumLvl) || bIsPreset)) + { + m_xExamplesVS->SelectItem(1); + NumSelectHdl_Impl(m_xExamplesVS.get()); + bPreset = true; + } + bPreset |= bIsPreset; + bModified = false; +} + +DeactivateRC SvxBulletPickTabPage::DeactivatePage(SfxItemSet *_pSet) +{ + if(_pSet) + FillItemSet(_pSet); + return DeactivateRC::LeavePage; +} + +void SvxBulletPickTabPage::Reset( const SfxItemSet* rSet ) +{ + const SfxPoolItem* pItem; + // in Draw the item exists as WhichId, in Writer only as SlotId + SfxItemState eState = rSet->GetItemState(SID_ATTR_NUMBERING_RULE, false, &pItem); + if(eState != SfxItemState::SET) + { + nNumItemId = rSet->GetPool()->GetWhich(SID_ATTR_NUMBERING_RULE); + eState = rSet->GetItemState(nNumItemId, false, &pItem); + + if( eState != SfxItemState::SET ) + { + pItem = &static_cast< const SvxNumBulletItem& >( rSet->Get( nNumItemId ) ); + eState = SfxItemState::SET; + } + + } + DBG_ASSERT(eState == SfxItemState::SET, "no item found!"); + pSaveNum.reset( new SvxNumRule(*static_cast(pItem)->GetNumRule()) ); + + if(!pActNum) + pActNum.reset( new SvxNumRule(*pSaveNum) ); + else if(*pSaveNum != *pActNum) + *pActNum = *pSaveNum; +} + +IMPL_LINK_NOARG(SvxBulletPickTabPage, NumSelectHdl_Impl, ValueSet*, void) +{ + if(!pActNum) + return; + + bPreset = false; + bModified = true; + sal_Unicode cChar = aBulletTypes[m_xExamplesVS->GetSelectedItemId() - 1]; + const vcl::Font& rActBulletFont = lcl_GetDefaultBulletFont(); + + sal_uInt16 nMask = 1; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + { + SvxNumberFormat aFmt(pActNum->GetLevel(i)); + aFmt.SetNumberingType( SVX_NUM_CHAR_SPECIAL ); + // #i93908# clear suffix for bullet lists + aFmt.SetPrefix( OUString() ); + aFmt.SetSuffix( OUString() ); + aFmt.SetBulletFont(&rActBulletFont); + aFmt.SetBulletChar(cChar ); + aFmt.SetCharFormatName(sBulletCharFormatName); + aFmt.SetBulletRelSize(45); + pActNum->SetLevel(i, aFmt); + } + nMask <<= 1; + } +} + +IMPL_LINK_NOARG(SvxBulletPickTabPage, DoubleClickHdl_Impl, ValueSet*, void) +{ + NumSelectHdl_Impl(m_xExamplesVS.get()); + weld::Button& rOk = GetDialogController()->GetOKButton(); + rOk.clicked(); +} + +void SvxBulletPickTabPage::PageCreated(const SfxAllItemSet& aSet) +{ + const SfxStringItem* pBulletCharFmt = aSet.GetItem(SID_BULLET_CHAR_FMT, false); + + if (pBulletCharFmt) + sBulletCharFormatName = pBulletCharFmt->GetValue(); +} + +SvxNumPickTabPage::SvxNumPickTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/pickoutlinepage.ui", "PickOutlinePage", &rSet) + , nActNumLvl(SAL_MAX_UINT16) + , nNumItemId(SID_ATTR_NUMBERING_RULE) + , bModified(false) + , bPreset(false) + , m_xExamplesVS(new SvxNumValueSet(m_xBuilder->weld_scrolled_window("valuesetwin"))) + , m_xExamplesVSWin(new weld::CustomWeld(*m_xBuilder, "valueset", *m_xExamplesVS)) +{ + SetExchangeSupport(); + + m_xExamplesVS->init(NumberingPageType::OUTLINE); + m_xExamplesVS->SetSelectHdl(LINK(this, SvxNumPickTabPage, NumSelectHdl_Impl)); + m_xExamplesVS->SetDoubleClickHdl(LINK(this, SvxNumPickTabPage, DoubleClickHdl_Impl)); + + Reference xDefNum = SvxNumOptionsTabPageHelper::GetNumberingProvider(); + if(!xDefNum.is()) + return; + + Sequence > aOutlineAccess; + const Locale& rLocale = Application::GetSettings().GetLanguageTag().getLocale(); + try + { + aOutlineAccess = xDefNum->getDefaultOutlineNumberings( rLocale ); + + for(sal_Int32 nItem = 0; + nItem < aOutlineAccess.getLength() && nItem < NUM_VALUSET_COUNT; + nItem++ ) + { + SvxNumSettingsArr_Impl& rItemArr = aNumSettingsArrays[ nItem ]; + + Reference xLevel = aOutlineAccess.getConstArray()[nItem]; + for(sal_Int32 nLevel = 0; nLevel < xLevel->getCount() && nLevel < 5; nLevel++) + { + Any aValueAny = xLevel->getByIndex(nLevel); + Sequence aLevelProps; + aValueAny >>= aLevelProps; + SvxNumSettings_Impl* pNew = lcl_CreateNumSettingsPtr(aLevelProps); + rItemArr.push_back( std::unique_ptr(pNew) ); + } + } + } + catch(const Exception&) + { + } + Reference xFormat(xDefNum, UNO_QUERY); + m_xExamplesVS->SetOutlineNumberingSettings(aOutlineAccess, xFormat, rLocale); +} + +SvxNumPickTabPage::~SvxNumPickTabPage() +{ + m_xExamplesVSWin.reset(); + m_xExamplesVS.reset(); +} + +std::unique_ptr SvxNumPickTabPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet) +{ + return std::make_unique(pPage, pController, *rAttrSet); +} + +bool SvxNumPickTabPage::FillItemSet( SfxItemSet* rSet ) +{ + if( (bPreset || bModified) && pActNum) + { + *pSaveNum = *pActNum; + rSet->Put(SvxNumBulletItem( *pSaveNum, nNumItemId )); + rSet->Put(SfxBoolItem(SID_PARAM_NUM_PRESET, bPreset)); + } + return bModified; +} + +void SvxNumPickTabPage::ActivatePage(const SfxItemSet& rSet) +{ + const SfxPoolItem* pItem; + bPreset = false; + bool bIsPreset = false; + const SfxItemSet* pExampleSet = GetDialogExampleSet(); + if(pExampleSet) + { + if(SfxItemState::SET == pExampleSet->GetItemState(SID_PARAM_NUM_PRESET, false, &pItem)) + bIsPreset = static_cast(pItem)->GetValue(); + if(SfxItemState::SET == pExampleSet->GetItemState(SID_PARAM_CUR_NUM_LEVEL, false, &pItem)) + nActNumLvl = static_cast(pItem)->GetValue(); + } + if(SfxItemState::SET == rSet.GetItemState(nNumItemId, false, &pItem)) + { + pSaveNum.reset( new SvxNumRule(*static_cast(pItem)->GetNumRule()) ); + } + if(pActNum && *pSaveNum != *pActNum) + { + *pActNum = *pSaveNum; + m_xExamplesVS->SetNoSelection(); + } + + if(pActNum && (!lcl_IsNumFmtSet(pActNum.get(), nActNumLvl) || bIsPreset)) + { + m_xExamplesVS->SelectItem(1); + NumSelectHdl_Impl(m_xExamplesVS.get()); + bPreset = true; + } + bPreset |= bIsPreset; + bModified = false; +} + +DeactivateRC SvxNumPickTabPage::DeactivatePage(SfxItemSet *_pSet) +{ + if(_pSet) + FillItemSet(_pSet); + return DeactivateRC::LeavePage; +} + +void SvxNumPickTabPage::Reset( const SfxItemSet* rSet ) +{ + const SfxPoolItem* pItem; + // in Draw the item exists as WhichId, in Writer only as SlotId + SfxItemState eState = rSet->GetItemState(SID_ATTR_NUMBERING_RULE, false, &pItem); + if(eState != SfxItemState::SET) + { + nNumItemId = rSet->GetPool()->GetWhich(SID_ATTR_NUMBERING_RULE); + eState = rSet->GetItemState(nNumItemId, false, &pItem); + + if( eState != SfxItemState::SET ) + { + pItem = &static_cast< const SvxNumBulletItem& >( rSet->Get( nNumItemId ) ); + eState = SfxItemState::SET; + } + + } + DBG_ASSERT(eState == SfxItemState::SET, "no item found!"); + pSaveNum.reset( new SvxNumRule(*static_cast(pItem)->GetNumRule()) ); + + if(!pActNum) + pActNum.reset( new SvxNumRule(*pSaveNum) ); + else if(*pSaveNum != *pActNum) + *pActNum = *pSaveNum; + +} + +// all levels are changed here +IMPL_LINK_NOARG(SvxNumPickTabPage, NumSelectHdl_Impl, ValueSet*, void) +{ + if(!pActNum) + return; + + bPreset = false; + bModified = true; + + const FontList* pList = nullptr; + + SvxNumSettingsArr_Impl& rItemArr = aNumSettingsArrays[m_xExamplesVS->GetSelectedItemId() - 1]; + + const vcl::Font& rActBulletFont = lcl_GetDefaultBulletFont(); + SvxNumSettings_Impl* pLevelSettings = nullptr; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(rItemArr.size() > i) + pLevelSettings = rItemArr[i].get(); + if(!pLevelSettings) + break; + SvxNumberFormat aFmt(pActNum->GetLevel(i)); + aFmt.SetNumberingType( pLevelSettings->nNumberType ); + sal_uInt16 nUpperLevelOrChar = static_cast(pLevelSettings->nParentNumbering); + if(aFmt.GetNumberingType() == SVX_NUM_CHAR_SPECIAL) + { + // #i93908# clear suffix for bullet lists + aFmt.SetPrefix(OUString()); + aFmt.SetSuffix(OUString()); + if( !pLevelSettings->sBulletFont.isEmpty() && + pLevelSettings->sBulletFont != rActBulletFont.GetFamilyName()) + { + //search for the font + if(!pList) + { + SfxObjectShell* pCurDocShell = SfxObjectShell::Current(); + const SvxFontListItem* pFontListItem = + static_cast( pCurDocShell + ->GetItem( SID_ATTR_CHAR_FONTLIST )); + pList = pFontListItem ? pFontListItem->GetFontList() : nullptr; + } + if(pList && pList->IsAvailable( pLevelSettings->sBulletFont ) ) + { + FontMetric aFontMetric = pList->Get( + pLevelSettings->sBulletFont,WEIGHT_NORMAL, ITALIC_NONE); + vcl::Font aFont(aFontMetric); + aFmt.SetBulletFont(&aFont); + } + else + { + //if it cannot be found then create a new one + vcl::Font aCreateFont( pLevelSettings->sBulletFont, + OUString(), Size( 0, 14 ) ); + aCreateFont.SetCharSet( RTL_TEXTENCODING_DONTKNOW ); + aCreateFont.SetFamily( FAMILY_DONTKNOW ); + aCreateFont.SetPitch( PITCH_DONTKNOW ); + aCreateFont.SetWeight( WEIGHT_DONTKNOW ); + aCreateFont.SetTransparent( true ); + aFmt.SetBulletFont( &aCreateFont ); + } + } + else + aFmt.SetBulletFont( &rActBulletFont ); + + aFmt.SetBulletChar( !pLevelSettings->sBulletChar.isEmpty() + ? pLevelSettings->sBulletChar[0] + : 0 ); + aFmt.SetCharFormatName( sBulletCharFormatName ); + aFmt.SetBulletRelSize(45); + } + else + { + aFmt.SetIncludeUpperLevels(sal::static_int_cast< sal_uInt8 >(0 != nUpperLevelOrChar ? pActNum->GetLevelCount() : 0)); + aFmt.SetCharFormatName(sNumCharFmtName); + aFmt.SetBulletRelSize(100); + // #i93908# + aFmt.SetPrefix(pLevelSettings->sPrefix); + aFmt.SetSuffix(pLevelSettings->sSuffix); + } + pActNum->SetLevel(i, aFmt); + } +} + +IMPL_LINK_NOARG(SvxNumPickTabPage, DoubleClickHdl_Impl, ValueSet*, void) +{ + NumSelectHdl_Impl(m_xExamplesVS.get()); + weld::Button& rOk = GetDialogController()->GetOKButton(); + rOk.clicked(); +} + +void SvxNumPickTabPage::PageCreated(const SfxAllItemSet& aSet) +{ + const SfxStringItem* pNumCharFmt = aSet.GetItem(SID_NUM_CHAR_FMT, false); + const SfxStringItem* pBulletCharFmt = aSet.GetItem(SID_BULLET_CHAR_FMT, false); + + + if (pNumCharFmt &&pBulletCharFmt) + SetCharFormatNames( pNumCharFmt->GetValue(),pBulletCharFmt->GetValue()); +} + +SvxBitmapPickTabPage::SvxBitmapPickTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/pickgraphicpage.ui", "PickGraphicPage", &rSet) + , nActNumLvl(SAL_MAX_UINT16) + , nNumItemId(SID_ATTR_NUMBERING_RULE) + , bModified(false) + , bPreset(false) + , m_xErrorText(m_xBuilder->weld_label("errorft")) + , m_xBtBrowseFile(m_xBuilder->weld_button("browseBtn")) + , m_xExamplesVS(new SvxBmpNumValueSet(m_xBuilder->weld_scrolled_window("valuesetwin"))) + , m_xExamplesVSWin(new weld::CustomWeld(*m_xBuilder, "valueset", *m_xExamplesVS)) +{ + SetExchangeSupport(); + + m_xExamplesVS->init(); + m_xExamplesVS->SetSelectHdl(LINK(this, SvxBitmapPickTabPage, NumSelectHdl_Impl)); + m_xExamplesVS->SetDoubleClickHdl(LINK(this, SvxBitmapPickTabPage, DoubleClickHdl_Impl)); + m_xBtBrowseFile->connect_clicked(LINK(this, SvxBitmapPickTabPage, ClickAddBrowseHdl_Impl)); + + eCoreUnit = rSet.GetPool()->GetMetric(rSet.GetPool()->GetWhich(SID_ATTR_NUMBERING_RULE)); + + // determine graphic name + GalleryExplorer::FillObjList(GALLERY_THEME_BULLETS, aGrfNames); + + size_t i = 0; + for (auto & grfName : aGrfNames) + { + m_xExamplesVS->InsertItem( i + 1, i); + + INetURLObject aObj(grfName); + if(aObj.GetProtocol() == INetProtocol::File) + grfName = aObj.PathToFileName(); + + m_xExamplesVS->SetItemText( i + 1, grfName ); + ++i; + } + + if(aGrfNames.empty()) + { + m_xErrorText->show(); + } + else + { + m_xExamplesVS->Show(); + m_xExamplesVS->SetFormat(); + m_xExamplesVS->Invalidate(); + } +} + +SvxBitmapPickTabPage::~SvxBitmapPickTabPage() +{ + m_xExamplesVSWin.reset(); + m_xExamplesVS.reset(); +} + +std::unique_ptr SvxBitmapPickTabPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet) +{ + return std::make_unique(pPage, pController, *rAttrSet); +} + +void SvxBitmapPickTabPage::ActivatePage(const SfxItemSet& rSet) +{ + const SfxPoolItem* pItem; + bPreset = false; + bool bIsPreset = false; + const SfxItemSet* pExampleSet = GetDialogExampleSet(); + if(pExampleSet) + { + if(SfxItemState::SET == pExampleSet->GetItemState(SID_PARAM_NUM_PRESET, false, &pItem)) + bIsPreset = static_cast(pItem)->GetValue(); + if(SfxItemState::SET == pExampleSet->GetItemState(SID_PARAM_CUR_NUM_LEVEL, false, &pItem)) + nActNumLvl = static_cast(pItem)->GetValue(); + } + if(SfxItemState::SET == rSet.GetItemState(nNumItemId, false, &pItem)) + { + pSaveNum.reset( new SvxNumRule(*static_cast(pItem)->GetNumRule()) ); + } + if(pActNum && *pSaveNum != *pActNum) + { + *pActNum = *pSaveNum; + m_xExamplesVS->SetNoSelection(); + } + + if(!aGrfNames.empty() && + (pActNum && (!lcl_IsNumFmtSet(pActNum.get(), nActNumLvl) || bIsPreset))) + { + m_xExamplesVS->SelectItem(1); + NumSelectHdl_Impl(m_xExamplesVS.get()); + bPreset = true; + } + bPreset |= bIsPreset; + bModified = false; +} + +DeactivateRC SvxBitmapPickTabPage::DeactivatePage(SfxItemSet *_pSet) +{ + if(_pSet) + FillItemSet(_pSet); + return DeactivateRC::LeavePage; +} + +bool SvxBitmapPickTabPage::FillItemSet( SfxItemSet* rSet ) +{ + if ( aGrfNames.empty() ) + { + return false; + } + if( (bPreset || bModified) && pActNum) + { + *pSaveNum = *pActNum; + rSet->Put(SvxNumBulletItem( *pSaveNum, nNumItemId ) ); + rSet->Put(SfxBoolItem(SID_PARAM_NUM_PRESET, bPreset)); + } + + return bModified; +} + +void SvxBitmapPickTabPage::Reset( const SfxItemSet* rSet ) +{ + const SfxPoolItem* pItem; + // in Draw the item exists as WhichId, in Writer only as SlotId + SfxItemState eState = rSet->GetItemState(SID_ATTR_NUMBERING_RULE, false, &pItem); + if(eState != SfxItemState::SET) + { + nNumItemId = rSet->GetPool()->GetWhich(SID_ATTR_NUMBERING_RULE); + eState = rSet->GetItemState(nNumItemId, false, &pItem); + + if( eState != SfxItemState::SET ) + { + pItem = &static_cast< const SvxNumBulletItem& >( rSet->Get( nNumItemId ) ); + eState = SfxItemState::SET; + } + + } + DBG_ASSERT(eState == SfxItemState::SET, "no item found!"); + pSaveNum.reset( new SvxNumRule(*static_cast(pItem)->GetNumRule()) ); + + if(!pActNum) + pActNum.reset( new SvxNumRule(*pSaveNum) ); + else if(*pSaveNum != *pActNum) + *pActNum = *pSaveNum; +} + +IMPL_LINK_NOARG(SvxBitmapPickTabPage, NumSelectHdl_Impl, ValueSet*, void) +{ + if(!pActNum) + return; + + bPreset = false; + bModified = true; + sal_uInt16 nIdx = m_xExamplesVS->GetSelectedItemId() - 1; + + sal_uInt16 nMask = 1; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + { + SvxNumberFormat aFmt(pActNum->GetLevel(i)); + aFmt.SetNumberingType(SVX_NUM_BITMAP); + aFmt.SetPrefix( "" ); + aFmt.SetSuffix( "" ); + aFmt.SetCharFormatName( "" ); + + Graphic aGraphic; + if(GalleryExplorer::GetGraphicObj( GALLERY_THEME_BULLETS, nIdx, &aGraphic)) + { + Size aSize = SvxNumberFormat::GetGraphicSizeMM100(&aGraphic); + sal_Int16 eOrient = text::VertOrientation::LINE_CENTER; + aSize = OutputDevice::LogicToLogic(aSize, MapMode(MapUnit::Map100thMM), MapMode(eCoreUnit)); + SvxBrushItem aBrush(aGraphic, GPOS_AREA, SID_ATTR_BRUSH ); + aFmt.SetGraphicBrush( &aBrush, &aSize, &eOrient ); + } + else if(aGrfNames.size() > nIdx) + aFmt.SetGraphic( aGrfNames[nIdx] ); + pActNum->SetLevel(i, aFmt); + } + nMask <<= 1; + } +} + +IMPL_LINK_NOARG(SvxBitmapPickTabPage, DoubleClickHdl_Impl, ValueSet*, void) +{ + NumSelectHdl_Impl(m_xExamplesVS.get()); + weld::Button& rOk = GetDialogController()->GetOKButton(); + rOk.clicked(); +} + +IMPL_LINK_NOARG(SvxBitmapPickTabPage, ClickAddBrowseHdl_Impl, weld::Button&, void) +{ + sfx2::FileDialogHelper aFileDialog(0, FileDialogFlags::NONE, GetFrameWeld()); + aFileDialog.SetTitle(CuiResId(RID_SVXSTR_ADD_IMAGE)); + if ( aFileDialog.Execute() != ERRCODE_NONE ) + return; + + OUString aPath = SvtPathOptions().GetGalleryPath(); + OUString aPathToken = aPath.getToken( 1 , SEARCHPATH_DELIMITER ); + + OUString aUserImageURL = aFileDialog.GetPath(); + + OUString aFileName; + const sal_Int32 nPos {aUserImageURL.lastIndexOf(SEARCHFILENAME_DELIMITER)+1}; + if (nPos<=0) + aFileName = aUserImageURL; + else if (nPos xFactory = ::comphelper::getProcessServiceFactory(); + uno::Reference xSimpleFileAccess( + ucb::SimpleFileAccess::create( ::comphelper::getComponentContext(xFactory) ) ); + if ( !xSimpleFileAccess->exists( aUserImageURL )) + return; + + xSimpleFileAccess->copy( aUserImageURL, aUserGalleryURL ); + INetURLObject gURL( aUserGalleryURL ); + std::unique_ptr pIn(::utl::UcbStreamHelper::CreateStream( + gURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), StreamMode::READ )); + if ( !pIn ) + return; + + Graphic aGraphic; + GraphicConverter::Import( *pIn, aGraphic ); + + BitmapEx aBitmap = aGraphic.GetBitmapEx(); + long nPixelX = aBitmap.GetSizePixel().Width(); + long nPixelY = aBitmap.GetSizePixel().Height(); + double ratio = nPixelY/static_cast(nPixelX); + if(nPixelX > 30) + { + nPixelX = 30; + nPixelY = static_cast(nPixelX*ratio); + } + if(nPixelY > 30) + { + nPixelY = 30; + nPixelX = static_cast(nPixelY/ratio); + } + + aBitmap.Scale( Size( nPixelX, nPixelY ), BmpScaleFlag::Fast ); + Graphic aScaledGraphic( aBitmap ); + GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter(); + + Sequence< PropertyValue > aFilterData( 2 ); + aFilterData[ 0 ].Name = "Compression"; + aFilterData[ 0 ].Value <<= sal_Int32(-1) ; + aFilterData[ 1 ].Name = "Quality"; + aFilterData[ 1 ].Value <<= sal_Int32(1); + + sal_uInt16 nFilterFormat = rFilter.GetExportFormatNumberForShortName( gURL.GetFileExtension() ); + rFilter.ExportGraphic( aScaledGraphic, gURL , nFilterFormat, &aFilterData ); + GalleryExplorer::InsertURL( GALLERY_THEME_BULLETS, aUserGalleryURL ); + + aGrfNames.push_back(aUserGalleryURL); + size_t i = 0; + for (auto & grfName : aGrfNames) + { + m_xExamplesVS->InsertItem( i + 1, i); + INetURLObject aObj(grfName); + if(aObj.GetProtocol() == INetProtocol::File) + grfName = aObj.PathToFileName(); + m_xExamplesVS->SetItemText( i + 1, grfName ); + ++i; + } + + if(aGrfNames.empty()) + { + m_xErrorText->show(); + } + else + { + m_xExamplesVS->Show(); + m_xExamplesVS->SetFormat(); + } +} + +// tabpage numbering options +SvxNumOptionsTabPage::SvxNumOptionsTabPage(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/numberingoptionspage.ui", "NumberingOptionsPage", &rSet) + , m_pLevelHdlEvent(nullptr) + , bLastWidthModified(false) + , bModified(false) + , bPreset(false) + , bAutomaticCharStyles(true) + , bHTMLMode(false) + , nBullet(0xff) + , nActNumLvl(1) + , nNumItemId(SID_ATTR_NUMBERING_RULE) + , m_xGrid(m_xBuilder->weld_widget("grid2")) + , m_xLevelLB(m_xBuilder->weld_tree_view("levellb")) + , m_xFmtLB(m_xBuilder->weld_combo_box("numfmtlb")) + , m_xSeparatorFT(m_xBuilder->weld_label("separator")) + , m_xPrefixFT(m_xBuilder->weld_label("prefixft")) + , m_xPrefixED(m_xBuilder->weld_entry("prefix")) + , m_xSuffixFT(m_xBuilder->weld_label("suffixft")) + , m_xSuffixED(m_xBuilder->weld_entry("suffix")) + , m_xCharFmtFT(m_xBuilder->weld_label("charstyleft")) + , m_xCharFmtLB(m_xBuilder->weld_combo_box("charstyle")) + , m_xBulColorFT(m_xBuilder->weld_label("colorft")) + , m_xBulColLB(new ColorListBox(m_xBuilder->weld_menu_button("color"), pController->getDialog())) + , m_xBulRelSizeFT(m_xBuilder->weld_label("relsizeft")) + , m_xBulRelSizeMF(m_xBuilder->weld_metric_spin_button("relsize", FieldUnit::PERCENT)) + , m_xAllLevelFT(m_xBuilder->weld_label("sublevelsft")) + , m_xAllLevelNF(m_xBuilder->weld_spin_button("sublevels")) + , m_xStartFT(m_xBuilder->weld_label("startatft")) + , m_xStartED(m_xBuilder->weld_spin_button("startat")) + , m_xBulletFT(m_xBuilder->weld_label("bulletft")) + , m_xBulletPB(m_xBuilder->weld_button("bullet")) + , m_xBitmapFT(m_xBuilder->weld_label("bitmapft")) + , m_xBitmapMB(m_xBuilder->weld_menu_button("bitmap")) + , m_xWidthFT(m_xBuilder->weld_label("widthft")) + , m_xWidthMF(m_xBuilder->weld_metric_spin_button("widthmf", FieldUnit::CM)) + , m_xHeightFT(m_xBuilder->weld_label("heightft")) + , m_xHeightMF(m_xBuilder->weld_metric_spin_button("heightmf", FieldUnit::CM)) + , m_xRatioCB(m_xBuilder->weld_check_button("keepratio")) + , m_xOrientFT(m_xBuilder->weld_label("orientft")) + , m_xOrientLB(m_xBuilder->weld_combo_box("orientlb")) + , m_xAllLevelsFrame(m_xBuilder->weld_widget("levelsframe")) + , m_xSameLevelCB(m_xBuilder->weld_check_button("allsame")) + , m_xPreviewWIN(new weld::CustomWeld(*m_xBuilder, "preview", m_aPreviewWIN)) +{ + m_xBulColLB->SetSlotId(SID_ATTR_CHAR_COLOR); + m_xBulRelSizeMF->set_min(SVX_NUM_REL_SIZE_MIN, FieldUnit::PERCENT); + m_xBulRelSizeMF->set_increments(5, 50, FieldUnit::PERCENT); + SetExchangeSupport(); + aActBulletFont = lcl_GetDefaultBulletFont(); + + m_xBulletPB->connect_clicked(LINK(this, SvxNumOptionsTabPage, BulletHdl_Impl)); + m_xFmtLB->connect_changed(LINK(this, SvxNumOptionsTabPage, NumberTypeSelectHdl_Impl)); + m_xBitmapMB->connect_selected(LINK(this, SvxNumOptionsTabPage, GraphicHdl_Impl)); + m_xBitmapMB->connect_toggled(LINK(this, SvxNumOptionsTabPage, PopupActivateHdl_Impl)); + m_xLevelLB->set_selection_mode(SelectionMode::Multiple); + m_xLevelLB->connect_changed(LINK(this, SvxNumOptionsTabPage, LevelHdl_Impl)); + m_xCharFmtLB->connect_changed(LINK(this, SvxNumOptionsTabPage, CharFmtHdl_Impl)); + m_xWidthMF->connect_value_changed(LINK(this, SvxNumOptionsTabPage, SizeHdl_Impl)); + m_xHeightMF->connect_value_changed(LINK(this, SvxNumOptionsTabPage, SizeHdl_Impl)); + m_xRatioCB->connect_toggled(LINK(this, SvxNumOptionsTabPage, RatioHdl_Impl)); + m_xStartED->connect_value_changed(LINK(this, SvxNumOptionsTabPage, SpinModifyHdl_Impl)); + m_xPrefixED->connect_changed(LINK(this, SvxNumOptionsTabPage, EditModifyHdl_Impl)); + m_xSuffixED->connect_changed(LINK(this, SvxNumOptionsTabPage, EditModifyHdl_Impl)); + m_xAllLevelNF->connect_value_changed(LINK(this,SvxNumOptionsTabPage, AllLevelHdl_Impl)); + m_xOrientLB->connect_changed(LINK(this, SvxNumOptionsTabPage, OrientHdl_Impl)); + m_xSameLevelCB->connect_toggled(LINK(this, SvxNumOptionsTabPage, SameLevelHdl_Impl)); + m_xBulRelSizeMF->connect_value_changed(LINK(this,SvxNumOptionsTabPage, BulRelSizeHdl_Impl)); + m_xBulColLB->SetSelectHdl(LINK(this, SvxNumOptionsTabPage, BulColorHdl_Impl)); + aInvalidateTimer.SetInvokeHandler(LINK(this, SvxNumOptionsTabPage, PreviewInvalidateHdl_Impl)); + aInvalidateTimer.SetTimeout(50); + + eCoreUnit = rSet.GetPool()->GetMetric(rSet.GetPool()->GetWhich(SID_ATTR_NUMBERING_RULE)); + + // Fill ListBox with predefined / translated numbering types. + sal_uInt32 nCount = SvxNumberingTypeTable::Count(); + for (sal_uInt32 i = 0; i < nCount; ++i) + { + m_xFmtLB->append(OUString::number(SvxNumberingTypeTable::GetValue(i)), SvxNumberingTypeTable::GetString(i)); + } + + // Get advanced numbering types from the component. + // Watch out for the ugly + // 136 == 0x88 == SVX_NUM_BITMAP|0x80 == SVX_NUM_BITMAP|LINK_TOKEN + // to not remove that. + SvxNumOptionsTabPageHelper::GetI18nNumbering( *m_xFmtLB, (SVX_NUM_BITMAP | LINK_TOKEN)); + + m_xFmtLB->set_active(0); + + m_xCharFmtLB->set_size_request(m_xCharFmtLB->get_approximate_digit_width() * 10, -1); + Size aSize(m_xGrid->get_preferred_size()); + m_xGrid->set_size_request(aSize.Width(), -1); +} + +SvxNumOptionsTabPage::~SvxNumOptionsTabPage() +{ + m_xPreviewWIN.reset(); + m_xBulColLB.reset(); + pActNum.reset(); + pSaveNum.reset(); + if (m_pLevelHdlEvent) + { + Application::RemoveUserEvent(m_pLevelHdlEvent); + m_pLevelHdlEvent = nullptr; + } +} + +void SvxNumOptionsTabPage::SetMetric(FieldUnit eMetric) +{ + if(eMetric == FieldUnit::MM) + { + m_xWidthMF->set_digits(1); + m_xHeightMF->set_digits(1); + } + m_xWidthMF->set_unit(eMetric); + m_xHeightMF->set_unit(eMetric); +} + +std::unique_ptr SvxNumOptionsTabPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet) +{ + return std::make_unique(pPage, pController, *rAttrSet); +}; + +void SvxNumOptionsTabPage::ActivatePage(const SfxItemSet& rSet) +{ + const SfxPoolItem* pItem; + const SfxItemSet* pExampleSet = GetDialogExampleSet(); + sal_uInt16 nTmpNumLvl = 1; + if(pExampleSet) + { + if(SfxItemState::SET == pExampleSet->GetItemState(SID_PARAM_NUM_PRESET, false, &pItem)) + bPreset = static_cast(pItem)->GetValue(); + if(SfxItemState::SET == pExampleSet->GetItemState(SID_PARAM_CUR_NUM_LEVEL, false, &pItem)) + nTmpNumLvl = static_cast(pItem)->GetValue(); + } + if(SfxItemState::SET == rSet.GetItemState(nNumItemId, false, &pItem)) + { + pSaveNum.reset( new SvxNumRule(*static_cast(pItem)->GetNumRule()) ); + } + + bModified = (!pActNum->Get( 0 ) || bPreset); + if(*pActNum == *pSaveNum && nActNumLvl == nTmpNumLvl) + return; + + nActNumLvl = nTmpNumLvl; + sal_uInt16 nMask = 1; + m_xLevelLB->unselect_all(); + if (nActNumLvl == SAL_MAX_UINT16) + m_xLevelLB->select(pActNum->GetLevelCount()); + if(nActNumLvl != SAL_MAX_UINT16) + { + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + m_xLevelLB->select(i); + nMask <<= 1 ; + } + } + *pActNum = *pSaveNum; + + InitControls(); +} + +DeactivateRC SvxNumOptionsTabPage::DeactivatePage(SfxItemSet * _pSet) +{ + if(_pSet) + FillItemSet(_pSet); + return DeactivateRC::LeavePage; +} + +bool SvxNumOptionsTabPage::FillItemSet( SfxItemSet* rSet ) +{ + rSet->Put(SfxUInt16Item(SID_PARAM_CUR_NUM_LEVEL, nActNumLvl)); + if(bModified && pActNum) + { + *pSaveNum = *pActNum; + rSet->Put(SvxNumBulletItem( *pSaveNum, nNumItemId )); + rSet->Put(SfxBoolItem(SID_PARAM_NUM_PRESET, false)); + } + return bModified; +}; + +void SvxNumOptionsTabPage::Reset( const SfxItemSet* rSet ) +{ + const SfxPoolItem* pItem; + // in Draw the item exists as WhichId, in Writer only as SlotId + SfxItemState eState = rSet->GetItemState(SID_ATTR_NUMBERING_RULE, false, &pItem); + if(eState != SfxItemState::SET) + { + nNumItemId = rSet->GetPool()->GetWhich(SID_ATTR_NUMBERING_RULE); + eState = rSet->GetItemState(nNumItemId, false, &pItem); + + if( eState != SfxItemState::SET ) + { + pItem = &static_cast< const SvxNumBulletItem& >( rSet->Get( nNumItemId ) ); + eState = SfxItemState::SET; + } + + } + DBG_ASSERT(eState == SfxItemState::SET, "no item found!"); + pSaveNum.reset( new SvxNumRule(*static_cast(pItem)->GetNumRule()) ); + + // insert levels + if (!m_xLevelLB->n_children()) + { + for(sal_uInt16 i = 1; i <= pSaveNum->GetLevelCount(); i++) + m_xLevelLB->append_text(OUString::number(i)); + if(pSaveNum->GetLevelCount() > 1) + { + OUString sEntry = "1 - " + OUString::number( pSaveNum->GetLevelCount() ); + m_xLevelLB->append_text(sEntry); + m_xLevelLB->select_text(sEntry); + } + else + m_xLevelLB->select(0); + } + else + m_xLevelLB->select(m_xLevelLB->n_children() - 1); + + sal_uInt16 nMask = 1; + m_xLevelLB->unselect_all(); + if (nActNumLvl == SAL_MAX_UINT16) + { + m_xLevelLB->select( pSaveNum->GetLevelCount() ); + } + else + { + for(sal_uInt16 i = 0; i < pSaveNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + m_xLevelLB->select( i ); + nMask <<= 1 ; + } + } + + if(!pActNum) + pActNum.reset( new SvxNumRule(*pSaveNum) ); + else if(*pSaveNum != *pActNum) + *pActNum = *pSaveNum; + m_aPreviewWIN.SetNumRule(pActNum.get()); + m_xSameLevelCB->set_active(pActNum->IsContinuousNumbering()); + + SfxObjectShell* pShell; + if ( SfxItemState::SET == rSet->GetItemState( SID_HTML_MODE, false, &pItem ) + || ( nullptr != ( pShell = SfxObjectShell::Current()) && + nullptr != ( pItem = pShell->GetItem( SID_HTML_MODE ) ) ) ) + { + sal_uInt16 nHtmlMode = static_cast(pItem)->GetValue(); + bHTMLMode = 0 != (nHtmlMode&HTMLMODE_ON); + } + + bool bCharFmt = pActNum->IsFeatureSupported(SvxNumRuleFlags::CHAR_STYLE); + m_xCharFmtFT->set_visible(bCharFmt); + m_xCharFmtLB->set_visible(bCharFmt); + + bool bContinuous = pActNum->IsFeatureSupported(SvxNumRuleFlags::CONTINUOUS); + + bool bAllLevel = bContinuous && !bHTMLMode; + m_xAllLevelFT->set_visible(bAllLevel); + m_xAllLevelNF->set_visible(bAllLevel); + + m_xAllLevelsFrame->set_visible(bContinuous); + + // again misusage: in Draw there is numeration only until the bitmap + // without SVX_NUM_NUMBER_NONE + //remove types that are unsupported by Draw/Impress + if(!bContinuous) + { + sal_Int32 nFmtCount = m_xFmtLB->get_count(); + for(sal_Int32 i = nFmtCount; i; i--) + { + sal_uInt16 nEntryData = m_xFmtLB->get_id(i - 1).toUInt32(); + if(/*SVX_NUM_NUMBER_NONE == nEntryData ||*/ + (SVX_NUM_BITMAP|LINK_TOKEN) == nEntryData) + m_xFmtLB->remove(i - 1); + } + } + //one must be enabled + if(!pActNum->IsFeatureSupported(SvxNumRuleFlags::ENABLE_LINKED_BMP)) + { + auto nPos = m_xFmtLB->find_id(OUString::number(SVX_NUM_BITMAP|LINK_TOKEN)); + if (nPos != -1) + m_xFmtLB->remove(nPos); + } + else if(!pActNum->IsFeatureSupported(SvxNumRuleFlags::ENABLE_EMBEDDED_BMP)) + { + auto nPos = m_xFmtLB->find_id(OUString::number(SVX_NUM_BITMAP)); + if (nPos != -1) + m_xFmtLB->remove(nPos); + } + + // MegaHack: because of a not-fixable 'design mistake/error' in Impress + // delete all kinds of numeric enumerations + if(pActNum->IsFeatureSupported(SvxNumRuleFlags::NO_NUMBERS)) + { + sal_Int32 nFmtCount = m_xFmtLB->get_count(); + for(sal_Int32 i = nFmtCount; i; i--) + { + sal_uInt16 nEntryData = m_xFmtLB->get_id(i - 1).toUInt32(); + if( /*nEntryData >= SVX_NUM_CHARS_UPPER_LETTER &&*/ nEntryData <= SVX_NUM_NUMBER_NONE) + m_xFmtLB->remove(i - 1); + } + } + + InitControls(); + bModified = false; +} + +void SvxNumOptionsTabPage::InitControls() +{ + bool bShowBullet = true; + bool bShowBitmap = true; + bool bSameType = true; + bool bSameStart = true; + bool bSamePrefix = true; + bool bSameSuffix = true; + bool bAllLevel = true; + bool bSameCharFmt = true; + bool bSameVOrient = true; + bool bSameSize = true; + bool bSameBulColor = true; + bool bSameBulRelSize= true; + + const SvxNumberFormat* aNumFmtArr[SVX_MAX_NUM]; + OUString sFirstCharFmt; + sal_Int16 eFirstOrient = text::VertOrientation::NONE; + Size aFirstSize(0,0); + sal_uInt16 nMask = 1; + sal_uInt16 nLvl = SAL_MAX_UINT16; + sal_uInt16 nHighestLevel = 0; + + bool bBullColor = pActNum->IsFeatureSupported(SvxNumRuleFlags::BULLET_COLOR); + bool bBullRelSize = pActNum->IsFeatureSupported(SvxNumRuleFlags::BULLET_REL_SIZE); + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + { + aNumFmtArr[i] = &pActNum->GetLevel(i); + bShowBullet &= aNumFmtArr[i]->GetNumberingType() == SVX_NUM_CHAR_SPECIAL; + bShowBitmap &= (aNumFmtArr[i]->GetNumberingType()&(~LINK_TOKEN)) == SVX_NUM_BITMAP; + if(SAL_MAX_UINT16 == nLvl) + { + nLvl = i; + sFirstCharFmt = aNumFmtArr[i]->GetCharFormatName(); + eFirstOrient = aNumFmtArr[i]->GetVertOrient(); + if(bShowBitmap) + aFirstSize = aNumFmtArr[i]->GetGraphicSize(); + } + if( i > nLvl) + { + bSameType &= aNumFmtArr[i]->GetNumberingType() == aNumFmtArr[nLvl]->GetNumberingType(); + bSameStart = aNumFmtArr[i]->GetStart() == aNumFmtArr[nLvl]->GetStart(); + + bSamePrefix = aNumFmtArr[i]->GetPrefix() == aNumFmtArr[nLvl]->GetPrefix(); + bSameSuffix = aNumFmtArr[i]->GetSuffix() == aNumFmtArr[nLvl]->GetSuffix(); + bAllLevel &= aNumFmtArr[i]->GetIncludeUpperLevels() == aNumFmtArr[nLvl]->GetIncludeUpperLevels(); + bSameCharFmt &= sFirstCharFmt == aNumFmtArr[i]->GetCharFormatName(); + bSameVOrient &= eFirstOrient == aNumFmtArr[i]->GetVertOrient(); + if(bShowBitmap && bSameSize) + bSameSize &= aNumFmtArr[i]->GetGraphicSize() == aFirstSize; + bSameBulColor &= aNumFmtArr[i]->GetBulletColor() == aNumFmtArr[nLvl]->GetBulletColor(); + bSameBulRelSize &= aNumFmtArr[i]->GetBulletRelSize() == aNumFmtArr[nLvl]->GetBulletRelSize(); + } + nHighestLevel = i; + } + else + aNumFmtArr[i] = nullptr; + + nMask <<= 1 ; + } + SwitchNumberType(bShowBullet ? 1 : bShowBitmap ? 2 : 0); + + sal_uInt16 nNumberingType; + if (nLvl != SAL_MAX_UINT16) + nNumberingType = aNumFmtArr[nLvl]->GetNumberingType(); + else + { + nNumberingType = SVX_NUM_NUMBER_NONE; + bAllLevel = false; + bSameBulRelSize = false; + bSameBulColor = false; + bSameStart = false; + bSamePrefix = false; + bSameSuffix = false; + } + + CheckForStartValue_Impl(nNumberingType); + + if(bShowBitmap) + { + if(!bSameVOrient || eFirstOrient == text::VertOrientation::NONE) + m_xOrientLB->set_active(-1); + else + m_xOrientLB->set_active( + sal::static_int_cast< sal_Int32 >(eFirstOrient - 1)); + // no text::VertOrientation::NONE + + if(bSameSize) + { + SetMetricValue(*m_xHeightMF, aFirstSize.Height(), eCoreUnit); + SetMetricValue(*m_xWidthMF, aFirstSize.Width(), eCoreUnit); + } + else + { + m_xHeightMF->set_text(""); + m_xWidthMF->set_text(""); + } + } + + if(bSameType) + { + sal_uInt16 nLBData = nNumberingType; + m_xFmtLB->set_active_id(OUString::number(nLBData)); + } + else + m_xFmtLB->set_active(-1); + + m_xAllLevelNF->set_sensitive(nHighestLevel > 0 && !m_xSameLevelCB->get_active()); + m_xAllLevelNF->set_max(nHighestLevel + 1); + if(bAllLevel) + { + m_xAllLevelNF->set_value(aNumFmtArr[nLvl]->GetIncludeUpperLevels()); + } + else + { + m_xAllLevelNF->set_text(""); + } + + if(bBullRelSize) + { + if(bSameBulRelSize) + m_xBulRelSizeMF->set_value(aNumFmtArr[nLvl]->GetBulletRelSize(), FieldUnit::PERCENT); + else + m_xBulRelSizeMF->set_text(""); + } + if(bBullColor) + { + if(bSameBulColor) + m_xBulColLB->SelectEntry(aNumFmtArr[nLvl]->GetBulletColor()); + else + m_xBulColLB->SetNoSelection(); + } + switch(nBullet) + { + case SHOW_NUMBERING: + if(bSameStart) + { + m_xStartED->set_value(aNumFmtArr[nLvl]->GetStart()); + } + else + m_xStartED->set_text(""); + break; + case SHOW_BULLET: + break; + case SHOW_BITMAP: + break; + } + + if(bSamePrefix) + m_xPrefixED->set_text(aNumFmtArr[nLvl]->GetPrefix()); + else + m_xPrefixED->set_text(""); + if(bSameSuffix) + m_xSuffixED->set_text(aNumFmtArr[nLvl]->GetSuffix()); + else + m_xSuffixED->set_text(""); + + if(bSameCharFmt) + { + if (!sFirstCharFmt.isEmpty()) + m_xCharFmtLB->set_active_text(sFirstCharFmt); + else + m_xCharFmtLB->set_active(0); + } + else + m_xCharFmtLB->set_active(-1); + + m_aPreviewWIN.SetLevel(nActNumLvl); + m_aPreviewWIN.Invalidate(); +} + +// 0 - Number; 1 - Bullet; 2 - Bitmap +void SvxNumOptionsTabPage::SwitchNumberType( sal_uInt8 nType ) +{ + if(nBullet == nType) + return; + nBullet = nType; + bool bBullet = (nType == SHOW_BULLET); + bool bBitmap = (nType == SHOW_BITMAP); + bool bEnableBitmap = (nType == SHOW_BITMAP); + bool bNumeric = !(bBitmap||bBullet); + m_xSeparatorFT->set_visible(bNumeric); + m_xPrefixFT->set_visible(bNumeric); + m_xPrefixED->set_visible(bNumeric); + m_xSuffixFT->set_visible(bNumeric); + m_xSuffixED->set_visible(bNumeric); + + bool bCharFmt = pActNum->IsFeatureSupported(SvxNumRuleFlags::CHAR_STYLE); + m_xCharFmtFT->set_visible(!bBitmap && bCharFmt); + m_xCharFmtLB->set_visible(!bBitmap && bCharFmt); + + // this is rather misusage, as there is no own flag + // for complete numeration + bool bAllLevelFeature = pActNum->IsFeatureSupported(SvxNumRuleFlags::CONTINUOUS); + bool bAllLevel = bNumeric && bAllLevelFeature && !bHTMLMode; + m_xAllLevelFT->set_visible(bAllLevel); + m_xAllLevelNF->set_visible(bAllLevel); + + m_xStartFT->set_visible(!(bBullet||bBitmap)); + m_xStartED->set_visible(!(bBullet||bBitmap)); + + m_xBulletFT->set_visible(bBullet); + m_xBulletPB->set_visible(bBullet); + bool bBullColor = pActNum->IsFeatureSupported(SvxNumRuleFlags::BULLET_COLOR); + m_xBulColorFT->set_visible(!bBitmap && bBullColor); + m_xBulColLB->set_visible(!bBitmap && bBullColor); + bool bBullResSize = pActNum->IsFeatureSupported(SvxNumRuleFlags::BULLET_REL_SIZE); + m_xBulRelSizeFT->set_visible(!bBitmap && bBullResSize); + m_xBulRelSizeMF->set_visible(!bBitmap && bBullResSize); + + m_xBitmapFT->set_visible(bBitmap); + m_xBitmapMB->set_visible(bBitmap); + + m_xWidthFT->set_visible(bBitmap); + m_xWidthMF->set_visible(bBitmap); + m_xHeightFT->set_visible(bBitmap); + m_xHeightMF->set_visible(bBitmap); + m_xRatioCB->set_visible(bBitmap); + + m_xOrientFT->set_visible(bBitmap && bAllLevelFeature); + m_xOrientLB->set_visible(bBitmap && bAllLevelFeature); + + m_xWidthFT->set_sensitive(bEnableBitmap); + m_xWidthMF->set_sensitive(bEnableBitmap); + m_xHeightFT->set_sensitive(bEnableBitmap); + m_xHeightMF->set_sensitive(bEnableBitmap); + m_xRatioCB->set_sensitive(bEnableBitmap); + m_xOrientFT->set_sensitive(bEnableBitmap); + m_xOrientLB->set_sensitive(bEnableBitmap); +} + +IMPL_LINK_NOARG(SvxNumOptionsTabPage, LevelHdl_Impl, weld::TreeView&, void) +{ + if (m_pLevelHdlEvent) + return; + // tdf#127112 (borrowing tdf#127120 solution) multiselection may be implemented by deselect follow by select so + // fire off the handler to happen on next event loop and only process the + // final state + m_pLevelHdlEvent = Application::PostUserEvent(LINK(this, SvxNumOptionsTabPage, LevelHdl)); +} + +IMPL_LINK_NOARG(SvxNumOptionsTabPage, LevelHdl, void*, void) +{ + m_pLevelHdlEvent = nullptr; + + sal_uInt16 nSaveNumLvl = nActNumLvl; + nActNumLvl = 0; + std::vector aSelectedRows = m_xLevelLB->get_selected_rows(); + if (std::find(aSelectedRows.begin(), aSelectedRows.end(), pActNum->GetLevelCount()) != aSelectedRows.end() && + (aSelectedRows.size() == 1 || nSaveNumLvl != 0xffff)) + { + nActNumLvl = 0xFFFF; + for( sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++ ) + m_xLevelLB->unselect(i); + } + else if (!aSelectedRows.empty()) + { + sal_uInt16 nMask = 1; + for( sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++ ) + { + if (std::find(aSelectedRows.begin(), aSelectedRows.end(), i) != aSelectedRows.end()) + nActNumLvl |= nMask; + nMask <<= 1; + } + m_xLevelLB->unselect(pActNum->GetLevelCount()); + } + else + { + nActNumLvl = nSaveNumLvl; + sal_uInt16 nMask = 1; + for( sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++ ) + { + if(nActNumLvl & nMask) + { + m_xLevelLB->select(i); + break; + } + nMask <<=1; + } + } + InitControls(); +} + +IMPL_LINK_NOARG(SvxNumOptionsTabPage, PreviewInvalidateHdl_Impl, Timer *, void) +{ + m_aPreviewWIN.Invalidate(); +} + +IMPL_LINK(SvxNumOptionsTabPage, AllLevelHdl_Impl, weld::SpinButton&, rBox, void) +{ + sal_uInt16 nMask = 1; + for(sal_uInt16 e = 0; e < pActNum->GetLevelCount(); e++) + { + if(nActNumLvl & nMask) + { + SvxNumberFormat aNumFmt(pActNum->GetLevel(e)); + aNumFmt.SetIncludeUpperLevels(static_cast(std::min(rBox.get_value(), int(e + 1))) ); + pActNum->SetLevel(e, aNumFmt); + } + nMask <<= 1; + } + SetModified(); +} + +IMPL_LINK(SvxNumOptionsTabPage, NumberTypeSelectHdl_Impl, weld::ComboBox&, rBox, void) +{ + OUString sSelectStyle; + bool bShowOrient = false; + bool bBmp = false; + sal_uInt16 nMask = 1; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + { + SvxNumberFormat aNumFmt(pActNum->GetLevel(i)); + // PAGEDESC does not exist + SvxNumType nNumType = static_cast(rBox.get_active_id().toUInt32()); + aNumFmt.SetNumberingType(nNumType); + sal_uInt16 nNumberingType = aNumFmt.GetNumberingType(); + if(SVX_NUM_BITMAP == (nNumberingType&(~LINK_TOKEN))) + { + bBmp |= nullptr != aNumFmt.GetBrush(); + aNumFmt.SetIncludeUpperLevels( 0 ); + aNumFmt.SetSuffix( "" ); + aNumFmt.SetPrefix( "" ); + if(!bBmp) + aNumFmt.SetGraphic(""); + pActNum->SetLevel(i, aNumFmt); + SwitchNumberType(SHOW_BITMAP); + bShowOrient = true; + } + else if( SVX_NUM_CHAR_SPECIAL == nNumberingType ) + { + aNumFmt.SetIncludeUpperLevels( 0 ); + aNumFmt.SetSuffix( "" ); + aNumFmt.SetPrefix( "" ); + if( !aNumFmt.GetBulletFont() ) + aNumFmt.SetBulletFont(&aActBulletFont); + if( !aNumFmt.GetBulletChar() ) + aNumFmt.SetBulletChar( SVX_DEF_BULLET ); + pActNum->SetLevel(i, aNumFmt); + SwitchNumberType(SHOW_BULLET); + // allocation of the drawing pattern is automatic + if(bAutomaticCharStyles) + { + sSelectStyle = m_sBulletCharFormatName; + } + } + else + { + aNumFmt.SetPrefix( m_xPrefixED->get_text() ); + aNumFmt.SetSuffix( m_xSuffixED->get_text() ); + SwitchNumberType(SHOW_NUMBERING); + pActNum->SetLevel(i, aNumFmt); + CheckForStartValue_Impl(nNumberingType); + + // allocation of the drawing pattern is automatic + if(bAutomaticCharStyles) + { + sSelectStyle = m_sNumCharFmtName; + } + } + } + nMask <<= 1; + } + bool bAllLevelFeature = pActNum->IsFeatureSupported(SvxNumRuleFlags::CONTINUOUS); + if(bShowOrient && bAllLevelFeature) + { + m_xOrientFT->show(); + m_xOrientLB->show(); + } + else + { + m_xOrientFT->hide(); + m_xOrientLB->hide(); + } + SetModified(); + if(!sSelectStyle.isEmpty()) + { + m_xCharFmtLB->set_active_text(sSelectStyle); + CharFmtHdl_Impl(*m_xCharFmtLB); + bAutomaticCharStyles = true; + } +} + +void SvxNumOptionsTabPage::CheckForStartValue_Impl(sal_uInt16 nNumberingType) +{ + bool bIsNull = m_xStartED->get_value() == 0; + bool bNoZeroAllowed = nNumberingType < SVX_NUM_ARABIC || + SVX_NUM_CHARS_UPPER_LETTER_N == nNumberingType || + SVX_NUM_CHARS_LOWER_LETTER_N == nNumberingType; + m_xStartED->set_min(bNoZeroAllowed ? 1 : 0); + if (bIsNull && bNoZeroAllowed) + EditModifyHdl_Impl(*m_xStartED); +} + +IMPL_LINK(SvxNumOptionsTabPage, OrientHdl_Impl, weld::ComboBox&, rBox, void) +{ + sal_Int32 nPos = rBox.get_active(); + nPos ++; // no VERT_NONE + + sal_uInt16 nMask = 1; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + { + SvxNumberFormat aNumFmt(pActNum->GetLevel(i)); + if(SVX_NUM_BITMAP == (aNumFmt.GetNumberingType()&(~LINK_TOKEN))) + { + const SvxBrushItem* pBrushItem = aNumFmt.GetBrush(); + const Size& rSize = aNumFmt.GetGraphicSize(); + sal_Int16 eOrient = static_cast(nPos); + aNumFmt.SetGraphicBrush( pBrushItem, &rSize, &eOrient ); + pActNum->SetLevel(i, aNumFmt); + } + } + nMask <<= 1; + } + SetModified(false); +} + +IMPL_LINK(SvxNumOptionsTabPage, SameLevelHdl_Impl, weld::ToggleButton&, rBox, void) +{ + bool bSet = rBox.get_active(); + pActNum->SetContinuousNumbering(bSet); + bool bRepaint = false; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + SvxNumberFormat aNumFmt(pActNum->GetLevel(i)); + if(aNumFmt.GetNumberingType() != SVX_NUM_NUMBER_NONE) + { + bRepaint = true; + break; + } + } + SetModified(bRepaint); + InitControls(); +} + +IMPL_LINK(SvxNumOptionsTabPage, BulColorHdl_Impl, ColorListBox&, rColorBox, void) +{ + Color nSetColor = rColorBox.GetSelectEntryColor(); + + sal_uInt16 nMask = 1; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + { + SvxNumberFormat aNumFmt(pActNum->GetLevel(i)); + aNumFmt.SetBulletColor(nSetColor); + pActNum->SetLevel(i, aNumFmt); + } + nMask <<= 1; + } + SetModified(); +} + +IMPL_LINK(SvxNumOptionsTabPage, BulRelSizeHdl_Impl, weld::MetricSpinButton&, rField, void) +{ + sal_uInt16 nRelSize = rField.get_value(FieldUnit::PERCENT); + + sal_uInt16 nMask = 1; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + { + SvxNumberFormat aNumFmt(pActNum->GetLevel(i)); + aNumFmt.SetBulletRelSize(nRelSize); + pActNum->SetLevel(i, aNumFmt); + } + nMask <<= 1; + } + SetModified(); +} + +IMPL_LINK(SvxNumOptionsTabPage, GraphicHdl_Impl, const OString&, rIdent, void) +{ + OUString aGrfName; + Size aSize; + bool bSucc(false); + SvxOpenGraphicDialog aGrfDlg(CuiResId(RID_SVXSTR_EDIT_GRAPHIC), GetFrameWeld()); + + OString sNumber; + if (rIdent.startsWith("gallery", &sNumber)) + { + auto idx = sNumber.toUInt32(); + if (idx < aGrfNames.size()) + { + aGrfName = aGrfNames[idx]; + Graphic aGraphic; + if(GalleryExplorer::GetGraphicObj( GALLERY_THEME_BULLETS, idx, &aGraphic)) + { + aSize = SvxNumberFormat::GetGraphicSizeMM100(&aGraphic); + bSucc = true; + } + } + } + else if (rIdent == "fromfile") + { + aGrfDlg.EnableLink( false ); + aGrfDlg.AsLink( false ); + if ( !aGrfDlg.Execute() ) + { + // memorize selected filter + aGrfName = aGrfDlg.GetPath(); + + Graphic aGraphic; + if( !aGrfDlg.GetGraphic(aGraphic) ) + { + aSize = SvxNumberFormat::GetGraphicSizeMM100(&aGraphic); + bSucc = true; + } + } + } + if(!bSucc) + return; + + aSize = OutputDevice::LogicToLogic(aSize, MapMode(MapUnit::Map100thMM), MapMode(eCoreUnit)); + + sal_uInt16 nMask = 1; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + { + SvxNumberFormat aNumFmt(pActNum->GetLevel(i)); + aNumFmt.SetCharFormatName(m_sNumCharFmtName); + aNumFmt.SetGraphic(aGrfName); + + // set size for a later comparison + const SvxBrushItem* pBrushItem = aNumFmt.GetBrush(); + // initiate asynchronous loading + sal_Int16 eOrient = aNumFmt.GetVertOrient(); + aNumFmt.SetGraphicBrush( pBrushItem, &aSize, &eOrient ); + aInitSize[i] = aNumFmt.GetGraphicSize(); + + pActNum->SetLevel(i, aNumFmt); + } + nMask <<= 1; + } + m_xRatioCB->set_sensitive(true); + m_xWidthFT->set_sensitive(true); + m_xHeightFT->set_sensitive(true); + m_xWidthMF->set_sensitive(true); + m_xHeightMF->set_sensitive(true); + SetMetricValue(*m_xWidthMF, aSize.Width(), eCoreUnit); + SetMetricValue(*m_xHeightMF, aSize.Height(), eCoreUnit); + m_xOrientFT->set_sensitive(true); + m_xOrientLB->set_sensitive(true); + SetModified(); + //needed due to asynchronous loading of graphics in the SvxBrushItem + aInvalidateTimer.Start(); +} + +IMPL_LINK_NOARG(SvxNumOptionsTabPage, PopupActivateHdl_Impl, weld::ToggleButton&, void) +{ + if (m_xGalleryMenu) + return; + + m_xGalleryMenu = m_xBuilder->weld_menu("gallerysubmenu"); + weld::WaitObject aWait(GetFrameWeld()); + + if (!GalleryExplorer::FillObjList(GALLERY_THEME_BULLETS, aGrfNames)) + return; + + GalleryExplorer::BeginLocking(GALLERY_THEME_BULLETS); + + Graphic aGraphic; + OUString sGrfName; + ScopedVclPtrInstance< VirtualDevice > pVD; + size_t i = 0; + for (const auto & grfName : aGrfNames) + { + sGrfName = grfName; + OUString sItemId = "gallery" + OUString::number(i); + INetURLObject aObj(sGrfName); + if(aObj.GetProtocol() == INetProtocol::File) + sGrfName = aObj.PathToFileName(); + if(GalleryExplorer::GetGraphicObj( GALLERY_THEME_BULLETS, i, &aGraphic)) + { + BitmapEx aBitmap(aGraphic.GetBitmapEx()); + Size aSize(aBitmap.GetSizePixel()); + if(aSize.Width() > MAX_BMP_WIDTH || + aSize.Height() > MAX_BMP_HEIGHT) + { + bool bWidth = aSize.Width() > aSize.Height(); + double nScale = bWidth ? + double(MAX_BMP_WIDTH) / static_cast(aSize.Width()): + double(MAX_BMP_HEIGHT) / static_cast(aSize.Height()); + aBitmap.Scale(nScale, nScale); + } + pVD->SetOutputSizePixel(aBitmap.GetSizePixel(), false); + pVD->DrawBitmapEx(Point(), aBitmap); + m_xGalleryMenu->append(sItemId, sGrfName, *pVD); + } + else + { + m_xGalleryMenu->append(sItemId, sGrfName); + } + ++i; + } + GalleryExplorer::EndLocking(GALLERY_THEME_BULLETS); +} + +IMPL_LINK_NOARG(SvxNumOptionsTabPage, BulletHdl_Impl, weld::Button&, void) +{ + SvxCharacterMap aMap(GetFrameWeld(), nullptr, nullptr); + + sal_uInt16 nMask = 1; + const vcl::Font* pFmtFont = nullptr; + bool bSameBullet = true; + sal_Unicode cBullet = 0; + bool bFirst = true; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + { + const SvxNumberFormat& rCurFmt = pActNum->GetLevel(i); + if(bFirst) + { + cBullet = rCurFmt.GetBulletChar(); + } + else if(rCurFmt.GetBulletChar() != cBullet ) + { + bSameBullet = false; + break; + } + if(!pFmtFont) + pFmtFont = rCurFmt.GetBulletFont(); + bFirst = false; + } + nMask <<= 1; + + } + + if (pFmtFont) + aMap.SetCharFont(*pFmtFont); + else + aMap.SetCharFont(aActBulletFont); + if (bSameBullet) + aMap.SetChar(cBullet); + if (aMap.run() != RET_OK) + return; + + // change Font Numrules + aActBulletFont = aMap.GetCharFont(); + + sal_uInt16 _nMask = 1; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & _nMask) + { + SvxNumberFormat aNumFmt(pActNum->GetLevel(i)); + aNumFmt.SetBulletFont(&aActBulletFont); + aNumFmt.SetBulletChar( static_cast(aMap.GetChar()) ); + pActNum->SetLevel(i, aNumFmt); + } + _nMask <<= 1; + } + + SetModified(); +} + +IMPL_LINK( SvxNumOptionsTabPage, SizeHdl_Impl, weld::MetricSpinButton&, rField, void) +{ + bool bWidth = &rField == m_xWidthMF.get(); + bLastWidthModified = bWidth; + bool bRatio = m_xRatioCB->get_active(); + long nWidthVal = static_cast(m_xWidthMF->denormalize(m_xWidthMF->get_value(FieldUnit::MM_100TH))); + long nHeightVal = static_cast(m_xHeightMF->denormalize(m_xHeightMF->get_value(FieldUnit::MM_100TH))); + nWidthVal = OutputDevice::LogicToLogic( nWidthVal , + MapUnit::Map100thMM, eCoreUnit ); + nHeightVal = OutputDevice::LogicToLogic( nHeightVal, + MapUnit::Map100thMM, eCoreUnit); + double fSizeRatio; + + bool bRepaint = false; + sal_uInt16 nMask = 1; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + { + SvxNumberFormat aNumFmt(pActNum->GetLevel(i)); + if(SVX_NUM_BITMAP == (aNumFmt.GetNumberingType()&(~LINK_TOKEN))) + { + Size aSize(aNumFmt.GetGraphicSize() ); + Size aSaveSize(aSize); + + if (aInitSize[i].Height()) + fSizeRatio = static_cast(aInitSize[i].Width()) / static_cast(aInitSize[i].Height()); + else + fSizeRatio = double(1); + + if(bWidth) + { + long nDelta = nWidthVal - aInitSize[i].Width(); + aSize.setWidth( nWidthVal ); + if (bRatio) + { + aSize.setHeight( aInitSize[i].Height() + static_cast(static_cast(nDelta) / fSizeRatio) ); + m_xHeightMF->set_value(m_xHeightMF->normalize( + OutputDevice::LogicToLogic( aSize.Height(), eCoreUnit, MapUnit::Map100thMM )), + FieldUnit::MM_100TH); + } + } + else + { + long nDelta = nHeightVal - aInitSize[i].Height(); + aSize.setHeight( nHeightVal ); + if (bRatio) + { + aSize.setWidth( aInitSize[i].Width() + static_cast(static_cast(nDelta) * fSizeRatio) ); + m_xWidthMF->set_value(m_xWidthMF->normalize( + OutputDevice::LogicToLogic( aSize.Width(), eCoreUnit, MapUnit::Map100thMM )), + FieldUnit::MM_100TH); + } + } + const SvxBrushItem* pBrushItem = aNumFmt.GetBrush(); + sal_Int16 eOrient = aNumFmt.GetVertOrient(); + if(aSize != aSaveSize) + bRepaint = true; + aNumFmt.SetGraphicBrush( pBrushItem, &aSize, &eOrient ); + pActNum->SetLevel(i, aNumFmt); + } + } + nMask <<= 1; + } + SetModified(bRepaint); +} + +IMPL_LINK(SvxNumOptionsTabPage, RatioHdl_Impl, weld::ToggleButton&, rBox, void) +{ + if (rBox.get_active()) + { + if (bLastWidthModified) + SizeHdl_Impl(*m_xWidthMF); + else + SizeHdl_Impl(*m_xHeightMF); + } +} + +IMPL_LINK_NOARG(SvxNumOptionsTabPage, CharFmtHdl_Impl, weld::ComboBox&, void) +{ + bAutomaticCharStyles = false; + sal_Int32 nEntryPos = m_xCharFmtLB->get_active(); + OUString sEntry = m_xCharFmtLB->get_active_text(); + sal_uInt16 nMask = 1; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + { + SvxNumberFormat aNumFmt(pActNum->GetLevel(i)); + if( 0 == nEntryPos ) + aNumFmt.SetCharFormatName(""); + else + { + if(SVX_NUM_BITMAP != (aNumFmt.GetNumberingType()&(~LINK_TOKEN))) + aNumFmt.SetCharFormatName(sEntry); + } + pActNum->SetLevel(i, aNumFmt); + } + nMask <<= 1; + } + SetModified(false); +}; + +IMPL_LINK(SvxNumOptionsTabPage, EditModifyHdl_Impl, weld::Entry&, rEdit, void) +{ + EditModifyHdl_Impl(&rEdit); +} + +IMPL_LINK(SvxNumOptionsTabPage, SpinModifyHdl_Impl, weld::SpinButton&, rSpinButton, void) +{ + EditModifyHdl_Impl(&rSpinButton); +} + +void SvxNumOptionsTabPage::EditModifyHdl_Impl(const weld::Entry* pEdit) +{ + bool bPrefix = pEdit == m_xPrefixED.get(); + bool bSuffix = pEdit == m_xSuffixED.get(); + bool bStart = pEdit == m_xStartED.get(); + sal_uInt16 nMask = 1; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + { + SvxNumberFormat aNumFmt(pActNum->GetLevel(i)); + if(bPrefix) + aNumFmt.SetPrefix(m_xPrefixED->get_text()); + else if(bSuffix) + aNumFmt.SetSuffix(m_xSuffixED->get_text()); + else if(bStart) + aNumFmt.SetStart(m_xStartED->get_value()); + pActNum->SetLevel(i, aNumFmt); + } + nMask <<= 1; + } + SetModified(); +} + +static long lcl_DrawGraphic(VirtualDevice* pVDev, const SvxNumberFormat &rFmt, long nXStart, + long nYMiddle, long nDivision) +{ + const SvxBrushItem* pBrushItem = rFmt.GetBrush(); + long nRet = 0; + if(pBrushItem) + { + const Graphic* pGrf = pBrushItem->GetGraphic(); + if(pGrf) + { + Size aGSize( rFmt.GetGraphicSize() ); + aGSize.setWidth( aGSize.Width() / nDivision ); + nRet = aGSize.Width(); + aGSize.setHeight( aGSize.Height() / nDivision ); + pGrf->Draw( pVDev, Point(nXStart,nYMiddle - ( aGSize.Height() / 2) ), + pVDev->PixelToLogic( aGSize ) ); + } + } + return nRet; + +} + +static long lcl_DrawBullet(VirtualDevice* pVDev, + const SvxNumberFormat& rFmt, long nXStart, + long nYStart, const Size& rSize) +{ + vcl::Font aTmpFont(pVDev->GetFont()); + + // via Uno it's possible that no font has been set! + vcl::Font aFont(rFmt.GetBulletFont() ? *rFmt.GetBulletFont() : aTmpFont); + Size aTmpSize(rSize); + aTmpSize.setWidth( aTmpSize.Width() * ( rFmt.GetBulletRelSize()) ); + aTmpSize.setWidth( aTmpSize.Width() / 100 ) ; + aTmpSize.setHeight( aTmpSize.Height() * ( rFmt.GetBulletRelSize()) ); + aTmpSize.setHeight( aTmpSize.Height() / 100 ) ; + // in case of a height of zero it is drawn in original height + if(!aTmpSize.Height()) + aTmpSize.setHeight( 1 ); + aFont.SetFontSize(aTmpSize); + aFont.SetTransparent(true); + Color aBulletColor = rFmt.GetBulletColor(); + if(aBulletColor == COL_AUTO) + aBulletColor = pVDev->GetFillColor().IsDark() ? COL_WHITE : COL_BLACK; + else if(aBulletColor == pVDev->GetFillColor()) + aBulletColor.Invert(); + aFont.SetColor(aBulletColor); + pVDev->SetFont( aFont ); + OUString aText(rFmt.GetBulletChar()); + long nY = nYStart; + nY -= ((aTmpSize.Height() - rSize.Height())/ 2); + pVDev->DrawText( Point(nXStart, nY), aText ); + long nRet = pVDev->GetTextWidth(aText); + + pVDev->SetFont(aTmpFont); + return nRet; +} + +SvxNumberingPreview::SvxNumberingPreview() + : pActNum(nullptr) + , bPosition(false) + , nActLevel(SAL_MAX_UINT16) +{ +} + +// paint preview of numeration +void SvxNumberingPreview::Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle& /*rRect*/) +{ + Size aSize(rRenderContext.PixelToLogic(GetOutputSizePixel())); + + const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings(); + const Color aBackColor = rStyleSettings.GetFieldColor(); + const Color aTextColor = rStyleSettings.GetFieldTextColor(); + + ScopedVclPtrInstance pVDev(rRenderContext); + pVDev->EnableRTL(rRenderContext.IsRTLEnabled()); + pVDev->SetMapMode(rRenderContext.GetMapMode()); + pVDev->SetOutputSize(aSize); + + Color aLineColor(COL_LIGHTGRAY); + if (aLineColor == aBackColor) + aLineColor.Invert(); + pVDev->SetLineColor(aLineColor); + pVDev->SetFillColor(aBackColor); + + if (pActNum) + { + long nWidthRelation = 30; // chapter dialog + + // height per level + long nXStep = aSize.Width() / (3 * pActNum->GetLevelCount()); + if (pActNum->GetLevelCount() < 10) + nXStep /= 2; + long nYStart = 4; + // the whole height mustn't be used for a single level + long nYStep = (aSize.Height() - 6)/ (pActNum->GetLevelCount() > 1 ? pActNum->GetLevelCount() : 5); + + aStdFont = OutputDevice::GetDefaultFont(DefaultFontType::UI_SANS, MsLangId::getSystemLanguage(), GetDefaultFontFlags::OnlyOne); + aStdFont.SetColor(aTextColor); + aStdFont.SetFillColor(aBackColor); + + long nFontHeight = nYStep * 6 / 10; + if (bPosition) + nFontHeight = nYStep * 15 / 10; + aStdFont.SetFontSize(Size( 0, nFontHeight )); + + SvxNodeNum aNum; + sal_uInt16 nPreNum = pActNum->GetLevel(0).GetStart(); + + if (bPosition) + { + long nLineHeight = nFontHeight * 8 / 7; + sal_uInt8 nStart = 0; + while (!(nActLevel & (1<GetLevelCount())); + for (sal_uInt8 nLevel = nStart; nLevel < nEnd; ++nLevel) + { + const SvxNumberFormat &rFmt = pActNum->GetLevel(nLevel); + aNum.GetLevelVal()[nLevel] = rFmt.GetStart(); + + long nXStart( 0 ); + short nTextOffset( 0 ); + long nNumberXPos( 0 ); + if (rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION) + { + nXStart = rFmt.GetAbsLSpace() / nWidthRelation; + nTextOffset = rFmt.GetCharTextDistance() / nWidthRelation; + nNumberXPos = nXStart; + long nFirstLineOffset = (-rFmt.GetFirstLineOffset()) / nWidthRelation; + + if (nFirstLineOffset <= nNumberXPos) + nNumberXPos = nNumberXPos - nFirstLineOffset; + else + nNumberXPos = 0; + // in draw this is valid + if (nTextOffset < 0) + nNumberXPos = nNumberXPos + nTextOffset; + } + else if (rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT) + { + const long nTmpNumberXPos((rFmt.GetIndentAt() + rFmt.GetFirstLineIndent() ) / nWidthRelation); + if (nTmpNumberXPos < 0) + { + nNumberXPos = 0; + } + else + { + nNumberXPos = nTmpNumberXPos; + } + } + + long nBulletWidth = 0; + if (SVX_NUM_BITMAP == (rFmt.GetNumberingType() &(~LINK_TOKEN))) + { + long nYMiddle = nYStart + ( nFontHeight / 2 ); + nBulletWidth = rFmt.IsShowSymbol() ? lcl_DrawGraphic(pVDev.get(), rFmt, nNumberXPos, nYMiddle, nWidthRelation) : 0; + } + else if (SVX_NUM_CHAR_SPECIAL == rFmt.GetNumberingType()) + { + nBulletWidth = rFmt.IsShowSymbol() ? lcl_DrawBullet(pVDev.get(), rFmt, nNumberXPos, nYStart, aStdFont.GetFontSize()) : 0; + } + else + { + pVDev->SetFont(aStdFont); + aNum.SetLevel(nLevel); + if (pActNum->IsContinuousNumbering()) + aNum.GetLevelVal()[nLevel] = nPreNum; + OUString aText(pActNum->MakeNumString( aNum )); + vcl::Font aSaveFont = pVDev->GetFont(); + vcl::Font aColorFont(aSaveFont); + Color aTmpBulletColor = rFmt.GetBulletColor(); + if (aTmpBulletColor == COL_AUTO) + aTmpBulletColor = aBackColor.IsDark() ? COL_WHITE : COL_BLACK; + else if (aTmpBulletColor == aBackColor) + aTmpBulletColor.Invert(); + aColorFont.SetColor(aTmpBulletColor); + pVDev->SetFont(aColorFont); + pVDev->DrawText(Point(nNumberXPos, nYStart), aText); + pVDev->SetFont(aSaveFont); + nBulletWidth = pVDev->GetTextWidth(aText); + nPreNum++; + } + if (rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT && + rFmt.GetLabelFollowedBy() == SvxNumberFormat::SPACE ) + { + pVDev->SetFont(aStdFont); + OUString aText(' '); + pVDev->DrawText( Point(nNumberXPos, nYStart), aText ); + nBulletWidth = nBulletWidth + pVDev->GetTextWidth(aText); + } + + long nTextXPos( 0 ); + if (rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION) + { + nTextXPos = nXStart; + if (nTextOffset < 0) + nTextXPos = nTextXPos + nTextOffset; + if (nNumberXPos + nBulletWidth + nTextOffset > nTextXPos) + nTextXPos = nNumberXPos + nBulletWidth + nTextOffset; + } + else if (rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT) + { + switch (rFmt.GetLabelFollowedBy()) + { + case SvxNumberFormat::LISTTAB: + { + nTextXPos = rFmt.GetListtabPos() / nWidthRelation; + if (nTextXPos < nNumberXPos + nBulletWidth) + { + nTextXPos = nNumberXPos + nBulletWidth; + } + } + break; + case SvxNumberFormat::SPACE: + case SvxNumberFormat::NOTHING: + case SvxNumberFormat::NEWLINE: + { + nTextXPos = nNumberXPos + nBulletWidth; + } + break; + } + + nXStart = rFmt.GetIndentAt() / nWidthRelation; + } + + ::tools::Rectangle aRect1(Point(nTextXPos, nYStart + nFontHeight / 2), Size(aSize.Width() / 2, 2)); + pVDev->SetFillColor(aBackColor); + pVDev->DrawRect(aRect1); + + ::tools::Rectangle aRect2(Point(nXStart, nYStart + nLineHeight + nFontHeight / 2 ), Size(aSize.Width() / 2, 2)); + pVDev->DrawRect(aRect2); + nYStart += 2 * nLineHeight; + } + } + else + { + //#i5153# painting gray or black rectangles as 'normal' numbering text + long nWidth = pVDev->GetTextWidth("Preview"); + long nTextHeight = pVDev->GetTextHeight(); + long nRectHeight = nTextHeight * 2 / 3; + long nTopOffset = nTextHeight - nRectHeight; + Color aBlackColor(COL_BLACK); + if (aBlackColor == aBackColor) + aBlackColor.Invert(); + + for (sal_uInt16 nLevel = 0; nLevel < pActNum->GetLevelCount(); ++nLevel, nYStart = nYStart + nYStep) + { + const SvxNumberFormat &rFmt = pActNum->GetLevel(nLevel); + aNum.GetLevelVal()[ nLevel ] = rFmt.GetStart(); + long nXStart( 0 ); + pVDev->SetFillColor( aBackColor ); + + if (rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION) + { + nXStart = rFmt.GetAbsLSpace() / nWidthRelation; + } + else if (rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT) + { + const long nTmpXStart((rFmt.GetIndentAt() + rFmt.GetFirstLineIndent() ) / nWidthRelation); + if (nTmpXStart < 0) + { + nXStart = 0; + } + else + { + nXStart = nTmpXStart; + } + } + nXStart /= 2; + nXStart += 2; + long nTextOffset = 2 * nXStep; + if (SVX_NUM_BITMAP == (rFmt.GetNumberingType()&(~LINK_TOKEN))) + { + if (rFmt.IsShowSymbol()) + { + long nYMiddle = nYStart + ( nFontHeight / 2 ); + nTextOffset = lcl_DrawGraphic(pVDev.get(), rFmt, nXStart, nYMiddle, nWidthRelation); + nTextOffset = nTextOffset + nXStep; + } + } + else if (SVX_NUM_CHAR_SPECIAL == rFmt.GetNumberingType()) + { + if (rFmt.IsShowSymbol()) + { + nTextOffset = lcl_DrawBullet(pVDev.get(), rFmt, nXStart, nYStart, aStdFont.GetFontSize()); + nTextOffset = nTextOffset + nXStep; + } + } + else + { + vcl::Font aFont(aStdFont); + Size aTmpSize(aStdFont.GetFontSize()); + if(pActNum->IsFeatureSupported(SvxNumRuleFlags::BULLET_REL_SIZE)) + { + aTmpSize.setWidth( aTmpSize.Width() * ( rFmt.GetBulletRelSize()) ); + aTmpSize.setWidth( aTmpSize.Width() / 100 ) ; + aTmpSize.setHeight( aTmpSize.Height() * ( rFmt.GetBulletRelSize()) ); + aTmpSize.setHeight( aTmpSize.Height() / 100 ) ; + } + if(!aTmpSize.Height()) + aTmpSize.setHeight( 1 ); + aFont.SetFontSize(aTmpSize); + Color aTmpBulletColor = rFmt.GetBulletColor(); + if (aTmpBulletColor == COL_AUTO) + aTmpBulletColor = aBackColor.IsDark() ? COL_WHITE : COL_BLACK; + else if (aTmpBulletColor == aBackColor) + aTmpBulletColor.Invert(); + aFont.SetColor(aTmpBulletColor); + pVDev->SetFont(aFont); + aNum.SetLevel( nLevel ); + if (pActNum->IsContinuousNumbering()) + aNum.GetLevelVal()[nLevel] = nPreNum; + OUString aText(pActNum->MakeNumString(aNum)); + long nY = nYStart; + nY -= (pVDev->GetTextHeight() - nTextHeight - pVDev->GetFontMetric().GetDescent()); + pVDev->DrawText(Point(nXStart, nY), aText); + nTextOffset = pVDev->GetTextWidth(aText); + nTextOffset = nTextOffset + nXStep; + nPreNum++; + pVDev->SetFont(aStdFont); + } + //#i5153# the selected rectangle(s) should be black + if (0 != (nActLevel & (1<SetFillColor( aBlackColor ); + pVDev->SetLineColor( aBlackColor ); + } + else + { + //#i5153# unselected levels are gray + pVDev->SetFillColor( aLineColor ); + pVDev->SetLineColor( aLineColor ); + } + ::tools::Rectangle aRect1(Point(nXStart + nTextOffset, nYStart + nTopOffset), Size(nWidth, nRectHeight)); + pVDev->DrawRect(aRect1); + } + } + } + rRenderContext.DrawOutDev(Point(), aSize, Point(), aSize, *pVDev); +} + + +//See uiconfig/swriter/ui/outlinepositionpage.ui for effectively a duplicate +//dialog to this one, except with a different preview window impl. +//TODO, determine if SwNumPositionTabPage and SvxNumPositionTabPage can be +//merged +SvxNumPositionTabPage::SvxNumPositionTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/numberingpositionpage.ui", "NumberingPositionPage", &rSet) + , m_pLevelHdlEvent(nullptr) + , nActNumLvl(1) + , nNumItemId(SID_ATTR_NUMBERING_RULE) + , bModified(false) + , bPreset(false) + , bInInintControl(false) + , bLabelAlignmentPosAndSpaceModeActive(false) + , m_xLevelLB(m_xBuilder->weld_tree_view("levellb")) + , m_xDistBorderFT(m_xBuilder->weld_label("indent")) + , m_xDistBorderMF(m_xBuilder->weld_metric_spin_button("indentmf", FieldUnit::CM)) + , m_xRelativeCB(m_xBuilder->weld_check_button("relative")) + , m_xIndentFT(m_xBuilder->weld_label("numberingwidth")) + , m_xIndentMF(m_xBuilder->weld_metric_spin_button("numberingwidthmf", FieldUnit::CM)) + , m_xDistNumFT(m_xBuilder->weld_label("numdist")) + , m_xDistNumMF(m_xBuilder->weld_metric_spin_button("numdistmf", FieldUnit::CM)) + , m_xAlignFT(m_xBuilder->weld_label("numalign")) + , m_xAlignLB(m_xBuilder->weld_combo_box("numalignlb")) + , m_xLabelFollowedByFT(m_xBuilder->weld_label("numfollowedby")) + , m_xLabelFollowedByLB(m_xBuilder->weld_combo_box("numfollowedbylb")) + , m_xListtabFT(m_xBuilder->weld_label("at")) + , m_xListtabMF(m_xBuilder->weld_metric_spin_button("atmf", FieldUnit::CM)) + , m_xAlign2FT(m_xBuilder->weld_label("num2align")) + , m_xAlign2LB(m_xBuilder->weld_combo_box("num2alignlb")) + , m_xAlignedAtFT(m_xBuilder->weld_label("alignedat")) + , m_xAlignedAtMF(m_xBuilder->weld_metric_spin_button("alignedatmf", FieldUnit::CM)) + , m_xIndentAtFT(m_xBuilder->weld_label("indentat")) + , m_xIndentAtMF(m_xBuilder->weld_metric_spin_button("indentatmf", FieldUnit::CM)) + , m_xStandardPB(m_xBuilder->weld_button("standard")) + , m_xPreviewWIN(new weld::CustomWeld(*m_xBuilder, "preview", m_aPreviewWIN)) +{ + SetExchangeSupport(); + + m_xAlignedAtMF->set_range(0, SAL_MAX_INT32, FieldUnit::NONE); + m_xListtabMF->set_range(0, SAL_MAX_INT32, FieldUnit::NONE); + m_xIndentAtMF->set_range(0, SAL_MAX_INT32, FieldUnit::NONE); + + m_xRelativeCB->set_active(true); + m_xAlignLB->connect_changed(LINK(this, SvxNumPositionTabPage, EditModifyHdl_Impl)); + m_xAlign2LB->connect_changed(LINK(this, SvxNumPositionTabPage, EditModifyHdl_Impl)); + for ( sal_Int32 i = 0; i < m_xAlignLB->get_count(); ++i ) + { + m_xAlign2LB->append_text(m_xAlignLB->get_text(i)); + } + + Link aLk3 = LINK(this, SvxNumPositionTabPage, DistanceHdl_Impl); + m_xDistBorderMF->connect_value_changed(aLk3); + m_xDistNumMF->connect_value_changed(aLk3); + m_xIndentMF->connect_value_changed(aLk3); + + m_xLabelFollowedByLB->connect_changed(LINK(this, SvxNumPositionTabPage, LabelFollowedByHdl_Impl)); + + m_xListtabMF->connect_value_changed(LINK(this, SvxNumPositionTabPage, ListtabPosHdl_Impl)); + m_xAlignedAtMF->connect_value_changed(LINK(this, SvxNumPositionTabPage, AlignAtHdl_Impl)); + m_xIndentAtMF->connect_value_changed(LINK(this, SvxNumPositionTabPage, IndentAtHdl_Impl)); + + m_xLevelLB->set_selection_mode(SelectionMode::Multiple); + m_xLevelLB->connect_changed(LINK(this, SvxNumPositionTabPage, LevelHdl_Impl)); + m_xRelativeCB->connect_toggled(LINK(this, SvxNumPositionTabPage, RelativeHdl_Impl)); + m_xStandardPB->connect_clicked(LINK(this, SvxNumPositionTabPage, StandardHdl_Impl)); + + m_xRelativeCB->set_active(bLastRelative); + m_aPreviewWIN.SetPositionMode(); + eCoreUnit = rSet.GetPool()->GetMetric(rSet.GetPool()->GetWhich(SID_ATTR_NUMBERING_RULE)); +} + +SvxNumPositionTabPage::~SvxNumPositionTabPage() +{ + if (m_pLevelHdlEvent) + { + Application::RemoveUserEvent(m_pLevelHdlEvent); + m_pLevelHdlEvent = nullptr; + } + m_xPreviewWIN.reset(); +} + +/*-------------------------------------------------------*/ + +void SvxNumPositionTabPage::InitControls() +{ + bInInintControl = true; + const bool bRelative = !bLabelAlignmentPosAndSpaceModeActive && + m_xRelativeCB->get_sensitive() && m_xRelativeCB->get_active(); + const bool bSingleSelection = m_xLevelLB->count_selected_rows() == 1 && + SAL_MAX_UINT16 != nActNumLvl; + + m_xDistBorderMF->set_sensitive( !bLabelAlignmentPosAndSpaceModeActive && + ( bSingleSelection || bRelative ) ); + m_xDistBorderFT->set_sensitive( !bLabelAlignmentPosAndSpaceModeActive && + ( bSingleSelection || bRelative ) ); + + bool bSetDistEmpty = false; + bool bSameDistBorderNum = !bLabelAlignmentPosAndSpaceModeActive; + bool bSameDist = !bLabelAlignmentPosAndSpaceModeActive; + bool bSameIndent = !bLabelAlignmentPosAndSpaceModeActive; + bool bSameAdjust = true; + + bool bSameLabelFollowedBy = bLabelAlignmentPosAndSpaceModeActive; + bool bSameListtab = bLabelAlignmentPosAndSpaceModeActive; + bool bSameAlignAt = bLabelAlignmentPosAndSpaceModeActive; + bool bSameIndentAt = bLabelAlignmentPosAndSpaceModeActive; + + const SvxNumberFormat* aNumFmtArr[SVX_MAX_NUM]; + sal_uInt16 nMask = 1; + sal_uInt16 nLvl = SAL_MAX_UINT16; + long nFirstBorderTextRelative = -1; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + aNumFmtArr[i] = &pActNum->GetLevel(i); + if(nActNumLvl & nMask) + { + if(SAL_MAX_UINT16 == nLvl) + nLvl = i; + + if( i > nLvl) + { + bSameAdjust &= aNumFmtArr[i]->GetNumAdjust() == aNumFmtArr[nLvl]->GetNumAdjust(); + if ( !bLabelAlignmentPosAndSpaceModeActive ) + { + if(bRelative) + { + if(nFirstBorderTextRelative == -1) + nFirstBorderTextRelative = + (aNumFmtArr[i]->GetAbsLSpace() + aNumFmtArr[i]->GetFirstLineOffset() - + aNumFmtArr[i - 1]->GetAbsLSpace() + aNumFmtArr[i - 1]->GetFirstLineOffset()); + else + bSameDistBorderNum &= nFirstBorderTextRelative == + (aNumFmtArr[i]->GetAbsLSpace() + aNumFmtArr[i]->GetFirstLineOffset() - + aNumFmtArr[i - 1]->GetAbsLSpace() + aNumFmtArr[i - 1]->GetFirstLineOffset()); + } + else + bSameDistBorderNum &= + aNumFmtArr[i]->GetAbsLSpace() - aNumFmtArr[i]->GetFirstLineOffset() == + aNumFmtArr[i - 1]->GetAbsLSpace() - aNumFmtArr[i - 1]->GetFirstLineOffset(); + + bSameDist &= aNumFmtArr[i]->GetCharTextDistance() == aNumFmtArr[nLvl]->GetCharTextDistance(); + bSameIndent &= aNumFmtArr[i]->GetFirstLineOffset() == aNumFmtArr[nLvl]->GetFirstLineOffset(); + } + else + { + bSameLabelFollowedBy &= + aNumFmtArr[i]->GetLabelFollowedBy() == aNumFmtArr[nLvl]->GetLabelFollowedBy(); + bSameListtab &= + aNumFmtArr[i]->GetListtabPos() == aNumFmtArr[nLvl]->GetListtabPos(); + bSameAlignAt &= + ( ( aNumFmtArr[i]->GetIndentAt() + aNumFmtArr[i]->GetFirstLineIndent() ) + == ( aNumFmtArr[nLvl]->GetIndentAt() + aNumFmtArr[nLvl]->GetFirstLineIndent() ) ); + bSameIndentAt &= + aNumFmtArr[i]->GetIndentAt() == aNumFmtArr[nLvl]->GetIndentAt(); + } + } + } + nMask <<= 1; + + } + if (SVX_MAX_NUM <= nLvl) + { + OSL_ENSURE(false, "cannot happen."); + return; + } + + if(bSameDistBorderNum) + { + long nDistBorderNum; + if(bRelative) + { + nDistBorderNum = static_cast(aNumFmtArr[nLvl]->GetAbsLSpace())+ aNumFmtArr[nLvl]->GetFirstLineOffset(); + if(nLvl) + nDistBorderNum -= static_cast(aNumFmtArr[nLvl - 1]->GetAbsLSpace())+ aNumFmtArr[nLvl - 1]->GetFirstLineOffset(); + } + else + { + nDistBorderNum = static_cast(aNumFmtArr[nLvl]->GetAbsLSpace())+ aNumFmtArr[nLvl]->GetFirstLineOffset(); + } + SetMetricValue(*m_xDistBorderMF, nDistBorderNum, eCoreUnit); + } + else + bSetDistEmpty = true; + + if(bSameDist) + SetMetricValue(*m_xDistNumMF, aNumFmtArr[nLvl]->GetCharTextDistance(), eCoreUnit); + else + m_xDistNumMF->set_text(""); + if(bSameIndent) + SetMetricValue(*m_xIndentMF, - aNumFmtArr[nLvl]->GetFirstLineOffset(), eCoreUnit); + else + m_xIndentMF->set_text(""); + + if(bSameAdjust) + { + sal_Int32 nPos = 1; // centered + if(aNumFmtArr[nLvl]->GetNumAdjust() == SvxAdjust::Left) + nPos = 0; + else if(aNumFmtArr[nLvl]->GetNumAdjust() == SvxAdjust::Right) + nPos = 2; + m_xAlignLB->set_active(nPos); + m_xAlign2LB->set_active(nPos); + } + else + { + m_xAlignLB->set_active(-1); + m_xAlign2LB->set_active(-1); + } + + if ( bSameLabelFollowedBy ) + { + sal_Int32 nPos = 0; // LISTTAB + if ( aNumFmtArr[nLvl]->GetLabelFollowedBy() == SvxNumberFormat::SPACE ) + { + nPos = 1; + } + else if ( aNumFmtArr[nLvl]->GetLabelFollowedBy() == SvxNumberFormat::NOTHING ) + { + nPos = 2; + } + else if ( aNumFmtArr[nLvl]->GetLabelFollowedBy() == SvxNumberFormat::NEWLINE ) + { + nPos = 3; + } + m_xLabelFollowedByLB->set_active(nPos); + } + else + { + m_xLabelFollowedByLB->set_active(-1); + } + + if ( aNumFmtArr[nLvl]->GetLabelFollowedBy() == SvxNumberFormat::LISTTAB ) + { + m_xListtabFT->set_sensitive(true); + m_xListtabMF->set_sensitive(true); + if ( bSameListtab ) + { + SetMetricValue(*m_xListtabMF, aNumFmtArr[nLvl]->GetListtabPos(), eCoreUnit); + } + else + { + m_xListtabMF->set_text(""); + } + } + else + { + m_xListtabFT->set_sensitive(false); + m_xListtabMF->set_sensitive(false); + m_xListtabMF->set_text(""); + } + + if ( bSameAlignAt ) + { + SetMetricValue(*m_xAlignedAtMF, + aNumFmtArr[nLvl]->GetIndentAt() + aNumFmtArr[nLvl]->GetFirstLineIndent(), + eCoreUnit); + } + else + { + m_xAlignedAtMF->set_text(""); + } + + if ( bSameIndentAt ) + { + SetMetricValue(*m_xIndentAtMF, aNumFmtArr[nLvl]->GetIndentAt(), eCoreUnit); + } + else + { + m_xIndentAtMF->set_text(""); + } + + if ( bSetDistEmpty ) + m_xDistBorderMF->set_text(""); + + bInInintControl = false; +} + +void SvxNumPositionTabPage::ActivatePage(const SfxItemSet& rSet) +{ + const SfxPoolItem* pItem; + sal_uInt16 nTmpNumLvl = 1; + const SfxItemSet* pExampleSet = GetDialogExampleSet(); + if(pExampleSet) + { + if(SfxItemState::SET == pExampleSet->GetItemState(SID_PARAM_NUM_PRESET, false, &pItem)) + bPreset = static_cast(pItem)->GetValue(); + if(SfxItemState::SET == pExampleSet->GetItemState(SID_PARAM_CUR_NUM_LEVEL, false, &pItem)) + nTmpNumLvl = static_cast(pItem)->GetValue(); + } + if(SfxItemState::SET == rSet.GetItemState(nNumItemId, false, &pItem)) + { + pSaveNum.reset( new SvxNumRule(*static_cast(pItem)->GetNumRule()) ); + } + bModified = (!pActNum->Get( 0 ) || bPreset); + if(*pSaveNum != *pActNum || + nActNumLvl != nTmpNumLvl ) + { + *pActNum = *pSaveNum; + nActNumLvl = nTmpNumLvl; + sal_uInt16 nMask = 1; + m_xLevelLB->unselect_all(); + if (nActNumLvl == SAL_MAX_UINT16) + m_xLevelLB->select(pActNum->GetLevelCount()); + if (nActNumLvl != SAL_MAX_UINT16) + for (sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if (nActNumLvl & nMask) + m_xLevelLB->select(i); + nMask <<= 1 ; + } + m_xRelativeCB->set_sensitive(nActNumLvl != 1); + + InitPosAndSpaceMode(); + ShowControlsDependingOnPosAndSpaceMode(); + + InitControls(); + } + m_aPreviewWIN.SetLevel(nActNumLvl); + m_aPreviewWIN.Invalidate(); +} + +DeactivateRC SvxNumPositionTabPage::DeactivatePage(SfxItemSet *_pSet) +{ + if(_pSet) + { + if (m_xDistBorderMF->get_sensitive()) + DistanceHdl_Impl(*m_xDistBorderMF); + DistanceHdl_Impl(*m_xIndentMF); + FillItemSet(_pSet); + } + return DeactivateRC::LeavePage; +} + +bool SvxNumPositionTabPage::FillItemSet( SfxItemSet* rSet ) +{ + rSet->Put(SfxUInt16Item(SID_PARAM_CUR_NUM_LEVEL, nActNumLvl)); + + if(bModified && pActNum) + { + *pSaveNum = *pActNum; + rSet->Put(SvxNumBulletItem( *pSaveNum, nNumItemId )); + rSet->Put(SfxBoolItem(SID_PARAM_NUM_PRESET, false)); + } + return bModified; +} + +void SvxNumPositionTabPage::Reset( const SfxItemSet* rSet ) +{ + const SfxPoolItem* pItem; + // in Draw the item exists as WhichId, in Writer only as SlotId + SfxItemState eState = rSet->GetItemState(SID_ATTR_NUMBERING_RULE, false, &pItem); + if(eState != SfxItemState::SET) + { + nNumItemId = rSet->GetPool()->GetWhich(SID_ATTR_NUMBERING_RULE); + eState = rSet->GetItemState(nNumItemId, false, &pItem); + + if( eState != SfxItemState::SET ) + { + pItem = &static_cast< const SvxNumBulletItem& >( rSet->Get( nNumItemId ) ); + eState = SfxItemState::SET; + } + + } + DBG_ASSERT(eState == SfxItemState::SET, "no item found!"); + pSaveNum.reset( new SvxNumRule(*static_cast(pItem)->GetNumRule()) ); + + // insert levels + if (!m_xLevelLB->count_selected_rows()) + { + for(sal_uInt16 i = 1; i <= pSaveNum->GetLevelCount(); i++) + m_xLevelLB->append_text(OUString::number(i)); + if(pSaveNum->GetLevelCount() > 1) + { + OUString sEntry = "1 - " + OUString::number( pSaveNum->GetLevelCount() ); + m_xLevelLB->append_text(sEntry); + m_xLevelLB->select_text(sEntry); + } + else + m_xLevelLB->select(0); + } + else + m_xLevelLB->select(m_xLevelLB->count_selected_rows() - 1); + sal_uInt16 nMask = 1; + m_xLevelLB->unselect_all(); + if (nActNumLvl == SAL_MAX_UINT16) + { + m_xLevelLB->select(pSaveNum->GetLevelCount()); + } + else + { + for(sal_uInt16 i = 0; i < pSaveNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + m_xLevelLB->select(i); + nMask <<= 1; + } + } + + if(!pActNum) + pActNum.reset( new SvxNumRule(*pSaveNum) ); + else if(*pSaveNum != *pActNum) + *pActNum = *pSaveNum; + m_aPreviewWIN.SetNumRule(pActNum.get()); + + InitPosAndSpaceMode(); + ShowControlsDependingOnPosAndSpaceMode(); + + InitControls(); + bModified = false; +} + +void SvxNumPositionTabPage::InitPosAndSpaceMode() +{ + if ( pActNum == nullptr ) + { + SAL_WARN( "cui.tabpages", + " - misusage of method -> has to be already set!" ); + return; + } + + SvxNumberFormat::SvxNumPositionAndSpaceMode ePosAndSpaceMode = + SvxNumberFormat::LABEL_ALIGNMENT; + sal_uInt16 nMask = 1; + for( sal_uInt16 i = 0; i < pActNum->GetLevelCount(); ++i ) + { + if(nActNumLvl & nMask) + { + SvxNumberFormat aNumFmt( pActNum->GetLevel(i) ); + ePosAndSpaceMode = aNumFmt.GetPositionAndSpaceMode(); + if ( ePosAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT ) + { + break; + } + } + nMask <<= 1; + } + + bLabelAlignmentPosAndSpaceModeActive = + ePosAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT; +} + +void SvxNumPositionTabPage::ShowControlsDependingOnPosAndSpaceMode() +{ + m_xDistBorderFT->set_visible( !bLabelAlignmentPosAndSpaceModeActive ); + m_xDistBorderMF->set_visible( !bLabelAlignmentPosAndSpaceModeActive ); + m_xRelativeCB->set_visible( !bLabelAlignmentPosAndSpaceModeActive ); + m_xIndentFT->set_visible( !bLabelAlignmentPosAndSpaceModeActive ); + m_xIndentMF->set_visible( !bLabelAlignmentPosAndSpaceModeActive ); + m_xDistNumFT->set_visible( !bLabelAlignmentPosAndSpaceModeActive && + pActNum->IsFeatureSupported(SvxNumRuleFlags::CONTINUOUS) ); + m_xDistNumMF->set_visible( !bLabelAlignmentPosAndSpaceModeActive && + pActNum->IsFeatureSupported(SvxNumRuleFlags::CONTINUOUS)); + m_xAlignFT->set_visible( !bLabelAlignmentPosAndSpaceModeActive ); + m_xAlignLB->set_visible( !bLabelAlignmentPosAndSpaceModeActive ); + + m_xLabelFollowedByFT->set_visible( bLabelAlignmentPosAndSpaceModeActive ); + m_xLabelFollowedByLB->set_visible( bLabelAlignmentPosAndSpaceModeActive ); + m_xListtabFT->set_visible( bLabelAlignmentPosAndSpaceModeActive ); + m_xListtabMF->set_visible( bLabelAlignmentPosAndSpaceModeActive ); + m_xAlign2FT->set_visible( bLabelAlignmentPosAndSpaceModeActive ); + m_xAlign2LB->set_visible( bLabelAlignmentPosAndSpaceModeActive ); + m_xAlignedAtFT->set_visible( bLabelAlignmentPosAndSpaceModeActive ); + m_xAlignedAtMF->set_visible( bLabelAlignmentPosAndSpaceModeActive ); + m_xIndentAtFT->set_visible( bLabelAlignmentPosAndSpaceModeActive ); + m_xIndentAtMF->set_visible( bLabelAlignmentPosAndSpaceModeActive ); +} + +std::unique_ptr SvxNumPositionTabPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet) +{ + return std::make_unique(pPage, pController, *rAttrSet); +} + +void SvxNumPositionTabPage::SetMetric(FieldUnit eMetric) +{ + if (eMetric == FieldUnit::MM) + { + m_xDistBorderMF->set_digits(1); + m_xDistNumMF->set_digits(1); + m_xIndentMF->set_digits(1); + m_xListtabMF->set_digits(1); + m_xAlignedAtMF->set_digits(1); + m_xIndentAtMF->set_digits(1); + } + m_xDistBorderMF->set_unit(eMetric); + m_xDistNumMF->set_unit(eMetric); + m_xIndentMF->set_unit(eMetric); + m_xListtabMF->set_unit(eMetric); + m_xAlignedAtMF->set_unit(eMetric); + m_xIndentAtMF->set_unit(eMetric); +} + +IMPL_LINK_NOARG(SvxNumPositionTabPage, EditModifyHdl_Impl, weld::ComboBox&, void) +{ + sal_uInt16 nMask = 1; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + { + SvxNumberFormat aNumFmt(pActNum->GetLevel(i)); + + const sal_Int32 nPos = m_xAlignLB->get_visible() + ? m_xAlignLB->get_active() + : m_xAlign2LB->get_active(); + SvxAdjust eAdjust = SvxAdjust::Center; + if(nPos == 0) + eAdjust = SvxAdjust::Left; + else if(nPos == 2) + eAdjust = SvxAdjust::Right; + aNumFmt.SetNumAdjust( eAdjust ); + pActNum->SetLevel(i, aNumFmt); + } + nMask <<= 1; + } + SetModified(); +} + +IMPL_LINK_NOARG(SvxNumPositionTabPage, LevelHdl_Impl, weld::TreeView&, void) +{ + if (m_pLevelHdlEvent) + return; + // tdf#127120 multiselection may be implemented by deselect follow by select so + // fire off the handler to happen on next event loop and only process the + // final state + m_pLevelHdlEvent = Application::PostUserEvent(LINK(this, SvxNumPositionTabPage, LevelHdl)); +} + +IMPL_LINK_NOARG(SvxNumPositionTabPage, LevelHdl, void*, void) +{ + m_pLevelHdlEvent = nullptr; + + sal_uInt16 nSaveNumLvl = nActNumLvl; + nActNumLvl = 0; + std::vector aSelectedRows = m_xLevelLB->get_selected_rows(); + if (std::find(aSelectedRows.begin(), aSelectedRows.end(), pActNum->GetLevelCount()) != aSelectedRows.end() && + (aSelectedRows.size() == 1 || nSaveNumLvl != 0xffff)) + { + nActNumLvl = 0xFFFF; + for( sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++ ) + m_xLevelLB->unselect(i); + } + else if (!aSelectedRows.empty()) + { + sal_uInt16 nMask = 1; + for( sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++ ) + { + if (std::find(aSelectedRows.begin(), aSelectedRows.end(), i) != aSelectedRows.end()) + nActNumLvl |= nMask; + nMask <<= 1; + } + m_xLevelLB->unselect(pActNum->GetLevelCount()); + } + else + { + nActNumLvl = nSaveNumLvl; + sal_uInt16 nMask = 1; + for( sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++ ) + { + if(nActNumLvl & nMask) + { + m_xLevelLB->select(i); + break; + } + nMask <<=1; + } + } + m_xRelativeCB->set_sensitive(nActNumLvl != 1); + SetModified(); + InitPosAndSpaceMode(); + ShowControlsDependingOnPosAndSpaceMode(); + InitControls(); +} + +IMPL_LINK(SvxNumPositionTabPage, DistanceHdl_Impl, weld::MetricSpinButton&, rFld, void) +{ + if(bInInintControl) + return; + long nValue = GetCoreValue(rFld, eCoreUnit); + sal_uInt16 nMask = 1; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + { + SvxNumberFormat aNumFmt( pActNum->GetLevel( i ) ); + if (&rFld == m_xDistBorderMF.get()) + { + + if (m_xRelativeCB->get_active()) + { + if(0 == i) + { + auto const nTmp = aNumFmt.GetFirstLineOffset(); + aNumFmt.SetAbsLSpace( nValue - nTmp); + } + else + { + long nTmp = pActNum->GetLevel( i - 1 ).GetAbsLSpace() + + pActNum->GetLevel( i - 1 ).GetFirstLineOffset() - + pActNum->GetLevel( i ).GetFirstLineOffset(); + + aNumFmt.SetAbsLSpace( nValue + nTmp); + } + } + else + { + aNumFmt.SetAbsLSpace( nValue - aNumFmt.GetFirstLineOffset()); + } + } + else if (&rFld == m_xDistNumMF.get()) + { + aNumFmt.SetCharTextDistance( static_cast(nValue) ); + } + else if (&rFld == m_xIndentMF.get()) + { + // together with the FirstLineOffset the AbsLSpace must be changed, too + long nDiff = nValue + aNumFmt.GetFirstLineOffset(); + auto const nAbsLSpace = aNumFmt.GetAbsLSpace(); + aNumFmt.SetAbsLSpace(nAbsLSpace + nDiff); + aNumFmt.SetFirstLineOffset( -nValue ); + } + + pActNum->SetLevel( i, aNumFmt ); + } + nMask <<= 1; + } + + SetModified(); + if (!m_xDistBorderMF->get_sensitive()) + { + m_xDistBorderMF->set_text(""); + } +} + +IMPL_LINK(SvxNumPositionTabPage, RelativeHdl_Impl, weld::ToggleButton&, rBox, void) +{ + bool bOn = rBox.get_active(); + bool bSingleSelection = m_xLevelLB->count_selected_rows() == 1 && SAL_MAX_UINT16 != nActNumLvl; + bool bSetValue = false; + long nValue = 0; + if(bOn || bSingleSelection) + { + sal_uInt16 nMask = 1; + bool bFirst = true; + bSetValue = true; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + { + const SvxNumberFormat &rNumFmt = pActNum->GetLevel(i); + if(bFirst) + { + nValue = rNumFmt.GetAbsLSpace() + rNumFmt.GetFirstLineOffset(); + if(bOn && i) + nValue -= (pActNum->GetLevel(i - 1).GetAbsLSpace() + pActNum->GetLevel(i - 1).GetFirstLineOffset()); + } + else + bSetValue = nValue == + (rNumFmt.GetAbsLSpace() + rNumFmt.GetFirstLineOffset()) - + (pActNum->GetLevel(i - 1).GetAbsLSpace() + pActNum->GetLevel(i - 1).GetFirstLineOffset()); + bFirst = false; + } + nMask <<= 1; + } + + } + if(bSetValue) + SetMetricValue(*m_xDistBorderMF, nValue, eCoreUnit); + else + m_xDistBorderMF->set_text(""); + m_xDistBorderMF->set_sensitive(bOn || bSingleSelection); + m_xDistBorderFT->set_sensitive(bOn || bSingleSelection); + bLastRelative = bOn; +} + +IMPL_LINK_NOARG(SvxNumPositionTabPage, LabelFollowedByHdl_Impl, weld::ComboBox&, void) +{ + // determine value to be set at the chosen list levels + SvxNumberFormat::LabelFollowedBy eLabelFollowedBy = SvxNumberFormat::LISTTAB; + { + const auto nPos = m_xLabelFollowedByLB->get_active(); + if ( nPos == 1 ) + { + eLabelFollowedBy = SvxNumberFormat::SPACE; + } + else if ( nPos == 2 ) + { + eLabelFollowedBy = SvxNumberFormat::NOTHING; + } + else if ( nPos == 3 ) + { + eLabelFollowedBy = SvxNumberFormat::NEWLINE; + } + } + + // set value at the chosen list levels + bool bSameListtabPos = true; + sal_uInt16 nFirstLvl = SAL_MAX_UINT16; + sal_uInt16 nMask = 1; + for( sal_uInt16 i = 0; i < pActNum->GetLevelCount(); ++i ) + { + if ( nActNumLvl & nMask ) + { + SvxNumberFormat aNumFmt( pActNum->GetLevel(i) ); + aNumFmt.SetLabelFollowedBy( eLabelFollowedBy ); + pActNum->SetLevel( i, aNumFmt ); + + if ( nFirstLvl == SAL_MAX_UINT16 ) + { + nFirstLvl = i; + } + else + { + bSameListtabPos &= aNumFmt.GetListtabPos() == + pActNum->GetLevel( nFirstLvl ).GetListtabPos(); + } + } + nMask <<= 1; + } + + // enable/disable metric field for list tab stop position depending on + // selected item following the list label. + m_xListtabFT->set_sensitive( eLabelFollowedBy == SvxNumberFormat::LISTTAB ); + m_xListtabMF->set_sensitive( eLabelFollowedBy == SvxNumberFormat::LISTTAB ); + if ( bSameListtabPos && eLabelFollowedBy == SvxNumberFormat::LISTTAB ) + { + SetMetricValue(*m_xListtabMF, pActNum->GetLevel( nFirstLvl ).GetListtabPos(), eCoreUnit); + } + else + { + m_xListtabMF->set_text(OUString()); + } + + SetModified(); +} + +IMPL_LINK(SvxNumPositionTabPage, ListtabPosHdl_Impl, weld::MetricSpinButton&, rFld, void) +{ + // determine value to be set at the chosen list levels + const long nValue = GetCoreValue(rFld, eCoreUnit); + + // set value at the chosen list levels + sal_uInt16 nMask = 1; + for( sal_uInt16 i = 0; i < pActNum->GetLevelCount(); ++i ) + { + if ( nActNumLvl & nMask ) + { + SvxNumberFormat aNumFmt( pActNum->GetLevel(i) ); + aNumFmt.SetListtabPos( nValue ); + pActNum->SetLevel( i, aNumFmt ); + } + nMask <<= 1; + } + + SetModified(); +} + +IMPL_LINK(SvxNumPositionTabPage, AlignAtHdl_Impl, weld::MetricSpinButton&, rFld, void) +{ + // determine value to be set at the chosen list levels + const long nValue = GetCoreValue(rFld, eCoreUnit); + + // set value at the chosen list levels + sal_uInt16 nMask = 1; + for( sal_uInt16 i = 0; i < pActNum->GetLevelCount(); ++i ) + { + if ( nActNumLvl & nMask ) + { + SvxNumberFormat aNumFmt( pActNum->GetLevel(i) ); + const long nFirstLineIndent = nValue - aNumFmt.GetIndentAt(); + aNumFmt.SetFirstLineIndent( nFirstLineIndent ); + pActNum->SetLevel( i, aNumFmt ); + } + nMask <<= 1; + } + + SetModified(); +} + +IMPL_LINK(SvxNumPositionTabPage, IndentAtHdl_Impl, weld::MetricSpinButton&, rFld, void) +{ + // determine value to be set at the chosen list levels + const long nValue = GetCoreValue(rFld, eCoreUnit); + + // set value at the chosen list levels + sal_uInt16 nMask = 1; + for( sal_uInt16 i = 0; i < pActNum->GetLevelCount(); ++i ) + { + if ( nActNumLvl & nMask ) + { + SvxNumberFormat aNumFmt( pActNum->GetLevel(i) ); + const long nAlignedAt = aNumFmt.GetIndentAt() + + aNumFmt.GetFirstLineIndent(); + aNumFmt.SetIndentAt( nValue ); + const long nNewFirstLineIndent = nAlignedAt - nValue; + aNumFmt.SetFirstLineIndent( nNewFirstLineIndent ); + pActNum->SetLevel( i, aNumFmt ); + } + nMask <<= 1; + } + + SetModified(); +} + +IMPL_LINK_NOARG(SvxNumPositionTabPage, StandardHdl_Impl, weld::Button&, void) +{ + sal_uInt16 nMask = 1; + SvxNumRule aTmpNumRule( pActNum->GetFeatureFlags(), + pActNum->GetLevelCount(), + pActNum->IsContinuousNumbering(), + SvxNumRuleType::NUMBERING, + pActNum->GetLevel( 0 ).GetPositionAndSpaceMode() ); + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + { + SvxNumberFormat aNumFmt( pActNum->GetLevel( i ) ); + const SvxNumberFormat& aTempFmt(aTmpNumRule.GetLevel( i )); + aNumFmt.SetPositionAndSpaceMode( aTempFmt.GetPositionAndSpaceMode() ); + if ( aTempFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION ) + { + aNumFmt.SetAbsLSpace( aTempFmt.GetAbsLSpace() ); + aNumFmt.SetCharTextDistance( aTempFmt.GetCharTextDistance() ); + aNumFmt.SetFirstLineOffset( aTempFmt.GetFirstLineOffset() ); + } + else if ( aTempFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT ) + { + aNumFmt.SetNumAdjust( aTempFmt.GetNumAdjust() ); + aNumFmt.SetLabelFollowedBy( aTempFmt.GetLabelFollowedBy() ); + aNumFmt.SetListtabPos( aTempFmt.GetListtabPos() ); + aNumFmt.SetFirstLineIndent( aTempFmt.GetFirstLineIndent() ); + aNumFmt.SetIndentAt( aTempFmt.GetIndentAt() ); + } + + pActNum->SetLevel( i, aNumFmt ); + } + nMask <<= 1; + } + + InitControls(); + SetModified(); +} + +void SvxNumPositionTabPage::SetModified() +{ + bModified = true; + m_aPreviewWIN.SetLevel(nActNumLvl); + m_aPreviewWIN.Invalidate(); +} + +void SvxNumOptionsTabPage::SetModified(bool bRepaint) +{ + bModified = true; + if (bRepaint) + { + m_aPreviewWIN.SetLevel(nActNumLvl); + m_aPreviewWIN.Invalidate(); + } +} + +void SvxNumOptionsTabPage::PageCreated(const SfxAllItemSet& aSet) +{ + const SfxStringListItem* pListItem = aSet.GetItem(SID_CHAR_FMT_LIST_BOX, false); + const SfxStringItem* pNumCharFmt = aSet.GetItem(SID_NUM_CHAR_FMT, false); + const SfxStringItem* pBulletCharFmt = aSet.GetItem(SID_BULLET_CHAR_FMT, false); + const SfxUInt16Item* pMetricItem = aSet.GetItem(SID_METRIC_ITEM, false); + + if (pNumCharFmt &&pBulletCharFmt) + SetCharFmts( pNumCharFmt->GetValue(),pBulletCharFmt->GetValue()); + + if (pListItem) + { + const std::vector &aList = pListItem->GetList(); + sal_uInt32 nCount = aList.size(); + for(sal_uInt32 i = 0; i < nCount; i++) + m_xCharFmtLB->append_text(aList[i]); + } + if (pMetricItem) + SetMetric(static_cast(pMetricItem->GetValue())); +} + +void SvxNumPositionTabPage::PageCreated(const SfxAllItemSet& aSet) +{ + const SfxUInt16Item* pMetricItem = aSet.GetItem(SID_METRIC_ITEM, false); + + if (pMetricItem) + SetMetric(static_cast(pMetricItem->GetValue())); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/page.cxx b/cui/source/tabpages/page.cxx new file mode 100644 index 000000000..1b5fc2851 --- /dev/null +++ b/cui/source/tabpages/page.cxx @@ -0,0 +1,1554 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// static ---------------------------------------------------------------- + +// #i19922# - tdf#126051 see svx/source/dialog/hdft.cxx and sw/source/uibase/sidebar/PageMarginControl.hxx +static const long MINBODY = 56; // 1mm in twips rounded + +const sal_uInt16 SvxPageDescPage::pRanges[] = +{ + SID_ATTR_BORDER_OUTER, + SID_ATTR_BORDER_SHADOW, + SID_ATTR_LRSPACE, + SID_ATTR_PAGE_SHARED, + SID_SWREGISTER_COLLECTION, + SID_SWREGISTER_MODE, + 0 +}; +// ------- Mapping page layout ------------------------------------------ + +const SvxPageUsage aArr[] = +{ + SvxPageUsage::All, + SvxPageUsage::Mirror, + SvxPageUsage::Right, + SvxPageUsage::Left +}; + + +static sal_uInt16 PageUsageToPos_Impl( SvxPageUsage nUsage ) +{ + for ( size_t i = 0; i < SAL_N_ELEMENTS(aArr); ++i ) + if ( aArr[i] == nUsage ) + return i; + return 3; +} + + +static SvxPageUsage PosToPageUsage_Impl( sal_uInt16 nPos ) +{ + if ( nPos >= SAL_N_ELEMENTS(aArr) ) + return SvxPageUsage::NONE; + return aArr[nPos]; +} + + +static Size GetMinBorderSpace_Impl( const SvxShadowItem& rShadow, const SvxBoxItem& rBox ) +{ + Size aSz; + aSz.setHeight( rShadow.CalcShadowSpace( SvxShadowItemSide::BOTTOM ) + rBox.CalcLineSpace( SvxBoxItemLine::BOTTOM ) ); + aSz.AdjustHeight(rShadow.CalcShadowSpace( SvxShadowItemSide::TOP ) + rBox.CalcLineSpace( SvxBoxItemLine::TOP ) ); + aSz.setWidth( rShadow.CalcShadowSpace( SvxShadowItemSide::LEFT ) + rBox.CalcLineSpace( SvxBoxItemLine::LEFT ) ); + aSz.AdjustWidth(rShadow.CalcShadowSpace( SvxShadowItemSide::RIGHT ) + rBox.CalcLineSpace( SvxBoxItemLine::RIGHT ) ); + return aSz; +} + + +static long ConvertLong_Impl( const long nIn, MapUnit eUnit ) +{ + return OutputDevice::LogicToLogic( nIn, eUnit, MapUnit::MapTwip ); +} + +static bool IsEqualSize_Impl( const SvxSizeItem* pSize, const Size& rSize ) +{ + if ( pSize ) + { + Size aSize = pSize->GetSize(); + long nDiffW = std::abs( rSize.Width () - aSize.Width () ); + long nDiffH = std::abs( rSize.Height() - aSize.Height() ); + return ( nDiffW < 10 && nDiffH < 10 ); + } + else + return false; +} + + +#define MARGIN_LEFT ( MarginPosition(0x0001) ) +#define MARGIN_RIGHT ( MarginPosition(0x0002) ) +#define MARGIN_TOP ( MarginPosition(0x0004) ) +#define MARGIN_BOTTOM ( MarginPosition(0x0008) ) + +// class SvxPageDescPage -------------------------------------------------- + +std::unique_ptr SvxPageDescPage::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet ) +{ + return std::make_unique(pPage, pController, *rSet); +} + +SvxPageDescPage::SvxPageDescPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rAttr) + : SfxTabPage(pPage, pController, "cui/ui/pageformatpage.ui", "PageFormatPage", &rAttr) + , bLandscape(false) + , eMode(SVX_PAGE_MODE_STANDARD) + , ePaperStart(PAPER_A3) + , m_nPos(0) + , mpDefPrinter(nullptr) + , mbDelPrinter(false) + , mbEnableDrawingLayerFillStyles(false) + , m_xPaperSizeBox(new SvxPaperSizeListBox(m_xBuilder->weld_combo_box("comboPageFormat"))) + , m_xPaperWidthEdit(m_xBuilder->weld_metric_spin_button("spinWidth", FieldUnit::CM)) + , m_xPaperHeightEdit(m_xBuilder->weld_metric_spin_button("spinHeight", FieldUnit::CM)) + , m_xOrientationFT(m_xBuilder->weld_label("labelOrientation")) + , m_xPortraitBtn(m_xBuilder->weld_radio_button("radiobuttonPortrait")) + , m_xLandscapeBtn(m_xBuilder->weld_radio_button("radiobuttonLandscape")) + , m_xTextFlowLbl(m_xBuilder->weld_label("labelTextFlow")) + , m_xTextFlowBox(new svx::FrameDirectionListBox(m_xBuilder->weld_combo_box("comboTextFlowBox"))) + , m_xPaperTrayBox(m_xBuilder->weld_combo_box("comboPaperTray")) + , m_xLeftMarginLbl(m_xBuilder->weld_label("labelLeftMargin")) + , m_xLeftMarginEdit(m_xBuilder->weld_metric_spin_button("spinMargLeft", FieldUnit::CM)) + , m_xRightMarginLbl(m_xBuilder->weld_label("labelRightMargin")) + , m_xRightMarginEdit(m_xBuilder->weld_metric_spin_button("spinMargRight", FieldUnit::CM)) + , m_xTopMarginEdit(m_xBuilder->weld_metric_spin_button("spinMargTop", FieldUnit::CM)) + , m_xBottomMarginEdit(m_xBuilder->weld_metric_spin_button("spinMargBot", FieldUnit::CM)) + , m_xPageText(m_xBuilder->weld_label("labelPageLayout")) + , m_xLayoutBox(m_xBuilder->weld_combo_box("comboPageLayout")) + , m_xNumberFormatText(m_xBuilder->weld_label("labelPageNumbers")) + , m_xNumberFormatBox(new SvxPageNumberListBox(m_xBuilder->weld_combo_box("comboLayoutFormat"))) + , m_xTblAlignFT(m_xBuilder->weld_label("labelTblAlign")) + , m_xHorzBox(m_xBuilder->weld_check_button("checkbuttonHorz")) + , m_xVertBox(m_xBuilder->weld_check_button("checkbuttonVert")) + , m_xAdaptBox(m_xBuilder->weld_check_button("checkAdaptBox")) + , m_xRegisterCB(m_xBuilder->weld_check_button("checkRegisterTrue")) + , m_xRegisterFT(m_xBuilder->weld_label("labelRegisterStyle")) + , m_xRegisterLB(m_xBuilder->weld_combo_box("comboRegisterStyle")) + // Strings stored in UI + , m_xInsideLbl(m_xBuilder->weld_label("labelInner")) + , m_xOutsideLbl(m_xBuilder->weld_label("labelOuter")) + , m_xPrintRangeQueryText(m_xBuilder->weld_label("labelMsg")) + , m_xBspWin(new weld::CustomWeld(*m_xBuilder, "drawingareaPageDirection", m_aBspWin)) +{ + m_xRegisterLB->set_size_request(m_xRegisterLB->get_approximate_digit_width() * 20, -1); + + bBorderModified = false; + m_aBspWin.EnableRTL(false); + + // this page needs ExchangeSupport + SetExchangeSupport(); + + SvtLanguageOptions aLangOptions; + bool bCJK = aLangOptions.IsAsianTypographyEnabled(); + bool bCTL = aLangOptions.IsCTLFontEnabled(); + bool bWeb = false; + const SfxPoolItem* pItem; + + SfxObjectShell* pShell; + if(SfxItemState::SET == rAttr.GetItemState(SID_HTML_MODE, false, &pItem) || + ( nullptr != (pShell = SfxObjectShell::Current()) && + nullptr != (pItem = pShell->GetItem(SID_HTML_MODE)))) + bWeb = 0 != (static_cast(pItem)->GetValue() & HTMLMODE_ON); + + // fill text flow listbox with valid entries + + m_xTextFlowBox->append(SvxFrameDirection::Horizontal_LR_TB, SvxResId(RID_SVXSTR_PAGEDIR_LTR_HORI)); + + if (bCTL) + m_xTextFlowBox->append(SvxFrameDirection::Horizontal_RL_TB, SvxResId(RID_SVXSTR_PAGEDIR_RTL_HORI)); + + + // #109989# do not show vertical directions in Writer/Web + if( !bWeb && bCJK ) + { + m_xTextFlowBox->append(SvxFrameDirection::Vertical_RL_TB, SvxResId(RID_SVXSTR_PAGEDIR_RTL_VERT)); + m_xTextFlowBox->append(SvxFrameDirection::Vertical_LR_TB, SvxResId(RID_SVXSTR_PAGEDIR_LTR_VERT)); + } + + // #109989# show the text direction box in Writer/Web too + if( (bCJK || bCTL) && + SfxItemState::UNKNOWN < rAttr.GetItemState(GetWhich( SID_ATTR_FRAMEDIRECTION ))) + { + m_xTextFlowLbl->show(); + m_xTextFlowBox->show(); + m_xTextFlowBox->connect_changed(LINK(this, SvxPageDescPage, FrameDirectionModify_Impl)); + + m_aBspWin.EnableFrameDirection(true); + } + Init_Impl(); + + FieldUnit eFUnit = GetModuleFieldUnit( rAttr ); + SetFieldUnit( *m_xLeftMarginEdit, eFUnit ); + SetFieldUnit( *m_xRightMarginEdit, eFUnit ); + SetFieldUnit( *m_xTopMarginEdit, eFUnit ); + SetFieldUnit( *m_xBottomMarginEdit, eFUnit ); + SetFieldUnit( *m_xPaperWidthEdit, eFUnit ); + SetFieldUnit( *m_xPaperHeightEdit, eFUnit ); + + if ( SfxViewShell::Current() && SfxViewShell::Current()->GetPrinter() ) + { + mpDefPrinter = SfxViewShell::Current()->GetPrinter(); + } + else + { + mpDefPrinter = VclPtr::Create(); + mbDelPrinter = true; + } + + MapMode aOldMode = mpDefPrinter->GetMapMode(); + mpDefPrinter->SetMapMode(MapMode(MapUnit::MapTwip)); + + // set first- and last-values for the margins + Size aPaperSize = mpDefPrinter->GetPaperSize(); + Size aPrintSize = mpDefPrinter->GetOutputSize(); + + /* + * To convert a point ( 0,0 ) into logic coordinates + * looks like nonsense; but it makes sense when the + * coordinate system's origin has been moved. + */ + Point aPrintOffset = mpDefPrinter->GetPageOffset() - mpDefPrinter->PixelToLogic( Point() ); + mpDefPrinter->SetMapMode( aOldMode ); + + nFirstLeftMargin = m_xLeftMarginEdit->convert_value_from(m_xLeftMarginEdit->normalize(aPrintOffset.X()), FieldUnit::TWIP); + nFirstRightMargin = m_xRightMarginEdit->convert_value_from(m_xRightMarginEdit->normalize(aPaperSize.Width() - aPrintSize.Width() - aPrintOffset.X()), FieldUnit::TWIP); + nFirstTopMargin = m_xTopMarginEdit->convert_value_from(m_xTopMarginEdit->normalize(aPrintOffset.Y() ), FieldUnit::TWIP); + nFirstBottomMargin = m_xBottomMarginEdit->convert_value_from(m_xBottomMarginEdit->normalize(aPaperSize.Height() - aPrintSize.Height() - aPrintOffset.Y()), FieldUnit::TWIP ); + nLastLeftMargin = m_xLeftMarginEdit->convert_value_from(m_xLeftMarginEdit->normalize(aPrintOffset.X() + aPrintSize.Width()), FieldUnit::TWIP); + nLastRightMargin = m_xRightMarginEdit->convert_value_from(m_xRightMarginEdit->normalize(aPrintOffset.X() + aPrintSize.Width()), FieldUnit::TWIP); + nLastTopMargin = m_xTopMarginEdit->convert_value_from(m_xTopMarginEdit->normalize(aPrintOffset.Y() + aPrintSize.Height()), FieldUnit::TWIP); + nLastBottomMargin = m_xBottomMarginEdit->convert_value_from(m_xBottomMarginEdit->normalize(aPrintOffset.Y() + aPrintSize.Height()), FieldUnit::TWIP); + + // #i4219# get DrawingLayer options + const SvtOptionsDrawinglayer aDrawinglayerOpt; + + // #i4219# take Maximum now from configuration (1/100th cm) + // was: 11900 -> 119 cm ;new value 3 meters -> 300 cm -> 30000 + m_xPaperWidthEdit->set_max(m_xPaperWidthEdit->normalize(aDrawinglayerOpt.GetMaximumPaperWidth()), FieldUnit::CM); + m_xPaperHeightEdit->set_max(m_xPaperHeightEdit->normalize(aDrawinglayerOpt.GetMaximumPaperHeight()), FieldUnit::CM); + + // #i4219# also for margins (1/100th cm). Was: 9999, keeping. + m_xLeftMarginEdit->set_max(m_xLeftMarginEdit->normalize(aDrawinglayerOpt.GetMaximumPaperLeftMargin()), FieldUnit::MM); + m_xRightMarginEdit->set_max(m_xRightMarginEdit->normalize(aDrawinglayerOpt.GetMaximumPaperRightMargin()), FieldUnit::MM); + m_xTopMarginEdit->set_max(m_xTopMarginEdit->normalize(aDrawinglayerOpt.GetMaximumPaperTopMargin()), FieldUnit::MM); + m_xBottomMarginEdit->set_max(m_xBottomMarginEdit->normalize(aDrawinglayerOpt.GetMaximumPaperBottomMargin()), FieldUnit::MM); + + // Get the i18n framework numberings and add them to the listbox. + SvxNumOptionsTabPageHelper::GetI18nNumbering(m_xNumberFormatBox->get_widget(), std::numeric_limits::max()); +} + +SvxPageDescPage::~SvxPageDescPage() +{ + if(mbDelPrinter) + { + mpDefPrinter.disposeAndClear(); + mbDelPrinter = false; + } +} + +void SvxPageDescPage::Init_Impl() +{ + // adjust the handler + m_xLayoutBox->connect_changed(LINK(this, SvxPageDescPage, LayoutHdl_Impl)); + + m_xPaperSizeBox->connect_changed(LINK(this, SvxPageDescPage, PaperSizeSelect_Impl)); + m_xPaperWidthEdit->connect_value_changed( LINK(this, SvxPageDescPage, PaperSizeModify_Impl)); + m_xPaperHeightEdit->connect_value_changed(LINK(this, SvxPageDescPage, PaperSizeModify_Impl)); + m_xLandscapeBtn->connect_clicked(LINK(this, SvxPageDescPage, SwapOrientation_Impl)); + m_xPortraitBtn->connect_clicked(LINK(this, SvxPageDescPage, SwapOrientation_Impl)); + + Link aLink = LINK(this, SvxPageDescPage, BorderModify_Impl); + m_xLeftMarginEdit->connect_value_changed(aLink); + m_xRightMarginEdit->connect_value_changed(aLink); + m_xTopMarginEdit->connect_value_changed(aLink); + m_xBottomMarginEdit->connect_value_changed(aLink); + + m_xHorzBox->connect_toggled(LINK(this, SvxPageDescPage, CenterHdl_Impl)); + m_xVertBox->connect_toggled(LINK(this, SvxPageDescPage, CenterHdl_Impl)); +} + +void SvxPageDescPage::Reset( const SfxItemSet* rSet ) +{ + SfxItemPool* pPool = rSet->GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + MapUnit eUnit = pPool->GetMetric( GetWhich( SID_ATTR_LRSPACE ) ); + + // adjust margins (right/left) + const SfxPoolItem* pItem = GetItem( *rSet, SID_ATTR_LRSPACE ); + + if ( pItem ) + { + const SvxLRSpaceItem& rLRSpace = static_cast(*pItem); + SetMetricValue( *m_xLeftMarginEdit, rLRSpace.GetLeft(), eUnit ); + m_aBspWin.SetLeft( + static_cast(ConvertLong_Impl( rLRSpace.GetLeft(), eUnit )) ); + SetMetricValue( *m_xRightMarginEdit, rLRSpace.GetRight(), eUnit ); + m_aBspWin.SetRight( + static_cast(ConvertLong_Impl( rLRSpace.GetRight(), eUnit )) ); + } + + // adjust margins (top/bottom) + pItem = GetItem( *rSet, SID_ATTR_ULSPACE ); + + if ( pItem ) + { + const SvxULSpaceItem& rULSpace = static_cast(*pItem); + SetMetricValue( *m_xTopMarginEdit, rULSpace.GetUpper(), eUnit ); + m_aBspWin.SetTop( + static_cast(ConvertLong_Impl( static_cast(rULSpace.GetUpper()), eUnit )) ); + SetMetricValue( *m_xBottomMarginEdit, rULSpace.GetLower(), eUnit ); + m_aBspWin.SetBottom( + static_cast(ConvertLong_Impl( static_cast(rULSpace.GetLower()), eUnit )) ); + } + + // general page data + SvxNumType eNumType = SVX_NUM_ARABIC; + bLandscape = ( mpDefPrinter->GetOrientation() == Orientation::Landscape ); + SvxPageUsage nUse = SvxPageUsage::All; + pItem = GetItem( *rSet, SID_ATTR_PAGE ); + + if ( pItem ) + { + const SvxPageItem& rItem = static_cast(*pItem); + eNumType = rItem.GetNumType(); + nUse = rItem.GetPageUsage(); + bLandscape = rItem.IsLandscape(); + } + + // alignment + m_xLayoutBox->set_active(::PageUsageToPos_Impl(nUse)); + m_aBspWin.SetUsage( nUse ); + LayoutHdl_Impl( *m_xLayoutBox ); + + //adjust numeration type of the page style + m_xNumberFormatBox->set_active_id(eNumType); + + m_xPaperTrayBox->clear(); + sal_uInt8 nPaperBin = PAPERBIN_PRINTER_SETTINGS; + pItem = GetItem( *rSet, SID_ATTR_PAGE_PAPERBIN ); + + if ( pItem ) + { + nPaperBin = static_cast(pItem)->GetValue(); + + if ( nPaperBin >= mpDefPrinter->GetPaperBinCount() ) + nPaperBin = PAPERBIN_PRINTER_SETTINGS; + } + + OUString aBinName; + + if ( PAPERBIN_PRINTER_SETTINGS == nPaperBin ) + aBinName = EditResId(RID_SVXSTR_PAPERBIN_SETTINGS); + else + aBinName = mpDefPrinter->GetPaperBinName( static_cast(nPaperBin) ); + + m_xPaperTrayBox->append(OUString::number(nPaperBin), aBinName); + m_xPaperTrayBox->set_active_text(aBinName); + // reset focus handler to default first so know none already connected + m_xPaperTrayBox->connect_focus_in(Link()); + // update the list when widget gets focus + m_xPaperTrayBox->connect_focus_in(LINK(this, SvxPageDescPage, PaperBinHdl_Impl)); + + Size aPaperSize = SvxPaperInfo::GetPaperSize( mpDefPrinter ); + pItem = GetItem( *rSet, SID_ATTR_PAGE_SIZE ); + + if ( pItem ) + aPaperSize = static_cast(pItem)->GetSize(); + + bool bOrientationSupport = + mpDefPrinter->HasSupport( PrinterSupport::SetOrientation ); + + if ( !bOrientationSupport && + aPaperSize.Width() > aPaperSize.Height() ) + bLandscape = true; + + // tdf#130548 disable callbacks on the other of a pair of the radiogroup + // when toggling its partner + m_xLandscapeBtn->connect_clicked(Link()); + m_xPortraitBtn->connect_clicked(Link()); + + m_xLandscapeBtn->set_active(bLandscape); + m_xPortraitBtn->set_active(!bLandscape); + + m_xLandscapeBtn->connect_clicked(LINK(this, SvxPageDescPage, SwapOrientation_Impl)); + m_xPortraitBtn->connect_clicked(LINK(this, SvxPageDescPage, SwapOrientation_Impl)); + + m_aBspWin.SetSize( Size( ConvertLong_Impl( aPaperSize.Width(), eUnit ), + ConvertLong_Impl( aPaperSize.Height(), eUnit ) ) ); + + aPaperSize = OutputDevice::LogicToLogic(aPaperSize, MapMode(eUnit), MapMode(MapUnit::Map100thMM)); + if ( bLandscape ) + Swap( aPaperSize ); + + // Actual Paper Format + Paper ePaper = SvxPaperInfo::GetSvxPaper( aPaperSize, MapUnit::Map100thMM ); + + if ( PAPER_USER != ePaper ) + aPaperSize = SvxPaperInfo::GetPaperSize( ePaper, MapUnit::Map100thMM ); + + if ( bLandscape ) + Swap( aPaperSize ); + + // write values into the edits + SetMetricValue( *m_xPaperHeightEdit, aPaperSize.Height(), MapUnit::Map100thMM ); + SetMetricValue( *m_xPaperWidthEdit, aPaperSize.Width(), MapUnit::Map100thMM ); + m_xPaperSizeBox->clear(); + + m_xPaperSizeBox->FillPaperSizeEntries( ( ePaperStart == PAPER_A3 ) ? PaperSizeApp::Std : PaperSizeApp::Draw ); + m_xPaperSizeBox->set_active_id( ePaper ); + + // application specific + + switch ( eMode ) + { + case SVX_PAGE_MODE_CENTER: + { + m_xTblAlignFT->show(); + m_xHorzBox->show(); + m_xVertBox->show(); + DisableVerticalPageDir(); + + // horizontal alignment + pItem = GetItem( *rSet, SID_ATTR_PAGE_EXT1 ); + m_xHorzBox->set_active(pItem && static_cast(pItem)->GetValue()); + + // vertical alignment + pItem = GetItem( *rSet, SID_ATTR_PAGE_EXT2 ); + m_xVertBox->set_active(pItem && static_cast(pItem)->GetValue()); + + // set example window on the table + m_aBspWin.SetTable( true ); + m_aBspWin.SetHorz(m_xHorzBox->get_active()); + m_aBspWin.SetVert(m_xVertBox->get_active()); + + break; + } + + case SVX_PAGE_MODE_PRESENTATION: + { + DisableVerticalPageDir(); + m_xAdaptBox->show(); + pItem = GetItem( *rSet, SID_ATTR_PAGE_EXT1 ); + m_xAdaptBox->set_active( pItem && + static_cast(pItem)->GetValue() ); + + //!!! hidden, because not implemented by StarDraw + m_xLayoutBox->hide(); + m_xPageText->hide(); + + break; + } + default: ;//prevent warning + } + + + // display background and border in the example + ResetBackground_Impl( *rSet ); +//! UpdateExample_Impl(); + RangeHdl_Impl(); + + InitHeadFoot_Impl( *rSet ); + + bBorderModified = false; + SwapFirstValues_Impl( false ); + UpdateExample_Impl(); + + m_xLeftMarginEdit->save_value(); + m_xRightMarginEdit->save_value(); + m_xTopMarginEdit->save_value(); + m_xBottomMarginEdit->save_value(); + m_xLayoutBox->save_value(); + m_xNumberFormatBox->save_value(); + m_xPaperSizeBox->save_value(); + m_xPaperWidthEdit->save_value(); + m_xPaperHeightEdit->save_value(); + m_xPortraitBtn->save_state(); + m_xLandscapeBtn->save_state(); + m_xPaperTrayBox->save_value(); + m_xVertBox->save_state(); + m_xHorzBox->save_state(); + m_xAdaptBox->save_state(); + + CheckMarginEdits( true ); + + + if(SfxItemState::SET == rSet->GetItemState(SID_SWREGISTER_MODE)) + { + m_xRegisterCB->set_active(static_cast(rSet->Get( + SID_SWREGISTER_MODE)).GetValue()); + m_xRegisterCB->save_state(); + RegisterModify(*m_xRegisterCB); + } + if(SfxItemState::SET == rSet->GetItemState(SID_SWREGISTER_COLLECTION)) + { + m_xRegisterLB->set_active_text( + static_cast(rSet->Get(SID_SWREGISTER_COLLECTION)).GetValue()); + m_xRegisterLB->save_value(); + } + + SfxItemState eState = rSet->GetItemState( GetWhich( SID_ATTR_FRAMEDIRECTION ), + true, &pItem ); + if( SfxItemState::UNKNOWN != eState ) + { + SvxFrameDirection nVal = SfxItemState::SET == eState + ? static_cast(pItem)->GetValue() + : SvxFrameDirection::Horizontal_LR_TB; + m_xTextFlowBox->set_active_id(nVal); + + m_xTextFlowBox->save_value(); + m_aBspWin.SetFrameDirection(nVal); + } +} + +void SvxPageDescPage::FillUserData() +{ + if (SVX_PAGE_MODE_PRESENTATION == eMode) + SetUserData(m_xAdaptBox->get_active() ? OUString("1") : OUString("0")) ; + +} + +bool SvxPageDescPage::FillItemSet( SfxItemSet* rSet ) +{ + bool bModified = false; + const SfxItemSet& rOldSet = GetItemSet(); + SfxItemPool* pPool = rOldSet.GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + sal_uInt16 nWhich = GetWhich( SID_ATTR_LRSPACE ); + MapUnit eUnit = pPool->GetMetric( nWhich ); + const SfxPoolItem* pOld = nullptr; + + // copy old left and right margins + SvxLRSpaceItem aMargin( static_cast(rOldSet.Get( nWhich )) ); + + // copy old top and bottom margins + nWhich = GetWhich( SID_ATTR_ULSPACE ); + SvxULSpaceItem aTopMargin( static_cast(rOldSet.Get( nWhich )) ); + + if (m_xLeftMarginEdit->get_value_changed_from_saved()) + { + aMargin.SetLeft( static_cast(GetCoreValue( *m_xLeftMarginEdit, eUnit )) ); + bModified = true; + } + + if (m_xRightMarginEdit->get_value_changed_from_saved()) + { + aMargin.SetRight( static_cast(GetCoreValue( *m_xRightMarginEdit, eUnit )) ); + bModified = true; + } + + // set left and right margins + if (bModified) + { + pOld = GetOldItem( *rSet, SID_ATTR_LRSPACE ); + + if ( !pOld || *static_cast(pOld) != aMargin ) + rSet->Put( aMargin ); + else + bModified = false; + } + + bool bMod = false; + + if (m_xTopMarginEdit->get_value_changed_from_saved()) + { + aTopMargin.SetUpper( static_cast(GetCoreValue( *m_xTopMarginEdit, eUnit )) ); + bMod = true; + } + + if (m_xBottomMarginEdit->get_value_changed_from_saved()) + { + aTopMargin.SetLower( static_cast(GetCoreValue( *m_xBottomMarginEdit, eUnit )) ); + bMod = true; + } + + // set top and bottom margins + + if ( bMod ) + { + pOld = GetOldItem( *rSet, SID_ATTR_ULSPACE ); + + if ( !pOld || *static_cast(pOld) != aTopMargin ) + { + bModified = true; + rSet->Put( aTopMargin ); + } + } + + // paper tray + nWhich = GetWhich( SID_ATTR_PAGE_PAPERBIN ); + sal_Int32 nPos = m_xPaperTrayBox->get_active(); + sal_uInt16 nBin = m_xPaperTrayBox->get_id(nPos).toInt32(); + pOld = GetOldItem( *rSet, SID_ATTR_PAGE_PAPERBIN ); + + if ( !pOld || static_cast(pOld)->GetValue() != nBin ) + { + rSet->Put( SvxPaperBinItem( nWhich, static_cast(nBin) ) ); + bModified = true; + } + + Paper ePaper = m_xPaperSizeBox->get_active_id(); + bool bChecked = m_xLandscapeBtn->get_active(); + + if ( PAPER_USER == ePaper ) + { + if ( m_xPaperSizeBox->get_value_changed_from_saved() || + m_xPaperWidthEdit->get_value_changed_from_saved() || + m_xPaperHeightEdit->get_value_changed_from_saved() || + m_xLandscapeBtn->get_state_changed_from_saved() ) + { + Size aSize( GetCoreValue( *m_xPaperWidthEdit, eUnit ), + GetCoreValue( *m_xPaperHeightEdit, eUnit ) ); + pOld = GetOldItem( *rSet, SID_ATTR_PAGE_SIZE ); + + if ( !pOld || static_cast(pOld)->GetSize() != aSize ) + { + rSet->Put( SvxSizeItem( GetWhich(SID_ATTR_PAGE_SIZE), aSize ) ); + bModified = true; + } + } + } + else + { + if (m_xPaperSizeBox->get_value_changed_from_saved() || m_xLandscapeBtn->get_state_changed_from_saved()) + { + Size aSize( SvxPaperInfo::GetPaperSize( ePaper, eUnit ) ); + + if ( bChecked ) + Swap( aSize ); + + pOld = GetOldItem( *rSet, SID_ATTR_PAGE_SIZE ); + + if ( !pOld || static_cast(pOld)->GetSize() != aSize ) + { + rSet->Put( SvxSizeItem( GetWhich(SID_ATTR_PAGE_SIZE), aSize ) ); + bModified = true; + } + } + } + + nWhich = GetWhich( SID_ATTR_PAGE ); + SvxPageItem aPage( static_cast(rOldSet.Get( nWhich )) ); + bMod = m_xLayoutBox->get_value_changed_from_saved(); + + if ( bMod ) + aPage.SetPageUsage(::PosToPageUsage_Impl(m_xLayoutBox->get_active())); + + if (m_xLandscapeBtn->get_state_changed_from_saved()) + { + aPage.SetLandscape(bChecked); + bMod = true; + } + + //Get the NumType value + if (m_xNumberFormatBox->get_value_changed_from_saved()) + { + SvxNumType nEntryData = m_xNumberFormatBox->get_active_id(); + aPage.SetNumType( nEntryData ); + bMod = true; + } + + if ( bMod ) + { + pOld = GetOldItem( *rSet, SID_ATTR_PAGE ); + + if ( !pOld || *static_cast(pOld) != aPage ) + { + rSet->Put( aPage ); + bModified = true; + } + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich ) ) + rSet->ClearItem( nWhich ); + else + rSet->Put( rOldSet.Get( nWhich ) ); + + // evaluate mode specific controls + + switch ( eMode ) + { + case SVX_PAGE_MODE_CENTER: + { + if (m_xHorzBox->get_state_changed_from_saved()) + { + SfxBoolItem aHorz( GetWhich( SID_ATTR_PAGE_EXT1 ), + m_xHorzBox->get_active() ); + rSet->Put( aHorz ); + bModified = true; + } + + if (m_xVertBox->get_state_changed_from_saved()) + { + SfxBoolItem aVert( GetWhich( SID_ATTR_PAGE_EXT2 ), + m_xVertBox->get_active() ); + rSet->Put( aVert ); + bModified = true; + } + break; + } + + case SVX_PAGE_MODE_PRESENTATION: + { + // always put so that draw can evaluate this + rSet->Put( SfxBoolItem( GetWhich( SID_ATTR_PAGE_EXT1 ), + m_xAdaptBox->get_active() ) ); + bModified = true; + break; + } + default: ;//prevent warning + + } + + if (m_xRegisterCB->get_visible() && + (m_xRegisterCB->get_active() || m_xRegisterCB->get_state_changed_from_saved())) + { + const SfxBoolItem& rRegItem = static_cast(rOldSet.Get(SID_SWREGISTER_MODE)); + std::unique_ptr pRegItem(rRegItem.Clone()); + bool bCheck = m_xRegisterCB->get_active(); + pRegItem->SetValue(bCheck); + rSet->Put(std::move(pRegItem)); + bModified = true; + if(bCheck) + { + bModified = true; + rSet->Put(SfxStringItem(SID_SWREGISTER_COLLECTION, + m_xRegisterLB->get_active_text())); + } + } + + if (m_xTextFlowBox->get_visible() && m_xTextFlowBox->get_value_changed_from_saved()) + { + SvxFrameDirection eDirection = m_xTextFlowBox->get_active_id(); + rSet->Put( SvxFrameDirectionItem( eDirection, GetWhich( SID_ATTR_FRAMEDIRECTION ) ) ); + bModified = true; + } + + return bModified; +} + +IMPL_LINK_NOARG(SvxPageDescPage, LayoutHdl_Impl, weld::ComboBox&, void) +{ + // switch inside outside + const SvxPageUsage nUsage = PosToPageUsage_Impl(m_xLayoutBox->get_active()); + + if (nUsage == SvxPageUsage::Mirror) + { + m_xLeftMarginLbl->hide(); + m_xRightMarginLbl->hide(); + m_xInsideLbl->show(); + m_xOutsideLbl->show(); + } + else + { + m_xLeftMarginLbl->show(); + m_xRightMarginLbl->show(); + m_xInsideLbl->hide(); + m_xOutsideLbl->hide(); + } + UpdateExample_Impl( true ); +} + +IMPL_LINK_NOARG(SvxPageDescPage, PaperBinHdl_Impl, weld::Widget&, void) +{ + // tdf#124226 disconnect so not called again, unless Reset occurs + m_xPaperTrayBox->connect_focus_in(Link()); + + OUString aOldName = m_xPaperTrayBox->get_active_text(); + m_xPaperTrayBox->freeze(); + m_xPaperTrayBox->clear(); + m_xPaperTrayBox->append(OUString::number(PAPERBIN_PRINTER_SETTINGS), EditResId(RID_SVXSTR_PAPERBIN_SETTINGS)); + OUString aPaperBin(EditResId(RID_SVXSTR_PAPERBIN)); + const sal_uInt16 nBinCount = mpDefPrinter->GetPaperBinCount(); + + for (sal_uInt16 i = 0; i < nBinCount; ++i) + { + OUString aName = mpDefPrinter->GetPaperBinName(i); + if (aName.isEmpty()) + { + aName = aPaperBin + " " + OUString::number( i+1 ); + } + m_xPaperTrayBox->append(OUString::number(i), aName); + } + m_xPaperTrayBox->set_active_text(aOldName); + m_xPaperTrayBox->thaw(); + + // tdf#123650 explicitly grab-focus after the modification otherwise gtk loses track + // of there the focus should be + m_xPaperTrayBox->grab_focus(); +} + +IMPL_LINK_NOARG(SvxPageDescPage, PaperSizeSelect_Impl, weld::ComboBox&, void) +{ + Paper ePaper = m_xPaperSizeBox->get_active_id(); + + if ( ePaper == PAPER_USER ) + return; + + Size aSize( SvxPaperInfo::GetPaperSize( ePaper, MapUnit::Map100thMM ) ); + + if (m_xLandscapeBtn->get_active()) + Swap( aSize ); + + if ( aSize.Height() < m_xPaperHeightEdit->get_min( FieldUnit::MM_100TH ) ) + m_xPaperHeightEdit->set_min( + m_xPaperHeightEdit->normalize( aSize.Height() ), FieldUnit::MM_100TH ); + if ( aSize.Width() < m_xPaperWidthEdit->get_min( FieldUnit::MM_100TH ) ) + m_xPaperWidthEdit->set_min( + m_xPaperWidthEdit->normalize( aSize.Width() ), FieldUnit::MM_100TH ); + SetMetricValue( *m_xPaperHeightEdit, aSize.Height(), MapUnit::Map100thMM ); + SetMetricValue( *m_xPaperWidthEdit, aSize.Width(), MapUnit::Map100thMM ); + + CalcMargin_Impl(); + + RangeHdl_Impl(); + UpdateExample_Impl( true ); + + if ( eMode != SVX_PAGE_MODE_PRESENTATION ) + return; + + // Draw: if paper format the margin shall be 1 cm + long nTmp = 0; + bool bScreen = (( PAPER_SCREEN_4_3 == ePaper )||( PAPER_SCREEN_16_9 == ePaper)||( PAPER_SCREEN_16_10 == ePaper)); + + if ( !bScreen ) + // no margin if screen + nTmp = 1; // accordingly 1 cm + + if ( bScreen || m_xRightMarginEdit->get_value(FieldUnit::NONE) == 0 ) + SetMetricValue( *m_xRightMarginEdit, nTmp, MapUnit::MapCM ); + if ( bScreen || m_xLeftMarginEdit->get_value(FieldUnit::NONE) == 0 ) + SetMetricValue( *m_xLeftMarginEdit, nTmp, MapUnit::MapCM ); + if ( bScreen || m_xBottomMarginEdit->get_value(FieldUnit::NONE) == 0 ) + SetMetricValue( *m_xBottomMarginEdit, nTmp, MapUnit::MapCM ); + if ( bScreen || m_xTopMarginEdit->get_value(FieldUnit::NONE) == 0 ) + SetMetricValue( *m_xTopMarginEdit, nTmp, MapUnit::MapCM ); + UpdateExample_Impl( true ); +} + +IMPL_LINK_NOARG(SvxPageDescPage, PaperSizeModify_Impl, weld::MetricSpinButton&, void) +{ + sal_uInt16 nWhich = GetWhich( SID_ATTR_LRSPACE ); + MapUnit eUnit = GetItemSet().GetPool()->GetMetric( nWhich ); + Size aSize( GetCoreValue( *m_xPaperWidthEdit, eUnit ), + GetCoreValue( *m_xPaperHeightEdit, eUnit ) ); + + if ( aSize.Width() > aSize.Height() ) + { + m_xLandscapeBtn->set_active(true); + bLandscape = true; + } + else + { + m_xPortraitBtn->set_active(true); + bLandscape = false; + } + + Paper ePaper = SvxPaperInfo::GetSvxPaper( aSize, eUnit ); + m_xPaperSizeBox->set_active_id( ePaper ); + UpdateExample_Impl( true ); + + RangeHdl_Impl(); +} + +IMPL_LINK(SvxPageDescPage, SwapOrientation_Impl, weld::Button&, rBtn, void) +{ + if ( + !((!bLandscape && &rBtn == m_xLandscapeBtn.get()) || + (bLandscape && &rBtn == m_xPortraitBtn.get())) + ) + return; + + bLandscape = m_xLandscapeBtn->get_active(); + + const long lWidth = GetCoreValue( *m_xPaperWidthEdit, MapUnit::Map100thMM ); + const long lHeight = GetCoreValue( *m_xPaperHeightEdit, MapUnit::Map100thMM ); + + // swap width and height + SetMetricValue(*m_xPaperWidthEdit, lHeight, MapUnit::Map100thMM); + SetMetricValue(*m_xPaperHeightEdit, lWidth, MapUnit::Map100thMM); + + // recalculate margins if necessary + CalcMargin_Impl(); + + PaperSizeSelect_Impl(m_xPaperSizeBox->get_widget()); + RangeHdl_Impl(); + SwapFirstValues_Impl(bBorderModified); + UpdateExample_Impl(true); +} + +void SvxPageDescPage::SwapFirstValues_Impl( bool bSet ) +{ + MapMode aOldMode = mpDefPrinter->GetMapMode(); + Orientation eOri = Orientation::Portrait; + + if ( bLandscape ) + eOri = Orientation::Landscape; + Orientation eOldOri = mpDefPrinter->GetOrientation(); + mpDefPrinter->SetOrientation( eOri ); + mpDefPrinter->SetMapMode(MapMode(MapUnit::MapTwip)); + + // set first- and last-values for margins + Size aPaperSize = mpDefPrinter->GetPaperSize(); + Size aPrintSize = mpDefPrinter->GetOutputSize(); + /* + * To convert a point ( 0,0 ) into logic coordinates + * looks like nonsense; but it makes sense if the + * coordinate system's origin has been moved. + */ + Point aPrintOffset = mpDefPrinter->GetPageOffset() - mpDefPrinter->PixelToLogic( Point() ); + mpDefPrinter->SetMapMode( aOldMode ); + mpDefPrinter->SetOrientation( eOldOri ); + + sal_Int64 nSetL = m_xLeftMarginEdit->denormalize( + m_xLeftMarginEdit->get_value( FieldUnit::TWIP ) ); + sal_Int64 nSetR = m_xRightMarginEdit->denormalize( + m_xRightMarginEdit->get_value( FieldUnit::TWIP ) ); + sal_Int64 nSetT = m_xTopMarginEdit->denormalize( + m_xTopMarginEdit->get_value( FieldUnit::TWIP ) ); + sal_Int64 nSetB = m_xBottomMarginEdit->denormalize( + m_xBottomMarginEdit->get_value( FieldUnit::TWIP ) ); + + long nNewL = aPrintOffset.X(); + long nNewR = aPaperSize.Width() - aPrintSize.Width() - aPrintOffset.X(); + long nNewT = aPrintOffset.Y(); + long nNewB = aPaperSize.Height() - aPrintSize.Height() - aPrintOffset.Y(); + + nFirstLeftMargin = m_xLeftMarginEdit->convert_value_from(m_xLeftMarginEdit->normalize(nNewL), FieldUnit::TWIP); + nFirstRightMargin = m_xRightMarginEdit->convert_value_from(m_xRightMarginEdit->normalize(nNewR), FieldUnit::TWIP); + nFirstTopMargin = m_xTopMarginEdit->convert_value_from(m_xTopMarginEdit->normalize(nNewT), FieldUnit::TWIP); + nFirstBottomMargin = m_xBottomMarginEdit->convert_value_from(m_xBottomMarginEdit->normalize(nNewB), FieldUnit::TWIP); + + if ( !bSet ) + return; + + if ( nSetL < nNewL ) + m_xLeftMarginEdit->set_value( m_xLeftMarginEdit->normalize( nNewL ), + FieldUnit::TWIP ); + if ( nSetR < nNewR ) + m_xRightMarginEdit->set_value( m_xRightMarginEdit->normalize( nNewR ), + FieldUnit::TWIP ); + if ( nSetT < nNewT ) + m_xTopMarginEdit->set_value( m_xTopMarginEdit->normalize( nNewT ), + FieldUnit::TWIP ); + if ( nSetB < nNewB ) + m_xBottomMarginEdit->set_value( m_xBottomMarginEdit->normalize( nNewB ), + FieldUnit::TWIP ); +} + +IMPL_LINK_NOARG(SvxPageDescPage, BorderModify_Impl, weld::MetricSpinButton&, void) +{ + if ( !bBorderModified ) + bBorderModified = true; + UpdateExample_Impl(); + + RangeHdl_Impl(); +} + +void SvxPageDescPage::UpdateExample_Impl( bool bResetbackground ) +{ + // Size + Size aSize( GetCoreValue( *m_xPaperWidthEdit, MapUnit::MapTwip ), + GetCoreValue( *m_xPaperHeightEdit, MapUnit::MapTwip ) ); + + m_aBspWin.SetSize( aSize ); + + // Margins + m_aBspWin.SetTop( GetCoreValue( *m_xTopMarginEdit, MapUnit::MapTwip ) ); + m_aBspWin.SetBottom( GetCoreValue( *m_xBottomMarginEdit, MapUnit::MapTwip ) ); + m_aBspWin.SetLeft( GetCoreValue( *m_xLeftMarginEdit, MapUnit::MapTwip ) ); + m_aBspWin.SetRight( GetCoreValue( *m_xRightMarginEdit, MapUnit::MapTwip ) ); + + // Layout + m_aBspWin.SetUsage(PosToPageUsage_Impl(m_xLayoutBox->get_active())); + if ( bResetbackground ) + m_aBspWin.ResetBackground(); + m_aBspWin.Invalidate(); +} + + +void SvxPageDescPage::ResetBackground_Impl(const SfxItemSet& rSet) +{ + sal_uInt16 nWhich(GetWhich(SID_ATTR_PAGE_HEADERSET)); + + if (SfxItemState::SET == rSet.GetItemState(nWhich, false)) + { + const SvxSetItem& rSetItem = static_cast< const SvxSetItem& >(rSet.Get(nWhich, false)); + const SfxItemSet& rTmpSet = rSetItem.GetItemSet(); + const SfxBoolItem& rOn = static_cast< const SfxBoolItem& >(rTmpSet.Get(GetWhich(SID_ATTR_PAGE_ON))); + + if(rOn.GetValue()) + { + drawinglayer::attribute::SdrAllFillAttributesHelperPtr aHeaderFillAttributes; + + if(mbEnableDrawingLayerFillStyles) + { + // create FillAttributes directly from DrawingLayer FillStyle entries + aHeaderFillAttributes = std::make_shared(rTmpSet); + } + else + { + nWhich = GetWhich(SID_ATTR_BRUSH); + + if(SfxItemState::SET == rTmpSet.GetItemState(nWhich)) + { + // create FillAttributes from SvxBrushItem + const SvxBrushItem& rItem = static_cast< const SvxBrushItem& >(rTmpSet.Get(nWhich)); + SfxItemSet aTempSet(*rTmpSet.GetPool(), svl::Items{}); + + setSvxBrushItemAsFillAttributesToTargetSet(rItem, aTempSet); + aHeaderFillAttributes = std::make_shared(aTempSet); + } + } + + m_aBspWin.setHeaderFillAttributes(aHeaderFillAttributes); + } + } + + nWhich = GetWhich(SID_ATTR_PAGE_FOOTERSET); + + if (SfxItemState::SET == rSet.GetItemState(nWhich, false)) + { + const SvxSetItem& rSetItem = static_cast< const SvxSetItem& >(rSet.Get(nWhich,false)); + const SfxItemSet& rTmpSet = rSetItem.GetItemSet(); + const SfxBoolItem& rOn = static_cast< const SfxBoolItem& >(rTmpSet.Get(GetWhich(SID_ATTR_PAGE_ON))); + + if(rOn.GetValue()) + { + drawinglayer::attribute::SdrAllFillAttributesHelperPtr aFooterFillAttributes; + + if(mbEnableDrawingLayerFillStyles) + { + // create FillAttributes directly from DrawingLayer FillStyle entries + aFooterFillAttributes = std::make_shared(rTmpSet); + } + else + { + nWhich = GetWhich(SID_ATTR_BRUSH); + + if(SfxItemState::SET == rTmpSet.GetItemState(nWhich)) + { + // create FillAttributes from SvxBrushItem + const SvxBrushItem& rItem = static_cast< const SvxBrushItem& >(rTmpSet.Get(nWhich)); + SfxItemSet aTempSet(*rTmpSet.GetPool(), svl::Items{}); + + setSvxBrushItemAsFillAttributesToTargetSet(rItem, aTempSet); + aFooterFillAttributes = std::make_shared(aTempSet); + } + } + + m_aBspWin.setFooterFillAttributes(aFooterFillAttributes); + } + } + + drawinglayer::attribute::SdrAllFillAttributesHelperPtr aPageFillAttributes; + const SfxPoolItem* pItem = nullptr; + + if(mbEnableDrawingLayerFillStyles) + { + // create FillAttributes directly from DrawingLayer FillStyle entries + aPageFillAttributes = std::make_shared(rSet); + } + else + { + pItem = GetItem(rSet, SID_ATTR_BRUSH); + + if(pItem) + { + // create FillAttributes from SvxBrushItem + const SvxBrushItem& rItem = static_cast< const SvxBrushItem& >(*pItem); + SfxItemSet aTempSet(*rSet.GetPool(), svl::Items{}); + + setSvxBrushItemAsFillAttributesToTargetSet(rItem, aTempSet); + aPageFillAttributes = std::make_shared(aTempSet); + } + } + + m_aBspWin.setPageFillAttributes(aPageFillAttributes); +} + +void SvxPageDescPage::InitHeadFoot_Impl( const SfxItemSet& rSet ) +{ + bLandscape = m_xLandscapeBtn->get_active(); + const SfxPoolItem* pItem = GetItem( rSet, SID_ATTR_PAGE_SIZE ); + + if ( pItem ) + m_aBspWin.SetSize( static_cast(pItem)->GetSize() ); + + const SvxSetItem* pSetItem = nullptr; + + // evaluate header attributes + + if ( SfxItemState::SET == + rSet.GetItemState( GetWhich( SID_ATTR_PAGE_HEADERSET ), + false, reinterpret_cast(&pSetItem) ) ) + { + const SfxItemSet& rHeaderSet = pSetItem->GetItemSet(); + const SfxBoolItem& rHeaderOn = + static_cast(rHeaderSet.Get( GetWhich( SID_ATTR_PAGE_ON ) )); + + if ( rHeaderOn.GetValue() ) + { + const SvxSizeItem& rSize = static_cast( + rHeaderSet.Get( GetWhich( SID_ATTR_PAGE_SIZE ) )); + const SvxULSpaceItem& rUL = static_cast( + rHeaderSet.Get( GetWhich( SID_ATTR_ULSPACE ) )); + long nDist = rUL.GetLower(); + m_aBspWin.SetHdHeight( rSize.GetSize().Height() - nDist ); + m_aBspWin.SetHdDist( nDist ); + const SvxLRSpaceItem& rLR = static_cast( + rHeaderSet.Get( GetWhich( SID_ATTR_LRSPACE ) )); + m_aBspWin.SetHdLeft( rLR.GetLeft() ); + m_aBspWin.SetHdRight( rLR.GetRight() ); + m_aBspWin.SetHeader( true ); + } + else + m_aBspWin.SetHeader( false ); + + // show background and border in the example + drawinglayer::attribute::SdrAllFillAttributesHelperPtr aHeaderFillAttributes; + + if(mbEnableDrawingLayerFillStyles) + { + // create FillAttributes directly from DrawingLayer FillStyle entries + aHeaderFillAttributes = std::make_shared(rHeaderSet); + } + else + { + const sal_uInt16 nWhich(GetWhich(SID_ATTR_BRUSH)); + + if(rHeaderSet.GetItemState(nWhich) >= SfxItemState::DEFAULT) + { + // aBspWin.SetHdColor(rItem.GetColor()); + const SvxBrushItem& rItem = static_cast< const SvxBrushItem& >(rHeaderSet.Get(nWhich)); + SfxItemSet aTempSet(*rHeaderSet.GetPool(), svl::Items{}); + + setSvxBrushItemAsFillAttributesToTargetSet(rItem, aTempSet); + aHeaderFillAttributes = std::make_shared(aTempSet); + } + } + + m_aBspWin.setHeaderFillAttributes(aHeaderFillAttributes); + } + + // evaluate footer attributes + + if ( SfxItemState::SET != + rSet.GetItemState( GetWhich( SID_ATTR_PAGE_FOOTERSET ), + false, reinterpret_cast(&pSetItem) ) ) + return; + + const SfxItemSet& rFooterSet = pSetItem->GetItemSet(); + const SfxBoolItem& rFooterOn = + static_cast(rFooterSet.Get( GetWhich( SID_ATTR_PAGE_ON ) )); + + if ( rFooterOn.GetValue() ) + { + const SvxSizeItem& rSize = static_cast( + rFooterSet.Get( GetWhich( SID_ATTR_PAGE_SIZE ) )); + const SvxULSpaceItem& rUL = static_cast( + rFooterSet.Get( GetWhich( SID_ATTR_ULSPACE ) )); + long nDist = rUL.GetUpper(); + m_aBspWin.SetFtHeight( rSize.GetSize().Height() - nDist ); + m_aBspWin.SetFtDist( nDist ); + const SvxLRSpaceItem& rLR = static_cast( + rFooterSet.Get( GetWhich( SID_ATTR_LRSPACE ) )); + m_aBspWin.SetFtLeft( rLR.GetLeft() ); + m_aBspWin.SetFtRight( rLR.GetRight() ); + m_aBspWin.SetFooter( true ); + } + else + m_aBspWin.SetFooter( false ); + + // show background and border in the example + drawinglayer::attribute::SdrAllFillAttributesHelperPtr aFooterFillAttributes; + + if(mbEnableDrawingLayerFillStyles) + { + // create FillAttributes directly from DrawingLayer FillStyle entries + aFooterFillAttributes = std::make_shared(rFooterSet); + } + else + { + const sal_uInt16 nWhich(GetWhich(SID_ATTR_BRUSH)); + + if(rFooterSet.GetItemState(nWhich) >= SfxItemState::DEFAULT) + { + // aBspWin.SetFtColor(rItem.GetColor()); + const SvxBrushItem& rItem = static_cast(rFooterSet.Get(nWhich)); + SfxItemSet aTempSet(*rFooterSet.GetPool(), svl::Items{}); + + setSvxBrushItemAsFillAttributesToTargetSet(rItem, aTempSet); + aFooterFillAttributes = std::make_shared(aTempSet); + } + } + + m_aBspWin.setFooterFillAttributes(aFooterFillAttributes); +} + +void SvxPageDescPage::ActivatePage( const SfxItemSet& rSet ) +{ + InitHeadFoot_Impl( rSet ); + UpdateExample_Impl(); + ResetBackground_Impl( rSet ); + RangeHdl_Impl(); +} + +DeactivateRC SvxPageDescPage::DeactivatePage( SfxItemSet* _pSet ) +{ + // Inquiry whether the page margins are beyond the printing area. + // If not, ask user whether they shall be taken. + // If not, stay on the TabPage. + Paper ePaper = m_xPaperSizeBox->get_active_id(); + + if ( ePaper != PAPER_SCREEN_4_3 && ePaper != PAPER_SCREEN_16_9 && ePaper != PAPER_SCREEN_16_10 && IsMarginOutOfRange() ) + { + std::unique_ptr xQueryBox(Application::CreateMessageDialog(GetFrameWeld(), + VclMessageType::Question, VclButtonsType::YesNo, + m_xPrintRangeQueryText->get_label())); + xQueryBox->set_default_response(RET_NO); + if (xQueryBox->run() == RET_NO) + { + weld::MetricSpinButton* pField = nullptr; + if ( IsPrinterRangeOverflow( *m_xLeftMarginEdit, nFirstLeftMargin, nLastLeftMargin, MARGIN_LEFT ) ) + pField = m_xLeftMarginEdit.get(); + if ( IsPrinterRangeOverflow( *m_xRightMarginEdit, nFirstRightMargin, nLastRightMargin, MARGIN_RIGHT ) + && !pField ) + pField = m_xRightMarginEdit.get(); + if ( IsPrinterRangeOverflow( *m_xTopMarginEdit, nFirstTopMargin, nLastTopMargin, MARGIN_TOP ) + && !pField ) + pField = m_xTopMarginEdit.get(); + if ( IsPrinterRangeOverflow( *m_xBottomMarginEdit, nFirstBottomMargin, nLastBottomMargin, MARGIN_BOTTOM ) + && !pField ) + pField = m_xBottomMarginEdit.get(); + if ( pField ) + pField->grab_focus(); + UpdateExample_Impl(); + return DeactivateRC::KeepPage; + } + else + CheckMarginEdits( false ); + } + + if ( _pSet ) + { + FillItemSet( _pSet ); + + // put portray/landscape if applicable + sal_uInt16 nWh = GetWhich( SID_ATTR_PAGE_SIZE ); + MapUnit eUnit = GetItemSet().GetPool()->GetMetric( nWh ); + Size aSize( GetCoreValue( *m_xPaperWidthEdit, eUnit ), + GetCoreValue( *m_xPaperHeightEdit, eUnit ) ); + + // put, if current size is different to the value in _pSet + const SvxSizeItem* pSize = GetItem( *_pSet, SID_ATTR_PAGE_SIZE ); + if ( aSize.Width() && ( !pSize || !IsEqualSize_Impl( pSize, aSize ) ) ) + _pSet->Put( SvxSizeItem( nWh, aSize ) ); + } + + return DeactivateRC::LeavePage; +} + +void SvxPageDescPage::RangeHdl_Impl() +{ + // example window + long nHHeight = m_aBspWin.GetHdHeight(); + long nHDist = m_aBspWin.GetHdDist(); + + long nFHeight = m_aBspWin.GetFtHeight(); + long nFDist = m_aBspWin.GetFtDist(); + + long nHFLeft = std::max(m_aBspWin.GetHdLeft(), m_aBspWin.GetFtLeft()); + long nHFRight = std::max(m_aBspWin.GetHdRight(), m_aBspWin.GetFtRight()); + + // current values for page margins + long nBT = static_cast(m_xTopMarginEdit->denormalize(m_xTopMarginEdit->get_value(FieldUnit::TWIP))); + long nBB = static_cast(m_xBottomMarginEdit->denormalize(m_xBottomMarginEdit->get_value(FieldUnit::TWIP))); + long nBL = static_cast(m_xLeftMarginEdit->denormalize(m_xLeftMarginEdit->get_value(FieldUnit::TWIP))); + long nBR = static_cast(m_xRightMarginEdit->denormalize(m_xRightMarginEdit->get_value(FieldUnit::TWIP))); + + // calculate width of page border + const SfxItemSet* _pSet = &GetItemSet(); + Size aBorder; + + if ( _pSet->GetItemState( GetWhich(SID_ATTR_BORDER_SHADOW) ) >= + SfxItemState::DEFAULT && + _pSet->GetItemState( GetWhich(SID_ATTR_BORDER_OUTER) ) >= + SfxItemState::DEFAULT ) + { + aBorder = GetMinBorderSpace_Impl( + static_cast(_pSet->Get(GetWhich(SID_ATTR_BORDER_SHADOW))), + static_cast(_pSet->Get(GetWhich(SID_ATTR_BORDER_OUTER)))); + } + + // limits paper + // maximum is 54 cm + + long nMin = nHHeight + nHDist + nFDist + nFHeight + nBT + nBB + + MINBODY + aBorder.Height(); + m_xPaperHeightEdit->set_min(m_xPaperHeightEdit->normalize(nMin), FieldUnit::TWIP); + + nMin = MINBODY + nBL + nBR + aBorder.Width(); + m_xPaperWidthEdit->set_min(m_xPaperWidthEdit->normalize(nMin), FieldUnit::TWIP); + + long nH = static_cast(m_xPaperHeightEdit->denormalize(m_xPaperHeightEdit->get_value(FieldUnit::TWIP))); + long nW = static_cast(m_xPaperWidthEdit->denormalize(m_xPaperWidthEdit->get_value(FieldUnit::TWIP))); + + // Top + long nMax = nH - nBB - aBorder.Height() - MINBODY - + nFDist - nFHeight - nHDist - nHHeight; + + m_xTopMarginEdit->set_max(m_xTopMarginEdit->normalize(nMax), FieldUnit::TWIP); + + // Bottom + nMax = nH - nBT - aBorder.Height() - MINBODY - + nFDist - nFHeight - nHDist - nHHeight; + + m_xBottomMarginEdit->set_max(m_xTopMarginEdit->normalize(nMax), FieldUnit::TWIP); + + // Left + nMax = nW - nBR - MINBODY - aBorder.Width() - nHFLeft - nHFRight; + m_xLeftMarginEdit->set_max(m_xLeftMarginEdit->normalize(nMax), FieldUnit::TWIP); + + // Right + nMax = nW - nBL - MINBODY - aBorder.Width() - nHFLeft - nHFRight; + m_xRightMarginEdit->set_max(m_xRightMarginEdit->normalize(nMax), FieldUnit::TWIP); +} + +void SvxPageDescPage::CalcMargin_Impl() +{ + // current values for page margins + long nBT = GetCoreValue( *m_xTopMarginEdit, MapUnit::MapTwip ); + long nBB = GetCoreValue( *m_xBottomMarginEdit, MapUnit::MapTwip ); + + long nBL = GetCoreValue( *m_xLeftMarginEdit, MapUnit::MapTwip ); + long nBR = GetCoreValue( *m_xRightMarginEdit, MapUnit::MapTwip ); + + long nH = GetCoreValue( *m_xPaperHeightEdit, MapUnit::MapTwip ); + long nW = GetCoreValue( *m_xPaperWidthEdit, MapUnit::MapTwip ); + + long nWidth = nBL + nBR + MINBODY; + long nHeight = nBT + nBB + MINBODY; + + if ( !(nWidth > nW || nHeight > nH) ) + return; + + if ( nWidth > nW ) + { + long nTmp = nBL <= nBR ? nBR : nBL; + nTmp -= nWidth - nW; + + if ( nBL <= nBR ) + SetMetricValue( *m_xRightMarginEdit, nTmp, MapUnit::MapTwip ); + else + SetMetricValue( *m_xLeftMarginEdit, nTmp, MapUnit::MapTwip ); + } + + if ( nHeight > nH ) + { + long nTmp = nBT <= nBB ? nBB : nBT; + nTmp -= nHeight - nH; + + if ( nBT <= nBB ) + SetMetricValue( *m_xBottomMarginEdit, nTmp, MapUnit::MapTwip ); + else + SetMetricValue( *m_xTopMarginEdit, nTmp, MapUnit::MapTwip ); + } +} + +IMPL_LINK_NOARG(SvxPageDescPage, CenterHdl_Impl, weld::ToggleButton&, void) +{ + m_aBspWin.SetHorz(m_xHorzBox->get_active()); + m_aBspWin.SetVert(m_xVertBox->get_active()); + UpdateExample_Impl(); +} + +void SvxPageDescPage::SetCollectionList(const std::vector &aList) +{ + OSL_ENSURE(!aList.empty(), "Empty string list"); + + sStandardRegister = aList[0]; + m_xRegisterLB->freeze(); + for (size_t i = 1; i < aList.size(); ++i) + m_xRegisterLB->append_text(aList[i]); + m_xRegisterLB->thaw(); + + m_xRegisterCB->show(); + m_xRegisterFT->show(); + m_xRegisterLB->show(); + m_xRegisterCB->connect_toggled(LINK(this, SvxPageDescPage, RegisterModify)); +} + +IMPL_LINK(SvxPageDescPage, RegisterModify, weld::ToggleButton&, rBox, void) +{ + bool bEnable = false; + if (rBox.get_active()) + { + bEnable = true; + if (m_xRegisterLB->get_active() == -1) + m_xRegisterLB->set_active_text(sStandardRegister); + } + m_xRegisterFT->set_sensitive(bEnable); + m_xRegisterLB->set_sensitive(bEnable); +} + +void SvxPageDescPage::DisableVerticalPageDir() +{ + m_xTextFlowBox->remove_id(SvxFrameDirection::Vertical_RL_TB); + m_xTextFlowBox->remove_id(SvxFrameDirection::Vertical_LR_TB); + if (m_xTextFlowBox->get_count() < 2) + { + m_xTextFlowLbl->hide(); + m_xTextFlowBox->hide(); + m_aBspWin.EnableFrameDirection( false ); + } +} + +IMPL_LINK_NOARG(SvxPageDescPage, FrameDirectionModify_Impl, weld::ComboBox&, void) +{ + m_aBspWin.SetFrameDirection(m_xTextFlowBox->get_active_id()); + m_aBspWin.Invalidate(); +} + +bool SvxPageDescPage::IsPrinterRangeOverflow( + weld::MetricSpinButton& rField, long nFirstMargin, long nLastMargin, MarginPosition nPos ) +{ + bool bRet = false; + bool bCheck = ( ( m_nPos & nPos ) == 0 ); + long nValue = rField.get_value(FieldUnit::NONE); + if ( bCheck && + ( nValue < nFirstMargin || nValue > nLastMargin ) && + rField.get_value_changed_from_saved() ) + { + rField.set_value(nValue < nFirstMargin ? nFirstMargin : nLastMargin, FieldUnit::NONE); + bRet = true; + } + + return bRet; +} + +/** Check if a value of a margin edit is outside the printer paper margins + and save this information. +*/ +void SvxPageDescPage::CheckMarginEdits( bool _bClear ) +{ + if ( _bClear ) + m_nPos = 0; + + sal_Int64 nValue = m_xLeftMarginEdit->get_value(FieldUnit::NONE); + if ( nValue < nFirstLeftMargin || nValue > nLastLeftMargin ) + m_nPos |= MARGIN_LEFT; + nValue = m_xRightMarginEdit->get_value(FieldUnit::NONE); + if ( nValue < nFirstRightMargin || nValue > nLastRightMargin ) + m_nPos |= MARGIN_RIGHT; + nValue = m_xTopMarginEdit->get_value(FieldUnit::NONE); + if ( nValue < nFirstTopMargin || nValue > nLastTopMargin ) + m_nPos |= MARGIN_TOP; + nValue = m_xBottomMarginEdit->get_value(FieldUnit::NONE); + if ( nValue < nFirstBottomMargin || nValue > nLastBottomMargin ) + m_nPos |= MARGIN_BOTTOM; +} + +bool SvxPageDescPage::IsMarginOutOfRange() const +{ + bool bRet = ( ( ( !( m_nPos & MARGIN_LEFT ) && + m_xLeftMarginEdit->get_value_changed_from_saved() ) && + ( m_xLeftMarginEdit->get_value(FieldUnit::NONE) < nFirstLeftMargin || + m_xLeftMarginEdit->get_value(FieldUnit::NONE) > nLastLeftMargin ) ) || + ( ( !( m_nPos & MARGIN_RIGHT ) && + m_xRightMarginEdit->get_value_changed_from_saved() ) && + ( m_xRightMarginEdit->get_value(FieldUnit::NONE) < nFirstRightMargin || + m_xRightMarginEdit->get_value(FieldUnit::NONE) > nLastRightMargin ) ) || + ( ( !( m_nPos & MARGIN_TOP ) && + m_xTopMarginEdit->get_value_changed_from_saved() ) && + ( m_xTopMarginEdit->get_value(FieldUnit::NONE) < nFirstTopMargin || + m_xTopMarginEdit->get_value(FieldUnit::NONE) > nLastTopMargin ) ) || + ( ( !( m_nPos & MARGIN_BOTTOM ) && + m_xBottomMarginEdit->get_value_changed_from_saved() ) && + ( m_xBottomMarginEdit->get_value(FieldUnit::NONE) < nFirstBottomMargin || + m_xBottomMarginEdit->get_value(FieldUnit::NONE) > nLastBottomMargin ) ) ); + return bRet; +} + +void SvxPageDescPage::PageCreated(const SfxAllItemSet& aSet) +{ + const SfxUInt16Item* pModeItem = aSet.GetItem(SID_ENUM_PAGE_MODE, false); + const SfxUInt16Item* pPaperStartItem = aSet.GetItem(SID_PAPER_START, false); + const SfxUInt16Item* pPaperEndItem = aSet.GetItem(SID_PAPER_END, false); + const SfxStringListItem* pCollectListItem = aSet.GetItem(SID_COLLECT_LIST, false); + const SfxBoolItem* pSupportDrawingLayerFillStyleItem = aSet.GetItem(SID_DRAWINGLAYER_FILLSTYLES, false); + const SfxBoolItem* pIsImpressDoc = aSet.GetItem(SID_IMPRESS_DOC, false); + + if (pModeItem) + { + eMode = static_cast(pModeItem->GetValue()); + } + + if(pPaperStartItem && pPaperEndItem) + { + SetPaperFormatRanges(static_cast(pPaperStartItem->GetValue())); + } + + if(pCollectListItem) + { + SetCollectionList(pCollectListItem->GetList()); + } + + if(pSupportDrawingLayerFillStyleItem) + { + const bool bNew(pSupportDrawingLayerFillStyleItem->GetValue()); + + mbEnableDrawingLayerFillStyles = bNew; + } + + if (pIsImpressDoc) + m_xNumberFormatText->set_label(SvxResId(STR_SLIDE_NUMBERS)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/paragrph.cxx b/cui/source/tabpages/paragrph.cxx new file mode 100644 index 000000000..5f6ae38d3 --- /dev/null +++ b/cui/source/tabpages/paragrph.cxx @@ -0,0 +1,2311 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +const sal_uInt16 SvxStdParagraphTabPage::pStdRanges[] = +{ + SID_ATTR_PARA_LINESPACE, // 10033 + SID_ATTR_PARA_LINESPACE, + SID_ATTR_LRSPACE, // 10048 - + SID_ATTR_ULSPACE, // 10049 + SID_ATTR_PARA_REGISTER, // 10413 + SID_ATTR_PARA_REGISTER, + 0 +}; + +const sal_uInt16 SvxParaAlignTabPage::pAlignRanges[] = +{ + SID_ATTR_PARA_ADJUST, // 10027 + SID_ATTR_PARA_ADJUST, + 0 +}; + +const sal_uInt16 SvxExtParagraphTabPage::pExtRanges[] = +{ + SID_ATTR_PARA_PAGEBREAK, // 10037 - + SID_ATTR_PARA_WIDOWS, // 10041 + SID_ATTR_PARA_MODEL, // 10065 - + SID_ATTR_PARA_KEEP, // 10066 + 0 +}; + +#define MAX_DURCH 5670 // 10 cm makes sense as maximum interline lead + // according to BP +#define FIX_DIST_DEF 283 // standard fix distance 0,5 cm + +namespace { + +enum LineSpaceList +{ + LLINESPACE_1 = 0, + LLINESPACE_115 = 1, + LLINESPACE_15 = 2, + LLINESPACE_2 = 3, + LLINESPACE_PROP = 4, + LLINESPACE_MIN = 5, + LLINESPACE_DURCH= 6, + LLINESPACE_FIX = 7 +}; + +} + +static void SetLineSpace_Impl( SvxLineSpacingItem&, int, long lValue = 0 ); + +void SetLineSpace_Impl( SvxLineSpacingItem& rLineSpace, + int eSpace, long lValue ) +{ + switch ( eSpace ) + { + case LLINESPACE_1: + rLineSpace.SetLineSpaceRule( SvxLineSpaceRule::Auto ); + rLineSpace.SetInterLineSpaceRule( SvxInterLineSpaceRule::Off ); + break; + + case LLINESPACE_115: + rLineSpace.SetLineSpaceRule( SvxLineSpaceRule::Auto ); + rLineSpace.SetPropLineSpace( 115 ); + break; + + case LLINESPACE_15: + rLineSpace.SetLineSpaceRule( SvxLineSpaceRule::Auto ); + rLineSpace.SetPropLineSpace( 150 ); + break; + + case LLINESPACE_2: + rLineSpace.SetLineSpaceRule( SvxLineSpaceRule::Auto ); + rLineSpace.SetPropLineSpace( 200 ); + break; + + case LLINESPACE_PROP: + rLineSpace.SetLineSpaceRule( SvxLineSpaceRule::Auto ); + rLineSpace.SetPropLineSpace( static_cast(lValue) ); + break; + + case LLINESPACE_MIN: + rLineSpace.SetLineHeight( static_cast(lValue) ); + rLineSpace.SetInterLineSpaceRule( SvxInterLineSpaceRule::Off ); + break; + + case LLINESPACE_DURCH: + rLineSpace.SetLineSpaceRule( SvxLineSpaceRule::Auto ); + rLineSpace.SetInterLineSpace( static_cast(lValue) ); + break; + + case LLINESPACE_FIX: + rLineSpace.SetLineHeight(static_cast(lValue)); + rLineSpace.SetLineSpaceRule( SvxLineSpaceRule::Fix ); + rLineSpace.SetInterLineSpaceRule( SvxInterLineSpaceRule::Off ); + break; + } +} + +static sal_uInt16 GetHtmlMode_Impl(const SfxItemSet& rSet) +{ + sal_uInt16 nHtmlMode = 0; + const SfxPoolItem* pItem = nullptr; + SfxObjectShell* pShell; + if(SfxItemState::SET == rSet.GetItemState(SID_HTML_MODE, false, &pItem) || + ( nullptr != (pShell = SfxObjectShell::Current()) && + nullptr != (pItem = pShell->GetItem(SID_HTML_MODE)))) + { + nHtmlMode = static_cast(pItem)->GetValue(); + } + return nHtmlMode; + +} + +void SvxStdParagraphTabPage::ELRLoseFocus() +{ + SfxItemPool* pPool = GetItemSet().GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + FieldUnit eUnit = + MapToFieldUnit( pPool->GetMetric( GetWhich( SID_ATTR_LRSPACE ) ) ); + + sal_Int64 nL = m_xLeftIndent->denormalize(m_xLeftIndent->get_value(eUnit)); + sal_Int64 nR = m_xRightIndent->denormalize(m_xRightIndent->get_value(eUnit)); + OUString aTmp = m_xFLineIndent->get_text(); + + if (m_xLeftIndent->get_min(FieldUnit::NONE) < 0) + m_xFLineIndent->set_min(-99999, FieldUnit::MM); + else + m_xFLineIndent->set_min(m_xFLineIndent->normalize(-nL), eUnit); + + // Check only for concrete width (Shell) + sal_Int64 nTmp = nWidth - nL - nR - MM50; + m_xFLineIndent->set_max(m_xFLineIndent->normalize(nTmp), eUnit); + + if (aTmp.isEmpty()) + m_xFLineIndent->set_text(OUString()); + // maximum left right + aTmp = m_xLeftIndent->get_text(); + nTmp = nWidth - nR - MM50; + m_xLeftIndent->set_max(m_xLeftIndent->normalize(nTmp), eUnit); + + if ( aTmp.isEmpty() ) + m_xLeftIndent->set_text(OUString()); + aTmp = m_xRightIndent->get_text(); + nTmp = nWidth - nL - MM50; + m_xRightIndent->set_max(m_xRightIndent->normalize(nTmp), eUnit); + + if ( aTmp.isEmpty() ) + m_xRightIndent->set_text(OUString()); + + UpdateExample_Impl(); +} + +IMPL_LINK_NOARG(SvxStdParagraphTabPage, ELRLoseFocusHdl, weld::MetricSpinButton&, void) +{ + ELRLoseFocus(); +} + +std::unique_ptr SvxStdParagraphTabPage::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet) +{ + return std::make_unique(pPage, pController, *rSet); +} + +bool SvxStdParagraphTabPage::FillItemSet( SfxItemSet* rOutSet ) +{ + SfxItemState eState = SfxItemState::UNKNOWN; + const SfxPoolItem* pOld = nullptr; + SfxItemPool* pPool = rOutSet->GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + + bool bModified = false; + sal_uInt16 nWhich; + int nPos = m_xLineDist->get_active(); + + if ( nPos != -1 && + ( m_bLineDistToggled || + m_xLineDist->get_value_changed_from_saved() || + m_xLineDistAtPercentBox->get_value_changed_from_saved() || + m_xLineDistAtMetricBox->get_value_changed_from_saved() ) ) + { + nWhich = GetWhich( SID_ATTR_PARA_LINESPACE ); + MapUnit eUnit = SfxViewFrame::Current()->GetPool().GetMetric( nWhich ); + SvxLineSpacingItem aSpacing( + static_cast(GetItemSet().Get( nWhich )) ); + + switch ( nPos ) + { + case LLINESPACE_1: + case LLINESPACE_115: + case LLINESPACE_15: + case LLINESPACE_2: + SetLineSpace_Impl( aSpacing, nPos ); + break; + + case LLINESPACE_PROP: + SetLineSpace_Impl( aSpacing, nPos, + static_cast(m_xLineDistAtPercentBox->denormalize( + m_xLineDistAtPercentBox->get_value(FieldUnit::NONE) )) ); + break; + + case LLINESPACE_MIN: + case LLINESPACE_DURCH: + case LLINESPACE_FIX: + SetLineSpace_Impl( aSpacing, nPos, + GetCoreValue( *m_xLineDistAtMetricBox, eUnit ) ); + break; + + default: + OSL_FAIL( "unknown LineDist entry" ); + break; + } + eState = GetItemSet().GetItemState( nWhich ); + pOld = GetOldItem( *rOutSet, SID_ATTR_PARA_LINESPACE ); + + if ( m_bLineDistToggled || + !pOld || !( *static_cast(pOld) == aSpacing ) || + SfxItemState::DONTCARE == eState ) + { + rOutSet->Put( aSpacing ); + bModified = true; + } + } + + if ( m_xTopDist->get_value_changed_from_saved() || m_xBottomDist->get_value_changed_from_saved() + || m_xContextualCB->get_state_changed_from_saved()) + { + nWhich = GetWhich( SID_ATTR_ULSPACE ); + MapUnit eUnit = pPool->GetMetric( nWhich ); + pOld = GetOldItem( *rOutSet, SID_ATTR_ULSPACE ); + SvxULSpaceItem aMargin( nWhich ); + + if ( bRelativeMode ) + { + DBG_ASSERT( GetItemSet().GetParent(), "No ParentSet" ); + + const SvxULSpaceItem& rOldItem = + static_cast(GetItemSet().GetParent()->Get( nWhich )); + + if ( m_xTopDist->IsRelative() ) + aMargin.SetUpper( rOldItem.GetUpper(), + static_cast(m_xTopDist->get_value(FieldUnit::NONE)) ); + else + aMargin.SetUpper( static_cast(m_xTopDist->GetCoreValue(eUnit)) ); + + if ( m_xBottomDist->IsRelative() ) + aMargin.SetLower( rOldItem.GetLower(), + static_cast(m_xBottomDist->get_value(FieldUnit::NONE)) ); + else + aMargin.SetLower( static_cast(m_xBottomDist->GetCoreValue(eUnit)) ); + + } + else + { + aMargin.SetUpper(static_cast(m_xTopDist->GetCoreValue(eUnit))); + aMargin.SetLower(static_cast(m_xBottomDist->GetCoreValue(eUnit))); + } + aMargin.SetContextValue(m_xContextualCB->get_active()); + eState = GetItemSet().GetItemState( nWhich ); + + if ( !pOld || *static_cast(pOld) != aMargin || + SfxItemState::DONTCARE == eState ) + { + rOutSet->Put( aMargin ); + bModified = true; + } + } + bool bNullTab = false; + + if ( m_xLeftIndent->get_value_changed_from_saved() || + m_xFLineIndent->get_value_changed_from_saved() || + m_xRightIndent->get_value_changed_from_saved() || + m_xAutoCB->get_state_changed_from_saved() ) + { + nWhich = GetWhich( SID_ATTR_LRSPACE ); + MapUnit eUnit = pPool->GetMetric( nWhich ); + SvxLRSpaceItem aMargin( nWhich ); + pOld = GetOldItem( *rOutSet, SID_ATTR_LRSPACE ); + + if ( bRelativeMode ) + { + DBG_ASSERT( GetItemSet().GetParent(), "No ParentSet" ); + + const SvxLRSpaceItem& rOldItem = + static_cast(GetItemSet().GetParent()->Get( nWhich )); + + if (m_xLeftIndent->IsRelative()) + aMargin.SetTextLeft( rOldItem.GetTextLeft(), + static_cast(m_xLeftIndent->get_value(FieldUnit::NONE)) ); + else + aMargin.SetTextLeft(m_xLeftIndent->GetCoreValue(eUnit)); + + if ( m_xRightIndent->IsRelative() ) + aMargin.SetRight( rOldItem.GetRight(), + static_cast(m_xRightIndent->get_value(FieldUnit::NONE)) ); + else + aMargin.SetRight(m_xRightIndent->GetCoreValue(eUnit)); + + if ( m_xFLineIndent->IsRelative() ) + aMargin.SetTextFirstLineOffset( rOldItem.GetTextFirstLineOffset(), + static_cast(m_xFLineIndent->get_value(FieldUnit::NONE)) ); + else + aMargin.SetTextFirstLineOffset(static_cast(m_xFLineIndent->GetCoreValue(eUnit))); + } + else + { + aMargin.SetTextLeft(m_xLeftIndent->GetCoreValue(eUnit)); + aMargin.SetRight(m_xRightIndent->GetCoreValue(eUnit)); + aMargin.SetTextFirstLineOffset(static_cast(m_xFLineIndent->GetCoreValue(eUnit))); + } + aMargin.SetAutoFirst(m_xAutoCB->get_active()); + if ( aMargin.GetTextFirstLineOffset() < 0 ) + bNullTab = true; + eState = GetItemSet().GetItemState( nWhich ); + + if ( !pOld || *static_cast(pOld) != aMargin || + SfxItemState::DONTCARE == eState ) + { + rOutSet->Put( aMargin ); + bModified = true; + } + } + + if ( bNullTab ) + { + MapUnit eUnit = pPool->GetMetric( GetWhich( SID_ATTR_TABSTOP ) ); + if ( MapUnit::Map100thMM != eUnit ) + { + + // negative first line indent -> set null default tabstob if applicable + sal_uInt16 _nWhich = GetWhich( SID_ATTR_TABSTOP ); + const SfxItemSet& rInSet = GetItemSet(); + + if ( rInSet.GetItemState( _nWhich ) >= SfxItemState::DEFAULT ) + { + const SvxTabStopItem& rTabItem = + static_cast(rInSet.Get( _nWhich )); + SvxTabStopItem aNullTab( rTabItem ); + SvxTabStop aNull( 0, SvxTabAdjust::Default ); + aNullTab.Insert( aNull ); + rOutSet->Put( aNullTab ); + } + } + } + if (m_xRegisterCB->get_visible()) + { + const SfxBoolItem* pBoolItem = static_cast(GetOldItem( + *rOutSet, SID_ATTR_PARA_REGISTER)); + if (!pBoolItem) + return bModified; + std::unique_ptr pRegItem(pBoolItem->Clone()); + sal_uInt16 _nWhich = GetWhich( SID_ATTR_PARA_REGISTER ); + bool bSet = pRegItem->GetValue(); + + if (m_xRegisterCB->get_active() != bSet) + { + pRegItem->SetValue(!bSet); + rOutSet->Put(*pRegItem); + bModified = true; + } + else if ( SfxItemState::DEFAULT == GetItemSet().GetItemState( _nWhich, false ) ) + rOutSet->ClearItem(_nWhich); + } + + return bModified; +} + +void SvxStdParagraphTabPage::Reset( const SfxItemSet* rSet ) +{ + SfxItemPool* pPool = rSet->GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + + // adjust metric + FieldUnit eFUnit = GetModuleFieldUnit( *rSet ); + + bool bApplyCharUnit = GetApplyCharUnit( *rSet ); + + SvtCJKOptions aCJKOptions; + if(aCJKOptions.IsAsianTypographyEnabled() && bApplyCharUnit ) + eFUnit = FieldUnit::CHAR; + + m_xLeftIndent->SetFieldUnit(eFUnit); + m_xRightIndent->SetFieldUnit(eFUnit); + m_xFLineIndent->SetFieldUnit(eFUnit); + if ( eFUnit == FieldUnit::CHAR ) + { + m_xTopDist->SetFieldUnit(FieldUnit::LINE); + m_xBottomDist->SetFieldUnit(FieldUnit::LINE); + SetFieldUnit(*m_xLineDistAtMetricBox, FieldUnit::POINT); + } + else + { + m_xTopDist->SetFieldUnit(eFUnit); + m_xBottomDist->SetFieldUnit(eFUnit); + SetFieldUnit(*m_xLineDistAtMetricBox, eFUnit); + } + + sal_uInt16 _nWhich = GetWhich( SID_ATTR_LRSPACE ); + SfxItemState eItemState = rSet->GetItemState( _nWhich ); + + if ( eItemState >= SfxItemState::DEFAULT ) + { + MapUnit eUnit = pPool->GetMetric( _nWhich ); + + if ( bRelativeMode ) + { + const SvxLRSpaceItem& rOldItem = + static_cast(rSet->Get( _nWhich )); + + if ( rOldItem.GetPropLeft() != 100 ) + { + m_xLeftIndent->SetRelative( true ); + m_xLeftIndent->set_value(rOldItem.GetPropLeft(), FieldUnit::NONE); + } + else + { + m_xLeftIndent->SetRelative(false); + m_xLeftIndent->SetFieldUnit(eFUnit); + m_xLeftIndent->SetMetricValue(rOldItem.GetTextLeft(), eUnit); + } + + if ( rOldItem.GetPropRight() != 100 ) + { + m_xRightIndent->SetRelative( true ); + m_xRightIndent->set_value(rOldItem.GetPropRight(), FieldUnit::NONE); + } + else + { + m_xRightIndent->SetRelative(false); + m_xRightIndent->SetFieldUnit(eFUnit); + m_xRightIndent->SetMetricValue(rOldItem.GetRight(), eUnit); + } + + if ( rOldItem.GetPropTextFirstLineOffset() != 100 ) + { + m_xFLineIndent->SetRelative(true); + m_xFLineIndent->set_value(rOldItem.GetPropTextFirstLineOffset(), FieldUnit::NONE); + } + else + { + m_xFLineIndent->SetRelative(false); + m_xFLineIndent->set_min(-9999, FieldUnit::NONE); + m_xFLineIndent->SetFieldUnit(eFUnit); + m_xFLineIndent->SetMetricValue(rOldItem.GetTextFirstLineOffset(), eUnit); + } + m_xAutoCB->set_active(rOldItem.IsAutoFirst()); + } + else + { + const SvxLRSpaceItem& rSpace = + static_cast(rSet->Get( _nWhich )); + + m_xLeftIndent->SetMetricValue(rSpace.GetTextLeft(), eUnit); + m_xRightIndent->SetMetricValue(rSpace.GetRight(), eUnit); + m_xFLineIndent->SetMetricValue(rSpace.GetTextFirstLineOffset(), eUnit); + m_xAutoCB->set_active(rSpace.IsAutoFirst()); + } + AutoHdl_Impl(*m_xAutoCB); + } + else + { + m_xLeftIndent->set_text(OUString()); + m_xRightIndent->set_text(OUString()); + m_xFLineIndent->set_text(OUString()); + } + + _nWhich = GetWhich( SID_ATTR_ULSPACE ); + eItemState = rSet->GetItemState( _nWhich ); + + if ( eItemState >= SfxItemState::DEFAULT ) + { + MapUnit eUnit = pPool->GetMetric( _nWhich ); + + const SvxULSpaceItem& rOldItem = + static_cast(rSet->Get( _nWhich )); + if ( bRelativeMode ) + { + + if ( rOldItem.GetPropUpper() != 100 ) + { + m_xTopDist->SetRelative( true ); + m_xTopDist->set_value(rOldItem.GetPropUpper(), FieldUnit::NONE); + } + else + { + m_xTopDist->SetRelative(false); + if (eFUnit == FieldUnit::CHAR) + m_xTopDist->SetFieldUnit(FieldUnit::LINE); + else + m_xTopDist->SetFieldUnit(eFUnit); + m_xTopDist->SetMetricValue(rOldItem.GetUpper(), eUnit); + } + + if ( rOldItem.GetPropLower() != 100 ) + { + m_xBottomDist->SetRelative( true ); + m_xBottomDist->set_value(rOldItem.GetPropLower(), FieldUnit::NONE); + } + else + { + m_xBottomDist->SetRelative(false); + if (eFUnit == FieldUnit::CHAR) + m_xBottomDist->SetFieldUnit(FieldUnit::LINE); + else + m_xBottomDist->SetFieldUnit(eFUnit); + m_xBottomDist->SetMetricValue(rOldItem.GetLower(), eUnit); + } + } + else + { + m_xTopDist->SetMetricValue(rOldItem.GetUpper(), eUnit); + m_xBottomDist->SetMetricValue(rOldItem.GetLower(), eUnit); + } + m_xContextualCB->set_active(rOldItem.GetContext()); + } + else + { + m_xTopDist->set_text(OUString()); + m_xBottomDist->set_text(OUString()); + } + + _nWhich = GetWhich( SID_ATTR_PARA_LINESPACE ); + eItemState = rSet->GetItemState( _nWhich ); + + if ( eItemState >= SfxItemState::DEFAULT ) + SetLineSpacing_Impl( static_cast(rSet->Get( _nWhich )) ); + else + m_xLineDist->set_active(-1); + + _nWhich = GetWhich( SID_ATTR_PARA_REGISTER ); + eItemState = rSet->GetItemState( _nWhich ); + + if ( eItemState >= SfxItemState::DEFAULT ) + m_xRegisterCB->set_active( static_cast(rSet->Get( _nWhich )).GetValue()); + m_xRegisterCB->save_state(); + sal_uInt16 nHtmlMode = GetHtmlMode_Impl(*rSet); + if(nHtmlMode & HTMLMODE_ON) + { + m_xRegisterFL->hide(); + m_xRegisterCB->hide(); + m_xAutoCB->hide(); + } + + // this sets the min/max limits; do this _after_ setting the values, + // because for Impress the min of first-line indent depends on value of + // left-indent! + ELRLoseFocus(); + ChangesApplied(); +} + +void SvxStdParagraphTabPage::ChangesApplied() +{ + m_xLeftIndent->save_value(); + m_xRightIndent->save_value(); + m_xFLineIndent->save_value(); + m_xLineDist->save_value(); + m_xLineDistAtPercentBox->save_value(); + m_xLineDistAtMetricBox->save_value(); + m_xRegisterCB->save_state(); + m_xTopDist->save_value(); + m_xBottomDist->save_value(); + m_xContextualCB->save_state(); + m_xAutoCB->save_state(); +} + +void SvxStdParagraphTabPage::EnableRelativeMode() +{ + DBG_ASSERT( GetItemSet().GetParent(), "RelativeMode, but no parent-set!" ); + + m_xLeftIndent->EnableRelativeMode( 0, 999 ); + m_xFLineIndent->EnableRelativeMode( 0, 999 ); + m_xRightIndent->EnableRelativeMode( 0, 999 ); + m_xTopDist->EnableRelativeMode( 0, 999 ); + m_xBottomDist->EnableRelativeMode( 0, 999 ); + bRelativeMode = true; +} + +void SvxStdParagraphTabPage::ActivatePage( const SfxItemSet& rSet ) +{ + sal_uInt16 _nWhich = GetWhich( SID_ATTR_PARA_ADJUST ); + SfxItemState eItemState = rSet.GetItemState( _nWhich ); + + if ( eItemState < SfxItemState::DEFAULT ) + return; + + const SvxAdjustItem& rAdj = static_cast( rSet.Get( _nWhich ) ); + SvxAdjust eAdjust = rAdj.GetAdjust(); + if ( eAdjust == SvxAdjust::Center || eAdjust == SvxAdjust::Block ) + { + _nWhich = GetWhich( SID_ATTR_FRAMEDIRECTION ); + eItemState = rSet.GetItemState( _nWhich ); + + if ( eItemState >= SfxItemState::DEFAULT ) + { + const SvxFrameDirectionItem& rFrameDirItem = static_cast( rSet.Get( _nWhich ) ); + SvxFrameDirection eFrameDirection = rFrameDirItem.GetValue(); + + m_aExampleWin.EnableRTL( SvxFrameDirection::Horizontal_RL_TB == eFrameDirection ); + + if ( eAdjust == SvxAdjust::Block ) + m_aExampleWin.SetLastLine( rAdj.GetLastBlock() ); + } + } + else + { + m_aExampleWin.EnableRTL( eAdjust == SvxAdjust::Right ); + eAdjust = SvxAdjust::Left; //required for correct preview display + m_aExampleWin.SetLastLine( eAdjust ); + } + m_aExampleWin.SetAdjust( eAdjust ); + + UpdateExample_Impl(); +} + +DeactivateRC SvxStdParagraphTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + ELRLoseFocus(); + + if ( _pSet ) + FillItemSet( _pSet ); + return DeactivateRC::LeavePage; +} + +SvxStdParagraphTabPage::SvxStdParagraphTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rAttr) + : SfxTabPage(pPage, pController, "cui/ui/paraindentspacing.ui", "ParaIndentSpacing", &rAttr) + , nWidth(11905 /*567 * 50*/) + , nMinFixDist(0) + , bRelativeMode(false) + , m_xLeftIndent(new SvxRelativeField(m_xBuilder->weld_metric_spin_button("spinED_LEFTINDENT", FieldUnit::CM))) + , m_xRightLabel(m_xBuilder->weld_label("labelFT_RIGHTINDENT")) + , m_xRightIndent(new SvxRelativeField(m_xBuilder->weld_metric_spin_button("spinED_RIGHTINDENT", FieldUnit::CM))) + , m_xFLineLabel(m_xBuilder->weld_label("labelFT_FLINEINDENT")) + , m_xFLineIndent(new SvxRelativeField(m_xBuilder->weld_metric_spin_button("spinED_FLINEINDENT", FieldUnit::CM))) + , m_xAutoCB(m_xBuilder->weld_check_button("checkCB_AUTO")) + , m_xTopDist(new SvxRelativeField(m_xBuilder->weld_metric_spin_button("spinED_TOPDIST", FieldUnit::CM))) + , m_xBottomDist(new SvxRelativeField(m_xBuilder->weld_metric_spin_button("spinED_BOTTOMDIST", FieldUnit::CM))) + , m_xContextualCB(m_xBuilder->weld_check_button("checkCB_CONTEXTUALSPACING")) + , m_xLineDist(m_xBuilder->weld_combo_box("comboLB_LINEDIST")) + , m_xLineDistAtPercentBox(m_xBuilder->weld_metric_spin_button("spinED_LINEDISTPERCENT", FieldUnit::PERCENT)) + , m_xLineDistAtMetricBox(m_xBuilder->weld_metric_spin_button("spinED_LINEDISTMETRIC", FieldUnit::CM)) + , m_xLineDistAtLabel(m_xBuilder->weld_label("labelFT_LINEDIST")) + , m_xAbsDist(m_xBuilder->weld_label("labelST_LINEDIST_ABS")) + , m_xRegisterFL(m_xBuilder->weld_widget("frameFL_REGISTER")) + , m_xRegisterCB(m_xBuilder->weld_check_button("checkCB_REGISTER")) + , m_xExampleWin(new weld::CustomWeld(*m_xBuilder, "drawingareaWN_EXAMPLE", m_aExampleWin)) +{ + sAbsDist = m_xAbsDist->get_label(); + + // this page needs ExchangeSupport + SetExchangeSupport(); + + m_xLineDistAtMetricBox->hide(); + + Init_Impl(); + m_xFLineIndent->set_min(-9999, FieldUnit::NONE); // is set to 0 on default +} + +SvxStdParagraphTabPage::~SvxStdParagraphTabPage() +{ +} + +void SvxStdParagraphTabPage::EnableNegativeMode() +{ + m_xLeftIndent->set_min(-9999, FieldUnit::NONE); + m_xRightIndent->set_min(-9999, FieldUnit::NONE); + m_xRightIndent->EnableNegativeMode(); + m_xLeftIndent->EnableNegativeMode(); +} + +void SvxStdParagraphTabPage::SetLineSpacing_Impl +( + const SvxLineSpacingItem &rAttr +) +{ + MapUnit eUnit = SfxViewFrame::Current()->GetPool().GetMetric( rAttr.Which() ); + + switch( rAttr.GetLineSpaceRule() ) + { + case SvxLineSpaceRule::Auto: + { + SvxInterLineSpaceRule eInter = rAttr.GetInterLineSpaceRule(); + + switch( eInter ) + { + // Default single line spacing + case SvxInterLineSpaceRule::Off: + m_xLineDist->set_active( LLINESPACE_1 ); + break; + + // Default single line spacing + case SvxInterLineSpaceRule::Prop: + if ( 100 == rAttr.GetPropLineSpace() ) + { + m_xLineDist->set_active( LLINESPACE_1 ); + break; + } + // 1.15 line spacing + if ( 115 == rAttr.GetPropLineSpace() ) + { + m_xLineDist->set_active( LLINESPACE_115 ); + break; + } + // 1.5 line spacing + if ( 150 == rAttr.GetPropLineSpace() ) + { + m_xLineDist->set_active( LLINESPACE_15 ); + break; + } + // double line spacing + if ( 200 == rAttr.GetPropLineSpace() ) + { + m_xLineDist->set_active( LLINESPACE_2 ); + break; + } + // the set per cent value + m_xLineDistAtPercentBox->set_value(m_xLineDistAtPercentBox->normalize(rAttr.GetPropLineSpace()), FieldUnit::NONE); + m_xLineDist->set_active( LLINESPACE_PROP ); + break; + + case SvxInterLineSpaceRule::Fix: + SetMetricValue( *m_xLineDistAtMetricBox, rAttr.GetInterLineSpace(), eUnit ); + m_xLineDist->set_active( LLINESPACE_DURCH ); + break; + default: ;//prevent warning + } + } + break; + case SvxLineSpaceRule::Fix: + SetMetricValue(*m_xLineDistAtMetricBox, rAttr.GetLineHeight(), eUnit); + m_xLineDist->set_active( LLINESPACE_FIX ); + break; + + case SvxLineSpaceRule::Min: + SetMetricValue(*m_xLineDistAtMetricBox, rAttr.GetLineHeight(), eUnit); + m_xLineDist->set_active( LLINESPACE_MIN ); + break; + default: ;//prevent warning + } + LineDistHdl_Impl( *m_xLineDist ); +} + +IMPL_LINK_NOARG(SvxStdParagraphTabPage, LineDistPopupHdl_Impl, weld::ComboBox&, void) +{ + m_bLineDistToggled = true; +} + +IMPL_LINK(SvxStdParagraphTabPage, LineDistHdl_Impl, weld::ComboBox&, rBox, void) +{ + switch (rBox.get_active()) + { + case LLINESPACE_1: + case LLINESPACE_115: + case LLINESPACE_15: + case LLINESPACE_2: + m_xLineDistAtLabel->set_sensitive(false); + m_xLineDistAtPercentBox->set_sensitive(false); + m_xLineDistAtPercentBox->set_text(OUString()); + m_xLineDistAtMetricBox->set_sensitive(false); + m_xLineDistAtMetricBox->set_text(OUString()); + break; + + case LLINESPACE_DURCH: + // setting a sensible default? + // limit MS min(10, aPageSize) + m_xLineDistAtMetricBox->set_min(0, FieldUnit::NONE); + + if (m_xLineDistAtMetricBox->get_text().isEmpty()) + m_xLineDistAtMetricBox->set_value(m_xLineDistAtMetricBox->normalize(1), FieldUnit::NONE); + m_xLineDistAtPercentBox->hide(); + m_xLineDistAtMetricBox->show(); + m_xLineDistAtMetricBox->set_sensitive(true); + m_xLineDistAtLabel->set_sensitive(true); + break; + + case LLINESPACE_MIN: + m_xLineDistAtMetricBox->set_min(0, FieldUnit::NONE); + + if (m_xLineDistAtMetricBox->get_text().isEmpty()) + m_xLineDistAtMetricBox->set_value(m_xLineDistAtMetricBox->normalize(10), FieldUnit::TWIP); + m_xLineDistAtPercentBox->hide(); + m_xLineDistAtMetricBox->show(); + m_xLineDistAtMetricBox->set_sensitive(true); + m_xLineDistAtLabel->set_sensitive(true); + break; + + case LLINESPACE_PROP: + + if (m_xLineDistAtPercentBox->get_text().isEmpty()) + m_xLineDistAtPercentBox->set_value(m_xLineDistAtPercentBox->normalize(100), FieldUnit::TWIP); + m_xLineDistAtMetricBox->hide(); + m_xLineDistAtPercentBox->show(); + m_xLineDistAtPercentBox->set_sensitive(true); + m_xLineDistAtLabel->set_sensitive(true); + break; + case LLINESPACE_FIX: + { + auto nTemp = m_xLineDistAtMetricBox->get_value(FieldUnit::NONE); + m_xLineDistAtMetricBox->set_min(m_xLineDistAtMetricBox->normalize(nMinFixDist), FieldUnit::TWIP); + + // if the value has been changed at SetMin, + // it is time for the default + if (m_xLineDistAtMetricBox->get_value(FieldUnit::NONE) != nTemp) + SetMetricValue( *m_xLineDistAtMetricBox, FIX_DIST_DEF, MapUnit::MapTwip ); // fix is only in Writer + m_xLineDistAtPercentBox->hide(); + m_xLineDistAtMetricBox->show(); + m_xLineDistAtMetricBox->set_sensitive(true); + m_xLineDistAtLabel->set_sensitive(true); + } + break; + } + UpdateExample_Impl(); +} + +IMPL_LINK_NOARG(SvxStdParagraphTabPage, ModifyHdl_Impl, weld::MetricSpinButton&, void) +{ + UpdateExample_Impl(); +} + +void SvxStdParagraphTabPage::Init_Impl() +{ + m_xLineDist->connect_popup_toggled(LINK(this, SvxStdParagraphTabPage, LineDistPopupHdl_Impl)); + m_xLineDist->connect_changed(LINK(this, SvxStdParagraphTabPage, LineDistHdl_Impl)); + + Link aLink2 = LINK(this, SvxStdParagraphTabPage, ELRLoseFocusHdl); + m_xFLineIndent->connect_value_changed(aLink2); + m_xLeftIndent->connect_value_changed(aLink2); + m_xRightIndent->connect_value_changed(aLink2); + + Link aLink = LINK(this, SvxStdParagraphTabPage, ModifyHdl_Impl); + m_xTopDist->connect_value_changed(aLink); + m_xBottomDist->connect_value_changed(aLink); + + m_xAutoCB->connect_toggled(LINK(this, SvxStdParagraphTabPage, AutoHdl_Impl)); + SfxItemPool* pPool = GetItemSet().GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( GetWhich( SID_ATTR_LRSPACE ) ) ); + + m_xTopDist->set_max( m_xTopDist->normalize( MAX_DURCH ), eUnit ); + m_xBottomDist->set_max( m_xBottomDist->normalize( MAX_DURCH ), eUnit ); + m_xLineDistAtMetricBox->set_max( m_xLineDistAtMetricBox->normalize( MAX_DURCH ), eUnit ); +} + +void SvxStdParagraphTabPage::UpdateExample_Impl() +{ + m_aExampleWin.SetFirstLineOffset( static_cast(m_xFLineIndent->denormalize( m_xFLineIndent->get_value( FieldUnit::TWIP ) )) ); + m_aExampleWin.SetLeftMargin( static_cast(m_xLeftIndent->denormalize( m_xLeftIndent->get_value( FieldUnit::TWIP ) ) ) ); + m_aExampleWin.SetRightMargin( static_cast(m_xRightIndent->denormalize( m_xRightIndent->get_value( FieldUnit::TWIP ) ) ) ); + m_aExampleWin.SetUpper( static_cast(m_xTopDist->denormalize( m_xTopDist->get_value( FieldUnit::TWIP ) )) ); + m_aExampleWin.SetLower( static_cast(m_xBottomDist->denormalize( m_xBottomDist->get_value( FieldUnit::TWIP ) )) ); + + int nPos = m_xLineDist->get_active(); + + switch ( nPos ) + { + case LLINESPACE_1: + case LLINESPACE_115: + case LLINESPACE_15: + case LLINESPACE_2: + case LLINESPACE_PROP: + case LLINESPACE_MIN: + case LLINESPACE_DURCH: + case LLINESPACE_FIX: + m_aExampleWin.SetLineSpace( static_cast(nPos) ); + break; + } + m_aExampleWin.Invalidate(); +} + +void SvxStdParagraphTabPage::EnableRegisterMode() +{ + m_xRegisterCB->show(); + m_xRegisterFL->show(); +} + +void SvxStdParagraphTabPage::EnableContextualMode() +{ + m_xContextualCB->show(); +} + +IMPL_LINK(SvxStdParagraphTabPage, AutoHdl_Impl, weld::ToggleButton&, rBox, void) +{ + bool bEnable = !rBox.get_active(); + m_xFLineLabel->set_sensitive(bEnable); + m_xFLineIndent->set_sensitive(bEnable); +} + +void SvxStdParagraphTabPage::EnableAutoFirstLine() +{ + m_xAutoCB->show(); +} + +void SvxStdParagraphTabPage::EnableAbsLineDist(long nMinTwip) +{ + m_xLineDist->append_text(sAbsDist); + nMinFixDist = nMinTwip; +} + +void SvxStdParagraphTabPage::PageCreated(const SfxAllItemSet& aSet) +{ + +/* different bit represent call to different method of SvxStdParagraphTabPage + 0x0001 --->EnableRelativeMode() + 0x0002 --->EnableRegisterMode() + 0x0004 --->EnableAutoFirstLine() + 0x0008 --->EnableNegativeMode() + 0x0010 --->EnableContextualMode() + */ + const SfxUInt16Item* pPageWidthItem = aSet.GetItem(SID_SVXSTDPARAGRAPHTABPAGE_PAGEWIDTH, false); + const SfxUInt32Item* pFlagSetItem = aSet.GetItem(SID_SVXSTDPARAGRAPHTABPAGE_FLAGSET, false); + const SfxUInt32Item* pLineDistItem = aSet.GetItem(SID_SVXSTDPARAGRAPHTABPAGE_ABSLINEDIST, false); + + if (pPageWidthItem) + nWidth = pPageWidthItem->GetValue(); + + if (pFlagSetItem ) + { + if (( 0x0001 & pFlagSetItem->GetValue())== 0x0001 ) + EnableRelativeMode(); + + if (( 0x0002 & pFlagSetItem->GetValue())== 0x0002 ) + EnableRegisterMode(); + + if ( ( 0x0004 & pFlagSetItem->GetValue())== 0x0004 ) + EnableAutoFirstLine(); + } + + if(pLineDistItem) + EnableAbsLineDist(pLineDistItem->GetValue()); + + if (pFlagSetItem) + { + if (( 0x0008 & pFlagSetItem->GetValue()) == 0x0008 ) + EnableNegativeMode(); + + if (( 0x0010 & pFlagSetItem->GetValue()) == 0x0010 ) + EnableContextualMode(); + } +} + +#define LASTLINEPOS_DEFAULT 0 +#define LASTLINEPOS_LEFT 1 + +#define LASTLINECOUNT_OLD 3 +#define LASTLINECOUNT_NEW 4 + +SvxParaAlignTabPage::SvxParaAlignTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/paragalignpage.ui", "ParaAlignPage", &rSet) + , m_xLeft(m_xBuilder->weld_radio_button("radioBTN_LEFTALIGN")) + , m_xRight(m_xBuilder->weld_radio_button("radioBTN_RIGHTALIGN")) + , m_xCenter(m_xBuilder->weld_radio_button("radioBTN_CENTERALIGN")) + , m_xJustify(m_xBuilder->weld_radio_button("radioBTN_JUSTIFYALIGN")) + , m_xLeftBottom(m_xBuilder->weld_label("labelST_LEFTALIGN_ASIAN")) + , m_xRightTop(m_xBuilder->weld_label("labelST_RIGHTALIGN_ASIAN")) + , m_xLastLineFT(m_xBuilder->weld_label("labelLB_LASTLINE")) + , m_xLastLineLB(m_xBuilder->weld_combo_box("comboLB_LASTLINE")) + , m_xExpandCB(m_xBuilder->weld_check_button("checkCB_EXPAND")) + , m_xSnapToGridCB(m_xBuilder->weld_check_button("checkCB_SNAP")) + , m_xExampleWin(new weld::CustomWeld(*m_xBuilder, "drawingareaWN_EXAMPLE", m_aExampleWin)) + , m_xVertAlignFL(m_xBuilder->weld_widget("frameFL_VERTALIGN")) + , m_xVertAlignLB(m_xBuilder->weld_combo_box("comboLB_VERTALIGN")) + , m_xPropertiesFL(m_xBuilder->weld_widget("framePROPERTIES")) + , m_xTextDirectionLB(new svx::FrameDirectionListBox(m_xBuilder->weld_combo_box("comboLB_TEXTDIRECTION"))) +{ + SetExchangeSupport(); + + SvtLanguageOptions aLangOptions; + sal_uInt16 nLastLinePos = LASTLINEPOS_DEFAULT; + + if ( aLangOptions.IsAsianTypographyEnabled() ) + { + m_xLeft->set_label(m_xLeftBottom->get_label()); + m_xRight->set_label(m_xRightTop->get_label()); + + OUString sLeft(m_xLeft->get_label()); + sLeft = MnemonicGenerator::EraseAllMnemonicChars( sLeft ); + + if (m_xLastLineLB->get_count() == LASTLINECOUNT_OLD) + { + m_xLastLineLB->remove(0); + m_xLastLineLB->insert_text(0, sLeft); + } + else + nLastLinePos = LASTLINEPOS_LEFT; + } + + // remove "Default" or "Left" entry, depends on CJKOptions + if (m_xLastLineLB->get_count() == LASTLINECOUNT_NEW) + m_xLastLineLB->remove(nLastLinePos); + + Link aLink = LINK( this, SvxParaAlignTabPage, AlignHdl_Impl ); + m_xLeft->connect_toggled(aLink); + m_xRight->connect_toggled(aLink); + m_xCenter->connect_toggled(aLink); + m_xJustify->connect_toggled(aLink); + m_xLastLineLB->connect_changed(LINK(this, SvxParaAlignTabPage, LastLineHdl_Impl)); + m_xTextDirectionLB->connect_changed(LINK(this, SvxParaAlignTabPage, TextDirectionHdl_Impl)); + + m_xTextDirectionLB->append(SvxFrameDirection::Environment, SvxResId(RID_SVXSTR_FRAMEDIR_SUPER)); + m_xTextDirectionLB->append(SvxFrameDirection::Horizontal_LR_TB, SvxResId(RID_SVXSTR_FRAMEDIR_LTR)); + m_xTextDirectionLB->append(SvxFrameDirection::Horizontal_RL_TB, SvxResId(RID_SVXSTR_FRAMEDIR_RTL)); +} + +SvxParaAlignTabPage::~SvxParaAlignTabPage() +{ +} + +DeactivateRC SvxParaAlignTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if ( _pSet ) + FillItemSet( _pSet ); + return DeactivateRC::LeavePage; +} + +std::unique_ptr SvxParaAlignTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet) +{ + return std::make_unique(pPage, pController, *rSet); +} + +bool SvxParaAlignTabPage::FillItemSet( SfxItemSet* rOutSet ) +{ + bool bModified = false; + + bool bAdj = false; + SvxAdjust eAdjust = SvxAdjust::Left; + + if (m_xLeft->get_active()) + { + eAdjust = SvxAdjust::Left; + bAdj = m_xLeft->get_saved_state() == TRISTATE_FALSE; + } + else if (m_xRight->get_active()) + { + eAdjust = SvxAdjust::Right; + bAdj = m_xRight->get_saved_state() == TRISTATE_FALSE; + } + else if (m_xCenter->get_active()) + { + eAdjust = SvxAdjust::Center; + bAdj = m_xCenter->get_saved_state() == TRISTATE_FALSE; + } + else if (m_xJustify->get_active()) + { + eAdjust = SvxAdjust::Block; + bAdj = m_xJustify->get_saved_state() == TRISTATE_FALSE || + m_xExpandCB->get_state_changed_from_saved() || + m_xLastLineLB->get_value_changed_from_saved(); + } + + sal_uInt16 _nWhich = GetWhich( SID_ATTR_PARA_ADJUST ); + + if (bAdj) + { + SvxAdjust eOneWord = m_xExpandCB->get_active() ? SvxAdjust::Block : SvxAdjust::Left; + + int nLBPos = m_xLastLineLB->get_active(); + SvxAdjust eLastBlock = SvxAdjust::Left; + if ( 1 == nLBPos ) + eLastBlock = SvxAdjust::Center; + else if ( 2 == nLBPos ) + eLastBlock = SvxAdjust::Block; + + SvxAdjustItem aAdj( static_cast(GetItemSet().Get( _nWhich )) ); + aAdj.SetAdjust( eAdjust ); + aAdj.SetOneWord( eOneWord ); + aAdj.SetLastBlock( eLastBlock ); + rOutSet->Put( aAdj ); + bModified = true; + } + + if (m_xSnapToGridCB->get_state_changed_from_saved()) + { + rOutSet->Put(SvxParaGridItem(m_xSnapToGridCB->get_active(), GetWhich( SID_ATTR_PARA_SNAPTOGRID ))); + bModified = true; + } + + if (m_xVertAlignLB->get_value_changed_from_saved()) + { + rOutSet->Put(SvxParaVertAlignItem(static_cast(m_xVertAlignLB->get_active()), GetWhich( SID_PARA_VERTALIGN ))); + bModified = true; + } + + if (m_xTextDirectionLB->get_visible()) + { + if (m_xTextDirectionLB->get_value_changed_from_saved()) + { + SvxFrameDirection eDir = m_xTextDirectionLB->get_active_id(); + rOutSet->Put( SvxFrameDirectionItem( eDir, GetWhich( SID_ATTR_FRAMEDIRECTION ) ) ); + bModified = true; + } + } + + return bModified; +} + +void SvxParaAlignTabPage::ActivatePage( const SfxItemSet& rSet ) +{ + Reset( &rSet ); +} + +void SvxParaAlignTabPage::Reset( const SfxItemSet* rSet ) +{ + sal_uInt16 _nWhich = GetWhich( SID_ATTR_PARA_ADJUST ); + SfxItemState eItemState = rSet->GetItemState( _nWhich ); + + sal_Int32 nLBSelect = 0; + if ( eItemState >= SfxItemState::DEFAULT ) + { + const SvxAdjustItem& rAdj = static_cast(rSet->Get( _nWhich )); + + switch ( rAdj.GetAdjust() /*!!! ask VB rAdj.GetLastBlock()*/ ) + { + case SvxAdjust::Left: m_xLeft->set_active(true); break; + + case SvxAdjust::Right: m_xRight->set_active(true); break; + + case SvxAdjust::Center: m_xCenter->set_active(true); break; + + case SvxAdjust::Block: m_xJustify->set_active(true); break; + default: ; //prevent warning + } + bool bEnable = m_xJustify->get_active(); + m_xLastLineFT->set_sensitive(bEnable); + m_xLastLineLB->set_sensitive(bEnable); + + switch(rAdj.GetLastBlock()) + { + case SvxAdjust::Left: nLBSelect = 0; break; + + case SvxAdjust::Center: nLBSelect = 1; break; + + case SvxAdjust::Block: nLBSelect = 2; break; + default: ; //prevent warning + } + m_xExpandCB->set_sensitive(bEnable && nLBSelect == 2); + m_xExpandCB->set_active(SvxAdjust::Block == rAdj.GetOneWord()); + } + else + { + m_xLeft->set_active(false); + m_xRight->set_active(false); + m_xCenter->set_active(false); + m_xJustify->set_active(false); + } + m_xLastLineLB->set_active(nLBSelect); + + sal_uInt16 nHtmlMode = GetHtmlMode_Impl(*rSet); + if(nHtmlMode & HTMLMODE_ON) + { + m_xLastLineLB->hide(); + m_xLastLineFT->hide(); + m_xExpandCB->hide(); + if(!(nHtmlMode & HTMLMODE_FULL_STYLES) ) + m_xJustify->set_sensitive(false); + m_xSnapToGridCB->hide(); + } + _nWhich = GetWhich(SID_ATTR_PARA_SNAPTOGRID); + eItemState = rSet->GetItemState( _nWhich ); + if ( eItemState >= SfxItemState::DEFAULT ) + { + const SvxParaGridItem& rSnap = static_cast(rSet->Get( _nWhich )); + m_xSnapToGridCB->set_active(rSnap.GetValue()); + } + + _nWhich = GetWhich( SID_PARA_VERTALIGN ); + eItemState = rSet->GetItemState( _nWhich ); + + if ( eItemState >= SfxItemState::DEFAULT ) + { + m_xVertAlignFL->show(); + + const SvxParaVertAlignItem& rAlign = static_cast(rSet->Get( _nWhich )); + + m_xVertAlignLB->set_active(static_cast(rAlign.GetValue())); + } + + _nWhich = GetWhich( SID_ATTR_FRAMEDIRECTION ); + //text direction + if( SfxItemState::DEFAULT <= rSet->GetItemState( _nWhich ) ) + { + const SvxFrameDirectionItem& rFrameDirItem = static_cast( rSet->Get( _nWhich ) ); + m_xTextDirectionLB->set_active_id(rFrameDirItem.GetValue()); + m_xTextDirectionLB->save_value(); + } + + m_xSnapToGridCB->save_state(); + m_xVertAlignLB->save_value(); + m_xLeft->save_state(); + m_xRight->save_state(); + m_xCenter->save_state(); + m_xJustify->save_state(); + m_xLastLineLB->save_value(); + m_xExpandCB->save_state(); + + UpdateExample_Impl(); +} + +void SvxParaAlignTabPage::ChangesApplied() +{ + m_xTextDirectionLB->save_value(); + m_xSnapToGridCB->save_state(); + m_xVertAlignLB->save_value(); + m_xLeft->save_state(); + m_xRight->save_state(); + m_xCenter->save_state(); + m_xJustify->save_state(); + m_xLastLineLB->save_value(); + m_xExpandCB->save_state(); +} + +IMPL_LINK_NOARG(SvxParaAlignTabPage, AlignHdl_Impl, weld::ToggleButton&, void) +{ + bool bJustify = m_xJustify->get_active(); + m_xLastLineFT->set_sensitive(bJustify); + m_xLastLineLB->set_sensitive(bJustify); + bool bLastLineIsBlock = m_xLastLineLB->get_active() == 2; + m_xExpandCB->set_sensitive(bJustify && bLastLineIsBlock); + //set last line listbox to entry position 0 if not enabled + if (!m_xLastLineLB->get_sensitive()) + m_xLastLineLB->set_active(0); + //uncheck 'Expand ... word' when check box is not enabled + if (!m_xExpandCB->get_sensitive()) + m_xExpandCB->set_active(false); + UpdateExample_Impl(); +} + +IMPL_LINK_NOARG(SvxParaAlignTabPage, LastLineHdl_Impl, weld::ComboBox&, void) +{ + //fdo#41350 only enable 'Expand last word' if last line is also justified + bool bLastLineIsBlock = m_xLastLineLB->get_active() == 2; + m_xExpandCB->set_sensitive(bLastLineIsBlock); + //uncheck 'Expand ... word' when check box is not enabled + if (!m_xExpandCB->get_sensitive()) + m_xExpandCB->set_active(false); + UpdateExample_Impl(); +} + +IMPL_LINK_NOARG(SvxParaAlignTabPage, TextDirectionHdl_Impl, weld::ComboBox&, void) +{ + UpdateExample_Impl(); +} + +void SvxParaAlignTabPage::UpdateExample_Impl() +{ + if (m_xLeft->get_active()) + { + m_aExampleWin.EnableRTL(false); + m_aExampleWin.SetAdjust(SvxAdjust::Left); + m_aExampleWin.SetLastLine(SvxAdjust::Left); + } + else if (m_xRight->get_active()) + { + m_aExampleWin.EnableRTL(true); + m_aExampleWin.SetAdjust(SvxAdjust::Left); + m_aExampleWin.SetLastLine(SvxAdjust::Left); + } + else + { + SvxFrameDirection eDir = m_xTextDirectionLB->get_active_id(); + switch ( eDir ) + { + case SvxFrameDirection::Environment : + if ( !m_xRight->get_active() ) + m_aExampleWin.EnableRTL( AllSettings::GetLayoutRTL() ); + break; + case SvxFrameDirection::Horizontal_RL_TB : + if ( !m_xLeft->get_active() ) + m_aExampleWin.EnableRTL( true ); + break; + case SvxFrameDirection::Horizontal_LR_TB : + if ( !m_xRight->get_active() ) + m_aExampleWin.EnableRTL( false ); + break; + default: ; //prevent warning + } + if (m_xCenter->get_active()) + m_aExampleWin.SetAdjust( SvxAdjust::Center ); + else if (m_xJustify->get_active()) + { + m_aExampleWin.SetAdjust( SvxAdjust::Block ); + int nLBPos = m_xLastLineLB->get_active(); + if (nLBPos == 0) + m_aExampleWin.SetLastLine(SvxAdjust::Left); + else if (nLBPos == 1) + m_aExampleWin.SetLastLine(SvxAdjust::Center); + else if (nLBPos == 2) + m_aExampleWin.SetLastLine(SvxAdjust::Block); + } + } + + m_aExampleWin.Invalidate(); +} + +void SvxParaAlignTabPage::EnableJustifyExt() +{ + m_xLastLineFT->show(); + m_xLastLineLB->show(); + m_xExpandCB->show(); + SvtLanguageOptions aCJKOptions; + if (aCJKOptions.IsAsianTypographyEnabled()) + m_xSnapToGridCB->show(); + +} + +void SvxParaAlignTabPage::PageCreated (const SfxAllItemSet& aSet) +{ + const SfxBoolItem* pBoolItem = aSet.GetItem(SID_SVXPARAALIGNTABPAGE_ENABLEJUSTIFYEXT, false); + if (pBoolItem && pBoolItem->GetValue()) + EnableJustifyExt(); +} + +std::unique_ptr SvxExtParagraphTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet) +{ + return std::make_unique(pPage, pController, *rSet); +} + +bool SvxExtParagraphTabPage::FillItemSet( SfxItemSet* rOutSet ) +{ + bool bModified = false; + sal_uInt16 _nWhich = GetWhich( SID_ATTR_PARA_HYPHENZONE ); + const TriState eHyphenState = m_xHyphenBox->get_state(); + const SfxPoolItem* pOld = GetOldItem( *rOutSet, SID_ATTR_PARA_HYPHENZONE ); + + if ( m_xHyphenBox->get_state_changed_from_saved() || + m_xHyphenNoCapsBox->get_state_changed_from_saved() || + m_xExtHyphenBeforeBox->get_value_changed_from_saved() || + m_xExtHyphenAfterBox->get_value_changed_from_saved() || + m_xMaxHyphenEdit->get_value_changed_from_saved() ) + { + SvxHyphenZoneItem aHyphen( + static_cast(GetItemSet().Get( _nWhich )) ); + aHyphen.SetHyphen( eHyphenState == TRISTATE_TRUE ); + aHyphen.SetNoCapsHyphenation(m_xHyphenNoCapsBox->get_state() == TRISTATE_TRUE); + + if ( eHyphenState == TRISTATE_TRUE ) + { + aHyphen.GetMinLead() = static_cast(m_xExtHyphenBeforeBox->get_value()); + aHyphen.GetMinTrail() = static_cast(m_xExtHyphenAfterBox->get_value()); + } + aHyphen.GetMaxHyphens() = static_cast(m_xMaxHyphenEdit->get_value()); + + if ( !pOld || + *static_cast(pOld) != aHyphen || + m_xHyphenBox->get_state_changed_from_saved()) + { + rOutSet->Put( aHyphen ); + bModified = true; + } + } + + if (m_xPageNumBox->get_sensitive() + && (m_xPageNumBox->get_state_changed_from_saved() || m_xPagenumEdit->get_value_changed_from_saved())) + { + pOld = GetOldItem( *rOutSet, SID_ATTR_PARA_PAGENUM ); + + if (TRISTATE_TRUE == m_xPageNumBox->get_state() + && (!pOld || IsInvalidItem(pOld) + || static_cast(pOld)->GetValue() != m_xPagenumEdit->get_value())) + { + SfxUInt16Item aPageNum(SID_ATTR_PARA_PAGENUM, + static_cast(m_xPagenumEdit->get_value())); + rOutSet->Put( aPageNum ); + bModified = true; + } + else if (TRISTATE_FALSE == m_xPageNumBox->get_state() + && (pOld || IsInvalidItem(pOld))) + { + // need to tell sw to remove the item + rOutSet->DisableItem(SID_ATTR_PARA_PAGENUM); + bModified = true; + } + } + + // pagebreak + + TriState eState = m_xApplyCollBtn->get_state(); + bool bIsPageModel = false; + + _nWhich = GetWhich( SID_ATTR_PARA_MODEL ); + OUString sPage; + if ( m_xApplyCollBtn->get_state_changed_from_saved() || + ( TRISTATE_TRUE == eState && + m_xApplyCollBox->get_value_changed_from_saved() ) ) + { + if ( eState == TRISTATE_TRUE ) + { + sPage = m_xApplyCollBox->get_active_text(); + bIsPageModel = !sPage.isEmpty(); + } + pOld = GetOldItem( *rOutSet, SID_ATTR_PARA_MODEL ); + + if ( !pOld || static_cast(pOld)->GetValue() != sPage ) + { + rOutSet->Put( SvxPageModelItem( sPage, false, _nWhich ) ); + bModified = true; + } + else + bIsPageModel = false; + } + else if(TRISTATE_TRUE == eState && m_xApplyCollBtn->get_sensitive()) + bIsPageModel = true; + else + rOutSet->Put( SvxPageModelItem( sPage, false, _nWhich ) ); + + _nWhich = GetWhich( SID_ATTR_PARA_PAGEBREAK ); + + if ( bIsPageModel ) + // if PageModel is turned on, always turn off PageBreak + rOutSet->Put( SvxFormatBreakItem( SvxBreak::NONE, _nWhich ) ); + else + { + eState = m_xPageBreakBox->get_state(); + SfxItemState eModelState = GetItemSet().GetItemState(SID_ATTR_PARA_MODEL, false); + + if ( (eModelState == SfxItemState::SET && TRISTATE_TRUE == m_xPageBreakBox->get_state()) || + m_xPageBreakBox->get_state_changed_from_saved() || + m_xBreakTypeLB->get_value_changed_from_saved() || + m_xBreakPositionLB->get_value_changed_from_saved() ) + { + const SvxFormatBreakItem rOldBreak( + static_cast(GetItemSet().Get( _nWhich ))); + SvxFormatBreakItem aBreak(rOldBreak.GetBreak(), rOldBreak.Which()); + + switch ( eState ) + { + case TRISTATE_TRUE: + { + bool bBefore = m_xBreakPositionLB->get_active() == 0; + + if (m_xBreakTypeLB->get_active() == 0) + { + if ( bBefore ) + aBreak.SetValue( SvxBreak::PageBefore ); + else + aBreak.SetValue( SvxBreak::PageAfter ); + } + else + { + if ( bBefore ) + aBreak.SetValue( SvxBreak::ColumnBefore ); + else + aBreak.SetValue( SvxBreak::ColumnAfter ); + } + break; + } + + case TRISTATE_FALSE: + aBreak.SetValue( SvxBreak::NONE ); + break; + default: ; //prevent warning + } + pOld = GetOldItem( *rOutSet, SID_ATTR_PARA_PAGEBREAK ); + + if ( eState != m_xPageBreakBox->get_saved_state() || + !pOld || !( *static_cast(pOld) == aBreak ) ) + { + bModified = true; + rOutSet->Put( aBreak ); + } + } + } + + // paragraph split + _nWhich = GetWhich( SID_ATTR_PARA_SPLIT ); + eState = m_xKeepTogetherBox->get_state(); + + if (m_xKeepTogetherBox->get_state_changed_from_saved()) + { + pOld = GetOldItem( *rOutSet, SID_ATTR_PARA_SPLIT ); + + if ( !pOld || static_cast(pOld)->GetValue() != + ( eState == TRISTATE_FALSE ) ) + { + rOutSet->Put( SvxFormatSplitItem( eState == TRISTATE_FALSE, _nWhich ) ); + bModified = true; + } + } + + // keep paragraphs + _nWhich = GetWhich( SID_ATTR_PARA_KEEP ); + eState = m_xKeepParaBox->get_state(); + + if (m_xKeepParaBox->get_state_changed_from_saved()) + { + // if the status has changed, putting is necessary + rOutSet->Put( SvxFormatKeepItem( eState == TRISTATE_TRUE, _nWhich ) ); + bModified = true; + } + + // widows and orphans + _nWhich = GetWhich( SID_ATTR_PARA_WIDOWS ); + eState = m_xWidowBox->get_state(); + + if ( m_xWidowBox->get_state_changed_from_saved() || + m_xWidowRowNo->get_value_changed_from_saved() ) + { + SvxWidowsItem rItem( eState == TRISTATE_TRUE ? + static_cast(m_xWidowRowNo->get_value()) : 0, _nWhich ); + pOld = GetOldItem( *rOutSet, SID_ATTR_PARA_WIDOWS ); + + if ( m_xWidowBox->get_state_changed_from_saved() || !pOld || !( *static_cast(pOld) == rItem ) ) + { + rOutSet->Put( rItem ); + bModified = true; + } + } + + _nWhich = GetWhich( SID_ATTR_PARA_ORPHANS ); + eState = m_xOrphanBox->get_state(); + + if ( m_xOrphanBox->get_state_changed_from_saved() || + m_xOrphanRowNo->get_value_changed_from_saved() ) + { + SvxOrphansItem rItem( eState == TRISTATE_TRUE ? + static_cast(m_xOrphanRowNo->get_value()) : 0, _nWhich ); + pOld = GetOldItem( *rOutSet, SID_ATTR_PARA_ORPHANS ); + + if ( m_xOrphanBox->get_state_changed_from_saved() || + !pOld || + !( *static_cast(pOld) == rItem ) ) + { + rOutSet->Put( rItem ); + bModified = true; + } + } + + return bModified; +} +void SvxExtParagraphTabPage::Reset( const SfxItemSet* rSet ) +{ + sal_uInt16 _nWhich = GetWhich( SID_ATTR_PARA_HYPHENZONE ); + SfxItemState eItemState = rSet->GetItemState( _nWhich ); + + bool bItemAvailable = eItemState >= SfxItemState::DEFAULT; + bool bIsHyphen = false; + if( !bHtmlMode && bItemAvailable ) + { + const SvxHyphenZoneItem& rHyphen = + static_cast(rSet->Get( _nWhich )); + aHyphenState.bTriStateEnabled = false; + + bIsHyphen = rHyphen.IsHyphen(); + m_xHyphenBox->set_state(bIsHyphen ? TRISTATE_TRUE : TRISTATE_FALSE); + m_xHyphenNoCapsBox->set_state(rHyphen.IsNoCapsHyphenation() ? TRISTATE_TRUE : TRISTATE_FALSE); + + m_xExtHyphenBeforeBox->set_value(rHyphen.GetMinLead()); + m_xExtHyphenAfterBox->set_value(rHyphen.GetMinTrail()); + m_xMaxHyphenEdit->set_value(rHyphen.GetMaxHyphens()); + } + else + { + m_xHyphenBox->set_state(TRISTATE_INDET); + m_xHyphenNoCapsBox->set_state(TRISTATE_INDET); + } + bool bEnable = bItemAvailable && bIsHyphen; + m_xHyphenNoCapsBox->set_sensitive(bEnable); + m_xExtHyphenBeforeBox->set_sensitive(bEnable); + m_xExtHyphenAfterBox->set_sensitive(bEnable); + m_xBeforeText->set_sensitive(bEnable); + m_xAfterText->set_sensitive(bEnable); + m_xMaxHyphenLabel->set_sensitive(bEnable); + m_xMaxHyphenEdit->set_sensitive(bEnable); + + _nWhich = GetWhich( SID_ATTR_PARA_PAGENUM ); + + switch (rSet->GetItemState(_nWhich)) + { + case SfxItemState::SET: + { + aPageNumState.bTriStateEnabled = false; + m_xPageNumBox->set_state(TRISTATE_TRUE); + SfxUInt16Item const*const pItem(rSet->GetItem(_nWhich)); + const sal_uInt16 nPageNum(pItem->GetValue()); + m_xPagenumEdit->set_value(nPageNum); + break; + } + case SfxItemState::DONTCARE: + { + aPageNumState.bTriStateEnabled = true; + m_xPageNumBox->set_state(TRISTATE_INDET); + break; + } + case SfxItemState::UNKNOWN: + case SfxItemState::DEFAULT: + case SfxItemState::DISABLED: + { + aPageNumState.bTriStateEnabled = false; + m_xPageNumBox->set_state(TRISTATE_FALSE); + break; + } + default: + assert(false); // unexpected + break; + } + + if ( bPageBreak ) + { + // first handle PageModel + _nWhich = GetWhich( SID_ATTR_PARA_MODEL ); + bool bIsPageModel = false; + eItemState = rSet->GetItemState( _nWhich ); + + if ( eItemState >= SfxItemState::SET ) + { + aApplyCollState.bTriStateEnabled = false; + + const SvxPageModelItem& rModel = + static_cast(rSet->Get( _nWhich )); + const OUString& aStr( rModel.GetValue() ); + + if (!aStr.isEmpty() && m_xApplyCollBox->find_text(aStr) != -1) + { + m_xApplyCollBox->set_active_text(aStr); + m_xApplyCollBtn->set_state(TRISTATE_TRUE); + bIsPageModel = true; + + m_xPageBreakBox->set_sensitive(true); + aPageBreakState.bTriStateEnabled = false; + m_xBreakTypeFT->set_sensitive(true); + m_xBreakTypeLB->set_sensitive(true); + m_xBreakPositionFT->set_sensitive(true); + m_xBreakPositionLB->set_sensitive(true); + m_xApplyCollBtn->set_sensitive(false); + m_xPageBreakBox->set_state(TRISTATE_TRUE); + + //select page break + m_xBreakTypeLB->set_active(0); + //select break before + m_xBreakPositionLB->set_active(0); + } + else + { + m_xApplyCollBox->set_active(-1); + m_xApplyCollBtn->set_state(TRISTATE_FALSE); + } + } + else if ( SfxItemState::DONTCARE == eItemState ) + { + aApplyCollState.bTriStateEnabled = true; + m_xApplyCollBtn->set_state(TRISTATE_INDET); + m_xApplyCollBox->set_active(-1); + } + else + { + m_xApplyCollBtn->set_sensitive(false); + m_xApplyCollBox->set_sensitive(false); + m_xPagenumEdit->set_sensitive(false); + m_xPageNumBox->set_sensitive(false); + } + + if ( !bIsPageModel ) + { + _nWhich = GetWhich( SID_ATTR_PARA_PAGEBREAK ); + eItemState = rSet->GetItemState( _nWhich ); + + if ( eItemState >= SfxItemState::DEFAULT ) + { + const SvxFormatBreakItem& rPageBreak = + static_cast(rSet->Get( _nWhich )); + + SvxBreak eBreak = rPageBreak.GetBreak(); + + // PageBreak not via CTRL-RETURN, + // then CheckBox can be freed + m_xPageBreakBox->set_sensitive(true); + aPageBreakState.bTriStateEnabled = false; + m_xBreakTypeFT->set_sensitive(true); + m_xBreakTypeLB->set_sensitive(true); + m_xBreakPositionFT->set_sensitive(true); + m_xBreakPositionLB->set_sensitive(true); + + m_xPageBreakBox->set_state(TRISTATE_TRUE); + + bool _bEnable = eBreak != SvxBreak::NONE && + eBreak != SvxBreak::ColumnBefore && + eBreak != SvxBreak::ColumnAfter; + m_xApplyCollBtn->set_sensitive(_bEnable); + if (!_bEnable) + { + m_xApplyCollBox->set_sensitive(_bEnable); + m_xPageNumBox->set_sensitive(false); + m_xPagenumEdit->set_sensitive(_bEnable); + } + + if ( eBreak == SvxBreak::NONE ) + m_xPageBreakBox->set_state(TRISTATE_FALSE); + + sal_Int32 nType = 0; // selection position in break type ListBox : Page + sal_Int32 nPosition = 0; // selection position in break position ListBox : Before + switch ( eBreak ) + { + case SvxBreak::PageBefore: + break; + case SvxBreak::PageAfter: + nPosition = 1; + break; + case SvxBreak::ColumnBefore: + nType = 1; + break; + case SvxBreak::ColumnAfter: + nType = 1; + nPosition = 1; + break; + default: ;//prevent warning + } + m_xBreakTypeLB->set_active(nType); + m_xBreakPositionLB->set_active(nPosition); + } + else if ( SfxItemState::DONTCARE == eItemState ) + m_xPageBreakBox->set_state(TRISTATE_INDET); + else + { + m_xPageBreakBox->set_sensitive(false); + m_xBreakTypeFT->set_sensitive(false); + m_xBreakTypeLB->set_sensitive(false); + m_xBreakPositionFT->set_sensitive(false); + m_xBreakPositionLB->set_sensitive(false); + } + } + + PageBreakPosHdl_Impl(*m_xBreakPositionLB); + PageBreakHdl(); + } + + _nWhich = GetWhich( SID_ATTR_PARA_KEEP ); + eItemState = rSet->GetItemState( _nWhich ); + + if ( eItemState >= SfxItemState::DEFAULT ) + { + aKeepParaState.bTriStateEnabled = false; + const SvxFormatKeepItem& rKeep = + static_cast(rSet->Get( _nWhich )); + + if ( rKeep.GetValue() ) + m_xKeepParaBox->set_state(TRISTATE_TRUE); + else + m_xKeepParaBox->set_state(TRISTATE_FALSE); + } + else if ( SfxItemState::DONTCARE == eItemState ) + m_xKeepParaBox->set_state(TRISTATE_INDET); + else + m_xKeepParaBox->set_sensitive(false); + + _nWhich = GetWhich( SID_ATTR_PARA_SPLIT ); + eItemState = rSet->GetItemState( _nWhich ); + + if ( eItemState >= SfxItemState::DEFAULT ) + { + const SvxFormatSplitItem& rSplit = + static_cast(rSet->Get( _nWhich )); + aKeepTogetherState.bTriStateEnabled = false; + + if ( !rSplit.GetValue() ) + m_xKeepTogetherBox->set_state(TRISTATE_TRUE); + else + { + m_xKeepTogetherBox->set_state(TRISTATE_FALSE); + + // widows and orphans + m_xWidowBox->set_sensitive(true); + _nWhich = GetWhich( SID_ATTR_PARA_WIDOWS ); + SfxItemState eTmpState = rSet->GetItemState( _nWhich ); + + if ( eTmpState >= SfxItemState::DEFAULT ) + { + const SvxWidowsItem& rWidow = + static_cast(rSet->Get( _nWhich )); + aWidowState.bTriStateEnabled = false; + const sal_uInt16 nLines = rWidow.GetValue(); + + bool _bEnable = nLines > 0; + m_xWidowRowNo->set_value(m_xWidowRowNo->normalize(nLines)); + m_xWidowBox->set_state(_bEnable ? TRISTATE_TRUE : TRISTATE_FALSE); + m_xWidowRowNo->set_sensitive(_bEnable); + //m_xWidowRowLabel->set_sensitive(_bEnable); + + } + else if ( SfxItemState::DONTCARE == eTmpState ) + m_xWidowBox->set_state( TRISTATE_INDET ); + else + m_xWidowBox->set_sensitive(false); + + m_xOrphanBox->set_sensitive(true); + _nWhich = GetWhich( SID_ATTR_PARA_ORPHANS ); + eTmpState = rSet->GetItemState( _nWhich ); + + if ( eTmpState >= SfxItemState::DEFAULT ) + { + const SvxOrphansItem& rOrphan = + static_cast(rSet->Get( _nWhich )); + const sal_uInt16 nLines = rOrphan.GetValue(); + aOrphanState.bTriStateEnabled = false; + + bool _bEnable = nLines > 0; + m_xOrphanBox->set_state(_bEnable ? TRISTATE_TRUE : TRISTATE_FALSE); + m_xOrphanRowNo->set_value(m_xOrphanRowNo->normalize(nLines)); + m_xOrphanRowNo->set_sensitive(_bEnable); + m_xOrphanRowLabel->set_sensitive(_bEnable); + + } + else if ( SfxItemState::DONTCARE == eTmpState ) + m_xOrphanBox->set_state(TRISTATE_INDET); + else + m_xOrphanBox->set_sensitive(false); + aOrphanState.eState = m_xOrphanBox->get_state(); + } + } + else if ( SfxItemState::DONTCARE == eItemState ) + m_xKeepTogetherBox->set_state(TRISTATE_INDET); + else + m_xKeepTogetherBox->set_sensitive(false); + + // so that everything is enabled correctly + KeepTogetherHdl(); + WidowHdl(); + OrphanHdl(); + ChangesApplied(); +} +void SvxExtParagraphTabPage::ChangesApplied() +{ + m_xHyphenBox->save_state(); + m_xHyphenNoCapsBox->save_state(); + m_xExtHyphenBeforeBox->set_value(m_xExtHyphenBeforeBox->get_value()); + m_xExtHyphenAfterBox->set_value(m_xExtHyphenAfterBox->get_value()); + m_xMaxHyphenEdit->set_value(m_xMaxHyphenEdit->get_value()); + m_xPageBreakBox->save_state(); + m_xBreakPositionLB->save_value(); + m_xBreakTypeLB->save_value(); + m_xApplyCollBtn->save_state(); + m_xApplyCollBox->save_value(); + m_xPageNumBox->save_state(); + m_xPagenumEdit->save_value(); + m_xKeepTogetherBox->save_state(); + m_xKeepParaBox->save_state(); + m_xWidowBox->save_state(); + m_xOrphanBox->save_state(); + m_xOrphanRowNo->save_value(); + m_xWidowRowNo->save_value(); +} + +DeactivateRC SvxExtParagraphTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if ( _pSet ) + FillItemSet( _pSet ); + return DeactivateRC::LeavePage; +} + +void SvxExtParagraphTabPage::DisablePageBreak() +{ + bPageBreak = false; + m_xPageBreakBox->set_sensitive(false); + m_xBreakTypeLB->remove(0); + m_xBreakPositionFT->set_sensitive(false); + m_xBreakPositionLB->set_sensitive(false); + m_xApplyCollBtn->set_sensitive(false); + m_xApplyCollBox->set_sensitive(false); + m_xPageNumBox->set_sensitive(false); + m_xPagenumEdit->set_sensitive(false); +} + +SvxExtParagraphTabPage::SvxExtParagraphTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rAttr) + : SfxTabPage(pPage, pController, "cui/ui/textflowpage.ui", "TextFlowPage", &rAttr) + , bPageBreak(true) + , bHtmlMode(false) + , nStdPos(0) + // Hyphenation + , m_xHyphenBox(m_xBuilder->weld_check_button("checkAuto")) + , m_xHyphenNoCapsBox(m_xBuilder->weld_check_button("checkNoCaps")) + , m_xBeforeText(m_xBuilder->weld_label("labelLineBegin")) + , m_xExtHyphenBeforeBox(m_xBuilder->weld_spin_button("spinLineEnd")) + , m_xAfterText(m_xBuilder->weld_label("labelLineEnd")) + , m_xExtHyphenAfterBox(m_xBuilder->weld_spin_button("spinLineBegin")) + , m_xMaxHyphenLabel(m_xBuilder->weld_label("labelMaxNum")) + , m_xMaxHyphenEdit(m_xBuilder->weld_spin_button("spinMaxNum")) + //Page break + , m_xPageBreakBox(m_xBuilder->weld_check_button("checkInsert")) + , m_xBreakTypeFT(m_xBuilder->weld_label("labelType")) + , m_xBreakTypeLB(m_xBuilder->weld_combo_box("comboBreakType")) + , m_xBreakPositionFT(m_xBuilder->weld_label("labelPosition")) + , m_xBreakPositionLB(m_xBuilder->weld_combo_box("comboBreakPosition")) + , m_xApplyCollBtn(m_xBuilder->weld_check_button("checkPageStyle")) + , m_xApplyCollBox(m_xBuilder->weld_combo_box("comboPageStyle")) + , m_xPageNumBox(m_xBuilder->weld_check_button("labelPageNum")) + , m_xPagenumEdit(m_xBuilder->weld_spin_button("spinPageNumber")) + // Options + , m_xKeepTogetherBox(m_xBuilder->weld_check_button("checkSplitPara")) + , m_xKeepParaBox(m_xBuilder->weld_check_button("checkKeepPara")) + , m_xOrphanBox(m_xBuilder->weld_check_button("checkOrphan")) + , m_xOrphanRowNo(m_xBuilder->weld_spin_button("spinOrphan")) + , m_xOrphanRowLabel(m_xBuilder->weld_label("labelOrphan")) + , m_xWidowBox(m_xBuilder->weld_check_button("checkWidow")) + , m_xWidowRowNo(m_xBuilder->weld_spin_button("spinWidow")) + , m_xWidowRowLabel(m_xBuilder->weld_label("labelWidow")) +{ + // this page needs ExchangeSupport + SetExchangeSupport(); + + m_xHyphenBox->connect_toggled(LINK(this, SvxExtParagraphTabPage, HyphenClickHdl_Impl)); + m_xPageBreakBox->connect_toggled(LINK(this, SvxExtParagraphTabPage, PageBreakHdl_Impl)); + m_xKeepTogetherBox->connect_toggled(LINK(this, SvxExtParagraphTabPage, KeepTogetherHdl_Impl)); + m_xWidowBox->connect_toggled(LINK(this, SvxExtParagraphTabPage, WidowHdl_Impl)); + m_xOrphanBox->connect_toggled(LINK(this, SvxExtParagraphTabPage, OrphanHdl_Impl)); + m_xApplyCollBtn->connect_toggled(LINK(this, SvxExtParagraphTabPage, ApplyCollClickHdl_Impl)); + m_xBreakTypeLB->connect_changed(LINK(this, SvxExtParagraphTabPage, PageBreakTypeHdl_Impl)); + m_xBreakPositionLB->connect_changed(LINK(this, SvxExtParagraphTabPage, PageBreakPosHdl_Impl)); + m_xPageNumBox->connect_toggled(LINK(this, SvxExtParagraphTabPage, PageNumBoxClickHdl_Impl)); + m_xKeepParaBox->connect_toggled(LINK(this, SvxExtParagraphTabPage, KeepParaBoxClickHdl_Impl)); + + SfxObjectShell* pSh = SfxObjectShell::Current(); + if ( pSh ) + { + SfxStyleSheetBasePool* pPool = pSh->GetStyleSheetPool(); + SfxStyleSheetBase* pStyle = pPool->First(SfxStyleFamily::Page); + OUString aStdName; + + while( pStyle ) + { + if ( aStdName.isEmpty() ) + // first style == standard style + aStdName = pStyle->GetName(); + m_xApplyCollBox->append_text(pStyle->GetName()); + pStyle = pPool->Next(); + } + nStdPos = m_xApplyCollBox->find_text(aStdName); + } + + sal_uInt16 nHtmlMode = GetHtmlMode_Impl( rAttr ); + if ( !(nHtmlMode & HTMLMODE_ON) ) + return; + + bHtmlMode = true; + m_xHyphenBox->set_sensitive(false); + m_xHyphenNoCapsBox->set_sensitive(false); + m_xBeforeText->set_sensitive(false); + m_xExtHyphenBeforeBox->set_sensitive(false); + m_xAfterText->set_sensitive(false); + m_xExtHyphenAfterBox->set_sensitive(false); + m_xMaxHyphenLabel->set_sensitive(false); + m_xMaxHyphenEdit->set_sensitive(false); + m_xPageNumBox->set_sensitive(false); + m_xPagenumEdit->set_sensitive(false); + // no column break in HTML + m_xBreakTypeLB->remove(1); +} + +SvxExtParagraphTabPage::~SvxExtParagraphTabPage() +{ +} + +void SvxExtParagraphTabPage::PageBreakHdl() +{ + switch (m_xPageBreakBox->get_state()) + { + case TRISTATE_TRUE: + m_xBreakTypeFT->set_sensitive(true); + m_xBreakTypeLB->set_sensitive(true); + m_xBreakPositionFT->set_sensitive(true); + m_xBreakPositionLB->set_sensitive(true); + + if (0 == m_xBreakTypeLB->get_active() && 0 == m_xBreakPositionLB->get_active()) + { + m_xApplyCollBtn->set_sensitive(true); + + bool bEnable = TRISTATE_TRUE == m_xApplyCollBtn->get_state() && + m_xApplyCollBox->get_count(); + m_xApplyCollBox->set_sensitive(bEnable); + if(!bHtmlMode) + { + m_xPageNumBox->set_sensitive(bEnable); + m_xPagenumEdit->set_sensitive(bEnable && m_xPageNumBox->get_state() == TRISTATE_TRUE); + } + } + break; + + case TRISTATE_FALSE: + case TRISTATE_INDET: + m_xApplyCollBtn->set_state(TRISTATE_FALSE); + m_xApplyCollBtn->set_sensitive(false); + m_xApplyCollBox->set_sensitive(false); + m_xPageNumBox->set_sensitive(false); + m_xPagenumEdit->set_sensitive(false); + m_xBreakTypeFT->set_sensitive(false); + m_xBreakTypeLB->set_sensitive(false); + m_xBreakPositionFT->set_sensitive(false); + m_xBreakPositionLB->set_sensitive(false); + break; + } +} + +IMPL_LINK(SvxExtParagraphTabPage, PageBreakHdl_Impl, weld::ToggleButton&, rToggle, void) +{ + aPageBreakState.ButtonToggled(rToggle); + PageBreakHdl(); +} + +void SvxExtParagraphTabPage::KeepTogetherHdl() +{ + bool bEnable = m_xKeepTogetherBox->get_state() == TRISTATE_FALSE; + m_xWidowBox->set_sensitive(bEnable); + m_xOrphanBox->set_sensitive(bEnable); +} + +IMPL_LINK(SvxExtParagraphTabPage, KeepTogetherHdl_Impl, weld::ToggleButton&, rToggle, void) +{ + aKeepTogetherState.ButtonToggled(rToggle); + KeepTogetherHdl(); +} + +void SvxExtParagraphTabPage::WidowHdl() +{ + switch (m_xWidowBox->get_state()) + { + case TRISTATE_TRUE: + m_xWidowRowNo->set_sensitive(true); + m_xWidowRowLabel->set_sensitive(true); + m_xKeepTogetherBox->set_sensitive(false); + break; + case TRISTATE_FALSE: + if (m_xOrphanBox->get_state() == TRISTATE_FALSE) + m_xKeepTogetherBox->set_sensitive(true); + [[fallthrough]]; + case TRISTATE_INDET: + m_xWidowRowNo->set_sensitive(false); + m_xWidowRowLabel->set_sensitive(false); + break; + } +} + +IMPL_LINK(SvxExtParagraphTabPage, WidowHdl_Impl, weld::ToggleButton&, rToggle, void) +{ + aWidowState.ButtonToggled(rToggle); + WidowHdl(); +} + +IMPL_LINK(SvxExtParagraphTabPage, OrphanHdl_Impl, weld::ToggleButton&, rToggle, void) +{ + aOrphanState.ButtonToggled(rToggle); + OrphanHdl(); +} + +void SvxExtParagraphTabPage::OrphanHdl() +{ + switch (m_xOrphanBox->get_state()) + { + case TRISTATE_TRUE: + m_xOrphanRowNo->set_sensitive(true); + m_xOrphanRowLabel->set_sensitive(true); + m_xKeepTogetherBox->set_sensitive(false); + break; + + case TRISTATE_FALSE: + if (m_xWidowBox->get_state() == TRISTATE_FALSE) + m_xKeepTogetherBox->set_sensitive(true); + [[fallthrough]]; + case TRISTATE_INDET: + m_xOrphanRowNo->set_sensitive(false); + m_xOrphanRowLabel->set_sensitive(false); + break; + } +} + +void SvxExtParagraphTabPage::HyphenClickHdl() +{ + bool bEnable = m_xHyphenBox->get_state() == TRISTATE_TRUE; + m_xHyphenNoCapsBox->set_sensitive(bEnable); + m_xBeforeText->set_sensitive(bEnable); + m_xExtHyphenBeforeBox->set_sensitive(bEnable); + m_xAfterText->set_sensitive(bEnable); + m_xExtHyphenAfterBox->set_sensitive(bEnable); + m_xMaxHyphenLabel->set_sensitive(bEnable); + m_xMaxHyphenEdit->set_sensitive(bEnable); + m_xHyphenBox->set_state(bEnable ? TRISTATE_TRUE : TRISTATE_FALSE); +} + +IMPL_LINK(SvxExtParagraphTabPage, HyphenClickHdl_Impl, weld::ToggleButton&, rToggle, void) +{ + aHyphenState.ButtonToggled(rToggle); + HyphenClickHdl(); +} + +void SvxExtParagraphTabPage::ApplyCollClickHdl() +{ + bool bEnable = false; + if (m_xApplyCollBtn->get_state() == TRISTATE_TRUE && m_xApplyCollBox->get_count()) + { + bEnable = true; + m_xApplyCollBox->set_active(nStdPos); + } + else + { + m_xApplyCollBox->set_active(-1); + } + m_xApplyCollBox->set_sensitive(bEnable); + if (!bHtmlMode) + { + m_xPageNumBox->set_sensitive(bEnable); + m_xPagenumEdit->set_sensitive(bEnable && m_xPageNumBox->get_state() == TRISTATE_TRUE); + } +} + +IMPL_LINK(SvxExtParagraphTabPage, ApplyCollClickHdl_Impl, weld::ToggleButton&, rToggle, void) +{ + aApplyCollState.ButtonToggled(rToggle); + ApplyCollClickHdl(); +} + +IMPL_LINK(SvxExtParagraphTabPage, PageBreakPosHdl_Impl, weld::ComboBox&, rListBox, void) +{ + if (0 == rListBox.get_active()) + { + m_xApplyCollBtn->set_sensitive(true); + + bool bEnable = m_xApplyCollBtn->get_state() == TRISTATE_TRUE && m_xApplyCollBox->get_count(); + + m_xApplyCollBox->set_sensitive(bEnable); + if (!bHtmlMode) + { + m_xPageNumBox->set_sensitive(bEnable); + m_xPagenumEdit->set_sensitive(bEnable && m_xPageNumBox->get_state() == TRISTATE_TRUE); + } + } + else if (1 == rListBox.get_active()) + { + m_xApplyCollBtn->set_state(TRISTATE_FALSE); + m_xApplyCollBtn->set_sensitive(false); + m_xApplyCollBox->set_sensitive(false); + m_xPageNumBox->set_sensitive(false); + m_xPagenumEdit->set_sensitive(false); + } +} + +IMPL_LINK(SvxExtParagraphTabPage, PageBreakTypeHdl_Impl, weld::ComboBox&, rListBox, void) +{ + //column break or break after + int nBreakPos = m_xBreakPositionLB->get_active(); + if (rListBox.get_active() == 1 || 1 == nBreakPos) + { + m_xApplyCollBtn->set_state(TRISTATE_FALSE); + m_xApplyCollBtn->set_sensitive(false); + m_xApplyCollBox->set_sensitive(false); + m_xPageNumBox->set_sensitive(false); + m_xPagenumEdit->set_sensitive(false); + } + else + PageBreakPosHdl_Impl(*m_xBreakPositionLB); +} + +void SvxExtParagraphTabPage::PageNumBoxClickHdl() +{ + m_xPagenumEdit->set_sensitive(m_xPageNumBox->get_state() == TRISTATE_TRUE); +} + +IMPL_LINK(SvxExtParagraphTabPage, PageNumBoxClickHdl_Impl, weld::ToggleButton&, rToggle, void) +{ + aPageNumState.ButtonToggled(rToggle); + PageNumBoxClickHdl(); +} + +IMPL_LINK(SvxExtParagraphTabPage, KeepParaBoxClickHdl_Impl, weld::ToggleButton&, rToggle, void) +{ + aKeepParaState.ButtonToggled(rToggle); +} + +void SvxExtParagraphTabPage::PageCreated(const SfxAllItemSet& aSet) +{ + const SfxBoolItem* pDisablePageBreakItem = aSet.GetItem(SID_DISABLE_SVXEXTPARAGRAPHTABPAGE_PAGEBREAK, false); + + if (pDisablePageBreakItem) + if ( pDisablePageBreakItem->GetValue()) + DisablePageBreak(); +} + +SvxAsianTabPage::SvxAsianTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/asiantypography.ui", "AsianTypography", &rSet) + , m_xForbiddenRulesCB(m_xBuilder->weld_check_button("checkForbidList")) + , m_xHangingPunctCB(m_xBuilder->weld_check_button("checkHangPunct")) + , m_xScriptSpaceCB(m_xBuilder->weld_check_button("checkApplySpacing")) +{ +} + +SvxAsianTabPage::~SvxAsianTabPage() +{ +} + +std::unique_ptr SvxAsianTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet) +{ + return std::make_unique(pPage, pController, *rSet); +} + +const sal_uInt16* SvxAsianTabPage::GetRanges() +{ + static const sal_uInt16 pRanges[] = + { + SID_ATTR_PARA_SCRIPTSPACE, SID_ATTR_PARA_FORBIDDEN_RULES, + 0 + }; + return pRanges; +} + +bool SvxAsianTabPage::FillItemSet( SfxItemSet* rSet ) +{ + bool bRet = false; + SfxItemPool* pPool = rSet->GetPool(); + if (m_xScriptSpaceCB->get_sensitive() && m_xScriptSpaceCB->get_state_changed_from_saved()) + { + std::unique_ptr pNewItem(static_cast(rSet->Get( + pPool->GetWhich(SID_ATTR_PARA_SCRIPTSPACE)).Clone())); + pNewItem->SetValue(m_xScriptSpaceCB->get_active()); + rSet->Put(std::move(pNewItem)); + bRet = true; + } + if (m_xHangingPunctCB->get_sensitive() && m_xHangingPunctCB->get_state_changed_from_saved()) + { + std::unique_ptr pNewItem(static_cast(rSet->Get( + pPool->GetWhich(SID_ATTR_PARA_HANGPUNCTUATION)).Clone())); + pNewItem->SetValue(m_xHangingPunctCB->get_active()); + rSet->Put(std::move(pNewItem)); + bRet = true; + } + if (m_xForbiddenRulesCB->get_sensitive() && m_xForbiddenRulesCB->get_state_changed_from_saved()) + { + std::unique_ptr pNewItem(static_cast(rSet->Get( + pPool->GetWhich(SID_ATTR_PARA_FORBIDDEN_RULES)).Clone())); + pNewItem->SetValue(m_xForbiddenRulesCB->get_active()); + rSet->Put(std::move(pNewItem)); + bRet = true; + } + return bRet; +} + +static void lcl_SetBox(const SfxItemSet& rSet, sal_uInt16 nSlotId, weld::CheckButton& rBox) +{ + sal_uInt16 _nWhich = rSet.GetPool()->GetWhich(nSlotId); + SfxItemState eState = rSet.GetItemState(_nWhich); + if( eState == SfxItemState::UNKNOWN || eState == SfxItemState::DISABLED ) + rBox.set_sensitive(false); + else if(eState >= SfxItemState::DEFAULT) + rBox.set_active(static_cast(rSet.Get(_nWhich)).GetValue()); + else + rBox.set_state(TRISTATE_INDET); + rBox.save_state(); +} + +void SvxAsianTabPage::Reset( const SfxItemSet* rSet ) +{ + lcl_SetBox(*rSet, SID_ATTR_PARA_FORBIDDEN_RULES, *m_xForbiddenRulesCB ); + lcl_SetBox(*rSet, SID_ATTR_PARA_HANGPUNCTUATION, *m_xHangingPunctCB ); + + //character distance not yet available + lcl_SetBox(*rSet, SID_ATTR_PARA_SCRIPTSPACE, *m_xScriptSpaceCB ); +} + +void SvxAsianTabPage::ChangesApplied() +{ + m_xForbiddenRulesCB->save_state(); + m_xHangingPunctCB->save_state(); + m_xScriptSpaceCB->save_state(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/swpossizetabpage.cxx b/cui/source/tabpages/swpossizetabpage.cxx new file mode 100644 index 000000000..93644e7c3 --- /dev/null +++ b/cui/source/tabpages/swpossizetabpage.cxx @@ -0,0 +1,1891 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace ::com::sun::star::text; + +namespace { + +enum class LB; + +} + +struct FrmMap +{ + SvxSwFramePosString::StringId eStrId; + SvxSwFramePosString::StringId eMirrorStrId; + short nAlign; + LB nLBRelations; +}; + +namespace { + +struct RelationMap +{ + SvxSwFramePosString::StringId eStrId; + SvxSwFramePosString::StringId eMirrorStrId; + LB nLBRelation; + short nRelation; +}; +struct StringIdPair_Impl +{ + SvxSwFramePosString::StringId eHori; + SvxSwFramePosString::StringId eVert; +}; + +enum class LB { + NONE = 0x000000, + Frame = 0x000001, // paragraph text area + PrintArea = 0x000002, // paragraph text area + indents + VertFrame = 0x000004, // vertical paragraph text area + VertPrintArea = 0x000008, // vertical paragraph text area + indents + RelFrameLeft = 0x000010, // left paragraph margin + RelFrameRight = 0x000020, // right paragraph margin + + RelPageLeft = 0x000040, // left page margin + RelPageRight = 0x000080, // right page margin + RelPageFrame = 0x000100, // complete page + RelPagePrintArea = 0x000200, // text area of page + + FlyRelPageLeft = 0x000400, // left frame margin + FlyRelPageRight = 0x000800, // right frame margin + FlyRelPageFrame = 0x001000, // complete frame + FlyRelPagePrintArea = 0x002000, // frame interior + + RelBase = 0x004000, // as char, relative to baseline + RelChar = 0x008000, // as char, relative to character + RelRow = 0x010000, // as char, relative to line + +// #i22305# + FlyVertFrame = 0x020000, // vertical entire frame + FlyVertPrintArea = 0x040000, // vertical frame text area + +// #i22341# + VertLine = 0x080000, // vertical text line + + RelPagePrintAreaBottom = 0x100000, // bottom of text area of page + + LAST = 0x200000 +}; + +} + +namespace o3tl { + template<> struct typed_flags : is_typed_flags {}; +} + +static RelationMap const aRelationMap[] = +{ + {SvxSwFramePosString::FRAME, SvxSwFramePosString::FRAME, LB::Frame, RelOrientation::FRAME}, + {SvxSwFramePosString::PRTAREA, SvxSwFramePosString::PRTAREA, LB::PrintArea, RelOrientation::PRINT_AREA}, + {SvxSwFramePosString::REL_PG_LEFT, SvxSwFramePosString::MIR_REL_PG_LEFT, LB::RelPageLeft, RelOrientation::PAGE_LEFT}, + {SvxSwFramePosString::REL_PG_RIGHT, SvxSwFramePosString::MIR_REL_PG_RIGHT, LB::RelPageRight, RelOrientation::PAGE_RIGHT}, + {SvxSwFramePosString::REL_FRM_LEFT, SvxSwFramePosString::MIR_REL_FRM_LEFT, LB::RelFrameLeft, RelOrientation::FRAME_LEFT}, + {SvxSwFramePosString::REL_FRM_RIGHT, SvxSwFramePosString::MIR_REL_FRM_RIGHT, LB::RelFrameRight, RelOrientation::FRAME_RIGHT}, + {SvxSwFramePosString::REL_PG_FRAME, SvxSwFramePosString::REL_PG_FRAME, LB::RelPageFrame, RelOrientation::PAGE_FRAME}, + {SvxSwFramePosString::REL_PG_PRTAREA,SvxSwFramePosString::REL_PG_PRTAREA, LB::RelPagePrintArea, RelOrientation::PAGE_PRINT_AREA}, + {SvxSwFramePosString::REL_PG_PRTAREA_BOTTOM,SvxSwFramePosString::REL_PG_PRTAREA_BOTTOM, LB::RelPagePrintAreaBottom, RelOrientation::PAGE_PRINT_AREA_BOTTOM}, + {SvxSwFramePosString::REL_CHAR, SvxSwFramePosString::REL_CHAR, LB::RelChar, RelOrientation::CHAR}, + + {SvxSwFramePosString::FLY_REL_PG_LEFT, SvxSwFramePosString::FLY_MIR_REL_PG_LEFT, LB::FlyRelPageLeft, RelOrientation::PAGE_LEFT}, + {SvxSwFramePosString::FLY_REL_PG_RIGHT, SvxSwFramePosString::FLY_MIR_REL_PG_RIGHT, LB::FlyRelPageRight, RelOrientation::PAGE_RIGHT}, + {SvxSwFramePosString::FLY_REL_PG_FRAME, SvxSwFramePosString::FLY_REL_PG_FRAME, LB::FlyRelPageFrame, RelOrientation::PAGE_FRAME}, + {SvxSwFramePosString::FLY_REL_PG_PRTAREA, SvxSwFramePosString::FLY_REL_PG_PRTAREA, LB::FlyRelPagePrintArea, RelOrientation::PAGE_PRINT_AREA}, + + {SvxSwFramePosString::REL_BORDER, SvxSwFramePosString::REL_BORDER, LB::VertFrame, RelOrientation::FRAME}, + {SvxSwFramePosString::REL_PRTAREA, SvxSwFramePosString::REL_PRTAREA, LB::VertPrintArea, RelOrientation::PRINT_AREA}, + + // #i22305# + {SvxSwFramePosString::FLY_REL_PG_FRAME, SvxSwFramePosString::FLY_REL_PG_FRAME, LB::FlyVertFrame, RelOrientation::FRAME}, + {SvxSwFramePosString::FLY_REL_PG_PRTAREA, SvxSwFramePosString::FLY_REL_PG_PRTAREA, LB::FlyVertPrintArea, RelOrientation::PRINT_AREA}, + + // #i22341# + {SvxSwFramePosString::REL_LINE, SvxSwFramePosString::REL_LINE, LB::VertLine, RelOrientation::TEXT_LINE} +}; + +static RelationMap const aAsCharRelationMap[] = +{ + {SvxSwFramePosString::REL_BASE, SvxSwFramePosString::REL_BASE, LB::RelBase, RelOrientation::FRAME}, + {SvxSwFramePosString::REL_CHAR, SvxSwFramePosString::REL_CHAR, LB::RelChar, RelOrientation::FRAME}, + {SvxSwFramePosString::REL_ROW, SvxSwFramePosString::REL_ROW, LB::RelRow, RelOrientation::FRAME} +}; + +/*-------------------------------------------------------------------- + Anchored at page + --------------------------------------------------------------------*/ + +static constexpr auto HORI_PAGE_REL = LB::RelPageFrame|LB::RelPagePrintArea|LB::RelPageLeft| + LB::RelPageRight; + +static FrmMap const aHPageMap[] = +{ + {SvxSwFramePosString::LEFT, SvxSwFramePosString::MIR_LEFT, HoriOrientation::LEFT, HORI_PAGE_REL}, + {SvxSwFramePosString::RIGHT, SvxSwFramePosString::MIR_RIGHT, HoriOrientation::RIGHT, HORI_PAGE_REL}, + {SvxSwFramePosString::CENTER_HORI,SvxSwFramePosString::CENTER_HORI, HoriOrientation::CENTER, HORI_PAGE_REL}, + {SvxSwFramePosString::FROMLEFT, SvxSwFramePosString::MIR_FROMLEFT, HoriOrientation::NONE, HORI_PAGE_REL} +}; + +static FrmMap const aHPageHtmlMap[] = +{ + {SvxSwFramePosString::FROMLEFT, SvxSwFramePosString::MIR_FROMLEFT, HoriOrientation::NONE, LB::RelPageFrame} +}; + +#define VERT_PAGE_REL (LB::RelPageFrame|LB::RelPagePrintArea) + +static FrmMap const aVPageMap[] = +{ + {SvxSwFramePosString::TOP, SvxSwFramePosString::TOP, VertOrientation::TOP, VERT_PAGE_REL}, + {SvxSwFramePosString::BOTTOM, SvxSwFramePosString::BOTTOM, VertOrientation::BOTTOM, VERT_PAGE_REL}, + {SvxSwFramePosString::CENTER_VERT, SvxSwFramePosString::CENTER_VERT, VertOrientation::CENTER, VERT_PAGE_REL}, + {SvxSwFramePosString::FROMTOP, SvxSwFramePosString::FROMTOP, VertOrientation::NONE, VERT_PAGE_REL} +}; + +static FrmMap const aVPageHtmlMap[] = +{ + {SvxSwFramePosString::FROMTOP, SvxSwFramePosString::FROMTOP, VertOrientation::NONE, LB::RelPageFrame} +}; + +/*-------------------------------------------------------------------- + Anchored at frame + --------------------------------------------------------------------*/ + +static constexpr auto HORI_FRAME_REL = LB::FlyRelPageFrame|LB::FlyRelPagePrintArea| + LB::FlyRelPageLeft|LB::FlyRelPageRight; + +static FrmMap const aHFrameMap[] = +{ + {SvxSwFramePosString::LEFT, SvxSwFramePosString::MIR_LEFT, HoriOrientation::LEFT, HORI_FRAME_REL}, + {SvxSwFramePosString::RIGHT, SvxSwFramePosString::MIR_RIGHT, HoriOrientation::RIGHT, HORI_FRAME_REL}, + {SvxSwFramePosString::CENTER_HORI, SvxSwFramePosString::CENTER_HORI, HoriOrientation::CENTER, HORI_FRAME_REL}, + {SvxSwFramePosString::FROMLEFT, SvxSwFramePosString::MIR_FROMLEFT, HoriOrientation::NONE, HORI_FRAME_REL} +}; + +static FrmMap const aHFlyHtmlMap[] = +{ + {SvxSwFramePosString::LEFT, SvxSwFramePosString::MIR_LEFT, HoriOrientation::LEFT, LB::FlyRelPageFrame}, + {SvxSwFramePosString::FROMLEFT, SvxSwFramePosString::MIR_FROMLEFT, HoriOrientation::NONE, LB::FlyRelPageFrame} +}; + +// #i18732# - own vertical alignment map for to frame anchored objects +// #i22305# +#define VERT_FRAME_REL (LB::VertFrame|LB::FlyVertPrintArea) + +static FrmMap const aVFrameMap[] = +{ + {SvxSwFramePosString::TOP, SvxSwFramePosString::TOP, VertOrientation::TOP, VERT_FRAME_REL}, + {SvxSwFramePosString::BOTTOM, SvxSwFramePosString::BOTTOM, VertOrientation::BOTTOM, VERT_FRAME_REL}, + {SvxSwFramePosString::CENTER_VERT, SvxSwFramePosString::CENTER_VERT, VertOrientation::CENTER, VERT_FRAME_REL}, + {SvxSwFramePosString::FROMTOP, SvxSwFramePosString::FROMTOP, VertOrientation::NONE, VERT_FRAME_REL} +}; + +static FrmMap const aVFlyHtmlMap[] = +{ + {SvxSwFramePosString::TOP, SvxSwFramePosString::TOP, VertOrientation::TOP, LB::FlyVertFrame}, + {SvxSwFramePosString::FROMTOP, SvxSwFramePosString::FROMTOP, VertOrientation::NONE, LB::FlyVertFrame} +}; + +static FrmMap const aVMultiSelectionMap[] = +{ + {SvxSwFramePosString::FROMTOP, SvxSwFramePosString::FROMTOP, VertOrientation::NONE, LB::NONE} +}; +static FrmMap const aHMultiSelectionMap[] = +{ + {SvxSwFramePosString::FROMLEFT, SvxSwFramePosString::FROMLEFT, HoriOrientation::NONE, LB::NONE} +}; + +/*-------------------------------------------------------------------- + Anchored at paragraph + --------------------------------------------------------------------*/ + +static constexpr auto HORI_PARA_REL = LB::Frame|LB::PrintArea|LB::RelPageLeft|LB::RelPageRight| + LB::RelPageFrame|LB::RelPagePrintArea|LB::RelFrameLeft| + LB::RelFrameRight; + +static FrmMap const aHParaMap[] = +{ + {SvxSwFramePosString::LEFT, SvxSwFramePosString::MIR_LEFT, HoriOrientation::LEFT, HORI_PARA_REL}, + {SvxSwFramePosString::RIGHT, SvxSwFramePosString::MIR_RIGHT, HoriOrientation::RIGHT, HORI_PARA_REL}, + {SvxSwFramePosString::CENTER_HORI, SvxSwFramePosString::CENTER_HORI, HoriOrientation::CENTER, HORI_PARA_REL}, + {SvxSwFramePosString::FROMLEFT, SvxSwFramePosString::MIR_FROMLEFT, HoriOrientation::NONE, HORI_PARA_REL} +}; + +#define HTML_HORI_PARA_REL (LB::Frame|LB::PrintArea) + +static FrmMap const aHParaHtmlMap[] = +{ + {SvxSwFramePosString::LEFT, SvxSwFramePosString::LEFT, HoriOrientation::LEFT, HTML_HORI_PARA_REL}, + {SvxSwFramePosString::RIGHT, SvxSwFramePosString::RIGHT, HoriOrientation::RIGHT, HTML_HORI_PARA_REL} +}; + +static FrmMap const aHParaHtmlAbsMap[] = +{ + {SvxSwFramePosString::LEFT, SvxSwFramePosString::MIR_LEFT, HoriOrientation::LEFT, HTML_HORI_PARA_REL}, + {SvxSwFramePosString::RIGHT, SvxSwFramePosString::MIR_RIGHT, HoriOrientation::RIGHT, HTML_HORI_PARA_REL} +}; + + +static constexpr auto VERT_PARA_REL = LB::VertFrame|LB::VertPrintArea| + LB::RelPageFrame|LB::RelPagePrintArea; + +static FrmMap const aVParaMap[] = +{ + {SvxSwFramePosString::TOP, SvxSwFramePosString::TOP, VertOrientation::TOP, VERT_PARA_REL}, + {SvxSwFramePosString::BOTTOM, SvxSwFramePosString::BOTTOM, VertOrientation::BOTTOM, VERT_PARA_REL}, + {SvxSwFramePosString::CENTER_VERT, SvxSwFramePosString::CENTER_VERT, VertOrientation::CENTER, VERT_PARA_REL}, + {SvxSwFramePosString::FROMTOP, SvxSwFramePosString::FROMTOP, VertOrientation::NONE, VERT_PARA_REL|LB::RelPagePrintAreaBottom} +}; + +static FrmMap const aVParaHtmlMap[] = +{ + {SvxSwFramePosString::TOP, SvxSwFramePosString::TOP, VertOrientation::TOP, LB::VertPrintArea} +}; + +/*-------------------------------------------------------------------- + Anchored at character + --------------------------------------------------------------------*/ + +static constexpr auto HORI_CHAR_REL = LB::Frame|LB::PrintArea|LB::RelPageLeft|LB::RelPageRight| + LB::RelPageFrame|LB::RelPagePrintArea|LB::RelFrameLeft| + LB::RelFrameRight|LB::RelChar; + +static FrmMap aHCharMap[] = +{ + {SvxSwFramePosString::LEFT, SvxSwFramePosString::MIR_LEFT, HoriOrientation::LEFT, HORI_CHAR_REL}, + {SvxSwFramePosString::RIGHT, SvxSwFramePosString::MIR_RIGHT, HoriOrientation::RIGHT, HORI_CHAR_REL}, + {SvxSwFramePosString::CENTER_HORI, SvxSwFramePosString::CENTER_HORI, HoriOrientation::CENTER, HORI_CHAR_REL}, + {SvxSwFramePosString::FROMLEFT, SvxSwFramePosString::MIR_FROMLEFT, HoriOrientation::NONE, HORI_CHAR_REL} +}; + +#define HTML_HORI_CHAR_REL (LB::Frame|LB::PrintArea|LB::RelChar) + +static FrmMap aHCharHtmlMap[] = +{ + {SvxSwFramePosString::LEFT, SvxSwFramePosString::LEFT, HoriOrientation::LEFT, HTML_HORI_CHAR_REL}, + {SvxSwFramePosString::RIGHT, SvxSwFramePosString::RIGHT, HoriOrientation::RIGHT, HTML_HORI_CHAR_REL} +}; + +static FrmMap aHCharHtmlAbsMap[] = +{ + {SvxSwFramePosString::LEFT, SvxSwFramePosString::MIR_LEFT, HoriOrientation::LEFT, LB::PrintArea|LB::RelChar}, + {SvxSwFramePosString::RIGHT, SvxSwFramePosString::MIR_RIGHT, HoriOrientation::RIGHT, LB::PrintArea}, + {SvxSwFramePosString::FROMLEFT, SvxSwFramePosString::MIR_FROMLEFT, HoriOrientation::NONE, LB::RelPageFrame} +}; + +// #i18732# - allow vertical alignment at page areas +// #i22341# - handle on its own +static constexpr auto VERT_CHAR_REL = LB::VertFrame|LB::VertPrintArea| + LB::RelPageFrame|LB::RelPagePrintArea; + +static FrmMap aVCharMap[] = +{ + // #i22341# + // introduce mappings for new vertical alignment at top of line + // and correct mapping for vertical alignment at character for position + // Note: because of these adjustments the map becomes ambiguous in its values + // / and . These ambiguities are considered + // in the methods , + // and + {SvxSwFramePosString::TOP, SvxSwFramePosString::TOP, VertOrientation::TOP, VERT_CHAR_REL|LB::RelChar}, + {SvxSwFramePosString::BOTTOM, SvxSwFramePosString::BOTTOM, VertOrientation::BOTTOM, VERT_CHAR_REL|LB::RelChar}, + {SvxSwFramePosString::BELOW, SvxSwFramePosString::BELOW, VertOrientation::CHAR_BOTTOM, LB::RelChar}, + {SvxSwFramePosString::CENTER_VERT, SvxSwFramePosString::CENTER_VERT, VertOrientation::CENTER, VERT_CHAR_REL|LB::RelChar}, + {SvxSwFramePosString::FROMTOP, SvxSwFramePosString::FROMTOP, VertOrientation::NONE, VERT_CHAR_REL|LB::RelPagePrintAreaBottom}, + {SvxSwFramePosString::FROMBOTTOM, SvxSwFramePosString::FROMBOTTOM, VertOrientation::NONE, LB::RelChar|LB::VertLine}, + {SvxSwFramePosString::TOP, SvxSwFramePosString::TOP, VertOrientation::LINE_TOP, LB::VertLine}, + {SvxSwFramePosString::BOTTOM, SvxSwFramePosString::BOTTOM, VertOrientation::LINE_BOTTOM, LB::VertLine}, + {SvxSwFramePosString::CENTER_VERT, SvxSwFramePosString::CENTER_VERT, VertOrientation::LINE_CENTER, LB::VertLine} +}; + + +static FrmMap const aVCharHtmlMap[] = +{ + {SvxSwFramePosString::BELOW, SvxSwFramePosString::BELOW, VertOrientation::CHAR_BOTTOM, LB::RelChar} +}; + +static FrmMap const aVCharHtmlAbsMap[] = +{ + {SvxSwFramePosString::TOP, SvxSwFramePosString::TOP, VertOrientation::TOP, LB::RelChar}, + {SvxSwFramePosString::BELOW, SvxSwFramePosString::BELOW, VertOrientation::CHAR_BOTTOM, LB::RelChar} +}; +/*-------------------------------------------------------------------- + anchored as character + --------------------------------------------------------------------*/ + +static FrmMap const aVAsCharMap[] = +{ + {SvxSwFramePosString::TOP, SvxSwFramePosString::TOP, VertOrientation::TOP, LB::RelBase}, + {SvxSwFramePosString::BOTTOM, SvxSwFramePosString::BOTTOM, VertOrientation::BOTTOM, LB::RelBase}, + {SvxSwFramePosString::CENTER_VERT, SvxSwFramePosString::CENTER_VERT, VertOrientation::CENTER, LB::RelBase}, + + {SvxSwFramePosString::TOP, SvxSwFramePosString::TOP, VertOrientation::CHAR_TOP, LB::RelChar}, + {SvxSwFramePosString::BOTTOM, SvxSwFramePosString::BOTTOM, VertOrientation::CHAR_BOTTOM, LB::RelChar}, + {SvxSwFramePosString::CENTER_VERT, SvxSwFramePosString::CENTER_VERT, VertOrientation::CHAR_CENTER, LB::RelChar}, + + {SvxSwFramePosString::TOP, SvxSwFramePosString::TOP, VertOrientation::LINE_TOP, LB::RelRow}, + {SvxSwFramePosString::BOTTOM, SvxSwFramePosString::BOTTOM, VertOrientation::LINE_BOTTOM, LB::RelRow}, + {SvxSwFramePosString::CENTER_VERT, SvxSwFramePosString::CENTER_VERT, VertOrientation::LINE_CENTER, LB::RelRow}, + + {SvxSwFramePosString::FROMBOTTOM, SvxSwFramePosString::FROMBOTTOM, VertOrientation::NONE, LB::RelBase} +}; + +static FrmMap const aVAsCharHtmlMap[] = +{ + {SvxSwFramePosString::TOP, SvxSwFramePosString::TOP, VertOrientation::TOP, LB::RelBase}, + {SvxSwFramePosString::CENTER_VERT, SvxSwFramePosString::CENTER_VERT, VertOrientation::CENTER, LB::RelBase}, + + {SvxSwFramePosString::TOP, SvxSwFramePosString::TOP, VertOrientation::CHAR_TOP, LB::RelChar}, + + {SvxSwFramePosString::TOP, SvxSwFramePosString::TOP, VertOrientation::LINE_TOP, LB::RelRow}, + {SvxSwFramePosString::BOTTOM, SvxSwFramePosString::BOTTOM, VertOrientation::LINE_BOTTOM, LB::RelRow}, + {SvxSwFramePosString::CENTER_VERT, SvxSwFramePosString::CENTER_VERT, VertOrientation::LINE_CENTER, LB::RelRow} +}; + +static std::size_t lcl_GetFrmMapCount(const FrmMap* pMap) +{ + if( pMap ) + { + if( pMap == aVParaHtmlMap ) + return SAL_N_ELEMENTS(aVParaHtmlMap); + if( pMap == aVAsCharHtmlMap ) + return SAL_N_ELEMENTS( aVAsCharHtmlMap ); + if( pMap == aHParaHtmlMap ) + return SAL_N_ELEMENTS( aHParaHtmlMap ); + if( pMap == aHParaHtmlAbsMap ) + return SAL_N_ELEMENTS( aHParaHtmlAbsMap ); + if( pMap == aVPageMap ) + return SAL_N_ELEMENTS( aVPageMap ); + if( pMap == aVPageHtmlMap ) + return SAL_N_ELEMENTS( aVPageHtmlMap ); + if( pMap == aVAsCharMap ) + return SAL_N_ELEMENTS( aVAsCharMap ); + if( pMap == aVParaMap ) + return SAL_N_ELEMENTS( aVParaMap ); + if( pMap == aHParaMap ) + return SAL_N_ELEMENTS( aHParaMap ); + if( pMap == aHFrameMap ) + return SAL_N_ELEMENTS( aHFrameMap ); + if( pMap == aVFrameMap ) + return SAL_N_ELEMENTS( aVFrameMap ); + if( pMap == aHCharMap ) + return SAL_N_ELEMENTS( aHCharMap ); + if( pMap == aHCharHtmlMap ) + return SAL_N_ELEMENTS( aHCharHtmlMap ); + if( pMap == aHCharHtmlAbsMap ) + return SAL_N_ELEMENTS( aHCharHtmlAbsMap ); + if( pMap == aVCharMap ) + return SAL_N_ELEMENTS( aVCharMap ); + if( pMap == aVCharHtmlMap ) + return SAL_N_ELEMENTS( aVCharHtmlMap ); + if( pMap == aVCharHtmlAbsMap ) + return SAL_N_ELEMENTS( aVCharHtmlAbsMap ); + if( pMap == aHPageHtmlMap ) + return SAL_N_ELEMENTS( aHPageHtmlMap ); + if( pMap == aHFlyHtmlMap ) + return SAL_N_ELEMENTS( aHFlyHtmlMap ); + if( pMap == aVFlyHtmlMap ) + return SAL_N_ELEMENTS( aVFlyHtmlMap ); + if( pMap == aVMultiSelectionMap ) + return SAL_N_ELEMENTS( aVMultiSelectionMap ); + if( pMap == aHMultiSelectionMap ) + return SAL_N_ELEMENTS( aHMultiSelectionMap ); + return SAL_N_ELEMENTS(aHPageMap); + } + return 0; +} + +static SvxSwFramePosString::StringId lcl_ChangeResIdToVerticalOrRTL( + SvxSwFramePosString::StringId eStringId, bool bVertical, bool bRTL) +{ + //special handling of STR_FROMLEFT + if(SvxSwFramePosString::FROMLEFT == eStringId) + { + eStringId = bVertical ? + bRTL ? SvxSwFramePosString::FROMBOTTOM : SvxSwFramePosString::FROMTOP : + bRTL ? SvxSwFramePosString::FROMRIGHT : SvxSwFramePosString::FROMLEFT; + return eStringId; + } + if(bVertical) + { + //exchange horizontal strings with vertical strings and vice versa + static const StringIdPair_Impl aHoriIds[] = + { + {SvxSwFramePosString::LEFT, SvxSwFramePosString::TOP}, + {SvxSwFramePosString::RIGHT, SvxSwFramePosString::BOTTOM}, + {SvxSwFramePosString::CENTER_HORI, SvxSwFramePosString::CENTER_VERT}, + {SvxSwFramePosString::FROMTOP, SvxSwFramePosString::FROMRIGHT}, + {SvxSwFramePosString::REL_PG_LEFT, SvxSwFramePosString::REL_PG_TOP}, + {SvxSwFramePosString::REL_PG_RIGHT, SvxSwFramePosString::REL_PG_BOTTOM} , + {SvxSwFramePosString::REL_FRM_LEFT, SvxSwFramePosString::REL_FRM_TOP}, + {SvxSwFramePosString::REL_FRM_RIGHT, SvxSwFramePosString::REL_FRM_BOTTOM} + }; + static const StringIdPair_Impl aVertIds[] = + { + {SvxSwFramePosString::TOP, SvxSwFramePosString::RIGHT}, + {SvxSwFramePosString::BOTTOM, SvxSwFramePosString::LEFT }, + {SvxSwFramePosString::CENTER_VERT, SvxSwFramePosString::CENTER_HORI}, + {SvxSwFramePosString::FROMTOP, SvxSwFramePosString::FROMRIGHT }, + {SvxSwFramePosString::REL_PG_TOP, SvxSwFramePosString::REL_PG_LEFT }, + {SvxSwFramePosString::REL_PG_BOTTOM, SvxSwFramePosString::REL_PG_RIGHT } , + {SvxSwFramePosString::REL_FRM_TOP, SvxSwFramePosString::REL_FRM_LEFT }, + {SvxSwFramePosString::REL_FRM_BOTTOM, SvxSwFramePosString::REL_FRM_RIGHT } + }; + for(size_t nIndex = 0; nIndex < SAL_N_ELEMENTS(aHoriIds); ++nIndex) + { + if(aHoriIds[nIndex].eHori == eStringId) + { + eStringId = aHoriIds[nIndex].eVert; + return eStringId; + } + } + for(size_t nIndex = 0; nIndex < SAL_N_ELEMENTS(aVertIds); ++nIndex) + { + if(aVertIds[nIndex].eHori == eStringId) + { + eStringId = aVertIds[nIndex].eVert; + break; + } + } + } + return eStringId; +} +// #i22341# - helper method in order to determine all possible +// listbox relations in a relation map for a given relation +static LB lcl_GetLBRelationsForRelations( const sal_uInt16 _nRel ) +{ + LB nLBRelations = LB::NONE; + + for (RelationMap const & nRelMapPos : aRelationMap) + { + if ( nRelMapPos.nRelation == _nRel ) + { + nLBRelations |= nRelMapPos.nLBRelation; + } + } + + return nLBRelations; +} + +// #i22341# - helper method on order to determine all possible +// listbox relations in a relation map for a given string ID +static LB lcl_GetLBRelationsForStrID(const FrmMap* _pMap, + const SvxSwFramePosString::StringId _eStrId, + const bool _bUseMirrorStr ) +{ + LB nLBRelations = LB::NONE; + + std::size_t nRelMapSize = lcl_GetFrmMapCount( _pMap ); + for ( std::size_t nRelMapPos = 0; nRelMapPos < nRelMapSize; ++nRelMapPos ) + { + if ( ( !_bUseMirrorStr && _pMap[nRelMapPos].eStrId == _eStrId ) || + ( _bUseMirrorStr && _pMap[nRelMapPos].eMirrorStrId == _eStrId ) ) + { + nLBRelations |= _pMap[nRelMapPos].nLBRelations; + } + } + + return nLBRelations; +} + +SvxSwPosSizeTabPage::SvxSwPosSizeTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "cui/ui/swpossizepage.ui", "SwPosSizePage", &rInAttrs) + , m_pVMap(nullptr) + , m_pHMap(nullptr) + , m_pSdrView(nullptr) + , m_nOldH(HoriOrientation::CENTER) + , m_nOldHRel(RelOrientation::FRAME) + , m_nOldV(VertOrientation::TOP) + , m_nOldVRel(RelOrientation::PRINT_AREA) + , m_fWidthHeightRatio(1.0) + , m_bHtmlMode(false) + , m_bIsVerticalFrame(false) + , m_bPositioningDisabled(false) + , m_bIsMultiSelection(false) + , m_bIsInRightToLeft(false) + , m_nProtectSizeState(TRISTATE_FALSE) + , m_xWidthMF(m_xBuilder->weld_metric_spin_button("width", FieldUnit::CM)) + , m_xHeightMF(m_xBuilder->weld_metric_spin_button("height", FieldUnit::CM)) + , m_xKeepRatioCB(m_xBuilder->weld_check_button("ratio")) + , m_xToPageRB(m_xBuilder->weld_radio_button("topage")) + , m_xToParaRB(m_xBuilder->weld_radio_button("topara")) + , m_xToCharRB(m_xBuilder->weld_radio_button("tochar")) + , m_xAsCharRB(m_xBuilder->weld_radio_button("aschar")) + , m_xToFrameRB(m_xBuilder->weld_radio_button("toframe")) + , m_xPositionCB(m_xBuilder->weld_check_button("pos")) + , m_xSizeCB(m_xBuilder->weld_check_button("size")) + , m_xPosFrame(m_xBuilder->weld_widget("posframe")) + , m_xHoriFT(m_xBuilder->weld_label("horiposft")) + , m_xHoriLB(m_xBuilder->weld_combo_box("horipos")) + , m_xHoriByFT(m_xBuilder->weld_label("horibyft")) + , m_xHoriByMF(m_xBuilder->weld_metric_spin_button("byhori", FieldUnit::CM)) + , m_xHoriToFT(m_xBuilder->weld_label("horitoft")) + , m_xHoriToLB(m_xBuilder->weld_combo_box("horianchor")) + , m_xHoriMirrorCB(m_xBuilder->weld_check_button("mirror")) + , m_xVertFT(m_xBuilder->weld_label("vertposft")) + , m_xVertLB(m_xBuilder->weld_combo_box("vertpos")) + , m_xVertByFT(m_xBuilder->weld_label("vertbyft")) + , m_xVertByMF(m_xBuilder->weld_metric_spin_button("byvert", FieldUnit::CM)) + , m_xVertToFT(m_xBuilder->weld_label("verttoft")) + , m_xVertToLB(m_xBuilder->weld_combo_box("vertanchor")) + , m_xFollowCB(m_xBuilder->weld_check_button("followtextflow")) + , m_xExampleWN(new weld::CustomWeld(*m_xBuilder, "preview", m_aExampleWN)) +{ + setOptimalFrmWidth(); + setOptimalRelWidth(); + + FieldUnit eDlgUnit = GetModuleFieldUnit( rInAttrs ); + SetFieldUnit(*m_xHoriByMF, eDlgUnit, true); + SetFieldUnit(*m_xVertByMF, eDlgUnit, true); + SetFieldUnit(*m_xWidthMF , eDlgUnit, true); + SetFieldUnit(*m_xHeightMF, eDlgUnit, true); + + SetExchangeSupport(); + + Link aLk3 = LINK(this, SvxSwPosSizeTabPage, RangeModifyHdl); + m_xWidthMF->connect_focus_out(aLk3); + m_xHeightMF->connect_focus_out(aLk3); + m_xHoriByMF->connect_focus_out(aLk3); + m_xVertByMF->connect_focus_out(aLk3); + m_xFollowCB->connect_toggled(LINK(this, SvxSwPosSizeTabPage, RangeModifyClickHdl)); + + Link aLk = LINK(this, SvxSwPosSizeTabPage, ModifyHdl); + m_xWidthMF->connect_value_changed( aLk ); + m_xHeightMF->connect_value_changed( aLk ); + m_xHoriByMF->connect_value_changed( aLk ); + m_xVertByMF->connect_value_changed( aLk ); + + Link aLk2 = LINK(this, SvxSwPosSizeTabPage, AnchorTypeHdl); + m_xToPageRB->connect_toggled( aLk2 ); + m_xToParaRB->connect_toggled( aLk2 ); + m_xToCharRB->connect_toggled( aLk2 ); + m_xAsCharRB->connect_toggled( aLk2 ); + m_xToFrameRB->connect_toggled( aLk2 ); + + m_xHoriLB->connect_changed(LINK(this, SvxSwPosSizeTabPage, PosHdl)); + m_xVertLB->connect_changed(LINK(this, SvxSwPosSizeTabPage, PosHdl)); + + m_xHoriToLB->connect_changed(LINK(this, SvxSwPosSizeTabPage, RelHdl)); + m_xVertToLB->connect_changed(LINK(this, SvxSwPosSizeTabPage, RelHdl)); + + m_xHoriMirrorCB->connect_toggled(LINK(this, SvxSwPosSizeTabPage, MirrorHdl)); + m_xPositionCB->connect_toggled(LINK(this, SvxSwPosSizeTabPage, ProtectHdl)); +} + +SvxSwPosSizeTabPage::~SvxSwPosSizeTabPage() +{ + m_xWidthMF.reset(); + m_xHeightMF.reset(); + m_xHoriByMF.reset(); + m_xVertByMF.reset(); +} + +namespace +{ + struct FrmMaps + { + FrmMap const *pMap; + size_t nCount; + }; +} + +void SvxSwPosSizeTabPage::setOptimalFrmWidth() +{ + static const FrmMaps aMaps[] = { + { aHPageMap, SAL_N_ELEMENTS(aHPageMap) }, + { aHPageHtmlMap, SAL_N_ELEMENTS(aHPageHtmlMap) }, + { aVPageMap, SAL_N_ELEMENTS(aVPageMap) }, + { aVPageHtmlMap, SAL_N_ELEMENTS(aVPageHtmlMap) }, + { aHFrameMap, SAL_N_ELEMENTS(aHFrameMap) }, + { aHFlyHtmlMap, SAL_N_ELEMENTS(aHFlyHtmlMap) }, + { aVFrameMap, SAL_N_ELEMENTS(aVFrameMap) }, + { aVFlyHtmlMap, SAL_N_ELEMENTS(aVFlyHtmlMap) }, + { aHParaMap, SAL_N_ELEMENTS(aHParaMap) }, + { aHParaHtmlMap, SAL_N_ELEMENTS(aHParaHtmlMap) }, + { aHParaHtmlAbsMap, SAL_N_ELEMENTS(aHParaHtmlAbsMap) }, + { aVParaMap, SAL_N_ELEMENTS(aVParaMap) }, + { aVParaHtmlMap, SAL_N_ELEMENTS(aVParaHtmlMap) }, + { aHCharMap, SAL_N_ELEMENTS(aHCharMap) }, + { aHCharHtmlMap, SAL_N_ELEMENTS(aHCharHtmlMap) }, + { aHCharHtmlAbsMap, SAL_N_ELEMENTS(aHCharHtmlAbsMap) }, + { aVCharMap, SAL_N_ELEMENTS(aVCharMap) }, + { aVCharHtmlMap, SAL_N_ELEMENTS(aVCharHtmlMap) }, + { aVCharHtmlAbsMap, SAL_N_ELEMENTS(aVCharHtmlAbsMap) }, + { aVAsCharMap, SAL_N_ELEMENTS(aVAsCharMap) }, + { aVAsCharHtmlMap, SAL_N_ELEMENTS(aVAsCharHtmlMap) } + }; + + std::vector aFrames; + for (const FrmMaps& aMap : aMaps) + { + for (size_t j = 0; j < aMap.nCount; ++j) + { + aFrames.push_back(aMap.pMap[j].eStrId); + aFrames.push_back(aMap.pMap[j].eMirrorStrId); + } + } + + std::sort(aFrames.begin(), aFrames.end()); + aFrames.erase(std::unique(aFrames.begin(), aFrames.end()), aFrames.end()); + + for (auto const& frame : aFrames) + { + m_xHoriLB->append_text(SvxSwFramePosString::GetString(frame)); + } + + Size aBiggest(m_xHoriLB->get_preferred_size()); + m_xHoriLB->set_size_request(aBiggest.Width(), -1); + m_xVertLB->set_size_request(aBiggest.Width(), -1); + m_xHoriLB->clear(); +} + +namespace +{ + struct RelationMaps + { + RelationMap const *pMap; + size_t nCount; + }; +} + +void SvxSwPosSizeTabPage::setOptimalRelWidth() +{ + static const RelationMaps aMaps[] = { + { aRelationMap, SAL_N_ELEMENTS(aRelationMap) }, + { aAsCharRelationMap, SAL_N_ELEMENTS(aAsCharRelationMap) } + }; + + std::vector aRels; + for (const RelationMaps& aMap : aMaps) + { + for (size_t j = 0; j < aMap.nCount; ++j) + { + aRels.push_back(aMap.pMap[j].eStrId); + aRels.push_back(aMap.pMap[j].eMirrorStrId); + } + } + + std::sort(aRels.begin(), aRels.end()); + aRels.erase(std::unique(aRels.begin(), aRels.end()), aRels.end()); + + for (auto const& elem : aRels) + { + m_xHoriLB->append_text(SvxSwFramePosString::GetString(elem)); + } + + Size aBiggest(m_xHoriLB->get_preferred_size()); + m_xHoriLB->set_size_request(aBiggest.Width(), -1); + m_xVertLB->set_size_request(aBiggest.Width(), -1); + m_xHoriLB->clear(); +} + +std::unique_ptr SvxSwPosSizeTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet) +{ + return std::make_unique(pPage, pController, *rSet); +} + +const sal_uInt16* SvxSwPosSizeTabPage::GetRanges() +{ + static const sal_uInt16 pSwPosRanges[] = + { + SID_ATTR_TRANSFORM_POS_X, + SID_ATTR_TRANSFORM_POS_Y, + SID_ATTR_TRANSFORM_PROTECT_POS, + SID_ATTR_TRANSFORM_PROTECT_POS, + SID_ATTR_TRANSFORM_INTERN, + SID_ATTR_TRANSFORM_INTERN, + SID_ATTR_TRANSFORM_ANCHOR, + SID_ATTR_TRANSFORM_VERT_ORIENT, + SID_ATTR_TRANSFORM_WIDTH, + SID_ATTR_TRANSFORM_SIZE_POINT, + SID_ATTR_TRANSFORM_PROTECT_POS, + SID_ATTR_TRANSFORM_INTERN, + SID_ATTR_TRANSFORM_AUTOWIDTH, + SID_ATTR_TRANSFORM_VERT_ORIENT, + SID_HTML_MODE, + SID_HTML_MODE, + SID_SW_FOLLOW_TEXT_FLOW, + SID_SW_FOLLOW_TEXT_FLOW, + SID_ATTR_TRANSFORM_HORI_POSITION, + SID_ATTR_TRANSFORM_VERT_POSITION, + 0 + }; + return pSwPosRanges; +} + +bool SvxSwPosSizeTabPage::FillItemSet( SfxItemSet* rSet) +{ + bool bAnchorChanged = false; + RndStdIds nAnchor = GetAnchorType(&bAnchorChanged); + bool bModified = false; + if(bAnchorChanged) + { + rSet->Put(SfxInt16Item(SID_ATTR_TRANSFORM_ANCHOR, static_cast(nAnchor))); + bModified = true; + } + if (m_xPositionCB->get_state_changed_from_saved()) + { + if (m_xPositionCB->get_inconsistent()) + rSet->InvalidateItem( SID_ATTR_TRANSFORM_PROTECT_POS ); + else + rSet->Put( + SfxBoolItem( GetWhich( SID_ATTR_TRANSFORM_PROTECT_POS ), + m_xPositionCB->get_state() == TRISTATE_TRUE ) ); + bModified = true; + } + + if (m_xSizeCB->get_state_changed_from_saved()) + { + if (m_xSizeCB->get_inconsistent()) + rSet->InvalidateItem( SID_ATTR_TRANSFORM_PROTECT_SIZE ); + else + rSet->Put( + SfxBoolItem( GetWhich( SID_ATTR_TRANSFORM_PROTECT_SIZE ), + m_xSizeCB->get_state() == TRISTATE_TRUE ) ); + bModified = true; + } + + const SfxItemSet& rOldSet = GetItemSet(); + + if(!m_bPositioningDisabled) + { + //on multiple selections the positioning is set via SdrView + if (m_bIsMultiSelection) + { + if (m_xHoriByMF->get_value_changed_from_saved() || m_xVertByMF->get_value_changed_from_saved()) + { + auto nHoriByPos = m_xHoriByMF->denormalize(m_xHoriByMF->get_value(FieldUnit::TWIP)); + auto nVertByPos = m_xVertByMF->denormalize(m_xVertByMF->get_value(FieldUnit::TWIP)); + + // old rectangle with CoreUnit + m_aRect = m_pSdrView->GetAllMarkedRect(); + m_pSdrView->GetSdrPageView()->LogicToPagePos( m_aRect ); + + nHoriByPos += m_aAnchorPos.X(); + nVertByPos += m_aAnchorPos.Y(); + + rSet->Put( SfxInt32Item( GetWhich( SID_ATTR_TRANSFORM_POS_X ), nHoriByPos ) ); + rSet->Put( SfxInt32Item( GetWhich( SID_ATTR_TRANSFORM_POS_Y ), nVertByPos ) ); + + bModified = true; + } + } + else + { + if ( m_pHMap ) + { + const SfxInt16Item& rHoriOrient = + static_cast(rOldSet.Get( SID_ATTR_TRANSFORM_HORI_ORIENT)); + const SfxInt16Item& rHoriRelation = + static_cast(rOldSet.Get( SID_ATTR_TRANSFORM_HORI_RELATION)); + const SfxInt32Item& rHoriPosition = + static_cast(rOldSet.Get( SID_ATTR_TRANSFORM_HORI_POSITION)) ; + + sal_uInt16 nMapPos = GetMapPos(m_pHMap, *m_xHoriLB); + short nAlign = GetAlignment(m_pHMap, nMapPos, *m_xHoriToLB); + short nRel = GetRelation(*m_xHoriToLB); + const auto nHoriByPos = m_xHoriByMF->denormalize(m_xHoriByMF->get_value(FieldUnit::TWIP)); + if ( + nAlign != rHoriOrient.GetValue() || + nRel != rHoriRelation.GetValue() || + (m_xHoriByMF->get_sensitive() && nHoriByPos != rHoriPosition.GetValue()) + ) + { + rSet->Put(SfxInt16Item(SID_ATTR_TRANSFORM_HORI_ORIENT, nAlign)); + rSet->Put(SfxInt16Item(SID_ATTR_TRANSFORM_HORI_RELATION, nRel)); + if(m_xHoriByMF->get_sensitive()) + rSet->Put(SfxInt32Item(SID_ATTR_TRANSFORM_HORI_POSITION, nHoriByPos)); + bModified = true; + } + } + if (m_xHoriMirrorCB->get_sensitive() && m_xHoriMirrorCB->get_state_changed_from_saved()) + bModified |= nullptr != rSet->Put(SfxBoolItem(SID_ATTR_TRANSFORM_HORI_MIRROR, m_xHoriMirrorCB->get_active())); + + if ( m_pVMap ) + { + const SfxInt16Item& rVertOrient = + static_cast(rOldSet.Get( SID_ATTR_TRANSFORM_VERT_ORIENT)); + const SfxInt16Item& rVertRelation = + static_cast(rOldSet.Get( SID_ATTR_TRANSFORM_VERT_RELATION)); + const SfxInt32Item& rVertPosition = + static_cast(rOldSet.Get( SID_ATTR_TRANSFORM_VERT_POSITION)); + + sal_uInt16 nMapPos = GetMapPos(m_pVMap, *m_xVertLB); + short nAlign = GetAlignment(m_pVMap, nMapPos, *m_xVertToLB); + short nRel = GetRelation(*m_xVertToLB); + // #i34055# - convert vertical position for + // as-character anchored objects + auto nVertByPos = m_xVertByMF->denormalize(m_xVertByMF->get_value(FieldUnit::TWIP)); + if (GetAnchorType() == RndStdIds::FLY_AS_CHAR) + { + nVertByPos *= -1; + } + if ( nAlign != rVertOrient.GetValue() || + nRel != rVertRelation.GetValue() || + ( m_xVertByMF->get_sensitive() && + nVertByPos != rVertPosition.GetValue() ) ) + { + rSet->Put(SfxInt16Item(SID_ATTR_TRANSFORM_VERT_ORIENT, nAlign)); + rSet->Put(SfxInt16Item(SID_ATTR_TRANSFORM_VERT_RELATION, nRel)); + if(m_xVertByMF->get_sensitive()) + rSet->Put(SfxInt32Item(SID_ATTR_TRANSFORM_VERT_POSITION, nVertByPos)); + bModified = true; + } + } + + // #i18732# + if (m_xFollowCB->get_state_changed_from_saved()) + { + //Writer internal type - based on SfxBoolItem + const SfxPoolItem* pItem = GetItem( rOldSet, SID_SW_FOLLOW_TEXT_FLOW); + if(pItem) + { + std::unique_ptr pFollow(static_cast(pItem->Clone())); + pFollow->SetValue(m_xFollowCB->get_active()); + bModified |= nullptr != rSet->Put(*pFollow); + } + } + } + } + if (m_xWidthMF->get_value_changed_from_saved() || m_xHeightMF->get_value_changed_from_saved()) + { + sal_uInt32 nWidth = static_cast(m_xWidthMF->denormalize(m_xWidthMF->get_value(FieldUnit::TWIP))); + sal_uInt32 nHeight = static_cast(m_xHeightMF->denormalize(m_xHeightMF->get_value(FieldUnit::TWIP))); + rSet->Put( SfxUInt32Item( GetWhich( SID_ATTR_TRANSFORM_WIDTH ), nWidth ) ); + rSet->Put( SfxUInt32Item( GetWhich( SID_ATTR_TRANSFORM_HEIGHT ), nHeight ) ); + //this item is required by SdrEditView::SetGeoAttrToMarked() + rSet->Put( SfxUInt16Item( GetWhich( SID_ATTR_TRANSFORM_SIZE_POINT ), sal_uInt16(RectPoint::LT) ) ); + + bModified = true; + } + + return bModified; +} + +void SvxSwPosSizeTabPage::Reset( const SfxItemSet* rSet) +{ + const SfxPoolItem* pItem = GetItem( *rSet, SID_ATTR_TRANSFORM_ANCHOR ); + bool bInvalidateAnchor = false; + RndStdIds nAnchorType = RndStdIds::FLY_AT_PARA; + if(pItem) + { + nAnchorType = static_cast(static_cast(pItem)->GetValue()); + switch(nAnchorType) + { + case RndStdIds::FLY_AT_PAGE: m_xToPageRB->set_active(true); break; + case RndStdIds::FLY_AT_PARA: m_xToParaRB->set_active(true); break; + case RndStdIds::FLY_AT_CHAR: m_xToCharRB->set_active(true); break; + case RndStdIds::FLY_AS_CHAR: m_xAsCharRB->set_active(true); break; + case RndStdIds::FLY_AT_FLY: m_xToFrameRB->set_active(true); break; + default : bInvalidateAnchor = true; + } + m_xToPageRB->save_state(); + m_xToParaRB->save_state(); + m_xToCharRB->save_state(); + m_xAsCharRB->save_state(); + m_xToFrameRB->save_state(); + } + if (bInvalidateAnchor) + { + m_xToPageRB->set_sensitive( false ); + m_xToParaRB->set_sensitive( false ); + m_xToCharRB->set_sensitive( false ); + m_xAsCharRB->set_sensitive( false ); + m_xToFrameRB->set_sensitive( false ); + } + + pItem = GetItem( *rSet, SID_ATTR_TRANSFORM_PROTECT_POS ); + if (pItem) + { + bool bProtected = static_cast(pItem)->GetValue(); + m_xPositionCB->set_active(bProtected); + m_xSizeCB->set_sensitive(!bProtected); + } + else + { + m_xPositionCB->set_inconsistent(true); + } + + m_xPositionCB->save_state(); + + pItem = GetItem( *rSet, SID_ATTR_TRANSFORM_PROTECT_SIZE ); + + if (pItem) + { + m_xSizeCB->set_active(static_cast(pItem)->GetValue()); + } + else + m_xSizeCB->set_inconsistent(true); + m_xSizeCB->save_state(); + + pItem = GetItem( *rSet, SID_HTML_MODE ); + if(pItem) + { + m_bHtmlMode = + (static_cast(pItem)->GetValue() & HTMLMODE_ON) + != 0; + } + + pItem = GetItem( *rSet, SID_ATTR_TRANSFORM_IN_VERTICAL_TEXT ); + if(pItem && static_cast(pItem)->GetValue()) + { + OUString sHLabel = m_xHoriFT->get_label(); + m_xHoriFT->set_label(m_xVertFT->get_label()); + m_xVertFT->set_label(sHLabel); + m_bIsVerticalFrame = true; + } + pItem = GetItem( *rSet, SID_ATTR_TRANSFORM_IN_RTL_TEXT); + if(pItem) + m_bIsInRightToLeft = static_cast(pItem)->GetValue(); + + pItem = GetItem( *rSet, SID_SW_FOLLOW_TEXT_FLOW); + if(pItem) + { + const bool bFollowTextFlow = + static_cast(pItem)->GetValue(); + m_xFollowCB->set_active(bFollowTextFlow); + } + m_xFollowCB->save_state(); + + if(m_bHtmlMode) + { + m_xHoriMirrorCB->hide(); + m_xKeepRatioCB->set_sensitive(false); + // #i18732# - hide checkbox in HTML mode + m_xFollowCB->hide(); + } + else + { + // #i18732# correct enable/disable of check box 'Mirror on..' + m_xHoriMirrorCB->set_sensitive(!m_xAsCharRB->get_active() && !m_bIsMultiSelection); + + // #i18732# - enable/disable check box 'Follow text flow'. + m_xFollowCB->set_sensitive(m_xToParaRB->get_active() || + m_xToCharRB->get_active()); + } + + pItem = GetItem( *rSet, SID_ATTR_TRANSFORM_WIDTH ); + sal_Int32 nWidth = std::max( pItem ? ( static_cast(pItem)->GetValue()) : 0, sal_uInt32(1) ); + + m_xWidthMF->set_value(m_xWidthMF->normalize(nWidth), FieldUnit::TWIP); + m_xWidthMF->save_value(); + + pItem = GetItem( *rSet, SID_ATTR_TRANSFORM_HEIGHT ); + sal_Int32 nHeight = std::max( pItem ? ( static_cast(pItem)->GetValue()) : 0, sal_uInt32(1) ); + m_xHeightMF->set_value(m_xHeightMF->normalize(nHeight), FieldUnit::TWIP); + m_xHeightMF->save_value(); + m_fWidthHeightRatio = double(nWidth) / double(nHeight); + + if(m_bPositioningDisabled) + return; + + pItem = GetItem( *rSet, SID_ATTR_TRANSFORM_HORI_ORIENT); + if(pItem) + { + short nHoriOrientation = static_cast< const SfxInt16Item*>(pItem)->GetValue(); + m_nOldH = nHoriOrientation; + } + pItem = GetItem( *rSet, SID_ATTR_TRANSFORM_VERT_ORIENT); + if(pItem) + { + short nVertOrientation = static_cast< const SfxInt16Item*>(pItem)->GetValue(); + m_nOldV = nVertOrientation; + } + pItem = GetItem( *rSet, SID_ATTR_TRANSFORM_HORI_RELATION); + if(pItem) + { + m_nOldHRel = static_cast< const SfxInt16Item*>(pItem)->GetValue(); + } + + pItem = GetItem( *rSet, SID_ATTR_TRANSFORM_VERT_RELATION); + if(pItem) + { + m_nOldVRel = static_cast< const SfxInt16Item*>(pItem)->GetValue(); + } + pItem = GetItem( *rSet, SID_ATTR_TRANSFORM_HORI_MIRROR); + if(pItem) + m_xHoriMirrorCB->set_active(static_cast(pItem)->GetValue()); + m_xHoriMirrorCB->save_state(); + + sal_Int32 nHoriPos = 0; + sal_Int32 nVertPos = 0; + pItem = GetItem( *rSet, SID_ATTR_TRANSFORM_HORI_POSITION); + if(pItem) + nHoriPos = static_cast(pItem)->GetValue(); + pItem = GetItem( *rSet, SID_ATTR_TRANSFORM_VERT_POSITION); + if(pItem) + nVertPos = static_cast(pItem)->GetValue(); + + InitPos(nAnchorType, m_nOldH, m_nOldHRel, m_nOldV, m_nOldVRel, nHoriPos, nVertPos); + + m_xVertByMF->save_value(); + m_xHoriByMF->save_value(); + // #i18732# + m_xFollowCB->save_state(); + + RangeModifyHdl(m_xWidthMF->get_widget()); // initially set maximum values +} + +DeactivateRC SvxSwPosSizeTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if( _pSet ) + { + _pSet->Put(SfxBoolItem(GetWhich( SID_ATTR_TRANSFORM_PROTECT_POS ), + m_xPositionCB->get_active())); + _pSet->Put(SfxBoolItem(GetWhich( SID_ATTR_TRANSFORM_PROTECT_SIZE ), + m_xSizeCB->get_active())); + FillItemSet( _pSet ); + } + return DeactivateRC::LeavePage; +} + +void SvxSwPosSizeTabPage::EnableAnchorTypes(SvxAnchorIds nAnchorEnable) +{ + if (nAnchorEnable & SvxAnchorIds::Fly) + m_xToFrameRB->show(); + if (!(nAnchorEnable & SvxAnchorIds::Page)) + m_xToPageRB->set_sensitive(false); +} + +RndStdIds SvxSwPosSizeTabPage::GetAnchorType(bool* pbHasChanged) +{ + RndStdIds nRet = RndStdIds::UNKNOWN; + weld::RadioButton* pCheckedButton = nullptr; + if(m_xToParaRB->get_sensitive()) + { + if(m_xToPageRB->get_active()) + { + nRet = RndStdIds::FLY_AT_PAGE; + pCheckedButton = m_xToPageRB.get(); + } + else if(m_xToParaRB->get_active()) + { + nRet = RndStdIds::FLY_AT_PARA; + pCheckedButton = m_xToParaRB.get(); + } + else if(m_xToCharRB->get_active()) + { + nRet = RndStdIds::FLY_AT_CHAR; + pCheckedButton = m_xToCharRB.get(); + } + else if(m_xAsCharRB->get_active()) + { + nRet = RndStdIds::FLY_AS_CHAR; + pCheckedButton = m_xAsCharRB.get(); + } + else if(m_xToFrameRB->get_active()) + { + nRet = RndStdIds::FLY_AT_FLY; + pCheckedButton = m_xToFrameRB.get(); + } + } + if(pbHasChanged) + { + if(pCheckedButton) + *pbHasChanged = pCheckedButton->get_state_changed_from_saved(); + else + *pbHasChanged = false; + } + return nRet; +} + +IMPL_LINK_NOARG(SvxSwPosSizeTabPage, RangeModifyClickHdl, weld::ToggleButton&, void) +{ + RangeModifyHdl(m_xWidthMF->get_widget()); +} + +IMPL_LINK_NOARG(SvxSwPosSizeTabPage, RangeModifyHdl, weld::Widget&, void) +{ + if (m_bPositioningDisabled) + return; + SvxSwFrameValidation aVal; + + aVal.nAnchorType = GetAnchorType(); + aVal.bAutoHeight = false; + aVal.bMirror = m_xHoriMirrorCB->get_active(); + // #i18732# + aVal.bFollowTextFlow = m_xFollowCB->get_active(); + + if ( m_pHMap ) + { + // horizontal alignment + sal_uInt16 nMapPos = GetMapPos(m_pHMap, *m_xHoriToLB); + sal_uInt16 nAlign = GetAlignment(m_pHMap, nMapPos, *m_xHoriToLB); + sal_uInt16 nRel = GetRelation(*m_xHoriToLB); + + aVal.nHoriOrient = static_cast(nAlign); + aVal.nHRelOrient = static_cast(nRel); + } + else + aVal.nHoriOrient = HoriOrientation::NONE; + + if ( m_pVMap ) + { + // vertical alignment + sal_uInt16 nMapPos = GetMapPos(m_pVMap, *m_xVertLB); + sal_uInt16 nAlign = GetAlignment(m_pVMap, nMapPos, *m_xVertToLB); + sal_uInt16 nRel = GetRelation(*m_xVertToLB); + + aVal.nVertOrient = static_cast(nAlign); + aVal.nVRelOrient = static_cast(nRel); + } + else + aVal.nVertOrient = VertOrientation::NONE; + + const auto nAtHorzPosVal = m_xHoriByMF->denormalize(m_xHoriByMF->get_value(FieldUnit::TWIP)); + const auto nAtVertPosVal = m_xVertByMF->denormalize(m_xVertByMF->get_value(FieldUnit::TWIP)); + + aVal.nHPos = nAtHorzPosVal; + aVal.nVPos = nAtVertPosVal; + + sal_Int32 nWidth = static_cast(m_xWidthMF->denormalize(m_xWidthMF->get_value(FieldUnit::TWIP))); + sal_Int32 nHeight = static_cast(m_xHeightMF->denormalize(m_xHeightMF->get_value(FieldUnit::TWIP))); + aVal.nWidth = nWidth; + aVal.nHeight = nHeight; + + m_aValidateLink.Call(aVal); + + // minimum width also for style + m_xHeightMF->set_min(m_xHeightMF->normalize(aVal.nMinHeight), FieldUnit::TWIP); + m_xWidthMF->set_min(m_xWidthMF->normalize(aVal.nMinWidth), FieldUnit::TWIP); + + sal_Int32 nMaxWidth(aVal.nMaxWidth); + sal_Int32 nMaxHeight(aVal.nMaxHeight); + + sal_Int64 nTmp = m_xHeightMF->normalize(nMaxHeight); + m_xHeightMF->set_max(nTmp, FieldUnit::TWIP); + + nTmp = m_xWidthMF->normalize(nMaxWidth); + m_xWidthMF->set_max(nTmp, FieldUnit::TWIP); + + m_xHoriByMF->set_range(m_xHoriByMF->normalize(aVal.nMinHPos), + m_xHoriByMF->normalize(aVal.nMaxHPos), FieldUnit::TWIP); + if ( aVal.nHPos != nAtHorzPosVal ) + m_xHoriByMF->set_value(m_xHoriByMF->normalize(aVal.nHPos), FieldUnit::TWIP); + + m_xVertByMF->set_range(m_xVertByMF->normalize(aVal.nMinVPos), + m_xVertByMF->normalize(aVal.nMaxVPos), FieldUnit::TWIP); + if ( aVal.nVPos != nAtVertPosVal ) + m_xVertByMF->set_value(m_xVertByMF->normalize(aVal.nVPos), FieldUnit::TWIP); +} + +IMPL_LINK_NOARG(SvxSwPosSizeTabPage, AnchorTypeHdl, weld::ToggleButton&, void) +{ + m_xHoriMirrorCB->set_sensitive(!m_xAsCharRB->get_active() && !m_bIsMultiSelection); + + // #i18732# - enable check box 'Follow text flow' for anchor + // type to-paragraph' and to-character + m_xFollowCB->set_sensitive(m_xToParaRB->get_active() || m_xToCharRB->get_active()); + + RndStdIds nId = GetAnchorType(); + + InitPos( nId, USHRT_MAX, 0, USHRT_MAX, 0, LONG_MAX, LONG_MAX); + RangeModifyHdl(m_xWidthMF->get_widget()); + + if(m_bHtmlMode) + { + PosHdl(*m_xHoriLB); + PosHdl(*m_xVertLB); + } +} + +IMPL_LINK_NOARG(SvxSwPosSizeTabPage, MirrorHdl, weld::ToggleButton&, void) +{ + RndStdIds nId = GetAnchorType(); + InitPos( nId, USHRT_MAX, 0, USHRT_MAX, 0, LONG_MAX, LONG_MAX); +} + +IMPL_LINK( SvxSwPosSizeTabPage, RelHdl, weld::ComboBox&, rLB, void ) +{ + bool bHori = &rLB == m_xHoriToLB.get(); + + UpdateExample(); + + if (m_bHtmlMode && RndStdIds::FLY_AT_CHAR == GetAnchorType()) // again special treatment + { + if(bHori) + { + sal_uInt16 nRel = GetRelation(*m_xHoriToLB); + if(RelOrientation::PRINT_AREA == nRel && 0 == m_xVertLB->get_active()) + { + m_xVertLB->set_active(1); + } + else if(RelOrientation::CHAR == nRel && 1 == m_xVertLB->get_active()) + { + m_xVertLB->set_active(0); + } + } + } + RangeModifyHdl(m_xWidthMF->get_widget()); +} + +IMPL_LINK(SvxSwPosSizeTabPage, PosHdl, weld::ComboBox&, rLB, void) +{ + bool bHori = &rLB == m_xHoriLB.get(); + weld::ComboBox* pRelLB = bHori ? m_xHoriToLB.get() : m_xVertToLB.get(); + weld::Label* pRelFT = bHori ? m_xHoriToFT.get() : m_xVertToFT.get(); + FrmMap const *pMap = bHori ? m_pHMap : m_pVMap; + + + sal_uInt16 nMapPos = GetMapPos(pMap, rLB); + sal_uInt16 nAlign = GetAlignment(pMap, nMapPos, *pRelLB); + + if (bHori) + { + bool bEnable = HoriOrientation::NONE == nAlign; + m_xHoriByMF->set_sensitive( bEnable ); + m_xHoriByFT->set_sensitive( bEnable ); + } + else + { + bool bEnable = VertOrientation::NONE == nAlign; + m_xVertByMF->set_sensitive( bEnable ); + m_xVertByFT->set_sensitive( bEnable ); + } + + RangeModifyHdl(m_xWidthMF->get_widget()); + + short nRel = 0; + if (rLB.get_active() != -1) + { + if (pRelLB->get_active() != -1) + nRel = reinterpret_cast(pRelLB->get_active_id().toUInt64())->nRelation; + + FillRelLB(pMap, nMapPos, nAlign, nRel, *pRelLB, *pRelFT); + } + else + pRelLB->clear(); + + UpdateExample(); + + // special treatment for HTML-Mode with horz-vert-dependencies + if (!(m_bHtmlMode && RndStdIds::FLY_AT_CHAR == GetAnchorType())) + return; + + bool bSet = false; + if(bHori) + { + // on the right only below is allowed - from the left only at the top + // from the left at the character -> below + if((HoriOrientation::LEFT == nAlign || HoriOrientation::RIGHT == nAlign) && + 0 == m_xVertLB->get_active()) + { + if(RelOrientation::FRAME == nRel) + m_xVertLB->set_active(1); + else + m_xVertLB->set_active(0); + bSet = true; + } + else if(HoriOrientation::LEFT == nAlign && 1 == m_xVertLB->get_active()) + { + m_xVertLB->set_active(0); + bSet = true; + } + else if(HoriOrientation::NONE == nAlign && 1 == m_xVertLB->get_active()) + { + m_xVertLB->set_active(0); + bSet = true; + } + if(bSet) + PosHdl(*m_xVertLB); + } + else + { + if(VertOrientation::TOP == nAlign) + { + if(1 == m_xHoriLB->get_active()) + { + m_xHoriLB->set_active(0); + bSet = true; + } + m_xHoriToLB->set_active(1); + } + else if(VertOrientation::CHAR_BOTTOM == nAlign) + { + if(2 == m_xHoriLB->get_active()) + { + m_xHoriLB->set_active(0); + bSet = true; + } + m_xHoriToLB->set_active(0) ; + } + if(bSet) + PosHdl(*m_xHoriLB); + } +} + +IMPL_LINK( SvxSwPosSizeTabPage, ModifyHdl, weld::MetricSpinButton&, rEdit, void ) +{ + auto nWidth = m_xWidthMF->denormalize(m_xWidthMF->get_value(FieldUnit::TWIP)); + auto nHeight = m_xHeightMF->denormalize(m_xHeightMF->get_value(FieldUnit::TWIP)); + if (m_xKeepRatioCB->get_active()) + { + if ( &rEdit == m_xWidthMF.get() ) + { + nHeight = int(static_cast(nWidth) / m_fWidthHeightRatio); + m_xHeightMF->set_value(m_xHeightMF->normalize(nHeight), FieldUnit::TWIP); + } + else if(&rEdit == m_xHeightMF.get()) + { + nWidth = int(static_cast(nHeight) * m_fWidthHeightRatio); + m_xWidthMF->set_value(m_xWidthMF->normalize(nWidth), FieldUnit::TWIP); + } + } + m_fWidthHeightRatio = nHeight ? double(nWidth) / double(nHeight) : 1.0; + UpdateExample(); +} + +IMPL_LINK_NOARG(SvxSwPosSizeTabPage, ProtectHdl, weld::ToggleButton&, void) +{ + if (m_xSizeCB->get_sensitive()) + { + m_nProtectSizeState = m_xSizeCB->get_state(); + } + + m_xSizeCB->set_state(m_xPositionCB->get_state() == TRISTATE_TRUE ? TRISTATE_TRUE : m_nProtectSizeState); + m_xSizeCB->set_sensitive(m_xPositionCB->get_sensitive() && !m_xPositionCB->get_active()); +} + +short SvxSwPosSizeTabPage::GetRelation(const weld::ComboBox& rRelationLB) +{ + short nRel = 0; + int nPos = rRelationLB.get_active(); + if (nPos != -1) + { + RelationMap *pEntry = reinterpret_cast(rRelationLB.get_id(nPos).toUInt64()); + nRel = pEntry->nRelation; + } + + return nRel; +} + +short SvxSwPosSizeTabPage::GetAlignment(FrmMap const *pMap, sal_uInt16 nMapPos, const weld::ComboBox& rRelationLB) +{ + short nAlign = 0; + + // #i22341# - special handling also for map , + // because it contains ambiguous items for alignment + if (pMap == aVAsCharHtmlMap || pMap == aVAsCharMap || + pMap == aVCharMap ) + { + if (rRelationLB.get_active() != -1) + { + LB nRel = reinterpret_cast(rRelationLB.get_active_id().toUInt64())->nLBRelation; + std::size_t nMapCount = ::lcl_GetFrmMapCount(pMap); + SvxSwFramePosString::StringId eStrId = pMap[nMapPos].eStrId; + + for (std::size_t i = 0; i < nMapCount; i++) + { + if (pMap[i].eStrId == eStrId) + { + LB nLBRelations = pMap[i].nLBRelations; + if (nLBRelations & nRel) + { + nAlign = pMap[i].nAlign; + break; + } + } + } + } + } + else if (pMap) + nAlign = pMap[nMapPos].nAlign; + + return nAlign; +} + +sal_uInt16 SvxSwPosSizeTabPage::GetMapPos(FrmMap const *pMap, const weld::ComboBox& rAlignLB) +{ + sal_uInt16 nMapPos = 0; + int nLBSelPos = rAlignLB.get_active(); + + if (nLBSelPos != -1) + { + if (pMap == aVAsCharHtmlMap || pMap == aVAsCharMap) + { + std::size_t nMapCount = ::lcl_GetFrmMapCount(pMap); + OUString sSelEntry(rAlignLB.get_active_text()); + + for (std::size_t i = 0; i < nMapCount; i++) + { + SvxSwFramePosString::StringId eResId = pMap[i].eStrId; + + OUString sEntry = SvxSwFramePosString::GetString(eResId); + + if (sEntry == sSelEntry) + { + nMapPos = sal::static_int_cast< sal_uInt16 >(i); + break; + } + } + } + else + nMapPos = nLBSelPos; + } + + return nMapPos; +} + +void SvxSwPosSizeTabPage::InitPos(RndStdIds nAnchor, + sal_uInt16 nH, + sal_uInt16 nHRel, + sal_uInt16 nV, + sal_uInt16 nVRel, + long nX, + long nY) +{ + int nPos = m_xVertLB->get_active(); + if (nPos != -1 && m_pVMap) + { + m_nOldV = m_pVMap[nPos].nAlign; + nPos = m_xVertToLB->get_active(); + if (nPos != -1) + m_nOldVRel = reinterpret_cast(m_xVertToLB->get_id(nPos).toUInt64())->nRelation; + } + + nPos = m_xHoriLB->get_active(); + if (nPos != -1 && m_pHMap) + { + m_nOldH = m_pHMap[nPos].nAlign; + + nPos = m_xHoriToLB->get_active(); + if (nPos != -1) + m_nOldHRel = reinterpret_cast(m_xHoriToLB->get_id(nPos).toUInt64())->nRelation; + } + + bool bEnable = true; + if( m_bIsMultiSelection ) + { + m_pVMap = aVMultiSelectionMap; + m_pHMap = aHMultiSelectionMap; + } + else if (nAnchor == RndStdIds::FLY_AT_PAGE) + { + m_pVMap = m_bHtmlMode ? aVPageHtmlMap : aVPageMap; + m_pHMap = m_bHtmlMode ? aHPageHtmlMap : aHPageMap; + } + else if (nAnchor == RndStdIds::FLY_AT_FLY) + { + // #i18732# - own vertical alignment map for to frame + // anchored objects. + m_pVMap = m_bHtmlMode ? aVFlyHtmlMap : aVFrameMap; + m_pHMap = m_bHtmlMode ? aHFlyHtmlMap : aHFrameMap; + } + else if (nAnchor == RndStdIds::FLY_AT_PARA) + { + if(m_bHtmlMode) + { + m_pVMap = aVParaHtmlMap; + m_pHMap = aHParaHtmlAbsMap; + } + else + { + m_pVMap = aVParaMap; + m_pHMap = aHParaMap; + } + } + else if (nAnchor == RndStdIds::FLY_AT_CHAR) + { + if(m_bHtmlMode) + { + m_pVMap = aVCharHtmlAbsMap; + m_pHMap = aHCharHtmlAbsMap; + } + else + { + m_pVMap = aVCharMap; + m_pHMap = aHCharMap; + } + } + else if (nAnchor == RndStdIds::FLY_AS_CHAR) + { + m_pVMap = m_bHtmlMode ? aVAsCharHtmlMap : aVAsCharMap; + m_pHMap = nullptr; + bEnable = false; + } + m_xHoriLB->set_sensitive(bEnable); + m_xHoriFT->set_sensitive(bEnable); + + // select current Pos + // horizontal + if ( nH == USHRT_MAX ) + { + nH = m_nOldH; + nHRel = m_nOldHRel; + } + // #i22341# - pass as 3rd parameter to method + sal_uInt16 nMapPos = FillPosLB(m_pHMap, nH, nHRel, *m_xHoriLB); + FillRelLB(m_pHMap, nMapPos, nH, nHRel, *m_xHoriToLB, *m_xHoriToFT); + + // vertical + if ( nV == USHRT_MAX ) + { + nV = m_nOldV; + nVRel = m_nOldVRel; + } + // #i22341# - pass as 3rd parameter to method + nMapPos = FillPosLB(m_pVMap, nV, nVRel, *m_xVertLB); + FillRelLB(m_pVMap, nMapPos, nV, nVRel, *m_xVertToLB, *m_xVertToFT); + + // Edits init + bEnable = nH == HoriOrientation::NONE && nAnchor != RndStdIds::FLY_AS_CHAR; //#61359# why not in formats&& !bFormat; + if (!bEnable) + { + m_xHoriByMF->set_value(0, FieldUnit::TWIP); + } + else if(m_bIsMultiSelection) + { + m_xHoriByMF->set_value(m_xHoriByMF->normalize(m_aRect.Left()), FieldUnit::TWIP); + } + else + { + if (nX != LONG_MAX) + m_xHoriByMF->set_value(m_xHoriByMF->normalize(nX), FieldUnit::TWIP); + } + m_xHoriByFT->set_sensitive(bEnable); + m_xHoriByMF->set_sensitive(bEnable); + + bEnable = nV == VertOrientation::NONE; + if ( !bEnable ) + { + m_xVertByMF->set_value( 0, FieldUnit::TWIP ); + } + else if(m_bIsMultiSelection) + { + m_xVertByMF->set_value(m_xVertByMF->normalize(m_aRect.Top()), FieldUnit::TWIP); + } + else + { + if (nAnchor == RndStdIds::FLY_AS_CHAR) + { + if ( nY == LONG_MAX ) + nY = 0; + else + nY *= -1; + } + if ( nY != LONG_MAX ) + m_xVertByMF->set_value( m_xVertByMF->normalize(nY), FieldUnit::TWIP ); + } + m_xVertByFT->set_sensitive( bEnable ); + m_xVertByMF->set_sensitive( bEnable ); + UpdateExample(); +} + +void SvxSwPosSizeTabPage::UpdateExample() +{ + int nPos = m_xHoriLB->get_active(); + if (m_pHMap && nPos != -1) + { + sal_uInt16 nMapPos = GetMapPos(m_pHMap, *m_xHoriLB); + short nAlign = GetAlignment(m_pHMap, nMapPos, *m_xHoriToLB); + short nRel = GetRelation(*m_xHoriToLB); + + m_aExampleWN.SetHAlign(nAlign); + m_aExampleWN.SetHoriRel(nRel); + } + + nPos = m_xVertLB->get_active(); + if (m_pVMap && nPos != -1) + { + sal_uInt16 nMapPos = GetMapPos(m_pVMap, *m_xVertLB); + sal_uInt16 nAlign = GetAlignment(m_pVMap, nMapPos, *m_xVertToLB); + sal_uInt16 nRel = GetRelation(*m_xVertToLB); + + m_aExampleWN.SetVAlign(nAlign); + m_aExampleWN.SetVertRel(nRel); + } + + // Size + auto nXPos = m_xHoriByMF->denormalize(m_xHoriByMF->get_value(FieldUnit::TWIP)); + auto nYPos = m_xVertByMF->denormalize(m_xVertByMF->get_value(FieldUnit::TWIP)); + m_aExampleWN.SetRelPos(Point(nXPos, nYPos)); + + m_aExampleWN.SetAnchor( GetAnchorType() ); + m_aExampleWN.Invalidate(); +} + +void SvxSwPosSizeTabPage::FillRelLB(FrmMap const *pMap, sal_uInt16 nMapPos, sal_uInt16 nAlign, + sal_uInt16 nRel, weld::ComboBox& rLB, weld::Label& rFT) +{ + OUString sSelEntry; + LB nLBRelations = LB::NONE; + std::size_t nMapCount = ::lcl_GetFrmMapCount(pMap); + + rLB.clear(); + + if (nMapPos < nMapCount) + { + if (pMap == aVAsCharHtmlMap || pMap == aVAsCharMap) + { + OUString sOldEntry(rLB.get_active_text()); + SvxSwFramePosString::StringId eStrId = pMap[nMapPos].eStrId; + + for (std::size_t _nMapPos = 0; _nMapPos < nMapCount; _nMapPos++) + { + if (pMap[_nMapPos].eStrId == eStrId) + { + nLBRelations = pMap[_nMapPos].nLBRelations; + for (size_t nRelPos = 0; nRelPos < SAL_N_ELEMENTS(aAsCharRelationMap); nRelPos++) + { + if (nLBRelations & aAsCharRelationMap[nRelPos].nLBRelation) + { + SvxSwFramePosString::StringId sStrId1 = aAsCharRelationMap[nRelPos].eStrId; + + sStrId1 = lcl_ChangeResIdToVerticalOrRTL(sStrId1, m_bIsVerticalFrame, m_bIsInRightToLeft); + OUString sEntry = SvxSwFramePosString::GetString(sStrId1); + rLB.append(OUString::number(reinterpret_cast(&aAsCharRelationMap[nRelPos])), sEntry); + if (pMap[_nMapPos].nAlign == nAlign) + sSelEntry = sEntry; + break; + } + } + } + } + if (!sSelEntry.isEmpty()) + rLB.set_active_text(sSelEntry); + else + { + rLB.set_active_text(sOldEntry); + if (rLB.get_active() == -1) + { + for (int i = 0; i < rLB.get_count(); i++) + { + RelationMap *pEntry = reinterpret_cast(rLB.get_id(i).toUInt64()); + if (pEntry->nLBRelation == LB::RelChar) // Default + { + rLB.set_active(i); + break; + } + } + } + } + } + else + { + // #i22341# - special handling for map , + // because its ambiguous in its /. + if ( pMap == aVCharMap ) + { + nLBRelations = ::lcl_GetLBRelationsForStrID( pMap, + ( m_xHoriMirrorCB->get_active() + ? pMap[nMapPos].eMirrorStrId + : pMap[nMapPos].eStrId ), + m_xHoriMirrorCB->get_active() ); + } + else + { + nLBRelations = pMap[nMapPos].nLBRelations; + } + + for (sal_uLong nBit = 1; nBit < sal_uLong(LB::LAST); nBit <<= 1) + { + if (nLBRelations & static_cast(nBit)) + { + for (size_t nRelPos = 0; nRelPos < SAL_N_ELEMENTS(aRelationMap); nRelPos++) + { + if (aRelationMap[nRelPos].nLBRelation == static_cast(nBit)) + { + SvxSwFramePosString::StringId sStrId1 = m_xHoriMirrorCB->get_active() ? aRelationMap[nRelPos].eMirrorStrId : aRelationMap[nRelPos].eStrId; + sStrId1 = lcl_ChangeResIdToVerticalOrRTL(sStrId1, m_bIsVerticalFrame, m_bIsInRightToLeft); + OUString sEntry = SvxSwFramePosString::GetString(sStrId1); + rLB.append(OUString::number(reinterpret_cast(&aRelationMap[nRelPos])), sEntry); + if (sSelEntry.isEmpty() && aRelationMap[nRelPos].nRelation == nRel) + sSelEntry = sEntry; + } + } + } + } + if (!sSelEntry.isEmpty()) + rLB.set_active_text(sSelEntry); + else + { + // Probably anchor change. So look for a similar relation. + switch (nRel) + { + case RelOrientation::FRAME: nRel = RelOrientation::PAGE_FRAME; break; + case RelOrientation::PRINT_AREA: nRel = RelOrientation::PAGE_PRINT_AREA; break; + case RelOrientation::PAGE_LEFT: nRel = RelOrientation::FRAME_LEFT; break; + case RelOrientation::PAGE_RIGHT: nRel = RelOrientation::FRAME_RIGHT; break; + case RelOrientation::FRAME_LEFT: nRel = RelOrientation::PAGE_LEFT; break; + case RelOrientation::FRAME_RIGHT: nRel = RelOrientation::PAGE_RIGHT; break; + case RelOrientation::PAGE_FRAME: nRel = RelOrientation::FRAME; break; + case RelOrientation::PAGE_PRINT_AREA: nRel = RelOrientation::PRINT_AREA; break; + + default: + if (rLB.get_count()) + { + RelationMap *pEntry = reinterpret_cast(rLB.get_id(rLB.get_count() - 1).toUInt64()); + nRel = pEntry->nRelation; + } + break; + } + + for (int i = 0; i < rLB.get_count(); ++i) + { + RelationMap *pEntry = reinterpret_cast(rLB.get_id(i).toUInt64()); + if (pEntry->nRelation == nRel) + { + rLB.set_active(i); + break; + } + } + + if (rLB.get_active() == -1) + rLB.set_active(0); + } + } + } + + rLB.set_sensitive(rLB.get_count() != 0); + rFT.set_sensitive(rLB.get_count() != 0); + + RelHdl(rLB); +} + +sal_uInt16 SvxSwPosSizeTabPage::FillPosLB(FrmMap const *_pMap, + sal_uInt16 _nAlign, + const sal_uInt16 _nRel, + weld::ComboBox& _rLB) +{ + OUString sSelEntry, sOldEntry; + sOldEntry = _rLB.get_active_text(); + + _rLB.clear(); + + // #i22341# - determine all possible listbox relations for + // given relation for map + const LB nLBRelations = (_pMap != aVCharMap) + ? LB::NONE + : ::lcl_GetLBRelationsForRelations( _nRel ); + + // fill listbox + std::size_t nCount = ::lcl_GetFrmMapCount(_pMap); + for (std::size_t i = 0; _pMap && i < nCount; ++i) + { + SvxSwFramePosString::StringId eStrId = m_xHoriMirrorCB->get_active() ? _pMap[i].eMirrorStrId : _pMap[i].eStrId; + eStrId = lcl_ChangeResIdToVerticalOrRTL(eStrId, m_bIsVerticalFrame, m_bIsInRightToLeft); + OUString sEntry(SvxSwFramePosString::GetString(eStrId)); + if (_rLB.find_text(sEntry) == -1) + { + // don't insert duplicate entries at character wrapped borders + _rLB.append_text(sEntry); + } + // #i22341# - add condition to handle map + // that is ambiguous in the alignment. + if ( _pMap[i].nAlign == _nAlign && + ( _pMap != aVCharMap || _pMap[i].nLBRelations & nLBRelations ) ) + { + sSelEntry = sEntry; + } + } + + _rLB.set_active_text(sSelEntry); + if (_rLB.get_active() == -1) + _rLB.set_active_text(sOldEntry); + + if (_rLB.get_active() == -1) + _rLB.set_active(0); + + PosHdl(_rLB); + + return GetMapPos(_pMap, _rLB); +} + +void SvxSwPosSizeTabPage::SetView( const SdrView* pSdrView ) +{ + m_pSdrView = pSdrView; + if(!m_pSdrView) + { + OSL_FAIL("No SdrView* set"); + return; + } + + // setting of the rectangle and the working area + m_aRect = m_pSdrView->GetAllMarkedRect(); + m_pSdrView->GetSdrPageView()->LogicToPagePos( m_aRect ); + + // get WorkArea + m_aWorkArea = m_pSdrView->GetWorkArea(); + + // consider anchor position (for Writer) + const SdrMarkList& rMarkList = m_pSdrView->GetMarkedObjectList(); + if( rMarkList.GetMarkCount() > 0 ) + { + const SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj(); + m_aAnchorPos = pObj->GetAnchorPos(); + + if( m_aAnchorPos != Point(0,0) ) // -> Writer + { + for( size_t i = 1; i < rMarkList.GetMarkCount(); ++i ) + { + pObj = rMarkList.GetMark( i )->GetMarkedSdrObj(); + if( m_aAnchorPos != pObj->GetAnchorPos() ) + { + // different anchor positions -> disable positioning + m_xPosFrame->set_sensitive(false); + m_bPositioningDisabled = true; + return; + } + } + } + Point aPt = m_aAnchorPos * -1; + Point aPt2 = aPt; + + aPt += m_aWorkArea.TopLeft(); + m_aWorkArea.SetPos( aPt ); + + aPt2 += m_aRect.TopLeft(); + m_aRect.SetPos( aPt2 ); + } + + // this should happen via SID_ATTR_TRANSFORM_AUTOSIZE + if( rMarkList.GetMarkCount() != 1 ) + m_bIsMultiSelection = true; +#if OSL_DEBUG_LEVEL > 1 + else + { + const SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj(); + SdrObjKind eKind = (SdrObjKind) pObj->GetObjIdentifier(); + if( ( pObj->GetObjInventor() == SdrInventor::Default ) && + ( eKind==OBJ_TEXT || eKind==OBJ_TITLETEXT || eKind==OBJ_OUTLINETEXT) && + pObj->HasText() ) + { + OSL_FAIL("AutoWidth/AutoHeight should be enabled"); + } + } +#endif +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/tabarea.cxx b/cui/source/tabpages/tabarea.cxx new file mode 100644 index 000000000..a400c0207 --- /dev/null +++ b/cui/source/tabpages/tabarea.cxx @@ -0,0 +1,248 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include + +#include +#include +#include +#include + +SvxAreaTabDialog::SvxAreaTabDialog +( + weld::Window* pParent, + const SfxItemSet* pAttr, + SdrModel* pModel, + bool bShadow +) + : SfxTabDialogController(pParent, "cui/ui/areadialog.ui", "AreaDialog", pAttr) + , mpDrawModel ( pModel ), + mpColorList ( pModel->GetColorList() ), + mpNewColorList ( pModel->GetColorList() ), + mpGradientList ( pModel->GetGradientList() ), + mpNewGradientList ( pModel->GetGradientList() ), + mpHatchingList ( pModel->GetHatchList() ), + mpNewHatchingList ( pModel->GetHatchList() ), + mpBitmapList ( pModel->GetBitmapList() ), + mpNewBitmapList ( pModel->GetBitmapList() ), + mpPatternList ( pModel->GetPatternList() ), + mpNewPatternList ( pModel->GetPatternList() ), + + mnColorListState ( ChangeType::NONE ), + mnBitmapListState ( ChangeType::NONE ), + mnPatternListState ( ChangeType::NONE ), + mnGradientListState ( ChangeType::NONE ), + mnHatchingListState ( ChangeType::NONE ) +{ + AddTabPage("RID_SVXPAGE_AREA", SvxAreaTabPage::Create, nullptr); + + if (bShadow) + { + AddTabPage("RID_SVXPAGE_SHADOW", SvxShadowTabPage::Create, nullptr); + } + else + { + RemoveTabPage( "RID_SVXPAGE_SHADOW" ); + } + + AddTabPage( "RID_SVXPAGE_TRANSPARENCE", SvxTransparenceTabPage::Create, nullptr); + + weld::Button& rBtnCancel = GetCancelButton(); + rBtnCancel.connect_clicked(LINK(this, SvxAreaTabDialog, CancelHdlImpl)); +} + +void SvxAreaTabDialog::SavePalettes() +{ + SfxObjectShell* pShell = SfxObjectShell::Current(); + if( mpNewColorList != mpDrawModel->GetColorList() ) + { + mpDrawModel->SetPropertyList( static_cast(mpNewColorList.get()) ); + SvxColorListItem aColorListItem( mpNewColorList, SID_COLOR_TABLE ); + if ( pShell ) + pShell->PutItem( aColorListItem ); + else + mpDrawModel->GetItemPool().Put(aColorListItem,SID_COLOR_TABLE); + mpColorList = mpDrawModel->GetColorList(); + } + if( mpNewGradientList != mpDrawModel->GetGradientList() ) + { + mpDrawModel->SetPropertyList( static_cast(mpNewGradientList.get()) ); + SvxGradientListItem aItem( mpNewGradientList, SID_GRADIENT_LIST ); + if ( pShell ) + pShell->PutItem( aItem ); + else + mpDrawModel->GetItemPool().Put(aItem,SID_GRADIENT_LIST); + mpGradientList = mpDrawModel->GetGradientList(); + } + if( mpNewHatchingList != mpDrawModel->GetHatchList() ) + { + mpDrawModel->SetPropertyList( static_cast(mpNewHatchingList.get()) ); + SvxHatchListItem aItem( mpNewHatchingList, SID_HATCH_LIST ); + if ( pShell ) + pShell->PutItem( aItem ); + else + mpDrawModel->GetItemPool().Put(aItem,SID_HATCH_LIST); + mpHatchingList = mpDrawModel->GetHatchList(); + } + if( mpNewBitmapList != mpDrawModel->GetBitmapList() ) + { + mpDrawModel->SetPropertyList( static_cast(mpNewBitmapList.get()) ); + SvxBitmapListItem aItem( mpNewBitmapList, SID_BITMAP_LIST ); + if ( pShell ) + pShell->PutItem( aItem ); + else + mpDrawModel->GetItemPool().Put(aItem,SID_BITMAP_LIST); + mpBitmapList = mpDrawModel->GetBitmapList(); + } + if( mpNewPatternList != mpDrawModel->GetPatternList() ) + { + mpDrawModel->SetPropertyList( static_cast(mpNewPatternList.get()) ); + SvxPatternListItem aItem( mpNewPatternList, SID_PATTERN_LIST ); + if( pShell ) + pShell->PutItem( aItem ); + else + mpDrawModel->GetItemPool().Put(aItem,SID_PATTERN_LIST); + mpPatternList = mpDrawModel->GetPatternList(); + } + + // save the tables when they have been changed + + OUString aPalettePath(SvtPathOptions().GetPalettePath()); + OUString aPath; + sal_Int32 nIndex = 0; + do + { + aPath = aPalettePath.getToken(0, ';', nIndex); + } + while (nIndex >= 0); + + if( mnHatchingListState & ChangeType::MODIFIED ) + { + mpHatchingList->SetPath( aPath ); + mpHatchingList->Save(); + + SvxHatchListItem aItem( mpHatchingList, SID_HATCH_LIST ); + // ToolBoxControls are informed: + if ( pShell ) + pShell->PutItem( aItem ); + else + mpDrawModel->GetItemPool().Put(aItem); + } + + if( mnBitmapListState & ChangeType::MODIFIED ) + { + mpBitmapList->SetPath( aPath ); + mpBitmapList->Save(); + + SvxBitmapListItem aItem( mpBitmapList, SID_BITMAP_LIST ); + // ToolBoxControls are informed: + if ( pShell ) + pShell->PutItem( aItem ); + else + { + mpDrawModel->GetItemPool().Put(aItem); + } + } + + if( mnPatternListState & ChangeType::MODIFIED ) + { + mpPatternList->SetPath( aPath ); + mpPatternList->Save(); + + SvxPatternListItem aItem( mpPatternList, SID_PATTERN_LIST ); + // ToolBoxControls are informed: + if( pShell ) + pShell->PutItem( aItem ); + else + mpDrawModel->GetItemPool().Put(aItem); + } + + if( mnGradientListState & ChangeType::MODIFIED ) + { + mpGradientList->SetPath( aPath ); + mpGradientList->Save(); + + SvxGradientListItem aItem( mpGradientList, SID_GRADIENT_LIST ); + // ToolBoxControls are informed: + if ( pShell ) + pShell->PutItem( aItem ); + else + { + mpDrawModel->GetItemPool().Put(aItem); + } + } + + if (mnColorListState & ChangeType::MODIFIED && mpColorList.is()) + { + SvxColorListItem aItem( mpColorList, SID_COLOR_TABLE ); + // ToolBoxControls are informed: + if ( pShell ) + pShell->PutItem( aItem ); + else + { + mpDrawModel->GetItemPool().Put(aItem); + } + } +} + +short SvxAreaTabDialog::Ok() +{ + SavePalettes(); + // RET_OK is returned, if at least one + // TabPage returns sal_True in FillItemSet(). + // This happens by default at the moment. + return SfxTabDialogController::Ok(); +} + +IMPL_LINK_NOARG(SvxAreaTabDialog, CancelHdlImpl, weld::Button&, void) +{ + SavePalettes(); + m_xDialog->response(RET_CANCEL); +} + +void SvxAreaTabDialog::PageCreated(const OString& rId, SfxTabPage &rPage) +{ + if (rId == "RID_SVXPAGE_AREA") + { + static_cast(rPage).SetColorList( mpColorList ); + static_cast(rPage).SetGradientList( mpGradientList ); + static_cast(rPage).SetHatchingList( mpHatchingList ); + static_cast(rPage).SetBitmapList( mpBitmapList ); + static_cast(rPage).SetPatternList( mpPatternList ); + static_cast(rPage).SetGrdChgd( &mnGradientListState ); + static_cast(rPage).SetHtchChgd( &mnHatchingListState ); + static_cast(rPage).SetBmpChgd( &mnBitmapListState ); + static_cast(rPage).SetPtrnChgd( &mnPatternListState ); + static_cast(rPage).SetColorChgd( &mnColorListState ); + } + else if (rId == "RID_SVXPAGE_SHADOW") + { + static_cast(rPage).SetColorList( mpColorList ); + static_cast(rPage).SetColorChgd( &mnColorListState ); + } + else if (rId == "RID_SVXPAGE_TRANSPARENCE") + { + static_cast(rPage).SetPageType( PageType::Area ); + static_cast(rPage).SetDlgType( 0 ); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/tabline.cxx b/cui/source/tabpages/tabline.cxx new file mode 100644 index 000000000..f4e0a1268 --- /dev/null +++ b/cui/source/tabpages/tabline.cxx @@ -0,0 +1,207 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +SvxLineTabDialog::SvxLineTabDialog(weld::Window* pParent, const SfxItemSet* pAttr, + SdrModel* pModel, const SdrObject* pSdrObj, bool bHasObj) + : SfxTabDialogController(pParent, "cui/ui/linedialog.ui", "LineDialog", pAttr) + , pDrawModel(pModel) + , pObj(pSdrObj) + , pColorList(pModel->GetColorList()) + , mpNewColorList(pModel->GetColorList()) + , pDashList(pModel->GetDashList()) + , pNewDashList(pModel->GetDashList()) + , pLineEndList(pModel->GetLineEndList()) + , pNewLineEndList(pModel->GetLineEndList()) + , bObjSelected(bHasObj) + , nLineEndListState(ChangeType::NONE) + , nDashListState(ChangeType::NONE) + , mnColorListState(ChangeType::NONE) + , nPageType(PageType::Area) // We use it here primarily to get the right attributes with FillItemSet + , nPosDashLb(0) + , nPosLineEndLb(0) +{ + bool bLineOnly = false; + if( pObj && pObj->GetObjInventor() == SdrInventor::Default ) + { + switch( pObj->GetObjIdentifier() ) + { + case OBJ_LINE: + case OBJ_PLIN: + case OBJ_PATHLINE: + case OBJ_FREELINE: + case OBJ_MEASURE: + case OBJ_EDGE: + bLineOnly = true; + break; + + default: + break; + } + + } + + AddTabPage("RID_SVXPAGE_LINE", SvxLineTabPage::Create, nullptr); + if( bLineOnly ) + AddTabPage("RID_SVXPAGE_SHADOW", SvxShadowTabPage::Create, nullptr); + else + RemoveTabPage( "RID_SVXPAGE_SHADOW" ); + + AddTabPage("RID_SVXPAGE_LINE_DEF", SvxLineDefTabPage::Create, nullptr); + AddTabPage("RID_SVXPAGE_LINEEND_DEF", SvxLineEndDefTabPage::Create, nullptr); + + weld::Button& rBtnCancel = GetCancelButton(); + rBtnCancel.connect_clicked(LINK(this, SvxLineTabDialog, CancelHdlImpl)); +} + +void SvxLineTabDialog::SavePalettes() +{ + SfxObjectShell* pShell = SfxObjectShell::Current(); + if( mpNewColorList != pDrawModel->GetColorList() ) + { + pDrawModel->SetPropertyList( static_cast(mpNewColorList.get()) ); + if ( pShell ) + pShell->PutItem( SvxColorListItem( mpNewColorList, SID_COLOR_TABLE ) ); + pColorList = pDrawModel->GetColorList(); + } + if( pNewDashList != pDrawModel->GetDashList() ) + { + pDrawModel->SetPropertyList( static_cast(pNewDashList.get()) ); + if ( pShell ) + pShell->PutItem( SvxDashListItem( pNewDashList, SID_DASH_LIST ) ); + pDashList = pDrawModel->GetDashList(); + } + if( pNewLineEndList != pDrawModel->GetLineEndList() ) + { + pDrawModel->SetPropertyList( static_cast(pNewLineEndList.get()) ); + if ( pShell ) + pShell->PutItem( SvxLineEndListItem( pNewLineEndList, SID_LINEEND_LIST ) ); + pLineEndList = pDrawModel->GetLineEndList(); + } + + // Save the tables when they have been changed + OUString aPalettePath(SvtPathOptions().GetPalettePath()); + OUString aPath; + sal_Int32 nIndex = 0; + do + { + aPath = aPalettePath.getToken(0, ';', nIndex); + } + while (nIndex >= 0); + + if( nDashListState & ChangeType::MODIFIED ) + { + pDashList->SetPath( aPath ); + pDashList->Save(); + + // Notify ToolBoxControls + if ( pShell ) + pShell->PutItem( SvxDashListItem( pDashList, SID_DASH_LIST ) ); + } + + if( nLineEndListState & ChangeType::MODIFIED ) + { + pLineEndList->SetPath( aPath ); + pLineEndList->Save(); + + // Notify ToolBoxControls + if ( pShell ) + pShell->PutItem( SvxLineEndListItem( pLineEndList, SID_LINEEND_LIST ) ); + } + + if( mnColorListState & ChangeType::MODIFIED ) + { + pColorList->SetPath( aPath ); + pColorList->Save(); + + // Notify ToolBoxControls + if ( pShell ) + pShell->PutItem( SvxColorListItem( pColorList, SID_COLOR_TABLE ) ); + } +} + +short SvxLineTabDialog::Ok() +{ + SavePalettes(); + + // We return RET_OK if at least one TabPage in FillItemSet() returns sal_True. + // We do this by default at the moment. + return SfxTabDialogController::Ok(); +} + +IMPL_LINK_NOARG(SvxLineTabDialog, CancelHdlImpl, weld::Button&, void) +{ + SavePalettes(); + + m_xDialog->response(RET_CANCEL); +} + +void SvxLineTabDialog::PageCreated(const OString& rId, SfxTabPage &rPage) +{ + if (rId == "RID_SVXPAGE_LINE") + { + static_cast(rPage).SetDashList( pDashList ); + static_cast(rPage).SetLineEndList( pLineEndList ); + static_cast(rPage).SetDlgType( 0 ); + static_cast(rPage).SetPageType( nPageType ); + static_cast(rPage).SetPosDashLb( &nPosDashLb ); + static_cast(rPage).SetPosLineEndLb( &nPosLineEndLb ); + static_cast(rPage).SetDashChgd( &nDashListState ); + static_cast(rPage).SetLineEndChgd( &nLineEndListState ); + static_cast(rPage).SetObjSelected( bObjSelected ); + static_cast(rPage).Construct(); + static_cast(rPage).SetColorChgd( &mnColorListState ); + } + else if (rId == "RID_SVXPAGE_LINE_DEF") + { + static_cast(rPage).SetDashList( pDashList ); + static_cast(rPage).SetDlgType( 0 ); + static_cast(rPage).SetPageType( &nPageType ); + static_cast(rPage).SetPosDashLb( &nPosDashLb ); + static_cast(rPage).SetDashChgd( &nDashListState ); + static_cast(rPage).Construct(); + } + else if (rId == "RID_SVXPAGE_LINEEND_DEF") + { + static_cast(rPage).SetLineEndList( pLineEndList ); + static_cast(rPage).SetPolyObj( pObj ); + static_cast(rPage).SetDlgType( 0 ); + static_cast(rPage).SetPageType( &nPageType ); + static_cast(rPage).SetPosLineEndLb( &nPosLineEndLb ); + static_cast(rPage).SetLineEndChgd( &nLineEndListState ); + static_cast(rPage).Construct(); + } + else if (rId == "RID_SVXPAGE_SHADOW") + { + static_cast(rPage).SetColorList( pColorList ); + static_cast(rPage).SetPageType( nPageType ); + static_cast(rPage).SetDlgType( 0 ); + static_cast(rPage).SetColorChgd( &mnColorListState ); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/tabstpge.cxx b/cui/source/tabpages/tabstpge.cxx new file mode 100644 index 000000000..939a51e41 --- /dev/null +++ b/cui/source/tabpages/tabstpge.cxx @@ -0,0 +1,667 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +constexpr FieldUnit eDefUnit = FieldUnit::MM_100TH; + +const sal_uInt16 SvxTabulatorTabPage::pRanges[] = +{ + SID_ATTR_TABSTOP, + SID_ATTR_TABSTOP_OFFSET, + 0 +}; + +static void FillUpWithDefTabs_Impl( long nDefDist, SvxTabStopItem& rTabs ) +{ + if( rTabs.Count() ) + return; + { + SvxTabStop aSwTabStop( nDefDist, SvxTabAdjust::Default ); + rTabs.Insert( aSwTabStop ); + } +} + +void TabWin_Impl::Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle&) +{ + // Paint tabulators + Point aPoint; + Size aSize(GetOutputSizePixel()); + aPoint.setX( aSize.Width() / 2 ); + aPoint.setY( aSize.Height() / 2 ); + Ruler::DrawTab(rRenderContext, rRenderContext.GetSettings().GetStyleSettings().GetFontColor(), aPoint, nTabStyle); +} + +SvxTabulatorTabPage::SvxTabulatorTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rAttr) + : SfxTabPage(pPage, pController, "cui/ui/paratabspage.ui", "ParagraphTabsPage", &rAttr) + , aCurrentTab(0) + , aNewTabs(std::make_unique(0, 0, SvxTabAdjust::Left, GetWhich(SID_ATTR_TABSTOP))) + , nDefDist(0) + , m_xTabSpin(m_xBuilder->weld_metric_spin_button("SP_TABPOS", FieldUnit::CM)) + , m_xTabBox(m_xBuilder->weld_entry_tree_view("tabgrid", "ED_TABPOS", "LB_TABPOS")) + , m_xCenterTab(m_xBuilder->weld_radio_button("radiobuttonBTN_TABTYPE_CENTER")) + , m_xDezTab(m_xBuilder->weld_radio_button("radiobuttonBTN_TABTYPE_DECIMAL")) + , m_xDezChar(m_xBuilder->weld_entry("entryED_TABTYPE_DECCHAR")) + , m_xDezCharLabel(m_xBuilder->weld_label("labelFT_TABTYPE_DECCHAR")) + // lower radio buttons + , m_xNoFillChar(m_xBuilder->weld_radio_button("radiobuttonBTN_FILLCHAR_NO")) + , m_xFillPoints(m_xBuilder->weld_radio_button("radiobuttonBTN_FILLCHAR_POINTS")) + , m_xFillDashLine(m_xBuilder->weld_radio_button("radiobuttonBTN_FILLCHAR_DASHLINE")) + , m_xFillSolidLine(m_xBuilder->weld_radio_button("radiobuttonBTN_FILLCHAR_UNDERSCORE")) + , m_xFillSpecial(m_xBuilder->weld_radio_button("radiobuttonBTN_FILLCHAR_OTHER")) + , m_xFillChar(m_xBuilder->weld_entry("entryED_FILLCHAR_OTHER")) + // button bar + , m_xNewBtn(m_xBuilder->weld_button("buttonBTN_NEW")) + , m_xDelAllBtn(m_xBuilder->weld_button("buttonBTN_DELALL")) + , m_xDelBtn(m_xBuilder->weld_button("buttonBTN_DEL")) + , m_xTypeFrame(m_xBuilder->weld_container("frameFL_TABTYPE")) + , m_xFillFrame(m_xBuilder->weld_container("frameFL_FILLCHAR")) + // the tab images + , m_xLeftWin(new weld::CustomWeld(*m_xBuilder, "drawingareaWIN_TABLEFT", m_aLeftWin)) + , m_xRightWin(new weld::CustomWeld(*m_xBuilder, "drawingareaWIN_TABRIGHT", m_aRightWin)) + , m_xCenterWin(new weld::CustomWeld(*m_xBuilder, "drawingareaWIN_TABCENTER", m_aCenterWin)) + , m_xDezWin(new weld::CustomWeld(*m_xBuilder, "drawingareaWIN_TABDECIMAL", m_aDezWin)) +{ + m_aLeftWin.SetTabStyle(sal_uInt16(RULER_TAB_LEFT|WB_HORZ)); + m_aRightWin.SetTabStyle(sal_uInt16(RULER_TAB_RIGHT|WB_HORZ)); + m_aCenterWin.SetTabStyle(sal_uInt16(RULER_TAB_CENTER|WB_HORZ)); + m_aDezWin.SetTabStyle(sal_uInt16(RULER_TAB_DECIMAL|WB_HORZ)); + //upper radiobuttons + SvtCJKOptions aCJKOptions; + m_xLeftTab = m_xBuilder->weld_radio_button(aCJKOptions.IsAsianTypographyEnabled() ? "radiobuttonST_LEFTTAB_ASIAN" : "radiobuttonBTN_TABTYPE_LEFT"); + m_xRightTab = m_xBuilder->weld_radio_button(aCJKOptions.IsAsianTypographyEnabled() ? "radiobuttonST_RIGHTTAB_ASIAN" : "radiobuttonBTN_TABTYPE_RIGHT"); + m_xLeftTab->show(); + m_xRightTab->show(); + + // This page needs ExchangeSupport + SetExchangeSupport(); + + // Set metric + FieldUnit eFUnit = GetModuleFieldUnit( rAttr ); + SetFieldUnit(*m_xTabSpin, eFUnit); + + // Initialize buttons + m_xNewBtn->connect_clicked(LINK(this,SvxTabulatorTabPage, NewHdl_Impl)); + m_xDelBtn->connect_clicked(LINK(this,SvxTabulatorTabPage, DelHdl_Impl)); + m_xDelAllBtn->connect_clicked(LINK(this,SvxTabulatorTabPage, DelAllHdl_Impl)); + + Link aLink = LINK(this, SvxTabulatorTabPage, TabTypeCheckHdl_Impl); + m_xLeftTab->connect_toggled(aLink); + m_xRightTab->connect_toggled(aLink); + m_xDezTab->connect_toggled(aLink); + m_xCenterTab->connect_toggled(aLink); + + m_xDezChar->connect_focus_out(LINK(this, SvxTabulatorTabPage, GetDezCharHdl_Impl)); + m_xDezChar->set_sensitive(false); + m_xDezCharLabel->set_sensitive(false); + + aLink = LINK(this, SvxTabulatorTabPage, FillTypeCheckHdl_Impl); + m_xNoFillChar->connect_toggled(aLink); + m_xFillPoints->connect_toggled(aLink); + m_xFillDashLine->connect_toggled(aLink); + m_xFillSolidLine->connect_toggled(aLink); + m_xFillSpecial->connect_toggled(aLink); + m_xFillChar->connect_focus_out(LINK(this, SvxTabulatorTabPage, GetFillCharHdl_Impl)); + m_xFillChar->set_sensitive(false); + + m_xTabBox->connect_row_activated(LINK(this, SvxTabulatorTabPage, SelectHdl_Impl)); + m_xTabBox->connect_changed(LINK(this, SvxTabulatorTabPage, ModifyHdl_Impl)); + m_xTabBox->connect_focus_out(LINK(this, SvxTabulatorTabPage, ReformatHdl_Impl)); + + // Get the default decimal char from the system + const LocaleDataWrapper& rLocaleWrapper( Application::GetSettings().GetLocaleDataWrapper() ); + aCurrentTab.GetDecimal() = rLocaleWrapper.getNumDecimalSep()[0]; +} + +SvxTabulatorTabPage::~SvxTabulatorTabPage() +{ + m_xDezWin.reset(); + m_xCenterWin.reset(); + m_xRightWin.reset(); + m_xLeftWin.reset(); + m_xFillChar.reset(); + m_xDezChar.reset(); + m_xTabBox.reset(); +} + +bool SvxTabulatorTabPage::FillItemSet(SfxItemSet* rSet) +{ + bool bModified = false; + + // Put the controls' values in here + if (m_xNewBtn->get_sensitive()) + NewHdl_Impl(nullptr); + + // Call the LoseFocus-Handler first + GetDezCharHdl_Impl(*m_xDezChar); + GetFillCharHdl_Impl(*m_xFillChar); + + FillUpWithDefTabs_Impl(nDefDist, *aNewTabs); + SfxItemPool* pPool = rSet->GetPool(); + MapUnit eUnit = pPool->GetMetric(GetWhich(SID_ATTR_TABSTOP)); + const SfxPoolItem* pOld = GetOldItem(*rSet, SID_ATTR_TABSTOP); + + if (MapUnit::Map100thMM != eUnit) + { + // If the ItemSet contains a LRSpaceItem with negative first line indent, + // the TabStopItem needs to have a DefTab at position 0. + const SfxPoolItem* pLRSpace; + // If not in the new set, then maybe in the old one + if (SfxItemState::SET != rSet->GetItemState(GetWhich(SID_ATTR_LRSPACE), true, &pLRSpace)) + pLRSpace = GetOldItem(*rSet, SID_ATTR_LRSPACE); + + if (pLRSpace && static_cast(pLRSpace)->GetTextFirstLineOffset() < 0) + { + SvxTabStop aNull(0, SvxTabAdjust::Default); + aNewTabs->Insert(aNull); + } + + std::unique_ptr aTmp(aNewTabs->Clone()); + aTmp->Remove(0, aTmp->Count()); + + for (sal_uInt16 i = 0; i < aNewTabs->Count(); ++i) + { + SvxTabStop aTmpStop = (*aNewTabs)[i]; + aTmpStop.GetTabPos() = OutputDevice::LogicToLogic(aTmpStop.GetTabPos(), MapUnit::Map100thMM, eUnit); + aTmp->Insert(aTmpStop); + } + + if (!pOld || *static_cast(pOld) != *aTmp) + { + rSet->Put(*aTmp); + bModified = true; + } + } + else if (!pOld || *static_cast(pOld) != *aNewTabs) + { + rSet->Put(*aNewTabs); + bModified = true; + } + + return bModified; +} + +std::unique_ptr SvxTabulatorTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet) +{ + return std::make_unique(pPage, pController, *rSet); +} + +void SvxTabulatorTabPage::Reset(const SfxItemSet* rSet) +{ + SfxItemPool* pPool = rSet->GetPool(); + MapUnit eUnit = pPool->GetMetric(GetWhich(SID_ATTR_TABSTOP)); + + // Current tabs + const SfxPoolItem* pItem = GetItem(*rSet, SID_ATTR_TABSTOP); + + if (pItem) + { + if (MapUnit::Map100thMM != eUnit) + { + std::unique_ptr aTmp(static_cast(pItem->Clone())); + aNewTabs->Remove(0, aNewTabs->Count()); + + for (sal_uInt16 i = 0; i < aTmp->Count(); ++i) + { + SvxTabStop aTmpStop = (*aTmp)[i]; + aTmpStop.GetTabPos() = OutputDevice::LogicToLogic(aTmpStop.GetTabPos(), eUnit, MapUnit::Map100thMM); + aNewTabs->Insert(aTmpStop); + } + } + else + { + aNewTabs.reset(static_cast(pItem->Clone())); + } + } + else + { + aNewTabs->Remove(0, aNewTabs->Count()); + } + + // Default tab distance + nDefDist = SVX_TAB_DEFDIST; + pItem = GetItem(*rSet, SID_ATTR_TABSTOP_DEFAULTS); + + if (pItem) + nDefDist = OutputDevice::LogicToLogic(long(static_cast(pItem)->GetValue()), eUnit, MapUnit::Map100thMM); + + // Tab pos currently selected + sal_uInt16 nTabPos = 0; + pItem = GetItem(*rSet, SID_ATTR_TABSTOP_POS); + + if (pItem) + nTabPos = static_cast(pItem)->GetValue(); + + InitTabPos_Impl(nTabPos); +} + +void SvxTabulatorTabPage::DisableControls(const TabulatorDisableFlags nFlag) +{ + if (TabulatorDisableFlags::TypeLeft & nFlag) + { + m_xLeftTab->set_sensitive(false); + m_xLeftWin->set_sensitive(false); + } + if (TabulatorDisableFlags::TypeRight & nFlag) + { + m_xRightTab->set_sensitive(false); + m_xRightWin->set_sensitive(false); + } + if (TabulatorDisableFlags::TypeCenter & nFlag) + { + m_xCenterTab->set_sensitive(false); + m_xCenterWin->set_sensitive(false); + } + if (TabulatorDisableFlags::TypeDecimal & nFlag) + { + m_xDezTab->set_sensitive(false); + m_xDezWin->set_sensitive(false); + m_xDezCharLabel->set_sensitive(false); + m_xDezChar->set_sensitive(false); + } + if (TabulatorDisableFlags::TypeMask & nFlag) + m_xTypeFrame->set_sensitive(false); + if (TabulatorDisableFlags::FillNone & nFlag) + m_xNoFillChar->set_sensitive(false); + if (TabulatorDisableFlags::FillPoint & nFlag) + m_xFillPoints->set_sensitive(false); + if (TabulatorDisableFlags::FillDashLine & nFlag) + m_xFillDashLine->set_sensitive(false); + if (TabulatorDisableFlags::FillSolidLine & nFlag) + m_xFillSolidLine->set_sensitive(false); + if (TabulatorDisableFlags::FillSpecial & nFlag) + { + m_xFillSpecial->set_sensitive(false); + m_xFillChar->set_sensitive(false); + } + if (TabulatorDisableFlags::FillMask & nFlag) + m_xFillFrame->set_sensitive(false); +} + +DeactivateRC SvxTabulatorTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if ( _pSet ) + FillItemSet( _pSet ); + return DeactivateRC::LeavePage; +} + +void SvxTabulatorTabPage::InitTabPos_Impl( sal_uInt16 nTabPos ) +{ + m_xTabBox->clear(); + + long nOffset = 0; + const SfxPoolItem* pItem = nullptr; + if (GetItemSet().GetItemState(SID_ATTR_TABSTOP_OFFSET, true, &pItem) == SfxItemState::SET) + { + nOffset = static_cast(pItem)->GetValue(); + MapUnit eUnit = GetItemSet().GetPool()->GetMetric(GetWhich(SID_ATTR_TABSTOP)); + nOffset = OutputDevice::LogicToLogic(nOffset, eUnit, MapUnit::Map100thMM); + } + + // Correct current TabPos and default tabs + for ( sal_uInt16 i = 0; i < aNewTabs->Count(); i++ ) + { + if ( (*aNewTabs)[i].GetAdjustment() != SvxTabAdjust::Default ) + { + m_xTabSpin->set_value(m_xTabSpin->normalize((*aNewTabs)[i].GetTabPos() + nOffset ), eDefUnit); + m_xTabBox->append_text(m_xTabSpin->get_text()); + } + else + { + aNewTabs->Remove( i-- ); + } + } + + // Select current tabulator + const sal_uInt16 nSize = aNewTabs->Count(); + + if ( nTabPos >= nSize ) + nTabPos = 0; + + // Switch off all RadioButtons for a start + m_xLeftTab->set_active(true); + m_xNoFillChar->set_active(true); + + if (m_xTabBox->get_count() > 0) + { + m_xTabBox->set_active(nTabPos); + aCurrentTab = (*aNewTabs)[nTabPos]; + + SetFillAndTabType_Impl(); + m_xNewBtn->set_sensitive(false); + m_xDelBtn->set_sensitive(true); + } + else + { // If no entry, 0 is the default value + m_xTabSpin->set_value(0, eDefUnit); + m_xTabBox->set_entry_text(m_xTabSpin->get_text()); + + m_xNewBtn->set_sensitive(true); + m_xDelBtn->set_sensitive(false); + } +} + +void SvxTabulatorTabPage::SetFillAndTabType_Impl() +{ + weld::RadioButton* pTypeBtn = nullptr; + weld::RadioButton* pFillBtn = nullptr; + + m_xDezChar->set_sensitive(false); + m_xDezCharLabel->set_sensitive(false); + + if ( aCurrentTab.GetAdjustment() == SvxTabAdjust::Left ) + pTypeBtn = m_xLeftTab.get(); + else if ( aCurrentTab.GetAdjustment() == SvxTabAdjust::Right ) + pTypeBtn = m_xRightTab.get(); + else if ( aCurrentTab.GetAdjustment() == SvxTabAdjust::Decimal ) + { + pTypeBtn = m_xDezTab.get(); + m_xDezChar->set_sensitive(true); + m_xDezCharLabel->set_sensitive(true); + m_xDezChar->set_text(OUString(aCurrentTab.GetDecimal())); + } + else if ( aCurrentTab.GetAdjustment() == SvxTabAdjust::Center ) + pTypeBtn = m_xCenterTab.get(); + + if (pTypeBtn) + pTypeBtn->set_active(true); + + m_xFillChar->set_sensitive(false); + m_xFillChar->set_text(""); + + if ( aCurrentTab.GetFill() == ' ' ) + pFillBtn = m_xNoFillChar.get(); + else if ( aCurrentTab.GetFill() == '-' ) + pFillBtn = m_xFillDashLine.get(); + else if ( aCurrentTab.GetFill() == '_' ) + pFillBtn = m_xFillSolidLine.get(); + else if ( aCurrentTab.GetFill() == '.' ) + pFillBtn = m_xFillPoints.get(); + else + { + pFillBtn = m_xFillSpecial.get(); + m_xFillChar->set_sensitive(true); + m_xFillChar->set_text(OUString(aCurrentTab.GetFill())); + } + pFillBtn->set_active(true); +} + +IMPL_LINK(SvxTabulatorTabPage, NewHdl_Impl, weld::Button&, rBtn, void) +{ + NewHdl_Impl(&rBtn); +} + +void SvxTabulatorTabPage::NewHdl_Impl(const weld::Button* pBtn) +{ + // Add a new one and select it + // Get the value from the display + ReformatHdl_Impl(*m_xTabBox); + m_xTabSpin->set_text(m_xTabBox->get_active_text()); + auto nVal = m_xTabSpin->denormalize(m_xTabSpin->get_value(eDefUnit)); + + // If the pBtn == 0 && the value == 0 then do not create a tab, because we create via OK + if (nVal == 0 && pBtn == nullptr) + return; + + long nOffset = 0; + const SfxPoolItem* pItem = nullptr; + + if ( GetItemSet().GetItemState( SID_ATTR_TABSTOP_OFFSET, true, &pItem ) == + SfxItemState::SET ) + { + nOffset = static_cast(pItem)->GetValue(); + MapUnit eUnit = GetItemSet().GetPool()->GetMetric( GetWhich( SID_ATTR_TABSTOP ) ); + nOffset = OutputDevice::LogicToLogic( nOffset, eUnit, MapUnit::Map100thMM ); + } + const long nReal = nVal - nOffset; + sal_Int32 nSize = m_xTabBox->get_count(); + + sal_Int32 i; + for( i = 0; i < nSize; i++ ) + { + if ( nReal < (*aNewTabs)[i].GetTabPos() ) + break; + } + + // Make ListBox entry + m_xTabSpin->set_value(m_xTabSpin->normalize(nVal), eDefUnit); + m_xTabBox->insert_text(i, m_xTabSpin->get_text()); + + aCurrentTab.GetTabPos() = nReal; + SvxTabAdjust eAdj = SvxTabAdjust::Left; + + if (m_xRightTab->get_active()) + eAdj = SvxTabAdjust::Right; + else if (m_xCenterTab->get_active()) + eAdj = SvxTabAdjust::Center; + else if (m_xDezTab->get_active()) + eAdj = SvxTabAdjust::Decimal; + + aCurrentTab.GetAdjustment() = eAdj; + aNewTabs->Insert( aCurrentTab ); + + m_xNewBtn->set_sensitive(false); + m_xDelBtn->set_sensitive(true); + m_xTabBox->grab_focus(); + + // Set the selection into the position Edit + m_xTabBox->select_entry_region(0, -1); +} + +int SvxTabulatorTabPage::FindCurrentTab() +{ + return m_xTabBox->find_text(FormatTab()); +} + +IMPL_LINK_NOARG(SvxTabulatorTabPage, DelHdl_Impl, weld::Button&, void) +{ + int nPos = FindCurrentTab(); + if (nPos == -1) + return; + + if (m_xTabBox->get_count() == 1) + { + DelAllHdl_Impl(*m_xDelAllBtn); + return; + } + + // Delete Tab + m_xTabBox->remove(nPos); + aNewTabs->Remove( nPos ); + + // Reset aCurrentTab + const sal_uInt16 nSize = aNewTabs->Count(); + + if ( nSize > 0 ) + { + // Correct Pos + nPos = ( ( nSize - 1 ) >= nPos) ? nPos : nPos - 1; + m_xTabBox->set_active(nPos); + aCurrentTab = (*aNewTabs)[nPos]; + } + + // If no Tabs Enable Disable Controls + if (m_xTabBox->get_count() == 0) + { + m_xDelBtn->set_sensitive(false); + m_xNewBtn->set_sensitive(true); + m_xTabBox->grab_focus(); + } +} + +IMPL_LINK_NOARG(SvxTabulatorTabPage, DelAllHdl_Impl, weld::Button&, void) +{ + if ( aNewTabs->Count() ) + { + aNewTabs = std::make_unique(GetWhich(SID_ATTR_TABSTOP)); + InitTabPos_Impl(); + } +} + +IMPL_LINK(SvxTabulatorTabPage, TabTypeCheckHdl_Impl, weld::ToggleButton&, rBox, void) +{ + if (!rBox.get_active()) + return; + + SvxTabAdjust eAdj; + m_xDezChar->set_sensitive(false); + m_xDezCharLabel->set_sensitive(false); + m_xDezChar->set_text(""); + + if (&rBox == m_xLeftTab.get()) + eAdj = SvxTabAdjust::Left; + else if (&rBox == m_xRightTab.get()) + eAdj = SvxTabAdjust::Right; + else if (&rBox == m_xCenterTab.get()) + eAdj = SvxTabAdjust::Center; + else + { + eAdj = SvxTabAdjust::Decimal; + m_xDezChar->set_sensitive(true); + m_xDezCharLabel->set_sensitive(true); + m_xDezChar->set_text(OUString(aCurrentTab.GetDecimal())); + } + + aCurrentTab.GetAdjustment() = eAdj; + int nPos = FindCurrentTab(); + if (nPos != -1) + { + aNewTabs->Remove( nPos ); + aNewTabs->Insert( aCurrentTab ); + } +} + +IMPL_LINK(SvxTabulatorTabPage, FillTypeCheckHdl_Impl, weld::ToggleButton&, rBox, void) +{ + if (!rBox.get_active()) + return; + + sal_uInt8 cFill = ' '; + m_xFillChar->set_text( "" ); + m_xFillChar->set_sensitive(false); + + if (&rBox == m_xFillSpecial.get()) + m_xFillChar->set_sensitive(true); + else if (&rBox == m_xNoFillChar.get()) + cFill = ' '; + else if (&rBox == m_xFillSolidLine.get()) + cFill = '_'; + else if (&rBox == m_xFillPoints.get()) + cFill = '.'; + else if (&rBox == m_xFillDashLine.get()) + cFill = '-'; + + aCurrentTab.GetFill() = cFill; + int nPos = FindCurrentTab(); + if (nPos != -1) + { + aNewTabs->Remove( nPos ); + aNewTabs->Insert( aCurrentTab ); + } +} + +IMPL_LINK_NOARG(SvxTabulatorTabPage, GetFillCharHdl_Impl, weld::Widget&, void) +{ + OUString aChar(m_xFillChar->get_text()); + if ( !aChar.isEmpty() ) + aCurrentTab.GetFill() = aChar[0]; + + const int nPos = FindCurrentTab(); + if (nPos != -1) + { + aNewTabs->Remove( nPos ); + aNewTabs->Insert( aCurrentTab ); + } +} + +IMPL_LINK_NOARG(SvxTabulatorTabPage, GetDezCharHdl_Impl, weld::Widget&, void) +{ + OUString aChar(m_xDezChar->get_text()); + if ( !aChar.isEmpty() && ( aChar[0] >= ' ')) + aCurrentTab.GetDecimal() = aChar[0]; + + const int nPos = FindCurrentTab(); + if (nPos != -1) + { + aNewTabs->Remove( nPos ); + aNewTabs->Insert( aCurrentTab ); + } +} + +IMPL_LINK_NOARG(SvxTabulatorTabPage, SelectHdl_Impl, weld::TreeView&, bool) +{ + const int nPos = FindCurrentTab(); + if (nPos != -1) + { + aCurrentTab = (*aNewTabs)[nPos]; + m_xNewBtn->set_sensitive(false); + SetFillAndTabType_Impl(); + } + return true; +} + +OUString SvxTabulatorTabPage::FormatTab() +{ + m_xTabSpin->set_text(m_xTabBox->get_active_text()); + m_xTabSpin->reformat(); + return m_xTabSpin->get_text(); +} + +IMPL_LINK_NOARG(SvxTabulatorTabPage, ReformatHdl_Impl, weld::Widget&, void) +{ + m_xTabBox->set_entry_text(FormatTab()); +} + +IMPL_LINK_NOARG(SvxTabulatorTabPage, ModifyHdl_Impl, weld::ComboBox&, void) +{ + const int nPos = FindCurrentTab(); + if (nPos != -1) + { + aCurrentTab = (*aNewTabs)[nPos]; + SetFillAndTabType_Impl(); + + m_xTabSpin->set_text(m_xTabBox->get_active_text()); + aCurrentTab.GetTabPos() = m_xTabSpin->denormalize(m_xTabSpin->get_value(eDefUnit)); + m_xNewBtn->set_sensitive(false); + m_xDelBtn->set_sensitive(true); + return; + } + m_xNewBtn->set_sensitive(true); + m_xDelBtn->set_sensitive(false); +} + +void SvxTabulatorTabPage::PageCreated(const SfxAllItemSet& aSet) +{ + const SfxUInt16Item* pControlItem = aSet.GetItem(SID_SVXTABULATORTABPAGE_DISABLEFLAGS, false); + if (pControlItem) + DisableControls(static_cast(pControlItem->GetValue())); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/textanim.cxx b/cui/source/tabpages/textanim.cxx new file mode 100644 index 000000000..ab5dc095b --- /dev/null +++ b/cui/source/tabpages/textanim.cxx @@ -0,0 +1,536 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +const sal_uInt16 SvxTextAnimationPage::pRanges[] = +{ + SDRATTR_TEXT_ANIKIND, + SDRATTR_TEXT_ANIAMOUNT, + 0 +}; + +/************************************************************************* +|* +|* constructor of the tab dialog: adds pages to the dialog +|* +\************************************************************************/ + +SvxTextTabDialog::SvxTextTabDialog(weld::Window* pParent, const SfxItemSet* pAttr, const SdrView* pSdrView) + : SfxTabDialogController(pParent, "cui/ui/textdialog.ui", "TextDialog", pAttr) + , pView(pSdrView) +{ + AddTabPage("RID_SVXPAGE_TEXTATTR", SvxTextAttrPage::Create, nullptr); + AddTabPage("RID_SVXPAGE_TEXTANIMATION", SvxTextAnimationPage::Create, nullptr); +} + +/************************************************************************* +|* +|* PageCreated() +|* +\************************************************************************/ + +void SvxTextTabDialog::PageCreated(const OString& rId, SfxTabPage &rPage) +{ + if (rId != "RID_SVXPAGE_TEXTATTR") + return; + + SdrObjKind eKind = OBJ_NONE; + if (pView) + { + const SdrMarkList& rMarkList = pView->GetMarkedObjectList(); + bool bHasMarked = rMarkList.GetMarkCount() > 0; + if (bHasMarked) + { + if (rMarkList.GetMarkCount() == 1) + { + const SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); + eKind = static_cast(pObj->GetObjIdentifier()); + } + } + } + static_cast(rPage).SetObjKind(eKind); + static_cast(rPage).Construct(); +} + +/************************************************************************* +|* +|* Page +|* +\************************************************************************/ +SvxTextAnimationPage::SvxTextAnimationPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "cui/ui/textanimtabpage.ui", "TextAnimation", &rInAttrs) + , eAniKind(SdrTextAniKind::NONE) + , m_aUpState(TRISTATE_INDET) + , m_aLeftState(TRISTATE_INDET) + , m_aRightState(TRISTATE_INDET) + , m_aDownState(TRISTATE_INDET) + , m_xLbEffect(m_xBuilder->weld_combo_box("LB_EFFECT")) + , m_xBoxDirection(m_xBuilder->weld_widget("boxDIRECTION")) + , m_xBtnUp(m_xBuilder->weld_toggle_button("BTN_UP")) + , m_xBtnLeft(m_xBuilder->weld_toggle_button("BTN_LEFT")) + , m_xBtnRight(m_xBuilder->weld_toggle_button("BTN_RIGHT")) + , m_xBtnDown(m_xBuilder->weld_toggle_button("BTN_DOWN")) + , m_xFlProperties(m_xBuilder->weld_frame("FL_PROPERTIES")) + , m_xTsbStartInside(m_xBuilder->weld_check_button("TSB_START_INSIDE")) + , m_xTsbStopInside(m_xBuilder->weld_check_button("TSB_STOP_INSIDE")) + , m_xBoxCount(m_xBuilder->weld_widget("boxCOUNT")) + , m_xTsbEndless(m_xBuilder->weld_check_button("TSB_ENDLESS")) + , m_xNumFldCount(m_xBuilder->weld_spin_button("NUM_FLD_COUNT")) + , m_xTsbPixel(m_xBuilder->weld_check_button("TSB_PIXEL")) + , m_xMtrFldAmount(m_xBuilder->weld_metric_spin_button("MTR_FLD_AMOUNT", FieldUnit::PIXEL)) + , m_xTsbAuto(m_xBuilder->weld_check_button("TSB_AUTO")) + , m_xMtrFldDelay(m_xBuilder->weld_metric_spin_button("MTR_FLD_DELAY", FieldUnit::MILLISECOND)) +{ + eFUnit = GetModuleFieldUnit( rInAttrs ); + SfxItemPool* pPool = rInAttrs.GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + eUnit = pPool->GetMetric( SDRATTR_TEXT_LEFTDIST ); + + m_xLbEffect->connect_changed( LINK( this, SvxTextAnimationPage, SelectEffectHdl_Impl ) ); + m_xTsbEndless->connect_clicked( LINK( this, SvxTextAnimationPage, ClickEndlessHdl_Impl ) ); + m_xTsbAuto->connect_clicked( LINK( this, SvxTextAnimationPage, ClickAutoHdl_Impl ) ); + m_xTsbPixel->connect_clicked( LINK( this, SvxTextAnimationPage, ClickPixelHdl_Impl ) ); + + Link aLink( LINK( this, SvxTextAnimationPage, ClickDirectionHdl_Impl ) ); + m_xBtnUp->connect_clicked( aLink ); + m_xBtnLeft->connect_clicked( aLink ); + m_xBtnRight->connect_clicked( aLink ); + m_xBtnDown->connect_clicked( aLink ); +} + +SvxTextAnimationPage::~SvxTextAnimationPage() +{ +} + +/************************************************************************* +|* +|* reads the passed item set +|* +\************************************************************************/ + +void SvxTextAnimationPage::Reset( const SfxItemSet* rAttrs ) +{ + const SfxItemPool* pPool = rAttrs->GetPool(); + + // animation type + const SfxPoolItem* pItem = GetItem( *rAttrs, SDRATTR_TEXT_ANIKIND ); + + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_TEXT_ANIKIND ); + + eAniKind = static_cast(pItem)->GetValue(); + m_xLbEffect->set_active(sal::static_int_cast(eAniKind)); + m_xLbEffect->save_value(); + + // animation direction + pItem = GetItem( *rAttrs, SDRATTR_TEXT_ANIDIRECTION ); + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_TEXT_ANIDIRECTION ); + + SelectDirection(static_cast(pItem)->GetValue()); + m_aUpState = m_xBtnUp->get_state(); + m_aLeftState = m_xBtnLeft->get_state(); + m_aRightState = m_xBtnRight->get_state(); + m_aDownState = m_xBtnDown->get_state(); + + // Start inside + pItem = GetItem( *rAttrs, SDRATTR_TEXT_ANISTARTINSIDE ); + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_TEXT_ANISTARTINSIDE ); + + if (static_cast(pItem)->GetValue()) + m_xTsbStartInside->set_state(TRISTATE_TRUE); + else + m_xTsbStartInside->set_state(TRISTATE_FALSE); + m_xTsbStartInside->save_state(); + + // Stop inside + pItem = GetItem( *rAttrs, SDRATTR_TEXT_ANISTOPINSIDE ); + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_TEXT_ANISTOPINSIDE ); + + if (static_cast(pItem)->GetValue()) + m_xTsbStopInside->set_state(TRISTATE_TRUE); + else + m_xTsbStopInside->set_state(TRISTATE_FALSE); + m_xTsbStopInside->save_state(); + + // quantity + pItem = GetItem( *rAttrs, SDRATTR_TEXT_ANICOUNT ); + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_TEXT_ANICOUNT ); + + long nValue = static_cast(static_cast(pItem)->GetValue()); + m_xNumFldCount->set_value(nValue); + if (nValue == 0) + { + if (eAniKind == SdrTextAniKind::Slide) + { + m_xTsbEndless->set_state(TRISTATE_FALSE); + m_xTsbEndless->set_sensitive(false); + } + else + { + m_xTsbEndless->set_state(TRISTATE_TRUE); + m_xNumFldCount->set_text(""); + } + } + else + m_xTsbEndless->set_state(TRISTATE_FALSE); + m_xTsbEndless->save_state(); + m_xNumFldCount->save_value(); + + // delay + pItem = GetItem( *rAttrs, SDRATTR_TEXT_ANIDELAY ); + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_TEXT_ANIDELAY ); + + nValue = static_cast(static_cast(pItem)->GetValue()); + m_xMtrFldDelay->set_value(nValue, FieldUnit::NONE); + if (nValue == 0) + { + m_xTsbAuto->set_state(TRISTATE_TRUE); + m_xMtrFldDelay->set_text(""); + } + else + m_xTsbAuto->set_state(TRISTATE_FALSE); + m_xTsbAuto->save_state(); + m_xMtrFldDelay->save_value(); + + // step size + pItem = GetItem( *rAttrs, SDRATTR_TEXT_ANIAMOUNT ); + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_TEXT_ANIAMOUNT ); + + nValue = static_cast(static_cast(pItem)->GetValue()); + if (nValue <= 0) + { + m_xTsbPixel->set_state(TRISTATE_TRUE); + nValue = -nValue; + if (nValue == 0) + nValue++; + m_xMtrFldAmount->set_unit(FieldUnit::CUSTOM); + m_xMtrFldAmount->set_digits(0); + + m_xMtrFldAmount->set_increments(1, 10, FieldUnit::NONE); + m_xMtrFldAmount->set_range(1, 100, FieldUnit::NONE); + m_xMtrFldAmount->set_value(nValue, FieldUnit::NONE); + } + else + { + m_xTsbPixel->set_state(TRISTATE_FALSE); + m_xMtrFldAmount->set_unit(eFUnit); + m_xMtrFldAmount->set_digits(2); + + m_xMtrFldAmount->set_increments(10, 100, FieldUnit::NONE); + m_xMtrFldAmount->set_range(1, 10000, FieldUnit::NONE); + + SetMetricValue(*m_xMtrFldAmount, nValue, eUnit); + } + m_xTsbPixel->save_state(); + m_xMtrFldAmount->save_value(); + + SelectEffectHdl_Impl(*m_xLbEffect); + ClickEndlessHdl_Impl(*m_xTsbEndless); + ClickAutoHdl_Impl(*m_xTsbAuto); +} + +/************************************************************************* +|* +|* fills the passed item set with dialog box attributes +|* +\************************************************************************/ + +bool SvxTextAnimationPage::FillItemSet( SfxItemSet* rAttrs) +{ + bool bModified = false; + TriState eState; + + // animation type + int nPos = m_xLbEffect->get_active(); + if( nPos != -1 && + m_xLbEffect->get_value_changed_from_saved() ) + { + rAttrs->Put( SdrTextAniKindItem( static_cast(nPos) ) ); + bModified = true; + } + + // animation direction + if (m_aUpState != m_xBtnUp->get_state() || + m_aLeftState != m_xBtnLeft->get_state() || + m_aRightState != m_xBtnRight->get_state() || + m_aDownState != m_xBtnDown->get_state()) + { + SdrTextAniDirection eValue = static_cast(GetSelectedDirection()); + rAttrs->Put( SdrTextAniDirectionItem( eValue ) ); + bModified = true; + } + + // Start inside + eState = m_xTsbStartInside->get_state(); + if (m_xTsbStartInside->get_state_changed_from_saved()) + { + rAttrs->Put( SdrTextAniStartInsideItem( TRISTATE_TRUE == eState ) ); + bModified = true; + } + + // Stop inside + eState = m_xTsbStopInside->get_state(); + if (m_xTsbStopInside->get_state_changed_from_saved()) + { + rAttrs->Put( SdrTextAniStopInsideItem( TRISTATE_TRUE == eState ) ); + bModified = true; + } + + // quantity + eState = m_xTsbEndless->get_state(); + if (m_xTsbEndless->get_state_changed_from_saved() || + m_xNumFldCount->get_value_changed_from_saved()) + { + sal_Int64 nValue = 0; + if( eState == TRISTATE_TRUE /*#89844#*/ && m_xTsbEndless->get_sensitive()) + bModified = true; + else + { + if( m_xNumFldCount->get_value_changed_from_saved() ) + { + nValue = m_xNumFldCount->get_value(); + bModified = true; + } + } + if( bModified ) + rAttrs->Put( SdrTextAniCountItem( static_cast(nValue) ) ); + } + + // delay + eState = m_xTsbAuto->get_state(); + if (m_xTsbAuto->get_state_changed_from_saved() || + m_xMtrFldDelay->get_value_changed_from_saved()) + { + sal_Int64 nValue = 0; + if( eState == TRISTATE_TRUE ) + bModified = true; + else + { + if( m_xMtrFldDelay->get_value_changed_from_saved() ) + { + nValue = m_xMtrFldDelay->get_value(FieldUnit::NONE); + bModified = true; + } + } + if( bModified ) + rAttrs->Put( SdrTextAniDelayItem( static_cast(nValue) ) ); + } + + // step size + eState = m_xTsbPixel->get_state(); + if (m_xTsbPixel->get_state_changed_from_saved() || + m_xMtrFldAmount->get_value_changed_from_saved()) + { + sal_Int64 nValue = 0; + if( eState == TRISTATE_TRUE ) + { + nValue = m_xMtrFldAmount->get_value(FieldUnit::NONE); + nValue = -nValue; + } + else + { + nValue = GetCoreValue( *m_xMtrFldAmount, eUnit ); + } + rAttrs->Put( SdrTextAniAmountItem( static_cast(nValue) ) ); + + bModified = true; + } + + return bModified; +} + +/************************************************************************* +|* +|* creates the page +|* +\************************************************************************/ + +std::unique_ptr SvxTextAnimationPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrs) +{ + return std::make_unique(pPage, pController, *rAttrs); +} + +IMPL_LINK_NOARG(SvxTextAnimationPage, SelectEffectHdl_Impl, weld::ComboBox&, void) +{ + int nPos = m_xLbEffect->get_active(); + if (nPos == -1) + return; + + eAniKind = static_cast(nPos); + switch( eAniKind ) + { + case SdrTextAniKind::NONE: + { + m_xBoxDirection->set_sensitive(false); + m_xFlProperties->set_sensitive(false); + } + break; + + case SdrTextAniKind::Blink: + case SdrTextAniKind::Scroll: + case SdrTextAniKind::Alternate: + case SdrTextAniKind::Slide: + { + m_xFlProperties->set_sensitive(true); + if( eAniKind == SdrTextAniKind::Slide ) + { + m_xTsbStartInside->set_sensitive(false); + m_xTsbStopInside->set_sensitive(false); + m_xTsbEndless->set_sensitive(false); + m_xNumFldCount->set_sensitive(true); + m_xNumFldCount->set_value(m_xNumFldCount->get_value()); + } + else + { + m_xTsbStartInside->set_sensitive(true); + m_xTsbStopInside->set_sensitive(true); + m_xTsbEndless->set_sensitive(true); + ClickEndlessHdl_Impl(*m_xTsbEndless); + } + + m_xTsbAuto->set_sensitive(true); + ClickAutoHdl_Impl(*m_xTsbAuto); + + if( eAniKind == SdrTextAniKind::Blink ) + { + m_xBoxDirection->set_sensitive(false); + m_xBoxCount->set_sensitive(false); + } + else + { + m_xBoxDirection->set_sensitive(true); + m_xBoxCount->set_sensitive(true); + } + } + break; + } +} + +IMPL_LINK_NOARG(SvxTextAnimationPage, ClickEndlessHdl_Impl, weld::Button&, void) +{ + if( eAniKind == SdrTextAniKind::Slide ) + return; + + TriState eState = m_xTsbEndless->get_state(); + if( eState != TRISTATE_FALSE ) + { + m_xNumFldCount->set_sensitive(false); + m_xNumFldCount->set_text(""); + } + else + { + m_xNumFldCount->set_sensitive(true); + m_xNumFldCount->set_value(m_xNumFldCount->get_value()); + } +} + +IMPL_LINK_NOARG(SvxTextAnimationPage, ClickAutoHdl_Impl, weld::Button&, void) +{ + TriState eState = m_xTsbAuto->get_state(); + if( eState != TRISTATE_FALSE ) + { + m_xMtrFldDelay->set_sensitive(false); + m_xMtrFldDelay->set_text(""); + } + else + { + m_xMtrFldDelay->set_sensitive(true); + m_xMtrFldDelay->set_value(m_xMtrFldDelay->get_value(FieldUnit::NONE), FieldUnit::NONE); //to-do + } +} + +IMPL_LINK_NOARG(SvxTextAnimationPage, ClickPixelHdl_Impl, weld::Button&, void) +{ + TriState eState = m_xTsbPixel->get_state(); + if (eState == TRISTATE_TRUE) + { + int nValue = m_xMtrFldAmount->get_value(FieldUnit::NONE) / 10; + m_xMtrFldAmount->set_sensitive(true); + m_xMtrFldAmount->set_unit(FieldUnit::CUSTOM); + m_xMtrFldAmount->set_digits(0); + + m_xMtrFldAmount->set_increments(1, 10, FieldUnit::NONE); + m_xMtrFldAmount->set_range(1, 100, FieldUnit::NONE); + + m_xMtrFldAmount->set_value(nValue, FieldUnit::NONE); + } + else if( eState == TRISTATE_FALSE ) + { + int nValue = m_xMtrFldAmount->get_value(FieldUnit::NONE) * 10; + m_xMtrFldAmount->set_sensitive(true); + m_xMtrFldAmount->set_unit(eFUnit); + m_xMtrFldAmount->set_digits(2); + + m_xMtrFldAmount->set_increments(10, 100, FieldUnit::NONE); + m_xMtrFldAmount->set_range(1, 10000, FieldUnit::NONE); + + m_xMtrFldAmount->set_value(nValue, FieldUnit::NONE); + } +} + +IMPL_LINK(SvxTextAnimationPage, ClickDirectionHdl_Impl, weld::Button&, rBtn, void) +{ + m_xBtnUp->set_active(&rBtn == m_xBtnUp.get()); + m_xBtnLeft->set_active(&rBtn == m_xBtnLeft.get()); + m_xBtnRight->set_active(&rBtn == m_xBtnRight.get()); + m_xBtnDown->set_active(&rBtn == m_xBtnDown.get()); +} + +void SvxTextAnimationPage::SelectDirection( SdrTextAniDirection nValue ) +{ + m_xBtnUp->set_active( nValue == SdrTextAniDirection::Up ); + m_xBtnLeft->set_active( nValue == SdrTextAniDirection::Left ); + m_xBtnRight->set_active( nValue == SdrTextAniDirection::Right ); + m_xBtnDown->set_active( nValue == SdrTextAniDirection::Down ); +} + +sal_uInt16 SvxTextAnimationPage::GetSelectedDirection() const +{ + SdrTextAniDirection nValue = SdrTextAniDirection::Left; + + if( m_xBtnUp->get_active() ) + nValue = SdrTextAniDirection::Up; + else if( m_xBtnLeft->get_active() ) + nValue = SdrTextAniDirection::Left; + else if( m_xBtnRight->get_active() ) + nValue = SdrTextAniDirection::Right; + else if( m_xBtnDown->get_active() ) + nValue = SdrTextAniDirection::Down; + + return static_cast(nValue); +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/textattr.cxx b/cui/source/tabpages/textattr.cxx new file mode 100644 index 000000000..c9eaf461c --- /dev/null +++ b/cui/source/tabpages/textattr.cxx @@ -0,0 +1,668 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +using namespace ::com::sun::star; + +const sal_uInt16 SvxTextAttrPage::pRanges[] = +{ + SDRATTR_MISC_FIRST + , SDRATTR_TEXT_HORZADJUST + , SDRATTR_TEXT_WORDWRAP + , SDRATTR_TEXT_WORDWRAP + , 0 +}; + +/************************************************************************* +|* +|* dialog (page) for copying objects +|* +\************************************************************************/ +SvxTextAttrPage::SvxTextAttrPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SvxTabPage(pPage, pController, "cui/ui/textattrtabpage.ui", "TextAttributesPage", rInAttrs) + , rOutAttrs(rInAttrs) + , m_eObjKind(OBJ_NONE) + , bAutoGrowSizeEnabled(false) + , bContourEnabled(false) + , bAutoGrowWidthEnabled(false) + , bAutoGrowHeightEnabled(false) + , bWordWrapTextEnabled(false) + , bFitToSizeEnabled(false) + , m_aCtlPosition(this) + , m_xDrawingText(m_xBuilder->weld_widget("drawingtext")) + , m_xCustomShapeText(m_xBuilder->weld_widget("customshapetext")) + , m_xTsbAutoGrowWidth(m_xBuilder->weld_check_button("TSB_AUTOGROW_WIDTH")) + , m_xTsbAutoGrowHeight(m_xBuilder->weld_check_button("TSB_AUTOGROW_HEIGHT")) + , m_xTsbFitToSize(m_xBuilder->weld_check_button("TSB_FIT_TO_SIZE")) + , m_xTsbContour(m_xBuilder->weld_check_button("TSB_CONTOUR")) + , m_xTsbWordWrapText(m_xBuilder->weld_check_button("TSB_WORDWRAP_TEXT")) + , m_xTsbAutoGrowSize(m_xBuilder->weld_check_button("TSB_AUTOGROW_SIZE")) + , m_xFlDistance(m_xBuilder->weld_frame("FL_DISTANCE")) + , m_xMtrFldLeft(m_xBuilder->weld_metric_spin_button("MTR_FLD_LEFT", FieldUnit::CM)) + , m_xMtrFldRight(m_xBuilder->weld_metric_spin_button("MTR_FLD_RIGHT", FieldUnit::CM)) + , m_xMtrFldTop(m_xBuilder->weld_metric_spin_button("MTR_FLD_TOP", FieldUnit::CM)) + , m_xMtrFldBottom(m_xBuilder->weld_metric_spin_button("MTR_FLD_BOTTOM", FieldUnit::CM)) + , m_xFlPosition(m_xBuilder->weld_frame("FL_POSITION")) + , m_xCtlPosition(new weld::CustomWeld(*m_xBuilder, "CTL_POSITION", m_aCtlPosition)) + , m_xTsbFullWidth(m_xBuilder->weld_check_button("TSB_FULL_WIDTH")) +{ + m_aCtlPosition.SetControlSettings(RectPoint::MM, 240); + + FieldUnit eFUnit = GetModuleFieldUnit( rInAttrs ); + SetFieldUnit( *m_xMtrFldLeft, eFUnit ); + SetFieldUnit( *m_xMtrFldRight, eFUnit ); + SetFieldUnit( *m_xMtrFldTop, eFUnit ); + SetFieldUnit( *m_xMtrFldBottom, eFUnit ); + + Link aLink( LINK( this, SvxTextAttrPage, ClickHdl_Impl ) ); + m_xTsbAutoGrowWidth->connect_clicked( aLink ); + m_xTsbAutoGrowHeight->connect_clicked( aLink ); + m_xTsbAutoGrowSize->connect_clicked( aLink ); + m_xTsbFitToSize->connect_clicked( aLink ); + m_xTsbContour->connect_clicked( aLink ); + + m_xTsbFullWidth->connect_clicked(LINK( this, SvxTextAttrPage, ClickFullWidthHdl_Impl ) ); +} + +SvxTextAttrPage::~SvxTextAttrPage() +{ +} + +/************************************************************************* +|* +|* reads the passed item set +|* +\************************************************************************/ + +void SvxTextAttrPage::Reset( const SfxItemSet* rAttrs ) +{ + SfxItemPool* pPool = rAttrs->GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + MapUnit eUnit = pPool->GetMetric( SDRATTR_TEXT_LEFTDIST ); + + const SfxPoolItem* pItem = GetItem( *rAttrs, SDRATTR_TEXT_LEFTDIST ); + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_TEXT_LEFTDIST ); + + SetMetricValue(*m_xMtrFldLeft, static_cast(pItem)->GetValue(), eUnit); + m_xMtrFldLeft->save_value(); + + pItem = GetItem( *rAttrs, SDRATTR_TEXT_RIGHTDIST ); + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_TEXT_RIGHTDIST ); + + SetMetricValue(*m_xMtrFldRight, static_cast(pItem)->GetValue(), eUnit); + m_xMtrFldRight->save_value(); + + pItem = GetItem( *rAttrs, SDRATTR_TEXT_UPPERDIST ); + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_TEXT_UPPERDIST ); + + SetMetricValue(*m_xMtrFldTop, static_cast(pItem)->GetValue(), eUnit); + m_xMtrFldTop->save_value(); + + pItem = GetItem( *rAttrs, SDRATTR_TEXT_LOWERDIST ); + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_TEXT_LOWERDIST ); + + SetMetricValue(*m_xMtrFldBottom, static_cast(pItem)->GetValue(), eUnit); + m_xMtrFldBottom->save_value(); + + // adjust to height and autogrowsize + if ( rAttrs->GetItemState( SDRATTR_TEXT_AUTOGROWHEIGHT ) != SfxItemState::DONTCARE ) + { + m_xTsbAutoGrowHeight->set_state( rAttrs->Get( SDRATTR_TEXT_AUTOGROWHEIGHT ). + GetValue() ? TRISTATE_TRUE : TRISTATE_FALSE ); + + m_xTsbAutoGrowSize->set_state( rAttrs->Get( SDRATTR_TEXT_AUTOGROWHEIGHT ). + GetValue() ? TRISTATE_TRUE : TRISTATE_FALSE ); + } + else + { + m_xTsbAutoGrowHeight->set_state( TRISTATE_INDET ); + m_xTsbAutoGrowSize->set_state( TRISTATE_INDET ); + } + m_xTsbAutoGrowHeight->save_state(); + m_xTsbAutoGrowSize->save_state(); + + // adjust to width + if ( rAttrs->GetItemState( SDRATTR_TEXT_AUTOGROWWIDTH ) != SfxItemState::DONTCARE ) + { + m_xTsbAutoGrowWidth->set_state( rAttrs->Get( SDRATTR_TEXT_AUTOGROWWIDTH ). + GetValue() ? TRISTATE_TRUE : TRISTATE_FALSE ); + } + else + m_xTsbAutoGrowWidth->set_state( TRISTATE_INDET ); + m_xTsbAutoGrowWidth->save_state(); + + // wordwrap text + if ( rAttrs->GetItemState( SDRATTR_TEXT_WORDWRAP ) != SfxItemState::DONTCARE ) + { + m_xTsbWordWrapText->set_state( rAttrs->Get( SDRATTR_TEXT_WORDWRAP ). + GetValue() ? TRISTATE_TRUE : TRISTATE_FALSE ); + } + else + m_xTsbWordWrapText->set_state( TRISTATE_INDET ); + m_xTsbWordWrapText->save_state(); + + + // #103516# Do the setup based on states of hor/ver adjust + // Setup center field and FullWidth + SfxItemState eVState = rAttrs->GetItemState( SDRATTR_TEXT_VERTADJUST ); + SfxItemState eHState = rAttrs->GetItemState( SDRATTR_TEXT_HORZADJUST ); + + if(SfxItemState::DONTCARE != eVState && SfxItemState::DONTCARE != eHState) + { + // VertAdjust and HorAdjust are unequivocal, thus + SdrTextVertAdjust eTVA = rAttrs->Get(SDRATTR_TEXT_VERTADJUST).GetValue(); + SdrTextHorzAdjust eTHA = rAttrs->Get(SDRATTR_TEXT_HORZADJUST).GetValue(); + RectPoint eRP = RectPoint::LB; + + if (m_xTsbFullWidth->get_state() == TRISTATE_INDET) + m_xTsbFullWidth->set_state(TRISTATE_FALSE); + + // Translate item values into local anchor position. + switch (eTVA) + { + case SDRTEXTVERTADJUST_TOP: + { + switch (eTHA) + { + case SDRTEXTHORZADJUST_LEFT: eRP = RectPoint::LT; break; + case SDRTEXTHORZADJUST_BLOCK: + case SDRTEXTHORZADJUST_CENTER: eRP = RectPoint::MT; break; + case SDRTEXTHORZADJUST_RIGHT: eRP = RectPoint::RT; break; + } + break; + } + case SDRTEXTVERTADJUST_BLOCK: + case SDRTEXTVERTADJUST_CENTER: + { + switch (eTHA) + { + case SDRTEXTHORZADJUST_LEFT: eRP = RectPoint::LM; break; + case SDRTEXTHORZADJUST_BLOCK: + case SDRTEXTHORZADJUST_CENTER: eRP = RectPoint::MM; break; + case SDRTEXTHORZADJUST_RIGHT: eRP = RectPoint::RM; break; + } + break; + } + case SDRTEXTVERTADJUST_BOTTOM: + { + switch (eTHA) + { + case SDRTEXTHORZADJUST_LEFT: eRP = RectPoint::LB; break; + case SDRTEXTHORZADJUST_BLOCK: + case SDRTEXTHORZADJUST_CENTER: eRP = RectPoint::MB; break; + case SDRTEXTHORZADJUST_RIGHT: eRP = RectPoint::RB; break; + } + break; + } + default: + break; + } + + // See if we have to check the "full width" check button. + bool bLeftToRight(IsTextDirectionLeftToRight()); + + if((bLeftToRight && (SDRTEXTHORZADJUST_BLOCK == eTHA)) || (!bLeftToRight && (SDRTEXTVERTADJUST_BLOCK == eTVA))) + { + // Move anchor to valid position. + ClickFullWidthHdl_Impl(*m_xTsbFullWidth); + m_xTsbFullWidth->set_state(TRISTATE_TRUE); + } + + m_aCtlPosition.SetActualRP( eRP ); + } + else + { + // VertAdjust or HorAdjust is not unequivocal + m_aCtlPosition.Reset(); + + m_aCtlPosition.SetState(CTL_STATE::NOVERT); + m_aCtlPosition.DoCompletelyDisable(true); + + m_xTsbFullWidth->set_state(TRISTATE_INDET); + m_xFlPosition->set_sensitive( false ); + } + + // adjust to border + if (rAttrs->GetItemState(SDRATTR_TEXT_FITTOSIZE) != SfxItemState::DONTCARE) + { + drawing::TextFitToSizeType const eFTS = + rAttrs->Get( SDRATTR_TEXT_FITTOSIZE ).GetValue(); + if (eFTS == drawing::TextFitToSizeType_AUTOFIT || eFTS == drawing::TextFitToSizeType_NONE) + m_xTsbFitToSize->set_state( TRISTATE_FALSE ); + else + m_xTsbFitToSize->set_state( TRISTATE_TRUE ); + } + else + m_xTsbFitToSize->set_state( TRISTATE_INDET ); + m_xTsbFitToSize->save_state(); + + if( rAttrs->GetItemState( SDRATTR_TEXT_CONTOURFRAME ) != SfxItemState::DONTCARE ) + { + bool bContour = rAttrs->Get( SDRATTR_TEXT_CONTOURFRAME ).GetValue(); + m_xTsbContour->set_state( bContour ? TRISTATE_TRUE : TRISTATE_FALSE ); + } + else + m_xTsbContour->set_state( TRISTATE_INDET ); + m_xTsbContour->save_state(); + + ClickHdl_Impl(*m_xTsbContour); +} + +/************************************************************************* +|* +|* fills the passed item set with dialog box attributes +|* +\************************************************************************/ + +bool SvxTextAttrPage::FillItemSet( SfxItemSet* rAttrs) +{ + SfxItemPool* pPool = rAttrs->GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + MapUnit eUnit = pPool->GetMetric( SDRATTR_TEXT_LEFTDIST ); + + sal_Int32 nValue; + TriState eState; + + if( m_xMtrFldLeft->get_value_changed_from_saved() ) + { + nValue = GetCoreValue( *m_xMtrFldLeft, eUnit ); + rAttrs->Put( makeSdrTextLeftDistItem( nValue ) ); + } + + if( m_xMtrFldRight->get_value_changed_from_saved() ) + { + nValue = GetCoreValue( *m_xMtrFldRight, eUnit ); + rAttrs->Put( makeSdrTextRightDistItem( nValue ) ); + } + + if( m_xMtrFldTop->get_value_changed_from_saved() ) + { + nValue = GetCoreValue( *m_xMtrFldTop, eUnit ); + rAttrs->Put( makeSdrTextUpperDistItem( nValue ) ); + } + + if( m_xMtrFldBottom->get_value_changed_from_saved() ) + { + nValue = GetCoreValue( *m_xMtrFldBottom, eUnit ); + rAttrs->Put( makeSdrTextLowerDistItem( nValue ) ); + } + + eState = m_xTsbAutoGrowHeight->get_state(); + if( m_xTsbAutoGrowHeight->get_state_changed_from_saved() ) + { + rAttrs->Put( makeSdrTextAutoGrowHeightItem( TRISTATE_TRUE == eState ) ); + } + + eState = m_xTsbAutoGrowWidth->get_state(); + if( m_xTsbAutoGrowWidth->get_state_changed_from_saved() ) + { + rAttrs->Put( makeSdrTextAutoGrowWidthItem( TRISTATE_TRUE == eState ) ); + } + + eState = m_xTsbAutoGrowSize->get_state(); + if( m_xTsbAutoGrowSize->get_state_changed_from_saved() ) + { + rAttrs->Put( makeSdrTextAutoGrowHeightItem( TRISTATE_TRUE == eState ) ); + } + + eState = m_xTsbWordWrapText->get_state(); + if( m_xTsbWordWrapText->get_state_changed_from_saved() ) + { + rAttrs->Put( makeSdrTextWordWrapItem( TRISTATE_TRUE == eState ) ); + } + + eState = m_xTsbContour->get_state(); + if( m_xTsbContour->get_state_changed_from_saved() ) + { + rAttrs->Put( makeSdrTextContourFrameItem( TRISTATE_TRUE == eState ) ); + } + + eState = m_xTsbFitToSize->get_state(); + if( m_xTsbFitToSize->get_state_changed_from_saved() ) + { + drawing::TextFitToSizeType eFTS; + switch( eState ) + { + default: ; //prevent warning + OSL_FAIL( "svx::SvxTextAttrPage::FillItemSet(), unhandled state!" ); + [[fallthrough]]; + case TRISTATE_FALSE: eFTS = drawing::TextFitToSizeType_AUTOFIT; break; + case TRISTATE_TRUE: eFTS = drawing::TextFitToSizeType_PROPORTIONAL; break; + } + rAttrs->Put( SdrTextFitToSizeTypeItem( eFTS ) ); + } + + // centered + RectPoint eRP = m_aCtlPosition.GetActualRP(); + SdrTextVertAdjust eTVA, eOldTVA; + SdrTextHorzAdjust eTHA, eOldTHA; + + switch( eRP ) + { + default: + case RectPoint::LT: eTVA = SDRTEXTVERTADJUST_TOP; + eTHA = SDRTEXTHORZADJUST_LEFT; break; + case RectPoint::LM: eTVA = SDRTEXTVERTADJUST_CENTER; + eTHA = SDRTEXTHORZADJUST_LEFT; break; + case RectPoint::LB: eTVA = SDRTEXTVERTADJUST_BOTTOM; + eTHA = SDRTEXTHORZADJUST_LEFT; break; + case RectPoint::MT: eTVA = SDRTEXTVERTADJUST_TOP; + eTHA = SDRTEXTHORZADJUST_CENTER; break; + case RectPoint::MM: eTVA = SDRTEXTVERTADJUST_CENTER; + eTHA = SDRTEXTHORZADJUST_CENTER; break; + case RectPoint::MB: eTVA = SDRTEXTVERTADJUST_BOTTOM; + eTHA = SDRTEXTHORZADJUST_CENTER; break; + case RectPoint::RT: eTVA = SDRTEXTVERTADJUST_TOP; + eTHA = SDRTEXTHORZADJUST_RIGHT; break; + case RectPoint::RM: eTVA = SDRTEXTVERTADJUST_CENTER; + eTHA = SDRTEXTHORZADJUST_RIGHT; break; + case RectPoint::RB: eTVA = SDRTEXTVERTADJUST_BOTTOM; + eTHA = SDRTEXTHORZADJUST_RIGHT; break; + } + + // #103516# Do not change values if adjust controls were disabled. + bool bIsDisabled(m_aCtlPosition.IsCompletelyDisabled()); + + if(!bIsDisabled) + { + if( m_xTsbFullWidth->get_state() == TRISTATE_TRUE ) + { + if (IsTextDirectionLeftToRight()) + eTHA = SDRTEXTHORZADJUST_BLOCK; + else + eTVA = SDRTEXTVERTADJUST_BLOCK; + } + + if ( rOutAttrs.GetItemState( SDRATTR_TEXT_VERTADJUST ) != SfxItemState::DONTCARE ) + { + eOldTVA = rOutAttrs.Get( SDRATTR_TEXT_VERTADJUST ).GetValue(); + if( eOldTVA != eTVA ) + rAttrs->Put( SdrTextVertAdjustItem( eTVA ) ); + } + else + rAttrs->Put( SdrTextVertAdjustItem( eTVA ) ); + + if ( rOutAttrs.GetItemState( SDRATTR_TEXT_HORZADJUST ) != SfxItemState::DONTCARE ) + { + eOldTHA = rOutAttrs.Get( SDRATTR_TEXT_HORZADJUST ).GetValue(); + if( eOldTHA != eTHA ) + rAttrs->Put( SdrTextHorzAdjustItem( eTHA ) ); + } + else + rAttrs->Put( SdrTextHorzAdjustItem( eTHA ) ); + } + + return true; +} + +void SvxTextAttrPage::Construct() +{ + switch (m_eObjKind) + { + case OBJ_NONE: + // indeterminate, show them all + bFitToSizeEnabled = bContourEnabled = bWordWrapTextEnabled = + bAutoGrowSizeEnabled = bAutoGrowWidthEnabled = bAutoGrowHeightEnabled = true; + m_xCustomShapeText->show(); + m_xDrawingText->show(); + break; + case OBJ_TEXT: + case OBJ_TITLETEXT: + case OBJ_OUTLINETEXT: + case OBJ_CAPTION: + // contour NOT possible for pure text objects + bContourEnabled = bWordWrapTextEnabled = bAutoGrowSizeEnabled = false; + + // adjusting width and height is ONLY possible for pure text objects + bFitToSizeEnabled = bAutoGrowWidthEnabled = bAutoGrowHeightEnabled = true; + m_xCustomShapeText->hide(); + m_xDrawingText->show(); + break; + case OBJ_CUSTOMSHAPE: + bFitToSizeEnabled = bContourEnabled = bAutoGrowWidthEnabled = bAutoGrowHeightEnabled = false; + bWordWrapTextEnabled = bAutoGrowSizeEnabled = true; + m_xDrawingText->hide(); + m_xCustomShapeText->show(); + break; + default: + bFitToSizeEnabled = bContourEnabled = true; + bWordWrapTextEnabled = bAutoGrowSizeEnabled = bAutoGrowWidthEnabled = bAutoGrowHeightEnabled = false; + m_xCustomShapeText->hide(); + m_xDrawingText->show(); + break; + } + + m_xTsbAutoGrowHeight->set_visible( bAutoGrowHeightEnabled ); + m_xTsbAutoGrowWidth->set_visible( bAutoGrowWidthEnabled ); + m_xTsbFitToSize->set_visible( bFitToSizeEnabled ); + m_xTsbContour->set_visible( bContourEnabled ); + m_xTsbAutoGrowSize->set_visible( bAutoGrowSizeEnabled ); + m_xTsbWordWrapText->set_visible( bWordWrapTextEnabled ); +} + +std::unique_ptr SvxTextAttrPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrs) +{ + return std::make_unique(pPage, pController, *rAttrs); +} + +/** Check whether we have to uncheck the "Full width" check box. +*/ +void SvxTextAttrPage::PointChanged(weld::DrawingArea*, RectPoint eRP) +{ + if (m_xTsbFullWidth->get_state() != TRISTATE_TRUE) + return; + + // Depending on write direction and currently checked anchor we have + // to uncheck the "full width" button. + if (IsTextDirectionLeftToRight()) + switch( eRP ) + { + case RectPoint::LT: + case RectPoint::LM: + case RectPoint::LB: + case RectPoint::RT: + case RectPoint::RM: + case RectPoint::RB: + m_xTsbFullWidth->set_state( TRISTATE_FALSE ); + break; + default: ;//prevent warning + } + else + switch (eRP) + { + case RectPoint::LT: + case RectPoint::MT: + case RectPoint::RT: + case RectPoint::LB: + case RectPoint::MB: + case RectPoint::RB: + m_xTsbFullWidth->set_state( TRISTATE_FALSE ); + break; + default: ;//prevent warning + } +} + + +/************************************************************************* +|* +|* possibly changes the position of the position-control +|* +\************************************************************************/ + +/** When switching the "full width" check button on the text anchor may have + to be moved to a valid and adjacent position. This position depends on + the current anchor position and the text writing direction. +*/ +IMPL_LINK_NOARG(SvxTextAttrPage, ClickFullWidthHdl_Impl, weld::Button&, void) +{ + if( m_xTsbFullWidth->get_state() != TRISTATE_TRUE ) + return; + + if (IsTextDirectionLeftToRight()) + { + // Move text anchor to horizontal middle axis. + switch( m_aCtlPosition.GetActualRP() ) + { + case RectPoint::LT: + case RectPoint::RT: + m_aCtlPosition.SetActualRP( RectPoint::MT ); + break; + + case RectPoint::LM: + case RectPoint::RM: + m_aCtlPosition.SetActualRP( RectPoint::MM ); + break; + + case RectPoint::LB: + case RectPoint::RB: + m_aCtlPosition.SetActualRP( RectPoint::MB ); + break; + default: ;//prevent warning + } + } + else + { + // Move text anchor to vertical middle axis. + switch( m_aCtlPosition.GetActualRP() ) + { + case RectPoint::LT: + case RectPoint::LB: + m_aCtlPosition.SetActualRP( RectPoint::LM ); + break; + + case RectPoint::MT: + case RectPoint::MB: + m_aCtlPosition.SetActualRP( RectPoint::MM ); + break; + + case RectPoint::RT: + case RectPoint::RB: + m_aCtlPosition.SetActualRP( RectPoint::RM ); + break; + default: ;//prevent warning + } + } +} + +/************************************************************************* +|* +|* enables/disables "size at text" or "adjust to frame" +|* +\************************************************************************/ + +IMPL_LINK(SvxTextAttrPage, ClickHdl_Impl, weld::Button&, rButton, void) +{ + if (&rButton == m_xTsbAutoGrowSize.get()) + { + m_xTsbAutoGrowHeight->set_state(m_xTsbAutoGrowSize->get_state()); + if (m_xTsbAutoGrowSize->get_state() == TRISTATE_TRUE) + { + m_xTsbFitToSize->set_state(TRISTATE_FALSE); + m_xTsbContour->set_state(TRISTATE_FALSE); + } + } + else if (&rButton == m_xTsbAutoGrowHeight.get()) + m_xTsbAutoGrowSize->set_state(m_xTsbAutoGrowHeight->get_state()); + + bool bAutoGrowWidth = m_xTsbAutoGrowWidth->get_state() == TRISTATE_TRUE; + bool bAutoGrowHeight = m_xTsbAutoGrowHeight->get_state() == TRISTATE_TRUE; + bool bFitToSize = m_xTsbFitToSize->get_state() == TRISTATE_TRUE; + bool bContour = m_xTsbContour->get_state() == TRISTATE_TRUE; + + m_xTsbContour->set_sensitive( !bFitToSize && + !( ( bAutoGrowWidth && bAutoGrowWidthEnabled ) || ( bAutoGrowHeight && bAutoGrowHeightEnabled ) ) && + bContourEnabled ); + + m_xTsbAutoGrowWidth->set_sensitive( !bFitToSize && + !( bContour && bContourEnabled ) && + bAutoGrowWidthEnabled ); + + m_xTsbAutoGrowHeight->set_sensitive( !bFitToSize && + !( bContour && bContourEnabled ) && + bAutoGrowHeightEnabled ); + + m_xTsbFitToSize->set_sensitive( !( ( bAutoGrowWidth && bAutoGrowWidthEnabled ) || ( bAutoGrowHeight && bAutoGrowHeightEnabled ) ) && + !( bContour && bContourEnabled ) && + bFitToSizeEnabled ); + + // #101901# enable/disable metric fields and decorations dependent of contour + m_xFlDistance->set_sensitive(!bContour); + + if( bContour && bContourEnabled ) + { + m_xMtrFldLeft->set_value(0, FieldUnit::NONE); + m_xMtrFldRight->set_value(0, FieldUnit::NONE); + m_xMtrFldTop->set_value(0, FieldUnit::NONE); + m_xMtrFldBottom->set_value(0, FieldUnit::NONE); + } + + // #103516# Do the setup based on states of hor/ver adjust + SfxItemState eVState = rOutAttrs.GetItemState( SDRATTR_TEXT_VERTADJUST ); + SfxItemState eHState = rOutAttrs.GetItemState( SDRATTR_TEXT_HORZADJUST ); + bool bHorAndVer(SfxItemState::DONTCARE == eVState || SfxItemState::DONTCARE == eHState); + + // #83698# enable/disable text anchoring dependent of contour + m_xFlPosition->set_sensitive(!bContour && !bHorAndVer); +} + + +bool SvxTextAttrPage::IsTextDirectionLeftToRight() const +{ + // Determine the text writing direction with left to right as default. + bool bLeftToRightDirection = true; + SfxItemState eState = rOutAttrs.GetItemState(SDRATTR_TEXTDIRECTION); + + if(SfxItemState::DONTCARE != eState) + { + const SvxWritingModeItem& rItem = rOutAttrs.Get(SDRATTR_TEXTDIRECTION); + if (rItem.GetValue() == css::text::WritingMode_TB_RL) + bLeftToRightDirection = false; + } + return bLeftToRightDirection; +} + +void SvxTextAttrPage::PageCreated(const SfxAllItemSet& aSet) +{ + const CntUInt16Item* pObjTypeItem = aSet.GetItem(SID_SVXTEXTATTRPAGE_OBJKIND, false); + + if (pObjTypeItem) + SetObjKind(static_cast(pObjTypeItem->GetValue())); + + Construct(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/tparea.cxx b/cui/source/tabpages/tparea.cxx new file mode 100644 index 000000000..079b717c3 --- /dev/null +++ b/cui/source/tabpages/tparea.cxx @@ -0,0 +1,465 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace com::sun::star; + +// static ---------------------------------------------------------------- + +namespace { + +enum FillType +{ + TRANSPARENT, + SOLID, + GRADIENT, + HATCH, + BITMAP, + PATTERN +}; + +} + +const sal_uInt16 SvxAreaTabPage::pAreaRanges[] = +{ + XATTR_GRADIENTSTEPCOUNT, + XATTR_GRADIENTSTEPCOUNT, + SID_ATTR_FILL_STYLE, + SID_ATTR_FILL_BITMAP, + 0 +}; + +namespace +{ + +void lclExtendSize(Size& rSize, const Size& rInputSize) +{ + if (rSize.Width() < rInputSize.Width()) + rSize.setWidth( rInputSize.Width() ); + if (rSize.Height() < rInputSize.Height()) + rSize.setHeight( rInputSize.Height() ); +} + +} // end anonymous namespace + +/************************************************************************* +|* +|* Dialog to modify fill-attributes +|* +\************************************************************************/ + +SvxAreaTabPage::SvxAreaTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "cui/ui/areatabpage.ui", "AreaTabPage", &rInAttrs) + // local fixed not o be changed values for local pointers + , maFixed_ChangeType(ChangeType::NONE) + // init with pointers to fixed ChangeType + , m_pnColorListState(&maFixed_ChangeType) + , m_pnBitmapListState(&maFixed_ChangeType) + , m_pnPatternListState(&maFixed_ChangeType) + , m_pnGradientListState(&maFixed_ChangeType) + , m_pnHatchingListState(&maFixed_ChangeType) + , m_aXFillAttr(rInAttrs.GetPool()) + , m_rXFSet(m_aXFillAttr.GetItemSet()) + , m_xFillTab(m_xBuilder->weld_container("fillstylebox")) + , m_xBtnNone(m_xBuilder->weld_toggle_button("btnnone")) + , m_xBtnColor(m_xBuilder->weld_toggle_button("btncolor")) + , m_xBtnGradient(m_xBuilder->weld_toggle_button("btngradient")) + , m_xBtnHatch(m_xBuilder->weld_toggle_button("btnhatch")) + , m_xBtnBitmap(m_xBuilder->weld_toggle_button("btnbitmap")) + , m_xBtnPattern(m_xBuilder->weld_toggle_button("btnpattern")) +{ + maBox.AddButton(m_xBtnNone.get()); + maBox.AddButton(m_xBtnColor.get()); + maBox.AddButton(m_xBtnGradient.get()); + maBox.AddButton(m_xBtnHatch.get()); + maBox.AddButton(m_xBtnBitmap.get()); + maBox.AddButton(m_xBtnPattern.get()); + Link aLink = LINK(this, SvxAreaTabPage, SelectFillTypeHdl_Impl); + m_xBtnNone->connect_toggled(aLink); + m_xBtnColor->connect_toggled(aLink); + m_xBtnGradient->connect_toggled(aLink); + m_xBtnHatch->connect_toggled(aLink); + m_xBtnBitmap->connect_toggled(aLink); + m_xBtnPattern->connect_toggled(aLink); + + SetExchangeSupport(); +} + +void SvxAreaTabPage::SetOptimalSize(weld::DialogController* pController) +{ + m_xFillTab->set_size_request(-1, -1); + + // Calculate optimal size of all pages... + m_xFillTabPage = SvxColorTabPage::Create(m_xFillTab.get(), pController, &m_rXFSet); + Size aSize(m_xFillTab->get_preferred_size()); + + if (m_xBtnGradient->get_visible()) + { + m_xFillTabPage = SvxGradientTabPage::Create(m_xFillTab.get(), pController, &m_rXFSet); + Size aGradientSize = m_xFillTab->get_preferred_size(); + lclExtendSize(aSize, aGradientSize); + } + if (m_xBtnBitmap->get_visible()) + { + m_xFillTabPage = SvxBitmapTabPage::Create(m_xFillTab.get(), pController, &m_rXFSet); + Size aBitmapSize = m_xFillTab->get_preferred_size(); + lclExtendSize(aSize, aBitmapSize); + } + if (m_xBtnHatch->get_visible()) + { + m_xFillTabPage = SvxHatchTabPage::Create(m_xFillTab.get(), pController, &m_rXFSet); + Size aHatchSize = m_xFillTab->get_preferred_size(); + lclExtendSize(aSize, aHatchSize); + } + if (m_xBtnPattern->get_visible()) + { + m_xFillTabPage = SvxPatternTabPage::Create(m_xFillTab.get(), pController, &m_rXFSet); + Size aPatternSize = m_xFillTab->get_preferred_size(); + lclExtendSize(aSize, aPatternSize); + } + m_xFillTabPage.reset(); + + aSize.extendBy(10, 10); // apply a bit of margin + + m_xFillTab->set_size_request(aSize.Width(), aSize.Height()); +} + +SvxAreaTabPage::~SvxAreaTabPage() +{ + m_xFillTabPage.reset(); +} + +void SvxAreaTabPage::ActivatePage( const SfxItemSet& rSet ) +{ + drawing::FillStyle eXFS = drawing::FillStyle_NONE; + if( rSet.GetItemState( XATTR_FILLSTYLE ) != SfxItemState::DONTCARE ) + { + XFillStyleItem aFillStyleItem( static_cast( rSet.Get( GetWhich( XATTR_FILLSTYLE ) ) ) ); + eXFS = aFillStyleItem.GetValue(); + m_rXFSet.Put( aFillStyleItem ); + } + + switch(eXFS) + { + default: + case drawing::FillStyle_NONE: + { + SelectFillType(*m_xBtnNone); + break; + } + case drawing::FillStyle_SOLID: + { + m_rXFSet.Put( static_cast( rSet.Get( GetWhich( XATTR_FILLCOLOR ) ) ) ); + SelectFillType(*m_xBtnColor); + break; + } + case drawing::FillStyle_GRADIENT: + { + m_rXFSet.Put( static_cast( rSet.Get( GetWhich( XATTR_FILLGRADIENT ) ) ) ); + SelectFillType(*m_xBtnGradient); + break; + } + case drawing::FillStyle_HATCH: + { + m_rXFSet.Put( rSet.Get(XATTR_FILLHATCH) ); + m_rXFSet.Put( rSet.Get(XATTR_FILLBACKGROUND) ); + m_rXFSet.Put( rSet.Get(XATTR_FILLCOLOR) ); + SelectFillType(*m_xBtnHatch); + break; + } + case drawing::FillStyle_BITMAP: + { + const bool bPattern + = rSet.Get(TypedWhichId(GetWhich(XATTR_FILLBITMAP))).isPattern(); + // pass full item set here, bitmap fill has many attributes (tiling, size, offset etc.) + m_rXFSet.Put( rSet ); + if (!bPattern) + SelectFillType(*m_xBtnBitmap); + else + SelectFillType(*m_xBtnPattern); + break; + } + } +} + +template< typename TTabPage > +DeactivateRC SvxAreaTabPage::DeactivatePage_Impl( SfxItemSet* _pSet ) +{ + return static_cast(*m_xFillTabPage).DeactivatePage(_pSet); +} + +DeactivateRC SvxAreaTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + FillType eFillType = static_cast(maBox.GetCurrentButtonPos()); + switch( eFillType ) + { + case TRANSPARENT: + { + // Fill: None doesn't have its own tabpage and thus + // implementation of FillItemSet, so we supply it here + if ( m_bBtnClicked ) + { + XFillStyleItem aStyleItem( drawing::FillStyle_NONE ); + _pSet->Put( aStyleItem ); + } + break; + } + case SOLID: + return DeactivatePage_Impl(_pSet); + case GRADIENT: + return DeactivatePage_Impl(_pSet); + case HATCH: + return DeactivatePage_Impl(_pSet); + case BITMAP: + return DeactivatePage_Impl(_pSet); + case PATTERN: + return DeactivatePage_Impl(_pSet); + default: + break; + } + return DeactivateRC::LeavePage; +} + +template< typename TTabPage > +bool SvxAreaTabPage::FillItemSet_Impl( SfxItemSet* rAttrs) +{ + return static_cast( *m_xFillTabPage ).FillItemSet( rAttrs ); +} + +bool SvxAreaTabPage::FillItemSet( SfxItemSet* rAttrs ) +{ + FillType eFillType = static_cast(maBox.GetCurrentButtonPos()); + switch( eFillType ) + { + case TRANSPARENT: + { + rAttrs->Put( XFillStyleItem( drawing::FillStyle_NONE ) ); + return true; + } + case SOLID: + { + return FillItemSet_Impl( rAttrs ); + } + case GRADIENT: + { + return FillItemSet_Impl( rAttrs ); + } + case HATCH: + { + return FillItemSet_Impl( rAttrs ); + } + case BITMAP: + { + return FillItemSet_Impl( rAttrs ); + } + case PATTERN: + { + return FillItemSet_Impl( rAttrs ); + } + default: + return false; + } +} + +template< typename TTabPage > +void SvxAreaTabPage::Reset_Impl( const SfxItemSet* rAttrs ) +{ + static_cast( *m_xFillTabPage ).Reset( rAttrs ); +} + +void SvxAreaTabPage::Reset( const SfxItemSet* rAttrs ) +{ + m_bBtnClicked = false; + auto eFillType = maBox.GetCurrentButtonPos(); + switch(eFillType) + { + case SOLID: + { + Reset_Impl( rAttrs ); + break; + } + case GRADIENT: + { + Reset_Impl( rAttrs ); + break; + } + case HATCH: + { + Reset_Impl( rAttrs ); + break; + } + case BITMAP: + { + Reset_Impl( rAttrs ); + break; + } + case PATTERN: + { + Reset_Impl( rAttrs ); + break; + } + default: + break; + } +} + +std::unique_ptr SvxAreaTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrs) +{ + auto xRet = std::make_unique(pPage, pController, *rAttrs); + xRet->SetOptimalSize(pController); + return xRet; +} + +namespace { + +std::unique_ptr lcl_CreateFillStyleTabPage(sal_uInt16 nId, weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) +{ + CreateTabPage fnCreate = nullptr; + switch(nId) + { + case TRANSPARENT: fnCreate = nullptr; break; + case SOLID: fnCreate = &SvxColorTabPage::Create; break; + case GRADIENT: fnCreate = &SvxGradientTabPage::Create; break; + case HATCH: fnCreate = &SvxHatchTabPage::Create; break; + case BITMAP: fnCreate = &SvxBitmapTabPage::Create; break; + case PATTERN: fnCreate = &SvxPatternTabPage::Create; break; + } + return fnCreate ? (*fnCreate)( pPage, pController, &rSet ) : nullptr; +} + +} + +IMPL_LINK(SvxAreaTabPage, SelectFillTypeHdl_Impl, weld::ToggleButton&, rButton, void) +{ + //tdf#124549 - If the button is already active do not toggle it back. + if(!rButton.get_active()) + rButton.set_active(true); + + SelectFillType(rButton); + m_bBtnClicked = true; +} + +void SvxAreaTabPage::SelectFillType(weld::ToggleButton& rButton, const SfxItemSet* _pSet) +{ + if (_pSet) + m_rXFSet.Set(*_pSet); + + sal_Int32 nPos = maBox.GetButtonPos(&rButton); + if (nPos != -1 && (_pSet || nPos != maBox.GetCurrentButtonPos())) + { + maBox.SelectButton(&rButton); + FillType eFillType = static_cast(maBox.GetCurrentButtonPos()); + m_xFillTabPage = lcl_CreateFillStyleTabPage(eFillType, m_xFillTab.get(), GetDialogController(), m_rXFSet); + if (m_xFillTabPage) + m_xFillTabPage->SetDialogController(GetDialogController()); + CreatePage(eFillType, m_xFillTabPage.get()); + } +} + +void SvxAreaTabPage::PageCreated(const SfxAllItemSet& aSet) +{ + const SvxColorListItem* pColorListItem = aSet.GetItem(SID_COLOR_TABLE, false); + const SvxGradientListItem* pGradientListItem = aSet.GetItem(SID_GRADIENT_LIST, false); + const SvxHatchListItem* pHatchingListItem = aSet.GetItem(SID_HATCH_LIST, false); + const SvxBitmapListItem* pBitmapListItem = aSet.GetItem(SID_BITMAP_LIST, false); + const SvxPatternListItem* pPatternListItem = aSet.GetItem(SID_PATTERN_LIST, false); + + if (pColorListItem) + SetColorList(pColorListItem->GetColorList()); + if (pGradientListItem) + SetGradientList(pGradientListItem->GetGradientList()); + if (pHatchingListItem) + SetHatchingList(pHatchingListItem->GetHatchList()); + if (pBitmapListItem) + SetBitmapList(pBitmapListItem->GetBitmapList()); + if (pPatternListItem) + SetPatternList(pPatternListItem->GetPatternList()); +} + +void SvxAreaTabPage::CreatePage( sal_Int32 nId, SfxTabPage* pTab ) +{ + if(nId == SOLID ) + { + auto* pColorTab = static_cast(pTab); + pColorTab->SetColorList(m_pColorList); + pColorTab->SetColorChgd(m_pnColorListState); + pColorTab->Construct(); + pColorTab->ActivatePage(m_rXFSet); + pColorTab->Reset(&m_rXFSet); + pColorTab->set_visible(true); + } + else if(nId == GRADIENT) + { + auto* pGradientTab = static_cast(pTab); + pGradientTab->SetColorList(m_pColorList); + pGradientTab->SetGradientList(m_pGradientList); + pGradientTab->SetGrdChgd(m_pnGradientListState); + pGradientTab->SetColorChgd(m_pnColorListState); + pGradientTab->Construct(); + pGradientTab->ActivatePage(m_rXFSet); + pGradientTab->Reset(&m_rXFSet); + pGradientTab->set_visible(true); + } + else if(nId == HATCH) + { + auto* pHatchTab = static_cast(pTab); + pHatchTab->SetColorList(m_pColorList); + pHatchTab->SetHatchingList(m_pHatchingList); + pHatchTab->SetHtchChgd(m_pnHatchingListState); + pHatchTab->SetColorChgd(m_pnColorListState); + pHatchTab->Construct(); + pHatchTab->ActivatePage(m_rXFSet); + pHatchTab->Reset(&m_rXFSet); + pHatchTab->set_visible(true); + } + else if(nId == BITMAP) + { + auto* pBitmapTab = static_cast(pTab); + pBitmapTab->SetBitmapList(m_pBitmapList); + pBitmapTab->SetBmpChgd(m_pnBitmapListState); + pBitmapTab->Construct(); + pBitmapTab->ActivatePage(m_rXFSet); + pBitmapTab->Reset(&m_rXFSet); + pBitmapTab->set_visible(true); + } + else if(nId == PATTERN) + { + auto* pPatternTab = static_cast(pTab); + pPatternTab->SetColorList(m_pColorList); + pPatternTab->SetPatternList(m_pPatternList); + pPatternTab->SetPtrnChgd(m_pnPatternListState); + pPatternTab->SetColorChgd(m_pnColorListState); + pPatternTab->Construct(); + pPatternTab->ActivatePage(m_rXFSet); + pPatternTab->Reset(&m_rXFSet); + pPatternTab->set_visible(true); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/tpbitmap.cxx b/cui/source/tabpages/tpbitmap.cxx new file mode 100644 index 000000000..87f22835a --- /dev/null +++ b/cui/source/tabpages/tpbitmap.cxx @@ -0,0 +1,825 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace com::sun::star; + +namespace { + +enum BitmapStyle +{ + CUSTOM, + TILED, + STRETCHED +}; + +enum TileOffset +{ + ROW, + COLUMN +}; + +} + +const sal_uInt16 SvxBitmapTabPage::pBitmapRanges[] = +{ + SID_ATTR_TRANSFORM_WIDTH, + SID_ATTR_TRANSFORM_HEIGHT, + 0 +}; + +SvxBitmapTabPage::SvxBitmapTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "cui/ui/bitmaptabpage.ui", "BitmapTabPage", &rInAttrs) + , m_rOutAttrs(rInAttrs) + , m_pnBitmapListState(nullptr) + , m_fObjectWidth(0.0) + , m_fObjectHeight(0.0) + , m_bLogicalSize(false) + , m_aXFillAttr(rInAttrs.GetPool()) + , m_rXFSet(m_aXFillAttr.GetItemSet()) + , mpView(nullptr) + , m_xBitmapLB(new SvxPresetListBox(m_xBuilder->weld_scrolled_window("bitmapwin"))) + , m_xBitmapStyleLB(m_xBuilder->weld_combo_box("bitmapstyle")) + , m_xSizeBox(m_xBuilder->weld_container("sizebox")) + , m_xTsbScale(m_xBuilder->weld_check_button("scaletsb")) + , m_xBitmapWidth(m_xBuilder->weld_metric_spin_button("width", FieldUnit::PERCENT)) + , m_xBitmapHeight(m_xBuilder->weld_metric_spin_button("height", FieldUnit::PERCENT)) + , m_xPositionBox(m_xBuilder->weld_container("posbox")) + , m_xPositionLB(m_xBuilder->weld_combo_box("positionlb")) + , m_xPositionOffBox(m_xBuilder->weld_container("posoffbox")) + , m_xPositionOffX(m_xBuilder->weld_metric_spin_button("posoffx", FieldUnit::PERCENT)) + , m_xPositionOffY(m_xBuilder->weld_metric_spin_button("posoffy", FieldUnit::PERCENT)) + , m_xTileOffBox(m_xBuilder->weld_container("tileoffbox")) + , m_xTileOffLB(m_xBuilder->weld_combo_box("tileofflb")) + , m_xTileOffset(m_xBuilder->weld_metric_spin_button("tileoffmtr", FieldUnit::PERCENT)) + , m_xBtnImport(m_xBuilder->weld_button("BTN_IMPORT")) + , m_xCtlBitmapPreview(new weld::CustomWeld(*m_xBuilder, "CTL_BITMAP_PREVIEW", m_aCtlBitmapPreview)) + , m_xBitmapLBWin(new weld::CustomWeld(*m_xBuilder, "BITMAP", *m_xBitmapLB)) +{ + // setting the output device + m_rXFSet.Put( XFillStyleItem(drawing::FillStyle_BITMAP) ); + m_rXFSet.Put( XFillBitmapItem(OUString(), Graphic()) ); + m_aCtlBitmapPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + + m_xBitmapLB->SetSelectHdl( LINK(this, SvxBitmapTabPage, ModifyBitmapHdl) ); + m_xBitmapLB->SetRenameHdl( LINK(this, SvxBitmapTabPage, ClickRenameHdl) ); + m_xBitmapLB->SetDeleteHdl( LINK(this, SvxBitmapTabPage, ClickDeleteHdl) ); + m_xBitmapStyleLB->connect_changed( LINK(this, SvxBitmapTabPage, ModifyBitmapStyleHdl) ); + Link aLink1( LINK(this, SvxBitmapTabPage, ModifyBitmapSizeHdl) ); + m_xBitmapWidth->connect_value_changed( aLink1 ); + m_xBitmapHeight->connect_value_changed( aLink1 ); + m_xTsbScale->connect_clicked(LINK(this, SvxBitmapTabPage, ClickScaleHdl)); + m_xPositionLB->connect_changed( LINK( this, SvxBitmapTabPage, ModifyBitmapPositionHdl ) ); + Link aLink( LINK( this, SvxBitmapTabPage, ModifyPositionOffsetHdl ) ); + m_xPositionOffX->connect_value_changed(aLink); + m_xPositionOffY->connect_value_changed(aLink); + m_xTileOffset->connect_value_changed( LINK( this, SvxBitmapTabPage, ModifyTileOffsetHdl ) ); + m_xBtnImport->connect_clicked( LINK(this, SvxBitmapTabPage, ClickImportHdl) ); + if (comphelper::LibreOfficeKit::isActive()) + m_xBtnImport->hide(); + + // Calculate size of display boxes + Size aSize = getDrawPreviewOptimalSize(m_aCtlBitmapPreview.GetDrawingArea()->get_ref_device()); + m_xBitmapLB->set_size_request(aSize.Width(), aSize.Height()); + m_xCtlBitmapPreview->set_size_request(aSize.Width(), aSize.Height()); + + SfxItemPool* pPool = m_rXFSet.GetPool(); + mePoolUnit = pPool->GetMetric( XATTR_FILLBMP_SIZEX ); + meFieldUnit = GetModuleFieldUnit( rInAttrs ); + SetFieldUnit( *m_xBitmapWidth, meFieldUnit, true ); + SetFieldUnit( *m_xBitmapHeight, meFieldUnit, true ); + + SfxViewShell* pViewShell = SfxViewShell::Current(); + if( pViewShell ) + mpView = pViewShell->GetDrawView(); + DBG_ASSERT( mpView, "no valid view (!)" ); +} + +SvxBitmapTabPage::~SvxBitmapTabPage() +{ + m_xBitmapLBWin.reset(); + m_xBitmapLB.reset(); + m_xCtlBitmapPreview.reset(); +} + +void SvxBitmapTabPage::Construct() +{ + m_xBitmapLB->FillPresetListBox( *m_pBitmapList ); +} + +void SvxBitmapTabPage::ActivatePage( const SfxItemSet& rSet ) +{ + XFillBitmapItem aItem( rSet.Get(XATTR_FILLBITMAP) ); + + sal_Int32 nPos( 0 ); + if ( !aItem.isPattern() ) + { + nPos = SearchBitmapList( aItem.GetGraphicObject() ); + if (nPos == -1) + return; + } + else + { + m_xBitmapWidth->set_value( 100, FieldUnit::NONE ); + m_xBitmapHeight->set_value( 100, FieldUnit::NONE ); + const_cast(rSet).Put( XFillBmpSizeXItem( GetCoreValue( *m_xBitmapWidth, mePoolUnit ) ) ); + const_cast(rSet).Put( XFillBmpSizeYItem( GetCoreValue( *m_xBitmapHeight, mePoolUnit ) ) ); + } + + sal_uInt16 nId = m_xBitmapLB->GetItemId( static_cast( nPos ) ); + m_xBitmapLB->SelectItem( nId ); +} + +DeactivateRC SvxBitmapTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if( _pSet ) + FillItemSet( _pSet ); + + return DeactivateRC::LeavePage; +} + + +bool SvxBitmapTabPage::FillItemSet( SfxItemSet* rAttrs ) +{ + rAttrs->Put(XFillStyleItem(drawing::FillStyle_BITMAP)); + size_t nPos = m_xBitmapLB->GetSelectItemPos(); + if(VALUESET_ITEM_NOTFOUND != nPos) + { + const XBitmapEntry* pXBitmapEntry = m_pBitmapList->GetBitmap(nPos); + const OUString aString(m_xBitmapLB->GetItemText( m_xBitmapLB->GetSelectedItemId() )); + rAttrs->Put(XFillBitmapItem(aString, pXBitmapEntry->GetGraphicObject())); + } + + BitmapStyle eStylePos = static_cast(m_xBitmapStyleLB->get_active()); + bool bIsStretched( eStylePos == STRETCHED ); + bool bIsTiled( eStylePos == TILED ); + + rAttrs->Put( XFillBmpTileItem(bIsTiled) ); + rAttrs->Put( XFillBmpStretchItem(bIsStretched) ); + + if(!bIsStretched) + { + Size aSetBitmapSize; + switch(eStylePos) + { + case CUSTOM: + case TILED: + { + sal_Int64 nWidthPercent = m_xBitmapWidth->get_value(FieldUnit::NONE); + sal_Int64 nHeightPercent = m_xBitmapHeight->get_value(FieldUnit::NONE); + if (m_xTsbScale->get_sensitive() && m_xTsbScale->get_state() == TRISTATE_TRUE) + { + aSetBitmapSize.setWidth( -nWidthPercent ); + aSetBitmapSize.setHeight( -nHeightPercent ); + } + else if (!m_bLogicalSize) + { + aSetBitmapSize.setWidth( GetCoreValue(*m_xBitmapWidth, mePoolUnit) ); + aSetBitmapSize.setHeight( GetCoreValue(*m_xBitmapHeight, mePoolUnit) ); + } + else + { + rAttrs->Put( XFillBmpSizeLogItem(true) ); + aSetBitmapSize.setWidth( 0 ); + aSetBitmapSize.setHeight( 0 ); + } + + break; + } + default: + break; + } + + rAttrs->Put( XFillBmpSizeXItem( aSetBitmapSize.Width() ) ); + rAttrs->Put( XFillBmpSizeYItem( aSetBitmapSize.Height() ) ); + } + + if (m_xPositionLB->get_sensitive()) + rAttrs->Put( XFillBmpPosItem( static_cast( m_xPositionLB->get_active() ) ) ); + if (m_xPositionOffX->get_sensitive()) + rAttrs->Put( XFillBmpPosOffsetXItem(m_xPositionOffX->get_value(FieldUnit::PERCENT))); + if (m_xPositionOffY->get_sensitive()) + rAttrs->Put( XFillBmpPosOffsetYItem(m_xPositionOffY->get_value(FieldUnit::PERCENT))); + if (m_xTileOffBox->get_sensitive()) + { + TileOffset eValue = static_cast(m_xTileOffLB->get_active()); + sal_uInt16 nOffsetValue = static_cast(m_xTileOffset->get_value(FieldUnit::PERCENT)); + sal_uInt16 nRowOff = (eValue == ROW) ? nOffsetValue : 0; + sal_uInt16 nColOff = (eValue == COLUMN) ? nOffsetValue : 0; + rAttrs->Put( XFillBmpTileOffsetXItem(nRowOff) ); + rAttrs->Put( XFillBmpTileOffsetYItem(nColOff) ); + } + return true; +} + + +void SvxBitmapTabPage::Reset( const SfxItemSet* rAttrs ) +{ + double transfWidth = 0.0; + double transfHeight = 0.0; + double fUIScale = 1.0; + if (mpView) + { + fUIScale = ( mpView->GetModel() ? double(mpView->GetModel()->GetUIScale()) : 1.0); + + + if (mpView->AreObjectsMarked()) + { + SfxItemSet rGeoAttr(mpView->GetGeoAttrFromMarked()); + transfWidth = static_cast(GetItem( rGeoAttr, SID_ATTR_TRANSFORM_WIDTH )->GetValue()); + transfHeight= static_cast(GetItem( rGeoAttr, SID_ATTR_TRANSFORM_HEIGHT )->GetValue()); + } + } + m_fObjectWidth = std::max( transfWidth, 1.0 ); + m_fObjectHeight = std::max( transfHeight, 1.0 ); + double fTmpWidth((OutputDevice::LogicToLogic(static_cast(m_fObjectWidth), mePoolUnit, MapUnit::Map100thMM )) / fUIScale); + m_fObjectWidth = fTmpWidth; + + double fTmpHeight((OutputDevice::LogicToLogic(static_cast(m_fObjectHeight), mePoolUnit, MapUnit::Map100thMM )) / fUIScale); + m_fObjectHeight = fTmpHeight; + + XFillBitmapItem aItem( rAttrs->Get(XATTR_FILLBITMAP) ); + + if(!aItem.isPattern()) + { + m_rXFSet.Put( aItem ); + m_aCtlBitmapPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + m_aCtlBitmapPreview.Invalidate(); + } + else + m_xCtlBitmapPreview->set_sensitive(false); + + std::unique_ptr pGraphicObject; + pGraphicObject.reset( new GraphicObject(aItem.GetGraphicObject()) ); + + BitmapEx aBmpEx(pGraphicObject->GetGraphic().GetBitmapEx()); + Size aTempBitmapSize = aBmpEx.GetSizePixel(); + rBitmapSize = Application::GetDefaultDevice()->PixelToLogic(aTempBitmapSize, MapMode(MapUnit::Map100thMM)); + CalculateBitmapPresetSize(); + + bool bTiled = false; bool bStretched = false; + if(rAttrs->GetItemState( XATTR_FILLBMP_TILE ) != SfxItemState::DONTCARE) + bTiled = rAttrs->Get( XATTR_FILLBMP_TILE ).GetValue(); + if(rAttrs->GetItemState( XATTR_FILLBMP_STRETCH ) != SfxItemState::DONTCARE) + bStretched = rAttrs->Get( XATTR_FILLBMP_STRETCH ).GetValue(); + + if (bTiled) + m_xBitmapStyleLB->set_active(static_cast(TILED)); + else if (bStretched) + m_xBitmapStyleLB->set_active(static_cast(STRETCHED)); + else + m_xBitmapStyleLB->set_active(static_cast(CUSTOM)); + + long nWidth = 0; + long nHeight = 0; + + if(rAttrs->GetItemState(XATTR_FILLBMP_SIZELOG) != SfxItemState::DONTCARE) + { + if (rAttrs->Get( XATTR_FILLBMP_SIZELOG ).GetValue()) + { + m_xTsbScale->set_state(TRISTATE_FALSE); + m_bLogicalSize = true; + } + else + { + m_xTsbScale->set_state(TRISTATE_TRUE); + m_bLogicalSize = false; + } + } + else + m_xTsbScale->set_state(TRISTATE_INDET); + + TriState eRelative = TRISTATE_FALSE; + if(rAttrs->GetItemState(XATTR_FILLBMP_SIZEX) != SfxItemState::DONTCARE) + { + nWidth = static_cast( rAttrs->Get( XATTR_FILLBMP_SIZEX ) ).GetValue(); + if(nWidth == 0) + nWidth = rBitmapSize.Width(); + else if(nWidth < 0) + { + eRelative = TRISTATE_TRUE; + nWidth = std::abs(nWidth); + } + } + + if(rAttrs->GetItemState( XATTR_FILLBMP_SIZEY ) != SfxItemState::DONTCARE) + { + nHeight = rAttrs->Get( XATTR_FILLBMP_SIZEY ).GetValue(); + if(nHeight == 0) + nHeight = rBitmapSize.Height(); + else if(nHeight < 0) + { + eRelative = TRISTATE_TRUE; + nHeight = std::abs(nHeight); + } + } + m_xTsbScale->set_state(eRelative); + ClickScaleHdl(*m_xTsbScale); + + + if(!rBitmapSize.IsEmpty()) + { + if (eRelative == TRISTATE_TRUE) + { + m_xBitmapWidth->set_value(nWidth, FieldUnit::NONE); + m_xBitmapHeight->set_value(nHeight, FieldUnit::NONE); + } + else + { + SetMetricValue(*m_xBitmapWidth, nWidth, mePoolUnit); + SetMetricValue(*m_xBitmapHeight, nHeight, mePoolUnit); + } + } + + if( rAttrs->GetItemState( XATTR_FILLBMP_POS ) != SfxItemState::DONTCARE ) + { + RectPoint eValue = rAttrs->Get( XATTR_FILLBMP_POS ).GetValue(); + m_xPositionLB->set_active( static_cast< sal_Int32 >(eValue) ); + } + + if( rAttrs->GetItemState( XATTR_FILLBMP_POSOFFSETX ) != SfxItemState::DONTCARE ) + { + sal_Int32 nValue = rAttrs->Get( XATTR_FILLBMP_POSOFFSETX ).GetValue(); + m_xPositionOffX->set_value(nValue, FieldUnit::PERCENT); + } + else + m_xPositionOffX->set_text(""); + + if( rAttrs->GetItemState( XATTR_FILLBMP_POSOFFSETY ) != SfxItemState::DONTCARE ) + { + sal_Int32 nValue = rAttrs->Get( XATTR_FILLBMP_POSOFFSETY ).GetValue(); + m_xPositionOffY->set_value(nValue, FieldUnit::PERCENT); + } + else + m_xPositionOffY->set_text(""); + + if( rAttrs->GetItemState( XATTR_FILLBMP_TILEOFFSETX ) != SfxItemState::DONTCARE) + { + sal_Int32 nValue = rAttrs->Get( XATTR_FILLBMP_TILEOFFSETX ).GetValue(); + if(nValue > 0) + { + m_xTileOffLB->set_active(static_cast(ROW)); + m_xTileOffset->set_value(nValue, FieldUnit::PERCENT); + } + } + + if( rAttrs->GetItemState( XATTR_FILLBMP_TILEOFFSETY ) != SfxItemState::DONTCARE ) + { + sal_Int32 nValue = rAttrs->Get( XATTR_FILLBMP_TILEOFFSETY ).GetValue(); + if(nValue > 0) + { + m_xTileOffLB->set_active(static_cast(COLUMN)); + m_xTileOffset->set_value(nValue, FieldUnit::PERCENT); + } + } + + ClickBitmapHdl_Impl(); +} + +std::unique_ptr SvxBitmapTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrs) +{ + return std::make_unique(pPage, pController, *rAttrs); +} + +void SvxBitmapTabPage::ClickBitmapHdl_Impl() +{ + m_xBitmapLBWin->set_sensitive(true); + m_xCtlBitmapPreview->set_sensitive(true); + + ModifyBitmapHdl(m_xBitmapLB.get()); +} + +void SvxBitmapTabPage::CalculateBitmapPresetSize() +{ + if(rBitmapSize.IsEmpty()) + return; + + long nObjectWidth = static_cast(m_fObjectWidth); + long nObjectHeight = static_cast(m_fObjectHeight); + + if(std::abs(rBitmapSize.Width() - nObjectWidth) < std::abs(rBitmapSize.Height() - nObjectHeight)) + { + rFilledSize.setWidth( nObjectWidth ); + rFilledSize.setHeight( rBitmapSize.Height()*nObjectWidth/rBitmapSize.Width() ); + rZoomedSize.setWidth( rBitmapSize.Width()*nObjectHeight/rBitmapSize.Height() ); + rZoomedSize.setHeight( nObjectHeight ); + } + else + { + rFilledSize.setWidth( rBitmapSize.Width()*nObjectHeight/rBitmapSize.Height() ); + rFilledSize.setHeight( nObjectHeight ); + rZoomedSize.setWidth( nObjectWidth ); + rZoomedSize.setHeight( rBitmapSize.Height()*nObjectWidth/rBitmapSize.Width() ); + } +} + +IMPL_LINK_NOARG(SvxBitmapTabPage, ModifyBitmapHdl, ValueSet*, void) +{ + std::unique_ptr pGraphicObject; + size_t nPos = m_xBitmapLB->GetSelectItemPos(); + + if( nPos != VALUESET_ITEM_NOTFOUND ) + { + pGraphicObject.reset(new GraphicObject(m_pBitmapList->GetBitmap( static_cast(nPos) )->GetGraphicObject())); + } + else + { + const SfxPoolItem* pPoolItem = nullptr; + + if(SfxItemState::SET == m_rOutAttrs.GetItemState(GetWhich(XATTR_FILLSTYLE), true, &pPoolItem)) + { + const drawing::FillStyle eXFS(static_cast(pPoolItem)->GetValue()); + + if((drawing::FillStyle_BITMAP == eXFS) && (SfxItemState::SET == m_rOutAttrs.GetItemState(GetWhich(XATTR_FILLBITMAP), true, &pPoolItem))) + { + pGraphicObject.reset(new GraphicObject(static_cast(pPoolItem)->GetGraphicObject())); + } + } + + if(!pGraphicObject) + { + sal_uInt16 nId = m_xBitmapLB->GetItemId(0); + m_xBitmapLB->SelectItem(nId); + + if(0 != nId) + { + pGraphicObject.reset(new GraphicObject(m_pBitmapList->GetBitmap(0)->GetGraphicObject())); + } + } + } + + if(pGraphicObject) + { + BitmapEx aBmpEx(pGraphicObject->GetGraphic().GetBitmapEx()); + Size aTempBitmapSize = aBmpEx.GetSizePixel(); + const double fUIScale = ( (mpView && mpView->GetModel()) ? double(mpView->GetModel()->GetUIScale()) : 1.0); + + rBitmapSize.setWidth( (OutputDevice::LogicToLogic(static_cast(aTempBitmapSize.Width()),MapUnit::MapPixel, MapUnit::Map100thMM )) / fUIScale ); + rBitmapSize.setHeight( (OutputDevice::LogicToLogic(static_cast(aTempBitmapSize.Height()),MapUnit::MapPixel, MapUnit::Map100thMM )) / fUIScale ); + CalculateBitmapPresetSize(); + ModifyBitmapStyleHdl( *m_xBitmapStyleLB ); + ModifyBitmapPositionHdl( *m_xPositionLB ); + + m_rXFSet.ClearItem(XATTR_FILLBITMAP); + m_rXFSet.Put(XFillStyleItem(drawing::FillStyle_BITMAP)); + m_rXFSet.Put(XFillBitmapItem(OUString(), *pGraphicObject)); + + m_aCtlBitmapPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + m_aCtlBitmapPreview.Invalidate(); + } + else + { + SAL_WARN("cui.tabpages", "SvxBitmapTabPage::ModifyBitmapHdl(): null pGraphicObject"); + } + +} + +IMPL_LINK_NOARG(SvxBitmapTabPage, ClickRenameHdl, SvxPresetListBox*, void) +{ + sal_uInt16 nId = m_xBitmapLB->GetSelectedItemId(); + size_t nPos = m_xBitmapLB->GetSelectItemPos(); + + if( nPos == VALUESET_ITEM_NOTFOUND ) + return; + + OUString aDesc( CuiResId( RID_SVXSTR_DESC_NEW_BITMAP ) ); + OUString aName( m_pBitmapList->GetBitmap( nPos )->GetName() ); + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateSvxNameDialog(GetFrameWeld(), aName, aDesc)); + + bool bLoop = true; + while( bLoop && pDlg->Execute() == RET_OK ) + { + pDlg->GetName( aName ); + sal_Int32 nBitmapPos = SearchBitmapList( aName ); + bool bValidBitmapName = (nBitmapPos == static_cast(nPos) ) || (nBitmapPos == -1); + + if(bValidBitmapName) + { + bLoop = false; + m_pBitmapList->GetBitmap(nPos)->SetName(aName); + + m_xBitmapLB->SetItemText(nId, aName); + m_xBitmapLB->SelectItem( nId ); + + *m_pnBitmapListState |= ChangeType::MODIFIED; + } + else + { + std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/queryduplicatedialog.ui")); + std::unique_ptr xBox(xBuilder->weld_message_dialog("DuplicateNameDialog")); + xBox->run(); + } + } +} + +IMPL_LINK_NOARG(SvxBitmapTabPage, ClickDeleteHdl, SvxPresetListBox*, void) +{ + sal_uInt16 nId = m_xBitmapLB->GetSelectedItemId(); + size_t nPos = m_xBitmapLB->GetSelectItemPos(); + + if( nPos == VALUESET_ITEM_NOTFOUND ) + return; + + std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querydeletebitmapdialog.ui")); + std::unique_ptr xQueryBox(xBuilder->weld_message_dialog("AskDelBitmapDialog")); + + if (xQueryBox->run() == RET_YES) + { + m_pBitmapList->Remove( static_cast(nPos) ); + m_xBitmapLB->RemoveItem( nId ); + nId = m_xBitmapLB->GetItemId(0); + m_xBitmapLB->SelectItem( nId ); + + m_aCtlBitmapPreview.Invalidate(); + ModifyBitmapHdl(m_xBitmapLB.get()); + *m_pnBitmapListState |= ChangeType::MODIFIED; + } +} + +IMPL_LINK_NOARG( SvxBitmapTabPage, ModifyBitmapSizeHdl, weld::MetricSpinButton&, void ) +{ + m_bLogicalSize = false; + if (m_xTsbScale->get_state() != TRISTATE_TRUE && static_cast(m_xBitmapStyleLB->get_active()) != TILED) + { + sal_Int64 nWidthPercent = m_xBitmapWidth->denormalize(m_xBitmapWidth->get_value(FieldUnit::NONE)); + sal_Int64 nHeightPercent = m_xBitmapHeight->denormalize(m_xBitmapHeight->get_value(FieldUnit::NONE)); + if (nWidthPercent == 100 && nHeightPercent == 100) + m_xBitmapStyleLB->set_active(static_cast(CUSTOM)); + } + ModifyBitmapStyleHdl(*m_xBitmapStyleLB); + + m_aCtlBitmapPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + m_aCtlBitmapPreview.Invalidate(); +} + +IMPL_LINK_NOARG( SvxBitmapTabPage, ClickScaleHdl, weld::Button&, void ) +{ + if (m_xTsbScale->get_state() == TRISTATE_TRUE) + { + m_xBitmapWidth->set_digits( 0 ); + m_xBitmapWidth->set_unit(FieldUnit::PERCENT); + m_xBitmapWidth->set_value(100, FieldUnit::NONE); + m_xBitmapWidth->set_range(0, 100, FieldUnit::NONE); + + m_xBitmapHeight->set_digits( 0 ); + m_xBitmapHeight->set_unit(FieldUnit::PERCENT); + m_xBitmapHeight->set_value(100, FieldUnit::NONE); + m_xBitmapHeight->set_range(0, 100, FieldUnit::NONE); + } + else + { + m_xBitmapWidth->set_digits( 2 ); + m_xBitmapWidth->set_unit(meFieldUnit); + m_xBitmapWidth->set_value(100, FieldUnit::NONE); + m_xBitmapWidth->set_range(0, 999900, FieldUnit::NONE); + + m_xBitmapHeight->set_digits( 2 ); + m_xBitmapHeight->set_unit(meFieldUnit); + m_xBitmapHeight->set_value(100, FieldUnit::NONE); + m_xBitmapHeight->set_range(0, 999900, FieldUnit::NONE); + } + + ModifyBitmapStyleHdl( *m_xBitmapStyleLB ); +} + +IMPL_LINK_NOARG( SvxBitmapTabPage, ModifyBitmapStyleHdl, weld::ComboBox&, void ) +{ + BitmapStyle eStylePos = static_cast(m_xBitmapStyleLB->get_active()); + bool bIsStretched( eStylePos == STRETCHED ); + bool bIsTiled( eStylePos == TILED ); + + m_xSizeBox->set_sensitive( !bIsStretched ); + m_xPositionBox->set_sensitive( !bIsStretched ); + m_xPositionOffBox->set_sensitive( bIsTiled ); + m_xTileOffBox->set_sensitive( bIsTiled ); + + m_rXFSet.Put( XFillBmpTileItem( bIsTiled ) ); + m_rXFSet.Put( XFillBmpStretchItem( bIsStretched ) ); + + if(!bIsStretched) + { + Size aSetBitmapSize; + switch(eStylePos) + { + case CUSTOM: + case TILED: + { + if (m_xTsbScale->get_sensitive() && m_xTsbScale->get_state() == TRISTATE_TRUE) + { + aSetBitmapSize.setWidth(-m_xBitmapWidth->get_value(FieldUnit::NONE)); + aSetBitmapSize.setHeight(-m_xBitmapHeight->get_value(FieldUnit::NONE)); + } + else + { + aSetBitmapSize.setWidth( GetCoreValue( *m_xBitmapWidth, mePoolUnit ) ); + aSetBitmapSize.setHeight( GetCoreValue( *m_xBitmapHeight, mePoolUnit ) ); + } + } + break; + default: + break; + } + + m_rXFSet.Put( XFillBmpSizeXItem( aSetBitmapSize.Width() ) ); + m_rXFSet.Put( XFillBmpSizeYItem( aSetBitmapSize.Height() ) ); + } + + m_aCtlBitmapPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + m_aCtlBitmapPreview.Invalidate(); +} + +IMPL_LINK_NOARG(SvxBitmapTabPage, ModifyBitmapPositionHdl, weld::ComboBox&, void) +{ + if (m_xPositionLB->get_sensitive()) + m_rXFSet.Put( XFillBmpPosItem( static_cast< RectPoint >( m_xPositionLB->get_active() ) ) ); + + m_aCtlBitmapPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + m_aCtlBitmapPreview.Invalidate(); +} + +IMPL_LINK_NOARG(SvxBitmapTabPage, ModifyPositionOffsetHdl, weld::MetricSpinButton&, void) +{ + if (m_xPositionOffX->get_sensitive()) + m_rXFSet.Put( XFillBmpPosOffsetXItem( m_xPositionOffX->get_value(FieldUnit::PERCENT) ) ); + + if (m_xPositionOffY->get_sensitive()) + m_rXFSet.Put( XFillBmpPosOffsetYItem( m_xPositionOffY->get_value(FieldUnit::PERCENT) ) ); + + m_aCtlBitmapPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + m_aCtlBitmapPreview.Invalidate(); +} + +IMPL_LINK_NOARG(SvxBitmapTabPage, ModifyTileOffsetHdl, weld::MetricSpinButton&, void) +{ + sal_uInt16 nTileXOff = 0; + sal_uInt16 nTileYOff = 0; + + if(m_xTileOffLB->get_active() == static_cast(ROW)) + nTileXOff = m_xTileOffset->get_value(FieldUnit::PERCENT); + + if(m_xTileOffLB->get_active() == static_cast(COLUMN)) + nTileYOff = m_xTileOffset->get_value(FieldUnit::PERCENT); + + m_rXFSet.Put( XFillBmpTileOffsetXItem(nTileXOff) ); + m_rXFSet.Put( XFillBmpTileOffsetYItem(nTileYOff) ); + + m_aCtlBitmapPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + m_aCtlBitmapPreview.Invalidate(); +} + +IMPL_LINK_NOARG(SvxBitmapTabPage, ClickImportHdl, weld::Button&, void) +{ + weld::Window* pDialogFrameWeld = GetFrameWeld(); + + SvxOpenGraphicDialog aDlg(CuiResId(RID_SVXSTR_ADD_IMAGE), pDialogFrameWeld); + aDlg.EnableLink(false); + long nCount = m_pBitmapList->Count(); + + if( aDlg.Execute() ) + return; + + Graphic aGraphic; + + std::unique_ptr xWait(new weld::WaitObject(pDialogFrameWeld)); + ErrCode nError = aDlg.GetGraphic( aGraphic ); + xWait.reset(); + + if( !nError ) + { + OUString aDesc(CuiResId(RID_SVXSTR_DESC_EXT_BITMAP)); + + // convert file URL to UI name + OUString aName; + INetURLObject aURL( aDlg.GetPath() ); + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateSvxNameDialog( + pDialogFrameWeld, aURL.GetLastName().getToken(0, '.'), aDesc)); + nError = ErrCode(1); + + while( pDlg->Execute() == RET_OK ) + { + pDlg->GetName( aName ); + + bool bDifferent = true; + + for( long i = 0; i < nCount && bDifferent; i++ ) + if( aName == m_pBitmapList->GetBitmap( i )->GetName() ) + bDifferent = false; + + if( bDifferent ) { + nError = ERRCODE_NONE; + break; + } + + std::unique_ptr xBuilder(Application::CreateBuilder(pDialogFrameWeld, "cui/ui/queryduplicatedialog.ui")); + std::unique_ptr xBox(xBuilder->weld_message_dialog("DuplicateNameDialog")); + if (xBox->run() != RET_OK) + break; + } + + pDlg.disposeAndClear(); + + if( !nError ) + { + m_pBitmapList->Insert(std::make_unique(aGraphic, aName), nCount); + + sal_Int32 nId = m_xBitmapLB->GetItemId( nCount - 1 ); + BitmapEx aBitmap = m_pBitmapList->GetBitmapForPreview( nCount, m_xBitmapLB->GetIconSize() ); + + m_xBitmapLB->InsertItem( nId + 1, Image(aBitmap), aName ); + m_xBitmapLB->SelectItem( nId + 1 ); + *m_pnBitmapListState |= ChangeType::MODIFIED; + + ModifyBitmapHdl(m_xBitmapLB.get()); + } + } + else + { + // graphic couldn't be loaded + std::unique_ptr xBuilder(Application::CreateBuilder(pDialogFrameWeld, "cui/ui/querynoloadedfiledialog.ui")); + std::unique_ptr xBox(xBuilder->weld_message_dialog("NoLoadedFileDialog")); + xBox->run(); + } +} + +sal_Int32 SvxBitmapTabPage::SearchBitmapList(const GraphicObject& rGraphicObject) +{ + long nCount = m_pBitmapList->Count(); + sal_Int32 nPos = -1; + + for(long i = 0;i < nCount;i++) + { + if(rGraphicObject.GetUniqueID() == m_pBitmapList->GetBitmap( i )->GetGraphicObject().GetUniqueID()) + { + nPos = i; + break; + } + } + return nPos; +} + +sal_Int32 SvxBitmapTabPage::SearchBitmapList(const OUString& rBitmapName) +{ + long nCount = m_pBitmapList->Count(); + bool bValidBitmapName = true; + sal_Int32 nPos = -1; + + for(long i = 0;i < nCount && bValidBitmapName;i++) + { + if(rBitmapName == m_pBitmapList->GetBitmap( i )->GetName()) + { + nPos = i; + bValidBitmapName = false; + } + } + return nPos; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/tpcolor.cxx b/cui/source/tabpages/tpcolor.cxx new file mode 100644 index 000000000..5933985a9 --- /dev/null +++ b/cui/source/tabpages/tpcolor.cxx @@ -0,0 +1,747 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace com::sun::star; + +SvxColorTabPage::SvxColorTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "cui/ui/colorpage.ui", "ColorPage", &rInAttrs) + , rOutAttrs ( rInAttrs ) + // All the horrific pointers we store and should not + , pnColorListState( nullptr ) + , aXFillAttr( rInAttrs.GetPool() ) + , rXFSet( aXFillAttr.GetItemSet() ) + , eCM( ColorModel::RGB ) + , m_context(comphelper::getProcessComponentContext()) + , m_xValSetColorList(new SvxColorValueSet(m_xBuilder->weld_scrolled_window("colorsetwin"))) + , m_xValSetRecentList(new SvxColorValueSet(nullptr)) + , m_xSelectPalette(m_xBuilder->weld_combo_box("paletteselector")) + , m_xRbRGB(m_xBuilder->weld_radio_button("RGB")) + , m_xRbCMYK(m_xBuilder->weld_radio_button("CMYK")) + , m_xRGBcustom(m_xBuilder->weld_widget("rgbcustom")) + , m_xRGBpreset(m_xBuilder->weld_widget("rgbpreset")) + , m_xRpreset(m_xBuilder->weld_entry("R_preset")) + , m_xGpreset(m_xBuilder->weld_entry("G_preset")) + , m_xBpreset(m_xBuilder->weld_entry("B_preset")) + , m_xRcustom(m_xBuilder->weld_spin_button("R_custom")) + , m_xGcustom(m_xBuilder->weld_spin_button("G_custom")) + , m_xBcustom(m_xBuilder->weld_spin_button("B_custom")) + , m_xHexpreset(new weld::HexColorControl(m_xBuilder->weld_entry("hex_preset"))) + , m_xHexcustom(new weld::HexColorControl(m_xBuilder->weld_entry("hex_custom"))) + , m_xCMYKcustom(m_xBuilder->weld_widget("cmykcustom")) + , m_xCMYKpreset(m_xBuilder->weld_widget("cmykpreset")) + , m_xCpreset(m_xBuilder->weld_entry("C_preset")) + , m_xYpreset(m_xBuilder->weld_entry("Y_preset")) + , m_xMpreset(m_xBuilder->weld_entry("M_preset")) + , m_xKpreset(m_xBuilder->weld_entry("K_preset")) + , m_xCcustom(m_xBuilder->weld_metric_spin_button("C_custom", FieldUnit::PERCENT)) + , m_xYcustom(m_xBuilder->weld_metric_spin_button("Y_custom", FieldUnit::PERCENT)) + , m_xMcustom(m_xBuilder->weld_metric_spin_button("M_custom", FieldUnit::PERCENT)) + , m_xKcustom(m_xBuilder->weld_metric_spin_button("K_custom", FieldUnit::PERCENT)) + , m_xBtnAdd(m_xBuilder->weld_button("add")) + , m_xBtnDelete(m_xBuilder->weld_button("delete")) + , m_xBtnWorkOn(m_xBuilder->weld_button("edit")) + , m_xCtlPreviewOld(new weld::CustomWeld(*m_xBuilder, "oldpreview", m_aCtlPreviewOld)) + , m_xCtlPreviewNew(new weld::CustomWeld(*m_xBuilder, "newpreview", m_aCtlPreviewNew)) + , m_xValSetColorListWin(new weld::CustomWeld(*m_xBuilder, "colorset", *m_xValSetColorList)) + , m_xValSetRecentListWin(new weld::CustomWeld(*m_xBuilder, "recentcolorset", *m_xValSetRecentList)) +{ + Size aSize(m_xBtnWorkOn->get_approximate_digit_width() * 25, + m_xBtnWorkOn->get_text_height() * 10); + m_xValSetColorList->set_size_request(aSize.Width(), aSize.Height()); + aSize = Size(m_xBtnWorkOn->get_approximate_digit_width() * 8, + m_xBtnWorkOn->get_text_height() * 3); + m_aCtlPreviewOld.set_size_request(aSize.Width(), aSize.Height()); + m_aCtlPreviewNew.set_size_request(aSize.Width(), aSize.Height()); + // this page needs ExchangeSupport + SetExchangeSupport(); + + // setting the output device + rXFSet.Put( XFillStyleItem(drawing::FillStyle_SOLID) ); + rXFSet.Put( XFillColorItem(OUString(), COL_BLACK) ); + m_aCtlPreviewOld.SetAttributes( aXFillAttr.GetItemSet() ); + m_aCtlPreviewNew.SetAttributes( aXFillAttr.GetItemSet() ); + + // set handler + m_xSelectPalette->connect_changed(LINK(this, SvxColorTabPage, SelectPaletteLBHdl)); + Link aValSelectLink = LINK(this, SvxColorTabPage, SelectValSetHdl_Impl); + m_xValSetColorList->SetSelectHdl(aValSelectLink); + m_xValSetRecentList->SetSelectHdl(aValSelectLink); + + Link aSpinLink = LINK(this, SvxColorTabPage, SpinValueHdl_Impl); + m_xRcustom->connect_value_changed(aSpinLink); + m_xGcustom->connect_value_changed(aSpinLink); + m_xBcustom->connect_value_changed(aSpinLink); + Link aEntryLink = LINK(this, SvxColorTabPage, ModifiedHdl_Impl); + m_xHexcustom->connect_changed(aEntryLink); + Link aMetricSpinLink = LINK(this, SvxColorTabPage, MetricSpinValueHdl_Impl); + m_xCcustom->connect_value_changed(aMetricSpinLink); + m_xYcustom->connect_value_changed(aMetricSpinLink); + m_xMcustom->connect_value_changed(aMetricSpinLink); + m_xKcustom->connect_value_changed(aMetricSpinLink); + + Link aLink2 = LINK( this, SvxColorTabPage, SelectColorModeHdl_Impl ); + m_xRbRGB->connect_toggled(aLink2); + m_xRbCMYK->connect_toggled(aLink2); + SetColorModel( eCM ); + ChangeColorModel(); + + m_xBtnAdd->connect_clicked( LINK( this, SvxColorTabPage, ClickAddHdl_Impl ) ); + m_xBtnWorkOn->connect_clicked( LINK( this, SvxColorTabPage, ClickWorkOnHdl_Impl ) ); + m_xBtnDelete->connect_clicked( LINK( this, SvxColorTabPage, ClickDeleteHdl_Impl ) ); + // disable modify buttons + // Color palettes can't be modified + m_xBtnDelete->set_sensitive(false); + m_xBtnDelete->set_tooltip_text( SvxResId(RID_SVXSTR_DELETEUSERCOLOR1) ); + + // disable preset color values + m_xRGBpreset->set_sensitive(false); + m_xCMYKpreset->set_sensitive(false); + + // ValueSet + m_xValSetColorList->SetStyle(m_xValSetColorList->GetStyle() | WB_ITEMBORDER); + m_xValSetColorList->Show(); + + m_xValSetRecentList->SetStyle(m_xValSetRecentList->GetStyle() | WB_ITEMBORDER); + m_xValSetRecentList->Show(); + + maPaletteManager.ReloadRecentColorSet(*m_xValSetRecentList); + aSize = m_xValSetRecentList->layoutAllVisible(maPaletteManager.GetRecentColorCount()); + m_xValSetRecentList->set_size_request(aSize.Width(), aSize.Height()); +} + +SvxColorTabPage::~SvxColorTabPage() +{ + m_xValSetRecentListWin.reset(); + m_xValSetRecentList.reset(); + m_xValSetColorListWin.reset(); + m_xValSetColorList.reset(); +} + +void SvxColorTabPage::ImpColorCountChanged() +{ + if (!pColorList.is()) + return; + m_xValSetColorList->SetColCount(SvxColorValueSet::getColumnCount()); + m_xValSetRecentList->SetColCount(SvxColorValueSet::getColumnCount()); +} + +void SvxColorTabPage::FillPaletteLB() +{ + m_xSelectPalette->clear(); + std::vector aPaletteList = maPaletteManager.GetPaletteList(); + for (auto const& palette : aPaletteList) + { + m_xSelectPalette->append_text(palette); + } + OUString aPaletteName( officecfg::Office::Common::UserColors::PaletteName::get() ); + m_xSelectPalette->set_active_text(aPaletteName); + if (m_xSelectPalette->get_active() != -1) + { + SelectPaletteLBHdl(*m_xSelectPalette); + } +} + +void SvxColorTabPage::Construct() +{ + if (pColorList.is()) + { + FillPaletteLB(); + ImpColorCountChanged(); + } +} + +void SvxColorTabPage::ActivatePage( const SfxItemSet& ) +{ + if( !pColorList.is() ) + return; + + const SfxPoolItem* pPoolItem = nullptr; + if( SfxItemState::SET == rOutAttrs.GetItemState( GetWhich( XATTR_FILLCOLOR ), true, &pPoolItem ) ) + { + SetColorModel( ColorModel::RGB ); + ChangeColorModel(); + + const Color aColor = static_cast(pPoolItem)->GetColorValue(); + ChangeColor( aColor ); + sal_Int32 nPos = FindInPalette( aColor ); + + if ( nPos != -1 ) + m_xValSetColorList->SelectItem(m_xValSetColorList->GetItemId(nPos)); + // else search in other palettes? + + } + + m_aCtlPreviewOld.SetAttributes(aXFillAttr.GetItemSet()); + m_aCtlPreviewOld.Invalidate(); + + SelectValSetHdl_Impl(m_xValSetColorList.get()); +} + +DeactivateRC SvxColorTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if( _pSet ) + FillItemSet( _pSet ); + + return DeactivateRC::LeavePage; +} + +bool SvxColorTabPage::FillItemSet( SfxItemSet* rSet ) +{ + Color aColor = m_xValSetColorList->GetItemColor( m_xValSetColorList->GetSelectedItemId() ); + OUString sColorName; + if ( aCurrentColor == aColor ) + sColorName = m_xValSetColorList->GetItemText( m_xValSetColorList->GetSelectedItemId() ); + else + sColorName = "#" + aCurrentColor.AsRGBHexString().toAsciiUpperCase(); + maPaletteManager.AddRecentColor( aCurrentColor, sColorName ); + rSet->Put( XFillColorItem( sColorName, aCurrentColor ) ); + rSet->Put( XFillStyleItem( drawing::FillStyle_SOLID ) ); + return true; +} + +void SvxColorTabPage::UpdateModified() +{ + bool bEnable = pColorList.is() && pColorList->Count(); + m_xBtnWorkOn->set_sensitive(bEnable); +} + +void SvxColorTabPage::Reset( const SfxItemSet* rSet ) +{ + SfxItemState nState = rSet->GetItemState( XATTR_FILLCOLOR ); + + Color aNewColor; + + if ( nState >= SfxItemState::DEFAULT ) + { + XFillColorItem aColorItem( rSet->Get( XATTR_FILLCOLOR ) ); + aPreviousColor = aColorItem.GetColorValue(); + aNewColor = aColorItem.GetColorValue(); + } + + // set color model + OUString aStr = GetUserData(); + eCM = static_cast(aStr.toInt32()); + SetColorModel( eCM ); + ChangeColorModel(); + + ChangeColor(aNewColor); + + UpdateModified(); +} + +std::unique_ptr SvxColorTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rOutAttrs) +{ + return std::make_unique(pPage, pController, *rOutAttrs); +} + +// is called when the content of the MtrFields is changed for color values +IMPL_LINK_NOARG(SvxColorTabPage, SpinValueHdl_Impl, weld::SpinButton&, void) +{ + // read current MtrFields, if cmyk, then k-value as transparency + aCurrentColor = Color(static_cast(PercentToColor_Impl(m_xRcustom->get_value())), + static_cast(PercentToColor_Impl(m_xGcustom->get_value())), + static_cast(PercentToColor_Impl(m_xBcustom->get_value()))); + UpdateColorValues(); + + rXFSet.Put( XFillColorItem( OUString(), aCurrentColor ) ); + m_aCtlPreviewNew.SetAttributes( aXFillAttr.GetItemSet() ); + + m_aCtlPreviewNew.Invalidate(); +} + +IMPL_LINK_NOARG(SvxColorTabPage, MetricSpinValueHdl_Impl, weld::MetricSpinButton&, void) +{ + // read current MtrFields, if cmyk, then k-value as transparency + aCurrentColor = Color(static_cast(PercentToColor_Impl(m_xKcustom->get_value(FieldUnit::NONE))), + static_cast(PercentToColor_Impl(m_xCcustom->get_value(FieldUnit::NONE))), + static_cast(PercentToColor_Impl(m_xYcustom->get_value(FieldUnit::NONE))), + static_cast(PercentToColor_Impl(m_xMcustom->get_value(FieldUnit::NONE)))); + ConvertColorValues (aCurrentColor, ColorModel::RGB); + + rXFSet.Put( XFillColorItem( OUString(), aCurrentColor ) ); + m_aCtlPreviewNew.SetAttributes( aXFillAttr.GetItemSet() ); + + m_aCtlPreviewNew.Invalidate(); +} + +IMPL_LINK_NOARG(SvxColorTabPage, ModifiedHdl_Impl, weld::Entry&, void) +{ + aCurrentColor = m_xHexcustom->GetColor(); + UpdateColorValues(); + + rXFSet.Put( XFillColorItem( OUString(), aCurrentColor ) ); + m_aCtlPreviewNew.SetAttributes( aXFillAttr.GetItemSet() ); + + m_aCtlPreviewNew.Invalidate(); +} + +IMPL_LINK_NOARG(SvxColorTabPage, ClickAddHdl_Impl, weld::Button&, void) +{ + OUString aNewName( SvxResId( RID_SVXSTR_COLOR ) ); + OUString aDesc( CuiResId( RID_SVXSTR_DESC_COLOR ) ); + OUString aName; + + long j = 1; + bool bValidColorName = false; + // check if name is already existing + while (!bValidColorName) + { + aName = aNewName + " " + OUString::number( j++ ); + bValidColorName = (FindInCustomColors(aName) == -1); + } + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateSvxNameDialog(GetFrameWeld(), aName, aDesc)); + sal_uInt16 nError = 1; + + while (pDlg->Execute() == RET_OK) + { + pDlg->GetName( aName ); + + bValidColorName = (FindInCustomColors(aName) == -1); + if (bValidColorName) + { + nError = 0; + break; + } + + std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/queryduplicatedialog.ui")); + std::unique_ptr xWarnBox(xBuilder->weld_message_dialog("DuplicateNameDialog")); + if (xWarnBox->run() != RET_OK) + break; + } + + pDlg.disposeAndClear(); + + if (!nError) + { + m_xSelectPalette->set_active(0); + SelectPaletteLBHdl(*m_xSelectPalette); + std::shared_ptr batch(comphelper::ConfigurationChanges::create(m_context)); + css::uno::Sequence< sal_Int32 > aCustomColorList(officecfg::Office::Common::UserColors::CustomColor::get()); + css::uno::Sequence< OUString > aCustomColorNameList(officecfg::Office::Common::UserColors::CustomColorName::get()); + sal_Int32 nSize = aCustomColorList.getLength(); + aCustomColorList.realloc( nSize + 1 ); + aCustomColorNameList.realloc( nSize + 1 ); + aCustomColorList[nSize] = sal_Int32(aCurrentColor); + aCustomColorNameList[nSize] = aName; + officecfg::Office::Common::UserColors::CustomColor::set(aCustomColorList, batch); + officecfg::Office::Common::UserColors::CustomColorName::set(aCustomColorNameList, batch); + batch->commit(); + sal_uInt16 nId = m_xValSetColorList->GetItemId(nSize - 1); + m_xValSetColorList->InsertItem( nId + 1 , aCurrentColor, aName ); + m_xValSetColorList->SelectItem( nId + 1 ); + m_xBtnDelete->set_sensitive(false); + m_xBtnDelete->set_tooltip_text( SvxResId(RID_SVXSTR_DELETEUSERCOLOR2) ); + ImpColorCountChanged(); + } + + UpdateModified(); +} + +IMPL_LINK_NOARG(SvxColorTabPage, ClickWorkOnHdl_Impl, weld::Button&, void) +{ + SvColorDialog aColorDlg; + + aColorDlg.SetColor (aCurrentColor); + aColorDlg.SetMode( svtools::ColorPickerMode::Modify ); + + if (aColorDlg.Execute(GetFrameWeld()) == RET_OK) + { + Color aPreviewColor = aColorDlg.GetColor(); + aCurrentColor = aPreviewColor; + UpdateColorValues( false ); + // fill ItemSet and pass it on to XOut + rXFSet.Put( XFillColorItem( OUString(), aPreviewColor ) ); + //m_aCtlPreviewOld.SetAttributes( aXFillAttr ); + m_aCtlPreviewNew.SetAttributes( aXFillAttr.GetItemSet() ); + + m_aCtlPreviewNew.Invalidate(); + } +} + +IMPL_LINK_NOARG(SvxColorTabPage, ClickDeleteHdl_Impl, weld::Button&, void) +{ + sal_uInt16 nId = m_xValSetColorList->GetSelectedItemId(); + size_t nPos = m_xValSetColorList->GetSelectItemPos(); + if (!(m_xSelectPalette->get_active() == 0 && nPos != VALUESET_ITEM_NOTFOUND) ) + return; + + std::shared_ptr batch(comphelper::ConfigurationChanges::create(m_context)); + css::uno::Sequence< sal_Int32 > aCustomColorList(officecfg::Office::Common::UserColors::CustomColor::get()); + css::uno::Sequence< OUString > aCustomColorNameList(officecfg::Office::Common::UserColors::CustomColorName::get()); + sal_Int32 nSize = aCustomColorList.getLength() - 1; + for(sal_Int32 nIndex = static_cast(nPos);nIndex < nSize;nIndex++) + { + aCustomColorList[nIndex] = aCustomColorList[nIndex+1]; + aCustomColorNameList[nIndex] = aCustomColorNameList[nIndex+1]; + } + aCustomColorList.realloc(nSize); + aCustomColorNameList.realloc(nSize); + officecfg::Office::Common::UserColors::CustomColor::set(aCustomColorList, batch); + officecfg::Office::Common::UserColors::CustomColorName::set(aCustomColorNameList, batch); + batch->commit(); + m_xValSetColorList->RemoveItem(nId); + if (m_xValSetColorList->GetItemCount() != 0) + { + nId = m_xValSetColorList->GetItemId(0); + m_xValSetColorList->SelectItem(nId); + SelectValSetHdl_Impl(m_xValSetColorList.get()); + } + else + { + m_xBtnDelete->set_sensitive(false); + m_xBtnDelete->set_tooltip_text( SvxResId(RID_SVXSTR_DELETEUSERCOLOR2) ); + } +} + +IMPL_LINK_NOARG(SvxColorTabPage, SelectPaletteLBHdl, weld::ComboBox&, void) +{ + m_xValSetColorList->Clear(); + sal_Int32 nPos = m_xSelectPalette->get_active(); + maPaletteManager.SetPalette( nPos ); + maPaletteManager.ReloadColorSet(*m_xValSetColorList); + + if(nPos != maPaletteManager.GetPaletteCount() - 1 && nPos != 0) + { + XColorListRef pList = XPropertyList::AsColorList( + XPropertyList::CreatePropertyListFromURL( + XPropertyListType::Color, maPaletteManager.GetSelectedPalettePath())); + pList->SetName(maPaletteManager.GetPaletteName()); + if(pList->Load()) + { + SfxOkDialogController* pController = GetDialogController(); + SvxAreaTabDialog* pArea = dynamic_cast(pController); + SvxLineTabDialog* pLine = dynamic_cast(pController); + pColorList = pList; + if( pArea ) + pArea->SetNewColorList(pList); + else if( pLine ) + pLine->SetNewColorList(pList); + else + SetColorList(pList); + *pnColorListState |= ChangeType::CHANGED; + *pnColorListState &= ~ChangeType::MODIFIED; + } + } + if (nPos != 0) + { + m_xBtnDelete->set_sensitive(false); + m_xBtnDelete->set_tooltip_text( SvxResId(RID_SVXSTR_DELETEUSERCOLOR1) ); + } + + m_xValSetColorList->Resize(); +} + +IMPL_LINK(SvxColorTabPage, SelectValSetHdl_Impl, ValueSet*, pValSet, void) +{ + sal_Int32 nPos = pValSet->GetSelectedItemId(); + if( nPos == 0 ) + return; + + Color aColor = pValSet->GetItemColor( nPos ); + + rXFSet.Put( XFillColorItem( OUString(), aColor ) ); + m_aCtlPreviewNew.SetAttributes( aXFillAttr.GetItemSet() ); + m_aCtlPreviewNew.Invalidate(); + ChangeColor(aColor, false); + + if (pValSet == m_xValSetColorList.get()) + { + m_xValSetRecentList->SetNoSelection(); + if (m_xSelectPalette->get_active() == 0 && m_xValSetColorList->GetSelectedItemId() != 0) + { + m_xBtnDelete->set_sensitive(true); + m_xBtnDelete->set_tooltip_text(""); + } + else + { + m_xBtnDelete->set_sensitive(false); + m_xBtnDelete->set_tooltip_text( SvxResId(RID_SVXSTR_DELETEUSERCOLOR1) ); + } + } + if (pValSet == m_xValSetRecentList.get()) + { + m_xValSetColorList->SetNoSelection(); + m_xBtnDelete->set_sensitive(false); + m_xBtnDelete->set_tooltip_text( SvxResId(RID_SVXSTR_DELETEUSERCOLOR2) ); + } +} + +void SvxColorTabPage::ConvertColorValues (Color& rColor, ColorModel eModell) +{ + switch (eModell) + { + case ColorModel::RGB: + { + CmykToRgb_Impl (rColor, static_cast(rColor.GetTransparency()) ); + rColor.SetTransparency (sal_uInt8(0)); + } + break; + + case ColorModel::CMYK: + { + sal_uInt16 nK; + RgbToCmyk_Impl (rColor, nK ); + rColor.SetTransparency (static_cast(nK)); + } + break; + } +} + +IMPL_LINK_NOARG(SvxColorTabPage, SelectColorModeHdl_Impl, weld::ToggleButton&, void) +{ + if (m_xRbRGB->get_active()) + eCM = ColorModel::RGB; + else if (m_xRbCMYK->get_active()) + eCM = ColorModel::CMYK; + ChangeColorModel(); + UpdateColorValues(); +} + +void SvxColorTabPage::ChangeColor(const Color &rNewColor, bool bUpdatePreset ) +{ + aPreviousColor = rNewColor; + aCurrentColor = rNewColor; + UpdateColorValues( bUpdatePreset ); + // fill ItemSet and pass it on to XOut + rXFSet.Put( XFillColorItem( OUString(), aCurrentColor ) ); + m_aCtlPreviewNew.SetAttributes(aXFillAttr.GetItemSet()); + m_aCtlPreviewNew.Invalidate(); +} + +void SvxColorTabPage::SetColorModel( ColorModel eModel ) +{ + if (eModel == ColorModel::RGB) + m_xRbRGB->set_active(true); + else if (eModel == ColorModel::CMYK) + m_xRbCMYK->set_active(true); +} + +void SvxColorTabPage::ChangeColorModel() +{ + switch( eCM ) + { + case ColorModel::RGB: + { + m_xRGBcustom->show(); + m_xRGBpreset->show(); + m_xCMYKcustom->hide(); + m_xCMYKpreset->hide(); + } + break; + + case ColorModel::CMYK: + { + m_xCMYKcustom->show(); + m_xCMYKpreset->show(); + m_xRGBcustom->hide(); + m_xRGBpreset->hide(); + } + break; + } +} + +void SvxColorTabPage::UpdateColorValues( bool bUpdatePreset ) +{ + if (eCM != ColorModel::RGB) + { + ConvertColorValues (aPreviousColor, eCM ); + ConvertColorValues (aCurrentColor, eCM); + + m_xCcustom->set_value( ColorToPercent_Impl( aCurrentColor.GetRed() ), FieldUnit::PERCENT ); + m_xMcustom->set_value( ColorToPercent_Impl( aCurrentColor.GetBlue() ), FieldUnit::PERCENT ); + m_xYcustom->set_value( ColorToPercent_Impl( aCurrentColor.GetGreen() ), FieldUnit::PERCENT ); + m_xKcustom->set_value( ColorToPercent_Impl( aCurrentColor.GetTransparency() ), FieldUnit::PERCENT ); + + if( bUpdatePreset ) + { + m_xCpreset->set_text(unicode::formatPercent(ColorToPercent_Impl(aPreviousColor.GetRed()), + Application::GetSettings().GetUILanguageTag())); + m_xMpreset->set_text(unicode::formatPercent(ColorToPercent_Impl(aPreviousColor.GetBlue()), + Application::GetSettings().GetUILanguageTag())); + m_xYpreset->set_text(unicode::formatPercent(ColorToPercent_Impl(aPreviousColor.GetGreen()), + Application::GetSettings().GetUILanguageTag())); + m_xKpreset->set_text(unicode::formatPercent(ColorToPercent_Impl(aPreviousColor.GetTransparency()), + Application::GetSettings().GetUILanguageTag())); + } + + ConvertColorValues (aPreviousColor, ColorModel::RGB); + ConvertColorValues (aCurrentColor, ColorModel::RGB); + } + else + { + m_xRcustom->set_value( ColorToPercent_Impl( aCurrentColor.GetRed() ) ); + m_xGcustom->set_value( ColorToPercent_Impl( aCurrentColor.GetGreen() ) ); + m_xBcustom->set_value( ColorToPercent_Impl( aCurrentColor.GetBlue() ) ); + m_xHexcustom->SetColor( aCurrentColor ); + + if( bUpdatePreset ) + { + m_xRpreset->set_text(OUString::number(ColorToPercent_Impl(aPreviousColor.GetRed()))); + m_xGpreset->set_text(OUString::number(ColorToPercent_Impl(aPreviousColor.GetGreen()))); + m_xBpreset->set_text(OUString::number(ColorToPercent_Impl(aPreviousColor.GetBlue()))); + m_xHexpreset->SetColor( aPreviousColor ); + } + } +} + +sal_Int32 SvxColorTabPage::FindInCustomColors(OUString const & aColorName) +{ + css::uno::Sequence< OUString > aCustomColorNameList(officecfg::Office::Common::UserColors::CustomColorName::get()); + long nCount = aCustomColorNameList.getLength(); + bool bValidColorName = true; + sal_Int32 nPos = -1; + + for(long i = 0;i < nCount && bValidColorName;i++) + { + if(aColorName == aCustomColorNameList[i]) + { + nPos = i; + bValidColorName = false; + } + } + return nPos; +} + +sal_Int32 SvxColorTabPage::FindInPalette( const Color& rColor ) +{ + return pColorList->GetIndexOfColor(rColor); +} + +// A RGB value is converted to a CMYK value - not in an ideal way as +// R is converted into C, G into M and B into Y. The K value is held in an +// extra variable. For further color models one should develop own +// classes which should contain the respective casts. + +void SvxColorTabPage::RgbToCmyk_Impl( Color& rColor, sal_uInt16& rK ) +{ + sal_uInt16 const nColor1 = 255 - rColor.GetRed(); + sal_uInt16 const nColor2 = 255 - rColor.GetGreen(); + sal_uInt16 const nColor3 = 255 - rColor.GetBlue(); + + rK = std::min( std::min( nColor1, nColor2 ), nColor3 ); + + rColor.SetRed( sal::static_int_cast< sal_uInt8 >( nColor1 - rK ) ); + rColor.SetGreen( sal::static_int_cast< sal_uInt8 >( nColor2 - rK ) ); + rColor.SetBlue( sal::static_int_cast< sal_uInt8 >( nColor3 - rK ) ); +} + + +// reverse case to RgbToCmyk_Impl (see above) + +void SvxColorTabPage::CmykToRgb_Impl( Color& rColor, const sal_uInt16 nK ) +{ + long lTemp; + + lTemp = 255 - ( rColor.GetRed() + nK ); + + if( lTemp < 0 ) + lTemp = 0; + rColor.SetRed( static_cast(lTemp) ); + + lTemp = 255 - ( rColor.GetGreen() + nK ); + + if( lTemp < 0 ) + lTemp = 0; + rColor.SetGreen( static_cast(lTemp) ); + + lTemp = 255 - ( rColor.GetBlue() + nK ); + + if( lTemp < 0 ) + lTemp = 0; + rColor.SetBlue( static_cast(lTemp) ); +} + + +sal_uInt16 SvxColorTabPage::ColorToPercent_Impl( sal_uInt16 nColor ) +{ + sal_uInt16 nValue = 0; + + switch (eCM) + { + case ColorModel::RGB : + nValue = nColor; + break; + + case ColorModel::CMYK: + nValue = static_cast( static_cast(nColor) * 100.0 / 255.0 + 0.5 ); + break; + } + + return nValue; +} + + +sal_uInt16 SvxColorTabPage::PercentToColor_Impl( sal_uInt16 nPercent ) +{ + sal_uInt16 nValue = 0; + + switch (eCM) + { + case ColorModel::RGB : + nValue = nPercent; + break; + + case ColorModel::CMYK: + nValue = static_cast( static_cast(nPercent) * 255.0 / 100.0 + 0.5 ); + break; + } + + return nValue; +} + + +void SvxColorTabPage::FillUserData() +{ + // the color model is saved in the Ini-file + SetUserData( OUString::number( static_cast(eCM) ) ); +} + + +void SvxColorTabPage::SetPropertyList( XPropertyListType t, const XPropertyListRef &xRef ) +{ + OSL_ASSERT( t == XPropertyListType::Color ); + pColorList = XColorListRef( static_cast(xRef.get() ) ); +} + +void SvxColorTabPage::SetColorList( const XColorListRef& pColList ) +{ + SetPropertyList( XPropertyListType::Color, XPropertyListRef( ( pColList.get() ) ) ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/tpgradnt.cxx b/cui/source/tabpages/tpgradnt.cxx new file mode 100644 index 000000000..628c042ee --- /dev/null +++ b/cui/source/tabpages/tpgradnt.cxx @@ -0,0 +1,630 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEFAULT_GRADIENTSTEP 64 + +using namespace com::sun::star; + +SvxGradientTabPage::SvxGradientTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "cui/ui/gradientpage.ui", "GradientPage", &rInAttrs) + , m_rOutAttrs(rInAttrs) + , m_pnGradientListState(nullptr) + , m_pnColorListState(nullptr) + , m_aXFillAttr(rInAttrs.GetPool()) + , m_rXFSet(m_aXFillAttr.GetItemSet()) + , m_xLbGradientType(m_xBuilder->weld_combo_box("gradienttypelb")) + , m_xFtCenter(m_xBuilder->weld_label("centerft")) + , m_xMtrCenterX(m_xBuilder->weld_metric_spin_button("centerxmtr", FieldUnit::PERCENT)) + , m_xMtrCenterY(m_xBuilder->weld_metric_spin_button("centerymtr", FieldUnit::PERCENT)) + , m_xFtAngle(m_xBuilder->weld_label("angleft")) + , m_xMtrAngle(m_xBuilder->weld_metric_spin_button("anglemtr", FieldUnit::DEGREE)) + , m_xSliderAngle(m_xBuilder->weld_scale("angleslider")) + , m_xMtrBorder(m_xBuilder->weld_metric_spin_button("bordermtr", FieldUnit::PERCENT)) + , m_xSliderBorder(m_xBuilder->weld_scale("borderslider")) + , m_xLbColorFrom(new ColorListBox(m_xBuilder->weld_menu_button("colorfromlb"), pController->getDialog())) + , m_xMtrColorFrom(m_xBuilder->weld_metric_spin_button("colorfrommtr", FieldUnit::PERCENT)) + , m_xLbColorTo(new ColorListBox(m_xBuilder->weld_menu_button("colortolb"), pController->getDialog())) + , m_xMtrColorTo(m_xBuilder->weld_metric_spin_button("colortomtr", FieldUnit::PERCENT)) + , m_xGradientLB(new SvxPresetListBox(m_xBuilder->weld_scrolled_window("gradientpresetlistwin"))) + , m_xMtrIncrement(m_xBuilder->weld_spin_button("incrementmtr")) + , m_xCbIncrement(m_xBuilder->weld_check_button("autoincrement")) + , m_xBtnAdd(m_xBuilder->weld_button("add")) + , m_xBtnModify(m_xBuilder->weld_button("modify")) + , m_xCtlPreview(new weld::CustomWeld(*m_xBuilder, "previewctl", m_aCtlPreview)) + , m_xGradientLBWin(new weld::CustomWeld(*m_xBuilder, "gradientpresetlist", *m_xGradientLB)) +{ + Size aSize = getDrawPreviewOptimalSize(m_aCtlPreview.GetDrawingArea()->get_ref_device()); + m_xGradientLB->set_size_request(aSize.Width(), aSize.Height()); + m_xCtlPreview->set_size_request(aSize.Width(), aSize.Height()); + // this page needs ExchangeSupport + SetExchangeSupport(); + + // as long as NOT supported by the item + + m_xMtrColorTo->set_value(100, FieldUnit::PERCENT); + m_xMtrColorFrom->set_value(100, FieldUnit::PERCENT); + + // setting the output device + m_rXFSet.Put( XFillStyleItem(drawing::FillStyle_GRADIENT) ); + m_rXFSet.Put( XFillGradientItem(OUString(), XGradient( COL_BLACK, COL_WHITE )) ); + m_aCtlPreview.SetAttributes(m_aXFillAttr.GetItemSet()); + + // set handler + m_xGradientLB->SetSelectHdl( LINK( this, SvxGradientTabPage, ChangeGradientHdl ) ); + m_xGradientLB->SetRenameHdl( LINK( this, SvxGradientTabPage, ClickRenameHdl_Impl ) ); + m_xGradientLB->SetDeleteHdl( LINK( this, SvxGradientTabPage, ClickDeleteHdl_Impl ) ); + m_xBtnAdd->connect_clicked(LINK(this, SvxGradientTabPage, ClickAddHdl_Impl)); + m_xBtnModify->connect_clicked(LINK(this, SvxGradientTabPage, ClickModifyHdl_Impl)); + + Link aLink = LINK( this, SvxGradientTabPage, ModifiedMetricHdl_Impl ); + Link aLink2 = LINK( this, SvxGradientTabPage, ModifiedListBoxHdl_Impl ); + m_xLbGradientType->connect_changed( aLink2 ); + m_xCbIncrement->connect_toggled(LINK(this, SvxGradientTabPage, ChangeAutoStepHdl_Impl)); + m_xMtrIncrement->connect_value_changed(LINK(this, SvxGradientTabPage, ModifiedEditHdl_Impl)); + m_xMtrCenterX->connect_value_changed( aLink ); + m_xMtrCenterY->connect_value_changed( aLink ); + m_xMtrAngle->connect_value_changed( aLink ); + m_xSliderAngle->connect_value_changed(LINK(this, SvxGradientTabPage, ModifiedSliderHdl_Impl)); + m_xMtrBorder->connect_value_changed( aLink ); + m_xSliderBorder->connect_value_changed(LINK(this, SvxGradientTabPage, ModifiedSliderHdl_Impl)); + m_xMtrColorFrom->connect_value_changed( aLink ); + Link aLink3 = LINK( this, SvxGradientTabPage, ModifiedColorListBoxHdl_Impl ); + m_xLbColorFrom->SetSelectHdl( aLink3 ); + m_xMtrColorTo->connect_value_changed( aLink ); + m_xLbColorTo->SetSelectHdl( aLink3 ); + + // #i76307# always paint the preview in LTR, because this is what the document does + m_aCtlPreview.EnableRTL(false); +} + +SvxGradientTabPage::~SvxGradientTabPage() +{ + m_xCtlPreview.reset(); + m_xGradientLBWin.reset(); + m_xGradientLB.reset(); + m_xLbColorTo.reset(); + m_xLbColorFrom.reset(); +} + +void SvxGradientTabPage::Construct() +{ + m_xGradientLB->FillPresetListBox( *m_pGradientList ); +} + +void SvxGradientTabPage::ActivatePage( const SfxItemSet& rSet ) +{ + if( !m_pColorList.is() ) + return; + + // ColorList + if( *m_pnColorListState & ChangeType::CHANGED || + *m_pnColorListState & ChangeType::MODIFIED ) + { + SvxAreaTabDialog* pArea = (*m_pnColorListState & ChangeType::CHANGED) ? + dynamic_cast(GetDialogController()) : nullptr; + if (pArea) + m_pColorList = pArea->GetNewColorList(); + + ModifiedHdl_Impl( this ); + } + + // determining (and possibly cutting) the name and + // displaying it in the GroupBox + OUString aString = CuiResId( RID_SVXSTR_TABLE ) + ": "; + INetURLObject aURL( m_pGradientList->GetPath() ); + + aURL.Append( m_pGradientList->GetName() ); + SAL_WARN_IF( aURL.GetProtocol() == INetProtocol::NotValid, "cui.tabpages", "invalid URL" ); + + if ( aURL.getBase().getLength() > 18 ) + { + aString += aURL.getBase().copy( 0, 15 ) + "..."; + } + else + aString += aURL.getBase(); + + sal_Int32 nPos = SearchGradientList( rSet.Get(XATTR_FILLGRADIENT).GetName() ); + if ( nPos != -1) + { + sal_uInt16 nId = m_xGradientLB->GetItemId( static_cast( nPos ) ); + m_xGradientLB->SelectItem( nId ); + } + // colors could have been deleted + ChangeGradientHdl_Impl(); +} + + +DeactivateRC SvxGradientTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if( _pSet ) + FillItemSet( _pSet ); + + return DeactivateRC::LeavePage; +} + +bool SvxGradientTabPage::FillItemSet( SfxItemSet* rSet ) +{ + std::unique_ptr pXGradient; + OUString aString; + size_t nPos = m_xGradientLB->IsNoSelection() ? VALUESET_ITEM_NOTFOUND : m_xGradientLB->GetSelectItemPos(); + if( nPos != VALUESET_ITEM_NOTFOUND ) + { + pXGradient.reset(new XGradient( m_pGradientList->GetGradient( static_cast(nPos) )->GetGradient() )); + aString = m_xGradientLB->GetItemText( m_xGradientLB->GetSelectedItemId() ); + rSet->Put( XFillGradientItem( aString, *pXGradient ) ); + } + else + // gradient was passed (unidentified) + { + pXGradient.reset(new XGradient( m_xLbColorFrom->GetSelectEntryColor(), + m_xLbColorTo->GetSelectEntryColor(), + static_cast(m_xLbGradientType->get_active()), + static_cast(m_xMtrAngle->get_value(FieldUnit::NONE) * 10), // should be changed in resource + static_cast(m_xMtrCenterX->get_value(FieldUnit::NONE)), + static_cast(m_xMtrCenterY->get_value(FieldUnit::NONE)), + static_cast(m_xMtrBorder->get_value(FieldUnit::NONE)), + static_cast(m_xMtrColorFrom->get_value(FieldUnit::NONE)), + static_cast(m_xMtrColorTo->get_value(FieldUnit::NONE)), + static_cast(m_xMtrIncrement->get_value()) )); + rSet->Put( XFillGradientItem( OUString(), *pXGradient ) ); + } + + sal_uInt16 nValue = 0; + if (!m_xCbIncrement->get_active()) + nValue = m_xMtrIncrement->get_value(); + + assert( pXGradient && "XGradient could not be created" ); + rSet->Put( XFillStyleItem( drawing::FillStyle_GRADIENT ) ); + rSet->Put( XGradientStepCountItem( nValue ) ); + return true; +} + +void SvxGradientTabPage::Reset( const SfxItemSet* ) +{ + m_xMtrIncrement->set_value(DEFAULT_GRADIENTSTEP); + ChangeGradientHdl_Impl(); + + // determine state of the buttons + if( m_pGradientList->Count() ) + m_xBtnModify->set_sensitive(true); + else + m_xBtnModify->set_sensitive(false); +} + +std::unique_ptr SvxGradientTabPage::Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rOutAttrs ) +{ + return std::make_unique(pPage, pController, *rOutAttrs); +} + +IMPL_LINK( SvxGradientTabPage, ModifiedListBoxHdl_Impl, weld::ComboBox&, rListBox, void ) +{ + ModifiedHdl_Impl(&rListBox); + // gradient params changed, it is no longer one of the presets + m_xGradientLB->SetNoSelection(); +} + +IMPL_LINK( SvxGradientTabPage, ModifiedColorListBoxHdl_Impl, ColorListBox&, rListBox, void ) +{ + ModifiedHdl_Impl(&rListBox); + m_xGradientLB->SetNoSelection(); +} + +IMPL_LINK( SvxGradientTabPage, ModifiedEditHdl_Impl, weld::SpinButton&, rBox, void ) +{ + ModifiedHdl_Impl(&rBox); + m_xGradientLB->SetNoSelection(); +} + +IMPL_LINK( SvxGradientTabPage, ModifiedMetricHdl_Impl, weld::MetricSpinButton&, rBox, void ) +{ + ModifiedHdl_Impl(&rBox); + m_xGradientLB->SetNoSelection(); +} + +IMPL_LINK( SvxGradientTabPage, ModifiedSliderHdl_Impl, weld::Scale&, rSlider, void ) +{ + ModifiedHdl_Impl(&rSlider); + m_xGradientLB->SetNoSelection(); +} + +IMPL_LINK_NOARG( SvxGradientTabPage, ChangeAutoStepHdl_Impl, weld::ToggleButton&, void ) +{ + if (m_xCbIncrement->get_active()) + { + m_xMtrIncrement->set_sensitive(false); + } + else + { + m_xMtrIncrement->set_sensitive(true); + } + ModifiedHdl_Impl(m_xMtrIncrement.get()); +} + +void SvxGradientTabPage::ModifiedHdl_Impl( void const * pControl ) +{ + if (pControl == m_xMtrBorder.get()) + m_xSliderBorder->set_value(m_xMtrBorder->get_value(FieldUnit::NONE)); + if (pControl == m_xSliderBorder.get()) + m_xMtrBorder->set_value(m_xSliderBorder->get_value(), FieldUnit::NONE); + if (pControl == m_xMtrAngle.get()) + m_xSliderAngle->set_value(m_xMtrAngle->get_value(FieldUnit::NONE)); + if (pControl == m_xSliderAngle.get()) + m_xMtrAngle->set_value(m_xSliderAngle->get_value(), FieldUnit::NONE); + + css::awt::GradientStyle eXGS = static_cast(m_xLbGradientType->get_active()); + + XGradient aXGradient( m_xLbColorFrom->GetSelectEntryColor(), + m_xLbColorTo->GetSelectEntryColor(), + eXGS, + static_cast(m_xMtrAngle->get_value(FieldUnit::NONE) * 10), // should be changed in resource + static_cast(m_xMtrCenterX->get_value(FieldUnit::NONE)), + static_cast(m_xMtrCenterY->get_value(FieldUnit::NONE)), + static_cast(m_xMtrBorder->get_value(FieldUnit::NONE)), + static_cast(m_xMtrColorFrom->get_value(FieldUnit::NONE)), + static_cast(m_xMtrColorTo->get_value(FieldUnit::NONE)), + static_cast(m_xMtrIncrement->get_value()) ); + + // enable/disable controls + if (pControl == m_xLbGradientType.get() || pControl == this) + SetControlState_Impl( eXGS ); + + sal_uInt16 nValue = 0; + if (!m_xCbIncrement->get_active()) + nValue = static_cast(m_xMtrIncrement->get_value()); + m_rXFSet.Put( XGradientStepCountItem( nValue ) ); + + // displaying in XOutDev + m_rXFSet.Put( XFillGradientItem( OUString(), aXGradient ) ); + m_aCtlPreview.SetAttributes(m_aXFillAttr.GetItemSet()); + m_aCtlPreview.Invalidate(); +} + +IMPL_LINK_NOARG(SvxGradientTabPage, ClickAddHdl_Impl, weld::Button&, void) +{ + OUString aNewName( SvxResId( RID_SVXSTR_GRADIENT ) ); + OUString aDesc( CuiResId( RID_SVXSTR_DESC_GRADIENT ) ); + OUString aName; + + long nCount = m_pGradientList->Count(); + long j = 1; + bool bValidGradientName = false; + + while( !bValidGradientName ) + { + aName = aNewName + " " + OUString::number( j++ ); + bValidGradientName = (SearchGradientList(aName) == -1); + } + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateSvxNameDialog(GetFrameWeld(), aName, aDesc)); + sal_uInt16 nError = 1; + + while (pDlg->Execute() == RET_OK) + { + pDlg->GetName( aName ); + + bValidGradientName = (SearchGradientList(aName) == -1); + + if (bValidGradientName) + { + nError = 0; + break; + } + + std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/queryduplicatedialog.ui")); + std::unique_ptr xWarnBox(xBuilder->weld_message_dialog("DuplicateNameDialog")); + if (xWarnBox->run() != RET_OK) + break; + } + pDlg.disposeAndClear(); + + if( !nError ) + { + XGradient aXGradient( m_xLbColorFrom->GetSelectEntryColor(), + m_xLbColorTo->GetSelectEntryColor(), + static_cast(m_xLbGradientType->get_active()), + static_cast(m_xMtrAngle->get_value(FieldUnit::NONE) * 10), // should be changed in resource + static_cast(m_xMtrCenterX->get_value(FieldUnit::NONE)), + static_cast(m_xMtrCenterY->get_value(FieldUnit::NONE)), + static_cast(m_xMtrBorder->get_value(FieldUnit::NONE)), + static_cast(m_xMtrColorFrom->get_value(FieldUnit::NONE)), + static_cast(m_xMtrColorTo->get_value(FieldUnit::NONE)), + static_cast(m_xMtrIncrement->get_value()) ); + + m_pGradientList->Insert(std::make_unique(aXGradient, aName), nCount); + + sal_Int32 nId = m_xGradientLB->GetItemId(nCount - 1); //calculate the last ID + BitmapEx aBitmap = m_pGradientList->GetBitmapForPreview( nCount, m_xGradientLB->GetIconSize() ); + m_xGradientLB->InsertItem( nId + 1, Image(aBitmap), aName ); + m_xGradientLB->SelectItem( nId + 1 ); + m_xGradientLB->Resize(); + + *m_pnGradientListState |= ChangeType::MODIFIED; + + ChangeGradientHdl_Impl(); + } + + // determine button state + if (m_pGradientList->Count()) + m_xBtnModify->set_sensitive(true); +} + + +IMPL_LINK_NOARG(SvxGradientTabPage, ClickModifyHdl_Impl, weld::Button&, void) +{ + sal_uInt16 nId = m_xGradientLB->GetSelectedItemId(); + size_t nPos = m_xGradientLB->GetSelectItemPos(); + + if ( nPos == VALUESET_ITEM_NOTFOUND ) + return; + + OUString aName( m_pGradientList->GetGradient( static_cast(nPos) )->GetName() ); + + XGradient aXGradient( m_xLbColorFrom->GetSelectEntryColor(), + m_xLbColorTo->GetSelectEntryColor(), + static_cast(m_xLbGradientType->get_active()), + static_cast(m_xMtrAngle->get_value(FieldUnit::NONE) * 10), // should be changed in resource + static_cast(m_xMtrCenterX->get_value(FieldUnit::NONE)), + static_cast(m_xMtrCenterY->get_value(FieldUnit::NONE)), + static_cast(m_xMtrBorder->get_value(FieldUnit::NONE)), + static_cast(m_xMtrColorFrom->get_value(FieldUnit::NONE)), + static_cast(m_xMtrColorTo->get_value(FieldUnit::NONE)), + static_cast(m_xMtrIncrement->get_value()) ); + + m_pGradientList->Replace(std::make_unique(aXGradient, aName), nPos); + + BitmapEx aBitmap = m_pGradientList->GetBitmapForPreview( static_cast(nPos), m_xGradientLB->GetIconSize() ); + m_xGradientLB->RemoveItem( nId ); + m_xGradientLB->InsertItem( nId, Image(aBitmap), aName, static_cast(nPos) ); + m_xGradientLB->SelectItem( nId ); + + *m_pnGradientListState |= ChangeType::MODIFIED; +} + +IMPL_LINK_NOARG(SvxGradientTabPage, ClickDeleteHdl_Impl, SvxPresetListBox*, void) +{ + sal_uInt16 nId = m_xGradientLB->GetSelectedItemId(); + size_t nPos = m_xGradientLB->GetSelectItemPos(); + + if( nPos != VALUESET_ITEM_NOTFOUND ) + { + std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querydeletegradientdialog.ui")); + std::unique_ptr xQueryBox(xBuilder->weld_message_dialog("AskDelGradientDialog")); + if (xQueryBox->run() == RET_YES) + { + m_pGradientList->Remove(nPos); + m_xGradientLB->RemoveItem( nId ); + nId = m_xGradientLB->GetItemId( 0 ); + m_xGradientLB->SelectItem( nId ); + m_xGradientLB->Resize(); + + m_aCtlPreview.Invalidate(); + + ChangeGradientHdl_Impl(); + + *m_pnGradientListState |= ChangeType::MODIFIED; + } + } + // determine button state + if( !m_pGradientList->Count() ) + m_xBtnModify->set_sensitive(false); +} + +IMPL_LINK_NOARG(SvxGradientTabPage, ClickRenameHdl_Impl, SvxPresetListBox*, void) +{ + sal_uInt16 nId = m_xGradientLB->GetSelectedItemId(); + size_t nPos = m_xGradientLB->GetSelectItemPos(); + + if ( nPos == VALUESET_ITEM_NOTFOUND ) + return; + + OUString aDesc( CuiResId( RID_SVXSTR_DESC_GRADIENT ) ); + OUString aName( m_pGradientList->GetGradient( nPos )->GetName() ); + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateSvxNameDialog(GetFrameWeld(), aName, aDesc)); + + bool bLoop = true; + while( bLoop && pDlg->Execute() == RET_OK ) + { + pDlg->GetName( aName ); + sal_Int32 nGradientPos = SearchGradientList(aName); + bool bValidGradientName = (nGradientPos == static_cast(nPos) ) || (nGradientPos == -1); + + if( bValidGradientName ) + { + bLoop = false; + m_pGradientList->GetGradient(nPos)->SetName(aName); + + m_xGradientLB->SetItemText( nId, aName ); + m_xGradientLB->SelectItem( nId ); + + *m_pnGradientListState |= ChangeType::MODIFIED; + } + else + { + std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/queryduplicatedialog.ui")); + std::unique_ptr xBox(xBuilder->weld_message_dialog("DuplicateNameDialog")); + xBox->run(); + } + } +} + +IMPL_LINK_NOARG(SvxGradientTabPage, ChangeGradientHdl, ValueSet*, void) +{ + ChangeGradientHdl_Impl(); +} + +void SvxGradientTabPage::ChangeGradientHdl_Impl() +{ + std::unique_ptr pGradient; + size_t nPos = m_xGradientLB->GetSelectItemPos(); + + if( nPos != VALUESET_ITEM_NOTFOUND ) + pGradient.reset(new XGradient( m_pGradientList->GetGradient( static_cast( nPos ) )->GetGradient() )); + else + { + const SfxPoolItem* pPoolItem = nullptr; + if( SfxItemState::SET == m_rOutAttrs.GetItemState( GetWhich( XATTR_FILLSTYLE ), true, &pPoolItem ) ) + { + if( ( drawing::FillStyle_GRADIENT == static_cast( pPoolItem )->GetValue() ) && + ( SfxItemState::SET == m_rOutAttrs.GetItemState( GetWhich( XATTR_FILLGRADIENT ), true, &pPoolItem ) ) ) + { + pGradient.reset(new XGradient( static_cast( pPoolItem )->GetGradientValue() )); + } + } + if( !pGradient ) + { + sal_uInt16 nPosition = m_xGradientLB->GetItemId(0); + m_xGradientLB->SelectItem( nPosition ); + if( nPosition != 0 ) + pGradient.reset(new XGradient( m_pGradientList->GetGradient( 0 )->GetGradient() )); + } + } + + if( !pGradient ) + return; + + css::awt::GradientStyle eXGS = pGradient->GetGradientStyle(); + sal_uInt16 nValue = pGradient->GetSteps(); + if( nValue == 0 ) + { + m_xCbIncrement->set_state(TRISTATE_TRUE); + m_xMtrIncrement->set_sensitive(false); + } + else + { + m_xCbIncrement->set_state(TRISTATE_FALSE); + m_xMtrIncrement->set_sensitive(true); + m_xMtrIncrement->set_value( nValue ); + } + m_xLbGradientType->set_active( + sal::static_int_cast< sal_Int32 >( eXGS ) ); + // if the entry is not in the listbox, + // colors are added temporarily + m_xLbColorFrom->SetNoSelection(); + m_xLbColorFrom->SelectEntry( pGradient->GetStartColor() ); + + m_xLbColorTo->SetNoSelection(); + m_xLbColorTo->SelectEntry( pGradient->GetEndColor() ); + + m_xMtrAngle->set_value(pGradient->GetAngle() / 10, FieldUnit::NONE); // should be changed in resource + m_xSliderAngle->set_value(pGradient->GetAngle() / 10); + m_xMtrBorder->set_value(pGradient->GetBorder(), FieldUnit::NONE); + m_xSliderBorder->set_value(pGradient->GetBorder()); + m_xMtrCenterX->set_value(pGradient->GetXOffset(), FieldUnit::NONE); + m_xMtrCenterY->set_value(pGradient->GetYOffset(), FieldUnit::NONE); + m_xMtrColorFrom->set_value(pGradient->GetStartIntens(), FieldUnit::NONE); + m_xMtrColorTo->set_value(pGradient->GetEndIntens(), FieldUnit::NONE); + + // disable/enable controls + SetControlState_Impl( eXGS ); + + // fill ItemSet and pass it on to aCtlPreview + m_rXFSet.Put( XFillGradientItem( OUString(), *pGradient ) ); + m_rXFSet.Put( XGradientStepCountItem( nValue ) ); + m_aCtlPreview.SetAttributes(m_aXFillAttr.GetItemSet()); + + m_aCtlPreview.Invalidate(); +} + +void SvxGradientTabPage::SetControlState_Impl( css::awt::GradientStyle eXGS ) +{ + switch( eXGS ) + { + case css::awt::GradientStyle_LINEAR: + case css::awt::GradientStyle_AXIAL: + m_xFtCenter->set_sensitive(false); + m_xMtrCenterX->set_sensitive(false); + m_xMtrCenterY->set_sensitive(false); + m_xFtAngle->set_sensitive(true); + m_xMtrAngle->set_sensitive(true); + m_xSliderAngle->set_sensitive(true); + break; + + case css::awt::GradientStyle_RADIAL: + m_xFtCenter->set_sensitive(true); + m_xMtrCenterX->set_sensitive(true); + m_xMtrCenterY->set_sensitive(true); + m_xFtAngle->set_sensitive(false); + m_xMtrAngle->set_sensitive(false); + m_xSliderAngle->set_sensitive(false); + break; + + case css::awt::GradientStyle_ELLIPTICAL: + m_xFtCenter->set_sensitive(true); + m_xMtrCenterX->set_sensitive(true); + m_xMtrCenterY->set_sensitive(true); + m_xFtAngle->set_sensitive(true); + m_xMtrAngle->set_sensitive(true); + m_xSliderAngle->set_sensitive(true); + break; + + case css::awt::GradientStyle_SQUARE: + case css::awt::GradientStyle_RECT: + m_xFtCenter->set_sensitive(true); + m_xMtrCenterX->set_sensitive(true); + m_xMtrCenterY->set_sensitive(true); + m_xFtAngle->set_sensitive(true); + m_xMtrAngle->set_sensitive(true); + m_xSliderAngle->set_sensitive(true); + break; + default: + break; + } +} + +sal_Int32 SvxGradientTabPage::SearchGradientList(const OUString& rGradientName) +{ + long nCount = m_pGradientList->Count(); + bool bValidGradientName = true; + sal_Int32 nPos = -1; + + for(long i = 0;i < nCount && bValidGradientName;i++) + { + if(rGradientName == m_pGradientList->GetGradient( i )->GetName()) + { + nPos = i; + bValidGradientName = false; + } + } + return nPos; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/tphatch.cxx b/cui/source/tabpages/tphatch.cxx new file mode 100644 index 000000000..d1dbbc79a --- /dev/null +++ b/cui/source/tabpages/tphatch.cxx @@ -0,0 +1,558 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace com::sun::star; + +SvxHatchTabPage::SvxHatchTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "cui/ui/hatchpage.ui", "HatchPage", &rInAttrs) + , m_rOutAttrs(rInAttrs) + , m_pnHatchingListState(nullptr) + , m_pnColorListState(nullptr) + , m_aXFillAttr(rInAttrs.GetPool()) + , m_rXFSet(m_aXFillAttr.GetItemSet()) + , m_xMtrDistance(m_xBuilder->weld_metric_spin_button("distancemtr", FieldUnit::MM)) + , m_xMtrAngle(m_xBuilder->weld_metric_spin_button("anglemtr", FieldUnit::DEGREE)) + , m_xSliderAngle(m_xBuilder->weld_scale("angleslider")) + , m_xLbLineType(m_xBuilder->weld_combo_box("linetypelb")) + , m_xLbLineColor(new ColorListBox(m_xBuilder->weld_menu_button("linecolorlb"), pController->getDialog())) + , m_xCbBackgroundColor(m_xBuilder->weld_check_button("backgroundcolor")) + , m_xLbBackgroundColor(new ColorListBox(m_xBuilder->weld_menu_button("backgroundcolorlb"), pController->getDialog())) + , m_xHatchLB(new SvxPresetListBox(m_xBuilder->weld_scrolled_window("hatchpresetlistwin"))) + , m_xBtnAdd(m_xBuilder->weld_button("add")) + , m_xBtnModify(m_xBuilder->weld_button("modify")) + , m_xHatchLBWin(new weld::CustomWeld(*m_xBuilder, "hatchpresetlist", *m_xHatchLB)) + , m_xCtlPreview(new weld::CustomWeld(*m_xBuilder, "previewctl", m_aCtlPreview)) +{ + Size aSize = getDrawPreviewOptimalSize(m_aCtlPreview.GetDrawingArea()->get_ref_device()); + m_xHatchLBWin->set_size_request(aSize.Width(), aSize.Height()); + m_xCtlPreview->set_size_request(aSize.Width(), aSize.Height()); + + // this page needs ExchangeSupport + SetExchangeSupport(); + + // adjust metric + FieldUnit eFUnit = GetModuleFieldUnit( rInAttrs ); + + switch ( eFUnit ) + { + case FieldUnit::M: + case FieldUnit::KM: + eFUnit = FieldUnit::MM; + break; + default: ;//prevent warning + } + SetFieldUnit( *m_xMtrDistance, eFUnit ); + + // determine PoolUnit + SfxItemPool* pPool = m_rOutAttrs.GetPool(); + assert( pPool && "Where is the pool?" ); + m_ePoolUnit = pPool->GetMetric( SID_ATTR_FILL_HATCH ); + + // setting the output device + m_rXFSet.Put( XFillStyleItem(drawing::FillStyle_HATCH) ); + m_rXFSet.Put( XFillHatchItem(OUString(), XHatch()) ); + m_aCtlPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + m_xHatchLB->SetSelectHdl( LINK( this, SvxHatchTabPage, ChangeHatchHdl ) ); + m_xHatchLB->SetRenameHdl( LINK( this, SvxHatchTabPage, ClickRenameHdl_Impl ) ); + m_xHatchLB->SetDeleteHdl( LINK( this, SvxHatchTabPage, ClickDeleteHdl_Impl ) ); + + Link aLink = LINK( this, SvxHatchTabPage, ModifiedEditHdl_Impl ); + Link aLink2 = LINK( this, SvxHatchTabPage, ModifiedListBoxHdl_Impl ); + m_xMtrDistance->connect_value_changed( aLink ); + m_xMtrAngle->connect_value_changed( aLink ); + m_xSliderAngle->connect_value_changed(LINK(this, SvxHatchTabPage, ModifiedSliderHdl_Impl)); + m_xLbLineType->connect_changed( aLink2 ); + Link aLink3 = LINK( this, SvxHatchTabPage, ModifiedColorListBoxHdl_Impl ); + m_xLbLineColor->SetSelectHdl( aLink3 ); + m_xCbBackgroundColor->connect_toggled( LINK( this, SvxHatchTabPage, ToggleHatchBackgroundColor_Impl ) ); + m_xLbBackgroundColor->SetSelectHdl( LINK( this, SvxHatchTabPage, ModifiedBackgroundHdl_Impl ) ); + + m_xBtnAdd->connect_clicked( LINK( this, SvxHatchTabPage, ClickAddHdl_Impl ) ); + m_xBtnModify->connect_clicked( LINK( this, SvxHatchTabPage, ClickModifyHdl_Impl ) ); + + m_aCtlPreview.SetDrawMode(Application::GetSettings().GetStyleSettings().GetHighContrastMode() ? OUTPUT_DRAWMODE_CONTRAST : OUTPUT_DRAWMODE_COLOR); +} + +SvxHatchTabPage::~SvxHatchTabPage() +{ + m_xCtlPreview.reset(); + m_xHatchLBWin.reset(); + m_xHatchLB.reset(); + m_xLbBackgroundColor.reset(); + m_xLbLineColor.reset(); +} + +void SvxHatchTabPage::Construct() +{ + m_xHatchLB->FillPresetListBox(*m_pHatchingList); +} + +void SvxHatchTabPage::ActivatePage( const SfxItemSet& rSet ) +{ + if( m_pColorList.is() ) + { + // ColorList + if( *m_pnColorListState & ChangeType::CHANGED || + *m_pnColorListState & ChangeType::MODIFIED ) + { + SvxAreaTabDialog* pArea = (*m_pnColorListState & ChangeType::CHANGED) ? + dynamic_cast(GetDialogController()) : nullptr; + if (pArea) + m_pColorList = pArea->GetNewColorList(); + + ModifiedHdl_Impl( this ); + } + + // determining (possibly cutting) the name + // and displaying it in the GroupBox + OUString aString = CuiResId( RID_SVXSTR_TABLE ) + ": "; + INetURLObject aURL( m_pHatchingList->GetPath() ); + + aURL.Append( m_pHatchingList->GetName() ); + SAL_WARN_IF( aURL.GetProtocol() == INetProtocol::NotValid, "cui.tabpages", "invalid URL" ); + + if ( aURL.getBase().getLength() > 18 ) + { + aString += aURL.getBase().copy( 0, 15 ) + "..."; + } + else + aString += aURL.getBase(); + + sal_Int32 nPos = SearchHatchList( rSet.Get(XATTR_FILLHATCH).GetName() ); + if( nPos != -1) + { + sal_uInt16 nId = m_xHatchLB->GetItemId( static_cast( nPos ) ); + m_xHatchLB->SelectItem( nId ); + } + // colors could have been deleted + ChangeHatchHdl_Impl(); + } + + XFillBackgroundItem aBckItem( rSet.Get(XATTR_FILLBACKGROUND)); + m_rXFSet.Put( aBckItem ); + + if (aBckItem.GetValue()) + { + m_xCbBackgroundColor->set_state(TRISTATE_TRUE); + XFillColorItem aColorItem( rSet.Get(XATTR_FILLCOLOR) ); + Color aColor(aColorItem.GetColorValue()); + m_xLbBackgroundColor->SelectEntry(aColor); + m_xLbBackgroundColor->set_sensitive(true); + m_rXFSet.Put( aColorItem ); + } + else + { + m_xCbBackgroundColor->set_state(TRISTATE_FALSE); + m_xLbBackgroundColor->SelectEntry(COL_AUTO); + m_xLbBackgroundColor->set_sensitive(false); + } + + m_aCtlPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + m_aCtlPreview.Invalidate(); +} + +DeactivateRC SvxHatchTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if( _pSet ) + FillItemSet( _pSet ); + + return DeactivateRC::LeavePage; +} + +sal_Int32 SvxHatchTabPage::SearchHatchList(const OUString& rHatchName) +{ + long nCount = m_pHatchingList->Count(); + bool bValidHatchName = true; + sal_Int32 nPos = -1; + + for(long i = 0;i < nCount && bValidHatchName;i++) + { + if(rHatchName == m_pHatchingList->GetHatch( i )->GetName()) + { + nPos = i; + bValidHatchName = false; + } + } + return nPos; +} + +bool SvxHatchTabPage::FillItemSet( SfxItemSet* rSet ) +{ + std::unique_ptr pXHatch; + OUString aString; + size_t nPos = m_xHatchLB->IsNoSelection() ? VALUESET_ITEM_NOTFOUND : m_xHatchLB->GetSelectItemPos(); + if( nPos != VALUESET_ITEM_NOTFOUND ) + { + pXHatch.reset(new XHatch( m_pHatchingList->GetHatch( static_cast(nPos) )->GetHatch() )); + aString = m_xHatchLB->GetItemText( m_xHatchLB->GetSelectedItemId() ); + } + // unidentified hatch has been passed + else + { + pXHatch.reset(new XHatch( m_xLbLineColor->GetSelectEntryColor(), + static_cast(m_xLbLineType->get_active()), + GetCoreValue( *m_xMtrDistance, m_ePoolUnit ), + static_cast(m_xMtrAngle->get_value(FieldUnit::NONE) * 10) )); + } + assert( pXHatch && "XHatch couldn't be created" ); + rSet->Put( XFillStyleItem( drawing::FillStyle_HATCH ) ); + rSet->Put( XFillHatchItem( aString, *pXHatch ) ); + rSet->Put( XFillBackgroundItem( m_xCbBackgroundColor->get_active() ) ); + if (m_xCbBackgroundColor->get_active()) + { + NamedColor aColor = m_xLbBackgroundColor->GetSelectedEntry(); + rSet->Put(XFillColorItem(aColor.second, aColor.first)); + } + return true; +} + +void SvxHatchTabPage::Reset( const SfxItemSet* rSet ) +{ + ChangeHatchHdl_Impl(); + + XFillColorItem aColItem( rSet->Get(XATTR_FILLCOLOR) ); + m_xLbBackgroundColor->SelectEntry(aColItem.GetColorValue()); + m_rXFSet.Put( aColItem ); + + XFillBackgroundItem aBckItem( rSet->Get(XATTR_FILLBACKGROUND) ); + if(aBckItem.GetValue()) + m_xCbBackgroundColor->set_state(TRISTATE_TRUE); + else + m_xCbBackgroundColor->set_state(TRISTATE_FALSE); + m_rXFSet.Put( aBckItem ); + + m_aCtlPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + m_aCtlPreview.Invalidate(); +} + +std::unique_ptr SvxHatchTabPage::Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rSet ) +{ + return std::make_unique(pPage, pController, *rSet); +} + +IMPL_LINK( SvxHatchTabPage, ModifiedListBoxHdl_Impl, weld::ComboBox&, rListBox, void ) +{ + ModifiedHdl_Impl(&rListBox); + // hatch params have changed, it is no longer one of the presets + m_xHatchLB->SetNoSelection(); +} + +IMPL_LINK( SvxHatchTabPage, ModifiedColorListBoxHdl_Impl, ColorListBox&, rListBox, void ) +{ + ModifiedHdl_Impl(&rListBox); + m_xHatchLB->SetNoSelection(); +} + +IMPL_LINK_NOARG( SvxHatchTabPage, ToggleHatchBackgroundColor_Impl, weld::ToggleButton&, void ) +{ + if (m_xCbBackgroundColor->get_active()) + m_xLbBackgroundColor->set_sensitive(true); + else + m_xLbBackgroundColor->set_sensitive(false); + m_rXFSet.Put( XFillBackgroundItem( m_xCbBackgroundColor->get_active() ) ); + ModifiedBackgroundHdl_Impl(*m_xLbBackgroundColor); +} + +IMPL_LINK_NOARG( SvxHatchTabPage, ModifiedBackgroundHdl_Impl, ColorListBox&, void ) +{ + Color aColor(COL_TRANSPARENT); + if (m_xCbBackgroundColor->get_active()) + { + aColor = m_xLbBackgroundColor->GetSelectEntryColor(); + m_aCtlPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + m_aCtlPreview.Invalidate(); + } + m_rXFSet.Put(XFillColorItem( OUString(), aColor )); + + m_aCtlPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + m_aCtlPreview.Invalidate(); +} + +IMPL_LINK( SvxHatchTabPage, ModifiedEditHdl_Impl, weld::MetricSpinButton&, rEdit, void ) +{ + ModifiedHdl_Impl(&rEdit); + m_xHatchLB->SetNoSelection(); +} + +IMPL_LINK( SvxHatchTabPage, ModifiedSliderHdl_Impl, weld::Scale&, rSlider, void ) +{ + ModifiedHdl_Impl(&rSlider); + m_xHatchLB->SetNoSelection(); +} + +void SvxHatchTabPage::ModifiedHdl_Impl( void const * p ) +{ + if (p == m_xMtrAngle.get()) + m_xSliderAngle->set_value(m_xMtrAngle->get_value(FieldUnit::NONE)); + + if (p == m_xSliderAngle.get()) + m_xMtrAngle->set_value(m_xSliderAngle->get_value(), FieldUnit::NONE); + + XHatch aXHatch( m_xLbLineColor->GetSelectEntryColor(), + static_cast(m_xLbLineType->get_active()), + GetCoreValue( *m_xMtrDistance, m_ePoolUnit ), + static_cast(m_xMtrAngle->get_value(FieldUnit::NONE) * 10) ); + + m_rXFSet.Put( XFillHatchItem( OUString(), aXHatch ) ); + + m_aCtlPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + m_aCtlPreview.Invalidate(); +} + +IMPL_LINK_NOARG(SvxHatchTabPage, ChangeHatchHdl, ValueSet*, void) +{ + ChangeHatchHdl_Impl(); +} + +void SvxHatchTabPage::ChangeHatchHdl_Impl() +{ + std::unique_ptr pHatch; + size_t nPos = m_xHatchLB->GetSelectItemPos(); + + if( nPos != VALUESET_ITEM_NOTFOUND ) + pHatch.reset(new XHatch( m_pHatchingList->GetHatch( static_cast(nPos) )->GetHatch() )); + else + { + const SfxPoolItem* pPoolItem = nullptr; + if( SfxItemState::SET == m_rOutAttrs.GetItemState( GetWhich( XATTR_FILLSTYLE ), true, &pPoolItem ) ) + { + if( ( drawing::FillStyle_HATCH == static_cast( pPoolItem )->GetValue() ) && + ( SfxItemState::SET == m_rOutAttrs.GetItemState( GetWhich( XATTR_FILLHATCH ), true, &pPoolItem ) ) ) + { + pHatch.reset(new XHatch( static_cast( pPoolItem )->GetHatchValue() )); + } + } + if( !pHatch ) + { + sal_uInt16 nPosition = m_xHatchLB->GetItemId( 0 ); + m_xHatchLB->SelectItem( nPosition ); + if( nPosition != 0 ) + pHatch.reset( new XHatch( m_pHatchingList->GetHatch( 0 )->GetHatch() ) ); + } + } + if( pHatch ) + { + m_xLbLineType->set_active( + sal::static_int_cast< sal_Int32 >( pHatch->GetHatchStyle() ) ); + m_xLbLineColor->SetNoSelection(); + m_xLbLineColor->SelectEntry( pHatch->GetColor() ); + SetMetricValue( *m_xMtrDistance, pHatch->GetDistance(), m_ePoolUnit ); + long nHatchAngle = pHatch->GetAngle() / 10; + m_xMtrAngle->set_value(nHatchAngle, FieldUnit::NONE); + m_xSliderAngle->set_value(nHatchAngle); + + // fill ItemSet and pass it on to m_aCtlPreview + m_rXFSet.Put( XFillHatchItem( OUString(), *pHatch ) ); + m_aCtlPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + + m_aCtlPreview.Invalidate(); + pHatch.reset(); + } + m_xMtrDistance->save_value(); + m_xMtrAngle->save_value(); + m_xLbLineType->save_value(); + m_xLbLineColor->SaveValue(); + m_xLbBackgroundColor->SaveValue(); +} + +IMPL_LINK_NOARG(SvxHatchTabPage, ClickAddHdl_Impl, weld::Button&, void) +{ + OUString aNewName( SvxResId( RID_SVXSTR_HATCH ) ); + OUString aDesc( CuiResId( RID_SVXSTR_DESC_HATCH ) ); + OUString aName; + + long nCount = m_pHatchingList->Count(); + long j = 1; + bool bValidHatchName = false; + + while( !bValidHatchName ) + { + aName = aNewName + " " + OUString::number( j++ ); + bValidHatchName = (SearchHatchList(aName) == -1); + } + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateSvxNameDialog(GetFrameWeld(), aName, aDesc)); + sal_uInt16 nError = 1; + + while( pDlg->Execute() == RET_OK ) + { + pDlg->GetName( aName ); + + bValidHatchName = (SearchHatchList(aName) == -1); + if( bValidHatchName ) + { + nError = 0; + break; + } + + std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/queryduplicatedialog.ui")); + std::unique_ptr xWarnBox(xBuilder->weld_message_dialog("DuplicateNameDialog")); + if (xWarnBox->run() != RET_OK) + break; + } + pDlg.disposeAndClear(); + + if( nError ) + return; + + XHatch aXHatch( m_xLbLineColor->GetSelectEntryColor(), + static_cast(m_xLbLineType->get_active()), + GetCoreValue( *m_xMtrDistance, m_ePoolUnit ), + static_cast(m_xMtrAngle->get_value(FieldUnit::NONE) * 10) ); + + m_pHatchingList->Insert(std::make_unique(aXHatch, aName), nCount); + + sal_Int32 nId = m_xHatchLB->GetItemId(nCount - 1); // calculate the last ID + BitmapEx aBitmap = m_pHatchingList->GetBitmapForPreview( nCount, m_xHatchLB->GetIconSize() ); + // Insert the new entry at the next ID + m_xHatchLB->InsertItem( nId + 1, Image(aBitmap), aName ); + m_xHatchLB->SelectItem( nId + 1 ); + m_xHatchLB->Resize(); + + *m_pnHatchingListState |= ChangeType::MODIFIED; + + ChangeHatchHdl_Impl(); +} + +IMPL_LINK_NOARG(SvxHatchTabPage, ClickModifyHdl_Impl, weld::Button&, void) +{ + sal_uInt16 nId = m_xHatchLB->GetSelectedItemId(); + size_t nPos = m_xHatchLB->GetSelectItemPos(); + + if( nPos == VALUESET_ITEM_NOTFOUND ) + return; + + OUString aName( m_pHatchingList->GetHatch( static_cast(nPos) )->GetName() ); + + XHatch aXHatch( m_xLbLineColor->GetSelectEntryColor(), + static_cast(m_xLbLineType->get_active()), + GetCoreValue( *m_xMtrDistance, m_ePoolUnit ), + static_cast(m_xMtrAngle->get_value(FieldUnit::NONE) * 10) ); + + m_pHatchingList->Replace(std::make_unique(aXHatch, aName), nPos); + + BitmapEx aBitmap = m_pHatchingList->GetBitmapForPreview( static_cast(nPos), m_xHatchLB->GetIconSize() ); + m_xHatchLB->RemoveItem( nId ); + m_xHatchLB->InsertItem( nId, Image(aBitmap), aName, static_cast(nPos) ); + m_xHatchLB->SelectItem( nId ); + + // save values for changes recognition (-> method) + m_xMtrDistance->save_value(); + m_xMtrAngle->save_value(); + m_xLbLineType->save_value(); + m_xLbLineColor->SaveValue(); + m_xLbBackgroundColor->SaveValue(); + + *m_pnHatchingListState |= ChangeType::MODIFIED; +} + +IMPL_LINK_NOARG(SvxHatchTabPage, ClickDeleteHdl_Impl, SvxPresetListBox*, void) +{ + sal_uInt16 nId = m_xHatchLB->GetSelectedItemId(); + size_t nPos = m_xHatchLB->GetSelectItemPos(); + + if( nPos == VALUESET_ITEM_NOTFOUND ) + return; + + std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querydeletehatchdialog.ui")); + std::unique_ptr xQueryBox(xBuilder->weld_message_dialog("AskDelHatchDialog")); + if (xQueryBox->run() != RET_YES) + return; + + m_pHatchingList->Remove(nPos); + m_xHatchLB->RemoveItem( nId ); + nId = m_xHatchLB->GetItemId(0); + m_xHatchLB->SelectItem( nId ); + m_xHatchLB->Resize(); + + m_aCtlPreview.Invalidate(); + + ChangeHatchHdl_Impl(); + + *m_pnHatchingListState |= ChangeType::MODIFIED; +} + +IMPL_LINK_NOARG(SvxHatchTabPage, ClickRenameHdl_Impl, SvxPresetListBox*, void ) +{ + sal_uInt16 nId = m_xHatchLB->GetSelectedItemId(); + size_t nPos = m_xHatchLB->GetSelectItemPos(); + + if( nPos == VALUESET_ITEM_NOTFOUND ) + return; + + OUString aDesc( CuiResId( RID_SVXSTR_DESC_HATCH ) ); + OUString aName( m_pHatchingList->GetHatch( nPos )->GetName() ); + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateSvxNameDialog(GetFrameWeld(), aName, aDesc)); + + bool bLoop = true; + while( bLoop && pDlg->Execute() == RET_OK ) + { + pDlg->GetName( aName ); + sal_Int32 nHatchPos = SearchHatchList( aName ); + bool bValidHatchName = (nHatchPos == static_cast(nPos) ) || (nHatchPos == -1); + + if(bValidHatchName) + { + bLoop = false; + m_pHatchingList->GetHatch(nPos)->SetName(aName); + + m_xHatchLB->SetItemText(nId, aName); + m_xHatchLB->SelectItem( nId ); + + *m_pnHatchingListState |= ChangeType::MODIFIED; + } + else + { + std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/queryduplicatedialog.ui")); + std::unique_ptr xBox(xBuilder->weld_message_dialog("DuplicateNameDialog")); + xBox->run(); + } + } + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/tpline.cxx b/cui/source/tabpages/tpline.cxx new file mode 100644 index 000000000..6079adcd5 --- /dev/null +++ b/cui/source/tabpages/tpline.cxx @@ -0,0 +1,1689 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_BMP_WIDTH 16 +#define MAX_BMP_HEIGHT 16 + +using namespace com::sun::star; + +// static ---------------------------------------------------------------- + +const sal_uInt16 SvxLineTabPage::pLineRanges[] = +{ + XATTR_LINETRANSPARENCE, + XATTR_LINETRANSPARENCE, + SID_ATTR_LINE_STYLE, + SID_ATTR_LINE_ENDCENTER, + 0 +}; + +SvxLineTabPage::SvxLineTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "cui/ui/linetabpage.ui", "LineTabPage", &rInAttrs) + , m_pSymbolList(nullptr) + , m_bNewSize(false) + , m_nSymbolType(SVX_SYMBOLTYPE_UNKNOWN) // unknown respectively unchanged + , m_pSymbolAttr(nullptr) + , m_bLastWidthModified(false) + , m_aSymbolLastSize(Size(0,0)) + , m_bSymbols(false) + , m_rOutAttrs(rInAttrs) + , m_bObjSelected(false) + , m_aXLineAttr(rInAttrs.GetPool()) + , m_rXLSet(m_aXLineAttr.GetItemSet()) + , m_pnLineEndListState(nullptr) + , m_pnDashListState(nullptr) + , m_pnColorListState(nullptr) + , m_nPageType(PageType::Area) + , m_nDlgType(0) + , m_pPosDashLb(nullptr) + , m_pPosLineEndLb(nullptr) + , m_xBoxColor(m_xBuilder->weld_widget("boxCOLOR")) + , m_xLbLineStyle(new SvxLineLB(m_xBuilder->weld_combo_box("LB_LINE_STYLE"))) + , m_xLbColor(new ColorListBox(m_xBuilder->weld_menu_button("LB_COLOR"), pController->getDialog())) + , m_xBoxWidth(m_xBuilder->weld_widget("boxWIDTH")) + , m_xMtrLineWidth(m_xBuilder->weld_metric_spin_button("MTR_FLD_LINE_WIDTH", FieldUnit::CM)) + , m_xBoxTransparency(m_xBuilder->weld_widget("boxTRANSPARENCY")) + , m_xMtrTransparent(m_xBuilder->weld_metric_spin_button("MTR_LINE_TRANSPARENT", FieldUnit::PERCENT)) + , m_xFlLineEnds(m_xBuilder->weld_widget("FL_LINE_ENDS")) + , m_xBoxArrowStyles(m_xBuilder->weld_widget("boxARROW_STYLES")) + , m_xLbStartStyle(new SvxLineEndLB(m_xBuilder->weld_combo_box("LB_START_STYLE"))) + , m_xBoxStart(m_xBuilder->weld_widget("boxSTART")) + , m_xMtrStartWidth(m_xBuilder->weld_metric_spin_button("MTR_FLD_START_WIDTH", FieldUnit::CM)) + , m_xTsbCenterStart(m_xBuilder->weld_check_button("TSB_CENTER_START")) + , m_xBoxEnd(m_xBuilder->weld_widget("boxEND")) + , m_xLbEndStyle(new SvxLineEndLB(m_xBuilder->weld_combo_box("LB_END_STYLE"))) + , m_xMtrEndWidth(m_xBuilder->weld_metric_spin_button("MTR_FLD_END_WIDTH", FieldUnit::CM)) + , m_xTsbCenterEnd(m_xBuilder->weld_check_button("TSB_CENTER_END")) + , m_xCbxSynchronize(m_xBuilder->weld_check_button("CBX_SYNCHRONIZE")) + , m_xCtlPreview(new weld::CustomWeld(*m_xBuilder, "CTL_PREVIEW", m_aCtlPreview)) + , m_xFLEdgeStyle(m_xBuilder->weld_widget("FL_EDGE_STYLE")) + , m_xGridEdgeCaps(m_xBuilder->weld_widget("gridEDGE_CAPS")) + , m_xLBEdgeStyle(m_xBuilder->weld_combo_box("LB_EDGE_STYLE")) + , m_xLBCapStyle(m_xBuilder->weld_combo_box("LB_CAP_STYLE")) // LineCaps + , m_xFlSymbol(m_xBuilder->weld_widget("FL_SYMBOL_FORMAT")) //#58425# Symbols on a line (e.g. StarChart) + , m_xGridIconSize(m_xBuilder->weld_widget("gridICON_SIZE")) + , m_xSymbolMB(m_xBuilder->weld_menu_button("MB_SYMBOL_BITMAP")) + , m_xSymbolWidthMF(m_xBuilder->weld_metric_spin_button("MF_SYMBOL_WIDTH", FieldUnit::CM)) + , m_xSymbolHeightMF(m_xBuilder->weld_metric_spin_button("MF_SYMBOL_HEIGHT", FieldUnit::CM)) + , m_xSymbolRatioCB(m_xBuilder->weld_check_button("CB_SYMBOL_RATIO")) +{ + // This Page requires ExchangeSupport + SetExchangeSupport(); + + // Metric set + FieldUnit eFUnit = GetModuleFieldUnit( rInAttrs ); + + switch ( eFUnit ) + { + case FieldUnit::M: + case FieldUnit::KM: + eFUnit = FieldUnit::MM; + [[fallthrough]]; // we now have mm + case FieldUnit::MM: + m_xMtrLineWidth->set_increments(50, 500, FieldUnit::NONE); + m_xMtrStartWidth->set_increments(50, 500, FieldUnit::NONE); + m_xMtrEndWidth->set_increments(50, 500, FieldUnit::NONE); + break; + + case FieldUnit::INCH: + m_xMtrLineWidth->set_increments(2, 20, FieldUnit::NONE); + m_xMtrStartWidth->set_increments(2, 20, FieldUnit::NONE); + m_xMtrEndWidth->set_increments(2, 20, FieldUnit::NONE); + break; + default: ;// prevent warning + } + SetFieldUnit( *m_xMtrLineWidth, eFUnit ); + SetFieldUnit( *m_xMtrStartWidth, eFUnit ); + SetFieldUnit( *m_xMtrEndWidth, eFUnit ); + + // determine PoolUnit + SfxItemPool* pPool = m_rOutAttrs.GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + m_ePoolUnit = pPool->GetMetric( SID_ATTR_LINE_WIDTH ); + + m_xLbLineStyle->connect_changed(LINK(this, SvxLineTabPage, ClickInvisibleHdl_Impl)); + m_xLbColor->SetSelectHdl( LINK( this, SvxLineTabPage, ChangePreviewListBoxHdl_Impl ) ); + m_xMtrLineWidth->connect_value_changed(LINK(this, SvxLineTabPage, ChangePreviewModifyHdl_Impl)); + m_xMtrTransparent->connect_value_changed(LINK( this, SvxLineTabPage, ChangeTransparentHdl_Impl)); + + m_xLbStartStyle->connect_changed(LINK(this, SvxLineTabPage, ChangeStartListBoxHdl_Impl)); + m_xLbEndStyle->connect_changed(LINK(this, SvxLineTabPage, ChangeEndListBoxHdl_Impl)); + m_xMtrStartWidth->connect_value_changed(LINK(this, SvxLineTabPage, ChangeStartModifyHdl_Impl)); + m_xMtrEndWidth->connect_value_changed(LINK( this, SvxLineTabPage, ChangeEndModifyHdl_Impl)); + m_xTsbCenterStart->connect_clicked(LINK(this, SvxLineTabPage, ChangeStartClickHdl_Impl)); + m_xTsbCenterEnd->connect_clicked(LINK(this, SvxLineTabPage, ChangeEndClickHdl_Impl)); + + Link aEdgeStyle = LINK(this, SvxLineTabPage, ChangeEdgeStyleHdl_Impl); + m_xLBEdgeStyle->connect_changed(aEdgeStyle); + + // LineCaps + Link aCapStyle = LINK(this, SvxLineTabPage, ChangeCapStyleHdl_Impl); + m_xLBCapStyle->connect_changed(aCapStyle); + + // Symbols on a line (eg star charts), MB-handler set + m_xSymbolMB->connect_selected(LINK(this, SvxLineTabPage, GraphicHdl_Impl)); + m_xSymbolMB->connect_toggled(LINK(this, SvxLineTabPage, MenuCreateHdl_Impl)); + m_xSymbolWidthMF->connect_value_changed(LINK(this, SvxLineTabPage, SizeHdl_Impl)); + m_xSymbolHeightMF->connect_value_changed(LINK(this, SvxLineTabPage, SizeHdl_Impl)); + m_xSymbolRatioCB->connect_toggled(LINK(this, SvxLineTabPage, RatioHdl_Impl)); + + m_xSymbolRatioCB->set_active(true); + ShowSymbolControls(false); + + m_nActLineWidth = -1; +} + +void SvxLineTabPage::ShowSymbolControls(bool bOn) +{ + // Symbols on a line (e.g. StarCharts), symbol-enable controls + + m_bSymbols=bOn; + m_xFlSymbol->set_visible(bOn); + m_aCtlPreview.ShowSymbol(bOn); +} + +SvxLineTabPage::~SvxLineTabPage() +{ + m_xCtlPreview.reset(); + m_xLbEndStyle.reset(); + m_xLbStartStyle.reset(); + m_xLbColor.reset(); + m_xLbLineStyle.reset(); + m_aGalleryBrushItems.clear(); + m_aSymbolBrushItems.clear(); +} + +void SvxLineTabPage::Construct() +{ + FillListboxes(); +} + +void SvxLineTabPage::FillListboxes() +{ + // Line styles + auto nOldSelect = m_xLbLineStyle->get_active(); + // aLbLineStyle.FillStyles(); + m_xLbLineStyle->Fill( m_pDashList ); + m_xLbLineStyle->set_active( nOldSelect ); + + // Line end style + OUString sNone( comphelper::LibreOfficeKit::isActive() ? SvxResId( RID_SVXSTR_INVISIBLE ) + : SvxResId( RID_SVXSTR_NONE ) ); + nOldSelect = m_xLbStartStyle->get_active(); + m_xLbStartStyle->clear(); + m_xLbStartStyle->append_text(sNone); + m_xLbStartStyle->Fill(m_pLineEndList); + m_xLbStartStyle->set_active(nOldSelect); + nOldSelect = m_xLbEndStyle->get_active(); + m_xLbEndStyle->clear(); + m_xLbEndStyle->append_text(sNone); + m_xLbEndStyle->Fill(m_pLineEndList, false); + m_xLbEndStyle->set_active(nOldSelect); +} + +void SvxLineTabPage::ActivatePage( const SfxItemSet& rSet ) +{ + const CntUInt16Item* pPageTypeItem = rSet.GetItem(SID_PAGE_TYPE, false); + if (pPageTypeItem) + SetPageType(static_cast(pPageTypeItem->GetValue())); + if( m_nDlgType == 0 && m_pDashList.is() ) + { + sal_Int32 nPos; + sal_Int32 nCount; + + // Dash list + if( ( *m_pnDashListState & ChangeType::MODIFIED ) || + ( *m_pnDashListState & ChangeType::CHANGED ) ) + { + if( *m_pnDashListState & ChangeType::CHANGED ) + m_pDashList = static_cast(GetDialogController() )->GetNewDashList(); + + *m_pnDashListState = ChangeType::NONE; + + // Style list + nPos = m_xLbLineStyle->get_active(); + + m_xLbLineStyle->clear(); + m_xLbLineStyle->append_text(SvxResId(RID_SVXSTR_INVISIBLE)); + m_xLbLineStyle->append_text(SvxResId(RID_SVXSTR_SOLID)); + m_xLbLineStyle->Fill(m_pDashList); + nCount = m_xLbLineStyle->get_count(); + + if ( nCount == 0 ) + ; // This case should never occur + else if( nCount <= nPos ) + m_xLbLineStyle->set_active(0); + else + m_xLbLineStyle->set_active(nPos); + } + + INetURLObject aDashURL( m_pDashList->GetPath() ); + + aDashURL.Append( m_pDashList->GetName() ); + DBG_ASSERT( aDashURL.GetProtocol() != INetProtocol::NotValid, "invalid URL" ); + // LineEnd list + if( ( *m_pnLineEndListState & ChangeType::MODIFIED ) || ( *m_pnLineEndListState & ChangeType::CHANGED ) ) + { + if( *m_pnLineEndListState & ChangeType::CHANGED ) + m_pLineEndList = static_cast(GetDialogController())->GetNewLineEndList(); + + *m_pnLineEndListState = ChangeType::NONE; + + nPos = m_xLbLineStyle->get_active(); + OUString sNone( comphelper::LibreOfficeKit::isActive() ? SvxResId( RID_SVXSTR_INVISIBLE ) + : SvxResId( RID_SVXSTR_NONE ) ); + + m_xLbStartStyle->clear(); + m_xLbStartStyle->append_text(sNone); + + m_xLbStartStyle->Fill( m_pLineEndList ); + nCount = m_xLbStartStyle->get_count(); + if( nCount == 0 ) + ; // This case should never occur + else if( nCount <= nPos ) + m_xLbStartStyle->set_active(0); + else + m_xLbStartStyle->set_active(nPos); + + m_xLbEndStyle->clear(); + m_xLbEndStyle->append_text(sNone); + + m_xLbEndStyle->Fill( m_pLineEndList, false ); + nCount = m_xLbEndStyle->get_count(); + + if( nCount == 0 ) + ; // This case should never occur + else if( nCount <= nPos ) + m_xLbEndStyle->set_active(0); + else + m_xLbEndStyle->set_active(nPos); + } + INetURLObject aLineURL( m_pLineEndList->GetPath() ); + + aLineURL.Append( m_pLineEndList->GetName() ); + DBG_ASSERT( aLineURL.GetProtocol() != INetProtocol::NotValid, "invalid URL" ); + // Evaluate if another TabPage set another fill type + if( m_xLbLineStyle->get_active() != 0 ) + { + if( m_nPageType == PageType::Hatch ) // 1 + { + m_xLbLineStyle->set_active(*m_pPosDashLb + 2); // +2 due to SOLID and INVISIBLE + ChangePreviewHdl_Impl( nullptr ); + } + if( m_nPageType == PageType::Bitmap ) + { + m_xLbStartStyle->set_active(*m_pPosLineEndLb + 1);// +1 due to SOLID + m_xLbEndStyle->set_active(*m_pPosLineEndLb + 1);// +1 due to SOLID + ChangePreviewHdl_Impl( nullptr ); + } + } + + // ColorList + if( *m_pnColorListState != ChangeType::NONE ) + { + ChangePreviewHdl_Impl( nullptr ); + } + + m_nPageType = PageType::Area; + } + // Page does not yet exist in the ctor, that's why we do it here! + + else if (m_nDlgType == 1101) // nNoArrowNoShadowDlg from chart2/source/controller/dialogs/dlg_ObjectProperties.cxx + { + m_xFlLineEnds->hide(); + m_xFLEdgeStyle->hide(); + } +} + + +DeactivateRC SvxLineTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if( m_nDlgType == 0 ) // Line dialog + { + m_nPageType = PageType::Gradient; // possibly for extensions + *m_pPosDashLb = m_xLbLineStyle->get_active() - 2;// First entry SOLID!!! + sal_Int32 nPos = m_xLbStartStyle->get_active(); + if (nPos != -1) + nPos--; + *m_pPosLineEndLb = nPos; + } + + if( _pSet ) + FillItemSet( _pSet ); + + return DeactivateRC::LeavePage; +} + + +bool SvxLineTabPage::FillItemSet( SfxItemSet* rAttrs ) +{ + const SfxPoolItem* pOld = nullptr; + sal_Int32 nPos; + bool bModified = false; + + // To prevent modifications to the list, we do not set other page's items. + if( m_nDlgType != 0 || m_nPageType != PageType::Hatch ) + { + nPos = m_xLbLineStyle->get_active(); + if( nPos != -1 && + m_xLbLineStyle->get_value_changed_from_saved() ) + { + std::unique_ptr pStyleItem; + + if( nPos == 0 ) + pStyleItem.reset(new XLineStyleItem( drawing::LineStyle_NONE )); + else if( nPos == 1 ) + pStyleItem.reset(new XLineStyleItem( drawing::LineStyle_SOLID )); + else + { + pStyleItem.reset(new XLineStyleItem( drawing::LineStyle_DASH )); + + // For added security + if( m_pDashList->Count() > static_cast( nPos - 2 ) ) + { + XLineDashItem aDashItem( m_xLbLineStyle->get_active_text(), + m_pDashList->GetDash( nPos - 2 )->GetDash() ); + pOld = GetOldItem( *rAttrs, XATTR_LINEDASH ); + if ( !pOld || !( *static_cast(pOld) == aDashItem ) ) + { + rAttrs->Put( aDashItem ); + bModified = true; + } + } + } + pOld = GetOldItem( *rAttrs, XATTR_LINESTYLE ); + if ( !pOld || !( *static_cast(pOld) == *pStyleItem ) ) + { + rAttrs->Put( *pStyleItem ); + bModified = true; + } + } + } + // Line width + // GetSavedValue() returns OUString! + if( m_xMtrLineWidth->get_value_changed_from_saved() ) + { + XLineWidthItem aItem( GetCoreValue( *m_xMtrLineWidth, m_ePoolUnit ) ); + pOld = GetOldItem( *rAttrs, XATTR_LINEWIDTH ); + if ( !pOld || !( *static_cast(pOld) == aItem ) ) + { + rAttrs->Put( aItem ); + bModified = true; + } + } + // Width line start + if( m_xMtrStartWidth->get_value_changed_from_saved() ) + { + XLineStartWidthItem aItem( GetCoreValue( *m_xMtrStartWidth, m_ePoolUnit ) ); + pOld = GetOldItem( *rAttrs, XATTR_LINESTARTWIDTH ); + if ( !pOld || !( *static_cast(pOld) == aItem ) ) + { + rAttrs->Put( aItem ); + bModified = true; + } + } + // Width line end + if( m_xMtrEndWidth->get_value_changed_from_saved() ) + { + XLineEndWidthItem aItem( GetCoreValue( *m_xMtrEndWidth, m_ePoolUnit ) ); + pOld = GetOldItem( *rAttrs, XATTR_LINEENDWIDTH ); + if ( !pOld || !( *static_cast(pOld) == aItem ) ) + { + rAttrs->Put( aItem ); + bModified = true; + } + } + + // Line color + if (m_xLbColor->IsValueChangedFromSaved()) + { + NamedColor aColor = m_xLbColor->GetSelectedEntry(); + XLineColorItem aItem(aColor.second, aColor.first); + pOld = GetOldItem( *rAttrs, XATTR_LINECOLOR ); + if ( !pOld || !( *static_cast(pOld) == aItem ) ) + { + rAttrs->Put( aItem ); + bModified = true; + } + } + + if( m_nDlgType != 0 || m_nPageType != PageType::Bitmap ) + { + // Line start + nPos = m_xLbStartStyle->get_active(); + if( nPos != -1 && m_xLbStartStyle->get_value_changed_from_saved() ) + { + std::unique_ptr pItem; + if( nPos == 0 ) + pItem.reset(new XLineStartItem()); + else if( m_pLineEndList->Count() > static_cast( nPos - 1 ) ) + pItem.reset(new XLineStartItem( m_xLbStartStyle->get_active_text(), m_pLineEndList->GetLineEnd( nPos - 1 )->GetLineEnd() )); + pOld = GetOldItem( *rAttrs, XATTR_LINESTART ); + if( pItem && ( !pOld || *pOld != *pItem ) ) + { + rAttrs->Put( *pItem ); + bModified = true; + } + } + // Line end + nPos = m_xLbEndStyle->get_active(); + if( nPos != -1 && m_xLbEndStyle->get_value_changed_from_saved() ) + { + std::unique_ptr pItem; + if( nPos == 0 ) + pItem.reset(new XLineEndItem()); + else if( m_pLineEndList->Count() > static_cast( nPos - 1 ) ) + pItem.reset(new XLineEndItem( m_xLbEndStyle->get_active_text(), m_pLineEndList->GetLineEnd( nPos - 1 )->GetLineEnd() )); + pOld = GetOldItem( *rAttrs, XATTR_LINEEND ); + if( pItem && + ( !pOld || !( *static_cast(pOld) == *pItem ) ) ) + { + rAttrs->Put( *pItem ); + bModified = true; + } + } + } + + // Centered line end + TriState eState = m_xTsbCenterStart->get_state(); + if( m_xTsbCenterStart->get_state_changed_from_saved() ) + { + XLineStartCenterItem aItem( eState != TRISTATE_FALSE ); + pOld = GetOldItem( *rAttrs, XATTR_LINESTARTCENTER ); + if ( !pOld || !( *static_cast(pOld) == aItem ) ) + { + rAttrs->Put( aItem ); + bModified = true; + } + } + eState = m_xTsbCenterEnd->get_state(); + if( m_xTsbCenterEnd->get_state_changed_from_saved() ) + { + XLineEndCenterItem aItem( eState != TRISTATE_FALSE ); + pOld = GetOldItem( *rAttrs, XATTR_LINEENDCENTER ); + if ( !pOld || !( *static_cast(pOld) == aItem ) ) + { + rAttrs->Put( aItem ); + bModified = true; + } + } + + // Transparency + sal_uInt16 nVal = m_xMtrTransparent->get_value(FieldUnit::PERCENT); + if( m_xMtrTransparent->get_value_changed_from_saved() ) + { + XLineTransparenceItem aItem( nVal ); + pOld = GetOldItem( *rAttrs, XATTR_LINETRANSPARENCE ); + if ( !pOld || !( *static_cast(pOld) == aItem ) ) + { + rAttrs->Put( aItem ); + bModified = true; + } + } + + nPos = m_xLBEdgeStyle->get_active(); + if (nPos != -1 && m_xLBEdgeStyle->get_value_changed_from_saved()) + { + std::unique_ptr pNew; + + switch(nPos) + { + case 0: // Rounded, default + { + pNew.reset(new XLineJointItem(css::drawing::LineJoint_ROUND)); + break; + } + case 1: // - none - + { + pNew.reset(new XLineJointItem(css::drawing::LineJoint_NONE)); + break; + } + case 2: // Miter + { + pNew.reset(new XLineJointItem(css::drawing::LineJoint_MITER)); + break; + } + case 3: // Bevel + { + pNew.reset(new XLineJointItem(css::drawing::LineJoint_BEVEL)); + break; + } + } + + if(pNew) + { + pOld = GetOldItem( *rAttrs, XATTR_LINEJOINT ); + + if(!pOld || !(*static_cast(pOld) == *pNew)) + { + rAttrs->Put( *pNew ); + bModified = true; + } + } + } + + // LineCaps + nPos = m_xLBCapStyle->get_active(); + if (nPos != -1 && m_xLBCapStyle->get_value_changed_from_saved()) + { + std::unique_ptr pNew; + + switch(nPos) + { + case 0: // Butt (=Flat), default + { + pNew.reset(new XLineCapItem(css::drawing::LineCap_BUTT)); + break; + } + case 1: // Round + { + pNew.reset(new XLineCapItem(css::drawing::LineCap_ROUND)); + break; + } + case 2: // Square + { + pNew.reset(new XLineCapItem(css::drawing::LineCap_SQUARE)); + break; + } + } + + if(pNew) + { + pOld = GetOldItem( *rAttrs, XATTR_LINECAP ); + + if(!pOld || !(*static_cast(pOld) == *pNew)) + { + rAttrs->Put( *pNew ); + bModified = true; + } + } + } + + if(m_nSymbolType!=SVX_SYMBOLTYPE_UNKNOWN || m_bNewSize) + { + // Was set by selection or the size is different + SvxSizeItem aSItem(rAttrs->GetPool()->GetWhich(SID_ATTR_SYMBOLSIZE),m_aSymbolSize); + const SfxPoolItem* pSOld = GetOldItem( *rAttrs, rAttrs->GetPool()->GetWhich(SID_ATTR_SYMBOLSIZE) ); + m_bNewSize = pSOld ? *static_cast(pSOld) != aSItem : m_bNewSize ; + if(m_bNewSize) + { + rAttrs->Put(aSItem); + bModified=true; + } + + SfxInt32Item aTItem(rAttrs->GetPool()->GetWhich(SID_ATTR_SYMBOLTYPE),m_nSymbolType); + const SfxPoolItem* pTOld = GetOldItem( *rAttrs, rAttrs->GetPool()->GetWhich(SID_ATTR_SYMBOLTYPE) ); + bool bNewType = pTOld == nullptr || *static_cast(pTOld) != aTItem; + if(bNewType && m_nSymbolType==SVX_SYMBOLTYPE_UNKNOWN) + bNewType=false; // a small fix, type wasn't set -> don't create a type item after all! + if(bNewType) + { + rAttrs->Put(aTItem); + bModified=true; + } + + if(m_nSymbolType!=SVX_SYMBOLTYPE_NONE) + { + SvxBrushItem aBItem(m_aSymbolGraphic,GPOS_MM,rAttrs->GetPool()->GetWhich(SID_ATTR_BRUSH)); + const SfxPoolItem* pBOld = GetOldItem( *rAttrs, rAttrs->GetPool()->GetWhich(SID_ATTR_BRUSH) ); + bool bNewBrush = + pBOld == nullptr || *static_cast(pBOld) != aBItem; + if(bNewBrush) + { + rAttrs->Put(aBItem); + bModified=true; + } + } + } + rAttrs->Put (CntUInt16Item(SID_PAGE_TYPE, static_cast(m_nPageType))); + return bModified; +} + + +void SvxLineTabPage::FillXLSet_Impl() +{ + sal_Int32 nPos; + + if (m_xLbLineStyle->get_active() == -1) + { + m_rXLSet.Put( XLineStyleItem( drawing::LineStyle_NONE ) ); + } + else if (m_xLbLineStyle->get_active() == 0) + m_rXLSet.Put( XLineStyleItem( drawing::LineStyle_NONE ) ); + else if (m_xLbLineStyle->get_active() == 1) + m_rXLSet.Put( XLineStyleItem( drawing::LineStyle_SOLID ) ); + else + { + m_rXLSet.Put( XLineStyleItem( drawing::LineStyle_DASH ) ); + + nPos = m_xLbLineStyle->get_active(); + if (nPos != -1) + { + m_rXLSet.Put( XLineDashItem( m_xLbLineStyle->get_active_text(), + m_pDashList->GetDash( nPos - 2 )->GetDash() ) ); + } + } + + nPos = m_xLbStartStyle->get_active(); + if (nPos != -1) + { + if( nPos == 0 ) + m_rXLSet.Put( XLineStartItem() ); + else + m_rXLSet.Put( XLineStartItem( m_xLbStartStyle->get_active_text(), + m_pLineEndList->GetLineEnd( nPos - 1 )->GetLineEnd() ) ); + } + nPos = m_xLbEndStyle->get_active(); + if (nPos != -1) + { + if( nPos == 0 ) + m_rXLSet.Put( XLineEndItem() ); + else + m_rXLSet.Put( XLineEndItem( m_xLbEndStyle->get_active_text(), + m_pLineEndList->GetLineEnd( nPos - 1 )->GetLineEnd() ) ); + } + + nPos = m_xLBEdgeStyle->get_active(); + if (nPos != -1) + { + switch(nPos) + { + case 0: // Rounded, default + { + m_rXLSet.Put(XLineJointItem(css::drawing::LineJoint_ROUND)); + break; + } + case 1: // - none - + { + m_rXLSet.Put(XLineJointItem(css::drawing::LineJoint_NONE)); + break; + } + case 2: // Miter + { + m_rXLSet.Put(XLineJointItem(css::drawing::LineJoint_MITER)); + break; + } + case 3: // Bevel + { + m_rXLSet.Put(XLineJointItem(css::drawing::LineJoint_BEVEL)); + break; + } + } + } + + // LineCaps + nPos = m_xLBCapStyle->get_active(); + if (nPos != -1) + { + switch(nPos) + { + case 0: // Butt (=Flat), default + { + m_rXLSet.Put(XLineCapItem(css::drawing::LineCap_BUTT)); + break; + } + case 1: // Round + { + m_rXLSet.Put(XLineCapItem(css::drawing::LineCap_ROUND)); + break; + } + case 2: // Square + { + m_rXLSet.Put(XLineCapItem(css::drawing::LineCap_SQUARE)); + break; + } + } + } + + m_rXLSet.Put( XLineStartWidthItem( GetCoreValue( *m_xMtrStartWidth, m_ePoolUnit ) ) ); + m_rXLSet.Put( XLineEndWidthItem( GetCoreValue( *m_xMtrEndWidth, m_ePoolUnit ) ) ); + + m_rXLSet.Put( XLineWidthItem( GetCoreValue( *m_xMtrLineWidth, m_ePoolUnit ) ) ); + NamedColor aColor = m_xLbColor->GetSelectedEntry(); + m_rXLSet.Put(XLineColorItem(aColor.second, aColor.first)); + + // Centered line end + if( m_xTsbCenterStart->get_state() == TRISTATE_TRUE ) + m_rXLSet.Put( XLineStartCenterItem( true ) ); + else if( m_xTsbCenterStart->get_state() == TRISTATE_FALSE ) + m_rXLSet.Put( XLineStartCenterItem( false ) ); + + if( m_xTsbCenterEnd->get_state() == TRISTATE_TRUE ) + m_rXLSet.Put( XLineEndCenterItem( true ) ); + else if( m_xTsbCenterEnd->get_state() == TRISTATE_FALSE ) + m_rXLSet.Put( XLineEndCenterItem( false ) ); + + // Transparency + sal_uInt16 nVal = m_xMtrTransparent->get_value(FieldUnit::PERCENT); + m_rXLSet.Put( XLineTransparenceItem( nVal ) ); + + m_aCtlPreview.SetLineAttributes(m_aXLineAttr.GetItemSet()); +} + + +void SvxLineTabPage::Reset( const SfxItemSet* rAttrs ) +{ + drawing::LineStyle eXLS; // drawing::LineStyle_NONE, drawing::LineStyle_SOLID, drawing::LineStyle_DASH + + // Line style + const SfxPoolItem *pPoolItem; + long nSymType=SVX_SYMBOLTYPE_UNKNOWN; + bool bPrevSym=false; + bool bEnable=true; + bool bIgnoreGraphic=false; + bool bIgnoreSize=false; + if(rAttrs->GetItemState(rAttrs->GetPool()->GetWhich(SID_ATTR_SYMBOLTYPE),true,&pPoolItem) == SfxItemState::SET) + { + nSymType=static_cast(pPoolItem)->GetValue(); + } + + if(nSymType == SVX_SYMBOLTYPE_AUTO) + { + m_aSymbolGraphic=m_aAutoSymbolGraphic; + m_aSymbolSize=m_aSymbolLastSize=m_aAutoSymbolGraphic.GetPrefSize(); + bPrevSym=true; + } + else if(nSymType == SVX_SYMBOLTYPE_NONE) + { + bEnable=false; + bIgnoreGraphic=true; + bIgnoreSize=true; + } + else if(nSymType >= 0) + { + ScopedVclPtrInstance< VirtualDevice > pVDev; + pVDev->SetMapMode(MapMode(MapUnit::Map100thMM)); + + std::unique_ptr pModel( + new SdrModel(nullptr, nullptr, true)); + pModel->GetItemPool().FreezeIdRanges(); + SdrPage* pPage = new SdrPage( *pModel, false ); + pPage->SetSize(Size(1000,1000)); + pModel->InsertPage( pPage, 0 ); + { + std::unique_ptr pView(new SdrView( *pModel, pVDev )); + pView->hideMarkHandles(); + pView->ShowSdrPage(pPage); + SdrObject *pObj=nullptr; + size_t nSymTmp = static_cast(nSymType); + if(m_pSymbolList) + { + if(m_pSymbolList->GetObjCount()) + { + nSymTmp %= m_pSymbolList->GetObjCount(); // Treat list as cyclic! + pObj=m_pSymbolList->GetObj(nSymTmp); + if(pObj) + { + // directly clone to target SdrModel + pObj = pObj->CloneSdrObject(*pModel); + + if(m_pSymbolAttr) + { + pObj->SetMergedItemSet(*m_pSymbolAttr); + } + else + { + pObj->SetMergedItemSet(m_rOutAttrs); + } + + pPage->NbcInsertObject(pObj); + + // Generate invisible square to give all symbol types a + // bitmap size, which is independent from specific glyph + SdrObject* pInvisibleSquare(m_pSymbolList->GetObj(0)); + + // directly clone to target SdrModel + pInvisibleSquare = pInvisibleSquare->CloneSdrObject(*pModel); + + pPage->NbcInsertObject(pInvisibleSquare); + pInvisibleSquare->SetMergedItem(XFillTransparenceItem(100)); + pInvisibleSquare->SetMergedItem(XLineTransparenceItem(100)); + + pView->MarkAll(); + GDIMetaFile aMeta(pView->GetMarkedObjMetaFile()); + + m_aSymbolGraphic=Graphic(aMeta); + m_aSymbolSize=pObj->GetSnapRect().GetSize(); + m_aSymbolGraphic.SetPrefSize(pInvisibleSquare->GetSnapRect().GetSize()); + m_aSymbolGraphic.SetPrefMapMode(MapMode(MapUnit::Map100thMM)); + bPrevSym=true; + bEnable=true; + bIgnoreGraphic=true; + + pView->UnmarkAll(); + pInvisibleSquare=pPage->RemoveObject(1); + SdrObject::Free( pInvisibleSquare); + pObj=pPage->RemoveObject(0); + SdrObject::Free( pObj ); + } + } + } + } + } + if(rAttrs->GetItemState(rAttrs->GetPool()->GetWhich(SID_ATTR_BRUSH),true,&pPoolItem) == SfxItemState::SET) + { + const Graphic* pGraphic = static_cast(pPoolItem)->GetGraphic(); + if( pGraphic ) + { + if(!bIgnoreGraphic) + { + m_aSymbolGraphic=*pGraphic; + } + if(!bIgnoreSize) + { + m_aSymbolSize=OutputDevice::LogicToLogic( pGraphic->GetPrefSize(), + pGraphic->GetPrefMapMode(), + MapMode(MapUnit::Map100thMM)); + } + bPrevSym=true; + } + } + + if(rAttrs->GetItemState(rAttrs->GetPool()->GetWhich(SID_ATTR_SYMBOLSIZE),true,&pPoolItem) == SfxItemState::SET) + { + m_aSymbolSize = static_cast(pPoolItem)->GetSize(); + } + + m_xGridIconSize->set_sensitive(bEnable); + + if(bPrevSym) + { + SetMetricValue(*m_xSymbolWidthMF, m_aSymbolSize.Width(), m_ePoolUnit); + SetMetricValue(*m_xSymbolHeightMF, m_aSymbolSize.Height(),m_ePoolUnit); + m_aCtlPreview.SetSymbol(&m_aSymbolGraphic,m_aSymbolSize); + m_aSymbolLastSize=m_aSymbolSize; + } + + if( rAttrs->GetItemState( XATTR_LINESTYLE ) != SfxItemState::DONTCARE ) + { + eXLS = rAttrs->Get( XATTR_LINESTYLE ).GetValue(); + + switch( eXLS ) + { + case drawing::LineStyle_NONE: + m_xLbLineStyle->set_active(0); + break; + case drawing::LineStyle_SOLID: + m_xLbLineStyle->set_active(1); + break; + + case drawing::LineStyle_DASH: + m_xLbLineStyle->set_active(-1); + m_xLbLineStyle->set_active_text(rAttrs->Get( XATTR_LINEDASH ).GetName()); + break; + + default: + break; + } + } + else + { + m_xLbLineStyle->set_active(-1); + } + + // Line strength + if( rAttrs->GetItemState( XATTR_LINEWIDTH ) != SfxItemState::DONTCARE ) + { + SetMetricValue( *m_xMtrLineWidth, rAttrs->Get( XATTR_LINEWIDTH ).GetValue(), m_ePoolUnit ); + } + else + m_xMtrLineWidth->set_text(""); + + // Line color + m_xLbColor->SetNoSelection(); + + if ( rAttrs->GetItemState( XATTR_LINECOLOR ) != SfxItemState::DONTCARE ) + { + Color aCol = rAttrs->Get( XATTR_LINECOLOR ).GetColorValue(); + m_xLbColor->SelectEntry( aCol ); + } + + // Line start + if( m_bObjSelected && rAttrs->GetItemState( XATTR_LINESTART ) == SfxItemState::DEFAULT ) + { + m_xLbStartStyle->set_sensitive(false); + } + else if( rAttrs->GetItemState( XATTR_LINESTART ) != SfxItemState::DONTCARE ) + { + // #86265# select entry using list and polygon, not string + bool bSelected(false); + const basegfx::B2DPolyPolygon& rItemPolygon = rAttrs->Get(XATTR_LINESTART).GetLineStartValue(); + + for(long a(0);!bSelected && a < m_pLineEndList->Count(); a++) + { + const XLineEndEntry* pEntry = m_pLineEndList->GetLineEnd(a); + const basegfx::B2DPolyPolygon& rEntryPolygon = pEntry->GetLineEnd(); + + if(rItemPolygon == rEntryPolygon) + { + // select this entry + m_xLbStartStyle->set_active(a + 1); + bSelected = true; + } + } + + if(!bSelected) + m_xLbStartStyle->set_active(0); + } + else + { + m_xLbStartStyle->set_active(-1); + } + + // Line end + if( m_bObjSelected && rAttrs->GetItemState( XATTR_LINEEND ) == SfxItemState::DEFAULT ) + { + m_xLbEndStyle->set_sensitive(false); + } + else if( rAttrs->GetItemState( XATTR_LINEEND ) != SfxItemState::DONTCARE ) + { + // #86265# select entry using list and polygon, not string + bool bSelected(false); + const basegfx::B2DPolyPolygon& rItemPolygon = rAttrs->Get(XATTR_LINEEND).GetLineEndValue(); + + for(long a(0);!bSelected && a < m_pLineEndList->Count(); a++) + { + const XLineEndEntry* pEntry = m_pLineEndList->GetLineEnd(a); + const basegfx::B2DPolyPolygon& rEntryPolygon = pEntry->GetLineEnd(); + + if(rItemPolygon == rEntryPolygon) + { + // select this entry + m_xLbEndStyle->set_active(a + 1); + bSelected = true; + } + } + + if(!bSelected) + m_xLbEndStyle->set_active(0); + } + else + { + m_xLbEndStyle->set_active(-1); + } + + // Line start strength + if( m_bObjSelected && rAttrs->GetItemState( XATTR_LINESTARTWIDTH ) == SfxItemState::DEFAULT ) + { + m_xMtrStartWidth->set_sensitive(false); + } + else if( rAttrs->GetItemState( XATTR_LINESTARTWIDTH ) != SfxItemState::DONTCARE ) + { + SetMetricValue( *m_xMtrStartWidth, + rAttrs->Get( XATTR_LINESTARTWIDTH ).GetValue(), + m_ePoolUnit ); + } + else + m_xMtrStartWidth->set_text( "" ); + + // Line end strength + if( m_bObjSelected && rAttrs->GetItemState( XATTR_LINEENDWIDTH ) == SfxItemState::DEFAULT ) + { + m_xMtrEndWidth->set_sensitive(false); + } + else if( rAttrs->GetItemState( XATTR_LINEENDWIDTH ) != SfxItemState::DONTCARE ) + { + SetMetricValue( *m_xMtrEndWidth, + rAttrs->Get( XATTR_LINEENDWIDTH ).GetValue(), + m_ePoolUnit ); + } + else + m_xMtrEndWidth->set_text(""); + + // Centered line end (start) + if( m_bObjSelected && rAttrs->GetItemState( XATTR_LINESTARTCENTER ) == SfxItemState::DEFAULT ) + { + m_xTsbCenterStart->set_sensitive(false); + } + else if( rAttrs->GetItemState( XATTR_LINESTARTCENTER ) != SfxItemState::DONTCARE ) + { + if( rAttrs->Get( XATTR_LINESTARTCENTER ).GetValue() ) + m_xTsbCenterStart->set_state(TRISTATE_TRUE); + else + m_xTsbCenterStart->set_state(TRISTATE_FALSE); + } + else + { + m_xTsbCenterStart->set_state(TRISTATE_INDET); + } + + // Centered line end (end) + if( m_bObjSelected && rAttrs->GetItemState( XATTR_LINEENDCENTER ) == SfxItemState::DEFAULT ) + { + m_xTsbCenterEnd->set_sensitive(false); + } + else if( rAttrs->GetItemState( XATTR_LINEENDCENTER ) != SfxItemState::DONTCARE ) + { + if( rAttrs->Get( XATTR_LINEENDCENTER ).GetValue() ) + m_xTsbCenterEnd->set_state(TRISTATE_TRUE); + else + m_xTsbCenterEnd->set_state(TRISTATE_FALSE); + } + else + { + m_xTsbCenterEnd->set_state(TRISTATE_INDET); + } + + // Transparency + if( rAttrs->GetItemState( XATTR_LINETRANSPARENCE ) != SfxItemState::DONTCARE ) + { + sal_uInt16 nTransp = rAttrs->Get( XATTR_LINETRANSPARENCE ).GetValue(); + m_xMtrTransparent->set_value(nTransp, FieldUnit::PERCENT); + ChangeTransparentHdl_Impl(*m_xMtrTransparent); + } + else + m_xMtrTransparent->set_text( "" ); + + if( !m_xLbStartStyle->get_sensitive() && + !m_xLbEndStyle->get_sensitive() && + !m_xMtrStartWidth->get_sensitive() && + !m_xMtrEndWidth->get_sensitive() && + !m_xTsbCenterStart->get_sensitive()&& + !m_xTsbCenterEnd->get_sensitive() ) + { + m_xCbxSynchronize->set_sensitive(false); + m_xFlLineEnds->set_sensitive(false); + } + + // Synchronize + // We get the value from the INI file now + OUString aStr = GetUserData(); + m_xCbxSynchronize->set_active(aStr.toInt32() != 0); + + if(m_bObjSelected && SfxItemState::DEFAULT == rAttrs->GetItemState(XATTR_LINEJOINT)) + { +// maFTEdgeStyle.set_sensitive(false); + m_xLBEdgeStyle->set_sensitive(false); + } + else if(SfxItemState::DONTCARE != rAttrs->GetItemState(XATTR_LINEJOINT)) + { + const css::drawing::LineJoint eLineJoint = rAttrs->Get(XATTR_LINEJOINT).GetValue(); + + switch(eLineJoint) + { + case css::drawing::LineJoint::LineJoint_MAKE_FIXED_SIZE: // fallback to round, unused value + case css::drawing::LineJoint_ROUND : m_xLBEdgeStyle->set_active(0); break; + case css::drawing::LineJoint_NONE : m_xLBEdgeStyle->set_active(1); break; + case css::drawing::LineJoint_MIDDLE : // fallback to mitre, unused value + case css::drawing::LineJoint_MITER : m_xLBEdgeStyle->set_active(2); break; + case css::drawing::LineJoint_BEVEL : m_xLBEdgeStyle->set_active(3); break; + } + } + else + { + m_xLBEdgeStyle->set_active(-1); + } + + // fdo#43209 + if(m_bObjSelected && SfxItemState::DEFAULT == rAttrs->GetItemState(XATTR_LINECAP)) + { + m_xLBCapStyle->set_sensitive(false); + } + else if(SfxItemState::DONTCARE != rAttrs->GetItemState(XATTR_LINECAP)) + { + const css::drawing::LineCap eLineCap(rAttrs->Get(XATTR_LINECAP).GetValue()); + + switch(eLineCap) + { + case css::drawing::LineCap_ROUND: m_xLBCapStyle->set_active(1); break; + case css::drawing::LineCap_SQUARE : m_xLBCapStyle->set_active(2); break; + default /*css::drawing::LineCap_BUTT*/: m_xLBCapStyle->set_active(0); break; + } + } + else + { + m_xLBCapStyle->set_active(-1); + } + + // Save values + m_xLbLineStyle->save_value(); + m_xMtrLineWidth->save_value(); + m_xLbColor->SaveValue(); + m_xLbStartStyle->save_value(); + m_xLbEndStyle->save_value(); + m_xMtrStartWidth->save_value(); + m_xMtrEndWidth->save_value(); + m_xTsbCenterStart->save_state(); + m_xTsbCenterEnd->save_state(); + m_xMtrTransparent->save_value(); + + m_xLBEdgeStyle->save_value(); + + // LineCaps + m_xLBCapStyle->save_value(); + + ClickInvisibleHdl_Impl(); + + ChangePreviewHdl_Impl( nullptr ); +} + +std::unique_ptr SvxLineTabPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrs) +{ + return std::make_unique(pPage, pController, *rAttrs); +} + +IMPL_LINK_NOARG(SvxLineTabPage, ChangePreviewListBoxHdl_Impl, ColorListBox&, void) +{ + ChangePreviewHdl_Impl(nullptr); +} + +IMPL_LINK(SvxLineTabPage, ChangePreviewModifyHdl_Impl, weld::MetricSpinButton&, rEdit, void) +{ + ChangePreviewHdl_Impl(&rEdit); +} + +void SvxLineTabPage::ChangePreviewHdl_Impl(const weld::MetricSpinButton* pCntrl) +{ + if (pCntrl == m_xMtrLineWidth.get()) + { + // Line width and start end width + sal_Int32 nNewLineWidth = GetCoreValue( *m_xMtrLineWidth, m_ePoolUnit ); + if(m_nActLineWidth == -1) + { + // Don't initialize yet, get the start value + const SfxPoolItem* pOld = GetOldItem( m_rXLSet, XATTR_LINEWIDTH ); + sal_Int32 nStartLineWidth = 0; + if(pOld) + nStartLineWidth = static_cast(pOld)->GetValue(); + m_nActLineWidth = nStartLineWidth; + } + + if(m_nActLineWidth != nNewLineWidth) + { + // Adapt start/end width + sal_Int32 nValAct = GetCoreValue( *m_xMtrStartWidth, m_ePoolUnit ); + sal_Int32 nValNew = nValAct + (((nNewLineWidth - m_nActLineWidth) * 15) / 10); + if(nValNew < 0) + nValNew = 0; + SetMetricValue( *m_xMtrStartWidth, nValNew, m_ePoolUnit ); + + nValAct = GetCoreValue( *m_xMtrEndWidth, m_ePoolUnit ); + nValNew = nValAct + (((nNewLineWidth - m_nActLineWidth) * 15) / 10); + if(nValNew < 0) + nValNew = 0; + SetMetricValue( *m_xMtrEndWidth, nValNew, m_ePoolUnit ); + } + + // Remember current value + m_nActLineWidth = nNewLineWidth; + } + + FillXLSet_Impl(); + m_aCtlPreview.Invalidate(); + + // Make transparency accessible accordingly + if( m_xLbLineStyle->get_active() == 0 ) // invisible + { + m_xBoxTransparency->set_sensitive(false); + } + else + { + m_xBoxTransparency->set_sensitive(true); + } + + const bool bHasLineStyle = m_xLbLineStyle->get_active() !=0; + const bool bHasLineStart = m_xLbStartStyle->get_active() != 0; + + m_xBoxStart->set_sensitive(bHasLineStart && bHasLineStyle); + + const bool bHasLineEnd = m_xLbEndStyle->get_active() != 0; + + m_xBoxEnd->set_sensitive(bHasLineEnd && bHasLineStyle); +} + +IMPL_LINK_NOARG(SvxLineTabPage, ChangeStartClickHdl_Impl, weld::Button&, void) +{ + if (m_xCbxSynchronize->get_active()) + m_xTsbCenterEnd->set_state(m_xTsbCenterStart->get_state()); + ChangePreviewHdl_Impl(nullptr); +} + +IMPL_LINK_NOARG(SvxLineTabPage, ChangeStartListBoxHdl_Impl, weld::ComboBox&, void) +{ + if (m_xCbxSynchronize->get_active()) + m_xLbEndStyle->set_active(m_xLbStartStyle->get_active()); + + ChangePreviewHdl_Impl(nullptr); +} + +IMPL_LINK_NOARG(SvxLineTabPage, ChangeStartModifyHdl_Impl, weld::MetricSpinButton&, void) +{ + if (m_xCbxSynchronize->get_active()) + m_xMtrEndWidth->set_value(m_xMtrStartWidth->get_value(FieldUnit::NONE), FieldUnit::NONE); + + ChangePreviewHdl_Impl(nullptr); +} + +IMPL_LINK_NOARG(SvxLineTabPage, ChangeEdgeStyleHdl_Impl, weld::ComboBox&, void) +{ + ChangePreviewHdl_Impl( nullptr ); +} + +// fdo#43209 +IMPL_LINK_NOARG(SvxLineTabPage, ChangeCapStyleHdl_Impl, weld::ComboBox&, void) +{ + ChangePreviewHdl_Impl( nullptr ); +} + +IMPL_LINK_NOARG(SvxLineTabPage, ClickInvisibleHdl_Impl, weld::ComboBox&, void) +{ + ClickInvisibleHdl_Impl(); +} + +void SvxLineTabPage::ClickInvisibleHdl_Impl() +{ + if( m_xLbLineStyle->get_active() == 0 ) // invisible + { + if(!m_bSymbols) + m_xBoxColor->set_sensitive(false); + + m_xBoxWidth->set_sensitive(false); + + if( m_xFlLineEnds->get_sensitive() ) + { + m_xBoxStart->set_sensitive(false); + m_xBoxArrowStyles->set_sensitive(false); + m_xGridEdgeCaps->set_sensitive(false); + } + } + else + { + m_xBoxColor->set_sensitive(true); + m_xBoxWidth->set_sensitive(true); + + if (m_xFlLineEnds->get_sensitive()) + { + m_xBoxArrowStyles->set_sensitive(true); + m_xGridEdgeCaps->set_sensitive(true); + } + } + ChangePreviewHdl_Impl( nullptr ); +} + +IMPL_LINK_NOARG(SvxLineTabPage, ChangeEndClickHdl_Impl, weld::Button&, void) +{ + if (m_xCbxSynchronize->get_active()) + m_xTsbCenterStart->set_state(m_xTsbCenterEnd->get_state()); + + ChangePreviewHdl_Impl(nullptr); +} + +IMPL_LINK_NOARG(SvxLineTabPage, ChangeEndListBoxHdl_Impl, weld::ComboBox&, void) +{ + if (m_xCbxSynchronize->get_active()) + m_xLbStartStyle->set_active(m_xLbEndStyle->get_active()); + + ChangePreviewHdl_Impl(nullptr); +} + +IMPL_LINK_NOARG(SvxLineTabPage, ChangeEndModifyHdl_Impl, weld::MetricSpinButton&, void) +{ + if (m_xCbxSynchronize->get_active()) + m_xMtrStartWidth->set_value(m_xMtrEndWidth->get_value(FieldUnit::NONE), FieldUnit::NONE); + + ChangePreviewHdl_Impl(nullptr); +} + +IMPL_LINK_NOARG(SvxLineTabPage, ChangeTransparentHdl_Impl, weld::MetricSpinButton&, void) +{ + sal_uInt16 nVal = m_xMtrTransparent->get_value(FieldUnit::PERCENT); + + m_rXLSet.Put(XLineTransparenceItem(nVal)); + + FillXLSet_Impl(); + + m_aCtlPreview.Invalidate(); +} + +void SvxLineTabPage::FillUserData() +{ + // Write the synched value to the INI file + OUString aStrUserData = OUString::boolean(m_xCbxSynchronize->get_active()); + SetUserData( aStrUserData ); +} + +// #58425# Symbols on a list (e.g. StarChart) +// Handler for the symbol selection's popup menu (NumMenueButton) +// The following link originates from SvxNumOptionsTabPage +IMPL_LINK_NOARG(SvxLineTabPage, MenuCreateHdl_Impl, weld::ToggleButton&, void) +{ + ScopedVclPtrInstance< VirtualDevice > pVD; + + // Initialize popup + if (!m_xGalleryMenu) + { + m_xGalleryMenu = m_xBuilder->weld_menu("gallerysubmenu"); + weld::WaitObject aWait(GetFrameWeld()); + // Get gallery entries + GalleryExplorer::FillObjList(GALLERY_THEME_BULLETS, m_aGrfNames); + + sal_uInt32 i = 0; + for (auto const& grfName : m_aGrfNames) + { + const OUString *pUIName = &grfName; + + // Convert URL encodings to UI characters (e.g. %20 for spaces) + OUString aPhysicalName; + if (osl::FileBase::getSystemPathFromFileURL(grfName, aPhysicalName) + == osl::FileBase::E_None) + { + pUIName = &aPhysicalName; + } + + SvxBmpItemInfo* pInfo = new SvxBmpItemInfo; + pInfo->pBrushItem.reset(new SvxBrushItem(grfName, "", GPOS_AREA, SID_ATTR_BRUSH)); + pInfo->sItemId = "gallery" + OUString::number(i); + m_aGalleryBrushItems.emplace_back(pInfo); + const Graphic* pGraphic = pInfo->pBrushItem->GetGraphic(); + + if(pGraphic) + { + BitmapEx aBitmap(pGraphic->GetBitmapEx()); + Size aSize(aBitmap.GetSizePixel()); + if(aSize.Width() > MAX_BMP_WIDTH || aSize.Height() > MAX_BMP_HEIGHT) + { + bool bWidth = aSize.Width() > aSize.Height(); + double nScale = bWidth ? + double(MAX_BMP_WIDTH) / static_cast(aSize.Width()): + double(MAX_BMP_HEIGHT) / static_cast(aSize.Height()); + aBitmap.Scale(nScale, nScale); + + } + pVD->SetOutputSizePixel(aBitmap.GetSizePixel()); + pVD->DrawBitmapEx(Point(), aBitmap); + m_xGalleryMenu->append(pInfo->sItemId, *pUIName, *pVD); + } + else + { + m_xGalleryMenu->append(pInfo->sItemId, *pUIName); + } + ++i; + } + + if (m_aGrfNames.empty()) + m_xSymbolMB->set_item_sensitive("gallery", false); + } + + if (!(!m_xSymbolsMenu && m_pSymbolList)) + return; + + m_xSymbolsMenu = m_xBuilder->weld_menu("symbolssubmenu"); + ScopedVclPtrInstance< VirtualDevice > pVDev; + pVDev->SetMapMode(MapMode(MapUnit::Map100thMM)); + std::unique_ptr pModel( + new SdrModel(nullptr, nullptr, true)); + pModel->GetItemPool().FreezeIdRanges(); + // Page + SdrPage* pPage = new SdrPage( *pModel, false ); + pPage->SetSize(Size(1000,1000)); + pModel->InsertPage( pPage, 0 ); + { + // 3D View + std::unique_ptr pView(new SdrView( *pModel, pVDev )); + pView->hideMarkHandles(); + pView->ShowSdrPage(pPage); + + // Generate invisible square to give all symbols a + // bitmap size, which is independent from specific glyph + SdrObject *pInvisibleSquare=m_pSymbolList->GetObj(0); + + // directly clone to target SdrModel + pInvisibleSquare = pInvisibleSquare->CloneSdrObject(*pModel); + + pPage->NbcInsertObject(pInvisibleSquare); + pInvisibleSquare->SetMergedItem(XFillTransparenceItem(100)); + pInvisibleSquare->SetMergedItem(XLineTransparenceItem(100)); + + for(size_t i=0; i < m_pSymbolList->GetObjCount(); ++i) + { + SdrObject *pObj=m_pSymbolList->GetObj(i); + assert(pObj); + + // directly clone to target SdrModel + pObj = pObj->CloneSdrObject(*pModel); + + m_aGrfNames.emplace_back(""); + pPage->NbcInsertObject(pObj); + if(m_pSymbolAttr) + { + pObj->SetMergedItemSet(*m_pSymbolAttr); + } + else + { + pObj->SetMergedItemSet(m_rOutAttrs); + } + pView->MarkAll(); + BitmapEx aBitmapEx(pView->GetMarkedObjBitmapEx()); + GDIMetaFile aMeta(pView->GetMarkedObjMetaFile()); + pView->UnmarkAll(); + pObj=pPage->RemoveObject(1); + SdrObject::Free(pObj); + + SvxBmpItemInfo* pInfo = new SvxBmpItemInfo; + pInfo->pBrushItem.reset(new SvxBrushItem(Graphic(aMeta), GPOS_AREA, SID_ATTR_BRUSH)); + pInfo->sItemId = "symbol" + OUString::number(i); + m_aSymbolBrushItems.emplace_back(pInfo); + + Size aSize(aBitmapEx.GetSizePixel()); + if(aSize.Width() > MAX_BMP_WIDTH || aSize.Height() > MAX_BMP_HEIGHT) + { + bool bWidth = aSize.Width() > aSize.Height(); + double nScale = bWidth ? + double(MAX_BMP_WIDTH) / static_cast(aSize.Width()): + double(MAX_BMP_HEIGHT) / static_cast(aSize.Height()); + aBitmapEx.Scale(nScale, nScale); + } + pVD->SetOutputSizePixel(aBitmapEx.GetSizePixel()); + pVD->DrawBitmapEx(Point(), aBitmapEx); + m_xSymbolsMenu->append(pInfo->sItemId, "", *pVD); + } + pInvisibleSquare=pPage->RemoveObject(0); + SdrObject::Free(pInvisibleSquare); + + if (m_aGrfNames.empty()) + m_xSymbolMB->set_item_sensitive("symbols", false); + } +} + +// #58425# Symbols on a list (e.g. StarChart) +// Handler for menu button +IMPL_LINK(SvxLineTabPage, GraphicHdl_Impl, const OString&, rIdent, void) +{ + const Graphic* pGraphic = nullptr; + Graphic aGraphic; + bool bResetSize = false; + bool bEnable = true; + long nPreviousSymbolType = m_nSymbolType; + + OString sNumber; + if (rIdent.startsWith("gallery", &sNumber)) + { + SvxBmpItemInfo* pInfo = m_aGalleryBrushItems[sNumber.toUInt32()].get(); + pGraphic = pInfo->pBrushItem->GetGraphic(); + m_nSymbolType = SVX_SYMBOLTYPE_BRUSHITEM; + } + else if (rIdent.startsWith("symbol", &sNumber)) + { + m_nSymbolType = sNumber.toUInt32(); + SvxBmpItemInfo* pInfo = m_aSymbolBrushItems[m_nSymbolType].get(); + pGraphic = pInfo->pBrushItem->GetGraphic(); + } + else if (rIdent == "automatic") + { + pGraphic=&m_aAutoSymbolGraphic; + m_aAutoSymbolGraphic.SetPrefSize( Size(253,253) ); + m_nSymbolType=SVX_SYMBOLTYPE_AUTO; + } + else if (rIdent == "none") + { + m_nSymbolType=SVX_SYMBOLTYPE_NONE; + pGraphic=nullptr; + bEnable = false; + } + else if (rIdent == "file") + { + SvxOpenGraphicDialog aGrfDlg(CuiResId(RID_SVXSTR_EDIT_GRAPHIC), GetFrameWeld()); + aGrfDlg.EnableLink(false); + aGrfDlg.AsLink(false); + if( !aGrfDlg.Execute() ) + { + // Remember selected filters + if( !aGrfDlg.GetGraphic(aGraphic) ) + { + m_nSymbolType=SVX_SYMBOLTYPE_BRUSHITEM; + pGraphic = &aGraphic; + bResetSize = true; + } + } + if( !pGraphic ) + return; + } + + if (pGraphic) + { + Size aSize = SvxNumberFormat::GetGraphicSizeMM100(pGraphic); + aSize = OutputDevice::LogicToLogic(aSize, MapMode(MapUnit::Map100thMM), MapMode(m_ePoolUnit)); + m_aSymbolGraphic=*pGraphic; + if( bResetSize ) + { + m_aSymbolSize=aSize; + } + else if( nPreviousSymbolType == SVX_SYMBOLTYPE_BRUSHITEM ) + { //#i31097# Data Point Symbol size changes when a different symbol is chosen(maoyg) + if( m_aSymbolSize.Width() != m_aSymbolSize.Height() ) + { + aSize.setWidth( static_cast( m_aSymbolSize.Width() + m_aSymbolSize.Height() )/2 ); + aSize.setHeight( static_cast( m_aSymbolSize.Width() + m_aSymbolSize.Height() )/2 ); + m_aSymbolSize = aSize; + } + } + m_aCtlPreview.SetSymbol(&m_aSymbolGraphic,m_aSymbolSize); + } + else + { + m_aSymbolGraphic=Graphic(); + m_aCtlPreview.SetSymbol(nullptr,m_aSymbolSize); + bEnable = false; + } + m_aSymbolLastSize=m_aSymbolSize; + SetMetricValue(*m_xSymbolWidthMF, m_aSymbolSize.Width(), m_ePoolUnit); + SetMetricValue(*m_xSymbolHeightMF, m_aSymbolSize.Height(), m_ePoolUnit); + + m_xGridIconSize->set_sensitive(bEnable); + m_aCtlPreview.Invalidate(); +} + +IMPL_LINK( SvxLineTabPage, SizeHdl_Impl, weld::MetricSpinButton&, rField, void) +{ + m_bNewSize = true; + bool bWidth = &rField == m_xSymbolWidthMF.get(); + m_bLastWidthModified = bWidth; + bool bRatio = m_xSymbolRatioCB->get_active(); + long nWidthVal = static_cast(m_xSymbolWidthMF->denormalize(m_xSymbolWidthMF->get_value(FieldUnit::MM_100TH))); + long nHeightVal= static_cast(m_xSymbolHeightMF->denormalize(m_xSymbolHeightMF->get_value(FieldUnit::MM_100TH))); + nWidthVal = OutputDevice::LogicToLogic(nWidthVal,MapUnit::Map100thMM, m_ePoolUnit ); + nHeightVal = OutputDevice::LogicToLogic(nHeightVal,MapUnit::Map100thMM, m_ePoolUnit); + m_aSymbolSize = Size(nWidthVal,nHeightVal); + double fSizeRatio = double(1); + + if(bRatio) + { + if (m_aSymbolLastSize.Height() && m_aSymbolLastSize.Width()) + fSizeRatio = static_cast(m_aSymbolLastSize.Width()) / m_aSymbolLastSize.Height(); + } + + if (bWidth) + { + long nDelta = nWidthVal - m_aSymbolLastSize.Width(); + m_aSymbolSize.setWidth( nWidthVal ); + if (bRatio) + { + m_aSymbolSize.setHeight( m_aSymbolLastSize.Height() + static_cast(static_cast(nDelta) / fSizeRatio) ); + m_aSymbolSize.setHeight( OutputDevice::LogicToLogic( m_aSymbolSize.Height(), m_ePoolUnit, MapUnit::Map100thMM ) ); +//TODO m_xSymbolHeightMF->SetUserValue(m_xSymbolHeightMF->normalize(m_aSymbolSize.Height()), FieldUnit::MM_100TH); + m_xSymbolHeightMF->set_value(m_xSymbolHeightMF->normalize(m_aSymbolSize.Height()), FieldUnit::MM_100TH); + } + } + else + { + long nDelta = nHeightVal - m_aSymbolLastSize.Height(); + m_aSymbolSize.setHeight( nHeightVal ); + if (bRatio) + { + m_aSymbolSize.setWidth( m_aSymbolLastSize.Width() + static_cast(static_cast(nDelta) * fSizeRatio) ); + m_aSymbolSize.setWidth( OutputDevice::LogicToLogic( m_aSymbolSize.Width(), m_ePoolUnit, MapUnit::Map100thMM ) ); +//TODO m_xSymbolWidthMF->SetUserValue(m_xSymbolWidthMF->normalize(m_aSymbolSize.Width()), FieldUnit::MM_100TH); + m_xSymbolWidthMF->set_value(m_xSymbolWidthMF->normalize(m_aSymbolSize.Width()), FieldUnit::MM_100TH); + } + } + m_aCtlPreview.ResizeSymbol(m_aSymbolSize); + m_aSymbolLastSize=m_aSymbolSize; +} + +IMPL_LINK(SvxLineTabPage, RatioHdl_Impl, weld::ToggleButton&, rBox, void) +{ + if (rBox.get_active()) + { + if (m_bLastWidthModified) + SizeHdl_Impl(*m_xSymbolWidthMF); + else + SizeHdl_Impl(*m_xSymbolHeightMF); + } +} + +void SvxLineTabPage::PageCreated(const SfxAllItemSet& aSet) +{ + const SvxDashListItem* pDashListItem = aSet.GetItem(SID_DASH_LIST, false); + const SvxLineEndListItem* pLineEndListItem = aSet.GetItem(SID_LINEEND_LIST, false); + const SfxUInt16Item* pPageTypeItem = aSet.GetItem(SID_PAGE_TYPE, false); + const SfxUInt16Item* pDlgTypeItem = aSet.GetItem(SID_DLG_TYPE, false); + const OfaPtrItem* pSdrObjListItem = aSet.GetItem(SID_OBJECT_LIST, false); + const SfxTabDialogItem* pSymbolAttrItem = aSet.GetItem(SID_ATTR_SET, false); + const SvxGraphicItem* pGraphicItem = aSet.GetItem(SID_GRAPHIC, false); + + if (pDashListItem) + SetDashList(pDashListItem->GetDashList()); + if (pLineEndListItem) + SetLineEndList(pLineEndListItem->GetLineEndList()); + if (pPageTypeItem) + SetPageType(static_cast(pPageTypeItem->GetValue())); + if (pDlgTypeItem) + SetDlgType(pDlgTypeItem->GetValue()); + Construct(); + + if(pSdrObjListItem) //symbols + { + ShowSymbolControls(true); + m_pSymbolList = static_cast(pSdrObjListItem->GetValue()); + if (pSymbolAttrItem) + m_pSymbolAttr = new SfxItemSet(pSymbolAttrItem->GetItemSet()); + if(pGraphicItem) + m_aAutoSymbolGraphic = pGraphicItem->GetGraphic(); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/tplnedef.cxx b/cui/source/tabpages/tplnedef.cxx new file mode 100644 index 000000000..2cef64e0e --- /dev/null +++ b/cui/source/tabpages/tplnedef.cxx @@ -0,0 +1,839 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define XOUT_WIDTH 150 + +using namespace com::sun::star; + + +SvxLineDefTabPage::SvxLineDefTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "cui/ui/linestyletabpage.ui", "LineStylePage", &rInAttrs) + , rOutAttrs(rInAttrs) + , aXLineAttr(rInAttrs.GetPool()) + , rXLSet(aXLineAttr.GetItemSet()) + , pnDashListState(nullptr) + , pPageType(nullptr) + , nDlgType(0) + , pPosDashLb(nullptr) + , m_xLbLineStyles(new SvxLineLB(m_xBuilder->weld_combo_box("LB_LINESTYLES"))) + , m_xLbType1(m_xBuilder->weld_combo_box("LB_TYPE_1")) + , m_xLbType2(m_xBuilder->weld_combo_box("LB_TYPE_2")) + , m_xNumFldNumber1(m_xBuilder->weld_spin_button("NUM_FLD_1")) + , m_xNumFldNumber2(m_xBuilder->weld_spin_button("NUM_FLD_2")) + , m_xMtrLength1(m_xBuilder->weld_metric_spin_button("MTR_FLD_LENGTH_1", FieldUnit::CM)) + , m_xMtrLength2(m_xBuilder->weld_metric_spin_button("MTR_FLD_LENGTH_2", FieldUnit::CM)) + , m_xMtrDistance(m_xBuilder->weld_metric_spin_button("MTR_FLD_DISTANCE", FieldUnit::CM)) + , m_xCbxSynchronize(m_xBuilder->weld_check_button("CBX_SYNCHRONIZE")) + , m_xBtnAdd(m_xBuilder->weld_button("BTN_ADD")) + , m_xBtnModify(m_xBuilder->weld_button("BTN_MODIFY")) + , m_xBtnDelete(m_xBuilder->weld_button("BTN_DELETE")) + , m_xBtnLoad(m_xBuilder->weld_button("BTN_LOAD")) + , m_xBtnSave(m_xBuilder->weld_button("BTN_SAVE")) + , m_xCtlPreview(new weld::CustomWeld(*m_xBuilder, "CTL_PREVIEW", m_aCtlPreview)) +{ + // this page needs ExchangeSupport + SetExchangeSupport(); + + // adjust metric + eFUnit = GetModuleFieldUnit( rInAttrs ); + + switch ( eFUnit ) + { + case FieldUnit::M: + case FieldUnit::KM: + eFUnit = FieldUnit::MM; + break; + default: ; //prevent warning + } + SetFieldUnit(*m_xMtrDistance, eFUnit); + SetFieldUnit(*m_xMtrLength1, eFUnit); + SetFieldUnit(*m_xMtrLength2, eFUnit); + + // determine PoolUnit + SfxItemPool* pPool = rOutAttrs.GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + ePoolUnit = pPool->GetMetric( SID_ATTR_LINE_WIDTH ); + + rXLSet.Put( XLineStyleItem(drawing::LineStyle_DASH) ); + rXLSet.Put( XLineWidthItem(XOUT_WIDTH) ); + rXLSet.Put( XLineDashItem( OUString(), XDash( css::drawing::DashStyle_RECT, 3, 7, 2, 40, 15 ) ) ); + rXLSet.Put( XLineColorItem(OUString(), COL_BLACK) ); + + // #i34740# + m_aCtlPreview.SetLineAttributes(aXLineAttr.GetItemSet()); + + m_xBtnAdd->connect_clicked(LINK(this, SvxLineDefTabPage, ClickAddHdl_Impl)); + m_xBtnModify->connect_clicked(LINK(this, SvxLineDefTabPage, ClickModifyHdl_Impl)); + m_xBtnDelete->connect_clicked(LINK(this, SvxLineDefTabPage, ClickDeleteHdl_Impl)); + m_xBtnLoad->connect_clicked(LINK(this, SvxLineDefTabPage, ClickLoadHdl_Impl)); + m_xBtnSave->connect_clicked(LINK(this, SvxLineDefTabPage, ClickSaveHdl_Impl)); + + m_xNumFldNumber1->connect_value_changed(LINK(this, SvxLineDefTabPage, ChangeNumber1Hdl_Impl)); + m_xNumFldNumber2->connect_value_changed(LINK(this, SvxLineDefTabPage, ChangeNumber2Hdl_Impl)); + m_xLbLineStyles->connect_changed(LINK(this, SvxLineDefTabPage, SelectLinestyleListBoxHdl_Impl)); + + // #i122042# switch off default adding of 'none' and 'solid' entries + // for this ListBox; we want to select only editable/dashed styles + m_xLbLineStyles->setAddStandardFields(false); + + // absolute (in mm) or relative (in %) + m_xCbxSynchronize->connect_toggled(LINK(this, SvxLineDefTabPage, ChangeMetricHdl_Impl)); + + // preview must be updated when there's something changed + Link aLink = LINK(this, SvxLineDefTabPage, SelectTypeListBoxHdl_Impl); + m_xLbType1->connect_changed(aLink); + m_xLbType2->connect_changed(aLink); + Link aLink2 = LINK( this, SvxLineDefTabPage, ChangePreviewHdl_Impl ); + m_xMtrLength1->connect_value_changed(aLink2); + m_xMtrLength2->connect_value_changed(aLink2); + m_xMtrDistance->connect_value_changed(aLink2); + + pDashList = nullptr; +} + +SvxLineDefTabPage::~SvxLineDefTabPage() +{ + m_xCtlPreview.reset(); + m_xLbLineStyles.reset(); +} + +void SvxLineDefTabPage::Construct() +{ + // Line style fill; do *not* add default fields here + m_xLbLineStyles->Fill( pDashList ); +} + +void SvxLineDefTabPage::ActivatePage( const SfxItemSet& ) +{ + if( nDlgType != 0 ) // area dialog + return; + + // ActivatePage() is called before the dialog receives PageCreated() !!! + if( !pDashList.is() ) + return; + + if (*pPageType == PageType::Gradient && + *pPosDashLb != -1) + { + m_xLbLineStyles->set_active(*pPosDashLb); + } + // so that a possibly existing line style is discarded + SelectLinestyleHdl_Impl( nullptr ); + + // determining (and possibly cutting) the name + // and displaying it in the GroupBox +// OUString aString( CuiResId( RID_SVXSTR_TABLE ) ); +// aString += ": "; + INetURLObject aURL( pDashList->GetPath() ); + + aURL.Append( pDashList->GetName() ); + DBG_ASSERT( aURL.GetProtocol() != INetProtocol::NotValid, "invalid URL" ); + + *pPageType = PageType::Area; // 2 + *pPosDashLb = -1; +} + + +DeactivateRC SvxLineDefTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + CheckChanges_Impl(); + + if( _pSet ) + FillItemSet( _pSet ); + + return DeactivateRC::LeavePage; +} + +void SvxLineDefTabPage::CheckChanges_Impl() +{ + // is here used to NOT lose changes + //css::drawing::DashStyle eXDS; + + if( m_xNumFldNumber1->get_value_changed_from_saved() || + m_xMtrLength1->get_value_changed_from_saved() || + m_xLbType1->get_value_changed_from_saved() || + m_xNumFldNumber2->get_value_changed_from_saved() || + m_xMtrLength2->get_value_changed_from_saved() || + m_xLbType2->get_value_changed_from_saved() || + m_xMtrDistance->get_value_changed_from_saved() ) + { + std::unique_ptr xMessDlg(Application::CreateMessageDialog(GetFrameWeld(), + VclMessageType::Warning, VclButtonsType::Cancel, + CuiResId(RID_SVXSTR_ASK_CHANGE_LINESTYLE))); + xMessDlg->set_title(SvxResId(RID_SVXSTR_LINESTYLE)); + xMessDlg->add_button(CuiResId(RID_SVXSTR_CHANGE), RET_BTN_1); + xMessDlg->add_button(CuiResId(RID_SVXSTR_ADD), RET_BTN_2); + + short nRet = xMessDlg->run(); + + switch( nRet ) + { + case RET_BTN_1: + { + ClickModifyHdl_Impl(*m_xBtnModify); + } + break; + + case RET_BTN_2: + { + ClickAddHdl_Impl(*m_xBtnAdd); + } + break; + + case RET_CANCEL: + break; + } + } + + int nPos = m_xLbLineStyles->get_active(); + if (nPos != -1) + { + *pPosDashLb = nPos; + } +} + + +bool SvxLineDefTabPage::FillItemSet( SfxItemSet* rAttrs ) +{ + if( nDlgType == 0 ) // line dialog + { + if( *pPageType == PageType::Hatch ) + { + FillDash_Impl(); + + OUString aString(m_xLbLineStyles->get_active_text()); + rAttrs->Put( XLineStyleItem( drawing::LineStyle_DASH ) ); + rAttrs->Put( XLineDashItem( aString, aDash ) ); + } + } + return true; +} + + +void SvxLineDefTabPage::Reset( const SfxItemSet* rAttrs ) +{ + if( rAttrs->GetItemState( GetWhich( XATTR_LINESTYLE ) ) != SfxItemState::DONTCARE ) + { + drawing::LineStyle eXLS = static_cast( rAttrs->Get( GetWhich( XATTR_LINESTYLE ) ) ).GetValue(); + + switch( eXLS ) + { + case drawing::LineStyle_NONE: + case drawing::LineStyle_SOLID: + m_xLbLineStyles->set_active(0); + break; + case drawing::LineStyle_DASH: + { + const XLineDashItem& rDashItem = rAttrs->Get( XATTR_LINEDASH ); + aDash = rDashItem.GetDashValue(); + + m_xLbLineStyles->set_active(-1); + m_xLbLineStyles->set_active_text(rDashItem.GetName()); + break; + } + default: + break; + } + } + SelectLinestyleHdl_Impl( nullptr ); + + // determine button state + if( pDashList->Count() ) + { + m_xBtnModify->set_sensitive(true); + m_xBtnDelete->set_sensitive(true); + m_xBtnSave->set_sensitive(true); + } + else + { + m_xBtnModify->set_sensitive(false); + m_xBtnDelete->set_sensitive(false); + m_xBtnSave->set_sensitive(false); + } +} + +std::unique_ptr SvxLineDefTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rOutAttrs ) +{ + return std::make_unique(pPage, pController, *rOutAttrs); +} + +IMPL_LINK(SvxLineDefTabPage, SelectLinestyleListBoxHdl_Impl, weld::ComboBox&, rListBox, void) +{ + SelectLinestyleHdl_Impl(&rListBox); +} + +void SvxLineDefTabPage::SelectLinestyleHdl_Impl(const weld::ComboBox* p) +{ + if(!pDashList->Count()) + return; + + int nTmp = m_xLbLineStyles->get_active(); + if (nTmp == -1) + { + OSL_ENSURE(false, "OOps, non-existent LineDash selected (!)"); + nTmp = 1; + } + + aDash = pDashList->GetDash( nTmp )->GetDash(); + + FillDialog_Impl(); + + rXLSet.Put( XLineDashItem( OUString(), aDash ) ); + + // #i34740# + m_aCtlPreview.SetLineAttributes(aXLineAttr.GetItemSet()); + m_aCtlPreview.Invalidate(); + + // Is not set before, in order to take the new style + // only if there was an entry selected in the ListBox. + // If it was called via Reset(), then p is == NULL + if( p ) + *pPageType = PageType::Hatch; +} + +IMPL_LINK_NOARG(SvxLineDefTabPage, ChangePreviewHdl_Impl, weld::MetricSpinButton&, void) +{ + FillDash_Impl(); + m_aCtlPreview.Invalidate(); +} + +IMPL_LINK_NOARG(SvxLineDefTabPage, ChangeNumber1Hdl_Impl, weld::SpinButton&, void) +{ + if (m_xNumFldNumber1->get_value() == 0) + { + m_xNumFldNumber2->set_min(1); + } + else + { + m_xNumFldNumber2->set_min(0); + } + + ChangePreviewHdl_Impl(*m_xMtrLength1); +} + +IMPL_LINK_NOARG(SvxLineDefTabPage, ChangeNumber2Hdl_Impl, weld::SpinButton&, void) +{ + if (m_xNumFldNumber2->get_value() == 0) + { + m_xNumFldNumber1->set_min(1); + } + else + { + m_xNumFldNumber1->set_min(0); + } + + ChangePreviewHdl_Impl(*m_xMtrLength1); +} + +IMPL_LINK( SvxLineDefTabPage, ChangeMetricHdl_Impl, weld::ToggleButton&, r, void) +{ + ChangeMetricHdl_Impl(&r); +} + +void SvxLineDefTabPage::ChangeMetricHdl_Impl(const weld::ToggleButton* p) +{ + if( !m_xCbxSynchronize->get_active() && m_xMtrLength1->get_unit() != eFUnit ) + { + long nTmp1, nTmp2, nTmp3; + + // was changed with Control + if( p ) + { + nTmp1 = GetCoreValue( *m_xMtrLength1, ePoolUnit ) * XOUT_WIDTH / 100; + nTmp2 = GetCoreValue( *m_xMtrLength2, ePoolUnit ) * XOUT_WIDTH / 100; + nTmp3 = GetCoreValue( *m_xMtrDistance, ePoolUnit ) * XOUT_WIDTH / 100; + } + else + { + nTmp1 = GetCoreValue( *m_xMtrLength1, ePoolUnit ); + nTmp2 = GetCoreValue( *m_xMtrLength2, ePoolUnit ); + nTmp3 = GetCoreValue( *m_xMtrDistance, ePoolUnit ); + } + m_xMtrLength1->set_digits(2); + m_xMtrLength2->set_digits(2); + m_xMtrDistance->set_digits(2); + + // adjust metric + m_xMtrLength1->set_unit(eFUnit); + m_xMtrLength2->set_unit(eFUnit); + m_xMtrDistance->set_unit(eFUnit); + + // tdf#126736 max 5cm + m_xMtrLength1->set_range(0, 500, FieldUnit::CM); + m_xMtrLength2->set_range(0, 500, FieldUnit::CM); + m_xMtrDistance->set_range(0, 500, FieldUnit::CM); + + SetMetricValue( *m_xMtrLength1, nTmp1, ePoolUnit ); + SetMetricValue( *m_xMtrLength2, nTmp2, ePoolUnit ); + SetMetricValue( *m_xMtrDistance, nTmp3, ePoolUnit ); + } + else if( m_xCbxSynchronize->get_active() && m_xMtrLength1->get_unit() != FieldUnit::PERCENT ) + { + long nTmp1, nTmp2, nTmp3; + + // was changed with Control + if( p ) + { + nTmp1 = GetCoreValue( *m_xMtrLength1, ePoolUnit ) * 100 / XOUT_WIDTH; + nTmp2 = GetCoreValue( *m_xMtrLength2, ePoolUnit ) * 100 / XOUT_WIDTH; + nTmp3 = GetCoreValue( *m_xMtrDistance, ePoolUnit ) * 100 / XOUT_WIDTH; + } + else + { + nTmp1 = GetCoreValue( *m_xMtrLength1, ePoolUnit ); + nTmp2 = GetCoreValue( *m_xMtrLength2, ePoolUnit ); + nTmp3 = GetCoreValue( *m_xMtrDistance, ePoolUnit ); + } + + m_xMtrLength1->set_digits(0); + m_xMtrLength2->set_digits(0); + m_xMtrDistance->set_digits(0); + + m_xMtrLength1->set_unit(FieldUnit::PERCENT); + m_xMtrLength2->set_unit(FieldUnit::PERCENT); + m_xMtrDistance->set_unit(FieldUnit::PERCENT); + + // tdf#126736 800% + m_xMtrLength1->set_range(0, 800, FieldUnit::PERCENT); + m_xMtrLength2->set_range(0, 800, FieldUnit::PERCENT); + m_xMtrDistance->set_range(0, 800, FieldUnit::PERCENT); + + m_xMtrLength1->set_value(nTmp1, FieldUnit::PERCENT); + m_xMtrLength2->set_value(nTmp2, FieldUnit::PERCENT); + m_xMtrDistance->set_value(nTmp3, FieldUnit::PERCENT); + } + SelectTypeHdl_Impl( nullptr ); +} + +IMPL_LINK( SvxLineDefTabPage, SelectTypeListBoxHdl_Impl, weld::ComboBox&, rListBox, void ) +{ + SelectTypeHdl_Impl(&rListBox); +} + +void SvxLineDefTabPage::SelectTypeHdl_Impl(const weld::ComboBox* p) +{ + if (p == m_xLbType1.get() || !p) + { + if (m_xLbType1->get_active() == 0) + { + m_xMtrLength1->set_sensitive(false); + m_xMtrLength1->set_text(""); + } + else if (!m_xMtrLength1->get_sensitive()) + { + m_xMtrLength1->set_sensitive(true); + m_xMtrLength1->reformat(); + } + } + + if (p == m_xLbType2.get() || !p) + { + if (m_xLbType2->get_active() == 0) + { + m_xMtrLength2->set_sensitive(false); + m_xMtrLength2->set_text(""); + } + else if (!m_xMtrLength2->get_sensitive()) + { + m_xMtrLength2->set_sensitive(true); + m_xMtrLength2->reformat(); + } + } + ChangePreviewHdl_Impl(*m_xMtrLength1); +} + +IMPL_LINK_NOARG(SvxLineDefTabPage, ClickAddHdl_Impl, weld::Button&, void) +{ + OUString aNewName(SvxResId(RID_SVXSTR_LINESTYLE)); + OUString aDesc(CuiResId(RID_SVXSTR_DESC_LINESTYLE)); + OUString aName; + + long nCount = pDashList->Count(); + long j = 1; + bool bDifferent = false; + + while ( !bDifferent ) + { + aName = aNewName + " " + OUString::number( j++ ); + bDifferent = true; + + for ( long i = 0; i < nCount && bDifferent; i++ ) + if ( aName == pDashList->GetDash( i )->GetName() ) + bDifferent = false; + } + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateSvxNameDialog(GetFrameWeld(), aName, aDesc)); + bool bLoop = true; + + while ( bLoop && pDlg->Execute() == RET_OK ) + { + pDlg->GetName( aName ); + bDifferent = true; + + for( long i = 0; i < nCount && bDifferent; i++ ) + { + if( aName == pDashList->GetDash( i )->GetName() ) + bDifferent = false; + } + + if( bDifferent ) + { + bLoop = false; + FillDash_Impl(); + + long nDashCount = pDashList->Count(); + pDashList->Insert( std::make_unique(aDash, aName), nDashCount ); + m_xLbLineStyles->Append( *pDashList->GetDash(nDashCount), pDashList->GetUiBitmap(nDashCount) ); + + m_xLbLineStyles->set_active(m_xLbLineStyles->get_count() - 1); + + *pnDashListState |= ChangeType::MODIFIED; + + *pPageType = PageType::Hatch; + + // save values for changes recognition (-> method) + m_xNumFldNumber1->save_value(); + m_xMtrLength1->save_value(); + m_xLbType1->save_value(); + m_xNumFldNumber2->save_value(); + m_xMtrLength2->save_value(); + m_xLbType2->save_value(); + m_xMtrDistance->save_value(); + } + else + { + std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/queryduplicatedialog.ui")); + std::unique_ptr xBox(xBuilder->weld_message_dialog("DuplicateNameDialog")); + xBox->run(); + } + } + pDlg.disposeAndClear(); + + // determine button state + if ( pDashList->Count() ) + { + m_xBtnModify->set_sensitive(true); + m_xBtnDelete->set_sensitive(true); + m_xBtnSave->set_sensitive(true); + } +} + +IMPL_LINK_NOARG(SvxLineDefTabPage, ClickModifyHdl_Impl, weld::Button&, void) +{ + int nPos = m_xLbLineStyles->get_active(); + if (nPos == -1) + return; + + OUString aDesc(CuiResId(RID_SVXSTR_DESC_LINESTYLE)); + OUString aName( pDashList->GetDash( nPos )->GetName() ); + OUString aOldName = aName; + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateSvxNameDialog(GetFrameWeld(), aName, aDesc)); + + long nCount = pDashList->Count(); + bool bLoop = true; + + while ( bLoop && pDlg->Execute() == RET_OK ) + { + pDlg->GetName( aName ); + bool bDifferent = true; + + for( long i = 0; i < nCount && bDifferent; i++ ) + { + if( aName == pDashList->GetDash( i )->GetName() && + aName != aOldName ) + bDifferent = false; + } + + if ( bDifferent ) + { + bLoop = false; + FillDash_Impl(); + + pDashList->Replace(std::make_unique(aDash, aName), nPos); + m_xLbLineStyles->Modify(*pDashList->GetDash(nPos), nPos, pDashList->GetUiBitmap(nPos)); + + m_xLbLineStyles->set_active(nPos); + + *pnDashListState |= ChangeType::MODIFIED; + + *pPageType = PageType::Hatch; + + // save values for changes recognition (-> method) + m_xNumFldNumber1->save_value(); + m_xMtrLength1->save_value(); + m_xLbType1->save_value(); + m_xNumFldNumber2->save_value(); + m_xMtrLength2->save_value(); + m_xLbType2->save_value(); + m_xMtrDistance->save_value(); + } + else + { + std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/queryduplicatedialog.ui")); + std::unique_ptr xBox(xBuilder->weld_message_dialog("DuplicateNameDialog")); + xBox->run(); + } + } +} + +IMPL_LINK_NOARG(SvxLineDefTabPage, ClickDeleteHdl_Impl, weld::Button&, void) +{ + int nPos = m_xLbLineStyles->get_active(); + if (nPos != -1) + { + std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querydeletelinestyledialog.ui")); + std::unique_ptr xQueryBox(xBuilder->weld_message_dialog("AskDelLineStyleDialog")); + if (xQueryBox->run() == RET_YES) + { + pDashList->Remove(nPos); + m_xLbLineStyles->remove(nPos); + m_xLbLineStyles->set_active(0); + + SelectLinestyleHdl_Impl( nullptr ); + *pPageType = PageType::Area; // style should not be taken + + *pnDashListState |= ChangeType::MODIFIED; + + ChangePreviewHdl_Impl( *m_xMtrLength1 ); + } + } + + // determine button state + if ( !pDashList->Count() ) + { + m_xBtnModify->set_sensitive(false); + m_xBtnDelete->set_sensitive(false); + m_xBtnSave->set_sensitive(false); + } +} + +IMPL_LINK_NOARG(SvxLineDefTabPage, ClickLoadHdl_Impl, weld::Button&, void) +{ + sal_uInt16 nReturn = RET_YES; + + if ( *pnDashListState & ChangeType::MODIFIED ) + { + std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querysavelistdialog.ui")); + std::unique_ptr xBox(xBuilder->weld_message_dialog("AskSaveList")); + + nReturn = xBox->run(); + + if ( nReturn == RET_YES ) + pDashList->Save(); + } + + if ( nReturn != RET_CANCEL ) + { + ::sfx2::FileDialogHelper aDlg(css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE, + FileDialogFlags::NONE, GetFrameWeld()); + OUString aStrFilterType( "*.sod" ); + aDlg.AddFilter( aStrFilterType, aStrFilterType ); + OUString aPalettePath(SvtPathOptions().GetPalettePath()); + OUString aLastDir; + sal_Int32 nIndex = 0; + do + { + aLastDir = aPalettePath.getToken(0, ';', nIndex); + } + while (nIndex >= 0); + + INetURLObject aFile(aLastDir); + aDlg.SetDisplayDirectory( aFile.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); + + if( aDlg.Execute() == ERRCODE_NONE ) + { + INetURLObject aURL( aDlg.GetPath() ); + INetURLObject aPathURL( aURL ); + + aPathURL.removeSegment(); + aPathURL.removeFinalSlash(); + + XDashListRef pDshLst = XPropertyList::AsDashList(XPropertyList::CreatePropertyList( XPropertyListType::Dash, aPathURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), "" )); + pDshLst->SetName( aURL.getName() ); + + if( pDshLst->Load() ) + { + pDashList = pDshLst; + static_cast(GetDialogController())->SetNewDashList( pDashList ); + + m_xLbLineStyles->clear(); + m_xLbLineStyles->Fill( pDashList ); + Reset( &rOutAttrs ); + + pDashList->SetName( aURL.getName() ); + + *pnDashListState |= ChangeType::CHANGED; + *pnDashListState &= ~ChangeType::MODIFIED; + } + else + { + std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querynoloadedfiledialog.ui")); + std::unique_ptr xBox(xBuilder->weld_message_dialog("NoLoadedFileDialog")); + xBox->run(); + } + } + } + + // determine button state + if ( pDashList->Count() ) + { + m_xBtnModify->set_sensitive(true); + m_xBtnDelete->set_sensitive(true); + m_xBtnSave->set_sensitive(true); + } + else + { + m_xBtnModify->set_sensitive(false); + m_xBtnDelete->set_sensitive(false); + m_xBtnSave->set_sensitive(false); + } +} + +IMPL_LINK_NOARG(SvxLineDefTabPage, ClickSaveHdl_Impl, weld::Button&, void) +{ + ::sfx2::FileDialogHelper aDlg(css::ui::dialogs::TemplateDescription::FILESAVE_SIMPLE, FileDialogFlags::NONE, GetFrameWeld()); + OUString aStrFilterType( "*.sod" ); + aDlg.AddFilter( aStrFilterType, aStrFilterType ); + + OUString aPalettePath(SvtPathOptions().GetPalettePath()); + OUString aLastDir; + sal_Int32 nIndex = 0; + do + { + aLastDir = aPalettePath.getToken(0, ';', nIndex); + } + while (nIndex >= 0); + + INetURLObject aFile(aLastDir); + DBG_ASSERT( aFile.GetProtocol() != INetProtocol::NotValid, "invalid URL" ); + + if( !pDashList->GetName().isEmpty() ) + { + aFile.Append( pDashList->GetName() ); + + if( aFile.getExtension().isEmpty() ) + aFile.SetExtension( "sod" ); + } + + aDlg.SetDisplayDirectory( aFile.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); + if ( aDlg.Execute() != ERRCODE_NONE ) + return; + + INetURLObject aURL( aDlg.GetPath() ); + INetURLObject aPathURL( aURL ); + + aPathURL.removeSegment(); + aPathURL.removeFinalSlash(); + + pDashList->SetName( aURL.getName() ); + pDashList->SetPath( aPathURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); + + if( pDashList->Save() ) + { + *pnDashListState &= ~ChangeType::MODIFIED; + } + else + { + std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querynosavefiledialog.ui")); + std::unique_ptr xBox(xBuilder->weld_message_dialog("NoSaveFileDialog")); + xBox->run(); + } +} + +void SvxLineDefTabPage::FillDash_Impl() +{ + css::drawing::DashStyle eXDS; + + if (m_xCbxSynchronize->get_active()) + eXDS = css::drawing::DashStyle_RECTRELATIVE; + else + eXDS = css::drawing::DashStyle_RECT; + + aDash.SetDashStyle( eXDS ); + aDash.SetDots( static_cast(m_xNumFldNumber1->get_value()) ); + aDash.SetDotLen( m_xLbType1->get_active() == 0 ? 0 : GetCoreValue( *m_xMtrLength1, ePoolUnit ) ); + aDash.SetDashes( static_cast(m_xNumFldNumber2->get_value()) ); + aDash.SetDashLen( m_xLbType2->get_active() == 0 ? 0 : GetCoreValue( *m_xMtrLength2, ePoolUnit ) ); + aDash.SetDistance( GetCoreValue( *m_xMtrDistance, ePoolUnit ) ); + + rXLSet.Put( XLineDashItem( OUString(), aDash ) ); + + // #i34740# + m_aCtlPreview.SetLineAttributes(aXLineAttr.GetItemSet()); +} + +void SvxLineDefTabPage::FillDialog_Impl() +{ + css::drawing::DashStyle eXDS = aDash.GetDashStyle(); // css::drawing::DashStyle_RECT, css::drawing::DashStyle_ROUND + if( eXDS == css::drawing::DashStyle_RECTRELATIVE ) + m_xCbxSynchronize->set_active(true); + else + m_xCbxSynchronize->set_active(false); + + m_xNumFldNumber1->set_value(aDash.GetDots()); + SetMetricValue( *m_xMtrLength1, aDash.GetDotLen(), ePoolUnit ); + m_xLbType1->set_active(aDash.GetDotLen() == 0 ? 0 : 1); + m_xNumFldNumber2->set_value(aDash.GetDashes()); + SetMetricValue( *m_xMtrLength2, aDash.GetDashLen(), ePoolUnit ); + m_xLbType2->set_active(aDash.GetDashLen() == 0 ? 0 : 1); + SetMetricValue( *m_xMtrDistance, aDash.GetDistance(), ePoolUnit ); + + ChangeMetricHdl_Impl(nullptr); + + // save values for changes recognition (-> method) + m_xNumFldNumber1->save_value(); + m_xMtrLength1->save_value(); + m_xLbType1->save_value(); + m_xNumFldNumber2->save_value(); + m_xMtrLength2->save_value(); + m_xLbType2->save_value(); + m_xMtrDistance->save_value(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/tplneend.cxx b/cui/source/tabpages/tplneend.cxx new file mode 100644 index 000000000..a9db979bc --- /dev/null +++ b/cui/source/tabpages/tplneend.cxx @@ -0,0 +1,609 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define XOUT_WIDTH 150 + +SvxLineEndDefTabPage::SvxLineEndDefTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "cui/ui/lineendstabpage.ui", "LineEndPage", &rInAttrs) + , rOutAttrs(rInAttrs) + , pPolyObj(nullptr) + , aXLineAttr(rInAttrs.GetPool()) + , rXLSet(aXLineAttr.GetItemSet()) + , pnLineEndListState(nullptr) + , pPageType(nullptr) + , nDlgType(0) + , pPosLineEndLb(nullptr) + , m_xEdtName(m_xBuilder->weld_entry("EDT_NAME")) + , m_xLbLineEnds(new SvxLineEndLB(m_xBuilder->weld_combo_box("LB_LINEENDS"))) + , m_xBtnAdd(m_xBuilder->weld_button("BTN_ADD")) + , m_xBtnModify(m_xBuilder->weld_button("BTN_MODIFY")) + , m_xBtnDelete(m_xBuilder->weld_button("BTN_DELETE")) + , m_xBtnLoad(m_xBuilder->weld_button("BTN_LOAD")) + , m_xBtnSave(m_xBuilder->weld_button("BTN_SAVE")) + , m_xCtlPreview(new weld::CustomWeld(*m_xBuilder, "CTL_PREVIEW", m_aCtlPreview)) +{ + // this page needs ExchangeSupport + SetExchangeSupport(); + + rXLSet.Put( XLineStyleItem(css::drawing::LineStyle_SOLID) ); + rXLSet.Put( XLineWidthItem(XOUT_WIDTH) ); + rXLSet.Put( XLineColorItem( OUString(), COL_BLACK ) ); + rXLSet.Put( XLineStartWidthItem( m_aCtlPreview.GetOutputSize().Height() / 2 ) ); + rXLSet.Put( XLineEndWidthItem( m_aCtlPreview.GetOutputSize().Height() / 2 ) ); + + // #i34740# + m_aCtlPreview.SetLineAttributes(aXLineAttr.GetItemSet()); + + m_xBtnAdd->connect_clicked(LINK(this, SvxLineEndDefTabPage, ClickAddHdl_Impl)); + m_xBtnModify->connect_clicked(LINK( this, SvxLineEndDefTabPage, ClickModifyHdl_Impl)); + m_xBtnDelete->connect_clicked(LINK( this, SvxLineEndDefTabPage, ClickDeleteHdl_Impl)); + m_xBtnLoad->connect_clicked(LINK( this, SvxLineEndDefTabPage, ClickLoadHdl_Impl)); + m_xBtnSave->connect_clicked(LINK( this, SvxLineEndDefTabPage, ClickSaveHdl_Impl)); + + m_xLbLineEnds->connect_changed(LINK(this, SvxLineEndDefTabPage, SelectLineEndHdl_Impl)); +} + +SvxLineEndDefTabPage::~SvxLineEndDefTabPage() +{ + m_xCtlPreview.reset(); + m_xLbLineEnds.reset(); +} + +void SvxLineEndDefTabPage::Construct() +{ + m_xLbLineEnds->Fill( pLineEndList ); + + bool bCreateArrowPossible = true; + + if( !pPolyObj ) + { + bCreateArrowPossible = false; + } + else if( nullptr == dynamic_cast( pPolyObj) ) + { + SdrObjTransformInfoRec aInfoRec; + pPolyObj->TakeObjInfo( aInfoRec ); + SdrObjectUniquePtr pNewObj; + if( aInfoRec.bCanConvToPath ) + pNewObj = pPolyObj->ConvertToPolyObj( true, false ); + + bCreateArrowPossible = nullptr != dynamic_cast( pNewObj.get()); + } + + if( !bCreateArrowPossible ) + m_xBtnAdd->set_sensitive(false); +} + +void SvxLineEndDefTabPage::ActivatePage( const SfxItemSet& ) +{ + if( nDlgType != 0 ) // area dialog + return; + + // ActivatePage() is called before the dialog receives PageCreated() !!! + if( !pLineEndList.is() ) + return; + + if( *pPosLineEndLb != -1) + { + m_xLbLineEnds->set_active(*pPosLineEndLb); + SelectLineEndHdl_Impl(); + } + INetURLObject aURL( pLineEndList->GetPath() ); + + aURL.Append( pLineEndList->GetName() ); + DBG_ASSERT( aURL.GetProtocol() != INetProtocol::NotValid, "invalid URL" ); + *pPageType = PageType::Area; // 3 + *pPosLineEndLb = -1; +} + + +DeactivateRC SvxLineEndDefTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + CheckChanges_Impl(); + + if( _pSet ) + FillItemSet( _pSet ); + + return DeactivateRC::LeavePage; +} + + +void SvxLineEndDefTabPage::CheckChanges_Impl() +{ + int nPos = m_xLbLineEnds->get_active(); + + if (nPos != -1) + { + OUString aString = m_xEdtName->get_text(); + + if( aString != m_xLbLineEnds->get_active_text() ) + { + std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querychangelineenddialog.ui")); + std::unique_ptr xQueryBox(xBuilder->weld_message_dialog("AskChangeLineEndDialog")); + if (xQueryBox->run() == RET_YES) + ClickModifyHdl_Impl(*m_xBtnModify); + } + } + nPos = m_xLbLineEnds->get_active(); + + if (nPos != -1) + *pPosLineEndLb = nPos; +} + + +bool SvxLineEndDefTabPage::FillItemSet( SfxItemSet* rSet ) +{ + if( nDlgType == 0 ) // line dialog + { + if( *pPageType == PageType::Bitmap ) + { + CheckChanges_Impl(); + + int nPos = m_xLbLineEnds->get_active(); + const XLineEndEntry* pEntry = pLineEndList->GetLineEnd(nPos); + + rSet->Put( XLineStartItem( pEntry->GetName(), pEntry->GetLineEnd() ) ); + rSet->Put( XLineEndItem( pEntry->GetName(), pEntry->GetLineEnd() ) ); + } + } + return true; +} + +void SvxLineEndDefTabPage::Reset( const SfxItemSet* ) +{ + m_xLbLineEnds->set_active(0); + + // Update lineend + if( pLineEndList->Count() > 0 ) + { + int nPos = m_xLbLineEnds->get_active(); + + const XLineEndEntry* pEntry = pLineEndList->GetLineEnd(nPos); + + m_xEdtName->set_text(m_xLbLineEnds->get_active_text()); + + rXLSet.Put( XLineStartItem( OUString(), pEntry->GetLineEnd() ) ); + rXLSet.Put( XLineEndItem( OUString(), pEntry->GetLineEnd() ) ); + + // #i34740# + m_aCtlPreview.SetLineAttributes(aXLineAttr.GetItemSet()); + m_aCtlPreview.Invalidate(); + } + + // determine button state + if( pLineEndList->Count() ) + { + m_xBtnModify->set_sensitive(true); + m_xBtnDelete->set_sensitive(true); + m_xBtnSave->set_sensitive(true); + } + else + { + m_xBtnModify->set_sensitive(false); + m_xBtnDelete->set_sensitive(false); + m_xBtnSave->set_sensitive(false); + } +} + +std::unique_ptr SvxLineEndDefTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet) +{ + return std::make_unique(pPage, pController, *rSet ); +} + +void SvxLineEndDefTabPage::SelectLineEndHdl_Impl() +{ + if( pLineEndList->Count() <= 0 ) + return; + + int nPos = m_xLbLineEnds->get_active(); + + const XLineEndEntry* pEntry = pLineEndList->GetLineEnd(nPos); + + m_xEdtName->set_text(m_xLbLineEnds->get_active_text()); + + rXLSet.Put( XLineStartItem( OUString(), pEntry->GetLineEnd() ) ); + rXLSet.Put( XLineEndItem( OUString(), pEntry->GetLineEnd() ) ); + + // #i34740# + m_aCtlPreview.SetLineAttributes(aXLineAttr.GetItemSet()); + m_aCtlPreview.Invalidate(); + + // Is not set before, in order to only take the new style, + // if there is an entry selected in the ListBox + *pPageType = PageType::Bitmap; +} + +IMPL_LINK_NOARG(SvxLineEndDefTabPage, SelectLineEndHdl_Impl, weld::ComboBox&, void) +{ + SelectLineEndHdl_Impl(); +} + +IMPL_LINK_NOARG(SvxLineEndDefTabPage, ClickModifyHdl_Impl, weld::Button&, void) +{ + int nPos = m_xLbLineEnds->get_active(); + if (nPos == -1) + return; + + OUString aDesc(CuiResId(RID_SVXSTR_DESC_LINEEND)); + OUString aName(m_xEdtName->get_text()); + long nCount = pLineEndList->Count(); + bool bDifferent = true; + + // check whether the name is existing already + for ( long i = 0; i < nCount && bDifferent; i++ ) + if ( aName == pLineEndList->GetLineEnd( i )->GetName() ) + bDifferent = false; + + // if yes, repeat and demand a new name + if ( !bDifferent ) + { + std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/queryduplicatedialog.ui")); + std::unique_ptr xWarningBox(xBuilder->weld_message_dialog("DuplicateNameDialog")); + xWarningBox->run(); + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateSvxNameDialog(GetFrameWeld(), aName, aDesc)); + bool bLoop = true; + + while( !bDifferent && bLoop && pDlg->Execute() == RET_OK ) + { + pDlg->GetName( aName ); + bDifferent = true; + + for( long i = 0; i < nCount && bDifferent; i++ ) + { + if( aName == pLineEndList->GetLineEnd( i )->GetName() ) + bDifferent = false; + } + + if( bDifferent ) + bLoop = false; + else + xWarningBox->run(); + } + } + + // if not existing, enter the entry + if( !bDifferent ) + return; + + const XLineEndEntry* pOldEntry = pLineEndList->GetLineEnd(nPos); + + if(pOldEntry) + { + // #123497# Need to replace the existing entry with a new one + pLineEndList->Replace(std::make_unique(pOldEntry->GetLineEnd(), aName), nPos); + + m_xEdtName->set_text(aName); + + m_xLbLineEnds->Modify(*pLineEndList->GetLineEnd(nPos), nPos, pLineEndList->GetUiBitmap(nPos)); + m_xLbLineEnds->set_active(nPos); + + // set flag for modified + *pnLineEndListState |= ChangeType::MODIFIED; + + *pPageType = PageType::Bitmap; + } + else + { + OSL_ENSURE(false, "LineEnd to be modified not existing (!)"); + } +} + +IMPL_LINK_NOARG(SvxLineEndDefTabPage, ClickAddHdl_Impl, weld::Button&, void) +{ + if( pPolyObj ) + { + const SdrObject* pNewObj; + SdrObjectUniquePtr pConvPolyObj; + + if( nullptr != dynamic_cast( pPolyObj) ) + { + pNewObj = pPolyObj; + } + else + { + SdrObjTransformInfoRec aInfoRec; + pPolyObj->TakeObjInfo( aInfoRec ); + + if( aInfoRec.bCanConvToPath ) + { + pConvPolyObj = pPolyObj->ConvertToPolyObj( true, false ); + pNewObj = pConvPolyObj.get(); + + if( !pNewObj || nullptr == dynamic_cast( pNewObj) ) + return; // cancel, additional safety, which + // has no use for group objects though. + } + else return; // cancel + } + + basegfx::B2DPolyPolygon aNewPolyPolygon(static_cast(pNewObj)->GetPathPoly()); + basegfx::B2DRange aNewRange(basegfx::utils::getRange(aNewPolyPolygon)); + + // normalize + aNewPolyPolygon.transform(basegfx::utils::createTranslateB2DHomMatrix( -aNewRange.getMinX(), -aNewRange.getMinY())); + + pConvPolyObj.reset(); + + OUString aNewName(SvxResId(RID_SVXSTR_LINEEND)); + OUString aDesc(CuiResId(RID_SVXSTR_DESC_LINEEND)); + OUString aName; + + long nCount = pLineEndList->Count(); + long j = 1; + bool bDifferent = false; + + while ( !bDifferent ) + { + aName = aNewName + " " + OUString::number( j++ ); + bDifferent = true; + + for( long i = 0; i < nCount && bDifferent; i++ ) + if ( aName == pLineEndList->GetLineEnd( i )->GetName() ) + bDifferent = false; + } + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateSvxNameDialog(GetFrameWeld(), aName, aDesc )); + bool bLoop = true; + + while ( bLoop && pDlg->Execute() == RET_OK ) + { + pDlg->GetName( aName ); + bDifferent = true; + + for( long i = 0; i < nCount && bDifferent; i++ ) + { + if( aName == pLineEndList->GetLineEnd( i )->GetName() ) + bDifferent = false; + } + + if( bDifferent ) + { + bLoop = false; + + auto nLineEndCount = pLineEndList->Count(); + pLineEndList->Insert(std::make_unique(aNewPolyPolygon, aName), nLineEndCount); + + // add to the ListBox + m_xLbLineEnds->Append(*pLineEndList->GetLineEnd(nLineEndCount), pLineEndList->GetUiBitmap(nLineEndCount)); + m_xLbLineEnds->set_active(m_xLbLineEnds->get_count() - 1); + + *pnLineEndListState |= ChangeType::MODIFIED; + + SelectLineEndHdl_Impl(); + } + else + { + std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/queryduplicatedialog.ui")); + std::unique_ptr xWarningBox(xBuilder->weld_message_dialog("DuplicateNameDialog")); + xWarningBox->run(); + } + } + } + else + m_xBtnAdd->set_sensitive(false); + + // determine button state + if ( pLineEndList->Count() ) + { + m_xBtnModify->set_sensitive(true); + m_xBtnDelete->set_sensitive(true); + m_xBtnSave->set_sensitive(true); + } +} + +IMPL_LINK_NOARG(SvxLineEndDefTabPage, ClickDeleteHdl_Impl, weld::Button&, void) +{ + int nPos = m_xLbLineEnds->get_active(); + + if (nPos != -1) + { + std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querydeletelineenddialog.ui")); + std::unique_ptr xQueryBox(xBuilder->weld_message_dialog("AskDelLineEndDialog")); + + if (xQueryBox->run() == RET_YES) + { + pLineEndList->Remove(nPos); + m_xLbLineEnds->remove(nPos); + m_xLbLineEnds->set_active(0); + + SelectLineEndHdl_Impl(); + *pPageType = PageType::Area; // LineEnd shall not be taken over + + *pnLineEndListState |= ChangeType::MODIFIED; + + m_aCtlPreview.Invalidate(); + } + } + // determine button state + if( !pLineEndList->Count() ) + { + m_xBtnModify->set_sensitive(false); + m_xBtnDelete->set_sensitive(false); + m_xBtnSave->set_sensitive(false); + } +} + +IMPL_LINK_NOARG(SvxLineEndDefTabPage, ClickLoadHdl_Impl, weld::Button&, void) +{ + sal_uInt16 nReturn = RET_YES; + + if ( *pnLineEndListState & ChangeType::MODIFIED ) + { + std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querysavelistdialog.ui")); + std::unique_ptr xBox(xBuilder->weld_message_dialog("AskSaveList")); + + nReturn = xBox->run(); + + if ( nReturn == RET_YES ) + pLineEndList->Save(); + } + + if ( nReturn != RET_CANCEL ) + { + ::sfx2::FileDialogHelper aDlg(css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE, + FileDialogFlags::NONE, GetFrameWeld()); + OUString aStrFilterType( "*.soe" ); + aDlg.AddFilter( aStrFilterType, aStrFilterType ); + + OUString aPalettePath(SvtPathOptions().GetPalettePath()); + OUString aLastDir; + sal_Int32 nIndex = 0; + do + { + aLastDir = aPalettePath.getToken(0, ';', nIndex); + } + while (nIndex >= 0); + + INetURLObject aFile(aLastDir); + aDlg.SetDisplayDirectory( aFile.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); + + if( aDlg.Execute() == ERRCODE_NONE ) + { + INetURLObject aURL( aDlg.GetPath() ); + INetURLObject aPathURL( aURL ); + + aPathURL.removeSegment(); + aPathURL.removeFinalSlash(); + + XLineEndListRef pLeList = XPropertyList::AsLineEndList( + XPropertyList::CreatePropertyList( + XPropertyListType::LineEnd, + aPathURL.GetMainURL(INetURLObject::DecodeMechanism::NONE), "")); + pLeList->SetName( aURL.getName() ); + if( pLeList->Load() ) + { + pLineEndList = pLeList; + static_cast(GetDialogController())->SetNewLineEndList( pLineEndList ); + m_xLbLineEnds->clear(); + m_xLbLineEnds->Fill( pLineEndList ); + Reset( &rOutAttrs ); + + pLineEndList->SetName( aURL.getName() ); + + *pnLineEndListState |= ChangeType::CHANGED; + *pnLineEndListState &= ~ChangeType::MODIFIED; + } + else + { + std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querynoloadedfiledialog.ui")); + std::unique_ptr xBox(xBuilder->weld_message_dialog("NoLoadedFileDialog")); + xBox->run(); + } + } + } + + // determine button state + if ( pLineEndList->Count() ) + { + m_xBtnModify->set_sensitive(true); + m_xBtnDelete->set_sensitive(true); + m_xBtnSave->set_sensitive(true); + } + else + { + m_xBtnModify->set_sensitive(false); + m_xBtnDelete->set_sensitive(false); + m_xBtnSave->set_sensitive(false); + } +} + +IMPL_LINK_NOARG(SvxLineEndDefTabPage, ClickSaveHdl_Impl, weld::Button&, void) +{ + ::sfx2::FileDialogHelper aDlg(css::ui::dialogs::TemplateDescription::FILESAVE_SIMPLE, FileDialogFlags::NONE, GetFrameWeld()); + OUString aStrFilterType( "*.soe" ); + aDlg.AddFilter( aStrFilterType, aStrFilterType ); + + OUString aPalettePath(SvtPathOptions().GetPalettePath()); + OUString aLastDir; + sal_Int32 nIndex = 0; + do + { + aLastDir = aPalettePath.getToken(0, ';', nIndex); + } + while (nIndex >= 0); + + INetURLObject aFile(aLastDir); + DBG_ASSERT( aFile.GetProtocol() != INetProtocol::NotValid, "invalid URL" ); + + if( !pLineEndList->GetName().isEmpty() ) + { + aFile.Append( pLineEndList->GetName() ); + + if( aFile.getExtension().isEmpty() ) + aFile.SetExtension( "soe" ); + } + + aDlg.SetDisplayDirectory( aFile.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); + if ( aDlg.Execute() != ERRCODE_NONE ) + return; + + INetURLObject aURL( aDlg.GetPath() ); + INetURLObject aPathURL( aURL ); + + aPathURL.removeSegment(); + aPathURL.removeFinalSlash(); + + pLineEndList->SetName( aURL.getName() ); + pLineEndList->SetPath( aPathURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); + + if( pLineEndList->Save() ) + { + *pnLineEndListState &= ~ChangeType::MODIFIED; + } + else + { + std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querynosavefiledialog.ui")); + std::unique_ptr xBox(xBuilder->weld_message_dialog("NoSaveFileDialog")); + xBox->run(); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/tppattern.cxx b/cui/source/tabpages/tppattern.cxx new file mode 100644 index 000000000..a22197d77 --- /dev/null +++ b/cui/source/tabpages/tppattern.cxx @@ -0,0 +1,554 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace com::sun::star; + +/************************************************************************* +|* Preview control for the display of bitmaps +\************************************************************************/ + +class SvxBitmapCtl +{ +private: + Color aPixelColor, aBackgroundColor; + std::array const * pBmpArray; + +public: + // Constructor: BitmapCtl for SvxPixelCtl + SvxBitmapCtl() + : pBmpArray(nullptr) + { + } + + // BitmapCtl: Returns the Bitmap + BitmapEx GetBitmapEx() const + { + if (!pBmpArray) + return BitmapEx(); + return vcl::bitmap::createHistorical8x8FromArray(*pBmpArray, aPixelColor, aBackgroundColor); + } + + void SetBmpArray( std::array const & pPixel ) { pBmpArray = &pPixel; } + void SetPixelColor( Color aColor ) { aPixelColor = aColor; } + void SetBackgroundColor( Color aColor ) { aBackgroundColor = aColor; } +}; + +SvxPatternTabPage::SvxPatternTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SvxTabPage(pPage, pController, "cui/ui/patterntabpage.ui", "PatternTabPage", rInAttrs) + , m_rOutAttrs(rInAttrs) + , m_pnPatternListState(nullptr) + , m_pnColorListState(nullptr) + , m_aXFillAttr(rInAttrs.GetPool()) + , m_rXFSet(m_aXFillAttr.GetItemSet()) + , m_xCtlPixel(new SvxPixelCtl(this)) + , m_xLbColor(new ColorListBox(m_xBuilder->weld_menu_button("LB_COLOR"), pController->getDialog())) + , m_xLbBackgroundColor(new ColorListBox(m_xBuilder->weld_menu_button("LB_BACKGROUND_COLOR"), pController->getDialog())) + , m_xPatternLB(new SvxPresetListBox(m_xBuilder->weld_scrolled_window("patternpresetlistwin"))) + , m_xBtnAdd(m_xBuilder->weld_button("BTN_ADD")) + , m_xBtnModify(m_xBuilder->weld_button("BTN_MODIFY")) + , m_xCtlPixelWin(new weld::CustomWeld(*m_xBuilder, "CTL_PIXEL", *m_xCtlPixel)) + , m_xCtlPreview(new weld::CustomWeld(*m_xBuilder, "CTL_PREVIEW", m_aCtlPreview)) + , m_xPatternLBWin(new weld::CustomWeld(*m_xBuilder, "patternpresetlist", *m_xPatternLB)) +{ + // size of the bitmap display + Size aSize = getDrawPreviewOptimalSize(m_aCtlPreview.GetDrawingArea()->get_ref_device()); + m_xPatternLB->set_size_request(aSize.Width(), aSize.Height()); + m_xCtlPreview->set_size_request(aSize.Width(), aSize.Height()); + + m_xBitmapCtl.reset(new SvxBitmapCtl); + + // this page needs ExchangeSupport + SetExchangeSupport(); + + // setting the output device + m_rXFSet.Put( XFillStyleItem(drawing::FillStyle_BITMAP) ); + m_rXFSet.Put( XFillBitmapItem(OUString(), Graphic()) ); + + m_xBtnAdd->connect_clicked( LINK( this, SvxPatternTabPage, ClickAddHdl_Impl ) ); + m_xBtnModify->connect_clicked( LINK( this, SvxPatternTabPage, ClickModifyHdl_Impl ) ); + + m_xPatternLB->SetSelectHdl( LINK( this, SvxPatternTabPage, ChangePatternHdl_Impl ) ); + m_xPatternLB->SetRenameHdl( LINK( this, SvxPatternTabPage, ClickRenameHdl_Impl ) ); + m_xPatternLB->SetDeleteHdl( LINK( this, SvxPatternTabPage, ClickDeleteHdl_Impl ) ); + m_xLbColor->SetSelectHdl( LINK( this, SvxPatternTabPage, ChangeColorHdl_Impl ) ); + m_xLbBackgroundColor->SetSelectHdl( LINK( this, SvxPatternTabPage, ChangeColorHdl_Impl ) ); +} + +SvxPatternTabPage::~SvxPatternTabPage() +{ + m_xPatternLBWin.reset(); + m_xCtlPreview.reset(); + m_xCtlPixelWin.reset(); + m_xPatternLB.reset(); + m_xLbBackgroundColor.reset(); + m_xLbColor.reset(); + m_xCtlPixel.reset(); +} + +void SvxPatternTabPage::Construct() +{ + m_xPatternLB->FillPresetListBox( *m_pPatternList ); +} + +void SvxPatternTabPage::ActivatePage( const SfxItemSet& rSet ) +{ + if( !m_pColorList.is() ) + return; + + // ColorList + if( *m_pnColorListState & ChangeType::CHANGED || + *m_pnColorListState & ChangeType::MODIFIED ) + { + SvxAreaTabDialog* pArea = (*m_pnColorListState & ChangeType::CHANGED) ? + dynamic_cast(GetDialogController()) : nullptr; + if (pArea) + m_pColorList = pArea->GetNewColorList(); + } + + // determining (possibly cutting) the name and + // displaying it in the GroupBox + OUString aString = CuiResId( RID_SVXSTR_TABLE ) + ": "; + INetURLObject aURL( m_pPatternList->GetPath() ); + + aURL.Append( m_pPatternList->GetName() ); + SAL_WARN_IF( aURL.GetProtocol() == INetProtocol::NotValid, "cui.tabpages", "invalid URL" ); + + if( aURL.getBase().getLength() > 18 ) + { + aString += aURL.getBase().copy( 0, 15 ) + "..."; + } + else + aString += aURL.getBase(); + + XFillBitmapItem aItem( rSet.Get( XATTR_FILLBITMAP ) ); + + if ( aItem.isPattern() ) + { + sal_Int32 nPos = SearchPatternList( aItem.GetName() ); + if ( nPos != -1) + { + sal_uInt16 nId = m_xPatternLB->GetItemId( static_cast( nPos ) ); + m_xPatternLB->SelectItem( nId ); + } + } + else + m_xPatternLB->SelectItem( m_xPatternLB->GetItemId( static_cast( 0 ) ) ); +} + + +DeactivateRC SvxPatternTabPage::DeactivatePage( SfxItemSet* _pSet) +{ + if( _pSet ) + FillItemSet( _pSet ); + + return DeactivateRC::LeavePage; +} + + +bool SvxPatternTabPage::FillItemSet( SfxItemSet* _rOutAttrs ) +{ + _rOutAttrs->Put(XFillStyleItem(drawing::FillStyle_BITMAP)); + size_t nPos = m_xPatternLB->IsNoSelection() ? VALUESET_ITEM_NOTFOUND : m_xPatternLB->GetSelectItemPos(); + if(VALUESET_ITEM_NOTFOUND != nPos) + { + const XBitmapEntry* pXBitmapEntry = m_pPatternList->GetBitmap( static_cast(nPos) ); + const OUString aString( m_xPatternLB->GetItemText( m_xPatternLB->GetSelectedItemId() ) ); + + _rOutAttrs->Put(XFillBitmapItem(aString, pXBitmapEntry->GetGraphicObject())); + } + else + { + const BitmapEx aBitmapEx(m_xBitmapCtl->GetBitmapEx()); + + _rOutAttrs->Put(XFillBitmapItem(OUString(), Graphic(aBitmapEx))); + } + _rOutAttrs->Put(XFillBmpTileItem(true)); + return true; +} + + +void SvxPatternTabPage::Reset( const SfxItemSet* ) +{ + m_xBitmapCtl->SetPixelColor( m_xLbColor->GetSelectEntryColor() ); + m_xBitmapCtl->SetBackgroundColor( m_xLbBackgroundColor->GetSelectEntryColor() ); + m_xBitmapCtl->SetBmpArray( m_xCtlPixel->GetBitmapPixelPtr() ); + + // get bitmap and display it + const XFillBitmapItem aBmpItem(OUString(), Graphic(m_xBitmapCtl->GetBitmapEx())); + if(aBmpItem.isPattern()) + { + m_rXFSet.Put( aBmpItem ); + m_aCtlPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + m_aCtlPreview.Invalidate(); + } + + ChangePatternHdl_Impl(m_xPatternLB.get()); + + // determine button state + if( m_pPatternList.is() && m_pPatternList->Count() ) + { + m_xBtnAdd->set_sensitive(true); + m_xBtnModify->set_sensitive(true); + } + else + { + m_xBtnModify->set_sensitive(false); + } +} + +std::unique_ptr SvxPatternTabPage::Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rSet ) +{ + return std::make_unique(pPage, pController, *rSet); +} + +IMPL_LINK_NOARG(SvxPatternTabPage, ChangePatternHdl_Impl, ValueSet*, void) +{ + std::unique_ptr pGraphicObject; + size_t nPos = m_xPatternLB->GetSelectItemPos(); + + if(VALUESET_ITEM_NOTFOUND != nPos) + { + pGraphicObject.reset(new GraphicObject(m_pPatternList->GetBitmap( static_cast(nPos) )->GetGraphicObject())); + } + else + { + const SfxPoolItem* pPoolItem = nullptr; + + if(SfxItemState::SET == m_rOutAttrs.GetItemState(GetWhich(XATTR_FILLSTYLE), true, &pPoolItem)) + { + const drawing::FillStyle eXFS(static_cast(pPoolItem)->GetValue()); + + if((drawing::FillStyle_BITMAP == eXFS) && (SfxItemState::SET == m_rOutAttrs.GetItemState(GetWhich(XATTR_FILLBITMAP), true, &pPoolItem))) + { + pGraphicObject.reset(new GraphicObject(static_cast(pPoolItem)->GetGraphicObject())); + } + } + + if(!pGraphicObject) + { + sal_uInt16 nPosition = m_xPatternLB->GetItemId( 0 ); + m_xPatternLB->SelectItem( nPosition ); + if( nPosition != 0 ) + { + pGraphicObject.reset(new GraphicObject(m_pPatternList->GetBitmap(0)->GetGraphicObject())); + } + } + } + + if(!pGraphicObject) + return; + + Color aBackColor; + Color aPixelColor; + bool bIs8x8(vcl::bitmap::isHistorical8x8(pGraphicObject->GetGraphic().GetBitmapEx(), aBackColor, aPixelColor)); + + m_xLbColor->SetNoSelection(); + m_xLbBackgroundColor->SetNoSelection(); + + if(bIs8x8) + { + m_xCtlPixel->SetPaintable( true ); + m_xBtnModify->set_sensitive(true); + m_xBtnAdd->set_sensitive(true); + + // setting the pixel control + + m_xCtlPixel->SetXBitmap(pGraphicObject->GetGraphic().GetBitmapEx()); + + m_xLbColor->SelectEntry( aPixelColor ); + m_xLbBackgroundColor->SelectEntry( aBackColor ); + + // update m_xBitmapCtl, rXFSet and m_aCtlPreview + m_xBitmapCtl->SetPixelColor( aPixelColor ); + m_xBitmapCtl->SetBackgroundColor( aBackColor ); + m_rXFSet.ClearItem(); + m_rXFSet.Put(XFillStyleItem(drawing::FillStyle_BITMAP)); + m_rXFSet.Put(XFillBitmapItem(OUString(), Graphic(m_xBitmapCtl->GetBitmapEx()))); + m_aCtlPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + m_aCtlPreview.Invalidate(); + } + else + { + m_xCtlPixel->Reset(); + m_xCtlPixel->SetPaintable( false ); + m_xBtnModify->set_sensitive(false); + m_xBtnAdd->set_sensitive(false); + } + + m_xCtlPixel->Invalidate(); +} + +IMPL_LINK_NOARG(SvxPatternTabPage, ClickAddHdl_Impl, weld::Button&, void) +{ + + OUString aNewName( SvxResId( RID_SVXSTR_PATTERN_UNTITLED ) ); + OUString aDesc( CuiResId( RID_SVXSTR_DESC_NEW_PATTERN ) ); + OUString aName; + + long nCount = m_pPatternList->Count(); + long j = 1; + bool bValidPatternName = false; + + while( !bValidPatternName ) + { + aName = aNewName + " " + OUString::number( j++ ); + bValidPatternName = (SearchPatternList(aName) == -1); + } + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateSvxNameDialog(GetFrameWeld(), aName, aDesc)); + sal_uInt16 nError(1); + + while( pDlg->Execute() == RET_OK ) + { + pDlg->GetName( aName ); + + bValidPatternName = (SearchPatternList(aName) == -1); + + if( bValidPatternName ) { + nError = 0; + break; + } + + std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/queryduplicatedialog.ui")); + std::unique_ptr xWarnBox(xBuilder->weld_message_dialog("DuplicateNameDialog")); + if (xWarnBox->run() != RET_OK) + break; + } + + pDlg.disposeAndClear(); + + if( !nError ) + { + std::unique_ptr pEntry; + if( m_xCtlPixel->IsEnabled() ) + { + const BitmapEx aBitmapEx(m_xBitmapCtl->GetBitmapEx()); + + pEntry.reset(new XBitmapEntry(Graphic(aBitmapEx), aName)); + } + else // it must be a not existing imported bitmap + { + const SfxPoolItem* pPoolItem = nullptr; + + if(SfxItemState::SET == m_rOutAttrs.GetItemState(XATTR_FILLBITMAP, true, &pPoolItem)) + { + auto pFillBmpItem = dynamic_cast(pPoolItem); + assert(pFillBmpItem); + pEntry.reset(new XBitmapEntry(pFillBmpItem->GetGraphicObject(), aName)); + } + else + assert(!"SvxPatternTabPage::ClickAddHdl_Impl(), XBitmapEntry* pEntry == nullptr ?"); + } + + if( pEntry ) + { + m_pPatternList->Insert(std::move(pEntry), nCount); + sal_Int32 nId = m_xPatternLB->GetItemId( nCount - 1 ); + BitmapEx aBitmap = m_pPatternList->GetBitmapForPreview( nCount, m_xPatternLB->GetIconSize() ); + m_xPatternLB->InsertItem( nId + 1, Image(aBitmap), aName ); + m_xPatternLB->SelectItem( nId + 1 ); + m_xPatternLB->Resize(); + + *m_pnPatternListState |= ChangeType::MODIFIED; + + ChangePatternHdl_Impl(m_xPatternLB.get()); + } + } + + // determine button state + if( m_pPatternList->Count() ) + { + m_xBtnModify->set_sensitive(true); + } +} + +IMPL_LINK_NOARG(SvxPatternTabPage, ClickModifyHdl_Impl, weld::Button&, void) +{ + sal_uInt16 nId = m_xPatternLB->GetSelectedItemId(); + size_t nPos = m_xPatternLB->GetSelectItemPos(); + + if ( nPos == VALUESET_ITEM_NOTFOUND ) + return; + + OUString aName( m_pPatternList->GetBitmap( static_cast(nPos) )->GetName() ); + + const BitmapEx aBitmapEx(m_xBitmapCtl->GetBitmapEx()); + + // #i123497# Need to replace the existing entry with a new one (old returned needs to be deleted) + m_pPatternList->Replace(std::make_unique(Graphic(aBitmapEx), aName), nPos); + + BitmapEx aBitmap = m_pPatternList->GetBitmapForPreview( static_cast( nPos ), m_xPatternLB->GetIconSize() ); + m_xPatternLB->RemoveItem(nId); + m_xPatternLB->InsertItem( nId, Image(aBitmap), aName, static_cast(nPos) ); + m_xPatternLB->SelectItem( nId ); + + *m_pnPatternListState |= ChangeType::MODIFIED; +} + + +IMPL_LINK_NOARG(SvxPatternTabPage, ClickRenameHdl_Impl, SvxPresetListBox*, void) +{ + size_t nPos = m_xPatternLB->GetSelectItemPos(); + sal_Int32 nId = m_xPatternLB->GetSelectedItemId(); + + if ( nPos == VALUESET_ITEM_NOTFOUND ) + return; + + OUString aDesc(CuiResId(RID_SVXSTR_DESC_NEW_PATTERN)); + OUString aName(m_pPatternList->GetBitmap(nPos)->GetName()); + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateSvxNameDialog(GetFrameWeld(), aName, aDesc)); + + bool bLoop = true; + + while( bLoop && pDlg->Execute() == RET_OK ) + { + pDlg->GetName( aName ); + sal_Int32 nPatternPos = SearchPatternList(aName); + bool bValidPatternName = (nPatternPos == static_cast(nPos) ) || (nPatternPos == -1); + + if( bValidPatternName ) + { + bLoop = false; + + m_pPatternList->GetBitmap(nPos)->SetName(aName); + + m_xPatternLB->SetItemText( nId, aName ); + m_xPatternLB->SelectItem( nId ); + + *m_pnPatternListState |= ChangeType::MODIFIED; + } + else + { + std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/queryduplicatedialog.ui")); + std::unique_ptr xWarnBox(xBuilder->weld_message_dialog("DuplicateNameDialog")); + xWarnBox->run(); + } + } +} + +IMPL_LINK_NOARG(SvxPatternTabPage, ClickDeleteHdl_Impl, SvxPresetListBox*, void) +{ + sal_uInt16 nId = m_xPatternLB->GetSelectedItemId(); + size_t nPos = m_xPatternLB->GetSelectItemPos(); + + if( nPos != VALUESET_ITEM_NOTFOUND ) + { + std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querydeletebitmapdialog.ui")); + std::unique_ptr xQueryBox(xBuilder->weld_message_dialog("AskDelBitmapDialog")); + if (xQueryBox->run() == RET_YES) + { + m_pPatternList->Remove(nPos); + m_xPatternLB->RemoveItem( nId ); + nId = m_xPatternLB->GetItemId(0); + m_xPatternLB->SelectItem( nId ); + m_xPatternLB->Resize(); + + m_aCtlPreview.Invalidate(); + m_xCtlPixel->Invalidate(); + + ChangePatternHdl_Impl(m_xPatternLB.get()); + + *m_pnPatternListState |= ChangeType::MODIFIED; + } + } + // determine button state + if( !m_pPatternList->Count() ) + { + m_xBtnModify->set_sensitive(false); + } +} + +IMPL_LINK_NOARG(SvxPatternTabPage, ChangeColorHdl_Impl, ColorListBox&, void) +{ + ChangeColor_Impl(); + m_xPatternLB->SetNoSelection(); +} + +void SvxPatternTabPage::ChangeColor_Impl() +{ + m_xCtlPixel->SetPixelColor( m_xLbColor->GetSelectEntryColor() ); + m_xCtlPixel->SetBackgroundColor( m_xLbBackgroundColor->GetSelectEntryColor() ); + m_xCtlPixel->Invalidate(); + + m_xBitmapCtl->SetPixelColor( m_xLbColor->GetSelectEntryColor() ); + m_xBitmapCtl->SetBackgroundColor( m_xLbBackgroundColor->GetSelectEntryColor() ); + + // get bitmap and display it + m_rXFSet.Put(XFillBitmapItem(OUString(), Graphic(m_xBitmapCtl->GetBitmapEx()))); + m_aCtlPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + m_aCtlPreview.Invalidate(); +} + +void SvxPatternTabPage::PointChanged(weld::DrawingArea* pDrawingArea, RectPoint) +{ + if (pDrawingArea == m_xCtlPixel->GetDrawingArea()) + { + m_xBitmapCtl->SetBmpArray(m_xCtlPixel->GetBitmapPixelPtr()); + + // get bitmap and display it + m_rXFSet.Put(XFillBitmapItem(OUString(), Graphic(m_xBitmapCtl->GetBitmapEx()))); + m_aCtlPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + m_aCtlPreview.Invalidate(); + } + + m_xPatternLB->SetNoSelection(); +} + +sal_Int32 SvxPatternTabPage::SearchPatternList(const OUString& rPatternName) +{ + long nCount = m_pPatternList->Count(); + bool bValidPatternName = true; + sal_Int32 nPos = -1; + + for(long i = 0;i < nCount && bValidPatternName;i++) + { + if(rPatternName == m_pPatternList->GetBitmap( i )->GetName()) + { + nPos = i; + bValidPatternName = false; + } + } + return nPos; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/tpshadow.cxx b/cui/source/tabpages/tpshadow.cxx new file mode 100644 index 000000000..de448b197 --- /dev/null +++ b/cui/source/tabpages/tpshadow.cxx @@ -0,0 +1,495 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace com::sun::star; + +const sal_uInt16 SvxShadowTabPage::pShadowRanges[] = +{ + SDRATTR_SHADOWCOLOR, + SDRATTR_SHADOWTRANSPARENCE, + SID_ATTR_FILL_SHADOW, + SID_ATTR_FILL_SHADOW, + SID_ATTR_SHADOW_TRANSPARENCE, + SID_ATTR_SHADOW_YDISTANCE, + 0 +}; + +SvxShadowTabPage::SvxShadowTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SvxTabPage(pPage, pController, "cui/ui/shadowtabpage.ui", "ShadowTabPage", rInAttrs) + , m_rOutAttrs(rInAttrs) + , m_pnColorListState(nullptr) + , m_nPageType(PageType::Area) + , m_nDlgType(0) + , m_aXFillAttr(rInAttrs.GetPool()) + , m_rXFSet(m_aXFillAttr.GetItemSet()) + , m_aCtlPosition(this) + , m_xTsbShowShadow(m_xBuilder->weld_check_button("TSB_SHOW_SHADOW")) + , m_xGridShadow(m_xBuilder->weld_widget("gridSHADOW")) + , m_xMtrDistance(m_xBuilder->weld_metric_spin_button("MTR_FLD_DISTANCE", FieldUnit::CM)) + , m_xLbShadowColor(new ColorListBox(m_xBuilder->weld_menu_button("LB_SHADOW_COLOR"), pController->getDialog())) + , m_xMtrTransparent(m_xBuilder->weld_metric_spin_button("MTR_SHADOW_TRANSPARENT", FieldUnit::PERCENT)) + , m_xCtlPosition(new weld::CustomWeld(*m_xBuilder, "CTL_POSITION", m_aCtlPosition)) + , m_xCtlXRectPreview(new weld::CustomWeld(*m_xBuilder, "CTL_COLOR_PREVIEW", m_aCtlXRectPreview)) +{ + // this page needs ExchangeSupport + SetExchangeSupport(); + + // adjust metric + FieldUnit eFUnit = GetModuleFieldUnit( rInAttrs ); + + switch ( eFUnit ) + { + case FieldUnit::M: + case FieldUnit::KM: + eFUnit = FieldUnit::MM; + break; + default: ;//prevent warning + } + SetFieldUnit( *m_xMtrDistance, eFUnit ); + + // determine PoolUnit + SfxItemPool* pPool = m_rOutAttrs.GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + m_ePoolUnit = pPool->GetMetric( SDRATTR_SHADOWXDIST ); + + // setting the output device + drawing::FillStyle eXFS = drawing::FillStyle_SOLID; + if( m_rOutAttrs.GetItemState( XATTR_FILLSTYLE ) != SfxItemState::DONTCARE ) + { + eXFS = static_cast( m_rOutAttrs. + Get( GetWhich( XATTR_FILLSTYLE ) ) ).GetValue(); + switch( eXFS ) + { + case drawing::FillStyle_SOLID: + if( SfxItemState::DONTCARE != m_rOutAttrs.GetItemState( XATTR_FILLCOLOR ) ) + { + m_rXFSet.Put( m_rOutAttrs.Get( XATTR_FILLCOLOR ) ); + } + break; + + case drawing::FillStyle_GRADIENT: + if( SfxItemState::DONTCARE != m_rOutAttrs.GetItemState( XATTR_FILLGRADIENT ) ) + { + m_rXFSet.Put( m_rOutAttrs.Get( XATTR_FILLGRADIENT ) ); + } + break; + + case drawing::FillStyle_HATCH: + if( SfxItemState::DONTCARE != m_rOutAttrs.GetItemState( XATTR_FILLHATCH ) ) + { + m_rXFSet.Put( m_rOutAttrs.Get( XATTR_FILLHATCH ) ); + } + break; + + case drawing::FillStyle_BITMAP: + { + if( SfxItemState::DONTCARE != m_rOutAttrs.GetItemState( XATTR_FILLBITMAP ) ) + { + m_rXFSet.Put( m_rOutAttrs.Get( XATTR_FILLBITMAP ) ); + } + } + break; + case drawing::FillStyle_NONE : break; + default: break; + } + } + else + { + m_rXFSet.Put( XFillColorItem( OUString(), COL_LIGHTRED ) ); + } + + if(drawing::FillStyle_NONE == eXFS) + { + // #i96350# + // fallback to solid fillmode when no fill mode is provided to have + // a reasonable shadow preview. The used color will be a set one or + // the default (currently blue8) + eXFS = drawing::FillStyle_SOLID; + } + + m_rXFSet.Put( XFillStyleItem( eXFS ) ); + m_aCtlXRectPreview.SetRectangleAttributes(m_aXFillAttr.GetItemSet()); + + m_xTsbShowShadow->connect_toggled(LINK( this, SvxShadowTabPage, ClickShadowHdl_Impl)); + m_xLbShadowColor->SetSelectHdl( LINK( this, SvxShadowTabPage, SelectShadowHdl_Impl ) ); + Link aLink = LINK( this, SvxShadowTabPage, ModifyShadowHdl_Impl ); + m_xMtrTransparent->connect_value_changed(aLink); + m_xMtrDistance->connect_value_changed(aLink); +} + +SvxShadowTabPage::~SvxShadowTabPage() +{ + m_xCtlXRectPreview.reset(); + m_xLbShadowColor.reset(); + m_xCtlPosition.reset(); +} + +void SvxShadowTabPage::ActivatePage( const SfxItemSet& rSet ) +{ + const SfxUInt16Item* pPageTypeItem = rSet.GetItem(SID_PAGE_TYPE, false); + if (pPageTypeItem) + SetPageType(static_cast(pPageTypeItem->GetValue())); + + if( m_nDlgType != 0 ) + return; + + if( !m_pColorList.is() ) + return; + + // ColorList + if( *m_pnColorListState & ChangeType::CHANGED || + *m_pnColorListState & ChangeType::MODIFIED ) + { + if( *m_pnColorListState & ChangeType::CHANGED ) + { + SvxAreaTabDialog* pArea = dynamic_cast(GetDialogController()); + if( pArea ) + { + m_pColorList = pArea->GetNewColorList(); + } + else + { + SvxLineTabDialog* pLine = dynamic_cast(GetDialogController()); + if( pLine ) + m_pColorList = pLine->GetNewColorList(); + } + } + + SfxItemSet rAttribs( rSet ); + // rSet contains shadow attributes too, but we want + // to use it for updating rectangle attributes only, + // so set the shadow to none here + SdrOnOffItem aItem( makeSdrShadowItem( false )); + rAttribs.Put( aItem ); + + m_aCtlXRectPreview.SetRectangleAttributes( rAttribs ); + ModifyShadowHdl_Impl( *m_xMtrTransparent ); + } + m_nPageType = PageType::Shadow; +} + + +DeactivateRC SvxShadowTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if( _pSet ) + FillItemSet( _pSet ); + + return DeactivateRC::LeavePage; +} + + +bool SvxShadowTabPage::FillItemSet( SfxItemSet* rAttrs ) +{ + bool bModified = false; + + const SfxPoolItem* pOld = nullptr; + + if (m_xTsbShowShadow->get_state_changed_from_saved()) + { + TriState eState = m_xTsbShowShadow->get_state(); + assert(eState != TRISTATE_INDET); + // given how m_xTsbShowShadow is set up and saved in Reset(), + // eState == TRISTATE_INDET would imply + // !IsValueChangedFromSaved() + SdrOnOffItem aItem( makeSdrShadowItem(eState == TRISTATE_TRUE) ); + pOld = GetOldItem( *rAttrs, SDRATTR_SHADOW ); + if ( !pOld || !( *static_cast(pOld) == aItem ) ) + { + rAttrs->Put( aItem ); + bModified = true; + } + } + + // shadow removal + // a bit intricate inquiry whether there was something changed, + // as the items can't be displayed directly on controls + sal_Int32 nX = 0, nY = 0; + sal_Int32 nXY = GetCoreValue( *m_xMtrDistance, m_ePoolUnit ); + + switch (m_aCtlPosition.GetActualRP()) + { + case RectPoint::LT: nX = nY = -nXY; break; + case RectPoint::MT: nY = -nXY; break; + case RectPoint::RT: nX = nXY; nY = -nXY; break; + case RectPoint::LM: nX = -nXY; break; + case RectPoint::RM: nX = nXY; break; + case RectPoint::LB: nX = -nXY; nY = nXY; break; + case RectPoint::MB: nY = nXY; break; + case RectPoint::RB: nX = nY = nXY; break; + case RectPoint::MM: break; + } + + // If the values of the shadow distances==SfxItemState::DONTCARE and the displayed + // string in the respective MetricField=="", then the comparison of the old + // and the new distance values would return a wrong result because in such a + // case the new distance values would match the default values of the MetricField !!!! + if ( !m_xMtrDistance->get_text().isEmpty() || + m_rOutAttrs.GetItemState( SDRATTR_SHADOWXDIST ) != SfxItemState::DONTCARE || + m_rOutAttrs.GetItemState( SDRATTR_SHADOWYDIST ) != SfxItemState::DONTCARE ) + { + sal_Int32 nOldX = 9876543; // impossible value, so DontCare + sal_Int32 nOldY = 9876543; + if( m_rOutAttrs.GetItemState( SDRATTR_SHADOWXDIST ) != SfxItemState::DONTCARE && + m_rOutAttrs.GetItemState( SDRATTR_SHADOWYDIST ) != SfxItemState::DONTCARE ) + { + nOldX = m_rOutAttrs.Get( SDRATTR_SHADOWXDIST ).GetValue(); + nOldY = m_rOutAttrs.Get( SDRATTR_SHADOWYDIST ).GetValue(); + } + SdrMetricItem aXItem( makeSdrShadowXDistItem(nX) ); + pOld = GetOldItem( *rAttrs, SDRATTR_SHADOWXDIST ); + if ( nX != nOldX && + ( !pOld || !( *static_cast(pOld) == aXItem ) ) ) + { + rAttrs->Put( aXItem ); + bModified = true; + } + SdrMetricItem aYItem( makeSdrShadowYDistItem(nY) ); + pOld = GetOldItem( *rAttrs, SDRATTR_SHADOWYDIST ); + if ( nY != nOldY && + ( !pOld || !( *static_cast(pOld) == aYItem ) ) ) + { + rAttrs->Put( aYItem ); + bModified = true; + } + } + + // ShadowColor + { + XColorItem aItem(makeSdrShadowColorItem(m_xLbShadowColor->GetSelectEntryColor())); + pOld = GetOldItem( *rAttrs, SDRATTR_SHADOWCOLOR ); + if ( !pOld || !( *static_cast(pOld) == aItem ) ) + { + rAttrs->Put( aItem ); + bModified = true; + } + } + + // transparency + sal_uInt16 nVal = static_cast(m_xMtrTransparent->get_value(FieldUnit::PERCENT)); + if (m_xMtrTransparent->get_value_changed_from_saved()) + { + SdrPercentItem aItem( makeSdrShadowTransparenceItem(nVal) ); + pOld = GetOldItem( *rAttrs, SDRATTR_SHADOWTRANSPARENCE ); + if ( !pOld || !( *static_cast(pOld) == aItem ) ) + { + rAttrs->Put( aItem ); + bModified = true; + } + } + + rAttrs->Put (CntUInt16Item(SID_PAGE_TYPE, static_cast(m_nPageType))); + + return bModified; +} + + +void SvxShadowTabPage::Reset( const SfxItemSet* rAttrs ) +{ + // all objects can have a shadow + // at the moment there are only 8 possible positions where a shadow can be set + + // has a shadow been set? + if( rAttrs->GetItemState( SDRATTR_SHADOW ) != SfxItemState::DONTCARE ) + { + if( rAttrs->Get( SDRATTR_SHADOW ).GetValue() ) + m_xTsbShowShadow->set_state(TRISTATE_TRUE); + else + { + m_xTsbShowShadow->set_state(TRISTATE_FALSE); + } + } + else + m_xTsbShowShadow->set_state(TRISTATE_INDET); + + // distance (only 8 possible positions), + // so there is only one item evaluated + + if( rAttrs->GetItemState( SDRATTR_SHADOWXDIST ) != SfxItemState::DONTCARE && + rAttrs->GetItemState( SDRATTR_SHADOWYDIST ) != SfxItemState::DONTCARE ) + { + sal_Int32 nX = rAttrs->Get( SDRATTR_SHADOWXDIST ).GetValue(); + sal_Int32 nY = rAttrs->Get( SDRATTR_SHADOWYDIST ).GetValue(); + + if( nX != 0 ) + SetMetricValue( *m_xMtrDistance, nX < 0 ? -nX : nX, m_ePoolUnit ); + else + SetMetricValue( *m_xMtrDistance, nY < 0 ? -nY : nY, m_ePoolUnit ); + + // setting the shadow control + if ( nX < 0 && nY < 0 ) m_aCtlPosition.SetActualRP( RectPoint::LT ); + else if( nX == 0 && nY < 0 ) m_aCtlPosition.SetActualRP( RectPoint::MT ); + else if( nX > 0 && nY < 0 ) m_aCtlPosition.SetActualRP( RectPoint::RT ); + else if( nX < 0 && nY == 0 ) m_aCtlPosition.SetActualRP( RectPoint::LM ); + // there's no center point anymore + else if( nX == 0 && nY == 0 ) m_aCtlPosition.SetActualRP( RectPoint::RB ); + else if( nX > 0 && nY == 0 ) m_aCtlPosition.SetActualRP( RectPoint::RM ); + else if( nX < 0 && nY > 0 ) m_aCtlPosition.SetActualRP( RectPoint::LB ); + else if( nX == 0 && nY > 0 ) m_aCtlPosition.SetActualRP( RectPoint::MB ); + else if( nX > 0 && nY > 0 ) m_aCtlPosition.SetActualRP( RectPoint::RB ); + } + else + { + // determine default-distance + SfxItemPool* pPool = m_rOutAttrs.GetPool(); + { + sal_Int32 n = pPool->GetDefaultItem(SDRATTR_SHADOWXDIST).GetValue(); + if (n == 0) + n = pPool->GetDefaultItem(SDRATTR_SHADOWYDIST).GetValue(); + SetMetricValue(*m_xMtrDistance, std::abs(n), m_ePoolUnit); + } + + // Tristate, e. g. multiple objects have been marked of which some have a shadow and some don't. + // The text (which shall be displayed) of the MetricFields is set to "" and serves as an + // identification in the method FillItemSet for the fact that the distance value was NOT changed !!!! + m_xMtrDistance->set_text( "" ); + m_aCtlPosition.SetActualRP( RectPoint::MM ); + } + + if( rAttrs->GetItemState( SDRATTR_SHADOWCOLOR ) != SfxItemState::DONTCARE ) + { + m_xLbShadowColor->SelectEntry( rAttrs->Get( SDRATTR_SHADOWCOLOR ).GetColorValue() ); + } + else + m_xLbShadowColor->SetNoSelection(); + + if( rAttrs->GetItemState( SDRATTR_SHADOWTRANSPARENCE ) != SfxItemState::DONTCARE ) + { + sal_uInt16 nTransp = rAttrs->Get( SDRATTR_SHADOWTRANSPARENCE ).GetValue(); + m_xMtrTransparent->set_value(nTransp, FieldUnit::PERCENT); + } + else + m_xMtrTransparent->set_text(""); + + //aCtlPosition + m_xMtrDistance->save_value(); + m_xLbShadowColor->SaveValue(); + m_xTsbShowShadow->save_state(); + + // #66832# This field was not saved, but used to determine changes. + // Why? Seems to be the error. + // It IS the error. + m_xMtrTransparent->save_value(); + + ClickShadowHdl_Impl(*m_xTsbShowShadow); + ModifyShadowHdl_Impl(*m_xMtrTransparent); +} + +std::unique_ptr SvxShadowTabPage::Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrs ) +{ + return std::make_unique(pPage, pController, *rAttrs); +} + +IMPL_LINK_NOARG(SvxShadowTabPage, ClickShadowHdl_Impl, weld::ToggleButton&, void) +{ + if (m_xTsbShowShadow->get_state() == TRISTATE_FALSE) + { + m_xGridShadow->set_sensitive(false); + m_xCtlPosition->set_sensitive(false); + } + else + { + m_xGridShadow->set_sensitive(true); + m_xCtlPosition->set_sensitive(true); + } + m_aCtlPosition.Invalidate(); + ModifyShadowHdl_Impl(*m_xMtrTransparent); +} + +IMPL_LINK_NOARG(SvxShadowTabPage, SelectShadowHdl_Impl, ColorListBox&, void) +{ + ModifyShadowHdl_Impl(*m_xMtrTransparent); +} + +IMPL_LINK_NOARG(SvxShadowTabPage, ModifyShadowHdl_Impl, weld::MetricSpinButton&, void) +{ + if (m_xTsbShowShadow->get_state() == TRISTATE_TRUE) + m_rXFSet.Put( XFillStyleItem( drawing::FillStyle_SOLID ) ); + else + m_rXFSet.Put( XFillStyleItem( drawing::FillStyle_NONE ) ); + + m_rXFSet.Put( XFillColorItem( OUString(), m_xLbShadowColor->GetSelectEntryColor() ) ); + sal_uInt16 nVal = static_cast(m_xMtrTransparent->get_value(FieldUnit::PERCENT)); + m_rXFSet.Put( XFillTransparenceItem( nVal ) ); + + // shadow removal + sal_Int32 nX = 0, nY = 0; + sal_Int32 nXY = GetCoreValue( *m_xMtrDistance, m_ePoolUnit ); + switch( m_aCtlPosition.GetActualRP() ) + { + case RectPoint::LT: nX = nY = -nXY; break; + case RectPoint::MT: nY = -nXY; break; + case RectPoint::RT: nX = nXY; nY = -nXY; break; + case RectPoint::LM: nX = -nXY; break; + case RectPoint::RM: nX = nXY; break; + case RectPoint::LB: nX = -nXY; nY = nXY; break; + case RectPoint::MB: nY = nXY; break; + case RectPoint::RB: nX = nY = nXY; break; + case RectPoint::MM: break; + } + + m_aCtlXRectPreview.SetShadowPosition(Point(nX, nY)); + + m_aCtlXRectPreview.SetShadowAttributes(m_aXFillAttr.GetItemSet()); + m_aCtlXRectPreview.Invalidate(); +} + +void SvxShadowTabPage::PointChanged( weld::DrawingArea*, RectPoint ) +{ + // repaint shadow + ModifyShadowHdl_Impl( *m_xMtrTransparent ); +} + +void SvxShadowTabPage::PageCreated(const SfxAllItemSet& aSet) +{ + const SvxColorListItem* pColorListItem = aSet.GetItem(SID_COLOR_TABLE, false); + const SfxUInt16Item* pPageTypeItem = aSet.GetItem(SID_PAGE_TYPE, false); + const SfxUInt16Item* pDlgTypeItem = aSet.GetItem(SID_DLG_TYPE, false); + + if (pColorListItem) + SetColorList(pColorListItem->GetColorList()); + if (pPageTypeItem) + SetPageType(static_cast(pPageTypeItem->GetValue())); + if (pDlgTypeItem) + SetDlgType(pDlgTypeItem->GetValue()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/tptrans.cxx b/cui/source/tabpages/tptrans.cxx new file mode 100644 index 000000000..ac950ceb3 --- /dev/null +++ b/cui/source/tabpages/tptrans.cxx @@ -0,0 +1,524 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace com::sun::star; + +const sal_uInt16 SvxTransparenceTabPage::pTransparenceRanges[] = +{ + XATTR_FILLTRANSPARENCE, + XATTR_FILLTRANSPARENCE, + SDRATTR_SHADOWTRANSPARENCE, + SDRATTR_SHADOWTRANSPARENCE, + XATTR_FILLFLOATTRANSPARENCE, + XATTR_FILLFLOATTRANSPARENCE, + 0 +}; + +/************************************************************************* +|* +|* Dialog for transparence +|* +\************************************************************************/ + +IMPL_LINK_NOARG(SvxTransparenceTabPage, ClickTransOffHdl_Impl, weld::ToggleButton&, void) +{ + // disable all other controls + ActivateLinear(false); + ActivateGradient(false); + + // Preview + rXFSet.ClearItem(XATTR_FILLTRANSPARENCE); + rXFSet.ClearItem(XATTR_FILLFLOATTRANSPARENCE); + m_aCtlXRectPreview.SetAttributes( aXFillAttr.GetItemSet() ); + m_aCtlBitmapPreview.SetAttributes( aXFillAttr.GetItemSet() ); + + InvalidatePreview(false); +} + +IMPL_LINK_NOARG(SvxTransparenceTabPage, ClickTransLinearHdl_Impl, weld::ToggleButton&, void) +{ + // enable linear, disable other + ActivateLinear(true); + ActivateGradient(false); + + // preview + rXFSet.ClearItem (XATTR_FILLFLOATTRANSPARENCE); + ModifyTransparentHdl_Impl(*m_xMtrTransparent); +} + +IMPL_LINK_NOARG(SvxTransparenceTabPage, ClickTransGradientHdl_Impl, weld::ToggleButton&, void) +{ + // enable gradient, disable other + ActivateLinear(false); + ActivateGradient(true); + + // preview + rXFSet.ClearItem (XATTR_FILLTRANSPARENCE); + ModifiedTrgrHdl_Impl(nullptr); +} + +SvxTransparenceTabPage::~SvxTransparenceTabPage() +{ +} + +void SvxTransparenceTabPage::ActivateLinear(bool bActivate) +{ + m_xMtrTransparent->set_sensitive(bActivate); +} + +IMPL_LINK_NOARG(SvxTransparenceTabPage, ModifyTransparentHdl_Impl, weld::MetricSpinButton&, void) +{ + sal_uInt16 nPos = m_xMtrTransparent->get_value(FieldUnit::PERCENT); + rXFSet.Put(XFillTransparenceItem(nPos)); + + // preview + InvalidatePreview(); +} + +IMPL_LINK(SvxTransparenceTabPage, ModifiedTrgrListBoxHdl_Impl, weld::ComboBox&, rListBox, void) +{ + ModifiedTrgrHdl_Impl(&rListBox); +} + +IMPL_LINK_NOARG(SvxTransparenceTabPage, ModifiedTrgrEditHdl_Impl, weld::MetricSpinButton&, void) +{ + ModifiedTrgrHdl_Impl(nullptr); +} + +void SvxTransparenceTabPage::ModifiedTrgrHdl_Impl(const weld::ComboBox* pControl) +{ + if (pControl == m_xLbTrgrGradientType.get()) + { + css::awt::GradientStyle eXGS = static_cast(m_xLbTrgrGradientType->get_active()); + SetControlState_Impl( eXGS ); + } + + // preview + sal_uInt8 nStartCol = static_cast((static_cast(m_xMtrTrgrStartValue->get_value(FieldUnit::PERCENT)) * 255) / 100); + sal_uInt8 nEndCol = static_cast((static_cast(m_xMtrTrgrEndValue->get_value(FieldUnit::PERCENT)) * 255) / 100); + XGradient aTmpGradient( + Color(nStartCol, nStartCol, nStartCol), + Color(nEndCol, nEndCol, nEndCol), + static_cast(m_xLbTrgrGradientType->get_active()), + static_cast(m_xMtrTrgrAngle->get_value(FieldUnit::DEGREE)) * 10, + static_cast(m_xMtrTrgrCenterX->get_value(FieldUnit::PERCENT)), + static_cast(m_xMtrTrgrCenterY->get_value(FieldUnit::PERCENT)), + static_cast(m_xMtrTrgrBorder->get_value(FieldUnit::PERCENT)), + 100, 100); + + XFillFloatTransparenceItem aItem( aTmpGradient); + rXFSet.Put ( aItem ); + + InvalidatePreview(); +} + +void SvxTransparenceTabPage::ActivateGradient(bool bActivate) +{ + m_xGridGradient->set_sensitive(bActivate); + + if (bActivate) + { + css::awt::GradientStyle eXGS = static_cast(m_xLbTrgrGradientType->get_active()); + SetControlState_Impl( eXGS ); + } +} + +void SvxTransparenceTabPage::SetControlState_Impl(css::awt::GradientStyle eXGS) +{ + switch(eXGS) + { + case css::awt::GradientStyle_LINEAR: + case css::awt::GradientStyle_AXIAL: + m_xFtTrgrCenterX->set_sensitive(false); + m_xMtrTrgrCenterX->set_sensitive(false); + m_xFtTrgrCenterY->set_sensitive(false); + m_xMtrTrgrCenterY->set_sensitive(false); + m_xFtTrgrAngle->set_sensitive(true); + m_xMtrTrgrAngle->set_sensitive(true); + break; + + case css::awt::GradientStyle_RADIAL: + m_xFtTrgrCenterX->set_sensitive(true); + m_xMtrTrgrCenterX->set_sensitive(true); + m_xFtTrgrCenterY->set_sensitive(true); + m_xMtrTrgrCenterY->set_sensitive(true); + m_xFtTrgrAngle->set_sensitive(false); + m_xMtrTrgrAngle->set_sensitive(false); + break; + + case css::awt::GradientStyle_ELLIPTICAL: + case css::awt::GradientStyle_SQUARE: + case css::awt::GradientStyle_RECT: + m_xFtTrgrCenterX->set_sensitive(true); + m_xMtrTrgrCenterX->set_sensitive(true); + m_xFtTrgrCenterY->set_sensitive(true); + m_xMtrTrgrCenterY->set_sensitive(true); + m_xFtTrgrAngle->set_sensitive(true); + m_xMtrTrgrAngle->set_sensitive(true); + break; + default: + break; + } +} + +SvxTransparenceTabPage::SvxTransparenceTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "cui/ui/transparencytabpage.ui", "TransparencyTabPage", &rInAttrs) + , rOutAttrs(rInAttrs) + , nPageType(PageType::Area) + , nDlgType(0) + , bBitmap(false) + , aXFillAttr(rInAttrs.GetPool()) + , rXFSet(aXFillAttr.GetItemSet()) + , m_xRbtTransOff(m_xBuilder->weld_radio_button("RBT_TRANS_OFF")) + , m_xRbtTransLinear(m_xBuilder->weld_radio_button("RBT_TRANS_LINEAR")) + , m_xRbtTransGradient(m_xBuilder->weld_radio_button("RBT_TRANS_GRADIENT")) + , m_xMtrTransparent(m_xBuilder->weld_metric_spin_button("MTR_TRANSPARENT", FieldUnit::PERCENT)) + , m_xGridGradient(m_xBuilder->weld_widget("gridGradient")) + , m_xLbTrgrGradientType(m_xBuilder->weld_combo_box("LB_TRGR_GRADIENT_TYPES")) + , m_xFtTrgrCenterX(m_xBuilder->weld_label("FT_TRGR_CENTER_X")) + , m_xMtrTrgrCenterX(m_xBuilder->weld_metric_spin_button("MTR_TRGR_CENTER_X", FieldUnit::PERCENT)) + , m_xFtTrgrCenterY(m_xBuilder->weld_label("FT_TRGR_CENTER_Y")) + , m_xMtrTrgrCenterY(m_xBuilder->weld_metric_spin_button("MTR_TRGR_CENTER_Y", FieldUnit::PERCENT)) + , m_xFtTrgrAngle(m_xBuilder->weld_label("FT_TRGR_ANGLE")) + , m_xMtrTrgrAngle(m_xBuilder->weld_metric_spin_button("MTR_TRGR_ANGLE", FieldUnit::DEGREE)) + , m_xMtrTrgrBorder(m_xBuilder->weld_metric_spin_button("MTR_TRGR_BORDER", FieldUnit::PERCENT)) + , m_xMtrTrgrStartValue(m_xBuilder->weld_metric_spin_button("MTR_TRGR_START_VALUE", FieldUnit::PERCENT)) + , m_xMtrTrgrEndValue(m_xBuilder->weld_metric_spin_button("MTR_TRGR_END_VALUE", FieldUnit::PERCENT)) + , m_xCtlBitmapBorder(m_xBuilder->weld_widget("bitmap_border")) + , m_xCtlXRectBorder(m_xBuilder->weld_widget("trans_border")) + , m_xCtlBitmapPreview(new weld::CustomWeld(*m_xBuilder, "CTL_BITMAP_PREVIEW", m_aCtlBitmapPreview)) + , m_xCtlXRectPreview(new weld::CustomWeld(*m_xBuilder, "CTL_TRANS_PREVIEW", m_aCtlXRectPreview)) +{ + // main selection + m_xRbtTransOff->connect_toggled(LINK(this, SvxTransparenceTabPage, ClickTransOffHdl_Impl)); + m_xRbtTransLinear->connect_toggled(LINK(this, SvxTransparenceTabPage, ClickTransLinearHdl_Impl)); + m_xRbtTransGradient->connect_toggled(LINK(this, SvxTransparenceTabPage, ClickTransGradientHdl_Impl)); + + // linear transparency + m_xMtrTransparent->set_value(50, FieldUnit::PERCENT); + m_xMtrTransparent->connect_value_changed(LINK(this, SvxTransparenceTabPage, ModifyTransparentHdl_Impl)); + + // gradient transparency + m_xMtrTrgrEndValue->set_value(100, FieldUnit::PERCENT); + m_xMtrTrgrStartValue->set_value(0, FieldUnit::PERCENT); + Link aLink = LINK( this, SvxTransparenceTabPage, ModifiedTrgrEditHdl_Impl); + m_xLbTrgrGradientType->connect_changed(LINK(this, SvxTransparenceTabPage, ModifiedTrgrListBoxHdl_Impl)); + m_xMtrTrgrCenterX->connect_value_changed( aLink ); + m_xMtrTrgrCenterY->connect_value_changed( aLink ); + m_xMtrTrgrAngle->connect_value_changed( aLink ); + m_xMtrTrgrBorder->connect_value_changed( aLink ); + m_xMtrTrgrStartValue->connect_value_changed( aLink ); + m_xMtrTrgrEndValue->connect_value_changed( aLink ); + + // this page needs ExchangeSupport + SetExchangeSupport(); +} + +std::unique_ptr SvxTransparenceTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrs) +{ + return std::make_unique(pPage, pController, *rAttrs); +} + +bool SvxTransparenceTabPage::FillItemSet(SfxItemSet* rAttrs) +{ + const SfxPoolItem* pGradientItem = nullptr; + const SfxPoolItem* pLinearItem = nullptr; + SfxItemState eStateGradient(rOutAttrs.GetItemState(XATTR_FILLFLOATTRANSPARENCE, true, &pGradientItem)); + SfxItemState eStateLinear(rOutAttrs.GetItemState(XATTR_FILLTRANSPARENCE, true, &pLinearItem)); + bool bGradActive = (eStateGradient == SfxItemState::SET && static_cast(pGradientItem)->IsEnabled()); + bool bLinearActive = (eStateLinear == SfxItemState::SET && static_cast(pLinearItem)->GetValue() != 0); + + bool bGradUsed = (eStateGradient == SfxItemState::DONTCARE); + bool bLinearUsed = (eStateLinear == SfxItemState::DONTCARE); + + bool bModified(false); + bool bSwitchOffLinear(false); + bool bSwitchOffGradient(false); + + if (m_xMtrTransparent->get_sensitive()) + { + // linear transparence + sal_uInt16 nPos = m_xMtrTransparent->get_value(FieldUnit::PERCENT); + if (m_xMtrTransparent->get_value_changed_from_saved() || !bLinearActive) + { + XFillTransparenceItem aItem(nPos); + SdrPercentItem aShadowItem(makeSdrShadowTransparenceItem(nPos)); + const SfxPoolItem* pOld = GetOldItem(*rAttrs, XATTR_FILLTRANSPARENCE); + if(!pOld || !(*static_cast(pOld) == aItem) || !bLinearActive) + { + rAttrs->Put(aItem); + rAttrs->Put(aShadowItem); + bModified = true; + bSwitchOffGradient = true; + } + } + } + else if (m_xGridGradient->get_sensitive()) + { + // transparence gradient, fill ItemSet from values + if (!bGradActive + || m_xLbTrgrGradientType->get_value_changed_from_saved() + || m_xMtrTrgrAngle->get_value_changed_from_saved() + || m_xMtrTrgrCenterX->get_value_changed_from_saved() + || m_xMtrTrgrCenterY->get_value_changed_from_saved() + || m_xMtrTrgrBorder->get_value_changed_from_saved() + || m_xMtrTrgrStartValue->get_value_changed_from_saved() + || m_xMtrTrgrEndValue->get_value_changed_from_saved()) + { + sal_uInt8 nStartCol = static_cast((static_cast(m_xMtrTrgrStartValue->get_value(FieldUnit::PERCENT)) * 255) / 100); + sal_uInt8 nEndCol = static_cast((static_cast(m_xMtrTrgrEndValue->get_value(FieldUnit::PERCENT)) * 255) / 100); + XGradient aTmpGradient( + Color(nStartCol, nStartCol, nStartCol), + Color(nEndCol, nEndCol, nEndCol), + static_cast(m_xLbTrgrGradientType->get_active()), + static_cast(m_xMtrTrgrAngle->get_value(FieldUnit::DEGREE)) * 10, + static_cast(m_xMtrTrgrCenterX->get_value(FieldUnit::PERCENT)), + static_cast(m_xMtrTrgrCenterY->get_value(FieldUnit::PERCENT)), + static_cast(m_xMtrTrgrBorder->get_value(FieldUnit::PERCENT)), + 100, 100); + + XFillFloatTransparenceItem aItem(aTmpGradient); + const SfxPoolItem* pOld = GetOldItem(*rAttrs, XATTR_FILLFLOATTRANSPARENCE); + + if(!pOld || !(*static_cast(pOld) == aItem) || !bGradActive) + { + rAttrs->Put(aItem); + bModified = true; + bSwitchOffLinear = true; + } + } + } + else + { + // no transparence + bSwitchOffGradient = true; + bSwitchOffLinear = true; + } + + // disable unused XFillFloatTransparenceItem + if(bSwitchOffGradient && (bGradActive || bGradUsed)) + { + XGradient aGrad(COL_BLACK, COL_WHITE); + aGrad.SetStartIntens(100); + aGrad.SetEndIntens(100); + XFillFloatTransparenceItem aItem(aGrad); + aItem.SetEnabled(false); + rAttrs->Put(aItem); + bModified = true; + } + + // disable unused XFillFloatTransparenceItem + if(bSwitchOffLinear && (bLinearActive || bLinearUsed)) + { + XFillTransparenceItem aItem(0); + SdrPercentItem aShadowItem(makeSdrShadowTransparenceItem(0)); + rAttrs->Put(aItem); + rAttrs->Put(aShadowItem); + bModified = true; + } + rAttrs->Put(CntUInt16Item(SID_PAGE_TYPE, static_cast(nPageType))); + return bModified; +} + +void SvxTransparenceTabPage::Reset(const SfxItemSet* rAttrs) +{ + const SfxPoolItem* pGradientItem = nullptr; + SfxItemState eStateGradient(rAttrs->GetItemState(XATTR_FILLFLOATTRANSPARENCE, true, &pGradientItem)); + if(!pGradientItem) + pGradientItem = &rAttrs->Get(XATTR_FILLFLOATTRANSPARENCE); + bool bGradActive = (eStateGradient == SfxItemState::SET && static_cast(pGradientItem)->IsEnabled()); + + const SfxPoolItem* pLinearItem = nullptr; + SfxItemState eStateLinear(rAttrs->GetItemState(XATTR_FILLTRANSPARENCE, true, &pLinearItem)); + if(!pLinearItem) + pLinearItem = &rAttrs->Get(XATTR_FILLTRANSPARENCE); + bool bLinearActive = (eStateLinear == SfxItemState::SET && static_cast(pLinearItem)->GetValue() != 0); + + // transparence gradient + const XGradient& rGradient = static_cast(pGradientItem)->GetGradientValue(); + css::awt::GradientStyle eXGS(rGradient.GetGradientStyle()); + m_xLbTrgrGradientType->set_active(sal::static_int_cast< sal_Int32 >(eXGS)); + m_xMtrTrgrAngle->set_value(rGradient.GetAngle() / 10, FieldUnit::DEGREE); + m_xMtrTrgrBorder->set_value(rGradient.GetBorder(), FieldUnit::PERCENT); + m_xMtrTrgrCenterX->set_value(rGradient.GetXOffset(), FieldUnit::PERCENT); + m_xMtrTrgrCenterY->set_value(rGradient.GetYOffset(), FieldUnit::PERCENT); + m_xMtrTrgrStartValue->set_value(static_cast(((static_cast(rGradient.GetStartColor().GetRed()) + 1) * 100) / 255), FieldUnit::PERCENT); + m_xMtrTrgrEndValue->set_value(static_cast(((static_cast(rGradient.GetEndColor().GetRed()) + 1) * 100) / 255), FieldUnit::PERCENT); + + // linear transparence + sal_uInt16 nTransp = static_cast(pLinearItem)->GetValue(); + m_xMtrTransparent->set_value(bLinearActive ? nTransp : 50, FieldUnit::PERCENT); + ModifyTransparentHdl_Impl(*m_xMtrTransparent); + + // select the correct radio button + if(bGradActive) + { + // transparence gradient, set controls appropriate to item + m_xRbtTransGradient->set_active(true); + ClickTransGradientHdl_Impl(*m_xRbtTransGradient); + } + else if(bLinearActive) + { + // linear transparence + m_xRbtTransLinear->set_active(true); + ClickTransLinearHdl_Impl(*m_xRbtTransLinear); + } + else + { + // no transparence + m_xRbtTransOff->set_active(true); + ClickTransOffHdl_Impl(*m_xRbtTransOff); + ModifiedTrgrHdl_Impl(nullptr); + } + + // save values + ChangesApplied(); + bool bActive = InitPreview ( *rAttrs ); + InvalidatePreview ( bActive ); +} + +void SvxTransparenceTabPage::ChangesApplied() +{ + m_xMtrTransparent->save_value(); + m_xLbTrgrGradientType->save_value(); + m_xMtrTrgrCenterX->save_value(); + m_xMtrTrgrCenterY->save_value(); + m_xMtrTrgrAngle->save_value(); + m_xMtrTrgrBorder->save_value(); + m_xMtrTrgrStartValue->save_value(); + m_xMtrTrgrEndValue->save_value(); +} + +void SvxTransparenceTabPage::ActivatePage(const SfxItemSet& rSet) +{ + const CntUInt16Item* pPageTypeItem = rSet.GetItem(SID_PAGE_TYPE, false); + if (pPageTypeItem) + SetPageType(static_cast(pPageTypeItem->GetValue())); + + if(nDlgType == 0) // area dialog + nPageType = PageType::Transparence; + + InitPreview ( rSet ); +} + +DeactivateRC SvxTransparenceTabPage::DeactivatePage(SfxItemSet* _pSet) +{ + if( _pSet ) + FillItemSet( _pSet ); + return DeactivateRC::LeavePage; +} + +// Preview-Methods + +bool SvxTransparenceTabPage::InitPreview(const SfxItemSet& rSet) +{ + // set transparencetype for preview + if (m_xRbtTransOff->get_active()) + { + ClickTransOffHdl_Impl(*m_xRbtTransOff); + } + else if (m_xRbtTransLinear->get_active()) + { + ClickTransLinearHdl_Impl(*m_xRbtTransLinear); + } + else if (m_xRbtTransGradient->get_active()) + { + ClickTransGradientHdl_Impl(*m_xRbtTransGradient); + } + + // Get fillstyle for preview + rXFSet.Put ( rSet.Get(XATTR_FILLSTYLE) ); + rXFSet.Put ( rSet.Get(XATTR_FILLCOLOR) ); + rXFSet.Put ( rSet.Get(XATTR_FILLGRADIENT) ); + rXFSet.Put ( rSet.Get(XATTR_FILLHATCH) ); + rXFSet.Put ( rSet.Get(XATTR_FILLBACKGROUND) ); + rXFSet.Put ( rSet.Get(XATTR_FILLBITMAP) ); + + m_aCtlXRectPreview.SetAttributes( aXFillAttr.GetItemSet() ); + m_aCtlBitmapPreview.SetAttributes( aXFillAttr.GetItemSet() ); + + bBitmap = rSet.Get(XATTR_FILLSTYLE).GetValue() == drawing::FillStyle_BITMAP; + + // show the right preview window + if ( bBitmap ) + { + m_xCtlBitmapBorder->show(); + m_xCtlXRectBorder->hide(); + } + else + { + m_xCtlBitmapBorder->hide(); + m_xCtlXRectBorder->show(); + } + + return !m_xRbtTransOff->get_active(); +} + +void SvxTransparenceTabPage::InvalidatePreview (bool bEnable) +{ + if ( bBitmap ) + { + if ( bEnable ) + { + m_xCtlBitmapPreview->set_sensitive(true); + m_aCtlBitmapPreview.SetAttributes( aXFillAttr.GetItemSet() ); + } + else + m_xCtlBitmapPreview->set_sensitive(false); + m_xCtlBitmapPreview->queue_draw(); + } + else + { + if ( bEnable ) + { + m_xCtlXRectPreview->set_sensitive(true); + m_aCtlXRectPreview.SetAttributes( aXFillAttr.GetItemSet() ); + } + else + m_xCtlXRectPreview->set_sensitive(false); + m_xCtlXRectPreview->queue_draw(); + } +} + +void SvxTransparenceTabPage::PageCreated(const SfxAllItemSet& aSet) +{ + const SfxUInt16Item* pPageTypeItem = aSet.GetItem(SID_PAGE_TYPE, false); + const SfxUInt16Item* pDlgTypeItem = aSet.GetItem(SID_DLG_TYPE, false); + + if (pPageTypeItem) + SetPageType(static_cast(pPageTypeItem->GetValue())); + if (pDlgTypeItem) + SetDlgType(pDlgTypeItem->GetValue()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/transfrm.cxx b/cui/source/tabpages/transfrm.cxx new file mode 100644 index 000000000..77c3b7e7e --- /dev/null +++ b/cui/source/tabpages/transfrm.cxx @@ -0,0 +1,1584 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +// static ---------------------------------------------------------------- + +const sal_uInt16 SvxPositionSizeTabPage::pPosSizeRanges[] = +{ + SID_ATTR_TRANSFORM_POS_X, + SID_ATTR_TRANSFORM_POS_Y, + SID_ATTR_TRANSFORM_PROTECT_POS, + SID_ATTR_TRANSFORM_PROTECT_POS, + SID_ATTR_TRANSFORM_INTERN, + SID_ATTR_TRANSFORM_INTERN, + SID_ATTR_TRANSFORM_ANCHOR, + SID_ATTR_TRANSFORM_VERT_ORIENT, + SID_ATTR_TRANSFORM_WIDTH, + SID_ATTR_TRANSFORM_SIZE_POINT, + SID_ATTR_TRANSFORM_PROTECT_POS, + SID_ATTR_TRANSFORM_INTERN, + SID_ATTR_TRANSFORM_AUTOWIDTH, + SID_ATTR_TRANSFORM_AUTOHEIGHT, + 0 +}; + +const sal_uInt16 SvxAngleTabPage::pAngleRanges[] = +{ + SID_ATTR_TRANSFORM_ROT_X, + SID_ATTR_TRANSFORM_ANGLE, + SID_ATTR_TRANSFORM_INTERN, + SID_ATTR_TRANSFORM_INTERN, + 0 +}; + +const sal_uInt16 SvxSlantTabPage::pSlantRanges[] = +{ + SDRATTR_ECKENRADIUS, + SDRATTR_ECKENRADIUS, + SID_ATTR_TRANSFORM_SHEAR, + SID_ATTR_TRANSFORM_SHEAR_VERTICAL, + SID_ATTR_TRANSFORM_INTERN, + SID_ATTR_TRANSFORM_INTERN, + 0 +}; + +/************************************************************************* +|* +|* constructor of the tab dialog: adds the pages to the dialog +|* +\************************************************************************/ + +SvxTransformTabDialog::SvxTransformTabDialog(weld::Window* pParent, const SfxItemSet* pAttr, + const SdrView* pSdrView, SvxAnchorIds nAnchorTypes) + : SfxTabDialogController(pParent, "cui/ui/positionsizedialog.ui", "PositionAndSizeDialog", pAttr) + , pView(pSdrView) + , nAnchorCtrls(nAnchorTypes) +{ + DBG_ASSERT(pView, "no valid view (!)"); + + //different positioning page in Writer + if(nAnchorCtrls & (SvxAnchorIds::Paragraph | SvxAnchorIds::Character | SvxAnchorIds::Page | SvxAnchorIds::Fly)) + { + AddTabPage("RID_SVXPAGE_SWPOSSIZE", SvxSwPosSizeTabPage::Create, SvxSwPosSizeTabPage::GetRanges); + RemoveTabPage("RID_SVXPAGE_POSITION_SIZE"); + } + else + { + AddTabPage("RID_SVXPAGE_POSITION_SIZE", SvxPositionSizeTabPage::Create, SvxPositionSizeTabPage::GetRanges); + RemoveTabPage("RID_SVXPAGE_SWPOSSIZE"); + } + + AddTabPage("RID_SVXPAGE_ANGLE", SvxAngleTabPage::Create, SvxAngleTabPage::GetRanges); + AddTabPage("RID_SVXPAGE_SLANT", SvxSlantTabPage::Create, SvxSlantTabPage::GetRanges); +} + + +void SvxTransformTabDialog::PageCreated(const OString& rId, SfxTabPage &rPage) +{ + if (rId == "RID_SVXPAGE_POSITION_SIZE") + { + SvxPositionSizeTabPage& rSvxPos = static_cast(rPage); + rSvxPos.SetView(pView); + rSvxPos.Construct(); + + if(nAnchorCtrls & SvxAnchorIds::NoResize) + { + rSvxPos.DisableResize(); + } + + if(nAnchorCtrls & SvxAnchorIds::NoProtect) + { + rSvxPos.DisableProtect(); + rSvxPos.UpdateControlStates(); + } + } + else if (rId == "RID_SVXPAGE_SWPOSSIZE") + { + SvxSwPosSizeTabPage& rSwPos = static_cast(rPage); + + rSwPos.EnableAnchorTypes(nAnchorCtrls); + rSwPos.SetValidateFramePosLink(aValidateLink); + rSwPos.SetView(pView); + } + else if (rId == "RID_SVXPAGE_ANGLE") + { + SvxAngleTabPage& rSvxAng = static_cast(rPage); + + rSvxAng.SetView( pView ); + rSvxAng.Construct(); + } + else if (rId == "RID_SVXPAGE_SLANT") + { + SvxSlantTabPage& rSvxSlnt = static_cast(rPage); + + rSvxSlnt.SetView( pView ); + rSvxSlnt.Construct(); + } +} + +void SvxTransformTabDialog::SetValidateFramePosLink(const Link& rLink) +{ + aValidateLink = rLink; +} + +/************************************************************************* +|* +|* dialog for changing the positions of the rotation +|* angle and the rotation angle of the graphic objects +|* +\************************************************************************/ +SvxAngleTabPage::SvxAngleTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SvxTabPage(pPage, pController, "cui/ui/rotationtabpage.ui", "Rotation", rInAttrs) + , pView(nullptr) + , eDlgUnit(FieldUnit::NONE) + , m_aCtlRect(this) + , m_xFlPosition(m_xBuilder->weld_widget("FL_POSITION")) + , m_xMtrPosX(m_xBuilder->weld_metric_spin_button("MTR_FLD_POS_X", FieldUnit::CM)) + , m_xMtrPosY(m_xBuilder->weld_metric_spin_button("MTR_FLD_POS_Y", FieldUnit::CM)) + , m_xCtlRect(new weld::CustomWeld(*m_xBuilder, "CTL_RECT", m_aCtlRect)) + , m_xFlAngle(m_xBuilder->weld_widget("FL_ANGLE")) + , m_xNfAngle(m_xBuilder->weld_metric_spin_button("NF_ANGLE", FieldUnit::DEGREE)) + , m_xCtlAngle(new svx::DialControl) + , m_xCtlAngleWin(new weld::CustomWeld(*m_xBuilder, "CTL_ANGLE", *m_xCtlAngle)) +{ + // calculate PoolUnit + SfxItemPool* pPool = rInAttrs.GetPool(); + DBG_ASSERT( pPool, "no pool (!)" ); + ePoolUnit = pPool->GetMetric(SID_ATTR_TRANSFORM_POS_X); + + m_xCtlAngle->SetLinkedField(m_xNfAngle.get(), 2); +} + +SvxAngleTabPage::~SvxAngleTabPage() +{ +} + +void SvxAngleTabPage::Construct() +{ + DBG_ASSERT(pView, "No valid view (!)"); + eDlgUnit = GetModuleFieldUnit(GetItemSet()); + SetFieldUnit(*m_xMtrPosX, eDlgUnit, true); + SetFieldUnit(*m_xMtrPosY, eDlgUnit, true); + + if (FieldUnit::MILE == eDlgUnit || FieldUnit::KM == eDlgUnit) + { + m_xMtrPosX->set_digits(3); + m_xMtrPosY->set_digits(3); + } + + { // #i75273# + ::tools::Rectangle aTempRect(pView->GetAllMarkedRect()); + pView->GetSdrPageView()->LogicToPagePos(aTempRect); + maRange = vcl::unotools::b2DRectangleFromRectangle(aTempRect); + } + + // Take anchor into account (Writer) + const SdrMarkList& rMarkList = pView->GetMarkedObjectList(); + + if(rMarkList.GetMarkCount()) + { + const SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); + maAnchor = basegfx::B2DPoint(pObj->GetAnchorPos().X(), pObj->GetAnchorPos().Y()); + + if(!maAnchor.equalZero()) // -> Writer + { + maRange = basegfx::B2DRange(maRange.getMinimum() - maAnchor, maRange.getMaximum() - maAnchor); + } + } + + // take scale into account + const Fraction aUIScale(pView->GetModel()->GetUIScale()); + TransfrmHelper::ScaleRect(maRange, aUIScale); + + // take UI units into account + sal_uInt16 nDigits(m_xMtrPosX->get_digits()); + TransfrmHelper::ConvertRect(maRange, nDigits, ePoolUnit, eDlgUnit); + + if(!pView->IsRotateAllowed()) + { + m_xFlPosition->set_sensitive(false); + m_xFlAngle->set_sensitive(false); + } +} + +bool SvxAngleTabPage::FillItemSet(SfxItemSet* rSet) +{ + bool bModified = false; + + if (m_xCtlAngle->IsValueModified() || m_xMtrPosX->get_value_changed_from_saved() || m_xMtrPosY->get_value_changed_from_saved()) + { + const double fUIScale(double(pView->GetModel()->GetUIScale())); + const double fTmpX((GetCoreValue(*m_xMtrPosX, ePoolUnit) + maAnchor.getX()) * fUIScale); + const double fTmpY((GetCoreValue(*m_xMtrPosY, ePoolUnit) + maAnchor.getY()) * fUIScale); + + rSet->Put(SfxInt32Item(GetWhich(SID_ATTR_TRANSFORM_ANGLE), m_xCtlAngle->GetRotation())); + rSet->Put(SfxInt32Item(GetWhich(SID_ATTR_TRANSFORM_ROT_X), basegfx::fround(fTmpX))); + rSet->Put(SfxInt32Item(GetWhich(SID_ATTR_TRANSFORM_ROT_Y), basegfx::fround(fTmpY))); + + bModified = true; + } + + return bModified; +} + + +void SvxAngleTabPage::Reset(const SfxItemSet* rAttrs) +{ + const double fUIScale(double(pView->GetModel()->GetUIScale())); + + const SfxPoolItem* pItem = GetItem( *rAttrs, SID_ATTR_TRANSFORM_ROT_X ); + if(pItem) + { + const double fTmp((static_cast(static_cast(pItem)->GetValue()) - maAnchor.getX()) / fUIScale); + SetMetricValue(*m_xMtrPosX, basegfx::fround(fTmp), ePoolUnit); + } + else + { + m_xMtrPosX->set_text(OUString()); + } + + pItem = GetItem(*rAttrs, SID_ATTR_TRANSFORM_ROT_Y); + if(pItem) + { + const double fTmp((static_cast(static_cast(pItem)->GetValue()) - maAnchor.getY()) / fUIScale); + SetMetricValue(*m_xMtrPosY, basegfx::fround(fTmp), ePoolUnit); + } + else + { + m_xMtrPosY->set_text(OUString()); + } + + pItem = GetItem( *rAttrs, SID_ATTR_TRANSFORM_ANGLE ); + if(pItem) + { + m_xCtlAngle->SetRotation(static_cast(pItem)->GetValue()); + } + else + { + m_xCtlAngle->SetRotation(0); + } + m_xCtlAngle->SaveValue(); + m_xMtrPosX->save_value(); + m_xMtrPosY->save_value(); +} + +std::unique_ptr SvxAngleTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet) +{ + return std::make_unique(pPage, pController, *rSet); +} + +void SvxAngleTabPage::ActivatePage(const SfxItemSet& rSet) +{ + SfxBoolItem const * bPosProtect = nullptr; + if(SfxItemState::SET == rSet.GetItemState( GetWhich(SID_ATTR_TRANSFORM_PROTECT_POS ) , false, reinterpret_cast(&bPosProtect) )) + { + m_xFlPosition->set_sensitive(!bPosProtect->GetValue()); + m_xFlAngle->set_sensitive(!bPosProtect->GetValue()); + } +} + +DeactivateRC SvxAngleTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if(_pSet) + { + FillItemSet(_pSet); + } + + return DeactivateRC::LeavePage; +} + +void SvxAngleTabPage::PointChanged(weld::DrawingArea* pDrawingArea, RectPoint eRP) +{ + if (pDrawingArea != m_aCtlRect.GetDrawingArea()) + return; + + switch(eRP) + { + case RectPoint::LT: + { + m_xMtrPosX->set_value( basegfx::fround64(maRange.getMinX()), FieldUnit::NONE ); + m_xMtrPosY->set_value( basegfx::fround64(maRange.getMinY()), FieldUnit::NONE ); + break; + } + case RectPoint::MT: + { + m_xMtrPosX->set_value( basegfx::fround64(maRange.getCenter().getX()), FieldUnit::NONE ); + m_xMtrPosY->set_value( basegfx::fround64(maRange.getMinY()), FieldUnit::NONE ); + break; + } + case RectPoint::RT: + { + m_xMtrPosX->set_value( basegfx::fround64(maRange.getMaxX()), FieldUnit::NONE ); + m_xMtrPosY->set_value( basegfx::fround64(maRange.getMinY()), FieldUnit::NONE ); + break; + } + case RectPoint::LM: + { + m_xMtrPosX->set_value( basegfx::fround64(maRange.getMinX()), FieldUnit::NONE ); + m_xMtrPosY->set_value( basegfx::fround64(maRange.getCenter().getY()), FieldUnit::NONE ); + break; + } + case RectPoint::MM: + { + m_xMtrPosX->set_value( basegfx::fround64(maRange.getCenter().getX()), FieldUnit::NONE ); + m_xMtrPosY->set_value( basegfx::fround64(maRange.getCenter().getY()), FieldUnit::NONE ); + break; + } + case RectPoint::RM: + { + m_xMtrPosX->set_value( basegfx::fround64(maRange.getMaxX()), FieldUnit::NONE ); + m_xMtrPosY->set_value( basegfx::fround64(maRange.getCenter().getY()), FieldUnit::NONE ); + break; + } + case RectPoint::LB: + { + m_xMtrPosX->set_value( basegfx::fround64(maRange.getMinX()), FieldUnit::NONE ); + m_xMtrPosY->set_value( basegfx::fround64(maRange.getMaxY()), FieldUnit::NONE ); + break; + } + case RectPoint::MB: + { + m_xMtrPosX->set_value( basegfx::fround64(maRange.getCenter().getX()), FieldUnit::NONE ); + m_xMtrPosY->set_value( basegfx::fround64(maRange.getMaxY()), FieldUnit::NONE ); + break; + } + case RectPoint::RB: + { + m_xMtrPosX->set_value( basegfx::fround64(maRange.getMaxX()), FieldUnit::NONE ); + m_xMtrPosY->set_value( basegfx::fround64(maRange.getMaxY()), FieldUnit::NONE ); + break; + } + } +} + +/************************************************************************* +|* +|* dialog for changing slant and corner radius +|* +\************************************************************************/ +SvxSlantTabPage::SvxSlantTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "cui/ui/slantcornertabpage.ui", "SlantAndCornerRadius", &rInAttrs) + , pView(nullptr) + , eDlgUnit(FieldUnit::NONE) + , m_xFlRadius(m_xBuilder->weld_widget("FL_RADIUS")) + , m_xMtrRadius(m_xBuilder->weld_metric_spin_button("MTR_FLD_RADIUS", FieldUnit::CM)) + , m_xFlAngle(m_xBuilder->weld_widget("FL_SLANT")) + , m_xMtrAngle(m_xBuilder->weld_metric_spin_button("MTR_FLD_ANGLE", FieldUnit::DEGREE)) +{ + for (int i = 0; i < 2; ++i) + { + m_aControlGroups[i] = m_xBuilder->weld_widget("controlgroups" + OString::number(i+1)); + m_aControlGroupX[i] = m_xBuilder->weld_widget("controlgroupx" + OString::number(i+1)); + m_aControlX[i] = m_xBuilder->weld_metric_spin_button("controlx" + OString::number(i+1), FieldUnit::CM); + m_aControlGroupY[i] = m_xBuilder->weld_widget("controlgroupy" + OString::number(i+1)); + m_aControlY[i] = m_xBuilder->weld_metric_spin_button("controly" + OString::number(i+1), FieldUnit::CM); + } + + // this page needs ExchangeSupport + SetExchangeSupport(); + + // evaluate PoolUnit + SfxItemPool* pPool = rInAttrs.GetPool(); + assert(pPool && "no pool (!)"); + ePoolUnit = pPool->GetMetric( SID_ATTR_TRANSFORM_POS_X ); +} + +SvxSlantTabPage::~SvxSlantTabPage() +{ +} + +void SvxSlantTabPage::Construct() +{ + // get the range + DBG_ASSERT(pView, "no valid view (!)"); + eDlgUnit = GetModuleFieldUnit(GetItemSet()); + SetFieldUnit(*m_xMtrRadius, eDlgUnit, true); + for (int i = 0; i < 2; ++i) + { + SetFieldUnit(*m_aControlX[i], eDlgUnit, true); + SetFieldUnit(*m_aControlY[i], eDlgUnit, true); + } + + { // #i75273# + ::tools::Rectangle aTempRect(pView->GetAllMarkedRect()); + pView->GetSdrPageView()->LogicToPagePos(aTempRect); + } +} + +bool SvxSlantTabPage::FillItemSet(SfxItemSet* rAttrs) +{ + bool bModified = false; + + if (m_xMtrRadius->get_value_changed_from_saved()) + { + Fraction aUIScale = pView->GetModel()->GetUIScale(); + long nTmp = long(GetCoreValue(*m_xMtrRadius, ePoolUnit) * aUIScale); + + rAttrs->Put( makeSdrEckenradiusItem( nTmp ) ); + bModified = true; + } + + if (m_xMtrAngle->get_value_changed_from_saved()) + { + sal_Int32 nValue = static_cast(m_xMtrAngle->get_value(FieldUnit::NONE)); + rAttrs->Put( SfxInt32Item( SID_ATTR_TRANSFORM_SHEAR, nValue ) ); + bModified = true; + } + + if( bModified ) + { + // set reference points + ::tools::Rectangle aObjectRect(pView->GetAllMarkedRect()); + pView->GetSdrPageView()->LogicToPagePos(aObjectRect); + Point aPt = aObjectRect.Center(); + + rAttrs->Put(SfxInt32Item(SID_ATTR_TRANSFORM_SHEAR_X, aPt.X())); + rAttrs->Put(SfxInt32Item(SID_ATTR_TRANSFORM_SHEAR_Y, aPt.Y())); + rAttrs->Put( SfxBoolItem( SID_ATTR_TRANSFORM_SHEAR_VERTICAL, false ) ); + } + + bool bControlPointsChanged = false; + for (int i = 0; i < 2; ++i) + { + bControlPointsChanged |= (m_aControlX[i]->get_value_changed_from_saved() || + m_aControlY[i]->get_value_changed_from_saved()); + } + + if (!bControlPointsChanged) + return bModified; + + bool bSelectionIsSdrObjCustomShape(false); + + while(true) + { + if(nullptr == pView) + { + break; + } + + if(0 == pView->GetMarkedObjectList().GetMarkCount()) + { + break; + } + + SdrObject* pCandidate(pView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj()); + + if(nullptr == pCandidate) + { + break; + } + + if(nullptr == dynamic_cast< SdrObjCustomShape* >(pCandidate)) + { + break; + } + + bSelectionIsSdrObjCustomShape = true; + break; + } + + if(bSelectionIsSdrObjCustomShape) + { + SdrObjCustomShape& rSdrObjCustomShape( + static_cast< SdrObjCustomShape& >( + *pView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj())); + SdrModel& rModel(rSdrObjCustomShape.getSdrModelFromSdrObject()); + std::unique_ptr pUndo; + if (rModel.IsUndoEnabled()) + pUndo = rModel.GetSdrUndoFactory().CreateUndoAttrObject(rSdrObjCustomShape); + + if(pUndo) + { + rModel.BegUndo(pUndo->GetComment()); + } + + EnhancedCustomShape2d aShape(rSdrObjCustomShape); + ::tools::Rectangle aLogicRect = aShape.GetLogicRect(); + + for (int i = 0; i < 2; ++i) + { + if (m_aControlX[i]->get_value_changed_from_saved() || m_aControlY[i]->get_value_changed_from_saved()) + { + Point aNewPosition(GetCoreValue(*m_aControlX[i], ePoolUnit), + GetCoreValue(*m_aControlY[i], ePoolUnit)); + aNewPosition.Move(aLogicRect.Left(), aLogicRect.Top()); + + css::awt::Point aPosition; + aPosition.X = aNewPosition.X(); + aPosition.Y = aNewPosition.Y(); + + aShape.SetHandleControllerPosition(i, aPosition); + } + } + + rSdrObjCustomShape.SetChanged(); + rSdrObjCustomShape.BroadcastObjectChange(); + bModified = true; + + if (pUndo) + { + rModel.AddUndo(std::move(pUndo)); + rModel.EndUndo(); + } + } + + return bModified; +} + +void SvxSlantTabPage::Reset(const SfxItemSet* rAttrs) +{ + // if the view has selected objects, items with SfxItemState::DEFAULT need to be disabled + const SfxPoolItem* pItem; + + // corner radius + if(!pView->IsEdgeRadiusAllowed()) + { + m_xMtrRadius->set_text(""); + m_xFlRadius->set_sensitive(false); + } + else + { + pItem = GetItem( *rAttrs, SDRATTR_ECKENRADIUS ); + + if( pItem ) + { + const double fUIScale(double(pView->GetModel()->GetUIScale())); + const double fTmp(static_cast(static_cast(pItem)->GetValue()) / fUIScale); + SetMetricValue(*m_xMtrRadius, basegfx::fround(fTmp), ePoolUnit); + } + else + { + m_xMtrRadius->set_text(""); + } + } + + m_xMtrRadius->save_value(); + + // slant: angle + if( !pView->IsShearAllowed() ) + { + m_xMtrAngle->set_text( "" ); + m_xFlAngle->set_sensitive(false); + } + else + { + pItem = GetItem( *rAttrs, SID_ATTR_TRANSFORM_SHEAR ); + + if( pItem ) + { + m_xMtrAngle->set_value(static_cast(pItem)->GetValue(), FieldUnit::NONE); + } + else + { + m_xMtrAngle->set_text(""); + } + } + + m_xMtrAngle->save_value(); + + bool bSelectionIsSdrObjCustomShape(false); + + while(true) + { + if(1 != pView->GetMarkedObjectList().GetMarkCount()) + { + break; + } + + SdrObject* pCandidate(pView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj()); + + if(nullptr == pCandidate) + { + break; + } + + if(nullptr == dynamic_cast< SdrObjCustomShape* >(pCandidate)) + { + break; + } + + bSelectionIsSdrObjCustomShape = true; + break; + } + + if(bSelectionIsSdrObjCustomShape) + { + SdrObjCustomShape& rSdrObjCustomShape( + static_cast< SdrObjCustomShape& >( + *pView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj())); + + //save geometry + SdrCustomShapeGeometryItem aInitialGeometry(rSdrObjCustomShape.GetMergedItem(SDRATTR_CUSTOMSHAPE_GEOMETRY)); + EnhancedCustomShape2d aShape(rSdrObjCustomShape); + + for (int i = 0; i < 2; ++i) + { + Point aInitialPosition; + if (!aShape.GetHandlePosition(i, aInitialPosition)) + break; + m_aControlGroups[i]->set_sensitive(true); + css::awt::Point aPosition; + + aPosition.X = SAL_MAX_INT32/2; + aPosition.Y = SAL_MAX_INT32/2; + aShape.SetHandleControllerPosition(i, aPosition); + Point aMaxPosition; + aShape.GetHandlePosition(i, aMaxPosition); + + aPosition.X = SAL_MIN_INT32/2; + aPosition.Y = SAL_MIN_INT32/2; + aShape.SetHandleControllerPosition(i, aPosition); + Point aMinPosition; + aShape.GetHandlePosition(i, aMinPosition); + + ::tools::Rectangle aLogicRect = aShape.GetLogicRect(); + aInitialPosition.Move(-aLogicRect.Left(), -aLogicRect.Top()); + aMaxPosition.Move(-aLogicRect.Left(), -aLogicRect.Top()); + aMinPosition.Move(-aLogicRect.Left(), -aLogicRect.Top()); + + SetMetricValue(*m_aControlX[i], aInitialPosition.X(), ePoolUnit); + SetMetricValue(*m_aControlY[i], aInitialPosition.Y(), ePoolUnit); + + if (aMaxPosition.X() == aMinPosition.X()) + m_aControlGroupX[i]->set_sensitive(false); + else + m_aControlX[i]->set_range(aMinPosition.X(), aMaxPosition.X(), FieldUnit::MM); + if (aMaxPosition.Y() == aMinPosition.Y()) + m_aControlGroupY[i]->set_sensitive(false); + else + m_aControlY[i]->set_range(aMinPosition.Y(), aMaxPosition.Y(), FieldUnit::MM); + } + + //restore geometry + rSdrObjCustomShape.SetMergedItem(aInitialGeometry); + } + + for (int i = 0; i < 2; ++i) + { + m_aControlX[i]->save_value(); + m_aControlY[i]->save_value(); + } +} + +std::unique_ptr SvxSlantTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rOutAttrs) +{ + return std::make_unique(pPage, pController, *rOutAttrs); +} + +void SvxSlantTabPage::ActivatePage( const SfxItemSet& rSet ) +{ + SfxBoolItem const * bPosProtect = nullptr; + if(SfxItemState::SET == rSet.GetItemState( GetWhich(SID_ATTR_TRANSFORM_PROTECT_POS ) , false, reinterpret_cast(&bPosProtect) )) + { + m_xFlAngle->set_sensitive(!bPosProtect->GetValue()); + } + SfxBoolItem const * bSizeProtect = nullptr; + if(SfxItemState::SET == rSet.GetItemState( GetWhich(SID_ATTR_TRANSFORM_PROTECT_SIZE ) , false, reinterpret_cast(&bSizeProtect) )) + { + m_xFlAngle->set_sensitive(!bSizeProtect->GetValue()); + } + +} + +DeactivateRC SvxSlantTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if(_pSet) + { + FillItemSet(_pSet); + } + + return DeactivateRC::LeavePage; +} + + +/************************************************************************* +|* +|* Dialog for changing position and size of graphic objects +|* +\************************************************************************/ +SvxPositionSizeTabPage::SvxPositionSizeTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SvxTabPage(pPage, pController, "cui/ui/possizetabpage.ui", "PositionAndSize", rInAttrs) + , mrOutAttrs(rInAttrs) + , mpView(nullptr) + , meDlgUnit(FieldUnit::NONE) + , mnProtectSizeState(TRISTATE_FALSE) + , mbPageDisabled(false) + , mbProtectDisabled(false) + , mbSizeDisabled(false) + , mbAdjustDisabled(true) + , mbIgnoreAutoGrowWidth(true) + , mbIgnoreAutoGrowHeight(true) + , mfOldWidth(0.0) + , mfOldHeight(0.0) + , m_aCtlPos(this) + , m_aCtlSize(this) + , m_xFlPosition(m_xBuilder->weld_widget("FL_POSITION")) + , m_xMtrPosX(m_xBuilder->weld_metric_spin_button("MTR_FLD_POS_X", FieldUnit::CM)) + , m_xMtrPosY(m_xBuilder->weld_metric_spin_button("MTR_FLD_POS_Y", FieldUnit::CM)) + , m_xCtlPos(new weld::CustomWeld(*m_xBuilder, "CTL_POSRECT", m_aCtlPos)) + , m_xFlSize(m_xBuilder->weld_widget("FL_SIZE")) + , m_xFtWidth(m_xBuilder->weld_label("FT_WIDTH")) + , m_xMtrWidth(m_xBuilder->weld_metric_spin_button("MTR_FLD_WIDTH", FieldUnit::CM)) + , m_xFtHeight(m_xBuilder->weld_label("FT_HEIGHT")) + , m_xMtrHeight(m_xBuilder->weld_metric_spin_button("MTR_FLD_HEIGHT", FieldUnit::CM)) + , m_xCbxScale(m_xBuilder->weld_check_button("CBX_SCALE")) + , m_xCtlSize(new weld::CustomWeld(*m_xBuilder, "CTL_SIZERECT", m_aCtlSize)) + , m_xFlProtect(m_xBuilder->weld_widget("FL_PROTECT")) + , m_xTsbPosProtect(m_xBuilder->weld_check_button("TSB_POSPROTECT")) + , m_xTsbSizeProtect(m_xBuilder->weld_check_button("TSB_SIZEPROTECT")) + , m_xFlAdjust(m_xBuilder->weld_widget("FL_ADJUST")) + , m_xTsbAutoGrowWidth(m_xBuilder->weld_check_button("TSB_AUTOGROW_WIDTH")) + , m_xTsbAutoGrowHeight(m_xBuilder->weld_check_button("TSB_AUTOGROW_HEIGHT")) +{ + // this page needs ExchangeSupport + SetExchangeSupport(); + + // evaluate PoolUnit + SfxItemPool* pPool = mrOutAttrs.GetPool(); + DBG_ASSERT( pPool, "no pool (!)" ); + mePoolUnit = pPool->GetMetric( SID_ATTR_TRANSFORM_POS_X ); + + m_aCtlPos.SetActualRP(RectPoint::LT); + m_aCtlSize.SetActualRP(RectPoint::LT); + meRP = RectPoint::LT; // see above + + m_xMtrWidth->connect_value_changed( LINK( this, SvxPositionSizeTabPage, ChangeWidthHdl ) ); + m_xMtrHeight->connect_value_changed( LINK( this, SvxPositionSizeTabPage, ChangeHeightHdl ) ); + m_xCbxScale->connect_toggled( LINK( this, SvxPositionSizeTabPage, ClickAutoHdl ) ); + + m_xFlAdjust->set_sensitive(false); + + // #i2379# disable controls when protected + m_xTsbPosProtect->connect_toggled( LINK( this, SvxPositionSizeTabPage, ChangePosProtectHdl ) ); + m_xTsbSizeProtect->connect_toggled( LINK( this, SvxPositionSizeTabPage, ChangeSizeProtectHdl ) ); +} + +SvxPositionSizeTabPage::~SvxPositionSizeTabPage() +{ +} + +void SvxPositionSizeTabPage::Construct() +{ + // get range and work area + DBG_ASSERT( mpView, "no valid view (!)" ); + meDlgUnit = GetModuleFieldUnit( GetItemSet() ); + SetFieldUnit( *m_xMtrPosX, meDlgUnit, true ); + SetFieldUnit( *m_xMtrPosY, meDlgUnit, true ); + SetFieldUnit( *m_xMtrWidth, meDlgUnit, true ); + SetFieldUnit( *m_xMtrHeight, meDlgUnit, true ); + + if(FieldUnit::MILE == meDlgUnit || FieldUnit::KM == meDlgUnit) + { + m_xMtrPosX->set_digits( 3 ); + m_xMtrPosY->set_digits( 3 ); + m_xMtrWidth->set_digits( 3 ); + m_xMtrHeight->set_digits( 3 ); + } + + { // #i75273# + ::tools::Rectangle aTempRect(mpView->GetAllMarkedRect()); + mpView->GetSdrPageView()->LogicToPagePos(aTempRect); + maRange = vcl::unotools::b2DRectangleFromRectangle(aTempRect); + } + + { // #i75273# + ::tools::Rectangle aTempRect(mpView->GetWorkArea()); + mpView->GetSdrPageView()->LogicToPagePos(aTempRect); + maWorkRange = vcl::unotools::b2DRectangleFromRectangle(aTempRect); + } + + // take anchor into account (Writer) + const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); + + if(rMarkList.GetMarkCount()) + { + const SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); + maAnchor = basegfx::B2DPoint(pObj->GetAnchorPos().X(), pObj->GetAnchorPos().Y()); + + if(!maAnchor.equalZero()) // -> Writer + { + for(size_t i = 1; i < rMarkList.GetMarkCount(); ++i) + { + pObj = rMarkList.GetMark(i)->GetMarkedSdrObj(); + + if(maAnchor != basegfx::B2DPoint(pObj->GetAnchorPos().X(), pObj->GetAnchorPos().Y())) + { + // different anchor positions + m_xMtrPosX->set_text(""); + m_xMtrPosY->set_text(""); + mbPageDisabled = true; + return; + } + } + + // translate ranges about anchor + maRange = basegfx::B2DRange(maRange.getMinimum() - maAnchor, maRange.getMaximum() - maAnchor); + maWorkRange = basegfx::B2DRange(maWorkRange.getMinimum() - maAnchor, maWorkRange.getMaximum() - maAnchor); + } + } + + // this should happen via SID_ATTR_TRANSFORM_AUTOSIZE + if(1 == rMarkList.GetMarkCount()) + { + const SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); + const SdrObjKind eKind(static_cast(pObj->GetObjIdentifier())); + + if((pObj->GetObjInventor() == SdrInventor::Default) && + (OBJ_TEXT == eKind || OBJ_TITLETEXT == eKind || OBJ_OUTLINETEXT == eKind) && + pObj->HasText()) + { + mbAdjustDisabled = false; + + m_xFlAdjust->set_sensitive(true); + + m_xTsbAutoGrowWidth->connect_toggled( LINK( this, SvxPositionSizeTabPage, ClickSizeProtectHdl ) ); + m_xTsbAutoGrowHeight->connect_toggled( LINK( this, SvxPositionSizeTabPage, ClickSizeProtectHdl ) ); + + // is used as flag to evaluate if its selectable + mbIgnoreAutoGrowWidth = false; + mbIgnoreAutoGrowHeight = false; + } + } + + // take scale into account + const Fraction aUIScale(mpView->GetModel()->GetUIScale()); + TransfrmHelper::ScaleRect( maWorkRange, aUIScale ); + TransfrmHelper::ScaleRect( maRange, aUIScale ); + + // take UI units into account + const sal_uInt16 nDigits(m_xMtrPosX->get_digits()); + TransfrmHelper::ConvertRect( maWorkRange, nDigits, mePoolUnit, meDlgUnit ); + TransfrmHelper::ConvertRect( maRange, nDigits, mePoolUnit, meDlgUnit ); + + SetMinMaxPosition(); +} + + +bool SvxPositionSizeTabPage::FillItemSet( SfxItemSet* rOutAttrs ) +{ + bool bModified(false); + + if ( m_xMtrWidth->has_focus() ) + { + ChangeWidthHdl( *m_xMtrWidth ); + } + + if ( m_xMtrHeight->has_focus() ) + { + ChangeHeightHdl( *m_xMtrHeight ); + } + + if( !mbPageDisabled ) + { + if (m_xMtrPosX->get_value_changed_from_saved() || m_xMtrPosY->get_value_changed_from_saved()) + { + const double fUIScale(double(mpView->GetModel()->GetUIScale())); + double fX((GetCoreValue( *m_xMtrPosX, mePoolUnit ) + maAnchor.getX()) * fUIScale); + double fY((GetCoreValue( *m_xMtrPosY, mePoolUnit ) + maAnchor.getY()) * fUIScale); + + { // #i75273# + ::tools::Rectangle aTempRect(mpView->GetAllMarkedRect()); + mpView->GetSdrPageView()->LogicToPagePos(aTempRect); + maRange = vcl::unotools::b2DRectangleFromRectangle(aTempRect); + } + + // #101581# GetTopLeftPosition(...) needs coordinates after UI scaling, in real PagePositions + GetTopLeftPosition(fX, fY, maRange); + + rOutAttrs->Put(SfxInt32Item(GetWhich(SID_ATTR_TRANSFORM_POS_X), basegfx::fround(fX))); + rOutAttrs->Put(SfxInt32Item(GetWhich(SID_ATTR_TRANSFORM_POS_Y), basegfx::fround(fY))); + + bModified = true; + } + + if (m_xTsbPosProtect->get_state_changed_from_saved()) + { + if( m_xTsbPosProtect->get_inconsistent() ) + { + rOutAttrs->InvalidateItem( SID_ATTR_TRANSFORM_PROTECT_POS ); + } + else + { + rOutAttrs->Put( + SfxBoolItem( GetWhich( SID_ATTR_TRANSFORM_PROTECT_POS ), + m_xTsbPosProtect->get_active() ) ); + } + + bModified = true; + } + } + + if (m_xMtrWidth->get_value_changed_from_saved() || m_xMtrHeight->get_value_changed_from_saved()) + { + Fraction aUIScale = mpView->GetModel()->GetUIScale(); + + // get Width + double nWidth = static_cast(m_xMtrWidth->get_value(FieldUnit::MM_100TH)); + long lWidth = long(nWidth * static_cast(aUIScale)); + lWidth = OutputDevice::LogicToLogic( lWidth, MapUnit::Map100thMM, mePoolUnit ); + lWidth = static_cast(m_xMtrWidth->denormalize( lWidth )); + + // get Height + double nHeight = static_cast(m_xMtrHeight->get_value(FieldUnit::MM_100TH)); + long lHeight = long(nHeight * static_cast(aUIScale)); + lHeight = OutputDevice::LogicToLogic( lHeight, MapUnit::Map100thMM, mePoolUnit ); + lHeight = static_cast(m_xMtrHeight->denormalize( lHeight )); + + // put Width & Height to itemset + rOutAttrs->Put( SfxUInt32Item( GetWhich( SID_ATTR_TRANSFORM_WIDTH ), static_cast(lWidth) ) ); + rOutAttrs->Put( SfxUInt32Item( GetWhich( SID_ATTR_TRANSFORM_HEIGHT ), static_cast(lHeight) ) ); + rOutAttrs->Put( SfxUInt16Item( GetWhich( SID_ATTR_TRANSFORM_SIZE_POINT ), sal::static_int_cast< sal_uInt16 >( meRP ) ) ); + bModified = true; + } + + if (m_xTsbSizeProtect->get_state_changed_from_saved()) + { + if ( m_xTsbSizeProtect->get_inconsistent() ) + rOutAttrs->InvalidateItem( SID_ATTR_TRANSFORM_PROTECT_SIZE ); + else + rOutAttrs->Put( + SfxBoolItem( GetWhich( SID_ATTR_TRANSFORM_PROTECT_SIZE ), + m_xTsbSizeProtect->get_active() ) ); + bModified = true; + } + + if (m_xTsbAutoGrowWidth->get_state_changed_from_saved()) + { + if (!mbIgnoreAutoGrowWidth) + { + if( m_xTsbAutoGrowWidth->get_inconsistent() ) + rOutAttrs->InvalidateItem( SID_ATTR_TRANSFORM_AUTOWIDTH ); + else + rOutAttrs->Put( + SfxBoolItem( GetWhich( SID_ATTR_TRANSFORM_AUTOWIDTH ), + m_xTsbAutoGrowWidth->get_active() ) ); + } + bModified = true; + } + + if (m_xTsbAutoGrowHeight->get_state_changed_from_saved()) + { + if (!mbIgnoreAutoGrowHeight) + { + if (m_xTsbAutoGrowHeight->get_inconsistent()) + { + rOutAttrs->InvalidateItem( SID_ATTR_TRANSFORM_AUTOHEIGHT ); + } + else + { + rOutAttrs->Put( + SfxBoolItem( GetWhich( SID_ATTR_TRANSFORM_AUTOHEIGHT ), + m_xTsbAutoGrowHeight->get_active() ) ); + } + } + bModified = true; + } + + return bModified; +} + +void SvxPositionSizeTabPage::Reset( const SfxItemSet* ) +{ + const SfxPoolItem* pItem; + const double fUIScale(double(mpView->GetModel()->GetUIScale())); + + if ( !mbPageDisabled ) + { + pItem = GetItem( mrOutAttrs, SID_ATTR_TRANSFORM_POS_X ); + if ( pItem ) + { + const double fTmp((static_cast(pItem)->GetValue() - maAnchor.getX()) / fUIScale); + SetMetricValue(*m_xMtrPosX, basegfx::fround(fTmp), mePoolUnit); + } + + pItem = GetItem( mrOutAttrs, SID_ATTR_TRANSFORM_POS_Y ); + if ( pItem ) + { + const double fTmp((static_cast(pItem)->GetValue() - maAnchor.getY()) / fUIScale); + SetMetricValue(*m_xMtrPosY, basegfx::fround(fTmp), mePoolUnit); + } + + pItem = GetItem( mrOutAttrs, SID_ATTR_TRANSFORM_PROTECT_POS ); + if ( pItem ) + { + bool bProtected = static_cast( pItem )->GetValue(); + m_xTsbPosProtect->set_active(bProtected); + } + else + { + m_xTsbPosProtect->set_inconsistent(true); + } + + m_xTsbPosProtect->save_state(); + m_aCtlPos.Reset(); + + // #i2379# Disable controls for protected objects + ChangePosProtectHdl(*m_xTsbPosProtect); + } + + { // #i75273# set width + pItem = GetItem( mrOutAttrs, SID_ATTR_TRANSFORM_WIDTH ); + mfOldWidth = std::max( pItem ? static_cast(static_cast(pItem)->GetValue()) : 0.0, 1.0 ); + double fTmpWidth((OutputDevice::LogicToLogic(static_cast(mfOldWidth), mePoolUnit, MapUnit::Map100thMM)) / fUIScale); + if (m_xMtrWidth->get_digits()) + fTmpWidth *= pow(10.0, m_xMtrWidth->get_digits()); + m_xMtrWidth->set_value(static_cast(fTmpWidth), FieldUnit::MM_100TH); + } + + { // #i75273# set height + pItem = GetItem( mrOutAttrs, SID_ATTR_TRANSFORM_HEIGHT ); + mfOldHeight = std::max( pItem ? static_cast(static_cast(pItem)->GetValue()) : 0.0, 1.0 ); + double fTmpHeight((OutputDevice::LogicToLogic(static_cast(mfOldHeight), mePoolUnit, MapUnit::Map100thMM)) / fUIScale); + if (m_xMtrHeight->get_digits()) + fTmpHeight *= pow(10.0, m_xMtrHeight->get_digits()); + m_xMtrHeight->set_value(static_cast(fTmpHeight), FieldUnit::MM_100TH); + } + + pItem = GetItem( mrOutAttrs, SID_ATTR_TRANSFORM_PROTECT_SIZE ); + if ( pItem ) + { + m_xTsbSizeProtect->set_active(static_cast(pItem)->GetValue()); + } + else + m_xTsbSizeProtect->set_inconsistent(true); + + pItem = GetItem( mrOutAttrs, SID_ATTR_TRANSFORM_AUTOWIDTH ); + if ( pItem ) + { + m_xTsbAutoGrowWidth->set_active(static_cast( pItem )->GetValue()); + } + else + m_xTsbAutoGrowWidth->set_inconsistent(true); + + pItem = GetItem( mrOutAttrs, SID_ATTR_TRANSFORM_AUTOHEIGHT ); + if ( pItem ) + { + m_xTsbAutoGrowHeight->set_active(static_cast( pItem )->GetValue()); + } + else + m_xTsbAutoGrowHeight->set_inconsistent(true); + + // Is matching set? + OUString aStr = GetUserData(); + m_xCbxScale->set_active(aStr.toInt32() != 0); + + m_xMtrPosX->save_value(); + m_xMtrPosY->save_value(); + m_xMtrWidth->save_value(); + m_xMtrHeight->save_value(); + + m_xTsbSizeProtect->save_state(); + m_xTsbAutoGrowWidth->save_state(); + m_xTsbAutoGrowHeight->save_state(); + ClickSizeProtectHdl(*m_xTsbAutoGrowHeight); + + // #i2379# Disable controls for protected objects + ChangeSizeProtectHdl(*m_xTsbSizeProtect); +} + +std::unique_ptr SvxPositionSizeTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rOutAttrs) +{ + return std::make_unique(pPage, pController, *rOutAttrs); +} + +void SvxPositionSizeTabPage::ActivatePage( const SfxItemSet& rSet ) +{ + SfxRectangleItem const * pRectItem = nullptr; + + if( SfxItemState::SET == rSet.GetItemState( GetWhich( SID_ATTR_TRANSFORM_INTERN ) , false, reinterpret_cast(&pRectItem) ) ) + { + { // #i75273# + const ::tools::Rectangle aTempRect(pRectItem->GetValue()); + maRange = vcl::unotools::b2DRectangleFromRectangle(aTempRect); + } + + SetMinMaxPosition(); + } +} + + +DeactivateRC SvxPositionSizeTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if( _pSet ) + { + double fX(static_cast(m_xMtrPosX->get_value(FieldUnit::NONE))); + double fY(static_cast(m_xMtrPosY->get_value(FieldUnit::NONE))); + + GetTopLeftPosition(fX, fY, maRange); + const ::tools::Rectangle aOutRectangle( + basegfx::fround(fX), basegfx::fround(fY), + basegfx::fround(fX + maRange.getWidth()), basegfx::fround(fY + maRange.getHeight())); + _pSet->Put(SfxRectangleItem(SID_ATTR_TRANSFORM_INTERN, aOutRectangle)); + _pSet->Put(SfxBoolItem( GetWhich( SID_ATTR_TRANSFORM_PROTECT_POS ), + m_xTsbPosProtect->get_state() == TRISTATE_TRUE )); + _pSet->Put(SfxBoolItem( GetWhich( SID_ATTR_TRANSFORM_PROTECT_SIZE ), + m_xTsbSizeProtect->get_state() == TRISTATE_TRUE )); + FillItemSet(_pSet); + } + + return DeactivateRC::LeavePage; +} + + +IMPL_LINK_NOARG(SvxPositionSizeTabPage, ChangePosProtectHdl, weld::ToggleButton&, void) +{ + // #106572# Remember user's last choice + m_xTsbSizeProtect->set_state(m_xTsbPosProtect->get_state() == TRISTATE_TRUE ? TRISTATE_TRUE : mnProtectSizeState); + UpdateControlStates(); +} + + +void SvxPositionSizeTabPage::UpdateControlStates() +{ + const bool bPosProtect = m_xTsbPosProtect->get_state() == TRISTATE_TRUE; + const bool bSizeProtect = m_xTsbSizeProtect->get_state() == TRISTATE_TRUE; + const bool bHeightChecked = !mbIgnoreAutoGrowHeight && (m_xTsbAutoGrowHeight->get_active()); + const bool bWidthChecked = !mbIgnoreAutoGrowWidth && (m_xTsbAutoGrowWidth->get_active()); + + m_xFlPosition->set_sensitive(!bPosProtect && !mbPageDisabled); + + m_xTsbPosProtect->set_sensitive( !mbProtectDisabled && !mbPageDisabled ); + + m_xFlSize->set_sensitive( !mbSizeDisabled && !bSizeProtect ); + + m_xFtWidth->set_sensitive( !mbSizeDisabled && !bSizeProtect && !bWidthChecked ); + m_xMtrWidth->set_sensitive( !mbSizeDisabled && !bSizeProtect && !bWidthChecked ); + + m_xFtHeight->set_sensitive( !mbSizeDisabled && !bSizeProtect && !bHeightChecked ); + m_xMtrHeight->set_sensitive( !mbSizeDisabled && !bSizeProtect && !bHeightChecked ); + + m_xCbxScale->set_sensitive( !mbSizeDisabled && !bSizeProtect && !bHeightChecked && !bWidthChecked ); + m_xCtlSize->set_sensitive( !mbSizeDisabled && !bSizeProtect && (!bHeightChecked || !bWidthChecked) ); + + m_xFlProtect->set_sensitive( !mbProtectDisabled ); + m_xTsbSizeProtect->set_sensitive( !mbProtectDisabled && !bPosProtect ); + + m_xFlAdjust->set_sensitive( !mbSizeDisabled && !bSizeProtect && !mbAdjustDisabled ); + + m_aCtlSize.Invalidate(); + m_aCtlPos.Invalidate(); +} + +IMPL_LINK_NOARG(SvxPositionSizeTabPage, ChangeSizeProtectHdl, weld::ToggleButton&, void) +{ + if (m_xTsbSizeProtect->get_sensitive()) + { + // #106572# Remember user's last choice + + // Note: this works only as long as the dialog is open. When + // the user closes the dialog, there is no way to remember + // whether size was enabled or disabled before pos protect was + // clicked. Thus, if pos protect is selected, the dialog is + // closed and reopened again, unchecking pos protect will + // always uncheck size protect, too. That's life. + mnProtectSizeState = m_xTsbSizeProtect->get_state(); + } + + UpdateControlStates(); +} + +void SvxPositionSizeTabPage::SetMinMaxPosition() +{ + // position + double fLeft(maWorkRange.getMinX()); + double fTop(maWorkRange.getMinY()); + double fRight(maWorkRange.getMaxX()); + double fBottom(maWorkRange.getMaxY()); + + switch (m_aCtlPos.GetActualRP()) + { + case RectPoint::LT: + { + fRight -= maRange.getWidth(); + fBottom -= maRange.getHeight(); + break; + } + case RectPoint::MT: + { + fLeft += maRange.getWidth() / 2.0; + fRight -= maRange.getWidth() / 2.0; + fBottom -= maRange.getHeight(); + break; + } + case RectPoint::RT: + { + fLeft += maRange.getWidth(); + fBottom -= maRange.getHeight(); + break; + } + case RectPoint::LM: + { + fRight -= maRange.getWidth(); + fTop += maRange.getHeight() / 2.0; + fBottom -= maRange.getHeight() / 2.0; + break; + } + case RectPoint::MM: + { + fLeft += maRange.getWidth() / 2.0; + fRight -= maRange.getWidth() / 2.0; + fTop += maRange.getHeight() / 2.0; + fBottom -= maRange.getHeight() / 2.0; + break; + } + case RectPoint::RM: + { + fLeft += maRange.getWidth(); + fTop += maRange.getHeight() / 2.0; + fBottom -= maRange.getHeight() / 2.0; + break; + } + case RectPoint::LB: + { + fRight -= maRange.getWidth(); + fTop += maRange.getHeight(); + break; + } + case RectPoint::MB: + { + fLeft += maRange.getWidth() / 2.0; + fRight -= maRange.getWidth() / 2.0; + fTop += maRange.getHeight(); + break; + } + case RectPoint::RB: + { + fLeft += maRange.getWidth(); + fTop += maRange.getHeight(); + break; + } + } + + const double fMaxLong(static_cast(vcl::ConvertValue( LONG_MAX, 0, MapUnit::Map100thMM, meDlgUnit ) - 1)); + fLeft = std::clamp(fLeft, -fMaxLong, fMaxLong); + fRight = std::clamp(fRight, -fMaxLong, fMaxLong); + fTop = std::clamp(fTop, - fMaxLong, fMaxLong); + fBottom = std::clamp(fBottom, -fMaxLong, fMaxLong); + + // #i75273# normalizing when setting the min/max values was wrong, removed + m_xMtrPosX->set_range(basegfx::fround64(fLeft), basegfx::fround64(fRight), FieldUnit::NONE); + m_xMtrPosY->set_range(basegfx::fround64(fTop), basegfx::fround64(fBottom), FieldUnit::NONE); + + // size + fLeft = maWorkRange.getMinX(); + fTop = maWorkRange.getMinY(); + fRight = maWorkRange.getMaxX(); + fBottom = maWorkRange.getMaxY(); + double fNewX(0); + double fNewY(0); + + switch (m_aCtlSize.GetActualRP()) + { + case RectPoint::LT: + { + fNewX = maWorkRange.getWidth() - ( maRange.getMinX() - fLeft ); + fNewY = maWorkRange.getHeight() - ( maRange.getMinY() - fTop ); + break; + } + case RectPoint::MT: + { + fNewX = std::min( maRange.getCenter().getX() - fLeft, fRight - maRange.getCenter().getX() ) * 2.0; + fNewY = maWorkRange.getHeight() - ( maRange.getMinY() - fTop ); + break; + } + case RectPoint::RT: + { + fNewX = maWorkRange.getWidth() - ( fRight - maRange.getMaxX() ); + fNewY = maWorkRange.getHeight() - ( maRange.getMinY() - fTop ); + break; + } + case RectPoint::LM: + { + fNewX = maWorkRange.getWidth() - ( maRange.getMinX() - fLeft ); + fNewY = std::min( maRange.getCenter().getY() - fTop, fBottom - maRange.getCenter().getY() ) * 2.0; + break; + } + case RectPoint::MM: + { + const double f1(maRange.getCenter().getX() - fLeft); + const double f2(fRight - maRange.getCenter().getX()); + const double f3(std::min(f1, f2)); + const double f4(maRange.getCenter().getY() - fTop); + const double f5(fBottom - maRange.getCenter().getY()); + const double f6(std::min(f4, f5)); + + fNewX = f3 * 2.0; + fNewY = f6 * 3.0; + + break; + } + case RectPoint::RM: + { + fNewX = maWorkRange.getWidth() - ( fRight - maRange.getMaxX() ); + fNewY = std::min( maRange.getCenter().getY() - fTop, fBottom - maRange.getCenter().getY() ) * 2.0; + break; + } + case RectPoint::LB: + { + fNewX = maWorkRange.getWidth() - ( maRange.getMinX() - fLeft ); + fNewY = maWorkRange.getHeight() - ( fBottom - maRange.getMaxY() ); + break; + } + case RectPoint::MB: + { + fNewX = std::min( maRange.getCenter().getX() - fLeft, fRight - maRange.getCenter().getX() ) * 2.0; + fNewY = maWorkRange.getHeight() - ( maRange.getMaxY() - fBottom ); + break; + } + case RectPoint::RB: + { + fNewX = maWorkRange.getWidth() - ( fRight - maRange.getMaxX() ); + fNewY = maWorkRange.getHeight() - ( fBottom - maRange.getMaxY() ); + break; + } + } + + // #i75273# normalizing when setting the min/max values was wrong, removed + m_xMtrWidth->set_max(basegfx::fround64(fNewX), FieldUnit::NONE); + m_xMtrHeight->set_max(basegfx::fround64(fNewY), FieldUnit::NONE); +} + +void SvxPositionSizeTabPage::GetTopLeftPosition(double& rfX, double& rfY, const basegfx::B2DRange& rRange) +{ + switch (m_aCtlPos.GetActualRP()) + { + case RectPoint::LT: + { + break; + } + case RectPoint::MT: + { + rfX -= rRange.getCenter().getX() - rRange.getMinX(); + break; + } + case RectPoint::RT: + { + rfX -= rRange.getWidth(); + break; + } + case RectPoint::LM: + { + rfY -= rRange.getCenter().getY() - rRange.getMinY(); + break; + } + case RectPoint::MM: + { + rfX -= rRange.getCenter().getX() - rRange.getMinX(); + rfY -= rRange.getCenter().getY() - rRange.getMinY(); + break; + } + case RectPoint::RM: + { + rfX -= rRange.getWidth(); + rfY -= rRange.getCenter().getY() - rRange.getMinY(); + break; + } + case RectPoint::LB: + { + rfY -= rRange.getHeight(); + break; + } + case RectPoint::MB: + { + rfX -= rRange.getCenter().getX() - rRange.getMinX(); + rfY -= rRange.getHeight(); + break; + } + case RectPoint::RB: + { + rfX -= rRange.getWidth(); + rfY -= rRange.getHeight(); + break; + } + } +} + +void SvxPositionSizeTabPage::PointChanged(weld::DrawingArea* pDrawingArea, RectPoint eRP) +{ + if (pDrawingArea == m_aCtlPos.GetDrawingArea()) + { + SetMinMaxPosition(); + switch( eRP ) + { + case RectPoint::LT: + { + m_xMtrPosX->set_value( basegfx::fround64(maRange.getMinX()), FieldUnit::NONE ); + m_xMtrPosY->set_value( basegfx::fround64(maRange.getMinY()), FieldUnit::NONE ); + break; + } + case RectPoint::MT: + { + m_xMtrPosX->set_value( basegfx::fround64(maRange.getCenter().getX()), FieldUnit::NONE ); + m_xMtrPosY->set_value( basegfx::fround64(maRange.getMinY()), FieldUnit::NONE ); + break; + } + case RectPoint::RT: + { + m_xMtrPosX->set_value( basegfx::fround64(maRange.getMaxX()), FieldUnit::NONE ); + m_xMtrPosY->set_value( basegfx::fround64(maRange.getMinY()), FieldUnit::NONE ); + break; + } + case RectPoint::LM: + { + m_xMtrPosX->set_value( basegfx::fround64(maRange.getMinX()), FieldUnit::NONE ); + m_xMtrPosY->set_value( basegfx::fround64(maRange.getCenter().getY()), FieldUnit::NONE ); + break; + } + case RectPoint::MM: + { + m_xMtrPosX->set_value( basegfx::fround64(maRange.getCenter().getX()), FieldUnit::NONE ); + m_xMtrPosY->set_value( basegfx::fround64(maRange.getCenter().getY()), FieldUnit::NONE ); + break; + } + case RectPoint::RM: + { + m_xMtrPosX->set_value( basegfx::fround64(maRange.getMaxX()), FieldUnit::NONE ); + m_xMtrPosY->set_value( basegfx::fround64(maRange.getCenter().getY()), FieldUnit::NONE ); + break; + } + case RectPoint::LB: + { + m_xMtrPosX->set_value( basegfx::fround64(maRange.getMinX()), FieldUnit::NONE ); + m_xMtrPosY->set_value( basegfx::fround64(maRange.getMaxY()), FieldUnit::NONE ); + break; + } + case RectPoint::MB: + { + m_xMtrPosX->set_value( basegfx::fround64(maRange.getCenter().getX()), FieldUnit::NONE ); + m_xMtrPosY->set_value( basegfx::fround64(maRange.getMaxY()), FieldUnit::NONE ); + break; + } + case RectPoint::RB: + { + m_xMtrPosX->set_value( basegfx::fround64(maRange.getMaxX()), FieldUnit::NONE ); + m_xMtrPosY->set_value( basegfx::fround64(maRange.getMaxY()), FieldUnit::NONE ); + break; + } + } + } + else + { + meRP = eRP; + SetMinMaxPosition(); + } +} + +void SvxPositionSizeTabPage::DisableResize() +{ + mbSizeDisabled = true; +} + + +void SvxPositionSizeTabPage::DisableProtect() +{ + mbProtectDisabled = true; +} + + +IMPL_LINK_NOARG(SvxPositionSizeTabPage, ChangeWidthHdl, weld::MetricSpinButton&, void) +{ + if( !(m_xCbxScale->get_active() && m_xCbxScale->get_sensitive()) ) + return; + + sal_Int64 nHeight(basegfx::fround64((mfOldHeight * static_cast(m_xMtrWidth->get_value(FieldUnit::NONE))) / mfOldWidth)); + int nMin, nMax; + m_xMtrHeight->get_range(nMin, nMax, FieldUnit::NONE); + + if (nHeight <= nMax) + { + m_xMtrHeight->set_value(nHeight, FieldUnit::NONE); + } + else + { + nHeight = nMax; + m_xMtrHeight->set_value(nHeight, FieldUnit::NONE); + + const sal_Int64 nWidth(basegfx::fround64((mfOldWidth * static_cast(nHeight)) / mfOldHeight)); + m_xMtrWidth->set_value(nWidth, FieldUnit::NONE); + } +} + +IMPL_LINK_NOARG(SvxPositionSizeTabPage, ChangeHeightHdl, weld::MetricSpinButton&, void) +{ + if( !(m_xCbxScale->get_active() && m_xCbxScale->get_sensitive()) ) + return; + + sal_Int64 nWidth(basegfx::fround64((mfOldWidth * static_cast(m_xMtrHeight->get_value(FieldUnit::NONE))) / mfOldHeight)); + int nMin, nMax; + m_xMtrWidth->get_range(nMin, nMax, FieldUnit::NONE); + + if (nWidth <= nMax) + { + m_xMtrWidth->set_value(nWidth, FieldUnit::NONE); + } + else + { + nWidth = nMax; + m_xMtrWidth->set_value(nWidth, FieldUnit::NONE); + + const sal_Int64 nHeight(basegfx::fround64((mfOldHeight * static_cast(nWidth)) / mfOldWidth)); + m_xMtrHeight->set_value(nHeight, FieldUnit::NONE); + } +} + +IMPL_LINK_NOARG(SvxPositionSizeTabPage, ClickSizeProtectHdl, weld::ToggleButton&, void) +{ + UpdateControlStates(); +} + +IMPL_LINK_NOARG(SvxPositionSizeTabPage, ClickAutoHdl, weld::ToggleButton&, void) +{ + if (m_xCbxScale->get_active()) + { + mfOldWidth = std::max( static_cast(GetCoreValue( *m_xMtrWidth, mePoolUnit )), 1.0 ); + mfOldHeight = std::max( static_cast(GetCoreValue( *m_xMtrHeight, mePoolUnit )), 1.0 ); + } +} + +void SvxPositionSizeTabPage::FillUserData() +{ + // matching is saved in the Ini-file + OUString aStr = m_xCbxScale->get_active() ? OUString("1") : OUString("0"); + SetUserData( aStr ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/uno/services.cxx b/cui/source/uno/services.cxx new file mode 100644 index 000000000..62c6bbaf4 --- /dev/null +++ b/cui/source/uno/services.cxx @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include + +#include + +using namespace com::sun::star; + +namespace +{ + cppu::ImplementationEntry const entries[] = { + { &::cui::ColorPicker_createInstance, &::cui::ColorPicker_getImplementationName, &::cui::ColorPicker_getSupportedServiceNames, &cppu::createSingleComponentFactory, nullptr, 0 }, + { nullptr, nullptr, nullptr, nullptr, nullptr, 0 } + }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT void * cui_component_getFactory( char const * implName, void * serviceManager, void * registryKey) +{ + return cppu::component_getFactoryHelper(implName, serviceManager, registryKey, entries); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit v1.2.3