1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <hintids.hxx>
21 #include <sfx2/request.hxx>
22 #include <svl/eitem.hxx>
23 #include <svl/stritem.hxx>
24 #include <editeng/numitem.hxx>
25 #include <editeng/brushitem.hxx>
26 #include <numrule.hxx>
27 
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 <uiitems.hxx>
36 #include <swabstdlg.hxx>
37 #include <SwStyleNameMapper.hxx>
38 #include <globals.hrc>
39 #include <sfx2/tabdlg.hxx>
40 #include <svx/nbdtmg.hxx>
41 #include <svx/nbdtmgfact.hxx>
42 #include <svx/svxids.hrc>
43 #include <sfx2/viewfrm.hxx>
44 #include <sfx2/bindings.hxx>
45 #include <memory>
46 
ExecEnterNum(SfxRequest & rReq)47 void SwTextShell::ExecEnterNum(SfxRequest &rReq)
48 {
49     //Because the record before any shell exchange.
50     switch(rReq.GetSlot())
51     {
52     case FN_NUM_NUMBERING_ON:
53     {
54         GetShell().StartAllAction();
55         const SfxBoolItem* pItem = rReq.GetArg<SfxBoolItem>(FN_PARAM_1);
56         bool bMode = !GetShell().SelectionHasNumber(); // #i29560#
57         if ( pItem )
58             bMode = pItem->GetValue();
59         else
60             rReq.AppendItem( SfxBoolItem( FN_PARAM_1, bMode ) );
61 
62         if ( bMode != (GetShell().SelectionHasNumber()) ) // #i29560#
63         {
64             rReq.Done();
65             if( bMode )
66                 GetShell().NumOn();
67             else
68                 GetShell().NumOrBulletOff(); // #i29560#
69         }
70         bool bNewResult = GetShell().SelectionHasNumber();
71         if (bNewResult!=bMode) {
72             SfxBindings& rBindings = GetView().GetViewFrame()->GetBindings();
73             SfxBoolItem aItem(FN_NUM_NUMBERING_ON,!bNewResult);
74             rBindings.SetState(aItem);
75             SfxBoolItem aNewItem(FN_NUM_NUMBERING_ON,bNewResult);
76             rBindings.SetState(aNewItem);
77         }
78         GetShell().EndAllAction();
79     }
80     break;
81     case FN_NUM_BULLET_ON:
82     {
83         GetShell().StartAllAction();
84         const SfxBoolItem* pItem = rReq.GetArg<SfxBoolItem>(FN_PARAM_1);
85         bool bMode = !GetShell().SelectionHasBullet(); // #i29560#
86         if ( pItem )
87             bMode = pItem->GetValue();
88         else
89             rReq.AppendItem( SfxBoolItem( FN_PARAM_1, bMode ) );
90 
91         if ( bMode != (GetShell().SelectionHasBullet()) ) // #i29560#
92         {
93             rReq.Done();
94             if( bMode )
95                 GetShell().BulletOn();
96             else
97                 GetShell().NumOrBulletOff(); // #i29560#
98         }
99         bool bNewResult = GetShell().SelectionHasBullet();
100         if (bNewResult!=bMode) {
101             SfxBindings& rBindings = GetView().GetViewFrame()->GetBindings();
102             SfxBoolItem aItem(FN_NUM_BULLET_ON,!bNewResult);
103             rBindings.SetState(aItem);
104             SfxBoolItem aNewItem(FN_NUM_BULLET_ON,bNewResult);
105             rBindings.SetState(aNewItem);
106         }
107         GetShell().EndAllAction();
108     }
109     break;
110 
111     case FN_NUMBER_BULLETS:
112     case SID_OUTLINE_BULLET:
113     {
114         SfxItemSet aSet( GetPool(),
115                          svl::Items<SID_HTML_MODE, SID_HTML_MODE,
116                          SID_ATTR_NUMBERING_RULE, SID_PARAM_CUR_NUM_LEVEL>{} );
117         SwDocShell* pDocSh = GetView().GetDocShell();
118         const bool bHtml = dynamic_cast<SwWebDocShell*>( pDocSh  ) !=  nullptr;
119         const SwNumRule* pNumRuleAtCurrentSelection = GetShell().GetNumRuleAtCurrentSelection();
120         if ( pNumRuleAtCurrentSelection != nullptr )
121         {
122             SvxNumRule aRule = pNumRuleAtCurrentSelection->MakeSvxNumRule();
123 
124             //convert type of linked bitmaps from SVX_NUM_BITMAP to (SVX_NUM_BITMAP|LINK_TOKEN)
125             for ( sal_uInt16 i = 0; i < aRule.GetLevelCount(); i++ )
126             {
127                 SvxNumberFormat aFormat( aRule.GetLevel( i ) );
128                 if ( SVX_NUM_BITMAP == aFormat.GetNumberingType() )
129                 {
130                     const SvxBrushItem* pBrush = aFormat.GetBrush();
131                     if(pBrush && !pBrush->GetGraphicLink().isEmpty())
132                         aFormat.SetNumberingType(SvxNumType(SVX_NUM_BITMAP|LINK_TOKEN));
133                     aRule.SetLevel(i, aFormat, aRule.Get(i) != nullptr);
134                 }
135             }
136             if(bHtml)
137                 aRule.SetFeatureFlag(SvxNumRuleFlags::ENABLE_EMBEDDED_BMP, false);
138 
139             aSet.Put(SvxNumBulletItem(aRule));
140             OSL_ENSURE( GetShell().GetNumLevel() < MAXLEVEL,
141                     "<SwTextShell::ExecEnterNum()> - numbered node without valid list level. Serious defect." );
142             sal_uInt16 nLevel = GetShell().GetNumLevel();
143             if( nLevel < MAXLEVEL )
144             {
145                 nLevel = 1 << nLevel;
146                 aSet.Put( SfxUInt16Item( SID_PARAM_CUR_NUM_LEVEL, nLevel ) );
147             }
148         }
149         else
150         {
151             SwNumRule aRule( GetShell().GetUniqueNumRuleName(),
152                              // #i89178#
153                              numfunc::GetDefaultPositionAndSpaceMode() );
154             SvxNumRule aSvxRule = aRule.MakeSvxNumRule();
155             const bool bRightToLeft = GetShell().IsInRightToLeftText();
156 
157             if ( bHtml || bRightToLeft )
158             {
159                 for ( sal_uInt8 n = 0; n < MAXLEVEL; ++n )
160                 {
161                     SvxNumberFormat aFormat( aSvxRule.GetLevel( n ) );
162                     if ( n && bHtml )
163                     {
164                         // 1/2" for HTML
165                         aFormat.SetAbsLSpace(n * 720);
166                     }
167                     // #i38904#  Default alignment for
168                     // numbering/bullet should be rtl in rtl paragraph:
169                     if ( bRightToLeft )
170                     {
171                         aFormat.SetNumAdjust( SvxAdjust::Right );
172                     }
173                     aSvxRule.SetLevel( n, aFormat, false );
174                 }
175                 aSvxRule.SetFeatureFlag(SvxNumRuleFlags::ENABLE_EMBEDDED_BMP, false);
176             }
177             aSet.Put( SvxNumBulletItem( aSvxRule ) );
178         }
179 
180         aSet.Put( SfxBoolItem( SID_PARAM_NUM_PRESET,false ));
181 
182         // Before the dialogue of the HTML mode will be dropped at the Docshell.
183         pDocSh->PutItem(SfxUInt16Item(SID_HTML_MODE, ::GetHtmlMode(pDocSh)));
184 
185         SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
186         weld::Window *pParent = rReq.GetFrameWeld();
187         VclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateSvxNumBulletTabDialog(pParent, &aSet, GetShell()));
188         const SfxStringItem* pPageItem = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
189         if ( pPageItem )
190             pDlg->SetCurPageId( OUStringToOString( pPageItem->GetValue(), RTL_TEXTENCODING_UTF8 ) );
191 
192         std::shared_ptr<SfxRequest> pRequest(new SfxRequest(rReq));
193         rReq.Ignore(); // the 'old' request is not relevant any more
194 
195         pDlg->StartExecuteAsync([aSet, pDlg, pNumRuleAtCurrentSelection, pRequest, this](sal_Int32 nResult){
196             if (RET_OK == nResult)
197             {
198                 const SfxPoolItem* pItem;
199                 if (SfxItemState::SET == pDlg->GetOutputItemSet()->GetItemState(SID_ATTR_NUMBERING_RULE, false, &pItem))
200                 {
201                     pRequest->AppendItem(*pItem);
202                     pRequest->Done();
203                     SvxNumRule* pSetRule = static_cast<const SvxNumBulletItem*>(pItem)->GetNumRule();
204                     pSetRule->UnLinkGraphics();
205                     SwNumRule aSetRule(pNumRuleAtCurrentSelection != nullptr
206                                        ? pNumRuleAtCurrentSelection->GetName()
207                                        : GetShell().GetUniqueNumRuleName(),
208                         numfunc::GetDefaultPositionAndSpaceMode());
209                     aSetRule.SetSvxRule(*pSetRule, GetShell().GetDoc());
210                     aSetRule.SetAutoRule(true);
211                     // No start of new list, if an existing list style is edited.
212                     // Otherwise start a new list.
213                     const bool bCreateList = (pNumRuleAtCurrentSelection == nullptr);
214                     GetShell().SetCurNumRule(aSetRule, bCreateList);
215                 }
216                 // If the Dialog was leaved with OK but nothing was chosen then the
217                 // numbering must be at least activated, if it is not already.
218                 else if (pNumRuleAtCurrentSelection == nullptr
219                          && SfxItemState::SET == aSet.GetItemState(SID_ATTR_NUMBERING_RULE, false, &pItem))
220                 {
221                     pRequest->AppendItem(*pItem);
222                     pRequest->Done();
223                     SvxNumRule* pSetRule = static_cast<const SvxNumBulletItem*>(pItem)->GetNumRule();
224                     SwNumRule aSetRule(
225                         GetShell().GetUniqueNumRuleName(),
226                         numfunc::GetDefaultPositionAndSpaceMode());
227                     aSetRule.SetSvxRule(*pSetRule, GetShell().GetDoc());
228                     aSetRule.SetAutoRule(true);
229                     // start new list
230                     GetShell().SetCurNumRule(aSetRule, true);
231                 }
232             }
233             else if (RET_USER == nResult)
234                 GetShell().DelNumRules();
235             pDlg->disposeOnce();
236         });
237     }
238     break;
239 
240     default:
241         OSL_FAIL("wrong dispatcher");
242         return;
243     }
244 }
245 
246 
ExecSetNumber(SfxRequest const & rReq)247 void SwTextShell::ExecSetNumber(SfxRequest const &rReq)
248 {
249     const sal_uInt16 nSlot = rReq.GetSlot();
250     switch ( nSlot )
251     {
252     case FN_SVX_SET_NUMBER:
253     case FN_SVX_SET_BULLET:
254     case FN_SVX_SET_OUTLINE:
255         {
256             const SfxUInt16Item* pItem = rReq.GetArg<SfxUInt16Item>(nSlot);
257             if ( pItem != nullptr )
258             {
259                 const sal_uInt16 nChoosenItemIdx = pItem->GetValue();
260                 svx::sidebar::NBOType nNBOType = svx::sidebar::NBOType::Bullets;
261                 if ( nSlot == FN_SVX_SET_NUMBER )
262                     nNBOType = svx::sidebar::NBOType::Numbering;
263                 else if ( nSlot == FN_SVX_SET_OUTLINE )
264                     nNBOType = svx::sidebar::NBOType::Outline;
265 
266                 svx::sidebar::NBOTypeMgrBase* pNBOTypeMgr = svx::sidebar::NBOutlineTypeMgrFact::CreateInstance( nNBOType );
267 
268                 if ( pNBOTypeMgr != nullptr )
269                 {
270                     const SwNumRule* pNumRuleAtCurrentSelection = GetShell().GetNumRuleAtCurrentSelection();
271                     sal_uInt16 nActNumLvl = USHRT_MAX;
272                     if ( pNumRuleAtCurrentSelection != nullptr )
273                     {
274                         const sal_uInt16 nLevel = GetShell().GetNumLevel();
275                         if ( nLevel < MAXLEVEL )
276                         {
277                             nActNumLvl = 1 << nLevel;
278                         }
279                     }
280                     SwNumRule aNewNumRule(
281                         pNumRuleAtCurrentSelection != nullptr ? pNumRuleAtCurrentSelection->GetName() : GetShell().GetUniqueNumRuleName(),
282                         numfunc::GetDefaultPositionAndSpaceMode() );
283                     SvxNumRule aNewSvxNumRule = pNumRuleAtCurrentSelection != nullptr
284                                                     ? pNumRuleAtCurrentSelection->MakeSvxNumRule()
285                                                     : aNewNumRule.MakeSvxNumRule();
286 
287                     OUString aNumCharFormat, aBulletCharFormat;
288                     SwStyleNameMapper::FillUIName( RES_POOLCHR_NUM_LEVEL, aNumCharFormat );
289                     SwStyleNameMapper::FillUIName( RES_POOLCHR_BUL_LEVEL, aBulletCharFormat );
290 
291                     SfxAllItemSet aSet( GetPool() );
292                     aSet.Put( SfxStringItem( SID_NUM_CHAR_FMT, aNumCharFormat ) );
293                     aSet.Put( SfxStringItem( SID_BULLET_CHAR_FMT, aBulletCharFormat ) );
294                     aSet.Put( SvxNumBulletItem( aNewSvxNumRule, SID_ATTR_NUMBERING_RULE ) );
295 
296                     pNBOTypeMgr->SetItems( &aSet );
297                     pNBOTypeMgr->ApplyNumRule( aNewSvxNumRule, nChoosenItemIdx - 1, nActNumLvl );
298 
299                     aNewNumRule.SetSvxRule( aNewSvxNumRule, GetShell().GetDoc() );
300                     aNewNumRule.SetAutoRule( true );
301                     const bool bCreateNewList = ( pNumRuleAtCurrentSelection == nullptr );
302                     GetShell().SetCurNumRule( aNewNumRule, bCreateNewList );
303                 }
304             }
305         }
306         break;
307 
308     default:
309         OSL_ENSURE(false, "wrong Dispatcher");
310         return;
311     }
312 }
313 
314 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
315