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
21 #include <com/sun/star/drawing/BitmapMode.hpp>
22 #include <com/sun/star/style/XStyle.hpp>
23 #include <com/sun/star/text/WritingMode.hpp>
24 #include <com/sun/star/table/TableBorder.hpp>
25 #include <com/sun/star/table/BorderLine2.hpp>
26 #include <com/sun/star/lang/Locale.hpp>
27
28 #include <comphelper/sequence.hxx>
29 #include <cppuhelper/supportsservice.hxx>
30 #include <cppuhelper/typeprovider.hxx>
31 #include <o3tl/any.hxx>
32 #include <svl/style.hxx>
33 #include <svl/itemset.hxx>
34
35 #include <vcl/svapp.hxx>
36 #include <libxml/xmlwriter.h>
37
38 #include <sdr/properties/textproperties.hxx>
39 #include <editeng/outlobj.hxx>
40 #include <editeng/writingmodeitem.hxx>
41 #include <svx/svdotable.hxx>
42 #include <svx/svdoutl.hxx>
43 #include <svx/unoshtxt.hxx>
44 #include <svx/svdmodel.hxx>
45 #include <svx/sdooitm.hxx>
46 #include <svx/sdtagitm.hxx>
47 #include <svx/sdmetitm.hxx>
48 #include <svx/xit.hxx>
49 #include <getallcharpropids.hxx>
50 #include "tableundo.hxx"
51 #include <cell.hxx>
52 #include <svx/unoshprp.hxx>
53 #include <svx/unoshape.hxx>
54 #include <editeng/editobj.hxx>
55 #include <editeng/borderline.hxx>
56 #include <editeng/boxitem.hxx>
57 #include <editeng/charrotateitem.hxx>
58 #include <svx/xflbstit.hxx>
59 #include <svx/xflbmtit.hxx>
60 #include <svx/svdpool.hxx>
61
62
63 using ::editeng::SvxBorderLine;
64 using namespace ::com::sun::star::uno;
65 using namespace ::com::sun::star::beans;
66 using namespace ::com::sun::star::lang;
67 using namespace ::com::sun::star::text;
68 using namespace ::com::sun::star::table;
69 using namespace ::com::sun::star::drawing;
70 using namespace ::com::sun::star::style;
71 using namespace ::com::sun::star::container;
72
73
ImplGetSvxCellPropertySet()74 static const SvxItemPropertySet* ImplGetSvxCellPropertySet()
75 {
76 // property map for an outliner text
77 static const SfxItemPropertyMapEntry aSvxCellPropertyMap[] =
78 {
79 FILL_PROPERTIES
80 // { "HasLevels", OWN_ATTR_HASLEVELS, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::READONLY, 0},
81 { OUString("Style"), OWN_ATTR_STYLE, cppu::UnoType< css::style::XStyle >::get(), css::beans::PropertyAttribute::MAYBEVOID, 0},
82 { OUString(UNO_NAME_TEXT_WRITINGMODE), SDRATTR_TEXTDIRECTION, cppu::UnoType<css::text::WritingMode>::get(), 0, 0},
83 { OUString(UNO_NAME_TEXT_HORZADJUST), SDRATTR_TEXT_HORZADJUST, cppu::UnoType<css::drawing::TextHorizontalAdjust>::get(), 0, 0},
84 { OUString(UNO_NAME_TEXT_LEFTDIST), SDRATTR_TEXT_LEFTDIST, cppu::UnoType<sal_Int32>::get(), 0, 0, PropertyMoreFlags::METRIC_ITEM},
85 { OUString(UNO_NAME_TEXT_LOWERDIST), SDRATTR_TEXT_LOWERDIST, cppu::UnoType<sal_Int32>::get(), 0, 0, PropertyMoreFlags::METRIC_ITEM},
86 { OUString(UNO_NAME_TEXT_RIGHTDIST), SDRATTR_TEXT_RIGHTDIST, cppu::UnoType<sal_Int32>::get(), 0, 0, PropertyMoreFlags::METRIC_ITEM},
87 { OUString(UNO_NAME_TEXT_UPPERDIST), SDRATTR_TEXT_UPPERDIST, cppu::UnoType<sal_Int32>::get(), 0, 0, PropertyMoreFlags::METRIC_ITEM},
88 { OUString(UNO_NAME_TEXT_VERTADJUST), SDRATTR_TEXT_VERTADJUST, cppu::UnoType<css::drawing::TextVerticalAdjust>::get(), 0, 0},
89 { OUString(UNO_NAME_TEXT_WORDWRAP), SDRATTR_TEXT_WORDWRAP, cppu::UnoType<bool>::get(), 0, 0},
90
91 { OUString("TableBorder"), OWN_ATTR_TABLEBORDER, cppu::UnoType<TableBorder>::get(), 0, 0 },
92 { OUString("TopBorder"), SDRATTR_TABLE_BORDER, cppu::UnoType<BorderLine>::get(), 0, TOP_BORDER },
93 { OUString("BottomBorder"), SDRATTR_TABLE_BORDER, cppu::UnoType<BorderLine>::get(), 0, BOTTOM_BORDER },
94 { OUString("LeftBorder"), SDRATTR_TABLE_BORDER, cppu::UnoType<BorderLine>::get(), 0, LEFT_BORDER },
95 { OUString("RightBorder"), SDRATTR_TABLE_BORDER, cppu::UnoType<BorderLine>::get(), 0, RIGHT_BORDER },
96 { OUString("RotateAngle"), SDRATTR_TABLE_TEXT_ROTATION, cppu::UnoType<sal_Int32>::get(), 0, 0 },
97
98 SVX_UNOEDIT_OUTLINER_PROPERTIES,
99 SVX_UNOEDIT_CHAR_PROPERTIES,
100 SVX_UNOEDIT_PARA_PROPERTIES,
101 { OUString(), 0, css::uno::Type(), 0, 0 }
102 };
103
104 static SvxItemPropertySet aSvxCellPropertySet( aSvxCellPropertyMap, SdrObject::GetGlobalDrawObjectItemPool() );
105 return &aSvxCellPropertySet;
106 }
107
108 namespace
109 {
110
111 class CellTextProvider : public svx::ITextProvider
112 {
113 public:
114 explicit CellTextProvider(const sdr::table::CellRef& rCell);
115 virtual ~CellTextProvider();
116
117 private:
118 virtual sal_Int32 getTextCount() const override;
119 virtual SdrText* getText(sal_Int32 nIndex) const override;
120
121 private:
122 const sdr::table::CellRef m_xCell;
123 };
124
CellTextProvider(const sdr::table::CellRef & rCell)125 CellTextProvider::CellTextProvider(const sdr::table::CellRef& rCell)
126 : m_xCell(rCell)
127 {
128 }
129
~CellTextProvider()130 CellTextProvider::~CellTextProvider()
131 {
132 }
133
getTextCount() const134 sal_Int32 CellTextProvider::getTextCount() const
135 {
136 return 1;
137 }
138
getText(sal_Int32 nIndex) const139 SdrText* CellTextProvider::getText(sal_Int32 nIndex) const
140 {
141 (void) nIndex;
142 assert(nIndex == 0);
143 return m_xCell.get();
144 }
145
146 }
147
148 namespace sdr
149 {
150 namespace properties
151 {
152 class CellProperties : public TextProperties
153 {
154 protected:
155 // create a new itemset
156 std::unique_ptr<SfxItemSet> CreateObjectSpecificItemSet(SfxItemPool& rPool) override;
157
158 const svx::ITextProvider& getTextProvider() const override;
159
160 public:
161 // basic constructor
162 CellProperties(SdrObject& rObj, sdr::table::Cell* pCell );
163
164 // constructor for copying, but using new object
165 CellProperties(const CellProperties& rProps, SdrObject& rObj, sdr::table::Cell* pCell);
166
167 // Clone() operator, normally just calls the local copy constructor
168 std::unique_ptr<BaseProperties> Clone(SdrObject& rObj) const override;
169
170 void ForceDefaultAttributes() override;
171
172 void ItemSetChanged(const SfxItemSet& rSet) override;
173
174 void ItemChange(const sal_uInt16 nWhich, const SfxPoolItem* pNewItem = nullptr) override;
175
176 sdr::table::CellRef mxCell;
177
178 private:
179 const CellTextProvider maTextProvider;
180 };
181
182 // create a new itemset
CreateObjectSpecificItemSet(SfxItemPool & rPool)183 std::unique_ptr<SfxItemSet> CellProperties::CreateObjectSpecificItemSet(SfxItemPool& rPool)
184 {
185 return std::make_unique<SfxItemSet>(rPool,
186
187 // range from SdrAttrObj
188 svl::Items<SDRATTR_START, SDRATTR_SHADOW_LAST,
189 SDRATTR_MISC_FIRST, SDRATTR_MISC_LAST,
190 SDRATTR_TEXTDIRECTION, SDRATTR_TEXTDIRECTION,
191
192 // range for SdrTableObj
193 SDRATTR_TABLE_FIRST, SDRATTR_TABLE_LAST,
194
195 // range from SdrTextObj
196 EE_ITEMS_START, EE_ITEMS_END>{});
197 }
198
getTextProvider() const199 const svx::ITextProvider& CellProperties::getTextProvider() const
200 {
201 return maTextProvider;
202 }
203
CellProperties(SdrObject & rObj,sdr::table::Cell * pCell)204 CellProperties::CellProperties(SdrObject& rObj, sdr::table::Cell* pCell)
205 : TextProperties(rObj)
206 , mxCell(pCell)
207 , maTextProvider(mxCell)
208 {
209 }
210
CellProperties(const CellProperties & rProps,SdrObject & rObj,sdr::table::Cell * pCell)211 CellProperties::CellProperties(const CellProperties& rProps, SdrObject& rObj, sdr::table::Cell* pCell)
212 : TextProperties(rProps, rObj)
213 , mxCell( pCell )
214 , maTextProvider(mxCell)
215 {
216 }
217
Clone(SdrObject & rObj) const218 std::unique_ptr<BaseProperties> CellProperties::Clone(SdrObject& rObj) const
219 {
220 OSL_FAIL("CellProperties::Clone(), does not work yet!");
221 return std::unique_ptr<BaseProperties>(new CellProperties(*this, rObj,nullptr));
222 }
223
ForceDefaultAttributes()224 void CellProperties::ForceDefaultAttributes()
225 {
226 }
227
ItemSetChanged(const SfxItemSet & rSet)228 void CellProperties::ItemSetChanged(const SfxItemSet& rSet )
229 {
230 SdrTextObj& rObj = static_cast<SdrTextObj&>(GetSdrObject());
231
232 if( mxCell.is() )
233 {
234 OutlinerParaObject* pParaObj = mxCell->CreateEditOutlinerParaObject().release();
235
236 const bool bOwnParaObj = pParaObj != nullptr;
237
238 if( pParaObj == nullptr )
239 pParaObj = mxCell->GetOutlinerParaObject();
240
241 if(pParaObj)
242 {
243 // handle outliner attributes
244 Outliner* pOutliner = nullptr;
245
246 if(mxCell->IsTextEditActive())
247 {
248 pOutliner = rObj.GetTextEditOutliner();
249 }
250 else
251 {
252 pOutliner = &rObj.ImpGetDrawOutliner();
253 pOutliner->SetText(*pParaObj);
254 }
255
256 sal_Int32 nParaCount(pOutliner->GetParagraphCount());
257
258 // if the user sets character attributes to the complete
259 // cell we want to remove all hard set character attributes
260 // with same which ids from the text
261 std::vector<sal_uInt16> aCharWhichIds(GetAllCharPropIds(rSet));
262
263 for(sal_Int32 nPara = 0; nPara < nParaCount; nPara++)
264 {
265 SfxItemSet aSet(pOutliner->GetParaAttribs(nPara));
266 aSet.Put(rSet);
267
268 for (const auto& rWhichId : aCharWhichIds)
269 {
270 pOutliner->RemoveCharAttribs(nPara, rWhichId);
271 }
272
273 pOutliner->SetParaAttribs(nPara, aSet);
274 }
275
276 if(!mxCell->IsTextEditActive())
277 {
278 if(nParaCount)
279 {
280 // force ItemSet
281 GetObjectItemSet();
282
283 SfxItemSet aNewSet(pOutliner->GetParaAttribs(0));
284 mpItemSet->Put(aNewSet);
285 }
286
287 std::unique_ptr<OutlinerParaObject> pTemp = pOutliner->CreateParaObject(0, nParaCount);
288 pOutliner->Clear();
289 mxCell->SetOutlinerParaObject(std::move(pTemp));
290 }
291
292 if( bOwnParaObj )
293 delete pParaObj;
294 }
295 }
296
297 // call parent
298 AttributeProperties::ItemSetChanged(rSet);
299
300 if( mxCell.is() )
301 mxCell->notifyModified();
302 }
303
ItemChange(const sal_uInt16 nWhich,const SfxPoolItem * pNewItem)304 void CellProperties::ItemChange(const sal_uInt16 nWhich, const SfxPoolItem* pNewItem)
305 {
306 if(pNewItem && (SDRATTR_TEXTDIRECTION == nWhich))
307 {
308 bool bVertical(css::text::WritingMode_TB_RL == static_cast<const SvxWritingModeItem*>(pNewItem)->GetValue());
309
310 sdr::table::SdrTableObj& rObj = static_cast<sdr::table::SdrTableObj&>(GetSdrObject());
311 rObj.SetVerticalWriting(bVertical);
312
313 // Set a cell vertical property
314 OutlinerParaObject* pParaObj = mxCell->CreateEditOutlinerParaObject().release();
315
316 const bool bOwnParaObj = pParaObj != nullptr;
317
318 if( pParaObj == nullptr )
319 pParaObj = mxCell->GetOutlinerParaObject();
320
321 if(pParaObj)
322 {
323 pParaObj->SetVertical(bVertical);
324
325 if( bOwnParaObj )
326 delete pParaObj;
327 }
328 }
329
330 if (pNewItem && (SDRATTR_TABLE_TEXT_ROTATION == nWhich))
331 {
332 const SvxTextRotateItem* pRotateItem = static_cast<const SvxTextRotateItem*>(pNewItem);
333
334 // Set a cell vertical property
335 OutlinerParaObject* pParaObj = mxCell->CreateEditOutlinerParaObject().release();
336
337 const bool bOwnParaObj = pParaObj != nullptr;
338
339 if (pParaObj == nullptr)
340 pParaObj = mxCell->GetOutlinerParaObject();
341
342 if (pParaObj)
343 {
344 pParaObj->SetVertical(pRotateItem->IsVertical(), pRotateItem->IsTopToBottom());
345
346 if (bOwnParaObj)
347 delete pParaObj;
348 }
349
350 // Change autogrow direction
351 SdrTextObj& rObj = static_cast<SdrTextObj&>(GetSdrObject());
352
353 // rescue object size
354 tools::Rectangle aObjectRect = rObj.GetSnapRect();
355
356 const SfxItemSet& rSet = rObj.GetObjectItemSet();
357 bool bAutoGrowWidth = rSet.Get(SDRATTR_TEXT_AUTOGROWWIDTH).GetValue();
358 bool bAutoGrowHeight = rSet.Get(SDRATTR_TEXT_AUTOGROWHEIGHT).GetValue();
359
360 // prepare ItemSet to set exchanged width and height items
361 SfxItemSet aNewSet(*rSet.GetPool(),
362 svl::Items<SDRATTR_TEXT_AUTOGROWHEIGHT, SDRATTR_TEXT_AUTOGROWHEIGHT>{});
363
364 aNewSet.Put(rSet);
365 aNewSet.Put(makeSdrTextAutoGrowWidthItem(bAutoGrowHeight));
366 aNewSet.Put(makeSdrTextAutoGrowHeightItem(bAutoGrowWidth));
367 rObj.SetObjectItemSet(aNewSet);
368
369 // restore object size
370 rObj.SetSnapRect(aObjectRect);
371 }
372
373 // call parent
374 AttributeProperties::ItemChange( nWhich, pNewItem );
375 }
376
377 } // end of namespace properties
378 } // end of namespace sdr
379
380 namespace sdr { namespace table {
381
382
383 // Cell
384
385
create(SdrTableObj & rTableObj)386 rtl::Reference< Cell > Cell::create( SdrTableObj& rTableObj )
387 {
388 rtl::Reference< Cell > xCell( new Cell( rTableObj ) );
389 if( xCell->mxTable.is() )
390 {
391 Reference< XEventListener > xListener( xCell.get() );
392 xCell->mxTable->addEventListener( xListener );
393 }
394 return xCell;
395 }
396
397
Cell(SdrTableObj & rTableObj)398 Cell::Cell(
399 SdrTableObj& rTableObj)
400 : SdrText(rTableObj)
401 ,SvxUnoTextBase( ImplGetSvxUnoOutlinerTextCursorSvxPropertySet() )
402 ,mpPropSet( ImplGetSvxCellPropertySet() )
403 ,mpProperties( new sdr::properties::CellProperties( rTableObj, this ) )
404 ,mnCellContentType( CellContentType_EMPTY )
405 ,mfValue( 0.0 )
406 ,mnError( 0 )
407 ,mbMerged( false )
408 ,mnRowSpan( 1 )
409 ,mnColSpan( 1 )
410 ,mxTable( rTableObj.getTable() )
411 {
412 // Caution: Old SetModel() indirectly did a very necessary thing here,
413 // it created a valid SvxTextEditSource which is needed to bind contained
414 // Text to the UNO API and thus to save/load and more. Added version without
415 // model change.
416 // Also done was (not needed, for reference):
417 // SetStyleSheet( nullptr, true );
418 // ForceOutlinerParaObject( OutlinerMode::TextObject );
419 if(nullptr == GetEditSource())
420 {
421 SetEditSource(new SvxTextEditSource(&GetObject(), this));
422 }
423 }
424
425
~Cell()426 Cell::~Cell() throw()
427 {
428 dispose();
429 }
430
431
dispose()432 void Cell::dispose()
433 {
434 if( mxTable.is() )
435 {
436 try
437 {
438 Reference< XEventListener > xThis( this );
439 mxTable->removeEventListener( xThis );
440 }
441 catch( Exception& )
442 {
443 OSL_FAIL("Cell::dispose(), exception caught!");
444 }
445 mxTable.clear();
446 }
447
448 // tdf#118199 avoid double dispose, detect by using mpProperties
449 // as indicator. Only use SetOutlinerParaObject once
450 if( mpProperties )
451 {
452 mpProperties.reset();
453 SetOutlinerParaObject( nullptr );
454 }
455 }
456
merge(sal_Int32 nColumnSpan,sal_Int32 nRowSpan)457 void Cell::merge( sal_Int32 nColumnSpan, sal_Int32 nRowSpan )
458 {
459 if ((mnColSpan != nColumnSpan) || (mnRowSpan != nRowSpan) || mbMerged)
460 {
461 mnColSpan = nColumnSpan;
462 mnRowSpan = nRowSpan;
463 mbMerged = false;
464 notifyModified();
465 }
466 }
467
468
mergeContent(const CellRef & xSourceCell)469 void Cell::mergeContent( const CellRef& xSourceCell )
470 {
471 SdrTableObj& rTableObj = dynamic_cast< SdrTableObj& >( GetObject() );
472
473 if( xSourceCell->hasText() )
474 {
475 SdrOutliner& rOutliner=rTableObj.ImpGetDrawOutliner();
476 rOutliner.SetUpdateMode(true);
477
478 if( hasText() )
479 {
480 rOutliner.SetText(*GetOutlinerParaObject());
481 rOutliner.AddText(*xSourceCell->GetOutlinerParaObject());
482 }
483 else
484 {
485 rOutliner.SetText(*xSourceCell->GetOutlinerParaObject());
486 }
487
488 SetOutlinerParaObject( rOutliner.CreateParaObject() );
489 rOutliner.Clear();
490 xSourceCell->SetOutlinerParaObject(rOutliner.CreateParaObject());
491 rOutliner.Clear();
492 SetStyleSheet( GetStyleSheet(), true );
493 }
494 }
495
496
cloneFrom(const CellRef & xCell)497 void Cell::cloneFrom( const CellRef& xCell )
498 {
499 if( xCell.is() )
500 {
501 replaceContentAndFormating( xCell );
502
503 mnCellContentType = xCell->mnCellContentType;
504
505 msFormula = xCell->msFormula;
506 mfValue = xCell->mfValue;
507 mnError = xCell->mnError;
508
509 mbMerged = xCell->mbMerged;
510 mnRowSpan = xCell->mnRowSpan;
511 mnColSpan = xCell->mnColSpan;
512
513 }
514 notifyModified();
515 }
516
replaceContentAndFormating(const CellRef & xSourceCell)517 void Cell::replaceContentAndFormating( const CellRef& xSourceCell )
518 {
519 if( xSourceCell.is() && mpProperties )
520 {
521 mpProperties->SetMergedItemSet( xSourceCell->GetObjectItemSet() );
522
523 // tdf#118354 OutlinerParaObject may be nullptr, do not dereference when
524 // not set (!)
525 if(nullptr != xSourceCell->GetOutlinerParaObject())
526 {
527 SetOutlinerParaObject( std::make_unique<OutlinerParaObject>(*xSourceCell->GetOutlinerParaObject()) );
528 }
529
530 SdrTableObj& rTableObj = dynamic_cast< SdrTableObj& >( GetObject() );
531 SdrTableObj& rSourceTableObj = dynamic_cast< SdrTableObj& >( xSourceCell->GetObject() );
532
533 if(&rSourceTableObj.getSdrModelFromSdrObject() != &rTableObj.getSdrModelFromSdrObject())
534 {
535 // TTTT should not happen - if, then a clone may be needed
536 // Maybe add an assertion here later
537 SetStyleSheet( nullptr, true );
538 }
539 }
540 }
541
542
setMerged()543 void Cell::setMerged()
544 {
545 if( !mbMerged )
546 {
547 mbMerged = true;
548 notifyModified();
549 }
550 }
551
552
copyFormatFrom(const CellRef & xSourceCell)553 void Cell::copyFormatFrom( const CellRef& xSourceCell )
554 {
555 if( xSourceCell.is() && mpProperties )
556 {
557 mpProperties->SetMergedItemSet( xSourceCell->GetObjectItemSet() );
558 SdrTableObj& rTableObj = dynamic_cast< SdrTableObj& >( GetObject() );
559 SdrTableObj& rSourceTableObj = dynamic_cast< SdrTableObj& >( xSourceCell->GetObject() );
560
561 if(&rSourceTableObj.getSdrModelFromSdrObject() != &rTableObj.getSdrModelFromSdrObject())
562 {
563 // TTTT should not happen - if, then a clone may be needed
564 // Maybe add an assertion here later
565 SetStyleSheet( nullptr, true );
566 }
567
568 notifyModified();
569 }
570 }
571
572
notifyModified()573 void Cell::notifyModified()
574 {
575 if( mxTable.is() )
576 mxTable->setModified( true );
577 }
578
579
580 // SdrTextShape proxy
581
582
IsActiveCell() const583 bool Cell::IsActiveCell() const
584 {
585 bool isActive = false;
586 SdrTableObj& rTableObj = dynamic_cast< SdrTableObj& >( GetObject() );
587 if( rTableObj.getActiveCell().get() == this )
588 isActive = true;
589
590 return isActive;
591 }
592
IsTextEditActive() const593 bool Cell::IsTextEditActive() const
594 {
595 bool isActive = false;
596 SdrTableObj& rTableObj = dynamic_cast< SdrTableObj& >( GetObject() );
597 if(rTableObj.getActiveCell().get() == this )
598 {
599 if( rTableObj.CanCreateEditOutlinerParaObject() )
600 {
601 isActive = true;
602 }
603 }
604 return isActive;
605 }
606
607
hasText() const608 bool Cell::hasText() const
609 {
610 OutlinerParaObject* pParaObj = GetOutlinerParaObject();
611 if( pParaObj )
612 {
613 const EditTextObject& rTextObj = pParaObj->GetTextObject();
614 if( rTextObj.GetParagraphCount() >= 1 )
615 {
616 if( rTextObj.GetParagraphCount() == 1 )
617 {
618 if( rTextObj.GetText(0).isEmpty() )
619 return false;
620 }
621 return true;
622 }
623 }
624
625 return false;
626 }
627
CanCreateEditOutlinerParaObject() const628 bool Cell::CanCreateEditOutlinerParaObject() const
629 {
630 SdrTableObj& rTableObj = dynamic_cast< SdrTableObj& >( GetObject() );
631 if( rTableObj.getActiveCell().get() == this )
632 return rTableObj.CanCreateEditOutlinerParaObject();
633 return false;
634 }
635
CreateEditOutlinerParaObject() const636 std::unique_ptr<OutlinerParaObject> Cell::CreateEditOutlinerParaObject() const
637 {
638 SdrTableObj& rTableObj = dynamic_cast< SdrTableObj& >( GetObject() );
639 if( rTableObj.getActiveCell().get() == this )
640 return rTableObj.CreateEditOutlinerParaObject();
641 return nullptr;
642 }
643
644
SetStyleSheet(SfxStyleSheet * pStyleSheet,bool bDontRemoveHardAttr)645 void Cell::SetStyleSheet( SfxStyleSheet* pStyleSheet, bool bDontRemoveHardAttr )
646 {
647 // only allow cell styles for cells
648 if( pStyleSheet && pStyleSheet->GetFamily() != SfxStyleFamily::Frame )
649 return;
650
651 if( mpProperties && (mpProperties->GetStyleSheet() != pStyleSheet) )
652 {
653 mpProperties->SetStyleSheet( pStyleSheet, bDontRemoveHardAttr );
654 }
655 }
656
657
GetObjectItemSet()658 const SfxItemSet& Cell::GetObjectItemSet()
659 {
660 if( mpProperties )
661 {
662 return mpProperties->GetObjectItemSet();
663 }
664 else
665 {
666 OSL_FAIL("Cell::GetObjectItemSet(), called without properties!");
667 return GetObject().GetObjectItemSet();
668 }
669 }
670
SetObjectItem(const SfxPoolItem & rItem)671 void Cell::SetObjectItem(const SfxPoolItem& rItem)
672 {
673 if( mpProperties )
674 {
675 mpProperties->SetObjectItem( rItem );
676 notifyModified();
677 }
678 }
679
SetMergedItem(const SfxPoolItem & rItem)680 void Cell::SetMergedItem(const SfxPoolItem& rItem)
681 {
682 SetObjectItem(rItem);
683 }
684
GetStyleSheet() const685 SfxStyleSheet* Cell::GetStyleSheet() const
686 {
687 if( mpProperties )
688 return mpProperties->GetStyleSheet();
689 else
690 return nullptr;
691 }
692
TakeTextAnchorRect(tools::Rectangle & rAnchorRect) const693 void Cell::TakeTextAnchorRect(tools::Rectangle& rAnchorRect) const
694 {
695 rAnchorRect.SetLeft( maCellRect.Left() + GetTextLeftDistance() );
696 rAnchorRect.SetRight( maCellRect.Right() - GetTextRightDistance() );
697 rAnchorRect.SetTop( maCellRect.Top() + GetTextUpperDistance() );
698 rAnchorRect.SetBottom( maCellRect.Bottom() - GetTextLowerDistance() );
699 }
700
701
SetMergedItemSetAndBroadcast(const SfxItemSet & rSet,bool bClearAllItems)702 void Cell::SetMergedItemSetAndBroadcast(const SfxItemSet& rSet, bool bClearAllItems)
703 {
704 if( mpProperties )
705 {
706 mpProperties->SetMergedItemSetAndBroadcast(rSet, bClearAllItems);
707 notifyModified();
708 }
709 }
710
711
calcPreferredWidth(const Size aSize)712 sal_Int32 Cell::calcPreferredWidth( const Size aSize )
713 {
714 if ( !hasText() )
715 return getMinimumWidth();
716
717 Outliner& rOutliner=static_cast< SdrTableObj& >( GetObject() ).ImpGetDrawOutliner();
718 rOutliner.SetPaperSize(aSize);
719 rOutliner.SetUpdateMode(true);
720 ForceOutlinerParaObject( OutlinerMode::TextObject );
721
722 if( GetOutlinerParaObject() )
723 rOutliner.SetText(*GetOutlinerParaObject());
724
725 sal_Int32 nPreferredWidth = const_cast<EditEngine&>(rOutliner.GetEditEngine()).CalcTextWidth();
726 rOutliner.Clear();
727
728 return GetTextLeftDistance() + GetTextRightDistance() + nPreferredWidth;
729 }
730
getMinimumWidth() const731 sal_Int32 Cell::getMinimumWidth() const
732 {
733 return GetTextLeftDistance() + GetTextRightDistance() + 100;
734 }
735
736
getMinimumHeight()737 sal_Int32 Cell::getMinimumHeight()
738 {
739 if( !mpProperties )
740 return 0;
741
742 SdrTableObj& rTableObj = dynamic_cast< SdrTableObj& >( GetObject() );
743 sal_Int32 nMinimumHeight = 0;
744
745 tools::Rectangle aTextRect;
746 TakeTextAnchorRect( aTextRect );
747 Size aSize( aTextRect.GetSize() );
748 aSize.setHeight(0x0FFFFFFF );
749
750 SdrOutliner* pEditOutliner = rTableObj.GetCellTextEditOutliner( *this );
751 if(pEditOutliner)
752 {
753 pEditOutliner->SetMaxAutoPaperSize(aSize);
754 nMinimumHeight = pEditOutliner->GetTextHeight()+1;
755 }
756 else
757 {
758 Outliner& rOutliner=rTableObj.ImpGetDrawOutliner();
759 rOutliner.SetPaperSize(aSize);
760 rOutliner.SetUpdateMode(true);
761 ForceOutlinerParaObject( OutlinerMode::TextObject );
762
763 if( GetOutlinerParaObject() )
764 {
765 rOutliner.SetText(*GetOutlinerParaObject());
766 }
767 nMinimumHeight=rOutliner.GetTextHeight()+1;
768 rOutliner.Clear();
769 }
770
771 nMinimumHeight += GetTextUpperDistance() + GetTextLowerDistance();
772 return nMinimumHeight;
773 }
774
775
GetTextLeftDistance() const776 long Cell::GetTextLeftDistance() const
777 {
778 return GetItemSet().Get(SDRATTR_TEXT_LEFTDIST).GetValue();
779 }
780
781
GetTextRightDistance() const782 long Cell::GetTextRightDistance() const
783 {
784 return GetItemSet().Get(SDRATTR_TEXT_RIGHTDIST).GetValue();
785 }
786
787
GetTextUpperDistance() const788 long Cell::GetTextUpperDistance() const
789 {
790 return GetItemSet().Get(SDRATTR_TEXT_UPPERDIST).GetValue();
791 }
792
793
GetTextLowerDistance() const794 long Cell::GetTextLowerDistance() const
795 {
796 return GetItemSet().Get(SDRATTR_TEXT_LOWERDIST).GetValue();
797 }
798
799
GetTextVerticalAdjust() const800 SdrTextVertAdjust Cell::GetTextVerticalAdjust() const
801 {
802 return GetItemSet().Get(SDRATTR_TEXT_VERTADJUST).GetValue();
803 }
804
805
GetTextHorizontalAdjust() const806 SdrTextHorzAdjust Cell::GetTextHorizontalAdjust() const
807 {
808 return GetItemSet().Get(SDRATTR_TEXT_HORZADJUST).GetValue();
809 }
810
811
SetOutlinerParaObject(std::unique_ptr<OutlinerParaObject> pTextObject)812 void Cell::SetOutlinerParaObject( std::unique_ptr<OutlinerParaObject> pTextObject )
813 {
814 bool bNullTextObject = pTextObject == nullptr;
815 SdrText::SetOutlinerParaObject( std::move(pTextObject) );
816 maSelection.nStartPara = EE_PARA_MAX_COUNT;
817
818 if( bNullTextObject )
819 ForceOutlinerParaObject( OutlinerMode::TextObject );
820 }
821
822
AddUndo()823 void Cell::AddUndo()
824 {
825 SdrObject& rObj = GetObject();
826
827 if( rObj.IsInserted() && rObj.getSdrModelFromSdrObject().IsUndoEnabled() )
828 {
829 CellRef xCell( this );
830 rObj.getSdrModelFromSdrObject().AddUndo( std::make_unique<CellUndo>( &rObj, xCell ) );
831
832 // Undo action for the after-text-edit-ended stack.
833 SdrTableObj* pTableObj = dynamic_cast<sdr::table::SdrTableObj*>(&rObj);
834 if (pTableObj && pTableObj->IsTextEditActive())
835 pTableObj->AddUndo(new CellUndo(pTableObj, xCell));
836 }
837 }
838
839
CloneProperties(sdr::properties::TextProperties const * pProperties,SdrObject & rNewObj,Cell & rNewCell)840 sdr::properties::TextProperties* Cell::CloneProperties( sdr::properties::TextProperties const * pProperties, SdrObject& rNewObj, Cell& rNewCell )
841 {
842 if( pProperties )
843 return new sdr::properties::CellProperties( *static_cast<sdr::properties::CellProperties const *>(pProperties), rNewObj, &rNewCell );
844 else
845 return nullptr;
846 }
847
848
CloneProperties(SdrObject & rNewObj,Cell & rNewCell)849 sdr::properties::TextProperties* Cell::CloneProperties( SdrObject& rNewObj, Cell& rNewCell )
850 {
851 return CloneProperties(mpProperties.get(),rNewObj,rNewCell);
852 }
853
854
855 // XInterface
856
857
queryInterface(const Type & rType)858 Any SAL_CALL Cell::queryInterface( const Type & rType )
859 {
860 if( rType == cppu::UnoType<XMergeableCell>::get() )
861 return Any( Reference< XMergeableCell >( this ) );
862
863 if( rType == cppu::UnoType<XCell>::get() )
864 return Any( Reference< XCell >( this ) );
865
866 if( rType == cppu::UnoType<XLayoutConstrains>::get() )
867 return Any( Reference< XLayoutConstrains >( this ) );
868
869 if( rType == cppu::UnoType<XEventListener>::get() )
870 return Any( Reference< XEventListener >( this ) );
871
872 Any aRet( SvxUnoTextBase::queryAggregation( rType ) );
873 if( aRet.hasValue() )
874 return aRet;
875
876 return ::cppu::OWeakObject::queryInterface( rType );
877 }
878
879
acquire()880 void SAL_CALL Cell::acquire() throw ()
881 {
882 ::cppu::OWeakObject::acquire();
883 }
884
885
release()886 void SAL_CALL Cell::release() throw ()
887 {
888 ::cppu::OWeakObject::release();
889 }
890
891
892 // XTypeProvider
893
894
getTypes()895 Sequence< Type > SAL_CALL Cell::getTypes( )
896 {
897 return comphelper::concatSequences( SvxUnoTextBase::getTypes(),
898 Sequence {
899 cppu::UnoType<XMergeableCell>::get(),
900 cppu::UnoType<XLayoutConstrains>::get() });
901 }
902
903
getImplementationId()904 Sequence< sal_Int8 > SAL_CALL Cell::getImplementationId( )
905 {
906 return css::uno::Sequence<sal_Int8>();
907 }
908
909 // XLayoutConstrains
getMinimumSize()910 css::awt::Size SAL_CALL Cell::getMinimumSize()
911 {
912 return css::awt::Size( getMinimumWidth(), getMinimumHeight() );
913 }
914
915
getPreferredSize()916 css::awt::Size SAL_CALL Cell::getPreferredSize()
917 {
918 return getMinimumSize();
919 }
920
921
calcAdjustedSize(const css::awt::Size & aNewSize)922 css::awt::Size SAL_CALL Cell::calcAdjustedSize( const css::awt::Size& aNewSize )
923 {
924 return aNewSize;
925 }
926
927
928 // XMergeableCell
929
930
getRowSpan()931 sal_Int32 SAL_CALL Cell::getRowSpan()
932 {
933 return mnRowSpan;
934 }
935
936
getColumnSpan()937 sal_Int32 SAL_CALL Cell::getColumnSpan()
938 {
939 return mnColSpan;
940 }
941
942
isMerged()943 sal_Bool SAL_CALL Cell::isMerged()
944 {
945 return mbMerged;
946 }
947
948
949 // XCell
950
951
getFormula()952 OUString SAL_CALL Cell::getFormula( )
953 {
954 return msFormula;
955 }
956
957
setFormula(const OUString & aFormula)958 void SAL_CALL Cell::setFormula( const OUString& aFormula )
959 {
960 if( msFormula != aFormula )
961 {
962 msFormula = aFormula;
963 }
964 }
965
966
getValue()967 double SAL_CALL Cell::getValue( )
968 {
969 return mfValue;
970 }
971
972
setValue(double nValue)973 void SAL_CALL Cell::setValue( double nValue )
974 {
975 if( mfValue != nValue )
976 {
977 mfValue = nValue;
978 mnCellContentType = CellContentType_VALUE;
979 }
980 }
981
982
getType()983 CellContentType SAL_CALL Cell::getType()
984 {
985 return mnCellContentType;
986 }
987
988
getError()989 sal_Int32 SAL_CALL Cell::getError( )
990 {
991 return mnError;
992 }
993
994
995 // XPropertySet
996
997
GetAnyForItem(SfxItemSet const & aSet,const SfxItemPropertySimpleEntry * pMap)998 Any Cell::GetAnyForItem( SfxItemSet const & aSet, const SfxItemPropertySimpleEntry* pMap )
999 {
1000 Any aAny( SvxItemPropertySet_getPropertyValue( pMap, aSet ) );
1001
1002 if( pMap->aType != aAny.getValueType() )
1003 {
1004 // since the sfx uint16 item now exports a sal_Int32, we may have to fix this here
1005 if( ( pMap->aType == ::cppu::UnoType<sal_Int16>::get()) && aAny.getValueType() == ::cppu::UnoType<sal_Int32>::get() )
1006 {
1007 sal_Int32 nValue = 0;
1008 aAny >>= nValue;
1009 aAny <<= static_cast<sal_Int16>(nValue);
1010 }
1011 else
1012 {
1013 OSL_FAIL("GetAnyForItem() Returnvalue has wrong Type!" );
1014 }
1015 }
1016
1017 return aAny;
1018 }
1019
getPropertySetInfo()1020 Reference< XPropertySetInfo > SAL_CALL Cell::getPropertySetInfo()
1021 {
1022 return mpPropSet->getPropertySetInfo();
1023 }
1024
1025
setPropertyValue(const OUString & rPropertyName,const Any & rValue)1026 void SAL_CALL Cell::setPropertyValue( const OUString& rPropertyName, const Any& rValue )
1027 {
1028 ::SolarMutexGuard aGuard;
1029
1030 if(mpProperties == nullptr)
1031 throw DisposedException();
1032
1033 const SfxItemPropertySimpleEntry* pMap = mpPropSet->getPropertyMapEntry(rPropertyName);
1034 if( pMap )
1035 {
1036 if( (pMap->nFlags & PropertyAttribute::READONLY ) != 0 )
1037 throw PropertyVetoException();
1038
1039 switch( pMap->nWID )
1040 {
1041 case OWN_ATTR_STYLE:
1042 {
1043 Reference< XStyle > xStyle;
1044 if( !( rValue >>= xStyle ) )
1045 throw IllegalArgumentException();
1046
1047 SfxUnoStyleSheet* pStyle = SfxUnoStyleSheet::getUnoStyleSheet(xStyle);
1048 SetStyleSheet( pStyle, true );
1049 return;
1050 }
1051 case OWN_ATTR_TABLEBORDER:
1052 {
1053 auto pBorder = o3tl::tryAccess<TableBorder>(rValue);
1054 if(!pBorder)
1055 break;
1056
1057 SvxBoxItem aBox( SDRATTR_TABLE_BORDER );
1058 SvxBoxInfoItem aBoxInfo( SDRATTR_TABLE_BORDER_INNER );
1059 SvxBorderLine aLine;
1060
1061 bool bSet = SvxBoxItem::LineToSvxLine(pBorder->TopLine, aLine, false);
1062 aBox.SetLine(bSet ? &aLine : nullptr, SvxBoxItemLine::TOP);
1063 aBoxInfo.SetValid(SvxBoxInfoItemValidFlags::TOP, pBorder->IsTopLineValid);
1064
1065 bSet = SvxBoxItem::LineToSvxLine(pBorder->BottomLine, aLine, false);
1066 aBox.SetLine(bSet ? &aLine : nullptr, SvxBoxItemLine::BOTTOM);
1067 aBoxInfo.SetValid(SvxBoxInfoItemValidFlags::BOTTOM, pBorder->IsBottomLineValid);
1068
1069 bSet = SvxBoxItem::LineToSvxLine(pBorder->LeftLine, aLine, false);
1070 aBox.SetLine(bSet ? &aLine : nullptr, SvxBoxItemLine::LEFT);
1071 aBoxInfo.SetValid(SvxBoxInfoItemValidFlags::LEFT, pBorder->IsLeftLineValid);
1072
1073 bSet = SvxBoxItem::LineToSvxLine(pBorder->RightLine, aLine, false);
1074 aBox.SetLine(bSet ? &aLine : nullptr, SvxBoxItemLine::RIGHT);
1075 aBoxInfo.SetValid(SvxBoxInfoItemValidFlags::RIGHT, pBorder->IsRightLineValid);
1076
1077 bSet = SvxBoxItem::LineToSvxLine(pBorder->HorizontalLine, aLine, false);
1078 aBoxInfo.SetLine(bSet ? &aLine : nullptr, SvxBoxInfoItemLine::HORI);
1079 aBoxInfo.SetValid(SvxBoxInfoItemValidFlags::HORI, pBorder->IsHorizontalLineValid);
1080
1081 bSet = SvxBoxItem::LineToSvxLine(pBorder->VerticalLine, aLine, false);
1082 aBoxInfo.SetLine(bSet ? &aLine : nullptr, SvxBoxInfoItemLine::VERT);
1083 aBoxInfo.SetValid(SvxBoxInfoItemValidFlags::VERT, pBorder->IsVerticalLineValid);
1084
1085 aBox.SetAllDistances(pBorder->Distance); //TODO
1086 aBoxInfo.SetValid(SvxBoxInfoItemValidFlags::DISTANCE, pBorder->IsDistanceValid);
1087
1088 mpProperties->SetObjectItem(aBox);
1089 mpProperties->SetObjectItem(aBoxInfo);
1090 return;
1091 }
1092 case OWN_ATTR_FILLBMP_MODE:
1093 {
1094 BitmapMode eMode;
1095 if(!(rValue >>= eMode) )
1096 {
1097 sal_Int32 nMode = 0;
1098 if(!(rValue >>= nMode))
1099 throw IllegalArgumentException();
1100
1101 eMode = static_cast<BitmapMode>(nMode);
1102 }
1103
1104 mpProperties->SetObjectItem( XFillBmpStretchItem( eMode == BitmapMode_STRETCH ) );
1105 mpProperties->SetObjectItem( XFillBmpTileItem( eMode == BitmapMode_REPEAT ) );
1106 return;
1107 }
1108 case SDRATTR_TABLE_TEXT_ROTATION:
1109 {
1110 sal_Int32 nRotVal = 0;
1111 if (!(rValue >>= nRotVal))
1112 throw IllegalArgumentException();
1113
1114 if (nRotVal != 27000 && nRotVal != 9000 && nRotVal != 0)
1115 throw IllegalArgumentException();
1116
1117 mpProperties->SetObjectItem(SvxTextRotateItem(nRotVal/10, SDRATTR_TABLE_TEXT_ROTATION));
1118 return;
1119 }
1120 default:
1121 {
1122 SfxItemSet aSet(GetObject().getSdrModelFromSdrObject().GetItemPool(), {{pMap->nWID, pMap->nWID}});
1123 aSet.Put(mpProperties->GetItem(pMap->nWID));
1124
1125 bool bSpecial = false;
1126
1127 switch( pMap->nWID )
1128 {
1129 case XATTR_FILLBITMAP:
1130 case XATTR_FILLGRADIENT:
1131 case XATTR_FILLHATCH:
1132 case XATTR_FILLFLOATTRANSPARENCE:
1133 case XATTR_LINEEND:
1134 case XATTR_LINESTART:
1135 case XATTR_LINEDASH:
1136 {
1137 if( pMap->nMemberId == MID_NAME )
1138 {
1139 OUString aApiName;
1140 if( rValue >>= aApiName )
1141 {
1142 if(SvxShape::SetFillAttribute(pMap->nWID, aApiName, aSet, &GetObject().getSdrModelFromSdrObject()))
1143 bSpecial = true;
1144 }
1145 }
1146 }
1147 break;
1148 }
1149
1150 if( !bSpecial )
1151 {
1152
1153 if( !SvxUnoTextRangeBase::SetPropertyValueHelper( pMap, rValue, aSet ))
1154 {
1155 if( aSet.GetItemState( pMap->nWID ) != SfxItemState::SET )
1156 {
1157 // fetch the default from ItemPool
1158 if(SfxItemPool::IsWhich(pMap->nWID))
1159 aSet.Put(GetObject().getSdrModelFromSdrObject().GetItemPool().GetDefaultItem(pMap->nWID));
1160 }
1161
1162 if( aSet.GetItemState( pMap->nWID ) == SfxItemState::SET )
1163 {
1164 SvxItemPropertySet_setPropertyValue( pMap, rValue, aSet );
1165 }
1166 }
1167 }
1168
1169 GetObject().getSdrModelFromSdrObject().SetChanged();
1170 mpProperties->SetMergedItemSetAndBroadcast( aSet );
1171 return;
1172 }
1173 }
1174 }
1175 throw UnknownPropertyException( rPropertyName, static_cast<cppu::OWeakObject*>(this));
1176 }
1177
1178
getPropertyValue(const OUString & PropertyName)1179 Any SAL_CALL Cell::getPropertyValue( const OUString& PropertyName )
1180 {
1181 ::SolarMutexGuard aGuard;
1182
1183 if(mpProperties == nullptr)
1184 throw DisposedException();
1185
1186 const SfxItemPropertySimpleEntry* pMap = mpPropSet->getPropertyMapEntry(PropertyName);
1187 if( pMap )
1188 {
1189 switch( pMap->nWID )
1190 {
1191 case OWN_ATTR_STYLE:
1192 {
1193 return Any( Reference< XStyle >( dynamic_cast< SfxUnoStyleSheet* >( GetStyleSheet() ) ) );
1194 }
1195 case OWN_ATTR_TABLEBORDER:
1196 {
1197 const SvxBoxInfoItem& rBoxInfoItem = mpProperties->GetItem(SDRATTR_TABLE_BORDER_INNER);
1198 const SvxBoxItem& rBox = mpProperties->GetItem(SDRATTR_TABLE_BORDER);
1199
1200 TableBorder aTableBorder;
1201 aTableBorder.TopLine = SvxBoxItem::SvxLineToLine(rBox.GetTop(), false);
1202 aTableBorder.IsTopLineValid = rBoxInfoItem.IsValid(SvxBoxInfoItemValidFlags::TOP);
1203 aTableBorder.BottomLine = SvxBoxItem::SvxLineToLine(rBox.GetBottom(), false);
1204 aTableBorder.IsBottomLineValid = rBoxInfoItem.IsValid(SvxBoxInfoItemValidFlags::BOTTOM);
1205 aTableBorder.LeftLine = SvxBoxItem::SvxLineToLine(rBox.GetLeft(), false);
1206 aTableBorder.IsLeftLineValid = rBoxInfoItem.IsValid(SvxBoxInfoItemValidFlags::LEFT);
1207 aTableBorder.RightLine = SvxBoxItem::SvxLineToLine(rBox.GetRight(), false);
1208 aTableBorder.IsRightLineValid = rBoxInfoItem.IsValid(SvxBoxInfoItemValidFlags::RIGHT );
1209 aTableBorder.HorizontalLine = SvxBoxItem::SvxLineToLine(rBoxInfoItem.GetHori(), false);
1210 aTableBorder.IsHorizontalLineValid = rBoxInfoItem.IsValid(SvxBoxInfoItemValidFlags::HORI);
1211 aTableBorder.VerticalLine = SvxBoxItem::SvxLineToLine(rBoxInfoItem.GetVert(), false);
1212 aTableBorder.IsVerticalLineValid = rBoxInfoItem.IsValid(SvxBoxInfoItemValidFlags::VERT);
1213 aTableBorder.Distance = rBox.GetSmallestDistance();
1214 aTableBorder.IsDistanceValid = rBoxInfoItem.IsValid(SvxBoxInfoItemValidFlags::DISTANCE);
1215
1216 return Any( aTableBorder );
1217 }
1218 case OWN_ATTR_FILLBMP_MODE:
1219 {
1220 const XFillBmpStretchItem& rStretchItem = mpProperties->GetItem(XATTR_FILLBMP_STRETCH);
1221 const XFillBmpTileItem& rTileItem = mpProperties->GetItem(XATTR_FILLBMP_TILE);
1222 if( rTileItem.GetValue() )
1223 {
1224 return Any( BitmapMode_REPEAT );
1225 }
1226 else if( rStretchItem.GetValue() )
1227 {
1228 return Any( BitmapMode_STRETCH );
1229 }
1230 else
1231 {
1232 return Any( BitmapMode_NO_REPEAT );
1233 }
1234 }
1235 case SDRATTR_TABLE_TEXT_ROTATION:
1236 {
1237 const SvxTextRotateItem& rTextRotate = mpProperties->GetItem(SDRATTR_TABLE_TEXT_ROTATION);
1238 return Any(sal_Int32(rTextRotate.GetValue() * 10));
1239 }
1240 default:
1241 {
1242 SfxItemSet aSet(GetObject().getSdrModelFromSdrObject().GetItemPool(), {{pMap->nWID, pMap->nWID}});
1243 aSet.Put(mpProperties->GetItem(pMap->nWID));
1244
1245 Any aAny;
1246 if(!SvxUnoTextRangeBase::GetPropertyValueHelper( aSet, pMap, aAny ))
1247 {
1248 if(!aSet.Count())
1249 {
1250 // fetch the default from ItemPool
1251 if(SfxItemPool::IsWhich(pMap->nWID))
1252 aSet.Put(GetObject().getSdrModelFromSdrObject().GetItemPool().GetDefaultItem(pMap->nWID));
1253 }
1254
1255 if( aSet.Count() )
1256 aAny = GetAnyForItem( aSet, pMap );
1257 }
1258
1259 return aAny;
1260 }
1261 }
1262 }
1263 throw UnknownPropertyException( PropertyName, static_cast<cppu::OWeakObject*>(this));
1264 }
1265
1266
addPropertyChangeListener(const OUString &,const Reference<XPropertyChangeListener> &)1267 void SAL_CALL Cell::addPropertyChangeListener( const OUString& /*aPropertyName*/, const Reference< XPropertyChangeListener >& /*xListener*/ )
1268 {
1269 }
1270
1271
removePropertyChangeListener(const OUString &,const Reference<XPropertyChangeListener> &)1272 void SAL_CALL Cell::removePropertyChangeListener( const OUString& /*aPropertyName*/, const Reference< XPropertyChangeListener >& /*aListener*/ )
1273 {
1274 }
1275
1276
addVetoableChangeListener(const OUString &,const Reference<XVetoableChangeListener> &)1277 void SAL_CALL Cell::addVetoableChangeListener( const OUString& /*PropertyName*/, const Reference< XVetoableChangeListener >& /*aListener*/ )
1278 {
1279 }
1280
1281
removeVetoableChangeListener(const OUString &,const Reference<XVetoableChangeListener> &)1282 void SAL_CALL Cell::removeVetoableChangeListener( const OUString& /*PropertyName*/, const Reference< XVetoableChangeListener >& /*aListener*/ )
1283 {
1284 }
1285
1286
1287 // XMultiPropertySet
1288
1289
setPropertyValues(const Sequence<OUString> & aPropertyNames,const Sequence<Any> & aValues)1290 void SAL_CALL Cell::setPropertyValues( const Sequence< OUString >& aPropertyNames, const Sequence< Any >& aValues )
1291 {
1292 ::SolarMutexGuard aSolarGuard;
1293
1294 if(mpProperties == nullptr)
1295 throw DisposedException();
1296
1297 const sal_Int32 nCount = aPropertyNames.getLength();
1298
1299 const OUString* pNames = aPropertyNames.getConstArray();
1300 const Any* pValues = aValues.getConstArray();
1301
1302 for( sal_Int32 nIdx = 0; nIdx < nCount; nIdx++, pNames++, pValues++ )
1303 {
1304 try
1305 {
1306 setPropertyValue( *pNames, *pValues );
1307 }
1308 catch( UnknownPropertyException& )
1309 {
1310 OSL_FAIL("svx::Cell::setPropertyValues(), unknown property!" );
1311 }
1312 catch( Exception& )
1313 {
1314 OSL_FAIL("svx::Cell::setPropertyValues(), Exception caught!" );
1315 }
1316 }
1317 }
1318
1319
getPropertyValues(const Sequence<OUString> & aPropertyNames)1320 Sequence< Any > SAL_CALL Cell::getPropertyValues( const Sequence< OUString >& aPropertyNames )
1321 {
1322 ::SolarMutexGuard aSolarGuard;
1323
1324 if(mpProperties == nullptr)
1325 throw DisposedException();
1326
1327 const sal_Int32 nCount = aPropertyNames.getLength();
1328 Sequence< Any > aRet( nCount );
1329 Any* pValue = aRet.getArray();
1330
1331 for( const OUString& rName : aPropertyNames )
1332 {
1333 try
1334 {
1335 *pValue = getPropertyValue( rName );
1336 }
1337 catch( UnknownPropertyException& )
1338 {
1339 OSL_FAIL("svx::Cell::setPropertyValues(), unknown property!" );
1340 }
1341 catch( Exception& )
1342 {
1343 OSL_FAIL( "svx::Cell::getPropertyValues(), Exception caught!" );
1344 }
1345 pValue++;
1346 }
1347
1348 return aRet;
1349 }
1350
1351
addPropertiesChangeListener(const Sequence<OUString> &,const Reference<XPropertiesChangeListener> &)1352 void SAL_CALL Cell::addPropertiesChangeListener( const Sequence< OUString >& /*aPropertyNames*/, const Reference< XPropertiesChangeListener >& /*xListener*/ )
1353 {
1354 }
1355
1356
removePropertiesChangeListener(const Reference<XPropertiesChangeListener> &)1357 void SAL_CALL Cell::removePropertiesChangeListener( const Reference< XPropertiesChangeListener >& /*xListener*/ )
1358 {
1359 }
1360
1361
firePropertiesChangeEvent(const Sequence<OUString> &,const Reference<XPropertiesChangeListener> &)1362 void SAL_CALL Cell::firePropertiesChangeEvent( const Sequence< OUString >& /*aPropertyNames*/, const Reference< XPropertiesChangeListener >& /*xListener*/ )
1363 {
1364 }
1365
1366
1367 // XPropertyState
1368
1369
getPropertyState(const OUString & PropertyName)1370 PropertyState SAL_CALL Cell::getPropertyState( const OUString& PropertyName )
1371 {
1372 ::SolarMutexGuard aGuard;
1373
1374 if(mpProperties == nullptr)
1375 throw DisposedException();
1376
1377 const SfxItemPropertySimpleEntry* pMap = mpPropSet->getPropertyMapEntry(PropertyName);
1378
1379 if( pMap )
1380 {
1381 PropertyState eState;
1382 switch( pMap->nWID )
1383 {
1384 case OWN_ATTR_FILLBMP_MODE:
1385 {
1386 const SfxItemSet& rSet = mpProperties->GetMergedItemSet();
1387
1388 const bool bStretch = rSet.GetItemState( XATTR_FILLBMP_STRETCH, false ) == SfxItemState::SET;
1389 const bool bTile = rSet.GetItemState( XATTR_FILLBMP_TILE, false ) == SfxItemState::SET;
1390 if( bStretch || bTile )
1391 {
1392 eState = PropertyState_DIRECT_VALUE;
1393 }
1394 else
1395 {
1396 eState = PropertyState_DEFAULT_VALUE;
1397 }
1398 break;
1399 }
1400 case OWN_ATTR_STYLE:
1401 {
1402 return PropertyState_DIRECT_VALUE;
1403 }
1404 case OWN_ATTR_TABLEBORDER:
1405 {
1406 const SfxItemSet& rSet = mpProperties->GetMergedItemSet();
1407 if( (rSet.GetItemState( SDRATTR_TABLE_BORDER_INNER, false ) == SfxItemState::DEFAULT) && (rSet.GetItemState( SDRATTR_TABLE_BORDER, false ) == SfxItemState::DEFAULT) )
1408 return PropertyState_DEFAULT_VALUE;
1409
1410 return PropertyState_DIRECT_VALUE;
1411 }
1412 default:
1413 {
1414 const SfxItemSet& rSet = mpProperties->GetMergedItemSet();
1415
1416 switch( rSet.GetItemState( pMap->nWID, false ) )
1417 {
1418 case SfxItemState::READONLY:
1419 case SfxItemState::SET:
1420 eState = PropertyState_DIRECT_VALUE;
1421 break;
1422 case SfxItemState::DEFAULT:
1423 eState = PropertyState_DEFAULT_VALUE;
1424 break;
1425 default:
1426 eState = PropertyState_AMBIGUOUS_VALUE;
1427 break;
1428 }
1429
1430 // if an item is set, this doesn't mean we want it :)
1431 if( PropertyState_DIRECT_VALUE == eState )
1432 {
1433 switch( pMap->nWID )
1434 {
1435 // the following items are disabled by changing the
1436 // fill style or the line style. so there is no need
1437 // to export items without names which should be empty
1438 case XATTR_FILLBITMAP:
1439 case XATTR_FILLGRADIENT:
1440 case XATTR_FILLHATCH:
1441 case XATTR_LINEDASH:
1442 {
1443 const NameOrIndex* pItem = rSet.GetItem<NameOrIndex>(pMap->nWID);
1444 if( ( pItem == nullptr ) || pItem->GetName().isEmpty() )
1445 eState = PropertyState_DEFAULT_VALUE;
1446 }
1447 break;
1448
1449 // #i36115#
1450 // If e.g. the LineStart is on NONE and thus the string has length 0, it still
1451 // may be a hard attribute covering the set LineStart of the parent (Style).
1452 // #i37644#
1453 // same is for fill float transparency
1454 case XATTR_LINEEND:
1455 case XATTR_LINESTART:
1456 case XATTR_FILLFLOATTRANSPARENCE:
1457 {
1458 const NameOrIndex* pItem = rSet.GetItem<NameOrIndex>(pMap->nWID);
1459 if( pItem == nullptr )
1460 eState = PropertyState_DEFAULT_VALUE;
1461 }
1462 break;
1463 }
1464 }
1465 }
1466 }
1467 return eState;
1468 }
1469 throw UnknownPropertyException(PropertyName);
1470 }
1471
1472
getPropertyStates(const Sequence<OUString> & aPropertyName)1473 Sequence< PropertyState > SAL_CALL Cell::getPropertyStates( const Sequence< OUString >& aPropertyName )
1474 {
1475 ::SolarMutexGuard aGuard;
1476
1477 if(mpProperties == nullptr)
1478 throw DisposedException();
1479
1480 const sal_Int32 nCount = aPropertyName.getLength();
1481 Sequence< PropertyState > aRet( nCount );
1482
1483 std::transform(aPropertyName.begin(), aPropertyName.end(), aRet.begin(),
1484 [this](const OUString& rName) -> PropertyState {
1485 try
1486 {
1487 return getPropertyState( rName );
1488 }
1489 catch( Exception& )
1490 {
1491 return PropertyState_AMBIGUOUS_VALUE;
1492 }
1493 });
1494
1495 return aRet;
1496 }
1497
1498
setPropertyToDefault(const OUString & PropertyName)1499 void SAL_CALL Cell::setPropertyToDefault( const OUString& PropertyName )
1500 {
1501 ::SolarMutexGuard aGuard;
1502
1503 if(mpProperties == nullptr)
1504 throw DisposedException();
1505
1506 const SfxItemPropertySimpleEntry* pMap = mpPropSet->getPropertyMapEntry(PropertyName);
1507 if( pMap )
1508 {
1509 switch( pMap->nWID )
1510 {
1511 case OWN_ATTR_FILLBMP_MODE:
1512 {
1513 mpProperties->ClearObjectItem( XATTR_FILLBMP_STRETCH );
1514 mpProperties->ClearObjectItem( XATTR_FILLBMP_TILE );
1515 break;
1516 }
1517 case OWN_ATTR_STYLE:
1518 break;
1519
1520 case OWN_ATTR_TABLEBORDER:
1521 {
1522 mpProperties->ClearObjectItem( SDRATTR_TABLE_BORDER_INNER );
1523 mpProperties->ClearObjectItem( SDRATTR_TABLE_BORDER );
1524 break;
1525 }
1526
1527 default:
1528 {
1529 mpProperties->ClearObjectItem( pMap->nWID );
1530 }
1531 }
1532
1533 GetObject().getSdrModelFromSdrObject().SetChanged();
1534 return;
1535 }
1536 throw UnknownPropertyException( PropertyName, static_cast<cppu::OWeakObject*>(this));
1537 }
1538
1539
getPropertyDefault(const OUString & aPropertyName)1540 Any SAL_CALL Cell::getPropertyDefault( const OUString& aPropertyName )
1541 {
1542 ::SolarMutexGuard aGuard;
1543
1544 if(mpProperties == nullptr)
1545 throw DisposedException();
1546
1547 const SfxItemPropertySimpleEntry* pMap = mpPropSet->getPropertyMapEntry(aPropertyName);
1548 if( pMap )
1549 {
1550 switch( pMap->nWID )
1551 {
1552 case OWN_ATTR_FILLBMP_MODE:
1553 return Any( BitmapMode_NO_REPEAT );
1554
1555 case OWN_ATTR_STYLE:
1556 {
1557 Reference< XStyle > xStyle;
1558 return Any( xStyle );
1559 }
1560
1561 case OWN_ATTR_TABLEBORDER:
1562 {
1563 TableBorder aBorder;
1564 return Any( aBorder );
1565 }
1566
1567 default:
1568 {
1569 if( SfxItemPool::IsWhich(pMap->nWID) )
1570 {
1571 SfxItemSet aSet(GetObject().getSdrModelFromSdrObject().GetItemPool(), {{pMap->nWID, pMap->nWID}});
1572 aSet.Put(GetObject().getSdrModelFromSdrObject().GetItemPool().GetDefaultItem(pMap->nWID));
1573 return GetAnyForItem( aSet, pMap );
1574 }
1575 }
1576 }
1577 }
1578 throw UnknownPropertyException( aPropertyName, static_cast<cppu::OWeakObject*>(this));
1579 }
1580
1581
1582 // XMultiPropertyStates
1583
1584
setAllPropertiesToDefault()1585 void SAL_CALL Cell::setAllPropertiesToDefault()
1586 {
1587 mpProperties.reset(new sdr::properties::CellProperties( static_cast< SdrTableObj& >( GetObject() ), this ));
1588
1589 SdrOutliner& rOutliner = GetObject().ImpGetDrawOutliner();
1590
1591 OutlinerParaObject* pParaObj = GetOutlinerParaObject();
1592 if( pParaObj )
1593 {
1594 rOutliner.SetText(*pParaObj);
1595 sal_Int32 nParaCount(rOutliner.GetParagraphCount());
1596
1597 if(nParaCount)
1598 {
1599 ESelection aSelection( 0, 0, EE_PARA_ALL, EE_TEXTPOS_ALL);
1600 rOutliner.RemoveAttribs(aSelection, true, 0);
1601
1602 std::unique_ptr<OutlinerParaObject> pTemp = rOutliner.CreateParaObject(0, nParaCount);
1603 rOutliner.Clear();
1604
1605 SetOutlinerParaObject(std::move(pTemp));
1606 }
1607 }
1608 }
1609
1610
setPropertiesToDefault(const Sequence<OUString> & aPropertyNames)1611 void SAL_CALL Cell::setPropertiesToDefault( const Sequence< OUString >& aPropertyNames )
1612 {
1613 for(const OUString& rName : aPropertyNames)
1614 setPropertyToDefault( rName );
1615 }
1616
1617
getPropertyDefaults(const Sequence<OUString> & aPropertyNames)1618 Sequence< Any > SAL_CALL Cell::getPropertyDefaults( const Sequence< OUString >& aPropertyNames )
1619 {
1620 sal_Int32 nCount = aPropertyNames.getLength();
1621 Sequence< Any > aDefaults( nCount );
1622
1623 std::transform(aPropertyNames.begin(), aPropertyNames.end(), aDefaults.begin(),
1624 [this](const OUString& rName) -> Any { return getPropertyDefault(rName); });
1625
1626 return aDefaults;
1627 }
1628
1629
1630 // XText
1631
1632
insertTextContent(const Reference<XTextRange> & xRange,const Reference<XTextContent> & xContent,sal_Bool bAbsorb)1633 void SAL_CALL Cell::insertTextContent( const Reference< XTextRange >& xRange, const Reference< XTextContent >& xContent, sal_Bool bAbsorb )
1634 {
1635 SvxUnoTextBase::insertTextContent( xRange, xContent, bAbsorb );
1636 notifyModified();
1637 }
1638
1639
removeTextContent(const Reference<XTextContent> & xContent)1640 void SAL_CALL Cell::removeTextContent( const Reference< XTextContent >& xContent )
1641 {
1642 SvxUnoTextBase::removeTextContent( xContent );
1643 notifyModified();
1644 }
1645
1646
1647 // XSimpleText
1648
1649
insertString(const Reference<XTextRange> & xRange,const OUString & aString,sal_Bool bAbsorb)1650 void SAL_CALL Cell::insertString( const Reference< XTextRange >& xRange, const OUString& aString, sal_Bool bAbsorb )
1651 {
1652 SvxUnoTextBase::insertString( xRange, aString, bAbsorb );
1653 notifyModified();
1654 }
1655
1656
insertControlCharacter(const Reference<XTextRange> & xRange,sal_Int16 nControlCharacter,sal_Bool bAbsorb)1657 void SAL_CALL Cell::insertControlCharacter( const Reference< XTextRange >& xRange, sal_Int16 nControlCharacter, sal_Bool bAbsorb )
1658 {
1659 SvxUnoTextBase::insertControlCharacter( xRange, nControlCharacter, bAbsorb );
1660 notifyModified();
1661 }
1662
1663
1664 // XTextRange
1665
1666
getString()1667 OUString SAL_CALL Cell::getString( )
1668 {
1669 maSelection.nStartPara = EE_PARA_MAX_COUNT;
1670 return SvxUnoTextBase::getString();
1671 }
1672
1673
setString(const OUString & aString)1674 void SAL_CALL Cell::setString( const OUString& aString )
1675 {
1676 SvxUnoTextBase::setString( aString );
1677 notifyModified();
1678 }
1679
1680 // XEventListener
disposing(const EventObject &)1681 void SAL_CALL Cell::disposing( const EventObject& /*Source*/ )
1682 {
1683 mxTable.clear();
1684 dispose();
1685 }
1686
dumpAsXml(xmlTextWriterPtr pWriter,sal_Int32 nRow,sal_Int32 nCol) const1687 void Cell::dumpAsXml(xmlTextWriterPtr pWriter, sal_Int32 nRow, sal_Int32 nCol) const
1688 {
1689 xmlTextWriterStartElement(pWriter, BAD_CAST("Cell"));
1690 xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("row"), "%" SAL_PRIdINT32, nRow);
1691 xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("col"), "%" SAL_PRIdINT32, nCol);
1692 SdrText::dumpAsXml(pWriter);
1693 //SvxUnoTextBase::dumpAsXml(pWriter);
1694 //mpPropSet->dumpAsXml(pWriter);
1695 mpProperties->dumpAsXml(pWriter);
1696 xmlTextWriterEndElement(pWriter);
1697 }
1698
1699 } }
1700
1701 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1702