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