Add a comment to clarify what kind of inputs the class handles
[LibreOffice.git] / sw / source / uibase / shells / txtnum.cxx
blobd93eb7286070efe69b0e6c4f1c173b1e001236fd
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sfx2/request.hxx>
21 #include <svl/eitem.hxx>
22 #include <svl/stritem.hxx>
23 #include <editeng/numitem.hxx>
24 #include <editeng/brushitem.hxx>
25 #include <osl/diagnose.h>
26 #include <numrule.hxx>
28 #include <cmdid.h>
29 #include <wrtsh.hxx>
30 #include <view.hxx>
31 #include <viewopt.hxx>
32 #include <wdocsh.hxx>
33 #include <poolfmt.hxx>
34 #include <textsh.hxx>
35 #include <swabstdlg.hxx>
36 #include <SwStyleNameMapper.hxx>
37 #include <sfx2/tabdlg.hxx>
38 #include <svx/nbdtmg.hxx>
39 #include <svx/nbdtmgfact.hxx>
40 #include <sfx2/viewfrm.hxx>
41 #include <sfx2/bindings.hxx>
42 #include <memory>
44 void SwTextShell::ExecEnterNum(SfxRequest &rReq)
46 //Because the record before any shell exchange.
47 switch(rReq.GetSlot())
49 case FN_NUM_NUMBERING_ON:
51 GetShell().StartAllAction();
52 const SfxBoolItem* pItem = rReq.GetArg<SfxBoolItem>(FN_PARAM_1);
53 bool bMode = !GetShell().SelectionHasNumber(); // #i29560#
54 if ( pItem )
55 bMode = pItem->GetValue();
56 else
57 rReq.AppendItem( SfxBoolItem( FN_PARAM_1, bMode ) );
59 if ( bMode != (GetShell().SelectionHasNumber()) ) // #i29560#
61 rReq.Done();
62 if( bMode )
63 GetShell().NumOn();
64 else
65 GetShell().NumOrBulletOff(); // #i29560#
67 bool bNewResult = GetShell().SelectionHasNumber();
68 if (bNewResult!=bMode) {
69 SfxBindings& rBindings = GetView().GetViewFrame().GetBindings();
70 SfxBoolItem aItem(FN_NUM_NUMBERING_ON,!bNewResult);
71 rBindings.SetState(aItem);
72 SfxBoolItem aNewItem(FN_NUM_NUMBERING_ON,bNewResult);
73 rBindings.SetState(aNewItem);
75 GetShell().EndAllAction();
77 break;
78 case FN_NUM_BULLET_ON:
80 GetShell().StartAllAction();
81 const SfxBoolItem* pItem = rReq.GetArg<SfxBoolItem>(FN_PARAM_1);
82 bool bMode = !GetShell().SelectionHasBullet(); // #i29560#
83 if ( pItem )
84 bMode = pItem->GetValue();
85 else
86 rReq.AppendItem( SfxBoolItem( FN_PARAM_1, bMode ) );
88 if ( bMode != (GetShell().SelectionHasBullet()) ) // #i29560#
90 rReq.Done();
91 if( bMode )
92 GetShell().BulletOn();
93 else
94 GetShell().NumOrBulletOff(); // #i29560#
96 bool bNewResult = GetShell().SelectionHasBullet();
97 if (bNewResult!=bMode) {
98 SfxBindings& rBindings = GetView().GetViewFrame().GetBindings();
99 SfxBoolItem aItem(FN_NUM_BULLET_ON,!bNewResult);
100 rBindings.SetState(aItem);
101 SfxBoolItem aNewItem(FN_NUM_BULLET_ON,bNewResult);
102 rBindings.SetState(aNewItem);
104 GetShell().EndAllAction();
106 break;
108 case FN_NUM_BULLET_OFF:
110 GetShell().StartAllAction();
111 SfxRequest aReq(GetView().GetViewFrame(), FN_NUM_BULLET_ON);
112 aReq.AppendItem(SfxBoolItem(FN_PARAM_1, false));
113 aReq.Done();
114 GetShell().DelNumRules();
115 GetShell().EndAllAction();
117 break;
119 case FN_NUMBER_BULLETS:
120 case SID_OUTLINE_BULLET:
122 SfxItemSetFixed<SID_HTML_MODE, SID_HTML_MODE,
123 SID_ATTR_NUMBERING_RULE, SID_PARAM_CUR_NUM_LEVEL> aSet( GetPool() );
124 SwDocShell* pDocSh = GetView().GetDocShell();
125 const bool bHtml = dynamic_cast<SwWebDocShell*>( pDocSh ) != nullptr;
126 const SwNumRule* pNumRuleAtCurrentSelection = GetShell().GetNumRuleAtCurrentSelection();
127 if ( pNumRuleAtCurrentSelection != nullptr )
129 SvxNumRule aRule = pNumRuleAtCurrentSelection->MakeSvxNumRule();
131 //convert type of linked bitmaps from SVX_NUM_BITMAP to (SVX_NUM_BITMAP|LINK_TOKEN)
132 for ( sal_uInt16 i = 0; i < aRule.GetLevelCount(); i++ )
134 SvxNumberFormat aFormat( aRule.GetLevel( i ) );
135 if ( SVX_NUM_BITMAP == aFormat.GetNumberingType() )
137 const SvxBrushItem* pBrush = aFormat.GetBrush();
138 if(pBrush && !pBrush->GetGraphicLink().isEmpty())
139 aFormat.SetNumberingType(SvxNumType(SVX_NUM_BITMAP|LINK_TOKEN));
140 aRule.SetLevel(i, aFormat, aRule.Get(i) != nullptr);
143 if(bHtml)
144 aRule.SetFeatureFlag(SvxNumRuleFlags::ENABLE_EMBEDDED_BMP, false);
146 aSet.Put(SvxNumBulletItem(aRule));
147 OSL_ENSURE( GetShell().GetNumLevel() < MAXLEVEL,
148 "<SwTextShell::ExecEnterNum()> - numbered node without valid list level. Serious defect." );
149 sal_uInt16 nLevel = GetShell().GetNumLevel();
150 if( nLevel < MAXLEVEL )
152 nLevel = 1 << nLevel;
153 aSet.Put( SfxUInt16Item( SID_PARAM_CUR_NUM_LEVEL, nLevel ) );
156 else
158 SwNumRule aRule( GetShell().GetUniqueNumRuleName(),
159 // #i89178#
160 numfunc::GetDefaultPositionAndSpaceMode() );
161 SvxNumRule aSvxRule = aRule.MakeSvxNumRule();
162 const bool bRightToLeft = GetShell().IsInRightToLeftText();
164 if ( bHtml || bRightToLeft )
166 for ( sal_uInt8 n = 0; n < MAXLEVEL; ++n )
168 SvxNumberFormat aFormat( aSvxRule.GetLevel( n ) );
169 if ( n && bHtml )
171 // 1/2" for HTML
172 aFormat.SetAbsLSpace(n * 720);
174 // #i38904# Default alignment for
175 // numbering/bullet should be rtl in rtl paragraph:
176 if ( bRightToLeft )
178 aFormat.SetNumAdjust( SvxAdjust::Right );
180 aSvxRule.SetLevel( n, aFormat, false );
182 aSvxRule.SetFeatureFlag(SvxNumRuleFlags::ENABLE_EMBEDDED_BMP, false);
184 aSet.Put( SvxNumBulletItem( std::move(aSvxRule) ) );
187 aSet.Put( SfxBoolItem( SID_PARAM_NUM_PRESET,false ));
189 // Before the dialogue of the HTML mode will be dropped at the Docshell.
190 pDocSh->PutItem(SfxUInt16Item(SID_HTML_MODE, ::GetHtmlMode(pDocSh)));
192 SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
193 weld::Window *pParent = rReq.GetFrameWeld();
194 VclPtr<AbstractNumBulletDialog> pDlg(pFact->CreateSvxNumBulletTabDialog(pParent, aSet, GetShell()));
195 const SfxStringItem* pPageItem = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
196 if ( pPageItem )
197 pDlg->SetCurPageId( pPageItem->GetValue() );
199 auto xRequest = std::make_shared<SfxRequest>(rReq);
200 rReq.Ignore(); // the 'old' request is not relevant any more
202 pDlg->StartExecuteAsync([pDlg, pNumRuleAtCurrentSelection, xRequest=std::move(xRequest), this](sal_Int32 nResult){
203 if (RET_OK == nResult)
205 const SvxNumBulletItem* pBulletItem = pDlg->GetOutputItemSet()->GetItemIfSet(SID_ATTR_NUMBERING_RULE, false);
206 if (pBulletItem)
208 xRequest->AppendItem(*pBulletItem);
209 xRequest->Done();
210 SvxNumRule& rSetRule = const_cast<SvxNumRule&>(pBulletItem->GetNumRule());
211 rSetRule.UnLinkGraphics();
212 SwNumRule aSetRule(pNumRuleAtCurrentSelection != nullptr
213 ? pNumRuleAtCurrentSelection->GetName()
214 : GetShell().GetUniqueNumRuleName(),
215 numfunc::GetDefaultPositionAndSpaceMode());
216 aSetRule.SetSvxRule(rSetRule, GetShell().GetDoc());
217 aSetRule.SetAutoRule(true);
218 // No start of new list, if an existing list style is edited.
219 // Otherwise start a new list.
220 const bool bCreateList = (pNumRuleAtCurrentSelection == nullptr);
221 GetShell().SetCurNumRule(aSetRule, bCreateList);
223 // If the Dialog was leaved with OK but nothing was chosen then the
224 // numbering must be at least activated, if it is not already.
225 else if (pNumRuleAtCurrentSelection == nullptr
226 && (pBulletItem = pDlg->GetInputItemSet()->GetItemIfSet(SID_ATTR_NUMBERING_RULE, false)))
228 xRequest->AppendItem(*pBulletItem);
229 xRequest->Done();
230 const SvxNumRule& rSetRule = pBulletItem->GetNumRule();
231 SwNumRule aSetRule(
232 GetShell().GetUniqueNumRuleName(),
233 numfunc::GetDefaultPositionAndSpaceMode());
234 aSetRule.SetSvxRule(rSetRule, GetShell().GetDoc());
235 aSetRule.SetAutoRule(true);
236 // start new list
237 GetShell().SetCurNumRule(aSetRule, true);
240 else if (RET_USER == nResult)
241 GetShell().DelNumRules();
242 pDlg->disposeOnce();
245 break;
247 default:
248 OSL_FAIL("wrong dispatcher");
249 return;
254 void SwTextShell::ExecSetNumber(SfxRequest const &rReq)
256 const sal_uInt16 nSlot = rReq.GetSlot();
257 switch ( nSlot )
259 case FN_SVX_SET_NUMBER:
260 case FN_SVX_SET_BULLET:
261 case FN_SVX_SET_OUTLINE:
263 const SfxUInt16Item* pIndexItem = nullptr;
264 const SfxStringItem* pCharItem = nullptr;
265 const SfxStringItem* pFontItem = nullptr;
267 // tdf#162264 check if rReq.GetArgs() is a nullptr
268 if ( rReq.GetArgs() )
270 pIndexItem = rReq.GetArgs()->GetItem( SID_ATTR_BULLET_INDEX );
271 if (!pIndexItem) // tdf#161653
272 pIndexItem = rReq.GetArg<SfxUInt16Item>(nSlot);
273 pCharItem = rReq.GetArgs()->GetItem( SID_ATTR_BULLET_CHAR );
274 pFontItem = rReq.GetArgs()->GetItem( SID_ATTR_BULLET_FONT );
277 if ( pIndexItem != nullptr || ( pCharItem != nullptr && pFontItem != nullptr ) )
279 svx::sidebar::NBOType nNBOType = svx::sidebar::NBOType::Bullets;
280 if ( nSlot == FN_SVX_SET_NUMBER )
281 nNBOType = svx::sidebar::NBOType::Numbering;
282 else if ( nSlot == FN_SVX_SET_OUTLINE )
283 nNBOType = svx::sidebar::NBOType::Outline;
285 svx::sidebar::NBOTypeMgrBase* pNBOTypeMgr = svx::sidebar::NBOutlineTypeMgrFact::CreateInstance( nNBOType );
287 if ( pNBOTypeMgr != nullptr )
289 const SwNumRule* pNumRuleAtCurrentSelection = GetShell().GetNumRuleAtCurrentSelection();
290 sal_uInt16 nActNumLvl = USHRT_MAX;
291 if ( pNumRuleAtCurrentSelection != nullptr )
293 const sal_uInt16 nLevel = GetShell().GetNumLevel();
294 if ( nLevel < MAXLEVEL )
296 nActNumLvl = 1 << nLevel;
299 SwNumRule aNewNumRule(
300 pNumRuleAtCurrentSelection != nullptr ? pNumRuleAtCurrentSelection->GetName() : GetShell().GetUniqueNumRuleName(),
301 numfunc::GetDefaultPositionAndSpaceMode() );
302 SvxNumRule aNewSvxNumRule = pNumRuleAtCurrentSelection != nullptr
303 ? pNumRuleAtCurrentSelection->MakeSvxNumRule()
304 : aNewNumRule.MakeSvxNumRule();
306 OUString aNumCharFormat, aBulletCharFormat;
307 SwStyleNameMapper::FillUIName( RES_POOLCHR_NUM_LEVEL, aNumCharFormat );
308 SwStyleNameMapper::FillUIName( RES_POOLCHR_BULLET_LEVEL, aBulletCharFormat );
310 SfxAllItemSet aSet( GetPool() );
311 aSet.Put( SfxStringItem( SID_NUM_CHAR_FMT, aNumCharFormat ) );
312 aSet.Put( SfxStringItem( SID_BULLET_CHAR_FMT, aBulletCharFormat ) );
313 aSet.Put( SvxNumBulletItem( aNewSvxNumRule, SID_ATTR_NUMBERING_RULE ) );
315 pNBOTypeMgr->SetItems( &aSet );
316 if (pIndexItem)
317 pNBOTypeMgr->ApplyNumRule( aNewSvxNumRule, pIndexItem->GetValue() - 1, nActNumLvl );
318 else
320 svx::sidebar::BulletsTypeMgr* pBulletsTypeMgr
321 = dynamic_cast<svx::sidebar::BulletsTypeMgr*>(pNBOTypeMgr);
322 pBulletsTypeMgr->ApplyCustomRule(aNewSvxNumRule, pCharItem->GetValue(),
323 pFontItem->GetValue(), nActNumLvl);
326 aNewNumRule.SetSvxRule( aNewSvxNumRule, GetShell().GetDoc() );
327 aNewNumRule.SetAutoRule( true );
328 const bool bCreateNewList = ( pNumRuleAtCurrentSelection == nullptr );
329 GetShell().SetCurNumRule( aNewNumRule, bCreateNewList );
332 else if (nSlot == FN_SVX_SET_OUTLINE)
334 // no outline provided: launch dialog to request a specific outline
335 SfxBindings& rBindings = GetView().GetViewFrame().GetBindings();
336 const SfxStringItem aPage(FN_PARAM_1, u"outlinenum"_ustr);
337 const SfxPoolItem* aItems[] = { &aPage, nullptr };
338 rBindings.Execute(SID_OUTLINE_BULLET, aItems);
341 break;
343 default:
344 OSL_ENSURE(false, "wrong Dispatcher");
345 return;
349 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */