calc: on editing invalidation of view with different zoom is wrong
[LibreOffice.git] / sc / source / ui / unoobj / fielduno.cxx
blob4d14e4139652565efc3d209b37b96160f75c0170
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <memory>
21 #include <fielduno.hxx>
22 #include <textuno.hxx>
23 #include <miscuno.hxx>
24 #include <docsh.hxx>
25 #include <hints.hxx>
26 #include <editsrc.hxx>
27 #include <unonames.hxx>
28 #include <editutil.hxx>
30 #include <svl/hint.hxx>
31 #include <utility>
32 #include <vcl/svapp.hxx>
34 #include <editeng/eeitem.hxx>
36 #include <editeng/editeng.hxx>
37 #include <editeng/editobj.hxx>
38 #include <editeng/flditem.hxx>
39 #include <comphelper/sequence.hxx>
40 #include <cppuhelper/supportsservice.hxx>
42 #include <com/sun/star/beans/PropertyAttribute.hpp>
43 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
44 #include <com/sun/star/text/TextContentAnchorType.hpp>
45 #include <com/sun/star/text/WrapTextMode.hpp>
46 #include <com/sun/star/text/FilenameDisplayFormat.hpp>
47 #include <com/sun/star/text/textfield/Type.hpp>
49 using namespace com::sun::star;
51 namespace {
53 // no Which-ID here, map only for PropertySetInfo
55 const SfxItemPropertySet* getDateTimePropertySet()
57 static const SfxItemPropertyMapEntry aMapContent[] =
59 { SC_UNONAME_DATETIME, 0, cppu::UnoType<util::DateTime>::get(), 0, 0 },
60 { SC_UNONAME_ISFIXED, 0, cppu::UnoType<bool>::get(), 0, 0 },
61 { SC_UNONAME_ISDATE, 0, cppu::UnoType<bool>::get(), 0, 0 },
62 { SC_UNONAME_NUMFMT, 0, cppu::UnoType<sal_Int32>::get(), 0, 0 },
64 static SfxItemPropertySet aMap(aMapContent);
65 return &aMap;
68 const SfxItemPropertySet* getEmptyPropertySet()
70 static SfxItemPropertySet aMap({});
71 return &aMap;
74 const SfxItemPropertySet* lcl_GetURLPropertySet()
76 static const SfxItemPropertyMapEntry aURLPropertyMap_Impl[] =
78 { SC_UNONAME_ANCTYPE, 0, cppu::UnoType<text::TextContentAnchorType>::get(), beans::PropertyAttribute::READONLY, 0 },
79 { SC_UNONAME_ANCTYPES, 0, cppu::UnoType<uno::Sequence<text::TextContentAnchorType>>::get(), beans::PropertyAttribute::READONLY, 0 },
80 { SC_UNONAME_REPR, 0, cppu::UnoType<OUString>::get(), 0, 0},
81 { SC_UNONAME_TARGET, 0, cppu::UnoType<OUString>::get(), 0, 0},
82 { SC_UNONAME_TEXTWRAP, 0, cppu::UnoType<text::WrapTextMode>::get(), beans::PropertyAttribute::READONLY, 0 },
83 { SC_UNONAME_URL, 0, cppu::UnoType<OUString>::get(), 0, 0},
85 static SfxItemPropertySet aURLPropertySet_Impl( aURLPropertyMap_Impl );
86 return &aURLPropertySet_Impl;
89 const SfxItemPropertySet* lcl_GetHeaderFieldPropertySet()
91 static const SfxItemPropertyMapEntry aHeaderFieldPropertyMap_Impl[] =
93 { SC_UNONAME_ANCTYPE, 0, cppu::UnoType<text::TextContentAnchorType>::get(), beans::PropertyAttribute::READONLY, 0 },
94 { SC_UNONAME_ANCTYPES, 0, cppu::UnoType<uno::Sequence<text::TextContentAnchorType>>::get(), beans::PropertyAttribute::READONLY, 0 },
95 { SC_UNONAME_TEXTWRAP, 0, cppu::UnoType<text::WrapTextMode>::get(), beans::PropertyAttribute::READONLY, 0 },
97 static SfxItemPropertySet aHeaderFieldPropertySet_Impl( aHeaderFieldPropertyMap_Impl );
98 return &aHeaderFieldPropertySet_Impl;
101 const SfxItemPropertySet* lcl_GetFileFieldPropertySet()
103 static const SfxItemPropertyMapEntry aFileFieldPropertyMap_Impl[] =
105 { SC_UNONAME_ANCTYPE, 0, cppu::UnoType<text::TextContentAnchorType>::get(), beans::PropertyAttribute::READONLY, 0 },
106 { SC_UNONAME_ANCTYPES, 0, cppu::UnoType<uno::Sequence<text::TextContentAnchorType>>::get(), beans::PropertyAttribute::READONLY, 0 },
107 { SC_UNONAME_FILEFORM, 0, cppu::UnoType<sal_Int16>::get(), 0, 0 },
108 { SC_UNONAME_TEXTWRAP, 0, cppu::UnoType<text::WrapTextMode>::get(), beans::PropertyAttribute::READONLY, 0 },
110 static SfxItemPropertySet aFileFieldPropertySet_Impl( aFileFieldPropertyMap_Impl );
111 return &aFileFieldPropertySet_Impl;
114 SvxFileFormat lcl_UnoToSvxFileFormat( sal_Int16 nUnoValue )
116 switch( nUnoValue )
118 case text::FilenameDisplayFormat::FULL: return SvxFileFormat::PathFull;
119 case text::FilenameDisplayFormat::PATH: return SvxFileFormat::PathOnly;
120 case text::FilenameDisplayFormat::NAME: return SvxFileFormat::NameOnly;
121 default:
122 return SvxFileFormat::NameAndExt;
126 sal_Int16 lcl_SvxToUnoFileFormat( SvxFileFormat nSvxValue )
128 switch( nSvxValue )
130 case SvxFileFormat::NameAndExt: return text::FilenameDisplayFormat::NAME_AND_EXT;
131 case SvxFileFormat::PathFull: return text::FilenameDisplayFormat::FULL;
132 case SvxFileFormat::PathOnly: return text::FilenameDisplayFormat::PATH;
133 default:
134 return text::FilenameDisplayFormat::NAME;
140 SC_SIMPLE_SERVICE_INFO( ScCellFieldsObj, "ScCellFieldsObj", "com.sun.star.text.TextFields" )
141 SC_SIMPLE_SERVICE_INFO( ScHeaderFieldsObj, "ScHeaderFieldsObj", "com.sun.star.text.TextFields" )
143 namespace {
145 enum ScUnoCollectMode
147 SC_UNO_COLLECT_NONE,
148 SC_UNO_COLLECT_COUNT,
149 SC_UNO_COLLECT_FINDINDEX,
150 SC_UNO_COLLECT_FINDPOS
154 * This class exists solely to allow searching through field items. TODO:
155 * Look into providing the same functionality directly in EditEngine, to
156 * avoid having this class altogether.
158 class ScUnoEditEngine : public ScEditEngineDefaulter
160 ScUnoCollectMode eMode;
161 sal_uInt16 nFieldCount;
162 sal_Int32 mnFieldType;
163 std::unique_ptr<SvxFieldData>
164 pFound; // local copy
165 sal_Int32 nFieldPar;
166 sal_Int32 nFieldPos;
167 sal_uInt16 nFieldIndex;
169 public:
170 explicit ScUnoEditEngine(ScEditEngineDefaulter* pSource);
172 virtual OUString CalcFieldValue( const SvxFieldItem& rField, sal_Int32 nPara, sal_Int32 nPos,
173 std::optional<Color>& rTxtColor, std::optional<Color>& rFldColor ) override;
175 sal_uInt16 CountFields();
176 SvxFieldData* FindByIndex(sal_uInt16 nIndex);
177 SvxFieldData* FindByPos(sal_Int32 nPar, sal_Int32 nPos, sal_Int32 nType);
179 sal_Int32 GetFieldPar() const { return nFieldPar; }
180 sal_Int32 GetFieldPos() const { return nFieldPos; }
185 ScUnoEditEngine::ScUnoEditEngine(ScEditEngineDefaulter* pSource)
186 : ScEditEngineDefaulter(*pSource)
187 , eMode(SC_UNO_COLLECT_NONE)
188 , nFieldCount(0)
189 , mnFieldType(text::textfield::Type::UNSPECIFIED)
190 , nFieldPar(0)
191 , nFieldPos(0)
192 , nFieldIndex(0)
194 std::unique_ptr<EditTextObject> pData = pSource->CreateTextObject();
195 SetTextCurrentDefaults( *pData );
198 OUString ScUnoEditEngine::CalcFieldValue( const SvxFieldItem& rField,
199 sal_Int32 nPara, sal_Int32 nPos, std::optional<Color>& rTxtColor, std::optional<Color>& rFldColor )
201 OUString aRet(EditEngine::CalcFieldValue( rField, nPara, nPos, rTxtColor, rFldColor ));
202 if (eMode != SC_UNO_COLLECT_NONE)
204 const SvxFieldData* pFieldData = rField.GetField();
205 if ( pFieldData )
207 if (mnFieldType == text::textfield::Type::UNSPECIFIED || pFieldData->GetClassId() == mnFieldType)
209 if ( eMode == SC_UNO_COLLECT_FINDINDEX && !pFound && nFieldCount == nFieldIndex )
211 pFound = pFieldData->Clone();
212 nFieldPar = nPara;
213 nFieldPos = nPos;
215 if ( eMode == SC_UNO_COLLECT_FINDPOS && !pFound &&
216 nPara == nFieldPar && nPos == nFieldPos )
218 pFound = pFieldData->Clone();
219 nFieldIndex = nFieldCount;
221 ++nFieldCount;
225 return aRet;
228 sal_uInt16 ScUnoEditEngine::CountFields()
230 eMode = SC_UNO_COLLECT_COUNT;
231 mnFieldType = text::textfield::Type::UNSPECIFIED;
232 nFieldCount = 0;
233 UpdateFields();
234 eMode = SC_UNO_COLLECT_NONE;
236 return nFieldCount;
239 SvxFieldData* ScUnoEditEngine::FindByIndex(sal_uInt16 nIndex)
241 eMode = SC_UNO_COLLECT_FINDINDEX;
242 nFieldIndex = nIndex;
243 mnFieldType = text::textfield::Type::UNSPECIFIED;
244 nFieldCount = 0;
245 UpdateFields();
246 eMode = SC_UNO_COLLECT_NONE;
248 return pFound.get();
251 SvxFieldData* ScUnoEditEngine::FindByPos(sal_Int32 nPar, sal_Int32 nPos, sal_Int32 nType)
253 eMode = SC_UNO_COLLECT_FINDPOS;
254 nFieldPar = nPar;
255 nFieldPos = nPos;
256 mnFieldType = nType;
257 nFieldCount = 0;
258 UpdateFields();
259 mnFieldType = text::textfield::Type::UNSPECIFIED;
260 eMode = SC_UNO_COLLECT_NONE;
262 return pFound.get();
265 ScCellFieldsObj::ScCellFieldsObj(
266 uno::Reference<text::XTextRange> xContent,
267 ScDocShell* pDocSh, const ScAddress& rPos) :
268 mxContent(std::move(xContent)),
269 pDocShell( pDocSh ),
270 aCellPos( rPos )
272 pDocShell->GetDocument().AddUnoObject(*this);
274 mpEditSource.reset( new ScCellEditSource( pDocShell, aCellPos ) );
277 ScCellFieldsObj::~ScCellFieldsObj()
279 SolarMutexGuard g;
281 if (pDocShell)
282 pDocShell->GetDocument().RemoveUnoObject(*this);
284 mpEditSource.reset();
286 // increment refcount to prevent double call off dtor
287 osl_atomic_increment( &m_refCount );
289 if (mpRefreshListeners)
291 lang::EventObject aEvent;
292 aEvent.Source.set(static_cast<cppu::OWeakObject*>(this));
293 mpRefreshListeners->disposeAndClear(aEvent);
294 mpRefreshListeners.reset();
298 void ScCellFieldsObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
300 if ( dynamic_cast<const ScUpdateRefHint*>(&rHint) )
302 //! update of references
304 else if ( rHint.GetId() == SfxHintId::Dying )
306 pDocShell = nullptr; // became invalid
309 // EditSource registered itself as a listener
312 // XIndexAccess (via XTextFields)
314 uno::Reference<text::XTextField> ScCellFieldsObj::GetObjectByIndex_Impl(sal_Int32 Index) const
316 //! Field functions have to be passed to the forwarder !!!
317 ScEditEngineDefaulter* pEditEngine = mpEditSource->GetEditEngine();
318 ScUnoEditEngine aTempEngine(pEditEngine);
319 SvxFieldData* pData = aTempEngine.FindByIndex(static_cast<sal_uInt16>(Index));
320 if (!pData)
321 return uno::Reference<text::XTextField>();
323 sal_Int32 nPar = aTempEngine.GetFieldPar();
324 sal_Int32 nPos = aTempEngine.GetFieldPos();
325 ESelection aSelection( nPar, nPos, nPar, nPos+1 ); // Field size is 1 character
327 sal_Int32 eType = pData->GetClassId();
328 uno::Reference<text::XTextField> xRet(
329 new ScEditFieldObj(mxContent, std::make_unique<ScCellEditSource>(pDocShell, aCellPos), eType, aSelection));
330 return xRet;
333 sal_Int32 SAL_CALL ScCellFieldsObj::getCount()
335 SolarMutexGuard aGuard;
337 //! Field functions have to be passed to the forwarder !!!
338 ScEditEngineDefaulter* pEditEngine = mpEditSource->GetEditEngine();
339 ScUnoEditEngine aTempEngine(pEditEngine);
341 return aTempEngine.CountFields(); // count the fields, we don't care about their type in the cell
344 uno::Any SAL_CALL ScCellFieldsObj::getByIndex( sal_Int32 nIndex )
346 SolarMutexGuard aGuard;
347 uno::Reference<text::XTextField> xField(GetObjectByIndex_Impl(nIndex));
348 if (!xField.is())
349 throw lang::IndexOutOfBoundsException();
351 return uno::Any(xField);
354 uno::Type SAL_CALL ScCellFieldsObj::getElementType()
356 return cppu::UnoType<text::XTextField>::get();
359 sal_Bool SAL_CALL ScCellFieldsObj::hasElements()
361 SolarMutexGuard aGuard;
362 return ( getCount() != 0 );
365 uno::Reference<container::XEnumeration> SAL_CALL ScCellFieldsObj::createEnumeration()
367 SolarMutexGuard aGuard;
368 return new ScIndexEnumeration(this, "com.sun.star.text.TextFieldEnumeration");
371 void SAL_CALL ScCellFieldsObj::addContainerListener(
372 const uno::Reference<container::XContainerListener>& /* xListener */ )
374 OSL_FAIL("not implemented");
377 void SAL_CALL ScCellFieldsObj::removeContainerListener(
378 const uno::Reference<container::XContainerListener>& /* xListener */ )
380 OSL_FAIL("not implemented");
383 // XRefreshable
384 void SAL_CALL ScCellFieldsObj::refresh( )
386 if (mpRefreshListeners)
388 // Call all listeners.
389 lang::EventObject aEvent;
390 aEvent.Source.set(uno::Reference< util::XRefreshable >(this));
391 mpRefreshListeners->notifyEach( &util::XRefreshListener::refreshed, aEvent );
395 void SAL_CALL ScCellFieldsObj::addRefreshListener( const uno::Reference< util::XRefreshListener >& xListener )
397 if (xListener.is())
399 SolarMutexGuard aGuard;
400 if (!mpRefreshListeners)
401 mpRefreshListeners.reset( new comphelper::OInterfaceContainerHelper3<util::XRefreshListener>(aMutex) );
402 mpRefreshListeners->addInterface(xListener);
406 void SAL_CALL ScCellFieldsObj::removeRefreshListener( const uno::Reference<util::XRefreshListener >& xListener )
408 if (xListener.is())
410 SolarMutexGuard aGuard;
411 if (mpRefreshListeners)
412 mpRefreshListeners->removeInterface(xListener);
416 ScHeaderFieldsObj::ScHeaderFieldsObj(ScHeaderFooterTextData& rData) :
417 mrData(rData)
419 mpEditSource.reset( new ScHeaderFooterEditSource(rData) );
422 ScHeaderFieldsObj::~ScHeaderFieldsObj()
424 mpEditSource.reset();
426 // increment refcount to prevent double call off dtor
427 osl_atomic_increment( &m_refCount );
429 if (mpRefreshListeners)
431 lang::EventObject aEvent;
432 aEvent.Source = static_cast<cppu::OWeakObject*>(this);
433 mpRefreshListeners->disposeAndClear(aEvent);
434 mpRefreshListeners.reset();
438 // XIndexAccess (via XTextFields)
440 uno::Reference<text::XTextField> ScHeaderFieldsObj::GetObjectByIndex_Impl(sal_Int32 Index) const
442 //! Field functions have to be passed to the forwarder !!!
443 ScEditEngineDefaulter* pEditEngine = mpEditSource->GetEditEngine();
444 ScUnoEditEngine aTempEngine(pEditEngine);
446 SvxFieldData* pData = aTempEngine.FindByIndex(static_cast<sal_uInt16>(Index));
447 if (!pData)
448 return nullptr;
450 // Get the parent text range instance.
451 uno::Reference<text::XTextRange> xTextRange;
452 uno::Reference<sheet::XHeaderFooterContent> xContentObj = mrData.GetContentObj();
453 if (!xContentObj.is())
454 throw uno::RuntimeException("");
456 rtl::Reference<ScHeaderFooterContentObj> pContentObj = ScHeaderFooterContentObj::getImplementation(xContentObj);
457 uno::Reference<text::XText> xText;
459 switch ( mrData.GetPart() )
461 case ScHeaderFooterPart::LEFT:
462 xText = pContentObj->getLeftText();
463 break;
464 case ScHeaderFooterPart::CENTER:
465 xText = pContentObj->getCenterText();
466 break;
467 case ScHeaderFooterPart::RIGHT:
468 xText = pContentObj->getRightText();
469 break;
472 xTextRange = xText;
474 sal_Int32 nPar = aTempEngine.GetFieldPar();
475 sal_Int32 nPos = aTempEngine.GetFieldPos();
476 ESelection aSelection( nPar, nPos, nPar, nPos+1 ); // Field size is 1 character
478 sal_Int32 eRealType = pData->GetClassId();
479 uno::Reference<text::XTextField> xRet(
480 new ScEditFieldObj(xTextRange, std::make_unique<ScHeaderFooterEditSource>(mrData), eRealType, aSelection));
481 return xRet;
484 sal_Int32 SAL_CALL ScHeaderFieldsObj::getCount()
486 SolarMutexGuard aGuard;
488 //! Field functions have to be passed to the forwarder !!!
489 ScEditEngineDefaulter* pEditEngine = mpEditSource->GetEditEngine();
490 ScUnoEditEngine aTempEngine(pEditEngine);
491 return aTempEngine.CountFields();
494 uno::Any SAL_CALL ScHeaderFieldsObj::getByIndex( sal_Int32 nIndex )
496 SolarMutexGuard aGuard;
497 uno::Reference<text::XTextField> xField(GetObjectByIndex_Impl(nIndex));
498 if (!xField.is())
499 throw lang::IndexOutOfBoundsException();
501 return uno::Any(xField);
504 uno::Type SAL_CALL ScHeaderFieldsObj::getElementType()
506 return cppu::UnoType<text::XTextField>::get();
509 sal_Bool SAL_CALL ScHeaderFieldsObj::hasElements()
511 SolarMutexGuard aGuard;
512 return ( getCount() != 0 );
515 uno::Reference<container::XEnumeration> SAL_CALL ScHeaderFieldsObj::createEnumeration()
517 SolarMutexGuard aGuard;
518 return new ScIndexEnumeration(this, "com.sun.star.text.TextFieldEnumeration");
521 void SAL_CALL ScHeaderFieldsObj::addContainerListener(
522 const uno::Reference<container::XContainerListener>& /* xListener */ )
524 OSL_FAIL("not implemented");
527 void SAL_CALL ScHeaderFieldsObj::removeContainerListener(
528 const uno::Reference<container::XContainerListener>& /* xListener */ )
530 OSL_FAIL("not implemented");
533 // XRefreshable
534 void SAL_CALL ScHeaderFieldsObj::refresh( )
536 if (mpRefreshListeners)
538 // Call all listeners.
539 lang::EventObject aEvent;
540 aEvent.Source.set(uno::Reference< util::XRefreshable >(this));
541 mpRefreshListeners->notifyEach( &util::XRefreshListener::refreshed, aEvent);
545 void SAL_CALL ScHeaderFieldsObj::addRefreshListener( const uno::Reference< util::XRefreshListener >& xListener )
547 if (xListener.is())
549 SolarMutexGuard aGuard;
550 if (!mpRefreshListeners)
551 mpRefreshListeners.reset(new comphelper::OInterfaceContainerHelper3<util::XRefreshListener>(aMutex));
552 mpRefreshListeners->addInterface(xListener);
556 void SAL_CALL ScHeaderFieldsObj::removeRefreshListener( const uno::Reference<util::XRefreshListener >& xListener )
558 if (xListener.is())
560 SolarMutexGuard aGuard;
561 if (mpRefreshListeners)
562 mpRefreshListeners->removeInterface(xListener);
566 SvxFieldData& ScEditFieldObj::getData()
568 if (!mpData)
570 switch (meType)
572 case text::textfield::Type::DATE:
573 mpData.reset(new SvxDateField);
574 break;
575 case text::textfield::Type::EXTENDED_FILE:
576 mpData.reset(
577 new SvxExtFileField(OUString(), SvxFileType::Var, SvxFileFormat::NameAndExt));
578 break;
579 case text::textfield::Type::PAGE:
580 mpData.reset(new SvxPageField);
581 break;
582 case text::textfield::Type::PAGES:
583 mpData.reset(new SvxPagesField);
584 break;
585 case text::textfield::Type::TABLE:
586 mpData.reset(new SvxTableField);
587 break;
588 case text::textfield::Type::TIME:
589 mpData.reset(new SvxTimeField);
590 break;
591 case text::textfield::Type::EXTENDED_TIME:
593 if (mbIsDate)
594 mpData.reset(new SvxDateField);
595 else
596 mpData.reset(new SvxExtTimeField);
598 break;
599 case text::textfield::Type::DOCINFO_TITLE:
600 mpData.reset(new SvxFileField);
601 break;
602 case text::textfield::Type::URL:
603 mpData.reset(
604 new SvxURLField(OUString(), OUString(), SvxURLFormat::AppDefault));
605 break;
606 default:
607 mpData.reset(new SvxFieldData);
610 return *mpData;
613 void ScEditFieldObj::setPropertyValueURL(const OUString& rName, const css::uno::Any& rVal)
615 OUString aStrVal;
616 if (mpEditSource)
618 // Edit engine instance already exists for this field item. Use it.
619 ScEditEngineDefaulter* pEditEngine = mpEditSource->GetEditEngine();
620 ScUnoEditEngine aTempEngine(pEditEngine);
622 // don't care about the type (only URLs can be found in the cells)
623 SvxFieldData* pField = aTempEngine.FindByPos(
624 aSelection.nStartPara, aSelection.nStartPos, text::textfield::Type::UNSPECIFIED);
625 OSL_ENSURE(pField,"setPropertyValue: Field not found");
626 if (!pField)
627 return;
629 if (pField->GetClassId() != text::textfield::Type::URL)
630 // Make sure this is indeed a URL field.
631 return;
633 SvxURLField* pURL = static_cast<SvxURLField*>(pField);
635 if (rName == SC_UNONAME_URL)
637 if (rVal >>= aStrVal)
638 pURL->SetURL(aStrVal);
640 else if (rName == SC_UNONAME_REPR)
642 if (rVal >>= aStrVal)
643 pURL->SetRepresentation(aStrVal);
645 else if (rName == SC_UNONAME_TARGET)
647 if (rVal >>= aStrVal)
648 pURL->SetTargetFrame(aStrVal);
650 else
651 throw beans::UnknownPropertyException(rName);
653 pEditEngine->QuickInsertField( SvxFieldItem(*pField, EE_FEATURE_FIELD), aSelection );
654 mpEditSource->UpdateData();
655 return;
658 // Edit engine instance not yet present. Store the item data for later use.
659 SvxURLField& rData = static_cast<SvxURLField&>(getData());
660 if (rName == SC_UNONAME_URL)
662 if (rVal >>= aStrVal)
663 rData.SetURL(aStrVal);
665 else if (rName == SC_UNONAME_REPR)
667 if (rVal >>= aStrVal)
668 rData.SetRepresentation(aStrVal);
670 else if (rName == SC_UNONAME_TARGET)
672 if (rVal >>= aStrVal)
673 rData.SetTargetFrame(aStrVal);
675 else
676 throw beans::UnknownPropertyException(rName);
679 uno::Any ScEditFieldObj::getPropertyValueURL(const OUString& rName)
681 uno::Any aRet;
683 // anchor type is always "as character", text wrap always "none"
685 if (mpEditSource)
687 //! Field functions have to be passed to the forwarder !!!
688 ScEditEngineDefaulter* pEditEngine = mpEditSource->GetEditEngine();
689 ScUnoEditEngine aTempEngine(pEditEngine);
691 // don't care about the type (only URLs can be found in the cells)
692 const SvxFieldData* pField = aTempEngine.FindByPos(
693 aSelection.nStartPara, aSelection.nStartPos, text::textfield::Type::UNSPECIFIED);
694 OSL_ENSURE(pField,"getPropertyValue: Field not found");
695 if (!pField)
696 throw uno::RuntimeException();
698 if (pField->GetClassId() != text::textfield::Type::URL)
699 throw uno::RuntimeException();
701 const SvxURLField* pURL = static_cast<const SvxURLField*>(pField);
703 if (rName == SC_UNONAME_URL)
704 aRet <<= pURL->GetURL();
705 else if (rName == SC_UNONAME_REPR)
706 aRet <<= pURL->GetRepresentation();
707 else if (rName == SC_UNONAME_TARGET)
708 aRet <<= pURL->GetTargetFrame();
709 else
710 throw beans::UnknownPropertyException(rName);
712 else // not inserted yet
714 const SvxURLField& rURL = static_cast<const SvxURLField&>(getData());
716 if (rName == SC_UNONAME_URL)
717 aRet <<= rURL.GetURL();
718 else if (rName == SC_UNONAME_REPR)
719 aRet <<= rURL.GetRepresentation();
720 else if (rName == SC_UNONAME_TARGET)
721 aRet <<= rURL.GetTargetFrame();
722 else
723 throw beans::UnknownPropertyException(rName);
725 return aRet;
728 void ScEditFieldObj::setPropertyValueFile(const OUString& rName, const uno::Any& rVal)
730 if (rName != SC_UNONAME_FILEFORM)
731 throw beans::UnknownPropertyException(rName);
733 sal_Int16 nIntVal = 0;
734 if (!(rVal >>= nIntVal))
735 return;
737 SvxFileFormat eFormat = lcl_UnoToSvxFileFormat(nIntVal);
738 if (mpEditSource)
740 ScEditEngineDefaulter* pEditEngine = mpEditSource->GetEditEngine();
741 ScUnoEditEngine aTempEngine(pEditEngine);
742 SvxFieldData* pField = aTempEngine.FindByPos(
743 aSelection.nStartPara, aSelection.nStartPos, text::textfield::Type::EXTENDED_FILE);
744 OSL_ENSURE(pField, "setPropertyValueFile: Field not found");
745 if (pField)
747 SvxExtFileField* pExtFile = static_cast<SvxExtFileField*>(pField); // local to the ScUnoEditEngine
748 pExtFile->SetFormat(eFormat);
749 pEditEngine->QuickInsertField(SvxFieldItem(*pField, EE_FEATURE_FIELD), aSelection);
750 mpEditSource->UpdateData();
753 else
755 SvxExtFileField& rExtFile = static_cast<SvxExtFileField&>(getData());
756 rExtFile.SetFormat(eFormat);
761 uno::Any ScEditFieldObj::getPropertyValueFile(const OUString& rName)
763 uno::Any aRet;
764 if (rName != SC_UNONAME_FILEFORM)
765 throw beans::UnknownPropertyException(rName);
767 SvxFileFormat eFormat = SvxFileFormat::NameAndExt;
768 const SvxFieldData* pField = nullptr;
769 if (mpEditSource)
771 ScEditEngineDefaulter* pEditEngine = mpEditSource->GetEditEngine();
772 ScUnoEditEngine aTempEngine(pEditEngine);
773 pField = aTempEngine.FindByPos(
774 aSelection.nStartPara, aSelection.nStartPos, text::textfield::Type::EXTENDED_FILE);
776 else
777 pField = &getData();
779 OSL_ENSURE(pField, "setPropertyValueFile: Field not found");
780 if (!pField)
781 throw uno::RuntimeException();
783 const SvxExtFileField* pExtFile = static_cast<const SvxExtFileField*>(pField);
784 eFormat = pExtFile->GetFormat();
785 sal_Int16 nIntVal = lcl_SvxToUnoFileFormat(eFormat);
786 aRet <<= nIntVal;
788 return aRet;
791 void ScEditFieldObj::setPropertyValueDateTime(const OUString& rName, const uno::Any& rVal)
793 if (mpEditSource)
795 // Field already inserted.
796 ScEditEngineDefaulter* pEditEngine = mpEditSource->GetEditEngine();
797 ScUnoEditEngine aTempEngine(pEditEngine);
798 SvxFieldData* pField = aTempEngine.FindByPos(aSelection.nStartPara, aSelection.nStartPos, meType);
799 if (!pField)
800 return;
802 switch (meType)
804 case text::textfield::Type::DATE:
806 SvxDateField* p = static_cast<SvxDateField*>(pField);
807 if (rName == SC_UNONAME_ISDATE)
809 // Do nothing for now.
811 else if (rName == SC_UNONAME_ISFIXED)
813 SvxDateType eType = rVal.get<bool>() ? SvxDateType::Fix : SvxDateType::Var;
814 p->SetType(eType);
816 else if (rName == SC_UNONAME_DATETIME)
818 maDateTime = rVal.get<util::DateTime>();
819 Date aDate(maDateTime.Day, maDateTime.Month, maDateTime.Year);
820 p->SetFixDate(aDate);
822 else if (rName == SC_UNONAME_NUMFMT)
824 mnNumFormat = rVal.get<sal_Int32>();
825 p->SetFormat(static_cast<SvxDateFormat>(mnNumFormat));
827 else
828 throw beans::UnknownPropertyException(rName);
830 break;
831 case text::textfield::Type::TIME:
833 // SvxTimeField doesn't have any attributes.
834 if (rName != SC_UNONAME_ISDATE && rName != SC_UNONAME_ISFIXED &&
835 rName != SC_UNONAME_DATETIME && rName != SC_UNONAME_NUMFMT)
836 throw beans::UnknownPropertyException(rName);
838 break;
839 case text::textfield::Type::EXTENDED_TIME:
841 SvxExtTimeField* p = static_cast<SvxExtTimeField*>(pField);
842 if (rName == SC_UNONAME_ISDATE)
844 // Do nothing for now.
846 else if (rName == SC_UNONAME_ISFIXED)
848 SvxTimeType eType = rVal.get<bool>() ? SvxTimeType::Fix : SvxTimeType::Var;
849 p->SetType(eType);
851 else if (rName == SC_UNONAME_DATETIME)
853 maDateTime = rVal.get<util::DateTime>();
854 tools::Time aTime(maDateTime);
855 p->SetFixTime(aTime);
857 else if (rName == SC_UNONAME_NUMFMT)
859 mnNumFormat = rVal.get<sal_Int32>();
860 p->SetFormat(static_cast<SvxTimeFormat>(mnNumFormat));
862 else
863 throw beans::UnknownPropertyException(rName);
865 break;
866 default:
867 throw beans::UnknownPropertyException(rName);
870 else
872 if (rName == SC_UNONAME_ISDATE)
873 mbIsDate = rVal.get<bool>();
874 else if (rName == SC_UNONAME_ISFIXED)
875 mbIsFixed = rVal.get<bool>();
876 else if (rName == SC_UNONAME_DATETIME)
877 maDateTime = rVal.get<util::DateTime>();
878 else if (rName == SC_UNONAME_NUMFMT)
879 mnNumFormat = rVal.get<sal_Int32>();
880 else
881 throw beans::UnknownPropertyException(rName);
885 uno::Any ScEditFieldObj::getPropertyValueDateTime(const OUString& rName)
887 if (mpEditSource)
889 // Field already inserted.
890 ScEditEngineDefaulter* pEditEngine = mpEditSource->GetEditEngine();
891 ScUnoEditEngine aTempEngine(pEditEngine);
892 SvxFieldData* pField = aTempEngine.FindByPos(aSelection.nStartPara, aSelection.nStartPos, meType);
893 if (!pField)
894 throw uno::RuntimeException();
896 switch (meType)
898 case text::textfield::Type::DATE:
900 SvxDateField* p = static_cast<SvxDateField*>(pField);
901 if (rName == SC_UNONAME_ISDATE)
902 return uno::Any(true);
904 if (rName == SC_UNONAME_ISFIXED)
905 return uno::Any(p->GetType() == SvxDateType::Fix);
907 if (rName == SC_UNONAME_DATETIME)
909 Date aD(p->GetFixDate());
910 maDateTime.Year = aD.GetYear();
911 maDateTime.Month = aD.GetMonth();
912 maDateTime.Day = aD.GetDay();
913 maDateTime.Hours = 0;
914 maDateTime.Minutes = 0;
915 maDateTime.Seconds = 0;
916 maDateTime.NanoSeconds = 0;
917 return uno::Any(maDateTime);
920 if (rName == SC_UNONAME_NUMFMT)
921 return uno::Any(static_cast<sal_Int32>(p->GetFormat()));
923 break;
924 case text::textfield::Type::TIME:
926 // SvxTimeField doesn't have any attributes.
927 if (rName == SC_UNONAME_ISDATE)
928 return uno::Any(false);
930 if (rName == SC_UNONAME_ISFIXED)
931 return uno::Any(false);
933 if (rName == SC_UNONAME_DATETIME)
934 // This is the best we can do.
935 return uno::Any(maDateTime);
937 if (rName == SC_UNONAME_NUMFMT)
938 // Same as above.
939 return uno::Any(sal_Int32(0));
941 break;
942 case text::textfield::Type::EXTENDED_TIME:
944 SvxExtTimeField* p = static_cast<SvxExtTimeField*>(pField);
945 if (rName == SC_UNONAME_ISDATE)
946 return uno::Any(false);
948 if (rName == SC_UNONAME_ISFIXED)
949 return uno::Any(p->GetType() == SvxTimeType::Fix);
951 if (rName == SC_UNONAME_DATETIME)
953 tools::Time aT(p->GetFixTime());
954 maDateTime.Year = 0;
955 maDateTime.Month = 0;
956 maDateTime.Day = 0;
957 maDateTime.Hours = aT.GetHour();
958 maDateTime.Minutes = aT.GetMin();
959 maDateTime.Seconds = aT.GetSec();
960 maDateTime.NanoSeconds = aT.GetNanoSec();
961 return uno::Any(maDateTime);
964 if (rName == SC_UNONAME_NUMFMT)
965 return uno::Any(static_cast<sal_Int32>(p->GetFormat()));
967 break;
968 default:
972 else
974 if (rName == SC_UNONAME_ISDATE)
975 return uno::Any(mbIsDate);
977 if (rName == SC_UNONAME_ISFIXED)
978 return uno::Any(mbIsFixed);
980 if (rName == SC_UNONAME_DATETIME)
981 return uno::Any(maDateTime);
983 if (rName == SC_UNONAME_NUMFMT)
984 return uno::Any(mnNumFormat);
987 throw beans::UnknownPropertyException(rName);
990 void ScEditFieldObj::setPropertyValueSheet(const OUString& rName, const uno::Any& rVal)
992 if (mpEditSource)
994 // Edit engine instance already exists for this field item. Use it.
995 ScEditEngineDefaulter* pEditEngine = mpEditSource->GetEditEngine();
996 ScUnoEditEngine aTempEngine(pEditEngine);
998 // don't care about the type (only URLs can be found in the cells)
999 SvxFieldData* pField = aTempEngine.FindByPos(
1000 aSelection.nStartPara, aSelection.nStartPos, text::textfield::Type::UNSPECIFIED);
1001 OSL_ENSURE(pField,"setPropertyValue: Field not found");
1002 if (!pField)
1003 return;
1005 if (pField->GetClassId() != text::textfield::Type::TABLE)
1006 // Make sure this is indeed a URL field.
1007 return;
1009 SvxTableField* p = static_cast<SvxTableField*>(pField);
1011 if (rName != SC_UNONAME_TABLEPOS)
1012 throw beans::UnknownPropertyException(rName);
1014 sal_Int32 nTab = rVal.get<sal_Int32>();
1015 p->SetTab(nTab);
1018 pEditEngine->QuickInsertField(SvxFieldItem(*pField, EE_FEATURE_FIELD), aSelection);
1019 mpEditSource->UpdateData();
1020 return;
1023 // Edit engine instance not yet present. Store the item data for later use.
1024 SvxTableField& r = static_cast<SvxTableField&>(getData());
1025 if (rName != SC_UNONAME_TABLEPOS)
1026 throw beans::UnknownPropertyException(rName);
1028 sal_Int32 nTab = rVal.get<sal_Int32>();
1029 r.SetTab(nTab);
1032 ScEditFieldObj::ScEditFieldObj(
1033 uno::Reference<text::XTextRange> xContent,
1034 std::unique_ptr<ScEditSource> pEditSrc, sal_Int32 eType, const ESelection& rSel) :
1035 pPropSet(nullptr),
1036 mpEditSource(std::move(pEditSrc)),
1037 aSelection(rSel),
1038 meType(eType), mpContent(std::move(xContent)), mnNumFormat(0), mbIsDate(false), mbIsFixed(false)
1040 switch (meType)
1042 case text::textfield::Type::DOCINFO_TITLE:
1043 pPropSet = getEmptyPropertySet();
1044 break;
1045 case text::textfield::Type::EXTENDED_FILE:
1046 pPropSet = lcl_GetFileFieldPropertySet();
1047 break;
1048 case text::textfield::Type::URL:
1049 pPropSet = lcl_GetURLPropertySet();
1050 break;
1051 case text::textfield::Type::DATE:
1052 case text::textfield::Type::TIME:
1053 case text::textfield::Type::EXTENDED_TIME:
1054 pPropSet = getDateTimePropertySet();
1055 break;
1056 default:
1057 pPropSet = lcl_GetHeaderFieldPropertySet();
1060 if (meType == text::textfield::Type::DATE)
1061 mbIsDate = true;
1064 void ScEditFieldObj::InitDoc(
1065 const uno::Reference<text::XTextRange>& rContent, std::unique_ptr<ScEditSource> pEditSrc, const ESelection& rSel)
1067 if (!mpEditSource)
1069 mpContent = rContent;
1070 mpData.reset();
1072 aSelection = rSel;
1073 mpEditSource = std::move( pEditSrc );
1077 ScEditFieldObj::~ScEditFieldObj()
1081 SvxFieldItem ScEditFieldObj::CreateFieldItem()
1083 OSL_ENSURE( !mpEditSource, "CreateFieldItem with inserted field" );
1084 return SvxFieldItem(getData(), EE_FEATURE_FIELD);
1087 void ScEditFieldObj::DeleteField()
1089 if (mpEditSource)
1091 SvxTextForwarder* pForwarder = mpEditSource->GetTextForwarder();
1092 pForwarder->QuickInsertText( OUString(), aSelection );
1093 mpEditSource->UpdateData();
1095 aSelection.nEndPara = aSelection.nStartPara;
1096 aSelection.nEndPos = aSelection.nStartPos;
1098 //! Broadcast in order to adjust selection in other objects
1099 //! (also for other actions)
1103 bool ScEditFieldObj::IsInserted() const
1105 return mpEditSource != nullptr;
1108 // XTextField
1110 OUString SAL_CALL ScEditFieldObj::getPresentation( sal_Bool bShowCommand )
1112 SolarMutexGuard aGuard;
1114 if (!mpEditSource)
1115 return OUString();
1117 //! Field functions have to be passed to the forwarder !!!
1118 ScEditEngineDefaulter* pEditEngine = mpEditSource->GetEditEngine();
1119 ScUnoEditEngine aTempEngine(pEditEngine);
1121 // don't care about the type (only URLs can be found in the cells)
1122 const SvxFieldData* pField = aTempEngine.FindByPos(
1123 aSelection.nStartPara, aSelection.nStartPos, text::textfield::Type::UNSPECIFIED);
1124 OSL_ENSURE(pField,"getPresentation: Field not found");
1125 if (!pField)
1126 return OUString();
1128 switch (meType)
1130 case text::textfield::Type::URL:
1132 if (pField->GetClassId() != text::textfield::Type::URL)
1133 // Not a URL field, but URL is expected.
1134 throw uno::RuntimeException();
1136 const SvxURLField* pURL = static_cast<const SvxURLField*>(pField);
1137 return bShowCommand ? pURL->GetURL() : pURL->GetRepresentation();
1139 break;
1140 default:
1143 return OUString();
1146 // XTextContent
1148 void SAL_CALL ScEditFieldObj::attach( const uno::Reference<text::XTextRange>& xTextRange )
1150 SolarMutexGuard aGuard;
1151 if (xTextRange.is())
1153 uno::Reference<text::XText> xText(xTextRange->getText());
1154 if (xText.is())
1156 xText->insertTextContent( xTextRange, this, true );
1161 uno::Reference<text::XTextRange> SAL_CALL ScEditFieldObj::getAnchor()
1163 SolarMutexGuard aGuard;
1164 return mpContent;
1167 // XPropertySet
1169 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScEditFieldObj::getPropertySetInfo()
1171 SolarMutexGuard aGuard;
1172 uno::Reference<beans::XPropertySetInfo> aRef = pPropSet->getPropertySetInfo();
1173 return aRef;
1176 void SAL_CALL ScEditFieldObj::setPropertyValue(
1177 const OUString& aPropertyName, const uno::Any& aValue )
1179 SolarMutexGuard aGuard;
1180 if (aPropertyName == SC_UNONAME_ANCHOR)
1182 aValue >>= mpContent;
1183 return;
1186 switch (meType)
1188 case text::textfield::Type::URL:
1189 setPropertyValueURL(aPropertyName, aValue);
1190 break;
1191 case text::textfield::Type::EXTENDED_FILE:
1192 setPropertyValueFile(aPropertyName, aValue);
1193 break;
1194 case text::textfield::Type::DATE:
1195 case text::textfield::Type::TIME:
1196 case text::textfield::Type::EXTENDED_TIME:
1197 setPropertyValueDateTime(aPropertyName, aValue);
1198 break;
1199 case text::textfield::Type::TABLE:
1200 setPropertyValueSheet(aPropertyName, aValue);
1201 break;
1202 case text::textfield::Type::DOCINFO_TITLE:
1203 default:
1204 throw beans::UnknownPropertyException(OUString::number(meType));
1208 uno::Any SAL_CALL ScEditFieldObj::getPropertyValue( const OUString& aPropertyName )
1210 SolarMutexGuard aGuard;
1211 if (aPropertyName == SC_UNONAME_TEXTFIELD_TYPE)
1212 return uno::Any(meType);
1214 if (aPropertyName == SC_UNONAME_ANCHOR)
1215 return uno::Any(mpContent);
1217 if (aPropertyName == SC_UNONAME_ANCTYPE)
1219 uno::Any aRet;
1220 aRet <<= text::TextContentAnchorType_AS_CHARACTER;
1221 return aRet;
1223 if (aPropertyName == SC_UNONAME_ANCTYPES)
1225 uno::Any aRet;
1226 uno::Sequence<text::TextContentAnchorType> aSeq { text::TextContentAnchorType_AS_CHARACTER };
1227 aRet <<= aSeq;
1228 return aRet;
1230 if (aPropertyName == SC_UNONAME_TEXTWRAP)
1232 uno::Any aRet;
1233 aRet <<= text::WrapTextMode_NONE;
1234 return aRet;
1237 switch (meType)
1239 case text::textfield::Type::URL:
1240 return getPropertyValueURL(aPropertyName);
1241 case text::textfield::Type::EXTENDED_FILE:
1242 return getPropertyValueFile(aPropertyName);
1243 case text::textfield::Type::DATE:
1244 case text::textfield::Type::TIME:
1245 case text::textfield::Type::EXTENDED_TIME:
1246 return getPropertyValueDateTime(aPropertyName);
1247 case text::textfield::Type::DOCINFO_TITLE:
1248 default:
1249 throw beans::UnknownPropertyException(OUString::number(meType));
1253 SC_IMPL_DUMMY_PROPERTY_LISTENER( ScEditFieldObj )
1255 // XUnoTunnel
1257 UNO3_GETIMPLEMENTATION_IMPL(ScEditFieldObj);
1259 // XServiceInfo
1261 OUString SAL_CALL ScEditFieldObj::getImplementationName()
1263 return "ScEditFieldObj";
1266 sal_Bool SAL_CALL ScEditFieldObj::supportsService( const OUString& rServiceName )
1268 return cppu::supportsService(this, rServiceName);
1271 uno::Sequence<OUString> SAL_CALL ScEditFieldObj::getSupportedServiceNames()
1273 return {"com.sun.star.text.TextField",
1274 "com.sun.star.text.TextContent"};
1277 uno::Sequence<uno::Type> SAL_CALL ScEditFieldObj::getTypes()
1279 return comphelper::concatSequences(
1280 ScEditFieldObj_Base::getTypes(),
1281 uno::Sequence<uno::Type>
1283 cppu::UnoType<text::XTextField>::get(),
1284 cppu::UnoType<beans::XPropertySet>::get(),
1285 cppu::UnoType<lang::XUnoTunnel>::get(),
1286 cppu::UnoType<lang::XServiceInfo>::get()
1287 } );
1290 uno::Sequence<sal_Int8> SAL_CALL ScEditFieldObj::getImplementationId()
1292 return css::uno::Sequence<sal_Int8>();
1295 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */