cui/source/tabpages/paragrph.cxx |   68 +++++++++++++++++++--------
 editeng/source/uno/unoipset.cxx  |    4 -
 include/svx/relfld.hxx           |   12 ++++
 include/tools/fldunit.hxx        |    2 
 include/vcl/fieldvalues.hxx      |    1 
 svx/source/dialog/relfld.cxx     |   95 ++++++++++++++++++++++++++++++---------
 vcl/inc/units.hrc                |    6 ++
 vcl/source/control/field.cxx     |   10 ++++
 8 files changed, 153 insertions(+), 45 deletions(-)

New commits:
commit 78a18a5dc6986c9f5612f26d164c62202a1b94f8
Author:     Jonathan Clark <jonat...@libreoffice.org>
AuthorDate: Wed Nov 13 03:24:21 2024 -0700
Commit:     Jonathan Clark <jonat...@libreoffice.org>
CommitDate: Thu Nov 14 17:30:06 2024 +0100

    tdf#36709 GUI changes for font-relative first-line indent
    
    This change includes GUI element changes to support viewing and editing
    first-line indent values with font-relative units in the paragraph style
    dialog.
    
    Change-Id: I72ada2565f51d70475eb17096a1317be9316b770
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176595
    Reviewed-by: Jonathan Clark <jonat...@libreoffice.org>
    Tested-by: Jenkins

diff --git a/cui/source/tabpages/paragrph.cxx b/cui/source/tabpages/paragrph.cxx
index 2889ea2cdf76..a8f6150d0dab 100644
--- a/cui/source/tabpages/paragrph.cxx
+++ b/cui/source/tabpages/paragrph.cxx
@@ -102,6 +102,44 @@ enum LineSpaceList
     LLINESPACE_FIX  = 7
 };
 
+SvxIndentValue lcl_GetFontRelativeValue(SvxRelativeField& rField, MapUnit 
eUnit)
+{
+    switch (rField.GetCurrentUnit())
+    {
+        case FieldUnit::FONT_EM:
+            return SvxIndentValue{ 
static_cast<double>(rField.get_value(FieldUnit::NONE)) / 100.0,
+                                   css::util::MeasureUnit::FONT_EM };
+
+        case FieldUnit::FONT_CJK_ADVANCE:
+            return SvxIndentValue{ 
static_cast<double>(rField.get_value(FieldUnit::NONE)) / 100.0,
+                                   css::util::MeasureUnit::FONT_CJK_ADVANCE };
+
+        default:
+            return 
SvxIndentValue::twips(static_cast<double>(rField.GetCoreValue(eUnit)));
+    }
+}
+
+void lcl_SetFontRelativeValue(SvxRelativeField& rField, const SvxIndentValue& 
rValue, MapUnit eUnit)
+{
+    switch (rValue.m_nUnit)
+    {
+        case css::util::MeasureUnit::FONT_EM:
+            rField.SetFontRelative(FieldUnit::FONT_EM);
+            
rField.set_value(static_cast<sal_Int64>(std::llround(rValue.m_dValue * 100.0)),
+                             FieldUnit::FONT_EM);
+            break;
+
+        case css::util::MeasureUnit::FONT_CJK_ADVANCE:
+            rField.SetFontRelative(FieldUnit::FONT_CJK_ADVANCE);
+            
rField.set_value(static_cast<sal_Int64>(std::llround(rValue.m_dValue * 100.0)),
+                             FieldUnit::FONT_CJK_ADVANCE);
+            break;
+
+        default:
+            
rField.SetMetricValue(static_cast<sal_Int64>(std::llround(rValue.m_dValue)), 
eUnit);
+            break;
+    }
+}
 }
 
 static void SetLineSpace_Impl( SvxLineSpacingItem&, int, tools::Long lValue = 
0 );
@@ -417,16 +455,12 @@ bool SvxStdParagraphTabPage::FillItemSet( SfxItemSet* 
rOutSet )
             }
             else
             {
-                // tdf#36709: TODO: Handle font-relative units from GUI
-                item.SetTextFirstLineOffset(
-                    SvxIndentValue::twips(m_aFLineIndent.GetCoreValue(eUnit)),
-                    css::util::MeasureUnit::TWIP);
+                
item.SetTextFirstLineOffset(lcl_GetFontRelativeValue(m_aFLineIndent, eUnit));
             }
         }
         else
         {
-            // tdf#36709: TODO: Handle font-relative units from GUI
-            
item.SetTextFirstLineOffset(SvxIndentValue::twips(m_aFLineIndent.GetCoreValue(eUnit)));
+            
item.SetTextFirstLineOffset(lcl_GetFontRelativeValue(m_aFLineIndent, eUnit));
         }
         item.SetAutoFirst(m_xAutoCB->get_active());
         if (item.GetTextFirstLineOffsetValue() < 0)
@@ -478,18 +512,14 @@ bool SvxStdParagraphTabPage::FillItemSet( SfxItemSet* 
rOutSet )
                     
static_cast<sal_uInt16>(m_aFLineIndent.get_value(FieldUnit::NONE)));
             else
             {
-                // tdf#36709: TODO: Handle font-relative units from GUI
-                aMargin.SetTextFirstLineOffset(
-                    SvxIndentValue::twips(m_aFLineIndent.GetCoreValue(eUnit)));
+                
aMargin.SetTextFirstLineOffset(lcl_GetFontRelativeValue(m_aFLineIndent, eUnit));
             }
         }
         else
         {
             aMargin.SetTextLeft(m_aLeftIndent.GetCoreValue(eUnit));
             aMargin.SetRight(m_aRightIndent.GetCoreValue(eUnit));
-            // tdf#36709: TODO: Handle font-relative units from GUI
-            aMargin.SetTextFirstLineOffset(
-                SvxIndentValue::twips(m_aFLineIndent.GetCoreValue(eUnit)));
+            
aMargin.SetTextFirstLineOffset(lcl_GetFontRelativeValue(m_aFLineIndent, eUnit));
         }
         aMargin.SetAutoFirst(m_xAutoCB->get_active());
         if ( aMargin.GetTextFirstLineOffsetValue() < 0.0 )
@@ -672,18 +702,17 @@ void SvxStdParagraphTabPage::Reset( const SfxItemSet* 
rSet )
             }
             else
             {
-                // tdf#36709: TODO: Handle font-relative units from GUI
                 m_aFLineIndent.SetRelative(false);
                 m_aFLineIndent.set_min(-9999, FieldUnit::NONE);
                 m_aFLineIndent.SetFieldUnit(eFUnit);
-                
m_aFLineIndent.SetMetricValue(rOldFirstLine.GetTextFirstLineOffsetValue(), 
eUnit);
+                lcl_SetFontRelativeValue(m_aFLineIndent, 
rOldFirstLine.GetTextFirstLineOffset(),
+                                         eUnit);
             }
             m_xAutoCB->set_active(rOldFirstLine.IsAutoFirst());
         }
         else
         {
-            // tdf#36709: TODO: Handle font-relative units from GUI
-            
m_aFLineIndent.SetMetricValue(rOldFirstLine.GetTextFirstLineOffsetValue(), 
eUnit);
+            lcl_SetFontRelativeValue(m_aFLineIndent, 
rOldFirstLine.GetTextFirstLineOffset(), eUnit);
             m_xAutoCB->set_active(rOldFirstLine.IsAutoFirst());
         }
         AutoHdl_Impl(*m_xAutoCB);
@@ -739,8 +768,7 @@ void SvxStdParagraphTabPage::Reset( const SfxItemSet* rSet )
                 m_aFLineIndent.SetRelative(false);
                 m_aFLineIndent.set_min(-9999, FieldUnit::NONE);
                 m_aFLineIndent.SetFieldUnit(eFUnit);
-                // tdf#36709: TODO: Populate GUI with font-relative unit
-                
m_aFLineIndent.SetMetricValue(rOldItem.GetTextFirstLineOffsetValue(), eUnit);
+                lcl_SetFontRelativeValue(m_aFLineIndent, 
rOldItem.GetTextFirstLineOffset(), eUnit);
             }
             m_xAutoCB->set_active(rOldItem.IsAutoFirst());
         }
@@ -751,8 +779,7 @@ void SvxStdParagraphTabPage::Reset( const SfxItemSet* rSet )
 
             m_aLeftIndent.SetMetricValue(rSpace.GetTextLeft(), eUnit);
             m_aRightIndent.SetMetricValue(rSpace.GetRight(), eUnit);
-            // tdf#36709: TODO: Populate GUI with font-relative units
-            
m_aFLineIndent.SetMetricValue(rSpace.GetTextFirstLineOffsetValue(), eUnit);
+            lcl_SetFontRelativeValue(m_aFLineIndent, 
rSpace.GetTextFirstLineOffset(), eUnit);
             m_xAutoCB->set_active(rSpace.IsAutoFirst());
         }
         AutoHdl_Impl(*m_xAutoCB);
@@ -951,6 +978,7 @@ 
SvxStdParagraphTabPage::SvxStdParagraphTabPage(weld::Container* pPage, weld::Dia
 
     Init_Impl();
     m_aFLineIndent.set_min(-9999, FieldUnit::NONE);    // is set to 0 on 
default
+    m_aFLineIndent.EnableFontRelativeMode();
 }
 
 SvxStdParagraphTabPage::~SvxStdParagraphTabPage()
