[Libreoffice-commits] core.git: sc/source sc/uiconfig

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Sat Dec 22 22:28:30 UTC 2018


 sc/source/ui/StatisticsDialogs/SamplingDialog.cxx |  124 ++++++++++++++++++----
 sc/source/ui/inc/SamplingDialog.hxx               |    9 +
 sc/uiconfig/scalc/ui/samplingdialog.ui            |   55 ++++++++-
 3 files changed, 159 insertions(+), 29 deletions(-)

New commits:
commit 2c5c20b19c349a4b7f6d78d69d8d57f9af5c351c
Author:     Eike Rathke <erack at redhat.com>
AuthorDate: Sat Dec 22 22:06:02 2018 +0100
Commit:     Eike Rathke <erack at redhat.com>
CommitDate: Sat Dec 22 23:28:11 2018 +0100

    Rework Data -> Statistics dialog, add WithReplacement and KeepOrder
    
    * Add "With replacement" checkbutton
      * checked: WR (with replacement, put back after draw), larger
        sample size than population size possible
        * mutually exclusive with "Keep order"
      * unchecked: WOR (without replacement, do not put back after
        draw), sample size limited to population size
        * automatically unchecked for "Periodic" samples
    
    * Add "Keep order" checkbutton
      * checked: samples are drawn in order of population data
        * WOR method mutually exclusive with "With replacement"
        * automatically checked for "Periodic" samples
      * unchecked: samples are drawn in random order
    
    * Limit "Sample size" and "Period" input fields to size of
      population for all WOR methods
      * when limiting, increment "Sample size" and "Period" up to
        their last known value when enlargening the population size
    
    Previously, for "Periodic" samples the "Period" field was never
    limited, which for populations of smaller size makes no sense.
    
    The new recent implementation for "Random" without "Keep order"
    and without "With replacement" set (WOR) strictly needs "Sample
    size" limited to population size.
    
    Change-Id: I3c0bef402afb775bca7ae877e6424f4a4eaae359
    Reviewed-on: https://gerrit.libreoffice.org/65574
    Reviewed-by: Eike Rathke <erack at redhat.com>
    Tested-by: Jenkins

diff --git a/sc/source/ui/StatisticsDialogs/SamplingDialog.cxx b/sc/source/ui/StatisticsDialogs/SamplingDialog.cxx
index b43cef257d4e..33d8d0bc07f0 100644
--- a/sc/source/ui/StatisticsDialogs/SamplingDialog.cxx
+++ b/sc/source/ui/StatisticsDialogs/SamplingDialog.cxx
@@ -35,6 +35,8 @@ ScSamplingDialog::ScSamplingDialog(
     mAddressDetails ( mDocument->GetAddressConvention(), 0, 0 ),
     mOutputAddress  ( ScAddress::INITIALIZE_INVALID ),
     mCurrentAddress ( pViewData->GetCurX(), pViewData->GetCurY(), pViewData->GetTabNo() ),
+    mnLastSampleSizeValue(1),
+    mnLastPeriodValue(1),
     mDialogLostFocus( false )
 {
     get(mpInputRangeLabel,  "input-range-label");
@@ -53,6 +55,8 @@ ScSamplingDialog::ScSamplingDialog(
     get(mpPeriod,     "period-spin");
 
     get(mpRandomMethodRadio,   "random-method-radio");
+    get(mpWithReplacement,     "with-replacement");
+    get(mpKeepOrder,           "keep-order");
     get(mpPeriodicMethodRadio, "periodic-method-radio");
 
     get(mpButtonOk,     "ok");
@@ -77,6 +81,8 @@ void ScSamplingDialog::dispose()
     mpSampleSize.clear();
     mpPeriod.clear();
     mpRandomMethodRadio.clear();
+    mpWithReplacement.clear();
+    mpKeepOrder.clear();
     mpPeriodicMethodRadio.clear();
     mpButtonOk.clear();
     mpActiveEdit.clear();
@@ -105,12 +111,13 @@ void ScSamplingDialog::Init()
     mpOutputRangeEdit->SetModifyHdl( aLink2);
 
     mpSampleSize->SetModifyHdl( LINK( this, ScSamplingDialog, SamplingSizeValueModified ));
+    mpPeriod->SetModifyHdl( LINK( this, ScSamplingDialog, PeriodValueModified ));
 
     mpPeriodicMethodRadio->SetToggleHdl( LINK( this, ScSamplingDialog, ToggleSamplingMethod ) );
     mpRandomMethodRadio->SetToggleHdl( LINK( this, ScSamplingDialog, ToggleSamplingMethod ) );
 
-    mpSampleSize->SetMin( 0 );
-    mpSampleSize->SetMax( SAL_MAX_INT64 );
+    mpWithReplacement->SetClickHdl( LINK( this, ScSamplingDialog, CheckHdl));
+    mpKeepOrder->SetClickHdl( LINK( this, ScSamplingDialog, CheckHdl));
 
     mpOutputRangeEdit->GrabFocus();
     mpPeriodicMethodRadio->Check();
@@ -159,6 +166,8 @@ void ScSamplingDialog::SetReference( const ScRange& rReferenceRange, ScDocument*
             mInputRange = rReferenceRange;
             aReferenceString = mInputRange.Format(ScRefFlags::RANGE_ABS_3D, pDocument, mAddressDetails);
             mpInputRangeEdit->SetRefString( aReferenceString );
+
+            LimitSampleSizeAndPeriod();
         }
         else if ( mpActiveEdit == mpOutputRangeEdit )
         {
@@ -179,8 +188,11 @@ void ScSamplingDialog::SetReference( const ScRange& rReferenceRange, ScDocument*
     }
 
     // Enable OK if both, input range and output address are set.
+    // Disable if at least one is invalid.
     if (mInputRange.IsValid() && mOutputAddress.IsValid())
         mpButtonOk->Enable();
+    else
+        mpButtonOk->Enable(false);
 }
 
 ScRange ScSamplingDialog::PerformPeriodicSampling(ScDocShell* pDocShell)
@@ -233,9 +245,7 @@ ScRange ScSamplingDialog::PerformRandomSampling(ScDocShell* pDocShell)
     // by rows or area.
     const sal_Int64 nPopulationSize = aEnd.Row() - aStart.Row() + 1;
 
-    /* TODO: the previously existing implementation was WOR, we may want to
-     * additionally offer WR as option. */
-    bool bWithReplacement = false;
+    const bool bWithReplacement = mpWithReplacement->IsEnabled() && mpWithReplacement->IsChecked();
 
     // WOR (WithOutReplacement) can't draw more than population. Catch that in
     // the caller.
@@ -357,7 +367,10 @@ void ScSamplingDialog::PerformSampling()
 
     if (mpRandomMethodRadio->IsChecked())
     {
-        aModifiedRange = PerformRandomSampling(pDocShell);
+        if (mpKeepOrder->IsEnabled() && mpKeepOrder->IsChecked())
+            aModifiedRange = PerformRandomSamplingKeepOrder(pDocShell);
+        else
+            aModifiedRange = PerformRandomSampling(pDocShell);
     }
     else if (mpPeriodicMethodRadio->IsChecked())
     {
@@ -368,35 +381,66 @@ void ScSamplingDialog::PerformSampling()
     pDocShell->PostPaint(aModifiedRange, PaintPartFlags::Grid);
 }
 
-IMPL_LINK_NOARG( ScSamplingDialog, OkClicked, Button*, void )
+sal_Int64 ScSamplingDialog::GetPopulationSize() const
 {
-    PerformSampling();
-    Close();
+    return mInputRange.IsValid() ? mInputRange.aEnd.Row() - mInputRange.aStart.Row() + 1 : 0;
 }
 
-IMPL_LINK( ScSamplingDialog, GetFocusHandler, Control&, rCtrl, void )
+void ScSamplingDialog::LimitSampleSizeAndPeriod()
+{
+    // Limit sample size (for WOR methods) and period if population is smaller
+    // than last known value. When enlargening the input population range the
+    // values will be adjusted up to the last known value again.
+    const sal_Int64 nPopulationSize = GetPopulationSize();
+    if (nPopulationSize <= mnLastSampleSizeValue && !mpWithReplacement->IsChecked())
+        mpSampleSize->SetValue( nPopulationSize);
+    if (nPopulationSize <= mnLastPeriodValue)
+        mpPeriod->SetValue( nPopulationSize);
+}
+
+IMPL_LINK_NOARG(ScSamplingDialog, SamplingSizeValueModified, Edit&, void)
+{
+    if (!mpWithReplacement->IsChecked())
+    {
+        // For all WOR methods limit sample size to population size.
+        const sal_Int64 nPopulationSize = GetPopulationSize();
+        if (mpSampleSize->GetValue() > nPopulationSize)
+            mpSampleSize->SetValue(nPopulationSize);
+    }
+    mnLastSampleSizeValue = mpSampleSize->GetValue();
+}
+
+IMPL_LINK_NOARG(ScSamplingDialog, PeriodValueModified, Edit&, void)
 {
-    mpActiveEdit = nullptr;
+    // Limit period to population size.
+    const sal_Int64 nPopulationSize = GetPopulationSize();
+    if (mpPeriod->GetValue() > nPopulationSize)
+        mpPeriod->SetValue(nPopulationSize);
+    mnLastPeriodValue = mpPeriod->GetValue();
+}
 
-    if(      (&rCtrl == static_cast<Control*>(mpInputRangeEdit))  || (&rCtrl == static_cast<Control*>(mpInputRangeButton)) )
+IMPL_LINK( ScSamplingDialog, GetFocusHandler, Control&, rCtrl, void )
+{
+    if (     (&rCtrl == static_cast<Control*>(mpInputRangeEdit))  || (&rCtrl == static_cast<Control*>(mpInputRangeButton)))
         mpActiveEdit = mpInputRangeEdit;
-    else if( (&rCtrl == static_cast<Control*>(mpOutputRangeEdit)) || (&rCtrl == static_cast<Control*>(mpOutputRangeButton)) )
+    else if ((&rCtrl == static_cast<Control*>(mpOutputRangeEdit)) || (&rCtrl == static_cast<Control*>(mpOutputRangeButton)))
         mpActiveEdit = mpOutputRangeEdit;
+    else
+        mpActiveEdit = nullptr;
 
-    if( mpActiveEdit )
+    if (mpActiveEdit)
         mpActiveEdit->SetSelection( Selection( 0, SELECTION_MAX ) );
 }
 
-IMPL_LINK_NOARG(ScSamplingDialog, LoseFocusHandler, Control&, void)
+IMPL_LINK_NOARG( ScSamplingDialog, OkClicked, Button*, void )
 {
-    mDialogLostFocus = !IsActive();
+    PerformSampling();
+    Close();
 }
 
-IMPL_LINK_NOARG(ScSamplingDialog, SamplingSizeValueModified, Edit&, void)
+IMPL_LINK_NOARG(ScSamplingDialog, LoseFocusHandler, Control&, void)
 {
-    sal_Int64 aPopulationSize = mInputRange.aEnd.Row() - mInputRange.aStart.Row() + 1;
-    if (mpSampleSize->GetValue() > aPopulationSize)
-        mpSampleSize->SetValue(aPopulationSize);
+    mDialogLostFocus = !IsActive();
 }
 
 IMPL_LINK_NOARG(ScSamplingDialog, ToggleSamplingMethod, RadioButton&, void)
@@ -410,11 +454,49 @@ void ScSamplingDialog::ToggleSamplingMethod()
     {
         mpPeriod->Enable(false);
         mpSampleSize->Enable();
+        mpWithReplacement->Enable();
+        mpKeepOrder->Enable();
     }
     else if (mpPeriodicMethodRadio->IsChecked())
     {
+        // WOR keeping order.
         mpPeriod->Enable();
         mpSampleSize->Enable(false);
+        mpWithReplacement->Check(false);
+        mpWithReplacement->Enable(false);
+        mpKeepOrder->Check();
+        mpKeepOrder->Enable(false);
+    }
+}
+
+IMPL_LINK( ScSamplingDialog, CheckHdl, Button*, pBtn, void )
+{
+    // Keep both checkboxes enabled so user can easily switch between the three
+    // possible combinations (one or the other or none), just uncheck the other
+    // one if one is checked. Otherwise the other checkbox would had to be
+    // disabled until user unchecks the enabled one again, which would force
+    // user to two clicks to switch.
+    if (pBtn == mpWithReplacement)
+    {
+        if (static_cast<const CheckBox*>(pBtn)->IsChecked())
+        {
+            // For WR can't keep order.
+            mpKeepOrder->Check(false);
+        }
+        else
+        {
+            // For WOR limit sample size to population size.
+            SamplingSizeValueModified(*mpSampleSize);
+        }
+    }
+    else if (pBtn == mpKeepOrder)
+    {
+        if (static_cast<const CheckBox*>(pBtn)->IsChecked())
+        {
+            // Keep order is always WOR.
+            mpWithReplacement->Check(false);
+            SamplingSizeValueModified(*mpSampleSize);
+        }
     }
 }
 
@@ -432,6 +514,8 @@ IMPL_LINK_NOARG(ScSamplingDialog, RefInputModifyHandler, Edit&, void)
                 mInputRange = *pRange;
                 // Highlight the resulting range.
                 mpInputRangeEdit->StartUpdateData();
+
+                LimitSampleSizeAndPeriod();
             }
             else
             {
diff --git a/sc/source/ui/inc/SamplingDialog.hxx b/sc/source/ui/inc/SamplingDialog.hxx
index 4994f73cb8a4..cf517a2bfa39 100644
--- a/sc/source/ui/inc/SamplingDialog.hxx
+++ b/sc/source/ui/inc/SamplingDialog.hxx
@@ -45,6 +45,8 @@ private:
     VclPtr<NumericField>       mpPeriod;
 
     VclPtr<RadioButton>        mpRandomMethodRadio;
+    VclPtr<CheckBox>           mpWithReplacement;
+    VclPtr<CheckBox>           mpKeepOrder;
     VclPtr<RadioButton>        mpPeriodicMethodRadio;
 
     VclPtr<OKButton>           mpButtonOk;
@@ -61,11 +63,16 @@ private:
 
     ScAddress const           mCurrentAddress;
 
+    sal_Int64                 mnLastSampleSizeValue;
+    sal_Int64                 mnLastPeriodValue;
+
     bool                mDialogLostFocus;
 
     void Init();
     void GetRangeFromSelection();
     void PerformSampling();
+    sal_Int64 GetPopulationSize() const;
+    void LimitSampleSizeAndPeriod();
 
     ScRange PerformRandomSampling(ScDocShell* pDocShell);
     ScRange PerformRandomSamplingKeepOrder(ScDocShell* pDocShell);
@@ -75,8 +82,10 @@ private:
     DECL_LINK( GetFocusHandler, Control&, void );
     DECL_LINK( LoseFocusHandler, Control&, void );
     DECL_LINK( SamplingSizeValueModified, Edit&, void );
+    DECL_LINK( PeriodValueModified, Edit&, void );
     DECL_LINK( ToggleSamplingMethod, RadioButton&, void );
     DECL_LINK( RefInputModifyHandler, Edit&, void );
+    DECL_LINK( CheckHdl, Button*, void );
     void ToggleSamplingMethod();
 };
 
diff --git a/sc/uiconfig/scalc/ui/samplingdialog.ui b/sc/uiconfig/scalc/ui/samplingdialog.ui
index 0264ec00de63..033772f8590f 100644
--- a/sc/uiconfig/scalc/ui/samplingdialog.ui
+++ b/sc/uiconfig/scalc/ui/samplingdialog.ui
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.18.3 -->
+<!-- Generated with glade 3.22.1 -->
 <interface domain="sc">
   <requires lib="gtk+" version="3.18"/>
   <requires lib="LibreOffice" version="1.0"/>
@@ -21,6 +21,9 @@
     <property name="title" translatable="yes" context="samplingdialog|SamplingDialog">Sampling</property>
     <property name="resizable">False</property>
     <property name="type_hint">dialog</property>
+    <child>
+      <placeholder/>
+    </child>
     <child internal-child="vbox">
       <object class="GtkBox" id="dialog-vbox1">
         <property name="can_focus">False</property>
@@ -109,10 +112,10 @@
                       <object class="GtkLabel" id="input-range-label">
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
-                        <property name="xalign">0</property>
                         <property name="label" translatable="yes" context="samplingdialog|input-range-label">Input range:</property>
                         <property name="use_underline">True</property>
                         <property name="mnemonic_widget">input-range-edit</property>
+                        <property name="xalign">0</property>
                       </object>
                       <packing>
                         <property name="left_attach">0</property>
@@ -147,10 +150,10 @@
                       <object class="GtkLabel" id="output-range-label">
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
-                        <property name="xalign">0</property>
                         <property name="label" translatable="yes" context="samplingdialog|output-range-label">Results to:</property>
                         <property name="use_underline">True</property>
                         <property name="mnemonic_widget">output-range-edit</property>
+                        <property name="xalign">0</property>
                       </object>
                       <packing>
                         <property name="left_attach">0</property>
@@ -227,9 +230,10 @@
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
                         <property name="hexpand">True</property>
-                        <property name="text" translatable="no">0</property>
+                        <property name="text">1</property>
                         <property name="adjustment">sample-size-adjustment</property>
                         <property name="update_policy">if-valid</property>
+                        <property name="value">1</property>
                       </object>
                       <packing>
                         <property name="left_attach">1</property>
@@ -242,12 +246,12 @@
                         <property name="can_focus">False</property>
                         <property name="margin_left">12</property>
                         <property name="hexpand">True</property>
-                        <property name="xalign">0</property>
                         <property name="xpad">12</property>
                         <property name="label" translatable="yes" context="samplingdialog|label1">Sample size:</property>
                         <property name="use_underline">True</property>
                         <property name="justify">center</property>
                         <property name="mnemonic_widget">sample-size-spin</property>
+                        <property name="xalign">0</property>
                       </object>
                       <packing>
                         <property name="left_attach">0</property>
@@ -284,7 +288,7 @@
                       </object>
                       <packing>
                         <property name="left_attach">0</property>
-                        <property name="top_attach">2</property>
+                        <property name="top_attach">4</property>
                         <property name="width">2</property>
                       </packing>
                     </child>
@@ -293,13 +297,14 @@
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
                         <property name="hexpand">True</property>
-                        <property name="text" translatable="no">1</property>
+                        <property name="text">1</property>
                         <property name="adjustment">period-adjustment</property>
+                        <property name="update_policy">if-valid</property>
                         <property name="value">1</property>
                       </object>
                       <packing>
                         <property name="left_attach">1</property>
-                        <property name="top_attach">3</property>
+                        <property name="top_attach">5</property>
                       </packing>
                     </child>
                     <child>
@@ -308,15 +313,47 @@
                         <property name="can_focus">False</property>
                         <property name="margin_left">12</property>
                         <property name="hexpand">True</property>
-                        <property name="xalign">0</property>
                         <property name="xpad">12</property>
                         <property name="label" translatable="yes" context="samplingdialog|label3">Period:</property>
                         <property name="use_underline">True</property>
                         <property name="mnemonic_widget">period-spin</property>
+                        <property name="xalign">0</property>
+                      </object>
+                      <packing>
+                        <property name="left_attach">0</property>
+                        <property name="top_attach">5</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkCheckButton" id="with-replacement">
+                        <property name="label" translatable="yes" context="samplingdialog|with-replacement">With replacement</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="use_underline">True</property>
+                        <property name="xalign">0</property>
+                        <property name="draw_indicator">True</property>
+                      </object>
+                      <packing>
+                        <property name="left_attach">0</property>
+                        <property name="top_attach">2</property>
+                        <property name="width">2</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkCheckButton" id="keep-order">
+                        <property name="label" translatable="yes" context="samplingdialog|keep-order">Keep order</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="use_underline">True</property>
+                        <property name="xalign">0</property>
+                        <property name="draw_indicator">True</property>
                       </object>
                       <packing>
                         <property name="left_attach">0</property>
                         <property name="top_attach">3</property>
+                        <property name="width">2</property>
                       </packing>
                     </child>
                   </object>


More information about the Libreoffice-commits mailing list