tdf#134564 tdf#134578 Improve hierarchy viewing in Inspector

Significance of this patch -

* Added TreeView Lines in the ui file for Inspector
  for better hierarchy viewing
* Properties and there respective values are divided
  into separate columns.
* Grey out disabled properties
* bold PS, CS and DF

Change-Id: I825a75dd2c5bc54715fe59f3c639024a5e3ab5cb
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/98990
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
diff --git a/include/svx/sidebar/InspectorTextPanel.hxx b/include/svx/sidebar/InspectorTextPanel.hxx
index 30285a8..10ddf93 100644
--- a/include/svx/sidebar/InspectorTextPanel.hxx
+++ b/include/svx/sidebar/InspectorTextPanel.hxx
@@ -26,7 +26,20 @@ namespace svx::sidebar
struct TreeNode
{
    OUString sNodeName;
    css::uno::Any aValue;
    bool isGrey;
    enum
    {
        Category,
        ComplexProperty,
        SimpleProperty
    } NodeType;
    std::vector<TreeNode> children;
    TreeNode()
        : isGrey(false)
        , NodeType(SimpleProperty)
    {
    }
};
class SVX_DLLPUBLIC InspectorTextPanel : public PanelLayout
{
diff --git a/svx/source/sidebar/inspector/InspectorTextPanel.cxx b/svx/source/sidebar/inspector/InspectorTextPanel.cxx
index 6ab6b10..ddbee7f5 100644
--- a/svx/source/sidebar/inspector/InspectorTextPanel.cxx
+++ b/svx/source/sidebar/inspector/InspectorTextPanel.cxx
@@ -19,6 +19,9 @@

#include <svx/sidebar/InspectorTextPanel.hxx>

#include <svl/languageoptions.hxx>
#include <com/sun/star/awt/FontSlant.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/lang/IllegalArgumentException.hpp>

using namespace css;
@@ -45,6 +48,56 @@ InspectorTextPanel::InspectorTextPanel(vcl::Window* pParent,
    , mpListBoxStyles(m_xBuilder->weld_tree_view("listbox_fonts"))
{
    mpListBoxStyles->set_size_request(-1, mpListBoxStyles->get_height_rows(25));
    float fWidth = mpListBoxStyles->get_approximate_digit_width();
    std::vector<int> aWidths;
    aWidths.push_back(fWidth * 34);
    aWidths.push_back(fWidth * 15);
    mpListBoxStyles->set_column_fixed_widths(aWidths);
}

static bool GetPropertyValues(const OUString& rPropName, const uno::Any& rAny, OUString& rString)
{
    // Hide Asian and Complex properties
    if (SvtLanguageOptions().IsCJKFontEnabled() && rPropName.indexOf("Asian") != -1)
        return false;
    if (SvtLanguageOptions().IsCTLFontEnabled() && rPropName.indexOf("Complex") != -1)
        return false;

    if (bool bValue; rAny >>= bValue)
    {
        rString = OUString::boolean(bValue);
    }
    else if (OUString aValue; (rAny >>= aValue) && !(aValue.isEmpty()))
    {
        rString = aValue;
    }
    else if (awt::FontSlant eValue; rAny >>= eValue)
    {
        rString = (eValue == awt::FontSlant_ITALIC) ? OUStringLiteral("italic")
                                                    : OUStringLiteral("normal");
    }
    else if (long nValueLong; rAny >>= nValueLong)
    {
        if (rPropName.indexOf("Color") != -1)
            rString = "0x" + OUString::number(nValueLong, 16);
        else
            rString = OUString::number(nValueLong);
    }
    else if (double fValue; rAny >>= fValue)
    {
        if (rPropName.indexOf("Weight") != -1)
            rString = (fValue > 100) ? OUStringLiteral("bold") : OUStringLiteral("normal");
        else
            rString = OUString::number((round(fValue * 100)) / 100.00);
    }
    else if (short nValueShort; rAny >>= nValueShort)
    {
        rString = OUString::number(nValueShort);
    }
    else
        return false;

    return true;
}

static void FillBox_Impl(weld::TreeView& rListBoxStyles, const TreeNode& rCurrent,
@@ -52,10 +105,25 @@ static void FillBox_Impl(weld::TreeView& rListBoxStyles, const TreeNode& rCurren
{
    std::unique_ptr<weld::TreeIter> pResult = rListBoxStyles.make_iterator();
    const OUString& rName = rCurrent.sNodeName;
    rListBoxStyles.insert(pParent, -1, &rName, nullptr, nullptr, nullptr, false, pResult.get());
    OUString sPairValue;

    for (const TreeNode& rChildNode : rCurrent.children)
        FillBox_Impl(rListBoxStyles, rChildNode, pResult.get());
    if (rCurrent.NodeType != TreeNode::SimpleProperty
        || GetPropertyValues(rName, rCurrent.aValue, sPairValue))
    {
        rListBoxStyles.insert(pParent, -1, &rName, nullptr, nullptr, nullptr, false, pResult.get());
        rListBoxStyles.set_sensitive(*pResult, !rCurrent.isGrey, 0);
        rListBoxStyles.set_text_emphasis(*pResult, rCurrent.NodeType == TreeNode::Category, 0);

        if (rCurrent.NodeType == TreeNode::SimpleProperty)
        {
            rListBoxStyles.set_text(*pResult, sPairValue, 1);
            rListBoxStyles.set_sensitive(*pResult, !rCurrent.isGrey, 1);
            rListBoxStyles.set_text_emphasis(*pResult, false, 1);
        }

        for (const TreeNode& rChildNode : rCurrent.children)
            FillBox_Impl(rListBoxStyles, rChildNode, pResult.get());
    }
}

void InspectorTextPanel::updateEntries(const std::vector<TreeNode>& rStore)
diff --git a/svx/uiconfig/ui/inspectortextpanel.ui b/svx/uiconfig/ui/inspectortextpanel.ui
index af7c5cb..71199a8 100644
--- a/svx/uiconfig/ui/inspectortextpanel.ui
+++ b/svx/uiconfig/ui/inspectortextpanel.ui
@@ -4,10 +4,20 @@
  <requires lib="gtk+" version="3.18"/>
  <object class="GtkTreeStore" id="liststore">
    <columns>
      <!-- column-name text -->
      <!-- column-name text1 -->
      <column type="gchararray"/>
      <!-- column-name text2 -->
      <column type="gchararray"/>
      <!-- column-name id -->
      <column type="gchararray"/>
      <!-- column-name weight1 -->
      <column type="gint"/>
      <!-- column-name weight2 -->
      <column type="gint"/>
      <!-- column-name sensitive1 -->
      <column type="gboolean"/>
      <!-- column-name sensitive2 -->
      <column type="gboolean"/>
    </columns>
  </object>
  <object class="GtkGrid" id="InspectorTextPanel">
@@ -40,12 +50,14 @@
                  <object class="GtkTreeView" id="listbox_fonts">
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="receives_default">True</property>
                    <property name="hexpand">True</property>
                    <property name="vexpand">True</property>
                    <property name="model">liststore</property>
                    <property name="headers_visible">False</property>
                    <property name="headers_clickable">False</property>
                    <property name="search_column">0</property>
                    <property name="enable_tree_lines">True</property>
                    <child internal-child="selection">
                      <object class="GtkTreeSelection"/>
                    </child>
@@ -54,7 +66,21 @@
                        <child>
                          <object class="GtkCellRendererText" id="cellrenderertext1"/>
                          <attributes>
                            <attribute name="sensitive">5</attribute>
                            <attribute name="text">0</attribute>
                            <attribute name="weight">3</attribute>
                          </attributes>
                        </child>
                      </object>
                    </child>
                    <child>
                      <object class="GtkTreeViewColumn" id="treeviewcolumn2">
                        <child>
                          <object class="GtkCellRendererText" id="cellrenderertext2"/>
                          <attributes>
                            <attribute name="sensitive">6</attribute>
                            <attribute name="text">1</attribute>
                            <attribute name="weight">4</attribute>
                          </attributes>
                        </child>
                      </object>
diff --git a/sw/source/uibase/sidebar/WriterInspectorTextPanel.cxx b/sw/source/uibase/sidebar/WriterInspectorTextPanel.cxx
index 3082492..a6faa29 100644
--- a/sw/source/uibase/sidebar/WriterInspectorTextPanel.cxx
+++ b/sw/source/uibase/sidebar/WriterInspectorTextPanel.cxx
@@ -25,14 +25,12 @@
#include <wrtsh.hxx>
#include <com/sun/star/text/XTextRange.hpp>
#include <com/sun/star/text/XTextCursor.hpp>
#include <com/sun/star/awt/FontSlant.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/beans/XPropertyState.hpp>
#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
#include <com/sun/star/lang/IllegalArgumentException.hpp>

#include <unotextrange.hxx>
#include <svl/languageoptions.hxx>

namespace sw::sidebar
{
@@ -59,54 +57,6 @@ WriterInspectorTextPanel::WriterInspectorTextPanel(vcl::Window* pParent,
        pShell->SetChgLnk(LINK(this, WriterInspectorTextPanel, AttrChangedNotify));
}

static bool GetPropertyValues(const beans::Property rProperty, const uno::Any& rAny,
                              OUString& rString)
{
    // Hide Asian and Complex properties
    if (SvtLanguageOptions().IsCJKFontEnabled() && rProperty.Name.indexOf("Asian") != -1)
        return false;
    if (SvtLanguageOptions().IsCTLFontEnabled() && rProperty.Name.indexOf("Complex") != -1)
        return false;

    rString = rProperty.Name + "     ";

    if (bool bValue; rAny >>= bValue)
    {
        rString += OUString::boolean(bValue);
    }
    else if (OUString aValue; (rAny >>= aValue) && !(aValue.isEmpty()))
    {
        rString += aValue;
    }
    else if (awt::FontSlant eValue; rAny >>= eValue)
    {
        rString += (eValue == awt::FontSlant_ITALIC) ? OUStringLiteral("italic")
                                                     : OUStringLiteral("normal");
    }
    else if (long nValueLong; rAny >>= nValueLong)
    {
        if (rString.indexOf("Color") != -1)
            rString += "0x" + OUString::number(nValueLong, 16);
        else
            rString += OUString::number(nValueLong);
    }
    else if (double fValue; rAny >>= fValue)
    {
        if (rString.indexOf("Weight") != -1)
            rString += (fValue > 100) ? OUStringLiteral("bold") : OUStringLiteral("normal");
        else
            rString += OUString::number((round(fValue * 100)) / 100.00);
    }
    else if (short nValueShort; rAny >>= nValueShort)
    {
        rString += OUString::number(nValueShort);
    }
    else
        return false;

    return true;
}

static void UpdateTree(SwDocShell* pDocSh, std::vector<svx::sidebar::TreeNode>& aStore)
{
    SwDoc* pDoc = pDocSh->GetDoc();
@@ -118,6 +68,9 @@ static void UpdateTree(SwDocShell* pDocSh, std::vector<svx::sidebar::TreeNode>& 
    aDFNode.sNodeName = "Direct Formatting";
    aCharNode.sNodeName = "Character Styles";
    aParaNode.sNodeName = "Paragraph Styles";
    aDFNode.NodeType = svx::sidebar::TreeNode::Category;
    aCharNode.NodeType = svx::sidebar::TreeNode::Category;
    aParaNode.NodeType = svx::sidebar::TreeNode::Category;

    uno::Reference<text::XTextRange> xRange(
        SwXTextRange::CreateXTextRange(*pDoc, *pCursor->GetPoint(), nullptr));
@@ -133,15 +86,12 @@ static void UpdateTree(SwDocShell* pDocSh, std::vector<svx::sidebar::TreeNode>& 
    {
        if (xPropertiesState->getPropertyState(rProperty.Name) == beans::PropertyState_DIRECT_VALUE)
        {
            OUString aPropertyValuePair;
            const uno::Any aAny = xPropertiesSet->getPropertyValue(rProperty.Name);
            if (GetPropertyValues(rProperty, aAny, aPropertyValuePair))
            {
                aIsDefined[rProperty.Name] = true;
                svx::sidebar::TreeNode aTemp;
                aTemp.sNodeName = aPropertyValuePair;
                aDFNode.children.push_back(aTemp);
            }
            aIsDefined[rProperty.Name] = true;
            svx::sidebar::TreeNode aTemp;
            aTemp.sNodeName = rProperty.Name;
            aTemp.aValue = aAny;
            aDFNode.children.push_back(aTemp);
        }
    }

@@ -164,24 +114,21 @@ static void UpdateTree(SwDocShell* pDocSh, std::vector<svx::sidebar::TreeNode>& 
        aProperties = xPropertiesSet->getPropertySetInfo()->getProperties();
        svx::sidebar::TreeNode aCurrentChild;
        aCurrentChild.sNodeName = sDisplayName;
        aCurrentChild.NodeType = svx::sidebar::TreeNode::ComplexProperty;

        for (const beans::Property& rProperty : std::as_const(aProperties))
        {
            OUString sPropName = rProperty.Name;
            if (xPropertiesState->getPropertyState(sPropName) == beans::PropertyState_DIRECT_VALUE)
            {
                OUString aPropertyValuePair;
                const uno::Any aAny = xPropertiesSet->getPropertyValue(sPropName);
                if (GetPropertyValues(rProperty, aAny, aPropertyValuePair))
                {
                    if (aIsDefined[sPropName]) // Already defined in "Direct Formatting" ?
                        aPropertyValuePair = aPropertyValuePair + "  !!<GREY>!!";
                    else
                        aIsDefined[sPropName] = true;
                    svx::sidebar::TreeNode aTemp;
                    aTemp.sNodeName = aPropertyValuePair;
                    aCurrentChild.children.push_back(aTemp);
                }
                svx::sidebar::TreeNode aTemp;
                if (aIsDefined[sPropName]) // Already defined in "Direct Formatting" ?
                    aTemp.isGrey = true;
                aIsDefined[sPropName] = true;
                aTemp.sNodeName = sPropName;
                aTemp.aValue = aAny;
                aCurrentChild.children.push_back(aTemp);
            }
        }

@@ -201,6 +148,7 @@ static void UpdateTree(SwDocShell* pDocSh, std::vector<svx::sidebar::TreeNode>& 
        OUString aParentParaStyle = xPropertiesStyle->getParentStyle();
        svx::sidebar::TreeNode aCurrentChild;
        aCurrentChild.sNodeName = sDisplayName;
        aCurrentChild.NodeType = svx::sidebar::TreeNode::ComplexProperty;

        for (const beans::Property& rProperty : std::as_const(aProperties))
        {
@@ -209,19 +157,15 @@ static void UpdateTree(SwDocShell* pDocSh, std::vector<svx::sidebar::TreeNode>& 
                || xPropertiesState->getPropertyState(sPropName)
                       == beans::PropertyState_DIRECT_VALUE)
            {
                OUString aPropertyValuePair;
                const uno::Any aAny = xPropertiesSet->getPropertyValue(sPropName);
                if (GetPropertyValues(rProperty, aAny, aPropertyValuePair))
                {
                    // Already defined in "Default Formatting" or "Character Styles" or any child Paragraph Style ?
                    if (aIsDefined[sPropName])
                        aPropertyValuePair = aPropertyValuePair + "    !!<GREY>!! ";
                    else
                        aIsDefined[sPropName] = true;
                    svx::sidebar::TreeNode aTemp;
                    aTemp.sNodeName = aPropertyValuePair;
                    aCurrentChild.children.push_back(aTemp);
                }
                svx::sidebar::TreeNode aTemp;
                // Already defined in "Default Formatting" or "Character Styles" or any child Paragraph Style ?
                if (aIsDefined[sPropName])
                    aTemp.isGrey = true;
                aIsDefined[sPropName] = true;
                aTemp.sNodeName = sPropName;
                aTemp.aValue = aAny;
                aCurrentChild.children.push_back(aTemp);
            }
        }