document RasterOp a little
[LibreOffice.git] / sfx2 / source / devtools / ObjectInspectorTreeHandler.cxx
blobbd403d84c5a36f9475950d571ea92f3126b29475
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.getValueTypeName()),
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(u"Name"_ustr))
206 uno::Any aAny = xInvocation->getValue(u"Name"_ustr);
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.getValueTypeName();
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 void 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);
368 // appends the node to the parent
369 void lclAppendNodeToParent(const std::unique_ptr<weld::TreeView>& pTree,
370 const weld::TreeIter* pParent, ObjectInspectorNodeInterface* pEntry)
372 OUString sName = pEntry->getObjectName();
373 OUString sId(weld::toId(pEntry));
374 std::unique_ptr<weld::TreeIter> pCurrent = pTree->make_iterator();
375 pTree->insert(pParent, -1, &sName, &sId, nullptr, nullptr, pEntry->shouldShowExpander(),
376 pCurrent.get());
377 pTree->set_text_emphasis(*pCurrent, true, 0);
379 for (auto const& rPair : pEntry->getColumnValues())
381 pTree->set_text(*pCurrent, rPair.second, rPair.first);
385 /** Node that represent just a simple string with no children or columns */
386 class SimpleStringNode : public ObjectInspectorNodeInterface
388 protected:
389 OUString msName;
391 public:
392 SimpleStringNode(OUString sName)
393 : msName(std::move(sName))
397 void fillChildren(std::unique_ptr<weld::TreeView>& /*rTree*/,
398 const weld::TreeIter* /*pParent*/) override
402 OUString getObjectName() override { return msName; }
405 /** Node represents a method of an object */
406 class MethodNode : public ObjectInspectorNodeInterface
408 private:
409 uno::Reference<reflection::XIdlMethod> mxMethod;
411 public:
412 MethodNode(uno::Reference<reflection::XIdlMethod> xMethod)
413 : mxMethod(std::move(xMethod))
417 OUString getObjectName() override { return mxMethod->getName(); }
419 static OUString simpleTypeName(uno::Reference<reflection::XIdlClass> const& xClass)
421 switch (xClass->getTypeClass())
423 case uno::TypeClass_INTERFACE:
424 return SfxResId(STR_METHOD_TYPE_OBJECT);
425 case uno::TypeClass_STRUCT:
426 return SfxResId(STR_METHOD_TYPE_STRUCT);
427 case uno::TypeClass_ENUM:
428 return SfxResId(STR_METHOD_TYPE_ENUM);
429 case uno::TypeClass_SEQUENCE:
430 return SfxResId(STR_METHOD_TYPE_SEQUENCE);
431 default:
432 break;
434 return xClass->getName();
437 std::vector<std::pair<sal_Int32, OUString>> getColumnValues() override
439 OUString aOutString;
440 auto xClass = mxMethod->getReturnType();
441 aOutString = simpleTypeName(xClass);
443 OUString aInString;
444 const auto aParameters = mxMethod->getParameterInfos();
445 bool bFirst = true;
446 for (auto const& rParameterInfo : aParameters)
448 if (!bFirst)
449 aInString += ", ";
450 else
451 bFirst = false;
453 switch (rParameterInfo.aMode)
455 case reflection::ParamMode_IN:
456 aInString += SfxResId(STR_PARMETER_MODE_IN) + " ";
457 break;
458 case reflection::ParamMode_OUT:
459 aInString += SfxResId(STR_PARMETER_MODE_OUT) + " ";
460 break;
461 case reflection::ParamMode_INOUT:
462 aInString += SfxResId(STR_PARMETER_MODE_IN_AND_OUT) + " ";
463 break;
464 default:
465 break;
468 aInString += rParameterInfo.aName + " : " + simpleTypeName(rParameterInfo.aType);
471 OUString aImplementationClass = mxMethod->getDeclaringClass()->getName();
473 return {
474 { 1, aOutString },
475 { 2, aInString },
476 { 3, aImplementationClass },
480 void fillChildren(std::unique_ptr<weld::TreeView>& /*rTree*/,
481 const weld::TreeIter* /*pParent*/) override
486 /** Node represents a class (XIdlClass) of an object.
488 * Children are superclasses of the current class. XInterface superclass
489 * is ignored.
492 class ClassNode : public ObjectInspectorNodeInterface
494 private:
495 uno::Reference<reflection::XIdlClass> mxClass;
497 static bool isXInterface(uno::Reference<reflection::XIdlClass> const& xClass)
499 return xClass->getName() == "com.sun.star.uno.XInterface";
502 public:
503 ClassNode(uno::Reference<reflection::XIdlClass> xClass)
504 : mxClass(std::move(xClass))
508 bool shouldShowExpander() override
510 auto const xSuperClasses = mxClass->getSuperclasses();
511 return xSuperClasses.getLength() > 2
512 || (xSuperClasses.getLength() == 1 && !isXInterface(xSuperClasses[0]));
515 OUString getObjectName() override { return mxClass->getName(); }
517 // Fill superclasses
518 void fillChildren(std::unique_ptr<weld::TreeView>& rTree,
519 const weld::TreeIter* pParent) override
521 auto const xSuperClasses = mxClass->getSuperclasses();
522 for (auto const& xSuper : xSuperClasses)
524 if (!isXInterface(xSuper))
525 lclAppendNodeToParent(rTree, pParent, new ClassNode(xSuper));
530 /** Node represents a basic value, that can be any object, sequence, struct */
531 class BasicValueNode : public SimpleStringNode
533 protected:
534 uno::Any maAny;
535 OUString mrInfo;
536 uno::Reference<uno::XComponentContext> mxContext;
538 ObjectInspectorNodeInterface*
539 createNodeObjectForAny(OUString const& rName, const uno::Any& rAny, OUString const& mrInfo);
541 public:
542 BasicValueNode(OUString const& rName, uno::Any aAny, OUString aInfo,
543 uno::Reference<uno::XComponentContext> xContext)
544 : SimpleStringNode(rName)
545 , maAny(std::move(aAny))
546 , mrInfo(std::move(aInfo))
547 , mxContext(std::move(xContext))
551 const uno::Any& getAny() const { return maAny; }
553 bool shouldShowExpander() override
555 if (maAny.hasValue())
557 switch (maAny.getValueTypeClass())
559 case uno::TypeClass_INTERFACE:
561 uno::Reference<uno::XInterface> xInterface(maAny, uno::UNO_QUERY);
562 return xInterface.is();
564 case uno::TypeClass_SEQUENCE:
565 return true;
566 default:
567 break;
570 return false;
573 std::vector<std::pair<sal_Int32, OUString>> getColumnValues() override
575 OUString aValue = convertAnyToShortenedString(maAny, mxContext);
576 OUString aType = getAnyType(maAny);
578 return { { 1, aValue }, { 2, aType }, { 3, mrInfo } };
582 /** Node represents a property */
583 class GenericPropertiesNode : public BasicValueNode
585 public:
586 GenericPropertiesNode(OUString const& rName, uno::Any const& rAny, OUString const& rInfo,
587 uno::Reference<uno::XComponentContext> const& xContext)
588 : BasicValueNode(rName, rAny, rInfo, xContext)
592 void fillChildren(std::unique_ptr<weld::TreeView>& pTree,
593 const weld::TreeIter* pParent) override;
596 /** Node represents a struct */
597 class StructNode : public BasicValueNode
599 public:
600 StructNode(OUString const& rName, uno::Any const& rAny, OUString const& rInfo,
601 uno::Reference<uno::XComponentContext> const& xContext)
602 : BasicValueNode(rName, rAny, rInfo, xContext)
606 bool shouldShowExpander() override { return true; }
608 void fillChildren(std::unique_ptr<weld::TreeView>& pTree,
609 const weld::TreeIter* pParent) override;
612 /** Node represents a sequence */
613 class SequenceNode : public BasicValueNode
615 uno::Reference<reflection::XIdlArray> mxIdlArray;
617 public:
618 SequenceNode(OUString const& rName, uno::Any const& rAny, OUString const& rInfo,
619 uno::Reference<uno::XComponentContext> const& xContext)
620 : BasicValueNode(rName, rAny, rInfo, xContext)
622 auto xClass = convertTypeToIdlClass(maAny.getValueType(), mxContext);
623 mxIdlArray = xClass->getArray();
626 bool shouldShowExpander() override
628 // Show expander only if the sequence has elements
629 int nLength = mxIdlArray->getLen(maAny);
630 return nLength > 0;
633 void fillChildren(std::unique_ptr<weld::TreeView>& pTree,
634 const weld::TreeIter* pParent) override
636 int nLength = mxIdlArray->getLen(maAny);
638 for (int i = 0; i < nLength; i++)
640 uno::Any aArrayValue = mxIdlArray->get(maAny, i);
642 auto* pObjectInspectorNode
643 = createNodeObjectForAny(OUString::number(i), aArrayValue, u""_ustr);
644 if (pObjectInspectorNode)
645 lclAppendNodeToParent(pTree, pParent, pObjectInspectorNode);
649 std::vector<std::pair<sal_Int32, OUString>> getColumnValues() override
651 int nLength = mxIdlArray->getLen(maAny);
653 OUString aType
654 = getAnyType(maAny).replaceAll(u"[]", u"") + u"[" + OUString::number(nLength) + u"]";
656 OUString aValue
657 = SfxResId(STR_PROPERTY_VALUE_SEQUENCE).replaceFirst("%1", OUString::number(nLength));
659 return {
660 { 1, aValue },
661 { 2, aType },
666 void GenericPropertiesNode::fillChildren(std::unique_ptr<weld::TreeView>& pTree,
667 const weld::TreeIter* pParent)
669 if (!maAny.hasValue())
670 return;
674 const auto xNameAccess = uno::Reference<container::XNameAccess>(maAny, uno::UNO_QUERY);
675 if (xNameAccess.is())
677 const uno::Sequence<OUString> aNames = xNameAccess->getElementNames();
678 for (OUString const& rName : aNames)
680 uno::Any aAny = xNameAccess->getByName(rName);
681 auto* pObjectInspectorNode = createNodeObjectForAny(
682 u"@" + rName, aAny, SfxResId(STR_PROPERTY_TYPE_IS_NAMED_CONTAINER));
683 lclAppendNodeToParent(pTree, pParent, pObjectInspectorNode);
687 catch (...)
693 const auto xIndexAccess = uno::Reference<container::XIndexAccess>(maAny, uno::UNO_QUERY);
694 if (xIndexAccess.is())
696 for (sal_Int32 nIndex = 0; nIndex < xIndexAccess->getCount(); ++nIndex)
698 uno::Any aAny = xIndexAccess->getByIndex(nIndex);
699 auto* pObjectInspectorNode
700 = createNodeObjectForAny(u"@" + OUString::number(nIndex), aAny,
701 SfxResId(STR_PROPERTY_TYPE_IS_INDEX_CONTAINER));
702 lclAppendNodeToParent(pTree, pParent, pObjectInspectorNode);
706 catch (...)
712 const auto xEnumAccess
713 = uno::Reference<container::XEnumerationAccess>(maAny, uno::UNO_QUERY);
714 if (xEnumAccess.is())
716 uno::Reference<container::XEnumeration> xEnumeration = xEnumAccess->createEnumeration();
717 if (xEnumeration.is())
719 for (sal_Int32 nIndex = 0; xEnumeration->hasMoreElements(); nIndex++)
721 uno::Any aAny = xEnumeration->nextElement();
722 auto* pObjectInspectorNode
723 = createNodeObjectForAny(u"@" + OUString::number(nIndex), aAny,
724 SfxResId(STR_PROPERTY_TYPE_IS_ENUMERATION));
725 lclAppendNodeToParent(pTree, pParent, pObjectInspectorNode);
730 catch (...)
734 auto xInvocationFactory = css::script::Invocation::create(mxContext);
735 uno::Sequence<uno::Any> aParameters = { maAny };
736 auto xInvocationInterface = xInvocationFactory->createInstanceWithArguments(aParameters);
737 if (!xInvocationInterface.is())
738 return;
740 uno::Reference<script::XInvocation2> xInvocation(xInvocationInterface, uno::UNO_QUERY);
741 if (!xInvocation.is())
742 return;
744 auto const xInvocationAccess = xInvocation->getIntrospection();
745 if (!xInvocationAccess.is())
746 return;
748 uno::Sequence<script::InvocationInfo> aInvocationInfoSequence;
751 aInvocationInfoSequence = xInvocation->getInfo();
753 catch (...)
757 for (auto const& aInvocationInfo : aInvocationInfoSequence)
759 if (aInvocationInfo.eMemberType == script::MemberType_PROPERTY)
761 uno::Any aCurrentAny;
762 auto const& aPropertyName = aInvocationInfo.aName;
764 bool bIsAttribute = false;
765 bool bIsGetSetMethod = false;
766 bool bMethodGet = false;
767 bool bMethodSet = false;
768 bool bMethodIs = false;
771 aCurrentAny = xInvocation->getValue(aPropertyName);
772 bIsAttribute = xInvocationAccess->hasProperty(aPropertyName,
773 beans::PropertyConcept::ATTRIBUTES);
774 bIsGetSetMethod = xInvocationAccess->hasProperty(aPropertyName,
775 beans::PropertyConcept::METHODS);
776 if (bIsGetSetMethod)
778 bMethodGet = xInvocationAccess->hasMethod(u"get" + aPropertyName,
779 beans::MethodConcept::PROPERTY);
780 bMethodSet = xInvocationAccess->hasMethod(u"set" + aPropertyName,
781 beans::MethodConcept::PROPERTY);
782 bMethodIs = xInvocationAccess->hasMethod(u"is" + aPropertyName,
783 beans::MethodConcept::PROPERTY);
786 catch (...)
790 std::vector<OUString> aInfoCollection;
791 if (bIsAttribute)
792 aInfoCollection.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_IS_ATTRIBUTE));
793 if (bIsGetSetMethod)
795 bool bHasGet = false;
796 OUString aString;
797 if (bMethodGet || bMethodIs)
799 aString += SfxResId(STR_PROPERTY_ATTRIBUTE_GET);
800 bHasGet = true;
802 if (bMethodSet)
804 if (bHasGet)
805 aString += u"+";
806 aString += SfxResId(STR_PROPERTY_ATTRIBUTE_SET);
808 aInfoCollection.push_back(aString);
809 if (bMethodSet && !bHasGet)
810 aInfoCollection.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_WRITEONLY));
812 if (aInvocationInfo.PropertyAttribute & beans::PropertyAttribute::MAYBEVOID)
813 aInfoCollection.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_MAYBEVOID));
814 if (aInvocationInfo.PropertyAttribute & beans::PropertyAttribute::READONLY)
815 aInfoCollection.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_READONLY));
816 if (aInvocationInfo.PropertyAttribute & beans::PropertyAttribute::REMOVABLE)
817 aInfoCollection.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_REMOVABLE));
818 if (aInvocationInfo.PropertyAttribute & beans::PropertyAttribute::BOUND)
819 aInfoCollection.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_BOUND));
820 if (aInvocationInfo.PropertyAttribute & beans::PropertyAttribute::CONSTRAINED)
821 aInfoCollection.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_CONSTRAINED));
822 if (aInvocationInfo.PropertyAttribute & beans::PropertyAttribute::TRANSIENT)
823 aInfoCollection.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_TRANSIENT));
824 if (aInvocationInfo.PropertyAttribute & beans::PropertyAttribute::MAYBEAMBIGUOUS)
825 aInfoCollection.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_MAYBEAMBIGUOUS));
826 if (aInvocationInfo.PropertyAttribute & beans::PropertyAttribute::MAYBEDEFAULT)
827 aInfoCollection.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_MAYBEDEFAULT));
829 bool bSet = false;
830 OUString aInfoString;
831 for (auto const& rString : aInfoCollection)
833 if (bSet)
834 aInfoString += ", ";
835 else
836 bSet = true;
838 aInfoString += rString;
841 auto* pObjectInspectorNode
842 = createNodeObjectForAny(aPropertyName, aCurrentAny, aInfoString);
843 if (pObjectInspectorNode)
844 lclAppendNodeToParent(pTree, pParent, pObjectInspectorNode);
849 void StructNode::fillChildren(std::unique_ptr<weld::TreeView>& pTree, const weld::TreeIter* pParent)
851 auto xReflection = reflection::theCoreReflection::get(mxContext);
852 uno::Reference<reflection::XIdlClass> xClass = xReflection->forName(maAny.getValueTypeName());
854 const auto xFields = xClass->getFields();
856 for (auto const& xField : xFields)
858 OUString aFieldName = xField->getName();
859 uno::Any aFieldValue = xField->get(maAny);
861 auto* pObjectInspectorNode = createNodeObjectForAny(aFieldName, aFieldValue, u""_ustr);
862 if (pObjectInspectorNode)
864 lclAppendNodeToParent(pTree, pParent, pObjectInspectorNode);
869 ObjectInspectorNodeInterface* BasicValueNode::createNodeObjectForAny(OUString const& rName,
870 const uno::Any& rAny,
871 OUString const& rInfo)
873 switch (rAny.getValueTypeClass())
875 case uno::TypeClass_INTERFACE:
876 return new GenericPropertiesNode(rName, rAny, rInfo, mxContext);
878 case uno::TypeClass_SEQUENCE:
879 return new SequenceNode(rName, rAny, rInfo, mxContext);
881 case uno::TypeClass_STRUCT:
882 return new StructNode(rName, rAny, rInfo, mxContext);
884 default:
885 break;
888 return new BasicValueNode(rName, rAny, rInfo, mxContext);
891 } // end anonymous namespace
893 // Object inspector tree view helper functions
894 namespace
896 ObjectInspectorNodeInterface* getSelectedNode(weld::TreeView const& rTreeView)
898 OUString sID = rTreeView.get_selected_id();
899 if (sID.isEmpty())
900 return nullptr;
902 if (auto* pNode = weld::fromId<ObjectInspectorNodeInterface*>(sID))
903 return pNode;
905 return nullptr;
908 uno::Reference<uno::XInterface> getSelectedXInterface(weld::TreeView const& rTreeView)
910 uno::Reference<uno::XInterface> xInterface;
912 if (auto* pNode = getSelectedNode(rTreeView))
914 if (auto* pBasicValueNode = dynamic_cast<BasicValueNode*>(pNode))
916 uno::Any aAny = pBasicValueNode->getAny();
917 xInterface.set(aAny, uno::UNO_QUERY);
921 return xInterface;
924 } // end anonymous namespace
926 ObjectInspectorTreeHandler::ObjectInspectorTreeHandler(
927 std::unique_ptr<ObjectInspectorWidgets>& pObjectInspectorWidgets)
928 : mpObjectInspectorWidgets(pObjectInspectorWidgets)
929 , mxContext(comphelper::getProcessComponentContext())
930 , mxSorter(mxContext, Application::GetSettings().GetLanguageTag().getLocale())
932 mpObjectInspectorWidgets->mpInterfacesTreeView->connect_expanding(
933 LINK(this, ObjectInspectorTreeHandler, ExpandingHandlerInterfaces));
934 mpObjectInspectorWidgets->mpServicesTreeView->connect_expanding(
935 LINK(this, ObjectInspectorTreeHandler, ExpandingHandlerServices));
936 mpObjectInspectorWidgets->mpPropertiesTreeView->connect_expanding(
937 LINK(this, ObjectInspectorTreeHandler, ExpandingHandlerProperties));
938 mpObjectInspectorWidgets->mpMethodsTreeView->connect_expanding(
939 LINK(this, ObjectInspectorTreeHandler, ExpandingHandlerMethods));
941 mpObjectInspectorWidgets->mpPropertiesTreeView->connect_popup_menu(
942 LINK(this, ObjectInspectorTreeHandler, PopupMenuHandler));
944 mpObjectInspectorWidgets->mpInterfacesTreeView->connect_selection_changed(
945 LINK(this, ObjectInspectorTreeHandler, SelectionChanged));
946 mpObjectInspectorWidgets->mpServicesTreeView->connect_selection_changed(
947 LINK(this, ObjectInspectorTreeHandler, SelectionChanged));
948 mpObjectInspectorWidgets->mpPropertiesTreeView->connect_selection_changed(
949 LINK(this, ObjectInspectorTreeHandler, SelectionChanged));
950 mpObjectInspectorWidgets->mpMethodsTreeView->connect_selection_changed(
951 LINK(this, ObjectInspectorTreeHandler, SelectionChanged));
953 mpObjectInspectorWidgets->mpInterfacesTreeView->make_sorted();
954 mpObjectInspectorWidgets->mpServicesTreeView->make_sorted();
955 mpObjectInspectorWidgets->mpPropertiesTreeView->make_sorted();
956 mpObjectInspectorWidgets->mpMethodsTreeView->make_sorted();
958 setSortFunction(mpObjectInspectorWidgets->mpInterfacesTreeView);
959 setSortFunction(mpObjectInspectorWidgets->mpServicesTreeView);
960 setSortFunction(mpObjectInspectorWidgets->mpPropertiesTreeView);
961 setSortFunction(mpObjectInspectorWidgets->mpMethodsTreeView);
963 mpObjectInspectorWidgets->mpInterfacesTreeView->connect_column_clicked(
964 LINK(this, ObjectInspectorTreeHandler, HeaderBarClick));
965 mpObjectInspectorWidgets->mpServicesTreeView->connect_column_clicked(
966 LINK(this, ObjectInspectorTreeHandler, HeaderBarClick));
967 mpObjectInspectorWidgets->mpPropertiesTreeView->connect_column_clicked(
968 LINK(this, ObjectInspectorTreeHandler, HeaderBarClick));
969 mpObjectInspectorWidgets->mpMethodsTreeView->connect_column_clicked(
970 LINK(this, ObjectInspectorTreeHandler, HeaderBarClick));
972 mpObjectInspectorWidgets->mpToolbar->connect_clicked(
973 LINK(this, ObjectInspectorTreeHandler, ToolbarButtonClicked));
974 mpObjectInspectorWidgets->mpToolbar->set_item_sensitive(u"inspect"_ustr, false);
975 mpObjectInspectorWidgets->mpToolbar->set_item_sensitive(u"back"_ustr, false);
977 mpObjectInspectorWidgets->mpNotebook->connect_leave_page(
978 LINK(this, ObjectInspectorTreeHandler, NotebookLeavePage));
979 mpObjectInspectorWidgets->mpNotebook->connect_enter_page(
980 LINK(this, ObjectInspectorTreeHandler, NotebookEnterPage));
982 auto nPropertiesDigitWidth
983 = mpObjectInspectorWidgets->mpPropertiesTreeView->get_approximate_digit_width();
984 std::vector<int> aPropertiesWidths(4, nPropertiesDigitWidth * 30);
985 mpObjectInspectorWidgets->mpPropertiesTreeView->set_column_fixed_widths(aPropertiesWidths);
987 auto nMethodsDigitWidth
988 = mpObjectInspectorWidgets->mpMethodsTreeView->get_approximate_digit_width();
989 std::vector<int> aMethodsWidths{ static_cast<int>(nMethodsDigitWidth * 30),
990 static_cast<int>(nMethodsDigitWidth * 15),
991 static_cast<int>(nMethodsDigitWidth * 30),
992 static_cast<int>(nMethodsDigitWidth * 50) };
993 mpObjectInspectorWidgets->mpMethodsTreeView->set_column_fixed_widths(aMethodsWidths);
995 mpObjectInspectorWidgets->mpPaned->set_position(160);
998 void ObjectInspectorTreeHandler::setSortFunction(std::unique_ptr<weld::TreeView>& pTreeView)
1000 pTreeView->set_sort_func(
1001 [this, &pTreeView](const weld::TreeIter& rLeft, const weld::TreeIter& rRight) {
1002 return compare(pTreeView, rLeft, rRight);
1006 sal_Int32 ObjectInspectorTreeHandler::compare(std::unique_ptr<weld::TreeView>& pTreeView,
1007 const weld::TreeIter& rLeft,
1008 const weld::TreeIter& rRight)
1010 int nSortColumn = pTreeView->get_sort_column();
1012 OUString sLeft = pTreeView->get_text(rLeft, nSortColumn);
1013 OUString sRight = pTreeView->get_text(rRight, nSortColumn);
1014 sal_Int32 nCompare = mxSorter.compare(sLeft, sRight);
1015 return nCompare;
1018 void ObjectInspectorTreeHandler::handleExpanding(std::unique_ptr<weld::TreeView>& pTreeView,
1019 weld::TreeIter const& rParent)
1021 OUString sID = pTreeView->get_id(rParent);
1022 if (sID.isEmpty())
1023 return;
1025 clearObjectInspectorChildren(pTreeView, rParent);
1026 auto* pNode = weld::fromId<ObjectInspectorNodeInterface*>(sID);
1027 pNode->fillChildren(pTreeView, &rParent);
1030 IMPL_LINK(ObjectInspectorTreeHandler, ExpandingHandlerInterfaces, weld::TreeIter const&, rParent,
1031 bool)
1033 handleExpanding(mpObjectInspectorWidgets->mpInterfacesTreeView, rParent);
1034 return true;
1037 IMPL_LINK(ObjectInspectorTreeHandler, ExpandingHandlerServices, weld::TreeIter const&, rParent,
1038 bool)
1040 handleExpanding(mpObjectInspectorWidgets->mpServicesTreeView, rParent);
1041 return true;
1044 IMPL_LINK(ObjectInspectorTreeHandler, ExpandingHandlerProperties, weld::TreeIter const&, rParent,
1045 bool)
1047 handleExpanding(mpObjectInspectorWidgets->mpPropertiesTreeView, rParent);
1048 return true;
1051 IMPL_LINK(ObjectInspectorTreeHandler, ExpandingHandlerMethods, weld::TreeIter const&, rParent, bool)
1053 handleExpanding(mpObjectInspectorWidgets->mpMethodsTreeView, rParent);
1054 return true;
1057 IMPL_LINK(ObjectInspectorTreeHandler, SelectionChanged, weld::TreeView&, rTreeView, void)
1059 bool bHaveNodeWithObject = false;
1060 mpObjectInspectorWidgets->mpTextView->set_text(u""_ustr);
1061 if (mpObjectInspectorWidgets->mpPropertiesTreeView.get() == &rTreeView)
1063 auto* pNode = getSelectedNode(rTreeView);
1064 if (auto* pBasicValueNode = dynamic_cast<BasicValueNode*>(pNode))
1066 uno::Any aAny = pBasicValueNode->getAny();
1067 uno::Reference<uno::XInterface> xInterface(aAny, uno::UNO_QUERY);
1068 bHaveNodeWithObject = xInterface.is();
1069 mpObjectInspectorWidgets->mpTextView->set_text(convertAnyToString(aAny, mxContext));
1073 mpObjectInspectorWidgets->mpToolbar->set_item_sensitive(u"inspect"_ustr, bHaveNodeWithObject);
1076 static void updateOrder(const std::unique_ptr<weld::TreeView>& pTreeView, sal_Int32 nColumn)
1078 pTreeView->set_sort_column(nColumn);
1080 bool bSortAtoZ = pTreeView->get_sort_order();
1081 pTreeView->set_sort_order(!bSortAtoZ);
1082 pTreeView->set_sort_indicator(!bSortAtoZ ? TRISTATE_TRUE : TRISTATE_FALSE, nColumn);
1085 IMPL_LINK(ObjectInspectorTreeHandler, HeaderBarClick, int, nColumn, void)
1087 auto rPageId = mpObjectInspectorWidgets->mpNotebook->get_current_page_ident();
1089 if (rPageId == "object_inspector_interfaces_tab")
1090 updateOrder(mpObjectInspectorWidgets->mpInterfacesTreeView, nColumn);
1091 else if (rPageId == "object_inspector_services_tab")
1092 updateOrder(mpObjectInspectorWidgets->mpServicesTreeView, nColumn);
1093 else if (rPageId == "object_inspector_properties_tab")
1094 updateOrder(mpObjectInspectorWidgets->mpPropertiesTreeView, nColumn);
1095 else if (rPageId == "object_inspector_methods_tab")
1096 updateOrder(mpObjectInspectorWidgets->mpMethodsTreeView, nColumn);
1099 IMPL_LINK(ObjectInspectorTreeHandler, PopupMenuHandler, const CommandEvent&, rCommandEvent, bool)
1101 if (rCommandEvent.GetCommand() != CommandEventId::ContextMenu)
1102 return false;
1104 auto xInterface = getSelectedXInterface(*mpObjectInspectorWidgets->mpPropertiesTreeView);
1105 if (xInterface.is())
1107 std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(
1108 mpObjectInspectorWidgets->mpPropertiesTreeView.get(), u"sfx/ui/devtoolsmenu.ui"_ustr));
1109 std::unique_ptr<weld::Menu> xMenu(xBuilder->weld_menu(u"inspect_menu"_ustr));
1111 OUString sCommand(
1112 xMenu->popup_at_rect(mpObjectInspectorWidgets->mpPropertiesTreeView.get(),
1113 tools::Rectangle(rCommandEvent.GetMousePosPixel(), Size(1, 1))));
1115 if (sCommand == "inspect")
1117 addToStack(uno::Any(xInterface));
1118 inspectObject(xInterface);
1121 return true;
1124 IMPL_LINK(ObjectInspectorTreeHandler, ToolbarButtonClicked, const OUString&, rSelectionId, void)
1126 if (rSelectionId == "inspect")
1128 auto xInterface = getSelectedXInterface(*mpObjectInspectorWidgets->mpPropertiesTreeView);
1129 if (xInterface.is())
1131 addToStack(uno::Any(xInterface));
1132 inspectObject(xInterface);
1135 else if (rSelectionId == "back")
1137 uno::Any aAny = popFromStack();
1138 if (aAny.hasValue())
1140 uno::Reference<uno::XInterface> xInterface(aAny, uno::UNO_QUERY);
1141 inspectObject(xInterface);
1144 else if (rSelectionId == "refresh")
1146 auto rPageId = mpObjectInspectorWidgets->mpNotebook->get_current_page_ident();
1147 NotebookEnterPage(rPageId);
1151 IMPL_LINK(ObjectInspectorTreeHandler, NotebookEnterPage, const OUString&, rPageId, void)
1153 uno::Any aAny = maInspectionStack.back();
1154 if (!aAny.hasValue())
1155 return;
1157 uno::Reference<uno::XInterface> xInterface(aAny, uno::UNO_QUERY);
1158 if (rPageId == "object_inspector_interfaces_tab")
1160 mpObjectInspectorWidgets->mpInterfacesTreeView->freeze();
1161 clearAll(mpObjectInspectorWidgets->mpInterfacesTreeView);
1162 appendInterfaces(xInterface);
1163 mpObjectInspectorWidgets->mpInterfacesTreeView->thaw();
1165 else if (rPageId == "object_inspector_services_tab")
1167 mpObjectInspectorWidgets->mpServicesTreeView->freeze();
1168 clearAll(mpObjectInspectorWidgets->mpServicesTreeView);
1169 appendServices(xInterface);
1170 mpObjectInspectorWidgets->mpServicesTreeView->thaw();
1172 else if (rPageId == "object_inspector_properties_tab")
1174 mpObjectInspectorWidgets->mpPropertiesTreeView->freeze();
1175 clearAll(mpObjectInspectorWidgets->mpPropertiesTreeView);
1176 appendProperties(xInterface);
1177 mpObjectInspectorWidgets->mpPropertiesTreeView->thaw();
1179 else if (rPageId == "object_inspector_methods_tab")
1181 mpObjectInspectorWidgets->mpMethodsTreeView->freeze();
1182 clearAll(mpObjectInspectorWidgets->mpMethodsTreeView);
1183 appendMethods(xInterface);
1184 mpObjectInspectorWidgets->mpMethodsTreeView->thaw();
1188 IMPL_LINK(ObjectInspectorTreeHandler, NotebookLeavePage, const OUString&, rPageId, bool)
1190 if (rPageId == "object_inspector_interfaces_tab")
1192 mpObjectInspectorWidgets->mpInterfacesTreeView->freeze();
1193 clearAll(mpObjectInspectorWidgets->mpInterfacesTreeView);
1194 mpObjectInspectorWidgets->mpInterfacesTreeView->thaw();
1196 else if (rPageId == "object_inspector_services_tab")
1198 mpObjectInspectorWidgets->mpServicesTreeView->freeze();
1199 clearAll(mpObjectInspectorWidgets->mpServicesTreeView);
1200 mpObjectInspectorWidgets->mpServicesTreeView->thaw();
1202 else if (rPageId == "object_inspector_properties_tab")
1204 mpObjectInspectorWidgets->mpPropertiesTreeView->freeze();
1205 clearAll(mpObjectInspectorWidgets->mpPropertiesTreeView);
1206 mpObjectInspectorWidgets->mpPropertiesTreeView->thaw();
1208 else if (rPageId == "object_inspector_methods_tab")
1210 mpObjectInspectorWidgets->mpMethodsTreeView->freeze();
1211 clearAll(mpObjectInspectorWidgets->mpMethodsTreeView);
1212 mpObjectInspectorWidgets->mpMethodsTreeView->thaw();
1214 return true;
1217 void ObjectInspectorTreeHandler::clearObjectInspectorChildren(
1218 std::unique_ptr<weld::TreeView>& pTreeView, weld::TreeIter const& rParent)
1220 bool bChild = false;
1223 bChild = pTreeView->iter_has_child(rParent);
1224 if (bChild)
1226 std::unique_ptr<weld::TreeIter> pChild = pTreeView->make_iterator(&rParent);
1227 bChild = pTreeView->iter_children(*pChild);
1228 if (bChild)
1230 clearObjectInspectorChildren(pTreeView, *pChild);
1231 OUString sID = pTreeView->get_id(*pChild);
1232 auto* pEntry = weld::fromId<ObjectInspectorNodeInterface*>(sID);
1233 delete pEntry;
1234 pTreeView->remove(*pChild);
1237 } while (bChild);
1240 /** Deletes all the node objects in a tree view */
1241 void ObjectInspectorTreeHandler::clearAll(std::unique_ptr<weld::TreeView>& pTreeView)
1243 // destroy all ObjectInspectorNodes from the tree
1244 pTreeView->all_foreach([&pTreeView](weld::TreeIter& rEntry) {
1245 OUString sID = pTreeView->get_id(rEntry);
1246 auto* pEntry = weld::fromId<ObjectInspectorNodeInterface*>(sID);
1247 delete pEntry;
1248 return false;
1250 pTreeView->clear();
1253 /** Append interfaces to the "interfaces" tree view */
1254 void ObjectInspectorTreeHandler::appendInterfaces(uno::Reference<uno::XInterface> const& xInterface)
1256 if (!xInterface.is())
1257 return;
1259 uno::Reference<lang::XTypeProvider> xTypeProvider(xInterface, uno::UNO_QUERY);
1260 if (xTypeProvider.is())
1262 const auto xSequenceTypes = xTypeProvider->getTypes();
1263 for (auto const& xType : xSequenceTypes)
1265 auto xClass = convertTypeToIdlClass(xType, mxContext);
1266 lclAppendNode(mpObjectInspectorWidgets->mpInterfacesTreeView, new ClassNode(xClass));
1271 /** Append services to the "services" tree view */
1272 void ObjectInspectorTreeHandler::appendServices(uno::Reference<uno::XInterface> const& xInterface)
1274 if (!xInterface.is())
1275 return;
1277 auto xServiceInfo = uno::Reference<lang::XServiceInfo>(xInterface, uno::UNO_QUERY);
1278 const uno::Sequence<OUString> aServiceNames(xServiceInfo->getSupportedServiceNames());
1279 for (auto const& aServiceName : aServiceNames)
1281 lclAppendNode(mpObjectInspectorWidgets->mpServicesTreeView,
1282 new SimpleStringNode(aServiceName));
1286 /** Append properties to the "properties" tree view */
1287 void ObjectInspectorTreeHandler::appendProperties(uno::Reference<uno::XInterface> const& xInterface)
1289 if (!xInterface.is())
1290 return;
1291 GenericPropertiesNode aNode(u""_ustr, uno::Any(xInterface), u""_ustr, mxContext);
1292 aNode.fillChildren(mpObjectInspectorWidgets->mpPropertiesTreeView, nullptr);
1295 /** Append methods to the "methods" tree view */
1296 void ObjectInspectorTreeHandler::appendMethods(uno::Reference<uno::XInterface> const& xInterface)
1298 if (!xInterface.is())
1299 return;
1301 uno::Reference<beans::XIntrospection> xIntrospection = beans::theIntrospection::get(mxContext);
1302 auto xIntrospectionAccess = xIntrospection->inspect(uno::Any(xInterface));
1304 const auto xMethods = xIntrospectionAccess->getMethods(beans::MethodConcept::ALL);
1305 for (auto const& xMethod : xMethods)
1307 lclAppendNode(mpObjectInspectorWidgets->mpMethodsTreeView, new MethodNode(xMethod));
1311 // Update the back button state depending if there are objects in the stack
1312 void ObjectInspectorTreeHandler::updateBackButtonState()
1314 mpObjectInspectorWidgets->mpToolbar->set_item_sensitive(u"back"_ustr,
1315 maInspectionStack.size() > 1);
1318 // Clears all the objects from the stack
1319 void ObjectInspectorTreeHandler::clearStack()
1321 maInspectionStack.clear();
1322 updateBackButtonState();
1325 // Adds an object to the stack
1326 void ObjectInspectorTreeHandler::addToStack(css::uno::Any const& rAny)
1328 maInspectionStack.push_back(rAny);
1329 updateBackButtonState();
1332 // Removes an object from the back of the stack and return it
1333 css::uno::Any ObjectInspectorTreeHandler::popFromStack()
1335 maInspectionStack.pop_back();
1336 uno::Any aAny = maInspectionStack.back();
1337 updateBackButtonState();
1338 return aAny;
1341 // Inspect the input object in the object inspector
1342 void ObjectInspectorTreeHandler::inspectObject(uno::Reference<uno::XInterface> const& xInterface)
1344 if (!xInterface.is())
1345 return;
1347 // Set implementation name
1348 OUString aImplementationName = getInterfaceImplementationClass(xInterface);
1349 mpObjectInspectorWidgets->mpClassNameLabel->set_label(aImplementationName);
1350 sal_Int32 nStrLen = aImplementationName.getLength();
1351 sal_Int32 nDigitWidth
1352 = mpObjectInspectorWidgets->mpClassNameLabel->get_approximate_digit_width();
1354 //get_about_digit_width() returns an approximate value. To always see the full class name (nStrLen+2)
1355 mpObjectInspectorWidgets->mpClassNameLabel->set_size_request((nStrLen + 2) * nDigitWidth, -1);
1357 // Fire entering the current opened page manually
1358 auto rPageId = mpObjectInspectorWidgets->mpNotebook->get_current_page_ident();
1359 NotebookEnterPage(rPageId);
1362 // Inspect the input object in the object inspector.
1363 // Make the input object the root of the stack (clear all other
1364 // objects from the stack).
1365 void ObjectInspectorTreeHandler::introspect(uno::Reference<uno::XInterface> const& xInterface)
1367 clearStack();
1368 addToStack(uno::Any(xInterface));
1369 inspectObject(xInterface);
1372 void ObjectInspectorTreeHandler::dispose()
1374 // We need to clear all the nodes
1375 clearAll(mpObjectInspectorWidgets->mpInterfacesTreeView);
1376 clearAll(mpObjectInspectorWidgets->mpServicesTreeView);
1377 clearAll(mpObjectInspectorWidgets->mpPropertiesTreeView);
1378 clearAll(mpObjectInspectorWidgets->mpMethodsTreeView);
1381 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */