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 <com/sun/star/style/XStyleFamiliesSupplier.hpp>
21
22 #include <scitems.hxx>
23 #include <editeng/borderline.hxx>
24
25 #include <sfx2/viewfrm.hxx>
26 #include <sfx2/bindings.hxx>
27 #include <sfx2/objface.hxx>
28 #include <sfx2/request.hxx>
29 #include <svl/whiter.hxx>
30
31 #include <svl/stritem.hxx>
32 #include <svl/numformat.hxx>
33 #include <svl/zformat.hxx>
34 #include <svl/languageoptions.hxx>
35 #include <svl/cjkoptions.hxx>
36 #include <svl/ctloptions.hxx>
37 #include <editeng/boxitem.hxx>
38 #include <editeng/langitem.hxx>
39 #include <editeng/svxenum.hxx>
40 #include <editeng/wghtitem.hxx>
41 #include <editeng/postitem.hxx>
42 #include <editeng/udlnitem.hxx>
43 #include <editeng/lineitem.hxx>
44 #include <editeng/colritem.hxx>
45 #include <editeng/brushitem.hxx>
46 #include <editeng/frmdiritem.hxx>
47 #include <editeng/scriptsetitem.hxx>
48 #include <editeng/shaditem.hxx>
49 #include <editeng/justifyitem.hxx>
50 #include <editeng/fhgtitem.hxx>
51 #include <sal/log.hxx>
52 #include <osl/diagnose.h>
53 #include <comphelper/lok.hxx>
54 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
55
56 #include <formatsh.hxx>
57 #include <sc.hrc>
58 #include <docsh.hxx>
59 #include <patattr.hxx>
60 #include <scmod.hxx>
61 #include <stlpool.hxx>
62 #include <stlsheet.hxx>
63 #include <docpool.hxx>
64 #include <tabvwsh.hxx>
65 #include <attrib.hxx>
66
67 #define ShellClass_ScFormatShell
68 #define ShellClass_TableFont
69 #define ShellClass_FormatForSelection
70 #include <scslots.hxx>
71
72 #include <editeng/fontitem.hxx>
73 #include <sfx2/classificationhelper.hxx>
74
75 #include <memory>
76
77 namespace {
78
lclConvertSlotToHAlign(sal_uInt16 nSlot)79 SvxCellHorJustify lclConvertSlotToHAlign( sal_uInt16 nSlot )
80 {
81 SvxCellHorJustify eHJustify = SvxCellHorJustify::Standard;
82 switch( nSlot )
83 {
84 case SID_ALIGN_ANY_HDEFAULT: eHJustify = SvxCellHorJustify::Standard; break;
85 case SID_ALIGN_ANY_LEFT: eHJustify = SvxCellHorJustify::Left; break;
86 case SID_ALIGN_ANY_HCENTER: eHJustify = SvxCellHorJustify::Center; break;
87 case SID_ALIGN_ANY_RIGHT: eHJustify = SvxCellHorJustify::Right; break;
88 case SID_ALIGN_ANY_JUSTIFIED: eHJustify = SvxCellHorJustify::Block; break;
89 default: OSL_FAIL( "lclConvertSlotToHAlign - invalid slot" );
90 }
91 return eHJustify;
92 }
93
lclConvertSlotToVAlign(sal_uInt16 nSlot)94 SvxCellVerJustify lclConvertSlotToVAlign( sal_uInt16 nSlot )
95 {
96 SvxCellVerJustify eVJustify = SvxCellVerJustify::Standard;
97 switch( nSlot )
98 {
99 case SID_ALIGN_ANY_VDEFAULT: eVJustify = SvxCellVerJustify::Standard; break;
100 case SID_ALIGN_ANY_TOP: eVJustify = SvxCellVerJustify::Top; break;
101 case SID_ALIGN_ANY_VCENTER: eVJustify = SvxCellVerJustify::Center; break;
102 case SID_ALIGN_ANY_BOTTOM: eVJustify = SvxCellVerJustify::Bottom; break;
103 default: OSL_FAIL( "lclConvertSlotToVAlign - invalid slot" );
104 }
105 return eVJustify;
106 }
107
108 } // namespace
109
110
SFX_IMPL_INTERFACE(ScFormatShell,SfxShell)111 SFX_IMPL_INTERFACE(ScFormatShell, SfxShell)
112
113 void ScFormatShell::InitInterface_Impl()
114 {
115 GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT,
116 SfxVisibilityFlags::Standard | SfxVisibilityFlags::Server,
117 ToolbarId::Objectbar_Format);
118 }
119
ScFormatShell(ScViewData & rData)120 ScFormatShell::ScFormatShell(ScViewData& rData) :
121 SfxShell(rData.GetViewShell()),
122 rViewData(rData)
123 {
124 ScTabViewShell* pTabViewShell = GetViewData().GetViewShell();
125
126 SetPool( &pTabViewShell->GetPool() );
127 SfxUndoManager* pMgr = rViewData.GetSfxDocShell().GetUndoManager();
128 SetUndoManager( pMgr );
129 if (pMgr && !rViewData.GetDocument().IsUndoEnabled())
130 {
131 pMgr->SetMaxUndoActionCount( 0 );
132 }
133 SetName(u"Format"_ustr);
134 }
135
~ScFormatShell()136 ScFormatShell::~ScFormatShell()
137 {
138 }
139
ExecuteStyle(SfxRequest & rReq)140 void ScFormatShell::ExecuteStyle( SfxRequest& rReq )
141 {
142 const SfxItemSet* pArgs = rReq.GetArgs();
143 const sal_uInt16 nSlotId = rReq.GetSlot();
144
145 ScDocShell& rDocSh = GetViewData().GetDocShell();
146 ScTabViewShell* pTabViewShell= GetViewData().GetViewShell();
147 ScDocument& rDoc = rDocSh.GetDocument();
148 SfxStyleSheetBasePool* pStylePool = rDoc.GetStyleSheetPool();
149
150 if (nSlotId == SID_STYLE_PREVIEW)
151 {
152 SfxStyleFamily eFamily = SfxStyleFamily::Para;
153 const SfxUInt16Item* pFamItem;
154 if ( pArgs && (pFamItem = pArgs->GetItemIfSet( SID_STYLE_FAMILY )) )
155 eFamily = static_cast<SfxStyleFamily>(pFamItem->GetValue());
156 const SfxPoolItem* pNameItem;
157 OUString aStyleName;
158 if (pArgs && SfxItemState::SET == pArgs->GetItemState( nSlotId, true, &pNameItem ))
159 aStyleName = static_cast<const SfxStringItem*>(pNameItem)->GetValue();
160 if ( eFamily == SfxStyleFamily::Para ) // CellStyles
161 {
162 ScMarkData aFuncMark( rViewData.GetMarkData() );
163 ScViewUtil::UnmarkFiltered( aFuncMark, rDoc );
164 aFuncMark.MarkToMulti();
165
166 if ( !aFuncMark.IsMarked() && !aFuncMark.IsMultiMarked() )
167 {
168 SCCOL nCol = rViewData.GetCurX();
169 SCROW nRow = rViewData.GetCurY();
170 SCTAB nTab = rViewData.GetTabNo();
171 ScRange aRange( nCol, nRow, nTab );
172 aFuncMark.SetMarkArea( aRange );
173 }
174 rDoc.SetPreviewSelection( aFuncMark );
175 ScStyleSheet* pPreviewStyle = static_cast<ScStyleSheet*>( pStylePool->Find( aStyleName, eFamily ) );
176 rDoc.SetPreviewCellStyle( pPreviewStyle );
177 ScPatternAttr aAttr( *rDoc.GetSelectionPattern( aFuncMark ) );
178 aAttr.SetStyleSheet( pPreviewStyle );
179
180 SfxItemSet aItemSet( GetPool() );
181
182 ScPatternAttr aNewAttrs(GetViewData().GetDocument().getCellAttributeHelper());
183 SfxItemSet& rNewSet = aNewAttrs.GetItemSetWritable();
184 rNewSet.Put( aItemSet, false );
185
186 rDoc.ApplySelectionPattern( aNewAttrs, rDoc.GetPreviewSelection() );
187 pTabViewShell->UpdateSelectionArea(aFuncMark, &aAttr, /*adjustHeight*/ false);
188 }
189 }
190 else if (nSlotId == SID_STYLE_END_PREVIEW)
191 {
192 // No mark at all happens when creating a new document, in which
193 // case the selection pattern obtained would be empty (created of
194 // GetPool()) anyway and nothing needs to be applied.
195 ScMarkData aPreviewMark( rDoc.GetPreviewSelection());
196 if (aPreviewMark.IsMarked() || aPreviewMark.IsMultiMarked())
197 {
198 ScPatternAttr aAttr( *rDoc.GetSelectionPattern( aPreviewMark ) );
199 if ( ScStyleSheet* pPreviewStyle = rDoc.GetPreviewCellStyle() )
200 aAttr.SetStyleSheet( pPreviewStyle );
201 rDoc.SetPreviewCellStyle(nullptr);
202
203 SfxItemSet aItemSet( GetPool() );
204
205 ScPatternAttr aNewAttrs(GetViewData().GetDocument().getCellAttributeHelper());
206 SfxItemSet& rNewSet = aNewAttrs.GetItemSetWritable();
207 rNewSet.Put( aItemSet, false );
208 rDoc.ApplySelectionPattern( aNewAttrs, aPreviewMark );
209 pTabViewShell->UpdateSelectionArea(aPreviewMark, &aAttr, /*adjustHeight*/ false);
210 }
211 }
212 else if (nSlotId == SID_CLASSIFICATION_APPLY)
213 {
214 const SfxPoolItem* pItem = nullptr;
215 if (pArgs && pArgs->GetItemState(nSlotId, false, &pItem) == SfxItemState::SET)
216 {
217 const OUString& rName = static_cast<const SfxStringItem*>(pItem)->GetValue();
218 SfxClassificationHelper aHelper(rDocSh.getDocProperties());
219 auto eType = SfxClassificationPolicyType::IntellectualProperty;
220 if (const SfxStringItem* pNameItem = pArgs->GetItemIfSet(SID_TYPE_NAME, false))
221 {
222 const OUString& rType = pNameItem->GetValue();
223 eType = SfxClassificationHelper::stringToPolicyType(rType);
224 }
225 aHelper.SetBACName(rName, eType);
226 }
227 else
228 SAL_WARN("sc.ui", "missing parameter for SID_CLASSIFICATION_APPLY");
229 }
230 else
231 {
232 OSL_FAIL( "Unknown slot (ScViewShell::ExecuteStyle)" );
233 }
234 }
235
ExecuteNumFormat(SfxRequest & rReq)236 void ScFormatShell::ExecuteNumFormat( SfxRequest& rReq )
237 {
238 ScModule* pScMod = ScModule::get();
239 ScTabViewShell* pTabViewShell = GetViewData().GetViewShell();
240 const SfxItemSet* pReqArgs = rReq.GetArgs();
241 sal_uInt16 nSlot = rReq.GetSlot();
242 SfxBindings& rBindings = pTabViewShell->GetViewFrame().GetBindings();
243
244 pTabViewShell->HideListBox(); // Autofilter-DropDown-Listbox
245
246 // End input
247 if ( GetViewData().HasEditView( GetViewData().GetActivePart() ) )
248 {
249 switch ( nSlot )
250 {
251 case SID_NUMBER_TYPE_FORMAT:
252 case SID_NUMBER_TWODEC:
253 case SID_NUMBER_SCIENTIFIC:
254 case SID_NUMBER_DATE:
255 case SID_NUMBER_CURRENCY:
256 case SID_NUMBER_PERCENT:
257 case SID_NUMBER_STANDARD:
258 case SID_NUMBER_FORMAT:
259 case SID_NUMBER_INCDEC:
260 case SID_NUMBER_DECDEC:
261 case SID_NUMBER_THOUSANDS:
262 case FID_DEFINE_NAME:
263 case FID_ADD_NAME:
264 case FID_USE_NAME:
265 case FID_INSERT_NAME:
266 case SID_SPELL_DIALOG:
267 case SID_HANGUL_HANJA_CONVERSION:
268
269 pScMod->InputEnterHandler();
270 pTabViewShell->UpdateInputHandler();
271 break;
272
273 default:
274 break;
275 }
276 }
277
278 SvNumFormatType nType = GetCurrentNumberFormatType();
279 switch ( nSlot )
280 {
281 case SID_NUMBER_TWODEC:
282 {
283 const SfxItemSet& rAttrSet = pTabViewShell->GetSelectionPattern()->GetItemSet();
284 sal_uInt32 nNumberFormat = rAttrSet.Get(ATTR_VALUE_FORMAT).GetValue();
285
286 if ((nType & SvNumFormatType::NUMBER) && nNumberFormat == 4)
287 pTabViewShell->SetNumberFormat( SvNumFormatType::NUMBER );
288 else
289 pTabViewShell->SetNumberFormat( SvNumFormatType::NUMBER, 4 );
290 rBindings.Invalidate( nSlot );
291 rReq.Done();
292 }
293 break;
294 case SID_NUMBER_SCIENTIFIC:
295 if (nType & SvNumFormatType::SCIENTIFIC)
296 pTabViewShell->SetNumberFormat( SvNumFormatType::NUMBER );
297 else
298 pTabViewShell->SetNumberFormat( SvNumFormatType::SCIENTIFIC );
299 rBindings.Invalidate( nSlot );
300 rReq.Done();
301 break;
302 case SID_NUMBER_DATE:
303 if (nType & SvNumFormatType::DATE)
304 pTabViewShell->SetNumberFormat( SvNumFormatType::NUMBER );
305 else
306 pTabViewShell->SetNumberFormat( SvNumFormatType::DATE );
307 rBindings.Invalidate( nSlot );
308 rReq.Done();
309 break;
310 case SID_NUMBER_TIME:
311 if (nType & SvNumFormatType::TIME)
312 pTabViewShell->SetNumberFormat( SvNumFormatType::NUMBER );
313 else
314 pTabViewShell->SetNumberFormat( SvNumFormatType::TIME );
315 rBindings.Invalidate( nSlot );
316 rReq.Done();
317 break;
318 case SID_NUMBER_CURRENCY:
319 if(pReqArgs)
320 {
321 const SfxPoolItem* pItem;
322 if ( pReqArgs->HasItem( SID_NUMBER_CURRENCY, &pItem ) )
323 {
324 sal_uInt32 nNewFormat = static_cast<const SfxUInt32Item*>(pItem)->GetValue();
325 ScDocument& rDoc = rViewData.GetDocument();
326 SvNumberFormatter* pFormatter = rDoc.GetFormatTable();
327 const SfxItemSet& rOldSet = pTabViewShell->GetSelectionPattern()->GetItemSet();
328
329 LanguageType eOldLang = rOldSet.Get( ATTR_LANGUAGE_FORMAT ).GetLanguage();
330 sal_uInt32 nOldFormat = rOldSet.Get( ATTR_VALUE_FORMAT ).GetValue();
331
332 if ( nOldFormat != nNewFormat )
333 {
334 const SvNumberformat* pNewEntry = pFormatter->GetEntry( nNewFormat );
335 ScPatternAttr aNewAttrs(rDoc.getCellAttributeHelper());
336 LanguageType eNewLang = pNewEntry ? pNewEntry->GetLanguage() : LANGUAGE_DONTKNOW;
337 if ( eNewLang != eOldLang && eNewLang != LANGUAGE_DONTKNOW )
338 aNewAttrs.ItemSetPut(SvxLanguageItem(eNewLang, ATTR_LANGUAGE_FORMAT));
339 aNewAttrs.ItemSetPut(SfxUInt32Item(ATTR_VALUE_FORMAT, nNewFormat));
340 pTabViewShell->ApplySelectionPattern( aNewAttrs );
341 }
342 else
343 pTabViewShell->SetNumberFormat( SvNumFormatType::NUMBER );
344 }
345 }
346 else
347 {
348 if ( nType & SvNumFormatType::CURRENCY )
349 pTabViewShell->SetNumberFormat( SvNumFormatType::NUMBER );
350 else
351 pTabViewShell->SetNumberFormat( SvNumFormatType::CURRENCY );
352 }
353 rBindings.Invalidate( nSlot );
354 rReq.Done();
355 break;
356 case SID_NUMBER_PERCENT:
357 if (nType & SvNumFormatType::PERCENT)
358 pTabViewShell->SetNumberFormat( SvNumFormatType::NUMBER );
359 else
360 pTabViewShell->SetNumberFormat( SvNumFormatType::PERCENT );
361 rBindings.Invalidate( nSlot );
362 rReq.Done();
363 break;
364 case SID_NUMBER_STANDARD:
365 pTabViewShell->SetNumberFormat( SvNumFormatType::NUMBER );
366 rReq.Done();
367 break;
368 case SID_NUMBER_INCDEC:
369 pTabViewShell->ChangeNumFmtDecimals( true );
370 rReq.Done();
371 break;
372 case SID_NUMBER_DECDEC:
373 pTabViewShell->ChangeNumFmtDecimals( false );
374 rReq.Done();
375 break;
376 case SID_NUMBER_THOUSANDS:
377 {
378 ScDocument& rDoc = rViewData.GetDocument();
379 SvNumberFormatter* pFormatter = rDoc.GetFormatTable();
380 bool bThousand(false);
381 bool bNegRed(false);
382 sal_uInt16 nPrecision(0);
383 sal_uInt16 nLeadZeroes(0);
384 LanguageType eLanguage = ScGlobal::eLnge;
385
386 sal_uInt32 nCurrentNumberFormat = rDoc.GetNumberFormat(
387 rViewData.GetCurX(), rViewData.GetCurY(), rViewData.GetTabNo());
388 const SvNumberformat* pEntry = pFormatter->GetEntry(nCurrentNumberFormat);
389
390 if (pEntry)
391 eLanguage = pEntry->GetLanguage();
392
393 pFormatter->GetFormatSpecialInfo(nCurrentNumberFormat, bThousand, bNegRed, nPrecision, nLeadZeroes);
394 bThousand = !bThousand;
395 OUString aCode = pFormatter->GenerateFormat(
396 nCurrentNumberFormat,
397 eLanguage,
398 bThousand,
399 bNegRed,
400 nPrecision,
401 nLeadZeroes);
402 pTabViewShell->SetNumFmtByStr(aCode);
403
404 rBindings.Invalidate(nSlot);
405 rReq.Done();
406 }
407 break;
408 case SID_NUMBER_FORMAT:
409 // symphony version with format interpretation
410 if(pReqArgs)
411 {
412 const SfxPoolItem* pItem;
413 ScDocument& rDoc = rViewData.GetDocument();
414 SvNumberFormatter* pFormatter = rDoc.GetFormatTable();
415
416 sal_uInt32 nCurrentNumberFormat = rDoc.GetNumberFormat(
417 rViewData.GetCurX(), rViewData.GetCurY(), rViewData.GetTabNo());
418 const SvNumberformat* pEntry = pFormatter->GetEntry(nCurrentNumberFormat);
419
420 if(!pEntry)
421 break;
422
423 LanguageType eLanguage = pEntry->GetLanguage();
424 SvNumFormatType eType = pEntry->GetMaskedType();
425
426 //Just use eType to judge whether the command is fired for NUMBER/PERCENT/CURRENCY/SCIENTIFIC/FRACTION/TIME
427 //In sidebar, users can fire SID_NUMBER_FORMAT command by operating the related UI controls before they are disable
428 if(!(eType == SvNumFormatType::ALL
429 || eType == SvNumFormatType::NUMBER
430 || eType == SvNumFormatType::PERCENT
431 || eType == SvNumFormatType::CURRENCY
432 || eType == SvNumFormatType::SCIENTIFIC
433 || eType == SvNumFormatType::TIME
434 || eType == SvNumFormatType::FRACTION))
435 pEntry = nullptr;
436
437 if(SfxItemState::SET == pReqArgs->GetItemState(nSlot, true, &pItem) && pEntry)
438 {
439 OUString aCode = static_cast<const SfxStringItem*>(pItem)->GetValue();
440 sal_uInt16 aLen = aCode.getLength();
441 std::unique_ptr<OUString[]> sFormat( new OUString[4] );
442 OUStringBuffer sTmpStr;
443 sal_uInt16 nCount(0);
444 sal_uInt16 nStrCount(0);
445
446 while(nCount < aLen)
447 {
448 sal_Unicode cChar = aCode[nCount];
449
450 if(cChar == ',')
451 {
452 sFormat[nStrCount] = sTmpStr.makeStringAndClear();
453 nStrCount++;
454 }
455 else
456 {
457 sTmpStr.append(cChar);
458 }
459
460 nCount++;
461
462 if(nStrCount > 3)
463 break;
464 }
465
466 const bool bThousand = static_cast<bool>(sFormat[0].toInt32());
467 const bool bNegRed = static_cast<bool>(sFormat[1].toInt32());
468 const sal_uInt16 nPrecision = static_cast<sal_uInt16>(sFormat[2].toInt32());
469 const sal_uInt16 nLeadZeroes = static_cast<sal_uInt16>(sFormat[3].toInt32());
470
471 aCode = pFormatter->GenerateFormat(
472 nCurrentNumberFormat,//modify
473 eLanguage,
474 bThousand,
475 bNegRed,
476 nPrecision,
477 nLeadZeroes);
478 pTabViewShell->SetNumFmtByStr(aCode);
479 }
480 }
481 break;
482
483 case SID_ATTR_NUMBERFORMAT_VALUE:
484 if ( pReqArgs )
485 {
486 if ( const SfxUInt32Item* pItem = pReqArgs->GetItemIfSet( ATTR_VALUE_FORMAT ) )
487 {
488 // We have to accomplish this using ApplyAttributes()
489 // because we also need the language information to be
490 // considered.
491 const SfxItemSet& rOldSet =
492 pTabViewShell->GetSelectionPattern()->GetItemSet();
493 SfxItemPool* pDocPool = GetViewData().GetDocument().GetPool();
494 SfxItemSetFixed<ATTR_PATTERN_START, ATTR_PATTERN_END> aNewSet( *pDocPool );
495 aNewSet.Put( *pItem );
496 pTabViewShell->ApplyAttributes( aNewSet, rOldSet );
497 }
498 }
499 break;
500
501 case SID_NUMBER_TYPE_FORMAT:
502 if ( pReqArgs )
503 {
504 const SfxPoolItem* pItem;
505 if ( pReqArgs->GetItemState( nSlot, true, &pItem ) == SfxItemState::SET )
506 {
507 sal_uInt16 nFormat = static_cast<const SfxUInt16Item *>(pItem)->GetValue();
508 switch(nFormat)
509 {
510 case 0:
511 pTabViewShell->SetNumberFormat( SvNumFormatType::NUMBER); //Modify
512 break;
513 case 1:
514 pTabViewShell->SetNumberFormat( SvNumFormatType::NUMBER, 2 ); //Modify
515 break;
516 case 2:
517 pTabViewShell->SetNumberFormat( SvNumFormatType::PERCENT );
518 break;
519 case 3:
520 pTabViewShell->SetNumberFormat( SvNumFormatType::CURRENCY );
521 break;
522 case 4:
523 pTabViewShell->SetNumberFormat( SvNumFormatType::DATE );
524 break;
525 case 5:
526 pTabViewShell->SetNumberFormat( SvNumFormatType::TIME );
527 break;
528 case 6:
529 pTabViewShell->SetNumberFormat( SvNumFormatType::SCIENTIFIC );
530 break;
531 case 7:
532 pTabViewShell->SetNumberFormat( SvNumFormatType::FRACTION );
533 break;
534 case 8:
535 pTabViewShell->SetNumberFormat( SvNumFormatType::LOGICAL );
536 break;
537 case 9:
538 pTabViewShell->SetNumberFormat( SvNumFormatType::TEXT );
539 break;
540 default:
541 ;
542 }
543 rReq.Done();
544 }
545 }
546 break;
547
548 default:
549 OSL_FAIL("ExecuteEdit: invalid slot");
550 break;
551 }
552 }
553
ExecuteAlignment(SfxRequest & rReq)554 void ScFormatShell::ExecuteAlignment( SfxRequest& rReq )
555 {
556 ScTabViewShell* pTabViewShell = GetViewData().GetViewShell();
557 SfxBindings& rBindings = rViewData.GetBindings();
558 const SfxItemSet* pSet = rReq.GetArgs();
559 sal_uInt16 nSlot = rReq.GetSlot();
560
561 pTabViewShell->HideListBox(); // Autofilter-DropDown-Listbox
562
563 switch( nSlot )
564 {
565 // pseudo slots for Format menu
566 case SID_ALIGN_ANY_HDEFAULT:
567 case SID_ALIGN_ANY_LEFT:
568 case SID_ALIGN_ANY_HCENTER:
569 case SID_ALIGN_ANY_RIGHT:
570 case SID_ALIGN_ANY_JUSTIFIED:
571 pTabViewShell->ApplyAttr( SvxHorJustifyItem( lclConvertSlotToHAlign( nSlot ), ATTR_HOR_JUSTIFY ) );
572 break;
573 case SID_ALIGN_ANY_VDEFAULT:
574 case SID_ALIGN_ANY_TOP:
575 case SID_ALIGN_ANY_VCENTER:
576 case SID_ALIGN_ANY_BOTTOM:
577 pTabViewShell->ApplyAttr( SvxVerJustifyItem( lclConvertSlotToVAlign( nSlot ), ATTR_VER_JUSTIFY ) );
578 break;
579
580 default:
581 if( pSet )
582 {
583 const SfxPoolItem* pItem = nullptr;
584 if( pSet->GetItemState(GetPool().GetWhichIDFromSlotID(nSlot), true, &pItem ) == SfxItemState::SET )
585 {
586
587 switch ( nSlot )
588 {
589 case SID_ATTR_ALIGN_HOR_JUSTIFY:
590 case SID_ATTR_ALIGN_VER_JUSTIFY:
591 case SID_ATTR_ALIGN_INDENT:
592 case SID_ATTR_ALIGN_HYPHENATION:
593 case SID_ATTR_ALIGN_DEGREES:
594 case SID_ATTR_ALIGN_LOCKPOS:
595 case SID_ATTR_ALIGN_MARGIN:
596 case SID_ATTR_ALIGN_STACKED:
597 pTabViewShell->ApplyAttr( *pItem );
598 break;
599
600 case SID_H_ALIGNCELL:
601 {
602 SvxCellHorJustify eJust = static_cast<const SvxHorJustifyItem*>(pItem)->GetValue();
603 // #i78476# update alignment of text in cell edit mode
604 pTabViewShell->UpdateInputHandlerCellAdjust( eJust );
605 pTabViewShell->ApplyAttr( SvxHorJustifyItem( eJust, ATTR_HOR_JUSTIFY ) );
606 }
607 break;
608 case SID_V_ALIGNCELL:
609 pTabViewShell->ApplyAttr( SvxVerJustifyItem( static_cast<const SvxVerJustifyItem*>(pItem)->GetValue(), ATTR_VER_JUSTIFY ) );
610 break;
611 default:
612 OSL_FAIL( "ExecuteAlignment: invalid slot" );
613 return;
614 }
615 }
616 }
617 }
618 rBindings.Invalidate( SID_ATTR_PARA_ADJUST_LEFT );
619 rBindings.Invalidate( SID_ATTR_PARA_ADJUST_RIGHT );
620 rBindings.Invalidate( SID_ATTR_PARA_ADJUST_BLOCK );
621 rBindings.Invalidate( SID_ATTR_PARA_ADJUST_CENTER);
622 rBindings.Invalidate( SID_ALIGNLEFT );
623 rBindings.Invalidate( SID_ALIGNRIGHT );
624 rBindings.Invalidate( SID_ALIGNCENTERHOR );
625 rBindings.Invalidate( SID_ALIGNBLOCK );
626 rBindings.Invalidate( SID_ALIGNTOP );
627 rBindings.Invalidate( SID_ALIGNBOTTOM );
628 rBindings.Invalidate( SID_ALIGNCENTERVER );
629 rBindings.Invalidate( SID_V_ALIGNCELL );
630 rBindings.Invalidate( SID_H_ALIGNCELL );
631 // pseudo slots for Format menu
632 rBindings.Invalidate( SID_ALIGN_ANY_HDEFAULT );
633 rBindings.Invalidate( SID_ALIGN_ANY_LEFT );
634 rBindings.Invalidate( SID_ALIGN_ANY_HCENTER );
635 rBindings.Invalidate( SID_ALIGN_ANY_RIGHT );
636 rBindings.Invalidate( SID_ALIGN_ANY_JUSTIFIED );
637 rBindings.Invalidate( SID_ALIGN_ANY_VDEFAULT );
638 rBindings.Invalidate( SID_ALIGN_ANY_TOP );
639 rBindings.Invalidate( SID_ALIGN_ANY_VCENTER );
640 rBindings.Invalidate( SID_ALIGN_ANY_BOTTOM );
641 rBindings.Update();
642
643 if( ! rReq.IsAPI() )
644 rReq.Done();
645 }
646
ExecuteTextAttr(SfxRequest & rReq)647 void ScFormatShell::ExecuteTextAttr( SfxRequest& rReq )
648 {
649 ScTabViewShell* pTabViewShell = GetViewData().GetViewShell();
650 SfxBindings& rBindings = rViewData.GetBindings();
651 const ScPatternAttr* pAttrs = pTabViewShell->GetSelectionPattern();
652 const SfxItemSet* pSet = rReq.GetArgs();
653 sal_uInt16 nSlot = rReq.GetSlot();
654 std::optional<SfxAllItemSet> pNewSet;
655
656 pTabViewShell->HideListBox(); // Autofilter-DropDown-Listbox
657
658 if ( (nSlot == SID_ATTR_CHAR_WEIGHT)
659 ||(nSlot == SID_ATTR_CHAR_POSTURE)
660 ||(nSlot == SID_ATTR_CHAR_UNDERLINE)
661 ||(nSlot == SID_ULINE_VAL_NONE)
662 ||(nSlot == SID_ULINE_VAL_SINGLE)
663 ||(nSlot == SID_ULINE_VAL_DOUBLE)
664 ||(nSlot == SID_ULINE_VAL_DOTTED) )
665 {
666 pNewSet.emplace( GetPool() );
667
668 switch ( nSlot )
669 {
670 case SID_ATTR_CHAR_WEIGHT:
671 {
672 // #i78017 establish the same behaviour as in Writer
673 SvtScriptType nScript = SvtScriptType::LATIN | SvtScriptType::ASIAN | SvtScriptType::COMPLEX;
674
675 SfxItemPool& rPool = GetPool();
676 SvxScriptSetItem aSetItem( nSlot, rPool );
677 if ( pSet )
678 aSetItem.PutItemForScriptType( nScript, pSet->Get( ATTR_FONT_WEIGHT ) );
679 else
680 {
681 // toggle manually
682
683 FontWeight eWeight = WEIGHT_BOLD;
684 SvxScriptSetItem aOldSetItem( nSlot, rPool );
685 aOldSetItem.GetItemSet().Put( pAttrs->GetItemSet(), false );
686 const SfxPoolItem* pCore = aOldSetItem.GetItemOfScript( nScript );
687 if ( pCore && static_cast<const SvxWeightItem*>(pCore)->GetWeight() == WEIGHT_BOLD )
688 eWeight = WEIGHT_NORMAL;
689
690 aSetItem.PutItemForScriptType( nScript, SvxWeightItem( eWeight, ATTR_FONT_WEIGHT ) );
691 }
692 pTabViewShell->ApplyUserItemSet( aSetItem.GetItemSet() );
693 pNewSet->Put( aSetItem.GetItemSet(), false );
694 }
695 break;
696
697 case SID_ATTR_CHAR_POSTURE:
698 {
699 // #i78017 establish the same behaviour as in Writer
700 SvtScriptType nScript = SvtScriptType::LATIN | SvtScriptType::ASIAN | SvtScriptType::COMPLEX;
701
702 SfxItemPool& rPool = GetPool();
703 SvxScriptSetItem aSetItem( nSlot, rPool );
704 if ( pSet )
705 aSetItem.PutItemForScriptType( nScript, pSet->Get( ATTR_FONT_POSTURE ) );
706 else
707 {
708 // toggle manually
709
710 FontItalic eItalic = ITALIC_NORMAL;
711 SvxScriptSetItem aOldSetItem( nSlot, rPool );
712 aOldSetItem.GetItemSet().Put( pAttrs->GetItemSet(), false );
713 const SfxPoolItem* pCore = aOldSetItem.GetItemOfScript( nScript );
714 if ( pCore && static_cast<const SvxPostureItem*>(pCore)->GetPosture() == ITALIC_NORMAL )
715 eItalic = ITALIC_NONE;
716
717 aSetItem.PutItemForScriptType( nScript, SvxPostureItem( eItalic, ATTR_FONT_POSTURE ) );
718 }
719 pTabViewShell->ApplyUserItemSet( aSetItem.GetItemSet() );
720 pNewSet->Put( aSetItem.GetItemSet(), false );
721 }
722 break;
723
724 case SID_ATTR_CHAR_UNDERLINE:
725 {
726 if( pSet )
727 {
728 const SfxPoolItem& rUnderline = pSet->Get( ATTR_FONT_UNDERLINE );
729
730 if( dynamic_cast<const SvxUnderlineItem*>( &rUnderline) != nullptr )
731 {
732 pTabViewShell->ApplyAttr( rUnderline );
733 pNewSet->Put( rUnderline );
734 }
735 else if ( auto pTextLineItem = dynamic_cast<const SvxTextLineItem*>( &rUnderline) )
736 {
737 // #i106580# also allow SvxTextLineItem (base class of SvxUnderlineItem)
738 SvxUnderlineItem aNewItem( pTextLineItem->GetLineStyle(), pTextLineItem->Which() );
739 aNewItem.SetColor( pTextLineItem->GetColor() );
740 pTabViewShell->ApplyAttr( aNewItem );
741 pNewSet->Put( aNewItem );
742 }
743 }
744 else
745 {
746 SvxUnderlineItem aUnderline( pAttrs->GetItem( ATTR_FONT_UNDERLINE ) );
747 FontLineStyle eUnderline = (LINESTYLE_NONE != aUnderline.GetLineStyle())
748 ? LINESTYLE_NONE
749 : LINESTYLE_SINGLE;
750 aUnderline.SetLineStyle( eUnderline );
751 pTabViewShell->ApplyAttr( aUnderline );
752 pNewSet->Put( aUnderline );
753 }
754 }
755 break;
756
757 case SID_ULINE_VAL_NONE:
758 pTabViewShell->ApplyAttr( SvxUnderlineItem( LINESTYLE_NONE, ATTR_FONT_UNDERLINE ) );
759 break;
760 case SID_ULINE_VAL_SINGLE: // Toggles
761 case SID_ULINE_VAL_DOUBLE:
762 case SID_ULINE_VAL_DOTTED:
763 {
764 FontLineStyle eOld = pAttrs->GetItem(ATTR_FONT_UNDERLINE).GetLineStyle();
765 FontLineStyle eNew = eOld;
766 switch (nSlot)
767 {
768 case SID_ULINE_VAL_SINGLE:
769 eNew = ( eOld == LINESTYLE_SINGLE ) ? LINESTYLE_NONE : LINESTYLE_SINGLE;
770 break;
771 case SID_ULINE_VAL_DOUBLE:
772 eNew = ( eOld == LINESTYLE_DOUBLE ) ? LINESTYLE_NONE : LINESTYLE_DOUBLE;
773 break;
774 case SID_ULINE_VAL_DOTTED:
775 eNew = ( eOld == LINESTYLE_DOTTED ) ? LINESTYLE_NONE : LINESTYLE_DOTTED;
776 break;
777 }
778 pTabViewShell->ApplyAttr( SvxUnderlineItem( eNew, ATTR_FONT_UNDERLINE ) );
779 }
780 break;
781
782 default:
783 break;
784 }
785 rBindings.Invalidate( nSlot );
786 }
787 else
788 {
789 /*
790 * "Self-made" functionality of radio buttons
791 * At the toggle the default state is used, this means
792 * no button was clicked.
793 */
794
795 const SfxItemSet& rAttrSet = pTabViewShell->GetSelectionPattern()->GetItemSet();
796 const SvxHorJustifyItem* pHorJustify = rAttrSet.GetItemIfSet(ATTR_HOR_JUSTIFY);
797 const SvxVerJustifyItem* pVerJustify = rAttrSet.GetItemIfSet(ATTR_VER_JUSTIFY );
798 SvxCellHorJustify eHorJustify = SvxCellHorJustify::Standard;
799 SvxCellVerJustify eVerJustify = SvxCellVerJustify::Standard;
800
801 if (pHorJustify)
802 {
803 eHorJustify = pHorJustify->GetValue();
804 }
805 if (pVerJustify)
806 {
807 eVerJustify = pVerJustify->GetValue();
808 }
809
810 switch ( nSlot )
811 {
812 case SID_ALIGNLEFT:
813 rReq.SetSlot( SID_H_ALIGNCELL );
814 rReq.AppendItem( SvxHorJustifyItem(
815 !pHorJustify || (eHorJustify != SvxCellHorJustify::Left) ?
816 SvxCellHorJustify::Left : SvxCellHorJustify::Standard, SID_H_ALIGNCELL ) );
817 ExecuteSlot( rReq, GetInterface() );
818 return;
819
820 case SID_ALIGNRIGHT:
821 rReq.SetSlot( SID_H_ALIGNCELL );
822 rReq.AppendItem( SvxHorJustifyItem(
823 !pHorJustify || (eHorJustify != SvxCellHorJustify::Right) ?
824 SvxCellHorJustify::Right : SvxCellHorJustify::Standard, SID_H_ALIGNCELL ) );
825 ExecuteSlot( rReq, GetInterface() );
826 return;
827
828 case SID_ALIGNCENTERHOR:
829 rReq.SetSlot( SID_H_ALIGNCELL );
830 rReq.AppendItem( SvxHorJustifyItem(
831 !pHorJustify || (eHorJustify != SvxCellHorJustify::Center) ?
832 SvxCellHorJustify::Center : SvxCellHorJustify::Standard, SID_H_ALIGNCELL ) );
833 ExecuteSlot( rReq, GetInterface() );
834 return;
835
836 case SID_ALIGNBLOCK:
837 rReq.SetSlot( SID_H_ALIGNCELL );
838 rReq.AppendItem( SvxHorJustifyItem(
839 !pHorJustify || (eHorJustify != SvxCellHorJustify::Block) ?
840 SvxCellHorJustify::Block : SvxCellHorJustify::Standard, SID_H_ALIGNCELL ) );
841 ExecuteSlot( rReq, GetInterface() );
842 return;
843
844 case SID_ALIGNTOP:
845 rReq.SetSlot( SID_V_ALIGNCELL );
846 rReq.AppendItem( SvxVerJustifyItem(
847 !pVerJustify || (eVerJustify != SvxCellVerJustify::Top) ?
848 SvxCellVerJustify::Top : SvxCellVerJustify::Standard, SID_V_ALIGNCELL ) );
849 ExecuteSlot( rReq, GetInterface() );
850 return;
851
852 case SID_ALIGNBOTTOM:
853 rReq.SetSlot( SID_V_ALIGNCELL );
854 rReq.AppendItem( SvxVerJustifyItem(
855 !pVerJustify || (eVerJustify != SvxCellVerJustify::Bottom) ?
856 SvxCellVerJustify::Bottom : SvxCellVerJustify::Standard, SID_V_ALIGNCELL ) );
857 ExecuteSlot( rReq, GetInterface() );
858 return;
859
860 case SID_ALIGNCENTERVER:
861 rReq.SetSlot( SID_V_ALIGNCELL );
862 rReq.AppendItem( SvxVerJustifyItem(
863 !pVerJustify || (eVerJustify != SvxCellVerJustify::Center) ?
864 SvxCellVerJustify::Center : SvxCellVerJustify::Standard, SID_V_ALIGNCELL ) );
865 ExecuteSlot( rReq, GetInterface() );
866 return;
867
868 default:
869 break;
870 }
871
872 }
873
874 rBindings.Update();
875
876 if( pNewSet )
877 {
878 rReq.Done( *pNewSet );
879 pNewSet.reset();
880 }
881 else
882 {
883 rReq.Done();
884 }
885
886 }
887
ExecuteAttr(SfxRequest & rReq)888 void ScFormatShell::ExecuteAttr( SfxRequest& rReq )
889 {
890 ScTabViewShell* pTabViewShell = GetViewData().GetViewShell();
891 SfxBindings& rBindings = rViewData.GetBindings();
892 const SfxItemSet* pNewAttrs = rReq.GetArgs();
893 sal_uInt16 nSlot = rReq.GetSlot();
894
895 pTabViewShell->HideListBox(); // Autofilter-DropDown-Listbox
896 ScDocument& rDoc = GetViewData().GetDocument();
897 if ( !pNewAttrs )
898 {
899 switch ( nSlot )
900 {
901 case SID_GROW_FONT_SIZE:
902 case SID_SHRINK_FONT_SIZE:
903 {
904 SfxItemPool& rPool = GetPool();
905 SvxScriptSetItem aSetItem( SID_ATTR_CHAR_FONTHEIGHT, rPool );
906 aSetItem.GetItemSet().Put( pTabViewShell->GetSelectionPattern()->GetItemSet(), false );
907
908 SvtScriptType nScriptTypes = pTabViewShell->GetSelectionScriptType();
909 const SvxFontHeightItem* pSize( static_cast<const SvxFontHeightItem*>( aSetItem.GetItemOfScript( nScriptTypes ) ) );
910
911 if ( pSize )
912 {
913 SvxFontHeightItem aSize( *pSize );
914 sal_uInt32 nSize = aSize.GetHeight();
915
916 const sal_uInt32 nFontInc = 40; // 2pt
917 const sal_uInt32 nFontMaxSz = 19998; // 999.9pt
918 if ( nSlot == SID_GROW_FONT_SIZE )
919 nSize = std::min< sal_uInt32 >( nSize + nFontInc, nFontMaxSz );
920 else
921 nSize = std::max< sal_Int32 >( nSize - nFontInc, nFontInc );
922
923 aSize.SetHeight( nSize );
924 aSetItem.PutItemForScriptType( nScriptTypes, aSize );
925 pTabViewShell->ApplyUserItemSet( aSetItem.GetItemSet() );
926 }
927 rBindings.Invalidate( SID_ATTR_CHAR_FONTHEIGHT );
928 }
929 break;
930
931 case SID_ATTR_CHAR_ENDPREVIEW_FONT:
932 {
933 rDoc.SetPreviewFont(nullptr);
934 pTabViewShell->UpdateSelectionArea(rDoc.GetPreviewSelection(), nullptr,
935 /*adjustHeight*/ false);
936 break;
937 }
938 case SID_ATTR_CHAR_COLOR:
939 case SID_ATTR_CHAR_FONT:
940 case SID_ATTR_CHAR_FONTHEIGHT:
941 pTabViewShell->ExecuteCellFormatDlg(rReq, u"font"_ustr); // when ToolBar is vertical
942 break;
943
944 case SID_BACKGROUND_COLOR:
945 {
946 SvxBrushItem aBrushItem(
947 pTabViewShell->GetSelectionPattern()->GetItem( ATTR_BACKGROUND ) );
948 aBrushItem.SetColor( COL_TRANSPARENT );
949 pTabViewShell->ApplyAttr( aBrushItem, false );
950 }
951 break;
952
953 case SID_ATTR_ALIGN_LINEBREAK: // without parameter as toggle
954 {
955 const ScPatternAttr* pAttrs = pTabViewShell->GetSelectionPattern();
956 bool bOld = pAttrs->GetItem(ATTR_LINEBREAK).GetValue();
957 ScLineBreakCell aBreakItem(!bOld);
958 pTabViewShell->ApplyAttr( aBreakItem );
959
960 SfxAllItemSet aNewSet( GetPool() );
961 aNewSet.Put( aBreakItem );
962 rReq.Done( aNewSet );
963
964 rBindings.Invalidate( nSlot );
965 }
966 break;
967
968 case SID_SCATTR_CELLPROTECTION: // without parameter as toggle
969 {
970 const ScPatternAttr* pAttrs = pTabViewShell->GetSelectionPattern();
971 bool bProtect = pAttrs->GetItem(ATTR_PROTECTION).GetProtection();
972 bool bHideFormula = pAttrs->GetItem(ATTR_PROTECTION).GetHideFormula();
973 bool bHideCell = pAttrs->GetItem(ATTR_PROTECTION).GetHideCell();
974 bool bHidePrint = pAttrs->GetItem(ATTR_PROTECTION).GetHidePrint();
975
976 ScProtectionAttr aProtectionItem( !bProtect, bHideFormula, bHideCell, bHidePrint );
977 pTabViewShell->ApplyAttr( aProtectionItem );
978
979 SfxAllItemSet aNewSet( GetPool() );
980 aNewSet.Put( aProtectionItem );
981 aNewSet.Put( SfxBoolItem( SID_SCATTR_CELLPROTECTION, !bProtect ) );
982 rReq.Done( aNewSet );
983
984 rBindings.Invalidate( nSlot );
985 }
986 break;
987 }
988 }
989 else
990 {
991 switch ( nSlot )
992 {
993 case SID_ATTR_CHAR_PREVIEW_FONT:
994 {
995 SfxItemPool& rPool = GetPool();
996 sal_uInt16 nWhich = rPool.GetWhichIDFromSlotID( nSlot );
997 const SvxFontItem& rFont = static_cast<const SvxFontItem&>(pNewAttrs->Get( nWhich ));
998 SvxScriptSetItem aSetItem( SID_ATTR_CHAR_FONT, rPool );
999 SvtScriptType nScript = pTabViewShell->GetSelectionScriptType();
1000 aSetItem.PutItemForScriptType( nScript, rFont );
1001
1002 ScMarkData aFuncMark( rViewData.GetMarkData() );
1003 ScViewUtil::UnmarkFiltered( aFuncMark, rDoc );
1004 rDoc.SetPreviewFont( aSetItem.GetItemSet().Clone() );
1005 aFuncMark.MarkToMulti();
1006
1007 if ( !aFuncMark.IsMarked() && !aFuncMark.IsMultiMarked() )
1008 {
1009 SCCOL nCol = rViewData.GetCurX();
1010 SCROW nRow = rViewData.GetCurY();
1011 SCTAB nTab = rViewData.GetTabNo();
1012 ScRange aRange( nCol, nRow, nTab );
1013 aFuncMark.SetMarkArea( aRange );
1014 }
1015 rDoc.SetPreviewSelection( aFuncMark );
1016 pTabViewShell->UpdateSelectionArea(aFuncMark, nullptr, /*adjustHeight*/ false);
1017 break;
1018 }
1019 case SID_ATTR_CHAR_OVERLINE:
1020 case SID_ATTR_CHAR_STRIKEOUT:
1021 case SID_ATTR_ALIGN_LINEBREAK:
1022 case SID_ATTR_CHAR_CONTOUR:
1023 case SID_ATTR_CHAR_SHADOWED:
1024 case SID_ATTR_CHAR_RELIEF:
1025 pTabViewShell->ApplyAttr( pNewAttrs->Get( pNewAttrs->GetPool()->GetWhichIDFromSlotID( nSlot ) ) );
1026 rBindings.Invalidate( nSlot );
1027 rBindings.Update( nSlot );
1028 break;
1029 case SID_ATTR_CHAR_COLOR:
1030 case SID_SCATTR_PROTECTION :
1031 {
1032 pTabViewShell->ApplyAttr( pNewAttrs->Get( pNewAttrs->GetPool()->GetWhichIDFromSlotID( nSlot) ), false);
1033
1034 rBindings.Invalidate( nSlot );
1035 rBindings.Update( nSlot );
1036 }
1037
1038 break;
1039
1040 case SID_ATTR_CHAR_FONT:
1041 case SID_ATTR_CHAR_FONTHEIGHT:
1042 {
1043 // #i78017 establish the same behaviour as in Writer
1044 SvtScriptType nScript = SvtScriptType::LATIN | SvtScriptType::ASIAN | SvtScriptType::COMPLEX;
1045 if (nSlot == SID_ATTR_CHAR_FONT)
1046 nScript = pTabViewShell->GetSelectionScriptType();
1047
1048 SfxItemPool& rPool = GetPool();
1049 SvxScriptSetItem aSetItem( nSlot, rPool );
1050 sal_uInt16 nWhich = rPool.GetWhichIDFromSlotID( nSlot );
1051 aSetItem.PutItemForScriptType( nScript, pNewAttrs->Get( nWhich ) );
1052
1053 pTabViewShell->ApplyUserItemSet( aSetItem.GetItemSet() );
1054
1055 rBindings.Invalidate( nSlot );
1056 rBindings.Update( nSlot );
1057 }
1058 break;
1059
1060 case SID_FRAME_LINESTYLE:
1061 {
1062 // Update default line
1063 ::editeng::SvxBorderLine aLine;
1064 const ::editeng::SvxBorderLine* pLine = nullptr;
1065 const SfxInt16Item* lineStyleItem = rReq.GetArg<SfxInt16Item>(FN_PARAM_1);
1066
1067 if (lineStyleItem)
1068 {
1069 const SfxInt16Item* InnerLineWidthItem
1070 = rReq.GetArg<SfxInt16Item>(FN_PARAM_2);
1071 const SfxInt16Item* OuterLineWidthItem
1072 = rReq.GetArg<SfxInt16Item>(FN_PARAM_3);
1073 const SfxInt16Item* LineDistanceItem
1074 = rReq.GetArg<SfxInt16Item>(FN_PARAM_4);
1075
1076 sal_uInt16 InnerLineWidth, OuterLineWidth, LineDistance;
1077 SvxBorderLineStyle lineStyle
1078 = static_cast<SvxBorderLineStyle>(lineStyleItem->GetValue());
1079 InnerLineWidth = InnerLineWidthItem ? InnerLineWidthItem->GetValue() : 0;
1080 OuterLineWidth = OuterLineWidthItem ? OuterLineWidthItem->GetValue() : 0;
1081 LineDistance = LineDistanceItem ? LineDistanceItem->GetValue() : 0;
1082
1083 aLine.GuessLinesWidths(
1084 lineStyle, InnerLineWidth, OuterLineWidth, LineDistance);
1085
1086 pLine = &aLine;
1087 }
1088 else
1089 {
1090 pLine = pNewAttrs->Get(SID_FRAME_LINESTYLE).GetLine();
1091 }
1092
1093 if ( pLine )
1094 {
1095 ::editeng::SvxBorderLine* pDefLine = pTabViewShell->GetDefaultFrameLine();
1096
1097 if ( pDefLine )
1098 {
1099 pDefLine->SetBorderLineStyle(
1100 pLine->GetBorderLineStyle());
1101 pDefLine->SetWidth( pLine->GetWidth( ) );
1102 pTabViewShell->SetSelectionFrameLines( pDefLine, false );
1103 }
1104 else
1105 {
1106 pTabViewShell->SetDefaultFrameLine( pLine );
1107 pTabViewShell->GetDefaultFrameLine()->SetColor( COL_BLACK );
1108 pTabViewShell->SetSelectionFrameLines( pLine, false );
1109 }
1110 }
1111 else
1112 {
1113 Color aColorBlack( COL_BLACK );
1114 ::editeng::SvxBorderLine aDefLine( &aColorBlack, 20,
1115 SvxBorderLineStyle::SOLID );
1116 pTabViewShell->SetDefaultFrameLine( &aDefLine );
1117 pTabViewShell->SetSelectionFrameLines( nullptr, false );
1118 }
1119 rReq.Done();
1120 }
1121 break;
1122
1123 case SID_FRAME_LINECOLOR:
1124 {
1125 ::editeng::SvxBorderLine* pDefLine = pTabViewShell->GetDefaultFrameLine();
1126
1127 Color aColor = pNewAttrs->Get( SID_FRAME_LINECOLOR ).GetValue();
1128
1129 // Update default line
1130 if ( pDefLine )
1131 {
1132 pDefLine->SetColor( aColor );
1133 pTabViewShell->SetSelectionFrameLines( pDefLine, true );
1134 }
1135 else
1136 {
1137 ::editeng::SvxBorderLine aDefLine( &aColor, 20, SvxBorderLineStyle::SOLID );
1138 pTabViewShell->SetDefaultFrameLine( &aDefLine );
1139 pTabViewShell->SetSelectionFrameLines( &aDefLine, false );
1140 }
1141 }
1142 break;
1143
1144 case SID_ATTR_BORDER_OUTER:
1145 case SID_ATTR_BORDER:
1146 {
1147 ::editeng::SvxBorderLine* pDefLine = pTabViewShell->GetDefaultFrameLine();
1148 const ScPatternAttr* pOldAttrs = pTabViewShell->GetSelectionPattern();
1149 SfxItemSetFixed<ATTR_PATTERN_START, ATTR_PATTERN_END> aOldSet( *rDoc.GetPool() );
1150 SfxItemSetFixed<ATTR_PATTERN_START, ATTR_PATTERN_END> aNewSet( *rDoc.GetPool() );
1151 const SfxPoolItem& rBorderAttr =
1152 pOldAttrs->GetItemSet().
1153 Get( ATTR_BORDER );
1154
1155 // Evaluate border items from controller:
1156
1157 if ( const SvxBoxItem* pBoxItem = pNewAttrs->GetItemIfSet( ATTR_BORDER ) )
1158 {
1159 // The SvxFrameToolBoxControl toolbox controller uses a default
1160 // SvxBorderLine (all widths 0) to mark the lines that should be set.
1161 // Macro recording uses a SvxBoxItem with the real values (OutWidth > 0)
1162 // or NULL pointers for no lines.
1163 // -> Substitute existing lines with pDefLine only if widths are 0.
1164 SvxBoxItem aBoxItem ( *pBoxItem );
1165 if ( aBoxItem.GetTop() && aBoxItem.GetTop()->GetOutWidth() == 0 )
1166 aBoxItem.SetLine( pDefLine, SvxBoxItemLine::TOP );
1167 if ( aBoxItem.GetBottom() && aBoxItem.GetBottom()->GetOutWidth() == 0 )
1168 aBoxItem.SetLine( pDefLine, SvxBoxItemLine::BOTTOM );
1169 if ( aBoxItem.GetLeft() && aBoxItem.GetLeft()->GetOutWidth() == 0 )
1170 aBoxItem.SetLine( pDefLine, SvxBoxItemLine::LEFT );
1171 if ( aBoxItem.GetRight() && aBoxItem.GetRight()->GetOutWidth() == 0 )
1172 aBoxItem.SetLine( pDefLine, SvxBoxItemLine::RIGHT );
1173 aNewSet.Put( aBoxItem );
1174 rReq.AppendItem( aBoxItem );
1175 }
1176
1177 if ( const SvxBoxInfoItem* pBoxInfoItem = pNewAttrs->GetItemIfSet( ATTR_BORDER_INNER ) )
1178 {
1179 SvxBoxInfoItem aBoxInfoItem( *pBoxInfoItem );
1180 if ( aBoxInfoItem.GetHori() && aBoxInfoItem.GetHori()->GetOutWidth() == 0 )
1181 aBoxInfoItem.SetLine( pDefLine, SvxBoxInfoItemLine::HORI );
1182 if ( aBoxInfoItem.GetVert() && aBoxInfoItem.GetVert()->GetOutWidth() == 0 )
1183 aBoxInfoItem.SetLine( pDefLine, SvxBoxInfoItemLine::VERT );
1184 aNewSet.Put( aBoxInfoItem );
1185 rReq.AppendItem( aBoxInfoItem );
1186 }
1187 else
1188 {
1189 SvxBoxInfoItem aBoxInfoItem( ATTR_BORDER_INNER );
1190 aBoxInfoItem.SetLine( nullptr, SvxBoxInfoItemLine::HORI );
1191 aBoxInfoItem.SetLine( nullptr, SvxBoxInfoItemLine::VERT );
1192 aNewSet.Put( aBoxInfoItem );
1193 }
1194
1195 aOldSet.Put( rBorderAttr );
1196 pTabViewShell->ApplyAttributes( aNewSet, aOldSet );
1197 }
1198 break;
1199
1200 case SID_ATTR_BORDER_DIAG_TLBR:
1201 case SID_ATTR_BORDER_DIAG_BLTR:
1202 {
1203 const ScPatternAttr* pOldAttrs = pTabViewShell->GetSelectionPattern();
1204 SfxItemSet aOldSet(pOldAttrs->GetItemSet());
1205 SfxItemSet aNewSet(aOldSet);
1206
1207 if(SID_ATTR_BORDER_DIAG_TLBR == nSlot)
1208 {
1209 if(SfxItemState::SET == pNewAttrs->GetItemState(ATTR_BORDER_TLBR))
1210 {
1211 SvxLineItem aItem(ATTR_BORDER_TLBR);
1212 aItem.SetLine(pNewAttrs->Get(ATTR_BORDER_TLBR).GetLine());
1213 aNewSet.Put(aItem);
1214 rReq.AppendItem(aItem);
1215 pTabViewShell->ApplyAttributes(aNewSet, aOldSet);
1216 }
1217 }
1218 else // if( nSlot == SID_ATTR_BORDER_DIAG_BLTR )
1219 {
1220 if(SfxItemState::SET == pNewAttrs->GetItemState(ATTR_BORDER_BLTR ))
1221 {
1222 SvxLineItem aItem(ATTR_BORDER_BLTR);
1223 aItem.SetLine(pNewAttrs->Get(ATTR_BORDER_BLTR).GetLine());
1224 aNewSet.Put(aItem);
1225 rReq.AppendItem(aItem);
1226 pTabViewShell->ApplyAttributes(aNewSet, aOldSet);
1227 }
1228 }
1229
1230 rBindings.Invalidate(nSlot);
1231 }
1232 break;
1233
1234 // ATTR_BACKGROUND (=SID_ATTR_BRUSH) has to be set to two IDs:
1235 case SID_BACKGROUND_COLOR:
1236 {
1237 const SvxColorItem& rNewColorItem = pNewAttrs->Get( SID_BACKGROUND_COLOR );
1238 Color aColor = rNewColorItem.GetValue();
1239
1240 SvxBrushItem aBrushItem(
1241 pTabViewShell->GetSelectionPattern()->GetItem( ATTR_BACKGROUND ) );
1242 aBrushItem.SetColor(aColor);
1243 aBrushItem.setComplexColor(rNewColorItem.getComplexColor());
1244
1245 pTabViewShell->ApplyAttr( aBrushItem, false );
1246 }
1247 break;
1248
1249 case SID_ATTR_BRUSH:
1250 {
1251 SvxBrushItem aBrushItem( pTabViewShell->GetSelectionPattern()->
1252 GetItem( ATTR_BACKGROUND ) );
1253 const SvxBrushItem& rNewBrushItem = static_cast<const SvxBrushItem&>(
1254 pNewAttrs->Get( GetPool().GetWhichIDFromSlotID(nSlot) ) );
1255 aBrushItem.SetColor(rNewBrushItem.GetColor());
1256 aBrushItem.setComplexColor(rNewBrushItem.getComplexColor());
1257 pTabViewShell->ApplyAttr( aBrushItem );
1258 }
1259 break;
1260
1261 case SID_ATTR_BORDER_SHADOW:
1262 {
1263 const SvxShadowItem& rNewShadowItem =
1264 pNewAttrs->Get( ATTR_SHADOW );
1265 pTabViewShell->ApplyAttr( rNewShadowItem );
1266 }
1267 break;
1268
1269 default:
1270 break;
1271 }
1272
1273 if( ! rReq.IsAPI() && ! rReq.IsDone() )
1274 rReq.Done();
1275 }
1276 }
1277
GetAttrState(SfxItemSet & rSet)1278 void ScFormatShell::GetAttrState( SfxItemSet& rSet )
1279 {
1280 ScTabViewShell* pTabViewShell = GetViewData().GetViewShell();
1281 const SfxItemSet& rAttrSet = pTabViewShell->GetSelectionPattern()->GetItemSet();
1282 const SvxBrushItem& rBrushItem = rAttrSet.Get( ATTR_BACKGROUND );
1283 SfxWhichIter aIter( rSet );
1284 sal_uInt16 nWhich = aIter.FirstWhich();
1285
1286 rSet.Put( rAttrSet, false );
1287
1288 // choose font info according to selection script type
1289 SvtScriptType nScript = SvtScriptType::NONE; // GetSelectionScriptType never returns 0
1290 if ( rSet.GetItemState( ATTR_FONT ) != SfxItemState::UNKNOWN )
1291 {
1292 nScript = pTabViewShell->GetSelectionScriptType();
1293 ScViewUtil::PutItemScript( rSet, rAttrSet, ATTR_FONT, nScript );
1294 }
1295 if ( rSet.GetItemState( ATTR_FONT_HEIGHT ) != SfxItemState::UNKNOWN )
1296 {
1297 if (nScript == SvtScriptType::NONE) nScript = pTabViewShell->GetSelectionScriptType();
1298 ScViewUtil::PutItemScript( rSet, rAttrSet, ATTR_FONT_HEIGHT, nScript );
1299 }
1300
1301 while ( nWhich )
1302 {
1303 switch(nWhich)
1304 {
1305 case SID_BACKGROUND_COLOR:
1306 {
1307 rSet.Put( SvxColorItem( rBrushItem.GetColor(), SID_BACKGROUND_COLOR ) );
1308 if(SfxItemState::INVALID == rAttrSet.GetItemState(ATTR_BACKGROUND))
1309 {
1310 rSet.InvalidateItem(SID_BACKGROUND_COLOR);
1311 }
1312 }
1313 break;
1314 case SID_FRAME_LINESTYLE:
1315 case SID_FRAME_LINECOLOR:
1316 {
1317 // handled together because both need the cell border information for decisions
1318 Color aCol;
1319 editeng::SvxBorderLine aLine(nullptr,0,SvxBorderLineStyle::SOLID);
1320 bool bCol = false;
1321 bool bColDisable = false, bStyleDisable = false;
1322 std::shared_ptr<SvxBoxItem> aBoxItem(std::make_shared<SvxBoxItem>(ATTR_BORDER));
1323 std::shared_ptr<SvxBoxInfoItem> aInfoItem(std::make_shared<SvxBoxInfoItem>(ATTR_BORDER_INNER));
1324
1325 pTabViewShell->GetSelectionFrame(aBoxItem, aInfoItem);
1326
1327 if( aBoxItem->GetTop() )
1328 {
1329 bCol = true;
1330 aCol = aBoxItem->GetTop()->GetColor() ;
1331 aLine.SetColor(aCol);
1332 aLine.SetWidth( aBoxItem->GetTop()->GetWidth());
1333 aLine.SetBorderLineStyle( aBoxItem->GetTop()->GetBorderLineStyle());
1334 }
1335
1336 if( aBoxItem->GetBottom() )
1337 {
1338 if(!bCol)
1339 {
1340 bCol = true;
1341 aCol = aBoxItem->GetBottom()->GetColor() ;
1342 aLine.SetColor(aCol);
1343 aLine.SetWidth( aBoxItem->GetBottom()->GetWidth());
1344 aLine.SetBorderLineStyle( aBoxItem->GetBottom()->GetBorderLineStyle());
1345 }
1346 else
1347 {
1348 if(aCol != aBoxItem->GetBottom()->GetColor() )
1349 bColDisable = true;
1350 if( aLine != *aBoxItem->GetBottom() )
1351 bStyleDisable = true;
1352 }
1353 }
1354
1355 if( aBoxItem->GetLeft() )
1356 {
1357 if(!bCol)
1358 {
1359 bCol = true;
1360 aCol = aBoxItem->GetLeft()->GetColor() ;
1361 aLine.SetColor(aCol);
1362 aLine.SetWidth( aBoxItem->GetLeft()->GetWidth());
1363 aLine.SetBorderLineStyle( aBoxItem->GetLeft()->GetBorderLineStyle());
1364 }
1365 else
1366 {
1367 if(aCol != aBoxItem->GetLeft()->GetColor() )
1368 bColDisable = true;
1369 if( aLine != *aBoxItem->GetLeft() )
1370 bStyleDisable = true;
1371 }
1372 }
1373
1374 if( aBoxItem->GetRight() )
1375 {
1376 if(!bCol)
1377 {
1378 bCol = true;
1379 aCol = aBoxItem->GetRight()->GetColor() ;
1380 aLine.SetColor(aCol);
1381 aLine.SetWidth( aBoxItem->GetRight()->GetWidth());
1382 aLine.SetBorderLineStyle( aBoxItem->GetRight()->GetBorderLineStyle());
1383 }
1384 else
1385 {
1386 if(aCol != aBoxItem->GetRight()->GetColor() )
1387 bColDisable = true;
1388 if( aLine != *aBoxItem->GetRight() )
1389 bStyleDisable = true;
1390 }
1391 }
1392
1393 if( aInfoItem->GetVert())
1394 {
1395 if(!bCol)
1396 {
1397 bCol = true;
1398 aCol = aInfoItem->GetVert()->GetColor() ;
1399 aLine.SetColor(aCol);
1400 aLine.SetWidth( aInfoItem->GetVert()->GetWidth());
1401 aLine.SetBorderLineStyle( aInfoItem->GetVert()->GetBorderLineStyle());
1402 }
1403 else
1404 {
1405 if(aCol != aInfoItem->GetVert()->GetColor() )
1406 bColDisable = true;
1407 if( aLine != *aInfoItem->GetVert() )
1408 bStyleDisable = true;
1409 }
1410 }
1411
1412 if( aInfoItem->GetHori())
1413 {
1414 if(!bCol)
1415 {
1416 bCol = true;
1417 aCol = aInfoItem->GetHori()->GetColor() ;
1418 aLine.SetColor(aCol);
1419 aLine.SetWidth( aInfoItem->GetHori()->GetWidth());
1420 aLine.SetBorderLineStyle( aInfoItem->GetHori()->GetBorderLineStyle());
1421 }
1422 else
1423 {
1424 if(aCol != aInfoItem->GetHori()->GetColor() )
1425 bColDisable = true;
1426 if( aLine != *aInfoItem->GetHori() )
1427 bStyleDisable = true;
1428 }
1429 }
1430
1431 if( !aInfoItem->IsValid( SvxBoxInfoItemValidFlags::VERT )
1432 || !aInfoItem->IsValid( SvxBoxInfoItemValidFlags::HORI )
1433 || !aInfoItem->IsValid( SvxBoxInfoItemValidFlags::LEFT )
1434 || !aInfoItem->IsValid( SvxBoxInfoItemValidFlags::RIGHT )
1435 || !aInfoItem->IsValid( SvxBoxInfoItemValidFlags::TOP )
1436 || !aInfoItem->IsValid( SvxBoxInfoItemValidFlags::BOTTOM ) )
1437 {
1438 bColDisable = true;
1439 bStyleDisable = true;
1440 }
1441
1442 if(SID_FRAME_LINECOLOR == nWhich)
1443 {
1444 if(bColDisable) // if different lines have different colors
1445 {
1446 aCol = COL_TRANSPARENT;
1447 rSet.Put( SvxColorItem(aCol, SID_FRAME_LINECOLOR ) );
1448 rSet.InvalidateItem(SID_FRAME_LINECOLOR);
1449 }
1450 else if (!bCol) // if no line available
1451 {
1452 aCol = COL_AUTO;
1453 rSet.Put( SvxColorItem(aCol, SID_FRAME_LINECOLOR ) );
1454 }
1455 else
1456 rSet.Put( SvxColorItem(aCol, SID_FRAME_LINECOLOR ) );
1457 }
1458 else // if( nWhich == SID_FRAME_LINESTYLE)
1459 {
1460 if(bStyleDisable) // if have several lines but don't have same style
1461 {
1462 aLine.SetWidth( 1 );
1463 SvxLineItem aItem(SID_FRAME_LINESTYLE);
1464 aItem.SetLine(&aLine);
1465 rSet.Put( aItem );
1466 rSet.InvalidateItem(SID_FRAME_LINESTYLE);
1467 }
1468 else // all the lines have same style or no line available, use initial value (0,0,0,0)
1469 {
1470 SvxLineItem aItem(SID_FRAME_LINESTYLE);
1471 aItem.SetLine(&aLine);
1472 rSet.Put( aItem );
1473 if (!aLine.GetWidth())
1474 rSet.DisableItem(SID_FRAME_LINESTYLE);
1475 }
1476 }
1477 }
1478 break;
1479 case SID_ATTR_BRUSH:
1480 {
1481 rSet.Put( rBrushItem.CloneSetWhich(GetPool().GetWhichIDFromSlotID(nWhich)) );
1482 }
1483 break;
1484 case SID_SCATTR_CELLPROTECTION:
1485 {
1486 bool bProtect = rAttrSet.Get( ATTR_PROTECTION ).GetProtection();
1487 rSet.Put( SfxBoolItem(SID_SCATTR_CELLPROTECTION, bProtect) );
1488 }
1489 break;
1490 }
1491 nWhich = aIter.NextWhich();
1492 }
1493
1494 // stuff for sidebar panels
1495 Invalidate(SID_ATTR_ALIGN_DEGREES);
1496 Invalidate(SID_ATTR_ALIGN_LOCKPOS);
1497 Invalidate(SID_ATTR_ALIGN_STACKED);
1498 }
1499
GetTextAttrState(SfxItemSet & rSet)1500 void ScFormatShell::GetTextAttrState( SfxItemSet& rSet )
1501 {
1502 ScTabViewShell* pTabViewShell = GetViewData().GetViewShell();
1503 const SfxItemSet& rAttrSet = pTabViewShell->GetSelectionPattern()->GetItemSet();
1504 rSet.Put( rAttrSet, false ); // Include ItemStates in copy
1505
1506 // choose font info according to selection script type
1507 SvtScriptType nScript = SvtScriptType::NONE; // GetSelectionScriptType never returns 0
1508 if ( rSet.GetItemState( ATTR_FONT_WEIGHT ) != SfxItemState::UNKNOWN )
1509 {
1510 nScript = pTabViewShell->GetSelectionScriptType();
1511 ScViewUtil::PutItemScript( rSet, rAttrSet, ATTR_FONT_WEIGHT, nScript );
1512 }
1513 if ( rSet.GetItemState( ATTR_FONT_POSTURE ) != SfxItemState::UNKNOWN )
1514 {
1515 if (nScript == SvtScriptType::NONE) nScript = pTabViewShell->GetSelectionScriptType();
1516 ScViewUtil::PutItemScript( rSet, rAttrSet, ATTR_FONT_POSTURE, nScript );
1517 }
1518
1519 SfxItemState eState;
1520
1521 // own control on radio button functionality:
1522
1523 // underline
1524
1525 eState = rAttrSet.GetItemState( ATTR_FONT_UNDERLINE );
1526 if ( eState == SfxItemState::INVALID )
1527 {
1528 rSet.InvalidateItem( SID_ULINE_VAL_NONE );
1529 rSet.InvalidateItem( SID_ULINE_VAL_SINGLE );
1530 rSet.InvalidateItem( SID_ULINE_VAL_DOUBLE );
1531 rSet.InvalidateItem( SID_ULINE_VAL_DOTTED );
1532 }
1533 else
1534 {
1535 FontLineStyle eUnderline =
1536 rAttrSet.Get(ATTR_FONT_UNDERLINE).GetLineStyle();
1537 rSet.Put(SfxBoolItem(SID_ULINE_VAL_SINGLE, eUnderline == LINESTYLE_SINGLE));
1538 rSet.Put(SfxBoolItem(SID_ULINE_VAL_DOUBLE, eUnderline == LINESTYLE_DOUBLE));
1539 rSet.Put(SfxBoolItem(SID_ULINE_VAL_DOTTED, eUnderline == LINESTYLE_DOTTED));
1540 rSet.Put(SfxBoolItem(SID_ULINE_VAL_NONE, eUnderline == LINESTYLE_NONE));
1541 }
1542
1543 // horizontal alignment
1544
1545 const SvxHorJustifyItem* pHorJustify = nullptr;
1546 const SvxVerJustifyItem* pVerJustify = nullptr;
1547 SvxCellVerJustify eVerJustify = SvxCellVerJustify::Standard;
1548 sal_uInt16 nWhich = 0;
1549 bool bJustifyStd = false;
1550 SfxBoolItem aBoolItem ( 0, true );
1551
1552 eState = rAttrSet.GetItemState( ATTR_HOR_JUSTIFY, true,
1553 reinterpret_cast<const SfxPoolItem**>(&pHorJustify) );
1554 switch ( eState )
1555 {
1556 case SfxItemState::SET:
1557 {
1558 switch ( pHorJustify->GetValue() )
1559 {
1560 case SvxCellHorJustify::Standard:
1561 break;
1562
1563 case SvxCellHorJustify::Left:
1564 nWhich = SID_ALIGNLEFT;
1565 break;
1566
1567 case SvxCellHorJustify::Right:
1568 nWhich = SID_ALIGNRIGHT;
1569 break;
1570
1571 case SvxCellHorJustify::Center:
1572 nWhich = SID_ALIGNCENTERHOR;
1573 break;
1574
1575 case SvxCellHorJustify::Block:
1576 nWhich = SID_ALIGNBLOCK;
1577 break;
1578
1579 case SvxCellHorJustify::Repeat:
1580 default:
1581 bJustifyStd = true;
1582 break;
1583 }
1584 }
1585 break;
1586
1587 case SfxItemState::INVALID:
1588 rSet.InvalidateItem( SID_ALIGNLEFT );
1589 rSet.InvalidateItem( SID_ALIGNRIGHT );
1590 rSet.InvalidateItem( SID_ALIGNCENTERHOR );
1591 rSet.InvalidateItem( SID_ALIGNBLOCK );
1592 break;
1593
1594 default:
1595 bJustifyStd = true;
1596 break;
1597 }
1598
1599 if ( nWhich )
1600 {
1601 aBoolItem.SetWhich( nWhich );
1602 rSet.Put( aBoolItem );
1603 }
1604 else if ( bJustifyStd )
1605 {
1606 aBoolItem.SetValue( false );
1607 aBoolItem.SetWhich( SID_ALIGNLEFT ); rSet.Put( aBoolItem );
1608 aBoolItem.SetWhich( SID_ALIGNRIGHT ); rSet.Put( aBoolItem );
1609 aBoolItem.SetWhich( SID_ALIGNCENTERHOR ); rSet.Put( aBoolItem );
1610 aBoolItem.SetWhich( SID_ALIGNBLOCK ); rSet.Put( aBoolItem );
1611 bJustifyStd = false;
1612 }
1613
1614 // vertical alignment
1615
1616 nWhich = 0;
1617 aBoolItem.SetValue( true );
1618
1619 eState = rAttrSet.GetItemState( ATTR_VER_JUSTIFY, true,
1620 reinterpret_cast<const SfxPoolItem**>(&pVerJustify) );
1621
1622 switch ( eState )
1623 {
1624 case SfxItemState::SET:
1625 {
1626 eVerJustify = pVerJustify->GetValue();
1627
1628 switch ( eVerJustify )
1629 {
1630 case SvxCellVerJustify::Top:
1631 nWhich = SID_ALIGNTOP;
1632 break;
1633
1634 case SvxCellVerJustify::Bottom:
1635 nWhich = SID_ALIGNBOTTOM;
1636 break;
1637
1638 case SvxCellVerJustify::Center:
1639 nWhich = SID_ALIGNCENTERVER;
1640 break;
1641
1642 case SvxCellVerJustify::Standard:
1643 default:
1644 bJustifyStd = true;
1645 break;
1646 }
1647 }
1648 break;
1649
1650 case SfxItemState::INVALID:
1651 rSet.InvalidateItem( SID_ALIGNTOP );
1652 rSet.InvalidateItem( SID_ALIGNBOTTOM );
1653 rSet.InvalidateItem( SID_ALIGNCENTERVER );
1654 break;
1655
1656 default:
1657 bJustifyStd = true;
1658 break;
1659 }
1660
1661 if ( nWhich )
1662 {
1663 aBoolItem.SetWhich( nWhich );
1664 rSet.Put( aBoolItem );
1665 }
1666 else if ( bJustifyStd )
1667 {
1668 aBoolItem.SetValue( false );
1669 aBoolItem.SetWhich( SID_ALIGNTOP ); rSet.Put( aBoolItem );
1670 aBoolItem.SetWhich( SID_ALIGNBOTTOM ); rSet.Put( aBoolItem );
1671 aBoolItem.SetWhich( SID_ALIGNCENTERVER ); rSet.Put( aBoolItem );
1672 }
1673 }
1674
GetBorderState(SfxItemSet & rSet)1675 void ScFormatShell::GetBorderState( SfxItemSet& rSet )
1676 {
1677 ScTabViewShell* pTabViewShell = GetViewData().GetViewShell();
1678 std::shared_ptr<SvxBoxItem> aBoxItem(std::make_shared<SvxBoxItem>(ATTR_BORDER));
1679 std::shared_ptr<SvxBoxInfoItem> aInfoItem(std::make_shared<SvxBoxInfoItem>(ATTR_BORDER_INNER));
1680
1681 pTabViewShell->GetSelectionFrame( aBoxItem, aInfoItem );
1682
1683 if ( rSet.GetItemState( ATTR_BORDER ) != SfxItemState::UNKNOWN )
1684 rSet.Put( *aBoxItem );
1685 if ( rSet.GetItemState( ATTR_BORDER_INNER ) != SfxItemState::UNKNOWN )
1686 rSet.Put( *aInfoItem );
1687 }
1688
GetAlignState(SfxItemSet & rSet)1689 void ScFormatShell::GetAlignState( SfxItemSet& rSet )
1690 {
1691 ScTabViewShell* pTabViewShell = GetViewData().GetViewShell();
1692 const SfxItemSet& rAttrSet = pTabViewShell->GetSelectionPattern()->GetItemSet();
1693 SfxWhichIter aIter(rSet);
1694 sal_uInt16 nWhich = aIter.FirstWhich();
1695
1696 SvxCellHorJustify eHAlign = SvxCellHorJustify::Standard;
1697 bool bHasHAlign = rAttrSet.GetItemState( ATTR_HOR_JUSTIFY ) != SfxItemState::INVALID;
1698 if( bHasHAlign )
1699 eHAlign = rAttrSet.Get( ATTR_HOR_JUSTIFY ).GetValue();
1700
1701 SvxCellVerJustify eVAlign = SvxCellVerJustify::Standard;
1702 bool bHasVAlign = rAttrSet.GetItemState( ATTR_VER_JUSTIFY ) != SfxItemState::INVALID;
1703 if( bHasVAlign )
1704 eVAlign = rAttrSet.Get( ATTR_VER_JUSTIFY ).GetValue();
1705
1706 while ( nWhich )
1707 {
1708 switch ( nWhich )
1709 {
1710 case SID_H_ALIGNCELL:
1711 if ( bHasHAlign )
1712 rSet.Put( SvxHorJustifyItem( eHAlign, nWhich ));
1713 break;
1714 case SID_V_ALIGNCELL:
1715 if ( bHasVAlign )
1716 rSet.Put( SvxVerJustifyItem( eVAlign, nWhich ));
1717 break;
1718
1719 // pseudo slots for Format menu
1720 case SID_ALIGN_ANY_HDEFAULT:
1721 case SID_ALIGN_ANY_LEFT:
1722 case SID_ALIGN_ANY_HCENTER:
1723 case SID_ALIGN_ANY_RIGHT:
1724 case SID_ALIGN_ANY_JUSTIFIED:
1725 rSet.Put( SfxBoolItem( nWhich, bHasHAlign && (eHAlign == lclConvertSlotToHAlign( nWhich )) ) );
1726 break;
1727 case SID_ALIGN_ANY_VDEFAULT:
1728 case SID_ALIGN_ANY_TOP:
1729 case SID_ALIGN_ANY_VCENTER:
1730 case SID_ALIGN_ANY_BOTTOM:
1731 rSet.Put( SfxBoolItem( nWhich, bHasVAlign && (eVAlign == lclConvertSlotToVAlign( nWhich )) ) );
1732 break;
1733 }
1734 nWhich = aIter.NextWhich();
1735 }
1736 }
1737
GetNumFormatState(SfxItemSet & rSet)1738 void ScFormatShell::GetNumFormatState( SfxItemSet& rSet )
1739 {
1740 ScTabViewShell* pTabViewShell = GetViewData().GetViewShell();
1741 ScDocument& rDoc = rViewData.GetDocument();
1742 const SfxItemSet& rAttrSet = pTabViewShell->GetSelectionPattern()->GetItemSet();
1743 const SfxItemState eItemState = rAttrSet.GetItemState( ATTR_VALUE_FORMAT );
1744 sal_uInt32 nNumberFormat = rAttrSet.Get(ATTR_VALUE_FORMAT).GetValue();
1745 SvNumberFormatter* pFormatter = rDoc.GetFormatTable();
1746 // If item state is default or set it
1747 // indicates one number format so we
1748 // don't have to iterate over all
1749 // selected cells' attribute ranges to
1750 // determine selected types.
1751 // Does *NOT* include the
1752 // SvNumFormatType::DEFINED bit.
1753 const SvNumFormatType nType = (eItemState >= SfxItemState::DEFAULT ? pFormatter->GetType( nNumberFormat) :
1754 GetCurrentNumberFormatType());
1755 NfIndexTableOffset nOffset = SvNumberFormatter::GetIndexTableOffset(nNumberFormat);
1756
1757 SfxWhichIter aIter(rSet);
1758 sal_uInt16 nWhich = aIter.FirstWhich();
1759
1760 while ( nWhich )
1761 {
1762 switch ( nWhich )
1763 {
1764 case SID_NUMBER_THOUSANDS:
1765 {
1766 bool bEnable = (SfxItemState::INVALID != eItemState);
1767 if (bEnable)
1768 {
1769 bEnable = ((nType != SvNumFormatType::ALL) && (nType &
1770 (SvNumFormatType::NUMBER |
1771 SvNumFormatType::PERCENT |
1772 SvNumFormatType::CURRENCY |
1773 SvNumFormatType::FRACTION)));
1774 if (bEnable)
1775 {
1776 bool bThousand( false );
1777 bool bNegRed( false );
1778 sal_uInt16 nPrecision( 0 );
1779 sal_uInt16 nLeadZeroes( 0 );
1780 pFormatter->GetFormatSpecialInfo( nNumberFormat, bThousand, bNegRed, nPrecision, nLeadZeroes);
1781 rSet.Put( SfxBoolItem( nWhich, bThousand));
1782 }
1783 }
1784 if (!bEnable)
1785 {
1786 rSet.DisableItem( nWhich );
1787 }
1788 }
1789 break;
1790 case SID_NUMBER_FORMAT:
1791 // symphony version with format interpretation
1792 {
1793 if(SfxItemState::INVALID != eItemState)
1794 {
1795 bool bThousand(false);
1796 bool bNegRed(false);
1797 sal_uInt16 nPrecision(0);
1798 sal_uInt16 nLeadZeroes(0);
1799
1800 pFormatter->GetFormatSpecialInfo(nNumberFormat,bThousand, bNegRed, nPrecision, nLeadZeroes);
1801
1802 const SvNumberformat* pFormatEntry = pFormatter->GetEntry( nNumberFormat );
1803 if (pFormatEntry && (pFormatEntry->GetType() & SvNumFormatType::SCIENTIFIC))
1804 {
1805 // if scientific, bThousand is used for engineering notation
1806 const sal_uInt16 nIntegerDigits = pFormatEntry->GetFormatIntegerDigits();
1807 bThousand = nIntegerDigits > 0 && ((nIntegerDigits % 3) == 0);
1808 }
1809 OUString aFormat;
1810 static constexpr OUString sBreak = u","_ustr;
1811 const OUString sThousand = OUString::number(static_cast<sal_Int32>(bThousand));
1812 const OUString sNegRed = OUString::number(static_cast<sal_Int32>(bNegRed));
1813 const OUString sPrecision = OUString::number(nPrecision);
1814 const OUString sLeadZeroes = OUString::number(nLeadZeroes);
1815 const OUString sNatNum12 = OUString::number( static_cast< sal_Int32 >( pFormatter->IsNatNum12( nNumberFormat ) ) );
1816
1817 aFormat += sThousand +
1818 sBreak +
1819 sNegRed +
1820 sBreak +
1821 sPrecision +
1822 sBreak +
1823 sLeadZeroes +
1824 sBreak +
1825 sNatNum12 +
1826 sBreak;
1827
1828 rSet.Put(SfxStringItem(nWhich, aFormat));
1829
1830 if (comphelper::LibreOfficeKit::isActive())
1831 {
1832 OUString sPayload = ".uno:NumberFormat=" + aFormat;
1833 GetViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_STATE_CHANGED,
1834 OUStringToOString(sPayload, RTL_TEXTENCODING_ASCII_US));
1835 }
1836 }
1837 else
1838 {
1839 rSet.InvalidateItem( nWhich );
1840 }
1841 }
1842 break;
1843
1844 case SID_NUMBER_TYPE_FORMAT:
1845 {
1846 sal_Int16 nFormatCategory = -1;
1847 if ( eItemState >= SfxItemState::DEFAULT ) //Modify for more robust
1848 {
1849 switch(nType)
1850 {
1851 case SvNumFormatType::NUMBER:
1852 // Determine if General format.
1853 if ((nNumberFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0)
1854 nFormatCategory = 0;
1855 else
1856 nFormatCategory = 1;
1857 break;
1858 case SvNumFormatType::PERCENT:
1859 nFormatCategory = 2;
1860 break;
1861 case SvNumFormatType::CURRENCY:
1862 nFormatCategory = 3;
1863 break;
1864 case SvNumFormatType::DATE:
1865 //Add
1866 case SvNumFormatType::DATETIME:
1867 nFormatCategory = 4;
1868 break;
1869 case SvNumFormatType::TIME:
1870 nFormatCategory = 5;
1871 break;
1872 case SvNumFormatType::SCIENTIFIC:
1873 nFormatCategory = 6;
1874 break;
1875 case SvNumFormatType::FRACTION:
1876 nFormatCategory = 7;
1877 break;
1878 case SvNumFormatType::LOGICAL:
1879 nFormatCategory = 8;
1880 break;
1881 case SvNumFormatType::TEXT:
1882 nFormatCategory = 9;
1883 break;
1884 default:
1885 nFormatCategory = -1; //for more robust
1886 }
1887 if( nFormatCategory == -1 )
1888 rSet.InvalidateItem( nWhich );
1889 else
1890 rSet.Put( SfxUInt16Item( nWhich, nFormatCategory ) );
1891 }
1892 else
1893 {
1894 rSet.InvalidateItem( nWhich );
1895 }
1896
1897 }
1898 break;
1899 case SID_NUMBER_CURRENCY:
1900 rSet.Put( SfxBoolItem(nWhich, bool(nType & SvNumFormatType::CURRENCY)) );
1901 break;
1902 case SID_NUMBER_SCIENTIFIC:
1903 rSet.Put( SfxBoolItem(nWhich, bool(nType & SvNumFormatType::SCIENTIFIC)) );
1904 break;
1905 case SID_NUMBER_DATE:
1906 rSet.Put( SfxBoolItem(nWhich, bool(nType & SvNumFormatType::DATE)) );
1907 break;
1908 case SID_NUMBER_PERCENT:
1909 rSet.Put( SfxBoolItem(nWhich, bool(nType & SvNumFormatType::PERCENT)) );
1910 break;
1911 case SID_NUMBER_TIME:
1912 rSet.Put( SfxBoolItem(nWhich, bool(nType & SvNumFormatType::TIME)) );
1913 break;
1914 case SID_NUMBER_TWODEC:
1915 rSet.Put( SfxBoolItem(nWhich, (nType & SvNumFormatType::NUMBER) && nOffset == NF_NUMBER_1000DEC2 ) );
1916 break;
1917 case SID_NUMBER_STANDARD:
1918 rSet.Put( SfxBoolItem(nWhich, (nType & SvNumFormatType::NUMBER) && (nNumberFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0) );
1919 break;
1920 }
1921 nWhich = aIter.NextWhich();
1922 }
1923 }
1924
ExecuteTextDirection(const SfxRequest & rReq)1925 void ScFormatShell::ExecuteTextDirection( const SfxRequest& rReq )
1926 {
1927 ScTabViewShell* pTabViewShell = GetViewData().GetViewShell();
1928 pTabViewShell->HideListBox(); // Autofilter-DropDown-Listbox
1929 bool bEditMode = false;
1930 if ( GetViewData().HasEditView( GetViewData().GetActivePart() ) )
1931 {
1932 bEditMode=true;
1933 ScModule::get()->InputEnterHandler();
1934 pTabViewShell->UpdateInputHandler();
1935 }
1936 sal_uInt16 nSlot = rReq.GetSlot();
1937 switch( nSlot )
1938 {
1939 case SID_TEXTDIRECTION_LEFT_TO_RIGHT:
1940 case SID_TEXTDIRECTION_TOP_TO_BOTTOM:
1941 {
1942 bool bVert = (nSlot == SID_TEXTDIRECTION_TOP_TO_BOTTOM);
1943 ScPatternAttr aAttr(GetViewData().GetDocument().getCellAttributeHelper());
1944 aAttr.ItemSetPut(ScVerticalStackCell(bVert));
1945 aAttr.ItemSetPut(SfxBoolItem(ATTR_VERTICAL_ASIAN, bVert));
1946 pTabViewShell->ApplySelectionPattern( aAttr );
1947 pTabViewShell->AdjustBlockHeight();
1948 }
1949 break;
1950
1951 case SID_ATTR_PARA_LEFT_TO_RIGHT:
1952 case SID_ATTR_PARA_RIGHT_TO_LEFT:
1953 {
1954 SvxFrameDirection eDirection = ( nSlot == SID_ATTR_PARA_LEFT_TO_RIGHT ) ?
1955 SvxFrameDirection::Horizontal_LR_TB : SvxFrameDirection::Horizontal_RL_TB;
1956 pTabViewShell->ApplyAttr( SvxFrameDirectionItem( eDirection, ATTR_WRITINGDIR ) );
1957 }
1958 break;
1959 }
1960 if (bEditMode)
1961 ScModule::get()->SetInputMode(SC_INPUT_TABLE);
1962 }
1963
GetTextDirectionState(SfxItemSet & rSet)1964 void ScFormatShell::GetTextDirectionState( SfxItemSet& rSet )
1965 {
1966 ScTabViewShell* pTabViewShell = GetViewData().GetViewShell();
1967 const SfxItemSet& rAttrSet = pTabViewShell->GetSelectionPattern()->GetItemSet();
1968
1969 bool bVertDontCare =
1970 (rAttrSet.GetItemState( ATTR_VERTICAL_ASIAN ) == SfxItemState::INVALID) ||
1971 (rAttrSet.GetItemState( ATTR_STACKED ) == SfxItemState::INVALID);
1972 bool bLeftRight = !bVertDontCare &&
1973 !rAttrSet.Get( ATTR_STACKED ).GetValue();
1974 bool bTopBottom = !bVertDontCare && !bLeftRight &&
1975 rAttrSet.Get( ATTR_VERTICAL_ASIAN ).GetValue();
1976
1977 bool bBidiDontCare = (rAttrSet.GetItemState( ATTR_WRITINGDIR ) == SfxItemState::INVALID);
1978 EEHorizontalTextDirection eBidiDir = EEHorizontalTextDirection::Default;
1979 if ( !bBidiDontCare )
1980 {
1981 SvxFrameDirection eCellDir = rAttrSet.Get( ATTR_WRITINGDIR ).GetValue();
1982 if ( eCellDir == SvxFrameDirection::Environment )
1983 eBidiDir = GetViewData().GetDocument().
1984 GetEditTextDirection( GetViewData().GetTabNo() );
1985 else if ( eCellDir == SvxFrameDirection::Horizontal_RL_TB )
1986 eBidiDir = EEHorizontalTextDirection::R2L;
1987 else
1988 eBidiDir = EEHorizontalTextDirection::L2R;
1989 }
1990
1991 bool bDisableCTLFont = !SvtCTLOptions::IsCTLFontEnabled();
1992 bool bDisableVerticalText = !SvtCJKOptions::IsVerticalTextEnabled();
1993
1994 SfxWhichIter aIter( rSet );
1995 sal_uInt16 nWhich = aIter.FirstWhich();
1996 while( nWhich )
1997 {
1998 switch( nWhich )
1999 {
2000 case SID_TEXTDIRECTION_LEFT_TO_RIGHT:
2001 case SID_TEXTDIRECTION_TOP_TO_BOTTOM:
2002 if ( bDisableVerticalText )
2003 rSet.DisableItem( nWhich );
2004 else
2005 {
2006 if( bVertDontCare )
2007 rSet.InvalidateItem( nWhich );
2008 else if ( nWhich == SID_TEXTDIRECTION_LEFT_TO_RIGHT )
2009 rSet.Put( SfxBoolItem( nWhich, bLeftRight ) );
2010 else
2011 rSet.Put( SfxBoolItem( nWhich, bTopBottom ) );
2012 }
2013 break;
2014
2015 case SID_ATTR_PARA_LEFT_TO_RIGHT:
2016 case SID_ATTR_PARA_RIGHT_TO_LEFT:
2017 if ( bDisableCTLFont )
2018 rSet.DisableItem( nWhich );
2019 else
2020 {
2021 if ( bTopBottom )
2022 rSet.DisableItem( nWhich );
2023 else if ( bBidiDontCare )
2024 rSet.InvalidateItem( nWhich );
2025 else if ( nWhich == SID_ATTR_PARA_LEFT_TO_RIGHT )
2026 rSet.Put( SfxBoolItem( nWhich, eBidiDir == EEHorizontalTextDirection::L2R ) );
2027 else
2028 rSet.Put( SfxBoolItem( nWhich, eBidiDir == EEHorizontalTextDirection::R2L ) );
2029 }
2030 }
2031 nWhich = aIter.NextWhich();
2032 }
2033 }
2034
ExecFormatPaintbrush(const SfxRequest & rReq)2035 void ScFormatShell::ExecFormatPaintbrush( const SfxRequest& rReq )
2036 {
2037 ScViewFunc* pView = rViewData.GetView();
2038 if ( pView->HasPaintBrush() )
2039 {
2040 // cancel paintbrush mode
2041 pView->ResetBrushDocument();
2042 }
2043 else
2044 {
2045 bool bLock = false;
2046 const SfxItemSet *pArgs = rReq.GetArgs();
2047 if( pArgs && pArgs->Count() >= 1 )
2048 bLock = pArgs->Get(SID_FORMATPAINTBRUSH).GetValue();
2049
2050 // in case of multi selection, deselect all and use the cursor position
2051 ScRange aDummy;
2052 if ( rViewData.GetSimpleArea(aDummy) != SC_MARK_SIMPLE )
2053 pView->Unmark();
2054
2055 ScDocumentUniquePtr pBrushDoc(new ScDocument( SCDOCMODE_CLIP ));
2056 pView->CopyToClip( pBrushDoc.get(), false, true );
2057 pView->SetBrushDocument( std::move(pBrushDoc), bLock );
2058 }
2059 }
2060
StateFormatPaintbrush(SfxItemSet & rSet)2061 void ScFormatShell::StateFormatPaintbrush( SfxItemSet& rSet )
2062 {
2063 if ( rViewData.HasEditView( rViewData.GetActivePart() ) )
2064 rSet.DisableItem( SID_FORMATPAINTBRUSH );
2065 else
2066 rSet.Put( SfxBoolItem( SID_FORMATPAINTBRUSH, rViewData.GetView()->HasPaintBrush() ) );
2067 }
2068
GetCurrentNumberFormatType()2069 SvNumFormatType ScFormatShell::GetCurrentNumberFormatType()
2070 {
2071 SvNumFormatType nType = SvNumFormatType::ALL;
2072 ScDocument& rDoc = GetViewData().GetDocument();
2073 ScMarkData aMark(GetViewData().GetMarkData());
2074 const SvNumberFormatter* pFormatter = rDoc.GetFormatTable();
2075 if (!pFormatter)
2076 return nType;
2077
2078 // TODO: Find out how to get a selected table range in case multiple tables
2079 // are selected. Currently we only check for the current active table.
2080
2081 if ( aMark.IsMarked() || aMark.IsMultiMarked() )
2082 {
2083 aMark.MarkToMulti();
2084 const ScRange& aRange = aMark.GetMultiMarkArea();
2085 const ScMultiSel& rMultiSel = aMark.GetMultiSelData();
2086
2087 SvNumFormatType nComboType = SvNumFormatType::ALL;
2088 bool bFirstItem = true;
2089 for (SCCOL nCol = aRange.aStart.Col(); nCol <= aRange.aEnd.Col(); ++nCol)
2090 {
2091 if (!rMultiSel.HasMarks(nCol))
2092 continue;
2093
2094 SCROW nRow1, nRow2;
2095 ScMultiSelIter aMultiIter(rMultiSel, nCol);
2096 while (aMultiIter.Next(nRow1, nRow2))
2097 {
2098 ScRange aColRange(nCol, nRow1, aRange.aStart.Tab());
2099 aColRange.aEnd.SetRow(nRow2);
2100 sal_uInt32 nNumFmt = rDoc.GetNumberFormat(aColRange);
2101 SvNumFormatType nThisType = pFormatter->GetType(nNumFmt);
2102 if (bFirstItem)
2103 {
2104 bFirstItem = false;
2105 nComboType = nThisType;
2106 }
2107 else if (nComboType != nThisType)
2108 // mixed number format type.
2109 return SvNumFormatType::ALL;
2110 }
2111 }
2112 nType = nComboType;
2113 }
2114 else
2115 {
2116 sal_uInt32 nNumFmt = rDoc.GetNumberFormat( rViewData.GetCurX(), rViewData.GetCurY(),
2117 rViewData.GetTabNo());
2118 nType = pFormatter->GetType( nNumFmt );
2119 }
2120 return nType;
2121 }
2122
2123 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
2124