Blame SOURCES/0001-refine-current-date-time-hotkey-handling.patch

f085be
From 351235d046c48cf2d9ccbca4175c5b70bdbae847 Mon Sep 17 00:00:00 2001
f085be
Message-Id: <351235d046c48cf2d9ccbca4175c5b70bdbae847.1409054200.git.erack@redhat.com>
f085be
From: Eike Rathke <erack@redhat.com>
f085be
Date: Mon, 25 Aug 2014 16:34:20 +0200
f085be
Subject: [PATCH] refine current date/time hotkey handling
f085be
MIME-Version: 1.0
f085be
Content-Type: multipart/mixed; boundary="------------erAck-patch-parts"
f085be
f085be
This is a multi-part message in MIME format.
f085be
--------------erAck-patch-parts
f085be
Content-Type: text/plain; charset=UTF-8; format=fixed
f085be
Content-Transfer-Encoding: 8bit
f085be
f085be
f085be
Previously, a date or time hotkey lead to always the current date+time
f085be
value being set at the current cell, just formatted differently to
f085be
either date or time. This not only looked strange in the input line that
f085be
still displayed the full date+time value, but also affected day and time
f085be
calculations involving these values.
f085be
f085be
With this change the result depends on the previous value and formatting
f085be
of the cell. Furthermore, inserting a current date or time value at the
f085be
cursor position while editing a cell is now possible.
f085be
f085be
If cell is in input or edit mode, insert date/time at cursor position,
f085be
else create a date or time or date+time cell as follows:
f085be
f085be
* key date on time cell  =>  current date + time of cell  =>  date+time formatted cell
f085be
  * unless time cell was empty or 00:00 time  =>  current date  =>  date formatted cell
f085be
* key date on date+time cell  =>  current date + 00:00 time  =>  date+time formatted cell
f085be
  * unless date was current date  =>  current date  =>  date formatted cell
f085be
* key date on other cell  =>  current date  =>  date formatted cell
f085be
* key time on date cell  =>  date of cell + current time  =>  date+time formatted cell
f085be
  * unless date cell was empty  =>  current time  =>  time formatted cell
f085be
* key time on date+time cell  =>  current time  =>  time formatted cell
f085be
  * unless cell was empty  =>  current date+time  =>  date+time formatted cell
f085be
* key time on other cell  =>  current time  =>  time formatted cell
f085be
f085be
This is a backport of a series of commits on master, i.e. mainly
f085be
32e8c47df81292c71ce1d885762358f18559bdb7
f085be
0f4a999e02aff56043506e38dfa53ea3b349ce25
f085be
and others.
f085be
f085be
Conflicts:
f085be
	sc/source/ui/view/viewfun6.cxx
f085be
f085be
Change-Id: Ief48b3e312345ad5e289921ff5120dd074661882
f085be
---
f085be
 sc/source/ui/view/viewfun6.cxx | 229 ++++++++++++++++++++++++++++++++++++-----
f085be
 1 file changed, 205 insertions(+), 24 deletions(-)
f085be
f085be
f085be
--------------erAck-patch-parts
f085be
Content-Type: text/x-patch; name="0001-refine-current-date-time-hotkey-handling.patch"
f085be
Content-Transfer-Encoding: 8bit
f085be
Content-Disposition: attachment; filename="0001-refine-current-date-time-hotkey-handling.patch"
f085be
f085be
diff --git a/sc/source/ui/view/viewfun6.cxx b/sc/source/ui/view/viewfun6.cxx
f085be
index 8ec8bf1..a55dec3 100644
f085be
--- a/sc/source/ui/view/viewfun6.cxx
f085be
+++ b/sc/source/ui/view/viewfun6.cxx
f085be
@@ -25,6 +25,7 @@
f085be
 #include <vcl/msgbox.hxx>
f085be
 #include "svl/zforlist.hxx"
f085be
 #include "svl/zformat.hxx"
f085be
+#include <editeng/editview.hxx>
f085be
 
f085be
 #include "viewfunc.hxx"
f085be
 #include "detfunc.hxx"
f085be
@@ -44,6 +45,7 @@
f085be
 #include "markdata.hxx"
f085be
 #include "drawview.hxx"
f085be
 #include "globalnames.hxx"
f085be
+#include "inputhdl.hxx"
f085be
 
f085be
 #include <vector>
f085be
 
f085be
@@ -237,31 +239,210 @@ void ScViewFunc::DetectiveMarkSucc()
f085be
     MarkAndJumpToRanges(aDestRanges);
f085be
 }
f085be
 
f085be
-void ScViewFunc::InsertCurrentTime(short nCellFmt, const OUString& rUndoStr)
f085be
+/** Insert date or time into current cell.
f085be
+
f085be
+    If cell is in input or edit mode, insert date/time at cursor position, else
f085be
+    create a date or time or date+time cell as follows:
f085be
+
f085be
+    - key date on time cell  =>  current date + time of cell  =>  date+time formatted cell
f085be
+      - unless time cell was empty or 00:00 time  =>  current date  =>  date formatted cell
f085be
+    - key date on date+time cell  =>  current date + 00:00 time  =>  date+time formatted cell
f085be
+      - unless date was current date  =>  current date  =>  date formatted cell
f085be
+    - key date on other cell  =>  current date  =>  date formatted cell
f085be
+    - key time on date cell  =>  date of cell + current time  =>  date+time formatted cell
f085be
+      - unless date cell was empty  =>  current time  =>  time formatted cell
f085be
+    - key time on date+time cell  =>  current time  =>  time formatted cell
f085be
+      - unless cell was empty  =>  current date+time  =>  date+time formatted cell
f085be
+    - key time on other cell  =>  current time  =>  time formatted cell
f085be
+ */
f085be
+void ScViewFunc::InsertCurrentTime(short nReqFmt, const OUString& rUndoStr)
f085be
 {
f085be
-    ScViewData* pViewData = GetViewData();
f085be
-    ScAddress aCurPos = pViewData->GetCurPos();
f085be
-    ScDocShell* pDocSh = pViewData->GetDocShell();
f085be
-    ScDocument* pDoc = pDocSh->GetDocument();
f085be
-    ::svl::IUndoManager* pUndoMgr = pDocSh->GetUndoManager();
f085be
-    SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
f085be
-    Date aActDate( Date::SYSTEM );
f085be
-    double fDate = aActDate - *pFormatter->GetNullDate();
f085be
-    Time aActTime( Time::SYSTEM );
f085be
-    double fTime = aActTime.GetHour()    / static_cast<double>(::Time::hourPerDay)   +
f085be
-                   aActTime.GetMin()     / static_cast<double>(::Time::minutePerDay) +
f085be
-                   aActTime.GetSec()     / static_cast<double>(::Time::secondPerDay) +
f085be
-                   aActTime.GetNanoSec() / static_cast<double>(::Time::nanoSecPerDay);
f085be
-    pUndoMgr->EnterListAction(rUndoStr, rUndoStr);
f085be
-    pDocSh->GetDocFunc().SetValueCell(aCurPos, fDate+fTime, true);
f085be
-
f085be
-    // Set the new cell format only when it differs from the current cell
f085be
-    // format type.
f085be
-    sal_uInt32 nCurNumFormat = pDoc->GetNumberFormat(aCurPos);
f085be
-    const SvNumberformat* pEntry = pFormatter->GetEntry(nCurNumFormat);
f085be
-    if (!pEntry || !(pEntry->GetType() & nCellFmt))
f085be
-        SetNumberFormat(nCellFmt);
f085be
-    pUndoMgr->LeaveListAction();
f085be
+    ScViewData& rViewData = *GetViewData();
f085be
+
f085be
+    ScInputHandler* pInputHdl = SC_MOD()->GetInputHdl( rViewData.GetViewShell());
f085be
+    bool bInputMode = (pInputHdl && pInputHdl->IsInputMode());
f085be
+
f085be
+    ScDocShell* pDocSh = rViewData.GetDocShell();
f085be
+    ScDocument& rDoc = *pDocSh->GetDocument();
f085be
+    ScAddress aCurPos = rViewData.GetCurPos();
f085be
+    const sal_uInt32 nCurNumFormat = rDoc.GetNumberFormat(aCurPos);
f085be
+    SvNumberFormatter* pFormatter = rDoc.GetFormatTable();
f085be
+    const SvNumberformat* pCurNumFormatEntry = pFormatter->GetEntry(nCurNumFormat);
f085be
+
f085be
+    if (bInputMode)
f085be
+    {
f085be
+        double fVal = 0.0;
f085be
+        switch (nReqFmt)
f085be
+        {
f085be
+            case NUMBERFORMAT_DATE:
f085be
+                {
f085be
+                    Date aActDate( Date::SYSTEM );
f085be
+                    fVal = aActDate - *pFormatter->GetNullDate();
f085be
+                }
f085be
+                break;
f085be
+            case NUMBERFORMAT_TIME:
f085be
+                {
f085be
+                    Time aActTime( Time::SYSTEM );
f085be
+                    fVal = aActTime.GetTimeInDays();
f085be
+                }
f085be
+                break;
f085be
+            default:
f085be
+                assert(!"unhandled current date/time request");
f085be
+                nReqFmt = NUMBERFORMAT_DATETIME;
f085be
+                // fallthru
f085be
+            case NUMBERFORMAT_DATETIME:
f085be
+                {
f085be
+                    DateTime aActDateTime( DateTime::SYSTEM );
f085be
+                    fVal = aActDateTime - DateTime( *pFormatter->GetNullDate());
f085be
+                }
f085be
+                break;
f085be
+        }
f085be
+
f085be
+        LanguageType nLang = (pCurNumFormatEntry ? pCurNumFormatEntry->GetLanguage() : ScGlobal::eLnge);
f085be
+        sal_uInt32 nFormat = pFormatter->GetStandardFormat( nReqFmt, nLang);
f085be
+        // This would return a more precise format with seconds and 100th
f085be
+        // seconds for a time request.
f085be
+        //nFormat = pFormatter->GetStandardFormat( fVal, nFormat, nReqFmt, nLang);
f085be
+        OUString aString;
f085be
+        Color* pColor;
f085be
+        pFormatter->GetOutputString( fVal, nFormat, aString, &pColor);
f085be
+
f085be
+        pInputHdl->DataChanging();
f085be
+        EditView* pTopView = pInputHdl->GetTopView();
f085be
+        if (pTopView)
f085be
+            pTopView->InsertText( aString);
f085be
+        EditView* pTableView = pInputHdl->GetTableView();
f085be
+        if (pTableView)
f085be
+            pTableView->InsertText( aString);
f085be
+        pInputHdl->DataChanged( false, true);
f085be
+    }
f085be
+    else
f085be
+    {
f085be
+        const short nCurNumFormatType = (pCurNumFormatEntry ?
f085be
+                (pCurNumFormatEntry->GetType() & ~NUMBERFORMAT_DEFINED) : NUMBERFORMAT_UNDEFINED);
f085be
+        bool bForceReqFmt = false;
f085be
+        const double fCell = rDoc.GetValue( aCurPos);
f085be
+        // Combine requested date/time stamp with existing cell time/date, if any.
f085be
+        switch (nReqFmt)
f085be
+        {
f085be
+            case NUMBERFORMAT_DATE:
f085be
+                switch (nCurNumFormatType)
f085be
+                {
f085be
+                    case NUMBERFORMAT_TIME:
f085be
+                        // An empty cell formatted as time (or 00:00 time) shall
f085be
+                        // not result in the current date with 00:00 time, but only
f085be
+                        // in current date.
f085be
+                        if (fCell != 0.0)
f085be
+                            nReqFmt = NUMBERFORMAT_DATETIME;
f085be
+                        break;
f085be
+                    case NUMBERFORMAT_DATETIME:
f085be
+                        {
f085be
+                            // Force to only date if the existing date+time is the
f085be
+                            // current date. This way inserting current date twice
f085be
+                            // on an existing date+time cell can be used to force
f085be
+                            // date, which otherwise would only be possible by
f085be
+                            // applying a date format.
f085be
+                            double fDate = rtl::math::approxFloor( fCell);
f085be
+                            if (fDate == (Date( Date::SYSTEM) - *pFormatter->GetNullDate()))
f085be
+                                bForceReqFmt = true;
f085be
+                        }
f085be
+                        break;
f085be
+                }
f085be
+                break;
f085be
+            case NUMBERFORMAT_TIME:
f085be
+                switch (nCurNumFormatType)
f085be
+                {
f085be
+                    case NUMBERFORMAT_DATE:
f085be
+                        // An empty cell formatted as date shall not result in the
f085be
+                        // null date and current time, but only in current time.
f085be
+                        if (fCell != 0.0)
f085be
+                            nReqFmt = NUMBERFORMAT_DATETIME;
f085be
+                        break;
f085be
+                    case NUMBERFORMAT_DATETIME:
f085be
+                        // Requesting current time on an empty date+time cell
f085be
+                        // inserts both current date+time.
f085be
+                        if (fCell == 0.0)
f085be
+                            nReqFmt = NUMBERFORMAT_DATETIME;
f085be
+                        else
f085be
+                        {
f085be
+                            // Add current time to an existing date+time where time is
f085be
+                            // zero and date is current date, else force time only.
f085be
+                            double fDate = rtl::math::approxFloor( fCell);
f085be
+                            double fTime = fCell - fDate;
f085be
+                            if (fTime == 0.0 && fDate == (Date( Date::SYSTEM) - *pFormatter->GetNullDate()))
f085be
+                                nReqFmt = NUMBERFORMAT_DATETIME;
f085be
+                            else
f085be
+                                bForceReqFmt = true;
f085be
+                        }
f085be
+                        break;
f085be
+                }
f085be
+                break;
f085be
+            default:
f085be
+                assert(!"unhandled current date/time request");
f085be
+                nReqFmt = NUMBERFORMAT_DATETIME;
f085be
+                // fallthru
f085be
+            case NUMBERFORMAT_DATETIME:
f085be
+                break;
f085be
+        }
f085be
+        double fVal = 0.0;
f085be
+        switch (nReqFmt)
f085be
+        {
f085be
+            case NUMBERFORMAT_DATE:
f085be
+                {
f085be
+                    Date aActDate( Date::SYSTEM );
f085be
+                    fVal = aActDate - *pFormatter->GetNullDate();
f085be
+                }
f085be
+                break;
f085be
+            case NUMBERFORMAT_TIME:
f085be
+                {
f085be
+                    Time aActTime( Time::SYSTEM );
f085be
+                    fVal = aActTime.GetTimeInDays();
f085be
+                }
f085be
+                break;
f085be
+            case NUMBERFORMAT_DATETIME:
f085be
+                switch (nCurNumFormatType)
f085be
+                {
f085be
+                    case NUMBERFORMAT_DATE:
f085be
+                        {
f085be
+                            double fDate = rtl::math::approxFloor( fCell);
f085be
+                            Time aActTime( Time::SYSTEM );
f085be
+                            fVal = fDate + aActTime.GetTimeInDays();
f085be
+                        }
f085be
+                        break;
f085be
+                    case NUMBERFORMAT_TIME:
f085be
+                        {
f085be
+                            double fTime = fCell - rtl::math::approxFloor( fCell);
f085be
+                            Date aActDate( Date::SYSTEM );
f085be
+                            fVal = (aActDate - *pFormatter->GetNullDate()) + fTime;
f085be
+                        }
f085be
+                        break;
f085be
+                    default:
f085be
+                        {
f085be
+                            DateTime aActDateTime( DateTime::SYSTEM );
f085be
+                            // Converting the null date to DateTime forces the
f085be
+                            // correct operator-() to be used, resulting in a
f085be
+                            // fractional date+time instead of only date value.
f085be
+                            fVal = aActDateTime - DateTime( *pFormatter->GetNullDate());
f085be
+                        }
f085be
+                }
f085be
+                break;
f085be
+        }
f085be
+
f085be
+        ::svl::IUndoManager* pUndoMgr = pDocSh->GetUndoManager();
f085be
+        pUndoMgr->EnterListAction(rUndoStr, rUndoStr);
f085be
+
f085be
+        pDocSh->GetDocFunc().SetValueCell(aCurPos, fVal, true);
f085be
+
f085be
+        // Set the new cell format only when it differs from the current cell
f085be
+        // format type. Preserve a date+time format unless we force a format
f085be
+        // through.
f085be
+        if (bForceReqFmt || (nReqFmt != nCurNumFormatType && nCurNumFormatType != NUMBERFORMAT_DATETIME))
f085be
+            SetNumberFormat(nReqFmt);
f085be
+        else
f085be
+            rViewData.UpdateInputHandler();     // update input bar with new value
f085be
+
f085be
+        pUndoMgr->LeaveListAction();
f085be
+    }
f085be
 }
f085be
 
f085be
 void ScViewFunc::ShowNote( bool bShow )
f085be
f085be
--------------erAck-patch-parts--
f085be
f085be