diff --git a/editeng/source/uno/unoipset.cxx b/editeng/source/uno/unoipset.cxx
index a17783637818..43cb71aa0a86 100644
--- a/editeng/source/uno/unoipset.cxx
+++ b/editeng/source/uno/unoipset.cxx
@@ -72,10 +72,10 @@ uno::Any SvxItemPropertySet::getPropertyValue( const 
SfxItemPropertyMapEntry* pM
 
     if(pItem)
     {
-        pItem->QueryValue( aVal, nMemberId );
+        auto bQuerySucceeded = pItem->QueryValue(aVal, nMemberId);
         if( pMap->nMoreFlags & PropertyMoreFlags::METRIC_ITEM )
         {
-            if( eMapUnit != MapUnit::Map100thMM )
+            if (bQuerySucceeded && eMapUnit != MapUnit::Map100thMM)
             {
                 if ( !bDontConvertNegativeValues || 
SvxUnoCheckForPositiveValue( aVal ) )
                     SvxUnoConvertToMM( eMapUnit, aVal );
diff --git a/include/svx/relfld.hxx b/include/svx/relfld.hxx
index f035762da825..6cb3c8e9eb0b 100644
--- a/include/svx/relfld.hxx
+++ b/include/svx/relfld.hxx
@@ -29,11 +29,14 @@ class SVX_DLLPUBLIC SvxRelativeField
 private:
     std::unique_ptr<weld::MetricSpinButton> m_xSpinButton;
 
+    FieldUnit eAbsoluteFieldUnit = FieldUnit::NONE;
+    FieldUnit eFontRelativeFieldUnit = FieldUnit::NONE;
     sal_uInt16          nRelMin;
     sal_uInt16          nRelMax;
     bool                bRelativeMode;
     bool                bRelative;
     bool                bNegativeEnabled;
+    bool bFontRelativeMode;
 
     DECL_DLLPRIVATE_LINK(ModifyHdl, weld::Entry&, void);
 
@@ -41,9 +44,12 @@ public:
     SvxRelativeField(std::unique_ptr<weld::MetricSpinButton> pControl);
 
     void            EnableRelativeMode( sal_uInt16 nMin, sal_uInt16 nMax );
+    void EnableFontRelativeMode();
     void            SetRelative( bool bRelative );
+    void SetFontRelative(FieldUnit eNewRelativeUnit);
     bool            IsRelative() const { return bRelative; }
     void            EnableNegativeMode() {bNegativeEnabled = true;}
+    FieldUnit GetCurrentUnit() const { return eFontRelativeFieldUnit; }
 
     void set_sensitive(bool sensitive) { 
m_xSpinButton->set_sensitive(sensitive); }
     bool get_sensitive() const { return m_xSpinButton->get_sensitive(); }
@@ -62,7 +68,11 @@ public:
     weld::SpinButton& get_widget() { return m_xSpinButton->get_widget(); }
 
     sal_Int64 GetCoreValue(MapUnit eUnit) const { return 
::GetCoreValue(*m_xSpinButton, eUnit); }
-    void SetFieldUnit(FieldUnit eUnit, bool bAll = false) { 
::SetFieldUnit(*m_xSpinButton, eUnit, bAll); }
+    void SetFieldUnit(FieldUnit eUnit, bool bAll = false)
+    {
+        ::SetFieldUnit(*m_xSpinButton, eUnit, bAll);
+        eAbsoluteFieldUnit = m_xSpinButton->get_unit();
+    }
     void SetMetricValue(sal_Int64 lCoreValue, MapUnit eUnit) { 
::SetMetricValue(*m_xSpinButton, lCoreValue, eUnit); }
 };
 
diff --git a/include/tools/fldunit.hxx b/include/tools/fldunit.hxx
index 72ab9ad92d87..28649be98c00 100644
--- a/include/tools/fldunit.hxx
+++ b/include/tools/fldunit.hxx
@@ -47,6 +47,8 @@ enum class FieldUnit : sal_uInt16
     DEGREE,
     SECOND,
     MILLISECOND,
+    FONT_EM,
+    FONT_CJK_ADVANCE,
 };
 
 constexpr o3tl::Length FieldToO3tlLength(FieldUnit eU, o3tl::Length 
ePixelValue = o3tl::Length::px)
diff --git a/include/vcl/fieldvalues.hxx b/include/vcl/fieldvalues.hxx
index 220aef2e3b1a..c21b52c14e4f 100644
--- a/include/vcl/fieldvalues.hxx
+++ b/include/vcl/fieldvalues.hxx
@@ -38,6 +38,7 @@ VCL_DLLPUBLIC FieldUnit 
EnglishStringToMetric(std::u16string_view rEnglishMetric
 VCL_DLLPUBLIC bool TextToValue(const OUString& rStr, double& rValue, sal_Int64 
nBaseValue,
                                sal_uInt16 nDecDigits, const LocaleDataWrapper& 
rLocaleDataWrapper,
                                FieldUnit eUnit);
+VCL_DLLPUBLIC FieldUnit GetTextMetricUnit(std::u16string_view aStr);
 
 VCL_DLLPUBLIC sal_Int64 ConvertValue(sal_Int64 nValue, sal_Int64 mnBaseValue, 
sal_uInt16 nDecDigits,
                                      FieldUnit eInUnit, FieldUnit eOutUnit);
diff --git a/svx/source/dialog/relfld.cxx b/svx/source/dialog/relfld.cxx
index 3929e4fcf7df..77da81b0c77b 100644
--- a/svx/source/dialog/relfld.cxx
+++ b/svx/source/dialog/relfld.cxx
@@ -18,6 +18,7 @@
  */
 
 #include <svx/relfld.hxx>
+#include <vcl/fieldvalues.hxx>
 
 SvxRelativeField::SvxRelativeField(std::unique_ptr<weld::MetricSpinButton> 
pControl)
     : m_xSpinButton(std::move(pControl))
@@ -26,7 +27,7 @@ 
SvxRelativeField::SvxRelativeField(std::unique_ptr<weld::MetricSpinButton> pCont
     , bRelativeMode(false)
     , bRelative(false)
     , bNegativeEnabled(false)
-
+    , bFontRelativeMode(false)
 {
     weld::SpinButton& rSpinButton = m_xSpinButton->get_widget();
     rSpinButton.connect_changed(LINK(this, SvxRelativeField, ModifyHdl));
@@ -34,35 +35,57 @@ 
SvxRelativeField::SvxRelativeField(std::unique_ptr<weld::MetricSpinButton> pCont
 
 IMPL_LINK_NOARG(SvxRelativeField, ModifyHdl, weld::Entry&, void)
 {
-    if (!bRelativeMode)
-        return;
-
-    OUString  aStr = m_xSpinButton->get_text();
-    bool      bNewMode = bRelative;
-
-    if ( bRelative )
+    if (bRelativeMode)
     {
-        const sal_Unicode* pStr = aStr.getStr();
+        OUString aStr = m_xSpinButton->get_text();
+        bool bNewMode = bRelative;
 
-        while ( *pStr )
+        if (bRelative)
         {
-            if( ( ( *pStr < '0' ) || ( *pStr > '9' ) ) &&
-                ( *pStr != '%' ) )
+            const sal_Unicode* pStr = aStr.getStr();
+
+            while (*pStr)
             {
-                bNewMode = false;
-                break;
+                if (((*pStr < '0') || (*pStr > '9')) && (*pStr != '%'))
+                {
+                    bNewMode = false;
+                    break;
+                }
+                pStr++;
             }
-            pStr++;
         }
+        else
+        {
+            if (aStr.indexOf("%") != -1)
+                bNewMode = true;
+        }
+
+        if (bNewMode != bRelative)
+            SetRelative(bNewMode);
     }
-    else
+
+    if (bFontRelativeMode)
     {
-        if ( aStr.indexOf( "%" ) != -1 )
-            bNewMode = true;
-    }
+        OUString aStr = m_xSpinButton->get_text();
+        FieldUnit eNewFieldUnit = vcl::GetTextMetricUnit(aStr);
+
+        // Only allow font-relative units
+        switch (eNewFieldUnit)
+        {
+            default:
+                eNewFieldUnit = FieldUnit::NONE;
+                break;
+
+            case FieldUnit::FONT_EM:
+            case FieldUnit::FONT_CJK_ADVANCE:
+                break;
+        }
 
-    if ( bNewMode != bRelative )
-        SetRelative( bNewMode );
+        if (eNewFieldUnit != eFontRelativeFieldUnit)
+        {
+            SetFontRelative(eNewFieldUnit);
+        }
+    }
 }
 
 void SvxRelativeField::EnableRelativeMode(sal_uInt16 nMin, sal_uInt16 nMax)
@@ -73,6 +96,8 @@ void SvxRelativeField::EnableRelativeMode(sal_uInt16 nMin, 
sal_uInt16 nMax)
     m_xSpinButton->set_unit(FieldUnit::CM);
 }
 
+void SvxRelativeField::EnableFontRelativeMode() { bFontRelativeMode = true; }
+
 void SvxRelativeField::SetRelative( bool bNewRelative )
 {
     weld::SpinButton& rSpinButton = m_xSpinButton->get_widget();
@@ -81,6 +106,8 @@ void SvxRelativeField::SetRelative( bool bNewRelative )
     rSpinButton.get_selection_bounds(nStartPos, nEndPos);
     OUString aStr = rSpinButton.get_text();
 
+    eFontRelativeFieldUnit = FieldUnit::NONE;
+
     if ( bNewRelative )
     {
         bRelative = true;
@@ -100,4 +127,30 @@ void SvxRelativeField::SetRelative( bool bNewRelative )
     rSpinButton.select_region(nStartPos, nEndPos);
 }
 
+void SvxRelativeField::SetFontRelative(FieldUnit eNewRelativeUnit)
+{
+    weld::SpinButton& rSpinButton = m_xSpinButton->get_widget();
+
+    int nStartPos, nEndPos;
+    rSpinButton.get_selection_bounds(nStartPos, nEndPos);
+    OUString aStr = rSpinButton.get_text();
+
+    bRelative = false;
+    eFontRelativeFieldUnit = eNewRelativeUnit;
+    m_xSpinButton->set_digits(2);
+    m_xSpinButton->set_range(bNegativeEnabled ? -9999 : 0, 9999, 
FieldUnit::NONE);
+
+    if (eNewRelativeUnit == FieldUnit::NONE)
+    {
+        m_xSpinButton->set_unit(eAbsoluteFieldUnit);
+    }
+    else
+    {
+        m_xSpinButton->set_unit(eNewRelativeUnit);
+    }
+
+    rSpinButton.set_text(aStr);
+    rSpinButton.select_region(nStartPos, nEndPos);
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/units.hrc b/vcl/inc/units.hrc
index 677f9f5cefee..516cc12477d6 100644
--- a/vcl/inc/units.hrc
+++ b/vcl/inc/units.hrc
@@ -56,8 +56,12 @@ std::pair<TranslateId, FieldUnit> SV_FUNIT_STRINGS[] =
     /* To translators: degree */
     { NC_("SV_FUNIT_STRINGS", "°"), FieldUnit::DEGREE },
     { NC_("SV_FUNIT_STRINGS", "sec"), FieldUnit::SECOND },
+    { NC_("SV_FUNIT_STRINGS", "ms"), FieldUnit::MILLISECOND },
+    /* To translators: standard typographical metric 'em' */
+    { NC_("SV_FUNIT_STRINGS", "em"), FieldUnit::FONT_EM },
     // To translators: This is the last entry of the sequence of measurement 
unit names
-    { NC_("SV_FUNIT_STRINGS", "ms"), FieldUnit::MILLISECOND }
+    /* To translators: CSS unit 'ic'; CJK full-width advance in the current 
font */
+    { NC_("SV_FUNIT_STRINGS", "ic"), FieldUnit::FONT_CJK_ADVANCE }
 };
 
 #endif // INCLUDED_VCL_INC_UNITS_HRC
diff --git a/vcl/source/control/field.cxx b/vcl/source/control/field.cxx
index cfbef9171efc..d0ae78e907bf 100644
--- a/vcl/source/control/field.cxx
+++ b/vcl/source/control/field.cxx
@@ -117,6 +117,12 @@ std::string FieldUnitToString(FieldUnit unit)
 
         case FieldUnit::MILLISECOND:
             return "millisecond";
+
+        case FieldUnit::FONT_EM:
+            return "em";
+
+        case FieldUnit::FONT_CJK_ADVANCE:
+            return "ic";
     }
 
     return "";
@@ -1161,6 +1167,8 @@ namespace vcl
              eInUnit == FieldUnit::SECOND ||
              eInUnit == FieldUnit::MILLISECOND ||
              eInUnit == FieldUnit::PIXEL ||
+             eInUnit == FieldUnit::FONT_EM ||
+             eInUnit == FieldUnit::FONT_CJK_ADVANCE ||
              eOutUnit == MapUnit::MapPixel ||
              eOutUnit == MapUnit::MapSysFont ||
              eOutUnit == MapUnit::MapAppFont ||
@@ -1212,6 +1220,8 @@ namespace vcl
 
         return true;
     }
+
+    FieldUnit GetTextMetricUnit(std::u16string_view aStr) { return 
ImplMetricGetUnit(aStr); }
 }
 
 void MetricFormatter::ImplMetricReformat( const OUString& rStr, double& 
rValue, OUString& rOutStr )

Reply via email to