Bump version to 24.04.3.4
[LibreOffice.git] / sfx2 / source / devtools / ObjectInspectorTreeHandler.cxx
blobc5aa79c2d0360c7528408fc999cac1828d288d01
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 */
11 #include <memory>
13 #include <sfx2/devtools/ObjectInspectorTreeHandler.hxx>
14 #include <sfx2/sfxresid.hxx>
15 #include <utility>
16 #include <vcl/svapp.hxx>
17 #include "DevToolsStrings.hrc"
19 #include <com/sun/star/beans/theIntrospection.hpp>
20 #include <com/sun/star/beans/XIntrospection.hpp>
21 #include <com/sun/star/beans/XIntrospectionAccess.hpp>
22 #include <com/sun/star/beans/PropertyConcept.hpp>
23 #include <com/sun/star/beans/PropertyAttribute.hpp>
24 #include <com/sun/star/beans/MethodConcept.hpp>
26 #include <com/sun/star/reflection/theCoreReflection.hpp>
27 #include <com/sun/star/reflection/XIdlReflection.hpp>
28 #include <com/sun/star/reflection/XIdlMethod.hpp>
29 #include <com/sun/star/reflection/XIdlArray.hpp>
30 #include <com/sun/star/reflection/XEnumTypeDescription.hpp>
32 #include <com/sun/star/container/XNamed.hpp>
33 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
34 #include <com/sun/star/container/XIndexAccess.hpp>
35 #include <com/sun/star/container/XNameAccess.hpp>
36 #include <com/sun/star/container/XEnumerationAccess.hpp>
38 #include <com/sun/star/script/Invocation.hpp>
39 #include <com/sun/star/script/XInvocation2.hpp>
40 #include <com/sun/star/script/MemberType.hpp>
42 #include <com/sun/star/lang/XServiceInfo.hpp>
43 #include <com/sun/star/lang/XTypeProvider.hpp>
45 #include <comphelper/processfactory.hxx>
46 #include <comphelper/extract.hxx>
48 #include <vcl/settings.hxx>
49 #include <i18nlangtag/languagetag.hxx>
51 using namespace css;
53 namespace
55 constexpr OUStringLiteral constTypeDescriptionManagerSingletonName
56 = u"/singletons/com.sun.star.reflection.theTypeDescriptionManager";
58 OUString enumValueToEnumName(uno::Any const& aValue,
59 uno::Reference<uno::XComponentContext> const& xContext)
61 sal_Int32 nIntValue = 0;
62 if (!cppu::enum2int(nIntValue, aValue))
63 return OUString();
65 uno::Reference<container::XHierarchicalNameAccess> xManager;
66 xManager.set(xContext->getValueByName(constTypeDescriptionManagerSingletonName),
67 uno::UNO_QUERY);
69 uno::Reference<reflection::XEnumTypeDescription> xTypeDescription;
70 xTypeDescription.set(xManager->getByHierarchicalName(aValue.getValueType().getTypeName()),
71 uno::UNO_QUERY);
73 const uno::Sequence<sal_Int32> aValues = xTypeDescription->getEnumValues();
74 sal_Int32 nValuesIndex = std::find(aValues.begin(), aValues.end(), nIntValue) - aValues.begin();
75 uno::Sequence<OUString> aNames = xTypeDescription->getEnumNames();
76 return aNames[nValuesIndex];
79 OUString getInterfaceImplementationClass(uno::Reference<uno::XInterface> const& xInterface)
81 auto xServiceInfo = uno::Reference<lang::XServiceInfo>(xInterface, uno::UNO_QUERY);
82 if (xServiceInfo.is())
83 return xServiceInfo->getImplementationName();
84 return OUString();
87 /** converts basic any value to a string */
88 OUString convertBasicValueToString(const uno::Any& aValue,
89 const uno::Reference<uno::XComponentContext>& xContext)
91 OUString aRetStr;
93 // return early if we don't have any value
94 if (!aValue.hasValue())
95 return SfxResId(STR_ANY_VALUE_NULL);
97 uno::TypeClass eType = aValue.getValueTypeClass();
99 switch (eType)
101 case uno::TypeClass_BOOLEAN:
103 bool bBool = aValue.get<bool>();
104 aRetStr = bBool ? SfxResId(STR_ANY_VALUE_TRUE) : SfxResId(STR_ANY_VALUE_FALSE);
105 break;
107 case uno::TypeClass_CHAR:
109 sal_Unicode aChar = aValue.get<sal_Unicode>();
110 aRetStr = OUString::number(aChar);
111 break;
113 case uno::TypeClass_STRING:
115 aRetStr = u"\"" + aValue.get<OUString>() + u"\"";
116 break;
118 case uno::TypeClass_FLOAT:
120 auto aNumber = aValue.get<float>();
121 aRetStr = OUString::number(aNumber);
122 break;
124 case uno::TypeClass_DOUBLE:
126 auto aNumber = aValue.get<double>();
127 aRetStr = OUString::number(aNumber);
128 break;
130 case uno::TypeClass_BYTE:
132 auto aNumber = aValue.get<sal_Int8>();
133 aRetStr = OUString::number(aNumber);
134 break;
136 case uno::TypeClass_SHORT:
138 auto aNumber = aValue.get<sal_Int16>();
139 aRetStr = OUString::number(aNumber);
140 break;
142 case uno::TypeClass_LONG:
144 auto aNumber = aValue.get<sal_Int32>();
145 aRetStr = OUString::number(aNumber);
146 break;
148 case uno::TypeClass_HYPER:
150 auto aNumber = aValue.get<sal_Int64>();
151 aRetStr = OUString::number(aNumber);
152 break;
154 case uno::TypeClass_UNSIGNED_SHORT:
156 auto aNumber = aValue.get<sal_uInt16>();
157 aRetStr = OUString::number(aNumber);
158 break;
160 case uno::TypeClass_UNSIGNED_LONG:
162 auto aNumber = aValue.get<sal_uInt32>();
163 aRetStr = OUString::number(aNumber);
164 break;
166 case uno::TypeClass_UNSIGNED_HYPER:
168 auto aNumber = aValue.get<sal_uInt64>();
169 aRetStr = OUString::number(aNumber);
170 break;
172 case uno::TypeClass_TYPE:
174 auto aType = aValue.get<uno::Type>();
175 aRetStr = aType.getTypeName();
176 break;
178 case uno::TypeClass_ENUM:
180 aRetStr = enumValueToEnumName(aValue, xContext);
181 break;
184 default:
185 break;
187 return aRetStr;
190 // returns a name of the object, if available
191 OUString getInterfaceName(uno::Reference<uno::XInterface> const& xInterface,
192 const uno::Reference<uno::XComponentContext>& xContext)
194 uno::Reference<container::XNamed> xNamed(xInterface, uno::UNO_QUERY);
195 if (xNamed.is())
196 return xNamed->getName();
198 auto xInvocationFactory = css::script::Invocation::create(xContext);
199 uno::Sequence<uno::Any> aParameters = { uno::Any(xInterface) };
200 auto xInvocationInterface = xInvocationFactory->createInstanceWithArguments(aParameters);
201 if (xInvocationInterface.is())
203 uno::Reference<script::XInvocation2> xInvocation(xInvocationInterface, uno::UNO_QUERY);
204 if (xInvocation.is() && xInvocation->hasProperty("Name"))
206 uno::Any aAny = xInvocation->getValue("Name");
207 if (aAny.hasValue() && aAny.getValueTypeClass() == uno::TypeClass_STRING)
208 return aAny.get<OUString>();
211 return OUString();
214 OUString convertAnyToString(const uno::Any& aValue,
215 const uno::Reference<uno::XComponentContext>& xContext)
217 // return early if we don't have any value
218 if (!aValue.hasValue())
219 return SfxResId(STR_ANY_VALUE_NULL);
221 OUString aRetStr;
223 uno::TypeClass eType = aValue.getValueTypeClass();
225 switch (eType)
227 case uno::TypeClass_INTERFACE:
229 uno::Reference<uno::XInterface> xInterface(aValue, uno::UNO_QUERY);
230 if (!xInterface.is())
231 aRetStr = SfxResId(STR_ANY_VALUE_NULL);
232 else
234 OUString aImplementationClass = getInterfaceImplementationClass(xInterface);
235 if (aImplementationClass.isEmpty())
236 aImplementationClass = SfxResId(STR_CLASS_UNKNOWN);
237 aRetStr
238 = SfxResId(STR_PROPERTY_VALUE_OBJECT).replaceFirst("%1", aImplementationClass);
240 OUString aString = getInterfaceName(xInterface, xContext);
241 if (!aString.isEmpty())
242 aRetStr += " {" + aString + "}";
244 break;
246 case uno::TypeClass_STRUCT:
248 aRetStr = SfxResId(STR_PROPERTY_VALUE_STRUCT);
249 break;
251 default:
253 aRetStr = convertBasicValueToString(aValue, xContext);
254 break;
257 return aRetStr;
260 OUString convertAnyToShortenedString(const uno::Any& aValue,
261 const uno::Reference<uno::XComponentContext>& xContext)
263 // return early if we don't have any value
264 if (!aValue.hasValue())
265 return SfxResId(STR_ANY_VALUE_NULL);
267 OUString aRetStr;
269 uno::TypeClass eType = aValue.getValueTypeClass();
271 constexpr const sal_Int32 constMaxStringLength = 60;
273 switch (eType)
275 case uno::TypeClass_INTERFACE:
277 aRetStr = convertAnyToString(aValue, xContext);
279 if (aRetStr.getLength() > constMaxStringLength + 3)
280 aRetStr = OUString::Concat(aRetStr.subView(0, constMaxStringLength)) + u"...";
281 break;
283 case uno::TypeClass_STRING:
285 OUString aString = convertAnyToString(aValue, xContext);
286 if (aString.getLength() > constMaxStringLength + 4)
287 aString = OUString::Concat(aString.subView(0, constMaxStringLength)) + u"\"...";
288 aRetStr = aString.replaceAll("\n", " ");
289 break;
291 default:
293 aRetStr = convertAnyToString(aValue, xContext);
294 break;
297 return aRetStr;
300 /** converts an any's type to a string (in a short form) */
301 OUString getAnyType(const uno::Any& aValue)
303 OUString aTypeName = aValue.getValueType().getTypeName();
304 return aTypeName.replaceAll("com.sun.star", "css");
307 /** converts a Type to a XIdlClass */
308 uno::Reference<reflection::XIdlClass>
309 convertTypeToIdlClass(const uno::Type& rType,
310 const uno::Reference<uno::XComponentContext>& xContext)
312 auto xReflection = reflection::theCoreReflection::get(xContext);
313 return xReflection->forName(rType.getTypeName());
316 // Object inspector nodes
318 /** Object inspector node's main interface
320 * The interface for the "attached" object to a tree view nodes that
321 * are added to the tree views of the object inspector part. The node
322 * can return the main value of the node (object name) and if present
323 * also the values for additional columns. It signals if a tree needs
324 * an expander and fills the children of the tree is any exists.
327 class ObjectInspectorNodeInterface
329 public:
330 ObjectInspectorNodeInterface() = default;
332 virtual ~ObjectInspectorNodeInterface() {}
334 // main value (object name) of the tree view node
335 virtual OUString getObjectName() = 0;
337 // should show the expander for the tree view node
338 virtual bool shouldShowExpander() { return false; }
340 // fill the children for the current tree view node
341 virtual void fillChildren(std::unique_ptr<weld::TreeView>& rTree, const weld::TreeIter* pParent)
342 = 0;
344 // fill any additional column values for the current tree view node
345 virtual std::vector<std::pair<sal_Int32, OUString>> getColumnValues()
347 return std::vector<std::pair<sal_Int32, OUString>>();
351 // appends the node to the root of the tree view
352 OUString lclAppendNode(const std::unique_ptr<weld::TreeView>& pTree,
353 ObjectInspectorNodeInterface* pEntry)
355 OUString sName = pEntry->getObjectName();
356 OUString sId(weld::toId(pEntry));
357 std::unique_ptr<weld::TreeIter> pCurrent = pTree->make_iterator();
358 pTree->insert(nullptr, -1, &sName, &sId, nullptr, nullptr, pEntry->shouldShowExpander(),
359 pCurrent.get());
360 pTree->set_text_emphasis(*pCurrent, true, 0);
362 for (auto const& rPair : pEntry->getColumnValues())
364 pTree->set_text(*pCurrent, rPair.second, rPair.first);
367 return sId;
370 // appends the node to the parent
371 OUString lclAppendNodeToParent(const std::unique_ptr<weld::TreeView>& pTree,
372 const weld::TreeIter* pParent, ObjectInspectorNodeInterface* pEntry)
374 OUString sName = pEntry->getObjectName();
375 OUString sId(weld::toId(pEntry));
376 std::unique_ptr<weld::TreeIter> pCurrent = pTree->make_iterator();
377 pTree->insert(pParent, -1, &sName, &sId, nullptr, nullptr, pEntry->shouldShowExpander(),
378 pCurrent.get());
379 pTree->set_text_emphasis(*pCurrent, true, 0);
381 for (auto const& rPair : pEntry->getColumnValues())
383 pTree->set_text(*pCurrent, rPair.second, rPair.first);
386 return sId;
389 /** Node that represent just a simple string with no children or columns */
390 class SimpleStringNode : public ObjectInspectorNodeInterface
392 protected:
393 OUString msName;
395 public:
396 SimpleStringNode(OUString sName)
397 : msName(std::move(sName))
401 void fillChildren(std::unique_ptr<weld::TreeView>& /*rTree*/,
402 const weld::TreeIter* /*pParent*/) override
406 OUString getObjectName() override { return msName; }
409 /** Node represents a method of an object */
410 class MethodNode : public ObjectInspectorNodeInterface
412 private:
413 uno::Reference<reflection::XIdlMethod> mxMethod;
415 public:
416 MethodNode(uno::Reference<reflection::XIdlMethod> xMethod)
417 : mxMethod(std::move(xMethod))
421 OUString getObjectName() override { return mxMethod->getName(); }
423 static OUString simpleTypeName(uno::Reference<reflection::XIdlClass> const& xClass)
425 switch (xClass->getTypeClass())
427 case uno::TypeClass_INTERFACE:
428 return SfxResId(STR_METHOD_TYPE_OBJECT);
429 case uno::TypeClass_STRUCT:
430 return SfxResId(STR_METHOD_TYPE_STRUCT);
431 case uno::TypeClass_ENUM:
432 return SfxResId(STR_METHOD_TYPE_ENUM);
433 case uno::TypeClass_SEQUENCE:
434 return SfxResId(STR_METHOD_TYPE_SEQUENCE);
435 default:
436 break;
438 return xClass->getName();
441 std::vector<std::pair<sal_Int32, OUString>> getColumnValues() override
443 OUString aOutString;
444 auto xClass = mxMethod->getReturnType();
445 aOutString = simpleTypeName(xClass);
447 OUString aInString;
448 const auto aParameters = mxMethod->getParameterInfos();
449 bool bFirst = true;
450 for (auto const& rParameterInfo : aParameters)
452 if (!bFirst)
453 aInString += ", ";
454 else
455 bFirst = false;
457 switch (rParameterInfo.aMode)
459 case reflection::ParamMode_IN:
460 aInString += SfxResId(STR_PARMETER_MODE_IN) + " ";
461 break;
462 case reflection::ParamMode_OUT:
463 aInString += SfxResId(STR_PARMETER_MODE_OUT) + " ";
464 break;
465 case reflection::ParamMode_INOUT:
466 aInString += SfxResId(STR_PARMETER_MODE_IN_AND_OUT) + " ";
467 break;
468 default:
469 break;
472 aInString += rParameterInfo.aName + " : " + simpleTypeName(rParameterInfo.aType);
475 OUString aImplementationClass = mxMethod->getDeclaringClass()->getName();
477 return {
478 { 1, aOutString },
479 { 2, aInString },
480 { 3, aImplementationClass },
484 void fillChildren(std::unique_ptr<weld::TreeView>& /*rTree*/,
485 const weld::TreeIter* /*pParent*/) override
490 /** Node represents a class (XIdlClass) of an object.
492 * Children are superclasses of the current class. XInterface superclass
493 * is ignored.
496 class ClassNode : public ObjectInspectorNodeInterface
498 private:
499 uno::Reference<reflection::XIdlClass> mxClass;
501 static bool isXInterface(uno::Reference<reflection::XIdlClass> const& xClass)
503 return xClass->getName() == "com.sun.star.uno.XInterface";
506 public:
507 ClassNode(uno::Reference<reflection::XIdlClass> xClass)
508 : mxClass(std::move(xClass))
512 bool shouldShowExpander() override
514 auto const& xSuperClasses = mxClass->getSuperclasses();
515 return xSuperClasses.getLength() > 2
516 || (xSuperClasses.getLength() == 1 && !isXInterface(xSuperClasses[0]));
519 OUString getObjectName() override { return mxClass->getName(); }
521 // Fill superclasses
522 void fillChildren(std::unique_ptr<weld::TreeView>& rTree,
523 const weld::TreeIter* pParent) override
525 auto const& xSuperClasses = mxClass->getSuperclasses();
526 for (auto const& xSuper : xSuperClasses)
528 if (!isXInterface(xSuper))
529 lclAppendNodeToParent(rTree, pParent, new ClassNode(xSuper));
534 /** Node represents a basic value, that can be any object, sequence, struct */
535 class BasicValueNode : public SimpleStringNode
537 protected:
538 uno::Any maAny;
539 OUString mrInfo;
540 uno::Reference<uno::XComponentContext> mxContext;
542 ObjectInspectorNodeInterface*
543 createNodeObjectForAny(OUString const& rName, const uno::Any& rAny, OUString const& mrInfo);
545 public:
546 BasicValueNode(OUString const& rName, uno::Any aAny, OUString aInfo,
547 uno::Reference<uno::XComponentContext> xContext)
548 : SimpleStringNode(rName)
549 , maAny(std::move(aAny))
550 , mrInfo(std::move(aInfo))
551 , mxContext(std::move(xContext))
555 const uno::Any& getAny() const { return maAny; }
557 bool shouldShowExpander() override
559 if (maAny.hasValue())
561 switch (maAny.getValueType().getTypeClass())
563 case uno::TypeClass_INTERFACE:
565 uno::Reference<uno::XInterface> xInterface(maAny, uno::UNO_QUERY);
566 return xInterface.is();
568 case uno::TypeClass_SEQUENCE:
569 return true;
570 default:
571 break;
574 return false;
577 std::vector<std::pair<sal_Int32, OUString>> getColumnValues() override
579 OUString aValue = convertAnyToShortenedString(maAny, mxContext);
580 OUString aType = getAnyType(maAny);
582 return { { 1, aValue }, { 2, aType }, { 3, mrInfo } };
586 /** Node represents a property */
587 class GenericPropertiesNode : public BasicValueNode
589 public:
590 GenericPropertiesNode(OUString const& rName, uno::Any const& rAny, OUString const& rInfo,
591 uno::Reference<uno::XComponentContext> const& xContext)
592 : BasicValueNode(rName, rAny, rInfo, xContext)
596 void fillChildren(std::unique_ptr<weld::TreeView>& pTree,
597 const weld::TreeIter* pParent) override;
600 /** Node represents a struct */
601 class StructNode : public BasicValueNode
603 public:
604 StructNode(OUString const& rName, uno::Any const& rAny, OUString const& rInfo,
605 uno::Reference<uno::XComponentContext> const& xContext)
606 : BasicValueNode(rName, rAny, rInfo, xContext)
610 bool shouldShowExpander() override { return true; }
612 void fillChildren(std::unique_ptr<weld::TreeView>& pTree,
613 const weld::TreeIter* pParent) override;
616 /** Node represents a sequence */
617 class SequenceNode : public BasicValueNode
619 uno::Reference<reflection::XIdlArray> mxIdlArray;
621 public:
622 SequenceNode(OUString const& rName, uno::Any const& rAny, OUString const& rInfo,
623 uno::Reference<uno::XComponentContext> const& xContext)
624 : BasicValueNode(rName, rAny, rInfo, xContext)
626 auto xClass = convertTypeToIdlClass(maAny.getValueType(), mxContext);
627 mxIdlArray = xClass->getArray();
630 bool shouldShowExpander() override
632 // Show expander only if the sequence has elements
633 int nLength = mxIdlArray->getLen(maAny);
634 return nLength > 0;
637 void fillChildren(std::unique_ptr<weld::TreeView>& pTree,
638 const weld::TreeIter* pParent) override
640 int nLength = mxIdlArray->getLen(maAny);
642 for (int i = 0; i < nLength; i++)
644 uno::Any aArrayValue = mxIdlArray->get(maAny, i);
646 auto* pObjectInspectorNode
647 = createNodeObjectForAny(OUString::number(i), aArrayValue, "");
648 if (pObjectInspectorNode)
649 lclAppendNodeToParent(pTree, pParent, pObjectInspectorNode);
653 std::vector<std::pair<sal_Int32, OUString>> getColumnValues() override
655 int nLength = mxIdlArray->getLen(maAny);
657 OUString aType
658 = getAnyType(maAny).replaceAll(u"[]", u"") + u"[" + OUString::number(nLength) + u"]";
660 OUString aValue
661 = SfxResId(STR_PROPERTY_VALUE_SEQUENCE).replaceFirst("%1", OUString::number(nLength));
663 return {
664 { 1, aValue },
665 { 2, aType },
670 void GenericPropertiesNode::fillChildren(std::unique_ptr<weld::TreeView>& pTree,
671 const weld::TreeIter* pParent)
673 if (!maAny.hasValue())
674 return;
678 const auto xNameAccess = uno::Reference<container::XNameAccess>(maAny, uno::UNO_QUERY);
679 if (xNameAccess.is())
681 const uno::Sequence<OUString> aNames = xNameAccess->getElementNames();
682 for (OUString const& rName : aNames)
684 uno::Any aAny = xNameAccess->getByName(rName);
685 auto* pObjectInspectorNode = createNodeObjectForAny(
686 u"@" + rName, aAny, SfxResId(STR_PROPERTY_TYPE_IS_NAMED_CONTAINER));
687 lclAppendNodeToParent(pTree, pParent, pObjectInspectorNode);
691 catch (...)
697 const auto xIndexAccess = uno::Reference<container::XIndexAccess>(maAny, uno::UNO_QUERY);
698 if (xIndexAccess.is())
700 for (sal_Int32 nIndex = 0; nIndex < xIndexAccess->getCount(); ++nIndex)
702 uno::Any aAny = xIndexAccess->getByIndex(nIndex);
703 auto* pObjectInspectorNode
704 = createNodeObjectForAny(u"@" + OUString::number(nIndex), aAny,
705 SfxResId(STR_PROPERTY_TYPE_IS_INDEX_CONTAINER));
706 lclAppendNodeToParent(pTree, pParent, pObjectInspectorNode);
710 catch (...)
716 const auto xEnumAccess
717 = uno::Reference<container::XEnumerationAccess>(maAny, uno::UNO_QUERY);
718 if (xEnumAccess.is())
720 uno::Reference<container::XEnumeration> xEnumeration = xEnumAccess->createEnumeration();
721 if (xEnumeration.is())
723 for (sal_Int32 nIndex = 0; xEnumeration->hasMoreElements(); nIndex++)
725 uno::Any aAny = xEnumeration->nextElement();
726 auto* pObjectInspectorNode
727 = createNodeObjectForAny(u"@" + OUString::number(nIndex), aAny,
728 SfxResId(STR_PROPERTY_TYPE_IS_ENUMERATION));
729 lclAppendNodeToParent(pTree, pParent, pObjectInspectorNode);
734 catch (...)
738 auto xInvocationFactory = css::script::Invocation::create(mxContext);
739 uno::Sequence<uno::Any> aParameters = { maAny };
740 auto xInvocationInterface = xInvocationFactory->createInstanceWithArguments(aParameters);
741 if (!xInvocationInterface.is())
742 return;
744 uno::Reference<script::XInvocation2> xInvocation(xInvocationInterface, uno::UNO_QUERY);
745 if (!xInvocation.is())
746 return;
748 auto const& xInvocationAccess = xInvocation->getIntrospection();
749 if (!xInvocationAccess.is())
750 return;
752 uno::Sequence<script::InvocationInfo> aInvocationInfoSequence;
755 aInvocationInfoSequence = xInvocation->getInfo();
757 catch (...)
761 for (auto const& aInvocationInfo : std::as_const(aInvocationInfoSequence))
763 if (aInvocationInfo.eMemberType == script::MemberType_PROPERTY)
765 uno::Any aCurrentAny;
766 auto const& aPropertyName = aInvocationInfo.aName;
768 bool bIsAttribute = false;
769 bool bIsGetSetMethod = false;
770 bool bMethodGet = false;
771 bool bMethodSet = false;
772 bool bMethodIs = false;
775 aCurrentAny = xInvocation->getValue(aPropertyName);
776 bIsAttribute = xInvocationAccess->hasProperty(aPropertyName,
777 beans::PropertyConcept::ATTRIBUTES);
778 bIsGetSetMethod = xInvocationAccess->hasProperty(aPropertyName,
779 beans::PropertyConcept::METHODS);
780 if (bIsGetSetMethod)
782 bMethodGet = xInvocationAccess->hasMethod(u"get" + aPropertyName,
783 beans::MethodConcept::PROPERTY);
784 bMethodSet = xInvocationAccess->hasMethod(u"set" + aPropertyName,
785 beans::MethodConcept::PROPERTY);
786 bMethodIs = xInvocationAccess->hasMethod(u"is" + aPropertyName,
787 beans::MethodConcept::PROPERTY);
790 catch (...)
794 std::vector<OUString> aInfoCollection;
795 if (bIsAttribute)
796 aInfoCollection.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_IS_ATTRIBUTE));
797 if (bIsGetSetMethod)
799 bool bHasGet = false;
800 OUString aString;
801 if (bMethodGet || bMethodIs)
803 aString += SfxResId(STR_PROPERTY_ATTRIBUTE_GET);
804 bHasGet = true;
806 if (bMethodSet)
808 if (bHasGet)
809 aString += u"+";
810 aString += SfxResId(STR_PROPERTY_ATTRIBUTE_SET);
812 aInfoCollection.push_back(aString);
813 if (bMethodSet && !bHasGet)
814 aInfoCollection.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_WRITEONLY));
816 if (aInvocationInfo.PropertyAttribute & beans::PropertyAttribute::MAYBEVOID)
817 aInfoCollection.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_MAYBEVOID));
818 if (aInvocationInfo.PropertyAttribute & beans::PropertyAttribute::READONLY)
819 aInfoCollection.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_READONLY));
820 if (aInvocationInfo.PropertyAttribute & beans::PropertyAttribute::REMOVABLE)
821 aInfoCollection.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_REMOVABLE));
822 if (aInvocationInfo.PropertyAttribute & beans::PropertyAttribute::BOUND)
823 aInfoCollection.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_BOUND));
824 if (aInvocationInfo.PropertyAttribute & beans::PropertyAttribute::CONSTRAINED)
825 aInfoCollection.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_CONSTRAINED));
826 if (aInvocationInfo.PropertyAttribute & beans::PropertyAttribute::TRANSIENT)
827 aInfoCollection.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_TRANSIENT));
828 if (aInvocationInfo.PropertyAttribute & beans::PropertyAttribute::MAYBEAMBIGUOUS)
829 aInfoCollection.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_MAYBEAMBIGUOUS));
830 if (aInvocationInfo.PropertyAttribute & beans::PropertyAttribute::MAYBEDEFAULT)
831 aInfoCollection.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_MAYBEDEFAULT));
833 bool bSet = false;
834 OUString aInfoString;
835 for (auto const& rString : aInfoCollection)
837 if (bSet)
838 aInfoString += ", ";
839 else
840 bSet = true;
842 aInfoString += rString;
845 auto* pObjectInspectorNode
846 = createNodeObjectForAny(aPropertyName, aCurrentAny, aInfoString);
847 if (pObjectInspectorNode)
848 lclAppendNodeToParent(pTree, pParent, pObjectInspectorNode);
853 void StructNode::fillChildren(std::unique_ptr<weld::TreeView>& pTree, const weld::TreeIter* pParent)
855 auto xReflection = reflection::theCoreReflection::get(mxContext);
856 uno::Reference<reflection::XIdlClass> xClass
857 = xReflection->forName(maAny.getValueType().getTypeName());
859 const auto xFields = xClass->getFields();
861 for (auto const& xField : xFields)
863 OUString aFieldName = xField->getName();
864 uno::Any aFieldValue = xField->get(maAny);
866 auto* pObjectInspectorNode = createNodeObjectForAny(aFieldName, aFieldValue, "");
867 if (pObjectInspectorNode)
869 lclAppendNodeToParent(pTree, pParent, pObjectInspectorNode);
874 ObjectInspectorNodeInterface* BasicValueNode::createNodeObjectForAny(OUString const& rName,
875 const uno::Any& rAny,
876 OUString const& rInfo)
878 switch (rAny.getValueType().getTypeClass())
880 case uno::TypeClass_INTERFACE:
881 return new GenericPropertiesNode(rName, rAny, rInfo, mxContext);
883 case uno::TypeClass_SEQUENCE:
884 return new SequenceNode(rName, rAny, rInfo, mxContext);
886 case uno::TypeClass_STRUCT:
887 return new StructNode(rName, rAny, rInfo, mxContext);
889 default:
890 break;
893 return new BasicValueNode(rName, rAny, rInfo, mxContext);
896 } // end anonymous namespace
898 // Object inspector tree view helper functions
899 namespace
901 ObjectInspectorNodeInterface* getSelectedNode(weld::TreeView const& rTreeView)
903 OUString sID = rTreeView.get_selected_id();
904 if (sID.isEmpty())
905 return nullptr;
907 if (auto* pNode = weld::fromId<ObjectInspectorNodeInterface*>(sID))
908 return pNode;
910 return nullptr;
913 uno::Reference<uno::XInterface> getSelectedXInterface(weld::TreeView const& rTreeView)
915 uno::Reference<uno::XInterface> xInterface;
917 if (auto* pNode = getSelectedNode(rTreeView))
919 if (auto* pBasicValueNode = dynamic_cast<BasicValueNode*>(pNode))
921 uno::Any aAny = pBasicValueNode->getAny();
922 xInterface.set(aAny, uno::UNO_QUERY);
926 return xInterface;
929 } // end anonymous namespace
931 ObjectInspectorTreeHandler::ObjectInspectorTreeHandler(
932 std::unique_ptr<ObjectInspectorWidgets>& pObjectInspectorWidgets)
933 : mpObjectInspectorWidgets(pObjectInspectorWidgets)
934 , mxContext(comphelper::getProcessComponentContext())
935 , mxSorter(mxContext, Application::GetSettings().GetLanguageTag().getLocale())
937 mpObjectInspectorWidgets->mpInterfacesTreeView->connect_expanding(
938 LINK(this, ObjectInspectorTreeHandler, ExpandingHandlerInterfaces));
939 mpObjectInspectorWidgets->mpServicesTreeView->connect_expanding(
940 LINK(this, ObjectInspectorTreeHandler, ExpandingHandlerServices));
941 mpObjectInspectorWidgets->mpPropertiesTreeView->connect_expanding(
942 LINK(this, ObjectInspectorTreeHandler, ExpandingHandlerProperties));
943 mpObjectInspectorWidgets->mpMethodsTreeView->connect_expanding(
944 LINK(this, ObjectInspectorTreeHandler, ExpandingHandlerMethods));
946 mpObjectInspectorWidgets->mpPropertiesTreeView->connect_popup_menu(
947 LINK(this, ObjectInspectorTreeHandler, PopupMenuHandler));
949 mpObjectInspectorWidgets->mpInterfacesTreeView->connect_changed(
950 LINK(this, ObjectInspectorTreeHandler, SelectionChanged));
951 mpObjectInspectorWidgets->mpServicesTreeView->connect_changed(
952 LINK(this, ObjectInspectorTreeHandler, SelectionChanged));
953 mpObjectInspectorWidgets->mpPropertiesTreeView->connect_changed(
954 LINK(this, ObjectInspectorTreeHandler, SelectionChanged));
955 mpObjectInspectorWidgets->mpMethodsTreeView->connect_changed(
956 LINK(this, ObjectInspectorTreeHandler, SelectionChanged));
958 mpObjectInspectorWidgets->mpInterfacesTreeView->make_sorted();
959 mpObjectInspectorWidgets->mpServicesTreeView->make_sorted();
960 mpObjectInspectorWidgets->mpPropertiesTreeView->make_sorted();
961 mpObjectInspectorWidgets->mpMethodsTreeView->make_sorted();
963 setSortFunction(mpObjectInspectorWidgets->mpInterfacesTreeView);
964 setSortFunction(mpObjectInspectorWidgets->mpServicesTreeView);
965 setSortFunction(mpObjectInspectorWidgets->mpPropertiesTreeView);
966 setSortFunction(mpObjectInspectorWidgets->mpMethodsTreeView);
968 mpObjectInspectorWidgets->mpInterfacesTreeView->connect_column_clicked(
969 LINK(this, ObjectInspectorTreeHandler, HeaderBarClick));
970 mpObjectInspectorWidgets->mpServicesTreeView->connect_column_clicked(
971 LINK(this, ObjectInspectorTreeHandler, HeaderBarClick));
972 mpObjectInspectorWidgets->mpPropertiesTreeView->connect_column_clicked(
973 LINK(this, ObjectInspectorTreeHandler, HeaderBarClick));
974 mpObjectInspectorWidgets->mpMethodsTreeView->connect_column_clicked(
975 LINK(this, ObjectInspectorTreeHandler, HeaderBarClick));
977 mpObjectInspectorWidgets->mpToolbar->connect_clicked(
978 LINK(this, ObjectInspectorTreeHandler, ToolbarButtonClicked));
979 mpObjectInspectorWidgets->mpToolbar->set_item_sensitive("inspect", false);
980 mpObjectInspectorWidgets->mpToolbar->set_item_sensitive("back", false);
982 mpObjectInspectorWidgets->mpNotebook->connect_leave_page(
983 LINK(this, ObjectInspectorTreeHandler, NotebookLeavePage));
984 mpObjectInspectorWidgets->mpNotebook->connect_enter_page(
985 LINK(this, ObjectInspectorTreeHandler, NotebookEnterPage));
987 auto nPropertiesDigitWidth
988 = mpObjectInspectorWidgets->mpPropertiesTreeView->get_approximate_digit_width();
989 std::vector<int> aPropertiesWidths(4, nPropertiesDigitWidth * 30);
990 mpObjectInspectorWidgets->mpPropertiesTreeView->set_column_fixed_widths(aPropertiesWidths);
992 auto nMethodsDigitWidth
993 = mpObjectInspectorWidgets->mpMethodsTreeView->get_approximate_digit_width();
994 std::vector<int> aMethodsWidths{ static_cast<int>(nMethodsDigitWidth * 30),
995 static_cast<int>(nMethodsDigitWidth * 15),
996 static_cast<int>(nMethodsDigitWidth * 30),
997 static_cast<int>(nMethodsDigitWidth * 50) };
998 mpObjectInspectorWidgets->mpMethodsTreeView->set_column_fixed_widths(aMethodsWidths);
1000 mpObjectInspectorWidgets->mpPaned->set_position(160);
1003 void ObjectInspectorTreeHandler::setSortFunction(std::unique_ptr<weld::TreeView>& pTreeView)
1005 pTreeView->set_sort_func(
1006 [this, &pTreeView](const weld::TreeIter& rLeft, const weld::TreeIter& rRight) {
1007 return compare(pTreeView, rLeft, rRight);
1011 sal_Int32 ObjectInspectorTreeHandler::compare(std::unique_ptr<weld::TreeView>& pTreeView,
1012 const weld::TreeIter& rLeft,
1013 const weld::TreeIter& rRight)
1015 int nSortColumn = pTreeView->get_sort_column();
1017 OUString sLeft = pTreeView->get_text(rLeft, nSortColumn);
1018 OUString sRight = pTreeView->get_text(rRight, nSortColumn);
1019 sal_Int32 nCompare = mxSorter.compare(sLeft, sRight);
1020 return nCompare;
1023 void ObjectInspectorTreeHandler::handleExpanding(std::unique_ptr<weld::TreeView>& pTreeView,
1024 weld::TreeIter const& rParent)
1026 OUString sID = pTreeView->get_id(rParent);
1027 if (sID.isEmpty())
1028 return;
1030 clearObjectInspectorChildren(pTreeView, rParent);
1031 auto* pNode = weld::fromId<ObjectInspectorNodeInterface*>(sID);
1032 pNode->fillChildren(pTreeView, &rParent);
1035 IMPL_LINK(ObjectInspectorTreeHandler, ExpandingHandlerInterfaces, weld::TreeIter const&, rParent,
1036 bool)
1038 handleExpanding(mpObjectInspectorWidgets->mpInterfacesTreeView, rParent);
1039 return true;
1042 IMPL_LINK(ObjectInspectorTreeHandler, ExpandingHandlerServices, weld::TreeIter const&, rParent,
1043 bool)
1045 handleExpanding(mpObjectInspectorWidgets->mpServicesTreeView, rParent);
1046 return true;
1049 IMPL_LINK(ObjectInspectorTreeHandler, ExpandingHandlerProperties, weld::TreeIter const&, rParent,
1050 bool)
1052 handleExpanding(mpObjectInspectorWidgets->mpPropertiesTreeView, rParent);
1053 return true;
1056 IMPL_LINK(ObjectInspectorTreeHandler, ExpandingHandlerMethods, weld::TreeIter const&, rParent, bool)
1058 handleExpanding(mpObjectInspectorWidgets->mpMethodsTreeView, rParent);
1059 return true;
1062 IMPL_LINK(ObjectInspectorTreeHandler, SelectionChanged, weld::TreeView&, rTreeView, void)
1064 bool bHaveNodeWithObject = false;
1065 mpObjectInspectorWidgets->mpTextView->set_text("");
1066 if (mpObjectInspectorWidgets->mpPropertiesTreeView.get() == &rTreeView)
1068 auto* pNode = getSelectedNode(rTreeView);
1069 if (auto* pBasicValueNode = dynamic_cast<BasicValueNode*>(pNode))
1071 uno::Any aAny = pBasicValueNode->getAny();
1072 uno::Reference<uno::XInterface> xInterface(aAny, uno::UNO_QUERY);
1073 bHaveNodeWithObject = xInterface.is();
1074 mpObjectInspectorWidgets->mpTextView->set_text(convertAnyToString(aAny, mxContext));
1078 mpObjectInspectorWidgets->mpToolbar->set_item_sensitive("inspect", bHaveNodeWithObject);
1081 static void updateOrder(const std::unique_ptr<weld::TreeView>& pTreeView, sal_Int32 nColumn)
1083 pTreeView->set_sort_column(nColumn);
1085 bool bSortAtoZ = pTreeView->get_sort_order();
1086 pTreeView->set_sort_order(!bSortAtoZ);
1087 pTreeView->set_sort_indicator(!bSortAtoZ ? TRISTATE_TRUE : TRISTATE_FALSE, nColumn);
1090 IMPL_LINK(ObjectInspectorTreeHandler, HeaderBarClick, int, nColumn, void)
1092 auto rPageId = mpObjectInspectorWidgets->mpNotebook->get_current_page_ident();
1094 if (rPageId == "object_inspector_interfaces_tab")
1095 updateOrder(mpObjectInspectorWidgets->mpInterfacesTreeView, nColumn);
1096 else if (rPageId == "object_inspector_services_tab")
1097 updateOrder(mpObjectInspectorWidgets->mpServicesTreeView, nColumn);
1098 else if (rPageId == "object_inspector_properties_tab")
1099 updateOrder(mpObjectInspectorWidgets->mpPropertiesTreeView, nColumn);
1100 else if (rPageId == "object_inspector_methods_tab")
1101 updateOrder(mpObjectInspectorWidgets->mpMethodsTreeView, nColumn);
1104 IMPL_LINK(ObjectInspectorTreeHandler, PopupMenuHandler, const CommandEvent&, rCommandEvent, bool)
1106 if (rCommandEvent.GetCommand() != CommandEventId::ContextMenu)
1107 return false;
1109 auto xInterface = getSelectedXInterface(*mpObjectInspectorWidgets->mpPropertiesTreeView);
1110 if (xInterface.is())
1112 std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(
1113 mpObjectInspectorWidgets->mpPropertiesTreeView.get(), "sfx/ui/devtoolsmenu.ui"));
1114 std::unique_ptr<weld::Menu> xMenu(xBuilder->weld_menu("inspect_menu"));
1116 OUString sCommand(
1117 xMenu->popup_at_rect(mpObjectInspectorWidgets->mpPropertiesTreeView.get(),
1118 tools::Rectangle(rCommandEvent.GetMousePosPixel(), Size(1, 1))));
1120 if (sCommand == "inspect")
1122 addToStack(uno::Any(xInterface));
1123 inspectObject(xInterface);
1126 return true;
1129 IMPL_LINK(ObjectInspectorTreeHandler, ToolbarButtonClicked, const OUString&, rSelectionId, void)
1131 if (rSelectionId == "inspect")
1133 auto xInterface = getSelectedXInterface(*mpObjectInspectorWidgets->mpPropertiesTreeView);
1134 if (xInterface.is())
1136 addToStack(uno::Any(xInterface));
1137 inspectObject(xInterface);
1140 else if (rSelectionId == "back")
1142 uno::Any aAny = popFromStack();
1143 if (aAny.hasValue())
1145 uno::Reference<uno::XInterface> xInterface(aAny, uno::UNO_QUERY);
1146 inspectObject(xInterface);
1149 else if (rSelectionId == "refresh")
1151 auto rPageId = mpObjectInspectorWidgets->mpNotebook->get_current_page_ident();
1152 NotebookEnterPage(rPageId);
1156 IMPL_LINK(ObjectInspectorTreeHandler, NotebookEnterPage, const OUString&, rPageId, void)
1158 uno::Any aAny = maInspectionStack.back();
1159 if (!aAny.hasValue())
1160 return;
1162 uno::Reference<uno::XInterface> xInterface(aAny, uno::UNO_QUERY);
1163 if (rPageId == "object_inspector_interfaces_tab")
1165 mpObjectInspectorWidgets->mpInterfacesTreeView->freeze();
1166 clearAll(mpObjectInspectorWidgets->mpInterfacesTreeView);
1167 appendInterfaces(xInterface);
1168 mpObjectInspectorWidgets->mpInterfacesTreeView->thaw();
1170 else if (rPageId == "object_inspector_services_tab")
1172 mpObjectInspectorWidgets->mpServicesTreeView->freeze();
1173 clearAll(mpObjectInspectorWidgets->mpServicesTreeView);
1174 appendServices(xInterface);
1175 mpObjectInspectorWidgets->mpServicesTreeView->thaw();
1177 else if (rPageId == "object_inspector_properties_tab")
1179 mpObjectInspectorWidgets->mpPropertiesTreeView->freeze();
1180 clearAll(mpObjectInspectorWidgets->mpPropertiesTreeView);
1181 appendProperties(xInterface);
1182 mpObjectInspectorWidgets->mpPropertiesTreeView->thaw();
1184 else if (rPageId == "object_inspector_methods_tab")
1186 mpObjectInspectorWidgets->mpMethodsTreeView->freeze();
1187 clearAll(mpObjectInspectorWidgets->mpMethodsTreeView);
1188 appendMethods(xInterface);
1189 mpObjectInspectorWidgets->mpMethodsTreeView->thaw();
1193 IMPL_LINK(ObjectInspectorTreeHandler, NotebookLeavePage, const OUString&, rPageId, bool)
1195 if (rPageId == "object_inspector_interfaces_tab")
1197 mpObjectInspectorWidgets->mpInterfacesTreeView->freeze();
1198 clearAll(mpObjectInspectorWidgets->mpInterfacesTreeView);
1199 mpObjectInspectorWidgets->mpInterfacesTreeView->thaw();
1201 else if (rPageId == "object_inspector_services_tab")
1203 mpObjectInspectorWidgets->mpServicesTreeView->freeze();
1204 clearAll(mpObjectInspectorWidgets->mpServicesTreeView);
1205 mpObjectInspectorWidgets->mpServicesTreeView->thaw();
1207 else if (rPageId == "object_inspector_properties_tab")
1209 mpObjectInspectorWidgets->mpPropertiesTreeView->freeze();
1210 clearAll(mpObjectInspectorWidgets->mpPropertiesTreeView);
1211 mpObjectInspectorWidgets->mpPropertiesTreeView->thaw();
1213 else if (rPageId == "object_inspector_methods_tab")
1215 mpObjectInspectorWidgets->mpMethodsTreeView->freeze();
1216 clearAll(mpObjectInspectorWidgets->mpMethodsTreeView);
1217 mpObjectInspectorWidgets->mpMethodsTreeView->thaw();
1219 return true;
1222 void ObjectInspectorTreeHandler::clearObjectInspectorChildren(
1223 std::unique_ptr<weld::TreeView>& pTreeView, weld::TreeIter const& rParent)
1225 bool bChild = false;
1228 bChild = pTreeView->iter_has_child(rParent);
1229 if (bChild)
1231 std::unique_ptr<weld::TreeIter> pChild = pTreeView->make_iterator(&rParent);
1232 bChild = pTreeView->iter_children(*pChild);
1233 if (bChild)
1235 clearObjectInspectorChildren(pTreeView, *pChild);
1236 OUString sID = pTreeView->get_id(*pChild);
1237 auto* pEntry = weld::fromId<ObjectInspectorNodeInterface*>(sID);
1238 delete pEntry;
1239 pTreeView->remove(*pChild);
1242 } while (bChild);
1245 /** Deletes all the node objects in a tree view */
1246 void ObjectInspectorTreeHandler::clearAll(std::unique_ptr<weld::TreeView>& pTreeView)
1248 // destroy all ObjectInspectorNodes from the tree
1249 pTreeView->all_foreach([&pTreeView](weld::TreeIter& rEntry) {
1250 OUString sID = pTreeView->get_id(rEntry);
1251 auto* pEntry = weld::fromId<ObjectInspectorNodeInterface*>(sID);
1252 delete pEntry;
1253 return false;
1255 pTreeView->clear();
1258 /** Append interfaces to the "interfaces" tree view */
1259 void ObjectInspectorTreeHandler::appendInterfaces(uno::Reference<uno::XInterface> const& xInterface)
1261 if (!xInterface.is())
1262 return;
1264 uno::Reference<lang::XTypeProvider> xTypeProvider(xInterface, uno::UNO_QUERY);
1265 if (xTypeProvider.is())
1267 const auto xSequenceTypes = xTypeProvider->getTypes();
1268 for (auto const& xType : xSequenceTypes)
1270 auto xClass = convertTypeToIdlClass(xType, mxContext);
1271 lclAppendNode(mpObjectInspectorWidgets->mpInterfacesTreeView, new ClassNode(xClass));
1276 /** Append services to the "services" tree view */
1277 void ObjectInspectorTreeHandler::appendServices(uno::Reference<uno::XInterface> const& xInterface)
1279 if (!xInterface.is())
1280 return;
1282 auto xServiceInfo = uno::Reference<lang::XServiceInfo>(xInterface, uno::UNO_QUERY);
1283 const uno::Sequence<OUString> aServiceNames(xServiceInfo->getSupportedServiceNames());
1284 for (auto const& aServiceName : aServiceNames)
1286 lclAppendNode(mpObjectInspectorWidgets->mpServicesTreeView,
1287 new SimpleStringNode(aServiceName));
1291 /** Append properties to the "properties" tree view */
1292 void ObjectInspectorTreeHandler::appendProperties(uno::Reference<uno::XInterface> const& xInterface)
1294 if (!xInterface.is())
1295 return;
1296 GenericPropertiesNode aNode("", uno::Any(xInterface), "", mxContext);
1297 aNode.fillChildren(mpObjectInspectorWidgets->mpPropertiesTreeView, nullptr);
1300 /** Append methods to the "methods" tree view */
1301 void ObjectInspectorTreeHandler::appendMethods(uno::Reference<uno::XInterface> const& xInterface)
1303 if (!xInterface.is())
1304 return;
1306 uno::Reference<beans::XIntrospection> xIntrospection = beans::theIntrospection::get(mxContext);
1307 auto xIntrospectionAccess = xIntrospection->inspect(uno::Any(xInterface));
1309 const auto xMethods = xIntrospectionAccess->getMethods(beans::MethodConcept::ALL);
1310 for (auto const& xMethod : xMethods)
1312 lclAppendNode(mpObjectInspectorWidgets->mpMethodsTreeView, new MethodNode(xMethod));
1316 // Update the back button state depending if there are objects in the stack
1317 void ObjectInspectorTreeHandler::updateBackButtonState()
1319 mpObjectInspectorWidgets->mpToolbar->set_item_sensitive("back", maInspectionStack.size() > 1);
1322 // Clears all the objects from the stack
1323 void ObjectInspectorTreeHandler::clearStack()
1325 maInspectionStack.clear();
1326 updateBackButtonState();
1329 // Adds an object to the stack
1330 void ObjectInspectorTreeHandler::addToStack(css::uno::Any const& rAny)
1332 maInspectionStack.push_back(rAny);
1333 updateBackButtonState();
1336 // Removes an object from the back of the stack and return it
1337 css::uno::Any ObjectInspectorTreeHandler::popFromStack()
1339 maInspectionStack.pop_back();
1340 uno::Any aAny = maInspectionStack.back();
1341 updateBackButtonState();
1342 return aAny;
1345 // Inspect the input object in the object inspector
1346 void ObjectInspectorTreeHandler::inspectObject(uno::Reference<uno::XInterface> const& xInterface)
1348 if (!xInterface.is())
1349 return;
1351 // Set implementation name
1352 OUString aImplementationName = getInterfaceImplementationClass(xInterface);
1353 mpObjectInspectorWidgets->mpClassNameLabel->set_label(aImplementationName);
1354 sal_Int32 nStrLen = aImplementationName.getLength();
1355 sal_Int32 nDigitWidth
1356 = mpObjectInspectorWidgets->mpClassNameLabel->get_approximate_digit_width();
1358 //get_about_digit_width() returns an approximate value. To always see the full class name (nStrLen+2)
1359 mpObjectInspectorWidgets->mpClassNameLabel->set_size_request((nStrLen + 2) * nDigitWidth, -1);
1361 // Fire entering the current opened page manually
1362 auto rPageId = mpObjectInspectorWidgets->mpNotebook->get_current_page_ident();
1363 NotebookEnterPage(rPageId);
1366 // Inspect the input object in the object inspector.
1367 // Make the input object the root of the stack (clear all other
1368 // objects from the stack).
1369 void ObjectInspectorTreeHandler::introspect(uno::Reference<uno::XInterface> const& xInterface)
1371 clearStack();
1372 addToStack(uno::Any(xInterface));
1373 inspectObject(xInterface);
1376 void ObjectInspectorTreeHandler::dispose()
1378 // We need to clear all the nodes
1379 clearAll(mpObjectInspectorWidgets->mpInterfacesTreeView);
1380 clearAll(mpObjectInspectorWidgets->mpServicesTreeView);
1381 clearAll(mpObjectInspectorWidgets->mpPropertiesTreeView);
1382 clearAll(mpObjectInspectorWidgets->mpMethodsTreeView);
1385 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */